/* ============================================================
   Shared UI primitives + icons  →  window globals
   ============================================================ */
const { useState, useEffect, useRef, useContext, createContext, useReducer } = React;

/* ---------- Icons (simple line set) ---------- */
const I = {
  bag: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M6 8h12l-1 12H7L6 8Z" strokeLinejoin="round"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></svg>,
  search: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.2-3.2"/></svg>,
  user: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 4-6 8-6s8 2 8 6"/></svg>,
  heart: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M12 20s-7-4.4-7-9.5A4 4 0 0 1 12 7a4 4 0 0 1 7 3.5C19 15.6 12 20 12 20Z" strokeLinejoin="round"/></svg>,
  menu: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M4 7h16M4 12h16M4 17h16"/></svg>,
  close: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M6 6l12 12M18 6 6 18"/></svg>,
  plus: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  minus: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M5 12h14"/></svg>,
  star: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="m12 3 2.6 5.6 6.1.7-4.5 4.2 1.2 6L12 16.9 6.6 19.5l1.2-6L3.3 9.3l6.1-.7L12 3Z"/></svg>,
  arrow: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M5 12h14M13 6l6 6-6 6" strokeLinejoin="round" strokeLinecap="round"/></svg>,
  check: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" {...p}><path d="m5 13 4 4 10-11" strokeLinejoin="round" strokeLinecap="round"/></svg>,
  truck: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M3 6h11v9H3zM14 9h4l3 3v3h-7z"/><circle cx="7" cy="18" r="1.8"/><circle cx="17" cy="18" r="1.8"/></svg>,
  shield: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3Z" strokeLinejoin="round"/></svg>,
  gift: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M4 11h16v9H4zM4 8h16v3H4zM12 8v12M12 8c-1-3-5-3-5-1s4 1 5 1Zm0 0c1-3 5-3 5-1s-4 1-5 1Z" strokeLinejoin="round"/></svg>,
  globe: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18"/></svg>,
  ig: (p) => <svg viewBox="0 0 24 24" 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" cy="7" r="1" fill="currentColor" stroke="none"/></svg>,
  pin: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><circle cx="12" cy="12" r="9"/><path d="M12 7c-1.7 0-3 1.3-3 3 0 1.4 1 2 1 3s-.6 2.5-.6 2.5M12 7c1.7 0 3 1.3 3 3 0 2-2.3 2.3-3 4"/></svg>,
  tiktok: (p) => <svg viewBox="0 0 24 24" fill="currentColor" stroke="none" {...p}><path d="M19.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 0 1-2.88 2.5 2.89 2.89 0 0 1-2.89-2.89 2.89 2.89 0 0 1 2.89-2.89c.28 0 .54.04.79.1V9.01a6.33 6.33 0 0 0-.79-.05 6.34 6.34 0 0 0-6.34 6.34 6.34 6.34 0 0 0 6.34 6.34 6.34 6.34 0 0 0 6.33-6.34V8.69a8.18 8.18 0 0 0 4.78 1.52V6.77a4.85 4.85 0 0 1-1.01-.08Z"/></svg>,
  box: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M4 8l8-4 8 4v8l-8 4-8-4V8Z" strokeLinejoin="round"/><path d="M4 8l8 4 8-4M12 12v8" strokeLinejoin="round"/></svg>,
  car: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M4 16v-3.4L6.2 7h11.6L20 12.6V16" strokeLinejoin="round"/><path d="M4 12.6h16"/><circle cx="8" cy="16.6" r="1.7"/><circle cx="16" cy="16.6" r="1.7"/></svg>,
  cpu: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><rect x="7" y="7" width="10" height="10" rx="1.5"/><rect x="10.5" y="10.5" width="3" height="3"/><path d="M9 4v3M15 4v3M9 17v3M15 17v3M4 9h3M4 15h3M17 9h3M17 15h3"/></svg>,
  wa: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M21 11.7a8.6 8.6 0 0 1-12.6 7.6L4 20.5l1.3-4.2A8.6 8.6 0 1 1 21 11.7Z" strokeLinejoin="round"/><path d="M9.2 9.3c.4 3 2.5 5.1 5.5 5.5l1-1.4 2 .9c-.3 1.5-1.5 2.2-3 1.9-3.4-.7-6.2-3.5-6.9-6.9-.3-1.5.4-2.7 1.9-3l.9 2-1.4 1Z" strokeLinejoin="round"/></svg>,
  doc: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M6 3h9l4 4v14H6V3Z" strokeLinejoin="round"/><path d="M15 3v4h4M9 12h6M9 16h6"/></svg>,
};

/* ---------- Hero panel — video with a full-colour still as poster/fallback.
   The poster <img> always renders underneath; the <video> layers on top and
   unmounts itself on error (missing/unset clip), so the poster is the
   guaranteed fallback — never an empty panel. ---------- */
function HeroPanel({ poster, video, label, style }) {
  const [failed, setFailed] = useState(false);
  return (
    <div className="ph" data-label="" style={{ position: 'relative', ...style }}>
      <img src={poster} alt={label || ''} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} loading="lazy" decoding="async" />
      {!failed && video && (
        <video src={video} poster={poster} autoPlay muted loop playsInline preload="metadata" onError={() => setFailed(true)}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
      )}
    </div>
  );
}

/* ---------- Placeholder / Real image ---------- */
function Ph({ label, variant = '', style, className = '', src, video, videoSrc, children }) {
  const [err, setErr] = useState(false);
  const showImg = src && !err && !video;
  const showVideo = video && !err;
  return (
    <div className={`ph ${variant} ${className}`} data-label={(showImg || showVideo) ? '' : label} style={style}>
      {showImg && (
        <img
          src={src}
          alt={label || ''}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
          loading="lazy"
          decoding="async"
          onError={() => setErr(true)}
        />
      )}
      {showVideo && (
        videoSrc ? (
          <video
            src={videoSrc}
            poster={src}
            autoPlay muted loop playsInline
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
            onError={() => setErr(true)}
          />
        ) : (
          <img
            src={src}
            alt={label || ''}
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
            loading="lazy"
            decoding="async"
            onError={() => setErr(true)}
          />
        )
      )}
      {children}
    </div>
  );
}

/* ---------- Star rating ---------- */
function Stars({ value = 5, size = 13 }) {
  return (
    <span style={{ display: 'inline-flex', gap: 2, color: 'var(--gold)' }} aria-label={`${value} stars`}>
      {[0,1,2,3,4].map(i => <I.star key={i} width={size} height={size} style={{ opacity: i < Math.round(value) ? 1 : .25 }} />)}
    </span>
  );
}

/* ---------- Scroll reveal ---------- */
function Reveal({ children, as = 'div', delay = 0, className = '', ...rest }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el || shown) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setShown(true); io.disconnect(); }
    }, { threshold: 0.1 });
    io.observe(el);
    // Safety: ensure visible even if observer never fires
    const t = setTimeout(() => setShown(true), 1200);
    return () => { io.disconnect(); clearTimeout(t); };
  }, []);
  const Tag = as;
  return <Tag ref={ref} className={`reveal ${shown ? 'in' : ''} ${className}`} data-d={delay || undefined} {...rest}>{children}</Tag>;
}

Object.assign(window, { I, Ph, HeroPanel, Stars, Reveal, useState, useEffect, useRef, useContext, createContext, useReducer });
