root 7679efa7e4 feat(settings): eigene Unterseite für User-Einstellungen + Passwort-Wechsel
Header: Profil- und Modell-Dropdowns rausgenommen, dafür ein
"⚙ Einstellungen"-Link. Klick öffnet eine eigene Settings-View
(toggled die main-View aus) mit drei Sektionen:

- Standard-Profil (sofort speichernd)
- Standard-LLM-Modell (sofort speichernd, leer = Worker-Default)
- Passwort ändern (aktuelles + neues + Bestätigung)

Neuer Endpoint POST /api/auth/me/password — verlangt zwingend das
aktuelle Passwort (verhindert Übernahme via offene Browser-Session).
Admin-Reset über /api/admin/users/<id>/password bleibt unberührt.

Layout: Settings-View ist eine Card mit max-width 640px, jede
Sektion durch Trennlinie abgegrenzt. Inline-Status-Meldungen
("Standard-Profil ist jetzt: …") direkt unter den Controls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 20:40:28 +00:00

876 lines
22 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

:root {
--bg: #0f1115;
--card: #181c24;
--border: #262b36;
--text: #e6e8eb;
--muted: #8b93a3;
--accent: #4f8cff;
--accent-hover: #3a78f0;
--ok: #2ecc71;
--warn: #f1c40f;
--err: #e74c3c;
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.5;
}
header {
padding: 32px 24px 16px;
text-align: center;
border-bottom: 1px solid var(--border);
}
header h1 { margin: 0 0 4px; font-size: 28px; letter-spacing: .3px; }
.sub { color: var(--muted); margin: 0 0 12px; }
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 999px;
background: var(--card);
border: 1px solid var(--border);
font-size: 12px;
color: var(--muted);
}
.badge.ok { color: var(--ok); border-color: rgba(46,204,113,.4); }
.badge.err { color: var(--err); border-color: rgba(231,76,60,.4); }
main {
max-width: 1000px;
margin: 24px auto;
padding: 0 16px;
display: grid;
gap: 20px;
}
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 20px 22px;
}
.card h2 { margin-top: 0; font-size: 18px; }
form { display: grid; gap: 12px; }
label { display: grid; gap: 6px; font-size: 14px; color: var(--muted); }
input[type=text], input[type=file] {
background: #0f1219;
border: 1px solid var(--border);
color: var(--text);
padding: 10px 12px;
border-radius: 8px;
font-size: 14px;
}
button {
background: var(--accent);
color: white;
border: 0;
padding: 10px 16px;
border-radius: 8px;
font-size: 14px;
cursor: pointer;
justify-self: start;
}
button:hover { background: var(--accent-hover); }
button:disabled { opacity: .6; cursor: not-allowed; }
.hidden { display: none !important; }
.msg { min-height: 1em; margin: 8px 0 0; font-size: 13px; }
.msg.ok { color: var(--ok); }
.msg.err { color: var(--err); }
.muted { color: var(--muted); }
.bar {
width: 100%;
height: 8px;
background: #0f1219;
border-radius: 4px;
overflow: hidden;
margin-top: 6px;
}
.bar-fill {
height: 100%;
width: 0%;
background: var(--accent);
transition: width .25s ease;
}
table { width: 100%; border-collapse: collapse; font-size: 14px; table-layout: fixed; }
th, td { padding: 10px 8px; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; }
th { color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .5px; }
/* Spaltenbreiten — Status bekommt Platz für die Aktions-Buttons,
Updated wird schmaler weil das neue Format kürzer ist (Uhrzeit/dd.mm hh:mm) */
.col-id { width: 52px; }
.col-status { width: 170px; }
.col-progress { width: 110px; }
.col-updated { width: 78px; }
.col-dl { width: 320px; }
/* col-title nimmt den Rest */
.col-title { word-break: break-word; }
.col-title .job-title {
font-weight: 500;
line-height: 1.35;
font-size: 14px;
}
.col-title .job-tags {
margin-top: 3px;
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.col-title .job-tags:empty { display: none; }
.col-title .job-filename {
margin-top: 4px;
font-size: 11.5px;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
}
.col-title .job-owner { margin-top: 2px; font-size: 11.5px; }
.status-pill {
display: inline-block;
padding: 2px 10px;
border-radius: 999px;
font-size: 12px;
border: 1px solid var(--border);
white-space: nowrap;
}
.status-queued { color: var(--muted); }
.status-transcribing, .status-summarizing, .status-protocolling, .status-exporting { color: var(--warn); border-color: rgba(241,196,15,.4); }
.status-done { color: var(--ok); border-color: rgba(46,204,113,.4); }
.status-failed { color: var(--err); border-color: rgba(231,76,60,.4); }
/* Fehlertext unter dem Pill — bricht um, max. 3 Zeilen */
.status-error {
margin-top: 6px;
font-size: 11px;
color: var(--err);
line-height: 1.35;
word-break: break-word;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* Download-Buttons — 3-spaltiges Grid (5 Buttons → 2 Zeilen 3+2) */
.dl {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 6px;
}
.btn-dl {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 5px 10px;
border-radius: 6px;
background: rgba(79,140,255,.12);
border: 1px solid rgba(79,140,255,.4);
color: var(--accent);
text-decoration: none;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
transition: background .15s ease, border-color .15s ease;
}
.btn-dl:hover { background: rgba(79,140,255,.22); border-color: var(--accent); }
.btn-dl.disabled {
color: var(--muted);
background: transparent;
border-color: var(--border);
pointer-events: none;
opacity: .55;
}
footer { text-align: center; padding: 24px 16px 32px; }
/* ── Header-Layout ─────────────────────────────────────────────── */
.header-row {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
justify-content: space-between;
gap: 16px;
max-width: 1000px;
margin: 0 auto;
}
.header-left { text-align: left; }
.header-right { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.user-bar {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
}
.user-bar strong { color: var(--text); }
.btn-link {
background: transparent;
color: var(--accent);
border: 0;
padding: 2px 6px;
font-size: 13px;
cursor: pointer;
text-decoration: underline;
}
.btn-link:hover { color: var(--accent-hover); }
.btn-link.btn-danger { color: var(--err); }
.admin-badge {
background: rgba(79,140,255,.18);
color: var(--accent);
border-color: rgba(79,140,255,.45);
text-transform: uppercase;
font-size: 11px;
letter-spacing: .5px;
padding: 2px 8px;
}
/* ── Auth-Overlay ──────────────────────────────────────────────── */
.overlay {
position: fixed;
inset: 0;
background: rgba(15, 17, 21, .92);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
padding: 20px;
}
.auth-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 28px 28px 22px;
width: 100%;
max-width: 380px;
box-shadow: 0 20px 60px rgba(0,0,0,.4);
}
.auth-card h2 { margin: 0 0 8px; font-size: 20px; }
.auth-card #auth-info { font-size: 13px; margin: 0 0 14px; }
.auth-card form { display: grid; gap: 12px; }
.auth-card button { justify-self: stretch; }
/* ── Admin: Benutzer-Verwaltung ────────────────────────────────── */
.user-form {
display: grid;
grid-template-columns: 1fr 1fr auto auto;
gap: 12px;
align-items: end;
}
.user-form label { font-size: 13px; }
.inline-check {
display: flex !important;
flex-direction: row !important;
align-items: center;
gap: 6px;
color: var(--text);
}
.inline-check input { margin: 0; }
#users-table .user-actions {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
@media (max-width: 700px) {
.user-form { grid-template-columns: 1fr; }
}
/* Select-Felder im selben Stil wie Inputs */
select {
background: #0f1219;
border: 1px solid var(--border);
color: var(--text);
padding: 10px 12px;
border-radius: 8px;
font-size: 14px;
font-family: inherit;
}
/* Kompakter Profil-Selector im Header */
.header-profile-wrap {
display: inline-flex;
align-items: center;
gap: 6px;
}
.header-profile {
padding: 3px 6px;
font-size: 12px;
border-radius: 5px;
background: #0f1219;
border: 1px solid var(--border);
color: var(--text);
max-width: 180px;
}
.header-profile:disabled { opacity: .5; }
/* Aufnahme-Button (groß, rot, touch-tauglich) */
.btn-record {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
padding: 14px 18px;
background: rgba(231,76,60,.12);
color: var(--err);
border: 1px solid rgba(231,76,60,.5);
border-radius: 10px;
font-size: 15px;
font-weight: 600;
cursor: pointer;
min-height: 48px;
}
.btn-record:hover { background: rgba(231,76,60,.22); }
.rec-dot {
width: 12px; height: 12px;
background: var(--err);
border-radius: 50%;
}
/* Aufnahme-Bühne */
.record-pane {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 20px;
border: 1px solid rgba(231,76,60,.4);
background: rgba(231,76,60,.06);
border-radius: 12px;
margin-top: 6px;
}
.record-timer {
font-size: 44px;
font-variant-numeric: tabular-nums;
font-weight: 600;
color: var(--err);
letter-spacing: .04em;
}
.record-status { color: var(--muted); font-size: 13px; }
.record-status::before {
content: "● ";
color: var(--err);
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .25; } }
.record-controls { display: flex; gap: 10px; margin-top: 6px; }
.btn-record-ctrl {
padding: 12px 22px;
border-radius: 8px;
background: var(--card);
color: var(--text);
border: 1px solid var(--border);
font-size: 15px;
cursor: pointer;
min-height: 44px;
min-width: 100px;
}
.btn-record-ctrl.danger {
background: var(--err);
color: white;
border-color: var(--err);
}
/* Aufnahme-Ergebnis */
.record-result {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
background: rgba(46,204,113,.08);
border: 1px solid rgba(46,204,113,.4);
border-radius: 8px;
font-size: 13px;
}
/* ── Sichtbarkeit-Helfer ───────────────────────────────────────── */
.mobile-only { display: none; }
/* Upload-Form Layout (Desktop) */
.upload-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
align-items: end; /* Labels unten bündig → Inputs auf gleicher Höhe */
}
.upload-meta > label {
display: flex;
flex-direction: column;
gap: 4px; /* einheitlicher Abstand zwischen Label-Text und Control */
}
.audio-file-details summary {
cursor: pointer;
padding: 8px 4px;
color: var(--muted);
font-size: 13px;
user-select: none;
}
.audio-file-details summary:hover { color: var(--text); }
.audio-file-details[open] summary { color: var(--text); margin-bottom: 8px; }
.audio-file-label {
display: grid;
gap: 6px;
}
/* Admin-Toggle (auf Desktop deaktiviert) */
.admin-toggle { cursor: default; }
.admin-toggle-icon { display: none; }
/* ── Settings-Subpage ─────────────────────────────────────────── */
.settings-view { max-width: 640px; }
.settings-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
margin-bottom: 4px;
}
.settings-head h2 { margin: 0; }
.settings-section {
padding: 14px 0;
border-top: 1px solid var(--border);
}
.settings-section:first-of-type { border-top: 0; }
.settings-section h3 {
margin: 0 0 4px 0;
font-size: 14px;
font-weight: 600;
}
.settings-section p.muted { margin: 0 0 10px 0; font-size: 12.5px; }
.settings-input {
display: block;
width: 100%;
max-width: 380px;
padding: 7px 10px;
background: rgba(0,0,0,.25);
border: 1px solid var(--border);
color: inherit;
border-radius: 4px;
font-size: 14px;
}
#settings-pw-form { display: flex; flex-direction: column; gap: 12px; max-width: 380px; }
#settings-pw-form label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
#settings-pw-form input {
padding: 8px 10px;
background: rgba(0,0,0,.25);
border: 1px solid var(--border);
color: inherit;
border-radius: 4px;
font-size: 14px;
}
#settings-pw-form button {
align-self: flex-start;
margin-top: 4px;
padding: 8px 16px;
}
.settings-section .msg { margin-top: 8px; font-size: 12.5px; }
/* ── Mobile-Optimierung (echte Mobile-First-UI) ────────────────── */
@media (max-width: 700px) {
.desktop-only { display: none !important; }
.mobile-only { display: block; }
body { font-size: 15px; }
/* HEADER: nur Logo + User */
header {
padding: 10px 14px;
text-align: left;
border-bottom: 1px solid var(--border);
}
header h1 { font-size: 18px; margin: 0; }
.header-row {
flex-direction: row;
flex-wrap: wrap;
align-items: center;
gap: 8px;
}
.header-left, .header-right { align-items: center; }
.header-right { flex-direction: row; gap: 8px; flex: 1; justify-content: flex-end; }
.user-bar {
display: flex;
flex-direction: row;
align-items: center;
gap: 6px;
font-size: 13px;
flex-wrap: nowrap;
}
.user-bar strong { font-size: 14px; max-width: 90px; overflow: hidden; text-overflow: ellipsis; }
.header-profile { max-width: 130px; padding: 4px 6px; font-size: 12px; }
.btn-link { font-size: 12px; padding: 4px 6px; }
main { padding: 14px 12px 90px; gap: 14px; }
.card { padding: 16px; border-radius: 12px; }
.card h2 { font-size: 16px; margin-bottom: 10px; }
/* UPLOAD-CARD: Recording-Hero-Style */
.upload-card form { display: flex; flex-direction: column; gap: 14px; }
.btn-record {
/* HERO: groß und auffällig */
padding: 26px;
font-size: 19px;
min-height: 90px;
border-radius: 14px;
box-shadow: 0 4px 20px rgba(231,76,60,.15);
}
.btn-record .rec-dot { width: 16px; height: 16px; animation: pulse 1.5s ease-in-out infinite; }
.upload-meta { grid-template-columns: 1fr; gap: 10px; }
.upload-meta select,
.upload-meta input[type=text] {
padding: 14px 12px;
font-size: 16px; /* iOS: ≥16px verhindert Zoom-on-Focus */
min-height: 48px;
}
.audio-file-details summary { padding: 12px 4px; font-size: 14px; }
button[type="submit"] {
padding: 16px;
font-size: 16px;
min-height: 52px;
border-radius: 10px;
width: 100%;
}
/* Aufnahme-Bühne: noch größer auf Mobile */
.record-pane { padding: 24px 16px; }
.record-timer { font-size: 64px; line-height: 1; }
.record-controls { width: 100%; gap: 12px; }
.btn-record-ctrl {
flex: 1;
padding: 18px;
font-size: 17px;
min-height: 56px;
min-width: 0;
}
/* JOBS-CARDS statt Tabelle */
.jobs-cards { display: flex; flex-direction: column; gap: 10px; }
.jc {
background: #0f1219;
border: 1px solid var(--border);
border-radius: 10px;
padding: 12px 14px;
}
.jc-head {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 8px;
margin-bottom: 6px;
}
.jc-id { color: var(--muted); font-size: 12px; }
.jc-title { font-weight: 600; font-size: 15px; line-height: 1.3; word-break: break-word; }
.jc-sub { color: var(--muted); font-size: 12px; margin-top: 2px; }
.jc-status-row {
display: flex;
align-items: center;
gap: 8px;
margin: 8px 0 6px;
}
.jc-progress { flex: 1; }
.jc-error {
color: var(--err);
font-size: 12px;
margin: 4px 0;
word-break: break-word;
}
.jc-dl {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
margin-top: 8px;
}
.jc-dl .btn-dl { padding: 8px; font-size: 12px; min-height: 36px; }
/* Admin-Bereich: collapsible */
.admin-collapsible .admin-toggle {
cursor: pointer;
user-select: none;
display: flex;
justify-content: space-between;
align-items: center;
margin: 0;
}
.admin-toggle-icon { display: inline; transition: transform .2s; }
.admin-collapsible:not(.open) .admin-body { display: none; }
.admin-collapsible.open .admin-toggle-icon { transform: rotate(180deg); }
.user-form { grid-template-columns: 1fr; }
.user-form input { font-size: 16px; }
}
/* iOS PWA: oberer Sicherheitsbereich (Notch) respektieren */
@supports (padding: max(0px)) {
header { padding-top: max(10px, env(safe-area-inset-top)); }
main { padding-bottom: max(20px, env(safe-area-inset-bottom)); }
}
/* Retry-Button in der Status-Spalte */
.btn-retry {
display: inline-block;
margin-top: 6px;
padding: 3px 8px;
font-size: 11px;
font-weight: 500;
background: rgba(241,196,15,.12);
color: var(--warn);
border: 1px solid rgba(241,196,15,.4);
border-radius: 5px;
text-decoration: none;
cursor: pointer;
}
.btn-retry:hover { background: rgba(241,196,15,.22); text-decoration: none; }
.btn-retry:disabled { opacity: .55; cursor: not-allowed; }
/* Profile-Tag in der Job-Zeile — kleiner & ohne Außenabstand,
weil sie jetzt in einem eigenen .job-tags-Container mit gap leben */
.tag-profile {
display: inline-block;
padding: 1px 7px;
border-radius: 4px;
background: rgba(46,204,113,.12);
border: 1px solid rgba(46,204,113,.4);
color: var(--ok);
font-size: 10.5px;
text-transform: lowercase;
line-height: 1.5;
}
/* Modell-Tag — gleicher Stil wie Profile-Tag, andere Farbe (lila) */
.tag-model {
display: inline-block;
padding: 1px 7px;
border-radius: 4px;
background: rgba(155,89,182,.10);
border: 1px solid rgba(155,89,182,.4);
color: #b07cd6;
font-size: 10.5px;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
line-height: 1.5;
}
/* In der mobilen Karte (jc-title) sitzen Tags inline neben dem Titeltext —
dort brauchen sie etwas Luft nach links. In der Desktop-Tabelle stehen sie
im eigenen .job-tags-Container mit gap, dort kein margin nötig. */
.jc-title .tag-profile,
.jc-title .tag-model { margin-left: 6px; }
/* Modal für Modell-Auswahl beim Reprocess */
dialog.model-picker {
border: 1px solid rgba(255,255,255,.15);
border-radius: 8px;
background: #1a1d23;
color: inherit;
padding: 18px 20px;
max-width: 460px;
width: 90vw;
}
dialog.model-picker::backdrop {
background: rgba(0,0,0,.55);
}
dialog.model-picker h3 {
margin: 0 0 6px 0;
font-size: 15px;
}
dialog.model-picker .model-picker-label {
display: block;
margin: 12px 0 4px;
font-size: 13px;
}
dialog.model-picker select {
display: block;
width: 100%;
margin-top: 6px;
padding: 6px 8px;
background: rgba(0,0,0,.30);
border: 1px solid rgba(255,255,255,.20);
color: inherit;
border-radius: 4px;
font-size: 13px;
}
dialog.model-picker .dlg-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 14px;
}
dialog.model-picker button {
padding: 6px 14px;
background: rgba(255,255,255,.06);
border: 1px solid rgba(255,255,255,.18);
color: inherit;
border-radius: 4px;
cursor: pointer;
}
dialog.model-picker button.primary {
background: rgba(155,89,182,.20);
border-color: rgba(155,89,182,.55);
color: #d3afe6;
}
dialog.model-picker button:hover { background: rgba(255,255,255,.12); }
dialog.model-picker code {
background: rgba(255,255,255,.06);
padding: 1px 5px;
border-radius: 3px;
font-size: 11.5px;
}
/* Live-Timing direkt unter dem Status-Pill (läuft seit · letzter Ping vor) */
.status-timing, .jc-timing {
margin-top: 4px;
font-size: 11px;
line-height: 1.3;
}
.live-timing { color: var(--muted); }
/* Reprocess-Button (mit anderem Modell neu verarbeiten) violetter Akzent,
um ihn klar vom warning-gelben "Erneut versuchen" zu trennen */
.btn-reprocess {
display: inline-block;
margin-top: 6px;
margin-left: 4px;
padding: 3px 8px;
font-size: 11px;
font-weight: 500;
background: rgba(155,89,182,.14);
color: #b07cd6;
border: 1px solid rgba(155,89,182,.45);
border-radius: 5px;
cursor: pointer;
}
.btn-reprocess:hover { background: rgba(155,89,182,.24); }
.btn-reprocess:disabled { opacity: .55; cursor: not-allowed; }
/* Verlauf-Toggle wie Diagnose, aber leicht andere Farbe */
.btn-runs {
display: inline-block;
margin-top: 6px;
margin-left: 4px;
padding: 4px 10px;
font-size: 12px;
background: rgba(52,152,219,.10);
border: 1px solid rgba(52,152,219,.35);
color: #7fbce8;
border-radius: 5px;
cursor: pointer;
}
.btn-runs:hover { background: rgba(52,152,219,.20); }
/* Verlauf-Panel: gleiches Grundlayout wie diag, separates Styling für Listen-Items */
.runs-row > td {
background: rgba(52,152,219,.04);
border-top: 0;
padding: 10px 12px;
}
.runs-panel {
margin-top: 10px;
padding: 10px;
background: rgba(52,152,219,.05);
border: 1px solid rgba(52,152,219,.18);
border-radius: 6px;
}
.runs-meta { font-size: 12px; margin-bottom: 8px; }
.runs-list { display: flex; flex-direction: column; gap: 8px; }
.run-item {
padding: 8px 10px;
background: rgba(255,255,255,.03);
border: 1px solid rgba(255,255,255,.08);
border-radius: 5px;
}
.run-head {
display: flex;
flex-wrap: wrap;
gap: 14px;
align-items: baseline;
font-size: 12px;
margin-bottom: 6px;
}
.run-model code { font-size: 12px; padding: 1px 5px; }
.run-stamp { font-size: 11.5px; color: var(--muted); }
.run-files { display: flex; flex-wrap: wrap; gap: 6px; }
/* Diagnose-Button wie btn-retry, aber neutraler Ton */
.btn-diag {
display: inline-block;
margin-top: 6px;
margin-left: 4px;
padding: 4px 10px;
font-size: 12px;
background: rgba(120,120,120,.10);
border: 1px solid rgba(160,160,160,.35);
color: var(--muted);
border-radius: 5px;
text-decoration: none;
cursor: pointer;
}
.btn-diag:hover { background: rgba(160,160,160,.20); color: inherit; }
/* Aktions-Reihe in der mobilen Karte */
.jc-actions {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-top: 4px;
}
/* Diagnose-Panel: Tabelle (zweite Zeile, full-width) und Karte */
.diag-row > td {
background: rgba(255,255,255,.03);
border-top: 0;
padding: 10px 12px;
}
.diag-panel {
margin-top: 10px;
padding: 10px;
background: rgba(255,255,255,.03);
border: 1px solid rgba(255,255,255,.08);
border-radius: 6px;
}
.diag-meta {
display: flex;
gap: 16px;
flex-wrap: wrap;
font-size: 12px;
color: var(--muted);
margin-bottom: 6px;
}
.diag-meta code {
background: rgba(255,255,255,.08);
padding: 1px 4px;
border-radius: 3px;
}
.diag-err {
margin: 6px 0;
padding: 6px 8px;
background: rgba(231,76,60,.10);
border: 1px solid rgba(231,76,60,.35);
border-radius: 4px;
color: var(--err);
font-size: 12px;
word-break: break-word;
}
.diag-loghead {
margin-top: 8px;
font-size: 11px;
text-transform: uppercase;
letter-spacing: .05em;
color: var(--muted);
}
.diag-log {
margin: 4px 0 0 0;
padding: 8px;
background: rgba(0,0,0,.30);
border: 1px solid rgba(255,255,255,.06);
border-radius: 4px;
max-height: 320px;
overflow: auto;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
font-size: 11.5px;
line-height: 1.45;
white-space: pre-wrap;
word-break: break-word;
}