// Modals.jsx — all secondary flows (new key, recovery codes, upgrade, photo upload, confirms, change pw, totp, export, system prompt edit)
function ModalShell({ eb, title, desc, children, footer, width, onClose }) {
  React.useEffect(() => {
    const onKey = e => { if (e.key === 'Escape') onClose && onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);
  return (
    <div className="ch-modal-bg" onClick={onClose}>
      <div className={'ch-modal' + (width === 'wide' ? ' wide' : '')} onClick={e => e.stopPropagation()}>
        <div className="ch-modal-head">
          {eb && <div className="ch-modal-eb">{eb}</div>}
          <h2>{title}</h2>
          {desc && <p className="desc">{desc}</p>}
        </div>
        <div className="ch-modal-body">{children}</div>
        <div className="ch-modal-foot">{footer}</div>
      </div>
    </div>
  );
}

/* ---- 1. New API key (multi-step: name+scopes → reveal) ---- */
function NewKeyModal({ onClose }) {
  const [step, setStep] = React.useState(1);
  const [name, setName] = React.useState('production-2');
  const [scopes, setScopes] = React.useState({read: true, write: true, verify: true, billing: false});
  const tog = (k) => setScopes({...scopes, [k]: !scopes[k]});
  const key = 'zg-live-a8f3c91d4e7b8s2nCAAB2901F40137';

  if (step === 1) return (
    <ModalShell eb="Account · API keys" title="Create a new key" desc="Keys are shown once. Copy it after creation and store it in your secrets manager."
      onClose={onClose}
      footer={<>
        <div className="left"><div className="ch-steps"><div className="seg on"></div><div className="seg"></div></div></div>
        <div className="right">
          <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
          <button className="ch-btn primary" onClick={() => setStep(2)}>Create key</button>
        </div>
      </>}>
      <label className="field">Key name<input value={name} onChange={e => setName(e.target.value)}/></label>
      <div className="field" style={{marginBottom: 6}}>Scopes</div>
      {[
        {k: 'read', t: 'Read', s: 'List threads, models, and certificates'},
        {k: 'write', t: 'Write', s: 'Create threads and submit statements'},
        {k: 'verify', t: 'Verify', s: 'Run kernel verification, fetch certificates'},
        {k: 'billing', t: 'Billing', s: 'Read invoices and update payment methods'},
      ].map(o => (
        <label key={o.k} className={'chk' + (scopes[o.k] ? ' on' : '')}>
          <input type="checkbox" checked={scopes[o.k]} onChange={() => tog(o.k)}/>
          <div><div className="ti">{o.t}</div><div className="sb">{o.s}</div></div>
        </label>
      ))}
    </ModalShell>
  );

  return (
    <ModalShell eb="Account · API keys" title="Your new key" desc="This is the only time you can see this key. Copy it now."
      onClose={onClose}
      footer={<>
        <div className="left"><div className="ch-steps"><div className="seg on"></div><div className="seg on"></div></div></div>
        <div className="right"><button className="ch-btn primary" onClick={onClose}>Done</button></div>
      </>}>
      <div className="ch-revealkey">
        <span>{key}</span>
        <span className="copy">Copy</span>
      </div>
      <div className="ch-warn">Store this in a secure secrets manager. If lost, you'll need to create a new key. Treat it like a password.</div>
      <div style={{marginTop: 14, fontSize: 12, color: 'var(--fg-4)', fontFamily: 'var(--font-mono)'}}>
        name · {name}<br/>scopes · {Object.keys(scopes).filter(k => scopes[k]).join(', ')}<br/>created · {new Date().toISOString().slice(0, 16).replace('T', ' ')}
      </div>
    </ModalShell>
  );
}

/* ---- 2. Recovery codes ---- */
function RecoveryCodesModal({ onClose }) {
  const codes = ['8h2d-fw3k', 'p1qa-ne7r', 'm4xv-2tcb', 'gz9o-rk1y', 'aa3e-d8u2', 'sd0n-rm4p', '4er8-lo2k', 'b7yu-fwn9', 'cc1a-vb6q', '7l9z-hk4n'];
  return (
    <ModalShell eb="Account · Security" title="Recovery codes" desc="Use these one-time codes if you lose access to your authenticator. Each code works once."
      onClose={onClose}
      footer={<><div className="left">10 codes · 0 used</div><div className="right">
        <button className="ch-btn ghost">Regenerate</button>
        <button className="ch-btn ghost">Download .txt</button>
        <button className="ch-btn primary" onClick={onClose}>Done</button>
      </div></>}>
      <div className="ch-recovery-grid">{codes.map(c => <div key={c}>{c}</div>)}</div>
      <div className="ch-warn">Store these somewhere safe and offline. They are equivalent to your password.</div>
    </ModalShell>
  );
}

/* ---- 3. Change password ---- */
function ChangePasswordModal({ onClose }) {
  const [done, setDone] = React.useState(false);
  if (done) return (
    <ModalShell eb="Account · Security" title="Password updated" onClose={onClose}
      footer={<div className="right"><button className="ch-btn primary" onClick={onClose}>Close</button></div>}>
      <div className="ch-good">Your password has been changed. All other sessions have been signed out.</div>
    </ModalShell>
  );
  return (
    <ModalShell eb="Account · Security" title="Change password" desc="You'll be signed out of all other devices after the change."
      onClose={onClose}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={() => setDone(true)}>Update password</button>
      </div></>}>
      <label className="field">Current password<input type="password" placeholder="••••••••••"/></label>
      <label className="field">New password<input type="password" placeholder="At least 12 characters"/></label>
      <label className="field">Confirm new password<input type="password"/></label>
    </ModalShell>
  );
}

/* ---- 4. Reconfigure TOTP ---- */
function TotpModal({ onClose }) {
  const secret = 'JBSWY3DPEHPK3PXPSXNJWGGMTQTQM';
  return (
    <ModalShell eb="Account · Security" title="Reconfigure two-factor"
      desc="Scan the QR with your authenticator (1Password, Authy, Google Authenticator) and enter the 6-digit code to confirm."
      onClose={onClose} width="wide"
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={onClose}>Confirm</button>
      </div></>}>
      <div style={{display: 'grid', gridTemplateColumns: '156px 1fr', gap: 18, alignItems: 'center'}}>
        <div style={{width: 156, height: 156, background: '#fff', border: '8px solid #fff', borderRadius: 8, position: 'relative'}}>
          <div style={{width: '100%', height: '100%', background: 'repeating-conic-gradient(#000 0 25%, #fff 0 50%) 50% / 14px 14px'}}></div>
        </div>
        <div>
          <div style={{fontSize: 11, color: 'var(--fg-4)', marginBottom: 6}}>Or paste this secret</div>
          <div className="ch-revealkey"><span>{secret}</span><span className="copy">Copy</span></div>
          <label className="field" style={{marginTop: 14}}>6-digit code<input maxLength="6" placeholder="000 000" style={{letterSpacing: '0.2em', fontSize: 16}}/></label>
        </div>
      </div>
    </ModalShell>
  );
}

/* ---- 5. Upgrade plan ---- */
function UpgradeModal({ onClose }) {
  const [sel, setSel] = React.useState('atlas');
  return (
    <ModalShell eb="Account · Plan & billing" title="Upgrade your plan"
      desc="You're currently on Lab. Atlas adds dedicated capacity, audit logs, and SSO enforcement."
      onClose={onClose} width="wide"
      footer={<><div className="left">Billed monthly · prorated today</div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Not now</button>
        <button className="ch-btn primary" onClick={onClose}>Continue to checkout</button>
      </div></>}>
      <div className="ch-plan-cards">
        <div className={'ch-plan-card' + (sel === 'atlas' ? ' on' : '')} onClick={() => setSel('atlas')}>
          <div className="nm">Atlas</div><div className="pr">$1,499/mo</div>
          <div className="ft">10M tokens · 25k proofs · SSO · audit log · 99.95% SLA · email + slack support</div>
        </div>
        <div className={'ch-plan-card' + (sel === 'enterprise' ? ' on' : '')} onClick={() => setSel('enterprise')}>
          <div className="nm">Enterprise</div><div className="pr">Talk to us</div>
          <div className="ft">Dedicated kernel · on-prem option · custom retention · designated SRE · MSA</div>
        </div>
      </div>
    </ModalShell>
  );
}

/* ---- 6. Photo upload ---- */
function PhotoUploadModal({ onClose }) {
  const ref = React.useRef(null);
  return (
    <ModalShell eb="Account · Profile" title="Upload profile photo" desc="JPG or PNG, up to 4 MB. Square images crop best."
      onClose={onClose}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={onClose}>Save</button>
      </div></>}>
      <div className="ch-upload-drop" onClick={() => ref.current && ref.current.click()}>
        <div className="big">↑</div>
        <div className="ti">Drag an image here, or click to browse</div>
        <div className="sb">jpg · png · webp · 4 MB max</div>
        <input ref={ref} type="file" accept="image/*" style={{display:'none'}}/>
      </div>
    </ModalShell>
  );
}

/* ---- 7. Confirm destructive ---- */
function ConfirmModal({ eb, title, desc, confirmText = 'Confirm', requirePhrase, onClose, onConfirm }) {
  const [phrase, setPhrase] = React.useState('');
  const ok = !requirePhrase || phrase === requirePhrase;
  return (
    <ModalShell eb={eb} title={title} desc={desc} onClose={onClose}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className={'ch-btn danger'} disabled={!ok} style={{opacity: ok ? 1 : 0.5, cursor: ok ? 'pointer' : 'not-allowed'}} onClick={() => { onConfirm && onConfirm(); onClose(); }}>{confirmText}</button>
      </div></>}>
      <div className="ch-warn">This action cannot be undone.</div>
      {requirePhrase && (
        <label className="field" style={{marginTop: 14}}>Type <code style={{fontFamily:'var(--font-mono)',color:'var(--accent)'}}>{requirePhrase}</code> to confirm
          <input value={phrase} onChange={e => setPhrase(e.target.value)} placeholder={requirePhrase}/>
        </label>
      )}
    </ModalShell>
  );
}

/* ---- 8. Generic info modal ---- */
function ExportModal({ onClose }) {
  return (
    <ModalShell eb="Settings · Data & privacy" title="Export your data" desc="We'll bundle your threads, certificates, and account metadata into a single archive and email a download link."
      onClose={onClose}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={onClose}>Request export</button>
      </div></>}>
      <label className="chk on"><input type="checkbox" defaultChecked/><div><div className="ti">Conversations</div><div className="sb">All threads · markdown + JSON</div></div></label>
      <label className="chk on"><input type="checkbox" defaultChecked/><div><div className="ti">Proof certificates</div><div className="sb">Signed CBOR · with kernel version</div></div></label>
      <label className="chk on"><input type="checkbox" defaultChecked/><div><div className="ti">Account metadata</div><div className="sb">Profile, sessions, audit log</div></div></label>
      <label className="chk"><input type="checkbox"/><div><div className="ti">Billing history</div><div className="sb">Invoices and receipts</div></div></label>
    </ModalShell>
  );
}

/* ---- 9. Generic value-edit (radio-style selector) ---- */
const VALUE_PRESETS = {
  timezone:  { eb: 'Account · Profile',    title: 'Change timezone',       desc: 'Used for timestamps, scheduled sends, and daily digest delivery.',
               options: ['Asia/Seoul · UTC+09', 'Asia/Tokyo · UTC+09', 'America/Los_Angeles · UTC-08', 'Europe/London · UTC+00', 'UTC'] },
  locale:    { eb: 'Account · Profile',    title: 'Change locale',         desc: 'Affects UI language and number/date formatting.',
               options: ['한국어 / English', 'English (US)', '日本語', '中文 (简体)', 'Deutsch'] },
  'billing-email': { eb: 'Account · Plan & billing', title: 'Billing email', desc: 'Invoices and dunning notices are sent here.', input: true, current: 'billing@gbr.ai' },
  'pay-method':    { eb: 'Account · Plan & billing', title: 'Update payment method',
                     desc: 'We never store your full PAN. Stripe Elements handles the card field.',
                     options: ['Visa ···· 4128 (default)', 'Mastercard ···· 7733', '+ Add new card', '+ Add bank transfer / wire'] },
  invoices:        { eb: 'Account · Plan & billing', title: 'Download invoice history',
                     desc: 'Choose a range — we\u2019ll email the CSV bundle within 30 minutes.',
                     options: ['Last 30 days', 'Last 90 days', 'Last 12 months', 'All time'] },
  'math-render':   { eb: 'Settings · Appearance',    title: 'Math rendering engine',
                     desc: 'KaTeX is faster; MathJax has wider symbol support.',
                     options: ['KaTeX · italic serif (default)', 'KaTeX · upright sans', 'MathJax · classical', 'Plain text · monospace'] },
  'code-theme':    { eb: 'Settings · Appearance',    title: 'Code block theme',
                     options: ['GBR Gold (default)', 'Classic dark', 'Solarized dark', 'Monokai', 'High contrast'] },
  'default-model': { eb: 'Settings · Chat defaults', title: 'Default model',
                     desc: 'Applied to every new conversation. You can swap per-thread.',
                     options: ['proof-α-2.4 (recommended)', 'proof-α-2.4 · thinking', 'proof-β-1.1 · fast', 'kernel-only · no LLM'] },
  retention:       { eb: 'Settings · Data & privacy', title: 'Conversation retention',
                     desc: 'After this period, threads are permanently destroyed. Certificates are kept indefinitely.',
                     options: ['30 days', '90 days (default)', '180 days', '1 year', 'Forever (until manually deleted)'] },
};
function ValueEditModal({ presetKey, onClose, onSave }) {
  const p = VALUE_PRESETS[presetKey] || { eb: 'Settings', title: 'Edit value', options: [] };
  const [val, setVal] = React.useState(p.input ? (p.current || '') : (p.options ? p.options[0] : ''));
  return (
    <ModalShell eb={p.eb} title={p.title} desc={p.desc} onClose={onClose} width={520}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={() => { onSave && onSave(val); onClose(); }}>Save</button>
      </div></>}>
      {p.input ? (
        <input className="ch-input" defaultValue={p.current} onChange={e => setVal(e.target.value)} style={{width:'100%',background:'var(--bg-canvas)',border:'1px solid var(--border-1)',borderRadius:'var(--r-2)',padding:'10px 12px',color:'var(--fg-1)',fontFamily:'var(--font-mono)',fontSize:13,outline:'none'}}/>
      ) : (
        <div className="ch-radio-stack">
          {p.options.map(o => (
            <label key={o} className={'ch-radio-row' + (val === o ? ' on' : '')} onClick={() => setVal(o)}>
              <span className="dot"></span><span className="t">{o}</span>
            </label>
          ))}
        </div>
      )}
    </ModalShell>
  );
}

/* ---- 10. Share thread ---- */
function ShareModal({ onClose, threadTitle = 'Riemann zeta — non-trivial zeros' }) {
  const [scope, setScope] = React.useState('link');
  const [expiry, setExpiry] = React.useState('7d');
  const [allowVerify, setAllowVerify] = React.useState(true);
  const [copied, setCopied] = React.useState(false);
  const link = 'https://gbr.ai/s/' + (Math.random().toString(36).slice(2, 10));
  const scopes = [
    { id: 'link', t: 'Anyone with the link', s: 'Read-only. No sign-in required.' },
    { id: 'workspace', t: 'Workspace members', s: 'ZIGU LABS · 14 members' },
    { id: 'specific', t: 'Specific people', s: 'Invite by email; they\u2019ll need a GBR account.' },
    { id: 'off', t: 'Off · only me', s: 'Disable any existing share links.' },
  ];
  const expiries = ['24 hours', '7 days', '30 days', 'No expiry'];
  return (
    <ModalShell eb="Thread · Share" title="Share this conversation" desc={'\u201c' + threadTitle + '\u201d will be readable at the URL below.'} onClose={onClose} width="wide"
      footer={<><div className="left"><span style={{color:'var(--fg-4)',fontSize:11,fontFamily:'var(--font-mono)'}}>cert · 0xCAAB29F4…8E2A</span></div>
        <div className="right"><button className="ch-btn ghost" onClick={onClose}>Done</button></div></>}>
      <div className="ch-share-link">
        <span className="lk">{link}</span>
        <button className={'ch-btn ' + (copied ? 'success' : 'primary')} onClick={() => { navigator.clipboard && navigator.clipboard.writeText(link); setCopied(true); setTimeout(() => setCopied(false), 1600); }}>{copied ? 'Copied ✓' : 'Copy link'}</button>
      </div>
      <div className="ch-share-grid">
        <div>
          <div className="ch-share-h">Who can view</div>
          <div className="ch-radio-stack">
            {scopes.map(o => (
              <label key={o.id} className={'ch-radio-row' + (scope === o.id ? ' on' : '')} onClick={() => setScope(o.id)}>
                <span className="dot"></span><span className="t"><b>{o.t}</b><small>{o.s}</small></span>
              </label>
            ))}
          </div>
        </div>
        <div>
          <div className="ch-share-h">Link expires</div>
          <div className="ch-radio-group ch-radio-stack-h">
            {expiries.map(e => <button key={e} className={expiry === e ? 'on' : ''} onClick={() => setExpiry(e)}>{e}</button>)}
          </div>
          <div className="ch-share-h" style={{marginTop:18}}>Options</div>
          <label className="chk on"><input type="checkbox" defaultChecked={allowVerify} onChange={e => setAllowVerify(e.target.checked)}/><div><div className="ti">Allow proof re-verification</div><div className="sb">Viewers can re-run the kernel and inspect the certificate.</div></div></label>
          <label className="chk"><input type="checkbox"/><div><div className="ti">Hide my identity</div><div className="sb">Show as <i>anonymous</i> instead of LEE JUN SU.</div></div></label>
        </div>
      </div>
    </ModalShell>
  );
}

/* ---- 11. Export thread ---- */
function ExportThreadModal({ onClose, threadTitle = 'thread' }) {
  const [fmt, setFmt] = React.useState('md');
  const formats = [
    { id: 'md', t: 'Markdown', s: 'Plain .md · code fences preserved', size: '12.4 KB', ic: 'M↓' },
    { id: 'json', t: 'JSON', s: 'Structured messages + metadata', size: '38.1 KB', ic: '{}' },
    { id: 'pdf', t: 'PDF', s: 'Printable · GBR Gold theme · 1-column', size: '410 KB', ic: '📄' },
    { id: 'cbor', t: 'Proof bundle', s: 'Signed CBOR · re-verifiable offline', size: '4.2 MB', ic: '⛨' },
  ];
  return (
    <ModalShell eb="Thread · Export" title="Export this conversation" desc="The file will download immediately. Certificates stay attached only in JSON and Proof bundle." onClose={onClose}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={onClose}>Download .{fmt}</button></div></>}>
      <div className="ch-format-list">
        {formats.map(f => (
          <label key={f.id} className={'ch-format-row' + (fmt === f.id ? ' on' : '')} onClick={() => setFmt(f.id)}>
            <span className="ico">{f.ic}</span>
            <span className="meta"><b>{f.t}</b><small>{f.s}</small></span>
            <span className="sz">{f.size}</span>
            <span className="dot"></span>
          </label>
        ))}
      </div>
    </ModalShell>
  );
}

/* ---- 12. Search threads (command palette) ---- */
function SearchModal({ onClose, threads = [], onSelect }) {
  const [q, setQ] = React.useState('');
  const ref = React.useRef(null);
  React.useEffect(() => { ref.current && ref.current.focus(); }, []);
  const filtered = !q ? threads : threads.filter(t => t.title.toLowerCase().includes(q.toLowerCase()) || t.model.toLowerCase().includes(q.toLowerCase()));
  return (
    <div className="ch-modal-bg" onClick={onClose}>
      <div className="ch-search-modal" onClick={e => e.stopPropagation()}>
        <div className="ch-search-input">
          <span className="ic">⌕</span>
          <input ref={ref} placeholder="Search threads, models, certificates…" value={q} onChange={e => setQ(e.target.value)}/>
          <kbd>esc</kbd>
        </div>
        <div className="ch-search-results">
          {!q && <div className="ch-search-section">Jump to</div>}
          {!q && [
            { ic: '+', t: 'New conversation', kbd: '⌘ N' },
            { ic: '⚙', t: 'Settings', kbd: '⌘ ,' },
            { ic: '⌘', t: 'Switch model', kbd: '⌘ ⇧ M' },
            { ic: '✓', t: 'Verify last proof', kbd: '⌘ ⇧ V' },
          ].map((c, i) => (
            <div key={i} className="ch-search-row"><span className="ic">{c.ic}</span><span className="t">{c.t}</span><kbd>{c.kbd}</kbd></div>
          ))}
          <div className="ch-search-section">{q ? 'Threads · ' + filtered.length + ' match' + (filtered.length === 1 ? '' : 'es') : 'Recent threads'}</div>
          {filtered.length === 0 && <div className="ch-search-empty">No threads match <b>"{q}"</b>. Try a model name, a date, or a partial proof statement.</div>}
          {filtered.map(t => (
            <div key={t.id} className="ch-search-row thread" onClick={() => { onSelect && onSelect(t.id); onClose(); }}>
              <span className="ic">∎</span>
              <span className="t"><b>{t.title}</b><small>{t.model} · {t.time}</small></span>
              <kbd>↵</kbd>
            </div>
          ))}
        </div>
        <div className="ch-search-foot">
          <span><kbd>↑↓</kbd> navigate</span><span><kbd>↵</kbd> open</span><span><kbd>⌘ ↵</kbd> open in new tab</span><span><kbd>esc</kbd> close</span>
        </div>
      </div>
    </div>
  );
}

/* ---- 13. Rename thread ---- */
function RenameThreadModal({ onClose, current = '', onSave }) {
  const [v, setV] = React.useState(current);
  return (
    <ModalShell eb="Thread · Rename" title="Rename this conversation" desc="Titles are private to your workspace; shared viewers see the proof statement instead." onClose={onClose}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={() => { onSave && onSave(v); onClose(); }}>Rename</button></div></>}>
      <input autoFocus value={v} onChange={e => setV(e.target.value)} style={{width:'100%',background:'var(--bg-canvas)',border:'1px solid var(--border-1)',borderRadius:'var(--r-2)',padding:'12px 14px',color:'var(--fg-1)',fontFamily:'var(--font-sans)',fontSize:14,outline:'none'}}/>
    </ModalShell>
  );
}

/* ---- 14. Move to project ---- */
function MoveToProjectModal({ onClose }) {
  const [sel, setSel] = React.useState('p2');
  const projects = [
    { id: 'p1', t: 'Riemann hypothesis · 2026',   s: '12 threads · last update 2 hr ago' },
    { id: 'p2', t: 'Internal · proof-α evals',    s: '38 threads · pinned' },
    { id: 'p3', t: 'Sandbox',                     s: '6 threads · draft' },
    { id: 'new', t: '+ New project',              s: 'Create a project from this thread.' },
  ];
  return (
    <ModalShell eb="Thread · Move" title="Move to project" desc="Projects share system prompts, models, and access lists across all of their threads." onClose={onClose}
      footer={<><div className="left"></div><div className="right">
        <button className="ch-btn ghost" onClick={onClose}>Cancel</button>
        <button className="ch-btn primary" onClick={onClose}>Move thread</button></div></>}>
      <div className="ch-radio-stack">
        {projects.map(p => (
          <label key={p.id} className={'ch-radio-row' + (sel === p.id ? ' on' : '')} onClick={() => setSel(p.id)}>
            <span className="dot"></span><span className="t"><b>{p.t}</b><small>{p.s}</small></span>
          </label>
        ))}
      </div>
    </ModalShell>
  );
}

Object.assign(window, { ModalShell, NewKeyModal, RecoveryCodesModal, ChangePasswordModal, TotpModal, UpgradeModal, PhotoUploadModal, ConfirmModal, ExportModal, ValueEditModal, ShareModal, ExportThreadModal, SearchModal, RenameThreadModal, MoveToProjectModal });
