// Home page — hero, featured drop, categories, product grid, lookbook, info

const { useState: useStateH, useEffect: useEffectH, useMemo: useMemoH } = React;

// Spinning vinyl hero kept as an opt-in (Tweaks → Hero style: Vinyl)
function HeroVinyl() {
  return (
    <svg className="hero-vinyl" viewBox="0 0 600 600" aria-hidden="true">
      <defs>
        <radialGradient id="rec-grad" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#1a1612"/>
          <stop offset="60%" stopColor="#0a0908"/>
          <stop offset="100%" stopColor="#000"/>
        </radialGradient>
        <radialGradient id="rec-glow" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#c69464" stopOpacity="0.45"/>
          <stop offset="60%" stopColor="#c69464" stopOpacity="0"/>
        </radialGradient>
      </defs>
      {/* glow */}
      <circle cx="300" cy="300" r="300" fill="url(#rec-glow)"/>
      {/* vinyl */}
      <g style={{transformOrigin:'300px 300px', animation:'spin 22s linear infinite'}}>
        <circle cx="300" cy="300" r="290" fill="url(#rec-grad)"/>
        {Array.from({length: 80}).map((_, i) => (
          <circle key={i} cx="300" cy="300" r={290 - i * 2.6}
                  fill="none" stroke="#1a1612"
                  strokeWidth={i % 8 === 0 ? 0.6 : 0.25}
                  opacity={i % 8 === 0 ? 0.9 : 0.5}/>
        ))}
        {/* label */}
        <circle cx="300" cy="300" r="80" fill="#c69464"/>
        <circle cx="300" cy="300" r="80" fill="url(#rec-glow)"/>
        <text x="300" y="280" textAnchor="middle" fill="#0a0908" fontFamily="Newsreader" fontSize="22" fontStyle="italic" fontWeight="500">Peripheral</text>
        <text x="300" y="304" textAnchor="middle" fill="#0a0908" fontFamily="JetBrains Mono" fontSize="8" letterSpacing="3">VOLUME 02</text>
        <text x="300" y="322" textAnchor="middle" fill="#0a0908" fontFamily="JetBrains Mono" fontSize="7" letterSpacing="2">@PERIPHERALVINYL</text>
        <text x="300" y="336" textAnchor="middle" fill="#0a0908" fontFamily="JetBrains Mono" fontSize="6" letterSpacing="2" opacity="0.7">33 ⅓ RPM</text>
        {/* center hole */}
        <circle cx="300" cy="300" r="4" fill="#0a0908"/>
      </g>
    </svg>
  );
}

const TICKER_ITEMS = [
  'Made in Portugal', 'Worldwide Shipping', 'Volume 02 — Out Now',
  'Join Patreon — 5% Off', 'Free EU Shipping over €100', 'Limited Run', 'Made in Portugal',
  'Worldwide Shipping', 'Volume 02 — Out Now', 'Join Patreon — 5% Off', 'Free EU Shipping over €100', 'Limited Run',
];

// ── Hero: minimal Studio-Iki style (full-bleed image-slot + thin caption row) ─
function Hero({ onShop }) {
  return (
    <section className="hero-v2">
      <div className="hero-image">
        <video className="hero-bg-img" autoPlay muted loop playsInline preload="auto">
          <source src="/assets/hero-video.mp4" type="video/mp4"/>
        </video>
        <div className="hero-overlay-cta">
          <button className="hero-on-img-cta" onClick={onShop}
                  onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
            <span>Shop the collection</span>
            <Icon.arrow className="arrow" width={18} height={18}/>
          </button>
        </div>
      </div>
      <div className="hero-ticker" onClick={() => window.openEmailPopup?.()} style={{cursor:'none'}}>
        <div className="hero-ticker-inner">
          {[...TICKER_ITEMS, ...TICKER_ITEMS].map((t, i) => (
            <span key={i} className="hero-ticker-item">
              {t}<span className="dot">·</span>
            </span>
          ))}
        </div>
      </div>
    </section>
  );
}

function HeroVinylVersion({ onShop }) {
  return (
    <section className="hero">
      <div className="hero-stage" aria-hidden="true"/>
      <HeroVinyl/>
      <div className="hero-runner">
        <span>Side A · 04:32 / 38:14 · Sub-Floor → Long Player → Hypnose</span>
      </div>

      <div className="hero-top">
        <div className="eyebrow-block">
          <div className="eyebrow">Volume 02 — Limited Run</div>
          <div className="eyebrow" style={{color:'var(--accent)'}}>Now Shipping Worldwide</div>
        </div>
        <div className="eyebrow" style={{textAlign:'right'}}>
          Cat. № PVL/02<br/>
          Pressed in Portugal
        </div>
      </div>

      <div className="hero-content">
        <div className="eyebrow">A cinematic capsule for record nights</div>
        <h1 className="h-display">
          <em>Cut</em> for<br/>
          the closing <em>set</em>
        </h1>
        <p style={{ maxWidth: 540, color:'var(--fg-mute)', fontSize:17, lineHeight:1.6 }}>
          Heavyweight cotton, brushed-back fleece, and reinforced canvas —
          finished the way an old record sleeve is finished. Made in Portugal, in limited runs.
        </p>
        <button className="hero-cta" onClick={onShop}
                onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
          <span>Shop the Volume</span>
          <Icon.arrow className="arrow" width={18} height={18}/>
        </button>
      </div>
    </section>
  );
}

// ───────────────────────── drop banner ─────────────────────────
function DropBanner({ products, openProduct }) {
  const drop = products.filter(p => p.featured)[0];
  return (
    <section id="drop" className="section" style={{paddingTop: 40}}>
      <div className="section-head">
        <div className="left">
          <div className="eyebrow">The Drop · 03 / 12</div>
          <h2 className="h-1"><em>Volume 02</em> — the capsule</h2>
        </div>
        <div className="right">
          <span className="label-mono">Shipping March 2026</span>
        </div>
      </div>

      <div className="drop-banner">
        <div className="drop-banner-l">
          <div>
            <p style={{color:'var(--fg-mute)', maxWidth: 520, lineHeight:1.7, fontSize:16}}>
              A four-piece capsule that takes its cues from late-night Anjuna sets and
              the kind of record shop you find by accident on a side street in Lisbon.
              Considered cuts, weighty cotton, and one warm accent that ties everything together.
            </p>
          </div>
          <div className="drop-meta">
            <div className="drop-meta-row"><span className="l">Capsule</span><span className="r">04 pieces</span></div>
            <div className="drop-meta-row"><span className="l">Run size</span><span className="r">200 units / piece</span></div>
            <div className="drop-meta-row"><span className="l">Manufacturing</span><span className="r">Porto, Portugal</span></div>
            <div className="drop-meta-row"><span className="l">Designer</span><span className="r">In-house</span></div>
            <div className="drop-meta-row"><span className="l">Catalogue №</span><span className="r">PVL/02</span></div>
          </div>
          <button className="btn-secondary" style={{maxWidth:280, alignSelf:'flex-start'}}
                  onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
            View the capsule <Icon.arrow/>
          </button>
        </div>
        <div className="drop-banner-r" onClick={() => openProduct(drop)}
             onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
          <div style={{position:'absolute', inset:0, padding:'8% 14%',
                       background:`radial-gradient(60% 50% at 50% 40%, color-mix(in oklab, var(--accent-deep) 35%, transparent), transparent 75%), var(--bg-elev-2)`}}>
            <Garment kind={drop.silhouette} color={(drop?.printed?.[0] || drop?.embroidered?.[0])?.hex || '#888'}/>
          </div>
          <div style={{position:'absolute', left:24, bottom:24, right:24,
                       display:'flex', justifyContent:'space-between', alignItems:'flex-end',
                       background:'linear-gradient(to top, color-mix(in oklab, var(--bg) 60%, transparent), transparent)',
                       padding:24, margin:-24}}>
            <div>
              <div className="eyebrow" style={{color:'var(--accent)'}}>Featured · {drop.collection}</div>
              <div className="h-2" style={{marginTop:8}}>{drop.name}</div>
              <div className="label-mono" style={{marginTop:4}}>{drop.type}</div>
            </div>
            <div className="num" style={{fontSize:14}}>{window.fmt ? window.fmt((drop?.printed?.[0] || drop?.embroidered?.[0])?.price || drop.price) : `€${drop.price}`}</div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ───────────────────────── categories ─────────────────────────
function CategoryStrip({ onPick }) {
  const icons = {
    tees: 'tee',
    hoodies: 'hoodie',
    caps: 'cap5',
    totes: 'tote',
  };
  return (
    <section className="section" style={{paddingTop:0, paddingBottom:0}}>
      <div className="cats">
        {CATEGORIES.map((c, i) => (
          <a key={c.id} className="cat" onClick={() => onPick(c.id)}
             onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
            <div className="cat-num">0{i+1} / 04</div>
            <div>
              <div className="cat-name">{c.name}</div>
              <div className="cat-count" style={{marginTop: 6}}>{c.count} pieces</div>
            </div>
            <div className="cat-svg">
              <Garment kind={icons[c.id]} color="currentColor" graphic={false}/>
            </div>
          </a>
        ))}
      </div>
    </section>
  );
}

// Extra card entries injected into the collection grid.
// Each entry appears immediately after its parent product.
// { id, variantType, colorway, shirtColorIdx }
const GRID_EXTRA_CARDS = [
  { id: 'baggy-tee', variantType: 'printed',     colorway: 'Beach', shirtColorIdx: 1 },
  { id: 'crop-top',  variantType: 'printed',     colorway: 'Beach', shirtColorIdx: 1 },
  { id: 'pull-over', variantType: 'printed',     colorway: 'Beach', shirtColorIdx: 1 },
  { id: 'tank-top',  variantType: 'embroidered', colorway: 'Beach', shirtColorIdx: 1 },
];

function resolveExtraCard(p, cfg) {
  const cwArr = p[cfg.variantType] || [];
  const cwIdx = cwArr.findIndex(c => c.name === cfg.colorway);
  if (cwIdx < 0) return null;
  const scIdx = cfg.shirtColorIdx;
  if (scIdx >= (cwArr[cwIdx].shirtColors?.length ?? 0)) return null;
  return { p, initialVariantType: cfg.variantType, initialCwIdx: cwIdx, initialShirtColorIdx: scIdx };
}

// ───────────────────────── product grid ─────────────────────────
function ProductGrid({ products, openProduct, wish, onWish, filter, setFilter, sort, setSort }) {
  const filtered = useMemoH(() => {
    let arr = filter === 'all' ? products : products.filter(p => p.category === filter);
    if (sort === 'price-asc')  arr = [...arr].sort((a,b) => a.price - b.price);
    if (sort === 'price-desc') arr = [...arr].sort((a,b) => b.price - a.price);
    if (sort === 'alpha')      arr = [...arr].sort((a,b) => a.name.localeCompare(b.name));
    return arr;
  }, [products, filter, sort]);

  const gridCards = useMemoH(() => filtered.flatMap(p => {
    const extras = GRID_EXTRA_CARDS
      .filter(cfg => cfg.id === p.id)
      .map(cfg => resolveExtraCard(p, cfg))
      .filter(Boolean);
    return [{ p }, ...extras];
  }), [filtered]);

  return (
    <section id="shop" className="section">
      <div className="section-head">
        <div className="left">
          <div className="eyebrow">The Catalogue · {gridCards.length} pieces</div>
          <h2 className="h-1"><em>Shop</em> all</h2>
        </div>
      </div>

      <div className="toolbar">
        <div className="chips">
          <button className={`chip ${filter === 'all' ? 'on':''}`} onClick={() => setFilter('all')}
                  onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>All</button>
          {CATEGORIES.map(c => (
            <button key={c.id} className={`chip ${filter === c.id ? 'on':''}`} onClick={() => setFilter(c.id)}
                    onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
              {c.name}
            </button>
          ))}
        </div>
        <div className="right">
          <span>Sort</span>
          <select className="sort" value={sort} onChange={e => setSort(e.target.value)}>
            <option value="featured">Featured</option>
            <option value="price-asc">Price ↑</option>
            <option value="price-desc">Price ↓</option>
            <option value="alpha">A → Z</option>
          </select>
        </div>
      </div>

      <div className="grid">
        {gridCards.map((card, i) => (
          <ProductCard key={`${card.p.id}-${card.initialCwIdx ?? 0}-${card.initialShirtColorIdx ?? 0}`}
                       p={card.p} onOpen={openProduct} wish={wish} onWish={onWish}
                       initialVariantType={card.initialVariantType}
                       initialCwIdx={card.initialCwIdx}
                       initialShirtColorIdx={card.initialShirtColorIdx}/>
        ))}
      </div>
    </section>
  );
}

// ───────────────────────── lookbook ─────────────────────────
function LookbookItem({ shape='wide', label, color='#0a0908', kind='tee' }) {
  return (
    <div className={`lk ${shape}`}
         style={{ background: `radial-gradient(65% 55% at 50% 40%, ${color}33, transparent 75%), color-mix(in oklab, ${color} 55%, var(--bg-elev-2) 45%)` }}>
      <div style={{position:'absolute', inset:0, padding:'10% 16%', color:'var(--fg)'}}>
        <Garment kind={kind} color={color}/>
      </div>
      <div className="lk-caption">{label}</div>
    </div>
  );
}

function Lookbook() {
  return (
    <section id="lookbook" className="section" style={{paddingLeft:0, paddingRight:0}}>
      <div style={{padding: '0 var(--pad)'}}>
        <div className="section-head">
          <div className="left">
            <div className="eyebrow">Lookbook — 03 / 12</div>
            <h2 className="h-1"><em>The</em> Closing Set</h2>
          </div>
          <div className="right">
            <span className="label-mono">Photography · Studio 04</span>
          </div>
        </div>
      </div>

      <div className="lookbook">
        <LookbookItem shape="wide" label="01 — Sub-Floor, Black"   color="#1a1612" kind="tee"/>
        <LookbookItem shape="sq"   label="02 — Cartridge, Black"   color="#0a0908" kind="cap5"/>
        <LookbookItem shape="sq"   label="03 — Wax Crate, Natural" color="#a08458" kind="tote"/>
        <LookbookItem shape="tall" label="04 — Closing Set"        color="#c69464" kind="hoodie"/>
        <LookbookItem shape="tall" label="05 — Resident, Cream"    color="#d6cbb4" kind="beanie"/>
        <LookbookItem shape="tall" label="06 — Late Bloom"         color="#7a4a2b" kind="tee"/>
        <LookbookItem shape="tall" label="07 — Long Player"        color="#1a1612" kind="hoodie-zip"/>
      </div>
    </section>
  );
}

// ───────────────────────── size guide + faq accordions ─────────────────────────
function Accordion({ items, defaultOpen = null }) {
  const [open, setOpen] = useStateH(defaultOpen);
  return (
    <div className="acc">
      {items.map((it, i) => (
        <div key={i} className={`acc-item ${open === i ? 'open':''}`}>
          <button className="acc-head" onClick={() => setOpen(open === i ? null : i)}
                  onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
            <span className="h-2">{it.q}</span>
            <span className="plus">+</span>
          </button>
          <div className="acc-body">
            <div>
              <div className="acc-body-inner">{it.a}</div>
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

function SizeGuideSection() {
  const [tab, setTab] = useStateH('tee');
  const data = SIZES[tab];
  return (
    <section id="sizing" className="section">
      <div className="section-head">
        <div className="left">
          <div className="eyebrow">Sizing · in centimetres</div>
          <h2 className="h-1"><em>Size</em> guide</h2>
        </div>
        <div className="right" style={{display:'flex', gap:8}}>
          <button className={`chip ${tab==='tee' ? 'on':''}`} onClick={()=>setTab('tee')}>Tees & LS</button>
          <button className={`chip ${tab==='hoodie' ? 'on':''}`} onClick={()=>setTab('hoodie')}>Hoodies</button>
        </div>
      </div>
      <div style={{display:'grid', gridTemplateColumns:'1fr 1.4fr', gap:48, alignItems:'flex-start'}}>
        <div style={{color:'var(--fg-mute)', lineHeight:1.7, maxWidth:420}}>
          <p style={{marginBottom:14}}>
            Measurements are taken garment-flat. For a true-to-size fit, pick the row closest to your chest
            measurement. For a relaxed oversized look — the way these were cut — size up one.
          </p>
          <p>
            Models are between 5'10"–6'2" and wearing size M / L. If you sit between two sizes,
            we usually recommend the larger.
          </p>
        </div>
        <table className="size-table">
          <thead>
            <tr><th>Size</th><th>Chest (cm)</th><th>Length (cm)</th><th>Sleeve (cm)</th></tr>
          </thead>
          <tbody>
            {data.map(r => (
              <tr key={r.size}>
                <td>{r.size}</td>
                <td>{r.chest}</td>
                <td>{r.length}</td>
                <td>{r.sleeve}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </section>
  );
}

function FAQSection() {
  return (
    <section id="faq" className="section">
      <div className="section-head">
        <div className="left">
          <div className="eyebrow">Information</div>
          <h2 className="h-1"><em>Frequently</em> asked</h2>
        </div>
        <div className="right">
          <a className="section-link">Email us <Icon.arrow/></a>
        </div>
      </div>
      <Accordion items={FAQS.map(f => ({ q: f.q, a: <p>{f.a}</p> }))} defaultOpen={0}/>
    </section>
  );
}

// ───────────────────────── mid-page ticker divider ─────────────────────────
function MidTicker() {
  const items = ['Peripheral', 'Records', 'Volume 02 — Out Now', 'Limited Run', 'Join Patreon — 5% Off', 'Made in Portugal', 'Worldwide Shipping'];
  const repeated = [...items, ...items, ...items, ...items];
  return (
    <div className="mid-ticker" onClick={() => window.openEmailPopup?.()} style={{cursor:'none'}}>
      <span className="mid-ticker-inner">
        {repeated.map((t, i) => (
          <span key={i}>{t}<span className="dot"> · </span></span>
        ))}
      </span>
    </div>
  );
}

// ───────────────────────── product row (best sellers / new in) ─────────────────────────
function ProductRow({ id, eyebrow, title, products = [], cards, link, onLink, openProduct, wish, onWish, compact }) {
  const items = cards || products.map(p => ({ p }));
  return (
    <section id={id} className="section">
      <div className="section-head">
        <div className="left">
          <div className="eyebrow">{eyebrow}</div>
          <h2 className="h-2">{title}</h2>
        </div>
      </div>
      <div className="row-strip">
        {items.map(({ p, ...extra }) => (
          <ProductCard key={p.id + (extra.initialVariantType ? '-' + extra.initialVariantType : '')}
                       p={p} onOpen={openProduct} wish={wish} onWish={onWish} {...extra}/>
        ))}
      </div>
      {link && (
        <div className="section-cta-wrap">
          <button className="section-cta" onClick={onLink}
                  onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
            <span>{link}</span>
            <Icon.arrow className="arrow" width={18} height={18}/>
          </button>
        </div>
      )}
    </section>
  );
}

// ───────────────────────── about / press strip ─────────────────────────
function AboutSection() {
  return (
    <section id="about" className="section about">
      <div className="about-grid">
        <div className="about-image">
          <img src="/assets/banner-no-text.png" alt="Peripheral — studio session" className="about-bg-img"/>
        </div>
        <div className="about-copy">
          <div className="eyebrow">The label</div>
          <h2 className="h-2">
            Peripheral is a label for the people who still <em>buy records</em>.
          </h2>
          <p>
            Each Volume is a limited run — designed in-house, printed and finished to order.
            Heavyweight cottons, brushed-back fleece, garment-dyed colour, made to wear in.
          </p>
          <p>
            A meaningful share of every order funds the channel — studio time, mastering,
            and the records we play. When you wear it, you're keeping the platter spinning.
          </p>
          <div className="about-press">
            <div className="label-mono" style={{ color: 'var(--fg-dim)' }}>Tune in</div>
            <div className="press-row">
              <a href="https://www.youtube.com/@peripheralvinyl" target="_blank" rel="noreferrer" onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}><span>YouTube</span></a>
              <a href="https://www.instagram.com/peripheral.vinyl" target="_blank" rel="noreferrer" onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}><span>Instagram</span></a>
              <a href="https://soundcloud.com/peripheralvinyl" target="_blank" rel="noreferrer" onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}><span>SoundCloud</span></a>
              <a href="http://open.spotify.com/user/31zygcqtusf4yur7vtayweoyvtzu" target="_blank" rel="noreferrer" onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}><span>Spotify</span></a>
              <a href="https://discord.gg/qwEG4WAvAq" target="_blank" rel="noreferrer" onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}><span>Discord</span></a>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ────────────────────── collections strip ─────────────────────────
function CollectionsSection({ openCollection, products }) {
  const silhouettes = { tees: 'tee', knits: 'hoodie', cropped: 'tee-crop', bags: 'tote' };
  return (
    <section id="collections" className="section">
      <div className="section-head">
        <div className="left">
          <h2 className="h-2"><em>Browse</em> by collection</h2>
        </div>
      </div>
      <div className="collections">
        {COLLECTIONS.map((c, i) => {
          const firstProduct = (products || []).find(p => c.coverProduct ? p.id === c.coverProduct : p.category === c.cat);
          const cwArr = (c.coverVariant ? firstProduct?.[c.coverVariant] : null)
            || firstProduct?.printed || firstProduct?.embroidered || [];
          const firstCw = (c.coverColorway ? cwArr.find(cw => cw.name === c.coverColorway) : null) || cwArr[0];
          const coverImg = firstCw?.shirtColors?.[0]?.images?.[0] || firstCw?.images?.[0] || null;
          const count = (products || []).filter(p => p.category === c.cat).length;
          return (
            <a key={c.id} className="collection-card" onClick={() => openCollection(c.id)}
               onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
              <div className="collection-image">
                {coverImg ? (
                  <img src={coverImg} alt={c.name} className="collection-img"/>
                ) : (
                  <div className="collection-silhouette" aria-hidden="true">
                    <Garment kind={silhouettes[c.cat]} color="currentColor" graphic={false}/>
                  </div>
                )}
              </div>
              <div className="collection-meta">
                <div className="collection-num">{count} pieces</div>
                <div className="collection-name">{c.name}</div>
                <div className="collection-sub">{c.sub}</div>
                <div className="collection-link">View collection <Icon.arrow width={14} height={14}/></div>
              </div>
            </a>
          );
        })}
      </div>
      <div className="section-cta-wrap">
        <button className="section-cta" onClick={() => openCollection('all')}
                onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
          <span>View all</span>
          <Icon.arrow className="arrow" width={18} height={18}/>
        </button>
      </div>
    </section>
  );
}

// ────────────────────── collection page (sub-route) ──────────────────────
function CollectionPage({ id, products = [], openProduct, wish, onWish, onBack, openCollection }) {
  const [sort, setSort] = useStateH('featured');
  const isAll = id === 'all';
  const collection = isAll
    ? { id: 'all', name: 'All', sub: 'Everything in the drop' }
    : COLLECTIONS.find(c => c.id === id) || COLLECTIONS[0];
  let filtered = isAll ? products : products.filter(p => p.category === collection.cat);
  if (sort === 'price-asc')  filtered = [...filtered].sort((a,b)=>a.price-b.price);
  if (sort === 'price-desc') filtered = [...filtered].sort((a,b)=>b.price-a.price);
  if (sort === 'alpha')      filtered = [...filtered].sort((a,b)=>a.name.localeCompare(b.name));
  const products_compat = filtered; // rename for JSX below
  return (
    <main className="fade-in" style={{paddingTop:80}}>
      <section className="section collection-hero">
        <div className="pdp-crumb">
          <a onClick={onBack}
             onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>Shop</a>
          <span className="sep">/</span>
          <span>Collections</span>
          <span className="sep">/</span>
          <span>{collection.name}</span>
        </div>
        <div className="collection-head">
          <div>
            <h1 className="h-1"><em>{collection.name}</em></h1>
          </div>
          <div className="label-mono">{filtered.length} pieces</div>
        </div>
      </section>

      <section className="section" style={{paddingTop:0}}>
        <div className="toolbar" style={{borderBottom:'none', marginBottom:0}}>
          <div className="chips">
            <button className={`chip ${'all' === id ? 'on':''}`}
                    onClick={() => openCollection('all')}
                    onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
              All
            </button>
            {COLLECTIONS.map(c => (
              <button key={c.id}
                      className={`chip ${c.id === id ? 'on':''}`}
                      onClick={() => openCollection(c.id)}
                      onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
                {c.name}
              </button>
            ))}
          </div>
          <div className="right">
            <span>Sort</span>
            <select className="sort" value={sort} onChange={e=>setSort(e.target.value)}>
              <option value="featured">Featured</option>
              <option value="price-asc">Price ↑</option>
              <option value="price-desc">Price ↓</option>
              <option value="alpha">A → Z</option>
            </select>
          </div>
        </div>
        <div className="grid">
          {products_compat.flatMap(p => {
            const extras = GRID_EXTRA_CARDS
              .filter(cfg => cfg.id === p.id)
              .map(cfg => resolveExtraCard(p, cfg))
              .filter(Boolean);
            return [
              <ProductCard key={p.id} p={p} onOpen={openProduct} wish={wish} onWish={onWish}/>,
              ...extras.map(card => (
                <ProductCard key={`${card.p.id}-${card.initialCwIdx}-${card.initialShirtColorIdx}`}
                             p={card.p} onOpen={openProduct} wish={wish} onWish={onWish}
                             initialVariantType={card.initialVariantType}
                             initialCwIdx={card.initialCwIdx}
                             initialShirtColorIdx={card.initialShirtColorIdx}/>
              ))
            ];
          })}
        </div>
      </section>
    </main>
  );
}

// ────────────────────── second hero (bottom of page) ──────────────────────
function BottomHero() {
  return (
    <section className="bottom-hero">
      <img src="/assets/profile-cover.png" alt="Peripheral vinyl session" className="bottom-hero-img"/>
      <div className="bottom-hero-text">
        <div className="eyebrow" style={{ color: 'rgba(235,227,206,0.7)' }}>Peripheral — Vinyl Sessions</div>
        <h2 className="h-1" style={{ color: '#ebe3ce' }}>
          Hours of <em>melodic house</em><br/>on vinyl.
        </h2>
        <a className="hero-on-img-cta" href="https://www.youtube.com/@peripheralvinyl" target="_blank" rel="noreferrer"
           onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}
           style={{marginTop: 12}}>
          <span>Listen on YouTube</span>
          <Icon.arrow className="arrow" width={18} height={18}/>
        </a>
      </div>
    </section>
  );
}

const BEST_SELLER_CONFIG = [
  { id: 'baggy-tee', variantType: 'printed',    colorway: 'Sky'                          },
  { id: 'crop-top',  variantType: 'printed',    colorway: 'Rose', initialShirtColorIdx: 1 },
  { id: 'tote-bag',  variantType: 'printed',    colorway: 'Beach'                         },
  { id: 'pull-over', variantType: 'embroidered', colorway: 'Sky'                          },
];

// ───────────────────────── home root ─────────────────────────
function HomePage({ products = [], loading, openProduct, wish, onWish, openCollection, onShop }) {
  const bestSellerCards = BEST_SELLER_CONFIG.map(({ id, variantType, colorway, initialShirtColorIdx }) => {
    const p = products.find(pr => pr.id === id);
    if (!p) return null;
    const cwArr = p[variantType] || [];
    const cwIdx = cwArr.findIndex(cw => cw.name === colorway);
    return cwIdx >= 0 ? { p, initialVariantType: variantType, initialCwIdx: cwIdx, initialShirtColorIdx } : null;
  }).filter(Boolean);

  return (
    <main>
      <Hero onShop={onShop}/>
      <ProductRow id="best" title={<>Best sellers</>}
                  cards={bestSellerCards} openProduct={openProduct} wish={wish} onWish={onWish}
                  link="Shop all" onLink={() => openCollection('all')}
                  compact/>
      <CollectionsSection openCollection={openCollection} products={products}/>
      <BottomHero/>
    </main>
  );
}

// ───────────────────────── landing page ─────────────────────────
function LandingPage({ navigate }) {
  return (
    <main className="landing">
      <div className="landing-inner">
        <div className="eyebrow">Melodic house · On vinyl</div>
        <div className="landing-mark">
          <img src="/assets/logo-mark.png" alt="Peripheral"/>
        </div>
        <div className="landing-title">Peripheral</div>
        <div className="landing-sub">Volume 02 — Out Now</div>
        <div className="landing-ctas">
          <a className="landing-cta-primary"
             onClick={() => navigate({ name:'home' }, '/merch')}
             onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
            Shop merch <Icon.arrow width={18} height={18}/>
          </a>
          <a className="landing-cta-secondary" href="https://www.youtube.com/@peripheralvinyl" target="_blank" rel="noreferrer"
             onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
            Watch on YouTube <span style={{fontSize:12}}>↗</span>
          </a>
        </div>
      </div>
    </main>
  );
}

// ───────────────────────── full cart page ─────────────────────────
function CartPage({ cart, setCart, navigate, openProduct }) {
  const subtotal = cart.reduce((s, l) => s + l.price * l.qty, 0);
  const [confirmingDelete, setConfirmingDelete] = useStateH(null);

  const handleCheckout = async () => {
    const itemObjs = cart.map(l => {
      const vid = l.shirtColor?.variants?.[l.size];
      return vid ? { variantId: vid, qty: l.qty } : null;
    }).filter(Boolean);
    if (!itemObjs.length) return;
    const currency = window.shopCurrency || 'USD';
    try {
      const res = await fetch('/api/create-checkout', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ items: itemObjs, currency }),
      });
      if (!res.ok) throw new Error('api error');
      const { checkoutUrl, session } = await res.json();
      localStorage.setItem('pvl-checkout-session', session);
      window.location.href = checkoutUrl;
    } catch {
      const products = itemObjs.map(i => `${i.variantId}:${i.qty}`).join(',');
      const session = Date.now().toString(36) + Math.random().toString(36).slice(2);
      localStorage.setItem('pvl-checkout-session', session);
      window.location.href = `https://checkout.peripheralvinyl.com/cart/checkout?products=${products}&currency=${currency}&utm_content=${session}`;
    }
  };

  const updateQty = (key, delta) => {
    setCart(prev => prev
      .map(l => l.key === key ? { ...l, qty: Math.max(0, l.qty + delta) } : l)
      .filter(l => l.qty > 0)
    );
  };

  return (
    <main className="cart-page fade-in">
      <h1>Your Crate</h1>
      {cart.length === 0 ? (
        <div className="cart-page-empty">
          <Icon.cart width={48} height={48} style={{ color: 'var(--fg-dim)' }}/>
          <h3 className="h-2">Your crate is empty</h3>
          <p>Browse the collection and find something you love.</p>
          <button className="btn-primary" style={{ maxWidth: 240, marginTop: 8 }}
                  onClick={() => navigate({ name: 'home' }, '/merch')}
                  onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
            Back to shop <Icon.arrow/>
          </button>
        </div>
      ) : (
        <div className="cart-page-grid">
          <div className="cart-page-items">
            {[...cart].reverse().map(line => {
              const img = line.shirtColor?.images?.[0] || line.colorway?.images?.[0];
              const product = (window.PRODUCTS || []).find(p => p.id === line.id);
              const goToProduct = () => { if (product && openProduct) openProduct(product); };
              return (
                <div className="cart-item" key={line.key} style={{position:'relative', overflow:'visible'}}>
                  {confirmingDelete === line.key && (
                    <div style={{
                      position:'absolute', inset:'0 -32px', zIndex:10, borderRadius:8,
                      background:'color-mix(in oklab, var(--bg-elev) 88%, transparent)',
                      backdropFilter:'blur(6px)', WebkitBackdropFilter:'blur(6px)',
                      display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:14,
                    }} onClick={() => setConfirmingDelete(null)}>
                      <span style={{fontFamily:'var(--mono)', fontSize:11, letterSpacing:'0.1em', textTransform:'uppercase', color:'var(--fg)'}}>
                        {line.qty > 1 ? `Remove ${line.qty} items?` : 'Remove item?'}
                      </span>
                      <div style={{display:'flex', gap:10}} onClick={e => e.stopPropagation()}>
                        <button onClick={() => { setCart(prev => prev.filter(l => l.key !== line.key)); setConfirmingDelete(null); }}
                                onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
                                className="btn-primary" style={{padding:'8px 18px', fontSize:11, letterSpacing:'0.1em', background:'#c0392b', borderColor:'#c0392b'}}>
                          Remove
                        </button>
                        <button onClick={() => setConfirmingDelete(null)}
                                onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
                                className="btn-secondary" style={{padding:'8px 18px', fontSize:11, letterSpacing:'0.1em'}}>
                          Cancel
                        </button>
                      </div>
                    </div>
                  )}
                  <CartThumb line={line} img={img} onClick={goToProduct}/>
                  <div className="cart-info" onClick={goToProduct} style={{cursor:'none',flex:1}}>
                    <div className="nm">{line.name}</div>
                    <div className="vr">{line.colorway?.name} · {line.variantType === 'embroidered' ? 'Embroidered' : 'Print'}{line.shirtColor?.name ? ` · ${line.shirtColor.name}` : ''}</div>
                    <div className="vr">Size: {line.size}</div>
                    <div style={{display:'flex', alignItems:'center', gap:10, marginTop:12}} onClick={e => e.stopPropagation()}>
                      <div className="qty">
                        <button onClick={() => updateQty(line.key, -1)}
                                onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
                          <Icon.minus/>
                        </button>
                        <span className="v">{line.qty}</span>
                        <button onClick={() => updateQty(line.key, 1)}
                                onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
                          <Icon.plus/>
                        </button>
                      </div>
                      <button onClick={() => setConfirmingDelete(line.key)}
                              onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
                              className="x-btn" style={{display:'grid', placeItems:'center'}}>
                        <Icon.trash width={15} height={15}/>
                      </button>
                    </div>
                  </div>
                  <div className="cart-right" onClick={goToProduct} style={{cursor:'none'}}>
                    <span className="num">{window.fmt ? window.fmt(line.price * line.qty) : `€${(line.price * line.qty).toFixed(0)}`}</span>
                  </div>
                </div>
              );
            })}
          </div>
          <div className="cart-page-summary">
            <h3>Order Summary</h3>
            {[...cart].reverse().map(line => (
              <div className="cart-summary-line" key={line.key}>
                <span className="k">{line.name} × {line.qty}</span>
                <span className="num">{window.fmt ? window.fmt(line.price * line.qty) : `€${(line.price * line.qty).toFixed(0)}`}</span>
              </div>
            ))}
            <div className="cart-summary-total">
              <div style={{display:'flex', flexDirection:'column', gap:4}}>
                <span className="k">Subtotal</span>
                <div style={{ fontSize: 10, fontFamily: 'var(--mono)', color: 'var(--fg-dim)', letterSpacing: '0.08em' }}>
                  Tax &amp; shipping calculated at checkout
                </div>
                {localStorage.getItem('pvl-currency') === 'EUR' && (
                  <div style={{ fontSize: 10, fontFamily: 'var(--mono)', color: 'var(--fg-dim)', letterSpacing: '0.08em' }}>
                    Free shipping on EU orders over €100
                  </div>
                )}
              </div>
              <span className="v">{window.fmt ? window.fmt(subtotal) : `€${subtotal.toFixed(0)}`}</span>
            </div>
            <button className="btn-primary" onClick={handleCheckout}
                    onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
              Checkout <Icon.arrow/>
            </button>
            <button className="btn-secondary" onClick={() => navigate({ name: 'home' }, '/merch')}
                    onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
              Continue shopping
            </button>
          </div>
        </div>
      )}
    </main>
  );
}

const ExtLink = () => (
  <svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" style={{ marginLeft: 5, verticalAlign: 'middle', opacity: 0.7 }}>
    <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
    <polyline points="15 3 21 3 21 9"/>
    <line x1="10" y1="14" x2="21" y2="3"/>
  </svg>
);

function OrderCompletePage({ setCart, navigate, friendlyId, orderId, placedAt }) {
  const { useEffect: useEffectOC, useState: useStateOC } = React;
  const [copied, setCopied] = useStateOC(false);
  useEffectOC(() => { setCart([]); }, []);

  const copyOrderNumber = () => {
    navigator.clipboard.writeText(friendlyId).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };

  const formattedDate = placedAt ? (() => {
    const d = new Date(placedAt);
    return d.toLocaleString(undefined, { day: 'numeric', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' });
  })() : null;

  return (
    <main className="fade-in" style={{ paddingTop: 120, paddingBottom: 80, minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div style={{ maxWidth: 520, width: '100%', padding: '0 24px', textAlign: 'center' }}>
        <div className="eyebrow" style={{ marginBottom: 20 }}>Order confirmed</div>
        <h1 className="h-1" style={{ marginBottom: 16 }}>Thank you!</h1>
        {friendlyId && (
          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
              <p style={{ fontFamily: 'var(--mono)', fontSize: 13, letterSpacing: '0.08em', color: 'var(--fg)', margin: 0 }}>
                Order No. <span style={{ fontWeight: 700 }}>#{friendlyId}</span>
              </p>
            <button onClick={copyOrderNumber}
                    onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
                    title="Copy order number"
                    style={{ background: 'none', border: 'none', cursor: 'none', padding: 4, color: copied ? 'var(--accent)' : 'var(--fg-mute)', display: 'flex', alignItems: 'center', transition: 'color 0.15s' }}>
              {copied ? (
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
              ) : (
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
              )}
            </button>
            </div>
            {formattedDate && (
              <p style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.06em', color: 'var(--fg-mute)', fontWeight: 300, margin: '6px 0 0' }}>
                {formattedDate}
              </p>
            )}
          </div>
        )}
        <p style={{ color: 'var(--fg-mute)', lineHeight: 1.7, marginBottom: 12 }}>
          Your order is heading to the team in Portugal. You'll get a confirmation email from Fourthwall shortly with all the details.
        </p>
        <p style={{ color: 'var(--fg-mute)', lineHeight: 1.7, marginBottom: 40, fontFamily: 'var(--mono)', fontSize: 12, letterSpacing: '0.06em' }}>
          Ships in 3–5 business days.
        </p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12, maxWidth: 280, margin: '0 auto' }}>
          <button className="btn-primary" onClick={() => navigate({ name: 'home' }, '/merch')}
                  onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
            Back to shop <Icon.arrow/>
          </button>
          <a className="btn-secondary" href="https://www.patreon.com/peripheralvinyl/membership" target="_blank" rel="noreferrer"
             onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
             style={{ textAlign: 'center', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7 }}>
            <Icon.patreon/> Support me on Patreon <ExtLink/>
          </a>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <a className="btn-secondary" href="https://www.youtube.com/@peripheralvinyl" target="_blank" rel="noreferrer"
               onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
               style={{ textAlign: 'center', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, padding: '11px 12px', fontSize: 10 }}>
              <Icon.yt/> YouTube <ExtLink/>
            </a>
            <a className="btn-secondary" href="https://www.instagram.com/peripheral.vinyl" target="_blank" rel="noreferrer"
               onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}
               style={{ textAlign: 'center', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, padding: '11px 12px', fontSize: 10 }}>
              <Icon.ig/> Instagram <ExtLink/>
            </a>
          </div>
        </div>
      </div>
    </main>
  );
}

function CheckoutPendingPage({ navigate }) {
  const { useState: useStateCPP, useEffect: useEffectCPP } = React;
  const [timedOut, setTimedOut] = useStateCPP(false);
  const [confirming, setConfirming] = useStateCPP(false);

  useEffectCPP(() => {
    const t = setTimeout(() => setTimedOut(true), 6 * 60 * 1000);
    let hiddenAt = null;
    const onVisibility = () => {
      if (document.visibilityState === 'hidden') {
        hiddenAt = Date.now();
      } else if (hiddenAt && (Date.now() - hiddenAt) > 20000) {
        // Only switch to confirming if they were away for 20+ seconds — long
        // enough to have realistically completed checkout.
        setConfirming(true);
      }
    };
    document.addEventListener('visibilitychange', onVisibility);
    return () => { clearTimeout(t); document.removeEventListener('visibilitychange', onVisibility); };
  }, []);

  const goBack = () => {
    window._stopOrderPolling?.();
    localStorage.removeItem('pvl-checkout-session');
    navigate({ name: 'home' }, '/merch');
  };

  const spinner = (
    <div style={{ marginBottom: 40 }}>
      <div style={{ width: 28, height: 28, borderRadius: '50%', border: '1px solid var(--accent)', borderTopColor: 'transparent', animation: 'spin 0.9s linear infinite', display: 'inline-block' }}/>
    </div>
  );

  return (
    <main style={{ paddingTop: 120, paddingBottom: 80, minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div style={{ maxWidth: 480, width: '100%', padding: '0 24px', textAlign: 'center' }}>
        {timedOut ? (
          <>
            <div className="eyebrow" style={{ marginBottom: 20 }}>We couldn't confirm your order</div>
            <h1 className="h-1" style={{ marginBottom: 24 }}>Check your email</h1>
            <p style={{ color: 'var(--fg-mute)', lineHeight: 1.7, marginBottom: 16 }}>
              If you completed checkout, Fourthwall will have sent a confirmation to your inbox.
            </p>
            <p style={{ color: 'var(--fg-mute)', lineHeight: 1.7, marginBottom: 40 }}>
              If you didn't finish, no worries — your crate is still saved. Something go wrong? <a href="/merch/contact" style={{ color: 'var(--accent)' }}>Get in touch →</a>
            </p>
          </>
        ) : confirming ? (
          <>
            <div className="eyebrow" style={{ marginBottom: 20 }}>Almost there</div>
            <h1 className="h-1" style={{ marginBottom: 24 }}>Confirming your order…</h1>
            <p style={{ color: 'var(--fg-mute)', lineHeight: 1.7, marginBottom: 40 }}>
              This only takes a moment.
            </p>
            {spinner}
          </>
        ) : (
          <>
            <div className="eyebrow" style={{ marginBottom: 20 }}>Checkout in progress</div>
            <h1 className="h-1" style={{ marginBottom: 24 }}>Complete your checkout</h1>
            <p style={{ color: 'var(--fg-mute)', lineHeight: 1.7, marginBottom: 40 }}>
              Finish your order and your confirmation will appear here automatically.
            </p>
            {spinner}
          </>
        )}
        <button className="btn-secondary" onClick={goBack}
                onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
          Back to shop
        </button>
      </div>
    </main>
  );
}

Object.assign(window, { HomePage, LandingPage, Hero, ProductRow, CollectionsSection, CollectionPage, AboutSection, BottomHero, ProductGrid, Accordion, SizeGuideSection, FAQSection, CartPage, OrderCompletePage, CheckoutPendingPage });
