// components.jsx — IconCard, Sidebar, Hero, Collections, DetailPanel, CmdK

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

// ─── Icon card ─────────────────────────────────────────────────────────
function IconCard({ app, size = 132, onOpen, density = 'regular', radius = 'continuous', isFavorited = false, onToggleFavorite }) {
  const [hover, setHover] = useState(false);
  const pad = density === 'compact' ? 14 : density === 'comfy' ? 28 : 20;

  return (
    <div className="icon-card-wrap"
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{ position: 'relative' }}>
      <button
        className="icon-card"
        onClick={() => onOpen?.(app)}
        style={{ padding: pad, width: '100%' }}
        aria-label={`${app.app_name} by ${app.developer}`}>
        <div className="icon-card-art" style={{ width: size, height: size }}>
          <div className="icon-shadow" />
          <div className="icon-inner" style={{ transform: hover ? 'scale(1.04)' : 'scale(1)' }}>
            <IconArt app={app} size={size} radius={radius} />
          </div>
        </div>
        <div className={`icon-meta ${hover ? 'is-hover' : ''}`}>
          <div className="icon-name">{app.app_name}</div>
          <div className="icon-sub">
            <span>{app.developer}</span>
            <span className="dot">·</span>
            <span className="muted">{app.category}</span>
          </div>
        </div>
      </button>
      {(hover || isFavorited) && (
        <button className="fav-btn" aria-label={isFavorited ? 'Remove from favorites' : 'Save to favorites'}
          onClick={e => { e.stopPropagation(); onToggleFavorite?.(app.id); }}
          style={{ opacity: hover || isFavorited ? 1 : 0 }}>
          <svg viewBox="0 0 24 24" width="14" height="14" fill={isFavorited ? 'var(--accent)' : 'none'}
            stroke={isFavorited ? 'var(--accent)' : 'currentColor'} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
            <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
          </svg>
        </button>
      )}
    </div>
  );
}

// ─── Filter sidebar ───────────────────────────────────────────────────
function FilterSidebar({ filters, setFilters, counts, user, favorites, onFavoritesToggle }) {
  const update = (k, v) => setFilters({ ...filters, [k]: v });
  const toggle = (k, v) => {
    const cur = filters[k] || [];
    update(k, cur.includes(v) ? cur.filter((x) => x !== v) : [...cur, v]);
  };
  const active = (k, v) => (filters[k] || []).includes(v);

  return (
    <aside className="sidebar">
      <div className="side-section">
        <div className="side-h">
          <span>Filters</span>
          <button className="link-btn" onClick={() => setFilters({})}>Reset</button>
        </div>
      </div>

      {user && favorites?.size > 0 && (
        <div className="side-section">
          <button className={`check-row ${filters.favorites ? 'on' : ''}`} onClick={onFavoritesToggle}
                  style={{ width: '100%' }}>
            <span className="check-box">{filters.favorites && <span className="check-tick">✓</span>}</span>
            <span className="check-lbl">Saved icons</span>
            <span className="check-count">{favorites.size}</span>
          </button>
        </div>
      )}

      <SideGroup label="Category">
        {CATEGORIES.map((c) =>
        <CheckRow key={c} label={c} count={counts.category[c]}
        checked={active('category', c)} onClick={() => toggle('category', c)} />
        )}
      </SideGroup>

      <SideGroup label="Color">
        <div className="color-grid">
          {COLOR_TAGS.map((c) =>
          <button key={c.name}
          className={`color-chip ${active('color', c.name) ? 'on' : ''}`}
          onClick={() => toggle('color', c.name)}
          title={c.name}>
              <span className="swatch" style={{ background: c.hex }} />
              <span className="chip-label">{c.name}</span>
            </button>
          )}
        </div>
      </SideGroup>

      <SideGroup label="Style">
        {STYLES.map((s) =>
        <CheckRow key={s} label={s} count={counts.style[s]}
        checked={active('style', s)} onClick={() => toggle('style', s)} />
        )}
      </SideGroup>

      <SideGroup label="Pricing">
        <Segmented value={filters.pricing || 'all'}
        onChange={(v) => update('pricing', v)}
        options={[{ v: 'all', l: 'All' }, { v: 'free', l: 'Free' }, { v: 'paid', l: 'Paid' }]} />
      </SideGroup>

      <SideGroup label="Year">
        <Segmented value={filters.year || 'all'}
        onChange={(v) => update('year', v)}
        options={[{ v: 'all', l: 'All' }, { v: 2025, l: '2025' }, { v: 2024, l: '2024' }, { v: 2023, l: '2023' }]} />
      </SideGroup>

      <SideGroup label="Sort by">
        <Segmented value={filters.sort || 'popular'}
        onChange={(v) => update('sort', v)}
        options={[{ v: 'popular', l: 'Popular' }, { v: 'recent', l: 'Recent' }, { v: 'rating', l: 'Top' }]} />
      </SideGroup>
    </aside>);

}

function SideGroup({ label, children }) {
  const [open, setOpen] = useState(true);
  return (
    <div className="side-section">
      <button className="side-h side-h-btn" onClick={() => setOpen(!open)}>
        <span>{label}</span>
        <span className={`chev ${open ? 'open' : ''}`}>›</span>
      </button>
      {open && <div className="side-body">{children}</div>}
    </div>);

}

function CheckRow({ label, checked, onClick, count }) {
  return (
    <button className={`check-row ${checked ? 'on' : ''}`} onClick={onClick}>
      <span className="check-box">{checked && <span className="check-tick">✓</span>}</span>
      <span className="check-lbl">{label}</span>
      {count != null && <span className="check-count">{count}</span>}
    </button>);

}

function Segmented({ value, onChange, options }) {
  return (
    <div className="segmented">
      {options.map((o) =>
      <button key={o.v} className={`seg ${value === o.v ? 'on' : ''}`} onClick={() => onChange(o.v)}>
          {o.l}
        </button>
      )}
    </div>);

}

// ─── Top bar ─────────────────────────────────────────────────────────
// ─── Animated nav menu (magic pill + char flip on hover) ─────────────
function NavMenu({ items }) {
  const navRef = useRef(null);
  const pillRef = useRef(null);
  const itemRefs = useRef([]);
  const activeIdx = items.findIndex(i => i.active);
  const [hoverIdx, setHoverIdx] = useState(activeIdx >= 0 ? activeIdx : 0);

  // initial stagger-in
  useEffect(() => {
    if (!window.gsap) return;
    window.gsap.fromTo(itemRefs.current.filter(Boolean),
      { y: -8, opacity: 0 },
      { y: 0, opacity: 1, duration: 0.5, stagger: 0.05, ease: 'power3.out', delay: 0.1 });
    window.gsap.fromTo(pillRef.current,
      { opacity: 0, scale: 0.85 },
      { opacity: 1, scale: 1, duration: 0.45, ease: 'power3.out', delay: 0.25 });
  }, []);

  // pill follows hoverIdx
  useEffect(() => {
    if (!window.gsap || !navRef.current || !pillRef.current) return;
    const el = itemRefs.current[hoverIdx];
    if (!el) return;
    const navRect = navRef.current.getBoundingClientRect();
    const r = el.getBoundingClientRect();
    window.gsap.to(pillRef.current, {
      x: r.left - navRect.left,
      width: r.width,
      duration: 0.45,
      ease: 'expo.out',
    });
  }, [hoverIdx]);

  return (
    <nav className="topnav" ref={navRef}
         onMouseLeave={() => setHoverIdx(activeIdx >= 0 ? activeIdx : 0)}>
      <span className="nav-pill" ref={pillRef} />
      {items.map((it, i) => (
        <a key={it.label} href={it.href || '#'}
           ref={(el) => itemRefs.current[i] = el}
           className={`nav-link ${i === activeIdx ? 'active' : ''} ${i === hoverIdx ? 'is-hover' : ''}`}
           onMouseEnter={() => setHoverIdx(i)}>
          <span className="nav-label">
            <span className="nav-label-front">{it.label}</span>
            <span className="nav-label-back" aria-hidden="true">{it.label}</span>
          </span>
        </a>
      ))}
    </nav>
  );
}

function TopBar({ onSearch, onCmdK, dark, setDark, user, onAuthClick, page }) {
  const signOut = () => supabase.auth.signOut();
  return (
    <header className="topbar">
      <div className="topbar-inner">
        <a className="brand" href="#discover">
          <span className="brand-name">App<span className="brand-light" style={{ fontWeight: "600" }}>Store</span>Icons</span>
        </a>

        <NavMenu items={[
          { label: 'Discover',    href: '#discover',     active: page === 'discover' || !page },
          { label: 'Collections', href: '#collections',  active: page === 'collections' },
          { label: 'Styles',      href: '#styles',       active: page === 'styles' },
          { label: 'Submit',      href: '#submit',       active: page === 'submit' },
        ]} />

        <div className="topbar-actions">
          <button className="search-trigger" onClick={onCmdK}>
            <svg viewBox="0 0 24 24" width="14" height="14"><circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" strokeWidth="1.6" /><path d="M16 16L21 21" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" /></svg>
            <span>Search icons…</span>
            <kbd>⌘K</kbd>
          </button>
          <button className="icon-btn" onClick={() => setDark(!dark)} aria-label="Toggle theme">
            {dark ?
            <svg viewBox="0 0 24 24" width="16" height="16"><circle cx="12" cy="12" r="4" fill="currentColor" /><g stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><path d="M12 2v3M12 19v3M2 12h3M19 12h3M4.6 4.6l2.1 2.1M17.3 17.3l2.1 2.1M4.6 19.4l2.1-2.1M17.3 6.7l2.1-2.1" /></g></svg> :
            <svg viewBox="0 0 24 24" width="16" height="16"><path d="M20 14.5A8 8 0 1 1 9.5 4a6.5 6.5 0 0 0 10.5 10.5z" fill="currentColor" /></svg>}
          </button>
          {user ? (
            <button className="ghost-btn" onClick={signOut} title={user.email}>Sign out</button>
          ) : (
            <button className="primary-btn" onClick={onAuthClick}>Sign in</button>
          )}
        </div>
      </div>
    </header>
  );
}

// ─── Hero ────────────────────────────────────────────────────────────
function Hero({ onCmdK, totalCount }) {
  return (
    <section className="hero">
      <h1 className="hero-title" style={{ fontFamily: "system-ui" }}>
        Explore the world's best app icons<br />
        <em style={{ fontFamily: "system-ui" }}></em>
      </h1>
      <p className="hero-sub">
        A curated visual library of iOS icon design inspiration — searchable by color, style, category, and craft.
      </p>
      <div className="hero-actions">
        <button className="search-pill" onClick={onCmdK}>
          <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" strokeWidth="1.6" /><path d="M16 16L21 21" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" /></svg>
          <span className="search-pill-text">Search apps, developers, palettes…</span>
          <kbd>⌘K</kbd>
        </button>
      </div>
    </section>);

}

// ─── Collections row ─────────────────────────────────────────────────
function CollectionsRow({ collections, onOpen }) {
  return (
    <section className="row">
      <div className="row-h">
        <div>
          <h2 className="row-title" style={{ fontFamily: "\"SF Pro Text\"" }}>Featured collections</h2>
          <p className="row-sub">Curated by the editorial team · updated weekly</p>
        </div>
        <div className="row-nav">
          <a className="link-btn" href="#">View all →</a>
        </div>
      </div>
      <div className="collections-scroll">
        {collections.map((c) =>
        <CollectionCard key={c.id} collection={c} onOpen={onOpen} />
        )}
      </div>
    </section>);

}

function CollectionCard({ collection, onOpen }) {
  const apps = collection.appIds.slice(0, 4).map(getApp).filter(Boolean);
  const [c1, c2, c3] = ICON_PALETTES[collection.palette] || ICON_PALETTES.paper;
  return (
    <button className="collection-card" onClick={() => onOpen?.(collection)}
    style={{ background: `linear-gradient(135deg, ${c1}, ${c2})` }}>
      <div className="coll-grid">
        {apps.map((a, i) =>
        <div key={a.id} className={`coll-tile coll-tile-${i}`}>
            <IconArt app={a} size={48} radius="continuous" />
          </div>
        )}
      </div>
      <div className="coll-meta">
        <div className="coll-title" style={{ color: c3 }}>{collection.title}</div>
        <div className="coll-count">{collection.appIds.length} icons</div>
      </div>
    </button>);

}

// ─── Trending strip ─────────────────────────────────────────────────
function TrendingRow({ apps, onOpen }) {
  return (
    <section className="row">
      <div className="row-h">
        <div>
          <h2 className="row-title">Trending this week</h2>
          <p className="row-sub">Most-saved icons across the community</p>
        </div>
      </div>
      <div className="trending-scroll">
        {apps.map((a, i) =>
        <button key={a.id} className="trend-card" onClick={() => onOpen?.(a)}>
            <span className="trend-rank">{String(i + 1).padStart(2, '0')}</span>
            <IconArt app={a} size={64} radius="continuous" />
            <div className="trend-meta">
              <div className="trend-name">{a.app_name}</div>
              <div className="trend-dev">{a.developer}</div>
            </div>
            <div className="trend-spark">
              <Sparkline seed={i} />
            </div>
          </button>
        )}
      </div>
    </section>);

}

function Sparkline({ seed = 0 }) {
  const pts = useMemo(() => {
    const n = 20;
    let v = 50;
    const arr = [];
    for (let i = 0; i < n; i++) {
      v = Math.max(8, Math.min(60, v + (Math.sin(i * 1.3 + seed) + Math.cos(i * 0.7)) * 6 | 0));
      arr.push(v);
    }
    // ensure upward trend
    return arr.map((y, i) => 60 - y + i * 1.2);
  }, [seed]);
  const w = 70,h = 24;
  const d = pts.map((y, i) => `${i === 0 ? 'M' : 'L'} ${i / (pts.length - 1) * w} ${Math.max(2, Math.min(h - 2, y / 3))}`).join(' ');
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      <path d={d} fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
    </svg>);

}

// ─── Detail slide-over ─────────────────────────────────────────────
function DetailPanel({ app, onClose, onOpen, radius, isFavorited, onToggleFavorite }) {
  useEffect(() => {
    const onKey = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  if (!app) return null;
  const palette = ICON_PALETTES[app.palette] || [];
  const [c1, c2, c3] = palette;
  const similar = similarApps(app, 8);

  return (
    <div className="detail-overlay" onClick={onClose}>
      <div className="detail-panel" onClick={(e) => e.stopPropagation()}>
        <button className="detail-close" onClick={onClose} aria-label="Close">
          <svg viewBox="0 0 24 24" width="14" height="14"><path d="M5 5L19 19M19 5L5 19" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" /></svg>
        </button>

        <div className="detail-grid">
          <div className="detail-left">
            <div className="detail-icon-wrap" style={{ background: `radial-gradient(120% 80% at 30% 20%, ${c3}55, transparent 70%), linear-gradient(160deg, ${c1}10, ${c2}05)` }}>
              <div className="detail-icon">
                <IconArt app={app} size={220} radius={radius} />
              </div>
            </div>

            <div className="detail-actions">
              <button className="primary-btn block">
                <svg viewBox="0 0 24 24" width="14" height="14"><path d="M19 11.5c0-1.6-.8-2.9-2.1-3.7.5-.7.8-1.6.8-2.5 0-2-1.4-3.3-3.3-3.3-.7 0-1.5.2-2.1.6C11.6 1.5 10.6 1 9.5 1c-2 0-3.3 1.4-3.3 3.3 0 .9.3 1.8.8 2.5C5.7 7.7 5 9 5 10.5c0 4.5 4 11.5 7 11.5s7-7 7-10.5z" fill="currentColor" /></svg>
                View on App Store
              </button>
              <button className="ghost-btn block" onClick={() => onToggleFavorite?.(app.id)}>
                <svg viewBox="0 0 24 24" width="14" height="14"
                     fill={isFavorited ? 'var(--accent)' : 'none'}
                     stroke={isFavorited ? 'var(--accent)' : 'currentColor'}
                     strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
                </svg>
                {isFavorited ? 'Saved' : 'Save'}
              </button>
              <button className="ghost-btn block">
                <svg viewBox="0 0 24 24" width="14" height="14"><path d="M12 16V4M12 4l-4 4M12 4l4 4M4 20h16" stroke="currentColor" strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round" /></svg>
                Download .png
              </button>
            </div>

            <div className="meta-card">
              <div className="meta-h">Color palette</div>
              <div className="palette-row">
                {palette.map((hex, i) =>
                <div key={i} className="palette-swatch">
                    <span className="ps-color" style={{ background: hex }} />
                    <span className="ps-hex">{hex.toUpperCase()}</span>
                  </div>
                )}
              </div>
            </div>

            <div className="meta-card">
              <div className="meta-h">Metadata</div>
              <dl className="meta-list">
                <dt>Category</dt><dd>{app.category}</dd>
                <dt>Style</dt><dd>{app.styles.join(', ')}</dd>
                <dt>Released</dt><dd>{app.year}</dd>
                <dt>Rating</dt><dd>{app.rating} ★</dd>
                <dt>Pricing</dt><dd>{app.paid ? 'Paid' : 'Free'}</dd>
              </dl>
            </div>
          </div>

          <div className="detail-right">
            <div className="detail-eyebrow">{app.developer}</div>
            <h2 className="detail-title">{app.app_name}</h2>
            <p className="detail-pitch">
              An icon study in {app.styles.join(' & ').toLowerCase()} aesthetics. Anchored
              by a {app.category.toLowerCase()} use-case, the mark balances {palette.length}
              {' '}colors with deliberate negative space.
            </p>

            <div className="tag-row">
              {app.styles.map((s) => <span key={s} className="tag">{s}</span>)}
              {app.colors.map((c) => <span key={c} className="tag tag-mono">{c}</span>)}
            </div>

            <div className="screenshots">
              <div className="meta-h">Screenshots</div>
              <div className="screens-row">
                {[0, 1, 2].map((i) =>
                <div key={i} className="screen-frame" style={{ background: `linear-gradient(180deg, ${c1}10, ${c2}20)` }}>
                    <div className="screen-status">
                      <span>9:41</span>
                      <span className="screen-dots">●●●</span>
                    </div>
                    <div className="screen-icon">
                      <IconArt app={app} size={64} radius={radius} />
                    </div>
                    <div className="screen-name" style={{ color: c2 }}>{app.app_name}</div>
                    <div className="screen-bars">
                      <span style={{ width: '70%', background: c2 }} />
                      <span style={{ width: '50%', background: c2, opacity: 0.6 }} />
                      <span style={{ width: '85%', background: c2, opacity: 0.4 }} />
                    </div>
                  </div>
                )}
              </div>
            </div>

            <div className="similar">
              <div className="meta-h">Similar icons</div>
              <div className="similar-grid">
                {similar.map((s) =>
                <button key={s.id} className="sim-card" onClick={() => onOpen(s)}>
                    <IconArt app={s} size={72} radius={radius} />
                    <div className="sim-name">{s.app_name}</div>
                  </button>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>);

}

// ─── Cmd-K palette ──────────────────────────────────────────────────
function CmdK({ open, onClose, apps, collections, onOpenApp }) {
  const [q, setQ] = useState('');
  const [sel, setSel] = useState(0);
  const inputRef = useRef(null);

  useEffect(() => {
    if (open) {setTimeout(() => inputRef.current?.focus(), 30);setQ('');setSel(0);}
  }, [open]);

  const results = useMemo(() => {
    const ql = q.trim().toLowerCase();
    if (!ql) {
      return {
        apps: apps.slice(0, 6),
        collections: collections.slice(0, 4),
        suggested: ['Minimal', 'Gradient', 'Monochrome', 'Glyph']
      };
    }
    const matches = (a) =>
    a.app_name.toLowerCase().includes(ql) ||
    a.developer.toLowerCase().includes(ql) ||
    a.category.toLowerCase().includes(ql) ||
    a.colors.some((c) => c.toLowerCase().includes(ql)) ||
    a.styles.some((s) => s.toLowerCase().includes(ql));
    return {
      apps: apps.filter(matches).slice(0, 8),
      collections: collections.filter((c) => c.title.toLowerCase().includes(ql)).slice(0, 3),
      suggested: []
    };
  }, [q, apps, collections]);

  const flat = [...results.apps, ...results.collections];

  useEffect(() => {
    const onKey = (e) => {
      if (!open) return;
      if (e.key === 'Escape') onClose();else
      if (e.key === 'ArrowDown') {e.preventDefault();setSel((s) => Math.min(s + 1, flat.length - 1));} else
      if (e.key === 'ArrowUp') {e.preventDefault();setSel((s) => Math.max(s - 1, 0));} else
      if (e.key === 'Enter') {
        const picked = flat[sel];
        if (picked && picked.app_name) {onOpenApp(picked);onClose();}
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, flat, sel, onClose, onOpenApp]);

  if (!open) return null;
  return (
    <div className="cmdk-overlay" onClick={onClose}>
      <div className="cmdk" onClick={(e) => e.stopPropagation()}>
        <div className="cmdk-input-wrap">
          <svg viewBox="0 0 24 24" width="16" height="16"><circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" strokeWidth="1.6" /><path d="M16 16L21 21" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" /></svg>
          <input ref={inputRef} className="cmdk-input"
          placeholder="Search apps, developers, colors, styles…"
          value={q} onChange={(e) => {setQ(e.target.value);setSel(0);}} />
          <kbd>esc</kbd>
        </div>
        <div className="cmdk-body">
          {results.suggested?.length > 0 &&
          <div className="cmdk-section">
              <div className="cmdk-h">Try</div>
              <div className="cmdk-suggest">
                {results.suggested.map((s) =>
              <button key={s} className="cmdk-chip" onClick={() => setQ(s)}>{s}</button>
              )}
              </div>
            </div>
          }
          {results.apps.length > 0 &&
          <div className="cmdk-section">
              <div className="cmdk-h">Apps</div>
              {results.apps.map((a, i) =>
            <button key={a.id}
            className={`cmdk-row ${sel === i ? 'on' : ''}`}
            onMouseEnter={() => setSel(i)}
            onClick={() => {onOpenApp(a);onClose();}}>
                  <div className="cmdk-icon"><IconArt app={a} size={28} radius="continuous" /></div>
                  <div className="cmdk-text">
                    <div className="cmdk-name">{a.app_name}</div>
                    <div className="cmdk-sub">{a.developer} · {a.category}</div>
                  </div>
                  <span className="cmdk-kbd">↵</span>
                </button>
            )}
            </div>
          }
          {results.collections.length > 0 &&
          <div className="cmdk-section">
              <div className="cmdk-h">Collections</div>
              {results.collections.map((c, i) =>
            <button key={c.id} className="cmdk-row"
            onClick={() => {setQ(c.title);}}>
                  <div className="cmdk-icon cmdk-coll" style={{ background: ICON_PALETTES[c.palette]?.[1] }}>
                    <span style={{ color: ICON_PALETTES[c.palette]?.[2] }}>◇</span>
                  </div>
                  <div className="cmdk-text">
                    <div className="cmdk-name">{c.title}</div>
                    <div className="cmdk-sub">{c.appIds.length} icons · {c.description}</div>
                  </div>
                </button>
            )}
            </div>
          }
          {q && flat.length === 0 &&
          <div className="cmdk-empty">No matches for "{q}"</div>
          }
        </div>
        <div className="cmdk-foot">
          <span><kbd>↑</kbd><kbd>↓</kbd> navigate</span>
          <span><kbd>↵</kbd> open</span>
          <span><kbd>esc</kbd> close</span>
        </div>
      </div>
    </div>);

}

// ─── Collections page ────────────────────────────────────────────────
function CollectionsPage({ collections, subId, apps, favorites, onOpen, onToggleFavorite, radius }) {
  const [openColl, setOpenColl] = useState(subId ? collections.find(c => c.id === subId) : null);

  useEffect(() => {
    if (subId) setOpenColl(collections.find(c => c.id === subId) || null);
    else setOpenColl(null);
  }, [subId, collections]);

  if (openColl) {
    const collApps = (openColl.appIds || openColl.app_ids || []).map(id => apps.find(a => a.id === id)).filter(Boolean);
    return (
      <div className="container" style={{ paddingTop: 48, paddingBottom: 80 }}>
        <div style={{ marginBottom: 32 }}>
          <a href="#collections" className="link-btn" style={{ marginLeft: -6 }}>← All collections</a>
        </div>
        <h1 className="row-title" style={{ fontSize: 36, marginBottom: 6 }}>{openColl.title}</h1>
        <p className="row-sub" style={{ marginBottom: 32 }}>{openColl.description} · {collApps.length} icons</p>
        <div className="icon-grid" style={{ '--icon-size': '116px' }}>
          {collApps.map(a =>
            <IconCard key={a.id} app={a} size={116} radius={radius} onOpen={onOpen}
              isFavorited={favorites?.has(a.id)} onToggleFavorite={onToggleFavorite} />
          )}
        </div>
      </div>
    );
  }

  return (
    <div className="container" style={{ paddingTop: 64, paddingBottom: 80 }}>
      <div style={{ marginBottom: 40 }}>
        <h1 style={{ fontSize: 'clamp(32px,5vw,56px)', fontWeight: 600, letterSpacing: '-0.03em', margin: '0 0 10px' }}>Collections</h1>
        <p style={{ color: 'var(--fg-mute)', fontSize: 16, margin: 0 }}>Curated sets of icons by theme, style, and aesthetic.</p>
      </div>
      <div className="collections-page-grid">
        {collections.map(c => {
          const collApps = (c.appIds || c.app_ids || []).slice(0, 4).map(id => apps.find(a => a.id === id)).filter(Boolean);
          const [bg1, bg2] = ICON_PALETTES[c.palette] || ['#f5f1ea', '#e8e2d6'];
          return (
            <a key={c.id} href={`#collections/${c.id}`} className="coll-page-card"
               style={{ background: `linear-gradient(135deg, ${bg1}, ${bg2})` }}>
              <div className="coll-page-icons">
                {collApps.map(a => <div key={a.id} className="coll-page-icon"><IconArt app={a} size={56} radius="continuous" /></div>)}
              </div>
              <div className="coll-page-meta">
                <div className="coll-title" style={{ color: ICON_PALETTES[c.palette]?.[2] || '#fff', fontSize: 20 }}>{c.title}</div>
                <div className="coll-count">{(c.appIds || c.app_ids || []).length} icons · {c.description}</div>
              </div>
            </a>
          );
        })}
      </div>
    </div>
  );
}

// ─── Styles page ─────────────────────────────────────────────────────
const STYLE_DEFS = [
  { key: 'Minimal',      label: 'Minimal',       desc: 'Quiet, restraint, whitespace.',    palette: 'paper'    },
  { key: 'Gradient',     label: 'Gradient',       desc: 'Color transitions and depth.',     palette: 'rose'     },
  { key: 'Monochrome',   label: 'Monochrome',     desc: 'One color, done right.',           palette: 'ink'      },
  { key: 'Glyph',        label: 'Glyph',          desc: 'A single mark says everything.',   palette: 'amber'    },
  { key: 'Illustrative', label: 'Illustrative',   desc: 'Figurative and expressive.',       palette: 'moss'     },
  { key: 'Geometric',    label: 'Geometric',      desc: 'Shapes with intention.',           palette: 'ocean'    },
  { key: 'Skeuomorphic', label: 'Skeuomorphic',   desc: 'Texture, depth, realism.',         palette: 'cream'    },
];

function StylesPage({ apps, onOpen, radius, onStyleClick }) {
  return (
    <div className="container" style={{ paddingTop: 64, paddingBottom: 80 }}>
      <div style={{ marginBottom: 40 }}>
        <h1 style={{ fontSize: 'clamp(32px,5vw,56px)', fontWeight: 600, letterSpacing: '-0.03em', margin: '0 0 10px' }}>Browse by Style</h1>
        <p style={{ color: 'var(--fg-mute)', fontSize: 16, margin: 0 }}>Every aesthetic that defines great iOS icon design.</p>
      </div>
      <div className="styles-grid">
        {STYLE_DEFS.map(s => {
          const sample = apps.filter(a => a.styles?.includes(s.key) || a.style === s.key.toLowerCase().replace(' ', '-')).slice(0, 6);
          const count = apps.filter(a => a.styles?.includes(s.key) || a.style === s.key.toLowerCase().replace(' ', '-')).length;
          const [bg1, bg2, fg] = ICON_PALETTES[s.palette] || ['#f5f1ea', '#e8e2d6', '#3a2e16'];
          return (
            <button key={s.key} className="style-card" onClick={() => onStyleClick(s.key)}
                    style={{ background: `linear-gradient(135deg, ${bg1}, ${bg2})` }}>
              <div className="style-card-icons">
                {sample.map(a => <div key={a.id} className="style-card-icon"><IconArt app={a} size={48} radius="continuous" /></div>)}
              </div>
              <div className="style-card-meta">
                <div className="style-card-name" style={{ color: fg }}>{s.label}</div>
                <div className="style-card-desc" style={{ color: fg, opacity: 0.7 }}>{count > 0 ? `${count} icons · ` : ''}{s.desc}</div>
              </div>
            </button>
          );
        })}
      </div>
    </div>
  );
}

// ─── Submit page ──────────────────────────────────────────────────────
function SubmitPage({ user, onAuthClick }) {
  const [url, setUrl] = useState('');
  const [preview, setPreview] = useState(null);
  const [notes, setNotes] = useState('');
  const [loading, setLoading] = useState(false);
  const [fetching, setFetching] = useState(false);
  const [done, setDone] = useState(false);
  const [error, setError] = useState('');

  const lookupApp = async () => {
    if (!url.trim()) return;
    setFetching(true); setError(''); setPreview(null);
    // Extract app ID from App Store URL
    const match = url.match(/id(\d+)/);
    if (!match) { setError('Paste a valid App Store URL (e.g. apps.apple.com/app/…/id123456)'); setFetching(false); return; }
    try {
      const res = await fetch(`https://itunes.apple.com/lookup?id=${match[1]}&country=us`);
      const data = await res.json();
      const app = data.results?.[0];
      if (!app) { setError('App not found.'); setFetching(false); return; }
      setPreview({
        name: app.trackName,
        developer: app.artistName,
        category: app.primaryGenreName,
        icon: (app.artworkUrl512 || app.artworkUrl100 || '').replace('100x100bb', '512x512bb'),
        price: app.price,
        rating: app.averageUserRating,
        storeUrl: app.trackViewUrl,
        trackId: app.trackId,
      });
    } catch (e) { setError('Could not reach iTunes API. Try again.'); }
    setFetching(false);
  };

  const submit = async e => {
    e.preventDefault();
    if (!user) { onAuthClick(); return; }
    if (!preview) { setError('Look up the app first.'); return; }
    setLoading(true); setError('');
    const { error } = await supabase.from('submissions').insert({
      store_url: preview.storeUrl,
      itunes_id: String(preview.trackId),
      app_name: preview.name,
      developer: preview.developer,
      category: preview.category,
      icon_url: preview.icon,
      notes,
      user_id: user.id,
    });
    setLoading(false);
    if (error) setError(error.message);
    else setDone(true);
  };

  if (done) return (
    <div className="container" style={{ paddingTop: 120, paddingBottom: 120, textAlign: 'center' }}>
      <div style={{ fontSize: 48, marginBottom: 16 }}>🎉</div>
      <h2 style={{ fontSize: 28, fontWeight: 600, margin: '0 0 12px' }}>Thanks for the submission!</h2>
      <p style={{ color: 'var(--fg-mute)', marginBottom: 24 }}>We'll review it and add it to the library if it meets our quality bar.</p>
      <a href="#discover" className="primary-btn" style={{ display: 'inline-flex' }}>Browse icons</a>
    </div>
  );

  return (
    <div className="container" style={{ paddingTop: 64, paddingBottom: 80 }}>
      <div style={{ maxWidth: 560, margin: '0 auto' }}>
        <h1 style={{ fontSize: 'clamp(28px,4vw,48px)', fontWeight: 600, letterSpacing: '-0.03em', margin: '0 0 10px' }}>Submit an icon</h1>
        <p style={{ color: 'var(--fg-mute)', fontSize: 15, margin: '0 0 40px' }}>
          Found an iOS app with an exceptional icon? Submit it for curation.
        </p>

        <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
          <div className="submit-field">
            <label className="submit-label">App Store URL</label>
            <div style={{ display: 'flex', gap: 8 }}>
              <input type="url" placeholder="https://apps.apple.com/app/…" value={url}
                onChange={e => { setUrl(e.target.value); setPreview(null); }}
                className="submit-input" style={{ flex: 1 }} />
              <button type="button" className="ghost-btn" onClick={lookupApp} disabled={fetching}>
                {fetching ? '…' : 'Look up'}
              </button>
            </div>
          </div>

          {error && <p style={{ color: 'var(--accent)', fontSize: 13, margin: 0 }}>{error}</p>}

          {preview && (
            <div className="submit-preview">
              <img src={preview.icon} width={64} height={64} alt={preview.name}
                style={{ borderRadius: 16, flexShrink: 0 }} />
              <div>
                <div style={{ fontWeight: 600, fontSize: 16 }}>{preview.name}</div>
                <div style={{ color: 'var(--fg-mute)', fontSize: 13, marginTop: 2 }}>{preview.developer} · {preview.category}</div>
                <div style={{ color: 'var(--fg-soft)', fontSize: 12, marginTop: 2 }}>
                  {preview.price === 0 ? 'Free' : `$${preview.price}`}
                  {preview.rating ? ` · ${preview.rating.toFixed(1)} ★` : ''}
                </div>
              </div>
            </div>
          )}

          <div className="submit-field">
            <label className="submit-label">Why is this icon notable? <span style={{ color: 'var(--fg-soft)', fontWeight: 400 }}>(optional)</span></label>
            <textarea placeholder="What makes the design stand out…" value={notes}
              onChange={e => setNotes(e.target.value)} rows={3}
              className="submit-input" style={{ resize: 'vertical', lineHeight: 1.5 }} />
          </div>

          <div>
            {user ? (
              <button type="submit" className="primary-btn" disabled={loading || !preview}>
                {loading ? 'Submitting…' : 'Submit for review'}
              </button>
            ) : (
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
                <button type="button" className="primary-btn" onClick={onAuthClick}>Sign in to submit</button>
                <span style={{ color: 'var(--fg-mute)', fontSize: 13 }}>We use magic links — no password needed.</span>
              </div>
            )}
          </div>
        </form>
      </div>
    </div>
  );
}

Object.assign(window, {
  IconCard, FilterSidebar, TopBar, Hero,
  CollectionsRow, TrendingRow, DetailPanel, CmdK, AuthModal,
  CollectionsPage, StylesPage, SubmitPage,
});