// Gallery — curated mosaic, no category filter. 10 tiles.
function PSGallery() {
  const items = [
    { src: 'assets/g-leather-jacket.jpg', before: 'assets/g-leather-jacket-before.jpg', cat: 'Apparel', name: 'Leather · Jeans' },
    { src: 'assets/g-candle-vanity.jpg', before: 'assets/g-byredo-bath-before.jpg', cat: 'Homeware', name: 'Candle · Vanity' },
    { src: 'assets/faceoil-output.jpg', before: 'assets/faceoil-scene.jpg', cat: 'Skincare', name: 'Serum · Skin' },
    { src: 'assets/g-gold-pendant.jpg', before: 'assets/g-gold-pendant-before.jpg', cat: 'Jewelry', name: 'Pendant · Necklace' },
    { src: 'assets/g-shelf-skincare.jpg', before: 'assets/g-shelf-skincare-before.jpg', cat: 'Skincare', name: 'Serum · Skin' },
    { src: 'assets/g-face-wash.jpg', before: 'assets/g-amber-bottle-before.jpg', cat: 'Skincare', name: 'Face Wash · Cleanser' },
    { src: 'assets/g-beverly-hills.jpg', before: 'assets/g-beverly-hills-before.jpg', cat: 'Apparel', name: 'Clothes · Top & Shorts' },
    { src: 'assets/g-cowgirl-guitar.jpg', before: 'assets/g-cowgirl-guitar-before.jpg', cat: 'Apparel', name: 'Pants · Shirt' },
    { src: 'assets/g-brown-set.jpg', before: 'assets/g-brown-set-before.jpg', cat: 'Apparel', name: 'Top · Pants' },
    { src: 'assets/g-manu-kitchen.jpg', before: 'assets/g-manu-kitchen-before.jpg', cat: 'Apparel', name: 'Sweater · Pants' },
    { src: 'assets/g-volvo-peace.jpg', before: 'assets/g-volvo-peace-before.jpg', cat: 'Swimwear', name: 'Bikini · One Piece' },
    { src: 'assets/g-bomber-back.jpg', before: 'assets/g-bomber-back-before.jpg', cat: 'Apparel', name: 'Jacket · Jeans' },
  ];

  // Preload before-images so hover crossfade is instant
  React.useEffect(() => {
    items.forEach(it => { if (it.before) { const i = new Image(); i.src = it.before; } });
  }, []);

  return (
    <section id="examples" className="ps-section" data-mobile-pad="true" data-mobile-y="xs" style={{ background: 'var(--cream)', padding: '128px 48px' }}>
      <div className="ps-stack-mobile" style={{ maxWidth: 1320, margin: '0 auto 64px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 64, alignItems: 'end' }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: 14 }}>
            <span style={{ display: 'inline-block', width: 24, height: 1, background: 'var(--cocoa)', verticalAlign: 'middle', marginRight: 12 }}></span>
            Examples
          </div>
          <h2 className="celestial" style={{ fontSize: 'clamp(48px,6vw,96px)', color: 'var(--cocoa)', margin: 0 }}>
            Real scenes,<br/>placed products.
          </h2>
        </div>
        <p style={{ fontFamily: '"La Villa", sans-serif', fontSize: 17, lineHeight: 1.6, color: 'var(--fg-2)', maxWidth: 460, margin: 0, justifySelf: 'end' }}>
          Across skincare, jewelry, clothing, homeware. Choose an image from our library of <span style={{ color: 'var(--cocoa)' }}>10,000+</span> Vault Stock photographs, or upload your own. The product is yours, dropped in.
        </p>
      </div>

      <div className="ps-stack-mobile-2" style={{
        maxWidth: 1320, margin: '0 auto',
        display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
        gap: 12,
      }}>
        {items.map((it, i) => (
          <GalleryTile key={i} item={it} autoHint={i === 0} />
        ))}
      </div>

      {/* See-more link to the dedicated Examples page */}
      <div style={{
        maxWidth: 1320, margin: '64px auto 0',
        display: 'flex', justifyContent: 'center',
      }}>
        <a href="/examples" style={{
          display: 'inline-flex', alignItems: 'center', gap: 12,
          fontFamily: '"La Villa", sans-serif',
          fontSize: 14, letterSpacing: '0.18em', textTransform: 'uppercase',
          color: 'var(--cocoa)', textDecoration: 'none',
          padding: '18px 32px',
          border: '1px solid var(--cocoa)',
          borderRadius: 999, fontWeight: 500,
          transition: 'background 220ms var(--pe), color 220ms',
        }}
        onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--cocoa)'; e.currentTarget.style.color = 'var(--cream)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'var(--cocoa)'; }}>
          See full examples library
          <span aria-hidden="true" style={{ letterSpacing: 0 }}>→</span>
        </a>
      </div>
    </section>
  );
}

function GalleryTile({ item, autoHint }) {
  const [hover, setHover] = React.useState(false);
  const [tapped, setTapped] = React.useState(false);
  const [isTouch, setIsTouch] = React.useState(false);
  const tileRef = React.useRef(null);
  const hasBefore = !!item.before;
  // On touch devices, ignore hover entirely — iOS Safari fakes hover on tap and
  // sticks it, which made the toggle feel broken. Touch users get strict tap toggle.
  const showBefore = hasBefore && (tapped || (!isTouch && hover));

  // One-time hint flip on the first tile: when it scrolls into view, briefly
  // show the Before so mobile users learn the tap gesture.
  React.useEffect(() => {
    if (!autoHint || !hasBefore || !tileRef.current) return;
    const el = tileRef.current;
    let played = false;
    const obs = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !played) {
          played = true;
          const t1 = setTimeout(() => setTapped(true), 600);
          const t2 = setTimeout(() => setTapped(false), 1900);
          obs.disconnect();
          return () => { clearTimeout(t1); clearTimeout(t2); };
        }
      });
    }, { threshold: 0.4 });
    obs.observe(el);
    return () => obs.disconnect();
  }, [autoHint, hasBefore]);

  const handleTap = (e) => {
    if (!hasBefore) return;
    if (e && e.preventDefault) e.preventDefault();
    setTapped(t => !t);
  };

  return (
    <div
      ref={tileRef}
      role={hasBefore ? 'button' : undefined}
      tabIndex={hasBefore ? 0 : undefined}
      aria-pressed={hasBefore ? tapped : undefined}
      aria-label={hasBefore ? `${item.name} — tap to compare before and after` : undefined}
      onTouchStart={() => { if (!isTouch) setIsTouch(true); setHover(false); }}
      onMouseEnter={() => { if (!isTouch) setHover(true); }}
      onMouseLeave={() => setHover(false)}
      onClick={handleTap}
      onKeyDown={(e) => { if (hasBefore && (e.key === 'Enter' || e.key === ' ')) handleTap(e); }}
      style={{
        position: 'relative', overflow: 'hidden', cursor: hasBefore ? 'pointer' : 'default',
        background: 'var(--cream-deep)',
        aspectRatio: '2 / 3',
        userSelect: 'none',
        WebkitTapHighlightColor: 'transparent',
      }}>
      {/* AFTER (default) */}
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: `url(${item.src})`,
        backgroundSize: 'cover', backgroundPosition: 'center',
        transform: (hover || tapped) && !hasBefore ? 'scale(1.03)' : 'scale(1)',
        opacity: showBefore ? 0 : 1,
        transition: 'transform 600ms cubic-bezier(.22,.61,.36,1), opacity 420ms ease',
      }} />
      {/* BEFORE, only if provided, fades in on hover OR tap */}
      {hasBefore && (
        <div style={{
          position: 'absolute', inset: 0,
          backgroundImage: `url(${item.before})`,
          backgroundSize: 'cover', backgroundPosition: 'center',
          opacity: showBefore ? 1 : 0,
          transition: 'opacity 420ms ease',
        }} />
      )}
      {/* Vignette for legibility */}
      <div style={{
        position: 'absolute', inset: 0,
        background: 'linear-gradient(0deg, rgba(42,36,32,0.55) 0%, rgba(42,36,32,0) 50%)',
        opacity: (hover || tapped) ? 1 : 0.7,
        transition: 'opacity 300ms',
      }} />
      {/* Before / After toggle pill, top-left — visibly button-like so mobile users know to tap */}
      {hasBefore && (
        <div style={{
          position: 'absolute', top: 12, left: 12,
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '6px 10px',
          background: showBefore ? 'rgba(242,236,228,0.92)' : 'rgba(28,23,21,0.62)',
          backdropFilter: 'blur(4px)',
          color: showBefore ? 'var(--cocoa)' : 'var(--cream)',
          fontFamily: '"La Villa", sans-serif',
          fontSize: 9.5, letterSpacing: '0.22em', textTransform: 'uppercase',
          fontWeight: 500, borderRadius: 999,
          transition: 'all 240ms',
        }}>
          <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
            <path d="M7 7l-3 3 3 3" />
            <path d="M4 10h13a3 3 0 010 6h-3" />
          </svg>
          {showBefore ? 'Before' : 'After'}
        </div>
      )}
      <div style={{
        position: 'absolute', left: 14, bottom: 14, right: 14,
        display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end',
        color: 'var(--cream)',
      }}>
        <div>
          <div style={{ fontFamily: '"La Villa", sans-serif', fontSize: 9.5, letterSpacing: '0.22em', textTransform: 'uppercase', opacity: 0.85, marginBottom: 4 }}>{item.cat}</div>
          <div style={{ fontFamily: '"La Villa", sans-serif', fontStyle: 'normal', fontSize: 16 }}>{item.name}</div>
        </div>
        <div style={{
          width: 30, height: 30, borderRadius: 999,
          background: showBefore ? 'var(--cream)' : 'rgba(242,236,228,0.18)',
          color: showBefore ? 'var(--cocoa)' : 'var(--cream)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          transition: 'all 240ms',
        }} aria-hidden="true">
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" style={{ transform: showBefore ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 320ms cubic-bezier(.22,.61,.36,1)' }}>
            <path d="M16 4l4 4-4 4" />
            <path d="M20 8H6" />
            <path d="M8 20l-4-4 4-4" />
            <path d="M4 16h14" />
          </svg>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { PSGallery });
