/* Lena Portal 2.0 — design tokens (Carbon-Gray-100-derived, flat, dense). No gradients anywhere. */
:root {
  --bg: #161616;
  --layer-01: #1f1f1f;
  --layer-02: #262626;
  --layer-03: #333333;
  --terminal: #131313;
  --border-subtle: #393939;
  --border-strong: #525252;
  --text-primary: #f4f4f4;
  --text-secondary: #c6c6c6;
  --text-helper: #8d8d8d;
  --text-disabled: #6f6f6f;
  --accent: #4589ff;
  --accent-btn: #0f62fe;
  --accent-btn-hover: #0353e9;
  --ok: #42be65;
  --warn: #f1c21b;
  --err: #fa4d56;
  --info: #4589ff;
  --neutral: #8d8d8d;
  --ok-bg: #12291a;
  --warn-bg: #2b2611;
  --err-bg: #2d1416;
  --info-bg: #12213a;
  --neutral-bg: #262626;
  --mono: "IBM Plex Mono", "Cascadia Code", ui-monospace, Consolas, monospace;
  --sans: -apple-system, "Segoe UI", system-ui, Roboto, sans-serif;
}
/* Day theme: same token names, lighter/friendlier surfaces. Opt-in via data-theme="light" on <html>;
   the dark set above stays the default so nothing changes unless the operator flips the switch. */
:root[data-theme="light"] {
  --bg: #f4f4f4;
  --layer-01: #ffffff;
  --layer-02: #eef0f2;
  --layer-03: #e0e3e6;
  --terminal: #f3f4f6;
  --border-subtle: #d9dde1;
  --border-strong: #b4bac0;
  --text-primary: #1a1c1e;
  --text-secondary: #4a4f55;
  --text-helper: #6b7178;
  --text-disabled: #9aa0a6;
  --accent: #0f62fe;
  --accent-btn: #0f62fe;
  --accent-btn-hover: #0353e9;
  --ok: #1f9d55;
  --warn: #9a7400;
  --err: #da1e28;
  --info: #0f62fe;
  --neutral: #6b7178;
  --ok-bg: #e3f4ea;
  --warn-bg: #fbf3d9;
  --err-bg: #fdeaeb;
  --info-bg: #e6efff;
  --neutral-bg: #eef0f2;
}
:root[data-theme="light"] .logview .lv-dim { color: #8a9096; }
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--text-primary);
  font: 400 14px/1.45 var(--sans);
  font-feature-settings: "tnum";
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* styled scrollbars on every surface */
* { scrollbar-width: thin; scrollbar-color: var(--layer-03) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--layer-03); border-radius: 5px; border: 2px solid var(--bg); }
*::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }

/* ---------- shell: top bar + left rail ---------- */
.shell { display: grid; grid-template-rows: 48px 1fr; grid-template-columns: 240px 1fr; height: 100vh; }
.shell.rail-collapsed { grid-template-columns: 56px 1fr; }
.topbar {
  grid-column: 1 / -1; display: flex; align-items: center; gap: 16px;
  background: var(--layer-01); border-bottom: 1px solid var(--border-subtle); padding: 0 16px;
}
.topbar .brand { display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 15px; }
.topbar .brand img { height: 28px; }
.env-badge {
  font-size: 11px; font-weight: 600; letter-spacing: .04em; padding: 2px 8px;
  background: var(--layer-03); color: var(--text-secondary); border-radius: 2px;
}
.topbar .spacer { flex: 1; }
.topbar .clock { font-family: var(--mono); font-size: 12px; color: var(--text-helper); }
.health-dot { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--neutral); display: inline-block; }
.dot.ok { background: var(--ok); } .dot.err { background: var(--err); } .dot.warn { background: var(--warn); }
.rail {
  background: var(--layer-01); border-right: 1px solid var(--border-subtle);
  padding: 8px 0; display: flex; flex-direction: column; overflow-y: auto;
}
.rail a {
  display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 16px;
  color: var(--text-secondary); font-size: 13px; border-left: 3px solid transparent; white-space: nowrap;
}
.rail a:hover { background: var(--layer-02); text-decoration: none; }
.rail a.active { background: var(--layer-02); color: var(--text-primary); border-left-color: var(--accent); }
.rail a svg { width: 16px; height: 16px; flex: none; fill: currentColor; }
.rail .divider { border-top: 1px solid var(--border-subtle); margin: 8px 0; }
.rail .rail-foot { margin-top: auto; padding: 10px 16px; font-size: 11px; color: var(--text-disabled); font-family: var(--mono); }
.shell.rail-collapsed .rail a span, .shell.rail-collapsed .rail-foot { display: none; }
.main { overflow-y: auto; padding: 16px; }
.page-head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.page-head h1 { font-size: 20px; font-weight: 600; margin: 0; }
.page-head .actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
/* Speichern bleibt sichtbar. Auf einer langen Einstellungsseite stand der Knopf nur oben: wer
   unten etwas geaendert hatte, musste erst wieder hochscrollen, um ihn zu finden -- und "Ungespei-
   cherte Aenderungen" stand mit ihm ausserhalb des Bildes. .main ist der scrollende Kasten, also
   klebt der Kopf an dessen Oberkante; die negativen Aussenabstaende decken die 16 px Innenabstand
   von .main ab, damit kein Inhalt daneben durchlaeuft. */
.page-head.sticky-head {
  position: sticky; top: 0; z-index: 20;
  margin: -16px -16px 14px; padding: 12px 16px;
  background: var(--bg); border-bottom: 1px solid var(--border-subtle);
}
@media print { .page-head.sticky-head { position: static; margin: 0; padding: 0; border: 0; } }
/* Botname und Firma, eingeschoben ueber Begruessung und System-Prompt. */
.ident-box { margin-bottom: 16px; }
.ident-box .ident-note { grid-column: 2; margin-left: 214px; margin-top: -4px; }

/* ---------- panels & tiles ---------- */
.panel { background: var(--layer-01); border: 1px solid var(--border-subtle); border-radius: 4px; }
.panel + .panel { margin-top: 16px; }
/* ...but not inside a grid. There the gap already spaces them, and this sibling margin pushed the
   first panel of the SECOND column 16px below the first column's, so two headers side by side could
   never line up. Grid children are placed in cells; they do not stack. */
.grid-2 > .panel + .panel, .split > .panel + .panel,
.chart-grid > .panel + .panel { margin-top: 0; }
.panel-head {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  border-bottom: 1px solid var(--border-subtle); font-size: 13px; font-weight: 600;
}
.panel-head .sub { font-weight: 400; color: var(--text-helper); font-size: 12px; }
.panel-head .actions { margin-left: auto; display: flex; gap: 8px; }
.panel-body { padding: 14px; }
.kpi-row { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; border: 1px solid var(--border-subtle); border-radius: 4px; overflow: hidden; }
.kpi { background: var(--layer-01); padding: 12px 14px; border-right: 1px solid var(--border-subtle); cursor: default; }
.kpi:last-child { border-right: 0; }
.kpi .label { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-helper); }
.kpi .value { font-size: 24px; font-weight: 600; font-family: var(--mono); margin-top: 2px; }
.kpi .delta { font-size: 12px; margin-top: 2px; color: var(--text-helper); }
.kpi .delta.up { color: var(--ok); } .kpi .delta.down { color: var(--err); }

/* ---------- tables ---------- */
.tbl-wrap { overflow: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl thead th {
  position: sticky; top: 0; background: var(--layer-02); z-index: 2;
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-helper); text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap; cursor: pointer; user-select: none;
}
.tbl tbody td { padding: 6px 10px; border-bottom: 1px solid var(--border-subtle); height: 32px; white-space: nowrap; }
.tbl tbody tr:hover { background: var(--layer-02); cursor: pointer; }
.tbl tbody tr.selected { background: var(--layer-03); box-shadow: inset 3px 0 0 var(--accent); }
.tbl td.num, .tbl th.num { text-align: right; font-family: var(--mono); }
.tbl td.mono { font-family: var(--mono); font-size: 12px; }
.tbl td.ellip { max-width: 340px; overflow: hidden; text-overflow: ellipsis; }
.tbl-empty { padding: 14px; font-size: 13px; color: var(--text-helper); }
.tbl-toolbar { display: flex; gap: 8px; align-items: center; padding: 10px 14px; border-bottom: 1px solid var(--border-subtle); flex-wrap: wrap; }
.tbl-toolbar .count { margin-left: auto; font-size: 12px; color: var(--text-helper); font-family: var(--mono); }

/* ---------- badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 6px; height: 20px; padding: 0 8px;
  font-size: 12px; font-weight: 500; border-radius: 2px; border: 1px solid;
}
.badge .bdot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge.ok { color: var(--ok); background: var(--ok-bg); border-color: #42be6566; }
.badge.warn { color: var(--warn); background: var(--warn-bg); border-color: #f1c21b66; }
.badge.err { color: var(--err); background: var(--err-bg); border-color: #fa4d5666; }
.badge.info { color: var(--info); background: var(--info-bg); border-color: #4589ff66; }
.badge.neutral { color: var(--neutral); background: var(--neutral-bg); border-color: #8d8d8d66; }

/* ---------- forms ---------- */
.form-section { border-bottom: 1px solid var(--border-subtle); padding: 18px 14px; }
.form-section:last-child { border-bottom: 0; }
/* settings tabs + full-width card grid */
.tabbar { display: flex; gap: 2px; border-bottom: 1px solid var(--border-subtle); margin-bottom: 16px;
  overflow-x: auto; }
/* /admin and /help mark their tab strip "tabs", not "tabbar", and it had no rule -- so the first
   panel of every pane began exactly where the tabs ended, with nothing between them. */
.tabs { margin-bottom: 16px; }
.tab { appearance: none; background: transparent; border: 0; border-bottom: 2px solid transparent;
  color: var(--text-secondary); font-size: 13px; font-weight: 500; padding: 9px 14px; cursor: pointer;
  white-space: nowrap; }
.tab:hover { color: var(--text-primary); }
.tab.active { color: var(--text-primary); border-bottom-color: var(--accent); }
/* Columns, not grid. A grid row is as tall as its tallest cell, so a one-field section beside a
   four-field one left three fields of empty space under it -- which is what made the Sprachen and
   E-Mail blocks look broken. Columns pack: every card takes the height it needs and the next starts
   right underneath. */
.settings-grid { column-count: 2; column-gap: 16px; }
.settings-card { padding: 0; break-inside: avoid; -webkit-column-break-inside: avoid;
  page-break-inside: avoid; margin: 0 0 16px; }
.settings-card .form-section { border-bottom: 0; padding: 16px 18px; }
.settings-card.wide { column-span: all; }
/* Two 440px cards plus the gap need about 900px of content width. Anything narrower gets one
   column, which is also what a laptop at 1280 with the sidebar open ends up with. */
@media (max-width: 900px) { .settings-grid { column-count: 1; } }
.form-section h2 { font-size: 16px; font-weight: 600; margin: 0 0 4px; }
.form-section .desc { font-size: 13px; color: var(--text-secondary); margin: 0 0 14px; }
.form-row { display: grid; grid-template-columns: 200px 1fr; gap: 14px; align-items: start; margin-bottom: 12px; }
.form-row > label { font-size: 13px; font-weight: 500; padding-top: 7px; color: var(--text-secondary); }
.form-row .hint { font-size: 12px; color: var(--text-helper); margin-top: 4px; }
input[type=text], input[type=password], input[type=number], input[type=time], input[type=date], select, textarea {
  width: 100%; background: var(--layer-02); border: 1px solid var(--border-strong); color: var(--text-primary);
  border-radius: 4px; padding: 6px 10px; font: 400 14px/1.4 var(--sans); height: 32px;
}
textarea { height: auto; min-height: 90px; font-family: var(--mono); font-size: 13px; resize: vertical; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
input::placeholder, textarea::placeholder { color: var(--text-disabled); }
.chk { display: flex; gap: 8px; align-items: center; font-size: 13px; padding-top: 7px; }
.chk input { width: auto; height: auto; }
.subhead { font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted, var(--text-secondary)); margin: 4px 0 8px; padding-bottom: 6px;
  border-bottom: 1px solid var(--border-subtle); }
.notice { border: 1px solid var(--border-subtle); border-radius: 6px; background: var(--layer-01); font-size: 13px; }
.notice.warn { border-color: var(--warn); background: var(--warn-bg); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 14px;
  background: var(--accent-btn); color: #fff; border: 0; border-radius: 4px;
  font: 500 13px/1 var(--sans); cursor: pointer; white-space: nowrap;
}
.btn:hover { background: var(--accent-btn-hover); }
.btn:disabled { background: var(--layer-03); color: var(--text-disabled); cursor: not-allowed; }
.btn.ghost { background: transparent; border: 1px solid var(--border-strong); color: var(--text-secondary); }
.btn.ghost:hover { background: var(--layer-02); color: var(--text-primary); }
.btn.danger { background: transparent; border: 1px solid var(--err); color: var(--err); }
.btn.danger:hover { background: var(--err-bg); }
.btn.sm { height: 26px; padding: 0 10px; font-size: 12px; }
.theme-toggle { min-width: 76px; justify-content: center; }
.btn.rec { background: var(--err); border-color: var(--err); color: #fff; }
input[type=range] { -webkit-appearance: none; appearance: none; height: 4px; background: var(--layer-03); border-radius: 2px; padding: 0; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--accent); cursor: pointer; }
input[type=range]::-moz-range-thumb { width: 16px; height: 16px; border: 0; border-radius: 50%; background: var(--accent); cursor: pointer; }
.help-doc { max-width: 820px; }
.help-doc h2 { font-size: 17px; margin: 22px 0 8px; }
.help-doc h3 { font-size: 14px; margin: 16px 0 6px; color: var(--text-secondary); }
.help-doc p, .help-doc li { font-size: 14px; line-height: 1.6; color: var(--text-secondary); }
.help-doc ul { margin: 6px 0 6px 18px; }
.help-doc ol { margin: 6px 0 8px 20px; }
.help-doc ol li { margin-bottom: 4px; }
.help-doc li { margin-bottom: 3px; }
.help-doc .toc a { display: block; padding: 3px 0; }
/* ---------- handbook (Hilfe) building blocks ---------- */
.help-doc h4 { font-size: 13px; font-weight: 600; margin: 14px 0 4px; color: var(--text-primary); }
.help-doc code { font-family: var(--mono); font-size: 12.5px; background: var(--layer-02);
  border: 1px solid var(--border-subtle); border-radius: 4px; padding: 1px 5px; color: var(--text-primary); }
.help-doc figure { margin: 14px 0 18px; }
.help-doc figure img { max-width: 100%; border: 1px solid var(--border-subtle); border-radius: 6px; display: block; }
.help-doc figcaption, .help-doc .figcap { font-size: 12px; color: var(--text-helper); margin-top: 6px; font-style: italic; }
.help-doc .tbl-wrap { margin: 10px 0 4px; }
.help-doc table.tbl { font-size: 13px; }
.help-doc .tbl th { white-space: normal; cursor: default; }
.help-doc .tbl td { white-space: normal; height: auto; vertical-align: top; color: var(--text-secondary); }
.help-doc .tbl tbody tr:hover { background: transparent; cursor: default; }
.help-doc .callout { border: 1px solid var(--border-subtle); border-left: 3px solid var(--accent);
  background: var(--layer-01); border-radius: 6px; padding: 10px 14px; margin: 12px 0; font-size: 13px;
  line-height: 1.55; color: var(--text-secondary); }
.help-doc .callout.warn { border-left-color: var(--warn); background: var(--warn-bg); }
.help-doc .callout.tip { border-left-color: var(--ok); }
.help-doc .callout.info { border-left-color: var(--info); }
.help-doc .callout .clabel { font-weight: 600; color: var(--text-primary); margin-right: 4px; }
.inline-help { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; border-radius: 50%; background: var(--layer-03); color: var(--text-helper); font-size: 11px; cursor: help; margin-left: 6px; position: relative; }
.inline-help:hover::after { content: attr(data-help); position: absolute; left: 20px; top: -4px; width: 260px; background: var(--layer-03); color: var(--text-primary); border: 1px solid var(--border-strong); border-radius: 6px; padding: 8px 10px; font-size: 12px; line-height: 1.45; z-index: 30; white-space: normal; box-shadow: 0 6px 20px rgba(0,0,0,.4); }

/* ---------- transcript timeline ---------- */
.timeline { padding: 6px 0; }
.tl-row { display: grid; grid-template-columns: 56px 70px 1fr; gap: 10px; padding: 6px 14px; align-items: baseline; }
.tl-row:hover { background: var(--layer-02); }
.tl-row.active { background: var(--layer-02); box-shadow: inset 3px 0 0 var(--accent); }
.tl-ts { font-family: var(--mono); font-size: 12px; color: var(--text-helper); cursor: pointer; }
.tl-who { font-size: 11px; font-weight: 600; letter-spacing: .04em; }
.tl-who.lena { color: var(--accent); } .tl-who.caller { color: var(--text-secondary); } .tl-who.sys { color: var(--text-helper); }
.tl-text { font-size: 14px; line-height: 1.5; max-width: 72ch; white-space: pre-wrap; }
.tl-event { grid-column: 1 / -1; background: var(--layer-02); border-radius: 2px; padding: 4px 10px; font-size: 12px; color: var(--text-helper); }

/* ---------- audio bar ---------- */
.audio-bar {
  display: flex; align-items: center; gap: 12px; height: 48px; padding: 0 14px;
  background: var(--layer-02); border-top: 1px solid var(--border-subtle);
}
.audio-bar .time { font-family: var(--mono); font-size: 12px; color: var(--text-secondary); }
.audio-bar .seek { flex: 1; height: 4px; background: var(--layer-03); border-radius: 2px; cursor: pointer; position: relative; }
.audio-bar .seek .fill { position: absolute; inset: 0 auto 0 0; background: var(--accent); border-radius: 2px; width: 0; }

/* ---------- log viewer ---------- */
.logview {
  background: var(--terminal); font-family: var(--mono); font-size: 12px; line-height: 20px;
  overflow: auto; max-height: 460px; padding: 8px 12px; white-space: pre; border-radius: 0 0 4px 4px;
}
.logview .lv-err { color: var(--err); } .logview .lv-warn { color: var(--warn); } .logview .lv-dim { color: var(--text-disabled); }

/* ---------- split layout (master-detail) ---------- */
.split { display: grid; grid-template-columns: minmax(380px, 40%) 1fr; gap: 16px; align-items: start; }
.detail-empty { padding: 40px 14px; color: var(--text-helper); font-size: 13px; }
/* Die Zusammenfassung eines Anrufs. Bei einem Anruf ohne gespeicherten Verlauf ist sie der ganze
   Inhalt der Seite, also bekommt sie den Platz, den ein Fliesstext zum Lesen braucht. */
.call-summary {
  padding: 12px 14px; font-size: 14px; line-height: 1.55; max-width: 70ch;
  color: var(--text-primary); border-bottom: 1px solid var(--border-subtle);
}
.meta-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 1px; background: var(--border-subtle); border-bottom: 1px solid var(--border-subtle); }
.meta-grid > div { background: var(--layer-01); padding: 8px 12px; }
.meta-grid .k { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-helper); }
.meta-grid .v { font-size: 13px; margin-top: 2px; font-family: var(--mono); }

/* ---------- charts ---------- */
.chart-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.chart-grid .wide { grid-column: 1 / -1; }
.chart-box { position: relative; height: 260px; padding: 10px; }
.chart-box.tall { height: 320px; }

/* ---------- flow editor ---------- */
.flow-wrap { display: grid; grid-template-columns: 200px 1fr 320px; gap: 0; height: calc(100vh - 160px); min-height: 480px; border: 1px solid var(--border-subtle); border-radius: 4px; overflow: hidden; }
.flow-palette { background: var(--layer-01); border-right: 1px solid var(--border-subtle); padding: 10px; overflow-y: auto; }
.flow-palette h3 { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-helper); margin: 4px 0 8px; }
.pal-node { border: 1px solid var(--border-strong); border-radius: 4px; background: var(--layer-02); padding: 8px 10px; font-size: 13px; margin-bottom: 8px; cursor: grab; }
.pal-node:hover { border-color: var(--accent); }
.pal-node .pd { font-size: 11px; color: var(--text-helper); margin-top: 2px; }
.flow-canvas-holder { position: relative; background: var(--bg); }
#drawflow { width: 100%; height: 100%; background-image: radial-gradient(var(--layer-02) 1px, transparent 1px); background-size: 16px 16px; }
.flow-config { background: var(--layer-01); border-left: 1px solid var(--border-subtle); overflow-y: auto; }
.flow-config .form-row { grid-template-columns: 1fr; gap: 4px; margin-bottom: 10px; }
/* Ein Kaestchen gehoert neben seine Beschriftung, nicht darunter. Die einspaltige Zeile oben ist
   fuer Textfelder gedacht und liess jeden Schalter allein in der Mitte stehen. */
.flow-config .check-row .check-label { display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 13px; font-weight: 500; color: var(--text-secondary); padding-top: 0; }
.flow-config .check-row .check-label input { width: auto; margin: 0; flex: none; }
.flow-config .form-row > label { padding-top: 0; }
.flow-config-empty { padding: 20px 14px; color: var(--text-helper); font-size: 13px; }
.flow-toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; flex-wrap: wrap; }
.flow-errors { background: var(--err-bg); border: 1px solid #fa4d5666; border-radius: 4px; padding: 10px 14px; font-size: 13px; color: var(--err); margin-bottom: 12px; }
.flow-errors ul { margin: 4px 0 0 18px; padding: 0; }

/* drawflow node restyle (flat, semantic top border per type) */
#drawflow .drawflow-node {
  background: var(--layer-01); border: 1px solid var(--border-strong); border-radius: 4px;
  color: var(--text-primary); padding: 0; min-width: 190px; width: auto; font-family: var(--sans);
}
#drawflow .drawflow-node.selected { border: 2px solid var(--accent); }
#drawflow .drawflow-node .drawflow_content_node { width: 100%; }
.df-node { border-top: 4px solid var(--neutral); border-radius: 4px 4px 0 0; padding: 8px 12px 10px; }
.df-node .df-title { font-size: 13px; font-weight: 600; }
.df-node .df-sub { font-size: 12px; color: var(--text-secondary); margin-top: 3px; max-width: 220px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.df-node .df-ports { margin-top: 6px; border-top: 1px solid var(--border-subtle); padding-top: 4px; }
.df-node .df-port { font-size: 11px; color: var(--text-helper); line-height: 1.5; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 210px; }
.df-node.t-start { border-top-color: var(--ok); }
.df-node.t-say { border-top-color: var(--info); }
.df-node.t-collect { border-top-color: var(--accent); }
.df-node.t-dialog { border-top-color: #d55181; }
.df-node.t-classify { border-top-color: var(--warn); }
.df-node.t-branch { border-top-color: #d4bbff; }
.df-node.t-knowledge { border-top-color: #08bdba; }
.df-node.t-redirect { border-top-color: var(--info); }
.df-node.t-confirm { border-top-color: #199e70; }
.df-node.t-end { border-top-color: var(--neutral); }
#drawflow .connection .main-path { stroke: var(--border-strong); stroke-width: 2px; fill: none; }
#drawflow .connection .main-path:hover, #drawflow .connection.selected .main-path { stroke: var(--accent); }
#drawflow .drawflow-node .input, #drawflow .drawflow-node .output {
  background: var(--layer-02); border: 2px solid var(--border-strong); width: 20px; height: 20px; cursor: crosshair; }
#drawflow .drawflow-node .output { background: var(--accent); border-color: var(--accent); }
#drawflow .drawflow-node .input:hover, #drawflow .drawflow-node .output:hover {
  border-color: var(--accent); box-shadow: 0 0 0 4px rgba(69,137,255,.25); }
.df-node.t-condition-if { border-top-color: #f1c21b; }
.df-node.t-instruct { border-top-color: #ff832b; }
.drawflow-delete { background: var(--err); border: 0; color: #fff; border-radius: 50%; font-family: var(--sans); line-height: 22px; }

/* ---------- login ---------- */
.login-wrap { max-width: 360px; margin: 12vh auto 0; }
.login-wrap .logo { text-align: center; margin-bottom: 18px; }
.login-wrap .logo img { height: 110px; }
.login-wrap h1 { font-size: 18px; text-align: center; margin: 0 0 16px; }
.login-err { color: var(--err); font-size: 13px; margin-bottom: 10px; }

/* ---------- misc ---------- */
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { display: inline-flex; align-items: center; gap: 6px; background: var(--layer-02); border: 1px solid var(--border-strong); border-radius: 12px; padding: 2px 10px; font-size: 12px; cursor: pointer; color: var(--text-secondary); }
.chip.active { border-color: var(--accent); color: var(--text-primary); }
.toast {
  position: fixed; right: 16px; bottom: 16px; background: var(--layer-03); border: 1px solid var(--border-strong);
  border-left: 3px solid var(--accent); border-radius: 4px; padding: 10px 16px; font-size: 13px; z-index: 99;
  opacity: 0; transition: opacity .2s; pointer-events: none;
}
.toast.show { opacity: 1; }
.toast.err { border-left-color: var(--err); }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
/* Chart.js keeps a 1:1 ratio unless told otherwise, and once responsive resizing runs, the canvas
   height attribute is only an initial hint. A square chart therefore grows as tall as its panel is
   wide, which is how one doughnut came to fill an entire column. Bound the box, not the canvas. */
.chart-box { position: relative; height: 260px; }
.chart-box.sm { height: 210px; }
.mt { margin-top: 16px; }
.muted { color: var(--text-helper); font-size: 12px; }
.mono { font-family: var(--mono); }
.svc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 1px; background: var(--border-subtle); }
.svc-grid > div { background: var(--layer-01); padding: 12px 14px; }
.svc-grid .name { font-size: 13px; font-weight: 500; display: flex; gap: 8px; align-items: center; }
.svc-grid .val { font-family: var(--mono); font-size: 12px; color: var(--text-helper); margin-top: 4px; }
.vram-bar { height: 8px; background: var(--layer-03); border-radius: 2px; overflow: hidden; margin-top: 6px; position: relative; }
.vram-bar .fill { height: 100%; background: var(--accent); }
.vram-bar .fill.hot { background: var(--warn); }
.emu-chat { min-height: 260px; max-height: 46vh; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding: 12px; }
.emu-msg { max-width: 78%; padding: 8px 12px; border-radius: 4px; font-size: 13px; white-space: pre-wrap; }
.emu-msg.lena { align-self: flex-start; background: var(--layer-02); border: 1px solid var(--border-subtle); }
.emu-msg.caller { align-self: flex-end; background: var(--info-bg); border: 1px solid #4589ff66; }
.emu-bar { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--border-subtle); }
.emu-bar input { flex: 1; }
/* The rail used to be FORCED collapsed here by CSS, which meant the toggle below 1280 px
   appeared to do nothing: the class said expanded and the media query overruled it. The
   width now decides the DEFAULT (in initRailToggle) and the class decides the state, so one
   thing is in charge and the toggle works at every size. */
@media (max-width: 980px) { .split, .chart-grid, .grid-2 { grid-template-columns: 1fr; } .flow-wrap { grid-template-columns: 170px 1fr; } .flow-config { display: none; } }


/* --- multi-tenancy --- */
/* Die Leiste ist ein ZUSAETZLICHES Kind von .shell, und .shell hat genau zwei Zeilen: 48px fuer
   die Kopfzeile, 1fr fuer den Rest. Sobald die Leiste da ist, rutscht alles eine Zeile weiter:
   die Leiste bekommt die 48px, die Kopfzeile das 1fr -- und war damit so hoch wie das Fenster.
   Sichtbar ausschliesslich beim Ansehen als Mandant, weshalb es lange niemandem auffiel.
   Deshalb setzt die Vorlage beim Ansehen zusaetzlich .has-impersonation, und dann gibt es drei
   Zeilen statt zwei. Kein :has(), damit es auch in aelteren Browsern stimmt. */
.shell.has-impersonation{grid-template-rows:auto 48px 1fr}
.impersonation-bar{grid-column:1/-1;display:flex;align-items:center;gap:12px;padding:8px 16px;
  background:#8a5a00;color:#fff;font-size:13px}
.impersonation-bar strong{font-weight:600}
.impersonation-bar .btn{margin-left:auto;border-color:rgba(255,255,255,.5);color:#fff}
.tenant-chip{padding:3px 10px;border:1px solid var(--line);border-radius:999px;font-size:12px;
  color:var(--muted);white-space:nowrap}
.tenant-table td .muted{font-size:12px}
.key-reveal{font-family:Consolas,monospace;font-size:12px;word-break:break-all;padding:8px;
  border:1px dashed var(--line);border-radius:6px;background:var(--panel-2)}

/* --- API handbook page --- */
.doc-toc ol{margin:8px 0 0 18px;line-height:1.9}
.doc-sec h3{margin:16px 0 6px;font-size:14px}
.doc-sec p{max-width:840px;line-height:1.6}
.doc-code{background:var(--panel-2);border:1px solid var(--line);border-radius:6px;padding:10px 12px;
  overflow-x:auto;font-size:12px;line-height:1.5}
.callout{background:#fff6e0;border:1px solid #e0b357;color:#5a4200;border-radius:6px;padding:9px 12px;
  margin:10px 0;max-width:840px}
@media (prefers-color-scheme: dark){.callout{background:#3a2f14;color:#f0dcae;border-color:#7a6329}}

/* Modal used by the admin console to edit one tenant. Plain overlay: the console is operator-only
   and a dialog library for two fields would be more code than the feature. */
.modal-wrap{position:fixed;inset:0;background:rgba(8,16,24,.55);display:flex;align-items:center;
  justify-content:center;z-index:60;padding:20px}
.modal-wrap[hidden]{display:none}
.modal{background:var(--panel,#fff);border:1px solid var(--line,#d5dde5);border-radius:10px;
  width:min(560px,100%);box-shadow:0 18px 50px rgba(8,16,24,.28);max-height:90vh;overflow:auto}

/* A notice is not a failure. Same shape as .flow-errors so it sits naturally above the canvas, but
   in the warning colour, because it reports a state to look at rather than a rejected action. */
.flow-notice { background: var(--warn-bg, #fff6e0); border: 1px solid #e0b35766; border-radius: 4px;
  padding: 10px 14px; font-size: 13px; color: var(--warn, #8a6100); margin-bottom: 12px; }

/* ---- Drucken ----
   The Ausfallzeugnis exists to be handed to a customer, and "Drucken" on a dark portal page
   otherwise produces four pages of navigation rail in reverse video. Scoped to print only, so it
   cannot affect the screen. Forced to black on white: a browser printing a dark page either wastes
   a cartridge or drops the background and leaves pale grey text on white. */
@media print {
  .rail, .topbar, .impersonation-bar, .toast, .actions, .tabbar { display: none !important; }
  .shell, .main { display: block !important; margin: 0 !important; padding: 0 !important; }
  html, body, .panel, .kpi, .kpi-row, table.tbl, .tbl-wrap {
    background: #fff !important; color: #000 !important; box-shadow: none !important;
  }
  .panel, .kpi-row, .kpi, .tbl thead th, .tbl tbody td { border-color: #bbb !important; }
  .tbl thead th { background: #eee !important; color: #000 !important; }
  .muted, .kpi .label, .kpi .delta, .panel-head .sub { color: #444 !important; }
  a { color: #000 !important; text-decoration: none; }
  /* A table split across a page break loses its header, and this one is read row by row. */
  table.tbl { page-break-inside: auto; }
  .tbl tbody tr { page-break-inside: avoid; }
  .tbl-wrap { overflow: visible !important; }
  .page-head h1 { font-size: 20pt; }
}

/* ---- Handbuch: zwei Spalten ----
   The Bedienung tab was a single 820 px column inside a full-width main area, so a wide screen
   showed a narrow ribbon of text with a lot of nothing beside it, while the API tab next to it used
   the whole width. Twenty-two sections also had no visible position: the table of contents was one
   block at the top that scrolled away and never came back.

   Now the contents stay put and the text takes the rest. The measure is still bounded, because a
   110-character line is not more readable for being possible. */
.help-layout { display: grid; grid-template-columns: 262px minmax(0, 1fr); gap: 26px; align-items: start; }
.help-layout .help-doc { max-width: 1000px; }

.help-nav {
  position: sticky; top: 0; align-self: start;
  max-height: calc(100vh - 150px); overflow-y: auto;
  border-right: 1px solid var(--border-subtle); padding-right: 14px;
}
.help-nav input[type="search"] { width: 100%; margin-bottom: 4px; }
.help-nav-hint { font-size: 11.5px; color: var(--text-helper); min-height: 15px; margin-bottom: 6px; }
.help-nav nav { display: flex; flex-direction: column; }
.help-nav nav > a {
  display: block; padding: 4px 8px; font-size: 13px; line-height: 1.35; border-radius: 4px;
  color: var(--text-secondary); border-left: 2px solid transparent;
}
.help-nav nav > a:hover { background: var(--layer-02); color: var(--text-primary); }
.help-nav nav > a.current {
  color: var(--text-primary); font-weight: 600;
  border-left-color: var(--accent); background: var(--layer-02);
}
/* Subsections are shown for the section being read, and for a section the reader is pointing at.
   All of them at once is a 90-entry wall nobody scans. */
.help-nav .help-sub { display: none; flex-direction: column; margin: 1px 0 5px 12px; }
.help-nav .help-sub.open { display: flex; }
.help-nav .help-sub a {
  display: block; padding: 2px 8px; font-size: 12px; line-height: 1.35;
  color: var(--text-helper); border-left: 1px solid var(--border-subtle);
}
.help-nav .help-sub a:hover { color: var(--text-primary); }

/* Search hides what does not match instead of scrolling to one hit: the question is usually "where
   is this mentioned", and the answer is better as a shortened manual than as a jump. */
/* Scoped to the layout, not to the document: the search also shrinks the table of contents, and
   that lives in the sidebar. Scoped to .help-doc it was set on the nav links and hid nothing. */
.help-layout .hide-search { display: none !important; }
.help-doc mark { background: var(--warn-bg); color: inherit; border-radius: 2px; padding: 0 1px; }
.help-empty { padding: 20px 0; color: var(--text-helper); font-size: 14px; }

/* Anchored headings sit under nothing here, but a jump that lands with the heading flush against
   the top edge reads as if the section began mid-sentence. */
.help-doc h2, .help-doc h3 { scroll-margin-top: 12px; }

@media (max-width: 1100px) {
  .help-layout { grid-template-columns: 1fr; gap: 12px; }
  .help-nav { position: static; max-height: none; border-right: 0; padding-right: 0;
              border-bottom: 1px solid var(--border-subtle); padding-bottom: 10px; }
  .help-nav nav { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
  .help-nav .help-sub { display: none !important; }
}

/* ---------- Menü im Aktionsbereich ----------
   The flow editor had fourteen controls in one non-wrapping row: about 1400 px before it started
   pushing things off the side of a laptop. Grouping them needed a menu, and the portal had none.

   Two rules the grouping follows, so nothing important ends up hidden:
     - anything somebody does on most visits stays a visible button (Testen, Speichern,
       Veröffentlichen)
     - a menu only ever holds actions of ONE kind, and its label says which kind */
.menu { position: relative; display: inline-flex; }
.menu > .btn::after {
  content: ""; margin-left: 6px; width: 0; height: 0;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 4px solid currentColor; opacity: .7;
}
.menu-pop {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 40; min-width: 230px;
  background: var(--layer-01); border: 1px solid var(--border-strong); border-radius: 6px;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .35); padding: 4px; display: none;
}
.menu.open .menu-pop { display: block; }
.menu.open > .btn { background: var(--layer-02); color: var(--text-primary); }
.menu-pop button, .menu-pop a {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 7px 10px; border: 0; border-radius: 4px; background: none; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--text-secondary); white-space: nowrap;
}
.menu-pop button:hover, .menu-pop a:hover {
  background: var(--layer-02); color: var(--text-primary); text-decoration: none;
}
.menu-pop button[disabled] { opacity: .45; cursor: default; }
.menu-pop button[disabled]:hover { background: none; color: var(--text-secondary); }
.menu-pop .menu-sep { border-top: 1px solid var(--border-subtle); margin: 4px 2px; }
.menu-pop .menu-label {
  padding: 6px 10px 3px; font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-helper);
}
.menu-pop .menu-hint { font-size: 11.5px; color: var(--text-helper); padding: 0 10px 6px; white-space: normal; max-width: 260px; }
.menu-pop svg { width: 14px; height: 14px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.4; }

/* An icon-only action. The label lives in the tooltip and in the menu, never nowhere. */
.btn.icon { padding: 0 9px; }
.btn.icon svg { width: 15px; height: 15px; display: block; fill: none; stroke: currentColor; stroke-width: 1.5; }

/* A toolbar that cannot wrap pushes its last button off the screen instead of onto a second row,
   and the last button here is Veröffentlichen. */
.page-head { flex-wrap: wrap; }
.page-head .actions { flex-wrap: wrap; row-gap: 8px; }

/* ---------- Seitenleiste einklappen ----------
   The collapsed grid column and the hidden labels were already here and nothing ever set the class,
   so it was dead CSS. The toggle is in the topbar and the choice is remembered per browser. */
.rail-toggle { padding: 0 8px; }
.rail-toggle svg { width: 15px; height: 15px; display: block; fill: none; stroke: currentColor; stroke-width: 1.5; }
.shell.rail-collapsed .rail a { justify-content: center; padding: 0; }
.shell.rail-collapsed .rail a svg { width: 18px; height: 18px; }
.shell.rail-collapsed .rail .divider { margin: 8px 10px; }


/* ---------- Lehrvideos ---------- */
/* Grosser Abspieler ueber der Seite. Nicht herunterladen: wer erst eine Datei speichern muss,
   sieht sie nicht an. */
.video-back{position:fixed;inset:0;z-index:1000;background:rgba(8,16,24,.72);
  display:flex;align-items:center;justify-content:center;padding:24px}
.video-box{background:var(--layer-01);border:1px solid var(--border-subtle);border-radius:6px;
  width:min(1280px,94vw);max-height:92vh;display:flex;flex-direction:column;overflow:hidden;
  box-shadow:0 24px 70px rgba(8,16,24,.45)}
.video-head{display:flex;align-items:center;gap:12px;padding:10px 14px;
  border-bottom:1px solid var(--border-subtle)}
.video-head > div:first-child{flex:1;min-width:0}
.video-box video{width:100%;max-height:calc(92vh - 108px);background:#000;display:block}
.video-desc{padding:10px 14px;font-size:13px;border-top:1px solid var(--border-subtle)}

.video-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:10px;
  padding:12px 14px}
.video-card{display:flex;gap:12px;align-items:flex-start;padding:12px;cursor:pointer;
  border:1px solid var(--border-subtle);border-radius:4px;background:var(--layer-02)}
.video-card:hover{border-color:var(--accent)}
.video-play{flex:none;width:34px;height:34px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;background:var(--accent);color:#fff;font-size:13px}
.video-title{font-weight:600;font-size:13px;margin-bottom:2px}
.video-sub{font-size:12px;line-height:1.45}
.video-min{font-size:11px;margin-top:4px;font-family:var(--mono)}
@media print{.video-back,.video-cards{display:none !important}}
