// pages-shop.jsx — Home, Shop, PDP — all wired to FF_API
const { useState: useStateP, useEffect: useEffectP, useMemo: useMemoP } = React;

// ─── HOME PAGE ────────────────────────────────────────────────────────────────
function HomePage({ goto, addToCart, cardStyle, wishIds, toggleWishlist }) {
  const [viral, setViral] = useStateP([]);
  const [featured, setFeatured] = useStateP([]);
  const [cats, setCats] = useStateP([]);
  const [loading, setLoading] = useStateP(true);

  useEffectP(() => {
    if (typeof FF_API === 'undefined') { setLoading(false); return; }
    Promise.all([
      FF_API.products.list({ tag: 'viral', limit: 4 }),
      FF_API.products.list({ sort: 'sold', limit: 8 }),
      FF_API.products.categories(),
    ]).then(([v, f, c]) => {
      setViral(v.products || []);
      setFeatured(f.products || []);
      setCats(c || []);
    }).catch(console.error)
      .finally(() => setLoading(false));
  }, []);

  // Collage uses first 4 featured products
  const col = featured.slice(0, 4);

  return (
    <main>
      {/* ── HERO — mobile-first, product-first ── */}
      <section style={{ background: 'var(--ff-bg)', overflow: 'hidden' }}>

        {/* Mobile hero — full bleed product strip + hook */}
        <div className="ff-show-mobile" style={{ position: 'relative' }}>
          {/* Product image strip — scrollable, shows goods immediately */}
          {col.length > 0 && (
            <div style={{
              display: 'flex', gap: 10, overflowX: 'auto', padding: '20px 20px 0',
              scrollbarWidth: 'none', msOverflowStyle: 'none',
              WebkitOverflowScrolling: 'touch',
            }}>
              {[...col, ...viral.slice(0, 4)].filter(Boolean).filter((p, i, a) => a.findIndex(x => x.id === p.id) === i).slice(0, 6).map((p, i) => (
                <div key={p.id + '-strip-' + i} onClick={() => goto({ page: 'pdp', id: p.id })}
                  style={{
                    flexShrink: 0, width: 180, borderRadius: 16, overflow: 'hidden',
                    position: 'relative', cursor: 'pointer',
                    boxShadow: '0 4px 20px rgba(0,0,0,.12)',
                    transform: i % 2 === 0 ? 'rotate(-1deg)' : 'rotate(1deg)',
                  }}>
                  <ProductArt product={p} style={{ height: 220 }} />
                  {/* Price badge */}
                  <div style={{
                    position: 'absolute', bottom: 8, left: 8,
                    background: 'rgba(0,0,0,.72)', backdropFilter: 'blur(8px)',
                    color: '#fff', borderRadius: 8, padding: '4px 10px',
                    fontSize: 13, fontWeight: 700,
                  }}>
                    {fmtINR(p.price)}
                  </div>
                  {/* Discount badge */}
                  {p.compare > p.price && (
                    <div style={{
                      position: 'absolute', top: 8, right: 8,
                      background: 'var(--ff-accent)', color: '#fff',
                      borderRadius: 999, padding: '3px 9px',
                      fontSize: 11, fontWeight: 800,
                    }}>
                      -{Math.round((1 - p.price / p.compare) * 100)}%
                    </div>
                  )}
                </div>
              ))}
              {/* Trailing CTA card */}
              <div onClick={() => goto({ page: 'shop' })}
                style={{
                  flexShrink: 0, width: 140, borderRadius: 16,
                  background: 'var(--ff-accent)', cursor: 'pointer',
                  display: 'flex', flexDirection: 'column',
                  alignItems: 'center', justifyContent: 'center',
                  gap: 8, padding: 20, color: '#fff', height: 220,
                }}>
                <span style={{ fontSize: 28 }}>✦</span>
                <span style={{ fontWeight: 800, fontSize: 14, textAlign: 'center', lineHeight: 1.3 }}>See all finds</span>
                <Icon.Arrow style={{ stroke: '#fff' }} />
              </div>
            </div>
          )}

          {/* Hook text + CTA */}
          <div style={{ padding: '24px 20px 28px' }}>
            {/* Trust badges row */}
            <div style={{ display: 'flex', gap: 12, marginBottom: 16, overflowX: 'auto', scrollbarWidth: 'none' }}>
              {[
                { icon: '⚡', text: '48h shipping' },
                { icon: '❤️', text: 'With love' },
                { icon: '💳', text: 'Secure checkout' },
                { icon: '⭐', text: '4.8 avg rating' },
              ].map(b => (
                <div key={b.text} style={{
                  display: 'flex', alignItems: 'center', gap: 5, flexShrink: 0,
                  background: 'var(--ff-card)', border: 'var(--ff-border)',
                  borderRadius: 999, padding: '5px 12px',
                  fontSize: 12, fontWeight: 600, whiteSpace: 'nowrap',
                  boxShadow: 'var(--ff-shadow-sm)',
                }}>
                  <span>{b.icon}</span> {b.text}
                </div>
              ))}
            </div>

            <h1 className="ff-display" style={{ fontSize: 36, lineHeight: 1.0, marginBottom: 12 }}>
              The internet's<br />
              <span style={{
                background: 'var(--ff-accent)', color: '#fff',
                padding: '2px 12px', borderRadius: 8, display: 'inline-block',
              }}>most obsessed-over</span><br />
              products. Delivered.
            </h1>
            <p style={{ fontSize: 14, color: 'var(--ff-ink-2)', marginBottom: 20, lineHeight: 1.6 }}>
              Viral finds from across the web — tested, curated, shipped to your door in 48h.
            </p>
            <div style={{ display: 'flex', gap: 10 }}>
              <button className="ff-btn ff-btn--primary ff-btn--block" style={{ flex: 2 }}
                onClick={() => goto({ page: 'shop' })}>
                Shop the Finds ✦
              </button>
              <button className="ff-btn ff-btn--block" style={{ flex: 1 }}
                onClick={() => goto({ page: 'shop', filter: 'viral' })}>
                🔥 Viral
              </button>
            </div>
          </div>
        </div>

        {/* Desktop hero — original layout, improved */}
        <div className="ff-hide-mobile">
          <div style={{ maxWidth: 1320, margin: '0 auto', padding: '60px 40px', display: 'grid', gridTemplateColumns: '1.1fr 1fr', gap: 60, alignItems: 'center' }}>
            <div>
              <div style={{ display: 'flex', gap: 10, marginBottom: 20, flexWrap: 'wrap' }}>
                {[
                  { icon: '⚡', text: '48h shipping' },
                  { icon: '❤️', text: 'With love' },
                  { icon: '💳', text: 'Secure checkout' },
                  { icon: '⭐', text: '4.8 avg rating' },
                ].map(b => (
                  <div key={b.text} style={{
                    display: 'inline-flex', alignItems: 'center', gap: 6,
                    background: 'var(--ff-card)', border: 'var(--ff-border)',
                    borderRadius: 999, padding: '6px 14px',
                    fontSize: 12, fontWeight: 600,
                    boxShadow: 'var(--ff-shadow-sm)',
                  }}>{b.icon} {b.text}</div>
                ))}
              </div>
              <h1 className="ff-display" style={{ fontSize: 'clamp(48px, 5.5vw, 88px)', lineHeight: .96, marginBottom: 20 }}>
                The internet's<br />
                <span style={{
                  background: 'var(--ff-accent)', color: '#fff',
                  padding: '2px 16px', borderRadius: 10, display: 'inline-block',
                }}>most obsessed-over</span><br />
                products. Delivered.
              </h1>
              <p style={{ fontSize: 17, maxWidth: 480, color: 'var(--ff-ink-2)', lineHeight: 1.65, marginBottom: 32 }}>
                We hunt viral finds from across the internet, test them, and ship the good ones to your door in 48 hours. No fluff.
              </p>
              <div style={{ display: 'flex', gap: 12, marginBottom: 40 }}>
                <button className="ff-btn ff-btn--primary" onClick={() => goto({ page: 'shop' })}>Shop the Finds <Icon.Arrow /></button>
                <button className="ff-btn" onClick={() => goto({ page: 'shop', filter: 'viral' })}>🔥 What's viral</button>
              </div>
              <div style={{ display: 'flex', gap: 32 }}>
                <Stat n="127K" l="happy customers" />
                <Stat n="4.8★" l="avg rating" />
                <Stat n="48h" l="ship time" />
              </div>
            </div>
            {/* Desktop collage */}
            <div style={{ position: 'relative', height: 560 }}>
              {col[0] && <div style={{ position: 'absolute', top: 20, left: 0, width: 260, transform: 'rotate(-4deg)' }}><div className="ff-card" style={{ overflow: 'hidden' }}><ProductArt product={col[0]} /></div></div>}
              {col[1] && <div style={{ position: 'absolute', top: 0, right: 40, width: 240, transform: 'rotate(3deg)' }}><div className="ff-card" style={{ overflow: 'hidden' }}><ProductArt product={col[1]} /></div></div>}
              {col[2] && <div style={{ position: 'absolute', bottom: 30, left: 80, width: 250, transform: 'rotate(2deg)' }}><div className="ff-card" style={{ overflow: 'hidden' }}><ProductArt product={col[2]} /></div></div>}
              {col[3] && <div style={{ position: 'absolute', bottom: 60, right: 0, width: 220, transform: 'rotate(-3deg)' }}><div className="ff-card" style={{ overflow: 'hidden' }}><ProductArt product={col[3]} /></div></div>}
              <div style={{ position: 'absolute', top: 220, left: '50%', transform: 'translate(-50%,-50%) rotate(-8deg)', background: 'var(--ff-lime)', border: 'var(--ff-border)', borderRadius: 999, padding: '14px 22px', fontWeight: 700, boxShadow: 'var(--ff-shadow)', fontSize: 14 }}>
                As seen <u>6M+</u> times ✦
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* Press marquee */}
      <div className="ff-marquee">
        <div className="ff-marquee__track">
          {[...FF_PRESS, ...FF_PRESS, ...FF_PRESS].map((p, i) => (
            <span key={i} className="ff-marquee__item">
              <span className="ff-marquee__star">✦</span> AS SEEN ON {p}
            </span>
          ))}
        </div>
      </div>

      {/* Viral row */}
      <section style={{ maxWidth: 1320, margin: '0 auto', padding: '64px 24px 20px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', marginBottom: 28, flexWrap: 'wrap', gap: 12 }}>
          <div>
            <span className="ff-chip ff-chip--viral">TRENDING NOW</span>
            <h2 className="ff-display" style={{ fontSize: 44, marginTop: 10 }}>The viral wall ✦</h2>
          </div>
          <button className="ff-btn" onClick={() => goto({ page: 'shop', filter: 'viral' })}>See all viral <Icon.Arrow /></button>
        </div>
        {loading ? <LoadingGrid /> : (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 20 }}>
            {viral.map(p => <ProductCard key={p.id} product={p} onAdd={addToCart} onOpen={() => goto({ page: 'pdp', id: p.id })} cardStyle={cardStyle} wishlisted={wishIds?.has(p.id)} onWishlist={toggleWishlist} />)}
          </div>
        )}
      </section>

      {/* ── Social proof bar ── */}
      <section style={{ background: 'var(--ff-ink)', color: 'rgba(255,255,255,.9)' }}>
        <div style={{
          maxWidth: 1320, margin: '0 auto', padding: '28px 24px',
          display: 'flex', gap: 0, overflowX: 'auto', scrollbarWidth: 'none'
        }}>
          {[
            { n: '127K+', l: 'Happy customers', icon: '😊' },
            { n: '4.8★', l: 'Average rating', icon: '⭐' },
            { n: '48h', l: 'Ship time', icon: '⚡' },
            { n: 'COD', l: 'Cash on delivery', icon: '💳' },
            { n: 'Easy', l: 'Returns', icon: '🔄' },
          ].map((s, i) => (
            <div key={i} style={{
              flex: '1 0 140px', textAlign: 'center', padding: '0 20px',
              borderRight: i < 4 ? '1px solid rgba(255,255,255,.1)' : 'none'
            }}>
              <div style={{ fontSize: 22, marginBottom: 4 }}>{s.icon}</div>
              <div style={{ fontFamily: 'var(--ff-font-display)', fontSize: 22, fontWeight: 700 }}>{s.n}</div>
              <div style={{ fontSize: 12, color: 'rgba(255,255,255,.5)', marginTop: 2 }}>{s.l}</div>
            </div>
          ))}
        </div>
      </section>

      {/* ── UGC strip — customer photos & videos ── */}
      <UGCStrip goto={goto} />

      {/* Category grid — from API */}
      <section style={{ maxWidth: 1320, margin: '0 auto', padding: '48px 24px' }}>
        <h2 className="ff-display" style={{ fontSize: 44, marginBottom: 24 }}>Pick your rabbit hole</h2>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
          {cats.filter(c => c.id !== 'all').map((c, i) => {
            const catColors = ['var(--ff-lime)', 'var(--ff-lav)', 'var(--ff-sky)', 'var(--ff-sun)', 'var(--ff-pink)', 'var(--ff-mint)'];
            return (
              <button key={c.id} onClick={() => goto({ page: 'shop', cat: c.id })} className="ff-card" style={{
                background: catColors[i % catColors.length], padding: '22px 20px', textAlign: 'left', minHeight: 130,
                display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
              }}>
                <span className="ff-display" style={{ fontSize: 22 }}>{c.label}</span>
                <span style={{ fontSize: 13, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 6 }}>Shop now <Icon.Arrow /></span>
              </button>
            );
          })}
        </div>
      </section>

      {/* Blog strip */}
      <BlogStrip />

      {/* How we work */}
      <section style={{ background: 'var(--ff-ink)', color: 'var(--ff-bg)', borderTop: 'var(--ff-border)', borderBottom: 'var(--ff-border)' }}>
        <div style={{ maxWidth: 1320, margin: '0 auto', padding: '72px 24px', display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 32 }} className="ff-three-col">
          {[
            { t: 'We hunt', d: "Our team scrolls so you don't have to. 800+ products screened every week." },
            { t: 'We test', d: 'Every item we list is put through 30 days of real use. Fails get cut.' },
            { t: 'We ship', d: 'Fulfilled from our warehouse in 48 hours. Free over ₹999.' },
          ].map((f, i) => (
            <div key={i}>
              <div style={{ fontFamily: "'Space Grotesk',sans-serif", fontSize: 72, color: 'var(--ff-accent)', fontWeight: 700 }}>0{i + 1}</div>
              <h3 style={{ fontSize: 28, marginTop: 6 }}>{f.t}</h3>
              <p style={{ opacity: .75, marginTop: 8, fontSize: 16 }}>{f.d}</p>
            </div>
          ))}
        </div>
      </section>

      {/* All products — live from DB */}
      <section style={{ maxWidth: 1320, margin: '0 auto', padding: '64px 24px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', marginBottom: 28 }}>
          <h2 className="ff-display" style={{ fontSize: 44 }}>Everything in stock</h2>
          <button className="ff-btn" onClick={() => goto({ page: 'shop' })}>Browse all <Icon.Arrow /></button>
        </div>
        {loading ? <LoadingGrid /> : (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 20 }}>
            {featured.slice(0, 8).map(p => <ProductCard key={p.id} product={p} onAdd={addToCart} onOpen={() => goto({ page: 'pdp', id: p.id })} cardStyle={cardStyle} wishlisted={wishIds?.has(p.id)} onWishlist={toggleWishlist} />)}
          </div>
        )}
      </section>

      {/* Reviews strip — static, marketing copy */}
      <section style={{ maxWidth: 1320, margin: '0 auto', padding: '40px 24px 80px' }}>
        <h2 className="ff-display" style={{ fontSize: 44, marginBottom: 24, textAlign: 'center' }}>Real reviews, fussy people</h2>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 18 }}>
          {[
            { q: "My sister thought I spent a fortune. I did not.", n: 'Priya · Bangalore', s: 5 },
            { q: 'They said 48h shipping. It was 31.', n: 'Rahul · Delhi', s: 5 },
            { q: "Finally a site that doesn't lie about sizes.", n: 'Aisha · Mumbai', s: 4 },
          ].map((r, i) => (
            <div key={i} className="ff-card" style={{ padding: 20, background: ['var(--ff-lav)', 'var(--ff-lime)', 'var(--ff-sky)'][i] }}>
              <Stars value={r.s} />
              <p style={{ fontSize: 20, lineHeight: 1.3, fontFamily: "'Space Grotesk',sans-serif", fontWeight: 600, marginTop: 10, marginBottom: 12 }}>"{r.q}"</p>
              <div style={{ fontSize: 13, opacity: .75 }}>{r.n}</div>
            </div>
          ))}
        </div>
      </section>
    </main>
  );
}

function Stat({ n, l }) {
  return (
    <div>
      <div className="ff-display" style={{ fontSize: 28 }}>{n}</div>
      <div style={{ fontSize: 12, color: 'var(--ff-muted)', textTransform: 'uppercase', letterSpacing: '.08em' }}>{l}</div>
    </div>
  );
}

// Loading grid skeleton
function LoadingGrid({ count = 4 }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 20 }}>
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} className="ff-card" style={{ height: 340, background: 'var(--ff-bg-2)', animation: 'ffPulse 1.4s ease-in-out infinite' }} />
      ))}
    </div>
  );
}

// ─── SHOP PAGE ────────────────────────────────────────────────────────────────

// ── ReviewForm — text only (no uploads) ─────────────────────────────────────
function ReviewForm({ productId, onDone }) {
  const [name, setName] = useStateP('');
  const [stars, setStars] = useStateP(5);
  const [title, setTitle] = useStateP('');
  const [body, setBody] = useStateP('');
  const [saving, setSaving] = useStateP(false);
  const [error, setError] = useStateP('');

  const submit = async () => {
    if (!name.trim() || !body.trim()) { setError('Name and review are required'); return; }
    setSaving(true); setError('');
    const { ok } = await FF_API.products.addReview(productId, {
      name: name.trim(), stars, title: title.trim(), body: body.trim(),
    });
    setSaving(false);
    if (ok) onDone(true);
    else setError('Could not submit. Please try again.');
  };

  return (
    <div>
      {error && <div style={{ color: '#CC0000', fontSize: 13, marginBottom: 10, padding: '8px 12px', background: '#FFE4E4', borderRadius: 8 }}>{error}</div>}
      <input className="ff-input" placeholder="Your name *" value={name}
        onChange={e => setName(e.target.value)} style={{ marginBottom: 10 }} />
      <input className="ff-input" placeholder="Review title (optional)" value={title}
        onChange={e => setTitle(e.target.value)} style={{ marginBottom: 10 }} />
      <div style={{ display: 'flex', gap: 4, alignItems: 'center', marginBottom: 12 }}>
        {[1, 2, 3, 4, 5].map(s => (
          <button key={s} onClick={() => setStars(s)}
            style={{ fontSize: 30, color: s <= stars ? '#F5A623' : 'var(--ff-line)', background: 'none', border: 'none', cursor: 'pointer', padding: 0, lineHeight: 1 }}>
            ★
          </button>
        ))}
        <span style={{ marginLeft: 8, fontSize: 13, color: 'var(--ff-muted)' }}>
          {['', 'Terrible', 'Poor', 'OK', 'Good', 'Excellent!'][stars]}
        </span>
      </div>
      <textarea className="ff-input" placeholder="What did you think? Help others decide…"
        value={body} onChange={e => setBody(e.target.value)} rows={4} style={{ marginBottom: 12 }} />
      <button className="ff-btn ff-btn--primary" onClick={submit} disabled={saving}>
        {saving ? 'Submitting…' : 'Submit review ✦'}
      </button>
    </div>
  );
}

// ── Helpers for YouTube/video URLs ───────────────────────────────────────────
function getYouTubeId(url) {
  if (!url) return null;
  const m = url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([\w-]{11})/);
  return m ? m[1] : null;
}
function isYouTube(url) { return !!getYouTubeId(url); }
function isVideoFile(url) { return /\.(mp4|mov|webm|ogg)$/i.test(url || ''); }

// ── SpotlightModal — fullscreen lightbox with media + optional product link ──
function SpotlightModal({ p, onClose, goto }) {
  const ytId = getYouTubeId(p.media_url);
  const isVid = p.media_type === 'video' || isYouTube(p.media_url) || isVideoFile(p.media_url);

  // Clean product ID — strip any URL prefix
  const rawPid = p.product_id || '';
  const pid = rawPid.replace(/^.*\/product\//, '').replace(/^https?:\/\/[^/]+\//, '');

  React.useEffect(() => {
    const handler = e => e.key === 'Escape' && onClose();
    document.addEventListener('keydown', handler);
    return () => document.removeEventListener('keydown', handler);
  }, []);

  return (
    <div onClick={e => e.target === e.currentTarget && onClose()}
      style={{
        position: 'fixed', inset: 0, background: 'rgba(0,0,0,.92)', zIndex: 800,
        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 16
      }}>
      {/* Close */}
      <button onClick={onClose} style={{
        position: 'fixed', top: 16, right: 16, width: 40, height: 40,
        borderRadius: 999, background: 'rgba(255,255,255,.15)', border: 'none', color: '#fff',
        fontSize: 20, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 2
      }}>✕</button>

      {/* Media */}
      <div style={{ maxWidth: 600, width: '100%', borderRadius: 14, overflow: 'hidden', flexShrink: 0 }}>
        {ytId ? (
          <iframe
            src={'https://www.youtube.com/embed/' + ytId + '?autoplay=1&rel=0'}
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
            allowFullScreen
            style={{ width: '100%', aspectRatio: '16/9', border: 'none', display: 'block' }} />
        ) : isVid ? (
          <video src={p.media_url} controls autoPlay playsInline
            style={{ width: '100%', maxHeight: '70vh', objectFit: 'contain', background: '#000', display: 'block' }} />
        ) : (
          <img src={p.media_url} alt={p.caption || ''}
            style={{ width: '100%', maxHeight: '80vh', objectFit: 'contain', display: 'block' }} />
        )}
      </div>

      {/* Caption + CTA */}
      {(p.caption || p.reviewer_name || pid) && (
        <div style={{ maxWidth: 600, width: '100%', marginTop: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
          <div>
            {p.caption && <div style={{ color: '#fff', fontWeight: 600, fontSize: 15 }}>{p.caption}</div>}
            {p.reviewer_name && <div style={{ color: 'rgba(255,255,255,.5)', fontSize: 13, marginTop: 3 }}>— {p.reviewer_name}</div>}
          </div>
          {pid && (
            <button onClick={() => { onClose(); goto({ page: 'pdp', id: pid }); }}
              style={{
                background: '#fff', color: 'var(--ff-ink)', border: 'none', borderRadius: 10,
                padding: '10px 20px', fontWeight: 700, fontSize: 14, cursor: 'pointer', flexShrink: 0
              }}>
              View product →
            </button>
          )}
        </div>
      )}
    </div>
  );
}

// ── SpotlightCard — thumbnail card, opens modal on tap ───────────────────────
function SpotlightCard({ p, onOpen }) {
  const ytId = getYouTubeId(p.media_url);
  const isVid = p.media_type === 'video' || isYouTube(p.media_url) || isVideoFile(p.media_url);
  // Best thumbnail: admin-set > YouTube auto-thumb > video poster
  const thumb = p.thumbnail ||
    (ytId ? 'https://img.youtube.com/vi/' + ytId + '/hqdefault.jpg' : null) ||
    (p.media_type === 'photo' ? p.media_url : null);

  return (
    <div onClick={onOpen}
      style={{
        flexShrink: 0, width: 'clamp(200px, 30vw, 300px)', borderRadius: 14, overflow: 'hidden', position: 'relative',
        cursor: 'pointer', boxShadow: '0 4px 20px rgba(0,0,0,.15)', background: '#111',
        transition: 'transform .15s', userSelect: 'none'
      }}
      onMouseEnter={e => e.currentTarget.style.transform = 'scale(1.02)'}
      onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}>

      {/* Thumbnail image */}
      {thumb
        ? <img src={thumb} alt={p.caption || ''} style={{ width: '100%', height: 380, objectFit: 'cover', display: 'block' }} />
        : <div style={{ width: '100%', height: 380, background: '#222', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <span style={{ fontSize: 40, opacity: .4 }}>{isVid ? '🎬' : '📷'}</span>
        </div>
      }

      {/* Play button for videos */}
      {isVid && (
        <div style={{
          position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
          background: 'rgba(0,0,0,.2)'
        }}>
          <div style={{
            width: 52, height: 52, borderRadius: 999, background: 'rgba(255,255,255,.88)',
            display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 2px 12px rgba(0,0,0,.3)'
          }}>
            <span style={{ fontSize: 20, marginLeft: 3 }}>▶</span>
          </div>
        </div>
      )}

      {/* Gradient + caption */}
      <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(0,0,0,.8) 0%, transparent 50%)', pointerEvents: 'none' }} />
      <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: '10px 12px', pointerEvents: 'none' }}>
        {p.caption && <div style={{ color: '#fff', fontSize: 12, fontWeight: 600, lineHeight: 1.4 }}>{p.caption}</div>}
        {p.reviewer_name && <div style={{ color: 'rgba(255,255,255,.5)', fontSize: 11, marginTop: 2 }}>— {p.reviewer_name}</div>}
      </div>
    </div>
  );
}

// ── UGCStrip — "Spotted in the wild" horizontal scroll ────────────────────────
function UGCStrip({ goto }) {
  const [posts, setPosts] = useStateP([]);
  const [modal, setModal] = useStateP(null);
  useEffectP(() => {
    if (typeof FF_API === 'undefined') return;
    FF_API.content?.spotlight({ featured: 1, limit: 6 }).then(d => setPosts(Array.isArray(d) ? d : []));
  }, []);
  if (!posts.length) return null;
  return (
    <>
      {modal && <SpotlightModal p={modal} onClose={() => setModal(null)} goto={goto} />}
      <section style={{ padding: '56px 0' }}>
        <div style={{ maxWidth: 1320, margin: '0 auto', padding: '0 24px' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 24, flexWrap: 'wrap', gap: 10 }}>
            <div>
              <span className="ff-chip" style={{ marginBottom: 8 }}>Real customers</span>
              <h2 className="ff-display" style={{ fontSize: 36 }}>Spotted in the wild ✦</h2>
              <p style={{ color: 'var(--ff-muted)', fontSize: 14, marginTop: 4 }}>Real moments, real people</p>
            </div>
            <a href="/spotlight" style={{ fontSize: 13, fontWeight: 700, color: 'var(--ff-accent)', textDecoration: 'none', display: 'flex', alignItems: 'center', gap: 4, flexShrink: 0 }}>
              See all →
            </a>
          </div>
          <div style={{
            display: 'flex', gap: 16, overflowX: 'auto', scrollbarWidth: 'none',
            marginLeft: -24, marginRight: -24, padding: '0 24px 16px',
            WebkitOverflowScrolling: 'touch'
          }}>
            {posts.map(p => (
              <SpotlightCard key={p.id} p={p} onOpen={() => setModal(p)} />
            ))}
          </div>
        </div>
      </section>
    </>
  );
}

// ── BlogStrip — tips/articles section ────────────────────────────────────────
function BlogStrip() {
  const [posts, setPosts] = useStateP([]);
  useEffectP(() => {
    if (typeof FF_API === 'undefined') return;
    FF_API.content?.blogList({ limit: 3 }).then(d => setPosts(Array.isArray(d) ? d : []));
  }, []);
  if (!posts.length) return null;
  return (
    <section style={{ background: 'var(--ff-bg-2)', borderTop: 'var(--ff-border)', padding: '60px 0' }}>
      <div style={{ maxWidth: 1320, margin: '0 auto', padding: '0 24px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 28 }}>
          <div>
            <h2 className="ff-display" style={{ fontSize: 36 }}>Tips & ideas</h2>
            <p style={{ color: 'var(--ff-muted)', marginTop: 4, fontSize: 14 }}>From the Fussy Finds team</p>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 16 }}>
          {posts.map(p => (
            <div key={p.id} className="ff-card" style={{ overflow: 'hidden' }}>
              {p.cover_image && <img src={p.cover_image} alt={p.title} style={{ width: '100%', height: 200, objectFit: 'cover', display: 'block' }} />}
              <div style={{ padding: 18 }}>
                {p.tag && <span className="ff-chip" style={{ marginBottom: 10, fontSize: 10 }}>{p.tag}</span>}
                <h3 style={{ fontSize: 17, fontWeight: 700, lineHeight: 1.3, marginBottom: 8 }}>{p.title}</h3>
                {p.excerpt && <p style={{ fontSize: 13, color: 'var(--ff-muted)', lineHeight: 1.6, marginBottom: 12 }}>{p.excerpt}</p>}
                <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--ff-accent)', display: 'flex', alignItems: 'center', gap: 4 }}>
                  Read more <Icon.Arrow />
                </span>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}


function ShopPage({ goto, addToCart, cardStyle, initialFilter, initialCat, initialQuery, wishIds, toggleWishlist }) {
  const [cat, setCat] = useStateP(initialCat || 'all');
  const [tag, setTag] = useStateP(initialFilter || 'all');
  const [sort, setSort] = useStateP('sold');
  const [q, setQ] = useStateP(initialQuery || '');
  const [price, setPrice] = useStateP(5000);  // in rupees
  const [products, setProducts] = useStateP([]);
  const [total, setTotal] = useStateP(0);
  const [page, setPage] = useStateP(1);
  const [cats, setCats] = useStateP([]);
  const [loading, setLoading] = useStateP(true);

  // Load categories once
  useEffectP(() => {
    if (typeof FF_API === 'undefined') return;
    FF_API.products.categories().then(setCats).catch(console.error);
  }, []);

  // Reload products when filters change
  useEffectP(() => {
    if (typeof FF_API === 'undefined') { setLoading(false); return; }
    setLoading(true);
    const params = { page, limit: 20, sort };
    if (cat !== 'all') params.cat = cat;
    if (tag !== 'all') params.tag = tag;
    if (q) params.q = q;

    // price filter is client-side (API doesn't have max_price param)
    FF_API.products.list(params)
      .then(r => { setProducts(r.products || []); setTotal(r.total || 0); })
      .catch(console.error)
      .finally(() => setLoading(false));
  }, [cat, tag, sort, q, page]);

  // Client-side price filter
  // product.price is in paise, price state is in rupees — convert for comparison
  const items = useMemoP(() => products.filter(p => (parseInt(p.price) || 0) / 100 <= price), [products, price]);

  const catLabel = cats.find(c => c.id === cat)?.label || '';

  return (
    <main style={{ maxWidth: 1320, margin: '0 auto', padding: '32px 24px 80px' }}>
      <div style={{ marginBottom: 24 }}>
        <div style={{ fontSize: 13, color: 'var(--ff-muted)', marginBottom: 8 }}>
          <a onClick={() => goto({ page: 'home' })} style={{ cursor: 'pointer' }}>Home</a> › Shop {cat !== 'all' && `› ${catLabel}`}
        </div>
        <h1 className="ff-display" style={{ fontSize: 56 }}>
          {tag === 'viral' ? 'The viral wall ✦' : tag === 'new' ? 'New drops ✦' : cat !== 'all' ? catLabel : 'All the finds'}
        </h1>
        <p style={{ color: 'var(--ff-ink-2)', marginTop: 6 }}>{total} products · updated daily</p>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '240px 1fr', gap: 32 }} className="ff-shop-grid">
        {/* Sidebar */}
        <aside className="ff-hide-mobile" style={{ position: 'sticky', top: 110, alignSelf: 'start', height: 'fit-content' }}>
          <div className="ff-card" style={{ padding: 18 }}>
            <h3 style={{ fontSize: 13, textTransform: 'uppercase', letterSpacing: '.1em', color: 'var(--ff-muted)', marginBottom: 10 }}>Search</h3>
            <input value={q} onChange={e => { setQ(e.target.value); setPage(1); }} placeholder="Find something…" className="ff-input" style={{ padding: '8px 12px' }} />

            <h3 style={{ fontSize: 13, textTransform: 'uppercase', letterSpacing: '.1em', color: 'var(--ff-muted)', marginTop: 22, marginBottom: 10 }}>Category</h3>
            <div style={{ display: 'grid', gap: 4 }}>
              {cats.map(c => (
                <button key={c.id} onClick={() => { setCat(c.id); setPage(1); }} style={{
                  textAlign: 'left', padding: '7px 10px', borderRadius: 8,
                  background: cat === c.id ? 'var(--ff-ink)' : 'transparent',
                  color: cat === c.id ? '#fff' : 'inherit',
                  fontWeight: cat === c.id ? 600 : 500, fontSize: 14,
                }}>{c.label}</button>
              ))}
            </div>

            <h3 style={{ fontSize: 13, textTransform: 'uppercase', letterSpacing: '.1em', color: 'var(--ff-muted)', marginTop: 22, marginBottom: 10 }}>Tags</h3>
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
              {[{ k: 'all', l: 'All' }, { k: 'viral', l: 'Viral ✦' }, { k: 'new', l: 'New' }, { k: 'bestseller', l: 'Best' }].map(t => (
                <button key={t.k} onClick={() => { setTag(t.k); setPage(1); }} className="ff-chip" style={{
                  background: tag === t.k ? 'var(--ff-ink)' : '#fff',
                  color: tag === t.k ? '#fff' : 'inherit',
                }}>{t.l}</button>
              ))}
            </div>

            <h3 style={{ fontSize: 13, textTransform: 'uppercase', letterSpacing: '.1em', color: 'var(--ff-muted)', marginTop: 22, marginBottom: 10 }}>Max price: {fmtINR(price)}</h3>
            <input type="range" min="100" max="5000" step="100" value={price} onChange={e => setPrice(+e.target.value)} style={{ width: '100%' }} />
          </div>
        </aside>

        {/* Results */}
        <div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20, gap: 10, flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
              {cat !== 'all' && <button className="ff-chip" onClick={() => setCat('all')}>✕ {catLabel}</button>}
              {tag !== 'all' && <button className="ff-chip" onClick={() => setTag('all')}>✕ {tag}</button>}
              {q && <button className="ff-chip" onClick={() => setQ('')}>✕ "{q}"</button>}
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <span style={{ fontSize: 13, color: 'var(--ff-muted)' }}>Sort:</span>
              <select value={sort} onChange={e => { setSort(e.target.value); setPage(1); }} className="ff-input" style={{ padding: '8px 12px', width: 'auto' }}>
                <option value="sold">Most popular</option>
                <option value="rating">Highest rated</option>
                <option value="price_asc">Price: Low → High</option>
                <option value="price_desc">Price: High → Low</option>
              </select>
            </div>
          </div>

          {loading ? <LoadingGrid count={8} /> : items.length === 0 ? (
            <div className="ff-card" style={{ padding: 60, textAlign: 'center' }}>
              <div style={{ fontSize: 40 }}>🥲</div>
              <h3 className="ff-display" style={{ fontSize: 24, marginTop: 10 }}>Nothing matches yet</h3>
              <p style={{ color: 'var(--ff-muted)' }}>Try clearing a filter or searching something broader.</p>
            </div>
          ) : (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 20 }}>
              {items.map(p => <ProductCard key={p.id} product={p} onAdd={addToCart} onOpen={() => goto({ page: 'pdp', id: p.id })} cardStyle={cardStyle} wishlisted={wishIds?.has(p.id)} onWishlist={toggleWishlist} />)}
            </div>
          )}

          {/* Pagination */}
          {!loading && total > 20 && (
            <div style={{ display: 'flex', justifyContent: 'center', gap: 8, marginTop: 32 }}>
              <button className="ff-btn" disabled={page === 1} onClick={() => setPage(p => p - 1)}>← Prev</button>
              <span style={{ padding: '10px 16px', fontSize: 14, color: 'var(--ff-muted)' }}>Page {page} of {Math.ceil(total / 20)}</span>
              <button className="ff-btn" disabled={page * 20 >= total} onClick={() => setPage(p => p + 1)}>Next →</button>
            </div>
          )}
        </div>
      </div>
    </main>
  );
}


// ─── DESCRIPTION BLOCK — formats product description text ────────────────────
// Handles: – bullet points, **bold**, ALL CAPS HEADERS:, plain paragraphs
function DescriptionBlock({ text }) {
  if (!text) return null;

  // Split on newlines and also on "– " bullet markers inline
  // Some descriptions use – for bullet points inline in one long string
  const raw = text
    .replace(/\s*[–—-]\s+/g, '\n– ')   // normalize bullet chars to newlines
    .replace(/\n{3,}/g, '\n\n')           // max 2 newlines
    .trim();

  const lines = raw.split('\n').filter(l => l.trim());

  const renderLine = (line, key) => {
    const trimmed = line.trim();

    // Bullet point
    if (trimmed.startsWith('– ') || trimmed.startsWith('- ') || trimmed.startsWith('• ')) {
      const content = trimmed.replace(/^[–\-•]\s*/, '');
      return (
        <div key={key} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', marginBottom: 6 }}>
          <span style={{ color: 'var(--ff-accent)', fontWeight: 700, fontSize: 16, flexShrink: 0, lineHeight: 1.6 }}>✦</span>
          <span style={{ fontSize: 14, lineHeight: 1.6, color: 'var(--ff-ink-2)' }}>{renderInline(content)}</span>
        </div>
      );
    }

    // ALL CAPS HEADER: pattern (e.g. "PREMIUM STAINLESS STEEL:")
    if (/^[A-Z][A-Z\s&,\-]{4,}:/.test(trimmed)) {
      const [head, ...rest] = trimmed.split(':');
      return (
        <div key={key} style={{ marginBottom: 6, marginTop: key > 0 ? 12 : 0 }}>
          <span style={{ fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--ff-ink)', display: 'block', marginBottom: 3 }}>{head.trim()}</span>
          {rest.join(':').trim() && <span style={{ fontSize: 14, lineHeight: 1.6, color: 'var(--ff-ink-2)' }}>{renderInline(rest.join(':').trim())}</span>}
        </div>
      );
    }

    // Empty line = spacer
    if (!trimmed) return <div key={key} style={{ height: 6 }} />;

    // Normal paragraph
    return (
      <p key={key} style={{ fontSize: 14, lineHeight: 1.7, color: 'var(--ff-ink-2)', margin: '0 0 8px 0' }}>
        {renderInline(trimmed)}
      </p>
    );
  };

  // Inline: handle **bold** markers
  const renderInline = (text) => {
    if (!text.includes('**')) return text;
    const parts = text.split(/\*\*(.*?)\*\*/g);
    return parts.map((part, i) => i % 2 === 1 ? <strong key={i}>{part}</strong> : part);
  };

  return (
    <div style={{ paddingBottom: 4 }}>
      {lines.map((line, i) => renderLine(line, i))}
    </div>
  );
}

// ─── PRODUCT DETAIL PAGE ─────────────────────────────────────────────────────
function ProductPage({ id, goto, addToCart, cardStyle, cart, wishIds, toggleWishlist }) {
  const [product, setProduct] = useStateP(null);
  const [related, setRelated] = useStateP([]);
  const [qty, setQty] = useStateP(1);
  // How many already in cart
  const cartQty = React.useMemo(() =>
    (cart || []).find(i => i.product_id === id)?.qty || 0,
    [cart, id]
  );
  const [loading, setLoading] = useStateP(true);
  const [revName, setRevName] = useStateP('');
  const [revStars, setRevStars] = useStateP(5);
  const [revBody, setRevBody] = useStateP('');
  const [revSent, setRevSent] = useStateP(false);
  const [revModal, setRevModal] = useStateP(null); // media lightbox
  const [activeImg, setActiveImg] = useStateP(0);

  useEffectP(() => {
    if (!id || typeof FF_API === 'undefined') return;
    setLoading(true);
    FF_API.products.get(id)
      .then(p => {
        setProduct(p);
        document.title = p.name + ' · Fussy Finds';
        if (window.FF_TRACK) window.FF_TRACK('product_view', { product_id: p.id, name: p.name, price: p.price });
        // Update OG tags dynamically for WhatsApp/social sharing
        const setMeta = (prop, val, attr = 'property') => {
          let el = document.querySelector(`meta[${attr}="${prop}"]`);
          if (!el) { el = document.createElement('meta'); el.setAttribute(attr, prop); document.head.appendChild(el); }
          el.setAttribute('content', val);
        };
        setMeta('og:title', p.name + ' · Fussy Finds');
        setMeta('og:description', p.tagline || 'Shop ' + p.name + ' on Fussy Finds');
        setMeta('og:url', window.location.href);
        if (Array.isArray(p.images) && p.images[0]) setMeta('og:image', p.images[0]);
        setMeta('name', 'description', 'name');
        // Save to recently viewed
        try {
          const rv = JSON.parse(localStorage.getItem('ff_recently_viewed') || '[]');
          const filtered = rv.filter(x => x.id !== p.id);
          filtered.unshift({ id: p.id, name: p.name, price: p.price, swatch: p.swatch, image: Array.isArray(p.images) ? p.images[0] : null });
          localStorage.setItem('ff_recently_viewed', JSON.stringify(filtered.slice(0, 8)));
        } catch { }
        return FF_API.products.list({ cat: p.cat, limit: 5 });
      })
      .then(r => setRelated((r.products || []).filter(p => p.id !== id).slice(0, 4)))
      .catch(console.error)
      .finally(() => setLoading(false));
  }, [id]);

  if (loading) return <div style={{ padding: 80, textAlign: 'center', color: 'var(--ff-muted)' }}>Loading…</div>;
  if (!product) return <div style={{ padding: 80, textAlign: 'center' }}>Product not found.</div>;

  // Variants are separate products — use product data directly
  const activeImages = Array.isArray(product.images) ? product.images : [];
  const activePrice = product.price;
  const activeStock = product.stock;
  const discount = product.compare > product.price ? Math.round((1 - product.price / product.compare) * 100) : 0;
  const reviews = product.review_list || [];

  const submitReview = async () => {
    if (!revName || !revBody) return;
    const { ok } = await FF_API.products.addReview(product.id, { name: revName, stars: revStars, title: '', body: revBody });
    if (ok) { setRevSent(true); setRevName(''); setRevBody(''); }
  };

  return (
    <main style={{ maxWidth: 1320, margin: '0 auto', padding: '24px 24px 80px' }}>
      <div style={{ fontSize: 13, color: 'var(--ff-muted)', marginBottom: 16 }}>
        <a onClick={() => goto({ page: 'home' })} style={{ cursor: 'pointer' }}>Home</a> › <a onClick={() => goto({ page: 'shop', cat: product.cat })} style={{ cursor: 'pointer' }}>{product.cat_label}</a> › {product.name}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.2fr 1fr', gap: 40 }} className="ff-pdp-grid">

        {/* ── GALLERY with vertical thumbnail strip + carousel ── */}
        {(() => {
          const imgs = Array.isArray(product.images) && product.images.length > 0 ? product.images : null;
          const total = imgs ? imgs.length : 0;
          const prev = () => setActiveImg(i => (i - 1 + total) % total);
          const next = () => setActiveImg(i => (i + 1) % total);

          return (
            <div style={{ display: 'grid', gridTemplateColumns: imgs && total > 1 ? '72px 1fr' : '1fr', gap: 10 }}>

              {/* Vertical thumbnail strip (only if >1 image) */}
              {imgs && total > 1 && (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 8, maxHeight: 560, overflowY: 'auto' }}>
                  {imgs.map((url, i) => (
                    <div key={i} onClick={() => setActiveImg(i)} style={{
                      width: 68, height: 68, borderRadius: 10, overflow: 'hidden', flexShrink: 0,
                      cursor: 'pointer', border: activeImg === i ? '2.5px solid var(--ff-accent)' : '2px solid rgba(0,0,0,.1)',
                      opacity: activeImg === i ? 1 : 0.7, transition: 'all .15s',
                    }}>
                      <img src={url} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                    </div>
                  ))}
                </div>
              )}

              {/* Main image + carousel arrows */}
              <div style={{ position: 'relative' }}>
                <div
                  style={{ borderRadius: 16, overflow: 'hidden', border: 'var(--ff-border)', aspectRatio: '1', background: 'var(--ff-bg-2)', position: 'relative' }}
                  onTouchStart={e => { if (imgs && total > 1) e.currentTarget._tx = e.touches[0].clientX; }}
                  onTouchEnd={e => {
                    if (!imgs || total <= 1 || !e.currentTarget._tx) return;
                    const dx = e.changedTouches[0].clientX - e.currentTarget._tx;
                    if (dx < -40) next();
                    else if (dx > 40) prev();
                  }}
                >
                  {imgs ? (
                    <img
                      key={activeImg}
                      src={imgs[activeImg]}
                      alt={product.name}
                      style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block', animation: 'ffFade .2s' }}
                      onError={e => { e.target.style.display = 'none'; }}
                    />
                  ) : (
                    <ProductArt product={product} ratio="1 / 1" size="lg" />
                  )}

                  {/* Carousel arrows */}
                  {imgs && total > 1 && (
                    <>
                      <button onClick={prev} style={{
                        position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)',
                        width: 36, height: 36, borderRadius: 999, background: 'rgba(255,255,255,.92)',
                        border: 'var(--ff-border)', display: 'grid', placeItems: 'center',
                        fontSize: 16, fontWeight: 700, cursor: 'pointer', zIndex: 2,
                      }}>‹</button>
                      <button onClick={next} style={{
                        position: 'absolute', right: 12, top: '50%', transform: 'translateY(-50%)',
                        width: 36, height: 36, borderRadius: 999, background: 'rgba(255,255,255,.92)',
                        border: 'var(--ff-border)', display: 'grid', placeItems: 'center',
                        fontSize: 16, fontWeight: 700, cursor: 'pointer', zIndex: 2,
                      }}>›</button>
                    </>
                  )}

                  {/* Dot indicators */}
                  {imgs && total > 1 && (
                    <div style={{ position: 'absolute', bottom: 12, left: '50%', transform: 'translateX(-50%)', display: 'flex', gap: 5, zIndex: 2 }}>
                      {imgs.map((_, i) => (
                        <button key={i} onClick={() => setActiveImg(i)} style={{
                          width: activeImg === i ? 20 : 8, height: 8, borderRadius: 999,
                          background: activeImg === i ? 'var(--ff-accent)' : 'rgba(255,255,255,.7)',
                          border: '1.5px solid rgba(0,0,0,.2)', padding: 0, cursor: 'pointer',
                          transition: 'width .2s',
                        }} />
                      ))}
                    </div>
                  )}

                  {/* Image counter badge */}
                  {imgs && total > 1 && (
                    <div style={{ position: 'absolute', top: 12, right: 12, background: 'rgba(0,0,0,.5)', color: '#fff', fontSize: 11, fontWeight: 700, padding: '3px 8px', borderRadius: 999 }}>
                      {activeImg + 1} / {total}
                    </div>
                  )}
                </div>
              </div>
            </div>
          );
        })()}

        {/* ── PRODUCT INFO ── */}
        <div>
          <div style={{ display: 'flex', gap: 6, marginBottom: 10 }}>
            {(Array.isArray(product.tags) ? product.tags : []).includes('viral') && <span className="ff-chip ff-chip--viral">VIRAL ✦</span>}
            {(Array.isArray(product.tags) ? product.tags : []).includes('new') && <span className="ff-chip ff-chip--new">NEW</span>}
            {(Array.isArray(product.tags) ? product.tags : []).includes('bestseller') && <span className="ff-chip ff-chip--best">BESTSELLER</span>}
          </div>
          <h1 className="ff-display" style={{ fontSize: 'clamp(28px,4vw,48px)', lineHeight: 1.05 }}>{product.name}</h1>
          <p style={{ fontSize: 17, color: 'var(--ff-ink-2)', marginTop: 8, lineHeight: 1.5 }}>{product.tagline}</p>

          {/* ── Formatted description ── */}
          {product.description && (
            <div style={{ marginTop: 14, borderTop: 'var(--ff-border)', paddingTop: 14 }}>
              <DescriptionBlock text={product.description} />
            </div>
          )}

          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 14 }}>
            <Stars value={parseFloat(product.rating) || 0} />
            <span style={{ fontSize: 14 }}>{parseFloat(product.rating) || 0} · {Number(product.reviews || 0).toLocaleString()} reviews · {Number(product.sold || 0).toLocaleString()} sold</span>
          </div>

          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginTop: 20 }}>
            <span className="ff-display" style={{ fontSize: 40 }}>{fmtINR(activePrice)}</span>
            {discount > 0 && <>
              <span style={{ color: 'var(--ff-muted)', textDecoration: 'line-through' }}>{fmtINR(product.compare)}</span>
              <span className="ff-chip" style={{ background: 'var(--ff-lime)' }}>Save {discount}%</span>
            </>}
          </div>
          <div style={{ fontSize: 13, color: 'var(--ff-muted)', marginTop: 4 }}>Inclusive of all taxes · Free shipping over ₹999</div>

          {/* Variants — each is a full product, clicking navigates to it */}
          {product.variants && product.variants.length > 1 && (
            <div style={{ marginTop: 24 }}>
              <div className="ff-label" style={{ marginBottom: 10 }}>Also available in</div>
              <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
                {product.variants.map(v => {
                  const isCurrent = v.is_current || v.id === product.id;
                  const outOfStock = (v.stock ?? 1) === 0;
                  const thumb = v.images?.[0] || null;
                  return (
                    <button key={v.id}
                      onClick={() => { if (!isCurrent && !outOfStock) location.href = '/product/' + v.id; }}
                      title={(v.variant_label || v.name) + (outOfStock ? ' — Out of stock' : '')}
                      style={{
                        display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5,
                        border: isCurrent ? '2px solid var(--ff-ink)' : '1.5px solid var(--ff-line)',
                        borderRadius: 10, padding: 8,
                        background: 'var(--ff-card)',
                        cursor: (isCurrent || outOfStock) ? 'default' : 'pointer',
                        opacity: outOfStock ? .45 : 1,
                        boxShadow: isCurrent ? '0 0 0 2px var(--ff-bg),0 0 0 4px var(--ff-ink)' : 'none',
                        transition: 'all .15s',
                        minWidth: 64, maxWidth: 80,
                      }}>
                      {/* Image thumbnail */}
                      <div style={{
                        width: 52, height: 52, borderRadius: 7, overflow: 'hidden', flexShrink: 0,
                        background: v.swatch || 'var(--ff-bg-2)'
                      }}>
                        {thumb && <img src={thumb} alt={v.variant_label || v.name}
                          style={{ width: '100%', height: '100%', objectFit: 'cover' }} />}
                      </div>
                      {/* Label — show variant_label, or 'Original' for root (no parent_id) */}
                      <div style={{
                        fontSize: 11, fontWeight: isCurrent ? 700 : 500, textAlign: 'center',
                        color: isCurrent ? 'var(--ff-ink)' : 'var(--ff-muted)',
                        lineHeight: 1.3, wordBreak: 'break-word'
                      }}>
                        {v.variant_label || (!v.parent_id ? 'Original' : v.name)}
                      </div>
                      {outOfStock && (
                        <div style={{ fontSize: 9, color: '#CC4400', fontWeight: 700 }}>SOLD OUT</div>
                      )}
                    </button>
                  );
                })}
              </div>
            </div>
          )}

          {/* Media lightbox */}
          {revModal && (
            <div onClick={() => setRevModal(null)} style={{
              position: 'fixed', inset: 0, background: 'rgba(0,0,0,.88)', zIndex: 600,
              display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 20,
            }}>
              <div onClick={e => e.stopPropagation()} style={{ maxWidth: 520, width: '100%' }}>
                {revModal.type === 'video'
                  ? <video src={revModal.url} controls autoPlay style={{ width: '100%', borderRadius: 14, maxHeight: '60vh', objectFit: 'contain' }} />
                  : <img src={revModal.url} alt="" style={{ width: '100%', borderRadius: 14, maxHeight: '70vh', objectFit: 'contain' }} />
                }
                {revModal.body && (
                  <div style={{ background: 'rgba(255,255,255,.1)', borderRadius: 10, padding: 14, marginTop: 12 }}>
                    <div style={{ display: 'flex', gap: 3, marginBottom: 6 }}>
                      {[1, 2, 3, 4, 5].map(s => <span key={s} style={{ color: s <= (revModal.stars || 5) ? '#F5A623' : 'rgba(255,255,255,.2)' }}>★</span>)}
                    </div>
                    <div style={{ color: '#fff', fontSize: 14, lineHeight: 1.6 }}>{revModal.body}</div>
                    <div style={{ color: 'rgba(255,255,255,.5)', fontSize: 12, marginTop: 6 }}>— {revModal.reviewer}</div>
                  </div>
                )}
              </div>
              <button onClick={() => setRevModal(null)} style={{ position: 'fixed', top: 20, right: 20, background: 'rgba(255,255,255,.15)', border: 'none', color: '#fff', fontSize: 20, width: 40, height: 40, borderRadius: 999, cursor: 'pointer' }}>✕</button>
            </div>
          )}

          {/* Qty + add */}
          <div style={{ display: 'flex', gap: 12, marginTop: 24, alignItems: 'center' }}>
            <div className="ff-card" style={{ display: 'flex', alignItems: 'center', padding: '4px 6px', boxShadow: 'var(--ff-shadow-sm)' }}>
              {/* Qty selector — locked at stock - cartQty */}
              {(() => {
                const maxCanAdd = Math.max(0, (activeStock || 0) - cartQty);
                const atMax = qty >= maxCanAdd;
                const canIncrease = !atMax && maxCanAdd > 0;
                return (<>
                  <button onClick={() => setQty(Math.max(1, qty - 1))} disabled={qty <= 1}
                    style={{ padding: '8px 10px', opacity: qty <= 1 ? .4 : 1 }}><Icon.Minus /></button>
                  <span style={{ minWidth: 30, textAlign: 'center', fontWeight: 700 }}>{qty}</span>
                  <button onClick={() => {
                    if (!canIncrease) return;
                    setQty(qty + 1);
                    // Warn when approaching limit
                    if (qty + 1 >= maxCanAdd && maxCanAdd <= 3) {
                      window.FF_TOAST && window.FF_TOAST(`Only ${maxCanAdd} available — that's all we have!`);
                    }
                  }}
                    disabled={!canIncrease}
                    title={!canIncrease ? `Max ${maxCanAdd} available` : ''}
                    style={{ padding: '8px 10px', opacity: canIncrease ? 1 : .35, cursor: canIncrease ? 'pointer' : 'not-allowed' }}>
                    <Icon.Plus />
                  </button>
                </>);
              })()}
            </div>
            <button className="ff-btn ff-btn--primary" style={{ flex: 1 }} onClick={() => addToCart(product, qty)}>Add to cart · {fmtINR(product.price * qty)}</button>
            <button onClick={() => toggleWishlist && toggleWishlist(product.id)} style={{
              width: 52, height: 52, borderRadius: 12, border: '1.5px solid var(--ff-line)',
              background: wishIds?.has(product.id) ? 'var(--ff-accent)' : 'var(--ff-card)',
              color: wishIds?.has(product.id) ? '#fff' : 'var(--ff-ink)',
              fontSize: 22, cursor: 'pointer', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
              transition: 'all .18s',
            }} title={wishIds?.has(product.id) ? 'Remove from wishlist' : 'Save to wishlist'}>
              {wishIds?.has(product.id) ? '♥' : '♡'}
            </button>
          </div>
          <button className="ff-btn ff-btn--ink" style={{ width: '100%', marginTop: 10 }} onClick={() => { addToCart(product, qty); goto({ page: 'checkout' }); }}>Buy now</button>
          {/* Share */}
          <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
            <button onClick={() => {
              const url = location.origin + '/product/' + product.id;
              if (navigator.share) {
                navigator.share({ title: product.name, text: product.tagline || '', url })
                  .then(() => typeof FF_API !== 'undefined' && FF_API.content?.trackShare(product.id, 'native'));
              } else {
                navigator.clipboard.writeText(url);
                window.FF_TOAST && window.FF_TOAST('Link copied ✦');
                typeof FF_API !== 'undefined' && FF_API.content?.trackShare(product.id, 'copy');
              }
            }} style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, fontSize: 13, color: 'var(--ff-muted)', background: 'none', border: '1.5px solid var(--ff-line)', borderRadius: 8, padding: '9px 0', cursor: 'pointer' }}>
              ↗ Share
            </button>
            <button onClick={() => {
              const url = 'https://wa.me/?text=' + encodeURIComponent(product.name + ' — ' + location.origin + '/product/' + product.id);
              window.open(url, '_blank');
              typeof FF_API !== 'undefined' && FF_API.content?.trackShare(product.id, 'whatsapp');
            }} style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, fontSize: 13, color: '#25D366', background: 'none', border: '1.5px solid #25D366', borderRadius: 8, padding: '9px 0', cursor: 'pointer' }}>
              💬 WhatsApp
            </button>
          </div>

          {/* Trust strip */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginTop: 22 }}>
            <div className="ff-card" style={{ padding: 12, display: 'flex', gap: 10, alignItems: 'center', boxShadow: 'var(--ff-shadow-sm)' }}>
              <Icon.Truck /> <div><div style={{ fontWeight: 700, fontSize: 13 }}>Ships in 48h</div><div style={{ fontSize: 11, color: 'var(--ff-muted)' }}>Ships in 48h</div></div>
            </div>
            <div className="ff-card" style={{ padding: 12, display: 'flex', gap: 10, alignItems: 'center', boxShadow: 'var(--ff-shadow-sm)' }}>
              <Icon.Box /> <div><div style={{ fontWeight: 700, fontSize: 13 }}>All sales final</div><div style={{ fontSize: 11, color: 'var(--ff-muted)' }}>Contact us for defects</div></div>
            </div>
          </div>

          {product.stock <= 10 && product.stock > 0 && (() => {
            const remaining = product.stock - cartQty;
            const isCritical = remaining <= 3;
            if (remaining <= 0) return null; // fully in cart
            return (
              <div style={{ marginTop: 16, padding: '12px 16px', background: isCritical ? 'var(--ff-pink)' : 'var(--ff-sun)', border: 'var(--ff-border)', borderRadius: 10, display: 'flex', alignItems: 'center', gap: 10 }}>
                <div style={{ fontSize: 18 }}>{isCritical ? '🔥' : '⚡'}</div>
                <div>
                  <div style={{ fontWeight: 700, fontSize: 13 }}>
                    {isCritical ? `Only ${remaining} left — almost gone!` : `Only ${remaining} left in stock`}
                  </div>
                  <div style={{ fontSize: 12, color: 'var(--ff-ink-2)', marginTop: 2 }}>
                    {cartQty > 0 ? `${cartQty} already in your cart.` : (isCritical ? 'Order now before it sells out.' : 'Selling fast — order soon.')}
                  </div>
                </div>
              </div>
            );
          })()}
          {product.stock === 0 && (
            <div style={{ marginTop: 16, padding: '12px 16px', background: 'var(--ff-bg-2)', border: 'var(--ff-border)', borderRadius: 10 }}>
              <div style={{ fontWeight: 700, fontSize: 13, color: 'var(--ff-muted)' }}>Out of stock</div>
              <div style={{ fontSize: 12, color: 'var(--ff-muted)', marginTop: 2 }}>We're restocking soon. Check back shortly.</div>
            </div>
          )}
        </div>
      </div>

      {/* ── Reviews section ── */}
      <section style={{ marginTop: 60 }}>

        {/* Rating summary */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 24, flexWrap: 'wrap', gap: 12 }}>
          <div>
            <h2 className="ff-display" style={{ fontSize: 30, marginBottom: 6 }}>Customer reviews</h2>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <div style={{ display: 'flex', gap: 2 }}>
                {[1, 2, 3, 4, 5].map(s => (
                  <span key={s} style={{ fontSize: 18, color: s <= Math.round(product.rating || 0) ? '#F5A623' : 'var(--ff-line)' }}>★</span>
                ))}
              </div>
              <span style={{ fontWeight: 700, fontSize: 17 }}>{product.rating || 0}</span>
              <span style={{ color: 'var(--ff-muted)', fontSize: 14 }}>· {Number(product.reviews || 0).toLocaleString()} reviews</span>
            </div>
          </div>
          <button className="ff-btn ff-btn--sm" onClick={() => document.getElementById('review-form')?.scrollIntoView({ behavior: 'smooth' })}>
            ✍ Write a review
          </button>
        </div>



        {/* Review cards */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 14, marginBottom: 24 }}>
          {reviews.map((r, i) => (
            <div key={i} className="ff-card" style={{ padding: 18 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 8 }}>
                <div style={{ display: 'flex', gap: 2 }}>
                  {[1, 2, 3, 4, 5].map(s => (
                    <span key={s} style={{ fontSize: 14, color: s <= r.stars ? '#F5A623' : 'var(--ff-line)' }}>★</span>
                  ))}
                </div>
                {r.verified == 1 && (
                  <span style={{ fontSize: 10, fontWeight: 700, color: 'var(--ff-teal)', background: 'var(--ff-mint)', padding: '2px 7px', borderRadius: 4 }}>
                    ✓ Verified
                  </span>
                )}
              </div>
              {r.title && <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 4 }}>{r.title}</div>}
              <p style={{ fontSize: 13, color: 'var(--ff-ink-2)', lineHeight: 1.6, marginBottom: 10 }}>{r.body}</p>

              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <div style={{ fontSize: 12, color: 'var(--ff-muted)' }}>
                  <strong>{r.name}</strong> · {r.created_at?.slice(0, 10)}
                </div>
                <button onClick={() => FF_API.products.reviewHelpful(r.id)}
                  style={{ fontSize: 11, color: 'var(--ff-muted)', background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}>
                  👍 Helpful {r.helpful > 0 ? '(' + r.helpful + ')' : ''}
                </button>
              </div>
            </div>
          ))}
          {!reviews.length && (
            <div style={{ gridColumn: '1/-1', textAlign: 'center', padding: '40px 20px', color: 'var(--ff-muted)', fontSize: 14 }}>
              No reviews yet — be the first to review this product!
            </div>
          )}
        </div>

        {/* Write a review form */}
        <div id="review-form" className="ff-card" style={{ padding: 24, maxWidth: 560 }}>
          <h3 className="ff-display" style={{ fontSize: 22, marginBottom: 16 }}>
            {revSent ? '✦ Thanks for your review!' : 'Write a review'}
          </h3>
          {!revSent && (
            <ReviewForm productId={product.id} onDone={(ok) => { if (ok) setRevSent(true); }} />
          )}
        </div>
      </section>

      {/* Recently Viewed */}
      <RecentlyViewed currentId={product.id} goto={goto} addToCart={addToCart} cardStyle={cardStyle} wishIds={wishIds} toggleWishlist={toggleWishlist} />

      {/* Related */}
      {related.length > 0 && (
        <section style={{ marginTop: 60 }}>
          <h2 className="ff-display" style={{ fontSize: 32, marginBottom: 20 }}>People also grabbed</h2>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 20 }}>
            {related.map(p => <ProductCard key={p.id} product={p} onAdd={addToCart} onOpen={() => goto({ page: 'pdp', id: p.id })} cardStyle={cardStyle} wishlisted={wishIds?.has(p.id)} onWishlist={toggleWishlist} />)}
          </div>
        </section>
      )}
    </main>
  );
}


// ─── RECENTLY VIEWED ─────────────────────────────────────────────────────────
function RecentlyViewed({ currentId, goto, addToCart, cardStyle, wishIds, toggleWishlist }) {
  const [items, setItems] = useStateP([]);

  useStateP(() => { }); // dummy to keep hook count stable

  useEffectP(() => {
    try {
      const rv = JSON.parse(localStorage.getItem('ff_recently_viewed') || '[]');
      setItems(rv.filter(p => p.id !== currentId).slice(0, 4));
    } catch { }
  }, [currentId]);

  if (items.length === 0) return null;

  return (
    <section style={{ marginTop: 48 }}>
      <h2 className="ff-display" style={{ fontSize: 28, marginBottom: 20 }}>Recently viewed</h2>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px,1fr))', gap: 16 }}>
        {items.map(p => (
          <div key={p.id} onClick={() => goto({ page: 'pdp', id: p.id })} className="ff-card"
            style={{ cursor: 'pointer', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
            <div style={{ height: 120, background: p.swatch || '#F5EDE3', overflow: 'hidden', flexShrink: 0 }}>
              {p.image
                ? <img src={p.image} alt={p.name} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                : <div style={{ width: '100%', height: '100%', background: p.swatch || '#F5EDE3', display: 'grid', placeItems: 'center' }}>
                  <span style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 13, color: 'rgba(0,0,0,.5)', textAlign: 'center', padding: '0 8px' }}>{p.name}</span>
                </div>
              }
            </div>
            <div style={{ padding: '10px 12px' }}>
              <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 2 }}>{p.name}</div>
              <div style={{ fontSize: 13, color: 'var(--ff-accent)', fontWeight: 700 }}>{fmtINR(p.price)}</div>
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

// SearchPage — ShopPage with search pre-filled from URL
function SearchPage({ goto, addToCart, cardStyle, wishIds, toggleWishlist }) {
  const q = new URLSearchParams(location.search).get('q') || '';
  return <ShopPage goto={goto} addToCart={addToCart} cardStyle={cardStyle}
    wishIds={wishIds} toggleWishlist={toggleWishlist} initialQuery={q} />;
}

// CategoryPage — ShopPage with category pre-selected
function CategoryPage({ goto, addToCart, cardStyle, wishIds, toggleWishlist }) {
  const slug = FF_PATH_ID() || new URLSearchParams(location.search).get('slug') || '';
  return <ShopPage goto={goto} addToCart={addToCart} cardStyle={cardStyle}
    wishIds={wishIds} toggleWishlist={toggleWishlist} initialCat={slug} />;
}

Object.assign(window, { HomePage, ShopPage, ProductPage, LoadingGrid, SearchPage, CategoryPage });