/* ============================================================
   ui.jsx — primitives, icons, cart (context + drawer), sticky CTA
   ============================================================ */
const { createContext, useContext, useState, useEffect, useRef, useCallback } = React;

/* ---------- Icons (simple line set) ---------- */
const ICONS = {
  spark: 'M12 2l2.2 6.2L20 10l-5.8 1.8L12 18l-2.2-6.2L4 10l5.8-1.8z',
  shield: 'M12 3l7 3v5c0 4.3-3 7.4-7 9-4-1.6-7-4.7-7-9V6z',
  cart: 'M3 4h2l2.2 11.5a1 1 0 001 .8h8.8a1 1 0 001-.8L21 7H6',
  plus: 'M12 5v14M5 12h14',
  minus: 'M5 12h14',
  close: 'M6 6l12 12M18 6L6 18',
  arrowL: 'M15 5l-7 7 7 7',
  arrowR: 'M9 5l7 7-7 7',
  check: 'M4 12l5 5L20 6',
  star: 'M12 3l2.7 5.5 6 .9-4.3 4.2 1 6-5.4-2.8L6.6 19.6l1-6L3.3 9.4l6-.9z',
  whatsapp: 'M17.47 14.38c-.3-.15-1.76-.87-2.03-.97-.27-.1-.47-.15-.67.15-.2.3-.77.97-.94 1.16-.17.2-.35.22-.64.08-.3-.15-1.26-.46-2.39-1.48-.88-.79-1.48-1.76-1.65-2.06-.17-.3-.02-.46.13-.61.13-.13.3-.35.45-.52.15-.17.2-.3.3-.5.1-.2.05-.37-.02-.52-.08-.15-.67-1.61-.92-2.21-.24-.58-.49-.5-.67-.51-.17-.01-.37-.01-.57-.01-.2 0-.52.07-.79.37-.27.3-1.04 1.02-1.04 2.48 0 1.46 1.07 2.88 1.21 3.07.15.2 2.1 3.2 5.08 4.49.71.31 1.26.49 1.69.62.71.23 1.36.2 1.87.12.57-.08 1.76-.72 2.01-1.41.25-.7.25-1.29.17-1.41-.07-.13-.27-.2-.57-.35z M12.05 21.79h-.01a9.87 9.87 0 01-5.03-1.38l-.36-.21-3.74.98 1-3.65-.24-.37A9.86 9.86 0 012.17 11.9c0-5.45 4.44-9.88 9.89-9.88 2.64 0 5.12 1.03 6.99 2.9a9.83 9.83 0 012.89 6.99c0 5.46-4.44 9.88-9.89 9.88zm8.41-18.3A11.82 11.82 0 0012.05 0C5.44 0 .07 5.36.07 11.97c0 2.11.55 4.17 1.6 5.98L0 24l6.34-1.65a11.9 11.9 0 005.65 1.44h.01c6.61 0 11.98-5.37 11.99-11.97a11.9 11.9 0 00-3.53-8.33z',
};
function Icon({ name, size = 24, stroke = 'currentColor', fill = 'none', sw = 2, style }) {
  if (name === 'family') {
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" style={style}>
        <circle cx="8" cy="7" r="2.6" /><circle cx="16.5" cy="8" r="2.1" />
        <path d="M3.5 19c0-2.8 2-4.6 4.5-4.6S12.5 16.2 12.5 19" />
        <path d="M13.5 19c0-2.2 1.5-3.7 3.4-3.7S20 16.8 20 19" />
      </svg>
    );
  }
  if (name === 'gift') {
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" style={style}>
        <rect x="3.5" y="9" width="17" height="11" rx="1.5" /><path d="M3 13h18M12 9v11" />
        <path d="M12 9S10.5 4.5 8 5.2 9.5 9 12 9zM12 9s1.5-4.5 4-3.8S14.5 9 12 9z" />
      </svg>
    );
  }
  const d = ICONS[name];
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" style={style}>
      <path d={d} />
    </svg>
  );
}

/* ---------- Money ---------- */
function money(n) {
  return (Number.isInteger(n) ? n : n.toFixed(2)) + ' ₪';
}

/* Resolve a local asset path through an inlined data-URI map (used by the
   shareable single-file build). Remote URLs and unknown paths pass through. */
function assetURL(p) {
  if (p && window.__LOCAL && Object.prototype.hasOwnProperty.call(window.__LOCAL, p)) return window.__LOCAL[p];
  return p;
}
window.assetURL = assetURL;

/* ---------- Smart image: real photo with striped placeholder fallback ---------- */
function PlaceholderImg({ label, style, className }) {
  return (
    <div className={'ph ' + (className || '')} style={style}>
      <span className="ph-label">{label || 'תמונה'}</span>
    </div>
  );
}
function SmartImg({ url, alt, label, style, className, radius, objectFit = 'cover', lazy = false }) {
  const [err, setErr] = useState(false);
  const st = { ...style, borderRadius: radius };
  if (!url || err) {
    return <PlaceholderImg label={label || alt} style={st} className={className} />;
  }
  return (
    <img
      src={assetURL(url)}
      alt={alt || ''}
      loading={lazy ? 'lazy' : 'eager'}
      className={className}
      style={{ ...st, objectFit, display: 'block' }}
      onError={() => setErr(true)}
    />
  );
}

/* ---------- Button ---------- */
function Btn({ children, variant = 'solid', size = 'md', onClick, full, style, icon, href }) {
  const cls = `btn btn-${variant} btn-${size}` + (full ? ' btn-full' : '');
  const inner = (
    <>
      {icon && <Icon name={icon} size={size === 'lg' ? 22 : 18} sw={2.4} />}
      <span>{children}</span>
    </>
  );
  if (href) return <a className={cls} href={href} style={style} onClick={onClick}>{inner}</a>;
  return <button className={cls} onClick={onClick} style={style}>{inner}</button>;
}

/* ============================================================
   Cart
   ============================================================ */
const CartCtx = createContext(null);
window.CartCtx = CartCtx;
window.useCart = () => useContext(CartCtx);

function CartProvider({ children }) {
  const [items, setItems] = useState(() => {
    try { return JSON.parse(localStorage.getItem('st_cart') || '[]'); } catch (e) { return []; }
  });
  const [open, setOpen] = useState(false);
  const [bump, setBump] = useState(0);
  const [cust, setCust] = useState(() => {
    try { const c = JSON.parse(localStorage.getItem('st_cust') || '{}'); delete c.coupon; return c; } catch (e) { return {}; }
  });
  useEffect(() => {
    fetch('/api/coupons').then(r => r.ok ? r.json() : null).then(remote => {
      if (remote && Object.keys(remote).length) Object.assign(window.STData.COUPONS, remote);
    }).catch(() => {});
  }, []);
  const setCustomer = useCallback((patch) => setCust((c) => { const n = { ...c, ...patch }; try { const persist = { ...n }; delete persist.coupon; localStorage.setItem('st_cust', JSON.stringify(persist)); } catch (e) {} return n; }), []);
  useEffect(() => { try { localStorage.setItem('st_cart', JSON.stringify(items)); } catch (e) {} }, [items]);

  const add = useCallback((id) => {
    setItems((prev) => {
      const ex = prev.find((i) => i.id === id);
      if (ex) return prev.map((i) => i.id === id ? { ...i, qty: i.qty + 1 } : i);
      return [...prev, { id, qty: 1 }];
    });
    setBump((b) => b + 1);
    setOpen(true);
  }, []);
  const setQty = useCallback((id, qty) => {
    setItems((prev) => qty <= 0 ? prev.filter((i) => i.id !== id) : prev.map((i) => i.id === id ? { ...i, qty } : i));
  }, []);
  const remove = useCallback((id) => setItems((prev) => prev.filter((i) => i.id !== id)), []);
  const clear = useCallback(() => { setItems([]); try { localStorage.removeItem('st_cart'); } catch (e) {} }, []);

  const count = items.reduce((s, i) => s + i.qty, 0);
  const subtotal = items.reduce((s, i) => s + (STData.PRODUCTS[i.id]?.price || 0) * i.qty, 0);
  const DISC = 99;                                  // threshold for reduced shipping
  const isPickup = (cust.delivery || 'delivery') === 'pickup';
  const baseShip = (items.length === 0 || isPickup) ? 0 : (subtotal >= DISC ? 20 : 35);
  const reachedDisc = subtotal >= DISC;
  const toDisc = Math.max(0, DISC - subtotal);

  // ---- applied coupon (validated, persisted in cust.coupon) ----
  const cou = cust.coupon ? STData.evalCoupon(cust.coupon, subtotal, baseShip) : { ok: false };
  const couponApplied = cou.ok;
  const couponIsTest = couponApplied && cou.test;
  const discount = couponApplied ? cou.discount : 0;
  const ship = (couponApplied && cou.freeship) ? 0 : baseShip;
  const grandTotal = couponIsTest ? 1 : Math.max(0, Math.round((subtotal - discount + ship) * 100) / 100);

  // ---- Checkout via Make webhook → Grow payment link ----
  const CHECKOUT_WEBHOOK = 'https://hook.eu1.make.com/pyc390x5hakza5oshqnj4c7mu2ln1a4k';
  const [paying, setPaying] = useState(false);

  // Reset the paying state when the user returns to the tab (e.g. after
  // being redirected to Grow and hitting the browser Back button — the page
  // is restored from bfcache with paying still true, disabling the button).
  useEffect(() => {
    const reset = () => setPaying(false);
    window.addEventListener('pageshow', reset);
    document.addEventListener('visibilitychange', () => { if (!document.hidden) setPaying(false); });
    return () => window.removeEventListener('pageshow', reset);
  }, []);

  const checkout = useCallback(async () => {
    if (items.length === 0 || paying) return;
    const origin = (window.location.origin && window.location.origin.startsWith('http'))
      ? window.location.origin : 'https://storytable.shop';
    const absImg = (u) => {
      if (!u) return '';
      if (u.startsWith('http')) return u;            // Drive / external — already absolute
      return origin + '/' + u.replace(/^\//, '');    // local asset → full site URL
    };
    const lines = items.map((i) => {
      const p = STData.PRODUCTS[i.id];
      // Grow's payment page lets the buyer edit quantity, so we collapse every
      // line to quantity:1 — the price becomes the line total and the qty is
      // baked into the product name (e.g. "ספר הפנים (x2)").
      const lineTotal = Math.round(p.price * i.qty * 100) / 100;
      const name = i.qty > 1 ? `${p.name} (x${i.qty})` : p.name;
      const img = absImg(p.img);
      return { name, price: lineTotal, quantity: 1, productUrl: img, vatType: 1 };
    });
    const sub = items.reduce((s, i) => s + (STData.PRODUCTS[i.id]?.price || 0) * i.qty, 0);
    const pickup = (cust.delivery || 'delivery') === 'pickup';
    // evaluate the applied coupon
    const cc = cust.coupon ? STData.evalCoupon(cust.coupon, sub, pickup ? 0 : (sub >= 99 ? 20 : 35)) : { ok: false };
    const freeShip = cc.ok && cc.freeship;
    const shipCost = (pickup || freeShip) ? 0 : (sub >= 99 ? 20 : 35);
    const couponDiscount = cc.ok ? (cc.discount || 0) : 0;
    // iCount invoice lines — clean: description / unit price incl. VAT / real quantity
    const iCountItems = items.map((i) => {
      const p = STData.PRODUCTS[i.id];
      return { description: p.name, unitprice_incvat: p.price, quantity: i.qty };
    });
    if (!pickup && shipCost > 0) iCountItems.push({ description: 'משלוח עד הבית', unitprice_incvat: shipCost, quantity: 1 });
    if (couponDiscount > 0) iCountItems.push({ description: 'הנחת קופון (' + (cust.coupon || '').toUpperCase() + ')', unitprice_incvat: -couponDiscount, quantity: 1 });

    let total = Math.max(0, Math.round((sub - couponDiscount + shipCost) * 100) / 100);
    const fullAddress = pickup ? 'איסוף עצמי' : [cust.street, cust.city].filter(Boolean).join(', ');

    // product lines for Grow
    let outLines = lines;
    if (!pickup && shipCost > 0) outLines = [...outLines, { name: 'משלוח עד הבית', price: shipCost, quantity: 1, productUrl: '', vatType: 1 }];
    if (couponDiscount > 0) outLines = [...outLines, { name: 'הנחת קופון (' + (cust.coupon || '').toUpperCase() + ')', price: -couponDiscount, quantity: 1, productUrl: '', vatType: 1 }];
    let outICount = iCountItems;

    // test coupon → keep the full product breakdown, add a discount line down to 1 ₪
    if (cc.ok && cc.test) {
      const gross = Math.round((sub + shipCost) * 100) / 100;
      const testDisc = Math.round((gross - 1) * 100) / 100;
      total = 1;
      if (testDisc > 0) {
        outLines = [...outLines, { name: 'הנחת בדיקה (' + (cust.coupon || '').toUpperCase() + ')', price: -testDisc, quantity: 1, productUrl: '', vatType: 1 }];
        outICount = [...outICount, { description: 'הנחת בדיקה (' + (cust.coupon || '').toUpperCase() + ')', unitprice_incvat: -testDisc, quantity: 1 }];
      }
    }

    const orderId = 'ST-' + Date.now().toString(36).toUpperCase() + '-' + Math.random().toString(36).slice(2, 8).toUpperCase();
    const payload = {
      orderId: orderId,
      secret: 'st_9Kq4mZx7Rt2Vn6P',
      timestamp: Date.now(),
      amount: total,
      coupon: (cust.coupon || '').trim().toUpperCase(),
      customerName: (cust.name || '').trim(),
      fullName: (cust.name || '').trim(),
      phone: (cust.phone || '').trim(),
      email: (cust.email || '').trim(),
      deliveryMethod: pickup ? 'איסוף עצמי' : 'משלוח עד הבית',
      companyName: (cust.companyName || '').trim(),
      taxId: (cust.taxId || '').trim(),
      invoice_name: (cust.companyName || '').trim(),
      invoice_license_number: (cust.taxId || '').trim(),
      marketingOptIn: cust.marketing !== false,
      address: fullAddress,
      street: pickup ? '' : (cust.street || '').trim(),
      city: pickup ? '' : (cust.city || '').trim(),
      notes: (cust.notes || '').trim(),
      subtotal: sub,
      discount: couponDiscount,
      shipping: shipCost,
      items: outLines,
      iCount_items: outICount,
    };
    setPaying(true);
    try {
      const res = await fetch(CHECKOUT_WEBHOOK, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      const text = (await res.text()).trim();
      // Make may return the URL as plain text, or as JSON {url:"..."} / {paymentUrl:"..."}
      let url = '';
      if (text.startsWith('http')) {
        url = text;
      } else {
        try {
          const j = JSON.parse(text);
          url = j.url || j.paymentUrl || j.link || j.payment_url || j.data?.url || '';
        } catch (e) { /* not json */ }
      }
      if (url && url.startsWith('http')) {
        // break out of any iframe — payment pages refuse to be framed
        try {
          if (window.top && window.top !== window.self) { window.top.location.href = url; }
          else { window.location.href = url; }
        } catch (e) {
          // cross-origin framing (e.g. preview) blocks window.top — open in a new tab
          window.open(url, '_blank');
        }
      } else {
        setPaying(false);
        alert('אופס — לא הצלחנו ליצור קישור תשלום כרגע. נסו שוב, או צרו קשר בוואטסאפ 052-9256476.');
      }
    } catch (e) {
      setPaying(false);
      alert('אופס — משהו השתבש במעבר לתשלום. נסו שוב, או צרו קשר בוואטסאפ 052-9256476.');
    }
  }, [items, paying, cust]);

  const val = { items, open, setOpen, add, setQty, remove, clear, count, subtotal, ship, reachedDisc, toDisc, DISC, bump, checkout, paying, cust, setCustomer, couponApplied, couponIsTest, discount, grandTotal };
  return <CartCtx.Provider value={val}>{children}</CartCtx.Provider>;
}

/* ---------- Cart drawer (two steps: cart → checkout) ---------- */
function CartDrawer() {
  const cart = window.useCart();
  const { items, open, setOpen, setQty, remove, subtotal, ship, reachedDisc, toDisc, DISC, checkout, paying, cust, setCustomer, couponApplied, couponIsTest, discount, grandTotal } = cart;
  const [step, setStep] = useState('cart');
  const [couponField, setCouponField] = useState('');
  const [couponMsg, setCouponMsg] = useState(null); // {ok:bool, text}
  const [couponOpen, setCouponOpen] = useState(false);
  // whenever the drawer closes, or the cart empties, go back to the cart step
  useEffect(() => { if (!open) setStep('cart'); }, [open]);
  useEffect(() => { if (items.length === 0) setStep('cart'); }, [items.length]);
  useEffect(() => { setCouponField(cust.coupon || ''); if (cust.coupon && couponApplied) setCouponMsg({ ok: true }); }, [open]);

  const applyCoupon = () => {
    const code = couponField.trim();
    if (!code) { setCouponMsg(null); return; }
    const res = STData.evalCoupon(code, subtotal, isPickup ? 0 : (subtotal >= DISC ? 20 : 35));
    if (res.ok) {
      setCustomer({ coupon: code.toUpperCase() });
      setCouponMsg({ ok: true, text: res.test ? 'קוד בדיקה הוחל — סכום לתשלום ₪1' : (res.label || 'הקופון הוחל בהצלחה') });
    } else {
      setCouponMsg({ ok: false, text: 'קוד הקופון אינו תקף' });
    }
  };
  const removeCoupon = () => { setCustomer({ coupon: '' }); setCouponField(''); setCouponMsg(null); };

  const isPickup = (cust.delivery || 'delivery') === 'pickup';
  const phoneOk = /^0\d{8,9}$/.test((cust.phone || '').replace(/[-\s]/g, ''));
  const nameOk = (cust.name || '').trim().split(/\s+/).filter((w) => w.length >= 2).length >= 2;
  const emailOk = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test((cust.email || '').trim());
  const addrOk = isPickup || ((cust.street || '').trim().length >= 2 && (cust.city || '').trim().length >= 2);
  const canPay = nameOk && phoneOk && emailOk && addrOk && !paying;

  return (
    <>
      <div className={'drawer-scrim' + (open ? ' show' : '')} onClick={() => setOpen(false)}></div>
      <aside className={'drawer' + (open ? ' show' : '')} aria-hidden={!open}>
        <header className="drawer-head">
          {step === 'checkout'
            ? <button className="icon-btn" onClick={() => setStep('cart')} aria-label="חזרה לסל"><Icon name="arrowR" size={22} /></button>
            : <span style={{ width: 36 }}></span>}
          <h3>{step === 'checkout' ? 'פרטים ותשלום' : 'הסל שלי'}</h3>
          <button className="icon-btn" onClick={() => setOpen(false)} aria-label="סגירה"><Icon name="close" size={22} /></button>
        </header>

        {/* ===================== STEP 1 — CART ===================== */}
        {step === 'cart' && (
          <>
            <div className="ship-meter">
              {reachedDisc
                ? <span className="ship-win"><Icon name="check" size={16} sw={3} /> מגיע לך משלוח מוזל — 20 ₪ עד הבית!</span>
                : <span>עוד <b>{money(toDisc)}</b> ותקבלו משלוח מוזל (20 ₪ במקום 35 ₪)</span>}
              <div className="ship-bar"><div className="ship-fill" style={{ width: Math.min(100, (subtotal / DISC) * 100) + '%' }}></div></div>
            </div>

            <div className="drawer-body">
              {items.length === 0 && (
                <div className="cart-empty">
                  <div className="cart-empty-emoji">🛒</div>
                  <p>הסל ריק עדיין</p>
                  <Btn variant="ghost" onClick={() => setOpen(false)}>להמשך הקנייה</Btn>
                </div>
              )}
              {items.map((i) => {
                const p = STData.PRODUCTS[i.id];
                if (!p) return null;
                return (
                  <div className="cart-line" key={i.id}>
                    <div className="cart-thumb">
                      <SmartImg url={p.img} label={p.name} radius={12} style={{ width: '100%', height: '100%' }} />
                    </div>
                    <div className="cart-line-mid">
                      <div className="cart-line-name">{p.name}</div>
                      <div className="cart-line-sub">{p.sub}</div>
                      <button className="link-rm" onClick={() => remove(i.id)}>הסרה</button>
                    </div>
                    <div className="cart-line-end">
                      <div className="qty">
                        <button onClick={() => setQty(i.id, i.qty - 1)} aria-label="פחות"><Icon name="minus" size={15} sw={2.6} /></button>
                        <span>{i.qty}</span>
                        <button onClick={() => setQty(i.id, i.qty + 1)} aria-label="עוד"><Icon name="plus" size={15} sw={2.6} /></button>
                      </div>
                      <div className="cart-line-price">{money(p.price * i.qty)}</div>
                    </div>
                  </div>
                );
              })}
            </div>

            {items.length > 0 && (
              <footer className="drawer-foot">
                <div className="sub-row sub-row-total"><span>סה״כ</span><b>{money(subtotal)}</b></div>
                <Btn size="lg" full onClick={() => setStep('checkout')}>למעבר לתשלום</Btn>
                <button className="link-rm center" onClick={() => setOpen(false)}>המשך קנייה</button>
              </footer>
            )}
          </>
        )}

        {/* ===================== STEP 2 — CHECKOUT ===================== */}
        {step === 'checkout' && (
          <>
            <div className="drawer-body">
              <div className="co-deliv">
                <button type="button" className={'co-deliv-opt' + (!isPickup ? ' on' : '')} onClick={() => setCustomer({ delivery: 'delivery' })}>
                  <span className="co-deliv-t">משלוח עד הבית</span>
                  <span className="co-deliv-s">{subtotal >= DISC ? '20 ₪' : '35 ₪'}</span>
                </button>
                <button type="button" className={'co-deliv-opt' + (isPickup ? ' on' : '')} onClick={() => setCustomer({ delivery: 'pickup' })}>
                  <span className="co-deliv-t">איסוף עצמי</span>
                  <span className="co-deliv-s">חינם</span>
                </button>
              </div>

              <div className="co-fields">
                <input className="co-input" type="text" placeholder="שם פרטי ושם משפחה" value={cust.name || ''} onChange={(e) => setCustomer({ name: e.target.value })} />
                {(cust.name || '').trim().length > 0 && !nameOk && <span className="co-hint">יש להזין שם פרטי ושם משפחה</span>}
                <div className="co-row2">
                  <input className="co-input" type="tel" placeholder="טלפון נייד" value={cust.phone || ''} onChange={(e) => setCustomer({ phone: e.target.value })} />
                  <input className="co-input" type="email" placeholder="אימייל" value={cust.email || ''} onChange={(e) => setCustomer({ email: e.target.value })} />
                </div>
                {!isPickup && (
                  <div className="co-row2">
                    <input className="co-input" type="text" placeholder="רחוב ומספר" value={cust.street || ''} onChange={(e) => setCustomer({ street: e.target.value })} />
                    <input className="co-input" type="text" placeholder="עיר" value={cust.city || ''} onChange={(e) => setCustomer({ city: e.target.value })} />
                  </div>
                )}
                <div className="co-row2">
                  <input className="co-input" type="text" placeholder="שם החברה (אופציונלי)" value={cust.companyName || ''} onChange={(e) => setCustomer({ companyName: e.target.value })} />
                  <input className="co-input" type="text" placeholder="ח.פ / ע.מ (אופציונלי)" value={cust.taxId || ''} onChange={(e) => setCustomer({ taxId: e.target.value })} />
                </div>
                <label className="co-check">
                  <input type="checkbox" checked={cust.marketing !== false} onChange={(e) => setCustomer({ marketing: e.target.checked })} />
                  <span>אשמח לקבל עדכונים על מבצעים והטבות 💛</span>
                </label>
                {!couponOpen && !couponApplied && (
                  <button type="button" className="coupon-toggle" onClick={() => setCouponOpen(true)}>יש לך קופון?</button>
                )}
                {(couponOpen || couponApplied) && (
                  <div className="coupon-box">
                    <div className="coupon-field">
                      <input className="co-input" type="text" placeholder="הזינו קוד קופון" value={couponField}
                        onChange={(e) => { setCouponField(e.target.value); if (couponMsg) setCouponMsg(null); }}
                        onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); applyCoupon(); } }} />
                      {couponApplied
                        ? <button type="button" className="coupon-go coupon-go-rm" onClick={removeCoupon} aria-label="הסרת קופון"><Icon name="close" size={18} sw={2.6} /></button>
                        : <button type="button" className="coupon-go" onClick={applyCoupon} aria-label="החל קופון"><Icon name="arrowL" size={20} sw={2.6} /></button>}
                    </div>
                    {couponMsg && !couponMsg.ok && <span className="coupon-err">{couponMsg.text}</span>}
                    {couponApplied && <span className="coupon-ok"><Icon name="check" size={14} sw={3} /> {couponMsg && couponMsg.text ? couponMsg.text : 'הקופון הוחל'}</span>}
                  </div>
                )}
              </div>
            </div>

            <footer className="drawer-foot">
              <div className="sub-row sub-row-sm"><span>סה״כ ביניים</span><span>{money(subtotal)}</span></div>
              {couponApplied && !couponIsTest && discount > 0 && (
                <div className="sub-row sub-row-sm sub-row-disc"><span>הנחת קופון</span><span>−{money(discount)}</span></div>
              )}
              <div className="sub-row sub-row-sm"><span>{isPickup ? 'איסוף עצמי' : 'משלוח עד הבית'}</span><span>{(isPickup || ship === 0) ? 'חינם' : money(ship)}</span></div>
              <div className="sub-row sub-row-total"><span>סה״כ לתשלום</span><b>{money(grandTotal)}</b></div>
              <Btn size="lg" full onClick={checkout} style={canPay ? null : { opacity: .5, pointerEvents: 'none' }}>{paying ? 'מעבר לתשלום…' : 'לתשלום מאובטח'}</Btn>
              <button className="link-rm center" onClick={() => setStep('cart')}>חזרה לסל</button>
            </footer>
          </>
        )}
      </aside>
    </>
  );
}

Object.assign(window, { Icon, money, PlaceholderImg, SmartImg, Btn, CartProvider, CartDrawer });

/* ============================================================
   Product detail modal context
   ============================================================ */
const ModalCtx = createContext(null);
window.ModalCtx = ModalCtx;
window.useModal = () => useContext(ModalCtx);

function ModalProvider({ children }) {
  const [openId, setOpenId] = useState(null);
  const val = { openId, open: (id) => setOpenId(id), close: () => setOpenId(null) };
  return <ModalCtx.Provider value={val}>{children}</ModalCtx.Provider>;
}
window.ModalProvider = ModalProvider;
