
// ── Leather colour palettes (exported to window for bespoke.jsx) ─────
const NATURAL_COLORS = [
  { name: 'Onyx',         hex: '#0f0f0f' }, { name: 'Jet',          hex: '#1a1a1a' },
  { name: 'Dark Brown',   hex: '#2b1608' }, { name: 'Espresso',     hex: '#3d1f0d' },
  { name: 'Mocha',        hex: '#5a2d14' }, { name: 'Mahogany',     hex: '#6b2a1a' },
  { name: 'Cognac',       hex: '#7c4a1e' }, { name: 'Chestnut',     hex: '#954a12' },
  { name: 'Saddle',       hex: '#8b5e2a' }, { name: 'Tobacco',      hex: '#9b6840' },
  { name: 'Hazel',        hex: '#a07848' }, { name: 'Vintage',      hex: '#a0784a' },
  { name: 'Caramel',      hex: '#b5712a' }, { name: 'Amber',        hex: '#c07820' },
  { name: 'Honey',        hex: '#c8852a' }, { name: 'Tan',          hex: '#c89464' },
  { name: 'Butterscotch', hex: '#d4952a' }, { name: 'Fawn',         hex: '#c8a878' },
  { name: 'Sand',         hex: '#d4b896' }, { name: 'Wheat',        hex: '#d4be88' },
  { name: 'Parchment',    hex: '#dfc9a0' }, { name: 'Cream',        hex: '#e8d5b0' },
  { name: 'Bone',         hex: '#ede0c8' }, { name: 'Pearl',        hex: '#f5f0e8' },
];
const DYED_COLORS = [
  { name: 'Oxblood',      hex: '#6b1a1a' }, { name: 'Burgundy',     hex: '#800020' },
  { name: 'Crimson',      hex: '#a31620' }, { name: 'Fire Red',     hex: '#cc1a00' },
  { name: 'Burnt Orange', hex: '#c04010' }, { name: 'Orange',       hex: '#d45a18' },
  { name: 'Neon Orange',  hex: '#ff4500' }, { name: 'Neon Yellow',  hex: '#ccff00' },
  { name: 'Blush',        hex: '#e8a0b0' }, { name: 'Rose',         hex: '#d4607a' },
  { name: 'Hot Pink',     hex: '#d42070' }, { name: 'Neon Pink',    hex: '#ff1493' },
  { name: 'Magenta',      hex: '#c01878' }, { name: 'Plum',         hex: '#5c2d6e' },
  { name: 'Violet',       hex: '#6a1a8a' }, { name: 'Navy',         hex: '#1b2a4a' },
  { name: 'Cobalt',       hex: '#1a4a8a' }, { name: 'Royal Blue',   hex: '#2030a0' },
  { name: 'Slate',        hex: '#5a6472' }, { name: 'Army',         hex: '#4a5240' },
  { name: 'Forest',       hex: '#2d5a27' }, { name: 'Emerald',      hex: '#1a6b4a' },
  { name: 'Silver',       hex: '#b0b8c2' }, { name: 'Gold',         hex: '#c8a832' },
];
const HARDWARE_COLORS = [
  { name: 'Brushed Gunmetal', hex: '#3a3d42' }, { name: 'Antique Brass',    hex: '#8b6914' },
  { name: 'Polished Nickel',  hex: '#c8c8cc' }, { name: 'Matte Black',      hex: '#1c1c1e' },
  { name: 'Antique Gold',     hex: '#c8960c' }, { name: 'Aged Bronze',      hex: '#6e4c1e' },
  { name: 'Burnished Silver', hex: '#a8a9ad' }, { name: 'Rose Gold',        hex: '#c0837a' },
  { name: 'Copper',           hex: '#b87333' },
];

// ── Structured description renderer ──────────────────────────────────
const DESC_KEYS = ['Exterior','Shell','Inner','Lining','Closure','Pockets','Pocket','Collar',
  'Lapel','Cuffs','Cuff','Vents','Vent','Sleeves','Sleeve','Shoulders','Hem','Waist','Length',
  'Pants','Includes','Color','Colour','Material','Materials','Fabric','Fit','Style','Finish',
  'Type','Hardware','Belt','Buckle','Lace'];
const DESC_SPLIT = new RegExp(`(?=(?:${DESC_KEYS.join('|')}):)`);

function StructuredDesc({ text }) {
  if (!text) return null;
  // Lining now shows each product's REAL material straight from its description
  // (viscose / satin / polyester / shearling / etc.) — it is no longer forced to
  // read "Fleece"/"Faux Fur". The bespoke flow still offers Fleece/Shearling as
  // selectable lining upgrades; that is separate from this catalog spec table.
  const parts = text.split(DESC_SPLIT).map(s => s.trim()).filter(Boolean);
  if (parts.length <= 1) {
    return (
      <p style={{ fontSize: 14, lineHeight: 1.7, color: 'var(--fg-2)', marginTop: 28, marginBottom: 0 }}>
        {text}
      </p>
    );
  }
  return (
    <div style={{ marginTop: 28 }}>
      {parts.map((part, i) => {
        const colon = part.indexOf(':');
        const key = colon > -1 ? part.slice(0, colon).trim() : part;
        let val = colon > -1 ? part.slice(colon + 1).trim() : '';
        // Catalog linings are synthetic — never claim real shearling or real fur to
        // the customer. In the lining row only: "shearling" reads "fleece" and any
        // "fur" reads "faux fur" (display only; print/manufacturing keeps the real desc).
        if (/^(inner|lining)$/i.test(key)) {
          val = val.replace(/shearling/ig, 'fleece').replace(/(faux\s+)?fur/ig, 'faux fur')
                   // collapse accidental repeats, e.g. a desc that said "shearling fleece"
                   // -> "fleece fleece" -> "fleece"; same guard for "faux fur faux fur".
                   .replace(/\bfleece(?:\s+fleece)+\b/ig, 'fleece')
                   .replace(/\bfaux fur(?:\s+faux fur)+\b/ig, 'faux fur');
        }
        return (
          <div key={i} style={{
            display: 'flex', gap: 12, alignItems: 'baseline',
            padding: '7px 0',
            borderBottom: i < parts.length - 1 ? '.5px solid var(--line-2)' : 'none',
          }}>
            <span style={{
              fontFamily: 'var(--font-mono)', fontSize: 9, letterSpacing: '.18em',
              textTransform: 'uppercase', color: 'var(--fg-3)',
              minWidth: 72, flexShrink: 0, paddingTop: 1,
            }}>{key}</span>
            <span style={{ fontSize: 13, lineHeight: 1.55, color: 'var(--fg-2)' }}>{val}</span>
          </div>
        );
      })}
    </div>
  );
}

// ── Product gallery ───────────────────────────────────────────────────
function ProductGallery({ images, name }) {
  const [active, setActive] = React.useState(0);
  return (
    <div>
      <div style={{
        aspectRatio: '4/5', overflow: 'hidden', position: 'relative',
        background: 'var(--surface)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <img key={active} src={images[active]} alt={name} className="gallery-img"
          style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }} />
      </div>
      {images.length > 1 && (
        <div style={{ display: 'flex', gap: 8, marginTop: 12, overflowX: 'auto' }}>
          {images.map((src, i) => (
            <div key={i} onClick={() => setActive(i)} className="gallery-thumb" style={{
              width: 64, height: 80, flexShrink: 0, overflow: 'hidden', cursor: 'pointer',
              outline: i === active ? '1.5px solid var(--fg)' : '1.5px solid transparent',
              outlineOffset: 2, background: 'var(--surface)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              transition: 'outline-color .3s var(--ease)',
            }}>
              <img src={src} alt={`${name} view ${i + 1}`}
                style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }} />
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Product detail page ───────────────────────────────────────────────
function Product({ product, goTo, addToCart }) {
  useFadeUp();
  const loPrice = useCurrency();
  const mobile = useMobile();
  const [stickyVisible, setStickyVisible] = React.useState(false);
  const ctaRef = React.useRef(null);

  // Sizes — exclude "Custom" (that goes through the Bespoke flow)
  const sizes = React.useMemo(
    () => (product.sizes || []).filter(s => s !== 'Custom'),
    [product.id]
  );
  const [selectedSize, setSelectedSize] = React.useState('');
  const [showSizeGuide, setShowSizeGuide] = React.useState(false);
  // Reset when product changes — require explicit size selection
  React.useEffect(() => { setSelectedSize(''); }, [product.id]);

  React.useEffect(() => {
    setStickyVisible(false);
    window.scrollTo({ top: 0, behavior: 'instant' });
    try {
      const key = 'lo_rv';
      const prev = JSON.parse(localStorage.getItem(key) || '[]');
      const updated = [product.id, ...prev.filter(id => id !== product.id)].slice(0, 8);
      localStorage.setItem(key, JSON.stringify(updated));
    } catch (e) {}
  }, [product.id]);

  React.useEffect(() => {
    const el = ctaRef.current;
    if (!el) return;
    const io = new IntersectionObserver(
      ([entry]) => setStickyVisible(!entry.isIntersecting),
      { threshold: 0, rootMargin: '-64px 0px 0px 0px' }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [product.id]);

  const openBespoke = () => window.openBespoke && window.openBespoke({ product });

  const buyNow = () => {
    if (!addToCart) return;
    const sale = window.getSaleInfo && window.getSaleInfo(product);
    addToCart({
      id:          product.id,
      name:        product.name,
      frenchName:  product.frenchName,
      price:       (sale ? sale.sale : product.price),
      was:         sale ? sale.original : (product.comparePrice || null),
      color:       product.colors?.[0] || product.finish || '',
      size:        selectedSize,
      qty:         1,
      images:      product.images,
    });
  };

  return (
    <div data-screen-label="product">

      {/* Breadcrumb */}
      <div className="container" style={{ paddingTop: 28, paddingBottom: 20 }}>
        <div className="mono" style={{ color: 'var(--fg-3)' }}>
          <button onClick={() => goTo('home')} style={{ color: 'inherit' }}>Home</button>
          <span style={{ margin: '0 12px' }}>/</span>
          <button onClick={() => goTo('collection', { gender: product.gender })} style={{ color: 'inherit' }}>
            {product.gender}
          </button>
          <span style={{ margin: '0 12px' }}>/</span>
          <button onClick={() => goTo('collection', { gender: product.gender, category: product.category })} style={{ color: 'inherit' }}>
            {product.category}
          </button>
          <span style={{ margin: '0 12px' }}>/</span>
          <span style={{ color: 'var(--fg)' }}>{product.frenchName || product.name}</span>
        </div>
      </div>

      <section className="container product-detail-grid" style={{
        display: 'grid',
        gridTemplateColumns: mobile ? '1fr' : '1fr 440px',
        gap: mobile ? 24 : 40,
        alignItems: 'flex-start',
        paddingBottom: 80,
      }}>

        {/* Gallery */}
        <div style={{ position: 'relative' }}>
          {product.images && product.images.length > 0 ? (
            <ProductGallery images={product.images} name={product.name} />
          ) : (
            <Editorial product={product} variant="front"
              label={product.style} frame="FR · 0100"
              style={{ aspectRatio: '4/5' }} />
          )}
          {product.season === 'Luxury' && (
            <div style={{
              position: 'absolute', top: 18, right: 18, zIndex: 6,
              background: 'var(--fg)', color: 'var(--bg)',
              padding: '6px 12px', fontFamily: 'var(--font-mono)',
              fontSize: 10, letterSpacing: '.22em', textTransform: 'uppercase',
            }}>Luxury</div>
          )}
          <div className="mono" style={{
            display: 'flex', justifyContent: 'space-between',
            marginTop: 14, color: 'var(--fg-3)',
          }}>
            <span>{product.style}</span>
            <span>{product.finish}</span>
          </div>
        </div>

        {/* Info + CTA */}
        <div className="product-buy-sticky">
          <div style={{ position: mobile ? 'static' : 'sticky', top: 92 }}>

          <div className="mono" style={{ color: 'var(--fg-3)', marginBottom: 14 }}>
            {product.style}
          </div>

          <h1 className="display" style={{ fontSize: 'clamp(48px,5vw,76px)', margin: 0, lineHeight: .95 }}>
            {product.frenchName || product.name}
          </h1>

          {/* Price */}
          {(() => {
            const sale = window.getSaleInfo && window.getSaleInfo(product);
            return (
              <div style={{ marginTop: 20 }}>
                {sale && (
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 }}>
                    <span style={{
                      fontSize: 16, fontFamily: 'var(--font-display)',
                      color: 'var(--fg-3)', textDecoration: 'line-through',
                    }}>
                      {loPrice(sale.original)}
                    </span>
                    <span style={{
                      fontSize: 11, fontWeight: 700, letterSpacing: '.07em',
                      background: '#c0392b', color: '#fff',
                      padding: '3px 9px', borderRadius: 3,
                      fontFamily: 'var(--font-mono)',
                    }}>
                      -{sale.percent}% OFF
                    </span>
                  </div>
                )}
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                  <span style={{
                    fontSize: sale ? 30 : 24,
                    fontFamily: 'var(--font-display)',
                    fontWeight: sale ? 600 : 400,
                    color: sale ? '#c0392b' : 'var(--fg)',
                  }}>
                    {loPrice(sale ? sale.sale : product.price)}
                  </span>
                  <span style={{ fontSize: 12, color: 'var(--fg-3)' }}>
                    {(window.LO_CURRENCY || { code: 'USD' }).code}
                  </span>
                </div>
              </div>
            );
          })()}
          <div className="mono" style={{ fontSize: 9, color: 'var(--fg-3)', marginTop: 6, letterSpacing: '.06em' }}>
            Charged in USD · displayed currency is for reference only
          </div>

          {/* Structured description */}
          <StructuredDesc text={product.desc} />

          {/* Size selector + Buy + Customize */}
          <div ref={ctaRef} style={{ marginTop: 36 }}>

            {/* Size selector + Size guide link */}
            <div style={{ marginBottom: 20 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                <div className="mono" style={{
                  fontSize: 9.5, letterSpacing: '.18em', textTransform: 'uppercase',
                  color: 'var(--fg-3)',
                }}>Size</div>
                <button onClick={() => setShowSizeGuide(true)} className="mono"
                  style={{
                    fontSize: 9.5, letterSpacing: '.12em', color: 'var(--fg-3)',
                    textDecoration: 'underline', textDecorationColor: 'var(--line-2)',
                    textUnderlineOffset: '3px', cursor: 'pointer',
                    transition: 'color .15s',
                  }}
                  onMouseEnter={e => e.currentTarget.style.color = 'var(--fg)'}
                  onMouseLeave={e => e.currentTarget.style.color = 'var(--fg-3)'}>
                  Size guide
                </button>
              </div>
              {sizes.length > 0 && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                  {sizes.map(s => (
                    <button key={s} onClick={() => setSelectedSize(s)}
                      style={{
                        padding: '8px 16px',
                        fontFamily: 'var(--font-mono)', fontSize: 11,
                        letterSpacing: '.12em',
                        border: selectedSize === s
                          ? '1.5px solid var(--fg)'
                          : '.5px solid var(--line-2)',
                        background: selectedSize === s ? 'var(--fg)' : 'transparent',
                        color: selectedSize === s ? 'var(--bg)' : 'var(--fg)',
                        cursor: 'pointer',
                        transition: 'all .15s',
                      }}>
                      {s}
                    </button>
                  ))}
                </div>
              )}
            </div>

            {/* Buy button */}
            <button className="btn" style={{ width: '100%', padding: '18px' }}
              onClick={buyNow}
              disabled={sizes.length > 0 && !selectedSize}>
              Add to Cart <span className="arrow">→</span>
            </button>

            {/* Customize button */}
            <button className="btn ghost" style={{ width: '100%', padding: '16px', marginTop: 10 }}
              onClick={openBespoke}>
              Customize this piece <span className="arrow">→</span>
            </button>

            <p className="mono" style={{
              fontSize: 9.5, color: 'var(--fg-3)', marginTop: 12, lineHeight: 1.7,
            }}>
              Customize to choose your own leather type, colour, and hardware — built
              to your specifications as a bespoke commission.
            </p>
          </div>

          {/* Detail strip */}
          <div style={{
            marginTop: 36, paddingTop: 28, borderTop: '.5px solid var(--line)',
            display: 'flex', flexDirection: 'column', gap: 14,
          }}>
            {[
              ['Materials', product.materials],
              ['Fit',       product.fit],
              ['Production',product.origin],
              ['Lead time', 'Made-to-order in 2–4 weeks'],
              ['Shipping',  'Free worldwide shipping'],
            ].map(([k, v]) => v ? (
              <div key={k} style={{
                display: 'flex', justifyContent: 'space-between', gap: 16,
                fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '.06em',
              }}>
                <span style={{ color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '.18em' }}>{k}</span>
                <span style={{ color: 'var(--fg)', textAlign: 'right' }}>{v}</span>
              </div>
            ) : null)}
          </div>
          </div>{/* end sticky ordering panel */}
          <ProductReviews productId={product.id} inline />
        </div>
      </section>

      {/* Story strip */}
      <section style={{
        borderTop: '.5px solid var(--line)', background: 'var(--surf)',
        padding: '120px 0', marginTop: 40,
      }}>
        <div className="container">
          <div className="eyebrow" style={{ marginBottom: 24 }}>◇ &nbsp; About this piece</div>
          <div className="product-story-grid" style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 80 }}>
            <h2 className="display" style={{ fontSize: 'clamp(40px,5.4vw,80px)', margin: 0, lineHeight: 1 }}>
              <em>{product.finish}</em> — finished by hand in <em>full-grain</em>
              {' '}leather, made to <em className="gradient-text">your specifications.</em>
            </h2>
            <div>
              <p style={{ fontSize: 14, lineHeight: 1.7, color: 'var(--fg-2)', margin: 0 }}>
                Every {product.name} is cut and finished in our atelier on a per-order basis.
                Select your leather type, colour, hardware, and measurements through the Bespoke
                flow for a piece built exactly to you. Made to order and final sale — we accept
                returns only for a verified manufacturing flaw.
              </p>
              <div style={{ display: 'flex', gap: 14, marginTop: 28 }}>
                <button className="btn ghost sm" onClick={openBespoke}>
                  Customize this piece <span className="arrow">→</span>
                </button>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* Related products */}
      <section className="container" style={{ paddingTop: 120, paddingBottom: 80 }}>
        <header style={{ marginBottom: 48 }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>◇ &nbsp; You may also like</div>
          <h2 className="display" style={{ fontSize: 'clamp(40px,5vw,76px)', margin: 0 }}>
            Similar <em>pieces.</em>
          </h2>
        </header>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 28 }}>
          {(() => {
            const sameCat = PRODUCTS.filter(p => p.id !== product.id && p.category === product.category && p.gender === product.gender);
            const sameGender = PRODUCTS.filter(p => p.id !== product.id && p.gender === product.gender && p.category !== product.category);
            return [...sameCat, ...sameGender].slice(0, 4).map(p => (
              <ProductCard key={p.id} product={p} goTo={goTo} />
            ));
          })()}
        </div>
      </section>

      {/* Sticky Customize bar */}
      <div style={{
        position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 200,
        background: 'color-mix(in srgb,var(--bg) 92%,transparent)',
        backdropFilter: 'blur(20px)', WebkitBackdropFilter: 'blur(20px)',
        borderTop: '.5px solid var(--line)',
        transform: stickyVisible ? 'translateY(0)' : 'translateY(100%)',
        transition: 'transform .3s cubic-bezier(.22,.72,.36,1)',
        padding: '16px 0',
      }}>
        <div className="container" style={{
          display: 'flex', alignItems: 'center', gap: 24, justifyContent: 'space-between',
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 20, flex: 1, overflow: 'hidden' }}>
            <div style={{ width: 52, height: 68, flexShrink: 0, overflow: 'hidden' }}>
              {product.images?.[0]
                ? <img src={product.images[0]} alt={product.name}
                    style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }} />
                : <Editorial product={product} variant="front"
                    style={{ height: '100%', width: '100%', aspectRatio: 'auto' }} />
              }
            </div>
            <div style={{ overflow: 'hidden' }}>
              <div className="mono" style={{
                fontSize: 11, letterSpacing: '.12em', textTransform: 'uppercase',
                whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
              }}>{product.frenchName || product.name}</div>
              <div className="mono" style={{ color: 'var(--fg-3)', fontSize: 10, marginTop: 3 }}>
                {product.category} · {product.finish}
              </div>
            </div>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0 }}>
            {(() => {
              const sale = window.getSaleInfo && window.getSaleInfo(product);
              return sale ? (
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                  <span className="display" style={{ fontSize: 18, textDecoration: 'line-through', color: 'var(--fg-3)' }}>{loPrice(sale.original)}</span>
                  <span className="display" style={{ fontSize: 22, color: '#c0392b' }}>{loPrice(sale.sale)}</span>
                </div>
              ) : (
                <div className="display" style={{ fontSize: 22 }}>{loPrice(product.price)}</div>
              );
            })()}
            <button className="btn" style={{ padding: '14px 24px' }} onClick={buyNow}>
              Buy <span className="arrow">→</span>
            </button>
            <button className="btn ghost" style={{ padding: '14px 24px' }} onClick={openBespoke}>
              Customize
            </button>
          </div>
        </div>
      </div>

      <RecentlyViewed currentId={product.id} goTo={goTo} />
      {showSizeGuide && <SizeGuide product={product} onClose={() => setShowSizeGuide(false)} />}
    </div>
  );
}

// ── Shared review helpers ─────────────────────────────────────────────
function ReviewStars({ n, size = 14 }) {
  return (
    <span style={{ color: '#c9a233', fontSize: size, letterSpacing: 1, lineHeight: 1 }}>
      {'★'.repeat(Math.max(0, Math.min(5, n)))}{'☆'.repeat(5 - Math.max(0, Math.min(5, n)))}
    </span>
  );
}

async function compressReviewImage(file) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        const MAX = 1000;
        let w = img.width, h = img.height;
        if (w > MAX) { h = Math.round(h * MAX / w); w = MAX; }
        if (h > MAX) { w = Math.round(w * MAX / h); h = MAX; }
        const canvas = document.createElement('canvas');
        canvas.width = w; canvas.height = h;
        canvas.getContext('2d').drawImage(img, 0, 0, w, h);
        resolve(canvas.toDataURL('image/jpeg', 0.72));
      };
      img.src = e.target.result;
    };
    reader.readAsDataURL(file);
  });
}

function ReviewCard({ rv }) {
  const [lightbox, setLightbox] = React.useState(null);
  const photos = Array.isArray(rv.images) ? rv.images.filter(Boolean) : [];
  return (
    <div style={{ borderBottom: '0.5px solid var(--line-2)', paddingBottom: 24, marginBottom: 24 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
        <ReviewStars n={rv.rating} />
        <span className="mono" style={{ fontSize: 11, fontWeight: 600 }}>{rv.reviewer_name}</span>
        <span className="mono" style={{ fontSize: 10, color: 'var(--fg-3)' }}>
          {new Date(rv.created_at).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
        </span>
        {rv.product_id && <span className="mono" style={{ fontSize: 10, color: 'var(--fg-3)' }}>· {rv.product_id}</span>}
      </div>
      {rv.body && <p style={{ fontSize: 13, lineHeight: 1.7, color: 'var(--fg-2)', margin: '0 0 12px' }}>{rv.body}</p>}
      {photos.length > 0 && (
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          {photos.map((src, i) => (
            <img key={i} src={src} alt="Customer photo"
              onClick={() => setLightbox(src)}
              style={{ width: 80, height: 80, objectFit: 'cover', borderRadius: 3, cursor: 'zoom-in', border: '.5px solid var(--line-2)' }} />
          ))}
        </div>
      )}
      {lightbox && (
        <div onClick={() => setLightbox(null)}
          style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.88)', zIndex: 9999, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'zoom-out' }}>
          <img src={lightbox} style={{ maxWidth: '90vw', maxHeight: '90vh', objectFit: 'contain' }} />
        </div>
      )}
    </div>
  );
}

// ── Product Reviews ───────────────────────────────────────────────────
function ProductReviews({ productId, inline = false }) {
  const [reviews, setReviews] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [showForm, setShowForm] = React.useState(false);
  const [form, setForm] = React.useState({ name: '', rating: 5, comment: '' });
  const [images, setImages] = React.useState([]);
  const [submitted, setSubmitted] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);

  React.useEffect(() => {
    fetch(`/api/admin?a=review_list&product_id=${encodeURIComponent(productId)}`)
      .then(r => r.json())
      .then(d => { setReviews(d.reviews || []); setLoading(false); })
      .catch(() => setLoading(false));
  }, [productId]);

  const avg = reviews.length ? reviews.reduce((s, r) => s + r.rating, 0) / reviews.length : null;

  const handleImages = async (e) => {
    const files = [...e.target.files].slice(0, 3 - images.length);
    if (!files.length) return;
    const compressed = await Promise.all(files.map(compressReviewImage));
    setImages(prev => [...prev, ...compressed].slice(0, 3));
    e.target.value = '';
  };

  const submit = async () => {
    if (!form.name.trim() || !form.rating) return;
    setSubmitting(true);
    try {
      const r = await fetch('/api/admin?a=review_submit', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ product_id: productId, reviewer_name: form.name, rating: form.rating, comment: form.comment, images }),
      });
      if (r.ok) { setSubmitted(true); setShowForm(false); }
    } catch {}
    setSubmitting(false);
  };

  const fieldLabel = (t) => (
    <div className="mono" style={{ fontSize: 9, letterSpacing: '.14em', textTransform: 'uppercase', color: 'var(--fg-3)', marginBottom: 7 }}>{t}</div>
  );
  const fieldStyle = { width: '100%', border: '.5px solid var(--line-2)', borderRadius: 3, padding: '10px 14px', fontSize: 13, background: 'transparent', color: 'var(--fg)', outline: 'none', boxSizing: 'border-box' };

  return (
    <div {...(inline ? {} : { className: 'container' })}
      style={inline
        ? { paddingTop: 44, paddingBottom: 40, borderTop: '0.5px solid var(--line-2)' }
        : { paddingTop: 60, paddingBottom: 60, borderTop: '0.5px solid var(--line-2)' }}>
      <div className="mono" style={{ fontSize: 9.5, letterSpacing: '.22em', textTransform: 'uppercase', color: 'var(--fg-3)', marginBottom: 28 }}>
        Customer Reviews
      </div>

      {!loading && reviews.length > 0 && (
        <div style={{ marginBottom: 36 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginBottom: 28 }}>
            <span style={{ fontSize: 36, fontFamily: 'var(--font-display)', fontWeight: 400, lineHeight: 1 }}>{avg.toFixed(1)}</span>
            <ReviewStars n={Math.round(avg)} size={20} />
            <span className="mono" style={{ fontSize: 11, color: 'var(--fg-3)' }}>({reviews.length} review{reviews.length !== 1 ? 's' : ''})</span>
          </div>
          {reviews.slice(0, 8).map(rv => <ReviewCard key={rv.id} rv={rv} />)}
        </div>
      )}

      {!loading && reviews.length === 0 && !showForm && (
        <p style={{ fontSize: 13, color: 'var(--fg-3)', marginBottom: 24 }}>No reviews yet — be the first.</p>
      )}

      {submitted ? (
        <p className="mono" style={{ fontSize: 12, color: 'var(--fg-3)', letterSpacing: '.04em' }}>
          Thank you — your review is pending approval.
        </p>
      ) : showForm ? (
        <div style={{ maxWidth: 440 }}>
          <div className="mono" style={{ fontSize: 9, letterSpacing: '.22em', textTransform: 'uppercase', color: 'var(--fg-3)', marginBottom: 20 }}>Write a review</div>

          <div style={{ marginBottom: 16 }}>
            {fieldLabel('Your name')}
            <input value={form.name} onChange={e => setForm(f => ({ ...f, name: e.target.value }))} style={fieldStyle} />
          </div>

          <div style={{ marginBottom: 16 }}>
            {fieldLabel('Rating')}
            <div style={{ display: 'flex', gap: 4 }}>
              {[1,2,3,4,5].map(n => (
                <button key={n} onClick={() => setForm(f => ({ ...f, rating: n }))}
                  style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 26, color: n <= form.rating ? '#c9a233' : 'var(--line-2)', padding: '0 2px', lineHeight: 1 }}>★</button>
              ))}
            </div>
          </div>

          <div style={{ marginBottom: 16 }}>
            {fieldLabel('Comment (optional)')}
            <textarea value={form.comment} onChange={e => setForm(f => ({ ...f, comment: e.target.value }))}
              rows={4} style={{ ...fieldStyle, resize: 'vertical' }} />
          </div>

          <div style={{ marginBottom: 24 }}>
            {fieldLabel(`Photos — optional, up to 3`)}
            {images.length > 0 && (
              <div style={{ display: 'flex', gap: 8, marginBottom: 10, flexWrap: 'wrap' }}>
                {images.map((src, i) => (
                  <div key={i} style={{ position: 'relative' }}>
                    <img src={src} style={{ width: 80, height: 80, objectFit: 'cover', borderRadius: 3, border: '.5px solid var(--line-2)' }} />
                    <button onClick={() => setImages(imgs => imgs.filter((_, j) => j !== i))}
                      style={{ position: 'absolute', top: -5, right: -5, background: '#c0392b', color: '#fff', border: 'none', borderRadius: '50%', width: 18, height: 18, cursor: 'pointer', fontSize: 12, lineHeight: '18px', padding: 0, textAlign: 'center' }}>×</button>
                  </div>
                ))}
              </div>
            )}
            {images.length < 3 && (
              <label style={{ display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer', border: '.5px solid var(--line-2)', borderRadius: 3, padding: '8px 14px', fontSize: 12, fontFamily: 'var(--font-mono)', color: 'var(--fg-3)', letterSpacing: '.05em' }}>
                <span>+ Add photos</span>
                <input type="file" accept="image/*" multiple style={{ display: 'none' }} onChange={handleImages} />
              </label>
            )}
          </div>

          <div style={{ display: 'flex', gap: 12 }}>
            <button className="btn" onClick={submit} disabled={submitting} style={{ padding: '12px 24px', opacity: submitting ? .6 : 1 }}>
              {submitting ? 'Sending…' : 'Submit review →'}
            </button>
            <button className="btn ghost" onClick={() => { setShowForm(false); setImages([]); }} style={{ padding: '12px 24px' }}>Cancel</button>
          </div>
        </div>
      ) : (
        <button className="btn ghost" onClick={() => setShowForm(true)} style={{ padding: '12px 28px' }}>
          Write a review
        </button>
      )}
    </div>
  );
}

// ── Recently Viewed strip ─────────────────────────────────────────────
function RecentlyViewed({ currentId, goTo }) {
  const loPrice = useCurrency();
  const [products, setProducts] = React.useState([]);

  React.useEffect(() => {
    try {
      const ids = JSON.parse(localStorage.getItem('lo_rv') || '[]');
      const ps = ids
        .filter(id => id !== currentId)
        .map(id => PRODUCTS.find(p => p.id === id))
        .filter(Boolean).slice(0, 4);
      setProducts(ps);
    } catch (e) {}
  }, [currentId]);

  if (products.length < 2) return null;

  return (
    <section className="container" style={{
      paddingTop: 80, paddingBottom: 80,
      borderTop: '.5px solid var(--line)', marginTop: 40,
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 40 }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: 10 }}>◇ &nbsp; Recently viewed</div>
          <h2 className="display" style={{ fontSize: 'clamp(36px,4vw,60px)', margin: 0 }}>
            <em>Your history.</em>
          </h2>
        </div>
      </div>
      <div className="recently-viewed-grid" style={{
        display: 'grid', gridTemplateColumns: `repeat(${products.length},1fr)`, gap: 28,
      }}>
        {products.map(p => (
          <div key={p.id} className="card" onClick={() => goTo('product', { product: p })}>
            <Editorial product={p} ratio="3/4" />
            <div className="meta">
              <span className="name">{p.frenchName || p.name}</span>
              {(() => {
                const sale = window.getSaleInfo && window.getSaleInfo(p);
                return sale ? (
                  <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 2 }}>
                    <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--fg-3)', textDecoration: 'line-through' }}>{loPrice(sale.original)}</span>
                    <span className="price" style={{ color: '#c0392b' }}>{loPrice(sale.sale)}</span>
                  </div>
                ) : (
                  <span className="price">{loPrice(p.price)}</span>
                );
              })()}
            </div>
            <div className="status">
              {p.status === 'soldout' ? 'Sold out · Made-to-order' : `${p.finish} · ${p.gender}`}
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

Object.assign(window, { Product, RecentlyViewed, NATURAL_COLORS, DYED_COLORS, HARDWARE_COLORS });
