// store.jsx — MagicalKitten storefront prototype: Home / Shop / Product + cart.
// Themed live from the shared theme (useMKTheme). Uses Tile + Seal.
// Exports to window: StoreApp.

const MK_PRODUCTS = [
  { id: 'kitten', name: 'The Rainbow Kitten', cat: 'Signature', price: 2900, tile: { suit: 'cat', value: 1, rainbow: true },
    blurb: 'Our signature set, led by the hand-painted rainbow cat that gives the house its name. A full 144-tile set for the collector who plays.',
    materials: ['Hand-poured resin body', 'Painted in six colours', 'Solid brass case', 'Wool-felt lining'] },
  { id: 'vermilion', name: 'The Vermilion', cat: 'Honors', price: 2800, tile: { suit: 'dragon', value: 'red' },
    blurb: 'The red dragon, rendered in deep cinnabar. A house set finished in the colour of luck and celebration.',
    materials: ['Hand-poured resin body', 'Cinnabar lacquer accents', 'Solid brass case', 'Wool-felt lining'] },
  { id: 'ivory', name: 'The Ivory Characters', cat: 'Characters', price: 2400, tile: { suit: 'char', value: 5 },
    blurb: 'The classic wàn suit, brushed by hand in red and ink. Quiet, timeless, made to be handed down.',
    materials: ['Hand-poured resin body', 'Painted suits', 'Linen roll', 'Brass corners'] },
  { id: 'lotus', name: 'Lotus Circles', cat: 'Circles', price: 2400, tile: { suit: 'dot', value: 7 },
    blurb: 'The dots suit as a study in symmetry — concentric circles in jade, sapphire and ruby.',
    materials: ['Hand-poured resin body', 'Painted dots', 'Linen roll', 'Brass corners'] },
  { id: 'sparrow', name: 'The Sparrow', cat: 'Bamboo', price: 2400, tile: { suit: 'bamboo', value: 1 },
    blurb: 'Bamboo, led by the one-bamboo sparrow — the most painterly tile in the deck.',
    materials: ['Hand-poured resin body', 'Painted bamboo', 'Linen roll', 'Brass corners'] },
  { id: 'garden', name: 'Jade Garden', cat: 'Bamboo', price: 2500, tile: { suit: 'bamboo', value: 6 },
    blurb: 'A spring edition in greens, with painted flower tiles to round out the set.',
    materials: ['Hand-poured resin body', 'Painted bamboo & flowers', 'Linen roll', 'Brass corners'] },
  { id: 'four-winds', name: 'The Four Winds', cat: 'Honors', price: 2600, tile: { suit: 'wind', value: 'E' },
    blurb: 'East, south, west, north — the honour tiles, set in clean ink on ivory.',
    materials: ['Hand-poured resin body', 'Ink-painted honours', 'Solid brass case', 'Wool-felt lining'] },
  { id: 'heirloom', name: 'The Heirloom', cat: 'Signature', price: 4800, tile: { suit: 'cat', value: 1, rainbow: true },
    blurb: 'Made to order over eight weeks. Your monogram seal, a hardwood case, and the rainbow kitten throughout.',
    materials: ['Made to order', 'Monogrammed seal', 'Hardwood & brass case', 'Numbered, edition of 50'] },
];
const MK_FILTERS = ['All', 'Signature', 'Circles', 'Bamboo', 'Characters', 'Honors'];

function money(n) { return '$' + n.toLocaleString(); }

// responsive helper
function useIsNarrow(bp = 820) {
  const [n, setN] = React.useState(typeof window !== 'undefined' && window.innerWidth < bp);
  React.useEffect(() => {
    const f = () => setN(window.innerWidth < bp);
    f(); window.addEventListener('resize', f);
    return () => window.removeEventListener('resize', f);
  }, [bp]);
  return n;
}

// Production photography slot.
// Renders the real image at img/<id>.png. To use your own photo, replace that
// file (any web image format works — keep the same filename, or change MK_IMG_EXT).
// A tasteful placeholder ships for every id so the site looks finished on day one.
// If an image is missing, a styled fallback box is shown instead of a broken icon.
const MK_IMG_DIR = 'img';
const MK_IMG_EXT = 'png';
function ImageSlot({ id, w, h, radius = 12, placeholder = 'Photograph', style }) {
  const [failed, setFailed] = React.useState(false);
  const dims = {
    width: typeof w === 'number' ? w + 'px' : w,
    height: typeof h === 'number' ? h + 'px' : h,
  };
  if (failed) {
    return (
      <div style={{ ...dims, borderRadius: radius, border: '1px dashed rgba(122,33,23,0.45)',
        background: 'linear-gradient(160deg,#f4ecdd,#e6dac2)', display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: '#8a7257', fontSize: 12, letterSpacing: '0.16em', textTransform: 'uppercase', textAlign: 'center', padding: 16, ...style }}>
        {placeholder}
      </div>
    );
  }
  return (
    <img src={`${MK_IMG_DIR}/${id}.${MK_IMG_EXT}`} alt={placeholder} loading="lazy" onError={() => setFailed(true)}
      style={{ display: 'block', ...dims, objectFit: 'cover', borderRadius: radius, ...style }} />
  );
}

function StoreEnso({ color }) {
  return (
    <svg viewBox="0 0 400 400" style={{ position: 'absolute', top: '50%', left: '50%', width: 340, height: 340, transform: 'translate(-50%,-50%)', pointerEvents: 'none' }}>
      <path d="M252 64 C150 26 56 108 56 212 C56 322 162 374 244 352 C326 330 366 248 334 172 C314 126 270 104 233 114"
        fill="none" stroke={color} strokeWidth="20" strokeLinecap="round" opacity="0.92" />
      <path d="M233 114 C224 116 216 120 210 126" fill="none" stroke={color} strokeWidth="6.5" strokeLinecap="round" opacity="0.55" />
    </svg>
  );
}

function TButton({ t, children, onClick, kind = 'solid', style }) {
  const base = { cursor: 'pointer', border: 'none', font: 'inherit', fontSize: 12.5, letterSpacing: '0.14em', textTransform: 'uppercase',
    padding: '15px 30px', transition: 'transform .2s, opacity .2s, background .2s', borderRadius: 2 };
  const skin = kind === 'solid'
    ? { background: t.button, color: t.buttonText }
    : { background: 'transparent', color: t.accent, boxShadow: `inset 0 0 0 1px ${t.line}` };
  return (
    <button onClick={onClick} style={{ ...base, ...skin, ...style }}
      onMouseEnter={(e) => (e.currentTarget.style.transform = 'translateY(-2px)')}
      onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}>{children}</button>
  );
}

function StoreHeader({ t, view, onNav, cartCount, onCart }) {
  const narrow = useIsNarrow(720);
  const link = (id, label) => (
    <a className="v1-link" href="#" onClick={(e) => { e.preventDefault(); onNav(id); }}
      style={{ color: view === id ? t.accent : t.soft, textDecoration: 'none', fontWeight: view === id ? 600 : 400 }}>{label}</a>
  );
  const navLinks = (
    <div style={{ display: 'flex', gap: narrow ? 20 : 26, fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', justifyContent: 'center', flexWrap: 'wrap' }}>
      {link('home', 'Home')}{link('shop', 'Shop')}{link('bespoke', 'Bespoke')}{link('about', 'About')}
    </div>
  );
  const logo = (
    <div onClick={() => onNav('home')} style={{ display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer', justifyContent: 'center' }}>
      <Seal chars={['貓']} fill={t.sealFill} ink={t.sealInk} size={28} rotate={-6} />
      <div style={{ fontSize: 13, letterSpacing: '0.34em', fontWeight: 500, paddingLeft: '0.34em', color: t.accent }}>MAGICAL KITTEN</div>
    </div>
  );
  const bag = (
    <button onClick={onCart} style={{ cursor: 'pointer', border: 'none', background: 'transparent', color: t.accent, fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', display: 'flex', alignItems: 'center', gap: 8 }}>
      Bag
      <span style={{ minWidth: 20, height: 20, padding: '0 6px', borderRadius: 10, background: t.button, color: t.buttonText, fontSize: 11, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', letterSpacing: 0 }}>{cartCount}</span>
    </button>
  );
  if (narrow) {
    return (
      <div style={{ position: 'sticky', top: 0, zIndex: 20, background: t.bgFlat, borderBottom: `1px solid ${t.faint}` }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '14px 20px' }}>
          {logo}{bag}
        </div>
        <div style={{ padding: '0 20px 12px' }}>{navLinks}</div>
      </div>
    );
  }
  return (
    <div style={{ position: 'sticky', top: 0, zIndex: 20, background: t.bgFlat, borderBottom: `1px solid ${t.faint}` }}>
      <div style={{ maxWidth: 1180, margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr auto 1fr', alignItems: 'center', padding: '20px 32px' }}>
        <div style={{ justifySelf: 'start' }}>{navLinks}</div>
        {logo}
        <div style={{ display: 'flex', justifyContent: 'flex-end' }}>{bag}</div>
      </div>
    </div>
  );
}

function SealDivider({ t, char = '福' }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 18, maxWidth: 1180, margin: '0 auto', padding: '0 32px' }}>
      <div style={{ flex: 1, height: 1, background: t.line }} />
      <Seal chars={[char]} fill={t.sealFill} ink={t.sealInk} size={36} rotate={0} />
      <div style={{ flex: 1, height: 1, background: t.line }} />
    </div>
  );
}

function ProductCard({ t, p, onOpen, onAdd }) {
  return (
    <div className="v15-card" style={{ background: t.cardBg, border: `1px solid ${t.line}`, borderRadius: 10, padding: 18, cursor: 'pointer', display: 'flex', flexDirection: 'column' }}
      onClick={() => onOpen(p.id)}>
      <div style={{ height: 200, borderRadius: 8, background: t.faint, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <Tile {...p.tile} w={112} />
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginTop: 18 }}>
        <div style={{ fontFamily: t.titleFont, fontSize: 22, color: t.accent }}>{p.name}</div>
        <div style={{ fontSize: 14, color: t.soft }}>{money(p.price)}</div>
      </div>
      <div style={{ fontSize: 10.5, letterSpacing: '0.16em', textTransform: 'uppercase', color: t.soft, marginTop: 7 }}>{p.cat}</div>
      <div style={{ flex: 1 }} />
      <button onClick={(e) => { e.stopPropagation(); onAdd(p.id); }}
        style={{ marginTop: 18, cursor: 'pointer', border: `1px solid ${t.line}`, background: 'transparent', color: t.accent, padding: '11px', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', borderRadius: 2, transition: 'background .2s' }}
        onMouseEnter={(e) => { e.currentTarget.style.background = t.button; e.currentTarget.style.color = t.buttonText; e.currentTarget.style.borderColor = t.button; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = t.accent; e.currentTarget.style.borderColor = t.line; }}>Add to bag</button>
    </div>
  );
}

function HomeView({ t, onNav, onOpen, onAdd }) {
  const narrow = useIsNarrow(820);
  const featured = ['kitten', 'vermilion', 'lotus'].map((id) => MK_PRODUCTS.find((p) => p.id === id));
  return (
    <div>
      <div style={{ position: 'relative', maxWidth: 1180, margin: '0 auto', padding: narrow ? '40px 22px 30px' : '64px 32px 40px', textAlign: 'center' }}>
        {t.brackets && [['top', 'left'], ['top', 'right']].map(([v, h], i) => (
          <div key={i} style={{ position: 'absolute', [v]: 24, [h]: 28, width: 26, height: 26, [`border${v[0].toUpperCase()}${v.slice(1)}`]: `2px solid ${t.line}`, [`border${h[0].toUpperCase()}${h.slice(1)}`]: `2px solid ${t.line}` }} />
        ))}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 16, marginBottom: 22 }}>
          <span style={{ height: 1, width: 56, background: t.line }} />
          <span style={{ fontSize: 11, letterSpacing: '0.36em', textTransform: 'uppercase', color: t.soft }}>Est. 1924 · Reissued 2026</span>
          <span style={{ height: 1, width: 56, background: t.line }} />
        </div>
        <h1 style={{ fontFamily: t.titleFont, fontSize: 'clamp(40px, 8vw, 74px)', lineHeight: 1.04, fontWeight: 600, margin: 0, color: t.accent }}>The Vermilion Parlour</h1>
        <p style={{ maxWidth: 460, margin: '20px auto 0', fontSize: 14.5, lineHeight: 1.8, color: t.soft }}>
          Mahjong in the grand manner — hand-painted, sealed and signed. The geometry of the age it first dazzled the world, in the colour of luck.
        </p>
        <div style={{ position: 'relative', display: 'inline-block', margin: '34px 0 8px', padding: narrow ? '20px 30px' : '30px 60px' }}>
          <StoreEnso color={t.ensoColor} />
          <div style={{ position: 'relative', display: 'flex', alignItems: 'flex-end', justifyContent: 'center', gap: 14, height: 210 }}>
            <Tile suit="dragon" value="red" w={narrow ? 64 : 80} tilt={-8} style={{ alignSelf: 'center' }} />
            <Tile suit="cat" value={1} w={narrow ? 100 : 126} rainbow />
            <Tile suit="bamboo" value={1} w={narrow ? 64 : 80} tilt={8} style={{ alignSelf: 'center' }} />
          </div>
        </div>
        <div style={{ marginTop: 18 }}><TButton t={t} onClick={() => onNav('shop')}>Shop the collection</TButton></div>
      </div>

      <div style={{ padding: '30px 0 10px' }}><SealDivider t={t} /></div>

      <div style={{ maxWidth: 1180, margin: '0 auto', padding: '40px 32px 50px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 32 }}>
          <div style={{ fontFamily: t.titleFont, fontSize: 30, color: t.accent }}>The Collection</div>
          <a className="v1-link" href="#" onClick={(e) => { e.preventDefault(); onNav('shop'); }} style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: t.accent, textDecoration: 'none' }}>View all →</a>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 24 }}>
          {featured.map((p) => <ProductCard key={p.id} t={t} p={p} onOpen={onOpen} onAdd={onAdd} />)}
        </div>
      </div>

      {/* lifestyle photography */}
      {window.LifestyleBand && <window.LifestyleBand t={t} />}

      {/* house teaser */}
      <div style={{ maxWidth: 1180, margin: '0 auto', padding: '10px 32px 90px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: narrow ? '1fr' : '1fr 1fr', gap: 18 }}>
          {[{ k: 'The Artist', d: 'One hand, one brush, every tile. Meet the maker behind the house.', go: 'about', char: '藝' },
            { k: 'Bespoke', d: 'Your colours, your characters, your seal — a set made only for you.', go: 'bespoke', char: '訂' }].map((c) => (
            <div key={c.go} onClick={() => onNav(c.go)} style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 20, background: t.cardBg, border: `1px solid ${t.line}`, borderRadius: 12, padding: '28px 30px' }}>
              <Seal chars={[c.char]} fill={t.sealFill} ink={t.sealInk} size={48} rotate={-6} />
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: t.titleFont, fontSize: 26, color: t.accent }}>{c.k}</div>
                <div style={{ fontSize: 13.5, lineHeight: 1.6, color: t.soft, marginTop: 6 }}>{c.d}</div>
              </div>
              <span style={{ color: t.accent, fontSize: 20 }}>→</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function ShopView({ t, onOpen, onAdd }) {
  const [filter, setFilter] = React.useState('All');
  const list = filter === 'All' ? MK_PRODUCTS : MK_PRODUCTS.filter((p) => p.cat === filter);
  return (
    <div style={{ maxWidth: 1180, margin: '0 auto', padding: '54px 32px 90px' }}>
      <div style={{ textAlign: 'center', marginBottom: 30 }}>
        <h1 style={{ fontFamily: t.titleFont, fontSize: 52, fontWeight: 600, margin: 0, color: t.accent }}>The Collection</h1>
        <p style={{ fontSize: 14, color: t.soft, marginTop: 10 }}>Eight hand-painted sets. Each made to order in our atelier.</p>
      </div>
      <div style={{ display: 'flex', justifyContent: 'center', flexWrap: 'wrap', gap: 10, marginBottom: 40 }}>
        {MK_FILTERS.map((f) => (
          <button key={f} onClick={() => setFilter(f)} style={{ cursor: 'pointer', padding: '9px 18px', borderRadius: 999, fontSize: 12, letterSpacing: '0.06em',
            border: `1px solid ${filter === f ? t.accent : t.line}`, background: filter === f ? t.button : 'transparent', color: filter === f ? t.buttonText : t.soft, transition: 'all .2s' }}>{f}</button>
        ))}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(270px, 1fr))', gap: 24 }}>
        {list.map((p) => <ProductCard key={p.id} t={t} p={p} onOpen={onOpen} onAdd={onAdd} />)}
      </div>
    </div>
  );
}

function ProductView({ t, p, onAdd, onNav }) {
  const narrow = useIsNarrow(820);
  const [qty, setQty] = React.useState(1);
  const suitThumbs = [{ suit: 'dot', value: 3 }, { suit: 'bamboo', value: 1 }, { suit: 'char', value: 6 }, { suit: 'dragon', value: 'red' }, { suit: 'cat', value: 1, rainbow: true }];
  return (
    <div style={{ maxWidth: 1180, margin: '0 auto', padding: '34px 32px 90px' }}>
      <a className="v1-link" href="#" onClick={(e) => { e.preventDefault(); onNav('shop'); }} style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: t.soft, textDecoration: 'none' }}>← Back to the collection</a>
      <div style={{ display: 'grid', gridTemplateColumns: narrow ? '1fr' : '1fr 1fr', gap: narrow ? 32 : 56, alignItems: 'center', marginTop: 24 }}>
        <div style={{ position: 'relative', borderRadius: 12, background: t.cardBg, border: `1px solid ${t.line}`, padding: '50px 30px 40px', textAlign: 'center' }}>
          {t.brackets && [['top', 'left'], ['top', 'right'], ['bottom', 'left'], ['bottom', 'right']].map(([v, h], i) => (
            <div key={i} style={{ position: 'absolute', [v]: 14, [h]: 14, width: 20, height: 20, [`border${v[0].toUpperCase()}${v.slice(1)}`]: `2px solid ${t.line}`, [`border${h[0].toUpperCase()}${h.slice(1)}`]: `2px solid ${t.line}` }} />
          ))}
          <div style={{ position: 'relative', display: 'inline-block', padding: '10px 40px' }}>
            <StoreEnso color={t.ensoColor} />
            <div style={{ position: 'relative', height: 230, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Tile {...p.tile} w={150} />
            </div>
          </div>
          <div style={{ display: 'flex', justifyContent: 'center', gap: 10, marginTop: 18 }}>
            {suitThumbs.map((s, i) => <Tile key={i} {...s} w={44} lift={false} />)}
          </div>
        </div>
        <div>
          <div style={{ fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase', color: t.soft }}>{p.cat}</div>
          <h1 style={{ fontFamily: t.titleFont, fontSize: 50, fontWeight: 600, margin: '8px 0 0', color: t.accent }}>{p.name}</h1>
          <div style={{ fontSize: 22, color: t.soft, marginTop: 12 }}>{money(p.price)}</div>
          <p style={{ fontSize: 15, lineHeight: 1.8, color: t.soft, marginTop: 20, maxWidth: 440 }}>{p.blurb}</p>
          <div style={{ margin: '24px 0', borderTop: `1px solid ${t.line}`, paddingTop: 20 }}>
            {p.materials.map((m, i) => (
              <div key={i} style={{ display: 'flex', gap: 12, padding: '7px 0', fontSize: 13.5, color: t.soft }}>
                <span style={{ color: t.accent }}>·</span>{m}
              </div>
            ))}
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            <div style={{ display: 'flex', alignItems: 'center', border: `1px solid ${t.line}`, borderRadius: 2 }}>
              <button onClick={() => setQty((q) => Math.max(1, q - 1))} style={{ cursor: 'pointer', border: 'none', background: 'transparent', color: t.accent, width: 40, height: 44, fontSize: 18 }}>–</button>
              <span style={{ width: 30, textAlign: 'center', color: t.accent, fontVariantNumeric: 'tabular-nums' }}>{qty}</span>
              <button onClick={() => setQty((q) => q + 1)} style={{ cursor: 'pointer', border: 'none', background: 'transparent', color: t.accent, width: 40, height: 44, fontSize: 18 }}>+</button>
            </div>
            <TButton t={t} onClick={() => onAdd(p.id, qty)} style={{ flex: 1 }}>Add to bag — {money(p.price * qty)}</TButton>
          </div>
        </div>
      </div>
    </div>
  );
}

function CartDrawer({ t, open, items, onClose, onQty, onRemove, onCheckout }) {
  const lines = items.map(({ id, qty }) => ({ p: MK_PRODUCTS.find((x) => x.id === id), qty })).filter((l) => l.p);
  const subtotal = lines.reduce((s, l) => s + l.p.price * l.qty, 0);
  return (
    <React.Fragment>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(20,15,10,0.45)', opacity: open ? 1 : 0, pointerEvents: open ? 'auto' : 'none', transition: 'opacity .3s', zIndex: 40 }} />
      <div style={{ position: 'fixed', top: 0, right: 0, bottom: 0, width: 'min(420px, 92vw)', background: t.bgFlat, boxShadow: '-20px 0 60px rgba(20,15,10,0.25)', transform: open ? 'translateX(0)' : 'translateX(100%)', transition: 'transform .35s cubic-bezier(.2,.8,.25,1)', zIndex: 41, display: 'flex', flexDirection: 'column', color: t.accent, fontFamily: t.bodyFont }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '24px 26px', borderBottom: `1px solid ${t.line}` }}>
          <div style={{ fontFamily: t.titleFont, fontSize: 26 }}>Your bag</div>
          <button onClick={onClose} style={{ cursor: 'pointer', border: 'none', background: 'transparent', color: t.soft, fontSize: 22 }}>×</button>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', padding: '8px 26px' }}>
          {lines.length === 0 && <div style={{ color: t.soft, fontSize: 14, padding: '40px 0', textAlign: 'center' }}>Your bag is empty.</div>}
          {lines.map((l) => (
            <div key={l.p.id} style={{ display: 'flex', gap: 14, padding: '18px 0', borderBottom: `1px solid ${t.faint}` }}>
              <div style={{ width: 56, height: 76, borderRadius: 6, background: t.faint, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                <Tile {...l.p.tile} w={40} lift={false} />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: t.titleFont, fontSize: 18 }}>{l.p.name}</div>
                <div style={{ fontSize: 12, color: t.soft, margin: '2px 0 8px' }}>{money(l.p.price)}</div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <div style={{ display: 'flex', alignItems: 'center', border: `1px solid ${t.line}`, borderRadius: 2 }}>
                    <button onClick={() => onQty(l.p.id, -1)} style={{ cursor: 'pointer', border: 'none', background: 'transparent', color: t.accent, width: 26, height: 28 }}>–</button>
                    <span style={{ width: 22, textAlign: 'center', fontSize: 13 }}>{l.qty}</span>
                    <button onClick={() => onQty(l.p.id, 1)} style={{ cursor: 'pointer', border: 'none', background: 'transparent', color: t.accent, width: 26, height: 28 }}>+</button>
                  </div>
                  <button onClick={() => onRemove(l.p.id)} style={{ cursor: 'pointer', border: 'none', background: 'transparent', color: t.soft, fontSize: 11, letterSpacing: '0.1em', textTransform: 'uppercase' }}>Remove</button>
                </div>
              </div>
              <div style={{ fontSize: 14 }}>{money(l.p.price * l.qty)}</div>
            </div>
          ))}
        </div>
        <div style={{ padding: '20px 26px 26px', borderTop: `1px solid ${t.line}` }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 14, marginBottom: 16 }}>
            <span style={{ color: t.soft }}>Subtotal</span><span style={{ fontFamily: t.titleFont, fontSize: 22 }}>{money(subtotal)}</span>
          </div>
          <TButton t={t} onClick={() => { if (lines.length) { onClose(); onCheckout(); } }} style={{ width: '100%', opacity: lines.length ? 1 : 0.5 }}>Checkout</TButton>
        </div>
      </div>
    </React.Fragment>
  );
}

function StoreApp() {
  const [raw, t] = useMKTheme();
  const [view, setView] = React.useState('home');
  const [currentId, setCurrentId] = React.useState(null);
  const [cart, setCart] = React.useState([]);
  const [cartOpen, setCartOpen] = React.useState(false);
  const [order, setOrder] = React.useState(null);

  const nav = (v) => { setView(v); setCartOpen(false); window.scrollTo(0, 0); };
  const openProduct = (id) => { setCurrentId(id); setView('product'); window.scrollTo(0, 0); };
  const addToCart = (id, qty = 1) => {
    setCart((c) => { const ex = c.find((x) => x.id === id); return ex ? c.map((x) => x.id === id ? { ...x, qty: x.qty + qty } : x) : [...c, { id, qty }]; });
    setCartOpen(true);
  };
  const changeQty = (id, d) => setCart((c) => c.map((x) => x.id === id ? { ...x, qty: Math.max(1, x.qty + d) } : x));
  const removeItem = (id) => setCart((c) => c.filter((x) => x.id !== id));
  const placeOrder = (placed) => {
    setOrder(placed); setCart([]); setView('confirmation'); window.scrollTo(0, 0);
  };
  const cartCount = cart.reduce((s, x) => s + x.qty, 0);
  const current = MK_PRODUCTS.find((p) => p.id === currentId);
  const { AboutView, BespokeView, CheckoutView, ConfirmationView, Footer } = window;

  return (
    <div style={{ minHeight: '100vh', background: t.bg, color: t.accent, fontFamily: t.bodyFont }}>
      <StoreHeader t={t} view={view} onNav={nav} cartCount={cartCount} onCart={() => setCartOpen(true)} />
      {view === 'home' && <HomeView t={t} onNav={nav} onOpen={openProduct} onAdd={addToCart} />}
      {view === 'shop' && <ShopView t={t} onOpen={openProduct} onAdd={addToCart} />}
      {view === 'product' && current && <ProductView t={t} p={current} onAdd={addToCart} onNav={nav} />}
      {view === 'about' && AboutView && <AboutView t={t} onNav={nav} />}
      {view === 'bespoke' && BespokeView && <BespokeView t={t} />}
      {view === 'checkout' && CheckoutView && <CheckoutView t={t} items={cart} onNav={nav} onPlace={placeOrder} />}
      {view === 'confirmation' && ConfirmationView && order && <ConfirmationView t={t} order={order} onNav={nav} />}
      {Footer ? <Footer t={t} onNav={nav} /> : (
        <div style={{ borderTop: `1px solid ${t.faint}`, padding: '34px 32px', textAlign: 'center', fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', color: t.soft }}>
          Magical Kitten · Hand-painted mahjong · Made to order
        </div>
      )}
      <CartDrawer t={t} open={cartOpen} items={cart} onClose={() => setCartOpen(false)} onQty={changeQty} onRemove={removeItem} onCheckout={() => nav('checkout')} />
    </div>
  );
}

Object.assign(window, { StoreApp, money, TButton, SealDivider, StoreEnso, ProductCard, useIsNarrow, ImageSlot, MK_PRODUCTS, MK_FILTERS });
