/* Chaotic Control Center — nüchterner Ops-Look.
   Bewusst NICHT der Glass-Kanon des Kunden-Dashboards: eigener Origin,
   eigene Ästhetik, klare Ampel-Farben, große lesbare Typo. */

:root {
  --bg: #0f1419;
  --bg-panel: #171e26;
  --bg-hover: #1e2732;
  --border: #2a3644;
  --text: #e6edf3;
  --text-muted: #8b98a5;
  --accent: #4da3ff;
  --ok: #3fb950;
  --warn: #d29922;
  --crit: #f85149;
  --info: #58a6ff;
  --radius: 10px;
  font-size: 16px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.55;
}

/* ── Verstecken (AUFTRAG_OFFLINE_UND_COCKPIT Block 5, 11.08.2026) ──────────
 *
 * Seit dem 11.08. versteckt das HTML mit dem ATTRIBUT `hidden`, nicht mehr mit
 * der Klasse. Grund: kommt dieses Stylesheet nicht durch, greift eine
 * CSS-Klasse nicht — am Morgen des 11.08. lagen Anmeldung, 2FA-Einrichtung und
 * Cockpit dadurch gleichzeitig offen. Das Attribut wirkt auch ohne Stylesheet,
 * weil der Browser es selbst kennt.
 *
 * 🔴 ABER: Die Browser-eigene Regel `[hidden] { display: none }` verliert gegen
 * JEDE Regel aus DIESEM Stylesheet — `.app-wrap { display: flex }` haette das
 * Attribut also ueberstimmt, solange das Stylesheet LAEDT. Ohne die Zeile
 * unten waere der Fix genau andersherum kaputt gewesen: versteckt nur im
 * Fehlerfall, sichtbar im Normalfall.
 *
 * Deshalb beide Wege:
 *   Stylesheet laedt      -> `[hidden]` hier mit !important
 *   Stylesheet faellt aus -> die Browser-eigene Regel
 *
 * `.hidden` bleibt als Klasse bestehen (Rueckwaertskompatibilitaet fuer alles,
 * was sie noch setzt) — neuer Code nimmt das Attribut.
 */
[hidden] { display: none !important; }
.hidden { display: none !important; }
.muted { color: var(--text-muted); font-size: 0.9rem; }
.error { color: var(--crit); margin-top: 0.8rem; font-weight: 600; }
code { background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; }

/* ── Login ─────────────────────────────────────────────────────────────── */
.login-wrap {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
}
.login-card {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2rem;
  width: 100%; max-width: 420px;
}
.login-card h1 { font-size: 1.35rem; margin-bottom: 0.3rem; }
.login-card form { margin-top: 1.2rem; display: flex; flex-direction: column; gap: 0.5rem; }
.login-card label { font-weight: 600; font-size: 0.9rem; }
.login-card input {
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 0.65rem 0.8rem; font-size: 1rem;
}
.login-card input:focus { outline: 2px solid var(--accent); border-color: transparent; }
button {
  background: var(--accent); color: #06263f;
  border: none; border-radius: 6px;
  padding: 0.7rem 1rem; font-size: 1rem; font-weight: 700;
  cursor: pointer; margin-top: 0.5rem;
}
button:hover { filter: brightness(1.1); }
button.ghost {
  background: transparent; color: var(--text-muted);
  border: 1px solid var(--border);
}
.qr { width: 200px; height: 200px; margin: 0.8rem 0; border-radius: 8px; background: #fff; }
.backup {
  background: var(--bg); border: 1px dashed var(--warn);
  padding: 1rem; border-radius: 8px; margin: 0.8rem 0;
  font-size: 1.05rem; letter-spacing: 1px;
}

/* ── App-Layout (Layout A: Rail + Kontext-Sidebar + Inhalt) ───────────── */
.app-wrap { display: flex; min-height: 100vh; }

.rail {
  width: 60px; flex-shrink: 0;
  background: #0a0e12;
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column; align-items: center;
  padding: 0.8rem 0; gap: 0.5rem;
  position: sticky; top: 0; height: 100vh;
}
.rail a {
  width: 42px; height: 42px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 1rem; text-decoration: none;
  color: var(--text); background: var(--bg-hover);
  border: 2px solid transparent;
  position: relative;
}
.rail a:hover { border-color: var(--border); }
.rail a.active { border-color: var(--accent); }
.rail a.app-icon { background: #2a2140; color: #b9a6ff; }
.rail .rail-dot {
  position: absolute; right: -2px; bottom: -2px;
  width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid #0a0e12;
}
.rail .dot-ok { background: var(--ok); }
.rail .dot-degraded { background: var(--warn); }
.rail .dot-down { background: var(--crit); }
.rail .dot-unknown { background: var(--text-muted); }
.rail .rail-plus {
  opacity: 0.45; border: 2px dashed var(--border) !important;
  background: transparent; cursor: default;
}
.rail .rail-sep { width: 32px; border-top: 1px solid var(--border); margin: 0.2rem 0; }

.breadcrumb { color: var(--text-muted); font-size: 0.85rem; margin-bottom: 1rem; }
.breadcrumb a { color: var(--text-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb .sep { margin: 0 0.4rem; }

.sidebar {
  width: 230px; flex-shrink: 0;
  background: var(--bg-panel);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  padding: 1rem 0.7rem;
  position: sticky; top: 0; height: 100vh;
}
.brand { font-weight: 800; font-size: 1.05rem; padding: 0.4rem 0.6rem 1rem; }
#nav { flex: 1; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; }
#nav a {
  color: var(--text-muted); text-decoration: none;
  padding: 0.5rem 0.6rem; border-radius: 6px; font-weight: 600;
}
#nav a:hover { background: var(--bg-hover); color: var(--text); }
#nav a.active { background: var(--bg-hover); color: var(--accent); }
.session-box { border-top: 1px solid var(--border); padding-top: 0.8rem; }
.session-box button { width: 100%; margin-top: 0.5rem; }

main { flex: 1; padding: 1.5rem 2rem; max-width: 1200px; }
main h2 { margin-bottom: 0.3rem; }
main .sub { color: var(--text-muted); margin-bottom: 1.2rem; }

/* ── Bausteine ─────────────────────────────────────────────────────────── */
.grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); margin: 1rem 0; }
.card {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.2rem;
}
.card.clickable { cursor: pointer; }
.card.clickable:hover { background: var(--bg-hover); border-color: var(--accent); }
.kpi { font-size: 1.8rem; font-weight: 800; }
.kpi-label { color: var(--text-muted); font-size: 0.85rem; }

.badge {
  display: inline-block; padding: 2px 10px; border-radius: 99px;
  font-size: 0.78rem; font-weight: 700;
}
.badge.ok       { background: rgba(63,185,80,.15);  color: var(--ok); }
.badge.degraded { background: rgba(210,153,34,.15); color: var(--warn); }
.badge.down     { background: rgba(248,81,73,.15);  color: var(--crit); }
.badge.unknown  { background: var(--bg-hover);      color: var(--text-muted); }
.badge.pilot    { background: rgba(88,166,255,.15); color: var(--info); }
.badge.active   { background: rgba(63,185,80,.15);  color: var(--ok); }
.badge.beta     { background: rgba(210,153,34,.15); color: var(--warn); }
.badge.maintenance, .badge.retired { background: var(--bg-hover); color: var(--text-muted); }

/* DSGVO-Frist (03.08.2026): Ein Antrag, der in drei Tagen abläuft, darf nicht
   als 21. Zeile unter zwanzig anderen stehen. Die Zeile selbst wird markiert,
   nicht nur ein kleines Abzeichen. Welche Zeile das ist, entscheidet der
   Server (cc_dsgvo_frist.dringlichkeit) — hier steht nur die Farbe. */
tr.frist-rot            { background: rgba(248,81,73,.10); }
tr.frist-rot td:first-child { border-left: 4px solid var(--crit); }

.alarm { border-left: 4px solid var(--info); padding: 0.7rem 1rem; margin-bottom: 0.5rem;
         background: var(--bg-panel); border-radius: 6px; }
.alarm.critical { border-left-color: var(--crit); }
.alarm.warning  { border-left-color: var(--warn); }
.alarm.info     { border-left-color: var(--info); }

table { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: 0.92rem; }
th { text-align: left; color: var(--text-muted); font-size: 0.8rem;
     text-transform: uppercase; letter-spacing: 0.5px; }
th, td { padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--border); }
tbody tr:hover { background: var(--bg-hover); }
tr.clickable { cursor: pointer; }

.toolbar { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; margin: 0.8rem 0; }
.toolbar input, .toolbar select {
  background: var(--bg-panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 0.5rem 0.7rem; font-size: 0.95rem;
}
.toolbar button { margin-top: 0; padding: 0.5rem 0.9rem; }

/* Modal (geführte Aktionen: Grund-Pflicht, Doppelbestätigung) */
.modal-bg {
  position: fixed; inset: 0; background: rgba(0,0,0,.6);
  display: flex; align-items: center; justify-content: center; z-index: 50;
}
.modal {
  background: var(--bg-panel); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.5rem; width: 100%; max-width: 480px;
}
.modal h3 { margin-bottom: 0.8rem; }
.modal textarea, .modal input, .modal select {
  width: 100%; background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 0.6rem; font-size: 0.95rem; margin: 0.4rem 0;
}
.modal .row { display: flex; gap: 0.6rem; justify-content: flex-end; margin-top: 0.8rem; }
/* 03.08.2026 ENTSCHÄRFT: Diese Regel hieß `.modal .warnbox` — sie galt NUR im
   Modal. Eine Warnbox auf einer normalen Seite hätte gar keinen Stil bekommen
   und wäre als grauer Fließtext untergegangen: eine Warnung, die nicht warnt.
   Jetzt gilt sie überall; die Modal-Variante braucht keine Sonderregel mehr. */
.warnbox {
  background: rgba(210,153,34,.1); border: 1px solid var(--warn);
  border-radius: 6px; padding: 0.6rem 0.8rem; margin: 0.6rem 0; font-size: 0.9rem;
}

.toast {
  position: fixed; bottom: 1.2rem; right: 1.2rem; z-index: 99;
  background: var(--bg-hover); border: 1px solid var(--border);
  border-radius: 8px; padding: 0.8rem 1.2rem; font-weight: 600;
}
.toast.ok { border-color: var(--ok); }
.toast.err { border-color: var(--crit); }

@media (max-width: 760px) {
  .app-wrap { flex-direction: column; }
  .sidebar { width: 100%; height: auto; position: static; }
  main { padding: 1rem; }
}

/* ── Verweise in Tabellen (AUFTRAG_OFFLINE_UND_COCKPIT Block 4, 11.08.2026) ──
 *
 * Patrick: „Blaue Schrift auf dunklem Grund — kaum lesbar."
 *
 * `--accent` (#4da3ff) auf `--bg` (#0d1117) hat einen Kontrast von rund 5,6:1.
 * Das erfuellt AA fuer Fliesstext knapp, ist bei kleiner Tabellenschrift und
 * langen E-Mail-Adressen aber muehsam — genau da, wo man am genauesten lesen
 * muss. Weiss (`--text`, #e6edf3) liegt bei rund 14:1.
 *
 * ⚠️ Farbe war hier der EINZIGE Hinweis darauf, dass man klicken kann. Nimmt
 * man sie weg, ohne etwas an ihre Stelle zu setzen, ist der Verweis unsichtbar
 * — dann ist es lesbar und trotzdem kaputt (§3). Deshalb:
 *   - dezent gepunktete Unterstreichung (dauerhaft sichtbar, stoert nicht)
 *   - beim Ueberfahren volle Linie + Zeigefinger + Akzentfarbe
 * Farbe ist damit eine ZWEITE Kennzeichnung, nicht die einzige — das hilft
 * auch bei Farbfehlsichtigkeit.
 *
 * §19: Ersetzt SIEBEN verstreute `style="color:var(--accent)"` in sechs
 * Dateien (users, tenants, support, finance ×2, forum, impersonation). Es war
 * keine Klasse, sondern siebenmal derselbe Inline-Stil — deshalb jetzt eine.
 */
.tlink {
  color: var(--text);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
  text-decoration-color: var(--text-muted);
}
.tlink:hover,
.tlink:focus-visible {
  color: var(--accent);
  text-decoration-style: solid;
  text-decoration-color: var(--accent);
  cursor: pointer;
}

/* ── Vier Klassen, die BENUTZT, aber nie GESTYLT waren (21.08.2026) ──────────
 *
 * `tests/pruefe_css_klassen.mjs` meldete sie seit Tagen rot; niemand ist den
 * Fund angegangen, weil der Wächter an keinem Weg hing. Seit heute läuft er im
 * Docker-Bau (Block 3) — und dabei fiel auf, dass es keine Schönheitsfehler
 * sind, sondern drei Oberflächen, die etwas anderes versprechen, als sie tun
 * (§ 3):
 *
 *   .warn  (apps.js:71)      — „⚠️ 2 von 3 Diensten veraltet" stand als
 *                              grauer Fließtext da. Eine Warnung, die nicht
 *                              warnt, ist die perfide Variante: Der Code ist
 *                              da, das Element steht sichtbar auf der Seite,
 *                              nichts kracht — und niemand sieht es.
 *   .btn   (tenants.js:124)  — „Betriebsdaten ansehen" und „🔒 Einsicht" sind
 *                              <a>-Elemente. `button` ist als ELEMENT gestylt,
 *                              nicht als Klasse; beide sahen aus wie normale
 *                              Verweise. Der Weg zur Betriebssicht war da und
 *                              sah aus wie Text.
 *   .num   (betrieb.js)      — Zahlenspalten linksbündig. Beim Vergleichen von
 *                              Mengen (jetzt auch Futtergramm) ist das genau
 *                              die Spalte, in der man untereinander lesen will.
 *   .tbl   (betrieb/einsicht) — hier NICHT gestylt, sondern aus dem Markup
 *                              entfernt: `table` ist bereits global gestylt,
 *                              die Klasse war ein zweiter Name für dieselbe
 *                              Sache (§ 1).
 */
.warn { color: var(--warn); font-weight: 600; }

/* Ein <a>, das wie ein Knopf aussehen soll. Erbt bewusst NICHT von `button`
 * per Selektorliste — sonst müsste jede spätere Knopf-Regel daran denken. */
.btn {
  display: inline-block; padding: 0.5rem 0.9rem; border-radius: 6px;
  border: 1px solid var(--accent); background: var(--accent); color: #08111c;
  font-weight: 600; font-size: 0.9rem; text-decoration: none; cursor: pointer;
}
.btn:hover { filter: brightness(1.1); }
.btn.ghost {
  background: transparent; color: var(--text); border-color: var(--border);
}
.btn.ghost:hover { background: var(--bg-hover); border-color: var(--accent); }

/* Zahlenspalte: rechtsbündig + Tabellenziffern, damit Mengen untereinander
 * vergleichbar sind (variable Ziffernbreite verschiebt sonst jede Zeile). */
.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ══════════════════════════════════════════════════════════════════════
   🔴 D1 / V391 (07.09.2026) — HILFSKLASSEN STATT INLINE-STILE
   ══════════════════════════════════════════════════════════════════════

   Die CSP der Produktion setzt `style-src 'self'` OHNE `unsafe-inline`
   (`nginx/default.conf.template:72`). Jede `style="…"`-Angabe im
   ausgelieferten JavaScript wurde deshalb VERWORFEN — 115 Vorkommen in
   24 Dateien, seit jeher unbemerkt.

   Was der Betreiber sah: Die Inhalte rendern, nur die Stile fehlen —
   Spaltenbreiten, Akzentfarben, Abstaende. Und die Konsole blieb dauerhaft
   rot, was echte Fehler darin untergehen liess.

   ➡️ ZWEI WEGE standen zur Wahl. Gewaehlt ist der, der NICHTS schwaecht:
      die Stile hierher zu ziehen, statt `unsafe-inline` zu erlauben.
      **Die CSP bleibt unveraendert.**

   ⚠️ Die Namen sind aus dem Stil ABGELEITET, nicht durchnummeriert:
      `u-mt-1rem` ist `margin-top:1rem`. Wer die Klasse liest, weiss was
      sie tut, ohne hierher zu springen.

   🔴 ACHT Stile waren DYNAMISCH (`style="${warnColor(...)}"`) und liessen
      sich nicht in eine feste Klasse ziehen. Sie sind auf Klassennamen
      umgestellt (`.kpi-warn`, `.kpi-crit`, `.rand-ok`, `.rand-warn`) —
      eine Funktion, die eine KLASSE zurueckgibt statt eines Stils.
      Ein erster Anlauf ersetzte sie stumpf per Muster und zerbrach
      `system.js`: `class="u-${warnColor(...)"`. Genau die Klasse aus P3b —
      ein Muster ueber Code sieht keine Sprachkonstrukte.
   ══════════════════════════════════════════════════════════════════════ */

/* Dynamisch gesetzt (Wert entscheidet zur Laufzeit) */
.kpi-warn { color: var(--warn); }
.kpi-crit { color: var(--crit); }
.rand-ok   { border-left: 4px solid var(--ok); }
.rand-warn { border-left: 4px solid var(--warn); }
.rand-crit { border-left: 4px solid var(--crit); }
.rahmen-ok   { border-color: var(--ok); }
.rahmen-crit { border-color: var(--crit); }
.u-mb-1rem   { margin-bottom: 1rem; }

/* Aus statischen style="…" abgeleitet */
.u-bc-warn_mt-1rem { border-color: var(--warn); margin-top:1rem; }
.u-c-accent { color: var(--accent); }
.u-c-text-muted { color:var(--text-muted); }
.u-c-warn { color: var(--warn); }
.u-d-block_wb-break-all_m-5rem0 { display:block; word-break:break-all; margin:.5rem 0; }
.u-d-flex_jc-space-between_ai-center { display:flex;justify-content:space-between;align-items:center; }
.u-d-flex_jc-space-between_ai-center-2 { display:flex; justify-content:space-between; align-items:center; }
.u-fs-11rem { font-size:1.1rem; }
.u-fs-75rem { font-size:.75rem; }
.u-fs-85rem { font-size:.85rem; }
.u-fs-8rem { font-size:.8rem; }
.u-fw-400_fs-85rem { font-weight:400;font-size:.85rem; }
.u-gap-5rem_flex-wrap { gap:.5rem; flex-wrap:wrap; }
.u-grid-150 { grid-template-columns: repeat(auto-fill, minmax(150px,1fr)); }
.u-grid-160 { grid-template-columns: repeat(auto-fill, minmax(160px,1fr)); }
.u-grid-180 { grid-template-columns: repeat(auto-fill, minmax(180px,1fr)); }
.u-grid-200 { grid-template-columns: repeat(auto-fill, minmax(200px,1fr)); }
.u-grid-220 { grid-template-columns: repeat(auto-fill, minmax(220px,1fr)); }
.u-grid-340 { grid-template-columns: repeat(auto-fill, minmax(340px,1fr)); }
.u-grid-repeat-3-1fr_gap-6rem_m-6rem00 { grid-template-columns: repeat(3, 1fr); gap:.6rem; margin:.6rem 0 0; }
.u-m-3rem0 { margin:.3rem 0; }
.u-m-4rem0 { margin:.4rem 0; }
.u-m-5rem0 { margin:.5rem 0; }
.u-m-6rem0 { margin:.6rem 0; }
.u-maxw-220px { max-width:220px; }
.u-maxw-380px { max-width:380px; }
.u-mb-7rem { margin-bottom:.7rem; }
.u-ml-6rem { margin-left:.6rem; }
.u-mt-0 { margin-top:0; }
.u-mt-12rem { margin-top:1.2rem; }
.u-mt-14rem { margin-top:1.4rem; }
.u-mt-15rem { margin-top:1.5rem; }
.u-mt-1rem { margin-top:1rem; }
.u-mt-3rem { margin-top:.3rem; }
.u-mt-5rem { margin-top:.5rem; }
.u-op-045_cur-not-allowed { opacity:0.45; cursor:not-allowed; }
.u-op-45_cur-not-allowed { opacity:.45;cursor:not-allowed; }
.u-p-02rem07rem_fw-800 { padding:0.2rem 0.7rem; font-weight:800; }
.u-p-15rem5rem_fs-78rem { padding:.15rem .5rem;font-size:.78rem; }
.u-p-1rem5rem_fs-75rem { padding:.1rem .5rem;font-size:.75rem; }
.u-wb-break-all { word-break:break-all; }
.u-wb-break-all_d-block_m-4rem0 { word-break: break-all; display:block; margin:.4rem 0; }
.u-ws-pre-wrap_fs-85rem { white-space:pre-wrap; font-size:.85rem; }
.u-ws-pre-wrap_fs-9rem { white-space:pre-wrap;font-size:.9rem; }

/* RT19 (30.09.2026) — N07-Anhänge: der SHA256-Auszug braucht eine feste
   Zeichenbreite, sonst tanzen die Hexziffern in der Spalte.
   🔴 Hier stand zuerst ein Inline-Stil. Die CSP verwirft den, die Schrift
   wäre beim Betreiber nie angekommen — `pruefe_keine_inline_stile.mjs`
   hat es gefangen (§ 16b: Konfiguration muss ANKOMMEN, nicht nur da sein). */
.cc-hash {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
}
