const { useState, useEffect, useRef, useMemo } = React;

/* ---------- Logo ---------- */
function Logo({ inverted = false, size = 32 }) {
  const ink = inverted ? '#fff' : 'var(--navy)';
  return (
    <a href="#" onClick={(e) => e.preventDefault()} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, textDecoration: 'none', color: ink }}>
      <img src="/icons/logo.png" alt="FindMyPart logo" width={size} height={size} style={{ display: 'block' }} />
      <span style={{ fontWeight: 800, fontSize: size * 0.62, letterSpacing: -0.3, color: ink }}>
        FindMyPart<span style={{ color: 'var(--accent)' }}>.</span>
      </span>
    </a>
  );
}

/* ---------- Top Nav ---------- */
function TopNav({ onLogo, dense }) {
  const navStyle = {
    height: dense ? 56 : 64,
    background: 'var(--navy)',
    color: '#fff',
    display: 'flex',
    alignItems: 'center',
    padding: '0 28px',
    gap: 28,
    borderBottom: '1px solid rgba(255,255,255,.06)',
    position: 'sticky',
    top: 0,
    zIndex: 30,
  };
  const linkStyle = { color: 'rgba(255,255,255,.78)', textDecoration: 'none', fontSize: 14, fontWeight: 500 };
  return (
    <nav className="fmp-nav" style={navStyle}>
      <div onClick={onLogo} style={{ cursor: 'pointer' }}>
        <Logo inverted size={32} />
      </div>
      <div className="fmp-nav-links" style={{ display: 'flex', gap: 22, marginLeft: 14 }}>
        <a href="/" style={linkStyle}>Find parts</a>
        <a href="/how-it-works" style={linkStyle}>How it works</a>
      </div>
      <div style={{ marginLeft: 'auto', display: 'flex', gap: 14, alignItems: 'center' }}>
        <span className="fmp-nav-cur" style={{ ...linkStyle, display: 'inline-flex', alignItems: 'center', gap: 7 }}>
          <UnionJack />
          GBP · EN
        </span>
        <a href="#" style={linkStyle}>Sign in</a>
      </div>
    </nav>
  );
}

/* ---------- Union Jack ---------- */
function UnionJack({ w = 22, h = 14 }) {
  return (
    <svg width={w} height={h} viewBox="0 0 60 30" style={{ borderRadius: 2, display: 'block', flexShrink: 0 }} aria-label="UK">
      <rect width="60" height="30" fill="#012169" />
      <path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" strokeWidth="6" />
      <path d="M0,0 L60,30 M60,0 L0,30" stroke="#C8102E" strokeWidth="2" />
      <path d="M30,0 V30 M0,15 H60" stroke="#fff" strokeWidth="10" />
      <path d="M30,0 V30 M0,15 H60" stroke="#C8102E" strokeWidth="4" />
    </svg>
  );
}

/* ---------- UK Reg Plate input ---------- */
function RegPlateInput({ value, onChange, autoFocus, error }) {
  const wrap = {
    background: '#FFD329',
    border: '2px solid #1c1c1c',
    borderRadius: 6,
    display: 'flex',
    alignItems: 'stretch',
    height: 56,
    overflow: 'hidden',
    boxShadow: error ? '0 0 0 3px #fde0d8' : 'none',
    transition: 'box-shadow .15s',
  };
  const flag = {
    width: 32, background: '#012169', color: '#fff',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    fontFamily: "'JetBrains Mono', monospace",
    fontSize: 10, fontWeight: 700, letterSpacing: 0.5,
  };
  const input = {
    flex: 1, border: 0, outline: 0, background: 'transparent',
    fontFamily: "'JetBrains Mono', ui-monospace, monospace",
    fontWeight: 700, fontSize: 26, letterSpacing: 2,
    textTransform: 'uppercase', color: '#0b1220', padding: '0 14px', width: '100%',
  };
  const format = (s) => {
    const clean = s.toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 7);
    if (clean.length <= 4) return clean;
    return clean.slice(0, 4) + ' ' + clean.slice(4);
  };
  return (
    <div style={wrap}>
      <div style={flag}>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', lineHeight: 1 }}>
          <span style={{ fontSize: 12 }}>★</span>
          <span style={{ marginTop: 4 }}>UK</span>
        </div>
      </div>
      <input style={input} value={value} placeholder="AB12 CDE" autoFocus={autoFocus}
        onChange={(e) => onChange(format(e.target.value))} spellCheck={false} aria-label="UK vehicle registration" />
    </div>
  );
}

/* ---------- Part field with autocomplete ---------- */
function PartInput({ value, onChange, onSubmit, popularParts }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, []);
  const parts = popularParts || ['Alternator', 'Starter Motor', 'Wing Mirror', 'Headlight', 'Brake Discs', 'Catalytic Converter'];
  const matches = parts.filter((p) => !value || p.toLowerCase().includes(value.toLowerCase()));
  const wrap = {
    height: 56, border: '1.5px solid var(--border-strong)', borderRadius: 8,
    display: 'flex', alignItems: 'center', background: '#fff', position: 'relative', paddingLeft: 14,
  };
  const inputStyle = {
    flex: 1, border: 0, outline: 0, fontFamily: 'inherit',
    fontSize: 16, color: 'var(--ink)', padding: '0 12px', height: '100%', fontWeight: 500,
  };
  return (
    <div ref={ref} style={wrap}>
      <span style={{ color: 'var(--ink-3)', display: 'inline-flex' }}><Icon.Bolt /></span>
      <input style={inputStyle} value={value} placeholder="Alternator"
        onChange={(e) => onChange(e.target.value)} onFocus={() => setOpen(true)}
        onKeyDown={(e) => e.key === 'Enter' && onSubmit?.()} aria-label="Part name" />
      {open && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 6px)', left: 0, right: 0,
          background: '#fff', border: '1px solid var(--border)', borderRadius: 10,
          boxShadow: 'var(--shadow-pop)', padding: 6, zIndex: 40,
        }}>
          <div style={{ padding: '6px 10px 4px', fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: .8, fontWeight: 700 }}>
            Popular parts
          </div>
          {matches.slice(0, 6).map((m) =>
            <div key={m} onMouseDown={() => { onChange(m); setOpen(false); }}
              style={{ padding: '8px 10px', borderRadius: 6, cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8, fontSize: 14 }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'var(--surface)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
              <span style={{ color: 'var(--ink-3)' }}><Icon.Bolt /></span>
              {m}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

/* ---------- Search Card ---------- */
function SearchCard({ reg, setReg, part, setPart, onSearch, compact, loading }) {
  const card = {
    background: '#fff', border: '1px solid var(--border)', borderRadius: 14,
    padding: compact ? 12 : 18,
    boxShadow: compact ? 'var(--shadow-card)' : 'var(--shadow-pop)',
    display: 'grid', gridTemplateColumns: compact ? '220px 1fr auto' : '1fr 1.2fr auto',
    gap: 10, alignItems: 'stretch',
  };
  const btn = {
    background: 'var(--accent)', color: '#fff', border: 0, borderRadius: 8,
    height: 56, padding: '0 22px', fontWeight: 700, fontSize: 15, cursor: 'pointer',
    display: 'inline-flex', alignItems: 'center', gap: 8,
    boxShadow: '0 1px 0 rgba(0,0,0,.04), inset 0 -1px 0 rgba(0,0,0,.18)',
    opacity: loading ? 0.7 : 1, minWidth: 160, justifyContent: 'center',
  };
  return (
    <div className="fmp-search-card" style={card}>
      <div>
        {!compact && <Label icon={<Icon.Car />}>Vehicle registration</Label>}
        <RegPlateInput value={reg} onChange={setReg} autoFocus={!compact} />
      </div>
      <div>
        {!compact && <Label icon={<Icon.Bolt />}>Part you need</Label>}
        <PartInput value={part} onChange={setPart} onSubmit={onSearch} />
      </div>
      <div className="fmp-search-go-wrap" style={{ display: 'flex', alignItems: 'flex-end' }}>
        <button className="fmp-search-go" style={btn} onClick={onSearch} disabled={loading}>
          {loading ? <Spinner /> : <Icon.Search />}
          {loading ? 'Searching…' : 'Search Parts'}
        </button>
      </div>
    </div>
  );
}

function Label({ icon, children }) {
  return (
    <div style={{
      fontSize: 12, fontWeight: 700, color: 'var(--ink-2)',
      textTransform: 'uppercase', letterSpacing: 0.6,
      display: 'flex', alignItems: 'center', gap: 6, marginBottom: 8,
    }}>
      <span style={{ color: 'var(--ink-3)' }}>{icon}</span>{children}
    </div>
  );
}

function Spinner() {
  return (
    <span style={{
      width: 14, height: 14, border: '2px solid rgba(255,255,255,.4)',
      borderTopColor: '#fff', borderRadius: '50%', display: 'inline-block',
      animation: 'fmp-spin .8s linear infinite',
    }} />
  );
}

/* ---------- Vehicle Match Banner ---------- */
function VehicleMatchBanner({ v, onChange }) {
  const [imgError, setImgError] = useState(false);
  const hasImage = v.ImageUrl && !imgError;

  return (
    <div className="fmp-vehicle-banner" style={{
      background: 'var(--green-soft)', border: '1px solid #c7e9d2', borderRadius: 12,
      padding: '14px 18px', display: 'flex', alignItems: 'center', gap: 16,
    }}>
      {hasImage ? (
        <div style={{
          width: 110, height: 70, flexShrink: 0,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <img
            src={v.ImageUrl}
            alt={`${v.Make} ${v.Model}`}
            onError={() => setImgError(true)}
            style={{
              maxWidth: '100%', maxHeight: '100%',
              objectFit: 'contain', display: 'block',
              mixBlendMode: 'multiply',
            }}
          />
        </div>
      ) : (
        <span style={{
          width: 32, height: 32, borderRadius: '50%', background: 'var(--green)', color: '#fff',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
        }}>
          <Icon.Check />
        </span>
      )}
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 12, color: 'var(--green-ink)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: .6 }}>
          ✅ Match found · DVLA verified
        </div>
        <div style={{ fontWeight: 700, fontSize: 17, color: 'var(--ink)', marginTop: 2, lineHeight: 1.25 }}>
          {v.Colour} {v.Make} {v.Model} {v.Trim} ({v.YearOfManufacture})
        </div>
        <div style={{ display: 'flex', gap: 14, marginTop: 6, color: 'var(--ink-2)', fontSize: 13, flexWrap: 'wrap' }}>
          <span><strong>{v.EngineCapacity}cc</strong> {v.FuelType.toLowerCase()}</span>
          <span style={{ color: 'var(--border-strong)' }}>·</span>
          <span>{v.Transmission.toLowerCase()}</span>
        </div>
      </div>
      <div className="fmp-vehicle-right" style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4 }}>
        <span className="mono" style={{
          background: '#FFD329', border: '1.5px solid #1c1c1c', padding: '3px 10px',
          borderRadius: 4, fontWeight: 700, letterSpacing: 1.5, fontSize: 14, color: '#111',
        }}>
          {v.Vrm}
        </span>
        <button onClick={onChange} style={{
          background: 'transparent', border: 0, color: 'var(--green-ink)',
          fontWeight: 700, fontSize: 12, cursor: 'pointer', padding: 2,
        }}>
          Not my car? Change →
        </button>
      </div>
    </div>
  );
}

/* ---------- Smart Value Insight Card ---------- */
function SmartValueCard({ cheapestUsed, cheapestNew, partName }) {
  const savings = cheapestNew - cheapestUsed;
  const pct = cheapestNew > 0 ? Math.round(Math.abs(savings) / cheapestNew * 100) : 0;
  const usedWins = savings > 0;
  const wrap = {
    background: usedWins
      ? 'linear-gradient(180deg, #fff7f0 0%, #fff 100%)'
      : 'linear-gradient(180deg, #f0f7ff 0%, #fff 100%)',
    border: usedWins ? '1px solid #fcd7be' : '1px solid #cfe0fb',
    borderRadius: 14, padding: 22,
    display: 'grid', gridTemplateColumns: '1fr 320px', gap: 28,
    position: 'relative', overflow: 'hidden',
  };
  const badge = {
    position: 'absolute', top: 14, right: 14,
    background: 'var(--accent)', color: '#fff',
    fontSize: 11, fontWeight: 700, textTransform: 'uppercase',
    padding: '4px 8px', borderRadius: 4, letterSpacing: .6,
  };
  return (
    <div className="fmp-smart" style={wrap}>
      <div style={badge}>💡 Smart Value Insight</div>
      <div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
          <div style={{
            width: 36, height: 36, borderRadius: 8, background: 'var(--accent)',
            color: '#fff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 18,
          }}>💡</div>
          <div style={{ fontSize: 13, color: 'var(--accent-ink)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: .6 }}>
            FindMyPart Value Insight
          </div>
        </div>
        <h2 className="fmp-smart-h2" style={{
          margin: '6px 0 8px', fontSize: 28, fontWeight: 800, color: 'var(--ink)',
          lineHeight: 1.2, letterSpacing: -0.3,
        }}>
          {usedWins ? (
            <>You save <span style={{ color: 'var(--accent)' }}>£{savings.toFixed(2)}</span> ({pct}%) by buying a used OEM {partName.toLowerCase()} today.</>
          ) : (
            <>New aftermarket {partName.toLowerCase()}s are <span style={{ color: 'var(--blue)' }}>£{Math.abs(savings).toFixed(2)}</span> cheaper than used OEM for this vehicle.</>
          )}
        </h2>
        <p style={{ margin: 0, color: 'var(--ink-2)', fontSize: 14, lineHeight: 1.55 }}>
          {usedWins
            ? 'We compared live listings across the UK for your exact vehicle. The cheapest used OEM unit is genuine — same part as new — for less than the aftermarket price.'
            : 'For this part, new aftermarket options are the better deal. Used OEM parts carry a premium — consider buying new.'}
        </p>
        <div style={{ display: 'flex', gap: 10, marginTop: 16 }}>
          <button style={{
            background: 'var(--ink)', color: '#fff', border: 0, borderRadius: 8,
            padding: '10px 14px', fontWeight: 700, fontSize: 13, cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', gap: 6,
          }}>
            {usedWins ? 'View cheapest used' : 'View cheapest new'} <Icon.Chev style={{ transform: 'rotate(-90deg)' }} />
          </button>
          <button style={{
            background: 'transparent', color: 'var(--ink-2)', border: '1px solid var(--border-strong)',
            borderRadius: 8, padding: '10px 14px', fontWeight: 600, fontSize: 13, cursor: 'pointer',
          }}>
            How we calculate this
          </button>
        </div>
      </div>
      <div className="fmp-smart-side" style={{ borderLeft: '1px dashed ' + (usedWins ? '#fcd7be' : '#cfe0fb'), paddingLeft: 24, display: 'flex', flexDirection: 'column', gap: 14 }}>
        <PriceRow label="Cheapest USED OEM" sub="Used genuine part" value={cheapestUsed} highlight={usedWins} strike={!usedWins} />
        <PriceRow label="Cheapest NEW aftermarket" sub="New aftermarket" value={cheapestNew} highlight={!usedWins} strike={usedWins} />
        <div style={{
          marginTop: 4, padding: '10px 12px',
          background: usedWins ? 'var(--green-soft)' : 'var(--blue-soft)',
          border: usedWins ? '1px solid #c7e9d2' : '1px solid #cfe0fb',
          borderRadius: 8,
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        }}>
          <span style={{ fontSize: 12, fontWeight: 700, color: usedWins ? 'var(--green-ink)' : '#1448a8', textTransform: 'uppercase', letterSpacing: .6 }}>
            {usedWins ? 'Your saving' : 'Price difference'}
          </span>
          <span style={{ fontSize: 18, fontWeight: 800, color: usedWins ? 'var(--green-ink)' : '#1448a8' }}>
            £{Math.abs(savings).toFixed(2)} <span style={{ fontSize: 12, fontWeight: 700 }}>({pct}%)</span>
          </span>
        </div>
      </div>
    </div>
  );
}

function PriceRow({ label, sub, value, highlight, strike }) {
  return (
    <div>
      <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: .6 }}>{label}</div>
      <div style={{
        fontSize: 26, fontWeight: 800,
        color: highlight ? 'var(--accent)' : 'var(--ink)',
        textDecoration: strike ? 'line-through' : 'none',
        opacity: strike ? 0.55 : 1, lineHeight: 1.1, marginTop: 2, fontFeatureSettings: '"tnum"',
      }}>
        £{value.toFixed(2)}
      </div>
      <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>{sub}</div>
    </div>
  );
}

/* ---------- Tabs ---------- */
function TabBar({ tab, setTab, counts }) {
  const tabs = [
    { id: 'all', label: 'All listings', count: counts.all },
    { id: 'used', label: 'Used OEM', sub: 'Recommended', count: counts.used },
    { id: 'new', label: 'New aftermarket', count: counts.new },
  ];
  return (
    <div className="fmp-tabbar" style={{
      display: 'flex', gap: 4, padding: 4, background: 'var(--surface)',
      border: '1px solid var(--border)', borderRadius: 10, width: 'fit-content',
    }}>
      {tabs.map((t) => {
        const active = tab === t.id;
        return (
          <button key={t.id} onClick={() => setTab(t.id)} style={{
            background: active ? '#fff' : 'transparent',
            border: 0, borderRadius: 8, padding: '8px 14px',
            fontWeight: 700, fontSize: 13, color: active ? 'var(--ink)' : 'var(--ink-3)',
            cursor: 'pointer',
            boxShadow: active ? '0 1px 2px rgba(15,23,42,.08)' : 'none',
            display: 'inline-flex', alignItems: 'center', gap: 8,
          }}>
            {t.label}
            {t.sub && <span style={{
              background: 'var(--green-soft)', color: 'var(--green-ink)',
              fontSize: 10, fontWeight: 700, padding: '2px 6px', borderRadius: 4,
              textTransform: 'uppercase', letterSpacing: .4,
            }}>{t.sub}</span>}
            <span style={{
              background: active ? 'var(--surface-2)' : 'transparent',
              color: active ? 'var(--ink-2)' : 'var(--ink-3)',
              padding: '1px 7px', borderRadius: 10, fontSize: 12, minWidth: 22, textAlign: 'center',
            }}>{t.count}</span>
          </button>
        );
      })}
    </div>
  );
}

/* ---------- Result card ---------- */
function ResultCard({ part, isBestValue, onCompare, compared, onSelect, selected, onViewDetail, onReport }) {
  const [hovered, setHovered] = useState(false);
  const card = {
    background: '#fff',
    border: selected ? '2px solid var(--accent)' : isBestValue ? '2px solid var(--green)' : '1px solid var(--border)',
    borderRadius: 12, padding: 16,
    display: 'grid', gridTemplateColumns: '140px 1fr 220px', gap: 18,
    boxShadow: hovered ? 'var(--shadow-pop)' : 'var(--shadow-card)',
    transition: 'box-shadow .15s, transform .15s',
    transform: hovered ? 'translateY(-1px)' : 'translateY(0)',
    position: 'relative',
  };
  return (
    <div className="fmp-result-card" style={card} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} onClick={onSelect}>
      {isBestValue && <div style={{
        position: 'absolute', top: -10, left: 16,
        background: 'var(--green)', color: '#fff', padding: '3px 9px',
        borderRadius: 4, fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: .6,
      }}>★ Best value</div>}
      <PartThumb oem={part.oem} condition={part.condition} photos={part.photos} imageUrls={part.imageUrls} />
      <div style={{ minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4, flexWrap: 'wrap' }}>
          <ConditionBadge condition={part.condition} oem={part.oem} grade={part.grade} />
          <FitBadge confidence={part.fitConfidence} tier={part.fitTier} reason={part.fitReason} />
        </div>
        <div style={{ fontWeight: 700, fontSize: 15, color: 'var(--ink)', lineHeight: 1.3, marginBottom: 6, textWrap: 'pretty' }}>
          {part.title}
        </div>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', fontSize: 12.5, color: 'var(--ink-2)', marginBottom: 8 }}>
          <MetaItem icon={<Icon.Shield />}>{part.warranty} warranty</MetaItem>
          <MetaItem icon={<Icon.Truck />}>
            {part.postage === 0 ? <span style={{ color: 'var(--green-ink)', fontWeight: 700 }}>Free postage</span> : `£${part.postage.toFixed(2)} postage`}
            {' · '}{part.eta}
          </MetaItem>
          {part.mileage && part.mileage !== '—' && <MetaItem>{part.mileage} on donor</MetaItem>}
        </div>
        <div className="fmp-result-meta" style={{ display: 'flex', gap: 12, alignItems: 'center', fontSize: 12, color: 'var(--ink-3)' }}>
          <span><strong style={{ color: 'var(--ink-2)' }}>{part.seller}</strong></span>
          <span>·</span>
          <span>★ {part.feedback}% ({part.sales.toLocaleString()})</span>
          <span>·</span>
          <span>{part.location}</span>
          <span>·</span>
          <span className="mono" style={{ fontSize: 11 }}>SKU {part.sku}</span>
        </div>
      </div>
      <div className="fmp-result-actions" style={{
        borderLeft: '1px dashed var(--border)', paddingLeft: 18,
        display: 'flex', flexDirection: 'column', justifyContent: 'space-between', gap: 10,
        position: 'relative',
      }}>
        {onReport && (
          <ReportFlagButton
            title="Report incorrect listing"
            onClick={(e) => { e.stopPropagation(); onReport(part); }}
            style={{ position: 'absolute', top: 0, right: 0 }}
          />
        )}
        <div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: .6 }}>
            Total {part.postage === 0 ? '' : 'inc. postage'}
          </div>
          <div style={{
            fontSize: 28, fontWeight: 800, color: 'var(--ink)', lineHeight: 1,
            marginTop: 2, fontFeatureSettings: '"tnum"',
          }}>
            £{(part.price + part.postage).toFixed(2)}
          </div>
          <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4 }}>
            {part.postage > 0 && <>£{part.price.toFixed(2)} + £{part.postage.toFixed(2)} postage</>}
            {part.postage === 0 && 'Free UK postage included'}
          </div>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          <button
            onClick={(e) => { e.stopPropagation(); onViewDetail?.(); }}
            style={{
              background: 'var(--accent)', color: '#fff', border: 0,
              padding: '10px 12px', borderRadius: 8, fontWeight: 700, fontSize: 13,
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
              boxShadow: '0 1px 0 rgba(0,0,0,.04), inset 0 -1px 0 rgba(0,0,0,.18)',
              cursor: 'pointer',
            }}>
            View listing <Icon.Chev style={{ transform: 'rotate(-90deg)' }} />
          </button>
          <button onClick={(e) => { e.stopPropagation(); onCompare(); }}
            style={{
              background: compared ? 'var(--ink)' : 'transparent',
              color: compared ? '#fff' : 'var(--ink-2)',
              border: compared ? '1px solid var(--ink)' : '1px solid var(--border-strong)',
              borderRadius: 8, padding: '7px 10px', fontWeight: 600, fontSize: 12, cursor: 'pointer',
            }}>
            {compared ? '✓ In comparison' : '+ Compare'}
          </button>
        </div>
      </div>
    </div>
  );
}

function PartThumb({ condition, photos, imageUrls }) {
  const [idx, setIdx] = useState(0);
  const isUsed = condition === 'Used';
  const hasImages = imageUrls && imageUrls.length > 0;
  const total = hasImages ? imageUrls.length : 0;

  const go = (dir, e) => {
    e.stopPropagation();
    setIdx((i) => (i + dir + total) % total);
  };

  const arrowStyle = (side) => ({
    position: 'absolute', top: '50%', transform: 'translateY(-50%)',
    [side]: 4,
    width: 24, height: 24, borderRadius: '50%',
    background: 'rgba(11,18,32,.65)', color: '#fff',
    border: 0, cursor: 'pointer',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    fontSize: 12, fontWeight: 700, lineHeight: 1,
    opacity: 0, transition: 'opacity .15s',
    padding: 0,
  });

  const wrapRef = useRef(null);
  useEffect(() => {
    const el = wrapRef.current;
    if (!el) return;
    const show = () => el.querySelectorAll('.pt-arrow').forEach(a => a.style.opacity = '1');
    const hide = () => el.querySelectorAll('.pt-arrow').forEach(a => a.style.opacity = '0');
    el.addEventListener('mouseenter', show);
    el.addEventListener('mouseleave', hide);
    return () => { el.removeEventListener('mouseenter', show); el.removeEventListener('mouseleave', hide); };
  }, []);

  return (
    <div ref={wrapRef} className="fmp-thumb" style={{
      width: 140, height: 140, borderRadius: 10,
      background: isUsed
        ? 'repeating-linear-gradient(135deg, #eef2f6 0 8px, #f6f7f9 8px 16px)'
        : 'repeating-linear-gradient(135deg, #ffe9d8 0 8px, #fff4ea 8px 16px)',
      border: '1px solid var(--border)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      position: 'relative', flexShrink: 0, overflow: 'hidden',
    }}>
      {hasImages ? (
        <img
          src={imageUrls[idx]}
          alt="Listing photo"
          style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
        />
      ) : (
        <div className="mono" style={{
          fontSize: 10, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 1,
          background: 'rgba(255,255,255,.7)', padding: '2px 6px', borderRadius: 3,
        }}>
          {isUsed ? 'donor photo' : 'product shot'}
        </div>
      )}

      {total > 1 && (
        <>
          <button className="pt-arrow" style={arrowStyle('left')} onClick={(e) => go(-1, e)}>‹</button>
          <button className="pt-arrow" style={arrowStyle('right')} onClick={(e) => go(1, e)}>›</button>
        </>
      )}

      <div style={{
        position: 'absolute', bottom: 6, right: 6,
        background: 'rgba(11,18,32,.78)', color: '#fff',
        fontSize: 10, fontWeight: 600, padding: '2px 6px', borderRadius: 3,
      }}>
        {hasImages ? `${idx + 1}/${total}` : `+${photos}`}
      </div>
    </div>
  );
}

function ConditionBadge({ condition, oem, grade }) {
  const isUsed = condition === 'Used';
  const style = {
    display: 'inline-flex', alignItems: 'center', gap: 5,
    fontSize: 11, fontWeight: 700, padding: '3px 7px', borderRadius: 4,
    textTransform: 'uppercase', letterSpacing: .4,
    background: isUsed ? 'var(--green-soft)' : 'var(--accent-soft)',
    color: isUsed ? 'var(--green-ink)' : 'var(--accent-ink)',
    border: isUsed ? '1px solid #c7e9d2' : '1px solid #fcd7be',
  };
  return (
    <span style={style}>
      <span>{isUsed ? '♻️' : '✨'}</span>
      {isUsed ? 'USED' : 'NEW'} · {oem ? 'OEM' : 'AFTERMARKET'}{grade ? ` · ${grade}` : ''}
    </span>
  );
}

const FIT_TIER_STYLE = {
  confirmed: { bg: 'var(--green-soft)', ink: 'var(--green-ink)', bd: '#c7e9d2', label: 'Confirmed fit' },
  likely:    { bg: 'var(--blue-soft)',  ink: '#1448a8',          bd: '#cfe0fb', label: 'Likely fit' },
  possible:  { bg: 'var(--amber-soft)', ink: 'var(--amber)',     bd: '#f6df9b', label: 'Possible fit' },
  unknown:   { bg: '#f1f3f5',           ink: '#5a6470',          bd: '#e1e5ea', label: 'Fit unknown' },
  mismatch:  { bg: '#fdecec',           ink: '#b3261e',          bd: '#f4c7c3', label: 'Check compatibility' },
};

function FitBadge({ confidence, tier, reason }) {
  const [hover, setHover] = useState(false);
  const t = tier && FIT_TIER_STYLE[tier] ? tier : (confidence >= 95 ? 'confirmed' : confidence >= 85 ? 'likely' : confidence >= 70 ? 'possible' : 'unknown');
  const s = FIT_TIER_STYLE[t];
  return (
    <span
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        position: 'relative',
        display: 'inline-flex', alignItems: 'center', gap: 5,
        fontSize: 11, fontWeight: 700, padding: '3px 7px', borderRadius: 4,
        background: s.bg, color: s.ink, border: `1px solid ${s.bd}`,
        letterSpacing: .3, textTransform: 'uppercase',
        cursor: 'help',
      }}>
      ◎ Fit {confidence}%
      {hover && (
        <span
          onClick={(e) => e.stopPropagation()}
          style={{
            position: 'absolute', bottom: 'calc(100% + 8px)', left: '50%', transform: 'translateX(-50%)',
            background: '#1b232b', color: '#fff',
            padding: '8px 10px', borderRadius: 6,
            fontSize: 12, fontWeight: 500, textTransform: 'none', letterSpacing: 0,
            lineHeight: 1.4, width: 240, textAlign: 'left',
            boxShadow: '0 6px 18px rgba(0,0,0,.18)',
            zIndex: 50, pointerEvents: 'none',
          }}>
          <div style={{ fontWeight: 700, marginBottom: 3, color: '#fff' }}>{s.label}</div>
          <div style={{ color: '#cdd5dd' }}>{reason || 'No fitment detail available.'}</div>
          <span style={{
            position: 'absolute', top: '100%', left: '50%', transform: 'translateX(-50%)',
            width: 0, height: 0, borderLeft: '6px solid transparent', borderRight: '6px solid transparent',
            borderTop: '6px solid #1b232b',
          }} />
        </span>
      )}
    </span>
  );
}

function FitReason({ tier, reason }) {
  if (!reason) return null;
  const s = FIT_TIER_STYLE[tier] || FIT_TIER_STYLE.unknown;
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 6,
      fontSize: 12, color: s.ink,
      background: s.bg, border: `1px solid ${s.bd}`,
      padding: '5px 8px', borderRadius: 6,
      lineHeight: 1.35,
    }}>
      <span style={{ fontWeight: 700, flexShrink: 0 }}>{s.label}:</span>
      <span style={{ color: 'var(--ink-2)' }}>{reason}</span>
    </div>
  );
}

function MetaItem({ icon, children }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
      {icon && <span style={{ color: 'var(--ink-3)' }}>{icon}</span>}
      <span>{children}</span>
    </span>
  );
}

/* ---------- Side filters ---------- */
function SideFilters({ filters, setFilters }) {
  const wrap = {
    background: '#fff', border: '1px solid var(--border)', borderRadius: 12,
    padding: 16, display: 'flex', flexDirection: 'column', gap: 18,
    position: 'sticky', top: 140,
  };
  return (
    <aside className="fmp-filters" style={wrap}>
      <FilterGroup title="Condition">
        {[['used', 'Used OEM'], ['new-oem', 'New genuine OEM'], ['new-after', 'New aftermarket']].map(([k, label]) =>
          <CheckRow key={k} checked={filters.condition[k]}
            onChange={() => setFilters((f) => ({ ...f, condition: { ...f.condition, [k]: !f.condition[k] } }))}
            label={label} />
        )}
      </FilterGroup>
      <FilterGroup title="Price">
        <div style={{ display: 'flex', gap: 8 }}>
          <PriceField label="Min" value={filters.priceMin} onChange={(v) => setFilters((f) => ({ ...f, priceMin: v }))} />
          <PriceField label="Max" value={filters.priceMax} onChange={(v) => setFilters((f) => ({ ...f, priceMax: v }))} />
        </div>
      </FilterGroup>
      <FilterGroup title="Fitment confidence">
        {[['exact', 'Confirmed fit only'], ['likely', 'Confirmed + likely'], ['any', 'All plausible fits']].map(([k, label]) =>
          <RadioRow key={k} checked={filters.fit === k}
            onChange={() => setFilters((f) => ({ ...f, fit: k }))} label={label} />
        )}
      </FilterGroup>
      <FilterGroup title="Postage">
        <CheckRow checked={filters.freePostage} onChange={() => setFilters((f) => ({ ...f, freePostage: !f.freePostage }))} label="Free UK postage" />
        <CheckRow checked={filters.fastEta} onChange={() => setFilters((f) => ({ ...f, fastEta: !f.fastEta }))} label="Delivered within 2 days" />
      </FilterGroup>
      <FilterGroup title="Seller">
        <CheckRow checked={filters.topSeller} onChange={() => setFilters((f) => ({ ...f, topSeller: !f.topSeller }))} label="Top-rated (99%+ feedback)" />
        <CheckRow checked={filters.ukOnly} onChange={() => setFilters((f) => ({ ...f, ukOnly: !f.ukOnly }))} label="UK sellers only" />
      </FilterGroup>
    </aside>
  );
}

function FilterGroup({ title, children }) {
  return (
    <div>
      <div style={{ fontSize: 12, fontWeight: 800, color: 'var(--ink)', textTransform: 'uppercase', letterSpacing: .6, marginBottom: 10 }}>{title}</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>{children}</div>
    </div>
  );
}

function CheckRow({ checked, onChange, label, count }) {
  return (
    <label style={{ display: 'flex', alignItems: 'center', gap: 9, cursor: 'pointer', fontSize: 13.5, color: 'var(--ink-2)' }}>
      <span onClick={onChange} style={{
        width: 16, height: 16, borderRadius: 4,
        border: checked ? '1.5px solid var(--accent)' : '1.5px solid var(--border-strong)',
        background: checked ? 'var(--accent)' : '#fff',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', color: '#fff',
      }}>
        {checked && <Icon.Check style={{ width: 10, height: 10 }} />}
      </span>
      <span onClick={onChange} style={{ flex: 1 }}>{label}</span>
      {count !== undefined && <span style={{ color: 'var(--ink-3)', fontSize: 12 }}>{count}</span>}
    </label>
  );
}

function RadioRow({ checked, onChange, label }) {
  return (
    <label style={{ display: 'flex', alignItems: 'center', gap: 9, cursor: 'pointer', fontSize: 13.5, color: 'var(--ink-2)' }}
      onClick={onChange}>
      <span style={{
        width: 16, height: 16, borderRadius: '50%',
        border: checked ? '5px solid var(--accent)' : '1.5px solid var(--border-strong)',
        background: '#fff', display: 'inline-block',
      }} />
      <span style={{ flex: 1 }}>{label}</span>
    </label>
  );
}

function PriceField({ label, value, onChange }) {
  return (
    <div style={{
      flex: 1, border: '1px solid var(--border-strong)', borderRadius: 6,
      padding: '4px 8px', display: 'flex', flexDirection: 'column',
    }}>
      <span style={{ fontSize: 10, color: 'var(--ink-3)', textTransform: 'uppercase', fontWeight: 700, letterSpacing: .6 }}>{label}</span>
      <div style={{ display: 'flex', alignItems: 'center', gap: 2 }}>
        <span style={{ color: 'var(--ink-3)' }}>£</span>
        <input value={value} onChange={(e) => onChange(e.target.value.replace(/[^0-9]/g, ''))}
          style={{ border: 0, outline: 0, width: '100%', fontFamily: 'inherit', fontSize: 14, color: 'var(--ink)' }} />
      </div>
    </div>
  );
}

/* ---------- Loading sequence ---------- */
function LoadingPanel({ reg, part, step }) {
  const steps = [
    { id: 0, label: `Searching DVLA database for ${reg}…` },
    { id: 1, label: `Vehicle matched. Building precise query…` },
    { id: 2, label: `Fetching live inventory across the UK…` },
    { id: 3, label: `Analysing value: Used OEM vs. New aftermarket…` },
  ];
  return (
    <div style={{
      background: '#fff', border: '1px solid var(--border)', borderRadius: 14,
      padding: 28, display: 'flex', flexDirection: 'column', gap: 14,
      boxShadow: 'var(--shadow-card)',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <Spinner />
        <span style={{ color: 'var(--ink)', fontWeight: 700 }}>Finding the right {part.toLowerCase() || 'part'} for {reg}</span>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {steps.map((s) => {
          const done = step > s.id;
          const active = step === s.id;
          return (
            <div key={s.id} style={{
              display: 'flex', alignItems: 'center', gap: 10,
              color: done || active ? 'var(--ink)' : 'var(--muted)', fontSize: 13,
            }}>
              <span style={{
                width: 18, height: 18, borderRadius: '50%',
                background: done ? 'var(--green)' : active ? 'var(--accent)' : 'var(--surface-2)',
                color: '#fff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 10, fontWeight: 700,
              }}>
                {done ? <Icon.Check style={{ width: 10, height: 10 }} /> : s.id + 1}
              </span>
              {s.label}
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ---------- Trust strip ---------- */
function TrustStrip() {
  const items = [
    { v: '11.4M', l: 'parts indexed live' },
    { v: '2,300+', l: 'UK breakers & sellers' },
    { v: 'DVLA', l: 'verified fitment' },
    { v: '47%', l: 'avg. saving on OEM' },
  ];
  return (
    <div className="fmp-trust" style={{
      display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 1,
      background: 'var(--border)', borderRadius: 12, overflow: 'hidden',
      border: '1px solid var(--border)',
    }}>
      {items.map((i) =>
        <div key={i.l} style={{ background: '#fff', padding: '14px 18px' }}>
          <div style={{ fontSize: 22, fontWeight: 800, color: 'var(--navy)', letterSpacing: -0.5 }}>{i.v}</div>
          <div style={{ fontSize: 12.5, color: 'var(--ink-3)' }}>{i.l}</div>
        </div>
      )}
    </div>
  );
}

/* ---------- How It Works ---------- */
function HowItWorks() {
  const steps = [
    { n: 1, t: 'Enter your reg & the part', d: 'We pull the exact make, model, trim and engine from DVLA in milliseconds.' },
    { n: 2, t: 'We search every UK breaker', d: 'Live inventory from eBay, Car-Part, breakerlink and more — filtered to your exact fitment.' },
    { n: 3, t: 'See the smartest buy', d: 'Used OEM vs. new aftermarket, side by side. We tell you what to buy and why.' },
  ];
  return (
    <div className="fmp-how" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14 }}>
      {steps.map((s) =>
        <div key={s.n} style={{ background: '#fff', border: '1px solid var(--border)', borderRadius: 12, padding: 18 }}>
          <div style={{
            width: 28, height: 28, borderRadius: '50%', background: 'var(--surface)',
            color: 'var(--ink)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            fontWeight: 700, fontSize: 13, marginBottom: 10,
          }}>{s.n}</div>
          <div style={{ fontWeight: 700, fontSize: 15, color: 'var(--ink)', marginBottom: 4 }}>{s.t}</div>
          <div style={{ fontSize: 13, color: 'var(--ink-3)', lineHeight: 1.5 }}>{s.d}</div>
        </div>
      )}
    </div>
  );
}

/* ---------- Footer ---------- */
function Footer() {
  const sections = [
    { t: 'Find parts', l: ['Browse by reg', 'Browse by make', 'Browse by part', 'Popular searches'] },
    { t: 'Sell on FindMyPart', l: ['List a part', 'For breakers', 'For garages', 'Bulk upload'] },
    { t: 'Company', l: ['About', 'Press', 'Careers', 'Contact'] },
    { t: 'Trust', l: [
      { label: 'Privacy & cookies', href: '/privacy' },
      'DVLA data',
      'Buyer protection',
      'Help centre',
    ] },
  ];
  return (
    <footer style={{
      background: 'var(--navy)', color: 'rgba(255,255,255,.7)',
      padding: '36px 28px 24px', marginTop: 40,
    }}>
      <div style={{ maxWidth: 1240, margin: '0 auto' }}>
        <div className="fmp-footer-grid" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr 1fr', gap: 28 }}>
          <div>
            <Logo inverted />
            <p style={{ fontSize: 13, lineHeight: 1.5, marginTop: 10 }}>
              The UK's smartest way to find the right car part, at the right price.
            </p>
          </div>
          {sections.map((s) =>
            <div key={s.t}>
              <div style={{ color: '#fff', fontWeight: 700, fontSize: 13, marginBottom: 10 }}>{s.t}</div>
              <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 7 }}>
                {s.l.map((li) => {
                  const label = typeof li === 'string' ? li : li.label;
                  const href = typeof li === 'string' ? '#' : li.href;
                  return <li key={label} style={{ fontSize: 13 }}><a href={href} style={{ color: 'inherit', textDecoration: 'none' }}>{label}</a></li>;
                })}
              </ul>
            </div>
          )}
        </div>
        <div className="fmp-footer-bottom" style={{ borderTop: '1px solid rgba(255,255,255,.08)', marginTop: 24, paddingTop: 16, display: 'flex', justifyContent: 'space-between', fontSize: 12 }}>
          <span>© 2026 FindMyPart · Made in the UK</span>
          <span>Vehicle data via the DVLA. eBay® is a trademark of eBay Inc.</span>
        </div>
      </div>
    </footer>
  );
}

/* ---------- Comparison drawer ---------- */
function CompareDrawer({ items, onClose, onRemove }) {
  if (items.length === 0) return null;
  return (
    <div className="fmp-compare" style={{
      position: 'fixed', bottom: 16, left: '50%', transform: 'translateX(-50%)',
      width: 'min(960px, calc(100% - 32px))', zIndex: 50,
      background: '#fff', border: '1px solid var(--border)', borderRadius: 14,
      boxShadow: 'var(--shadow-pop)', padding: 14,
      display: 'flex', alignItems: 'center', gap: 14,
    }}>
      <div style={{
        background: 'var(--ink)', color: '#fff', padding: '6px 10px', borderRadius: 6,
        fontSize: 12, fontWeight: 700,
      }}>
        Comparing {items.length}
      </div>
      <div style={{ display: 'flex', gap: 8, flex: 1, overflow: 'auto' }}>
        {items.map((p) =>
          <div key={p.id} style={{
            border: '1px solid var(--border)', borderRadius: 8, padding: '6px 10px',
            fontSize: 12, color: 'var(--ink-2)', display: 'inline-flex', alignItems: 'center', gap: 8,
            background: 'var(--surface)', whiteSpace: 'nowrap',
          }}>
            <strong style={{ color: 'var(--ink)' }}>£{p.price.toFixed(2)}</strong>
            <span style={{ maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis' }}>{p.title.slice(0, 38)}…</span>
            <button onClick={() => onRemove(p.id)} style={{
              background: 'transparent', border: 0, color: 'var(--ink-3)', cursor: 'pointer', display: 'inline-flex',
            }}><Icon.X /></button>
          </div>
        )}
      </div>
      <button onClick={onClose} style={{
        background: 'transparent', border: '1px solid var(--border-strong)', borderRadius: 8,
        padding: '8px 12px', fontWeight: 600, fontSize: 13, color: 'var(--ink-2)', cursor: 'pointer',
      }}>Clear</button>
      <button style={{
        background: 'var(--accent)', color: '#fff', border: 0, borderRadius: 8,
        padding: '10px 14px', fontWeight: 700, fontSize: 13, cursor: 'pointer',
      }}>Compare side-by-side →</button>
    </div>
  );
}

/* ---------- Sort dropdown ---------- */
function SortDropdown({ sort, setSort }) {
  const [open, setOpen] = useState(false);
  const opts = [
    ['best-value', 'Best value'],
    ['price-asc', 'Price: low → high'],
    ['price-desc', 'Price: high → low'],
    ['fit-desc', 'Fitment confidence'],
  ];
  const cur = opts.find(o => o[0] === sort)?.[1];
  return (
    <div style={{ position: 'relative' }}>
      <button onClick={() => setOpen(o => !o)} style={{
        background: '#fff', border: '1px solid var(--border-strong)', borderRadius: 8,
        padding: '8px 12px', fontSize: 13, fontWeight: 600, color: 'var(--ink-2)',
        cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 8,
      }}>
        <Icon.Sort /> Sort: <strong style={{ color: 'var(--ink)' }}>{cur}</strong> <Icon.Chev />
      </button>
      {open && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 6px)', right: 0,
          background: '#fff', border: '1px solid var(--border)', borderRadius: 10,
          boxShadow: 'var(--shadow-pop)', padding: 6, zIndex: 30, minWidth: 200,
        }}>
          {opts.map(([k, l]) => (
            <div key={k} onClick={() => { setSort(k); setOpen(false); }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'var(--surface)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
              style={{
                padding: '8px 10px', borderRadius: 6, cursor: 'pointer',
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                fontSize: 13, color: 'var(--ink-2)',
              }}>
              {l} {sort === k && <Icon.Check style={{ color: 'var(--accent)' }} />}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ============================================================
   LISTING DETAIL PAGE COMPONENTS
   ============================================================ */

/* ---------- Detail Photo Gallery (flexible mosaic) ----------
   Layout adapts to photo count — Booking.com-style mosaic for 7+ photos,
   hero+stack for 4-6, simple row for 1-3. Each listing renders differently. */
function DetailPhotoGallery({ imageUrls, captions }) {
  const [selected, setSelected] = useState(0);
  const hasImages = imageUrls && imageUrls.length > 0;
  const photos = hasImages ? imageUrls : [];
  const total = photos.length;

  // Each photo gets a slightly different placeholder tone so the set
  // reads as distinct images, not repeated tiles.
  const placeholderBg = (i) => {
    const tones = [
      ['#eef2f6', '#f6f7f9'], // cool gray
      ['#fff4ea', '#fff1e8'], // warm cream
      ['#f0f7ff', '#e8f0fe'], // soft blue
      ['#f6f7f9', '#eef2f6'], // neutral
      ['#fff6e0', '#fff1e8'], // amber tint
      ['#e6f6ee', '#e6f6ee'], // green tint
      ['#f5f0ff', '#f0e6ff'], // purple tint
      ['#fff0f5', '#ffe8f0'], // pink tint
    ];
    const [a, b] = tones[i % tones.length];
    return `repeating-linear-gradient(${135 + (i*17)%45}deg, ${a} 0 10px, ${b} 10px 20px)`;
  };

  // Single tile — used for hero, stack items and thumbnails
  const Tile = ({ i, rounded = 8, label, overlay }) => (
    <button
      onClick={() => setSelected(i)}
      title={captions?.[i] || `Photo ${i + 1}`}
      style={{
        position: 'relative',
        flex: '1 1 0',
        minWidth: 0,
        minHeight: 0,
        background: placeholderBg(i),
        border: selected === i ? '2px solid var(--accent)' : '1px solid var(--border)',
        borderRadius: rounded,
        cursor: 'pointer',
        padding: 0,
        overflow: 'hidden',
      }}
    >
      {photos[i] && (
        <img
          src={photos[i]}
          alt={`Photo ${i + 1}`}
          style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
        />
      )}
      {!photos[i] && (
        <div className="mono" style={{
          position: 'absolute', left: 8, bottom: 8,
          fontSize: 9, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 1,
          background: 'rgba(255,255,255,.85)', padding: '2px 7px', borderRadius: 3,
          maxWidth: 'calc(100% - 16px)',
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          {label ?? `photo ${i + 1}`}
        </div>
      )}
      {overlay && (
        <div style={{
          position: 'absolute', inset: 0,
          background: 'rgba(11,18,32,.62)',
          color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 20, fontWeight: 700, letterSpacing: 0.2,
          textDecoration: 'underline', textUnderlineOffset: 4,
        }}>
          {overlay}
        </div>
      )}
    </button>
  );

  // Pick layout deterministically by photo count
  const n = photos.length;
  const variant = n >= 8 ? 'booking' : n >= 6 ? 'hero3' : n >= 4 ? 'hero2' : 'row';

  let mosaic;
  const GAP = 6;

  if (variant === 'booking') {
    // 1 hero + 2 stacked right, then 5-thumb row
    mosaic = (
      <div style={{ display: 'flex', flexDirection: 'column', gap: GAP }}>
        <div style={{ display: 'flex', gap: GAP, height: 340 }}>
          <div style={{ flex: '1.7 1 0', display: 'flex' }}>
            <Tile i={0} />
          </div>
          <div style={{ flex: '1 1 0', display: 'flex', flexDirection: 'column', gap: GAP }}>
            <Tile i={1} />
            <Tile i={2} />
          </div>
        </div>
        <div style={{ display: 'flex', gap: GAP, height: 90 }}>
          <Tile i={3} />
          <Tile i={4} />
          <Tile i={5} />
          <Tile i={6} />
          <Tile i={7} overlay={total > 8 ? `+${total - 8} photos` : null} />
        </div>
      </div>
    );
  } else if (variant === 'hero3') {
    // 1 hero + 3 stacked right, then small row of the rest
    const remaining = photos.slice(4);
    mosaic = (
      <div style={{ display: 'flex', flexDirection: 'column', gap: GAP }}>
        <div style={{ display: 'flex', gap: GAP, height: 360 }}>
          <div style={{ flex: '2 1 0', display: 'flex' }}>
            <Tile i={0} />
          </div>
          <div style={{ flex: '1 1 0', display: 'flex', flexDirection: 'column', gap: GAP }}>
            <Tile i={1} />
            <Tile i={2} />
            <Tile i={3} />
          </div>
        </div>
        {remaining.length > 0 && (
          <div style={{ display: 'flex', gap: GAP, height: 90 }}>
            {remaining.map((_, k) => {
              const i = 4 + k;
              const isLast = k === remaining.length - 1;
              return <Tile key={i} i={i} overlay={isLast && total > photos.length ? `+${total - photos.length} photos` : null} />;
            })}
          </div>
        )}
      </div>
    );
  } else if (variant === 'hero2') {
    // Hero left + 2 stacked right, no bottom row needed
    mosaic = (
      <div style={{ display: 'flex', gap: GAP, height: 360 }}>
        <div style={{ flex: '1.6 1 0', display: 'flex' }}>
          <Tile i={0} />
        </div>
        <div style={{ flex: '1 1 0', display: 'flex', flexDirection: 'column', gap: GAP }}>
          {photos.slice(1, 3).map((_, k) => {
            const i = 1 + k;
            const isLast = k === photos.slice(1, 3).length - 1;
            return <Tile key={i} i={i} overlay={isLast && total > photos.length ? `+${total - photos.length} photos` : null} />;
          })}
        </div>
      </div>
    );
  } else {
    // 1–3 photos: simple flex row, first one larger
    mosaic = (
      <div style={{ display: 'flex', gap: GAP, height: 340 }}>
        <div style={{ flex: '2 1 0', display: 'flex' }}>
          <Tile i={0} />
        </div>
        {photos.length > 1 && (
          <div style={{ flex: '1 1 0', display: 'flex', flexDirection: 'column', gap: GAP }}>
            {photos.slice(1).map((_, k) => <Tile key={k+1} i={k+1} />)}
          </div>
        )}
      </div>
    );
  }

  return (
    <div>
      {mosaic}
      {/* Caption + counter strip under the mosaic */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10,
        marginTop: 10,
      }}>
        <span className="mono" style={{
          fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 1,
          background: 'var(--surface)', border: '1px solid var(--border)',
          padding: '4px 10px', borderRadius: 4,
          flex: 1, minWidth: 0,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          {captions?.[selected] || `Photo ${selected + 1} of ${total}`}
        </span>
        <span style={{
          fontSize: 12, fontWeight: 600, color: 'var(--ink-2)',
          background: '#fff', border: '1px solid var(--border)',
          padding: '4px 10px', borderRadius: 6, whiteSpace: 'nowrap',
        }}>
          {selected + 1} / {total}
        </span>
      </div>
    </div>
  );
}

/* ---------- Seller Review Carousel ---------- */
function SellerReviewCard({ part }) {
  const sd = part.sellerDetail || {};
  const fb = typeof sd.feedbackPercentage === 'number' ? sd.feedbackPercentage : (typeof part.feedback === 'number' ? part.feedback : 0);
  const score = sd.feedbackScore || part.sales || 0;

  const ratingOut10 = Math.min(10, Math.round((fb / 10) * 10) / 10);
  const ratingLabel = ratingOut10 >= 9.5 ? 'Exceptional' : ratingOut10 >= 9.0 ? 'Superb' : ratingOut10 >= 8.0 ? 'Very good' : ratingOut10 >= 7.0 ? 'Good' : 'Average';

  const categoryScores = [
    { label: 'Accuracy', score: Math.min(10, (ratingOut10 + 0.2).toFixed(1)) },
    { label: 'Delivery', score: Math.min(10, (ratingOut10 - 0.1).toFixed(1)) },
    { label: 'Communication', score: Math.min(10, (ratingOut10 + 0.1).toFixed(1)) },
  ];

  return (
    <div style={{
      background: '#fff', border: '1px solid var(--border)', borderRadius: 14,
      padding: 20, boxShadow: 'var(--shadow-card)', marginBottom: 14,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
        <div>
          <div style={{ fontSize: 16, fontWeight: 800, color: 'var(--ink)' }}>{ratingLabel}</div>
          <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>{score.toLocaleString()} reviews</div>
        </div>
        <div style={{
          background: 'var(--navy)', color: '#fff', fontWeight: 800, fontSize: 15,
          width: 40, height: 40, borderRadius: '8px 8px 8px 0',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>{ratingOut10.toFixed(1)}</div>
      </div>

      <div style={{ borderTop: '1px solid var(--border)', paddingTop: 14, display: 'flex', flexDirection: 'column', gap: 8 }}>
        {categoryScores.map(cat => (
          <div key={cat.label} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: 13 }}>
            <span style={{ color: 'var(--ink-2)' }}>{cat.label}</span>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={{ width: 80, height: 5, background: 'var(--surface)', borderRadius: 3, overflow: 'hidden' }}>
                <div style={{ height: '100%', width: `${(cat.score / 10) * 100}%`, background: 'var(--navy)', borderRadius: 3 }} />
              </div>
              <span style={{ fontWeight: 700, color: 'var(--ink)', fontSize: 12, minWidth: 24, textAlign: 'right' }}>{cat.score}</span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------- Report flag button ---------- */
function ReportFlagButton({ onClick, title, style }) {
  const [hovered, setHovered] = useState(false);
  return (
    <button
      type="button"
      onClick={onClick}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      title={title || 'Report listing'}
      aria-label={title || 'Report listing'}
      style={{
        background: 'transparent', border: 0, padding: 4, cursor: 'pointer',
        color: hovered ? '#c0271a' : '#d14b3d',
        opacity: hovered ? 1 : 0.55,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        borderRadius: 6, transition: 'opacity .15s, color .15s',
        ...(style || {}),
      }}>
      <Icon.Flag style={{ width: 14, height: 14 }} />
    </button>
  );
}

/* ---------- Report toast (floating notification) ---------- */
function ReportToast({ message, onDismiss }) {
  useEffect(() => {
    if (!message) return;
    const t = setTimeout(onDismiss, 3200);
    return () => clearTimeout(t);
  }, [message, onDismiss]);
  if (!message) return null;
  return (
    <div style={{
      position: 'fixed', bottom: 24, right: 24, zIndex: 1000,
      background: '#1f2937', color: '#fff',
      padding: '10px 14px', borderRadius: 10,
      boxShadow: '0 6px 24px rgba(0,0,0,.25)',
      fontSize: 13, fontWeight: 600,
      display: 'flex', alignItems: 'center', gap: 8,
      maxWidth: 320,
    }}>
      <Icon.Flag style={{ width: 14, height: 14, color: '#ff6b5b' }} />
      <span>{message}</span>
    </div>
  );
}

/* ---------- Detail Price Card ---------- */
function DetailPriceCard({ part, onReport }) {
  const total = part.price + part.postage;
  return (
    <div style={{
      background: '#fff', border: '1px solid var(--border)', borderRadius: 14,
      padding: 20, boxShadow: 'var(--shadow-pop)', position: 'relative',
    }}>
      {onReport && (
        <ReportFlagButton
          title="Report incorrect listing"
          onClick={() => onReport(part)}
          style={{ position: 'absolute', top: 12, right: 12 }}
        />
      )}
      <div style={{ marginBottom: 16 }}>
        <div style={{ fontSize: 12, color: 'var(--ink-3)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: .6, marginBottom: 4 }}>
          Total price
        </div>
        <div style={{ fontSize: 36, fontWeight: 800, color: 'var(--ink)', lineHeight: 1, fontFeatureSettings: '"tnum"' }}>
          £{total.toFixed(2)}
        </div>
        <div style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 6 }}>
          {part.postage > 0
            ? <>£{part.price.toFixed(2)} + £{part.postage.toFixed(2)} postage</>
            : 'Free UK postage included'}
        </div>
      </div>

      <div style={{
        background: 'var(--green-soft)', border: '1px solid #c7e9d2', borderRadius: 8,
        padding: '10px 12px', marginBottom: 14, display: 'flex', alignItems: 'center', gap: 8,
      }}>
        <span style={{ fontSize: 16 }}>✓</span>
        <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--green-ink)' }}>In stock</div>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 16 }}>
        <DetailInfoRow icon={<Icon.Truck />} label="Delivery">{part.eta}</DetailInfoRow>
        <DetailInfoRow icon={<Icon.Shield />} label="Warranty">{part.warranty}</DetailInfoRow>
      </div>

      <a href={part.itemWebUrl || '#'} target="_blank" rel="noopener noreferrer"
        onClick={() => window.fmpTrack && window.fmpTrack('listing_clicked', {
          source: 'detail_view',
          condition: part.condition,
          price: part.price,
          seller: part.seller && part.seller.name,
          item_id: part.id,
          fit_tier: part.fitTier,
          fit_confidence: part.fitConfidence,
        })}
        style={{
        background: 'var(--accent)', color: '#fff', textDecoration: 'none',
        padding: '14px 16px', borderRadius: 10, fontWeight: 700, fontSize: 15,
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        boxShadow: '0 1px 0 rgba(0,0,0,.04), inset 0 -1px 0 rgba(0,0,0,.18)',
        marginBottom: 8,
      }}>
        View on eBay <Icon.External />
      </a>

      <button style={{
        background: 'transparent', border: '1px solid var(--border-strong)', borderRadius: 10,
        padding: '12px 14px', fontWeight: 600, fontSize: 14, color: 'var(--ink-2)',
        cursor: 'pointer', width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
      }}>
        <Icon.Heart /> Save for later
      </button>
    </div>
  );
}

function DetailInfoRow({ icon, label, children }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
      <span style={{ color: 'var(--ink-3)' }}>{icon}</span>
      <span style={{ color: 'var(--ink-3)' }}>{label}:</span>
      <span style={{ fontWeight: 600, color: 'var(--ink-2)' }}>{children}</span>
    </div>
  );
}

/* ---------- Section wrapper ---------- */
function DetailSection({ title, children, noDivider }) {
  return (
    <section style={{ paddingTop: 24, paddingBottom: 24, borderBottom: noDivider ? 'none' : '1px solid var(--border)' }}>
      <h2 style={{ fontSize: 20, fontWeight: 800, color: 'var(--ink)', margin: '0 0 14px', letterSpacing: -0.3 }}>
        {title}
      </h2>
      {children}
    </section>
  );
}

/* ---------- Seller card ---------- */
function DetailSellerCard({ part }) {
  const [expanded, setExpanded] = useState(false);
  const sd = part.sellerDetail || {};
  const name = sd.username || part.seller || 'Seller';
  const fb = typeof sd.feedbackPercentage === 'number' ? sd.feedbackPercentage : (typeof part.feedback === 'number' ? part.feedback : 0);
  const score = sd.feedbackScore || part.sales || 0;
  const location = sd.location || part.location || 'UK';
  const isTopRated = fb >= 99;

  const sellerBio = (() => {
    const lines = [];
    if (fb >= 99) {
      lines.push(`Top-rated eBay seller with ${fb.toFixed(1)}% positive feedback across ${score.toLocaleString()} transactions.`);
    } else if (fb > 0) {
      lines.push(`eBay seller with ${fb.toFixed(1)}% positive feedback and ${score.toLocaleString()} sales.`);
    }
    if (location && location !== 'UK') {
      lines.push(`Based in ${location}.`);
    }
    if (part.warranty && part.warranty !== 'Check listing') {
      lines.push(`Offers ${part.warranty} warranty on this part.`);
    }
    if (part.returnTerms) {
      const rt = part.returnTerms;
      if (rt.returnsAccepted) {
        const period = rt.returnPeriod?.value && rt.returnPeriod?.unit
          ? `${rt.returnPeriod.value} ${rt.returnPeriod.unit.toLowerCase()}`
          : '';
        lines.push(period ? `Returns accepted within ${period}.` : 'Returns accepted.');
      }
    }
    if (part.postage === 0) {
      lines.push('Free UK postage included on this listing.');
    }
    return lines.join(' ');
  })();

  const charLimit = 150;
  const isLong = sellerBio.length > charLimit;
  const displayText = expanded || !isLong ? sellerBio : sellerBio.slice(0, charLimit) + '…';

  return (
    <div style={{
      background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 12,
      padding: 18, display: 'flex', gap: 16, alignItems: 'flex-start',
    }}>
      <div style={{
        width: 64, height: 64, borderRadius: '50%', background: 'var(--navy)', color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontSize: 24, fontWeight: 800, flexShrink: 0,
      }}>
        {name[0].toUpperCase()}
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
          <div style={{ fontWeight: 700, fontSize: 17, color: 'var(--ink)' }}>{name}</div>
          {isTopRated && (
            <span style={{
              background: 'var(--green-soft)', color: 'var(--green-ink)',
              fontSize: 10, fontWeight: 700, padding: '2px 6px', borderRadius: 4,
              textTransform: 'uppercase', letterSpacing: .4,
            }}>★ Top rated</span>
          )}
        </div>
        <div style={{ display: 'flex', gap: 14, fontSize: 13, color: 'var(--ink-3)', marginBottom: 10, flexWrap: 'wrap' }}>
          <span>★ {fb.toFixed(1)}% positive</span>
          <span>·</span>
          <span>{score.toLocaleString()} sales</span>
        </div>
        <div style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.55, marginBottom: isLong ? 4 : 12 }}>
          {displayText}
        </div>
        {isLong && (
          <button onClick={() => setExpanded(e => !e)} style={{
            background: 'transparent', border: 0, padding: 0, cursor: 'pointer',
            color: 'var(--accent-ink)', fontSize: 13, fontWeight: 700,
            display: 'inline-flex', alignItems: 'center', gap: 4, marginBottom: 12,
          }}>
            {expanded ? 'Show less' : 'Show more'}
            <Icon.Chev style={{ width: 12, height: 12, transform: expanded ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }} />
          </button>
        )}
        <div style={{ display: 'flex', gap: 12, fontSize: 13, alignItems: 'center', flexWrap: 'wrap' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ color: 'var(--ink-3)' }}>📍</span>
            <span style={{ color: 'var(--ink-2)' }}>{location}</span>
          </div>
        </div>
      </div>
      <a href={part.itemWebUrl || '#'} target="_blank" rel="noopener noreferrer"
        onClick={() => window.fmpTrack && window.fmpTrack('listing_clicked', {
          source: 'seller_card',
          condition: part.condition,
          price: part.price,
          seller: part.seller && part.seller.name,
          item_id: part.id,
          fit_tier: part.fitTier,
          fit_confidence: part.fitConfidence,
        })}
        style={{
        background: 'transparent', border: '1px solid var(--border-strong)', borderRadius: 8,
        padding: '8px 14px', fontWeight: 600, fontSize: 13, color: 'var(--ink-2)',
        cursor: 'pointer', textDecoration: 'none', whiteSpace: 'nowrap', flexShrink: 0,
      }}>
        Contact seller
      </a>
    </div>
  );
}

/* ---------- Specs table ---------- */
function DetailSpecsTable({ specs }) {
  return (
    <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 10, overflow: 'hidden' }}>
      {specs.map((s, i) => (
        <div key={i} className="fmp-spec-row" style={{
          display: 'grid', gridTemplateColumns: '180px 1fr', gap: 16,
          padding: '12px 16px', borderBottom: i < specs.length - 1 ? '1px solid var(--border)' : 'none', fontSize: 14,
        }}>
          <div style={{ color: 'var(--ink-3)', fontWeight: 600 }}>{s.label}</div>
          <div style={{ color: 'var(--ink)', fontWeight: 600 }}>{s.value}</div>
        </div>
      ))}
    </div>
  );
}

/* ---------- Fitment confirmation ---------- */
function FitmentSection({ vehicle, confidence, tier, reason, compatibleVehicles }) {
  const [showAll, setShowAll] = useState(false);
  const cvs = compatibleVehicles || [];

  const scored = cvs.map(cv => {
    let score = 0;
    const cvMake = (cv.Make || cv.Car_Make || '').toUpperCase();
    const cvModel = (cv.Model || cv.Car_Model || '').toUpperCase();
    const cvYear = (cv.Year || cv.Car_Year || '').toString();
    const cvVariant = (cv.Variant || cv.Type || cv.Trim || '').toUpperCase();

    if (cvMake && cvMake === vehicle.Make.toUpperCase()) score += 4;
    if (cvModel && vehicle.Model.toUpperCase().includes(cvModel)) score += 3;
    if (cvModel && cvModel.includes(vehicle.Model.toUpperCase())) score += 2;
    if (cvYear && cvYear === vehicle.YearOfManufacture) score += 2;
    if (cvVariant && vehicle.Trim && cvVariant.includes(vehicle.Trim.toUpperCase())) score += 1;

    const label = [cvMake, cvModel, cvVariant].filter(Boolean).join(' ');
    const yearLabel = cvYear || '';
    return { ...cv, score, label, yearLabel };
  });

  scored.sort((a, b) => b.score - a.score);

  const deduped = [];
  const seen = new Set();
  scored.forEach(v => {
    const key = v.label + '|' + v.yearLabel;
    if (!seen.has(key)) { seen.add(key); deduped.push(v); }
  });

  const defaultCount = 5;
  const hasMore = deduped.length > defaultCount;
  const visible = showAll ? deduped : deduped.slice(0, defaultCount);

  return (
    <div>
      {(() => {
        const t = tier && FIT_TIER_STYLE[tier] ? tier : 'unknown';
        const s = FIT_TIER_STYLE[t];
        const headerByTier = {
          confirmed: '✓ Confirmed fitment for your vehicle',
          likely: '◎ Likely fits your vehicle',
          possible: '◎ Possible fit — check with seller',
          unknown: 'ⓘ Fitment not confirmed by seller',
          mismatch: '⚠ This listing may not fit your vehicle',
        };
        const vehicleLine = vehicle
          ? `Your vehicle: ${[vehicle.Colour, vehicle.Make, vehicle.Model, vehicle.Trim].filter(Boolean).join(' ')}${vehicle.YearOfManufacture ? ` (${vehicle.YearOfManufacture})` : ''}${vehicle.FuelType ? ` — ${vehicle.EngineCapacity || ''} ${vehicle.FuelType.toLowerCase()}` : ''}${vehicle.Transmission ? `, ${vehicle.Transmission.toLowerCase()}` : ''}.`
          : '';
        return (
          <div style={{
            background: s.bg, border: `1px solid ${s.bd}`, borderRadius: 10,
            padding: 16, marginBottom: 14,
          }}>
            <div style={{ fontSize: 13, fontWeight: 700, color: s.ink, marginBottom: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
              <span>{headerByTier[t]}</span>
              {typeof confidence === 'number' && (
                <span style={{ fontSize: 12, fontWeight: 800, letterSpacing: .3 }}>{confidence}% fit confidence</span>
              )}
            </div>
            {reason && (
              <div style={{ fontSize: 14, color: 'var(--ink-2)', marginBottom: vehicleLine ? 6 : 0 }}>{reason}</div>
            )}
            {vehicleLine && (
              <div style={{ fontSize: 13, color: 'var(--ink-3)' }}>{vehicleLine}</div>
            )}
          </div>
        );
      })()}

      {deduped.length > 0 && (
        <div>
          <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 6 }}>
            {visible.map((v, i) => (
              <li key={i} style={{ fontSize: 14, color: 'var(--ink-2)', display: 'flex', alignItems: 'center', gap: 8 }}>
                <span style={{ color: 'var(--green-ink)', fontWeight: 700, flexShrink: 0 }}>✓</span>
                <span>
                  {v.label}{v.yearLabel ? ` (${v.yearLabel})` : ''}
                  {v.score >= 6 && (
                    <span style={{
                      marginLeft: 8, fontSize: 10, fontWeight: 700, padding: '2px 6px', borderRadius: 4,
                      background: 'var(--green-soft)', color: 'var(--green-ink)', border: '1px solid #c7e9d2',
                      textTransform: 'uppercase', letterSpacing: .4,
                    }}>Your vehicle</span>
                  )}
                </span>
              </li>
            ))}
          </ul>
          {hasMore && (
            <button onClick={() => setShowAll(s => !s)} style={{
              background: 'transparent', border: 0, padding: 0, cursor: 'pointer',
              color: 'var(--accent-ink)', fontSize: 13, fontWeight: 700, marginTop: 10,
              display: 'inline-flex', alignItems: 'center', gap: 4,
            }}>
              {showAll ? 'Show fewer' : `Show all ${deduped.length} compatible vehicles`}
              <Icon.Chev style={{ width: 12, height: 12, transform: showAll ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }} />
            </button>
          )}
        </div>
      )}

      {deduped.length === 0 && (
        <div style={{ fontSize: 13, color: 'var(--ink-3)', fontStyle: 'italic' }}>
          Seller didn't provide a structured compatibility list.
        </div>
      )}
    </div>
  );
}

/* ---------- Listing Detail View ---------- */
function ListingDetailView({ part, vehicle, partName, onBack, onReport }) {
  const specs = [
    { label: 'Condition', value: part.condition + (part.oem ? ' — OEM' : ' — Aftermarket') },
    { label: 'SKU', value: part.sku },
    { label: 'Warranty', value: part.warranty },
    { label: 'Postage', value: part.postage === 0 ? 'Free UK postage' : `£${part.postage.toFixed(2)}` },
    { label: 'Estimated delivery', value: part.eta },
    { label: 'Location', value: part.location },
  ];

  return (
    <main style={{ maxWidth: 1280, margin: '0 auto', padding: '20px 28px 60px' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: 'var(--ink-3)', marginBottom: 16 }}>
        <button onClick={onBack} style={{
          background: 'transparent', border: 0, color: 'var(--accent-ink)',
          fontWeight: 700, fontSize: 13, cursor: 'pointer', padding: 0,
          display: 'inline-flex', alignItems: 'center', gap: 6,
        }}>
          <Icon.ArrowLeft style={{ width: 14, height: 14 }} /> Back to results
        </button>
        <span style={{ color: 'var(--border-strong)' }}>›</span>
        <span style={{ color: 'var(--ink-2)', fontWeight: 600 }}>{partName}</span>
      </div>

      <div className="fmp-detail-grid" style={{ display: 'grid', gridTemplateColumns: '1fr 380px', gap: 28, alignItems: 'flex-start' }}>
        <div>
          <div style={{ marginBottom: 18 }}>
            <h1 style={{ fontSize: 26, fontWeight: 800, color: 'var(--ink)', margin: '0 0 10px', lineHeight: 1.2, letterSpacing: -0.4 }}>
              {part.title}
            </h1>
            <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
              <ConditionBadge condition={part.condition} oem={part.oem} grade={part.grade} />
              <FitBadge confidence={part.fitConfidence} tier={part.fitTier} reason={part.fitReason} />
              <span className="mono" style={{
                fontSize: 12, color: 'var(--ink-3)', background: 'var(--surface)',
                padding: '4px 8px', borderRadius: 4, border: '1px solid var(--border)',
              }}>
                SKU: {part.sku}
              </span>
            </div>
          </div>

          <DetailPhotoGallery imageUrls={part.imageUrls} />

          <DetailSection title="Fits these models">
            <FitmentSection vehicle={vehicle} confidence={part.fitConfidence} tier={part.fitTier} reason={part.fitReason} compatibleVehicles={part.compatibleVehicles} />
          </DetailSection>

          <DetailSection title="Part details">
            <DetailSpecsTable specs={specs} />
          </DetailSection>

          <DetailSection title="Postage & delivery">
            <p style={{ fontSize: 14, lineHeight: 1.6, color: 'var(--ink-2)', margin: 0 }}>
              {part.postage === 0
                ? `Free UK postage included. Estimated delivery: ${part.eta}.`
                : `£${part.postage.toFixed(2)} postage via standard delivery. Estimated arrival: ${part.eta}.`}
            </p>
          </DetailSection>

          <DetailSection title="Warranty & returns">
            <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
              <div>
                <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink)', marginBottom: 6 }}>
                  🛡 {part.warranty} warranty
                </div>
                <p style={{ fontSize: 14, lineHeight: 1.6, color: 'var(--ink-2)', margin: 0 }}>
                  This part comes with a {part.warranty} warranty from the seller. If the part is faulty, contact the seller for a replacement or refund.
                </p>
              </div>
            </div>
          </DetailSection>

          <DetailSection title="About the seller" noDivider>
            <DetailSellerCard part={part} />
          </DetailSection>
        </div>

        <div>
          <SellerReviewCard part={part} />
          <DetailPriceCard part={part} onReport={onReport} />
        </div>
      </div>
    </main>
  );
}

/* ---------- Pagination ---------- */
function Pagination({ page, totalPages, onChange, loading }) {
  // Compact page list: 1 … (p-1) p (p+1) … last. Always shows first + last.
  const pages = [];
  const push = (v) => { if (!pages.includes(v)) pages.push(v); };
  push(1);
  for (let i = page - 1; i <= page + 1; i++) {
    if (i > 1 && i < totalPages) push(i);
  }
  if (totalPages > 1) push(totalPages);

  const btn = (active, disabled) => ({
    minWidth: 36, height: 36, padding: '0 10px', borderRadius: 8,
    border: '1px solid ' + (active ? 'var(--navy)' : 'var(--border)'),
    background: active ? 'var(--navy)' : '#fff',
    color: active ? '#fff' : 'var(--ink)',
    fontWeight: 700, fontSize: 13,
    cursor: disabled ? 'not-allowed' : 'pointer',
    opacity: disabled ? 0.5 : 1,
    transition: 'background .15s, border-color .15s',
  });

  return (
    <div style={{
      marginTop: 24, display: 'flex', alignItems: 'center', justifyContent: 'center',
      gap: 6, flexWrap: 'wrap',
    }}>
      <button onClick={() => onChange(page - 1)} disabled={page <= 1} style={btn(false, page <= 1)}>‹ Prev</button>
      {pages.map((p, i) => {
        const prev = pages[i - 1];
        const gap = prev && p - prev > 1;
        return (
          <React.Fragment key={p}>
            {gap && <span style={{ color: 'var(--ink-3)', padding: '0 4px' }}>…</span>}
            <button onClick={() => onChange(p)} style={btn(p === page, false)}>{p}</button>
          </React.Fragment>
        );
      })}
      <button onClick={() => onChange(page + 1)} disabled={page >= totalPages} style={btn(false, page >= totalPages)}>Next ›</button>
      {loading && (
        <span style={{ marginLeft: 10, fontSize: 12, color: 'var(--ink-3)' }}>Loading…</span>
      )}
    </div>
  );
}

/* ---------- Retailer Rail (external affiliate partners) ---------- */
const RETAILERS = [
  {
    id: 'amazon',
    name: 'Amazon UK',
    enabled: true,
    logo: '/icons/retailers/amazon-available-stacked.svg',
    buildUrl: (vehicle, part) => {
      const year = vehicle.YearOfManufacture || vehicle.ManufactureYear || '';
      const q = [vehicle.Make, vehicle.Model, year, part].filter(Boolean).join(' ');
      return `https://www.amazon.co.uk/s?k=${encodeURIComponent(q)}&tag=findmypart-21`;
    },
    blurb: 'Huge range, fast Prime delivery',
    accent: '#FF9900',
    ink: '#131921',
  },
  // Awin merchants — stubbed, flip enabled:true once approved
  { id: 'ecp', name: 'Euro Car Parts', enabled: false, buildUrl: () => '#', blurb: 'UK\'s largest factor', accent: '#e30613', ink: '#1a1a1a' },
  { id: 'gsf', name: 'GSF Car Parts', enabled: false, buildUrl: () => '#', blurb: 'Trade-grade parts', accent: '#0a4d9c', ink: '#1a1a1a' },
  { id: 'halfords', name: 'Halfords', enabled: false, buildUrl: () => '#', blurb: 'Accessories & bulbs', accent: '#ee3124', ink: '#1a1a1a' },
];

function RetailerCard({ retailer, vehicle, part }) {
  const r = retailer;
  const onClick = () => {
    try {
      window.fmpTrack && window.fmpTrack('affiliate_click', {
        retailer: r.id,
        retailer_name: r.name,
        part,
        vehicle_make: vehicle?.Make,
        vehicle_model: vehicle?.Model,
        vehicle_year: vehicle?.YearOfManufacture || vehicle?.ManufactureYear,
      });
    } catch (e) { /* never block the nav */ }
  };
  return (
    <a
      href={r.buildUrl(vehicle, part)}
      target="_blank"
      rel="sponsored noopener noreferrer"
      onClick={onClick}
      style={{
        flex: '1 1 220px', minWidth: 220,
        display: 'flex', alignItems: 'center', gap: 12,
        padding: '12px 14px',
        border: '1px solid var(--border)', borderRadius: 10,
        textDecoration: 'none', color: r.ink, background: '#fff',
        transition: 'box-shadow .12s, border-color .12s',
      }}
      onMouseEnter={(e) => { e.currentTarget.style.boxShadow = '0 4px 14px rgba(0,0,0,.06)'; e.currentTarget.style.borderColor = r.accent; }}
      onMouseLeave={(e) => { e.currentTarget.style.boxShadow = 'none'; e.currentTarget.style.borderColor = 'var(--border)'; }}
    >
      {r.logo ? (
        <img
          src={r.logo}
          alt={`Available at ${r.name}`}
          style={{ height: 44, width: 'auto', display: 'block', flexShrink: 0 }}
        />
      ) : (
        <div style={{
          width: 36, height: 36, borderRadius: 8,
          background: r.accent, color: '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontWeight: 800, fontSize: 16, flexShrink: 0,
        }}>
          {r.name.charAt(0)}
        </div>
      )}
      <div style={{ flex: 1, minWidth: 0 }}>
        {!r.logo && <div style={{ fontWeight: 700, fontSize: 14 }}>{r.name}</div>}
        <div style={{ fontSize: 12, color: 'var(--ink-3)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {r.blurb}
        </div>
      </div>
      <div style={{ fontSize: 18, color: r.accent, fontWeight: 700 }}>→</div>
    </a>
  );
}

function RetailerRail({ vehicle, part }) {
  if (!vehicle || !part) return null;
  const active = RETAILERS.filter(r => r.enabled);
  if (active.length === 0) return null;

  return (
    <div style={{
      background: '#fff', border: '1px solid var(--border)', borderRadius: 12,
      padding: 16, marginBottom: 14,
    }}>
      <div style={{
        fontSize: 13, fontWeight: 700, color: 'var(--ink-2)',
        textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 10,
      }}>
        Also check
      </div>
      <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
        {active.map(r => (
          <RetailerCard key={r.id} retailer={r} vehicle={vehicle} part={part} />
        ))}
      </div>
      <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 10 }}>
        Sponsored — we may earn a commission on qualifying purchases.
      </div>
    </div>
  );
}

Object.assign(window, {
  Logo, TopNav, UnionJack, RegPlateInput, PartInput, SearchCard, Label, Spinner,
  VehicleMatchBanner, SmartValueCard, PriceRow,
  TabBar, ResultCard, PartThumb, ConditionBadge, FitBadge, MetaItem,
  SideFilters, FilterGroup, CheckRow, RadioRow, PriceField,
  LoadingPanel, TrustStrip, HowItWorks, Footer, CompareDrawer, SortDropdown,
  DetailPhotoGallery, DetailPriceCard, DetailInfoRow, DetailSection,
  DetailSellerCard, DetailSpecsTable, FitmentSection, SellerReviewCard, ListingDetailView,
  Pagination, ReportFlagButton, ReportToast, RetailerRail,
});
