// Shared components: nav, logo, garments, product card, footer, now-playing

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ───────────────────────── icons ─────────────────────────
const Icon = {
  search: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  bag:    (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M5 8h14l-1 12H6L5 8Z"/><path d="M8.5 8a3.5 3.5 0 0 1 7 0"/></svg>,
  heart:  (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M12 20s-7-4.35-7-10a4 4 0 0 1 7-2.65A4 4 0 0 1 19 10c0 5.65-7 10-7 10Z"/></svg>,
  heartFill:(p)=> <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" {...p}><path d="M12 20s-7-4.35-7-10a4 4 0 0 1 7-2.65A4 4 0 0 1 19 10c0 5.65-7 10-7 10Z"/></svg>,
  user:   (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>,
  close:  (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M6 6 18 18M18 6 6 18"/></svg>,
  arrow:  (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  plus:   (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  minus:  (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M5 12h14"/></svg>,
  star:   (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" {...p}><path d="m12 2 2.95 6.65 7.05.8-5.3 4.8 1.6 7.05L12 17.7l-6.3 3.6 1.6-7.05L2 9.45l7.05-.8L12 2Z"/></svg>,
  yt:     (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" {...p}><path d="M23 7.5s-.2-1.6-.9-2.3c-.9-.9-1.8-.9-2.3-1C16.5 4 12 4 12 4s-4.5 0-7.8.2c-.5.1-1.4.1-2.3 1C1.2 5.9 1 7.5 1 7.5S.8 9.3.8 11.2v1.6c0 1.9.2 3.7.2 3.7s.2 1.6.9 2.3c.9.9 2.1.9 2.6 1 1.9.2 8 .2 8 .2s4.5 0 7.8-.2c.5-.1 1.4-.1 2.3-1 .7-.7.9-2.3.9-2.3s.2-1.8.2-3.7v-1.6c0-1.9-.2-3.7-.2-3.7ZM10 15V8l6 3.5-6 3.5Z"/></svg>,
  ig:     (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r=".8" fill="currentColor"/></svg>,
  sc:     (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" {...p}><path d="M2 16c0-.8.5-1.5 1.2-1.8.1 1 .3 2 .6 2.8C3 16.8 2 16.6 2 16Zm3-2.4c.3 0 .6.1.9.2-.1 1.1.1 2.3.5 3.4-.4.4-.9.6-1.4.6V13.6Zm2.4-.4c.3-.1.6-.1.9-.1.1 1.4.5 2.7 1.3 3.8-.4.3-.9.5-1.4.6-.5-1.3-.8-2.8-.8-4.3Zm2.6 0c.3.1.7.2 1 .3.3 1.7 1 3.2 2.1 4.4-.4.3-.8.5-1.4.5-1.1-1.5-1.7-3.3-1.7-5.2Zm3 1c.4.2.7.4 1 .7.7 1.6 1.9 3 3.4 3.8-.4.4-1 .7-1.6.7-1.4-1.3-2.4-3-2.8-5.2Zm3 2c0-3 2.5-5.6 5.5-5.6S22 13.2 22 16.2c0 .8-.2 1.6-.5 2.3H16Z"/></svg>,
  tt:     (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" {...p}><path d="M19 8.4a6.4 6.4 0 0 1-4-1.4v8.3a5.7 5.7 0 1 1-5.7-5.7c.4 0 .7 0 1 .1v3a2.8 2.8 0 1 0 1.9 2.6V2h3a4.4 4.4 0 0 0 3.8 3.7v2.7Z"/></svg>,
  spotify:(p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" {...p}><path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm4.6 14.4a.6.6 0 0 1-.9.2c-2.4-1.4-5.4-1.8-9-1a.6.6 0 1 1-.3-1.2c4-.9 7.3-.5 10 1.1a.6.6 0 0 1 .2.9Zm1.2-2.6a.8.8 0 0 1-1.1.2c-2.8-1.7-7-2.2-10.3-1.2a.8.8 0 1 1-.4-1.6c3.8-1.1 8.4-.6 11.6 1.4.4.2.5.7.2 1.1Zm.1-2.7c-3.3-2-8.8-2.2-12-1.2a1 1 0 1 1-.6-1.9c3.7-1.1 9.7-.9 13.6 1.4a1 1 0 0 1-1 1.7Z"/></svg>,
};

// ───────────────────────── garment SVGs ─────────────────────────
// Stylized, monochromatic apparel silhouettes. Designed to read as
// editorial product photography placeholders. User can drop in real
// images via <image-slot>.
function Garment({ kind, color = 'currentColor', graphic = true, back = false }) {
  // viewBox 0 0 200 240
  const common = { width: '100%', height: '100%', viewBox: '0 0 200 240', preserveAspectRatio: 'xMidYMid meet' };
  const stroke = 'currentColor';
  const fill = color;

  const Label = () => (
    <g opacity="0.85">
      <text x="100" y="122" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="7" letterSpacing="3" fill="currentColor">PVL</text>
      <line x1="82" y1="126" x2="118" y2="126" stroke="currentColor" strokeWidth="0.6"/>
    </g>
  );
  const BackGraphic = () => (
    <g opacity="0.7">
      <circle cx="100" cy="130" r="24" fill="none" stroke="currentColor" strokeWidth="0.8"/>
      <circle cx="100" cy="130" r="17" fill="none" stroke="currentColor" strokeWidth="0.8"/>
      <circle cx="100" cy="130" r="10" fill="none" stroke="currentColor" strokeWidth="0.8"/>
      <circle cx="100" cy="130" r="5"  fill="currentColor"/>
    </g>
  );

  if (kind === 'tee' || kind === 'tee-crop') {
    const bottom = kind === 'tee-crop' ? 175 : 220;
    return (
      <svg {...common}>
        <path d={`M40 70 L70 50 Q85 56 100 56 Q115 56 130 50 L160 70 L150 95 L138 90 L138 ${bottom} L62 ${bottom} L62 90 L50 95 Z`}
              fill={fill} stroke={stroke} strokeWidth="1.2"/>
        <path d="M82 56 Q100 70 118 56" fill="none" stroke={stroke} strokeWidth="1"/>
        <path d="M70 50 L75 72 M130 50 L125 72" fill="none" stroke={stroke} strokeWidth="0.6" opacity="0.5"/>
        {graphic && !back && <Label />}
        {back && <BackGraphic />}
      </svg>
    );
  }
  if (kind === 'longsleeve') {
    return (
      <svg {...common}>
        <path d="M30 70 L70 50 Q85 56 100 56 Q115 56 130 50 L170 70 L168 175 L155 180 L150 95 L138 92 L138 220 L62 220 L62 92 L50 95 L45 180 L32 175 Z"
              fill={fill} stroke={stroke} strokeWidth="0.6"/>
        <path d="M76 54 Q100 64 124 54 L122 60 Q100 68 78 60 Z" fill={stroke} opacity="0.18"/>
        {graphic && !back && <Label />}
        {back && <BackGraphic />}
      </svg>
    );
  }
  if (kind === 'hoodie' || kind === 'hoodie-zip' || kind === 'pullover') {
    return (
      <svg {...common}>
        {kind === 'hoodie' && (
          <path d="M76 36 Q100 22 124 36 Q132 50 130 60 L70 60 Q68 50 76 36 Z"
                fill={fill} stroke={stroke} strokeWidth="1"/>
        )}
        <path d="M38 76 L70 58 L130 58 L162 76 L154 100 L142 94 L142 220 L58 220 L58 94 L46 100 Z"
              fill={fill} stroke={stroke} strokeWidth="1.2"/>
        {kind === 'hoodie' && (
          <path d="M80 62 Q100 86 120 62" fill="none" stroke={stroke} strokeWidth="0.8"/>
        )}
        {kind === 'pullover' && (
          <>
            <path d="M82 58 Q100 72 118 58 L116 64 Q100 74 84 64 Z" fill={stroke} opacity="0.22"/>
            <path d="M82 58 Q100 72 118 58" fill="none" stroke={stroke} strokeWidth="0.6"/>
          </>
        )}
        {kind === 'hoodie' && (
          <>
            <line x1="94" y1="74" x2="92" y2="120" stroke={stroke} strokeWidth="0.8"/>
            <line x1="106" y1="74" x2="108" y2="120" stroke={stroke} strokeWidth="0.8"/>
            <circle cx="92" cy="121" r="1.8" fill={stroke}/>
            <circle cx="108" cy="121" r="1.8" fill={stroke}/>
            <path d="M70 140 Q100 156 130 140 L132 175 L68 175 Z" fill="none" stroke={stroke} strokeWidth="0.8" opacity="0.6"/>
          </>
        )}
        {kind === 'hoodie-zip' && (
          <line x1="100" y1="62" x2="100" y2="220" stroke={stroke} strokeWidth="0.6" strokeDasharray="2 2"/>
        )}
        {graphic && !back && <Label />}
        {back && <BackGraphic />}
      </svg>
    );
  }
  if (kind === 'tote') {
    return (
      <svg {...common}>
        <path d="M75 60 Q75 30 100 30 Q125 30 125 60" fill="none" stroke={stroke} strokeWidth="3"/>
        <path d="M50 60 L150 60 L160 220 L40 220 Z" fill={fill} stroke={stroke} strokeWidth="1.2"/>
        <rect x="72" y="58" width="6" height="14" fill={stroke} opacity="0.5"/>
        <rect x="122" y="58" width="6" height="14" fill={stroke} opacity="0.5"/>
        {graphic && !back && <Label />}
        {back && <BackGraphic />}
      </svg>
    );
  }
  if (kind === 'cap5') {
    return (
      <svg {...common}>
        {/* crown */}
        <path d="M45 130 Q45 90 100 86 Q155 90 155 130 L150 142 L50 142 Z" fill={fill} stroke={stroke} strokeWidth="0.6"/>
        {/* panel seams */}
        <line x1="100" y1="86" x2="100" y2="142" stroke={stroke} strokeWidth="0.3" opacity="0.4"/>
        <line x1="75" y1="92" x2="80" y2="142" stroke={stroke} strokeWidth="0.3" opacity="0.4"/>
        <line x1="125" y1="92" x2="120" y2="142" stroke={stroke} strokeWidth="0.3" opacity="0.4"/>
        {/* brim */}
        <path d="M40 142 Q100 168 160 142 L155 154 Q100 175 45 154 Z" fill={fill} stroke={stroke} strokeWidth="0.6"/>
        {/* logo */}
        {graphic && (
          <g opacity="0.75">
            <text x="100" y="124" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="6" letterSpacing="2" fill={stroke}>PVL</text>
          </g>
        )}
      </svg>
    );
  }
  if (kind === 'cap-trucker') {
    return (
      <svg {...common}>
        <path d="M45 130 Q45 90 100 86 Q155 90 155 130 L150 142 L50 142 Z" fill={fill} stroke={stroke} strokeWidth="0.6"/>
        {/* mesh back hint */}
        <pattern id="mesh" patternUnits="userSpaceOnUse" width="4" height="4"><circle cx="2" cy="2" r="0.4" fill={stroke} opacity="0.6"/></pattern>
        <path d="M120 95 Q140 100 155 130 L150 142 L120 142 Z" fill="url(#mesh)" opacity="0.5"/>
        <path d="M45 95 Q60 92 80 90 L80 142 L50 142 Z" fill="url(#mesh)" opacity="0.5"/>
        <path d="M40 142 Q100 168 160 142 L155 154 Q100 175 45 154 Z" fill={fill} stroke={stroke} strokeWidth="0.6"/>
        {graphic && <rect x="86" y="106" width="28" height="14" fill="none" stroke={stroke} strokeWidth="0.6" opacity="0.8"/>}
      </svg>
    );
  }
  if (kind === 'beanie') {
    return (
      <svg {...common}>
        <path d="M50 100 Q50 60 100 60 Q150 60 150 100 L150 150 Q150 170 130 175 L70 175 Q50 170 50 150 Z"
              fill={fill} stroke={stroke} strokeWidth="0.6"/>
        {/* ribbed cuff */}
        <rect x="50" y="148" width="100" height="28" fill="none" stroke={stroke} strokeWidth="0.3" opacity="0.5"/>
        {[58, 68, 78, 88, 98, 108, 118, 128, 138].map(x => (
          <line key={x} x1={x} y1="148" x2={x} y2="176" stroke={stroke} strokeWidth="0.3" opacity="0.5"/>
        ))}
        {graphic && <rect x="88" y="156" width="24" height="10" fill={stroke} opacity="0.25"/>}
      </svg>
    );
  }
  if (kind === 'tank') {
    return (
      <svg {...common}>
        {/* armhole-deep tank with low arm cuts */}
        <path d={`M68 60 Q85 56 100 56 Q115 56 132 60 L138 66 L132 92 Q124 84 124 78 L124 220 L76 220 L76 78 Q76 84 68 92 L62 66 Z`}
              fill={fill} stroke={stroke} strokeWidth="0.6"/>
        <path d="M82 56 Q100 70 118 56" fill="none" stroke={stroke} strokeWidth="0.5"/>
        {graphic && !back && <Label />}
        {back && <BackGraphic />}
      </svg>
    );
  }
  if (kind === 'pullover') {
    return (
      <svg {...common}>
        {/* crewneck pullover (no hood) */}
        <path d="M38 76 L70 58 L130 58 L162 76 L154 100 L142 94 L142 220 L58 220 L58 94 L46 100 Z"
              fill={fill} stroke={stroke} strokeWidth="0.6"/>
        {/* ribbed crewneck */}
        <path d="M82 58 Q100 72 118 58 L116 64 Q100 74 84 64 Z" fill={stroke} opacity="0.16"/>
        <path d="M82 58 Q100 72 118 58" fill="none" stroke={stroke} strokeWidth="0.4"/>
        {/* ribbed hem */}
        <line x1="58" y1="212" x2="142" y2="212" stroke={stroke} strokeWidth="0.3" opacity="0.4"/>
        {graphic && !back && <Label />}
        {back && <BackGraphic />}
      </svg>
    );
  }
  if (kind === 'carrier') {
    return (
      <svg {...common}>
        {/* longer/larger carrier bag */}
        <path d="M65 50 Q65 18 100 18 Q135 18 135 50" fill="none" stroke={stroke} strokeWidth="2.4"/>
        <path d="M42 50 L158 50 L168 222 L32 222 Z" fill={fill} stroke={stroke} strokeWidth="0.6"/>
        <rect x="62" y="48" width="6" height="16" fill={stroke} opacity="0.4"/>
        <rect x="132" y="48" width="6" height="16" fill={stroke} opacity="0.4"/>
        {graphic && !back && <Label />}
        {back && <BackGraphic />}
      </svg>
    );
  }
  return null;
}

// ───────────────────────── product card ─────────────────────────
function ProductCard({ p, onOpen, wish, onWish }) {
  const [cwIdx, setCwIdx] = useState(0);
  const isWished = wish.has(p.id);
  const card = useRef(null);

  // Resolve the active colorway — prefer printed, fall back to embroidered
  const colorways = p.printed?.length ? p.printed : (p.embroidered || []);
  const cw      = colorways[cwIdx] || colorways[0];
  const frontImg = cw?.images?.[0];
  const backImg  = frontImg; // designs are one-sided — don't swap to blank back on hover
  const bg       = cw?.hex || '#e8dfc8';

  return (
    <article className="card fade-in" ref={card}
             onMouseEnter={() => onCursor('hover')}
             onMouseLeave={() => onCursor('default')}
             onClick={() => { onCursor('default'); onOpen(p); }}>
      <div className="card-media">
        {frontImg ? (
          <>
            <div className="main" style={{ position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center',
                 background: `radial-gradient(70% 55% at 50% 42%, color-mix(in oklab, ${bg} 14%, #1a1612), #0f0d0a)` }}>
              <img src={frontImg} alt={p.name} style={{ width:'100%', height:'100%', objectFit:'contain', padding:'6% 10%' }}/>
            </div>
            <div className="alt" style={{ display:'flex', alignItems:'center', justifyContent:'center',
                 background: `radial-gradient(70% 55% at 50% 42%, color-mix(in oklab, ${bg} 14%, #1a1612), #0f0d0a)` }}>
              <img src={backImg} alt={p.name} style={{ width:'100%', height:'100%', objectFit:'contain', padding:'6% 10%' }}/>
            </div>
          </>
        ) : (
          <>
            <div className="main" style={{ position:'absolute', inset:0, padding:'10% 16%', color:'#ebe3ce',
                 background: `radial-gradient(75% 60% at 50% 42%, color-mix(in oklab, ${bg} 40%, #1a1612), #0f0d0a)` }}>
              <Garment kind={p.silhouette} color={bg}/>
            </div>
            <div className="alt" style={{ padding:'10% 16%', color:'#ebe3ce',
                 background: `radial-gradient(75% 60% at 50% 58%, color-mix(in oklab, ${bg} 32%, #1a1612), #0f0d0a)` }}>
              <Garment kind={p.silhouette} color={bg} back graphic={false}/>
            </div>
          </>
        )}
      </div>

      {p.featured && <div className="card-tag featured">Volume 02</div>}

      <div className="card-swatches">
        {(p.colors || []).slice(0, 5).map((c, i) => (
          <span key={i} className="swatch" title={c.name}
                style={{ background: c.hex, boxShadow: cwIdx === i ? '0 0 0 2px #fff, 0 0 0 3.5px rgba(0,0,0,0.6)' : 'none' }}
                onClick={(e) => { e.stopPropagation(); setCwIdx(i); }}/>
        ))}
      </div>

      <button className={`card-wish ${isWished ? 'on':''}`} onClick={(e)=>{e.stopPropagation(); onWish(p.id);}}
              onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
        {isWished ? <Icon.heartFill/> : <Icon.heart/>}
      </button>

      <div className="card-meta">
        <div>
          <div className="name">{p.name}</div>
          <div className="label-mono" style={{marginTop:4}}>{p.type}</div>
        </div>
        <div className="price num">€{p.price}</div>
      </div>
    </article>
  );
}

// tint a hex color toward warm light
function tint(hex, amt) {
  return `color-mix(in oklab, ${hex} ${100 - amt*100}%, var(--accent-warm) ${amt*100}%)`;
}

// ───────────────────────── nav ─────────────────────────
function Nav({ route, setRoute, cartCount, wishCount, onOpenCart, onOpenSearch, onOpenWish, openCollection }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 24);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  const goHome = () => setRoute({ name: 'home' });
  const goSection = (id) => { if (route.name !== 'home') setRoute({ name:'home' }); setTimeout(() => scrollToId(id), 50); };
  return (
    <header className={`nav ${scrolled ? 'scrolled' : ''}`}>
      <nav className="nav-left">
        <a className={`nav-link ${route.name==='home' ? 'active':''}`} onClick={goHome}>Shop</a>
        <a className={`nav-link ${route.name==='collection' ? 'active':''}`} onClick={() => openCollection('tees')}>Collections</a>
        <a className="nav-link" onClick={() => goSection('about')}>About</a>
      </nav>
      <a className="logo" onClick={() => setRoute({name:'home'})}
         onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
        <span className="logo-mark"><img src="assets/logo-mark.png" alt=""/></span>
        <span className="logo-word">Peripheral</span>
      </a>
      <div className="nav-right">
        <button className="nav-icon" onClick={onOpenSearch} aria-label="Search"><Icon.search/></button>
        <button className="nav-icon" onClick={onOpenWish} aria-label="Wishlist">
          <Icon.heart/>
          {wishCount > 0 && <span className="badge num">{wishCount}</span>}
        </button>
        <button className="nav-icon" onClick={onOpenCart} aria-label="Cart">
          <Icon.bag/>
          {cartCount > 0 && <span className="badge num">{cartCount}</span>}
        </button>
      </div>
    </header>
  );
}

function scrollToId(id) {
  const el = document.getElementById(id);
  if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 80, behavior: 'smooth' });
}

// ───────────────────────── footer ─────────────────────────
function Footer({ setRoute }) {
  const [email, setEmail] = useState('');
  const [submitted, setSubmitted] = useState(false);
  return (
    <footer className="footer">
      <div className="footer-display" aria-hidden="true">
        <span className="marquee">
          <em>Peripheral</em><span className="dot"> · </span>
          Records<span className="dot"> · </span>
          <em>Volume 02</em><span className="dot"> · </span>
          Out Now<span className="dot"> · </span>
          <em>Peripheral</em><span className="dot"> · </span>
          Records<span className="dot"> · </span>
          <em>Volume 02</em><span className="dot"> · </span>
          Out Now<span className="dot"> · </span>
        </span>
      </div>
      <div className="footer-top">
        <div className="footer-col">
          <h4>Newsletter</h4>
          <p style={{color:'var(--fg-mute)', maxWidth:340, marginBottom:16}}>
            Quiet emails for record drops, mixes, and the occasional behind-the-scenes note. No spam.
          </p>
          <form className="newsletter" onSubmit={(e)=>{e.preventDefault(); setSubmitted(true);}}>
            <input type="email" placeholder="your@email.com" value={email} onChange={e=>setEmail(e.target.value)} />
            <button onMouseEnter={()=>onCursor('hover')} onMouseLeave={()=>onCursor('default')}>
              {submitted ? 'Thanks ✓' : 'Subscribe →'}
            </button>
          </form>
        </div>
        <div className="footer-col">
          <h4>Shop</h4>
          <ul>
            <li><a>Tops</a></li>
            <li><a>Hoodies & Pullovers</a></li>
            <li><a>Cropped</a></li>
            <li><a>Bags</a></li>
          </ul>
        </div>
        <div className="footer-col">
          <h4>Info</h4>
          <ul>
            <li><a>Shipping & Returns</a></li>
            <li><a>Size Guide</a></li>
            <li><a>FAQ</a></li>
            <li><a>Contact</a></li>
          </ul>
        </div>
        <div className="footer-col">
          <h4>Elsewhere</h4>
          <ul>
            <li><a target="_blank" rel="noreferrer" href="https://www.youtube.com/@peripheralvinyl"><span style={{display:'inline-flex', alignItems:'center', gap:8}}><Icon.yt/> YouTube</span></a></li>
            <li><a><span style={{display:'inline-flex', alignItems:'center', gap:8}}><Icon.ig/> Instagram</span></a></li>
            <li><a><span style={{display:'inline-flex', alignItems:'center', gap:8}}><Icon.sc/> SoundCloud</span></a></li>
            <li><a><span style={{display:'inline-flex', alignItems:'center', gap:8}}><Icon.spotify/> Spotify</span></a></li>
            <li><a><span style={{display:'inline-flex', alignItems:'center', gap:8}}><Icon.tt/> TikTok</span></a></li>
          </ul>
        </div>
      </div>
      <div className="footer-bot">
        <div>© 2026 Peripheral. All rights reserved.</div>
        <div>Fulfilment by Fourthwall · Made in Portugal</div>
      </div>
    </footer>
  );
}

// ───────────────────────── now playing widget ─────────────────────────
function NowPlaying() {
  const tracks = [
    { side: 'A1', title: 'Yotto — Walls of Jericho (Mix 02)' },
    { side: 'A2', title: 'Ben Böhmer — Lights Out (live edit)' },
    { side: 'B1', title: 'Tinlicker — Because You Move Me' },
    { side: 'B2', title: 'Marsh — Endless (Anjuna Deep)' },
  ];
  const [i, setI] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setI(v => (v + 1) % tracks.length), 8000);
    return () => clearInterval(id);
  }, []);
  return (
    <div className="now-playing">
      <div className="np-spin"/>
      <div className="np-text">
        <div className="l1">Now Spinning · Side {tracks[i].side}</div>
        <div className="l2">{tracks[i].title}</div>
      </div>
    </div>
  );
}

// ───────────────────────── custom cursor helpers ─────────────────────────
function onCursor(mode) {
  const c = document.getElementById('cursor');
  if (!c) return;
  c.classList.remove('hover','text');
  if (mode && mode !== 'default') c.classList.add(mode);
}

function useCursor() {
  useEffect(() => {
    const c = document.getElementById('cursor');
    if (!c) return;
    if (!c.querySelector('.vinyl')) {
      const inner = document.createElement('div');
      inner.className = 'vinyl';
      c.appendChild(inner);
    }
    let x = window.innerWidth / 2, y = window.innerHeight / 2;
    let tx = x, ty = y;
    let needsSnap = false;

    // When the window loses focus (e.g. window.open opens a new tab), mark for snap.
    // On the next real mousemove we teleport the lerp source to avoid a catch-up zoop.
    const onBlur  = () => { needsSnap = true; };
    const onMove  = (e) => {
      tx = e.clientX; ty = e.clientY;
      if (needsSnap) { x = tx; y = ty; needsSnap = false; }
    };

    window.addEventListener('mousemove', onMove);
    window.addEventListener('blur',      onBlur);

    let raf;
    const tick = () => {
      x += (tx - x) * 0.28;
      y += (ty - y) * 0.28;
      c.style.left = x + 'px';
      c.style.top  = y + 'px';
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('blur',      onBlur);
      cancelAnimationFrame(raf);
    };
  }, []);
}

// expose
Object.assign(window, { Icon, Garment, ProductCard, Nav, Footer, NowPlaying, onCursor, useCursor, scrollToId, tint });
