/* =====================================================================
   KI-Fenster — Tabs in der Kopfzeile, Historie-Aufklapper, Pop-ups,
   Vollbild (P5, 04.09.2026, docs/KI-FENSTER.md).

   Eigene Datei neben css/prepp.css (Muster css/listen.css): Sie benutzt
   NUR die --pp-Tokens, die auf body liegen, und kein einziges festes
   Pixelmaß ausserhalb der Kopfzeile. Die Fensterhülle selbst (.pp-fenster,
   .ppf-*, .ki-*) bleibt in prepp.css — ein Pop-up IST ein Portal-Fenster
   in der Lage „frei"; hier stehen nur die Dinge, die es vorher nicht gab.
   ===================================================================== */

/* ---------- Die Leiste in der Kopfzeile ---------- */
/* `flex: 1 1` ist seit dem 06.09.2026 die Stelle, an der der Platz des
   kompakten Suchknopfes ankommt: `.kf-leiste` ist der EINZIGE Wachser in
   der Kopfzeile, also fällt ihr zu, was er nicht mehr braucht (rund
   210 px). Wer hier auf `flex: 0 1` zurückgeht, nimmt den Reitern genau
   diesen Gewinn wieder weg — der Knopf bliebe klein, und der Platz stünde
   leer zwischen Bereichsname und Leiste.

   „Der EINZIGE Wachser" ist dabei wörtlich zu nehmen und wird von
   js/app.js (`kopfWachserHtml`) durchgesetzt: Ohne KI-Freischaltung gibt
   es diese Leiste nicht, dann steht an ihrer Stelle der Platzhalter
   `.pp-top-luft` und nimmt den Rest der Zeile. So ist der Suchknopf in
   BEIDEN Fällen links verankert und zieht nach rechts auf. Ein zweiter
   Wachser daneben teilte den Platz und halbierte den Gewinn.

   Der aufgezogene Suchknopf SCHIEBT diese Leiste seit dem 06.09.2026
   nicht mehr: Er liegt als Overlay darüber (css/prepp.css,
   `.pp-top-such-wurzel`), Breite und Reiterpositionen bleiben in beiden
   Zuständen gleich. */
.kf-leiste {
  display: flex; align-items: center; gap: 4px;
  flex: 1 1 200px; min-width: 0; position: relative; height: 34px;
}
.kf-hist-kn, .kf-neu {
  flex: none; height: 28px; min-width: 28px; padding: 0 7px;
  border: 1px solid var(--pp-line); border-radius: 6px;
  background: transparent; color: var(--pp-text-2);
  font: inherit; font-size: var(--pp-fs-klein); line-height: var(--pp-lh-eng); cursor: pointer;
}
.kf-hist-kn:hover, .kf-neu:hover { border-color: var(--pp-accent-line); color: var(--pp-accent-2); }
.kf-hist-kn.on { border-color: var(--pp-accent); color: var(--pp-accent-2); background: var(--pp-accent-tint); }
/* Die Tabs scrollen waagerecht, ohne die Kopfzeile zu sprengen — ein
   Chrome-Tabstreifen, kein Umbruch.

   `flex: 0 1 auto` ist dabei BEIDES zugleich, und das ist die Antwort auf
   den freigewordenen Platz des Suchknopfes (06.09.2026): Die Reihe
   SCHRUMPFT, wenn es eng wird (die Reiter gehen bis 64 px herunter), und
   sie WÄCHST NICHT ins Leere, wenn Platz da ist — ein Reiter bleibt bei
   seinen 180 px. Mehr Raum heißt hier also nicht „breitere Reiter bei
   einem Chat", sondern „ab vier Chats stehen wieder Titel statt
   ‚Neuer C…' da". Ein `flex-grow: 1` hier zöge die Reihe an den rechten
   Rand und risse den Weg zu einem neuen Chat von ihr los. */
.kf-tabs {
  display: flex; align-items: stretch; gap: 3px;
  flex: 0 1 auto; min-width: 0; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; height: 30px;
}
.kf-tabs::-webkit-scrollbar { display: none; }
.kf-tab, .kf-tabneu {
  display: inline-flex; align-items: center; gap: 6px;
  flex: 0 1 180px; min-width: 64px; max-width: 200px; box-sizing: border-box;
  padding: 0 4px 0 10px; border: 1px solid var(--pp-line); border-radius: 7px 7px 3px 3px;
  background: var(--pp-surface-2); color: var(--pp-text-2);
  font-size: var(--pp-fs-klein); cursor: pointer; user-select: none; white-space: nowrap;
}
.kf-tab:hover { color: var(--pp-text); border-color: var(--pp-line-2); }
.kf-tab.on { background: var(--pp-bg); color: var(--pp-text); border-color: var(--pp-accent-line); border-bottom-color: var(--pp-bg); }
/* Minimiert ist eine FORM, nicht nur eine Farbe (Regel der Sandbox-Bänder):
   gestrichelter Rand. */
.kf-tab.min { border-style: dashed; }
/* „zuletzt benutzt" (07.09.2026): der zuletzt angefasste Chat ohne offenes
   Fenster hier — auf dem Telefon der Chat, in dem am anderen Gerät gerade
   gearbeitet wird. Eine Unterstreichung, kein zweites `on`. */
.kf-tab.zuletzt:not(.on) .kf-tab-t { text-decoration: underline dotted; text-decoration-color: var(--pp-accent); text-underline-offset: 3px; }
/* „Gehört zu DIESER Seite" (N2a, 12.09.2026): der Reiter jedes Chats,
   dessen Heimat die gerade offene Seite ist — offen wie minimiert. Er ist
   der Weg dorthin, wo man auf dieser Seite aufgehört hat.

   BLAUER RAND, sonst nichts. Dass hier kein zusätzlicher `inset`-Ring
   steht (das Muster von `.sb-b.on`, „der EIN-Zustand ist eine FORM"), ist
   eine Entscheidung und kein Vergessen: Ein solcher Ring ist immer SOLID
   und läge über dem gestrichelten Rand von `.kf-tab.min` — und gerade der
   minimierte Chat ist Jonas' Fall („jetzt vielleicht nur minimiert").
   Die Markierung nähme also der Minimierung ihre Form. Der Rand allein
   trägt trotzdem ohne Farbwahrnehmung: gegen `--pp-line` (den Rand, den
   er ersetzt) misst `--pp-accent` 4,40 : 1 im dunklen und 3,39 : 1 im
   hellen Theme, gegen die Fläche der Leiste (`--pp-surface`) 6,22 bzw.
   4,63 : 1 — beides über den 3 : 1 aus WCAG 1.4.11. Gerechnet aus den
   Tokendefinitionen, nachgerechnet in verify-leiste-markierung-sync.js.

   `border-bottom-color` bleibt beim aktiven Reiter unangetastet: Dort
   verschmilzt die Unterkante mit dem Panel (`--pp-bg`), und eine blaue
   Linie quer hindurch machte aus dem Reiter wieder einen Kasten. */
.kf-tab.daheim { border-color: var(--pp-accent); }
.kf-tab.daheim.on { border-bottom-color: var(--pp-bg); }
.kf-tab:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
.kf-tab-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Die laufende Nummer gleichnamiger Reiter (C40) steht NEBEN dem Titel,
   nicht darin (09.09.2026, Jonas' Screenshot mit vier gleich aussehenden
   Reitern): Sie stand als letztes Wort im Titel und fiel damit als
   Erstes der Ellipse zum Opfer — vier Chats mit den Nummern 2, 3, 4 und
   5 sahen identisch aus. `flex: none` ist die ganze Reparatur: Was nicht
   schrumpft, wird nicht abgeschnitten. Sie ist eine Unterscheidungs-
   hilfe fürs Auge (aria-hidden — der volle Titel samt Nummer steht im
   `title` des Reiters, den ein Screenreader ohnehin liest). */
/* FARBE: `--pp-text-2`, nicht `--pp-text-3`. Aus den Tokendefinitionen
   gerechnet, auf der Reiterfläche `--pp-surface-2`: text-3 gibt
   4,65 : 1 (dunkel) und 4,63 : 1 (hell) — über AA, aber knapp, und das
   bei 11 px. text-2 gibt 6,45 / 6,20 : 1. Die Nummer ist das EINZIGE,
   was vier sonst gleich aussehende Reiter unterscheidet; sie blasser zu
   setzen als den Titel daneben (gemessen 6,45 : 1) wäre die falsche
   Rangfolge. Im aktiven Reiter erbt sie dessen Farbe (16,02 / 14,84). */
.kf-tab-nr { flex: none; margin-left: 3px; font-variant-numeric: tabular-nums;
  color: var(--pp-text-2); font-size: var(--pp-fs-mini, .78em); }
.kf-tab.on .kf-tab-nr { color: inherit; }
.kf-tab-x {
  flex: none; border: 0; background: transparent; color: var(--pp-text-3);
  width: 18px; height: 18px; border-radius: 4px; font: inherit; font-size: var(--pp-fs-klein);
  line-height: var(--pp-lh-eng); cursor: pointer; padding: 0;
}
.kf-tab-x:hover { background: var(--pp-err-tint); color: var(--pp-err); }
/* Der letzte Reiter der Reihe ist der WEG zu einem neuen Chat (06.09.2026).
   Er sieht aus wie ein Tab, ist aber keiner: kein role="tab", kein
   aria-selected, keine Auswahlfarbe — eine AKTION in der Gestalt der
   Reihe, in der sie wirkt (Muster: die Plus-Kachel auf #courses, K2).
   Er schrumpft NICHT mit (`flex: 0 0 auto`): Ein „Chat erst…" wäre genau
   das Zeichen ohne Wort, das er ersetzt; die Reihe scrollt lieber.
   Der gestrichelte Rand ist hier NICHT zu haben — er gehört .kf-tab.min
   („minimiert ist eine FORM"); unterschieden wird über das ＋ und die
   Akzentkante, wie beim ▾ im Hover. */
.kf-tabneu {
  flex: 0 0 auto; max-width: none; gap: 5px; padding: 0 10px; height: 30px;
  background: transparent; border-color: var(--pp-accent-line); color: var(--pp-accent-2);
  font: inherit; font-size: var(--pp-fs-klein);
}
.kf-tabneu:hover { background: var(--pp-accent-tint); color: var(--pp-accent-2); }
.kf-tabneu:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
.kf-tabneu .kf-tab-t { overflow: visible; }
.kf-tabneu-ico { flex: none; line-height: var(--pp-lh-eng); }
/* Läuft ein Stream, pulsiert ein Punkt — derselbe wie am Job-Chip. */
.kf-tab-dot {
  flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: var(--pp-accent); animation: pp-pulse 1.6s infinite;
}
@media (prefers-reduced-motion: reduce) { .kf-tab-dot { animation: none; } }
/* Ein Lauf der Hülle WARTET auf einen freien Platz (LAEUFE-ALS-CHAT,
   13.10.2026): derselbe Punkt, hohl und ruhig — da, aber noch nicht dran. */
.kf-tab-dot.wartet {
  background: transparent; box-shadow: inset 0 0 0 1.5px var(--pp-accent); animation: none;
}
/* Ergebnis und Warteschlange eines Hintergrund-Laufs im Verlauf: eine
   Zeile mit Text und Knopf, die auf schmalen Fenstern umbricht. */
.ki-lauf-ergebnis, .ki-lauf-schlange {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  padding: 6px 8px; border-radius: 8px; background: var(--pp-accent-tint);
}
.ki-lauf-schlange { background: transparent; border: 1px dashed var(--pp-line); }
.ki-lauf-ergebnis-t { min-width: 0; overflow-wrap: anywhere; }

/* ---------- Der Schatten, der zum Reiter fliegt (09.09.2026) ----------
   Die GEOMETRIE steht in js/anim.js (PreppAnim.fensterFlug schreibt
   Breite, Höhe und die zwei transform-Werte), FARBE und BEWEGUNG hier —
   dasselbe Muster wie bei den Mini-Demos des Handbuchs (css/handbuch.css).

   Der Knoten heißt `.pp-flug`, weil der Mechanismus allgemein ist; sein
   Aussehen wohnt trotzdem hier, weil ihn heute nur das Chatfenster
   benutzt und er wie eines aussehen soll. Bekommt er einen zweiten
   Benutzer, zieht dieser Block nach css/prepp.css um — bis dahin wäre
   ein allgemeiner Block eine Behauptung über eine Verwendung, die es
   nicht gibt.

   z-index 137: über den Pop-ups (131–135) und über der aufgestellten
   Kopfzeile (136 — dort landet der Flug), unter dem Kontextmenü (140)
   und den Dialogen (150). `pointer-events: none`, damit der Schatten
   keinen Klick abfängt, der dem Fenster oder dem Reiter gilt.

   prefers-reduced-motion GEWINNT: `an()` in anim.js liefert dann zwar
   ohnehin schon false (animAn() fragt bewegungsSperre()), aber die
   Zusage gehört auch dorthin, wo sie ohne JavaScript gilt. */
.pp-flug {
  position: fixed; left: 0; top: 0; z-index: 137; pointer-events: none;
  box-sizing: border-box; transform-origin: 0 0; opacity: .96;
  overflow: hidden; padding: 8px 12px;
  background: var(--pp-bg-2); color: var(--pp-text-2);
  border: 1px solid var(--pp-accent-line); border-radius: 10px;
  box-shadow: var(--pp-lift, 0 14px 36px rgba(0, 0, 0, .28));
  font-family: var(--pp-sans); font-size: var(--pp-fs-klein);
  line-height: var(--pp-lh-eng); white-space: nowrap; text-overflow: ellipsis;
  transition: transform var(--pp-flug-ms, 220ms) cubic-bezier(.4, 0, .2, 1),
              opacity var(--pp-flug-ms, 220ms) ease;
}
@media (prefers-reduced-motion: reduce) { .pp-flug { display: none !important; } }

/* ---------- Der Historie-Aufklapper ---------- */
/* Unter dem ▾, über allem Seiteninhalt (z 135: unter Kontextmenü 140,
   über den Pop-ups 130–139). Die Liste darin ist die bisherige
   Gesprächsliste (.prof-liste) — Suche, Gruppen, ⋯-Menü unverändert. */
.kf-hist {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 135;
  width: min(360px, 92vw); max-height: min(70vh, 640px); overflow-y: auto;
  box-sizing: border-box; padding: 8px;
  background: var(--pp-bg-2); color: var(--pp-text);
  border: 1px solid var(--pp-line-2); border-radius: 10px;
  box-shadow: var(--pp-lift, 0 14px 36px rgba(0, 0, 0, .28));
}
.kf-hist .prof-liste { max-height: none; }
/* Die Kopfzeile ist `position: sticky` mit z-index 20 (prepp.css) und
   damit ein eigener Stapel: z 135 gilt nur INNERHALB von ihr. In WebKit
   bei 1100 px lag die Liste deshalb UNTER dem Pop-up (z 130 am body), das
   sich mit ihr überschnitt (Stufe 3, docs/abnahme/ki-fenster). Solange
   die Historie offen ist (Marke aus kfLeisteBinden), steht die ganze
   Kopfzeile über den Pop-ups (130–135) und unter den Dialogen (150).

   DASSELBE gilt, solange überhaupt ein Pop-up steht (`kf-pop-auf`, B40
   der Abnahme vom 04.09.2026): Die TAB-LEISTE ist der einzige Ort, an
   dem offene Chats stehen, und sie war unter einem Pop-up nicht nur
   verdeckt, sondern unklickbar (WebKit, 1440 px: 5400 px² Überlappung,
   elementFromPoint trifft das Fenster). Zwei Marken statt einer, weil die
   zwei Anlässe verschieden sind — die Stufe ist dieselbe und steht
   deshalb in EINER Regel.

   Die 136 gilt erst, seit das Pop-up-Band bei 135 endet (js/app.js,
   kfNachVorn): Vorher reichte es bis 139 und gewann ab dem sechsten
   „nach vorn" wieder. */
.pp-top.kf-hist-auf, .pp-top.kf-pop-auf,
.kf-wirt-leiste.kf-hist-auf, .kf-wirt-leiste.kf-pop-auf { z-index: 136; }

/* ---------- Die Leiste außerhalb der Kopfzeile (N1d, 12.09.2026) ----------
   Die EINSICHT ist die eine Portalseite ohne `.pp-top`, und ihre
   Prüfungsfassung ist gar keine Portalseite. Beide tragen die Leiste
   jetzt selbst — derselbe Bauer (kfLeisteHtml), zwei Rahmen.

   Der Rahmen setzt im Ruhezustand SO WENIG z-index wie möglich:
   `.kf-hist` liegt darin absolut auf 135 und muss im Stapel der SEITE
   zählen. Jedes z-index hier macht den Rahmen zum eigenen
   Stapelkontext und klemmt den Aufklapper auf dessen Stufe — deshalb
   hebt ihn erst die Marke `kf-hist-auf` (oben, 136), und zwar genau
   dann, wenn der Aufklapper wirklich offen steht. In der PrepP-Fassung
   kommt der Rahmen ganz ohne aus (in WebKit gemessen: sein Reiter
   gehört sich selbst); in der Prüfungsfassung braucht er eine niedrige
   Stufe, siehe `.kf-wirt-dyn`. */
.kf-wirt-leiste { position: relative; min-width: 0; display: flex; }
/* (a) In der PrepP-Fassung: dritter Platz in `.ein-top`, zwischen Titel
   und den Knöpfen rechts (die halten ihr `margin-left: auto`). Der
   Wachser ist die Leiste selbst — `.kf-leiste { flex: 1 1 200px }` —,
   also darf der Rahmen wachsen. */
.kf-wirt-ein { flex: 1 1 220px; }
/* (b) In der Prüfungsfassung: ein Streifen im Inhaltsstrom, der an der
   Unterkante der dunklen Leiste hängen bleibt. `sticky` statt `fixed`,
   weil er dann seinen Platz im Fluss BEHÄLT — ein festes Fenster hätte
   das 80-px-Polster von `.exam-scroll` gebraucht, und das gehört der
   echten Prüfungsoberfläche (es gilt auch in #run, wo es keine Leiste
   gibt).

   `z-index: 45` ist GEMESSEN, nicht gewählt (WebKit, 12.09.2026): Ohne
   z-index malte der Klausurinhalt über den Streifen — `.answer-row` und
   `.ex-card` sind `position: relative` und stehen später im Dokument,
   ein gescrollter Lösungsweg (`.sp-body`) lag also darauf (gemessen
   `obenDrauf: "sp-body"`). Die 45 hebt ihn über den Inhalt (0) und
   lässt die dunkle Leiste (50), die Fußleiste (50) und den Punktekasten
   (60) darüber, wo sie hingehören — überlappen kann er sie ohnehin
   nicht, er klebt an ihrer Unterkante. Der Aufklapper darin ist damit
   auf 45 geklemmt; genau dafür gibt es `kf-hist-auf` (136), das ihn
   beim Öffnen über alles hebt.

   Heller Grund: Der Streifen steht auf dem grauen Klausurhintergrund,
   und die Reiter sind Portal-Bauteile auf --pp-Tokens. Er bekommt
   deshalb dieselbe Fläche wie das Klausurblatt darunter und eine Kante,
   damit er nicht im Grau schwimmt. */
.kf-wirt-dyn {
  position: sticky; top: var(--exam-top-h, 56px); z-index: 45;
  margin: 0 0 14px; padding: 6px 10px; border-radius: 4px;
  background: #fff; box-shadow: var(--shadow, 0 1px 4px rgba(0, 0, 0, .14));
}
/* Die Prüfungsfassung ist in BEIDEN Themes hell (Zwei-Welten) — die
   --pp-Tokens am body tragen aber die Werte des gewählten Themes. Im
   dunklen Theme läge sonst eine dunkle Reiterreihe auf dem weißen
   Streifen. Gepinnt wird wie bei der Bewerter-Karte (A1, 10.09.2026):
   die Tokens lokal auf ihre hellen Werte, EINE Stelle, und jede künftige
   Reiter-Regel gilt von selbst mit. Die Werte sind wörtlich die aus
   `body[data-theme="light"]` in css/prepp.css. */
body:not(.pp-mode) .kf-wirt-dyn {
  /* --pp-bg ist hier BEWUSST weiß und nicht #f6f8fa wie im hellen
     Theme: Der aktive Reiter setzt seine Fläche darauf, und er soll mit
     dem Streifen verschmelzen, auf dem er steht (in der Kopfzeile tut er
     dasselbe — dort IST --pp-bg die Seitenfläche). */
  --pp-bg: #ffffff;
  --pp-bg-2: #ffffff;
  --pp-surface: #ffffff;
  --pp-surface-2: #f0f3f6;
  --pp-line: #d7dde3;
  --pp-line-2: #c3ccd4;
  --pp-line-feld: #838c96;
  --pp-text: #1f2328;
  --pp-text-2: #525b65;
  --pp-text-3: #676e77;
  --pp-accent: #1f6feb;
  --pp-accent-2: #175bc7;
  --pp-accent-contrast: #ffffff;
  --pp-accent-tint: #e7f0fd;
  --pp-accent-line: #b6d3fa;
  --pp-err: #cf222e;
  --pp-err-tint: #ffebe9;
  color: var(--pp-text);
}

/* ---------- Pop-ups ---------- */
/* Ein Pop-up ist ein .pp-fenster in der Lage „frei" (prepp.css: fixed,
   z 130). Hier nur, was ein Pop-up ZUSÄTZLICH ist: der Wirt am body
   nimmt keinen Platz ein, und die Ankerzeile ist ein Weg.

   ---- DER WIRT HÄNGT AM body UND ERBT DESHALB NICHTS VOM PORTAL ----
   (Q1, 05.09.2026, Jonas' Befund „die Antworten sind ausgegraut").
   `#kf-wirt` steht ausserhalb von `.pp-root` — das MUSS so sein, sonst
   riesse `shell()` bei jeder Navigation die offenen Fenster samt
   laufendem Strom weg (die Zusage „ein Pop-up ueberlebt die Navigation",
   verify-ki-fenster.js 3). Der Preis: Alles Vererbte kommt vom `body`,
   und den beschreibt css/exam.css (`--txt: #333c48`, Segoe UI, 14.5px) —
   nicht das Portal. In WebKit gemessen (dunkel, 1440 px): Antworttext und
   Wartezeile standen auf `rgb(51, 60, 72)` gegen `--pp-surface-2`, also
   1,42 : 1 statt 13,40 : 1; Schrift Segoe UI statt IBM Plex; Grundgroesse
   14,5 statt 13,5 px. Im HELLEN Theme faellt es nicht auf (10,03 : 1) —
   deshalb hat es niemand gesehen.

   Der Wirt holt das Portal deshalb nach: genau die Erklaerungen, die
   `.pp-root` in css/prepp.css vererbt. Das ist die HAUSREGEL, nicht eine
   Ausnahme — jeder schwebende Baustein am body macht es so
   (`.pp-modal`, `.ed-hintwin`: beide setzen color und font-family selbst;
   .ed-hintwin ist ausdrucklich das Vorbild des Pop-ups, docs/KI-FENSTER.md
   Abschnitt 1). Wer hier eine Eigenschaft ergaenzt, ergaenzt sie in
   .pp-root ebenfalls — und umgekehrt. */
#kf-wirt {
  position: static; width: 0; height: 0;
  color: var(--pp-text);
  font-family: var(--pp-sans);
  font-size: var(--pp-fs-text);
  font-weight: 400;
  line-height: var(--pp-lh-text);
  -webkit-font-smoothing: antialiased;
}
#kf-wirt b, #kf-wirt strong { font-weight: 600; }
#kf-wirt a { color: var(--pp-accent-2); text-decoration: none; }
#kf-wirt a:hover { color: var(--pp-accent-2); text-decoration: underline; }
/* Eingabefeld und Knoepfe des Chats: exam.css setzt `button { font-family:
   inherit }`, ein <textarea> aber nicht — es fiel auf die Browservorgabe
   zurueck. */
#kf-wirt input, #kf-wirt button, #kf-wirt select, #kf-wirt textarea { font-family: inherit; }
#kf-wirt *:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 2px; }
/* Die Regel darüber trägt eine Kennung und schlägt damit jede Klassenregel
   im Pop-up — auch den INNEN liegenden Ring der Anbieterwahl
   (.ki-anb-btn, -2px): Der Ring lag wieder außen und wurde vom
   `overflow: hidden` der Leiste abgeschnitten, gemessen 50 von ~300
   Ringpixeln (ns0929-p5, WebKit). Dieselbe Regel wie in css/prepp.css
   („Ring nach innen, wo ein Behälter bündig abschneidet"), nur mit der
   Kennung des Wirts. Und das Chatfeld: Den Ring trägt der KASTEN
   (.ki-box:has(textarea:focus-visible)), sonst stünden im Pop-up zwei. */
#kf-wirt :is(.ki-anbieter, .pp-segment, .kf-tabs) > :focus-visible { outline-offset: -2px; }
#kf-wirt .ki-eingabe textarea:focus-visible { outline: none; }
#kf-wirt ::selection { background: var(--pp-accent-tint); }
/* Die Ankerzeile des Pop-ups ist ein Weg — sie führt dorthin zurück,
   wo der Chat begann. */
.ppf-unter.kf-anker-link { cursor: pointer; }
.ppf-unter.kf-anker-link:hover { color: var(--pp-accent-2); text-decoration: underline; }
/* ---------- Der Wartezustand: drei Punkte in der Statusfarbe ----------
   Q1 (05.09.2026), Jonas: „Dunkel Modus drei Punkte umdesignen, dass
   keine weisse Oberflaeche mehr ist."
   P11 hat die Punkte aus `currentColor` gemalt (css/prepp.css). Das
   heisst: im dunklen Theme sind sie fast WEISS (--pp-text #e6edf3, im
   Puls bis Deckkraft 1), im hellen fast schwarz — dieselbe Marke sieht
   je Theme entgegengesetzt aus, und im Dunkeln sind es drei helle
   Flecken. Sie bekommen deshalb die Farbe, die PrepP fuer „hier laeuft
   etwas" ohnehin benutzt: `--pp-accent`, wie der Punkt am Tab
   (.kf-tab-dot, gleiche Bedeutung, gleiche Groessenordnung, gleicher
   Puls-Bereich). EINE Marke, EINE Farbe, in beiden Themes.
   Gerechnet gegen --pp-surface-2 (die Flaeche der Antwortblase), im
   Scheitel des Pulses: 5,75 : 1 dunkel, 4,14 : 1 hell — beide ueber den
   3 : 1 aus WCAG 1.4.11 fuer eine Nicht-Text-Anzeige. Der gedaempfte Teil
   des Pulses (.35) liegt darunter; das ist bei .kf-tab-dot und beim
   Punkt der Laufenden-Versuch-Pille genauso und ist die Natur eines
   Pulses — die Aussage traegt der Scheitel.
   Bewegung, Zeitverlauf und der reduced-motion-Stopp bleiben, wie P11 sie
   gebaut hat: Nur die FARBE aendert sich, kein neuer Keyframe. */
.ki-warte-punkte i { background: var(--pp-accent); }
/* ---------- Anheften und Umbenennen: das ⋯-Menü darf nicht springen ----
   Q1 (05.09.2026), Jonas: „Chat anheften oder umbenennen funktioniert
   noch nicht."
   In WebKit gemessen, mit echten Maus-Ereignissen: `mousedown` traf den
   Knopf „Anheften", `mouseup` traf `div.prof-kopfzeile` — zwei
   verschiedene Ziele, also feuert der Browser `click` auf den
   gemeinsamen VORFAHREN, und der `onclick` des Menüpunkts läuft NIE.
   Kein DOM-Wechsel dazwischen (MutationObserver: leer), kein JS-Fehler.
   Die Ursache ist eine Zeile, die nach nichts aussieht:
   `.pp-pick:active { transform: translateY(0) }` (css/prepp.css). Ein
   Transform — auch die IDENTITÄT — macht das Element zum CONTAINING BLOCK
   für seine `position: fixed`-Kinder. Das ⋯-Menü ist genau so ein Kind
   (es bleibt bewusst Kind seiner Zeile, damit es mit der Liste
   verschwindet — 24.08.2026). Solange die Maustaste gedrückt ist, gilt
   `:active`, und die Lage aus profMenuAusrichten (Fensterkoordinaten,
   `left: 680px; top: 196px`) wird plötzlich gegen die ZEILE gerechnet:
   gemessen sprang das Menü von 680/196 auf 1248/364 — genau um den
   Ursprung der Zeile (568/168). Unter dem Zeiger lag danach die Zeile.
   Also: Eine Zeile, die ein schwebendes Menü TRÄGT, ist nie ein
   Containing Block. `transform: none` statt `translateY(0)` ist dabei
   pixelgleich (die Zeile hat auf hover ohnehin kein Transform, gemessen)
   — es verschwindet nur der Containing Block.
   Die Zeile in prepp.css ist die eigentliche Falle und trifft jedes
   künftige `position: fixed`-Kind einer anfassbaren Fläche; sie steht
   als Empfehlung im Bericht (docs/KI-FENSTER-Q1.md 2). Hier wird sie für
   den einen Ort entschärft, den Jonas gemeldet hat — css/prepp.css
   gehört in dieser Sitzung einem parallelen Paket. */
/* Seit dem 18.09.2026 gegenstandslos und deshalb ohne Regel: Das Menue
   haengt am body (#pp-ctx), die Zeile ist also gar nicht mehr sein
   Containing Block. Die allgemeine Falle — `.pp-pick:active { transform }`
   in css/prepp.css macht jede anfassbare Flaeche zum Bezug eines
   `position: fixed`-Kindes — bleibt bestehen und steht als Empfehlung im
   Bericht (docs/KI-FENSTER-Q1.md 2). */
/* Das ⋯ trägt seit Q1 die Klassen jedes anderen ⋯ des Portals
   (`pp-btn slim pp-lmore`, js/app.js) — ohne Klasse malte der Browser
   seine Vorgabe, im dunklen Theme eine helle Kachel. Die MASSE bleiben
   die der kompakten Gesprächszeile: `.pp-btn.slim` polstert 6 px oben
   und unten, damit wuchs die Zeile von 33 auf 42 px und die Verdichtung
   vom 13.08.2026 („46 → 33 px je Zeile") wäre zur Hälfte zurückgedreht.
   Gemessen: mit dieser Regel wieder 33 px. */
.prof-liste .pp-actions .pp-lmore {
  padding: 1px 8px; min-width: 28px; line-height: var(--pp-lh-knapp);
}
/* Meldet die Liste selbst etwas (abgelehntes Umbenennen oder Löschen),
   steht es in derselben Hülle wie im Chat (.ki-fehler) — die Liste hat
   `gap: 1px`, also braucht der Kasten seinen eigenen Abstand. */
.prof-liste .prof-fehler { margin: 6px 0; }
/* ---------- Die Knöpfe der Chat-Kopfzeile sind EIN Satz ----------
   Q1 (05.09.2026), Jonas: „das Vollbild und das X voneinander verschoben
   oben rechts."
   In WebKit gemessen (Pop-up, 1440 px): ⛶ war 20 × 16 px bei 12 px
   Schrift, ✕ 18 × 21 px bei 17 px — nebeneinander, mit 8 px Abstand, und
   die Kästen zwar auf einer Mittellinie, die GLYPHEN aber in zwei
   Größen und aus zwei Schnitten. Im Training stehen davor noch die fünf
   Lagenknöpfe (18 × 17 px): drei Maße in einer Reihe.
   Sie bekommen deshalb dieselbe quadratische Box und dieselbe Größe, und
   die Glyphe wird darin ZENTRIERT (inline-flex) statt an der Grundlinie
   abgesetzt — das ist der Punkt: Ein ⛶ und ein ✕ haben verschiedene
   Ober- und Unterlängen, an der Grundlinie ausgerichtet sitzen sie nie
   auf derselben Höhe. Nur die KI-Fenster (.ki-tutor: Aufgaben-Panel und
   Pop-up); das Notizfenster teilt sich die Klassen und bleibt, wie es
   ist — seine Hülle wohnt in css/prepp.css. */
.ki-tutor > .ppf-kopf .ppf-dock,
.ki-tutor > .ppf-kopf > .ppf-x {
  display: inline-flex; align-items: center; justify-content: center;
  box-sizing: border-box; width: 24px; height: 24px;
  padding: 0; border-radius: 6px; font-size: var(--pp-fs-text); line-height: var(--pp-lh-eng);
}
/* Zwei Zeichen, zwei Schnitte: Bei GLEICHER Schriftgröße zeichnet WebKit
   das ⛶ 11,4 px breit und das ✕ nur 8,4 px — das eine wirkt schwerer.
   Die Größen sind deshalb einzeln gesetzt und an den Tintenbreiten
   nachgemessen (Bericht Abschnitt 4), nicht geschätzt. */
.ki-tutor > .ppf-kopf > .kf-vollkn { font-size: var(--pp-fs-klein); }
.ki-tutor > .ppf-kopf > .ppf-x { font-size: var(--pp-fs-gross); }
.kf-vollkn { font-size: var(--pp-fs-klein); }
/* Das „−" ist ein Bindestrich in einer 24-px-Box: bei der Textgröße
   verschwindet er fast, deshalb dieselbe Stufe wie das ✕ daneben. Er
   trägt .ppf-dock und bekommt Box und Mitte damit aus der Regel oben. */
.ki-tutor > .ppf-kopf > .kf-minkn { font-size: var(--pp-fs-gross); }
/* Das „⋯" (12.09.2026, der ganze Chat: kopieren, drucken) steht LINKS
   vom „−" und trägt dieselbe .ppf-dock-Box — es ist ein Knopf dieses
   Satzes, kein Fremdkörper daneben. Wie das „−" ist es eine flache
   Glyphe ohne Ober- und Unterlängen und verschwände bei der Textgröße in
   der 24-px-Box; es bekommt deshalb dieselbe Stufe. */
.ki-tutor > .ppf-kopf > .kf-mehrkn,
.kf-voll-chat > .ki-kopf > .kf-mehrkn { font-size: var(--pp-fs-gross); }
/* Der Griff sagt, dass er offen ist, solange sein Menü steht — dieselbe
   Marke, die das Lagen-Untermenü an seinem ⛶ setzt (aria-expanded) und
   die #pp-ctx beim Schließen an EINER Stelle zurücknimmt. */
.kf-mehrkn[aria-expanded="true"] { color: var(--pp-text); background: var(--pp-bg-2); }

/* ---------- Das ✕ ist ROT, weil es SCHLIESST (S1, 06.09.2026) ----------
   Jonas: „… oder mit dem roten X im Fenster sollen sie auch direkt
   geschlossen werden." Bis dahin minimierte das ✕ nur — es trug das
   Zeichen einer Handlung und tat eine andere; die Farbe macht die neue
   Bedeutung sichtbar, und zwar VOR dem Klick.

   Der Zuschnitt ist strukturell (`.ki-tutor > .ppf-kopf > .ppf-x`), nicht
   über die Marke aus dem Binder: Ein Fenster, dessen Binder aus welchem
   Grund auch immer nicht gelaufen ist, soll nicht anders aussehen als
   eines, dessen Binder lief. Das Notizfenster teilt sich die .ppf-Klassen
   und bleibt unberührt.

   Gemessen (Q5-Tokenwerte, an --pp-surface, der Fläche der Fensterkarte):
   #f85149 auf #161b22 = 5,16 : 1, #cf222e auf #ffffff = 5,36 : 1 — beide
   über AA. Der HOVER nimmt --pp-surface-2, den Ruhe-Hover des Portals,
   und lässt die Schrift rot: 4,72 : 1 dunkel, 4,81 : 1 hell.
   --pp-err-tint wäre der naheliegende Ton und ist GEMESSEN VERWORFEN —
   dunkel kommt Rot darauf nur auf 4,47 : 1, also knapp unter AA. */
.ki-tutor > .ppf-kopf > .ppf-x { color: var(--pp-err); }
.ki-tutor > .ppf-kopf > .ppf-x:hover,
.ki-tutor > .ppf-kopf > .ppf-x:focus-visible {
  color: var(--pp-err); background: var(--pp-surface-2);
}
/* Das Pop-up hat einen Kopf zum Ziehen — derselbe Cursor wie beim Tutor. */
.kf-fenster > .ppf-kopf { cursor: move; }

/* ---------- Der Weg zurück nach einem Fehlschlag (C9, S1) ---------- */
/* NEBEN der Fehlerzeile, nicht darin: Deren Text ist der des Servers und
   bleibt zeichengleich (js/app.js, kiVerlaufHtml). Der Knopf steht
   deshalb als eigene Zeile darunter, linksbündig wie die Meldung. */
.ki-fehler-akt { margin: var(--pp-sp-2) 0 var(--pp-sp-1); }
/* Zwei Wege nebeneinander (Nochmal · Mit PrepP-KI erneut): Sie dürfen in
   einer Zeile stehen, dann teilt sie der Abstand. */
.ki-fehler-akt + .ki-fehler-akt { margin-top: 0; }
/* Die Auskunft „ohne die Anhänge" unter dem Wiederholungsknopf (C4,
   10.09.2026). Sie steht als eigene ZEILE, nicht neben dem Knopf: Der
   Satz nennt eine Zahl und einen Weg und wäre neben einem Knopf in einem
   380 px breiten Pop-up das Erste, was umbricht. --pp-text-2, nicht -3:
   Es ist eine Warnung, kein Nebentext. */
.ki-erneut-ohne {
  margin-top: var(--pp-sp-1);
  font-size: var(--pp-fs-klein);
  color: var(--pp-text-2);
}

/* ---------- Die Anbieterwahl unter der Eingabe (08.09.2026) ----------
   docs/KI-ANBIETERWAHL-2026-09-08.md. Ein Segment [PrepP-KI] [RWTHgpt]
   in der Fußzeile — dieselbe Bauart wie der Privat/Öffentlich-Umschalter
   (.pp-vis, prepp.css), nur kleiner, weil es unter jedem Eingabefeld
   steht. Der EIN-Zustand ist eine FORM, keine Farbe: ein Balken UNTER dem
   gewählten Knopf (inset box-shadow, kein Layout-Sprung) plus Gewicht 600
   — in Graustufen unterscheidbar (die Lehre vom Sandbox-Band, 24.08.).
   Ausgegraut (.aus) heißt aria-disabled, NICHT disabled: Der Klick führt in
   die Einstellungen, der Zeiger bleibt deshalb eine Hand; der Ton ist
   --pp-text-3 (4,63 : 1 seit der Skala Q5) und die Schrift durchgestrichen
   nicht — sie muss lesbar bleiben, denn sie sagt, WAS es freizuschalten
   gilt. Nur --pp-Tokens; #kf-wirt hängt am body (Q1).
   KURSIV AUCH NICHT (wa1009-r2 D, 10.10.2026; Abnahme wa1009-p5, Befund 19):
   Für IBM Plex Sans ist kein Kursivschnitt eingebettet (vendor/fonts.css),
   WebKit stellte die Schrift deshalb synthetisch schräg — gelesen wurde
   „RWTHgpt" als fremde, „kursiv-serif" wirkende Schrift. Den Zustand tragen
   Farbe (--pp-text-3), aria-disabled, der title und der Klick in die
   Einstellungen; eine unechte Kursive fügt dem nichts hinzu. */
.ki-anbieter { display: inline-flex; gap: 0; border: 1px solid var(--pp-line); border-radius: 6px;
  overflow: hidden; flex: none; max-width: 100%; }
.ki-anb-btn { display: inline-flex; align-items: baseline; gap: 6px; min-width: 0;
  padding: 4px 10px; border: 0; background: transparent; font: inherit;
  font-size: var(--pp-fs-mini); line-height: var(--pp-lh-text); color: var(--pp-text-2);
  cursor: pointer; white-space: nowrap; }
.ki-anb-btn + .ki-anb-btn { border-left: 1px solid var(--pp-line); }
.ki-anb-btn:hover { background: var(--pp-accent-tint); color: var(--pp-text); }
.ki-anb-btn.on { color: var(--pp-text); font-weight: 600;
  box-shadow: inset 0 -3px 0 0 var(--pp-accent); }
.ki-anb-btn.aus { color: var(--pp-text-3); }
.ki-anb-btn.aus:hover { color: var(--pp-text-2); }
.ki-anb-btn:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: -2px; }
/* Die Freianfragen im PrepP-Knopf — mono wie der Zähler rechts, damit die
   Zahl als Zahl gelesen wird. */
.ki-anb-info { font-family: var(--pp-mono); font-weight: 400; color: var(--pp-text-3); }
.ki-anb-btn.on .ki-anb-info { color: var(--pp-text-2); }
/* Auf dem Telefon füllt das Segment die Zeile und teilt sie gleichmäßig —
   Trefferfläche je Knopf 44 px hoch (R3-Regel). */
@media (max-width: 860px), (pointer: coarse) {
  .ki-anbieter { display: flex; width: 100%; }
  .ki-anb-btn { flex: 1 1 0; justify-content: center; min-height: 44px; }
}

/* ---------- Was aus der vollen Leiste fiel (S1) ---------- */
/* Absolut unter der Leiste, wie der Historie-Aufklapper: Ein Hinweis im
   Fluss ließe die Kopfzeile springen, und die Kopfzeile ist der Ort, an
   dem gerade etwas verschwunden ist. Dieselbe Stufe wie die Historie —
   über den Pop-ups (die Kopfzeile trägt dafür kf-pop-auf). */
.kf-meldung {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 135;
  display: flex; align-items: center; gap: var(--pp-sp-2);
  max-width: min(420px, 92vw); box-sizing: border-box;
  padding: 6px var(--pp-sp-2) 6px var(--pp-sp-3);
  background: var(--pp-bg-2); color: var(--pp-text-2);
  border: 1px solid var(--pp-line-2); border-radius: 8px;
  font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp);
  box-shadow: var(--pp-lift, 0 14px 36px rgba(0, 0, 0, .28));
}
.kf-meldung-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kf-meldung-x {
  flex: none; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 4px;
  background: transparent; color: var(--pp-text-3);
  font: inherit; font-size: var(--pp-fs-text); line-height: var(--pp-lh-eng); cursor: pointer;
}
.kf-meldung-x:hover { background: var(--pp-surface-2); color: var(--pp-text); }

/* ---------- Vollbild ---------- */
/* Der Chat nimmt die Seite ein: keine Portal-Maximalbreite, Höhe bis zum
   Fensterrand (wie die frühere .prof-grid-Regel, nur ohne Spalten). */
@media (min-width: 861px) {
  .pp-page.kf-voll { max-width: none; }
  .kf-voll .prof-chat { height: calc(100vh - 130px); max-height: none; }
}
/* Der Vollbild-Kopf trägt seit dem 06.09.2026 denselben Knopfsatz wie
   jedes andere Fenster: − ⛶ ✕, oben rechts, in dieser Reihenfolge — und
   zwar in der DOM-Reihenfolge, damit Tastaturfolge und Bild sich decken
   (kein `order`; das frühere `.kf-voll-x { order: -1 }` zog den einen
   Knopf nach links und war genau diese Ausnahme). Die Maße kommen aus
   demselben Satz wie beim Pop-up; die Regel steht getrennt, weil der
   Vollbild-Kopf `.ki-kopf` heißt und nicht `.ppf-kopf`. */
.kf-voll-chat > .ki-kopf .ppf-dock,
.kf-voll-chat > .ki-kopf > .ppf-x {
  display: inline-flex; align-items: center; justify-content: center;
  box-sizing: border-box; width: 24px; height: 24px;
  padding: 0; border-radius: 6px; line-height: var(--pp-lh-eng);
}
.kf-voll-chat > .ki-kopf > .kf-minkn { font-size: var(--pp-fs-gross); }
.kf-voll-chat > .ki-kopf > .kf-vollkn { font-size: var(--pp-fs-klein); }
.kf-voll-chat > .ki-kopf > .ppf-x { font-size: var(--pp-fs-gross); }
/* Rot, weil es SCHLIESST — dieselbe Rechnung wie beim Pop-up (S1). */
.kf-voll-chat > .ki-kopf > .ppf-x { color: var(--pp-err); }
.kf-voll-chat > .ki-kopf > .ppf-x:hover,
.kf-voll-chat > .ki-kopf > .ppf-x:focus-visible {
  color: var(--pp-err); background: var(--pp-surface-2);
}
.kf-voll .prof-chat .ki-kopf { cursor: move; }
.kf-voll .prof-chat .ki-kopf button, .kf-voll .prof-chat .ki-kopf input { cursor: pointer; }
.kf-anker {
  font-size: var(--pp-fs-mini); color: var(--pp-text-2); max-width: 40%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* WF5 (web1014 D1-03, Jonas F11): Zwischen 861 und 1250 px bekommt die
   Leiste die zweite Zeile der Kopfzeile (Umbruch und Höhe in
   css/prepp.css, dort auch die Begründung). Die Reiter bleiben in der
   Maus-Gestalt (schrumpfen bis 64 px); der Aufklapper hängt weiter an der
   Leiste (`position: absolute`), also unter der zweiten Zeile. */
@media (min-width: 861px) and (max-width: 1250px) and (pointer: fine), (min-width: 1201px) and (max-width: 1250px) {
  .pp-top:not(.pp-top-zeile2) > .kf-leiste { flex-basis: 100%; order: 5; }
}

/* ---------- Mobil ---------- */
/* Die .pp-top bricht unter 861 px ohnehin um (prepp.css); die Leiste
   bekommt dort die volle Zeile. Pop-ups gibt es auf dem Telefon NICHT —
   jedes Öffnen ist ein Vollbild-Wechsel (kfOeffnen; in WebKit bei 390 px
   gemessen: ein 374×440-Fenster, das kein Daumen verschieben kann, weil
   die Griffe nur auf die Maus hören). Entschieden mit Stufe 3. */
@media (max-width: 860px), (pointer: coarse) and (max-width: 1200px) {
  .kf-leiste { flex-basis: 100%; order: 5; }
  .kf-hist { position: fixed; left: 8px; right: 8px; top: 60px; width: auto; }
  /* Die Reihe SCROLLT statt zu schrumpfen: Am Desktop dürfen Tabs bis auf
     64 px schrumpfen (Chrome-Streifen), auf 345 px Leistenbreite wären
     vier Tabs damit vier „Neu…" ohne einen lesbaren Titel (gemessen).
     Ein Tab behält hier seine Textbreite (bis 170 px), der aktive wird
     in die Sicht gescrollt (kfLeisteBinden). */
  .kf-tab { flex: 0 0 auto; min-width: 0; max-width: 170px; }
  /* ---- Trefferflächen der Leiste auf dem Finger (Nacharbeit S3 #18,
     17.09.2026; WebKit-Abnahme B5): Reiter und „Chat erstellen" 30 px
     hoch, ▾ 28 × 28, das × im Reiter 18 × 18 — die R3-Regel (css/prepp.css)
     erfasste die Leiste nie. Gewachsen ist die TREFFERFLÄCHE, nicht der
     Kasten: Muster Erledigt-Kästchen des Lernplans (C48), ein unsichtbarer
     Vorsatz. Drei Dinge daran sind gemessen, nicht geschmackvoll:
       · Der Reiterstreifen scrollt waagerecht und SCHNEIDET damit auch
         senkrecht ab — ein Vorsatz, der über ihn hinausragt, wäre nicht
         antippbar. Er wird deshalb 46 px hoch und gibt die 16 px über
         negative Ränder zurück: Die Leiste bleibt 34 px hoch, die
         Reiter 30. 46 und nicht 44, weil die Leiste auf einem
         Bruchteil-Pixel sitzt: Mit 44 maß WebKit 42 px wirksam (der
         Rand fiel je einmal auf den Nachbarpixel). Darüber und
         darunter liegen je ≥ 12 px leere Kopfzeile (gemessen) — die
         8 px treffen dort nichts. Dasselbe beim ▾ (28 + 2 × 9).
       · Das × bekommt `position: relative`: Der Vorsatz des Reiters ist
         selbst positioniert und läge sonst über ihm.
       · Das × darf nicht über den Reiter hinausragen (der Nachbar steht
         3 px daneben, SPÄTER im Markup, und gewönne dort) — der Reiter
         polstert rechts deshalb 13 px statt 4, genau so viel, wie der
         44er Vorsatz des × über seine 18 px hinaus braucht. */
  .kf-tabs { height: 46px; margin: -8px 0; align-items: center; }
  .kf-tab, .kf-tabneu { height: 30px; position: relative; }
  .kf-tab::before, .kf-tabneu::before { content: ""; position: absolute; inset: -8px 0; }
  /* Der Vorsatz des × wächst NUR nach rechts, nie über den Titel
     (WebKit-Abnahme 27.09.2026: auf dem iPad quer traf ein Tap MITTEN auf
     den kurzen Reiter „Item 2" das × — der symmetrische Vorsatz ragte
     13 px in den Titel, und der unbenutzte Tutor, der im Arbeitsmodus in
     seinen Reiter geht, wurde beim Zurückholen geschlossen statt
     geöffnet). 18 + 26 = 44 px breit, dafür polstert der Reiter rechts
     28 px statt 13 (26 auf das 4-px-Raster gehoben, verify-skala 4b) —
     der Vorsatz endet 2 px vor der Reiterkante und berührt den Nachbarn
     nicht. */
  .kf-tab { padding-right: 28px; }
  /* WO16 (A1-12, 14.10.2026): Bei KURZEM Titel („Home", „AI chat 2")
     nahm die ×-Fläche 37–50 % des Reiters ein, bei „Home" begann sie an
     der Reitermitte — ein Tipp mitten auf den Reiter schloss den Chat.
     Der Titel hält deshalb mindestens 64 px (vier Rasterschritte) links
     vom ×: Die 44-px-Fläche bleibt bei jedem Reiter unter einem Drittel
     seiner Breite und die Mitte liegt immer auf dem Titel. */
  .kf-tab .kf-tab-t { min-width: 64px; }
  .kf-tab-x { position: relative; }
  .kf-tab-x::before { content: ""; position: absolute; inset: -13px -26px -13px 0; }
  .kf-hist-kn { position: relative; margin-right: 12px; }
  .kf-hist-kn::before { content: ""; position: absolute; inset: -9px; }
  /* Der Kopf des Vollbilds (⋯ − ⛶ ✕, je 24 × 24 bei 8 px Abstand): Vier
     44er Vorsätze um Mitten im Abstand von 32 px überlappten sich um je
     12 px — und weil der rechte Nachbar später im Markup steht, träfe
     ein Finger knapp rechts neben „−" das ⛶, knapp neben ⛶ das Schließen.
     Deshalb erst der Abstand, dann die Fläche: 12 px mehr Rand machen die
     Mitten 44 px voneinander, und die Vorsätze stoßen auf Kante. */
  .kf-voll-chat > .ki-kopf > .kf-mehrkn,
  .kf-voll-chat > .ki-kopf > .ppf-dock,
  .kf-voll-chat > .ki-kopf > .ppf-x { position: relative; margin-left: 12px; }
  /* Das ⋯ steht zuerst: Links neben ihm liegt der 44 px hohe Anker-Knopf,
     dem reichen 8 + 2 px Abstand für seine 10 px Vorsatz. Jeder Pixel hier
     geht dem Titel der Krume ab (gemessen: 109 → 61 px mit 12 px). */
  .kf-voll-chat > .ki-kopf > .kf-mehrkn { margin-left: 2px; }
  .kf-voll-chat > .ki-kopf > .kf-mehrkn::before,
  .kf-voll-chat > .ki-kopf > .ppf-dock::before,
  .kf-voll-chat > .ki-kopf > .ppf-x::before { content: ""; position: absolute; inset: -10px; }
  /* Die Vollbild-Höhe kommt gemessen aus kfVollHoeheNachziehen (app.js);
     der Rückfall ist die alte Regel aus prepp.css. */
  .kf-voll .prof-chat { height: var(--kf-voll-h, calc(100vh - 140px)); max-height: none; min-height: 0; }
}

/* ---- Die Weiche (08.09.2026, docs/KI-WEICHE.md) ----
   Die Karte „Zugeordnet: …" mit dem Weg in den Fach-Dialog und die Notiz
   im umgeleiteten Aufgaben-Chat. Sie liegt im Verlauf wie eine Antwort,
   ist aber keine: eigener Rahmen in der Akzent-Tönung, kein Sprechblasen-
   Grund — damit sie nicht wie eine KI-Aussage gelesen wird. Nur
   --pp-Tokens (der Wirt #kf-wirt erklärt sie selbst, Q1). */
.kf-weiche { border: 1px solid var(--pp-accent-tint); background: var(--pp-surface-2);
  border-radius: 8px; padding: var(--pp-sp-3, 10px) var(--pp-sp-4, 12px); }
.kf-weiche-kopf { font-weight: 600; font-size: var(--pp-fs-klein); color: var(--pp-accent-2); margin-bottom: 4px; }
.kf-weiche-text { font-size: var(--pp-fs-klein); line-height: var(--pp-lh-text, 1.45); }
.kf-weiche-akt { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.kf-weiche-notiz { border-style: dashed; }

/* ---- Büroklammer und Kamera auf dem Finger (Politur 03.10.2026) ----
   Ihr unsichtbarer Vorsatz (css/prepp.css, ns0929) wächst nur SENKRECHT,
   weil die beiden nebeneinander stehen — wirksam blieben sie deshalb
   34 px breit (WebKit, 390 × 844, Flächen-Chat: 📎 34 × 46, Kamera
   34 × 44). Die Breite kommt hier über den Kasten selbst, nicht über
   einen zweiten Vorsatz: Zwei Vorsätze nebeneinander überlappten, und
   der spätere im Markup gewönne. Das Symbol behält seine Größe. Mit der
   Maus bleibt alles, wie es ist. */
@media (hover: none) {
  .ki-box-links :is(.ki-klammer, .ki-kamera) { width: 44px; }
}

/* Codeblock und Zitat in einer KI-Antwort (QA1013 W2-02, 14.10.2026):
   mdLite setzt sie mit den Klassen der Notizen (.nz-code, .nz-zitat in
   css/notizen.css) — ein Aussehen für beide Orte. Hier nur, was die Blase
   dazu braucht: Der Block rollt in der Blase waagerecht, statt sie über
   ihre 96 % hinaus aufzuschieben, und er erbt NICHT das overflow-wrap
   der Blase (eine Codezeile bricht nie mitten im Bezeichner um). */
.ki-msg .nz-code { max-width: 100%; overflow-x: auto; overflow-wrap: normal; }
/* Kurze Inline-Formel + Satzzeichen bleiben zusammen (W2-09, mdLite). */
.md-nobr { white-space: nowrap; }

/* Nach einem Abriss (QA1013 W2-03): die schon gelesene Teilantwort steht
   über der Wartezeile — gestrichelt, weil sie (noch) nicht die Antwort ist;
   „Nicht warten" rückt in der Wartezeile nach rechts. */
.ki-msg.ki-abriss-teil { border-style: dashed; }
.ki-fremd.ki-abriss .ki-abriss-weg { margin-left: auto; }

/* „↺ Original" / „↻ aufrichten" am Bild-Chip (QA1013 W2-07): ein Angebot,
   kein Löschen — beim Überfahren in der Akzentfarbe, nicht im Rot des ✕
   (.ki-anhang-chip button:hover in prepp.css). */
.ki-anhang-chip .ki-anhang-orig { color: var(--pp-accent-2); }
.ki-anhang-chip .ki-anhang-orig:hover { color: var(--pp-accent-2); text-decoration: underline; }

