// 1Radar v3 — Products Library (masonry grid of product cards)

const _fmtCompactP = (n) => {
  if (n == null) return '—';
  if (n >= 1_000_000) return (n / 1_000_000).toFixed(n % 1_000_000 === 0 ? 0 : 1) + 'M';
  if (n >= 1_000) return (n / 1_000).toFixed(n % 1_000 === 0 ? 0 : 1) + 'K';
  return String(n);
};

const fmtEur = (n) => {
  if (n >= 1_000_000) return '€' + (n / 1_000_000).toFixed(1) + 'M';
  if (n >= 1_000) return '€' + (n / 1_000).toFixed(n % 1_000 === 0 ? 0 : 1) + 'K';
  return '€' + n.toFixed(0);
};

const ProdTag = ({ icon, children, tone = 'neutral' }) => {
  const tones = {
    neutral: { bg: 'var(--bg-muted)',         fg: 'var(--text-muted)' },
    green:   { bg: 'rgba(16,185,129,0.12)',   fg: '#047857' },
    amber:   { bg: 'rgba(245,158,11,0.18)',   fg: '#B45309' },
    blue:    { bg: 'rgba(51,92,255,0.10)',    fg: 'var(--accent)' },
  };
  const t = tones[tone] || tones.neutral;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 3,
      height: 20, padding: '0 6px', borderRadius: 6,
      background: t.bg, color: t.fg,
      fontSize: 11, fontWeight: 600, lineHeight: 1, whiteSpace: 'nowrap',
    }}>
      {icon && <Icon name={icon} size={11}/>}
      {children}
    </span>
  );
};

const StarRating = ({ rating, size = 11 }) => {
  const stars = [];
  for (let i = 1; i <= 5; i++) {
    const filled = i <= Math.floor(rating);
    stars.push(
      <svg key={i} width={size} height={size} viewBox="0 0 16 16"
        fill={filled ? '#F59E0B' : 'none'} stroke="#F59E0B" strokeWidth="1.5">
        <polygon points="8,1 10.2,6 15,6.5 11.5,10 12.5,15 8,12.5 3.5,15 4.5,10 1,6.5 5.8,6"/>
      </svg>
    );
  }
  return <span style={{ display: 'inline-flex', alignItems: 'center', gap: 1 }}>{stars}</span>;
};

// Inline sparkline — uses position:absolute tooltip so it works inside a
// CSS-transformed parent (unlike MiniAreaChart which uses position:fixed).
let _pscSeq = 0;
const ProductSalesChart = ({ data, labels, height = 40 }) => {
  const [uid]   = React.useState(() => `psc${++_pscSeq}`);
  const [hov, setHov] = React.useState(null);
  if (!data || data.length < 2) return null;

  const VW    = 400;
  const yMin  = 0;
  const yMax  = Math.max(...data) || 1;
  const getPY = (v) => height - (v / yMax) * (height * 0.88) - height * 0.06;

  const pts      = data.map((v, i) => ({ x: (i / (data.length - 1)) * VW, y: getPY(v) }));
  const linePath = pts.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(' ');
  const areaPath = `${linePath} L${pts[pts.length-1].x.toFixed(1)},${height} L0,${height} Z`;

  const onMouseMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const relX  = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
    const idx   = Math.round(relX * (data.length - 1));
    setHov({ idx, relX });
  };

  const dotPY = hov !== null ? getPY(data[hov.idx]) : null;
  const color = 'var(--accent)';

  // Tooltip flips side when near the right edge
  const tipLeft = hov !== null && hov.relX > 0.65;

  return (
    <div style={{ position: 'relative', overflow: 'visible' }}>
      <svg viewBox={`0 0 ${VW} ${height}`} width="100%" height={height}
        style={{ display: 'block', cursor: 'crosshair', overflow: 'visible' }}
        preserveAspectRatio="none"
        onMouseMove={onMouseMove} onMouseLeave={() => setHov(null)}>
        <defs>
          <linearGradient id={uid} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%"   stopColor={color} stopOpacity="0.22"/>
            <stop offset="100%" stopColor={color} stopOpacity="0.02"/>
          </linearGradient>
        </defs>
        <path d={areaPath} fill={`url(#${uid})`}/>
        <path d={linePath} fill="none" stroke={color} strokeWidth="1.6"
          vectorEffect="non-scaling-stroke" strokeLinejoin="round" strokeLinecap="round"/>
      </svg>

      {hov !== null && <>
        <div style={{
          position: 'absolute', top: 0, bottom: 0,
          left: `${hov.relX * 100}%`, width: 1,
          background: color, opacity: 0.3, pointerEvents: 'none',
          transform: 'translateX(-0.5px)',
        }}/>
        <div style={{
          position: 'absolute',
          left: `${hov.relX * 100}%`, top: dotPY,
          width: 7, height: 7, borderRadius: 999,
          transform: 'translate(-50%, -50%)',
          background: color, border: '1.5px solid var(--bg-surface)',
          pointerEvents: 'none',
        }}/>
        <div style={{
          position: 'absolute',
          top: Math.max(0, dotPY - 36),
          ...(tipLeft
            ? { right: `${(1 - hov.relX) * 100 + 1}%` }
            : { left:  `${hov.relX * 100 + 1}%` }),
          background: 'var(--bg-surface)',
          border: '1px solid var(--border)',
          borderRadius: 8, padding: '4px 8px',
          fontFamily: 'var(--font-mono)',
          boxShadow: '0 4px 14px rgba(14,18,27,0.12)',
          zIndex: 10, pointerEvents: 'none', whiteSpace: 'nowrap',
          display: 'flex', flexDirection: 'column', gap: 1,
        }}>
          {labels && <span style={{ color: 'var(--text-faint)', fontSize: 10 }}>{labels[hov.idx]}</span>}
          <span style={{ fontWeight: 600, color: 'var(--text)', fontSize: 11.5 }}>
            {Math.round(data[hov.idx])} sales
          </span>
        </div>
      </>}
    </div>
  );
};

const PRODUCT_CARD_FIELDS_DEFAULT = {
  activity: true, tags: true, rank: true, stats: true,
  salesChart: true, rating: true, description: true, price: true,
};

const PRODUCT_CARD_FIELD_OPTIONS = [
  { id: 'activity',    label: 'Brand activity',   icon: 'sparkles' },
  { id: 'tags',        label: 'Header tags',      icon: 'tag' },
  { id: 'rank',        label: 'Rank',             icon: 'trend-up' },
  { id: 'stats',       label: 'Sales stats',      icon: 'wallet' },
  { id: 'salesChart',  label: 'Sales chart',      icon: 'trend-up' },
  { id: 'rating',      label: 'Rating & reviews', icon: 'star' },
  { id: 'description', label: 'Description',      icon: 'message' },
  { id: 'price',       label: 'Price',            icon: 'tag' },
];

const PRODUCT_CARD_MENU_ITEMS = [
  { id: 'open',   label: 'Open product details', icon: 'external' },
  { id: 'copy',   label: 'Copy product URL',     icon: 'copy' },
  { id: 'folder', label: 'Add to folder…',       icon: 'folder' },
  { id: 'share',  label: 'Share',                icon: 'share' },
  { id: 'sep' },
  { id: 'hide',   label: 'Hide brand',           icon: 'eye-off', danger: false },
  { id: 'report', label: 'Report product',       icon: 'flag',    danger: true },
];

const ProductCard = ({ product, onOpen, onSave, onAnalyze, rank, fields }) => {
  const [hover, setHover] = React.useState(false);
  const [savedFolders, setSavedFolders] = React.useState(() => new Set());
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [saveOpen, setSaveOpen] = React.useState(false);
  const [extraFolders, setExtraFolders] = React.useState([]);
  const f = { ...PRODUCT_CARD_FIELDS_DEFAULT, ...(fields || {}) };
  const savedToFile = savedFolders.size > 0;

  const myRank       = rank ?? Math.max(1, ((product.sales % 18) + 1));
  const prevRank     = Math.max(1, myRank + ((product.reviews % 10) - 5));
  const rankWindow   = 30 + (product.daysListed % 60);
  const activeProds  = 5  + (product.sales % 40);
  const totalProds   = activeProds + 15 + (product.reviews % 60);
  const seed         = parseInt(product.id.replace('prod', ''), 10);
  const salesData    = React.useMemo(() => genDailyData(seed * 37, product.sales / 30, 30), [product.id]);

  const popoverOpen = menuOpen || saveOpen;
  const isHover     = hover || popoverOpen;

  const badgeTone = product.badge === 'New' ? 'green'
    : product.badge === 'Sale' ? 'amber'
    : product.badge === 'Trending' ? 'blue'
    : 'neutral';

  return (
    <div
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      onClick={() => onOpen && onOpen(product)}
      style={{
        breakInside: 'avoid', marginBottom: 12,
        background: 'var(--bg-surface)',
        borderRadius: 14,
        border: '1px solid var(--border)',
        overflow: 'hidden',
        cursor: popoverOpen ? 'default' : 'pointer',
        transition: 'box-shadow .15s, transform .15s',
        transform: isHover ? 'translateY(-1px)' : 'none',
        boxShadow: isHover
          ? '0 10px 28px rgba(14,18,27,0.10)'
          : '0 1px 2px rgba(14,18,27,0.04)',
      }}>

      {/* Product image */}
      <div style={{
        position: 'relative',
        height: Math.max(160, product.h - 220),
        background: product.thumb,
        overflow: 'hidden',
      }}>
        <div style={{
          position: 'absolute', inset: 0,
          background: 'linear-gradient(180deg, rgba(0,0,0,0) 50%, rgba(0,0,0,0.42))',
        }}/>
        {/* Product name overlay */}
        <div style={{
          position: 'absolute', left: 14, bottom: 14, right: 14,
          color: '#fff',
          fontFamily: 'var(--font-display)', fontWeight: 700,
          fontSize: 18, letterSpacing: '-0.02em',
          lineHeight: 1.2,
          overflow: 'hidden', display: '-webkit-box',
          WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
        }}>
          {product.name}
        </div>

        {/* Badge top-right */}
        {f.tags && product.badge && (
          <div style={{ position: 'absolute', top: 10, right: 10 }}>
            <ProdTag tone={badgeTone}>{product.badge}</ProdTag>
          </div>
        )}

        {/* Hover overlay */}
        {isHover && (
          <div style={{
            position: 'absolute', inset: 0,
            background: 'linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.15))',
          }}/>
        )}
      </div>

      {/* Brand header + price */}
      <div style={{ padding: '10px 12px 0', display: 'flex', alignItems: 'flex-start', gap: 10 }}>
        <BrandChip name={product.brand} size={26} square/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontSize: 13, fontWeight: 600, color: 'var(--text)',
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>
            {product.brand}
          </div>
          {f.activity && (
            <div style={{ fontSize: 11, color: 'var(--text-muted)', display: 'flex', alignItems: 'center', gap: 5, marginTop: 1 }}>
              <span style={{ width: 5, height: 5, borderRadius: 999, background: '#10B981' }}/>
              <span style={{ fontFamily: 'var(--font-mono)' }}>{activeProds}</span>
              {' '}of{' '}
              <span style={{ fontFamily: 'var(--font-mono)' }}>{totalProds}</span>
              {' '}products
            </div>
          )}
        </div>
        {f.price && (
          <div style={{ flexShrink: 0, textAlign: 'right' }}>
            <span style={{
              fontSize: 16, fontWeight: 700, color: 'var(--text)',
              fontFamily: 'var(--font-display)', letterSpacing: '-0.02em',
            }}>
              {fmtEur(product.price)}
            </span>
          </div>
        )}
      </div>

      {/* Rank row */}
      {f.rank && (
        <div style={{
          padding: '6px 12px', marginTop: 8,
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          fontSize: 11.5, color: 'var(--text-muted)',
          background: 'var(--bg-muted)',
          borderTop: '1px solid var(--border-soft)',
          borderBottom: '1px solid var(--border-soft)',
        }}>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, color: 'var(--text)', fontWeight: 600 }}>
            <Icon name="trend-up" size={12} style={{ color: 'var(--text-muted)' }}/>
            Rank <span style={{ fontFamily: 'var(--font-mono)' }}>#{myRank}</span>
          </span>
          <span>
            from{' '}
            <span style={{
              display: 'inline-block', padding: '1px 5px', borderRadius: 4,
              background: 'var(--bg-surface)', border: '1px solid var(--border)',
              fontFamily: 'var(--font-mono)', color: 'var(--text)', fontWeight: 500,
            }}>#{prevRank}</span>
            {' '}in{' '}
            <span style={{
              display: 'inline-block', padding: '1px 5px', borderRadius: 4,
              background: 'var(--bg-surface)', border: '1px solid var(--border)',
              fontFamily: 'var(--font-mono)', color: 'var(--text)', fontWeight: 500,
            }}>{rankWindow}</span>
            {' '}days
          </span>
        </div>
      )}

      {/* Sales stats */}
      {f.stats && (
        <div style={{
          padding: '8px 12px',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          fontSize: 12, color: 'var(--text)', fontFamily: 'var(--font-mono)',
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--text-muted)' }}>
            <span style={{ color: 'var(--text)' }}>{_fmtCompactP(product.sales)} sold</span>
            <span>·</span>
            <span style={{ color: 'var(--text)' }}>{fmtEur(product.revenue)}</span>
          </div>
          <div style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
            <Icon name={`flag-${product.country}`} size={12}/>
          </div>
        </div>
      )}

      {/* Sales area chart */}
      {f.salesChart && (
        <div style={{ padding: '4px 12px 8px' }}>
          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            marginBottom: 5,
            fontSize: 10.5, color: 'var(--text-faint)',
          }}>
            <span>Sales · last 30 days</span>
            <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', fontWeight: 500 }}>
              {_fmtCompactP(Math.round(salesData.reduce((a, b) => a + b, 0)))} units
            </span>
          </div>
          <ProductSalesChart
            data={salesData}
            labels={DAY_LABELS_30}
            height={40}
          />
        </div>
      )}

      {/* Rating + category */}
      {f.rating && (
        <div style={{
          padding: '0 12px 10px',
          display: 'flex', alignItems: 'center', gap: 6,
          fontSize: 11.5, color: 'var(--text-muted)',
          flexWrap: 'wrap',
        }}>
          <StarRating rating={product.rating}/>
          <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text)', fontWeight: 500 }}>
            {product.rating.toFixed(1)}
          </span>
          <span>· {_fmtCompactP(product.reviews)} reviews</span>
          <span style={{ marginLeft: 'auto' }}>
            <ProdTag>{product.category}</ProdTag>
          </span>
        </div>
      )}

      {/* Description */}
      {f.description && (
        <div style={{
          padding: '0 14px 12px',
          fontSize: 12.5, lineHeight: '18px', color: 'var(--text-muted)',
          letterSpacing: '-0.006em',
          overflow: 'hidden', display: '-webkit-box',
          WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
        }}>
          {product.description}
        </div>
      )}

      {/* Footer: Save | Analyze | More */}
      <div style={{
        display: 'flex', alignItems: 'stretch',
        borderTop: '1px solid var(--border-soft)',
        background: 'var(--bg-surface)',
      }}>
        <div style={{ flex: 1, position: 'relative' }} onClick={(e) => e.stopPropagation()}>
          <button onClick={() => setSaveOpen(v => !v)} style={{
            width: '100%', height: 38, border: 0,
            background: saveOpen ? 'var(--bg-soft)' : 'transparent',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            fontSize: 12.5, fontWeight: 500,
            color: savedToFile ? 'var(--accent)' : 'var(--text)',
            cursor: 'pointer', transition: 'background .12s',
          }}
          onMouseEnter={(e) => { if (!saveOpen) e.currentTarget.style.background = 'var(--bg-soft)'; }}
          onMouseLeave={(e) => { if (!saveOpen) e.currentTarget.style.background = 'transparent'; }}>
            <Icon name="bookmark" size={14}/>
            {savedToFile ? `Saved · ${savedFolders.size}` : 'Save'}
          </button>
          {saveOpen && (
            <SaveToFolderPopup
              folders={[...SAVE_FOLDERS_V3, ...extraFolders]}
              selected={savedFolders}
              onToggle={(id) => {
                setSavedFolders(s => {
                  const n = new Set(s);
                  n.has(id) ? n.delete(id) : n.add(id);
                  return n;
                });
                onSave && onSave(product);
              }}
              onCreateFolder={(name, choice) => {
                const id = 'custom_' + Date.now();
                setExtraFolders(arr => [...arr, {
                  id, name, count: 0,
                  icon:  choice?.icon  || 'folder',
                  color: choice?.color || 'var(--text-faint)',
                }]);
                setSavedFolders(s => { const n = new Set(s); n.add(id); return n; });
              }}
              onClose={() => setSaveOpen(false)}
              anchor="left"
            />
          )}
        </div>

        <div style={{ width: 1, background: 'var(--border-soft)' }}/>

        <button onClick={(e) => { e.stopPropagation(); onAnalyze && onAnalyze(product); }} style={{
          flex: 1, height: 38, border: 0, background: 'transparent',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          fontSize: 12.5, fontWeight: 500, color: 'var(--text)',
          cursor: 'pointer', transition: 'background .12s',
        }}
        onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-muted)'}
        onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
          <Icon name="sparkles" size={14} style={{ color: 'var(--accent)' }}/>
          Analyze
        </button>

        <div style={{ width: 1, background: 'var(--border-soft)' }}/>

        <div style={{ position: 'relative' }} onClick={(e) => e.stopPropagation()}>
          <button onClick={() => setMenuOpen(v => !v)} style={{
            width: 38, height: 38, border: 0,
            background: menuOpen ? 'var(--bg-muted)' : 'transparent',
            color: menuOpen ? 'var(--text)' : 'var(--text-muted)',
            cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            transition: 'background .12s, color .12s',
          }}
          onMouseEnter={(e) => { if (!menuOpen) e.currentTarget.style.background = 'var(--bg-muted)'; }}
          onMouseLeave={(e) => { if (!menuOpen) e.currentTarget.style.background = 'transparent'; }}
          aria-label="More actions">
            <Icon name="more-h" size={16}/>
          </button>
          {menuOpen && (
            <>
              <div onClick={() => setMenuOpen(false)} style={{ position: 'fixed', inset: 0, zIndex: 60, cursor: 'default' }}/>
              <div role="menu" style={{
                position: 'absolute', bottom: 'calc(100% + 6px)', right: 0,
                zIndex: 61, width: 220,
                background: 'var(--bg-surface)',
                border: '1px solid var(--border)',
                borderRadius: 10,
                boxShadow: '0 12px 32px rgba(14,18,27,0.12)',
                padding: 4, cursor: 'default',
              }}>
                {PRODUCT_CARD_MENU_ITEMS.map((item) => {
                  if (item.id === 'sep') return <div key="sep" style={{ height: 1, background: 'var(--border)', margin: '4px 6px' }}/>;
                  const handle = (e) => {
                    e.stopPropagation();
                    setMenuOpen(false);
                    if (item.id === 'open') onOpen && onOpen(product);
                    if (item.id === 'copy') navigator.clipboard?.writeText(`https://${product.brand.toLowerCase().replace(/\s+/g, '-')}.com`);
                    if (item.id === 'folder') setSaveOpen(true);
                  };
                  return (
                    <button key={item.id} onClick={handle} style={{
                      display: 'flex', alignItems: 'center', gap: 10,
                      width: '100%', padding: '7px 10px',
                      background: 'transparent', border: 0, borderRadius: 6,
                      color: item.danger ? 'var(--danger, #E5484D)' : 'var(--text)',
                      fontSize: 13, textAlign: 'left', cursor: 'pointer',
                    }}
                    onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-muted)'}
                    onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
                      <Icon name={item.icon} size={14} style={{ color: item.danger ? 'var(--danger, #E5484D)' : 'var(--text-muted)' }}/>
                      <span style={{ flex: 1 }}>{item.label}</span>
                    </button>
                  );
                })}
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
};

const PRODUCT_SORT_OPTIONS = [
  { id: 'sales',   label: 'Sales',       icon: 'wallet',   key: (p) => p.sales },
  { id: 'revenue', label: 'Revenue',     icon: 'wallet',   key: (p) => p.revenue },
  { id: 'price',   label: 'Price',       icon: 'tag',      key: (p) => p.price },
  { id: 'rating',  label: 'Rating',      icon: 'star',     key: (p) => p.rating },
  { id: 'reviews', label: 'Reviews',     icon: 'users',    key: (p) => p.reviews },
  { id: 'recent',  label: 'Most recent', icon: 'sparkles', key: (p) => -p.daysListed },
  { id: 'days',    label: 'Days listed', icon: 'calendar', key: (p) => p.daysListed },
  { id: 'brand',   label: 'Brand (A–Z)', icon: 'building', key: (p) => p.brand.toLowerCase() },
];

const sortProducts = (products, sortId, direction) => {
  const opt = PRODUCT_SORT_OPTIONS.find(o => o.id === sortId) || PRODUCT_SORT_OPTIONS[0];
  const sign = direction === 'asc' ? 1 : -1;
  return [...products].sort((a, b) => {
    const ka = opt.key(a), kb = opt.key(b);
    if (typeof ka === 'string') return sign * ka.localeCompare(kb);
    return sign * (ka - kb);
  });
};

const ExploreProductsV3 = ({ onOpenProduct, onAnalyzeProduct }) => {
  const [search, setSearch] = React.useState('');
  const [activeChip, setActiveChip] = React.useState([]);
  const [savedIds, setSavedIds] = React.useState({});
  const [sort, setSort] = React.useState('sales');
  const [sortDir, setSortDir] = React.useState('desc');
  const [cardFields, setCardFields] = React.useState(PRODUCT_CARD_FIELDS_DEFAULT);

  const mkFilter = (id, icon) => {
    const value = FILTER_DEFS[id]?.initial;
    return { id, icon, value, label: FILTER_DEFS[id]?.label(value) ?? '' };
  };
  const [activeFilters, setActiveFilters] = React.useState(() => [
    mkFilter('date',  'calendar'),
    mkFilter('geo',   'globe'),
    mkFilter('reach', 'users'),
    mkFilter('spend', 'wallet'),
  ]);

  const chips = [
    { id: 'fashion',   label: 'Fashion',   icon: null },
    { id: 'beauty',    label: 'Beauty',    icon: null },
    { id: 'fragrance', label: 'Fragrance', icon: null },
    { id: 'sale',      label: 'On sale',   icon: 'tag' },
    { id: 'new',       label: 'New',       icon: 'sparkles' },
    { id: 'trending',  label: 'Trending',  icon: 'trend-up' },
  ];

  const toggleChip = (id) => setActiveChip(a => a.includes(id) ? a.filter(x => x !== id) : [...a, id]);

  const baseProducts = PRODUCTS_V3.filter(p => {
    if (activeChip.includes('fashion')   && p.category !== 'Fashion')   return false;
    if (activeChip.includes('beauty')    && p.category !== 'Beauty')    return false;
    if (activeChip.includes('fragrance') && p.category !== 'Fragrance') return false;
    if (activeChip.includes('sale')      && p.badge !== 'Sale')         return false;
    if (activeChip.includes('new')       && p.badge !== 'New')          return false;
    if (activeChip.includes('trending')  && p.badge !== 'Trending')     return false;
    if (search && !(
      p.name.toLowerCase().includes(search.toLowerCase()) ||
      p.brand.toLowerCase().includes(search.toLowerCase()) ||
      p.category.toLowerCase().includes(search.toLowerCase())
    )) return false;
    return true;
  });

  const products = sortProducts(baseProducts, sort, sortDir);

  return (
    <>
      <PageHeader
        icon="shop"
        title="Product Library"
        subtitle="Explore top-performing products from leading brands"
        right={
          <>
            <button className="btn btn-stroke btn-sm">
              <Icon name="play-line" size={14}/> Tutorial
            </button>
            <button className="btn btn-night btn-sm">
              <Icon name="plus" size={14}/> New search
            </button>
          </>
        }
      />

      <FilterStripV3
        filterMode="all"
        onFilterMode={() => {}}
        search={search} onSearch={setSearch}
        chips={chips} activeChip={activeChip} onChip={toggleChip}
        activeFilters={activeFilters}
        onActiveFiltersChange={setActiveFilters}
      />

      <SortRowV3
        count={products.length * 8420}
        sort={sort}
        sortOptions={PRODUCT_SORT_OPTIONS}
        direction={sortDir}
        onSort={setSort}
        onDirection={setSortDir}
        cardFields={cardFields}
        cardFieldOptions={PRODUCT_CARD_FIELD_OPTIONS}
        onCardFieldsChange={setCardFields}
      />

      <div style={{ padding: 24, flex: 1, overflow: 'auto' }} className="scroll">
        <div style={{ columnCount: 4, columnGap: 12 }}>
          {products.map((product, i) => (
            <ProductCard
              key={product.id}
              product={product}
              rank={i + 1}
              fields={cardFields}
              onOpen={onOpenProduct}
              onAnalyze={onAnalyzeProduct}
              onSave={(p) => setSavedIds(s => ({ ...s, [p.id]: !s[p.id] }))}
            />
          ))}
        </div>
      </div>
    </>
  );
};

Object.assign(window, { ExploreProductsV3, ProductCard, PRODUCT_SORT_OPTIONS, sortProducts, PRODUCT_CARD_FIELDS_DEFAULT, PRODUCT_CARD_FIELD_OPTIONS });
