/* ===================================================================
   KabelFlux v5 — Admin slide-over panels
   Each panel is a self-contained slide-over (matches BackupsPanel pattern)
   and is opened from the topbar Admin dropdown.
   =================================================================== */

/* ---------- Shared slide-over chrome ---------- */
const AdminSlideover = ({ title, subtitle, onClose, children, headerExtra }) => (
  <div className="kf-slideover-bg fade-in" onClick={onClose} role="dialog" aria-modal="true" aria-label={title}>
    <div className="kf-slideover kf-slideover-wide" onClick={e => e.stopPropagation()}>
      <div className="kf-slideover-head">
        <div>
          <h2>{title}</h2>
          {subtitle && <p>{subtitle}</p>}
        </div>
        <div className="kf-slideover-head-actions">
          {headerExtra}
          <IconBtn icon="x" label={`Close ${title}`} onClick={onClose}/>
        </div>
      </div>
      {children}
    </div>
  </div>
);

/* ===================================================================
   AUDIT LOG
   What happened, who did it, when, and what changed.
   =================================================================== */
const AUDIT_ENTRIES = [
  { id:'a1',  ts:'2026-05-23 09:14:22', who:'L. Kohli',   role:'designer',  kind:'edit',   target:'Wire W-014',           detail:'Gauge 24 AWG → 22 AWG',          ip:'10.4.2.118' },
  { id:'a2',  ts:'2026-05-23 09:11:08', who:'L. Kohli',   role:'designer',  kind:'create', target:'Wire W-118',           detail:'New wire · J1.5 → J3.2 · red',   ip:'10.4.2.118' },
  { id:'a3',  ts:'2026-05-23 08:57:41', who:'system',     role:'system',    kind:'backup', target:'Project HA0000167',    detail:'Auto-snapshot 218 KB · 0.9s',    ip:'—' },
  { id:'a4',  ts:'2026-05-23 08:42:03', who:'R. Bedi',    role:'reviewer',  kind:'review', target:'BOM rev B',            detail:'Approved · "Looks good"',        ip:'10.4.2.27'  },
  { id:'a5',  ts:'2026-05-23 08:31:55', who:'L. Kohli',   role:'designer',  kind:'delete', target:'Wire W-099',           detail:'Removed unused jumper',          ip:'10.4.2.118' },
  { id:'a6',  ts:'2026-05-23 08:14:12', who:'L. Kohli',   role:'designer',  kind:'edit',   target:'Connector J3.2',       detail:'Backshell EN3155-008 → -012',    ip:'10.4.2.118' },
  { id:'a7',  ts:'2026-05-23 07:58:00', who:'M. Adler',   role:'admin',     kind:'auth',   target:'Sign-in',              detail:'OAuth · Ikran Aerospace SSO',    ip:'10.4.0.4'   },
  { id:'a8',  ts:'2026-05-22 18:42:17', who:'R. Bedi',    role:'reviewer',  kind:'edit',   target:'Note N-031',           detail:'Added 3 lines · cure cycle ref',  ip:'10.4.2.27'  },
  { id:'a9',  ts:'2026-05-22 18:11:09', who:'system',     role:'system',    kind:'export', target:'Production drawing',   detail:'PDF · 14 pages · 2.4 MB',        ip:'—' },
  { id:'a10', ts:'2026-05-22 17:55:30', who:'L. Kohli',   role:'designer',  kind:'create', target:'Bundle B-04',          detail:'Grouped 18 wires · L=482 mm',    ip:'10.4.2.118' },
  { id:'a11', ts:'2026-05-22 17:30:21', who:'A. Park',    role:'viewer',    kind:'auth',   target:'Sign-in',              detail:'Magic link',                      ip:'72.14.5.211' },
  { id:'a12', ts:'2026-05-22 16:00:00', who:'system',     role:'system',    kind:'backup', target:'Project HA0000167',    detail:'Pre-push snapshot 216 KB',       ip:'—' },
];
const AUDIT_KINDS = [
  { k:'all',    l:'All',     tone:null },
  { k:'edit',   l:'Edits',   tone:'info'    },
  { k:'create', l:'Creates', tone:'success' },
  { k:'delete', l:'Deletes', tone:'danger'  },
  { k:'review', l:'Reviews', tone:'violet'  },
  { k:'export', l:'Exports', tone:'warning' },
  { k:'backup', l:'Backups', tone:null      },
  { k:'auth',   l:'Auth',    tone:null      },
];

const AuditLogPanel = ({ onClose }) => {
  const [filter, setFilter] = useState('all');
  const [q, setQ] = useState('');
  const filtered = useMemo(() => {
    let list = AUDIT_ENTRIES;
    if (filter !== 'all') list = list.filter(e => e.kind === filter);
    const needle = q.trim().toLowerCase();
    if (needle) list = list.filter(e => (e.who + ' ' + e.target + ' ' + e.detail).toLowerCase().includes(needle));
    return list;
  }, [filter, q]);
  // Group rows by ISO date.
  const grouped = useMemo(() => {
    const out = {};
    filtered.forEach(e => { const d = e.ts.slice(0, 10); (out[d] = out[d] || []).push(e); });
    return out;
  }, [filtered]);

  return (
    <AdminSlideover title="Audit log" subtitle="Every edit · 90-day retention · exportable to CSV"
                    onClose={onClose}
                    headerExtra={<Btn kind="outline" size="sm" icon="download">Export CSV</Btn>}>
      <div className="kf-admin-toolbar">
        <div className="kf-admin-search">
          <Icon name="search" size={13} stroke="var(--t-3)"/>
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search by user, target or detail…" aria-label="Search audit log"/>
        </div>
        <div className="kf-admin-chips">
          {AUDIT_KINDS.map(k => (
            <button key={k.k}
                    className={`kf-admin-chip ${filter === k.k ? 'on' : ''}`}
                    onClick={() => setFilter(k.k)}>
              {k.l}
              <span className="kf-admin-chip-n">
                {k.k === 'all' ? AUDIT_ENTRIES.length : AUDIT_ENTRIES.filter(e => e.kind === k.k).length}
              </span>
            </button>
          ))}
        </div>
      </div>

      <div className="kf-admin-body">
        {Object.keys(grouped).length === 0 && (
          <EmptyState icon="search" title="No matching entries" hint="Try a different filter or search term."/>
        )}
        {Object.entries(grouped).map(([day, entries]) => (
          <div key={day} className="kf-audit-day">
            <div className="kf-audit-day-head">
              <span className="num">{day}</span>
              <span>{entries.length} entries</span>
            </div>
            <div className="kf-audit-list">
              {entries.map(e => {
                const tone = AUDIT_KINDS.find(k => k.k === e.kind)?.tone;
                return (
                  <div key={e.id} className="kf-audit-row">
                    <div className="kf-audit-time num">{e.ts.slice(11)}</div>
                    <Chip size="sm" tone={tone || undefined}>{e.kind}</Chip>
                    <div className="kf-audit-who">
                      <div className="kf-audit-avatar">{e.who.split(' ').map(s => s[0]).join('').slice(0,2)}</div>
                      <div>
                        <div className="kf-audit-who-name">{e.who}</div>
                        <div className="kf-audit-who-role">{e.role}</div>
                      </div>
                    </div>
                    <div className="kf-audit-detail">
                      <div className="kf-audit-target num">{e.target}</div>
                      <div className="kf-audit-msg">{e.detail}</div>
                    </div>
                    <div className="kf-audit-ip num">{e.ip}</div>
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
    </AdminSlideover>
  );
};

/* ===================================================================
   USERS — wired to /api/users
   Backend roles: admin · designer · viewer · superadmin (last only
   if current user is superadmin). Scoped to current company unless
   the caller is superadmin.
   =================================================================== */
const ROLE_OPTS = ['admin', 'designer', 'viewer'];

const UsersPanel = ({ onClose, me, companies = [] }) => {
  const toast = useToast();
  const [q, setQ] = useState('');
  const [roleFilter, setRoleFilter] = useState('all');
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState(null);   // user row being edited, or {} for new
  const [confirm, setConfirm] = useState(null);

  const isSuper = me && me.role === 'superadmin';
  const allRoles = isSuper ? [...ROLE_OPTS, 'superadmin'] : ROLE_OPTS;

  const refresh = useCallback(async () => {
    try {
      const list = await kfxListUsers();
      setRows(Array.isArray(list) ? list : []);
    } catch (e) {
      toast.err('Could not load users', (e && e.message) || 'Unknown error');
    } finally {
      setLoading(false);
    }
  }, [toast]);

  useEffect(() => { refresh(); }, [refresh]);

  const filtered = useMemo(() => {
    let list = rows;
    const needle = q.trim().toLowerCase();
    if (needle) list = list.filter(u => ((u.full_name || '') + ' ' + (u.username || '') + ' ' + (u.email || '')).toLowerCase().includes(needle));
    if (roleFilter !== 'all') list = list.filter(u => u.role === roleFilter);
    return list;
  }, [rows, q, roleFilter]);

  const counts = useMemo(() => ({
    all:    rows.length,
    active: rows.length,
    admins: rows.filter(u => u.role === 'admin' || u.role === 'superadmin').length,
  }), [rows]);

  return (
    <AdminSlideover title="Users & permissions" subtitle={isSuper ? 'All users across every workspace' : 'Members of the current workspace'}
                    onClose={onClose}
                    headerExtra={<Btn kind="primary" size="sm" icon="plus" onClick={() => setEditing({})}>Add user</Btn>}>
      <div className="kf-admin-stats">
        <div className="kf-admin-stat"><div className="kf-admin-stat-n num">{counts.all}</div><div className="kf-admin-stat-l">Members</div></div>
        <div className="kf-admin-stat"><div className="kf-admin-stat-n num">{counts.admins}</div><div className="kf-admin-stat-l">Admins</div></div>
      </div>

      <div className="kf-admin-toolbar">
        <div className="kf-admin-search">
          <Icon name="search" size={13} stroke="var(--t-3)"/>
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search by name or email…" aria-label="Search users"/>
        </div>
        <div className="kf-admin-chips">
          {['all', ...allRoles].map(r => (
            <button key={r} className={`kf-admin-chip ${roleFilter === r ? 'on' : ''}`} onClick={() => setRoleFilter(r)}>
              {r === 'all' ? 'All roles' : r}
              <span className="kf-admin-chip-n">{r === 'all' ? rows.length : rows.filter(u => u.role === r).length}</span>
            </button>
          ))}
        </div>
      </div>

      <div className="kf-admin-body">
        {loading && <div style={{ padding: 20, color:'var(--t-3)', fontSize:12 }}>Loading users…</div>}
        {!loading && (
          <table className="kf-admin-table">
            <thead>
              <tr>
                <th>Member</th>
                <th>Role</th>
                {isSuper && <th>Company</th>}
                <th>Job title</th>
                <th aria-label="Actions"/>
              </tr>
            </thead>
            <tbody>
              {filtered.map(u => (
                <tr key={u.uid || u.id}>
                  <td>
                    <div className="kf-admin-who">
                      <div className="kf-audit-avatar">{((u.full_name || u.username || '??')).split(' ').map(s => s[0]).join('').slice(0,2).toUpperCase()}</div>
                      <div>
                        <div className="kf-audit-who-name">{u.full_name || u.username}</div>
                        <div className="kf-audit-who-role">{u.email || u.username}</div>
                      </div>
                    </div>
                  </td>
                  <td><Chip size="sm" tone={u.role === 'admin' || u.role === 'superadmin' ? 'info' : 'success'}>{u.role}</Chip></td>
                  {isSuper && <td className="kf-admin-muted">{u.company_name || '—'}</td>}
                  <td className="kf-admin-muted">{u.job_title || '—'}</td>
                  <td className="kf-admin-actions">
                    <IconBtn icon="settings" label={`Edit ${u.username}`} onClick={() => setEditing(u)}/>
                    <IconBtn icon="trash" label={`Remove ${u.username}`} danger
                             onClick={() => setConfirm({
                               title: `Remove ${u.full_name || u.username}?`,
                               body: <>This user will be permanently removed.</>,
                               confirmLabel: 'Remove user',
                               danger: true,
                               onConfirm: async () => {
                                 try {
                                   await kfxDeleteUser(u.uid || u.id);
                                   toast.ok('User removed');
                                   await refresh();
                                 } catch (e) {
                                   toast.err('Delete failed', (e && e.message) || 'Unknown error');
                                 }
                               },
                             })}/>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
        {!loading && filtered.length === 0 && <EmptyState compact icon="user" title="No users match" hint="Try a different role or search term."/>}
      </div>

      {editing && (
        <UserEditModal
          user={editing}
          roles={allRoles}
          isSuper={isSuper}
          companies={companies}
          onClose={() => setEditing(null)}
          onSaved={async () => { setEditing(null); await refresh(); }}/>
      )}
      {confirm && <ConfirmModal {...confirm} onClose={() => setConfirm(null)}/>}
    </AdminSlideover>
  );
};

const UserEditModal = ({ user, roles, isSuper, companies, onClose, onSaved }) => {
  const toast = useToast();
  const isNew = !user.uid && !user.id;
  const [username, setUsername]   = useState(user.username || '');
  const [password, setPassword]   = useState('');
  const [fullName, setFullName]   = useState(user.full_name || '');
  const [email, setEmail]         = useState(user.email || '');
  const [role, setRole]           = useState(user.role || 'designer');
  const [jobTitle, setJobTitle]   = useState(user.job_title || '');
  const [companyId, setCompanyId] = useState(user.company_id || (companies[0] && companies[0].id) || '');
  const [busy, setBusy] = useState(false);

  const canSave = username.trim() && (isNew ? password.length >= 6 : true);

  const submit = async () => {
    setBusy(true);
    try {
      if (isNew) {
        await kfxCreateUser({
          username: username.trim(), password,
          full_name: fullName, email, role, job_title: jobTitle,
          company_id: isSuper ? companyId : undefined,
        });
        toast.ok('User created', username);
      } else {
        const patch = { full_name: fullName, email, role, job_title: jobTitle };
        if (isSuper && companyId) patch.company_id = companyId;
        await kfxUpdateUser(user.uid || user.id, patch);
        toast.ok('User updated', username);
      }
      await onSaved();
    } catch (e) {
      toast.err(isNew ? 'Create failed' : 'Update failed', (e && e.message) || 'Unknown error');
      setBusy(false);
    }
  };

  return (
    <Modal title={isNew ? 'Add user' : `Edit ${user.username}`} size="md" onClose={busy ? () => {} : onClose} footer={
      <>
        <Btn kind="ghost" onClick={onClose} disabled={busy}>Cancel</Btn>
        <Btn kind="primary" icon="check" disabled={!canSave || busy} busy={busy} onClick={submit}>
          {isNew ? 'Create user' : 'Save changes'}
        </Btn>
      </>
    }>
      <div className="kf-form">
        <div className="kf-form-row">
          <div className="kf-field">
            <label>Username <span className="kf-req">*</span></label>
            <input className="kf-input num" value={username} disabled={!isNew}
                   onChange={e => setUsername(e.target.value)} autoFocus={isNew}/>
          </div>
        </div>
        {isNew && (
          <div className="kf-form-row">
            <div className="kf-field">
              <label>Password <span className="kf-req">*</span></label>
              <input className="kf-input num" type="password" value={password}
                     onChange={e => setPassword(e.target.value)} placeholder="min 6 characters"/>
            </div>
          </div>
        )}
        <div className="kf-form-row">
          <div className="kf-field">
            <label>Full name</label>
            <input className="kf-input" value={fullName} onChange={e => setFullName(e.target.value)}/>
          </div>
          <div className="kf-field">
            <label>Email</label>
            <input className="kf-input num" type="email" value={email} onChange={e => setEmail(e.target.value)}/>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-field">
            <label>Role</label>
            <select className="kf-input" value={role} onChange={e => setRole(e.target.value)}>
              {roles.map(r => <option key={r} value={r}>{r}</option>)}
            </select>
          </div>
          <div className="kf-field">
            <label>Job title</label>
            <input className="kf-input" value={jobTitle} onChange={e => setJobTitle(e.target.value)}/>
          </div>
        </div>
        {isSuper && companies && companies.length > 0 && (
          <div className="kf-form-row">
            <div className="kf-field">
              <label>Company</label>
              <select className="kf-input" value={companyId} onChange={e => setCompanyId(e.target.value)}>
                {companies.map(c => <option key={c.id} value={c.id}>{c.name || c.company_name}</option>)}
              </select>
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
};

/* ===================================================================
   COMPANIES
   Multi-tenant orgs. Switch active workspace, see usage per org.
   =================================================================== */
const ORG_ROWS = [
  { id:'o7', name:'Skyline Composites',     domain:'skyline-c.com',      plan:'Team',       members:  1, projects:  0, owner:'(pending)',    status:'pending',   created:'2026-05-23', mrr: 0,    admins:[{ name:'David Cho',     email:'david@skyline-c.com', role:'Owner Admin', signupIp:'72.14.5.42', verified:false }], requestedAt:'2 hours ago' },
  { id:'o8', name:'Arrowhead Robotics',     domain:'arrowhead.ai',       plan:'Enterprise', members:  1, projects:  0, owner:'(pending)',    status:'pending',   created:'2026-05-23', mrr: 0,    admins:[{ name:'Sara Patel',    email:'sara@arrowhead.ai', role:'Owner Admin', signupIp:'34.219.18.7', verified:true }],  requestedAt:'5 hours ago' },
  { id:'o1', name:'Ikran Aerospace',        domain:'ikran.aero',         plan:'Enterprise', members: 14, projects: 47, owner:'M. Adler',  status:'active',    created:'2024-03-12', mrr: 320,  admins:[{ name:'Maya Adler',    email:'maya@ikran.aero',     role:'Owner Admin' }, { name:'Laila Kohli', email:'laila@ikran.aero', role:'Billing Admin' }] },
  { id:'o2', name:'Boreal Drones',          domain:'borealdrones.com',   plan:'Team',       members:  6, projects: 12, owner:'L. Kohli',  status:'active',    created:'2025-01-04', mrr: 199,  admins:[{ name:'Laila Kohli',   email:'laila@borealdrones.com', role:'Owner Admin' }] },
  { id:'o3', name:'Cathay Marine Robotics', domain:'cathay-marine.io',   plan:'Team',       members:  4, projects:  8, owner:'L. Kohli',  status:'active',    created:'2025-06-21', mrr: 199,  admins:[{ name:'Laila Kohli',   email:'laila@cathay-marine.io', role:'Owner Admin' }] },
  { id:'o4', name:'Sandbox · personal',     domain:'kohli.dev',          plan:'Free',       members:  1, projects:  3, owner:'L. Kohli',  status:'active',    created:'2023-11-08', mrr: 0,    admins:[{ name:'Laila Kohli',   email:'laila@kohli.dev', role:'Owner Admin' }] },
  { id:'o5', name:'NovaSat Avionics',       domain:'novasat.space',      plan:'Enterprise', members:  9, projects: 21, owner:'R. Bedi',   status:'suspended', created:'2024-09-30', mrr: 0,    admins:[{ name:'Reza Bedi',     email:'reza@novasat.space', role:'Owner Admin' }] },
  { id:'o6', name:'Helix Composites',       domain:'helix-c.com',        plan:'Team',       members:  3, projects:  5, owner:'D. Halmos', status:'trial',     created:'2026-05-18', mrr: 0,    admins:[{ name:'Dan Halmos',    email:'dan@helix-c.com', role:'Owner Admin' }] },
];
const PLAN_TONE = { Free:'info', Team:'success', Enterprise:'violet' };
const PLAN_OPTS = ['Free', 'Team', 'Enterprise'];
const ORG_STATUS_TONE = { active:'success', suspended:'danger', trial:'warning', pending:'info' };

const CompaniesPanel = ({ onClose }) => {
  const toast = useToast();
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(true);
  const [q, setQ] = useState('');
  const [statusFilter, setStatusFilter] = useState('all');
  const [createOpen, setCreateOpen] = useState(false);
  const [editing, setEditing] = useState(null);  // company being edited, or null
  const [confirm, setConfirm] = useState(null);

  const refresh = useCallback(async () => {
    try {
      const list = await kfxListCompanies();
      // Normalise: backend rows use { id, name, status, plan, ... }; the
      // panel reads .name/.status/.id/.plan/.created_at directly.
      setRows(Array.isArray(list) ? list : []);
    } catch (e) {
      toast.err('Could not load companies', (e && e.message) || 'Unknown error');
    } finally {
      setLoading(false);
    }
  }, [toast]);

  useEffect(() => { refresh(); }, [refresh]);

  const stats = useMemo(() => ({
    total:     rows.length,
    pending:   rows.filter(r => r.status === 'pending').length,
    active:    rows.filter(r => r.status === 'active').length,
    suspended: rows.filter(r => r.status === 'suspended').length,
    trial:     rows.filter(r => r.status === 'trial').length,
  }), [rows]);

  const approveOrg = async (id, name) => {
    try {
      await kfxApproveCompany(id);
      toast.ok('Workspace approved', `${name} is live (14-day trial)`);
      await refresh();
    } catch (e) {
      toast.err('Approve failed', (e && e.message) || 'Unknown error');
    }
  };
  const setStatus = async (id, name, status) => {
    try {
      await kfxSetCompanyStatus(id, status);
      toast.ok('Status updated', `${name} → ${status}`);
      await refresh();
    } catch (e) {
      toast.err('Update failed', (e && e.message) || 'Unknown error');
    }
  };
  /* Save edited company. Super-admin only — backend PUT /api/companies/{cid}
     allows superadmin to edit any company, tenant-admin only their own. */
  const saveEdit = async (draft) => {
    try {
      await kfxUpdateCompany(draft.id, {
        name: draft.name,
        email_domain: draft.email_domain,
        plan: draft.plan,
        signup_email: draft.signup_email,
      });
      toast.ok('Workspace saved', draft.name);
      setEditing(null);
      await refresh();
    } catch (e) {
      toast.err('Save failed', (e && e.message) || 'Unknown error');
    }
  };

  const filtered = useMemo(() => {
    let list = rows;
    if (statusFilter !== 'all') list = list.filter(r => r.status === statusFilter);
    const needle = q.trim().toLowerCase();
    if (needle) list = list.filter(r => ((r.name || '') + ' ' + (r.email_domain || '') + ' ' + (r.signup_email || '')).toLowerCase().includes(needle));
    return list;
  }, [rows, statusFilter, q]);

  return (
    <AdminSlideover
      title="Companies & workspaces"
      subtitle={`Super-admin view · ${stats.total} tenants · ${stats.pending > 0 ? `${stats.pending} awaiting approval` : 'all approved'}`}
      onClose={onClose}
      headerExtra={
        <>
          {stats.pending > 0 && <Chip dot tone="warning">{stats.pending} pending</Chip>}
          <Btn kind="primary" size="sm" icon="plus" onClick={() => setCreateOpen(true)}>Add company</Btn>
        </>
      }>
      <div className="kf-admin-stats">
        <div className="kf-admin-stat"><div className="kf-admin-stat-n num" style={stats.pending > 0 ? { color: 'var(--warning)' } : undefined}>{stats.pending}</div><div className="kf-admin-stat-l">Awaiting approval</div></div>
        <div className="kf-admin-stat"><div className="kf-admin-stat-n num">{stats.active}</div><div className="kf-admin-stat-l">Active</div></div>
        <div className="kf-admin-stat"><div className="kf-admin-stat-n num">{stats.trial}</div><div className="kf-admin-stat-l">In trial</div></div>
        <div className="kf-admin-stat"><div className="kf-admin-stat-n num">{stats.suspended}</div><div className="kf-admin-stat-l">Suspended</div></div>
      </div>

      <div className="kf-admin-toolbar">
        <div className="kf-admin-search">
          <Icon name="search" size={13} stroke="var(--t-3)"/>
          <input value={q} onChange={e => setQ(e.target.value)}
                 placeholder="Search by company name, domain or email…"
                 aria-label="Search companies"/>
        </div>
        <div className="kf-admin-chips">
          {[['all','Any status'],['pending','Pending'],['active','Active'],['trial','Trial'],['suspended','Suspended']].map(([k, l]) => (
            <button key={k}
                    className={`kf-admin-chip ${statusFilter === k ? 'on' : ''}`}
                    onClick={() => setStatusFilter(k)}>{l}{k === 'pending' && stats.pending > 0 && <span className="kf-admin-chip-n" style={{ background:'var(--warning-soft)', color:'var(--warning)' }}>{stats.pending}</span>}</button>
          ))}
        </div>
      </div>

      <div className="kf-admin-body">
        {loading && <div style={{ padding: 20, color:'var(--t-3)', fontSize:12 }}>Loading companies…</div>}
        {!loading && filtered.length === 0 && <EmptyState compact icon="search" title="No companies match" hint="Try a different search or filter."/>}
        {!loading && filtered.length > 0 && (
          <table className="kf-admin-table">
            <thead>
              <tr>
                <th>Company</th>
                <th>Domain</th>
                <th>Status</th>
                <th>Plan</th>
                <th>Created</th>
                <th aria-label="Actions"/>
              </tr>
            </thead>
            <tbody>
              {filtered.map(o => (
                <tr key={o.id}>
                  <td>
                    <div className="kf-admin-who">
                      <div className="kf-org-avatar" style={{ background: stringToColor(o.name || ''), width:28, height:28, fontSize:10 }}>
                        {(o.name || '?').split(' ').map(s => s[0]).join('').slice(0,2).toUpperCase()}
                      </div>
                      <div>
                        <div className="kf-audit-who-name">{o.name}</div>
                        <div className="kf-audit-who-role num">{o.signup_email || ''}</div>
                      </div>
                    </div>
                  </td>
                  <td className="kf-admin-muted num">{o.email_domain || '—'}</td>
                  <td><Chip size="sm" dot tone={ORG_STATUS_TONE[o.status] || 'neutral'}>{o.status}</Chip></td>
                  <td>
                    {o.status === 'pending' ? (
                      <span className="kf-admin-muted">—</span>
                    ) : (
                      <select className="kf-input kf-input-sm"
                              value={o.status}
                              onChange={e => setStatus(o.id, o.name, e.target.value)}>
                        <option value="active">active</option>
                        <option value="trial">trial</option>
                        <option value="suspended">suspended</option>
                      </select>
                    )}
                  </td>
                  <td className="kf-admin-muted num">{(o.created_at || '').slice(0, 10) || '—'}</td>
                  <td className="kf-admin-actions">
                    {/* Edit is super-admin's primary action — rename, change
                        domain, switch plan. PUT /api/companies/{cid}. */}
                    <IconBtn icon="edit" label={`Edit ${o.name}`}
                             onClick={() => setEditing({
                               id: o.id,
                               name: o.name || '',
                               email_domain: o.email_domain || '',
                               plan: o.plan || '',
                               signup_email: o.signup_email || '',
                               status: o.status,
                             })}/>
                    {o.status === 'pending' && (
                      <Btn size="sm" kind="primary" icon="check"
                           onClick={() => approveOrg(o.id, o.name)}>
                        Approve
                      </Btn>
                    )}
                    {(o.status === 'active' || o.status === 'trial') && (
                      <Btn size="sm" kind="ghost" danger
                           onClick={() => setConfirm({
                             title: `Suspend ${o.name}?`,
                             body: <>Members will lose access until you reactivate.</>,
                             confirmLabel: 'Suspend',
                             danger: true,
                             onConfirm: () => setStatus(o.id, o.name, 'suspended'),
                           })}>
                        Suspend
                      </Btn>
                    )}
                    {o.status === 'suspended' && (
                      <Btn size="sm" kind="ghost"
                           onClick={() => setStatus(o.id, o.name, 'active')}>
                        Reactivate
                      </Btn>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {createOpen && (
        <CreateCompanyModal
          onClose={() => setCreateOpen(false)}
          onCreated={async () => { setCreateOpen(false); await refresh(); }}/>
      )}
      {editing && (
        <EditCompanyModal
          draft={editing}
          onChange={setEditing}
          onClose={() => setEditing(null)}
          onSave={saveEdit}/>
      )}
      {confirm && <ConfirmModal {...confirm} onClose={() => setConfirm(null)}/>}
    </AdminSlideover>
  );
};

/* Super-admin edit modal — name, domain, plan, signup_email.
   Status is changed via the row's status dropdown or Suspend/Reactivate
   buttons, NOT here, to keep the edit modal scoped to identity fields. */
const EditCompanyModal = ({ draft, onChange, onClose, onSave }) => {
  const setF = (k, v) => onChange({ ...draft, [k]: v });
  return (
    <Modal title={`Edit · ${draft.name || '—'}`} size="md" onClose={onClose} footer={
      <>
        <Btn kind="ghost" onClick={onClose}>Cancel</Btn>
        <Btn kind="primary" icon="check" onClick={() => onSave(draft)}>Save changes</Btn>
      </>
    }>
      <div className="kf-form">
        <label className="kf-field">
          <span className="kf-field-label">Company name</span>
          <input className="kf-input" value={draft.name}
                 onChange={e => setF('name', e.target.value)} autoFocus/>
        </label>
        <label className="kf-field">
          <span className="kf-field-label">Email domain</span>
          <input className="kf-input" value={draft.email_domain}
                 onChange={e => setF('email_domain', e.target.value)}
                 placeholder="example.com"/>
        </label>
        <label className="kf-field">
          <span className="kf-field-label">Plan</span>
          <select className="kf-input" value={draft.plan || ''}
                  onChange={e => setF('plan', e.target.value)}>
            <option value="">(none)</option>
            <option value="trial">trial</option>
            <option value="starter">starter</option>
            <option value="pro">pro</option>
            <option value="enterprise">enterprise</option>
          </select>
        </label>
        <label className="kf-field">
          <span className="kf-field-label">Signup email (read-only audit)</span>
          <input className="kf-input" value={draft.signup_email}
                 onChange={e => setF('signup_email', e.target.value)}
                 placeholder="admin@example.com"/>
        </label>
        <div className="kf-field-hint" style={{ color: 'var(--t-3)', fontSize: 11.5, marginTop: 4 }}>
          Status changes (Approve / Suspend / Reactivate) use the row buttons in the table — not this form.
        </div>
      </div>
    </Modal>
  );
};

const CreateCompanyModal = ({ onClose, onCreated }) => {
  const toast = useToast();
  const [name, setName]     = useState('');
  const [domain, setDomain] = useState('');
  const [busy, setBusy] = useState(false);
  const canSubmit = name.trim() && domain.trim();

  const submit = async () => {
    setBusy(true);
    try {
      await kfxCreateCompany({
        name: name.trim(),
        email_domain: domain.trim().toLowerCase(),
      });
      toast.ok('Company created', name.trim());
      await onCreated();
    } catch (e) {
      toast.err('Create failed', (e && e.message) || 'Unknown error');
      setBusy(false);
    }
  };

  return (
    <Modal title="New company" size="md" onClose={busy ? () => {} : onClose} footer={
      <>
        <Btn kind="ghost" onClick={onClose} disabled={busy}>Cancel</Btn>
        <Btn kind="primary" icon="check" disabled={!canSubmit || busy} busy={busy} onClick={submit}>
          Create company
        </Btn>
      </>
    }>
      <div className="kf-form">
        <div className="kf-form-row">
          <div className="kf-field">
            <label>Company name <span className="kf-req">*</span></label>
            <input className="kf-input" placeholder="e.g. Helix Composites" value={name} onChange={e => setName(e.target.value)} autoFocus/>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-field">
            <label>Primary email domain <span className="kf-req">*</span></label>
            <input className="kf-input num" placeholder="helix-c.com" value={domain} onChange={e => setDomain(e.target.value)}/>
            <div className="kf-field-hint">Used to scope user accounts to this workspace.</div>
          </div>
        </div>
      </div>
    </Modal>
  );
};

const stringToColor = (s) => {
  let h = 0; for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0;
  return `hsl(${Math.abs(h) % 360} 50% 35%)`;
};

/* ===================================================================
   SHARE LINKS — wired to /api/projects/{pid}/shares and /api/share/{token}
   Scoped to the currently-open project (realPid from app.jsx).
   =================================================================== */
const ShareLinksPanel = ({ onClose, realPid, projectName }) => {
  const toast = useToast();
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(true);
  const [createOpen, setCreateOpen] = useState(false);
  const [confirm, setConfirm] = useState(null);

  const refresh = useCallback(async () => {
    if (!realPid) { setLoading(false); return; }
    try {
      const list = await kfxListShareLinks(realPid);
      setRows(Array.isArray(list) ? list : []);
    } catch (e) {
      toast.err('Could not load share links', (e && e.message) || 'Unknown error');
    } finally {
      setLoading(false);
    }
  }, [realPid, toast]);

  useEffect(() => { refresh(); }, [refresh]);

  if (!realPid) {
    return (
      <AdminSlideover title="Share links" subtitle="Open a project first" onClose={onClose}>
        <div className="kf-admin-body">
          <EmptyState icon="share" title="No project selected"
                      hint="Open a project from the topbar, then re-open this panel to manage its share links."/>
        </div>
      </AdminSlideover>
    );
  }

  return (
    <AdminSlideover
      title="Share links"
      subtitle={`${projectName || ''} · public read-only URLs`}
      onClose={onClose}
      headerExtra={<Btn kind="primary" size="sm" icon="plus" onClick={() => setCreateOpen(true)}>New share link</Btn>}>

      <div className="kf-admin-body">
        {loading && <div style={{ padding: 20, color:'var(--t-3)', fontSize:12 }}>Loading…</div>}
        {!loading && rows.length === 0 && (
          <EmptyState compact icon="share" title="No share links yet" hint="Click 'New share link' to mint one."/>
        )}
        {!loading && rows.length > 0 && (
          <div className="kf-share-list">
            {rows.map(l => {
              const url = `${window.location.origin}/api/share/${l.token}`;
              const status = l.status || 'active';
              const isInactive = status !== 'active';
              return (
                <div key={l.token} className={`kf-share-row ${isInactive ? 'expired' : ''}`}>
                  <div className="kf-share-icon" style={{ background: 'var(--info-soft)' }}>
                    <Icon name="share" size={14} stroke="var(--info)"/>
                  </div>
                  <div className="kf-share-main">
                    <div className="kf-share-name">
                      {l.note || '(no note)'}
                      <Chip size="sm" dot tone={status === 'active' ? 'success' : status === 'expired' ? 'warning' : 'danger'}>{status}</Chip>
                    </div>
                    <div className="kf-share-url num" title={url}>{url}</div>
                  </div>
                  <div className="kf-share-expiry">
                    <div className="kf-admin-muted">Expires</div>
                    <div className="num">{l.expires_at ? l.expires_at.slice(0, 10) : 'never'}</div>
                  </div>
                  <div className="kf-share-actions">
                    <IconBtn icon="copy" label="Copy link"
                             onClick={() => { navigator.clipboard?.writeText(url); toast.ok('Link copied'); }}/>
                    {status === 'active' && (
                      <IconBtn icon="trash" label="Revoke link" danger
                               onClick={() => setConfirm({
                                 title: 'Revoke this share link?',
                                 body: <>Anyone using this link will lose access immediately. This cannot be undone.</>,
                                 confirmLabel: 'Revoke link',
                                 danger: true,
                                 onConfirm: async () => {
                                   try {
                                     await kfxRevokeShareLink(l.token);
                                     toast.ok('Share link revoked');
                                     await refresh();
                                   } catch (e) {
                                     toast.err('Revoke failed', (e && e.message) || 'Unknown error');
                                   }
                                 },
                               })}/>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>

      {createOpen && (
        <NewShareLinkModal realPid={realPid}
          onClose={() => setCreateOpen(false)}
          onCreated={async () => { setCreateOpen(false); await refresh(); }}/>
      )}
      {confirm && <ConfirmModal {...confirm} onClose={() => setConfirm(null)}/>}
    </AdminSlideover>
  );
};

const NewShareLinkModal = ({ realPid, onClose, onCreated }) => {
  const toast = useToast();
  const [expires, setExpires] = useState('');   // YYYY-MM-DD; empty = never
  const [note, setNote]       = useState('');
  const [busy, setBusy] = useState(false);
  const submit = async () => {
    setBusy(true);
    try {
      const r = await kfxCreateShareLink(realPid, { expires_at: expires || null, note });
      toast.ok('Share link created', r.url || r.token || '');
      await onCreated();
    } catch (e) {
      toast.err('Create failed', (e && e.message) || 'Unknown error');
      setBusy(false);
    }
  };
  return (
    <Modal title="New share link" size="md" onClose={busy ? () => {} : onClose} footer={
      <>
        <Btn kind="ghost" onClick={onClose} disabled={busy}>Cancel</Btn>
        <Btn kind="primary" icon="check" disabled={busy} busy={busy} onClick={submit}>
          Create link
        </Btn>
      </>
    }>
      <div className="kf-form">
        <div className="kf-form-row">
          <div className="kf-field">
            <label>Expires on</label>
            <input className="kf-input num" type="date" value={expires} onChange={e => setExpires(e.target.value)}/>
            <div className="kf-field-hint">Leave blank for no expiry.</div>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-field">
            <label>Note (optional)</label>
            <input className="kf-input" value={note} onChange={e => setNote(e.target.value)}
                   placeholder="e.g. 'Vendor pin-out · J3.2'"/>
          </div>
        </div>
      </div>
    </Modal>
  );
};

/* ===================================================================
   SYSTEM HEALTH — wired to /api/health, /api/version, /api/admin/backups
   Backend doesn't expose service-level uptime / incidents / resource
   usage, so those sections are dropped (read-only — show what we have).
   =================================================================== */
const STATUS_TONE  = { ok:'success', warn:'warning', err:'danger' };
const STATUS_LABEL = { ok:'Operational', warn:'Degraded', err:'Outage' };

const SystemHealthPanel = ({ onClose }) => {
  const toast = useToast();
  const [health, setHealth]   = useState(null);   // null = loading, {ok:bool}
  const [version, setVersion] = useState(null);   // {version, name}
  const [latest, setLatest]   = useState(null);   // newest backup row
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const [h, v, backups] = await Promise.all([
          kfxGetHealth().catch(() => ({ ok: false })),
          kfxGetVersion().catch(() => null),
          kfxListBackups().catch(() => []),
        ]);
        if (cancelled) return;
        setHealth(h);
        setVersion(v);
        setLatest(Array.isArray(backups) && backups.length > 0 ? backups[0] : null);
      } catch (e) {
        if (!cancelled) toast.err('Could not load health', (e && e.message) || 'Unknown');
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, [toast]);

  const status = !health ? 'warn' : (health.ok ? 'ok' : 'err');

  return (
    <AdminSlideover title="System health" subtitle="API status · version · last backup"
                    onClose={onClose}
                    headerExtra={<Chip dot tone={STATUS_TONE[status]}>{STATUS_LABEL[status]}</Chip>}>
      <div className="kf-admin-body">
        {loading && <div style={{ padding: 20, color:'var(--t-3)', fontSize:12 }}>Probing backend…</div>}
        {!loading && (
          <>
            <div className="kf-admin-section-label">Services</div>
            <div className="kf-sys-grid">
              <div className={`kf-sys-card kf-sys-card-${status}`}>
                <div className="kf-sys-card-head">
                  <span className={`kf-status-dot kf-status-${status === 'ok' ? 'active' : status === 'warn' ? 'review' : 'archived'}`}/>
                  <div className="kf-sys-card-name">API</div>
                  <div className="kf-sys-card-v num">{version ? `v${version.version}` : '—'}</div>
                </div>
                <div className="kf-sys-card-row">
                  <div><div className="kf-sys-stat-l">Status</div><div className="kf-sys-stat-n num">{health && health.ok ? 'OK' : 'DOWN'}</div></div>
                  <div><div className="kf-sys-stat-l">App</div><div className="kf-sys-stat-n num">{version ? version.name : '—'}</div></div>
                </div>
              </div>

              <div className="kf-sys-card kf-sys-card-ok">
                <div className="kf-sys-card-head">
                  <span className="kf-status-dot kf-status-active"/>
                  <div className="kf-sys-card-name">Database backups</div>
                  <div className="kf-sys-card-v num">{latest ? latest.label : '—'}</div>
                </div>
                <div className="kf-sys-card-row">
                  <div><div className="kf-sys-stat-l">Last snapshot</div><div className="kf-sys-stat-n num">{latest ? (latest.timestamp || latest.filename) : 'never'}</div></div>
                  <div><div className="kf-sys-stat-l">Latest size</div><div className="kf-sys-stat-n num">{latest ? `${(latest.size_kb || 0).toFixed ? latest.size_kb.toFixed(1) : latest.size_kb}` : '—'}<span>KB</span></div></div>
                </div>
              </div>
            </div>
          </>
        )}
      </div>
    </AdminSlideover>
  );
};

/* ---------- Styles ---------- */
const ADMIN_STYLE = `
.kf-slideover-wide { max-width: 1080px; width: 92vw; }
.kf-slideover-head-actions { display: flex; align-items: center; gap: 8px; }

.kf-admin-toolbar {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.kf-admin-search {
  display: flex; align-items: center; gap: 8px;
  flex: 1; min-width: 220px;
  height: 32px; padding: 0 12px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  transition: border-color .12s var(--ease);
}
.kf-admin-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.kf-admin-search input { flex:1; background: transparent; border: none; outline: none; color: var(--t-1); font-family: inherit; font-size: 12.5px; }
.kf-admin-search input::placeholder { color: var(--t-4); }

.kf-admin-chips { display: flex; gap: 4px; flex-wrap: wrap; }
.kf-admin-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 10px;
  background: transparent; border: 1px solid transparent;
  color: var(--t-2);
  font-family: inherit; font-size: 11.5px; font-weight: 500;
  border-radius: var(--r-2); cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease), border-color .12s var(--ease);
}
.kf-admin-chip:hover:not(.on) { background: var(--bg-3); color: var(--t-1); }
.kf-admin-chip.on { background: var(--bg-1); border-color: var(--line-strong); color: var(--t-1); }
.kf-admin-chip-n { font-family: var(--f-mono); font-size: 10px; color: var(--t-3); padding: 1px 6px; background: var(--bg-2); border-radius: 999px; }

.kf-admin-body { padding: 16px 20px 28px; overflow-y: auto; flex: 1; }

.kf-admin-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; padding: 16px 20px 6px; }
.kf-admin-stat { padding: 12px 14px; background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-3); }
.kf-admin-stat-n { font-family: var(--f-mono); font-size: 22px; font-weight: 600; color: var(--t-1); }
.kf-admin-stat-l { font-size: 11px; color: var(--t-3); text-transform: uppercase; letter-spacing: .05em; margin-top: 2px; }

.kf-admin-section-label {
  font-family: var(--f-mono); font-size: 10.5px; font-weight: 600;
  color: var(--t-3); text-transform: uppercase; letter-spacing: .08em;
  margin: 18px 0 10px;
}
.kf-admin-section-label:first-child { margin-top: 0; }
.kf-admin-muted { color: var(--t-3); font-size: 11.5px; }

/* Audit log */
.kf-audit-day { margin-bottom: 18px; }
.kf-audit-day-head { display: flex; justify-content: space-between; align-items: baseline; padding: 4px 2px 8px; font-size: 11.5px; color: var(--t-3); font-family: var(--f-mono); border-bottom: 1px dashed var(--line); }
.kf-audit-list { display: flex; flex-direction: column; }
.kf-audit-row {
  display: grid;
  grid-template-columns: 80px 80px 200px 1fr 120px;
  gap: 12px; align-items: center;
  padding: 10px 6px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12.5px;
}
.kf-audit-row:hover { background: var(--bg-1); }
.kf-audit-time { color: var(--t-3); font-size: 11.5px; }
.kf-audit-who { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kf-audit-avatar {
  width: 24px; height: 24px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 50%;
  font-size: 9.5px; font-weight: 700; color: var(--t-2);
  letter-spacing: .02em; text-transform: uppercase;
}
.kf-audit-who-name { font-size: 12.5px; font-weight: 600; color: var(--t-1); }
.kf-audit-who-role { font-size: 10.5px; color: var(--t-3); text-transform: uppercase; letter-spacing: .04em; }
.kf-audit-detail { min-width: 0; }
.kf-audit-target { font-size: 11.5px; font-weight: 600; color: var(--t-2); }
.kf-audit-msg { font-size: 12px; color: var(--t-2); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kf-audit-ip { font-size: 11px; color: var(--t-3); text-align: right; }

/* Users table */
.kf-admin-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; }
.kf-admin-table thead th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--t-3); font-weight: 600; padding: 8px 12px; border-bottom: 1px solid var(--line); }
.kf-admin-table tbody td { padding: 10px 12px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.kf-admin-table tbody tr:hover { background: var(--bg-1); }
.kf-admin-who { display: flex; align-items: center; gap: 10px; min-width: 0; }
.kf-input-sm { height: 28px; font-size: 12px; padding: 0 8px; }
.kf-admin-actions { display: flex; gap: 4px; justify-content: flex-end; align-items: center; }

/* Companies */
.kf-org-current {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
  padding: 18px 20px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--line);
}
.kf-org-current-label { font-family: var(--f-mono); font-size: 10px; font-weight: 600; color: var(--t-3); text-transform: uppercase; letter-spacing: .08em; }
.kf-org-current-name { font-family: var(--f-display); font-size: 22px; font-weight: 700; color: var(--t-1); margin: 4px 0 6px; letter-spacing: -.3px; }
.kf-org-current-meta { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--t-3); flex-wrap: wrap; }
.kf-org-list { display: flex; flex-direction: column; gap: 6px; }
.kf-org-row {
  display: grid;
  grid-template-columns: 36px 1fr auto auto auto auto;
  gap: 14px; align-items: center;
  padding: 12px 14px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
}
.kf-org-avatar {
  width: 36px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 12px; font-weight: 700;
  border-radius: var(--r-2); letter-spacing: .04em;
}
.kf-org-name { font-size: 13.5px; font-weight: 600; color: var(--t-1); }
.kf-org-meta { font-size: 11.5px; color: var(--t-3); margin-top: 2px; }
.kf-org-stats { display: flex; gap: 16px; font-size: 12px; }
.kf-org-stats .num { font-family: var(--f-mono); font-weight: 600; color: var(--t-1); }

/* Share links */
.kf-share-list { display: flex; flex-direction: column; gap: 6px; }
.kf-share-row {
  display: grid;
  grid-template-columns: 36px 1fr 140px 130px 80px;
  gap: 14px; align-items: center;
  padding: 12px 14px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
}
.kf-share-row.expired { opacity: .65; }
.kf-share-icon { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: var(--r-2); }
.kf-share-name { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--t-1); }
.kf-share-url { font-size: 11.5px; color: var(--t-3); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kf-share-stats > div + div { margin-top: 2px; }
.kf-share-stats .num { font-family: var(--f-mono); font-weight: 600; color: var(--t-2); }
.kf-share-expiry .num { font-family: var(--f-mono); font-weight: 600; color: var(--t-1); }
.kf-share-expired-text { color: var(--danger) !important; }
.kf-share-actions { display: flex; gap: 4px; justify-content: flex-end; }

/* System health */
.kf-sys-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; }
.kf-sys-card {
  padding: 14px 16px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  color: var(--success);
}
.kf-sys-card-warn { color: var(--warning); border-color: rgba(245,183,58,.32); }
.kf-sys-card-err  { color: var(--danger);  border-color: rgba(239,78,78,.32); background: rgba(239,78,78,.04); }
.kf-sys-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.kf-sys-card-name { font-size: 13px; font-weight: 600; color: var(--t-1); flex: 1; }
.kf-sys-card-v { font-family: var(--f-mono); font-size: 10.5px; color: var(--t-3); }
.kf-sys-card-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-bottom: 8px; }
.kf-sys-stat-l { font-size: 10px; color: var(--t-3); text-transform: uppercase; letter-spacing: .05em; }
.kf-sys-stat-n { font-family: var(--f-mono); font-size: 15px; font-weight: 600; color: var(--t-1); margin-top: 2px; }
.kf-sys-stat-n span { font-size: 10px; font-weight: 500; color: var(--t-3); margin-left: 2px; }
.kf-sys-stat-region { font-size: 11px; }
.kf-sys-spark { width: 100%; height: 28px; opacity: .8; }
.kf-sys-note { display: flex; align-items: center; gap: 6px; margin-top: 8px; font-size: 11.5px; color: var(--warning); }

.kf-incident-list { display: flex; flex-direction: column; }
.kf-incident-row { display: flex; align-items: center; gap: 14px; padding: 10px 8px; border-bottom: 1px solid var(--line-soft); }
.kf-incident-text { flex: 1; }
.kf-incident-title { font-size: 12.5px; font-weight: 600; color: var(--t-1); }
.kf-incident-meta { font-family: var(--f-mono); font-size: 11px; color: var(--t-3); margin-top: 2px; }

.kf-sys-usage { display: flex; flex-direction: column; gap: 8px; }
.kf-sys-usage-row { display: grid; grid-template-columns: 130px 1fr 60px 1fr; gap: 12px; align-items: center; font-size: 12px; }
.kf-sys-usage-l { color: var(--t-2); font-weight: 500; }
.kf-sys-usage-bar { height: 6px; background: var(--bg-3); border-radius: 999px; overflow: hidden; }
.kf-sys-usage-bar > div { height: 100%; border-radius: 999px; }
.kf-sys-usage-pct { font-family: var(--f-mono); font-weight: 600; color: var(--t-1); text-align: right; }

/* Workspace settings panel layout */
.kf-ws-body { display: grid; grid-template-columns: 200px 1fr; flex: 1; overflow: hidden; }
.kf-ws-nav { padding: 14px 8px; border-right: 1px solid var(--line); background: var(--bg-1); display: flex; flex-direction: column; gap: 2px; overflow-y: auto; }
.kf-ws-panel { padding: 18px 20px 28px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }
/* In a flex column, .card (overflow:hidden) was getting squeezed below
   its content height, cropping bodies and showing only the head row.
   Block shrinking so each card expands to its natural height. */
.kf-ws-panel > .card,
.kf-settings-panel > .card { flex-shrink: 0; }

/* Workspace + Project Settings cards use a roomier, more readable header.
   Layout: h3 on top-left, trailing action on top-right, kf-card-sub on a
   full-width line beneath both. Explicit row spacing so the action button
   never crushes against the title. */
.kf-ws-panel .card-head,
.kf-settings .card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  padding: 18px 20px 14px;
  gap: 10px 16px;
}
.kf-ws-panel .card-head > h3,
.kf-settings .card-head > h3 {
  flex: 1 1 auto;
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: -.01em;
  color: var(--t-1);
  margin: 0;
}
/* Trailing action (button/chip) on the top row, hard right. */
.kf-ws-panel .card-head > .kf-btn,
.kf-ws-panel .card-head > .kf-chip,
.kf-ws-panel .card-head > .kf-iconbtn,
.kf-settings .card-head > .kf-btn,
.kf-settings .card-head > .kf-chip,
.kf-settings .card-head > .kf-iconbtn { margin-left: auto; flex-shrink: 0; }
/* Subtitle drops to its own row, separated from the title row by the
   row gap (10px). No negative margin hack. */
.kf-ws-panel .card-head > .kf-card-sub,
.kf-settings .card-head > .kf-card-sub {
  flex: 0 0 100%;
  margin: 0;
  font-size: 12.5px;
  color: var(--t-3);
  line-height: 1.5;
  max-width: 620px;
  font-weight: 400;
}
.kf-ws-panel .card-body,
.kf-settings .card-body { padding: 14px 20px 18px; }
.kf-ws-plan-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 12px 0; border-bottom: 1px dashed var(--line); }
.kf-ws-plan-row:last-child { border-bottom: none; }
.kf-ws-plan-name { font-size: 15px; font-weight: 600; color: var(--t-1); }
.kf-ws-plan-meta { font-size: 12px; color: var(--t-3); margin-top: 4px; line-height: 1.5; max-width: 420px; }
.kf-ws-plan-price .num { font-family: var(--f-mono); font-size: 22px; font-weight: 600; color: var(--t-1); }
.kf-ws-logo-drop {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 16px;
  background: var(--bg-1);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-3);
}
.kf-ws-logo-drop > div { flex: 1; font-size: 12px; }

/* — Workspace usage cards (Overview section) — */
.kf-ws-usage {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}
.kf-ws-stat-card {
  padding: 14px 16px 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  display: flex; flex-direction: column; gap: 6px;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.kf-ws-stat-card:hover { background: var(--bg-3); border-color: var(--line-strong); }
.kf-ws-stat-top { display: flex; align-items: center; gap: 8px; }
.kf-ws-stat-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  border-radius: 6px;
  flex-shrink: 0;
}
.kf-ws-stat-icon-info    { background: var(--info-soft);    color: var(--info); }
.kf-ws-stat-icon-success { background: var(--success-soft); color: var(--success); }
.kf-ws-stat-icon-warning { background: var(--warning-soft); color: var(--warning); }
.kf-ws-stat-icon-violet  { background: rgba(167,139,250,.16); color: var(--violet); }
.kf-ws-stat-icon svg { stroke: currentColor; }
.kf-ws-stat-label {
  font-size: 11px; font-weight: 600;
  color: var(--t-3);
  text-transform: uppercase; letter-spacing: .06em;
}
.kf-ws-stat-delta {
  margin-left: auto;
  font-family: var(--f-mono); font-size: 11px; font-weight: 700;
  padding: 1px 6px;
  border-radius: 4px;
}
.kf-ws-stat-delta-success { background: var(--success-soft); color: var(--success); }
.kf-ws-stat-delta-danger  { background: rgba(239,78,78,.16); color: var(--danger); }

.kf-ws-stat-num {
  display: flex; align-items: baseline; gap: 3px;
  font-family: var(--f-mono); font-size: 28px; font-weight: 700;
  color: var(--t-1); letter-spacing: -.5px; line-height: 1;
}
.kf-ws-stat-unit { font-size: 14px; font-weight: 600; color: var(--t-3); margin-left: 2px; }
.kf-ws-stat-of { font-size: 11.5px; color: var(--t-3); margin-top: 2px; }

.kf-ws-stat-bar {
  height: 4px; border-radius: 999px;
  background: var(--bg-1);
  overflow: hidden;
  margin-top: 4px;
}
.kf-ws-stat-bar-fill { height: 100%; border-radius: 999px; transition: width .25s var(--ease); }
.kf-ws-stat-bar-fill-info    { background: var(--info); }
.kf-ws-stat-bar-fill-success { background: var(--success); }
.kf-ws-stat-bar-fill-warning { background: var(--warning); }
.kf-ws-stat-bar-fill-violet  { background: var(--violet); }
.kf-ws-stat-note { font-size: 10.5px; color: var(--t-3); font-style: italic; margin-top: 2px; }

/* Company list (super-admin) */
.kf-co-list { display: flex; flex-direction: column; gap: 8px; }
.kf-co-card {
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  overflow: hidden;
  transition: border-color .12s var(--ease);
}
.kf-co-card.on { border-color: var(--line-strong); }
.kf-co-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 14px;
  cursor: pointer;
  transition: background .12s var(--ease);
}
.kf-co-row:hover { background: var(--bg-2); }
.kf-co-row > .kf-org-avatar { flex-shrink: 0; }
.kf-co-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.kf-co-name-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.kf-co-name { font-size: 14px; font-weight: 600; color: var(--t-1); line-height: 1.2; }
.kf-co-meta { font-size: 11.5px; color: var(--t-3); display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.kf-co-meta .num { font-family: var(--f-mono); }
.kf-co-stats {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  font-size: 11.5px; color: var(--t-3);
  margin-top: 2px;
}
.kf-co-stats .num { font-family: var(--f-mono); font-weight: 600; color: var(--t-2); }
.kf-co-right {
  display: flex; align-items: center; gap: 6px; flex-shrink: 0;
}
.kf-co-plan-select { width: 110px; height: 30px; padding: 0 8px; font-size: 12px; }
.kf-co-expand {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid transparent;
  border-radius: var(--r-2);
  cursor: pointer;
}
.kf-co-expand:hover { background: var(--bg-3); border-color: var(--line); }

@media (max-width: 560px) {
  .kf-co-right { flex-direction: column; align-items: flex-end; gap: 4px; }
  .kf-co-plan-select { width: 100px; }
}

.kf-co-detail {
  padding: 14px 16px 16px;
  background: var(--bg-2);
  border-top: 1px solid var(--line);
}
.kf-co-detail-head {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--f-mono); font-size: 10.5px; font-weight: 600;
  color: var(--t-3); text-transform: uppercase; letter-spacing: .08em;
  margin-bottom: 10px;
}
.kf-co-empty {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  background: var(--warning-soft);
  border: 1px solid rgba(245,183,58,.32);
  border-radius: var(--r-2);
  font-size: 12px; color: var(--warning);
}
.kf-co-admin-list { display: flex; flex-direction: column; gap: 4px; }
.kf-co-admin-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  background: var(--bg-1);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-2);
}
.kf-co-admin-text { flex: 1; min-width: 0; }
.kf-co-actions {
  display: flex; align-items: center; gap: 6px;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px dashed var(--line);
}

@media (max-width: 720px) {
  .kf-co-row { gap: 10px; padding: 10px 12px; }
}

/* — Invoice list (replaces narrow table; flex rows that always show actions) — */
.kf-inv-list { display: flex; flex-direction: column; }
.kf-inv-row {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line-soft);
}
.kf-inv-row:last-child { border-bottom: none; }
.kf-inv-row:hover { background: var(--bg-1); }
.kf-inv-main   { flex: 1; min-width: 0; }
.kf-inv-id     { font-family: var(--f-mono); font-size: 12.5px; font-weight: 600; color: var(--t-1); }
.kf-inv-period { font-size: 11px; color: var(--t-3); margin-top: 2px; }
.kf-inv-amount { font-family: var(--f-mono); font-size: 13px; font-weight: 700; color: var(--t-1); flex-shrink: 0; }
.kf-inv-status { flex-shrink: 0; }
.kf-inv-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; margin-left: auto; }

/* At narrow widths, wrap status + actions below the main info so they
   still fit, instead of getting cropped. */
@media (max-width: 560px) {
  .kf-inv-row { flex-wrap: wrap; row-gap: 8px; }
  .kf-inv-main { flex: 1 1 100%; }
  .kf-inv-amount { order: 2; }
  .kf-inv-status { order: 3; margin-left: auto; }
  .kf-inv-actions { order: 4; flex-basis: 100%; justify-content: flex-end; }
}

/* — Billing summary (simple) — */
.kf-bill-card { padding: 18px 20px; display: flex; flex-direction: column; gap: 16px; }
.kf-bill-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.kf-bill-eyebrow { font-family: var(--f-mono); font-size: 10.5px; font-weight: 600; color: var(--t-3); text-transform: uppercase; letter-spacing: .08em; margin-bottom: 6px; }
.kf-bill-tier-row { display: flex; align-items: center; gap: 10px; }
.kf-bill-tier { font-family: var(--f-display); font-size: 22px; font-weight: 700; color: var(--t-1); margin: 0; letter-spacing: -.3px; }
.kf-bill-price-block { display: flex; align-items: baseline; gap: 2px; }
.kf-bill-price-currency { font-family: var(--f-mono); font-size: 14px; color: var(--t-3); font-weight: 600; }
.kf-bill-price-amount   { font-family: var(--f-mono); font-size: 30px; font-weight: 700; color: var(--t-1); letter-spacing: -.5px; line-height: 1; }
.kf-bill-price-cycle    { font-size: 12.5px; color: var(--t-3); margin-left: 4px; }

.kf-bill-meta {
  display: flex; flex-direction: column;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
}
.kf-bill-meta-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0;
  font-size: 12.5px;
  border-bottom: 1px dashed var(--line-soft);
}
.kf-bill-meta-row:last-child { border-bottom: none; }
.kf-bill-meta-row > span:first-child { color: var(--t-3); }
.kf-bill-meta-row > span:last-child  { color: var(--t-1); display: flex; align-items: center; gap: 6px; font-weight: 500; }
.kf-bill-meta-row .num { font-family: var(--f-mono); }
.kf-bill-meta-row b.num { font-weight: 700; }

.kf-bill-card-badge {
  font-family: var(--f-mono); font-size: 9px; font-weight: 800; color: #fff;
  padding: 2px 5px; border-radius: 3px;
  background: linear-gradient(135deg, #1a1f71, #2a40b5);
  letter-spacing: .04em;
}

.kf-bill-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.kf-bill-foot-hint { font-size: 12px; color: var(--t-3); max-width: 360px; line-height: 1.45; }

.kf-bill-tip {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 12px;
  background: var(--bg-1);
  border: 1px dashed var(--line);
  border-radius: var(--r-2);
  font-size: 12px; color: var(--t-3); line-height: 1.5;
}
.kf-bill-tip a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.kf-bill-tip a:hover { color: var(--accent); text-decoration-thickness: 2px; }
.kf-bill-hero {
  background: linear-gradient(135deg, var(--bg-3) 0%, var(--bg-2) 100%);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-3);
  padding: 22px 24px 20px;
  display: flex; flex-direction: column; gap: 18px;
  position: relative; overflow: hidden;
}
.kf-bill-hero::before {
  /* subtle radial accent so the hero feels distinct from regular cards */
  content: ""; position: absolute; right: -120px; top: -120px;
  width: 320px; height: 320px;
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 70%);
  pointer-events: none;
}
.kf-bill-hero > * { position: relative; }
.kf-bill-hero-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.kf-bill-eyebrow { font-family: var(--f-mono); font-size: 10.5px; font-weight: 600; color: var(--t-3); text-transform: uppercase; letter-spacing: .08em; margin-bottom: 6px; }
.kf-bill-tier-row { display: flex; align-items: center; gap: 10px; }
.kf-bill-tier { font-family: var(--f-display); font-size: 28px; font-weight: 700; color: var(--t-1); margin: 0; letter-spacing: -.4px; }
.kf-bill-blurb { font-size: 13px; color: var(--t-2); margin-top: 6px; max-width: 460px; line-height: 1.5; }

.kf-bill-cycle-toggle {
  display: inline-flex;
  padding: 3px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
}
.kf-bill-cycle-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px;
  background: transparent; border: none;
  color: var(--t-2);
  font-family: inherit; font-size: 12.5px; font-weight: 600;
  border-radius: var(--r-2); cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.kf-bill-cycle-btn:hover { color: var(--t-1); }
.kf-bill-cycle-btn.on { background: var(--bg-3); color: var(--t-1); box-shadow: 0 1px 2px rgba(0,0,0,.18); }

.kf-bill-hero-mid {
  display: flex; align-items: baseline; gap: 14px;
  padding: 4px 0;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
}
.kf-bill-price-block { display: flex; align-items: baseline; gap: 4px; }
.kf-bill-price-currency { font-family: var(--f-mono); font-size: 18px; color: var(--t-3); font-weight: 600; }
.kf-bill-price-amount   { font-family: var(--f-mono); font-size: 42px; font-weight: 700; color: var(--t-1); letter-spacing: -1px; line-height: 1; }
.kf-bill-price-cycle    { font-size: 14px; color: var(--t-3); margin-left: 6px; }
.kf-bill-save           { font-size: 12px; color: var(--success); font-weight: 600; }

.kf-bill-hero-bottom { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.kf-bill-next-amt    { font-size: 14px; font-weight: 600; color: var(--t-1); margin-top: 2px; }
.kf-bill-next-amt .num { font-family: var(--f-mono); font-weight: 700; color: var(--t-1); }
.kf-bill-next-method { font-size: 11.5px; color: var(--t-3); margin-top: 4px; }
.kf-bill-next-method .num { font-family: var(--f-mono); color: var(--t-2); }
.kf-bill-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.kf-bill-tiers {
  display: flex; gap: 6px;
  padding-top: 14px;
  border-top: 1px dashed var(--line);
  flex-wrap: wrap;
}
.kf-bill-tier-pill {
  flex: 1 1 140px; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  padding: 10px 14px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  color: var(--t-2);
  font-family: inherit; font-size: 12px; font-weight: 600;
  cursor: pointer; text-align: left;
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.kf-bill-tier-pill .num { font-family: var(--f-mono); font-size: 13px; font-weight: 700; color: var(--t-1); }
.kf-bill-tier-pill:hover { background: var(--bg-3); border-color: var(--line-strong); }
.kf-bill-tier-pill.on { border-color: var(--accent); background: var(--bg-3); color: var(--t-1); box-shadow: inset 0 0 0 1px var(--accent); }

/* — Payment methods — */
.kf-pay-row {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line-soft);
}
.kf-pay-row:last-child { border-bottom: none; }
.kf-pay-row-default { background: var(--accent-soft); margin: 0 -10px; padding: 12px 10px; border-radius: var(--r-2); border-bottom: 1px solid transparent; }
.kf-pay-brand {
  width: 48px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 4px;
  font-family: var(--f-mono); font-size: 10px; font-weight: 800;
  letter-spacing: .04em;
  color: #fff;
  flex-shrink: 0;
}
.kf-pay-brand-visa { background: linear-gradient(135deg, #1a1f71, #2a40b5); }
.kf-pay-brand-mc   { background: linear-gradient(135deg, #eb001b, #f79e1b); }
.kf-pay-brand-bank { background: linear-gradient(135deg, #4a5568, #2d3748); }
.kf-pay-text { flex: 1; min-width: 0; }
.kf-pay-name { font-size: 13px; font-weight: 600; color: var(--t-1); }
.kf-pay-name .num { font-family: var(--f-mono); }
.kf-pay-meta { font-size: 11.5px; color: var(--t-3); margin-top: 3px; font-family: var(--f-mono); }

/* — Invoice table — */
.kf-invoice-table td { padding: 12px 16px; }
.kf-invoice-table .kf-btn-primary { padding: 4px 12px; height: 28px; font-size: 11.5px; }

@media (max-width: 720px) {
  .kf-slideover-wide { width: 100vw; }
  .kf-admin-stats { grid-template-columns: 1fr 1fr; }
  .kf-audit-row { grid-template-columns: 70px 70px 1fr; }
  .kf-audit-row > :nth-child(4), .kf-audit-row > :nth-child(5) { grid-column: 1 / -1; }
  .kf-org-row { grid-template-columns: 36px 1fr auto; }
  .kf-org-row > :nth-child(n+4) { grid-column: 2 / -1; }
  .kf-share-row { grid-template-columns: 36px 1fr; }
  .kf-share-row > :nth-child(n+3) { grid-column: 1 / -1; }
  .kf-ws-body { grid-template-columns: 1fr; }
  .kf-ws-nav { border-right: none; border-bottom: 1px solid var(--line); flex-direction: row; overflow-x: auto; }
}
`;

document.head.insertAdjacentHTML('beforeend', `<style>${ADMIN_STYLE}

/* User picker (typeahead dropdown) — Attach existing user in AssignAdminModal */
.kf-userpick { position: relative; }
.kf-userpick-trigger {
  display: flex; align-items: center; gap: 8px;
  height: 38px; padding: 0 12px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
.kf-userpick-trigger:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.kf-userpick-input { flex: 1; background: transparent; border: none; outline: none; color: var(--t-1); font-family: inherit; font-size: 13px; min-width: 0; }
.kf-userpick-input::placeholder { color: var(--t-4); }
.kf-userpick-clear {
  background: transparent; border: none; cursor: pointer;
  display: flex; align-items: center; color: var(--t-3); padding: 2px; border-radius: 4px;
}
.kf-userpick-clear:hover { background: var(--bg-3); color: var(--t-1); }
.kf-userpick-menu {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0;
  background: var(--bg-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-3);
  box-shadow: 0 12px 32px -8px rgba(0,0,0,.4);
  max-height: 260px; overflow-y: auto;
  padding: 4px;
  z-index: 50;
}
.kf-userpick-empty { padding: 14px; text-align: center; font-size: 12px; color: var(--t-3); }
.kf-userpick-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 10px;
  background: transparent; border: none;
  border-radius: var(--r-2);
  cursor: pointer; text-align: left;
  font-family: inherit;
  transition: background .1s var(--ease);
}
.kf-userpick-item:hover { background: var(--bg-3); }
.kf-userpick-text { flex: 1; min-width: 0; }
.kf-userpick-name { font-size: 13px; font-weight: 600; color: var(--t-1); }
.kf-userpick-meta { font-size: 11px; color: var(--t-3); margin-top: 2px; }
.kf-userpick-tags { display: flex; align-items: center; gap: 6px; flex-shrink: 0; font-size: 11px; }
</style>`);

/* ===================================================================
   WORKSPACE SETTINGS
   Company / org-level configuration for the ACTIVE workspace —
   billing, plan, branding, security, defaults. Distinct from
   "Companies" (the cross-tenant browser, which lives under System).
   =================================================================== */
const WORKSPACE = {
  name:        'Ikran Aerospace',
  legalName:   'Ikran Aerospace Ltd.',
  domain:      'ikran.aero',
  vat:         'GB 482 3917 11',
  address:     'Bay 6, Filton Aerodrome, Bristol BS34 7QW, UK',
  plan:        'Enterprise',
  seats:       { used: 14, total: 25 },
  storage:     { used: 4.2, total: 25 },     // GB
  renews:      '2027-01-04',
  billingEmail:'billing@ikran.aero',
  sso:         'Okta · auto-provisioned',
  defaultRole: 'Designer',
};

/* ----- Billing summary card -----
   Deliberately minimal: a single read-only summary card with the plan,
   next charge and payment method, plus a primary "Manage billing"
   button that hands off to the billing portal on the website. Tier
   comparison, invoice archive and dunning all live there. */
const BillingPlanCard = () => {
  const toast = useToast();
  const tier = 'Enterprise';
  const price = 320;
  const cycle = 'monthly';
  const nextDate = 'Jun 1, 2026';
  return (
    <div className="card kf-bill-card">
      <div className="kf-bill-row">
        <div>
          <div className="kf-bill-eyebrow">Current plan</div>
          <div className="kf-bill-tier-row">
            <h3 className="kf-bill-tier">{tier}</h3>
            <Chip size="sm" tone="success" dot>Active</Chip>
          </div>
        </div>
        <div className="kf-bill-price-block">
          <span className="kf-bill-price-currency">$</span>
          <span className="kf-bill-price-amount num">{price}</span>
          <span className="kf-bill-price-cycle">/ {cycle === 'monthly' ? 'mo' : 'yr'}</span>
        </div>
      </div>

      <div className="kf-bill-meta">
        <div className="kf-bill-meta-row">
          <span>Next charge</span>
          <span><b className="num">${price}.00</b> · <span className="num">{nextDate}</span></span>
        </div>
        <div className="kf-bill-meta-row">
          <span>Payment method</span>
          <span><span className="kf-bill-card-badge">VISA</span> ending <span className="num">4242</span></span>
        </div>
        <div className="kf-bill-meta-row">
          <span>Billing email</span>
          <span className="num">billing@ikran.aero</span>
        </div>
      </div>

      <div className="kf-bill-foot">
        <span className="kf-bill-foot-hint">
          Plans, invoices and payment methods are managed on the billing portal.
        </span>
        <Btn kind="primary" icon="share"
             onClick={() => toast.ok('Opening billing portal', 'kabelflux.com/billing')}>
          Manage billing
        </Btn>
      </div>
    </div>
  );
};

const WorkspaceSettingsPanel = ({ onClose, me }) => {
  const toast = useToast();
  const [section, setSection] = useState('overview');
  const [company, setCompany] = useState(null);   // raw row from /api/companies
  const [edits, setEdits] = useState({});         // pending field edits
  const [saving, setSaving] = useState(false);

  // Load the current company on mount. /api/companies returns one row for
  // admin (current company) or all rows for superadmin.
  useEffect(() => {
    (async () => {
      try {
        const list = await kfxFetch('/companies');
        const myCid = me && me.company_id;
        const row = Array.isArray(list)
          ? (list.find(c => c && c.id === myCid) || list[0])
          : null;
        if (row) {
          setCompany(row);
          setEdits({
            name: row.name || '',
            email_domain: row.email_domain || '',
            address: row.address || '',
            phone: row.phone || '',
            website: row.website || '',
          });
        }
      } catch (e) {
        toast.err('Could not load workspace', (e && e.message) || 'Unknown');
      }
    })();
  }, [me, toast]);

  const saveCompany = async () => {
    if (!company) return;
    setSaving(true);
    try {
      await kfxFetch('/companies/' + company.id, {
        method: 'PUT',
        body: { ...company, ...edits },
      });
      toast.ok('Workspace saved');
      setCompany({ ...company, ...edits });
    } catch (e) {
      toast.err('Save failed', (e && e.message) || 'Unknown');
    } finally {
      setSaving(false);
    }
  };

  const sections = [
    { k:'overview',  l:'Overview',           icon:'folder'    },
    { k:'billing',   l:'Billing & plan',     icon:'bom'       },
    { k:'branding',  l:'Branding',           icon:'eye'       },
    { k:'security',  l:'Security & SSO',     icon:'check'     },
    { k:'defaults',  l:'Workspace defaults', icon:'settings'  },
  ];

  const NOT_YET = 'Backend endpoint not yet implemented (Behemoth Step 6).';

  return (
    <AdminSlideover title="Workspace settings"
                    subtitle={company ? `Settings for ${company.name} · ${company.email_domain || ''}` : 'Loading…'}
                    onClose={onClose}>
      <div className="kf-ws-body">
        <nav className="kf-ws-nav" aria-label="Workspace settings sections">
          {sections.map(s => (
            <button key={s.k} className={`kf-settings-nav-item ${section === s.k ? 'on' : ''}`} onClick={() => setSection(s.k)}>
              <Icon name={s.icon} size={14}/> {s.l}
            </button>
          ))}
        </nav>
        <div className="kf-ws-panel">
          {section === 'overview' && (
            <>
              <div className="card">
                <div className="card-head">
                  <h3>Company details</h3>
                  <Btn kind="primary" size="sm" icon="check" disabled={!company || saving} busy={saving}
                       onClick={saveCompany}>Save</Btn>
                </div>
                <div className="card-body kf-form">
                  <div className="kf-form-row">
                    <div className="kf-field">
                      <label htmlFor="w-name">Display name</label>
                      <input id="w-name" className="kf-input"
                             value={edits.name || ''}
                             onChange={e => setEdits(s => ({ ...s, name: e.target.value }))}/>
                    </div>
                    <div className="kf-field">
                      <label htmlFor="w-domain">Primary domain</label>
                      <input id="w-domain" className="kf-input num"
                             value={edits.email_domain || ''}
                             onChange={e => setEdits(s => ({ ...s, email_domain: e.target.value }))}/>
                    </div>
                  </div>
                  <div className="kf-form-row">
                    <div className="kf-field">
                      <label htmlFor="w-website">Website</label>
                      <input id="w-website" className="kf-input num"
                             value={edits.website || ''}
                             onChange={e => setEdits(s => ({ ...s, website: e.target.value }))}/>
                    </div>
                    <div className="kf-field">
                      <label htmlFor="w-phone">Phone</label>
                      <input id="w-phone" className="kf-input num"
                             value={edits.phone || ''}
                             onChange={e => setEdits(s => ({ ...s, phone: e.target.value }))}/>
                    </div>
                  </div>
                  <div className="kf-form-row">
                    <div className="kf-field">
                      <label htmlFor="w-addr">Registered address</label>
                      <textarea id="w-addr" className="kf-input" rows="2"
                                value={edits.address || ''}
                                onChange={e => setEdits(s => ({ ...s, address: e.target.value }))}/>
                    </div>
                  </div>
                </div>
              </div>

              {/* Workspace usage — bigger, more legible cards with
                  inline progress bars so seat and storage usage are
                  immediately scannable. */}
              <div className="kf-ws-usage">
                {[
                  { l:'Seats used',      n:`${WORKSPACE.seats.used}`, of:`of ${WORKSPACE.seats.total}`,
                    icon:'user',  pct: WORKSPACE.seats.used / WORKSPACE.seats.total * 100,
                    note: `${WORKSPACE.seats.total - WORKSPACE.seats.used} seats available`, tone:'info' },
                  { l:'Storage',         n:`${WORKSPACE.storage.used}`, unit:'GB', of:`of ${WORKSPACE.storage.total} GB`,
                    icon:'backup', pct: WORKSPACE.storage.used / WORKSPACE.storage.total * 100,
                    note:'Auto-cleanup at 90%', tone:'success' },
                  { l:'Active projects', n:'47',  of:'across 9 programs',
                    icon:'folder', delta:'+3', deltaTone:'success', note:'this month', tone:'violet' },
                  { l:'Until renewal',   n:'8',   unit:'mo', of:`on ${WORKSPACE.renews}`,
                    icon:'history', note:'auto-renews', tone:'warning' },
                ].map(s => (
                  <div key={s.l} className="kf-ws-stat-card">
                    <div className="kf-ws-stat-top">
                      <span className={`kf-ws-stat-icon kf-ws-stat-icon-${s.tone}`}><Icon name={s.icon} size={14}/></span>
                      <span className="kf-ws-stat-label">{s.l}</span>
                      {s.delta && (
                        <span className={`kf-ws-stat-delta kf-ws-stat-delta-${s.deltaTone}`}>{s.delta}</span>
                      )}
                    </div>
                    <div className="kf-ws-stat-num">
                      <span className="num">{s.n}</span>
                      {s.unit && <span className="kf-ws-stat-unit">{s.unit}</span>}
                    </div>
                    <div className="kf-ws-stat-of">{s.of}</div>
                    {s.pct !== undefined && (
                      <div className="kf-ws-stat-bar">
                        <div className={`kf-ws-stat-bar-fill kf-ws-stat-bar-fill-${s.tone}`} style={{ width: `${Math.min(100, s.pct)}%` }}/>
                      </div>
                    )}
                    {!s.pct && <div className="kf-ws-stat-note">{s.note}</div>}
                  </div>
                ))}
              </div>
            </>
          )}

          {section === 'billing' && (
            <>
              <BillingPlanCard/>
              <div className="kf-bill-tip">
                <Icon name="info" size={14} stroke="var(--t-3)"/>
                <span>
                  Need an invoice receipt, tax forms or to update VAT / payment method?
                  Use the <a href="#" onClick={e => { e.preventDefault(); toast.ok('Opening billing portal', 'kabelflux.com/billing'); }}>billing portal</a>.
                </span>
              </div>
            </>
          )}

          {section === 'invoices' && (
            <div className="card">
              <div className="card-head">
                <h3>Invoices</h3>
                <span className="kf-card-sub">All invoices · last 90 days. Older receipts on request.</span>
                <Btn size="sm" kind="ghost" icon="download">Export all</Btn>
              </div>
              <div className="card-body" style={{ padding: 0 }}>
                <div className="kf-inv-list">
                  {[
                    { n:'INV-2026-005', period:'May 2026',    a:'$320.00',   s:'due',  due:'May 31' },
                    { n:'INV-2026-004', period:'Apr 2026',    a:'$320.00',   s:'paid', paidOn:'May 1' },
                    { n:'INV-2026-003', period:'Mar 2026',    a:'$320.00',   s:'paid', paidOn:'Apr 1' },
                    { n:'INV-2026-002', period:'Feb 2026',    a:'$320.00',   s:'paid', paidOn:'Mar 1' },
                    { n:'INV-2026-001', period:'Jan 2026',    a:'$320.00',   s:'paid', paidOn:'Feb 2' },
                    { n:'INV-2025-A',   period:'Annual 2025', a:'$3,400.00', s:'paid', paidOn:'Jan 4' },
                  ].map(i => (
                    <div key={i.n} className="kf-inv-row">
                      <div className="kf-inv-main">
                        <div className="kf-inv-id num">{i.n}</div>
                        <div className="kf-inv-period">{i.period}</div>
                      </div>
                      <div className="kf-inv-amount num">{i.a}</div>
                      <div className="kf-inv-status">
                        {i.s === 'paid'
                          ? <Chip size="sm" tone="success" dot>Paid · {i.paidOn}</Chip>
                          : <Chip size="sm" tone="warning" dot>Due {i.due}</Chip>}
                      </div>
                      <div className="kf-inv-actions">
                        {i.s === 'due' && (
                          <Btn size="sm" kind="primary"
                               onClick={() => toast.ok('Opening payment portal', 'kabelflux.com/billing')}>
                            Pay
                          </Btn>
                        )}
                        <IconBtn icon="download" label={`Download ${i.n}`}
                                 onClick={() => toast.ok('Downloading invoice', i.n + '.pdf')}/>
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          )}

          {section === 'branding' && (
            <div className="card">
              <div className="card-head"><h3>Workspace branding</h3><span className="kf-card-sub">Used in the topbar, login screen and PDF exports.</span></div>
              <div className="card-body kf-form">
                <div className="kf-form-row">
                  <div className="kf-field">
                    <label>Workspace logo</label>
                    <div className="kf-ws-logo-drop">
                      <Icon name="image" size={20} stroke="var(--t-3)"/>
                      <div>
                        <div style={{ fontWeight: 600, color:'var(--t-1)' }}>Drop a PNG or SVG here</div>
                        <div className="kf-admin-muted">Recommended 256×256 · transparent background</div>
                      </div>
                      <Btn kind="outline" size="sm">Browse files</Btn>
                    </div>
                  </div>
                </div>
                <div className="kf-form-row">
                  <div className="kf-field">
                    <label htmlFor="w-accent">Brand accent</label>
                    <input id="w-accent" type="color" className="kf-input" defaultValue="#d63838" style={{ height: 38, padding: 4 }}/>
                  </div>
                  <div className="kf-field">
                    <label htmlFor="w-subdomain">Workspace subdomain</label>
                    <input id="w-subdomain" className="kf-input num" defaultValue="ikran.flux.kabel.io"/>
                    <div className="kf-field-hint">Members sign in at this URL.</div>
                  </div>
                </div>
              </div>
            </div>
          )}

          {section === 'security' && (
            <>
              <div className="card">
                <div className="card-head"><h3>Single sign-on</h3><Chip size="sm" tone="success" dot>Connected</Chip></div>
                <div className="card-body kf-form">
                  <div className="kf-form-row">
                    <div className="kf-field"><label>Provider</label><input className="kf-input" defaultValue={WORKSPACE.sso} readOnly/></div>
                    <div className="kf-field"><label>Domain</label><input className="kf-input num" defaultValue={`@${WORKSPACE.domain}`} readOnly/></div>
                  </div>
                  <div className="kf-checkfield"><input id="w-sso-only" type="checkbox" defaultChecked/><label htmlFor="w-sso-only">Require SSO for all members</label></div>
                  <div className="kf-checkfield"><input id="w-sso-provision" type="checkbox" defaultChecked/><label htmlFor="w-sso-provision">Auto-provision new members from SSO directory</label></div>
                </div>
              </div>
              <div className="card">
                <div className="card-head"><h3>Access policy</h3></div>
                <div className="card-body kf-form">
                  <div className="kf-checkfield"><input id="w-mfa" type="checkbox" defaultChecked/><label htmlFor="w-mfa">Enforce MFA for Admin role</label></div>
                  <div className="kf-checkfield"><input id="w-ip" type="checkbox"/><label htmlFor="w-ip">Restrict access by IP range (corporate VPN only)</label></div>
                  <div className="kf-checkfield"><input id="w-session" type="checkbox" defaultChecked/><label htmlFor="w-session">Sign out idle sessions after 8 hours</label></div>
                  <div className="kf-checkfield"><input id="w-export" type="checkbox" defaultChecked/><label htmlFor="w-export">Require approval before exporting more than 100 wires</label></div>
                </div>
              </div>
            </>
          )}

          {section === 'defaults' && (
            <div className="card">
              <div className="card-head"><h3>Workspace defaults for new projects</h3><span className="kf-card-sub">Applied to every new harness — projects can override locally.</span></div>
              <div className="card-body kf-form">
                <div className="kf-form-row">
                  <div className="kf-field">
                    <label htmlFor="w-default-units">Default units</label>
                    <select id="w-default-units" className="kf-input" defaultValue="mm">
                      <option value="mm">Millimetres (mm)</option><option value="in">Inches (in)</option>
                    </select>
                  </div>
                  <div className="kf-field">
                    <label htmlFor="w-default-role">Default member role</label>
                    <select id="w-default-role" className="kf-input" defaultValue={WORKSPACE.defaultRole}>
                      <option>Admin</option><option>Designer</option><option>Reviewer</option><option>Viewer</option>
                    </select>
                  </div>
                </div>
                <div className="kf-form-row">
                  <div className="kf-field">
                    <label htmlFor="w-default-spec">Default wire spec</label>
                    <select id="w-default-spec" className="kf-input" defaultValue="m22759">
                      <option value="m22759">MIL-DTL-22759</option>
                      <option value="m81044">MIL-DTL-81044</option>
                      <option value="iso6722">ISO 6722</option>
                    </select>
                  </div>
                  <div className="kf-field">
                    <label htmlFor="w-default-cur">Default currency</label>
                    <select id="w-default-cur" className="kf-input" defaultValue="USD">
                      <option>USD</option><option>EUR</option><option>GBP</option><option>JPY</option>
                    </select>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>
      </div>
    </AdminSlideover>
  );
};

Object.assign(window, { AuditLogPanel, UsersPanel, CompaniesPanel, ShareLinksPanel, SystemHealthPanel, WorkspaceSettingsPanel });
