feat(design): AegisSight-Design, Lucide-Icons und aufgeräumter Verbrauchs-Bereich

Drei Pakete auf Nutzerwunsch.

1. Design-Angleichung an das AegisSight-Design-System. Navy/Gold-Token
   statt Slate/Amber, Light- UND Dark-Theme mit goldenem Schiebeschalter
   oben rechts (Dark = Standard, Wahl persistiert), Barrierefreiheits-
   Panel über js/a11y.js (identische Datei wie im Monitor), echtes Logo
   mit heller Plakette in Kopfzeile und Login, Poppins/Inter-Typografie,
   Radius 6/8 nach Styleguide. Automatisch erzeugte Light-Theme-
   Überschreibungen für alle Badge-Pastelltöne.
2. Lucide-Icons (Inline-SVG, keine externen Quellen) für alle
   Navigations-Tabs inkl. nachgeladenem Verbrauchsrechner, die
   Anlege-Knöpfe, Abmelden und Speichern.
3. Verbrauchs-Bereich aufgeräumt. Reiter heißt jetzt Verbrauch,
   Statistik in Kundensicht (Credits) und Interne Kosten (Einkauf, USD)
   getrennt, Leiste heißt Kontingent-Auslastung, Sätze-Infozeile mit
   Sprung zum Verbrauchsrechner, Altmodus-Felder (USD) und die
   Verbrauchs-Korrektur liegen in einem eingeklappten Bereich
   Erweitert mit Erklärtext. Der Rechner trägt einen deutlichen
   Simulations-Hinweis. Lizenz verlängern nutzt ein eigenes Modal
   statt des Browser-prompt().

Cache-Buster auf 20260725 gebumpt, alle Restfarben tokenisiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-07-25 13:57:59 +00:00
Ursprung eeb74c74c1
Commit 8fd087ea0c
7 geänderte Dateien mit 654 neuen und 80 gelöschten Zeilen

Datei anzeigen

@@ -6,32 +6,63 @@
<title>AegisSight Monitor-Verwaltung</title>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<link rel="apple-touch-icon" href="/static/favicon.svg">
<link rel="stylesheet" href="/static/css/style.css?v=20260509d">
<link rel="stylesheet" href="/static/css/style.css?v=20260725a">
<script>(function(){var t=localStorage.getItem('portal_theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');try{var a=JSON.parse(localStorage.getItem('osint_a11y')||'{}');Object.keys(a).forEach(function(k){if(a[k])document.documentElement.setAttribute('data-a11y-'+k,'true');});}catch(e){}})()</script>
<style>
.source-badge { display:inline-block; padding:2px 8px; border-radius:4px; font-size:12px; font-weight:600; }
.badge-monitor { background:#e3f2fd; color:#1565c0; }
.badge-globe { background:#e8f5e9; color:#2e7d32; }
.badge-monitor { background:rgba(59,130,246,0.15); color:#93c5fd; }
.badge-globe { background:rgba(16,185,129,0.15); color:#86efac; }
[data-theme="light"] .badge-monitor { background:#e3f2fd; color:#1565c0; }
[data-theme="light"] .badge-globe { background:#e8f5e9; color:#2e7d32; }
</style>
</head>
<body>
<!-- Header -->
<header class="app-header">
<div class="logo">AegisSight <span>Monitor-Verwaltung</span></div>
<div class="logo">
<span class="logo-plaque"><img src="/static/favicon.svg" alt="AegisSight Logo"></span>
AegisSight <span>Monitor-Verwaltung</span>
</div>
<div class="header-right">
<div class="theme-switch dark" id="theme-toggle" onclick="ThemeManager.toggle()" role="switch" aria-checked="true" aria-label="Dark Mode" title="Theme wechseln">
<span class="theme-switch-icon theme-switch-sun">&#9728;&#65038;</span>
<div class="theme-switch-track">
<div class="theme-switch-knob"></div>
</div>
<span class="theme-switch-icon theme-switch-moon">&#9789;</span>
</div>
<span class="header-user" id="headerUser"></span>
<button class="btn btn-secondary btn-small" id="logoutBtn">Abmelden</button>
<button class="btn btn-secondary btn-small" id="logoutBtn">
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/></svg>
Abmelden
</button>
</div>
</header>
<main class="app-content">
<!-- Navigation -->
<!-- Navigation (Lucide-Icons, Strichstaerke 2 bei 15px) -->
<nav class="nav-tabs">
<button class="nav-tab active" data-section="dashboard">Dashboard</button>
<button class="nav-tab" data-section="orgs">Organisationen</button>
<button class="nav-tab" data-section="licenses">Lizenzen</button>
<button class="nav-tab" data-section="sources">Quellen</button>
<button class="nav-tab" data-section="audit">Audit-Log</button>
<button class="nav-tab active" data-section="dashboard">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></svg>
Dashboard
</button>
<button class="nav-tab" data-section="orgs">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z"/><path d="M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"/><path d="M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2"/><path d="M10 6h4"/><path d="M10 10h4"/><path d="M10 14h4"/><path d="M10 18h4"/></svg>
Organisationen
</button>
<button class="nav-tab" data-section="licenses">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 18v3c0 .6.4 1 1 1h4v-3h3v-3h2l1.4-1.4a6.5 6.5 0 1 0-4-4Z"/><circle cx="16.5" cy="7.5" r=".5"/></svg>
Lizenzen
</button>
<button class="nav-tab" data-section="sources">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1"/></svg>
Quellen
</button>
<button class="nav-tab" data-section="audit">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>
Audit-Log
</button>
</nav>
<!-- Dashboard Section -->
@@ -93,7 +124,7 @@
<div id="orgListView">
<div class="action-bar">
<input type="text" class="search-input" id="orgSearch" placeholder="Organisation suchen...">
<button class="btn btn-primary" id="newOrgBtn">+ Neue Organisation</button>
<button class="btn btn-primary" id="newOrgBtn"><svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Neue Organisation</button>
</div>
<div class="card">
<div class="table-wrap">
@@ -123,14 +154,14 @@
<button class="nav-tab active" data-subtab="users">Nutzer</button>
<button class="nav-tab" data-subtab="org-licenses">Lizenzen</button>
<button class="nav-tab" data-subtab="settings">Einstellungen</button>
<button class="nav-tab" data-subtab="tokens">Token-Nutzung</button>
<button class="nav-tab" data-subtab="tokens">Verbrauch</button>
</div>
<!-- Users Sub-Tab -->
<div class="section active" id="sub-users">
<div class="action-bar">
<span class="text-secondary" id="userLimitInfo"></span>
<button class="btn btn-primary" id="newUserBtn">+ Nutzer anlegen</button>
<button class="btn btn-primary" id="newUserBtn"><svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Nutzer anlegen</button>
</div>
<div class="card">
<div class="table-wrap">
@@ -155,7 +186,7 @@
<div class="section" id="sub-org-licenses">
<div class="action-bar">
<span></span>
<button class="btn btn-primary" id="newLicenseBtn">+ Neue Lizenz</button>
<button class="btn btn-primary" id="newLicenseBtn"><svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Neue Lizenz</button>
</div>
<div class="card">
<div class="table-wrap">
@@ -211,34 +242,46 @@
</div>
<div class="section" id="sub-tokens">
<div class="token-overview">
<!-- Kundensicht: das, was der Kunde im Monitor auch sieht -->
<h3 style="margin-bottom:8px;">Kundensicht (Credits)</h3>
<div class="token-stats-row" id="tokenStatsRow">
<div class="token-stat-card">
<div class="token-stat-label">Verbrauchte Credits</div>
<div class="token-stat-label">Verbrauchte Credits (Periode)</div>
<div class="token-stat-value" id="tokenCreditsUsed">-</div>
</div>
<div class="token-stat-card">
<div class="token-stat-label">Verbleibend</div>
<div class="token-stat-value" id="tokenCreditsRemaining">-</div>
</div>
<div class="token-stat-card">
<div class="token-stat-label">Budget (USD)</div>
<div class="token-stat-value" id="tokenBudgetUsd">-</div>
</div>
<div class="token-stat-card">
<div class="token-stat-label">Kosten (USD)</div>
<div class="token-stat-value" id="tokenCostUsd">-</div>
</div>
</div>
<div id="tokenSourceSplit" style="margin-top:12px;font-size:14px;"></div>
<div class="token-budget-bar-section">
<div class="token-budget-label">
<span>Budget-Auslastung</span>
<span>Kontingent-Auslastung (laufende Periode)</span>
<span id="tokenBudgetPercent">0%</span>
</div>
<div class="token-budget-bar-container">
<div class="token-budget-bar" id="tokenBudgetBar"></div>
</div>
</div>
<p style="margin-top:10px; font-size:12px; color:var(--text-muted); display:flex; align-items:center; gap:6px;">
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex-shrink:0;"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
<span>Zur Einordnung. Ein Live-Lauf kostet 45 Credits, das Anlegen einer Recherche 120 (drei Durchläufe), jede Vertiefung 40, Chat und Beschreibungs-Assistent je 1 Credit.
<a href="#" onclick="openRechnerTab(); return false;" style="color:var(--accent);">Verbrauchsrechner öffnen</a></span>
</p>
<!-- Interne Sicht: was uns der Betrieb im Einkauf kostet -->
<h3 style="margin-top:24px; margin-bottom:8px;">Interne Kosten (Einkauf, USD)</h3>
<div class="token-stats-row">
<div class="token-stat-card">
<div class="token-stat-label">API-Kosten aktueller Monat</div>
<div class="token-stat-value" id="tokenCostUsd">-</div>
</div>
<div class="token-stat-card">
<div class="token-stat-label">Budget-Limit (USD, Altmodus)</div>
<div class="token-stat-value" id="tokenBudgetUsd">-</div>
</div>
</div>
<div id="tokenSourceSplit" style="margin-top:12px;font-size:14px;"></div>
<h3 style="margin-top:24px;">Monatlicher Verlauf</h3>
<table class="data-table">
<thead>
@@ -255,11 +298,11 @@
<tbody id="tokenMonthlyTable"></tbody>
</table>
<h3 style="margin-top:24px;">Budget bearbeiten</h3>
<h3 style="margin-top:24px;">Credits-Kontingent bearbeiten</h3>
<div class="card" style="margin-top:12px;">
<div class="card-body">
<form id="tokenBudgetForm" style="display:grid; grid-template-columns:1fr 1fr; gap:12px;">
<div style="grid-column:1/-1; padding:8px 12px; background:var(--bg-tertiary,#0f172a); border-radius:6px; border:1px solid var(--border);">
<div style="grid-column:1/-1; padding:8px 12px; background:var(--bg-tertiary); border-radius:6px; border:1px solid var(--border);">
<label style="display:flex; align-items:center; gap:8px; cursor:pointer; margin:0;">
<input type="checkbox" id="editUnlimitedBudget" onchange="onUnlimitedToggle()">
<span><strong>Unbegrenztes Budget</strong> &mdash; Verbrauch wird trotzdem getrackt, aber kein Limit/Hard-Stop</span>
@@ -286,20 +329,37 @@
<label for="editWarnPercent">Warnschwelle (%)</label>
<input type="number" id="editWarnPercent" min="1" max="100" placeholder="80">
</div>
<div class="form-group">
<label for="editCostPerCredit">Kosten pro Credit (USD)</label>
<input type="number" id="editCostPerCredit" step="0.01" placeholder="0.20">
</div>
<div class="form-group">
<label for="editBudgetUsd">Budget-Limit (USD)</label>
<input type="number" id="editBudgetUsd" step="0.01" placeholder="z.B. 2000">
</div>
<div class="form-group">
<label for="editCreditsUsed">Verbrauchte Credits (laufende Periode)</label>
<input type="number" id="editCreditsUsed" step="0.01" placeholder="Aktueller Verbrauch">
</div>
<details class="adv-section">
<summary>
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
Erweitert (Altmodus und Korrektur)
</summary>
<p class="adv-hint">
Die beiden USD-Felder gehören zum alten Abrechnungsmodus (BILLING_MODE=actual)
und haben im heutigen Pauschalmodus keine Wirkung auf den Kunden. Das
Korrektur-Feld überschreibt den Verbrauch der laufenden Periode direkt,
nur für bewusste Eingriffe gedacht.
</p>
<div class="adv-grid" style="margin-top:10px;">
<div class="form-group">
<label for="editCostPerCredit">Kosten pro Credit (USD, nur Altmodus)</label>
<input type="number" id="editCostPerCredit" step="0.01" placeholder="0.20">
</div>
<div class="form-group">
<label for="editBudgetUsd">Budget-Limit (USD, nur Altmodus)</label>
<input type="number" id="editBudgetUsd" step="0.01" placeholder="z.B. 2000">
</div>
<div class="form-group">
<label for="editCreditsUsed">Verbrauch korrigieren (Credits, laufende Periode)</label>
<input type="number" id="editCreditsUsed" step="0.01" placeholder="Aktueller Verbrauch">
</div>
</div>
</details>
<div style="grid-column:1/-1; display:flex; gap:8px; align-items:center;">
<button type="submit" class="btn btn-primary">Speichern</button>
<button type="submit" class="btn btn-primary">
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
Speichern
</button>
<span id="tokenBudgetMsg" style="font-size:13px; color:var(--text-secondary);"></span>
</div>
</form>
@@ -786,6 +846,30 @@
</div>
<!-- Modal: Lizenz verlängern (ersetzt das alte Browser-prompt) -->
<div class="modal-overlay" id="modalExtendLicense">
<div class="modal">
<div class="modal-header">
<h3>Lizenz verlängern</h3>
<button class="modal-close" onclick="closeModal('modalExtendLicense')">&times;</button>
</div>
<form id="extendLicenseForm">
<div class="modal-body">
<div class="form-group">
<label for="extendDays">Um wie viele Tage verlängern?</label>
<input type="number" id="extendDays" value="365" min="1" max="3650" required>
<div class="text-muted mt-8" style="font-size:12px;">Die Verlängerung setzt am aktuellen Ablaufdatum an und aktiviert die Lizenz, falls sie abgelaufen war.</div>
</div>
<div id="extendLicenseError" class="error-msg" style="display:none"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeModal('modalExtendLicense')">Abbrechen</button>
<button type="submit" class="btn btn-primary">Verlängern</button>
</div>
</form>
</div>
</div>
<!-- Modal: Source (Create/Edit) -->
<div class="modal-overlay" id="modalSource">
<div class="modal">
@@ -1154,7 +1238,8 @@
</div>
</div>
<script src="/static/js/app.js?v=20260725a"></script>
<script src="/static/js/a11y.js?v=20260725a"></script>
<script src="/static/js/app.js?v=20260725b"></script>
<script src="/static/js/sources.js?v=20260522x2"></script>
<script src="/static/js/x-scraper.js?v=20260522a"></script>
<script src="/static/js/source-health.js?v=20260509l"></script>