// THE EPIZODE — checkout (Чекаут).

// «Попросить оплатить» — ссылка на чекаут с составом корзины (?pay=), мини-меню поделиться/скопировать.
function EpzAskToPay({ T }) {
  const F = EPZ_FONTS;
  useEpzLang();
  const [open, setOpen] = React.useState(false);
  const url = () => {
    try {
      const cart = epzReadStore(EPZ_CART_KEY).map((l) => ({ id: l.id, variant: l.variant || null, size: l.size || null, qty: l.qty || 1 }));
      return location.origin + location.pathname + '?pay=' + encodeURIComponent(JSON.stringify(cart)) + '&gift=1';
    } catch (e) { return location.href; }
  };
  const copy = () => {
    const u = url();
    const done = () => epzToast(epzT('ссылка на оплату скопирована'));
    try { navigator.clipboard.writeText(u).then(done, () => window.prompt(epzT('Скопируйте ссылку'), u)); }
    catch (e) { window.prompt(epzT('Скопируйте ссылку'), u); }
    setOpen(false);
  };
  const share = () => {
    const u = url();
    if (navigator.share) { navigator.share({ title: 'THE EPIZODE', url: u }).catch(() => {}); setOpen(false); }
    else copy();
  };
  const rowS = { display: 'block', width: '100%', textAlign: 'left', background: 'transparent', border: 0, color: 'inherit', cursor: 'pointer', padding: '11px 15px', fontFamily: F.mono, fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase' };
  return (
    <div style={{ position: 'relative', marginTop: 10 }}>
      <button type="button" onClick={() => setOpen((v) => !v)} style={{ width: '100%', background: 'transparent', border: `1px solid ${T.accent}`, borderRadius: 40, cursor: 'pointer', color: T.accentInk, padding: '17px 24px', fontFamily: F.mono, fontSize: 12, letterSpacing: '0.18em', textTransform: 'uppercase', transition: 'background 0.2s' }}>{epzT('намекнуть на подарок')}</button>
      {open &&
      <div style={{ position: 'absolute', left: '50%', transform: 'translateX(-50%)', top: 'calc(100% + 8px)', zIndex: 40, background: T.bg, border: `1px solid ${T.border}`, boxShadow: '0 12px 30px rgba(20,17,14,0.18)', minWidth: 210 }}>
        <button type="button" onClick={share} style={{ ...rowS, borderBottom: `1px solid ${T.border}` }}>{epzT('поделиться')}</button>
        <button type="button" onClick={copy} style={rowS}>{epzT('скопировать ссылку')}</button>
      </div>}
    </div>
  );
}
// Conversion-focused, low-friction layout (ref: Nude Project / Idol):
// LEFT  — express pay → contact → delivery → shipping → payment
// RIGHT — sticky order summary (burgundy panel) with promo code + totals.

function EpzCheckoutPage() {
  const F = EPZ_FONTS;
  useEpzLang();

  // Гидратация по ссылке «попросить оплатить»: ?pay=[{id,variant,size,qty}]
  React.useEffect(() => {
    try {
      const p = new URLSearchParams(location.search).get('pay');
      if (!p) return;
      if (sessionStorage.getItem('epz-pay-hydrated') === p) return;
      const lines = JSON.parse(p);
      if (!Array.isArray(lines)) return;
      const cart = epzReadStore(EPZ_CART_KEY);
      lines.forEach((l) => {
        if (!l || !l.id) return;
        const ex = cart.find((c) => c.id === l.id && (c.variant || null) === (l.variant || null) && (c.size || null) === (l.size || null));
        if (ex) ex.qty = Math.max(ex.qty || 1, l.qty || 1);
        else cart.push({ id: l.id, variant: l.variant || null, size: l.size || null, qty: l.qty || 1 });
      });
      epzWriteStore(EPZ_CART_KEY, cart);
      sessionStorage.setItem('epz-pay-hydrated', p);
    } catch (e) {}
  }, []);

  // Подарочный чекаут: даритель только платит — адрес и доставку уточняем у получателя после оплаты
  const isGift = (() => {
    try { return new URLSearchParams(location.search).get('gift') === '1'; } catch (e) { return false; }
  })();
  const [theme, setTheme, T] = useEpzTheme();
  const store = useEpzStore();

  // Live cart; fall back to a demo line so preview is never blank.
  const cart = store.cart.length ? store.cart : [{ id: '003-1', variant: null, size: 'M', qty: 1 }];
  const lines = cart.map((c) => {
    const a = epzArticle(c.id);
    if (!a) return null;
    const ep = epzEpisode(a.episode);
    const v = a.variants && c.variant ? a.variants.find((x) => x.key === c.variant) : null;
    const price = v ? v.price : a.price;
    return { ...c, a, ep, v, price, lineTotal: price * (c.qty || 1) };
  }).filter(Boolean);
  const grouped = epzGroupCart(cart);
  const subtotal = grouped.subtotal;
  const bundleSavings = grouped.savings;
  const count = cart.reduce((s, c) => s + (c.qty || 1), 0);
  const fmt = epzFmt;

  // Summary panel — neutral, on page background with a hairline divider (no loud fill).
  const S = { bg: 'transparent', ink: T.text, line: T.border, dim: T.textDim || 'rgba(20,17,14,0.5)' };

  // Form state
  const [email, setEmail] = React.useState('');
  const [phone, setPhone] = React.useState('');
  const [firstName, setFirstName] = React.useState('');
  const [lastName, setLastName] = React.useState('');
  const [city, setCity] = React.useState('');
  const [address, setAddress] = React.useState('');
  const [zip, setZip] = React.useState('');
  const [apartment, setApartment] = React.useState('');
  const [country, setCountry] = React.useState('Россия');
  // Soft geo guess by browser language (real IP geo is wired on the host).
  React.useEffect(() => {
    try {
      const lang = (navigator.language || '').toLowerCase();
      if (!/^ru|^be|^kk|^uk/.test(lang)) setCountry('Европа');
    } catch (e) {}
  }, []);
  // Согласие на рассылку: по умолчанию СНЯТО (согласие должно быть явным), за отметку — −10% на заказ.
  const [subscribe, setSubscribe] = React.useState(false);
  const [saveInfo, setSaveInfo] = React.useState(true);
  const [openBundles, setOpenBundles] = React.useState({});
  const [hintOpen, setHintOpen] = React.useState(false);
  const [delivery, setDelivery] = React.useState('cdek');
  const [payment, setPayment] = React.useState('sbp');
  const [agree, setAgree] = React.useState(true);
  const [promo, setPromo] = React.useState('');
  const [promoApplied, setPromoApplied] = React.useState(false);
  const [restorable, setRestorable] = React.useState(null);
  const itemsScrollRef = React.useRef(null);
  const [itemsAtBottom, setItemsAtBottom] = React.useState(false);

  const deliveryOptions = {
    cdek: { label: epzT('СДЭК — пункт выдачи'), sublabel: epzT('3–7 дней по России'), cost: 0 },
    cdek_door: { label: epzT('СДЭК — курьер до двери'), sublabel: epzT('3–7 дней'), cost: 450 },
    pickup: { label: epzT('Самовывоз, Москва'), sublabel: epzT('по записи'), cost: 0 },
    world: { label: epzT('Международная доставка'), sublabel: epzT('7–14 дней'), cost: 3200 },
  };
  const shipping = deliveryOptions[delivery].cost;
  const isIntl = !['Россия', 'Беларусь', 'Казахстан'].includes(country);
  // Switch payment method when crossing the RU/intl boundary.
  React.useEffect(() => {
    if (isIntl && ['sbp', 'yandex'].includes(payment)) setPayment('card');
    if (!isIntl && ['paypal'].includes(payment)) setPayment('card');
  }, [isIntl]);
  const promoDiscount = promoApplied ? Math.round(subtotal * 0.1) : 0;
  // −10% за согласие на рассылку; с промокодом не суммируется (действует одна скидка).
  const subscribeDiscount = subscribe && !promoApplied ? Math.round(subtotal * 0.1) : 0;
  const total = subtotal + shipping - promoDiscount - subscribeDiscount;

  const [submitted, setSubmitted] = React.useState(false);
  const [orderNumber] = React.useState(() => 'EPZ-' + Math.floor(100000 + Math.random() * 900000));

  const [subscribeErr, setSubscribeErr] = React.useState(false);
  function handleSubmit(e) {
    e.preventDefault();
    if (!agree) return;
    if (email && !subscribe) { // указан e-mail → нужно согласие на письма: подсвечиваем и скроллим к галочке
      setSubscribeErr(true);
      const el = document.getElementById('subscribe-consent');
      if (el) {
        const top = el.getBoundingClientRect().top + window.pageYOffset - 140;
        window.scrollTo({ top, behavior: 'smooth' });
      }
      return;
    }
    // Фиксируем согласие на рассылку вместе с заказом (заберётся бэкендом вместе с заказом).
    if (subscribe && email) {
      try {
        const subs = JSON.parse(localStorage.getItem('epz-subscribers') || '[]');
        if (!subs.some((s) => s.email === email)) {
          subs.push({ email, order: orderNumber, date: new Date().toISOString(), consent: 'marketing' });
          localStorage.setItem('epz-subscribers', JSON.stringify(subs));
        }
      } catch (err) {}
    }
    setSubmitted(true);
    window.scrollTo(0, 0);
    setTimeout(() => window.scrollTo(0, 0), 50);
  }
  function applyPromo() {
    if (promo.trim()) setPromoApplied(true);
  }
  const rememberLine = (id, variant, size) => {
    const a = epzArticle(id);
    const title = (a && a.variantNames && variant && a.variantNames[variant]) || (a && (a.short || a.title)) || '';
    setRestorable({ single: true, title, parts: [{ id, variant: variant || null, size, qty: 1 }] });
  };
  const setQty = (id, variant, size, delta) => {
    const cur = store.cart.find((c) => c.id === id && (c.variant || null) === (variant || null) && c.size === size);
    if (delta < 0 && cur && (cur.qty || 1) <= 1) rememberLine(id, variant, size);
    const next = store.cart.map((c) => (c.id === id && (c.variant || null) === (variant || null) && c.size === size) ? { ...c, qty: Math.max(0, (c.qty || 1) + delta) } : c).filter((c) => c.qty > 0);
    store.setCart(next);
  };
  const removeIdxs = (idxs) => store.setCart(store.cart.filter((c) => !idxs.includes(store.cart.indexOf(c))));
  const removeLine = (id, variant, size) => { rememberLine(id, variant, size); store.setCart(store.cart.filter((c) => !(c.id === id && (c.variant || null) === (variant || null) && c.size === size))); };
  const removeLineRaw = (id, variant, size) => store.setCart(store.cart.filter((c) => !(c.id === id && (c.variant || null) === (variant || null) && c.size === size)));
  const setQtyRaw = (id, variant, size, delta) => store.setCart(store.cart.map((c) => (c.id === id && (c.variant || null) === (variant || null) && c.size === size) ? { ...c, qty: Math.max(0, (c.qty || 1) + delta) } : c).filter((c) => c.qty > 0));
  const breakPart = (p, title, mode) => {
    setRestorable({ title, parts: [{ id: p.line.id, variant: p.line.variant || null, size: p.line.size, qty: 1 }] });
    if (mode === 'remove') removeLineRaw(p.line.id, p.line.variant, p.line.size);
    else setQtyRaw(p.line.id, p.line.variant, p.line.size, -1);
  };
  const removeBundle = (r) => {
    setRestorable({ title: r.title, parts: r.parts.map((p) => ({ id: p.line.id, variant: p.line.variant || null, size: p.line.size, qty: p.consumed })) });
    removeIdxs(r.parts.map((p) => p.line.idx));
  };
  const restoreSet = () => {
    if (!restorable) return;
    restorable.parts.forEach((p) => store.addToCart(p.id, { variant: p.variant, size: p.size, qty: p.qty || 1 }));
    setRestorable(null);
  };
  React.useEffect(() => {
    if (!restorable) return;
    if (restorable.single) {
      const p = restorable.parts[0];
      if (store.cart.some((c) => c.id === p.id && (c.variant || null) === (p.variant || null) && c.size === p.size)) setRestorable(null);
    } else if (grouped.rows.some((r) => r.kind === 'bundle' && epzT(r.title) === epzT(restorable.title))) setRestorable(null);
  }, [store.cart]);
  const setBundleQty = (idxs, delta) => {
    const next = store.cart.map((c, i) => idxs.includes(i) ? { ...c, qty: Math.max(0, (c.qty || 1) + delta) } : c).filter((c) => c.qty > 0);
    store.setCart(next);
  };
  const grpRows = grouped.rows;

  if (submitted) {
    return (
      <div style={{ width: '100%', minHeight: '100vh', background: T.bg, color: T.text, fontFamily: F.body, WebkitFontSmoothing: 'antialiased', transition: 'background 0.3s ease, color 0.3s ease' }}>
        <EpzHeader theme={theme} setTheme={setTheme} T={T} current="episodes" cartCount={0} />
        <CheckoutSuccess T={T} email={email} firstName={firstName} orderNumber={orderNumber} total={total} fmt={fmt} delivery={deliveryOptions[delivery]} isGift={isGift} />
        <EpzFooter T={T} />
      </div>
    );
  }

  const fieldStyle = {
    width: '100%', background: 'transparent', color: 'inherit',
    border: `1px solid ${T.border}`, outline: 'none', padding: '15px 16px',
    fontFamily: F.body, fontSize: 15, letterSpacing: 0,
  };

  return (
    <div style={{ width: '100%', minHeight: '100vh', background: T.bg, color: T.text, fontFamily: F.body, fontSize: 14, lineHeight: 1.5, WebkitFontSmoothing: 'antialiased', transition: 'background 0.3s ease, color 0.3s ease' }}>
      <style>{`
        .ch-input { width:100%; background:transparent; color:inherit; border:1px solid ${T.border}; border-radius:10px; outline:none; padding:13px 15px; font-family:${F.body}; font-size:15px; transition:border-color .2s; }
        .ch-input:focus { border-color:${T.accent}; }
        .ch-input::placeholder { color:inherit; opacity:.45; }
        .ch-card { cursor:pointer; transition:border-color .2s, background .2s; }
        .ch-card:hover { border-color:${T.accent}; }
        .ch-card-active { border-color:${T.accent} !important; }
        .ch-express:hover { transform:translateY(-1px); }
        .ch-express { transition:transform .15s, box-shadow .15s; }
        @media (max-width: 940px) {
          .ch-grid { grid-template-columns: 1fr !important; }
          .ch-summary { position: static !important; }
          .ch-form { border-right: none !important; }
        }
      `}</style>

      {/* logo bar — логотип слева, крупно (вариант 5) */}
      <div style={{ padding: '26px 44px', borderBottom: `1px solid ${T.border}` }}>
        <a href="/" aria-label="THE EPIZODE" style={{ display: 'block', height: 30, width: 230, background: T.text, WebkitMaskImage: 'url(/assets/logo-epizode.svg)', maskImage: 'url(/assets/logo-epizode.svg)', WebkitMaskRepeat: 'no-repeat', maskRepeat: 'no-repeat', WebkitMaskPosition: 'left center', maskPosition: 'left center', WebkitMaskSize: 'contain', maskSize: 'contain' }} />
      </div>

      {isGift ? (
      /* ── ПОДАРОЧНЫЙ ЧЕКАУТ — открытка-паспарту, максимально простой ── */
      <div style={{ background: T.bgFeatured || '#F2E9D9', padding: 'clamp(20px, 4vw, 40px) clamp(16px, 3vw, 28px)' }}>
        <form onSubmit={handleSubmit} style={{ position: 'relative', maxWidth: 812, margin: '0 auto', border: `1px solid ${T.accent}`, background: T.bg, padding: 'clamp(30px, 5vw, 44px) clamp(20px, 4vw, 40px) clamp(26px, 4vw, 36px)', textAlign: 'center', boxSizing: 'border-box' }}>
          <span style={{ position: 'absolute', top: -20, left: '50%', transform: 'translateX(-50%)', width: 40, height: 40, borderRadius: 40, background: T.accent, color: T.accentText, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', border: `5px solid ${T.bgFeatured || '#F2E9D9'}` }}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"><rect x="3.5" y="8" width="17" height="4" /><rect x="5" y="12" width="14" height="8.5" /><path d="M12 8v12.5M12 8c-4 0-5.5-4.5-2.5-4.5C11.5 3.5 12 8 12 8zm0 0c4 0 5.5-4.5 2.5-4.5C12.5 3.5 12 8 12 8z" /></svg>
          </span>
          <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, marginTop: 4, fontFamily: F.mono, fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: T.accentInk }}>
            <span className="epz-rec-dot" style={{ width: 6, height: 6, borderRadius: 6, background: T.accent, display: 'inline-block' }} />
            {epzT('вы дарите')}
          </div>
          {(() => {
            const giftLines = store.cart.map((l) => {
              const a = epzArticle(l.id); if (!a) return null;
              const v = a.variants && l.variant ? a.variants.find((x) => x.key === l.variant) : null;
              return {
                title: (a.variantNames && l.variant && a.variantNames[l.variant]) || a.short || a.title,
                img: (l.variant && typeof epzVariantImage === 'function' && epzVariantImage(l.id, l.variant)) || epzArticleImage(a),
                size: l.size, qty: l.qty || 1, price: (v ? v.price : a.price) || 0,
              };
            }).filter(Boolean);
            return (<>
              {giftLines.length === 1 &&
              <h1 style={{ fontFamily: F.display, fontSize: 'clamp(28px, 4.4vw, 38px)', fontWeight: 400, lineHeight: 1.05, margin: '10px 0 0', letterSpacing: '-0.01em' }}>{epzT(giftLines[0].title)}</h1>}
              {giftLines.length === 1 ? (
              <div style={{ marginTop: 18, display: 'flex', flexDirection: 'column', gap: 14, alignItems: 'center' }}>
                {giftLines.map((l, i) => (
                  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 14, textAlign: 'left' }}>
                    <div style={{ width: 88, height: 110, flexShrink: 0, backgroundColor: '#fff', border: `1px solid ${T.border}`, backgroundImage: l.img ? `url(${l.img})` : 'none', backgroundSize: 'contain', backgroundRepeat: 'no-repeat', backgroundPosition: 'center' }} />
                    <div>
                      <div style={{ marginTop: 0, fontFamily: F.mono, fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase', opacity: 0.6 }}>{l.size || epzT('размер укажет получатель')}{l.qty > 1 ? ` · ×${l.qty}` : ''}</div>
                      <div style={{ marginTop: 6, fontFamily: F.display, fontSize: 21, lineHeight: 1 }}>{fmt(l.price * l.qty)}</div>
                    </div>
                  </div>
                ))}
              </div>
              ) : (
              <div style={{ marginTop: 16, maxWidth: 470, marginLeft: 'auto', marginRight: 'auto', textAlign: 'left' }}>
                {giftLines.map((l, i) => (
                  <div key={i} style={{ display: 'grid', gridTemplateColumns: '44px 1fr auto', gap: 12, alignItems: 'center', padding: '9px 0', borderBottom: `1px solid ${T.border}` }}>
                    <div style={{ width: 44, height: 56, backgroundColor: '#fff', border: `1px solid ${T.border}`, backgroundImage: l.img ? `url(${l.img})` : 'none', backgroundSize: 'contain', backgroundRepeat: 'no-repeat', backgroundPosition: 'center' }} />
                    <div>
                      <div style={{ fontFamily: F.display, fontSize: 16, lineHeight: 1.1 }}>{epzT(l.title)}</div>
                      <div style={{ marginTop: 3, fontFamily: F.mono, fontSize: 8, letterSpacing: '0.16em', textTransform: 'uppercase', opacity: 0.55 }}>{l.size || epzT('размер укажет получатель')}{l.qty > 1 ? ` · ×${l.qty}` : ''}</div>
                    </div>
                    <div style={{ fontFamily: F.display, fontSize: 16 }}>{fmt(l.price * l.qty)}</div>
                  </div>
                ))}
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', paddingTop: 12, marginTop: 2, flexDirection: 'column', gap: 6 }}>
                  {(() => {
                    const linesSum = giftLines.reduce((s, l) => s + l.price * l.qty, 0);
                    const diff = linesSum - subtotal;
                    return diff > 0 ? (
                      <div style={{ width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                        <span style={{ fontFamily: F.mono, fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase', color: T.accentInk }}>{epzT('выгода комплектом')}</span>
                        <span style={{ fontFamily: F.display, fontSize: 16, color: T.accentInk }}>−{fmt(diff)}</span>
                      </div>
                    ) : null;
                  })()}
                  <div style={{ width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                    <span style={{ fontFamily: F.mono, fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', opacity: 0.55 }}>{epzT('итого')}</span>
                    <span style={{ fontFamily: F.display, fontSize: 24 }}>{fmt(subtotal)}</span>
                  </div>
                </div>
              </div>
              )}
            </>);
          })()}
          <div style={{ maxWidth: 470, margin: '0 auto' }}>
          <div style={{ marginTop: 20, textAlign: 'left', background: T.bgFeatured || '#FAF6EE', border: `1px solid ${T.accent}`, padding: '13px 16px', display: 'flex', gap: 10, alignItems: 'flex-start' }}>
            <span style={{ color: T.accentInk, flexShrink: 0 }}>✦</span>
            <span style={{ fontFamily: F.body, fontSize: 13, lineHeight: 1.55, opacity: 0.85 }}>{epzT('Вам намекнули на подарок. Адрес и удобный способ доставки мы уточним у получателя сами после оплаты')}</span>
          </div>
          <input className="ch-input" type="email" placeholder={epzT('Email — пришлём чек')} value={email} onChange={(e) => setEmail(e.target.value)} required style={{ marginTop: 12 }} />
          <input className="ch-input" placeholder={epzT('Ваше имя — подпишем открытку (необязательно)')} value={firstName} onChange={(e) => setFirstName(e.target.value)} style={{ marginTop: 8 }} />
          <div style={{ marginTop: 12, display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
            {[['sbp', 'СБП'], ['installments', 'Долями'], ['yandex', 'Yandex Pay'], ['card', 'Карта']].map(([key, label]) => {
              const active = payment === key;
              return (
                <label key={key} className="ch-card" style={{ border: `1.5px solid ${active ? T.accent : T.border}`, borderRadius: 10, padding: '11px 6px', textAlign: 'center', fontFamily: F.body, fontSize: 12.5, fontWeight: 600, color: active ? T.accentInk : T.text, cursor: 'pointer' }}>
                  <input type="radio" name="gift-pay" checked={active} onChange={() => setPayment(key)} style={{ position: 'absolute', opacity: 0 }} />
                  {epzT(label)}
                </label>
              );
            })}
          </div>
          <button type="submit" disabled={!agree} style={{ marginTop: 16, width: '100%', background: agree ? T.btnPrimary : T.border, color: agree ? T.btnPrimaryFg : T.textDim, border: 0, borderRadius: 40, padding: '18px 24px', fontFamily: F.mono, fontSize: 12, letterSpacing: '0.18em', textTransform: 'uppercase', cursor: agree ? 'pointer' : 'not-allowed' }}>
            {epzT('Оплатить')}
          </button>
          <div style={{ marginTop: 12, fontFamily: F.body, fontSize: 12, lineHeight: 1.6, opacity: 0.55 }}>{epzT('Получателю ничего платить не нужно')}</div>
          </div>
        </form>
      </div>
      ) : (
      <form onSubmit={handleSubmit} className="ch-grid" style={{ display: 'grid', gridTemplateColumns: '1.15fr 1fr', alignItems: 'start' }}>
        {/* ── LEFT: express + delivery + recipient + payment ── */}
        <div className="ch-form" style={{ padding: '24px 44px 80px' }}>
          <div style={{ maxWidth: 460, margin: '0 auto' }}>

          {/* Express — one-click via Yandex (RU) / PayPal (intl) */}
          <div>
            {isIntl ? (
              <button type="button" onClick={() => setPayment('paypal')} className="ch-express" style={{ width: '100%', height: 60, background: T.bgFeatured, border: `1px solid ${T.accent}`, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12, color: T.text }}>
                <PayMark name="paypal" label="PayPal" color={T.text} />
                <span style={{ fontFamily: F.body, fontSize: 15 }}>{epzT('Заказать в один клик')}</span>
              </button>
            ) : (
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>
                <span style={{ fontFamily: F.mono, fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase', color: T.text, opacity: 0.45 }}>{epzT('Заказать в один клик')}</span>
                <button type="button" onClick={(e) => handleSubmit(e)} className="ch-express" style={{ height: 48, padding: '0 30px', background: '#fff', border: '1px solid rgba(20,17,14,0.16)', borderRadius: 40, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
                  <img src="/assets/pay/yandex-pay-full.svg" alt="Yandex Pay" style={{ height: 24, display: 'block' }} />
                </button>
              </div>
            )}
            <div style={{ display: 'flex', alignItems: 'center', gap: 16, margin: '24px 0 4px', opacity: 0.5 }}>
              <span style={{ flex: 1, height: 1, background: T.border }} />
              <span style={{ fontFamily: F.mono, fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase' }}>{epzT('или оформить вручную')}</span>
              <span style={{ flex: 1, height: 1, background: T.border }} />
            </div>
          </div>

          {/* email — нулевой блок перед шагами, поле как в остальном чекауте */}
          {!isGift &&
          <div style={{ margin: '26px 0 40px' }}>
            <div style={{ fontFamily: F.mono, fontSize: 9.5, letterSpacing: '0.18em', textTransform: 'uppercase', color: T.accentInk, marginBottom: 10 }}>{epzT('первым 300 клиентам −10% на первый заказ')}</div>
            <input className="ch-input" type="email" required value={email} onChange={(e) => setEmail(e.target.value)} placeholder="вашa@почта.ru" />
            <label id="subscribe-consent" style={{ marginTop: 12, display: 'flex', alignItems: 'flex-start', gap: 10, cursor: 'pointer', maxWidth: 400, outline: subscribeErr && !subscribe ? `1.5px solid ${T.accent}` : 'none', outlineOffset: 6 }}>
              <input type="checkbox" checked={subscribe} onChange={(e) => { setSubscribe(e.target.checked); if (e.target.checked) setSubscribeErr(false); }} style={{ position: 'absolute', opacity: 0, width: 13, height: 13 }} />
              <span aria-hidden="true" style={{ width: 13, height: 13, marginTop: 2, flexShrink: 0, borderRadius: 3, border: `1.5px solid ${subscribe ? T.accent : T.border}`, background: subscribe ? T.accent : 'transparent', color: T.accentText, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 9, lineHeight: 1, transition: 'background 0.15s, border-color 0.15s' }}>{subscribe ? '✓' : ''}</span>
              <span style={{ fontFamily: F.body, fontSize: 11.5, opacity: 0.65, lineHeight: 1.5 }}>
                {epzT('Согласен получать письма от THE EPIZODE и принимаю')}{' '}
                <a href="/delivery/" style={{ color: 'inherit', textDecorationStyle: 'dotted' }}>{epzT('политику конфиденциальности')}</a>
              </span>
            </label>
            {subscribeErr && !subscribe &&
            <div style={{ marginTop: 10, fontFamily: F.body, fontSize: 11.5, color: T.accentInk }}>{epzT('Отметьте согласие на письма — или очистите поле e-mail')}</div>
            }
          </div>}

          {/* Контакты — в подарочном режиме первым шагом */}
          {isGift &&
          <Step n="01" title={epzT('Контакты')} T={T}>
            <input className="ch-input" type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} required />
            <div style={{ marginTop: 13, fontFamily: F.mono, fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', color: T.accentInk }}>{epzT('−10% на первый заказ')}</div>
            <label style={{ marginTop: 9, display: 'flex', alignItems: 'flex-start', gap: 10, cursor: 'pointer', maxWidth: 400 }}>
              <input type="checkbox" checked={subscribe} onChange={(e) => setSubscribe(e.target.checked)} style={{ position: 'absolute', opacity: 0, width: 13, height: 13 }} />
              <span aria-hidden="true" style={{ width: 13, height: 13, marginTop: 2, flexShrink: 0, borderRadius: 3, border: `1.5px solid ${subscribe ? T.accent : T.border}`, background: subscribe ? T.accent : 'transparent', color: T.accentText, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 9, lineHeight: 1, transition: 'background 0.15s, border-color 0.15s' }}>{subscribe ? '✓' : ''}</span>
              <span style={{ fontFamily: F.body, fontSize: 11.5, opacity: 0.65, lineHeight: 1.5 }}>
                {epzT('Согласен получать письма от THE EPIZODE и принимаю')}{' '}
                <a href="/delivery/" style={{ color: 'inherit', textDecorationStyle: 'dotted' }}>{epzT('политику конфиденциальности')}</a>
              </span>
            </label>
          </Step>}

          {/* 02 — Доставка (адрес получателя) — в подарочном режиме скрыта */}
          {isGift &&
          <Step n="02" title={epzT('Подарок')} T={T}>
            <div style={{ background: T.bgFeatured || '#FAF6EE', border: `1px solid ${T.accent}`, padding: '16px 18px', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
              <span style={{ color: T.accentInk, fontSize: 15, lineHeight: 1.3, flexShrink: 0 }}>✦</span>
              <span style={{ fontFamily: F.body, fontSize: 13.5, lineHeight: 1.6, opacity: 0.8 }}>
                {epzT('Вам намекнули на подарок. Адрес и удобный способ доставки мы уточним у получателя сами после оплаты')}
              </span>
            </div>
            <input className="ch-input" placeholder={epzT('Ваше имя — подпишем открытку (необязательно)')} value={firstName} onChange={(e) => setFirstName(e.target.value)} style={{ marginTop: 10 }} />
          </Step>}

          {!isGift &&
          <Step n="01" title={(
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>
              {epzT('Доставка')}
              <span style={{ position: 'relative', display: 'inline-flex' }}>
                <button type="button" onClick={() => setHintOpen((v) => !v)} aria-label={epzT('Подробнее')} style={{ width: 18, height: 18, borderRadius: '50%', border: `1px solid ${T.accent}`, color: T.accentInk, background: 'transparent', cursor: 'pointer', fontFamily: F.mono, fontSize: 10, lineHeight: 1, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>i</button>
                {hintOpen &&
                <span style={{ position: 'absolute', top: '150%', left: -6, zIndex: 20, width: 290, display: 'flex', gap: 14, alignItems: 'flex-start', background: T.bgFeatured || '#FAF6EE', border: `1px solid ${T.accent}`, boxShadow: '0 18px 50px rgba(0,0,0,0.2)', borderRadius: 14, padding: '15px 18px', fontWeight: 400, letterSpacing: 0, textTransform: 'none' }}>
                  <span style={{ color: T.accentInk, fontSize: 14, lineHeight: 1.4, flexShrink: 0 }}>✦</span>
                  <span style={{ fontFamily: F.body, fontSize: 13, lineHeight: 1.55, opacity: 0.68 }}>{epzT('Заполните данные всего раз — а дальше мы всё запомним, и следующий заказ займёт меньше минут')}</span>
                  <span style={{ position: 'absolute', bottom: '100%', left: 16, width: 10, height: 10, background: T.bgFeatured || '#FAF6EE', borderLeft: `1px solid ${T.accent}`, borderTop: `1px solid ${T.accent}`, transform: 'translateY(50%) rotate(45deg)' }} />
                </span>
                }
              </span>
            </span>
          )} T={T}>
            <select className="ch-input" value={country} onChange={(e) => setCountry(e.target.value)} style={{ marginBottom: 8 }}>
              <optgroup label={epzT('Россия и СНГ')}>
                <option value="Россия">{epzT('Россия')}</option>
                <option value="Беларусь">{epzT('Беларусь')}</option>
                <option value="Казахстан">{epzT('Казахстан')}</option>
                <option value="Армения">{epzT('Армения')}</option>
                <option value="Грузия">{epzT('Грузия')}</option>
                <option value="Кыргызстан">{epzT('Кыргызстан')}</option>
                <option value="Узбекистан">{epzT('Узбекистан')}</option>
              </optgroup>
              <optgroup label={epzT('Европа')}>
                <option value="Европа (ЕС)">{epzT('Европа (ЕС)')}</option>
                <option value="Великобритания">{epzT('Великобритания')}</option>
                <option value="Швейцария">{epzT('Швейцария')}</option>
              </optgroup>
              <optgroup label={epzT('Америка')}>
                <option value="США">{epzT('США')}</option>
                <option value="Канада">{epzT('Канада')}</option>
              </optgroup>
              <optgroup label={epzT('Ближний Восток и Азия')}>
                <option value="ОАЭ">{epzT('ОАЭ')}</option>
                <option value="Израиль">{epzT('Израиль')}</option>
                <option value="Турция">{epzT('Турция')}</option>
              </optgroup>
              <option value="Другая">{epzT('Другая страна')}</option>
            </select>
            <div style={{ marginBottom: 10, fontFamily: F.mono, fontSize: 9, letterSpacing: '0.12em', textTransform: 'uppercase', opacity: 0.5 }}>{epzT('Доставляем в любую точку мира')}</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 8 }}>
              <input className="ch-input" placeholder={epzT('Имя')} value={firstName} onChange={(e) => setFirstName(e.target.value)} required />
              <input className="ch-input" placeholder={epzT('Фамилия')} value={lastName} onChange={(e) => setLastName(e.target.value)} required />
            </div>
            <input className="ch-input" placeholder={epzT('Адрес — улица, дом')} value={address} onChange={(e) => setAddress(e.target.value)} style={{ marginBottom: 8 }} required />
            <input className="ch-input" placeholder={epzT('Квартира, офис и т.д. (необязательно)')} value={apartment} onChange={(e) => setApartment(e.target.value)} style={{ marginBottom: 8 }} />
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 8 }}>
              <input className="ch-input" placeholder={epzT('Индекс')} value={zip} onChange={(e) => setZip(e.target.value)} />
              <input className="ch-input" placeholder={epzT('Город')} value={city} onChange={(e) => setCity(e.target.value)} required />
            </div>
            <input className="ch-input" type="tel" placeholder={epzT('Телефон')} value={phone} onChange={(e) => setPhone(e.target.value)} required />
            <label style={{ marginTop: 13, display: 'flex', alignItems: 'center', gap: 11, cursor: 'pointer' }}>
              <input type="checkbox" checked={saveInfo} onChange={(e) => setSaveInfo(e.target.checked)} style={{ position: 'absolute', opacity: 0, width: 17, height: 17 }} />
              <span aria-hidden="true" style={{ width: 17, height: 17, flexShrink: 0, borderRadius: 4, border: `1.5px solid ${saveInfo ? T.accent : T.border}`, background: saveInfo ? T.accent : 'transparent', color: T.accentText, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, lineHeight: 1, transition: 'background 0.15s, border-color 0.15s' }}>{saveInfo ? '✓' : ''}</span>
              <span style={{ fontSize: 13.5 }}>{epzT('Сохранить данные для следующего раза')}</span>
            </label>
          </Step>}

          {/* 02 — Способ доставки (рассчёт после заполнения данных) — в подарочном режиме скрыт */}
          {!isGift && (() => { const ready = firstName && lastName && address && city && phone; return (
          <Step n="02" title={epzT('Способ доставки')} T={T}>
            {!ready ? (
              <div style={{ fontFamily: F.body, fontSize: 13.5, lineHeight: 1.55, opacity: 0.5 }}>{epzT('Способ и стоимость доставки рассчитаются после заполнения данных получателя')}</div>
            ) : (
            <>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              {[['cdek', epzT('Пункт выдачи'), epzT('СДЭК · 3–7 дней')], ['cdek_door', epzT('Курьер до двери'), epzT('СДЭК · 3–7 дней')]].map(([key, label, sub]) => {
                const active = delivery === key;
                return (
                  <label key={key} className="ch-card" style={{ position: 'relative', display: 'block', padding: '16px 16px 18px', borderRadius: 10, border: `1.5px solid ${active ? T.accent : T.border}`, cursor: 'pointer' }}>
                    <input type="radio" name="delivery" checked={active} onChange={() => setDelivery(key)} style={{ position: 'absolute', opacity: 0 }} />
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <span style={{ fontFamily: F.body, fontWeight: 700, fontSize: 12, letterSpacing: '0.04em', color: '#1AB248' }}>СДЭК</span>
                    </div>
                    <div style={{ marginTop: 8, fontFamily: F.display, fontSize: 18, lineHeight: 1.05 }}>{label}</div>
                    <div style={{ marginTop: 8, fontFamily: F.mono, fontSize: 10, letterSpacing: '0.08em', opacity: 0.7 }}>{sub}</div>
                    <div style={{ marginTop: 4, fontFamily: F.mono, fontSize: 11 }}>{deliveryOptions[key].cost === 0 ? epzT('бесплатно') : fmt(deliveryOptions[key].cost)}</div>
                    <span style={{ position: 'absolute', top: 14, right: 14, width: 20, height: 20, borderRadius: '50%', border: `1.5px solid ${active ? T.accent : T.border}`, background: active ? T.accent : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', color: T.accentText, fontSize: 11 }}>{active ? '✓' : ''}</span>
                  </label>
                );
              })}
            </div>
            {delivery === 'cdek' &&
            <input className="ch-input" placeholder={epzT('Пункт выдачи — адрес или код')} style={{ marginTop: 10 }} />
            }
            </>
            )}
          </Step>
          ); })()}

          {/* Payment */}
          <Step n="03" title={epzT('Оплата')} T={T}>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {(isIntl ? [
                ['card', epzT('Картой онлайн'), epzT('Visa · Mastercard · Amex — через Stripe')],
                ['paypal', 'PayPal', epzT('оплата кошельком или картой')],
                ['installments', epzT('Klarna / в рассрочку'), epzT('3–4 платежа без переплаты')],
              ] : [
                ['sbp', epzT('СБП'), epzT('через банковское приложение')],
                ['installments', epzT('Оплата долями'), '4 × ' + fmt(Math.round(total / 4))],
                ['yandex', 'Yandex Pay', epzT('в один клик')],
                ['card', epzT('Картой онлайн'), 'Visa · Mastercard · Мир'],
              ]).map(([key, label, sub]) => (
                <label key={key} className={`ch-card ${payment === key ? 'ch-card-active' : ''}`} style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: 14, alignItems: 'center', padding: '15px 16px', borderRadius: 10, border: `1px solid ${payment === key ? T.accent : T.border}` }}>
                  <input type="radio" name="payment" checked={payment === key} onChange={() => setPayment(key)} style={{ position: 'absolute', opacity: 0 }} />
                  <span aria-hidden="true" style={{ width: 16, height: 16, borderRadius: '50%', border: `1.5px solid ${payment === key ? T.accent : T.border}`, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, transition: 'border-color 0.15s' }}>{payment === key && <span style={{ width: 8, height: 8, borderRadius: '50%', background: T.accent, display: 'inline-block' }}></span>}</span>
                  <div>
                    <div style={{ fontSize: 14 }}>{label}</div>
                    <div style={{ marginTop: 2, fontSize: 12.5, opacity: 0.6 }}>{sub}</div>
                  </div>
                </label>
              ))}
            </div>
            {payment === 'card' &&
            <div style={{ marginTop: 14 }}>
              <input className="ch-input" placeholder={epzT('Номер карты')} />
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0, marginTop: '-1px' }}>
                <input className="ch-input" placeholder={epzT('ММ / ГГ')} style={{ borderRight: 'none' }} />
                <input className="ch-input" placeholder="CVC" />
              </div>
              {isIntl && <div style={{ marginTop: 10, fontSize: 12.5, opacity: 0.6, lineHeight: 1.5 }}>{epzT('Безопасная оплата картой любой страны через Stripe. Сумма спишется в рублях по курсу банка.')}</div>}
            </div>
            }
            {payment === 'installments' &&
            <div style={{ marginTop: 14, border: `1px solid ${T.border}`, padding: 16 }}>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
                {[0, 1, 2, 3].map((i) => (
                  <div key={i} style={{ border: `1px solid ${T.border}`, padding: '10px 6px', textAlign: 'center' }}>
                    <div style={{ fontFamily: F.mono, fontSize: 9, letterSpacing: '0.12em', textTransform: 'uppercase', opacity: 0.55 }}>{i === 0 ? epzT('сегодня') : `+${i * 2} ${epzT('нед')}`}</div>
                    <div style={{ fontFamily: F.display, fontSize: 18, marginTop: 5 }}>{fmt(Math.round(total / 4))}</div>
                  </div>
                ))}
              </div>
            </div>
            }
            {/* pay — кнопка слева, внизу оплаты */}
            <button type="submit" style={{
              marginTop: 22, width: '100%', background: agree ? T.btnPrimary : T.border, color: agree ? T.btnPrimaryFg : T.textDim,
              border: 0, borderRadius: 40, padding: '19px 24px', fontFamily: F.mono, fontSize: 12, letterSpacing: '0.18em', textTransform: 'uppercase',
              cursor: agree ? 'pointer' : 'not-allowed', transition: 'background 0.3s, color 0.3s',
            }}>
              {isGift ? epzT('Оплатить подарок') : epzT('Оплатить')}
            </button>
            {!isGift && <EpzAskToPay T={T} />}
            <label style={{ display: 'flex', alignItems: 'flex-start', gap: 10, cursor: 'pointer', marginTop: 14 }}>
              <input type="checkbox" checked={agree} onChange={(e) => setAgree(e.target.checked)} style={{ position: 'absolute', opacity: 0, width: 16, height: 16 }} />
              <span aria-hidden="true" style={{ width: 16, height: 16, marginTop: 1, flexShrink: 0, borderRadius: 4, border: `1.5px solid ${agree ? T.accent : T.border}`, background: agree ? T.accent : 'transparent', color: T.accentText, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, lineHeight: 1, transition: 'background 0.15s, border-color 0.15s' }}>{agree ? '✓' : ''}</span>
              <span style={{ fontSize: 12, opacity: 0.7, lineHeight: 1.5 }}>
                {epzT('Соглашаюсь с')} <a href="/delivery/" style={{ color: 'inherit' }}>{epzT('обработкой данных')}</a> {epzT('и')} <a href="/delivery/" style={{ color: 'inherit' }}>{epzT('правилами возврата')}</a>
              </span>
            </label>
            <div style={{ marginTop: 20, paddingTop: 16, borderTop: `1px solid ${T.border}`, display: 'flex', flexWrap: 'wrap', gap: '6px 16px', fontFamily: F.mono, fontSize: 10, letterSpacing: '0.1em', textTransform: 'uppercase', opacity: 0.4 }}>
              <a href="/delivery/?tab=returns" style={{ color: 'inherit', textDecoration: 'underline', textUnderlineOffset: 3 }}>{epzT('Правила возврата')}</a>
              <a href="/delivery/" style={{ color: 'inherit', textDecoration: 'underline', textUnderlineOffset: 3 }}>{epzT('Политика конфиденциальности')}</a>
              <a href="/delivery/" style={{ color: 'inherit', textDecoration: 'underline', textUnderlineOffset: 3 }}>{epzT('Условия')}</a>
            </div>
          </Step>
        </div>
        </div>

        {/* ── RIGHT: summary panel (промокод · состав · итого) ── */}
        <aside className="ch-summary" style={{ position: 'sticky', top: 0, alignSelf: 'flex-start', background: T.bgAlt, color: T.text, padding: '24px 32px 36px', display: 'flex', flexDirection: 'column' }}>
          {/* promo */}
          <div style={{ order: 2, display: 'flex', gap: 0, marginBottom: 22, marginTop: 4 }}>
            <input value={promo} onChange={(e) => setPromo(e.target.value)} placeholder={epzT('Промокод закрытого клуба')}
              style={{ flex: 1, background: T.bg, color: T.text, border: `1px solid ${T.border}`, borderRight: 'none', outline: 'none', padding: '14px 15px', fontFamily: F.body, fontSize: 13 }} />
            <button type="button" onClick={applyPromo} style={{ background: T.bg, color: T.text, border: `1px solid ${T.border}`, padding: '0 20px', cursor: 'pointer', fontFamily: F.mono, fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase' }}>{epzT('применить')}</button>
          </div>

          {/* totals */}
          <div style={{ order: 3, display: 'flex', flexDirection: 'column', gap: 9, fontFamily: F.body, fontSize: 14 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ opacity: 0.6 }}>{count} {epzIsEN() ? (count === 1 ? 'item' : 'items') : plural(count, 'товар', 'товара', 'товаров')}</span><span>{fmt(subtotal + bundleSavings)}</span></div>
            {bundleSavings > 0 && <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ opacity: 0.6 }}>{epzT('Комплект')}</span><span>−{fmt(bundleSavings)}</span></div>}
            <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ opacity: 0.6 }}>{epzT('Доставка')}</span><span>{shipping === 0 ? epzT('бесплатно') : fmt(shipping)}</span></div>
            {promoApplied && <div style={{ display: 'flex', justifyContent: 'space-between', color: T.accentInk }}><span>{epzT('Промокод −10%')}</span><span>−{fmt(promoDiscount)}</span></div>}
            {subscribeDiscount > 0 && <div style={{ display: 'flex', justifyContent: 'space-between', color: T.accentInk }}><span>{epzT('−10% на первый заказ')}</span><span>−{fmt(subscribeDiscount)}</span></div>}
          </div>
          <div style={{ order: 3, marginTop: 16, paddingTop: 16, borderTop: `1px solid ${T.border}`, display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
            <span style={{ fontFamily: F.display, fontSize: 28 }}>{epzT('Итого')}</span>
            <span style={{ fontFamily: F.display, fontSize: 34, lineHeight: 1 }}>{fmt(total)}</span>
          </div>

          {/* order items — без заголовка, прокрутка при >4 */}
          <div style={{ order: 1, marginBottom: 24 }}>
            <div className="ch-items-scroll" ref={itemsScrollRef} onScroll={(e) => { const el = e.currentTarget; setItemsAtBottom(el.scrollTop + el.clientHeight >= el.scrollHeight - 4); }} style={{ maxHeight: 430, overflowY: 'auto', position: 'relative', padding: '9px 0 0 9px' }}>
            {grpRows.map((r, ri) => r.kind === 'bundle' ? (
              /* bundle — оформлен как единичное изделие */
              <div key={'b' + ri} style={{ padding: '10px 0' }}>
                <div style={{ display: 'grid', gridTemplateColumns: '54px 1fr', gap: 12 }}>
                  <div style={{ position: 'relative', width: 54, height: 68, backgroundColor: '#ffffff', backgroundImage: (r.image || r.parts[0].img) ? `url(${r.image || r.parts[0].img})` : 'none', backgroundRepeat: 'no-repeat', backgroundPosition: 'center', backgroundSize: 'contain' }}>
                    <span style={{ position: 'absolute', top: -7, left: -7, minWidth: 18, height: 18, borderRadius: 18, background: T.accent, color: T.accentText, fontFamily: F.mono, fontSize: 9, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: '0 4px', boxSizing: 'border-box' }}>{r.nSets}</span>
                  </div>
                  <div style={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10, alignItems: 'flex-start' }}>
                      <div style={{ fontFamily: F.display, fontSize: 15, lineHeight: 1.15 }}>{epzT(r.title)}</div>
                      <span style={{ fontFamily: F.display, fontSize: 15, flexShrink: 0 }}>{fmt(r.setPrice * r.nSets)}</span>
                    </div>
                    <div style={{ marginTop: 4, display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 5, fontFamily: F.mono, fontSize: 8.5, letterSpacing: '0.14em', textTransform: 'uppercase', opacity: 0.7 }}>
                      {(() => { const cols = []; r.parts.forEach((p) => { if (p.a.color && !cols.find((c) => c[0] === p.a.color)) cols.push([p.a.color, p.a.colorHex]); }); return cols.map(([nm, hex], i) => (
                        <span key={nm} style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                          <span style={{ width: 7, height: 7, borderRadius: '50%', background: hex || '#ccc', border: `1px solid ${T.border}`, flexShrink: 0 }} />
                          <span>{epzT(nm)}</span>{i < cols.length - 1 ? <span style={{ opacity: 0.5 }}>·</span> : null}
                        </span>
                      )); })()}
                      <span style={{ opacity: 0.6 }}>· {r.parts.map((p) => p.line.size).join(' · ')}</span>
                    </div>
                    <button type="button" onClick={() => setOpenBundles((o) => ({ ...o, [ri]: !o[ri] }))} style={{ marginTop: 6, background: 'transparent', border: 0, color: T.accentInk, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 9, fontFamily: F.mono, fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase', padding: 0, alignSelf: 'flex-start' }}>
                      <span>{openBundles[ri] ? epzT('скрыть состав') : epzT('состав комплекта')}</span>
                      <span style={{ display: 'inline-block', fontSize: 15, lineHeight: 1, transition: 'transform 0.2s', transform: openBundles[ri] ? 'rotate(180deg)' : 'none' }}>⌄</span>
                    </button>
                    {openBundles[ri] &&
                    <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 12 }}>
                      {r.parts.map((p, pi) => (
                        <div key={pi} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                          <div style={{ width: 30, height: 38, flexShrink: 0, backgroundColor: '#ffffff', backgroundImage: p.img ? `url(${p.img})` : 'none', backgroundRepeat: 'no-repeat', backgroundPosition: 'center', backgroundSize: 'contain' }} />
                          <div style={{ flex: 1, minWidth: 0 }}>
                            <div style={{ fontFamily: F.display, fontSize: 14, lineHeight: 1.15 }}>{epzT((p.a.variantNames && p.line.variant && p.a.variantNames[p.line.variant]) || p.a.short || p.a.title)}</div>
                            <span style={{ display: 'block', fontFamily: F.mono, fontSize: 8, letterSpacing: '0.14em', textTransform: 'uppercase', opacity: 0.55, marginTop: 2 }}>{p.line.size}{p.consumed > 1 ? ` · ×${p.consumed}` : ''}</span>
                          </div>
                          <div style={{ fontFamily: F.display, fontSize: 13, opacity: 0.55, flexShrink: 0 }}>{fmt(p.price)}</div>
                        </div>
                      ))}
                    </div>
                    }
                  </div>
                </div>
              </div>
            ) : (() => {
              const l = r.line; const a = r.a; const lImg = r.img;
              return (
              <div key={l.id + (l.variant || '') + l.size} style={{ display: 'grid', gridTemplateColumns: '54px 1fr', gap: 12, padding: '10px 0' }}>
                <a href={a.href || `/product/?id=${l.id}`} style={{ position: 'relative', display: 'block', width: 54, height: 68, backgroundColor: '#ffffff', backgroundImage: lImg ? `url(${lImg})` : 'none', backgroundRepeat: 'no-repeat', backgroundPosition: 'center', backgroundSize: 'contain' }}>
                  <span style={{ position: 'absolute', top: -7, left: -7, minWidth: 18, height: 18, borderRadius: 18, background: T.accent, color: T.accentText, fontFamily: F.mono, fontSize: 9, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: '0 4px', boxSizing: 'border-box' }}>{l.qty || 1}</span>
                </a>
                <div style={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10, alignItems: 'flex-start' }}>
                    <a href={a.href || `/product/?id=${l.id}`} style={{ fontFamily: F.display, fontSize: 15, lineHeight: 1.15, color: 'inherit', textDecoration: 'none' }}>{epzT((a.variantNames && l.variant && a.variantNames[l.variant]) || a.short || a.title)}</a>
                    <span style={{ fontFamily: F.display, fontSize: 15, flexShrink: 0 }}>{fmt(r.price * (l.qty || 1))}</span>
                  </div>
                  <div style={{ marginTop: 4, display: 'flex', alignItems: 'center', gap: 5, fontFamily: F.mono, fontSize: 8.5, letterSpacing: '0.14em', textTransform: 'uppercase', opacity: 0.7 }}>
                    {a.color ? <>
                      <span style={{ width: 7, height: 7, borderRadius: '50%', background: a.colorHex || '#ccc', border: `1px solid ${T.border}`, flexShrink: 0 }} />
                      <span>{epzT(a.color)}</span>
                      <span style={{ opacity: 0.5 }}>·</span>
                    </> : null}
                    <span>{l.size}</span>
                  </div>
                </div>
              </div>
              );
            })())}
            </div>
            {cart.length > 4 && !itemsAtBottom && <div style={{ marginTop: 8, textAlign: 'center', fontFamily: F.mono, fontSize: 9, letterSpacing: '0.16em', textTransform: 'uppercase', opacity: 0.5 }}>↓ {epzT('листайте — ещё')} {cart.length - 4}</div>}
            {restorable && !grouped.rows.some((r) => r.kind === 'bundle' && epzT(r.title) === epzT(restorable.title)) &&
            <div style={{ marginTop: 12, border: `1px solid ${T.accent}`, background: T.bgAlt, padding: '12px 14px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontFamily: F.mono, fontSize: 8, letterSpacing: '0.16em', textTransform: 'uppercase', color: T.accentInk, marginBottom: 3 }}>✦ {restorable.single ? epzT('товар удалён') : epzT('комплект распался')}</div>
                <div style={{ fontFamily: F.display, fontSize: 15, lineHeight: 1.1 }}>{epzT(restorable.title)}</div>
              </div>
              <button type="button" onClick={restoreSet} style={{ flexShrink: 0, background: T.accent, color: T.accentText, border: 0, cursor: 'pointer', padding: '10px 14px', fontFamily: F.mono, fontSize: 9, letterSpacing: '0.16em', textTransform: 'uppercase' }}>{restorable.single ? epzT('вернуть товар') : epzT('вернуть комплект')}</button>
            </div>
            }
          </div>

        </aside>
      </form>
      )}
    </div>
  );
}

// ─── Step section ────────────────────────────────────────────────────────────
function Step({ n, title, T, children }) {
  const F = EPZ_FONTS;
  return (
    <section style={{ marginTop: 10, marginBottom: 22 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 14 }}>
        <span style={{ fontFamily: F.mono, fontSize: 11, letterSpacing: '0.12em', color: T.accentInk }}>{n}</span>
        <span style={{ fontFamily: F.display, fontSize: 24, fontWeight: 400 }}>{title}</span>
      </div>
      <div>{children}</div>
    </section>
  );
}

// ─── Success state ───────────────────────────────────────────────────────────
function CheckoutSuccess({ T, email, firstName, orderNumber, total, fmt, delivery, isGift }) {
  const F = EPZ_FONTS;
  const claimUrl = () => {
    try {
      const cart = epzReadStore(EPZ_CART_KEY).map((l) => ({ id: l.id, variant: l.variant || null, size: l.size || null, qty: l.qty || 1 }));
      return location.origin + '/gift/?items=' + encodeURIComponent(JSON.stringify(cart)) + (firstName ? '&from=' + encodeURIComponent(firstName) : '') + '&order=' + orderNumber;
    } catch (e) { return location.href; }
  };
  const copyClaim = () => {
    const u = claimUrl();
    const done = () => epzToast(epzT('ссылка-открытка скопирована'));
    try { navigator.clipboard.writeText(u).then(done, () => window.prompt(epzT('Скопируйте ссылку'), u)); }
    catch (e) { window.prompt(epzT('Скопируйте ссылку'), u); }
  };
  const shareClaim = () => {
    const u = claimUrl();
    if (navigator.share) navigator.share({ title: 'THE EPIZODE — вам подарок', url: u }).catch(() => {});
    else copyClaim();
  };
  if (isGift) {
    return (
      <section style={{ padding: '80px 32px 110px', maxWidth: 760, margin: '0 auto' }}>
        <div style={{ fontFamily: F.mono, fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: T.accentInk, marginBottom: 18 }}>{epzT('подарок оплачен')}</div>
        <h1 style={{ fontFamily: F.display, fontSize: 'clamp(40px, 6vw, 72px)', fontWeight: 400, lineHeight: 1.02, margin: 0 }}>
          {epzT('Спасибо')}{firstName ? `, ${firstName}` : ''}!
        </h1>
        <p style={{ marginTop: 22, fontFamily: F.body, fontSize: 16, lineHeight: 1.65, opacity: 0.85, maxWidth: 540 }}>
          {epzT('Осталось одно: отправьте получательнице ссылку-открытку. Она увидит подарок и сама укажет удобный адрес доставки. Чек придёт на')} <b>{email || epzT('ваш email')}</b>
        </p>
        <div style={{ marginTop: 30, display: 'flex', gap: 12, flexWrap: 'wrap' }}>
          <button onClick={shareClaim} style={{ background: T.btnPrimary, color: T.btnPrimaryFg, border: 0, cursor: 'pointer', padding: '16px 28px', fontFamily: F.mono, fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase' }}>{epzT('отправить ссылку-открытку →')}</button>
          <button onClick={copyClaim} style={{ background: 'transparent', color: T.text, border: `1px solid ${T.border}`, cursor: 'pointer', padding: '16px 28px', fontFamily: F.mono, fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase' }}>{epzT('скопировать ссылку')}</button>
        </div>
        <div style={{ marginTop: 34, border: `1px solid ${T.border}`, padding: '24px 26px', display: 'grid', gridTemplateColumns: '1fr auto', gap: '14px 24px', fontSize: 14 }}>
          <span style={{ opacity: 0.6 }}>{epzT('Номер заказа')}</span><span style={{ textAlign: 'right', fontFamily: F.mono, letterSpacing: '0.08em' }}>{orderNumber}</span>
          <span style={{ opacity: 0.6 }}>{epzT('Сумма')}</span><span style={{ textAlign: 'right', fontFamily: F.display, fontSize: 20 }}>{fmt(total)}</span>
        </div>
        <p style={{ marginTop: 18, fontFamily: F.body, fontSize: 13, lineHeight: 1.6, opacity: 0.55, maxWidth: 520 }}>
          {epzT('Если что-то пойдёт не так — мы рядом в Telegram @epizode_help')}
        </p>
      </section>
    );
  }
  return (
    <section style={{ padding: '22px 32px 60px', maxWidth: 760, margin: '0 auto' }}>
      <h1 style={{ fontFamily: F.display, fontSize: 'clamp(36px, 4.6vw, 56px)', fontWeight: 400, lineHeight: 1.02, margin: 0 }}>
        Спасибо{firstName ? `, ${firstName}` : ''}!
      </h1>
      <p style={{ marginTop: 14, fontFamily: F.body, fontSize: 15, lineHeight: 1.6, opacity: 0.85, maxWidth: 520 }}>
        Заказ принят. Подтверждение и трек-номер придут на <b>{email || 'ваш email'}</b> в течение часа. Если нужно что-то изменить или уточнить — напишите в Telegram <b>@epizode_help</b>
      </p>

      <a href="https://t.me/epizode_help" target="_blank" rel="noopener" style={{ marginTop: 16, display: 'flex', alignItems: 'center', gap: 16, border: `1px solid ${T.accentInk}`, padding: '13px 18px', textDecoration: 'none', color: 'inherit', boxSizing: 'border-box' }}>
        <span style={{ flexShrink: 0, width: 32, height: 32, borderRadius: '50%', background: T.accentInk, color: '#F7F2E9', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
          <svg viewBox="0 0 24 24" width="15" height="15" fill="currentColor"><path d="M21.9 4.1 2.9 11.4c-1 .4-1 1.3-.2 1.6l4.8 1.5 1.9 5.7c.2.7 1 .9 1.5.4l2.7-2.6 4.9 3.6c.7.4 1.5 0 1.7-.8l3-14.9c.2-1-.5-1.5-1.3-1.2ZM8.5 14l9.3-6.4c.4-.3.8.1.5.4l-7.7 7-.3 3.1L8.5 14Z"/></svg>
        </span>
        <span>
          <span style={{ display: 'block', fontFamily: F.body, fontSize: 13.5, fontWeight: 600 }}>Статусы заказа в Telegram</span>
          <span style={{ display: 'block', marginTop: 2, fontFamily: F.body, fontSize: 12, opacity: 0.65, lineHeight: 1.45 }}>Нажмите, чтобы получать статус пошива и доставки прямо в Telegram</span>
        </span>
      </a>

      <div style={{ marginTop: 16, border: `1px solid ${T.border}`, padding: '18px 22px', display: 'grid', gridTemplateColumns: '1fr auto', gap: '10px 24px', fontSize: 14 }}>
        <span style={{ opacity: 0.6 }}>Номер заказа</span><span style={{ textAlign: 'right', fontFamily: F.mono, letterSpacing: '0.08em' }}>{orderNumber}</span>
        <span style={{ opacity: 0.6 }}>Доставка</span><span style={{ textAlign: 'right' }}>{delivery.label}</span>
        <span style={{ opacity: 0.6 }}>Срок</span><span style={{ textAlign: 'right' }}>{delivery.sublabel}</span>
        <span style={{ opacity: 0.6 }}>Сумма</span><span style={{ textAlign: 'right', fontFamily: F.display, fontSize: 20 }}>{fmt(total)}</span>
      </div>

      <div style={{ marginTop: 18, display: 'flex', gap: 12, flexWrap: 'wrap' }}>
        <a href="/" style={{ background: T.btnPrimary, color: T.btnPrimaryFg, textDecoration: 'none', padding: '16px 28px', fontFamily: F.mono, fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase' }}>на главную →</a>
        <a href="/catalog/" style={{ background: 'transparent', color: T.text, textDecoration: 'none', border: `1px solid ${T.border}`, padding: '16px 28px', fontFamily: F.mono, fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase' }}>в каталог</a>
      </div>
    </section>
  );
}

// ─── Express pay button shell ────────────────────────────────────────────────
function ExpressBtn({ onClick, bg, border, children }) {
  return (
    <button type="button" className="ch-express" onClick={onClick} style={{
      height: 52, background: bg, border: border ? `1px solid ${border}` : 0, cursor: 'pointer',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 0,
    }}>
      {children}
    </button>
  );
}

// ─── Payment marks ────────────────────────────────────────────────────────────
// Tries an official logo file at assets/pay/<name>.svg (drop real brand assets
// there on the host); falls back to a clean text wordmark until then.
function PayMark({ name, label, color }) {
  const sans = '"Manrope", system-ui, sans-serif';
  const [failed, setFailed] = React.useState(false);
  if (!failed) {
    return (
      <img src={`/assets/pay/${name}.svg`} alt={label} style={{ height: 22, maxWidth: '78%', objectFit: 'contain' }}
        onError={() => setFailed(true)} />
    );
  }
  return <span style={{ fontFamily: sans, fontWeight: 700, fontSize: 15, color, letterSpacing: '0.01em' }}>{label}</span>;
}

window.EpzCheckoutPage = EpzCheckoutPage;
