/* app.css — Leitstand-Layout (Auftrag "Layout-Ueberarbeitung", 09.09.2026): Sidebar-Navigation im
   Stil des echten HUBrobotix-Web-GUIs (Farben/Masse 1:1 aus mailrobotix/app/css/main.css
   uebernommen - dieses Repo hat keinen Dateizugriff darauf, deshalb hier per Hand uebertragen,
   nicht importiert) statt der fruoheren 720px-Mittelspalte. Akzent bewusst das im HUBrobotix-
   Design-System DOKUMENTIERTE Indigo (#6366f1, ui-design-system.md §9.2), nicht das abweichend
   ausgelieferte Cyan - identisch zum bisherigen Updater-Akzent, keine dritte Marke. */
:root {
  --bg: #0f172a;
  --sidebar: #1e293b;
  --card: #1e293b;
  --card-alt: #263449;
  --border: #334155;
  --text: #e2e8f0;
  --text-dim: #94a3b8;
  --text-faint: #64748b;
  --accent: #6366f1;
  --accent-soft: rgba(99,102,241,.2);
  --danger: #f87171;
  --danger-bg: #450a0a;
  --warning: #fb923c;
  --warning-bg: #422006;
  --success: #4ade80;
  --success-bg: #052e16;
  --ok: #4ade80;
  --ok-bg: #052e16;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
/* Ladeanzeige (Nutzer-Vorgabe 10.09.2026): load() in dashboard.js laedt ueber ein Dutzend
   Bereiche sequenziell nach - ohne diese Anzeige stand die Seite vorher fuer diese Zeit auf einer
   halb leeren/unstrukturierten Sidebar. Deckt den gesamten Viewport mit derselben Hintergrundfarbe
   ab (kein Aufblitzen der dahinterliegenden Seite), zentriert per Flexbox. dashboard.js blendet sie
   per .hidden nach load() wieder aus (auch im Fehlerfall, s. dortiges finally). */
#app-loader {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
  background: var(--bg); color: var(--text-dim);
}
#app-loader.hidden { display: none; }
.app-loader-spinner {
  width: 40px; height: 40px; border-radius: 50%;
  border: 3px solid var(--border); border-top-color: var(--accent);
  animation: app-loader-spin .8s linear infinite;
}
.app-loader-text { font-size: 13px; }
@keyframes app-loader-spin { to { transform: rotate(360deg); } }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  font-size: 14px;
}
code { font-family: var(--mono); }

/* ---------- Frame: Kopfleiste (4 Hauptpunkte) + Content ----------
   UX-/GUI-Redesign (Auftrag "Updater-Oberflaeche fuer Geschaeftsfuehrer/Betreiber neu bauen"):
   ersetzt die vormalige linke Sidebar-Akkordeon-Navigation (die auf schmalen Bildschirmen ohne
   jeden Umschalt-Knopf nur "position:fixed" ueber dem Inhalt lag, s. altes @media 880px) durch
   eine horizontale Kopfleiste mit GENAU VIER Hauptpunkten - laesst sich nativ per
   Zeilenumbruch/Scroll auf schmalen Bildschirmen bedienen, ohne einen separaten Hamburger-Zustand
   nachzubauen. */
.shell { display: flex; flex-direction: column; min-height: 100vh; }

.appbar {
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  background: var(--sidebar); border-bottom: 1px solid var(--border);
  padding: 10px 24px; position: sticky; top: 0; z-index: 20;
}
.appbar-brand { display: flex; align-items: center; gap: 10px; flex: none; }
.brand-mark {
  width: 28px; height: 28px; border-radius: 7px; background: var(--accent); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 13px; flex: none;
}
/* Nutzer-Vorgabe 12.09.2026: dieselbe Wortmarke wie im Core-Web-GUI statt des generischen
   "H"-Buchstaben-Badges - .brand-mark bleibt fuer login.html erhalten (dort kein Logo-Bild). */
.brand-logo { width: 34px; height: 34px; object-fit: contain; flex: none; }
.brand-name { font-weight: 650; font-size: 14.5px; }
.brand-sub { font-size: 11px; color: var(--text-faint); margin-top: 1px; }

.main-nav { display: flex; gap: 4px; flex: 1 1 auto; overflow-x: auto; min-width: 0; }
.main-nav-item {
  display: flex; align-items: center; gap: 8px; white-space: nowrap; flex: none;
  padding: 9px 16px; border-radius: 8px; border: none; background: none;
  color: var(--text-dim); cursor: pointer; font-size: 13.5px; font-weight: 600;
}
.main-nav-item:hover { background: var(--border); color: var(--text); }
.main-nav-item.active { background: var(--accent-soft); color: #a5b4fc; }
.nav-icon { width: 18px; text-align: center; flex: none; opacity: .9; }

.appbar-right { display: flex; align-items: center; gap: 10px; flex: none; margin-left: auto; }

/* Profilmenue (Auftrag: "Einstellungen fuer berechtigte Administratoren kommen in ein
   Profilmenue") - Rollen/Stufe-1-Zugaenge/Segmente/Credential-Zuordnung/Versionierung sind
   dieselben Views/Funktionen wie zuvor, nur ueber diesen Knopf statt einer Sidebar erreichbar. */
.profile-menu-wrap { position: relative; }
.profile-menu-btn { display: flex; align-items: center; gap: 6px; }
.profile-menu-btn .chev { font-size: 11px; color: var(--text-faint); }
.profile-dropdown {
  position: absolute; top: calc(100% + 8px); right: 0; width: 260px; z-index: 30;
  background: var(--card); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0,0,0,.45); padding: 6px; display: flex; flex-direction: column; gap: 1px;
}
.profile-dropdown-user { padding: 8px 10px; font-size: 12.5px; color: var(--text-dim); }
.profile-dropdown-section { padding: 6px 10px 2px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); }
.profile-dropdown .nav-item {
  padding: 9px 10px; border-radius: 6px; border-left: none; font-size: 13px; color: var(--text-dim); cursor: pointer;
}
.profile-dropdown .nav-item:hover { background: var(--card-alt); color: var(--text); }
.profile-dropdown-divider { height: 1px; background: var(--border); margin: 6px 4px; }
.profile-dropdown-logout { width: calc(100% - 8px); margin: 2px 4px; text-align: left; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; justify-content: space-between; padding: 18px 32px 8px;
}
.topbar h1 { font-size: 18px; margin: 0; font-weight: 700; color: var(--text); }
.topbar .crumb { font-size: 12px; color: var(--text-faint); margin-bottom: 3px; text-transform: uppercase; letter-spacing: .04em; }
.identity { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-dim); }
.live-flag { display: flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 20px; background: var(--success-bg); color: var(--success); font-weight: 650; font-size: 12px; }
.live-flag.is-live { background: var(--danger-bg); color: var(--danger); }
/* Status nicht lesbar (/healthz fehlgeschlagen oder Feld fehlt): neutral statt gruen. */
.live-flag.is-unknown { background: var(--card-alt); color: var(--text-faint); }

.content { padding: 8px 32px 60px; flex: 1; }
.view { display: none; }
.view.active { display: block; }

/* Reiterleiste fuer Unter-Bereiche EINES Hauptnavigationspunkts (Veroeffentlichungen: 3 fachliche
   Bereiche; Verlauf: Release-Verlauf/Audit-Log) - go() haengt die "active"-Klasse hier genauso an
   wie an .nav-item/.nav-single (s. dashboard.js). Nur sichtbar, solange eine ihrer Views aktiv ist
   (steuert view-core/-sandboxarea/-web bzw. -history/-audit, s. dashboard.js showRelevantSubtabs()). */
.subtabs { display: none; gap: 4px; margin: 12px 0 18px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.subtabs.visible { display: flex; }
.subtab-btn {
  background: none; border: none; padding: 10px 16px; margin-bottom: -1px;
  color: var(--text-dim); font-size: 13.5px; font-weight: 600; cursor: pointer;
  border-bottom: 2px solid transparent;
}
.subtab-btn:hover { color: var(--text); }
.subtab-btn.active { color: var(--text); border-bottom-color: var(--accent); }

.area-lede { color: var(--text-dim); font-size: 13px; margin: 0 0 16px; }
.live-action-badge {
  display: inline-flex; align-items: center; gap: 6px; background: var(--danger-bg); color: var(--danger);
  padding: 3px 10px; border-radius: 20px; font-size: 11px; font-weight: 700; vertical-align: middle; margin-left: 8px;
}
.consequence-list { margin: 0; padding-left: 20px; font-size: 13px; color: var(--text-dim); display: flex; flex-direction: column; gap: 8px; }
.locked-note { font-size: 12.5px; color: var(--text-dim); background: var(--card-alt); border-left: 3px solid var(--warning); border-radius: 6px; padding: 8px 12px; margin: 0; }
.locked-card { opacity: .92; }
.locked-card .card-header h3 { color: var(--text-dim); }

/* Uebersicht: "Bereiche im Vergleich - DEV vs. LIVE" (Auftrag "Updater-Oberflaeche fuer
   Geschaeftsfuehrer/Betreiber neu bauen") - fehlende Angaben stehen IMMER als "unbekannt", nie als
   erfundenes Gruen (s. .unknown-val). */
.unknown-val { color: var(--text-faint); font-style: italic; }
/* "Updater-Blocker Runde 5", Punkt 1/4: Karte, deren Laden per Timeout/Fehler scheiterte -
   "Status unbekannt" + erneuter Versuch + aufklappbare technische Details (stabiler Fehlercode). */
.card-unknown { color: var(--text-dim); font-size: 13px; line-height: 1.6; }
.card-retry-btn { margin-left: 6px; padding: 4px 10px; font-size: 12px; vertical-align: baseline; }
.tech-details { margin-top: 4px; font-size: 12px; color: var(--text-faint); }
.tech-details > summary { display: inline; font-size: 12px; color: var(--text-faint); text-decoration: underline dotted; }
.tech-details > summary::before { font-size: 11px; margin-right: 4px; }
.tech-details code { color: var(--text-dim); word-break: break-all; }
/* "Updater-Blocker Runde 5", Punkt 2 (Browser-Fund bei ~800px): ein langer, unumbrechbarer Wert
   (z.B. "gesperrt (SANDBOX_CONTROL_TARGET_UNVERIFIED)") machte die Karten-Tabelle breiter als ihre
   Grid-Spalte; .card { overflow:hidden } schnitt die LIVE-Spalte dann einfach ab. Jetzt: feste
   Tabellenaufteilung + Umbruch an beliebiger Stelle, min()-Spaltenbreite (kein Ueberlauf < 280px). */
.area-overview-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); gap: 16px; }
.area-card { background: var(--card-alt); border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; min-width: 0; }
.area-card-table { table-layout: fixed; }
.area-card-table th:first-child, .area-card-table td:first-child { width: 38%; }
.area-card-table td { overflow-wrap: anywhere; word-break: normal; }
.area-card-table td:first-child { overflow-wrap: break-word; hyphens: auto; }
.area-card-table .badge { display: inline-block; line-height: 1.35; }
.area-card-head { gap: 8px; flex-wrap: wrap; }
.area-card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.area-card-head h4 { margin: 0; font-size: 14px; }
.area-card-table th, .area-card-table td { padding: 6px 8px; font-size: 12.5px; }
.area-card-table th:first-child, .area-card-table td:first-child { color: var(--text-faint); font-weight: 600; }

/* Auftrag "Navigation nach 3 Kernbereichen" (09.09.2026): <details>/<summary> fuer "Details je
   Paket" - Browser-Standardmarker unterdrueckt, eigenes card-header-Aussehen bleibt unveraendert. */
details > summary { list-style: none; cursor: pointer; justify-content: flex-start !important; gap: 12px; }
details > summary::-webkit-details-marker { display: none; }
details > summary::before { content: '▸'; display: inline-block; font-size: 16px; line-height: 1; color: var(--text-faint); transition: transform .15s; }
details[open] > summary::before { transform: rotate(90deg); }

/* ---------- Card (Header/Body/Footer) ---------- */
.card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; margin-bottom: 20px; }
.card-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--border); gap: 16px; }
.card-header h3 { margin: 0; font-size: 15px; font-weight: 600; color: var(--text); }
.card-header .sub { font-size: 12px; color: var(--text-faint); margin-top: 2px; }
.card-body { padding: 20px; overflow-x: auto; } /* Runde 5, Punkt 2: breite Tabellen scrollen IN der Karte statt abgeschnitten zu werden */
.card-body table.data td { overflow-wrap: anywhere; }
.card-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 20px; border-top: 1px solid var(--border); }
.card-footer .note { font-size: 12px; color: var(--text-faint); }
.card-footer .actions { display: flex; gap: 10px; }
.card-header .actions { display: flex; align-items: center; gap: 8px; }

h1 { font-size: 20px; margin: 0 0 16px; }
label { display: block; font-size: 13px; color: var(--text-dim); margin-bottom: 6px; }
input[type=password], input[type=text], input[type=number], select {
  padding: 9px 10px; border-radius: 6px; border: 1px solid var(--border);
  background: #0b1220; color: var(--text); font-size: 13.5px;
}
button, .btn {
  background: var(--accent); color: #fff; border: none; padding: 9px 16px;
  border-radius: 7px; font-size: 13px; font-weight: 600; cursor: pointer;
}
button:hover, .btn:hover { opacity: 0.9; }
.btn-outline { background: none; border: 1px solid var(--border); color: var(--text-dim); }
.btn-outline:hover { color: var(--text); border-color: var(--text-faint); opacity: 1; }
.btn-ghost { background: none; border: 1px solid var(--border); color: var(--text-dim); padding: 7px 13px; border-radius: 7px; font-size: 12.5px; }
.btn-ghost:hover { color: var(--text); border-color: var(--text-faint); opacity: 1; }
.error { color: var(--danger); font-size: 13px; margin-bottom: 10px; }

/* ---------- Login/Reset (1:1 aus mailrobotix/app/css/main.css #loginPage/.login-box/.btn-primary
   uebernommen - laut mailrobotix CLAUDE.md ist der Gradient-Button dort bewusst NUR fuer
   Login/Reset-Seiten erlaubt, nirgends sonst in der GUI. Eigener Selektor-Namespace
   (.login-shell/.login-box), damit nichts mit dem Dashboard-.card-Muster kollidiert.) */
.login-shell { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; }
.login-box { background: var(--card); border-radius: 16px; padding: 48px; width: 380px; max-width: 100%; box-shadow: 0 25px 50px rgba(0,0,0,.5); }
.login-box .brand-mark { margin: 0 auto 20px; }
.login-box h1 { font-size: 24px; font-weight: 700; margin-bottom: 8px; color: var(--text); text-align: center; }
.login-box p.lede { color: var(--text-dim); margin-bottom: 28px; font-size: 13px; line-height: 1.5; }
.login-box .form-group { margin-bottom: 20px; }
.login-box .form-group label { margin-bottom: 8px; }
.login-box input[type=password], .login-box input[type=text], .login-box input[type=email] { width: 100%; padding: 12px; box-sizing: border-box; }
/* Sicherheitscode-Eingabe (admin-login.html) - ein eigenes Feld je Ziffer statt eines einzelnen
   6-stelligen Textfelds, gaengiges Muster fuer Einmalcodes. */
.code-digits { display: flex; gap: 8px; }
.code-digits input.code-digit {
  flex: 1 1 0; min-width: 0; padding: 12px 0; box-sizing: border-box; text-align: center;
  font-size: 22px; font-weight: 700;
}
/* Stufe-1-Login (admin-login.html) hat als einzige Login-Seite ein Logo-Bild - .brand-logo ist
   sonst die 34px-Sidebar-Ikone (siehe oben), hier bewusst eigene Darstellung. Logo-Datei ist sehr
   breit (1000x171px, ~5.85:1) - ueber die Breite statt der Hoehe begrenzt, sonst sprengt es die
   284px Innenbreite der 380px-Login-Box (48px Padding je Seite). */
.login-box .brand-logo { width: 220px; max-width: 100%; height: auto; margin: 0 auto 20px; display: block; }
.btn-primary {
  width: 100%; padding: 12px; background: linear-gradient(135deg, #0284c7, #8b5cf6); border: none;
  border-radius: 8px; color: #fff; font-size: 15px; font-weight: 600; cursor: pointer; transition: opacity .2s;
}
.btn-primary:hover { opacity: .9; }
.error-msg { background: var(--danger-bg); border: 1px solid #7f1d1d; color: #fca5a5; padding: 12px; border-radius: 8px; font-size: 13px; margin-bottom: 16px; }
.login-divider { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.identity-box { margin-top: 16px; padding: 14px 16px; border-radius: 8px; background: var(--card-alt); }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
table.data th, table.data td, th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--border); }
th { color: var(--text-faint); font-weight: 650; font-size: 11.5px; text-transform: uppercase; letter-spacing: .3px; }
tr:last-child td { border-bottom: none; }
.badge { padding: 3px 9px; border-radius: 20px; font-size: 11px; font-weight: 650; }
.badge-applied { background: var(--success-bg); color: var(--success); }
.badge-failed { background: var(--danger-bg); color: var(--danger); }
.badge-other { background: var(--warning-bg); color: var(--warning); }

/* Nutzer-Vorgabe 12.09.2026: Paginator fuer Release-Verlauf/Audit-Log (s. dashboard.js
   renderPagerControls()). */
.pager { display: flex; align-items: center; gap: 12px; margin-top: 12px; font-size: 12.5px; color: var(--text-dim); flex-wrap: wrap; }
.pager-info { flex: 1; }
.pager select { background: var(--card-alt); color: var(--text); border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px; font-size: 12.5px; }
.pager .btn-ghost { padding: 4px 10px; font-size: 12.5px; }
.pager .btn-ghost:disabled { opacity: .4; cursor: default; }
.pager-page { white-space: nowrap; }

/* ---------- Dashboard-Tickets ---------- */
.ticket-section { margin-bottom: 26px; }
.ticket-section-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.ticket-section-head h2 { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-dim); margin: 0; font-weight: 700; }
.ticket-section-head .count { font-size: 12px; color: var(--text-faint); }
.ticket {
  display: flex; align-items: stretch; gap: 14px; background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--border); border-radius: 10px; padding: 14px 16px; margin-bottom: 8px; cursor: pointer;
}
.ticket:hover { background: var(--card-alt); }
.ticket.sev-danger { border-left-color: var(--danger); }
.ticket.sev-warning { border-left-color: var(--warning); }
.ticket.sev-done { border-left-color: var(--success); opacity: .7; }
.ticket-icon { width: 32px; height: 32px; border-radius: 9px; flex: none; display: flex; align-items: center; justify-content: center; font-size: 14px; }
.sev-danger .ticket-icon { background: var(--danger-bg); color: var(--danger); }
.sev-warning .ticket-icon { background: var(--warning-bg); color: var(--warning); }
.sev-done .ticket-icon { background: var(--success-bg); color: var(--success); }
.ticket-body { flex: 1; min-width: 0; }
.ticket-title { font-weight: 650; font-size: 14px; margin-bottom: 2px; }
.ticket-desc { color: var(--text-dim); font-size: 12.5px; }
.ticket-desc code { background: var(--bg); padding: 1px 5px; border-radius: 4px; font-size: 11.5px; }
.ticket-parts { display: flex; gap: 6px; margin-top: 7px; flex-wrap: wrap; }
.ticket-part { font-size: 11px; padding: 3px 9px; border-radius: 20px; background: var(--bg); border: 1px solid var(--border); color: var(--text-dim); }
.ticket-meta { display: flex; align-items: center; justify-content: center; flex: none; }
.ticket-cta { font-size: 12px; color: var(--accent); font-weight: 650; white-space: nowrap; }
.empty-note { color: var(--text-faint); font-size: 13px; padding: 14px 16px; background: var(--card); border: 1px dashed var(--border); border-radius: 10px; }

.bundle-flow { display: flex; gap: 0; margin-top: 4px; }
.bundle-step { flex: 1; text-align: center; padding: 10px 6px; border: 1px solid var(--border); background: var(--bg); font-size: 12px; color: var(--text-dim); }
.bundle-step:first-child { border-radius: 8px 0 0 8px; }
.bundle-step:last-child { border-radius: 0 8px 8px 0; }
.bundle-step + .bundle-step { border-left: none; }
.bundle-step b { display: block; font-size: 13px; color: var(--text); margin-bottom: 2px; }
.bundle-step.ready { background: var(--warning-bg); border-color: transparent; color: var(--warning); }
.bundle-step.ready b { color: var(--warning); }

@media (max-width: 880px) {
  .content, .topbar { padding-left: 18px; padding-right: 18px; }
  .appbar { padding: 10px 14px; gap: 10px; }
  /* Runde 5, Punkt 2: Hauptnavigation in eigener Zeile und umbrechend - bei ~800px war
     "Betrieb & Wiederherstellung" sonst nur per verstecktem Seitwaerts-Scroll erreichbar. */
  .main-nav { order: 3; flex-basis: 100%; flex-wrap: wrap; overflow-x: visible; }
  .card-header { flex-wrap: wrap; }
  .card-footer { flex-wrap: wrap; }
  .card-footer .actions { flex-wrap: wrap; }
  .appbar-brand .brand-name { font-size: 13px; }
  .appbar-brand .brand-sub { display: none; }
}
@media (max-width: 640px) {
  .main-nav-item { padding: 9px 11px; font-size: 12.5px; }
  .live-flag { display: none; }
  /* Runde 5, Punkt 2 (375px): lange Codes/Kennungen im Fliesstext umbrechen, Tabellenzellen enger -
     eine wirklich breite Tabelle (z.B. Credential-Zuordnung, 7 Spalten) scrollt dann IN der Karte. */
  .card-body code, .card-body p, .locked-note { overflow-wrap: anywhere; }
  table.data th, table.data td { padding: 7px 6px; }
  th { letter-spacing: 0; }
  .card-body { padding: 14px; }
  .card-header { padding: 14px; }
}

/* Release-Ablauf-Dialog (Auftrag "Sichtbarer Schritt-fuer-Schritt-Ablauf beim Bereich-1-Update",
   09.09.2026): zeigt die real durchlaufenen Schritte (Plan aufloesen -> Antrag -> Freigabe ->
   Ausfuehrungsrecht -> Rollout) einzeln mit Status, statt nur eines einzelnen "Laeuft..."-Textes.
   Die ersten vier Schritte sind je ein eigener, schneller Server-Aufruf und werden live abgehakt;
   der Rollout-Schritt selbst ist eine einzelne Anfrage ohne Server-seitiges Zwischen-Streaming -
   waehrend er laeuft, zeigt der Dialog einen Spinner mit der Anzahl geplanter Einzelposten
   ("DB+Code+Workflows: 42 Posten"), das reale Ergebnis je Posten erscheint danach als Liste. */
.flow-overlay {
  position: fixed; inset: 0; background: rgba(2,6,23,.72); display: flex;
  align-items: center; justify-content: center; z-index: 100;
}
.flow-box {
  width: 560px; max-width: calc(100vw - 32px); max-height: calc(100vh - 64px);
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  display: flex; flex-direction: column; overflow: hidden;
}
.flow-header { padding: 18px 22px; border-bottom: 1px solid var(--border); flex: none; }
.flow-header h3 { margin: 0 0 4px 0; font-size: 16px; }
.flow-content { padding: 18px 22px; overflow-y: auto; flex: 1 1 auto; }
.flow-footer {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 14px 22px; border-top: 1px solid var(--border); flex: none;
}
.flow-sub { color: var(--text-dim); font-size: 12.5px; margin: 0; }
.flow-steps { list-style: none; margin: 0 0 16px 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.flow-step {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 8px; font-size: 13.5px;
  color: var(--text-dim);
}
.flow-step-note { margin-left: auto; font-size: 11.5px; color: var(--text-faint); white-space: nowrap; padding-left: 10px; }
.flow-step.active .flow-step-note { color: var(--text-dim); }
.flow-step.failed .flow-step-note { color: var(--danger); }
.flow-step.active { background: var(--accent-soft); color: var(--text); }
.flow-step.done { color: var(--ok); }
.flow-step.failed { color: var(--danger); }
.flow-step.skipped { color: var(--text-faint); }
.flow-step.rolledback { color: var(--warning); }
.flow-step-icon { width: 18px; flex: none; text-align: center; font-size: 13px; }
.flow-step.active .flow-step-icon::before { content: '◌'; animation: flow-spin 1s linear infinite; display: inline-block; }
.flow-step.done .flow-step-icon::before { content: '✓'; }
.flow-step.failed .flow-step-icon::before { content: '✕'; }
.flow-step.pending .flow-step-icon::before { content: '○'; color: var(--text-faint); }
.flow-step.skipped .flow-step-icon::before { content: '–'; }
.flow-step.rolledback .flow-step-icon::before { content: '↺'; }
@keyframes flow-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.flow-counter { font-size: 12px; color: var(--text-faint); margin: -8px 0 14px 0; }
.flow-items { list-style: none; margin: 0 0 16px 0; padding: 0; max-height: 220px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; }
.flow-item { display: flex; align-items: center; gap: 8px; padding: 6px 10px; font-size: 12.5px; border-bottom: 1px solid var(--border); }
.flow-item:last-child { border-bottom: none; }
.flow-item.ok { color: var(--ok); }
.flow-item.err { color: var(--danger); }
.flow-item-file { color: var(--text-dim); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flow-error-box {
  background: var(--danger-bg); border: 1px solid var(--danger); border-radius: 8px;
  padding: 10px 12px; font-size: 12.5px; color: var(--danger); margin: 0 0 16px 0;
}
.flow-error-box b { display: block; margin-bottom: 4px; color: var(--text); }
.flow-error-box ul { margin: 6px 0 0 0; padding-left: 18px; }
/* Nutzer-Vorgabe (10.09.2026): "INVALID_DOMAINS" bei einer leeren Domaenen-Liste ist kein
   Fehler, sondern "nichts auszurollen, alles bereits synchron" - eigene, gruene Variante statt
   der roten Fehlerbox, damit dieser haeufige, gute Fall nicht wie ein Rollout-Fehler aussieht. */
.flow-success-box {
  background: var(--success-bg); border: 1px solid var(--success); border-radius: 8px;
  padding: 10px 12px; font-size: 13px; color: var(--success); margin: 0 0 16px 0;
  display: flex; align-items: center; gap: 8px; font-weight: 600;
}
