// p05-seed.jsx — Seed detail screen + P05a/b/c/e sheets
// States: default / playingPhrase / playingDialogue / unfiled (no pouch)

function ScreenSeed({ state, onNavigate, seedId, from }) {
  const T = window.T;
  const seed = window.MOCK_SEEDS.find(s => s.id === (seedId || 's01')) || window.MOCK_SEEDS[0];
  const isUnfiled = state === 'unfiled';
  const seedPouches = isUnfiled ? [] : seed.pouches.map(id => window.MOCK_POUCHES.find(p => p.id === id)).filter(Boolean);

  // When entering from P10 (success screen), show a context breadcrumb
  // so the user knows where to return. P10 multi additionally gets prev/next
  // navigation through the freshly-created seeds.
  const fromP10 = from === 'P10' || from === 'P10m';
  const fromP10Multi = from === 'P10m';
  const createdList = fromP10Multi ? (window.MOCK_SEEDS || []).slice(0, 5) : null;
  const createdIdx  = fromP10Multi ? createdList.findIndex(s => s.id === seed.id) : -1;
  const prevSeed = createdIdx > 0 ? createdList[createdIdx - 1] : null;
  const nextSeed = createdIdx >= 0 && createdIdx < createdList?.length - 1 ? createdList[createdIdx + 1] : null;

  // 인라인 편집 가능한 분류: 첨출표 제거(×) + "+ 추가" 시트.
  // 초기값은 씨앗의 자동 분류는 ID. 편집 세션이 이어지도록 state로 든다.
  const [seedCats, setSeedCats] = React.useState(seed.categories || []);
  React.useEffect(() => { setSeedCats(seed.categories || []); }, [seed.id]);
  const [catSheetOpen, setCatSheetOpen] = React.useState(false);

  const [playingPhrase, setPlayingPhrase] = React.useState(state === 'playingPhrase');
  const [playingDialogue, setPlayingDialogue] = React.useState(state === 'playingDialogue');

  const [sheet, setSheet] = React.useState(null); // 'actions' | 'move' | 'cats' | null
  const [showDelete, setShowDelete] = React.useState(false);

  // 곳간(즐겨찾기) — 별 토글 + 토스트
  const seedFavs = useSeedFavs();
  const fav = seedFavs.isFav(seed.id);
  const [favToast, setFavToast] = React.useState(null);
  React.useEffect(() => {
    if (!favToast) return;
    const t = setTimeout(() => setFavToast(null), 2200);
    return () => clearTimeout(t);
  }, [favToast]);
  const toggleFav = () => {
    const now = seedFavs.toggle(seed.id);
    setFavToast(now ? '곳간에 담았어요' : '곳간에서 뺐어요');
  };

  // Tokenize foreign text: word-by-word for space-separated langs, char-by-char otherwise (JA/ZH).
  const hasSpaces = /\s/.test(seed.foreign);
  const isPunct = (t) => /^[\s、。?,.!?¿¡·…]+$/.test(t);
  const words = React.useMemo(() => (
    hasSpaces
      ? seed.foreign.split(/(\s+)/).filter(Boolean)
      : Array.from(seed.foreign)
  ), [seed.foreign, hasSpaces]);
  const highlightables = React.useMemo(
    () => words.map((w, i) => (isPunct(w) ? -1 : i)).filter(i => i >= 0),
    [words]
  );

  // Static frames for screenshot states: mid-phrase highlight + the "me" turn.
  const staticPhraseIdx = highlightables[Math.min(2, highlightables.length - 1)] ?? -1;
  const meIdx = seed.dialogue.findIndex(l => l.who === 'me');
  const staticDialIdx = meIdx >= 0 ? meIdx : Math.min(1, seed.dialogue.length - 1);

  const [phraseWordIdx, setPhraseWordIdx] = React.useState(
    state === 'playingPhrase' ? staticPhraseIdx : -1
  );
  const [dialIdx, setDialIdx] = React.useState(
    state === 'playingDialogue' ? staticDialIdx : -1
  );

  // When entering via state prop, hold the static frame on first mount.
  // Only animate when the user toggles play themselves.
  const skipPhraseAnim = React.useRef(state === 'playingPhrase');
  const skipDialAnim = React.useRef(state === 'playingDialogue');

  // ─── 내 표현 듣기: walk word-by-word, then auto-stop. ───
  React.useEffect(() => {
    if (!playingPhrase) { setPhraseWordIdx(-1); return; }
    if (skipPhraseAnim.current) { skipPhraseAnim.current = false; return; }
    let step = 0;
    setPhraseWordIdx(highlightables[0] ?? -1);
    const perWord = hasSpaces ? 380 : 240; // chars tick faster than words
    const id = setInterval(() => {
      step += 1;
      if (step >= highlightables.length) {
        clearInterval(id);
        setPhraseWordIdx(-1);
        setPlayingPhrase(false);
      } else {
        setPhraseWordIdx(highlightables[step]);
      }
    }, perWord);
    return () => clearInterval(id);
  }, [playingPhrase, highlightables, hasSpaces]);

  // ─── 대화 전체 듣기: start at line 0, advance through all, auto-stop. ───
  React.useEffect(() => {
    if (!playingDialogue) { setDialIdx(-1); return; }
    if (skipDialAnim.current) { skipDialAnim.current = false; return; }
    let i = 0;
    setDialIdx(0);
    const id = setInterval(() => {
      i += 1;
      if (i >= seed.dialogue.length) {
        clearInterval(id);
        setDialIdx(-1);
        setPlayingDialogue(false);
      } else {
        setDialIdx(i);
      }
    }, 1500);
    return () => clearInterval(id);
  }, [playingDialogue, seed.dialogue.length]);

  return (
    <div style={{ position: 'absolute', inset: 0, background: T.bg,
                  display: 'flex', flexDirection: 'column' }}>
      <TopBar
        leading={<IconButton icon={<Icons.Back size={22} color={T.ink}/>}
                             onClick={() => onNavigate('back')}/>}
        trailing={
          <div style={{ display: 'flex', alignItems: 'center', gap: 2 }}>
            <IconButton icon={<Icons.Star size={22} color={fav ? T.accent : T.ink} filled={fav}/>}
                        onClick={toggleFav}/>
            <IconButton icon={<Icons.More size={22} color={T.ink}/>}
                        onClick={() => setSheet('actions')}/>
          </div>
        }
      />            

      {/* P10 context breadcrumb. Both default (1 seed) and multi (5 seeds)
          users see this; multi additionally gets prev/next buttons. */}
      {fromP10 && (
        <div style={{
          flexShrink: 0,
          margin: '0 16px 6px',
          padding: '8px 10px 8px 12px',
          background: T.accentSoft,
          borderRadius: 14,
          display: 'flex', alignItems: 'center', gap: 8,
          fontSize: 12.5, color: T.accent, fontWeight: 700,
          letterSpacing: '-0.005em',
        }}>
          <Icons.Sparkle size={14} color={T.accent}/>
          <span style={{ flex: 1 }}>
            {fromP10Multi && createdIdx >= 0
              ? <React.Fragment>✨ 방금 만든 <span style={{ color: T.ink, fontWeight: 800 }}>{createdList.length}개</span> 중 <span style={{ color: T.ink, fontWeight: 800 }}>{createdIdx + 1}번째</span></React.Fragment>
              : <React.Fragment>방금 만든 씨앗 확인 중</React.Fragment>}
          </span>
          {fromP10Multi && (
            <React.Fragment>
              <button onClick={() => prevSeed && onNavigate('P05', { seedId: prevSeed.id, from: 'P10m' })}
                      disabled={!prevSeed}
                      aria-label="이전 씨앗"
                      style={{
                width: 30, height: 30, borderRadius: '50%',
                background: prevSeed ? '#FFF' : 'transparent',
                border: `0.5px solid ${prevSeed ? T.hairlineStrong : 'transparent'}`,
                cursor: prevSeed ? 'pointer' : 'default',
                opacity: prevSeed ? 1 : 0.3,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                padding: 0, fontFamily: 'inherit',
              }}>
                <Icons.Back size={14} color={T.accent}/>
              </button>
              <button onClick={() => nextSeed && onNavigate('P05', { seedId: nextSeed.id, from: 'P10m' })}
                      disabled={!nextSeed}
                      aria-label="다음 씨앗"
                      style={{
                width: 30, height: 30, borderRadius: '50%',
                background: nextSeed ? '#FFF' : 'transparent',
                border: `0.5px solid ${nextSeed ? T.hairlineStrong : 'transparent'}`,
                cursor: nextSeed ? 'pointer' : 'default',
                opacity: nextSeed ? 1 : 0.3,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                padding: 0, fontFamily: 'inherit',
              }}>
                <Icons.Forward size={14} color={T.accent}/>
              </button>
            </React.Fragment>
          )}
          <button onClick={() => onNavigate('back')}
                  style={{
            height: 30, padding: '0 12px', borderRadius: 15,
            background: T.accent, color: '#FFF', border: 'none',
            fontSize: 12, fontWeight: 700, fontFamily: 'inherit',
            letterSpacing: '-0.005em', cursor: 'pointer',
            WebkitTapHighlightColor: 'transparent',
          }}>
            {fromP10Multi ? '목록' : '돌아가기'}
          </button>
        </div>
      )}

      <div style={{ flex: 1, overflowY: 'auto', padding: '4px 20px 28px' }}>
        {/* Language label */}
        <div style={{
          fontSize: 11.5, fontWeight: 700, color: T.ink3,
          letterSpacing: '0.1em', textTransform: 'uppercase',
          marginBottom: 14,
        }}>{seed.langLabel}</div>

        {/* Foreign (largest) */}
        <div style={{
          fontSize: 30, fontWeight: 700, color: T.ink,
          letterSpacing: '-0.025em', lineHeight: 1.25,
          marginBottom: 10,
        }}>
          {playingPhrase ? words.map((w, i) => (
            <span key={i} style={{
              color: i === phraseWordIdx ? T.accent : T.ink,
              background: i === phraseWordIdx ? T.accentSoft : 'transparent',
              borderRadius: 4,
              padding: i === phraseWordIdx ? '0 2px' : 0,
              transition: 'color .15s',
            }}>{w}</span>
          )) : seed.foreign}
        </div>

        {/* Pronunciation */}
        <div style={{
          fontSize: 17, fontWeight: 500, color: T.ink2,
          letterSpacing: '-0.01em', lineHeight: 1.4,
          marginBottom: 10,
        }}>{seed.pron}</div>

        {/* Korean */}
        <div style={{
          fontSize: 15, color: T.ink3, lineHeight: 1.45,
          marginBottom: 22,
        }}>{seed.korean}</div>

        {/* Primary play */}
        <button onClick={() => { setPlayingPhrase(p => !p); setPlayingDialogue(false); }}
                style={{
          width: '100%', height: 56, borderRadius: 16,
          background: playingPhrase ? T.accent : T.ink,
          color: playingPhrase ? '#FFF' : T.onInk, border: 'none',
          fontFamily: 'inherit', fontSize: 15.5, fontWeight: 700,
          letterSpacing: '-0.01em',
          cursor: 'pointer', marginBottom: 26,
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10,
        }}>
          {playingPhrase ? <Icons.Stop size={18} color="#FFF"/> : <Icons.Play size={18} color={T.onInk} fillTri/>}
          {playingPhrase ? '듣는 중…' : '내 표현 듣기'}
        </button>

        {/* Dialogue context */}
        <div style={{
          fontSize: 11.5, fontWeight: 700, color: T.ink3,
          letterSpacing: '0.08em', textTransform: 'uppercase',
          marginBottom: 12,
        }}>이런 상황에서</div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 16 }}>
          {seed.dialogue.map((line, i) => {
            const isMe = line.who === 'me';
            const active = playingDialogue && i === dialIdx;
            return (
              <div key={i} style={{
                display: 'flex', justifyContent: isMe ? 'flex-end' : 'flex-start',
              }}>
                <div style={{
                  maxWidth: '82%',
                  background: isMe
                    ? (active ? T.accent : T.surface2)
                    : (active ? T.accentSoft : T.surface),
                  color: isMe ? (active ? '#FFF' : T.ink) : T.ink,
                  border: isMe
                    ? (active ? 'none' : `1.5px solid ${T.accent}`)
                    : (active ? `0.5px solid ${T.accent}` : `0.5px solid ${T.hairline}`),
                  transition: 'background .15s, border-color .15s, color .15s',
                  borderRadius: isMe ? '16px 16px 4px 16px' : '16px 16px 16px 4px',
                  padding: '12px 14px',
                  position: 'relative',
                }}>
                  <div style={{
                    fontSize: 11, fontWeight: 700,
                    color: isMe
                      ? (active ? 'rgba(255,255,255,0.7)' : T.accent)
                      : (active ? T.accent : T.ink3),
                    letterSpacing: '0.06em', textTransform: 'uppercase',
                    marginBottom: 4,
                  }}>{isMe ? '나' : '상대'}</div>
                  <div style={{
                    fontSize: 15.5, fontWeight: 600,
                    letterSpacing: '-0.01em', lineHeight: 1.35,
                    marginBottom: 4,
                  }}>{line.text}</div>
                  <div style={{
                    fontSize: 12, opacity: 0.75,
                  }}>{line.pron}</div>
                  {active && (
                    <div style={{ position: 'absolute', right: -6, bottom: -6,
                                  display: 'flex', alignItems: 'flex-end', gap: 2,
                                  background: T.bg, borderRadius: 10,
                                  padding: '4px 6px', }}>
                      {[0, 1, 2].map(b => (
                        <div key={b} style={{
                          width: 3, height: 10,
                          background: T.accent, borderRadius: 2,
                          animation: `cp-wave 0.8s ease-in-out infinite ${b * 0.15}s`,
                          transformOrigin: 'bottom',
                        }}/>
                      ))}
                    </div>
                  )}
                </div>
              </div>
            );
          })}
        </div>

        <button onClick={() => { setPlayingDialogue(p => !p); setPlayingPhrase(false); }}
                style={{
          width: '100%', height: 48, borderRadius: 14,
          background: T.surface, color: T.ink,
          border: `0.5px solid ${T.hairlineStrong}`,
          fontFamily: 'inherit', fontSize: 14.5, fontWeight: 600,
          letterSpacing: '-0.01em',
          cursor: 'pointer', marginBottom: 22,
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        }}>
          {playingDialogue ? <Icons.Stop size={16} color={T.ink}/> : <Icons.Play size={16} color={T.ink} fillTri/>}
          {playingDialogue
            ? `대화 재생 중… ${dialIdx + 1}/${seed.dialogue.length}`
            : '대화 전체 듣기'}
        </button>

        {/* Categories */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 22 }}>
          <div>
            <div style={{
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              marginBottom: 8,
            }}>
              <div style={{ fontSize: 11.5, fontWeight: 700, color: T.ink3,
                            letterSpacing: '0.08em', textTransform: 'uppercase' }}>분류</div>
              <button onClick={() => setCatSheetOpen(true)} style={{
                background: 'transparent', border: 'none', padding: 0,
                color: T.accent, fontSize: 11.5, fontWeight: 700,
                fontFamily: 'inherit', cursor: 'pointer',
                letterSpacing: '-0.005em',
                WebkitTapHighlightColor: 'transparent',
              }}>
                + 카테고리 추가
              </button>
            </div>
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap',
                          alignItems: 'center' }}>
              {seedCats.map(cid => {
                const liveCats = window.__cpCats || window.MOCK_CATEGORIES;
                const c = liveCats.find(x => x.id === cid);
                if (!c) return null;
                return (
                  <div key={cid} style={{
                    height: 30, padding: '0 4px 0 10px',
                    background: T.accentSoft,
                    border: '0.5px solid transparent',
                    borderRadius: 15,
                    display: 'inline-flex', alignItems: 'center', gap: 5,
                    whiteSpace: 'nowrap', flexShrink: 0,
                  }}>
                    <span style={{ fontSize: 13, lineHeight: 1 }}>
                      {c.icon || window.monogramOf(c.label)}
                    </span>
                    <span style={{ fontSize: 12.5, fontWeight: 600, color: T.ink,
                                   letterSpacing: '-0.005em' }}>{c.label}</span>
                    <button onClick={() => setSeedCats(cs => cs.filter(x => x !== cid))}
                            aria-label={`${c.label} 분류 빼기`}
                            style={{
                      width: 22, height: 22, borderRadius: '50%',
                      background: 'transparent', border: 'none', padding: 0,
                      cursor: 'pointer', flexShrink: 0,
                      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                      WebkitTapHighlightColor: 'transparent',
                    }}>
                      <Icons.Close size={11} color={T.ink3} strokeWidth={2.4}/>
                    </button>
                  </div>
                );
              })}
              {seedCats.length === 0 && (
                <span style={{ fontSize: 12.5, color: T.ink3 }}>
                  분류가 없어요. 옆 버튼으로 추가해주세요
                </span>
              )}
            </div>
          </div>
        </div>

        {/* Pouches — moved to bottom per design feedback */}
        <div style={{
          marginTop: 4, paddingTop: 18,
          borderTop: `0.5px solid ${T.hairline}`,
        }}>
          <div style={{ fontSize: 11.5, fontWeight: 700, color: T.ink3,
                        letterSpacing: '0.08em', textTransform: 'uppercase',
                        marginBottom: 10 }}>담긴 주머니</div>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 6,
            flexWrap: 'wrap',
          }}>
            {seedPouches.map(p => (
              <Chip key={p.id} active leadingDot={T[p.color]}
                    onClick={() => onNavigate('P04', { pouchId: p.id, from: 'P05' })}
                    accent={T[p.color]}>
                {p.name}
              </Chip>
            ))}
            {seedPouches.length === 0 && (
              <span style={{ fontSize: 12.5, color: T.ink3 }}>아직 주머니에 담기지 않았어요</span>
            )}
            <button onClick={() => setSheet('move')} style={{
              height: 32, padding: '0 12px', borderRadius: 16,
              background: 'transparent', border: `1px dashed ${T.hairlineStrong}`,
              color: T.ink2, fontSize: 12.5, fontWeight: 600,
              fontFamily: 'inherit', cursor: 'pointer',
              display: 'inline-flex', alignItems: 'center', gap: 4,
            }}>
              <Icons.Plus size={14} color={T.ink2}/> 담기
            </button>
          </div>
        </div>
      </div>

      {/* P05a Actions sheet */}
      <BottomSheet open={sheet === 'actions'} onClose={() => setSheet(null)}>
        <ActionsSheet seed={seed} pouches={seedPouches}
          fav={fav}
          onToggleFav={() => { setSheet(null); toggleFav(); }}
          onMove={() => setSheet('move')}
          onCats={() => setSheet('cats')}
          onDelete={() => { setSheet(null); setShowDelete(true); }}
        />
      </BottomSheet>

      {/* P05b Move (pouches) sheet */}
      <BottomSheet open={sheet === 'move'} onClose={() => setSheet(null)} title="주머니에 담기">
        <MoveSheet seedPouches={seedPouches} onClose={() => setSheet(null)}/>
      </BottomSheet>

      {/* P05c Categories sheet */}
      <BottomSheet open={sheet === 'cats'} onClose={() => setSheet(null)} title="카테고리 변경">
        <CatsSheet seed={seed} onClose={() => setSheet(null)}/>
      </BottomSheet>

      {/* P05e Delete confirm */}
      <AlertModal
        open={showDelete}
        title="이 씨앗을 삭제할까요?"
        message="모든 주머니에서 사라지고, 되돌릴 수 없어요."
        confirmLabel="삭제"
        danger
        onConfirm={() => { setShowDelete(false); onNavigate('back'); }}
        onCancel={() => setShowDelete(false)}
      />

      {/* Inline 분류 추가 sheet — reused from P10. */}
      {catSheetOpen && window.CategoryAddSheet && (
        <window.CategoryAddSheet
          allCats={window.__cpCats || window.MOCK_CATEGORIES}
          excludeIds={seedCats}
          onPick={(id) => {
            setSeedCats(cs => cs.includes(id) ? cs : [...cs, id]);
            setCatSheetOpen(false);
          }}
          onClose={() => setCatSheetOpen(false)}
        />
      )}

      {favToast && <Toast message={favToast}/>}
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// P05a Actions sheet content
// ──────────────────────────────────────────────────────────────
function ActionsSheet({ seed, pouches, fav, onToggleFav, onMove, onCats, onDelete }) {
  const T = window.T;
  return (
    <div style={{ padding: '6px 16px 24px' }}>
      {/* Preview */}
      <div style={{
        background: T.surface, borderRadius: 14,
        border: `0.5px solid ${T.hairline}`,
        padding: 14, margin: '4px 0 14px',
      }}>
        <div style={{ fontSize: 10.5, fontWeight: 700, color: T.ink3,
                      letterSpacing: '0.08em', textTransform: 'uppercase',
                      marginBottom: 6 }}>{seed.langLabel}</div>
        <div style={{ fontSize: 16, fontWeight: 700, color: T.ink,
                      letterSpacing: '-0.01em', marginBottom: 4 }}>{seed.foreign}</div>
        <div style={{ fontSize: 13, color: T.ink2 }}>{seed.korean}</div>
        <div style={{ marginTop: 10, display: 'flex', gap: 4, flexWrap: 'wrap' }}>
          {pouches.slice(0, 3).map(p => (
            <span key={p.id} style={{
              fontSize: 11, fontWeight: 600, color: T.ink2,
              padding: '3px 8px', borderRadius: 8,
              background: T.inkOverlaySoft,
              display: 'inline-flex', alignItems: 'center', gap: 4,
            }}>
              <span style={{ width: 6, height: 6, borderRadius: 3, background: T[p.color] }}/>
              {p.name}
            </span>
          ))}
        </div>
      </div>

      <div style={{
        background: T.surface, borderRadius: 14,
        border: `0.5px solid ${T.hairline}`,
        overflow: 'hidden', marginBottom: 10,
      }}>
        <ListRow label={fav ? '곳간에서 빼기' : '곳간에 담기'}
                 sub={fav ? null : '집 곳간에 따로 모아둬요'}
                 leading={<Icons.Star size={20} color={fav ? T.accent : T.ink2} filled={fav}/>}
                 onClick={onToggleFav} last/>
      </div>

      <div style={{
        background: T.surface, borderRadius: 14,
        border: `0.5px solid ${T.hairline}`,
        overflow: 'hidden', marginBottom: 10,
      }}>
        <ListRow label="주머니에 담기"
                 leading={<Icons.Bag size={20} color={T.ink2}/>}
                 trailing={<Icons.ChevronR size={18} color={T.ink3}/>}
                 onClick={onMove}/>
        <ListRow label="카테고리 변경"
                 leading={<Icons.Globe size={20} color={T.ink2}/>}
                 trailing={<Icons.ChevronR size={18} color={T.ink3}/>}
                 onClick={onCats} last/>
      </div>

      <div style={{
        background: T.surface, borderRadius: 14,
        border: `0.5px solid ${T.hairline}`,
        overflow: 'hidden',
      }}>
        <ListRow label="씨앗 삭제" danger
                 leading={<Icons.Trash size={20} color={T.danger}/>}
                 onClick={onDelete} last/>
      </div>
    </div>
  );
}

function MoveSheet({ seedPouches, onClose }) {
  const T = window.T;
  const all = window.MOCK_POUCHES;
  const [sel, setSel] = React.useState(new Set(seedPouches.map(p => p.id)));
  const toggle = (id) => {
    const n = new Set(sel);
    n.has(id) ? n.delete(id) : n.add(id);
    setSel(n);
  };
  return (
    <div style={{ padding: '6px 16px 24px' }}>
      <div style={{ fontSize: 12.5, color: T.ink2, padding: '6px 4px 14px' }}>
        여러 주머니에 동시에 담을 수 있어요
      </div>
      <div style={{
        background: T.surface, borderRadius: 14,
        border: `0.5px solid ${T.hairline}`, overflow: 'hidden',
      }}>
        {all.map((p, i) => (
          <ListRow key={p.id}
            label={p.name} sub={`씨앗 ${p.seedIds.length}개`}
            leading={<div style={{ width: 24, height: 24, borderRadius: 6,
                                   background: T[p.color]}}/>}
            trailing={
              <div style={{
                width: 24, height: 24, borderRadius: '50%',
                background: sel.has(p.id) ? T.accent : 'transparent',
                border: sel.has(p.id) ? 'none' : `1.5px solid ${T.hairlineStrong}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>{sel.has(p.id) && <Icons.Check size={14} color="#FFF"/>}</div>
            }
            onClick={() => toggle(p.id)}
            last={i === all.length - 1}
          />
        ))}
      </div>
      <Button kind="primary" fullWidth onClick={onClose}
              style={{ marginTop: 14, height: 52 }}>완료</Button>
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// P05c — Categories sheet.
// Now sources from the live in-app store (window.__cpCats) so adds from
// P13b / P06 show up here. Inline [+ 새 카테고리] expands a compact form
// without leaving the sheet. "자주 쓰는" surfaced first, rest behind 더 보기.
// ──────────────────────────────────────────────────────────────
function CatsSheet({ seed, onClose }) {
  const T = window.T;
  const liveCats = window.__cpCats || window.MOCK_CATEGORIES;
  const [cats, setCats] = React.useState(liveCats);
  const [sel, setSel] = React.useState(new Set(seed.categories));
  const [showMore, setShowMore] = React.useState(false);
  const [addOpen, setAddOpen] = React.useState(false);
  const [newLabel, setNewLabel] = React.useState('');
  const [newIcon, setNewIcon]   = React.useState(null);

  const MAX = 3; // multi-select cap

  // Sort cats by usage descending → top N visible by default.
  const sorted = window.sortCatsByUsage(cats);
  const TOP = 6;
  const topCats  = sorted.slice(0, TOP);
  const restCats = sorted.slice(TOP);
  const visibleCats = showMore ? sorted : topCats;

  const toggle = (id) => {
    const n = new Set(sel);
    if (n.has(id)) n.delete(id);
    else if (n.size < MAX) n.add(id);
    setSel(n);
  };

  const commitNew = () => {
    const label = newLabel.trim();
    if (!label) return;
    const c = window.makeNewCat(label, newIcon);
    const next = [c, ...cats];
    setCats(next);
    window.__cpCats = next;            // share with other screens this session
    const ns = new Set(sel);
    if (ns.size < MAX) ns.add(c.id);   // auto-select new one (if room)
    setSel(ns);
    setNewLabel(''); setNewIcon(null); setAddOpen(false);
  };

  return (
    <div style={{ padding: '6px 20px 24px' }}>
      <div style={{ fontSize: 12.5, color: T.ink2, padding: '6px 0 14px',
                    display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <span>최대 {MAX}개까지 선택할 수 있어요</span>
        <span style={{ fontSize: 11.5, fontWeight: 700, color: sel.size >= MAX ? T.danger : T.ink3 }}>
          {sel.size}/{MAX}
        </span>
      </div>

      <div style={{ fontSize: 11.5, fontWeight: 700, color: T.ink3,
                    letterSpacing: '0.08em', textTransform: 'uppercase',
                    marginBottom: 10 }}>분류</div>

      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 10 }}>
        {visibleCats.map(c => {
          const on = sel.has(c.id);
          const disabled = !on && sel.size >= MAX;
          return (
            <button key={c.id} onClick={() => toggle(c.id)} disabled={disabled}
              style={{
                padding: '9px 12px 9px 8px', borderRadius: 14,
                background: on ? T.accent : T.surface,
                color: on ? '#FFF' : T.ink2,
                border: on ? 'none' : `0.5px solid ${T.hairline}`,
                fontFamily: 'inherit', fontSize: 13, fontWeight: 600,
                cursor: disabled ? 'default' : 'pointer',
                opacity: disabled ? 0.4 : 1,
                display: 'inline-flex', gap: 8, alignItems: 'center',
              }}>
              {c.icon
                ? <span style={{ fontSize: 14 }}>{c.icon}</span>
                : <span style={{
                    width: 18, height: 18, borderRadius: 5,
                    background: on ? 'rgba(255,255,255,0.22)' : T.accentSoft,
                    color: on ? '#FFF' : T.accent,
                    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                    fontSize: 9.5, fontWeight: 800, letterSpacing: '-0.04em',
                  }}>{window.monogramOf(c.label)}</span>}
              {c.label}
              {c.kind === 'auto' && !on && (
                <span style={{ fontSize: 9, fontWeight: 700,
                               color: T.ink3, letterSpacing: '0.04em',
                               textTransform: 'uppercase' }}>AI</span>
              )}
            </button>
          );
        })}

        {/* + 새 카테고리 (inline opener) */}
        {!addOpen && (
          <button onClick={() => setAddOpen(true)} style={{
            padding: '9px 14px', borderRadius: 14,
            background: 'transparent',
            border: `1px dashed ${T.hairlineStrong}`,
            color: T.ink2, fontFamily: 'inherit',
            fontSize: 13, fontWeight: 600, cursor: 'pointer',
            display: 'inline-flex', gap: 4, alignItems: 'center',
          }}>
            <Icons.Plus size={14} color={T.ink2}/> 새 카테고리
          </button>
        )}
      </div>

      {/* See-more toggle */}
      {restCats.length > 0 && (
        <button onClick={() => setShowMore(s => !s)} style={{
          background: 'transparent', border: 'none', padding: '0 4px',
          fontFamily: 'inherit', fontSize: 12, fontWeight: 700,
          color: T.accent, cursor: 'pointer', marginBottom: 14,
          display: 'inline-flex', alignItems: 'center', gap: 4,
        }}>
          {showMore
            ? <React.Fragment><Icons.ChevronU size={12} color={T.accent}/> 자주 쓰는 것만 보기</React.Fragment>
            : <React.Fragment><Icons.ChevronD size={12} color={T.accent}/> {restCats.length}개 더 보기</React.Fragment>}
        </button>
      )}

      {/* Inline new-category form */}
      {addOpen && (
        <div style={{
          background: T.surface, borderRadius: 14,
          border: `0.5px solid ${T.hairlineStrong}`,
          padding: 14, marginTop: 4, marginBottom: 18,
        }}>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10,
          }}>
            <CatIcon icon={newIcon} label={newLabel || '?'} size={36}/>
            <input value={newLabel}
                   onChange={e => setNewLabel(e.target.value.slice(0, 16))}
                   placeholder="카테고리 이름"
                   autoFocus maxLength={16}
                   onKeyDown={(e) => { if (e.key === 'Enter') commitNew(); }}
                   style={{
                     flex: 1, height: 38, padding: '0 12px',
                     background: T.bg, border: `0.5px solid ${T.hairlineStrong}`,
                     borderRadius: 10, fontSize: 14, color: T.ink,
                     fontFamily: 'inherit', outline: 'none',
                     letterSpacing: '-0.01em',
                   }}/>
          </div>
          {/* Quick emoji picker (compact: first 16) */}
          <div style={{
            display: 'grid', gridTemplateColumns: 'repeat(8, 1fr)', gap: 4,
            marginBottom: 12,
          }}>
            <button onClick={() => setNewIcon(null)} style={{
              aspectRatio: '1/1', borderRadius: 8,
              background: newIcon === null ? T.accent : T.bg,
              color: newIcon === null ? '#FFF' : T.ink2,
              border: newIcon === null ? 'none' : `0.5px solid ${T.hairlineStrong}`,
              fontFamily: 'inherit', fontSize: 11, fontWeight: 700,
              cursor: 'pointer',
            }}>글자</button>
            {(window.MOCK_CAT_EMOJI || []).slice(0, 15).map(e => {
              const on = newIcon === e;
              return (
                <button key={e} onClick={() => setNewIcon(on ? null : e)} style={{
                  aspectRatio: '1/1', borderRadius: 8,
                  background: on ? T.accentSoft : T.bg,
                  border: on ? `1.5px solid ${T.accent}` : `0.5px solid ${T.hairline}`,
                  fontFamily: 'inherit', fontSize: 15, cursor: 'pointer',
                }}>{e}</button>
              );
            })}
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <Button kind="ghost" onClick={() => {
              setAddOpen(false); setNewLabel(''); setNewIcon(null);
            }} style={{ flex: 1, height: 40 }}>취소</Button>
            <Button kind="primary" disabled={!newLabel.trim()}
                    onClick={commitNew} style={{ flex: 2, height: 40 }}>추가</Button>
          </div>
        </div>
      )}

      {!addOpen && <div style={{ height: 14 }}/>}

      <Button kind="primary" fullWidth onClick={onClose}
              style={{ marginTop: 22, height: 52 }}>완료</Button>
    </div>
  );
}

Object.assign(window, { ScreenSeed });
