/* aorta-ui — schlanke Chat-Oberflaeche. Keine Fremdfont, kein Framework. */

:root {
  --bg: #fafaf9;
  --fg: #1a1a1a;
  --fg-dim: #5c5c5c;
  --border: #d8d8d5;
  --accent: #a51e1e;
  --accent-dim: #f5e6e6;
  --user-bg: #eef2f7;
  --assistant-bg: #f6f2ea;
  --system-bg: #f0f0e8;
  --tool-bg: #eae5f0;
  --verdichtung-bg: #e6f2ea;
  /* --warning wird auf --bg (#fafaf9) verwendet. #8a5a00 auf #fafaf9 hat
     einen Kontrast von ~4.28:1 — knapp unter WCAG AA (4.5:1) fuer Fliesstext.
     #6b4700 kommt auf ~5.7:1 und bleibt visuell noch "amber". */
  --warning: #6b4700;
  --shadow: 0 1px 2px rgba(0,0,0,0.05);
  /* Linienstaerke aller Rahmen und Trennlinien; die Brillen-Ansicht setzt 2px. */
  --lw: 1px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #17181a;
    --fg: #e6e6e6;
    --fg-dim: #a1a1a1;
    /* war #34363a: auf --bg nur 1.4:1, in der XR-Brille (175 %) kaum noch
       sichtbar. #4c5057 kommt auf ~2.1:1 und bleibt ruhig. */
    --border: #4c5057;
    --accent: #ff7676;
    --accent-dim: #40222a;
    --user-bg: #22262c;
    --assistant-bg: #2a251d;
    --system-bg: #262622;
    --tool-bg: #2a2432;
    --verdichtung-bg: #1e2a20;
    --warning: #d4a54a;
    --shadow: 0 1px 2px rgba(0,0,0,0.35);
  }
}

/* Brillen-Ansicht (Schalter im Geraete-Dialog, je Geraet): 2px-Linien in
   deutlich hellerer Farbe fuer Micro-OLED-Brillen mit Skalierung, wo
   1px-Linien zwischen die Pixel fallen. Nur Linien, keine Abstaende. Der
   Nutzer-Kasten bekommt einen Innenrand (box-shadow, kostet keinen Platz). */
html.brille { --lw: 2px; --border: #a3a39e; }
@media (prefers-color-scheme: dark) {
  html.brille { --border: #7d828b; }
}
html.brille .msg[data-role="user"] .msg-body {
  box-shadow: inset 0 0 0 var(--lw) var(--border), var(--shadow);
}

* { box-sizing: border-box; }

/* [hidden] muss JEDE display-Regel schlagen. Ohne diese Zeile gewinnt eine
   Klassenregel wie `.overlay { display: flex }` gegen das display:none aus
   dem Browser-Stylesheet — die Fenster liessen sich dann nicht schliessen,
   obwohl das JS `el.hidden = true` sauber setzt. Gemessen 10.09.2026 an
   Geraete- und Werkzeuge-Fenster. Dieselbe Falle wie bei `.pane` unter
   900 px. */
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; }
body {
  font: 14px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg); color: var(--fg);
  display: flex; flex-direction: column;
}

.topbar {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.4rem 0.8rem;
  background: var(--bg); border-bottom: var(--lw) solid var(--border);
}
.topbar .brand { font-weight: 600; color: var(--accent); letter-spacing: 0.02em; }
.topbar .status { margin-left: auto; color: var(--fg-dim); font-size: 1.2rem; line-height: 1; }
.topbar .status.ok { color: #2f8a3d; }
.topbar .status.bad { color: var(--accent); }

/* tsk-af-ui-vorlesen-spalten — verstellbare Spalten via CSS-Variablen.
   Fuenf Grid-Spalten: [Chats] [Griff] [Chat] [Griff] [Kontext]. Die zwei
   Griffe sind 6 px schmal, sie sind die Klick-Flaeche fuers Ziehen. Die
   Breiten der Aussen-Spalten setzt JS je nach gespeichertem Zustand; hier
   ist die Vorgabe die alte (240 / 320). */
.layout {
  flex: 1 1 auto; min-height: 0;
  display: grid;
  --col-left: 240px;
  --col-right: 320px;
  --col-handle: 6px;
  grid-template-columns:
    var(--col-left) var(--col-handle) 1fr var(--col-handle) var(--col-right);
  gap: 0;
}
@media (max-width: 900px) {
  /* Unter 900 px bleibt das alte Verhalten: nur der Chat-Bereich ist da,
     die zwei Seitenspalten und ihre Griffe verschwinden vollstaendig. */
  .layout { grid-template-columns: 1fr; }
  .pane-chats, .pane-context, .pane-resize { display: none; }
}

/* Griff zwischen zwei Panes. `col-resize`-Cursor macht den Zweck sichtbar,
   ohne dass ein Icon noetig waere. Der schmale Balken hebt sich beim
   Zeigen kurz ab, damit die Klick-Zone erkennbar ist. */
.pane-resize {
  background: var(--border);
  cursor: col-resize;
  user-select: none;
  transition: background 120ms ease;
}
.pane-resize:hover,
body.resizing .pane-resize { background: var(--accent); }
/* Wenn die zugehoerige Spalte zugeklappt ist, ist der Griff sinnlos —
   deaktivieren und optisch ausblenden. Aufklappen macht der Knopf. */
.layout.left-collapsed  .pane-resize[data-side="left"],
.layout.right-collapsed .pane-resize[data-side="right"] {
  pointer-events: none;
  background: transparent;
}
body.resizing { cursor: col-resize; }
body.resizing * { user-select: none !important; }

/* Zugeklappte Pane: Nur der Kopf mit dem Aufklapp-Knopf ist sichtbar,
   alles andere (Liste, Zusammenfassung, Kaestchen) faellt raus. Der
   Kopf wird eng, damit die 32-px-Spalte nicht platzt. */
.layout.left-collapsed  .pane-chats   > *:not(.pane-head),
.layout.right-collapsed .pane-context > *:not(.pane-head) { display: none; }
.layout.left-collapsed  .pane-chats   .pane-head > *:not(.pane-collapse),
.layout.right-collapsed .pane-context .pane-head > *:not(.pane-collapse) { display: none; }
.layout.left-collapsed  .pane-chats   .pane-head,
.layout.right-collapsed .pane-context .pane-head {
  padding: 0.5rem 0.15rem;
  justify-content: center;
  writing-mode: horizontal-tb;
}
.layout.left-collapsed  .pane-chats   .pane-collapse,
.layout.right-collapsed .pane-context .pane-collapse {
  margin-left: 0;
  margin-right: 0;
  width: 100%;
}

/* Einklapp-Knopf im Panel-Kopf. Rechtes Panel: der Knopf gehoert an den
   Anfang, damit er in der zugeklappten Ansicht direkt am inneren Rand
   steht (er zeigt dann nach links, "hier wieder rausziehen"). */
.pane-collapse {
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border);
  border-radius: 4px; padding: 0.05rem 0.4rem;
  cursor: pointer; font: inherit; font-size: 0.85rem;
  line-height: 1;
}
.pane-collapse:hover {
  background: var(--accent-dim); color: var(--accent); border-color: var(--accent);
}
.pane-context .pane-head .pane-collapse {
  order: -1;
  margin-left: 0;
}
.pane-head .pane-title { font-weight: 600; color: var(--fg-dim); }

.pane {
  display: flex; flex-direction: column;
  min-height: 0;
  border-right: var(--lw) solid var(--border);
  background: var(--bg);
}
.pane:last-child { border-right: none; }
.pane-head {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-bottom: var(--lw) solid var(--border);
  font-weight: 600; font-size: 0.9rem;
  color: var(--fg-dim);
  flex: 0 0 auto;
}
.pane-head button {
  margin-left: auto;
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border);
  border-radius: 4px; padding: 0.15rem 0.5rem;
  cursor: pointer; font: inherit;
}
.pane-head button:hover { background: var(--accent-dim); color: var(--accent); border-color: var(--accent); }

/* --- Chats pane --- */

.chats { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1 1 auto; }
.chats li {
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  border-bottom: var(--lw) solid var(--border);
  display: flex; flex-direction: column;
}
.chats li:hover { background: var(--accent-dim); }
.chats li.active { background: var(--accent-dim); color: var(--fg); }
.chats .chat-title { font-weight: 500; }
.chats .chat-sub { font-size: 0.75rem; color: var(--fg-dim); margin-top: 0.15rem; }
.chats .chat-flag {
  display: inline-block; margin-left: 0.4rem;
  font-size: 0.7rem; color: var(--accent);
  padding: 0 0.35rem; border: 1px solid var(--accent);
  border-radius: 8px;
}
.chats .chat-unread {
  display: inline-block; margin-left: 0.4rem;
  font-size: 0.7rem; color: white; background: var(--accent);
  padding: 0 0.4rem; border-radius: 8px;
  font-variant-numeric: tabular-nums;
}
.chats li.has-unread .chat-title { font-weight: 700; }
/* tsk-rk-punkte-server: blau (Weckruf angekommen, Antwort fehlt noch) und
   grau (still erledigt, ungelesen). tsk-nf-webui: orange (der Chat haengt).
   Punkt ohne Zahl, kleiner als der rote Zaehler; es steht immer hoechstens
   einer da (orange > rot > blau > grau). */
.chats .chat-punkt {
  display: inline-block; margin-left: 0.45rem;
  width: 0.5rem; height: 0.5rem; border-radius: 50%;
  vertical-align: middle;
}
.chats .chat-punkt-blau { background: #2f6fd6; }
.chats .chat-punkt-grau { background: #8a8a8a; }
/* Orange, nicht rot: rot ist bei Chunta seit je "ungelesen" und traegt eine
   Zahl. #d97706 liegt weit genug von --accent (#a51e1e) weg, um im
   Augenwinkel nicht dasselbe zu sein. */
.chats .chat-punkt-orange { background: #d97706; }
@media (prefers-color-scheme: dark) {
  .chats .chat-punkt-blau { background: #6fa2ff; }
  .chats .chat-punkt-grau { background: #9a9a9a; }
  .chats .chat-punkt-orange { background: #f59e0b; }
}

/* tsk-kos-anzeigen — was der naechste Zug kostet.

   KEINE eigene Farbe. Die Liste hat vier Punktfarben mit einer Rangfolge
   (orange > rot > blau > grau); eine fuenfte waere das Alarm-Theater, das
   der Auftrag ausdruecklich ausschliesst, und sie wuerde mit orange um
   dieselbe Zeile streiten. Der Unterschied zwischen "guenstig" und "teuer"
   ist deshalb allein Daempfung und Gewicht:

     guenstig  gedaempft (--fg-dim), mager    -> man sieht es, wenn man hinsieht
     teuer     voller Vordergrund, 600        -> man sieht es, ohne hinzusehen

   Wo die Zahl steht und warum sie dort ganz bleibt, steht seit
   tsk-kos-sprache eine Regel weiter unten — sie haengt seither daran, ob die
   Uhr noch laeuft. */
.chats .chat-title { display: flex; align-items: center; min-width: 0; }
.chats .chat-title-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Fahne, Zaehler und Punkt bleiben ganz — gekuerzt wird der Name. */
.chats .chat-flag, .chats .chat-unread, .chats .chat-punkt { flex: 0 0 auto; }
/* tsk-kos-sprache — wie teuer ein Chat ist. Kein Token mehr, sondern ein
   Vielfaches mit einem kleinen Balken davor.

   Die Farbe zeigt IMMER den Zustand JETZT (Nachtrag Chunta, 21.09.): laeuft
   die Uhr, ist alles gruen und es steht die Restzeit da; das Vielfache haengt
   nur gedaempft hinterher. Erst nach Ablauf traegt die Zeile rot bzw. gelb.
   Welche Klasse gesetzt wird, entscheidet `kostenwort.js` (Feld `jetzt`) —
   hier steht nur, wie sie aussieht.

   ZWEI Plaetze, je nach Lage — und das ist kein Schoenheitsfehler, sondern
   der Punkt: kalt ist es ein Abzeichen (eine Zahl), warm ein Satz (eine
   Restzeit und ihr Ausblick). Ein Satz an den Platz eines Abzeichens
   gezwungen, hat den Chatnamen aufgefressen: gemessen in Chromium mit dieser
   Datei, bei `--col-left: 240px` blieben dem Namen 0,0 px. Der Nachtrag
   schreibt den warmen Fall ohnehin als Zeile ("noch 54 min günstig · dann
   12×"), mit der Restzeit zuerst. */
.chats .chat-kosten {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.72rem; font-weight: 400; color: var(--fg-dim);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Kalt: das Abzeichen ganz rechts in der Titelzeile. `margin-left: auto`
   schiebt es hinter Fahne und Punkt, `flex: 0 0 auto` haelt die Zahl ganz —
   gekuerzt wird der Name. Das traegt hier wieder, weil oben nur noch die
   Zahl steht (rund 75 px von 216 px); mit dem warmen Satz tat es das nicht.
   Was passt und was nicht, misst die Probe (j13) am gerenderten Bild nach —
   eine Untergrenze in der CSS wuerde statt dessen irgendwann die Zahl
   abschneiden, und eine halbe Zahl ist schlimmer als ein halber Name. */
.chats .chat-title > .chat-kosten { margin-left: auto; padding-left: 0.5rem; flex: 0 0 auto; }
/* Warm: die Zeile unter dem Namen, wo auch "laeuft…" steht. Hier ist die
   ganze Spaltenbreite da, der Name bleibt oben unangetastet. */
.chats .chat-sub > .chat-kosten { max-width: 100%; }
/* Der Trennpunkt aus dem Nachtrag. Er steht in der CSS und nicht im Text,
   damit `textContent` genau der Wortlaut aus `kostenwort.js` bleibt
   ("dann 11×") — vorgelesen wird ohnehin der `aria-label`-Satz. */
.chats .chat-sub > .chat-kosten .chat-kosten-dann::before {
  content: "·"; margin-right: 0.3rem; color: var(--fg-dim);
}
.chats .chat-kosten-balken {
  width: 2.2rem; height: 0.3rem; border-radius: 0.15rem;
  background: var(--kos-spur); overflow: hidden; flex: 0 0 auto;
}
.chats .chat-kosten-balken > i { display: block; height: 100%; background: currentColor; }
/* Die drei Stufen. `--kos-rot`/`-gelb`/`-gruen` stehen weiter unten im
   Abschnitt dieser Phase — dort, wo auch ihr dunkler Satz steht, damit ein
   Thema sie an EINER Stelle umstellt. */
.chats .chat-kosten-rot   { color: var(--kos-rot); }
.chats .chat-kosten-gelb  { color: var(--kos-gelb); }
.chats .chat-kosten-gruen { color: var(--kos-gruen); }
/* Nach Ablauf und ab gelb faellt die Zahl auf — vorher nicht. Ein guenstiger
   Chat soll ganz ruhig bleiben. */
.chats .chat-kosten.laut .chat-kosten-wort { font-weight: 600; }
/* "dann 12x" — der Ausblick neben der laufenden Uhr. Bewusst schwaecher als
   die Restzeit davor: die Restzeit ist die Auskunft ueber JETZT.

   Gedaempft heisst hier KLEINER und leichter, nicht blasser: das `opacity:
   0.8`, das hier stand, drueckte `--fg-dim` auf 4,00:1 gegen `--bg` und auf
   3,61:1 gegen die hervorgehobene Zeile. Das ist Text, den Chunta lesen
   soll — also gilt 4,5:1, und wo Daempfung und Schwelle sich widersprechen,
   gewinnt die Schwelle (Entscheidung 21.09., 16:15, Punkt 3). Ohne die
   Deckkraft steht `--fg-dim` bei 6,40 / 5,52 (hell) und 6,88 / 5,49
   (dunkel); die kleinere Schrift traegt die Daempfung allein. */
.chats .chat-kosten-dann {
  color: var(--fg-dim); font-size: 0.66rem; font-weight: 400;
}

/* Das Alter der Zahlen, einmal fuer die ganze Liste. Steht unter der Liste,
   nicht darueber: es ist eine Fussnote zu allen Zeilen, keine Ueberschrift.
   `flex: 0 0 auto` — die Liste darueber nimmt den Rest. */
.kosten-stand {
  flex: 0 0 auto;
  padding: 0.35rem 0.75rem;
  border-top: var(--lw) solid var(--border);
  font-size: 0.7rem; color: var(--fg-dim);
}

/* tsk-nf-webui: der Knopf "Nachforschen" traegt dieselbe Farbe wie der
   Punkt — er gehoert sichtbar zu ihm. Er steht ohnehin nur da, solange der
   offene Chat orange ist.
   `.pane-head` muss mit im Waehler stehen: `.pane-head button` (0,1,1) und
   `.pane-head button:hover` (0,2,1) schlagen sonst jede blosse Klasse, egal
   wie weit unten sie steht — daran haengt `.chat-action-danger:hover`
   heute schon wirkungslos in der Luft. */
.pane-head .chat-action-haengt { color: #b45309; border-color: #d97706; }
.pane-head .chat-action-haengt:hover { background: #d97706; color: #fff; border-color: #d97706; }
.pane-head .chat-action-haengt[disabled] { opacity: 0.6; cursor: progress; }
@media (prefers-color-scheme: dark) {
  .pane-head .chat-action-haengt { color: #f59e0b; border-color: #a06a0d; }
  .pane-head .chat-action-haengt:hover { background: #f59e0b; color: #17181a; border-color: #f59e0b; }
}

/* tsk-kos-umzug: „Umziehen" ist kein Loeschen — der alte Chat bleibt
   nachlesbar — und es ist auch kein Befund wie das orange „Nachforschen".
   Es ist ein Griff, den Chunta bewusst zieht. Darum ein eigener, ruhiger
   Blauton: nicht `--accent` (das ist hier rot und damit der Nachbar von
   `.chat-action-danger`), nicht amber (das gehoert dem haengenden Chat).

   #1d4ed8 auf --bg (#fafaf9) kommt auf ~6.9:1, #7dabff auf --bg (#17181a)
   auf ~8.0:1 — beide ueber WCAG AA, auch in der Brillen-Ansicht.

   `cursor: progress` im gesperrten Zustand ist derselbe Griff wie bei
   `.chat-action-haengt`: ein Umzug dauert, und der Zeiger soll das sagen,
   nicht nur der Streifen darunter. */
/* Beide Umzugs-Knoepfe tragen einen mehrwortigen Text („Umzug
   zurueckdrehen", „Zieht um …"). Ohne `nowrap` bricht er in der Leiste auf
   zwei Zeilen um, und die ganze Kopfzeile wird hoeher, sobald der Umzug
   laeuft — die Leiste huepfte unter dem Zeigefinger. */
.pane-head #btn-umziehen-chat,
.pane-head #btn-umzug-rueckweg { white-space: nowrap; }
.pane-head .chat-action-umzug { color: #1d4ed8; border-color: #3b6fe0; }
.pane-head .chat-action-umzug:hover { background: #1d4ed8; color: #fff; border-color: #1d4ed8; }
.pane-head .chat-action-umzug[disabled] { opacity: 0.6; cursor: progress; }
@media (prefers-color-scheme: dark) {
  .pane-head .chat-action-umzug { color: #7dabff; border-color: #3f5f91; }
  .pane-head .chat-action-umzug:hover { background: #7dabff; color: #17181a; border-color: #7dabff; }
}

/* Rueckmeldung des Knopfes: ein schmaler Streifen unter der Leiste. Kein
   Fenster, das weggeklickt werden muss — die Oberflaeche springt im selben
   Atemzug in den neuen Chat, und der Satz soll dort noch zu lesen sein. */
.nf-melder {
  padding: 0.35rem 1rem;
  font-size: 0.8rem;
  border-bottom: var(--lw) solid var(--border);
  background: var(--accent-dim);
  color: var(--fg);
}
.nf-melder-fehler { background: var(--accent-dim); color: var(--accent); font-weight: 600; }
/* Leer heisst unsichtbar — aber NICHT `display:none` und NICHT `hidden`.
   Die Region muss im Baum stehen bleiben, sonst liest ein Screenreader die
   Rueckmeldung nie vor (siehe den Kommentar an der Stelle in index.html).
   Null Hoehe, kein Rand, kein Grund: der Streifen ist da und nimmt nichts
   weg, bis ein Satz hineinkommt. */
.nf-melder:empty { padding: 0; border-bottom: 0; background: none; }

.topbar .device-label {
  color: var(--fg-dim); font-size: 0.8rem;
  font-family: ui-monospace, monospace;
  margin-left: 0.6rem;
}

.mark-read,
.chat-action {
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border);
  border-radius: 4px; padding: 0.15rem 0.5rem;
  cursor: pointer; font: inherit; font-size: 0.75rem;
}
.mark-read:hover,
.chat-action:hover { background: var(--accent-dim); color: var(--accent); border-color: var(--accent); }
.chat-action-danger:hover { background: #a4161a; color: #fff; border-color: #a4161a; }

/* --- Chat pane --- */

.pane-chat .pane-head { justify-content: space-between; }
.pane-chat .chat-meta { color: var(--fg-dim); font-weight: 400; font-size: 0.8rem; }

.messages {
  flex: 1 1 auto; overflow-y: auto;
  padding: 0.9rem 1rem 0.6rem;
  display: flex; flex-direction: column; gap: 0.55rem;
}

/* Grundgeruest einer Zeile: nur Layout, keine Farbe.
   Farbe/Bubble/Ausrichtung werden je nach Rolle gesetzt. So sieht die
   assistant-Nachricht ohne Kasten aus und der Verlauf wirkt wie ein Chat,
   nicht wie eine Auswahlliste. */
.msg {
  list-style: none;
  display: flex; align-items: flex-start; gap: 0.5rem;
  padding: 0;
  background: transparent;
  box-shadow: none;
  border-radius: 0;
  max-width: 100%;
}
/* tsk-aorta-kontext-ui, Auftrag 2: "ausser Kontext" wird NICHT mehr durch
   Verblassen gezeigt. `opacity: 0.45` zog den Fliesstext von 14.24 auf 3.60
   (dunkles Schema) bzw. von 16.66 auf 2.77 (helles) — beides unter der
   Schwelle 4.5, und in der Kopfzeile multiplizierte es sich mit deren
   eigenen 0.75 auf 0.338, also 1.81 bzw. 1.62. Das war genau der Text, den
   Chunta nicht lesen konnte. Die Marke steht jetzt als Randstrich plus Wort
   (siehe unten, nach den Rollen-Regeln); die Farbe bleibt voll.
   Das `transition: opacity` an `.msg` ist mit weggefallen: es blendete
   genau diesen Wechsel weich, und den gibt es nicht mehr. */

/* Nachrichtenkoerper: die eigentliche Zeilenbreite. Wir begrenzen sie hier,
   damit lange Antworten lesbar bleiben (Auftrag 3). Der Rand entsteht durch
   align-self der jeweiligen Rolle. */
.msg .msg-body {
  flex: 1 1 auto; min-width: 0;
  max-width: 70ch;
}

/* Kopfzeile leiser (Auftrag 4): kleiner und blasser als der Inhalt. Die
   Beschriftung darf den Blick nicht klauen.

   tsk-aorta-kontext-ui, Auftrag 2: sie war dreifach gedaempft — `--fg-dim`
   UND `0.68rem` UND `opacity: 0.75` uebereinander. Das ergab 4.42 (dunkel)
   und 3.61 (hell) bei 10.9 px. Gedaempft wird jetzt nur noch ueber die
   Farbe: `--fg-dim` steht allein fuer 6.88 bzw. 6.40, und 0.85rem (13.6 px)
   liest sich ohne Zusammenkneifen. Leiser als der 14-px-Fliesstext bleibt
   sie durch Farbe, Versalien und Sperrung — nicht durch Deckkraft. */
.msg .msg-head {
  display: flex; align-items: baseline; gap: 0.5rem;
  color: var(--fg-dim); font-size: 0.85rem; margin-bottom: 0.15rem;
}
/* Feste Reihenfolge in der Kopfzeile. Ohne sie landete die Marke
   "nur im Speicher" (ein ::after) hinter den Vorlese-Knoepfen ganz rechts,
   weit weg von dem, worauf sie sich bezieht. */
.msg .msg-role { text-transform: uppercase; letter-spacing: 0.05em; font-weight: 500; order: 1; }
.msg .msg-ts { font-variant-numeric: tabular-nums; order: 2; }
.msg .msg-head::after { order: 3; }
.msg .msg-head .msg-speak { order: 4; }
.msg .msg-head .msg-speak-from { order: 5; }
.msg .msg-head .msg-copy { order: 6; }
.msg .msg-text { white-space: pre-wrap; overflow-wrap: anywhere; }

/* tsk-abr-lesbar - Adressen im Nachrichtentext sind Anker (verlauf.js).
   Sichtbar unterstrichen und in der Akzentfarbe: der Befund war "Links
   werden auch nicht als solche erkannt". `overflow-wrap: anywhere` erbt
   der Anker von .msg-text, eine lange Adresse sprengt die Spalte also
   nicht. */
.msg .msg-text a.msg-link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.msg .msg-text a.msg-link:hover,
.msg .msg-text a.msg-link:focus-visible {
  background: var(--accent-dim);
  border-radius: 3px;
}
/* Bild-Links (`![name](/uploads/...)`) bekommen ihr Zeichen per CSS und
   nicht als Textknoten - so bleibt der markierte und kopierte Text genau
   der Name der Datei. */
.msg .msg-text a.msg-link-bild::before { content: "\1f5bc\fe0f  "; }
/* Auftrag 2: hier stand `--fg-dim` UND `opacity: 0.7`, und in einer Zeile
   ausser Kontext multiplizierte sich das mit deren 0.45 auf 0.315 —
   gemessen 1.74 (dunkel) und 1.57 (hell), die niedrigsten Werte im ganzen
   Bericht. Jetzt nur die Farbe: 5.88 bzw. 5.95, bei 0.8rem statt 0.7rem. */
.msg .msg-tokens { margin-top: 0.3rem; color: var(--fg-dim); font-size: 0.8rem; font-family: ui-monospace, monospace; }
.msg .msg-tokens.warn { color: var(--warning); }

/* Rolle „user" (Auftrag 2): eigene Nachricht ABGESETZT. Bubble rechts,
   distinktive Farbe. Nur diese Rolle bekommt einen Kasten. */
.msg[data-role="user"] { align-self: flex-end; flex-direction: row-reverse; max-width: 78ch; }
.msg[data-role="user"] .msg-body {
  background: var(--user-bg);
  padding: 0.5rem 0.75rem;
  border-radius: 12px 12px 3px 12px;
  box-shadow: var(--shadow);
}
.msg[data-role="user"] .msg-head { justify-content: flex-end; }

/* Rolle „assistant" (Auftrag 2): ruhig, ohne Kasten, links. */
.msg[data-role="assistant"] { align-self: flex-start; max-width: 78ch; }
.msg[data-role="assistant"] .msg-body {
  background: transparent;
  padding: 0 0.15rem;
}

/* Debug-artige Rollen — dezenter Kasten, kleiner, monospaced. Sie sind
   selten und sollen ihre Herkunft signalisieren, aber nicht mit dem
   eigentlichen Dialog konkurrieren. */
.msg[data-role="system"],
.msg[data-role="tool"],
.msg[data-role="verdichtung"] { align-self: stretch; max-width: 100%; }
.msg[data-role="system"] .msg-body,
.msg[data-role="tool"] .msg-body,
.msg[data-role="verdichtung"] .msg-body {
  padding: 0.35rem 0.55rem;
  border-radius: 4px;
  border-left: calc(var(--lw) + 1px) solid var(--border);
  max-width: none;
}
.msg[data-role="system"] .msg-body      { background: var(--system-bg); font-family: ui-monospace, monospace; font-size: 0.82rem; }
.msg[data-role="tool"] .msg-body        { background: var(--tool-bg);   font-family: ui-monospace, monospace; font-size: 0.82rem; }
.msg[data-role="verdichtung"] .msg-body { background: var(--verdichtung-bg); font-style: italic; }

/* --- tsk-aorta-kontext-ui, Auftrag 2: "ausser Kontext" ohne Verblassen ---

   Zwei Zeichen statt weniger Deckkraft: ein gestrichelter Randstrich am
   Nachrichtenkoerper und ein Wort in der Kopfzeile. Beides in `--fg-dim`,
   also 6.88 (dunkel) bzw. 6.40 (hell) — ueber den 3.0, die WCAG fuer eine
   grafische Marke verlangt, und ueber den 4.5 fuer das Wort.

   Gestrichelt, weil die Rollen system/tool/verdichtung schon einen
   durchgezogenen Strich in `--border` tragen; die zwei Bedeutungen duerfen
   nicht gleich aussehen. Diese Regeln stehen darum HINTER den Rollen-
   Regeln — gleiche Spezifitaet, es gewinnt die spaetere.

   Und der Wortlaut ist Absicht: "nur im Speicher", nicht "entfernt". Es ist
   dieselbe Marke wie im Kontext-Panel, und sie sagt genau das, was Kriterium
   6 verlangt — die Nachricht ist noch da. */
.msg.out-of-context .msg-body {
  border-left: 3px dashed var(--fg-dim);
  padding-left: 0.55rem;
}
/* Die user-Blase hat ein groesseres Polster (0.75rem); ihres bleibt, sonst
   rutscht der Text an den Strich. Die Kasten-Rollen system/tool/verdichtung
   stehen ohnehin schon auf 0.55rem und brauchen keine eigene Zeile. */
.msg.out-of-context[data-role="user"] .msg-body { padding-left: 0.75rem; }

.msg.out-of-context .msg-head::after {
  content: "nur im Speicher";
  text-transform: none; letter-spacing: 0;
  border: 1px solid var(--fg-dim);
  border-radius: 8px;
  padding: 0 0.4rem;
  white-space: nowrap;
}

/* Auswahl-Modus (Auftrag 1): Kaestchen an den Nachrichten nur sichtbar,
   wenn body.select-mode gesetzt ist. Ohne den Modus sind sie im DOM
   nicht sichtbar (display:none, also weder Fluss noch A11y-Baum). */
.msg .ctx-toggle { flex: 0 0 auto; padding-top: 0.35rem; display: none; }
body.select-mode .msg .ctx-toggle { display: block; }

.compose {
  flex: 0 0 auto;
  display: flex; flex-direction: column; gap: 0.4rem;
  padding: 0.5rem 0.75rem;
  border-top: var(--lw) solid var(--border);
  background: var(--bg);
}
.compose textarea {
  flex: 1 1 auto; resize: vertical;
  font: inherit;
  padding: 0.4rem 0.5rem;
  border: var(--lw) solid var(--border); border-radius: 4px;
  background: var(--bg); color: var(--fg);
  min-height: 2.2rem;
}
.compose textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.compose-row {
  display: flex; align-items: center; gap: 0.5rem;
}
.compose-row .spacer { flex: 1 1 auto; }
.compose button {
  background: var(--accent); color: white; border: none;
  border-radius: 4px; padding: 0.4rem 0.9rem;
  cursor: pointer; font: inherit;
}
.compose #btn-mic, .compose #btn-attach {
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border);
}
.compose #btn-mic:hover, .compose #btn-attach:hover {
  border-color: var(--accent); color: var(--accent); background: var(--accent-dim);
}
.compose #btn-mic.recording {
  background: var(--accent); color: white; border-color: var(--accent);
}
.compose button:disabled { opacity: 0.5; cursor: wait; }
.voice-status {
  color: var(--fg-dim); font-size: 0.78rem;
  font-family: ui-monospace, monospace;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}
.voice-status.err { color: var(--accent); }
.voice-status.warn { color: var(--warning); }

/* AP6 — Vorlesen-Knopf pro Nachricht. Klein, rechts in der Kopfzeile.
   tsk-af-ui-vorlesen-spalten — direkt daneben der "Ab hier"-Knopf. Nur
   der erste hat margin-left:auto, damit die beiden zusammen bleiben. */
.msg .msg-head .msg-speak {
  margin-left: auto;
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border);
  border-radius: 4px; padding: 0.05rem 0.4rem;
  font: inherit; font-size: 0.8rem;
  cursor: pointer;
}
.msg .msg-head .msg-speak-from,
.msg .msg-head .msg-copy {
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border);
  border-radius: 4px; padding: 0.05rem 0.4rem;
  font: inherit; font-size: 0.8rem;
  cursor: pointer;
}
.msg .msg-head .msg-speak:hover,
.msg .msg-head .msg-speak[aria-pressed="true"],
.msg .msg-head .msg-speak-from:hover,
.msg .msg-head .msg-speak-from[aria-pressed="true"],
.msg .msg-head .msg-copy:hover,
.msg .msg-head .msg-copy:focus-visible {
  color: var(--accent); border-color: var(--accent); background: var(--accent-dim);
}

/* Sprechende Nachricht deutlich markieren — im Verlauf muss sofort
   erkennbar sein, welche Zeile gerade laeuft. Wir setzen einen
   Akzent-Rahmen um den Nachrichtenkoerper (funktioniert fuer alle
   Rollen: user-Bubble, assistant-ohne-Kasten, system/tool/verdichtung
   mit linker Kante). Der Rahmen bleibt auch beim Neu-Rendern durch
   den Poller stehen, weil die Klasse aus state.speakingId kommt. */
.msg.speaking .msg-body {
  box-shadow: 0 0 0 2px var(--accent);
  border-radius: 6px;
}
.msg[data-role="assistant"].speaking .msg-body {
  padding: 0.3rem 0.5rem;
}
.msg.speaking .msg-role { color: var(--accent); font-weight: 700; }

/* --- Context pane --- */

.pane-context .pane-head { flex-wrap: wrap; row-gap: 0.35rem; }
.ctx-actions {
  display: flex; gap: 0.35rem; margin-left: auto; align-items: center;
  /* Drei Knoepfe (Auswahl + zwei Sammelknoepfe) passen im schmalen
     Kontext-Panel nicht in eine Zeile — brechen lassen statt abschneiden. */
  flex-wrap: wrap; justify-content: flex-end;
}
.ctx-actions button { margin-left: 0; padding: 0.15rem 0.5rem; }

/* Sammelknoepfe (Alles auswaehlen / abwaehlen) gehoeren in den Auswahl-Modus
   (Auftrag 1). Ausserhalb des Modus sind sie nicht sichtbar. */
body:not(.select-mode) #btn-select-all,
body:not(.select-mode) #btn-deselect-all { display: none; }

/* Der Kasten in der Kontext-Liste teilt dieselbe Regel: nur im Modus da.
   'label' ist die Klick-Flaeche des Kaestchens; ohne label bleibt eine
   leere Grid-Spalte, das ist ok — die Struktur ist stabil. */
body:not(.select-mode) .ctx-row label { display: none; }

/* Der Umschalter zeigt seinen Zustand deutlich: ist er an, hat er die
   Akzentfarbe wie ein gedrueckter Knopf. */
#btn-toggle-select[aria-pressed="true"] {
  background: var(--accent-dim);
  color: var(--accent);
  border-color: var(--accent);
}

.ctx-summary {
  padding: 0.6rem 0.75rem;
  border-bottom: var(--lw) solid var(--border);
  display: flex; align-items: baseline; gap: 0.35rem;
  color: var(--fg-dim); font-size: 0.85rem;
}
.ctx-summary .ctx-num {
  font-family: ui-monospace, monospace;
  color: var(--fg); font-weight: 600;
}
.ctx-summary .ctx-arrow { color: var(--fg-dim); }
.ctx-summary .ctx-ratio { margin-left: auto; font-family: ui-monospace, monospace; }
.ctx-summary .ctx-ratio.warn { color: var(--warning); }
/* Ohne Beschriftung stand hier nur "– → –" — richtig gerechnet, aber
   niemand konnte sehen, was da gerechnet wird. */
.ctx-summary .ctx-summary-name { color: var(--fg-dim); font-size: 0.8rem; }

.ctx-list { list-style: none; padding: 0; margin: 0; overflow-y: auto; flex: 1 1 auto; }
/* tsk-aorta-kontext-ui: zwei Zeilen statt einer. Die Kopfzeile bleibt wie
   bisher (Kaestchen, Rolle, Vorschau); darunter kommen Token-Zahl und die
   Lage-Marke. In eine einzige Zeile passt beides in einer schmalen Spalte
   nicht, ohne dass die Vorschau auf ein paar Zeichen zusammenschrumpft. */
.ctx-row {
  display: grid;
  grid-template-columns: auto 4.6rem 1fr;
  grid-template-areas:
    "check role    preview"
    "check tokens  lage";
  align-items: center;
  gap: 0.1rem 0.4rem;
  padding: 0.35rem 0.75rem;
  border-bottom: var(--lw) solid var(--border);
  /* Auftrag 2: 0.82rem waren 13.1 px in einer ohnehin schmalen Spalte. */
  font-size: 0.9rem;
}
.ctx-row > label      { grid-area: check; }
.ctx-row .ctx-role    { grid-area: role; }
.ctx-row .ctx-preview { grid-area: preview; }
.ctx-row .ctx-tokens  { grid-area: tokens; }
.ctx-row .ctx-lage    { grid-area: lage; justify-self: end; }
/* Auftrag 2: hier stand dasselbe `opacity: 0.45` wie im Verlauf — es zog
   die Vorschau auf 3.84 (dunkel) bzw. 2.86 (hell) und Rolle/Token/Marke auf
   2.41 bzw. 2.01. Dieselbe Loesung wie dort: gestrichelter Randstrich, volle
   Farbe. Die Marke in Worten steht in dieser Zeile ohnehin schon
   ("nur im speicher", .ctx-lage), sie wird jetzt nur endlich lesbar. */
.ctx-row.out-of-context {
  border-left: 3px dashed var(--fg-dim);
  padding-left: calc(0.75rem - 3px);
}

/* --- tsk-aorta-kontext-ui: Vormerkung, Token-Rechnung, Verdichten --- */

/* Der Vormerk-Balken. Er ist auffaellig, weil er eine Aussage traegt, die
   sonst niemand sieht: "es ist noch nichts gespeichert". */
.ctx-pending {
  margin: 0.5rem 0.75rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--accent, #4a9);
  border-left-width: 3px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent, #4a9) 10%, transparent);
  display: flex; flex-direction: column; gap: 0.5rem;
}
.ctx-pending-count { font-size: 0.9rem; }
.ctx-pending-count strong { color: var(--accent, #4a9); }
.ctx-pending-buttons { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.ctx-pending-buttons button { font-size: 0.85rem; }
.ctx-pending-note {
  margin: 0; font-size: 0.82rem; line-height: 1.4; color: var(--fg-dim);
}
.ctx-pending-note strong { color: var(--fg); }

/* tsk-ax-kontext-wirkt: der Preis-Satz. Er steht auf derselben Stufe wie der
   Satz darueber (keine vierte Daempfung, siehe tsk-aorta-kontext-ui), traegt
   aber oben eine feine Trennlinie — er sagt etwas anderes als "es wird nichts
   geloescht", naemlich was es kostet. */
.ctx-pending-preis {
  padding-top: 0.45rem;
  border-top: 1px solid color-mix(in srgb, var(--fg-dim, #888) 30%, transparent);
}

/* Der Deckel-Hinweis. Sichtbar nur, wenn die Auswahl NICHT darunter passt —
   dann ist er eine Warnung und darf die Daempfung verlassen. */
.ctx-deckel {
  margin: 0.4rem 0 0; font-size: 0.82rem; line-height: 1.4;
  color: var(--warning);
}

/* Ergebnis des letzten `Anwenden` fuer die Sitzung. Normalfall gedaempft;
   ging das Schliessen am Laeufer schief, faerbt .warn sie ein. */
.ctx-sitzung-note {
  margin: 0.4rem 0 0; font-size: 0.82rem; line-height: 1.4;
  color: var(--fg-dim);
}
.ctx-sitzung-note.warn { color: var(--warning); }

/* Zeilen, deren Vormerkung vom gespeicherten Stand abweicht. */
.ctx-row.vorgemerkt-geaendert {
  outline: 1px dashed var(--accent, #4a9);
  outline-offset: -1px;
}

/* Token-Rechnung: vier Zeilen, Zahl rechtsbuendig und monospaced, damit
   Groessenordnungen untereinander vergleichbar bleiben. */
.ctx-rechnung {
  margin: 0.5rem 0.75rem 0.25rem;
  display: flex; flex-direction: column; gap: 0.15rem;
  font-size: 0.85rem;
}
.ctx-rechnung-zeile {
  display: grid;
  grid-template-columns: 7.5rem auto;
  align-items: baseline;
  column-gap: 0.5rem;
}
.ctx-rechnung-name { color: var(--fg-dim); }
.ctx-rechnung-wert {
  font-family: ui-monospace, monospace;
  color: var(--fg);
}
.ctx-rechnung-wert.vorgemerkt { color: var(--accent, #4a9); }
.ctx-rechnung-sub {
  grid-column: 2; color: var(--fg-dim); font-size: 0.8rem;
}

.ctx-tools {
  margin: 0.25rem 0.75rem 0.5rem;
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem;
}
.ctx-tools button { font-size: 0.85rem; }
.ctx-compact-note { color: var(--fg-dim); font-size: 0.8rem; }

/* Die Lage-Marke je Zeile: "im kontext" vs. "nur im speicher". Das ist die
   Stelle, an der das Versprechen "abwaehlen loescht nicht" je Nachricht
   ablesbar wird. */
.ctx-row .ctx-lage {
  font-size: 0.78rem; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent, #4a9); white-space: nowrap;
}
.ctx-row .ctx-lage.nur-speicher { color: var(--fg-dim); }
.ctx-row .ctx-role {
  color: var(--fg-dim); text-transform: uppercase; font-size: 0.8rem;
  letter-spacing: 0.06em;
  /* Ohne die Begrenzung laeuft 'ASSISTANT' in die Vorschau hinein und die
     zwei Spalten kleben aneinander. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ctx-row .ctx-preview { color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctx-row .ctx-tokens { color: var(--fg-dim); font-family: ui-monospace, monospace; font-size: 0.8rem; }

/* --- Empty state --- */

.empty {
  color: var(--fg-dim); padding: 1rem 1.25rem;
  text-align: center; font-style: italic;
}

/* Nur fuer Screenreader sichtbar: Labels, die den visuellen Fluss nicht
   stoeren sollen (z.B. das Compose-Feld, dessen Zweck durch die Platzierung
   im Chat-Panel augenscheinlich klar ist, aber ohne <label> unangesagt
   bliebe). Klassische clip-Technik, gleiche Wirkung wie WAI-ARIA-Label,
   aber ohne aria-Duplizierung. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- Geraete-Verwaltung (tsk-aorta-geraeteverwaltung) --------------------
   Dialog mit dunklem/ruhigem .pane-Stil, aufgerufen ueber den "Geraete"-
   Knopf oben in der Kopfzeile. Der Overlay-Hintergrund dimmt die Seite,
   der Dialog selbst laeuft im Kartenraster (Name, Lesegruppe, gesehen-
   Zeitstempel, Token-Zustand, Aktionen). Der Rohtoken taucht NIRGENDS
   auf — nicht ausklappbar, nicht mit Tooltip. */

.topbar-action {
  margin-left: auto;
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border);
  border-radius: 4px; padding: 0.2rem 0.55rem;
  cursor: pointer; font: inherit; font-size: 0.8rem;
}
.topbar-action:hover {
  background: var(--accent-dim); color: var(--accent);
  border-color: var(--accent);
}
/* Der Verbindungspunkt bleibt ganz rechts, auch wenn der Knopf davor
   die margin-left:auto der .status-Regel verdraengt. */
.topbar-action + .status { margin-left: 0.5rem; }

/* Schalter Brillen-Ansicht links neben „Geraete": er schiebt nach rechts,
   der Geraete-Knopf rueckt direkt an ihn heran. */
.topbar-brille {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 0.3rem;
  color: var(--fg-dim); font-size: 0.8rem; cursor: pointer;
}
.topbar-brille input { margin: 0; cursor: pointer; }
.topbar-brille + .topbar-action { margin-left: 0; }

.overlay {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 3vh 1rem;
  z-index: 100;
}
.overlay .dialog {
  background: var(--bg);
  border: var(--lw) solid var(--border);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  width: min(1000px, 96vw);
  max-height: 90vh;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.overlay .dialog .pane-head {
  padding: 0.5rem 0.75rem;
  gap: 0.6rem;
}
.overlay .dialog .pane-head .pane-collapse {
  margin-left: auto;
  font-size: 1.1rem; line-height: 1;
}
.overlay .devices-hint {
  color: var(--fg-dim); font-size: 0.8rem;
  font-family: ui-monospace, monospace;
}
.overlay .devices-body {
  overflow-y: auto; padding: 0.75rem 1rem 1rem;
}
.overlay .devices-status {
  min-height: 1.4em; margin-bottom: 0.5rem;
  color: var(--fg-dim); font-size: 0.85rem;
}
.overlay .devices-status.ok  { color: #2f8a3d; }
.overlay .devices-status.err { color: var(--accent); }

.devices-table {
  width: 100%; border-collapse: collapse;
  font-size: 0.85rem;
}
.devices-table th, .devices-table td {
  padding: 0.4rem 0.5rem;
  border-bottom: var(--lw) solid var(--border);
  text-align: left; vertical-align: top;
}
.devices-table thead th {
  color: var(--fg-dim); font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase; letter-spacing: 0.04em;
  border-bottom: var(--lw) solid var(--border);
}
.devices-table tr.is-self td { background: var(--accent-dim); }
.devices-table tr.is-revoked td { color: var(--fg-dim); }
.devices-table .devices-name { min-width: 12rem; }
.devices-table .devices-name-text { font-weight: 600; }
.devices-selfflag {
  margin-left: 0.4rem;
  color: var(--accent); font-size: 0.7rem;
  border: 1px solid var(--accent); border-radius: 3px;
  padding: 0 0.35rem;
}
.devices-table .devices-ts {
  color: var(--fg-dim); font-family: ui-monospace, monospace;
  font-size: 0.78rem; white-space: nowrap;
}
.devices-table .devices-token { white-space: nowrap; }
.devices-table .devices-token.alive { color: #2f8a3d; font-weight: 600; }
.devices-table .devices-token.dead  { color: var(--fg-dim); }
.devices-table .devices-token-count { color: var(--fg-dim); font-weight: 400; font-size: 0.75rem; }

.devices-table .devices-actions {
  white-space: nowrap; text-align: right;
  display: flex; gap: 0.35rem; justify-content: flex-end;
}
.devices-btn {
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border); border-radius: 4px;
  padding: 0.15rem 0.5rem; cursor: pointer;
  font: inherit; font-size: 0.75rem;
}
.devices-btn:hover:not(:disabled) {
  background: var(--accent-dim); color: var(--accent); border-color: var(--accent);
}
.devices-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.devices-btn-danger:hover:not(:disabled) {
  background: #a4161a; color: #fff; border-color: #a4161a;
}
.devices-empty {
  color: var(--fg-dim); font-style: italic;
  text-align: center; padding: 1rem;
}

.devices-btn-primary {
  border-color: var(--accent);
  color: var(--accent);
}
.devices-btn-primary:hover:not(:disabled) {
  background: var(--accent); color: #fff; border-color: var(--accent);
}
.devices-toolbar {
  display: flex; justify-content: flex-end; align-items: center;
  gap: 1rem;
  margin-bottom: 0.5rem;
}
.devices-lesemodus {
  display: flex; align-items: center; gap: 0.4rem;
  margin-right: auto;
  color: var(--fg-dim); font-size: 0.85rem; cursor: pointer;
}

/* Wenn der Bildschirm eng wird, faellt die Tabelle auf ein Karten-Layout
   zurueck — sonst kollidieren Aktionen und Zeitstempel. */
@media (max-width: 800px) {
  .devices-table thead { display: none; }
  .devices-table, .devices-table tbody { display: block; }
  .devices-table tr { display: block; margin-bottom: 0.75rem;
    border: var(--lw) solid var(--border); border-radius: 4px; padding: 0.5rem; }
  .devices-table td { display: block; border-bottom: none; padding: 0.15rem 0; }
  .devices-table td::before {
    content: attr(data-label);
    color: var(--fg-dim); font-size: 0.7rem; margin-right: 0.35rem;
  }
  .devices-table .devices-actions { justify-content: flex-start; margin-top: 0.4rem; }
}

/* Werkzeug-Freigabe-Dialog (tsk-aa-werkzeuge). Layout uebernimmt die
   Grundzuege des Geraete-Dialogs; die zwei Modi (Katalog-Vorgabe / eigene
   Auswahl) schalten die Kaestchen an oder aus. Ist die Vorgabe aktiv, sind
   die Chat-eigenen Kaestchen ausgegraut — der Server richtet sich dann
   nach der Katalog-`default`-Marke pro Server (Spalte "Katalog"). */
.werkzeuge-mode {
  display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem;
  padding: 0.5rem 0.25rem 0.75rem;
  border-bottom: var(--lw) solid var(--border);
  margin-bottom: 0.5rem;
  font-size: 0.85rem;
}
.werkzeuge-mode label {
  display: inline-flex; align-items: center; gap: 0.4rem;
  cursor: pointer;
}
.werkzeuge-mode-hint {
  color: var(--fg-dim); font-size: 0.75rem;
  font-family: ui-monospace, monospace;
}
.werkzeuge-table td.werkzeuge-toggle,
.werkzeuge-table th.werkzeuge-toggle {
  width: 8rem; text-align: center;
}
.werkzeuge-table td.werkzeuge-default,
.werkzeuge-table th.werkzeuge-default {
  width: 5rem; text-align: center;
  color: var(--fg-dim); font-size: 0.75rem;
}
.werkzeuge-table td.werkzeuge-name { font-weight: 600; }
.werkzeuge-table tr.werkzeuge-row.disabled td { color: var(--fg-dim); }
.werkzeuge-table tr.werkzeuge-row.disabled input[type="checkbox"] { opacity: 0.5; }
.werkzeuge-vorschau {
  margin-top: 0.75rem;
  padding: 0.5rem 0.6rem;
  background: var(--accent-dim);
  border: var(--lw) solid var(--border); border-radius: 4px;
  font-family: ui-monospace, monospace;
  font-size: 0.78rem;
  color: var(--fg-dim);
  white-space: pre-wrap; word-break: break-word;
}
.werkzeuge-vorschau .werkzeuge-vorschau-title {
  display: block; margin-bottom: 0.25rem;
  color: var(--fg); font-family: inherit; font-size: 0.8rem;
  font-weight: 600;
}
.werkzeuge-actions {
  display: flex; gap: 0.5rem; justify-content: flex-end;
  margin-top: 0.75rem;
}
.werkzeuge-body { min-height: 12rem; }

/* Grundierung je Chat (tsk-aa-grundierung).
   Ein Textfeld, kein Formular — die Grundierung ist Prosa, und sie geht
   so ab, wie sie hier steht. Deshalb Monospace und weicher Umbruch: was
   man sieht, ist die Zeilenform, die die Sitzung bekommt. Im Vorgabe-Modus
   ist das Feld `readOnly` und wird ausgegraut, damit niemand darin tippt
   und glaubt, es sei gespeichert. */
.grundierung-body { min-height: 12rem; }
.grundierung-text {
  width: 100%;
  min-height: 18rem;
  box-sizing: border-box;
  resize: vertical;
  padding: 0.5rem 0.6rem;
  background: var(--bg); color: var(--fg);
  border: var(--lw) solid var(--border); border-radius: 4px;
  font-family: ui-monospace, monospace;
  font-size: 0.78rem;
  line-height: 1.45;
  white-space: pre-wrap; word-break: break-word;
}
.grundierung-text[readonly] {
  background: var(--accent-dim);
  color: var(--fg-dim);
}
.grundierung-fuss {
  margin-top: 0.5rem;
  font-size: 0.75rem;
  color: var(--fg-dim);
}
/* --- Koppel-QR (tsk-aorta-koppel-ui) ------------------------------------
   Eigener Dialog ueber der Geraete-Liste. Formular oben (Adresse, Laufzeit,
   Bezeichnung), Ergebnis darunter (Status, QR, Countdown, Klartext-Adresse).
   Der QR wird im Browser gezeichnet (qrcode-generator.js); die Grafik ist
   quadratisch und bekommt einen weissen Rahmen, damit ein Handy sie auch
   im dunklen Theme sauber liest. */
.pair-dialog {
  max-width: 42rem;
}
.pair-body {
  padding: 0.75rem 0.5rem;
  display: flex; flex-direction: column; gap: 1rem;
}
.pair-form {
  display: grid; gap: 0.5rem;
  grid-template-columns: 1fr;
}
.pair-field {
  display: flex; flex-direction: column; gap: 0.15rem;
}
.pair-field-label {
  font-size: 0.75rem; color: var(--fg-dim);
}
.pair-field input {
  background: var(--pane-bg, transparent); color: var(--fg);
  border: var(--lw) solid var(--border); border-radius: 4px;
  padding: 0.3rem 0.5rem; font: inherit;
}
.pair-field input:focus { outline: 2px solid var(--accent); outline-offset: -2px; }
.pair-form > .devices-btn { justify-self: end; margin-top: 0.25rem; }
@media (min-width: 480px) {
  .pair-form {
    grid-template-columns: 1fr 8rem;
    align-items: end;
  }
  .pair-form > .pair-field:first-child,
  .pair-form > .devices-btn { grid-column: 1 / -1; }
}
.pair-result {
  display: flex; flex-direction: column; gap: 0.5rem;
  border-top: var(--lw) solid var(--border); padding-top: 0.75rem;
}
.pair-status { font-weight: 600; }
.pair-status.ok       { color: #2f8a3d; }
.pair-status.warn     { color: #b3651c; }
.pair-status.expired  { color: var(--accent); }
.pair-status.err      { color: var(--accent); }
.pair-qr-wrap {
  display: flex; justify-content: center;
}
.pair-qr {
  background: #fff; padding: 0.75rem; border-radius: 6px;
  line-height: 0; display: inline-block;
  max-width: 100%;
}
.pair-qr svg { width: min(20rem, 80vw); height: auto; display: block; }
.pair-result.is-expired  .pair-qr,
.pair-result.is-redeemed .pair-qr { opacity: 0.35; filter: grayscale(1); }
.pair-meta {
  display: flex; flex-direction: column; gap: 0.4rem;
  font-size: 0.9rem;
}
.pair-countdown { font-weight: 600; font-variant-numeric: tabular-nums; }
.pair-address {
  display: flex; gap: 0.35rem; flex-wrap: wrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85rem;
}
.pair-address-label { color: var(--fg-dim); }
.pair-address-value { word-break: break-all; }
.pair-note { color: var(--fg-dim); font-size: 0.8rem; }

/* --- tsk-acu-webui: neuer Chat aus Kontext --- */

/* Fusszeile des Kontext-Panels. Die Liste darueber rollt (flex 1 1 auto),
   die Fusszeile bleibt unten stehen — die zwei Knoepfe sind immer da. Der
   Auswahl-Knopf ist ausgegraut, solange nichts angehakt ist. */
.ctx-fuss {
  flex: 0 0 auto;
  display: flex; flex-wrap: wrap; gap: 0.4rem;
  padding: 0.5rem 0.75rem;
  border-top: var(--lw) solid var(--border);
  background: var(--bg);
}
.ctx-fuss button { font-size: 0.85rem; }
.ctx-fuss button:disabled { opacity: 0.45; cursor: not-allowed; }

/* Das Fenster ist klein: ein Feld, eine Wahl, ein Haken. */
.overlay .dialog.neuer-chat-dialog { width: min(34rem, 96vw); margin-top: 12vh; }
.neuer-chat-body { display: flex; flex-direction: column; gap: 0.75rem; }
.neuer-chat-name {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  gap: 0.75rem; font-size: 0.9rem;
}
.neuer-chat-name input {
  width: 100%; padding: 0.35rem 0.5rem;
  background: var(--bg); color: var(--fg);
  border: var(--lw) solid var(--border); border-radius: 4px;
  font: inherit;
}
.neuer-chat-name input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.neuer-chat-art { margin-bottom: 0; }
.neuer-chat-loeschen {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.85rem; cursor: pointer;
}
/* Der Loesch-Satz ist eine Warnung, kein Kleingedrucktes. */
.neuer-chat-warnung {
  margin: 0; padding: 0.45rem 0.6rem;
  border-left: 3px solid var(--warning); border-radius: 4px;
  background: color-mix(in srgb, var(--warning) 12%, transparent);
  color: var(--fg); font-size: 0.85rem; line-height: 1.4;
}
.neuer-chat-body .devices-status { margin-bottom: 0; }
.neuer-chat-body .werkzeuge-actions { margin-top: 0; }
.neuer-chat-body .devices-btn { font-size: 0.85rem; padding: 0.3rem 0.8rem; }

/* Der neue Chat, solange die Zusammenfassung entsteht. */
.empty.uebernahme-laeuft { font-style: normal; color: var(--fg); }

/* "Nochmal versuchen" an der Hinweis-Zeile einer gescheiterten
   Zusammenfassung — sichtbar wie ein Knopf, nicht wie ein Link. */
.msg .msg-nochmal {
  margin-top: 0.45rem;
  background: var(--accent); color: #fff;
  border: none; border-radius: 4px;
  padding: 0.3rem 0.8rem;
  cursor: pointer; font: inherit; font-size: 0.85rem;
}
.msg .msg-nochmal:disabled { opacity: 0.5; cursor: wait; }

/* --- Tools in der Mitte (tsk-tools-webui) --- */

/* Zwei Knoepfe in der Kopfleiste: nur der erste schiebt nach rechts. */
.topbar-action + .topbar-tools { margin-left: 0; }
.topbar-tools[aria-pressed="true"] {
  background: var(--accent-dim); color: var(--accent); border-color: var(--accent);
}

.pane-tools { min-width: 0; }
/* Die Leiste bricht in sich um, wenn es doch einmal zu viele werden;
   "Einstellen" bleibt oben rechts daneben. */
.tools-kopf { align-items: flex-start; padding-top: 0.35rem; padding-bottom: 0.35rem; }
.tools-leiste {
  display: flex; flex-wrap: wrap; gap: 0.35rem;
  flex: 1 1 auto; min-width: 0;
}
/* Reiter und sein × sind EIN Knopf-Paar ohne Luft dazwischen: so passen
   alle Werkzeuge in eine Zeile statt in zwei. Die Hoehe der Leiste ist
   Platz, der den Werkzeugen fehlt (Chunta, 20.09.: "all die header viel zu
   gross"). */
.tools-reiter-halter {
  display: inline-flex; align-items: center; gap: 0;
}
.pane-head .tools-leiste .tools-reiter-halter > .tools-reiter {
  border-top-right-radius: 0; border-bottom-right-radius: 0;
}
.pane-head .tools-leiste .tools-reiter-halter > .tools-zu {
  border-top-left-radius: 0; border-bottom-left-radius: 0;
  border-left-width: 0; margin-left: 0;
}
/* .pane-head button schiebt mit margin-left:auto nach rechts — in der
   Leiste soll alles aneinander stehen. */
.pane-head .tools-leiste button { margin-left: 0; }
.pane-head .tools-leiste .tools-reiter {
  font-weight: 500; font-size: 0.8rem; padding: 0.1rem 0.4rem;
}
.pane-head .tools-leiste .tools-reiter.tools-offen { color: var(--fg); }
.pane-head .tools-leiste .tools-reiter.tools-aktiv {
  background: var(--accent-dim); color: var(--accent); border-color: var(--accent);
}
.pane-head .tools-leiste .tools-reiter.tools-grau,
.pane-head .tools-leiste .tools-reiter.tools-grau:hover {
  opacity: 0.45; cursor: default;
  background: transparent; color: var(--fg-dim); border-color: var(--border);
}
.pane-head .tools-leiste .tools-reiter.tools-versteckt { border-style: dashed; }
/* Angehalten (tsk-afs-reiter): der Reiter steht weiter da, seine Seite ist
   entladen. Der Hinweis dazu haengt als `title` am Reiter — eine eigene
   Zeile unter der Leiste naehme den Werkzeugen Platz weg. */
.pane-head .tools-leiste .tools-reiter.tools-schlaeft { opacity: 0.6; }
.pane-head .tools-leiste .tools-zu,
.pane-head .tools-leiste .tools-hoch,
.pane-head .tools-leiste .tools-runter,
.pane-head .tools-leiste .tools-stern {
  padding: 0.1rem 0.3rem; font-size: 0.8rem;
}
.pane-head .tools-leiste button:disabled,
.pane-head .tools-leiste button:disabled:hover {
  opacity: 0.4; cursor: default;
  background: transparent; color: var(--fg-dim); border-color: var(--border);
}
.tools-sicht { font: inherit; font-size: 0.8rem; font-weight: 400; }
.tools-einstellen, .tools-neuladen { flex: 0 0 auto; }
/* Nur das Icon; neben "Einstellen" statt ganz rechts. */
.pane-head .tools-neuladen { padding: 0.15rem 0.45rem; }
.pane-head .tools-neuladen + .tools-einstellen { margin-left: 0.35rem; }
.pane-head .tools-neuladen:disabled,
.pane-head .tools-neuladen:disabled:hover {
  opacity: 0.4; cursor: default;
  background: transparent; color: var(--fg-dim); border-color: var(--border);
}
.tools-fehler { color: var(--accent); font-weight: 400; font-size: 0.8rem; }

.tools-flaeche { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.tools-panel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* Der Verweis auf den eigenen Tab sitzt in der Leiste, nicht mehr in einer
   eigenen Zeile ueber jedem Rahmen. */
.tools-eigener-tab {
  flex: 0 0 auto; margin-left: 0;
  color: var(--fg-dim); text-decoration: none;
  border: var(--lw) solid var(--border); border-radius: 4px;
  padding: 0.1rem 0.4rem; font-size: 0.9rem; line-height: 1.3;
}
.tools-eigener-tab:hover { color: var(--accent); border-color: var(--accent); }
.tools-eigener-tab[hidden] { display: none; }
.tools-koerper { flex: 1 1 auto; min-height: 0; display: flex; }
.tools-rahmen { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
.tools-weg, .tools-pruefe {
  flex: 1 1 auto;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.6rem; color: var(--fg-dim);
}
.tools-weg p { margin: 0; font-size: 1rem; }
.tools-nochmal {
  background: transparent; color: var(--fg-dim);
  border: var(--lw) solid var(--border); border-radius: 4px;
  padding: 0.25rem 0.8rem; cursor: pointer; font: inherit;
}
.tools-nochmal:hover { background: var(--accent-dim); color: var(--accent); border-color: var(--accent); }


/* tsk-kos-sprache ── die Legende und das Blatt ────────────────────── */

/* Die drei Stufenfarben. Sie sitzen NUR an der Kostenzahl und ihrem Balken;
   die vier Punktfarben der Liste (orange > rot > blau > grau) und ihre
   Rangfolge bleiben unberuehrt.

   ZWEI Saetze, einer je Thema — und das ist keine Bequemlichkeit, sondern
   Rechnung: gegen den hellen Grund (#fafaf9) und den dunklen (#17181a) gibt
   es KEINE einzelne Farbe, die beide Male die 4,5:1 aus WCAG 2.2 AA schafft.
   Ein Satz fuer beide muss also scheitern. Die Farbe traegt hier Text
   (0,72rem in der Liste, 1,05rem im Blatt — beides unter 18,66px, also
   Normaltext), deshalb gilt 4,5:1 und nicht 3:1.

   Die Werte sind nachgerechnet und werden bei jedem Lauf nachgerechnet:
   `agent-aorta/tests/kos_sprache_kontrast.test.mjs` liest genau diese Datei
   und rechnet die Verhaeltnisse nach der WCAG-2.2-Formel selbst nach. Wer
   hier eine Farbe anfasst, sieht es sofort am Lauf.

   GEGEN WELCHEN GRUND (Entscheidung 21.09., 16:15)
   ------------------------------------------------
   Die ersten drei Runden am Kontrast haben immer nur gegen `--bg` gemessen
   und darum jedes Mal eine neue Stelle uebersehen. Eine Stufenfarbe steht
   aber auf ZWEI Untergruenden: auf `--bg` (ruhige Zeile, Blatt, Legende)
   und auf `--accent-dim` — das ist die hervorgehobene Zeile, `.chats
   li:hover` und `.chats li.active`. Beide muessen 4,5:1 schaffen, in beiden
   Themen. Der Lauf prueft deshalb die ganze Tafel {Farbe} x {Untergrund} x
   {Thema} und liest die Kombinationen aus dieser Datei, statt sie von Hand
   zu pflegen.

                            auf --bg   auf --accent-dim
     hell    rot   #b3272f    6,19            5,34
             gelb  #8a5a00    5,67            4,90
             gruen #1b773e    5,35            4,62
     dunkel  rot   #f85e69    5,75            4,59
             gelb  #d9a441    7,90            6,31
             gruen #4fa86a    6,04            4,82

   Zwei Werte sind aus genau diesem Grund nachgezogen worden, und nur die
   zwei: `--kos-gruen` hell war #1c7a40 und kam auf der hervorgehobenen
   Zeile auf 4,44; `--kos-rot` dunkel war #e0555f und kam dort auf 3,81.
   Auf `--bg` waren beide in Ordnung — deshalb hat es keiner gesehen.

   Der Fehler davor fiel nicht auf, weil beim Entwickeln das dunkle Thema
   aktiv war: die alten Werte sind die dunklen, und im hellen Thema kam Gelb
   auf 2,15:1. */
:root {
  --kos-rot:   #b3272f;
  --kos-gelb:  #8a5a00;
  --kos-gruen: #1b773e;
  /* Der Untergrund von Balken und Legenden-Pille. Frueher lief er auf
     `--border`; der ist fuer die Brillen-Ansicht im dunklen Thema auf
     #4c5057 aufgehellt worden, und damit fiel der dunkle Balken auf 2,17:1
     gegen seine eigene Spur — als Flaeche gilt 3:1 (WCAG 1.4.11). Eine
     eigene Spur haelt beides auseinander: die Linien duerfen hell werden,
     ohne dass der Balken verschwindet. */
  --kos-spur: #d8d8d5;
}

/* Der dunkle Satz steht bewusst HIER und nicht oben im grossen
   `prefers-color-scheme`-Block: beide Regeln haben dieselbe Spezifitaet,
   also gewinnt die spaetere. Stuenden die dunklen Werte oben, wuerde der
   helle `:root` von hier sie wieder ueberschreiben — und zwar in beiden
   Themen. */
@media (prefers-color-scheme: dark) {
  :root {
    --kos-rot:   #f85e69;
    --kos-gelb:  #d9a441;
    --kos-gruen: #4fa86a;
    /* Der alte `--border`-Wert des dunklen Themas. Als Spur ist er richtig:
       rot 3,92 — gelb 5,38 — gruen 4,12, alle drei ueber den 3:1 fuer
       Flaechen. */
    --kos-spur: #34363a;
  }
}

/* Die Legende steht zugeklappt unter der Liste: gelesen wird sie einmal,
   danach ist sie Rauschen. Aufgeklappt bleibt sie aufgeklappt (details). */
.kosten-legende {
  flex: 0 0 auto;
  padding: 0.35rem 0.75rem;
  border-top: var(--lw) solid var(--border);
  font-size: 0.72rem; color: var(--fg-dim);
}
/* Der Aufklapper ist ein Bedienelement, und bei 0.72rem Schrift waere seine
   Trefferflaeche knapp 15 px hoch — unter den 24 px, die WCAG 2.2 als
   Mindestgroesse fuer ein Ziel verlangt. Die 24 px kommen deshalb aus einer
   `min-height`, nicht aus groesserer Schrift: die Legende soll so leise
   bleiben wie im Entwurf. Kein `display: flex` hier — das nimmt dem `summary`
   seine Rolle als `list-item` und damit das Dreieck, das der Browser selbst
   zeichnet; anders als das Blatt zeichnet die Legende keines nach. */
.kosten-legende > summary { cursor: pointer; min-height: 1.5rem; padding: 0.25rem 0; }
.kosten-legende .leg { display: flex; gap: 0.45rem; align-items: flex-start; padding: 0.25rem 0; }
.kosten-legende .leg b { color: var(--fg); font-weight: 600; }
.kosten-legende .pill {
  width: 1.1rem; height: 0.3rem; border-radius: 0.15rem; flex: 0 0 auto; margin-top: 0.35rem;
}
.kosten-legende .pill-rot   { background: var(--kos-rot); }
.kosten-legende .pill-gelb  { background: var(--kos-gelb); }
.kosten-legende .pill-gruen { background: var(--kos-gruen); }
.kosten-legende .leg-klein { margin: 0.3rem 0 0; }

/* Das Blatt zum offenen Chat. Es sitzt unter der Leiste, nicht in einem
   Fenster: es ist eine Auskunft, kein Vorgang — es soll nichts wegnehmen,
   was Chunta gerade liest. */
.kosten-blatt {
  flex: 0 0 auto;
  padding: 0.6rem 0.75rem 0.7rem;
  border-bottom: var(--lw) solid var(--border);
  font-size: 0.8rem;
}
/* Der Kopf ist der Aufklapper (`summary`). Zugeklappt ist die Kennzahl das
   Einzige, was vom Blatt stehen bleibt — bei gruen ist das der Normalfall
   (Nachtrag Chunta, 21.09.). `display: flex` muss sein: ein `summary` ist
   `display: list-item`, und damit saesse das Dreieck des Browsers in einer
   eigenen Zeile ueber der Zahl. Das Dreieck zeichnen wir selbst, damit es in
   beiden Themen dieselbe Farbe hat wie der uebrige gedaempfte Text. */
.kosten-blatt-kopf {
  display: flex; align-items: baseline; gap: 0.5rem;
  cursor: pointer; list-style: none;
  /* Dieselben 24 px Mindesthoehe wie bei der Legende (WCAG 2.2). Die
     Ausrichtung bleibt `baseline`, damit Zahl und Dreieck auf einer Linie
     sitzen — die Hoehe kommt aus der `min-height`, nicht aus der Ausrichtung. */
  min-height: 1.5rem;
}
.kosten-blatt-kopf::-webkit-details-marker { display: none; }
/* Das Dreieck steht HINTER der Zahl: die Kennzahl ist die Auskunft, der
   Aufklapper nur das Angebot, mehr zu sehen. */
.kosten-blatt-kopf::after {
  content: "▸"; margin-left: auto; color: var(--fg-dim); font-size: 0.85rem;
}
.kosten-blatt[open] > .kosten-blatt-kopf::after { content: "▾"; }
/* Die Zahl im Kopf lebt von derselben `--kos-jetzt` wie die starke Stelle im
   Satz — eine Quelle, damit Kopf und Satz nicht auseinanderlaufen koennen. */
.kosten-blatt-mal {
  font-size: 1.05rem; font-variant-numeric: tabular-nums;
  color: var(--kos-jetzt, var(--fg));
}
.kosten-blatt-satz { margin: 0.35rem 0 0.5rem; line-height: 1.5; }
/* Die Auszeichnung im Satz folgt der ROLLE, die `kostenwort.js` mitgibt —
   frueher stand hier pauschal `var(--kos-rot)`, und damit las Chunta im
   warmen Fall "Noch 54 Minuten" in Rot, waehrend die Zeile darueber gruen
   war. Genau der Widerspruch, den der Nachtrag verbietet.

     .jetzt  die Aussage ueber JETZT — sie traegt die Farbe des Blattes
             (warm gruen, kalt die Stufe), gesetzt ueber `--kos-jetzt`.
     .dann   der Ausblick auf NACHHER — gedaempft, nie eine Stufenfarbe. */
.kosten-blatt-satz em { font-style: normal; font-weight: 600; }
.kosten-blatt-satz em.jetzt { color: var(--kos-jetzt, var(--fg)); }
.kosten-blatt-satz em.dann  { color: var(--fg-dim); font-weight: 500; }

/* Das Blatt setzt `--kos-jetzt` auf die Farbe, die JETZT gilt. Eine Stelle,
   von der sowohl die Zahl im Kopf als auch die starke Stelle im Satz lebt —
   zwei getrennte Regeln koennten auseinanderlaufen. */
.kosten-blatt-jetzt-rot   { --kos-jetzt: var(--kos-rot); }
.kosten-blatt-jetzt-gelb  { --kos-jetzt: var(--kos-gelb); }
.kosten-blatt-jetzt-gruen { --kos-jetzt: var(--kos-gruen); }
.kosten-blatt-zeile {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: 0.28rem 0; color: var(--fg-dim);
  border-bottom: var(--lw) dotted var(--border);
}
.kosten-blatt-zeile b { color: var(--fg); font-weight: 500; font-variant-numeric: tabular-nums; }
/* Die Uhr ist die einzige gruene Zeile im Blatt — sie sagt, was JETZT gilt. */
.kosten-blatt-zeile.warm b { color: var(--kos-gruen); }
.kosten-blatt-zeile:last-of-type { border-bottom: 0; }
/* tsk-uz-kosten: die Umzugsrechnung steht in derselben Liste wie die Runden,
   ist aber etwas anderes — einmal bezahlt statt je Runde. Sie bekommt
   deshalb eine gedaempfte Zeile mit einem Strich darueber: sichtbar
   abgesetzt, ohne eine zweite Tafel aufzumachen. */
.kosten-blatt-zeile.umzug { border-top: 1px solid var(--rand, currentColor); opacity: .85; }
.kosten-blatt-zeile.umzug + .kosten-blatt-zeile.umzug { border-top: 0; }
.kosten-blatt-knopf { margin-top: 0.6rem; }
.kosten-blatt-klein { margin: 0.55rem 0 0; font-size: 0.72rem; color: var(--fg-dim); line-height: 1.5; }
