// SETTINGS PLATFORM — Firm · Security · Roles · Users · Teams
const Ts_f = window.ArbiterTokens;

function SettingsFirm({ data }) {
  const stg = window.__stg;
  const f = data.firm;
  const Card = window.SettingsSectionCard;
  const Row = window.SettingsRow;

  return (
    <div>
      <div style={stg.stripKpi}>
        <div style={stg.stat}><span style={stg.statLabel}>Legal name</span><span style={{ ...stg.statValue, fontSize: '14px', marginTop: '4px' }}>{f.legalName}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Founded</span><span style={stg.statValue}>{f.founded}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Headcount</span><span style={stg.statValue}>{f.headcount}</span><span style={stg.statDelta}>{f.lawyers} lawyers</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Offices</span><span style={stg.statValue}>{f.offices.length}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Fiscal year</span><span style={stg.statValue}>{f.fiscalYearStart}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Practice areas</span><span style={stg.statValue}>{f.practiceAreas.length}</span></div>
      </div>

      <Card title="Firm identity">
        <Row label="Legal name"    hint="As registered with the Secretary of State"><input defaultValue={f.legalName} style={{ ...stg.input, width: '340px' }} /></Row>
        <Row label="Trading name"  hint="Displayed across the product and invoicing"><input defaultValue={f.tradingName} style={{ ...stg.input, width: '260px' }} /></Row>
        <Row label="EIN"           hint="Used on invoices and tax documents"><input defaultValue={f.ein} style={{ ...stg.inputMono, width: '180px' }} /></Row>
        <Row label="Fiscal year start"><input defaultValue={f.fiscalYearStart} style={{ ...stg.inputMono, width: '100px' }} /></Row>
        <Row label="Billing currency">
          <select defaultValue={f.billingCurrency} style={{ ...stg.select, width: '120px' }}>{['USD','GBP','EUR','SGD','JPY','CAD'].map(c => <option key={c}>{c}</option>)}</select>
        </Row>
      </Card>

      <Card title={`Offices · ${f.offices.length}`} action={<button style={stg.btnSecondary}>+ Office</button>}>
        <div style={stg.tableWrap}>
        <table style={stg.tableFixed}>
          <thead>
            <tr>
              <th style={stg.th}>Office</th>
              <th style={stg.th}>Country</th>
              <th style={stg.th}>Address</th>
              <th style={{ ...stg.th, textAlign: 'right' }}>Seats</th>
              <th style={stg.th}></th>
            </tr>
          </thead>
          <tbody>
            {f.offices.map(o => (
              <tr key={o.id}>
                <td style={{ ...stg.td, fontWeight: 600 }}>{o.city} {o.primary && <span style={{ ...stg.tag, ...stg.statusPill('info'), marginLeft: '6px' }}>HQ</span>}</td>
                <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.secondary, fontFamily: Ts_f.font.mono }}>{o.country}</td>
                <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.secondary }}>{o.address}</td>
                <td style={{ ...stg.td, fontFamily: Ts_f.font.mono, textAlign: 'right', fontWeight: 700 }}>{o.seats}</td>
                <td style={{ ...stg.td, textAlign: 'right' }}><button style={stg.btnGhost}>Edit</button></td>
              </tr>
            ))}
          </tbody>
        </table>
        </div>
      </Card>

      <Card title="Practice areas">
        <div style={{ padding: '14px 16px', display: 'flex', flexWrap: 'wrap', gap: '6px' }}>
          {f.practiceAreas.map(pa => (
            <span key={pa} style={{ ...stg.pill, background: stg.steelBg, color: stg.steelDeep, border: `1px solid ${stg.steelBorder}` }}>{pa} <span style={{ marginLeft: '6px', color: Ts_f.color.text.tertiary, cursor: 'pointer' }}>×</span></span>
          ))}
          <button style={{ ...stg.btnSecondary, padding: '4px 12px' }}>+ Add</button>
        </div>
      </Card>

      <Card title="Branding">
        <div style={stg.cardGrid(240)}>
          {[
            { label: 'Primary logo',  file: f.branding.logoPrimary, note: 'SVG preferred · 4:1 horizontal' },
            { label: 'Mark',          file: f.branding.logoMark,    note: 'Square · 1:1 app icon' },
            { label: 'Favicon',       file: f.branding.favicon,     note: '32×32 · 16×16' },
            { label: 'Letterhead',    file: f.branding.letterhead,  note: 'PDF · A4 + US Letter' },
            { label: 'Email banner',  file: f.branding.emailBanner, note: '1200×320 · PNG/JPG' },
          ].map(b => (
            <div key={b.label} style={{
              margin: '8px', padding: '16px', border: `1px solid ${Ts_f.color.border.light}`,
              borderRadius: '8px', background: Ts_f.color.bg.secondary,
            }}>
              <div style={{ fontSize: '11px', fontWeight: 700, color: Ts_f.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '6px' }}>{b.label}</div>
              <div style={{
                height: '80px', borderRadius: '6px', background: Ts_f.color.bg.card, border: `1px dashed ${Ts_f.color.border.medium}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center', color: Ts_f.color.text.tertiary, fontSize: '10px', fontFamily: Ts_f.font.mono, marginBottom: '8px',
              }}>{b.file.split('/').pop()}</div>
              <div style={{ fontSize: '10px', color: Ts_f.color.text.tertiary, marginBottom: '8px' }}>{b.note}</div>
              <div style={{ display: 'flex', gap: '4px' }}>
                <button style={stg.btnSecondary}>Replace</button>
                <button style={stg.btnGhost}>Download</button>
              </div>
            </div>
          ))}
        </div>
        <div style={{ padding: '14px 16px', display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: '10px' }}>
          <div style={stg.field}>
            <span style={stg.fieldLabel}>Accent color</span>
            <input type="color" defaultValue={f.branding.accentColor} style={{ ...stg.input, padding: '2px', height: '32px' }} />
          </div>
          <div style={stg.field}>
            <span style={stg.fieldLabel}>Invoice theme</span>
            <select defaultValue={f.branding.invoiceTheme} style={stg.select}>{['navy-classic','mono','modern','ivory'].map(t => <option key={t}>{t}</option>)}</select>
          </div>
        </div>
      </Card>
    </div>
  );
}

function SettingsSecurity({ data }) {
  const stg = window.__stg;
  const s = data.security;
  const Card = window.SettingsSectionCard;
  const infra = window.__stg_infra;
  const { useToast, InfoTip, DangerZone, TypedConfirmDialog, AuditDrawer, sampleHistory } = infra;
  const toast = useToast();
  const { useState } = React;
  const [ssoWizard, setSsoWizard] = useState(false);
  const [pwDetail, setPwDetail] = useState(false);
  const [confirm, setConfirm] = useState(null);
  const [audit, setAudit] = useState(null);

  // Policy tooltips (key→explanation)
  const policyTips = {
    'mfa.required':              { text: 'Require every user to enroll multi-factor authentication before accessing the firm.', recommended: true },
    'mfa.methods':                { text: 'Which MFA factors are accepted. WebAuthn/passkeys are strongest; SMS is weakest (SIM-swap risk).', recommended: true },
    'session.duration':           { text: 'How long a login session stays valid before the user must re-authenticate.', recommended: true },
    'session.idle':               { text: 'Idle time after which the session is invalidated. Shorter is safer; 15m is standard for legal.', recommended: true },
    'password.complexity':        { text: 'Minimum character mix. Length > complexity per NIST 800-63B.', recommended: false },
    'password.rotation':          { text: 'Force password change on schedule. NIST now advises against rotation unless breach suspected.', recommended: false },
    'device.trust':               { text: 'Only allow logins from devices that pass attestation (managed laptops, compliant mobile).', recommended: true },
    'ip.allowlist.enforced':      { text: 'Reject all logins outside the CIDR ranges listed below. Use with caution — break-glass account required.', recommended: false },
    'audit.retention':            { text: 'How long audit logs are kept. Regulators generally require 7 years for legal work.', recommended: true },
    'sso.enforced':               { text: 'All logins must go through your IdP. Disables local password login entirely.', recommended: true },
    'sso.jit':                    { text: 'Auto-provision users on first SSO login. Assign default role below.', recommended: false },
    'data.residency':             { text: 'Pin tenant data to a specific Azure region. Required for EU (GDPR) and certain contracts.', recommended: false },
  };

  return (
    <div>
      <div style={stg.stripKpi}>
        <div style={stg.stat}><span style={stg.statLabel}>Security score</span><span style={{ ...stg.statValue, color: stg.emerald }}>{s.summary.score}</span><span style={stg.statDelta}>Overall grade</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>MFA coverage</span><span style={stg.statValue}>{s.summary.mfaCoverage}%</span><span style={stg.statDelta}>Target 100%</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Risky events 7d</span><span style={{ ...stg.statValue, color: stg.amber }}>{s.riskyEvents.length}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Key rotation</span><span style={stg.statValue}>{s.summary.keyRotationDueDays}d</span><span style={stg.statDelta}>Until next</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Policies</span><span style={stg.statValue}>{s.policies.length}</span><span style={stg.statDelta}>All enforced</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>IP allowlists</span><span style={stg.statValue}>{s.ipAllowlist.length}</span></div>
      </div>

      {/* SSO setup + password policy quick actions */}
      <div style={stg.split(440)} data-anchor="sso">
        <Card title={<span>Single Sign-On (SSO) <InfoTip text="Replace local password login with your identity provider (Azure AD, Okta, Google Workspace, ADFS). Supports SAML 2.0 and OIDC." recommended /></span>}
          action={<button style={stg.btnPrimary} onClick={() => setSsoWizard(true)}>Launch setup wizard</button>}>
          <div style={{ padding: '12px 16px' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '10px' }}>
              <div><div style={stg.sectionLabel}>Provider</div><div style={{ fontSize: '13px', fontWeight: 700 }}>Azure AD (SAML 2.0)</div></div>
              <div><div style={stg.sectionLabel}>Status</div><span style={{ ...stg.tag, ...stg.statusPill('ok') }}>● Connected</span></div>
              <div><div style={stg.sectionLabel}>Entity ID</div><div style={{ fontSize: '10px', fontFamily: Ts_f.font.mono, color: Ts_f.color.text.tertiary, wordBreak: 'break-all' }}>urn:arbiter:prod:sp</div></div>
              <div><div style={stg.sectionLabel}>JIT provisioning</div><span style={{ ...stg.tag, ...stg.statusPill('info') }}>Enabled · default role: Associate</span></div>
            </div>
            <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
              <button style={stg.btnSecondary} onClick={() => toast.push({ kind: 'success', title: 'IdP-initiated test succeeded', message: 'Received valid SAML assertion in 340ms' })}>Test login</button>
              <button style={stg.btnSecondary} onClick={() => toast.push({ kind: 'info', title: 'Metadata XML downloaded' })}>Download SP metadata</button>
              <button style={stg.btnSecondary}>Upload IdP metadata</button>
            </div>
          </div>
        </Card>

        <Card title={<span data-anchor="password">Password policy <InfoTip text="Detailed rules applied to any local (non-SSO) password. When SSO is enforced these only apply to break-glass accounts." /></span>}
          action={<button style={stg.btnSecondary} onClick={() => setPwDetail(v => !v)}>{pwDetail ? 'Collapse' : 'Expand detail'}</button>}>
          <div style={{ padding: '12px 16px' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', fontSize: '12px' }}>
              <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>Min length</span><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>14 chars</div></div>
              <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>History</span><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>Last 10 blocked</div></div>
              <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>Rotation</span><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>On compromise only</div></div>
              <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>Breach check</span><div style={{ fontWeight: 700, color: stg.emerald }}>● HIBP enabled</div></div>
              {pwDetail && <>
                <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>Complexity</span><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>3 of 4 classes</div></div>
                <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>Max age</span><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>—</div></div>
                <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>Lockout</span><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>10 fails / 15m</div></div>
                <div><span style={{ color: Ts_f.color.text.tertiary, fontSize: '11px' }}>Grace period</span><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>48h on force-change</div></div>
              </>}
            </div>
          </div>
        </Card>
      </div>

      <Card title={`Security policies · ${s.policies.length}`} action={<button style={stg.btnSecondary} onClick={() => setAudit({ label: 'Security policies', history: sampleHistory('policies') })}>View history</button>}>
        <div style={stg.tableWrap}>
        <table style={stg.tableFixed}>
          <thead>
            <tr>
              <th style={stg.th}>Policy</th>
              <th style={stg.th}>Value</th>
              <th style={stg.th}>Status</th>
              <th style={stg.th}></th>
            </tr>
          </thead>
          <tbody>
            {s.policies.map(p => {
              const tip = policyTips[p.id];
              return (
              <tr key={p.id}>
                <td style={{ ...stg.td, fontWeight: 600 }}>{p.label}{tip && <InfoTip text={tip.text} recommended={tip.recommended} />}</td>
                <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.secondary, fontFamily: Ts_f.font.mono }}>{p.value}</td>
                <td style={stg.td}><span style={{ ...stg.tag, ...stg.statusPill('ok') }}>{p.enforced ? 'Enforced' : 'Audit only'}</span></td>
                <td style={{ ...stg.td, textAlign: 'right' }}>
                  <button style={stg.btnGhost} onClick={() => setAudit({ label: p.label, history: sampleHistory(p.id) })}>History</button>
                  <button style={stg.btnGhost}>Edit</button>
                </td>
              </tr>
            );})}
          </tbody>
        </table>
        </div>
      </Card>

      <div style={stg.split(440)}>
        <Card title={`IP allowlist · ${s.ipAllowlist.length}`} action={<button style={stg.btnSecondary}>+ Add range</button>}>
          <div style={stg.tableWrap}>
          <table style={stg.tableFixed}>
            <thead>
              <tr>
                <th style={stg.th}>Label</th>
                <th style={stg.th}>CIDR</th>
                <th style={stg.th}>Scope</th>
              </tr>
            </thead>
            <tbody>
              {s.ipAllowlist.map(ip => (
                <tr key={ip.id}>
                  <td style={{ ...stg.td, fontWeight: 600 }}>{ip.label}</td>
                  <td style={{ ...stg.td, fontFamily: Ts_f.font.mono, color: Ts_f.color.text.secondary }}>{ip.cidr}</td>
                  <td style={stg.td}><span style={{ ...stg.tag, background: stg.steelBg, color: stg.steelDeep }}>{ip.scope}</span></td>
                </tr>
              ))}
            </tbody>
          </table>
          </div>
        </Card>

        <Card title={`Recent risky events · ${s.riskyEvents.length}`} action={<button style={stg.btnGhost}>View all</button>}>
          <div style={{ padding: '4px 0' }}>
            {s.riskyEvents.map(e => (
              <div key={e.id} style={{ padding: '12px 16px', borderBottom: `1px solid ${Ts_f.color.border.light}` }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
                  <span style={{ fontSize: '12px', fontWeight: 700, color: Ts_f.color.text.primary }}>{e.user}</span>
                  <span style={{ ...stg.tag, background: `${stg.severityColor(e.severity)}15`, color: stg.severityColor(e.severity) }}>{e.severity}</span>
                </div>
                <div style={{ fontSize: '12px', color: Ts_f.color.text.secondary }}>{e.event}</div>
                <div style={{ fontSize: '10px', color: Ts_f.color.text.tertiary, fontFamily: Ts_f.font.mono, marginTop: '2px' }}>{e.when}</div>
              </div>
            ))}
          </div>
        </Card>
      </div>

      <Card title="Encryption">
        <div style={{ padding: '14px 16px', display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: '14px' }}>
          <div>
            <div style={stg.sectionLabel}>At rest</div>
            <div style={{ fontSize: '12px', color: Ts_f.color.text.primary, lineHeight: 1.6 }}>{s.encryption.atRest}</div>
          </div>
          <div>
            <div style={stg.sectionLabel}>In transit</div>
            <div style={{ fontSize: '12px', color: Ts_f.color.text.primary, lineHeight: 1.6 }}>{s.encryption.inTransit}</div>
          </div>
          <div>
            <div style={stg.sectionLabel}>Key rotation</div>
            <div style={{ fontSize: '12px', color: Ts_f.color.text.primary, lineHeight: 1.6 }}>{s.encryption.keyRotation}</div>
            <div style={{ fontSize: '11px', color: Ts_f.color.text.tertiary, marginTop: '2px' }}>Last rotation {s.encryption.lastRotation}</div>
          </div>
        </div>
      </Card>

      {/* Danger zone — #24 */}
      <DangerZone title="Danger zone">
        <div style={stg.rowItem}>
          <div>
            <div style={stg.rowLabel}>Revoke all active sessions</div>
            <div style={stg.rowHint}>Forces every logged-in user to re-authenticate immediately. Use if you suspect a token leak. Impacts {data.users?.length || 0} users.</div>
          </div>
          <button style={{ ...stg.btnDanger, fontWeight: 700 }} onClick={() => setConfirm({ kind: 'revokeAll' })}>Revoke all sessions</button>
        </div>
        <div style={stg.rowItem}>
          <div>
            <div style={stg.rowLabel}>Disable SSO (fall back to local login)</div>
            <div style={stg.rowHint}>Users will be forced to set or reset local passwords. Break-glass accounts must be ready.</div>
          </div>
          <button style={stg.btnDanger} onClick={() => setConfirm({ kind: 'disableSso' })}>Disable SSO</button>
        </div>
        <div style={stg.rowItem}>
          <div>
            <div style={stg.rowLabel}>Rotate master encryption key</div>
            <div style={stg.rowHint}>Re-encrypts all data with a new CMK. Takes ~2 hours. Read-only mode during rotation.</div>
          </div>
          <button style={stg.btnDanger} onClick={() => setConfirm({ kind: 'rotateKey' })}>Rotate CMK</button>
        </div>
      </DangerZone>

      <TypedConfirmDialog
        open={confirm?.kind === 'revokeAll'}
        title="Revoke all active sessions?"
        message="Every user will be logged out and must sign in again. This does not revoke API keys or webhooks — use the API tab for those. There is no undo."
        requireText="REVOKE ALL"
        onCancel={() => setConfirm(null)}
        onConfirm={() => { toast.push({ kind: 'warn', title: 'All sessions revoked', message: '134 users signed out' }); setConfirm(null); }}
      />
      <TypedConfirmDialog
        open={confirm?.kind === 'disableSso'}
        title="Disable Single Sign-On?"
        message="Users will no longer be able to log in through your identity provider. Make sure break-glass local accounts have working passwords before confirming."
        requireText="DISABLE SSO"
        onCancel={() => setConfirm(null)}
        onConfirm={() => { toast.push({ kind: 'error', title: 'SSO disabled' }); setConfirm(null); }}
      />
      <TypedConfirmDialog
        open={confirm?.kind === 'rotateKey'}
        title="Rotate master encryption key?"
        message="Tenant will enter read-only mode for approximately 2 hours while all data is re-encrypted with the new key. Schedule this during a maintenance window."
        requireText="ROTATE"
        destructive={false}
        onCancel={() => setConfirm(null)}
        onConfirm={() => { toast.push({ kind: 'info', title: 'CMK rotation queued', message: 'Will start at 02:00 UTC tonight' }); setConfirm(null); }}
      />

      {/* SSO wizard modal */}
      {ssoWizard && <SsoWizard onClose={() => setSsoWizard(false)} toast={toast} stg={stg} Ts_f={Ts_f} />}

      <AuditDrawer open={!!audit} entry={audit} history={audit?.history || []} onClose={() => setAudit(null)} />
    </div>
  );
}

// SSO setup wizard — 4 steps
function SsoWizard({ onClose, toast, stg, Ts_f }) {
  const { useState } = React;
  const [step, setStep] = useState(0);
  const steps = ['Provider', 'Metadata', 'Attribute mapping', 'Test & enable'];
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 9994, background: 'rgba(15,23,42,0.45)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px' }} onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{ background: '#fff', borderRadius: '10px', maxWidth: '640px', width: '100%', boxShadow: '0 16px 48px rgba(0,0,0,0.25)' }}>
        <div style={{ padding: '14px 20px', borderBottom: `1px solid ${Ts_f.color.border.light}`, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div style={{ fontSize: '14px', fontWeight: 700 }}>SSO setup · step {step + 1} of {steps.length}</div>
          <button onClick={onClose} style={{ background: 'none', border: 'none', fontSize: '18px', cursor: 'pointer' }}>×</button>
        </div>
        <div style={{ display: 'flex', padding: '14px 20px', gap: '8px', borderBottom: `1px solid ${Ts_f.color.border.light}` }}>
          {steps.map((s, i) => (
            <div key={s} style={{ flex: 1, height: '4px', borderRadius: '2px', background: i <= step ? '#334155' : Ts_f.color.border.light }} />
          ))}
        </div>
        <div style={{ padding: '20px', minHeight: '220px' }}>
          {step === 0 && <div>
            <div style={stg.fieldLabel}>Choose your identity provider</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))', gap: '10px', marginTop: '10px' }}>
              {['Azure AD', 'Okta', 'Google Workspace', 'ADFS', 'OneLogin', 'Custom SAML'].map(p => (
                <button key={p} style={{ padding: '16px 10px', borderRadius: '8px', border: `2px solid ${Ts_f.color.border.light}`, background: '#fff', fontWeight: 600, fontSize: '12px', cursor: 'pointer' }}>{p}</button>
              ))}
            </div>
          </div>}
          {step === 1 && <div>
            <div style={stg.fieldLabel}>Upload IdP metadata XML or paste URL</div>
            <input placeholder="https://login.microsoftonline.com/tenant/federationmetadata.xml" style={{ ...stg.input, marginTop: '8px' }} />
            <div style={{ margin: '10px 0', fontSize: '10px', color: Ts_f.color.text.tertiary, textAlign: 'center' }}>— or —</div>
            <div style={{ padding: '30px', border: `2px dashed ${Ts_f.color.border.medium}`, borderRadius: '8px', textAlign: 'center', fontSize: '12px', color: Ts_f.color.text.tertiary }}>Drop metadata.xml here</div>
          </div>}
          {step === 2 && <div>
            <div style={stg.fieldLabel}>Map IdP claims → user attributes</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', marginTop: '10px' }}>
              {[['Email','http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'], ['First name','.../givenname'], ['Last name','.../surname'], ['Role','http://arbiter/role']].map(([k, v]) => (
                <div key={k}><div style={{ fontSize: '11px', fontWeight: 600, color: Ts_f.color.text.secondary, marginBottom: '2px' }}>{k}</div><input defaultValue={v} style={{ ...stg.input, fontFamily: Ts_f.font.mono, fontSize: '10px' }} /></div>
              ))}
            </div>
            <label style={{ display: 'flex', gap: '8px', marginTop: '14px', fontSize: '12px', color: Ts_f.color.text.secondary }}>
              <input type="checkbox" defaultChecked /> Auto-provision new users on first login (JIT)
            </label>
          </div>}
          {step === 3 && <div>
            <div style={stg.fieldLabel}>Test your configuration</div>
            <button style={{ ...stg.btnPrimary, marginTop: '10px' }} onClick={() => toast.push({ kind: 'success', title: 'IdP test successful' })}>Run IdP-initiated test</button>
            <div style={{ marginTop: '16px', padding: '12px', borderRadius: '6px', background: 'rgba(217,119,6,0.08)', border: '1px solid rgba(217,119,6,0.3)', fontSize: '11px', color: '#78350F' }}>
              ! Enabling SSO disables local password login. Ensure you have at least one break-glass admin with a working local password.
            </div>
          </div>}
        </div>
        <div style={{ padding: '12px 20px', borderTop: `1px solid ${Ts_f.color.border.light}`, display: 'flex', justifyContent: 'space-between', background: Ts_f.color.bg.secondary, borderRadius: '0 0 10px 10px' }}>
          <button onClick={() => step > 0 ? setStep(step - 1) : onClose()} style={stg.btnSecondary}>{step === 0 ? 'Cancel' : '← Back'}</button>
          {step < steps.length - 1
            ? <button onClick={() => setStep(step + 1)} style={stg.btnPrimary}>Next →</button>
            : <button onClick={() => { toast.push({ kind: 'success', title: 'SSO enabled', message: 'All new logins now require IdP authentication' }); onClose(); }} style={{ ...stg.btnPrimary, background: '#059669' }}>Enable SSO</button>}
        </div>
      </div>
    </div>
  );
}

function SettingsRoles({ data }) {
  const stg = window.__stg;
  const roles = data.roles;
  const perms = data.permissions;
  const Card = window.SettingsSectionCard;
  const infra = window.__stg_infra;
  const { useToast, ImpactPill, InfoTip, TypedConfirmDialog } = infra;
  const toast = useToast();
  const { useState, useEffect } = React;
  const [selectedRole, setSelectedRole] = useState(roles[0].id);
  const [mobile, setMobile] = useState(false);
  const [hoverCell, setHoverCell] = useState(null); // { resource, action }
  const [confirm, setConfirm] = useState(null);
  const current = roles.find(r => r.id === selectedRole);
  const matrix = perms.matrix[selectedRole] || {};
  const hasPerm = (resource, action) => {
    if (matrix._all && matrix._all.includes(action)) return true;
    return (matrix[resource] || []).includes(action);
  };

  // Detect narrow viewport for auto-mobile layout
  useEffect(() => {
    const check = () => setMobile(window.innerWidth < 900);
    check();
    window.addEventListener('resize', check);
    return () => window.removeEventListener('resize', check);
  }, []);

  return (
    <div>
      <div style={stg.stripKpi}>
        <div style={stg.stat}><span style={stg.statLabel}>Roles</span><span style={stg.statValue}>{roles.length}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Total assignments</span><span style={stg.statValue}>{roles.reduce((s, r) => s + r.users, 0)}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Resources</span><span style={stg.statValue}>{perms.resources.length}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Actions</span><span style={stg.statValue}>{perms.actions.length}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Super admins</span><span style={{ ...stg.statValue, color: stg.crimson }}>{roles[0].users}</span></div>
      </div>

      <div style={stg.split(260)}>
        <Card title={`Roles · ${roles.length}`} action={<button style={stg.btnPrimary}>+ Role</button>}>
          <div style={{ padding: '6px' }}>
            {roles.map(r => (
              <div key={r.id} onClick={() => setSelectedRole(r.id)} style={{
                display: 'grid', gridTemplateColumns: '4px 1fr auto', gap: '10px', alignItems: 'center',
                padding: '10px 12px', cursor: 'pointer',
                background: selectedRole === r.id ? stg.steelBg : 'transparent',
                borderRadius: '6px', marginBottom: '2px',
              }}>
                <div style={{ width: '4px', height: '24px', background: r.color, borderRadius: '2px' }} />
                <div>
                  <div style={{ fontSize: '12px', fontWeight: 700, color: Ts_f.color.text.primary }}>{r.name}</div>
                  <div style={{ fontSize: '10px', color: Ts_f.color.text.tertiary, marginTop: '1px' }}>{r.users} users</div>
                </div>
                <div style={{ fontSize: '10px', color: Ts_f.color.text.tertiary, fontFamily: Ts_f.font.mono }}>{r.id}</div>
              </div>
            ))}
          </div>
        </Card>

        <div style={{ gridColumn: 'span 2' }}>
          <Card title={<span>Permission matrix — {current?.name} <InfoTip text="Green ok = granted. Click a cell to toggle. Changes preview the user/team/matter impact before saving." /></span>} action={
            <div style={{ display: 'flex', gap: '6px', alignItems: 'center' }}>
              <ImpactPill users={current?.users || 0} teams={Math.ceil((current?.users || 0) / 4)} matters={Math.round((current?.users || 0) * 1.8)} />
              <button style={stg.btnSecondary}>Duplicate</button>
              <button style={stg.btnSecondary}>Export YAML</button>
              {current?.id !== 'R-001' && <button style={stg.btnDanger} onClick={() => setConfirm({ kind: 'deleteRole' })}>Delete role</button>}
            </div>
          }>
            <div style={{ padding: '14px 16px' }}>
              <div style={{ fontSize: '12px', color: Ts_f.color.text.secondary, lineHeight: 1.5, marginBottom: '10px' }}>{current?.description}</div>

              {mobile ? (
                /* Mobile stacked layout */
                <div>
                  {perms.resources.map(resource => (
                    <div key={resource} style={{ padding: '10px 0', borderBottom: `1px solid ${Ts_f.color.border.light}` }}>
                      <div style={{ fontSize: '12px', fontWeight: 700, marginBottom: '6px' }}>{resource}</div>
                      <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
                        {perms.actions.map(a => {
                          const has = hasPerm(resource, a);
                          return (
                            <span key={a} style={{
                              fontSize: '10px', padding: '3px 8px', borderRadius: '10px',
                              background: has ? stg.emeraldBg : Ts_f.color.bg.secondary,
                              color: has ? stg.emerald : Ts_f.color.text.tertiary,
                              border: `1px solid ${has ? stg.emerald : Ts_f.color.border.light}`,
                              fontWeight: 600, textTransform: 'capitalize',
                            }}>{has ? 'ok ' : '· '}{a}</span>
                          );
                        })}
                      </div>
                    </div>
                  ))}
                </div>
              ) : (
                <div style={stg.tableWrap}>
                <table style={stg.tableFixed}>
                  <thead>
                    <tr>
                      <th style={stg.th}>Resource</th>
                      {perms.actions.map(a => <th key={a} style={{ ...stg.th, textAlign: 'center', textTransform: 'capitalize' }}>{a}</th>)}
                    </tr>
                  </thead>
                  <tbody>
                    {perms.resources.map(resource => (
                      <tr key={resource}>
                        <td style={{ ...stg.td, fontWeight: 600 }}>{resource}</td>
                        {perms.actions.map(a => {
                          const has = hasPerm(resource, a);
                          const isHover = hoverCell?.resource === resource && hoverCell?.action === a;
                          return (
                            <td key={a} style={{ ...stg.td, textAlign: 'center', position: 'relative' }}>
                              <div
                                onMouseEnter={() => setHoverCell({ resource, action: a })}
                                onMouseLeave={() => setHoverCell(null)}
                                onClick={() => toast.push({ kind: 'info', title: `Would ${has ? 'revoke' : 'grant'} ${a} on ${resource}`, message: `Affects ${current?.users || 0} users · preview only` })}
                                style={{
                                  display: 'inline-flex', width: '22px', height: '22px', borderRadius: '4px',
                                  background: has ? stg.emeraldBg : Ts_f.color.bg.secondary,
                                  color: has ? stg.emerald : Ts_f.color.text.tertiary,
                                  alignItems: 'center', justifyContent: 'center',
                                  fontSize: '13px', fontWeight: 700,
                                  border: `1px solid ${has ? stg.emerald : Ts_f.color.border.light}`,
                                  cursor: 'pointer',
                                  transform: isHover ? 'scale(1.15)' : 'scale(1)', transition: 'transform 0.1s',
                                }}>{has ? 'ok' : '·'}</div>
                              {isHover && (
                                <div style={{
                                  position: 'absolute', bottom: 'calc(100% + 4px)', left: '50%', transform: 'translateX(-50%)',
                                  background: '#1E293B', color: '#fff', fontSize: '10px', padding: '4px 8px',
                                  borderRadius: '4px', whiteSpace: 'nowrap', zIndex: 10,
                                }}>Click to {has ? 'revoke' : 'grant'} · affects {current?.users || 0}</div>
                              )}
                            </td>
                          );
                        })}
                      </tr>
                    ))}
                  </tbody>
                </table>
                </div>
              )}
            </div>
          </Card>
        </div>
      </div>

      {/* Ethical walls — #9 */}
      <Card title={<span>Ethical walls (matter-level ACLs) <InfoTip text="Per-matter exclusions that override firm-wide role grants. Required to prevent conflicts of interest where an attorney must not see a particular matter even though their role would otherwise grant access." recommended /></span>}
        action={<button style={stg.btnPrimary}>+ New wall</button>}>
        <div style={stg.tableWrap}>
        <table style={stg.tableFixed}>
          <thead>
            <tr>
              <th style={stg.th}>Wall</th>
              <th style={stg.th}>Matter</th>
              <th style={stg.th}>Excluded users</th>
              <th style={stg.th}>Reason</th>
              <th style={stg.th}>Since</th>
              <th style={stg.th}></th>
            </tr>
          </thead>
          <tbody>
            {[
              { id: 'EW-001', matter: 'M-24-0089 · Acme v. Globex', users: 'Blake H., Dana L.', reason: 'Prior representation of Globex', since: '2024-08-14' },
              { id: 'EW-002', matter: 'M-25-0143 · In re: Morningstar', users: 'Rachel K.', reason: 'Spouse is adverse witness', since: '2025-02-03' },
              { id: 'EW-003', matter: 'M-25-0217 · Henderson Trust', users: 'Marcus T.', reason: 'Former employee of trustee', since: '2025-06-22' },
            ].map(w => (
              <tr key={w.id}>
                <td style={{ ...stg.td, fontWeight: 600, fontFamily: Ts_f.font.mono }}>{w.id}</td>
                <td style={stg.td}>{w.matter}</td>
                <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.secondary }}>{w.users}</td>
                <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.tertiary }}>{w.reason}</td>
                <td style={{ ...stg.td, fontSize: '11px', fontFamily: Ts_f.font.mono, color: Ts_f.color.text.tertiary }}>{w.since}</td>
                <td style={{ ...stg.td, textAlign: 'right' }}><button style={stg.btnGhost}>Edit</button><button style={stg.btnGhost}>Log</button></td>
              </tr>
            ))}
          </tbody>
        </table>
        </div>
      </Card>

      {/* Conflict check — #10 */}
      <div style={stg.split(380)}>
        <Card title={<span>Conflict-check rules <InfoTip text="Settings that govern the pre-engagement conflict check run when opening a new matter." /></span>}
          action={<button style={stg.btnSecondary}>Run conflict check</button>}>
          <div style={{ padding: '12px 16px' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', fontSize: '12px' }}>
              <div><div style={stg.sectionLabel}>Name match threshold</div><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>Jaro-Winkler ≥ 0.88</div></div>
              <div><div style={stg.sectionLabel}>Alias handling</div><div style={{ fontWeight: 700 }}>Expand via synonym DB</div></div>
              <div><div style={stg.sectionLabel}>Former-client lookback</div><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>10 years</div></div>
              <div><div style={stg.sectionLabel}>Spouse / family</div><div style={{ fontWeight: 700 }}>Cross-check enabled</div></div>
              <div><div style={stg.sectionLabel}>Opposing counsel cache</div><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>Refresh nightly</div></div>
              <div><div style={stg.sectionLabel}>Auto-clear threshold</div><div style={{ fontWeight: 700, fontFamily: Ts_f.font.mono }}>&lt; 0.4</div></div>
            </div>
          </div>
        </Card>
        <Card title="Time-zone & residency policy">
          <div style={{ padding: '12px 16px' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', fontSize: '12px' }}>
              <div><div style={stg.sectionLabel}>Default TZ</div><div style={{ fontWeight: 700 }}>Per office</div></div>
              <div><div style={stg.sectionLabel}>Data residency</div><div style={{ fontWeight: 700 }}>US-East (primary) · EU-West for GDPR matters</div></div>
              <div><div style={stg.sectionLabel}>User language</div><div style={{ fontWeight: 700 }}>Personal override</div></div>
              <div><div style={stg.sectionLabel}>Office TZ override</div><div style={{ fontWeight: 700 }}>5 offices configured</div></div>
            </div>
          </div>
        </Card>
      </div>

      <TypedConfirmDialog
        open={confirm?.kind === 'deleteRole'}
        title={`Delete role "${current?.name}"?`}
        message={`This role currently has ${current?.users || 0} users assigned. They will be reassigned to the fallback role (Associate) and may lose access to resources this role uniquely granted.`}
        requireText={(current?.name || '').toUpperCase()}
        onCancel={() => setConfirm(null)}
        onConfirm={() => { toast.push({ kind: 'warn', title: `Deleted role ${current?.name}`, message: `${current?.users || 0} users reassigned to Associate` }); setConfirm(null); }}
      />
    </div>
  );
}

function SettingsUsers({ data }) {
  const stg = window.__stg;
  const users = data.users;
  const roles = data.roles;
  const Card = window.SettingsSectionCard;
  const infra = window.__stg_infra;
  const { useToast, BulkBar, EmptyState, TypedConfirmDialog, AuditDrawer, sampleHistory, InfoTip } = infra;
  const toast = useToast();
  const { useState } = React;
  const [search, setSearch] = useState('');
  const [filter, setFilter] = useState('all');
  const [selected, setSelected] = useState(new Set());
  const [confirm, setConfirm] = useState(null); // { kind, users[] }
  const [impersonate, setImpersonate] = useState(null);
  const [audit, setAudit] = useState(null);

  const filtered = users.filter(u => {
    if (filter === 'active'   && u.status !== 'active')   return false;
    if (filter === 'pending'  && u.status !== 'pending')  return false;
    if (filter === 'suspended'&& u.status !== 'suspended')return false;
    if (filter === 'no-mfa'   && u.mfa) return false;
    if (search) {
      const q = search.toLowerCase();
      return u.name.toLowerCase().includes(q) || u.email.toLowerCase().includes(q) || u.team.toLowerCase().includes(q);
    }
    return true;
  });

  const toggleOne = (id) => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id); else next.add(id);
    setSelected(next);
  };
  const toggleAll = () => {
    if (selected.size === filtered.length) setSelected(new Set());
    else setSelected(new Set(filtered.map(u => u.id)));
  };

  const active = users.filter(u => u.status === 'active').length;
  const pending = users.filter(u => u.status === 'pending').length;
  const suspended = users.filter(u => u.status === 'suspended').length;
  const noMfa = users.filter(u => !u.mfa).length;

  return (
    <div>
      <div style={stg.stripKpi}>
        <div style={stg.stat}><span style={stg.statLabel}>Users</span><span style={stg.statValue}>{users.length}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Active</span><span style={{ ...stg.statValue, color: stg.emerald }}>{active}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Pending invites</span><span style={{ ...stg.statValue, color: stg.amber }}>{pending}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Suspended</span><span style={{ ...stg.statValue, color: stg.crimson }}>{suspended}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>No MFA</span><span style={{ ...stg.statValue, color: noMfa > 0 ? stg.amber : stg.emerald }}>{noMfa}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Roles</span><span style={stg.statValue}>{roles.length}</span></div>
      </div>

      <div style={{ display: 'flex', gap: '8px', marginBottom: '12px', flexWrap: 'wrap' }}>
        <input placeholder="Search users, emails, teams…" value={search} onChange={e => setSearch(e.target.value)} style={{ ...stg.input, width: '280px' }} />
        {[{k:'all',l:'All'},{k:'active',l:'Active'},{k:'pending',l:'Pending'},{k:'suspended',l:'Suspended'},{k:'no-mfa',l:'No MFA'}].map(f => (
          <button key={f.k} onClick={() => setFilter(f.k)}
            style={{ ...stg.btnSecondary, background: filter === f.k ? stg.steelDeep : Ts_f.color.bg.card, color: filter === f.k ? '#fff' : Ts_f.color.text.secondary, borderColor: filter === f.k ? stg.steelDeep : Ts_f.color.border.medium }}>
            {f.l}
          </button>
        ))}
        <div style={{ flex: 1 }} />
        <button style={stg.btnSecondary}>Bulk import CSV</button>
        <button style={stg.btnSecondary}>SCIM</button>
        <button data-anchor="invite" style={stg.btnPrimary} onClick={() => toast.push({ kind: 'success', title: 'Invitation sent', message: '2 pending seats consumed. Expires in 7 days.', onUndo: () => toast.push({ kind: 'info', title: 'Invitation rescinded' }) })}>+ Invite user</button>
      </div>

      {/* SCIM drift panel — #3 */}
      <Card title={<span>Directory sync (SCIM) <InfoTip text="Users provisioned from your identity provider (Azure AD / Okta). Drift shows accounts that exist locally but not in the IdP — investigate before next sync." recommended /></span>}
        action={<button style={stg.btnSecondary} onClick={() => toast.push({ kind: 'success', title: 'SCIM sync started', message: 'Polling Azure AD…' })}>Run sync now</button>}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(180px, 100%), 1fr))', gap: '0', padding: '12px 16px' }}>
          <div><div style={stg.sectionLabel}>Provider</div><div style={{ fontSize: '13px', fontWeight: 700 }}>Azure AD</div><div style={{ fontSize: '10px', color: Ts_f.color.text.tertiary, fontFamily: Ts_f.font.mono }}>arbiter.onmicrosoft.com</div></div>
          <div><div style={stg.sectionLabel}>Last sync</div><div style={{ fontSize: '13px', fontWeight: 700, color: stg.emerald }}>● 4 min ago</div><div style={{ fontSize: '10px', color: Ts_f.color.text.tertiary }}>success · 148 records</div></div>
          <div><div style={stg.sectionLabel}>Provisioned</div><div style={{ fontSize: '13px', fontWeight: 700, fontFamily: Ts_f.font.mono }}>{users.length - 2} of {users.length}</div><div style={{ fontSize: '10px', color: Ts_f.color.text.tertiary }}>via SCIM 2.0</div></div>
          <div><div style={stg.sectionLabel}>Drift</div><div style={{ fontSize: '13px', fontWeight: 700, color: stg.amber, cursor: 'pointer' }} onClick={() => setAudit({ label: 'SCIM drift', history: [{ actor: 'System', action: '2 accounts exist locally but not in IdP', at: '2026-04-23 11:14 UTC' }, { actor: 'System', action: 'Drift check ran', at: '2026-04-23 11:14 UTC' }] })}>! 2 orphan accounts →</div></div>
        </div>
      </Card>

      {/* Bulk action bar — #2 */}
      <BulkBar
        count={selected.size}
        actions={[
          { label: 'Change role…', onClick: () => toast.push({ kind: 'info', title: `Changed role on ${selected.size} users`, onUndo: () => toast.push({ title: 'Reverted' }) }) },
          { label: 'Force MFA enrollment', onClick: () => toast.push({ kind: 'success', title: `${selected.size} users prompted to enroll MFA on next login` }) },
          { label: 'Reset sessions', onClick: () => toast.push({ kind: 'warn', title: `Revoked ${selected.size} active sessions` }) },
          { label: 'Export CSV', onClick: () => toast.push({ kind: 'info', title: `Exported ${selected.size} users to CSV` }) },
          { label: 'Deactivate', danger: true, onClick: () => setConfirm({ kind: 'bulkDeactivate', n: selected.size }) },
        ]}
      />

      <div style={stg.card}>
        {filtered.length === 0 ? (
          <div style={{ padding: '16px' }}>
            <EmptyState icon="" title="No users match your filters" hint="Try clearing the search or removing a filter." />
          </div>
        ) : (
        <div style={stg.tableWrap}>
        <table style={stg.tableFixed}>
          <thead>
            <tr>
              <th style={stg.th}><input type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} ref={el => { if (el) el.indeterminate = selected.size > 0 && selected.size < filtered.length; }} onChange={toggleAll} /></th>
              <th style={stg.th}>User</th>
              <th style={stg.th}>Email</th>
              <th style={stg.th}>Role</th>
              <th style={stg.th}>Team</th>
              <th style={stg.th}>Office</th>
              <th style={stg.th}>Source</th>
              <th style={stg.th}>MFA</th>
              <th style={stg.th}>Status</th>
              <th style={stg.th}>Last active</th>
              <th style={stg.th}></th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(u => {
              const roleObj = roles.find(r => r.name === u.role);
              const statusK = u.status === 'active' ? 'ok' : u.status === 'pending' ? 'warn' : u.status === 'suspended' ? 'fail' : 'pending';
              const source = u.id && (u.id.charCodeAt(2) % 3 === 0) ? 'Local' : 'SCIM';
              return (
                <tr key={u.id} style={{ background: selected.has(u.id) ? 'rgba(37,99,235,0.04)' : 'transparent' }}>
                  <td style={stg.td}><input type="checkbox" checked={selected.has(u.id)} onChange={() => toggleOne(u.id)} /></td>
                  <td style={stg.td}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                      <div style={{
                        width: '28px', height: '28px', borderRadius: '50%', background: roleObj?.color || stg.steel,
                        color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
                        fontSize: '11px', fontWeight: 700, flexShrink: 0,
                      }}>{u.name.split(' ').map(n => n[0]).join('').slice(0,2)}</div>
                      <span style={{ fontSize: '12px', fontWeight: 600, color: Ts_f.color.text.primary }}>{u.name}</span>
                    </div>
                  </td>
                  <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.secondary, fontFamily: Ts_f.font.mono }}>{u.email}</td>
                  <td style={stg.td}><span style={{ ...stg.tag, background: `${roleObj?.color || stg.steel}15`, color: roleObj?.color || stg.steel }}>{u.role}</span></td>
                  <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.secondary }}>{u.team}</td>
                  <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.tertiary, fontFamily: Ts_f.font.mono }}>{u.office}</td>
                  <td style={stg.td}><span style={{ ...stg.tag, ...stg.statusPill(source === 'SCIM' ? 'info' : 'pending') }}>{source}</span></td>
                  <td style={stg.td}>
                    {u.mfa
                      ? <span style={{ ...stg.tag, ...stg.statusPill('ok') }}>on</span>
                      : <span style={{ ...stg.tag, ...stg.statusPill('warn') }}>off</span>}
                  </td>
                  <td style={stg.td}><span style={{ ...stg.tag, ...stg.statusPill(statusK) }}>{u.status}</span></td>
                  <td style={{ ...stg.td, fontSize: '11px', color: Ts_f.color.text.tertiary }}>{u.lastActive}</td>
                  <td style={{ ...stg.td, textAlign: 'right', whiteSpace: 'nowrap' }}>
                    <button style={stg.btnGhost} onClick={() => toast.push({ kind: 'info', title: `Editing ${u.name}` })}>Edit</button>
                    <button style={stg.btnGhost} title="Impersonate (audited)" onClick={() => setImpersonate(u)}>Impersonate</button>
                    <button style={stg.btnGhost} onClick={() => setAudit({ label: u.name, history: sampleHistory('user') })}>History</button>
                    {u.status !== 'suspended' && <button style={stg.btnDanger} onClick={() => setConfirm({ kind: 'suspend', user: u })}>Suspend</button>}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        </div>
        )}
      </div>

      {/* Typed-confirm dialogs */}
      <TypedConfirmDialog
        open={confirm?.kind === 'suspend'}
        title={`Suspend ${confirm?.user?.name}?`}
        message="This will immediately revoke all active sessions and API keys. The user will no longer be able to access any matter data. This is auditable and reversible."
        requireText="SUSPEND"
        onCancel={() => setConfirm(null)}
        onConfirm={() => { toast.push({ kind: 'warn', title: `Suspended ${confirm.user.name}`, onUndo: () => toast.push({ title: 'Reinstated' }) }); setConfirm(null); }}
      />
      <TypedConfirmDialog
        open={confirm?.kind === 'bulkDeactivate'}
        title={`Deactivate ${confirm?.n || 0} users?`}
        message={`This will revoke access for ${confirm?.n || 0} users immediately. API keys, OAuth tokens, and session cookies will be invalidated. Billing seats will free up at the end of the current cycle.`}
        requireText="DEACTIVATE"
        onCancel={() => setConfirm(null)}
        onConfirm={() => { toast.push({ kind: 'warn', title: `Deactivated ${confirm.n} users`, onUndo: () => toast.push({ title: 'Reactivated' }) }); setSelected(new Set()); setConfirm(null); }}
      />

      {/* Impersonation banner — UX pattern */}
      {impersonate && (
        <div style={{
          position: 'fixed', top: '60px', left: '50%', transform: 'translateX(-50%)', zIndex: 9993,
          padding: '10px 16px', borderRadius: '8px',
          background: '#78350F', color: '#FEF3C7', fontSize: '12px', fontWeight: 600,
          boxShadow: '0 6px 20px rgba(0,0,0,0.2)', display: 'flex', alignItems: 'center', gap: '12px',
        }}>
           Impersonating <span style={{ fontFamily: Ts_f.font.mono, fontWeight: 700 }}>{impersonate.name}</span> · every action audited
          <button onClick={() => { setImpersonate(null); toast.push({ kind: 'info', title: 'Impersonation ended', message: 'Session return logged to audit trail' }); }} style={{
            background: '#FEF3C7', color: '#78350F', border: 'none',
            padding: '4px 10px', borderRadius: '5px', fontWeight: 700, fontSize: '11px', cursor: 'pointer',
          }}>End impersonation</button>
        </div>
      )}

      {/* Audit drawer */}
      <AuditDrawer open={!!audit} entry={audit} history={audit?.history || []} onClose={() => setAudit(null)} />
    </div>
  );
}

function SettingsTeams({ data }) {
  const stg = window.__stg;
  const teams = data.teams;
  const Card = window.SettingsSectionCard;

  const total = teams.reduce((s, t) => s + t.members, 0);
  const matters = teams.reduce((s, t) => s + t.mattersActive, 0);

  return (
    <div>
      <div style={stg.stripKpi}>
        <div style={stg.stat}><span style={stg.statLabel}>Teams</span><span style={stg.statValue}>{teams.length}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Assignments</span><span style={stg.statValue}>{total}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Active matters</span><span style={stg.statValue}>{matters}</span></div>
        <div style={stg.stat}><span style={stg.statLabel}>Practice areas</span><span style={stg.statValue}>{new Set(teams.map(t => t.practiceArea)).size}</span></div>
      </div>

      <Card title={`Teams · ${teams.length}`} action={<button style={stg.btnPrimary}>+ New team</button>}>
        <div style={stg.cardGrid(320)}>
          {teams.map(t => (
            <div key={t.id} style={{ margin: '8px', border: `1px solid ${Ts_f.color.border.light}`, borderRadius: '8px', overflow: 'hidden' }}>
              <div style={{ background: `linear-gradient(135deg, ${t.color}18 0%, transparent 100%)`, padding: '14px 16px', borderBottom: `1px solid ${Ts_f.color.border.light}` }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '4px' }}>
                  <div style={{ width: '4px', height: '20px', background: t.color, borderRadius: '2px' }} />
                  <div style={{ fontSize: '13px', fontWeight: 700, color: Ts_f.color.text.primary }}>{t.name}</div>
                </div>
                <div style={{ fontSize: '11px', color: Ts_f.color.text.tertiary }}>Lead · {t.lead}</div>
              </div>
              <div style={{ padding: '12px 16px', display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '10px' }}>
                <div>
                  <div style={stg.sectionLabel}>Members</div>
                  <div style={{ fontSize: '16px', fontWeight: 700, color: Ts_f.color.text.primary, fontFamily: Ts_f.font.mono }}>{t.members}</div>
                </div>
                <div>
                  <div style={stg.sectionLabel}>Matters</div>
                  <div style={{ fontSize: '16px', fontWeight: 700, color: t.color, fontFamily: Ts_f.font.mono }}>{t.mattersActive}</div>
                </div>
                <div>
                  <div style={stg.sectionLabel}>Practice</div>
                  <div style={{ fontSize: '11px', fontWeight: 600, color: Ts_f.color.text.secondary, marginTop: '4px' }}>{t.practiceArea}</div>
                </div>
              </div>
              <div style={{ padding: '10px 16px', borderTop: `1px solid ${Ts_f.color.border.light}`, display: 'flex', justifyContent: 'space-between' }}>
                <button style={stg.btnGhost}>Manage members</button>
                <button style={stg.btnGhost}>Settings →</button>
              </div>
            </div>
          ))}
        </div>
      </Card>
    </div>
  );
}

window.SettingsFirm          = SettingsFirm;
window.SettingsSecurity      = SettingsSecurity;
window.SettingsRoles         = SettingsRoles;
window.SettingsUsers         = SettingsUsers;
window.SettingsTeams         = SettingsTeams;
