
/* === Board = Kachel-Raster. Genau EIN Board pro Anzeige. Jede Panele belegt >=1
      Kachel und hat drei Größen: Kachel (1×1) → Panele (3 breit × 3 hoch) → Vollbild. === */
:root{ --tile:96px; --tile-gap:6px;   /* 96 = 4× das 24px-Punktraster des Board-Hintergrunds */
  /* Fußzeilen-Maße: Desktop kompakt (Maus). Auf dem Handy größer (Finger) — siehe @media unten. */
  --foot-h:30px; --foot-btn:30px; --foot-fs:12px; --foot-gap:5px; --foot-pad:8px;
  --pf-tile:26px;   /* Kachel rechts IN der Eingabebox (App/Senden) */
  /* Ruhezustand der Bedienleiste: leer ist schmaler als voll (2026-08-01). Kopf- und Fußzeile sind
     im Ruhezustand nur die Klickfläche, aus der auf Wunsch die Eingabebox wird — sie brauchen
     deshalb nicht die Höhe der Box, die sie noch nicht tragen. */
  --foot-rest:22px;
  /* §30.21 — im Ruhezustand steht unten GAR KEINE Leiste mehr. Was bleibt, ist ein Streifen ohne
     Inhalt: die Fläche, über die man sie holt (`LEER_SEL` trifft den Detailbereich selbst, und ein
     Klick darauf ruft `barInAuf`). Er ist kein Ersatz für die Leiste, sondern ihr Zugang — ohne ihn
     endet der Inhalt bündig am Rahmen und ein Panel mit langer Liste hätte keinen antippbaren
     Rest mehr. */
  --foot-tap:18px; }
/* `--foot-res` ist das EINE Maß, aus dem sich Leistenhöhe UND der im Detailbereich freigehaltene
   Platz ableiten. Es kippt an genau einer Stelle — offene Eingabe (`.reco-open`) ⇒ Boxhöhe, sonst
   Ruhehöhe —, damit oben (Kopf-Slot der Liste) und unten (Fußzeile) dasselbe gilt und der
   reservierte Platz nie größer ist als die Leiste, die dort steht. */
:root{ --foot-res:var(--foot-h); }
/* Voll ist die Leiste in genau zwei Zuständen: offene Eingabebox (`.reco-open`) und offene
   Lauf-Steuerung (`.runctl-open` — ihre Schalter sind `--foot-btn` groß und stünden in einer
   Ruhe-Leiste über). Sonst trägt sie nur den Chip und ist entsprechend niedriger. */
.panel:not(.reco-open):not(.runctl-open){ --foot-res:var(--foot-rest); }
/* §30.21 — DIE RUHENDE LEISTE AM PANELBODEN IST ENTFALLEN (2026-08-01).
   Sie stand an jeder Panele und sagte im Ruhezustand nur den Namen des Agenten — ein fester
   Streifen für eine Auskunft, die daneben ohnehin in jeder Lauf-Zeile steht (§30.20). Die Leiste
   selbst bleibt: sie hat weiterhin ZWEI Plätze, an denen sie sichtbar ruht — den Kopf einer
   Vorschlagsliste (`bar-top`, §30.13) und den Strom, wo man hingeklickt hat (`bar-in`, §30.19) —
   und sie kommt unten zurück, sobald sie etwas zu zeigen hat: offene Eingabebox (`reco-open`,
   z.B. in einer Panele ohne Ausgabe, unter der `barInAuf` keinen Platz findet) oder offene
   Lauf-Steuerung (`runctl-open`).
   Zwei Dinge müssen dabei GEMEINSAM kippen, sonst zieht die Lücke nur um: die Leiste verschwindet
   UND der für sie freigehaltene Platz schrumpft auf den Zugangsstreifen (`--foot-tap`).
   `!important` steht hier bewusst und genau einmal: die Leiste wird an vier Stellen eingeblendet
   (Panele-/Custom-/Vollbildgröße, mobil zusätzlich mit `!important`) — eine Bedingung an jede
   dieser Regeln zu hängen hieße, dieselbe Entscheidung viermal zu pflegen. */
.panel:not(.bar-top):not(.bar-in):not(.reco-open):not(.runctl-open):not(.corner-open) .pfoot{ display:none !important; }
/* §30.28 — DER ZUGANGSSTREIFEN GEHÖRT DER PANELE, NICHT DEM SCROLL-INHALT (2026-08-01).
   §30.21 hielt ihn als Polster am ENDE des Inhalts frei (`--foot-res`) — damit rutschte er mit dem
   Inhalt weg: eine randvolle Liste (Journal in der Home-Panele, §30.28) ließ keine antippbare
   Stelle übrig, und mit der entfallenen Leiste war die Panele dann ohne Eingabe — am Handy, wo
   sie den Schirm füllt und kein Panel-Chrome trägt, ohne jeden Ausweg. Gemessen: 0 Treffer bei
   348 px und bei 900 px Panelhöhe, obwohl der Streifen rechnerisch da war.
   Jetzt hält ihn die PANELE frei (`padding-bottom`), unterhalb des scrollenden Bereichs: er ist
   damit immer an der unteren Kante, egal wie lang der Inhalt ist. Der Detailbereich reserviert
   dafür nichts mehr (`--foot-res:0`), sonst stünde die Lücke zweimal.
   `.pinned` bleibt außen vor: Board-Möbel (Logo/KPI/App-Icons) sind keine Fenster, ein Streifen
   unter ihrem Icon wäre nur eine kleinere Kachel. */
.panel:not(.bar-top):not(.bar-in):not(.reco-open):not(.runctl-open):not(.corner-open){ --foot-res:0px; }
.panel:not(.pinned):not(.bar-top):not(.bar-in):not(.reco-open):not(.runctl-open):not(.corner-open){
  padding-bottom:var(--foot-tap); }
/* 2026-08-03 — App-Panele braucht den Zugangsstreifen nicht: bis 2026-09-01 hatte sie mit dem
   runden Knopf (`.app-nav`) ihren eigenen, sichtbaren Einstieg zur Eingabe; seit dessen Ausbau
   liegt die App nackt in der Panele und ein iframe schluckt ohnehin jeden Klick, den der Streifen
   nahe der Kante aufnehmen würde. Ohne diese Ausnahme reservierte `.panel-body` 18px, die der Knopf im Ruhezustand NICHT
   hatte, sobald die Eingabe offen ist (dort gilt `:not(.reco-open)` nicht mehr, das Polster fällt
   weg) — Knopf und Eingabefläche lagen dadurch 18px versetzt zueinander, statt auf gleicher Höhe
   (gemessen: Knopf bottom=866, Eingabe bottom=884 bei 900px Panelhöhe). */
.panel.app-panel:not(.pinned):not(.bar-top):not(.bar-in):not(.reco-open):not(.runctl-open){
  padding-bottom:0; }
/* Ein Bereich (Journal · Kontakte · Lauf · Kontakt-Profil, `.area-out` in `_showArea`) füllt seine
   Panele mit einer eigenen scrollenden Liste ohne Fußzeilen-Funktion an dieser Stelle — der
   Zugangsstreifen hätte hier nichts zu öffnen und blieb als toter weißer Rand unter dem Inhalt
   stehen (gemessen: ~18 px Leerfläche, unabhängig vom Scrollstand). */
.panel:has(.area-out){ padding-bottom:0 !important; }
/* Avatar-Bild/-Video (Toggle-Mini-Panele `.av-vid`, laina/bbkif `ctl:avatar` per `#laina-avatar`/
   `.live-avatar`) füllt seine Panele ebenso randvoll — derselbe Fall: der Zugangsstreifen hat hier
   nichts zu öffnen und blieb als weiße Zeile unter dem Bild stehen. */
.panel:has(.av-vid), .panel:has(#laina-avatar), .panel:has(.live-avatar){ padding-bottom:0 !important; }
/* Board-Hintergrund: sehr dezentes Punkt-Raster (Bullet-Journal) + angedeutetes Wasserzeichen (Logo + Agentname). */
#board{ position:relative;
  background-image:
    radial-gradient(var(--karo,rgba(15,23,42,.14)) 1.5px, transparent 1.5px);
  background-size:24px 24px; }
#board.board-dark{ --karo:rgba(255,255,255,.14); }
/* Wasserzeichen liegt hinter dem (transparenten) Scroll-Bereich; Kacheln sind deckend und überdecken es. */
.board-wm{ position:absolute; inset:0; z-index:0; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:16px; pointer-events:none; overflow:hidden; }
.board-wm img{ width:min(34vmin,300px); max-height:34vmin; object-fit:contain; opacity:.12; }
#board-scroll{ position:relative; z-index:1; flex:1; overflow-y:auto; overflow-x:auto; -webkit-overflow-scrolling:touch; }
@media (max-width:640px){ #board-scroll{ overflow-x:hidden; } }   /* mobil: Listen-Layout, kein Seitwärts-Scroll */
/* §32 — DIE LUPE IST ENTFALLEN (2026-08-01): die −/+-Knöpfe unten rechts (`#board-zoom`), ihre
   Prozent-Anzeige und der Faktor `--z` an `.panel-body`. Sie war ein Bedienelement, das zu keiner
   Panele gehörte (dieselbe Klasse wie die mobile Aktionsleiste, §28) und ein zweites Maßsystem im
   Layout: jede Rechnung über Kachelgröße, Auto-Höhe und Fußzeilen-Lage musste den Faktor
   herausrechnen. Größer und kleiner macht der Browser selbst (Strg/⌘ +/−) — für die ganze Seite,
   ohne dass der Code davon wissen muss. */
#panel-grid{
  position:relative;   /* Bezugsrahmen der frei platzierten Panele (.panel.positioned, absolut) */
  display:grid;
  /* Quadratische Kacheln: feste Kachelgröße (Breite = Höhe = --tile); so viele Spalten wie passen.
     1×1 = Quadrat, sz-panel = 2×1 Kacheln (breiter als hoch). Anzahl/Reihe hängt an der Screenbreite (auto-fill). */
  grid-template-columns:repeat(auto-fill, var(--tile));
  grid-auto-rows:var(--tile);
  grid-auto-flow:row;
  gap:var(--tile-gap);
  /* §33 — DIE BODENFREIHEIT IST KEIN FESTER STREIFEN MEHR (2026-08-01). Hier standen unten drei
     Kachelhöhen (`calc(var(--tile) * 3)` = 336 px) „damit die letzte Panele per Ziehgriff größer
     gezogen werden kann" — zusammen mit derselben Reserve in `updateExtent` (`h + rowH*3`) war das
     Board damit IMMER rund 350 px höher als sein Inhalt: eine Panele von halber Schirmhöhe genügte,
     und das Board zeigte eine Scrollbar für leere Fläche. Wie viel unten frei bleibt, entscheidet
     jetzt `updateExtent` — so viel wie möglich, ohne selbst eine Scrollbar zu erzeugen. */
  padding:var(--tile-gap);
  /* Verankert oben links: das Raster wächst nach rechts/unten. Zentrierung würde beim
     Verbreitern des Fensters alle Kacheln/Panele nach rechts wandern lassen. */
  justify-content:start;
}
/* Am Desktop ist die Kachel 112 px — genau das schreibt `fitTiles` gleich nach dem Laden als
   Inline-Style (`var t=112`, nur die SPALTENZAHL hängt am Platz). Ohne diese Zeile ist das erste
   Bild mit `--tile` (96 px) gerastert und rutscht danach um 16 px je Reihe zurecht: gemessen war
   der Kopfzeilen-Streifen erst 198, dann 230 px hoch, und alles darunter sprang mit. `--tile`
   selbst bleibt bei 96 px — daran hängen Maße INNERHALB der Kacheln (z.B. `.hs-tile`), die
   `fitTiles` nicht anfasst; hier geht es nur um die Rasterspuren. `#panel-grid.lt-grid` (Launcher,
   130 px) wiegt eine Klasse mehr und behält seine eigenen Spuren. */
@media (min-width:641px){
  #panel-grid{ grid-template-columns:repeat(auto-fill,112px); grid-auto-rows:112px; }
}
.panel{
  grid-column:span 1; grid-row:span 1;   /* Standard: 1 Kachel */
  display:flex; flex-direction:column;
  background:#fff; border-radius:10px;
  border:1px solid #94a3b8;                 /* alle Panele: dunklerer Rahmen */
  box-shadow:0 1px 3px rgba(0,0,0,.07);
  overflow:hidden; position:relative; min-height:0;
}
.panel.sz-panel{ grid-column:span 2; grid-row:span 3; }   /* Panele: 2 breit × 3 hoch (höher als breit) */
.panel.sz-panel.wide{ grid-column:1 / -1; grid-row:span 7; }   /* volle Rasterbreite + Tabellenhöhe (afsde-Listen); nur im Panele-Zustand → min/max bleiben */
/* Halbe Rasterbreite (zwei Listen nebeneinander, z.B. Bestellungen + Fahrten): Span je nach
   Viewport-Spaltenzahl (auto-fill, --tile 96 + gap 6 ≈ 102px/Spalte); schmaler = untereinander. */
.panel.sz-panel.half{ grid-column:1 / -1; grid-row:span 7; }
@media (min-width:1280px){ .panel.sz-panel.half{ grid-column:span 6; } }
@media (min-width:1480px){ .panel.sz-panel.half{ grid-column:span 7; } }
@media (min-width:1700px){ .panel.sz-panel.half{ grid-column:span 8; } }
@media (min-width:1900px){ .panel.sz-panel.half{ grid-column:span 9; } }
.panel.afsde-hidden{ display:none !important; }   /* per KPI-Kachel aus-/eingeblendet (Toggle) */
/* Detail-Panele (`wide tall` aus backbone.bbOpen: E-Mail/PDF/Objekt) sind so hoch wie die Liste,
   aus der sie geöffnet wurden — ihr Detailbereich reicht bis ans untere Ende der Panele, wo die
   Fußzeile anfängt. `.tall`/`.afsde-tall` setzten hier `grid-row:span 3` und ZOGEN die volle
   Listenhöhe aus `.wide` (span 7) wieder auf 348px herunter: der Inhalt brach nach wenigen Zeilen
   ab, darunter lag leere Boardfläche. Mobil galt für dieselben Panele längst span 7 (Media-Query).
   `.tall` heißt jetzt, was es sagt: HOCH (span 7 = dieselbe Höhe wie eine Liste). Es die Höhe
   allein aus der Breitenklasse ziehen zu lassen, reichte nicht — das Zeilen-Detail (`stdRowOpen`)
   trägt nur `.tall` und fiel damit auf die Grundhöhe `.sz-panel` (span 3 = 348 px) zurück:
   gemessen am afsde-Board 616 px Inhalt in 346 px Fläche, neben einer 820 px hohen Liste. */
.panel.sz-panel.afsde-tall, .panel.sz-panel.tall{ grid-row:span 7; }
/* Kopfzeilen-Panele (board_config.head_tiles): ALLE Board-Kacheln horizontal in EINER Panele,
   fest in Reihe 1 (volle Breite → nichts rutscht daneben). Objekt-Kacheln toggeln ihre Panele. */
.panel.head-strip{ grid-column:1 / -1; grid-row:1; }
.head-strip .hs-tiles{ display:flex; flex-wrap:wrap; gap:var(--tile-gap); align-content:flex-start;
  height:100%; box-sizing:border-box; padding:8px; overflow:auto; }
/* Überschrift des Streifens (board_config.head_title, z.B. „Logistik Control Tower"): eine Zeile
   ÜBER Logo und Kacheln. Sie kostet Höhe, deshalb hängen zwei Dinge an derselben Klasse:
   der Streifen bekommt eine zweite Rasterreihe, und die Kachelzeile gibt ihr `height:100%` auf —
   sonst nähme sie erneut die ganze Panelhöhe und schöbe Titel bzw. Chat-Zeile hinaus. */
.panel.head-strip.has-title{ grid-row:1 / span 2; }
.head-strip.has-title .hs-tiles{ height:auto; }
.head-strip .hs-title{ padding:2px 8px 0; font-weight:700; font-size:1.05rem; color:#0f172a;
  line-height:1.2; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Kacheln mit fester Höhe (1 Kachelzeile passt exakt in die 1-Reihen-Leiste) und Umbruch:
   sie gliedern sich in die Panelfläche ein — zieht man die Leiste schmaler/höher (hochkant),
   brechen die Kacheln um und stehen untereinander. */
.head-strip .hs-tile{ flex:0 0 auto; min-width:calc(var(--tile) - 16px); max-width:170px;
  height:calc(var(--tile) - 16px); padding:4px 12px; box-sizing:border-box;
  border:1px solid #e5e7eb; border-radius:8px; background:#fff; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:2px; cursor:pointer; text-align:center; }
.head-strip .hs-tile:hover{ background:#f8fafc; }
/* Sichtbarkeits-Status der zugehörigen Panele: eingeblendet = hervorgehoben, ausgeblendet = gedimmt. */
.head-strip .hs-tile.on{ border-color:#2563eb66; background:#eff4ff; }
.head-strip .hs-tile.on .hs-val{ color:#2563eb; }
.head-strip .hs-tile.off{ background:#eef2f6; border-color:transparent; }   /* Panele ausgeblendet → Kachel grau, Text bleibt kräftig lesbar */
.head-strip .hs-tile.off .hs-val{ color:#334155; }
/* Datenkachel (board_config.kpis): Zahl in ihrer Akzentfarbe, ohne den blauen „Panele sichtbar"-
   Rahmen — sie sagt nichts über Sichtbarkeit, sondern zählt. Aktiver Filter = kräftiger Rahmen. */
.head-strip .hs-tile.hs-kpi{ border-color:#e5e7eb; background:#fff; }
.head-strip .hs-tile.hs-kpi.filtered{ border-color:#0f172a55; background:#f1f5f9; box-shadow:inset 0 0 0 1px #0f172a22; }
.head-strip .hs-chat{ margin-top:8px; }   /* Chat-Eingabebox unter der Kachel-Zeile */
.head-strip .hs-chat-in{ width:100%; box-sizing:border-box; border:1px solid #e5e7eb; border-radius:10px;
  padding:9px 12px; font:inherit; font-size:.9rem; color:#0f172a; background:#fff; outline:none; }
.head-strip .hs-chat-in:focus{ border-color:#94a3b8; }
.head-strip .hs-chat-in::placeholder{ color:#94a3b8; }
.head-strip .hs-val{ font-weight:700; font-size:1.1rem; color:#0f172a; line-height:1.1; }
.head-strip .hs-label{ font-size:.68rem; color:#64748b; max-width:150px; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.head-strip .hs-logo img{ max-width:64px; max-height:56px; object-fit:contain; }
.panel.head-hidden{ display:none !important; }   /* per Kopfzeilen-Kachel ausgeblendet (Toggle) */

/* === afsde-Panele: Titel (mit Suche/Excel) + Tabelle/Body, Kachel = Kennzahl. Die Fußzeile
   (Größe/Schließen/Aktionsleiste) liefert einheitlich die Board-Engine als `.panel-foot`. === */
.afsde-wrap{ display:flex; flex-direction:column; height:100%; box-sizing:border-box;
  font-family:system-ui,-apple-system,sans-serif; color:#0f172a; }
/* §41 — DIE OBERE RECHTE ECKE GEHÖRT DEM ✕ (2026-08-25). Die Aktionen dieser Titelzeile stehen
   im FLUSS (`_ui.head` schiebt sie mit einem Spacer ans rechte Ende), nicht absolut — sie lagen
   deshalb unter dem ✕, gemeldet an den b_logistik-Panelen („Wareneingang", Knopf „Auffrischen",
   32×32). Umhängen in `.p-acts` scheidet aus: `data-reload-skill` sucht sein Ziel mit
   `rb.closest('.panel-body')` (board.js:3085) und fände es außerhalb des Körpers nicht mehr
   (derselbe Grund steht in `spaces/b_logistik/panels/liste.html:38`). Also hält die Zeile den
   Platz frei — mit demselben Maß, aus dem die Leiste ihre Position nimmt.
   Grenze: eine Panele, die ZUSÄTZLICH `data-p-act`-Knöpfe in die Leiste hängt, bräuchte hier
   mehr; heute nutzt keine beides zugleich. */
.afsde-head{ flex:0 0 auto; padding:4px 14px; font-weight:700; font-size:1.02rem; color:#0f172a; }
/* Zwei Klassen tief, und das mit Absicht: die Spaces liefern denselben Selektor in einem eigenen
   `<style>`-Block mit (`spaces/b_logistik/skills/_ui.py:214`, `spaces/aryzta/skills/afsde_ui.py`),
   und der steht später im Dokument — bei gleicher Spezifität gewinnt er. Nur IN einer Panele gibt
   es ein ✕, außerhalb (App-Kachel im Rahmen) soll die Zeile ihren schmalen Rand behalten. */
.panel .afsde-head{ padding-right:max(14px, var(--p-corner, 14px)); }
.afsde-head .afsde-count{ margin-left:8px; font-weight:500; font-size:.85rem; color:#94a3b8; }
.afsde-head .afsde-xls{ border:0; background:transparent; }
.afsde-head .afsde-xls:hover{ background:#f1f5f9; }
/* `overflow:visible` statt `auto`: seit der Panel-Stream-Vereinheitlichung erzwingt
   `.panel-body.ps > *{height:auto!important}` (§21/§38) ohnehin, dass `.afsde-wrap`/`.afsde-body`
   nie kleiner sind als ihr Inhalt — sie überlaufen nie, scrollen tut ausschließlich `.panel-body`
   selbst. Mit `overflow:auto` blieb `.afsde-body` trotzdem ein eigener Scroll-Container (per
   Spezifikation, unabhängig davon ob er je überläuft) und kappte damit die
   `position:sticky`-Bezugsbox der Tabellenköpfe VOR `.panel-body` — der Spaltenkopf blieb beim
   Scrollen des Panels nie stehen. */
.afsde-body{ flex:1 1 auto; min-height:0; overflow:visible; padding:4px 12px 8px; }
.afsde-kpi{ display:none; }
/* Kachel-Modus (1×1): nur die Kennzahl zeigen, klickbar → wieder aufziehen */
.panel:not(.sz-panel):not(.sz-full):not(.sz-custom) .afsde-head,
.panel:not(.sz-panel):not(.sz-full):not(.sz-custom) .afsde-body{ display:none; }
.panel:not(.sz-panel):not(.sz-full):not(.sz-custom) .afsde-kpi{
  display:flex; align-items:center; justify-content:center; height:100%; cursor:pointer; }
.panel.sz-full{                                           /* Vollbild */
  /* `!important` auf `position` allein: `.panel.positioned{position:absolute}` (weiter unten,
     gleiche Spezifität) gewann sonst bei jeder frei platzierten Panele (praktisch immer, §31) —
     sichtbar als Panele, die relativ zu `#panel-grid` bleibt statt zum Fenster, und dessen
     Restbreite/-höhe (Boardfläche kann größer sein als der Bildschirm) statt der echten
     Bildschirmgröße trägt. Ohne `!important` bräuchte es stattdessen eine spätere/spezifischere
     Regel — fragiler, weil jede künftige `.positioned`-Änderung dieselbe Reihenfolge neu träfe. */
  position:fixed !important; inset:0; z-index:1200;
  grid-column:auto; grid-row:auto; border-radius:0;
  box-shadow:0 0 0 100vmax rgba(15,23,42,.35);
}
/* Vollbild: randlos — aber MIT Fußzeile. Sie war hier bis 2026-07-31 ausgeblendet, und damit war
   das Vollbild die einzige Größe ohne Eingabe und ohne ⋮ (aus dem Vollbild führte nur ein
   unsichtbarer Ecken-Klick). Eine Panele trägt in JEDER aufgezogenen Größe dieselben drei Dinge:
   Kopf, Inhalt, Fußzeile. */
.panel.sz-full{ border:0 !important; }
.panel.sz-full.active{ border:0 !important; box-shadow:0 0 0 100vmax rgba(15,23,42,.35) !important; }
.board-maxed #board-scroll{ overflow:hidden; }
/* Rahmen aus (User-Einstellung): flache Kacheln ohne Schatten */
#board.noframe .panel{ box-shadow:none; border:1px solid #94a3b8; }
/* Aktives Panel (zuletzt angeklickt): etwas kräftigerer/dunklerer Rahmen */
/* Fokus/aktiv wird nicht mehr durch einen dunkleren Rahmen markiert (Nutzerwunsch) —
   .active bleibt als Logik-Klasse (Fokusziel) ohne eigene Optik. */
/* Kein `zoom` mehr am Detailbereich (§32, 2026-08-01) — mit der Lupe ist auch ihr Faktor `--z`
   entfallen; die Ausnahme für App-iframes (`zoom:1`) braucht es damit ebenfalls nicht mehr. */
.panel-body{ flex:1 1 auto; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch; position:relative; }
.panel-hash{ display:none; }   /* Hashcode oben links pauschal ausgeblendet */
/* Panel-Steuerung (oben rechts): Größe zyklen / schließen */
/* Die Steuer-Icon-Reihe `.panel-ctl` (min/max/close oben rechts) ist ENTFALLEN (2026-07-31):
   sie wurde von niemandem mehr erzeugt (der letzte Erzeuger, `spaces/aryzta/skills/afsde_ui.py`
   `controls()`, ist längst weg — nur sein Docstring erwähnt sie noch) und war der DRITTE Weg für
   Größe und Schließen neben Ecken-Hotspots und Fußzeile. Jetzt: `✕` im Kopf, `⋮` in der Fußzeile. */
/* Ziehgriff unten rechts: zieht die Panelgröße frei, rastet aufs Kachelraster (grid-span).
   (Diese Regeln standen im selben Block wie die entfallenen Ecken-Hotspots und waren beim
   Aufräumen am 2026-07-31 versehentlich mit verschwunden — ohne sie liegen die Griffe zwar im
   DOM, aber unpositioniert am Panelende: Vergrößern aus der Ecke ging nicht mehr.) */
/* 14×14 statt 28×28 (2026-07-31): die Fußzeile ist 30 px hoch, ein 28er Griff legte sich also über
   ihre GANZE Höhe bis in den Knopf unten rechts hinein. Jetzt bleibt er in der Ecke, und der Knopf
   daneben (rechts ab `--foot-pad`+4) hat wieder freie Fläche. */
.panel-resize{ position:absolute; right:1px; bottom:1px; width:14px; height:14px; z-index:4;
  cursor:nwse-resize; opacity:0; transition:opacity .15s; touch-action:none; }
.panel:hover .panel-resize, .panel.sz-panel .panel-resize, .panel.sz-custom .panel-resize,
.panel.sz-full .panel-resize{ opacity:1; }   /* im Vollbild sichtbar: Klick auf den Griff → zurück auf Panele */
/* ENTFALLEN (2026-07-31): die drei Kanten-Ziehstreifen an rechter/linker/unterer Panelkante
   (Breite bzw. Höhe). Die Größe wird ausschließlich über die Ecke unten rechts gezogen
   (.panel-resize) — ein Griff, eine Geste; die Kanten lagen unsichtbar 2 px ÜBER dem Panelrand
   und fingen dort Klicks der Nachbarpanele ab. */
/* Nicht ziehbar: Vollbild-Apps und die festen Kachel-Rollen. Die Schnellaktions-Panele
   (`.navbar`) stand hier bis 2026-07-31 mit drin — sie ist jetzt eine gewöhnliche Panele und
   wird gezogen wie jede andere. */
/* App-Panele NICHT mehr in dieser Liste (2026-08-03): in Panele-Größe (`appToPanel`) soll sich die
   Ecke ziehen lassen wie bei jeder anderen Inhalts-Panele; im Vollbild bleibt sie über die
   allgemeine `.panel.sz-full .panel-resize{opacity:1}`-Regel sichtbar (Klick → zurück auf Panele,
   dieselbe Geste wie überall sonst — bisher von dieser Zeile verdeckt). */
.panel.agent .panel-resize,
.panel.kpi .panel-resize, .panel.user .panel-resize, .panel.logo-panel .panel-resize{ display:none; }
.panel-move{ position:absolute; left:0; right:0; top:0; height:20px; z-index:2;
  cursor:grab; opacity:0; transition:opacity .15s; touch-action:none;
  border-radius:12px 12px 0 0; background:transparent; }
.panel-move:active{ cursor:grabbing; }
/* §38 — DER TITEL IST TEIL DER AUSGABE, KEINE EIGENE KOPFZEILE (Rücknahme von §34, 2026-08-0x).
   §34 hatte den Titel in ein eigenständiges Kopf-Band VOR `.panel-body` gelegt (kein Overlay, aber
   ein eigenes, statisches Element außerhalb des Stroms), damit er nicht mit der wandernden
   Bedienleiste verschwindet. Der Nutzer will genau das nicht: „keine extra Titelzeile — der Titel
   ist Teil des Ausgabebereichs". `.panel-title` liegt jetzt als ERSTER EINTRAG IN `.panel-body`
   (`chrome()` fügt sie dort ein, nicht am Panel) — sie scrollt mit dem restlichen Inhalt weg, wie
   jede andere Zeile des Stroms, genau wie zuvor schon `.ph-x` (§30.42). Inhalt weiterhin aus
   `headTitle(p)` (`headSync()`, dieselbe Quelle wie die Objekt-Kacheln). */
.panel-body > .panel-title{ flex:0 0 auto; display:flex; align-items:center; min-height:var(--pf-tile);
  padding:0 0 6px; font-size:13px; font-weight:600; color:#0f172a; }
.panel-body > .panel-title .ph-txt{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
#board.board-dark .panel-body > .panel-title{ color:#e8edf5; }
/* Kachel-Modus (1×1): dort ist ein Klick das Aufziehen, kein Platz für eine Titelzeile — dieselbe
   Ausnahme wie bei der Fußzeile. */
.panel:not(.sz-panel):not(.sz-full):not(.sz-custom) .panel-title{ display:none; }
/* 2026-08-03 — KEINE TITELZEILE MEHR, IN KEINER GRÖSSE (Rücknahme von §38 für ALLE Panele, nicht nur
   die Home-Fläche wie §30.37). Der Nutzer sah sie an jeder Vollbild-App als „Pfleiderer Gütersloh —
   Admin ⌄" über dem eigentlichen Inhalt und wollte weder den Text noch das Zeichen daneben (`.ph-x`,
   „eine Ebene zurück", §21.10/§30.32) — die App soll ganz oben an der Panelkante beginnen. `.ph-x`
   ist Kind von `.panel-title` und verschwindet damit von selbst, kein zweiter Selektor nötig.
   `chrome()`/`headSync()` bleiben unverändert (sie bauen/befüllen die Zeile weiter) — sie liegt nur
   nirgends mehr im Bild; das ist dieselbe Art Ausnahme wie zuvor für `.pinned`/Kachelgröße/Home, nur
   ausnahmslos. Preis: der Rückweg „eine Ebene zurück" (Journal/Lauf/Kontakt-Profil → Liste) hat damit
   keine eigene Schaltfläche mehr — Schließen bleibt über das ⋮ der Panele erreichbar. */
.panel-title{ display:none !important; }
/* Schließ-Zeichen `.ph-x`: Teil DERSELBEN Zeile wie der Titel, nicht mehr `position:absolute` über
   dem Inhalt — `.ph-txt` trägt `flex:1 1 auto` und schiebt es dadurch von selbst an die rechte Kante
   DIESER Zeile. Weil die Titelzeile ihre EIGENE Zeile ist (liegt über keiner anderen), braucht keine
   Nachbarzeile mehr Platz für den Knopf freizuhalten — `.turn-q`/der Kopf-Slot der Liste reservieren
   nichts. `⌄` heißt weiterhin „eine Ebene zurück" (`panelBack`, §21.10/§30.32), kein „weg" — im
   Ruhezustand blass, beim Überfahren der Panele voll sichtbar. */
.panel-body > .panel-title > .ph-x{ flex:0 0 auto; margin-left:6px; width:22px; height:22px;
  border:0; padding:0; border-radius:50%; background:transparent; color:#94a3b8; cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center;
  opacity:.5; transition:opacity .15s, background .15s, color .15s; }
.panel:hover .panel-body > .panel-title > .ph-x{ opacity:1; }
.panel-body > .panel-title > .ph-x:hover{ background:#f1f5f9; color:#0f172a; }
.panel-body > .panel-title > .ph-x svg{ width:16px; height:16px; }
.panel:hover .panel-move, .panel.sz-panel .panel-move, .panel.sz-custom .panel-move{ opacity:1; }
.panel.sz-full .panel-move{ display:none; }   /* Vollbild wird nicht verschoben */
/* space.json `kacheln_fest`: eine feste Kachel hat keinen Ziehgriff — sonst Greifhand und
   Tooltip „Verschieben“ für einen Zug, den `startMove` ablehnt (board.js, `KACHELN_FEST`). */
#panel-grid.kacheln-fest .panel.pinned[data-tile] > .panel-move{ display:none; }
/* Verschieben gilt für JEDE Inhalts-Panele gleich — Griff ist die Titelzeile.
   Früher standen hier auch `.prompt-input`, `.hist`, `.lay` und `.sz-panel.wide` — letzteres nahm
   ausgerechnet den Objekt-Panelen (E-Mail-/PDF-Ansicht, `wide tall` aus backbone.bbOpen) den Griff
   weg, so dass „manche Panele lassen sich nicht verschieben" die Regel war statt der Ausnahme. */
/* App-Panele NICHT mehr in dieser Liste (2026-08-03): im Vollbild ist der Griff über die separate
   `.panel.sz-full .panel-move`-Regel (oben) ohnehin weg, in der Panele-Größe (`appToPanel`) soll sie
   sich wie jede andere Inhalts-Panele ziehen lassen.
   Board-Möbel (`.agent`/`.kpi`/`.user`/`.logo-panel` — Logo/KPI/User/App-/Skill-Kacheln) sind seit
   2026-08-03 EBENFALLS per Drag verschiebbar (dieselbe `startMove`-Mechanik, Position bleibt über
   einen Neuladen erhalten) — die frühere Ausnahme hier ist deshalb entfallen. Seit 2026-08-11 gilt
   das auch für den Kopfzeilen-Streifen (`.head-strip`), und damit gibt es keine unverschiebbare
   Panele mehr: `MOVE_SKIP` ist ersatzlos weg (s. `startMove`). */
/* „Seitenzahl": kleine fortlaufende Nummer am rechten Ende der Panel-Fußzeile (renumber()),
   damit der Nutzer die Boxen im Assistenten ansprechen kann („schließe 2 und 4"). Als Flex-Kind
   der Fußzeile mit hohem order → immer ganz rechts (auch neben Senden/Schließen-Buttons);
   pointer-events:none → keine Störung der Fußzeilen-Klicklogik. Sichtbar nur mit der Fußzeile. */
/* Seitenzahl visuell ausgeblendet — die interne Nummer (p._num) bleibt für die Assistenten-Adressierung erhalten. */
.panel-num{ display:none; }
/* Kachel-Modus (1×1): erst aufziehen, dann verschieben (wie beim Größengriff). */
.panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .panel-move,
.panel.cmd:not(.sz-panel):not(.sz-full):not(.sz-custom) .panel-move{ display:none !important; }
/* Panel während des Verschiebens: über anderen, leicht transparent. */
.panel.dragging{ z-index:1000; opacity:.85; }
/* FREIE POSITION (2026-07-31): eine Panele, die der Nutzer platziert oder angefasst hat, liegt in
   PIXELN über dem Board — nicht in Rasterzellen. Damit gibt es kein Einrasten und kein Nachrücken:
   sie steht auf den Pixel genau dort, wo losgelassen wurde. Das Raster darunter ist nur noch die
   Erst-Ablage für frisch entstandene Panele (und die Aufgaben-Liste, die sich selbst sortiert).
   Der frühere Ablage-Umriss (`.board-drop-hint`) ist mit dem Einrasten entfallen: er zeigte die
   Zelle, in die gesprungen worden wäre — es springt nichts mehr. */
.panel.positioned{ position:absolute; margin:0; }

/* === Generische Kommando-Panele (Prompt an den Agenten) === */
.cmd-wrap{ position:relative; display:flex; flex-direction:column; height:100%; box-sizing:border-box; font-family:system-ui,-apple-system,sans-serif; }
/* Kein Kopf mehr — Status/Fortschritt erscheint im Fuß (an Stelle des Eingabefelds), solange der Agent arbeitet. */
/* Agent-Slot (links, immer sichtbar): Ruhezustand = Agentname; während der Ausführung
   Agentname · Laufzeit · Tokens im selben Slot. Feste Höhe → kein Umbruch vor/nach der Ausführung. */
.cmd-agent{ order:1; flex:0 1 auto; min-width:0; max-width:52%; display:inline-flex; align-items:center; gap:5px;
  height:var(--foot-res); padding:0 6px; border-radius:8px; font-size:var(--foot-fs); font-weight:600;
  color:#64748b; line-height:1; white-space:nowrap; overflow:hidden; }
.cmd-ag-ic{ flex:0 0 auto; }
.cmd-ag-ic:empty{ display:none; }
.cmd-ag-txt{ min-width:0; overflow:hidden; text-overflow:ellipsis; }
/* Warteliste dieses Panel-Kontexts: Anzahl der Folge-Prompts, die während der Verarbeitung
   eingegeben wurden und nach dem laufenden Turn abgearbeitet werden. Leer → unsichtbar. */
.cmd-ag-q{ flex:0 0 auto; color:#2563eb; font-variant-numeric:tabular-nums; }
.cmd-ag-q:empty{ display:none; }
/* Während der Ausführung: Akzentfarbe + tabellarische Ziffern für Laufzeit · Tokens. */
.panel.cmd.busy .cmd-agent{ color:#0f172a; font-weight:700; font-variant-numeric:tabular-nums; }
/* Touch-Panel: .touch-wrap füllt die Panel-Body-Box per absoluter Positionierung
   (bulletproof, unabhängig von der height:100%-Kette, die je nach Browser nicht
   auflöst → sonst kollabiert .touch-center auf Inhaltshöhe und die Eingabe „klebt"
   oben statt zentriert). Darin zentriert .touch-center die Eingabe vertikal,
   .touch-inner horizontal. Kein Rahmen/Hintergrund — nur der Motivations-Prompt mittig. */
.panel.touch > .panel-body{ display:flex; flex-direction:column; padding:0; overflow:hidden; }
.panel.touch .touch-wrap{ position:relative; flex:1 1 auto; min-height:0; }   /* füllt die Panel-Body-Höhe (Flex, kein out-of-flow → kann nicht kollabieren); position:relative verankert die Fußzeile als Overlay */
.panel.touch .touch-center{ align-items:center; }   /* horizontal mittig; vertikal via justify-content:center (inline/setView) */
/* Touch-Fußzeile: Overlay über dem Body (kein Flex-Sibling mehr) — der Body nimmt immer die volle
   Panelhöhe ein; die Fußzeile legt sich nur bei Bedarf (.controls-open) sichtbar darüber. */
.panel.touch .touch-foot{ position:absolute; left:0; right:0; bottom:0; z-index:2; box-sizing:border-box; display:flex; align-items:center; gap:var(--foot-gap);
  padding:2px var(--foot-pad); background:transparent; min-height:var(--foot-res); }
.panel.touch .touch-agent{ display:flex; align-items:center; flex:0 1 auto; min-width:0; font-size:var(--foot-fs); font-weight:600;
  color:var(--muted,#6b7280); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; cursor:pointer; line-height:1; }
/* Während der Ausführung: Laufzeit · Tokens in Akzentfarbe, tabellarische Ziffern. */
.panel.touch.busy .touch-agent{ color:#0f172a; font-weight:700; font-variant-numeric:tabular-nums; }
/* Abschluss-Signal: kein eigener Haken-Button mehr rechts in der Fußzeile — der Chip selbst trägt
   nach dem Lauf den grünen Haken (siehe .panel.done .pf-status::before). */
/* Agentenliste als rahmenlose Zeilen-Kacheln (antippen = Agent wählen): Avatar links, Name + Space rechts.
   Wie die Skill-Liste unter der Eingabe positioniert (Eingabe bleibt oben). */
.panel.touch .touch-agents{ margin-top:10px; width:100%; overflow-y:auto; }
/* §30.8 — EINE Optik für JEDE Vorschlagsliste (2026-07-31): die Home-Fläche, das Blatt am runden
   Knopf einer Panele (`.pf-acts`) und die Empfehlungen einer Chat-Panele (`.touch-skills`) sind
   dieselbe Liste. Die drei sahen verschieden aus (Zeilen ⇄ 3-spaltiges Kachelraster mit
   Zwischenüberschriften), obwohl sie dieselbe Frage beantworten — unterschiedlich ist nur, WORAUS
   der Inhalt gewählt wird. Deshalb steht die Grundoptik hier einmal und gilt für alle drei. */
.panel.touch .ta-grid, .pf-acts .ta-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(120px,1fr)); gap:2px; align-content:start; }
.panel.touch .ta-tile, .pf-acts .ta-tile{ display:flex; align-items:center; gap:7px; border:none; background:transparent; border-radius:8px;
  padding:5px 6px; cursor:pointer; font:inherit; text-align:left; box-sizing:border-box; min-width:0; }
.panel.touch .ta-tile:hover, .pf-acts .ta-tile:hover{ background:rgba(148,163,184,.10); }
.panel.touch .ta-tile.sel{ background:rgba(37,99,235,.10); }
.panel.touch .ta-ic, .pf-acts .ta-ic{ flex:0 0 auto; width:26px; height:26px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-weight:700; font-size:12px; text-transform:uppercase; }
.panel.touch .ta-txt, .pf-acts .ta-txt{ min-width:0; display:flex; flex-direction:column; line-height:1.15; }
.panel.touch .ta-name, .pf-acts .ta-name{ font-weight:600; font-size:var(--foot-fs); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.panel.touch .ta-tile.sel .ta-name{ color:#2563eb; }
.panel.touch .ta-space, .pf-acts .ta-space{ font-size:calc(var(--foot-fs) - 2px); color:var(--muted,#6b7280); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Empfehlungsliste unter der Eingabe (gleiche Optik wie die Agentenliste).
   KEIN eigenes `overflow-y:auto` (§30.11, 2026-07-31): es machte diesen Kasten zum Scrollport,
   OHNE dass er je scrollte (gemessen: clientHeight 472 = scrollHeight 472). Die Suchzeile am Kopf
   klebte damit an einem Kasten, der stillsteht, während der Panelkörper darunter alles wegscrollte
   — sie wanderte aus dem Bild (gemessen: top 61 → −595). Ohne die Regel ist der nächste Scrollport
   `.panel-body`, genau wie in der Home-Fläche, und `position:sticky` greift dort. */
.panel.touch .touch-skills{ margin-top:10px; width:100%; }
/* Das Kachelraster `.app-grid` ist mit §30.8 entfallen: jede Vorschlagsliste ist eine Zeilenliste
   (`.ps-list`). Es baut niemand mehr eines. */
/* Home-Panele: EINE Liste, ein Eintrag je Zeile (§30). Auch eine Aktion ist eine Zeile — vorher
   standen die Aktionen als Kachelreihe (`.ps-tiles`) über der Verlaufsliste (`.ps-hist`), also
   zwei Formen für dieselbe Frage „was jetzt?". Untereinander, weil die Reihenfolge die Aussage
   ist (Empfehlung nach Nutzung): in einer umbrechenden Kachelreihe ist „weiter vorn" nicht zu
   sehen, in einer Liste schon. `.ps-list` überschreibt dafür das `display:grid` von `.ta-grid` —
   die Klasse bleibt dran, denn sie ist die Leerfläche, auf die ein Tipp die Eingabe öffnet
   (`LEER_SEL`). */
/* §30.27 — DIE LISTE BEGINNT AM RAHMEN (2026-08-01): 12 px links und rechts kosteten in einer
   230 px schmalen Panele ein Zehntel der Breite für Nichts — die Zeilen tragen ihr eigenes Polster
   (5/6 px) schon in sich, der äußere Rand war doppelt. 6 px bleiben, damit der Hover-Ton einer
   Zeile nicht am Panelrahmen klebt. Die Kante gilt für alle drei Vorschlagslisten (§30.8) und
   MUSS mit `.panel.bar-top .ps-q` (unten) übereinstimmen: Leiste und Zeilen sind eine Liste.
   §30.28 — und seit 2026-08-01 sind auch diese 6 px weg: die Zeile trägt ihr Polster (8 px) schon
   in sich, der äußere Rand war der zweite. Der Hover-Ton beginnt damit AM Rahmen — das ist kein
   Kleben, sondern die Kante der Liste; in einer 230 px schmalen Panele sind 12 px Breite mehr
   wert als ein Rand um nichts. */
/* Höhere Selektor-Spezifität als `.panel.touch .ta-grid, .pf-acts .ta-grid` (oben, `display:grid`
   mit `auto-fill`) — sonst gewinnt dort das Grid und die Vorschlagsliste bricht ab ~250 px
   Panelbreite in mehrere Spalten um (gemessen). Eine Vorschlagsliste ist eine Zeilenliste, keine
   Kachelfläche, unabhängig davon, wie breit die Panele gerade ist. */
.panel.touch .ta-grid.ps-list, .pf-acts .ta-grid.ps-list, .ps-list{ display:flex; flex-direction:column; gap:1px; padding:0; max-width:none; }
.ps-list .ta-tile{ width:100%; align-items:flex-start; gap:9px; padding:7px 8px; }
/* §30.39 — was nicht mehr in die Panele passt, steht auch nicht da (`kappen`). Eigene Klasse statt
   `style.display`: der Filter (`actsFilter`) schreibt dort seine eigene Entscheidung hin, und zwei
   Schreiber auf derselben Eigenschaft löschen einander. */
.ps-list .ta-tile.ps-cut{ display:none; }
/* Der Hinweis-Satz (Begrüßung, client-/`presence.py`-serverseitig für Bereichs-Ansichten) ist kein
   `.ta-tile` — kein Klick, kein Symbol, keine Note — sondern ein Satz wie jeder Fließtext; er bleibt
   deshalb von `actsFilter` unberührt (die Auswahl trifft nur `.ta-tile,.ph-row`). Ungebunden an
   `.ps-list` (2026-08-03): Journal/Kontakt-Profil/… rendern ihn in `.area-out`, nicht in der Liste —
   derselbe Look überall, wo ein Bereich seinen Hinweis zeigt. `.ps-cut` bleibt dennoch wirksam, falls
   `kappen()` ihn in einer sehr kleinen Home-Panele doch einmal treffen muss — sonst zeigte er sich
   trotz Klasse weiter an und die Höhenrechnung von `kappen()` stimmte nicht mehr mit dem
   Sichtbaren zusammen. Linksbündig wie jede Zeile der Liste darunter — der ganze Strom (Begrüßung,
   Empfehlungen, Chat) schließt links gleich ab, keine Ausnahme im Fluss. */
.ps-hint{ width:100%; box-sizing:border-box; padding:10px 8px; font-size:.82rem;
  color:var(--muted,#6b7280); text-align:left; }
.ps-list .ps-hint.ps-cut{ display:none; }
/* Wege der Panele (Vollbild/Kachel/Schließen …, `navIcons`) als schmale Symbolzeile — Werkzeuge der
   Panele, kein Eintrag der Empfehlungsliste. Sie steht als LETZTE Zeile der Liste (`navRow`) und
   bleibt zu, bis der runde Punkt sie aufklappt: ein Werkzeug, das man erst sucht, wenn man es
   braucht, nicht eines, das vor jedem Angebot steht. Flaches Farbsystem wie Fußzeile/Sende-Pfeil:
   transparente, runde Icon-Knöpfe. */
.ps-list .ps-navrow.ps-cut{ display:none; }   /* dieselbe Kapp-Regel wie `.ta-tile`/`.ps-hint` — sonst rechnet `kappen()` sie weg, ohne dass sie wirklich verschwindet */
.ps-navrow{ display:flex; align-items:center; gap:2px; padding:4px 8px; }
.ps-navdot{ border:none; background:transparent; border-radius:50%; width:26px; height:26px;
  flex:0 0 auto; display:flex; align-items:center; justify-content:center; font-size:11px;
  letter-spacing:1px; line-height:1; color:var(--muted,#6b7280); cursor:pointer; padding:0; }
.ps-navdot:hover{ background:rgba(148,163,184,.10); color:var(--fg); }
.ps-navicons{ display:flex; gap:2px; padding:0; }
.ps-navicons.ps-navicons-hidden{ display:none; }
.ps-navicon{ border:none; background:transparent; border-radius:50%; width:26px; height:26px;
  display:flex; align-items:center; justify-content:center; font-size:13px; line-height:1;
  color:var(--muted,#6b7280); cursor:pointer; }
.ps-navicon:hover{ background:rgba(148,163,184,.10); color:var(--fg); }
.ps-list .ta-ic{ margin-top:1px; }
/* Ein Journal-Eintrag ist ein ganzer Satz, kein Schlagwort: zwei Zeilen statt abgeschnitten. */
.ps-list .ta-name{ white-space:normal; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; overflow:hidden; }
/* §30.6 (2026-07-31) — ES GIBT NUR NOCH DEN LISTEN-EINTRAG. Vorher waren drei Dinge in derselben
   Fläche drei verschiedene Formen: die Wege der Panele als kleine Zeichenreihe (`.ps-nav.ps-top`),
   Navigation als Kachel-Feld (`.ps-nav`), alles Übrige als Zeile. Wer etwas sucht, musste also
   erst herausfinden, in welcher Form es dargestellt ist. Jetzt ist jedes Angebot eine Zeile —
   Vollbild, Journal, ein Skill, ein alter Lauf, ein Kontakt —, und die Suchzeile am Kopf filtert
   sie ausnahmslos alle. `.ps-nav` und `.ps-top` sind damit entfallen.
   Die SUCHZEILE gehört zur Liste, nicht zur Panele: sie filtert das Angebot. Die Eingabe der
   Panele steht wie überall in der Fußzeile hinter dem Agentnamen. */
/* §30.13 — DIE BEDIENLEISTE STEHT OBEN ODER UNTEN, NIE BEIDES (2026-07-31). Es ist DASSELBE
   Element (`.pfoot` mit rundem Knopf, Agentname und Eingabe): zeigt die Panele ihre
   Vorschlagsliste, zieht die Leiste in diesen Kopf-Slot; zeigt sie Chat/Inhalt, steht sie wieder
   unten. Vorher trug die Home-Fläche beides zugleich — oben eine Suchzeile, unten Name und Knopf —
   also zwei Orte für dieselbe Absicht. */
/* §30.22 — DIE LEISTE IM KOPF DER LISTE SCROLLT MIT (2026-08-01). Sie klebte am oberen Rand
   (`position:sticky` samt Deckfarbe und `z-index`, damit die Zeilen unter ihr durchlaufen) und war
   damit das einzige Stück Panelinhalt, das nicht zur AUSGABE gehörte, sondern über ihr lag. Jetzt
   ist sie der erste Eintrag des Stroms wie jeder andere und wandert beim Blättern mit ihm weg;
   zurück kommt sie über den Anfang der Liste (`☰`/Kreis rollen dorthin, `scrollTop=0`) oder als
   Leiste im Strom, dort wo man hingeklickt hat (`bar-in`, §30.19). Deckfarbe und `z-index`
   entfallen mit dem Kleben — es liegt nichts mehr übereinander (deshalb ist auch die dunkle
   Variante `#board.board-dark .ps-q` weg). Gilt für alle drei Vorschlagslisten (§30.8): es ist
   EINE Regel, und dieselbe Fläche darf nicht je nach Herkunft anders scrollen. */
/* §36 — DER KOPF-SLOT HÄLT SEINEN PLATZ, AUCH LEER (2026-08-0x). Zieht die Leiste weiter (`bar-in`,
   in den Chat), verlässt `.pfoot` diesen Slot komplett — ohne eigene Mindesthöhe fiel er auf sein
   Polster zusammen (10 px) und die Liste rutschte um die Höhe der Box (~26–34 px) nach oben: „die
   Eingabe bewegt sich" wurde sichtbar zu „die ganze Liste bewegt sich mit". `min-height:var(--pf-tile)`
   hält denselben Raum offen, ob die Box gerade dort steht oder nicht — ein Wechsel der Leiste ändert
   dann nur SIE, nicht die Position von allem darunter. */
.ps-q{ padding:4px 8px 6px; min-height:var(--pf-tile); box-sizing:content-box; }
/* Steht die Leiste oben, deckte sie den Ziehgriff zu (`.panel-move`: 20 px unsichtbar am
   Panelkopf, seit dem Wegfall der Titelzeile der einzige Griff — gemessen: Ziehen bewegte die
   Panele um 0 px). Der Streifen bekommt seinen Platz als POLSTER über der Leiste zurück und liegt
   wieder obenauf; darin ist nichts zu bedienen, also nimmt er niemandem einen Klick weg.
   Seit die Leiste mitscrollt (§30.22) gilt das Polster nur am Anfang der Liste: weiter unten
   geblättert laufen die Zeilen unter dem Griffstreifen durch wie der Inhalt jeder anderen Panele
   auch — dieselbe Lage, für die §30.9 den `elementFromPoint`-Umweg beschreibt.
   §30.27 — DAS POLSTER IST SO HOCH WIE DER GRIFF (2026-08-01): 22 px waren die Höhe des Griffs
   (20 px) plus Luft, die niemand braucht — oben stand damit ein leerer Streifen über der Eingabe.
   Jetzt tragen Polster UND Griff dasselbe Maß (12 px): der Griff bleibt vollständig ÜBER der
   Leiste (er darf ihr keinen Klick abfangen, siehe oben), ist mit 12 px noch zu treffen, und die
   Fläche darüber ist genau so hoch, wie sie sein muss. Beide Zahlen MÜSSEN gemeinsam kippen —
   ein kleineres Polster über einem 20-px-Griff wäre der Fehler von §30.13 zurück.
   §30.38 (2026-08-01): dasselbe Maß noch einmal halbiert (6 px). Der Streifen war der einzige
   Abstand zwischen Panelkante und Eingabe und stand als leere Fläche über ihr. Preis, bewusst
   getragen: der Ziehgriff ist damit 6 px hoch — schmaler, aber weiterhin der volle Panelbreite
   nach zu treffen, und der Rest der Kopfzeile gehört der Eingabe. */
.panel.bar-top .ps-q{ padding-top:6px; }
.panel.bar-top .panel-move{ z-index:4; height:6px; }
/* Oben ist die Leiste kein Overlay mehr, sondern eine Zeile in der Liste.
   `position:relative` statt `static` (2026-08-01): der Senden-Pfeil liegt absolut IN der Leiste
   (`.pfoot .pf-send`, rechts, unten verankert). Ohne Bezug an der Leiste fiel er auf den nächsten
   positionierten Vorfahren zurück — das ist der ganze Listen-Kasten (`.ps-obj.ps-acts`), also
   stand der Pfeil am UNTEREN Ende der Liste statt in der Eingabezeile (gemessen: Pfeil bei
   y 299–325, die Zeile bei y 66–96). Am Fluss ändert `relative` nichts, die Leiste bleibt eine
   Zeile in der Liste; left/right/bottom sind hier ohnehin zurückgenommen. */
/* §30.36 — OBEN IST DIE EINGABE SO HOCH WIE DER SENDEN-PFEIL DARIN (2026-08-01). Unten ist die Box
   ein Overlay mit Rahmen und Schatten, das sich vom Inhalt abheben muss (`--foot-h`, 30 px); oben
   ist sie eine Zeile IN der Liste und war damit höher als jeder Eintrag darunter. Ihr Maß ist jetzt
   `--pf-tile` (26 px / am Handy 34 px) — dasselbe wie der Knopf, der IN ihr liegt: damit sitzen
   Text und Pfeil auf einer Mittellinie, statt dass der Pfeil (unten verankert für die wachsende
   mehrzeilige Box) über den Text hinausragt. Der Text steht senkrecht MITTIG darin (halbe Restluft
   oben wie unten), die Linie hat also Abstand zu ihm; enger geschriebene Zeilen (`line-height:1.35`
   statt 1.5) schaffen den Platz dafür, ohne die Zeile wieder hoch zu machen. Die drei Zeilen MÜSSEN
   gemeinsam kippen — eine niedrigere Box in einer unverändert hohen Leiste verschöbe die Lücke nur,
   und ein unten verankerter Pfeil stünde wieder daneben. Der Innenabstand SEITLICH bleibt (dort
   hält `.reco-typed` den Platz für den Pfeil frei). */
.panel.bar-top .ps-q > .pfoot{ position:relative; left:auto; right:auto; bottom:auto;
  border-top:0; background:transparent; padding:0; min-height:var(--pf-tile); display:flex; }
.panel.bar-top .ps-q > .pfoot .pf-send{ bottom:0; }
/* Oben gilt DIESELBE Regel wie unten: Chip ODER Box, nie beides (2026-08-01). Der Chip (Kreis +
   Agentname) nimmt die GANZE Breite des Kopfes — er ist die eine Fläche, die man antippt, und ein
   Griff, der je nach Länge des Namens 45 % oder 20 % breit ist, ist als Griff nicht zu treffen.
   Die Breite kommt aus der Basisregel (`flex:1 1 auto`, `max-width:none`), hier steht deshalb
   keine eigene. Vorher standen Knopf, Name UND Box gleichzeitig oben — zwei Angebote für dieselbe
   Absicht, und die Box war der Ruhezustand, obwohl sie unten der geöffnete Modus ist. */
/* §30.23 — OBEN IST DER CHIP EINE ZEILE DER LISTE (2026-08-01). Er stand als PILLE über ihr: weiße
   Fläche, Rahmen, 999-px-Ecken, und darin ein 18-px-Kreis als bloßer Umriss. Die Zeilen darunter
   tragen dagegen ein gefülltes rundes Feld mit Symbol (`.ta-ic`, 26 px) und daneben den Namen — zwei
   Formen für zwei Dinge, die untereinander liegen und beide dasselbe heißen: „hier ist etwas, das du
   antippen kannst". Der Chip sah damit aus wie ein Bedienelement ÜBER der Liste, obwohl er seit
   §30.22 ihr erster Eintrag IST (er scrollt mit ihr weg). Jetzt trägt er genau die Form einer Zeile:
   rahmenlos und flächenlos, 8-px-Ecken, dieselbe Polsterung, dasselbe Loch zwischen Rundem und
   Namen, dieselbe Schrift, derselbe Hover-Ton — und der runde Knopf IST das runde Feld mit Symbol.
   Sein Symbol bleibt der Kreis mit blauem Punkt (`RECO_SVG`, „hier ist eine Auswahl für dich"), und
   der Punkt pulsiert weiter, solange die Panele arbeitet (§30.18).
   Es ist dieselbe Entscheidung wie §30.8 (EINE Optik für jede Vorschlagsliste), einen Eintrag
   weitergedacht: die Leiste steht IN der Liste, also sieht sie aus wie die Liste.
   NUR oben. Unten ruht die Leiste seit §30.21 unsichtbar, und im Strom (`bar-in`) liegt sie über dem
   INHALT — dort sagt der Rahmen, wo der Chip aufhört, und es gibt keine Liste, an die er sich
   anlehnen könnte.
   §30.16 („leer ist schmaler als voll") bleibt erfüllt: die Zeile ist mit 36 px immer noch niedriger
   als die geöffnete Eingabebox (51 px) — gemessen, nicht angenommen.
   Die Maße stehen hier als Zahlen und nicht als Verweis, weil die Zeilen daneben ZWEI Fassungen
   haben: `.ps-list .ta-tile` (7/8 px, Loch 9) verliert auf einer Chat-/Kommando-/Menü-Panele gegen
   die dreiklassige Grundregel (`.panel.touch .ta-tile` & Co., 5/6 px, Loch 7) — die §30.8 erklärte
   Gleichheit der drei Listen ist an dieser Stelle also von der Kaskade schon aufgehoben. Genommen
   ist die Fassung, die auf der Home-Fläche WIRKLICH gilt (gemessen: 5/6 px, Loch 7, Zeile 37 px);
   im Blatt einer Panele ohne diese Klassen liegen die Zeilen deshalb 2 px weiter innen als der Chip.
   Nicht mitrepariert — das wäre eine Entscheidung über alle drei Listen, nicht über diese Leiste. */
.panel.bar-top .ps-q{ padding-left:0; padding-right:0; }   /* äußere Kante auf der der Zeilen (`.ps-list`, §30.28) */
.panel.bar-top .ps-q .pf-status{ height:auto; padding:5px 6px; gap:7px;
  background:transparent; border:0; border-radius:8px; color:inherit; }
.panel.bar-top .ps-q .pf-status:hover{ background:rgba(148,163,184,.10); }
/* 26 px LITERAL wie `.ta-ic`, nicht `--pf-tile`: das Maß der Zeile ist am Handy dasselbe (26 px),
   `--pf-tile` wächst dort auf 34 px — der Kreis wäre größer als das runde Feld daneben. */
.panel.bar-top .ps-q .pf-rest{ width:26px; height:26px; margin-right:0;
  background:#f1f5f9; color:#475569; }
.panel.bar-top .ps-q .pf-rest:hover{ background:#e2e8f0; color:#0f172a; }
.panel.bar-top .ps-q .pf-rest svg{ width:15px; height:15px; }
/* Keine Platzreservierung für `.ph-x` nötig (§30.31/§38): es sitzt in `.panel-title`, der EIGENEN
   ersten Zeile des Stroms — die Leiste im Kopf-Slot der Liste (eine andere, spätere Zeile) teilt sich
   mit ihr keine Fläche. */
/* Oben ist die Eingabebox rahmenlos, keine Linie darunter (2026-08-02): ein Rahmen mit Ecken,
   Fläche und Schatten machte daraus ein zweites Fenster über der Liste; die Unterstreichung
   trennte sie unnötig vom Chip darüber. Unten (Overlay über dem Inhalt) trägt die Box ihren
   Rahmen weiter, dort grenzt er sie vom Inhalt darunter ab.
   Der Innenabstand bleibt unangetastet, damit `.reco-typed` weiter Platz für den Senden-Pfeil hält. */
.panel.bar-top .pf-reco-ta, .panel.bar-in .pf-reco-ta{ border:0; border-radius:0;
  background:transparent; box-shadow:none;
  /* §30.36 — so hoch wie der Knopf darin, Text senkrecht mittig (halbe Restluft: Höhe − Zeile − Linie).
     2026-08-03 — dieselbe Formel jetzt auch unten (`bar-in`, Fußzeilen-Chat): „identisch zum Kopf,
     nur dass sie unten größer werden kann" — die Ruhehöhe ist dieselbe (`--pf-tile`, nicht das
     größere `--foot-h` der übrigen Overlay-Fußzeile), das Wachsen selbst ist unverändert die
     normale Mehrzeiligkeit der Textarea (kein `max-height`, `resize:none` verhindert nur das
     Ziehen von Hand). */
  min-height:var(--pf-tile); line-height:1.35;
  padding-top:calc((var(--pf-tile) - 1.35em - 1px) / 2);
  padding-bottom:calc((var(--pf-tile) - 1.35em - 1px) / 2); }
/* §30.33 — OBEN GEHÖRT DER KOPF DER BOX ALLEIN (2026-08-01). §30.25 hatte hier Kreis UND Box
   nebeneinander gestellt (drei Regeln, die den Chip gegen „bei offener Eingabe weicht alles außer
   Box und Pfeil" wieder einblendeten). Damit stand der Kreis links vor der Box — ein Griff, der
   an dieser Stelle nichts anbietet, was die Liste unter ihm nicht schon zeigt (§30.10: „Kreis
   gedrückt" IST „Home geöffnet") — und die Box begann 40 px innen: der Browser holte das
   fokussierte Feld in den Blick und schob die Fläche dabei in die Breite.
   Jetzt gilt oben wieder DIE Fußzeilenregel (§19.1): ist die Eingabe offen, weicht der Chip samt
   Kreis (`.reco-open .pfoot .pf-status`, `.reco-open .pf-rest`) — die Box läuft von der linken bis
   zur rechten Kante der Panele. Es ist eine RÜCKNAHME, kein neuer Sonderfall: die drei
   `!important`-Gegenregeln sind entfallen, nicht überschrieben.
   Was bleibt: den Adressaten sagt die Zustandszeile jedes Laufs (§30.20); der pulsierende Kreis
   während der Verarbeitung steht im eigenen Kopf-Slot `.ps-busy` (§30.24, dort ohne offene Box);
   und ein hart geschlossener Kopf zeigt weiter den Chip als Zeile (§30.23) — mit `barPlace` ist
   das nicht der Ruhezustand, sondern nur der Weg dorthin. */
/* §30.26 — DIE BOX BEGINNT AUF DER KANTE DER ZEILEN (2026-08-01, mit §30.33 auf eine Regel
   geschrumpft). Ihr Platzhalter stand 18 px weiter innen als „Vollbild"/„Kachel" darunter
   (gemessen: Text 470 gegen 452 px), also sichtbar eingerückt gegen die Liste, in der die Leiste
   steht. Von den drei Polstern, die sich zu dem Versatz addierten, sind zwei mit dem Chip selbst
   weggefallen (sein rechtes Polster und die Fußzeilen-Lücke `--foot-gap`); übrig bleibt das linke
   Polster der Box. Nur `padding-left`, nicht der ganze Innenabstand: rechts hält er den Platz für
   den Senden-Pfeil (`.reco-typed`), oben/unten den Text auf der Mittellinie (§30.13-Rechnung mit
   `--foot-h`). Der Text sitzt damit auf der Kante der RUNDEN FELDER der Zeilen, nicht auf deren
   Schriftkante — ohne Kreis gibt es oben nichts, was diese 33 px einrücken würde. Die 6 px sind
   deshalb das linke Polster der Zeile selbst (`.ta-tile`, 5/6 px, siehe §30.23) und nicht null:
   bei null stünde der Text 6 px WEITER AUSSEN als alles darunter (gemessen: 161 gegen 167 px).
   Gilt nur OBEN und nur bei offener Box — unten und im Strom (`bar-in`) ist die Box ein Overlay mit
   Rahmen, dort gibt es keine Liste, auf deren Kante sie sich ausrichten könnte. */
.panel.bar-top.reco-open .pf-reco-ta{ padding-left:6px; }
/* Unten ist dann nichts mehr zu reservieren. */
.panel.bar-top > .panel-body.ps{ padding-bottom:6px; }
.panel.bar-top .touch-out{ padding-bottom:6px; }
/* Zustand eines Laufs am Icon (`spec.tone`): läuft blau · fertig grün · abgebrochen/Fehler rot —
   dieselben drei Farben wie der Punkt der Journal-Zeile (`.jr-dot`), damit ein Zustand überall
   gleich aussieht. */
.panel.touch .ta-ic.ta-run{ background:rgba(37,99,235,.12); color:#2563eb; }
.panel.touch .ta-ic.ta-ok{ background:rgba(22,163,74,.12); color:#16a34a; }
.panel.touch .ta-ic.ta-ab{ background:rgba(192,57,43,.12); color:#c0392b; }
/* Verlauf-Zeilen (Basis-Skill „Verlauf") — die Tickets dieses Agenten als klickbare Liste
   (Prompt/Aktion + Status der Verarbeitung). */
.panel.touch .ph-row{ display:block; width:100%; text-align:left; border:none; background:transparent; font:inherit; border-radius:8px; padding:8px 10px; cursor:pointer; color:var(--fg); }
.panel.touch .ph-row:hover{ background:rgba(148,163,184,.10); }
.panel.touch .ph-tx{ font-size:13px; line-height:1.35; overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; }
.panel.touch .ph-meta{ font-size:11px; color:var(--muted,#6b7280); margin-top:2px; }
/* Status der Prompt-Verarbeitung in der Ticket-Zeile (läuft/fertig/Fehler). */
.panel.touch .ph-st{ font-weight:600; }
.panel.touch .ph-st.run{ color:var(--accent,#2563eb); }
.panel.touch .ph-st.done{ color:#16a34a; }
.panel.touch .ph-st.err{ color:#c0392b; }
/* Die eigene Kopfzeile der Chat-Panele (`.touch-head`/`.th-name`) ist ENTFALLEN (2026-07-31).
   Der Adressat steht im Fußzeilen-Chip; „Fertig" schließt die offene Auswahl.
   „Fertig" schließt die offene Adressaten-Auswahl. Sie bleibt beim Antippen einer Kachel offen,
   damit ein Ticket an MEHRERE Agenten adressiert werden kann (Sammel-Modus, siehe showAgents). */
.pfoot .th-done{ flex:0 0 auto; border:0; background:transparent; padding:0 2px; cursor:pointer;
  font:inherit; font-size:13px; font-weight:700; color:#2563eb; }
.pfoot .th-done[hidden]{ display:none; }
/* Gruppen-Überschrift in der Quick-Action-Liste (Panele · Favoriten · Aktionen · Verlauf). Sie
   spannt die ganze Rasterbreite und verschwindet mit ihrer Gruppe, sobald der Filter alles darin
   ausblendet (`filterSkills`) — eine Überschrift ohne Inhalt wäre eine Lüge über die Liste. */
/* ENTFALLEN mit §30.8: Zwischenüberschriften („Panele/Favoriten/Aktionen/Boards/Verlauf"). Die
   Home-Liste hatte nie welche — die Reihenfolge IST die Aussage, und gefiltert wird über die
   Suchzeile. Regel behalten, falls ein Blatt sie je wieder braucht:
.panel.touch .ta-hd{ grid-column:1 / -1; padding:6px 4px 2px; font-size:calc(var(--foot-fs) - 2px);
  font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--muted,#94a3b8); }
.panel.touch .ta-hd[hidden]{ display:none; } */
/* Panele-Aktionen (Vollbild/Kachel/Zurücksetzen/Schließen) — dieselbe Kachel wie ein Skill, nur
   grau: sie tun etwas mit der ANSICHT, nicht mit dem Auftrag. */
.panel.touch .ta-tile.act-view .ta-ic{ background:#f1f5f9 !important; color:#475569 !important; }
/* Ticket-Zähler: er sitzt AM ICON der Verlauf-App in der Empfehlungsliste (Anzahl laufender
   Prompts/Tickets, tabellarische Ziffern; blau sobald etwas läuft). */
.panel.touch .ta-ic.tk-count{ font-size:12px; font-variant-numeric:tabular-nums; }
.panel.touch .ta-ic.tk-count.on{ background:rgba(37,99,235,.12) !important; color:#2563eb !important; }
/* Fußzeilen-Eingabe (Overlay) darf die Empfehlungsliste darüber nicht verdecken. */
.panel.touch.reco-open .touch-body{ padding-bottom:calc(var(--foot-h) + 8px); }
/* Agent gewählt → NUR die Skill-Liste (keine Eingabe darüber), nutzt die volle Resthöhe. */
.panel.touch.skills-open .touch-center{ justify-content:flex-start; }
.panel.touch.skills-open .touch-inner{ display:none; }
.panel.touch.skills-open .touch-skills{ flex:1 1 auto; min-height:0; }
/* „Volle Resthöhe" braucht mitwachsende Kästen DARÜBER. Das galt bis 2026-07-31 nur für die zwei
   Zustände mit offener Liste (`!important` gegen ein inline `flex:0 0 auto`) — der Chat selbst
   blieb so hoch wie sein Inhalt, und zwischen ihm und der Fußzeile stand die halbe Panele leer
   (gemessen auf `/claude`: Kachelblock 138 px, `.touch-wrap` 306 px, darin `.touch-body` 42 px ⇒
   229 px toter Streifen). `.touch-body`/`.touch-center`/`.touch-out` tragen die Regel jetzt inline
   als `flex:1 0 auto` — wachsen bis zur Fußzeile, nie unter die Inhaltshöhe schrumpfen (dann
   scrollt der Strom). Die beiden Sonderregeln sind damit entfallen.
   `.touch-center` braucht hier weiterhin `display:flex`: `setView()` schreibt
   `center.style.display=''` und LÖSCHT damit die Inline-Angabe — danach war der Kasten ein Block,
   und `flex:1 1 auto` an der Liste darin ohne Wirkung (gemessen: Kasten 738 px, Liste 334 px). */
.panel.touch.skills-open .touch-center{ display:flex; flex-direction:column; min-height:0; }
/* … UND die Erst-Eingabe im Körper darf sie nicht besetzen. Sie ist ein LEERER Platzhalter
   (`.touch-greet` trägt keinen Motivations-Prompt mehr, `.touch-main` ist unsichtbar bis jemand
   hineintippt) — mit dem inline `flex:1 0 auto` nahm sie trotzdem die ganze Fläche zwischen den
   Kacheln und der Fußzeile. Sichtbar war davon zweierlei: die halbe Panele stand leer, obwohl sie
   dem Detailbereich gehören sollte, und ein Tipp dorthin holte KEINE Eingabe — `LEER_SEL` trifft
   `.touch-body`, nicht `.touch-center`, und der Klick landete stattdessen in der unsichtbaren
   Erst-Eingabe (Cursor mitten in der Panele, Eingabebox unten unberührt). `flex:0 0 auto` gibt die
   Fläche zurück; nur solange keine Liste offen ist und niemand in der Erst-Eingabe tippt
   (`ti-full`) — dort ist sie der Inhalt. `!important` gegen die Inline-Angabe. */
.panel.touch:not(.skills-open):not(.agents-open):not(.ti-full) .touch-center{ flex:0 0 auto !important; }
/* Agentenliste offen: NUR die Liste (keine Eingabe darüber). Die Aktionsleiste bleibt sichtbar,
   damit das Menü-Icon (☰) die Liste wieder schließen kann. */
.panel.touch.agents-open .touch-center,
.panel.touch.agents-open .touch-out{ display:none !important; }
.panel.touch.agents-open .touch-agents{ flex:1 1 auto; min-height:0; }
.panel.touch.agents-open .touch-foot > .touch-agent{ display:none !important; }
/* Ausgabe/Chat sichtbar → die zentrierte Erst-Eingabe (großer Prompt) darf NICHT dahinter durchscheinen. */
.panel.touch.out-mode .touch-center{ display:none !important; }
/* Grüner Haken am Ende der Agenten-Antwort (Legacy aus älteren gespeicherten Panelen, siehe markDone() in
   makeTouch — heute wird nichts Neues mit dieser Klasse erzeugt, das Abschluss-Signal ist der grüne Haken
   am Chip); CSS + Klick-Handler bleiben für evtl. noch vorhandene alte Restore-Daten bestehen. */
.panel.touch .touch-ansdone{ display:inline-flex; align-items:center; color:#16a34a; cursor:pointer; margin-top:8px; }
.panel.touch .touch-ansdone svg{ width:20px; height:20px; }
.panel.touch .touch-out{ padding-top:2px; padding-bottom:calc(var(--foot-res) + 8px); }   /* erste Prompt-Zeile weit oben; unten Platz für die Overlay-Fußzeile */
.panel.touch .touch-greet{ margin-top:26px; }   /* Motivations-Box tiefer setzen */
/* Adressierte Agenten als Schlagworte UNTEN LINKS in der (leeren) Panele: ein Ticket kann an
   mehrere Agenten gehen, die dann gemeinsam daran arbeiten. ✕ nimmt einen Agenten heraus,
   ＋ öffnet die Auswahl im Sammel-Modus. Sichtbar nur im Eingabe-Zustand (siehe syncTags);
   den Platz über der Overlay-Fußzeile schafft .reco-open .touch-body. */
.panel.touch .touch-tags{ flex:0 0 auto; display:flex; flex-wrap:wrap; align-items:center; gap:4px; padding:6px 0 2px; }
.panel.touch .touch-tags[hidden]{ display:none; }
.panel.touch:not(.reco-open) .touch-tags{ margin-bottom:var(--foot-res); }   /* ohne offene Eingabebox reserviert der Body keinen Fußzeilenplatz → Schlagworte selbst freistellen */
/* Das CSS der Schlagwortzeile (`.tt-chip`/`.tt-nm`/`.tt-x`/`.tt-add`) ist mit ihr ENTFALLEN. */
/* Mehrfach-Adressierung: Kopfzeile je Agent über dessen Antwort (bei einem Adressaten nicht gesetzt). */
.panel.touch .touch-who{ margin-top:10px; font-size:11px; font-weight:700; letter-spacing:.03em;
  text-transform:uppercase; color:var(--muted,#6b7280); }
/* Laufzeile (Adressat · Laufzeit · Tokens): letzte Zeile der Ausgabe, läuft sekündlich mit und
   bleibt nach dem Abschluss als Schluss-Auskunft stehen — dieselbe Rolle und dieselbe Optik wie
   `.cmd-meta` in den Kommando-Panelen (§30.18).
   NICHT auf `.panel.touch` eingeschränkt (§30.20): dieselbe Zeile schreibt die serverseitige
   Lauf-Ansicht (`presence.run`, geöffnet aus dem Journal) an ihr Ende — ein Lauf sieht gleich aus,
   ob er gerade läuft oder aus dem Register kommt. Eine zweite Regel dafür wären zwei Optiken. */
.touch-meta{ margin-top:8px; font-size:11px; color:#94a3b8; font-variant-numeric:tabular-nums; }
/* §30.20 — Unterzeile des Lauf-Kopfes (Zustand · Agent · Uhrzeit). Dieselbe Optik wie die
   Unterzeile einer Listenzeile (`.st-row .st-rw-s`), aber ein eigener Name: sie steht nicht in
   einer Zeile, sondern unter dem Auftrag. */
.run-sub{ display:block; font-size:12px; color:#64748b; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; margin-top:2px; }
/* Einordnung des Assistenten direkt unter dem Lauf-Kopf (`noteEl`) — dieselbe Optik wie eine
   gesprochene Notiz im talk-Protokoll (`.tk-note`), damit es überall dieselbe Stimme ist. */
.assist-note{ font-size:12px; color:#64748b; margin:4px 0 8px; }
/* Antwort-Inhalt eines Turns (`send()`, ein Element je Adressat) — Basis-Abstand, bisher als
   Inline-Stil gesetzt; als eigene Klasse überschreibbar (die Home-Panele bekommt ihre eigene
   Fassung darunter). */
.ps-ans{ margin-top:4px; }
/* §Home-Punkt (2026-08-08, EINE Fläche statt zwei — „card" und Panele waren zwei verschachtelte
   Kästen mit je eigenem Rahmen/Radius/Schatten für dieselbe Sache; das war der Widerspruch, nicht
   nur ein Stilfehler. Es gibt jetzt keine eigene „Karte" mehr: die Panele SELBST ist die Fläche —
   normaler Rahmen/Kopf/Ziehgriff/Ecke/✕ wie jede andere, klein per `setCustomSize` (`homePanel`).
   Der runde Knopf ist der einzige Sonderfall (steht im Detailbereich, normaler Fluss) — sobald die
   erste Frage läuft, verschwindet er (er hat seine Aufgabe erfüllt) und `footAsk` behandelt `.home`
   NICHT mehr gesondert: die Antwort läuft über denselben generischen Weg wie bei jeder anderen
   Panele (`psInit`/`psTurn` unten in `footAsk`) — direkt im Detailbereich, mit derselben Fußzeile
   (Chip + Eingabe) wie überall. Eine Antwort darf dabei selbst eine Liste/Tabelle sein (`psAdd`,
   kein Sonderfall nötig — dieselbe Panele zeigt also auch Daten, nicht nur Text). */
/* 2026-08-24 — DER RUNDE KNOPF IST ENTFALLEN (Nutzerwunsch „entferne alle runden punkte inklusive
   bug"). Damit fällt der ganze Zwischenzustand „Punkt, der sich auf Klick zur Eingabe öffnet" weg:
   `homePanel()` legt die Panele an und öffnet die Eingabe sofort — ein Klick auf die freie Fläche
   bringt also direkt den Chat-Bereich. Geschlossen existiert diese Panele nicht mehr (sie räumt
   sich in `onClose` selbst weg), deshalb sind auch die Regeln für den geschlossenen Zustand
   (feste 56×56, Fußzeile aus, Detailbereich ohne Scrollen) hier entfallen. */
/* 2026-08-24 — `.home` sah bis heute NIE wie eine Panele aus (`background:transparent !important;
   border:0; box-shadow:none`): sichtbar war nur die eingerückte weiße Karte darin, die Panele war
   ihr durchsichtiger Rahmen. Das war die Fassung dafür, dass Panele und Karte zwei verschiedene
   Flächen waren. Jetzt füllt die Karte die Panele randlos (s.u.) — es gibt nur noch EINE Fläche,
   und ihr Aussehen kommt aus `.panel` (weiß, Rahmen, Radius, Schatten). Die Zeile ist damit
   entfallen; `.panel.home.pinned` (die Agent-Logo-Kachel, zweiter Träger derselben Klasse) war
   davon ohnehin ausgenommen und bleibt unberührt. */
/* Ziehgriff und Ecke bleiben BENUTZBAR (2026-08-24, geändert): früher waren sie ausgeblendet,
   weil der runde Knopf sein eigener Griff war (`startMove` an `.app-home`). Ohne ihn wäre die
   Panele sonst weder zu verschieben noch zu vergrößern — beides sind unsichtbare Hotspots, sie
   bringen keinen Rahmen zurück. */
/* Solange der Ausgabebereich leer ist — und das ist er in `.home` IMMER, `footAsk` schreibt eine
   Antwort erst NACHDEM `.home` bereits zu `.home-chat` geworden ist —, soll die Panele nur so hoch
   sein wie die Eingabebox (Nutzerwunsch 2026-08-09): sonst wuchs sie beim Öffnen sofort auf die
   volle `setCustomSize`-Höhe (170 px), die Karte (unten verankert, `bottom:16px`) blieb dabei am
   PANELBODEN und der Klickpunkt lag am Panelkopf — der leere Detailbereich dazwischen sah aus wie
   „die Eingabe erscheint woanders". 84 px war 16 (oberer Rand) + 52 (Mindesthöhe der Karte) + 16
   (unterer Anker); seit die Karte randlos in der Panele sitzt (2026-08-24, s.u.), fallen die beiden
   16er weg und es bleiben die 52 der Karte selbst — genug für die Karte, ohne die Lücke der
   generischen Panele-Höhe. Wächst der
   Text über eine Zeile hinaus, bleibt die Karte innerhalb dieser Höhe (`max-height:45vh` an
   `.pf-ans-block`, hier ungenutzt, und `overflow-y:auto` an der Eingabe selbst) — WÄCHST DAFÜR
   ABER IN DIE BREITE: `homeWide()` im Skript zieht die Fläche mit dem getippten Text mit (Start
   700 px statt der früheren 220 — auf Nutzerwunsch eingependelt, 420 → 620 → 820 → 700 —,
   Grenze 1200 px bzw. die Boardbreite). Bis 2026-08-24 blieb sie
   220 px und der Text scrollte im 31 px hohen Feld — gemessen bei 130 Zeichen: 196 px Inhalt in
   31 px Fenster, sichtbar drei Wörter. Sobald `footAsk` auf `.home-chat` wechselt,
   greift diese Regel nicht mehr und die Panele darf ihre volle, vom Nutzer einstellbare Größe
   zeigen. */
/* Zwei Ausnahmen von der Klemmung (2026-08-24, beide gemessen — das `!important` schlug die
   Inline-Höhe und machte den Absatz „Ziehgriff und Ecke bleiben BENUTZBAR" oben zur Hälfte
   unwahr): `[data-user-sized]` — der Nutzer hat die Ecke gezogen (`startResize`), dann gilt seine
   Größe (gemessen: gezogen auf 283 px, dargestellt 52 px, „lässt sich nur verbreitern") — und
   `.sz-full`, das Vollbild nach reinem Klick auf die Ecke (gemessen: 1400×52 statt 1400×900). */
/* Seit die Fläche ein Sofortbild ist (§43), sind die 52 px nicht mehr „die Karte selbst": die
   Fußzeile trägt jetzt oben `--pola-luft` und unten die breite `--pola-kante`. Gemessen mit den
   alten 52: die Zeile wollte 57 px und wurde auf 36 geklemmt, der Text lief unter die Unterkante.
   Die Höhe steht deshalb nicht mehr als Zahl da, sondern als dieselbe Rechnung: 3 (Panelrand 2 +
   obere Trennlinie der Fußzeile 1) + die Eingabezeile selbst (`--foot-h`) + die beiden Kanten. */
.panel.home.reco-open:not(.pinned):not(.sz-full):not([data-user-sized]){
  height:calc(3px + var(--foot-h) + var(--pola-luft, 12px) + var(--pola-kante, 12px)) !important; }
/* `.home-chat` (nach der ersten Frage): der Detailbereich bleibt für immer LEER — `appAns` schreibt
   nie in `.panel-body`, nur in die Karte (`.panel-foot`, s.u.). Der frühere Grund, ihr Fläche und
   Rahmen zu nehmen, war: Panele-Rahmen UND eine zweite, eingerückte Kartenoptik DARIN sahen wie
   zwei Kästen übereinander aus („ein Mix aus allem", 2026-08-09). Seit die Karte randlos die ganze
   Panele füllt (2026-08-24, s.u.), gibt es diese zwei Kästen nicht mehr — es bleibt einer, und der
   ist die Panele. Die Zeile ist deshalb entfallen. */
/* §30.19 — DIE EINGABE STEHT IM STROM, WO MAN HINGEKLICKT HAT (2026-08-01). Ein Klick in die leere
   Fläche unter der letzten Antwort holt DIESELBE eine Bedienleiste (`.pfoot`, §30.13) an das ENDE
   der Ausgabe, statt sie unten als Overlay aufgehen zu lassen: dort hat man hingesehen, und der
   getippte Satz steht damit an derselben Stelle wie die Antwort, auf die er sich bezieht.
   Der Platz (`.ps-in`) ist ein GESCHWISTER nach dem Ausgabekasten, nicht sein Kind: `.touch-out`
   wird im Ganzen ersetzt (`out.innerHTML=''` bei jedem Prompt (§30.14), `_resetFresh`,
   `setHTML(out,…)` beim Wiederherstellen) und im Board GESICHERT (`collectBoardCmds`) — als Kind
   wäre die Leiste beim nächsten Satz zerstört und als tote Kopie im gespeicherten Board wieder da.
   Damit sie trotzdem direkt unter der letzten Zeile sitzt, gibt der Ausgabekasten seine Restfläche
   her (`flex:0 0 auto`); sonst wächst er bis zum Panelboden und schöbe sie genau dorthin, wo die
   Fußzeile ohnehin schon war. Der leere Rest darunter bleibt antippbar (`.touch-body`/`.cmd-wrap`
   stehen in `LEER_SEL`). */
.ps-in{ flex:0 0 auto; padding:6px 0 2px; }
.panel.cmd .ps-in{ padding:6px 12px 2px; }
.panel.bar-in .ps-in > .pfoot{ position:static; left:auto; right:auto; bottom:auto;
  border-top:0; background:transparent; padding:0; min-height:var(--foot-res); display:flex; }
/* `display:flex` steht in BEIDEN Umzugs-Regeln, weil die allgemeine Fußzeile (`.panel-foot`, von
   `ensureFoot` gebaut) nur als DIREKTES Kind der Panele eingeblendet wird
   (`.panel.sz-panel > .panel-foot`). Sobald sie in den Kopf-Slot oder in den Strom zieht, greift
   dieses `>` nicht mehr — die Leiste war dann zwar am richtigen Platz, aber unsichtbar (gemessen
   2026-08-01 an der Journal-Panele: Höhe 0). Die Chat-/Kommando-Panelen fiel das nie auf, ihre
   Fußzeile heißt `.touch-foot`/`.cmd-foot` und hängt an anderen Regeln. */
/* Unten ist dann nichts mehr freizuhalten — die Fußzeile steht ja nicht mehr dort. */
.panel.touch.bar-in .touch-out{ flex:0 0 auto !important; padding-bottom:0; }
.panel.touch.bar-in .touch-body{ padding-bottom:0; }
.panel.cmd.bar-in .cmd-body{ flex:0 0 auto; padding-bottom:0; }
/* §Journal-Plus — derselbe Platz ein viertes Mal: MITTEN in der Liste, an der Stelle der Zeile
   „＋ Neuer Eintrag". Er braucht nur sein eigenes Polster — das seitliche hat der Detailbereich
   schon, und gescrollt wird ohnehin der Strom darüber (`.panel-body.ps`), nicht `.cmd-body`. */
.panel.cmd .ps-in.jr-in{ padding:2px 0 6px; }
/* Aktive Erst-Eingabe (nach Klick): mehrzeilig, linksbündig; die Höhe steuert grow() (bis zum Ausgabebereich).
   Oben ausgerichtet (justify-content via setView/activateInput) mit demselben Top-Offset wie .touch-out → beim Absenden springt der Text nicht (Eingabe- und Ausgabe-Bereich sind deckungsgleich). */
.panel.touch.ti-full .touch-inner{ padding-top:2px; }
.panel.touch.ti-full .touch-main{ text-align:left !important; }   /* linksbündig nach dem Senden (fett via Inline-Style, da font:inherit sonst gewinnt) */
/* HTML-Fragment (Tabelle/div/Liste …) in einer Antwort wird als HTML gerendert (sonst als Text). */
.panel.touch .touch-ans.html{ white-space:normal; }
.panel.touch .touch-ans.html table{ border-collapse:collapse; font-size:12px; margin:2px 0; }
.panel.touch .touch-ans.html th,.panel.touch .touch-ans.html td{ border:1px solid var(--line,#e5e7eb); padding:3px 7px; text-align:left; }
.panel.touch .touch-ans.html th{ background:rgba(148,163,184,.12); }
.panel.touch .touch-ans.html img{ max-width:100%; height:auto; }
/* Skill-Menü-Panel (☰): Skills des aktuellen Agenten als Kachel-Liste (gleiche Optik wie die Touch-Skills). */
.panel.skillmenu .sm-body{ height:100%; overflow-y:auto; padding:8px 6px; }
.panel.skillmenu .sm-head{ font-weight:600; font-size:var(--foot-fs); color:var(--muted,#6b7280); padding:2px 8px 6px; }
.panel.skillmenu .sm-empty{ padding:12px 10px; color:var(--muted,#6b7280); font-size:13px; }
.panel.skillmenu .ta-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(120px,1fr)); gap:2px; align-content:start; }
.panel.skillmenu .ta-tile{ display:flex; align-items:center; gap:7px; border:none; background:transparent; border-radius:8px;
  padding:5px 6px; cursor:pointer; font:inherit; text-align:left; box-sizing:border-box; min-width:0; }
.panel.skillmenu .ta-tile:hover{ background:rgba(148,163,184,.10); }
.panel.skillmenu .ta-ic{ flex:0 0 auto; width:26px; height:26px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-weight:700; font-size:12px; text-transform:uppercase; }
.panel.skillmenu .ta-txt{ min-width:0; display:flex; flex-direction:column; line-height:1.15; }
.panel.skillmenu .ta-name{ font-weight:600; font-size:var(--foot-fs); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.panel.skillmenu .ta-space{ font-size:calc(var(--foot-fs) - 2px); color:var(--muted,#6b7280); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cmd-body{ flex:1 1 auto; min-height:0; overflow:auto; padding:12px; padding-bottom:calc(var(--foot-res) + 8px); margin:0;
  font-size:12.5px; line-height:1.6; color:#1f2937; white-space:pre-wrap; word-break:break-word; }
.cmd-body.stream{ font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:11.5px; }
/* `.cmd-turn` („» Prompt") wird seit §30.20 nicht mehr ERZEUGT — der Lauf-Kopf ist überall
   `.turn-q`. Die Regel bleibt trotzdem stehen: in schon gespeicherten Verläufen (Board-Stand,
   Prompt-Ring) steckt das alte Markup noch, und ohne sie stünde es dort ungestylt da. */
.cmd-turn{ color:#0f172a; margin:8px 0 2px; padding:6px 10px; border-radius:8px; background:transparent; }
.cmd-turn:first-child{ margin-top:0; }
.cmd-toolline{ color:#b45309; } .cmd-errline{ color:#c0392b; }
/* Enthält die Antwort ein HTML-Fragment (Tabelle/div/…), wird es am Ende des Laufs als HTML gerendert. */
.cmd-ans.html{ white-space:normal; }
.cmd-ans.html table{ border-collapse:collapse; font-size:12px; margin:2px 0; }
.cmd-ans.html th,.cmd-ans.html td{ border:1px solid #e5e7eb; padding:3px 7px; text-align:left; }
.cmd-ans.html th{ background:#f8fafc; }
.cmd-ans.html img{ max-width:100%; height:auto; }
/* Datei-Verweis im Antworttext („Titel (datei.md)"): der Name ist ein Knopf, der die Datei in
   ihrer eigenen Panele oeffnet (board.js `docLinkify` → `openDoc`). */
.doc-ref{ border:0; background:transparent; color:var(--accent,#2563eb); font:inherit; padding:0;
  cursor:pointer; text-decoration:underline; text-underline-offset:2px; }
.doc-ref:hover{ text-decoration-thickness:2px; }
.cmd-body hr,.panel.touch .touch-ans hr{ display:none; }   /* keine Trennlinie in der Panel-Ausgabe (markdown --- → <hr>); .cmd-body deckt Stream-.cmd-ans UND Chat-Antwort-Div ab */
/* Laufzeit-/Token-Zeile unter der Antwort — läuft sekündlich mit (siehe setMeta), bleibt immer
   das letzte Element im Body (wird bei neuen Turns/Chunks re-angehängt), zeigt am Ende die
   Abschluss-Info (Laufzeit · Tokens · Tools). */
.cmd-meta{ margin-top:8px; font-size:11px; color:#94a3b8; font-variant-numeric:tabular-nums; }
/* Abschluss-Signal: grüner Haken am Ende eines fertigen (Stream-)Laufs, direkt im Verlauf. */
.cmd-done-mark{ margin:6px 0 2px; color:#16a34a; font-size:15px; font-weight:700; line-height:1; }
/* Agentname klein unter der Abschluss-Zeile. */
.cmd-meta-who{ margin-top:1px; font-size:9.5px; color:#94a3b8; opacity:.7; }
/* Eingabebox unter der letzten Antwort: Folge-Prompt in diesem Panel-Kontext (Antwort darüber bleibt sichtbar). */
.cmd-cont-box{ margin-top:12px; }
.cmd-cont-in{ width:100%; box-sizing:border-box; border:1px solid transparent; border-radius:14px; background:transparent;
  color:#0f172a; padding:6px 0; font:inherit; font-size:16px; font-weight:700; outline:none; resize:none; line-height:1.4; }
.cmd-cont-in::placeholder{ color:#94a3b8; }
.cmd-cont-in:focus{ border-color:transparent; }
/* Fußzeile: Overlay über dem Body (kein Flex-Sibling mehr) — der Body nimmt immer die volle
   Panelhöhe ein; die Fußzeile legt sich nur bei Bedarf (.controls-open) sichtbar darüber. */
.cmd-foot{ position:absolute; left:0; right:0; bottom:0; z-index:2; box-sizing:border-box; display:flex; align-items:center; gap:var(--foot-gap);
  padding:2px var(--foot-pad); background:transparent; min-height:var(--foot-res); }

/* === Kachel-Modus (1×1): Schlagwort aus dem Prompt (oben, groß) + Meta-Zeile
      „Symbol · Agent · Laufzeit" (unten, klein). Kein reguläres UI (Body/Fuß aus).
      Klick auf die Kachel → Panele (2×2). === */
.panel.cmd:not(.sz-panel):not(.sz-full):not(.sz-custom){ cursor:pointer; }
.panel.cmd:not(.sz-panel):not(.sz-full):not(.sz-custom) .cmd-body,
.panel.cmd:not(.sz-panel):not(.sz-full):not(.sz-custom) .cmd-foot{ display:none; }
.panel.cmd:not(.sz-panel):not(.sz-full):not(.sz-custom) .cmd-tile{ display:flex; }
/* Agent-Wahl (Kontaktliste) bzw. Skill-Liste im Kommando-Panel: Menü-/Skills-Icon der Aktionsleiste
   blendet sie an Stelle des Bodys ein (siehe .agents-open/.skills-open unten). */
.cmd-agents,.cmd-skills{ flex:1 1 auto; min-height:0; overflow-y:auto; padding:6px; }
.cmd-agents[hidden],.cmd-skills[hidden]{ display:none; }
.panel.cmd.agents-open .cmd-body,
.panel.cmd.skills-open .cmd-body{ display:none; }
.panel.cmd .ta-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(120px,1fr)); gap:2px; align-content:start; }
.panel.cmd .ta-tile{ display:flex; align-items:center; gap:7px; border:none; background:transparent; border-radius:8px;
  padding:6px 8px; cursor:pointer; text-align:left; font:inherit; color:var(--fg); }
.panel.cmd .ta-tile:hover{ background:rgba(148,163,184,.10); }
.panel.cmd .ta-tile.sel{ background:rgba(37,99,235,.10); }
.panel.cmd .ta-ic{ flex:0 0 auto; width:26px; height:26px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-weight:700; font-size:13px; }
.panel.cmd .ta-txt{ min-width:0; display:flex; flex-direction:column; line-height:1.15; }
.panel.cmd .ta-name{ font-weight:600; font-size:var(--foot-fs); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.panel.cmd .ta-tile.sel .ta-name{ color:#2563eb; }
.panel.cmd .ta-space{ font-size:calc(var(--foot-fs) - 2px); color:var(--muted,#6b7280); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cmd-tile{ display:none; flex-direction:column; height:100%; box-sizing:border-box; padding:8px; gap:5px; font-family:system-ui,-apple-system,sans-serif; }
/* Shortcut-Symbol (oben): kennzeichnet die Kachel als Verknüpfung zum letzten Prompt (Klick → aufziehen). */
.cmd-tile-cut{ flex:0 0 auto; font-size:13px; line-height:1; color:#2563eb; }
.panel.cmd.done .cmd-tile-cut{ color:#16a34a; }
.panel.cmd.err  .cmd-tile-cut{ color:#c0392b; }
/* Schlagwort (letzter Prompt): nimmt den Großteil der Kachel, mehrzeilig gekappt. */
.cmd-tile-kw{ flex:1 1 auto; min-height:0; overflow:hidden; font-size:12.5px; line-height:1.35; font-weight:600; color:#0f172a;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3; word-break:break-word; }
/* Meta-Zeile am Fuß der Kachel: Uhrzeit (links), Symbol (Status) mittig, Tokens rechts. */
.cmd-tile-meta{ flex:0 0 auto; display:flex; align-items:center; gap:5px; min-width:0; font-size:10.5px; color:#94a3b8; }
.cmd-tile-sym{ flex:0 0 auto; text-align:center; font-size:12px; line-height:1; color:#2563eb; }
.panel.cmd.done .cmd-tile-sym{ color:#16a34a; }
.panel.cmd.err  .cmd-tile-sym{ color:#c0392b; }
.cmd-tile-time{ flex:1 1 0; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-variant-numeric:tabular-nums; }
.cmd-tile-tok{ flex:1 1 0; min-width:0; text-align:right; font-variant-numeric:tabular-nums; }

/* === Touch-Panel Kachel-Modus (1×1): nur Icon + Schlagwort (KPI-artig), kein UI/keine Punkte/kein Ziehen. Klick → Panele. === */
.panel.touch .touch-tile{ display:none; }
.panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom){ cursor:pointer; }
.panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .touch-wrap{ display:none !important; }   /* Kachel-Modus: die absolut positionierte Wrap-Box nicht über die Kachel legen */
.panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .touch-body,
.panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .touch-foot{ display:none !important; }
.panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .panel-resize{ display:none !important; }
.panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .touch-tile{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px; height:100%; padding:8px; text-align:center; color:var(--fg); }
.panel.touch .touch-kw{ font-size:12px; font-weight:600; line-height:1.2; overflow:hidden; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3; }
.panel.touch .touch-tile-ic{ color:var(--muted,#6b7280); }
.panel.touch .touch-tile-ag{ display:none; }   /* Adressat in der Kachel: nur in der mobilen Panele-Liste (siehe @media) */

/* === User-Kachel (erste Kachel im User-Board: Personen-Icon + Name) === */
.panel.user{ grid-column:span 1; grid-row:span 1; }
.user-tile{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px; height:100%; box-sizing:border-box; padding:8px; text-align:center; font-family:system-ui,-apple-system,sans-serif; }
.ut-ic{ width:34px; height:34px; color:#2563eb; flex-shrink:0; }
.ut-ic svg{ width:100%; height:100%; }
.ut-name{ font-size:13px; font-weight:700; color:#0f172a; max-width:100%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* === Agenten-Kacheln (Kontaktliste: kontaktieren/wechseln) === */
.panel.agent{ grid-column:span 1; grid-row:span 1; cursor:pointer; }
.agent-tile{ display:flex; flex-direction:column; justify-content:center; gap:4px; height:100%; box-sizing:border-box; padding:6px 8px; font-family:system-ui,-apple-system,sans-serif; }
.at-name{ font-size:14px; font-weight:700; color:#0f172a; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.at-sub{ font-size:11px; color:#94a3b8; }
.panel.agent:hover{ box-shadow:0 2px 10px rgba(37,99,235,.25); }
/* Skill-Kommando: kein Folgethread → Fußzeile ganz aus (Icons sitzen oben rechts) */
.cmd-foot.noinput{ display:none; }

/* === KPI-Kacheln: zwei eigene Kacheln, je eine klickbare Kennzahl (Aktiv / Beendet) === */
.panel.kpi{ grid-column:span 1; grid-row:span 1; }
.kpi-tile{ display:flex; align-items:center; justify-content:space-around; gap:0; height:100%; box-sizing:border-box; padding:8px 6px; font-family:system-ui,-apple-system,sans-serif; }
.kpi-metric{ display:flex; flex-direction:column; align-items:center; gap:3px; flex:1 1 0; min-width:0; }
.kpi-metric+.kpi-metric{ border-left:1px solid #eef1f4; }
.kpi-val{ font-size:24px; font-weight:800; line-height:1; color:#0f172a; font-variant-numeric:tabular-nums; }
.kpi-label{ font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.04em; color:#94a3b8; }
.kpi-type{ font-size:13px; font-weight:500; color:#475569; letter-spacing:.01em; }   /* Objekt-Name (dritte Zeile, groß, nicht fett) */
.kpi-metric.on .kpi-val{ color:#2563eb; }      /* aktive Läufe > 0 → blau hervorgehoben */
.kpi-metric.kpi-hit{ cursor:pointer; border-radius:8px; transition:background .12s; }   /* Klick öffnet die Aufgabenliste / filtert die Detailliste */
.kpi-metric.kpi-hit:hover{ background:#f6f8fa; }
.kpi-metric.kpi-sel{ background:#eaf1ff; box-shadow:inset 0 0 0 2px #b9d0ff; }   /* aktiver Detail-Filter (Klick-Kennzahl) */

/* === Aufgaben-Panel: Liste der Aufgaben einer KPI-Kategorie (Klick auf „Aktiv"/„Beendet") === */
.hist-wrap{ display:flex; flex-direction:column; height:100%; box-sizing:border-box; font-family:system-ui,-apple-system,sans-serif; }
.hist-list{ flex:1 1 auto; min-height:0; overflow-y:auto; padding:4px 0; }
.hist-row{ display:flex; align-items:center; gap:8px; padding:8px 12px; cursor:pointer; border-bottom:1px solid #f5f6f8; }
.hist-row:hover{ background:#f6f8fa; }
.hist-label{ flex:1 1 auto; min-width:0; font-size:13px; color:#1f2937; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.hist-time{ flex:0 0 auto; font-size:11px; color:#9ca3af; font-variant-numeric:tabular-nums; }
.hist-ic{ flex:0 0 auto; font-size:12px; line-height:1; width:16px; text-align:center; }
.hist-ic.ok{ color:#16a34a; }
.hist-ic.bad{ color:#c0392b; }
.hist-empty{ padding:16px 12px; font-size:12.5px; color:#94a3b8; }
/* Stopp-Icon je aktiver Aufgabe (nur in der „Aktiv"-Liste): bricht den Lauf ohne Öffnen ab. */
.hist-stop{ flex:0 0 auto; border:none; background:transparent; color:#dc2626; width:24px; height:24px;
  border-radius:6px; cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; }
.hist-stop:hover{ background:#fde8e8; }
.hist-stop svg{ width:11px; height:11px; display:block; }

/* === Aufgaben-Board: je Task EINE Panele, die nur Prompt + Status zeigt ===
   Das Aufgaben-Board ist abgeleitet (Quelle = Task-Store des Servers), nicht gespeichert:
   Panele werden bei jedem Abgleich an die Task-Liste angeglichen (siehe paintTasks). */
.panel.task:not(.sz-full){ grid-column:1 / -1; grid-row:span 1; }
.panel.task{ cursor:pointer; }
/* Aufgaben-Board offen → nur Tasks (+ Ticket/Eingabe); die festen Board-Kacheln bleiben verborgen. */
#panel-grid.tasks-on > .panel:not(.task):not(.task-detail):not(.tnew){ display:none; }
.task-tile{ display:flex; align-items:center; gap:10px; height:100%; padding:8px 12px; box-sizing:border-box;
  font-family:system-ui,-apple-system,sans-serif; }
.task-st{ flex:0 0 auto; width:8px; height:8px; border-radius:50%; background:#cbd5e1; }
.task-st.run{ background:#2563eb; animation:task-pulse 1.2s ease-in-out infinite; }
.task-st.wait{ background:#f59e0b; }
.task-st.ok{ background:#16a34a; }
.task-st.bad{ background:#dc2626; }
@keyframes task-pulse{ 50%{ opacity:.3; } }
.task-prompt{ flex:1 1 auto; min-width:0; font-size:13.5px; color:#1f2937; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.task-meta{ flex:0 0 auto; font-size:11px; color:#9ca3af; }
/* Ticket-Detail: Original-Prompt UND die strukturierte Fassung des lokalen Agenten. */
.task-doc{ height:100%; overflow-y:auto; padding:12px 14px; box-sizing:border-box; font-family:system-ui,-apple-system,sans-serif; }
.task-doc h4{ margin:14px 0 4px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:#94a3b8; }
.task-doc h4:first-child{ margin-top:0; }
.task-doc p, .task-doc li{ margin:0 0 4px; font-size:13.5px; color:#1f2937; white-space:pre-wrap; }
.task-doc ol{ margin:0; padding-left:18px; }
.task-doc .task-orig{ color:#475569; }
.task-stop{ margin-top:14px; border:1px solid #fca5a5; border-radius:8px; background:transparent; color:#dc2626;
  font:inherit; font-weight:600; padding:6px 12px; cursor:pointer; }
/* Neuer Task: Eingabe-Panele des großen „+" (Prompt → lokaler Agent strukturiert). */
.tnew-wrap{ position:relative; display:flex; flex-direction:column; height:100%; box-sizing:border-box; }
.tnew-in{ flex:1 1 auto; min-height:0; border:none; outline:none; background:none; resize:none; padding:12px 14px;
  font:inherit; font-size:16px; color:#0f172a; line-height:1.4; }
.tnew-foot{ display:flex; align-items:center; gap:8px; padding:6px 10px; }
.tnew-say{ flex:1 1 auto; min-width:0; font-size:12px; color:#94a3b8; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.tnew-send{ flex:0 0 auto; border:none; border-radius:8px; background:#2563eb; color:#fff; font:inherit; font-weight:600;
  padding:7px 14px; cursor:pointer; }
.tnew-send[disabled]{ opacity:.5; cursor:default; }

/* Die Prompt-Eingabe-Kachel (`.prompt-input`/`.pi-*`) ist ENTFALLEN (2026-07-31): sie war ein
   zweites Eingabe-Fenster ohne Kopf, ohne Fußzeile und ohne ✕ neben der Chat-Panele. Eine
   Eingabe entsteht jetzt nur noch als Chat-Panele (`freshChat`). */

/* === App-Panele (eingebettete App als iframe) === */
.panel.app-panel .panel-body{ padding:0; overflow:hidden; }
.panel.app-panel iframe{ width:100%; height:100%; border:0; display:block; }
/* space.json `app_home`: runder Knopf unten links = zurück zum Board. Nur im Vollbild sichtbar
   (in Panele-Größe wäre er größer als die halbe Panele), und dort statt des ✕ oben rechts
   (Nutzerhinweis 2026-09-02: Kunden lesen das ✕ als „App schließen"). Dieselbe schwimmende Form
   wie der bis 2026-09-01 entfernte `.app-home` — der trug die Fußzeile, dieser den Rücksprung. */
.panel.app-panel > .app-home{ display:none; }
.panel.app-panel.sz-full > .app-home{ position:absolute; bottom:16px; left:16px; z-index:1302;
  width:52px; height:52px; border-radius:50%; border:none; background:#fff; padding:8px;
  box-shadow:0 2px 12px rgba(0,0,0,.28); cursor:pointer; box-sizing:border-box;
  display:flex; align-items:center; justify-content:center; }
.panel.app-panel.sz-full > .app-home:hover{ box-shadow:0 4px 16px rgba(0,0,0,.38); }
.panel.app-panel > .app-home img{ max-width:100%; max-height:100%; object-fit:contain; }
.panel.app-panel.app-home-on.sz-full > .p-x{ display:none; }
/* `ensureFoot()` ruft `psInit()` für JEDE Panele (auch App-Panele) und gibt dem Detailbereich
   die Klasse `.ps` — dafür gilt `.panel-body.ps > *{ height:auto !important }` (Chat-/Stream-
   Zeilen sollen ihre eigene Inhaltshöhe behalten). Ein App-Panel hat mehrere Geschwister
   (`.panel-title`, `iframe`), die `:only-child`-Ausnahme (`flex:1 0 auto`) greift also
   nie, und die Regel zwingt dem iframe `height:auto` auf — sichtbar als eingebettete App, die
   nur ihre intrinsische Standardgröße (~150 px) füllt, egal wie groß die Panele/das Vollbild
   ist. Höhere Spezifität + `!important` (dieselbe Priorität wie die Regel, die überschrieben
   wird) holt die volle Höhe zurück, ohne `.ps` von jeder Panele fernhalten zu müssen. */
.panel.app-panel .panel-body.ps > iframe{ height:100% !important; flex:1 1 auto; }
/* KEIN Overlay mehr über der App (2026-09-01, Nutzerwunsch „entferne diesen überall" und „ja
   pfeile entfernen"): die Leiste unten links (`.app-nav`, 2026-08-03) trug den runden Knopf
   (52 px, weiß, Schatten, blaues `RECO_SVG`) und die zwei 36-px-Blätter-Pfeile. Alle drei sind
   weg, mit ihnen die Regeln für `.app-focused` (nur die vordere App zeigte die Leiste) und für
   `.reco-open` (die Leiste wich der geöffneten Eingabe). `board.app_home` ist als Schalter aus
   `board_view.py`/`bauen.py` entfernt. Funktionen AN der App stehen dort, wo man ohnehin
   hinschaut: `⌄`/✕ am Panel selbst, Bug melden seit 2026-08-03 in der Eingabefläche. */
/* 2026-08-03 — DER RUNDE KNOPF VERWANDELT SICH IN DIE EINGABE, AN DERSELBEN STELLE, UND DIE
   ANTWORT STEHT IN DERSELBEN FLÄCHE (Nachzug: die Antwort stand zunächst in einer eigenen, engen
   Sprechblase über dem Knopf — der Nutzer wollte sie stattdessen IN der Eingabefläche selbst,
   die dafür auf Bildschirmbreite gehen und nach oben wachsen darf). Die generische Fußzeile ist
   sonst randlos über die volle Panelbreite (guter Standard für die üblichen, textlangen Panele) —
   hier wäre das ein zweites, andersartiges Bedienelement neben dem, das gerade verschwunden ist.
   Stattdessen bekommt sie dieselbe schwimmende Kartenform wie der frühere runde Knopf .app-home
   (weiß, rund, Schatten, unten links) — nur breiter und mit wachsender Höhe. Aufgemacht wird sie
   seit dem Ausbau dieses Knopfes (2026-09-01) wie bei jeder anderen Panele (Zugangsstreifen bzw.
   `⌄` → _openReco()); zu geht sie durch Danebenklicken/Fokusverlust (closeOnBlur, s. ensureFoot). Die :not(.bar-top):not(.bar-in)-Kette ist für
   App-Panele immer wahr (sie kennen diese Zustände nicht) — sie steht nur, damit dieser Override
   dieselbe Spezifität wie die generische Spalten-Regel erreicht und nicht gegen sie verliert; sie
   liefert dafür auch gleich das Richtige: Spalte statt Zeile (Antwort oben, Eingabe unten), Pfeil
   mittig UNTER der (mehrzeilig wachsenden) Eingabe statt seitlich daneben. */
.panel.app-panel.reco-open:not(.bar-top):not(.bar-in) > .panel-foot,
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) > .panel-foot,
.panel.home.reco-open:not(.bar-top):not(.bar-in) > .panel-foot{
  position:absolute; left:16px; right:16px; bottom:16px; top:auto; width:auto; min-height:52px;
  border-radius:20px; background:#fff; box-shadow:0 2px 12px rgba(0,0,0,.28); padding:10px 16px;
}
/* 2026-08-24 — .home/.home-chat: DIE KARTE IST DIE PANELE, nicht eine Karte in ihr.
   Bei .app-panel ist die Karte richtig unten verankert (`bottom:16px; top:auto`): darunter liegt
   eine echte App, die Karte schwimmt darüber und darf nur so hoch sein wie ihr Inhalt. Bei
   .home/.home-chat liegt darunter NICHTS — `.panel-body` bleibt für immer leer (`appAns` schreibt
   nur in die Karte). Die untere Verankerung hatte damit zwei gemessene Folgen (2026-08-24, echter
   Browser, Panele von 220×170 auf 532×482 gezogen): die Karte WANDERTE beim Vergrößern nach unten
   mit (Oberkante -342 → +243 px, weil sie der Unterkante der Panele unter dem Zeiger folgt) und
   sie SCHRUMPFTE dabei (502 → 229 px), weil ihre Höhe vom Inhalt kam und nicht von der Fläche.
   Vergrößern machte die Chat-Ausgabe also kleiner.
   Der Rand von 16 px fällt jetzt ganz weg (Nutzerwunsch: „die Box soll die ganze Panele
   einnehmen"). Mit ihm fallen Radius, Fläche und Schatten DER KARTE — sonst stünde ein zweiter
   Kasten randgenau im ersten. Weiß, Rahmen, Radius und Schatten kommen ab hier von der Panele
   selbst (`.panel`, §oben); die früheren `background:transparent !important`-Zeilen für
   `.home`/`.home-chat`, die genau das unterdrückten, sind deshalb entfallen. */
.panel.home.reco-open:not(.bar-top):not(.bar-in) > .panel-foot,
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) > .panel-foot{
  left:0; right:0; top:0; bottom:0; overflow:hidden;
  border-radius:0; background:transparent; box-shadow:none;
}
/* 2026-08-24 — die Knopfzeile `.pf-app-acts` (Vollbild ⇄ Panele · Bug melden · Schließen) ist
   ENTFALLEN, ihre Regeln mit ihr (Nutzerwunsch „entferne alle runden punkte inklusive bug"). Was
   sie konnte, steht weiter im ⋮-Weg der Kopfzeile (Gruppe „Panele"); der Bug-Knopf hat keinen
   Nachfolger — der Meldeweg selbst (`core/tickets/melden.py`) ist davon unberührt. */
/* Kurzantwort: nächster Eintrag der Fläche, wächst mit dem Text nach oben (die Karte ist unten
   verankert, bottom:16px bleibt fest — mehr Inhalt schiebt die Oberkante nach oben statt nach
   unten zu laufen). Sehr lange Antworten scrollen INNERHALB der Karte, statt sie über den halben
   Bildschirm wachsen zu lassen. :empty hält die Karte kompakt, solange noch nichts gefragt wurde
   (derselbe kleine Knopf-Ersatz wie zu Beginn dieser Funktion). */
.panel.app-panel .pfoot .pf-ans-block,
.panel.home-chat .pfoot .pf-ans-block{ max-height:45vh; overflow-y:auto; margin-bottom:8px;
  font-size:14px; line-height:1.5; color:#1e293b; }
.panel.app-panel .pfoot .pf-ans-block:empty,
.panel.home-chat .pfoot .pf-ans-block:empty{ display:none; margin-bottom:0; }
/* 2026-08-24 — in .home-chat nimmt die Antwort die ganze Karte. Die Karte ist dort (s.o.) eine
   Spalte ueber die volle Panelhoehe (`flex-direction:column; align-items:stretch`, §21-Block
   weiter unten), also faellt der Antwort die Restflaeche zu, waehrend Eingabe und Pfeil unten
   stehen bleiben. `max-height:45vh` muss dafuer weg: es ist die Kappung fuer eine Karte, die nach
   OBEN aus einem App-Panel herauswaechst — hier ist die Karte die Flaeche, und die Kappung machte
   sie in einer grossen Panele kleiner als das Fenster erlaubt. `min-height:0` ist die Bedingung
   dafuer, dass ein Flex-Kind ueberhaupt kleiner als sein Inhalt werden und damit scrollen darf. */
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-ans-block{
  flex:1 1 auto; min-height:0; max-height:none;
}
/* Und die Eingabe darf NICHT mitwachsen. `.pfoot .pf-reco-ta` ist `flex:1 1 auto` (weiter unten) —
   in der Zeile daneben richtig, in einer Spalte ueber die volle Panelhoehe falsch: gemessen teilte
   sie sich die Flaeche mit der Antwort und wurde bei einer kurzen Antwort 204 px hoch, waehrend die
   Antwort auf 212 px sass. Ihre Hoehe kommt von `grow()` in board.js (setzt `style.height` nach
   Inhalt, gekappt) — mit `flex:0 0 auto` gilt genau die, und die Restflaeche faellt der Antwort zu. */
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-reco-ta{ flex:0 0 auto; }
/* Gesendete Frage steht ALS TEIL der Antwort (Bubble-Optik: fett/gedeckt über der eigentlichen
   Antwort, keine zweite Fläche) — `appAns(panel, question, text)` baut beide als Kinder von
   `.pf-ans-block`. Gilt seit 2026-08-09 auch für `.home-chat` (Home-Punkt nach der ersten Frage,
   Nutzerwunsch „wie zuvor mit dem card": Antwort oben, Eingabe unten, statt des generischen
   Panel-Stroms). */
.panel.app-panel .pfoot .pf-ans-q,
.panel.home-chat .pfoot .pf-ans-q{ font-weight:600; color:#0f172a; margin-bottom:4px; }
.panel.app-panel .pfoot .pf-ans-a,
.panel.home-chat .pfoot .pf-ans-a{ color:#1e293b; }
/* §47 — DIE SCHRITTE STEHEN ZWISCHEN FRAGE UND ERGEBNIS und bleiben stehen, wenn das Ergebnis
   kommt (board.js `appAns(…, lauf)`): der Weg zur Antwort ist Teil der Antwort, keine Ladeanzeige.
   Solange nichts darin steht, ist die Zelle nicht da (`:empty`), sonst klaffte über jeder Antwort
   eine leere Zeile. Nach dem Ergebnis (`.fertig`) tritt sie zurück — sie ist dann Protokoll. */
.panel.app-panel .pfoot .pf-ans-lauf:empty,
.panel.home-chat .pfoot .pf-ans-lauf:empty{ display:none; }
.panel.app-panel .pfoot .pf-ans-lauf,
.panel.home-chat .pfoot .pf-ans-lauf{ margin-bottom:6px; }
.panel.app-panel .pfoot .pf-ans-lauf.fertig,
.panel.home-chat .pfoot .pf-ans-lauf.fertig{ opacity:.55; }
/* Die Vorschlagsliste (Skill `vorschlaege`) steht in der Ergebniszelle — minimalistisch: Zeichen,
   ein Wort, keine Kacheln. Dieselbe Klasse `.ps-list` wie im Aktions-Blatt, damit `actsFilter`
   und `actsEnter` sie ohne zweiten Mechanismus bedienen; nur die Optik ist hier schmaler. */
.pfoot .pf-ans-a .ps-list .ta-tile{ display:flex; align-items:center; border:0; background:transparent;
  border-radius:6px; font:inherit; text-align:left; cursor:pointer; color:#1e293b; }
.pfoot .pf-ans-a .ps-list .ta-tile:hover{ background:rgba(148,163,184,.14); }
.pfoot .pf-ans-a .ps-list .ta-ic{ flex:0 0 auto; width:20px; height:20px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; font-weight:700; font-size:11px;
  text-transform:uppercase; background:rgba(148,163,184,.18); color:#475569; }
.pfoot .pf-ans-a .ps-list .ta-txt{ min-width:0; display:flex; align-items:baseline; gap:6px; }
.pfoot .pf-ans-a .ps-list .ta-name{ font-size:13px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pfoot .pf-ans-a .ps-list .ta-space{ font-size:11px; color:var(--muted,#6b7280); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
/* §48 — TITEL UND INFOTEXT DER LISTE STEHEN HIER, NICHT IM PANEL. Das `<style>` eines Fragments
   ueberlebt DOMPurify nicht (gemessen 2026-08-30: Fragment 2 Stilbloecke → im Strom 0) — und diese
   Liste gibt es ohnehin nur im Antwortstrom: ihre Zeilen brauchen die Verdrahtung in board.js. */
.pfoot .pf-ans-a .vs-titel{ font-weight:600; color:#0f172a; margin:0 0 2px; }
.pfoot .pf-ans-a .vs-info{ font-size:12px; color:#64748b; margin:0 0 6px; cursor:pointer; }
.pfoot .pf-ans-a .vs-info-u{ margin:6px 0 0; }
.pfoot .pf-ans-a .vs-leer{ font-size:13px; color:#64748b; padding:4px 0; }
/* Das `⤢` oeffnet dieselbe Ansicht als eigene Vollbild-Panele (board.js, `[data-voll]`). Es steht
   IN der Zeile, nicht als Knopf daneben: `actsFilter` blendet `.ta-tile` aus, ein Geschwister
   bliebe beim Filtern allein stehen. */
.pfoot .pf-ans-a .ps-list .ta-voll{ margin-left:auto; flex:0 0 auto; padding:0 2px; font-size:12px;
  line-height:1; color:var(--muted,#94a3b8); opacity:.5; }
.pfoot .pf-ans-a .ps-list .ta-tile:hover .ta-voll{ opacity:1; color:#2563eb; }
/* Eingabe UND Antwort beginnen an derselben Kante (vorher lag die Eingabe 14px weiter innen,
   ihr eigenes `padding-left` aus der Basisregel `.pfoot .pf-reco-ta`) — „linksbündig wie die
   Antwort". Rechts bleibt Platz für den Senden-Pfeil, der hier (anders als der generische
   Standard, der ihn mittig UNTER die Box setzt) an der rechten Kante der Eingabe selbst steht,
   auf der letzten (untersten) Zeile verankert — dieselbe Stelle, an der er stand, bevor die
   Fläche zur Karte wurde. Schriftgröße gleicht der Antwort an (14px statt 15px), das Gewicht
   bleibt bewusst FETT (2026-08-03, Rücknahme des Angleichs an die Antwort auf Nutzerwunsch —
   die Eingabe darf sich vom eher normalgewichtigen Antworttext abheben). */
.panel.app-panel.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-reco-ta,
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-reco-ta,
.panel.home.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-reco-ta{ padding-left:0; padding-right:38px; font-size:14px; font-weight:600; }
.panel.app-panel .pfoot .pf-reco-ta::placeholder,
.panel.home-chat .pfoot .pf-reco-ta::placeholder,
.panel.home .pfoot .pf-reco-ta::placeholder{ font-weight:600; }
/* Höhere Spezifität als die generische Spalten-Regel nötig (`:not(.bar-top):not(.bar-in)` zählt
   doppelt, s.o.), sonst gewinnt dort weiter „Pfeil mittig unter der Box". */
.panel.app-panel.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-send,
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-send,
.panel.home.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-send,
.panel.app-panel.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-menu:not(.pf-rest),
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-menu:not(.pf-rest),
.panel.home.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-menu:not(.pf-rest){ position:absolute; right:0; bottom:var(--pf-send-b, 8px); margin:0; align-self:auto; }
/* `--pf-send-b` (2026-08-24, Nutzerwunsch „der senden pfeil soll in der höhe mittig sein mit der
   input box. aktuell ist er zu niedrig"): die Zahl kommt aus `sendMitte()` in board.js — die
   Eingabezeile ist das letzte Flex-Kind dieser Karte und hat eine vom Inhalt abhängige Höhe, der
   Pfeil hängt dagegen am Kartenfuß. Gemessen vorher: Mitte des Pfeils 4 px unter der Mitte des
   Feldes. Der Rückfallwert 8px ist der alte Stand — ohne Skript sitzt er wie bisher. */
/* Schlagworte (`<strong>`, aus „[Wort]" — core/agent/agent.py `_quick_reply`) sind anklickbar: ein
   Tipp sendet das Wort als Folgeprompt IN DIESEM Kontext (`footAsk`, dieselbe Route wie normal
   getippter Text — App-Panel UND Bug-Modus, `footAsk` verzweigt selbst). Blauer Akzent + Zeiger
   zeigen die Interaktivität an, dieselbe Farbe wie Sende-Pfeil/Fußzeilen-Chip. */
.panel.app-panel .pfoot .pf-ans-a strong{ cursor:pointer; color:#2563eb; }
.panel.app-panel .pfoot .pf-ans-a strong:hover{ text-decoration:underline; }

/* === Eck-Punkt ENTFALLEN (2026-08-24, Nutzerwunsch „alle runden Punkte-Optionen überall
   entfernen") === Er stand von 2026-08-08 bis heute unten links an jeder Panele (hover-sichtbar,
   Klick → `.corner-open`). Sein Markup wird in `chrome()` nicht mehr angelegt; die
   `:not(.corner-open)`-Ausnahmen weiter oben bleiben stehen — sie kosten nichts und die Klasse
   könnte über einen anderen Weg zurückkommen. */

/* === Universale Panel-Fußzeile (Touch-Footer-Layout als Basis) ===
   Jede Ausgabe-Panele ohne eigene (funktionale) Fußzeile bekommt diese identische
   Fußzeile mit Größen-/Schließen-Steuerung — so ist jede Panele eine „intelligente
   Notiz" (Ausgabe-Bereich + Fußzeile) und immer löschbar. NUR im Panele-/Custom-Modus,
   nicht als Kachel (1×1) und nicht im Vollbild. Buttons nutzen die vorhandene
   .panel-ctl-Delegation (data-act min/max/close) — kein eigener Handler. */
/* KEINE Trennlinie oben (2026-07-31): die Fußzeile gehört zur Panele, sie ist kein zweiter Kasten
   darin. Der Panelrahmen begrenzt sie schon, und der Chip/die Eingabe darin ist deutlich genug —
   die Linie zog quer durch jede Panele des Boards. Gilt für ALLE Fußzeilen-Regeln unten (Overlay,
   Vollbild mobil, Strom) und auch für die frühere blaue Linie des laufenden Panels. */
.panel-foot{ box-sizing:border-box; flex:0 0 auto; display:none; align-items:center; gap:var(--foot-gap);
  padding:2px var(--foot-pad); min-height:var(--foot-res); background:transparent; }
.panel.sz-panel > .panel-foot, .panel.sz-custom > .panel-foot,
.panel.sz-full > .panel-foot{ display:flex; }   /* jede aufgezogene Größe — nur die Kachel zeigt keine */
.panel-foot .pf-title{ display:flex; align-items:center; flex:0 1 auto; min-width:0; font-size:var(--foot-fs); font-weight:600;
  color:var(--muted,#6b7280); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; line-height:1; }
.panel-foot .pf-spacer{ flex:1 1 auto; }
.panel-foot .pf-ans{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  text-align:right; font-size:var(--foot-fs); color:#334155; }   /* Kompakt-Antwort der Prompt-Selektion (bleibt stehen) */
.panel-foot .pf-ans.pf-filter{ cursor:pointer; color:#1d4ed8; }   /* aktiver Filter: klickbar (ändern) */
.panel-foot .pf-clear{ flex:0 0 auto; border:0; background:transparent; color:#64748b; cursor:pointer;
  width:22px; height:22px; border-radius:6px; font-size:.8rem; line-height:1; padding:0; }   /* ✕ = Filter entfernen */
.panel-foot .pf-clear:hover{ background:#f3f4f6; color:#dc2626; }
.panel.reco-open > .panel-foot .pf-ans,
.panel.reco-open > .panel-foot .pf-clear{ display:none; }   /* beim Tippen des nächsten Prompts weicht beides der Eingabebox */

/* Aktive Verarbeitung (busy = laufender Skill/Chat/Touch): kein blauer Flächen-Hintergrund und
   seit 2026-07-31 auch keine blaue Trennlinie oben mehr — es gibt dort keine Linie mehr, die man
   einfärben könnte. Den Zustand trägt der Chip (`.panel.busy .pfoot .pf-status` blau + `•••`). */
.panel.busy .cmd-foot,
.panel.busy > .panel-foot,
.panel.busy .touch-foot{ background:transparent; }

/* === Launcher-Kacheln (Apps/Rollen): blaues Icon + Name, quadratisches Raster (wie das alte Dashboard) === */
#panel-grid.lt-grid{ grid-template-columns:repeat(auto-fill,minmax(130px,1fr)); grid-auto-rows:130px; }
#panel-grid.lt-grid .panel.sz-panel{ grid-column:span 2; grid-row:span 2; }
.lt-tile{ display:flex; flex-direction:column; align-items:center; justify-content:center; height:100%; box-sizing:border-box; padding:6px; text-align:center; font-family:system-ui,-apple-system,sans-serif; }
.lt-ic{ width:36px; height:36px; margin-bottom:8px; color:#2563eb; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.lt-ic svg{ width:28px; height:28px; }
/* Kachelname: die Schriftgröße folgt der LÄNGE des Namens (`fitTileName` unten setzt
   `--lt-fs`). Vorher stand hier eine feste Größe mit `line-clamp:2` — „Check-in /
   Check-out" und „Öffnungszeiten (TDA)" brachen damit mitten im Wort um und wurden am
   Ende abgeschnitten. Drei Zeilen sind erlaubt, weil eine 130px-Kachel sie trägt;
   `hyphens:auto` trennt an erlaubten Stellen statt irgendwo (`break-word` bleibt als
   Rückfall für Wörter ohne Trennstelle, z.B. lange Codes). */
.lt-name{ font-size:var(--lt-fs,.82rem); font-weight:600; line-height:1.25; hyphens:auto;
  overflow-wrap:break-word; color:#111; display:-webkit-box; -webkit-line-clamp:3;
  -webkit-box-orient:vertical; overflow:hidden; max-width:100%; }
.lt-sec{ font-size:.65rem; color:#9ca3af; text-transform:uppercase; letter-spacing:.03em; margin-top:3px; }
.panel.agent.lt-open{ box-shadow:0 0 0 2px #2563eb; }   /* Kachel deren App gerade offen ist */
.panel.agent.set-on{ box-shadow:inset 0 0 0 2px #2563eb; }   /* Einstellung aktiv (Toggle an) */
.panel.agent.set-on .lt-ic{ color:#2563eb; }
.panel.agent.set-on .lt-sec{ color:#2563eb; font-weight:700; }
/* Das CSS der Bereiche-Panele (`.panel.navbar`, `.nav-row`, `.nav-btn`, `.nav-lb`) ist mit ihr
   ENTFALLEN (2026-07-31) — siehe den Block im Skript. */
/* 2026-08-03 — Rollen-Wechsel/Konto als PANELE statt als eigene Kachel je Eintrag (Opt-in
   `board.compact_tiles`, s. `mountSwitch`/`mountAccount`): eine schlichte, eigens beschriebene
   Zeilenoptik statt der bestehenden `.ta-tile`-Familie — die hängt an `.panel.touch`/`.pf-acts`/
   `.panel.cmd`/`.panel.skillmenu` als Vorfahren (vier fast identische Kopien im CSS schon), eine
   fünfte für zwei kurze, feste Listen wäre dieselbe Vervielfältigung ohne eigenen Nutzen. */
.panel.rolepick .rp-row, .panel.acctpanel .rp-row{ display:flex; align-items:center; gap:10px;
  width:100%; border:none; background:transparent; border-radius:8px; padding:9px 8px;
  cursor:pointer; font:inherit; text-align:left; box-sizing:border-box; }
.panel.rolepick .rp-row:hover, .panel.acctpanel .rp-row:hover{ background:rgba(148,163,184,.10); }
.panel.rolepick .rp-ic, .panel.acctpanel .rp-ic{ flex:0 0 auto; width:30px; height:30px;
  border-radius:50%; background:rgba(37,99,235,.12); color:#2563eb; display:flex;
  align-items:center; justify-content:center; }
.panel.rolepick .rp-ic svg, .panel.acctpanel .rp-ic svg{ width:17px; height:17px; }
.panel.rolepick .rp-txt, .panel.acctpanel .rp-txt{ min-width:0; display:flex; flex-direction:column; line-height:1.2; }
.panel.rolepick .rp-name, .panel.acctpanel .rp-name{ font-weight:600; font-size:14px; color:#0f172a; }
.panel.rolepick .rp-note, .panel.acctpanel .rp-note{ font-size:12px; color:#6b7280; }
.panel.acctpanel .rp-row.rp-danger .rp-name{ color:#b91c1c; }
.panel.acctpanel .rp-row.rp-danger .rp-ic{ background:rgba(185,28,28,.10); color:#b91c1c; }
.panel.acctpanel .rp-info{ padding:9px 8px 4px; font-size:13px; font-weight:600; color:#0f172a; }
.panel.acctpanel .rp-info .rp-sub{ display:block; font-size:12px; font-weight:400; color:#6b7280; margin-top:2px; }
/* Logo-Panele (Launcher-Spaces): erste = Space-Logo, letzte = intec-Logo (je eine Kachel) */
.panel.logo-panel{ grid-column:span 1; grid-row:span 1; }
.panel.logo-panel.intec{ cursor:pointer; }
.panel.logo-panel.home{ cursor:pointer; }   /* Agent-Logo → zurück zum User-Assistenten */
.logo-tile{ display:flex; align-items:center; justify-content:center; height:100%; padding:6px; box-sizing:border-box; }
.logo-tile img{ max-width:100%; max-height:100%; object-fit:contain; }

/* Die STATISCHE AKTIONSLEISTE am Board-Fuß ist ENTFALLEN (2026-07-31, `#board-abar`). Sie war
   das letzte Bedienelement, das nicht zu einer Panele gehörte: eine Zeile, die am Handy immer
   Platz kostete und dabei Handlungen anbot, die es daneben schon gab — „Neu" = die Chat-Panele,
   „Skills"/„Aufgaben" = zwei Kacheln im ⋮-Blatt jeder Panele. Am Desktop war sie ohnehin nie
   sichtbar. Der Einstieg am Handy ist jetzt der Druck auf das leere Board: er bringt die
   Chat-Panele MIT ihren Kacheln (`freshChat` + `_onMenu`, board.html §28). Der einzige Inhalt
   der Leiste, den es sonst nirgends gab — der Board-Umschalter —, steht als Gruppe „Boards"
   in denselben Kacheln (`boardActs`). */

/* Mobil: Kachel = 1/3 Bildschirmbreite (3 Spalten fest, bis zu 3 Kacheln nebeneinander);
   Panele = 2 breit × 3 hoch (zwei Drittel Breite), Eingabe = volle Breite */
@media(max-width:640px){
  /* kleinere Kacheln, aber GRÖSSERE Fußzeilen-Elemente (Fingerbedienung). */
  :root{ --tile:96px; --foot-h:40px; --foot-btn:40px; --foot-fs:14px; --foot-gap:7px; --foot-pad:10px; --pf-tile:34px;
    --foot-rest:30px;     /* Ruhezustand auch am Handy schmaler als die Box — aber fingergerecht */
    --foot-tap:26px; }    /* §30.21 — der Zugangsstreifen muss mit dem FINGER zu treffen sein */
  /* Aktive (aufgezogene) Panele nehmen die volle Bildschirmbreite ein — über alle Spalten
     (1 / -1), unabhängig davon, wie viele Kacheln fitTiles pro Reihe berechnet. */
  /* Aufgezogene Panele nehmen auf dem Handy den vollen Tabellen-Screen ein:
     volle Breite (1 / -1) UND Tabellenhöhe (grid-row:span 7) — jede neue Panele
     füllt so den Bildschirm (wie die afsde-.wide-Listen). */
  .panel.sz-panel, .panel.sz-panel.afsde-tall{ grid-column:1 / -1; grid-row:span 7; }
  .panel.sz-custom{ grid-column:1 / -1 !important; grid-row:span 7 !important; }   /* Touch/Custom-Panele: volle Breite+Höhe (überschreibt inline grid-column/row span N) */
  /* `board.mobile_tiles` (bbkif): keine erzwungene Vollbild-Höhe (siehe `mobileWide()`/
     `addPanel`) — eine gewöhnliche Panele bleibt bei ihrer definierten Höhe (2 breit × 3 hoch,
     board.html:121), nur die Breite folgt hier wie überall dem Screen. Die `wide`/`half`/`tall`-
     Varianten sind von der Rücknahme ausgenommen: ihre 7 Zeilen SIND die definierte Höhe. */
  #board.mobile-wide .panel.sz-panel:not(.wide):not(.half):not(.tall):not(.afsde-tall){ grid-row:span 3; }
  /* Mobil gibt es keine freie Position: Listen-Layout, volle Breite. Die Pixel-Werte stehen inline
     (der Nutzer hat sie am Desktop gesetzt) — nur `!important` kommt dagegen an.
     `:not(.sz-full)` (2026-08-25): Vollbild IST eine feste Lage am Fenster
     (`.panel.sz-full{position:fixed !important; inset:0}`, Zeile oben). Beide Regeln tragen
     `!important` und dieselbe Spezifität — diese hier steht später im Blatt und gewann deshalb:
     eine am Desktop platzierte Panele fiel bei schmalem Schirm trotz `sz-full` in den Rasterfluss
     zurück und stand dort als 1×1-Kachel (gemessen 2026-08-25: 90×90 auf einem 390×844-Schirm).
     Gemeint war die Regel nie für sie, sondern für die Panele, die mobil im Fluss liegt. */
  .panel.positioned:not(.sz-full){ position:static !important; left:auto !important; top:auto !important;
    width:auto !important; height:auto !important; }
  /* Panele-Liste: nicht aufgezogene Tickets stehen als volle Zeile untereinander (Adressat ·
     Schlagwort) statt als Mini-Quadrat — die Kachelquadrate bleiben den festen Board-Rollen
     (Logo/Apps/KPI) vorbehalten. Aufgezogen ist ein Ticket weiterhin Vollbild (= Einzelpanel);
     zwischen beidem schaltet das Listen-/Einzel-Icon der Aktionsleiste. */
  .panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom),
  .panel.cmd:not(.sz-panel):not(.sz-full):not(.sz-custom){ grid-column:1 / -1; grid-row:span 1; }
  .panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .touch-tile{
    flex-direction:row; align-items:center; justify-content:flex-start; gap:10px; padding:8px 12px; text-align:left; }
  .panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .touch-kw{
    flex:1 1 auto; min-width:0; text-align:left; -webkit-line-clamp:2; }
  .panel.touch:not(.sz-panel):not(.sz-full):not(.sz-custom) .touch-tile-ag{
    display:block; flex:0 0 auto; max-width:38%; font-size:12px; font-weight:700; color:#2563eb;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .panel-move{ display:none !important; }   /* freies Verschieben ist ein Desktop-Feature (Raster erzwingt hier volle Breite) */
  /* Panel-Chrome komplett aus: Größe/Schließen laufen mobil AUSSCHLIESSLICH über die Aktionen
     der Panele (`⋮` → Gruppe „Panele") — kein Ziehen, keine Ecken-Hotspots, keine Steuer-Icons. */
  .panel-resize{ display:none !important; }
  .panel-title{ display:none !important; }
  /* Die Fußzeile am Handy trägt NUR den Agentennamen. Ein Klick darauf macht daraus die Eingabe.
     Das `☰` IM Chip soll hier ausgeblendet sein: auf einem Bildschirm, auf dem genau EINE Panele
     liegt, ist die Fußzeile die einzige ruhige Zeile — zwei Zeichen darin sind eines zu viel; die
     Aktionen stehen am Handy als Kacheln IM Strom (`psActs`, erste Ausgabe der Home-Panele).
     ACHTUNG, diese Regel WIRKT NICHT (gemessen am 2026-07-31 bei 390 px: der Kreis steht da):
     `.pfoot .pf-send, .pfoot .pf-menu{display:inline-flex}` steht weiter unten im Blatt, hat
     dieselbe Spezifität (0-2-0) und schlägt sie deshalb im Kaskaden-Rang — ein Media Query hat
     keinen Vorrang, er ist nur eine Bedingung. Das gilt, seit der Kreis `pf-menu` trägt, und ist
     unabhängig davon, dass er jetzt IM Chip sitzt. Hier NICHT einfach repariert: „am Handy nur der
     Name" ist eine Entscheidung über die Bedienung, keine Formatfrage — sie gehört bestätigt,
     bevor ein Bedienelement verschwindet, das es dort seit Wochen gibt. */
  .pfoot .pf-rest{ display:none; }
  /* Kein Punkt-Raster am Handy: es ist die Textur eines Blackboards, auf dem Panelen nebeneinander
     liegen — dort liegt aber genau EINE, im Vollbild. Sichtbar wäre das Muster nur in den Momenten
     dazwischen, und dann als Rauschen hinter einer weißen Fläche. Einfach Weiß. */
  #board{ background-image:none; background-color:#fff; }
  #board.board-dark{ background-color:#0b1220; }
  .board-wm{ display:none; }   /* auch das Wasserzeichen: es gehört zur leeren Fläche, die es hier nicht gibt */
  /* Mobil rahmenlos: kein grauer Rahmen, kein Schatten und kein dunkler Ring am aktiven Panel —
     die weiße Fläche grenzt sich allein gegen das Board ab (Rahmenbreite bleibt als transparente
     1px-Linie stehen, damit sich am Innenmaß nichts verschiebt). Der Schalter `frame=aus`
     (`#board.noframe`, board.js:320) braucht hier keine eigene Zeile mehr: mobil ist rahmenlos
     der einzige Zustand. */
  .panel:not(.sz-full), .panel.active:not(.sz-full){ border-color:transparent; box-shadow:none; }
  /* Aufgezogene Panele sind mobil immer Vollbild (applySize/isMobile) — dort zusätzlich ohne
     Radius/Abdunkelung, damit die Panele den Bildschirm rahmenlos füllt. Weil Vollbild mobil der
     normale Offen-Zustand ist, bleibt die Fußzeile (Chip/Eingabe) sichtbar — anders als am Desktop,
     wo Vollbild bewusst fußzeilenlos ist (board.html:69). Vollbild heißt seit dem Entfall der
     Aktionsleiste wieder GANZER Bildschirm — vorher blieb unten ihr Streifen frei. */
  .panel.sz-full, .panel.sz-full.active{ border-radius:0; box-shadow:none !important; }
  .panel.sz-full > .panel-foot{ display:flex !important; }
  /* ---- Mobil: die Fußzeile steht UNTEN, der Strom scrollt dahinter --------------------------
     Eine Regel für JEDE Panele. Vorher galt sie nur für die generische `.panel-foot`, und die
     Body-Freihaltung nahm `.cmd` und `.touch` ausdrücklich AUS — also genau die Chat-/Home-Panele:
     deren Fußzeile hing am `.touch-wrap` statt am Panel, und ihr Körper reservierte unten keinen
     Platz. Zusammen mit dem Titel-Eintrag darüber ging die Rechnung nicht mehr auf — die Zeile saß
     schief und das Ende des Inhalts lag darunter.
     Damit die Fußzeile am PANEL hängt (und nicht am Wrap), verliert dieser mobil seinen
     Positions-Anker; das Panel ist ohnehin `position:fixed` und damit der Bezug. */
  .panel.sz-full .touch-wrap, .panel.sz-full .cmd-wrap{ position:static; }
  .panel.sz-full .pfoot{
    position:absolute; left:0; right:0; bottom:0; z-index:6;
    background:#fff; border-top:1px solid #e5e7eb; }
  #board.board-dark .panel.sz-full .pfoot{ background:#0f172a; border-top-color:#1e293b; }
  /* Der Körper nimmt die volle Höhe und scrollt; unten bleibt genau die Fußzeilenhöhe frei, damit
     der letzte Eintrag nicht darunter liegt. */
  .panel.sz-full > .panel-body{ overflow-y:auto; padding-bottom:calc(var(--foot-res) + 10px) !important; }
  .panel.sz-full .touch-body, .panel.sz-full .touch-out{ overflow:visible; }
  .panel.sz-panel > .panel-foot{
    position:absolute; left:0; right:0; bottom:0; z-index:5; }
  .panel:not(.cmd):not(.touch).sz-panel > .panel-body{ padding-bottom:calc(var(--foot-res) + 8px); }
  /* §40 — AM HANDY STEHT DIE EINGABE AM UNTEREN RAND, DIE AUSGABE BEKOMMT DEN REST (2026-08-25).
     Gemessen im echten Browser (390×844, `/user`): die Eingabezeile der Einstiegsfläche war 823 px
     hoch, also der GANZE Bildschirm. Zwei Regeln treffen sich dort, die einzeln richtig sind: die
     Karte füllt am Handy die ganze Panele (`.home/.home-chat.reco-open > .panel-foot{inset:0}`,
     §oben — die Panele IST die Karte), und die Box darin ist `flex:1 1 auto` (Basisregel `.pfoot
     .pf-reco-ta`, gedacht für die Zeile NEBEN dem Chip). In einer Spalte über den ganzen Schirm
     heißt das: die Eingabe nimmt alles. `grow()` schrieb dieses Maß danach als Inline-Höhe fest —
     `ta.style.height='auto'` nimmt einer Flex-Box das Wachsen nicht, ihr `scrollHeight` ist dann
     die Flex-Höhe (gemessen 804 px = `panel.clientHeight-40`, der Deckel) —, und nach der ersten
     Antwort blieben dem Ausgabeblock 4 px: die Fläche zum LESEN war weg, die zum TIPPEN war alles.
     Deshalb hier: die Box ist so hoch wie ihr Inhalt (`flex:0 0 auto`, Höhe aus `grow()`) und wird
     an den unteren Rand geschoben (`margin-top:auto`); die Antwort bekommt die Restfläche.
     NUR am Handy: am Desktop ist dieselbe Karte ~170 px hoch (`HOME_H`), und eine Box, die sie
     füllt, IST dort die Einstiegszeile — nicht dasselbe Bild, dieselbe Regel. */
  .panel.home.reco-open .pfoot .pf-reco-ta,
  .panel.home-chat.reco-open .pfoot .pf-reco-ta{ flex:0 0 auto; margin-top:auto; }
  .panel.home-chat.reco-open .pfoot .pf-ans-block{ flex:1 1 auto; min-height:0; max-height:none; }
  /* Mobile Browser zoomen beim Fokus automatisch in Eingabefelder mit weniger als 16px Schrift —
     mit 16px bleibt die Seite unverändert und die Eingabe steht sofort an der richtigen Stelle. */
  .pfoot .pf-reco-ta{ font-size:16px; }
  /* App-Ansicht mobil: immer genau 3 Kacheln pro Reihe (auto-fill über minmax(120px,…) ergäbe auf
     schmalen Geräten nur 2). Wie viele Reihen sichtbar sind, sagt die Panelhöhe — nicht mehr eine
     Kappung auf drei (`capAppRows` ist entfallen, siehe renderSkills). */
  /* Seiten-Steuerung offen → kein leerer Bereich unter der (immer letzten) Nav-Panele:
     die sonst als Zieh-Headroom reservierte 3-Kachel-Bodenfreiheit auf Mobil entfernen. */
  #panel-grid.pagectl-open{ padding-bottom:var(--tile-gap); }
}

/* ===================================================================
   EINHEITLICHE PANEL-CHROME — eine identische Fußzeile für ALLE Panele.
   ------------------------------------------------------------------
   Ruhezustand: nur eine Statuszeile (Panel-/Agentname bzw. Laufzeit).
   Klick auf die Fußzeilen-Fläche → .controls-open am Panel: Aktionsleiste
   (✏ Chat · 🔍 Filter · − · ⤢ · ✕) UND Kopfzeile erscheinen GEMEINSAM.
   Klick in den Body blendet beide wieder aus.
   Alle drei Fußzeilentypen (.panel-foot, .cmd-foot, .touch-foot) tragen
   zusätzlich die Klasse .pfoot und teilen sich diese Regeln.
   =================================================================== */
/* Ruhezustand (auch busy): Fußzeile bleibt unsichtbar (keine Linie, keine Statuszeile) — nur die
   Klickfläche (min-height der jeweiligen *-foot-Regel) bleibt bestehen. Erst ein Klick öffnet
   Kopf- + Fußzeile gemeinsam (.controls-open); die Fußzeile zeigt dann die Aktionsleiste (Linie
   siehe unten). Laufzeit/Tokens laufender Panele stehen stattdessen live im Body (siehe setMeta). */
/* Die Fußzeile liegt als Overlay über dem Inhalt, ist aber NUR dort greifbar, wo etwas steht:
   der Streifen selbst lässt Tipp-/Klickereignisse durch (pointer-events:none), erst seine
   Elemente (Chip, Eingabe, Lauf-Steuerung) fangen sie wieder ab. Ohne das würde der Streifen
   die untersten ~40px des Detailbereichs blockieren. */
/* Fußzeile: Agentname LINKS, ⋮ rechts — an jeder Panele gleich (Chat-, Lauf-, Objekt-Panele).
   Vorher stand der Chip mittig und nur `foot_chat`-Boards zogen ihn per `.pf-left` nach links;
   damit lag derselbe Name je Panele an einer anderen Stelle. */
.pfoot{ position:relative; justify-content:flex-start; pointer-events:none; }
.pfoot > *{ pointer-events:auto; }
/* Chip (immer sichtbar, mittig): Agentname · Prozessierungszeit. Die vorhandenen Slots
   (.pf-title/.cmd-agent/.touch-agent) tragen zusätzlich .pf-status. Klick → Eingabemodus
   (.pf-reco-ta). Es gibt keine Aktionsleiste (☰/▦) mehr — der Chip ist die einzige Fußzeilen-Bedienung. */
/* Der Chip ist eine geschlossene Pille mit Rahmen (2026-07-31): weiße Fläche, dünne Linie, kein
   Schatten. Vorher lief er nach RECHTS und LINKS per Verlauf in den Hintergrund aus (transparente
   Enden) — das vermied sichtbare Pillen-Kanten, ließ das Textlabel an den Rändern aber
   halbdurchsichtig auf dem Inhalt liegen. Der Rahmen sagt jetzt, wo der Chip aufhört; deshalb
   braucht die Fläche keine weichen Enden mehr und ist durchgehend deckend. */
/* Der Chip nimmt die GANZE Breite der Fußzeile (2026-07-31) — genau wie die Eingabebox, die an
   seiner Stelle aufgeht (`.pf-reco-ta`, ebenfalls `flex:1 1 auto`). Vorher schrumpfte er auf seinen
   Text (`flex:0 0 auto`, `max-width:80%`): derselbe Griff hatte je nach Länge des Agentnamens eine
   andere Größe, und der Wechsel Name ⇄ Eingabe sprang in der Breite. `min-width:0` gehört dazu,
   sonst kann ein langer Name die Fußzeile aufblasen (Flex-Grundbreite = Inhalt). */
.panel .pfoot .pf-status{ display:inline-flex; align-items:center; justify-content:flex-start; flex:1 1 auto; min-width:0; max-width:none;
  margin:0; height:var(--foot-res); box-sizing:border-box; padding:0 12px 0 2px; cursor:pointer;
  background:#fff; border:1px solid #e5e7eb;
  border-radius:999px; box-shadow:none;
  font-size:var(--foot-fs); font-weight:600; color:#64748b; line-height:1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pfoot .pf-status:hover{ color:#0f172a; }
/* `.pf-left` bleibt als Klasse bestehen (foot_chat setzt sie), ist aber kein Sonderfall mehr —
   linksbündig ist jetzt der Normalzustand jeder Fußzeile. */
.pfoot .pf-status.pf-left{ margin:0 auto 0 0; }
/* Flüchtiges Antwort-Overlay (footAsk): kurze Info zur Panele, blendet nach Lesezeit aus. */
/* === Standard-Tabellen (core/agent/skills/table.py): EIN Tabellen-Objekt für alle Listen-Panele.
   Fußzeilen-Box filtert (foot_chat), Spaltenkopf sortiert, Zeile → Detail-Panel, mobil Kacheln. */
table.std-tbl{ width:100%; border-collapse:collapse; font-size:.9rem; }
table.std-tbl th.std-th{ padding:8px 10px; text-align:left; color:#64748b; font-weight:600; font-size:.8rem;
  border-bottom:1px solid #e5e7eb; cursor:pointer; user-select:none; white-space:nowrap;
  position:sticky; top:0; background:#fff; z-index:1; }
table.std-tbl th.std-th:hover{ color:#0f172a; }
table.std-tbl th.std-asc .std-dir::after{ content:'▲'; margin-left:4px; font-size:.7em; }
table.std-tbl th.std-desc .std-dir::after{ content:'▼'; margin-left:4px; font-size:.7em; }
table.std-tbl tbody td{ padding:8px 10px; border-bottom:1px solid #eef1f4; color:#334155; }
table.std-tbl tbody tr[data-row]{ cursor:pointer; }
table.std-tbl tbody tr[data-row]:hover{ background:#f8fafc; }
/* Mobil: Tabellenzeilen als Kacheln (Spaltenlabel aus data-label, Wert rechts). */
@media (max-width:640px){
  table.std-tbl{ display:block; width:100%; }
  table.std-tbl thead{ display:none; }
  table.std-tbl tbody{ display:block; }
  table.std-tbl tr{ display:block; }
  table.std-tbl tbody tr[data-row]{ margin:0 0 10px; padding:6px 12px; border:1px solid #e5e7eb;
    border-radius:12px; background:#fff; box-shadow:0 1px 2px rgba(15,23,42,.06); }
  table.std-tbl tbody tr[data-row] td{ display:flex; align-items:baseline; justify-content:space-between;
    gap:14px; padding:6px 0!important; border-bottom:1px solid #f1f5f9!important; background:none!important;
    max-width:none!important; white-space:normal!important; overflow:visible!important;
    text-overflow:clip!important; text-align:right; }
  table.std-tbl tbody tr[data-row] td:last-child{ border-bottom:0!important; }
  table.std-tbl tbody tr[data-row] td::before{ content:attr(data-label); flex:0 0 auto; text-align:left;
    color:#94a3b8; font-size:.7rem; font-weight:700; text-transform:uppercase; letter-spacing:.03em; }
}
/* Zeilen-Detail-Panel (Klick auf eine Standard-Tabellenzeile): Label → Wert. */
.std-detail{ font-family:system-ui; font-size:.9rem; padding:12px 14px; overflow:auto; height:100%; box-sizing:border-box; }
.std-detail .sd-head{ display:flex; align-items:center; gap:10px; font-weight:700; margin-bottom:10px; color:#0f172a; }
.std-detail .sd-ti{ flex:1 1 auto; min-width:0; }
.std-detail .sd-row{ display:flex; gap:14px; padding:7px 0; border-bottom:1px solid #f1f5f9; align-items:baseline; }
.std-detail .sd-k{ flex:0 0 32%; color:#94a3b8; font-size:.75rem; font-weight:700; text-transform:uppercase; letter-spacing:.03em; }
.std-detail .sd-v{ flex:1; min-width:0; color:#0f172a; word-break:break-word; }
/* `⌄` oben rechts = EINE Ebene zurück (aus dem Detail in die Liste, aus der es kam) — im
   Unterschied zu `✕`, das die Sache wegnimmt. Ein Zeichen, eine Bedeutung, überall: eine
   Strom-Panele trägt es als Symbol ihrer Aktion „Zurück zum Strom" (Panele-Gruppe des `⋮`,
   `_viewActs`) — seit ihre Kopfzeile der gemeinsamen Fußzeile gewichen ist.
   (`.str-back` darin ist Altbestand ohne Nutzer — nicht von hier aus entfernt.) */
.sd-back, .str-back{ flex:0 0 auto; width:26px; height:26px; padding:0; border:0; border-radius:8px;
  background:transparent; color:#64748b; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; }
.sd-back:hover, .str-back:hover{ background:#f1f5f9; color:#0f172a; }
.sd-back svg, .str-back svg{ width:18px; height:18px; }
/* §41 — auch dieser Rückweg steht IM FLUSS (erstes Kind der `.sd-head`, `board.js:2234` — links
   vom Titel wie überall sonst). Er bleibt, wo er ist — verschöbe man ihn in die Leiste, verlöre er den
   Bezug zu seiner Zeile (drei verschiedene Handler je Herkunft, `board.js:2259/2265/2272`).
   Abgezogen werden die 14px, die `.std-detail` als eigenen Rand schon mitbringt. */
.panel .std-detail > .sd-head{ padding-right:max(0px, calc(var(--p-corner, 14px) - 14px)); }
/* ===== Der Panel-Stream: die Basis jeder Panele (2026-07-31) ==================================
   Eine Panele ist ein SCOPE, und ihr Detailbereich ist der Verlauf dieses Scopes. Darin stehen
   drei Arten von Einträgen, alle in einer Spalte, alle scrollend:
     (Eine Titelzeile gibt es nicht: der Name steht im Fußzeilen-Chip.)
     `.ps-obj`  — ein Objekt des Scopes (Tabelle, Ergebnis, Datei …). Zwei Größen: `voll` (füllt
                  die Panele) und `tile` (kleine Kachel im Fluss). Antippen schaltet um.
     `.ps-msg`  — eine Zeile der Unterhaltung (`me` = vom Nutzer).
   Vorher gab es dafür zwei getrennte Zustände: Inhalt ODER Chat (`.pf-chat`, Inhalt lag beiseite,
   `⌄` holte ihn zurück). Ein Scope kann aber mehrere Objekte tragen, und ein Gespräch DARÜBER ist
   kein anderer Modus — es ist derselbe Strom. */
/* Bei OFFENER Eingabe gehört die Fußzeile UNTEN ihr allein: alles andere weicht, damit die
   abgerundete Box die volle Breite hat. Sie war zuletzt an den rechten Rand gedrängt, weil daneben
   noch etwas stand (Chip, ☰, Nummer, Antwort-Slot …). Statt jedes Einzelteil zu verstecken — und
   das nächste zu übersehen — weicht hier ALLES außer Box und Senden-Pfeil.
   Das gilt seit 2026-08-01 auch OBEN im Kopf der Liste (die Ausnahme `:not(.bar-top)` ist weg):
   dort ist der Chip der Ruhezustand und die Box der geöffnete Modus — genau wie unten.
   §47 (2026-08-30): `:not(.pf-menu)` kam dazu. Das Menü-Zeichen ist kein Einzelteil NEBEN der Box,
   sondern der Ruhezustand DES Senden-Platzes — leer zeigt er das Menü, getippt den Pfeil
   (`syncSend` in board.js). Es hier mitzuverstecken hieße, den Platz im Ruhezustand leer zu lassen.
   Der Ruhe-Kreis der Fußzeile trägt dieselbe Klasse (`pf-menu pf-rest`) und bleibt trotzdem weg:
   `.reco-open .pf-rest{display:none}` steht weiter unten im Blatt und schlägt bei gleicher
   Spezifität die Anzeige-Regel. */
.panel.reco-open > .panel-foot > :not(.pf-reco-ta):not(.pf-send):not(.pf-menu):not(.pf-ans-block),
.panel.reco-open .touch-foot > :not(.pf-reco-ta):not(.pf-send):not(.pf-menu):not(.pf-ans-block),
.panel.reco-open .cmd-foot > :not(.pf-reco-ta):not(.pf-send):not(.pf-menu):not(.pf-ans-block){ display:none !important; }
.pfoot .pf-reco-ta{ flex:1 1 auto; width:100%; }
/* Die Fußzeile zeigt im Ruhezustand NUR den Agentennamen — ein Klick darauf macht daraus die
   Eingabebox (`.pf-status` → `_openReco`). Die Panel-Nummer stand daneben; sie ist die Adresse,
   unter der der Assistent eine Panele anspricht („Panele 3"). Sichtbar war sie ein zweites
   Zeichen in einer Zeile, die ruhig sein soll — sie bleibt im DOM (und `p._num` bleibt die
   Adresse), wird aber nicht mehr angezeigt. Wer sie braucht, fragt den Assistenten. */
.pfoot .panel-num{ display:none; }
/* Der Detailbereich reicht vom Kopf bis GANZ nach unten: die Fußzeile liegt als STABILE Zeile
   darüber (sie scrollt nicht mit), der Strom scrollt dahinter. Vorher belegte die Fußzeile eine
   eigene Rasterzeile — der Strom bekam nur den Rest, und bei kleinen Panelen war das fast nichts.
   Das galt mobil schon; hier gilt es überall, damit eine Panele sich nicht je nach Gerät anders
   aufteilt. `.touch-wrap`/`.cmd-wrap` verlieren dafür ihren Positions-Anker: die Fußzeile hängt
   am PANEL, nicht an einem Kasten darin. */
/* `.panel.touch .touch-wrap` muss AUSDRÜCKLICH dastehen: die Regel weiter oben (Zeile 236) setzt
   `position:relative` mit höherer Spezifität und hat die Fußzeile trotz dieser Zeile weiter am
   WRAP verankert (gemessen auf `/claude`: `offsetParent` der `.touch-foot` = `.touch-wrap`, Wrap
   235 px, Fußzeile 46 px über dem Panelboden). Solange sie dort hängt, MUSS der Wrap die Resthöhe
   nehmen, damit die Eingabe unten steht — genau das war die halbe leere Panele zwischen Kachel
   und Chat. Am Panel verankert, steht die Eingabe unten, egal wie hoch der Wrap ist. */
.panel .touch-wrap, .panel.touch .touch-wrap, .panel .cmd-wrap{ position:static; }
.panel.sz-panel > .panel-foot, .panel.sz-custom > .panel-foot,
.panel.sz-full > .panel-foot, .panel .touch-foot, .panel .cmd-foot{
  position:absolute; left:0; right:0; bottom:0; z-index:6;
  /* Als Overlay braucht sie einen DECKENDEN Grund — sonst scrollt der Strom sichtbar dahinter
     durch. Die Trennlinie oben ist zurück (2026-08-02, Rücknahme des 2026-07-31-Entfalls): eine
     leichte Linie statt eines Rahmens um die Eingabe selbst — siehe `.pfoot .pf-reco-ta`. */
  background:#fff; border-top:1px solid #e5e7eb; }
#board.board-dark .panel.sz-panel > .panel-foot, #board.board-dark .panel.sz-custom > .panel-foot,
#board.board-dark .panel.sz-full > .panel-foot,
#board.board-dark .panel .touch-foot, #board.board-dark .panel .cmd-foot{
  background:#0f172a; border-top-color:#1e293b; }
.panel > .panel-body.ps{ padding-bottom:calc(var(--foot-res) + 10px); }
/* Der Strom SCROLLT — er ist die Detailsicht, und die ist länger als der Schirm. Die Regel steht
   bewusst nach `.panel.touch > .panel-body{overflow:hidden}` (gleiche Spezifität, später gewinnt):
   dort war „nicht scrollen" richtig, solange der Körper nur einen Wrap trug, der sich selbst
   kümmerte. Innere Scroll-Flächen werden dafür stillgelegt — zwei ineinander scrollende Kästen
   sind der Grund, warum man mit dem Finger mal das eine und mal das andere erwischt. */
.panel > .panel-body.ps{ display:flex; flex-direction:column; gap:10px; padding:0 0 10px; overflow-y:auto; }
/* App-Panele: das iframe füllt die Panele, es gibt keinen Strom darunter, für den 10px Luft
   nötig wären. `.panel.app-panel .panel-body{padding:0}` weiter oben verliert gegen die Zeile
   darüber (gleiche Spezifität, später gewinnt) — die Folge war ein WEISSER STREIFEN am unteren
   Rand JEDER App-Panele: gemessen Panele 900, iframe 890 (bbkif-Avatar über die Kachel geöffnet,
   2026-08-06). Betraf alle iframe-Apps, nicht nur diese. */
.panel.app-panel > .panel-body.ps{ padding:0; }
/* §35 (Rücknahme der 2026-08-03-Sonderregel) — Liste (`.ps-acts`) und Chat (`.touch-wrap`) sind
   wieder zwei gewöhnliche Einträge DESSELBEN Stroms, kein Zwischenraum-Sonderfall mehr: sie
   teilen sich das allgemeine `gap:10px` wie jede andere Kind-Abfolge in `.panel-body.ps`. Die
   negative Marge, die die Lücke bis 2026-08-03 schloss ("zwei Teile DERSELBEN Fläche"), ist mit
   der Fläche selbst entfallen — ein Strom trennt seine Einträge einheitlich, nicht je nach
   Herkunft. */
.panel-body.ps .touch-out, .panel-body.ps .touch-body, .panel-body.ps .cmd-body{ overflow:visible; }
/* Der Inhalt teilt sich die Body jetzt mit dem Titel-Eintrag — und beansprucht sie trotzdem ganz:
   fast jeder Panel-Inhalt trägt `height:100%` aus der Zeit, als er das EINZIGE Kind war
   (`.touch-wrap`, `.cmd-wrap`, `.hist-wrap`, `.tnew-wrap`, `.afsde-wrap`, `.coll-/dt-/mf-wrap`,
   dazu server-gerenderte Skill-Panele). Titel + 100 % ist mehr als die Body hoch ist; mit
   `overflow:hidden` wird unten abgeschnitten — die Panele sah „nur zum Teil" da aus und ihr Inhalt
   verschoben. Deshalb hier EINE Regel für alle statt neun Einzelkorrekturen (und einer, die man
   bei server-gerendertem HTML ohnehin nicht treffen könnte): im Strom nimmt der Inhalt die
   RESTHÖHE, nicht die ganze. Strom-Einträge sind ausgenommen, sie bringen ihre eigene mit. */
/* JEDES Kind des Stroms hat seine NATÜRLICHE Höhe — gescrollt wird der Strom, nicht ein Kasten
   darin. Vorher stand hier `flex:1 1 auto`: dann teilten sich die Kachel-Fläche und der Chat-Wrap
   die Panelhöhe zur Hälfte, jeder mit eigenem Scrollbalken, und beide blieben starr. Ein Strom
   hat einen Anfang und ein Ende, keine Fächer. */
.panel-body.ps > *{ flex:0 0 auto; min-height:0; height:auto !important; }
/* AUSNAHME: trägt der Strom NUR seinen Inhalt (noch kein Satz, keine zweite Sache), gehört ihm die
   ganze Höhe. Ein Detail, das auf halber Panelhöhe endet und darunter weiße Fläche lässt, sieht aus,
   als fehlte etwas — gemessen auf dem afsde-Board: Kennzahlen 344 px in einer 818 px hohen Panele,
   Bestell-Detail 567 px. `1 0 auto` (wachsen, aber nie unter die Inhaltshöhe schrumpfen) ist dabei
   der Unterschied zu einer Falle: mit `1 1 auto` würde eine 18.000 px lange Tabelle auf die
   Panelhöhe zusammengedrückt und der Rest wäre unerreichbar, weil dann auch der Strom nichts mehr
   zu scrollen hat. Sobald ein zweiter Eintrag dazukommt, gilt wieder „natürliche Höhe": dann ist
   die Body ein Verlauf und keine Fläche. */
.panel-body.ps > *:only-child:not(.ps-acts){ flex:1 0 auto; }
/* DIE RESTHÖHE GEHÖRT DEM INHALT, NICHT DEM LEEREN CHAT (2026-07-31).
   Bis heute nahm sie der Chat-Wrap (`.touch-wrap:last-child{flex:1 0 auto}`) — begründet damit,
   dass die Fläche jemandem gehören muss, sonst holt kein Tipp dort die Eingabe. Der Preis war
   genau die halbe leere Panele zwischen Kachel und Chat: gemessen auf `/claude` bei 1400 px
   Angebot 209 px, Chat-Wrap 235 px mit 30 px Inhalt darin; bei 390 px Angebot 209 px gegen einen
   575 px leeren Wrap. Der Detailbereich, dem sie gehören sollte, bekam sie nie.
   Jetzt bekommt sie der ERSTE Eintrag: er IST der Inhalt des Scopes, die Unterhaltung ist sein
   Boden. Zwei Voraussetzungen, beide erfüllt: die Eingabe hängt am PANEL (Zeile 828 f.), rutscht
   mit dem kürzeren Wrap also nicht hoch, und die Fläche bleibt antippbar — `LEER_SEL` trifft
   `.ps-obj:not(.tile)` und `.ta-grid` genauso wie den Wrap.
   `:not(.touch-wrap):not(.cmd-wrap)`: ist der Chat der erste Eintrag, ist er der einzige — dann
   gilt die `:only-child`-Regel darüber. `:not(.tile)`: eine Kachel im Fluss ist ein Merkzettel,
   keine Fläche.
   `:not(.ps-acts)` (§35): ohne die Ausnahme wüchse `.ps-acts` per `flex:1 0 auto` auf die ganze
   Resthöhe, während ihr Inhalt (`g`, von `kappen()` auf die tatsächlich passende Zeilenzahl gekappt)
   viel kürzer bliebe — ein leerer Bereich UNTER der Zeilenliste, INNERHALB der eigenen (zu groß
   gewachsenen) Box. `kappen()` verhindert nur den Überlauf nach unten, nicht das Wachsen der Box
   selbst. `.ps-acts` bleibt so bei ihrer natürlichen (gekappten) Höhe wie jeder andere Listen-/
   Formularinhalt (Basisregel `flex:0 0 auto`, Zeile oben).
   `:not(.panel-title)` (§38): die Titelzeile ist jetzt der WIRKLICHE erste Eintrag des Stroms (sie
   liegt, anders als `.ph-x` vorher, nicht `position:absolute` — sie ist ein echtes Flex-Kind). Ohne
   die Ausnahme bekäme sie dieselbe Resthöhe wie ein einsamer Inhalt und stünde als hohe, halbleere
   Zeile über allem — sie soll bei ihrer natürlichen, kleinen Höhe bleiben. */
.panel-body.ps > *:first-child:not(.touch-wrap):not(.cmd-wrap):not(.tile):not(.ps-q):not(.ps-acts):not(.panel-title){ flex:1 0 auto; }
/* Und der Chat gibt sie wirklich her: `.panel.touch .touch-wrap{flex:1 1 auto}` (Zeile 236) hat
   eine höhere Spezifität als `.panel-body.ps > *` und ließ ihn weiter mitwachsen — die Resthöhe
   wurde dann zwischen Inhalt und Chat GETEILT (gemessen bei 390 px: Angebot 476 px, Wrap 309 px).
   `:not(:only-child)` — trägt der Strom nur den Chat, gehört ihm die Fläche ja doch. */
.panel-body.ps > .touch-wrap:not(:only-child),
.panel-body.ps > .cmd-wrap:not(:only-child){ flex:0 0 auto; }
/* Die Vorschlagsliste der Home-Fläche steht BILDSCHIRM-seitig unter der Antwort, sobald eine da
   ist — reine `order`, kein Umbau im DOM: die Wachstumsregeln oben hängen an der DOM-Position
   (`:first-child`/`:only-child`) und bleiben deshalb unverändert richtig, auch wenn die Liste
   optisch nach unten rutscht. Trifft nur den direkten Kind-Bezug — `.ps-acts.followups` (die
   Folge-Prompts JEDES Turns, `renderFollowups`) hängt verschachtelt im `.touch-out`, nicht hier. */
.panel-body.ps > .ps-acts{ order:1; }
/* §30.24 — die BEDIENLEISTE ist kein Eintrag des Stroms. Steht sie während der Verarbeitung als
   Kopf-Slot (`.ps-q.ps-busy`) über dem Chat, ist der Chat trotzdem der einzige INHALT: die beiden
   Regeln darüber („erster Eintrag nimmt die Resthöhe" / „der Chat gibt sie her") würden sie sonst
   dem leeren Slot geben und die Antwort endete auf halber Panelhöhe. */
.panel-body.ps > .ps-q + .touch-wrap:last-child,
.panel-body.ps > .ps-q + .cmd-wrap:last-child{ flex:1 0 auto; }
.ps-obj > *{ height:auto !important; }
/* Die Titelzeile ist ein EINTRAG des Stroms und scrollt mit ihm weg — sie war zwischenzeitlich
   `sticky`, damit das `✕` erreichbar bleibt. Das `✕` gibt es nicht mehr (Titel-Klick = Kachel,
   ☰ = Aktionen), also darf sie sein, was sie ist: die erste Ausgabe. */
/* Das CSS der Titelzeile (`.ps-ti`, `.ps-ti-t`, `.ph-menu`) ist mit ihr ENTFALLEN (2026-07-31). */
/* Objekt in Großform: es füllt die Panele — der Strom liegt dahinter und ist über die Kachel
   wieder erreichbar. */
/* Ein Objekt ist ein Eintrag: so hoch, wie es ist. Ein eigenes `overflow:auto` machte daraus
   einen zweiten Scroll-Kasten im Strom — mit dem Finger erwischte man mal das eine, mal das andere. */
.ps-obj{ flex:0 0 auto; position:relative; }
/* ===== Zwei Zustände einer Panele — nie beide =================================================
   OBJEKTSICHT (`.panel.objview`): das eine Objekt füllt den Detailbereich (App-Ausgabe, Tabelle,
   Datei …). Der Strom ist ausgeblendet, nicht weg.
   CHATSICHT (ohne die Klasse): der Strom mit den Nachrichten, und die Objekte darin als Kacheln.
   Vorher lagen beide gleichzeitig im Körper und teilten sich die Höhe — das war die eigentliche
   Ursache der halben Panele. */
.panel.objview > .panel-body.ps > :not(.ps-obj){ display:none !important; }
/* `board.eingabe_offen`: in der Objektsicht liegt die EINGABE mit im Strom-Container
   (`.touch-wrap > .touch-foot`) — der oben ausgeblendet wird, und damit verschwindet die
   einzige Stelle, an der man antworten kann (gemessen 18.08.2026: Fußzeile 0×0, der Nutzer
   konnte nach der ersten Antwort nichts mehr eingeben). Nicht der Container weicht, sondern
   sein Strom; die Fußzeile bleibt. */
#board.eingabe-offen .panel.objview > .panel-body.ps > .touch-wrap{
  display:flex !important; flex:0 0 auto; }
#board.eingabe-offen .panel.objview > .panel-body.ps > .touch-wrap > .touch-body{
  display:none !important; }
.panel.objview > .panel-body.ps > .ps-obj:not(.voll){ display:none !important; }
.panel.objview > .panel-body.ps{ padding-bottom:calc(var(--foot-res) + 10px); }
/* Das aufgezogene Objekt FÜLLT die Panele (grow), wird aber nie KLEINER als sein Inhalt
   (`flex-shrink:0`): mit `1 1 auto` schrumpfte es unter die Inhaltshöhe und schnitt ab — gemessen
   an der Home-Panele auf `/claude`: Kachelraster 178 px, Objekt 70 px, die Kacheln lagen
   angeschnitten da. Ist der Inhalt höher als die Panele, scrollt der Strom (die `.panel-body.ps`),
   und zwar er allein. */
.panel.objview .ps-obj.voll{ flex:1 0 auto; min-height:0; }
/* `⌄` — eine Ebene zurück in den Chat. Ein Zustand ohne sichtbaren Ausgang ist eine Falle, auch
   wenn der Prompt der eigentliche Weg zurück ist. Er hing bis 2026-08-25 am OBJEKT auf
   `top:4px; right:6px` — und ein aufgezogenes Objekt FÜLLT die Panele, lag damit unter dem ✕
   (§39: top:6/right:6). Seit §41 hängt er in der Aktionsleiste der Panele, also links daneben;
   Position und Abstand stehen nur noch dort. Sichtbar ist er, wenn er da ist: `psSize` hängt ihn
   beim Aufziehen ein und beim Zurückgehen aus — kein zweiter Schalter im CSS. */
.p-acts > .ps-back{ width:26px; height:26px;
  padding:0; border:0; border-radius:8px; background:rgba(255,255,255,.9); color:#64748b;
  cursor:pointer; display:inline-flex; align-items:center; justify-content:center; }
.p-acts > .ps-back:hover{ background:#fff; color:#0f172a; }
.p-acts > .ps-back svg{ width:18px; height:18px; }
#board.board-dark .p-acts > .ps-back{ background:rgba(15,23,42,.9); }
.ps-obj.tile{ flex:0 0 auto; align-self:flex-start; margin:0 12px; max-width:calc(100% - 24px);
  display:flex; align-items:center; gap:8px; padding:8px 10px; cursor:pointer;
  border:1px solid #e5e7eb; border-radius:12px; background:#f8fafc;
  font:600 13px/1.25 system-ui; color:#0f172a; overflow:hidden; }
.ps-obj.tile:hover{ background:#f1f5f9; }
#board.board-dark .ps-obj.tile{ background:#111c31; border-color:#1e293b; color:#e8edf5; }
.ps-obj.tile > *{ display:none; }                 /* der Inhalt bleibt im DOM, die Kachel zeigt ihn nicht */
.ps-obj.tile::before{ content:attr(data-kw); display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ps-msg{ flex:0 0 auto; padding:0 12px; white-space:pre-wrap; font:14px/1.5 system-ui; color:var(--fg,#0f172a); }
.ps-msg.me{ font-weight:600; }
/* §30.9 — DIE PROMPT-ZEILE IST DER WEG ZURÜCK. Ein Klick auf den Satz, der einen Lauf eröffnet
   hat, führt auf die Home-Fläche: dort beginnt man einen NEUEN Auftrag. Die Fußzeile bleibt
   daneben der Weg für den FOLGE-Satz im selben Zusammenhang — zwei Absichten, zwei Griffe.
   Die Zeile sieht klickbar aus, ohne wie ein Knopf zu wirken: sie ist Inhalt, kein Bedienelement. */
.turn-q, .ps-msg.me{ cursor:pointer; border-radius:6px; margin-left:-4px; padding-left:4px; padding-right:4px; }
/* Die frühere Eck-Reservierung für `.ph-x` (§30.31/§21.10) bleibt entfallen (§38): es liegt in
   `.panel-title`, seiner EIGENEN Zeile vor `.turn-q` — nicht mehr über ihr. */
.turn-q:hover, .ps-msg.me:hover{ background:rgba(148,163,184,.12); }
#board.board-dark .turn-q:hover, #board.board-dark .ps-msg.me:hover{ background:rgba(148,163,184,.18); }
/* Läuft der Prompt-Task, steht der Kreis als ERSTES Zeichen an seinem Titel (2026-08-01), und ein
   Tipp darauf schließt die Panele. Er ist ein Zeichen, kein Kästchen — rund und flächenlos wie der
   Ruhe-Kreis im Chip (`.pf-rest`), und sein Punkt pulsiert nach derselben Regel: der Zustand steht
   damit an der Stelle, an der man ohnehin liest, statt nur unten in der Leiste. Im Ruhezustand ist
   er WEG (der Lauf ist vorbei, der Rückweg ist dann `⌄` bzw. die Panele-Gruppe des `☰`). */
.turn-q .tq-x{ display:none; }
.panel.busy .turn-q .tq-x{ display:inline-flex; align-items:center; justify-content:center; vertical-align:-4px;
  width:18px; height:18px; margin-right:6px; flex:0 0 auto;
  border:0; padding:0; background:transparent; border-radius:50%; color:#94a3b8; cursor:pointer; }
.panel.busy .turn-q .tq-x:hover{ background:#f1f5f9; color:#64748b; }
.panel.busy .turn-q .tq-x svg{ width:18px; height:18px; }
.panel.busy .turn-q .tq-x .pf-dot{ transform-box:fill-box; transform-origin:center;
  animation:pf-puls 1.1s ease-in-out infinite; }
.ps-msg.wait{ color:var(--muted,#6b7280); }
/* Quick-Action-Blatt einer generischen Panele (⋮ in der Fußzeile): es nutzt die GANZE Panele,
   liegt aber nur über ihrem Detailbereich — der Inhalt darunter bleibt unangetastet, und die
   Fußzeile bleibt frei. Optik = §30.8: dieselbe Zeilenliste (`.ps-list`) mit derselben Suchzeile
   (`.ps-q`) wie die Home-Fläche und die Empfehlungen der Chat-Panele. */
/* Es liegt IM Rahmen, nicht über ihm: unter dem Kopf (Titel + ✕ bleiben sichtbar und bedienbar)
   und über der Fußzeile (die trägt den Filter). Eine Fläche, die den eigenen Kopf verdeckt,
   nimmt der Panele ihren Namen und den Rückweg. */
.pf-acts{ position:absolute; left:0; right:0; top:var(--head-h); bottom:var(--foot-res); z-index:5;
  overflow-y:auto; padding:10px; box-sizing:border-box; background:#fff; }
.panel:not(.sz-panel):not(.sz-full):not(.sz-custom) > .pf-acts{ top:0; }   /* Kachel: kein Kopf, also kein Abstand */
#board.board-dark .pf-acts{ background:#0f172a; }
/* Sie blenden sich von UNTEN ein — dort, wo das Menü-Icon steht, aus dem sie kommen. Eine Fläche,
   die einfach da ist, lässt offen, woher sie kam. Gilt für beide Aktions-Flächen (generisches
   Blatt und die Liste in den Chat-Panelen) und respektiert `prefers-reduced-motion`. */
@keyframes acts-up{ from{ transform:translateY(14px); opacity:0; } to{ transform:none; opacity:1; } }
.pf-acts, .panel.touch.skills-open .touch-skills{ animation:acts-up .16s ease-out; }
@media (prefers-reduced-motion:reduce){
  .pf-acts, .panel.touch.skills-open .touch-skills{ animation:none; }
}
/* Solange das Blatt offen ist, fängt der Ziehgriff NICHT: `startResize` ruft
   preventDefault/stopPropagation, die Kachel darunter bekäme kein click. */
.panel.acts-open .panel-resize{ display:none; }
/* Lauf-Zustand am Chip: blau während der Verarbeitung, grüner Haken nach Abschluss
   (ersetzt den früheren Abschluss-Haken rechts in der Touch-Fußzeile). */
.panel.busy .pfoot .pf-status{ color:#2563eb; }
/* Der grüne Haken nach Abschluss ist ENTFALLEN (2026-08-01): dass eine Antwort dasteht, sieht man
   an der Antwort. Der Chip zeigt weiterhin den LAUF (blau während der Verarbeitung) — das ist die
   Auskunft, die man nicht anders bekommt. */
/* Laufzeit-Slot im Chip (Sekundenzähler · Tokens): eigener Klickbereich neben dem Agentnamen.
   Bei einem laufenden, steuerbaren Lauf (.can-stop) öffnet er die Lauf-Steuerung (siehe .pf-ctl);
   angehalten (.paused) markiert ihn ein Pausenzeichen. */
.pfoot .pf-run{ flex:0 0 auto; margin-left:4px; font-variant-numeric:tabular-nums; }
.pfoot .pf-run:empty{ display:none; }
.panel.busy.can-stop .pfoot .pf-run{ cursor:pointer; text-decoration:underline dotted; text-underline-offset:3px; }
.panel.paused .pfoot .pf-run::after{ content:' ⏸'; }
/* Lauf-Steuerung (Anhalten · Fortsetzen · Stoppen): tritt für die Dauer der Bedienung AN STELLE
   des Chips (Agentname · Laufzeit) in die Fußzeile — gleiche Chip-Optik, nur Icon-Schalter. */
.panel.runctl-open .pfoot .pf-status{ display:none; }
.pfoot .pf-ctl{ display:inline-flex; align-items:center; gap:2px; flex:0 0 auto; margin:0 auto;
  height:var(--foot-res); box-sizing:border-box; padding:0 5px;
  background:#fff; border-radius:999px; box-shadow:0 1px 4px rgba(37,99,235,.30); }
.pfoot .pf-ctl button{ flex:0 0 auto; border:0; background:transparent; width:var(--foot-btn); height:var(--foot-btn);
  border-radius:50%; padding:0; cursor:pointer; color:#2563eb; line-height:1; font-size:calc(var(--foot-fs) + 1px);
  display:inline-flex; align-items:center; justify-content:center; }
.pfoot .pf-ctl button:hover{ background:#f3f4f6; }
.pfoot .pf-ctl button.stop{ color:#c0392b; }
.pfoot .pf-ctl button[disabled]{ color:#cbd5e1; cursor:default; background:transparent; }
/* Kein eigenes Kopf-Band mehr (§38): der Titel ist die erste Zeile des Stroms (`.panel-title`),
   kein Element außerhalb davon. `--head-h` bleibt trotzdem als Bezugsmaß — nicht für einen Kopf,
   sondern für die Höhe der Fußzeile in der Aktions-Fläche (Name aus einer Zeit vor beiden). */
:root{ --head-h:30px; }
/* Chip-Klick → Eingabe (KEINE Auswahl-/Empfehlungsliste): der Chip verwandelt sich AN SEINER STELLE
   (unten in der Fußzeile) in eine Eingabebox — gleicher leichter Chip-Rahmen, aber mehrzeilig: die
   Box wächst beim Tippen (natürlicher Zeilenumbruch) nach oben in den Detailbereich hinein. */
/* `.reco-open` OHNE `.panel` davor: die Regel gehört zur Fußzeile, nicht zum Kachelraster —
   am Handy trägt sie die Schale `#mob` (die Pille IST dort die Fußzeile, §19). Sie ist zugleich
   die Umsetzung von „Name ODER Eingabe, nie beides": ist die Eingabe offen, weicht der Chip. */
.reco-open .pfoot .pf-status{ display:none; }
.pfoot .pf-reco-ta{ flex:1 1 auto; min-width:0; box-sizing:border-box; margin:0 auto; min-height:var(--foot-h);
  resize:none; overflow:hidden; white-space:pre-wrap; outline:none; border:0; border-radius:0;
  /* Ohne Rahmen (2026-08-02): die Trennlinie am Fußzeilen-Rand (`.panel-foot` u.a.) grenzt die
     Eingabe schon vom Inhalt ab — ein zweiter Rahmen/Schatten UM die Box wäre ein Kasten im Kasten. */
  background:transparent; box-shadow:none;
  /* Senkrecht zentriert: der Innenabstand ist genau die halbe Restluft (Boxhöhe − eine Zeile − Rahmen),
     damit Text UND Kachel im Ausgangszustand (einzeilig) auf derselben Mittellinie sitzen. */
  padding:calc((var(--foot-h) - 1.5em - 2px) / 2) 14px;
  font:inherit; font-size:15px; font-weight:600; color:#0f172a; line-height:1.5; }
.pfoot .pf-reco-ta::placeholder{ color:#94a3b8; font-weight:600; }
/* Rechts IN der Eingabebox liegt genau EIN Knopf: der Senden-Pfeil (`.pf-send`, sichtbar sobald
   etwas getippt ist — `.reco-typed`). Er ist ein ZEICHEN, kein Kästchen (2026-07-31): keine eigene
   Fläche, kein Rahmen, RUND — dieselbe Form wie der Ruhe-Kreis im Chip (`.pf-rest`) und dasselbe
   flache Farbsystem, in dem Fußzeile und Sende-Knöpfe transparente Icon-Knöpfe sind; nur der Hover
   legt kurz einen runden Grund darunter, damit der Knopf antwortet.
   Der Innenabstand (padding-right) hält den Text davon frei, solange der Knopf da ist.
   Unten verankert → bei mehrzeiliger, nach oben wachsender Box bleibt er auf der letzten Zeile. */
.pfoot .pf-send, .pfoot .pf-menu{ position:absolute; z-index:1; right:calc(var(--foot-pad) + 4px);
  bottom:calc(2px + (var(--foot-h) - var(--pf-tile)) / 2); width:var(--pf-tile); height:var(--pf-tile);
  box-sizing:border-box; border:0; border-radius:50%; background:transparent;
  padding:0; cursor:pointer; color:#2563eb;
  display:inline-flex; align-items:center; justify-content:center; }
.pfoot .pf-menu{ color:#64748b; }
.pfoot .pf-send:hover, .pfoot .pf-menu:hover{ background:#f1f5f9; color:#0f172a; }
.pfoot .pf-send[hidden], .pfoot .pf-menu[hidden]{ display:none; }
/* Solange nichts getippt ist, liegen dort zwei weitere Zeichen: Mikrofon (Spracheingabe) und
   Foto/Datei-Anhang (2026-08-02) — dieselbe Ecke, derselbe flache Icon-Knopf-Look wie der
   Senden-Pfeil. Beginnt der Nutzer zu tippen, weichen sie GENAU wie `.pf-menu` dem Senden-Pfeil
   (`.reco-typed`/`.reco-menu`). Nicht im Kopf einer Vorschlagsliste (`bar-top`) und nicht im
   In-Strom-Platz (`bar-in`): dort ist die Zeile ein Filter/Chip, kein Kompose-Feld. */
.pfoot .pf-tools{ position:absolute; z-index:1; right:calc(var(--foot-pad) + 4px + var(--pf-tile) + 2px);
  bottom:calc(2px + (var(--foot-h) - var(--pf-tile)) / 2); display:inline-flex; align-items:center; gap:2px; }
.reco-typed .pfoot .pf-tools, .reco-menu .pfoot .pf-tools,
.panel.bar-top .pfoot .pf-tools, .panel.bar-in .pfoot .pf-tools{ display:none; }
.pfoot .pf-tools button{ box-sizing:border-box; border:0; border-radius:50%; background:transparent;
  width:var(--pf-tile); height:var(--pf-tile); padding:0; cursor:pointer; color:#64748b;
  display:inline-flex; align-items:center; justify-content:center; }
.pfoot .pf-tools button:hover{ background:#f1f5f9; color:#0f172a; }
.pfoot .pf-tools button.on{ color:#dc2626; }   /* Mikrofon nimmt gerade auf */
.pfoot .pf-tools svg{ width:calc(var(--pf-tile) - 8px); height:calc(var(--pf-tile) - 8px); }
/* Ruhe-Knopf (in FOOT_HTML): weicht der Eingabe, die an derselben Stelle aufgeht. */
.reco-open .pf-rest{ display:none; }
/* Er ist ein KREIS mit blauem Punkt (2026-07-31), kein Kästchen mit drei Strichen — und er ist
   TEIL DES CHIPS (2026-07-31): er sitzt IN der Pille, vor dem Namen. Vorher lag er als absolut
   positioniertes Element in der Ecke unten rechts; die Fußzeile hatte damit zwei Enden mit Leere
   dazwischen, und er saß genau über dem Ziehgriff (.panel-resize, z-index 4), der ihm im
   Ruhezustand den Klick abfing (gemessen im Browser: „panel-resize intercepts pointer events") —
   die Gegenregel `z-index:5` ist mit dem Umzug entfallen, im Chip gibt es diese Kollision nicht.
   Deshalb hier KEIN eigener Rahmen und keine eigene Fläche: den Rahmen trägt der Chip, der Kreis
   ist ein Zeichen darin. Seit 2026-07-31 gilt dasselbe für den Senden-Pfeil in der Eingabe
   (`.pf-send`, rund und flächenlos) — die Regel oben trägt damit nur noch Lage und Größe, den
   Kästchen-Look (Rahmen, 8px-Ecken, graue Fläche) hat kein Fußzeilen-Knopf mehr.
   `order:-1` steht weiterhin da, obwohl der Grund entfallen ist (der grüne Haken des fertigen
   Laufs, ein generierter Kasten, war IMMER das erste Flex-Kind und hätte sonst vor dem Kreis
   gestanden). Die Ordnung Kreis · Name ist jetzt ohnehin die Markup-Reihenfolge.
   Seine Größe hängt an der RUHEHÖHE der Leiste, nicht an `--pf-tile` (das ist das Maß der Kachel in
   der Eingabebox): der Kreis steckt IM Chip, und der Chip ist im Ruhezustand niedriger als die Box
   (2026-08-01) — mit `--pf-tile` (26 px in einem 22 px hohen Chip) stünde er über. */
.pfoot .pf-rest{ position:static; order:-1; flex:0 0 auto;
  width:calc(var(--foot-rest) - 4px); height:calc(var(--foot-rest) - 4px);
  border:0; background:transparent; border-radius:50%; margin-right:4px; color:#94a3b8; }
.pfoot .pf-rest:hover{ background:#f1f5f9; color:#64748b; }
/* Der Textslot des Chips (`FOOT_HTML`/`TOUCH_HTML`): er trägt die Kürzung, nicht der Chip — sonst
   schnitte `text-overflow` am Kreis statt am Namen. */
.pfoot .pf-name{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pfoot .pf-send svg, .pfoot .pf-menu svg{ width:calc(var(--pf-tile) - 8px); height:calc(var(--pf-tile) - 8px); }
/* Der Ruhe-Kreis trägt BEIDE Klassen (`pf-menu pf-rest`) — diese Zeile muss deshalb NACH der
   vorigen stehen, sonst gewinnt bei gleicher Spezifität die spätere und das Zeichen bliebe so groß
   wie in der Eingabebox (18 px in einem 18 px großen Kreis). */
.pfoot .pf-rest svg{ width:calc(var(--foot-rest) - 8px); height:calc(var(--foot-rest) - 8px); }
/* Läuft die Panele, PULSIERT der Punkt im Kreis (2026-08-01) — der Zustand steht damit an dem
   Zeichen, das ohnehin die ganze Zeit dasteht, statt an einem zweiten Element daneben. Skaliert
   wird per `transform` statt über das SVG-Attribut `r`: `transform-box:fill-box` gibt dem Kreis
   seinen eigenen Kasten als Bezug, sonst rechnet `transform-origin:center` gegen das ganze SVG und
   der Punkt wandert beim Wachsen aus der Mitte. */
@keyframes pf-puls{ 0%,100%{ transform:scale(1); opacity:1; } 50%{ transform:scale(1.75); opacity:.3; } }
.panel.busy .pfoot .pf-rest .pf-dot{ transform-box:fill-box; transform-origin:center;
  animation:pf-puls 1.1s ease-in-out infinite; }
/* Der Leerflächen-Tipp (2026-08-08) verlangte einen runden Punkt am Klickpunkt, der erst beim
   Antippen die Fläche öffnet. Umgesetzt ist er NICHT als eigenes Element: die Home-Panele selbst
   erschien eingeklappt und zeigte nur ihren runden Knopf — ein Klick daneben versetzte sie, ein
   Klick darauf klappte sie auf. Den Zwischenschritt gibt es seit 2026-08-24 nicht mehr (die
   Eingabe IST der Einstieg, `homePanel`/`homeFocus`), den Knopf `.app-home` seit 2026-09-01
   überhaupt nicht mehr. Das frühere, nie gebaute
   `.board-tap-dot` samt `tap-dot-puls` ist am 2026-08-19 entfernt worden: es gab dafür Regeln und
   einen Kommentar auf eine Funktion `tapDotShow`, die nie eingecheckt wurde (einziger Commit
   15f4668f3). Abnahme: `scripts/check_board_tap_dot.py`. */
/* Ruhezustand: Platz für Mikrofon + Anhang (`.pf-tools`, siehe oben); getippt weicht das dem
   einen Senden-Pfeil. `bar-in` zeigt keine der beiden Gruppen (Filter-/Chip-Zeile) und bekommt
   deshalb ihr Polster zurück; `bar-top` hat schon eine eigene, spezifischere Regel. */
.pfoot .pf-reco-ta{ padding-right:calc(2 * var(--pf-tile) + 16px); }
.panel.bar-in .pfoot .pf-reco-ta{ padding-right:14px; }
.reco-typed .pfoot .pf-reco-ta, .reco-menu .pfoot .pf-reco-ta{ padding-right:calc(var(--pf-tile) + 12px); }
/* Fußzeilen-Box am Panelboden (Ende der Task-Verarbeitung, weder `bar-top` noch `bar-in`):
   der Senden-Pfeil steht UNTER der Box, mittig, statt IN ihrer Zeile — die Box selbst bleibt
   deshalb ohne rechtes Polster (kein Platz mehr für ein Icon in derselben Zeile freizuhalten).
   `align-items:stretch` lässt die Box weiter die volle Breite nehmen, `align-self:center` zieht
   nur den Pfeil in die Mitte der neuen, zweiten Zeile. */
.panel.reco-open:not(.bar-top):not(.bar-in) > .panel-foot,
.panel.reco-open:not(.bar-top):not(.bar-in) .touch-foot,
.panel.reco-open:not(.bar-top):not(.bar-in) .cmd-foot{ flex-direction:column; align-items:stretch; }
.panel.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-reco-ta{ padding-right:14px; text-align:left; }
.panel.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-send{ position:static; align-self:center; margin:2px 0 0; }
/* Offene Eingabe hat Vorrang vor den Ecken-Hotspots: Senden-/App-Icon liegen unten rechts GENAU
   unter dem Ziehgriff (.panel-resize, z-index 4). Ohne diese Anhebung fängt er den Klick ab (startResize ruft
   preventDefault/stopPropagation → der Knopf bekommt kein click) und das Panel schaltet die Größe um
   statt zu senden. Der Streifen selbst bleibt pointer-events:none — nur Eingabe/Knöpfe fangen. */
.panel.reco-open .pfoot{ z-index:1301; }
/* Vollbild: Fußzeile bleibt sichtbar (Detailansicht darf nicht die ganze Panelfläche einnehmen) — Verlassen weiterhin über die Ecken-Hotspots/Esc. */
/* Chat-/Filter-Eingabe im Detailbereich (Stift/Lupe): eine Zeile am Ende des Bodys. */
.pf-bodyin{ display:flex; align-items:center; gap:6px; margin:8px 0 2px; padding:0 2px; }
.pf-bodyin input{ flex:1 1 auto; min-width:0; box-sizing:border-box; height:var(--foot-h); border:1px solid #e5e7eb;
  border-radius:10px; padding:0 10px; font:inherit; font-size:15px; color:#0f172a; background:#fff; outline:none; }
.pf-bodyin button{ flex:0 0 auto; border:0; background:transparent; color:#2563eb; width:var(--foot-btn); height:var(--foot-btn);
  border-radius:8px; font-size:calc(var(--foot-fs) + 5px); cursor:pointer; line-height:1; display:inline-flex; align-items:center; justify-content:center; }
/* Kommando-/Touch-Fußzeile sind strukturell identisch zur generischen .panel-foot: Statuszeile
   (.cmd-agent/.touch-agent, beide .pf-status) + gemeinsame Aktionsleiste (.pf-actions). Chat-Eingabe
   läuft für Kommando-Panele im Body (.cmd-cont-box), für Touch-Panele über die Erst-Eingabe (.touch-main,
   Senden per Enter). */
.cmd-foot .cmd-agent.pf-status{ max-width:none; }
/* Der Chip füllt die Fußzeile — auch hier (2026-07-31). Diese Zeile stand auf `flex:0 1 auto` und
   war die letzte, spezifischste Stimme: der Chip blieb 101 px breit in einer 584 px breiten Panele,
   obwohl `.panel .pfoot .pf-status` längst `flex:1 1 auto` sagte. */
.panel.touch .touch-agent.pf-status{ flex:1 1 auto; }
/* Skill-Panele (noinput): Fußzeile bleibt sichtbar (einheitliche Aktionsleiste, kein Folgethread). */
.cmd-foot.noinput{ display:flex; }
.panel.cmd:not(.sz-panel):not(.sz-full):not(.sz-custom) .cmd-foot.noinput{ display:none; }   /* Kachel: keine Fußzeile */
/* ===================================================================
   PRÄSENZ-SCHICHT — drei Rollen, EINE Unterhaltung (docs/concepts/personal-presence.md).
   ------------------------------------------------------------------
   face  spricht (kurze Zusammenfassung, LiveAvatar-Video)
   stage zeigt GENAU EIN Artefakt (Ansicht/Plan/Dokument/Lauf) + Zurück-Stapel
   talk  schreibt dieselbe Unterhaltung mit (gleiche Session wie face)
   Desktop: face oben links, talk darunter, stage rechts über beide Reihen.
   Handy: face oben, stage darunter, talk als angedockte Zeile am Fuß.
   =================================================================== */
#board-presence{ display:grid; gap:var(--tile-gap); padding:var(--tile-gap) var(--tile-gap) 0;
  grid-template-columns:minmax(0,340px) minmax(0,1fr); grid-template-rows:auto minmax(0,1fr);
  height:calc(100vh - 2 * var(--tile-gap)); box-sizing:border-box; }
#board-presence[hidden]{ display:none; }
.pres{ display:flex; flex-direction:column; min-width:0; min-height:0; overflow:hidden;
  background:#fff; border:1px solid #94a3b8; border-radius:10px; box-shadow:0 1px 3px rgba(0,0,0,.07); }
#board.board-dark .pres{ background:#0b1220; border-color:#1e293b; color:#e2e8f0; }
#board.noframe .pres{ border-color:transparent; box-shadow:none; }
.pres-face{ grid-column:1; grid-row:1; }
.pres-talk{ grid-column:1; grid-row:2; }
.pres-stage{ grid-column:2; grid-row:1 / span 2; }
.pres[hidden]{ display:none; }
/* Ist der Avatar aus, füllt talk die linke Spalte allein. */
#board-presence.no-face .pres-talk{ grid-row:1 / span 2; }

/* ---- face ---- */
.pres-face .fc-stack{ position:relative; flex:1 1 auto; min-height:0; background:#0b1220; overflow:hidden; }
.pres-face .fc-vid{ width:100%; height:100%; object-fit:cover; object-position:top center; display:block; background:#0b1220; }
.pres-face .fc-idle{ position:absolute; inset:0; display:none; align-items:center; justify-content:center; background:#0b1220; }
.pres-face.fc-paused .fc-idle{ display:flex; }
.pres-face.fc-paused .fc-vid{ visibility:hidden; }
.pres-face .fc-ini{ width:54px; height:54px; border-radius:50%; background:#1e293b; color:#93c5fd;
  display:flex; align-items:center; justify-content:center; font:700 22px/1 system-ui; }
.pres-face .fc-status{ position:absolute; inset:0; display:none; align-items:center; justify-content:center;
  text-align:center; padding:16px; color:#94a3b8; font:13px/1.5 system-ui; background:rgba(11,18,32,.9); }
.pres-face.fc-msg .fc-status{ display:flex; }
.pres-face .fc-size{ position:absolute; top:6px; right:8px; width:30px; height:30px; border:none; border-radius:999px;
  background:rgba(0,0,0,.4); color:#fff; cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; }
.pres-face .fc-size svg{ width:18px; height:18px; transition:transform .15s; }
.pres-face.fc-full .fc-size svg{ transform:rotate(180deg); }
.pres-face .fc-cap{ flex:0 0 auto; padding:7px 12px; font:600 14px/1.45 system-ui; color:#0f172a;
  max-height:5.9em; overflow:hidden; }
#board.board-dark .pres-face .fc-cap{ color:#e2e8f0; }
.pres-face .fc-cap:empty{ display:none; }
/* Drei Stufen. `peek` = das Gesicht tritt zurück, damit die Bühne den Platz bekommt. */
.pres-face.fc-peek{ min-height:0; }
.pres-face.fc-peek .fc-stack{ flex:0 0 64px; }
.pres-face.fc-half .fc-stack{ flex:0 0 clamp(150px,26vh,260px); }
.pres-face.fc-full .fc-stack{ flex:1 1 auto; min-height:220px; }
.pres-face.fc-full .fc-cap{ max-height:none; }
/* Vierte Stufe: `dock`. Öffnet sich eine Panele im Vollbild, wandert das Gesicht klein nach
   oben links und bleibt präsent (mobile-agent.md §6.1). Es muss ÜBER dem Vollbild-Panel
   liegen (`.panel.sz-full` hat z-index 1200), sonst wäre „bleibt präsent" nicht wahr. */
.pres-face.fc-dock{ position:fixed; top:8px; left:8px; width:88px; height:88px; z-index:1310;
  border-radius:14px; overflow:hidden; box-shadow:0 2px 10px rgba(15,23,42,.35); }
.pres-face.fc-dock .fc-stack{ flex:1 1 auto; }
.pres-face.fc-dock .fc-cap{ display:none; }          /* der Untertitel gehört zum Strom, nicht ins Eck */
.pres-face.fc-dock .fc-size{ display:none; }         /* keine Stufen-Bedienung im Eck */

/* ---- stage ---- */
.pres-hd{ flex:0 0 auto; display:flex; align-items:center; gap:4px; padding:5px 8px 5px 10px;
  border-bottom:1px solid #eef1f4; }
#board.board-dark .pres-hd{ border-bottom-color:#1e293b; }
.pres-hd .pres-ti{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font:600 13px/1.4 system-ui; color:#0f172a; }
#board.board-dark .pres-hd .pres-ti{ color:#e2e8f0; }
.pres-hd button{ flex:0 0 auto; width:28px; height:28px; border:none; background:transparent; color:#64748b;
  cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; border-radius:8px; }
.pres-hd button svg{ width:17px; height:17px; }
.pres-hd button[hidden]{ display:none; }
.pres-hd button:hover{ background:#f1f5f9; }
#board.board-dark .pres-hd button:hover{ background:#1e293b; }
.pres-stage .st-body{ flex:1 1 auto; min-height:0; overflow:auto; -webkit-overflow-scrolling:touch;
  padding:10px 12px; font:14px/1.55 system-ui; color:#0f172a; }
#board.board-dark .pres-stage .st-body{ color:#e2e8f0; }
.pres-stage .st-body img{ max-width:100%; height:auto; }
.pres-stage .st-empty{ color:#94a3b8; font-size:13px; }
/* Zeilen, die in eine Ebene tiefer führen (Vorhaben, Läufe) — Bühne bleibt EIN Slot. */
.st-row{ display:flex; align-items:center; gap:9px; width:100%; box-sizing:border-box; text-align:left;
  border:none; border-bottom:1px solid #eef1f4; background:transparent; font:inherit; color:inherit;
  padding:9px 4px; cursor:pointer; }
#board.board-dark .st-row{ border-bottom-color:#1e293b; }
.st-row:hover{ background:#f8fafc; }
#board.board-dark .st-row:hover{ background:#111c31; }
.st-row .st-rw-t{ flex:1 1 auto; min-width:0; }
/* `display:block` ist hier NICHT Kosmetik: beides sind `<span>`, und auf einem inline-Kasten
   wirkt `overflow:hidden`/`text-overflow` nicht — `white-space:nowrap` dagegen schon. Der Text
   lief also weiter und malte über die Uhrzeit rechts. Erst als Block wird er abgeschnitten. */
.st-row .st-rw-n{ display:block; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.st-row .st-rw-s{ display:block; font-size:12px; color:#64748b; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.st-row .st-rw-b{ flex:0 0 auto; font-size:11px; font-weight:700; color:#2563eb; }
.st-sect{ font:700 11px/1.4 system-ui; letter-spacing:.04em; text-transform:uppercase; color:#94a3b8;
  margin:12px 0 4px; }
.st-sect:first-child{ margin-top:0; }
/* Bausteine der fünf Punkte (presence.now/contexts/contacts/journal) */
.nv-mission{ font:700 13px/1.35 system-ui; color:#2563eb; margin-bottom:8px; }
.nv-kpis{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:4px; }
.nv-kpi{ flex:0 0 auto; min-width:86px; box-sizing:border-box; border:1px solid #e5e7eb; border-radius:10px;
  background:#fff; padding:7px 9px; text-align:left; font:inherit; cursor:pointer;
  display:flex; flex-direction:column; gap:1px; }
#board.board-dark .nv-kpi{ background:#0b1220; border-color:#1e293b; }
.nv-kpi .nv-k-w{ font:700 19px/1 system-ui; color:#0f172a; font-variant-numeric:tabular-nums; }
#board.board-dark .nv-kpi .nv-k-w{ color:#e2e8f0; }
.nv-kpi .nv-k-l{ font-size:11px; color:#64748b; }
.nv-kpi .nv-k-h{ font-size:10px; color:#94a3b8; }
/* Ein Journal-Eintrag ist ZWEIZEILIG wie eine E-Mail: Betreff und Uhrzeit oben, das
   Kernergebnis darunter. Deshalb kippt `.st-row` hier auf eine Spalte — die Uhrzeit steht in
   der Titelzeile und kann von keinem Text mehr erreicht werden, und das Ergebnis hat eine
   eigene Zeile statt um denselben Platz zu kämpfen. */
.st-row.jr{ display:flex; flex-direction:column; align-items:stretch; gap:2px; }
.st-row.jr .jr-hd{ display:flex; align-items:baseline; gap:10px; }
.st-row.jr .jr-n{ flex:1 1 auto; min-width:0; display:block; font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.st-row.jr .jr-t{ flex:0 0 auto; font-size:11px; font-weight:700; color:#2563eb; }
/* Wer hat gearbeitet (Agent · Space) — nur im Journal gesetzt, grau als untere Zeile links. */
.st-row.jr .jr-w{ display:block; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; font-size:11px; color:#94a3b8; }
/* Die Kennung des Eintrags (`#a1b2c3`) steht in derselben Zeile vorn — monospace, damit sie
   als Kennung lesbar ist und nicht als Teil des Namens. */
.st-row.jr .jr-id{ font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
/* Das Ergebnis darf umbrechen — aber nur zweimal, sonst schiebt ein langer Satz die Liste auf. */
.st-row.jr .jr-s{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; font-size:12px; line-height:1.4; color:#64748b; }
/* „Neu starten" an einem abgebrochenen Lauf: ein Ziel IN der Zeile (die Klick-Auflösung
   nimmt das innere `data-go` zuerst) — blau als Text-Akzent, wie jede Aktion. */
.st-row.jr .jr-redo{ align-self:flex-start; font-size:11px; font-weight:700; color:#2563eb;
  cursor:pointer; padding:1px 0; }
/* Der Zustand eines Laufs als farbiger Punkt vor dem Betreff: offen = blau und pulsierend
   (da arbeitet noch jemand), fertig = grün, abgebrochen/Fehler = rot. Marken tragen keinen
   Zustand und deshalb keinen Punkt. Am `jr-run` hängt auch das Selbst-Nachfrischen der
   Liste (mobLoad/stWatchRun) — Klasse nicht umbenennen, ohne beide Leser mitzuziehen. */
/* Nicht auf `.st-row.jr` eingeschränkt: denselben Punkt trägt der Kopf des Lauf-Details
   (presence.run) — ein Zustand ist ein Zustand, egal ob er in einer Liste steht. */
.jr-dot{ flex:0 0 auto; display:inline-block; width:8px; height:8px; border-radius:50%;
  align-self:center; margin-right:7px; }
.st-row.jr .jr-dot{ margin-right:0; }
.jr-dot.jr-ok{ background:#16a34a; }
.jr-dot.jr-ab{ background:#dc2626; }
.jr-dot.jr-run{ background:#2563eb; animation:jr-puls 1.4s ease-in-out infinite; }
@keyframes jr-puls{ 0%,100%{opacity:1} 50%{opacity:.25} }
/* Eine Marke im Journal: DIESELBE Zeilenform wie ein Lauf, nur ohne Ziel. Zwei Formen
   nebeneinander ließen die Liste fleckig wirken, obwohl beides Historie ist. */
.st-row.mk{ cursor:default; }
.st-row.mk .jr-n{ font-weight:500; color:#64748b; }

/* ---- talk ---- */
.pres-talk .tk-ribbon{ flex:0 0 auto; display:flex; align-items:center; gap:6px; padding:5px 8px 5px 10px;
  background:#eff6ff; border-bottom:1px solid #dbeafe; font:600 12px/1.4 system-ui; color:#1d4ed8; }
#board.board-dark .pres-talk .tk-ribbon{ background:#122142; border-bottom-color:#1e3a6b; color:#93c5fd; }
.pres-talk .tk-ribbon[hidden]{ display:none; }
.pres-talk .tk-rb-lb{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pres-talk .tk-rb-x{ flex:0 0 auto; border:none; background:transparent; color:inherit; font-size:14px;
  cursor:pointer; padding:0 2px; }
.pres-talk .tk-log{ flex:1 1 auto; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
  padding:10px 12px; font:14px/1.55 system-ui; display:flex; flex-direction:column; gap:8px; }
.tk-msg{ max-width:92%; padding:7px 11px; border-radius:12px; white-space:pre-wrap; word-break:break-word; }
.tk-msg.me{ align-self:flex-end; background:#2563eb; color:#fff; border-bottom-right-radius:4px; }
.tk-msg.it{ align-self:flex-start; background:#f1f5f9; color:#0f172a; border-bottom-left-radius:4px; }
#board.board-dark .tk-msg.it{ background:#1e293b; color:#e2e8f0; }
.tk-msg.html{ white-space:normal; }
.tk-msg.html img{ max-width:100%; height:auto; }
.tk-note{ align-self:center; font-size:12px; color:#64748b; }
/* ---- Avatar-Ansicht einer Chat-Panele (.touch-avatar) ----
   Die persönliche Fläche des Agenten: ein Gesicht statt Text, in DERSELBEN Panele wie der Chat
   (kein zweites Fenster). Füllt denselben Bereich, den sonst .touch-center/.touch-out belegen. */
.touch-avatar{ position:relative; flex:1 0 auto; min-height:220px; border-radius:10px; overflow:hidden;
  background:#0b1220; }
.touch-avatar .ta-vid{ width:100%; height:100%; object-fit:cover; object-position:top center; display:block; }
.touch-avatar .ta-tap{ position:absolute; inset:0; cursor:pointer; }
.touch-avatar .ta-status{ position:absolute; inset:0; display:none; align-items:center; justify-content:center;
  text-align:center; padding:16px; color:#94a3b8; font:13px/1.5 system-ui; background:rgba(11,18,32,.9); pointer-events:none; }
.touch-avatar.ta-msg .ta-status{ display:flex; }
.touch-avatar .ta-back{ position:absolute; top:6px; left:8px; width:30px; height:30px; border:none; border-radius:999px;
  background:rgba(0,0,0,.4); color:#fff; cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; z-index:2; }
.touch-avatar .ta-back svg{ width:18px; height:18px; }
/* Zuhören: Tippen auf das Gesicht (`.ta-tap`) startet/stoppt das Mikrofon — sichtbar als roter,
   pulsierender Knopf MITTIG, nicht als Rahmen ums Bild (einheitlich mit spaces/<space>/skills/avatar.py). */
.touch-avatar .ta-listen{ position:absolute; left:50%; top:50%; width:64px; height:64px; margin:-32px 0 0 -32px;
  border-radius:50%; background:#dc2626; display:none; align-items:center; justify-content:center;
  color:#fff; pointer-events:none; box-shadow:0 2px 14px rgba(220,38,38,.5); }
.touch-avatar .ta-listen svg{ width:28px; height:28px; }
@keyframes ta-listen-puls{ 0%,100%{ transform:scale(1); opacity:1; } 50%{ transform:scale(1.18); opacity:.7; } }
.touch-avatar.ta-listening .ta-listen{ display:flex; animation:ta-listen-puls 1.1s ease-in-out infinite; }
/* Schnellaktion NACH einer Antwort — flacher, runder Icon-Knopf, dasselbe Farbsystem wie
   Sende-Pfeil/Fußzeilen-Chip (transparent, Akzent nur am Symbol). */
.turn-acts{ display:flex; gap:4px; margin-top:2px; }
.turn-acts button{ border:none; background:transparent; color:#64748b; width:26px; height:26px; border-radius:50%;
  cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; }
.turn-acts button:hover{ background:#f1f5f9; color:#0f172a; }
#board.board-dark .turn-acts button:hover{ background:#1e293b; color:#e2e8f0; }
.turn-acts svg{ width:15px; height:15px; }
/* Ein Prompt, der einen Lauf ausgelöst hat, ist antippbar — er führt in den Lauf. Sichtbar
   gemacht wird das mit einer Kante, nicht mit einem Knopf: die Blase bleibt eine Nachricht. */
.tk-msg.me.has-run{ cursor:pointer; border-right:3px solid #93c5fd; }
/* Der Kontext im Chat: eigener Block über die ganze Breite, damit man sieht, dass ab HIER
   über etwas anderes gesprochen wird. Kein Rahmen, nur eine Kante links und Abstand — er
   soll rahmen, nicht rufen. */
.str-ctx{ align-self:stretch; display:flex; align-items:center; gap:8px; margin:10px 0 4px;
  padding:6px 0 6px 10px; border-left:3px solid #2563eb; }
.str-ctx .sc-t{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font:700 12px/1.35 system-ui; letter-spacing:.03em; text-transform:uppercase; color:#2563eb; }
/* Schnellaktionen des Kontext-Agenten: seine Flächen als Kacheln, direkt unter dem Block.
   Zwei je Reihe — Skill-Beschriftungen sind Wörter, keine Zeichen; eine dritte Spalte klemmt
   sie ab. Sie hängen am Block, nicht am Kopf: sie gehören zu DIESEM Kontextwechsel. */
.str-acts{ align-self:stretch; display:grid; grid-template-columns:1fr 1fr; gap:6px;
  margin:0 0 6px 13px; }
.str-acts[hidden]{ display:none; }
.str-act{ text-align:left; border:1px solid #dbeafe; border-radius:12px; background:#eff6ff;
  color:#1d4ed8; padding:10px 12px; min-height:52px; font:600 13px/1.3 system-ui; cursor:pointer; }
#board.board-dark .str-act, body.mob-on.board-dark .str-act{ background:#122142;
  border-color:#1e3a6b; color:#93c5fd; }
/* Fremde Stimme: eigener Rahmen und ein Name. Sie soll erkennbar NICHT der Assistent sein. */
.tk-msg.fremd{ background:#fff; border:1px solid #cbd5e1; color:#0f172a; }
#board.board-dark .tk-msg.fremd, body.mob-on.board-dark .tk-msg.fremd{ background:#0b1220; border-color:#334155; color:#e2e8f0; }
.tk-msg.fremd .tk-who{ display:block; font:700 10px/1.4 system-ui; letter-spacing:.04em;
  text-transform:uppercase; color:#64748b; margin-bottom:3px; }
.pres-talk .tk-dock{ flex:0 0 auto; display:flex; align-items:flex-end; gap:4px; padding:6px 8px;
  border-top:1px solid #eef1f4; }
#board.board-dark .pres-talk .tk-dock{ border-top-color:#1e293b; }
.pres-talk .tk-in{ flex:1 1 auto; min-width:0; max-height:8em; border:none; background:transparent;
  color:inherit; font:inherit; font-size:16px; line-height:1.45; resize:none; outline:none; padding:6px 2px; }
.pres-talk .tk-dock button{ flex:0 0 auto; width:36px; height:36px; border:none; border-radius:999px;
  background:transparent; color:#64748b; cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; }
.pres-talk .tk-dock button svg{ width:19px; height:19px; }
.pres-talk .tk-dock button:hover{ background:#f1f5f9; }
#board.board-dark .pres-talk .tk-dock button:hover{ background:#1e293b; }
.pres-talk .tk-mic.on{ color:#dc2626; }
.pres-talk .tk-face.on{ color:#2563eb; }   /* Gesicht ist offen */
.pres-talk.tk-busy .tk-send{ opacity:.45; pointer-events:none; }

/* ---- Selbstbild (Kamera, Live-Modus) ----
   Oben RECHTS, weil oben links der Avatar andockt. Der rote Punkt ist nicht optional. */
.pres-cam{ position:fixed; top:8px; right:8px; width:88px; height:88px; z-index:1310;
  border-radius:14px; overflow:hidden; background:#0b1220; box-shadow:0 2px 10px rgba(15,23,42,.35); }
.pres-cam[hidden]{ display:none; }
.pres-cam .cm-vid{ width:100%; height:100%; object-fit:cover; display:block; transform:scaleX(-1); }
.pres-cam .cm-dot{ position:absolute; top:6px; left:6px; width:9px; height:9px; border-radius:50%;
  background:#dc2626; box-shadow:0 0 0 2px rgba(255,255,255,.7); }
.pres-cam .cm-x{ position:absolute; top:2px; right:2px; width:24px; height:24px; border:0; padding:0;
  background:rgba(0,0,0,.35); color:#fff; border-radius:50%; cursor:pointer; font-size:13px; line-height:1; }
.pres-talk .tk-cam.on{ color:#dc2626; }

/* ---- Strom (Handy) ---- */
.pres-stream{ display:none; }                       /* Desktop: die Bühne bleibt */
.pres-stream .str-log{ flex:1 1 auto; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
  padding:10px 12px 64px; font:14px/1.55 system-ui; display:flex; flex-direction:column; gap:8px; }
.pres-stream .str-empty{ align-self:center; color:#94a3b8; font-size:13px; }

/* ---- Panele IM Strom ----
   Es ist dieselbe `.panel` wie im Kachelraster (Rahmen, Radius, Flex-Spalte, und `sz-full`
   funktioniert placement-frei) — und seit 2026-07-30 auch mit derselben FUSSZEILE
   (`.panel-foot.pfoot`): die Steuerung einer Panele ist überall dieselbe Zeile, unten. Vorher
   trug sie stattdessen eine eigene Kopfzeile `.str-hd` (mobile-agent.md §3.1). Nummer, Titel,
   Zustand/Laufzeit und Stoppen sind mit umgezogen und sitzen in den Fußzeilen-Slots (`.pf-status`,
   `.pf-run`); Größen wechseln über das `⋮` (Panele-Gruppe), nicht mehr über ein eigenes `⌄`. */
.pres-stream .panel.stream{ flex:0 0 auto; align-self:stretch; }
.pres-stream .panel.stream.str-breit{ height:clamp(170px,38vh,330px); }
.pres-stream .panel.stream.str-kachel{ align-self:flex-start; width:132px; height:88px; }
/* `.panel-foot` startet `display:none` und wird sonst über die Rastergrößen eingeblendet
   (`.panel.sz-panel > .panel-foot`) — die Strom-Größen kennt diese Regel nicht, also hier. */
.panel.stream > .panel-foot{ display:flex; }
.panel.stream .pf-status .str-ti{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font:600 13px/1.4 system-ui; color:#0f172a; }
#board.board-dark .panel.stream .pf-status .str-ti{ color:#e2e8f0; }
.panel.stream .str-st{ flex:0 0 auto; padding:4px 6px; border-radius:8px; cursor:pointer;
  font:600 11px/1 system-ui; color:#64748b; font-variant-numeric:tabular-nums; }
.panel.stream .str-st:empty{ display:none; }
.panel.stream.str-laeuft .str-st{ color:#2563eb; }
.panel.stream.str-fehler .str-st{ color:#c0392b; }
/* Läuft: der Rahmen sagt es mit, wie bei den Kommando-Panelen (.panel.busy). */
.panel.stream.str-laeuft{ border-color:#3b82f6; }
.panel.stream .str-stop{ flex:0 0 auto; width:30px; height:30px; border:0; background:transparent; color:#c0392b;
  cursor:pointer; padding:0; display:flex; align-items:center; justify-content:center; }
.panel.stream .str-stop[hidden]{ display:none; }
.panel.stream .str-stop svg{ width:16px; height:16px; }
.panel.stream .str-body{ flex:1 1 auto; min-height:0; overflow:auto; -webkit-overflow-scrolling:touch;
  padding:8px 12px; font:14px/1.55 system-ui; color:#0f172a; }
#board.board-dark .panel.stream .str-body{ color:#e2e8f0; }
.panel.stream .str-body img{ max-width:100%; height:auto; }
.panel.stream .str-body .st-empty{ color:#94a3b8; font-size:13px; }
/* Kachel: nur der Zustand, kein Inhalt — dieselbe Regel wie bei den Kommando-Kacheln. Die
   Fußzeile füllt dann die Kachel (auch das wie dort: `.panel.cmd` im Kachelmodus). */
.panel.stream.str-kachel .str-body{ display:none; }
.panel.stream.str-kachel > .panel-foot{ flex:1 1 auto; flex-direction:column;
  align-items:flex-start; justify-content:center; gap:2px; padding:8px 10px; }
.panel.stream.str-kachel .pf-status{ max-width:100%; height:auto; padding:0; background:none; border:0; }   /* Kachel: der Chip IST der Inhalt, keine Pille darum */
.panel.stream.str-kachel .pf-status .str-ti{ white-space:normal; overflow:hidden; }
.panel.stream.str-kachel .str-st{ font-size:15px; color:#2563eb; }
.panel.stream.str-kachel .pf-rest{ display:none; }   /* Kachel zeigt nur den Zustand — erst aufgezogen bedient man sie */

/* ---- Handy: eine Fläche, gestapelt; talk dockt am Fuß an ---- */
@media(max-width:640px){
  #board-presence{ grid-template-columns:minmax(0,1fr); grid-template-rows:auto minmax(0,1fr);
    padding:0; gap:0; height:100vh; }
  .pres{ border-radius:0; border-left:0; border-right:0; border-top:0; box-shadow:none; }
  .pres-face{ grid-column:1; grid-row:1; }
  .pres-stage{ grid-column:1; grid-row:2; }
  /* Ist der Strom montiert, nimmt er die Fläche der Bühne ein und das talk-Protokoll
     verschwindet: der Strom IST das Protokoll (kein zweites davon, kein Overlay). */
  #board-presence.has-stream .pres-stage{ display:none; }
  #board-presence.has-stream .pres-talk .tk-log{ display:none !important; }
  /* EINE Fläche zur Zeit: `on-agent` zeigt den Strom, sonst die Kontext-Panele. */
  #board-presence.has-stream .pres-stream,
  #board-presence.has-stream .pres-surface{ display:none; grid-column:1; grid-row:2; }
  #board-presence.has-stream.on-agent .pres-stream{ display:flex; }
  #board-presence.has-stream:not(.on-agent) .pres-surface{ display:flex; }
  .pres-surface{ padding:0; border:0; background:transparent; box-shadow:none; }
  .pres-surface .panel.stream{ flex:1 1 auto; height:auto !important; border-radius:0;
    border-left:0; border-right:0; border-top:0; box-shadow:none; }
  /* Das Kachelraster gehört zum Desktop-Board. Am Handy ist der Strom die Oberfläche — beides
     gleichzeitig zu zeigen war die „Mischung aus Board und Strom". */
  body.has-presence #board-presence.has-stream ~ #panel-grid{ display:none; }
  /* talk = am Bildschirmfuß angedockte Zeile. Ein Tipp zieht das Protokoll darüber auf
     (Overlay statt eigener Fläche — die Bühne behält den Bildschirm). */
  .pres-talk{ position:fixed; left:0; right:0; bottom:0; z-index:1350; grid-row:auto;
    border-top:1px solid #e5e7eb; border-bottom:0; box-shadow:0 -2px 10px rgba(15,23,42,.09); }
  #board.board-dark .pres-talk{ border-top-color:#1e293b; }
  .pres-talk .tk-log{ display:none; }
  .pres-talk.tk-open .tk-log{ display:flex; max-height:min(62vh,420px); }
  .pres-talk .tk-dock{ border-top:0; }
  .pres-talk.tk-open .tk-dock{ border-top:1px solid #eef1f4; }
  /* Platz für die angedockte Zeile, damit das Bühnen-Ende nicht darunter liegt. */
  .pres-stage .st-body{ padding-bottom:64px; }
  #board-presence:not([hidden]) ~ #panel-grid{ padding-top:var(--tile-gap); }
}

/* Das CSS der mobilen Schale (`#mob`, `#mob-view`, `#mob-sheet`, `#mob-bar`, `.mv*`, `.ms-*`,
   `body.mob-on`) ist mit ihr ENTFALLEN (2026-07-31) — siehe den Block im Skript. */

/* --- Vollbild: Klick auf JEDE Ecke → zurück in den Panele-Modus. --- */
/* Die vier Vollbild-Ecken (`.panel-corner`, Klick = zurück auf Panele) sind ENTFALLEN
   (2026-07-31) — ebenfalls unsichtbar, ebenfalls doppelt: aus dem Vollbild führen jetzt das `✕`
   im Kopf, `⋮ → Vollbild aus` und Esc. */

/* ===== §39 — SCHLIESSEN IN DER PANEL-ECKE (2026-08-24) =========================================
   Nutzerwunsch: „the panel should have an closing x in top right corner on mouseover when the
   panel was actively used". Das alte `.ph-x` (§30.42) kann das nicht mehr: es ist Kind von
   `.panel-title`, und die ist seit 2026-08-03 ausnahmslos `display:none !important` (§oben) —
   gemessen im echten Browser (2026-08-24): Knopf im Markup vorhanden, Zeile unsichtbar, Schließen
   nur noch über ⋮. `.p-x` hängt deshalb direkt am Panel (`chrome()`), nicht in der Titelzeile.

   „Aktiv benutzt" ist hier keine neue Erfindung, sondern die Grenze, die das Board schon zieht:
   eine `.home`-Fläche, in der noch nichts gefragt wurde, RÄUMT SICH SELBST WEG (`ensureFoot`s
   `onClose`: unbenutzte `.home` ohne offene Eingabe → `p.remove()`) — sie braucht kein ✕ und
   soll auch keins zeigen, sonst stünde an der leeren Einstiegskarte ein Knopf für etwas, das der
   Klick daneben schon tut. Mit der ersten Frage wird sie zu `.home-chat` (`footAsk`) und ist ab
   da eine Panele wie jede andere — mit ✕. Kacheln (1×1) bleiben ausgenommen, dieselbe Grenze wie
   bei Titelzeile und Fußzeile: dort ist ein Klick das Aufziehen, kein Platz für Bedienung.
   Board-Möbel (`.pinned`) bekommen von `chrome()` ohnehin keins (`FOOT_SKIP`). */
/* `z-index` über der offenen Fußzeile: `.panel.reco-open .pfoot` steht auf 1301 (§oben, damit der
   Senden-Pfeil nicht am Ziehgriff hängenbleibt) — und in `.home-chat` füllt diese Fußzeile die
   GANZE Panele (inset:0, §oben). Mit einem kleinen Wert lag das ✕ zwar oben rechts, aber UNTER dem
   Antworttext: im echten Browser gemessen (2026-08-24) lieferte `elementFromPoint` in seiner Mitte
   `.pf-ans-q`, der Klick kam nie an. Innerhalb der Panele ist der Wert lokal (jede Panele ist ein
   eigener Stapelkontext), 1302 hebt also nichts über eine andere Panele. */
.panel > .p-x{ position:absolute; top:6px; right:6px; z-index:1302; width:26px; height:26px;
  border:0; padding:0; border-radius:50%; background:rgba(255,255,255,.88); color:#64748b;
  display:inline-flex; align-items:center; justify-content:center; cursor:pointer;
  opacity:0; transition:opacity .12s, background .12s, color .12s; }
.panel > .p-x svg{ width:15px; height:15px; }
/* NUR die Sichtbarkeit hängt am Überfahren, NICHT `pointer-events`. Beides zusammen ist ein
   Henne-Ei-Problem beim Treffertest: der erste Zeigerdruck in der Ecke wird noch mit dem alten
   Stil (`pointer-events:none`) ausgewertet und geht durch das ✕ hindurch an den Text darunter —
   im echten Browser gemessen (2026-08-24: `elementFromPoint` in der Mitte des ✕ lieferte
   `.pf-ans-q`, der Klick kam nie an). Dauerhaft klickbar ist gefahrlos: unsichtbar ist es nur,
   solange der Zeiger NICHT auf der Panele ist — und dann kann dort auch nicht geklickt werden. */
.panel:hover > .p-x{ opacity:1; }
.panel > .p-x:hover{ background:#e2e8f0; color:#0f172a; }
.panel.home > .p-x,
.panel:not(.sz-panel):not(.sz-full):not(.sz-custom) > .p-x{ display:none; }
#board.board-dark .panel > .p-x{ background:rgba(15,23,42,.82); color:#cbd5e1; }
#board.board-dark .panel > .p-x:hover{ background:#1e293b; color:#f8fafc; }
/* Ohne Zeigegerät gibt es kein „Überfahren" — dort stünde ein Knopf, den nichts erreichbar macht.
   Am Handy ist jede Panele Vollbild, das ✕ also der nächstliegende Weg hinaus. */
@media (hover:none){ .panel > .p-x{ opacity:1; } }

/* ===== §41 — PANEL-EIGENE KNÖPFE STEHEN LINKS NEBEN DEM ✕ (2026-08-25) ========================
   Nutzerwunsch: „wie könnten wir in Panelen einstellen, dass die Knöpfe IMMER links neben dem
   allgemeinen Schließen sind". Bis hierher setzte jede Panele ihre eigenen Knöpfe selbst auf
   `top:6px; right:6..10px` — also genau dorthin, wo seit §39 das ✕ liegt (gemessen deckungsgleich:
   `.tp-x` in `toolPanel`, `.av-x` im Avatar). Statt in jeder Panele einen Abstand zu raten, hält
   die tragende Panele den Platz offen: `--p-acts-right` ist der EINE Ort, an dem die Breite des ✕
   verrechnet wird (6 Rand + 26 Knopf + 6 Abstand). Eine Panele ohne ✕ (`.home`, Kacheln — siehe
   die beiden `display:none`-Regeln oben) setzt denselben Wert auf den blanken Rand; die Leiste
   rutscht mit, ohne dass eine einzelne Panele davon etwas weiß.
   Die Leiste hängt NICHT am Überfahren: „Zurück"/„Neu laden" sind Inhalt der Panele und müssen zu
   sehen sein — das ✕ ist Rahmen und kommt erst bei Benutzung. */
.panel{ --p-acts-right:38px; --p-acts-w:0px;
  /* Wie breit die obere rechte Ecke belegt ist: die Leiste plus das ✕ dahinter. `--p-acts-w`
     setzt `panelActs` beim Ein-/Aushängen (Knopfzahl × 32 = 26 Knopf + 6 Abstand) — ohne das
     müsste jede Zeile, die hier Platz freihält, raten, wieviele Knöpfe gerade stehen. */
  --p-corner:calc(var(--p-acts-right) + var(--p-acts-w)); }
.panel.home,
.panel:not(.sz-panel):not(.sz-full):not(.sz-custom){ --p-acts-right:6px; }
.panel > .p-acts{ position:absolute; top:6px; right:var(--p-acts-right); z-index:1302;
  display:flex; gap:6px; align-items:center; }
.panel > .p-acts:empty{ display:none; }
#board.board-dark .panel > .p-acts{ color:#cbd5e1; }

/* §41 — DIE EINGABE IST EIN SOFORTBILD (2026-08-25, Nutzerwunsch „mach den ‚Frage stellen …'
   bereich in der panele eingerahmt, wie bei einem polaroid foto"). Die Leiste lag randlos auf den
   drei Kanten der Panele und war vom Inhalt nur durch ihre Trennlinie geschieden. Jetzt steht sie
   als KARTE darin: ringsum gleich viel Luft, ein dünner Rand, ein flacher Schatten — und unten die
   breite Kante des Sofortbilds. Das Feld selbst bekommt einen Hauch Grund; ohne ihn wäre der weiße
   Rahmen auf weißem Grund kein Rahmen, sondern nur Abstand.
   AUSGENOMMEN `.home`/`.home-chat`: deren Fußzeile FÜLLT die Panele seit 2026-08-24 (§oben, „die
   Box soll die ganze Panele einnehmen") — Rahmen, Radius und Schatten sind dort bewusst gefallen,
   weil sonst ein zweiter Kasten randgenau im ersten stünde. Ausgenommen auch `bar-top`/`bar-in`:
   dort ist die Box ausdrücklich rahmenlos eine Zeile IM Strom (§30.26).
   Der Senden-Pfeil braucht keine eigene Zahl: `sendMitte()` rechnet ihn aus der lebenden Geometrie
   gegen den Innenrand der Karte (`--pf-send-b`, board.js) — die breite Unterkante geht dabei von
   selbst in die Rechnung ein. Nur die Panele, die bisher der festen Basiszeile folgten, werden
   hier auf dieselbe Variable gehoben; sonst stünde ihr Pfeil auf der Unterkante statt auf der
   Textzeile. Mikrofon/Anhang bleiben unberührt — sie sind bei offener Eingabe ohnehin verdeckt
   (`.panel.reco-open > .panel-foot > :not(…)`, §oben).
   Und der Detailbereich MUSS den neuen Platz kennen (`--foot-res`), sonst liegt das Ende des
   Inhalts unter der Karte — genau der Fehler, für den `--foot-res` das eine Maß ist. */
.panel.reco-open:not(.bar-top):not(.bar-in):not(.home):not(.home-chat){
  --pola-luft:10px; --pola-kante:26px;
  --foot-res:calc(var(--foot-h) + var(--pola-luft) + var(--pola-kante) + 10px); }
.panel.reco-open:not(.bar-top):not(.bar-in):not(.home):not(.home-chat) .pfoot{
  left:8px; right:8px; bottom:8px;
  padding:var(--pola-luft) var(--pola-luft) var(--pola-kante);
  background:#fff; border:1px solid #e5e7eb; border-radius:2px;
  box-shadow:0 1px 2px rgba(15,23,42,.10), 0 8px 18px -6px rgba(15,23,42,.28); }
.panel.reco-open:not(.bar-top):not(.bar-in):not(.home):not(.home-chat) .pfoot .pf-reco-ta{
  background:#f8fafc; border-radius:1px; }
.panel.reco-open:not(.bar-top):not(.bar-in):not(.home):not(.home-chat) .pfoot .pf-send{
  bottom:var(--pf-send-b, calc(var(--pola-kante) + 4px)); }
/* Die eine Regel, die den freizuhaltenden Platz aus `--foot-h` statt aus `--foot-res` nimmt. */
.panel.touch.reco-open:not(.bar-top):not(.bar-in):not(.home):not(.home-chat) .touch-body{
  padding-bottom:calc(var(--foot-res) + 8px); }
#board.board-dark .panel.reco-open:not(.bar-top):not(.bar-in):not(.home):not(.home-chat) .pfoot{
  background:#0f172a; border-color:#1e293b; }
#board.board-dark .panel.reco-open:not(.bar-top):not(.bar-in):not(.home):not(.home-chat) .pfoot .pf-reco-ta{
  background:#0b1220; }

/* §42 — DAS WARTENDE HAT EINE GESTALT (2026-08-25, Nutzerwunsch „da muss etwas variation rein.
   und eine prozessierungs zeit angezeigt werden. plus den ablauf der tool aufrufe").
   Drei Zeilenarten, alle leise — sie sind der WEG, nicht die Antwort (dieselbe Haltung wie beim
   Denken im Kommando-Panel, §30.20): oben das wechselnde Wort mit der laufenden Zeit rechts
   daneben, darunter je Werkzeug eine Zeile in der Reihenfolge, in der es lief. Die Uhr steht
   rechts und in Tabellenziffern, damit sie beim Weiterzählen nicht springt. Die Dauer unter der
   fertigen Antwort trägt dieselbe Farbe — sie ist dieselbe Auskunft, nur zum Schluss.
   „Leise" ist AUSSCHLIESSLICH die Farbe (2026-08-25, Nutzerwunsch „die agenten texte sollen nicht
   kursiv sein. in gleicher schriftart wie der restliche text. nur heller"): keine Kursive, keine
   eigene Schriftgröße — dieselbe Schrift wie die Antwort daneben, nur heller. Zwei Unterschiede
   auf einmal (schräg UND kleiner UND blasser) lesen sich als zweite Textsorte, nicht als Nebenton.
   Gebaut wird das in `warten()` (board.js), hier steht nur, wie es aussieht. */
.pf-wait{ line-height:1.5; }
.pf-wait-k{ display:flex; align-items:baseline; gap:8px; color:var(--muted,#6b7280); }
.pf-wait-w{ flex:1 1 auto; min-width:0; }
.pf-wait-z{ flex:0 0 auto; font-variant-numeric:tabular-nums; opacity:.75; }
.pf-wait-s{ margin-top:2px; padding-left:2px; color:var(--muted,#6b7280); opacity:.9;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* §43 — DASSELBE SOFORTBILD, WO DIE FUSSZEILE DIE PANELE IST (2026-08-25, Nutzerwunsch „prüf den
   footer bei afsde in den panelen, so soll es überall aussehen ohne den runden punkt" + „zieh über
   dem footer eine linie hinein"; am selben Tag nachgezogen: „auch das fresh home panel soll die
   weisse fläche anzeigen. reduzier das padding zwischen den inhalten der panel und dem rahmen").
   §41 gibt jeder Panele die eingerahmte Eingabe — AUSSER `.home` und `.home-chat`, deren Fußzeile
   die ganze Panele füllt (§oben, 2026-08-24). Dort IST DIE KARTE DIE PANELE: Weiß, Rahmen, Radius
   und Schatten kommen von `.panel`, und die Fußzeile trägt nur noch die Innenabstände der Karte —
   oben und seitlich `--pola-luft`, unten die breite `--pola-kante`, die Kante des Sofortbilds.
   Der erste Versuch legte Rand und Schatten auf die EINGABEZEILE und machte die Panele dafür
   durchsichtig (sonst stünden zwei Kästen ineinander). Gemessen sah die Einstiegsfläche danach
   keine weiße Fläche mehr, sondern eine graue Zeile auf dem Brett — genau das war der Einwand.
   Jetzt trägt EINE Fläche den Rahmen, die Panele — und die Eingabe darin hat keine eigene Optik
   mehr, weder Rand noch Grund („the input box should also have white background color"). Bei afsde
   ist das getönte Feld sinnvoll, weil die Karte dort IN einer Panele mit Inhalt liegt; hier ist die
   Karte die ganze Fläche, und ein zweiter Ton darin wäre wieder ein Kasten im Kasten. Weiß kommt
   ohne eigene Zeile: die Grundregel `.pfoot .pf-reco-ta` ist `background:transparent`, darunter
   liegt die Panele — hell wie dunkel richtig.
   `--pola-luft` ist 12, in drei gemessenen Schritten dahin: 17 px seitlich (1 Rand + 16 Karten-
   polster) und 11 px oben, dann 7/8 („reduzier das padding"), dann 9/10 („increase the padding
   again a bit") — jetzt 13/14.
   Die breite Unterkante des Sofortbilds ist HIER entfallen (`--pola-kante` = `--pola-luft`):
   „die input box soll by default einzeilig hoch sein". Die Eingabe war schon immer eine Zeile hoch
   (gemessen 30 px = `--foot-h`, `scrollHeight` 30) — was zwei Zeilen ergab, war die 26 px breite
   Kante darunter, die in einer Fläche, die NUR aus der Eingabe besteht, wie eine zweite leere Zeile
   dastand. In den Panelen mit Inhalt (§41) bleibt sie: dort liegt die Karte auf etwas und die Kante
   trennt sie davon.
   Kein `--pf-send-b`-Zuschlag mehr: der Pfeil hängt an der Mitte der Eingabebox (`sendMitte()` in
   board.js), und seit die Kanten an der Fußzeile hängen, ist die Box wieder symmetrisch — Mitte der
   Box = Mitte der Textzeile. Die generische Zeile `bottom:var(--pf-send-b, 8px)` (§oben) genügt.
   Der runde Punkt (`.pf-rest`) kommt ausdrücklich NICHT mit: bei offener Eingabe ist er überall
   verdeckt (§oben), im Ruhezustand ist die Fußzeile selbst verdeckt (§30.21) — die afsde-Optik ist
   der GEÖFFNETE Zustand, gemessen an jeder Panele dort (jedes `.pf-rest`-Rechteck 0×0). */
.panel.home.reco-open:not(.bar-top):not(.bar-in),
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in){ --pola-luft:12px; --pola-kante:12px; }
.panel.home.reco-open:not(.bar-top):not(.bar-in) > .panel-foot,
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) > .panel-foot{
  padding:var(--pola-luft) var(--pola-luft) var(--pola-kante); }
/* Die Linie über der Eingabe („zieh über dem footer eine linie hinein"): sie gehört zur Antwort
   darüber, nicht zur Karte darunter — so steht sie über die ganze Breite und bleibt stehen, wenn
   der Text in seiner Fläche rollt (Rahmen rollen nicht mit). Vor der ersten Frage ist die Fläche
   leer und verdeckt (`:empty`, §oben) — dann gibt es auch nichts zu scheiden. */
.panel.home-chat.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-ans-block{
  border-bottom:1px solid #e5e7eb; padding-bottom:10px; }
#board.board-dark .panel.home-chat.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-ans-block{
  border-bottom-color:#1e293b; }

/* §44 — WÄHREND ES LÄUFT, IST DAS WARTENDE DIE EINGABE (2026-08-25, Nutzerwunsch „platzier die
   prozessierungzeit und die agenten prozesierung an stelle der input box. und wenn man drauf
   klickt dann kommt wieder die input box.").
   Das Wartende (§42) stand bisher ÜBER der weiter sichtbaren Eingabe — zwei Zeilen für EINEN
   Zustand, und die untere lud zum Schreiben ein, während oben noch gerechnet wurde. Jetzt weicht
   die Eingabe, solange der Zug läuft (`pf-wartet`, gesetzt und genommen in `warten()`); das
   Wartende liegt ohnehin schon in derselben Fußzeile (`appAns` → `.pf-ans-block`) und rückt damit
   von selbst an ihre Stelle. Nur AUSBLENDEN, nicht schließen: die Box behält Text, Höhe und
   Fokusweg, ein Klick auf das Wartende zeigt sie sofort wieder (Handler in board.js).
   In der Einstiegsfläche hängt die Karte dabei UNTEN (`margin-top:auto` statt `flex:1 1 auto`,
   §oben): die Eingabe stand am unteren Rand, und genau dort soll das Wartende stehen — sonst
   rutschte es an den Kopf einer leeren Spalte. Die Trennlinie (§43) fällt mit; sie scheidet
   Antwort von Eingabe, und unter dem Wartenden steht keine mehr. `cursor:text` sagt die Geste
   an: hier wird geschrieben, sobald man hintippt. */
.panel.pf-wartet.reco-open > .panel-foot > .pf-reco-ta,
.panel.pf-wartet.reco-open > .panel-foot > .pf-send,
.panel.pf-wartet.reco-open > .panel-foot > .pf-tools{ display:none !important; }
.panel.pf-wartet.reco-open:not(.bar-top):not(.bar-in) .pfoot .pf-ans-block{
  flex:0 0 auto; margin-top:auto; margin-bottom:0; border-bottom:0; padding-bottom:0; }
.panel.pf-wartet .pf-wait{ cursor:text; }

/* §45 — DER ERKLÄRTEXT IST DIE FRAGE (2026-08-29, Nutzerwunsch „let the explanation text have the
   option to click on it. then it will result in an input box for the chat prompt to show a
   different answer in the explanation box").
   Ein Element mit `data-frage="<Abschnittstitel>"` wird anklickbar; verdrahtet in board.js (§45
   dort), das Panel liefert nur das Attribut. Hier steht ausschließlich die GESTE: dass man hier
   tippen kann, und dass die Eingabe auf der Zeile des Textes sitzt statt daneben. Farben erben
   (currentColor/inherit) — jede Panele bringt ihre eigene Palette mit, und der Erklärtext soll
   nach dem Tausch aussehen wie vorher. */
[data-frage]{ cursor:pointer; }
[data-frage]:hover{ background:rgba(127,127,127,.08); border-radius:4px; }
[data-frage].frage-an,[data-frage].frage-laeuft{ cursor:default; background:none; }
[data-frage].frage-laeuft{ opacity:.6; }
.frage-box{ display:flex; align-items:baseline; gap:8px; }
.frage-in{ flex:1 1 auto; min-width:0; font:inherit; color:inherit; background:transparent;
  border:0; border-bottom:1px solid currentColor; padding:1px 0; outline:none; }
.frage-tip{ flex:0 0 auto; font-size:11px; opacity:.55; }
.frage-zurueck{ font-size:11px; opacity:.55; cursor:pointer; text-decoration:underline;
  margin-left:8px; white-space:nowrap; }

/* ---- Möbel-Chips in der Home-Panele (board_config.home_chips, `mountHomeChips`) ------------
   Die Kacheln sind DIESELBEN `.panel`-Elemente wie auf dem Brett — sie stehen nur woanders.
   Deshalb wird hier nichts nachgebaut, sondern das Panel-Aussehen für diesen Wirt überschrieben:
   aus dem Rasterfeld wird ein Flussobjekt, aus der Kachel eine Pille. Panel-Ecke (✕/Aktionen)
   und Fußzeile gehören dem Brett und haben in einem Chip nichts zu suchen. */
.home-chips{ display:flex; flex-wrap:wrap; gap:6px; padding:6px 8px 2px; align-items:center; }
.home-chips > .panel.as-chip{
  position:static; grid-column:auto; grid-row:auto; flex:0 0 auto;
  width:auto; height:26px; min-width:0; min-height:0; max-width:none; max-height:none;
  border-radius:999px; box-shadow:none; cursor:pointer; }
.home-chips > .panel.as-chip > .panel-body{ padding:0; overflow:hidden; }
.home-chips > .panel.as-chip > .p-acts,
.home-chips > .panel.as-chip > .panel-foot,
.home-chips > .panel.as-chip > .p-close,
.home-chips > .panel.as-chip .lt-sec{ display:none; }
.home-chips > .panel.as-chip .lt-tile{ flex-direction:row; gap:5px; height:26px; padding:0 9px; }
.home-chips > .panel.as-chip .lt-ic{ display:flex; align-items:center; }
.home-chips > .panel.as-chip .lt-ic svg,
.home-chips > .panel.as-chip img{ width:14px; height:14px; }
.home-chips > .panel.as-chip .lt-name{ font-size:.74rem; white-space:nowrap; }
.home-chips > .panel.as-chip:hover{ border-color:#3b6fe0; }
