/* Mandera Portal — Admin console (master + team). Lives on MData. */

const A_money = (n) => '$' + n.toLocaleString();
function ATitle({ children }) { return <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 22, color: 'var(--text-strong)', margin: 0 }}>{children}</h3>; }
function AField({ label, children }) {
  return <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}><label style={{ fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600, color: 'var(--text-secondary)' }}>{label}</label>{children}</div>;
}
function ASelect({ value, onChange, options }) {
  return (
    <select value={value} onChange={onChange} style={{ height: 42, padding: '0 12px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 14, outline: 'none' }}>
      {options.map((o) => <option key={o.value || o} value={o.value || o}>{o.label || o}</option>)}
    </select>
  );
}

/* ---------------- Overview ---------------- */
function AdminOverview({ go }) {
  const { Card } = window.ManderaDesignSystem_8327ce;
  const clients = window.MData.clients();
  const projects = window.MData.get('projects');
  const shoots = window.MData.get('shoots');
  const db = window.MData.load();
  const pendingOnb = Object.values(db.onboarding).filter((o) => o.status === 'submitted').length;
  const openRev = window.MData.get('revisions').filter((r) => r.status !== 'done').length;
  const tiles = [
    { ic: 'users', lbl: 'Active clients', val: clients.filter((c) => c.status === 'active').length, color: 'var(--accent-text)', go: 'clients' },
    { ic: 'folder-kanban', lbl: 'Live projects', val: projects.length, color: 'var(--azure-400)', go: 'clients' },
    { ic: 'camera', lbl: 'Shoots booked', val: shoots.length, color: 'var(--positive)', go: 'clients' },
    { ic: 'clipboard-check', lbl: 'Onboarding to review', val: pendingOnb, color: 'var(--caution)', go: 'onboarding' },
    { ic: 'git-pull-request', lbl: 'Open revisions', val: openRev, color: 'var(--critical)', go: 'clients' },
  ];
  return (
    <div style={{ padding: 32, display: 'flex', flexDirection: 'column', gap: 24 }}>
      <div style={{ position: 'relative', overflow: 'hidden', borderRadius: 'var(--radius-xl)', border: '1px solid var(--border-subtle)', background: 'var(--ink-900)', padding: '30px 32px' }}>
        <window.MarkWash opacity={0.14} size={380} pos={{ top: '-110px', right: '-70px' }} />
        <div style={{ position: 'relative' }}>
          <span className="mandera-eyebrow">Mandera team console</span>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 34, color: 'var(--text-strong)', margin: '10px 0 6px' }}>Everything across every client.</h2>
          <p style={{ fontFamily: 'var(--font-sans)', fontSize: 15.5, color: 'var(--text-secondary)', margin: 0 }}>Create accounts, schedule shoots, manage content and talk to clients — all here.</p>
        </div>
      </div>
      <window.TodayPanel showClient />
      <div className="mp-grid-tiles" style={{ display: 'grid', gridTemplateColumns: 'repeat(5,1fr)', gap: 16 }}>
        {tiles.map((t) => (
          <div key={t.lbl} onClick={() => go(t.go)} style={{ cursor: 'pointer' }}>
            <Card interactive>
              <window.PIcon n={t.ic} s={20} color={t.color} stroke={1.7} />
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 32, color: 'var(--text-strong)', lineHeight: 1, marginTop: 14 }}>{t.val}</div>
              <div style={{ fontFamily: 'var(--font-sans)', fontSize: 13, color: 'var(--text-muted)', marginTop: 6 }}>{t.lbl}</div>
            </Card>
          </div>
        ))}
      </div>
      <div>
        <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 22, color: 'var(--text-strong)', margin: '0 0 14px' }}>Coming up — across all clients</h3>
        <window.Agenda clientId={null} showClient emptyText="Nothing scheduled yet. Schedule shoots and content from a client’s page." />
      </div>
    </div>
  );
}

/* ---------------- Clients list + detail ---------------- */
function AdminClients({ bump }) {
  const { Button, Input, Badge } = window.ManderaDesignSystem_8327ce;
  const [q, setQ] = React.useState('');
  const [filter, setFilter] = React.useState('all');
  const [openId, setOpenId] = React.useState(null);
  const clients = window.MData.clients().filter((c) => (filter === 'all' || c.status === filter) && (c.brand.toLowerCase().includes(q.toLowerCase()) || c.contact.toLowerCase().includes(q.toLowerCase())));

  if (openId) return <AdminClientDetail clientId={openId} back={() => setOpenId(null)} bump={bump} />;

  return (
    <div style={{ padding: 32, display: 'flex', flexDirection: 'column', gap: 18 }}>
      <div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
        <div style={{ flex: 1, minWidth: 240 }}><Input placeholder="Search clients…" value={q} onChange={(e) => setQ(e.target.value)} iconLeft={<window.PIcon n="search" s={16} />} /></div>
        <ASelect value={filter} onChange={(e) => setFilter(e.target.value)} options={[{ value: 'all', label: 'All statuses' }, { value: 'active', label: 'Active' }, { value: 'suspended', label: 'Suspended' }]} />
      </div>
      <div style={{ border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' }}>
        {clients.map((c, i) => {
          const onb = window.MData.onboardingOf(c.id);
          return (
            <div key={c.id} onClick={() => setOpenId(c.id)} style={{ display: 'grid', gridTemplateColumns: '1fr 160px 130px 110px 28px', gap: 16, alignItems: 'center', padding: '15px 18px', background: 'var(--surface-card)', borderTop: i ? '1px solid var(--border-subtle)' : 'none', cursor: 'pointer' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, minWidth: 0 }}>
                <span style={{ width: 38, height: 38, borderRadius: '50%', flex: 'none', background: 'var(--surface-raised)', border: '1px solid var(--border-default)', color: 'var(--accent-text)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontWeight: 600, fontFamily: 'var(--font-sans)', fontSize: 13 }}>{window.mInitials(c.brand)}</span>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14.5, fontWeight: 600, color: 'var(--text-strong)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{c.brand}</div>
                  <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--text-muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{c.contact}</div>
                </div>
              </div>
              <span style={{ fontFamily: 'var(--font-sans)', fontSize: 13, color: 'var(--text-muted)' }}>{c.industry || '—'}</span>
              {onb.status === 'approved' ? <Badge tone="positive" variant="soft">Onboarded</Badge> : onb.status === 'submitted' ? <Badge tone="caution" variant="soft">Review</Badge> : <Badge tone="neutral" variant="outline">Pending</Badge>}
              {c.status === 'active' ? <Badge tone="positive" variant="outline">Active</Badge> : <Badge tone="critical" variant="outline">Suspended</Badge>}
              <window.PIcon n="chevron-right" s={18} color="var(--text-faint)" />
            </div>
          );
        })}
        {!clients.length && <div style={{ padding: 40, textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)' }}>No clients match.</div>}
      </div>
    </div>
  );
}

function AdminClientDetail({ clientId, back, bump }) {
  const { Button, Input, Badge } = window.ManderaDesignSystem_8327ce;
  const [tab, setTab] = React.useState('shoots');
  const [, setTick] = React.useState(0);
  const refresh = () => { setTick((t) => t + 1); bump && bump(); };
  const c = window.MData.client(clientId);
  const onb = window.MData.onboardingOf(clientId);
  const avatarRef = React.useRef(null);
  const onAvatar = (e) => {
    const f = e.target.files && e.target.files[0]; if (!f) return;
    if (!f.type.startsWith('image')) { alert('Please choose an image file.'); return; }
    const r = new FileReader();
    r.onload = () => { window.MData.update('clients', clientId, { avatar: r.result }); refresh(); };
    r.readAsDataURL(f);
  };

  const Tab = ({ id, label }) => (
    <button onClick={() => setTab(id)} style={{ appearance: 'none', background: 'none', border: 'none', borderBottom: '2px solid', borderColor: tab === id ? 'var(--accent)' : 'transparent', padding: '10px 4px', marginRight: 18, cursor: 'pointer', fontFamily: 'var(--font-sans)', fontSize: 14, fontWeight: 600, color: tab === id ? 'var(--text-strong)' : 'var(--text-muted)' }}>{label}</button>
  );

  return (
    <div style={{ padding: 32, display: 'flex', flexDirection: 'column', gap: 18 }}>
      <button onClick={back} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', fontFamily: 'var(--font-sans)', fontSize: 14, padding: 0, alignSelf: 'flex-start' }}>
        <window.PIcon n="arrow-left" s={16} /> All clients
      </button>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        <button type="button" onClick={() => avatarRef.current && avatarRef.current.click()} title="Change client avatar" style={{ appearance: 'none', border: 'none', background: 'none', padding: 0, cursor: 'pointer', position: 'relative', flex: 'none' }}>
          <window.Avatar name={c.brand} src={c.avatar} size={52} accent fontSize={18} />
          <span style={{ position: 'absolute', right: -2, bottom: -2, width: 20, height: 20, borderRadius: '50%', background: 'var(--surface-raised)', border: '1px solid var(--border-default)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}><window.PIcon n="pencil" s={11} color="var(--text-secondary)" /></span>
        </button>
        <input ref={avatarRef} type="file" accept="image/*" style={{ display: 'none' }} onChange={onAvatar} />
        <div style={{ flex: 1 }}>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 28, color: 'var(--text-strong)', margin: 0 }}>{c.brand}</h2>
          <div style={{ fontFamily: 'var(--font-sans)', fontSize: 13.5, color: 'var(--text-muted)' }}>{c.contact} · {c.email} · lead {c.manager}</div>
        </div>
        {c.avatar && <button onClick={() => { window.MData.update('clients', clientId, { avatar: null }); refresh(); }} style={{ appearance: 'none', border: '1px solid var(--border-default)', background: 'var(--surface-raised)', borderRadius: 'var(--radius-sm)', cursor: 'pointer', color: 'var(--text-muted)', fontFamily: 'var(--font-sans)', fontSize: 12.5, padding: '7px 12px' }}>Remove logo</button>}
        {((window.MAuth.current() || {}).role === 'master') && (
          <button onClick={() => { if (confirm('Delete “' + c.brand + '” and ALL their data — shoots, content, files, messages, invoices and their sign-in account? This cannot be undone.')) { window.MData.deleteClient(clientId); back(); } }}
            style={{ appearance: 'none', border: '1px solid var(--border-default)', background: 'var(--surface-raised)', borderRadius: 'var(--radius-sm)', cursor: 'pointer', color: 'var(--critical)', fontFamily: 'var(--font-sans)', fontSize: 12.5, fontWeight: 600, padding: '7px 12px', display: 'inline-flex', alignItems: 'center', gap: 7 }}>
            <window.PIcon n="trash-2" s={14} color="var(--critical)" /> Delete client
          </button>
        )}
      </div>
      <div style={{ borderBottom: '1px solid var(--border-subtle)' }}>
        <Tab id="shoots" label="Shoots" /><Tab id="content" label="Content" /><Tab id="timeline" label="Timeline" /><Tab id="files" label="Files" /><Tab id="invoices" label="Invoices" /><Tab id="onboarding" label="Onboarding" />
      </div>
      {tab === 'shoots' && <AdminShoots clientId={clientId} refresh={refresh} />}
      {tab === 'content' && <AdminContent clientId={clientId} refresh={refresh} />}
      {tab === 'timeline' && <AdminTimeline clientId={clientId} refresh={refresh} />}
      {tab === 'files' && <AdminFiles clientId={clientId} refresh={refresh} />}
      {tab === 'invoices' && <AdminInvoices clientId={clientId} refresh={refresh} />}
      {tab === 'onboarding' && <AdminOnboardingReview clientId={clientId} refresh={refresh} />}
    </div>
  );
}

function AdminShoots({ clientId, refresh }) {
  const { Button, Input } = window.ManderaDesignSystem_8327ce;
  const shoots = window.MData.forClient('shoots', clientId).slice().sort((a, b) => a.date.localeCompare(b.date));
  const [form, setForm] = React.useState({ title: '', date: '', time: '', location: '', notes: '', status: 'Pending' });
  const set = (k, v) => setForm((p) => ({ ...p, [k]: v }));
  const add = (e) => { e.preventDefault(); if (!form.title.trim() || !form.date) return; const s = window.MData.add('shoots', { clientId, ...form }); window.MData.notify({ clientId, type: 'shoot', text: 'New shoot scheduled: “' + form.title.trim() + '” · ' + window.mFmtDate(form.date) + (form.time ? ' · ' + form.time : ''), link: 'shoots', refId: s.id }); try { fetch('../api/portal-mail.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'shoot_scheduled', clientId, title: form.title.trim(), date: form.date, time: form.time, location: form.location }) }).catch(() => {}); } catch (_) {} setForm({ title: '', date: '', time: '', location: '', notes: '', status: 'Pending' }); refresh(); };
  return (
    <div className="mp-grid2" style={{ display: 'grid', gridTemplateColumns: '340px 1fr', gap: 28, alignItems: 'start' }}>
      <form onSubmit={add} style={{ background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)', padding: 22, display: 'flex', flexDirection: 'column', gap: 14 }}>
        <ATitle>Schedule a shoot</ATitle>
        <Input label="Title" value={form.title} onChange={(e) => set('title', e.target.value)} placeholder="Product shoot…" />
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <AField label="Date"><input type="date" value={form.date} onChange={(e) => set('date', e.target.value)} style={{ height: 42, padding: '0 12px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 14 }} /></AField>
          <Input label="Time" value={form.time} onChange={(e) => set('time', e.target.value)} placeholder="09:00 – 13:00" />
        </div>
        <Input label="Location" value={form.location} onChange={(e) => set('location', e.target.value)} placeholder="Studio A · Lisbon" />
        <AField label="Notes"><textarea rows={2} value={form.notes} onChange={(e) => set('notes', e.target.value)} style={{ resize: 'vertical', padding: '10px 12px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 14 }} /></AField>
        <AField label="Status"><ASelect value={form.status} onChange={(e) => set('status', e.target.value)} options={['Pending', 'Confirmed']} /></AField>
        {form.status === 'Pending' && <p style={{ fontFamily: 'var(--font-sans)', fontSize: 12, color: 'var(--text-faint)', margin: '-6px 0 0', lineHeight: 1.5 }}>Pending asks the client to approve or decline this shoot in their portal.</p>}
        <Button variant="primary" type="submit" fullWidth iconLeft={<window.PIcon n="plus" s={16} color="var(--ink-950)" />}>Add shoot</Button>
      </form>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {shoots.map((s) => (
          <div key={s.id} style={{ display: 'flex', flexDirection: 'column', gap: 10, padding: '14px 16px', background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-md)' }}>
            <div style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
              <window.PIcon n="camera" s={18} color="var(--azure-400)" />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14, fontWeight: 600, color: 'var(--text-strong)' }}>{s.title}</div>
                <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--text-muted)' }}>{window.mFmtDate(s.date)} · {s.time} · {s.location}{s.respondedBy && s.status === 'Confirmed' ? ' · approved by ' + s.respondedBy : ''}{s.respondedBy && s.status === 'Declined' ? ' · declined by ' + s.respondedBy : ''}</div>
              </div>
              <window.StatusPill status={s.status} />
              <button onClick={() => { window.MData.del('shoots', s.id); refresh(); }} style={{ appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-faint)', padding: 4 }}><window.PIcon n="trash-2" s={15} /></button>
            </div>
            {s.changeRequest && (
              <div style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '9px 12px', borderRadius: 'var(--radius-md)', background: 'rgba(224,163,62,0.08)', border: '1px solid rgba(224,163,62,0.35)' }}>
                <window.PIcon n="calendar-clock" s={15} color="#e0a33e" />
                <span style={{ flex: 1, fontFamily: 'var(--font-sans)', fontSize: 13, color: '#e0a33e', lineHeight: 1.5 }}>Change requested{s.changeRequest.by ? ' by ' + s.changeRequest.by : ''}: “{s.changeRequest.note}”</span>
                <button onClick={() => { window.MData.update('shoots', s.id, { changeRequest: null }); refresh(); }} title="Mark handled — update the shoot details above, then clear this" style={{ appearance: 'none', border: '1px solid rgba(224,163,62,0.4)', background: 'none', borderRadius: 'var(--radius-sm)', cursor: 'pointer', color: '#e0a33e', fontFamily: 'var(--font-sans)', fontSize: 12, fontWeight: 600, padding: '5px 10px', whiteSpace: 'nowrap' }}>Handled</button>
              </div>
            )}
          </div>
        ))}
        {!shoots.length && <div style={{ padding: 30, textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)', fontSize: 14 }}>No shoots yet.</div>}
      </div>
    </div>
  );
}

function AdminContent({ clientId, refresh }) {
  const { Button, Input } = window.ManderaDesignSystem_8327ce;
  const items = window.MData.forClient('calendar', clientId).slice().sort((a, b) => a.date.localeCompare(b.date));
  const empty = { title: '', platform: 'Instagram', date: '', time: '', status: 'Draft', media: null };
  const [form, setForm] = React.useState(empty);
  const [busy, setBusy] = React.useState(false);
  const set = (k, v) => setForm((p) => ({ ...p, [k]: v }));
  const onFile = async (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    e.target.value = '';
    setBusy(true);
    const up = await window.mUploadFile(f);
    if (up) { set('media', up); setBusy(false); return; }
    const dataUrl = await window.mReadSmall(f, 2.5);
    setBusy(false);
    if (dataUrl) { set('media', { name: f.name, type: f.type, size: f.size, dataUrl }); return; }
    alert('Could not upload “' + f.name + '” — the server is unreachable and the file is too large to store locally.');
  };
  const add = (e) => {
    e.preventDefault();
    if (!form.title.trim() || !form.date) return;
    const it = window.MData.add('calendar', { clientId, ...form });
    if (!window.MData._persist()) alert('Saved, but the media file was too large to store locally. Try a smaller file or compress the video.');
    window.MData.notify({ clientId, type: 'schedule', text: 'New content scheduled: “' + form.title.trim() + '” (' + form.platform + ') · ' + window.mFmtDate(form.date), link: 'calendar', refId: it.id });
    setForm(empty); refresh();
  };
  const fld = { height: 42, padding: '0 12px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 14, width: '100%', boxSizing: 'border-box' };
  const isImg = (m) => m && m.type && m.type.startsWith('image');
  const isVid = (m) => m && m.type && m.type.startsWith('video');
  return (
    <div className="mp-grid2" style={{ display: 'grid', gridTemplateColumns: '340px 1fr', gap: 28, alignItems: 'start' }}>
      <form onSubmit={add} style={{ background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)', padding: 22, display: 'flex', flexDirection: 'column', gap: 14 }}>
        <ATitle>Schedule content</ATitle>
        <Input label="Title" value={form.title} onChange={(e) => set('title', e.target.value)} placeholder="Carousel — ingredient story" />
        <AField label="Platform"><ASelect value={form.platform} onChange={(e) => set('platform', e.target.value)} options={['Instagram', 'TikTok', 'Facebook', 'YouTube', 'Email']} /></AField>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <AField label="Date"><input type="date" value={form.date} onChange={(e) => set('date', e.target.value)} style={fld} /></AField>
          <AField label="Time"><input type="time" value={form.time} onChange={(e) => set('time', e.target.value)} style={fld} /></AField>
        </div>
        <AField label="Post media">
          <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 14px', border: '1px dashed var(--border-default)', borderRadius: 'var(--radius-md)', cursor: 'pointer', fontFamily: 'var(--font-sans)', fontSize: 13, color: form.media ? 'var(--accent-text)' : 'var(--text-muted)' }}>
            <window.PIcon n={form.media ? 'check' : 'upload'} s={16} color={form.media ? 'var(--accent-text)' : 'var(--text-muted)'} />
            <span style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{busy ? 'Reading…' : form.media ? form.media.name : 'Upload photo, reel or video'}</span>
            <input type="file" accept="image/*,video/*" onChange={onFile} style={{ display: 'none' }} />
          </label>
          {form.media && <button type="button" onClick={() => set('media', null)} style={{ alignSelf: 'flex-start', marginTop: 6, appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-faint)', fontFamily: 'var(--font-sans)', fontSize: 12 }}>Remove media</button>}
        </AField>
        <AField label="Status"><ASelect value={form.status} onChange={(e) => set('status', e.target.value)} options={['Draft', 'Scheduled']} /></AField>
        <Button variant="primary" type="submit" fullWidth iconLeft={<window.PIcon n="plus" s={16} color="var(--ink-950)" />}>Add to calendar</Button>
      </form>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {items.map((it) => (
          <div key={it.id} style={{ display: 'flex', flexDirection: 'column', gap: 12, padding: '14px 16px', background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-md)' }}>
            <div style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12.5, color: 'var(--text-muted)', width: 70 }}>{window.mFmtDate(it.date).split(',')[0]}</div>
            {it.media ? (
              isImg(it.media)
                ? <img src={it.media.url || it.media.dataUrl} alt="" style={{ width: 44, height: 44, borderRadius: 'var(--radius-sm)', objectFit: 'cover', border: '1px solid var(--border-subtle)' }} />
                : <div style={{ width: 44, height: 44, borderRadius: 'var(--radius-sm)', background: 'var(--surface-sunken)', border: '1px solid var(--border-subtle)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><window.PIcon n={isVid(it.media) ? 'film' : 'file'} s={18} color="var(--azure-400)" /></div>
            ) : null}
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14, fontWeight: 600, color: 'var(--text-strong)' }}>{it.title}</div>
              <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--text-muted)' }}>{it.platform}{it.time ? ' · ' + it.time : ''}{it.media ? ' · ' + it.media.name : ''}</div>
            </div>
            {it.media && <a href={it.media.url || it.media.dataUrl} download={it.media.name} title="Download media" style={{ display: 'inline-flex', color: 'var(--azure-400)', padding: 4 }}><window.PIcon n="download" s={16} color="var(--azure-400)" /></a>}
            {it.approval === 'approved' && <span title="Approved by the client" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-sans)', fontSize: 12, fontWeight: 600, color: 'var(--positive)', background: 'rgba(47,170,110,0.1)', border: '1px solid rgba(47,170,110,0.4)', borderRadius: 'var(--radius-pill)', padding: '4px 10px', whiteSpace: 'nowrap' }}><window.PIcon n="check" s={12} color="var(--positive)" /> Client</span>}
            {it.approval === 'changes' && <span title={it.approvalNote || 'Changes requested'} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-sans)', fontSize: 12, fontWeight: 600, color: '#e0a33e', background: 'rgba(224,163,62,0.1)', border: '1px solid rgba(224,163,62,0.4)', borderRadius: 'var(--radius-pill)', padding: '4px 10px', whiteSpace: 'nowrap' }}><window.PIcon n="pencil" s={12} color="#e0a33e" /> Changes</span>}
            <window.StatusPill status={it.status} />
            <button onClick={() => { window.MData.del('calendar', it.id); refresh(); }} style={{ appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-faint)', padding: 4 }}><window.PIcon n="trash-2" s={15} /></button>
            </div>
            <window.PNotes coll="calendar" item={it} me={{ name: ((window.MAuth.current() || {}).name || 'Mandera'), role: 'team' }} clientId={clientId} link="calendar" onChange={refresh} placeholder="Reply to the client / add a note…" />
          </div>
        ))}
        {!items.length && <div style={{ padding: 30, textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)', fontSize: 14 }}>No content scheduled.</div>}
      </div>
    </div>
  );
}

function AdminTimeline({ clientId, refresh }) {
  const { Button, Input } = window.ManderaDesignSystem_8327ce;
  const tl = window.MData.forClient('timeline', clientId);
  const [task, setTask] = React.useState('');
  const cycle = { upcoming: 'current', current: 'completed', completed: 'upcoming' };
  const add = (e) => { e.preventDefault(); if (!task.trim()) return; window.MData.add('timeline', { clientId, task: task.trim(), status: 'upcoming', date: new Date().toISOString().slice(0, 10) }); setTask(''); refresh(); };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14, maxWidth: 720 }}>
      <form onSubmit={add} style={{ display: 'flex', gap: 10, alignItems: 'flex-end' }}>
        <div style={{ flex: 1 }}><Input label="Add a task" value={task} onChange={(e) => setTask(e.target.value)} placeholder="e.g. Creative concepts" /></div>
        <Button variant="primary" type="submit" iconLeft={<window.PIcon n="plus" s={16} color="var(--ink-950)" />}>Add</Button>
      </form>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {tl.map((t) => (
          <div key={t.id} style={{ display: 'flex', flexDirection: 'column', gap: 10, padding: '12px 14px', background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-md)' }}>
            <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
              <button title="Cycle status" onClick={() => { window.MData.update('timeline', t.id, { status: cycle[t.status] }); refresh(); }} style={{ appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', padding: 0, display: 'inline-flex' }}>
                <window.PIcon n={t.status === 'completed' ? 'check-circle' : t.status === 'current' ? 'circle-dot' : 'circle'} s={18} color={t.status === 'completed' ? 'var(--positive)' : t.status === 'current' ? 'var(--accent-bright)' : 'var(--text-faint)'} />
              </button>
              <span style={{ flex: 1, fontFamily: 'var(--font-sans)', fontSize: 14, color: 'var(--text-strong)' }}>{t.task}</span>
              <span style={{ fontFamily: 'var(--font-sans)', fontSize: 12, color: 'var(--text-faint)' }}>{t.status}</span>
              <button onClick={() => { window.MData.del('timeline', t.id); refresh(); }} style={{ appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-faint)', padding: 4 }}><window.PIcon n="trash-2" s={15} /></button>
            </div>
            <window.PNotesBox coll="timeline" item={t} me={{ name: ((window.MAuth.current() || {}).name || 'Mandera'), role: 'team' }} clientId={clientId} link="timeline" what={'“' + t.task + '” on the project timeline'} onChange={refresh} placeholder="Comment on this step…" />
          </div>
        ))}
        {!tl.length && <div style={{ padding: 24, textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)', fontSize: 14 }}>No tasks yet.</div>}
      </div>
    </div>
  );
}

function AdminFiles({ clientId, refresh }) {
  const { Button } = window.ManderaDesignSystem_8327ce;
  const files = window.MData.forClient('files', clientId);
  const ref = React.useRef(null);
  const [busy, setBusy] = React.useState(false);
  const onUp = async (e) => {
    const fl = e.target.files && e.target.files[0]; if (!fl) return;
    e.target.value = '';
    const ext = (fl.name.split('.').pop() || '').toLowerCase();
    const kind = ext === 'pdf' ? 'pdf' : ['zip', 'rar'].includes(ext) ? 'zip' : ['png', 'jpg', 'jpeg'].includes(ext) ? 'img' : 'doc';
    setBusy(true);
    const up = await window.mUploadFile(fl);
    const dataUrl = up ? null : await window.mReadSmall(fl, 2.5);
    setBusy(false);
    if (!up && !dataUrl) { alert('Could not upload “' + fl.name + '” — the server is unreachable and the file is too large to store locally.'); return; }
    const f = window.MData.add('files', { clientId, name: fl.name, kind, size: (fl.size / 1048576).toFixed(1) + ' MB', by: 'Mandera team', date: new Date().toISOString().slice(0, 10), url: up ? up.url : null, dataUrl });
    window.MData.notify({ clientId, type: 'file', text: 'A new file was shared with you: ' + fl.name, link: 'files', refId: f.id });
    refresh();
  };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14, maxWidth: 760 }}>
      <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <Button variant="primary" size="sm" disabled={busy} onClick={() => ref.current && ref.current.click()} iconLeft={<window.PIcon n="upload" s={15} color="var(--ink-950)" />}>{busy ? 'Uploading…' : 'Upload for client'}</Button>
        <input ref={ref} type="file" style={{ display: 'none' }} onChange={onUp} />
      </div>
      <div style={{ border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' }}>
        {files.map((fl, i) => (
          <div key={fl.id} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '13px 16px', background: 'var(--surface-card)', borderTop: i ? '1px solid var(--border-subtle)' : 'none' }}>
            <window.PIcon n="file-text" s={18} color="var(--accent-text)" />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14, fontWeight: 600, color: 'var(--text-strong)' }}>{fl.name}</div>
              <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12, color: 'var(--text-muted)' }}>{fl.size} · {fl.by} · {window.mFmtDate(fl.date)}</div>
            </div>
            {(fl.url || fl.dataUrl) && <a href={fl.url || fl.dataUrl} download={fl.name} title="Download" style={{ display: 'inline-flex', color: 'var(--accent-text)', padding: 4 }}><window.PIcon n="download" s={16} color="var(--accent-text)" /></a>}
            <button onClick={() => { window.MData.del('files', fl.id); refresh(); }} style={{ appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-faint)', padding: 4 }}><window.PIcon n="trash-2" s={15} /></button>
          </div>
        ))}
        {!files.length && <div style={{ padding: 30, textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)', fontSize: 14 }}>No files.</div>}
      </div>
    </div>
  );
}

function AdminInvoices({ clientId, refresh }) {
  const { Button, Input } = window.ManderaDesignSystem_8327ce;
  const rows = window.MData.forClient('invoices', clientId).slice().sort((a, b) => (b.date || '').localeCompare(a.date || ''));
  const empty = { no: '', amount: '', status: 'Due', date: new Date().toISOString().slice(0, 10), file: null };
  const [form, setForm] = React.useState(empty);
  const [busy, setBusy] = React.useState(false);
  const set = (k, v) => setForm((p) => ({ ...p, [k]: v }));
  const onFile = async (e) => {
    const f = e.target.files && e.target.files[0]; if (!f) return;
    e.target.value = '';
    setBusy(true);
    const up = await window.mUploadFile(f);
    if (up) { set('file', { name: f.name, url: up.url }); setBusy(false); return; }
    const dataUrl = await window.mReadSmall(f, 4);
    setBusy(false);
    if (dataUrl) { set('file', { name: f.name, dataUrl }); return; }
    alert('Could not upload “' + f.name + '” — the server is unreachable and the file is too large to store locally.');
  };
  const add = (e) => {
    e.preventDefault();
    if (!form.no.trim() && !form.file) { alert('Add an invoice number or a file.'); return; }
    window.MData.add('invoices', { clientId, no: form.no.trim(), amount: form.amount.trim(), status: form.status, date: form.date, url: form.file ? form.file.url || null : null, dataUrl: form.file ? form.file.dataUrl || null : null, fileName: form.file ? form.file.name : null });
    if (!window.MData._persist()) alert('Saved, but the file was too large to store locally. Try a smaller PDF.');
    window.MData.notify({ clientId, type: 'invoice', text: 'New invoice' + (form.no.trim() ? ' ' + form.no.trim() : '') + (form.amount.trim() ? ' · ' + form.amount.trim() : ''), link: 'invoices' });
    setForm(empty); refresh();
  };
  const fld = { height: 42, padding: '0 12px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 14, width: '100%', boxSizing: 'border-box' };
  return (
    <div className="mp-grid2" style={{ display: 'grid', gridTemplateColumns: '340px 1fr', gap: 28, alignItems: 'start' }}>
      <form onSubmit={add} style={{ background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)', padding: 22, display: 'flex', flexDirection: 'column', gap: 14 }}>
        <ATitle>Add an invoice</ATitle>
        <Input label="Invoice number" value={form.no} onChange={(e) => set('no', e.target.value)} placeholder="INV-2026-001" />
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <Input label="Amount" value={form.amount} onChange={(e) => set('amount', e.target.value)} placeholder="$4,800" />
          <AField label="Status"><ASelect value={form.status} onChange={(e) => set('status', e.target.value)} options={['Due', 'Paid']} /></AField>
        </div>
        <AField label="Date"><input type="date" value={form.date} onChange={(e) => set('date', e.target.value)} style={fld} /></AField>
        <AField label="Invoice file (PDF)">
          <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 14px', border: '1px dashed var(--border-default)', borderRadius: 'var(--radius-md)', cursor: 'pointer', fontFamily: 'var(--font-sans)', fontSize: 13, color: form.file ? 'var(--accent-text)' : 'var(--text-muted)' }}>
            <window.PIcon n={form.file ? 'check' : 'upload'} s={16} color={form.file ? 'var(--accent-text)' : 'var(--text-muted)'} />
            <span style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{busy ? 'Reading…' : form.file ? form.file.name : 'Upload invoice PDF'}</span>
            <input type="file" accept=".pdf,image/*" onChange={onFile} style={{ display: 'none' }} />
          </label>
          {form.file && <button type="button" onClick={() => set('file', null)} style={{ alignSelf: 'flex-start', marginTop: 6, appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-faint)', fontFamily: 'var(--font-sans)', fontSize: 12 }}>Remove file</button>}
        </AField>
        <Button variant="primary" type="submit" fullWidth iconLeft={<window.PIcon n="plus" s={16} color="var(--ink-950)" />}>Add invoice</Button>
      </form>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {rows.map((r) => (
          <div key={r.id} style={{ display: 'flex', gap: 14, alignItems: 'center', padding: '14px 16px', background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-md)' }}>
            <window.PIcon n="receipt" s={18} color="var(--accent-text)" />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13.5, color: 'var(--text-strong)' }}>{r.no || r.fileName || 'Invoice'}</div>
              <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--text-muted)' }}>{r.date ? window.mFmtDate(r.date) : ''}{r.amount ? ' · ' + r.amount : ''} · {r.status || 'Due'}</div>
            </div>
            {(r.url || r.dataUrl) && <a href={r.url || r.dataUrl} download={r.fileName || ((r.no || 'invoice') + '.pdf')} title="Download" style={{ display: 'inline-flex', color: 'var(--accent-text)', padding: 4 }}><window.PIcon n="download" s={16} color="var(--accent-text)" /></a>}
            <button onClick={() => { if (confirm('Remove this invoice?')) { window.MData.del('invoices', r.id); refresh(); } }} style={{ appearance: 'none', border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-faint)', padding: 4 }}><window.PIcon n="trash-2" s={15} /></button>
          </div>
        ))}
        {!rows.length && <div style={{ padding: 30, textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)', fontSize: 14 }}>No invoices yet.</div>}
      </div>
    </div>
  );
}

function AdminOnboardingReview({ clientId, refresh }) {
  const { Button, Badge, Input } = window.ManderaDesignSystem_8327ce;
  const onb = window.MData.onboardingOf(clientId);
  const schema = window.MData.schema();
  const [editing, setEditing] = React.useState(false);
  const [data, setData] = React.useState(() => ({ ...(onb.data || {}) }));
  const [savedAt, setSavedAt] = React.useState(0);
  React.useEffect(() => { if (!editing) setData({ ...(onb.data || {}) }); }, [onb.status, editing]);

  const set = (k, v) => setData((p) => ({ ...p, [k]: v }));
  const toggle = (k, v, single) => setData((p) => {
    if (single) return { ...p, [k]: v };
    const arr = Array.isArray(p[k]) ? p[k] : [];
    return { ...p, [k]: arr.includes(v) ? arr.filter((x) => x !== v) : [...arr, v] };
  });
  const save = () => {
    window.MData.saveOnboarding(clientId, data, onb.status === 'pending' ? 'submitted' : onb.status);
    setEditing(false); setSavedAt(Date.now()); refresh();
  };

  const taStyle = { resize: 'vertical', width: '100%', boxSizing: 'border-box', padding: '10px 12px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 14, outline: 'none' };
  const renderEdit = (fld) => {
    if (fld.type === 'textarea') return <textarea rows={3} value={data[fld.key] || ''} onChange={(e) => set(fld.key, e.target.value)} placeholder={fld.hint || ''} style={taStyle} />;
    if (fld.type === 'chips') {
      const val = data[fld.key];
      const isOn = (o) => fld.single ? val === o : Array.isArray(val) && val.includes(o);
      return <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>{fld.options.map((o) => <window.OnbChip key={o} active={isOn(o)} onClick={() => toggle(fld.key, o, fld.single)}>{o}</window.OnbChip>)}</div>;
    }
    return <Input value={data[fld.key] || ''} onChange={(e) => set(fld.key, e.target.value)} placeholder={fld.hint || ''} />;
  };

  if (onb.status === 'pending' && !editing) {
    return (
      <div style={{ maxWidth: 720, display: 'flex', flexDirection: 'column', gap: 16 }}>
        <div style={{ padding: 30, textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)', fontSize: 14, background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)' }}>This client hasn’t submitted onboarding yet.</div>
        <Button variant="outline" onClick={() => { setData({ ...(onb.data || {}) }); setEditing(true); }} iconLeft={<window.PIcon n="pencil" s={15} color="var(--accent-text)" />}>Fill it in on their behalf</Button>
      </div>
    );
  }

  return (
    <div style={{ maxWidth: 720, display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <ATitle>Onboarding submission</ATitle>
        {onb.status === 'approved' ? <Badge tone="positive" variant="soft">Approved</Badge> : onb.status === 'submitted' ? <Badge tone="caution" variant="soft">Awaiting review</Badge> : <Badge tone="neutral" variant="outline">Draft</Badge>}
        <span style={{ flex: 1 }} />
        {!editing
          ? <Button variant="outline" size="sm" onClick={() => { setData({ ...(onb.data || {}) }); setEditing(true); }} iconLeft={<window.PIcon n="pencil" s={14} color="var(--accent-text)" />}>Edit answers</Button>
          : (<div style={{ display: 'flex', gap: 8 }}>
              <Button variant="ghost" size="sm" onClick={() => { setEditing(false); setData({ ...(onb.data || {}) }); }}>Cancel</Button>
              <Button variant="primary" size="sm" onClick={save} iconLeft={<window.PIcon n="check" s={14} color="var(--ink-950)" />}>Save changes</Button>
            </div>)}
      </div>
      {savedAt > 0 && !editing && <span style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--positive)' }}>Saved. The client sees these updated answers too.</span>}
      <div style={{ background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)', padding: 22, display: 'flex', flexDirection: 'column', gap: editing ? 18 : 0 }}>
        {schema.map((sec) => (
          <div key={sec.section} style={{ display: 'flex', flexDirection: 'column', gap: editing ? 14 : 0, ...(editing ? { paddingBottom: 6 } : {}) }}>
            {editing && <span className="mandera-eyebrow">{sec.section}</span>}
            {sec.fields.map((fld) => {
              if (editing) return (
                <div key={fld.key} style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
                  <label style={{ fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600, color: 'var(--text-secondary)' }}>{fld.label}</label>
                  {renderEdit(fld)}
                </div>
              );
              const v = onb.data[fld.key]; const disp = Array.isArray(v) ? v.join(', ') : v;
              return (
                <div key={fld.key} style={{ display: 'flex', justifyContent: 'space-between', gap: 24, padding: '10px 0', borderBottom: '1px solid var(--border-subtle)' }}>
                  <span style={{ fontFamily: 'var(--font-sans)', fontSize: 13.5, color: 'var(--text-muted)' }}>{fld.label}</span>
                  <span style={{ fontFamily: 'var(--font-sans)', fontSize: 13.5, fontWeight: 600, color: disp ? 'var(--text-strong)' : 'var(--text-faint)', textAlign: 'right', maxWidth: 400 }}>{disp || '—'}</span>
                </div>
              );
            })}
          </div>
        ))}
      </div>
      {!editing && (
        <div style={{ display: 'flex', gap: 12 }}>
          <Button variant="primary" disabled={onb.status === 'approved'} onClick={() => { window.MData.setOnboardingStatus(clientId, 'approved'); refresh(); }} iconLeft={<window.PIcon n="check" s={16} color="var(--ink-950)" />}>{onb.status === 'approved' ? 'Approved' : 'Approve onboarding'}</Button>
          <Button variant="outline" onClick={() => { window.MData.setOnboardingStatus(clientId, 'pending'); const a = window.MData.get('accounts').find((x) => x.clientId === clientId && x.role === 'client'); if (a) window.MData.update('accounts', a.id, { onboarded: false }); refresh(); }} iconLeft={<window.PIcon n="rotate-ccw" s={16} color="var(--accent-text)" />}>Send back to client</Button>
        </div>
      )}
    </div>
  );
}

/* ---------------- Accounts ---------------- */
function genPw() { const w = ['amber', 'azure', 'cedar', 'delta', 'ember', 'flint', 'grove', 'ivory']; return w[Math.floor(Math.random() * w.length)] + '-' + Math.floor(100 + Math.random() * 900); }

function AdminAccounts({ role, bump }) {
  const { Button, Input, Badge } = window.ManderaDesignSystem_8327ce;
  const [, setTick] = React.useState(0);
  const refresh = () => { setTick((t) => t + 1); bump && bump(); };
  const accounts = window.MData.get('accounts');
  const [nrole, setNrole] = React.useState('client');
  const [name, setName] = React.useState(''); const [email, setEmail] = React.useState(''); const [brand, setBrand] = React.useState(''); const [pw, setPw] = React.useState(genPw());
  const [created, setCreated] = React.useState(null); const [copied, setCopied] = React.useState(false);
  const isMaster = role === 'master';

  const create = (e) => { e.preventDefault(); if (!name.trim() || !email.trim()) return; const rec = window.MAuth.create({ role: nrole, name, email, password: pw, brand }); setCreated(rec); setCopied(false); setName(''); setEmail(''); setBrand(''); setPw(genPw()); refresh(); };
  const copy = (rec) => { navigator.clipboard && navigator.clipboard.writeText(`Mandera Client Portal\nEmail: ${rec.email}\nTemporary password: ${rec.password}`); setCopied(true); setTimeout(() => setCopied(false), 1600); };

  const seg = (on) => ({ appearance: 'none', border: 'none', cursor: 'pointer', padding: '8px 16px', borderRadius: 'var(--radius-sm)', fontFamily: 'var(--font-sans)', fontSize: 13.5, fontWeight: 600, background: on ? 'var(--accent)' : 'transparent', color: on ? 'var(--ink-950)' : 'var(--text-muted)' });

  return (
    <div className="mp-section mp-grid2" style={{ padding: 32, display: 'grid', gridTemplateColumns: '360px 1fr', gap: 32, alignItems: 'start' }}>
      <div style={{ background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-xl)', padding: 26, position: 'sticky', top: 20 }}>
        <ATitle>Create an account</ATitle>
        <p style={{ fontFamily: 'var(--font-sans)', fontSize: 13, color: 'var(--text-muted)', margin: '4px 0 18px' }}>They can sign in immediately. Clients set their own password on first sign-in.</p>
        <form onSubmit={create} style={{ display: 'flex', flexDirection: 'column', gap: 15 }}>
          <AField label="Account type">
            <div style={{ display: 'inline-flex', padding: 4, gap: 4, background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)' }}>
              <button type="button" style={seg(nrole === 'client')} onClick={() => setNrole('client')}>Client</button>
              <button type="button" style={seg(nrole === 'team')} onClick={() => setNrole('team')}>Team</button>
              {isMaster && <button type="button" style={seg(nrole === 'master')} onClick={() => setNrole('master')}>Master</button>}
            </div>
          </AField>
          <Input label="Full name" value={name} onChange={(e) => setName(e.target.value)} placeholder="Jane Doe" />
          <Input label="Email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="jane@brand.com" />
          {nrole === 'client' && <Input label="Brand / company" value={brand} onChange={(e) => setBrand(e.target.value)} placeholder="Acme Inc." />}
          <AField label="Temporary password">
            <div style={{ display: 'flex', gap: 8 }}>
              <div style={{ flex: 1 }}><Input value={pw} onChange={(e) => setPw(e.target.value)} /></div>
              <Button type="button" variant="secondary" onClick={() => setPw(genPw())} iconLeft={<window.PIcon n="refresh-cw" s={15} />}>New</Button>
            </div>
          </AField>
          <Button variant="primary" size="lg" type="submit" fullWidth iconRight={<window.PIcon n="user-plus" s={17} color="var(--ink-950)" />}>Create account</Button>
        </form>
        {created && (
          <div style={{ marginTop: 16, padding: 16, borderRadius: 'var(--radius-md)', background: 'var(--accent-soft)', border: '1px solid var(--border-accent)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}><window.PIcon n="check-circle" s={16} color="var(--accent-bright)" /><span style={{ fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600, color: 'var(--text-strong)' }}>Created — send these details</span></div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.6 }}>{created.email}<br />{created.password}</div>
            <Button variant="outline" size="sm" style={{ marginTop: 10 }} onClick={() => copy(created)} iconLeft={<window.PIcon n={copied ? 'check' : 'copy'} s={14} color="var(--accent-text)" />}>{copied ? 'Copied' : 'Copy details'}</Button>
          </div>
        )}
      </div>

      <div>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14 }}><ATitle>All accounts</ATitle><span style={{ fontFamily: 'var(--font-sans)', fontSize: 13, color: 'var(--text-muted)' }}>{accounts.length} total</span></div>
        <div style={{ border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' }}>
          {accounts.map((a, i) => {
            const canManage = isMaster || a.role === 'client';
            const protectedAcc = a.role === 'master';
            return (
              <div key={a.id} style={{ display: 'grid', gridTemplateColumns: '1fr 92px 84px auto', gap: 14, alignItems: 'center', padding: '13px 16px', background: 'var(--surface-card)', borderTop: i ? '1px solid var(--border-subtle)' : 'none', opacity: a.status === 'suspended' ? 0.6 : 1 }}>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14, fontWeight: 600, color: 'var(--text-strong)' }}>{a.name}</div>
                  <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--text-muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{a.email}</div>
                </div>
                <Badge tone={a.role === 'master' ? 'accent' : a.role === 'team' ? 'accent' : 'neutral'} variant={a.role === 'client' ? 'outline' : 'soft'}>{a.role}</Badge>
                {a.status === 'active' ? <Badge tone="positive" variant="outline">Active</Badge> : <Badge tone="critical" variant="outline">Suspended</Badge>}
                <div style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}>
                  <button title="Reset password" disabled={!canManage} onClick={() => { const np = genPw(); window.MAuth.resetPassword(a.id, np); refresh(); alert('New password for ' + a.name + ':\n' + np); }} style={{ appearance: 'none', border: '1px solid var(--border-default)', background: 'var(--surface-raised)', borderRadius: 'var(--radius-sm)', cursor: canManage ? 'pointer' : 'not-allowed', color: 'var(--text-secondary)', padding: 7, opacity: canManage ? 1 : 0.4 }}><window.PIcon n="key-round" s={14} /></button>
                  <button title={a.status === 'active' ? 'Suspend' : 'Reactivate'} disabled={!canManage || protectedAcc} onClick={() => { window.MAuth.suspend(a.id, a.status === 'active'); refresh(); }} style={{ appearance: 'none', border: '1px solid var(--border-default)', background: 'var(--surface-raised)', borderRadius: 'var(--radius-sm)', cursor: (canManage && !protectedAcc) ? 'pointer' : 'not-allowed', color: 'var(--text-secondary)', padding: 7, opacity: (canManage && !protectedAcc) ? 1 : 0.4 }}><window.PIcon n={a.status === 'active' ? 'ban' : 'circle-check'} s={14} /></button>
                  <button title="Delete" disabled={!isMaster || protectedAcc} onClick={() => { if (confirm('Delete ' + a.name + '?')) { window.MAuth.remove(a.id); refresh(); } }} style={{ appearance: 'none', border: '1px solid var(--border-default)', background: 'var(--surface-raised)', borderRadius: 'var(--radius-sm)', cursor: (isMaster && !protectedAcc) ? 'pointer' : 'not-allowed', color: 'var(--critical)', padding: 7, opacity: (isMaster && !protectedAcc) ? 1 : 0.4 }}><window.PIcon n="trash-2" s={14} /></button>
                </div>
              </div>
            );
          })}
        </div>
        {!isMaster && <p style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--text-faint)', marginTop: 12 }}>As a team (sub-master) account you can create clients and reset client passwords. Deleting accounts and managing master/team accounts is restricted to the Master account.</p>}
      </div>
    </div>
  );
}

/* ---------------- Admin messages (all conversations) ---------------- */
function AdminMessages({ acc, bump, initialClient }) {
  const { Button } = window.ManderaDesignSystem_8327ce;
  const clients = window.MData.clients();
  const [openId, setOpenId] = React.useState(initialClient || (clients[0] && clients[0].id));
  const [text, setText] = React.useState('');
  const [, setTick] = React.useState(0);
  const refresh = () => { setTick((t) => t + 1); bump && bump(); };
  const msgs = openId ? window.MData.forClient('messages', openId).slice().sort((a, b) => a.ts - b.ts) : [];
  const openClient = openId ? window.MData.client(openId) : null;
  const send = (e) => { e.preventDefault(); if (!text.trim() || !openId) return; window.MData.add('messages', { clientId: openId, fromRole: 'team', fromId: acc.id, fromName: (acc.name || 'Mandera').split(' ')[0], text: text.trim(), ts: Date.now(), read: true }); window.MData.notify({ clientId: openId, type: 'message', text: 'New message from your Mandera team', link: 'messages' }); setText(''); refresh(); };
  return (
    <div style={{ display: 'flex', height: '100%', overflow: 'hidden' }}>
      <div style={{ width: 280, flex: 'none', borderRight: '1px solid var(--border-subtle)', overflowY: 'auto' }} className="mandera-scroll">
        {clients.map((c) => {
          const last = window.MData.forClient('messages', c.id).slice().sort((a, b) => b.ts - a.ts)[0];
          return (
            <button key={c.id} onClick={() => setOpenId(c.id)} style={{ width: '100%', textAlign: 'left', display: 'flex', gap: 12, alignItems: 'center', padding: '14px 18px', background: openId === c.id ? 'var(--surface-raised)' : 'transparent', border: 'none', borderBottom: '1px solid var(--border-subtle)', cursor: 'pointer' }}>
              <window.Avatar name={c.brand} src={c.avatar} size={36} fontSize={12} />
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ fontFamily: 'var(--font-sans)', fontSize: 13.5, fontWeight: 600, color: 'var(--text-strong)' }}>{c.brand}</div>
                <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12, color: 'var(--text-muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{last ? last.text : 'No messages'}</div>
              </div>
            </button>
          );
        })}
      </div>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
        <div style={{ flex: 1, overflowY: 'auto', padding: 24, display: 'flex', flexDirection: 'column', gap: 14 }} className="mandera-scroll">
          {msgs.map((m) => { const mine = m.fromId ? m.fromId === acc.id : false; const isClient = m.fromRole === 'client'; const av = !mine ? (isClient ? (window.mAvatarOf(m.fromId) || (openClient && openClient.avatar)) : window.mAvatarOf(m.fromId)) : null; return (
            <div key={m.id} style={{ display: 'flex', justifyContent: mine ? 'flex-end' : 'flex-start', gap: 10 }}>
              {!mine && <window.Avatar name={isClient ? (openClient && openClient.brand) || m.fromName : m.fromName} src={av} size={32} accent={!isClient && !av} fontSize={12} />}
              <div style={{ maxWidth: 460 }}>
                <div style={{ padding: '11px 15px', borderRadius: 'var(--radius-lg)', fontFamily: 'var(--font-sans)', fontSize: 14, lineHeight: 1.5, background: mine ? 'var(--accent)' : 'var(--surface-card)', color: mine ? 'var(--ink-950)' : 'var(--text-body)', border: mine ? 'none' : '1px solid var(--border-subtle)' }}>{m.text}</div>
                <div style={{ fontFamily: 'var(--font-sans)', fontSize: 11, color: 'var(--text-faint)', marginTop: 4, textAlign: mine ? 'right' : 'left' }}>{m.fromName}{isClient ? '' : ' · Mandera'} · {window.mTimeAgo(m.ts)}</div>
              </div>
            </div>
          ); })}
          {!msgs.length && <div style={{ margin: 'auto', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)' }}>No messages with this client yet.</div>}
        </div>
        <form onSubmit={send} style={{ display: 'flex', gap: 12, padding: 20, borderTop: '1px solid var(--border-subtle)' }}>
          <input value={text} onChange={(e) => setText(e.target.value)} placeholder="Reply…" style={{ flex: 1, height: 46, padding: '0 16px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 15, outline: 'none' }} />
          <Button variant="primary" type="submit" iconRight={<window.PIcon n="send" s={16} color="var(--ink-950)" />}>Send</Button>
        </form>
      </div>
    </div>
  );
}

/* ---------------- Team chat (Mandera team + owners only) ---------------- */
function AdminTeamChat({ acc, bump }) {
  const { Button } = window.ManderaDesignSystem_8327ce;
  const [text, setText] = React.useState('');
  const [, setTick] = React.useState(0);
  const refresh = () => { setTick((t) => t + 1); bump && bump(); };
  const endRef = React.useRef(null);
  const msgs = window.MData.get('teamMessages').slice().sort((a, b) => a.ts - b.ts);
  React.useEffect(() => { if (endRef.current) endRef.current.scrollTop = endRef.current.scrollHeight; });
  const send = (e) => { e.preventDefault(); if (!text.trim()) return; window.MData.add('teamMessages', { fromId: acc.id, fromName: acc.name, fromRole: acc.role, text: text.trim(), ts: Date.now() }); setText(''); refresh(); };
  return (
    <div className="mp-chat" style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <div style={{ padding: '14px 24px', borderBottom: '1px solid var(--border-subtle)', display: 'flex', alignItems: 'center', gap: 10 }}>
        <window.PIcon n="users" s={16} color="var(--accent-text)" />
        <span style={{ fontFamily: 'var(--font-sans)', fontSize: 13.5, color: 'var(--text-muted)' }}>Internal channel — every Mandera team member and owner. Clients never see this.</span>
      </div>
      <div ref={endRef} style={{ flex: 1, overflowY: 'auto', padding: 24, display: 'flex', flexDirection: 'column', gap: 16 }} className="mandera-scroll">
        {msgs.map((m) => { const mine = m.fromId === acc.id; const av = !mine ? window.mAvatarOf(m.fromId) : null; return (
          <div key={m.id} style={{ display: 'flex', justifyContent: mine ? 'flex-end' : 'flex-start', gap: 10 }}>
            {!mine && <window.Avatar name={m.fromName} src={av} size={32} accent={!av} fontSize={12} />}
            <div style={{ maxWidth: 460 }}>
              <div style={{ padding: '11px 15px', borderRadius: 'var(--radius-lg)', fontFamily: 'var(--font-sans)', fontSize: 14, lineHeight: 1.5, background: mine ? 'var(--accent)' : 'var(--surface-card)', color: mine ? 'var(--ink-950)' : 'var(--text-body)', border: mine ? 'none' : '1px solid var(--border-subtle)' }}>{m.text}</div>
              <div style={{ fontFamily: 'var(--font-sans)', fontSize: 11, color: 'var(--text-faint)', marginTop: 4, textAlign: mine ? 'right' : 'left' }}>{m.fromName}{m.fromRole === 'master' ? ' · Owner' : ''} · {window.mTimeAgo(m.ts)}</div>
            </div>
          </div>
        ); })}
        {!msgs.length && <div style={{ margin: 'auto', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)', textAlign: 'center' }}>No messages yet — start the team conversation.</div>}
      </div>
      <form onSubmit={send} style={{ display: 'flex', gap: 12, padding: 20, borderTop: '1px solid var(--border-subtle)' }}>
        <input value={text} onChange={(e) => setText(e.target.value)} placeholder="Message the team…" style={{ flex: 1, height: 46, padding: '0 16px', background: 'var(--surface-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', color: 'var(--text-strong)', fontFamily: 'var(--font-sans)', fontSize: 15, outline: 'none' }} />
        <Button variant="primary" type="submit" iconRight={<window.PIcon n="send" s={16} color="var(--ink-950)" />}>Send</Button>
      </form>
    </div>
  );
}

/* ---------------- Onboarding queue ---------------- */
function AdminOnboardingQueue({ go, setClient }) {
  const { Badge, Button } = window.ManderaDesignSystem_8327ce;
  const db = window.MData.load();
  const rows = window.MData.clients().map((c) => ({ c, onb: window.MData.onboardingOf(c.id) }));
  return (
    <div style={{ padding: 32, display: 'flex', flexDirection: 'column', gap: 12 }}>
      {rows.map(({ c, onb }) => (
        <div key={c.id} style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '16px 18px', background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', borderRadius: 'var(--radius-md)' }}>
          <span style={{ width: 40, height: 40, borderRadius: '50%', flex: 'none', background: 'var(--surface-raised)', border: '1px solid var(--border-default)', color: 'var(--accent-text)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontWeight: 600, fontFamily: 'var(--font-sans)', fontSize: 13 }}>{window.mInitials(c.brand)}</span>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14.5, fontWeight: 600, color: 'var(--text-strong)' }}>{c.brand}</div>
            <div style={{ fontFamily: 'var(--font-sans)', fontSize: 12.5, color: 'var(--text-muted)' }}>{c.contact}</div>
          </div>
          {onb.status === 'approved' ? <Badge tone="positive" variant="soft">Approved</Badge> : onb.status === 'submitted' ? <Badge tone="caution" variant="soft">Awaiting review</Badge> : <Badge tone="neutral" variant="outline">Not submitted</Badge>}
          <Button variant="outline" size="sm" disabled={onb.status === 'pending'} onClick={() => { setClient(c.id); go('clients'); }} iconRight={<window.PIcon n="arrow-right" s={15} color="var(--accent-text)" />}>Review</Button>
        </div>
      ))}
    </div>
  );
}

/* ---------------- Admin notifications (message / shoot / everything) ---------------- */
function AdminNotifications({ openFromNotif, bump }) {
  const { Button } = window.ManderaDesignSystem_8327ce;
  const notes = window.MData.teamNotifications().slice().sort((a, b) => b.ts - a.ts);
  const icon = { shoot: 'camera', file: 'file-text', message: 'message-square', schedule: 'calendar-days', revision: 'git-pull-request', invoice: 'receipt', onboarding: 'clipboard-check', approval: 'check-check', note: 'message-circle', shootchange: 'calendar-clock' };
  const markAll = () => { notes.forEach((n) => window.MData.update('notifications', n.id, { read: true })); bump(); };
  const open = (n) => { window.MData.update('notifications', n.id, { read: true }); openFromNotif(n); };
  return (
    <div style={{ padding: 32, display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <Button variant="ghost" size="sm" onClick={markAll} iconLeft={<window.PIcon n="check-check" s={15} />}>Mark all read</Button>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {notes.map((n) => (
          <div key={n.id} onClick={() => open(n)} style={{ display: 'flex', gap: 14, alignItems: 'center', padding: '14px 16px', background: n.read ? 'var(--surface-card)' : 'var(--accent-soft)', border: '1px solid', borderColor: n.read ? 'var(--border-subtle)' : 'var(--border-accent)', borderRadius: 'var(--radius-md)', cursor: 'pointer' }}>
            <window.PIcon n={icon[n.type] || 'bell'} s={18} color={n.read ? 'var(--text-muted)' : 'var(--accent-text)'} />
            <span style={{ flex: 1, fontFamily: 'var(--font-sans)', fontSize: 14, color: 'var(--text-body)' }}>{n.text}</span>
            <window.PIcon n="chevron-right" s={15} color="var(--text-faint)" />
            <span style={{ fontFamily: 'var(--font-sans)', fontSize: 12, color: 'var(--text-faint)' }}>{window.mTimeAgo(n.ts)}</span>
          </div>
        ))}
        {!notes.length && <div style={{ padding: '60px 0', textAlign: 'center', fontFamily: 'var(--font-sans)', color: 'var(--text-faint)' }}>You’re all caught up.</div>}
      </div>
    </div>
  );
}

/* ---------------- Admin shell ---------------- */
function AdminApp() {
  const [nav, setNav] = React.useState('overview');
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [, setTick] = React.useState(0);
  const [forceClient, setForceClient] = React.useState(null);
  const [msgClient, setMsgClient] = React.useState(null);
  const bump = () => setTick((t) => t + 1);
  const acc = window.MAuth.current();
  if (!acc) return <div style={{ padding: 40, color: 'var(--text-muted)' }}>No session.</div>;
  const role = acc.role;

  const unreadNotif = window.MData.teamNotifications().filter((n) => !n.read).length;
  const NAV = [
    { id: 'overview', label: 'Overview', icon: 'layout-dashboard' },
    { id: 'clients', label: 'Clients', icon: 'users' },
    { id: 'onboarding', label: 'Onboarding', icon: 'clipboard-check' },
    { id: 'messages', label: 'Messages', icon: 'message-square' },
    { id: 'teamchat', label: 'Team Chat', icon: 'users-round' },
    { id: 'notifications', label: 'Notifications', icon: 'bell', badge: unreadNotif || undefined },
    { id: 'accounts', label: 'Accounts', icon: 'shield' },
  ];
  const TITLES = {
    overview: ['Overview', 'All clients at a glance'],
    clients: ['Clients', 'Manage projects, schedules & content'],
    onboarding: ['Onboarding', 'Review & approve client submissions'],
    messages: ['Messages', 'All client conversations'],
    teamchat: ['Team Chat', 'Internal — Mandera team & owners only'],
    notifications: ['Notifications', 'Messages, shoots & updates across every client'],
    accounts: ['Accounts', role === 'master' ? 'Full account control' : 'Create clients & manage access'],
  };
  const go = (id) => { setNav(id); setMenuOpen(false); };
  React.useEffect(() => { window.__mpView = nav; }, [nav]);
  // Open the right place when a notification is pressed.
  const openFromNotif = (n) => {
    if (n.type === 'message' && n.refId) { setMsgClient(n.refId); setNav('messages'); }
    else if (n.refId && (n.type === 'revision' || n.type === 'onboarding' || n.type === 'shoot' || n.type === 'schedule' || n.type === 'file' || n.type === 'invoice' || n.type === 'approval' || n.type === 'shootchange' || n.type === 'note')) { setForceClient(n.refId); setNav('clients'); }
    else if (n.type === 'onboarding') { setNav('onboarding'); }
    else { setNav(n.link || 'overview'); }
    setMenuOpen(false);
  };
  const [title, sub] = TITLES[nav];
  const footer = <window.UserCard name={acc.name} sub={role === 'master' ? 'Owner · full access' : 'Team · sub-master'} accent src={acc.avatar} onAvatar={(d) => { window.MData.update('accounts', acc.id, { avatar: d }); bump(); }} />;

  // when navigating to clients with a forced client, open it
  const clientsKey = forceClient ? 'detail:' + forceClient : 'list';

  return (
    <div className="mp-shell" style={{ display: 'flex', height: '100vh', background: 'var(--bg-canvas)', overflow: 'hidden' }}>
      {menuOpen && <div className="mp-overlay" onClick={() => setMenuOpen(false)} />}
      <window.Sidebar nav={NAV} active={nav} go={(id) => { setForceClient(null); setMsgClient(null); go(id); }} label={role === 'master' ? 'Owner Console' : 'Team Console'} footer={footer} mobileOpen={menuOpen} onSignOut={() => { window.MAuth.signOut(); window.__portalGo && window.__portalGo('login'); }} />
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
        <window.Topbar title={title} sub={sub} user={{ name: acc.name, sub: role, src: acc.avatar }} notifCount={unreadNotif} onBell={() => go('notifications')} onMenu={() => setMenuOpen(true)} />
        <main style={{ flex: 1, overflow: (nav === 'messages' || nav === 'teamchat') ? 'hidden' : 'auto' }} className="mandera-scroll">
          {nav === 'overview' && <AdminOverview go={go} />}
          {nav === 'clients' && (forceClient ? <AdminClientDetail key={clientsKey} clientId={forceClient} back={() => setForceClient(null)} bump={bump} /> : <AdminClients bump={bump} />)}
          {nav === 'onboarding' && <AdminOnboardingQueue go={go} setClient={setForceClient} />}
          {nav === 'messages' && <AdminMessages key={'msg:' + (msgClient || 'all')} acc={acc} bump={bump} initialClient={msgClient} />}
          {nav === 'teamchat' && <AdminTeamChat acc={acc} bump={bump} />}
          {nav === 'notifications' && <AdminNotifications openFromNotif={openFromNotif} bump={bump} />}
          {nav === 'accounts' && <AdminAccounts role={role} bump={bump} />}
        </main>
      </div>
    </div>
  );
}

Object.assign(window, { AdminApp });
