// Главное приложение: главная + каталог + корзина + заявка.
const { useState, useEffect, useMemo, useCallback, useRef } = React;

const RUB = (n) => new Intl.NumberFormat("ru-RU").format(n) + " ₽";

// ---------- TWEAKS DEFAULTS (persistable) ----------
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#FF4D14",
  "density": "comfort",
  "view": "grid",
  "typo": "editorial"
} /*EDITMODE-END*/;

// ---------- CART HOOK ----------
function useCart() {
  const [items, setItems] = useState(() => {
    try {
      return JSON.parse(localStorage.getItem("__cart_v1__") || "[]");
    } catch (e) {return [];}
  });
  useEffect(() => {
    try {localStorage.setItem("__cart_v1__", JSON.stringify(items));} catch (e) {}
  }, [items]);

  const add = useCallback((product, qty = 1) => {
    setItems((prev) => {
      const existing = prev.find((x) => x.id === product.id);
      if (existing) return prev.map((x) => x.id === product.id ? { ...x, qty: x.qty + qty } : x);
      return [...prev, {
        id: product.id, sourceId: product.sourceId, title: product.title,
        brand: product.brand, unit: product.unit, price: product.price,
        currency: product.currency, image: product.image, images: product.images,
        priceSource: product.priceSource || "komus",
        priceNote: product.priceNote || "Ориентировочная цена. Итоговая стоимость подтверждается менеджером.",
        qty
      }];
    });
  }, []);
  const setQty = useCallback((id, qty) => {
    setItems((prev) => {
      if (qty <= 0) return prev.filter((x) => x.id !== id);
      return prev.map((x) => x.id === id ? { ...x, qty } : x);
    });
  }, []);
  const remove = useCallback((id) => {
    setItems((prev) => prev.filter((x) => x.id !== id));
  }, []);
  const clear = useCallback(() => setItems([]), []);

  const counts = useMemo(() => items.reduce((s, x) => s + x.qty, 0), [items]);
  const knownTotal = useMemo(() =>
  items.filter((x) => x.price != null).reduce((s, x) => s + x.price * x.qty, 0),
  [items]);
  const hasUnknown = useMemo(() => items.some((x) => x.price == null), [items]);

  return { items, add, setQty, remove, clear, counts, knownTotal, hasUnknown };
}

// ---------- HEADER ----------
function Header({ cartCount, onOpenCart, onNavigate, page, contacts }) {
  return (
    <header className="site-header">
      <div className="site-header__inner">
        <a className="brand" href="#" onClick={(e) => {e.preventDefault();onNavigate("home");}}>
          <span className="brand__dot"></span>
          {window.SITE_CONFIG.brand.name}
          <span className="brand__sub">офисное снабжение</span>
        </a>
        <nav className="site-nav">
          <a href="#" className={page === "home" ? "is-active" : ""} onClick={(e) => {e.preventDefault();onNavigate("home");}}>Главная</a>
          <a href="#" className={page === "catalog" ? "is-active" : ""} onClick={(e) => {e.preventDefault();onNavigate("catalog");}}>Каталог</a>
          <a href="#gov" onClick={(e) => {e.preventDefault();onNavigate("home", "gov");}}>Госзакупка</a>
          <a href="#contacts" onClick={(e) => {e.preventDefault();onNavigate("home", "contacts");}}>Контакты</a>
          <a className="site-nav__phone" href={contacts.phoneHref}>{contacts.phone}</a>
          <button className="cart-btn" onClick={onOpenCart} style={{ backgroundColor: "rgb(255, 255, 255)" }}>
            Корзина
            {cartCount > 0 && <span className="cart-btn__count" style={{ color: "rgb(255, 255, 255)" }}>{cartCount}</span>}
          </button>
        </nav>
      </div>
    </header>);

}

// ---------- HERO ----------
function Hero({ onSearch, onGoCatalog }) {
  const [q, setQ] = useState("");
  const cfg = window.SITE_CONFIG;
  return (
    <section className="hero">
      <div className="hero__inner">
        <div>
          <div className="hero__eyebrow">№ 01 — Каталог · {new Date().getFullYear()}</div>
          <h1 className="hero__title">
            Закупка <em>без таблиц</em>,<br />
            счёт от <em>быстро</em>.
          </h1>
          <p className="hero__lede">Выберите товары, укажите количество и отправьте корзину на расчёт. Менеджер проверит наличие, применит доступные скидки и подтвердит итоговую стоимость.

          </p>
          <div className="hero__cta">
            <button className="btn btn--primary btn--cta-hero" onClick={onGoCatalog}>
              Перейти в каталог →
            </button>
            <a className="btn btn--ghost" href={`mailto:${cfg.contacts.email}`}>
              Написать менеджеру
            </a>
          </div>
          <form className="hero__search" onSubmit={(e) => {e.preventDefault();onSearch(q);}}>
            <input
              type="search"
              placeholder='Например: «бумага A4 80 г» или «папка-регистратор»'
              value={q}
              onChange={(e) => setQ(e.target.value)} />
            
            <button type="submit">Найти</button>
          </form>
        </div>
        <aside className="hero__stats">
          <div>
            <div className="stat__num">5<em> минут</em></div>
            <div className="stat__label">НА ЗАЯВКУ</div>
          </div>
          <div>
            <div className="stat__num"> <em>Скидки</em></div>
            <div className="stat__label">НА ОБЪЁМ</div>
          </div>
          <div>
            <div className="stat__num">КП сразу <em></em> нал</div>
            <div className="stat__label">ПО КОРЗИНЕ И РЕКВИЗИТАМ</div>
          </div>
        </aside>
      </div>
    </section>);

}

// ---------- QUICK CHIPS ----------
function QuickChips({ onPick }) {
  const groups = window.SITE_CONFIG.quickGroups;
  return (
    <div className="quick">
      <div className="quick__inner">
        <span className="quick__label">Быстрые группы</span>
        {groups.map((g) =>
        <button key={g} className="chip" onClick={() => onPick(g)}>{g}</button>
        )}
      </div>
    </div>);

}

// ---------- FEATURE STRIP ----------
function Features() {
  const items = [
  { n: "01", t: "Каталог из Комус", d: "Ассортимент синхронизирован с Комус — артикулы, характеристики и базовые цены приходят оттуда напрямую." },
  { n: "02", t: "Индивидуальный просчёт", d: "От базовой цены — скидка в зависимости от объёма и категории. Финальные цены подтверждает менеджер после заявки." },
  { n: "03", t: "Юрлица и ИП", d: "Безналичный расчёт, договор, закрывающие документы. Возможно коммерческое предложение по запросу." },
  { n: "04", t: "Отсрочка платежа", d: "После первых трёх заказов доступна отсрочка платежа. Условия согласовываются индивидуально." }];

  return (
    <section className="feature-strip" id="features">
      <div className="feature-strip__head">
        <div>
          <div className="section-eyebrow">Как работаем</div>
          <h2 className="section-title">Каталог — Комус. Условия — индивидуальные.</h2>
        </div>
        <p className="feature-strip__lede">
          Итоговые цены подтверждаются менеджером после сформированной заявки. Цены в каталоге — ориентировочные.
        </p>
      </div>
      <div className="feature-grid">
        {items.map((it) =>
        <div className="feature" key={it.n}>
            <div className="feature__num">{it.n}</div>
            <h3 className="feature__title">{it.t}</h3>
            <p className="feature__desc">{it.d}</p>
          </div>
        )}
      </div>
    </section>);

}

// ---------- HOW-TO ----------
function HowTo({ onGoCatalog }) {
  return (
    <section className="howto" id="howto">
      <div className="howto__inner">
        <div className="section-eyebrow">Как оформить заказ</div>
        <h2 className="section-title">Три шага, без регистрации.</h2>
        <div className="howto__steps">
          <div className="step">
            <div className="step__n">1</div>
            <h3 className="step__title">Выберите товары</h3>
            <p className="step__desc">Используйте поиск, фильтры и быстрые группы. Добавьте позиции в корзину — она сохранится после перезагрузки страницы.</p>
          </div>
          <div className="step">
            <div className="step__n">2</div>
            <h3 className="step__title">Отправьте заявку</h3>
            <p className="step__desc">Имя, телефон или email, при необходимости — компания и ИНН. Никаких регистраций, никаких онлайн-оплат на этом этапе.</p>
          </div>
          <div className="step">
            <div className="step__n">3</div>
            <h3 className="step__title">Получите подтверждение</h3>
            <p className="step__desc">Менеджер свяжется в течение часа в рабочее время, подтвердит наличие, цены и срок поставки. Оплата по счёту.</p>
          </div>
        </div>
        <div style={{ marginTop: 32 }}>
          <button className="btn btn--ink" onClick={onGoCatalog}>Открыть каталог →</button>
        </div>
      </div>
    </section>);

}

// ---------- THUMBNAIL ----------
// Миниатюры товаров: использует product.image из API, или плейсхолдер с инициалом категории.
function Thumb({ product, size = 56 }) {
  const initial = (product.categoryName || product.title || "").slice(0, 1).toUpperCase();
  if (product.image) {
    return (
      <div className="thumb" style={{ width: size, height: size }}>
        <img src={product.image} alt="" loading="lazy"
        onError={(e) => {e.currentTarget.style.display = "none";}} />
        <span className="thumb__fallback" aria-hidden="true">{initial}</span>
      </div>);
  }
  return (
    <div className="thumb thumb--ph" style={{ width: size, height: size }} aria-hidden="true">
      <span className="thumb__fallback">{initial}</span>
    </div>);
}

// ---------- GOV PROCUREMENT SECTION ----------
function GovSection({ onGoCatalog }) {
  return (
    <section className="gov" id="gov">
      <div className="gov__inner">
        <div className="gov__head">
          <div>
            <div className="section-eyebrow">ЗАКУПКА</div>
            <h2 className="section-title">Коммерческое предложение по корзине</h2>
          </div>
          <p className="gov__lede">

          </p>
        </div>
        <ol className="gov__steps">
          <li style={{ borderWidth: "0px" }}>
            <span className="gov__num">01</span>
            <h3>Соберите корзину</h3>
            <p>Добавьте позиции из каталога — можно поиском по артикулу или подбором аналогов.</p>
          </li>
          <li style={{ borderWidth: "0px" }}>
            <span className="gov__num">02</span>
            <h3>Нажмите «Получить КП»</h3>
            <p>В корзине выберите действие «Получить коммерческое предложение».</p>
          </li>
          <li style={{ borderWidth: "0px" }}>
            <span className="gov__num">03</span>
            <h3>Укажите реквизиты</h3>
            <p>Название юрлица, ИНН, КПП, юрадрес, контакт и кому адресовать КП.</p>
          </li>
          <li>
            <span className="gov__num">04</span>
            <h3>Получите КП на email</h3>
            <p>Менеджер пришлёт коммерческое предложение с подтверждёнными ценами, сроками и реквизитами.</p>
          </li>
        </ol>
        <div className="gov__cta">
          <button className="btn btn--primary btn--cta-hero" onClick={onGoCatalog}>Собрать корзину для КП →</button>
          <p className="gov__note">Работаем с юрлицами и ИП
Договор, закрывающие документы</p>
        </div>
      </div>
    </section>);}

// ---------- CATALOG ----------
function Catalog({ catalog, initialQuery, addToCart, cart, openProduct, view, density, mobileFiltersOpen, setMobileFiltersOpen }) {
  const [q, setQ] = useState(initialQuery || "");
  const [selectedCats, setSelectedCats] = useState(new Set());
  const [selectedBrands, setSelectedBrands] = useState(new Set());
  const [priceMin, setPriceMin] = useState("");
  const [priceMax, setPriceMax] = useState("");
  const [sort, setSort] = useState("name-asc");

  useEffect(() => {if (initialQuery !== undefined) setQ(initialQuery || "");}, [initialQuery]);

  // Build brand list
  const brandCounts = useMemo(() => {
    const m = {};
    catalog.products.forEach((p) => {if (p.brand) m[p.brand] = (m[p.brand] || 0) + 1;});
    return m;
  }, [catalog.products]);
  const allBrands = useMemo(() => Object.keys(brandCounts).sort(), [brandCounts]);

  const catCounts = useMemo(() => {
    const m = {};
    catalog.products.forEach((p) => {m[p.categoryId] = (m[p.categoryId] || 0) + 1;});
    return m;
  }, [catalog.products]);

  const categoryOptions = useMemo(() => {
    if (catalog.categories && catalog.categories.length) {
      return catalog.categories
        .map((c) => {
          const id = String(c.id || c.sourceId || c.slug || c.name);
          return {
            id,
            name: c.name || c.path || id,
            path: c.path || c.name || id,
            count: c.productCount ?? catCounts[id] ?? 0,
          };
        })
        .filter((c) => c.count > 0)
        .sort((a, b) => a.name.localeCompare(b.name, "ru"));
    }

    const byId = new Map();
    catalog.products.forEach((p) => {
      const id = String(p.categoryId || p.categoryName || "");
      if (!id) return;
      const current = byId.get(id) || {
        id,
        name: p.categoryName || p.categoryPath || id,
        path: p.categoryPath || p.categoryName || id,
        count: 0,
      };
      current.count += 1;
      byId.set(id, current);
    });
    return Array.from(byId.values()).sort((a, b) => a.name.localeCompare(b.name, "ru"));
  }, [catalog.categories, catalog.products, catCounts]);

  // Filter
  const filtered = useMemo(() => {
    const Q = q.trim().toLowerCase();
    const min = priceMin === "" ? null : Number(priceMin);
    const max = priceMax === "" ? null : Number(priceMax);
    let list = catalog.products.filter((p) => {
      if (Q) {
        const hay = (p.title + " " + (p.brand || "") + " " + (p.sourceId || "") +
        " " + Object.values(p.attributes || {}).join(" ")).toLowerCase();
        if (!hay.includes(Q)) return false;
      }
      if (selectedCats.size && !selectedCats.has(p.categoryId)) return false;
      if (selectedBrands.size && !selectedBrands.has(p.brand)) return false;
      if (min != null && (p.price == null || p.price < min)) return false;
      if (max != null && (p.price == null || p.price > max)) return false;
      return true;
    });
    list.sort((a, b) => {
      switch (sort) {
        case "price-asc":return (a.price ?? Infinity) - (b.price ?? Infinity);
        case "price-desc":return (b.price ?? -Infinity) - (a.price ?? -Infinity);
        case "category":return a.categoryName.localeCompare(b.categoryName, "ru");
        case "name-desc":return b.title.localeCompare(a.title, "ru");
        case "name-asc":default:return a.title.localeCompare(b.title, "ru");
      }
    });
    return list;
  }, [catalog.products, q, selectedCats, selectedBrands, priceMin, priceMax, sort]);

  const toggleSet = (set, val, update) => {
    const n = new Set(set);
    if (n.has(val)) n.delete(val);else n.add(val);
    update(n);
  };

  const resetAll = () => {
    setQ("");setSelectedCats(new Set());setSelectedBrands(new Set());
    setPriceMin("");setPriceMax("");setSort("name-asc");
  };

  const lastSync = catalog.lastSyncedAt ? new Date(catalog.lastSyncedAt) : null;

  return (
    <section className="catalog-section" id="catalog">
      <div className="catalog-head">
        <div>
          <div className="section-eyebrow">Каталог</div>
          <div className="catalog-head__title">
            <h2 className="section-title" style={{ marginTop: 8 }}>Каталог товаров</h2>
            <span className="catalog-head__count">{filtered.length} из {catalog.products.length} позиций</span>
          </div>
          <div className="catalog-head__sync">
            Источник: API Комуса {catalog.source === "mock" ? "(mock)" : "(live)"}
            {lastSync && ` · обновлено ${lastSync.toLocaleString("ru-RU")}`}
          </div>
        </div>
      </div>
      <div className="catalog-layout">
        <aside className={`filters${mobileFiltersOpen ? " is-open" : ""}`}>
          <div className="filter-block">
            <div className="filter-block__title">
              Фильтры
              <button onClick={resetAll}>Сбросить всё</button>
            </div>
          </div>
          <div className="filter-block">
            <div className="filter-block__title">Категории</div>
            <div className="filter-list">
              {categoryOptions.map((c) => {
                const count = c.count;
                const id = c.id;
                const active = selectedCats.has(id);
                return (
                  <label key={id} className="filter-item" title={c.path}>
                    <input type="checkbox" checked={active}
                    onChange={() => toggleSet(selectedCats, id, setSelectedCats)} />
                    <span>{c.name}</span>
                    <span className="filter-item__count">{count}</span>
                  </label>);

              })}
            </div>
          </div>
          <div className="filter-block">
            <div className="filter-block__title">Бренд</div>
            <div className="filter-list">
              {allBrands.map((b) =>
              <label key={b} className="filter-item">
                  <input type="checkbox" checked={selectedBrands.has(b)}
                onChange={() => toggleSet(selectedBrands, b, setSelectedBrands)} />
                  <span>{b}</span>
                  <span className="filter-item__count">{brandCounts[b]}</span>
                </label>
              )}
            </div>
          </div>
          <div className="filter-block">
            <div className="filter-block__title">Цена, ₽</div>
            <div className="filter-price">
              <input type="number" placeholder="от" value={priceMin} onChange={(e) => setPriceMin(e.target.value)} />
              <input type="number" placeholder="до" value={priceMax} onChange={(e) => setPriceMax(e.target.value)} />
            </div>
          </div>
        </aside>

        <div className="catalog-main">
          <div className="catalog-toolbar">
            <input className="search-input" type="search" placeholder="Поиск по названию, артикулу, бренду…"
            value={q} onChange={(e) => setQ(e.target.value)} />
            <button className="mobile-filters-btn" onClick={() => setMobileFiltersOpen(!mobileFiltersOpen)}>
              {mobileFiltersOpen ? "Скрыть фильтры" : "Фильтры"}
            </button>
            <select className="toolbar-select" value={sort} onChange={(e) => setSort(e.target.value)}>
              <option value="name-asc">По названию А→Я</option>
              <option value="name-desc">По названию Я→А</option>
              <option value="price-asc">По цене ↑</option>
              <option value="price-desc">По цене ↓</option>
              <option value="category">По категории</option>
            </select>
          </div>

          <div className="catalog-list">
            {filtered.length === 0 &&
            <div className="loading">
                Ничего не найдено. Попробуйте другой запрос или сбросьте фильтры.
              </div>
            }
            {view === "grid" ?
            <div className="products-grid">
                {filtered.map((p) => {
                const inCart = cart.items.find((x) => x.id === p.id);
                return (
                  <ProductCard key={p.id} product={p} onAdd={addToCart} onOpen={openProduct}
                  cartQty={inCart ? inCart.qty : 0} onSetQty={cart.setQty} />);
              })}
              </div> :

            <div className="products-list">
                {filtered.map((p) => {
                const inCart = cart.items.find((x) => x.id === p.id);
                return (
                  <ProductRow key={p.id} product={p} onAdd={addToCart} onOpen={openProduct}
                  cartQty={inCart ? inCart.qty : 0} onSetQty={cart.setQty} />);
              })}
              </div>
            }
          </div>
        </div>
      </div>
    </section>);

}

function ProductCard({ product, onAdd, cartQty, onSetQty, onOpen }) {
  const handleAdd = (e) => {e.stopPropagation();onAdd(product, 1);};
  const specs = Object.entries(product.attributes || {}).filter(([k]) => k !== "Бренд").slice(0, 3).
  map(([k, v]) => `${k}: ${v}`).join(" · ");
  const image = product.image || (product.images && product.images[0]);
  return (
    <article className="product-card" onClick={() => onOpen(product)}>
      <div className="product-card__top">
        <span className="product-card__sku">№ {product.sourceId}</span>
        <span className="product-card__brand">{product.brand}</span>
      </div>
      <div className={`product-card__img${image ? " has-image" : ""}`} aria-hidden={!image}>
        {image ?
        <img src={image} alt="" loading="lazy" decoding="async" /> :
        product.categoryName}
      </div>
      <h3 className="product-card__title">{product.title}</h3>
      {specs && <div className="product-card__specs">{specs}</div>}
      <div className="product-card__bottom">
        {product.price != null ?
        <div className="product-card__price">{RUB(product.price)}<em>/{product.unit}</em></div> :
        <div className="product-card__price--request">Цена по запросу</div>}
        {cartQty > 0 ?
        <div onClick={(e) => e.stopPropagation()}>
            <QtyStep value={cartQty} onChange={(v) => onSetQty(product.id, v)} variant="inline" />
          </div> :
        <button className="product-card__add" onClick={handleAdd}>В корзину</button>
        }
      </div>
    </article>);
}

function ProductRow({ product, onAdd, cartQty, onSetQty, onOpen }) {
  const handleAdd = (e) => {e.stopPropagation();onAdd(product, 1);};
  const image = product.image || (product.images && product.images[0]);
  return (
    <div className="product-row" onClick={() => onOpen(product)}>
      <div className={`product-row__img${image ? " has-image" : ""}`} aria-hidden={!image}>
        {image && <img src={image} alt="" loading="lazy" decoding="async" />}
      </div>
      <div>
        <div className="product-row__title">{product.title}</div>
        <div className="product-row__meta">№ {product.sourceId} · {product.brand} · {product.categoryName}</div>
      </div>
      <div>
        {product.price != null ?
        <div className="product-row__price">{RUB(product.price)}<em>/{product.unit}</em></div> :
        <div className="product-card__price--request">По запросу</div>}
      </div>
      <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--muted)" }}>
        {product.inStock ? `${product.deliveryDays || 1}–${(product.deliveryDays || 1) + 1} дн.` : "Под заказ"}
      </div>
      {cartQty > 0 ?
      <div onClick={(e) => e.stopPropagation()}>
          <QtyStep value={cartQty} onChange={(v) => onSetQty(product.id, v)} variant="inline" />
        </div> :
      <button className="btn btn--small btn--ink" onClick={handleAdd}>В корзину</button>
      }
    </div>);
}

// ---------- PRODUCT MODAL ----------
function ProductModal({ product, onClose, onAdd }) {
  const [qty, setQty] = useState(1);
  if (!product) return null;
  const handleAdd = () => {onAdd(product, qty);onClose();};
  const image = product.image || (product.images && product.images[0]);
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <button className="modal__close" onClick={onClose} aria-label="Закрыть">×</button>
        <div className="modal__eyebrow">{product.categoryPath || product.categoryName} · № {product.sourceId}</div>
        <h2 className="modal__title">{product.title}</h2>
        <div style={{ fontFamily: "var(--mono)", fontSize: 11, color: "var(--accent)", textTransform: "uppercase", letterSpacing: "0.1em" }}>
          {product.brand}
        </div>
        <div className={`modal__img${image ? " has-image" : ""}`}>
          {image ?
          <img src={image} alt={product.title} loading="lazy" decoding="async" /> :
          `${product.categoryName} — изображение из API Комуса`}
        </div>
        <div className="modal__price">
          {product.price != null ?
          <>{RUB(product.price)} <span style={{ fontSize: 14, fontFamily: "var(--mono)", color: "var(--muted)", fontWeight: 400 }}>/ {product.unit}</span></> :
          <span style={{ color: "var(--accent)" }}>Цена по запросу</span>}
        </div>
        <div className="price-note">
          {product.price != null ?
          "Ориентировочная цена. Итоговая стоимость подтверждается менеджером после обработки заявки." :
          "Итоговая стоимость подтверждается менеджером после обработки заявки."}
        </div>
        {product.description && <p className="modal__desc">{product.description}</p>}
        <dl className="modal__specs">
          {Object.entries(product.attributes || {}).map(([k, v]) =>
          <div className="modal__spec" key={k}>
              <dt>{k}</dt>
              <dd>{v}</dd>
            </div>
          )}
          <div className="modal__spec">
            <dt>Наличие</dt>
            <dd>{product.inStock ? `На складе, поставка ${product.deliveryDays || 1}–${(product.deliveryDays || 1) + 1} дн.` : "Под заказ, уточняйте у менеджера"}</dd>
          </div>
        </dl>
        <div className="modal__actions">
          <QtyStep value={qty} onChange={setQty} />
          <button className="btn btn--primary" onClick={handleAdd} style={{ flex: 1 }}>В корзину</button>
        </div>
      </div>
    </div>);

}

function QtyStep({ value, onChange, variant }) {
  const allowZero = variant === "inline";
  const lo = allowZero ? 0 : 1;
  return (
    <div className={`qty-step${variant === "inline" ? " qty-step--inline" : ""}`}>
      <button onClick={() => onChange(Math.max(lo, value - 1))} aria-label="Уменьшить">−</button>
      <input type="number" value={value} min={lo}
      onChange={(e) => onChange(Math.max(lo, parseInt(e.target.value || String(lo), 10)))} style={{ borderColor: "rgb(255, 255, 255)" }} />
      <button onClick={() => onChange(value + 1)} aria-label="Увеличить">+</button>
    </div>);

}

// ---------- CART FULLSCREEN ----------
function CartFullscreen({ open, onClose, cart, onCheckout, onKP }) {
  if (!open) return null;
  const empty = cart.items.length === 0;
  return (
    <div className="cart-full" role="dialog" aria-modal="true">
      <div className="cart-full__head">
        <div>
          <div className="modal__eyebrow">Корзина · {cart.counts} позиций</div>
          <h2 className="cart-full__title">Ваша заявка</h2>
        </div>
        <button className="cart-full__close" onClick={onClose} aria-label="Закрыть">×</button>
      </div>

      <div className="cart-full__body">
        {empty ?
        <div className="cart-empty">
            <div className="cart-empty__title">Корзина пуста</div>
            <p style={{ color: "var(--muted)", maxWidth: 380 }}>
              Добавьте позиции из каталога — корзина сохранится после перезагрузки страницы.
            </p>
            <button className="btn btn--primary btn--cta-hero" onClick={onClose}>Перейти в каталог</button>
          </div> :

        <div className="cart-full__grid">
            <div className="cart-full__list">
              {cart.items.map((it) =>
            <div className="cart-row" key={it.id}>
                  <Thumb product={it} size={72} />
                  <div className="cart-row__main">
                    <div className="cart-row__title">{it.title}</div>
                    <div className="cart-row__meta">
                      № {it.sourceId} · {it.brand} · {it.unit}
                    </div>
                  </div>
                  <div className="cart-row__qty">
                    <QtyStep value={it.qty} onChange={(v) => cart.setQty(it.id, v)} />
                  </div>
                  <div className="cart-row__price">
                    {it.price != null ?
                <>
                        <div className="cart-row__sum">{RUB(it.price * it.qty)}</div>
                        <div className="cart-row__unit">{RUB(it.price)} / {it.unit}</div>
                      </> :

                <div className="cart-row__request">по запросу</div>
                }
                  </div>
                  <button className="cart-row__remove" onClick={() => cart.remove(it.id)} aria-label="Удалить">×</button>
                </div>
            )}
            </div>

            <aside className="cart-full__summary">
              <div className="summary-card">
                <div className="summary-card__head">Итог по заявке</div>
                <div className="summary-card__row">
                  <span>Позиций</span>
                  <span>{cart.items.length}</span>
                </div>
                <div className="summary-card__row">
                  <span>Единиц товара</span>
                  <span>{cart.counts}</span>
                </div>
                <div className="summary-card__row summary-card__row--total">
                  <span>Ориентировочная сумма</span>
                  <span>{RUB(cart.knownTotal)}</span>
                </div>
                {cart.hasUnknown &&
              <div className="summary-card__note">
                    Есть позиции по запросу — итог будет уточнён менеджером.
                  </div>
              }
                <div className="cart-warn">
                  Итоговые цены подтверждаются менеджером после обработки заявки.
                </div>
                <button className="btn btn--primary btn--block btn--cta-hero" onClick={onCheckout}>
                  Оформить заявку →
                </button>
                <button className="btn btn--ink btn--block" onClick={onKP} style={{ marginTop: 8 }}>
                  Получить коммерческое предложение
                </button>
                <button className="btn btn--ghost btn--block" onClick={cart.clear} style={{ marginTop: 8 }}>
                  Очистить корзину
                </button>
              </div>
            </aside>
          </div>
        }
      </div>
    </div>);
}

// ---------- CHECKOUT KP (Коммерческое предложение) ----------
function CheckoutKP({ open, onClose, cart }) {
  const [step, setStep] = useState("form"); // form | preview | success
  const [form, setForm] = useState({
    companyName: "", inn: "", kpp: "", legalAddress: "",
    contactName: "", phone: "", email: "",
    addressedTo: "", comment: "", hp: ""
  });
  const [errors, setErrors] = useState({});
  const [sending, setSending] = useState(false);
  const [success, setSuccess] = useState(null);

  if (!open) return null;

  const upd = (k) => (e) => {
    const v = e.target.value;
    setForm((f) => ({ ...f, [k]: v }));
  };

  const validate = () => {
    const er = {};
    if (!form.companyName.trim()) er.companyName = "Укажите название компании";
    if (!form.inn.trim()) er.inn = "Укажите ИНН";
    if (form.inn && !/^\d{10}(\d{2})?$/.test(form.inn.trim())) er.inn = "ИНН: 10 или 12 цифр";
    if (!form.contactName.trim()) er.contactName = "Укажите контактное лицо";
    if (!form.phone.trim() && !form.email.trim()) {
      er.phone = "Укажите телефон или email";
      er.email = "Укажите телефон или email";
    }
    if (form.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) {
      er.email = "Некорректный email";
    }
    setErrors(er);
    return Object.keys(er).length === 0;
  };

  const goPreview = (e) => {
    e.preventDefault();
    if (form.hp) return;
    if (!validate()) return;
    setStep("preview");
  };

  const sendKP = async () => {
    setSending(true);
    const payload = {
      kind: "kp",
      ...form,
      items: cart.items,
      knownTotal: cart.knownTotal,
      currency: "RUB",
      siteOrigin: location.origin
    };
    const res = await window.CatalogAPI.sendCommercialOffer(payload);
    setSending(false);
    if (res.ok) {
      setSuccess(res);
      setStep("success");
      cart.clear();
    }
  };

  const today = new Date().toLocaleDateString("ru-RU");
  const kpNum = `KP-${String(Date.now()).slice(-6)}`;

  return (
    <div className="cart-full" role="dialog" aria-modal="true">
      <div className="cart-full__head">
        <div>
          <div className="modal__eyebrow">
            {step === "form" && "Коммерческое предложение · реквизиты"}
            {step === "preview" && "Коммерческое предложение · превью"}
            {step === "success" && `Заявка на КП № ${success?.orderId}`}
          </div>
          <h2 className="cart-full__title">
            {step === "form" && "Получить коммерческое предложение"}
            {step === "preview" && "Проверьте состав КП"}
            {step === "success" && "Заявка отправлена"}
          </h2>
        </div>
        <button className="cart-full__close" onClick={onClose} aria-label="Закрыть">×</button>
      </div>

      <div className="cart-full__body">
        {step === "form" &&
        <div className="kp-form-wrap">
          <form className="kp-form" onSubmit={goPreview} noValidate>
            <div className="kp-form__section">
              <div className="kp-form__section-title">Реквизиты юридического лица</div>
              <div className="field">
                <label htmlFor="kpComp">Название компании *</label>
                <input id="kpComp" value={form.companyName} onChange={upd("companyName")} autoComplete="organization" />
                {errors.companyName && <div className="field__error">{errors.companyName}</div>}
              </div>
              <div className="field--row">
                <div className="field">
                  <label htmlFor="kpInn">ИНН *</label>
                  <input id="kpInn" value={form.inn} onChange={upd("inn")} inputMode="numeric" />
                  {errors.inn && <div className="field__error">{errors.inn}</div>}
                </div>
                <div className="field">
                  <label htmlFor="kpKpp">КПП</label>
                  <input id="kpKpp" value={form.kpp} onChange={upd("kpp")} inputMode="numeric" />
                </div>
              </div>
              <div className="field">
                <label htmlFor="kpAddr">Юридический адрес</label>
                <input id="kpAddr" value={form.legalAddress} onChange={upd("legalAddress")} />
              </div>
            </div>

            <div className="kp-form__section">
              <div className="kp-form__section-title">Контакт</div>
              <div className="field">
                <label htmlFor="kpName">Контактное лицо *</label>
                <input id="kpName" value={form.contactName} onChange={upd("contactName")} autoComplete="name" />
                {errors.contactName && <div className="field__error">{errors.contactName}</div>}
              </div>
              <div className="field--row">
                <div className="field">
                  <label htmlFor="kpPh">Телефон *</label>
                  <input id="kpPh" type="tel" value={form.phone} onChange={upd("phone")} placeholder="+7 (___) ___-__-__" autoComplete="tel" />
                  {errors.phone && <div className="field__error">{errors.phone}</div>}
                </div>
                <div className="field">
                  <label htmlFor="kpEm">Email *</label>
                  <input id="kpEm" type="email" value={form.email} onChange={upd("email")} autoComplete="email" />
                  {errors.email && <div className="field__error">{errors.email}</div>}
                </div>
              </div>
            </div>

            <div className="kp-form__section">
              <div className="kp-form__section-title">Дополнительно</div>
              <div className="field">
                <label htmlFor="kpTo">Кому адресовать КП</label>
                <input id="kpTo" value={form.addressedTo} onChange={upd("addressedTo")}
                placeholder="Например: Генеральному директору ООО «Ромашка»" />
              </div>
              <div className="field">
                <label htmlFor="kpCmt">Комментарий</label>
                <textarea id="kpCmt" rows="3" value={form.comment} onChange={upd("comment")}
                placeholder="Сроки, условия доставки, особые требования…"></textarea>
              </div>
            </div>

            <input style={{ position: "absolute", left: -9999 }} tabIndex="-1" autoComplete="off"
            value={form.hp} onChange={upd("hp")} aria-hidden="true" />

            <div className="kp-form__actions">
              <button type="button" className="btn btn--ghost" onClick={onClose}>Отменить</button>
              <button type="submit" className="btn btn--primary btn--cta-hero">
                Продолжить — превью КП →
              </button>
            </div>
          </form>

          <aside className="cart-full__summary">
            <div className="summary-card">
              <div className="summary-card__head">Состав корзины</div>
              <div className="kp-mini-list">
                {cart.items.map((it) =>
                <div className="kp-mini-row" key={it.id}>
                  <Thumb product={it} size={40} />
                  <div className="kp-mini-row__main">
                    <div className="kp-mini-row__title">{it.title}</div>
                    <div className="kp-mini-row__meta">№ {it.sourceId} · {it.qty} {it.unit}</div>
                  </div>
                </div>
                )}
              </div>
              <div className="summary-card__row summary-card__row--total">
                <span>Ориентировочная сумма</span>
                <span>{RUB(cart.knownTotal)}</span>
              </div>
              <div className="cart-warn">
                Итоговые цены подтверждаются менеджером после обработки заявки.
              </div>
            </div>
          </aside>
        </div>
        }

        {step === "preview" &&
        <div className="kp-preview-wrap">
          <div className="kp-doc">
            <div className="kp-doc__head">
              <div>
                <div className="kp-doc__brand">{window.SITE_CONFIG.brand.name}</div>
                <div className="kp-doc__sub">{window.SITE_CONFIG.brand.tagline}</div>
              </div>
              <div className="kp-doc__meta">
                <div><strong>Коммерческое предложение</strong></div>
                <div>№ {kpNum}</div>
                <div>от {today}</div>
              </div>
            </div>

            <div className="kp-doc__parties">
              <div className="kp-doc__party">
                <div className="kp-doc__party-label">От кого</div>
                <div className="kp-doc__party-body">
                  <strong>{window.SITE_CONFIG.brand.name}</strong><br />
                  {window.SITE_CONFIG.contacts.city}<br />
                  {window.SITE_CONFIG.contacts.phone}<br />
                  {window.SITE_CONFIG.contacts.email}
                </div>
              </div>
              <div className="kp-doc__party">
                <div className="kp-doc__party-label">Кому</div>
                <div className="kp-doc__party-body">
                  <strong>{form.companyName || "—"}</strong><br />
                  ИНН {form.inn || "—"}{form.kpp && `, КПП ${form.kpp}`}<br />
                  {form.legalAddress && <>{form.legalAddress}<br /></>}
                  {form.addressedTo && <>{form.addressedTo}<br /></>}
                  {form.contactName}{form.phone && `, ${form.phone}`}{form.email && `, ${form.email}`}
                </div>
              </div>
            </div>

            <table className="kp-table">
              <thead>
                <tr>
                  <th>№</th>
                  <th>Наименование</th>
                  <th>Артикул</th>
                  <th>Кол-во</th>
                  <th>Ед.</th>
                  <th>Цена</th>
                  <th>Сумма</th>
                </tr>
              </thead>
              <tbody>
                {cart.items.map((it, i) =>
                <tr key={it.id}>
                  <td>{i + 1}</td>
                  <td>{it.title}</td>
                  <td className="mono">{it.sourceId}</td>
                  <td>{it.qty}</td>
                  <td>{it.unit}</td>
                  <td className="mono">{it.price != null ? RUB(it.price) : "по запросу"}</td>
                  <td className="mono">{it.price != null ? RUB(it.price * it.qty) : "—"}</td>
                </tr>
                )}
              </tbody>
              <tfoot>
                <tr>
                  <td colSpan="6" style={{ textAlign: "right" }}>Ориентировочная сумма</td>
                  <td className="mono"><strong>{RUB(cart.knownTotal)}</strong></td>
                </tr>
              </tfoot>
            </table>

            <div className="kp-doc__note">
              Итоговые цены подтверждаются менеджером после обработки заявки. Возможен индивидуальный просчёт от базовой цены в зависимости от объёма и категории. Доступны дополнительные скидки. После первых 3 заказов — отсрочка платежа по согласованию.
            </div>
            {form.comment &&
            <div className="kp-doc__comment">
              <strong>Комментарий:</strong> {form.comment}
            </div>
            }
          </div>

          <div className="kp-form__actions kp-preview__actions">
            <button type="button" className="btn btn--ghost" onClick={() => setStep("form")}>← Назад к реквизитам</button>
            <button type="button" className="btn btn--primary btn--cta-hero" onClick={sendKP} disabled={sending}>
              {sending ? "Отправка…" : "Отправить заявку на КП"}
            </button>
          </div>
        </div>
        }

        {step === "success" && success &&
        <div className="success">
          <div className="success__mark">✓</div>
          <div className="modal__eyebrow">Заявка на КП № {success.orderId}</div>
          <h2 className="success__title">Мы выставим КП</h2>
          <p style={{ maxWidth: 480, color: "var(--ink-2)" }}>
            Менеджер подтвердит цены, сроки и пришлёт коммерческое предложение с реквизитами на {form.email || "указанный вами email"}.
          </p>
          <p style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--muted)" }}>
            Копия письма ушла на {success.sentTo}
          </p>
          <button className="btn btn--primary btn--cta-hero" onClick={onClose}>Вернуться в каталог</button>
        </div>
        }
      </div>
    </div>);
}

// ---------- CHECKOUT (обычная заявка) ----------
function CheckoutDrawer({ open, onClose, cart, onSent }) {
  const [form, setForm] = useState({
    customerName: "", customerPhone: "", customerEmail: "",
    companyName: "", inn: "", city: "Москва", comment: "", consent: false,
    sendCopy: true, hp: ""
  });
  const [errors, setErrors] = useState({});
  const [sending, setSending] = useState(false);
  const [success, setSuccess] = useState(null);

  if (!open) return null;

  const upd = (k) => (e) => {
    const v = e.target.type === "checkbox" ? e.target.checked : e.target.value;
    setForm((f) => ({ ...f, [k]: v }));
  };

  const validate = () => {
    const er = {};
    if (!form.customerName.trim()) er.customerName = "Укажите имя";
    if (!form.customerPhone.trim() && !form.customerEmail.trim()) {
      er.customerPhone = "Укажите телефон или email";
      er.customerEmail = "Укажите телефон или email";
    }
    if (form.customerEmail && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.customerEmail)) {
      er.customerEmail = "Некорректный email";
    }
    if (!form.consent) er.consent = "Нужно согласие на обработку данных";
    setErrors(er);
    return Object.keys(er).length === 0;
  };

  const submit = async (e) => {
    e.preventDefault();
    if (form.hp) return; // honeypot
    if (!validate()) return;
    setSending(true);
    const payload = {
      ...form,
      items: cart.items,
      knownTotal: cart.knownTotal,
      currency: "RUB",
      siteOrigin: location.origin
    };
    const res = await window.CatalogAPI.sendOrder(payload);
    setSending(false);
    if (res.ok) {
      setSuccess(res);
      cart.clear();
      onSent && onSent(res);
    }
  };

  if (success) {
    return (
      <div className="modal-backdrop" onClick={onClose}>
        <div className="modal" onClick={(e) => e.stopPropagation()}>
          <button className="modal__close" onClick={onClose}>×</button>
          <div className="success">
            <div className="success__mark">✓</div>
            <div className="modal__eyebrow">Заявка № {success.orderId}</div>
            <h2 className="success__title">Заявка отправлена</h2>
            <p style={{ maxWidth: 380, color: "var(--ink-2)" }}>
              Менеджер свяжется в течение часа в рабочее время и подтвердит наличие, цены и срок поставки.
            </p>
            <p style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--muted)" }}>
              Копия письма ушла на {success.sentTo}
            </p>
            <button className="btn btn--ink" onClick={onClose}>Вернуться в каталог</button>
          </div>
        </div>
      </div>);

  }

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal modal--wide" onClick={(e) => e.stopPropagation()}>
        <button className="modal__close" onClick={onClose}>×</button>
        <div className="modal__eyebrow">Оформление заявки · {cart.counts} позиций</div>
        <h2 className="modal__title">Контактные данные</h2>

        <div className="checkout-items">
          {cart.items.map((it) =>
          <div className="checkout-item" key={it.id}>
            <Thumb product={it} size={48} />
            <div className="checkout-item__main">
              <div className="checkout-item__title">{it.title}</div>
              <div className="checkout-item__meta">№ {it.sourceId} · {it.qty} {it.unit}</div>
            </div>
            <div className="checkout-item__price">
              {it.price != null ? RUB(it.price * it.qty) :
              <span style={{ color: "var(--accent)" }}>по запросу</span>}
            </div>
          </div>
          )}
        </div>

        <form className="checkout" onSubmit={submit} noValidate>
          <div className="field">
            <label htmlFor="cn">Имя контактного лица *</label>
            <input id="cn" value={form.customerName} onChange={upd("customerName")} autoComplete="name" />
            {errors.customerName && <div className="field__error">{errors.customerName}</div>}
          </div>
          <div className="field--row">
            <div className="field">
              <label htmlFor="cp">Телефон *</label>
              <input id="cp" type="tel" value={form.customerPhone} onChange={upd("customerPhone")} placeholder="+7 (___) ___-__-__" autoComplete="tel" />
              {errors.customerPhone && <div className="field__error">{errors.customerPhone}</div>}
            </div>
            <div className="field">
              <label htmlFor="ce">Email *</label>
              <input id="ce" type="email" value={form.customerEmail} onChange={upd("customerEmail")} autoComplete="email" />
              {errors.customerEmail && <div className="field__error">{errors.customerEmail}</div>}
            </div>
          </div>
          <div className="field--row">
            <div className="field">
              <label htmlFor="comp">Компания</label>
              <input id="comp" value={form.companyName} onChange={upd("companyName")} autoComplete="organization" />
            </div>
            <div className="field">
              <label htmlFor="inn">ИНН</label>
              <input id="inn" value={form.inn} onChange={upd("inn")} inputMode="numeric" />
            </div>
          </div>
          <div className="field">
            <label htmlFor="city">Город доставки</label>
            <input id="city" value={form.city} onChange={upd("city")} />
          </div>
          <div className="field">
            <label htmlFor="cmt">Комментарий к заявке</label>
            <textarea id="cmt" rows="3" value={form.comment} onChange={upd("comment")} placeholder="Например: счёт на ООО, доставка до 17:00 и т.п."></textarea>
          </div>

          {/* honeypot */}
          <input style={{ position: "absolute", left: -9999 }} tabIndex="-1" autoComplete="off"
          value={form.hp} onChange={upd("hp")} aria-hidden="true" />

          <label className="checkbox">
            <input type="checkbox" checked={form.consent} onChange={upd("consent")} />
            <span>
              Согласен с обработкой персональных данных в целях обработки заявки.
              {errors.consent && <div className="field__error">{errors.consent}</div>}
            </span>
          </label>
          <label className="checkbox">
            <input type="checkbox" checked={form.sendCopy} onChange={upd("sendCopy")} />
            <span>Прислать мне копию заявки на email</span>
          </label>

          <div style={{ display: "flex", justifyContent: "space-between", padding: "16px 0", borderTop: "1px solid var(--line)", marginTop: 8 }}>
            <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--muted)", textTransform: "uppercase", letterSpacing: "0.08em" }}>
              Сумма по известным ценам
            </div>
            <div style={{ fontFamily: "var(--serif)", fontSize: 22, fontWeight: 500 }}>
              {RUB(cart.knownTotal)}
            </div>
          </div>

          <button className="btn btn--primary btn--block btn--cta-hero" type="submit" disabled={sending}>
            {sending ? "Отправка…" : "Отправить заявку"}
          </button>
          <p style={{ fontSize: 12, color: "var(--muted)", textAlign: "center", margin: 0 }}>
            Итоговые цены подтверждаются менеджером после обработки заявки. Заявка уйдёт на {window.SITE_CONFIG.orderRecipient}.
          </p>
        </form>
      </div>
    </div>);

}

// ---------- FOOTER ----------
function Footer({ contacts }) {
  return (
    <footer className="site-footer" id="contacts">
      <div className="site-footer__inner">
        <div>
          <div className="footer-brand">{window.SITE_CONFIG.brand.name}</div>
          <p style={{ color: "#a8a499", fontSize: 14, maxWidth: 320, marginTop: 12 }}>
            Поставщик офисных и канцелярских товаров. Каталог синхронизирован с API Комуса. Работаем с юрлицами, ИП и физлицами.
          </p>
        </div>
        <div className="footer-block">
          <h4>Контакты</h4>
          <a href={contacts.phoneHref}>{contacts.phone}</a>
          <a href={`mailto:${contacts.email}`}>{contacts.email}</a>
          <p>{contacts.workHours}</p>
          <p>{contacts.city}</p>
        </div>
        <div className="footer-block">
          <h4>Связаться</h4>
          <a href={contacts.telegram} target="_blank" rel="noopener">Telegram</a>
          <a href={contacts.whatsapp} target="_blank" rel="noopener">WhatsApp</a>
          <a href={`mailto:${contacts.email}`}>Email</a>
        </div>
        <div className="footer-block">
          <h4>Документы</h4>
          <a href="#">Политика обработки данных</a>
          <a href="#">Реквизиты</a>
          <a href="#">Договор-оферта</a>
        </div>
      </div>
      <div className="site-footer__bottom">
        <span>© {new Date().getFullYear()} {window.SITE_CONFIG.brand.name}. Все права защищены.</span>
        <span>Каталог: данные API Комуса</span>
      </div>
    </footer>);

}

// ---------- ROOT APP ----------
function App() {
  const [page, setPage] = useState("home"); // home | catalog
  const [catalog, setCatalog] = useState({ products: [], categories: [], lastSyncedAt: null, source: null });
  const [loading, setLoading] = useState(true);
  const [openProduct, setOpenProduct] = useState(null);
  const [cartOpen, setCartOpen] = useState(false);
  const [checkoutOpen, setCheckoutOpen] = useState(false);
  const [kpOpen, setKpOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
  const cart = useCart();

  // tweaks state
  const tweaks = useTweaks(TWEAK_DEFAULTS);
  const t = tweaks.values;

  useEffect(() => {
    const a = t.accent && t.accent !== "undefined" ? t.accent : "#FF4D14";
    document.documentElement.style.setProperty("--accent", a);
    document.body.classList.toggle("density-compact", t.density === "compact");
    document.body.classList.remove("typo-modern", "typo-editorial", "typo-mono-mix");
    document.body.classList.add("typo-" + t.typo);
  }, [t.accent, t.density, t.typo]);

  useEffect(() => {
    let active = true;
    setLoading(true);
    window.CatalogAPI.loadCatalog().then((data) => {
      if (active) {setCatalog(data);setLoading(false);}
    });
    return () => {active = false;};
  }, []);

  const goCatalog = (q) => {
    if (q !== undefined) setSearchQuery(q);
    setPage("catalog");
    setTimeout(() => {
      const el = document.getElementById("catalog");
      if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
    }, 50);
  };

  const onAdd = (p, qty) => {
    cart.add(p, qty);
  };

  const navigate = (target, anchor) => {
    setPage(target);
    if (anchor) {
      setTimeout(() => {
        const el = document.getElementById(anchor);
        if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
      }, 80);
    } else {
      window.scrollTo({ top: 0, behavior: "smooth" });
    }
  };

  return (
    <>
      <Header
        cartCount={cart.counts}
        onOpenCart={() => setCartOpen(true)}
        onNavigate={navigate}
        page={page}
        contacts={window.SITE_CONFIG.contacts} />
      
      {page === "home" &&
      <>
          <Hero onSearch={goCatalog} onGoCatalog={() => goCatalog()} />
          <QuickChips onPick={goCatalog} />
          <GovSection onGoCatalog={() => goCatalog()} />
        </>
      }
      {loading ?
      <div className="loading">
          Загружаем каталог из API Комуса
          <div className="loading__bar"></div>
        </div> :

      <Catalog
        catalog={catalog}
        initialQuery={searchQuery}
        addToCart={onAdd}
        cart={cart}
        openProduct={setOpenProduct}
        view={t.view}
        density={t.density}
        mobileFiltersOpen={mobileFiltersOpen}
        setMobileFiltersOpen={setMobileFiltersOpen} />

      }
      <Footer contacts={window.SITE_CONFIG.contacts} />

      {openProduct &&
      <ProductModal
        product={openProduct}
        onClose={() => setOpenProduct(null)}
        onAdd={onAdd} />

      }
      <CartFullscreen
        open={cartOpen}
        onClose={() => setCartOpen(false)}
        cart={cart}
        onCheckout={() => {setCartOpen(false);setCheckoutOpen(true);}}
        onKP={() => {setCartOpen(false);setKpOpen(true);}} />
      
      <CheckoutDrawer
        open={checkoutOpen}
        onClose={() => setCheckoutOpen(false)}
        cart={cart} />
      <CheckoutKP
        open={kpOpen}
        onClose={() => setKpOpen(false)}
        cart={cart} />
      

      <Tweaks tweaks={tweaks} />
    </>);

}

// ---------- TWEAKS PANEL ----------
function Tweaks({ tweaks }) {
  const t = tweaks.values;
  const set = tweaks.setTweak;
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Цвет">
        <TweakColor
          label="Акцент"
          value={t.accent}
          onChange={(v) => set("accent", v)}
          options={["#FF4D14", "#0F4C3A", "#1B3A8C", "#111111", "#C8102E"]} />
        
      </TweakSection>
      <TweakSection title="Каталог">
        <TweakRadio
          label="Плотность"
          value={t.density}
          onChange={(v) => set("density", v)}
          options={[{ value: "comfort", label: "Комфорт" }, { value: "compact", label: "Компакт" }]} />
        
        <TweakRadio
          label="Вид"
          value={t.view}
          onChange={(v) => set("view", v)}
          options={[{ value: "grid", label: "Сетка" }, { value: "list", label: "Список" }]} />
        
      </TweakSection>
      <TweakSection title="Типографика">
        <TweakSelect
          label="Шрифтовая пара"
          value={t.typo}
          onChange={(v) => set("typo", v)}
          options={[
          { value: "editorial", label: "Editorial: Fraunces + Inter" },
          { value: "modern", label: "Modern: Inter (без сериф)" },
          { value: "mono-mix", label: "Mono mix: Fraunces + JetBrains" }]
          } />
        
      </TweakSection>
    </TweaksPanel>);

}

ReactDOM.createRoot(document.getElementById("app")).render(<App />);
