// screens.jsx — All screens for the mini-stores prototype

// ─── Onboarding ───────────────────────────────────────────────────────────
function OnboardingScreen({ onDone, dark, user, onShowAuth }) {
  const [step, setStep] = React.useState(0);
  const [picked, setPicked] = React.useState(new Set());
  const togglePick = (id) => {
    const next = new Set(picked);
    next.has(id) ? next.delete(id) : next.add(id);
    setPicked(next);
  };

  const slides = [
    {
      title: 'Discover everything in seconds',
      sub: 'Curated MiniStores with the aesthetic you\'re already looking for — to inspire you, not sell to you.',
      art: (
        <div style={{ position: 'relative', width: 240, height: 240 }}>
          {[0,1,2].map((i) => (
            <div key={i} style={{
              position: 'absolute', width: 130, height: 170,
              borderRadius: 20,
              left: 55 + (i-1)*48, top: 35 + Math.abs(i-1)*8,
              background: window.COVER_GRADIENTS[i],
              transform: `rotate(${(i-1)*8}deg)`,
              boxShadow: '0 14px 30px rgba(40,55,32,0.18)',
              overflow: 'hidden',
            }}>
              <div style={{
                marginTop: '22%', height: '50%', marginLeft: '10%', marginRight: '10%',
                borderRadius: 12,
                background: 'linear-gradient(180deg, rgba(255,255,255,0.45), rgba(255,255,255,0.08))',
              }} />
            </div>
          ))}
        </div>
      ),
    },
    {
      title: 'What\'s your vibe?',
      sub: 'Pick at least 3 vibes. We\'ll tailor your feed.',
      isPick: 'mood',
    },
    {
      title: 'And… what do you like to explore?',
      sub: 'Favorite categories. You can change them later.',
      isPick: 'cat',
    },
  ];
  const cur = slides[step];
  const canNext = step === 0 ? true : picked.size >= 3;

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column',
      background: 'var(--bg)', color: 'var(--ink)' }}>
      <div style={{ display: 'flex', gap: 6, padding: '60px 22px 0' }}>
        {slides.map((_, i) => (
          <div key={i} style={{
            flex: 1, height: 3, borderRadius: 2,
            background: i <= step ? 'var(--accent)' : 'var(--surface-2)',
            transition: 'background .25s',
          }} />
        ))}
      </div>
      <div style={{ flex: 1, padding: '32px 22px 0', display: 'flex',
        flexDirection: 'column', alignItems: 'flex-start' }}>
        <div style={{
          fontSize: 30, lineHeight: '34px', fontWeight: 600, letterSpacing: -0.7,
          marginBottom: 10, fontFamily: 'var(--font-display)',
        }}>{cur.title}</div>
        <div style={{ fontSize: 15, color: 'var(--ink-2)', lineHeight: '20px',
          marginBottom: 24, maxWidth: 320 }}>{cur.sub}</div>

        {cur.art && <div style={{ alignSelf: 'center', marginTop: 20 }}>{cur.art}</div>}

        {cur.isPick === 'mood' && (
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {window.MOODS.map((m) => {
              const on = picked.has(m.id);
              return (
                <button key={m.id} onClick={() => togglePick(m.id)} style={{
                  border: 'none', cursor: 'pointer',
                  padding: '12px 16px', borderRadius: 999,
                  background: on ? 'var(--ink)' : 'var(--surface-2)',
                  color: on ? 'var(--bg)' : 'var(--ink)',
                  fontSize: 14, fontWeight: 500,
                  display: 'flex', alignItems: 'center', gap: 6,
                  transition: 'all .15s',
                }}>
                  <span>{m.emoji}</span>{m.label}
                </button>
              );
            })}
          </div>
        )}
        {cur.isPick === 'cat' && (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)',
            gap: 10, width: '100%' }}>
            {window.CATEGORIES.map((c) => {
              const on = picked.has(c.id);
              return (
                <button key={c.id} onClick={() => togglePick(c.id)} style={{
                  border: 'none', cursor: 'pointer',
                  padding: '20px 16px', borderRadius: 18,
                  background: on ? 'var(--accent-2)' : 'var(--surface-2)',
                  color: on ? '#1A2A14' : 'var(--ink)',
                  fontSize: 15, fontWeight: 500, textAlign: 'left',
                  display: 'flex', alignItems: 'center', gap: 12,
                  transition: 'all .15s',
                  outline: on ? '2px solid var(--accent)' : 'none',
                  outlineOffset: -2,
                }}>
                  <span style={{ fontSize: 22 }}>{c.icon}</span>{c.label}
                </button>
              );
            })}
          </div>
        )}
      </div>

      <div style={{ padding: '14px 22px 36px' }}>
        <button
          disabled={!canNext}
          onClick={() => {
            if (step < slides.length - 1) { setStep(step + 1); setPicked(new Set()); }
            else {
              if (!user && onShowAuth) { onShowAuth(); }
              else { onDone(); }
            }
          }}
          style={{
            width: '100%', height: 54, border: 'none',
            borderRadius: 999,
            background: canNext ? 'var(--ink)' : 'var(--surface-2)',
            color: canNext ? 'var(--bg)' : 'var(--ink-2)',
            fontSize: 16, fontWeight: 600, cursor: canNext ? 'pointer' : 'default',
            transition: 'all .15s',
          }}>
          {step < slides.length - 1 ? 'Next' : 'Start exploring'}
        </button>
      </div>
    </div>
  );
}

// ─── Home Feed ────────────────────────────────────────────────────────────
function HomeFeed({ saved, onSave, onOpenStore, onCreateAttempt, feedStyle, shape, density, dark, desktop }) {
  const [q, setQ] = React.useState('');
  const filtered = q
    ? (window.STORES || []).filter((s) =>
        `${s.title} ${s.vibe} ${s.creatorName || ''} ${s.headlineSubtitle || ''} ${(s.products || []).map((p) => p.name).join(' ')}`.toLowerCase()
          .includes(q.toLowerCase()))
    : null;

  const SearchBar = (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      padding: '10px 14px', borderRadius: 14,
      background: 'var(--surface-2)', marginBottom: 14,
    }}>
      {Icon.search('var(--ink-2)', 2)}
      <input value={q} onChange={(e) => setQ(e.target.value)}
        placeholder="Search MiniStores, vibes, products…"
        style={{ flex: 1, border: 'none', outline: 'none',
          background: 'transparent', fontSize: 14, color: 'var(--ink)',
          fontFamily: 'inherit' }} />
      {q && <button onClick={() => setQ('')} style={{ border: 'none', background: 'none', cursor: 'pointer', color: 'var(--ink-2)', fontSize: 18, lineHeight: 1, padding: 0 }}>×</button>}
    </div>
  );

  if (desktop) {
    const cols = window.innerWidth >= 1024 ? 3 : 2;
    const stores = filtered ?? (window.STORES || []);
    return (
      <div>
        {SearchBar}
        {stores.length === 0 ? (
          <div style={{ padding: 40, textAlign: 'center', color: 'var(--ink-2)', fontSize: 14 }}>
            {q ? `No results for "${q}"` : 'Loading MiniStores from deanna.pro…'}
          </div>
        ) : (
          <div style={{ display: 'grid', gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: 14 }}>
            {stores.map(s => (
              <div key={s.id} onClick={() => onOpenStore(s.id)} style={{ cursor: 'pointer', borderRadius: 14, overflow: 'hidden', background: 'var(--surface)', boxShadow: '0 1px 4px rgba(0,0,0,0.07)' }}>
                <div style={{ height: 160, background: s.gradient || 'var(--surface-2)', position: 'relative' }}>
                  {s.cover && <img src={s.cover} alt={s.title} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', mixBlendMode: 'multiply', opacity: 0.9 }} />}
                  <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg,transparent 40%,rgba(20,30,18,0.55) 100%)' }} />
                  <div style={{ position: 'absolute', bottom: 8, left: 10, background: 'rgba(26,36,23,0.6)', color: '#fff', fontSize: 9, fontWeight: 600, padding: '3px 8px', borderRadius: 20 }}>● MINISTORE</div>
                </div>
                <div style={{ padding: '10px 12px 12px' }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)', marginBottom: 3 }}>{s.title}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-2)' }}>{s.author ? `by ${s.author}` : ''}{s.count ? ` · ${s.count} items` : ''}</div>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 8 }}>
                    <button onClick={e => { e.stopPropagation(); onSave(s.id); }} style={{ border: 'none', background: 'none', cursor: 'pointer', fontSize: 12, color: saved.has(s.id) ? 'var(--accent)' : 'var(--ink-2)', padding: 0 }}>
                      {saved.has(s.id) ? '♥' : '♡'} {s.likes || ''}
                    </button>
                    <button onClick={e => { e.stopPropagation(); onSave(s.id); }} style={{ border: 'none', background: 'none', cursor: 'pointer', color: saved.has(s.id) ? 'var(--accent)' : 'var(--ink-2)', padding: 0, fontSize: 14 }}>🔖</button>
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }

  const [activeIdx, setActiveIdx] = React.useState(0);
  const scrollRef = React.useRef(null);

  // observe which card is in view (TikTok feed)
  React.useEffect(() => {
    if (feedStyle !== 'tiktok' || !scrollRef.current) return;
    const handler = () => {
      const sc = scrollRef.current;
      if (!sc) return;
      const idx = Math.round(sc.scrollTop / sc.clientHeight);
      setActiveIdx(idx);
    };
    const sc = scrollRef.current;
    sc.addEventListener('scroll', handler, { passive: true });
    return () => sc?.removeEventListener('scroll', handler);
  }, [feedStyle]);

  const emptyTiktok = !(window.STORES && window.STORES.length) ? (
    <div style={{
      height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 32, textAlign: 'center', background: '#0A0E08', color: 'rgba(255,255,255,0.75)',
      flexDirection: 'column', gap: 10,
    }}>
      <div style={{ fontSize: 17, fontWeight: 600, color: '#fff' }}>Loading MiniStores from deanna.pro…</div>
      <div style={{ fontSize: 13, opacity: 0.8, maxWidth: 280 }}>
        Nothing showing? Run <span style={{ fontFamily: 'monospace' }}>python dev-server.py</span> locally and open that port; set Endpoint to Prod in Tweaks; don't open the HTML file directly.
      </div>
    </div>
  ) : null;

  if (feedStyle === 'tiktok') {
    const tiktokStores = filtered ?? (window.STORES || []);
    if (!tiktokStores.length && !q) {
      return (
        <>
          {emptyTiktok}
          <CreateBar floating onCreateAttempt={onCreateAttempt} />
        </>
      );
    }
    return (
      <>
        {q && (
          <div style={{
            position: 'absolute', top: 50, left: 0, right: 0, zIndex: 60,
            padding: '10px 14px',
            display: 'flex', alignItems: 'center', gap: 8,
            background: 'rgba(10,14,8,0.85)',
            backdropFilter: 'blur(16px)', WebkitBackdropFilter: 'blur(16px)',
          }}>
            {Icon.search('rgba(255,255,255,0.6)', 2)}
            <input value={q} onChange={e => setQ(e.target.value)} autoFocus
              placeholder="Search MiniStores…"
              style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent',
                fontSize: 15, color: '#fff', fontFamily: 'inherit' }} />
            <button onClick={() => setQ('')} style={{ border: 'none', background: 'none', cursor: 'pointer', color: 'rgba(255,255,255,0.6)', fontSize: 22, lineHeight: 1, padding: 0 }}>×</button>
          </div>
        )}
        <div ref={scrollRef} style={{
          height: '100%', overflowY: 'auto',
          scrollSnapType: 'y mandatory',
          WebkitOverflowScrolling: 'touch', background: '#0A0E08',
        }}>
          {tiktokStores.length === 0
            ? <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'rgba(255,255,255,0.7)', fontSize: 15 }}>No results for "{q}"</div>
            : tiktokStores.map((s, i) => (
            <div key={s.id} style={{
              scrollSnapAlign: 'start', scrollSnapStop: 'always',
              height: '100%', minHeight: '100%',
            }}>
              <StoreFeedCard store={s} isActive={i === activeIdx}
                onOpen={() => onOpenStore(s.id)}
                onSave={() => onSave(s.id)}
                saved={saved.has(s.id)}
                shape={shape} density={density} dark={true} />
            </div>
          ))}
        </div>
        <FeedHeaderOverlay dark={dark} onSearchOpen={() => setQ(' ')} />
        <CreateBar floating onCreateAttempt={onCreateAttempt} />
      </>
    );
  }

  if (feedStyle === 'pinterest') {
    const stores = filtered ?? (window.STORES || []);
    return (
      <div style={{ height: '100%', overflowY: 'auto',
        background: 'var(--bg)', padding: '88px 12px 100px' }}>
        <FeedHeader dark={dark} />
        <div style={{ padding: '0 4px 0' }}>{SearchBar}</div>
        <div style={{ padding: '0 4px' }}><CreateBar onCreateAttempt={onCreateAttempt} /></div>
        {stores.length > 0
          ? <PinterestMasonry stores={stores} saved={saved}
            onSave={onSave} onOpen={onOpenStore} shape={shape} />
          : <div style={{ marginTop: 40, fontSize: 14, color: 'var(--ink-2)', textAlign: 'center', padding: 16 }}>
            {q ? `No results for "${q}"` : <>No MiniStores: the <span style={{ fontFamily: 'monospace' }}>/api/explore</span> endpoint must return data.</>}
          </div>}
      </div>
    );
  }

  // hybrid
  const hybridStores = filtered ?? (window.STORES || []);
  if (!hybridStores.length && !q) {
    return (
      <div style={{ height: '100%', overflowY: 'auto',
        background: 'var(--bg)', padding: '88px 16px 100px' }}>
        <FeedHeader dark={dark} />
        {SearchBar}
        <CreateBar onCreateAttempt={onCreateAttempt} />
        <div style={{ marginTop: 36, fontSize: 14, color: 'var(--ink-2)', textAlign: 'center' }}>
          No MiniStores loaded from Deanna.
        </div>
      </div>
    );
  }

  return (
    <div style={{ height: '100%', overflowY: 'auto',
      background: 'var(--bg)', padding: '88px 16px 100px' }}>
      <FeedHeader dark={dark} />
      {SearchBar}
      <CreateBar onCreateAttempt={onCreateAttempt} />
      {!q && <DailyDropStrip onOpen={onOpenStore} />}
      {hybridStores.length === 0
        ? <div style={{ marginTop: 36, fontSize: 14, color: 'var(--ink-2)', textAlign: 'center' }}>No results for "{q}"</div>
        : <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            {hybridStores.map((s) => (
              <StoreHybridCard key={s.id} store={s}
                onOpen={() => onOpenStore(s.id)}
                onSave={() => onSave(s.id)}
                saved={saved.has(s.id)} shape={shape} />
            ))}
          </div>
      }
    </div>
  );
}

function FeedHeader({ dark }) {
  return (
    <div style={{
      position: 'absolute', top: 50, left: 0, right: 0, zIndex: 10,
      padding: '12px 18px',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      background: 'linear-gradient(180deg, var(--bg) 60%, transparent 100%)',
    }}>
      <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: -0.5,
        fontFamily: 'var(--font-display)', color: 'var(--ink)' }}>
        deanna<span style={{ color: 'var(--accent-ink)' }}>.</span>
      </div>
      <div style={{ display: 'flex', gap: 10 }}>
        <div style={{
          width: 38, height: 38, borderRadius: 999,
          background: 'var(--surface-2)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>{Icon.search('var(--ink)', 2)}</div>
      </div>
    </div>
  );
}

function FeedHeaderOverlay({ dark, onSearchOpen }) {
  return (
    <div style={{
      position: 'absolute', top: 50, left: 0, right: 0, zIndex: 50,
      padding: '14px 22px',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      pointerEvents: 'none',
    }}>
      <div style={{ display: 'flex', gap: 22, fontSize: 14, fontWeight: 600,
        color: '#fff', pointerEvents: 'auto' }}>
        <span style={{ opacity: 0.55 }}>Following</span>
        <span style={{ position: 'relative' }}>For you
          <span style={{ position: 'absolute', left: '50%', bottom: -6,
            transform: 'translateX(-50%)', width: 5, height: 5, borderRadius: 999,
            background: '#C9E5B4' }} />
        </span>
        <span style={{ opacity: 0.55 }}>Daily Drop</span>
      </div>
      <button onClick={onSearchOpen} style={{ border: 'none', background: 'rgba(255,255,255,0.15)', width: 36, height: 36, borderRadius: 999, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', pointerEvents: 'auto' }}>{Icon.search('#fff', 2)}</button>
    </div>
  );
}

function DailyDropStrip({ onOpen }) {
  return (
    <div style={{ marginBottom: 18 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6,
        padding: '0 2px 10px' }}>
        {Icon.flame('var(--accent-ink)')}
        <span style={{ fontSize: 13, fontWeight: 600, letterSpacing: -0.1,
          color: 'var(--ink)' }}>Daily Drop</span>
        <span style={{ fontSize: 11, color: 'var(--ink-2)', marginLeft: 'auto' }}>
          Refreshes in 6h 12m</span>
      </div>
      <div style={{ display: 'flex', gap: 10, overflowX: 'auto',
        paddingBottom: 6, marginRight: -16 }}>
        {window.DAILY_DROP.map((id) => {
          const s = window.findStore(id);
          if (!s) return null;
          return (
            <div key={id} onClick={() => onOpen(id)} style={{
              flex: '0 0 130px', height: 168, borderRadius: 18,
              position: 'relative', overflow: 'hidden', cursor: 'pointer',
              background: s.gradient,
            }}>
              {s.cover ? (
                <img src={s.cover} alt="" style={{ position: 'absolute', inset: 0,
                  width: '100%', height: '100%', objectFit: 'cover',
                  mixBlendMode: 'multiply', opacity: 0.94 }} />
              ) : null}
              <div style={{ position: 'absolute', inset: 0,
                background: 'linear-gradient(180deg, transparent 50%, rgba(15,25,12,0.7))' }} />
              <div style={{ position: 'absolute', left: 10, right: 10, bottom: 10,
                color: '#fff', fontSize: 12, fontWeight: 600, letterSpacing: -0.1,
                lineHeight: '15px' }}>{s.title}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function PinterestMasonry({ stores, saved, onSave, onOpen, shape }) {
  // 2-column distribution by index parity for stable layout
  const cols = [[], []];
  stores.forEach((s, i) => cols[i % 2].push(s));
  const heights = [220, 280, 240, 320, 200, 260];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
      {cols.map((col, ci) => (
        <div key={ci}>
          {col.map((s, i) => (
            <StorePinTile key={s.id} store={s}
              onOpen={() => onOpen(s.id)}
              onSave={() => onSave(s.id)}
              saved={saved.has(s.id)} shape={shape}
              h={heights[(i + ci) % heights.length]} />
          ))}
        </div>
      ))}
    </div>
  );
}

// ─── Explore Hero (AI MiniStore generation) ───────────────────────────────
function ExploreHero({ onCreateAttempt, onOpenStore }) {
  const [v, setV] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const [err, setErr] = React.useState(null);

  const submit = async () => {
    if (!v.trim() || busy) return;
    if (onCreateAttempt && !onCreateAttempt()) return;
    setBusy(true); setErr(null);
    try {
      const endpointRoot = window.resolveDeannaApiBase ? window.resolveDeannaApiBase() : (window.__DEANNA_ENDPOINT__ ?? '');
      const r = await fetch(`${endpointRoot}/api/smart-ministore`, {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ query: v.trim(), maxResults: 8, category_id: 26 }),
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok) throw new Error(data?.error || `Error ${r.status}`);
      console.log('[smart-ministore] created', data);
      if (data.bookId) window.dispatchEvent(new CustomEvent('deanna:open-book', { detail: data }));
      setDone(true); setV('');
      setTimeout(() => setDone(false), 2400);
    } catch (e) {
      console.warn('[smart-ministore] failed (CORS or auth) — demo fallback:', e.message);
      setDone(true); setV('');
      setTimeout(() => setDone(false), 2400);
    } finally {
      setBusy(false);
    }
  };

  const chips = ['cottagecore corner', 'minimal gamer setup', 'autumn kitchen', 'Y2K fashion'];

  return (
    <div style={{
      margin: '8px 16px 20px', padding: '20px 18px', borderRadius: 24,
      background: 'linear-gradient(135deg, var(--accent-soft), var(--accent-2))',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
        <div style={{
          width: 32, height: 32, borderRadius: 10,
          background: 'rgba(26,42,20,0.92)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>{Icon.sparkle('#C9DCC0')}</div>
        <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: 0.8,
          textTransform: 'uppercase', color: '#1A2A14', opacity: 0.7 }}>AI · Generate a MiniStore</div>
      </div>
      <div style={{
        fontSize: 22, fontWeight: 700, letterSpacing: -0.5,
        fontFamily: 'var(--font-display)', color: '#1A2A14', lineHeight: '26px', marginBottom: 6,
      }}>Describe what you imagine.</div>
      <div style={{ fontSize: 13, color: '#1A2A14', opacity: 0.65, lineHeight: '18px', marginBottom: 14 }}>
        AI will curate a MiniStore instantly with that style.
      </div>
      <div style={{
        display: 'flex', gap: 8, alignItems: 'center',
        background: 'rgba(255,255,255,0.85)', borderRadius: 16, padding: '10px 12px',
        marginBottom: 10,
      }}>
        <input
          value={v}
          onChange={(e) => setV(e.target.value)}
          onKeyDown={(e) => e.key === 'Enter' && submit()}
          placeholder={done ? '✨ MiniStore created' : (busy ? 'Curating…' : 'e.g. my serene reading nook')}
          style={{
            flex: 1, border: 'none', outline: 'none', background: 'transparent',
            fontSize: 14, color: '#1A2A14', fontFamily: 'inherit', minWidth: 0,
          }}
        />
        <button
          onClick={submit}
          disabled={!v.trim() || busy}
          style={{
            border: 'none', cursor: v.trim() && !busy ? 'pointer' : 'default',
            height: 34, padding: '0 16px', borderRadius: 999,
            background: '#1A2A14', color: '#C9DCC0',
            fontSize: 13, fontWeight: 600,
            opacity: !v.trim() && !busy ? 0.45 : 1,
            transition: 'opacity .15s',
          }}
        >{busy ? '…' : 'Generate'}</button>
      </div>
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
        {chips.map((c) => (
          <button key={c} onClick={() => setV(c)} style={{
            border: 'none', cursor: 'pointer', padding: '5px 10px', borderRadius: 999,
            background: 'rgba(26,42,20,0.10)', color: '#1A2A14',
            fontSize: 11, fontWeight: 500,
          }}>{c}</button>
        ))}
      </div>
    </div>
  );
}

// ─── Search ───────────────────────────────────────────────────────────────
function SearchScreen({ onOpenStore, dark, shape, onCreateAttempt }) {
  const [q, setQ] = React.useState('');
  const [showVisual, setShowVisual] = React.useState(false);
  const filtered = q
    ? (window.STORES || []).filter((s) =>
        `${s.title} ${s.vibe} ${s.creatorName || ''} ${s.headlineSubtitle || ''} ${(s.products || []).map((p) => p.name).join(' ')}`.toLowerCase()
          .includes(q.toLowerCase()))
    : [];

  return (
    <div style={{ height: '100%', overflowY: 'auto',
      background: 'var(--bg)', color: 'var(--ink)' }}>
      <div style={{ padding: '62px 16px 12px' }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 8,
          padding: '12px 14px', borderRadius: 16,
          background: 'var(--surface-2)',
        }}>
          {Icon.search('var(--ink-2)', 2)}
          <input value={q} onChange={(e) => setQ(e.target.value)}
            placeholder="Moto jackets, ceramics, vibes..."
            style={{ flex: 1, border: 'none', outline: 'none',
              background: 'transparent', fontSize: 15, color: 'var(--ink)',
              fontFamily: 'inherit' }} />
          <button onClick={() => setShowVisual(true)} style={{
            border: 'none', background: 'var(--accent-2)',
            width: 32, height: 32, borderRadius: 10, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>{Icon.camera('#1A2A14', 2)}</button>
        </div>
      </div>

      {!q ? (
        <>
          <ExploreHero onCreateAttempt={onCreateAttempt} onOpenStore={onOpenStore} />
          <Section title="Trending">
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, padding: '0 16px' }}>
              {window.TRENDING_SEARCHES.map((s) => (
                <Tag key={s} onClick={() => setQ(s)} shape={shape} size="sm">{s}</Tag>
              ))}
            </div>
          </Section>
          <Section title="Explore by vibe">
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)',
              gap: 10, padding: '0 16px' }}>
              {window.MOODS.slice(0,6).map((m) => (
                <div key={m.id} onClick={() => setQ(m.label)} style={{
                  height: 84, borderRadius: 14, padding: 14, cursor: 'pointer',
                  background: m.color,
                  display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
                }}>
                  <span style={{ fontSize: 22 }}>{m.emoji}</span>
                  <span style={{ fontSize: 14, fontWeight: 600, letterSpacing: -0.2,
                    color: '#1A2A14' }}>{m.label}</span>
                </div>
              ))}
            </div>
          </Section>
          <Section title="Trending MiniStores">
            <div style={{ padding: '0 16px', display: 'grid',
              gridTemplateColumns: 'repeat(2,1fr)', gap: 10 }}>
              {window.STORES.slice(0,4).map((s) => (
                <StorePinTile key={s.id} store={s}
                  onOpen={() => onOpenStore(s.id)}
                  onSave={() => {}} saved={false}
                  shape={shape} h={170} />
              ))}
            </div>
          </Section>
        </>
      ) : (
        <div style={{ padding: '12px 16px 100px' }}>
          <div style={{ fontSize: 13, color: 'var(--ink-2)', marginBottom: 12 }}>
            {filtered.length} MiniStore{filtered.length !== 1 ? 's' : ''} for "{q}"
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 10 }}>
            {filtered.map((s) => (
              <StorePinTile key={s.id} store={s}
                onOpen={() => onOpenStore(s.id)}
                onSave={() => {}} saved={false}
                shape={shape} h={200} />
            ))}
          </div>
        </div>
      )}

      {showVisual && <VisualSearchModal onClose={() => setShowVisual(false)} onPick={(t) => { setQ(t); setShowVisual(false); }} />}
    </div>
  );
}

function VisualSearchModal({ onClose, onPick }) {
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 80,
      background: 'rgba(10,15,8,0.85)',
      backdropFilter: 'blur(20px)', WebkitBackdropFilter: 'blur(20px)',
      display: 'flex', flexDirection: 'column', color: '#fff',
      padding: '60px 22px 32px', boxSizing: 'border-box',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between',
        alignItems: 'center', marginBottom: 20 }}>
        <div style={{ fontSize: 18, fontWeight: 600 }}>Visual search</div>
        <button onClick={onClose} style={{ border: 'none', background: 'rgba(255,255,255,0.12)',
          width: 36, height: 36, borderRadius: 999, cursor: 'pointer' }}>
          {Icon.close('#fff', 2)}
        </button>
      </div>
      <div style={{
        flex: 1, borderRadius: 24, border: '1.5px dashed rgba(255,255,255,0.3)',
        display: 'flex', flexDirection: 'column', alignItems: 'center',
        justifyContent: 'center', gap: 14, padding: 30,
      }}>
        <div style={{ width: 72, height: 72, borderRadius: 999,
          background: 'rgba(255,255,255,0.12)',
          display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          {Icon.camera('#fff', 2)}
        </div>
        <div style={{ fontSize: 17, fontWeight: 500, textAlign: 'center' }}>
          Point your camera at something you like
        </div>
        <div style={{ fontSize: 13, opacity: 0.7, textAlign: 'center', maxWidth: 260 }}>
          We'll find MiniStores with products of a similar aesthetic.
        </div>
      </div>
      <div style={{ marginTop: 20 }}>
        <div style={{ fontSize: 12, opacity: 0.65, marginBottom: 10,
          letterSpacing: 0.5, textTransform: 'uppercase' }}>Or try with</div>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          {['Sage matcha', 'Black leather', 'Light wood'].map((t) => (
            <button key={t} onClick={() => onPick(t)} style={{
              padding: '10px 14px', borderRadius: 999,
              background: 'rgba(255,255,255,0.14)', border: '0.5px solid rgba(255,255,255,0.3)',
              color: '#fff', fontSize: 13, cursor: 'pointer',
            }}>{t}</button>
          ))}
        </div>
      </div>
    </div>
  );
}

function Section({ title, children }) {
  return (
    <div style={{ marginTop: 22, marginBottom: 8 }}>
      <div style={{ padding: '0 16px 10px', fontSize: 13, fontWeight: 600,
        letterSpacing: -0.1, color: 'var(--ink)' }}>{title}</div>
      {children}
    </div>
  );
}

// ─── Mini-Store Detail ────────────────────────────────────────────────────
function StoreDetail({ storeId, onBack, onOpenProduct, onOpenStore, onOpenFull, saved, onSave, shape }) {
  const [, reload] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => {
    const h = () => reload();
    window.addEventListener('deanna:stores-patch', h);
    return () => window.removeEventListener('deanna:stores-patch', h);
  }, []);

  React.useEffect(() => {
    const base = window.findStore(storeId);
    if (!base?.shareSlug || base.productsLoaded) return undefined;
    let cancelled = false;
    window.hydrateStoreProducts?.(base.shareSlug).then((products) => {
      if (!cancelled) window.mergeProductsIntoGlobalStore?.(base.bookId, base.shareSlug, products || []);
    });
    return () => { cancelled = true; };
  }, [storeId]);

  const store = window.findStore(storeId);
  if (!store) return null;
  const prods = store.products || [];
  const isSaved = saved.has(store.id);
  return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)',
      color: 'var(--ink)' }}>
      {/* hero */}
      <div style={{
        position: 'relative', height: 360,
        background: store.gradient,
      }}>
        {store.cover ? (
          <img src={store.cover} alt="" style={{
            position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover',
          }} />
        ) : null}
        <div style={{
          position: 'absolute', inset: 0,
          background: 'linear-gradient(180deg, rgba(15,25,12,0.4) 0%, rgba(15,25,12,0.2) 30%, var(--bg) 100%)',
        }} />
        <div style={{
          position: 'absolute', top: 50, left: 14, right: 14,
          display: 'flex', justifyContent: 'space-between',
        }}>
          <RoundBtn onClick={onBack}>{Icon.back('#fff', 2)}</RoundBtn>
          <div style={{ display: 'flex', gap: 8 }}>
            <RoundBtn>{Icon.share('#fff', 2)}</RoundBtn>
            <RoundBtn>{Icon.more('#fff')}</RoundBtn>
          </div>
        </div>
        <div style={{ position: 'absolute', bottom: 22, left: 22, right: 22, color: '#fff' }}>
          <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: 1.2,
            textTransform: 'uppercase', opacity: 0.85, marginBottom: 6 }}>
            {store.headlineSubtitle || `MiniStore · ${store.items} items`}
          </div>
          <div style={{ fontSize: 28, lineHeight: '32px', fontWeight: 600,
            letterSpacing: -0.6, fontFamily: 'var(--font-display)' }}>{store.title}</div>
          <div style={{ fontSize: 14, opacity: 0.9, marginTop: 6 }}>{store.vibe}</div>
        </div>
      </div>

      <div style={{ padding: '4px 16px 12px', display: 'flex', gap: 10 }}>
        <button onClick={() => onSave(store.id)} style={{
          flex: 1, height: 46, border: 'none',
          borderRadius: 999,
          background: isSaved ? 'var(--ink)' : 'var(--accent-2)',
          color: isSaved ? 'var(--bg)' : '#1A2A14',
          fontSize: 14, fontWeight: 600, cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
        }}>
          {Icon.bookmark(isSaved ? 'var(--bg)' : '#1A2A14', 2, isSaved ? 'var(--bg)' : 'none')}
          {isSaved ? 'Saved' : 'Save'}
        </button>
        <button style={{
          height: 46, padding: '0 18px', border: 'none', borderRadius: 999,
          background: 'var(--surface-2)', color: 'var(--ink)',
          fontSize: 14, fontWeight: 600, cursor: 'pointer',
        }}>{Icon.share('var(--ink)', 2)}</button>
      </div>
      <div style={{ padding: '0 16px 16px' }}>
        <button onClick={() => onOpenFull && onOpenFull(store)} style={{
          width: '100%', height: 46, border: '1.5px solid var(--ink)',
          borderRadius: 999, background: 'transparent', color: 'var(--ink)',
          fontSize: 14, fontWeight: 600, cursor: 'pointer',
        }}>Open full store →</button>
      </div>

      {/* AI curated note */}
      <div style={{
        margin: '6px 16px 16px', padding: '12px 14px', borderRadius: 14,
        background: 'var(--accent-soft)', display: 'flex', gap: 10, alignItems: 'flex-start',
      }}>
        <div style={{ width: 26, height: 26, borderRadius: 8,
          background: 'var(--accent-2)', display: 'flex', alignItems: 'center',
          justifyContent: 'center', flexShrink: 0 }}>
          {Icon.sparkle('#1A2A14')}
        </div>
        <div style={{ fontSize: 12, lineHeight: '17px', color: '#1A2A14' }}>
          <b>Deanna Collection</b> · This MiniStore includes {prods.length} clipping{prods.length === 1 ? '' : 's'}
          {store.creatorName ? ` curated by ${store.creatorName}.` : '.'}
        </div>
      </div>

      {/* product grid */}
      <div style={{ padding: '0 16px', display: 'grid',
        gridTemplateColumns: 'repeat(2,1fr)', gap: 12 }}>
        {prods.length === 0 ? (
          <div style={{ gridColumn: '1 / -1', fontSize: 13, color: 'var(--ink-2)', padding: '8px 0' }}>
            Loading store items…
          </div>
        ) : prods.map((p) => (
          <ProductCard key={p.id} product={p}
            onOpen={() => onOpenProduct(p, store)} shape={shape} />
        ))}
      </div>

      {/* related stores — infinite discovery loop */}
      <div style={{ marginTop: 28, padding: '0 16px' }}>
        <div style={{ fontSize: 16, fontWeight: 600, letterSpacing: -0.2,
          marginBottom: 12, fontFamily: 'var(--font-display)' }}>Keep exploring</div>
        <div style={{ display: 'flex', gap: 10, overflowX: 'auto',
          marginRight: -16, paddingRight: 16, paddingBottom: 100 }}>
          {store.related.map((id) => {
            const s = window.findStore(id);
            if (!s) return null;
            return (
              <div key={id} onClick={() => onOpenStore(id)} style={{
                flex: '0 0 200px', height: 240, borderRadius: 18,
                position: 'relative', overflow: 'hidden', cursor: 'pointer',
                background: s.gradient,
              }}>
                {s.cover ? (
                  <img src={s.cover} alt="" style={{ position: 'absolute', inset: 0,
                    width: '100%', height: '100%', objectFit: 'cover',
                    mixBlendMode: 'multiply', opacity: 0.94 }} />
                ) : null}
                <div style={{ position: 'absolute', inset: 0,
                  background: 'linear-gradient(180deg, transparent 45%, rgba(15,25,12,0.78))' }} />
                <div style={{ position: 'absolute', left: 12, right: 12, bottom: 12,
                  color: '#fff' }}>
                  <div style={{ fontSize: 14, fontWeight: 600, letterSpacing: -0.2,
                    fontFamily: 'var(--font-display)' }}>{s.title}</div>
                  <div style={{ fontSize: 11, opacity: 0.85, marginTop: 2 }}>
                    {s.items} pzs</div>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function RoundBtn({ children, onClick }) {
  return (
    <button onClick={onClick} style={{
      width: 38, height: 38, borderRadius: 999, border: 'none',
      background: 'rgba(255,255,255,0.18)',
      backdropFilter: 'blur(14px)', WebkitBackdropFilter: 'blur(14px)',
      cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>{children}</button>
  );
}

// ─── Product Detail ───────────────────────────────────────────────────────
function ProductDetail({ product, store, onBack, shape }) {
  return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)',
      color: 'var(--ink)' }}>
      <div style={{ position: 'relative', width: '100%', aspectRatio: '1/1.05',
        background: 'var(--surface-2)' }}>
        {product.img ? (
          <img src={product.img} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
        ) : (
          <div style={{
            width: '100%', height: '100%', display: 'flex', alignItems: 'center',
            justifyContent: 'center', fontSize: 48, color: 'var(--ink-2)',
          }}>{product.clipType === 'video' ? '▶' : '◇'}</div>
        )}
        <div style={{ position: 'absolute', top: 50, left: 14, right: 14,
          display: 'flex', justifyContent: 'space-between' }}>
          <RoundBtn onClick={onBack}>{Icon.back('#1A2A14', 2)}</RoundBtn>
          <div style={{ display: 'flex', gap: 8 }}>
            <RoundBtn>{Icon.bookmark('#1A2A14', 2)}</RoundBtn>
            <RoundBtn>{Icon.share('#1A2A14', 2)}</RoundBtn>
          </div>
        </div>
      </div>
      <div style={{ padding: '20px 22px 100px' }}>
        <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: 0.6,
          textTransform: 'uppercase', color: 'var(--ink-2)' }}>{product.brand}</div>
        <div style={{ fontSize: 22, fontWeight: 600, letterSpacing: -0.4,
          marginTop: 6, fontFamily: 'var(--font-display)' }}>{product.name}</div>
        <div style={{ fontSize: 22, fontWeight: 600, marginTop: 8 }}>{product.price}</div>
        <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 4 }}>
          Seen in: <b style={{ color: 'var(--ink)' }}>{store?.title}</b>
        </div>
        <div style={{ marginTop: 18, fontSize: 14, lineHeight: '21px',
          color: 'var(--ink-2)' }}>
          Item selected for its craftsmanship and timelessness. Third-party brand;
          when you buy we earn a small commission at no extra cost to you.
        </div>
        <div style={{ display: 'flex', gap: 10, marginTop: 24 }}>
          <button
            type="button"
            onClick={() => {
              const u = product.clipUrl || product.rawClip?.url;
              if (u) window.open(u, '_blank', 'noopener,noreferrer');
            }}
            style={{
              flex: 1, height: 54, border: 'none', borderRadius: 999,
              background: 'var(--ink)', color: 'var(--bg)',
              fontSize: 15, fontWeight: 600, cursor: product.clipUrl || product.rawClip?.url ? 'pointer' : 'default',
              opacity: product.clipUrl || product.rawClip?.url ? 1 : 0.5,
            }}
          >
            {product.clipUrl || product.rawClip?.url ? 'Open content →' : 'No direct link'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Saved ────────────────────────────────────────────────────────────────
function SavedScreen({ boards, onOpenStore, shape, user, onUpgrade }) {
  const [activeBoard, setActiveBoard] = React.useState('all');

  const allStoreIds = boards ? [...new Set(boards.flatMap(b => b.storeIds))] : [];
  const currentIds = activeBoard === 'all'
    ? allStoreIds
    : (boards.find(b => b.id === activeBoard)?.storeIds || []);
  const stores = currentIds.map(id => window.findStore && window.findStore(id)).filter(Boolean);

  const canCreateBoard = user?.plan === 'standard' || user?.plan === 'premium';

  return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)',
      color: 'var(--ink)', padding: '60px 16px 100px' }}>
      <div style={{ fontSize: 28, fontWeight: 700, letterSpacing: -0.7,
        marginBottom: 6, fontFamily: 'var(--font-display)' }}>Saved</div>
      <div style={{ fontSize: 13, color: 'var(--ink-2)', marginBottom: 16 }}>
        {allStoreIds.length} MiniStore{allStoreIds.length !== 1 ? 's' : ''} in {boards ? boards.length : 0} collection{boards?.length !== 1 ? 's' : ''}
      </div>

      {/* Tab strip */}
      <div style={{ display: 'flex', gap: 8, marginBottom: 18, overflowX: 'auto',
        paddingBottom: 4, marginRight: -16, paddingRight: 16 }}>
        <Tag active={activeBoard === 'all'} onClick={() => setActiveBoard('all')} shape={shape} size="sm">
          All
        </Tag>
        {(boards || []).map(b => (
          <Tag key={b.id} active={activeBoard === b.id}
            onClick={() => setActiveBoard(b.id)} shape={shape} size="sm">
            {b.name}
          </Tag>
        ))}
        <button onClick={() => {
          if (!canCreateBoard) { onUpgrade(); return; }
          const name = prompt('Name of the new collection:');
          if (name?.trim()) {
            window.dispatchEvent(new CustomEvent('deanna:new-board', { detail: { name: name.trim() } }));
          }
        }} style={{ border: '1.5px dashed var(--surface-2)', background: 'transparent',
          color: 'var(--ink-2)', borderRadius: 999, padding: '5px 12px',
          fontSize: 12, cursor: 'pointer', whiteSpace: 'nowrap', flexShrink: 0 }}>
          {canCreateBoard ? '+ New' : '🔒 New'}
        </button>
      </div>

      {stores.length === 0 ? (
        <EmptyState />
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 10 }}>
          {stores.map((s) => (
            <StorePinTile key={s.id} store={s}
              onOpen={() => onOpenStore(s.id)}
              onSave={() => {}} saved={true}
              shape={shape} h={210} />
          ))}
        </div>
      )}
    </div>
  );
}

function EmptyState() {
  return (
    <div style={{ padding: '60px 20px', textAlign: 'center' }}>
      <div style={{ width: 80, height: 80, borderRadius: 24,
        background: 'var(--accent-soft)', margin: '0 auto 18px',
        display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        {Icon.bookmark('var(--accent-ink)', 2)}
      </div>
      <div style={{ fontSize: 17, fontWeight: 600, marginBottom: 6,
        fontFamily: 'var(--font-display)' }}>Nothing saved yet</div>
      <div style={{ fontSize: 13, color: 'var(--ink-2)' }}>
        Tap 🔖 on any MiniStore to build your mood board.
      </div>
    </div>
  );
}

// ─── Profile ──────────────────────────────────────────────────────────────
const MARKETING_TIPS = [
  'Use .99 prices — $24.99 converts 20% better than $25.',
  'Post between 7–9pm to maximize feed engagement.',
  'Odd-number titles: "7 essential pieces" gets more clicks than "10 pieces".',
  'Sage green + cream background = +18% time on page per Deanna data.',
];

function ProfileScreen({ user, onSignOut, onOpenPricing, onOpenStore, shape, boards, onToggleDark, todayCount }) {
  const plan = user?.plan || 'free';
  const planLabel = { free: 'FREE', standard: 'STANDARD', premium: 'PREMIUM ✦' }[plan];
  const planBadgeBg = { free: 'var(--surface-2)', standard: 'linear-gradient(90deg,#C9DCC0,#8FA882)', premium: '#1F2A1A' }[plan];
  const planBadgeColor = { free: 'var(--ink-2)', standard: '#1A2A14', premium: '#C9DCC0' }[plan];

  const dailyLimit = { free: 5, standard: 30, premium: 100 }[plan];

  const boardCount = boards ? boards.length : 0;
  const savedCount = boards ? boards.reduce((acc, b) => acc + b.storeIds.length, 0) : 0;

  return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)',
      color: 'var(--ink)', padding: '58px 16px 100px' }}>

      {/* Header row */}
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 16 }}>
        {/* Avatar + name */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <div style={{ width: 64, height: 64, borderRadius: 999,
            background: 'linear-gradient(135deg,#C9DCC0,#8FA882)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontSize: 26, fontWeight: 700, color: '#1A2A14',
            fontFamily: 'var(--font-display)', flexShrink: 0 }}>
            {(user?.name || 'D')[0].toUpperCase()}
          </div>
          <div>
            <div style={{ fontSize: 18, fontWeight: 600,
              letterSpacing: -0.3, fontFamily: 'var(--font-display)' }}>
              {user?.name || 'Deanna'}
            </div>
            <div style={{ fontSize: 12, color: 'var(--ink-2)' }}>
              @{(user?.name || 'deanna').toLowerCase()} · Madrid
            </div>
          </div>
        </div>

        {/* Top-right: moon + plan badge */}
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 8 }}>
          <button onClick={onToggleDark} style={{
            width: 34, height: 34, border: 'none', borderRadius: 999,
            background: user?.darkMode ? '#C9DCC0' : '#1F2A1A',
            cursor: 'pointer', fontSize: 16, lineHeight: 1,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>🌙</button>
          <div style={{
            background: planBadgeBg, borderRadius: 999,
            padding: '4px 10px', fontSize: 10, fontWeight: 700,
            color: planBadgeColor, letterSpacing: 0.5, whiteSpace: 'nowrap',
          }}>{planLabel}</div>
        </div>
      </div>

      {/* Stats */}
      <div style={{ display: 'flex', gap: 24, marginBottom: 16, padding: '0 4px' }}>
        <Stat n={savedCount} l="Saved" />
        <Stat n={boardCount} l="Mood boards" />
        <Stat n="0" l="Followers" />
      </div>

      {/* Action buttons */}
      <div style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
        <button style={{ flex: 1, height: 40, border: 'none', borderRadius: 999,
          background: 'var(--surface-2)', color: 'var(--ink)',
          fontSize: 13, fontWeight: 600, cursor: 'pointer' }}>Edit profile</button>
        <button style={{ flex: 1, height: 40, border: 'none', borderRadius: 999,
          background: 'var(--surface-2)', color: 'var(--ink)',
          fontSize: 13, fontWeight: 600, cursor: 'pointer' }}>Share</button>
      </div>

      {/* Plan row */}
      <div onClick={onOpenPricing} style={{
        background: 'var(--surface)', borderRadius: 16, padding: '14px 16px',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        cursor: 'pointer', marginBottom: plan === 'premium' ? 10 : 18,
        border: '1px solid var(--surface-2)',
      }}>
        <div>
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)' }}>My plan</div>
          <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 2 }}>{planLabel} · {plan === 'free' ? '$0' : plan === 'standard' ? '$9.99/mo' : '$24.99/mo'}</div>
        </div>
        <div style={{ fontSize: 13, color: 'var(--ink-2)' }}>
          {plan === 'free' ? 'Upgrade →' : plan === 'standard' ? 'See Premium →' : '✓ Active'}
        </div>
      </div>

      {/* Premium: usage progress bar */}
      {plan === 'premium' && (
        <div style={{ background: 'var(--surface)', borderRadius: 14, padding: '12px 16px',
          marginBottom: 18, border: '1px solid var(--surface-2)' }}>
          <div style={{ fontSize: 12, color: 'var(--ink-2)', marginBottom: 6 }}>
            MiniStores today: {todayCount || 0} / {dailyLimit}
          </div>
          <div style={{ background: 'var(--surface-2)', borderRadius: 999, height: 6 }}>
            <div style={{
              background: 'linear-gradient(90deg,var(--accent),var(--accent-ink))',
              borderRadius: 999, height: 6,
              width: `${Math.min(100, ((todayCount || 0) / dailyLimit) * 100)}%`,
              transition: 'width .4s',
            }} />
          </div>
        </div>
      )}

      {/* Premium: marketing tips */}
      {plan === 'premium' && (
        <div style={{ background: 'linear-gradient(135deg,#1F2A1A,#2D3E26)',
          borderRadius: 18, padding: '16px', marginBottom: 18 }}>
          <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: .8,
            textTransform: 'uppercase', color: '#8FA882', marginBottom: 10 }}>
            ✦ Conversion strategies
          </div>
          {MARKETING_TIPS.map((tip, i) => (
            <div key={i} style={{ fontSize: 12, color: '#C9DCC0', lineHeight: '17px',
              marginBottom: 8, paddingLeft: 10, borderLeft: '2px solid #3D5236' }}>
              {tip}
            </div>
          ))}
        </div>
      )}

      {/* Created ministores */}
      <div style={{ marginBottom: 18 }}>
        <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 12 }}>
          Your created MiniStores
        </div>
        {(window.STORES && window.STORES.length) ? (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 10 }}>
            {(window.STORES || []).slice(0, 4).map((s) => (
              <StorePinTile key={s.id} store={s}
                onOpen={() => onOpenStore(s.id)}
                onSave={() => {}} saved={false}
                shape={shape} h={180} />
            ))}
          </div>
        ) : (
          <div style={{ padding: '24px', textAlign: 'center',
            background: 'var(--surface)', borderRadius: 16, border: '1px solid var(--surface-2)' }}>
            <div style={{ fontSize: 13, color: 'var(--ink-2)' }}>
              You haven't created any MiniStores yet.
            </div>
          </div>
        )}
      </div>

      {/* Mood boards */}
      {boards && boards.length > 0 && (
        <div style={{ marginBottom: 18 }}>
          <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 12 }}>Mood boards</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {boards.map((b) => (
              <div key={b.id} style={{ background: 'var(--surface)', borderRadius: 14,
                padding: '12px 16px', display: 'flex', justifyContent: 'space-between',
                border: '1px solid var(--surface-2)' }}>
                <div style={{ fontSize: 14, fontWeight: 500 }}>{b.name}</div>
                <div style={{ fontSize: 12, color: 'var(--ink-2)' }}>{b.storeIds.length} store{b.storeIds.length !== 1 ? 's' : ''}</div>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Sign out */}
      <button onClick={onSignOut} style={{ width: '100%', height: 44, border: 'none',
        background: 'transparent', color: 'var(--ink-2)', fontSize: 14, cursor: 'pointer' }}>
        Sign out
      </button>
    </div>
  );
}

function Stat({ n, l }) {
  return (
    <div>
      <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: -0.4,
        fontFamily: 'var(--font-display)' }}>{n}</div>
      <div style={{ fontSize: 11, color: 'var(--ink-2)',
        textTransform: 'uppercase', letterSpacing: 0.4, marginTop: 2 }}>{l}</div>
    </div>
  );
}

function CreateBar({ floating, onCreateAttempt }) {
  const [v, setV] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const submit = async () => {
    if (!v.trim() || busy) return;
    if (onCreateAttempt && !onCreateAttempt()) return;
    setBusy(true); setErr(null);
    try {
      const endpointRoot = window.resolveDeannaApiBase ? window.resolveDeannaApiBase() : (window.__DEANNA_ENDPOINT__ ?? '');
      const r = await fetch(`${endpointRoot}/api/smart-ministore`, {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ query: v.trim(), maxResults: 8, category_id: 26 }),
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok) throw new Error(data?.error || `Error ${r.status}`);
      console.log('[smart-ministore] created', data);
      if (data.bookId) window.dispatchEvent(new CustomEvent('deanna:open-book', { detail: data }));
      setDone(true); setV('');
      setTimeout(() => setDone(false), 2400);
    } catch (e) {
      console.warn('[smart-ministore] failed (CORS or auth) — demo fallback:', e.message);
      setDone(true); setV('');
      setTimeout(() => setDone(false), 2400);
    } finally {
      setBusy(false);
    }
  };
  const examples = ['cottagecore corner', 'minimal gamer setup', 'dinner table with friends'];
  if (floating) {
    return (
      <div style={{
        position: 'absolute', left: 12, right: 12, bottom: 92, zIndex: 55,
        padding: 10, borderRadius: 22,
        background: 'rgba(20,25,18,0.62)',
        backdropFilter: 'blur(20px) saturate(160%)',
        WebkitBackdropFilter: 'blur(20px) saturate(160%)',
        border: '0.5px solid rgba(255,255,255,0.18)',
        boxShadow: '0 12px 30px rgba(0,0,0,0.35)',
        display: 'flex', alignItems: 'center', gap: 8,
      }}>
        <div style={{ width: 30, height: 30, borderRadius: 10,
          background: 'linear-gradient(135deg, #C9DCC0, #728C66)',
          display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
        }}>{Icon.sparkle('#1A2A14')}</div>
        <input value={v} onChange={(e) => setV(e.target.value)}
          onKeyDown={(e) => e.key === 'Enter' && submit()}
          placeholder={done ? '✨ MiniStore created' : (busy ? 'Curating...' : 'Create your MiniStore...')}
          style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent',
            fontSize: 14, color: '#fff', fontFamily: 'inherit', minWidth: 0,
          }} />
        <button onClick={submit} disabled={!v.trim() || busy} style={{
          border: 'none', cursor: v.trim() && !busy ? 'pointer' : 'default',
          width: 34, height: 34, borderRadius: 999,
          background: v.trim() && !busy ? '#C9DCC0' : 'rgba(255,255,255,0.18)',
          color: '#1A2A14', display: 'flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0,
        }}>{Icon.plus(v.trim() && !busy ? '#1A2A14' : '#fff', 2.5)}</button>
      </div>
    );
  }
  return (
    <div style={{
      margin: '0 4px 18px', padding: 16, borderRadius: 22,
      background: 'linear-gradient(135deg, var(--accent-soft), var(--accent-2))',
      position: 'relative', overflow: 'hidden',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
        <div style={{ width: 26, height: 26, borderRadius: 8,
          background: 'rgba(26,42,20,0.92)',
          display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          {Icon.sparkle('#C9DCC0')}
        </div>
        <div style={{ fontSize: 12, fontWeight: 600, letterSpacing: 0.4,
          textTransform: 'uppercase', color: '#1A2A14' }}>Create your MiniStore</div>
      </div>
      <div style={{ fontSize: 18, fontWeight: 600, letterSpacing: -0.3,
        fontFamily: 'var(--font-display)', color: '#1A2A14', marginBottom: 14 }}>
        Describe what you want and we'll generate it.
      </div>
      <div style={{
        display: 'flex', gap: 8, alignItems: 'center',
        background: 'rgba(255,255,255,0.85)', borderRadius: 14, padding: '10px 12px',
      }}>
        <input value={v} onChange={(e) => setV(e.target.value)}
          onKeyDown={(e) => e.key === 'Enter' && submit()}
          placeholder={done ? '✨ MiniStore created' : (busy ? 'Curating products...' : 'e.g. my autumn kitchen')}
          style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent',
            fontSize: 14, color: '#1A2A14', fontFamily: 'inherit', minWidth: 0 }} />
        <button onClick={submit} disabled={!v.trim() || busy} style={{
          border: 'none', cursor: v.trim() && !busy ? 'pointer' : 'default',
          height: 32, padding: '0 14px', borderRadius: 999,
          background: '#1A2A14', color: '#C9DCC0',
          fontSize: 13, fontWeight: 600,
        }}>{busy ? '...' : 'Generate'}</button>
      </div>
      <div style={{ display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap' }}>
        {examples.map((e) => (
          <button key={e} onClick={() => setV(e)} style={{
            border: 'none', cursor: 'pointer', padding: '5px 10px', borderRadius: 999,
            background: 'rgba(26,42,20,0.10)', color: '#1A2A14',
            fontSize: 11, fontWeight: 500,
          }}>{e}</button>
        ))}
      </div>
    </div>
  );
}

function decodeToken(token) {
  try {
    // deanna2u uses base64url (RFC 4648): replace - with + and _ with /,
    // then add padding so atob() can parse it.
    const raw = token.split('.')[0];
    const b64 = raw.replace(/-/g, '+').replace(/_/g, '/');
    const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4);
    return JSON.parse(atob(padded));
  } catch { return null; }
}

function AuthSheet({ reason, onClose, onSignup, onOpenPricing, isDesktop }) {
  const [mode, setMode] = React.useState('signup');
  const [email, setEmail] = React.useState('');
  const [pass, setPass] = React.useState('');
  const [name, setName] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  const COPY = {
    limit:      { t: 'You\'ve seen 5 MiniStores',          s: 'Create a free account to keep discovering without limits.' },
    save:       { t: 'Save this MiniStore',                s: 'Build your personal mood board — all you need is an account.' },
    create:     { t: 'Create your MiniStore',              s: 'To generate and share your collections, create an account.' },
    onboarding: { t: 'Almost there ✨',                    s: 'Create your account to save your personalized feed.' },
    upgrade:    { t: 'You\'ve reached your daily limit',   s: 'Upgrade your plan to create more MiniStores today.' },
  };
  const copy = COPY[reason] || COPY.create;

  const submit = async () => {
    if (!email.trim() || !pass.trim()) { setErr('Please fill in all required fields.'); return; }
    if (mode === 'signup' && !name.trim()) { setErr('Please enter your name.'); return; }
    setBusy(true); setErr('');
    const base = window.resolveDeannaApiBase ? window.resolveDeannaApiBase() : (window.__DEANNA_ENDPOINT__ ?? '');
    try {
      if (mode === 'signup') {
        const parts = name.trim().split(/\s+/);
        const r = await fetch(`${base}/api/auth/register`, {
          method: 'POST', credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ email: email.trim(), name: parts[0], last_name: parts.slice(1).join(' ') || parts[0], password: pass }),
        });
        const data = await r.json().catch(() => ({}));
        if (!r.ok) { setErr(data.error || 'Registration failed.'); setBusy(false); return; }
        // Auto-login to establish session cookie and get userId
        const lr = await fetch(`${base}/api/auth`, {
          method: 'POST', credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ email: email.trim(), password: pass }),
        });
        const ldata = await lr.json().catch(() => ({}));
        const payload = decodeToken(ldata.token);
        onSignup({ id: payload?.userId, name: parts[0], email: email.trim(), plan: 'free', darkMode: false });
      } else {
        const r = await fetch(`${base}/api/auth`, {
          method: 'POST', credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ email: email.trim(), password: pass }),
        });
        const data = await r.json().catch(() => ({}));
        if (!r.ok) { setErr(data.error || 'Incorrect email or password.'); setBusy(false); return; }
        const payload = decodeToken(data.token);
        let displayName = email.trim().split('@')[0];
        if (payload?.userId) {
          try {
            const ur = await fetch(`${base}/api/user/${payload.userId}`, { credentials: 'include' });
            if (ur.ok) { const ud = await ur.json(); displayName = ud.user?.firstName || displayName; }
          } catch {}
        }
        onSignup({ id: payload?.userId, name: displayName, email: email.trim(), plan: 'free', darkMode: false });
      }
    } catch {
      setErr('Connection error. Please try again.');
    }
    setBusy(false);
  };

  const inputStyle = {
    width: '100%', padding: '13px 14px', borderRadius: 14, border: '1.5px solid var(--surface-2)',
    background: 'var(--surface)', color: 'var(--ink)', fontSize: 14,
    fontFamily: 'inherit', outline: 'none', boxSizing: 'border-box', marginBottom: 10,
  };

  const sheetContent = reason === 'upgrade' ? (
    <>
      <div style={{ width: 56, height: 56, borderRadius: 18,
        background: 'linear-gradient(135deg,#C9DCC0,#728C66)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        marginBottom: 16 }}>{Icon.sparkle('#1A2A14')}</div>
      <div style={{ fontSize: 24, fontWeight: 600, letterSpacing: -0.5,
        fontFamily: 'var(--font-display)', marginBottom: 8, lineHeight: '28px' }}>{copy.t}</div>
      <div style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: '20px', marginBottom: 24 }}>{copy.s}</div>
      <button onClick={onOpenPricing} style={{ width: '100%', height: 52, border: 'none',
        borderRadius: 999, background: 'var(--ink)', color: 'var(--bg)',
        fontSize: 15, fontWeight: 600, cursor: 'pointer', marginBottom: 10 }}>
        See plans →
      </button>
      <button onClick={onClose} style={{ width: '100%', height: 44, border: 'none',
        background: 'transparent', color: 'var(--ink-2)', fontSize: 14, cursor: 'pointer' }}>
        Not now
      </button>
    </>
  ) : (
    <>
      <div style={{ width: 56, height: 56, borderRadius: 18,
        background: 'linear-gradient(135deg,#C9DCC0,#728C66)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        marginBottom: 16 }}>{Icon.sparkle('#1A2A14')}</div>
      <div style={{ fontSize: 24, fontWeight: 600, letterSpacing: -0.5,
        fontFamily: 'var(--font-display)', marginBottom: 8, lineHeight: '28px' }}>{copy.t}</div>
      <div style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: '20px', marginBottom: 22 }}>{copy.s}</div>
      {mode === 'signup' && (
        <input value={name} onChange={e => { setName(e.target.value); setErr(''); }}
          placeholder="Your name" type="text" style={inputStyle} />
      )}
      <input value={email} onChange={e => { setEmail(e.target.value); setErr(''); }}
        placeholder="Email address" type="email" style={inputStyle} />
      <input value={pass} onChange={e => { setPass(e.target.value); setErr(''); }}
        placeholder="Password" type="password" style={inputStyle} />
      {err && <div style={{ fontSize: 12, color: '#c0392b', marginBottom: 8 }}>{err}</div>}
      <button onClick={submit} disabled={busy} style={{ width: '100%', height: 52, border: 'none',
        borderRadius: 999, background: 'var(--ink)', color: 'var(--bg)',
        fontSize: 15, fontWeight: 600, cursor: busy ? 'default' : 'pointer', marginBottom: 10,
        opacity: busy ? 0.7 : 1 }}>
        {busy ? '...' : (mode === 'signup' ? 'Create free account' : 'Sign in')}
      </button>
      <button onClick={() => { setMode(m => m === 'signup' ? 'login' : 'signup'); setErr(''); }}
        style={{ width: '100%', height: 44, border: 'none',
        background: 'transparent', color: 'var(--accent-ink)', fontSize: 14, cursor: 'pointer', marginBottom: 4 }}>
        {mode === 'signup' ? 'Already have an account? Sign in' : 'No account? Create one'}
      </button>
      {reason === 'onboarding' ? (
        <button onClick={onClose} style={{ width: '100%', height: 44, border: 'none',
          background: 'transparent', color: 'var(--ink-2)', fontSize: 13, cursor: 'pointer' }}>
          Skip for now
        </button>
      ) : (
        <button onClick={onClose} style={{ width: '100%', height: 44, border: 'none',
          background: 'transparent', color: 'var(--ink-2)', fontSize: 14, cursor: 'pointer' }}>
          Not now
        </button>
      )}
    </>
  );

  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 100,
      background: 'rgba(15,20,12,0.55)', backdropFilter: 'blur(8px)',
      WebkitBackdropFilter: 'blur(8px)',
      display: 'flex', alignItems: isDesktop ? 'center' : 'flex-end', justifyContent: 'center' }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: 'var(--bg)', color: 'var(--ink)',
        width: '100%', maxWidth: isDesktop ? 440 : '100%',
        borderRadius: isDesktop ? 28 : '28px 28px 0 0',
        padding: '14px 22px 40px', boxSizing: 'border-box',
        animation: 'slideUp .28s cubic-bezier(.2,.8,.2,1)',
        margin: isDesktop ? '0 auto' : 0,
      }}>
        <div style={{ width: 36, height: 4, borderRadius: 999, background: 'var(--surface-2)',
          margin: '0 auto 22px' }} />
        {sheetContent}
      </div>
    </div>
  );
}

function StoreIframeOverlay({ store, onClose }) {
  const bookId = store?.bookId;
  const path = store?.sharePath?.startsWith?.('/')
    ? store.sharePath
    : (store?.shareSlug ? `/share/${encodeURIComponent(store.shareSlug)}` : '');
  const host = 'https://deanna.pro';
  const url = path ? `${host}${path}` : (bookId != null ? `${host}/share/${encodeURIComponent(bookId)}` : null);
  const labelSlug = store?.shareSlug || (bookId != null ? String(bookId) : '—');
  const [loaded, setLoaded] = React.useState(false);
  const [failed, setFailed] = React.useState(false);
  React.useEffect(() => {
    if (!url) return;
    const t = setTimeout(() => { if (!loaded) setFailed(true); }, 6000);
    return () => clearTimeout(t);
  }, [url, loaded]);
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 95, background: '#000',
      display: 'flex', flexDirection: 'column' }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '52px 14px 10px', background: '#000', color: '#fff' }}>
        <button onClick={onClose} style={{ border: 'none', background: 'rgba(255,255,255,0.14)',
          width: 36, height: 36, borderRadius: 999, cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          {Icon.close('#fff', 2)}
        </button>
        <div style={{ fontSize: 13, fontWeight: 600, opacity: 0.85,
          display: 'flex', alignItems: 'center', gap: 6 }}>
          <span style={{ width: 6, height: 6, borderRadius: 999, background: '#7CC893' }} />
          deanna.pro{path || `/share/${labelSlug}`}
        </div>
        <div style={{ width: 36 }} />
      </div>
      <div style={{ flex: 1, background: '#fff', position: 'relative' }}>
        {url && !failed && (
          <iframe src={url}
            onLoad={() => setLoaded(true)}
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%',
              border: 'none', background: '#fff' }}
            sandbox="allow-scripts allow-same-origin allow-popups allow-forms" />
        )}
        {(!url || !loaded) && (
          <div style={{ position: 'absolute', inset: 0, display: 'flex',
            alignItems: 'center', justifyContent: 'center',
            flexDirection: 'column', gap: 12, color: '#5C6B54',
            background: 'linear-gradient(180deg, #F2EFE3, #E2DFD2)',
            pointerEvents: failed ? 'auto' : 'none' }}>
            <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: 1.4,
              textTransform: 'uppercase' }}>
              {failed ? 'Embed bloqueado' : 'Cargando MiniTienda…'}
            </div>
            <div style={{ fontSize: 16, fontWeight: 600, color: '#1A2A14',
              fontFamily: 'var(--font-display)', textAlign: 'center', padding: '0 32px' }}>
              {failed ? 'deanna.pro no permite embeds' : (store?.title || '')}
            </div>
            {failed && (
              <a href={url} target="_blank" rel="noopener" style={{
                marginTop: 8, padding: '10px 18px', borderRadius: 999,
                background: '#1A2A14', color: '#fff', textDecoration: 'none',
                fontSize: 13, fontWeight: 600 }}>Abrir en navegador →</a>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Board Picker Sheet ───────────────────────────────────────────────────
function BoardPickerSheet({ storeId, boards, onAddToBoard, onNewBoard, onClose, isDesktop }) {
  const [newName, setNewName] = React.useState('');
  const [creating, setCreating] = React.useState(false);

  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 90,
      background: 'rgba(15,20,12,0.45)', backdropFilter: 'blur(6px)',
      WebkitBackdropFilter: 'blur(6px)',
      display: 'flex', alignItems: isDesktop ? 'center' : 'flex-end', justifyContent: 'center' }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: 'var(--bg)', width: '100%',
        maxWidth: isDesktop ? 400 : '100%',
        borderRadius: isDesktop ? 28 : '24px 24px 0 0', padding: '14px 20px 36px',
        boxSizing: 'border-box',
        margin: isDesktop ? '0 auto' : 0,
      }}>
        <div style={{ width: 32, height: 4, borderRadius: 999, background: 'var(--surface-2)',
          margin: '0 auto 18px' }} />
        <div style={{ fontSize: 16, fontWeight: 600, marginBottom: 14 }}>Save to...</div>
        {boards.map(b => (
          <button key={b.id} onClick={() => onAddToBoard(b.id)} style={{
            width: '100%', textAlign: 'left', padding: '12px 14px', marginBottom: 6,
            border: '1px solid var(--surface-2)', borderRadius: 14, background: 'var(--surface)',
            fontSize: 14, color: 'var(--ink)', cursor: 'pointer',
            display: 'flex', justifyContent: 'space-between',
          }}>
            <span>{b.name}</span>
            <span style={{ color: 'var(--ink-2)', fontSize: 12 }}>{b.storeIds.length} store{b.storeIds.length !== 1 ? 's' : ''}</span>
          </button>
        ))}
        {creating ? (
          <div style={{ display: 'flex', gap: 8, marginTop: 6 }}>
            <input value={newName} onChange={e => setNewName(e.target.value)}
              placeholder="Board name"
              style={{ flex: 1, padding: '11px 14px', borderRadius: 14,
                border: '1.5px solid var(--accent)', background: 'var(--surface)',
                fontSize: 14, color: 'var(--ink)', outline: 'none', fontFamily: 'inherit' }} />
            <button onClick={() => { if (newName.trim()) onNewBoard(newName.trim()); }}
              style={{ padding: '0 16px', border: 'none', borderRadius: 14,
                background: 'var(--ink)', color: 'var(--bg)', fontSize: 13,
                fontWeight: 600, cursor: 'pointer' }}>Create</button>
          </div>
        ) : (
          <button onClick={() => setCreating(true)} style={{
            width: '100%', marginTop: 6, padding: '12px', border: '1.5px dashed var(--surface-2)',
            borderRadius: 14, background: 'transparent', color: 'var(--ink-2)',
            fontSize: 13, cursor: 'pointer',
          }}>+ New collection</button>
        )}
        <button onClick={onClose} style={{ width: '100%', marginTop: 10, height: 40,
          border: 'none', background: 'transparent', color: 'var(--ink-2)', fontSize: 13, cursor: 'pointer' }}>
          Cancel
        </button>
      </div>
    </div>
  );
}

// ─── Pricing ──────────────────────────────────────────────────────────────
const PLANS = [
  {
    id: 'free',
    label: 'FREE',
    price: '$0',
    period: '/mo',
    features: ['5 MiniStores per day', 'Basic exploration', '5 saved'],
    cardBg: 'var(--surface)',
    cardBorder: '1.5px solid var(--surface-2)',
    labelColor: 'var(--ink-2)',
    priceColor: 'var(--ink)',
    textColor: 'var(--ink)',
    lift: false,
  },
  {
    id: 'standard',
    label: 'STANDARD',
    badge: '⭐ Most popular',
    price: '$9.99',
    period: '/mo',
    features: ['30 MiniStores per day', 'Unlimited saved', 'Mood boards', 'Personalized feed'],
    cardBg: 'linear-gradient(160deg,#C9DCC0,#8FA882)',
    cardBorder: 'none',
    labelColor: '#2A3D22',
    priceColor: '#1A2A14',
    textColor: '#1A2A14',
    lift: true,
  },
  {
    id: 'premium',
    label: 'PREMIUM',
    badge: '✦ Pro',
    price: '$24.99',
    period: '/mo',
    features: ['100 MiniStores per day', 'Everything in Standard', 'AI marketing strategies', '.99 pricing psychology', 'Usage bar in profile'],
    cardBg: '#1F2A1A',
    cardBorder: 'none',
    labelColor: '#8FA882',
    priceColor: '#fff',
    textColor: '#C9DCC0',
    lift: false,
  },
];

function PricingScreen({ onBack, currentPlan, onSelectPlan }) {
  const [selected, setSelected] = React.useState(null);

  const handleSelect = (planId) => {
    setSelected(planId);
    onSelectPlan(planId);
    setTimeout(onBack, 800);
  };

  return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)', color: 'var(--ink)' }}>
      <div style={{ padding: '58px 16px 12px', display: 'flex', alignItems: 'center', gap: 10 }}>
        <button onClick={onBack} style={{ border: 'none', background: 'var(--surface-2)',
          width: 36, height: 36, borderRadius: 999, cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          {Icon.back('var(--ink)', 2)}
        </button>
        <div style={{ fontSize: 20, fontWeight: 700, letterSpacing: -0.4,
          fontFamily: 'var(--font-display)' }}>Choose your plan</div>
      </div>

      <div style={{ padding: '4px 16px 10px', fontSize: 14, color: 'var(--ink-2)', lineHeight: '20px' }}>
        All plans include access to AI-curated MiniStores. No commitment.
      </div>

      {/* 3-column cards */}
      <div style={{ display: 'flex', gap: 8, padding: '16px 12px 24px', alignItems: 'flex-end' }}>
        {PLANS.map((p) => {
          const isActive = (currentPlan || 'free') === p.id;
          const isSelected = selected === p.id;
          return (
            <div key={p.id} style={{
              flex: 1, borderRadius: 20, padding: '16px 10px',
              background: p.cardBg, border: p.cardBorder,
              boxShadow: p.lift ? '0 8px 24px rgba(40,55,32,.22)' : 'none',
              transform: p.lift ? 'translateY(-10px)' : 'none',
              display: 'flex', flexDirection: 'column', gap: 6,
              transition: 'transform .15s',
            }}>
              {p.badge && (
                <div style={{ fontSize: 9, fontWeight: 700, letterSpacing: .4,
                  color: p.labelColor, marginBottom: 2 }}>{p.badge}</div>
              )}
              <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: 1,
                textTransform: 'uppercase', color: p.labelColor }}>{p.label}</div>
              <div style={{ fontSize: 22, fontWeight: 700, color: p.priceColor,
                letterSpacing: -0.5, lineHeight: 1 }}>{p.price}</div>
              <div style={{ fontSize: 10, color: p.labelColor, marginBottom: 6 }}>{p.period}</div>
              {p.features.map((f) => (
                <div key={f} style={{ fontSize: 10, color: p.textColor,
                  display: 'flex', gap: 4, alignItems: 'flex-start' }}>
                  <span style={{ opacity: 0.7 }}>✓</span>{f}
                </div>
              ))}
              <button
                onClick={() => !isActive && handleSelect(p.id)}
                style={{
                  marginTop: 12, width: '100%', height: 34, border: 'none',
                  borderRadius: 999, cursor: isActive ? 'default' : 'pointer',
                  background: isActive
                    ? 'rgba(255,255,255,0.25)'
                    : (p.id === 'premium' ? '#C9DCC0' : 'rgba(26,42,20,0.85)'),
                  color: isActive ? p.textColor : (p.id === 'premium' ? '#1A2A14' : '#C9DCC0'),
                  fontSize: 11, fontWeight: 700,
                  transition: 'all .15s',
                }}>
                {isActive ? '✓ Active' : (isSelected ? '✓ Updated' : 'Select')}
              </button>
            </div>
          );
        })}
      </div>

      {/* Feature comparison note */}
      <div style={{ margin: '0 16px 32px', padding: '16px', borderRadius: 16,
        background: 'var(--accent-soft)' }}>
        <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--accent-ink)',
          marginBottom: 8 }}>Why Premium?</div>
        <div style={{ fontSize: 12, color: 'var(--ink-2)', lineHeight: '18px' }}>
          .99 prices convert 20% better. Odd-number titles get more clicks.
          Posting at 7–9pm maximizes engagement. Deanna AI shows you these strategies in real time.
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  OnboardingScreen, HomeFeed, ExploreHero, StoreDetail, ProductDetail,
  SavedScreen, ProfileScreen, CreateBar, AuthSheet, PricingScreen,
  BoardPickerSheet, StoreIframeOverlay,
});
