// Admin — full CRUD for campaigns/clients/influencers/bookings/users + i18n string editor.
// Tabs live at top. Uses PulseStore API; localStorage by default, pilot backend when ?api=1 is enabled.
const { useState: useStateAD, useEffect: useEffectAD, useMemo: useMemoAD } = React;

const AdminPanel = () => {
  const t = useT();
  const isMobile = useIsMobile();
  const [tab, setTab] = useStateAD('campaigns');
  const [, force] = React.useReducer(x => x + 1, 0);
  useEffectAD(() => {
    const h = () => force();
    window.addEventListener('pulse-data-change', h);
    window.addEventListener('pulse-lang-change', h);
    return () => { window.removeEventListener('pulse-data-change', h); window.removeEventListener('pulse-lang-change', h); };
  }, []);

  const tabs = [
    { k: 'campaigns',   l: t('admin.tab_campaigns'),   icon: 'megaphone' },
    { k: 'clients',     l: t('admin.tab_clients'),     icon: 'users' },
    { k: 'influencers', l: t('admin.tab_influencers'), icon: 'users-group' },
    { k: 'bookings',    l: t('admin.tab_bookings'),    icon: 'file-text' },
    { k: 'users',       l: t('admin.tab_users'),       icon: 'users' },
    { k: 'i18n',        l: t('admin.tab_i18n'),        icon: 'globe' },
    { k: 'data',        l: t('admin.tab_danger'),      icon: 'database' },
  ];

  return (
    <div style={{ padding: isMobile ? 16 : '24px 32px 80px', maxWidth: 1400, margin: '0 auto' }}>
      <div style={{ marginBottom: 24 }}>
        <h1 style={adStyles.title}>{t('admin.title')}</h1>
        <div style={{ fontSize: 14, color: 'var(--text-secondary)', marginTop: 6 }}>{t('admin.subtitle')}</div>
      </div>

      {/* Tab bar — horizontal scroll on mobile */}
      <div style={{ display: 'flex', gap: 4, borderBottom: '1px solid var(--border)', marginBottom: 16, overflowX: 'auto' }}>
        {tabs.map(tb => (
          <button key={tb.k} onClick={() => setTab(tb.k)} style={{
            padding: '10px 16px', fontSize: 12,
            color: tab === tb.k ? 'var(--ink-900)' : 'var(--ink-500)',
            fontWeight: 700,
            borderBottomWidth: 2, borderBottomStyle: 'solid',
            borderBottomColor: tab === tb.k ? 'var(--brand-500)' : 'transparent',
            marginBottom: -1, whiteSpace: 'nowrap',
            textTransform: 'uppercase', letterSpacing: '0.06em',
            display: 'flex', alignItems: 'center', gap: 8,
            background: 'transparent',
            borderTopWidth: 0, borderTopStyle: 'none', borderTopColor: 'transparent',
            borderLeftWidth: 0, borderLeftStyle: 'none', borderLeftColor: 'transparent',
            borderRightWidth: 0, borderRightStyle: 'none', borderRightColor: 'transparent',
          }}>
            <Icon name={tb.icon} size={13}/>
            {tb.l}
          </button>
        ))}
      </div>

      {tab === 'campaigns'   && <CampaignsAdmin/>}
      {tab === 'clients'     && <ClientsAdmin/>}
      {tab === 'influencers' && <InfluencersAdmin/>}
      {tab === 'bookings'    && <BookingsAdmin/>}
      {tab === 'users'       && <UsersAdmin/>}
      {tab === 'i18n'        && <I18nEditor/>}
      {tab === 'data'        && <DataAdmin/>}
    </div>
  );
};

// ---------- Shared helpers ----------
const AdminToolbar = ({ search, setSearch, count, actions }) => {
  const t = useT();
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14, flexWrap: 'wrap' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, background: 'var(--ink-100)', padding: '6px 10px', borderRadius: 4, flex: '1 1 240px', minWidth: 200 }}>
        <Icon name="search" size={14} style={{ color: 'var(--text-muted)' }}/>
        <input
          placeholder={t('action.search')}
          value={search}
          onChange={e => setSearch(e.target.value)}
          style={{ border: 'none', background: 'transparent', outline: 'none', flex: 1, fontSize: 13, color: 'var(--text-primary)', fontFamily: 'inherit' }}
        />
      </div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-muted)', letterSpacing: '0.1em', fontWeight: 700, textTransform: 'uppercase' }}>
        {t('admin.rows_n', { n: count })}
      </div>
      <div style={{ flex: 1 }}/>
      {actions}
    </div>
  );
};

const IconButton = ({ icon, onClick, title, danger }) => (
  <button onClick={onClick} title={title} style={{
    width: 28, height: 28, display: 'grid', placeItems: 'center',
    border: '1px solid var(--border)', background: 'var(--bg-panel)',
    color: danger ? 'var(--brand-500)' : 'var(--text-secondary)',
    cursor: 'pointer',
  }}>
    <Icon name={icon} size={13}/>
  </button>
);

const PLATFORM_OPTIONS = [
  { key: 'tiktok', label: 'TikTok' },
  { key: 'instagram', label: 'Instagram' },
  { key: 'facebook', label: 'Facebook' },
];
const emptyPlatformKpis = () => PLATFORM_OPTIONS.reduce((acc, p) => {
  acc[p.key] = { committedViews: 0, committedEngagement: 0, committedReach: 0, committedPosts: 0, avgEngagementRate: 0, benchmarkViews: 0 };
  return acc;
}, {});
const platformLabel = (p) => PLATFORM_OPTIONS.find(x => x.key === p)?.label || p;
const platformList = (arr) => (arr && arr.length ? arr : PLATFORM_OPTIONS.map(p => p.key));
const PlatformChips = ({ platforms }) => (
  <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
    {platformList(platforms).map(p => <span key={p} className="chip" style={{ fontSize: 10, padding: '3px 7px' }}>{platformLabel(p)}</span>)}
  </div>
);
const PlatformPicker = ({ value, onChange }) => {
  const selected = new Set(platformList(value));
  const toggle = (key) => {
    const next = new Set(selected);
    next.has(key) ? next.delete(key) : next.add(key);
    onChange(Array.from(next));
  };
  return (
    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
      {PLATFORM_OPTIONS.map(p => (
        <button key={p.key} type="button" className={`btn ${selected.has(p.key) ? 'brand' : ''}`} onClick={() => toggle(p.key)} style={{ padding: '7px 10px', fontSize: 11 }}>
          {selected.has(p.key) && <Icon name="check" size={12}/>} {p.label}
        </button>
      ))}
    </div>
  );
};
const PlatformKpiEditor = ({ value, onChange, mode = 'campaign', activePlatforms }) => {
  const rows = { ...emptyPlatformKpis(), ...(value || {}) };
  const active = new Set(platformList(activePlatforms));
  const update = (platform, patch) => onChange({ ...rows, [platform]: { ...rows[platform], ...patch } });
  return (
    <div style={{ display: 'grid', gap: 10 }}>
      {PLATFORM_OPTIONS.filter(p => !activePlatforms || active.has(p.key)).map(p => {
        const row = rows[p.key] || {};
        return (
          <div key={p.key} style={{ border: '1px solid var(--border)', background: 'var(--bg-elevated)', borderRadius: 6, padding: 12 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, fontSize: 12, fontWeight: 800, textTransform: 'uppercase', letterSpacing: '0.06em' }}>
              <PlatformBadge platform={p.key} size={18}/> {p.label}
            </div>
            {mode === 'campaign' ? (
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 8 }}>
                <Field label="Views"><input type="number" style={modalStyles.input} value={row.committedViews || 0} onChange={e => update(p.key, { committedViews: +e.target.value })}/></Field>
                <Field label="Engagement"><input type="number" style={modalStyles.input} value={row.committedEngagement || 0} onChange={e => update(p.key, { committedEngagement: +e.target.value })}/></Field>
                <Field label="Reach"><input type="number" style={modalStyles.input} value={row.committedReach || 0} onChange={e => update(p.key, { committedReach: +e.target.value })}/></Field>
                <Field label="Posts"><input type="number" style={modalStyles.input} value={row.committedPosts || 0} onChange={e => update(p.key, { committedPosts: +e.target.value })}/></Field>
              </div>
            ) : (
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 8 }}>
                <Field label="Avg ER %"><input type="number" step="0.1" style={modalStyles.input} value={row.avgEngagementRate || 0} onChange={e => update(p.key, { avgEngagementRate: +e.target.value })}/></Field>
                <Field label="Avg views/post"><input type="number" style={modalStyles.input} value={row.benchmarkViews || 0} onChange={e => update(p.key, { benchmarkViews: +e.target.value })}/></Field>
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
};
const CampaignKpiSummary = ({ campaign }) => {
  const targets = campaign.kpiTargets || {};
  const views = campaign.committedViews || Object.values(targets).reduce((s, x) => s + (+x.committedViews || 0), 0);
  const eng = campaign.committedEngagement || Object.values(targets).reduce((s, x) => s + (+x.committedEngagement || 0), 0);
  const posts = campaign.committedPosts || Object.values(targets).reduce((s, x) => s + (+x.committedPosts || 0), 0);
  return (
    <div style={{ display: 'grid', gap: 3, fontSize: 11 }}>
      <div><strong>{window.PulseStore.fmt(views)}</strong> views</div>
      <div><strong>{window.PulseStore.fmt(eng)}</strong> engagement</div>
      <div><strong>{posts || '—'}</strong> posts</div>
    </div>
  );
};
const InfluencerKpiSummary = ({ influencer }) => {
  const row = (influencer.platformKpis || {})[influencer.platform] || {};
  return (
    <div style={{ display: 'grid', gap: 3, fontSize: 11, textAlign: 'right' }}>
      <div><strong>{row.avgEngagementRate || influencer.avgEngagementRate || 0}%</strong> ER</div>
      <div><strong>{window.PulseStore.fmt(row.benchmarkViews || 0)}</strong> avg views</div>
    </div>
  );
};

// ---------- Campaigns ----------
const CampaignsAdmin = () => {
  const t = useT();
  const [search, setSearch] = useStateAD('');
  const [edit, setEdit] = useStateAD(null);
  const [showNew, setShowNew] = useStateAD(false);

  const all = window.PulseStore.getCampaigns();
  const clients = window.PulseStore.getClients();
  const filtered = all.filter(c =>
    !search || c.name.toLowerCase().includes(search.toLowerCase()) || (c.brand || '').toLowerCase().includes(search.toLowerCase())
  );

  return (
    <div>
      <AdminToolbar search={search} setSearch={setSearch} count={filtered.length} actions={
        <button className="btn brand" onClick={() => setShowNew(true)}><Icon name="plus" size={13}/> {t('action.new')}</button>
      }/>
      <div className="panel" style={{ padding: 0, overflow: 'auto' }}>
        <table style={adStyles.table}>
          <thead>
            <tr>
              <th style={adStyles.th}>Name</th>
              <th style={adStyles.th}>Client</th>
              <th style={adStyles.th}>Status</th>
              <th style={adStyles.th}>Platforms</th>
              <th style={adStyles.th}>Dates</th>
              <th style={{ ...adStyles.th, textAlign: 'right' }}>Budget</th>
              <th style={adStyles.th}>KPI details</th>
              <th style={{ ...adStyles.th, textAlign: 'right' }}>Done</th>
              <th style={adStyles.th}></th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(c => {
              const client = clients.find(cl => cl.id === c.clientId);
              return (
                <tr key={c.id} style={adStyles.row}>
                  <td style={adStyles.td}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <div style={{ width: 24, height: 24, background: c.brandColor, color: '#FFF', display: 'grid', placeItems: 'center', fontFamily: 'var(--font-display)', fontSize: 11 }}>{(c.brand || '?').charAt(0)}</div>
                      <div>
                        <div style={{ fontWeight: 600 }}>{c.name}</div>
                        <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{c.id}</div>
                      </div>
                    </div>
                  </td>
                  <td style={adStyles.td}>{client?.name || '—'}</td>
                  <td style={adStyles.td}><StatusBadge status={c.status}/></td>
                  <td style={adStyles.td}><PlatformChips platforms={c.platforms}/></td>
                  <td style={adStyles.td}><span style={{ fontFamily: 'var(--font-mono)', fontSize: 11 }}>{c.startDate} → {c.endDate}</span></td>
                  <td style={{ ...adStyles.td, textAlign: 'right' }} className="num">${c.budget.toLocaleString()}</td>
                  <td style={adStyles.td}><CampaignKpiSummary campaign={c}/></td>
                  <td style={{ ...adStyles.td, textAlign: 'right' }} className="num">{c.kpiPct}%</td>
                  <td style={adStyles.td}>
                    <div style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}>
                      <IconButton icon="edit" onClick={() => setEdit(c)}/>
                      <IconButton icon="trash" onClick={() => { if (confirm('Delete ' + c.name + '?')) window.PulseStore.deleteCampaign(c.id); }} danger/>
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      {edit && <EditCampaignDrawer campaign={edit} onClose={() => setEdit(null)}/>}
      {showNew && <EditCampaignDrawer campaign={null} onClose={() => setShowNew(false)}/>}
    </div>
  );
};

const EditCampaignDrawer = ({ campaign, onClose }) => {
  const t = useT();
  const clients = window.PulseStore.getClients();
  const [form, setForm] = useStateAD(campaign || {
    name: '', clientId: clients[0]?.id || '', status: 'draft',
    startDate: new Date().toISOString().slice(0,10),
    endDate: new Date(Date.now()+30*864e5).toISOString().slice(0,10),
    budget: 20000, committedViews: 5000000, committedEngagement: 200000, committedReach: 0, committedPosts: 0,
    platforms: ['tiktok'], kpiTargets: emptyPlatformKpis(),
    brandColor: '#EC2024', conversionsEnabled: false, objective: 'awareness',
  });
  const save = () => {
    const totals = Object.values(form.kpiTargets || {}).reduce((acc, row) => {
      acc.views += +row.committedViews || 0;
      acc.engagement += +row.committedEngagement || 0;
      acc.reach += +row.committedReach || 0;
      acc.posts += +row.committedPosts || 0;
      return acc;
    }, { views: 0, engagement: 0, reach: 0, posts: 0 });
    const payload = {
      ...form,
      budget: +form.budget || 0,
      committedViews: totals.views || +form.committedViews || 0,
      committedEngagement: totals.engagement || +form.committedEngagement || 0,
      committedReach: totals.reach || +form.committedReach || 0,
      committedPosts: totals.posts || +form.committedPosts || 0,
    };
    if (campaign) window.PulseStore.updateCampaign(campaign.id, payload);
    else          window.PulseStore.createCampaign(payload);
    onClose();
  };
  return (
    <Drawer title={campaign ? `Edit campaign` : t('nav.new_campaign')} onClose={onClose}>
      <Field label="Name"><input style={modalStyles.input} value={form.name} onChange={e => setForm({ ...form, name: e.target.value })}/></Field>
      <Field label="Client">
        <select style={modalStyles.input} value={form.clientId || ''} onChange={e => setForm({ ...form, clientId: e.target.value })}>
          <option value="">—</option>
          {clients.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
        </select>
      </Field>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <Field label="Status">
          <select style={modalStyles.input} value={form.status} onChange={e => setForm({ ...form, status: e.target.value })}>
            <option value="draft">Draft</option>
            <option value="live">Live</option>
            <option value="ended">Ended</option>
          </select>
        </Field>
        <Field label="Brand color"><input type="color" style={{ ...modalStyles.input, padding: 4, height: 38 }} value={form.brandColor} onChange={e => setForm({ ...form, brandColor: e.target.value })}/></Field>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <Field label="Start"><input type="date" style={modalStyles.input} value={form.startDate} onChange={e => setForm({ ...form, startDate: e.target.value })}/></Field>
        <Field label="End"><input type="date" style={modalStyles.input} value={form.endDate} onChange={e => setForm({ ...form, endDate: e.target.value })}/></Field>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
        <Field label="Budget (USD)"><input type="number" style={modalStyles.input} value={form.budget} onChange={e => setForm({ ...form, budget: +e.target.value })}/></Field>
        <Field label="Committed views"><input type="number" style={modalStyles.input} value={form.committedViews} onChange={e => setForm({ ...form, committedViews: +e.target.value })}/></Field>
        <Field label="Committed engagement"><input type="number" style={modalStyles.input} value={form.committedEngagement} onChange={e => setForm({ ...form, committedEngagement: +e.target.value })}/></Field>
      </div>
      <Field label="Platforms in this campaign">
        <PlatformPicker value={form.platforms} onChange={platforms => setForm({ ...form, platforms })}/>
      </Field>
      <Field label="Detailed KPI by platform">
        <PlatformKpiEditor
          value={form.kpiTargets}
          activePlatforms={form.platforms}
          onChange={kpiTargets => setForm({ ...form, kpiTargets })}
        />
      </Field>
      <DrawerFooter onSave={save} onClose={onClose}/>
    </Drawer>
  );
};

// ---------- Clients ----------
const ClientsAdmin = () => {
  const t = useT();
  const [search, setSearch] = useStateAD('');
  const [edit, setEdit] = useStateAD(null);
  const [showNew, setShowNew] = useStateAD(false);

  const all = window.PulseStore.getClients();
  const campaigns = window.PulseStore.getCampaigns();
  const filtered = all.filter(c =>
    !search || c.name.toLowerCase().includes(search.toLowerCase()) || (c.contact || '').toLowerCase().includes(search.toLowerCase())
  );
  return (
    <div>
      <AdminToolbar search={search} setSearch={setSearch} count={filtered.length} actions={
        <button className="btn brand" onClick={() => setShowNew(true)}><Icon name="plus" size={13}/> {t('action.new')}</button>
      }/>
      <div className="panel" style={{ padding: 0, overflow: 'auto' }}>
        <table style={adStyles.table}>
          <thead><tr>
            <th style={adStyles.th}>Name</th>
            <th style={adStyles.th}>Industry</th>
            <th style={adStyles.th}>Campaigns</th>
            <th style={adStyles.th}>Contact</th>
            <th style={adStyles.th}>Created</th>
            <th style={adStyles.th}></th>
          </tr></thead>
          <tbody>
            {filtered.map(c => (
              <tr key={c.id} style={adStyles.row}>
                <td style={{ ...adStyles.td, fontWeight: 600 }}>{c.name}</td>
                <td style={adStyles.td}>{c.industry}</td>
                <td style={adStyles.td}>
                  <div style={{ display: 'grid', gap: 3, fontSize: 11 }}>
                    {campaigns.filter(x => x.clientId === c.id).slice(0, 3).map(x => <span key={x.id}>{x.name}</span>)}
                    {campaigns.filter(x => x.clientId === c.id).length === 0 && <span style={{ color: 'var(--text-muted)' }}>—</span>}
                  </div>
                </td>
                <td style={adStyles.td}><a href={`mailto:${c.contact}`} style={{ color: 'var(--brand-500)' }}>{c.contact}</a></td>
                <td style={adStyles.td}><span style={{ fontFamily: 'var(--font-mono)', fontSize: 11 }}>{c.createdAt}</span></td>
                <td style={adStyles.td}>
                  <div style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}>
                    <IconButton icon="edit" onClick={() => setEdit(c)}/>
                    <IconButton icon="trash" onClick={() => { if (confirm('Delete ' + c.name + '?')) window.PulseStore.deleteClient(c.id); }} danger/>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {edit && <EditClientDrawer client={edit} onClose={() => setEdit(null)}/>}
      {showNew && <EditClientDrawer client={null} onClose={() => setShowNew(false)}/>}
    </div>
  );
};

const EditClientDrawer = ({ client, onClose }) => {
  const campaigns = window.PulseStore.getCampaigns();
  const [form, setForm] = useStateAD(client || { name: '', industry: '', contact: '' });
  const [campaignIds, setCampaignIds] = useStateAD(new Set(campaigns.filter(c => c.clientId === client?.id).map(c => c.id)));
  const toggleCampaign = (id) => {
    const next = new Set(campaignIds);
    next.has(id) ? next.delete(id) : next.add(id);
    setCampaignIds(next);
  };
  const save = () => {
    const saved = client ? window.PulseStore.updateClient(client.id, form) : window.PulseStore.createClient(form);
    campaigns.forEach(c => {
      if (campaignIds.has(c.id)) window.PulseStore.updateCampaign(c.id, { clientId: saved.id, brand: saved.name });
      else if (client && c.clientId === client.id) window.PulseStore.updateCampaign(c.id, { clientId: null });
    });
    onClose();
  };
  return (
    <Drawer title={client ? 'Edit client' : 'New client'} onClose={onClose}>
      <Field label="Name"><input style={modalStyles.input} value={form.name} onChange={e => setForm({ ...form, name: e.target.value })}/></Field>
      <Field label="Industry"><input style={modalStyles.input} value={form.industry} onChange={e => setForm({ ...form, industry: e.target.value })}/></Field>
      <Field label="Contact email"><input type="email" style={modalStyles.input} value={form.contact} onChange={e => setForm({ ...form, contact: e.target.value })}/></Field>
      <Field label="Assigned campaigns">
        <div style={{ display: 'grid', gap: 8, border: '1px solid var(--border)', background: 'var(--bg-elevated)', padding: 12, borderRadius: 6 }}>
          {campaigns.map(c => (
            <label key={c.id} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, cursor: 'pointer' }}>
              <input type="checkbox" checked={campaignIds.has(c.id)} onChange={() => toggleCampaign(c.id)}/>
              <span style={{ fontWeight: 700 }}>{c.name}</span>
              <span style={{ color: 'var(--text-muted)' }}>{c.status}</span>
            </label>
          ))}
          {campaigns.length === 0 && <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>No campaigns yet.</div>}
        </div>
      </Field>
      <DrawerFooter onSave={save} onClose={onClose}/>
    </Drawer>
  );
};

// ---------- Influencers ----------
const InfluencersAdmin = () => {
  const t = useT();
  const [search, setSearch] = useStateAD('');
  const [edit, setEdit] = useStateAD(null);
  const [showNew, setShowNew] = useStateAD(false);

  const all = window.PulseStore.getInfluencers();
  const filtered = all.filter(i =>
    !search || i.name.toLowerCase().includes(search.toLowerCase()) || i.handle.toLowerCase().includes(search.toLowerCase())
  );
  return (
    <div>
      <AdminToolbar search={search} setSearch={setSearch} count={filtered.length} actions={
        <button className="btn brand" onClick={() => setShowNew(true)}><Icon name="plus" size={13}/> {t('action.new')}</button>
      }/>
      <div className="panel" style={{ padding: 0, overflow: 'auto' }}>
        <table style={adStyles.table}>
          <thead><tr>
            <th style={adStyles.th}>Name</th>
            <th style={adStyles.th}>Handle</th>
            <th style={adStyles.th}>Platform</th>
            <th style={{ ...adStyles.th, textAlign: 'right' }}>Followers</th>
            <th style={adStyles.th}>Tier</th>
            <th style={{ ...adStyles.th, textAlign: 'right' }}>Platform KPI</th>
            <th style={adStyles.th}></th>
          </tr></thead>
          <tbody>
            {filtered.map(i => (
              <tr key={i.id} style={adStyles.row}>
                <td style={adStyles.td}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <img src={i.avatar} alt="" style={{ width: 28, height: 28, borderRadius: 4 }}/>
                    <span style={{ fontWeight: 600 }}>{i.name}</span>
                  </div>
                </td>
                <td style={adStyles.td}><span style={{ fontFamily: 'var(--font-mono)', fontSize: 12 }}>{i.handle}</span></td>
                <td style={adStyles.td}><PlatformBadge platform={i.platform} size={20}/></td>
                <td style={{ ...adStyles.td, textAlign: 'right' }} className="num">{window.PulseStore.fmt(i.followers)}</td>
                <td style={adStyles.td}><span style={adStyles.tierChip}>{t('tier.'+i.tier)}</span></td>
                <td style={{ ...adStyles.td, textAlign: 'right' }}><InfluencerKpiSummary influencer={i}/></td>
                <td style={adStyles.td}>
                  <div style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}>
                    <IconButton icon="edit" onClick={() => setEdit(i)}/>
                    <IconButton icon="trash" onClick={() => { if (confirm('Delete ' + i.name + '?')) window.PulseStore.deleteInfluencer(i.id); }} danger/>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {edit && <EditInfluencerDrawer inf={edit} onClose={() => setEdit(null)}/>}
      {showNew && <EditInfluencerDrawer inf={null} onClose={() => setShowNew(false)}/>}
    </div>
  );
};

const EditInfluencerDrawer = ({ inf, onClose }) => {
  const [form, setForm] = useStateAD(inf || { name: '', handle: '@', platform: 'tiktok', followers: 0, tier: 'micro', avgEngagementRate: 0, platformKpis: emptyPlatformKpis(), profileUrl: '', contactEmail: '', phone: '', notes: '' });
  const save = () => {
    const primary = (form.platformKpis || {})[form.platform] || {};
    const payload = { ...form, followers: +form.followers, avgEngagementRate: +(primary.avgEngagementRate ?? form.avgEngagementRate) || 0 };
    if (inf) window.PulseStore.updateInfluencer(inf.id, payload);
    else     window.PulseStore.createInfluencer(payload);
    onClose();
  };
  return (
    <Drawer title={inf ? 'Edit influencer' : 'New influencer'} onClose={onClose}>
      <Field label="Name"><input style={modalStyles.input} value={form.name} onChange={e => setForm({ ...form, name: e.target.value })}/></Field>
      <Field label="Handle"><input style={modalStyles.input} value={form.handle} onChange={e => setForm({ ...form, handle: e.target.value })}/></Field>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <Field label="Platform">
          <select style={modalStyles.input} value={form.platform} onChange={e => setForm({ ...form, platform: e.target.value })}>
            <option value="tiktok">TikTok</option>
            <option value="instagram">Instagram</option>
            <option value="facebook">Facebook</option>
          </select>
        </Field>
        <Field label="Followers"><input type="number" style={modalStyles.input} value={form.followers} onChange={e => setForm({ ...form, followers: e.target.value })}/></Field>
      </div>
      <Field label="Profile URL"><input type="url" style={modalStyles.input} value={form.profileUrl || ''} placeholder="https://www.tiktok.com/@creator" onChange={e => setForm({ ...form, profileUrl: e.target.value })}/></Field>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <Field label="Contact email"><input type="email" style={modalStyles.input} value={form.contactEmail || form.email || ''} placeholder="creator@email.com" onChange={e => setForm({ ...form, contactEmail: e.target.value, email: e.target.value })}/></Field>
        <Field label="Phone / Zalo"><input style={modalStyles.input} value={form.phone || ''} placeholder="Optional" onChange={e => setForm({ ...form, phone: e.target.value })}/></Field>
      </div>
      <Field label="Internal notes"><textarea style={{ ...modalStyles.input, minHeight: 70, resize: 'vertical' }} value={form.notes || ''} placeholder="Agency-only notes for contact, booking, or profile context" onChange={e => setForm({ ...form, notes: e.target.value })}/></Field>
      <Field label="Tier (manual select)">
        <select style={modalStyles.input} value={form.tier || 'micro'} onChange={e => setForm({ ...form, tier: e.target.value })}>
          <option value="micro">Micro</option>
          <option value="mid">Mid</option>
          <option value="macro">Macro</option>
          <option value="mega">Mega</option>
        </select>
      </Field>
      <Field label="Platform KPI baselines">
        <PlatformKpiEditor mode="influencer" value={form.platformKpis} onChange={platformKpis => setForm({ ...form, platformKpis })}/>
      </Field>
      <DrawerFooter onSave={save} onClose={onClose}/>
    </Drawer>
  );
};

// ---------- Bookings ----------
const BookingsAdmin = () => {
  const t = useT();
  const [search, setSearch] = useStateAD('');
  const [campaignFilter, setCampaignFilter] = useStateAD('all');
  const [edit, setEdit] = useStateAD(null);

  const campaigns = window.PulseStore.getCampaigns();
  const all = window.PulseStore.getBookings();
  const filtered = all.filter(b => {
    if (campaignFilter !== 'all' && b.campaignId !== campaignFilter) return false;
    if (search && !b.name.toLowerCase().includes(search.toLowerCase())) return false;
    return true;
  });

  return (
    <div>
      <AdminToolbar search={search} setSearch={setSearch} count={filtered.length} actions={
        <select value={campaignFilter} onChange={e => setCampaignFilter(e.target.value)} style={{ ...modalStyles.input, width: 'auto' }}>
          <option value="all">All campaigns</option>
          {campaigns.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
        </select>
      }/>
      <div className="panel" style={{ padding: 0, overflow: 'auto' }}>
        <table style={adStyles.table}>
          <thead><tr>
            <th style={adStyles.th}>Influencer</th>
            <th style={adStyles.th}>Campaign</th>
            <th style={{ ...adStyles.th, textAlign: 'right' }}>Fee</th>
            <th style={{ ...adStyles.th, textAlign: 'right' }}>Views</th>
            <th style={{ ...adStyles.th, textAlign: 'right' }}>Posts</th>
            <th style={adStyles.th}>Contract</th>
            <th style={adStyles.th}>Deliverables</th>
            <th style={{ ...adStyles.th, textAlign: 'right' }}>KPI</th>
            <th style={adStyles.th}></th>
          </tr></thead>
          <tbody>
            {filtered.map(b => {
              const c = campaigns.find(x => x.id === b.campaignId);
              return (
                <tr key={b.id} style={adStyles.row}>
                  <td style={adStyles.td}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <img src={b.avatar} alt="" style={{ width: 24, height: 24, borderRadius: 4 }}/>
                      <span style={{ fontWeight: 600 }}>{b.name}</span>
                    </div>
                  </td>
                  <td style={adStyles.td}>{c?.name || b.campaignId}</td>
                  <td style={{ ...adStyles.td, textAlign: 'right' }} className="num">${(b.fee||0).toLocaleString()}</td>
                  <td style={{ ...adStyles.td, textAlign: 'right' }} className="num">{window.PulseStore.fmt(b.actualViews)}</td>
                  <td style={{ ...adStyles.td, textAlign: 'right' }} className="num">{(b.posts || []).filter(p => p.url && !['missing_url','not_found','private_or_removed','error'].includes(p.pullStatus)).length}/{b.postsPlanned || (b.posts || []).length || 0}</td>
                  <td style={adStyles.td}>
                    <div style={{ fontSize: 11, display: 'grid', gap: 3 }}>
                      <span>{b.contractDetails?.paymentStatus || '—'}</span>
                      <span style={{ color: 'var(--text-muted)' }}>{Object.values(b.contractDetails?.clientVisibleFields || {}).filter(Boolean).length} client-visible fields</span>
                    </div>
                  </td>
                  <td style={adStyles.td}>
                    <div style={{ fontSize: 11, display: 'grid', gap: 3 }}>
                      <span>{(b.deliverables || []).filter(d => d.done).length}/{(b.deliverables || []).length} done</span>
                      <span style={{ color: 'var(--text-muted)' }}>{(b.deliverables || []).filter(d => d.visibility === 'client').length} client-visible</span>
                    </div>
                  </td>
                  <td style={{ ...adStyles.td, textAlign: 'right' }} className="num">{b.kpiPct}%</td>
                  <td style={adStyles.td}>
                    <div style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}>
                      <IconButton icon="edit" onClick={() => setEdit(b)} title="Edit booking and post URLs"/>
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      {edit && window.EditBookingModal && (
        <window.EditBookingModal
          booking={edit}
          campaign={campaigns.find(c => c.id === edit.campaignId)}
          onClose={() => setEdit(null)}
        />
      )}
    </div>
  );
};

// ---------- Users ----------
const UsersAdmin = () => {
  const t = useT();
  const [search, setSearch] = useStateAD('');
  const [edit, setEdit] = useStateAD(null);
  const [showNew, setShowNew] = useStateAD(false);
  const all = window.PulseStore.getUsers();
  const filtered = all.filter(u =>
    !search || u.name.toLowerCase().includes(search.toLowerCase()) || u.email.toLowerCase().includes(search.toLowerCase())
  );
  return (
    <div>
      <AdminToolbar search={search} setSearch={setSearch} count={filtered.length} actions={
        <button className="btn brand" onClick={() => setShowNew(true)}><Icon name="plus" size={13}/> {t('action.new')}</button>
      }/>
      <div className="panel" style={{ padding: 0, overflow: 'auto' }}>
        <table style={adStyles.table}>
          <thead><tr>
            <th style={adStyles.th}>User</th>
            <th style={adStyles.th}>Email</th>
            <th style={adStyles.th}>Role</th>
            <th style={adStyles.th}>Last active</th>
            <th style={adStyles.th}></th>
          </tr></thead>
          <tbody>
            {filtered.map(u => (
              <tr key={u.id} style={adStyles.row}>
                <td style={adStyles.td}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <img src={u.avatar} alt="" style={{ width: 28, height: 28, borderRadius: 4 }}/>
                    <span style={{ fontWeight: 600 }}>{u.name}</span>
                  </div>
                </td>
                <td style={adStyles.td}><a href={`mailto:${u.email}`} style={{ color: 'var(--brand-500)' }}>{u.email}</a></td>
                <td style={adStyles.td}><span style={{ ...adStyles.tierChip, background: u.role === 'owner' ? 'var(--brand-500)' : 'var(--ink-100)', color: u.role === 'owner' ? '#FFF' : 'var(--ink-700)' }}>{u.role}</span></td>
                <td style={adStyles.td}><span style={{ fontFamily: 'var(--font-mono)', fontSize: 11 }}>{u.lastActive}</span></td>
                <td style={adStyles.td}>
                  <div style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}>
                    <IconButton icon="edit" onClick={() => setEdit(u)}/>
                    <IconButton icon="trash" onClick={() => { if (confirm('Remove ' + u.name + '?')) window.PulseStore.deleteUser(u.id); }} danger/>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {edit && <EditUserDrawer user={edit} onClose={() => setEdit(null)}/>}
      {showNew && <EditUserDrawer user={null} onClose={() => setShowNew(false)}/>}
    </div>
  );
};

const EditUserDrawer = ({ user, onClose }) => {
  const [form, setForm] = useStateAD(user || { name: '', email: '', role: 'staff' });
  const save = () => {
    if (user) window.PulseStore.updateUser(user.id, form);
    else      window.PulseStore.createUser(form);
    onClose();
  };
  return (
    <Drawer title={user ? 'Edit user' : 'New user'} onClose={onClose}>
      <Field label="Name"><input style={modalStyles.input} value={form.name} onChange={e => setForm({ ...form, name: e.target.value })}/></Field>
      <Field label="Email"><input type="email" style={modalStyles.input} value={form.email} onChange={e => setForm({ ...form, email: e.target.value })}/></Field>
      <Field label="Role">
        <select style={modalStyles.input} value={form.role} onChange={e => setForm({ ...form, role: e.target.value })}>
          <option value="owner">Owner</option>
          <option value="staff">Staff</option>
          <option value="client">Client</option>
        </select>
      </Field>
      <DrawerFooter onSave={save} onClose={onClose}/>
    </Drawer>
  );
};

// ---------- i18n Editor ----------
const I18nEditor = () => {
  const t = useT();
  const [search, setSearch] = useStateAD('');
  const [showOnlyModified, setShowOnlyModified] = useStateAD(false);
  const keys = window.PulseI18n.getAllKeys();
  const filtered = keys.filter(k => {
    if (showOnlyModified && !window.PulseI18n.isModified(k)) return false;
    if (!search) return true;
    const vi = window.PulseI18n.getString(k, 'vi') || '';
    const en = window.PulseI18n.getString(k, 'en') || '';
    return k.toLowerCase().includes(search.toLowerCase())
        || vi.toLowerCase().includes(search.toLowerCase())
        || en.toLowerCase().includes(search.toLowerCase());
  });

  return (
    <div>
      <div style={{ fontSize: 13, color: 'var(--text-secondary)', marginBottom: 16, padding: 14, background: 'var(--bg-elevated)', borderLeft: '3px solid var(--brand-500)' }}>
        <Icon name="globe" size={14} style={{ marginRight: 6, verticalAlign: 'middle', color: 'var(--brand-500)' }}/>
        {t('admin.i18n.help')}
      </div>
      <AdminToolbar search={search} setSearch={setSearch} count={filtered.length} actions={
        <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--text-secondary)' }}>
          <Toggle checked={showOnlyModified} onChange={() => setShowOnlyModified(!showOnlyModified)}/>
          <span style={{ textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 700 }}>{t('admin.i18n.modified')} only</span>
        </label>
      }/>
      <div className="panel" style={{ padding: 0, overflow: 'auto' }}>
        <table style={{ ...adStyles.table, tableLayout: 'fixed' }}>
          <thead><tr>
            <th style={{ ...adStyles.th, width: 200 }}>{t('admin.i18n.key')}</th>
            <th style={adStyles.th}>{t('admin.i18n.vi')} 🇻🇳</th>
            <th style={adStyles.th}>{t('admin.i18n.en')} 🇬🇧</th>
            <th style={{ ...adStyles.th, width: 80 }}></th>
          </tr></thead>
          <tbody>
            {filtered.map(k => (
              <I18nRow key={k} keyName={k}/>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
};

const I18nRow = ({ keyName }) => {
  const t = useT();
  const [vi, setVi] = useStateAD(window.PulseI18n.getString(keyName, 'vi') || '');
  const [en, setEn] = useStateAD(window.PulseI18n.getString(keyName, 'en') || '');
  const [dirty, setDirty] = useStateAD(false);
  const modified = window.PulseI18n.isModified(keyName);

  const onBlurVi = () => { if (vi !== window.PulseI18n.getString(keyName, 'vi')) { window.PulseI18n.setString(keyName, 'vi', vi); setDirty(false); } };
  const onBlurEn = () => { if (en !== window.PulseI18n.getString(keyName, 'en')) { window.PulseI18n.setString(keyName, 'en', en); setDirty(false); } };
  const reset = () => {
    window.PulseI18n.resetString(keyName);
    setVi(window.PulseI18n.defaultString(keyName, 'vi') || '');
    setEn(window.PulseI18n.defaultString(keyName, 'en') || '');
  };

  return (
    <tr style={adStyles.row}>
      <td style={{ ...adStyles.td, verticalAlign: 'top' }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, color: modified ? 'var(--brand-500)' : 'var(--text-primary)', wordBreak: 'break-all' }}>
          {keyName}{modified && <span style={{ marginLeft: 6, fontSize: 9, color: 'var(--brand-500)' }}>●</span>}
        </div>
      </td>
      <td style={{ ...adStyles.td, verticalAlign: 'top' }}>
        <textarea
          value={vi}
          onChange={e => { setVi(e.target.value); setDirty(true); }}
          onBlur={onBlurVi}
          style={i18nStyles.textarea}
          rows={1}
        />
      </td>
      <td style={{ ...adStyles.td, verticalAlign: 'top' }}>
        <textarea
          value={en}
          onChange={e => { setEn(e.target.value); setDirty(true); }}
          onBlur={onBlurEn}
          style={i18nStyles.textarea}
          rows={1}
        />
      </td>
      <td style={{ ...adStyles.td, verticalAlign: 'top', textAlign: 'right' }}>
        {modified && <IconButton icon="refresh" onClick={reset} title={t('admin.i18n.reset_key')}/>}
      </td>
    </tr>
  );
};

// ---------- Data (danger zone) ----------
const DataAdmin = () => {
  const t = useT();
  const [raw, setRaw] = useStateAD(window.PulseStore.exportJSON());
  const [payload, setPayload] = useStateAD('');
  const [message, setMessage] = useStateAD('');
  useEffectAD(() => {
    const h = () => setRaw(window.PulseStore.exportJSON());
    window.addEventListener('pulse-data-change', h);
    return () => window.removeEventListener('pulse-data-change', h);
  }, []);
  const sync = window.PulseStore.getSyncStatus();
  const apiStatus = window.PulseStore.getApiStatus ? window.PulseStore.getApiStatus() : { enabled: false };
  const contract = window.PulseStore.getApiContract();
  const workflows = [
    { name: 'PULSE-Core-Pull-Posts', descKey: 'admin.workflow.core' },
    { name: 'PULSE-Auto-Daily', descKey: 'admin.workflow.daily' },
    { name: 'PULSE-Backfill-Yesterday', descKey: 'admin.workflow.backfill' },
    { name: 'PULSE-Manual-Run', descKey: 'admin.workflow.manual' },
    { name: 'PULSE-Error-Handler', descKey: 'admin.workflow.error' },
    { name: 'PULSE-Health-Check', descKey: 'admin.workflow.health' },
  ];
  const reset = () => {
    if (confirm(t('admin.reset_demo_confirm'))) {
      window.PulseStore.resetToDemo();
      window.PulseI18n.resetAll();
    }
  };
  const syncPayload = () => {
    try {
      window.PulseStore.syncFromApiPayload(JSON.parse(payload));
      setMessage(t('sync.ok'));
      setPayload('');
    } catch (e) {
      setMessage(t('sync.failed'));
    }
  };
  const download = () => {
    const blob = new Blob([raw], { type: 'application/json' });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'pulse-data.json';
    a.click();
  };
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr)', gap: 16 }}>
      <div className="panel" style={{ padding: 20 }}>
        <h3 style={{ fontFamily: 'var(--font-display)', textTransform: 'uppercase', margin: '0 0 6px', fontSize: 16 }}>{t('admin.ingestion_title')}</h3>
        <div style={{ fontSize: 12, color: 'var(--text-secondary)', marginBottom: 14 }}>{t('admin.ingestion_help')}</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, justifyContent: 'space-between', flexWrap: 'wrap', marginBottom: 14, padding: 12, border: '1px solid var(--border)', borderLeft: '3px solid var(--brand-500)', background: 'var(--bg-elevated)' }}>
          <div style={{ fontSize: 12, color: 'var(--text-primary)', fontWeight: 700 }}>{t('admin.n8n_recommendation')}</div>
          <a href="Guide.html" className="btn ghost" style={{ padding: '7px 10px', fontSize: 12 }}><Icon name="help-circle" size={13}/> {t('admin.open_guide')}</a>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))', gap: 10, marginBottom: 16 }}>
          <IngestionTile label="Adapter" value={apiStatus.enabled ? 'API mode' : 'localStorage'} accent={!!apiStatus.error}/>
          <IngestionTile label={t('admin.source')} value={sync.source || 'local'}/>
          <IngestionTile label={t('admin.last_sync')} value={sync.lastSyncedAt ? sync.lastSyncedAt.slice(0,16).replace('T',' ') : '—'}/>
          <IngestionTile label={t('admin.run_id')} value={sync.runId || '—'}/>
          <IngestionTile label={t('admin.posts_pulled')} value={sync.postCount}/>
          <IngestionTile label={t('admin.posts_stale')} value={sync.stalePostCount} accent={sync.stalePostCount > 0}/>
          <IngestionTile label={t('admin.posts_missing_url')} value={sync.missingUrlCount} accent={sync.missingUrlCount > 0}/>
        </div>
        {apiStatus.enabled && (
          <div style={{ fontSize: 12, color: apiStatus.error ? 'var(--brand-500)' : 'var(--text-secondary)', marginBottom: 16 }}>
            Backend API: {apiStatus.error || `${apiStatus.baseUrl || ''} connected${apiStatus.lastLoadedAt ? ` · loaded ${apiStatus.lastLoadedAt.slice(0,16).replace('T',' ')}` : ''}`}
          </div>
        )}
        <details style={{ marginBottom: 16 }}>
          <summary style={{ cursor: 'pointer', fontSize: 12, fontWeight: 800, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--text-secondary)' }}>{t('admin.workflow_family')}</summary>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8, marginTop: 12 }}>
            {workflows.map(w => (
              <div key={w.name} style={{ border: '1px solid var(--border)', padding: 12, background: 'var(--bg-elevated)', borderRadius: 6 }}>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 800, color: 'var(--brand-500)', marginBottom: 6 }}>{w.name}</div>
                <div style={{ fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.45 }}>{t(w.descKey)}</div>
              </div>
            ))}
          </div>
        </details>
        <Field label={t('admin.paste_payload')}>
          <textarea
            style={{ ...modalStyles.input, minHeight: 150, fontFamily: 'var(--font-mono)', fontSize: 11 }}
            value={payload}
            onChange={e => setPayload(e.target.value)}
            placeholder={JSON.stringify(contract.payloadShape, null, 2)}
          />
        </Field>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
          <button className="btn" onClick={() => setPayload(window.PulseStore.getSamplePayload())}><Icon name="file-text" size={13}/> {t('admin.load_sample')}</button>
          <button className="btn brand" onClick={syncPayload}><Icon name="upload" size={13}/> {t('admin.import_payload')}</button>
          {message && <span style={{ fontSize: 12, color: message === t('sync.ok') ? 'var(--text-primary)' : 'var(--brand-500)', fontWeight: 700 }}>{message}</span>}
        </div>
        <details style={{ marginTop: 16 }}>
          <summary style={{ cursor: 'pointer', fontSize: 12, fontWeight: 800, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--text-secondary)' }}>{t('admin.api_contract')}</summary>
          <pre style={{ background: 'var(--bg-inverse)', color: 'var(--text-inverse)', padding: 16, fontFamily: 'var(--font-mono)', fontSize: 11, overflow: 'auto', maxHeight: 260 }}>{JSON.stringify(contract, null, 2)}</pre>
        </details>
      </div>
      <div className="panel" style={{ padding: 20 }}>
        <h3 style={{ fontFamily: 'var(--font-display)', textTransform: 'uppercase', margin: '0 0 12px', fontSize: 16 }}>Raw data (JSON)</h3>
        <div style={{ fontSize: 12, color: 'var(--text-secondary)', marginBottom: 10 }}>
          Everything Pulse knows. Demo mode persists in your browser; API mode persists through the pilot backend.
        </div>
        <pre style={{ background: 'var(--bg-inverse)', color: 'var(--text-inverse)', padding: 16, fontFamily: 'var(--font-mono)', fontSize: 11, overflow: 'auto', maxHeight: 360, margin: 0 }}>{raw}</pre>
        <div style={{ display: 'flex', gap: 8, marginTop: 16, flexWrap: 'wrap' }}>
          <button className="btn" onClick={download}><Icon name="download" size={13}/> {t('admin.export_data')}</button>
          <button className="btn" style={{ borderColor: 'var(--brand-500)', color: 'var(--brand-500)' }} onClick={reset}><Icon name="refresh" size={13}/> {t('admin.reset_demo')}</button>
        </div>
      </div>
    </div>
  );
};

const IngestionTile = ({ label, value, accent }) => (
  <div style={{ border: '1px solid var(--border)', background: accent ? 'var(--brand-100)' : 'var(--bg-elevated)', padding: 12, borderRadius: 6 }}>
    <div style={{ fontSize: 9, textTransform: 'uppercase', letterSpacing: '0.1em', color: accent ? 'var(--brand-600)' : 'var(--text-muted)', fontWeight: 800, marginBottom: 6 }}>{label}</div>
    <div className="num" style={{ fontSize: 18, fontWeight: 700, color: accent ? 'var(--brand-600)' : 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{value}</div>
  </div>
);

// ---------- Drawer shell ----------
const Drawer = ({ title, onClose, children }) => (
  <div style={modalStyles.backdrop} onClick={onClose}>
    <div style={{ ...modalStyles.panel, maxWidth: 760 }} onClick={e => e.stopPropagation()}>
      <div style={modalStyles.header}>
        <div style={modalStyles.title}>{title}</div>
        <button className="btn ghost" onClick={onClose}><Icon name="x" size={16}/></button>
      </div>
      <div style={modalStyles.body}>{children}</div>
    </div>
  </div>
);

const DrawerFooter = ({ onSave, onClose }) => {
  const t = useT();
  return (
    <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 20, paddingTop: 16, borderTop: '1px solid var(--border)' }}>
      <button className="btn" onClick={onClose}>{t('action.cancel')}</button>
      <button className="btn brand" onClick={onSave}>{t('action.save')}</button>
    </div>
  );
};

const StatusBadge = ({ status }) => (
  <span style={{
    fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 700,
    padding: '3px 8px',
    background: status === 'live' ? 'var(--bg-inverse)' : status === 'draft' ? 'var(--brand-500)' : 'var(--ink-200)',
    color: status === 'live' ? 'var(--text-inverse)' : status === 'draft' ? '#FFFFFF' : 'var(--text-primary)',
    letterSpacing: '0.12em', textTransform: 'uppercase',
  }}>{status}</span>
);

const adStyles = {
  title: { fontFamily: 'var(--font-display)', fontSize: 'clamp(28px, 5vw, 44px)', fontWeight: 400, margin: 0, letterSpacing: 0, textTransform: 'uppercase' },
  table: { width: '100%', borderCollapse: 'collapse', minWidth: 980 },
  th: { textAlign: 'left', padding: '12px 14px', fontSize: 10, color: 'var(--ink-500)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700, background: 'var(--bg-elevated)', borderBottom: '1px solid var(--border)', fontFamily: 'var(--font-mono)' },
  td: { padding: '12px 14px', fontSize: 13, verticalAlign: 'middle' },
  row: { borderBottom: '1px solid var(--border)' },
  tierChip: { fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', padding: '2px 7px', background: 'var(--ink-100)', color: 'var(--ink-700)' },
};
const i18nStyles = {
  textarea: { width: '100%', minHeight: 34, padding: '6px 8px', fontSize: 13, border: '1px solid transparent', background: 'transparent', color: 'var(--text-primary)', fontFamily: 'inherit', resize: 'vertical', outline: 'none' },
};

Object.assign(window, { AdminPanel });
