// Hawaiian Style — Checkout page components.
// Three-step flow:
//   0: Beach Bag + Customer Form
//   1: Payment selection (PromptPay / Card)
//   2: Aloha confirmation
//
// Cart is persisted to localStorage and shared with index.html via the
// `hws-cart-v1` key and a `hws-cart-changed` event so the Nav badge
// stays live across pages.

// Store open/close + shipping are now controlled from the Admin dashboard
// (store_settings table, read via /api/store). No code flag — toggle live in Admin.

// ============================================================
// CART STORAGE + HOOK
// ============================================================

const CART_KEY = 'hws-cart-v1';

// Normalize a stored cart-item image path to whatever the current page
// expects. We accept any of these stored forms and rebuild relative to
// the running document so a single localStorage entry survives across
// the project paths (ui_kits/marketing-site/), the handoff (assets/), or
// the bundled standalone version:
//   "assets/products/foo.png"
//   "assets/products/foo.png"
//   "products/foo.png"   (just-in-case legacy)
//   "foo.png"
const normalizeCartImg = (raw) => {
  if (!raw || typeof raw !== 'string') return raw;
  // Already a data: or absolute URL — leave alone.
  if (/^(data:|blob:|https?:)/.test(raw)) return raw;
  // Extract filename only
  const file = raw.split('/').pop();
  if (!file) return raw;
  // Probe the current page: where do OTHER product imgs live?
  // Look for any <img src="*assets/products/...png"> already in DOM, take its
  // path prefix. If none, fall back to 'assets/products/' (matches
  // ui_kits/marketing-site/ source location).
  try {
    const probe = document.querySelector('img[src*="assets/products/"]');
    if (probe) {
      const src = probe.getAttribute('src') || '';
      const m = src.match(/^(.*assets\/products\/)/);
      if (m) return m[1] + file;
    }
  } catch {}
  return 'assets/products/' + file;
};

const readCart = () => {
  try {
    const raw = localStorage.getItem(CART_KEY);
    const items = raw ? JSON.parse(raw) : [];
    return Array.isArray(items)
      ? items.map(it => ({ ...it, img: normalizeCartImg(it.img) }))
      : [];
  } catch { return []; }
};

const writeCart = (items) => {
  try {
    localStorage.setItem(CART_KEY, JSON.stringify(items));
    window.dispatchEvent(new CustomEvent('hws-cart-changed', { detail: items }));
  } catch {}
};

const useCart = () => {
  const { useState, useEffect, useCallback } = React;
  const [items, setItems] = useState(() => readCart());

  useEffect(() => {
    const onChange = (e) => setItems(e?.detail || readCart());
    const onStorage = (e) => { if (!e || e.key === CART_KEY) setItems(readCart()); };
    window.addEventListener('hws-cart-changed', onChange);
    window.addEventListener('storage', onStorage);
    return () => {
      window.removeEventListener('hws-cart-changed', onChange);
      window.removeEventListener('storage', onStorage);
    };
  }, []);

  const setQty = useCallback((id, qty) => {
    setItems(curr => {
      const next = curr.map(it => it.id === id ? { ...it, qty: Math.max(1, qty | 0) } : it);
      writeCart(next);
      return next;
    });
  }, []);

  const remove = useCallback((id) => {
    setItems(curr => {
      const next = curr.filter(it => it.id !== id);
      writeCart(next);
      return next;
    });
  }, []);

  const clear = useCallback(() => {
    writeCart([]);
    setItems([]);
  }, []);

  const subtotal = items.reduce((s, it) => s + (it.price * it.qty), 0);
  const totalQty = items.reduce((s, it) => s + it.qty, 0);

  return { items, setQty, remove, clear, subtotal, totalQty };
};

// Pre-seeded demo cart, used only when the user opens checkout cold (no items).
// Lets the design tell its story without a real shopping trip first.
const DEMO_CART = [
  { id: 'coconut-oil', name: 'Coconut Tanning Oil', cat: 'Tanning · 100ml · SPF 2',
    price: 259, qty: 2, img: 'assets/products/coconut-tanning-oil.png',
    gradient: 'linear-gradient(160deg, #F5C97B 0%, #D8721D 100%)' },
  { id: 'sunblock-50', name: 'Sunblock SPF 50', cat: 'Sunblock · 100ml · PA++++',
    price: 395, qty: 1, img: 'assets/products/sunblock-spf50.png',
    gradient: 'linear-gradient(160deg, #6E83A0 0%, #465975 100%)' },
  { id: 'after-sun', name: 'After Sun Lotion', cat: 'After Sun · 100ml',
    price: 245, qty: 1, img: 'assets/products/after-sun.png',
    gradient: 'linear-gradient(160deg, #FCD5B6 0%, #F4BE92 100%)' },
];

// ============================================================
// COUNTRIES (used by the "Other" searchable dropdown)
// ============================================================

const COUNTRIES = [
  'Australia', 'Austria', 'Bahrain', 'Bangladesh', 'Belgium', 'Brazil',
  'Brunei', 'Cambodia', 'Canada', 'Chile', 'China', 'Colombia',
  'Czech Republic', 'Denmark', 'Egypt', 'Finland', 'France', 'Germany',
  'Greece', 'Hong Kong', 'Hungary', 'Iceland', 'India', 'Indonesia',
  'Ireland', 'Israel', 'Italy', 'Japan', 'Jordan', 'Kazakhstan',
  'Kuwait', 'Laos', 'Lebanon', 'Luxembourg', 'Macau', 'Malaysia',
  'Maldives', 'Malta', 'Mexico', 'Mongolia', 'Morocco', 'Myanmar',
  'Nepal', 'Netherlands', 'New Zealand', 'Norway', 'Oman', 'Pakistan',
  'Philippines', 'Poland', 'Portugal', 'Qatar', 'Romania', 'Russia',
  'Saudi Arabia', 'Singapore', 'South Africa', 'South Korea', 'Spain',
  'Sri Lanka', 'Sweden', 'Switzerland', 'Taiwan', 'Tanzania', 'Turkey',
  'United Arab Emirates', 'United Kingdom', 'United States', 'Vietnam',
];

// ============================================================
// SMALL UI BITS
// ============================================================

// Bilingual field label. EN top, small TH below.
const FieldLabel = ({ en, th, required }) => (
  <div style={{ marginBottom: 8 }}>
    <span style={{
      fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 11,
      letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--brown)',
    }}>{en}{required && <span style={{ color: 'var(--orange)' }}> *</span>}</span>
    {th && <span style={{
      display: 'block', fontFamily: 'var(--font-thai)', fontSize: 12,
      color: 'var(--brown-soft)', marginTop: 2, opacity: 0.85,
    }}>{th}</span>}
  </div>
);

const inputBase = {
  width: '100%', padding: '13px 16px', borderRadius: 12,
  border: '1.8px solid rgba(61, 47, 35, 0.22)',
  background: 'var(--paper)', color: 'var(--brown)',
  fontFamily: 'var(--font-body)', fontWeight: 500, fontSize: 15,
  outline: 'none', transition: 'border-color .15s, box-shadow .15s',
  boxSizing: 'border-box',
};

const TextField = ({ value, onChange, placeholder, type = 'text', ...rest }) => {
  const { useState } = React;
  const [focused, setFocused] = useState(false);
  return (
    <input
      type={type}
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      onFocus={() => setFocused(true)}
      onBlur={() => setFocused(false)}
      style={{
        ...inputBase,
        borderColor: focused ? 'var(--orange)' : inputBase.border.split(' ').pop(),
        boxShadow: focused ? '0 0 0 4px rgba(216, 114, 29, 0.15)' : 'none',
      }}
      {...rest}
    />
  );
};

// Step indicator pills (1 / 2 / 3).
const StepIndicator = ({ step, isQuote }) => {
  const steps = isQuote ? [
    { label: 'Beach Bag', th: 'ตะกร้า' },
    { label: 'Quote', th: 'ขอใบราคา' },
    { label: 'Sent!', th: 'ส่งคำขอแล้ว' },
  ] : [
    { label: 'Beach Bag', th: 'ตะกร้า' },
    { label: 'Payment', th: 'ชำระเงิน' },
    { label: 'Aloha!', th: 'สำเร็จ' },
  ];
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap',
      marginTop: 24,
    }}>
      {steps.map((s, i) => {
        const active = i === step;
        const done = i < step;
        return (
          <React.Fragment key={s.label}>
            <div style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '8px 16px 8px 8px', borderRadius: 999,
              background: active ? 'var(--brown)' : done ? 'var(--sun)' : 'transparent',
              color: active ? 'var(--paper)' : 'var(--brown)',
              border: !active && !done ? '1.5px solid rgba(61, 47, 35, 0.25)' : 'none',
              transition: 'all .25s',
            }}>
              <span style={{
                width: 28, height: 28, borderRadius: '50%',
                background: active ? 'var(--sun)' : done ? 'var(--brown)' : 'rgba(61,47,35,0.1)',
                color: active ? 'var(--brown)' : done ? 'var(--sun)' : 'var(--brown)',
                display: 'grid', placeItems: 'center',
                fontFamily: 'var(--font-display)', fontSize: 14,
              }}>
                {done ? '✓' : (i + 1)}
              </span>
              <div style={{ display: 'flex', flexDirection: 'column', lineHeight: 1 }}>
                <span style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase' }}>
                  {s.label}
                </span>
                <span style={{ fontFamily: 'var(--font-thai)', fontSize: 10, marginTop: 2, opacity: 0.85 }}>
                  {s.th}
                </span>
              </div>
            </div>
            {i < steps.length - 1 && (
              <span style={{ width: 28, height: 2, background: 'rgba(61,47,35,0.18)', display: 'inline-block' }} />
            )}
          </React.Fragment>
        );
      })}
    </div>
  );
};

// ============================================================
// HERO
// ============================================================

const CheckoutHero = ({ step, itemCount, isQuote }) => (
  <header style={{ maxWidth: 1320, margin: '0 auto', padding: '48px 36px 0' }}>
    <Eyebrow>Checkout · Pack the beach bag · ★ since 1995</Eyebrow>
    <h1 style={{
      fontFamily: 'var(--font-display)', fontWeight: 400,
      fontSize: 'clamp(56px, 7vw, 120px)', lineHeight: 0.92,
      letterSpacing: '0.005em', textTransform: 'uppercase',
      color: 'var(--brown)', margin: '20px 0 0',
    }}>
      {step === 2 ? (
        isQuote ? (
          <>Quote on the <span style={{
            fontFamily: 'var(--font-script)', textTransform: 'none', color: 'var(--orange)',
            fontSize: '0.78em', display: 'inline-block', transform: 'rotate(-3deg)',
          }}>way.</span></>
        ) : (
          <>You{'\u2019'}re <span style={{
            fontFamily: 'var(--font-script)', textTransform: 'none', color: 'var(--orange)',
            fontSize: '0.78em', display: 'inline-block', transform: 'rotate(-3deg)',
          }}>all set.</span></>
        )
      ) : step === 1 ? (
        <>How are we <span style={{
          fontFamily: 'var(--font-script)', textTransform: 'none', color: 'var(--orange)',
          fontSize: '0.78em', display: 'inline-block', transform: 'rotate(-3deg)',
        }}>paying</span>?</>
      ) : (
        <>Pack the <span style={{
          fontFamily: 'var(--font-script)', textTransform: 'none', color: 'var(--orange)',
          fontSize: '0.78em', display: 'inline-block', transform: 'rotate(-3deg)',
        }}>beach</span> bag.</>
      )}
    </h1>
    <p style={{ fontSize: 17, color: 'var(--brown-soft)', maxWidth: 580, marginTop: 18, lineHeight: 1.55 }}>
      {step === 2
        ? isQuote
          ? 'Thanks for your order! International shipping is quoted by hand — we’ll email your shipping quote and a secure payment link within 24 hours.'
          : 'Your bottles are on their way. We sent a confirmation to your email — sunscreen, summer, signed and sealed.'
        : step === 1
        ? 'PromptPay scans instantly, cards work everywhere. Pick whatever’s easiest.'
        : itemCount > 0
          ? `${itemCount} bottle${itemCount === 1 ? '' : 's'} ready to ship. Tell us where to send them.`
          : 'Your bag is empty — grab a bottle from the shop and we’ll get you packed up.'}
    </p>
    <StepIndicator step={step} isQuote={isQuote} />
  </header>
);

// ============================================================
// CART SUMMARY (right column, sticky)
// ============================================================

const QtyButton = ({ children, onClick, disabled }) => (
  <button
    onClick={onClick}
    disabled={disabled}
    style={{
      width: 28, height: 28, borderRadius: 8,
      border: '1.5px solid rgba(61,47,35,0.25)',
      background: 'var(--paper)', color: 'var(--brown)',
      fontFamily: 'var(--font-display)', fontSize: 16,
      cursor: disabled ? 'not-allowed' : 'pointer',
      opacity: disabled ? 0.4 : 1,
      display: 'grid', placeItems: 'center',
      transition: 'background .15s, border-color .15s',
    }}
    onMouseOver={e => !disabled && (e.currentTarget.style.background = 'var(--sun)')}
    onMouseOut={e => !disabled && (e.currentTarget.style.background = 'var(--paper)')}
  >{children}</button>
);

const CartItemRow = ({ item, onQty, onRemove, locked }) => (
  <div style={{
    display: 'grid', gridTemplateColumns: '76px 1fr auto', gap: 14,
    padding: '16px 0', borderBottom: '1.5px solid rgba(61,47,35,0.12)',
    alignItems: 'center',
  }}>
    {/* Product thumbnail — sized to its grid column so it stays inside the
        cell when the column collapses on mobile (was a hardcoded 76×76 box
        that overflowed into the qty stepper at narrow widths). */}
    <div style={{
      width: '100%', aspectRatio: '1 / 1', maxWidth: 76,
      borderRadius: 14,
      background: item.gradient || 'var(--beige)',
      display: 'grid', placeItems: 'center', overflow: 'hidden',
    }}>
      <img src={item.img} alt={item.name}
        style={{ width: '80%', height: '80%', objectFit: 'contain',
          filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.25))' }} />
    </div>
    <div style={{ minWidth: 0 }}>
      <div style={{
        fontFamily: 'var(--font-display)', fontSize: 16, letterSpacing: '0.02em',
        textTransform: 'uppercase', color: 'var(--brown)', lineHeight: 1.1,
      }}>{item.name}</div>
      <div className="hws-cart-item-cat" style={{
        fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.14em',
        textTransform: 'uppercase', color: 'var(--brown-soft)', marginTop: 4,
      }}>{item.cat}</div>
      {!locked && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 10 }}>
          <QtyButton onClick={() => onQty(item.id, item.qty - 1)} disabled={item.qty <= 1}>−</QtyButton>
          <span style={{ fontFamily: 'var(--font-display)', fontSize: 15, minWidth: 20, textAlign: 'center', color: 'var(--brown)' }}>
            {item.qty}
          </span>
          <QtyButton onClick={() => onQty(item.id, item.qty + 1)}>+</QtyButton>
          <button onClick={() => onRemove(item.id)} style={{
            background: 'transparent', border: 'none', color: 'var(--brown-soft)',
            fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 10,
            letterSpacing: '0.14em', textTransform: 'uppercase', cursor: 'pointer',
            padding: '4px 8px', marginLeft: 4,
          }}
            onMouseOver={e => e.currentTarget.style.color = 'var(--aloha)'}
            onMouseOut={e => e.currentTarget.style.color = 'var(--brown-soft)'}
          >Remove</button>
        </div>
      )}
      {locked && (
        <div style={{ fontFamily: 'var(--font-body)', fontSize: 12, color: 'var(--brown-soft)', marginTop: 8 }}>
          Qty {item.qty}
        </div>
      )}
    </div>
    <div style={{ textAlign: 'right' }}>
      <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, color: 'var(--brown)', letterSpacing: '0.02em' }}>
        ฿{(item.price * item.qty).toLocaleString()}
      </div>
      {item.qty > 1 && (
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9.5, letterSpacing: '0.12em', color: 'var(--brown-soft)', marginTop: 2 }}>
          ฿{item.price} ea
        </div>
      )}
    </div>
  </div>
);

// Compute Thai shipping from settings + subtotal (mirrors lib/validate calcShipping).
const computeShipping = (subtotal, settings) => {
  const flat = settings?.shipping_flat ?? 50;
  const threshold = settings?.free_shipping_threshold;
  if (threshold != null && subtotal >= threshold) return 0;
  return flat;
};

const ShippingLine = ({ country, subtotal = 0, settings }) => {
  if (!country) {
    return (
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        padding: '14px 0', borderTop: '1.5px dashed rgba(61,47,35,0.18)',
      }}>
        <div>
          <div style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13, textTransform: 'uppercase', letterSpacing: '0.14em', color: 'var(--brown)' }}>Shipping</div>
          <div style={{ fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)', marginTop: 2 }}>ค่าจัดส่ง</div>
        </div>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--brown-soft)', letterSpacing: '0.12em', textTransform: 'uppercase' }}>
          Pick a country →
        </div>
      </div>
    );
  }
  if (country === 'Thailand') {
    const ship = computeShipping(subtotal, settings);
    const threshold = settings?.free_shipping_threshold;
    return (
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        padding: '14px 0', borderTop: '1.5px dashed rgba(61,47,35,0.18)',
      }}>
        <div>
          <div style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13, textTransform: 'uppercase', letterSpacing: '0.14em', color: 'var(--brown)' }}>Shipping · Thailand</div>
          <div style={{ fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)', marginTop: 2 }}>
            {ship === 0
              ? 'จัดส่งฟรี · 2–4 วัน'
              : (threshold != null
                  ? `จัดส่งในไทย · ฟรีเมื่อซื้อครบ ฿${threshold.toLocaleString()}`
                  : 'จัดส่งในประเทศไทย · 2–4 วัน')}
          </div>
        </div>
        <div style={{ fontFamily: 'var(--font-display)', fontSize: 16, color: ship === 0 ? 'var(--aloe)' : 'var(--brown)', letterSpacing: '0.02em' }}>
          {ship === 0 ? 'FREE' : `฿${ship.toLocaleString()}`}
        </div>
      </div>
    );
  }
  // International — quote on request
  return (
    <div style={{
      padding: '14px 0', borderTop: '1.5px dashed rgba(61,47,35,0.18)',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13, textTransform: 'uppercase', letterSpacing: '0.14em', color: 'var(--brown)' }}>Shipping · International</div>
          <div style={{ fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)', marginTop: 2 }}>จัดส่งต่างประเทศ · เรากำลังขอราคา</div>
        </div>
        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.14em',
          textTransform: 'uppercase', color: 'var(--orange)',
          background: 'rgba(216,114,29,0.1)', padding: '5px 10px', borderRadius: 999,
        }}>To be quoted</div>
      </div>
      <p style={{ fontSize: 12, color: 'var(--brown-soft)', marginTop: 8, lineHeight: 1.5, margin: 0, marginTop: 8 }}>
        Place your order and we{'\u2019'}ll email a shipping quote within 24 hours before charging the card.
      </p>
    </div>
  );
};

const CartSummary = ({ cart, country, locked, settings }) => {
  const isTH = country === 'Thailand';
  const shipping = isTH ? computeShipping(cart.subtotal, settings) : 0;
  const total = cart.subtotal + shipping;
  return (
    <aside style={{
      background: 'var(--paper-soft)',
      border: '2px solid var(--brown)', borderRadius: 24,
      padding: '28px 28px 24px',
      boxShadow: '0 6px 0 var(--brown)',
      position: 'sticky', top: 96,
      alignSelf: 'start',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
        <h2 style={{
          fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 32,
          letterSpacing: '0.02em', textTransform: 'uppercase', color: 'var(--brown)', margin: 0,
        }}>
          Beach Bag <span style={{ fontFamily: 'var(--font-script)', textTransform: 'none', color: 'var(--orange)', fontSize: '0.6em' }}>{cart.items.length} item{cart.items.length === 1 ? '' : 's'}</span>
        </h2>
      </div>
      <div style={{ fontFamily: 'var(--font-thai)', fontSize: 12, color: 'var(--brown-soft)', marginBottom: 6 }}>
        สรุปรายการสั่งซื้อ
      </div>

      {cart.items.length === 0 ? (
        <div style={{
          padding: '32px 0 12px', textAlign: 'center',
        }}>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 24, color: 'var(--brown-soft)', textTransform: 'uppercase', letterSpacing: '0.02em' }}>
            Empty bag.
          </div>
          <div style={{ fontFamily: 'var(--font-script)', fontSize: 22, color: 'var(--orange)', marginTop: 2 }}>
            grab a bottle.
          </div>
          <a href="/#bestsellers" style={{ display: 'inline-block', marginTop: 18 }}>
            <Pill variant="sun" size="sm" as="span">Browse the shop →</Pill>
          </a>
        </div>
      ) : (
        <>
          <div style={{ marginTop: 14 }}>
            {cart.items.map(item => (
              <CartItemRow key={item.id}
                item={item}
                onQty={cart.setQty}
                onRemove={cart.remove}
                locked={locked}
              />
            ))}
          </div>

          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            padding: '14px 0',
          }}>
            <div>
              <div style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13, textTransform: 'uppercase', letterSpacing: '0.14em', color: 'var(--brown)' }}>Subtotal</div>
              <div style={{ fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)', marginTop: 2 }}>ราคารวมสินค้า</div>
            </div>
            <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, color: 'var(--brown)', letterSpacing: '0.02em' }}>
              ฿{cart.subtotal.toLocaleString()}
            </div>
          </div>

          <ShippingLine country={country} subtotal={cart.subtotal} settings={settings} />

          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
            padding: '18px 0 6px', borderTop: '2px solid var(--brown)', marginTop: 8,
          }}>
            <div>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 22, letterSpacing: '0.02em', textTransform: 'uppercase', color: 'var(--brown)' }}>Total</div>
              <div style={{ fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)' }}>ยอดรวมทั้งหมด</div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 32, color: 'var(--orange)', lineHeight: 1, letterSpacing: '0.005em' }}>
                ฿{total.toLocaleString()}
              </div>
              {!isTH && country && (
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9.5, letterSpacing: '0.14em', color: 'var(--brown-soft)', textTransform: 'uppercase', marginTop: 4 }}>
                  + shipping quote
                </div>
              )}
            </div>
          </div>

          {/* "Reef-safe · we got you" stamp */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 18, paddingTop: 14, borderTop: '1px dashed rgba(61,47,35,0.18)' }}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--aloe-deep)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M20 6L9 17l-5-5"/>
            </svg>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--brown-soft)' }}>
              Secure checkout · 30-day returns · packed by hand
            </span>
          </div>
        </>
      )}
    </aside>
  );
};

// ============================================================
// COUNTRY SEARCH (for "Other" selection)
// ============================================================

const CountrySearch = ({ value, onChange }) => {
  const { useState, useRef, useEffect } = React;
  const [query, setQuery] = useState(value || '');
  const [open, setOpen] = useState(false);
  const wrapRef = useRef(null);

  useEffect(() => { setQuery(value || ''); }, [value]);

  useEffect(() => {
    const onDoc = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, []);

  const filtered = query
    ? COUNTRIES.filter(c => c.toLowerCase().includes(query.toLowerCase()))
    : COUNTRIES;

  return (
    <div ref={wrapRef} style={{ position: 'relative' }}>
      <input
        type="text"
        value={query}
        onChange={(e) => { setQuery(e.target.value); setOpen(true); onChange(''); }}
        onFocus={() => setOpen(true)}
        placeholder="Search countries… (e.g. Japan, UK, UAE)"
        style={{ ...inputBase, paddingRight: 40 }}
      />
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--brown-soft)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
        style={{ position: 'absolute', right: 14, top: 17 }}>
        <circle cx="11" cy="11" r="7"/><line x1="20" y1="20" x2="17" y2="17"/>
      </svg>
      {open && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 6px)', left: 0, right: 0,
          maxHeight: 220, overflowY: 'auto',
          background: 'var(--paper-soft)',
          border: '1.8px solid var(--brown)', borderRadius: 12,
          boxShadow: '0 18px 40px -16px rgba(61, 47, 35, 0.35), 0 4px 0 rgba(61, 47, 35, 0.10)',
          zIndex: 20, padding: 6,
        }}>
          {filtered.length === 0 ? (
            <div style={{ padding: '14px 12px', fontSize: 13, color: 'var(--brown-soft)', fontStyle: 'italic' }}>
              No matches. Type your country and we{'\u2019'}ll add it to our list.
            </div>
          ) : filtered.map(c => (
            <button key={c} onClick={() => { onChange(c); setQuery(c); setOpen(false); }}
              style={{
                display: 'block', width: '100%', textAlign: 'left',
                padding: '10px 12px', borderRadius: 8,
                background: c === value ? 'var(--sun)' : 'transparent',
                border: 'none', cursor: 'pointer',
                fontFamily: 'var(--font-body)', fontSize: 14, color: 'var(--brown)',
              }}
              onMouseOver={e => { if (c !== value) e.currentTarget.style.background = 'rgba(247,223,77,0.4)'; }}
              onMouseOut={e => { if (c !== value) e.currentTarget.style.background = 'transparent'; }}
            >{c}</button>
          ))}
        </div>
      )}
    </div>
  );
};

// ============================================================
// CUSTOMER FORM
// ============================================================

const CustomerForm = ({ form, setForm, onContinue, cartItems, hasErrors }) => {
  const set = (k) => (v) => setForm(f => ({ ...f, [k]: v }));
  const empty = !cartItems || cartItems.length === 0;

  return (
    <div style={{
      background: 'var(--paper-soft)', border: '2px solid rgba(61,47,35,0.10)',
      borderRadius: 24, padding: '36px 36px 32px',
      boxShadow: '0 4px 0 rgba(61, 47, 35, 0.06)',
    }}>
      <Eyebrow>★ Step 01 · Contact & shipping</Eyebrow>
      <h2 style={{
        fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 36,
        letterSpacing: '0.02em', textTransform: 'uppercase', color: 'var(--brown)',
        margin: '14px 0 4px', lineHeight: 0.95,
      }}>
        Tell us where to send it.
      </h2>
      <p style={{ fontFamily: 'var(--font-thai)', fontSize: 13, color: 'var(--brown-soft)', margin: 0, marginBottom: 24 }}>
        กรอกข้อมูลสำหรับจัดส่ง — เก็บเป็นความลับ ไม่แชร์กับใคร
      </p>

      {/* Contact */}
      <div style={{ marginBottom: 28 }}>
        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.18em',
          textTransform: 'uppercase', color: 'var(--brown-soft)', marginBottom: 16,
        }}>· Contact</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
          <div>
            <FieldLabel en="First name" th="ชื่อ" required />
            <TextField value={form.firstName} onChange={set('firstName')} placeholder="Pim" autoComplete="given-name" />
          </div>
          <div>
            <FieldLabel en="Last name" th="นามสกุล" required />
            <TextField value={form.lastName} onChange={set('lastName')} placeholder="Tantawanich" autoComplete="family-name" />
          </div>
          <div>
            <FieldLabel en="Email address" th="อีเมล" required />
            <TextField type="email" value={form.email} onChange={set('email')} placeholder="aloha@example.com" autoComplete="email" />
          </div>
          <div>
            <FieldLabel en="Phone number" th="เบอร์โทรศัพท์" required />
            <TextField type="tel" value={form.tel} onChange={set('tel')} placeholder="+66 81 234 5678" autoComplete="tel" />
          </div>
        </div>
      </div>

      {/* Shipping */}
      <div style={{ marginBottom: 24 }}>
        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.18em',
          textTransform: 'uppercase', color: 'var(--brown-soft)', marginBottom: 16,
        }}>· Shipping address</div>

        {/* Country radio */}
        <FieldLabel en="Country" th="ประเทศ" required />
        <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginBottom: 8 }}>
          {[
            { v: 'Thailand', label: 'Thailand', th: 'ไทย · ฿50 shipping' },
            { v: 'Other',    label: 'Other',    th: 'ต่างประเทศ · ขอใบเสนอราคา' },
          ].map(opt => {
            const active = form.countryKind === opt.v;
            return (
              <button key={opt.v} type="button"
                onClick={() => setForm(f => ({ ...f, countryKind: opt.v, otherCountry: opt.v === 'Other' ? f.otherCountry : '' }))}
                style={{
                  flex: 1, minWidth: 200,
                  padding: '16px 18px', borderRadius: 14,
                  border: `2px solid ${active ? 'var(--brown)' : 'rgba(61,47,35,0.18)'}`,
                  background: active ? 'var(--sun)' : 'var(--paper)',
                  cursor: 'pointer', textAlign: 'left',
                  boxShadow: active ? '0 4px 0 var(--brown)' : 'none',
                  transition: 'all .15s',
                  display: 'flex', alignItems: 'center', gap: 12,
                }}>
                <span style={{
                  width: 22, height: 22, borderRadius: '50%',
                  border: '2px solid var(--brown)',
                  background: active ? 'var(--brown)' : 'transparent',
                  display: 'grid', placeItems: 'center', flexShrink: 0,
                }}>
                  {active && <span style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--sun)' }} />}
                </span>
                <div>
                  <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, color: 'var(--brown)', letterSpacing: '0.02em', textTransform: 'uppercase', lineHeight: 1 }}>
                    {opt.label}
                  </div>
                  <div style={{ fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)', marginTop: 4 }}>{opt.th}</div>
                </div>
              </button>
            );
          })}
        </div>

        {/* Country search appears when Other selected */}
        {form.countryKind === 'Other' && (
          <div style={{ marginTop: 16, padding: '18px 20px', background: 'rgba(247,223,77,0.18)',
            border: '1.5px dashed rgba(216,114,29,0.5)', borderRadius: 14 }}>
            <FieldLabel en="Which country?" th="เลือกประเทศ" required />
            <CountrySearch
              value={form.otherCountry}
              onChange={(v) => setForm(f => ({ ...f, otherCountry: v }))}
            />
            <p style={{ fontSize: 12, color: 'var(--brown-soft)', marginTop: 10, lineHeight: 1.55, margin: 0, marginTop: 10 }}>
              International orders: we{'\u2019'}ll email you a shipping quote within 24 hours before any payment is taken.
            </p>
          </div>
        )}

        {/* Address — country-specific.
            Thailand needs the full Thai structure (ตำบล/อำเภอ/จังหวัด);
            international keeps the simpler City + Zip. */}
        <div style={{ marginTop: 20 }}>
          <FieldLabel en="Shipping address" th="ที่อยู่จัดส่ง" required />
          <TextField value={form.address} onChange={set('address')}
            placeholder={form.countryKind === 'Thailand' ? '123 ซอยสุขุมวิท 22 ถนนสุขุมวิท' : '123 Main Street, Apt 4'}
            autoComplete="street-address" />
        </div>

        {form.countryKind === 'Thailand' ? (
          <>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 16 }}>
              <div>
                <FieldLabel en="Subdistrict" th="ตำบล / แขวง" required />
                <TextField value={form.subdistrict} onChange={set('subdistrict')} placeholder="คลองเตย" autoComplete="address-level3" />
              </div>
              <div>
                <FieldLabel en="District" th="อำเภอ / เขต" required />
                <TextField value={form.district} onChange={set('district')} placeholder="คลองเตย" autoComplete="address-level2" />
              </div>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 16, marginTop: 16 }}>
              <div>
                <FieldLabel en="Province" th="จังหวัด" required />
                <TextField value={form.province} onChange={set('province')} placeholder="กรุงเทพมหานคร" autoComplete="address-level1" />
              </div>
              <div>
                <FieldLabel en="Zip code" th="รหัสไปรษณีย์" required />
                <TextField value={form.zip} onChange={set('zip')} placeholder="10110" autoComplete="postal-code" />
              </div>
            </div>
          </>
        ) : (
          <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 16, marginTop: 16 }}>
            <div>
              <FieldLabel en="City" th="เมือง" required />
              <TextField value={form.city} onChange={set('city')} placeholder="Singapore" autoComplete="address-level2" />
            </div>
            <div>
              <FieldLabel en="Zip / Postal code" th="รหัสไปรษณีย์" required />
              <TextField value={form.zip} onChange={set('zip')} placeholder="018989" autoComplete="postal-code" />
            </div>
          </div>
        )}
      </div>

      {/* Newsletter */}
      <label style={{
        display: 'flex', alignItems: 'flex-start', gap: 12, cursor: 'pointer',
        padding: '14px 16px', borderRadius: 12,
        background: 'rgba(247,223,77,0.18)',
        border: '1.5px solid rgba(216,114,29,0.25)',
      }}>
        <input type="checkbox"
          checked={form.newsletter}
          onChange={(e) => setForm(f => ({ ...f, newsletter: e.target.checked }))}
          style={{
            width: 18, height: 18, accentColor: 'var(--orange)',
            marginTop: 2, flexShrink: 0, cursor: 'pointer',
          }} />
        <div>
          <span style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13, letterSpacing: '0.08em', color: 'var(--brown)', textTransform: 'uppercase' }}>
            Postcards from the beach
          </span>
          <span style={{ display: 'block', fontSize: 12, color: 'var(--brown-soft)', marginTop: 4, lineHeight: 1.55 }}>
            One summer-ready email a month — new bottle drops, retro reissues, the occasional sunset photo. Unsubscribe anytime.
          </span>
          <span style={{ display: 'block', fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)', marginTop: 2 }}>
            สมัครรับข่าวสารและส่วนลดพิเศษ
          </span>
        </div>
      </label>

      {hasErrors && (
        <div style={{
          marginTop: 18, padding: '12px 16px', borderRadius: 12,
          background: 'rgba(200, 54, 44, 0.08)', border: '1.5px solid rgba(200,54,44,0.3)',
          color: 'var(--aloha)', fontFamily: 'var(--font-body)', fontWeight: 600, fontSize: 13,
        }}>
          Please fill out every starred field before continuing.
          <span style={{ display: 'block', fontFamily: 'var(--font-thai)', fontSize: 12, marginTop: 2, opacity: 0.85 }}>
            กรุณากรอกข้อมูลที่จำเป็นทั้งหมดก่อนดำเนินการต่อ
          </span>
        </div>
      )}

      <div style={{ marginTop: 28, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 14 }}>
        <a href="/#bestsellers" style={{
          fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 12,
          letterSpacing: '0.14em', textTransform: 'uppercase',
          color: 'var(--brown-soft)', textDecoration: 'none',
        }}
          onMouseOver={e => e.currentTarget.style.color = 'var(--orange)'}
          onMouseOut={e => e.currentTarget.style.color = 'var(--brown-soft)'}
        >← Keep shopping</a>
        <Pill as="button" type="button" variant="sun" size="lg" onClick={onContinue}
          disabled={empty}
          style={empty ? { opacity: 0.4, cursor: 'not-allowed' } : null}
        >
          {form.countryKind === 'Other' ? 'Request shipping quote →' : 'Pay with Omise →'}
        </Pill>
      </div>
    </div>
  );
};

// ============================================================
// PAYMENT STEP
// ============================================================

const PaymentMethodCard = ({ id, title, th, sub, icon, active, onSelect, disabled, badge }) => (
  <button
    type="button"
    onClick={() => !disabled && onSelect(id)}
    disabled={disabled}
    style={{
      width: '100%', textAlign: 'left',
      padding: '20px 22px', borderRadius: 18,
      border: `2px solid ${active ? 'var(--brown)' : 'rgba(61,47,35,0.18)'}`,
      background: active ? 'var(--sun)' : 'var(--paper)',
      cursor: disabled ? 'not-allowed' : 'pointer',
      opacity: disabled ? 0.45 : 1,
      boxShadow: active ? '0 4px 0 var(--brown)' : 'none',
      transition: 'all .18s', display: 'flex', alignItems: 'center', gap: 18,
    }}>
    <span style={{
      width: 22, height: 22, borderRadius: '50%',
      border: '2px solid var(--brown)', flexShrink: 0,
      background: active ? 'var(--brown)' : 'transparent',
      display: 'grid', placeItems: 'center',
    }}>
      {active && <span style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--sun)' }} />}
    </span>
    <div style={{
      width: 52, height: 52, borderRadius: 12, flexShrink: 0,
      background: active ? 'var(--paper)' : 'var(--paper-soft)',
      border: '1.5px solid rgba(61,47,35,0.18)',
      display: 'grid', placeItems: 'center', color: 'var(--brown)',
    }}>{icon}</div>
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
        <span style={{ fontFamily: 'var(--font-display)', fontSize: 20, letterSpacing: '0.02em', textTransform: 'uppercase', color: 'var(--brown)', lineHeight: 1 }}>
          {title}
        </span>
        {badge && (
          <span style={{
            fontFamily: 'var(--font-mono)', fontSize: 9, letterSpacing: '0.14em',
            textTransform: 'uppercase', color: 'var(--paper)',
            background: 'var(--orange)', padding: '3px 8px', borderRadius: 999,
          }}>{badge}</span>
        )}
      </div>
      <div style={{ fontFamily: 'var(--font-thai)', fontSize: 11, color: 'var(--brown-soft)', marginTop: 4 }}>{th}</div>
      <div style={{ fontSize: 13, color: 'var(--brown-soft)', marginTop: 6, lineHeight: 1.45 }}>{sub}</div>
    </div>
  </button>
);

// QR placeholder block — visual only, not a real QR.
const PromptPayQR = ({ total }) => (
  <div style={{
    background: 'var(--paper)', borderRadius: 18,
    border: '2px dashed rgba(61, 47, 35, 0.35)',
    padding: '28px', textAlign: 'center',
    display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16,
  }}>
    <div style={{
      fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.18em',
      textTransform: 'uppercase', color: 'var(--brown-soft)',
    }}>Scan with any Thai bank app</div>
    <div style={{
      width: 200, height: 200, padding: 12, background: 'var(--paper)',
      border: '2px solid var(--brown)', borderRadius: 14,
      display: 'grid', gridTemplateColumns: 'repeat(20, 1fr)', gap: 0,
    }}>
      {Array.from({ length: 400 }).map((_, i) => {
        // Pseudo-QR pattern (deterministic from index)
        const dot = ((i * 73) % 7 < 3) || (i < 60 && i % 20 < 6) || (i >= 340 && i % 20 < 6) || (i % 20 >= 14 && i < 60);
        return <span key={i} style={{ width: '100%', aspectRatio: '1/1', background: dot ? 'var(--brown)' : 'transparent' }} />;
      })}
    </div>
    <div>
      <div style={{ fontFamily: 'var(--font-display)', fontSize: 28, color: 'var(--brown)', letterSpacing: '0.005em' }}>
        ฿{total.toLocaleString()}
      </div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.14em', color: 'var(--brown-soft)', textTransform: 'uppercase', marginTop: 4 }}>
        PromptPay · Hawaiian Style Co.
      </div>
    </div>
    <div style={{ fontFamily: 'var(--font-script)', fontSize: 22, color: 'var(--orange)', lineHeight: 1 }}>
      thanks, friend.
    </div>
  </div>
);

// Card form — visual only, not a real card processor.
const CardForm = ({ cardForm, setCardForm }) => {
  const set = (k) => (v) => setCardForm(f => ({ ...f, [k]: v }));
  return (
    <div style={{ background: 'var(--paper)', borderRadius: 18, padding: '24px', border: '1.5px solid rgba(61,47,35,0.18)' }}>
      <FieldLabel en="Cardholder name" th="ชื่อผู้ถือบัตร" required />
      <TextField value={cardForm.name} onChange={set('name')} placeholder="As shown on the card" />
      <div style={{ marginTop: 16 }}>
        <FieldLabel en="Card number" th="หมายเลขบัตร" required />
        <TextField value={cardForm.number} onChange={set('number')} placeholder="1234 5678 9012 3456" />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 16 }}>
        <div>
          <FieldLabel en="Expiry" th="วันหมดอายุ" required />
          <TextField value={cardForm.exp} onChange={set('exp')} placeholder="MM / YY" />
        </div>
        <div>
          <FieldLabel en="CVC" th="รหัส 3 หลัก" required />
          <TextField value={cardForm.cvc} onChange={set('cvc')} placeholder="123" />
        </div>
      </div>
    </div>
  );
};

const PaymentStep = ({ country, total, onBack, onPay, processing }) => {
  const { useState } = React;
  const [method, setMethod] = useState(country === 'Thailand' ? 'promptpay' : 'card');
  const [cardForm, setCardForm] = useState({ name: '', number: '', exp: '', cvc: '' });

  const isTH = country === 'Thailand';

  return (
    <div style={{
      background: 'var(--paper-soft)', border: '2px solid rgba(61,47,35,0.10)',
      borderRadius: 24, padding: '36px 36px 32px',
      boxShadow: '0 4px 0 rgba(61, 47, 35, 0.06)',
    }}>
      <Eyebrow>★ Step 02 · Payment</Eyebrow>
      <h2 style={{
        fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 36,
        letterSpacing: '0.02em', textTransform: 'uppercase', color: 'var(--brown)',
        margin: '14px 0 4px', lineHeight: 0.95,
      }}>
        Choose how to pay.
      </h2>
      <p style={{ fontFamily: 'var(--font-thai)', fontSize: 13, color: 'var(--brown-soft)', margin: 0, marginBottom: 24 }}>
        เลือกวิธีชำระเงิน
      </p>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <PaymentMethodCard
          id="promptpay"
          title="PromptPay"
          th="พร้อมเพย์ · สแกน QR"
          sub="Scan a QR with any Thai bank app. Confirmed instantly."
          badge={isTH ? 'Easiest in TH' : null}
          disabled={!isTH}
          active={method === 'promptpay'}
          onSelect={setMethod}
          icon={
            <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/>
              <rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="3" height="3"/>
              <rect x="18" y="14" width="3" height="3"/><rect x="14" y="18" width="3" height="3"/>
            </svg>
          }
        />
        <PaymentMethodCard
          id="card"
          title="Credit or debit card"
          th="บัตรเครดิต / เดบิต"
          sub="Visa, Mastercard, JCB. Charged once your shipping is confirmed."
          active={method === 'card'}
          onSelect={setMethod}
          icon={
            <svg width="26" height="20" viewBox="0 0 24 18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <rect x="1" y="1" width="22" height="16" rx="2"/><line x1="1" y1="6" x2="23" y2="6"/>
              <line x1="5" y1="12" x2="9" y2="12"/>
            </svg>
          }
        />
      </div>

      {/* Method-specific surface */}
      <div style={{ marginTop: 24 }}>
        {method === 'promptpay' && <PromptPayQR total={total} />}
        {method === 'card' && <CardForm cardForm={cardForm} setCardForm={setCardForm} />}
      </div>

      <div style={{ marginTop: 28, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 14 }}>
        <button onClick={onBack} style={{
          background: 'transparent', border: 'none', cursor: 'pointer',
          fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 12,
          letterSpacing: '0.14em', textTransform: 'uppercase',
          color: 'var(--brown-soft)', padding: '4px 0',
        }}
          onMouseOver={e => e.currentTarget.style.color = 'var(--orange)'}
          onMouseOut={e => e.currentTarget.style.color = 'var(--brown-soft)'}
        >← Edit shipping info</button>
        <Pill as="button" type="button" variant="sun" size="lg"
          onClick={() => onPay(method)}
          disabled={processing}
        >
          {processing
            ? 'Processing…'
            : isTH
              ? `Pay ฿${total.toLocaleString()} →`
              : 'Place order · we’ll quote shipping →'}
        </Pill>
      </div>
    </div>
  );
};

// ============================================================
// CONFIRMATION
// ============================================================

const ConfirmationStep = ({ order, onShopAgain }) => (
  <div style={{
    background: 'var(--brown)', borderRadius: 32, color: 'var(--paper)',
    padding: '56px 48px', position: 'relative', overflow: 'hidden',
  }}>
    <div style={{ position: 'absolute', bottom: -120, right: -90, width: 360, height: 360, borderRadius: '50%',
      background: 'radial-gradient(circle, rgba(247, 223, 77, 0.32) 0%, transparent 70%)', pointerEvents: 'none' }} />
    <div style={{ position: 'absolute', top: 30, right: 30, opacity: 0.18 }}>
      <Doodle.Palm size={140} color="var(--paper)" opacity={1} />
    </div>
    <div style={{ position: 'absolute', top: 40, left: 40 }}>
      <VintageStamp year="OK" label={order.isQuote ? 'quote sent' : 'order placed'} script={order.isQuote ? 'thank you!' : 'aloha!'} size={110} rotate={-12} />
    </div>

    <div style={{ position: 'relative', maxWidth: 680, marginLeft: 'auto' }}>
      <Eyebrow color="rgba(252, 213, 182, 0.85)">{order.isQuote ? '★ Quotation requested' : '★ Step 03 · Confirmation'}</Eyebrow>
      <h2 style={{
        fontFamily: 'var(--font-display)', fontWeight: 400,
        fontSize: 'clamp(48px, 5.6vw, 80px)', lineHeight: 0.92,
        letterSpacing: '0.005em', textTransform: 'uppercase',
        margin: '14px 0 0', color: 'var(--paper)',
      }}>
        Aloha, <span style={{
          fontFamily: 'var(--font-script)', textTransform: 'none', color: 'var(--sun)',
          fontSize: '0.78em', display: 'inline-block', transform: 'rotate(-3deg)',
        }}>{order.firstName || 'friend'}</span>.<br/>
        {order.isQuote ? 'Your quote is on the way.' : 'Your bag is packed.'}
      </h2>
      <p style={{ fontSize: 17, opacity: 0.88, marginTop: 18, lineHeight: 1.6, maxWidth: 540 }}>
        {order.isQuote ? (
          <>Thanks for ordering with Hawaiian Style! International shipping is quoted by hand. We{'\u2019'}re calculating your courier cost now and will send a shipping quote + a secure payment link to <strong style={{ color: 'var(--sun)' }}>{order.email || 'your email'}</strong> within 24 hours. Approve it and we{'\u2019'}ll pack your bag straight away.</>
        ) : (
          <>Payment received via <strong style={{ color: 'var(--sun)' }}>Omise</strong>. We sent the receipt to <strong style={{ color: 'var(--sun)' }}>{order.email || 'your email'}</strong>. Bottles ship within one working day; the courier will text you when they{'\u2019'}re on the move.</>
        )}
      </p>

      <div style={{
        marginTop: 32, padding: '20px 24px', borderRadius: 18,
        background: 'rgba(252, 213, 182, 0.08)',
        border: '1.5px solid rgba(252, 213, 182, 0.2)',
        display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 18,
      }}>
        {(order.isQuote ? [
          { lbl: 'Quotation no.', val: order.id },
          { lbl: 'Status',        val: 'Pending quote' },
          { lbl: 'Quote sent to', val: order.country || 'Overseas' },
        ] : [
          { lbl: 'Order number',  val: order.id },
          { lbl: 'Payment',       val: order.methodLabel },
          { lbl: 'Shipping',      val: order.country === 'Thailand' ? '฿50 · 2–4 days' : 'Quote within 24h' },
        ]).map(b => (
          <div key={b.lbl}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase', opacity: 0.65 }}>
              {b.lbl}
            </div>
            <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, color: 'var(--sun)', marginTop: 4, letterSpacing: '0.02em', textTransform: 'uppercase' }}>
              {b.val}
            </div>
          </div>
        ))}
      </div>

      <div style={{ marginTop: 28, display: 'flex', gap: 14, flexWrap: 'wrap' }}>
        <Pill variant="yellow" href="/">Keep shopping</Pill>
        <Pill variant="ghost-paper" href="/faq">Questions? FAQ</Pill>
      </div>
    </div>
  </div>
);

// ============================================================
// ORDERING-CLOSED SCREEN — shown when STORE_OPEN === false
// ============================================================
const OrderingClosed = () => (
  <>
    <CheckoutHero step={0} itemCount={0} isQuote={false} />
    <section style={{ maxWidth: 760, margin: '0 auto', padding: '40px 36px 96px' }}>
      <div style={{
        background: 'var(--paper-soft)', border: '2px solid var(--brown)',
        borderRadius: 24, padding: '56px 44px', textAlign: 'center',
        boxShadow: '8px 8px 0 var(--orange)',
      }}>
        <div style={{ fontSize: 64, lineHeight: 1, marginBottom: 18 }}>🌅</div>
        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.22em',
          textTransform: 'uppercase', color: 'var(--orange)', marginBottom: 14,
        }}>Almost there</div>
        <h2 style={{
          fontFamily: 'var(--font-display)', fontSize: 'clamp(30px, 5vw, 48px)',
          lineHeight: 1.0, letterSpacing: '0.01em', textTransform: 'uppercase',
          color: 'var(--brown)', margin: '0 0 18px',
        }}>
          Online ordering<br/>
          <span style={{ fontFamily: 'var(--font-script)', textTransform: 'none',
            color: 'var(--orange)', fontSize: '0.82em', display: 'inline-block',
            transform: 'rotate(-3deg)' }}>opens very soon.</span>
        </h2>
        <p style={{ fontSize: 16, color: 'var(--brown-soft)', lineHeight: 1.6,
          maxWidth: 460, margin: '0 auto 12px' }}>
          เรากำลังเปิดระบบสั่งซื้อออนไลน์เร็วๆ นี้ — ระหว่างนี้ช้อปได้ที่ร้านค้าออนไลน์ของเราด้านล่างครับ
        </p>
        <p style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.14em',
          textTransform: 'uppercase', color: 'var(--brown-soft)', margin: '0 0 32px' }}>
          We're putting the finishing touches on checkout.
        </p>
        <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', justifyContent: 'center' }}>
          <Pill variant="sun" size="lg" href="https://shopee.co.th/hawaiianstyleofficial"
            target="_blank" rel="noopener noreferrer">Shop on Shopee →</Pill>
          <Pill variant="ghost-paper" size="lg" href="/">Back to home</Pill>
        </div>
      </div>
    </section>
  </>
);

// ============================================================
// CHECKOUT PAGE — main orchestrator
// ============================================================

const CheckoutPage = () => {
  const { useState, useEffect, useMemo } = React;
  const cart = useCart();

  // Seed demo cart on first visit so the page tells its story.
  useEffect(() => {
    if (readCart().length === 0) {
      writeCart(DEMO_CART);
    }
  }, []); // eslint-disable-line

  const [step, setStep] = useState(0);
  const [form, setForm] = useState({
    firstName: '', lastName: '', email: '', tel: '',
    countryKind: 'Thailand', otherCountry: '',
    address: '', subdistrict: '', district: '', province: '', city: '', zip: '',
    newsletter: true,
  });
  const [showErrors, setShowErrors] = useState(false);
  const [redirecting, setRedirecting] = useState(false);
  const [order, setOrder] = useState(null);

  // Store open/close + shipping from DB (/api/store). null = still loading.
  // On fetch failure we default to CLOSED so we never expose checkout we can't confirm is open.
  const [storeConfig, setStoreConfig] = useState(null);
  useEffect(() => {
    fetch('/api/store')
      .then(r => r.json())
      .then(data => setStoreConfig(data.settings || { store_open: false }))
      .catch(() => setStoreConfig({ store_open: false }));
  }, []);

  // [SOP-SEC-M02] Handle return from Omise — verify order exists in DB before showing confirmation.
  // Omise redirects to /checkout?order=HWS-xxxx&confirmed=1 after the customer pays.
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const orderId   = params.get('order');
    const confirmed = params.get('confirmed');
    if (!orderId || confirmed !== '1') return;

    const pending = (() => {
      try { return JSON.parse(localStorage.getItem('hws-pending-order') || 'null'); } catch { return null; }
    })();

    // Verify order exists in DB — prevents fake ?order=xxx&confirmed=1 from showing confirmation
    fetch(`/api/verify-order?id=${encodeURIComponent(orderId)}`)
      .then(r => r.json())
      .then(data => {
        if (!data.found) { window.history.replaceState({}, '', '/checkout'); return; }
        setOrder({
          id:          data.id,
          firstName:   data.firstName || (pending?.orderId === orderId ? pending.firstName : ''),
          email:       pending?.orderId === orderId ? pending.email : '',
          country:     'Thailand',
          total:       data.total || (pending?.orderId === orderId ? pending.total : 0),
          methodLabel: 'Omise',
        });
        localStorage.removeItem('hws-pending-order');
        cart.clear();
        setStep(2);
        window.history.replaceState({}, '', '/checkout');
        window.scrollTo({ top: 0, behavior: 'smooth' });
      })
      .catch(() => { window.history.replaceState({}, '', '/checkout'); });
  }, []); // eslint-disable-line

  const country = form.countryKind === 'Thailand' ? 'Thailand' : (form.otherCountry || null);
  const shipping = country === 'Thailand' ? computeShipping(cart.subtotal, storeConfig) : 0;
  const total = cart.subtotal + shipping;

  const validate = () => {
    // Required fields differ by destination: Thai addresses need the full
    // ตำบล/อำเภอ/จังหวัด structure; international just needs City.
    const base = ['firstName', 'lastName', 'email', 'tel', 'address', 'zip'];
    const required = form.countryKind === 'Thailand'
      ? [...base, 'subdistrict', 'district', 'province']
      : [...base, 'city'];
    if (required.some(k => !form[k].trim())) return false;
    if (form.countryKind === 'Other' && !form.otherCountry) return false;
    if (!/^\S+@\S+\.\S+$/.test(form.email)) return false;
    return true;
  };

  const handleContinue = async () => {
    if (!validate()) { setShowErrors(true); window.scrollTo({ top: 0, behavior: 'smooth' }); return; }
    setShowErrors(false);

    // ── International path: POST quote → email sent by backend → show confirmation ──
    if (form.countryKind === 'Other') {
      try {
        const res = await fetch('/api/quote-request', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ cart: cart.items, form }),
        });
        const data = await res.json();
        if (!res.ok) throw new Error(data.error || 'Request failed');
        setOrder({
          id: data.quoteId,
          firstName: form.firstName,
          email: form.email,
          country, total: cart.subtotal,
          isQuote: true,
        });
        cart.clear();
        setStep(2);
        window.scrollTo({ top: 0, behavior: 'smooth' });
      } catch (err) {
        console.error('[handleContinue] quote-request:', err);
        alert('Unable to submit your request. Please try again.');
      }
      return;
    }

    // ── Thai path: POST to backend → create Omise charge → redirect to Omise ──
    setRedirecting(true);

    try {
      const res = await fetch('/api/create-payment', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ cart: cart.items, form }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Payment failed');
      // Save context to localStorage so we can restore the confirmation
      // screen when Omise redirects back to checkout.html?order=...&confirmed=1
      localStorage.setItem('hws-pending-order', JSON.stringify({
        orderId: data.orderId,
        firstName: form.firstName,
        email: form.email,
        total,
      }));
      window.location.href = data.authorizeUri;
    } catch (err) {
      console.error('[handleContinue] create-payment:', err);
      setRedirecting(false);
      alert('Payment failed. Please try again or contact us.');
    }
  };

  // A returning paid customer (post-Omise) must always see their confirmation,
  // even if the store was closed in the meantime.
  const showingConfirmation = step === 2 && !!order;

  // Still loading store state — avoid flashing the wrong screen.
  if (storeConfig === null && !showingConfirmation) {
    return (
      <>
        <CheckoutHero step={0} itemCount={cart.totalQty} isQuote={false} />
        <section style={{ maxWidth: 760, margin: '0 auto', padding: '80px 36px', textAlign: 'center' }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.2em',
            textTransform: 'uppercase', color: 'var(--brown-soft)' }}>Loading…</div>
        </section>
      </>
    );
  }

  // Ordering closed (toggled live from Admin) — show "coming soon".
  if (storeConfig && !storeConfig.store_open && !showingConfirmation) {
    return <OrderingClosed />;
  }

  return (
    <>
      <CheckoutHero step={step} itemCount={cart.totalQty} isQuote={!!(order && order.isQuote)} />

      <section style={{ maxWidth: 1320, margin: '0 auto', padding: '40px 36px 96px' }}>
        <div style={{
          display: 'grid', gridTemplateColumns: '1.35fr 1fr', gap: 32,
          alignItems: 'start',
        }}>
          {/* LEFT — step content */}
          <div>
            {step === 0 && (
              <CustomerForm
                form={form}
                setForm={setForm}
                onContinue={handleContinue}
                cartItems={cart.items}
                hasErrors={showErrors}
              />
            )}
            {step === 2 && order && (
              <ConfirmationStep order={order} />
            )}
          </div>

          {/* RIGHT — cart summary (sticky) */}
          <CartSummary
            cart={cart}
            country={country}
            locked={step > 0 || cart.items.length === 0 || step === 2}
            settings={storeConfig}
          />
        </div>
      </section>

      {/* Omise redirect overlay — simulates the hand-off to Omise's hosted
          payment page and the return to our thank-you page. */}
      {redirecting && (
        <div style={{
          position: 'fixed', inset: 0, zIndex: 2000,
          background: 'rgba(61, 47, 35, 0.86)', backdropFilter: 'blur(6px)',
          display: 'grid', placeItems: 'center', padding: 24,
          animation: 'hwsFadeIn .18s ease-out',
        }}>
          <div style={{
            background: 'var(--paper)', color: 'var(--brown)',
            borderRadius: 22, padding: '40px 44px', maxWidth: 420, width: '100%',
            textAlign: 'center', border: '2px solid var(--brown)',
            boxShadow: '8px 8px 0 var(--orange)',
          }}>
            <div style={{
              width: 56, height: 56, margin: '0 auto 20px', borderRadius: '50%',
              border: '5px solid rgba(216,114,29,0.25)', borderTopColor: 'var(--orange)',
              animation: 'hwsSpin 0.8s linear infinite',
            }} />
            <div style={{
              fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.22em',
              textTransform: 'uppercase', color: 'var(--orange)', marginBottom: 10,
            }}>Secure payment</div>
            <div style={{
              fontFamily: 'var(--font-display)', fontSize: 26, lineHeight: 1.05,
              textTransform: 'uppercase', color: 'var(--brown)', margin: '0 0 8px',
            }}>Redirecting to Omise…</div>
            <p style={{ fontSize: 14, lineHeight: 1.55, color: 'var(--brown-soft)', margin: 0 }}>
              Taking you to Omise{'\u2019'}s secure page to complete payment.
              <span style={{ display: 'block', fontFamily: 'var(--font-thai)', fontSize: 12, marginTop: 4 }}>
                กำลังพาไปหน้าชำระเงินที่ปลอดภัยของ Omise…
              </span>
            </p>
          </div>
          <style>{`
            @keyframes hwsFadeIn { from { opacity: 0 } to { opacity: 1 } }
            @keyframes hwsSpin { to { transform: rotate(360deg) } }
          `}</style>
        </div>
      )}
    </>
  );
};

Object.assign(window, {
  CheckoutPage, CartSummary, CustomerForm, PaymentStep, ConfirmationStep,
  useCart, readCart, writeCart, CART_KEY,
});
