// Checkout → Payment → PromptPay QR → Order confirmed → Track My Pasta

// ─── PromptPay EMVCo payload generator ───────────────────────────────────────
const PROMPTPAY_PHONE = '0954766235';

function ppTLV(id, val) { return id + String(val.length).padStart(2, '0') + val; }

function buildPromptPayPayload(phone, amount) {
  const digits = phone.replace(/\D/g, '');
  const acct = ('0066' + (digits.startsWith('0') ? digits.slice(1) : digits)).padStart(13, '0');
  const merchantInfo = ppTLV('00', 'A000000677010111') + ppTLV('01', acct);
  const body = [
    ppTLV('00', '01'),
    ppTLV('01', '12'),
    ppTLV('29', merchantInfo),
    ppTLV('53', '764'),
    ppTLV('54', amount.toFixed(2)),
    ppTLV('58', 'TH'),
    ppTLV('59', 'GUSTAI LAB'),
    ppTLV('60', 'PHUKET'),
    '6304',
  ].join('');
  let crc = 0xFFFF;
  for (let i = 0; i < body.length; i++) {
    crc ^= body.charCodeAt(i) << 8;
    for (let j = 0; j < 8; j++) crc = (crc & 0x8000) ? ((crc << 1) ^ 0x1021) & 0xFFFF : (crc << 1) & 0xFFFF;
  }
  return body + crc.toString(16).toUpperCase().padStart(4, '0');
}

function PromptPayQR({ amount }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!ref.current || !window.QRCode) return;
    ref.current.innerHTML = '';
    new window.QRCode(ref.current, {
      text: buildPromptPayPayload(PROMPTPAY_PHONE, amount),
      width: 220, height: 220,
      colorDark: '#0A0A0A', colorLight: '#ffffff',
      correctLevel: window.QRCode.CorrectLevel.M,
    });
    // qrcodejs creates a canvas; make it fill the container
    const canvas = ref.current.querySelector('canvas');
    if (canvas) { canvas.style.width = '100%'; canvas.style.height = 'auto'; canvas.style.display = 'block'; }
  }, [amount]);
  return <div ref={ref} style={{ width: '100%', minHeight: 200, display: 'flex', alignItems: 'center', justifyContent: 'center' }}/>;
}
// ─────────────────────────────────────────────────────────────────────────────

function GLCheckout({ app, go }) {
  const [address, setAddress] = React.useState(app.address);
  const [place, setPlace] = React.useState('home');
  const [timing, setTiming] = React.useState(0);
  const [payment, setPayment] = React.useState('promptpay');
  const [deliveryAck, setDeliveryAck] = React.useState(false);
  const [locating, setLocating] = React.useState(false);
  const [addingLabel, setAddingLabel] = React.useState(false);
  const [newLabel, setNewLabel] = React.useState('');
  const [customLabels, setCustomLabels] = React.useState([]);

  // Generate time slots based on current time
  const slots = React.useMemo(() => {
    const now = new Date();
    const pad = n => String(n).padStart(2, '0');
    const fmt = d => `${pad(d.getHours())}:${pad(d.getMinutes())}`;
    const addMin = (d, m) => new Date(d.getTime() + m * 60000);
    const roundUp30 = (d) => {
      const m = d.getMinutes();
      const add = m < 30 ? 30 - m : 60 - m;
      return addMin(d, add);
    };
    const asapEnd = addMin(now, 45);
    const slot2Start = roundUp30(addMin(now, 60));
    const slot3Start = addMin(slot2Start, 30);
    const slot4Start = addMin(slot3Start, 30);
    return [
      { kicker: 'ASAP', big: 'Now', sub: `${fmt(addMin(now, 30))} – ${fmt(asapEnd)}` },
      { kicker: 'Today', big: fmt(slot2Start), sub: `${fmt(slot2Start)} – ${fmt(addMin(slot2Start, 30))}` },
      { kicker: 'Today', big: fmt(slot3Start), sub: `${fmt(slot3Start)} – ${fmt(addMin(slot3Start, 30))}` },
      { kicker: 'Tmrw', big: fmt(slot4Start), sub: `${fmt(slot4Start)} – ${fmt(addMin(slot4Start, 30))}` },
    ];
  }, []);

  const useCurrentLocation = () => {
    if (!navigator.geolocation) return;
    setLocating(true);
    navigator.geolocation.getCurrentPosition(
      pos => {
        fetch(`https://nominatim.openstreetmap.org/reverse?lat=${pos.coords.latitude}&lon=${pos.coords.longitude}&format=json&accept-language=en`)
          .then(r => r.json())
          .then(d => {
            const a = d.address || {};
            const parts = [a.road, a.village || a.suburb || a.neighbourhood, a.city || a.town || a.county].filter(Boolean);
            const addr = parts.join(', ') || d.display_name || `${pos.coords.latitude.toFixed(4)}, ${pos.coords.longitude.toFixed(4)}`;
            setAddress(addr); app.setAddress(addr);
          })
          .catch(() => {
            const addr = `${pos.coords.latitude.toFixed(5)}, ${pos.coords.longitude.toFixed(5)}`;
            setAddress(addr); app.setAddress(addr);
          })
          .finally(() => setLocating(false));
      },
      () => { setLocating(false); alert('Please enable location access in your browser settings.'); }
    );
  };

  const openInMaps = () => {
    const q = encodeURIComponent(address || 'Phuket, Thailand');
    window.open(`https://maps.google.com/?q=${q}`, '_blank');
  };

  const addCustomLabel = () => {
    const label = newLabel.trim();
    if (!label) return;
    setCustomLabels(prev => [...prev, label]);
    setPlace(label.toLowerCase());
    setNewLabel('');
    setAddingLabel(false);
  };

  const allLabels = ['Home', 'Office', 'Villa 5', ...customLabels];

  const subtotal = app.cart.reduce((s, i) => s + i.price * i.qty, 0);
  const total = subtotal + 60;

  return (
    <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column' }}>
      <GLTopBar onBack={() => go('box')} center={
        <div className="gl-display" style={{ fontSize: 14, letterSpacing: '0.18em', color: GL.ink }}>CHECKOUT</div>
      }/>

      <div style={{ flex: 1, overflowY: 'auto', paddingBottom: 200 }} className="gl-noscroll">
        {/* Delivery */}
        <section style={{ padding: '26px 20px 28px', borderBottom: `2px solid ${GL.ink}` }}>
          <h2 className="gl-display" style={{ fontSize: 38, margin: '0 0 18px', color: GL.ink, letterSpacing: '-0.02em' }}>Delivery</h2>
          <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.16em', color: GL.muted, textTransform: 'uppercase', marginBottom: 8 }}>Address</div>
          <div style={{ display: 'flex', border: `2px solid ${GL.ink}`, background: '#fff', boxShadow: `4px 4px 0 ${GL.ink}` }}>
            <input value={address} onChange={e => { setAddress(e.target.value); app.setAddress(e.target.value); }}
              style={{ flex: 1, border: 'none', outline: 'none', padding: '14px 14px', fontSize: 14, fontWeight: 500 }}/>
            <button onClick={openInMaps} style={{ width: 48, borderLeft: `2px solid ${GL.ink}`, display: 'grid', placeItems: 'center', background: 'transparent' }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={GL.ink} strokeWidth="2"><path d="M3 6l6-3 6 3 6-3v15l-6 3-6-3-6 3V6zM9 3v15M15 6v15"/></svg>
            </button>
          </div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 8 }}>
            <span style={{ fontSize: 9, fontWeight: 800, background: GL.ink, color: '#fff', padding: '4px 8px', letterSpacing: '0.14em', textTransform: 'uppercase' }}>Phuket Area Only</span>
            <button onClick={useCurrentLocation} style={{ fontSize: 12, fontWeight: 700, borderBottom: `2px solid ${GL.teal}`, paddingBottom: 1, background: 'transparent', color: locating ? GL.muted : GL.ink }}>
              {locating ? 'Locating…' : '📍 Use Current Location'}
            </button>
          </div>
          <div style={{ display: 'flex', gap: 10, marginTop: 18, overflowX: 'auto' }} className="gl-noscroll">
            {allLabels.map(p => {
              const on = p.toLowerCase() === place;
              return (
                <button key={p} onClick={() => setPlace(p.toLowerCase())}
                  style={{
                    flexShrink: 0, padding: '8px 16px', border: `2px solid ${on ? GL.ink : '#D5DADA'}`,
                    background: on ? GL.teal : 'transparent',
                    color: on ? GL.ink : GL.muted,
                    boxShadow: on ? `2px 2px 0 ${GL.ink}` : 'none',
                    fontSize: 11, fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase',
                  }}>{p}</button>
              );
            })}
            {addingLabel ? (
              <div style={{ display: 'flex', gap: 6, flexShrink: 0, alignItems: 'center' }}>
                <input autoFocus value={newLabel} onChange={e => setNewLabel(e.target.value)}
                  onKeyDown={e => { if (e.key === 'Enter') addCustomLabel(); if (e.key === 'Escape') setAddingLabel(false); }}
                  placeholder="Label…"
                  style={{ width: 80, border: `2px solid ${GL.ink}`, padding: '6px 8px', fontSize: 11, fontWeight: 700, outline: 'none', textTransform: 'uppercase', letterSpacing: '0.1em' }}/>
                <button onClick={addCustomLabel} style={{ padding: '6px 10px', background: GL.teal, border: `2px solid ${GL.ink}`, fontSize: 11, fontWeight: 800 }}>✓</button>
                <button onClick={() => { setAddingLabel(false); setNewLabel(''); }} style={{ padding: '6px 8px', border: `2px solid ${GL.muted}`, fontSize: 11, color: GL.muted, background: 'transparent' }}>✕</button>
              </div>
            ) : (
              <button onClick={() => setAddingLabel(true)} style={{ flexShrink: 0, width: 38, height: 38, border: `2px dashed ${GL.muted}`, color: GL.muted, display: 'grid', placeItems: 'center', background: 'transparent' }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M12 5v14M5 12h14"/></svg>
              </button>
            )}
          </div>
        </section>

        {/* Timing */}
        <section style={{ padding: '26px 20px 28px', borderBottom: `2px solid ${GL.ink}`, background: GL.offwhite }}>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14 }}>
            <h2 className="gl-display" style={{ fontSize: 38, margin: 0, color: GL.ink, letterSpacing: '-0.02em' }}>Timing</h2>
            <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', color: GL.muted, textTransform: 'uppercase' }}>
              {timing === 0 ? 'Est. 30–45 mins' : slots[timing].sub}
            </span>
          </div>
          <div style={{ display: 'flex', gap: 12, overflowX: 'auto' }} className="gl-noscroll">
            {slots.map((s, i) => {
              const on = i === timing;
              return (
                <button key={i} onClick={() => setTiming(i)}
                  style={{
                    flexShrink: 0, width: 120, padding: 12, border: `2px solid ${GL.ink}`,
                    background: on ? GL.teal : '#fff',
                    boxShadow: on ? `4px 4px 0 ${GL.ink}` : 'none',
                    display: 'flex', flexDirection: 'column', gap: 4, textAlign: 'left', minHeight: 88,
                  }}>
                  <span style={{ fontSize: 9, fontWeight: 800, letterSpacing: '0.12em', color: on ? GL.ink : GL.muted, textTransform: 'uppercase' }}>{s.kicker}</span>
                  <span className="gl-display" style={{ fontSize: 22, color: GL.ink }}>{s.big}</span>
                  <span style={{ fontSize: 10, fontWeight: 600, color: on ? GL.ink : GL.muted, marginTop: 'auto' }}>{s.sub}</span>
                </button>
              );
            })}
          </div>
        </section>

        {/* Payment */}
        <section style={{ padding: '26px 20px 20px' }}>
          <h2 className="gl-display" style={{ fontSize: 38, margin: '0 0 18px', color: GL.ink, letterSpacing: '-0.02em' }}>Payment</h2>

          <PaymentOption id="promptpay" selected={payment === 'promptpay'} onSelect={() => setPayment('promptpay')}
            logo={
              <div style={{ width: 36, height: 22, background: '#003D82', display: 'grid', placeItems: 'center', borderRadius: 2 }}>
                <svg width="24" height="14" viewBox="0 0 80 48" fill="none">
                  <circle cx="24" cy="24" r="20" fill="#fff" opacity="0.9"/>
                  <circle cx="56" cy="24" r="20" fill="#fff" opacity="0.9"/>
                  <line x1="40" y1="4" x2="40" y2="44" stroke="#003D82" strokeWidth="4"/>
                </svg>
              </div>
            }
            label="PromptPay QR" sub="Scan &amp; pay via any Thai banking app"/>
          <PaymentOption id="cod" selected={payment === 'cod'} onSelect={() => setPayment('cod')}
            logo={
              <div style={{ width: 36, height: 22, background: '#2E7D32', display: 'grid', placeItems: 'center', borderRadius: 2 }}>
                <svg width="20" height="14" viewBox="0 0 24 16" fill="none" stroke="#fff" strokeWidth="1.5" strokeLinecap="round">
                  <rect x="1" y="1" width="22" height="14" rx="2"/>
                  <circle cx="12" cy="8" r="3"/>
                  <path d="M1 5h4M19 5h4M1 11h4M19 11h4"/>
                </svg>
              </div>
            }
            label="Cash on Delivery" sub="Pay the driver upon arrival"/>

          {/* Delivery fee acknowledgment — lives in scroll area, collapses once ticked */}
          <div style={{ marginTop: 20, borderTop: `1px solid ${GL.line}`, paddingTop: 16 }}>
            {!deliveryAck ? (
              <button onClick={() => setDeliveryAck(true)}
                style={{
                  width: '100%', display: 'flex', alignItems: 'flex-start', gap: 12,
                  padding: '12px 14px', background: GL.offwhite,
                  border: `1.5px solid ${GL.line}`, borderRadius: 8,
                  textAlign: 'left', cursor: 'pointer',
                }}>
                <div style={{ width: 20, height: 20, borderRadius: 4, flexShrink: 0, marginTop: 1, background: '#fff', border: `2px solid #C0CACA`, display: 'grid', placeItems: 'center' }}/>
                <div>
                  <div style={{ fontSize: 12, fontWeight: 700, color: GL.ink, lineHeight: 1.4 }}>
                    A Grab delivery fee applies — paid separately to the driver 🛵
                  </div>
                  <div style={{ fontSize: 11, color: GL.muted, marginTop: 4, lineHeight: 1.55 }}>
                    This fee is <span style={{ fontWeight: 700, color: GL.ink }}>not included</span> in your cart total shown below. It's charged by Grab at the time of delivery and paid directly to the driver upon arrival — in cash or via PromptPay. Tap to confirm.
                  </div>
                </div>
              </button>
            ) : (
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', background: '#F0FDF9', border: `1.5px solid ${GL.teal}`, borderRadius: 8 }}>
                <div style={{ width: 20, height: 20, borderRadius: 4, flexShrink: 0, background: GL.teal, border: `2px solid ${GL.teal}`, display: 'grid', placeItems: 'center' }}>
                  <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke={GL.ink} strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5"/></svg>
                </div>
                <span style={{ fontSize: 12, fontWeight: 700, color: GL.ink }}>Grab delivery fee acknowledged 🛵</span>
                <button onClick={() => setDeliveryAck(false)} style={{ marginLeft: 'auto', fontSize: 10, color: GL.muted, fontWeight: 700, textDecoration: 'underline' }}>undo</button>
              </div>
            )}
          </div>
        </section>
      </div>

      {/* Sticky footer — total + confirm only */}
      <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: '12px 16px 24px', background: GL.paper, borderTop: `2px solid ${GL.ink}` }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
          <span style={{ fontSize: 11, fontWeight: 800, letterSpacing: '0.16em', color: GL.muted, textTransform: 'uppercase' }}>Total</span>
          <div style={{ textAlign: 'right' }}>
            <div style={{ fontSize: 10, color: GL.muted }}>Excl. Grab delivery</div>
            <div className="gl-display" style={{ fontSize: 30, color: GL.ink }}>฿ {total.toLocaleString()}</div>
          </div>
        </div>

        <button onClick={async () => {
            if (!deliveryAck) return;
            // ── Place order in Supabase ──────────────────────────────────────
            try {
              const cartItems = app.cart.map(item => ({
                product_id: item.id || item.product_id,
                quantity:   item.qty || item.quantity || 1,
              }));
              const result = await window.GLOrders.place(
                cartItems,
                app.address || '',
                app.slot    || '',
                payment
              );
              // Pass the real order number through to the confirmed screen
              if (app.setOrderNo) app.setOrderNo(result.orderNo);
            } catch (e) {
              console.error('[Checkout] Order placement failed:', e);
              // Still navigate — the mock fallback always returns a result
            }
            go(payment === 'promptpay' ? 'qr' : 'confirmed');
          }}
          onMouseDown={e => deliveryAck && (e.currentTarget.style.transform = 'scale(0.99)')}
          onMouseUp={e => e.currentTarget.style.transform=''}
          onMouseLeave={e => e.currentTarget.style.transform=''}
          style={{
            width: '100%', height: 60, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 20px',
            fontSize: 14, fontWeight: 800, letterSpacing: '0.18em', textTransform: 'uppercase', transition: 'transform .15s, opacity .2s',
            background: deliveryAck ? GL.ink : '#C0CACA',
            color: '#fff',
            cursor: deliveryAck ? 'pointer' : 'not-allowed',
            opacity: deliveryAck ? 1 : 0.7,
          }}>
          <span>Confirm Order</span>
          <span style={{ display: 'flex', alignItems: 'center', gap: 6, opacity: 0.8, fontSize: 11 }}>
            {deliveryAck ? 'Checkout' : 'Check box above'}
            {' '}<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
          </span>
        </button>
      </div>
    </div>
  );
}

function PaymentOption({ selected, onSelect, logo, label, sub }) {
  return (
    <label onClick={onSelect}
      style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: 14, marginBottom: 10,
        border: `2px solid ${selected ? GL.ink : GL.line}`, background: '#fff', cursor: 'pointer',
        position: 'relative', overflow: 'hidden', transition: 'border-color .15s',
      }}>
      {selected && <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: 6, background: GL.teal }}/>}
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingLeft: 12 }}>
        {logo}
        <div style={{ display: 'flex', flexDirection: 'column' }}>
          <span style={{ fontWeight: 800, fontSize: 15, lineHeight: 1 }}>{label}</span>
          <span style={{ fontSize: 11, color: GL.muted, marginTop: 3 }}>{sub}</span>
        </div>
      </div>
      <div style={{ width: 22, height: 22, border: `2px solid ${selected ? GL.ink : GL.line}`, borderRadius: '50%', display: 'grid', placeItems: 'center' }}>
        {selected && <div style={{ width: 10, height: 10, borderRadius: '50%', background: GL.ink }}/>}
      </div>
    </label>
  );
}

// PromptPay QR Payment screen — with receipt upload + admin confirmation polling
function GLQRPayment({ app, go }) {
  const total    = app.cart.reduce((s, i) => s + i.price * i.qty, 0) + 60;
  const orderNo  = app.orderNo;

  // Timer state
  const [remaining, setRemaining] = React.useState(899);

  // Receipt upload state
  const [file, setFile]           = React.useState(null);
  const [preview, setPreview]     = React.useState(null);  // data-url for images
  const [uploading, setUploading] = React.useState(false);
  const [uploaded, setUploaded]   = React.useState(false);
  const [pollStatus, setPollStatus] = React.useState('pending'); // 'pending'|'confirmed'|'rejected'
  const [uploadErr, setUploadErr] = React.useState('');
  const [dragOver, setDragOver]   = React.useState(false);
  const fileRef = React.useRef(null);

  // Countdown — pauses after receipt uploaded
  React.useEffect(() => {
    if (uploaded || remaining <= 0) return;
    const t = setInterval(() => setRemaining(r => Math.max(0, r - 1)), 1000);
    return () => clearInterval(t);
  }, [uploaded, remaining]);

  const mm = String(Math.floor(remaining / 60)).padStart(2, '0');
  const ss = String(remaining % 60).padStart(2, '0');

  // Poll for admin confirmation every 15 s (up to 10 min = 40 tries)
  React.useEffect(() => {
    if (!uploaded) return;
    let tries = 0;
    const iv = setInterval(async () => {
      tries++;
      if (tries > 40) { clearInterval(iv); return; }
      try {
        const { data } = await window.db
          .from('payment_receipts')
          .select('status')
          .eq('order_no', orderNo)
          .order('created_at', { ascending: false })
          .limit(1)
          .single();
        if (data?.status === 'confirmed' || data?.status === 'auto_confirmed') {
          clearInterval(iv);
          setPollStatus('confirmed');
          setTimeout(() => go('confirmed'), 1400);
        } else if (data?.status === 'rejected') {
          clearInterval(iv);
          setPollStatus('rejected');
        }
      } catch (_) {}
    }, 8000);
    return () => clearInterval(iv);
  }, [uploaded]);

  // File validation + preview
  function chooseFile(f) {
    if (!f) return;
    const ALLOWED = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
    const MAX = 5 * 1024 * 1024;
    if (!ALLOWED.includes(f.type)) { setUploadErr('Please choose a JPG, PNG, WebP, or PDF.'); return; }
    if (f.size > MAX)              { setUploadErr('File must be under 5 MB.'); return; }
    setUploadErr('');
    setFile(f);
    if (f.type.startsWith('image/')) {
      const reader = new FileReader();
      reader.onload = e => setPreview(e.target.result);
      reader.readAsDataURL(f);
    } else {
      setPreview(null);
    }
  }

  // Save QR code to camera roll
  function saveQR() {
    const canvas = document.querySelector('.gl-qr-wrap canvas');
    if (!canvas) return;
    const a = document.createElement('a');
    a.href = canvas.toDataURL('image/png');
    a.download = `gustai-${orderNo}.png`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  }

  // Upload receipt to Supabase Storage + record in payment_receipts table
  async function handleUpload() {
    if (!file || uploading) return;
    setUploading(true);
    setUploadErr('');
    try {
      const ext  = file.name.split('.').pop().toLowerCase() || 'jpg';
      const path = `${orderNo}/${Date.now()}.${ext}`;

      const { error: storErr } = await window.db.storage
        .from('receipts')
        .upload(path, file, { contentType: file.type, upsert: false });
      if (storErr) throw storErr;

      const { data: { session } } = await window.db.auth.getSession();
      const { error: dbErr } = await window.db.from('payment_receipts').insert({
        order_no:     orderNo,
        amount:       total,
        receipt_path: path,
        receipt_mime: file.type,
        customer_id:  session?.user?.id || null,
      });
      if (dbErr) throw dbErr;

      setUploaded(true);
    } catch (e) {
      setUploadErr(e?.message || 'Upload failed — please try again.');
    } finally {
      setUploading(false);
    }
  }

  // ── Confirmed banner (after admin approves) ───────────────────────────────
  if (pollStatus === 'confirmed') {
    return (
      <div style={{ width: '100%', height: '100%', background: GL.ink, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 20 }}>
        <div style={{ width: 80, height: 80, borderRadius: '50%', border: `3px solid ${GL.teal}`, display: 'grid', placeItems: 'center', boxShadow: `0 0 40px ${GL.teal}88` }}>
          <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke={GL.teal} strokeWidth="2.5" strokeLinecap="round"><path d="M20 6L9 17l-5-5"/></svg>
        </div>
        <div className="gl-display" style={{ fontSize: 32, color: '#fff', textAlign: 'center' }}>Payment<br/>Confirmed!</div>
        <div style={{ fontSize: 12, color: 'rgba(255,255,255,0.5)' }}>Taking you to your order…</div>
      </div>
    );
  }

  const maskedPhone = '+66 ' + PROMPTPAY_PHONE.replace(/^0/, '') .replace(/(\d{2})(\d{3})(\d{4})/, '$1-XXX-$3');

  return (
    <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column' }}>
      <div style={{ height: 3, background: GL.teal }}/>
      <GLTopBar onBack={() => go('checkout')} center={
        <div className="gl-display" style={{ fontSize: 14, letterSpacing: '0.16em' }}>SCAN TO PAY</div>
      }/>

      <div style={{ flex: 1, overflowY: 'auto', padding: '20px 24px 24px' }} className="gl-noscroll">

        {/* Amount */}
        <div style={{ textAlign: 'center', marginBottom: 20 }}>
          <div className="gl-kicker" style={{ color: GL.muted, marginBottom: 6 }}>Order Total</div>
          <div className="gl-display" style={{ fontSize: 52, color: GL.ink, letterSpacing: '-0.02em', lineHeight: 1 }}>
            ฿{Math.floor(total).toLocaleString()}
            <span style={{ fontSize: 26 }}>.00</span>
          </div>
          <div style={{ fontSize: 11, color: GL.muted, marginTop: 4 }}>Gustai Lab · {maskedPhone}</div>
        </div>

        {/* QR frame */}
        <div style={{ border: `2px solid ${GL.ink}`, boxShadow: `6px 6px 0 ${GL.ink}`, background: '#fff', padding: 16, marginBottom: 12 }}>
          {/* PromptPay header */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14, paddingBottom: 12, borderBottom: `1px solid ${GL.line}` }}>
            <div style={{ width: 32, height: 20, background: '#003D82', display: 'grid', placeItems: 'center', borderRadius: 2 }}>
              <svg width="20" height="12" viewBox="0 0 80 48" fill="none">
                <circle cx="24" cy="24" r="20" fill="#fff" opacity="0.9"/>
                <circle cx="56" cy="24" r="20" fill="#fff" opacity="0.9"/>
                <line x1="40" y1="4" x2="40" y2="44" stroke="#003D82" strokeWidth="4"/>
              </svg>
            </div>
            <span style={{ fontSize: 11, fontWeight: 800, color: '#003D82', letterSpacing: '0.08em' }}>PromptPay</span>
            <div style={{ flex: 1 }}/>
            <button onClick={saveQR} style={{ fontSize: 9, fontWeight: 800, letterSpacing: '0.12em', color: GL.muted, textTransform: 'uppercase', display: 'flex', alignItems: 'center', gap: 4 }}>
              <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
              Save QR
            </button>
          </div>

          <div className="gl-qr-wrap">
            <PromptPayQR amount={total}/>
          </div>

          {/* Recipient info */}
          <div style={{ marginTop: 14, paddingTop: 12, borderTop: `1px solid ${GL.line}`, display: 'flex', flexDirection: 'column', gap: 4 }}>
            {[
              { l: 'Recipient', v: 'Gustai Lab' },
              { l: 'PromptPay', v: maskedPhone },
              { l: 'Amount',    v: `฿${total.toFixed(2)}` },
            ].map(r => (
              <div key={r.l} style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11 }}>
                <span style={{ color: GL.muted, fontWeight: 600 }}>{r.l}</span>
                <span style={{ color: GL.ink, fontWeight: 800, fontFamily: 'monospace' }}>{r.v}</span>
              </div>
            ))}
          </div>

          {/* Steps */}
          <div style={{ display: 'flex', justifyContent: 'center', gap: 20, marginTop: 14, paddingTop: 12, borderTop: `1px solid ${GL.line}` }}>
            {['Open Banking App', 'Scan QR', 'Transfer'].map((s, i) => (
              <div key={s} style={{ textAlign: 'center' }}>
                <div style={{ width: 22, height: 22, borderRadius: '50%', background: GL.ink, color: '#fff', fontSize: 10, fontWeight: 800, display: 'grid', placeItems: 'center', margin: '0 auto 4px' }}>{i + 1}</div>
                <div style={{ fontSize: 9, fontWeight: 700, color: GL.muted, letterSpacing: '0.08em', textTransform: 'uppercase' }}>{s}</div>
              </div>
            ))}
          </div>
        </div>

        {/* Timer */}
        {!uploaded && (
          <div style={{ background: GL.offwhite, padding: '10px 14px', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, fontSize: 12, fontWeight: 700, color: GL.ink, marginBottom: 20 }}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={GL.ink} strokeWidth="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
            QR expires in <span className="gl-mono" style={{ fontSize: 13 }}>{mm}:{ss}</span>
          </div>
        )}

        {/* ── Receipt upload section ───────────────────────────────────────── */}
        <div style={{ border: `2px solid ${GL.ink}`, padding: '18px 16px', marginBottom: 8 }}>
          <div className="gl-display" style={{ fontSize: 11, letterSpacing: '0.18em', color: GL.muted, marginBottom: 4 }}>STEP 4</div>
          <div className="gl-display" style={{ fontSize: 17, color: GL.ink, marginBottom: 12 }}>Upload Your Receipt</div>

          {uploaded ? (
            /* ── After upload ──────────────────────────────────────────── */
            <div>
              {pollStatus === 'rejected' ? (
                <div style={{ background: '#fdecea', border: '1px solid #c0392b', padding: '12px 14px', color: '#922b21', fontSize: 13, fontWeight: 700 }}>
                  ✗ Receipt rejected — please contact us via LINE @GustaiLab.
                </div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'center', padding: '8px 0' }}>
                  <div style={{ width: 44, height: 44, borderRadius: '50%', background: GL.offwhite, border: `2px solid ${GL.teal}`, display: 'grid', placeItems: 'center' }}>
                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={GL.teal} strokeWidth="2.5" strokeLinecap="round"><path d="M20 6L9 17l-5-5"/></svg>
                  </div>
                  <div style={{ textAlign: 'center' }}>
                    <div style={{ fontSize: 14, fontWeight: 800, color: GL.ink }}>Receipt received ✓</div>
                    <div style={{ fontSize: 11, color: GL.muted, marginTop: 4 }}>We'll verify your payment within a few minutes.</div>
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 11, color: GL.muted }}>
                    <div style={{ width: 8, height: 8, borderRadius: '50%', background: GL.teal, animation: 'gl-pulse 1.5s infinite' }}/>
                    Waiting for confirmation…
                  </div>
                </div>
              )}
            </div>
          ) : (
            /* ── Before upload ─────────────────────────────────────────── */
            <div>
              <p style={{ fontSize: 12, color: GL.muted, fontWeight: 600, margin: '0 0 14px', lineHeight: 1.5 }}>
                After transferring, upload a screenshot or PDF of the bank confirmation. We verify within minutes.
              </p>

              {/* Drop zone */}
              <label
                htmlFor="gl-receipt-file"
                onDragOver={e => { e.preventDefault(); setDragOver(true); }}
                onDragLeave={() => setDragOver(false)}
                onDrop={e => { e.preventDefault(); setDragOver(false); chooseFile(e.dataTransfer?.files?.[0]); }}
                style={{
                  display: 'block', border: `2px dashed ${dragOver ? GL.teal : (file ? GL.ink : GL.line)}`,
                  background: dragOver ? `${GL.teal}11` : GL.offwhite,
                  padding: '20px 16px', textAlign: 'center', cursor: 'pointer',
                  marginBottom: 12, transition: 'border-color .15s, background .15s',
                }}
              >
                {file && preview ? (
                  <img src={preview} alt="Receipt preview" style={{ maxHeight: 120, maxWidth: '100%', objectFit: 'contain', display: 'block', margin: '0 auto 8px' }}/>
                ) : (
                  <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={GL.muted} strokeWidth="1.5" strokeLinecap="round" style={{ display: 'block', margin: '0 auto 8px' }}>
                    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/>
                  </svg>
                )}
                <div style={{ fontSize: 13, fontWeight: 800, color: file ? GL.ink : GL.muted }}>
                  {file ? file.name : 'Tap to choose image or PDF'}
                </div>
                {file && (
                  <div style={{ fontSize: 10, color: GL.muted, marginTop: 4 }}>
                    {(file.size / 1024).toFixed(0)} KB · tap to change
                  </div>
                )}
                {!file && (
                  <div style={{ fontSize: 10, color: GL.muted, marginTop: 4 }}>JPG, PNG, WebP, or PDF · up to 5 MB</div>
                )}
                <input
                  id="gl-receipt-file"
                  ref={fileRef}
                  type="file"
                  accept="image/jpeg,image/png,image/webp,application/pdf"
                  style={{ display: 'none' }}
                  onChange={e => chooseFile(e.target.files?.[0])}
                />
              </label>

              {uploadErr && (
                <div style={{ marginBottom: 10, padding: '8px 12px', background: '#fdecea', border: '1px solid #c0392b', color: '#922b21', fontSize: 12, fontWeight: 600 }}>
                  {uploadErr}
                </div>
              )}

              <GLButton
                onClick={handleUpload}
                variant="primary"
                disabled={!file || uploading}
                icon={uploading
                  ? <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>
                  : <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/></svg>
                }
              >
                {uploading ? 'Uploading…' : 'Upload Receipt'}
              </GLButton>
            </div>
          )}
        </div>

        <p style={{ textAlign: 'center', fontSize: 10, color: GL.muted, fontWeight: 600, letterSpacing: '0.08em' }}>
          Need help? Message us on LINE @GustaiLab
        </p>
      </div>
    </div>
  );
}

// Order confirmed
function GLConfirmed({ app, go }) {
  return (
    <div style={{ width: '100%', height: '100%', background: '#F6F8F8', display: 'flex', flexDirection: 'column' }}>
      <div style={{ background: GL.ink, color: '#fff', padding: '60px 24px 54px', borderRadius: '0 0 20px 20px', position: 'relative', overflow: 'hidden' }}>
        <button onClick={() => go('home')} style={{ position: 'absolute', top: 20, left: 20, color: '#fff', width: 36, height: 36, display: 'grid', placeItems: 'center' }}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
        </button>
        <div style={{ textAlign: 'center' }}>
          <div className="gl-slide-up" style={{
            width: 78, height: 78, borderRadius: '50%', border: `2px solid ${GL.teal}`,
            margin: '0 auto 20px', display: 'grid', placeItems: 'center',
            boxShadow: `0 0 40px ${GL.teal}66`,
          }}>
            <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke={GL.teal} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5"/></svg>
          </div>
          <h1 className="gl-display" style={{ fontSize: 44, lineHeight: 0.9, margin: 0, letterSpacing: '-0.02em' }}>Order<br/>Confirmed</h1>
          <p style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.18em', color: 'rgba(255,255,255,0.6)', marginTop: 14, textTransform: 'uppercase' }}>Thank You For Your Order</p>
        </div>
      </div>

      <div style={{ padding: '28px 24px 0', flex: 1, overflowY: 'auto' }} className="gl-noscroll">
        <div style={{ textAlign: 'center', marginBottom: 28 }}>
          <div className="gl-kicker" style={{ color: GL.muted, marginBottom: 6 }}>Order No.</div>
          <div className="gl-display" style={{ fontSize: 34, color: GL.ink, letterSpacing: '-0.01em' }}>#GUSTAI-{app.orderNo}</div>
        </div>

        <div style={{ borderLeft: `2px solid ${GL.ink}`, paddingLeft: 16, margin: '28px 0' }}>
          <div className="gl-kicker" style={{ color: GL.muted, marginBottom: 4 }}>Destination</div>
          <div className="gl-display" style={{ fontSize: 16, color: GL.ink, letterSpacing: '0.04em', marginBottom: 4 }}>Delivery to Rawai</div>
          <div style={{ fontSize: 13, color: GL.muted, marginBottom: 16 }}>{app.address}</div>
          <div className="gl-kicker" style={{ color: GL.muted, marginBottom: 4 }}>Estimated Arrival</div>
          <div className="gl-display" style={{ fontSize: 22, color: GL.ink, letterSpacing: '0.02em' }}>45 mins <span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: '50%', background: GL.teal, marginLeft: 4, animation: 'gl-pulse 1.5s infinite' }}/></div>
        </div>
      </div>

      {/* Cook timer promo */}
      <div style={{ margin: '0 20px 20px', padding: '18px 16px', background: GL.ink, display: 'flex', alignItems: 'center', gap: 14 }}>
        <div style={{ width: 44, height: 44, borderRadius: '50%', border: `2px solid ${GL.teal}`, display: 'grid', placeItems: 'center', flexShrink: 0 }}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={GL.teal} strokeWidth="2" strokeLinecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
        </div>
        <div style={{ flex: 1 }}>
          <div className="gl-display" style={{ fontSize: 13, color: '#fff', letterSpacing: '0.04em' }}>Pasta Cook Timer</div>
          <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.5)', marginTop: 2 }}>Perfect al dente — every time</div>
        </div>
        <button onClick={() => go('cook')} style={{ padding: '9px 14px', background: GL.teal, color: GL.ink, fontSize: 10, fontWeight: 800, letterSpacing: '0.14em', textTransform: 'uppercase', flexShrink: 0 }}>
          Open
        </button>
      </div>

      <div style={{ padding: '0 20px 28px' }}>
        <GLButton onClick={() => go('track')} variant="primary"
          icon={<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>}>
          Track My Pasta
        </GLButton>
      </div>
    </div>
  );
}

// Track My Pasta — animated map
function GLTrack({ app, go }) {
  const [progress, setProgress] = React.useState(0.15);
  const [stage, setStage] = React.useState(2); // 0 extruded 1 boxed 2 on the road
  React.useEffect(() => {
    const i = setInterval(() => setProgress(p => Math.min(0.98, p + 0.003)), 80);
    return () => clearInterval(i);
  }, []);

  return (
    <div style={{ width: '100%', height: '100%', background: '#F6F8F8', display: 'flex', flexDirection: 'column' }}>
      <GLTopBar onBack={() => go('home')} center={
        <div className="gl-display" style={{ fontSize: 14, letterSpacing: '0.18em' }}>TRACK MY PASTA</div>
      } right={
        <button style={{ width: 32, height: 32, border: `1.5px solid ${GL.ink}`, display: 'grid', placeItems: 'center' }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={GL.ink} strokeWidth="2"><circle cx="12" cy="5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="12" cy="19" r="1.5"/></svg>
        </button>
      }/>

      <div style={{ flex: 1, overflowY: 'auto' }} className="gl-noscroll">
        {/* Map */}
        <div style={{ height: 280, position: 'relative', background: '#DDE3E3', overflow: 'hidden' }}>
          {/* coastline shapes */}
          <svg width="100%" height="100%" viewBox="0 0 400 280" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0 }}>
            <defs>
              <pattern id="gridBg" width="30" height="30" patternUnits="userSpaceOnUse">
                <path d="M30 0 L0 0 0 30" fill="none" stroke="#C6CDCD" strokeWidth="0.5"/>
              </pattern>
            </defs>
            <rect width="400" height="280" fill="url(#gridBg)"/>
            {/* land masses */}
            <path d="M20 30 Q 100 10 200 40 T 350 50 L 380 120 Q 360 200 300 230 T 150 260 Q 60 240 30 160 Z" fill="#EEF3F3" stroke="#AEB8B8"/>
            <path d="M100 120 Q 180 140 250 160 L 230 210 Q 150 200 110 170 Z" fill="#F6F8F8" stroke="#BDC7C7"/>
            {/* roads */}
            <path d="M40 80 Q 150 100 260 90" stroke="#B4BDBD" strokeWidth="2" fill="none" strokeDasharray="0"/>
            <path d="M80 200 Q 200 180 320 200" stroke="#B4BDBD" strokeWidth="2" fill="none"/>
            {/* labels */}
            {[['KARON BEACH', 80, 60],['KATA BEACH', 60, 120],['RAWAI BEACH', 180, 175],['CHALONG PIER', 230, 95],['PROMTHEP CAPE', 90, 230]].map(([t, x, y], i) => (
              <text key={i} x={x} y={y} fontSize="8" fontFamily="Inter" fontWeight="700" fill="#5A6868" letterSpacing="0.08em">{t}</text>
            ))}
            {/* route */}
            <path d="M 280 70 Q 260 130 230 165" stroke={GL.teal} strokeWidth="3" fill="none" strokeLinecap="round"/>
            {/* Destination */}
            <circle cx="230" cy="165" r="6" fill={GL.ink}/>
            {/* Truck moving along */}
            <g style={{ transform: `translate(${280 - 50 * progress}px, ${70 + 95 * progress}px)`, transition: 'transform .1s linear' }}>
              <rect x="-16" y="-12" width="32" height="22" fill={GL.ink} rx="2"/>
              <svg width="32" height="22" x="-16" y="-12" viewBox="0 0 32 22">
                <path d="M4 6 L4 14 L28 14 L28 10 L22 10 L22 6 Z" fill="#fff"/>
              </svg>
            </g>
          </svg>
          <div style={{ position: 'absolute', top: 16, left: 16, right: 16, display: 'flex', justifyContent: 'space-between' }}>
            <button onClick={() => go('confirmed')} style={{ width: 36, height: 36, background: '#fff', border: `1.5px solid ${GL.ink}`, display: 'grid', placeItems: 'center' }}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={GL.ink} strokeWidth="2.5"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
            </button>
            <button style={{ width: 36, height: 36, background: '#fff', border: `1.5px solid ${GL.ink}`, display: 'grid', placeItems: 'center' }}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={GL.ink} strokeWidth="2"><circle cx="12" cy="5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="12" cy="19" r="1.5"/></svg>
            </button>
          </div>
          <div style={{ position: 'absolute', top: '18%', left: '55%', background: GL.ink, color: '#fff', padding: '8px 10px', display: 'flex', alignItems: 'center', gap: 6 }}>
            <svg width="16" height="12" viewBox="0 0 24 16" fill={GL.teal}><path d="M2 0h14v8h4l2 4v2h-2a2 2 0 1 1-4 0H8a2 2 0 1 1-4 0H2z"/></svg>
            <span style={{ fontSize: 11, fontWeight: 800, letterSpacing: '0.08em' }}>2 mins away</span>
          </div>
        </div>

        <div style={{ padding: 16 }}>
          {/* En route card */}
          <div style={{ border: `2px solid ${GL.ink}`, background: '#fff', padding: 18, boxShadow: `4px 4px 0 ${GL.ink}`, marginBottom: 14 }}>
            <div style={{ width: 36, height: 4, borderRadius: 2, background: GL.line, margin: '0 auto 14px' }}/>
            <div style={{ textAlign: 'center', paddingBottom: 14, borderBottom: `1px solid ${GL.line}` }}>
              <div className="gl-display" style={{ fontSize: 32, fontStyle: 'italic', color: GL.ink }}>En Route</div>
            </div>
            <div style={{ textAlign: 'center', marginTop: 14, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10 }}>
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={GL.teal} strokeWidth="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
              <span className="gl-display" style={{ fontSize: 28, color: GL.ink }}>12:45 PM</span>
            </div>
            <div className="gl-kicker" style={{ color: GL.muted, textAlign: 'center', marginTop: 4 }}>Estimated Arrival</div>
          </div>

          {/* Driver */}
          <div style={{ border: `2px solid ${GL.ink}`, background: '#fff', padding: 14, boxShadow: `4px 4px 0 ${GL.ink}`, display: 'flex', alignItems: 'center', gap: 14, marginBottom: 14 }}>
            <div style={{ width: 56, height: 56, background: '#D5DADA', position: 'relative' }}>
              <div style={{ position: 'absolute', top: 2, left: 2, width: 6, height: 6, background: GL.teal }}/>
              <div style={{ position: 'absolute', top: 2, right: 2, width: 6, height: 6, background: GL.teal }}/>
              <svg width="100%" height="100%" viewBox="0 0 56 56"><circle cx="28" cy="22" r="10" fill="#8A9698"/><path d="M8 56 Q28 36 48 56" fill="#8A9698"/><path d="M15 30 Q28 42 41 30" stroke="#6A7878" strokeWidth="6" fill="none"/></svg>
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 10, fontWeight: 800, color: GL.teal, letterSpacing: '0.16em', textTransform: 'uppercase' }}>Your Driver</div>
              <div className="gl-display" style={{ fontSize: 20, color: GL.ink, marginTop: 2 }}>Somchai</div>
              <div style={{ fontSize: 11, color: GL.muted, marginTop: 2 }}>★ 4.9/5.0</div>
            </div>
            <button style={{ width: 44, height: 44, border: `1.5px solid ${GL.ink}`, display: 'grid', placeItems: 'center' }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={GL.ink} strokeWidth="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
            </button>
            <button style={{ width: 44, height: 44, background: GL.ink, display: 'grid', placeItems: 'center' }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="#fff"><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4 2h3a2 2 0 0 1 2 1.7c.1 1 .3 1.9.6 2.8a2 2 0 0 1-.5 2.1L7.9 9.8a16 16 0 0 0 6 6l1.2-1.2a2 2 0 0 1 2.1-.5c.9.3 1.8.5 2.8.6a2 2 0 0 1 1.7 2z"/></svg>
            </button>
          </div>

          {/* Progress bar */}
          <div style={{ border: `2px solid ${GL.ink}`, background: GL.ink, color: '#fff', padding: 16, marginBottom: 18 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
              {['Extruded', 'Boxed', 'On The Road'].map((s, i) => (
                <span key={s} style={{
                  fontSize: 10, fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase',
                  color: i === stage ? GL.teal : 'rgba(255,255,255,0.4)',
                  textDecoration: i < stage ? 'line-through' : 'none',
                }}>{s}</span>
              ))}
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
              {[0,1,2].map(i => (
                <React.Fragment key={i}>
                  <div style={{
                    width: 10, height: 10, borderRadius: '50%',
                    background: i <= stage ? GL.teal : 'rgba(255,255,255,0.2)',
                    boxShadow: i === stage ? `0 0 10px ${GL.teal}` : 'none',
                  }}/>
                  {i < 2 && <div style={{ flex: 1, height: 2, background: i < stage ? GL.teal : 'rgba(255,255,255,0.15)' }}/>}
                </React.Fragment>
              ))}
            </div>
            <div style={{ marginTop: 16, paddingTop: 12, borderTop: `1px solid rgba(255,255,255,0.1)`, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div>
                <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.5)' }}>Order #{app.orderNo}</div>
                <div style={{ fontSize: 13, marginTop: 4, fontWeight: 600 }}>{app.cart.length} items in your box</div>
              </div>
              <button style={{ color: GL.teal, fontSize: 11, fontWeight: 800, letterSpacing: '0.14em', textTransform: 'uppercase', borderBottom: `1px solid ${GL.teal}` }}>Details</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { GLCheckout, GLQRPayment, GLConfirmed, GLTrack });
