// Knowledge — search + filter chips + cards + file upload
// (audio → eBoo transcription · Word .docx → mammoth text extraction).

const EBOO_TOKEN = 'unmEbwr7mGrxQfZeWJXiMIa7NNq3UroK';
const EBOO_URL   = 'https://www.eboo.ir/api/ocr/getway';

async function ebooPost(fields) {
  const fd = new FormData();
  for (const [k, v] of Object.entries(fields)) fd.append(k, v);
  const res = await fetch(EBOO_URL, { method: 'POST', body: fd });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

// ── Word (.docx) text extraction ─────────────────────────────────────────────
// True only for OOXML .docx (mammoth can't read the legacy binary .doc format).
const isDocxFile = (file) =>
  /\.docx$/i.test(file.name) ||
  file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';

// Collapse the whitespace mammoth returns into tidy paragraphs.
const cleanDocText = (text) =>
  (text || '')
    .replace(/\r\n?/g, '\n')
    .split('\n').map(line => line.replace(/[ \t]+$/g, ''))
    .join('\n')
    .replace(/\n{3,}/g, '\n\n')
    .trim();

// Extract plain text from a .docx using the CDN-loaded mammoth library.
async function extractDocxText(file) {
  if (!window.mammoth || typeof window.mammoth.extractRawText !== 'function') {
    throw new Error('کتابخانهٔ پردازش ورد بارگذاری نشد. اتصال اینترنت را بررسی کن و دوباره امتحان کن.');
  }
  const arrayBuffer = await file.arrayBuffer();
  const result = await window.mammoth.extractRawText({ arrayBuffer });
  return cleanDocText(result?.value || '');
}

const knowledgeStyles = {
  scroll: { padding: '0 16px 220px', direction: 'rtl', height: '100%', overflow: 'auto' },

  searchWrap: {
    display: 'flex', alignItems: 'center', gap: 8,
    background: 'var(--surface)', border: '1px solid var(--c-border-xs)',
    borderRadius: 999, padding: '11px 16px', margin: '4px 0 14px',
    color: 'var(--ink-3)',
  },
  searchInput: {
    flex: 1, background: 'transparent', border: 'none', outline: 'none',
    font: "400 15px 'Estedad', sans-serif", color: 'var(--ink)', textAlign: 'right',
  },
  shortcut: {
    font: "500 11px 'Estedad', sans-serif",
    background: 'var(--paper-2)', color: 'var(--ink-3)',
    padding: '3px 7px', borderRadius: 6,
  },

  chipsRow: { display: 'flex', gap: 6, overflowX: 'auto', marginBottom: 14, paddingBottom: 4 },
  chip: {
    flex: 'none', font: "500 12px 'Estedad', sans-serif",
    padding: '7px 13px', borderRadius: 999,
    background: 'var(--paper-2)', color: 'var(--ink-2)',
    border: '1px solid var(--c-border-xs)', cursor: 'pointer',
  },
  chipActive: { background: 'var(--ink)', color: 'var(--paper)', borderColor: 'transparent' },

  sectionTitle: {
    font: "600 12px 'Estedad', sans-serif", color: 'var(--ink-3)',
    letterSpacing: '0.08em', textTransform: 'uppercase', margin: '16px 2px 10px',
  },

  card: {
    background: 'var(--surface)', border: '1px solid var(--c-border-xs)',
    borderRadius: 16, padding: 16, marginBottom: 10, boxShadow: 'var(--shadow-lift)', cursor: 'pointer',
  },
  head: { display: 'flex', alignItems: 'flex-start', gap: 12 },
  iconLeft: { width: 38, height: 38, borderRadius: 10, display: 'grid', placeItems: 'center', flex: 'none' },
  title: { font: "500 15px/1.4 'Estedad', sans-serif", color: 'var(--ink)' },
  body:  {
    font: "400 13.5px/1.6 'Estedad', sans-serif", color: 'var(--ink-2)', marginTop: 4,
    display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical',
    overflow: 'hidden', overflowWrap: 'anywhere',
  },
  footer: { display: 'flex', alignItems: 'center', gap: 6, marginTop: 10, flexWrap: 'wrap' },
  tag: {
    font: "500 11px 'Estedad', sans-serif",
    padding: '3px 8px', borderRadius: 999, background: 'var(--paper-2)', color: 'var(--ink-2)',
  },
  meta: { font: "500 11px 'Estedad', sans-serif", color: 'var(--ink-3)' },
  dot: { width: 3, height: 3, borderRadius: '50%', background: 'var(--ink-4)' },

  emptyState: {
    textAlign: 'center', padding: '40px 20px',
    font: "400 14px 'Estedad', sans-serif", color: 'var(--ink-3)',
  },

  // Upload sheet
  overlay: {
    position: 'fixed', inset: 0, background: 'rgba(27,26,23,0.45)',
    backdropFilter: 'blur(4px)', WebkitBackdropFilter: 'blur(4px)',
    zIndex: 200, display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
    direction: 'rtl',
  },
  sheet: {
    width: '100%', maxWidth: 600,
    background: 'var(--paper)', borderRadius: '22px 22px 0 0',
    padding: '0 0 env(safe-area-inset-bottom)',
    boxShadow: '0 -8px 32px rgba(0,0,0,0.10)',
    maxHeight: '85vh', display: 'flex', flexDirection: 'column',
  },
  sheetHandle: {
    width: 36, height: 4, borderRadius: 99,
    background: 'var(--c-inactive)', margin: '12px auto 0',
  },
  sheetHeader: {
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    padding: '14px 20px 10px',
    borderBottom: '1px solid var(--c-border-xs)',
  },
  sheetTitle: { font: "600 17px 'Estedad', sans-serif", color: 'var(--ink)' },
  sheetClose: {
    width: 32, height: 32, borderRadius: 999, border: 'none', cursor: 'pointer',
    background: 'var(--paper-2)', color: 'var(--ink-2)',
    display: 'grid', placeItems: 'center',
  },
  sheetBody: { flex: 1, overflow: 'auto', padding: '20px 20px 24px' },

  filePick: {
    display: 'flex', flexDirection: 'column', alignItems: 'center',
    gap: 12, padding: '28px 20px', borderRadius: 16,
    border: '2px dashed rgba(42,157,143,0.25)',
    background: 'var(--firoozeh-soft)', cursor: 'pointer',
    textAlign: 'center',
  },
  filePickIcon: {
    width: 52, height: 52, borderRadius: 999,
    background: 'var(--firoozeh)', color: '#fff',
    display: 'grid', placeItems: 'center',
  },
  filePickLabel: { font: "500 15px 'Estedad', sans-serif", color: 'var(--firoozeh-deep)' },
  filePickSub:   { font: "400 12.5px 'Estedad', sans-serif", color: 'var(--firoozeh-deep)', opacity: 0.7 },

  statusCard: {
    background: 'var(--surface)', border: '1px solid var(--c-border-xs)',
    borderRadius: 14, padding: '16px 18px', marginBottom: 16,
  },
  statusRow: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 },
  statusLabel: { font: "500 14px 'Estedad', sans-serif", color: 'var(--ink)', flex: 1 },
  progressBar: { height: 6, borderRadius: 99, background: 'var(--c-tint-sm)', overflow: 'hidden', marginBottom: 6 },
  progressFill: { height: '100%', background: 'var(--firoozeh)', borderRadius: 99, transition: 'width 400ms ease-out' },
  progressTxt: { font: "400 12px 'Estedad', sans-serif", color: 'var(--ink-3)', textAlign: 'left' },

  transcriptBox: {
    background: 'var(--paper-2)', borderRadius: 12,
    padding: '14px 16px', minHeight: 100, maxHeight: 220, overflowY: 'auto',
    font: "400 14px/1.8 'Estedad', sans-serif", color: 'var(--ink)',
    direction: 'rtl', textAlign: 'right', marginBottom: 16,
    border: '1px solid var(--c-border-xs)',
  },

  saveBtn: {
    width: '100%', padding: '14px', borderRadius: 999, border: 'none', cursor: 'pointer',
    background: 'var(--firoozeh)', color: '#fff',
    font: "600 15px 'Estedad', sans-serif",
  },
  saveBtnDisabled: { background: 'var(--ink-4)', cursor: 'not-allowed' },

  errBox: {
    background: 'rgba(178,58,72,0.08)', border: '1px solid rgba(178,58,72,0.18)',
    borderRadius: 12, padding: '12px 16px',
    font: "400 13.5px 'Estedad', sans-serif", color: 'var(--garnet)',
    direction: 'rtl', marginBottom: 16,
  },
};

const kindConfig = {
  'note':     { label: 'یادداشت', icon: 'Doc',      bg: 'var(--paper-2)',         fg: 'var(--ink-2)' },
  'meeting':  { label: 'جلسه',    icon: 'Calendar', bg: 'var(--firoozeh-soft)',   fg: 'var(--firoozeh-deep)' },
  'learning': { label: 'یادگیری', icon: 'Book',     bg: 'var(--saffron-soft)',    fg: 'var(--saffron)' },
  'doc':      { label: 'سند',     icon: 'Doc',      bg: 'rgba(88,166,88,0.13)',   fg: '#2E6B2E' },
  'personal': { label: 'شخصی',   icon: 'Heart',    bg: 'var(--garnet-soft)',     fg: 'var(--garnet)' },
};

function KCard({ card, onOpen, allCards = [], id, highlightId }) {
  const { Icons } = window;
  const kc = kindConfig[card.kind] || kindConfig['note'];
  const I = Icons[card.icon] || Icons[kc.icon] || Icons.Hash;
  const KIcon = Icons[kc.icon];
  const linkedCards = (card.linkedIds || []).map(id => allCards.find(k => k.id === id)).filter(Boolean);
  const isHl = highlightId === card.id;
  return (
    <div id={id} className="sb-animated-card" style={{ ...knowledgeStyles.card, cursor: onOpen ? 'pointer' : 'default', ...(isHl ? { boxShadow: '0 0 0 2px var(--firoozeh)', transition: 'box-shadow 0.3s' } : {}) }} onClick={onOpen ? () => onOpen(card.id) : undefined}>
      <div style={knowledgeStyles.head}>
        <div style={{ ...knowledgeStyles.iconLeft, background: kc.bg, color: kc.fg }}>
          <I size={18} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={knowledgeStyles.title}>{card.title}</div>
          <div style={knowledgeStyles.body}>{card.body}</div>
          <div style={knowledgeStyles.footer}>
            <span style={{
              ...knowledgeStyles.tag,
              background: kc.bg, color: kc.fg,
              display: 'inline-flex', alignItems: 'center', gap: 4,
            }}>
              {KIcon && <KIcon size={11} />} {kc.label}
            </span>
            {(card.tags || []).map(t => <span key={t} style={knowledgeStyles.tag}>{t}</span>)}
            {card.meta && <><span style={knowledgeStyles.dot} /><span style={knowledgeStyles.meta}>{card.meta}</span></>}
          </div>
          {linkedCards.length > 0 && (
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 8 }}>
              {linkedCards.map(lc => (
                <span key={lc.id} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '3px 8px', background: 'var(--firoozeh-soft)', color: 'var(--firoozeh-deep)', borderRadius: 999, font: "400 11px 'Estedad', sans-serif" }}>
                  <Icons.Link size={10} /> {lc.title.slice(0, 20)}
                </span>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Knowledge read sheet (comfortable full-text view; edit is secondary) ─────
function KnowledgeReadSheet({ card, onClose, onEdit, allCards = [], onOpenCard }) {
  const { Icons } = window;
  const kc = kindConfig[card.kind] || kindConfig['note'];
  const KIcon = Icons[kc.icon] || Icons.Doc;
  const linked = (card.linkedIds || []).map(id => allCards.find(k => k.id === id)).filter(Boolean);
  return (
    <div style={knowledgeStyles.overlay} onClick={onClose}>
      <div style={knowledgeStyles.sheet} onClick={e => e.stopPropagation()}>
        <div style={knowledgeStyles.sheetHandle} />
        <div style={knowledgeStyles.sheetHeader}>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '5px 11px', borderRadius: 999, background: kc.bg, color: kc.fg, font: "500 12px 'Estedad', sans-serif" }}>
            <KIcon size={13} /> {kc.label}
          </span>
          <button style={knowledgeStyles.sheetClose} onClick={onClose} aria-label="بستن"><Icons.X size={16} /></button>
        </div>

        <div style={knowledgeStyles.sheetBody}>
          <div style={{ font: "700 20px/1.5 'Estedad', sans-serif", color: 'var(--ink)', direction: 'rtl', marginBottom: 6 }}>
            {card.title}
          </div>
          {card.meta && (
            <div style={{ font: "400 12px 'Estedad', sans-serif", color: 'var(--ink-3)', direction: 'rtl', marginBottom: 16 }}>
              {card.meta}
            </div>
          )}
          {/* Full body — comfortable reading: large text, airy leading, preserves
              line breaks, selectable, wraps long unbroken strings */}
          <div style={{
            font: "400 16px/2 'Estedad', sans-serif", color: 'var(--ink)', direction: 'rtl',
            whiteSpace: 'pre-wrap', overflowWrap: 'anywhere', userSelect: 'text',
          }}>
            {(card.body || '').trim() || '—'}
          </div>

          {(card.tags || []).length > 0 && (
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 18, direction: 'rtl' }}>
              {card.tags.map(t => <span key={t} style={knowledgeStyles.tag}>{t}</span>)}
            </div>
          )}

          {linked.length > 0 && (
            <div style={{ marginTop: 18, direction: 'rtl' }}>
              <div style={{ font: "500 12px 'Estedad', sans-serif", color: 'var(--ink-3)', marginBottom: 8 }}>کارت‌های مرتبط</div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                {linked.map(lc => (
                  <button key={lc.id}
                    onClick={() => onOpenCard && onOpenCard(lc.id)}
                    style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '6px 11px', background: 'var(--firoozeh-soft)', color: 'var(--firoozeh-deep)', borderRadius: 999, font: "500 12px 'Estedad', sans-serif", border: 'none', cursor: 'pointer' }}>
                    <Icons.Link size={11} /> {lc.title}
                  </button>
                ))}
              </div>
            </div>
          )}
        </div>

        {onEdit && (
          <div style={{ padding: '12px 20px calc(16px + env(safe-area-inset-bottom))', borderTop: '1px solid var(--c-border-xs)' }}>
            <button onClick={onEdit} style={{ width: '100%', padding: '13px', borderRadius: 12, border: '1px solid var(--firoozeh)', background: 'transparent', color: 'var(--firoozeh-deep)', cursor: 'pointer', font: "600 14px 'Estedad', sans-serif", display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}>
              <Icons.Edit size={15} /> ویرایش کارت
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Knowledge edit sheet ─────────────────────────────────────────────────────
function KnowledgeEditSheet({ card, onClose, onUpdate, onDelete, allCards = [] }) {
  const { Icons } = window;
  const [kind,  setKind]  = React.useState(card.kind || 'note');
  const [title, setTitle] = React.useState(card.title || '');
  const [body,  setBody]  = React.useState(card.body || '');
  const [tagsText, setTagsText] = React.useState((card.tags || []).join(' '));
  const [linkedIds, setLinkedIds] = React.useState(card.linkedIds || []);
  const [linkSearch, setLinkSearch] = React.useState('');
  const [confirmDel, setConfirmDel] = React.useState(false);

  const filteredCards = allCards.filter(k =>
    k.id !== card.id &&
    (!linkSearch.trim() || k.title.toLowerCase().includes(linkSearch.toLowerCase()))
  );

  const inputStyle = {
    width: '100%', boxSizing: 'border-box', background: 'var(--surface)',
    border: '1px solid var(--c-border-sm)', borderRadius: 12, padding: '12px 14px',
    font: "400 15px/1.6 'Estedad', sans-serif", color: 'var(--ink)',
    direction: 'rtl', textAlign: 'right', outline: 'none', marginBottom: 16,
  };
  const labelStyle = { display: 'block', font: "500 12px 'Estedad', sans-serif", color: 'var(--ink-3)', marginBottom: 8 };

  const save = () => {
    if (!title.trim()) return;
    const tags = tagsText.trim() ? tagsText.trim().split(/[\s،,]+/).filter(Boolean) : [];
    onUpdate(card.id, { kind, icon: (kindConfig[kind] || kindConfig.note).icon, title: title.trim(), body: body.trim(), tags, linkedIds });
    onClose();
  };

  return (
    <div style={knowledgeStyles.overlay} onClick={onClose}>
      <div style={knowledgeStyles.sheet} onClick={e => e.stopPropagation()}>
        <div style={knowledgeStyles.sheetHandle} />
        <div style={knowledgeStyles.sheetHeader}>
          <span style={knowledgeStyles.sheetTitle}>ویرایش کارت</span>
          <button style={knowledgeStyles.sheetClose} onClick={onClose}><Icons.X size={16} /></button>
        </div>
        <div style={knowledgeStyles.sheetBody}>
          <span style={labelStyle}>نوع</span>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 16 }}>
            {Object.entries(kindConfig).map(([k, kc]) => {
              const KIcon = Icons[kc.icon];
              const on = kind === k;
              return (
                <button key={k}
                  style={{ ...knowledgeStyles.chip, display: 'inline-flex', alignItems: 'center', gap: 5,
                    ...(on ? { background: kc.bg, color: kc.fg, borderColor: 'transparent' } : {}) }}
                  onClick={() => setKind(k)}
                >{KIcon && <KIcon size={12} />}{kc.label}</button>
              );
            })}
          </div>

          <span style={labelStyle}>عنوان</span>
          <input style={inputStyle} value={title} onChange={e => setTitle(e.target.value)} placeholder="عنوان کارت…" />

          <span style={labelStyle}>متن</span>
          <textarea style={{ ...inputStyle, minHeight: 110, resize: 'none' }} value={body} onChange={e => setBody(e.target.value)} placeholder="متن یا توضیح…" rows={5} />

          <span style={labelStyle}>تگ‌ها (با فاصله جدا کن)</span>
          <input style={inputStyle} value={tagsText} onChange={e => setTagsText(e.target.value)} placeholder="#کار #ایده" />

          {allCards.length > 0 && (
            <>
              <span style={labelStyle}>کارت‌های مرتبط</span>
              <input
                style={{ ...inputStyle, marginBottom: 8 }}
                value={linkSearch}
                onChange={e => setLinkSearch(e.target.value)}
                placeholder="جستجو برای لینک…"
              />
              <div style={{ maxHeight: 140, overflowY: 'auto', marginBottom: 16, borderRadius: 10, border: '1px solid var(--c-border-xs)' }}>
                {filteredCards.slice(0, 20).map(k => {
                  const on = linkedIds.includes(k.id);
                  return (
                    <button key={k.id}
                      onClick={() => setLinkedIds(prev => on ? prev.filter(x => x !== k.id) : [...prev, k.id])}
                      style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 10, padding: '9px 12px', background: on ? 'var(--firoozeh-soft)' : 'transparent', border: 'none', borderBottom: '1px solid var(--c-border-xs)', cursor: 'pointer', direction: 'rtl', textAlign: 'right' }}
                    >
                      <span style={{ width: 18, height: 18, borderRadius: '50%', border: `2px solid ${on ? 'var(--firoozeh)' : 'var(--c-border-md)'}`, background: on ? 'var(--firoozeh)' : 'transparent', flexShrink: 0, display: 'grid', placeItems: 'center' }}>
                        {on && <Icons.Check size={10} style={{ color: '#fff' }} />}
                      </span>
                      <span style={{ font: "400 13px 'Estedad', sans-serif", color: 'var(--ink)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{k.title}</span>
                    </button>
                  );
                })}
                {filteredCards.length === 0 && <div style={{ padding: '12px', color: 'var(--ink-3)', font: "400 13px 'Estedad', sans-serif", textAlign: 'center' }}>نتیجه‌ای نیست</div>}
              </div>
              {linkedIds.length > 0 && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 16 }}>
                  {linkedIds.map(id => {
                    const linked = allCards.find(k => k.id === id);
                    if (!linked) return null;
                    return (
                      <span key={id} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '4px 10px', background: 'var(--firoozeh-soft)', color: 'var(--firoozeh-deep)', borderRadius: 999, font: "500 12px 'Estedad', sans-serif" }}>
                        <Icons.Link size={11} /> {linked.title.slice(0, 20)}
                        <button onClick={() => setLinkedIds(prev => prev.filter(x => x !== id))} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 0, color: 'var(--firoozeh-deep)', display: 'flex' }}>
                          <Icons.X size={11} />
                        </button>
                      </span>
                    );
                  })}
                </div>
              )}
            </>
          )}

          <button style={{ ...knowledgeStyles.saveBtn, ...(title.trim() ? {} : knowledgeStyles.saveBtnDisabled) }}
            onClick={title.trim() ? save : undefined}>ذخیره تغییرات</button>

          <button
            style={{
              width: '100%', marginTop: 12, padding: '13px', borderRadius: 12, cursor: 'pointer',
              background: confirmDel ? '#B41E1E' : 'rgba(178,58,72,0.06)',
              border: '1px solid rgba(178,58,72,0.18)',
              color: confirmDel ? '#fff' : '#B41E1E',
              font: "500 14px 'Estedad', sans-serif",
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            }}
            onClick={() => { if (confirmDel) { onDelete(card.id); onClose(); } else setConfirmDel(true); }}
          >
            <Icons.Trash size={16} /> {confirmDel ? 'مطمئنی؟ برای حذف دوباره بزن' : 'حذف کارت'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Manual add sheet (R01) ───────────────────────────────────────────────────
function AddKnowledgeSheet({ open, onClose, onAdd }) {
  const { Icons } = window;
  const [kind, setKind]         = React.useState('note');
  const [title, setTitle]       = React.useState('');
  const [body, setBody]         = React.useState('');
  const [tagsText, setTagsText] = React.useState('');

  React.useEffect(() => {
    if (!open) { setKind('note'); setTitle(''); setBody(''); setTagsText(''); }
  }, [open]);

  const save = () => {
    if (!title.trim()) return;
    const tags = tagsText.trim() ? tagsText.trim().split(/[\s،,]+/).filter(Boolean) : [];
    const kc = kindConfig[kind] || kindConfig.note;
    const time = new Intl.DateTimeFormat('fa-IR', { hour: '2-digit', minute: '2-digit' }).format(new Date());
    onAdd({ id: 'k-' + Date.now(), kind, icon: kc.icon, title: title.trim(), body: body.trim(), tags, meta: `دستی · ${time}` });
    onClose();
  };

  if (!open) return null;

  const inputStyle = {
    width: '100%', boxSizing: 'border-box', background: 'var(--surface)',
    border: '1px solid var(--c-border-sm)', borderRadius: 12, padding: '12px 14px',
    font: "400 15px/1.6 'Estedad', sans-serif", color: 'var(--ink)',
    direction: 'rtl', textAlign: 'right', outline: 'none', marginBottom: 16,
  };
  const lbl = { display: 'block', font: "500 12px 'Estedad', sans-serif", color: 'var(--ink-3)', marginBottom: 8 };

  return (
    <div style={knowledgeStyles.overlay} onClick={onClose}>
      <div style={knowledgeStyles.sheet} onClick={e => e.stopPropagation()}>
        <div style={knowledgeStyles.sheetHandle} />
        <div style={knowledgeStyles.sheetHeader}>
          <span style={knowledgeStyles.sheetTitle}>کارت دانش جدید</span>
          <button style={knowledgeStyles.sheetClose} onClick={onClose}><Icons.X size={16} /></button>
        </div>
        <div style={knowledgeStyles.sheetBody}>
          <span style={lbl}>نوع</span>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 16 }}>
            {Object.entries(kindConfig).map(([k, kc]) => {
              const KIcon = Icons[kc.icon];
              const on = kind === k;
              return (
                <button key={k} style={{ ...knowledgeStyles.chip, display: 'inline-flex', alignItems: 'center', gap: 5,
                  ...(on ? { background: kc.bg, color: kc.fg, borderColor: 'transparent' } : {}) }}
                  onClick={() => setKind(k)}>{KIcon && <KIcon size={12} />}{kc.label}</button>
              );
            })}
          </div>
          <span style={lbl}>عنوان</span>
          <input style={inputStyle} value={title} onChange={e => setTitle(e.target.value)} placeholder="عنوان کارت دانش…" />
          <span style={lbl}>متن</span>
          <textarea style={{ ...inputStyle, minHeight: 110, resize: 'none' }} value={body} onChange={e => setBody(e.target.value)} placeholder="متن، توضیح یا یادداشت…" rows={4} />
          <span style={lbl}>تگ‌ها (با فاصله جدا کن)</span>
          <input style={inputStyle} value={tagsText} onChange={e => setTagsText(e.target.value)} placeholder="#کار #ایده" />
          <button style={{ ...knowledgeStyles.saveBtn, ...(title.trim() ? {} : knowledgeStyles.saveBtnDisabled) }}
            onClick={title.trim() ? save : undefined}>ذخیره در حافظه</button>
        </div>
      </div>
    </div>
  );
}

// ── Upload sheet (audio via eBoo · Word .docx via mammoth) ────────────────────
const UPLOAD_MODES = {
  audio: {
    sheetTitle: 'افزودن فایل صوتی',
    pickLabel:  'انتخاب فایل صوتی',
    pickSub:    'mp3 · wav · m4a · ogg · flac پشتیبانی می‌شود',
    icon:       'Mic',
    accept:     'audio/*',
    maxBytes:   25 * 1024 * 1024,
    maxLabel:   '۲۵ مگابایت',
    defaultKind:'meeting',
    kinds:      ['meeting', 'learning', 'note'],
    tag:        '#صدا',
    metaPrefix: 'از فایل صوتی',
    fallbackTitle: 'فایل صوتی',
  },
  doc: {
    sheetTitle: 'افزودن سند ورد',
    pickLabel:  'انتخاب سند ورد',
    pickSub:    'فقط فرمت .docx پشتیبانی می‌شود',
    icon:       'Doc',
    accept:     '.docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    maxBytes:   15 * 1024 * 1024,
    maxLabel:   '۱۵ مگابایت',
    defaultKind:'doc',
    kinds:      ['doc', 'note', 'learning', 'meeting'],
    tag:        '#سند',
    metaPrefix: 'از سند ورد',
    fallbackTitle: 'سند ورد',
  },
};

function UploadSheet({ open, mode = 'audio', onClose, onAdd }) {
  const { Icons } = window;
  const cfg = UPLOAD_MODES[mode] || UPLOAD_MODES.audio;
  const ModeIcon = Icons[cfg.icon] || Icons.Doc;
  const [phase, setPhase]         = React.useState('idle');   // idle|uploading|converting|polling|reading|done|error
  const [fileName, setFileName]   = React.useState('');
  const [progress, setProgress]   = React.useState(0);
  const [transcript, setTranscript] = React.useState('');
  const [errMsg, setErrMsg]       = React.useState('');
  const [saveKind, setSaveKind]   = React.useState(cfg.defaultKind);
  const fileRef    = React.useRef(null);
  const pollTimer  = React.useRef(null);
  const fileObj    = React.useRef(null);
  const abortCtrl  = React.useRef(null);

  const stopPolling = () => {
    if (pollTimer.current) { clearTimeout(pollTimer.current); pollTimer.current = null; }
    if (abortCtrl.current) { abortCtrl.current.abort(); abortCtrl.current = null; }
  };

  const reset = () => {
    stopPolling();
    setPhase('idle'); setFileName(''); setProgress(0); setTranscript(''); setErrMsg(''); setSaveKind(cfg.defaultKind);
    fileObj.current = null;
  };

  const handleClose = () => { reset(); onClose(); };

  React.useEffect(() => { if (!open) reset(); }, [open]);

  // Audio → eBoo: upload, convert, poll for the transcript
  const startUpload = async (file) => {
    fileObj.current = file;
    setFileName(file.name.replace(/\.[^.]+$/, ''));
    setPhase('uploading');
    setErrMsg('');
    setProgress(0);
    try {
      // Step 1: upload
      const fd1 = new FormData();
      fd1.append('token', EBOO_TOKEN);
      fd1.append('command', 'addfile');
      fd1.append('filehandle', file);
      const res1 = await fetch(EBOO_URL, { method: 'POST', body: fd1 });
      const d1 = await res1.json();
      if (d1.Status !== 'Done') throw new Error(d1.Status || 'خطا در آپلود');
      const fileToken = d1.FileToken;

      // Step 2: start convert
      setPhase('converting');
      const fd2 = new FormData();
      fd2.append('token', EBOO_TOKEN);
      fd2.append('command', 'convert');
      fd2.append('filetoken', fileToken);
      fd2.append('language', 'fa');
      await fetch(EBOO_URL, { method: 'POST', body: fd2 });

      // Step 3: poll with exponential backoff (1s → 2s → 4s → 8s, capped)
      setPhase('polling');
      let delay = 1000;
      const poll = async () => {
        const ctrl = new AbortController();
        abortCtrl.current = ctrl;
        try {
          const fd3 = new FormData();
          fd3.append('token', EBOO_TOKEN);
          fd3.append('command', 'checkconvert');
          fd3.append('filetoken', fileToken);
          const res3 = await fetch(EBOO_URL, { method: 'POST', body: fd3, signal: ctrl.signal });
          const d3 = await res3.json();
          if (d3.Output) setTranscript(d3.Output);
          if (d3.Progress) setProgress(parseFloat(d3.Progress) || 0);
          if (d3.Status === 'Done' || parseFloat(d3.Progress) >= 100) {
            stopPolling();
            setProgress(100);
            setPhase('done');
            return;
          }
        } catch (err) {
          if (err.name === 'AbortError') return; // sheet closed — stop silently
          /* keep polling on transient errors */
        }
        delay = Math.min(delay * 2, 8000);
        pollTimer.current = setTimeout(poll, delay);
      };
      pollTimer.current = setTimeout(poll, delay);

    } catch (e) {
      stopPolling();
      setErrMsg(String(e.message));
      setPhase('error');
    }
  };

  // Word (.docx) → mammoth: extract text locally in the browser (fast, one step)
  const startDoc = async (file) => {
    fileObj.current = file;
    setFileName(file.name.replace(/\.[^.]+$/, ''));
    setErrMsg('');
    setProgress(0);
    setPhase('reading');
    try {
      const text = await extractDocxText(file);
      if (!text) throw new Error('متنی در این سند پیدا نشد.');
      setTranscript(text);
      setProgress(100);
      setPhase('done');
    } catch (e) {
      setErrMsg(String(e.message || e));
      setPhase('error');
    }
  };

  const handleFileChange = (e) => {
    const f = e.target.files?.[0];
    if (e.target) e.target.value = ''; // allow re-picking the same file after an error
    if (!f) return;
    if (f.size > cfg.maxBytes) {
      setErrMsg(`حجم فایل بیش از ${cfg.maxLabel} است. لطفاً فایل کوچک‌تری انتخاب کن.`);
      setPhase('error');
      return;
    }
    if (mode === 'doc') {
      if (!isDocxFile(f)) {
        const isLegacyDoc = /\.doc$/i.test(f.name);
        setErrMsg(isLegacyDoc
          ? 'فرمت قدیمی .doc پشتیبانی نمی‌شود. لطفاً در ورد فایل را با فرمت .docx ذخیره کن.'
          : 'فقط فایل ورد با فرمت .docx پشتیبانی می‌شود.');
        setPhase('error');
        return;
      }
      startDoc(f);
    } else {
      const isAudio = /^audio\//.test(f.type) || /\.(mp3|wav|m4a|ogg|aac|flac|opus|wma|amr)$/i.test(f.name);
      if (!isAudio) {
        setErrMsg('فقط فایل صوتی پشتیبانی می‌شود. لطفاً یک فایل صدا انتخاب کن.');
        setPhase('error');
        return;
      }
      startUpload(f);
    }
  };

  const handleSave = () => {
    const time = new Intl.DateTimeFormat('fa-IR', { hour: '2-digit', minute: '2-digit' }).format(new Date());
    const kc = kindConfig[saveKind] || kindConfig['note'];
    onAdd({
      id:    'k-' + Date.now(),
      kind:  saveKind,
      icon:  kc.icon,
      title: fileName || cfg.fallbackTitle,
      body:  transcript,
      tags:  [cfg.tag],
      meta:  `${cfg.metaPrefix} · ${time}`,
    });
    handleClose();
  };

  if (!open) return null;

  const phaseLabel = {
    uploading:  'در حال آپلود فایل…',
    converting: 'شروع تبدیل…',
    polling:    `در حال رونویسی… ${progress > 0 ? progress.toFixed(0) + '٪' : ''}`,
    reading:    'در حال خواندن سند…',
    done:       mode === 'doc' ? 'متن سند آماده شد' : 'رونویسی کامل شد',
    error:      'خطا',
  }[phase] || '';

  const busy = phase === 'uploading' || phase === 'converting' || phase === 'polling' || phase === 'reading';

  return (
    <div style={knowledgeStyles.overlay} onClick={handleClose}>
      <div style={knowledgeStyles.sheet} onClick={e => e.stopPropagation()}>
        <div style={knowledgeStyles.sheetHandle} />
        <div style={knowledgeStyles.sheetHeader}>
          <span style={knowledgeStyles.sheetTitle}>{cfg.sheetTitle}</span>
          <button style={knowledgeStyles.sheetClose} onClick={handleClose} aria-label="بستن">
            <Icons.X size={16} />
          </button>
        </div>

        <div style={knowledgeStyles.sheetBody}>

          {/* Idle: file picker */}
          {phase === 'idle' && (
            <div style={knowledgeStyles.filePick} onClick={() => fileRef.current?.click()}>
              <div style={knowledgeStyles.filePickIcon}><ModeIcon size={24} /></div>
              <div style={knowledgeStyles.filePickLabel}>{cfg.pickLabel}</div>
              <div style={knowledgeStyles.filePickSub}>{cfg.pickSub}</div>
            </div>
          )}

          <input
            ref={fileRef}
            type="file"
            accept={cfg.accept}
            style={{ display: 'none' }}
            onChange={handleFileChange}
          />

          {/* Status card while processing */}
          {(busy || phase === 'done') && (
            <div style={knowledgeStyles.statusCard}>
              <div style={knowledgeStyles.statusRow}>
                <div style={{
                  width: 34, height: 34, borderRadius: 999, flex: 'none',
                  background: phase === 'done' ? 'var(--moss-soft)' : 'var(--firoozeh-soft)',
                  color: phase === 'done' ? 'var(--moss)' : 'var(--firoozeh)',
                  display: 'grid', placeItems: 'center',
                }}>
                  {phase === 'done' ? <Icons.CheckCircle size={16} /> : <ModeIcon size={16} />}
                </div>
                <span style={knowledgeStyles.statusLabel}>{fileName || cfg.fallbackTitle}</span>
                <span style={{ font: "500 12px 'Estedad', sans-serif", color: phase === 'done' ? 'var(--moss)' : 'var(--firoozeh-deep)' }}>
                  {phaseLabel}
                </span>
              </div>
              <div className="sb-progress-track" style={knowledgeStyles.progressBar}>
                <div className="sb-progress-bar" style={{ ...knowledgeStyles.progressFill, width: `${busy && progress === 0 ? 5 : progress}%` }} />
              </div>
              <div style={knowledgeStyles.progressTxt}>{progress.toFixed(0)}٪</div>
            </div>
          )}

          {/* Error */}
          {phase === 'error' && (
            <>
              <div style={knowledgeStyles.errBox}>
                خطا: {errMsg}
              </div>
              <div style={knowledgeStyles.filePick} onClick={() => fileRef.current?.click()}>
                <div style={knowledgeStyles.filePickIcon}><ModeIcon size={24} /></div>
                <div style={knowledgeStyles.filePickLabel}>دوباره امتحان کن</div>
              </div>
            </>
          )}

          {/* Transcript / document text */}
          {(transcript || phase === 'done') && (
            <div style={knowledgeStyles.transcriptBox}>
              {transcript || '…'}
            </div>
          )}

          {/* Kind picker + Save */}
          {phase === 'done' && transcript && (
            <>
              <div style={{ marginBottom: 14 }}>
                <div style={{ font: "500 12px 'Estedad', sans-serif", color: 'var(--ink-3)', marginBottom: 10, direction: 'rtl' }}>
                  نوع محتوا
                </div>
                <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', direction: 'rtl' }}>
                  {cfg.kinds.map(k => {
                    const kc = kindConfig[k];
                    const KIcon = Icons[kc.icon];
                    const active = saveKind === k;
                    return (
                      <button key={k}
                        style={{
                          display: 'inline-flex', alignItems: 'center', gap: 6,
                          padding: '7px 14px', borderRadius: 999,
                          font: "500 13px 'Estedad', sans-serif",
                          border: '1px solid var(--c-border-sm)',
                          background: active ? kc.bg : 'var(--paper-2)',
                          color: active ? kc.fg : 'var(--ink-2)',
                          cursor: 'pointer', transition: 'all 100ms',
                          borderColor: active ? 'transparent' : undefined,
                        }}
                        onClick={() => setSaveKind(k)}
                      >
                        <KIcon size={14} /> {kc.label}
                      </button>
                    );
                  })}
                </div>
              </div>
              <button style={knowledgeStyles.saveBtn} onClick={handleSave}>
                ذخیره در حافظه
              </button>
            </>
          )}

          {busy && mode === 'audio' && (
            <div style={{ textAlign: 'center', font: "400 12.5px 'Estedad', sans-serif", color: 'var(--ink-3)', marginTop: 12 }}>
              این فرایند ممکن است چند دقیقه طول بکشد
            </div>
          )}

        </div>
      </div>
    </div>
  );
}

// ── Main Knowledge screen ────────────────────────────────────────────────────
function Knowledge({ knowledge, isDesktop, addOpen, onAddClose, onAdd,
                     onUpdate, onDelete,
                     conversations, onStar, onDeleteConv, openConvId, onConvOpened, highlightId }) {
  const { Icons } = window;
  const [seg, setSeg]       = React.useState('knowledge');
  const [filter, setFilter] = React.useState('all');
  const [tagFilter, setTagFilter] = React.useState(null); // PRD-008
  const [showAllTags, setShowAllTags] = React.useState(false);
  const [sortBy, setSortBy] = React.useState('newest');
  const [q, setQ] = React.useState('');
  const [editId, setEditId] = React.useState(null);
  const [viewId, setViewId] = React.useState(null); // read view (tap a card)
  const [showCount, setShowCount] = React.useState(20);
  const [addMode, setAddMode] = React.useState(null); // null|'choice'|'audio'|'doc'|'manual'
  const editCard = editId ? knowledge.find(k => k.id === editId) : null;
  const viewCard = viewId ? knowledge.find(k => k.id === viewId) : null;

  React.useEffect(() => {
    if (addOpen) setAddMode('choice');
    else setAddMode(null);
  }, [addOpen]);

  React.useEffect(() => {
    if (!highlightId) return;
    setSeg('knowledge');
    setTimeout(() => {
      const el = document.getElementById('know-item-' + highlightId);
      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }, 80);
  }, [highlightId]);

  const closeAddMode = () => { setAddMode(null); onAddClose?.(); };

  const filters = [
    { key: 'all',      label: 'همه' },
    { key: 'note',     label: 'یادداشت' },
    { key: 'meeting',  label: 'جلسه' },
    { key: 'learning', label: 'یادگیری' },
    { key: 'doc',      label: 'سند' },
    { key: 'personal', label: 'شخصی' },
  ];

  // PRD-008: tags across all cards, by frequency desc
  const tagCounts = {};
  knowledge.forEach(k => (k.tags || []).forEach(t => { tagCounts[t] = (tagCounts[t] || 0) + 1; }));
  const allTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);

  const rawItems = knowledge.filter(k => {
    if (filter !== 'all' && k.kind !== filter) return false;
    if (tagFilter && !(k.tags || []).includes(tagFilter)) return false; // AND with kind
    if (!q.trim()) return true;
    const hay = [k.title, k.body, ...(k.tags || []), k.meta || ''].join(' ').toLowerCase();
    return q.trim().toLowerCase().split(/\s+/).every(w => hay.includes(w));
  });

  const items = React.useMemo(() => {
    if (sortBy === 'oldest') return rawItems.slice().reverse();
    if (sortBy === 'alpha') return rawItems.slice().sort((a, b) => a.title.localeCompare(b.title, 'fa'));
    if (sortBy === 'type') return rawItems.slice().sort((a, b) => (a.kind || '').localeCompare(b.kind || ''));
    return rawItems; // newest
  }, [rawItems, sortBy]);

  React.useEffect(() => { setShowCount(20); }, [filter, q, sortBy]);

  const visibleItems = items.slice(0, showCount);
  const recent = visibleItems.slice(0, 2);
  const older  = visibleItems.slice(2);

  const hPad = isDesktop ? '0 24px' : '0 16px';
  const segWrap = { display:'flex', background:'var(--paper-2)', borderRadius:12, padding:3, gap:3 };
  const segBtn  = { flex:1, padding:'9px', borderRadius:10, border:'none', cursor:'pointer', font:"600 13px 'Estedad', sans-serif", background:'transparent', color:'var(--ink-3)', transition:'all 140ms' };
  const segOn   = { background:'var(--surface)', color:'var(--ink)', boxShadow:'0 1px 4px rgba(0,0,0,0.08)' };

  return (
    <>
      <div className="sb-flow" style={{ height:'100%', display:'flex', flexDirection:'column', overflow:'hidden', direction:'rtl' }}>

        {/* Sticky segment toggle */}
        <div style={{ padding: `6px ${isDesktop ? '24px' : '16px'} 12px`, flexShrink: 0 }}>
          <div style={segWrap}>
            <button style={{ ...segBtn, ...(seg==='knowledge' ? segOn : {}) }} onClick={() => setSeg('knowledge')}>حافظه</button>
            <button style={{ ...segBtn, ...(seg==='log'       ? segOn : {}) }} onClick={() => setSeg('log')}>گفتگوها</button>
          </div>
        </div>

        {/* Log segment */}
        {seg === 'log' && window.Log && (
          <div style={{ flex:1, overflow:'hidden' }}>
            <window.Log
              conversations={conversations || []}
              onStar={onStar || (() => {})}
              onDelete={onDeleteConv || (() => {})}
              isDesktop={isDesktop}
              openConvId={openConvId}
              onConvOpened={onConvOpened}
            />
          </div>
        )}

        {/* Knowledge segment */}
        {seg === 'knowledge' && (
          <div className="sb-flow" style={{ flex:1, overflow:'auto', direction:'rtl', padding: isDesktop ? '0 24px 40px' : '0 16px 220px' }}>

            <div style={knowledgeStyles.searchWrap}>
              <Icons.Search size={18} />
              <input
                style={knowledgeStyles.searchInput}
                placeholder="جستجو در عنوان، متن و تگ‌ها…"
                value={q}
                onChange={e => setQ(e.target.value)}
              />
              {q ? (
                <button onClick={() => setQ('')} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--ink-3)', padding:2, display:'grid', placeItems:'center' }}>
                  <Icons.X size={15} />
                </button>
              ) : (
                <span style={knowledgeStyles.shortcut}>
                  {String(knowledge.length).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d])}
                </span>
              )}
            </div>

            <div style={knowledgeStyles.chipsRow}>
              {filters.map(f => {
                const active = filter === f.key;
                const kc = kindConfig[f.key];
                const FIcon = kc ? Icons[kc.icon] : null;
                return (
                  <button key={f.key}
                    style={{
                      ...knowledgeStyles.chip,
                      display: 'inline-flex', alignItems: 'center', gap: 5,
                      ...(active && kc  ? { background: kc.bg, color: kc.fg, borderColor: 'transparent' } : {}),
                      ...(active && !kc ? knowledgeStyles.chipActive : {}),
                    }}
                    onClick={() => setFilter(f.key)}>
                    {FIcon && <FIcon size={12} />}
                    {f.label}
                  </button>
                );
              })}
            </div>

            {/* PRD-008: tag filter chips */}
            {allTags.length > 0 && (
              <div style={{ ...knowledgeStyles.chipsRow, flexWrap: showAllTags ? 'wrap' : 'nowrap' }}>
                {(showAllTags ? allTags : allTags.slice(0, 15)).map(t => {
                  const on = tagFilter === t;
                  return (
                    <button key={t}
                      style={{ ...knowledgeStyles.chip, flexShrink: 0,
                        ...(on ? { background: 'var(--firoozeh)', color: '#fff', borderColor: 'transparent' } : {}) }}
                      onClick={() => setTagFilter(on ? null : t)}>
                      {t}
                    </button>
                  );
                })}
                {allTags.length > 15 && (
                  <button style={{ ...knowledgeStyles.chip, flexShrink: 0, color: 'var(--firoozeh-deep)' }}
                    onClick={() => setShowAllTags(s => !s)}>
                    {showAllTags ? 'کمتر' : 'بیشتر…'}
                  </button>
                )}
              </div>
            )}

            {/* Sort chips (R09) */}
            <div style={{ display: 'flex', gap: 6, marginBottom: 12, alignItems: 'center' }}>
              <span style={{ font: "500 11px 'Estedad', sans-serif", color: 'var(--ink-3)', flexShrink: 0 }}>ترتیب:</span>
              {[['newest','جدیدترین'],['oldest','قدیمی‌ترین'],['alpha','الفبایی'],['type','نوع']].map(([k, l]) => (
                <button key={k}
                  style={{ ...knowledgeStyles.chip, ...(sortBy === k ? knowledgeStyles.chipActive : {}) }}
                  onClick={() => setSortBy(k)}
                >{l}</button>
              ))}
            </div>

            {items.length === 0 && (
              <div style={knowledgeStyles.emptyState}>
                {q.trim()
                  ? <><div style={{ fontSize:32, marginBottom:8 }}>🔍</div>
                      <div>نتیجه‌ای برای «{q}» پیدا نشد</div>
                      <div style={{ fontSize:12, marginTop:6, color:'var(--ink-4)' }}>فیلتر رو تغییر بده یا کلمه دیگه‌ای امتحان کن</div>
                    </>
                  : 'هنوز چیزی در حافظه ذخیره نشده'
                }
              </div>
            )}

            {q.trim() && items.length > 0 && (
              <div style={{ font:"400 12px 'Estedad', sans-serif", color:'var(--ink-3)', marginBottom:10, direction:'rtl' }}>
                {String(items.length).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d])} نتیجه پیدا شد
              </div>
            )}

            {!q.trim() && recent.length > 0 && (
              <div style={knowledgeStyles.sectionTitle}>اخیراً اضافه شد</div>
            )}
            {(!q.trim() ? recent : visibleItems).map(k => <KCard key={k.id} id={'know-item-' + k.id} card={k} onOpen={setViewId} allCards={knowledge} highlightId={highlightId} />)}

            {!q.trim() && older.length > 0 && (
              <>
                <div style={knowledgeStyles.sectionTitle}>قبل‌تر</div>
                {older.map(k => <KCard key={k.id} id={'know-item-' + k.id} card={k} onOpen={setViewId} allCards={knowledge} highlightId={highlightId} />)}
              </>
            )}

            {items.length > showCount && (
              <button
                onClick={() => setShowCount(c => c + 20)}
                style={{
                  display: 'block', width: '100%', margin: '8px 0 16px',
                  padding: '12px', border: '1px solid var(--c-border-sm)',
                  borderRadius: 14, background: 'var(--surface)',
                  font: "500 14px 'Estedad', sans-serif",
                  color: 'var(--ink-2)', cursor: 'pointer', direction: 'rtl',
                }}
              >
                بیشتر ({String(items.length - showCount).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d])} مورد دیگر)
              </button>
            )}
          </div>
        )}
      </div>

      {/* R01: choice bottom-sheet */}
      {addMode === 'choice' && (
        <div style={knowledgeStyles.overlay} onClick={closeAddMode}>
          <div style={{ ...knowledgeStyles.sheet, maxHeight: '42vh' }} onClick={e => e.stopPropagation()}>
            <div style={knowledgeStyles.sheetHandle} />
            <div style={knowledgeStyles.sheetHeader}>
              <span style={knowledgeStyles.sheetTitle}>افزودن به حافظه</span>
              <button style={knowledgeStyles.sheetClose} onClick={closeAddMode}><Icons.X size={16} /></button>
            </div>
            <div style={{ padding: '20px 20px 28px', display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, direction: 'rtl' }}>
              <button style={{
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 9, textAlign: 'center',
                padding: '18px 6px', borderRadius: 16, border: '1px solid var(--c-border-sm)',
                background: 'var(--firoozeh-soft)', cursor: 'pointer',
                font: "500 13px 'Estedad', sans-serif", color: 'var(--firoozeh-deep)',
              }} onClick={() => setAddMode('audio')}>
                <Icons.Mic size={24} /> فایل صوتی
              </button>
              <button style={{
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 9, textAlign: 'center',
                padding: '18px 6px', borderRadius: 16, border: '1px solid var(--c-border-sm)',
                background: 'rgba(88,166,88,0.13)', cursor: 'pointer',
                font: "500 13px 'Estedad', sans-serif", color: '#2E6B2E',
              }} onClick={() => setAddMode('doc')}>
                <Icons.Doc size={24} /> سند ورد
              </button>
              <button style={{
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 9, textAlign: 'center',
                padding: '18px 6px', borderRadius: 16, border: '1px solid var(--c-border-sm)',
                background: 'var(--paper-2)', cursor: 'pointer',
                font: "500 13px 'Estedad', sans-serif", color: 'var(--ink-2)',
              }} onClick={() => setAddMode('manual')}>
                <Icons.Type size={24} /> یادداشت دستی
              </button>
            </div>
          </div>
        </div>
      )}

      <UploadSheet open={addMode === 'audio'} mode="audio" onClose={closeAddMode} onAdd={onAdd} />
      <UploadSheet open={addMode === 'doc'}   mode="doc"   onClose={closeAddMode} onAdd={onAdd} />
      <AddKnowledgeSheet open={addMode === 'manual'} onClose={closeAddMode} onAdd={onAdd} />
      {viewCard && !editCard && (
        <KnowledgeReadSheet
          card={viewCard}
          onClose={() => setViewId(null)}
          onEdit={onUpdate ? () => { setEditId(viewCard.id); setViewId(null); } : undefined}
          allCards={knowledge}
          onOpenCard={(id) => setViewId(id)}
        />
      )}
      {editCard && onUpdate && (
        <KnowledgeEditSheet card={editCard} onClose={() => setEditId(null)} onUpdate={onUpdate} onDelete={onDelete || (() => {})} allCards={knowledge.filter(k => k.id !== editId)} />
      )}
    </>
  );
}

window.Knowledge = Knowledge;
