// admin.jsx — Admin Panel: User & Role Management

const { useState, useEffect, useMemo } = React;

const RoleBadge = ({ roleId, roles = [] }) => {
  const r = roles.find(x => x.id === roleId);
  if (!r) return <TagBadge label={roleId || 'keine Rolle'} />;
  return <TagBadge label={r.label} color={r.color} />;
};

const PermissionCheckboxes = ({ catalog, selected, onChange, disabled = false, requires2FA = [], onRequires2FAChange }) => {
  const groups = useMemo(() => {
    const m = {};
    for (const p of catalog) (m[p.group] = m[p.group] || []).push(p);
    return m;
  }, [catalog]);
  const toggle = (id) => {
    if (disabled) return;
    if (selected.includes(id)) {
      onChange(selected.filter(x => x !== id));
      // Wenn Permission entzogen wird, automatisch aus 2FA-Pflicht entfernen.
      if (onRequires2FAChange && requires2FA.includes(id)) {
        onRequires2FAChange(requires2FA.filter(x => x !== id));
      }
    } else {
      onChange([...selected, id]);
    }
  };
  const toggle2FA = (id) => {
    if (!onRequires2FAChange) return;
    if (requires2FA.includes(id)) onRequires2FAChange(requires2FA.filter(x => x !== id));
    else onRequires2FAChange([...requires2FA, id]);
  };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {Object.entries(groups).map(([group, perms]) => (
        <div key={group}>
          <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 6 }}>{group}</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
            {perms.map(p => {
              const has = selected.includes(p.id);
              const mfa = requires2FA.includes(p.id);
              const lockEnabled = has && !!onRequires2FAChange;
              return (
                <div key={p.id} style={{
                  display: 'flex', alignItems: 'center', gap: 8,
                  padding: '6px 10px', borderRadius: 6,
                  background: has ? 'var(--accent-dim)' : 'var(--surface-2)',
                  border: `1px solid ${has ? 'var(--accent)' : 'var(--border)'}`,
                  opacity: disabled ? 0.6 : 1,
                  fontSize: 13, color: has ? 'var(--accent)' : 'var(--text)',
                }}>
                  <label style={{ display: 'flex', alignItems: 'center', gap: 8, flex: 1, minWidth: 0, cursor: disabled ? 'not-allowed' : 'pointer' }}>
                    <input type="checkbox" checked={has} disabled={disabled}
                      onChange={() => toggle(p.id)}
                      style={{ accentColor: 'var(--accent)' }} />
                    <span style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }}>{p.label}</span>
                  </label>
                  <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text-dim)' }}>{p.id}</span>
                  {onRequires2FAChange && (
                    <button type="button"
                      onClick={() => lockEnabled && toggle2FA(p.id)}
                      disabled={!lockEnabled}
                      title={!has ? 'Erst Permission aktivieren' : (mfa ? '2FA wird erzwungen — klick zum Entfernen' : 'Klick: 2FA für diese Permission erzwingen')}
                      style={{
                        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                        width: 26, height: 26, padding: 0, marginLeft: 2,
                        background: mfa ? 'var(--accent)' : 'transparent',
                        border: `1px solid ${mfa ? 'var(--accent)' : 'var(--border)'}`,
                        borderRadius: 5,
                        cursor: lockEnabled ? 'pointer' : 'not-allowed',
                        opacity: lockEnabled ? 1 : 0.35,
                      }}>
                      <Icon name="lock" size={13} color={mfa ? '#fff' : 'var(--text-muted)'} />
                    </button>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      ))}
    </div>
  );
};

const AdminPanel = ({ currentUser, setRoute, roles = [], setRoles, permissionCatalog = [], topicAreas = [], sections = [], refreshStructure, refreshUser, onSettingsChange, embedded = false }) => {
  const [tab, setTab] = useState('users');
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState('');
  const [showAddUser, setShowAddUser] = useState(false);
  const [editingRoleFor, setEditingRoleFor] = useState(null); // userId
  const [newUser, setNewUser] = useState({ name: '', email: '', password: '', role: '' });
  const [addError, setAddError] = useState('');
  const [confirmDelete, setConfirmDelete] = useState(null);
  const [settings, setSettings] = useState(null);
  const [settingsError, setSettingsError] = useState('');
  const [savingSetting, setSavingSetting] = useState(null);

  // Audit-Log tab state
  const [auditEntries, setAuditEntries] = useState([]);
  const [auditTotal, setAuditTotal] = useState(0);
  const [auditPage, setAuditPage] = useState(0);
  const [auditFilter, setAuditFilter] = useState({ action: '', userId: '', from: '', to: '' });
  const [auditLoading, setAuditLoading] = useState(false);
  const [auditExporting, setAuditExporting] = useState(false);
  const AUDIT_PAGE_SIZE = 50;

  // Roles tab state
  const [editingRole, setEditingRole] = useState(null); // null | { id?, label, color, description, permissions, isSystem, topicAreaId, isNew? }
  const [roleError, setRoleError] = useState('');
  const [confirmDeleteRole, setConfirmDeleteRole] = useState(null);

  // Themenbereiche tab state
  const [editingArea, setEditingArea] = useState(null); // null | { id?, label, color, description, isNew? }
  const [editingSection, setEditingSection] = useState(null); // null | { id?, topicAreaId, short, label, color, description, sortOrder, isNew? }
  const [structureError, setStructureError] = useState('');
  const [confirmDeleteArea, setConfirmDeleteArea] = useState(null);
  const [confirmDeleteSection, setConfirmDeleteSection] = useState(null);
  const [expandedArea, setExpandedArea] = useState(null);

  const refresh = async () => {
    setLoading(true);
    const { ok, data } = await apiFetch('/api/users');
    if (ok) { setUsers(data.users); setLoadError(''); }
    else setLoadError(data.error || 'Liste konnte nicht geladen werden.');
    setLoading(false);
  };

  const refreshRoles = async () => {
    const { ok, data } = await apiFetch('/api/roles');
    if (ok && setRoles) setRoles(data.roles || []);
  };

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

  const loadSettings = async () => {
    setSettingsError('');
    const { ok, data } = await apiFetch('/api/settings');
    if (ok) setSettings(data.settings);
    else setSettingsError(data.error || 'Settings konnten nicht geladen werden.');
  };
  useEffect(() => { if (tab === 'settings' && !settings) loadSettings(); }, [tab]);

  // Lokale Drafts für die Maintenance-Felder. Ohne diese Zwischenstufe würde
  // jeder Keystroke updateSetting() triggern, das Input wäre während des
  // PUT-Requests `disabled` → Browser verliert den Fokus, User kann nur ein
  // Zeichen tippen. Drafts werden bei Server-Updates resynced und 500ms nach
  // dem letzten Tippen committed. Apps-Array (Checkboxen) committet ohne
  // Debounce, weil der Klick eh atomar ist.
  const [maintDrafts, setMaintDrafts] = useState({ scheduledAt: '', duration: 0, message: '' });
  const maintSyncRef = React.useRef(false);
  useEffect(() => {
    if (!settings) return;
    maintSyncRef.current = true;
    setMaintDrafts({
      scheduledAt: settings.maintenanceScheduledAt
        ? new Date(settings.maintenanceScheduledAt).toISOString().slice(0, 16)
        : '',
      duration: Number(settings.maintenanceScheduledDuration) || 0,
      message: settings.maintenanceMessage || '',
    });
  }, [settings?.maintenanceScheduledAt, settings?.maintenanceScheduledDuration, settings?.maintenanceMessage]);
  useEffect(() => {
    if (!settings) return;
    if (maintSyncRef.current) { maintSyncRef.current = false; return; }
    const t = setTimeout(() => {
      const targetIso = maintDrafts.scheduledAt ? new Date(maintDrafts.scheduledAt).toISOString() : '';
      if (targetIso !== (settings.maintenanceScheduledAt || '')) {
        updateSetting('maintenanceScheduledAt', targetIso);
      }
      const targetDur = Math.max(0, Math.floor(Number(maintDrafts.duration) || 0));
      if (targetDur !== (Number(settings.maintenanceScheduledDuration) || 0)) {
        updateSetting('maintenanceScheduledDuration', targetDur);
      }
      if (maintDrafts.message !== (settings.maintenanceMessage || '')) {
        updateSetting('maintenanceMessage', maintDrafts.message);
      }
    }, 500);
    return () => clearTimeout(t);
  }, [maintDrafts.scheduledAt, maintDrafts.duration, maintDrafts.message]);

  const toggleMaintenanceApp = (appId) => {
    const current = Array.isArray(settings?.maintenanceApps) ? settings.maintenanceApps : [];
    const next = current.includes(appId)
      ? current.filter(a => a !== appId)
      : [...current, appId];
    updateSetting('maintenanceApps', next);
  };
  const MAINT_APPS = [
    { id: 'heronry', label: 'Heronry',  hint: 'Knowledge-Base' },
    { id: 'hub',     label: 'Hub',      hint: 'sperrt ALLE Apps (Plattform-weit)' },
    { id: 'egret',   label: 'Egret',    hint: 'Subnet-Calc (statisch)' },
    { id: 'plumage', label: 'Plumage',  hint: 'Cheatsheets (statisch)' },
  ];

  const buildAuditQuery = (extras = {}) => {
    const params = new URLSearchParams({ ...extras });
    if (auditFilter.action) params.set('action', auditFilter.action);
    if (auditFilter.userId) params.set('userId', auditFilter.userId);
    if (auditFilter.from)   params.set('from', auditFilter.from);
    if (auditFilter.to)     params.set('to', auditFilter.to);
    return params;
  };

  const loadAudit = async () => {
    setAuditLoading(true);
    const params = buildAuditQuery({ limit: String(AUDIT_PAGE_SIZE), offset: String(auditPage * AUDIT_PAGE_SIZE) });
    const { ok, data } = await apiFetch(`/api/audit-log?${params}`);
    if (ok) { setAuditEntries(data.entries || []); setAuditTotal(data.total || 0); }
    setAuditLoading(false);
  };

  const exportAuditCsv = async () => {
    setAuditExporting(true);
    try {
      const params = buildAuditQuery();
      const token = localStorage.getItem('tb_token');
      const resp = await fetch(`/api/audit-log/export.csv?${params}`, {
        headers: token ? { Authorization: `Bearer ${token}` } : {},
      });
      if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
      const blob = await resp.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `audit-log-${new Date().toISOString().slice(0, 10)}.csv`;
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
    } catch (err) {
      alert(`CSV-Export fehlgeschlagen: ${err.message}`);
    } finally {
      setAuditExporting(false);
    }
  };
  useEffect(() => { if (tab === 'audit') loadAudit(); }, [tab, auditPage, auditFilter]);

  // Initial Default-Role for "neuer Nutzer"-Form
  useEffect(() => {
    if (!newUser.role) {
      const fallback = settings?.defaultRoleId || roles.find(r => !r.isSystem)?.id || roles[0]?.id || '';
      if (fallback) setNewUser(u => ({ ...u, role: fallback }));
    }
  }, [roles, settings]);

  const updateSetting = async (key, value) => {
    setSavingSetting(key); setSettingsError('');
    const { ok, data } = await apiFetch(`/api/settings/${key}`, { method: 'PUT', body: { value } });
    setSavingSetting(null);
    if (!ok) { setSettingsError(data.error || 'Speichern fehlgeschlagen.'); return; }
    setSettings(s => ({ ...(s || {}), [key]: value }));
    if (typeof onSettingsChange === 'function') onSettingsChange();
  };

  if (!can(currentUser, 'users:manage') && !can(currentUser, 'roles:manage') && !can(currentUser, 'settings:manage') && !can(currentUser, 'topic_areas:manage') && !can(currentUser, 'sections:manage')) {
    return (
      <div style={{ padding: 48, textAlign: 'center' }}>
        <Icon name="lock" size={40} color="var(--text-dim)" />
        <div style={{ marginTop: 16, fontSize: 16, color: 'var(--text-muted)', fontWeight: 600 }}>Kein Zugriff</div>
        <div style={{ marginTop: 8, fontSize: 13, color: 'var(--text-dim)' }}>Du hast keine Verwaltungs-Rechte.</div>
        <div style={{ marginTop: 20 }}><Btn variant="secondary" onClick={() => setRoute({ page: 'dashboard' })}>Zurück</Btn></div>
      </div>
    );
  }

  const handleAddUser = async () => {
    if (!newUser.name || !newUser.email || !newUser.password) { setAddError('Alle Felder ausfüllen.'); return; }
    if (!newUser.role) { setAddError('Bitte Rolle wählen.'); return; }
    const { ok, data } = await apiFetch('/api/users', { method: 'POST', body: newUser });
    if (!ok) { setAddError(data.error || 'Anlegen fehlgeschlagen.'); return; }
    setNewUser({ name: '', email: '', password: '', role: roles.find(r => !r.isSystem)?.id || '' });
    setAddError('');
    setShowAddUser(false);
    refresh();
  };

  const handleRoleChange = async (userId, newRoleId) => {
    if (userId === currentUser.id && newRoleId !== 'admin') {
      if (!window.confirm('Du änderst deine eigene Rolle. Du verlierst damit Admin-Rechte. Fortfahren?')) return;
    }
    const { ok, data } = await apiFetch(`/api/users/${userId}`, { method: 'PATCH', body: { role: newRoleId } });
    setEditingRoleFor(null);
    if (!ok) { alert(data.error || 'Rolle ändern fehlgeschlagen.'); return; }
    refresh();
    if (userId === currentUser.id && typeof refreshUser === 'function') refreshUser();
  };

  const handleDelete = async (userId) => {
    if (userId === currentUser.id) return;
    const { ok, data } = await apiFetch(`/api/users/${userId}`, { method: 'DELETE' });
    setConfirmDelete(null);
    if (!ok) { alert(data.error || 'Löschen fehlgeschlagen.'); return; }
    refresh();
  };

  const startNewRole = () => {
    setRoleError('');
    setEditingRole({
      isNew: true,
      label: '', color: '#9b5cf6', description: '',
      permissions: [], permissions2FA: [],
      isSystem: false, topicAreaId: null,
    });
  };
  const startEditRole = (r) => {
    setRoleError('');
    setEditingRole({
      isNew: false,
      id: r.id, label: r.label, color: r.color, description: r.description || '',
      permissions: r.permissions.includes('__all__')
        ? permissionCatalog.map(p => p.id)
        : r.permissions,
      permissions2FA: Array.isArray(r.permissions2FA) ? r.permissions2FA : [],
      isSystem: r.isSystem,
      topicAreaId: r.topicAreaId || null,
    });
  };
  const cancelRole = () => { setEditingRole(null); setRoleError(''); };

  const saveRole = async () => {
    if (!editingRole) return;
    if (!editingRole.label.trim()) { setRoleError('Label fehlt.'); return; }
    // permissions2FA muss Subset von permissions sein — defensiv filtern, falls UI inkonsistent ist.
    const cleanPerm2FA = (editingRole.permissions2FA || []).filter(p => editingRole.permissions.includes(p));
    const body = {
      label: editingRole.label.trim(),
      color: editingRole.color,
      description: editingRole.description,
      permissions: editingRole.permissions,
      permissions2FA: cleanPerm2FA,
      topicAreaId: editingRole.topicAreaId || null,
    };
    if (editingRole.isNew) {
      const { ok, data } = await apiFetch('/api/roles', { method: 'POST', body });
      if (!ok) { setRoleError(data.error || 'Anlegen fehlgeschlagen.'); return; }
    } else {
      const { ok, data } = await apiFetch(`/api/roles/${editingRole.id}`, { method: 'PUT', body });
      if (!ok) { setRoleError(data.error || 'Speichern fehlgeschlagen.'); return; }
    }
    await refreshRoles();
    if (!editingRole.isNew && editingRole.id === currentUser.role && typeof refreshUser === 'function') {
      refreshUser();
    }
    setEditingRole(null);
    setRoleError('');
  };

  // Themenbereiche-Handler
  const startNewArea = () => { setStructureError(''); setEditingArea({ isNew: true, label: '', color: '#9b5cf6', description: '' }); };
  const startEditArea = (a) => { setStructureError(''); setEditingArea({ isNew: false, id: a.id, label: a.label, color: a.color, description: a.description || '' }); };
  const cancelArea = () => { setEditingArea(null); setStructureError(''); };
  const saveArea = async () => {
    if (!editingArea || !editingArea.label.trim()) { setStructureError('Label fehlt.'); return; }
    const body = { label: editingArea.label.trim(), color: editingArea.color, description: editingArea.description };
    const path = editingArea.isNew ? '/api/topic-areas' : `/api/topic-areas/${editingArea.id}`;
    const method = editingArea.isNew ? 'POST' : 'PUT';
    const { ok, data } = await apiFetch(path, { method, body });
    if (!ok) { setStructureError(data.error || 'Speichern fehlgeschlagen.'); return; }
    if (typeof refreshStructure === 'function') await refreshStructure();
    setEditingArea(null);
  };
  const askDeleteArea = (a) => { setStructureError(''); setConfirmDeleteArea(a); };
  const doDeleteArea = async () => {
    if (!confirmDeleteArea) return;
    const { ok, data } = await apiFetch(`/api/topic-areas/${confirmDeleteArea.id}`, { method: 'DELETE' });
    if (!ok) { setStructureError(data.error || 'Löschen fehlgeschlagen.'); setConfirmDeleteArea(null); return; }
    setConfirmDeleteArea(null);
    if (typeof refreshStructure === 'function') await refreshStructure();
  };

  const startNewSection = (areaId) => {
    setStructureError('');
    setEditingSection({ isNew: true, topicAreaId: areaId, short: '', label: '', color: '#9b5cf6', description: '', sortOrder: 0 });
  };
  const startEditSection = (s) => {
    setStructureError('');
    setEditingSection({
      isNew: false, id: s.id, topicAreaId: s.topicAreaId,
      short: s.short || '', label: s.label, color: s.color, description: s.description || '', sortOrder: s.sortOrder || 0,
    });
  };
  const cancelSection = () => { setEditingSection(null); setStructureError(''); };
  const saveSection = async () => {
    if (!editingSection || !editingSection.label.trim()) { setStructureError('Label fehlt.'); return; }
    const body = {
      topicAreaId: editingSection.topicAreaId,
      short: editingSection.short || null,
      label: editingSection.label.trim(),
      color: editingSection.color,
      description: editingSection.description,
      sortOrder: editingSection.sortOrder || 0,
    };
    const path = editingSection.isNew ? '/api/sections' : `/api/sections/${editingSection.id}`;
    const method = editingSection.isNew ? 'POST' : 'PUT';
    const { ok, data } = await apiFetch(path, { method, body });
    if (!ok) { setStructureError(data.error || 'Speichern fehlgeschlagen.'); return; }
    if (typeof refreshStructure === 'function') await refreshStructure();
    setEditingSection(null);
  };
  const askDeleteSection = (s) => { setStructureError(''); setConfirmDeleteSection(s); };
  const doDeleteSection = async () => {
    if (!confirmDeleteSection) return;
    const { ok, data } = await apiFetch(`/api/sections/${confirmDeleteSection.id}`, { method: 'DELETE' });
    if (!ok) { setStructureError(data.error || 'Löschen fehlgeschlagen.'); setConfirmDeleteSection(null); return; }
    setConfirmDeleteSection(null);
    if (typeof refreshStructure === 'function') await refreshStructure();
  };

  const askDeleteRole = (r) => setConfirmDeleteRole(r);
  const doDeleteRole = async () => {
    if (!confirmDeleteRole) return;
    const { ok, data } = await apiFetch(`/api/roles/${confirmDeleteRole.id}`, { method: 'DELETE' });
    if (!ok) { setRoleError(data.error || 'Löschen fehlgeschlagen.'); setConfirmDeleteRole(null); return; }
    setConfirmDeleteRole(null);
    refreshRoles();
  };

  const usersByRole = useMemo(() => {
    const m = {};
    for (const u of users) m[u.role] = (m[u.role] || 0) + 1;
    return m;
  }, [users]);

  const canManageStructure = can(currentUser, 'topic_areas:manage') || can(currentUser, 'sections:manage');
  const visibleTabs = [
    can(currentUser, 'users:manage')    ? { id: 'users',     label: 'Nutzer',         icon: 'user'     } : null,
    can(currentUser, 'roles:manage')    ? { id: 'roles',     label: 'Rollen & Rechte', icon: 'lock'     } : null,
    canManageStructure                  ? { id: 'structure', label: 'Themenbereiche', icon: 'grid'     } : null,
    can(currentUser, 'settings:manage') ? { id: 'settings',  label: 'Einstellungen',  icon: 'sliders'  } : null,
    can(currentUser, 'audit:read')      ? { id: 'audit',     label: 'Audit-Log',      icon: 'eye'      } : null,
  ].filter(Boolean);

  const Wrapper = embedded ? React.Fragment : 'div';
  const wrapperProps = embedded ? {} : { style: { padding: 32, maxWidth: 960, width: '100%', margin: '0 auto', boxSizing: 'border-box' } };

  // 2FA-Banner: aktuelle Rolle des Users ermitteln, deren permissions2FA mit
  // den tatsächlichen User-Permissions schneiden. Wenn etwas dabei ist und der
  // User keine 2FA-Methode hat, blocked das Backend Mutations — wir zeigen es
  // hier prominent an, damit der User weiß, warum etwas nicht klappt.
  const myRole = roles.find(r => r.id === currentUser.role);
  const myPerm2FA = (myRole?.permissions2FA || []).filter(p => (currentUser.permissions || []).includes(p));
  const mfaEnabled = !!(currentUser.totpEnabled || currentUser.telegramEnabled);
  const showMfaBanner = !mfaEnabled && myPerm2FA.length > 0;
  const blockedLabels = myPerm2FA.map(p => permissionCatalog.find(pc => pc.id === p)?.label || p);

  return (
    <Wrapper {...wrapperProps}>
      {!embedded && <Breadcrumb parts={['admin']} />}

      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', margin: embedded ? '0 0 20px' : '16px 0 24px' }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 22, fontWeight: 700, color: 'var(--text)' }}>{embedded ? 'Verwaltung' : 'Admin Panel'}</h2>
          <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>Nutzer- und Rollenverwaltung</p>
        </div>
        <div style={{ display: 'flex', gap: 4, background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, padding: 3 }}>
          {visibleTabs.map(t => (
            <button key={t.id} onClick={() => setTab(t.id)}
              style={{
                display: 'flex', alignItems: 'center', gap: 6, padding: '6px 14px',
                borderRadius: 6, border: 'none', cursor: 'pointer', fontSize: 13,
                fontFamily: 'var(--font-sans)', transition: 'all 0.15s',
                background: tab === t.id ? 'var(--accent-dim)' : 'transparent',
                color: tab === t.id ? 'var(--accent)' : 'var(--text-muted)',
              }}>
              <Icon name={t.icon} size={13} color={tab === t.id ? 'var(--accent)' : 'var(--text-muted)'} />
              {t.label}
            </button>
          ))}
        </div>
      </div>

      {/* 2FA-Required-Banner */}
      {showMfaBanner && (
        <div style={{
          background: 'rgba(251,191,36,0.10)', border: '1px solid rgba(251,191,36,0.4)',
          borderRadius: 8, padding: '14px 18px', marginBottom: 20,
          display: 'flex', gap: 14, alignItems: 'flex-start',
        }}>
          <Icon name="lock" size={20} color="#fbbf24" />
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 14, fontWeight: 600, color: '#fbbf24', marginBottom: 4 }}>2FA erforderlich</div>
            <div style={{ fontSize: 13, color: 'var(--text)', lineHeight: 1.55 }}>
              Deine Rolle verlangt 2FA für: <strong>{blockedLabels.join(', ')}</strong>.
              Aktiviere eine 2FA-Methode (Authenticator-App oder Telegram), um diese Aktionen durchführen zu können.
            </div>
          </div>
          <Btn variant="secondary" icon="lock" onClick={() => setRoute({ page: 'settings', tab: 'security' })}>
            2FA einrichten
          </Btn>
        </div>
      )}

      {/* ── USERS TAB ── */}
      {tab === 'users' && can(currentUser, 'users:manage') && (
        <>
          <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 14 }}>
            <Btn variant="primary" icon="plus" onClick={() => setShowAddUser(true)}>Nutzer hinzufügen</Btn>
          </div>

          <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden' }}>
            <div style={{
              display: 'grid', gridTemplateColumns: '2fr 2fr 1.4fr 1fr auto',
              gap: 16, padding: '10px 20px',
              background: 'var(--surface-2)', borderBottom: '1px solid var(--border)',
              fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)',
              textTransform: 'uppercase', letterSpacing: '0.08em',
            }}>
              <span>Nutzer</span>
              <span>E-Mail</span>
              <span>Rolle</span>
              <span>Erstellt</span>
              <span>Aktionen</span>
            </div>

            {users.map((u, idx) => {
              const isSelf = u.id === currentUser.id;
              const isEditingThis = editingRoleFor === u.id;
              return (
                <div key={u.id} style={{
                  display: 'grid', gridTemplateColumns: '2fr 2fr 1.4fr 1fr auto',
                  gap: 16, padding: '14px 20px', alignItems: 'center',
                  borderBottom: idx < users.length - 1 ? '1px solid var(--border)' : 'none',
                  background: isSelf ? 'var(--accent-dim)' : 'transparent',
                }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <Avatar initials={u.initials} size={30} />
                    <div>
                      <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text)' }}>
                        {u.name}
                        {isSelf && <span style={{ marginLeft: 6, fontSize: 10, color: 'var(--accent)', fontFamily: 'var(--font-mono)' }}>(Du)</span>}
                      </div>
                    </div>
                  </div>

                  <div style={{ fontSize: 12, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                    {u.email}
                  </div>

                  <div>
                    {isEditingThis ? (
                      <div style={{ display: 'flex', gap: 6, alignItems: 'center', flexWrap: 'wrap' }}>
                        <select value={u.role || ''}
                          onChange={e => handleRoleChange(u.id, e.target.value)}
                          style={{
                            padding: '4px 8px', borderRadius: 6, border: '1px solid var(--accent)',
                            background: 'var(--surface-2)', color: 'var(--text)',
                            fontSize: 12, fontFamily: 'var(--font-sans)',
                          }}>
                          {roles.map(r => (
                            <option key={r.id} value={r.id}>{r.label}{r.isSystem ? ' (System)' : ''}</option>
                          ))}
                        </select>
                        <button onClick={() => setEditingRoleFor(null)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', display: 'flex', alignItems: 'center' }}>
                          <Icon name="x" size={14} />
                        </button>
                      </div>
                    ) : (
                      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                        <RoleBadge roleId={u.role} roles={roles} />
                        {can(currentUser, 'users:manage') && (
                          <button onClick={() => setEditingRoleFor(u.id)}
                            title="Rolle ändern"
                            style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-dim)', display: 'flex', padding: 2, borderRadius: 4 }}
                            onMouseEnter={e => e.currentTarget.style.color = 'var(--accent)'}
                            onMouseLeave={e => e.currentTarget.style.color = 'var(--text-dim)'}
                          >
                            <Icon name="edit" size={12} />
                          </button>
                        )}
                      </div>
                    )}
                  </div>

                  <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>
                    {formatDateDe(u.createdAt)}
                  </div>

                  <div style={{ display: 'flex', gap: 4 }}>
                    <button
                      onClick={() => !isSelf && setConfirmDelete(u)}
                      disabled={isSelf}
                      title={isSelf ? 'Eigenen Account nicht löschbar' : 'Nutzer löschen'}
                      style={{
                        padding: '5px', borderRadius: 6, border: '1px solid transparent',
                        background: 'transparent', cursor: isSelf ? 'not-allowed' : 'pointer',
                        color: 'var(--text-dim)', display: 'flex', opacity: isSelf ? 0.3 : 1,
                      }}
                      onMouseEnter={e => { if (!isSelf) { e.currentTarget.style.color = '#f87171'; e.currentTarget.style.borderColor = 'rgba(248,113,113,0.3)'; e.currentTarget.style.background = 'rgba(248,113,113,0.1)'; }}}
                      onMouseLeave={e => { e.currentTarget.style.color = 'var(--text-dim)'; e.currentTarget.style.borderColor = 'transparent'; e.currentTarget.style.background = 'transparent'; }}
                    >
                      <Icon name="trash" size={14} />
                    </button>
                  </div>
                </div>
              );
            })}
          </div>

          <div style={{ marginTop: 12, fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>
            {loading ? 'lade ...' : loadError ? loadError : `${users.length} Nutzer registriert`}
          </div>
        </>
      )}

      {/* ── ROLES TAB ── */}
      {tab === 'roles' && can(currentUser, 'roles:manage') && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
          <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
            <Btn variant="primary" icon="plus" onClick={startNewRole}>Neue Rolle</Btn>
          </div>

          {roleError && (
            <div style={{ fontSize: 12, color: '#f87171', background: 'rgba(248,113,113,0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(248,113,113,0.2)' }}>{roleError}</div>
          )}

          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 16 }}>
            {roles.map(r => {
              const userCount = usersByRole[r.id] || 0;
              const permLabel = r.permissions.includes('__all__')
                ? `Alle (${permissionCatalog.length})`
                : `${r.permissions.length} / ${permissionCatalog.length}`;
              return (
                <div key={r.id} style={{
                  background: 'var(--surface)', border: `1px solid ${r.color}30`,
                  borderRadius: 12, padding: '18px 20px', borderTop: `3px solid ${r.color}`,
                  display: 'flex', flexDirection: 'column', gap: 10,
                }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8, justifyContent: 'space-between' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <RoleBadge roleId={r.id} roles={roles} />
                      {r.isSystem && <Icon name="lock" size={12} color="var(--text-muted)" />}
                    </div>
                    <span style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>
                      {userCount} {userCount === 1 ? 'Nutzer' : 'Nutzer'}
                    </span>
                  </div>
                  <p style={{ margin: 0, fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.5, minHeight: 32 }}>
                    {r.description || <span style={{ fontStyle: 'italic' }}>(keine Beschreibung)</span>}
                  </p>
                  <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)' }}>
                    Permissions: {permLabel}
                  </div>
                  <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)' }}>
                    Bereich: {r.topicAreaId
                      ? (topicAreas.find(a => a.id === r.topicAreaId)?.label || r.topicAreaId)
                      : <span style={{ color: 'var(--text-muted)' }}>Global</span>}
                  </div>
                  <div style={{ display: 'flex', gap: 6, marginTop: 4 }}>
                    <Btn variant="secondary" size="sm" icon="edit" onClick={() => startEditRole(r)}>Bearbeiten</Btn>
                    {!r.isSystem && (
                      <Btn variant="danger" size="sm" icon="trash" onClick={() => askDeleteRole(r)} disabled={userCount > 0}>
                        {userCount > 0 ? `${userCount} zugeordnet` : 'Löschen'}
                      </Btn>
                    )}
                  </div>
                </div>
              );
            })}
          </div>

          {/* Permission Matrix */}
          {permissionCatalog.length > 0 && (
            <div>
              <div style={{ fontSize: 12, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 12 }}>
                Permission Matrix
              </div>
              <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 12, overflowX: 'auto' }}>
                <div style={{
                  display: 'grid',
                  gridTemplateColumns: `2fr repeat(${roles.length}, minmax(80px, 1fr))`,
                  padding: '10px 20px', background: 'var(--surface-2)', borderBottom: '1px solid var(--border)',
                  minWidth: 600,
                }}>
                  <span style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>Permission</span>
                  {roles.map(r => (
                    <span key={r.id} style={{ textAlign: 'center' }}><RoleBadge roleId={r.id} roles={roles} /></span>
                  ))}
                </div>
                {permissionCatalog.map((perm, idx) => (
                  <div key={perm.id} style={{
                    display: 'grid',
                    gridTemplateColumns: `2fr repeat(${roles.length}, minmax(80px, 1fr))`,
                    padding: '12px 20px',
                    borderBottom: idx < permissionCatalog.length - 1 ? '1px solid var(--border)' : 'none',
                    minWidth: 600,
                  }}>
                    <div>
                      <span style={{ fontSize: 13, color: 'var(--text)' }}>{perm.label}</span>
                      <span style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', display: 'block', marginTop: 1 }}>{perm.id}</span>
                    </div>
                    {roles.map(r => {
                      const has = r.permissions.includes('__all__') || r.permissions.includes(perm.id);
                      return (
                        <div key={r.id} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
                          <span style={{
                            width: 22, height: 22, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center',
                            background: has ? `${r.color}20` : 'var(--surface-2)',
                            color: has ? r.color : 'var(--text-dim)', fontSize: 13, fontWeight: 700,
                            border: `1px solid ${has ? `${r.color}40` : 'var(--border)'}`,
                          }}>
                            {has ? '✓' : '–'}
                          </span>
                        </div>
                      );
                    })}
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      )}

      {/* ── THEMENBEREICHE / STRUCTURE TAB ── */}
      {tab === 'structure' && canManageStructure && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
          <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
            {can(currentUser, 'topic_areas:manage') && (
              <Btn variant="primary" icon="plus" onClick={startNewArea}>Neuer Themenbereich</Btn>
            )}
          </div>
          {structureError && (
            <div style={{ fontSize: 12, color: '#f87171', background: 'rgba(248,113,113,0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(248,113,113,0.2)' }}>{structureError}</div>
          )}
          {topicAreas.length === 0 && (
            <div style={{ padding: 24, textAlign: 'center', color: 'var(--text-muted)', fontSize: 13, background: 'var(--surface)', borderRadius: 12, border: '1px dashed var(--border)' }}>
              Noch keine Themenbereiche.
            </div>
          )}
          {topicAreas.map(area => {
            const areaSections = sections.filter(s => s.topicAreaId === area.id);
            const expanded = expandedArea === area.id;
            return (
              <div key={area.id} style={{
                background: 'var(--surface)', border: `1px solid ${area.color}30`,
                borderRadius: 12, borderTop: `3px solid ${area.color}`,
                overflow: 'hidden',
              }}>
                {/* Header */}
                <div style={{ padding: '16px 20px', display: 'flex', alignItems: 'flex-start', gap: 12 }}>
                  <button onClick={() => setExpandedArea(expanded ? null : area.id)}
                    style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', display: 'flex', alignItems: 'center', padding: 4 }}>
                    <Icon name={expanded ? 'chevronDown' : 'chevronRight'} size={14} />
                  </button>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                      <span style={{ width: 8, height: 8, borderRadius: '50%', background: area.color }} />
                      <span style={{ fontSize: 15, fontWeight: 600, color: 'var(--text)' }}>{area.label}</span>
                      <span style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)' }}>
                        {areaSections.length} {areaSections.length === 1 ? 'Section' : 'Sections'}
                      </span>
                    </div>
                    {area.description && (
                      <div style={{ fontSize: 12, color: 'var(--text-muted)', lineHeight: 1.5 }}>{area.description}</div>
                    )}
                  </div>
                  <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
                    {can(currentUser, 'sections:manage') && (
                      <Btn variant="secondary" size="sm" icon="plus" onClick={() => startNewSection(area.id)}>Section</Btn>
                    )}
                    {can(currentUser, 'topic_areas:manage') && (
                      <Btn variant="secondary" size="sm" icon="edit" onClick={() => startEditArea(area)}>Bearbeiten</Btn>
                    )}
                    {can(currentUser, 'topic_areas:manage') && (
                      <Btn variant="danger" size="sm" icon="trash" onClick={() => askDeleteArea(area)}
                        disabled={areaSections.length > 0}>
                        {areaSections.length > 0 ? `${areaSections.length} drin` : 'Löschen'}
                      </Btn>
                    )}
                  </div>
                </div>
                {/* Sections-Liste */}
                {expanded && (
                  <div style={{ borderTop: '1px solid var(--border)', padding: '8px 14px 12px 40px', display: 'flex', flexDirection: 'column', gap: 6 }}>
                    {areaSections.length === 0 ? (
                      <div style={{ fontSize: 12, color: 'var(--text-dim)', fontStyle: 'italic', padding: '8px 0' }}>
                        Keine Sections in diesem Themenbereich.
                      </div>
                    ) : areaSections.map(s => (
                      <div key={s.id} style={{
                        display: 'flex', alignItems: 'center', gap: 10, padding: '8px 12px',
                        background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 8,
                      }}>
                        <span style={{ width: 7, height: 7, borderRadius: '50%', background: s.color, flexShrink: 0 }} />
                        {s.short && (
                          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: s.color, fontWeight: 600, minWidth: 50 }}>{s.short}</span>
                        )}
                        <span style={{ flex: 1, fontSize: 13, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{s.label}</span>
                        {can(currentUser, 'sections:manage') && (
                          <>
                            <button onClick={() => startEditSection(s)}
                              title="Bearbeiten"
                              style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-dim)', padding: 4, display: 'flex' }}
                              onMouseEnter={e => e.currentTarget.style.color = 'var(--accent)'}
                              onMouseLeave={e => e.currentTarget.style.color = 'var(--text-dim)'}>
                              <Icon name="edit" size={13} />
                            </button>
                            <button onClick={() => askDeleteSection(s)}
                              title="Löschen"
                              style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-dim)', padding: 4, display: 'flex' }}
                              onMouseEnter={e => e.currentTarget.style.color = '#f87171'}
                              onMouseLeave={e => e.currentTarget.style.color = 'var(--text-dim)'}>
                              <Icon name="trash" size={13} />
                            </button>
                          </>
                        )}
                      </div>
                    ))}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      )}

      {/* ── SETTINGS TAB ── */}
      {tab === 'settings' && can(currentUser, 'settings:manage') && (
        <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 12, padding: '20px 24px' }}>
          {settings === null ? (
            <div style={{ color: 'var(--text-muted)', fontSize: 13 }}>Lade…</div>
          ) : (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
              {/* Self-registration */}
              <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 24 }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--text)' }}>Selbst-Registrierung</div>
                  <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 4, lineHeight: 1.5 }}>
                    Wenn aktiviert, können sich neue User selbst über die Login-Seite registrieren.
                    Wenn deaktiviert, ist <code style={{ fontFamily: 'var(--font-mono)' }}>POST /api/auth/register</code> blockiert
                    und der Registrieren-Link verschwindet auf der Login-Seite. Manuelles Anlegen über den Nutzer-Tab funktioniert weiter.
                  </div>
                </div>
                <button
                  onClick={() => updateSetting('registrationEnabled', !settings.registrationEnabled)}
                  disabled={savingSetting === 'registrationEnabled'}
                  style={{
                    flexShrink: 0,
                    width: 46, height: 26, padding: 0, borderRadius: 13,
                    border: '1px solid var(--border)',
                    background: settings.registrationEnabled ? 'var(--accent)' : 'var(--surface-2)',
                    cursor: savingSetting === 'registrationEnabled' ? 'wait' : 'pointer',
                    position: 'relative', transition: 'background 0.15s',
                    opacity: savingSetting === 'registrationEnabled' ? 0.6 : 1,
                  }}
                  aria-pressed={settings.registrationEnabled}>
                  <span style={{
                    position: 'absolute', top: 2, left: settings.registrationEnabled ? 22 : 2,
                    width: 20, height: 20, borderRadius: '50%',
                    background: '#fff', transition: 'left 0.15s',
                    boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
                  }} />
                </button>
              </div>

              {/* Default role */}
              <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 24 }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--text)' }}>Standard-Rolle bei Selbst-Registrierung</div>
                  <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 4, lineHeight: 1.5 }}>
                    Welche Rolle bekommen neue User automatisch? Greift auch beim Anlegen über die Admin-UI ohne explizite Rollen-Auswahl.
                  </div>
                </div>
                <select
                  value={settings.defaultRoleId || ''}
                  disabled={savingSetting === 'defaultRoleId'}
                  onChange={e => updateSetting('defaultRoleId', e.target.value)}
                  style={{
                    minWidth: 180, padding: '8px 12px', borderRadius: 6,
                    border: '1px solid var(--border)', background: 'var(--surface-2)',
                    color: 'var(--text)', fontSize: 13, fontFamily: 'var(--font-sans)',
                  }}>
                  {roles.map(r => (
                    <option key={r.id} value={r.id}>{r.label}{r.isSystem ? ' (System)' : ''}</option>
                  ))}
                </select>
              </div>

              {/* Wartungsmodus */}
              <div style={{ borderTop: '1px solid var(--border)', paddingTop: 22, marginTop: 4 }}>
                <div style={{ fontSize: 12, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 14 }}>
                  Wartungsmodus
                </div>

                {/* App-Auswahl */}
                <div style={{ marginBottom: 18 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--text)', marginBottom: 4 }}>Apps in Wartung</div>
                  <div style={{ fontSize: 12, color: 'var(--text-muted)', marginBottom: 10, lineHeight: 1.5 }}>
                    Wähle, welche Apps in Wartung gehen sollen. <code style={{ fontFamily: 'var(--font-mono)' }}>Hub</code> sperrt alles (globaler Lockdown), die anderen wirken nur app-spezifisch.
                    User ohne <code style={{ fontFamily: 'var(--font-mono)' }}>system:bypass_maintenance</code>-Permission sehen die Wartungs-Seite. Admins haben den Bypass automatisch.
                  </div>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 8 }}>
                    {MAINT_APPS.map(app => {
                      const apps = Array.isArray(settings?.maintenanceApps) ? settings.maintenanceApps : [];
                      const checked = apps.includes(app.id);
                      const saving = savingSetting === 'maintenanceApps';
                      return (
                        <label key={app.id} style={{
                          display: 'flex', alignItems: 'center', gap: 10,
                          padding: '10px 12px', borderRadius: 8,
                          border: `1px solid ${checked ? '#fb923c' : 'var(--border)'}`,
                          background: checked ? 'rgba(251,146,60,0.10)' : 'var(--surface-2)',
                          cursor: saving ? 'wait' : 'pointer',
                          opacity: saving ? 0.6 : 1,
                          transition: 'background 0.15s, border-color 0.15s',
                        }}>
                          <input type="checkbox" checked={checked}
                            onChange={() => !saving && toggleMaintenanceApp(app.id)}
                            disabled={saving}
                            style={{ accentColor: '#fb923c', width: 16, height: 16, cursor: 'inherit' }} />
                          <div style={{ flex: 1, minWidth: 0 }}>
                            <div style={{ fontSize: 13, fontWeight: 600, color: checked ? '#fb923c' : 'var(--text)' }}>
                              {app.label}
                            </div>
                            <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 1 }}>
                              {app.hint}
                            </div>
                          </div>
                        </label>
                      );
                    })}
                  </div>
                </div>

                {/* Pre-Banner: Schedule */}
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 140px', gap: 12, marginBottom: 14 }}>
                  <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                    <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--text)' }}>Geplant für</span>
                    <input type="datetime-local"
                      value={maintDrafts.scheduledAt}
                      onChange={e => setMaintDrafts(d => ({ ...d, scheduledAt: e.target.value }))}
                      style={{
                        padding: '8px 10px', borderRadius: 6, border: '1px solid var(--border)',
                        background: 'var(--surface-2)', color: 'var(--text)', fontSize: 13,
                        fontFamily: 'var(--font-sans)',
                      }} />
                  </label>
                  <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                    <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--text)' }}>Dauer (Min)</span>
                    <input type="number" min={0} step={5}
                      value={maintDrafts.duration}
                      onChange={e => setMaintDrafts(d => ({ ...d, duration: e.target.value }))}
                      style={{
                        padding: '8px 10px', borderRadius: 6, border: '1px solid var(--border)',
                        background: 'var(--surface-2)', color: 'var(--text)', fontSize: 13,
                        fontFamily: 'var(--font-mono)',
                      }} />
                  </label>
                </div>

                <label style={{ display: 'flex', flexDirection: 'column', gap: 4, marginBottom: 10 }}>
                  <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--text)' }}>Nachricht (optional)</span>
                  <input type="text"
                    placeholder="z. B. „Wir spielen v0.7.1 ein."
                    value={maintDrafts.message}
                    onChange={e => setMaintDrafts(d => ({ ...d, message: e.target.value }))}
                    style={{
                      padding: '8px 10px', borderRadius: 6, border: '1px solid var(--border)',
                      background: 'var(--surface-2)', color: 'var(--text)', fontSize: 13,
                      fontFamily: 'var(--font-sans)',
                    }} />
                </label>

                <div style={{ fontSize: 11, color: 'var(--text-dim)', lineHeight: 1.5 }}>
                  Solange ein Termin gesetzt ist und in der Zukunft liegt, sehen alle User einen blauen Pre-Banner.
                  Der Banner verschwindet automatisch, wenn der Termin erreicht wird oder die Wartung an ist.
                  „Verstanden"-Klick versteckt ihn nur für die aktuelle Session.
                </div>
              </div>

              {settingsError && (
                <div style={{ fontSize: 12, color: '#f87171', background: 'rgba(248,113,113,0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(248,113,113,0.2)' }}>{settingsError}</div>
              )}
            </div>
          )}
        </div>
      )}

      {/* ── AUDIT TAB ── */}
      {tab === 'audit' && can(currentUser, 'audit:read') && (
        <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 12, padding: '20px 24px' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16, flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ fontSize: 12, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>Aktion:</span>
              <select value={auditFilter.action} onChange={e => { setAuditFilter(f => ({ ...f, action: e.target.value })); setAuditPage(0); }}
                style={{ background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text)', fontSize: 12, padding: '5px 8px', fontFamily: 'var(--font-mono)' }}>
                <option value="">— alle —</option>
                <option value="auth.login">auth.login</option>
                <option value="auth.login.fail">auth.login.fail</option>
                <option value="auth.register">auth.register</option>
                <option value="auth.verify_email">auth.verify_email</option>
                <option value="auth.password_reset">auth.password_reset</option>
                <option value="user.create">user.create</option>
                <option value="user.update_role">user.update_role</option>
                <option value="user.delete">user.delete</option>
                <option value="role.create">role.create</option>
                <option value="role.update">role.update</option>
                <option value="role.delete">role.delete</option>
                <option value="settings.update">settings.update</option>
                <option value="audit.export">audit.export</option>
              </select>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ fontSize: 12, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>von:</span>
              <input type="date" value={auditFilter.from}
                onChange={e => { setAuditFilter(f => ({ ...f, from: e.target.value })); setAuditPage(0); }}
                style={{ background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text)', fontSize: 12, padding: '4px 8px', fontFamily: 'var(--font-mono)' }} />
              <span style={{ fontSize: 12, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>bis:</span>
              <input type="date" value={auditFilter.to}
                onChange={e => { setAuditFilter(f => ({ ...f, to: e.target.value })); setAuditPage(0); }}
                style={{ background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text)', fontSize: 12, padding: '4px 8px', fontFamily: 'var(--font-mono)' }} />
              {(auditFilter.from || auditFilter.to || auditFilter.action || auditFilter.userId) && (
                <button onClick={() => { setAuditFilter({ action: '', userId: '', from: '', to: '' }); setAuditPage(0); }}
                  style={{ padding: '4px 8px', background: 'transparent', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text-muted)', fontSize: 11, cursor: 'pointer', fontFamily: 'var(--font-mono)' }}
                  title="Filter zurücksetzen">
                  ✕
                </button>
              )}
            </div>
            <div style={{ flex: 1 }} />
            <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{auditTotal} Einträge</div>
            <button onClick={exportAuditCsv} disabled={auditExporting || auditTotal === 0}
              style={{ padding: '5px 10px', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text)', fontSize: 12, cursor: auditExporting || auditTotal === 0 ? 'not-allowed' : 'pointer', opacity: auditExporting || auditTotal === 0 ? 0.5 : 1 }}
              title="Aktuellen Filter als CSV exportieren">
              {auditExporting ? '…' : '↓ CSV'}
            </button>
            <button onClick={loadAudit} disabled={auditLoading}
              style={{ padding: '5px 10px', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text)', fontSize: 12, cursor: 'pointer' }}>
              {auditLoading ? '…' : '⟳ Refresh'}
            </button>
          </div>
          <div style={{ overflowX: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--border)' }}>
                  <th style={{ textAlign: 'left', padding: '8px 10px', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontWeight: 500 }}>Zeitpunkt</th>
                  <th style={{ textAlign: 'left', padding: '8px 10px', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontWeight: 500 }}>User</th>
                  <th style={{ textAlign: 'left', padding: '8px 10px', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontWeight: 500 }}>Aktion</th>
                  <th style={{ textAlign: 'left', padding: '8px 10px', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontWeight: 500 }}>Ziel</th>
                  <th style={{ textAlign: 'left', padding: '8px 10px', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontWeight: 500 }}>Details</th>
                  <th style={{ textAlign: 'left', padding: '8px 10px', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontWeight: 500 }}>IP</th>
                </tr>
              </thead>
              <tbody>
                {auditEntries.length === 0 && !auditLoading && (
                  <tr><td colSpan={6} style={{ padding: 24, textAlign: 'center', color: 'var(--text-muted)' }}>Keine Einträge.</td></tr>
                )}
                {auditEntries.map(e => (
                  <tr key={e.id} style={{ borderBottom: '1px solid var(--border)' }}>
                    <td style={{ padding: '8px 10px', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', whiteSpace: 'nowrap' }}>
                      {new Date(e.createdAt).toLocaleString('de-DE')}
                    </td>
                    <td style={{ padding: '8px 10px' }}>
                      {e.userName ? (
                        <div style={{ color: 'var(--text)' }}>{e.userName}<div style={{ fontSize: 10, color: 'var(--text-muted)' }}>{e.userEmail}</div></div>
                      ) : <span style={{ color: 'var(--text-dim)' }}>—</span>}
                    </td>
                    <td style={{ padding: '8px 10px', fontFamily: 'var(--font-mono)', color: e.action.includes('fail') || e.action.includes('delete') ? '#f87171' : 'var(--accent)' }}>
                      {e.action}
                    </td>
                    <td style={{ padding: '8px 10px', fontFamily: 'var(--font-mono)', color: 'var(--text-muted)' }}>
                      {e.targetType ? `${e.targetType}:${e.targetId || '—'}` : '—'}
                    </td>
                    <td style={{ padding: '8px 10px', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-muted)', maxWidth: 320, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={e.meta ? JSON.stringify(e.meta) : ''}>
                      {e.meta ? JSON.stringify(e.meta) : '—'}
                    </td>
                    <td style={{ padding: '8px 10px', fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', fontSize: 11 }}>
                      {e.ipAddress || '—'}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          {auditTotal > AUDIT_PAGE_SIZE && (
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 16 }}>
              <button onClick={() => setAuditPage(p => Math.max(0, p - 1))} disabled={auditPage === 0}
                style={{ padding: '6px 12px', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text)', fontSize: 12, cursor: auditPage === 0 ? 'not-allowed' : 'pointer', opacity: auditPage === 0 ? 0.5 : 1 }}>
                ← Vorherige
              </button>
              <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>
                Seite {auditPage + 1} von {Math.ceil(auditTotal / AUDIT_PAGE_SIZE)}
              </span>
              <button onClick={() => setAuditPage(p => p + 1)} disabled={(auditPage + 1) * AUDIT_PAGE_SIZE >= auditTotal}
                style={{ padding: '6px 12px', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--text)', fontSize: 12, cursor: (auditPage + 1) * AUDIT_PAGE_SIZE >= auditTotal ? 'not-allowed' : 'pointer', opacity: (auditPage + 1) * AUDIT_PAGE_SIZE >= auditTotal ? 0.5 : 1 }}>
                Nächste →
              </button>
            </div>
          )}
        </div>
      )}

      {/* Add User Modal */}
      <Modal open={showAddUser} onClose={() => { setShowAddUser(false); setAddError(''); }} title="Neuen Nutzer hinzufügen">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div>
            <label style={{ fontSize: 12, color: 'var(--text-muted)', display: 'block', marginBottom: 5, fontFamily: 'var(--font-mono)' }}>Name</label>
            <Input value={newUser.name} onChange={e => setNewUser(u => ({ ...u, name: e.target.value }))} placeholder="Max Mustermann" icon="user" />
          </div>
          <div>
            <label style={{ fontSize: 12, color: 'var(--text-muted)', display: 'block', marginBottom: 5, fontFamily: 'var(--font-mono)' }}>E-Mail</label>
            <Input type="email" value={newUser.email} onChange={e => setNewUser(u => ({ ...u, email: e.target.value }))} placeholder="max@schule.de" />
          </div>
          <div>
            <label style={{ fontSize: 12, color: 'var(--text-muted)', display: 'block', marginBottom: 5, fontFamily: 'var(--font-mono)' }}>Passwort</label>
            <Input type="password" value={newUser.password} onChange={e => setNewUser(u => ({ ...u, password: e.target.value }))} placeholder="••••••••" icon="lock" />
          </div>
          <div>
            <label style={{ fontSize: 12, color: 'var(--text-muted)', display: 'block', marginBottom: 8, fontFamily: 'var(--font-mono)' }}>Rolle</label>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
              {roles.map(r => (
                <button key={r.id} type="button" onClick={() => setNewUser(u => ({ ...u, role: r.id }))}
                  style={{
                    padding: '8px 12px', borderRadius: 8, cursor: 'pointer',
                    border: `1px solid ${newUser.role === r.id ? r.color : 'var(--border)'}`,
                    background: newUser.role === r.id ? `${r.color}15` : 'transparent',
                    color: newUser.role === r.id ? r.color : 'var(--text-muted)',
                    fontSize: 12, fontFamily: 'var(--font-sans)', fontWeight: newUser.role === r.id ? 600 : 400,
                    minWidth: 110,
                  }}>
                  <div style={{ fontWeight: 600, marginBottom: 2 }}>{r.label}{r.isSystem ? ' 🔒' : ''}</div>
                  <div style={{ fontSize: 10, opacity: 0.8 }}>
                    {r.permissions.includes('__all__') ? 'alle Rechte' : `${r.permissions.length} Rechte`}
                  </div>
                </button>
              ))}
            </div>
          </div>
          {addError && (
            <div style={{ fontSize: 12, color: '#f87171', background: 'rgba(248,113,113,0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(248,113,113,0.2)' }}>{addError}</div>
          )}
          <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 4 }}>
            <Btn variant="secondary" onClick={() => { setShowAddUser(false); setAddError(''); }}>Abbrechen</Btn>
            <Btn variant="primary" icon="plus" onClick={handleAddUser}>Hinzufügen</Btn>
          </div>
        </div>
      </Modal>

      {/* Delete User Confirm */}
      <Modal open={!!confirmDelete} onClose={() => setConfirmDelete(null)} title="Nutzer löschen?">
        <p style={{ color: 'var(--text-muted)', fontSize: 13, margin: '0 0 20px' }}>
          Möchtest du <strong style={{ color: 'var(--text)' }}>„{confirmDelete?.name}"</strong> ({confirmDelete?.email}) wirklich löschen? Das kann nicht rückgängig gemacht werden.
        </p>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <Btn variant="secondary" onClick={() => setConfirmDelete(null)}>Abbrechen</Btn>
          <Btn variant="danger" icon="trash" onClick={() => handleDelete(confirmDelete.id)}>Löschen</Btn>
        </div>
      </Modal>

      {/* Role Editor Modal */}
      <Modal
        open={!!editingRole}
        onClose={cancelRole}
        title={editingRole?.isNew ? 'Neue Rolle' : `Rolle bearbeiten: ${editingRole?.label || ''}`}
        width={620}
      >
        {editingRole && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div style={{ display: 'flex', gap: 12 }}>
              <div style={{ flex: 1 }}>
                <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Label</label>
                <Input value={editingRole.label} onChange={e => setEditingRole(p => ({ ...p, label: e.target.value }))} placeholder="z. B. Berufsschule-Lehrer" />
              </div>
              <div>
                <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Farbe</label>
                <input type="color" value={editingRole.color}
                  onChange={e => setEditingRole(p => ({ ...p, color: e.target.value }))}
                  style={{ width: 56, height: 38, border: '1px solid var(--border)', borderRadius: 6, background: 'var(--surface-2)', cursor: 'pointer', padding: 0 }} />
              </div>
            </div>
            <div>
              <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Beschreibung</label>
              <textarea value={editingRole.description}
                onChange={e => setEditingRole(p => ({ ...p, description: e.target.value }))}
                rows={2}
                style={{
                  width: '100%', boxSizing: 'border-box', padding: '8px 12px',
                  background: 'var(--surface-2)', border: '1px solid var(--border)',
                  borderRadius: 'var(--radius)', color: 'var(--text)',
                  fontFamily: 'var(--font-sans)', fontSize: 13, resize: 'vertical', outline: 'none',
                }} />
            </div>
            <div>
              <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Themenbereich (Scope)</label>
              <select
                value={editingRole.topicAreaId || ''}
                disabled={editingRole.isSystem}
                onChange={e => setEditingRole(p => ({ ...p, topicAreaId: e.target.value || null }))}
                style={{
                  width: '100%', boxSizing: 'border-box', padding: '8px 12px',
                  background: 'var(--surface-2)', border: '1px solid var(--border)',
                  borderRadius: 'var(--radius)', color: 'var(--text)',
                  fontFamily: 'var(--font-sans)', fontSize: 13,
                  opacity: editingRole.isSystem ? 0.6 : 1,
                  cursor: editingRole.isSystem ? 'not-allowed' : 'pointer',
                }}>
                <option value="">Global (alle Bereiche)</option>
                {topicAreas.map(a => (
                  <option key={a.id} value={a.id}>{a.label}</option>
                ))}
              </select>
              <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 4 }}>
                Inhalts-Permissions (Notes/Deadlines/Flashcards) gelten nur in diesem Bereich. Verwaltungs-Permissions sind immer global.
              </div>
            </div>
            <div>
              <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 8 }}>Permissions</label>
              {editingRole.isSystem && (
                <div style={{ fontSize: 12, color: 'var(--text-muted)', background: 'var(--surface-2)', padding: '8px 12px', borderRadius: 6, marginBottom: 10, border: '1px solid var(--border)' }}>
                  <Icon name="lock" size={12} /> System-Rolle: Permissions sind fest („alle"), Bereich immer global. Label, Farbe, Beschreibung und 2FA-Pflicht pro Permission sind editierbar.
                </div>
              )}
              <div style={{ fontSize: 11, color: 'var(--text-muted)', marginBottom: 8, lineHeight: 1.5 }}>
                <Icon name="lock" size={11} /> Klick aufs Schloss neben einer Permission, damit User mit dieser Rolle für diese Aktion 2FA aktiviert haben müssen.
              </div>
              <PermissionCheckboxes
                catalog={permissionCatalog}
                selected={editingRole.permissions}
                onChange={perms => setEditingRole(p => ({ ...p, permissions: perms }))}
                disabled={editingRole.isSystem}
                requires2FA={editingRole.permissions2FA || []}
                onRequires2FAChange={perms2fa => setEditingRole(p => ({ ...p, permissions2FA: perms2fa }))}
              />
            </div>
            {roleError && (
              <div style={{ fontSize: 12, color: '#f87171', background: 'rgba(248,113,113,0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(248,113,113,0.2)' }}>{roleError}</div>
            )}
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
              <Btn variant="secondary" onClick={cancelRole}>Abbrechen</Btn>
              <Btn variant="primary" icon="check" onClick={saveRole} disabled={!editingRole.label.trim()}>Speichern</Btn>
            </div>
          </div>
        )}
      </Modal>

      {/* Delete Role Confirm */}
      <Modal open={!!confirmDeleteRole} onClose={() => setConfirmDeleteRole(null)} title="Rolle löschen?">
        <p style={{ color: 'var(--text-muted)', fontSize: 13, margin: '0 0 20px' }}>
          Rolle <strong style={{ color: 'var(--text)' }}>„{confirmDeleteRole?.label}"</strong> wirklich löschen?
        </p>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <Btn variant="secondary" onClick={() => setConfirmDeleteRole(null)}>Abbrechen</Btn>
          <Btn variant="danger" icon="trash" onClick={doDeleteRole}>Löschen</Btn>
        </div>
      </Modal>

      {/* Topic Area Editor Modal */}
      <Modal open={!!editingArea} onClose={cancelArea}
        title={editingArea?.isNew ? 'Neuer Themenbereich' : `Themenbereich bearbeiten: ${editingArea?.label || ''}`}
        width={520}>
        {editingArea && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div style={{ display: 'flex', gap: 12 }}>
              <div style={{ flex: 1 }}>
                <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Label</label>
                <Input value={editingArea.label} onChange={e => setEditingArea(p => ({ ...p, label: e.target.value }))} placeholder="z. B. Homelab" />
              </div>
              <div>
                <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Farbe</label>
                <input type="color" value={editingArea.color}
                  onChange={e => setEditingArea(p => ({ ...p, color: e.target.value }))}
                  style={{ width: 56, height: 38, border: '1px solid var(--border)', borderRadius: 6, background: 'var(--surface-2)', cursor: 'pointer', padding: 0 }} />
              </div>
            </div>
            <div>
              <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Beschreibung</label>
              <textarea value={editingArea.description}
                onChange={e => setEditingArea(p => ({ ...p, description: e.target.value }))}
                rows={2}
                style={{
                  width: '100%', boxSizing: 'border-box', padding: '8px 12px',
                  background: 'var(--surface-2)', border: '1px solid var(--border)',
                  borderRadius: 'var(--radius)', color: 'var(--text)',
                  fontFamily: 'var(--font-sans)', fontSize: 13, resize: 'vertical', outline: 'none',
                }} />
            </div>
            {structureError && (
              <div style={{ fontSize: 12, color: '#f87171', background: 'rgba(248,113,113,0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(248,113,113,0.2)' }}>{structureError}</div>
            )}
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
              <Btn variant="secondary" onClick={cancelArea}>Abbrechen</Btn>
              <Btn variant="primary" icon="check" onClick={saveArea} disabled={!editingArea.label.trim()}>Speichern</Btn>
            </div>
          </div>
        )}
      </Modal>

      {/* Section Editor Modal */}
      <Modal open={!!editingSection} onClose={cancelSection}
        title={editingSection?.isNew ? 'Neue Section' : `Section bearbeiten: ${editingSection?.label || ''}`}
        width={560}>
        {editingSection && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div>
              <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Themenbereich</label>
              <select value={editingSection.topicAreaId}
                onChange={e => setEditingSection(p => ({ ...p, topicAreaId: e.target.value }))}
                style={{
                  width: '100%', boxSizing: 'border-box', padding: '8px 12px',
                  background: 'var(--surface-2)', border: '1px solid var(--border)',
                  borderRadius: 'var(--radius)', color: 'var(--text)',
                  fontFamily: 'var(--font-sans)', fontSize: 13,
                }}>
                {topicAreas.map(a => <option key={a.id} value={a.id}>{a.label}</option>)}
              </select>
            </div>
            <div style={{ display: 'flex', gap: 12 }}>
              <div style={{ width: 130 }}>
                <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Kürzel (optional)</label>
                <Input value={editingSection.short} onChange={e => setEditingSection(p => ({ ...p, short: e.target.value }))} placeholder="LF 03" />
              </div>
              <div style={{ flex: 1 }}>
                <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Label</label>
                <Input value={editingSection.label} onChange={e => setEditingSection(p => ({ ...p, label: e.target.value }))} placeholder="Clients in Netzwerke einbinden" />
              </div>
              <div>
                <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Farbe</label>
                <input type="color" value={editingSection.color}
                  onChange={e => setEditingSection(p => ({ ...p, color: e.target.value }))}
                  style={{ width: 56, height: 38, border: '1px solid var(--border)', borderRadius: 6, background: 'var(--surface-2)', cursor: 'pointer', padding: 0 }} />
              </div>
            </div>
            <div>
              <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Beschreibung</label>
              <textarea value={editingSection.description}
                onChange={e => setEditingSection(p => ({ ...p, description: e.target.value }))}
                rows={2}
                style={{
                  width: '100%', boxSizing: 'border-box', padding: '8px 12px',
                  background: 'var(--surface-2)', border: '1px solid var(--border)',
                  borderRadius: 'var(--radius)', color: 'var(--text)',
                  fontFamily: 'var(--font-sans)', fontSize: 13, resize: 'vertical', outline: 'none',
                }} />
            </div>
            <div>
              <label style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 5 }}>Sortierung</label>
              <input type="number" value={editingSection.sortOrder}
                onChange={e => setEditingSection(p => ({ ...p, sortOrder: Number(e.target.value) || 0 }))}
                style={{
                  width: 120, boxSizing: 'border-box', padding: '8px 12px',
                  background: 'var(--surface-2)', border: '1px solid var(--border)',
                  borderRadius: 'var(--radius)', color: 'var(--text)',
                  fontFamily: 'var(--font-mono)', fontSize: 13,
                }} />
              <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 4 }}>Niedrigere Werte sind in der Sidebar weiter oben.</div>
            </div>
            {structureError && (
              <div style={{ fontSize: 12, color: '#f87171', background: 'rgba(248,113,113,0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(248,113,113,0.2)' }}>{structureError}</div>
            )}
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
              <Btn variant="secondary" onClick={cancelSection}>Abbrechen</Btn>
              <Btn variant="primary" icon="check" onClick={saveSection} disabled={!editingSection.label.trim()}>Speichern</Btn>
            </div>
          </div>
        )}
      </Modal>

      {/* Delete Area Confirm */}
      <Modal open={!!confirmDeleteArea} onClose={() => setConfirmDeleteArea(null)} title="Themenbereich löschen?">
        <p style={{ color: 'var(--text-muted)', fontSize: 13, margin: '0 0 20px' }}>
          Themenbereich <strong style={{ color: 'var(--text)' }}>„{confirmDeleteArea?.label}"</strong> wirklich löschen?
        </p>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <Btn variant="secondary" onClick={() => setConfirmDeleteArea(null)}>Abbrechen</Btn>
          <Btn variant="danger" icon="trash" onClick={doDeleteArea}>Löschen</Btn>
        </div>
      </Modal>

      {/* Delete Section Confirm */}
      <Modal open={!!confirmDeleteSection} onClose={() => setConfirmDeleteSection(null)} title="Section löschen?">
        <p style={{ color: 'var(--text-muted)', fontSize: 13, margin: '0 0 20px' }}>
          Section <strong style={{ color: 'var(--text)' }}>„{confirmDeleteSection?.label}"</strong> wirklich löschen?
        </p>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <Btn variant="secondary" onClick={() => setConfirmDeleteSection(null)}>Abbrechen</Btn>
          <Btn variant="danger" icon="trash" onClick={doDeleteSection}>Löschen</Btn>
        </div>
      </Modal>
    </Wrapper>
  );
};

Object.assign(window, { AdminPanel, RoleBadge });
