/* global React, window, useCart, useAuth, api, humanError, palette,
   BagPlate, TrunkPlate, RoundPlate, ShoeCabinetPlate, CasePlate, Eyebrow, Rule,
   useIsMobile, FavHeart, AddToCartButton */
const { useState: uS, useEffect: uE, useMemo: uM, useRef: uR } = React;

/* ---------- мелкие хелперы ---------- */
function Wrap({ children, style }) {
  return <div style={{ maxWidth: 1100, margin: "0 auto", padding: "0 24px", ...style }}>{children}</div>;
}

const cartInput = {
  all: "unset", display: "block", width: "100%", boxSizing: "border-box",
  fontFamily: "'Manrope', sans-serif", fontSize: 14, color: "var(--ink)",
  padding: "13px 14px", border: "1px solid rgba(0,0,0,0.18)", background: "var(--cream)",
};

function priceNum(item) { return parseInt(String(item.price || "").replace(/[^\d]/g, ""), 10) || 0; }
function fmtRub(n) { return n.toLocaleString("ru-RU") + " ₽"; }

// Переход на карточку товара. Комплекты - на свою детальную страницу.
function openProduct(item, setRoute) {
  if (!item || !setRoute) return;
  if (item.category === "ensemble") setRoute("ensemble", item.id);
  else setRoute("product", item.key);
}

function PlateFor({ item, size }) {
  const tones = item.tones || [palette.cognac, palette.brass, palette.bone];
  const P = { bag: BagPlate, trunk: TrunkPlate, round: RoundPlate, shoecabinet: ShoeCabinetPlate, case: CasePlate }[item.plate] || CasePlate;
  return (
    <div style={{ width: size, flex: "0 0 auto", background: "var(--cream)", border: "1px solid rgba(0,0,0,0.08)", padding: 8 }}>
      <P id={"thumb-" + item.key} tones={tones} ratio="1/1" dense />
    </div>
  );
}

function PageTitle({ kicker, title }) {
  return (
    <div style={{ marginBottom: 32 }}>
      <Eyebrow>{kicker}</Eyebrow>
      <h1 style={{
        fontFamily: "'Cormorant Garamond', serif", fontWeight: 300, fontStyle: "italic",
        fontSize: "clamp(34px, 4vw, 52px)", lineHeight: 1.05, margin: "12px 0 0",
      }}>{title}</h1>
    </div>
  );
}

function SolidBtn({ children, onClick, disabled, style }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      all: "unset", cursor: disabled ? "default" : "pointer", textAlign: "center",
      fontFamily: "'Manrope', sans-serif", fontSize: 12, letterSpacing: "0.2em", textTransform: "uppercase",
      padding: "16px 30px", background: "var(--ink)", color: "var(--cream)",
      opacity: disabled ? 0.5 : 1, ...style,
    }}>{children}</button>
  );
}

function GhostBtn2({ children, onClick, style }) {
  return (
    <button onClick={onClick} style={{
      all: "unset", cursor: "pointer", textAlign: "center",
      fontFamily: "'Manrope', sans-serif", fontSize: 12, letterSpacing: "0.2em", textTransform: "uppercase",
      padding: "15px 28px", border: "1px solid var(--ink)", color: "var(--ink)", ...style,
    }}>{children}</button>
  );
}

/* ---------- степпер количества ---------- */
function QtyStepper({ qty, onChange }) {
  const btn = {
    all: "unset", cursor: "pointer", width: 32, height: 32, textAlign: "center",
    fontFamily: "'Manrope', sans-serif", fontSize: 16, color: "var(--ink)",
    display: "flex", alignItems: "center", justifyContent: "center",
  };
  return (
    <div style={{ display: "inline-flex", alignItems: "center", border: "1px solid rgba(0,0,0,0.18)" }}>
      <button style={btn} onClick={() => onChange(qty - 1)} aria-label="Меньше">−</button>
      <span style={{ minWidth: 28, textAlign: "center", fontFamily: "'JetBrains Mono', monospace", fontSize: 13 }}>{qty}</span>
      <button style={btn} onClick={() => onChange(qty + 1)} aria-label="Больше">+</button>
    </div>
  );
}

/* ---------- строка товара в корзине ---------- */
function CartRow({ item, showPrice, setRoute }) {
  const { setQty, removeFromCart } = useCart();
  const m = useIsMobile();
  const open = () => openProduct(item, setRoute);
  return (
    <div style={{
      display: "flex", gap: m ? 14 : 20, alignItems: "center",
      padding: "18px 0", borderBottom: "1px solid rgba(0,0,0,0.08)",
    }}>
      <div onClick={open} style={{ cursor: setRoute ? "pointer" : "default", display: "flex" }}>
        <PlateFor item={item} size={m ? 64 : 84} />
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)" }}>
          {item.kind || item.category}
        </div>
        <div onClick={open} style={{ fontFamily: "'Cormorant Garamond', serif", fontStyle: "italic", fontSize: m ? 19 : 22, marginTop: 4, cursor: setRoute ? "pointer" : "default" }}>{item.name}</div>
        <button onClick={() => removeFromCart(item.key)} style={{
          all: "unset", cursor: "pointer", marginTop: 8,
          fontFamily: "'Manrope', sans-serif", fontSize: 11, letterSpacing: "0.1em",
          textTransform: "uppercase", color: "rgba(0,0,0,0.45)", borderBottom: "1px solid rgba(0,0,0,0.2)",
        }}>Удалить</button>
      </div>
      <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 12 }}>
        <QtyStepper qty={item.qty} onChange={q => setQty(item.key, q)} />
        <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 13.5, color: "var(--ink)", whiteSpace: "nowrap" }}>
          {showPrice ? fmtRub(priceNum(item) * item.qty) : item.price}
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   КОРЗИНА
   ========================================================= */
function CartPage({ setRoute }) {
  const { cartItems } = useCart();
  const m = useIsMobile();

  const bags = cartItems.filter(i => i.payable);
  const interior = cartItems.filter(i => !i.payable);
  const bagsTotal = bags.reduce((s, i) => s + priceNum(i) * i.qty, 0);

  if (cartItems.length === 0) {
    return (
      <div style={{ paddingTop: m ? 96 : 150, paddingBottom: m ? 80 : 140 }}>
        <Wrap>
          <PageTitle kicker="Корзина" title="Здесь пока пусто" />
          <p style={{ fontFamily: "'Manrope', sans-serif", fontSize: 15, color: "rgba(0,0,0,0.6)", maxWidth: 440, lineHeight: 1.7 }}>
            Загляните в каталог - добавьте сумки к оплате или чемоданы и интерьер под заявку.
          </p>
          <div style={{ display: "flex", gap: 14, flexWrap: "wrap", marginTop: 28 }}>
            <SolidBtn onClick={() => setRoute("bags", "all")}>Школьные сумки</SolidBtn>
            <GhostBtn2 onClick={() => setRoute("trunks")}>Чемоданы и интерьер</GhostBtn2>
          </div>
        </Wrap>
      </div>
    );
  }

  return (
    <div style={{ paddingTop: m ? 96 : 150, paddingBottom: m ? 80 : 140 }}>
      <Wrap>
        <PageTitle kicker="Корзина" title="Ваш выбор" />

        {bags.length > 0 && (
          <section style={{ marginBottom: 48 }}>
            <GroupHead title="Сумки" note="Фиксированная цена - можно оплатить онлайн." />
            {bags.map(i => <CartRow key={i.key} item={i} showPrice setRoute={setRoute} />)}
            <div style={{
              display: "flex", flexDirection: m ? "column" : "row", gap: 16,
              justifyContent: "space-between", alignItems: m ? "stretch" : "center", marginTop: 22,
            }}>
              <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 15 }}>
                Итого к оплате:&nbsp;
                <strong style={{ fontSize: 18 }}>{fmtRub(bagsTotal)}</strong>
              </div>
              <SolidBtn onClick={() => setRoute("checkout-pay")}>Перейти к оплате</SolidBtn>
            </div>
          </section>
        )}

        {interior.length > 0 && (
          <section>
            <GroupHead title="Чемоданы и интерьер" note="Точная цена и комплектация - по заявке, мы свяжемся с вами." />
            {interior.map(i => <CartRow key={i.key} item={i} setRoute={setRoute} />)}
            <div style={{
              display: "flex", flexDirection: m ? "column" : "row", gap: 16,
              justifyContent: "space-between", alignItems: m ? "stretch" : "center", marginTop: 22,
            }}>
              <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 13.5, color: "rgba(0,0,0,0.6)", maxWidth: 420, lineHeight: 1.6 }}>
                Это заявка, а не оплата. После отправки мастер свяжется и согласует размеры, тон и стоимость.
              </div>
              <SolidBtn onClick={() => setRoute("checkout-request")}>Оформить заявку</SolidBtn>
            </div>
          </section>
        )}
      </Wrap>
    </div>
  );
}

function GroupHead({ title, note }) {
  return (
    <div style={{ borderBottom: "1px solid rgba(0,0,0,0.14)", paddingBottom: 12, marginBottom: 6 }}>
      <h2 style={{ fontFamily: "'Cormorant Garamond', serif", fontStyle: "italic", fontWeight: 400, fontSize: 26, margin: 0 }}>{title}</h2>
      <p style={{ fontFamily: "'Manrope', sans-serif", fontSize: 12.5, color: "rgba(0,0,0,0.55)", margin: "6px 0 0" }}>{note}</p>
    </div>
  );
}

/* ---------- контактные поля (общие для заявки и оплаты) ---------- */
function useContactForm() {
  const auth = useAuth();
  const [form, setForm] = uS({ name: "", phone: "", email: "", comment: "" });
  const prefilled = uR(false);
  uE(() => {
    if (!prefilled.current && auth.isAuthed && auth.user) {
      setForm(f => ({
        ...f,
        name: f.name || auth.user.name || "",
        email: f.email || auth.user.email || "",
        phone: f.phone || auth.user.phone || "",
      }));
      prefilled.current = true;
    }
  }, [auth.isAuthed, auth.user]);
  return [form, setForm];
}

function ContactFields({ form, setForm, withComment }) {
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  return (
    <div style={{ display: "grid", gap: 14, maxWidth: 460 }}>
      <input style={cartInput} placeholder="Имя*" value={form.name} onChange={e => set("name", e.target.value)} />
      <input style={cartInput} placeholder="Телефон" value={form.phone} onChange={e => set("phone", e.target.value)} />
      <input style={cartInput} placeholder="E-mail" value={form.email} onChange={e => set("email", e.target.value)} />
      {withComment && (
        <textarea style={{ ...cartInput, resize: "vertical" }} rows={4} placeholder="Комментарий, пожелания, удобное время связи"
          value={form.comment} onChange={e => set("comment", e.target.value)} />
      )}
      <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 11.5, color: "rgba(0,0,0,0.5)" }}>
        Укажите телефон или e-mail - как с вами связаться.
      </div>
    </div>
  );
}

function validContact(form) {
  if (!form.name.trim()) return "Укажите имя.";
  if (!form.phone.trim() && !form.email.trim()) return "Укажите телефон или e-mail.";
  return null;
}

/* =========================================================
   ЗАЯВКА (интерьер)
   ========================================================= */
function CheckoutRequestPage({ setRoute }) {
  const { cartItems, removeKeys } = useCart();
  const m = useIsMobile();
  const [form, setForm] = useContactForm();
  const [err, setErr] = uS(null);
  const [busy, setBusy] = uS(false);
  const [done, setDone] = uS(null); // {publicId}

  const interior = cartItems.filter(i => !i.payable);

  uE(() => { if (!done && interior.length === 0) setRoute("cart"); }, [interior.length, done]);

  const submit = async () => {
    const v = validContact(form);
    if (v) { setErr(v); return; }
    setBusy(true); setErr(null);
    try {
      const items = interior.map(i => ({ key: i.key, qty: i.qty }));
      const res = await api.orders.request({ ...form, items });
      removeKeys(interior.map(i => i.key));
      setDone({ publicId: res.publicId });
    } catch (e) {
      setErr(humanError(e));
    } finally { setBusy(false); }
  };

  if (done) {
    return (
      <ResultScreen
        kicker="Заявка принята"
        title="Спасибо! С вами свяжутся"
        publicId={done.publicId}
        text="Мы получили вашу заявку и свяжемся в течение дня - уточним размеры, тон и стоимость."
        setRoute={setRoute}
      />
    );
  }

  return (
    <div style={{ paddingTop: m ? 96 : 150, paddingBottom: m ? 80 : 140 }}>
      <Wrap>
        <PageTitle kicker="Оформление заявки" title="Чемоданы и интерьер" />
        <div style={{ display: "grid", gridTemplateColumns: m ? "1fr" : "1fr 1fr", gap: m ? 36 : 64, alignItems: "start" }}>
          <div>
            <h3 style={{ fontFamily: "'Manrope', sans-serif", fontSize: 12, letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)", margin: "0 0 14px" }}>Состав заявки</h3>
            {interior.map(i => (
              <div key={i.key} style={{ display: "flex", gap: 14, alignItems: "center", padding: "12px 0", borderBottom: "1px solid rgba(0,0,0,0.08)" }}>
                <PlateFor item={i} size={56} />
                <div style={{ flex: 1 }}>
                  <div style={{ fontFamily: "'Cormorant Garamond', serif", fontStyle: "italic", fontSize: 19 }}>{i.name}</div>
                  <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 12.5, color: "rgba(0,0,0,0.55)" }}>{i.price} · × {i.qty}</div>
                </div>
              </div>
            ))}
          </div>
          <div>
            <h3 style={{ fontFamily: "'Manrope', sans-serif", fontSize: 12, letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)", margin: "0 0 14px" }}>Контактные данные</h3>
            <ContactFields form={form} setForm={setForm} withComment />
            {err && <div style={{ color: palette.oxblood, fontFamily: "'Manrope', sans-serif", fontSize: 13, marginTop: 14 }}>{err}</div>}
            <div style={{ marginTop: 22, display: "flex", gap: 14, flexWrap: "wrap" }}>
              <SolidBtn onClick={submit} disabled={busy}>{busy ? "Отправляем…" : "Отправить заявку"}</SolidBtn>
              <GhostBtn2 onClick={() => setRoute("cart")}>Назад в корзину</GhostBtn2>
            </div>
          </div>
        </div>
      </Wrap>
    </div>
  );
}

/* =========================================================
   ОПЛАТА (сумки)
   ========================================================= */
function CheckoutPaymentPage({ setRoute }) {
  const { cartItems } = useCart();
  const m = useIsMobile();
  const [form, setForm] = useContactForm();
  const [err, setErr] = uS(null);
  const [busy, setBusy] = uS(false);

  const bags = cartItems.filter(i => i.payable);
  const total = bags.reduce((s, i) => s + priceNum(i) * i.qty, 0);

  uE(() => { if (bags.length === 0) setRoute("cart"); }, [bags.length]);

  const submit = async () => {
    const v = validContact(form);
    if (v) { setErr(v); return; }
    setBusy(true); setErr(null);
    try {
      const items = bags.map(i => ({ key: i.key, qty: i.qty }));
      const res = await api.orders.checkout({ ...form, items });
      // Уходим на платёжную форму Т-Кассы (в stub-режиме - сразу на страницу результата).
      window.location.href = res.paymentUrl;
    } catch (e) {
      setErr(humanError(e));
      setBusy(false);
    }
  };

  return (
    <div style={{ paddingTop: m ? 96 : 150, paddingBottom: m ? 80 : 140 }}>
      <Wrap>
        <PageTitle kicker="Оплата" title="Оформление заказа" />
        <div style={{ display: "grid", gridTemplateColumns: m ? "1fr" : "1fr 1fr", gap: m ? 36 : 64, alignItems: "start" }}>
          <div>
            <h3 style={{ fontFamily: "'Manrope', sans-serif", fontSize: 12, letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)", margin: "0 0 14px" }}>Ваш заказ</h3>
            {bags.map(i => (
              <div key={i.key} style={{ display: "flex", gap: 14, alignItems: "center", padding: "12px 0", borderBottom: "1px solid rgba(0,0,0,0.08)" }}>
                <PlateFor item={i} size={56} />
                <div style={{ flex: 1 }}>
                  <div style={{ fontFamily: "'Cormorant Garamond', serif", fontStyle: "italic", fontSize: 19 }}>{i.name}</div>
                  <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 12.5, color: "rgba(0,0,0,0.55)" }}>× {i.qty}</div>
                </div>
                <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 13.5 }}>{fmtRub(priceNum(i) * i.qty)}</div>
              </div>
            ))}
            <div style={{ display: "flex", justifyContent: "space-between", marginTop: 18, fontFamily: "'Manrope', sans-serif" }}>
              <span style={{ fontSize: 14, letterSpacing: "0.04em" }}>Итого</span>
              <strong style={{ fontSize: 19 }}>{fmtRub(total)}</strong>
            </div>
          </div>
          <div>
            <h3 style={{ fontFamily: "'Manrope', sans-serif", fontSize: 12, letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)", margin: "0 0 14px" }}>Контактные данные</h3>
            <ContactFields form={form} setForm={setForm} />
            {err && <div style={{ color: palette.oxblood, fontFamily: "'Manrope', sans-serif", fontSize: 13, marginTop: 14 }}>{err}</div>}
            <div style={{ marginTop: 22, display: "flex", gap: 14, flexWrap: "wrap" }}>
              <SolidBtn onClick={submit} disabled={busy}>{busy ? "Переходим к оплате…" : `Оплатить ${fmtRub(total)}`}</SolidBtn>
              <GhostBtn2 onClick={() => setRoute("cart")}>Назад в корзину</GhostBtn2>
            </div>
            <p style={{ fontFamily: "'Manrope', sans-serif", fontSize: 11.5, color: "rgba(0,0,0,0.5)", marginTop: 16, lineHeight: 1.6 }}>
              Оплата проходит через защищённую форму Т-Кассы. Данные карты на сайт не попадают.
            </p>
          </div>
        </div>
      </Wrap>
    </div>
  );
}

/* =========================================================
   РЕЗУЛЬТАТ ОПЛАТЫ (возврат с Т-Кассы / страница статуса)
   ========================================================= */
function OrderStatusPage({ id, setRoute }) {
  const { removeKeys } = useCart();
  const m = useIsMobile();
  const [order, setOrder] = uS(undefined); // undefined=загрузка, null=не найден
  const cleared = uR(false);

  uE(() => {
    if (!id) { setOrder(null); return; }
    let stop = false;
    let tries = 0;
    const poll = async () => {
      try {
        const res = await api.orders.get(id);
        if (stop) return;
        setOrder(res.order);
        // Оплачено - убираем эти позиции из локальной корзины (для гостя).
        if (res.order.kind === "payment" && res.order.status === "paid" && !cleared.current) {
          cleared.current = true;
          removeKeys((res.order.items || []).map(i => i.key));
        }
        // Продолжаем опрашивать, пока оплата в ожидании.
        if (res.order.status === "pending" && tries < 20) {
          tries++; setTimeout(poll, 2500);
        }
      } catch (e) {
        if (!stop) setOrder(null);
      }
    };
    poll();
    return () => { stop = true; };
  }, [id]);

  if (order === undefined) {
    return <CenterNote m={m} title="Проверяем статус заказа…" text="Секунду." />;
  }
  if (order === null) {
    return (
      <ResultScreen kicker="Заказ" title="Заказ не найден" text="Проверьте ссылку из письма или вернитесь в каталог." setRoute={setRoute} />
    );
  }

  if (order.kind === "payment") {
    if (order.status === "paid") {
      return <ResultScreen kicker="Оплата получена" title="Спасибо за заказ!" publicId={order.publicId}
        text="Оплата прошла успешно. Мы собираем вашу посылку и свяжемся по доставке." setRoute={setRoute} />;
    }
    if (order.status === "failed") {
      return <ResultScreen kicker="Оплата" title="Оплата не прошла" publicId={order.publicId} danger
        text="Платёж не был завершён. Можно попробовать ещё раз из корзины." setRoute={setRoute} primaryLabel="В корзину" primaryRoute="cart" />;
    }
    return <CenterNote m={m} title="Ожидаем подтверждение оплаты…" text={`Заказ ${order.publicId}. Это занимает несколько секунд.`} />;
  }

  // Заявка
  return <ResultScreen kicker="Заявка" title="Заявка принята" publicId={order.publicId}
    text="Мы свяжемся с вами в течение дня." setRoute={setRoute} />;
}

function CenterNote({ m, title, text }) {
  return (
    <div style={{ paddingTop: m ? 120 : 180, paddingBottom: m ? 100 : 180, textAlign: "center" }}>
      <Wrap style={{ maxWidth: 560 }}>
        <div style={{ fontFamily: "'Cormorant Garamond', serif", fontStyle: "italic", fontSize: 30, marginBottom: 12 }}>{title}</div>
        <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 14, color: "rgba(0,0,0,0.6)" }}>{text}</div>
      </Wrap>
    </div>
  );
}

function ResultScreen({ kicker, title, text, publicId, setRoute, danger, primaryLabel, primaryRoute }) {
  const m = useIsMobile();
  return (
    <div style={{ paddingTop: m ? 110 : 170, paddingBottom: m ? 100 : 170 }}>
      <Wrap style={{ maxWidth: 640, textAlign: "center" }}>
        <div style={{
          width: 64, height: 64, borderRadius: "50%", margin: "0 auto 26px",
          display: "flex", alignItems: "center", justifyContent: "center",
          border: `1px solid ${danger ? palette.oxblood : "var(--ink)"}`,
          color: danger ? palette.oxblood : "var(--ink)", fontSize: 28,
        }}>{danger ? "!" : "✓"}</div>
        <Eyebrow>{kicker}</Eyebrow>
        <h1 style={{ fontFamily: "'Cormorant Garamond', serif", fontWeight: 300, fontStyle: "italic", fontSize: "clamp(32px,4vw,48px)", margin: "12px 0 16px" }}>{title}</h1>
        {publicId && (
          <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 13, letterSpacing: "0.1em", color: "rgba(0,0,0,0.6)", marginBottom: 16 }}>
            Номер: {publicId}
          </div>
        )}
        <p style={{ fontFamily: "'Manrope', sans-serif", fontSize: 15, lineHeight: 1.7, color: "rgba(0,0,0,0.65)", maxWidth: 460, margin: "0 auto 30px" }}>{text}</p>
        <div style={{ display: "flex", gap: 14, justifyContent: "center", flexWrap: "wrap" }}>
          <SolidBtn onClick={() => setRoute(primaryRoute || "home")}>{primaryLabel || "На главную"}</SolidBtn>
          <GhostBtn2 onClick={() => setRoute("bags", "all")}>В каталог</GhostBtn2>
        </div>
      </Wrap>
    </div>
  );
}

/* =========================================================
   ИЗБРАННОЕ
   ========================================================= */
function FavoritesPage({ setRoute }) {
  const { favItems } = useCart();
  const m = useIsMobile();

  if (favItems.length === 0) {
    return (
      <div style={{ paddingTop: m ? 96 : 150, paddingBottom: m ? 80 : 140 }}>
        <Wrap>
          <PageTitle kicker="Избранное" title="Здесь пока пусто" />
          <p style={{ fontFamily: "'Manrope', sans-serif", fontSize: 15, color: "rgba(0,0,0,0.6)", maxWidth: 440, lineHeight: 1.7 }}>
            Отмечайте понравившиеся модели сердечком - они появятся здесь.
          </p>
          <div style={{ marginTop: 28, display: "flex", gap: 14, flexWrap: "wrap" }}>
            <SolidBtn onClick={() => setRoute("bags", "all")}>Школьные сумки</SolidBtn>
            <GhostBtn2 onClick={() => setRoute("trunks")}>Чемоданы и интерьер</GhostBtn2>
          </div>
        </Wrap>
      </div>
    );
  }

  return (
    <div style={{ paddingTop: m ? 96 : 150, paddingBottom: m ? 80 : 140 }}>
      <Wrap>
        <PageTitle kicker="Избранное" title="Понравившиеся модели" />
        <div style={{ display: "grid", gridTemplateColumns: m ? "1fr 1fr" : "repeat(3, 1fr)", gap: m ? 18 : 32, rowGap: m ? 32 : 48 }}>
          {favItems.map(item => (
            <div key={item.key}>
              <div style={{ position: "relative", overflow: "hidden", background: "var(--cream)", border: "1px solid rgba(0,0,0,0.08)", padding: 16 }}>
                <div onClick={() => openProduct(item, setRoute)} style={{ cursor: "pointer" }}>
                  <PlateFull item={item} />
                </div>
                <FavHeart keyId={item.key} style={{ position: "absolute", top: 12, right: 12 }} />
              </div>
              <div style={{ paddingTop: 12 }}>
                <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.5)" }}>
                  {item.kind || item.category}
                </div>
                <div onClick={() => openProduct(item, setRoute)} style={{ fontFamily: "'Cormorant Garamond', serif", fontStyle: "italic", fontSize: 20, marginTop: 4, cursor: "pointer" }}>{item.name}</div>
                <div style={{ fontFamily: "'Manrope', sans-serif", fontSize: 13, color: "var(--ink)", marginTop: 6 }}>{item.price}</div>
                <div style={{ marginTop: 12 }}>
                  <AddToCartButton keyId={item.key} full />
                </div>
              </div>
            </div>
          ))}
        </div>
      </Wrap>
    </div>
  );
}

function PlateFull({ item }) {
  const tones = item.tones || [palette.cognac, palette.brass, palette.bone];
  const P = { bag: BagPlate, trunk: TrunkPlate, round: RoundPlate, shoecabinet: ShoeCabinetPlate, case: CasePlate }[item.plate] || CasePlate;
  return <P id={"fav-" + item.key} tones={tones} ratio="4/5" />;
}

Object.assign(window, { CartPage, CheckoutRequestPage, CheckoutPaymentPage, OrderStatusPage, FavoritesPage });
