/* Der Coder in der Konsole — die Formen zu coder.js.
 *
 * Dieselbe Regel wie in FARBEN.md: KEIN Farbwert steht hier. Alles
 * kommt aus tokens.css, sonst fehlt die Farbe im dunklen Modus.
 * Nachprüfbar:
 *
 *   grep -nE '#[0-9a-fA-F]{3,8}\b|rgba?\(' web/coder.css
 *
 * Das muss leer bleiben.
 *
 * Ebenso wenig steht hier eine eigene Bauform, wo es schon eine gibt.
 * Die Projektliste benutzt .konv-item aus style.css, die Datei-Zeilen
 * .datei-karte, die Kopfzeile der Tafel .tafel-kopf. Sonst stünden
 * Chat und Coder verschieden untereinander — und genau das war beim
 * Chat schon einmal der Anlass (D-482).
 *
 * Diese Datei wird NACH style.css und leiste.css geladen. Die
 * Regeln unten, die deren Regeln überstimmen sollen (der Platz für
 * die Tafel), haben dieselbe Stärke und gewinnen durch die
 * Reihenfolge — nicht durch !important.
 */

/* ── Der Umschalter ─────────────────────────────────────────────
 * Zwei Zeichen oben links, direkt unter der Marke: Sprechblase für
 * den Chat, spitze Klammern für den Coder. Eine eigene Zeile statt
 * eines Platzes in .leiste-kopf — dort sitzen Logo, Marke und der
 * Einklapp-Knopf bereits in einer abgestimmten Reihe, und ein
 * dritter Mitbewohner würde sie umbauen. */
.coder-umschalter {
  display: flex;
  gap: 2px;
  margin: 0 14px 6px;
  padding: 2px;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  flex-shrink: 0;
  width: fit-content;
}
.coder-umschalter button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 26px;
  border: none;
  background: none;
  border-radius: 6px;
  color: var(--text-muted);
  cursor: pointer;
  transition: var(--transition);
}
.coder-umschalter button:hover { color: var(--text); }
.coder-umschalter button[aria-current="true"] {
  background: var(--surface);
  color: var(--teal-darker);
  box-shadow: var(--shadow-sm);
}
.coder-umschalter button:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 1px;
}

/* ── Links: Chat-Inhalt raus, Coder-Inhalt rein ─────────────────
 * Getauscht wird der INHALT der Leiste, nicht die Leiste. Die
 * Chat-Liste bleibt im Baum stehen (nur unsichtbar) — chat.js
 * schreibt weiter hinein, und leiste.js liest die Markierung dort
 * ab, um zu wissen, welches Gespräch offen ist. Würde sie entfernt,
 * verlöre die Datei-Tafel des Chats ihren Bezug. */
#coder-leiste { display: none; }
body.coder-an .leiste-mitte > :not(#coder-leiste) { display: none; }
body.coder-an #coder-leiste {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.coder-projektliste {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0 8px 12px;
  min-height: 0;
}

/* ── Rechts: die Tafel ──────────────────────────────────────────
 * Gleiche Bauform wie die Datei-Tafel: legt sich über die rechte
 * Seite, ohne den Chat zu verschieben; der Chat rückt nur seinen
 * Innenrand nach. */
#coder-tafel {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: var(--coder-tafel-breite);
  max-width: 92vw;
  z-index: 20;
  display: none;
  flex-direction: column;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-md);
}
body { --coder-tafel-breite: 460px; }
body.coder-an #coder-tafel { display: flex; }

/* Die Datei-Tafel des Chats gehört zum Chat. Stünde sie offen, während
 * der Coder an ist, lägen zwei Tafeln übereinander. */
body.coder-an #datei-tafel { display: none; }

@media (min-width: 900px) {
  body.coder-an #messages,
  body.coder-an #input-area {
    padding-right: calc(var(--coder-tafel-breite) + 16px);
  }
}

/* ── Die vier Reiter ────────────────────────────────────────────
 * Dateien · Journal · Läufe · Änderungen. Sie sitzen in der
 * Kopfzeile der Tafel, auf der Höhe des Chat-Kopfes daneben — die
 * Höhe misst coder.js und trägt sie als --kopf-hoehe ein. */
.coder-tafel-kopf { padding: 0 10px; overflow-x: auto; }
.coder-reiter { display: flex; gap: 2px; }
.coder-reiter-knopf {
  border: none;
  background: none;
  padding: 6px 9px;
  border-radius: 6px;
  font: inherit;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  white-space: nowrap;
  cursor: pointer;
  transition: var(--transition);
}
.coder-reiter-knopf:hover { background: var(--bg-hover); color: var(--text); }
.coder-reiter-knopf[aria-selected="true"] {
  background: var(--teal-dim);
  color: var(--teal-darker);
}
.coder-reiter-knopf:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: -2px;
}

.coder-flaeche {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
  min-height: 0;
}

/* ── Meldungen und leere Flächen ────────────────────────────────
 * Ein leerer Bereich sagt, dass er leer ist, und ein unerreichbarer
 * Dienst sagt, dass er nicht antwortet. Beides sieht sonst gleich
 * aus — und wer „nichts da" liest, wo „ich komme nicht dran" gilt,
 * sucht den Fehler an der falschen Stelle. */
.coder-leer {
  padding: 14px 10px;
  font-size: 0.8rem;
  color: var(--text-muted);
  line-height: 1.5;
}
.coder-meldung {
  padding: 10px 12px;
  margin: 4px 2px;
  border-radius: var(--radius-sm);
  font-size: 0.8rem;
  line-height: 1.5;
  background: var(--bg-tertiary);
  color: var(--text-secondary);
}
.coder-meldung.warnung {
  background: var(--warnung-flaeche);
  color: var(--warnung);
}
/* Eine Stelle, an der Oberfläche und Dienst noch nicht verdrahtet
 * sind — oder an der ein Anschluss am Ergebnis des Motors
 * nachgearbeitet hat (D-601). Beides ist keine Warnung, sondern eine
 * offene Notiz, und darf deshalb nicht aussehen wie ein Fehler. */
.coder-meldung.offen {
  background: var(--teal-dim);
  color: var(--teal-darker);
}

.coder-raum {
  padding: 6px 10px 10px;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

/* ── Volltext: Journal, Ausgabe, Diff ───────────────────────────
 * Kein Deckel. Eine Prüffläche, die weniger zeigt als das Modell
 * gesehen hat, erzeugt falsche Befunde statt bloß fehlender Zeichen
 * (D-566). Die Marke darüber nennt die WAHRE Länge. */
.coder-volltext { margin: 6px 2px 10px; }
.coder-laenge {
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.coder-vorformatiert {
  margin: 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  color: var(--text-secondary);
  font-family: var(--mono);
  font-size: 0.75rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  /* Sichtbare Höhe, nicht Inhalts-Grenze: der Text ist vollständig
   * da, man scrollt nur. Kürzen würde ihn wegnehmen. */
  max-height: 60vh;
  overflow-y: auto;
}

/* ── Läufe ──────────────────────────────────────────────────────
 * Zwei Ebenen, weil der Dienst zwei kennt (schemas.py): ein LAUF ist
 * ein Auftrag, ein ZUG ein einzelner Werkzeug-Aufruf darin. Der Block
 * fasst zusammen, die Zeilen darin sind die Züge — kein Kasten je
 * Zug, nur eine Zeile, die sich beim Überfahren zeigt. */
.lauf-block { padding: 10px 0 6px; }
/* Die Trennlinie sitzt ZWISCHEN zwei Blöcken, nicht über jedem. Über
 * dem obersten stünde sonst eine Linie ins Nichts — und :first-child
 * hilft nicht, weil über den Blöcken noch die Befehlszeile und die
 * Zustands-Zeile stehen. */
.lauf-block + .lauf-block { border-top: 1px solid var(--border); }
.lauf-auftrag {
  flex: 1;
  min-width: 0;
  font-size: 0.82rem;
  color: var(--text);
  overflow-wrap: anywhere;
}
.lauf-zeile {
  padding: 8px 10px 10px;
  border-radius: var(--radius-sm);
  transition: var(--transition);
}
.lauf-zeile:hover { background: var(--bg-hover); }
.lauf-kopf {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.lauf-befehl {
  flex: 1;
  min-width: 0;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text);
  overflow-wrap: anywhere;
}
.lauf-fuss {
  font-size: 0.7rem;
  color: var(--text-muted);
  margin-top: 3px;
}

/* Ging es gut oder nicht — die halbe Auskunft eines Laufs. */
.lauf-marke {
  flex-shrink: 0;
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--bg-tertiary);
  color: var(--text-muted);
}
.lauf-marke.gut { background: var(--teal-dim); color: var(--teal-darker); }
.lauf-marke.schlecht { background: var(--danger-dim); color: var(--danger); }
/* Die fünf Zustände des Läufer-Vertrags plus 'bereit' (angelegt, noch
 * kein Lauf) — genau die Liste aus schemas.py. Fehlt hier einer, steht
 * er grau da statt falsch eingefärbt; das ist der harmlose Ausgang. */
.lauf-marke.zustand-laeuft { background: var(--warnung-flaeche); color: var(--warnung); }
.lauf-marke.zustand-fertig { background: var(--teal-dim); color: var(--teal-darker); }
.lauf-marke.zustand-abgebrochen,
.lauf-marke.zustand-grenze_erreicht,
.lauf-marke.zustand-gestorben { background: var(--danger-dim); color: var(--danger); }

.coder-zustand {
  margin: 4px 2px 8px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  font-size: 0.72rem;
  background: var(--bg-tertiary);
  color: var(--text-secondary);
}
.coder-zustand.zustand-laeuft { background: var(--warnung-flaeche); color: var(--warnung); }
.coder-zustand.zustand-abgebrochen,
.coder-zustand.zustand-grenze_erreicht,
.coder-zustand.zustand-gestorben { background: var(--danger-flaeche); color: var(--danger); }

/* Der wichtigste Knopf der ganzen Oberfläche (Plan, Stufe 3): er
 * verwandelt eine Behauptung in einen Nachweis. Er steht deshalb an
 * JEDER Lauf-Zeile und nicht in einem Menü. */
.lauf-nochmal {
  flex-shrink: 0;
  border: 1px solid var(--border);
  background: none;
  border-radius: 6px;
  padding: 3px 8px;
  font: inherit;
  font-size: 0.7rem;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition);
}
.lauf-nochmal:hover {
  background: var(--teal-dim);
  border-color: var(--teal-ring);
  color: var(--teal-darker);
}
.lauf-nochmal:focus-visible { outline: 2px solid var(--teal); outline-offset: 1px; }

/* Die eigene Zeile: selbst einen Befehl eintippen. */
.coder-befehlszeile {
  display: flex;
  gap: 6px;
  margin: 2px 2px 10px;
}
.coder-befehlszeile input {
  flex: 1;
  min-width: 0;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.76rem;
}
.coder-befehlszeile input:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-ring-zart);
}
.coder-knopf {
  flex-shrink: 0;
  border: none;
  border-radius: var(--radius-sm);
  padding: 7px 12px;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  background: var(--teal);
  color: var(--auf-teal);
  cursor: pointer;
  transition: var(--transition);
}
.coder-knopf:hover { background: var(--teal-dark); }
.coder-knopf:focus-visible { outline: 2px solid var(--teal-darker); outline-offset: 1px; }

/* ── Änderungen ─────────────────────────────────────────────────
 * Ein Diff wird nicht eingefärbt wie ein Programm, sondern nur in
 * drei Sorten Zeilen geteilt: dazu, weg, Stelle. */
.coder-diff .diff-zeile { display: block; }
.coder-diff .dazu { background: var(--teal-dim); color: var(--teal-darker); }
.coder-diff .weg { background: var(--danger-dim); color: var(--danger); }
.coder-diff .stelle { color: var(--text-muted); }

/* ── Schmale Fenster ────────────────────────────────────────────
 * Unter 900 px legt sich die Tafel über den Chat, wie die
 * Datei-Tafel es tut. Für zwei Spalten ist dort kein Platz. */
@media (max-width: 899px) {
  body { --coder-tafel-breite: 100%; }
}

/* ── Die rechte Tafel laesst sich schieben (Rico, 30.08.) ────────────
 *
 * „beim Coder ist das wichtig" — und das stimmt: im Chat liest man
 * Text, im Coder liest man Programme und Unterschiede. Was im Chat
 * bequem ist, ist beim Coder zu schmal.
 *
 * Der Griff sitzt auf der Kante und ist 8 Pixel breit, aber sein
 * Fangbereich reicht weiter (::before). Ein Griff, den man dreimal
 * verfehlt, ist schlimmer als keiner.
 */

.coder-griff {
  position: absolute;
  top: 0; left: -4px; bottom: 0;
  width: 8px;
  cursor: col-resize;
  z-index: 21;
  touch-action: none;
}

/* Fangbereich groesser als das, was man sieht. */
.coder-griff::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: -4px; right: -4px;
}

/* Sichtbar erst, wenn man in die Naehe kommt — sonst ist es ein
 * Strich, der den ganzen Tag nach einer Trennlinie aussieht. */
.coder-griff::after {
  content: "";
  position: absolute;
  top: 50%; left: 2px;
  width: 4px; height: 36px;
  margin-top: -18px;
  border-radius: 2px;
  background: var(--border);
  opacity: 0;
  transition: opacity .15s;
}

.coder-griff:hover::after,
body.coder-schiebt .coder-griff::after { opacity: 1; background: var(--teal); }

/* Waehrend des Ziehens keine Auswahl und kein Zeiger-Wechsel. */
body.coder-schiebt { user-select: none; cursor: col-resize; }
body.coder-schiebt #coder-tafel { transition: none; }

/* Zugeschoben: die Tafel ist weg, ein schmaler Streifen holt sie
 * zurueck. Nicht ganz verschwinden lassen — eine Flaeche, die man
 * nicht wiederfindet, ist verloren. */
body.coder-tafel-zu #coder-tafel { width: 0; border-left: none; box-shadow: none; }
body.coder-tafel-zu #coder-tafel > *:not(.coder-griff) { display: none; }
body.coder-tafel-zu .coder-griff { left: -14px; width: 14px; background: var(--surface); border-left: 1px solid var(--border); }
body.coder-tafel-zu .coder-griff::after { opacity: 1; }

/* ── Eigene Dialoge (Rico, 30.08.) ───────────────────────────────────
 *
 * „die Frage entspricht nicht dem Farbcode" — sie kam vom Browser, und
 * der zeichnet weiss mit blauem Knopf, egal wie die Seite aussieht.
 *
 * Jede Farbe hier kommt aus tokens.css. Kein einziger eigener Wert:
 * sonst waere der Dialog beim naechsten Wechsel von hell nach dunkel
 * genau das wieder, was er jetzt nicht mehr ist.
 */

.coder-dialog-hintergrund {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--schleier);
  padding: 16px;
}

.coder-dialog {
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 20px;
  font-family: var(--font);
}

.coder-dialog-frage {
  font-size: 15px;
  line-height: 1.45;
  margin-bottom: 14px;
}

.coder-dialog-feld {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 11px;
  font: inherit;
  color: inherit;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 16px;
}

.coder-dialog-feld:focus {
  outline: none;
  border-color: var(--teal);
}

.coder-dialog-knoepfe {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.coder-dialog-knopf {
  padding: 8px 16px;
  font: inherit;
  color: inherit;
  cursor: pointer;
  background: var(--neutral-flaeche);
  border: 1px solid var(--neutral-rahmen);
  border-radius: var(--radius-sm);
}

.coder-dialog-knopf:hover { background: var(--bg-hover); }

/* Der bestaetigende Knopf traegt die Hausfarbe … */
.coder-dialog-ja {
  background: var(--teal);
  border-color: var(--teal);
  color: var(--auf-teal);
}

.coder-dialog-ja:hover { background: var(--teal-dark); border-color: var(--teal-dark); }

/* … ausser er loescht etwas. Ein Knopf, der bei jeder Frage gleich
 * aussieht, wird irgendwann blind gedrueckt. */
.coder-dialog-warnung {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--auf-teal);
}

.coder-dialog-warnung:hover { background: var(--danger-dim); border-color: var(--danger-dim); }

/* ── Der Ordnerbaum (Rico, 30.08.) ───────────────────────────────────
 *
 * „ich als User will den Ordnerbaum sehen … wie beim Explorer durch den
 * Ordnerbaum klicken."
 *
 * Vorher eine flache Liste mit Pfaden. Bei drei Dateien geht das, bei
 * achtzehn sieht man nicht mehr, was zusammengehoert — und genau das
 * ist die Frage, die man an eine Dateiliste hat.
 */

.coder-baum { display: flex; flex-direction: column; }

.baum-zeile {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  padding: 5px 10px;
  font: inherit;
  font-size: 13px;
  color: inherit;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.baum-zeile:hover { background: var(--bg-hover); }
.baum-zeile svg { flex: none; opacity: .65; }
.baum-ordner { font-weight: 500; }
.baum-ordner svg { opacity: .85; color: var(--teal); }

/* Der Pfeil dreht sich beim Aufklappen. Dateien bekommen denselben
 * Platz ohne Pfeil — sonst springt die Einrueckung. */
.baum-pfeil {
  flex: none;
  width: 14px; height: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform .12s;
}
.baum-pfeil.auf { transform: rotate(90deg); }
.baum-pfeil svg { opacity: .5; }

.baum-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.baum-rechts {
  flex: none;
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  color: var(--text-muted);
}

.baum-marke {
  padding: 1px 6px;
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
  border: 1px solid var(--neutral-rahmen);
  border-radius: var(--radius-sm);
}

/* Ein toter Verweis wird gemeldet, nicht verschwiegen — genau daran
 * ist in der Nachtmessung ein Lauf gestorben. */
.baum-tot { color: var(--danger); border-color: var(--danger-rahmen); }

/* ── Eine Datei ansehen ──────────────────────────────────────────── */

.datei-ansicht-kopf {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 8px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

.datei-zurueck {
  flex: none;
  padding: 4px 9px;
  font: inherit;
  font-size: 12px;
  color: inherit;
  cursor: pointer;
  background: var(--neutral-flaeche);
  border: 1px solid var(--neutral-rahmen);
  border-radius: var(--radius-sm);
}
.datei-zurueck:hover { background: var(--bg-hover); }

.datei-ansicht-pfad {
  flex: 1;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;      /* bei langen Pfaden zaehlt das ENDE */
  text-align: left;
}

.datei-ansicht-marke {
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 8px;
}

/* ── Die Mitte im Coder-Modus (Rico, 30.08.) ─────────────────────────
 *
 * „wenn ich von Chat zu Coding gehe, bleibt der alte Chat bestehen und
 * wird nicht leer."
 *
 * Es war mehr als ein Schönheitsfehler: das Eingabefeld darunter
 * gehörte weiter dem CHAT. Wer im Coder-Modus etwas tippte, schickte
 * es an den Chat-Agenten — an ein Modell, das von Projekt und Raum
 * nichts weiß.
 *
 * Deshalb wird der Chat samt Eingabefeld ausgeblendet, nicht bloß
 * überdeckt.
 */

#coder-mitte { display: none; }

/* Nur die alten Nachrichten weg. Der EINGABEBEREICH bleibt, wie er
 * ist — er sieht aus wie im Chat, weil er der aus dem Chat IST.
 * Rico, 30.08.: „du hast das Layout unten geaendert, das machst du
 * rueckgaengig." Ein zweites Feld mit eigenem Aussehen macht aus einer
 * Oberflaeche zwei. */
body.coder-an #messages { display: none !important; }

body.coder-an #coder-mitte {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding: 16px;
  gap: 12px;
}

@media (min-width: 900px) {
  body.coder-an #coder-mitte { padding-right: calc(var(--coder-tafel-breite) + 32px); }
}

/* Ohne Projekt: nur der Hinweis. Ein Eingabefeld, das ins Leere führt,
 * ist schlimmer als keins. */
.coder-mitte-leer {
  margin: auto;
  color: var(--text-muted);
  font-size: 14px;
}
.coder-mitte-arbeit { display: none; flex-direction: column; flex: 1; min-height: 0; gap: 12px; }

#coder-mitte.hat-projekt .coder-mitte-leer { display: none; }
#coder-mitte.hat-projekt .coder-mitte-arbeit { display: flex; }

.coder-lauf {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  font-size: 13px;
  color: var(--text-secondary);
}


/* ── Das Gespräch in der Mitte ───────────────────────────────────────
 *
 * Es benutzt SEINE Bauformen: `msg-row`, `msg-bubble`, `msg-avatar`,
 * `schritte`, `tritt`. Deshalb steht hier fast nichts — was nicht
 * dasteht, sieht automatisch aus wie der Chat.
 *
 * Nur der Rahmen darum und die zwei Dinge, die es im Chat nicht gibt:
 * die Ausgabe eines Zuges und die Schluss-Zeile mit dem Beleg.
 */

.coder-lauf-leer {
  margin: auto;
  padding: 40px 0;
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
}

.coder-wartet { color: var(--text-muted); font-style: italic; }

/* Die Ausgabe eines Zuges — ungekürzt, deshalb scrollbar statt
 * abgeschnitten. Eine Fläche, die weniger zeigt als da ist, erzeugt
 * falsche Befunde (D-566). */
.coder-zug-ausgabe {
  margin: 4px 0 8px 18px;
  padding: 8px 10px;
  max-height: 340px;
  overflow: auto;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  border-radius: var(--radius-sm);
}

/* Die Schluss-Zeile: welcher Motor, welches Modell, welcher Port.
 * Ohne sie sähe ein späterer Vergleich zwei Verläufe und wüsste nicht,
 * welcher wozu gehört (D-600). */
.coder-ende {
  margin-top: 10px;
  padding-top: 8px;
  font-size: 11px;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
}

/* ── Zuklappen wie links (Rico, 30.08.) ──────────────────────────────
 *
 * „Das rechte Sidebar sollte zuklappbar sein wie die linke bei schmalen
 * Bildschirmen."
 *
 * Dasselbe Muster wie in leiste.css: der Zuklapp-Knopf sitzt IM Kopf
 * der Tafel, der Aufklapp-Knopf in der Kopfzeile daneben, und immer nur
 * einer von beiden ist zu sehen. Zwei Knöpfe für dieselbe Sache an
 * zwei Stellen sind eine Sache mehr, die man suchen muss.
 */

#btn-tafel-zu { margin-left: auto; flex: none; }

/* Der Aufklapp-Knopf gehört zum Coder. Im Chat hat er nichts verloren,
 * und bei offener Tafel wäre er ein Knopf, der nichts tut. */
#btn-tafel-auf { display: none; }
body.coder-an.coder-tafel-zu #btn-tafel-auf { display: inline-flex; }

/* Am Schreibtisch schrumpft sie auf Null und gibt ihren Platz frei —
 * sonst bliebe eine leere Spalte stehen und das Einklappen hätte
 * keinen Zweck. Wörtlich dieselbe Überlegung wie bei der linken. */
@media (min-width: 901px) {
  #coder-tafel { transition: width 0.18s ease; }
  body.coder-an.coder-tafel-zu #coder-mitte { padding-right: 16px; }
  body.coder-an.coder-tafel-zu #messages,
  body.coder-an.coder-tafel-zu #input-area { padding-right: 0; }
}

/* Auf schmalen Fenstern liegt sie ÜBER dem Gespräch statt daneben —
 * nebeneinander wäre beides zu schmal. Zugeklappt ist sie ganz weg;
 * der Griff bleibt als schmaler Streifen, damit man sie wiederfindet. */
@media (max-width: 900px) {
  #coder-tafel { width: 100%; max-width: 100%; }
  body.coder-an.coder-tafel-zu #coder-tafel { width: 0; }
  body.coder-an #coder-mitte { padding-right: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  #coder-tafel { transition: none; }
}

/* ── Mit wem redest du? (Rico, 30.08.) ───────────────────────────────
 *
 * „Links unten ist Bild und Datei anhängen. Die zwei entnehmen. An der
 * Stelle soll die Auswahlmöglichkeit sein: Planer und Coder."
 *
 * Bild und Datei gehören zum Chat. Im Coder-Modus legt man Dateien über
 * den Eingang des Projekts hinein — bewusst und dauerhaft. Zwei Wege
 * für dasselbe wären zwei Wege zu viel.
 */

body.coder-an #btn-image,
body.coder-an #btn-file { display: none !important; }

.coder-wahl { display: none; }
body.coder-an .coder-wahl {
  display: inline-flex;
  flex: none;
  gap: 2px;
  padding: 2px;
  background: var(--neutral-flaeche);
  border: 1px solid var(--neutral-rahmen);
  border-radius: var(--radius);
}

.coder-wahl button {
  padding: 6px 12px;
  font: inherit;
  font-size: 13px;
  color: var(--text-secondary);
  cursor: pointer;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
.coder-wahl button:hover { color: var(--text); }

/* Der Gewählte trägt die Hausfarbe. Ohne sichtbaren Unterschied
 * schickt man einen Auftrag an den Planer und wundert sich. */
.coder-wahl button[aria-current="true"] {
  color: var(--auf-teal);
  background: var(--teal);
}

/* Wer redet, steht dran — sonst hält man einen Vorschlag des Planers
 * für etwas, das der Coder schon getan hat. */
.coder-wer {
  margin-bottom: 6px;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--teal);
}
.msg-bubble.von-planer { border-left: 2px solid var(--teal-dim); }

/* ── Wer redet, steht dran (Rico, 30.08.) ────────────────────────────
 *
 * „Wenn der Planer schreibt, sehe ich PLANER. Beim Coder sehe ich das
 * nicht."
 *
 * Er hatte recht — nur einer trug ein Schild, und dann sieht das Fehlen
 * aus wie eine dritte Sorte. Jetzt beide, in verschiedenen Farben, mit
 * verschiedenem Rand. Man muss nicht lesen, um es zu unterscheiden.
 */

.coder-wer.ist-coder { color: var(--text-muted); }
.msg-bubble.von-coder { border-left: 2px solid var(--border); }

/* ── „Er arbeitet noch" ───────────────────────────────────────────────
 *
 * Rico, 30.08.: „das Modell arbeitet, jedoch sieht man es als Nutzer
 * nicht. Im Chat sind drei Punkte da — hier sollte es immer unten sein
 * wenn er arbeitet."
 *
 * Dieselben Punkte wie im Chat, damit es dasselbe Zeichen ist. Dazu
 * die Dauer: „arbeitet" ohne Zeitangabe ist bei einem Auftrag, der
 * Minuten laeuft, keine Auskunft.
 */

.coder-arbeitet {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 2px 4px;
}

.coder-arbeitet-text {
  font-size: 13px;
  color: var(--text-muted);
}

/* ── Das Entstehende (D-666) ──────────────────────────────────────
 *
 * Was gerade geschrieben wird, steht in der Blase, an der gearbeitet
 * wird. Bewusst zurueckhaltend: es ist ein Blick in die Werkstatt,
 * nicht das Ergebnis. Wer es liest, soll sehen DASS gearbeitet wird —
 * nicht abgelenkt werden von dem, was gleich sowieso dasteht.
 */
.lauf-entstehend { margin-top: .25rem; }

.lauf-entstehend .zug-denken-laeuft > summary {
  color: var(--text-muted);
  font-style: italic;
}

.lauf-entstehend .zug-denken-text {
  white-space: pre-wrap;
  word-break: break-word;
  margin: .25rem 0 0;
  color: var(--text-muted);
  font-size: .92em;
  line-height: 1.45;
}

.lauf-laufender-text {
  white-space: pre-wrap;
  word-break: break-word;
  margin: .25rem 0 0;
  font: inherit;
}

/* Der angekuendigte Griff, bevor sein Ergebnis da ist. Derselbe
 * gedaempfte Ton wie das Denken — er ist noch keine Tatsache. */
.lauf-laufendes-werkzeug {
  margin-top: .35rem;
  color: var(--text-muted);
  font-size: .92em;
}


/* ── D-703: der Auftrag bricht um, statt seitwaerts zu laufen ───────
 *
 * Rico, 01.09., vom Handy: „der Inhalt sollte sich der Breite der Box
 * anpassen." Er hatte einen Block vor sich, dessen Zeilen rechts
 * abgeschnitten waren — auf einem Telefon ist seitwaerts scrollen in
 * einem Chat praktisch unbenutzbar.
 *
 * ``.msg-bubble pre`` steht auf ``overflow-x: auto``, und das ist fuer
 * CODE richtig: dort traegt die Einrueckung Bedeutung, ein Umbruch
 * zerschnitte sie. Ein Auftrag ist aber Prosa in Listenform — ihn will
 * man LESEN. Weil die Block-Sprache seit D-702 am Element steht, laesst
 * sich das trennen, ohne Code anzufassen. */
code.sprache-auftrag {
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── D-702: Absegnen — der Auftrag geht mit einem Klick zum Coder ────
 *
 * Rico, 01.09.: „der planer bespricht den plan, ich segne ab. bei ja
 * geht der plan direkt zum coder."
 *
 * Der Knopf steht UNTER dem Auftrags-Block, nicht daneben: er gehoert
 * zu dem, was darueber steht, und eine Zeile spaeter liest man ihn als
 * Abschluss statt als Verzierung. Farben kommen aus tokens.css. */
.auftrag-absegnen {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}
.auftrag-absegnen.ist-weg { opacity: 0.55; }
.an-den-coder {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--teal);
  border-radius: var(--radius-sm);
  background: var(--teal);
  color: var(--auf-teal);
  font: inherit; font-size: 0.82rem; font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
}
.an-den-coder:hover { filter: brightness(1.08); }
.an-den-coder:disabled {
  background: none;
  color: var(--text-muted);
  border-color: var(--border);
  cursor: default;
  font-weight: 400;
}


/* ── D-706: „Nochmal senden" neben dem Kopier-Knopf ─────────────────
 *
 * Rico, 01.09.: „für den Fall, dass der Lauf abgestürzt ist … der Knopf
 * ist neben dem Kopier-Button."
 *
 * Er borgt sich das Aussehen des Kopier-Knopfes (`.kopieren`) und
 * bringt nur sein eigenes Zeichen mit. Ein zweiter Stil waere eine
 * zweite Stelle, die man beim naechsten Feinschliff vergisst. */
.kopieren.nochmal svg {
  width: 14px; height: 14px;
  stroke: currentColor; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
/* Waehrend er laeuft, ist er kein Knopf mehr — sondern eine Auskunft. */
.kopieren.nochmal:disabled { opacity: 0.5; cursor: default; }

/* ── Rueckfragen zum Anklicken (D-708) ───────────────────────────────
 *
 * Rico, 01.09.: „die Aufgabe schreiben mit send button funktioniert.
 * aber Rueckfrage-Auswahl ist bisher reiner Text." Auf die Frage, wie
 * es sich bedienen soll: „Wie bei Claude."
 *
 * Also Karten statt Knopfleiste: Titel fett, Erklaerung darunter
 * kleiner und blasser. Man liest, was die Wahl bedeutet, bevor man
 * klickt — bei einer nackten Knopfreihe raet man.
 */
.rueckfrage {
  margin: 10px 0 2px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-secondary);
}
.rueckfrage.ist-weg { opacity: 0.55; }
.rueckfrage-block + .rueckfrage-block { margin-top: 14px; }
.rueckfrage-titel {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 0.86rem; font-weight: 600;
  color: var(--text);
  margin-bottom: 8px;
}
.rueckfrage-chip {
  padding: 1px 7px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.68rem; font-weight: 500;
  color: var(--text-muted);
}
/* Untereinander, nicht nebeneinander: die Erklaerung braucht die
 * Zeilenbreite, und am Handy stehen zwei Karten nebeneinander ohnehin
 * nur als zwei schmale Saeulen. */
.rueckfrage-karten { display: flex; flex-direction: column; gap: 6px; }
.rueckfrage-karte {
  display: flex; flex-direction: column; gap: 2px;
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  text-align: left;
  font: inherit;
  cursor: pointer;
  transition: var(--transition);
}
.rueckfrage-karte:hover { border-color: var(--teal); }
.rueckfrage-karte.gewaehlt {
  border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-ring-zart);
}
.rueckfrage-karte-label { font-size: 0.84rem; font-weight: 600; color: var(--text); }
.rueckfrage-karte-text { font-size: 0.76rem; color: var(--text-secondary); }
.rueckfrage-frei {
  width: 100%;
  margin-top: 6px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  font: inherit; font-size: 0.8rem;
  color: var(--text);
}
.rueckfrage-frei:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-ring-zart);
}
/* Solange etwas offen ist, sagt der Knopf WAS offen ist — „gesperrt
 * ohne Grund" ist die haeufigste Art, jemanden ratlos zu machen. */
.rueckfrage-senden:disabled { cursor: default; }

/* ── Kontext-Karte: wie voll ist der Kopf, und wovon ────────────
 * Rico, 02.09.: „planer context wird lang, coder kontext wird lang."
 * Beim Nachmessen griff der Deckel bei einem Projekt längst — 210 738
 * Zeichen gegen 200 000 — und niemand sah es. Diese Fläche macht es
 * sichtbar, bevor jemand bewusst schneidet. Sie zeigt nur Gemessenes;
 * wo nichts gemessen werden konnte, steht ein Strich. */
.kontext-karte {
  padding: 10px 12px 12px;
  margin: 4px 2px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.kontext-titel {
  margin: 0 0 8px;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 600;
}
.kontext-feld {
  display: flex;
  gap: 10px;
  align-items: baseline;
  justify-content: space-between;
  padding: 3px 0;
  font-size: 0.78rem;
  line-height: 1.45;
}
.kontext-etikett { color: var(--text-muted); white-space: nowrap; }
.kontext-wert {
  color: var(--text);
  text-align: right;
  overflow-wrap: anywhere;
}

/* Der Füllstand. Über 100 % wächst der Balken nicht weiter — sonst
 * schöbe er die halbe Tafel zur Seite; die Zahl daneben sagt es. */
.kontext-balken {
  height: 6px;
  margin: 6px 0 2px;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  overflow: hidden;
}
.kontext-fuellung {
  height: 100%;
  background: var(--teal);
  transition: width var(--transition);
}
.kontext-fuellung.knapp { background: var(--warnung); }
.kontext-fuellung.voll { background: var(--danger); }

/* Woraus der Kontext besteht. Gemessen am 02.09.: 40 % waren
 * Coder-Berichte — der Posten, den niemand geschrieben hat und der
 * trotzdem das Fenster füllt. */
.kontext-anteil { margin: 10px 0 2px; }
.kontext-anteil-titel {
  font-size: 0.7rem;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.kontext-stapel {
  display: flex;
  height: 8px;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  overflow: hidden;
}
.kontext-stueck { height: 100%; }
.kontext-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.7rem;
  color: var(--text-secondary);
}
.kontext-legende li { display: flex; align-items: center; gap: 5px; }
/* Was anfiel, aber nicht im Balken steckt — dieselbe Zeile, leiser,
 * und durch den fehlenden Punkt vom Balken-Anteil unterscheidbar. */
.kontext-angefallen { color: var(--text-muted); }
.kontext-punkt {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
}

/* ── Vermerke des Dienstes ──────────────────────────────────────
 * „Der Planer hat plan.md geschrieben" ist keine Wortmeldung, sondern
 * eine Randnotiz. Rico, 02.09.: über genau dieser Zeile stand **CODER**
 * — weil die Oberfläche nur „Nutzer" und „alles andere" kannte. Ein
 * Vermerk bekommt deshalb weder Kopf noch Namensschild, sondern sieht
 * aus wie das, was er ist. */
.coder-vermerk {
  margin: 6px 0 6px 44px;
  padding: 4px 0;
  font-size: 0.72rem;
  color: var(--text-muted);
  line-height: 1.5;
  border-left: 2px solid var(--border);
  padding-left: 10px;
}

/* ── Zusehen, wie er schreibt (D-736) ───────────────────────────
 * Rico, 02.09.: „kann man auch streamen, wie er in eine Datei
 * schreibt?" Die Zeichen tropfen aus dem Modell, während es den Aufruf
 * baut. Der Kasten hält eine feste Höhe und rollt mit — sonst schöbe
 * eine wachsende Datei bei jedem Zeichen die halbe Seite nach unten. */
.lauf-schreibt {
  max-height: 180px;
  overflow-y: auto;
  margin: 6px 0 0;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  color: var(--text-secondary);
  font-family: var(--mono);
  font-size: 0.7rem;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ── B7b: Bild-Kacheln — was das Modell sah, siehst du ─────────────
 *
 * Die Kachel haengt sichtbar am Zug (nicht im Aufklapper): ein Bild,
 * das ans Modell ging, darf nie versteckt sein. Klick oeffnet gross.
 */
.bild-kacheln {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 6px 0 10px;
}
.bild-kacheln img {
  max-width: 220px;
  max-height: 160px;
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: zoom-in;
  display: block;
}
