/* Stimme an/aus. Erbt das Aussehen der Leiste, in der er steht — deshalb hier
   nur, was ihn als EINGESCHALTET kenntlich macht. */

.stimme-schalter.on { color: var(--accent); }

/* Am Handy steht er dort, wo am Schreibtisch der Canvas-Knopf sitzt.
   Alex, 27.08.: Der Ort ist eine Platzfrage — der Schalter gilt trotzdem
   fuer die ganze Foederation, nicht fuer den gerade offenen Agenten. */
.stimme-schalter.nur-handy { display: none; }

@media (max-width: 760px) {
  .stimme-schalter.nur-handy { display: inline-flex; }
}

/* Umgekehrt: am Schreibtisch sitzt er links oben in der Kopfleiste, am
   Handy waere er dort doppelt. */
@media (max-width: 760px) {
  .stimme-schalter.nur-desktop { display: none; }
}
/* Die Ansichts-Knöpfe. Gefaltet wird eine Ebene höher in `KopfGruppe` —
   diese Datei ordnet nur noch an.

   `display: contents` an beiden Behältern: Die Knöpfe liegen damit direkt in
   der Reihe ihres Elternteils, egal ob das die Kopfzeile (Schreibtisch) oder
   das Untermenü (Telefon) ist. Ein eigener Kasten hätte im Menü eine zweite
   Spalte aufgemacht. */
.linsen-wahl { display: contents; }
.linsen-wahl-breit { display: contents; }

/* Am Telefon stand hier einmal ein eigenes Auswahlmenü. Es ist am 29.08.
   entfallen, nachdem Alex die Ansichten in dieselben drei Punkte gelegt haben
   wollte wie Stimme, Vorlesen und Lesezeichen: „hau die Zeit und das alles
   auch in die drei Punkte rein." Ein Menü im Menü wäre daraus geworden. */

/* Am Schreibtisch steht die Sicht-Wahl seit 15.09. in der Sidebar bei den globalen
   Schaltern (Alex, Bild 125186: „links raus zum AgentOS, wo die anderen Buttons
   sind"). Im Kopf steht sie nur dort, wo die Sidebar NICHT neben dem Agenten
   steht — dieselbe Bedingung wie das Telefon-Layout in SessionList.css. Sonst gäbe
   es Breiten mit zwei Wahlen (Alex 17.09.: „am Desktop habe ich links im Menü die
   Auswahl") oder mit keiner. */
.linsen-wahl.nur-handy .conversation-view-toggle { display: none; }
@media (max-width: 768px), (max-height: 500px) {
  .linsen-wahl.nur-handy .conversation-view-toggle { display: inline-flex; }
}
/* Sicht für alle Agenten — Sidebar, unter dem Logo (Alex 15.09., Bild 125186).
   Seit 17.09. quadratische Symbol-Knöpfe wie die Knöpfe oben im Agentenkopf
   (.ahx-btn): 32 px, 1-px-Rahmen, dunkel wenn aktiv. Kein Text — der Name steht
   im Tooltip (Alex: „das würde mir reichen, nicht mit Text"). */
.sicht-leiste {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
.sicht-knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.sicht-knopf:hover { background: var(--bg-light); }
.sicht-knopf.active {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
}
.sicht-knopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Live mic-level VU meter (Alex 2026-06-26) — bars dance with the mic input
   so you can SEE capture instead of guessing.

   These rules live HERE, next to the component, not in the CSS of whichever
   view happened to use it first (AgentDetail). MultiAgent is lazy-loaded into
   its own chunk: had the styles stayed behind in a foreign file, the meter
   would have rendered as invisible zero-height spans the moment that file was
   no longer in the same bundle — looking exactly like the dead mic it exists
   to rule out. */
.voice-vu {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  height: 18px;
  flex-shrink: 0;
}
.voice-vu-bar {
  width: 3px;
  background: var(--accent);
  border-radius: 1px;
  min-height: 2px;
  transition: height 80ms ease-out;
}
/* WebGL lives inside the existing voice circle. This radial background is also
   the no-WebGL fallback: graphics failure must never break the voice action. */
.audio-blob-field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  contain: strict;
}

/* DER HINTERGRUNDKREIS GEHOERT NUR DEM RUECKFALL.
   ────────────────────────────────────────────────────────────────────────
   Diese Farbverlaeufe waren immer als Ersatz gedacht, falls WebGL fehlt —
   "graphics failure must never break the voice action". Solange der Shader
   deckend zeichnete, sah man sie nie.

   Seit er mit durchsichtigem Hintergrund zeichnet (27.08., Alex' magenta
   Knopf), schienen sie durch: eine blasse Kugel HINTER der eigentlichen
   Form. Alex, 28.08.: "kannst du den Hintergrundkreis entfernen, nur die
   Form selbst mit dem Orb und dem Glow waere geil."

   Sie sind nicht falsch, sie standen nur am falschen Ort. Jetzt haengen sie
   an `data-webgl='fallback'` — dort, wo sie gebraucht werden, und nur da.
   Das Attribut setzt der Renderer selbst beim Aufbau. */
.audio-blob-field[data-webgl='fallback'] {
  border-radius: 50%;
  background:
    radial-gradient(circle at 36% 28%, rgb(255 255 255 / 0.24), transparent 27%),
    radial-gradient(circle at 62% 64%, rgb(40 215 255 / 0.32), transparent 48%),
    radial-gradient(circle at 45% 50%, rgb(255 28 143 / 0.42), rgb(47 7 78 / 0.28) 62%, transparent 76%);
  filter: saturate(1.08);
  opacity: 0.96;
}

.audio-blob-field[data-webgl='fallback'] {
  animation: voice-orb-fallback 3.8s ease-in-out infinite alternate;
}

@keyframes voice-orb-fallback {
  from { filter: saturate(1.02) brightness(0.92); }
  to { filter: saturate(1.15) brightness(1.08); }
}

@media (prefers-reduced-motion: reduce) {
  .audio-blob-field[data-webgl='fallback'] { animation: none; }
}
.audio-input-picker {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  color: inherit;
  font-size: 10.5px;
}

.audio-input-picker select {
  min-width: 110px;
  max-width: 190px;
  height: 24px;
  padding: 0 22px 0 6px;
  border: 1px solid currentColor;
  border-radius: 0;
  background: var(--surface);
  color: var(--text-primary);
  font: inherit;
  text-transform: none;
  letter-spacing: 0;
  text-overflow: ellipsis;
}

.audio-input-picker select:disabled { opacity: 0.6; }
.audio-input-picker.has-error { color: #dc2626; }
.audio-input-picker.compact { flex: 0 1 auto; max-width: 100%; }
.audio-input-picker.compact select {
  width: clamp(132px, 42vw, 220px);
  min-width: 0;
  max-width: 100%;
}
.audio-input-active {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: 0.78;
}

@media (max-width: 620px) {
  .audio-input-picker { flex: 1 1 100%; }
  .audio-input-picker select { flex: 1; max-width: none; }
  .audio-input-active { max-width: 120px; }
}
/* SmartTable (Alex 2026-07-15) — table with a Tabelle/Karten view toggle. */
.smart-table { margin: 10px 0; }

.st-toolbar {
  display: flex;
  gap: 4px;
  justify-content: flex-end;
  margin-bottom: 4px;
}
.st-mode {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 22px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 0;
}
.st-mode.active {
  color: var(--text-primary);
  border-color: var(--border-strong);
  background: var(--chip-active-bg);
}
.st-mode:hover { color: var(--text-primary); }

/* Table mode — horizontal scroll container so a wide table never breaks the
   page layout (it scrolls inside its own box). */
.st-scroll { overflow-x: auto; }
.smart-table .md-table {
  border-collapse: collapse;
  width: 100%;
  font-size: 13px;
}
.smart-table .md-table th,
.smart-table .md-table td {
  border: 1px solid var(--border);
  padding: 6px 10px;
  text-align: left;
  vertical-align: top;
}
.smart-table .md-table th {
  background: var(--bg-light);
  font-weight: 600;
  color: var(--text-primary);
}

/* Cards / ticker mode — one row at a time, columns stacked vertically. */
.st-cards {
  border: 1px solid var(--border);
  background: var(--surface);
}
.st-card { padding: 4px 12px; }
.st-pair {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.st-pair:last-child { border-bottom: none; }
.st-key {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  font-weight: 600;
}
.st-val { font-size: 14px; color: var(--text-primary); line-height: 1.45; }
.st-val > :first-child { margin-top: 0; }
.st-val > :last-child { margin-bottom: 0; }
.st-empty { color: var(--text-muted); }

/* Ticker dots — small carousel-style indicators; tap to jump or swipe the card.
   The card is swipeable left/right (touch), so no slider/arrows needed. */
.st-dots {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  flex-wrap: wrap;
  padding: 9px 12px;
  border-top: 1px solid var(--border);
  background: var(--bg-light);
}
.st-dot {
  width: 6px;
  height: 6px;
  padding: 0;
  border-radius: 50%;
  border: none;
  background: var(--border-strong);
  opacity: 0.55;
  cursor: pointer;
  transition: opacity 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.st-dot:hover { opacity: 0.85; }
.st-dot.active {
  background: var(--accent);
  opacity: 1;
  transform: scale(1.35);
}
/* ── Agent Detail Container ───────────────────────────────────── */
.agent-detail-container {
  position: relative; /* anchors the glass header/footer overlays */
  flex: 1;
  display: flex;
  flex-direction: column;
  /* Use the JS-synced --vh from main.tsx (visualViewport.height) as the
     single source of truth — works pre-dvh and avoids iOS Safari's
     unreliable 100dvh which sometimes resolves to 100lvh (Large) even
     when the URL bar is visible, leaving a fat gap below the input. */
  height: calc(var(--vh, 1vh) * 100);
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
}

.agent-detail-container.drag-over {
  outline: 2px dashed var(--color-info);
  outline-offset: -2px;
}

/* ── Agent Header Bar ─────────────────────────────────────────── */
.agent-header {
  display: flex;
  align-items: center;
  gap: 12px;
  /* Oben und unten gleich (Alex 13.09.: „zwischen Header und Dropdown ein Gap von 10–15 px").
     Unten standen 16 px, oben 8 px: unter der Knopfzeile blieb ein Streifen Glas, bevor das
     Aufklappfeld begann — das las sich als Lücke. Die Höhe fließt über --agent-hdr-h in
     Verlauf und Aufklappfelder, nichts muss nachgezogen werden. */
  padding: 8px 32px;
  padding-top: calc(env(safe-area-inset-top, 0px) + 8px);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  /* Glassmorphism overlay (Alex 2026-07-03): translucent blur, theme-aware via
     --surface; the transcript scrolls beneath. */
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 95;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
}
/* No blur support → opaque surface (content still scrolls under, just hidden). */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .agent-header { background: var(--surface); }
}

/* Header-attached dropdown panels (issues, tags, group-chats) are SIBLINGS of the
   now-absolute header — in flow they'd start at container top, hidden behind the
   glass header ("fährt nur ein wenig raus", Alex 2026-07-03). Anchor them as glass
   overlays directly BELOW the header instead. */
.agent-detail-container > .agent-issues,
.agent-detail-container > .tagp,
.agent-detail-container > .agent-header-expand {
  position: absolute;
  top: var(--agent-hdr-h, 72px);
  left: 0;
  right: 0;
  z-index: 94;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  border-bottom: 1px solid var(--border);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .agent-detail-container > .agent-issues,
  .agent-detail-container > .tagp,
  .agent-detail-container > .agent-header-expand { background: var(--surface); }
}

/* Footer overlay wrapper (hosts InputBar) — the glass itself is painted by
   .input-bar-wrap / its rows (see InputBar.css). */
.agent-footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
}

.agent-header .status-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.agent-header .agent-name {
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  /* Allow the name to shrink in the flex header so it never pushes the action
     buttons off-screen — esp. on mobile (Alex 2026-06-24). */
  min-width: 0;
}
/* The name text truncates with an ellipsis; the caret (flex-shrink:0) stays. */
.agent-header .agent-name-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.agent-header .agent-name-clickable {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  cursor: pointer;
  user-select: none;
  border-bottom: 1px dotted transparent;
  transition: border-color 0.15s ease;
}

.agent-header .agent-name-clickable:hover {
  border-bottom-color: var(--text-muted);
}
.agent-header .agent-name-caret {
  opacity: 0.5;
  flex-shrink: 0;
  margin-top: 1px;
}
/* Tiny running-model tag beside the agent name (Alex 2026-07-14). */
/* DER NAME HAT VORRANG VOR DEM MODELL (Alex, 28.08., Bild 120945):
   „anstatt von GPT 5.6 … wenn es sich textuell nicht ausgeht, ist mir lieber,
   du zeigst nicht an welches LLM im Betrieb ist, sondern dass ich den Namen
   eher sehen kann, also der Name hat mehr Priorität."

   Warum es vorher genau andersherum war — und zwar nicht aus Absicht: Der
   Chip trug `flex-shrink: 0`, schrumpfte also NIE. Der Name daneben hat
   `min-width: 0` und eine Ellipse, gibt unter Druck also immer nach. Im
   schmalen Kopf blieb `gpt-5.6-sol` in voller Breite stehen und der Name
   verschwand vollstaendig — man sah, WELCHES Modell laeuft, aber nicht mehr,
   WER da spricht.

   Zwei Aenderungen: Der Chip darf jetzt schrumpfen und selbst ellipsieren,
   und unterhalb von 560px verschwindet er ganz. Das Modell bleibt im
   `title` und in den Einstellungen — es ist eine Zusatzangabe, kein Name. */
.agent-header .agent-name-model {
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.4;
  color: var(--text-muted);
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-radius: 0;
  white-space: nowrap;
  text-transform: none;
}

/* Login-Chip neben dem Modell (Alex 11.09., Bild 124885). Gleiche Form wie der
   Modell-Chip; die Stufe (aktiv/konfiguriert/unbekannt) steht im Wort, nicht nur
   in der Farbe. Warnung = Bot-Datei weicht vom Master ab. */
.agent-header .agent-name-login {
  flex-shrink: 1;
  min-width: 0;
  max-width: 12ch;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.4;
  color: var(--text-muted);
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-radius: 0;
  white-space: nowrap;
  text-transform: none;
}
.agent-header .agent-name-login.login-aktiv { color: var(--text-secondary); border-color: var(--border-strong); }
.agent-header .agent-name-login.login-unbekannt { border-style: dashed; }
.agent-header .agent-name-login.login-warnung { color: var(--color-warning); border-color: var(--color-warning); }

.header-action-status {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  margin-left: 8px;
}

.agent-header .agent-role {
  font-size: 13px;
  color: var(--text-muted);
  margin-left: 4px;
}

.agent-header .agent-meta {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 20px;
}

/* Explicit header action buttons — group-chats dropdown + new-groupchat.
   Sit at the far right (after the auto-margin meta block). Flat AgentOS
   square buttons (Alex 2026-06-22). */
.agent-header-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 14px;
  flex-shrink: 0;
}
.ahx-btn {
  display: inline-flex;
  align-items: center;
  gap: 1px;
  height: 32px;
  padding: 0 8px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  border-radius: 0;
}
.ahx-btn:hover { background: var(--bg-light); }
.ahx-btn.on {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
}
.ahx-btn-caret { transition: transform 0.15s ease; opacity: 0.7; }
.ahx-btn-caret.open { transform: rotate(180deg); }
/* Bookmark button: count badge + "agent is rewound" accent highlight. */
.ahx-btn-count {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1;
  margin-left: 2px;
  color: var(--text-secondary);
}
.ahx-btn.pinned {
  border-color: var(--accent);
  color: var(--accent);
}
.ahx-btn.pinned .ahx-btn-count { color: var(--accent); }
/* Unprocessed (open) issues for this agent (#177) — blue so it stands out at a glance. */
.ahx-btn.has-issues {
  border-color: var(--color-info);
  color: var(--color-info);
  background: var(--color-info-bg, var(--surface));
}
.ahx-btn.has-issues .ahx-btn-count { color: var(--color-info); }
/* When the panel is open, the active (dark) state still wins — higher specificity. */
.ahx-btn.has-issues.on { color: var(--white); border-color: var(--text-primary); background: var(--chip-active-bg); }
.ahx-btn.has-issues.on .ahx-btn-count { color: var(--white); }

.meta-tag {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 4px;
}

.meta-tag .label {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-family: var(--font-body);
  font-weight: 500;
}

/* Back-pressure queue depth (#1257 Phase B) — issues waiting for this agent. */
.meta-tag.meta-queued {
  color: var(--color-info);
  border: 1px solid var(--color-info);
  padding: 0 6px;
}
.meta-tag.meta-queued .label { color: var(--color-info); }

.badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 2px 8px;
}

.badge-success { background: var(--color-success-bg); color: var(--color-success); }
.badge-warning { background: var(--color-warning-bg); color: var(--color-warning); }
.badge-working { background: var(--accent-bg); color: var(--accent); }
.badge-error { background: var(--color-error-bg); color: var(--color-error); }
.badge-info { background: var(--color-info-bg); color: var(--color-info); }

/* Rate-limit badge: text + countdown sit above a thin progress strip
 * that grows from 0 → 100% over the watchdog's retry window (default
 * 180 s). Cloud-API commit 31a2735 emits stamped_at + retry_after on
 * the agent-state row so the strip is driven by absolute time, not
 * a local guess. */
.badge-rate-limited {
  position: relative;
  overflow: hidden;
  padding-bottom: 4px;
}

.badge-countdown {
  margin-left: 4px;
  opacity: 0.85;
  font-size: 10px;
}

.badge-progress {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  background: var(--color-warning);
  opacity: 0.7;
  transition: width 0.5s linear;
  pointer-events: none;
}

/* ── Content Stream ───────────────────────────────────────────── */
.content-stream {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 24px 32px;
  min-width: 0;
  min-height: 0;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.stream-entry {
  margin-bottom: 24px;
  min-width: 0;
  overflow: hidden;
}

.stream-entry:last-child {
  margin-bottom: 0;
}

/* ── User Input ───────────────────────────────────────────────── */
.entry-user {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.entry-user .entry-marker {
  width: 3px;
  min-height: 100%;
  background: var(--color-info);
  flex-shrink: 0;
  align-self: stretch;
}

.entry-user.source-queue .entry-marker { background: var(--color-warning); }
.entry-user.source-iacp .entry-marker { background: var(--accent); }
.entry-user.source-system .entry-marker { background: var(--border-strong); }

.entry-user .entry-content {
  padding: 8px 0;
  font-size: 14px;
  line-height: 1.6;
}

/* Direct user input: a glass bubble (Alex 2026-07-15 — the old dark/near-black
 * block read too harsh in light mode). Theme-aware via --surface: white frosted
 * glass in light, dark glass in dark; text stays --text-primary either way. Still
 * clearly a "human typed this" bubble (border + tint) vs. the bare agent prose,
 * without the heavy black slab. */
/* Eigene Eingabe: dieselbe Form wie ein Issue-Zug — ein flächiger heller Ton
   in der Farbe des Balkens, ohne Rahmen (Alex, 12.08.: „das helle Farbe im
   Seitenton gefällt mir gut bei Issue, mach User Input auch so mit hellgrau
   bei Schwarz, aber ohne den Rahmen rund um den Input").

   Vorher war es eine Glasblase mit Rand — die Blase hob den Text vom Rest ab,
   aber sie hob ihn nicht HERVOR, und genau das war die Beschwerde: „die geht
   fast unter". Der Ton nimmt den Balken auf, statt eine zweite Formsprache
   danebenzustellen.

   `--text-primary` als Tonquelle, damit es dem Balken folgt: hellgrau bei
   schwarzer Schrift, und in dunklem Thema ein heller Schleier statt eines
   schwarzen Flecks. 7% wie beim Issue-Zug — dieselbe Stärke, also dieselbe
   Familie. */
.entry-user.source-direct .entry-content {
  background: color-mix(in srgb, var(--text-primary) 7%, transparent);
  color: var(--text-primary);
  padding: 6px 10px;
}

/* Eigene Eingabe: kräftiger Balken links (Alex, 12.08.: „ich brauch da
   irgendwie noch einen schwarzen Balken links, damit ich meine Nachricht
   besser sehen kann, die geht fast unter").

   Er war seit 15.07. ausgeschaltet — damals ging es aber um den dunklen
   BLOCK hinter dem Text, der in hellem Thema zu hart wirkte. Die Glasblase
   bleibt; nur die Kante kommt zurück. Ein 4px-Streifen ist nicht dieselbe
   Sache wie eine schwarze Fläche.

   `--text-primary` statt echtem Schwarz, weil „schwarz" hier maximalen
   Kontrast meint, nicht den Farbwert: In dunklem Thema wäre ein schwarzer
   Balken unsichtbar — das Token ist dort hell und trägt dieselbe Absicht.

   GLEICHE BREITE wie die anderen Quellen (Alex, 12.08.: „der schwarze Balken
   ist dicker als die anderen, das passt ästhetisch nicht"). Ich hatte ihn
   verbreitert, um ihn auffälliger zu machen — das war eine Zutat zu viel:
   Der Kontrast allein trägt schon, und eine Reihe von Streifen in derselben
   Breite liest sich als System, eine mit einem dickeren als Ausnahme. */
.entry-user.source-direct .entry-marker {
  display: block;
  background: var(--text-primary);
}

.entry-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.user-media-row {
  display: flex;
  gap: 6px;
  margin-top: 6px;
  flex-wrap: wrap;
}

/* Gleich große Kacheln, Umbruch, Klick aufs Original (David #48, Steward 13.09.). */
.user-media-row > a { display: block; line-height: 0; }
.user-media-thumb {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: 0;
  background: var(--surface);
}

/* Abgelaufener Anhang: Portal-Uploads werden nach 24 h gelöscht, die
   Nachricht behält die Adresse. Benannter Zustand statt Browser-Bruchsymbol. */
.user-media-file,
.user-media-gone {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 56px;
  padding: 0 10px;
  border: 1px dashed var(--border);
  border-radius: 4px;
  color: var(--text-secondary);
  font-size: 11px;
  white-space: nowrap;
}

.entry-label-clickable {
  cursor: pointer;
}

.entry-label-clickable:hover {
  color: var(--text-primary);
}

.entry-source-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 1px 6px;
  margin-left: 8px;
  letter-spacing: 0;
  text-transform: none;
}

.entry-source-tag.queue {
  background: var(--color-warning-bg);
  color: var(--color-warning);
}

.entry-source-tag.iacp {
  background: var(--accent-bg-strong);
  color: var(--accent);
}

/* Small monochrome toggle to the right of the IACP/Queue tag — only
 * shown when the payload sniffer says XML or JSON. Click flips the
 * entry-content into a <pre> pretty-printed block. */
.format-toggle {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 1px 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  background: var(--bg-light);
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
  transition: all 0.15s ease;
}

.format-toggle:hover {
  background: var(--bg-inset);
  color: var(--text-primary);
}

.format-toggle.active {
  background: var(--chip-active-bg);
  color: var(--white);
  border-color: var(--text-primary);
}

.payload-pretty {
  margin: 0;
  padding: 10px 12px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-break: break-word;
  overflow-x: auto;
}

/* ── Agent Response ───────────────────────────────────────────── */
.entry-agent {
  padding-left: 15px;
  min-width: 0;
  overflow: hidden;
}

.entry-agent .entry-content {
  padding: 8px 0;
  font-size: 14px;
  line-height: 1.7;
  overflow-wrap: break-word;
  word-break: break-word;
  min-width: 0;
}

/* DIE MARKDOWN-TYPOGRAFIE GEHOERT DEM RENDERER, NICHT DER ANSICHT.
 *
 * ANLASS (Alex, 28.08.): „Wir haben ja ein spezielles Format-Styling fuer
 * Markdown, wie der Content dargestellt wird — und bei Codex2 schaut das
 * anders aus."
 *
 * Er hat recht, und die Ursache ist nicht der Renderer: Klassische Ansicht,
 * Kollab und Zeitlinie rendern Markdown mit DENSELBEN Bausteinen. Verschieden
 * war nur, WO das Ergebnis landet — und damit, welche Regeln greifen:
 *
 *     .entry-agent .entry-content   15 Regeln
 *     .collab-rich                   8
 *     .conversation-timeline         1
 *
 * Deshalb wurden Ueberschriften in der Zeitlinie riesig (Browser-Vorgabe),
 * Absaetze verloren ihren Abstand, `code` bekam keinen Rahmen.
 *
 * WARUM ERWEITERT UND NICHT UMGEZOGEN: In einer Selektorliste behaelt jeder
 * Selektor seine eigene Spezifitaet. `.entry-agent .entry-content p` bleibt
 * also (0,2,1) und die klassische Ansicht bit-genau, wie sie war; `.rich-md p`
 * kommt mit (0,1,1) daneben. Haette ich umgezogen, waere die Spezifitaet
 * gesunken und andere Regeln haetten stellenweise gewonnen — eine unsichtbare
 * Aenderung an einer Ansicht, die niemand angefragt hat.
 *
 * `rich-md` vergibt `RichMessage` selbst. Jede kuenftige Ansicht, die den
 * Renderer benutzt, bekommt die Typografie damit ohne eigenes Zutun.
 *
 * NACHTRAG 29.08. — DIE ZUSAGE GALT NUR FUER DIE HALBE RENDERSTRECKE.
 *
 * Alex: „Die H1 hat er viel zu gross gerendert. Bei der klassischen Ansicht
 * funktioniert das perfekt." Er hat recht, und Codex2 trifft keine Schuld:
 * Gewoehnlicher Agententext laeuft NICHT durch `RichMessage`, sondern durch
 * `SectionContent`, und die gab `<div class="entry-content">` aus — OHNE
 * `rich-md`.
 *
 * In der klassischen Ansicht steht dieses div unter `.entry-agent`, also
 * greift `.entry-agent .entry-content h1`. In Zeitlinie und Raumzeit gibt es
 * diesen Vorfahren nicht — dort griff GAR KEINE Regel, und der Browser setzt
 * H1 in Standardgroesse. Es war also kein abweichender Stil, sondern gar
 * keiner.
 *
 * Deshalb vergibt jetzt auch `SectionContent` (und die Werkzeug-/Diff-Koerper)
 * `rich-md`. Die klassische Ansicht aendert sich dabei nicht: Beide Selektoren
 * stehen in DERSELBEN Regel mit denselben Deklarationen, und wo sie
 * auseinandergingen, gewinnt der spezifischere klassische weiterhin. */
.entry-agent .entry-content p,
.rich-md p {
  margin: 0 0 8px;
}

.entry-agent .entry-content p:last-child,
.rich-md p:last-child {
  margin-bottom: 0;
}

.entry-agent .entry-content code,
.rich-md code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 1px 5px;
}

.entry-agent .entry-content pre,
.rich-md pre {
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 12px 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  overflow-x: auto;
  margin: 8px 0;
}

.entry-agent .entry-content pre code,
.rich-md pre code {
  background: none;
  border: none;
  padding: 0;
}

.entry-agent .entry-content ul,
.entry-agent .entry-content ol,
.rich-md ul,
.rich-md ol {
  padding-left: 20px;
  margin: 4px 0;
}

.entry-agent .entry-content a,
.rich-md a {
  color: var(--color-info);
  text-decoration: none;
}

.entry-agent .entry-content a:hover,
.rich-md a:hover {
  text-decoration: underline;
}

/* ── Pretty JSON ───────────────────────────────────────────────
 * Generic polished JSON view (Layer 1, Alex feedback 2026-06-04 on
 * screenshot 110171). Goals: read like a document, not like a debug
 * dump. Currency values pop, ISO dates auto-format, single-item arrays
 * lose their `0:` wrapper, empty objects/arrays skip rendering. No
 * domain-smart cards yet (Alex said not now). */
.json-pretty {
  padding: 6px 0;
  font-size: 13px;
  line-height: 1.55;
}

.json-pretty .json-pretty {
  padding: 0 0 0 14px;
  border-left: 1px solid var(--border);
  margin: 4px 0 4px 2px;
}

/* Semantic agent-card — rendering surface for persona-JSON output
   (Cloud IACP 57850f3a). Replaces the raw key-value dump with labelled
   sub-blocks for the well-known top-level fields: tts_summary,
   ergebnis, empfehlungen, memory_notes, _apus_chunk_. */
.agent-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.agent-card-summary {
  font-style: italic;
  color: var(--text-muted);
  border-left: 3px solid var(--border-strong);
  padding: 4px 0 4px 10px;
  font-size: 13px;
  line-height: 1.5;
}
.agent-card-section {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.agent-card-h {
  font-family: var(--font-heading);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  margin: 0;
}
.agent-card-list {
  list-style: disc;
  padding-left: 22px;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
}
.agent-card-list li {
  margin: 2px 0;
}

/* Memory-notes get an info-callout tint so they read distinctly from
   the action-oriented ergebnis/empfehlungen lists. */
.agent-card-memory {
  background: var(--bg-inset);
  border-left: 3px solid var(--accent, var(--text-primary));
  padding: 6px 10px;
  border-radius: 0 4px 4px 0;
}
.agent-card-memory .agent-card-list {
  list-style: none;
  padding-left: 0;
}
.agent-card-memory .agent-card-list li::before {
  content: '✎ ';
  color: var(--text-muted);
  margin-right: 4px;
}

/* Apus chunk-committed embed — content-api push payload re-emitted by
   the agent. Shows a compact post-link + section meta + preview text
   instead of a raw nested JSON. */
.agent-card-apus {
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
}
.agent-card-apus-meta {
  font-size: 11px;
  color: var(--text-muted);
  margin: 2px 0 6px;
  font-family: var(--font-mono);
}
.agent-card-apus-meta a {
  color: var(--text-primary);
  text-decoration: underline;
  font-weight: 600;
}
.agent-card-apus-text {
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-primary);
  white-space: pre-wrap;
}

/* Collapsed "Raw fields" — back-compat surface for keys the semantic
   renderer doesn't recognise. Hidden by default so the card stays
   scannable; users who care about debug fields can expand. */
.agent-card-debug {
  font-size: 12px;
}
.agent-card-debug summary {
  cursor: pointer;
  color: var(--text-muted);
  font-family: var(--font-mono);
  padding: 4px 0;
}
.agent-card-debug summary:hover {
  color: var(--text-primary);
}

.json-field {
  padding: 3px 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}

.json-key {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.02em;
  flex-shrink: 0;
  min-width: 88px;
  white-space: nowrap;
}

.json-key::after {
  content: ':';
  margin-left: 1px;
  color: var(--border-strong);
  font-weight: 400;
}

/* Internal/metadata keys (those starting with `_`) get de-emphasised
 * so the eye lands on the actual payload first. */
.json-key-meta {
  opacity: 0.6;
  font-style: italic;
}

/* Array item indices: numeric, slightly highlighted with the accent
 * colour so a list still reads as a list even without the `0:`-style
 * wrapper for single-item arrays. */
.json-key-index {
  min-width: 24px;
  color: var(--accent);
  font-weight: 600;
}

.json-key-index::after {
  content: '.';
}

.json-value {
  font-size: 13px;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* Currency: bold + monospace so subtotals visually align across a
 * column of rows (positions, expenses, …). */
.json-value-money {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.json-value-money.is-negative,
.json-value-num.is-negative {
  color: var(--color-error);
}

.json-value-num {
  font-family: var(--font-mono);
}

.json-value-date {
  color: var(--text-primary);
}

.json-value-long {
  display: block;
  flex-basis: 100%;
  margin-top: 2px;
  margin-left: 100px;
  line-height: 1.5;
  color: var(--text-primary);
  word-break: break-word;
}

.json-value-bool {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 12px;
}
.json-value-bool.is-true { color: var(--color-success); }
.json-value-bool.is-false { color: var(--color-error); }

.json-value-null {
  color: var(--text-muted);
  font-style: italic;
}

/* Mobile: drop the fixed key min-width so very narrow viewports don't
 * force the value onto its own line just because the key column took
 * 88px (Alex tests on iPhone portrait — visualViewport ~390px wide). */
@media (max-width: 480px) {
  .json-key { min-width: 0; }
  .json-value-long { margin-left: 0; }
}

.inline-media-img {
  max-width: 100%;
  max-height: 300px;
  margin: 8px 0;
  display: block;
  border: 1px solid var(--border);
  /* High-quality downscale: avoids the moiré bands Alex saw on helmet
     photos (fine parallel vents interacting with retina sub-pixel
     resampling). -webkit-optimize-contrast asks Safari/Chrome for the
     better bicubic-ish resampler instead of the cheap bilinear default. */
  image-rendering: -webkit-optimize-contrast;
  image-rendering: high-quality;
}

/* ── Content Post Embed ──────────────────────────────────────── */
.content-post-embed {
  position: relative;
  /* Volle verfügbare Breite statt 480px-Deckel (Alex #1573, Bild 123017:
     der Beitrag nutzte die halbe Fläche, rechts blieb Leere). Die Spalte
     des Gastgebers begrenzt weiterhin — der Beitrag füllt sie nur aus. */
  max-width: 100%;
  margin: 8px 0;
  /* Rahmen (Alex #1885, Bild 125210): Seit der iframe weg ist (28.08.), trug nur
     noch dessen Regel einen Rand — der eingebettete Beitrag selbst hatte keinen
     und war im hellen Theme vom Fließtext nicht zu unterscheiden. Eckig, flach,
     die kräftige Rahmenfarbe (--border ist auf Weiß kaum sichtbar). */
  border: 1px solid var(--border-strong);
  background: var(--surface);
}

/* Der iframe ist weg — der Beitrag wird jetzt selbst geholt und gerendert
   (28.08.). Die Regel bleibt als Rueckfall stehen, falls irgendwo noch eine
   Einbettung alter Art auftaucht; neu erzeugt wird sie nicht mehr. */
.content-post-iframe {
  width: 100%;
  height: 320px;
  border: 1px solid var(--border);
  background: var(--surface);
  display: block;
}

.content-post-title {
  font-family: var(--font-heading);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  padding: 8px 10px 0;
}

/* Der Beitragstext erbt die Markdown-Typografie ueber `rich-md`, das
   `RichMessage` selbst vergibt — hier nur Rand und Hoehe. */
.content-post-body {
  padding: 4px 10px 10px;
  max-height: 420px;
  overflow-y: auto;
}

/* Ein Satz statt einer leeren Flaeche: „laedt", „kein Zugriff", „gibt es
   nicht", „ging nicht". Alle vier sind Auskuenfte; die leere Flaeche war
   keine. */
.content-post-note {
  display: block;
  padding: 10px;
  font-size: 12px;
  color: var(--text-muted);
}

.content-post-open {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  color: var(--text-primary);
  text-decoration: none;
  font-size: 12px;
  line-height: 1;
  opacity: 0.85;
  transition: opacity 0.15s ease;
}

.content-post-open:hover {
  opacity: 1;
  background: var(--bg-light);
}

/* ── Generic trusted-URL embed (standalone link → iframe) ───── */
.v2-content-embed {
  margin: 8px 0 8px 16px;
  max-width: 720px;
}

.v2-content-embed-iframe {
  width: 100%;
  height: 560px;
  border: 1px solid var(--border);
  background: var(--surface);
  display: block;
}

.v2-content-embed-caption {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 4px;
  padding-left: 4px;
}

.v2-content-embed-caption a {
  color: var(--text-muted);
  word-break: break-all;
}

.inline-media-audio {
  width: 100%;
  margin: 8px 0;
  display: block;
}

/* Audio player + explicit download button (Alex 2026-07-06 — native <audio>
   controls hide/omit download). Row: player grows, button sits at the end. */
.audio-block {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
}
.audio-block .inline-media-audio { margin: 0; flex: 1; min-width: 0; }
.audio-dl {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 0;               /* flat/square house style */
  background: var(--surface);
  cursor: pointer;
  text-decoration: none;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.audio-dl:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.inline-media-video {
  max-width: 100%;
  max-height: 300px;
  margin: 8px 0;
  display: block;
  border: 1px solid var(--border);
}

.entry-agent .entry-content h1,
.rich-md h1 {
  font-size: 16px;
  font-weight: 600;
  margin: 12px 0 6px;
  line-height: 1.4;
}

.entry-agent .entry-content h2,
.rich-md h2 {
  font-size: 15px;
  font-weight: 600;
  margin: 10px 0 4px;
  line-height: 1.4;
}

.entry-agent .entry-content h3,
.rich-md h3 {
  font-size: 14px;
  font-weight: 600;
  margin: 8px 0 4px;
  line-height: 1.4;
}

.entry-agent .entry-content h4,
.entry-agent .entry-content h5,
.entry-agent .entry-content h6,
.rich-md h4,
.rich-md h5,
.rich-md h6 {
  font-size: 13px;
  font-weight: 600;
  margin: 6px 0 4px;
  line-height: 1.4;
}

/* ── Tool Call (collapsible) ──────────────────────────────────── */
.tool-call {
  margin: 12px 0;
  border-left: 1px solid var(--border);
  margin-left: 15px;
}

/* AUFEINANDERFOLGENDE Werkzeug-Aufrufe ruecken zusammen (Alex #1371,
   Screenshot 120814: "da muss nicht so viel Abstand zwischen diesen
   gerappten Dropdowns liegen").

   Zwischen zwei zugeklappten Zeilen lagen 12 px Abstand plus je 8 px
   Innenrand — 40 px Rahmen um 16 px Text. Eine Folge von zehn Aufrufen
   fuellte damit einen halben Bildschirm, ohne mehr zu sagen.

   Der Abstand bleibt, wo er etwas trennt: vor dem ersten Aufruf, nach dem
   letzten, und um einen AUFGEKLAPPTEN, dessen Rumpf ein eigener Block
   ist. Nur die Luecke zwischen zwei geschlossenen Nachbarn faellt weg —
   sie trennt zwei Zeilen, die ohnehin zusammengehoeren. */
.tool-call + .tool-call { margin-top: 2px; }
.tool-call:has(> .tool-call-body:not(.collapsed)) { margin: 12px 0; }
.tool-call:has(> .tool-call-body:not(.collapsed)) + .tool-call { margin-top: 12px; }

.tool-call-header {
  display: flex;
  align-items: center;
  gap: 8px;
  /* 8 -> 5: der Innenrand traegt hier keine Information, er verdoppelte nur
     die Zeilenhoehe. Bei 12 px Schrift bleiben 5 px oben und unten gut
     antippbar (22 px Gesamthoehe, ueber der 44-px-Regel liegt die Zeile
     durch den Rand des Elternteils). */
  padding: 5px 12px;
  cursor: pointer;
  transition: background-color 0.15s ease;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
}

.tool-call-header:hover {
  background: var(--bg-light);
}

.tool-call-chevron {
  font-size: 10px;
  transition: transform 0.15s ease;
  color: var(--text-muted);
}

.tool-call-chevron.open {
  transform: rotate(90deg);
}

.tool-call-name {
  font-weight: 500;
  color: var(--text-primary);
}

.tool-call-status {
  margin-left: auto;
}

.tool-call-body {
  padding: 0 12px 12px;
}

.tool-call-body.collapsed {
  display: none;
}

/* ── IACP Federation Tool Calls ─────────────────────────────────── */
.iacp-tool-call {
  border-left-color: var(--accent);
  border-left-width: 2px;
}

.iacp-tool-call .tool-call-header {
  color: var(--text-primary);
}

.iacp-icon {
  color: var(--accent);
  flex-shrink: 0;
}

.iacp-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.04em;
}

.iacp-target {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
}

.iacp-target-unknown {
  color: var(--text-muted);
  font-weight: 400;
}

/* Clickable federation target — opens that agent's conversation. Styled as a
   bare button so it inherits .iacp-target and stays visually a name, not a
   control; the underline on hover is the only affordance it needs. */
button.iacp-target-link {
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
}

button.iacp-target-link:hover,
button.iacp-target-link:focus-visible {
  text-decoration: underline;
}

.iacp-msgid {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  background: var(--bg-light);
  padding: 1px 6px;
  border-radius: 8px;
  letter-spacing: 0.02em;
}

.iacp-preview {
  font-style: italic;
  color: var(--text-muted);
  font-size: 12px;
  padding: 6px 0 8px;
  line-height: 1.5;
  border-bottom: 1px dashed var(--border);
  margin-bottom: 8px;
}

/* ── Code Block ───────────────────────────────────────────────── */
.code-block {
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 12px 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  overflow-x: auto;
  white-space: pre;
  color: var(--text-primary);
  max-width: 100%;
}

/* Bounded raw-blob fallback (#4231): a huge unparseable dump collapses behind a
   disclosure so it never floods the transcript; body is scroll-capped when open. */
.raw-fallback { margin: 6px 0; }
.raw-fallback-sum {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text-muted);
  padding: 4px 0;
  user-select: none;
}
.raw-fallback-sum:hover { color: var(--text-primary); }
.raw-fallback-pre { max-height: 320px; overflow: auto; margin-top: 6px; }

/* ── Mermaid Diagram ──────────────────────────────────────────── */
.v2-mermaid {
  /* No frame, no background — diagram sits naked in chat flow. */
  background: transparent;
  border: none;
  padding: 0;
  margin: 8px 0 8px 16px;
  text-align: center;
  overflow-x: auto;
  max-width: 100%;
  /* Use containment so the browser doesn't have to re-flow surrounding
     content while the SVG's embedded <style> block is being parsed. */
  contain: layout style;
}

.v2-mermaid svg {
  max-width: 100%;
  height: auto;
}

/* FOUC defense: beautiful-mermaid emits SVG with an embedded <style>
   block, which the browser parses asynchronously. For a frame or two
   the SVG renders with the SVG default fills (#000000 — that's the
   black flash Alex sees). Force the safe defaults at the SVG element
   level so even the unstyled paint already looks right. */
.v2-mermaid svg rect,
.v2-mermaid svg polygon,
.v2-mermaid svg ellipse {
  fill: #ffffff;
}

.v2-mermaid svg path:not([fill]),
.v2-mermaid svg line:not([stroke]) {
  stroke: #6b7280;
}

.v2-mermaid svg text {
  fill: #1f2937;
}

.mermaid-fallback {
  /* Inherits .code-block styles; flag the failure with a subtle border */
  border-color: var(--color-warning, #B45309);
}

/* ── Diff Block ───────────────────────────────────────────────── */
.diff-block {
  background: var(--bg-inset);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  overflow-x: auto;
}

.diff-line {
  padding: 1px 16px;
  white-space: pre;
}

.diff-line.add {
  background: var(--color-success-bg);
  color: var(--color-success);
}

.diff-line.remove {
  background: var(--color-error-bg);
  color: var(--color-error);
}

.diff-line.context {
  color: var(--text-muted);
}

.diff-line.header {
  color: var(--color-info);
  font-weight: 500;
}

/* ── Inline Table ─────────────────────────────────────────────── */
.inline-table {
  width: 100%;
  border-collapse: collapse;
  margin: 8px 0;
}

.inline-table th {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--text-muted);
  text-align: left;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
}

.inline-table td {
  padding: 8px 12px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}

.inline-table td.mono {
  font-family: var(--font-mono);
  font-size: 12px;
}

.inline-table tbody tr {
  transition: background-color 0.15s ease;
}

.inline-table tbody tr:hover {
  background: var(--bg-light);
}

/* ── V2 Table (Markdown-rendered) ─────────────────────────────── */
.v2-table {
  margin: 8px 0 8px 15px;
  overflow-x: auto;
}

.v2-tasklist {
  margin: 6px 0 6px 15px;
  font-size: 12px;
}

.v2-tasklist-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px 3px 4px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 11px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}

.v2-tasklist-toggle:hover {
  border-color: var(--border-strong);
  color: var(--text-primary);
}

.v2-tasklist-chevron {
  flex-shrink: 0;
  transition: transform 0.15s ease;
}

.v2-tasklist-chevron.is-open {
  transform: rotate(90deg);
}

.v2-tasklist-label {
  white-space: nowrap;
}

.v2-tasklist-body {
  margin-top: 6px;
  padding: 10px 14px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  border-radius: 4px;
  font-size: 13px;
}

.v2-tasklist-body p {
  margin: 0 0 6px 0;
}

.v2-tasklist-body ul {
  list-style: none;
  padding: 0;
  margin: 4px 0;
}

.v2-tasklist-body li {
  padding: 2px 0;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.v2-tasklist-body input[type="checkbox"] {
  margin-top: 4px;
  accent-color: var(--accent);
  cursor: default;
}

.v2-tasklist-body em {
  color: var(--text-muted);
  font-size: 12px;
}

.v2-tasklist-footer {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
}

.v2-tasklist-body li strong {
  font-weight: 600;
  color: var(--accent);
}

.v2-tree {
  margin: 8px 0 8px 15px;
  padding: 12px 14px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  border-radius: 4px;
  overflow-x: auto;
}

.v2-tree-row {
  display: flex;
  font-family: var(--font-mono);
  font-size: 12px;
  white-space: pre;
  line-height: 1.6;
}

.v2-tree-prefix {
  color: var(--text-light);
  flex-shrink: 0;
}

.v2-tree-name {
  color: var(--text-primary);
}

.v2-tree-name.folder {
  color: var(--accent);
  font-weight: 600;
}

.v2-tree-annotation {
  color: var(--text-muted);
  margin-left: auto;
  padding-left: 16px;
  font-style: italic;
  font-size: 11px;
}

/* Einzeilige Tabelle = ein Datensatz, gestapelt statt als Gitter. Label und
   Wert stehen nebeneinander, solange Platz ist, und untereinander sobald es
   eng wird — auf dem Handy ist die zweispaltige Variante sonst genau das
   Problem, das wir hier abstellen wollten. */
.v2-record {
  border: 1px solid var(--border);
  margin: 8px 0;
}

.v2-record-row {
  display: grid;
  grid-template-columns: minmax(120px, 22%) 1fr;
  gap: 12px;
  padding: 7px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

.v2-record-row:last-child {
  border-bottom: 0;
}

.v2-record-label {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  padding-top: 1px;
}

.v2-record-value > * {
  margin: 0;
}

@media (max-width: 560px) {
  /* Unter 560px reicht die Breite fuer beides nicht — dann faellt das Modell,
     nicht der Name (Alex, 28.08.). Es steht weiterhin im `title` des Namens
     und in den Einstellungen; im Kopf ist es die verzichtbare Haelfte. */
  .agent-header .agent-name-model { display: none; }
  /* Das Login bleibt am Telefon sichtbar — es ist die Aussage, die am 11.09. gefehlt hat. */

  .v2-record-row {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

.v2-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  font-family: inherit;
}

.v2-table th,
.v2-table td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: normal;
  word-break: break-word;
}

.v2-table th {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--text-muted);
}

.v2-table td {
  font-family: var(--font-mono);
  font-size: 12px;
}

.v2-table tbody tr {
  transition: background-color 0.15s ease;
}

.v2-table tbody tr:hover {
  background: var(--bg-light);
}

/* ── Input Bar ────────────────────────────────────────────────── */
.input-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 32px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--surface);
}

.input-field {
  flex: 1;
  padding: 10px 0;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 14px;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  outline: none;
  transition: border-color 0.2s ease;
}

.input-field:focus {
  border-bottom-color: var(--text-primary);
}

.input-field::placeholder {
  color: var(--text-muted);
}

.input-action {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: none;
  border: 1px solid var(--border);
  border-radius: 0;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 14px;
  transition: all 0.15s ease;
  flex-shrink: 0;
}

.input-action:hover {
  border-color: var(--text-primary);
  color: var(--text-primary);
}

.input-action.primary {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
}

.input-action.primary:hover {
  background: var(--black);
}

/* ── Empty State ─────────────────────────────────────────────── */
.main-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 13px;
  letter-spacing: 0.05em;
}

/* ── Sending Indicator ────────────────────────────────────────── */
/* In-flow, left aligned. Sits as the last child inside .content-stream
 * after the turns, so it scrolls with the conversation. Alex prefers
 * this over the floating pill variant (Commit 8d2b0c0, Issue #19). */
.sending-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 15px;
}

/* Wraps the three bouncing dots so the nth-child stagger stays scoped to
 * the dot group when an inline live-status label sits beside it. */
/* Stop button beside the working wave (Alex 2026-06-20) — moved out of the
 * input row to where you actually see the agent working. */
.sending-stop {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  /* Follows the user's accent / active main color, matching the mic (Alex 2026-06-22). */
  border: 1px solid var(--accent);
  border-radius: 4px;
  background: var(--accent-bg);
  color: var(--accent);
  cursor: pointer;
}
/* Hover = subtle red tint (stop is destructive) — ONE coherent rule. The old two
   overlapping rules (solid accent fill + red icon/border) clashed into a heavy
   pink-filled button with a red square (Alex 2026-07-02). */
.sending-stop:hover {
  background: var(--color-error-bg);
  border-color: var(--color-error);
  color: var(--color-error);
}

/* Sound-wave thinking indicator (Alex 2026-06-20) — same flowing motion
 * as the transcribe state, replaces the old three bouncing dots. */
.sending-wave {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 18px;
  flex-shrink: 0;
}

/* Inline live activity beside the dots (Alex 2026-06-18). Mirrors the
 * Now/Next card's tone but compact + single-line-friendly so it reads as
 * an extension of the "agent working" indicator, not a second card. */
.sending-live {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  font-size: 13px;
  color: var(--text-secondary, var(--text-muted));
}
.sending-live-act {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60ch;
}
.sending-live-elapsed {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent);
  flex-shrink: 0;
}
.sending-live-next {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.sending-wave-bar {
  width: 3px;
  height: 100%;
  border-radius: 2px;
  /* Working/sending wave follows the accent (Alex 2026-06-22). */
  background: var(--accent);
  transform-origin: center;
  animation: sending-wave 1s ease-in-out infinite;
}

@keyframes sending-wave {
  0%, 100% { transform: scaleY(0.28); opacity: 0.5; }
  50%      { transform: scaleY(1);    opacity: 1; }
}

/* Reduced motion: static wave silhouette instead of the pulse — same treatment
   AgentOsWave already had, which this indicator was missing. The bars still
   read as "wave", and the accompanying live-status text carries the actual
   "agent is working" information, so nothing is lost by holding them still. */
@media (prefers-reduced-motion: reduce) {
  .sending-wave-bar { animation: none; }
  .sending-wave-bar:nth-child(1) { transform: scaleY(0.45); opacity: 0.6; }
  .sending-wave-bar:nth-child(2) { transform: scaleY(0.75); opacity: 0.8; }
  .sending-wave-bar:nth-child(3) { transform: scaleY(1);    opacity: 1;   }
  .sending-wave-bar:nth-child(4) { transform: scaleY(0.75); opacity: 0.8; }
  .sending-wave-bar:nth-child(5) { transform: scaleY(0.45); opacity: 0.6; }
}

/* ── Back Button ──────────────────────────────────────────────── */
.back-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: none;
  border: 1px solid var(--border);
  border-radius: 0;
  color: var(--text-primary);
  cursor: pointer;
  font-size: 16px;
  flex-shrink: 0;
  transition: all 0.15s ease;
}

.back-button:hover {
  border-color: var(--text-primary);
  background: var(--bg-light);
}

/* ── Mobile ───────────────────────────────────────────────────── */
/* Phone landscape's innerWidth is >768px (iPhone 14 Pro: 844px), so
 * a pure max-width:768px never fired there. Adding the height clause
 * catches landscape too so InputBar pad + meta-hide kick in. */
@media (max-width: 768px), (max-height: 500px) {
  .agent-header {
    padding: 12px 16px;
  }

  .agent-header .agent-meta {
    display: none;
  }
  /* With .agent-meta (the margin-left:auto spacer) hidden on mobile, pin the
     action buttons to the right so a long agent name truncates instead of
     pushing them off-screen — they're the important part (Alex 2026-06-24). */
  .agent-header-actions {
    margin-left: auto;
  }
  .conversation-view-toggle span {
    display: none;
  }
  /* Keep the short role label from squeezing; the name absorbs the shrink. */
  .agent-header .agent-role {
    flex-shrink: 0;
  }

  .content-stream {
    padding: 16px;
  }

  .input-bar {
    padding: 12px 16px;
  }
}

/* Neutral badge for SUSPENDED — paused, not warning. */
.badge-neutral {
  background: var(--surface-elevated, rgba(255, 255, 255, 0.04));
  color: var(--text-muted);
}

/* Suspended-state empty body: replaces the blank conversation area when
 * the agent is paused. Click triggers /sessions/<name>/resume via the
 * same runHeaderAction path the lifecycle menu uses. */
/* Live-view-missing banner (Alex 2026-07-02): sticky at the top of the transcript so
   it stays visible; warning-colored. The stale history below is dimmed so it's clearly
   not the current state. */
.live-missing {
  position: sticky;
  top: var(--agent-hdr-h, 0px);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 14px;
  margin-bottom: 8px;
  /* OPAQUE warm tint (mixed with --surface, not transparent): the banner is
     position:sticky and the stale transcript scrolls BEHIND it — a translucent
     background let that text bleed through and collide with the banner text
     (Alex 2026-07-05 "komische Ansicht"). */
  background: color-mix(in srgb, var(--color-warning) 18%, var(--surface));
  border-left: 4px solid var(--color-warning);
  box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.4);
}
.live-missing-text { font-size: 13.5px; color: var(--text-primary); line-height: 1.45; }
/* Die Hervorhebung war orange AUF orangem Grund und damit kaum lesbar (Alex
   2026-08-06: „das kann ich nicht lesen im orangen Bereich"). Betonung jetzt
   über Gewicht und Unterstreichung statt über eine Farbe, die mit dem
   Hintergrund konkurriert. */
.live-missing-text strong {
  color: var(--text-primary);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 2px;
  text-decoration-color: var(--color-warning);
}
.live-missing-btn {
  /* Vorher `margin-left: auto` — auf einem breiten Bildschirm landete der Knopf
     zwei Meter neben dem Satz, auf den er sich bezieht. Jetzt direkt daneben. */
  margin-left: 4px;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 600;
  padding: 6px 14px;
  background: var(--chip-active-bg); color: var(--white);
  border: none; border-radius: 0; cursor: pointer;
  white-space: nowrap;
}
.live-missing-btn:hover { background: var(--black); }
/* Dim the stale history (everything except the sticky banner). */
.content-stream-stale .cs-inner > *:not(.live-missing) { opacity: 0.5; }

/* Blocking-state banner — needs_login / out_of_credits / error (Cloud IACP
   fb6dd9b2). Sticky at the top like live-missing, red-tinted (hard block, needs
   action). Opaque tint for the same scroll-behind reason. */
.agent-block-banner {
  position: sticky;
  top: var(--agent-hdr-h, 0px);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 14px;
  margin-bottom: 8px;
  background: color-mix(in srgb, var(--color-error) 13%, var(--surface));
  border-left: 3px solid var(--color-error);
  box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.4);
}
.agent-block-icon { display: inline-flex; color: var(--color-error); flex-shrink: 0; }
.agent-block-text { font-size: 13px; color: var(--text-primary); line-height: 1.4; flex: 1 1 220px; }
.agent-block-text strong { color: var(--color-error); }
.agent-block-btn {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 600;
  padding: 6px 14px;
  background: var(--chip-active-bg); color: var(--white);
  border: none; border-radius: 0; cursor: pointer;
  white-space: nowrap;
}
.agent-block-btn:hover { background: var(--black); }
/* Inner pin-observer wrapper — layout-neutral. */
.cs-inner { min-height: 100%; }

/* Never-blank transcript placeholder (Alex 2026-07-02: "weißer Screen, F5 3×"). */
.empty-view {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 64px 24px;
  color: var(--text-muted);
  text-align: center;
}
.empty-view-text { font-size: 14px; }
.empty-view-btn {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 600;
  padding: 7px 16px;
  background: transparent; color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 0; cursor: pointer;
}
.empty-view-btn:hover { border-color: var(--text-primary); }

.suspended-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 64px auto;
  padding: 32px 40px;
  max-width: 360px;
  text-align: center;
  background: var(--surface-elevated, rgba(255, 255, 255, 0.03));
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 10px;
  color: var(--text-muted);
}

.suspended-icon {
  opacity: 0.6;
}

.suspended-title {
  font-family: var(--font-heading);
  font-size: 16px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-primary);   /* war `var(--text)` — dieses Token gibt es nicht */
}

.suspended-detail {
  font-size: 13px;
  line-height: 1.5;
}

.suspended-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  padding: 8px 16px;
  background: var(--color-success, #16A34A);
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

.suspended-action:hover:not(:disabled) {
  opacity: 0.9;
}

.suspended-action:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* MCP-Server panel opened from the header menu — the shared <McpPanel>
   renders as an inline block (its native form in the sidebar), so here
   we float it as a centered card over a backdrop. Reuses .ctx-backdrop
   (z-index 9998) for the dimmer. */
.mcp-modal-wrap {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 9999;
  width: min(520px, 92vw);
  max-height: 80vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
}
.mcp-modal-wrap .mcp-panel {
  border-bottom: none;
}

/* Recap card — the CLI's "* recap:" turn-summary (Cloud IACP d3e3c1fa),
   rendered as a distinct meta-block set apart from the agent prose. */
.recap-card {
  margin: 8px 0;
  padding: 10px 12px;
  background: var(--bg-inset);
  border-left: 3px solid var(--accent, var(--text-primary));
  border-radius: 0 6px 6px 0;
}
.recap-head {
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: 5px;
  display: flex;
  align-items: center;
  gap: 5px;
}
.recap-icon { font-size: 12px; }
.recap-summary {
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-primary);
}
.recap-next {
  margin-top: 8px;
  font-size: 12px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
}
.recap-next-label {
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 10px;
}
.recap-next-text { color: var(--text-muted); line-height: 1.5; }
.recap-chips { display: inline-flex; flex-wrap: wrap; gap: 5px; }
.recap-chip {
  font-family: var(--font-body);
  font-size: 12px;
  padding: 3px 9px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  color: var(--text-primary);
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.recap-chip:hover {
  background: var(--chip-active-bg);
  color: var(--white);
  border-color: var(--text-primary);
}

/* Live Now/Next card (Cloud IACP 308c9a3b) — top of the conversation
   during an active turn. Warning accent = the orange "working" state
   made concrete. Vanishes on turn-end; the recap card then summarizes. */
.nownext-card {
  margin: 0 0 16px;
  padding: 10px 12px;
  /* Active "now/next" card follows the accent (Alex 2026-06-22). */
  background: var(--accent-bg);
  border-left: 3px solid var(--accent);
  border-radius: 0 6px 6px 0;
}
.nownext-now {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-primary);
}
.nownext-spinner {
  width: 12px;
  height: 12px;
  border: 2px solid var(--accent);
  border-top-color: transparent;
  border-radius: 50%;
  flex-shrink: 0;
  animation: nownext-spin 0.7s linear infinite;
}
@keyframes nownext-spin { to { transform: rotate(360deg); } }
.nownext-act { flex: 1; min-width: 0; }
.nownext-elapsed {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent);
  flex-shrink: 0;
}
.nownext-next {
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.4;
}
.nownext-next-label {
  font-family: var(--font-heading);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-right: 4px;
}

/* Per-reply action row (Alex 2026-06-21): speak + copy buttons bottom-left
   after each agent answer, like Claude/ChatGPT. Replaces the global composer
   speaker (which was removed to free input-bar space). Flat AgentOS style. */
.reply-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
}
/* Durable message timing from the transcript. Quiet by design — orientation
   metadata while scrolling, not primary conversation content. */
.message-time,
.turn-duration {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  cursor: default;
}
.entry-user .message-time {
  display: block;
  margin-top: 2px;
}
.reply-actions .message-time { margin-left: 2px; }
.turn-duration { margin-left: 0; }
.reply-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.12s ease, background 0.12s ease, color 0.12s ease;
}
.reply-action:hover { opacity: 1; background: var(--bg-light); color: var(--text-primary); }
.reply-action.active { opacity: 1; color: var(--accent); }
/* TTS transport seek buttons carry a small "15" next to the arrow (Alex #206). */
.reply-tts-seek { width: auto; gap: 1px; padding: 0 5px; }
.reply-tts-sec { font-family: var(--font-mono); font-size: 8.5px; font-weight: 600; }
/* Spinner while the TTS audio is still being fetched (no controls yet, #206). */
.reply-spin { animation: reply-tts-spin 0.9s linear infinite; }
@keyframes reply-tts-spin { to { transform: rotate(360deg); } }

/* Elapsed-seconds pill next to the speaker while a (prose) synthesis runs — the
   wait is legitimately 30-50s, so show the clock instead of a silent spinner. */
.reply-tts-elapsed {
  font-size: 10px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  margin-left: 4px;
  align-self: center;
}

/* Long-press TTS-mode menu on the per-reply speaker (Alex 2026-06-21). */
.reply-tts-anchor { position: relative; display: inline-flex; }
.reply-tts-backdrop { position: fixed; inset: 0; z-index: 40; }
.reply-tts-menu {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 0;
  z-index: 96; /* above the glass header/footer overlays */
  min-width: 168px;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  border: 1px solid var(--border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}
.reply-tts-head {
  padding: 8px 12px 6px;
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}
.reply-tts-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 9px 12px;
  border: none;
  background: var(--surface);
  font-size: 13px;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
}
.reply-tts-item:hover { background: var(--bg-light); }
.reply-tts-check { display: inline-flex; width: 14px; color: var(--accent); flex-shrink: 0; }

/* Group-chats section in the agent header dropdown (Alex 2026-06-22). */
.ctx-section-label {
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  padding: 9px 14px 4px;
}
.ctx-filter {
  display: block;
  width: calc(100% - 20px);
  margin: 0 10px 6px;
  padding: 6px 9px;
  border: 1px solid var(--border);
  border-radius: 0;
  font-family: inherit;
  font-size: 13px;
  color: var(--text-primary);
  background: var(--surface);
}
.ctx-filter:focus { outline: none; border-color: var(--border-strong); }
.ctx-gc-list { max-height: 220px; overflow-y: auto; }
.ctx-gc-title {
  max-width: 210px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ctx-gc-empty { padding: 6px 14px; font-size: 12px; color: var(--text-muted); }

/* Expandable header — click the header background to reveal the agent's group
   chats (Alex 2026-06-22). Styled as a continuation of the header. */
.agent-header { cursor: default; }
.agent-header-expand {
  flex-shrink: 0;
  /* Sits INSIDE the glass header — transparent so the header's blur shows through
     instead of an opaque slab over it (Alex 2026-07-03, dropdown glassmorphism). */
  background: transparent;
  border-bottom: 1px solid var(--border);
  padding: 8px 16px 12px;
  animation: ahx-down 0.15s ease;
}
@keyframes ahx-down { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
.ahx-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.ahx-label {
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.ahx-new {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; border: 1px solid var(--border); border-radius: 0;
  background: var(--surface); font-size: 12px; font-weight: 500;
  color: var(--text-primary); cursor: pointer;
}
.ahx-new:hover { border-color: var(--border-strong); color: var(--accent); }
.ahx-filter {
  width: 100%; margin-bottom: 8px; padding: 7px 10px;
  border: 1px solid var(--border); border-radius: 0;
  font-family: inherit; font-size: 13px; color: var(--text-primary); background: var(--surface);
}
.ahx-filter:focus { outline: none; border-color: var(--border-strong); }
.ahx-list { display: flex; flex-direction: column; max-height: 280px; overflow-y: auto; }
.ahx-item {
  display: flex; align-items: center; gap: 9px;
  width: 100%; padding: 9px 8px; border: none; background: transparent;
  font-family: var(--font-body); font-size: 13px; color: var(--text-primary);
  text-align: left; cursor: pointer; border-bottom: 1px solid var(--border);
}
.ahx-item:last-child { border-bottom: none; }
.ahx-item:hover { background: var(--bg-light); }
.ahx-item-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ahx-empty { padding: 8px; font-size: 12px; color: var(--text-muted); }

/* Scroll-up affordance for older transcript history (#1204, Alex 2026-06-23).
   The live /v2 view stays primary; this loads older turns ABOVE it. */
.history-top {
  display: flex;
  justify-content: center;
  padding: 8px 0 16px;
}
.history-top-hinweis {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  text-align: center;
  padding-inline: 16px;
}
.history-top-more {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 0;
  padding: 5px 14px;
  cursor: pointer;
}
.history-top-more:hover { color: var(--text-primary); background: var(--bg-light); }
.history-top-loading {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}

/* Wrap around the scroll area so the "jump to latest" button can anchor to
   the content bottom (above the input bar) regardless of input height. */
.content-stream-wrap {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.content-stream-wrap .content-stream { flex: 1; }
/* Full-height transcript under the glass overlays: overlay heights (JS-measured
   CSS vars) become scroll padding, so first/last content clears header/footer. */
.agent-detail-container .content-stream {
  padding-top: calc(var(--agent-hdr-h, 72px) + 16px);
  padding-bottom: calc(var(--agent-ftr-h, 76px) + 16px);
}
/* Banners that sit ABOVE the stream inside the wrap (voice bar, resume pin)
   must start below the glass header — and then the stream needs only its
   normal top padding. */
.content-stream-wrap > .voice-bar:first-child,
.content-stream-wrap > .resume-pin-banner:first-child { margin-top: var(--agent-hdr-h, 72px); }
.content-stream-wrap:has(> .voice-bar) .content-stream,
.content-stream-wrap:has(> .resume-pin-banner) .content-stream { padding-top: 16px; }
/* Überblick-Aufklappfeld (Alex 15.09., Bild 125183: „schließt nicht am Header an"):
   Die 16 px Luft oben sind für die erste Nachricht gedacht. Ein klebendes Feld hielt
   sie als Lücke offen — sticky achtet das Innenpolster des Scrollers, auch beim
   Blättern —, und durch die Lücke schaute der Verlauf. Mit Feld: Polster = Kopfhöhe,
   das Feld liegt bündig unter der Kopflinie; hinter einer Leiste (Stimme, Wiederauf-
   nahme) braucht es gar keins mehr. */
.agent-detail-container .content-stream:has(.ueberblick-oben) { padding-top: var(--agent-hdr-h, 72px); }
.content-stream-wrap:has(> .voice-bar) .content-stream:has(.ueberblick-oben),
.content-stream-wrap:has(> .resume-pin-banner) .content-stream:has(.ueberblick-oben) { padding-top: 0; }

/* Floating "scroll to bottom / latest" button (Alex 2026-06-23) — appears
   when scrolled up far into the history. */
.scroll-down-btn {
  position: absolute;
  /* --sprung-knopf-hub: Sichten mit eigener Leiste ueber dem Eingabefeld
     (Zeitansicht) heben den Knopf darueber, ohne ihn nachzubauen. */
  bottom: calc(var(--agent-ftr-h, 76px) + 16px + var(--sprung-knopf-hub, 0px));
  left: 50%;
  transform: translateX(-50%);
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  color: var(--text-primary);
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  z-index: 5;
  transition: background 0.12s ease, transform 0.06s ease;
}
.scroll-down-btn:hover { background: var(--bg-light); }
.scroll-down-btn:active { transform: translateX(-50%) scale(0.9); }

/* Orphan cold-start states (Alex 2026-06-23) — same card shell as the
   suspended card; the spinner is the accent-coloured cmd-spinner. */
.wake-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 64px auto;
  padding: 32px 40px;
  max-width: 360px;
  text-align: center;
  background: var(--bg-light);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text-muted);
}
.wake-card .cmd-spinner { width: 22px; height: 22px; border-width: 3px; }
.wake-title {
  font-family: var(--font-heading);
  font-size: 16px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-primary);
}
.wake-detail { font-size: 13px; line-height: 1.5; }

/* Realtime voice narrator (Step 1) — toggle button + live status bar (#1215). */
.voice-btn.voice-live {
  border-color: var(--accent);
  color: var(--accent);
}
.voice-pulse { animation: voice-pulse 1.4s ease-in-out infinite; }
@keyframes voice-pulse {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}
.voice-bar {
  /* Zwei FESTE Zeilen statt freiem Umbruch (Alex 2026-08-11, Screenshot 118938):
     Mit `flex-wrap` ergaben sich je nach Breite drei zerfranste Reihen, der
     Stopp-Knopf landete allein unten rechts, und der Geräte-Auswähler drängte
     alles auseinander. Jetzt ist die Aufteilung eine Entscheidung, keine Folge
     der Fensterbreite: Zeile 1 = Zustand + Handeln, Zeile 2 = Einstellen. */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding: 7px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--accent-bg);
  color: var(--accent);
  font-size: 12.5px;
  flex-shrink: 0;
}
/* Keep the Stop button last but always visible: push it to the row end and never
   let it shrink — wrapping puts it on its own line before it would ever clip. */
.voice-bar-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.voice-bar-orb {
  position: relative;
  flex: 0 0 34px;
  width: 34px;
  height: 34px;
  overflow: hidden;
  border-radius: 50%;
  box-shadow: 0 0 15px color-mix(in srgb, var(--accent) 28%, transparent);
}
/* Halten-zum-Sprechen und Stopp sitzen immer rechts — auch wenn die letzte
   Äußerung kurz ist und den Platz nicht füllt. */
.voice-bar-row.primary .voice-bar-mic.ptt { margin-left: auto; }
.voice-bar-row.primary .voice-bar-last ~ .voice-bar-mic.ptt { margin-left: 0; }
/* Der Geräte-Auswähler nimmt den Rest der zweiten Zeile, statt die anderen
   Bedienelemente zu verdrängen. */
.voice-bar-row.secondary .audio-input-picker { flex: 1; min-width: 0; }
.voice-bar-row.secondary .voice-bar-log { margin-left: auto; }

.voice-bar-stop { margin-left: auto; }
.voice-bar-error { background: rgba(220, 38, 38, 0.1); color: #dc2626; }
.voice-bar-label { font-weight: 600; white-space: nowrap; }
.voice-bar-last {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: 0.85;
  font-style: italic;
}
.voice-bar-stop {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  cursor: pointer;
  border-radius: 0;
}
.voice-bar-stop:hover { background: var(--accent); color: var(--white); }
/* Der Mikro-Pegel (.voice-vu) wohnt jetzt in MicLevelMeter.css, direkt bei
   seiner Komponente — sonst haengt er am Bundle der Ansicht, die ihn zufaellig
   zuerst benutzt hat. */

/* Global voice mini-pill (app-level, GlobalVoiceLayer): persistent AgentOS
   narrator indicator shown when AgentDetail's own bar is off screen (#1215). */
.voice-minibar {
  position: fixed;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  background: var(--accent-bg);
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 600;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
}
.voice-minibar-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  animation: voice-pulse 1.4s ease-in-out infinite;
  flex-shrink: 0;
}
.voice-minibar-orb {
  position: relative;
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  overflow: hidden;
  border-radius: 50%;
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 24%, transparent);
}
.voice-minibar.voice-bar-connecting .voice-minibar-dot { opacity: 0.5; }
.voice-minibar-label { white-space: nowrap; }
.voice-minibar-context {
  flex-shrink: 0;
  padding: 2px 6px;
  border: 1px solid currentColor;
  background: transparent;
  cursor: pointer;
  font: inherit;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.7;
}
.voice-minibar-context.on { color: var(--success, #16a34a); opacity: 1; }
/* Sprechtaste. In der Multi-Ansicht, im Dashboard und in Collab gibt es kein
   Avatar-Video — die Pille ist dort die EINZIGE Stelle, an der die Leertaste
   ueberhaupt entdeckt werden kann. Deshalb steht der Hinweis dauerhaft da und
   nicht nur beim Halten. */
.voice-minibar-ptt {
  flex-shrink: 0;
  padding: 2px 6px;
  border: 1px solid currentColor;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.55;
}
/* Waehrend der Aufnahme kein dezenter Hinweis mehr, sondern eine Aussage:
   gefuellte Flaeche statt Umriss, damit im Augenwinkel erkennbar bleibt, dass
   das Mikrofon gerade offen ist. */
.voice-minibar-ptt.on {
  opacity: 1;
  background: currentColor;
  color: var(--surface);
}

/* Am Handy gibt es keine Leertaste — der Hinweis ist dort nicht nur nutzlos,
   er nimmt der Pille die Breite, die sie für Modus und Ziel braucht (Alex
   2026-08-11: „am Handy bringt mir die Information Leertaste nichts").
   Gesprochen wird dort über das Avatar-Video, das ohnehin sichtbar ist. */
@media (pointer: coarse) {
  .voice-minibar-ptt { display: none; }
}

/* Ist das Avatar-Feld sichtbar, zeigt es Modus, Ziel, Zustand und Stopp bereits
   selbst. Die Pille wiederholte das ein zweites Mal — auf dem Handy stand
   „UPDATES AUS" gleichzeitig oben in der Pille und unten in der Leiste, und die
   Pille legte sich zusätzlich über die Kopfzeile (Screenshot 118939). Sie
   verschwindet dort, statt nach oben auszuweichen. */
@media (max-width: 768px) {
  body:has(.arc-wrap) .voice-minibar { display: none; }
}
.voice-minibar-stop {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  cursor: pointer;
  border-radius: 0;
}
.voice-minibar-stop:hover { background: var(--accent); color: var(--white); }

@media (max-width: 520px) {
  .voice-minibar {
    flex-wrap: wrap;
    justify-content: center;
    width: max-content;
    max-width: calc(100vw - 20px);
  }
}

/* Voice verify-log (Alex 2026-06-23) — feed ↔ narration trail. */
.voice-bar-log {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  height: 24px;
  padding: 0 8px;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  font-size: 11px;
  cursor: pointer;
  border-radius: 0;
}
.voice-bar-log.on { background: var(--accent); color: var(--white); }
/* Mic mute toggle — same square button language; red when muted. */
.voice-bar-mic {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  cursor: pointer;
  border-radius: 0;
}
.voice-bar-mic:hover { background: var(--accent); color: var(--white); }
.voice-bar-mic.muted { background: #dc2626; border-color: #dc2626; color: #fff; }
.voice-bar-mic:disabled { opacity: 0.45; cursor: not-allowed; }
/* Push-to-talk button (transparent mode, Alex 2026-06-25): bigger + thumb-reachable
   with a label, and NO iOS text-selection / callout / tap-highlight while held. */
.voice-bar-mic.ptt {
  width: auto;
  height: 34px;
  padding: 0 16px;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
}
.voice-bar-mic.ptt.talking { background: var(--accent); border-color: var(--accent); color: var(--white); }
.voice-log {
  flex-shrink: 0;
  max-height: 38vh;
  overflow-y: auto;
  border-bottom: 1px solid var(--border);
  background: var(--bg-light);
  padding: 8px 12px;
  font-size: 12px;
}
.voice-log-empty { color: var(--text-muted); font-style: italic; }
/* Wrap so the TEXT gets its own full-width line below the compact tag+attr meta,
   instead of being squeezed into a thin right column on mobile (Alex 2026-06-26). */
.voice-log-line { display: flex; flex-wrap: wrap; gap: 3px 8px; padding: 4px 0; border-bottom: 1px solid var(--border); }
.voice-log-tag {
  flex-shrink: 0;
  width: 86px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  opacity: 0.75;
}
.voice-log-fed .voice-log-tag { color: var(--text-muted); }
.voice-log-voice .voice-log-tag { color: var(--accent); }
.voice-log-attr {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  opacity: 0.7;
  white-space: nowrap;
  align-self: flex-start;
  padding-top: 1px;
}
.voice-log-text { flex: 1 1 100%; min-width: 0; white-space: pre-wrap; word-break: break-word; color: var(--text-primary); }
.voice-log-voice .voice-log-text { font-weight: 500; }
.voice-log-meta { margin-top: 6px; font-size: 11px; color: var(--text-muted); }

/* Voice session-metrics report (Codex 2026-06-24) — the exact Ist-Werte after a test. */
.voice-report {
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-light);
  padding: 8px 12px;
  font-size: 12px;
}
.voice-report-head {
  display: flex; align-items: center; justify-content: space-between;
  font-weight: 600; margin-bottom: 6px;
}
.voice-report-head button {
  border: none; background: transparent; color: var(--text-muted); cursor: pointer;
  display: inline-flex; padding: 2px;
}
.voice-report-grid {
  display: grid; grid-template-columns: auto 1fr; gap: 2px 12px;
}
.voice-report-grid span { color: var(--text-muted); font-family: var(--font-mono); font-size: 11px; }
.voice-report-grid b { font-family: var(--font-mono); font-size: 11px; color: var(--text-primary); word-break: break-all; }
.voice-log-you .voice-log-tag { color: var(--accent); font-weight: 600; }
.voice-log-you .voice-log-text { font-style: italic; }

/* Talkback confirm-chip (Step 2, #1220) — propose → confirm before send. */
/* Talkback-Bestätigung als zentrierte Karte (Alex, 14.08.). Vorher klemmte
   die Frage klein unter der Sprachleiste — für eine Entscheidung, die alles
   andere pausiert, die falsche Bühne. Formsprache des Portals: flach, eckig,
   dunkle Primärtaste (Stilvorgabe: radius 0, --text-primary als Knopf-Grund).
   Der Schleier dahinter führt den Blick, fängt aber bewusst KEINE Klicks auf
   Verlauf oder Sprech-Taste ab — pointer-events nur auf der Karte. */
.voice-proposal-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: color-mix(in srgb, var(--text-primary) 12%, transparent);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  pointer-events: none;
}
.voice-proposal {
  pointer-events: auto;
  width: min(440px, 100%);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 18px 50px color-mix(in srgb, var(--text-primary) 22%, transparent);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.voice-proposal.risky { border-color: #dc2626; }
.voice-proposal-kicker {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}
.voice-proposal-question {
  font-size: 18px;
  line-height: 1.35;
  color: var(--text-primary);
}
.voice-proposal-question b { font-weight: 700; }
.voice-proposal-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 1px 5px;
  border: 1px solid currentColor;
}
.voice-proposal-tag.cross { color: #b45309; }
.voice-proposal-tag.danger { color: #dc2626; }
.voice-proposal-text {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-break: break-word;
  padding: 10px 12px;
  background: color-mix(in srgb, var(--text-primary) 6%, transparent);
  border-left: 3px solid var(--border-strong);
  max-height: 40vh;
  overflow-y: auto;
}
.voice-proposal-actions { display: flex; gap: 10px; margin-top: 4px; }
.voice-proposal-ok, .voice-proposal-no {
  flex: 1;
  height: 40px;
  padding: 0 16px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  border-radius: 0;
  font-size: 13.5px;
  font-weight: 600;
}
.voice-proposal-ok { background: var(--chip-active-bg); border-color: var(--text-primary); color: var(--white); }
.voice-proposal.risky .voice-proposal-ok { background: #dc2626; border-color: #dc2626; }
.voice-proposal-no:hover { background: var(--bg-light); }

/* Focus-lock toggle active state (Alex 2026-06-24) — accent-filled when locked. */
.voice-bar-mic.on { background: var(--accent); border-color: var(--accent); color: var(--white); }

/* Glass fallback (no backdrop-filter support) → opaque surface. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .reply-tts-menu { background: var(--surface); }
}

/* Issue-dispatch turns — blue identity, distinct from pink IACP peer messages
   (Alex 2026-07-04). Marker, tag and a subtle info-tinted content wash. */
.entry-user.source-iacp.source-issue .entry-marker { background: var(--color-info); }
.entry-user.source-issue .entry-source-tag { background: var(--color-info); color: var(--white); }
.entry-user.source-issue .entry-content {
  background: color-mix(in srgb, var(--color-info) 7%, transparent);
}

/* „war 4 h 27 min angemeldet" am Blockier-Banner. Gedämpft — es ist eine
   Zusatzangabe zur Einordnung, nicht die Meldung selbst. */
.agent-block-age {
  flex: none;
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.03em;
  opacity: 0.75;
  white-space: nowrap;
}


/* Treffer des Sprungs zur eigenen Nachricht (Alex 12.08.2026). Kurz und
   deutlich: Der Sprung landet sonst „irgendwo", und man sucht von Hand, was
   gemeint war. Kein Dauerzustand — die Markierung verblasst von selbst. */
.stream-entry.own-jump-hit {
  animation: own-jump-flash 1.4s ease-out;
}
@keyframes own-jump-flash {
  0%   { background: var(--accent-bg, rgba(120, 120, 255, 0.18)); }
  100% { background: transparent; }
}


/* Hinweis auf den aktiven Sichtfilter (Alex 12.08.). Ein Filter, den man nicht
   sieht, wirkt wie ein verlorener Verlauf — deshalb steht die Stufe und die
   Taste, die weiterschaltet, ausdruecklich dort. */
.stream-filter-note {
  padding: 6px 12px;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

/* Steht anstelle der Eingabezeile, wenn `sessions:send` fehlt.
   Sie nimmt bewusst deren Platz ein statt spurlos zu fehlen: Die Eingabezeile
   ist die zentrale Handhabe dieser Ansicht, ihr wortloses Verschwinden saehe
   nach einem Fehler aus. Ein Satz beantwortet die Frage, die sonst entsteht. */
.nur-lesen-hinweis {
  padding: 12px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--text-secondary);
  background: var(--surface);
  border-top: 1px solid var(--border);
}

/* Beitrags-Erwähnung im Fließtext (Alex 17.08.): kompakter Chip statt
   Einbettung — die Einbettung bleibt der nackten URL vorbehalten. */
.post-ref-link {
  color: var(--accent, #d81b16);
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
  white-space: nowrap;
}
.post-ref-link:hover { opacity: 0.8; }

/* ── Terminal-Auszeichnung (Cloud b361f2c) ────────────────────────
   Über die ROLLE eingefärbt, nicht über die rohe Terminalfarbe: Ein hartes
   Terminal-Rot ist im hellen Thema unlesbar und im dunklen zu grell. So
   stimmen beide Themen, und die Bedeutung (Fehler, Zugabe, Wegnahme, Pfad)
   bleibt erhalten — sie ist bei Codex nicht dekorativ. */
.code-block .sp-error, .entry-plain .sp-error   { color: var(--color-error); }
.code-block .sp-success, .entry-plain .sp-success { color: var(--color-success); }
.code-block .sp-warning, .entry-plain .sp-warning { color: var(--color-warning); }
.code-block .sp-path, .entry-plain .sp-path    { color: var(--color-info); }
.code-block .sp-command, .entry-plain .sp-command { color: var(--accent); }
.code-block .sp-muted, .entry-plain .sp-muted   { opacity: 0.6; }
.code-block .sp-bold, .entry-plain .sp-bold    { font-weight: 600; }

/* Diff-Zeilen zusätzlich flächig hinterlegen — im Terminal trägt die Position
   die Bedeutung mit; im Fließtext des Portals geht sie sonst unter. */
.code-block .sp-add, .entry-plain .sp-add {
  color: var(--color-success);
  background: var(--color-success-bg);
}

.code-block .sp-del, .entry-plain .sp-del {
  color: var(--color-error);
  background: var(--color-error-bg);
}

/* Markdown-freie Prosa mit Terminal-Auszeichnung: Zeilenumbrüche erhalten,
   aber in der normalen Textschrift — es ist Fließtext, kein Code-Block. */
.entry-plain {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Warten ≠ Störung (Issue #1199): Ein erreichtes Kontingent-Limit ist keine
   Fehlfunktion — der Agent ist heil, er darf gerade nur nicht, und es löst sich
   von selbst. Deshalb dieselbe Bauform wie der Fehlerbalken, aber in der
   Warn-Farbe und ohne Alarmton. Rot bleibt dem vorbehalten, wo jemand
   eingreifen MUSS. */
.agent-block-banner.agent-block-wait {
  background: color-mix(in srgb, var(--color-warning) 13%, var(--surface));
  border-left-color: var(--color-warning);
}

.agent-block-banner.agent-block-wait .agent-block-icon,
.agent-block-banner.agent-block-wait .agent-block-text strong {
  color: var(--color-warning);
}

/* Erste Inhaltszeile im zugeklappten Werkzeug-Kopf (#1249). Sie trägt die
   Farbe des Terminals — deshalb steht sie hier ohne eigene Farbangabe: Die
   Spannen-Klassen aus ColoredPre färben sie, alles Ungefärbte bleibt gedämpft.
   `min-width: 0` + `ellipsis`, damit ein langer Dateipfad die Kopfzeile nicht
   sprengt; der Pfeil und das Abzeichen behalten ihren Platz. */
.tool-call-peek {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  opacity: 0.85;
}

/* ── Codeblock: Kopfzeile mit Sprache + Kopieren, Rumpf scrollt ────────────
   Vorbild ist die Darstellung, die Alex am 21.08. gezeigt hat: ruhige Flaeche,
   Sprache links, Kopier-Symbol rechts, Farben nach Wortart. Die Farben stehen
   hier als Marken (--hl-*) und nicht als fertiges highlight.js-Thema, weil das
   Portal hell UND dunkel kann — ein mitgeliefertes Thema kennt nur einen Fall. */
.v2-codeblock {
  margin: 10px 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg-inset);
}
.v2-codeblock-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-inset);
}
.v2-codeblock-lang {
  font: 600 12px/1.4 var(--font-sans, inherit);
  letter-spacing: 0.01em;
  opacity: 0.75;
}
.v2-codeblock-copy {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  font: 500 12px/1.4 var(--font-sans, inherit);
  color: inherit;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 120ms ease, border-color 120ms ease;
}
.v2-codeblock-copy:hover,
.v2-codeblock-copy:focus-visible {
  opacity: 1;
  border-color: var(--border);
}
@media (hover: none) { .v2-codeblock-copy { opacity: 0.85; } }

/* Waagrecht scrollen statt umbrechen: ein umgebrochener Befehl ist ein
   falscher Befehl, und beim Kopieren wandert der Umbruch mit. */
.v2-codeblock > pre {
  margin: 0;
  padding: 10px 12px;
  border: none;
  border-radius: 0;
  background: transparent;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.v2-codeblock > pre code {
  display: block;
  white-space: pre;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.55;
}

/* Wortarten. Hell zuerst, Dunkel ueberschreibt nur die Marken. */
:root {
  --hl-comment: #5F8C4E;
  --hl-string:  #C0392B;
  --hl-keyword: #8E44AD;
  --hl-name:    #148F9F;
  --hl-number:  #B36B00;
  --hl-meta:    #7A7A85;
}
[data-theme="dark"] {
  --hl-comment: #7FB069;
  --hl-string:  #E8836F;
  --hl-keyword: #C792EA;
  --hl-name:    #56C7D6;
  --hl-number:  #F2A65A;
  --hl-meta:    #9A9AA5;
}
.hljs-comment, .hljs-quote { color: var(--hl-comment); font-style: italic; }
.hljs-string, .hljs-regexp, .hljs-addition { color: var(--hl-string); }
.hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-built_in,
.hljs-doctag, .hljs-type { color: var(--hl-keyword); }
.hljs-variable, .hljs-template-variable, .hljs-attr, .hljs-attribute,
.hljs-title, .hljs-title.function_, .hljs-title.class_,
.hljs-section, .hljs-name, .hljs-selector-id, .hljs-selector-class {
  color: var(--hl-name);
}
.hljs-number, .hljs-symbol, .hljs-bullet, .hljs-link { color: var(--hl-number); }
.hljs-meta, .hljs-params, .hljs-deletion { color: var(--hl-meta); }
.hljs-emphasis { font-style: italic; }
.hljs-strong { font-weight: 600; }

/* ── Aufruf-Argumente im aufgeklappten Werkzeug-Abschnitt ──────────────────
   Cloud 44a69d7. Anlass: Codex bricht bei langen Argumenten nach dem Verb um,
   das Label ist bei 80 Zeichen abgeschnitten — man sah, DASS etwas gerufen
   wurde, nicht WOMIT (Alex, Screenshot 120459).

   Höhenbegrenzt: Ein `send_message` mit langem Text würde sonst das Ergebnis
   nach unten aus dem Blick drängen. Der Block scrollt in sich, die Seite
   nicht — dieselbe Regel wie bei breiten Tabellen. */
.tool-call-args {
  margin-bottom: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
}

.tool-call-args-label {
  display: block;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-secondary);
}

.tool-call-args pre {
  margin: 0;
  padding: 8px;
  max-height: 220px;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  font-family: var(--font-mono, monospace);
  font-size: 11px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text-primary);
}

/* Denkstand-Zeile (Cloud 25.08.): die „(summarized)"-Auskunft der CLI.
   RUHIGER gesetzt als `activity` — und das ist kein Geschmack: `activity`
   stammt aus der Aufgabenliste des Agenten (strukturiert, abgelesen), diese
   Zeile ist seine Prosa über sich selbst. Gleiche Auszeichnung liesse eine
   Selbstauskunft wie eine Messung aussehen. Kursiv und gedämpft sagt „das
   erzählt er, das haben wir nicht gemessen". */
.nownext-thinking {
  margin-top: 4px;
  padding-left: 2px;
  color: var(--text-muted);
  font-size: 12px;
  font-style: italic;
  line-height: 1.4;
}

/* Die Dauer neben dem Gedanken — noch leiser als er selbst. */
.nownext-thinking-age { opacity: 0.6; font-style: normal; }


/* „(summarized)"-Zusammenfassungen — im Rand, nicht im Fluss.
   Alex: sie standen wie gleichrangige Antworten und drueckten das Gespraech
   auseinander. Gedaempft, einzeilig, aufklappbar; flach und eckig wie der
   Rest des Portals. */
.entry-summary {
  margin: 2px 0;
}
.entry-summary-toggle {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  padding: 4px 8px;
  border: 0;
  border-left: 2px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 12px;
  font-style: italic;
  text-align: left;
  cursor: pointer;
}
.entry-summary-toggle:disabled { cursor: default; }
.entry-summary-toggle:not(:disabled):hover {
  background: var(--hover-bg);
  border-left-color: var(--text-muted);
}
.entry-summary-tag {
  flex: 0 0 auto;
  font-style: normal;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  opacity: 0.75;
}
.entry-summary-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}
/* Zugeklappt bleibt es strikt einzeilig — sonst ist der Gewinn dahin. */
.entry-summary:not(.is-open) .entry-summary-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Präsenz-Eingabe (Variante A, Post 4909): Wahrnehmungs-Block als Ebene 4 —
   einklappbar, zurückgenommen; die Frage bleibt der prominente Text. */
.presence-kontext {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 2px 0 6px;
}

.presence-kontext-schalter {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  cursor: pointer;
}

.presence-kontext-herkunft {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.03em;
}

.presence-kontext-text {
  flex-basis: 100%;
  margin: 0;
  padding: 6px 10px;
  border-left: 2px solid var(--border);
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-x: auto;
}

.entry-source-tag.gesprochen {
  border: 1px dashed var(--border);
  color: var(--text-muted);
}

/* Präsenz-Knopf in der Kopfzeile (Variante A): Eingang dort, wo man gerade ist. */
.ahx-btn.ahx-praesenz {
  gap: 5px;
  border-style: dashed;
}

.ahx-praesenz-label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

@media (max-width: 480px) {
  .ahx-praesenz-label { display: none; }
}

/* Kleinhirn-Karte in der klassischen Konversation: am Turn-Ende, eingerückt wie die Antwort. */
.stream-derivat {
  margin: 0 0 16px 44px;
}

.stream-linse-label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}


.stream-derivat-original { margin-top: 10px; }
.stream-derivat-fehlt { display: inline-block; margin: 0 0 14px 44px; }

/* Kleinhirn-Spanne (#4914): Prosa der Spanne, live wachsend. Sie sieht aus wie
   die Antwort selbst — kein Strich, kein Kasten (Alex 02.09.: „der Strich ist
   unpassend, das ist ja der Agenten-Output, nur verschönert"). Die Absätze
   laufen durch `.entry-agent .entry-content`, also durch dieselben Regeln wie
   jede Agenten-Antwort. */
.spanne-prosa {
  margin: 0 0 12px;
  padding: 0;
  border: 0;
  background: transparent;
}

.spanne-prosa-absatz {
  margin: 0 0 4px;
  /* Tönung statt Weiß, damit Prosa als Prosa erkennbar ist (Alex 03.09.);
     Tint-Token, kein Strich, kein color-mix — Theme-tauglich hell wie dunkel. */
  background: var(--color-info-bg);
  padding: 6px 12px;
}

.spanne-prosa-etikett {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  padding: 4px 12px 0;
  background: var(--color-info-bg);
}

.spanne-prosa-stand {
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.spanne-original {
  margin: 0 0 10px 44px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  background: transparent;
  border: 1px dashed var(--border);
  padding: 2px 8px;
  cursor: pointer;
}

/* Strang-Leiste (#4914): Zustand des Agenten in der Gehirn-Sicht — flach,
   Mono-Uppercase wie die Segmentschalter; Fokus als dunkle Pille. */
.strang-leiste {
  /* Nicht mehr sticky: Karten statt Chips (Alex 03.09. 12:0x) brauchen Höhe;
     der Gehirn-Banner darüber trägt die Zahlen. */
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 12px 10px;
  margin: 0 0 8px;
  /* Voller Kontrast (Alex 03.09. 00:0x: „graues Teil, kann nichts lesen"):
     deckende Fläche, Ink-Text, kein Ausblassen. */
  background: var(--surface);
  color: var(--text-primary);
  border-bottom: 1px solid var(--text-primary);
}

.strang-leiste-titel {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-primary);
}

.strang-leiste-liste {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.strang-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 2px 8px;
  border: 1px solid var(--text-primary);
  font-size: 13px;
  line-height: 1.5;
  background: transparent;
  color: var(--text-primary);
}

.strang-chip-titel { font-weight: 600; }

.strang-chip-detail {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--text-primary);
}

.strang-chip.zustand-aktiv { border-color: var(--text-primary); }
.strang-chip.zustand-wartet { border-style: dashed; }
/* Erledigt: kein Ausblassen (unleserlich), sondern Haken im Titel. */
.strang-chip.zustand-erledigt .strang-chip-titel::before { content: '✓ '; }
.strang-chip.zustand-verdraengt { border-style: dotted; }

.strang-chip-epistemik {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.05em;
  color: var(--text-primary);
  opacity: 0.85;
}

.strang-chip.is-fokus {
  background: var(--chip-active-bg);
  color: var(--chip-active-fg, var(--surface));
  border-color: transparent;
}

.strang-chip.is-fokus .strang-chip-detail { color: inherit; opacity: 0.8; }

.strang-chip-fokus {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.8;
}

/* B-light-Rollover (#4914): die Kurzfassung ist sichtbar als solche etikettiert —
   eine von uns gesetzte, belegte Verdichtung, nie ein stiller Endstand. */
.spanne-kurzfassung {
  border-top: 1px dashed var(--border);
  padding-top: 6px;
}

.spanne-kurzfassung-etikett {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.stream-derivat-fehlt.is-fehlgeschlagen { color: var(--error, #b91c1c); }

@media (max-width: 700px) {
    /* Sicherheitszone: Mikrofon-Knopf und Pfeil liegen ueber der letzten
     Textkante (Business 07.09., Bild 123704). */
  .agent-detail-container .content-stream { padding-bottom: calc(var(--agent-ftr-h, 76px) + 72px); }
}
/* Verlaufs-Linse in der Kopfzeile (Alex 10.09., Bild 123936): Segmentpaar
   Original | Prosa statt eines Balkens über dem Verlauf. Mono-Versalien wie
   die übrigen Segmentwahlen; am Telefon steht das Paar in der Kopfgruppe. */
.gehirn-linse { display: inline-flex; }
.gehirn-linse .gehirn-linse-knopf + .gehirn-linse-knopf { margin-left: -1px; }
.gehirn-linse-knopf.on { position: relative; z-index: 1; }
/* Der Gehirn-Knopf trägt die Zahl „brauchen dich" — die Farbe der Warnung,
   wie das Braucht-dich-Feld im Überblick. */
.ahx-btn.stream-linse.braucht { border-color: var(--color-warning); }
.ahx-btn.stream-linse.braucht .ahx-btn-count { color: var(--color-warning); }
.ahx-btn.stream-linse.on .ahx-btn-count { color: var(--white); }
@media (max-width: 1199px) {
  .kopf-gruppe-inhalt .gehirn-linse .gehirn-linse-knopf { flex: 1; justify-content: center; }
}

.strang-chip.is-klickbar { cursor: pointer; }
.strang-chip.is-klickbar:hover, .strang-chip.is-klickbar:focus-visible { background: var(--hover-bg); outline: none; }
.spanne-prosa-absatz:target, .spanne-prosa-absatz.is-ziel { outline: 2px solid var(--text-primary); }


/* „Braucht dich" — Stränge, die auf den Menschen warten, mit dem worauf als Satz. */
.braucht-dich { border: 2px solid var(--text-primary); padding: 8px 10px; background: var(--color-warning-bg, var(--surface)); }
.braucht-dich-liste { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.braucht-dich-eintrag { display: grid; grid-template-columns: 1fr auto; grid-template-areas: 'worauf knopf' 'meta knopf'; gap: 2px 12px; align-items: center; }
.braucht-dich-worauf { grid-area: worauf; font-size: 15px; font-weight: 600; line-height: 1.4; color: var(--text-primary); }
.braucht-dich-meta { grid-area: meta; font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); }
.braucht-dich-sprung { grid-area: knopf; border: 1px solid var(--text-primary); background: var(--text-primary); color: var(--surface); font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; padding: 6px 10px; cursor: pointer; border-radius: 0; }
.braucht-dich-sprung:hover, .braucht-dich-sprung:focus-visible { opacity: 0.85; outline: none; }

/* Strang-Karten: Titel, Zustand, mit wem, seit wann, die letzten Absätze, Referenzen. */
.strang-karten { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 8px; }
.strang-karte { border: 1px solid var(--text-primary); background: var(--surface); color: var(--text-primary); padding: 8px 10px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.strang-karte.zustand-wartet { border-style: dashed; }
.strang-karte.zustand-verdraengt { border-style: dotted; }
.strang-karte.is-fokus { box-shadow: inset 3px 0 0 var(--text-primary); }
.strang-karte.is-klickbar { cursor: pointer; }
.strang-karte.is-klickbar:hover, .strang-karte.is-klickbar:focus-visible { background: var(--hover-bg); outline: none; }
.strang-karte-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; }
.strang-karte-titel { font-weight: 600; font-size: 14px; }
.strang-karte-zustand { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); }
.strang-karte-zustand.zustand-aktiv { color: var(--text-primary); }
.strang-karte-meta { font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); }
.strang-karte-absaetze { display: flex; flex-direction: column; gap: 4px; }
.strang-karte-absatz { margin: 0; font-size: 13px; line-height: 1.45; color: var(--text-primary); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.strang-karte-refs { display: flex; flex-wrap: wrap; gap: 4px; }
.strang-karte-ref { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; border: 1px solid var(--text-secondary); color: var(--text-secondary); padding: 0 5px; }
.strang-erledigt summary { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); cursor: pointer; }
.strang-erledigt .strang-leiste-liste { margin-top: 6px; }

/* EINSTIEG — der erste Blick beim Öffnen eines Agenten (Alex 03.09. 18:5x). */
.einstieg { margin: 0 0 8px; border: 2px solid var(--text-primary); background: var(--surface); color: var(--text-primary); }
.einstieg-kopf { display: flex; align-items: baseline; gap: 10px; padding: 6px 12px; border-bottom: 1px solid var(--text-primary); }
.einstieg.is-zu .einstieg-kopf { border-bottom: 0; }
.einstieg-titel { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }
.einstieg-zaehler { font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); flex: 1; }
.einstieg-toggle, .einstieg-eingabe { background: none; border: 1px solid var(--text-primary); color: var(--text-primary); font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; padding: 2px 8px; cursor: pointer; border-radius: 0; }
.einstieg-koerper { display: flex; flex-direction: column; gap: 10px; padding: 8px 12px 10px; }
.einstieg-block-titel { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); margin-bottom: 4px; }
.einstieg-braucht .einstieg-block-titel { color: var(--text-primary); font-weight: 600; }
.einstieg-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
/* Einspaltig: Satz, Meta, Zusammenhang, darunter die Antwortzeile — auf dem
   Telefon gehoeren die Bedienelemente UNTER die Frage, nicht daneben
   (Business/Alex 07.09., Bild 123704: Frage auf sechs Zeilen umgebrochen,
   Platzhalter abgeschnitten). */
.einstieg-zeile { display: grid; grid-template-columns: 1fr; grid-template-areas: 'satz' 'meta'; gap: 2px; align-items: start; }
.einstieg-antwort { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }
.einstieg-antwort-feld { flex: 1 1 180px; min-width: 0; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-primary); padding: 6px 8px; font: inherit; font-size: 13px; border-radius: 0; }
.einstieg-antwort-feld::placeholder { color: var(--text-secondary); }
.einstieg-schnell { border: 1px solid var(--text-primary); background: var(--text-primary); color: var(--surface); font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; padding: 7px 10px; border-radius: 0; cursor: pointer; }
.einstieg-schnell[type='submit'] { background: transparent; color: var(--text-primary); }
.einstieg-schnell:disabled { opacity: 0.45; cursor: default; }
.einstieg-antwort-unklar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; text-transform: none; letter-spacing: 0; font-size: 12px; }
.einstieg-antwort-fehler { flex-basis: 100%; font-size: 12px; color: var(--error, #dc2626); }
.einstieg-antwort-fertig { grid-column: 1 / -1; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); margin-top: 4px; }
.einstieg-satz { grid-area: satz; font-size: 15px; font-weight: 600; line-height: 1.4; }
.einstieg-zielkarte { display: grid; grid-template-columns: 1fr; gap: 3px; border-left: 3px solid var(--text-primary); padding-left: 8px; }
.einstieg-zielstraenge { font-size: 12px; color: var(--text-secondary); }
.einstieg-schnell-leise { background: transparent; color: var(--text-primary); }
.einstieg-mehr { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 3px; margin-top: 2px; }
.einstieg-beleg { font-size: 12px; line-height: 1.35; color: var(--text-secondary); }
.einstieg-ziel, .strang-karte-ziel { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; border: 1px solid var(--text-primary); padding: 1px 6px; align-self: flex-start; }
.einstieg-meta { grid-area: meta; font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary); }
.einstieg-sprung { grid-area: knopf; border: 1px solid var(--text-primary); background: var(--text-primary); color: var(--surface); font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; padding: 6px 10px; cursor: pointer; border-radius: 0; }
.einstieg-karte { display: flex; flex-direction: column; gap: 2px; }
.einstieg-karte .einstieg-satz { font-size: 14px; }
.einstieg-punkt { font-size: 13px; line-height: 1.45; }
.einstieg-art { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; border: 1px solid var(--text-secondary); color: var(--text-secondary); padding: 0 4px; margin-right: 4px; }
.einstieg-straenge { display: flex; flex-wrap: wrap; gap: 6px; }
.einstieg-strang { background: transparent; border: 1px solid var(--text-primary); color: var(--text-primary); font-size: 13px; padding: 2px 8px; cursor: pointer; border-radius: 0; }
.einstieg-strang.zustand-wartet { border-style: dashed; }
.einstieg-strang.is-fokus { box-shadow: inset 3px 0 0 var(--text-primary); }
.einstieg-eingabe { align-self: flex-start; }

/* „In den Hintergrund" (Ctrl+B) neben dem Stopp-Knopf, nur bei laufendem Werkzeug (#4926). */
.sending-hintergrund { margin-left: 6px; border: 1px solid var(--text-primary); background: transparent; color: var(--text-primary); font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; padding: 2px 8px; cursor: pointer; border-radius: 0; }
.sending-hintergrund:disabled { opacity: 0.5; cursor: wait; }
/* Liste laufender Hintergrundaufgaben aus dem Verlauf. */
.hintergrund-leiste { margin: 0 0 8px; padding: 6px 12px; border: 1px dashed var(--text-primary); background: var(--surface); color: var(--text-primary); display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; }
.hintergrund-titel { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.hintergrund-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.hintergrund-eintrag { background: transparent; border: 1px solid var(--text-secondary); color: var(--text-primary); padding: 2px 8px; cursor: pointer; border-radius: 0; display: inline-flex; gap: 8px; align-items: baseline; font-size: 12px; }
.hintergrund-id { font-family: var(--font-mono); font-size: 11px; }
.hintergrund-text { max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hintergrund-meta { font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary); }

/* ÜBERBLICK — Variante B (#4950). Normales Scrollen, flach, eckig. */
.ueberblick { padding: 10px 12px 24px; display: flex; flex-direction: column; gap: 14px; }
/* Geteilte Sicht (Alex 10.09.): der Überblick ist die obere Hälfte und scrollt in
   sich; darunter läuft der Verlauf weiter. Klebend, damit die Hälfte bleibt,
   während man unten liest. */
.ueberblick-oben { position: sticky; top: 0; z-index: 4; max-height: 50vh; overflow: auto; overscroll-behavior: contain; background: color-mix(in srgb, var(--surface) 72%, transparent); -webkit-backdrop-filter: blur(14px) saturate(1.5); backdrop-filter: blur(14px) saturate(1.5); margin: 0 0 10px; border-bottom: 1px solid var(--border); box-shadow: 0 14px 24px -18px rgba(0, 0, 0, 0.45); }
/* Untere Kante (Alex 15.09.): eine helle Linie wie unter dem Kopf plus ein kurzer, weicher
   Schatten, damit sich das Feld vom Verlauf abhebt — kein Balken (Bild 125019). */
/* Glas wie Kopf und Fußleiste (Alex 13.09., Bild 125019): der schwebende Überblick ist ein
   Overlay über dem Verlauf, kein zweiter Hintergrund — und ohne den dicken Balken unten;
   Balken kennzeichnen bei uns vertikal, ein Overlay braucht keinen. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) { .ueberblick-oben { background: var(--surface); } }
.ueberblick-oben .ueberblick { padding-bottom: 12px; }
@media (max-width: 700px) { .ueberblick-oben { max-height: 45vh; } }
.ub-kopf { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); }
/* Die eine menschliche Kopfzeile (Alex über ChatGPT 13.09.): kein Zählwerk, ein Satz. */
.ub-kopf-mensch { font-size: 16px; font-weight: 700; line-height: 1.3; }
.ub-weitere > summary { cursor: pointer; list-style: none; }
.ub-weitere > summary::-webkit-details-marker { display: none; }
.ub-weitere > summary::before { content: '▸ '; }
.ub-weitere[open] > summary::before { content: '▾ '; }
.ub-weitere[open] { gap: 14px; }
.ub-block { display: flex; flex-direction: column; gap: 6px; }
.ub-offen { border: 2px solid var(--text-primary); background: var(--surface); padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.ub-offen-leise { border-width: 1px; border-color: var(--border-strong); margin-top: 4px; }
.ub-frage { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.35; }
.ub-zusammenhang { display: flex; flex-direction: column; gap: 4px; }
.ub-meta { font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary); }
.ub-beleg { margin: 0; font-size: 13px; line-height: 1.4; color: var(--text-secondary); }
.ub-fehlt { margin: 0; font-size: 13px; line-height: 1.4; color: var(--text-secondary); font-style: italic; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.ub-link { align-self: flex-start; background: transparent; border: 0; padding: 0; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); text-decoration: underline; cursor: pointer; }
.ub-zeilen { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.ub-zeile { width: 100%; text-align: left; display: grid; grid-template-columns: 1fr auto; grid-template-areas: 'titel seit' 'text seit'; gap: 1px 10px; align-items: center; background: transparent; border: 1px solid var(--border-strong); color: var(--text-primary); padding: 7px 10px; border-radius: 0; cursor: pointer; font: inherit; }
.ub-zeile.is-offen { border-color: var(--text-primary); }
.ub-zeile-still { cursor: default; opacity: 0.75; }
.ub-zeile-titel { grid-area: titel; font-weight: 600; font-size: 14px; }
.ub-zeile-text { grid-area: text; font-size: 12px; color: var(--text-secondary); }
.ub-zeile .ub-meta { grid-area: seit; }
.ub-hinweis, .ub-leer { margin: 0; font-size: 13px; color: var(--text-secondary); }
.ub-aeltere summary { cursor: pointer; }
.ub-fuss { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 6px; border-top: 1px solid var(--border-strong); }

/* Datei-Chip (kein Bild): klickbar, mit Name und Typ — Alex 09.09. (Bild 123878) */
.user-media-file { text-decoration: none; cursor: pointer; border-style: solid; }


/* ── Prosa-Vergleich (Debug, Alex 15.09., Bild 125206) ───────────────────────
   Neben jedem Prosa-Absatz die Abschnitte ⟨n⟩, aus denen Luna ihn erzählt hat:
   links die Prosa, rechts die Basis in Mono. Der Schalter sitzt am Behälter,
   die Absatz-Kästen bleiben unverändert (Wächter kleinhirnLinse.test.ts). */
.prosa-vergleich .spanne-prosa-absatz { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4px 14px; align-items: start; }
.prosa-vergleich .spanne-kurzfassung .spanne-kurzfassung-etikett { grid-column: 1 / -1; }
.prosa-basis { font-family: var(--font-mono); font-size: 11px; line-height: 1.45; color: var(--text-secondary); border-left: 1px solid var(--border); padding-left: 10px; max-height: 44vh; overflow: auto; overscroll-behavior: contain; min-width: 0; }
.prosa-basis-kopf { font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin-bottom: 4px; }
.prosa-basis-zeile { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0 0 6px; }
.prosa-basis-n { color: var(--text-muted); }
.prosa-basis-hinweis { font-style: italic; color: var(--text-muted); }
@media (max-width: 700px) {
  .prosa-vergleich .spanne-prosa-absatz { grid-template-columns: minmax(0, 1fr); }
  .prosa-basis { border-left: none; border-top: 1px solid var(--border); padding: 6px 0 0; max-height: 30vh; }
}

/* Codex-Rückfrage (Alex, Bilder 125211/125212; Cloud 15.09.): Leiste am Agenten
   statt Text im Verlauf. Eckig, flach, Mono — wie die Hintergrund-Leiste. */
.codex-rueckfrage { margin: 0 32px 6px; padding: 6px 12px; border: 1px solid var(--text-primary); background: var(--surface); color: var(--text-primary); display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
@media (max-width: 768px), (max-height: 500px) { .codex-rueckfrage { margin: 0 16px 6px; } }
/* Die Frage selbst in Leseschrift, nicht als Etikett; Optionen als dunkle Knöpfe
   (Codex' Vorschläge, wörtlich), das Textfeld für „Other". Alles eckig. */
.codex-rueckfrage-titel { flex-basis: 100%; font-family: var(--font-body); font-size: 13px; line-height: 1.4; text-transform: none; letter-spacing: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.codex-rueckfrage-antwort { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.codex-rueckfrage-option { border: 1px solid var(--text-primary); background: var(--text-primary); color: var(--surface); font-family: var(--font-mono); font-size: 11px; text-transform: none; letter-spacing: 0.02em; padding: 3px 10px; cursor: pointer; border-radius: 0; max-width: 100%; overflow-wrap: anywhere; text-align: left; }
.codex-rueckfrage-option:disabled { opacity: 0.5; cursor: wait; }
.codex-rueckfrage-frei { display: flex; flex: 1 1 220px; min-width: 0; align-items: center; gap: 0; }
.codex-rueckfrage-frei input { flex: 1 1 auto; min-width: 0; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-primary); font-family: var(--font-mono); font-size: 11px; padding: 3px 8px; border-radius: 0; text-transform: none; letter-spacing: 0; }
.codex-rueckfrage-frei input:focus { outline: none; border-color: var(--text-primary); }
.codex-rueckfrage-frei .sending-hintergrund { margin-left: 0; border-left: 0; padding: 3px 10px; font-size: 11px; }
/* Arcturian-Feld unter der Sessionliste. Flach und eckig wie der Rest der
   Oberfläche (radius 0), damit es wie ein Teil der Anwendung wirkt und nicht
   wie ein eingeklebtes Widget. */

.arc-panel {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  border-top: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  flex: none;
}

.arc-panel:hover .arc-stage { filter: brightness(1.06); }
.arc-panel:focus-visible { outline: 2px solid var(--text-primary); outline-offset: -2px; }
.arc-panel {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
}

/* Quadratisch — die Clips sind 960×960, jede andere Form würde beschneiden
   oder verzerren. */
.arc-stage {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: #05060f;  /* Kosmos-Schwarz der Clips, damit der Wechsel nicht blitzt */
  transition: filter 120ms linear;
}

/* Lesefläche und Klickhinweis liegen im Bild statt in einer eigenen Zeile.
   Der Verlauf hält Weiß auch über hellen Videoframes lesbar. */
.arc-stage::after {
  content: '';
  position: absolute;
  z-index: 1;
  inset: auto 0 0;
  height: 44px;
  background: linear-gradient(to bottom, transparent, rgb(0 0 0 / 0.68));
  pointer-events: none;
}

.arc-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  /* Dauer und Easing kommen aus dem web-Rendererprofil des Manifests, nicht
     von hier — deshalb steht hier keine transition-duration. */
  transition-property: opacity;
}

.arc-video.front { opacity: 1; }

.arc-video-name {
  position: absolute;
  z-index: 2;
  left: 12px;
  bottom: 9px;
  color: #fff;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-shadow: 0 1px 5px rgb(0 0 0 / 0.9);
  pointer-events: none;
}

.arc-video-action {
  position: absolute;
  z-index: 2;
  right: 12px;
  bottom: 5px;
  color: #fff;
  font-family: var(--font-mono);
  font-size: 22px;
  line-height: 1;
  text-shadow: 0 1px 5px rgb(0 0 0 / 0.9);
  pointer-events: none;
}

.arc-video-status {
  position: absolute;
  z-index: 2;
  top: 8px;
  right: 8px;
  max-width: calc(100% - 16px);
  padding: 2px 5px;
  overflow: hidden;
  background: rgb(5 6 15 / 0.72);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 10px;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}

/* Läuft ein Gespräch, bekommt das Feld einen Akzentrand — dieselbe Sprache wie
   der Live-Zustand anderswo in der App. */
.arc-panel.live .arc-stage { box-shadow: inset 0 0 0 2px var(--accent, var(--text-primary)); }
.arc-panel.talking .arc-stage {
  box-shadow: inset 0 0 0 4px var(--success, #16a34a), inset 0 0 24px rgb(22 163 74 / 0.28);
}

/* Manifest kaputt: eine dünne, stumme Zeile statt eines leeren Kastens. */
.arc-panel-slim {
  height: 2px;
  border-top: 1px solid var(--border);
}

/* Eingeklappte Sidebar: das Feld würde auf ~48 px schrumpfen und wäre dann
   weder erkennbar noch klickbar sinnvoll. */
.sidebar.collapsed .arc-panel,
.sidebar.collapsed .arc-panel-slim { display: none; }

@media (prefers-reduced-motion: reduce) {
  .arc-video { transition: none; }
}

/* Auf dem Handy ist die Seitenleiste die GANZE Breite — ein quadratisches Feld
   wird dort so hoch wie breit und frisst den halben Bildschirm (Alex' Screenshot
   117639). Deshalb dort gedeckelt: der Avatar bleibt erkennbar, nimmt aber
   nicht die Liste weg, die man eigentlich benutzt. Der Ausschnitt ist ein
   Beschnitt, keine Verzerrung — object-fit: cover bleibt. */
@media (max-width: 768px) {
  .arc-stage {
    aspect-ratio: auto;
    height: 22vh;
    max-height: 200px;
  }
  /* Fokuspunkt auf die GESICHTSMITTE, nicht auf den oberen Bildrand. 22 % war
     zu hoch: sichtbar war Stirn bis Nase, Mund und Kinn fielen aus dem
     Ausschnitt (Alex' Screenshot 118387). Im 960×960-Quellbild liegen die
     Augen bei rund 40 % und der Mund bei rund 52 % — 44 % rückt beides
     zusammen in die Mitte des Streifens. */
  .arc-video { object-position: 50% 44%; }
}

/* Sehr niedrige Fenster (Landscape-Handy): ganz aus, dort zählt jede Zeile. */
@media (max-height: 500px) {
  .arc-panel { display: none; }
}

/* Bedienleiste unter dem Video: Modus links, Mikrofon-Anzeige, Stopp rechts.
   Flach und eckig wie der Rest, Mono-Versalien wie die anderen Segment-
   Umschalter der Anwendung. */
.arc-wrap {
  border-top: 1px solid var(--border);
  flex: none;
}

.arc-wrap .arc-panel { border-top: 0; }

.arc-controls {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 4px 8px 6px;
  border-top: 1px solid var(--border);
}

.arc-modes {
  display: flex;
  flex: 1 1 100%;
  width: 100%;
  min-width: 0;
}

.arc-mode {
  flex: 1;
  min-width: 0;
  padding: 3px 2px;
  border: 1px solid var(--border);
  border-right: 0;
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.05em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.arc-mode:last-child { border-right: 1px solid var(--border); }
.arc-mode.active { background: var(--chip-active-bg); color: var(--surface); }
.arc-mode:disabled { opacity: 0.4; cursor: not-allowed; }

/* Anzeige, kein Bedienelement — deshalb kein Rahmen und kein Zeiger. */
.arc-mic {
  flex: none;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  opacity: 0.5;
}

.arc-mic.on { color: var(--success, #16a34a); opacity: 1; }

.arc-stop {
  flex: none;
  padding: 3px 8px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.05em;
  cursor: pointer;
}

.arc-stop:disabled { opacity: 0.35; cursor: not-allowed; }
.arc-stop:not(:disabled):hover { background: var(--error, #dc2626); border-color: var(--error, #dc2626); color: #fff; }

.sidebar.collapsed .arc-wrap { display: none; }
@media (max-height: 500px) { .arc-wrap { display: none; } }

/* Die schwebende Sprach-Pille lag GENAU auf dieser Leiste (Alex' Screenshot
   118483/118485). Solange das Feld sichtbar ist, zeigt es Modus, Ziel und
   Stopp bereits selbst — die Pille wandert nach oben, statt zu überdecken. */
.arc-wrap ~ .voice-minibar,
body:has(.arc-wrap) .voice-minibar {
  bottom: auto;
  top: 12px;
}

/* Vier Wörter statt vier Kürzel brauchen mehr Platz. */
.arc-mode { font-size: 8.5px; padding: 3px 1px; }
.arc-mic { font-size: 8.5px; }

.arc-controls .voice-vu {
  flex: 1;
  justify-content: flex-end;
}

.arc-voice-orb {
  position: relative;
  flex: 0 0 34px;
  width: 34px;
  height: 34px;
  overflow: hidden;
  border-radius: 50%;
  box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 26%, transparent);
}

/* Actual context-injection state, not the last spoken request. This shares the
   same hook state as the policy gate so the UI can never claim "aus" while
   feed items are being billed. */
.arc-context-status {
  flex: none;
  padding: 2px 5px;
  border: 1px solid currentColor;
  /* Seit 30.08. ein <button>: Browser-Knopfoptik neutralisieren, die Optik
     des Abzeichens bleibt. */
  background: transparent;
  cursor: pointer;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.65;
}
.arc-context-status.on {
  color: var(--success, #16a34a);
  opacity: 1;
}

/* Audio input is a rarely changed setting, not permanent status. Keep the dock
   one row tall and reveal the full picker only behind the gear. The popover
   floats over the video, so opening it never pushes the session list around. */
.arc-audio-settings {
  /* The popover must be positioned against .arc-controls, not against this
     24px gear. On the 280px desktop sidebar a gear-relative 260px menu starts
     left of the panel and gets clipped (Alex 118604). */
  position: static;
  display: inline-flex;
  flex: none;
}

.arc-settings-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

.arc-settings-btn:hover,
.arc-settings-btn.active { border-color: var(--text-primary); color: var(--text-primary); }
.arc-settings-btn.switching { border-color: var(--accent); color: var(--accent); }
.arc-settings-btn.failed { border-color: var(--error, #dc2626); background: var(--error, #dc2626); color: #fff; }

.arc-audio-popover {
  position: absolute;
  z-index: 8;
  right: 8px;
  left: auto;
  bottom: calc(100% + 7px);
  width: 260px;
  max-width: calc(100% - 16px);
  box-sizing: border-box;
  padding: 8px;
  border: 1px solid var(--text-primary);
  background: var(--surface);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.24);
  color: var(--text-primary);
}

.arc-audio-popover-title {
  display: block;
  margin-bottom: 6px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.arc-audio-popover .audio-input-picker { display: flex; width: 100%; }
.arc-audio-popover .audio-input-picker select { flex: 1; width: auto; max-width: none; }

/* On phones the sidebar spans the viewport and Alex explicitly preferred the
   compact single row. The two-row base above is for the narrower 280px desktop
   sidebar; restore the mobile layout only where the panel is actually wide. */
@media (max-width: 768px) {
  .arc-controls { flex-wrap: nowrap; }
  .arc-modes { flex: 1 1 auto; width: auto; }
  .arc-controls .voice-vu { flex: none; justify-content: initial; }
}

/* Fehlgeschlagener Start: die Zeile darf nicht aussehen wie Ruhe. */
.arc-video-status.failed { background: var(--error, #dc2626); }

/* Sprechen ohne Halten (Alex 14.09., Meta Quest): Umschalt-Knopf neben den Modi. */
.arc-talk-toggle { flex: none; padding: 3px 8px; border: 1px solid var(--border-strong); background: transparent; color: var(--text-primary); font-family: var(--font-mono); font-size: 9px; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; border-radius: 0; }
.arc-talk-toggle.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.arc-talk-toggle:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }
.ai-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  z-index: 9998;
}

.ai-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(520px, calc(100vw - 32px));
  max-height: calc(var(--vh, 1vh) * 88);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.18);
  z-index: 9999;
  display: flex;
  flex-direction: column;
}

.ai-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.ai-title {
  font-family: var(--font-heading);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-primary);
}

.ai-close {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 4px;
  display: inline-flex;
  align-items: center;
  border-radius: 3px;
}

.ai-close:hover {
  background: var(--bg-light);
  color: var(--text-primary);
}

.ai-body {
  overflow-y: auto;
  padding: 14px 18px 18px;
}

.ai-section + .ai-section {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px dashed var(--border);
}

.ai-section-title {
  margin: 0 0 10px;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.ai-rows {
  margin: 0;
  display: grid;
  grid-template-columns: minmax(120px, max-content) 1fr;
  row-gap: 6px;
  column-gap: 14px;
}

.ai-row {
  display: contents;
}

.ai-label {
  margin: 0;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--text-muted);
}

.ai-value {
  margin: 0;
  font-size: 13px;
  color: var(--text-primary);
  word-break: break-word;
}

.ai-mono {
  font-family: var(--font-mono);
  font-size: 12px;
}

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

.ai-mcp-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.ai-mcp-pill {
  padding: 3px 9px;
  background: var(--bg-light);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-primary);
}
/* `var(--text)` gab es hier siebenmal — ein Token, das nirgends definiert
   ist. Ein undefiniertes Token macht die Deklaration zur Rechenzeit
   ungueltig; bei `color` erbt der Text die Elternfarbe. Der Dialog sah
   deshalb nur zufaellig richtig aus. Berichtigt 27.08. auf
   `--text-primary`, gefunden vom Token-Waechter. */
.reset-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
}

.reset-modal {
  background: var(--surface, #1a1b26);
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
  border-radius: 12px;
  max-width: 640px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  color: var(--text, #d4d4d4);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}

.reset-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
}

.reset-modal-header h2 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 16px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-family: var(--font-heading, inherit);
}

.reset-modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  display: flex;
}

.reset-modal-close:hover {
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-primary);
}

.reset-modal-warning {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 16px 20px 8px;
  padding: 12px;
  background: rgba(217, 119, 6, 0.08);
  border: 1px solid rgba(217, 119, 6, 0.25);
  border-radius: 6px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--color-warning, #D97706);
}

.reset-modal-warning svg {
  flex-shrink: 0;
  margin-top: 2px;
}

.reset-modal-warning code {
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 4px;
  border-radius: 3px;
  font-size: 11px;
}

.reset-modal-label {
  display: block;
  margin: 12px 20px;
  font-size: 12px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.reset-modal-label small {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-muted);
  opacity: 0.8;
}

.reset-modal-label code {
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 4px;
  border-radius: 3px;
  font-family: var(--font-mono, monospace);
  font-size: 11px;
}

.reset-modal-textarea {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 10px;
  background: var(--surface-elevated, rgba(255, 255, 255, 0.03));
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
  border-radius: 6px;
  color: var(--text-primary);
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  line-height: 1.5;
  resize: vertical;
}

.reset-modal-inline {
  display: flex;
  align-items: center;
  gap: 12px;
  text-transform: none;
  letter-spacing: 0;
  font-size: 13px;
  color: var(--text-primary);
}

.reset-modal-input {
  width: 80px;
  padding: 6px 8px;
  background: var(--surface-elevated, rgba(255, 255, 255, 0.03));
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
  border-radius: 4px;
  color: var(--text-primary);
  font-family: var(--font-mono, monospace);
  font-size: 13px;
}

.reset-modal-cloud-guard {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px;
  background: rgba(220, 38, 38, 0.08);
  border: 1px solid rgba(220, 38, 38, 0.25);
  border-radius: 6px;
  text-transform: none;
  letter-spacing: 0;
  font-size: 12px;
  color: var(--color-error, #DC2626);
  line-height: 1.5;
}

.reset-modal-cloud-guard input {
  margin-top: 2px;
}

.reset-modal-cloud-guard strong {
  color: var(--text-primary);
}

.reset-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 16px 20px;
  border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  margin-top: 8px;
}

.reset-modal-cancel,
.reset-modal-submit {
  padding: 8px 16px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  border: none;
}

.reset-modal-cancel {
  background: var(--surface-elevated, rgba(255, 255, 255, 0.05));
  color: var(--text-primary);
}

.reset-modal-cancel:hover {
  background: rgba(255, 255, 255, 0.08);
}

.reset-modal-submit {
  background: var(--color-warning, #D97706);
  color: white;
}

.reset-modal-submit:hover:not(:disabled) {
  opacity: 0.9;
}

.reset-modal-submit:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.reset-modal-progress,
.reset-modal-result {
  padding: 20px;
  text-align: center;
  font-size: 13px;
  line-height: 1.6;
}

.reset-modal-progress {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.reset-modal-spinner {
  width: 32px;
  height: 32px;
  border: 3px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
  border-top-color: var(--color-warning, #D97706);
  border-radius: 50%;
  animation: reset-spin 1s linear infinite;
}

@keyframes reset-spin {
  to { transform: rotate(360deg); }
}

.reset-modal-result {
  text-align: left;
}

.reset-modal-result strong {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
}

.reset-modal-result ul {
  margin: 0;
  padding-left: 20px;
}

.reset-modal-result li {
  margin: 4px 0;
}

.reset-modal-result code {
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 5px;
  border-radius: 3px;
  font-family: var(--font-mono, monospace);
  font-size: 11px;
}

.reset-modal-result details {
  margin-top: 12px;
  font-size: 12px;
}

.reset-modal-result summary {
  cursor: pointer;
  color: var(--text-muted);
}

.reset-modal-phases {
  margin-top: 8px;
  padding: 10px;
  background: var(--surface-elevated, rgba(0, 0, 0, 0.3));
  border-radius: 4px;
  font-family: var(--font-mono, monospace);
  font-size: 11px;
  line-height: 1.5;
  white-space: pre-wrap;
  max-height: 280px;
  overflow-y: auto;
}

.reset-modal-error {
  border-left: 3px solid var(--color-error, #DC2626);
  padding-left: 17px;
}

.reset-modal-error strong {
  color: var(--color-error, #DC2626);
}

.reset-modal-ok {
  border-left: 3px solid var(--color-success, #16A34A);
  padding-left: 17px;
}

.reset-modal-ok strong {
  color: var(--color-success, #16A34A);
}
/* Clone dialog — extends ResetModal.css scaffold (Alex 2026-06-23). */
.clone-modal { max-width: 460px; }

.clone-inline {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 12px;
}

.clone-check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 12px;
  font-size: 13px;
  color: var(--text-primary);
  cursor: pointer;
}
.clone-check input { margin-top: 2px; flex-shrink: 0; }
.clone-check small { color: var(--text-muted); }

.clone-hint {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 8px;
  line-height: 1.4;
}
.clone-hint-warn { color: #dc2626; }

.clone-spin { animation: clone-spin 0.9s linear infinite; }
@keyframes clone-spin { to { transform: rotate(360deg); } }

/* Move dialog: from → to node route. */
.move-route {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 14px 0 4px;
  color: var(--text-secondary);
}
.move-node {
  font-family: var(--font-mono);
  font-size: 13px;
  padding: 4px 10px;
  border: 1px solid var(--border-strong);
}
.move-node-to {
  border-color: var(--accent);
  color: var(--accent);
}
/* Die vier Kontaktlisten. Flach und eckig wie der Rest des Portals:
   kein Radius, keine Schatten, Beschriftungen in Versalien/Monospace. */

.kl {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--border);
}

.kl-feld {
  background: var(--surface);
  padding: 10px 12px;
}

.kl-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}

.kl-titel {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-primary);
}

/* WANN eine Aenderung wirkt, steht neben dem Titel — nicht in einem
   Hilfetext, den niemand aufklappt. Der Unterschied zwischen „sofort" und
   „beim naechsten Start" ist der zwischen entzogenem und noch bestehendem
   Zugriff. */
.kl-wirkung {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  white-space: nowrap;
}

.kl-liste {
  list-style: none;
  margin: 0 0 6px;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.kl-eintrag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 4px 2px 7px;
  background: var(--chip-active-bg);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 11px;
}

.kl-weg {
  border: 0;
  background: none;
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 0 2px;
}
.kl-weg:hover { opacity: 1; }

/* Eine nicht konfigurierte Liste ist NICHT leer — sie bedeutet, was die
   Instanz vorgibt. Deshalb steht hier ein Satz und kein Nichts. */
.kl-leer {
  font-size: 12px;
  color: var(--text-muted);
  font-style: italic;
  margin-bottom: 6px;
}

.kl-zufuegen { display: flex; flex-direction: column; gap: 6px; }

.kl-freitext { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.kl-freitext .dialog-input { flex: 1 1 200px; }

.kl-hinweis {
  padding: 8px 12px;
  background: var(--bg-inset);
  border-left: 2px solid var(--border-strong);
  font-size: 12px;
  color: var(--text-secondary);
}

.kl-hinweis-warn {
  background: var(--color-warning-bg, var(--bg-inset));
  border-left-color: var(--color-warning);
  color: var(--text-primary);
}

.kl-hinweis-klein {
  flex-basis: 100%;
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.4;
}
/* ── Dialog Backdrop ──────────────────────────────────────────── */
.dialog-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.3);
  z-index: 9000;
}

/* ── Dialog Container ────────────────────────────────────────── */
.new-session-dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--surface);
  border: 1px solid var(--border);
  width: 480px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 64px);
  overflow-y: auto;
  z-index: 9001;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}

/* ── Header ──────────────────────────────────────────────────── */
.dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px 16px;
  border-bottom: 1px solid var(--border);
}

.dialog-title {
  font-family: var(--font-heading);
  font-size: 16px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-primary);
}

.dialog-close {
  width: 28px;
  height: 28px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s ease;
}

.dialog-close:hover {
  color: var(--text-primary);
}

/* ── Body ────────────────────────────────────────────────────── */
.dialog-body {
  padding: 20px 24px;
}

/* ── Avatar ──────────────────────────────────────────────────── */
.dialog-avatar-row {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.dialog-avatar {
  width: 56px;
  height: 56px;
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  overflow: hidden;
  border-radius: 50%;
  transition: border-color 0.15s ease;
}

.dialog-avatar:hover {
  border-color: var(--text-primary);
}

.dialog-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.dialog-avatar-placeholder {
  font-size: 20px;
  color: var(--text-muted);
}

.dialog-avatar-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.dialog-avatar {
  position: relative;
}

.dialog-avatar-overlay-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.dialog-avatar-btn {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  text-align: left;
  transition: color 0.15s ease;
}

.dialog-avatar-btn:hover {
  color: var(--text-primary);
}

.dialog-avatar-remove {
  color: var(--accent);
}

.dialog-avatar-remove:hover {
  color: var(--accent-hover);
}

.dialog-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 24px;
}

.dialog-field {
  display: flex;
  flex-direction: column;
}

.dialog-field.full {
  grid-column: 1 / -1;
}

.dialog-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: 6px;
}

.dialog-input {
  display: block;
  width: 100%;
  padding: 8px 0;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 16px;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  outline: none;
  transition: border-color 0.2s ease;
}

.dialog-input:focus {
  border-bottom-color: var(--text-primary);
}

.dialog-input::placeholder {
  color: var(--text-muted);
}

.dialog-select {
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  padding: 8px 28px 8px 0;
  background-color: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 14px;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  outline: none;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999999' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0 center;
  transition: border-color 0.2s ease;
}

.dialog-select:focus {
  border-bottom-color: var(--text-primary);
}

.dialog-select:disabled {
  color: var(--text-muted);
  cursor: not-allowed;
}

/* ── Effort Buttons ──────────────────────────────────────────── */
.dialog-effort-row {
  display: flex;
  border: 1px solid var(--border);
}

.dialog-effort-btn {
  flex: 1;
  padding: 6px 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border: none;
  border-right: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s ease;
}

.dialog-effort-btn:last-child {
  border-right: none;
}

.dialog-effort-btn:hover {
  color: var(--text-primary);
}

.dialog-effort-btn.active {
  background: var(--accent);
  color: var(--white);
}

/* ── Lifecycle ───────────────────────────────────────────────── */
.dialog-lifecycle-section {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.dialog-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
  cursor: pointer;
}

.dialog-toggle-info {
  flex: 1;
  min-width: 0;
}

.dialog-toggle-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
}

.dialog-toggle-desc {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
  line-height: 1.4;
}

.dialog-toggle-switch {
  width: 36px;
  height: 20px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  border-radius: 0;
  padding: 0;
  transition: all 0.15s ease;
}

.dialog-toggle-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  background: var(--text-muted);
  transition: all 0.15s ease;
}

.dialog-toggle-switch.active {
  background: var(--accent);
  border-color: var(--accent);
}

.dialog-toggle-switch.active::after {
  left: calc(100% - 16px);
  background: var(--surface);
}

/* ── MCP Servers ─────────────────────────────────────────────── */
.dialog-mcp-section {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.dialog-mcp-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin-top: 8px;
}

.dialog-mcp-item {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

.dialog-mcp-item input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--accent);
  cursor: pointer;
}

.dialog-mcp-name {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
}

/* ── Permissions Preview ─────────────────────────────────────── */
.dialog-permissions {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.dialog-perm-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}

.dialog-perm-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  padding: 2px 6px;
  border: 1px solid var(--border);
}

/* ── Error ───────────────────────────────────────────────────── */
.dialog-error {
  margin-top: 12px;
  padding: 8px 12px;
  background: var(--color-error-bg);
  color: var(--color-error);
  font-size: 12px;
}

/* ── Footer ──────────────────────────────────────────────────── */
.dialog-footer {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  padding: 16px 24px;
  border-top: 1px solid var(--border);
}

.dialog-btn-primary {
  padding: 8px 20px;
  background: var(--accent);
  color: var(--white);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: none;
  border-radius: 0;
  cursor: pointer;
  transition: background 0.15s ease;
}

.dialog-btn-primary:hover {
  background: var(--accent-hover);
}

.dialog-btn-primary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.dialog-btn-secondary {
  padding: 8px 20px;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: 1px solid var(--border);
  border-radius: 0;
  cursor: pointer;
  transition: all 0.15s ease;
}

.dialog-btn-secondary:hover {
  border-color: var(--text-primary);
}

/* ── Name-collision warning (#46) ─────────────────────────────── */
.dialog-input-error {
  border-color: var(--color-error, #d22) !important;
  background: var(--color-error-bg, rgba(220, 34, 34, 0.06)) !important;
}

.dialog-input-warn {
  border-color: var(--color-warning, #c80) !important;
  background: var(--color-warning-bg, rgba(204, 136, 0, 0.06)) !important;
}

.dialog-field-error {
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-error, #d22);
  line-height: 1.4;
}

.dialog-field-warn {
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-warning, #c80);
  line-height: 1.4;
}

.dialog-btn-primary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ── Mobile ──────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .new-session-dialog {
    width: calc(100vw - 24px);
    top: auto;
    bottom: 16px;
    transform: translateX(-50%);
  }

  .dialog-form-grid {
    grid-template-columns: 1fr;
  }
}

/* Erklärender Hinweis unter einem Pflichtfeld — ruhig, nicht alarmierend:
   Er steht da, solange nichts eingegeben ist, und begründet die Pflicht. */
.dialog-field-hint {
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-muted);
}

/* Pflichtangabe + erklaerender Hinweis am Feld.
   Der Stern allein sagt nur DASS etwas fehlt; der Satz darunter sagt, was
   passiert, wenn es fehlt — das ist der Teil, den ein Mensch braucht. */
.dialog-pflicht {
  color: var(--color-warning);
  font-weight: 700;
}

.dialog-hinweis {
  margin-top: 4px;
  font-size: 11px;
  line-height: 1.4;
  color: var(--text-muted);
}

/* Aktives Konto weicht vom Profil ab (Alex 11.09.): Warnfarbe, kein zweiter Kasten. */
.dialog-field-hint-warnung { color: var(--color-warning); }
/* Desktop hover info card — flat/square, dark surface (Alex 2026-06-23). */
.aht {
  position: fixed;
  z-index: 11000;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.32);
  padding: 8px 10px;
  font-family: var(--font-body);
  pointer-events: none; /* never steal hover from the trigger */
  animation: aht-in 0.1s ease;
}
@keyframes aht-in {
  from { opacity: 0; transform: translateY(-3px); }
  to { opacity: 1; transform: translateY(0); }
}

.aht-name {
  font-family: var(--font-heading);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-primary);
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
}

.aht-rows { margin: 0; }
.aht-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 2px 0;
}
.aht-row dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  flex-shrink: 0;
}
.aht-row dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pi-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  z-index: 9998;
}

.pi-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(960px, calc(100vw - 32px));
  height: min(680px, calc(var(--vh, 1vh) * 90));
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.18);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.pi-modal.is-brain {
  width: min(1320px, calc(100vw - 24px));
  height: min(860px, calc(var(--vh, 1vh) * 94));
}

.pi-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.pi-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-heading);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-primary);
}

.pi-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-muted);
  margin-left: 4px;
}

.pi-header-actions {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.pi-view-switch {
  display: inline-flex;
  margin-right: 5px;
  border: 1px solid var(--border);
}

.pi-view-switch button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 28px;
  padding: 0 8px;
  border: 0;
  border-right: 1px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  cursor: pointer;
}

.pi-view-switch button:last-child {
  border-right: 0;
}

.pi-view-switch button:hover {
  color: var(--text-primary);
  background: var(--bg-light);
}

.pi-view-switch button.active {
  color: var(--white);
  background: var(--chip-active-bg);
}

.pi-action,
.pi-close {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 6px;
  display: inline-flex;
  align-items: center;
  border-radius: 3px;
}

.pi-action:hover,
.pi-close:hover {
  background: var(--bg-light);
  color: var(--text-primary);
}

.pi-action:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pi-body {
  flex: 1;
  display: flex;
  min-height: 0;
}

.pi-brain-shell {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 0;
}

.pi-brain-detail {
  position: absolute;
  top: 12px;
  right: 12px;
  bottom: 58px;
  z-index: 6;
  display: flex;
  flex-direction: column;
  width: min(430px, calc(100% - 24px));
  border: 1px solid var(--border-strong);
  background: color-mix(in srgb, var(--surface) 96%, transparent);
  box-shadow: 0 16px 42px rgba(0, 0, 0, 0.2);
  backdrop-filter: blur(16px);
}

.pi-brain-detail > header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
}

.pi-brain-detail > header > div {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 3px;
}

.pi-brain-detail > header span {
  overflow: hidden;
  color: var(--text-primary);
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: 650;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pi-brain-detail > header small {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  line-height: 1.35;
}

.pi-brain-detail > header button {
  display: inline-grid;
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  place-items: center;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

.pi-brain-detail > header button:hover {
  color: var(--text-primary);
  background: var(--bg-light);
}

.pi-brain-detail-body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  user-select: text;
}

.pi-brain-detail-body .pi-content-md,
.pi-brain-detail-body .pi-content-raw {
  width: 100%;
  min-height: 100%;
  margin: 0;
  border: 0;
}

.pi-loading,
.pi-error {
  margin: auto;
  font-size: 13px;
  color: var(--text-muted);
}

.pi-error {
  color: var(--color-error);
}

.pi-layers {
  flex: 0 0 240px;
  border-right: 1px solid var(--border);
  overflow-y: auto;
  background: var(--bg-light);
  display: flex;
  flex-direction: column;
}

/* ── Scope-Switch (Bot vs Pool) ───────────────────────────────
 * Only rendered when the bot belongs to a pool. Lets the user toggle
 * which scope the per-row toggles apply to. */
.pi-scope-switch {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-inset);
}

.pi-scope-btn {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 6px;
  background: transparent;
  border: none;
  border-right: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pi-scope-btn:last-child {
  border-right: none;
}

.pi-scope-btn:hover {
  color: var(--text-primary);
  background: var(--bg-light);
}

.pi-scope-btn.active {
  background: var(--chip-active-bg);
  color: var(--white);
  font-weight: 600;
}

/* ── Counter + Reset row ──────────────────────────────────── */
.pi-toggle-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 6px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-inset);
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
}

.pi-toggle-counter {
  letter-spacing: 0.03em;
}

.pi-toggle-counter-off {
  color: var(--color-warning);
  font-weight: 600;
}

.pi-toggle-reset {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 6px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 3px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  cursor: pointer;
}

.pi-toggle-reset:hover:not(:disabled) {
  background: var(--surface);
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.pi-toggle-reset:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pi-toggle-error {
  padding: 6px 12px;
  background: var(--color-error-bg);
  color: var(--color-error);
  font-size: 11px;
  font-family: var(--font-mono);
  border-bottom: 1px solid var(--border);
}

.pi-layer-row {
  display: grid;
  /* Source label | size | toggle (optional). Toggle column is auto so it
   * collapses for rows without a canonical_key (identity, bot-dir, …). */
  grid-template-columns: 1fr auto auto;
  align-items: center;
  column-gap: 8px;
  padding: 10px 12px;
  border: none;
  background: transparent;
  text-align: left;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
}

.pi-layer-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.pi-layer-row:hover {
  background: var(--bg-inset);
}

.pi-layer-row.active {
  background: var(--chip-active-bg);
  color: var(--white);
}

.pi-layer-source {
  font-size: 12px;
  font-weight: 600;
}

.pi-layer-size {
  font-size: 10px;
  color: var(--text-muted);
}

.pi-layer-row.active .pi-layer-size {
  color: rgba(255, 255, 255, 0.7);
}

.pi-layer-path {
  grid-column: 1 / -1;
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 2px;
  word-break: break-all;
  white-space: normal;
}

/* ── Per-layer Fragment-Toggle ────────────────────────────────
 * Each prompt_fragment row gets a toggle that disables that fragment
 * for the active scope (bot or pool). Disabled fragments stay visible
 * in the sidebar but their content is grayed + struck through so the
 * user can SEE what was excluded without losing the visual anchor.
 * Cloud-API persists per-bot list in session_registry.disabled_fragments,
 * per-pool list in pool_config.disabled_fragments. Effect at next
 * prepare_bot_home (= bot restart). */
.pi-layer-toggle {
  background: transparent;
  border: none;
  padding: 2px 4px;
  cursor: pointer;
  color: var(--color-success);
  display: inline-flex;
  align-items: center;
  border-radius: 3px;
}

.pi-layer-toggle.is-off {
  color: var(--text-muted);
}

.pi-layer-toggle:hover:not(:disabled) {
  background: var(--bg-inset);
}

.pi-layer-toggle:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pi-layer-row.active .pi-layer-toggle {
  color: var(--white);
}

.pi-layer-row.active .pi-layer-toggle.is-off {
  color: rgba(255, 255, 255, 0.5);
}

/* Visual cue for disabled layers — content greyed, source label struck
 * through. The toggle itself stays full-opacity so it can be re-enabled. */
.pi-layer-row.is-disabled .pi-layer-source,
.pi-layer-row.is-disabled .pi-layer-size,
.pi-layer-row.is-disabled .pi-layer-path {
  text-decoration: line-through;
  opacity: 0.55;
}

.pi-layer-row.active .pi-layer-path {
  color: rgba(255, 255, 255, 0.6);
}

/* ── Memory section ─────────────────────────────────────────────
 * Visually separated band below the federation fragments. Lila
 * accent + "private" pill so it's obvious this is the bot's own
 * /auto-memory output, not part of the assembled prompt. */
.pi-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 12px 6px;
  font-family: var(--font-heading);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #6b21a8;
  border-top: 1px solid var(--border);
  margin-top: 4px;
}

.pi-section-pill {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  text-transform: lowercase;
  letter-spacing: 0;
  padding: 1px 6px;
  background: rgba(107, 33, 168, 0.08);
  border: 1px solid rgba(107, 33, 168, 0.25);
  color: #6b21a8;
  border-radius: 2px;
}

/* Collapsible fragment-source group header — neutral palette (not the
   purple "memory" accent). Used to group System / MCP / Department /
   etc. so the sidebar becomes a hierarchy instead of a flat list. */
.pi-section-header-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-start;
  width: 100%;
  background: var(--bg-inset);
  border: none;
  /* No border-top — the previous row already brings its bottom border,
     stacking the two would produce a visible double-line at the seam. */
  border-bottom: 1px solid var(--border);
  padding: 8px 12px;
  font-family: var(--font-heading);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-primary);
  cursor: pointer;
  text-align: left;
}
.pi-section-header-toggle:hover {
  background: var(--bg-light);
}
.pi-section-header-toggle .pi-section-chevron {
  display: inline-block;
  width: 10px;
  color: var(--text-muted);
  font-size: 10px;
}
.pi-section-header-toggle .pi-section-pill {
  margin-left: auto;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
}
.pi-section-header-toggle.is-collapsed {
  border-bottom: none;
}

.pi-fragment-group {
  /* The wrapper exists only to keep header + nested rows together for
     keyboard nav semantics; styles live on header + .pi-layer-row-nested. */
}
.pi-layer-row-nested {
  padding-left: 24px;
}

.pi-section-subheader {
  padding: 4px 12px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  background: var(--bg-inset);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pi-layer-row-memory .pi-layer-source {
  color: #6b21a8;
}

.pi-layer-row-memory.active {
  background: #6b21a8;
}

.pi-layer-row-memory.active .pi-layer-source {
  color: var(--white);
}

.pi-layer-badge {
  margin-left: 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  padding: 1px 4px;
  background: rgba(107, 33, 168, 0.12);
  color: #6b21a8;
  border-radius: 2px;
}

.pi-layer-row-memory.active .pi-layer-badge {
  background: rgba(255, 255, 255, 0.2);
  color: var(--white);
}

.pi-content {
  flex: 1;
  margin: 0;
  padding: 14px 18px;
  overflow: auto;
  color: var(--text-primary);
  background: var(--surface);
  min-width: 0;
}

/* Raw view — exact bytes, monospace, preserve whitespace. */
.pi-content-raw {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Rendered view — react-markdown output. Stays compact because the
 * left layer sidebar already eats 220 px; the prose column has to
 * survive even when the modal is at min-width. */
.pi-content-md {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  word-break: break-word;
}

.pi-content-md h1,
.pi-content-md h2,
.pi-content-md h3,
.pi-content-md h4,
.pi-content-md h5,
.pi-content-md h6 {
  margin: 18px 0 8px;
  font-family: var(--font-heading);
  font-weight: 600;
  line-height: 1.25;
  color: var(--text-primary);
}

.pi-content-md h1 { font-size: 19px; padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.pi-content-md h2 { font-size: 16px; padding-bottom: 4px; border-bottom: 1px solid var(--border); }
.pi-content-md h3 { font-size: 14px; }
.pi-content-md h4,
.pi-content-md h5,
.pi-content-md h6 { font-size: 13px; color: var(--text-muted); }

.pi-content-md p { margin: 0 0 10px; }

.pi-content-md a {
  color: var(--accent);
  text-decoration: none;
}
.pi-content-md a:hover { text-decoration: underline; }

.pi-content-md ul,
.pi-content-md ol {
  margin: 0 0 10px;
  padding-left: 20px;
}

.pi-content-md li { margin: 2px 0; }

.pi-content-md code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 1px 5px;
  border-radius: 2px;
}

.pi-content-md pre {
  margin: 8px 0;
  padding: 10px 12px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.45;
}

.pi-content-md pre code {
  background: none;
  border: none;
  padding: 0;
  font-size: 11px;
}

.pi-content-md blockquote {
  margin: 8px 0;
  padding: 4px 12px;
  border-left: 3px solid var(--border-strong);
  color: var(--text-muted);
}

.pi-content-md hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 16px 0;
}

.pi-content-md table {
  border-collapse: collapse;
  margin: 8px 0;
  font-size: 12px;
}
.pi-content-md th,
.pi-content-md td {
  border: 1px solid var(--border);
  padding: 4px 8px;
  text-align: left;
}
.pi-content-md th {
  background: var(--bg-light);
  font-weight: 600;
}

@media (max-width: 768px), (max-height: 500px) {
  .pi-modal.is-brain {
    top: 0;
    left: 0;
    width: 100vw;
    height: calc(var(--vh, 1vh) * 100);
    transform: none;
  }

  .pi-view-switch button span {
    display: none;
  }

  .pi-brain-detail {
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    max-height: 64%;
  }

  .pi-body {
    flex-direction: column;
  }
  .pi-layers {
    flex: 0 0 auto;
    max-height: 180px;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
}
.agent-brain-canvas {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  touch-action: none;
  background:
    radial-gradient(circle at 28% 48%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 34%),
    var(--bg-inset);
  color: var(--text-primary);
  cursor: grab;
  user-select: none;
}

.agent-brain-canvas:active {
  cursor: grabbing;
}

.agent-brain-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.agent-brain-world {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
}

.agent-brain-edges {
  position: absolute;
  inset: 0;
  overflow: visible;
  pointer-events: none;
}

.agent-brain-edges path {
  fill: none;
  stroke: color-mix(in srgb, var(--accent) 52%, var(--border));
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.agent-brain-edges path.kind-capability {
  stroke: color-mix(in srgb, var(--color-info) 62%, var(--border));
  stroke-dasharray: 8 5;
}

.agent-brain-edges path.kind-private {
  stroke: color-mix(in srgb, var(--text-muted) 70%, var(--border));
  stroke-dasharray: 2 7;
}

.agent-brain-node {
  position: absolute;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 13px 15px;
  border: 1px solid color-mix(in srgb, var(--border-strong) 78%, var(--accent));
  background: color-mix(in srgb, var(--surface) 95%, var(--accent));
  color: var(--text-primary);
  text-align: left;
  font: inherit;
  clip-path: polygon(10px 0, calc(100% - 10px) 0, 100% 10px, 100% calc(100% - 10px), calc(100% - 10px) 100%, 10px 100%, 0 calc(100% - 10px), 0 10px);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.11);
  overflow: hidden;
}

button.agent-brain-node {
  cursor: pointer;
}

button.agent-brain-node:hover,
.agent-brain-node.is-selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--surface) 88%, var(--accent));
}

button.agent-brain-node:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: 4px;
}

.agent-brain-node.kind-agent {
  border-width: 2px;
  background: color-mix(in srgb, var(--surface) 80%, var(--accent));
  box-shadow: 0 0 0 8px color-mix(in srgb, var(--accent) 9%, transparent), 0 16px 36px rgba(0, 0, 0, 0.14);
}

.agent-brain-node.kind-group,
.agent-brain-node.kind-memory-group {
  background: var(--bg-light);
  border-color: var(--border-strong);
  box-shadow: 0 7px 18px rgba(0, 0, 0, 0.08);
}

.agent-brain-node.kind-mcp,
.agent-brain-node.kind-tool {
  border-color: color-mix(in srgb, var(--color-info) 48%, var(--border));
}

.agent-brain-node.kind-memory,
.agent-brain-node.kind-memory-group {
  border-color: color-mix(in srgb, var(--text-muted) 55%, var(--border));
  background: color-mix(in srgb, var(--surface) 94%, var(--text-muted));
}

.agent-brain-node.is-disabled {
  opacity: 0.5;
  filter: grayscale(0.72);
}

.agent-brain-node-icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  clip-path: polygon(25% 0, 75% 0, 100% 25%, 100% 75%, 75% 100%, 25% 100%, 0 75%, 0 25%);
}

.kind-group .agent-brain-node-icon,
.kind-memory-group .agent-brain-node-icon {
  color: var(--text-secondary);
  background: var(--bg-inset);
}

.agent-brain-node-copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 3px;
}

.agent-brain-node-copy strong {
  overflow: hidden;
  color: var(--text-primary);
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: 650;
  line-height: 1.15;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-brain-node-copy > span {
  display: -webkit-box;
  overflow: hidden;
  color: var(--text-secondary);
  font-size: 11px;
  line-height: 1.3;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.agent-brain-node-copy small {
  overflow: hidden;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-brain-node-order {
  align-self: start;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
}

.agent-brain-node-state {
  position: absolute;
  right: 10px;
  bottom: 7px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
}

.agent-brain-controls {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 1px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  box-shadow: 0 7px 22px rgba(0, 0, 0, 0.13);
  backdrop-filter: blur(12px);
}

.agent-brain-controls button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 34px;
  height: 34px;
  justify-content: center;
  padding: 0 9px;
  border: 0;
  border-right: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: 10px;
  cursor: pointer;
}

.agent-brain-controls button:hover {
  background: var(--bg-light);
  color: var(--text-primary);
}

.agent-brain-zoom-value {
  min-width: 42px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  text-align: center;
}

.agent-brain-legend {
  position: absolute;
  left: 12px;
  bottom: 12px;
  z-index: 4;
  display: flex;
  gap: 12px;
  padding: 7px 9px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  backdrop-filter: blur(12px);
}

.agent-brain-caption {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 7px 9px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(12px);
}

.agent-brain-caption strong {
  color: var(--text-secondary);
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.agent-brain-caption span {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
}

.agent-brain-legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.agent-brain-legend i {
  display: inline-block;
  width: 18px;
  border-top: 2px solid var(--accent);
}

.agent-brain-legend .legend-capability {
  border-color: var(--color-info);
  border-top-style: dashed;
}

.agent-brain-legend .legend-private {
  border-color: var(--text-muted);
  border-top-style: dotted;
}

@media (max-width: 700px) {
  .agent-brain-controls {
    right: 8px;
    bottom: 8px;
  }

  .agent-brain-controls button span,
  .agent-brain-legend,
  .agent-brain-caption span {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .agent-brain-world {
    will-change: auto;
  }
}
/* Account-usage widget (#426) — sits above the connection footer in the
   sidebar. Flat/square like the rest of the shell (radius 0, mono-uppercase
   micro-labels, --surface/--border tokens so it themes in both modes). */

.usage-widget {
  padding: 8px 16px 10px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Gedeckelt und in sich rollend: die Liste waechst mit der Zahl der Konten
     (Alex hat Dutzende Profile) und schob Fusszeile und Avatar aus dem Bild —
     die Seitenleiste selbst rollt nicht. Ein Deckel ist ehrlicher als ein
     unerreichbarer Rest. */
  max-height: 30vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.uw-head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.uw-stale {
  color: var(--color-warning);
  background: var(--color-warning-bg);
  padding: 0 4px;
}

.uw-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.uw-name {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.uw-badge {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: none;
  font-family: var(--font-mono);
  font-size: 8px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 1px 3px;
  color: var(--color-error);
  background: var(--color-error-bg);
}

/* Sub-heading between the Anthropic block and the Codex block. */
.uw-sub {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-top: 2px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
}

/* Secondary Codex account — present, readable, but visibly not the one that
   matters (Alex' primary login leads). Ordering only, never hiding. */
.uw-row-secondary { opacity: 0.6; }

.uw-plan {
  flex: none;
  font-family: var(--font-mono);
  font-size: 8px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 1px 3px;
  color: var(--text-muted);
  background: var(--bg-light, transparent);
  border: 1px solid var(--border);
}

.uw-bots {
  flex: none;
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

/* Snapshot age. Deliberately muted but always present: the Codex values can be
   a day old (no usage endpoint at OpenAI), and a stale number that looks live
   is worse than no number. */
.uw-age {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-muted);
  margin-top: -1px;
}

.uw-err {
  font-size: 10px;
  color: var(--text-muted);
  font-style: italic;
}

.uw-metrics {
  display: flex;
  align-items: center;
  gap: 10px;
}

.uw-metric {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 1;
  min-width: 0;
  cursor: default;
}

.uw-metric-label {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  color: var(--text-muted);
  flex: none;
}

.uw-bar {
  flex: 1;
  min-width: 14px;
  height: 4px;
  background: var(--border);
  overflow: hidden;
}

.uw-bar-fill {
  display: block;
  height: 100%;
  background: currentColor;
  transition: width 0.4s ease;
}

.uw-pct {
  font-family: var(--font-mono);
  font-size: 10px;
  flex: none;
  min-width: 26px;
  text-align: right;
}

/* Traffic light — the colour rides on `color` so the bar fill (currentColor)
   and the number stay in sync. */
.uw-ok { color: var(--color-success); }
.uw-warn { color: var(--color-warning); }
.uw-crit { color: var(--color-error); }

/* Trennpunkt zwischen Stand und Reset in der Fußzeile — etwas blasser als der
   Text selbst, damit er trennt statt mitzulesen. */
.uw-sep { opacity: 0.45; }

/* Herkunft eines Kontos — leise, aber sichtbar (Issue #1205). Steht unter der
   Zeile wie die Stand-/Reset-Angabe, damit die Antwort auf „warum ist das hier"
   nicht in einem Tooltip verschwindet, den man am Handy nie sieht. */
.uw-origin {
  font-size: 10.5px;
  color: var(--text-muted);
  margin-top: 2px;
  opacity: 0.85;
}

/* Ein Konto, mehrere Master-Token-Profile (Alex 10.09.) — Hinweis statt Doppelzeile. */
.uw-dup { margin-left: 6px; }
.uw-fremd { margin-left: 6px; color: var(--color-warning); border-color: var(--color-warning); }
.uw-hide { margin-left: auto; background: transparent; border: 1px solid transparent; color: var(--text-secondary); font: inherit; font-size: 12px; line-height: 1; padding: 0 4px; cursor: pointer; border-radius: 0; opacity: 0; }
.uw-row:hover .uw-hide, .uw-hide:focus { opacity: 1; }
.uw-hidden-foot { display: flex; flex-wrap: wrap; gap: 8px; padding: 4px 0 0; }
.uw-link { background: transparent; border: 0; padding: 0; color: var(--text-secondary); font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; text-decoration: underline; cursor: pointer; }
/* Kontingent-Anzeige (Tenant Edition) — flach/eckig, Stil wie Chips/Meta. */
.usage-meter {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}
.usage-meter-bar {
  width: 72px;
  height: 5px;
  background: var(--bg-inset, var(--border));
  overflow: hidden;
  flex: none;
}
.usage-meter-fill {
  height: 100%;
  background: var(--text-muted);
}
.usage-warn .usage-meter-fill { background: var(--color-warning, #b58900); }
.usage-warn .usage-meter-label { color: var(--color-warning, #b58900); }
.usage-throttled .usage-meter-fill { background: var(--color-error, #d81b16); }
.usage-throttled .usage-meter-label { color: var(--color-error, #d81b16); font-weight: 700; }
/* ── Sidebar ──────────────────────────────────────────────────── */
.sidebar {
  position: relative; /* anchors the glass header overlay */
  width: var(--sidebar-width);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: var(--surface);
  flex-shrink: 0;
}

/* Glass header overlay (Alex 2026-07-03): logo + search + filter float as
   translucent blur, the agent list scrolls beneath. Height → --sb-hdr-h. */
.sidebar-header {
  padding: 20px 16px 16px;
  padding-top: calc(env(safe-area-inset-top, 0px) + 12px);
  border-bottom: 1px solid var(--border);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 90;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .sidebar-header { background: var(--surface); }
}

.sidebar-logo-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
}

.sidebar-logo {
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-primary);
}
/* Logo rendered as a button (opens Settings) — strip native button chrome so it
   reads identically to the static label, just clickable. */
.sidebar-logo-btn {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  transition: opacity 0.15s ease;
}
.sidebar-logo-btn:hover { opacity: 0.75; }

/* Right-side header action cluster: debug + theme toggle + collapse, grouped. */
.sidebar-header-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
/* Debug button error badge — red when console has captured errors. */
.sidebar-debug-btn.has-errors {
  background: var(--color-error);
  border-color: var(--color-error);
  color: var(--white);
}
.sidebar-debug-count {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}

.sidebar-collapse-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s ease;
}
.sidebar-collapse-btn:hover {
  color: var(--text-primary);
  background: var(--bg-light);
  border-color: var(--border-strong);
}

/* Initials fallback avatar — hidden in the expanded list (an avatar-less
 * agent shows just its dot + name there, unchanged), revealed only in the
 * collapsed rail so every agent has a clickable target. */
.session-avatar-initial {
  display: none;
  align-items: center;
  justify-content: center;
  background: var(--bg-light);
  color: var(--text-secondary, var(--text-muted));
  font-family: var(--font-heading);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
}

.sidebar-logo span {
  color: var(--accent);
}

/* ── Search ──────────────────────────────────────────────────── */
.search-wrapper {
  position: relative;
  margin-bottom: 12px;
}

.search-input {
  display: block;
  width: 100%;
  padding: 8px 0;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 16px;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  outline: none;
  transition: border-color 0.2s ease;
}

.search-input:focus {
  border-bottom-color: var(--text-primary);
}

.search-input::placeholder {
  color: var(--text-muted);
}

.search-input {
  padding-right: 28px;
}

.search-clear {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: none;
  background: var(--text-muted);
  color: var(--white);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background 0.15s ease;
}

.search-clear:hover {
  background: var(--chip-active-bg);
}

/* ── Filter Pills ─────────────────────────────────────────────── */
.filter-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.filter-pill {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 3px 10px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s ease;
}

.filter-pill:hover {
  border-color: var(--text-primary);
  color: var(--text-primary);
}

.filter-pill.active {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
}

/* ── Sort Row ─────────────────────────────────────────────────── */
.filter-row {
  display: flex;
  gap: 0;
  margin-top: 10px;
  border: 1px solid var(--border);
}

.filter-btn {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px 0;
  border: none;
  border-right: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.filter-btn:last-child {
  border-right: none;
}

.filter-btn:hover {
  color: var(--text-primary);
}

.filter-btn.active {
  background: var(--chip-active-bg);
  color: var(--white);
}

.filter-count {
  font-size: 9px;
  font-weight: 600;
  padding: 1px 5px;
  border-radius: 8px;
  background: var(--bg-light);
  color: var(--text-muted);
  letter-spacing: 0;
  min-width: 18px;
}

.filter-btn.active .filter-count {
  background: rgba(255, 255, 255, 0.22);
  color: var(--white);
}

.filter-empty-hint {
  padding: 14px 16px;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.5;
}

.filter-empty-switch {
  display: inline;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
}

.filter-empty-switch:hover {
  color: var(--text-primary);
}

.node-filter-btn {
  flex: 0 0 auto;
  padding: 5px 8px;
  gap: 4px;
}

.node-filter-btn svg {
  display: block;
}

.node-filter-backdrop {
  position: fixed;
  inset: 0;
  z-index: 99;
}

.node-filter-popover {
  position: absolute;
  top: 100%;
  right: 16px;
  margin-top: 4px;
  z-index: 100;
  min-width: 200px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
  padding: 6px 0;
  font-family: var(--font-body);
  font-size: 12px;
}

.node-filter-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 12px 8px;
  border-bottom: 1px solid var(--border);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.node-filter-reset {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  text-transform: none;
  letter-spacing: 0;
  color: var(--accent);
  cursor: pointer;
}

.node-filter-reset:hover {
  text-decoration: underline;
}

/* Two quick actions in the popover header — "Alle an" / "Alle aus". */
.node-filter-actions {
  display: inline-flex;
  gap: 10px;
  flex-shrink: 0;
}

.node-filter-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  cursor: pointer;
  color: var(--text-primary);
}

.node-filter-row:hover {
  background: var(--bg-light);
}

.node-filter-row input[type='checkbox'] {
  margin: 0;
  cursor: pointer;
  accent-color: var(--accent);
}

.node-filter-name {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 12px;
}

.node-filter-count {
  font-size: 10px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Gruppierungsleiste — umbruchsicher (Alex 15.09., Bild 125182). Seit „Parent"
   (27.08.) und „Hierarchie" (29.08.) stehen sieben Zellen in der Leiste; bei 280 px
   Sidebar (247 px innen) brauchen sie 289 px. Flex-Kinder schrumpfen nicht unter
   ihren Inhalt: die letzte Zelle ragte über Leiste und Sidebar hinaus („ARCHIE"
   stand im Verlauf), Baum-Symbol und Wort brachen auseinander. Jetzt: die Zeile
   darf umbrechen, Symbol und Wort bleiben zusammen, und die Trennlinien sind 1-px-
   Lücken auf Rahmenfarbe statt border-right je Knopf — so stimmen sie in jeder
   Zeile, ohne Doppellinie am Rand. Drei Zellen (Server+Parent, Owner, Flat+
   Hierarchie) mit je 40 % Grundbreite legen fest, WO gebrochen wird: mit Server-
   Zelle (120 %) bricht die Sichten-Zelle als Ganzes in Zeile 2 — nie „Hierarchie"
   allein —, ohne Server-Zelle (Kundeninstanz, 80 %) reicht eine Zeile. Gemessen
   bei 280/340/390 px (Chrome headless, Vorlage aus dieser CSS). */
.sort-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  margin-top: 8px;
  border: 1px solid var(--border);
  background: var(--border);
}

.sort-btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 4px 6px;
  border: none;
  border-radius: 0;
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s ease;
}
.sort-btn:hover {
  color: var(--text-primary);
}

.sort-btn.active {
  background: var(--chip-active-bg);
  color: var(--white);
}

.sort-separator {
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 0 2px;
}

/* Per-dimension grouping cell: the group tab + its own filter funnel
   (Alex 2026-06-22). One cell for Server, one for Owner; Flat has none. */
.group-cell {
  flex: 1 1 40%;
  display: flex;
  align-items: stretch;
  gap: 1px;
}
/* Innerhalb einer Zelle teilen sich die Knöpfe den Platz gleich (Flat = Hierarchie). */
.group-cell > .sort-btn { flex-basis: 0; }
.group-filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 4px 7px;
  border: none;
  border-radius: 0;
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
}
.group-filter-btn:hover { color: var(--text-primary); }
.group-filter-btn.active { color: var(--accent); }
.group-filter-btn .filter-count {
  font-family: var(--font-mono);
  font-size: 9px;
  margin-left: 1px;
}

/* ── Session List ─────────────────────────────────────────────── */
.session-list {
  flex: 1;
  overflow-y: auto;
  padding: 0;
  /* Scrolls beneath the glass header — measured height as top padding. */
  padding-top: var(--sb-hdr-h, 170px);
}

/* Hidden-node notice (Alex 2026-07-22) — named + one-click restore so a muted
   node is never a silent "it disappeared" again. Warm tint, flat/square. */
.hidden-nodes-note {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  margin: 0 0 4px;
  font-size: 12px;
  color: var(--text-primary);
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  border-bottom: 1px solid var(--border);
}
.hidden-nodes-icon { color: var(--text-muted); flex-shrink: 0; }
.hidden-nodes-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hidden-nodes-show {
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 12px;
  border: 1px solid var(--text-primary);
  border-radius: 0;
  background: transparent;
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.hidden-nodes-show:hover { background: var(--text-primary); color: var(--surface); }

.server-group {
  border-bottom: 1px solid var(--border);
}

.server-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--text-muted);
  padding: 16px 16px 8px;
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: color 0.15s ease;
}

.server-label:hover {
  color: var(--text-primary);
}

.server-name {
  flex: 1;
}

.server-chevron {
  display: inline-flex;
  align-items: center;
  transition: transform 0.15s ease;
  color: var(--text-muted);
}

.server-chevron.expanded {
  transform: rotate(90deg);
}

.server-count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  letter-spacing: 0;
  text-transform: none;
}

.session-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  cursor: pointer;
  transition: background-color 0.15s ease;
  border-left: 2px solid transparent;
}

.session-item:hover {
  background: var(--bg-light);
}

.session-item:active {
  background: var(--bg-inset, #EFEFEF);
}

.session-item.active {
  background: var(--bg-light);
  border-left-color: var(--accent);
}

.session-node {
  font-size: 9px;
  color: var(--border-strong);
}

.session-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* State semantics (2026-05-19, Alex's feedback):
 * - ready  / idle      → ALIVE in memory, waiting for input. Same color.
 * - thinking / tool    → ALIVE in memory, actively working. Yellow pulse.
 * - needs_login / err  → ALIVE but blocked. Red.
 * - suspended          → NOT in memory, on disk, wake on demand. Half-grey.
 * - dead               → NOT in memory, registry orphan. Solid grey.
 * - unknown            → detection still pending. Grey pulse.
 *
 * The previous CSS lumped `idle` together with `dead` + `suspended` —
 * all rendered solid grey — which made an active waiting CLI visually
 * indistinguishable from a process that wasn't running at all. Alex's
 * "warum ist der idle obwohl ich ihn benutzt habe" landed exactly there:
 * idle is the most-alive non-thinking state, not absence. Now idle gets
 * the same green dot as ready (= "live, ready for input").
 */
.status-dot.ready,
.status-dot.idle { background: var(--color-success); }
.status-dot.thinking,
.status-dot.tool { background: var(--accent); animation: pulse 1.5s infinite; }
.status-dot.error,
.status-dot.auth_required,
.status-dot.rate_limited,
.status-dot.needs_login { background: var(--color-error); }
/* Interrupted (#Cloud ea7b710): agent stopped mid-turn, awaiting a decision.
   Solid amber, NO pulse — pulse is reserved for ACTIVE work; interrupted is
   stopped-and-needs-attention. Global rule → covers sidebar + AgentDetail. */
.status-dot.interrupted { background: var(--color-warning); }
/* Kontingent: Warten, keine Störung (#1199/#1206). Bernstein wie „unterbrochen"
   — sichtbar, dass hier gerade nichts geht, aber ohne Alarm-Rot. Rot bleibt
   dem vorbehalten, wo jemand eingreifen MUSS; ein Kontingent läuft von selbst
   wieder auf. Kein Puls: Es arbeitet nichts, es wartet. */
.status-dot.quota_exhausted { background: var(--color-warning); opacity: 0.85; }
.status-dot.suspended { background: var(--border-strong); opacity: 0.5; }
.status-dot.dead { background: var(--border-strong); }
.status-dot.unknown { background: var(--border-strong); animation: pulse 2s infinite; }
/* New runtime/lifecycle semantics (Alex 2026-06-12, via Cloud IACP 628645e1):
 * activity_class is no longer wired to the dot color because it confused
 * users — bots ready in memory looked "cold/grey", and an active operator
 * editing tmux directly stayed grey because no activity-stamp was set.
 * Now driven by lifecycle status + runtime state:
 *
 *   working    state ∈ thinking/tool        → orange + pulse
 *   available  status running/idle + ready  → green
 *   offline    status suspended/dead/orphan → grey
 *   error/needs_login (red) — overrides everything
 */
.status-dot.working {
  /* Active/working point follows the accent (Alex 2026-06-22). */
  background: var(--accent);
  animation: pulse 1.5s infinite;
}
.status-dot.available {
  background: var(--color-success);
}
.status-dot.offline {
  background: var(--border-strong);
  opacity: 0.55;
}
/* Permission-blocked — the agent is halted waiting for the user's
 * allow/deny (Cloud sets state='waiting', IACP 276a605e). A gentle blue
 * pulse: distinct from working-orange (it is NOT working) and from
 * green-available (it is blocked, not free) — "wartet auf dich". */
.status-dot.waiting {
  background: var(--color-info, #3b82f6);
  animation: pulse 1.5s infinite;
}

/* Legacy activity_class buckets — kept defined in case other surfaces
 * still depend on them (e.g. health dashboards) but no longer the
 * default mapping in SessionList.tsx / AgentDetail.tsx. */
.status-dot.active { background: var(--color-success); }
.status-dot.warm   { background: #eab308; }
.status-dot.stale  { background: var(--border-strong); }
.status-dot.cold   { background: var(--border-strong); opacity: 0.55; }

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

.session-info {
  flex: 1;
  min-width: 0;
}

.mcp-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 9px;
  font-weight: 600;
  vertical-align: middle;
  padding: 1px 5px;
  border-radius: 3px;
}
.mcp-badge.bad {
  color: var(--color-error);
  background: var(--color-error-bg);
}
.mcp-badge.warn {
  color: var(--color-warning);
  background: var(--color-warning-bg);
}

.needs-login-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--white);
  background: var(--color-error);
  vertical-align: middle;
  animation: pulse 2s infinite;
}

/* Lifecycle (#37): grayed-out items for paused agents. Sub-second
   wake on click via /api/sessions/{name}/wake. */
.session-item.is-paused {
  opacity: 0.55;
}

.session-item.is-paused:hover {
  opacity: 0.85;
}

.session-item.lifecycle-orphan {
  /* never-spawned bot-home — slightly more muted than user-paused */
  opacity: 0.4;
}

.session-item.lifecycle-orphan:hover {
  opacity: 0.75;
}

.session-item.lifecycle-dead .status-dot,
.session-item.lifecycle-recovering .status-dot {
  background: var(--color-error, #d22) !important;
}

.lifecycle-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border: 1px solid var(--border);
  background: var(--bg-light);
  color: var(--text-muted);
  vertical-align: middle;
}

/* Declared lane-status pill (#1251) — semantic states beyond the live dot. */
.lane-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border: 1px solid currentColor;
  background: transparent;
  vertical-align: middle;
}
.lane-badge-blocked { color: var(--color-error); background: var(--color-error-bg); }
.lane-badge-error { color: var(--color-error); background: var(--color-error-bg); font-weight: 700; }
.lane-badge-waiting { color: var(--color-info); }
.lane-badge-done    { color: var(--color-success); }
/* Open-issues count (#180) — a blue circle/pill with the number, so you see at a glance
   which agents have unprocessed issues waiting. */
.sl-issue-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  margin-left: 6px;
  border-radius: 8px;
  background: var(--color-info);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  flex-shrink: 0;
  vertical-align: middle;
}

.lifecycle-badge-idle {
  color: var(--color-info, #2a7);
  border-color: var(--color-info, #2a7);
}

.lifecycle-badge-suspended {
  color: var(--text-muted);
}

.lifecycle-badge-orphan {
  color: var(--text-muted);
  font-style: italic;
}

.lifecycle-badge-recovering {
  color: var(--color-warning, #c80);
  border-color: var(--color-warning, #c80);
  animation: pulse 2s infinite;
}

.lifecycle-badge-dead {
  color: var(--color-error, #d22);
  border-color: var(--color-error, #d22);
}

.auto-heal-badge,
.heartbeat-badge {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
  vertical-align: middle;
  color: var(--text-muted);
  cursor: help;
}

.auto-heal-badge {
  color: var(--color-success);
}

.heartbeat-badge svg {
  opacity: 0.7;
}

.session-name {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.session-role {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Knoten und Zustandswort in EINER Zeile — sonst waechst jede Zeile um zwei
   Zeilen statt um eine (Alex liest die Liste am Telefon). */
.session-zustandzeile {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}
.session-zustandzeile .session-role::after {
  content: '·';
  margin-left: 6px;
  opacity: 0.5;
}
.session-zustandzeile .session-role:last-child::after { content: none; }

/* Das Zustandswort (Alex 17.09.): „die zwei arbeiten, die anderen drei sind
   fertig und warten" — er hat den Zustand aus Punktfarben abgelesen, weil er
   nirgends geschrieben stand. „fertig" bleibt gedaempft: der Normalfall soll
   nicht schreien, die Ausnahmen sollen auffallen. */
.session-zustand {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
}
.session-zustand.zustand-arbeitet { color: var(--accent); }
.session-zustand.zustand-braucht { color: var(--color-warning, #c80); font-weight: 500; }
.session-zustand.zustand-fehler { color: var(--color-error, #d22); }
.session-zustand.zustand-neustart { color: var(--color-warning, #c80); }

/* WORAN — deine letzte Anweisung, sonst der aktive Strang. Eine Zeile, gekappt;
   der volle Text steht im Tooltip. */
.session-woran {
  font-size: 11px;
  line-height: 1.35;
  color: var(--text-secondary, var(--text-muted));
  /* ZWEI Zeilen, nicht eine: in der schmalen Leiste (und erst recht in der
     zweispaltigen Liste am Telefon) brach eine einzelne Zeile nach ~25 Zeichen
     ab — „Die Buttons links…" sagt nichts. Zwei Zeilen tragen den Satz. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
  margin-top: 1px;
  min-width: 0;
}
/* Eine offene Rückfrage ist kein Bericht, sondern eine Bitte — sie darf auffallen. */
.session-woran-frage { color: var(--color-warning, #c80); }
.session-woran-alter {
  color: var(--text-muted);
  opacity: 0.8;
}

/* Live now/next ticker under a working agent. activity in the warning
   accent (it IS the orange-working state, made concrete), next dimmed. */
.session-live {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 2px;
  min-width: 0;
}
.session-live-act {
  font-size: 11px;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.session-live-elapsed {
  font-family: var(--font-mono);
  opacity: 0.75;
}
.session-live-next {
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0.85;
}

.session-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  text-align: right;
  flex-shrink: 0;
  line-height: 1.4;
}

/* ── Pool Section ─────────────────────────────────────────────── */
.pool-section {
  padding: 16px;
  border-top: 1px solid var(--border);
}

.pool-header {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--text-muted);
  margin-bottom: 12px;
}

.pool-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}

.pool-row:last-child {
  border-bottom: none;
}

.pool-name {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
}

.pool-dots {
  display: flex;
  gap: 4px;
  align-items: center;
}

.pool-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.pool-dot:hover {
  transform: scale(1.4);
  box-shadow: 0 0 0 2px var(--white), 0 0 0 3px var(--border-strong);
}

.pool-dot.active { background: var(--color-success); }
.pool-dot.standby { background: var(--border-strong); }
.pool-dot.acquired { background: var(--color-warning); }

.pool-count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  margin-left: 6px;
}

/* ── Sidebar Footer ───────────────────────────────────────────── */
.sidebar-footer {
  padding: 12px 16px;
  padding-bottom: 12px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.connection-status {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--text-muted);
}

.connection-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-success);
}

.connection-dot.error {
  background: var(--color-error);
}
/* SSE bus is live and pushing realtime updates. Same green as the
   default but kept explicit so future palette tweaks can differentiate. */
.connection-dot.live {
  background: var(--color-success);
}
/* SSE bus is mid-reconnect — polling-fallback is doing the heavy
   lifting in the meantime. Amber pulse signals "degraded but still
   updating". */
.connection-dot.reconnecting {
  background: var(--color-warning);
  animation: pulse 1.5s infinite;
}
/* SSE never connected (or repeatedly failed) — we're on pure polling.
   Solid amber to distinguish from the reconnecting pulse. */
.connection-dot.degraded {
  background: var(--color-warning);
}

/* ── Sidebar Nav ──────────────────────────────────────────────── */
.sidebar-nav {
  display: flex;
  border-top: 1px solid var(--border);
  position: relative;
}

.sidebar-nav-btn {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px 0;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  background: none;
  border: none;
  border-right: 1px solid var(--border);
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.sidebar-nav-btn:last-child {
  border-right: none;
}

.sidebar-nav-btn:hover {
  color: var(--text-primary);
  background: var(--bg-light);
}

.sidebar-nav-btn.active {
  color: var(--text-primary);
  background: var(--bg-light);
}

.sidebar-nav-primary {
  color: var(--accent);
  font-weight: 600;
}

/* ── Nav Drop-up Menu ────────────────────────────────────────── */
.nav-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: transparent;
}

/* Solange das Menue offen ist, weicht der untere Stapel (Auslastung, Kontingent,
   Avatar, Statuszeile). Alex 15.09., nach dem Panel-Fix: bei grosser
   Auslastungsanzeige blieb fuer das Menue kein Platz mehr — es schrumpfte auf
   null, und weil der Schalter „Usage" IM Menue sitzt, kam man nicht mehr an ihn
   heran. Die Zahlen sind Beiwerk, das Menue ist der Weg: es ist modal (eigener
   Hintergrund, Klick schliesst) und muss immer ganz sichtbar sein. Beim
   Schliessen kommt alles unveraendert zurueck. */
.sidebar.menue-offen .ctx-status,
.sidebar.menue-offen .usage-widget,
.sidebar.menue-offen .usage-meter,
.sidebar.menue-offen .arc-panel,
.sidebar.menue-offen .arc-panel-slim,
.sidebar.menue-offen .arc-controls {
  display: none;
}

.nav-menu-panel {
  position: relative;
  z-index: 60;
  background: var(--surface);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  /* Das Panel gibt nach, nicht die Leiste darunter (Alex 15.09., Bild 125251):
     mit `flex-shrink: 0` schob das Kachelraster auf dem Telefon die untere
     Leiste samt „Menü"-Knopf unter die Bildkante — kein Weg zurück ohne
     Neuladen. Jetzt schrumpft das Panel auf den Platz, der über der Leiste
     bleibt, und rollt innen; die Leiste steht immer im Bild. */
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.04);
}

.nav-menu-item {
  padding: 14px 16px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-primary);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  text-align: left;
  transition: background-color 0.15s ease;
}

.nav-menu-item:last-child {
  border-bottom: none;
}

.nav-menu-item:hover {
  background: var(--bg-light);
}

.nav-menu-item:active {
  background: var(--chip-active-bg);
  color: var(--white);
}

/* Icon-tile grid for the nav menu (Alex 2026-06-28: the plain text list was dull).
   Square tiles, thin divider lines via the grid gap, accent fill on hover. Responsive
   auto-fill so it works full-width on mobile and in the narrow desktop popup. */
.nav-menu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: 1px;
  background: var(--border);
  padding: 1px;
}
.nav-menu-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  aspect-ratio: 1 / 1;
  padding: 10px 6px;
  background: var(--surface);
  color: var(--text-primary);
  border: none;
  cursor: pointer;
  font-family: var(--font-body);
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-menu-tile span {
  font-size: 10px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: center;
  line-height: 1.2;
}
.nav-menu-tile:hover { background: var(--accent); color: var(--white); }
.nav-menu-tile:active { background: var(--accent-hover); color: var(--white); }
/* A toggle tile that's currently ON (e.g. Pools shown) stays accent-filled. */
.nav-menu-tile.active { background: var(--accent); color: var(--white); }

.sidebar-nav-btn:hover {
  color: var(--text-primary);
  background: var(--bg-light);
}

.sidebar-action {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  background: none;
  border: none;
  cursor: pointer;
  transition: color 0.15s ease;
}

.sidebar-action:hover {
  color: var(--text-primary);
}

/* ── Context Menu ─────────────────────────────────────────────── */
.ctx-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9998;
}

.ctx-menu {
  position: fixed;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  border: 1px solid var(--border);
  min-width: 150px;
  z-index: 9999;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.ctx-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 14px;
  background: transparent;
  border: none;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}

.ctx-item svg {
  color: var(--text-muted);
  flex-shrink: 0;
  transition: color 0.15s ease;
}

.ctx-item:hover {
  background: var(--bg-light);
}

.ctx-item:hover svg {
  color: var(--text-primary);
}

.ctx-item:active {
  background: var(--chip-active-bg);
  color: var(--white) !important;
  transform: scale(0.98);
}

.ctx-item:active svg {
  color: var(--white) !important;
}

/* Destructive actions (Kill) keep monochrome by default but hover-tint
 * red so the irreversible step has a visual nudge. No always-on red. */
.ctx-item.ctx-destructive:hover {
  color: var(--color-error);
}

.ctx-item.ctx-destructive:hover svg {
  color: var(--color-error);
}

.ctx-footer {
  padding: 6px 14px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
}

.ctx-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

/* ── MCP Panel ───────────────────────────────────────────────── */
.mcp-panel {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-light);
}

.mcp-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.mcp-panel-title {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-primary);
}

.mcp-panel-actions {
  display: flex;
  gap: 6px;
}

.mcp-panel-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
}

.mcp-panel-item {
  display: flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
}

.mcp-panel-item input[type="checkbox"] {
  width: 13px;
  height: 13px;
  accent-color: var(--text-primary);
  cursor: pointer;
}

.mcp-panel-name {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-primary);
}

/* ── Status Toast ────────────────────────────────────────────── */
.ctx-status {
  padding: 6px 16px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
  text-align: center;
}

/* ── Mobile ───────────────────────────────────────────────────── */
/* ── Collapsed rail mode (desktop only) ──────────────────────────
 * Sidebar shrinks to an avatar/dot strip so the conversation gets the
 * space and focus stays on the agent (Alex 2026-06-19). Desktop-scoped
 * so it never fights the mobile full-width sidebar. Agents stay clickable
 * as avatars; the name shows on hover (native title). */
@media (min-width: 769px) and (min-height: 501px) {
  .sidebar.collapsed {
    width: var(--sidebar-rail-width, 66px);
  }
  /* Hide all the text-heavy chrome. */
  .sidebar.collapsed .sidebar-logo,
  .sidebar.collapsed .sidebar-theme-btn,
  .sidebar.collapsed .sidebar-debug-btn,
  .sidebar.collapsed .search-wrapper,
  .sidebar.collapsed .filter-row,
  .sidebar.collapsed .sort-row,
  .sidebar.collapsed .sicht-leiste,
  .sidebar.collapsed .server-label,
  .sidebar.collapsed .filter-empty-hint,
  .sidebar.collapsed .ctx-status,
  .sidebar.collapsed .session-info,
  .sidebar.collapsed .session-meta,
  .sidebar.collapsed .pool-section,
  .sidebar.collapsed .sidebar-nav-label {
    display: none;
  }
  /* Header: just the expand toggle, centered. */
  .sidebar.collapsed .sidebar-header {
    padding: 12px 0;
    padding-top: calc(env(safe-area-inset-top, 0px) + 10px);
  }
  .sidebar.collapsed .sidebar-logo-row {
    margin-bottom: 0;
    justify-content: center;
  }
  /* Session rows → centered avatar with the status dot as a corner badge. */
  .sidebar.collapsed .session-item {
    justify-content: center;
    gap: 0;
    padding: 7px 0;
    position: relative;
  }
  .sidebar.collapsed .session-avatar {
    width: 34px;
    height: 34px;
  }
  .sidebar.collapsed .session-avatar-initial {
    display: flex;
  }
  .sidebar.collapsed .status-dot {
    position: absolute;
    top: 6px;
    right: 13px;
    width: 9px;
    height: 9px;
    border: 2px solid var(--white);
    box-sizing: content-box;
    z-index: 1;
  }
  /* Nav → icon-only, stacked vertically. */
  .sidebar.collapsed .sidebar-nav {
    flex-direction: column;
  }
  .sidebar.collapsed .sidebar-nav-btn {
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  /* Nav drop-up: in the rail the in-flow panel was squeezed into 66px and
   * its labels spilled out over the content (Alex 2026-06-19, asset
   * 111473). Float it as a fixed flyout just right of the rail with its
   * own width so the items read cleanly. */
  .sidebar.collapsed .nav-menu-panel {
    position: fixed;
    left: calc(var(--sidebar-rail-width, 66px) + 6px);
    bottom: 16px;
    width: 210px;
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.14);
    z-index: 60;
  }
}

@media (max-width: 768px), (max-height: 500px) {
  .sidebar {
    width: 100%;
    position: fixed;
    z-index: 50;
    left: 0;
    top: 0;
  }

  /* The rail toggle is a desktop affordance — on mobile the sidebar is a
   * full-screen overlay with its own back flow, so hide it. */
  .sidebar-collapse-btn {
    display: none;
  }

  .session-item {
    padding: 12px 16px;
  }

  /* Two-column agent list on mobile (Alex 2026-06-22) — at ~150 agents the
     single full-width column was endless scroll. Desktop/rail stay 1-col
     (this rule is mobile-only). */
  .session-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  .session-grid .session-item {
    padding: 11px 12px;
    gap: 8px;
    min-width: 0;
  }
  /* Column divider so the two columns read as a grid, not a jumble. */
  .session-grid .session-item:nth-child(odd) {
    border-right: 1px solid var(--border);
  }
  /* The time chip eats width in a half-cell — shrink + cap it so the name
     keeps room to truncate cleanly. */
  .session-grid .session-meta {
    font-size: 9px;
    max-width: 42px;
  }

  .sidebar-footer {
    /* Old Chrome (no dvh) needs a thick fallback to clear the bottom
       browser UI. Modern browsers override below to a tighter pad. */
    padding-bottom: 40px;
  }

  .filter-row {
    overflow-x: auto;
    flex-wrap: nowrap;
    padding-bottom: 4px;
  }
}

/* Modern browsers (dvh-aware) use viewport-precise sizing and only
   need the safe-area pad for the home-indicator. */
/* Modern browsers: --vh (visualViewport) on the body already excludes
   Safari's bottom UI + home-indicator. Tiny breathing pad is enough. */
@supports (height: 100dvh) {
  @media (max-width: 768px), (max-height: 500px) {
    .sidebar-footer {
      padding-bottom: 8px;
    }
  }
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ctx-menu { background: var(--surface); }
}

/* Gesperrter Lifecycle-Eintrag (Neustart läuft bereits). Sichtbar deaktiviert
   statt still wirkungslos. */
.ctx-item-locked {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Neustart: eigener Punkt, blau-pulsierend. Bewusst nicht rot (es ist kein
   Fehler) und nicht grau (der Agent ist nicht offline, er kommt gerade hoch). */
.status-dot.restarting {
  background: var(--accent, #3b82f6);
  animation: restart-pulse 1.1s ease-in-out infinite;
}

@keyframes restart-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
  .status-dot.restarting { animation: none; }
}

/* Neustart-Pille in der Agentenzeile. Ruhig gehalten: es ist ein Vorgang,
   keine Störung. */
.restart-badge {
  flex: none;
  font-family: var(--font-mono);
  font-size: 8px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 1px 4px;
  color: var(--accent, #3b82f6);
  border: 1px solid currentColor;
}

/* Aktive Umschalt-Kachel im Menü (Avatar an). Hebt sich ab, ohne wie ein
   Fehler auszusehen. */
.nav-menu-tile-on {
  color: var(--accent, #3b82f6);
  border-color: currentColor;
}

/* Vermuteter Zustand (Cloud 089feee): Der Dienst hat nicht gemessen, sondern
   geschlossen („seit 5 min keine Bewegung → idle"). Hohl statt gefüllt — die
   Farbe bleibt, die Gewissheit nicht. Eine Vermutung, die aussieht wie eine
   Messung, ist der Fehler, der bei #1206 zwei Stunden gekostet hat. */
.status-dot.inferred {
  background: transparent !important;
  box-shadow: inset 0 0 0 2px currentColor;
  opacity: 0.75;
}
.status-dot.available.inferred { color: var(--color-success); }
.status-dot.working.inferred   { color: var(--accent); }
.status-dot.offline.inferred,
.status-dot.unknown.inferred   { color: var(--border-strong); }

/* Lage-Zeile unter den Sprach-Kacheln. Ueber die ganze Rasterbreite, weil sie
   ein Satz ist und keine Kachel — und weil sie drei Zustaende unterscheidet,
   die vorher alle „bereit" hiessen. */
.nav-menu-note {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 8px;
  padding: 2px 4px 6px;
  font-size: 11px; color: var(--text-muted);
}
.nav-menu-note-btn {
  margin-left: auto;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.06em;
  text-transform: uppercase; padding: 3px 8px;
  background: transparent; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 0; cursor: pointer;
}
.nav-menu-note-btn:hover { color: var(--text-primary); border-color: var(--text-muted); }

/* MCP-Panel: die wirkliche Lage statt einer eigenen Liste (26.08.). */
.mcp-panel-hinweis {
  padding: 6px 10px;
  margin: 0 0 6px;
  border-left: 2px solid var(--border);
  background: var(--hover-bg);
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.45;
}
.mcp-panel-hinweis-warn { border-left-color: var(--warn, #d08a3a); }
.mcp-panel-zugriff {
  margin-left: auto;
  padding: 1px 6px;
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.mcp-panel-zugriff.is-full { color: var(--success, #4a9); border-color: currentColor; }
.mcp-panel-zugriff.is-partial { color: var(--warn, #d08a3a); border-color: currentColor; }
/* „kein Recht" bleibt gedaempft — es ist kein Fehler, sondern eine Aussage. */
.mcp-panel-item.is-ohne-recht .mcp-panel-name { opacity: 0.6; }

/* Eltern-Kind-Gruppen. Die ungültige Gruppe wird ausdrücklich markiert —
   ein verwaistes Kind stumm flach zu listen sähe aus wie „hatte nie einen
   Elternteil", und die verlorene Beziehung wäre unsichtbar. */
.parent-group.is-ungueltig .server-label { color: var(--color-warning); }

.parent-verwaist { display: flex; flex-direction: column; gap: 2px; }

.parent-verwaist-hinweis {
  font-size: 11px;
  line-height: 1.3;
  color: var(--color-warning);
}

/* Präsenz-Marke (Variante A): die Präsenz-Session hängt am Großhirn statt
   als eigener Agent in der Liste zu stehen. */
.session-praesenz {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 6px;
  padding: 0 5px;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  vertical-align: middle;
  cursor: pointer;
}

.session-praesenz:hover {
  color: var(--text-primary);
  border-style: solid;
}
/* Präsenzsicht: schriftliche Geschichte der Sprachgespräche (Post 4909, 02.09.). */
.praesenz-verlauf {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow-y: auto;
  padding: calc(var(--agent-hdr-h, 72px) + 16px) 22px calc(var(--agent-ftr-h, 76px) + 24px);
  color: var(--text-primary);
  background: var(--surface);
}

.praesenz-verlauf-kopf {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 14px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}

.praesenz-verlauf-leer,
.praesenz-verlauf-fehler {
  max-width: 60ch;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-secondary);
}

.praesenz-verlauf-fehler { color: var(--color-warning); }

.praesenz-verlauf-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.praesenz-tag {
  margin: 10px 0 4px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent);
}

.praesenz-zeile {
  padding: 10px 14px;
  border-left: 2px solid var(--border);
  background: var(--bg-light);
}

.praesenz-zeile.richtung-inbound {
  border-left-color: var(--text-primary);
  background: color-mix(in srgb, var(--text-primary) 7%, transparent);
}

.praesenz-zeile-kopf {
  display: flex;
  gap: 8px;
  align-items: baseline;
  margin-bottom: 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.praesenz-sprecher {
  font-weight: 700;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.praesenz-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  white-space: pre-wrap;
}
/* HAUPTBALKEN — eine Linie, Abschnitte = Arbeitsabschnitte (Vision #4973, Alex 13.09.;
 * verdichtet nach Alex' Rückmeldung über ChatGPT 13.09.). Flach, eckig, Mono-Versalien
 * nur für das eine Statuswort und kleine Meta. Der Balken selbst ist die 2-px-Linie
 * über jedem Abschnitt: grau = erledigt, voll = offen, gestrichelt = verdrängt oder
 * unbekannt; der Punkt markiert den Anfang, Akzent = braucht dich. Am Telefon
 * scrollt die Leiste seitlich, die Seite nie. */
.hb-leiste { display: flex; gap: 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; padding-bottom: 4px; max-width: 100%; }
.hb-station, .hb-frueher { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; background: transparent; border: 0; border-radius: 0; padding: 0 12px 6px 0; margin: 0; color: var(--text-primary); text-align: left; cursor: pointer; font: inherit; }
.hb-station { width: clamp(160px, 27vw, 230px); }
.hb-frueher { width: auto; min-width: 84px; color: var(--text-secondary); }
.hb-frueher-text { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; text-decoration: underline; text-underline-offset: 3px; }
.hb-frueher .hb-linie::before { background: repeating-linear-gradient(90deg, var(--border-strong) 0 4px, transparent 4px 8px); }
.hb-station:focus-visible, .hb-frueher:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }
.hb-linie { position: relative; display: block; width: 100%; height: 12px; }
.hb-linie::before { content: ''; position: absolute; left: 0; right: 0; top: 5px; height: 2px; background: var(--border-strong); }
.hb-station.is-aktiv .hb-linie::before, .hb-station.is-wartet .hb-linie::before { background: var(--text-primary); }
.hb-station.is-verdraengt .hb-linie::before, .hb-station.is-unbekannt .hb-linie::before { background: repeating-linear-gradient(90deg, var(--border-strong) 0 6px, transparent 6px 10px); }
.hb-punkt { position: absolute; left: 0; top: 0; width: 12px; height: 12px; box-sizing: border-box; background: var(--surface); border: 2px solid var(--border-strong); }
.hb-station.is-aktiv .hb-punkt, .hb-station.is-wartet .hb-punkt { border-color: var(--text-primary); }
.hb-station.is-erledigt .hb-punkt { background: var(--border-strong); }
.hb-station.is-gewaehlt .hb-punkt { background: var(--text-primary); border-color: var(--text-primary); }
.hb-station.is-braucht .hb-punkt { background: var(--accent); border-color: var(--accent); }
.hb-titel { font-size: 14px; font-weight: 600; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.hb-station.is-erledigt .hb-titel { color: var(--text-secondary); font-weight: 500; }
.hb-station.is-verdraengt .hb-titel, .hb-station.is-unbekannt .hb-titel { color: var(--text-secondary); font-weight: 500; font-style: italic; }
.hb-station.is-gewaehlt .hb-titel { text-decoration: underline; text-underline-offset: 3px; }
/* Thema plus ein Satz: das Ergebnis oder das Hindernis, kein abstraktes „offen". */
.hb-satz { font-size: 12px; line-height: 1.35; color: var(--text-secondary); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* Das eine Statussignal: ein Wort vor dem Satz, nur bei Offenem. */
.hb-status { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-primary); }
.hb-station.is-braucht .hb-status { color: var(--accent); }
.hb-quelle { font-weight: 400; text-transform: none; letter-spacing: 0; }
.hb-detail { margin-top: 2px; }
.hb-bitte { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.4; }
.hb-stand { margin: 0; font-size: 13px; line-height: 1.45; }
.hb-naechstes { margin: 0; font-size: 13px; line-height: 1.45; }
.hb-wort { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); margin-right: 4px; }
/* Schritte, Marker und Belege: zugeklappt, damit der Stand der Hauptinhalt bleibt. */
.hb-mehr { display: flex; flex-direction: column; gap: 6px; }
.hb-mehr > summary { cursor: pointer; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); list-style: none; }
.hb-mehr > summary::-webkit-details-marker { display: none; }
.hb-mehr > summary::before { content: '▸ '; }
.hb-mehr[open] > summary::before { content: '▾ '; }
.hb-schritte { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; font-size: 13px; line-height: 1.4; }
.hb-schritte li.is-erledigt { color: var(--text-secondary); }
.hb-schritt-titel { font-weight: 600; }
.hb-schritt-stand { color: var(--text-secondary); }
.hb-marker { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; font-size: 13px; line-height: 1.4; color: var(--text-secondary); }
.hb-marker-art { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); background: transparent; border: 0; padding: 0; margin: 0; }
button.hb-marker-art { text-decoration: underline; cursor: pointer; }
@media (max-width: 480px) {
  .hb-station { width: clamp(150px, 62vw, 220px); }
}
/* Realtime pre-start dialog — flat/square, matches NewSessionDialog/Settings + the
   accent (NOT the orange reset/warning button). Style guide: radius 0, dialog-btn
   colours (--accent primary, outline secondary), mono-uppercase labels. */
.vsd-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 16px;
}
.vsd-modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0;
  width: 100%;
  max-width: 420px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
}
.vsd-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}
.vsd-header h2 {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 8px;
}
.vsd-close {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  display: inline-flex;
  padding: 2px;
}
.vsd-close:hover { color: var(--text-primary); }
.vsd-body {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.vsd-label {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.vsd-select {
  background: var(--surface);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 8px 10px;
  font-size: 13px;
  font-family: var(--font-body);
  text-transform: none;
  letter-spacing: 0;
  cursor: pointer;
}
.vsd-select:focus { outline: none; border-color: var(--text-primary); }
.vsd-audio-scan {
  align-self: flex-start;
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  text-transform: none;
  letter-spacing: 0;
  cursor: pointer;
}
.vsd-audio-scan:hover:not(:disabled) { color: var(--text-primary); border-color: var(--text-primary); }
.vsd-audio-scan:disabled { opacity: 0.55; cursor: wait; }
.vsd-check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-primary);
  cursor: pointer;
}
.vsd-check input {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  accent-color: var(--accent);
}
.vsd-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 18px;
  border-top: 1px solid var(--border);
}
.vsd-cancel {
  padding: 8px 20px;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: 1px solid var(--border);
  border-radius: 0;
  cursor: pointer;
  transition: border-color 0.15s ease;
}
.vsd-cancel:hover { border-color: var(--text-primary); }
.vsd-start {
  padding: 8px 20px;
  background: var(--accent);
  color: var(--white);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: none;
  border-radius: 0;
  cursor: pointer;
}
.vsd-start:hover { background: var(--accent-hover); }

/* Zurücknehmen-Dialog (#4926) — teilt Rahmen und Knöpfe mit dem Start-Dialog. */
.rewind-text { margin: 0 0 8px; font-size: 14px; line-height: 1.45; }
.rewind-hint { margin: 6px 0 0; font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); }
.rewind-warn { margin: 0 0 8px; font-size: 13px; color: var(--color-error, #b00020); }
.rewind-ok { margin: 0 0 8px; font-size: 14px; color: var(--color-success, #1a7f37); }
.rewind-modi { display: flex; gap: 6px; flex-wrap: wrap; }
.rewind-modus { border: 1px solid var(--text-primary); background: transparent; color: var(--text-primary); font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; padding: 6px 10px; cursor: pointer; border-radius: 0; }
.rewind-modus.active { background: var(--text-primary); color: var(--surface); }
.rewind-pane summary { font-family: var(--font-mono); font-size: 11px; cursor: pointer; }
.rewind-pane pre { margin: 6px 0 0; padding: 8px; font-size: 11px; line-height: 1.4; background: var(--color-info-bg, rgba(127,127,127,0.12)); overflow-x: auto; max-height: 240px; }
.vsd-start:disabled { opacity: 0.45; cursor: not-allowed; }
.agent-issues {
  background: var(--surface);
  border: 1px solid var(--border);
  max-height: 55vh;
  overflow-y: auto;
}
.ai-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 1;
}
.ai-title { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-primary); }
.ai-count { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); flex: 1; }
.ai-x { background: none; border: none; color: var(--text-muted); cursor: pointer; display: inline-flex; padding: 2px; }
.ai-x:hover { color: var(--text-primary); }

.ai-flash { padding: 6px 12px; font-size: 12px; color: var(--color-success); background: var(--color-success-bg); }
.ai-empty { padding: 16px 12px; font-size: 13px; color: var(--text-muted); display: flex; align-items: center; gap: 8px; }
.ai-err { color: var(--color-error); }
.ai-spin { animation: ai-rot 1s linear infinite; }
@keyframes ai-rot { to { transform: rotate(360deg); } }

.ai-list { display: flex; flex-direction: column; }
.ai-issue { padding: 9px 12px; border-bottom: 1px solid var(--border); display: flex; flex-direction: column; gap: 7px; }
.ai-issue:last-child { border-bottom: none; }
/* Head row: title (left, grows) + status/actions cluster (top-right) — Issue #193.
   Keeps actions out of a separate row under the title to save vertical space. */
.ai-issue-head { display: flex; align-items: flex-start; gap: 10px; }
.ai-issue-main { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; flex: 1; min-width: 0; }
.ai-issue-right { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.ai-issue-id { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); flex-shrink: 0; }
.ai-issue-title { font-size: 13px; color: var(--text-primary); flex: 1; min-width: 0; }
.ai-tag { font-family: var(--font-mono); font-size: 9px; text-transform: uppercase; letter-spacing: 0.04em; padding: 0 5px; border: 1px solid currentColor; flex-shrink: 0; }
.ai-active { color: var(--accent); }
.ai-queued { color: var(--color-info); }
.ai-escal { color: var(--color-error); }
.ai-stages { display: inline-flex; gap: 2px; font-size: 11px; flex-shrink: 0; }
.ai-stage-done { color: var(--color-success); }
.ai-stage-in_progress { color: var(--accent); }
.ai-stage-pending { color: var(--border-strong); }
.ai-stage-skipped { color: var(--text-muted); }

.ai-actions { display: flex; gap: 6px; }
.ai-act {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-body);
  font-size: 11px;
  padding: 4px 8px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-primary);
  cursor: pointer;
  border-radius: 0;
}
.ai-act:hover { border-color: var(--text-primary); }
.ai-act:disabled { opacity: 0.5; cursor: default; }
/* Pink, but content-width (not full-row) so the row reads compactly — Issue #192. */
.ai-push { color: var(--accent); border-color: var(--accent); }
.ai-push:hover { background: var(--accent-bg); }
.ai-done:hover { color: var(--color-success); border-color: var(--color-success); }
.ai-drop:hover { color: var(--color-error); border-color: var(--color-error); }
/* Nudge a running issue — info-blue, distinct from the pink Pushen (Issue #195). */
.ai-remind { color: var(--color-info); border-color: var(--color-info); }
.ai-remind:hover { background: var(--color-info-bg, rgba(37, 99, 235, 0.12)); }

/* The exact prompt pushed to the agent, shown below the row so it's transparent
   what the agent receives on "Pushen" (Issue #192). Quoted/muted, mono. */
.ai-prompt {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-muted);
  line-height: 1.4;
  padding-left: 8px;
  border-left: 2px solid var(--border);
}

/* Drag-Sortierung der Warteschlange (Issue #943). Nur wartende Issues sind
   ziehbar — das aktive ist bereits zugeteilt und nicht mehr verhandelbar. */
.ai-issue.ai-sortable { cursor: grab; }
.ai-issue.ai-dragging { opacity: 0.45; cursor: grabbing; }
.ai-issue.ai-sortable:hover .ai-grip { color: var(--text-primary); }

.ai-grip {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: none;
  color: var(--text-muted);
  transition: color 120ms linear;
}

/* Die Positionsnummer ist der eigentliche Nutzen: sie sagt, das Wievielte
   dieses Issue in der Abarbeitung ist — die #ID sagt das nicht. */
.ai-pos {
  font-family: var(--font-mono);
  font-size: 9px;
  min-width: 10px;
  text-align: center;
}
/* History-tags panel — bookmark + rewind (Cloud 2026-06-23). Flat/square,
   sits below the agent header like the group-chat dropdown. */
.tagp {
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  padding: 8px 12px 10px;
  max-height: 42vh;
  overflow-y: auto;
}

.tagp-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.tagp-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}
.tagp-add {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--text-primary);
  background: var(--chip-active-bg);
  color: var(--white);
  font-size: 12px;
  cursor: pointer;
  border-radius: 0;
}
.tagp-add:hover { opacity: 0.88; }

.tagp-empty,
.tagp-empty-big {
  font-size: 12px;
  color: var(--text-muted);
  padding: 6px 2px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.tagp-empty-big { line-height: 1.5; }

.tagp-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border: 1px solid var(--border);
  background: var(--bg-light);
  margin-top: 6px;
}
.tagp-row.pinned {
  border-color: var(--accent);
  background: var(--accent-bg);
}
.tagp-row-main { flex: 1; min-width: 0; }
.tagp-row-name {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  color: var(--text-primary);
  font-weight: 500;
}
.tagp-pinbadge {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  border: 1px solid var(--accent);
  padding: 0 4px;
  margin-left: 2px;
}
.tagp-row-when {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 1px;
}
.tagp-row-actions { display: flex; gap: 4px; }
.tagp-resume,
.tagp-del {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 0;
}
.tagp-resume:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.tagp-del:hover:not(:disabled) { border-color: #dc2626; color: #dc2626; }
.tagp-resume:disabled,
.tagp-del:disabled { opacity: 0.4; cursor: default; }

.tagp-spin { animation: tagp-spin 0.9s linear infinite; }
@keyframes tagp-spin { to { transform: rotate(360deg); } }

/* Pin banner — shown at the top of the stream while the agent is rewound. */
.resume-pin-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 12px;
  margin: 0 0 8px;
  border: 1px solid var(--accent);
  background: var(--accent-bg);
  color: var(--accent);
  font-size: 12.5px;
}
.resume-pin-banner-main { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.resume-pin-banner-tag { font-weight: 600; }
.resume-pin-clear {
  flex-shrink: 0;
  height: 26px;
  padding: 0 10px;
  border: 1px solid var(--accent);
  background: var(--surface);
  color: var(--accent);
  font-size: 11.5px;
  cursor: pointer;
  border-radius: 0;
}
.resume-pin-clear:hover:not(:disabled) { background: var(--accent); color: var(--white); }
.resume-pin-clear:disabled { opacity: 0.5; cursor: default; }
.voice-recording-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: grid;
  place-items: center;
  padding: max(24px, env(safe-area-inset-top, 0px)) max(24px, env(safe-area-inset-right, 0px)) max(24px, env(safe-area-inset-bottom, 0px)) max(24px, env(safe-area-inset-left, 0px));
  background: color-mix(in srgb, var(--surface) 22%, transparent);
  -webkit-backdrop-filter: blur(5px) saturate(120%);
  backdrop-filter: blur(5px) saturate(120%);
}

.voice-recording-panel {
  width: min(100%, 980px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 18px;
  color: var(--text-primary);
}

/* Die Kopfgruppe erzeugt auf grossen Flächen bewusst keine eigene Box: Ziel
   und Verwerfen behalten dort ihre bisherige Position ober- bzw. unterhalb
   der Bühne. Erst die schmale Portrait-Regel macht daraus eine gemeinsame
   Zeile. */
.voice-recording-header { display: contents; }
.voice-recording-target { order: 0; }
.voice-recording-stage { order: 1; }
.voice-recording-cancel { order: 2; }

.voice-recording-stage {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(190px, 270px) auto minmax(190px, 270px);
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 5vw, 72px);
}

/* AM BREITEN SCHIRM BEKOMMT DAS BILD DEN PLATZ, DER OHNEHIN LEER IST.
   (Alex, 26.08.: „ich habe ja auf der linken Seite sehr viel Platz,
   eigentlich fast die ganze Page, weil der Hintergrund ist eh ausgeblendet
   mit Unschärfe … kannst du das Bild einfach viel größer darstellen, damit
   ich, wenn ich es beschreibe, es besser sehen kann?")

   Die Galerie war auf 270px gedeckelt — unabhängig von der Bildschirmbreite.
   Mit `object-fit: contain` schrumpft ein Querformat-Screenshot darin auf
   Briefmarkengröße, obwohl daneben ein halber Bildschirm ungenutzt liegt.

   Der Zweck der Ansicht bestimmt die Aufteilung: Man beschreibt hier ein
   Bild, während man spricht. Das Bild ist der Gegenstand, der Orb die
   Rückmeldung, die Sendewege sind Bedienung. Also wächst die Galerie, der
   Orb behält seine Größe, und die Wege bleiben schmal.

   Erst ab 1100px, damit Tablets und schmale Fenster ihre bisherige,
   ausbalancierte Aufteilung behalten. Das Telefon (#1332/#1333) bleibt
   unberührt — dort gilt weiter das Zeilenraster weiter unten. */
@media (min-width: 1100px) {
  /* Der eigentliche Deckel sass hier, nicht an der Galerie: Das Panel war auf
     980px begrenzt, also half auch eine breitere Bild-Spalte nichts. Auf
     einem 2560er-Schirm blieben ueber anderthalb Bildschirmbreiten
     ungenutzt — hinter einer Unschaerfe, die ohnehin nichts zeigt. */
  .voice-recording-panel { width: min(96vw, 1720px); }

  .voice-recording-stage.has-images {
    grid-template-columns: minmax(360px, 1fr) auto minmax(190px, 260px);
    gap: clamp(28px, 3.5vw, 64px);
    align-items: stretch;
  }

  /* Der Orb bleibt mittig auf seiner Spur, auch wenn links mehr Platz ist —
     sonst klebt er an der Bildkante. */
  .voice-recording-stage.has-images > :nth-child(2) { align-self: center; }
}

.voice-recording-target {
  max-width: min(80vw, 520px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-primary);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  border: 1px solid var(--border-strong);
  padding: 7px 12px;
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.voice-recording-send {
  width: clamp(156px, 20vmin, 220px);
  height: clamp(156px, 20vmin, 220px);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 2px solid color-mix(in srgb, var(--accent) 72%, var(--white));
  border-radius: 50%;
  position: relative;   /* Anker für die Wolkenfläche */
  overflow: hidden;     /* die Fläche endet am Kreis, nicht am Kasten */
  background: var(--accent);
  color: var(--white);
  /* DER INHALT BLEIBT IM EINBESCHRIEBENEN RECHTECK.
     Alex, 25.08. (Bild 120611): „unten passt der Text wieder nicht perfekt in
     den Magenta-Kreis rein."

     Der Grund ist geometrisch, nicht kosmetisch: Ein Kreis bietet auf Höhe
     seiner Ränder nur eine kurze Sehne, nicht den vollen Durchmesser. Ohne
     Begrenzung nimmt eine Beschriftung die volle Breite an — und stösst genau
     dort an, wo die Fläche schmal wird.

     Das einbeschriebene Quadrat misst Durchmesser ÷ √2, also rund 70 %. Der
     Rest ist der Rand, den die Krümmung ohnehin verlangt. */
  padding: 0 15%;
  box-shadow: 0 18px 54px color-mix(in srgb, var(--accent) 38%, transparent);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease, background-color 0.12s ease;
}

.voice-recording-send:disabled { cursor: wait; opacity: 0.92; }
.voice-recording-send:hover:not(:disabled) { background: var(--accent-hover); }
.voice-recording-send:active:not(:disabled) { transform: scale(0.94); }

.voice-recording-status {
  /* Im Kreis ist GESTAPELT richtiger als GESTRECKT: Zwei kurze Zeilen passen
     in eine runde Fläche, eine lange stösst an. */
  max-width: 100%;
  text-align: center;
  line-height: 1.25;
  letter-spacing: 0.06em;
  font-size: 12px;
  text-wrap: balance;
  position: relative;   /* über der Wolkenfläche */
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Jeder Teil eine eigene Zeile — der Trennpunkt entfällt, statt an den Anfang
   der zweiten Zeile zu rutschen und dort wie ein Fehler auszusehen. */
.voice-recording-status-line { display: block; white-space: nowrap; }

.voice-recording-send svg { position: relative; }

.voice-recording-meter {
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.voice-recording-meter .voice-vu { height: 28px; gap: 4px; }
.voice-recording-meter .voice-vu-bar {
  width: 4px;
  min-height: 3px;
  background: currentColor;
  border-radius: 2px;
  box-shadow: 0 0 8px color-mix(in srgb, currentColor 52%, transparent);
}

.voice-recording-meter .recording-vu { height: 28px; padding: 0; gap: 4px; }
.voice-recording-meter .recording-vu-bar {
  width: 4px;
  min-height: 3px;
  background: currentColor;
  border-radius: 2px;
  box-shadow: 0 0 8px color-mix(in srgb, currentColor 52%, transparent);
}

/* After the send click, this SAME mounted overlay becomes a card-local status
   orb. It neither blurs nor intercepts the rest of the Multi-Agent surface. */
.voice-recording-overlay.is-docked {
  padding: 0;
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  pointer-events: none;
  overflow: visible;
}

.voice-recording-overlay.is-docked .voice-recording-panel {
  position: fixed;
  width: auto;
  gap: 0;
  padding: 0;
  transform: translate(-50%, -50%);
}

.voice-recording-overlay.is-docked .voice-recording-header,
.voice-recording-overlay.is-docked .voice-recording-gallery,
.voice-recording-overlay.is-docked .voice-recording-routes {
  display: none;
}

.voice-recording-overlay.is-docked .voice-recording-stage {
  width: auto;
  display: block;
}

.voice-recording-overlay.is-docked .voice-recording-send {
  width: 92px;
  height: 92px;
  padding: 8px;
  gap: 3px;
  border-width: 1px;
  box-shadow: 0 12px 38px color-mix(in srgb, var(--accent) 34%, transparent);
  opacity: 1;
  transition: width 0.38s cubic-bezier(0.22, 1, 0.36, 1),
    height 0.38s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.16s ease;
}

.voice-recording-overlay.is-docked .voice-recording-send > svg {
  width: 24px;
  height: 24px;
}

.voice-recording-overlay.is-docked .voice-recording-status {
  max-width: 72px;
  font-size: 8px;
  line-height: 1.05;
}

@media (max-width: 600px) {
  .voice-recording-overlay.is-docked .voice-recording-send {
    width: 76px;
    height: 76px;
    padding: 6px;
  }

  .voice-recording-overlay.is-docked .voice-recording-send > svg {
    width: 20px;
    height: 20px;
  }

  .voice-recording-overlay.is-docked .voice-recording-status {
    max-width: 60px;
    font-size: 7px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .voice-recording-overlay.is-docked .voice-recording-send { transition: none; }
}

.voice-recording-gallery,
.voice-recording-routes {
  width: 100%;
  min-width: 0;
  border: 1px solid color-mix(in srgb, var(--border-strong) 72%, transparent);
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  box-shadow: 0 14px 38px color-mix(in srgb, var(--black) 18%, transparent);
  -webkit-backdrop-filter: blur(16px) saturate(135%);
  backdrop-filter: blur(16px) saturate(135%);
}

.voice-recording-gallery { position: relative; min-height: 224px; display: flex; flex-direction: column; }
.voice-recording-gallery.has-images { min-height: 280px; }
.voice-recording-file-input { display: none; }
.voice-recording-gallery-add {
  flex: 1;
  min-height: 222px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 22px;
  border: 0;
  background: transparent;
  color: var(--text-primary);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 13px;
}
.voice-recording-gallery-add svg { width: 58px; height: 58px; padding: 12px; border: 1px solid var(--accent); border-radius: 50%; color: var(--accent); }
.voice-recording-gallery-add small { color: var(--text-muted); font-size: 10px; }
.voice-recording-gallery-add:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.voice-recording-gallery-add:disabled { opacity: 0.55; cursor: not-allowed; }
/* GRUNDHÖHE RELATIV, NICHT FEST.
   Alex, 25.08.: „während ich eine Sprachnachricht aufnehme, möchte ich den
   Screenshot besser sehen können." Die feste Höhe von 188 px liess von einem
   hochkanten Bildschirmfoto kaum mehr als einen Streifen übrig. Die
   grosszügige Regel gab es bisher nur am Telefon — am Schreibtisch, wo mehr
   Platz ist, blieb es beim kleinsten Wert.

   Die Querlage-Regel weiter unten überschreibt das weiterhin; ihre Reihenfolge
   ist im Wächter festgehalten. */
/* touch-action: none — sonst frisst der Browser die Zwei-Finger-Geste (Pinch-Zoom
   auf dem Bild, Alex 03.09. 11:3x) und das Bild bleibt starr. */
.voice-recording-gallery-stage { position: relative; height: clamp(240px, 40vh, 560px); overflow: hidden; touch-action: none; background: color-mix(in srgb, var(--black) 46%, transparent); }
.voice-recording-gallery-stage.is-gezoomt { cursor: grab; }

/* Auch in die Höhe: 40vh liess oben und unten Rand stehen, den niemand
   braucht. 68vh nutzt den Schirm, ohne die Sendezeile darunter zu
   verdrängen. */
@media (min-width: 1100px) {
  .voice-recording-gallery.has-images .voice-recording-gallery-stage { height: clamp(320px, 68vh, 900px); }
}
.voice-recording-gallery-image { width: 100%; height: 100%; display: block; object-fit: contain; transform-origin: center center; will-change: transform; user-select: none; -webkit-user-drag: none; }
.voice-recording-gallery-remove,
.voice-recording-gallery-nav {
  position: absolute;
  z-index: 2; /* ueber dem gezoomten (transformierten) Bild */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid color-mix(in srgb, var(--white) 40%, transparent);
  background: color-mix(in srgb, var(--black) 58%, transparent);
  color: var(--white);
  cursor: pointer;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.voice-recording-gallery-remove { top: 8px; right: 8px; width: 36px; height: 36px; border-radius: 50%; }
.voice-recording-gallery-nav { top: 50%; width: 36px; height: 52px; transform: translateY(-50%); }
.voice-recording-gallery-nav.is-prev { left: 6px; }
.voice-recording-gallery-nav.is-next { right: 6px; }
.voice-recording-gallery-nav:disabled { opacity: 0.28; cursor: default; }
.voice-recording-gallery-footer { min-height: 35px; display: flex; align-items: center; gap: 7px; padding: 5px 7px; color: var(--text-muted); font-family: var(--font-mono); font-size: 10px; }
.voice-recording-gallery-footer button { min-height: 28px; display: inline-flex; align-items: center; gap: 3px; padding: 4px 7px; border: 1px solid var(--border); background: transparent; color: var(--text-primary); cursor: pointer; font: inherit; }
.voice-recording-gallery-footer button:first-of-type { margin-left: auto; }
.voice-recording-upload-state,
.voice-recording-upload-error { display: block; padding: 6px 8px; font-family: var(--font-mono); font-size: 10px; }
.voice-recording-upload-state { color: var(--accent); }
.voice-recording-upload-error { color: var(--color-error); }
.voice-recording-upload-actions { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 8px 8px; }
.voice-recording-upload-actions button { min-height: 34px; display: inline-flex; align-items: center; justify-content: center; gap: 5px; flex: 1 1 112px; padding: 6px 8px; border: 1px solid var(--border-strong); background: color-mix(in srgb, var(--surface) 72%, transparent); color: var(--text-primary); cursor: pointer; font-family: var(--font-mono); font-size: 10px; }
.voice-recording-upload-actions button:last-child { border-color: var(--accent); color: var(--accent); }

.voice-recording-routes { display: flex; flex-direction: column; gap: 5px; padding: 9px; }
.voice-recording-routes-label { padding: 3px 5px 6px; color: var(--text-muted); font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; }
.voice-recording-routes button { min-height: 42px; display: flex; align-items: center; gap: 9px; padding: 8px 10px; border: 1px solid transparent; background: transparent; color: var(--text-muted); cursor: pointer; font-family: var(--font-mono); font-size: 11px; text-align: left; }
.voice-recording-routes button:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 9%, transparent); color: var(--text-primary); }
.voice-recording-routes button.is-active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--text-primary); }
.voice-recording-routes button:disabled { opacity: 0.55; cursor: default; }
.voice-recording-route-label-mobile { display: none; }

.voice-recording-cancel {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 16px;
  border: 1px solid var(--border-strong);
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  color: var(--text-primary);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 12px;
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
.voice-recording-cancel:hover { border-color: var(--color-error); color: var(--color-error); }

@media (max-width: 900px), (max-height: 620px) {
  .voice-recording-overlay { overflow-y: auto; place-items: start center; }
  .voice-recording-stage { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .voice-recording-send { grid-row: 1; justify-self: center; }
  .voice-recording-gallery { grid-row: 2; max-width: 360px; justify-self: center; }
  .voice-recording-routes { grid-row: 3; max-width: 360px; justify-self: center; }
}

/* Phone portrait: the screenshot is the thing being discussed, so attached
   media receives the height budget. Controls become denser without changing
   the desktop/AR composition or shrinking their touch targets below 34px. */
@media (max-width: 600px) {
  .voice-recording-overlay {
    padding: max(8px, env(safe-area-inset-top, 0px)) max(8px, env(safe-area-inset-right, 0px)) max(8px, env(safe-area-inset-bottom, 0px)) max(8px, env(safe-area-inset-left, 0px));
  }

  .voice-recording-panel { gap: 8px; padding: 4px; }
  .voice-recording-stage { gap: 8px; }
  .voice-recording-target { max-width: 92vw; padding: 5px 9px; font-size: 10px; }

  .voice-recording-send {
    width: clamp(128px, 36vw, 148px);
    height: clamp(128px, 36vw, 148px);
    gap: 3px;
    font-size: 9px;
    letter-spacing: 0.035em;
  }
  .voice-recording-send > svg { width: 42px; height: 42px; }
  .voice-recording-status { max-width: 112px; line-height: 1.12; text-align: center; }
  .voice-recording-meter { min-height: 18px; }
  .voice-recording-meter .voice-vu,
  .voice-recording-meter .recording-vu { height: 18px; gap: 2px; }
  .voice-recording-meter .voice-vu-bar,
  .voice-recording-meter .recording-vu-bar { width: 2px; box-shadow: 0 0 5px color-mix(in srgb, currentColor 46%, transparent); }

  .voice-recording-gallery,
  .voice-recording-routes { max-width: min(100%, 440px); }
  .voice-recording-gallery { min-height: 150px; }
  .voice-recording-gallery-add { min-height: 148px; gap: 6px; padding: 12px; font-size: 11px; }
  .voice-recording-gallery-add svg { width: 46px; height: 46px; padding: 9px; }
  .voice-recording-gallery.has-images .voice-recording-gallery-stage {
    height: clamp(300px, 48dvh, 520px);
  }

  /* DER KREIS GEHÖRT IN DIE DAUMENZONE (#1332, Bild 120613).
     Am Telefon lag er ganz oben, während die untere Bildhälfte leer blieb —
     zum Absenden musste man mitten im Sprechen quer über den Bildschirm
     greifen. Jetzt dockt das Blatt unten an, und der Kreis ist das unterste
     Element.

     Die Reihenfolge dreht sich dafür um: Galerie, Sendewege, Kreis. Die
     Sendewege bleiben ÜBER dem Kreis — man wählt den Weg, bevor man absendet,
     und der Kreis verdeckt sie nicht.

     Nur am Telefon (≤600px). Schreibtisch und Querlage bleiben unberührt. */
  .voice-recording-overlay { align-items: end; }
  .voice-recording-panel { width: 100%; }
  .voice-recording-gallery { grid-row: 1; }
  .voice-recording-send {
    grid-row: 3;
    /* Abstand zur Browserleiste: Die Safe-Area allein reicht dort nicht, wo
       Safari seine Leiste über den Inhalt legt. */
    margin-bottom: max(6px, env(safe-area-inset-bottom, 0px));
  }

  /* „Verwerfen" wandert nach OBEN, weg vom Daumen. Eine zerstörende Aktion
     gehört nicht an die Stelle, an der die Hand ohnehin liegt. */
  .voice-recording-cancel { order: -1; }

  .voice-recording-routes {
    grid-row: 2;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px;
    padding: 6px;
  }
  .voice-recording-routes-label { grid-column: 1 / -1; padding: 0 3px 2px; font-size: 8px; }
  .voice-recording-routes button {
    min-height: 34px;
    gap: 5px;
    padding: 5px 7px;
    font-size: 9px;
    white-space: nowrap;
  }
  .voice-recording-routes button svg { width: 14px; height: 14px; flex-shrink: 0; }
  .voice-recording-route-label-full { display: none; }
  .voice-recording-route-label-mobile { display: inline; overflow: hidden; text-overflow: ellipsis; }

  .voice-recording-cancel { min-height: 38px; padding: 6px 12px; font-size: 10px; }
}

/* Telefon HOCHKANT: Alex will beim Sprechen möglichst viel vom angehängten
   Bild sehen (Storage 120664). Ziel + Verwerfen teilen deshalb eine Kopfzeile;
   die vier vorhandenen Sendewege teilen eine einzige Zeile. Die Buttons
   bleiben mindestens 42 px hoch und behalten ihre vollständigen aria-labels.
   Kleine Querformate bleiben beim bisherigen 2×2-Raster. */
@media (max-width: 600px) and (min-height: 561px) {
  .voice-recording-header {
    order: 0;
    width: min(100%, 440px);
    display: flex;
    align-items: stretch;
    gap: 5px;
  }

  .voice-recording-target {
    order: 0;
    flex: 1 1 auto;
    min-width: 0;
    max-width: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
  }

  .voice-recording-header .voice-recording-cancel {
    order: -1;
    flex: 0 0 auto;
    min-height: 34px;
    padding: 5px 8px;
  }

  .voice-recording-routes {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 3px;
    padding: 4px;
  }

  .voice-recording-routes-label { display: none; }

  .voice-recording-routes button {
    min-width: 0;
    min-height: 42px;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    padding: 3px 1px;
    text-align: center;
  }

  .voice-recording-route-label-mobile {
    display: block;
    max-width: 100%;
  }
}

/* A phone in landscape is wide but vertically starved. Never inherit the
   portrait gallery enlargement merely because a narrow split-view reports a
   small width; keep enough room for target, send and discard controls. */
@media (max-height: 560px) {
  .voice-recording-gallery.has-images .voice-recording-gallery-stage {
    height: min(36dvh, 180px);
  }
}

/* ── Ausgeblendet: der Kreis wandert nach rechts unten ─────────────────────
   Alex, 29.08.: „Dann soll der Aufnahmekreis nach rechts unten gehen und der
   Screen wird frei — ich kann damit herumhantieren und mir das anschauen,
   während ich rede."

   DER UNTERSCHIED ZUM `is-docked` DARÜBER: Jenes ist der Zustand NACH dem
   Absenden, ein reiner Statusanzeiger — er nimmt keine Klicks an
   (`pointer-events: none`). Dieser hier läuft WÄHREND der Aufnahme und ist
   der einzige Rückweg, also muss genau der Kreis anklickbar bleiben, während
   alles um ihn herum durchlässig wird. */
.voice-recording-overlay.ist-versteckt {
  padding: 0;
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  pointer-events: none;
  overflow: visible;
}

.voice-recording-overlay.ist-versteckt .voice-recording-panel {
  position: fixed;
  right: max(16px, env(safe-area-inset-right, 0px));
  bottom: max(16px, env(safe-area-inset-bottom, 0px));
  width: 92px;
  gap: 0;
  padding: 0;
  /* Der Kreis ist der Rückweg — er nimmt Klicks an, der Rest des Schirms
     nicht. */
  pointer-events: auto;
  cursor: pointer;
}

/* Alles, was den Blick verstellt, geht weg: Kopfzeile mit den Knöpfen, die
   Bildergalerie, die Routenwahl und die Statuszeile. Übrig bleibt die Kugel,
   damit sichtbar bleibt, DASS aufgenommen wird. */
.voice-recording-overlay.ist-versteckt .voice-recording-header,
.voice-recording-overlay.ist-versteckt .voice-recording-gallery,
.voice-recording-overlay.ist-versteckt .voice-recording-routes,
.voice-recording-overlay.ist-versteckt .voice-recording-status,
.voice-recording-overlay.ist-versteckt .voice-recording-actions {
  display: none;
}

.voice-recording-overlay.ist-versteckt .voice-recording-panel:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

.voice-recording-hide {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border: 0;
  color: var(--text-secondary);
  background: transparent;
  font: inherit;
  cursor: pointer;
}

.voice-recording-hide:hover,
.voice-recording-hide:focus-visible { color: var(--text-primary); }

/* ── Anhang ohne Bild (Alex 16.09., Bild 125410) ────────────────────────────
   Eine TSV hat keine Miniatur. Statt eines leeren <img> steht hier eine Karte:
   Name, Art und Groesse, darunter die ersten Zeilen in Festbreite — Tabulatoren
   bleiben, damit die Spalten einer Tabelle als Spalten lesbar sind. */
.voice-recording-gallery-datei {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  background: var(--surface);
  color: var(--text-primary);
  overflow: hidden;
}
.vrg-datei-kopf { display: flex; align-items: center; gap: 8px; min-width: 0; }
.vrg-datei-name { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vrg-datei-meta { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); }
.vrg-datei-text {
  flex: 1;
  min-height: 0;
  margin: 0;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  background: var(--bg-inset, var(--surface));
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.45;
  tab-size: 12;
  white-space: pre;
  overflow: auto;
  overscroll-behavior: contain;
}
.vrg-datei-leer { font-size: 12px; color: var(--text-secondary); }
/* ── Input Bar Wrapper ────────────────────────────────────────── */
.input-bar-wrap {
  flex-shrink: 0;
  border-top: 1px solid var(--border);
  background: var(--surface);
  position: relative;
  z-index: 50;
  padding-bottom: 0;
}
/* Inside the agent view's glass footer: translucent blur instead of opaque
   surface (Alex 2026-07-03). Theme-aware via --surface. */
.agent-footer .input-bar-wrap,
.collab-footer .input-bar-wrap {
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .agent-footer .input-bar-wrap, .collab-footer .input-bar-wrap { background: var(--surface); }
}

/* ── Prompt-Agent intake result flash ────────────────────────── */
.ib-pa-flash {
  margin: 8px 12px 0;
  padding: 7px 11px;
  font-size: 12px;
  cursor: pointer;
  background: var(--accent-bg);
  color: var(--text-primary);
}
.ib-pa-ok { background: var(--color-success-bg); color: var(--color-success); }
.ib-pa-err { background: var(--color-error-bg); color: var(--color-error); }
.ib-pa-info { background: var(--accent-bg); color: var(--text-primary); }

/* ── TTS Status ──────────────────────────────────────────────── */
.tts-status {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  padding: 4px 32px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
}
.tts-status-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tts-controls {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
.tts-ctrl-btn {
  display: inline-flex;
  align-items: center;
  gap: 1px;
  padding: 3px 7px;
  background: var(--bg-light);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-primary);
  cursor: pointer;
  transition: background-color 0.12s ease;
}
.tts-ctrl-btn:hover {
  background: var(--bg-inset);
}
.tts-ctrl-sec {
  font-size: 9px;
  font-weight: 600;
}
.tts-ctrl-stop {
  color: var(--color-error);
  border-color: var(--color-error);
}
.tts-ctrl-stop:hover {
  background: var(--color-error);
  color: var(--white);
}

.upload-error {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 32px;
  border-bottom: 1px solid var(--error, #dc2626);
  background: color-mix(in srgb, var(--error, #dc2626) 8%, transparent);
  color: var(--error, #dc2626);
  font-family: var(--font-mono);
  font-size: 11px;
}

.upload-error button {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

/* ── Attachment Previews ─────────────────────────────────────── */
.attachment-row {
  display: flex;
  gap: 8px;
  padding: 8px 32px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}

.attachment-item {
  position: relative;
  flex-shrink: 0;
}

.attachment-thumb {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: 4px;
}

.attachment-file {
  /* Karte statt Miniatur fuer alles, was kein Bild ist: Zeichen + Endung, Name
     und Groesse im Titel (Alex 16.09., Bild 125410). */
  flex-direction: column;
  gap: 2px;
  width: 48px;
  height: 48px;
  border: 1px solid var(--border);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-muted);
  text-transform: uppercase;
  background: var(--bg-inset);
}

.attachment-remove {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--chip-active-bg);
  color: var(--white);
  border: none;
  font-size: 10px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.attachment-loading {
  width: 48px;
  height: 48px;
  border: 1px solid var(--border);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-inset);
}

.attachment-spinner {
  width: 16px;
  height: 16px;
  border: 2px solid var(--border);
  border-top-color: var(--text-primary);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ── Command Button Upload Spinner ───────────────────────────── */
.input-action.uploading {
  border-color: var(--accent);
  color: var(--accent);
}

.cmd-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid var(--border);
  /* Transcribe/processing spinner follows the accent (Alex 2026-06-22). */
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

/* ── Key Row ─────────────────────────────────────────────────── */
.key-row {
  display: flex;
  gap: 6px;
  padding: 8px 32px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.key-btn {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: all 0.15s ease;
}

.key-btn:hover {
  border-color: var(--text-primary);
  color: var(--text-primary);
}

.key-btn:active {
  background: var(--bg-light);
}

.key-btn.key-success {
  color: var(--color-success);
  border-color: var(--color-success);
}

.key-btn.key-error {
  color: var(--color-error);
  border-color: var(--color-error);
}

.key-btn.key-warning {
  color: var(--color-warning);
  border-color: var(--color-warning);
}

.key-btn.key-purple {
  color: #9333ea;
  border-color: #9333ea;
}

.key-btn.key-accent {
  color: var(--color-info);
  border-color: var(--color-info);
}

/* ── Main Input Bar ──────────────────────────────────────────── */
.input-bar-wrap .input-bar {
  display: flex;
  /* Bottom-align so buttons sit at the row's base (and stay there when the
     textarea grows multi-line) — Alex 2026-06-22. */
  align-items: flex-end;
  gap: 12px;
  padding: 12px 32px;
}

.input-bar-wrap .input-field {
  flex: 1;
  padding: 10px 0;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 16px;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  outline: none;
  transition: border-color 0.2s ease;
  resize: none;
  /* Grow as the user types, scroll when we hit the cap.
   * Cap at 50% of the visual viewport so the conversation above
   * remains visible. The JS handler sets `style.height = scrollHeight + 'px'`
   * unbounded; CSS max-height clamps the rendered box and overflow:auto
   * kicks in beyond that. */
  overflow-y: auto;
  min-height: 24px;
  max-height: calc(var(--vh, 1vh) * 50);
  line-height: 1.4;
}

.input-bar-wrap .input-field:focus {
  border-bottom-color: var(--text-primary);
}

.input-bar-wrap .input-field::placeholder {
  color: var(--text-muted);
}

.input-bar-wrap .input-action {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: none;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  color: var(--text-primary);
  cursor: pointer;
  font-size: 14px;
  /* Quick transition for transform so :active feels snappy, slower for
     color/border so the inverse fade-in feels deliberate. */
  transition: transform 0.06s ease, background 0.12s ease,
              border-color 0.12s ease, color 0.12s ease;
  flex-shrink: 0;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  /* Kill iOS Safari's faded blue tap-highlight — we paint our own :active. */
  -webkit-tap-highlight-color: transparent;
  /* Don't let touch-actions drift into pan-y interpretation. */
  touch-action: manipulation;
}

.input-bar-wrap .input-action:hover {
  border-color: var(--text-primary);
  color: var(--text-primary);
}

/* Tactile press feedback — works on touch (no :hover) AND mouse-down.
   Strong inverse + scale-down so the press is unmistakable. */
.input-bar-wrap .input-action:active {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
  transform: scale(0.92);
}

.input-bar-wrap .input-action.active {
  border-color: var(--text-primary);
  color: var(--text-primary);
  background: var(--bg-light);
}

.input-bar-wrap .input-action.primary {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
}

.input-bar-wrap .input-action.primary:hover {
  background: var(--black);
}

.input-bar-wrap .input-action.primary:active {
  background: var(--accent);
  border-color: var(--accent);
  transform: scale(0.92);
}

/* Desktop/AR only: the two primary composer targets were 36px — precise with
   a mouse, unnecessarily small when the main view floats several metres away
   in MetaQuest. Mobile has its own touch layout below and is deliberately not
   changed by this media query. */
@media (min-width: 769px) and (min-height: 501px) {
  .agent-footer .input-bar-wrap .input-action.mic-primary,
  .agent-footer .input-bar-wrap .input-action.primary {
    width: 46px;
    height: 46px;
  }

  .agent-footer .input-bar-wrap .input-action.mic-primary svg,
  .agent-footer .input-bar-wrap .input-action.primary svg {
    width: 20px;
    height: 20px;
  }
}

/* "Sent!" confirmation — brief green fill + check icon so the user knows
   the message actually went to the agent. Pop animation draws the eye. */
.input-bar-wrap .input-action.primary.is-sent {
  background: var(--color-success);
  border-color: var(--color-success);
  color: var(--white);
  animation: send-pop 0.3s ease;
}
@keyframes send-pop {
  0%   { transform: scale(0.85); }
  45%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}

/* Send button when a queued message is waiting — stays in the primary
   black palette, but slightly desaturated so it reads as "parked". */
.input-bar-wrap .input-action.primary.has-queue {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
  opacity: 0.75;
}
.input-bar-wrap .input-action.primary.has-queue:hover {
  background: var(--black);
  border-color: var(--black);
  opacity: 1;
}

/* Long-press visual feedback — fires the moment touch/mouse-down
   lands, so the user sees the press IS being detected. A growing
   ring animates over ~500 ms to match the long-press timer — when
   the ring is "full" the menu pops. */
.input-bar-wrap .input-action.long-press-active {
  position: relative;
  transform: scale(0.92);
  animation: lp-pulse 0.5s ease-out forwards;
}
@keyframes lp-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.0);
  }
  100% {
    box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.35);
  }
}

/* Long-press progress ring (#119) — a conic sweep that fills over the 500 ms hold so
   the user SEES the countdown (paired with the haptic tick on press + buzz at fire). */
@property --lp-deg {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}
.input-bar-wrap .input-action.long-press-active::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: conic-gradient(var(--accent) var(--lp-deg), rgba(150, 150, 150, 0.3) 0deg);
  -webkit-mask: radial-gradient(closest-side, transparent 70%, #000 73%);
          mask: radial-gradient(closest-side, transparent 70%, #000 73%);
  animation: lp-sweep 0.5s linear forwards;
  pointer-events: none;
  z-index: 3;
}
@keyframes lp-sweep { to { --lp-deg: 360deg; } }

/* Disabled menu items — used when input is empty so "Queue" / "Send"
   options grey out instead of silently no-op'ing. */
.cmd-item:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.cmd-item:disabled:hover {
  background: none;
}

/* Send-menu uses the same .cmd-menu position rules as the cmd-menu-anchor.
   This wrapper is identical to .cmd-menu-anchor — same positioning context. */
.send-menu-anchor {
  position: relative;
}

/* Queue banner — neutral black/grey palette, matches the
   has-queue send button so the connection reads visually. */
.queue-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  margin-bottom: 6px;
  background: var(--bg-light);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 12px;
  color: var(--text-primary);
}
.queue-banner-icon {
  color: var(--text-primary);
  flex-shrink: 0;
}
.queue-banner-label {
  font-weight: 600;
  white-space: nowrap;
}
.queue-banner-preview {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-style: italic;
  color: var(--text-muted);
}
.queue-banner-push {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  padding: 3px 7px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--surface);
  color: var(--text-primary);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.queue-banner-push:hover {
  border-color: var(--text-muted);
  background: var(--bg-inset);
}
.queue-banner-push:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.queue-banner-cancel {
  background: transparent;
  border: none;
  color: var(--text-primary);
  padding: 2px;
  cursor: pointer;
  border-radius: 4px;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.queue-banner-cancel:hover {
  background: rgba(0, 0, 0, 0.08);
}

/* Outbox / offline retry banner — visual distinct from queue-banner
   because the meaning is different (network failure, not deliberate
   parking). Red-ish accent so "you're offline" reads at a glance. */
.outbox-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  margin-bottom: 6px;
  background: rgba(220, 38, 38, 0.08);
  border: 1px solid rgba(220, 38, 38, 0.45);
  border-radius: 6px;
  font-size: 12px;
  color: #991b1b;
}
.outbox-banner-icon {
  color: #dc2626;
  flex-shrink: 0;
}
.outbox-banner-label {
  font-weight: 600;
  white-space: nowrap;
}
.outbox-banner-preview {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-style: italic;
  color: #b91c1c;
}
.outbox-banner-retry,
.outbox-banner-cancel {
  background: transparent;
  border: none;
  color: #991b1b;
  padding: 2px 6px;
  cursor: pointer;
  border-radius: 4px;
  display: flex;
  align-items: center;
  flex-shrink: 0;
  font-size: 14px;
}
.outbox-banner-retry:hover,
.outbox-banner-cancel:hover {
  background: rgba(220, 38, 38, 0.16);
}

@media (prefers-color-scheme: dark) {
  .outbox-banner {
    background: rgba(220, 38, 38, 0.15);
    border-color: rgba(220, 38, 38, 0.6);
    color: #fca5a5;
  }
  .outbox-banner-preview {
    color: #fda4af;
  }
  .outbox-banner-retry,
  .outbox-banner-cancel {
    color: #fca5a5;
  }
}

.input-bar-wrap .input-action.error-state {
  border-color: var(--color-error);
  color: var(--color-error);
}

.input-bar-wrap .input-action.speaking {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--white);
  animation: tts-pulse 1.3s ease-in-out infinite;
}

@keyframes tts-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.45); }
  50% { box-shadow: 0 0 0 6px rgba(99, 102, 241, 0); }
}

.input-bar-wrap .input-action.mic-recording {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--white);
  animation: mic-pulse 1s infinite;
}

@keyframes mic-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

/* ── MCP Editor ──────────────────────────────────────────────── */
.mcp-editor {
  padding: 12px 32px;
}

.mcp-editor-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.mcp-editor-title {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
}

.mcp-editor-actions {
  display: flex;
  gap: 6px;
}

.mcp-editor-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
}

.mcp-editor-item {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

.mcp-editor-item input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--text-primary);
  cursor: pointer;
}

.mcp-editor-name {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
}

/* ── Stop Button ─────────────────────────────────────────────── */
.input-action.stop-btn {
  background: var(--surface);
  border-color: var(--text-primary);
  color: var(--text-primary);
  font-size: 12px;
}

.input-action.stop-btn:hover {
  background: var(--bg-light);
}

.input-action.long-press-active {
  background: var(--color-info);
  border-color: var(--color-info);
  color: var(--white);
}


/* ── Command Menu ────────────────────────────────────────────── */
.cmd-menu-anchor {
  position: relative;
}

.cmd-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9998;
}

.cmd-menu {
  position: fixed;
  bottom: 70px;
  right: 16px;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  border: 1px solid var(--border);
  min-width: 200px;
  z-index: 9999;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.cmd-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 16px;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-primary);
  cursor: pointer;
  text-align: left;
  transition: background-color 0.15s ease;
}

.cmd-item:last-child {
  border-bottom: none;
}

.cmd-item:hover {
  background: var(--bg-light);
}

.cmd-icon {
  font-size: 14px;
  width: 20px;
  text-align: center;
  flex-shrink: 0;
}

/* ── Recording Bar ───────────────────────────────────────────── */
.recording-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 32px;
  gap: 16px;
}

/* SENDEN DARF NIE AUS DER ZEILE FALLEN (Alex, #1280: „fehlt mir der Button
   Senden, weil die Breite zu breit ist … ich muss das Telefon quer drehen").
   Nachgerechnet: Abbrechen 36 + Pegel 70 + Zeit 40 + Optionen ~110 +
   Senden 36 + Rand 64 + Abstände 48 = ~404px Mindestbreite. Ein Telefon im
   Hochformat hat 390 — bei Alex' 115-%-Seitenzoom effektiv ~339.
   Die Pegelanzeige konnte nicht schrumpfen, weil ein flex-Kind ohne
   `min-width: 0` nie unter seine Inhaltsbreite geht; sie schob den
   Senden-Knopf aus dem sichtbaren Bereich. */
.recording-indicator {
  min-width: 0;
}

.recording-vu {
  min-width: 0;
  overflow: hidden;
}

.recording-cancel,
.recording-stop {
  flex-shrink: 0;
}

.recording-cancel {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: none;
  border: 1px solid var(--border);
  /* Round to match the recording send button + mic FAB (Alex 2026-07-03). */
  border-radius: 50%;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 16px;
  flex-shrink: 0;
  transition: all 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}

.recording-cancel:hover {
  border-color: var(--text-primary);
  color: var(--text-primary);
}

.recording-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  justify-content: center;
}

/* VU-equalizer — 12 vertical bars where each bar's HEIGHT animates with
   the amplitude of one frequency band from the live mic stream. Voice
   produces a moving spectral signature so the bars dance up and down
   while you speak. Smooth height transition makes the motion feel
   organic instead of stroboscopic. */
.recording-vu {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 28px;
  padding: 0 6px;
}
.recording-vu-bar {
  display: block;
  width: 3px;
  /* Recording/transcribe equalizer follows the accent (Alex 2026-06-22). */
  background: var(--accent);
  border-radius: 1px;
  /* Quick rise, slightly slower fall so peaks linger long enough to read. */
  transition: height 80ms ease-out, background-color 60ms linear;
  min-height: 2px;
}
.recording-vu-bar.is-peak {
  background: var(--accent-hover);
}

.recording-time {
  font-family: var(--font-mono);
  font-size: 16px;
  /* Recording time + send button follow the accent (Alex 2026-06-22). */
  color: var(--accent);
}

/* Route toggle during a long-press (Prompt-Agent) recording — mono/uppercase
   segmented control (house style), active = dark primary fill (Alex 2026-07-01). */
.voice-route { display: inline-flex; align-items: stretch; border: 1px solid var(--border); flex-shrink: 0; }
/* Fixed route label — the recording ALWAYS goes to the Prompt-Agent (2026-07-03). */
.voice-route-fixed {
  font-family: var(--font-mono);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 4px 8px;
  background: var(--chip-active-bg);
  color: var(--white);
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}
.voice-route-opt {
  font-family: var(--font-mono);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 4px 8px;
  background: transparent;
  color: var(--text-muted);
  border: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s ease, color 0.12s ease;
}
.voice-route-opt + .voice-route-opt { border-left: 1px solid var(--border); }
.voice-route-opt.is-active { background: var(--chip-active-bg); color: var(--white); }

.recording-stop {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: var(--accent);
  border: none;
  /* Round like the mic FAB it replaces during recording (Alex 2026-07-03). */
  border-radius: 50%;
  color: var(--white);
  cursor: pointer;
  font-size: 16px;
  flex-shrink: 0;
  transition: all 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}

.recording-stop:hover {
  background: var(--accent-hover);
}

.recording-stop:active {
  transform: scale(0.88);
  background: var(--accent-hover);
}

/* Pressed/sending state — distinct darker fill + spinner so the tap is
   unmistakably acknowledged while the async stop/transcribe runs. */
.recording-stop.is-pressed {
  background: var(--accent-hover);
  transform: scale(0.92);
  cursor: default;
}

/* Recording-state image gallery — larger, swipeable view of the
   attached pictures so the user can narrate them while speaking. */
.recording-gallery {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 12px 4px;
}
.recording-gallery-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  touch-action: pan-y;
}
.recording-gallery-img {
  max-width: 100%;
  /* Doppelt so groß wie vorher (Alex, 12.08.): „Bei der Analyse schaue ich
     meistens aufs Bild […] dass ich da auf den Hintergrund hin schauen kann,
     ist mir eigentlich egal." Beim Diktieren IST das Bild der Inhalt, der
     Verlauf dahinter nur Kulisse.

     Nicht schlicht 76vh, sondern gedeckelt durch den Platz, der übrig bleibt:
     Aufnahmeleiste, Punkte und die Sicherheitszone unten brauchen zusammen
     rund 190px. Eine feste Höhe schöbe auf einem kleinen Gerät genau die
     Knöpfe aus dem Bild, mit denen man die Aufnahme beendet.

     `dvh` steht als zweite Zeile: Wo es unterstützt wird, rechnet es die
     ein- und ausfahrende Browserleiste des Telefons mit — wo nicht, gilt die
     erste Zeile weiter. */
  max-height: min(76vh, calc(100vh - 190px));
  max-height: min(76dvh, calc(100dvh - 190px));
  object-fit: contain;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-inset);
}
.recording-gallery-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  border: none;
  border-radius: 50%;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.recording-gallery-nav.prev { left: 8px; }
.recording-gallery-nav.next { right: 8px; }
.recording-gallery-nav:disabled { opacity: 0.25; cursor: default; }
.recording-gallery-dots {
  display: flex;
  gap: 6px;
}
.recording-gallery-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: var(--border-strong);
  cursor: pointer;
}
.recording-gallery-dot.is-active {
  background: var(--chip-active-bg);
}

/* ── Transcribing Bar ────────────────────────────────────────── */
.transcribing-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 20px 32px;
}

/* Self-animating sound-wave — there's no live audio during transcribe, so
 * the bars run a staggered sine on their own to say "conversion läuft". */
.transcribing-wave {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 22px;
}
.transcribing-wave-bar {
  width: 3px;
  height: 100%;
  border-radius: 2px;
  /* Transcribe animation follows the accent (Alex 2026-06-22). */
  background: var(--accent);
  transform-origin: center;
  animation: transcribe-wave 1s ease-in-out infinite;
}
@keyframes transcribe-wave {
  0%, 100% { transform: scaleY(0.28); opacity: 0.5; }
  50%      { transform: scaleY(1);    opacity: 1; }
}

.transcribing-text {
  position: relative;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.05em;
  /* Sweeping shimmer: a moving light band over the warning colour so the
   * label itself feels alive, not just the bars beside it. */
  color: var(--accent);
  background: linear-gradient(
    90deg,
    var(--accent) 0%,
    var(--accent) 35%,
    rgba(255, 255, 255, 0.85) 50%,
    var(--accent) 65%,
    var(--accent) 100%
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: transcribe-shimmer 1.8s linear infinite;
}
@keyframes transcribe-shimmer {
  0%   { background-position: 120% 0; }
  100% { background-position: -120% 0; }
}

/* Breathing ellipsis — each dot fades in turn so it reads as "working…". */
.transcribing-dots i {
  font-style: normal;
  -webkit-text-fill-color: var(--accent);
  animation: transcribe-dot 1.4s ease-in-out infinite;
}
.transcribing-dots i:nth-child(2) { animation-delay: 0.2s; }
.transcribing-dots i:nth-child(3) { animation-delay: 0.4s; }
@keyframes transcribe-dot {
  0%, 80%, 100% { opacity: 0.25; }
  40%           { opacity: 1; }
}

/* ── Review Bar ──────────────────────────────────────────────── */
.review-bar {
  padding: 16px 32px;
}

.review-prefix {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
  padding: 8px 0 4px;
  overflow-wrap: break-word;
  word-break: break-all;
}

.review-text {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-primary);
  margin-bottom: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}

.review-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.review-btn {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 0;
  cursor: pointer;
  transition: all 0.15s ease;
}

/* Senden demoted from the wide primary to a normal outline button — the big
   primary slot now belongs to Prompt-Agent (Issue #188). */
.review-send {
  background: transparent;
  color: var(--text-primary);
}

.review-send:hover {
  border-color: var(--text-primary);
}

.review-edit {
  background: transparent;
  color: var(--text-primary);
}

.review-edit:hover {
  border-color: var(--text-primary);
}

.review-queue {
  background: transparent;
  color: var(--color-info);
  border-color: var(--color-info);
}
.review-queue:hover { background: var(--color-info-bg); }

/* Prompt-Agent is now THE big primary action (Issue #188): flex:1 wide + the
   dark primary fill Senden used to carry (matches the app's dark-primary
   convention, guaranteed contrast). */
.review-promptagent {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
  flex: 1;
}
.review-promptagent:hover { background: var(--black); }

.review-discard {
  background: transparent;
  color: var(--color-error);
  border-color: var(--color-error-bg);
}

.review-discard:hover {
  background: var(--color-error-bg);
  border-color: var(--color-error);
}

/* ── Mobile ──────────────────────────────────────────────────── */
@media (max-width: 768px), (max-height: 500px) {
  .input-bar-wrap {
    max-width: 100vw;
    overflow: hidden;
    /* Old Chrome (no dvh): the container fills more than the visible
       area, so the input bar lands behind the browser's bottom UI.
       Big 40px fallback keeps it visible. */
    padding-bottom: 40px;
  }
}

/* Modern browsers: parent container is sized via --vh (visualViewport.
   height, JS-synced in main.tsx) — already excludes Safari's bottom UI
   AND the home-indicator zone. So we only want a tiny breathing-room
   pad; adding safe-area-inset-bottom would double-pad and leave a fat
   gap above the Safari bottom bar. */
@supports (height: 100dvh) {
  @media (max-width: 768px), (max-height: 500px) {
    .input-bar-wrap {
      /* 8 px Luft — PLUS dem Teil der Geräte-Schutzzone, den die Browser-
         Oberfläche nicht ohnehin schon abzieht (`--chrome-bottom`, in
         main.tsx aus visualViewport gemessen).

         Zieht der Browser seine Leiste selbst ab (bisheriges Verhalten),
         ist --chrome-bottom groß, die Differenz 0 → es bleibt bei 8 px,
         keine fette Lücke. Legt er die Leiste ÜBER die Seite, ist
         --chrome-bottom 0 → wir halten die Schutzzone selbst frei und die
         Eingabezeile bleibt sichtbar. Beide Welten, ohne Fallunterscheidung
         nach Browser-Version. */
      /* DAZU die schwebende Adressleiste, wenn die Tastatur offen ist
         (Alex, 20.08., Bildschirmfoto 120051): Safari blendet bei offener
         Tastatur eine kompakte Adress-Pille EIN, die den sichtbaren Bereich
         NICHT verkleinert — sie liegt darüber. `--chrome-bottom` ist in dem
         Moment also korrekt klein, und die Eingabezeile liegt trotzdem
         darunter. Kein Rechenfehler, sondern eine Fläche, die in keiner
         gemessenen Zahl vorkommt.

         `--kb-clearance` wird nur gesetzt, solange ein Eingabefeld den Fokus
         hat (main.tsx setzt `kb-open` am <html>). Ohne Tastatur ist der Wert
         0 und es ändert sich nichts. */
      padding-bottom: calc(8px + var(--kb-clearance, 0px) + max(0px, env(safe-area-inset-bottom, 0px) - var(--chrome-bottom, 0px)));
    }
  }
}

@media (max-width: 768px), (max-height: 500px) {

  .input-bar-wrap .input-bar {
    padding: 10px 12px;
    gap: 6px;
  }

  .input-bar-wrap .input-action {
    width: 34px;
    height: 34px;
    font-size: 13px;
  }

  /* Mobile: when there's no send arrow (empty draft), the mic IS the action —
     make it double-size + a bigger glyph so it's the obvious tap target
     (Alex 2026-06-22). Only on mobile + only solo; with text the arrow
     returns and the mic shrinks back to the normal row height. */
  /* DIE MASSE DES SCHWEBENDEN KNOPFES — hier und NUR hier.
     Der durchsichtige Streifen ueber dem Glas rechnet daraus seine Hoehe
     (siehe `::before` weiter unten). Vorher stand dort die feste Zahl 34px,
     und genau deren Drift war der Fehler: Waechst der Umschlag (Sicherheits-
     abstand, Safaris Leiste), ragt der Knopf weniger heraus — der Streifen
     blieb trotzdem stehen und liess einen unbehandelten Spalt offen. */
  .input-bar-wrap:has(.input-action.mic-solo) {
    --mic-solo-size: 68px;
    --mic-solo-lift: 6px;
  }
  .input-bar-wrap .input-action.mic-primary.mic-solo {
    width: var(--mic-solo-size);
    height: var(--mic-solo-size);
    /* GANZ AUS DEM FLUSS (#1333).
       Vorher hing der Knopf im Fluss und wurde über einen negativen Rand
       zurückgezogen. Die Zeile blieb dadurch niedrig, aber der Umschlag musste
       oben 34 px reservieren, damit der Knopf nicht in den Scroller ragte —
       diese Zone war der Ballast, den Alex sieht.

       Jetzt schwebt er: absolut am unteren Rand des Umschlags verankert, ragt
       nach oben hinaus, nimmt im Layout keinen Platz. Textzeile und Fuss sind
       so hoch wie ihr Inhalt.

       DAS EIGENE KOMPOSITIONS-LAYER IST DER KERN, nicht Zierde: Ohne
       `translateZ` hat iOS den Scroller ÜBER den überstehenden Knopf gemalt,
       und er sah an der Trennlinie abgeschnitten aus (Alex 2026-06-22). Genau
       dagegen gab es die reservierte Zone. Das Problem ist nicht verschwunden
       — es ist über Stapelung gelöst statt über Höhe. */
    position: absolute;
    right: 8px;
    bottom: var(--mic-solo-lift);
    margin: 0;
    z-index: 3;
    transform: translateZ(0);
    will-change: transform;
  }

  /* Die Textzeile weicht dem schwebenden Knopf aus, statt unter ihm zu liegen. */
  .input-bar-wrap:has(.input-action.mic-solo) .input-row { padding-right: 78px; }
  .input-bar-wrap .input-action.mic-primary.mic-solo svg {
    width: 30px;
    height: 30px;
  }
  /* Solo-mic layout: move the divider OFF the wrap-top and onto the input
     row (= textbox level), and give the wrap top-padding so the tall mic
     rises ABOVE the line but stays INSIDE the wrap. Earlier it overflowed
     into the .content-stream scroller, which on iOS composites + painted
     OVER the mic → the button looked sliced at the line (Alex 2026-06-22).
     Keeping it inside the wrap avoids the scroller entirely. */
  .input-bar-wrap:has(.input-action.mic-solo),
  .agent-footer .input-bar-wrap:has(.input-action.mic-solo) {
    border-top: none;
    /* KEINE reservierte Mic-Zone mehr (#1333, Bild 120614).
       Alex: „Der Button darf über Conversation und Footer hinausragen, soll
       aber die Footer-/Textbox-Höhe nicht vergrössern." Die 34 px waren genau
       diese Reservierung. Der Knopf schwebt jetzt absolut und braucht im
       Layout keinen Platz; der Umschlag ist nur noch sein Anker und darf
       nicht beschneiden. */
    padding-top: 0;
    overflow: visible;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    /* The 34px mic-band is TRANSPARENT and overlaps the transcript (negative
       margin) instead of being an opaque strip that hides the last message
       (Alex 2026-07-03, green-marked screenshot). pointer-events pass through
       the empty band so the transcript stays scrollable/tappable there; the
       real rows below re-enable their own events + paint their own surface. */
    background: transparent;
    margin-top: 0;
    position: relative;
    pointer-events: none;
  }
  .input-bar-wrap:has(.input-action.mic-solo) > * {
    pointer-events: auto;
  }
  /* ONE continuous glass pane from below the clear mic-band to the wrap's very
     bottom — including the safe-area/padding-bottom zone, which used to be an
     unblurred "hole" showing raw transcript (Alex 2026-07-03). Rows sit on top
     of it and stay transparent; .queue-banner keeps its own tint. */
  .input-bar-wrap:has(.input-action.mic-solo)::before {
    content: '';
    position: absolute;
    /* SO HOCH WIE DER UEBERSTAND, NICHT MEHR.
       ANLASS (Alex, 28.08., Bild 120934): „Der Glasmorphism-Effekt ist im
       Footer nur bis zur Haelfte der Hoehe drinnen, da ist etwas verschoben."

       Der Knopf haengt `bottom: var(--mic-solo-lift)` und ist
       `var(--mic-solo-size)` hoch; sein Oberrand liegt also (Groesse + Abstand)
       ueber der Unterkante des Umschlags. Nur der Teil DAVON, der ueber den
       Umschlag hinausragt, darf glasfrei bleiben — damit die letzte Nachricht
       hinter dem Knopf lesbar bleibt (Alex, 03.07.).

       `100%` loest hier gegen die HOEHE DES UMSCHLAGS auf. Ist der Umschlag
       hoch genug, wird die Differenz negativ, `max()` klemmt auf 0 und das
       Glas deckt alles — genau der Fall, der vorher einen Spalt offen liess.

       Die feste 34 konnte das nicht wissen: Sie stimmte fuer EINE Geometrie
       und war ueberall sonst falsch. Jetzt kann sie nicht mehr driften, weil
       sie aus denselben Variablen kommt wie der Knopf. */
    top: max(0px, calc(var(--mic-solo-size) + var(--mic-solo-lift) - 100%));
    left: 0;
    right: 0;
    bottom: 0;
    background: color-mix(in srgb, var(--surface) 72%, transparent);
    -webkit-backdrop-filter: blur(14px) saturate(1.5);
    backdrop-filter: blur(14px) saturate(1.5);
    pointer-events: none;
  }
  .input-bar-wrap:has(.input-action.mic-solo) > *:not(.queue-banner) {
    background: transparent;
    position: relative; /* paint above the ::before glass pane */
  }
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .input-bar-wrap:has(.input-action.mic-solo)::before { background: var(--surface); }
  }
  .input-bar-wrap:has(.input-action.mic-solo) .input-bar {
    border-top: 1px solid var(--border);
  }

  .input-bar-wrap .input-field {
    min-width: 0;
  }

  .key-row {
    padding: 6px 12px;
    gap: 4px;
  }

  .key-btn {
    padding: 4px 8px;
    font-size: 10px;
  }

  .attachment-row {
    padding: 8px 12px;
  }

  .recording-bar,
  .transcribing-bar,
  .review-bar {
    padding-left: 12px;
    padding-right: 12px;
  }

  .cmd-menu {
    right: -8px;
    min-width: 180px;
  }
}

/* When the input is empty the send arrow is hidden and the mic is the primary
   action: a ROUND ORANGE button (contrast to the square elements; orange = the
   record indicator). Same footprint as the other buttons so it stays in the
   bar — no overflow over the divider, stable on desktop too (Alex 2026-06-22). */
.input-bar-wrap .input-action.mic-primary {
  /* Follows the user's accent / active main color (Alex 2026-06-22). */
  background: var(--accent);
  border-color: var(--accent);
  color: var(--white);
  border-radius: 50%;
}
/* Subtle "alive" animation on the mic fill (Alex 2026-07-03): a soft light sweep
   drifting across the accent + a gentle breathing glow. Slow (6s), low contrast —
   noticeable at a glance, never distracting. Static for reduced-motion users. */
@media (prefers-reduced-motion: no-preference) {
  .input-bar-wrap .input-action.mic-primary {
    background: linear-gradient(
      135deg,
      var(--accent) 0%,
      var(--accent) 32%,
      color-mix(in srgb, var(--accent) 74%, white) 50%,
      var(--accent) 68%,
      var(--accent) 100%
    );
    background-size: 300% 300%;
    animation: mic-breathe 6s ease-in-out infinite;
  }
  /* IN-FILL only (Alex 2026-07-03: kein Außen-Glow) — the light band drifts
     across the accent surface, nothing animates outside the button. */
  @keyframes mic-breathe {
    0%, 100% { background-position: 0% 100%; }
    50% { background-position: 100% 0%; }
  }
}
.input-bar-wrap .input-action.mic-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--white);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cmd-menu { background: var(--surface); }
}

/* Hinweis, dass ein Klick auf Senden auf den laufenden Upload wartet. Bewusst
   ruhig gehalten (kein Rot): es ist kein Fehler, sondern eine Zusage. */
.upload-pending-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 32px;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}


/* Höhe der schwebenden Safari-Adressleiste bei offener Tastatur. Aus Alex'
   Bildschirmfoto 120051 abgemessen (Pille rund 26 CSS-Punkte hoch, dazu Rand)
   — eine gemessene Zahl, keine geratene, aber gerätespezifisch. Wenn sie auf
   einem anderen Gerät nicht passt, ist DIESE Zeile die Stellschraube. */
html.kb-open .input-bar-wrap { --kb-clearance: 44px; }

/* Hochformat: der Rand ist hier Luxus, der Senden-Knopf ist es nicht.
   32px Rand und 16px Abstände kosten zusammen 112px — mehr als der
   Knopf breit ist. */
@media (max-width: 480px) {
  .recording-bar {
    padding: 10px 12px;
    gap: 8px;
  }

  .voice-route-fixed,
  .voice-route-opt {
    padding: 4px 6px;
    letter-spacing: 0.04em;
  }
}
/* MultiChoice picker — Claude Code 2.1.x numbered prompt block.
 *
 * Original stylesheet was authored against a `--c-*` variable namespace
 * that never existed in cloud-v2 (variables.css uses `--text-primary`,
 * `--text-muted`, `--accent`, …). Result: every fallback kicked in and
 * picked dark-theme defaults (light grey, semi-transparent white) →
 * invisible on the V2 white background. Alex screenshot 110094.
 * 2026-06-02 — switched to the project variables. */

.mc-block {
  margin: 12px 0;
  border-left: 3px solid var(--accent);
  background: var(--bg-light);
  padding: 12px 14px;
  border-radius: 4px;
}

.mc-question {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 8px;
  line-height: 1.4;
}

.mc-options {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.mc-option {
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 8px 10px;
  cursor: pointer;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 12px;
  transition: background 0.12s ease, border-color 0.12s ease;
}

.mc-option:hover {
  background: var(--bg-light);
  border-color: var(--border-strong);
}

/* The user's actively chosen option after they clicked. Highlighted
 * red + bold so they can see what's in flight. Pre-click there is
 * NO selected state any more (Alex feedback 2026-06-02). */
.mc-option.chosen {
  border-color: var(--accent);
  background: var(--accent-bg);
}

/* Whole-block sending state — the un-chosen options dim out so the
 * focus stays on the one being sent. */
.mc-block.is-sending .mc-option:not(.chosen) {
  opacity: 0.4;
}

.mc-option:disabled {
  cursor: not-allowed;
}

.mc-option:disabled:hover {
  background: var(--surface);
  border-color: var(--border);
}

.mc-block.is-sending .mc-option.chosen:hover {
  background: var(--accent-bg);
  border-color: var(--accent);
}

.mc-option-spin {
  display: inline-flex;
  align-items: center;
  color: var(--accent);
  margin-left: 4px;
}

.mc-option-spin svg {
  animation: mc-spin 0.9s linear infinite;
}

@keyframes mc-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.mc-option-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.mc-option-num {
  font-weight: 700;
  color: var(--accent);
  min-width: 18px;
}

.mc-option-label {
  flex: 1;
  font-weight: 600;
  color: var(--text-body);
}

.mc-option-desc {
  margin-top: 4px;
  padding-left: 26px;
  font-size: 12px;
  color: var(--text-primary);
  line-height: 1.45;
}

.mc-hint {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-muted);
  font-style: italic;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

/* Esc/dismiss (Alex 2026-07-16: no Escape key on mobile) — quiet ghost button,
   flat/square per style guide; generous hit area for touch. */
.mc-esc {
  flex-shrink: 0;
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  color: var(--text-muted);
  font-size: 11px;
  font-style: normal;
  padding: 5px 10px;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease;
}
.mc-esc:hover {
  color: var(--text-primary);
  border-color: var(--text-primary);
}

/* Abgelehnter Klick (409) — dieselbe Form wie im Erlaubnis-Block, damit beide
   Dialoge dasselbe Ereignis gleich aussehen lassen. Warnfarbe, nicht Fehler:
   Es ist nichts kaputt, der Dialog ist nur weitergezogen. */
.mc-stale {
  margin-top: 8px;
  padding: 7px 10px;
  border: 1px solid var(--color-warning, #b58900);
  background: var(--color-warning-bg, rgba(181, 137, 0, 0.08));
  font-size: 12.5px;
}
/* Permission gate — Claude Code "Do you want to proceed?" approval prompt.
 * Deliberately louder than .mc-block: this is a BLOCKING state (the agent
 * is halted), so it gets the warning colour, a shield icon, and a header
 * label that names what's happening — the user must notice it (Cloud IACP
 * 0d45d2ef: it used to masquerade as plain input). Uses the project
 * variables (see MultiChoiceBlock.css note on the dead --c-* namespace). */

.perm-block {
  margin: 12px 0;
  border: 1px solid var(--color-warning, #d97706);
  border-left: 3px solid var(--color-warning, #d97706);
  background: var(--color-warning-bg, rgba(217, 119, 6, 0.08));
  padding: 12px 14px;
  border-radius: 4px;
}

.perm-head {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 8px;
}
.perm-head-icon {
  color: var(--color-warning, #d97706);
  flex-shrink: 0;
}
.perm-head-label {
  font-family: var(--font-heading, inherit);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-warning, #d97706);
}

.perm-question {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 8px;
  line-height: 1.4;
}

/* The thing being approved — command / file / tool arg. Monospaced so a
 * shell command or path reads correctly; scrolls instead of wrapping ugly. */
.perm-context {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-bottom: 10px;
  padding: 6px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow-x: auto;
}
.perm-context-tool {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}
.perm-context-code {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
  white-space: pre;
}

.perm-options {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.perm-option {
  display: flex;
  align-items: center;
  gap: 8px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 8px 10px;
  cursor: pointer;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 12px;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.perm-option:hover {
  background: var(--bg-light);
  border-color: var(--border-strong);
}

/* Cosmetic affirm/deny hint — NOT load-bearing (the digit sent is the
 * truth; colour is inferred from position/label only). */
.perm-option.primary {
  border-color: var(--color-success, #16a34a);
}
.perm-option.primary .perm-option-num {
  background: var(--color-success, #16a34a);
}
.perm-option.deny .perm-option-num {
  background: var(--text-muted);
}

.perm-option.chosen {
  border-color: var(--color-warning, #d97706);
  background: var(--color-warning-bg, rgba(217, 119, 6, 0.08));
}
.perm-block.is-sending .perm-option:not(.chosen) {
  opacity: 0.4;
}
.perm-option:disabled {
  cursor: not-allowed;
}
.perm-option:disabled:hover {
  background: var(--surface);
  border-color: var(--border);
}

.perm-option-num {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 3px;
  background: var(--accent);
  color: var(--white);
  font-weight: 700;
  font-size: 11px;
}
.perm-option-label {
  flex: 1;
  font-weight: 600;
  color: var(--text-body);
  line-height: 1.4;
}
.perm-option-spin {
  display: inline-flex;
  align-items: center;
  color: var(--color-warning, #d97706);
}
.perm-option-spin svg {
  animation: perm-spin 0.9s linear infinite;
}
@keyframes perm-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.perm-hint {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-muted);
  font-style: italic;
}

/* Weitreichende Optionen („nicht mehr fragen", „Ordner vertrauen"):
   sichtbar abgehoben, damit ein Fehlklick nicht so leicht ist wie ein
   normaler (Vertrag mit Cloud, 18.08.). */
.perm-option.risky {
  border-color: var(--color-error, #d81b16);
  color: var(--color-error, #d81b16);
}
.perm-stale {
  margin-top: 8px;
  padding: 7px 10px;
  border: 1px solid var(--color-warning, #b58900);
  background: var(--color-warning-bg, rgba(181,137,0,0.08));
  font-size: 12.5px;
}
/* Theme-aware via the app's REAL tokens. The old --c-* vars never existed in
   variables.css, so the DARK fallbacks (#e5e7eb text on near-transparent bg)
   always applied → unreadable in light mode, worse over ambient (Alex
   2026-07-15 "kann unten den Vorschlag nicht lesen"). */
.sb-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 6px;
  padding: 8px 12px;
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  line-height: 1.45;
}

.sb-marker {
  color: var(--accent);
  font-weight: 700;
  font-size: 14px;
  flex-shrink: 0;
}

/* Don't stretch to fill — Alex wants the button hugging the text,
 * not pushed against the right margin. */
.sb-content {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-text {
  color: var(--text-primary);
}

.sb-ghost {
  color: var(--text-muted);
  font-style: italic;
}

.sb-send {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  background: var(--text-primary, #111);
  color: var(--white, #fff);
  border: none;
  border-radius: 3px;
  padding: 0;
  cursor: pointer;
  transition: opacity 0.12s ease;
}

.sb-send:hover {
  opacity: 0.85;
}

.sb-send:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
/* Sent feedback: green check, full opacity (overrides the disabled fade). */
.sb-send.sent {
  background: var(--color-success, #16A34A);
  opacity: 1;
}
.sb-spin { animation: sb-spin 0.8s linear infinite; }
@keyframes sb-spin { to { transform: rotate(360deg); } }

/* WARTENDE EINGABEN (Cloud-Vertrag 57b87dc).
   Bewusst NICHT wie ein Zug gesetzt — der ganze Fehler bestand darin, dass
   eine geparkte Eingabe wie ein Nutzer-Zug AUSSAH („USER INPUT", Alex
   25.08.). Gedaempft, eingerueckt, mit Warteschlangen-Symbol: sichtbar
   vorhanden, erkennbar noch nicht geschehen. */
.sb-queued { display: flex; flex-direction: column; gap: 2px; padding: 4px 8px 2px; }
.sb-queued-row { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.sb-queued-marker { color: var(--text-muted); opacity: 0.7; flex-shrink: 0; }
.sb-queued-text {
  color: var(--text-muted); font-size: 12px; font-style: italic;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.sb-queued-note {
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted); opacity: 0.65;
  flex-shrink: 0; margin-left: auto;
}
/* Wizard step indicator — Claude Code 2.1.x.
 *
 * Same fix as MultiChoiceBlock.css: replaced the never-defined `--c-*`
 * variable namespace with the project variables from variables.css.
 * The three step-dots Alex saw in screenshot 110094 were rendered as
 * `var(--c-muted, #9ca3af)` over the V2 white background → almost
 * invisible. The "active step / submit step" was the same colour as
 * the body text → no visual cue. 2026-06-02. */

.sp-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 0 6px;
  padding: 6px 10px;
  background: var(--bg-light);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.4;
}

.sp-nav {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  padding: 0;
  transition: background 0.12s ease, border-color 0.12s ease;
}

.sp-nav:hover {
  background: var(--bg-light);
  border-color: var(--border-strong);
}

.sp-steps {
  flex: 1 1 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sp-step {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}

.sp-marker {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  font-family: var(--font-mono);
  min-width: 12px;
  text-align: center;
}

.sp-label {
  font-family: var(--font-mono);
  color: var(--text-primary);
}

/* State styling */
.sp-step-done .sp-marker {
  color: var(--color-success);
}
.sp-step-done .sp-label {
  color: var(--text-muted);
  text-decoration: line-through;
  text-decoration-color: var(--border-strong);
}

.sp-step-active .sp-marker {
  color: var(--accent);
}
.sp-step-active .sp-label {
  color: var(--accent);
  font-weight: 700;
}

.sp-step-pending .sp-marker {
  color: var(--text-muted);
}
.sp-step-pending .sp-label {
  color: var(--text-muted);
}

.sp-step-failed .sp-marker {
  color: var(--color-error);
}
.sp-step-failed .sp-label {
  color: var(--color-error);
}

.sp-step-unknown .sp-marker,
.sp-step-unknown .sp-label {
  color: var(--text-muted);
  font-style: italic;
}
/* Verlauf des Zugangs im Login-Dialog. Jüngster Schritt oben — Menschen lesen
   von oben, und die letzte Ursache ist die interessanteste. */

.tkc {
  border-top: 1px solid var(--border);
  margin-top: 10px;
  padding-top: 8px;
}

.tkc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }

.tkc-title {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

.tkc-fp {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-muted);
  opacity: 0.7;
}

.tkc-summary { font-size: 12px; margin-bottom: 6px; }
.tkc-empty, .tkc-err { font-size: 11px; color: var(--text-muted); line-height: 1.45; }
.tkc-err { color: var(--error, #dc2626); }

.tkc-list { list-style: none; margin: 0; padding: 0; max-height: 190px; overflow-y: auto; }

.tkc-step {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 3px 0 3px 8px;
  border-left: 2px solid var(--border);
  font-size: 11px;
}

/* Der Ausgang trägt die Farbe, nicht der Schritt — „gescheitert" ist die
   Information, „Prüfung" nicht. */
.tkc-step.outcome-failed { border-left-color: var(--error, #dc2626); }
.tkc-step.outcome-ok { border-left-color: var(--success, #16a34a); }
.tkc-step.outcome-deferred { border-left-color: var(--color-warning, #d97706); }

.tkc-when { flex: none; font-family: var(--font-mono); font-size: 9px; color: var(--text-muted); min-width: 76px; }
.tkc-what { flex: none; }
.tkc-count { margin-left: 4px; font-family: var(--font-mono); font-size: 9px; color: var(--text-muted); }
.tkc-outcome { flex: none; font-family: var(--font-mono); font-size: 9px; color: var(--text-muted); }
.tkc-detail {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-muted);
}
/* DER DIALOG MUSS IN DEN SICHTBAREN BEREICH PASSEN, nicht in den
   Layout-Bereich (Alex, #1281: „sobald man auf das Eingabefenster klickt …
   öffnet sich die Tastatur, die überlagert dann den Bereich … ich kann den
   Key nicht einsetzen").
   `inset: 0` bezieht sich auf den LAYOUT-Viewport, und der schrumpft auf iOS
   beim Öffnen der Tastatur NICHT. Der Dialog blieb also stehen, wo er war,
   und die Tastatur legte sich darüber — samt Eingabefeld.
   `--vh` ist die zoombereinigte Höhe des SICHTBAREN Bereichs (main.tsx, folgt
   visualViewport). Damit endet der Dialog dort, wo die Tastatur beginnt. */
.lgm-backdrop {
  position: fixed;
  inset: 0;
  height: calc(var(--vh, 1vh) * 100);
  z-index: 3000;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: max(48px, 10vh) 16px 16px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Mit offener Tastatur ist oben kein Platz zu verschenken: aus max(48px,10vh)
   werden 8px. Das sind auf einem Telefon bis zu 80px, die dem Eingabefeld
   fehlen würden. */
html.kb-open .lgm-backdrop {
  padding-top: 8px;
  align-items: flex-start;
}

.lgm-modal {
  width: min(560px, 100%);
  background: var(--surface);
  border: 1px solid var(--border);
  /* flat/square house style */
  border-radius: 0;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
  /* Passt der Inhalt nicht, scrollt der Dialog — vorher wuchs er aus dem
     Bild heraus und das Untere war unerreichbar. */
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.lgm-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.lgm-title { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; font-size: 14px; color: var(--text-primary); }
.lgm-x { background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 2px; display: inline-flex; }
.lgm-x:hover { color: var(--text-primary); }

.lgm-body { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.lgm-center { align-items: center; text-align: center; gap: 12px; padding: 32px 16px; color: var(--text-primary); font-size: 14px; }
.lgm-muted { color: var(--text-muted); }

.lgm-ctx { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); }

/* Auto-flow progress header (mode=both). Colored by state; sits above the manual
   section which stays visible the whole time (no switching, #1276). */
.lgm-auto {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  line-height: 1.4;
  padding: 8px 10px;
  border-left: 3px solid var(--color-info);
  background: var(--bg-light);
}
.lgm-auto-icon { flex-shrink: 0; font-weight: 700; }
.lgm-auto-info { border-left-color: var(--color-info); color: var(--text-primary); }
.lgm-auto-warn { border-left-color: var(--color-warning); color: var(--color-warning); }
.lgm-auto-err { border-left-color: var(--color-error); color: var(--color-error); }
.lgm-auto-ok { border-left-color: var(--color-success); color: var(--color-success); }

.lgm-step { font-size: 13px; color: var(--text-primary); line-height: 1.4; display: flex; gap: 7px; align-items: baseline; }
.lgm-step code { font-family: var(--font-mono); font-size: 11.5px; background: var(--bg-light); padding: 0 4px; }
.lgm-num {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  width: 18px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--chip-active-bg); color: var(--white);
}

.lgm-url-row { display: flex; align-items: stretch; gap: 6px; }
.lgm-url {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--color-info);
  background: var(--bg-light);
  border: 1px solid var(--border);
  padding: 8px 10px;
  word-break: break-all;
  line-height: 1.4;
  text-decoration: none;
}
.lgm-url:hover { text-decoration: underline; }
.lgm-copy {
  flex-shrink: 0;
  background: var(--chip-active-bg);
  color: var(--white);
  border: none;
  padding: 0 12px;
  cursor: pointer;
  display: inline-flex; align-items: center;
}
.lgm-copy:hover { background: var(--black); }

.lgm-input {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
  background: var(--bg-light);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 9px 11px;
  resize: vertical;
  width: 100%;
  box-sizing: border-box;
}
.lgm-input:focus { outline: none; border-color: var(--accent); }
.lgm-input:disabled { opacity: 0.6; }

.lgm-btn {
  align-self: flex-start;
  font-size: 13px;
  font-weight: 600;
  padding: 8px 18px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-primary);
  border-radius: 0;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.lgm-btn:hover { border-color: var(--text-primary); }
.lgm-btn:disabled { opacity: 0.5; cursor: default; }
.lgm-primary { background: var(--chip-active-bg); color: var(--white); border-color: var(--text-primary); }
.lgm-primary:hover { background: var(--black); }

.lgm-done { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-primary); }
.lgm-ok { color: var(--color-success); flex-shrink: 0; }
.lgm-err { color: var(--color-error); font-size: 13.5px; }

/* Post-paste verify verdict (verify-login, #1276). */
.lgm-verified { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
.lgm-vfail { display: flex; flex-direction: column; gap: 9px; font-size: 13px; line-height: 1.4; }
.lgm-vfail-err { color: var(--color-error); }
.lgm-vfail-warn { color: var(--color-warning); }
.lgm-vfail-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.lgm-spin { animation: lgm-spin 0.9s linear infinite; flex-shrink: 0; }
@keyframes lgm-spin { to { transform: rotate(360deg); } }

/* Der Verlauf sitzt oben im Dialog und darf ihn nicht dominieren: kein eigener
   Rahmen, kein Abstand nach oben — er hängt an der Titelzeile. */
.lgm-chain-slot { padding-top: 0; padding-bottom: 0; }
.lgm-chain-slot .tkc { margin-top: 0; border-top: 0; }
/* AgentOS loading wave (Alex 2026-07-15) — the amber voice-wave as a loader.
   Five rounded bars pulse in a travelling wave: each bar scales up and glows as
   the wave passes through, echoing the mic/wave brand icon. Accent-driven so it
   follows the user's accent colour. */
.aos-wave {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.aos-wave-bars {
  display: flex;
  align-items: center; /* bars grow from the middle, like a waveform */
  gap: 5px;
  height: 34px;
}

.aos-wave-bars span {
  width: 6px;
  height: 100%;
  border-radius: 3px;
  background: var(--accent);
  transform: scaleY(0.25);
  transform-origin: center;
  animation: aos-wave-pulse 1.15s ease-in-out infinite;
  opacity: 0.85;
  will-change: transform, opacity;
}

/* Travelling wave: stagger each bar so the crest runs left → right, and let the
   resting opacity fall off to the right like the brand icon's fade. */
.aos-wave-bars span:nth-child(1) { animation-delay: 0s;    }
.aos-wave-bars span:nth-child(2) { animation-delay: 0.12s; }
.aos-wave-bars span:nth-child(3) { animation-delay: 0.24s; }
.aos-wave-bars span:nth-child(4) { animation-delay: 0.36s; }
.aos-wave-bars span:nth-child(5) { animation-delay: 0.48s; }

@keyframes aos-wave-pulse {
  0%, 100% { transform: scaleY(0.25); opacity: 0.45; }
  35%      { transform: scaleY(1);    opacity: 1;    }
  70%      { transform: scaleY(0.4);  opacity: 0.6;  }
}

.aos-wave-label {
  font-size: 13px;
  color: var(--text-muted);
  letter-spacing: 0.02em;
}

/* Sizes */
.aos-wave-sm .aos-wave-bars { height: 18px; gap: 3px; }
.aos-wave-sm .aos-wave-bars span { width: 4px; border-radius: 2px; }
.aos-wave-sm { gap: 8px; }
.aos-wave-lg .aos-wave-bars { height: 48px; gap: 7px; }
.aos-wave-lg .aos-wave-bars span { width: 8px; border-radius: 4px; }

/* Reduced motion: calm static wave silhouette instead of animation. */
@media (prefers-reduced-motion: reduce) {
  .aos-wave-bars span { animation: none; }
  .aos-wave-bars span:nth-child(1) { transform: scaleY(1);    opacity: 1;   }
  .aos-wave-bars span:nth-child(2) { transform: scaleY(0.8);  opacity: 0.85;}
  .aos-wave-bars span:nth-child(3) { transform: scaleY(0.55); opacity: 0.7; }
  .aos-wave-bars span:nth-child(4) { transform: scaleY(0.35); opacity: 0.55;}
  .aos-wave-bars span:nth-child(5) { transform: scaleY(0.25); opacity: 0.4; }
}
.iacp-event-card {
  position: relative;
  margin: 6px 0;
  padding: 10px 14px;
  background: var(--bg-light);
  border-left: 3px solid var(--accent);
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-primary);
}

.iacp-event-card.requires-response {
  border-top: 2px solid var(--color-error);
}

.iacp-event-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 8px;
}

.iacp-event-icon {
  display: inline-flex;
  color: var(--accent);
}

.iacp-event-sender {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text-primary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 11px;
}

.iacp-event-badge {
  font-family: var(--font-mono);
  font-size: 9px;
  padding: 1px 6px;
  background: var(--accent);
  color: var(--white);
  border-radius: 3px;
  letter-spacing: 0.08em;
}

.iacp-event-spacer { flex: 1; }

.iacp-event-needs-response {
  font-family: var(--font-mono);
  font-size: 9px;
  padding: 2px 6px;
  background: var(--color-error);
  color: var(--white);
  border-radius: 3px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.iacp-event-time {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}

.iacp-event-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}

.iacp-author-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
}

.iacp-author-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-muted);
}

.iacp-author-chip.prefix-agent .iacp-author-dot { background: var(--color-info); }
.iacp-author-chip.prefix-user .iacp-author-dot { background: var(--color-success); }
.iacp-author-chip.prefix-system .iacp-author-dot { background: var(--border-strong); }
.iacp-author-chip.prefix-human .iacp-author-dot { background: var(--color-warning); }

.iacp-trigger-badge {
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--bg-inset);
  color: var(--text-muted);
  border: 1px solid var(--border);
}

.iacp-trigger-badge.trigger-agent_write { background: rgba(255, 158, 100, 0.12); color: #c25a1d; border-color: rgba(255, 158, 100, 0.4); }
.iacp-trigger-badge.trigger-user_write  { background: rgba(122, 162, 247, 0.14); color: #2c5ab8; border-color: rgba(122, 162, 247, 0.4); }
.iacp-trigger-badge.trigger-newline_pause { background: rgba(245, 211, 110, 0.18); color: #8c6d10; border-color: rgba(245, 211, 110, 0.5); }

.iacp-event-body {
  color: var(--text-primary);
  white-space: pre-wrap;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.iacp-event-body.expanded {
  display: block;
  -webkit-line-clamp: unset;
  overflow: visible;
}

.iacp-event-more {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 11px;
  padding: 2px 0 0;
  text-decoration: underline;
}

.iacp-event-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}

.iacp-event-open {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
}

.iacp-event-open:hover { text-decoration: underline; }

/* ── Section-aware extensions (Content IACP f8203b07) ──────────────
 * IacpEventCard now routes its body render by section_role:
 *   start  → SectionOpener with type-badge + attrs chips
 *   content→ plain markdown
 *   reply  → ReplyBlock with author+timestamp from XML attrs
 *   end    → collapsed boundary line (no body)
 * Header decoration adds a small section-type chip + the role tag. */

/* Type chips — share style, differentiate by colour */
.iacp-section-type {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 3px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  background: var(--bg-inset);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
}
.iacp-section-type.type-product    { background: rgba(22,163,74,0.10);  color: var(--color-success); border-color: rgba(22,163,74,0.3); }
.iacp-section-type.type-question   { background: rgba(37,99,235,0.10);  color: var(--color-info);    border-color: rgba(37,99,235,0.3); }
.iacp-section-type.type-task       { background: rgba(217,119,6,0.10);  color: var(--color-warning); border-color: rgba(217,119,6,0.3); }
.iacp-section-type.type-annotation { background: rgba(107,33,168,0.10); color: #6b21a8;              border-color: rgba(107,33,168,0.3); }
.iacp-section-type.type-vote       { background: rgba(196,30,58,0.10);  color: var(--accent);        border-color: rgba(196,30,58,0.3); }

.iacp-section-role {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  padding: 1px 5px;
  border-radius: 2px;
  text-transform: lowercase;
  background: var(--bg-inset);
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.iacp-section-role.role-start  { color: var(--color-success); border-color: rgba(22,163,74,0.3); }
.iacp-section-role.role-reply  { color: #6b21a8; border-color: rgba(107,33,168,0.3); }
.iacp-section-role.role-end    { color: var(--text-muted); }

.iacp-your-role {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  padding: 1px 5px;
  border-radius: 2px;
  background: var(--accent-bg);
  color: var(--accent);
  border: 1px solid var(--accent-bg-strong);
  text-transform: lowercase;
}

/* targets / primary_recipient row */
.iacp-targets-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 8px;
  font-family: var(--font-mono);
  font-size: 10px;
}
.iacp-target-chip {
  padding: 1px 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 2px;
  color: var(--text-muted);
}
.iacp-target-chip.primary {
  background: var(--accent-bg);
  border-color: var(--accent-bg-strong);
  color: var(--accent);
  font-weight: 600;
}

/* Reply block — visually distinct via background + the lila ↩ icon
 * in the head. NO inner left-border because the outer card already
 * has one and two parallel vertical lines read as visual noise
 * (Alex feedback screenshot 110113). */
.iacp-reply-block {
  margin: 4px 0 6px;
  padding: 6px 10px;
  background: var(--surface);
  border-radius: 3px;
}

.iacp-reply-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}
.iacp-reply-icon { color: var(--accent); }
.iacp-reply-by   { font-weight: 600; color: var(--text-primary); }
.iacp-reply-at   { color: var(--text-muted); }

.iacp-reply-body {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-primary);
  /* Collapsed: 4-line clamp via plain-block render; markdown-aware
   * clamp uses max-height to avoid breaking nested block layout. */
  max-height: 6.2em;
  overflow: hidden;
}
.iacp-reply-body.expanded { max-height: none; overflow: visible; }

/* Section opener — shows the attrs of a <section …> opener at start
 * of a new section. */
.iacp-section-opener {
  margin: 4px 0 6px;
}
.iacp-section-opener-head {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-bottom: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}
.iacp-section-id {
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 1px 5px;
  border-radius: 2px;
  font-size: 10px;
}
.iacp-section-status {
  padding: 1px 5px;
  border-radius: 2px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  background: var(--bg-inset);
  border: 1px solid var(--border);
}
.iacp-section-status.status-open       { color: var(--color-info); border-color: rgba(37,99,235,0.3); }
.iacp-section-status.status-in_progress{ color: var(--color-warning); border-color: rgba(217,119,6,0.3); }
.iacp-section-status.status-done       { color: var(--color-success); border-color: rgba(22,163,74,0.3); }
.iacp-section-status.status-blocked    { color: var(--color-error); border-color: rgba(220,38,38,0.3); }

.iacp-section-initiator {
  font-style: italic;
}

/* Markdown body inside the card — same prose styles as PromptInspector
 * but at a slightly smaller scale because the card is constrained. */
.iacp-event-body-md {
  /* Override the plain-text clamp; markdown gets max-height instead so
   * block formatting (lists, headings, code) doesn't break mid-line. */
  display: block;
  max-height: 6.2em;
  -webkit-line-clamp: unset;
  overflow: hidden;
  white-space: normal;
}
.iacp-event-body-md.expanded { max-height: none; overflow: visible; }

.iacp-event-body-md > :first-child { margin-top: 0; }
.iacp-event-body-md > :last-child  { margin-bottom: 0; }

.iacp-event-body-md h1,
.iacp-event-body-md h2,
.iacp-event-body-md h3,
.iacp-event-body-md h4 {
  font-family: var(--font-heading);
  font-weight: 600;
  margin: 10px 0 4px;
  line-height: 1.25;
  color: var(--text-primary);
}
.iacp-event-body-md h1 { font-size: 15px; }
.iacp-event-body-md h2 { font-size: 14px; }
.iacp-event-body-md h3 { font-size: 13px; }
.iacp-event-body-md h4 { font-size: 12px; color: var(--text-muted); }

.iacp-event-body-md p { margin: 0 0 6px; }
.iacp-event-body-md ul,
.iacp-event-body-md ol { margin: 0 0 6px; padding-left: 18px; }
.iacp-event-body-md li { margin: 1px 0; }
.iacp-event-body-md code {
  font-family: var(--font-mono);
  font-size: 11px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 0 4px;
  border-radius: 2px;
}
.iacp-event-body-md pre {
  margin: 6px 0;
  padding: 8px 10px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 11px;
}
.iacp-event-body-md pre code { background: none; border: none; padding: 0; }
.iacp-event-body-md a { color: var(--accent); text-decoration: none; }
.iacp-event-body-md a:hover { text-decoration: underline; }

/* Reply body mirrors the markdown prose so its nested replies look the
 * same as the parent card's body. */
.iacp-reply-body > :first-child { margin-top: 0; }
.iacp-reply-body > :last-child  { margin-bottom: 0; }
.iacp-reply-body p              { margin: 0 0 4px; }
.iacp-reply-body h1,
.iacp-reply-body h2,
.iacp-reply-body h3,
.iacp-reply-body h4 {
  font-family: var(--font-heading);
  font-weight: 600;
  margin: 8px 0 4px;
  font-size: 13px;
  color: var(--text-primary);
}
.iacp-reply-body code {
  font-family: var(--font-mono);
  font-size: 11px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 0 4px;
  border-radius: 2px;
}

/* End-marker — minimal, full-width separator */
.iacp-event-card-end {
  padding: 4px 14px;
  background: transparent;
  border-left: 3px solid var(--border);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.05em;
  text-align: center;
}
.iacp-section-end {
  display: inline-block;
}

/* Kopf-Änderung ohne Fliesstext (Status, Freigaben, Eigentum). Vorher blieb
   die Karte hier leer — sichtbar war nur, DASS etwas passiert ist. */
.iacp-attr-change {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 6px 0 2px;
  font-size: 11px;
}

.iacp-attr-change-lead {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.iacp-attr-chip {
  padding: 1px 6px;
  border: 1px solid var(--border);
  color: var(--text-muted);
}

.iacp-attr-chip strong { color: var(--text-primary); font-weight: 600; }
/* Arcturian-Zustellung. Eigene Kontur, damit sie sich von normalem IACP
   unterscheidet — sie kommt im Auftrag eines Menschen, nicht von einem Agenten
   aus eigenem Antrieb. Flach und eckig wie der Rest der Oberfläche. */

.arcmsg {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent, #3b82f6);
  margin: 8px 0;
  background: var(--surface);
}

.arcmsg-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 6px 12px;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.arcmsg-persona { color: var(--accent, #3b82f6); font-weight: 600; }

.arcmsg-behalf {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
  font-size: 11px;
}

.arcmsg-channel {
  margin-left: auto;
  padding: 1px 5px;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 9px;
}

/* Lesegrösse und Fliesstext — das ist der Teil, für den die Nachricht da ist. */
.arcmsg-body {
  padding: 10px 12px;
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

.arcmsg-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  padding: 5px 12px;
  border: 0;
  border-top: 1px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: pointer;
  text-align: left;
}

.arcmsg-toggle:hover { color: var(--text-primary); }
.arcmsg-toggle svg { transition: transform 120ms linear; }
.arcmsg-toggle.open svg { transform: rotate(90deg); }

.arcmsg-fields {
  margin: 0;
  padding: 6px 12px 10px;
  border-top: 1px solid var(--border);
  display: grid;
  grid-template-columns: minmax(90px, auto) 1fr;
  gap: 3px 10px;
  font-family: var(--font-mono);
  font-size: 10px;
}

.arcmsg-field { display: contents; }
.arcmsg-field dt { color: var(--text-muted); }
.arcmsg-field dd { margin: 0; word-break: break-all; }

/* Der Antwortweg ist lang und für Menschen uninteressant — gedämpft. */
.arcmsg-field-wide dd { color: var(--text-muted); font-size: 9px; }

@media (max-width: 560px) {
  .arcmsg-fields { grid-template-columns: 1fr; gap: 1px; }
  .arcmsg-field dt { margin-top: 4px; }
}
.conversation-canvas-host {
  position: relative;
  overflow: hidden !important;
  padding: 0 !important;
  touch-action: none;
  cursor: grab;
  background:
    radial-gradient(circle at 50% 25%, color-mix(in srgb, var(--accent) 5%, transparent), transparent 48%),
    var(--bg);
}

.conversation-canvas-host:active { cursor: grabbing; }

.conversation-canvas-grid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}

.conversation-canvas-world {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  width: min(920px, calc(100vw - 32px));
  min-height: 0;
  padding:
    calc(var(--agent-hdr-h, 72px) + 28px)
    24px
    calc(var(--agent-ftr-h, 76px) + 28px);
  box-sizing: border-box;
  transform-origin: 0 0;
  will-change: transform;
  cursor: auto;
  contain: layout style;
}

/* The canvas is spatial, but the conversation remains the exact DOM renderer.
   A faint surface behind it preserves code/markdown contrast at deep zoom. */
.conversation-canvas-world::before {
  content: '';
  position: absolute;
  inset: calc(var(--agent-hdr-h, 72px) + 14px) 10px calc(var(--agent-ftr-h, 76px) + 14px);
  z-index: -1;
  border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  box-shadow: 0 22px 70px rgba(0, 0, 0, 0.12);
  pointer-events: none;
}

.conversation-canvas-primary {
  position: relative;
  z-index: 2;
  min-height: 1px;
}

.conversation-graph-layer {
  position: absolute;
  inset: 0 auto auto 0;
  z-index: 1;
  min-width: 1px;
  min-height: 1px;
  pointer-events: none;
}

.conversation-graph-edges {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: visible;
  pointer-events: none;
}

.conversation-graph-edge {
  fill: none;
  stroke: color-mix(in srgb, var(--accent) 72%, var(--text-muted));
  stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 2px 5px color-mix(in srgb, var(--accent) 25%, transparent));
}

.conversation-graph-edge.kind-content {
  stroke: color-mix(in srgb, var(--color-info) 68%, var(--text-muted));
  stroke-dasharray: 7 6;
}

#conversation-graph-arrow path {
  fill: color-mix(in srgb, var(--accent) 78%, var(--text-muted));
}

.conversation-graph-pane-position {
  position: absolute;
  z-index: 2;
  width: min(820px, calc(100vw - 64px));
  pointer-events: auto;
}

.conversation-agent-thought-board {
  position: absolute;
  z-index: 2;
  width: min(720px, calc(100vw - 64px));
  padding: 10px;
  box-sizing: border-box;
  border: 1px solid color-mix(in srgb, var(--border-strong) 82%, transparent);
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
  backdrop-filter: blur(18px) saturate(1.25);
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.16);
  pointer-events: auto;
}

.conversation-agent-thought-board > header {
  min-height: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 3px 9px;
  color: var(--text-muted);
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.conversation-agent-thought-board > header strong { color: var(--text-primary); }

.conversation-agent-thought-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(190px, 1fr));
  gap: 8px;
}

.conversation-agent-thought {
  position: relative;
  min-width: 0;
  min-height: 92px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 11px;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--conversation-agent-color) 42%, var(--border));
  border-left: 3px solid var(--conversation-agent-color);
  border-radius: 0;
  color: var(--text-primary);
  background: color-mix(in srgb, var(--surface) 90%, var(--conversation-agent-color) 10%);
  text-align: left;
  cursor: pointer;
}

.conversation-agent-thought:hover,
.conversation-agent-thought:focus-visible {
  border-color: var(--conversation-agent-color);
  background: color-mix(in srgb, var(--surface) 82%, var(--conversation-agent-color) 18%);
  outline: none;
}

.conversation-agent-thought-head {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.conversation-agent-thought-head strong {
  overflow: hidden;
  color: var(--conversation-agent-color);
  font: 700 11px/1.2 var(--font-mono);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-agent-thought-head > span {
  flex: none;
  color: var(--text-muted);
  font: 9px/1 var(--font-mono);
  text-transform: uppercase;
}

.conversation-agent-thought.state-thinking .conversation-agent-thought-head > span,
.conversation-agent-thought.state-tool .conversation-agent-thought-head > span {
  color: var(--accent);
}

.conversation-agent-thought-body {
  display: -webkit-box;
  overflow: hidden;
  color: var(--text-secondary);
  font: italic 11px/1.35 var(--font-sans);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

.conversation-agent-thought-body small {
  display: block;
  margin-bottom: 4px;
  color: var(--text-muted);
  font: 600 8px/1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.conversation-agent-thought-body.empty { color: var(--text-muted); }

.conversation-agent-link-port {
  position: absolute;
  left: -1px;
  top: 50%;
  width: 2px;
  height: 2px;
  pointer-events: none;
}

.conversation-graph-pane {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid color-mix(in srgb, var(--border-strong) 82%, transparent);
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.2);
}

.conversation-graph-pane-header {
  position: sticky;
  top: 0;
  z-index: 3;
  min-height: 42px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.25);
  backdrop-filter: blur(14px) saturate(1.25);
}

.conversation-graph-pane-header strong {
  color: var(--accent);
  font: 700 12px/1.2 var(--font-mono);
}

.conversation-graph-pane-header > span:not(.conversation-graph-pane-dot) {
  color: var(--text-muted);
  font: 10px/1 var(--font-mono);
}

.conversation-graph-pane-header .conversation-graph-window {
  padding-left: 7px;
  border-left: 1px solid var(--border);
  color: var(--text-muted);
  white-space: nowrap;
}

.conversation-graph-pane-header button {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid transparent;
  color: var(--text-muted);
  background: transparent;
  cursor: pointer;
}

.conversation-graph-pane-header button:first-of-type { margin-left: auto; }
.conversation-graph-pane-header button:hover,
.conversation-graph-pane-header button:focus-visible {
  border-color: var(--border-strong);
  color: var(--text-primary);
  outline: none;
}

.conversation-graph-pane-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 70%, transparent);
}

.conversation-graph-pane-content {
  max-height: clamp(420px, 68vh, 920px);
  overflow: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  padding: 18px 20px 28px;
}

.conversation-graph-load-older {
  position: sticky;
  top: 0;
  z-index: 2;
  display: block;
  margin: 0 auto 16px;
  padding: 7px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  color: var(--text-muted);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  font: 600 10px/1 var(--font-mono);
  cursor: pointer;
}

.conversation-graph-load-older:hover,
.conversation-graph-load-older:focus-visible {
  color: var(--text-primary);
  border-color: var(--accent);
  outline: none;
}

.conversation-graph-pane-state {
  padding: 24px;
  color: var(--text-muted);
  font: 11px/1.5 var(--font-mono);
  text-align: center;
}

.conversation-graph-pane-state.error { color: var(--color-error); }

[data-conversation-link-key] {
  scroll-margin: 24px;
}

.graph-active [data-conversation-link-key] {
  outline: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  outline-offset: 3px;
}

.conversation-canvas-controls {
  position: absolute;
  top: calc(var(--agent-hdr-h, 72px) + 10px);
  right: 12px;
  z-index: 7;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px;
  border: 1px solid var(--border-strong);
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.14);
  cursor: auto;
}

.conversation-canvas-controls button {
  min-width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: 0;
  color: var(--text-primary);
  background: transparent;
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  cursor: pointer;
}

.conversation-canvas-controls button:hover,
.conversation-canvas-controls button:focus-visible {
  border-color: var(--border-strong);
  background: var(--bg-light);
  outline: none;
}

.conversation-canvas-controls button.active {
  border-color: color-mix(in srgb, var(--accent) 68%, var(--border));
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.conversation-graph-add {
  max-width: 150px;
  height: 32px;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  padding: 0 8px;
  color: var(--text-primary);
  background: var(--surface);
  font: 600 10px/1 var(--font-mono);
}

.conversation-graph-edge-status {
  max-width: 132px;
  color: var(--text-muted);
  font: 9px/1.15 var(--font-mono);
  text-align: center;
}

.conversation-canvas-zoom {
  width: 42px;
  text-align: center;
  color: var(--text-muted);
  font: 10px/1 var(--font-mono);
}

@media (max-width: 600px) {
  .conversation-canvas-world {
    width: calc(100vw - 20px);
    padding-left: 14px;
    padding-right: 14px;
  }

  .conversation-canvas-controls {
    top: auto;
    right: 8px;
    bottom: calc(var(--agent-ftr-h, 76px) + 9px);
  }

  .conversation-canvas-controls button {
    width: 34px;
    padding: 0;
    font-size: 0;
  }

  .conversation-canvas-controls button svg { width: 15px; height: 15px; }

  .conversation-graph-add {
    width: 72px;
    max-width: 72px;
    padding: 0 4px;
  }

  .conversation-graph-edge-status { display: none; }

  .conversation-graph-pane-position { width: calc(100vw - 36px); }
  .conversation-agent-thought-board { width: calc(100vw - 36px); }
  .conversation-agent-thought-grid { grid-template-columns: 1fr; }
  .conversation-graph-pane-content {
    max-height: min(62dvh, 720px);
    padding: 12px 14px 22px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .conversation-canvas-world { will-change: auto; }
}
.conversation-timeline-event-icon {
  position: relative;
  width: 1em;
  height: 1em;
  display: inline-grid;
  place-items: center;
  line-height: 1;
}

.conversation-timeline-event-icon > svg {
  width: 100%;
  height: 100%;
}

.conversation-timeline-event-direction {
  position: absolute;
  z-index: 2;
  top: 50%;
  width: 1.25em;
  height: .82em;
  display: grid;
  place-items: center;
  color: var(--accent);
  filter: drop-shadow(0 0 2px color-mix(in srgb, var(--accent) 55%, transparent));
  pointer-events: none;
}

.conversation-timeline-event-direction > svg {
  width: 100%;
  height: 100%;
  stroke-width: 2.4;
}

/* In the vertical timeline the content lives to the right of the rail:
 * incoming transport points into that block, outgoing transport away from it. */
.conversation-timeline-event-direction.frame-rail-content.is-in {
  right: -1.42em;
  left: auto;
  transform: translateY(-50%);
}

.conversation-timeline-event-direction.frame-rail-content.is-out {
  right: auto;
  left: -1.42em;
  transform: translateY(-50%);
}

/* In horizontal Raumzeit the card is above its rail anchor. Incoming traffic
 * therefore points upward into the card; outgoing traffic points down and
 * away. This is presentation geometry only — transport semantics still come
 * exclusively from the canonical link direction. */
.conversation-timeline-event-direction.frame-rail-content-above.is-in {
  top: -1.28em;
  left: 50%;
  transform: translateX(-50%);
}

.conversation-timeline-event-direction.frame-rail-content-above.is-out {
  top: auto;
  bottom: -1.28em;
  left: 50%;
  transform: translateX(-50%);
}

.conversation-timeline-event-direction.frame-transport.is-in {
  right: auto;
  left: -1.42em;
  transform: translateY(-50%);
}

.conversation-timeline-event-direction.frame-transport.is-out {
  right: -1.42em;
  left: auto;
  transform: translateY(-50%);
}

/* An opened multi-lane bridge has real from/to coordinates. Its badge sits
 * in front of the endpoint icon and follows that exact vector, so stacked
 * horizontal lanes use up/down while side-by-side vertical lanes use
 * left/right. The transport parser still decides whether a badge exists. */
.conversation-timeline-event-direction.frame-bridge-vector {
  top: 50%;
  left: 50%;
  transform:
    translate(-50%, -50%)
    rotate(var(--timeline-direction-angle, 0deg))
    translateX(1.42em);
}

/* Zeitansicht (David #47, Bild 125000): der Knoten ist ein 36-px-Rahmen mit Rand, das
 * Symbol darin 16 px. Relativ zum Symbol gesetzt (−1,42 em) landete der Pfeil genau auf
 * dem rechten Rand. Im Knoten sitzt er deshalb außerhalb des Rahmens, mit Abstand —
 * links wie rechts. Der Knoten hat overflow: visible, nichts wird beschnitten. */
.conversation-timeline-node .conversation-timeline-event-direction.frame-rail-content.is-in { right: auto; left: calc(100% + 1em); }
.conversation-timeline-node .conversation-timeline-event-direction.frame-rail-content.is-out { left: auto; right: calc(100% + 1em); }
.conversation-timeline {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  color: var(--text-primary);
  background: var(--surface);
}

.conversation-timeline-viewport {
  position: absolute;
  top: calc(var(--agent-hdr-h, 72px) + 4px);
  right: 0;
  bottom: var(--agent-ftr-h, 76px);
  left: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* `auto` in JS must really snap; smooth is requested only for live growth
     or an explicit Aktuell click, never inherited during initialization. */
  scroll-behavior: auto;
  scrollbar-width: thin;
}

.conversation-timeline-toolbar {
  position: absolute;
  right: 12px;
  bottom: calc(var(--agent-ftr-h, 76px) + 12px);
  z-index: 12;
  display: flex;
  align-items: stretch;
  max-width: calc(100% - 24px);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 12px 38px color-mix(in srgb, var(--text-primary) 12%, transparent);
}

.conversation-timeline-toolbar button {
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 5px 11px;
  border: 0;
  border-left: 1px solid var(--border);
  border-radius: 0;
  color: var(--text-muted);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: .05em;
  cursor: pointer;
}

.conversation-timeline-toolbar button:hover {
  color: var(--text-primary);
  background: var(--hover-bg);
}

.conversation-timeline-toolbar button.active {
  color: var(--white);
  background: var(--chip-active-bg);
}

.conversation-timeline-toolbar button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.conversation-timeline-stream {
  width: 100%;
  min-height: 100%;
  padding: 26px 22px 74px;
}

.conversation-timeline-episode + .conversation-timeline-episode {
  margin-top: 34px;
}

.conversation-timeline-episode-head {
  margin-bottom: 14px;
  padding-left: 48px;
}

.conversation-timeline-episode-head span {
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
}

.conversation-timeline-events {
  --timeline-development-icon-size: calc(36px * .65);
  --timeline-development-gap: 3px;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-left: 48px;
}

.conversation-timeline-events::before {
  content: '';
  position: absolute;
  top: 17px;
  bottom: -34px;
  left: 17px;
  width: 2px;
  background: var(--border-strong);
}

.conversation-timeline-block {
  position: relative;
  min-width: 0;
  padding: 12px 14px 14px;
  border: 0;
  border-radius: 0;
  background: var(--bg-light);
}

.conversation-timeline-event-cluster {
  --timeline-development-top: 50px;
  position: relative;
  min-width: 0;
}

.conversation-timeline-event-cluster.has-development-run {
  min-height: var(--timeline-development-min-height, 0);
}

.conversation-timeline-display-cluster {
  position: relative;
  min-width: 0;
}

.conversation-timeline-display-cluster.live-arrival::before {
  content: '';
  position: absolute;
  z-index: 3;
  top: calc(-14px - var(--timeline-elapsed-gap, 0px));
  bottom: calc(100% - 18px);
  left: -31px;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: 50% 0;
  animation: conversation-timeline-rail-grow .3s ease-out forwards;
}

.conversation-timeline-display-cluster.live-arrival > .conversation-timeline-event-cluster,
.conversation-timeline-display-cluster.live-arrival > [class~="conversation-timeline-development-run"] {
  opacity: 0;
  animation: conversation-timeline-live-reveal .32s .28s ease-out forwards;
}

.conversation-timeline-scale {
  min-width: 190px;
  display: grid;
  align-content: center;
  gap: 2px;
  padding: 4px 8px;
  border-left: 1px solid var(--border);
  color: var(--text-muted);
  background: var(--surface);
  font: 700 8px/1 var(--font-mono);
  text-align: center;
  white-space: nowrap;
}

.conversation-timeline-scale input { width: 174px; accent-color: var(--accent); }

.conversation-timeline-events-absolute {
  position: relative;
  display: block;
  min-height: 80px;
}

.conversation-timeline-display-cluster.spacing-elapsed-absolute {
  position: absolute;
  right: 0;
  left: 0;
  margin: 0;
}

.conversation-timeline-display-cluster.spacing-elapsed-absolute .conversation-timeline-node,
.conversation-timeline-display-cluster.spacing-elapsed-absolute .conversation-timeline-node-time,
.conversation-timeline-display-cluster.spacing-elapsed-absolute > .conversation-timeline-development-run,
.conversation-timeline-display-cluster.spacing-elapsed-absolute .conversation-timeline-development-run.attached-to-event {
  transform: translateY(var(--timeline-absolute-anchor-shift, 0));
}

.conversation-timeline-display-cluster.spacing-elapsed-absolute.collision-displaced::after {
  content: '';
  position: absolute;
  z-index: 1;
  top: var(--timeline-absolute-anchor-shift, 0);
  left: -31px;
  width: 31px;
  height: var(--timeline-absolute-connector, 0);
  border-left: 1px solid var(--border-strong);
  border-bottom: 1px solid var(--border-strong);
  pointer-events: none;
}

.conversation-timeline-absolute-episode {
  position: absolute;
  z-index: 2;
  left: 8px;
  color: var(--text-muted);
  font: 700 7px/1 var(--font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  pointer-events: none;
}

.conversation-timeline-elapsed-label {
  position: absolute;
  z-index: 4;
  top: var(--timeline-elapsed-label-top, -14px);
  left: -48px;
  width: 36px;
  padding: 2px 1px;
  color: var(--text-muted);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 7px;
  font-weight: 700;
  line-height: 1.1;
  text-align: center;
  white-space: nowrap;
}

.conversation-timeline-elapsed-label.capped {
  border-top: 1px solid var(--accent);
  border-bottom: 1px solid var(--accent);
}

.conversation-timeline-elapsed-label.unknown {
  color: var(--color-warning);
}

.conversation-timeline-block.kind-user { background: color-mix(in srgb, var(--text-primary) 7%, transparent); }
.conversation-timeline-block.kind-agent { background: var(--surface); }
.conversation-timeline-block.kind-thinking { background: var(--color-warning-bg); }
.conversation-timeline-block.kind-iacp,
.conversation-timeline-block.has-iacp-event {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
.conversation-timeline-block.has-iacp-event .iacp-event-card {
  margin: 0;
  background: transparent;
}
.conversation-timeline-block.kind-issue {
  background: color-mix(in srgb, var(--color-info) 7%, transparent);
}

.conversation-timeline-node {
  position: absolute;
  top: 0;
  left: -48px;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  color: var(--text-primary);
  background: var(--surface);
}

button.conversation-timeline-node-link {
  padding: 0;
  overflow: visible;
  font: inherit;
  cursor: pointer;
}

button.conversation-timeline-node-link:hover,
button.conversation-timeline-node-link:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.conversation-timeline-node img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.conversation-timeline-block.kind-user .conversation-timeline-node { color: var(--text-primary); border-color: var(--text-primary); }
.conversation-timeline-block.kind-thinking .conversation-timeline-node,
.conversation-timeline-block.kind-code .conversation-timeline-node { color: var(--color-warning); }
.conversation-timeline-block.kind-artifact .conversation-timeline-node { color: var(--color-success); }
.conversation-timeline-block.kind-iacp .conversation-timeline-node { color: var(--accent); border-color: var(--accent); }
.conversation-timeline-block.kind-issue .conversation-timeline-node { color: var(--color-info); border-color: var(--color-info); }
.conversation-timeline-block.kind-content .conversation-timeline-node { color: var(--color-success); border-color: var(--color-success); }
.conversation-timeline-block.has-iacp-event .conversation-timeline-node { color: var(--accent); border-color: var(--accent); }

.conversation-timeline-node-time {
  position: absolute;
  top: 39px;
  left: -52px;
  z-index: 1;
  width: 44px;
  padding: 2px 0;
  color: var(--text-muted);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 8px;
  line-height: 1;
  text-align: center;
}

.conversation-timeline-block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.conversation-timeline-block-head strong {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: .06em;
}

.conversation-timeline-block-head time {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
}

.conversation-timeline-block-title {
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.conversation-timeline-block-title small {
  flex: 0 0 auto;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 8px;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: .08em;
}

.conversation-timeline-block-title strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-timeline-development-run {
  position: relative;
  z-index: 3;
  height: 0;
  min-width: 0;
  min-height: 0;
  margin-block: -7px;
}

.conversation-timeline-development-icons {
  --timeline-development-glyph-size: calc(16px * .65);
  position: absolute;
  top: auto;
  bottom: 0;
  left: -48px;
  z-index: 2;
  width: 36px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--timeline-development-gap);
  transform-origin: 50% 100%;
}

.conversation-timeline-event-cluster > .conversation-timeline-development-run.attached-to-event {
  position: absolute;
  inset: 0;
  margin: 0;
  pointer-events: none;
}

.conversation-timeline-event-cluster > .conversation-timeline-development-run.attached-to-event
  .conversation-timeline-development-icons {
  top: var(--timeline-development-top);
  bottom: auto;
  transform-origin: 50% 0;
  pointer-events: auto;
}

/* FAELLT DAS BOT-ZEICHEN WEG, RUECKT DIE SCHIENE NACH.
   Sonst klafft dort ein 36px-Loch, wo vorher der Knoten sass — und ein Loch
   sieht aus wie ein fehlendes Zeichen, nicht wie ein weggelassenes.
   Tetris-Logik aus derselben Ansicht: die Zeichen steigen, bis sie anstehen;
   ohne Knoten stehen sie oben an. */
.conversation-timeline-event-cluster.node-implied .conversation-timeline-node-time {
  top: 0;
}

.conversation-timeline-event-cluster.node-implied {
  --timeline-development-top: 13px;
}

.conversation-timeline-event-cluster.node-implied > .conversation-timeline-development-run.attached-to-event
  .conversation-timeline-development-icons {
  top: var(--timeline-development-top);
}

.conversation-timeline-development-icons.tetris-arrival {
  animation: conversation-timeline-tetris-rise .52s cubic-bezier(.22, .72, .24, 1) both;
}

.conversation-timeline-development-icon {
  position: relative;
  width: var(--timeline-development-icon-size);
  height: var(--timeline-development-icon-size);
  flex: 0 0 var(--timeline-development-icon-size);
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  color: var(--text-primary);
  background: var(--surface);
  cursor: pointer;
}

.conversation-timeline-development-count {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 12px;
  height: 12px;
  padding: 0 2px;
  border: 1px solid var(--border-strong);
  color: var(--text-primary);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 7px;
  font-weight: 700;
  line-height: 10px;
  text-align: center;
}

.conversation-timeline-development-icon-item {
  width: var(--timeline-development-icon-size);
  flex: 0 0 var(--timeline-development-icon-size);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.conversation-timeline-development-icon svg {
  width: var(--timeline-development-glyph-size);
  height: var(--timeline-development-glyph-size);
}

.conversation-timeline-development-icon-item time {
  width: 44px;
  padding: 2px 0;
  color: var(--text-muted);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 8px;
  line-height: 1;
  text-align: center;
}

.conversation-timeline-development-icon:hover,
.conversation-timeline-development-icon.active {
  color: var(--accent);
  background: var(--hover-bg);
}

.conversation-timeline-development-icon:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Three geometries stay readable without text: execution = weighted square,
   change = diamond, structure = double frame. */
.conversation-timeline-development-icon.development-execution {
  border-bottom-width: 4px;
}

.conversation-timeline-development-icon.development-change {
  border-color: var(--color-warning);
  color: var(--color-warning);
  transform: rotate(45deg) scale(.78);
}

.conversation-timeline-development-icon.development-change > span {
  transform: rotate(-45deg) scale(1.2);
}

.conversation-timeline-development-icon.development-change
  .conversation-timeline-development-count {
  transform: rotate(-45deg) scale(1.28);
}

.conversation-timeline-development-icon.development-structure {
  border-width: 3px;
  border-style: double;
  color: var(--color-success);
}

.conversation-timeline-development-detail {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  z-index: 5;
  min-width: 0;
  max-height: min(64vh, 560px);
  margin: 0;
  padding: 10px 11px 12px;
  overflow: auto;
  border: 1px solid var(--border);
  border-left: 0;
  border-radius: 0;
  background: var(--bg-light);
}

.conversation-timeline-event-cluster > .conversation-timeline-development-run.attached-to-event
  .conversation-timeline-development-detail {
  pointer-events: auto;
}

.conversation-timeline-development-detail-item + .conversation-timeline-development-detail-item {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.conversation-timeline-development-detail-item > strong {
  display: block;
  margin-bottom: 6px;
  font-size: 11px;
}

.conversation-timeline-development-close {
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 0;
  color: var(--text-secondary);
  background: var(--surface);
  cursor: pointer;
}

.conversation-timeline-development-close:hover,
.conversation-timeline-development-close:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
}

.conversation-timeline-block-text {
  margin: 0;
  color: var(--text-primary);
  font-size: 14px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.conversation-timeline-block-text > :first-child {
  margin-top: 0;
}

.conversation-timeline-block-text > :last-child {
  margin-bottom: 0;
}

.conversation-timeline-action-target.is-actionable {
  cursor: pointer;
}

.conversation-timeline-action-target.is-actionable:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 4px;
}

.conversation-timeline-block.actions-selected > .conversation-timeline-action-target {
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}

.conversation-timeline-selected-actions {
  margin-top: 8px;
}

.conversation-timeline-selected-actions .reply-actions {
  margin-top: 0;
}

.conversation-timeline-iacp-meta {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 6px;
  margin: 0 0 8px;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.conversation-timeline-iacp-relationship {
  display: inline-flex;
  min-width: 0;
  align-items: center;
  gap: 5px;
  text-transform: none;
}

.conversation-timeline-iacp-meta code {
  overflow: hidden;
  color: var(--text-muted);
  font: inherit;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-timeline-block-code {
  max-height: 18rem;
  margin: 0;
  padding: 10px 11px;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: 0;
  color: var(--text-secondary);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.conversation-timeline-empty {
  padding: 64px 18px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 11px;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .05em;
}

.conversation-timeline-now {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 22px 0 0 8px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
}

.conversation-timeline-now-node {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  border: 3px solid var(--surface);
  outline: 1px solid currentColor;
  border-radius: 0;
  color: var(--text-muted);
  background: var(--surface-elevated, var(--surface));
}

.conversation-timeline-now-copy {
  display: grid;
  gap: 2px;
  padding-top: 1px;
}

.conversation-timeline-now-copy strong,
.conversation-timeline-now-copy small {
  font: inherit;
}

.conversation-timeline-now-copy small {
  color: currentColor;
  opacity: .78;
}

.conversation-timeline-now.state-working,
.conversation-timeline-now.state-restarting { color: var(--accent); }
.conversation-timeline-now.state-ready { color: var(--color-success); }
.conversation-timeline-now.state-waiting { color: var(--color-warning); }
.conversation-timeline-now.state-blocked,
.conversation-timeline-now.state-error { color: var(--color-error); }
.conversation-timeline-now.state-paused,
.conversation-timeline-now.state-offline,
.conversation-timeline-now.state-stopped,
.conversation-timeline-now.state-unknown { color: var(--text-muted); }

.conversation-timeline-now.state-working .conversation-timeline-now-node,
.conversation-timeline-now.state-restarting .conversation-timeline-now-node {
  animation: conversation-timeline-agent-active 1.4s ease-in-out infinite;
}

@keyframes conversation-timeline-arrive {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes conversation-timeline-agent-active {
  50% { transform: scale(1.12); }
}

@keyframes conversation-timeline-tetris-rise {
  from {
    opacity: 0;
    transform: translateY(min(46vh, 360px));
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes conversation-timeline-rail-grow {
  to { transform: scaleY(1); }
}

@keyframes conversation-timeline-live-reveal {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Der Sprung-Knopf (geerbt aus AgentDetail.css, hier nicht nachgebaut)
   teilt sich die Hoehe mit der Werkzeugleiste (Aelter · Kompakt · Aktuell).
   Am Handy fuellt die Leiste fast die Breite und verdeckte ihn (Alex 07.09.,
   Bild 123670). Die Zeitansicht hebt ihn ueber die Leiste — allein ueber
   diese Variable, die die Grundregel einrechnet: Leisten-Hoehe (38px + Rand)
   + Luft. */
.conversation-timeline {
  --sprung-knopf-hub: 48px;
}

@media (max-width: 700px) {
  .conversation-timeline-viewport {
    top: calc(var(--agent-hdr-h, 72px) + 2px);
  }

  .conversation-timeline-toolbar {
    right: 6px;
    bottom: calc(var(--agent-ftr-h, 76px) + 6px);
    min-height: 36px;
  }

  .conversation-timeline-toolbar button {
    min-height: 34px;
    padding: 4px 9px;
  }

  .conversation-timeline {
    --sprung-knopf-hub: 42px;
  }

  .conversation-timeline-stream {
    padding: 18px 8px 70px;
  }

  .conversation-timeline-episode + .conversation-timeline-episode {
    margin-top: 26px;
  }

  .conversation-timeline-episode-head {
    margin-bottom: 10px;
    padding-left: 38px;
  }

  .conversation-timeline-events {
    --timeline-development-icon-size: calc(28px * .65);
    --timeline-development-gap: 2px;
    gap: 10px;
    padding-left: 38px;
  }

  .conversation-timeline-events::before {
    top: 14px;
    bottom: -26px;
    left: 13px;
    width: 1px;
  }

  .conversation-timeline-block {
    padding: 10px 10px 11px;
  }

  .conversation-timeline-node {
    left: -38px;
    width: 28px;
    height: 28px;
  }

  .conversation-timeline-elapsed-label {
    left: -38px;
    width: 28px;
    font-size: 6px;
  }

  .conversation-timeline-display-cluster.live-arrival::before {
    left: -25px;
    width: 1px;
  }

  .conversation-timeline-scale { min-width: 164px; padding-inline: 6px; }
  .conversation-timeline-scale input { width: 150px; }

  .conversation-timeline-node svg {
    width: 13px;
    height: 13px;
  }

  .conversation-timeline-node-time {
    top: 31px;
    left: -43px;
    width: 38px;
    font-size: 7px;
  }

  .conversation-timeline-block-head {
    margin-bottom: 6px;
  }

  .conversation-timeline-block-title {
    gap: 6px;
  }

  .conversation-timeline-block-title small {
    font-size: 7px;
  }

  .conversation-timeline-block-text {
    font-size: 13px;
    line-height: 1.48;
  }

  .conversation-timeline-block-code {
    max-height: 13rem;
    padding: 8px;
    font-size: 10px;
  }

  .conversation-timeline-development-icons {
    --timeline-development-glyph-size: calc(13px * .65);
    left: -38px;
    width: 28px;
    gap: var(--timeline-development-gap);
  }

  .conversation-timeline-development-run { margin-block: -5px; }

  .conversation-timeline-event-cluster > .conversation-timeline-development-run.attached-to-event
    .conversation-timeline-development-icons {
    top: var(--timeline-development-top);
  }

  .conversation-timeline-event-cluster {
    --timeline-development-top: 42px;
  }

  .conversation-timeline-event-cluster.has-development-run {
    min-height: var(--timeline-development-min-height-compact, 0);
  }

  .conversation-timeline-event-cluster.node-implied {
    --timeline-development-top: 11px;
  }

  .conversation-timeline-event-cluster.node-implied > .conversation-timeline-development-run.attached-to-event
    .conversation-timeline-development-icons {
    top: var(--timeline-development-top);
  }

  .conversation-timeline-development-icon {
    width: var(--timeline-development-icon-size);
    height: var(--timeline-development-icon-size);
    flex-basis: var(--timeline-development-icon-size);
  }

  .conversation-timeline-development-icon-item {
    width: var(--timeline-development-icon-size);
    flex-basis: var(--timeline-development-icon-size);
  }

  .conversation-timeline-development-icon-item time {
    width: 38px;
    font-size: 7px;
  }

  .conversation-timeline-development-icon svg {
    width: var(--timeline-development-glyph-size);
    height: var(--timeline-development-glyph-size);
  }

  .conversation-timeline-development-detail {
    padding: 8px;
  }

}

@media (prefers-reduced-motion: reduce) {
  .conversation-timeline-viewport { scroll-behavior: auto; }
  .conversation-timeline-block,
  .conversation-timeline-display-cluster.live-arrival::before,
  .conversation-timeline-display-cluster.live-arrival > .conversation-timeline-event-cluster,
  .conversation-timeline-display-cluster.live-arrival > [class~="conversation-timeline-development-run"],
  .conversation-timeline-development-icons.tetris-arrival,
  .conversation-timeline-now.state-working .conversation-timeline-now-node,
  .conversation-timeline-now.state-restarting .conversation-timeline-now-node { animation: none; }
  .conversation-timeline-display-cluster.live-arrival::before { transform: scaleY(1); }
  .conversation-timeline-display-cluster.live-arrival > .conversation-timeline-event-cluster,
  .conversation-timeline-display-cluster.live-arrival > [class~="conversation-timeline-development-run"] {
    opacity: 1;
    transform: none;
  }
}

/* ── Kleinhirn-Derivat (B2, Post 4907 p-d63443b5bce3) ─────────────────────
   Die Karte ersetzt in der Kleinhirn-Linse die Agenten-Cluster eines Turns;
   das Original bleibt über den Kopf-Knopf einen Tipp entfernt. „kein
   Derivat" ist ein ehrlicher Chip am Original, nie eine leere Karte. */
.derivat-karte {
  margin: 6px 0;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
  background: color-mix(in srgb, var(--accent) 6%, var(--surface));
  padding: 10px 12px;
}

.derivat-karte-kopf {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.derivat-karte-marke {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--accent);
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.derivat-karte-kopf > small {
  color: var(--text-muted);
  font: 10px/1 var(--font-mono);
}

.derivat-karte-original {
  margin-left: auto;
  background: none;
  border: 1px solid var(--border);
  padding: 3px 8px;
  color: var(--text-muted);
  font: 11px/1 var(--font-body);
  cursor: pointer;
}

.derivat-karte-original:hover { color: var(--text-primary); border-color: var(--border-strong); }

/* An dich (owner_note, Post 4909): die Ebene, die zuerst gelesen wird —
   Ich→Du, nur Belegtes; darunter wird die neutrale Zusammenfassung leiser. */
.derivat-karte-an-dich {
  margin: 0 0 8px;
  padding-left: 10px;
  border-left: 2px solid var(--accent);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-primary);
}

.derivat-karte-an-dich + .derivat-karte-zusammenfassung {
  color: var(--text-secondary);
  font-size: 12.5px;
}

.derivat-karte-zusammenfassung {
  margin: 0 0 8px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-primary);
}

/* Vorläufige Ableitung (settled:false, Post 4909): gestrichelt, mit
   Fortschritt — sie weiß, dass sie ein Zwischenstand ist. */
.derivat-karte.is-vorlaeufig {
  border-style: dashed;
}

.derivat-karte-vorlaeufig {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-warning);
}

/* Interne Selbst-Spur (self_note, Post 4909): einklappbar wie Reasoning,
   optisch zurückgenommen — sie ist die Denk-Schicht, nicht die Stimme. */
.derivat-selbstnotiz {
  margin: 0 0 8px;
}

.derivat-selbstnotiz-schalter {
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  cursor: pointer;
}

.derivat-selbstnotiz-text {
  margin: 6px 0 0;
  padding-left: 10px;
  border-left: 2px solid var(--border);
  font-size: 12.5px;
  line-height: 1.5;
  font-style: italic;
  color: var(--text-secondary);
}

.derivat-karte-items {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 5px;
}

.derivat-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-primary);
}

.derivat-item-chip {
  flex: 0 0 auto;
  padding: 1px 6px;
  border: 1px solid currentColor;
  font: 700 9px/1.5 var(--font-mono);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.derivat-item.kind-goal .derivat-item-chip { color: var(--color-success); }
.derivat-item.kind-problem .derivat-item-chip,
.derivat-item.kind-risk .derivat-item-chip { color: var(--color-error); }
.derivat-item.kind-decision .derivat-item-chip,
.derivat-item.kind-commitment .derivat-item-chip { color: var(--accent); }
.derivat-item.kind-question .derivat-item-chip { color: var(--color-info); }
.derivat-item.kind-action .derivat-item-chip,
.derivat-item.kind-result .derivat-item-chip { color: var(--color-warning); }

.derivat-item-epistemik {
  flex: 0 0 auto;
  color: var(--text-muted);
  font: 9px/1 var(--font-mono);
}

.derivat-fehlt-hinweis {
  display: inline-block;
  margin: 2px 0 4px;
  padding: 1px 6px;
  border: 1px dashed var(--border-strong);
  color: var(--text-muted);
  font: 10px/1.5 var(--font-mono);
}

/* ── QUERSTAPEL (Alex 16.09., Bild 125445) ───────────────────────────────────
   Der angehaengte Werkzeug-Stapel liegt senkrecht auf der Schiene und haelt die
   naechste Nachricht unter sich (min-height oben). Ist die Nachricht viel kuerzer
   als der Stapel, entstand rechts ein grosser leerer Raum. Dann kippt der Stapel
   in EINE Zeile unter die Nachricht, und die naechste folgt direkt darunter.
   Ob er kippt, misst ConversationTimelineViewport (data-stapel); die Stapelhoehe
   fuer die aktuelle Breite steht in einer eigenen Variablen, damit die Messung
   dieselbe Zahl liest, die das Stylesheet anwendet — keine doppelte Media-Query
   im Code. */
.conversation-timeline-stream .conversation-timeline-event-cluster.has-development-run {
  --timeline-development-stapelhoehe: var(--timeline-development-min-height, 0px);
}

@media (max-width: 700px) {
  .conversation-timeline-stream .conversation-timeline-event-cluster.has-development-run {
    --timeline-development-stapelhoehe: var(--timeline-development-min-height-compact, 0px);
  }
}

.conversation-timeline-event-cluster.has-development-run[data-stapel="quer"] {
  min-height: 0;
}

.conversation-timeline-event-cluster[data-stapel="quer"] > .conversation-timeline-development-run.attached-to-event {
  position: static;
  inset: auto;
  /* Der Lauf ist sonst 0 px hoch (height: 0, negative Ränder) — senkrecht hängt
     der Stapel ja absolut daneben. Quer liegt er im Fluss und braucht seine Höhe,
     sonst schiebt sich die nächste Nachricht über die Zeichenreihe (gemessen). */
  height: auto;
  margin: 6px 0 4px;
  pointer-events: auto;
}

.conversation-timeline-event-cluster[data-stapel="quer"] > .conversation-timeline-development-run.attached-to-event
  .conversation-timeline-development-icons {
  position: static;
  top: auto;
  bottom: auto;
  width: auto;
  margin-left: -48px;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  transform-origin: 0 50%;
}

/* Quer nebeneinander nur die Zeit beim Minutenwechsel — sonst verdeckt die
   undurchsichtige Zeit des Nachbarn die eigene. Unsichtbar statt entfernt,
   damit die Reihe gleich hoch bleibt. */
.conversation-timeline-event-cluster[data-stapel="quer"] .conversation-timeline-development-icon-item[data-gleiche-minute] time {
  visibility: hidden;
}

/* Telefon: die Schiene sitzt dort 10 px weiter innen (Zeichenspalte left: -38px),
   sonst ragt das erste Zeichen über den Bildrand (gemessen 390 px). */
@media (max-width: 700px) {
  .conversation-timeline-event-cluster[data-stapel="quer"] > .conversation-timeline-development-run.attached-to-event
    .conversation-timeline-development-icons {
    margin-left: -38px;
  }
}
/* Am Schreibtisch gibt es die Gruppe nicht: Der Behälter verschwindet aus dem
   Layout (`display: contents`), die Knöpfe liegen direkt in der Kopfzeile —
   genau wie vorher. Auf schmalen oder grob bedienten Touch-Viewports wird
   daraus ein Aufklappmenü. */
.kopf-gruppe { position: relative; display: inline-flex; }
.kopf-gruppe > .kopf-gruppe-knopf { display: none; }
.kopf-gruppe-inhalt { display: contents; }

/* GEFALTET WIRD NUR, WO DER PLATZ FEHLT (Alex 17.09.: die drei Punkte „am
   Mobiltelefon macht Sinn, aber nicht am Desktop, weil da habe ich ja links im
   Menü die Auswahl"). Vorher faltete die Gruppe bis 1199 px UND auf jedem Gerät
   mit grobem Zeiger — also auch auf der Quest mit breitem Fenster und
   sichtbarer Sidebar. Gemessen 17.09.: alle Knöpfe in einer Zeile brauchen im
   schlimmsten Fall (Prosa-Linse mit drei Textknöpfen) rund 420 px; neben der
   280-px-Sidebar passt das ab etwa 900 px Fensterbreite. 960 px lässt Luft für
   lange Agentennamen. Querformat am Telefon (max-height: 500px) faltet weiter. */
@media (max-width: 960px), (max-height: 500px) {
  .kopf-gruppe > .kopf-gruppe-knopf { display: inline-flex; }

  .kopf-gruppe-inhalt {
    position: absolute;
    z-index: 60;
    top: calc(100% + 6px);
    right: 0;
    display: none;
    flex-direction: column;
    gap: 4px;
    padding: 6px;
    max-width: calc(100vw - 24px);
    max-height: calc(100dvh - 100px);
    overflow-y: auto;
    overscroll-behavior: contain;
    border: 1px solid var(--border-strong);
    background: var(--surface);
    box-shadow: 0 12px 34px color-mix(in srgb, var(--black, #000) 22%, transparent);
  }

  .kopf-gruppe.offen .kopf-gruppe-inhalt { display: flex; }

  /* Im Menü darf ein Knopf die volle Breite nehmen und seine Beschriftung
     zeigen — der Platzdruck, der ihn in der Zeile stumm gemacht hat, gilt
     hier nicht mehr. */
  .kopf-gruppe-inhalt > * { width: 100%; justify-content: flex-start; }
  .kopf-gruppe-inhalt .conversation-view-toggle { width: 100%; justify-content: flex-start; gap: 8px; }
  .kopf-gruppe-inhalt .conversation-view-toggle span { display: inline; white-space: nowrap; }
}

/* Nur im GEFALTETEN Zustand: dort sind die Knöpfe Menüzeilen und bekommen volle
   Touch-Höhe. Ungefaltet liegen dieselben Knöpfe in der Kopfzeile — mit 44 px
   stünden sie dort wieder größer als ihre 32-px-Nachbarn (Bild 125491). */
@media (pointer: coarse) and (max-width: 960px), (pointer: coarse) and (max-height: 500px) {
  .kopf-gruppe-inhalt button { min-height: 44px; min-width: 44px; }
}

@media (pointer: coarse) {

  /* Der Knopf in der Kopfzeile sieht aus wie seine Nachbarn (.ahx-btn, 32 px).
     Alex 16.09., Bild 125491: mit min 44×44 stand er seit dem 14.09. auf jedem
     Touch-Gerät (Telefon, Quest) sichtbar größer und dicker zwischen den anderen
     Knöpfen. Die große Trefferfläche bleibt, aber unsichtbar: ein Rand aus
     ::before. `inset` zählt vom Innenrand (innerhalb des 1-px-Rahmens): 30 px
     + 2 × 7 px = 44 px Trefferhöhe — mit 6 px waren es gemessen nur 42. Seitlich
     3 px, das ragt 2 px über den Rahmen; der Abstand zu den Nachbarn ist 6 px,
     so greift der Rand nie in einen fremden Knopf. */
  .kopf-gruppe-knopf { position: relative; }
  .kopf-gruppe-knopf::before { content: ''; position: absolute; inset: -7px -3px; }
}
.three-camera-settings { position: relative; font-size: 12px; }
.three-camera-settings > summary { display: flex; align-items: center; gap: 5px; padding: 6px 8px; cursor: pointer; list-style: none; }
.three-camera-settings-panel { position: fixed; z-index: 1200; box-sizing: border-box; width: min(320px, calc(100vw - 24px)); overflow: auto; overscroll-behavior: contain; padding: 14px; border: 1px solid #52525b; border-radius: 10px; background: #18181b; color: #fafafa; box-shadow: 0 8px 30px #0008; display: grid; gap: 12px; }
.three-camera-settings-panel label { display: grid; gap: 4px; }
.three-camera-settings-panel select, .three-camera-settings-panel input { width: 100%; min-width: 0; box-sizing: border-box; color: inherit; background: #27272a; border: 1px solid #52525b; border-radius: 5px; padding: 7px; }
.three-camera-settings-panel p { margin: 0; color: #d4d4d8; line-height: 1.5; }
.three-camera-settings-panel { white-space: normal; text-align: left; font: 12px/1.4 system-ui, sans-serif; }
.canvas-media-reader {
  box-sizing: border-box;
  width: calc(100vw - 24px);
  height: calc(100dvh - 24px);
  max-width: none;
  max-height: none;
  margin: auto;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  color: var(--text-primary);
  background: var(--surface);
  overflow: hidden;
}
.canvas-media-reader[open] { display: flex; flex-direction: column; }
.canvas-media-reader::backdrop { background: rgb(0 0 0 / 75%); }
.canvas-media-reader header, .canvas-media-reader nav, .canvas-media-reader footer {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
}
.canvas-media-reader header strong { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.canvas-media-reader nav { flex-wrap: wrap; border-block: 1px solid var(--border); }
.canvas-media-reader button, .canvas-media-reader nav a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  background: var(--surface);
  color: var(--text-primary);
  font: inherit;
  cursor: pointer;
}
.canvas-media-reader button:disabled { opacity: .4; cursor: default; }
.canvas-media-reader button:focus-visible, .canvas-media-reader a:focus-visible, .canvas-media-reader-viewport:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.canvas-media-reader output { min-width: 55px; text-align: center; }
.canvas-media-reader-viewport {
  flex: 1 1 auto;
  min-height: 0;
  padding: 16px;
  overflow: auto;
  overscroll-behavior: contain;
  touch-action: pan-x pan-y;
}
.canvas-media-reader-content { margin: 0 auto; flex: none; }
.canvas-media-reader-content > img { display: block; width: 100%; height: 100%; max-width: none; object-fit: contain; }
.canvas-media-reader-content .v2-mermaid { box-sizing: border-box; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; background: transparent; }
.canvas-media-reader-content .v2-mermaid svg { display: block; width: 100%; height: 100%; max-width: none; }
.canvas-media-reader footer { flex-wrap: wrap; font-size: 12px; border-top: 1px solid var(--border); }
.canvas-media-reader footer span { color: var(--text-muted); }
.canvas-media-reader-error { display: grid; justify-items: start; gap: 12px; padding: 16px; }
.conversation-timecanvas {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  color: var(--text-primary);
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(120%);
  backdrop-filter: blur(18px) saturate(120%);
  border: 1px solid color-mix(in srgb, var(--text-primary) 10%, transparent);
}

.conversation-timecanvas-viewport {
  position: absolute;
  top: calc(var(--agent-hdr-h, 72px) + 4px);
  right: 0;
  bottom: var(--agent-ftr-h, 76px);
  left: 0;
  overflow: hidden;
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  cursor: grab;
  background:
    radial-gradient(circle at 50% 35%, color-mix(in srgb, var(--accent) 5%, transparent), transparent 52%),
    color-mix(in srgb, var(--surface) 60%, transparent);
  -webkit-backdrop-filter: blur(12px) saturate(115%);
  backdrop-filter: blur(12px) saturate(115%);
}

@supports not ((backdrop-filter: blur(1px))) {
  .conversation-timecanvas,
  .conversation-timecanvas-viewport { background: var(--surface); }
}

.conversation-timecanvas-viewport:active { cursor: grabbing; }

.conversation-timecanvas-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Separate experimental geometry lens: Waves LinesAA renders axes and
   causal curves in one WebGL layer. The existing world remains DOM so every
   rich card and control preserves its canonical renderer and hit testing. */
.conversation-timecanvas-three-layer {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
}

.conversation-timecanvas-three-webgl,
.conversation-timecanvas-three-css3d {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.conversation-timecanvas-three-webgl {
  z-index: 0;
  display: block;
}

.conversation-timecanvas-three-css3d {
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
  transform-style: preserve-3d;
}

/* CSS3DObject owns only the world transform. The mounted child is the exact
   React card used by the flat timeline, so Markdown, IACP, Issue, media and
   every existing interaction keep one canonical implementation. */
.conversation-timecanvas-css3d-card {
  position: relative;
  box-sizing: border-box;
  overflow: hidden;
  border: 1px solid var(--three-active-color, #718397);
  border-radius: 9px;
  background: #111925;
  pointer-events: auto;
  transform-style: preserve-3d;
  user-select: text;
  -webkit-user-select: text;
}

.conversation-timecanvas-css3d-media {
  position: relative;
  overflow: visible;
  pointer-events: auto;
  transform-style: preserve-3d;
  user-select: text;
  -webkit-user-select: text;
}

.conversation-timecanvas-image-status {
  position: absolute;
  box-sizing: border-box;
  padding: 18px;
  background: #141b26;
  color: #e2e8f0;
  pointer-events: auto;
  font-size: 14px;
}

.conversation-timecanvas-image-status a,
.conversation-timecanvas-image-status button {
  margin-inline-end: 12px;
}

/* Keyboard alternatives for raycast images; visible only while navigating
   these actions, never a permanent DOM rectangle over the depth-tested image. */
.conversation-timecanvas-image-actions {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.conversation-timecanvas-image-actions:focus-within {
  bottom: 12px;
  left: 12px;
  z-index: 3;
  width: auto;
  height: auto;
  padding: 10px;
  clip-path: none;
  background: #141b26;
  pointer-events: auto;
}

.conversation-timecanvas-css3d-card .three-reading-content,
.conversation-timecanvas-css3d-media .three-reading-content {
  box-sizing: border-box;
  min-width: 0;
  position: relative;
  width: 100%;
  height: auto;
}

.conversation-timecanvas-css3d-card .three-reading-content {
  height: auto;
}

.three-reading-heading {
  box-sizing: border-box;
  height: 52px;
  padding: 8px 12px;
  background: #111925;
  border-bottom: 1px solid #354251;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
}

.three-reading-heading strong {
  font-size: 15px;
  line-height: 19px;
  color: #f1f5f9;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.three-reading-heading span {
  font-size: 12px;
  line-height: 17px;
  color: var(--three-active-color, #7dd3fc);
}

.three-reading-controls {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-around;
  height: 36px;
  background: #111925;
  border-radius: 0 0 8px 8px;
  border-top: 1px solid #394353;
}

.three-reading-controls button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: #e2e8f0;
  background: transparent;
  border: 0;
  flex: 1;
  height: 100%;
  cursor: pointer;
}

.three-reading-controls small { font-size: 10px; }

.three-reading-controls button:focus-visible {
  outline: 2px solid #7dd3fc;
  outline-offset: -3px;
}

.conversation-timecanvas-css3d-card .three-reading-content > .conversation-timecanvas-card {
  box-sizing: border-box;
  min-width: 0;
  max-width: 100%;
  position: relative;
  top: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: auto !important;
  content-visibility: visible;
  contain-intrinsic-size: none;
  box-shadow: none;
}

.conversation-timecanvas-css3d-card.is-three-active .three-reading-content > .conversation-timecanvas-card {
  box-shadow:
    0 0 0 2px color-mix(in srgb, var(--three-active-color, var(--accent)) 86%, white 14%),
    0 18px 54px color-mix(in srgb, #000 42%, transparent),
    0 0 34px color-mix(in srgb, var(--three-active-color, var(--accent)) 24%, transparent);
}

.conversation-timecanvas-css3d-card a.is-three-reference-focused {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* Complete canonical reading bodies; this scope never changes flat cards. */
.conversation-timecanvas-css3d-card .conversation-timecanvas-card-body,
.conversation-timecanvas-css3d-card .conversation-timecanvas-card-text,
.conversation-timecanvas-css3d-card .iacp-event-card,
.conversation-timecanvas-css3d-media .kind-content-post,
.conversation-timecanvas-css3d-media .kind-content-post .conversation-timecanvas-media-body {
  height: auto !important;
  max-height: none !important;
  overflow: visible;
  flex: none;
}

.conversation-timecanvas-css3d-media .three-reading-content > .conversation-timecanvas-media-object {
  position: relative;
  top: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: 100% !important;
  content-visibility: visible;
  contain-intrinsic-size: none;
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--accent) 68%, transparent),
    0 22px 62px color-mix(in srgb, #000 42%, transparent),
    0 0 28px color-mix(in srgb, var(--accent) 12%, transparent);
}

.conversation-timecanvas-css3d-media[data-full-reading="true"] .three-reading-content > .conversation-timecanvas-media-object {
  height: auto !important;
}

.conversation-timecanvas-css3d-media[data-full-reading="false"] .three-reading-content {
  height: calc(100% - 36px);
}

.conversation-timecanvas-css3d-card .conversation-timecanvas-port,
.conversation-timecanvas-css3d-card .conversation-timecanvas-bridge-port {
  display: none;
}

/* Canonical cards stay mounted before requestSession so WebXR can capture the
   exact React rendering after the user gesture has opened the XR session.
   Keep them laid out and paintable, but far outside the visual viewport. */
.conversation-timecanvas-ar-card-capture {
  position: fixed;
  top: 0;
  left: -100000px;
  z-index: -1;
  width: max-content;
  pointer-events: none;
  contain: layout style;
}

.conversation-timecanvas.geometry-three .conversation-timecanvas-world {
  z-index: 2;
}

/* Desktop-Perspektive und WebXR teilen dieselbe Three-Szene. Nur die Kamera
   wechselt: hier gehoert die Eingabe den OrbitControls, waehrend die flache
   DOM-Projektion ausgeblendet wird, damit nichts doppelt erscheint. */
.conversation-timecanvas.geometry-three-perspective .conversation-timecanvas-three-layer {
  z-index: 3;
  pointer-events: auto;
  touch-action: none;
  cursor: grab;
}

.conversation-timecanvas.geometry-three-perspective .conversation-timecanvas-three-layer:active {
  cursor: grabbing;
}

.conversation-timecanvas.geometry-three-perspective
  .conversation-timecanvas-three-layer[data-desktop-controls='spectator'] {
  cursor: crosshair;
}

.conversation-timecanvas.geometry-three-perspective .conversation-timecanvas-three-layer[data-spectator-locked='true'] {
  cursor: none;
}

.conversation-timecanvas-spectator-hint {
  position: absolute;
  top: 14px;
  left: 50%;
  z-index: 4;
  padding: 7px 10px;
  border: 1px solid color-mix(in srgb, var(--border) 68%, transparent);
  border-radius: 999px;
  color: color-mix(in srgb, var(--text-primary) 82%, transparent);
  background: color-mix(in srgb, var(--surface) 76%, transparent);
  font: 650 9px/1.2 var(--font-mono);
  white-space: nowrap;
  transform: translateX(-50%);
  pointer-events: none;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.conversation-timecanvas-three-layer[data-spectator-locked='true'] .conversation-timecanvas-spectator-hint {
  opacity: 0.42;
}

.conversation-timecanvas.geometry-three-perspective .conversation-timecanvas-grid,
.conversation-timecanvas.geometry-three-perspective .conversation-timecanvas-world,
.conversation-timecanvas.geometry-three-perspective .conversation-timecanvas-overview-layer,
.conversation-timecanvas.geometry-three-perspective .conversation-timecanvas-lane-anchors {
  visibility: hidden;
}

.conversation-timecanvas.geometry-three-active .conversation-timecanvas-axis {
  background: transparent;
  box-shadow: none;
}

.conversation-timecanvas.geometry-three-active .conversation-timecanvas-axis.spacing-elapsed::before,
.conversation-timecanvas.geometry-three-active .conversation-timecanvas-segments {
  display: none;
}

/* The curve itself comes from WebGL. The lightweight SVG remains only as the
   path-following carrier for the already established live transport dot. */
.conversation-timecanvas.geometry-three-active .conversation-timecanvas-branch-lines .message-bridge-link,
.conversation-timecanvas.geometry-three-active .conversation-timecanvas-branch-lines .content-link,
.conversation-timecanvas.geometry-three-active .conversation-timecanvas-bridge-motion-path {
  stroke: transparent;
  marker-end: none;
}

/* In immersive AR the WebXR compositor owns the spatial picture. Only the
   small placement controls and canonical selected-event dialog remain as a
   DOM overlay; the flat world must not be painted a second time. */
.conversation-timecanvas.is-ar-active,
.conversation-timecanvas.is-ar-active .conversation-timecanvas-viewport {
  background: transparent;
}

.conversation-timecanvas.is-ar-active .conversation-timecanvas-grid,
.conversation-timecanvas.is-ar-active .conversation-timecanvas-world,
.conversation-timecanvas.is-ar-active .conversation-timecanvas-overview-layer,
.conversation-timecanvas.is-ar-active .conversation-timecanvas-agent-picker {
  visibility: hidden;
}

.conversation-timecanvas-ar-guide {
  position: absolute;
  top: calc(var(--agent-hdr-h, 72px) + 18px);
  left: 50%;
  z-index: 28;
  max-width: min(420px, calc(100% - 28px));
  padding: 8px 12px;
  border: 1px solid color-mix(in srgb, var(--accent) 58%, transparent);
  color: var(--text-primary);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  box-shadow: 0 12px 34px color-mix(in srgb, #000 24%, transparent);
  font: 700 10px/1.35 var(--font-mono);
  text-align: center;
  transform: translateX(-50%);
  pointer-events: none;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.conversation-timecanvas-ar-guide.is-error {
  border-color: color-mix(in srgb, var(--color-error) 64%, transparent);
  color: var(--color-error);
}

.conversation-timecanvas-world {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  transform-origin: 0 0;
  /* Promoted only during zoom by canvasZoomRaster; idle text/SVG must reraster. */
  will-change: auto;
  contain: layout style;
}

/* Far zoom is a screen-space symbol layer, not a second conversation
   renderer. Exact event anchors remain as tiny pins; only the semantic glyph
   is grouped and displaced in viewport pixels, with a connector back to the
   group's canonical representative anchor. */
.conversation-timecanvas-overview-layer {
  position: absolute;
  inset: 0;
  z-index: 7;
  overflow: hidden;
  pointer-events: none;
}

.conversation-timecanvas-overview-connectors {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.conversation-timecanvas-overview-connectors line {
  stroke: color-mix(in srgb, var(--timeline-lane-color, var(--text-muted)) 60%, transparent);
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
}

.conversation-timecanvas-overview-pin {
  position: absolute;
  top: 0;
  left: 0;
  width: 4px;
  height: 4px;
  border: 1px solid var(--timeline-lane-color, var(--text-muted));
  background: var(--surface);
  pointer-events: none;
  will-change: transform;
}

.conversation-timecanvas-overview-marker {
  position: absolute;
  top: 0;
  left: 0;
  width: 24px;
  height: 24px;
  display: inline-grid;
  place-items: center;
  padding: 3px;
  border: 1px solid currentColor;
  border-radius: 0;
  color: var(--text-secondary);
  background: var(--surface);
  box-shadow: 0 0 0 1px color-mix(in srgb, currentColor 14%, transparent);
  cursor: pointer;
  pointer-events: auto;
  will-change: transform;
}

.conversation-timecanvas-overview-marker:hover,
.conversation-timecanvas-overview-marker:focus-visible {
  z-index: 2;
  color: var(--accent);
  outline: 1px solid currentColor;
  outline-offset: 2px;
}

.conversation-timecanvas-overview-marker > small {
  position: absolute;
  right: -7px;
  bottom: -7px;
  min-width: 15px;
  height: 15px;
  display: grid;
  place-items: center;
  padding-inline: 3px;
  border: 1px solid currentColor;
  color: inherit;
  background: var(--surface);
  font: 8px/1 var(--font-mono);
}

.conversation-timecanvas-overview-marker.is-overflow {
  color: var(--timeline-lane-color, var(--text-secondary));
}

.conversation-timecanvas-overview-overflow-count {
  font: 9px/1 var(--font-mono);
  letter-spacing: -0.04em;
}

.conversation-timecanvas-overview-marker.kind-agent {
  color: var(--timeline-lane-color, var(--accent));
}

.conversation-timecanvas-overview-marker.kind-user { color: var(--text-primary); }
.conversation-timecanvas-overview-marker.kind-thinking,
.conversation-timecanvas-overview-marker.kind-tool,
.conversation-timecanvas-overview-marker.kind-code { color: var(--color-warning); }
.conversation-timecanvas-overview-marker.kind-artifact,
.conversation-timecanvas-overview-marker.kind-content { color: var(--color-success); }
.conversation-timecanvas-overview-marker.kind-iacp,
.conversation-timecanvas-overview-marker.has-iacp-event { color: var(--accent); }
.conversation-timecanvas-overview-marker.kind-issue { color: var(--color-info); }

.conversation-timecanvas-overview-bridge-marker {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--accent) 28%, transparent),
    0 0 12px color-mix(in srgb, var(--accent) 18%, transparent);
}

.conversation-timecanvas-axis {
  position: absolute;
  height: 3px;
  background: var(--timeline-lane-color, var(--border-strong));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--timeline-lane-color, var(--border-strong)) 18%, transparent);
  pointer-events: none;
}

/* Kompakt ist eine reine Ereignisachse. Echtzeit zeigt zusaetzlich den
   gewaehlt linearen Minutentakt; auch bei lokal kollisionsentzerrten Karten
   bleibt dadurch sichtbar, welcher Modus aktiv ist. */
.conversation-timecanvas-axis.spacing-elapsed::before {
  content: '';
  position: absolute;
  opacity: .52;
  pointer-events: none;
}

.conversation-timecanvas-axis.spacing-elapsed.orientation-horizontal::before {
  top: -5px;
  left: 0;
  width: 100%;
  height: 13px;
  background-image: repeating-linear-gradient(
    to right,
    color-mix(in srgb, var(--timeline-lane-color, var(--accent)) 72%, transparent) 0 1px,
    transparent 1px var(--timecanvas-minute-step, 100px)
  );
  background-position-x: var(--timecanvas-ruler-offset, 0);
}

.conversation-timecanvas-axis.spacing-elapsed.orientation-vertical::before {
  top: 0;
  left: -5px;
  width: 13px;
  height: 100%;
  background-image: repeating-linear-gradient(
    to bottom,
    color-mix(in srgb, var(--timeline-lane-color, var(--accent)) 72%, transparent) 0 1px,
    transparent 1px var(--timecanvas-minute-step, 100px)
  );
  background-position-y: var(--timecanvas-ruler-offset, 0);
}

/* Nur ein wirklich arbeitender/neustartender Agent traegt einen laufenden
   Lichtimpuls. Die Farbe bleibt die kanonische Lane-Farbe; die Bewegung ist
   Status, nicht eine zweite Identitaetsfarbe. */
.conversation-timecanvas-axis.state-working::after,
.conversation-timecanvas-axis.state-restarting::after {
  content: '';
  position: absolute;
  border-radius: 999px;
  box-shadow:
    0 0 12px color-mix(in srgb, var(--timeline-lane-color, var(--accent)) 88%, transparent),
    0 0 24px color-mix(in srgb, var(--timeline-lane-color, var(--accent)) 42%, transparent);
  pointer-events: none;
}

.conversation-timecanvas-axis.orientation-horizontal.state-working::after,
.conversation-timecanvas-axis.orientation-horizontal.state-restarting::after {
  top: -1px;
  left: 0;
  width: 68px;
  height: 5px;
  background: linear-gradient(
    to right,
    transparent 0%,
    color-mix(in srgb, var(--timeline-lane-color, var(--accent)) 48%, transparent) 34%,
    var(--timeline-lane-color, var(--accent)) 76%,
    transparent 100%
  );
  animation: conversation-timecanvas-agent-flow-x 1.7s linear infinite;
}

.conversation-timecanvas-axis.orientation-vertical.state-working::after,
.conversation-timecanvas-axis.orientation-vertical.state-restarting::after {
  top: 0;
  left: -1px;
  width: 5px;
  height: 68px;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    color-mix(in srgb, var(--timeline-lane-color, var(--accent)) 48%, transparent) 34%,
    var(--timeline-lane-color, var(--accent)) 76%,
    transparent 100%
  );
  animation: conversation-timecanvas-agent-flow-y 1.7s linear infinite;
}

.conversation-timecanvas-empty {
  position: absolute;
  top: 220px;
  left: 96px;
  z-index: 2;
  width: min(420px, calc(100% - 192px));
  padding: 18px;
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
  background: var(--surface);
  font: 11px/1.45 var(--font-mono);
  text-align: center;
}

.conversation-timecanvas-segments {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  overflow: visible;
  pointer-events: none;
}

.conversation-timecanvas-segments line {
  stroke: var(--border-strong);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.conversation-timecanvas-segments line.live-arrival {
  stroke: var(--accent);
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: conversation-timecanvas-segment-grow .68s cubic-bezier(.2, .72, .25, 1) forwards;
}

.conversation-timecanvas-node-anchor.live-arrival,
.conversation-timecanvas-dev.live-arrival,
.conversation-timecanvas-card.live-arrival {
  opacity: 0;
  animation: conversation-timecanvas-event-reveal .46s .58s cubic-bezier(.2, .72, .25, 1) forwards;
}

.conversation-timecanvas-segments text {
  fill: var(--text-muted);
  font: 600 9px/1 var(--font-mono);
  letter-spacing: .05em;
}

.conversation-timecanvas-segments text.unknown { fill: var(--color-warning); }
.conversation-timecanvas-segments text.capped { text-decoration: underline dotted; }

.conversation-timecanvas-episode {
  position: absolute;
  display: grid;
  max-width: 260px;
  gap: 3px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  pointer-events: none;
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-episode {
  transform: translate(-50%, calc(-100% - 42px));
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-episode {
  width: 46px;
  transform: translate(-100%, -50%);
}

.conversation-timecanvas-episode::before {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  width: 1px;
  height: 35px;
  background: var(--accent);
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-episode::before {
  top: 50%;
  left: 100%;
  width: 28px;
  height: 1px;
}

.conversation-timecanvas-episode span {
  color: var(--accent);
  font-size: 8px;
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .1em;
}

.conversation-timecanvas-episode strong {
  overflow: hidden;
  font-size: 10px;
  font-weight: 500;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-episode strong {
  display: none;
}

.conversation-timecanvas-card {
  position: absolute;
  z-index: 2;
  display: flex;
  flex-direction: column;
  border: 0;
  border-radius: 0;
  background: var(--surface);
  box-shadow: none;
  contain: layout paint style;
  content-visibility: auto;
  contain-intrinsic-size: 320px 246px;
}

.conversation-timecanvas-card.semantic-overview {
  height: 92px !important;
  box-shadow: none;
}

/* Detailed cards own their intrinsic block height. They are already bounded
 * by the explicit Canvas view-window virtualization, so forcing an inner
 * scroller or `content-visibility` placeholder here would make the geometry
 * lie about images, Markdown and long Collaboration letters. */
.conversation-timecanvas-card.intrinsic-height {
  content-visibility: visible;
  contain-intrinsic-size: none;
}

.conversation-timecanvas-card.intrinsic-height > .conversation-timecanvas-card-body {
  flex: 0 0 auto;
  overflow: visible;
}

.conversation-timecanvas-card.canonical-iacp-event.intrinsic-height .iacp-event-card {
  min-height: 0;
}

.conversation-timecanvas-overview-label {
  min-height: 0;
  padding: 9px;
  overflow: hidden;
  color: var(--text-muted);
  font: 10px/1.35 var(--font-mono);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-timecanvas-card.kind-user {
  background: color-mix(in srgb, var(--text-primary) 7%, var(--surface));
}

.conversation-timecanvas-card.kind-iacp {
  border-color: color-mix(in srgb, var(--accent) 62%, var(--border-strong));
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
}

.conversation-timecanvas-card.kind-issue {
  border-color: color-mix(in srgb, var(--color-info) 62%, var(--border-strong));
  background: color-mix(in srgb, var(--color-info) 7%, var(--surface));
}

.conversation-timecanvas-card.kind-issue.compact-issue {
  /* Beide Tokens setzt TimelineCanvasNode inline aus der Layout-Geometrie.
     Die Rückfallwerte spiegeln CONVERSATION_TIMELINE_CANVAS_ISSUE_CARD_* —
     sie greifen nie im Normalbetrieb, aber der statische Token-Wächter
     (tokenVollstaendig) kann Inline-Definitionen nicht sehen und verlangt
     zu Recht, dass kein var() ins Leere zeigen kann. */
  contain-intrinsic-size:
    var(--timecanvas-issue-card-width, 248px)
    var(--timecanvas-issue-card-height, 76px);
}

.conversation-timecanvas-card.kind-issue.semantic-overview.compact-issue {
  height: var(--timecanvas-issue-card-height, 76px) !important;
}

.conversation-timecanvas-issue-link {
  display: grid;
  align-content: center;
  gap: 5px;
  width: 100%;
  height: 100%;
  min-width: 0;
  padding: 10px 12px;
  color: var(--color-info);
  background: color-mix(in srgb, var(--color-info) 9%, transparent);
  font-family: var(--font-mono);
  text-decoration: none;
}

.conversation-timecanvas-issue-link span {
  color: inherit;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .04em;
}

.conversation-timecanvas-issue-link strong {
  display: -webkit-box;
  min-width: 0;
  overflow: hidden;
  color: var(--text-primary);
  font-size: 13px;
  line-height: 1.25;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.conversation-timecanvas-issue-link:hover strong,
.conversation-timecanvas-issue-link:focus-visible strong {
  text-decoration: underline;
}

.conversation-timecanvas-issue-link:focus-visible {
  outline: 1px solid var(--color-info);
  outline-offset: -3px;
}

.conversation-timecanvas-card.kind-content {
  border-color: color-mix(in srgb, var(--color-success) 62%, var(--border-strong));
  background: color-mix(in srgb, var(--color-success) 7%, var(--surface));
}

/* A structured Collaboration push is the same letter in every lens. The
 * absolute article owns only Canvas geometry; `IacpEventCard` keeps the exact
 * classic header, recipients, response state, Markdown body and footer. */
.conversation-timecanvas-card.canonical-iacp-event {
  border: 0;
  background: transparent;
  box-shadow: none;
  contain: layout style;
}

.conversation-timecanvas-card.canonical-iacp-event > .conversation-timecanvas-card-body {
  flex: 1 1 auto;
  padding: 0;
  overflow: auto;
}

.conversation-timecanvas-card.canonical-iacp-event .iacp-event-card {
  min-height: 100%;
  margin: 0;
}

.conversation-timecanvas-card.canonical-iacp-event > .canonical-iacp-branch-action {
  position: absolute;
  top: 10px;
  right: -30px;
  z-index: 3;
  width: 28px;
  min-height: 28px;
  justify-content: center;
  margin: 0;
  padding: 0;
}

.conversation-timecanvas-card.canonical-iacp-event > .canonical-iacp-branch-action span {
  display: none;
}

.conversation-timecanvas-card.branch-available {
  cursor: pointer;
}

.conversation-timecanvas-card.branch-available:hover,
.conversation-timecanvas-card.branch-available:focus-visible,
.conversation-timecanvas-card.branch-open {
  border-color: var(--accent);
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

.conversation-timecanvas-card.branch-open .conversation-timecanvas-port {
  background: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
}

.conversation-timecanvas-branch-action {
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 6px;
  margin: 7px 9px 0;
  padding: 4px 7px;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, var(--border));
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  font: 700 8px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: .05em;
  cursor: pointer;
}

.conversation-timecanvas-branch-action:hover,
.conversation-timecanvas-branch-action:focus-visible {
  border-color: var(--accent);
  outline: 1px solid var(--accent);
}

.conversation-timecanvas-card.semantic-overview .conversation-timecanvas-branch-action {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 28px;
  margin: 0;
  padding: 0;
  justify-content: center;
}

.conversation-timecanvas-card.semantic-overview .conversation-timecanvas-branch-action span {
  display: none;
}

.conversation-timecanvas-port {
  position: absolute;
  width: 9px;
  height: 9px;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--text-muted);
}

.conversation-timecanvas-boundary {
  position: absolute;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--text-muted);
  font: 700 8px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: .06em;
  pointer-events: none;
}

.conversation-timecanvas-boundary span {
  width: 10px;
  height: 10px;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--text-muted);
  box-shadow: 0 0 0 1px var(--border-strong);
}

.conversation-timecanvas-boundary.is-now {
  color: var(--timeline-lane-color, var(--accent));
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-boundary {
  width: 10px;
  height: 10px;
  transform: translate(-5px, -5px);
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-boundary {
  width: 10px;
  height: 10px;
  transform: translate(-5px, -5px);
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-boundary small {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-boundary small {
  position: absolute;
  top: 1px;
  right: 18px;
  white-space: nowrap;
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-card.side-before .conversation-timecanvas-port {
  bottom: -39px;
  left: 50%;
  transform: translateX(-50%);
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-card.side-after .conversation-timecanvas-port {
  top: -39px;
  left: 50%;
  transform: translateX(-50%);
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-card .conversation-timecanvas-port {
  top: 19px;
  left: -40px;
}

.conversation-timecanvas-card.kind-iacp .conversation-timecanvas-port { background: var(--accent); }
.conversation-timecanvas-card.kind-issue .conversation-timecanvas-port { background: var(--color-info); }
.conversation-timecanvas-card.kind-content .conversation-timecanvas-port { background: var(--color-success); }

.conversation-timecanvas-node-anchor {
  position: absolute;
  z-index: 6;
  width: 36px;
  height: 36px;
  color: var(--text-secondary);
  transform: translate(-50%, -50%);
}

/* The card is paint-contained for pan/zoom performance, so a connector owned
 * by the card is clipped at its edge. The uncontained axis marker owns the
 * complete connection. Horizontal elapsed cards may advance along the time
 * direction, hence their connector uses a measured length and angle. */
.conversation-timecanvas-node-anchor::before {
  content: '';
  position: absolute;
  z-index: 0;
  background: currentColor;
  opacity: .62;
  pointer-events: none;
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-node-anchor::before {
  top: 18px;
  left: 18px;
  width: var(--timecanvas-node-connector-length, var(--timecanvas-axis-card-gap, 34px));
  height: 1px;
  transform: rotate(var(--timecanvas-node-connector-angle, -90deg));
  transform-origin: 0 50%;
}

.conversation-timecanvas-world.orientation-horizontal
  .conversation-timecanvas-card.longitudinally-displaced .conversation-timecanvas-port {
  bottom: -5px;
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-node-anchor::before {
  top: 50%;
  left: 18px;
  width: calc(var(--timecanvas-node-connector, var(--timecanvas-axis-card-gap, 34px)) - 18px);
  height: 1px;
  transform: translateY(-50%);
}

.conversation-timecanvas-node-anchor > button,
.conversation-timecanvas-node-anchor > span {
  position: relative;
  z-index: 1;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  color: var(--text-secondary);
  background: var(--surface);
}

.conversation-timecanvas-node-anchor.kind-user > button,
.conversation-timecanvas-node-anchor.kind-user > span {
  color: var(--text-primary);
  border-color: var(--text-primary);
}
.conversation-timecanvas-node-anchor.kind-user { color: var(--text-primary); }

/* A plain Bot glyph identifies the owner of this lane, so it uses the same
   canonical identity color as the axis and its live endpoint. Semantic event
   kinds below deliberately keep their own issue/IACP/tool/content language. */
.conversation-timecanvas-node-anchor.kind-agent > button,
.conversation-timecanvas-node-anchor.kind-agent > span {
  color: var(--timeline-lane-color, var(--accent));
  border-color: var(--timeline-lane-color, var(--accent));
}
.conversation-timecanvas-node-anchor.kind-agent {
  color: var(--timeline-lane-color, var(--accent));
}

/* Das letzte semantische Zeichen IST zugleich der Jetzt-Punkt. Es bleibt das
   Ereignis-Icon, nimmt am Live-Ende aber Identitaet und Zustand seiner Lane
   an, statt als neutrales graues Bot-Zeichen ueber der farbigen Schiene zu
   stehen. */
.conversation-timecanvas-node-anchor.is-live-end.state-working > button,
.conversation-timecanvas-node-anchor.is-live-end.state-working > span,
.conversation-timecanvas-node-anchor.is-live-end.state-restarting > button,
.conversation-timecanvas-node-anchor.is-live-end.state-restarting > span {
  animation: conversation-timecanvas-agent-active 1.4s ease-in-out infinite;
}

.conversation-timecanvas-node-anchor.is-live-end.state-waiting > button,
.conversation-timecanvas-node-anchor.is-live-end.state-waiting > span {
  border-style: dashed;
}

.conversation-timecanvas-node-anchor.is-live-end.state-blocked > button,
.conversation-timecanvas-node-anchor.is-live-end.state-blocked > span,
.conversation-timecanvas-node-anchor.is-live-end.state-error > button,
.conversation-timecanvas-node-anchor.is-live-end.state-error > span {
  outline: 2px double currentColor;
  outline-offset: 2px;
}

.conversation-timecanvas-node-anchor.is-live-end.state-paused,
.conversation-timecanvas-node-anchor.is-live-end.state-offline,
.conversation-timecanvas-node-anchor.is-live-end.state-stopped { opacity: .58; }

.conversation-timecanvas-node-anchor.kind-thinking > button,
.conversation-timecanvas-node-anchor.kind-thinking > span,
.conversation-timecanvas-node-anchor.kind-code > button,
.conversation-timecanvas-node-anchor.kind-code > span { color: var(--color-warning); }
.conversation-timecanvas-node-anchor.kind-thinking,
.conversation-timecanvas-node-anchor.kind-code { color: var(--color-warning); }

.conversation-timecanvas-node-anchor.kind-artifact > button,
.conversation-timecanvas-node-anchor.kind-artifact > span,
.conversation-timecanvas-node-anchor.kind-content > button,
.conversation-timecanvas-node-anchor.kind-content > span {
  color: var(--color-success);
  border-color: var(--color-success);
}
.conversation-timecanvas-node-anchor.kind-artifact,
.conversation-timecanvas-node-anchor.kind-content { color: var(--color-success); }

.conversation-timecanvas-node-anchor.kind-iacp > button,
.conversation-timecanvas-node-anchor.kind-iacp > span,
.conversation-timecanvas-node-anchor.has-iacp-event > button,
.conversation-timecanvas-node-anchor.has-iacp-event > span {
  color: var(--accent);
  border-color: var(--accent);
}
.conversation-timecanvas-node-anchor.kind-iacp,
.conversation-timecanvas-node-anchor.has-iacp-event { color: var(--accent); }

.conversation-timecanvas-node-anchor.kind-issue > button,
.conversation-timecanvas-node-anchor.kind-issue > span {
  color: var(--color-info);
  border-color: var(--color-info);
}
.conversation-timecanvas-node-anchor.kind-issue { color: var(--color-info); }

.conversation-timecanvas-node-anchor > button { padding: 0; cursor: pointer; }
.conversation-timecanvas-node-anchor > button:hover,
.conversation-timecanvas-node-anchor > button:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
}
.conversation-timecanvas-node-anchor.is-live-end > button,
.conversation-timecanvas-node-anchor.is-live-end > span {
  color: var(--timeline-lane-color, var(--accent));
  border-color: var(--timeline-lane-color, var(--accent));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--timeline-lane-color, var(--accent)) 34%, transparent);
}
.conversation-timecanvas-node-anchor img { width: 100%; height: 100%; object-fit: cover; }

.conversation-timecanvas-node-anchor > time {
  position: absolute;
  top: 40px;
  left: 50%;
  width: 44px;
  transform: translateX(-50%);
  color: var(--text-muted);
  background: var(--surface);
  font: 8px/1 var(--font-mono);
  text-align: center;
  pointer-events: none;
}

.conversation-timecanvas-card-title {
  display: block;
  margin: 0 0 8px;
  color: var(--text-secondary);
  font: 700 11px/1.15 var(--font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
}

.conversation-timecanvas-card-body {
  --timecanvas-content-font-size: 12px;
  --timecanvas-content-line-height: 1.48;
  min-height: 0;
  flex: 1 1 auto;
  padding: 10px 12px;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  cursor: auto;
  -webkit-touch-callout: default;
  -webkit-user-select: text;
  user-select: text;
}

.conversation-timecanvas-card-body .entry-content {
  padding: 0;
  color: var(--text-primary);
  font-size: var(--timecanvas-content-font-size);
  line-height: var(--timecanvas-content-line-height);
}

/* User-Fallback (`RichMessage`) und kanonischer Bot-Renderer
 * (`SectionContent > .entry-content`) lesen dieselbe Basis. Markdown darf
 * seine Hierarchie darueber weiter auspraegen, aber nicht mehr je nach
 * Herkunft in einer anderen Grundgroesse beginnen. */
.conversation-timecanvas-card-text {
  color: var(--text-primary);
  font-size: var(--timecanvas-content-font-size);
  line-height: var(--timecanvas-content-line-height);
}

.conversation-timecanvas-card-body a[href^="#timecanvas-media-"],
.conversation-timecanvas-media-body a[href^="#timecanvas-media-"],
.conversation-timecanvas-media-reference {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 22px;
  margin: 2px 1px;
  padding: 3px 7px;
  border: 1px solid color-mix(in srgb, var(--accent) 34%, var(--border));
  border-radius: 999px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  font: 700 9px/1.2 var(--font-mono);
  letter-spacing: .03em;
  text-decoration: none;
  white-space: nowrap;
  cursor: default;
}

.conversation-timecanvas-card-body a[href^="#timecanvas-media-"]::before,
.conversation-timecanvas-media-body a[href^="#timecanvas-media-"]::before,
.conversation-timecanvas-media-reference::before {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 8px color-mix(in srgb, currentColor 64%, transparent);
  content: "";
}

.conversation-timecanvas-iacp-meta {
  min-height: 27px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border-bottom: 1px solid var(--border);
  color: var(--accent);
  font: 9px/1 var(--font-mono);
}

.conversation-timecanvas-iacp-meta code {
  margin-left: auto;
  color: var(--text-muted);
  font-size: 8px;
}

.conversation-timecanvas-iacp-relationship {
  display: inline-flex;
  min-width: 0;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}

.conversation-timecanvas-iacp-meta .conversation-timecanvas-branch-action.is-in-header {
  min-height: 21px;
  margin: 0 0 0 auto;
  padding: 3px 5px;
  font-size: 8px;
}

.conversation-timecanvas-iacp-meta .conversation-timecanvas-branch-action.is-in-header + code {
  margin-left: 2px;
}

.conversation-timecanvas-dev {
  position: absolute;
  z-index: 3;
  display: grid;
  place-items: center;
  padding: 4px;
  border: 1px solid var(--surface);
  border-radius: 0;
  color: var(--text-primary);
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--border-strong);
  cursor: pointer;
}

.conversation-timecanvas-dev .conversation-timeline-event-icon {
  width: 11px;
  height: 11px;
}

.conversation-timecanvas-dev-count {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 14px;
  height: 14px;
  display: grid;
  place-items: center;
  padding-inline: 2px;
  border: 1px solid currentColor;
  color: inherit;
  background: var(--surface);
  font: 700 8px/1 var(--font-mono);
}

.conversation-timecanvas-dev:hover,
.conversation-timecanvas-dev:focus-visible {
  color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
  outline: none;
}

.conversation-timecanvas-dev.development-execution {
  border-bottom-width: 4px;
}

.conversation-timecanvas-dev.development-change {
  border-color: var(--color-warning);
  color: var(--color-warning);
  transform: rotate(45deg) scale(.78);
}

.conversation-timecanvas-dev.development-change > .conversation-timeline-event-icon {
  transform: rotate(-45deg) scale(1.2);
}

.conversation-timecanvas-dev.development-change .conversation-timecanvas-dev-count {
  transform: rotate(-45deg) scale(1.28);
}

.conversation-timecanvas-dev.development-structure {
  border-width: 3px;
  border-style: double;
  color: var(--color-success);
}

.conversation-timecanvas-branch-lines {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: visible;
  pointer-events: none;
}

.conversation-timecanvas-branch-lines > path {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 7 5;
  vector-effect: non-scaling-stroke;
  animation: conversation-timecanvas-branch-flow .42s ease-out both;
}

.conversation-timecanvas-branch-lines > path.content-link {
  stroke: var(--color-success);
}

.conversation-timecanvas-branch-lines > path.media-object-link {
  stroke: color-mix(in srgb, var(--accent) 74%, var(--text-secondary));
  stroke-width: 1.5;
  stroke-dasharray: none;
}

.conversation-timecanvas-branch-lines > path.media-object-link.kind-mermaid {
  stroke: color-mix(in srgb, var(--color-info) 72%, var(--accent));
}

.conversation-timecanvas-branch-lines > path.content-update-hit {
  pointer-events: stroke;
  stroke: transparent;
  stroke-width: 16;
  stroke-dasharray: none;
  cursor: pointer;
  animation: none;
  outline: none;
}

.conversation-timecanvas-branch-lines > path.content-update-hit:focus-visible,
.conversation-timecanvas-branch-lines > path.content-update-link[data-change-active] {
  stroke: var(--accent);
  stroke-width: 3;
  outline: none;
}

.conversation-timecanvas-content-artifact .content-change-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-block: 10px;
}

.conversation-timecanvas-content-artifact select {
  max-width: 100%;
  color: var(--text-primary);
  background: var(--surface);
}

.conversation-timecanvas-content-artifact .content-change-controls :is(select, button) {
  font: inherit;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 5px;
  padding: 4px 6px;
}

.conversation-timecanvas-content-artifact .content-change-status {
  /* Changing hover must not resize/re-dock the very connector being hovered. */
  box-sizing: border-box;
  height: 60px;
  overflow: auto;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-secondary);
  border-inline-start: 2px solid var(--accent);
  padding-inline-start: 8px;
}

.conversation-timecanvas-content-artifact mark.content-update-highlight {
  color: var(--text-primary);
  background: color-mix(in srgb, var(--accent) 28%, var(--surface));
  box-shadow: 0 1px 0 var(--accent);
  font-style: inherit;
}

.conversation-timecanvas-branch-lines marker path {
  fill: var(--accent);
  stroke: none;
}

.conversation-timecanvas-bridge-motion-path {
  fill: none;
  stroke: none !important;
  animation: none !important;
}

.conversation-timecanvas-bridge-motion-dot {
  fill: var(--white);
  stroke: var(--accent);
  stroke-width: 2;
  filter: drop-shadow(0 0 5px var(--accent));
  pointer-events: none;
}

.conversation-timecanvas-card.message-bridge {
  z-index: 4;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 72%, var(--border-strong));
}

.conversation-timecanvas-media-object {
  box-sizing: border-box;
  position: absolute;
  z-index: 4;
  display: flex;
  flex-direction: column;
  margin: 0;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--accent) 52%, var(--border-strong));
  border-radius: 2px;
  color: var(--text-primary);
  background: color-mix(in srgb, var(--surface) 95%, var(--accent));
  box-shadow: 0 18px 48px color-mix(in srgb, #000 25%, transparent);
  contain: layout paint style;
  content-visibility: auto;
  contain-intrinsic-size: 544px 337px;
}

.conversation-timecanvas-media-object figcaption > button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.conversation-timecanvas-media-object figcaption {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 0 0 var(--timecanvas-media-header-height, 38px);
  height: var(--timecanvas-media-header-height, 38px);
  min-height: 0;
  padding: 7px 10px 6px;
  overflow: hidden;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 24%, var(--border));
  color: var(--text-muted);
  font: 700 9px/1.35 var(--font-mono);
  letter-spacing: .08em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.conversation-timecanvas-media-object figcaption > span {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Even a native 100px image keeps all three header actions reachable. */
.conversation-timecanvas-media-object.is-narrow figcaption { padding-inline: 4px; gap: 3px; }

.conversation-timecanvas-media-object [data-media-drag-handle] {
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.conversation-timecanvas-media-object [data-media-drag-handle]:active { cursor: grabbing; }

.conversation-timecanvas-media-object.kind-content-post .conversation-timecanvas-media-body {
  position: relative;
  display: block;
  padding: 12px;
  font-size: 12px;
  line-height: 1.48;
}

/* The window owns scrolling; avoid a second, nested 420px scroll pane. */
.conversation-timecanvas-media-object.kind-content-post .content-post-body {
  max-height: none;
  overflow: visible;
}

.conversation-timecanvas-content-artifact {
  overflow-wrap: anywhere;
}

/* Measure the document, not the scroll window; include collapsed margins. */
.conversation-timecanvas-document-measure { display: flow-root; }

/* The reference belongs inside the finite CSS3D card, before its scrollable
 * update body. The old 100%-tall IACP child pushed this port below the surface. */
.conversation-timecanvas-card.canonical-iacp-event .conversation-timecanvas-content-update .iacp-event-card {
  min-height: 0;
}

.conversation-timecanvas-content-artifact > small {
  display: block;
  opacity: 0.7;
  margin: 6px 0 12px;
}

.conversation-timecanvas-media-file {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 24px;
  font-size: 13px;
  text-align: center;
}

.conversation-timecanvas-media-file > span { color: var(--text-muted); }

.conversation-timecanvas-media-object figcaption > button {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  cursor: pointer;
}

.conversation-timecanvas-media-body img,
.conversation-timecanvas-media-body svg {
  cursor: pointer;
}

.conversation-timecanvas-media-body {
  min-width: 0;
  min-height: 0;
  flex: 1 1 auto;
  display: grid;
  place-items: center;
  overflow: auto;
  overscroll-behavior: contain;
  touch-action: pan-x pan-y;
  user-select: text;
  -webkit-user-select: text;
}

.conversation-timecanvas-media-body > a {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
}

.conversation-timecanvas-media-body img,
.conversation-timecanvas-media-body video,
.conversation-timecanvas-media-body .inline-media-img,
.conversation-timecanvas-media-body .inline-media-video {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  margin: 0;
  object-fit: contain;
}

.conversation-timecanvas-media-body .v2-mermaid {
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 14px;
}

.conversation-timecanvas-media-body .v2-mermaid svg {
  width: 100%;
  height: auto;
  max-height: 100%;
}

.conversation-timecanvas-bridge-endpoint {
  position: absolute;
  z-index: 5;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid currentColor;
  color: var(--accent);
  background: var(--surface);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.conversation-timecanvas-bridge-port {
  position: absolute;
  width: 9px;
  height: 9px;
  z-index: 5;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-bridge-port {
  left: 50%;
  transform: translateX(-50%);
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-bridge-port.is-entry {
  top: -5px;
}

.conversation-timecanvas-world.orientation-horizontal .conversation-timecanvas-bridge-port.is-exit {
  bottom: -5px;
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-bridge-port {
  top: 50%;
  transform: translateY(-50%);
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-bridge-port.is-entry {
  left: -5px;
}

.conversation-timecanvas-world.orientation-vertical .conversation-timecanvas-bridge-port.is-exit {
  right: -5px;
}

.conversation-timecanvas-related-lane {
  position: absolute;
  z-index: 1;
}

.conversation-timecanvas-related-lane > .conversation-timecanvas-axis {
  background: var(--timeline-lane-color, var(--accent));
  transform-origin: 0 50%;
  animation: conversation-timecanvas-lane-grow .68s .18s cubic-bezier(.2, .72, .25, 1) both;
}

.conversation-timecanvas-related-lane.orientation-vertical > .conversation-timecanvas-axis {
  transform-origin: 50% 0;
  animation-name: conversation-timecanvas-lane-grow-vertical;
}

.conversation-timecanvas-related-lane > :not(.conversation-timecanvas-axis) {
  opacity: 0;
  animation: conversation-timecanvas-lane-content-reveal .46s .78s cubic-bezier(.2, .72, .25, 1) forwards;
}

.conversation-timecanvas-content-branch > header {
  position: absolute;
  top: 10px;
  left: 12px;
  z-index: 6;
  min-height: 32px;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 7px;
  border: 1px solid var(--border-strong);
  color: var(--accent);
  background: var(--surface);
  font: 700 9px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: .05em;
}

.conversation-timecanvas-content-branch > header button,
.conversation-timecanvas-branch-state button {
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  color: var(--text-muted);
  background: transparent;
  cursor: pointer;
}

.conversation-timecanvas-content-branch > header button:hover,
.conversation-timecanvas-content-branch > header button:focus-visible,
.conversation-timecanvas-branch-state button:hover,
.conversation-timecanvas-branch-state button:focus-visible {
  color: var(--accent);
  outline: 1px solid var(--accent);
}

.conversation-timecanvas-lane-anchors {
  position: absolute;
  inset: 0;
  z-index: 9;
  overflow: hidden;
  pointer-events: none;
}

.conversation-timecanvas-lane-anchor {
  position: absolute;
  top: 0;
  left: 0;
  max-width: min(160px, calc(100% - 16px));
  height: 22px;
  display: inline-flex;
  align-items: center;
  padding: 0 7px;
  border: 1px solid var(--timeline-lane-color, var(--border-strong));
  overflow: hidden;
  color: var(--timeline-lane-color, var(--text-primary));
  background: var(--surface);
  font: 700 9px/1 var(--font-mono);
  text-overflow: ellipsis;
  white-space: nowrap;
  will-change: transform;
}

.conversation-timecanvas-lane-anchor[hidden] { display: none; }

.conversation-timecanvas-lane-anchor.orientation-vertical {
  top: 8px;
  left: 0;
}

.conversation-timecanvas-lane-anchor strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-timecanvas-content-branch {
  position: absolute;
  z-index: 4;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--color-success);
  background: var(--surface);
  box-shadow: 0 18px 54px color-mix(in srgb, var(--text-primary) 10%, transparent);
  animation: conversation-timecanvas-lane-arrive .28s ease-out both;
}

.conversation-timecanvas-content-branch > header {
  position: relative;
  inset: auto;
  flex: 0 0 auto;
  border: 0;
  border-bottom: 1px solid var(--border);
  color: var(--color-success);
}

.conversation-timecanvas-content-branch > header strong {
  flex: 1 1 auto;
}

.conversation-timecanvas-content-branch > header small {
  color: var(--text-muted);
}

.conversation-timecanvas-content-body {
  min-height: 0;
  flex: 1 1 auto;
  padding: 10px;
  overflow: auto;
  overscroll-behavior: contain;
  cursor: auto;
  -webkit-touch-callout: default;
  -webkit-user-select: text;
  user-select: text;
}

.conversation-timecanvas-content-body .content-post-embed {
  margin: 0;
}

.conversation-timecanvas-branch-state {
  position: absolute;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 11px;
  border: 1px solid var(--accent);
  color: var(--text-secondary);
  background: var(--surface);
  font: 10px/1.4 var(--font-mono);
  animation: conversation-timecanvas-lane-arrive .28s ease-out both;
}

.conversation-timecanvas-branch-state.failed {
  border-color: var(--color-warning);
}

.conversation-timecanvas-branch-state.missing {
  border-color: var(--border-strong);
  color: var(--text-muted);
}

.conversation-timecanvas-branch-state span {
  min-width: 0;
  flex: 1 1 auto;
}

.conversation-timecanvas-branch-state strong {
  color: var(--text-primary);
}

@keyframes conversation-timecanvas-lane-arrive {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes conversation-timecanvas-agent-active {
  50% { transform: scale(1.1); }
}

@keyframes conversation-timecanvas-agent-flow-x {
  from { left: 0; opacity: .46; }
  50% { opacity: 1; }
  to { left: calc(100% - 68px); opacity: .46; }
}

@keyframes conversation-timecanvas-agent-flow-y {
  from { top: 0; opacity: .46; }
  50% { opacity: 1; }
  to { top: calc(100% - 68px); opacity: .46; }
}

@keyframes conversation-timecanvas-segment-grow { to { stroke-dashoffset: 0; } }

@keyframes conversation-timecanvas-event-reveal {
  from { opacity: 0; transform: translateY(7px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes conversation-timecanvas-lane-grow {
  from { opacity: 0; transform: scaleX(0); }
  to { opacity: 1; transform: scaleX(1); }
}

@keyframes conversation-timecanvas-lane-grow-vertical {
  from { opacity: 0; transform: scaleY(0); }
  to { opacity: 1; transform: scaleY(1); }
}

@keyframes conversation-timecanvas-lane-content-reveal {
  /* Child types own different geometry transforms (axis icons are centred
     with translate(-50%, -50%), change icons rotate, episodes offset). A
     shared transform animation would replace those transforms permanently. */
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes conversation-timecanvas-branch-flow {
  from { opacity: 0; stroke-dashoffset: 24; }
  to { opacity: 1; stroke-dashoffset: 0; }
}

.conversation-timecanvas-controls {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 10;
  display: flex;
  align-items: stretch;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 12px 38px color-mix(in srgb, var(--text-primary) 12%, transparent);
}

.conversation-timecanvas.is-ar-active .conversation-timecanvas-controls > :not(.conversation-timecanvas-ar-control) {
  display: none;
}
.conversation-timecanvas.is-ar-active .conversation-timecanvas-controls > .conversation-timecanvas-three-scale {
  display: inline-flex;
}

.conversation-timecanvas-three-scale {
  min-height: 36px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 9px;
  border-left: 1px solid var(--border);
  color: var(--text-muted);
  font: 600 9px/1 var(--font-mono);
  text-transform: uppercase;
}
.conversation-timecanvas-three-scale input { width: 88px; accent-color: var(--accent); }
.conversation-timecanvas-three-scale output { min-width: 30px; color: var(--text-primary); }

.conversation-timecanvas-controls .conversation-timecanvas-ar-control {
  color: var(--accent);
}

.conversation-timecanvas-marker-navigation {
  display: inline-flex;
  align-items: stretch;
  min-width: 148px;
  border-left: 1px solid var(--border);
  background: var(--surface);
}

.conversation-timecanvas-marker-navigation > button {
  border-left: 0;
}

.conversation-timecanvas-marker-navigation-label {
  min-width: 82px;
  max-width: 148px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 5px 7px;
  border-inline: 1px solid var(--border);
  color: var(--text-primary);
  font: 700 9px/1 var(--font-mono);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.conversation-timecanvas-scale {
  min-width: 192px;
  display: grid;
  align-content: center;
  gap: 2px;
  padding: 4px 8px;
  border-left: 1px solid var(--border);
  color: var(--text-muted);
  background: var(--surface);
  font: 700 8px/1 var(--font-mono);
  text-align: center;
  white-space: nowrap;
}

.conversation-timecanvas-scale input { width: 176px; accent-color: var(--accent); }

.conversation-timecanvas-agent-picker {
  position: absolute;
  right: 12px;
  bottom: 58px;
  z-index: 12;
  width: min(360px, calc(100% - 24px));
  max-height: min(560px, calc(100% - 82px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 18px 54px color-mix(in srgb, var(--text-primary) 16%, transparent);
}

.conversation-timecanvas-agent-picker > header {
  min-height: 42px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border-bottom: 1px solid var(--border);
  color: var(--accent);
}

.conversation-timecanvas-agent-picker > header strong {
  flex: 1 1 auto;
  font: 700 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: .06em;
}

.conversation-timecanvas-agent-picker > header button {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  color: var(--text-muted);
  background: transparent;
}

.conversation-timecanvas-agent-picker-modes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: 1px solid var(--border);
}

.conversation-timecanvas-agent-picker-modes button {
  min-height: 38px;
  border: 0;
  border-right: 1px solid var(--border);
  color: var(--text-muted);
  background: transparent;
  font: 700 9px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: .05em;
}

.conversation-timecanvas-agent-picker-modes button:last-child { border-right: 0; }
.conversation-timecanvas-agent-picker-modes button.active {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
}

.conversation-timecanvas-agent-picker-info {
  display: grid;
  gap: 6px;
  padding: 14px;
  color: var(--text-secondary);
  font: 10px/1.4 var(--font-mono);
}

.conversation-timecanvas-agent-picker-info strong { color: var(--text-primary); }
.conversation-timecanvas-agent-picker-info small { color: var(--text-muted); }

.conversation-timecanvas-agent-search {
  min-height: 40px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 9px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
}

.conversation-timecanvas-agent-search input {
  min-width: 0;
  flex: 1 1 auto;
  border: 0;
  outline: 0;
  color: var(--text-primary);
  background: transparent;
  font: 11px/1.2 var(--font-mono);
}

.conversation-timecanvas-agent-list {
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
}

.conversation-timecanvas-agent-list > button {
  width: 100%;
  min-height: 46px;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 9px;
  border: 0;
  border-bottom: 1px solid var(--border);
  color: var(--text-secondary);
  background: transparent;
  text-align: left;
}

.conversation-timecanvas-agent-list > button.selected {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

.conversation-timecanvas-agent-list .conversation-timecanvas-identity {
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
}

.conversation-timecanvas-agent-list .conversation-timecanvas-identity img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.conversation-timecanvas-agent-list > button > span:not(.conversation-timecanvas-identity) {
  min-width: 0;
  display: grid;
  flex: 1 1 auto;
  gap: 3px;
}

.conversation-timecanvas-agent-list strong,
.conversation-timecanvas-agent-list small {
  overflow: hidden;
  font-family: var(--font-mono);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-timecanvas-agent-list strong { font-size: 10px; }
.conversation-timecanvas-agent-list small { color: var(--text-muted); font-size: 8px; }
.conversation-timecanvas-agent-list b { font: 700 13px/1 var(--font-mono); }

.conversation-timecanvas-agent-picker > footer {
  padding: 8px 10px;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font: 9px/1 var(--font-mono);
}

.conversation-timecanvas-controls button,
.conversation-timecanvas-zoom {
  min-height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 5px 9px;
  border: 0;
  border-left: 1px solid var(--border);
  border-radius: 0;
  color: var(--text-muted);
  background: var(--surface);
  font: 600 9px/1 var(--font-mono);
  text-transform: uppercase;
  cursor: pointer;
}

.conversation-timecanvas-controls button:first-child { border-left: 0; }
.conversation-timecanvas-controls button:hover { color: var(--text-primary); background: var(--hover-bg); }
.conversation-timecanvas-controls button.active { color: var(--white); background: var(--chip-active-bg); }
.conversation-timecanvas-controls button:disabled { opacity: .5; cursor: default; }
.conversation-timecanvas-zoom { min-width: 50px; }

.conversation-timecanvas-detail-backdrop {
  position: absolute;
  inset: 0;
  z-index: 30;
  display: grid;
  place-items: center;
  padding: calc(var(--agent-hdr-h, 72px) + 18px) 18px calc(var(--agent-ftr-h, 76px) + 18px);
  background: color-mix(in srgb, var(--bg) 58%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.conversation-timecanvas-detail {
  width: min(760px, 100%);
  max-height: min(72vh, 680px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  background: var(--surface);
  box-shadow: 0 28px 90px color-mix(in srgb, var(--text-primary) 20%, transparent);
}

.conversation-timecanvas-detail > header {
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border-bottom: 1px solid var(--border);
}

.conversation-timecanvas-detail > header strong { flex: 1 1 auto; font: 700 11px/1 var(--font-mono); }
.conversation-timecanvas-detail > header time { color: var(--text-muted); font: 9px/1 var(--font-mono); }
.conversation-timecanvas-detail > header button {
  width: 30px;
  height: 30px;
  display: inline-grid;
  place-items: center;
  border: 0;
  border-radius: 0;
  color: var(--text-muted);
  background: transparent;
  cursor: pointer;
}

.conversation-timecanvas-detail-body {
  min-height: 0;
  padding: 14px;
  overflow: auto;
  overscroll-behavior: contain;
  -webkit-touch-callout: default;
  -webkit-user-select: text;
  user-select: text;
}

.conversation-timecanvas-detail-body .entry-content { padding: 0; }

.conversation-timecanvas-detail-event + .conversation-timecanvas-detail-event {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.conversation-timecanvas-detail-event > h3 {
  margin: 0 0 8px;
  color: var(--text-muted);
  font: 700 10px/1.3 var(--font-mono);
}

@media (max-width: 700px) {
  .conversation-timecanvas-controls {
    right: 6px;
    bottom: 6px;
    left: 6px;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .conversation-timecanvas-controls::-webkit-scrollbar { display: none; }
  .conversation-timecanvas-controls button,
  .conversation-timecanvas-zoom { flex: 0 0 auto; min-height: 34px; padding-inline: 8px; }
  .conversation-timecanvas-marker-navigation { flex: 0 0 auto; min-width: 132px; }
  .conversation-timecanvas-scale { flex: 0 0 164px; padding-inline: 6px; }
  .conversation-timecanvas-scale input { width: 150px; }
  .conversation-timecanvas-detail-backdrop { padding-inline: 8px; }
  .conversation-timecanvas-lane-anchor { max-width: 42vw; }
}

@media (prefers-reduced-motion: reduce) {
  .conversation-timecanvas-world { will-change: auto; }
  .conversation-timecanvas-related-lane,
  .conversation-timecanvas-related-lane > .conversation-timecanvas-axis,
  .conversation-timecanvas-related-lane > :not(.conversation-timecanvas-axis),
  .conversation-timecanvas-branch-lines > path,
  .conversation-timecanvas-segments line.live-arrival,
  .conversation-timecanvas-node-anchor.live-arrival,
  .conversation-timecanvas-dev.live-arrival,
  .conversation-timecanvas-card.live-arrival,
  .conversation-timecanvas-content-branch,
  .conversation-timecanvas-branch-state { animation: none; }
  .conversation-timecanvas-bridge-motion-dot { display: none; }
  .conversation-timecanvas-axis.state-working::after,
  .conversation-timecanvas-axis.state-restarting::after { display: none; }
  .conversation-timecanvas-node-anchor.is-live-end.state-working > button,
  .conversation-timecanvas-node-anchor.is-live-end.state-working > span,
  .conversation-timecanvas-node-anchor.is-live-end.state-restarting > button,
  .conversation-timecanvas-node-anchor.is-live-end.state-restarting > span { animation: none; }
  .conversation-timecanvas-related-lane > :not(.conversation-timecanvas-axis) { opacity: 1; }
  .conversation-timecanvas-node-anchor.live-arrival,
  .conversation-timecanvas-dev.live-arrival,
  .conversation-timecanvas-card.live-arrival { opacity: 1; transform: none; }
}
/* Verlauf exportieren — flach, eckig, Mono-Versalien für Meta (Styleguide). */
.vex-modal { max-width: 440px; }
.vex-text { margin: 0 0 10px; font-size: 13px; color: var(--text-secondary); }
.vex-datei { font-family: var(--font-mono); font-size: 11px; word-break: break-all; }
.vex-label { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin: 10px 0 4px; }
.vex-wahl { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.vex-chip { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; padding: 4px 8px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-primary); border-radius: 0; cursor: pointer; }
.vex-chip.active { background: var(--chip-active-bg); color: var(--white); border-color: var(--text-primary); }
.vex-frei { flex: 1; min-width: 120px; font-family: var(--font-mono); font-size: 11px; padding: 4px 6px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-primary); border-radius: 0; }
.vex-frei-falsch { border-color: var(--color-warning); }
.vex-schalter { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 13px; color: var(--text-primary); }
.vex-ok { color: var(--text-primary); font-size: 13px; }
.vex-warn { color: var(--color-warning); font-size: 12px; margin: 6px 0 0; }
/* ZEITRAUM-ÜBERSICHT (Alex 15.09., Bild 125314) — flach, eckig, zweifarbig wie der
   Einstieg; Zustand als Zeichen plus Tönung, keine acht Farbtöne. */
.zeitraum { border: 1px solid var(--text-primary); background: var(--surface); color: var(--text-primary); }
.zeitraum-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; padding: 6px 12px; border-bottom: 1px solid var(--border-strong); }
.zeitraum.is-zu .zeitraum-kopf { border-bottom: 0; }
.zeitraum-titel { background: none; border: 0; padding: 0; color: inherit; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; cursor: pointer; text-align: left; }
.zeitraum-zaehler { font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); flex: 1; }
.zeitraum-tage { display: flex; gap: 1px; background: var(--border-strong); border: 1px solid var(--border-strong); }
.zeitraum-tage button { background: var(--surface); color: var(--text-primary); border: 0; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; padding: 2px 8px; cursor: pointer; }
.zeitraum-tage button.on { background: var(--chip-active-bg); color: var(--white); }
.zeitraum-koerper { padding: 8px 12px 10px; display: flex; flex-direction: column; gap: 8px; }
.zeitraum-meta { font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary); display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; }
.zeitraum-luecke { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; color: var(--color-warning); }
.zeitraum-leer { margin: 0; font-size: 12px; color: var(--text-secondary); }

/* Raster: Zeilen mit Kopf links und Spur rechts; Trennlinien über den Grid-Gap. */
.zeitraum-raster { display: flex; flex-direction: column; gap: 1px; background: var(--border); border: 1px solid var(--border); }
.zeitraum-zeile { display: grid; grid-template-columns: minmax(150px, 26%) 1fr; background: var(--surface); min-height: 30px; }
.zeitraum-zeile-kopf { padding: 5px 8px; font-size: 12px; display: flex; flex-direction: column; gap: 2px; min-width: 0; border-right: 1px solid var(--border); }
.zeitraum-zeile-kopf button, .zeitraum-zeile-name { background: none; border: 0; padding: 0; color: inherit; text-align: left; font: inherit; display: flex; gap: 6px; align-items: baseline; min-width: 0; }
.zeitraum-zeile-kopf button { cursor: pointer; }
/* „Kurz gesagt" — die Zeitraum-Prosa vom Server (Cloud, Prompt zeitraum-v1). */
.zeitraum-prosa { margin: 0; padding: 8px 10px; border: 1px solid var(--border-strong); font-size: 13px; line-height: 1.45; }
.zeitraum-prosa-kopf { display: block; font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); margin-bottom: 4px; }
.zeitraum-zeile-titel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zeitraum-zustand { font-family: var(--font-mono); font-size: 10px; width: 12px; flex-shrink: 0; }
.braucht .zeitraum-zustand { color: var(--color-error); font-weight: 700; }
.zustand-erledigt .zeitraum-zustand { color: var(--color-success); }
.zeitraum-worauf { font-size: 11px; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zeitraum-spur { position: relative; min-height: 30px; overflow: hidden; }
.zeitraum-gitter { position: absolute; top: 0; bottom: 0; width: 0; border-left: 1px dashed var(--border-strong); }

/* Balken = Spanne; Tönung nach Zustand der Zeile. Mindestbreite, damit eine kurze Spanne nicht verschwindet. */
.zeitraum-seg { position: absolute; top: 5px; bottom: 5px; min-width: 6px; box-sizing: border-box; border: 1px solid var(--text-primary); background: var(--accent-bg); color: var(--text-primary); font-family: var(--font-mono); font-size: 10px; line-height: 18px; padding: 0 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: pointer; text-align: left; }
.zeitraum-seg span { display: block; overflow: hidden; text-overflow: ellipsis; }
.zustand-erledigt .zeitraum-seg { background: var(--color-success-bg); }
.braucht .zeitraum-seg { background: var(--color-warning-bg); }
.zustand-unbekannt .zeitraum-seg, .zustand-verdraengt .zeitraum-seg { background: var(--surface); border-style: dashed; color: var(--text-secondary); }
.zeitraum-seg.laeuft { border-right-style: dotted; border-right-width: 2px; }

/* Achse oben: Tagesmarken fett, Stunden leise. */
.zeitraum-achse .zeitraum-spur, .zeitraum-achse .zeitraum-zeile-kopf { min-height: 22px; }
.zeitraum-marke { position: absolute; top: 4px; transform: translateX(-50%); font-family: var(--font-mono); font-size: 9px; color: var(--text-muted); white-space: nowrap; }
.zeitraum-marke.tag { color: var(--text-primary); font-weight: 600; }

/* Ereigniszeile: Punkte auf der Spur, Liste darunter. */
.zeitraum-ereignisse .zeitraum-spur, .zeitraum-ereignisse .zeitraum-zeile-kopf { min-height: 22px; }
.zeitraum-punkt { position: absolute; top: 50%; width: 8px; height: 8px; transform: translate(-50%, -50%); background: var(--text-primary); }
.zeitraum-punkt.art-wartet, .zeitraum-punkt.art-risk { background: var(--color-warning); }
.zeitraum-punkt.art-erledigt, .zeitraum-punkt.art-result { background: var(--color-success); }
.zeitraum-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; font-size: 12px; }
.zeitraum-liste li { display: grid; grid-template-columns: 110px 96px 1fr; gap: 8px; align-items: baseline; }
.zeitraum-liste-zeit { font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary); }
.zeitraum-liste-art { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; }
.zeitraum-liste-art.art-wartet, .zeitraum-liste-art.art-risk { color: var(--color-warning); }
.zeitraum-liste-art.art-erledigt, .zeitraum-liste-art.art-result { color: var(--color-success); }
.zeitraum-legende { font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary); }
.zeitraum-liste-mehr { display: block; padding-top: 2px; }

/* Telefon: Kopf über der Spur, nur Tagesmarken, Liste umbrechend. */
@media (max-width: 768px) {
  .zeitraum-zeile { grid-template-columns: 1fr; }
  .zeitraum-zeile-kopf { border-right: 0; border-bottom: 1px dashed var(--border); }
  .zeitraum-achse .zeitraum-zeile-kopf { display: none; }
  .zeitraum-marke:not(.tag) { display: none; }
  .zeitraum-liste li { display: flex; flex-wrap: wrap; gap: 2px 8px; }
  .zeitraum-liste-text { flex-basis: 100%; }
}
.agent-hierarchy-overlay {
  position: fixed;
  inset: 0;
  z-index: 280;
  background: var(--surface);
  color: var(--text-primary);
}

.agent-hierarchy-canvas {
  position: relative;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  touch-action: none;
  background:
    radial-gradient(circle at 30% 46%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 38%),
    var(--bg-inset);
  cursor: grab;
  user-select: none;
}

.agent-hierarchy-canvas:active { cursor: grabbing; }

.agent-hierarchy-grid,
.agent-hierarchy-world,
.agent-hierarchy-edges {
  position: absolute;
  inset: 0;
}

.agent-hierarchy-grid { pointer-events: none; }

.agent-hierarchy-world {
  transform-origin: 0 0;
  will-change: transform;
}

.agent-hierarchy-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 8px;
  padding: 24px;
  color: var(--text-muted);
  text-align: center;
  pointer-events: none;
}

.agent-hierarchy-empty strong {
  color: var(--text-primary);
  font: 600 12px/1.3 var(--font-heading);
}

.agent-hierarchy-empty span {
  max-width: 430px;
  font: 10px/1.5 var(--font-mono);
}

.agent-hierarchy-edges {
  overflow: visible;
  pointer-events: none;
}

.agent-hierarchy-edges path {
  fill: none;
  stroke: color-mix(in srgb, var(--accent) 58%, var(--border));
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.agent-hierarchy-node {
  position: absolute;
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid color-mix(in srgb, var(--border-strong) 82%, var(--accent));
  background: color-mix(in srgb, var(--surface) 94%, var(--accent));
  color: var(--text-primary);
  font: inherit;
  text-align: left;
  clip-path: polygon(10px 0, calc(100% - 10px) 0, 100% 10px, 100% calc(100% - 10px), calc(100% - 10px) 100%, 10px 100%, 0 calc(100% - 10px), 0 10px);
  box-shadow: 0 9px 24px rgba(0, 0, 0, 0.11);
  cursor: pointer;
}

.agent-hierarchy-node:hover,
.agent-hierarchy-node.is-selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--surface) 86%, var(--accent));
}

.agent-hierarchy-node.is-active-agent {
  box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 10%, transparent), 0 12px 30px rgba(0, 0, 0, 0.13);
}

.agent-hierarchy-node.has-problem {
  border-style: dashed;
  border-color: var(--color-warning);
}

.agent-hierarchy-node.is-ungrouped {
  border-color: var(--border);
  background: var(--surface);
}

.agent-hierarchy-avatar {
  display: grid;
  width: 38px;
  height: 38px;
  place-items: center;
  overflow: hidden;
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-light));
  color: var(--accent);
  clip-path: polygon(25% 0, 75% 0, 100% 25%, 100% 75%, 75% 100%, 25% 100%, 0 75%, 0 25%);
}

.agent-hierarchy-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.agent-hierarchy-node-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 3px;
}

.agent-hierarchy-node-copy strong,
.agent-hierarchy-node-copy span,
.agent-hierarchy-node-copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-hierarchy-node-copy strong {
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: 650;
}

.agent-hierarchy-node-copy span {
  color: var(--text-secondary);
  font-size: 10px;
}

.agent-hierarchy-node-copy small {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
}

.agent-hierarchy-state-dot {
  width: 7px;
  height: 7px;
  background: var(--text-muted);
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}

.state-working .agent-hierarchy-state-dot { background: var(--color-warning); }
.state-available .agent-hierarchy-state-dot { background: var(--color-success); }
.state-waiting .agent-hierarchy-state-dot { background: var(--color-info); }
.state-error .agent-hierarchy-state-dot { background: var(--color-error); }
.state-offline .agent-hierarchy-state-dot { background: var(--text-muted); }

.agent-hierarchy-problem {
  position: absolute;
  right: 10px;
  bottom: 8px;
  color: var(--color-warning);
}

.agent-hierarchy-controls,
.agent-hierarchy-legend,
.agent-hierarchy-selection {
  position: absolute;
  z-index: 4;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 12px 38px color-mix(in srgb, var(--text-primary) 12%, transparent);
}

.agent-hierarchy-controls {
  right: 12px;
  bottom: 12px;
  display: flex;
  align-items: stretch;
}

.agent-hierarchy-controls button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 34px;
  min-height: 36px;
  padding: 5px 9px;
  border: 0;
  border-left: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font: 600 9px/1 var(--font-mono);
  text-transform: uppercase;
  cursor: pointer;
}

.agent-hierarchy-controls button:first-child { border-left: 0; }
.agent-hierarchy-controls button:hover { color: var(--text-primary); background: var(--hover-bg); }

.agent-hierarchy-zoom-value {
  min-width: 42px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  text-align: center;
}

.agent-hierarchy-legend {
  left: 12px;
  bottom: 12px;
  display: flex;
  gap: 12px;
  padding: 7px 9px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
}

.agent-hierarchy-contract {
  padding-left: 10px;
  border-left: 1px solid var(--border);
}

.agent-hierarchy-count { color: var(--text-muted); }

.agent-hierarchy-legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.agent-hierarchy-legend i {
  width: 18px;
  border-top: 2px solid var(--accent);
}

.agent-hierarchy-legend i.is-problem {
  border-color: var(--color-warning);
  border-top-style: dashed;
}

.agent-hierarchy-legend i.is-ungrouped {
  border-color: var(--text-muted);
  border-top-style: dotted;
}

.agent-hierarchy-selection {
  top: 12px;
  right: 12px;
  display: flex;
  width: min(320px, calc(100% - 24px));
  flex-direction: column;
  gap: 7px;
  padding: 12px;
}

.agent-hierarchy-selection strong { font-family: var(--font-heading); }

.agent-hierarchy-selection span,
.agent-hierarchy-selection em {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-secondary);
  font-size: 11px;
  font-style: normal;
}

.agent-hierarchy-selection small {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 9px;
}

.agent-hierarchy-selection em { color: var(--color-warning); }

.agent-hierarchy-selection button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  border: 1px solid var(--border-strong);
  background: var(--bg-light);
  color: var(--text-primary);
  cursor: pointer;
}

@media (max-width: 700px) {
  .agent-hierarchy-count,
  .agent-hierarchy-controls button span,
  .agent-hierarchy-legend > span:not(.agent-hierarchy-contract) { display: none; }
  .agent-hierarchy-controls { right: 8px; bottom: 8px; }
  .agent-hierarchy-legend { left: 8px; bottom: 8px; }
  .agent-hierarchy-contract { padding-left: 0; border-left: 0; }
  .agent-hierarchy-selection { top: 8px; right: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .agent-hierarchy-world { will-change: auto; }
}
.queue-chat {
  height: calc(var(--vh, 1vh) * 100);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  font-family: var(--font-body);
  max-width: 600px;
  margin: 0 auto;
}

.qc-header {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.qc-title {
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-primary);
}

.qc-stream {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 16px;
  min-height: 0;
  min-width: 0;
  -webkit-overflow-scrolling: touch;
}

.qc-stream * { max-width: 100%; }

.qc-turn {
  margin-bottom: 16px;
}

.qc-user {
  display: flex;
  gap: 8px;
  margin-bottom: 6px;
}

.qc-user-marker {
  width: 3px;
  background: var(--color-info);
  flex-shrink: 0;
  align-self: stretch;
}

.qc-user-text {
  font-size: 14px;
  color: var(--text-primary);
  line-height: 1.5;
}

.qc-agent {
  padding-left: 11px;
}

.qc-text {
  font-size: 15px;
  line-height: 1.6;
  color: var(--text-primary);
  overflow-wrap: break-word;
}

.qc-text p { margin: 0 0 6px; font-size: 15px; }
.qc-text p:last-child { margin-bottom: 0; }
.qc-text code { font-family: var(--font-mono); font-size: 13px; background: var(--bg-inset); padding: 1px 4px; }
.qc-text a { color: var(--color-info); }
.qc-text ul, .qc-text ol { font-size: 15px; padding-left: 20px; }
.qc-text li { font-size: 15px; }
.qc-text img { max-width: 100%; height: auto; display: block; border: 1px solid var(--border); margin: 6px 0; }
.qc-text video, .qc-text audio { max-width: 100%; }
.qc-text pre { max-width: 100%; overflow-x: auto; }

.qc-tool {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  padding: 2px 0;
}

.qc-sending {
  display: flex;
  gap: 4px;
  padding: 8px 11px;
}

.qc-sending span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-muted);
  animation: qc-bounce 1.2s infinite ease-in-out;
}

.qc-sending span:nth-child(2) { animation-delay: 0.2s; }
.qc-sending span:nth-child(3) { animation-delay: 0.4s; }

@keyframes qc-bounce {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

.qc-input-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

.qc-input {
  flex: 1;
  padding: 8px 0;
  font-family: var(--font-body);
  font-size: 16px;
  border: none;
  border-bottom: 1px solid var(--border);
  outline: none;
  background: transparent;
  color: var(--text-primary);
  resize: none;
  overflow-y: hidden;
  line-height: 1.4;
}

.qc-input::placeholder { color: var(--text-muted); }
.qc-input:focus { border-bottom-color: var(--text-primary); }

.qc-btn {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--border);
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
  transition: all 0.15s ease;
}

.qc-btn:hover {
  border-color: var(--text-primary);
  color: var(--text-primary);
}

.qc-send {
  background: var(--chip-active-bg);
  border-color: var(--text-primary);
  color: var(--white);
}

.qc-send:hover { background: var(--black); }

.qc-cancel {
  color: var(--text-muted);
}

.qc-cancel:hover {
  color: var(--color-error);
  border-color: var(--color-error);
}

.qc-recording-label {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--color-success);
  text-align: center;
}
.login-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  width: 100vw;
  background: var(--surface);
}

.login-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 48px;
}

.login-logo {
  font-family: var(--font-heading);
  font-size: 24px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.login-logo span {
  color: var(--accent);
}

.login-subtitle {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 40px;
}

/* EIN Knopf-Stil fuer ALLE Anbieter (#4854).
 *
 * Vorher hiess die Klasse `.login-google-btn` und war damit nach dem Anbieter
 * benannt, obwohl sie nur den Haus-Stil traegt: flach, eckig, dunkel. Ein
 * zweiter Anbieter haette entweder die Google-Klasse mitbenutzt (dann steht
 * „Google" im Markup eines Microsoft-Knopfes) oder eine Kopie bekommen. Die
 * Marke steckt jetzt ausschliesslich im Zeichen, nie im Rahmen. */
.login-oauth-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Gleiche Breite fuer alle: Untereinander stehende Knoepfe mit
     unterschiedlich langem Text saehen sonst wie ein Fehler aus. */
  align-self: stretch;
  min-width: 260px;
  background: var(--chip-active-bg);
  color: var(--white);
  border: none;
  border-radius: 0;
  padding: 14px 28px;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease;
}

/* Abstand NUR zwischen zwei Knoepfen, nicht ueber dem ersten — sonst
   verschoebe ein zweiter Anbieter die ganze Karte. */
.login-oauth-btn + .login-oauth-btn {
  margin-top: 10px;
}

.login-oauth-btn:hover {
  background: var(--black);
}

.login-error {
  margin-top: 16px;
  color: var(--accent);
  font-size: 13px;
}

.login-toggle-email {
  margin-top: 12px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 12px;
  cursor: pointer;
  text-decoration: underline;
}

.login-toggle-email:hover {
  color: var(--text-primary);
}

.login-email-form {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.login-email-form input {
  padding: 10px 12px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-primary);
}

.login-email-form input:focus {
  outline: none;
  border-color: var(--text-primary);
}

.login-submit-btn {
  padding: 10px 14px;
  background: var(--chip-active-bg);
  color: var(--white);
  border: none;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
}

.login-submit-btn:hover:not(:disabled) {
  background: var(--black);
}

.login-submit-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* auth: null — Einrichtungs-Zustand, kein Login-Fehler (77eb0c9) */
.login-setup-note {
  margin: 18px 0 6px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-primary);
}
.login-setup-tech {
  margin: 0;
  font-size: 11px;
  color: var(--text-secondary, #888);
}
.login-setup-tech code { font-size: 11px; }
/* Public, pre-auth pages (Onboarding, Datenschutz, Impressum, Support).
   Reachable WITHOUT a login — see App.tsx, the check sits deliberately in front
   of the `if (!user)` gate. Before this existed, agentos/cloud2 answered every
   path with the login mask, so /privacy returned HTTP 200 showing a sign-in form
   — worse than a 404 for an App Store reviewer, because it looks like a working
   link to the wrong content.
   Uses the app's own theme tokens so a visitor arriving from the product
   recognises it, and so dark mode works without a second implementation. */

.pub {
  /* Das App-CSS setzt html/body auf overflow:hidden (SPA scrollt in eigenen
     Containern) — die öffentliche Seite muss deshalb SELBST scrollen, sonst
     steht sie auf dem Handy fest (Alex, 15.08.). 100dvh statt 100vh, damit
     die mobile Browser-Leiste nichts abschneidet. */
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* #root ist `display:flex` (iOS-Tastatur-Fix, 602f0b9). Ohne `flex: 1`
     schrumpft .pub als Flex-Element auf die Breite seines Inhalts — also auf
     die 860px von .pub-main — und klebt am linken Rand. Auf dem Telefon fällt
     das nicht auf, am Bürorechner steht die ganze Seite in der linken Hälfte
     (Marketing hat es bei 1920px gemessen: .pub bei x=0, 860px breit,
     rechts 1060px leer). Der Bürorechner ist der erste Eindruck. */
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  color: var(--text-body);
  font-family: var(--font-body);
}

.pub-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.pub-brand {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 16px;
  color: var(--text-primary);
  text-decoration: none;
}

.pub-nav {
  display: flex;
  gap: 18px;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

.pub-nav a {
  color: var(--text-muted);
  text-decoration: none;
}

.pub-nav a:hover {
  color: var(--text-primary);
}

.pub-main {
  flex: 1;
  width: 100%;
  max-width: 860px;
  margin: 0 auto;
  padding: 48px 24px 64px;
}

.pub-main.narrow {
  max-width: 620px;
}

.pub h1 {
  font-family: var(--font-heading);
  font-size: 30px;
  line-height: 1.25;
  margin: 0 0 14px;
  color: var(--text-primary);
}

.pub h2 {
  font-family: var(--font-heading);
  font-size: 18px;
  margin: 36px 0 10px;
  color: var(--text-primary);
}

.pub h3 {
  font-size: 15px;
  margin: 0 0 6px;
  color: var(--text-primary);
}

.pub p {
  line-height: 1.65;
}

.pub-eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin: 0 0 10px;
}

.pub-lede {
  font-size: 17px;
  color: var(--text-muted);
  margin: 0 0 26px;
  line-height: 1.6;
}

/* ---- feature grid ---- */

.pub-features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  margin: 32px 0;
}

.pub-feature {
  background: var(--surface);
  padding: 18px;
}

.pub-feature p {
  margin: 0;
  color: var(--text-muted);
  font-size: 14px;
}

/* ---- buttons ---- */

.pub-btn {
  display: inline-block;
  border: 1px solid var(--text-primary);
  background: var(--text-primary);
  color: var(--surface);
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  font-family: var(--font-body);
}

.pub-btn:hover:not(:disabled) {
  opacity: 0.86;
}

.pub-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.pub-btn-ghost {
  background: transparent;
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.pub-cta {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 24px;
}

/* ---- form ---- */

.pub-field {
  margin-bottom: 16px;
}

.pub-field label {
  display: block;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  margin-bottom: 5px;
}

.pub-field input {
  width: 100%;
  padding: 10px 11px;
  border: 1px solid var(--border-strong);
  background: var(--bg-inset);
  color: var(--text-body);
  font-size: 15px;
  font-family: var(--font-body);
  border-radius: 0;
}

.pub-field input:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.pub-row2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

@media (max-width: 520px) {
  .pub-row2 {
    grid-template-columns: 1fr;
  }
}

.pub-hint {
  font-size: 13px;
  color: var(--text-muted);
  margin: -8px 0 16px;
}

.pub-error {
  border: 1px solid var(--color-error);
  background: var(--color-error-bg);
  padding: 11px 13px;
  margin-bottom: 16px;
  font-size: 14px;
}

/* ---- notices ---- */

.pub-notice {
  background: var(--bg-light);
  border-left: 3px solid var(--accent);
  padding: 13px 15px;
  margin: 22px 0;
  font-size: 14.5px;
}

.pub-notice p {
  margin: 0 0 7px;
}

.pub-notice p:last-child {
  margin-bottom: 0;
}

.pub-stub {
  background: var(--color-warning-bg);
  border: 1px solid var(--color-warning);
  padding: 15px 17px;
  margin: 22px 0;
  font-size: 14.5px;
}

.pub-stub strong {
  display: block;
  margin-bottom: 5px;
}

/* Fehlende Betreiber-Angabe — sichtbar als Platzhalter statt als erfundener
   Wert. Soll auffallen: eine Anschrift, die niemand eingetragen hat, darf im
   Impressum nicht wie eine Anschrift aussehen. */
.pub-placeholder {
  background: var(--color-warning-bg);
  border: 1px dashed var(--color-warning);
  color: var(--text-primary);
  padding: 1px 6px;
  font-family: var(--font-mono);
  font-size: 0.85em;
}

/* ---- table ---- */

.pub table {
  width: 100%;
  border-collapse: collapse;
  margin: 14px 0;
  font-size: 14.5px;
}

.pub th,
.pub td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.pub th {
  color: var(--text-primary);
  font-weight: 600;
}

/* ---- footer ---- */

.pub-foot {
  border-top: 1px solid var(--border);
  padding: 20px 24px;
  display: flex;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--text-muted);
}

.pub-foot a {
  color: var(--text-muted);
  margin-right: 16px;
}

/* SaaS-Anwerbe-Seite (/product) — eigener Klassenname: .pub-cta gehört
   bereits der Onboarding-Button-Reihe weiter oben. */
.pub-sales-cta {
  margin: 40px 0 8px;
  padding: 28px;
  border: 1px solid var(--border);
  text-align: center;
}
.pub-sales-cta h2 { margin: 0 0 8px; }
.pub-sales-cta p { margin: 0 auto 18px; max-width: 560px; }
.pub-cta-btn {
  display: inline-block;
  padding: 12px 28px;
  background: var(--text-primary, #111);
  color: var(--surface, #fff);
  text-decoration: none;
  font-weight: 600;
}
.pub-cta-btn:hover { opacity: 0.85; }

/* Produktseiten-Grafiken — inline-SVG folgt currentColor (hell + dunkel) */
.pub-hero-art {
  display: block;
  margin: 32px auto 8px;
  max-width: 820px;
  color: var(--text-primary);
}
.pub-hero-art svg { display: block; width: 100%; height: auto; }
.pub-feature-art {
  display: block;
  width: 40px;
  height: 40px;
  margin-bottom: 12px;
  color: var(--text-primary);
}
.pub-feature-art svg { display: block; width: 100%; height: 100%; }
.agent-switch-modal {
  max-width: 600px;
}

.agent-switch-warning {
  color: var(--text-secondary, #b8b8c3);
}

.agent-switch-warning strong {
  color: var(--color-warning, #d97706);
}

.agent-switch-route {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 18px 20px 4px;
  color: var(--text-muted);
}

.agent-switch-node {
  min-width: 120px;
  padding: 8px 12px;
  border: 1px solid var(--border);   /* war `--border-subtle`, existiert nicht */
  border-radius: 7px;
  text-align: center;
  font: 600 13px/1.2 var(--font-mono, monospace);
}

.agent-switch-node.current {
  color: var(--text-muted);
}

.agent-switch-node.target {
  border-color: color-mix(in srgb, var(--accent) 65%, transparent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

.agent-switch-grid {
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  gap: 12px;
  margin: 14px 20px 4px;
}

.agent-switch-field {
  margin: 0;
}

.agent-switch-select {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 9px 10px;
  background: var(--surface-elevated, rgba(255, 255, 255, 0.04));
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.12));
  border-radius: 6px;
  color: var(--text-primary);
  font: 13px var(--font-mono, monospace);
}

.agent-switch-select:disabled {
  opacity: 0.55;
}

.agent-switch-check,
.agent-switch-ack,
.agent-switch-error {
  margin: 14px 20px 0;
}

.agent-switch-check span {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.agent-switch-check small {
  color: var(--text-muted);
}

.agent-switch-error {
  padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--color-error, #dc2626) 35%, transparent);
  border-radius: 6px;
  background: color-mix(in srgb, var(--color-error, #dc2626) 8%, transparent);
  color: var(--color-error, #dc2626);
  font-size: 12px;
  line-height: 1.45;
}

.agent-switch-submit {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

@media (max-width: 600px) {
  .agent-switch-grid {
    grid-template-columns: 1fr;
  }

  .agent-switch-route {
    gap: 8px;
  }

  .agent-switch-node {
    min-width: 0;
    flex: 1;
  }
}
/* Content of the "Neue Version verfügbar" toast (#194 — now rendered inside the
   generic <Toast>, so this is just the inner version line + changelog + reload
   button; positioning/frame come from the Toast). */
.up-toast { display: flex; flex-direction: column; gap: 3px; align-items: flex-start; }
.up-toast .up-ver { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); }
.up-toast .up-changelog { font-size: 12px; color: var(--text-muted); line-height: 1.35; }
.up-toast .up-reload {
  margin-top: 7px;
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 14px;
  background: var(--chip-active-bg);
  color: var(--white);
  border: none;
  border-radius: 0;
  cursor: pointer;
}
.up-toast .up-reload:hover { background: var(--black); }

/* ── legacy fixed-position styles below are unused since #194 (kept harmless) ── */
.update-prompt {
  position: fixed;
  left: 50%;
  /* Sit ABOVE the composer/mic bar so it isn't hidden behind it in an agent
     or collab chat (Alex 2026-06-23). */
  bottom: calc(env(safe-area-inset-bottom, 0px) + 88px);
  transform: translateX(-50%);
  z-index: 10000;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px 10px 16px;
  background: var(--chip-active-bg);
  color: var(--white);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
  font-family: var(--font-body);
  font-size: 13px;
  max-width: calc(100vw - 32px);
}
/* Post-update confirmation (#141) — restyled to the new card look (Issue #191):
   opaque surface card, rounded, soft shadow, with a green LEFT-stripe as the
   success signal instead of a full green fill. Matches the dispatch-toast
   (dt-card) aesthetic Alex asked us to converge on. */
.update-prompt-ok {
  background: var(--surface);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-left: 3px solid var(--color-success);
  border-radius: 14px;
  padding: 13px 16px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.30);
}
.update-prompt-ok .update-prompt-check { color: var(--color-success); font-weight: 700; }
.update-prompt-ok .update-prompt-dismiss { color: var(--text-muted); }
.update-prompt-text { white-space: nowrap; }
.update-prompt-btn {
  background: var(--surface);
  color: var(--text-primary);
  border: none;
  border-radius: 5px;
  padding: 5px 12px;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
}
.update-prompt-btn:hover { opacity: 0.88; }
.update-prompt-dismiss {
  background: transparent;
  border: none;
  color: var(--white);
  opacity: 0.6;
  cursor: pointer;
  font-size: 13px;
  padding: 2px 4px;
}
.update-prompt-dismiss:hover { opacity: 1; }

/* Version display in the update toast (Alex 2026-06-23). */
.update-prompt-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.update-prompt-ver {
  font-family: var(--font-mono);
  font-size: 10.5px;
  opacity: 0.8;
  white-space: nowrap;
}

/* "Neu: …" changelog line in the update toast (Alex 2026-06-24). */
.update-prompt-changelog {
  display: block;
  font-size: 11px;
  line-height: 1.3;
  opacity: 0.85;
  margin-top: 2px;
}
/* Mobile quick-switcher — full-screen panel (Alex 2026-06-20: no half-sheet
 * with a grey gap; the agents fill the screen). Height tracks the visual
 * viewport (--vh) so it never hides behind Safari's bottom bar. */
.mas-overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;
  height: calc(var(--vh, 1vh) * 100);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  animation: mas-fade 0.14s ease-out;
}
@keyframes mas-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.mas-sheet {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
}

.mas-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 16px calc(env(safe-area-inset-bottom, 0px) + 20px);
}

.mas-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  padding: 16px;
  padding-top: calc(env(safe-area-inset-top, 0px) + 14px);
  border-bottom: 1px solid var(--border);
}
.mas-title {
  font-family: var(--font-heading);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
}
.mas-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 4px;
  background: var(--bg-light);
  color: var(--text-muted);
  cursor: pointer;
}

.mas-band {
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin: 14px 2px 8px;
}
.mas-band:first-of-type {
  margin-top: 2px;
}

.mas-empty {
  padding: 28px 8px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}

.mas-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.mas-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 6px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  cursor: pointer;
  min-height: 96px;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.mas-tile:active {
  background: var(--bg-light);
}
.mas-tile.active {
  border-color: var(--accent);
  background: var(--bg-light);
}

.mas-avatar {
  position: relative;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  overflow: visible;
  flex-shrink: 0;
}
.mas-avatar img {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}
.mas-initial {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg-light);
  color: var(--text-secondary, var(--text-muted));
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: 600;
}
.mas-dot {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid var(--white);
  box-sizing: content-box;
}
.mas-dot.available { background: var(--color-success); }
.mas-dot.working   { background: var(--color-warning); }
.mas-dot.error     { background: var(--color-error); }
.mas-dot.waiting   { background: var(--color-info, #3b82f6); }

.mas-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
  text-align: center;
  line-height: 1.2;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%;
}
.mas-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
}
/* Wer spricht gerade? — rechts unten, nur waehrend die Hintergrundstimme laeuft.
   Flach und eckig wie der Rest des Portals; die Farbe traegt der Orb. */

.sprech-anzeige {
  position: fixed;
  right: max(12px, env(safe-area-inset-right));
  bottom: max(12px, env(safe-area-inset-bottom));
  /* UEBER dem Fuss, nicht darunter.
     ────────────────────────────────────────────────────────────────────────
     Stand hier zuerst auf 60 — und die Kopf-/Fussleisten des Portals liegen
     bei 90 bis 96. Die Anzeige war also von Anfang an verdeckt, und Alex hat
     es dreimal gemeldet, bevor ich an der richtigen Stelle gesucht habe.

     900 liegt zwischen den beiden Welten: hoechstes Rahmenwerk ist 240 (die
     Regler des V2-Rings), niedrigster echter Dialog 3000 (Anmelde-Fenster).
     Eine Anzeige, die sagt wer spricht, darf keinen Dialog zudecken — und
     mein erster Versuch mit 200 lag immer noch unter jenen 240. Gefunden hat
     das der Waechter unten, nicht ich. */
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(480px, calc(100vw - 24px));
  padding: 8px 12px 8px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  /* GANZ ANKLICKBAR — sie fuehrt zum sprechenden Agenten (Alex, 27.08.).
     Vorher stand hier `pointer-events: none` und nur der Name fing Klicks,
     damit die Blase die Bedienung darunter nicht faengt. Der Einwand gilt
     weiter; sie verdeckt dort jetzt Knoepfe, solange sie steht. Sie steht nur,
     waehrend gesprochen wird, plus Nachlauf. */
  pointer-events: auto;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  animation: sprech-herein 0.22s ease-out;
}

.sprech-anzeige:hover { border-color: var(--accent); }
.sprech-anzeige:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.sprech-anzeige.klingt-aus { opacity: 0.55; transition: opacity 0.4s ease; }

@keyframes sprech-herein {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

.sprech-orb {
  /* POSITIONIERT — sonst entkommt der Orb.
     `.audio-blob-field` ist `position: absolute; inset: 0` und sucht sich den
     naechsten POSITIONIERTEN Vorfahren. Ohne diese Zeile war das die ganze
     Blase (`position: fixed`): Das Canvas wurde 420 x 60 statt 44 x 44, der
     Orb schrumpfte auf 30 % der Hoehe und der Rest war deckender
     Hintergrund — Alex' „schwarzes Teil da unten, ich sehe nichts"
     (Screenshot 120855). */
  position: relative;
  flex-shrink: 0;
  /* GROESSER, ZWEITER ANLAUF (Alex, 28.08., Screenshot 120888: „kannst du den
     Orb groesser machen in der Stimme-an-Darstellung, der ist ja viel zu
     klein"). 44 -> 64 war zu zaghaft: Neben drei Zeilen Text verschwand er
     trotzdem.

     96 ist bewusst mehr als die Texthoehe. Der Orb ist das SIGNAL — er
     beantwortet aus dem Augenwinkel „spricht gerade jemand?"; der Name
     beantwortet erst danach „wer?". Ein Zeichen, das kleiner ist als seine
     Beschriftung, hat die Rollen vertauscht. Die Blase waechst dadurch mit,
     das ist gewollt. */
  display: block;
  width: 96px;
  height: 96px;
}

.sprech-orb-feld { width: 100%; height: 100%; }

.sprech-text {
  min-width: 0;          /* sonst sprengt ein langer Satz den Kasten */
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sprech-name {
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-primary);
}

.sprech-anzeige:hover .sprech-name { color: var(--accent); }

/* Der Satz wird gekuerzt, nicht abgeschnitten: zwei Zeilen, dann Ellipse.
   Ein vorgelesener Absatz waere sonst eine Wand ueber der halben Ansicht. */
.sprech-satz {
  margin: 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (max-width: 600px) {
  .sprech-anzeige { max-width: calc(100vw - 24px); }
  .sprech-orb { width: 76px; height: 76px; }
  .sprech-satz { -webkit-line-clamp: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .sprech-anzeige { animation: none; }
  .sprech-anzeige.klingt-aus { transition: none; }
}

/* Stimme an, aber blockiert oder gestoert — das MUSS man sehen.
   Schweigen waere hier nicht von „gerade spricht niemand" zu unterscheiden. */
.sprech-anzeige.stoerung {
  border-left: 2px solid var(--color-warning);
}

/* Der Name ist hier keine Schaltflaeche, sieht aber gleich aus. */
.sprech-name.als-text { cursor: default; color: var(--color-warning); }

/* Die Stoerungsfassung ist eine Meldung, keine Schaltflaeche — sie hat
   keinen Agenten, zu dem sie fuehren koennte. */
.sprech-anzeige.stoerung { pointer-events: none; cursor: default; }
/* Ambient video backdrop (Alex 2026-06-23). Sits at z-index:-1 INSIDE #root,
   so it paints above body's opaque --surface but behind every panel (the
   panels have no background of their own — only body does). Result: a frosted,
   heavily-blurred moving wash behind the whole UI, with text/cards floating on
   it (glassmorphism). pointer-events:none so it never intercepts clicks. */
.bgv {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}

.bgv-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Blur is slider-driven (Alex 2026-07-15: "von nicht durchschaubar bis voll
     transparent") — --ambient-blur comes from the glass-intensity slider
     (bgVideo.ts applyVeil): ~19px near-clear … ~87px milk glass, default ≈55px.
     scale() hides the transparent halo the blur leaves at the edges.
     saturate lowered 1.35→1.12 — the warm clips washed the UI too peachy
     (Alex 2026-07-14, mobile). */
  filter: blur(var(--ambient-blur, 55px)) saturate(1.12);
  transform: scale(1.12);
  opacity: 1;
  transition: opacity 1.4s ease;
}
.bgv-video.fading { opacity: 0; }

/* Frost veil — a --surface tint over the video so the UI stays readable and
   the motion is subtle. Theme-aware (flips with light/dark via --surface). */
.bgv-frost {
  position: absolute;
  inset: 0;
  /* Intensity is user-tunable (Settings slider → --ambient-frost, bgVideo.ts). */
  background: color-mix(in srgb, var(--surface) var(--ambient-frost, 55%), transparent);
}

/* Ambient-visible mode (Alex 2026-07-14, v2): keep the veil LIGHT so the moving
   backdrop clearly shows through the chat — and get text legibility from a
   TEXT-side halo, NOT an opaque box. The surface-coloured text-shadow gives every
   glyph its own tiny frosted scrim (light halo in light theme, dark in dark), so
   body copy stays crisp while ~40% of the ambient shows behind it. */
[data-bg="on"] .content-stream {
  background: color-mix(in srgb, var(--surface) var(--ambient-veil, 58%), transparent);
}
/* Halo ONLY on naked agent prose that sits directly on the ambient. */
[data-bg="on"] .content-stream .entry-content {
  text-shadow: 0 0 4px var(--surface), 0 0 9px var(--surface);
}
/* Elements with their OWN opaque background (user-input cards, tool/code cards)
   do NOT sit on the ambient → the surface-coloured halo just glows around their
   (often white) text (Alex 2026-07-14 "glow on white text"). Reset it there. */
[data-bg="on"] .content-stream .entry-user .entry-content,
[data-bg="on"] .content-stream .tool-call,
[data-bg="on"] .content-stream .code-block,
[data-bg="on"] .content-stream pre {
  text-shadow: none;
}

/* Flowing glass — with ambient on, the bars are ALWAYS transparent and frost
   purely via backdrop-blur (the two sliders control tint + blur). The old
   "Kräftige Leisten" solid mode is gone: its fixed 72% white tint on header/
   footer fought the sliders and read as a stuck "default white" (Alex). */
[data-bg="on"] .agent-header,
[data-bg="on"] .agent-footer,
[data-bg="on"] .collab-top,
[data-bg="on"] .collab-footer {
  background: transparent;
}

/* Sidebar matches the main panel when ambient is on (Alex 2026-07-15): the
   opaque --surface slab becomes the same translucent veil as .content-stream,
   so the moving backdrop shows through the session list too. Tracks the slider. */
[data-bg="on"] .sidebar {
  background: color-mix(in srgb, var(--surface) var(--ambient-veil, 58%), transparent);
}

/* Header must look IDENTICAL to the list below (Alex 2026-07-15: the top was a
   darker slab). The single veil lives on .sidebar; if the header ALSO tinted, its
   region got two veil layers → darker + a visible seam under FLAT. So the header
   is TRANSPARENT here and relies purely on its backdrop-blur to frost/mask the
   list items scrolling under it — same brightness as the list, no double-tint. */
[data-bg="on"] .sidebar-header {
  background: transparent;
}

/* Panel backdrop-blur tracks the glass slider too (Alex 2026-07-15: at slider 0
   the footer + sidebar-header still frosted through their FIXED 14px blur while
   list/main were already crystal). --glass-blur/-sat come from applyVeil:
   0px/1.0 at raw-video, ~14px/1.5 at default — the previous constant look.
   html-prefixed for specificity over the per-component base rules. */
html[data-bg="on"] .agent-header,
html[data-bg="on"] .agent-footer,
html[data-bg="on"] .agent-footer .input-bar-wrap,
html[data-bg="on"] .collab-footer .input-bar-wrap,
html[data-bg="on"] .collab-top,
html[data-bg="on"] .collab-footer,
html[data-bg="on"] .sidebar-header {
  -webkit-backdrop-filter: blur(var(--glass-blur, 14px)) saturate(var(--glass-sat, 1.5));
  backdrop-filter: blur(var(--glass-blur, 14px)) saturate(var(--glass-sat, 1.5));
}

/* The input bar's glass tint lives on .input-bar-wrap INSIDE the footer (not on
   .agent-footer), so the text-input band stayed an opaque slab while everything
   else flowed (Alex 2026-07-15). Transparent too — backdrop-blur keeps frosting
   the content scrolling beneath. */
[data-bg="on"] .agent-footer .input-bar-wrap,
[data-bg="on"] .collab-footer .input-bar-wrap {
  background: transparent;
}

/* The EMPTY-input (mic-solo) variant frosts through its own :before pane —
   which had no ambient override and painted a 72%/opaque surface band (the
   stubborn WHITE footer, Alex 2026-07-15: white only while the field was empty,
   gone as soon as you typed). Track the sliders there too. html-prefixed to
   outrank the base + @supports-fallback rules. */
html[data-bg="on"] .input-bar-wrap:has(.input-action.mic-solo)::before,
html[data-bg="on"] .agent-footer .input-bar-wrap:has(.input-action.mic-solo)::before,
html[data-bg="on"] .collab-footer .input-bar-wrap:has(.input-action.mic-solo)::before {
  background: transparent;
  -webkit-backdrop-filter: blur(var(--glass-blur, 14px)) saturate(var(--glass-sat, 1.5));
  backdrop-filter: blur(var(--glass-blur, 14px)) saturate(var(--glass-sat, 1.5));
}
.status-toasts {
  position: fixed;
  /* Up high + horizontally centered (was bottom-right, cramped against the nav) so the
     notice is prominent + easy to read (Alex #179). Still slides in from the side. */
  left: 50%;
  top: max(84px, 15vh);
  transform: translateX(-50%);
  z-index: 1200;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: min(440px, calc(100vw - 24px));
}
/* Desktop: anchor to the RIGHT edge instead of centered — the toast slides in
   from the right (stoast-in) and sits flush at the right margin (Alex #189).
   Mobile keeps the centered placement (#179), where a right-edge card would
   crowd the narrow screen. */
@media (min-width: 768px) {
  .status-toasts {
    left: auto;
    right: 20px;
    transform: none;
  }
}
.status-toast {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 13px 15px;
  background: var(--surface);
  /* Accent frame, not red — only the ⚠ icon stays red (Alex, #161). */
  border: 1px solid var(--accent);
  border-left-width: 3px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  /* Slide in from the SIDE — this is a federation-wide notice (a blocked agent), NOT
     about the agent you're viewing. The horizontal entrance signals "this came from
     outside / it's global", so it doesn't read as the current agent's status (Alex #165).
     Agent-tied status (outbox retry, intake result) stays in place, in the agent view. */
  animation: stoast-in 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes stoast-in { from { opacity: 0; transform: translateX(115%); } to { opacity: 1; transform: translateX(0); } }
.status-toast-icon { color: var(--color-error); flex-shrink: 0; margin-top: 1px; }
/* Dispatch notice (#1257) — info-blue frame + send icon, distinct from the blocked red. */
.status-toast-dispatch { border-color: var(--color-info); }
.status-toast-dispatch-icon { color: var(--color-info); flex-shrink: 0; margin-top: 1px; }
/* Auto-login-stopped alert (Cloud #182) — red warn frame, not the friendly accent.
   The red tint is LAYERED over the opaque surface (gradient-over-surface), not used as
   the background directly: --color-error-bg is translucent, so using it raw let the chat
   text bleed through and overlap (Alex, 2026-06-30). Stacking keeps the red wash but the
   final pixel stays opaque. */
.status-toast-login {
  border-color: var(--color-error);
  background: linear-gradient(var(--color-error-bg), var(--color-error-bg)), var(--surface);
}
.status-toast-tag {
  display: inline-block;
  margin-left: 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-info);
  border: 1px solid var(--color-info);
  padding: 0 4px;
}

/* ── Dispatch card (redesign, Alex 2026-06-30) — rounded, avatar, agent pill, big title,
   divider + "Details öffnen" action. Deliberately soft/rounded (not the flat default) per
   Alex's reference design. ───────────────────────────────────────────────────────────── */
.dt-card {
  display: flex;
  flex-direction: column;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--color-info);
  border-radius: 14px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.30);
  cursor: pointer;
  animation: stoast-in 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}
.dt-top { display: flex; align-items: center; gap: 13px; }
.dt-avatar {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid var(--color-info);
  background: var(--color-info-bg, rgba(96, 165, 250, 0.13));
  color: var(--color-info);
  display: flex;
  align-items: center;
  justify-content: center;
}
.dt-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.dt-head { display: flex; align-items: center; gap: 8px; }
.dt-issue {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
  flex-shrink: 0;
}
.dt-pill {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-info);
  background: var(--color-info-bg, rgba(96, 165, 250, 0.15));
  border-radius: 10px;
  padding: 1px 9px;
  flex-shrink: 0;
}
.dt-pill-queue { color: var(--text-muted); background: var(--bg-light); }
.dt-now { margin-left: auto; font-size: 11px; color: var(--text-muted); flex-shrink: 0; }
.dt-x {
  background: none; border: none; color: var(--text-muted);
  cursor: pointer; display: inline-flex; padding: 0; flex-shrink: 0;
}
.dt-x:hover { color: var(--text-primary); }
.dt-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.3;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.dt-action {
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  font-weight: 500;
  color: var(--color-info);
}
.status-toast-text { flex: 1; min-width: 0; font-size: 14.5px; color: var(--text-primary); line-height: 1.42; }
.status-toast-text strong { font-weight: 600; }
.status-toast-sum { display: block; font-size: 12.5px; color: var(--text-muted); margin-top: 3px; }
.status-toast-close {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  display: inline-flex;
}
.status-toast-close:hover { color: var(--text-primary); }
/* Generic messaging component (Issue #194). Card look shared with the dispatch
   dt-card: opaque surface, rounded, soft shadow, a 3px variant-colored left
   stripe (blue/red/green). Slides in from the right + fades; auto-hide toasts
   fade back out the same way. */

.toast {
  position: relative;   /* anchors the countdown bar */
  overflow: hidden;      /* keeps the bar inside the square edges */
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 13px 15px;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  border: 1px solid var(--border);
  border-left: 3px solid var(--color-info);
  /* Square, not rounded — matches the flat/square house style (Alex 2026-07-01). */
  border-radius: 0;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.30);
  animation: toast-in 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}
.toast-clickable { cursor: pointer; }

/* Variant = left stripe + icon color. info=blue, error=red, success=green. */
.toast-info { border-left-color: var(--color-info); }
.toast-error { border-left-color: var(--color-error); }
.toast-success { border-left-color: var(--color-success); }
.toast-pending { border-left-color: var(--color-warning); }

.toast-icon { flex-shrink: 0; margin-top: 1px; display: inline-flex; }
.toast-info .toast-icon { color: var(--color-info); }
.toast-error .toast-icon { color: var(--color-error); }
.toast-success .toast-icon { color: var(--color-success); }
.toast-pending .toast-icon { color: var(--color-warning); animation: toast-spin 1.1s linear infinite; }
@keyframes toast-spin { to { transform: rotate(360deg); } }

.toast-body { flex: 1; min-width: 0; }
.toast-title { font-size: 14.5px; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
.toast-msg { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; line-height: 1.4; word-break: break-word; }
.toast-title + .toast-msg { margin-top: 3px; }

.toast-x {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px 3px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
}
.toast-x:hover { color: var(--text-primary); }

/* AM TELEFON MUSS MAN ES TREFFEN.
   2px Innenabstand ergeben ein Ziel von rund 19px — unter jeder Empfehlung
   (44px) und in der Praxis ein mehrfaches Danebentippen. Ein Notausgang, den
   man nicht trifft, ist keiner; genau darum ging es bei Alex' Beschwerde.
   Der Hinweis selbst bleibt anklickbar (öffnet den Agenten) — das X liegt
   darüber und stoppt die Ausbreitung. */
@media (pointer: coarse), (max-width: 600px) {
  .toast-x {
    padding: 11px;
    margin: -11px -8px -11px 0;   /* Zielfläche wachsen lassen, Layout nicht */
  }
}

/* Enter from the right + fade; leave the same way (auto-hide "fades itself out"). */
@keyframes toast-in { from { opacity: 0; transform: translateX(115%); } to { opacity: 1; transform: translateX(0); } }
@keyframes toast-out { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(115%); } }
.toast-leaving { animation: toast-out 0.22s ease forwards; }

/* Countdown bar (#202): sits at the bottom, depletes right→left over autoHideMs
   (scaleX 1→0) so the remaining time is visible. Colour follows the variant. */
.toast-timer {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  transform-origin: left;
  background: var(--color-info);
  animation-name: toast-timer;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
.toast-info .toast-timer { background: var(--color-info); }
.toast-error .toast-timer { background: var(--color-error); }
.toast-success .toast-timer { background: var(--color-success); }
.toast-pending .toast-timer { background: var(--color-warning); }
@keyframes toast-timer { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* Fixed stack: top-right on desktop (slides from the right edge, #189),
   centered on mobile where a right-edge card would crowd the screen. */
.toast-stack {
  position: fixed;
  top: max(84px, 12vh);
  /* Flush to the right edge — no margin (Alex 2026-07-01). */
  right: 0;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(440px, calc(100vw - 12px));
  pointer-events: none; /* the container is a hit-through overlay… */
}
.toast-stack > * { pointer-events: auto; } /* …only the cards are interactive */

@media (max-width: 767px) {
  .toast-stack {
    /* Right-aligned (inherits right:0 from the base) — same as desktop, just
       narrower: max 75vw so it reads as a status overlay, not a full-width bar
       (Alex #205 width + right-alignment follow-up). */
    width: min(440px, 75vw);
  }
}

/* Glass fallback (no backdrop-filter support) → opaque surface. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .toast { background: var(--surface); }
}

/* ── Toast mit Handlungsknopf ─────────────────────────────────────
   Für Meldungen, die eine Entscheidung anbieten statt sie zu erzwingen
   (Profilwechsel: „gespeichert — jetzt neu starten?"). Flach und eckig
   wie der Rest der Oberfläche; der Knopf sitzt in einer eigenen Zeile,
   damit er auf dem Handy nicht in den Text rutscht. */
.toast-with-action {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.toast-action {
  align-self: flex-start;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: var(--text-primary);
  color: var(--surface);
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
}

.toast-action:hover { opacity: 0.85; }
.toast-action:active { transform: translateY(1px); }

/* Aufzählung in einer Meldung — z. B. „was beim Umbenennen NICHT mitgewandert
   ist". Kompakt, damit die Meldung nicht zur Seite wird. */
.toast-list {
  margin: 2px 0 0;
  padding-left: 18px;
  font-size: 12px;
  line-height: 1.5;
  opacity: 0.9;
}
:root {
  /* `--white` is the ALWAYS-white "on-accent / on-dark" ink (white icon on
     an orange button) — it does NOT flip in dark mode. `--surface` is the
     theme-aware page/card background (was conflated into --white before the
     dark-mode split, Alex 2026-06-22). `--chip-active-bg` is the dark pill
     behind active segmented tabs / primary buttons — stays dark in BOTH
     themes (white ink on it reads fine on light or dark surfaces). */
  --white: #FFFFFF;
  --black: #000000;
  --surface: #FFFFFF;
  --chip-active-bg: #333333;
  --text-primary: #333333;
  --text-body: #000000;
  --text-muted: #999999;
  /* ZWEI TOKEN, DIE ES NIE GAB — nachgetragen 27.08.
     `--text-secondary` wurde an 35 Stellen benutzt und war NIRGENDS definiert:
     nicht in dieser Datei, nicht zur Laufzeit (kein setProperty), nicht im
     gebauten Bundle. Dreifach nachgemessen.

     Das ist kein Schoenheitsfehler. Ein undefiniertes Token macht die ganze
     Deklaration zur Rechenzeit ungueltig; bei `color` erbt der Text dann die
     Farbe des Elternteils. Sekundaertext war also ueberall genauso dunkel wie
     Haupttext — die Abstufung, die er ausdruecken soll, existierte nicht.

     Der Wert liegt bewusst ZWISCHEN primary (#333) und muted (#999): Er ist
     leiser als die Hauptaussage, aber noch nicht Beiwerk. `--hover-bg` (2
     Verwendungen) fehlte ebenso. */
  --text-secondary: #666666;
  --hover-bg: #F2F2F2;
  --text-light: #999999;
  --border: #E5E5E5;
  --border-strong: #D0D0D0;
  --bg-light: #F8F8F8;
  --bg-inset: #FAFAFA;
  /* Brand accent = orange (was red #C41E3A). Replaces the AgentOS red
     everywhere --accent is used, incl. the selected left-stripe (Alex 2026-06-22). */
  --accent: #D97706;
  --accent-hover: #B45309;
  --accent-bg: rgba(217, 119, 6, 0.08);
  --accent-bg-strong: rgba(217, 119, 6, 0.15);
  --color-success: #16A34A;
  --color-success-bg: rgba(22, 163, 74, 0.10);
  --color-warning: #D97706;
  --color-warning-bg: rgba(217, 119, 6, 0.10);
  --color-error: #DC2626;
  --color-error-bg: rgba(220, 38, 38, 0.10);
  --color-info: #2563EB;
  --color-info-bg: rgba(37, 99, 235, 0.10);
  --font-body: 'Roboto', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --font-heading: 'Roboto Flex', 'Roboto', sans-serif;
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
  --sidebar-width: 280px;
}

/* ── Dark theme (Stage 1, Alex 2026-06-22) ──────────────────────────
   Toggled via [data-theme="dark"] on <html> (lib/accent.ts). Only the
   surface/text/border tokens flip — `--white`/`--chip-active-bg` stay so
   on-accent ink + dark pills keep contrast. `--accent`/`--color-success`
   are user-set at runtime and inherit unchanged. Semantic status hues
   (error/warning/info) keep their colour; their *-bg tints read fine as
   low-alpha overlays on the dark surface. */

[data-theme="dark"] {
  --surface: #1A1A1C;
  --bg-light: #232327;
  --bg-inset: #1E1E21;
  --black: #3A3A42;          /* "black" fills become a visible dark pill */
  --chip-active-bg: #3A3A42; /* dark pill, slightly above the surface */
  --text-primary: #E9E9EC;
  --text-body: #F4F4F6;
  --text-muted: #9A9AA3;
  --text-secondary: #B4B4BD;   /* zwischen primary #E9E9EC und muted #9A9AA3 */
  --hover-bg: #26262B;         /* knapp ueber der dunklen Flaeche */
  --text-light: #9A9AA3;
  --border: #34343B;
  --border-strong: #46464F;
}

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  overflow: hidden;
  height: 100%;
  max-width: 100vw;
}

body {
  overflow: hidden;
  height: 100%;
  max-width: 100vw;
}

body {
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: var(--chip-active-bg);
  color: var(--white);
}

::-webkit-scrollbar { width: 4px; height: 4px; }

::-webkit-scrollbar-track { background: transparent; }

::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.12); border-radius: 2px; }

::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.25); }

/* position: fixed anchors #root to the visual viewport so iOS Safari
 * can't auto-scroll the whole window upward to "reveal" a focused input
 * when the soft keyboard appears. Without this, overflow: hidden on
 * html/body is not enough — the layout viewport stays full-height while
 * the visual viewport collapses, and the system scrolls everything up.
 * Fixed positioning pins the app to the visible area; the visualViewport
 * resize listener in main.tsx keeps --vh in sync. */

#root {
  position: fixed;
  inset: 0;
  display: flex;
  height: calc(var(--vh, 1vh) * 100);
  overflow: hidden;
  width: 100%;
}

/* Suspense fallback while a lazy view-chunk downloads (code-splitting).
   Centered, quiet — chunks are small and cached, so this flashes at
   most once per view per deploy. */

.view-loading {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 13px;
}

/* Collab FAB (S2) — mobile floating "ask a question" button. Square-ish
 * (4px) to match the AgentOS angular style; clears the bottom safe-area. */

.collab-fab {
  position: fixed;
  right: 18px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 18px);
  z-index: 8000;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border: none;
  border-radius: 4px;
  background: var(--accent);
  color: var(--white);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.24);
  cursor: pointer;
}

.collab-fab:active { transform: scale(0.95); }
@font-face{font-display:block;font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2) format("woff2"),url(/assets/KaTeX_AMS-Regular-DMm9YOAa.woff) format("woff"),url(/assets/KaTeX_AMS-Regular-DRggAlZN.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2) format("woff2"),url(/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff) format("woff"),url(/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2) format("woff2"),url(/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff) format("woff"),url(/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2) format("woff2"),url(/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff) format("woff"),url(/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2) format("woff2"),url(/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff) format("woff"),url(/assets/KaTeX_Fraktur-Regular-CB_wures.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(/assets/KaTeX_Main-Bold-Cx986IdX.woff2) format("woff2"),url(/assets/KaTeX_Main-Bold-Jm3AIy58.woff) format("woff"),url(/assets/KaTeX_Main-Bold-waoOVXN0.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2) format("woff2"),url(/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff) format("woff"),url(/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2) format("woff2"),url(/assets/KaTeX_Main-Italic-BMLOBm91.woff) format("woff"),url(/assets/KaTeX_Main-Italic-3WenGoN9.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Main-Regular-B22Nviop.woff2) format("woff2"),url(/assets/KaTeX_Main-Regular-Dr94JaBh.woff) format("woff"),url(/assets/KaTeX_Main-Regular-ypZvNtVU.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2) format("woff2"),url(/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff) format("woff"),url(/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(/assets/KaTeX_Math-Italic-t53AETM-.woff2) format("woff2"),url(/assets/KaTeX_Math-Italic-DA0__PXp.woff) format("woff"),url(/assets/KaTeX_Math-Italic-flOr_0UB.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2) format("woff2"),url(/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff) format("woff"),url(/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2) format("woff2"),url(/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff) format("woff"),url(/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2) format("woff2"),url(/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff) format("woff"),url(/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Script-Regular-D3wIWfF6.woff2) format("woff2"),url(/assets/KaTeX_Script-Regular-D5yQViql.woff) format("woff"),url(/assets/KaTeX_Script-Regular-C5JkGWo-.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2) format("woff2"),url(/assets/KaTeX_Size1-Regular-C195tn64.woff) format("woff"),url(/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2) format("woff2"),url(/assets/KaTeX_Size2-Regular-oD1tc_U0.woff) format("woff"),url(/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(data:font/woff2;base64,d09GMgABAAAAAA4oAA4AAAAAHbQAAA3TAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmAAgRQIDgmcDBEICo1oijYBNgIkA14LMgAEIAWJAAeBHAyBHBvbGiMRdnO0IkRRkiYDgr9KsJ1NUAf2kILNxgUmgqIgq1P89vcbIcmsQbRps3vCcXdYOKSWEPEKgZgQkprQQsxIXUgq0DqpGKmIvrgkeVGtEQD9DzAO29fM9jYhxZEsL2FeURH2JN4MIcTdO049NCVdxQ/w9NrSYFEBKTDKpLKfNkCGDc1RwjZLQcm3vqJ2UW9Xfa3tgAHz6ivp6vgC2yD4/6352ndnN0X0TL7seypkjZlMsjmZnf0Mm5Q+JykRWQBKCVCVPbARPXWyQtb5VgLB6Biq7/Uixcj2WGqdI8tGSgkuRG+t910GKP2D7AQH0DB9FMDW/obJZ8giFI3Wg8Cvevz0M+5m0rTh7XDBlvo9Y4vm13EXmfttwI4mBo1EG15fxJhUiCLbiiyCf/ZA6MFAhg3pGIZGdGIVjtPn6UcMk9A/UUr9PhoNsCENw1APAq0gpH73e+M+0ueyHbabc3vkbcdtzcf/fiy+NxQEjf9ud/ELBHAXJ0nk4z+MXH2Ev/kWyV4k7SkvpPc9Qr38F6RPWnM9cN6DJ0AdD1BhtgABtmoRoFCvPsBAumNm6soZG2Gk5GyVTo2sJncSyp0jQTYoR6WDvTwaaEcHsxHfvuWhHA3a6bN7twRKtcGok6NsCi7jYRrM2jExsUFMxMQYuJbMhuWNOumEJy9hi29Dmg5zMp/A5+hhPG19j1vBrq8JTLr8ki5VLPmG/PynJHVul440bxg5xuymHUFPBshC+nA9I1FmwbRBTNHAcik3Oae0cxKoI3MOriM42UrPe51nsaGxJ+WfXubAsP84aabUlQSJ1IiE0iPETLUU4CATgfXSCSpuRFRmCGbO+wSpAnzaeaCYW1VNEysRtuXCEL1kUFUbbtMv3Tilt/1c11jt3Q5bbMa84cpWipp8Elw3MZhOHsOlwwVUQM3lAR35JiFQbaYCRnMF2lxAWoOg2gyoIV4PouX8HytNIfLhqpJtXB4vjiViUI8IJ7bkC4ikkQvKksnOTKICwnqWSZ9YS5f0WCxmpgjbIq7EJcM4aI2nmhLNY2JIUgOjXZFWBHb+x5oh6cwb0Tv1ackHdKi0I9OO2wE9aogIOn540CCCziyhN+IaejtgAONKznHlHyutPrHGwCx9S6B8kfS4Mfi4Eyv7OU730bT1SCBjt834cXsf43zVjPUqqJjgrjeGnBxSG4aYAKFuVbeCfkDIjAqMb6yLNIbCuvXhMH2/+k2vkNpkORhR59N1CkzoOENvneIosjYmuTxlhUzaGEJQ/iWqx4dmwpmKjrwTiTGTCVozNAYqk/zXOndWxuWSmJkQpJw3pK5KX6QrLt5LATMqpmPAQhkhK6PUjzHUn7E0gHE0kPE0iKkolgkUx9SZmVAdDgpffdyJKg3k7VmzYGCwVXGz/tXmkOIp+vcWs+EMuhhvN0h9uhfzWJziBQmCREGSIFmQIkgVpAnSBRmC//6hkLZwaVhwxlrJSOdqlFtOYxlau9F2QN5Y98xmIAsiM1HVp2VFX+DHHGg6Ecjh3vmqtidX3qHI2qycTk/iwxSt5UzTmEP92ZBnEWTk4Mx8Mpl78ZDokxg/KWb+Q0QkvdKVmq3TMW+RXEgrsziSAfNXFMhDc60N5N9jQzjfO0kBKpUZl0ZmwJ41j/B9Hz6wmRaJB84niNmQrzp9eSlQCDDzazGDdVi3P36VZQ+Jy4f9UBNp+3zTjqI4abaFAm+GShVaXlsGdF3FYzZcDI6cori4kMxUECl9IjJZpzkvitAoxKue+90pDMvcKRxLl53TmOKCmV/xRolNKSqqUxc6LStOETmFOiLZZptlZepcKiAzteG8PEdpnQpbOMNcMsR4RR2Bs0cKFEvSmIjAFcnarqwUL4lDhHmnVkwu1IwshbiCcgvOheZuYyOteufZZwlcTlLgnZ3o/WcYdzZHW/WGaqaVfmTZ1aWCceJjkbZqsfbkOtcFlUZM/jy+hXHDbaUobWqqXaeWobbLO99yG5N3U4wxco0rQGGcOLASFMXeJoham8M+/x6O2WywK2l4HGbq1CoUyC/IZikQhdq3SiuNrvAEj0AVu9x2x3lp/xWzahaxidezFVtdcb5uEnzyl0ZmYiuKI0exvCd4Xc9CV1KB0db00z92wDPde0kukbvZIWN6jUWFTmPIC/Y4UPCm8UfDTFZpZNon1qLFTkBhxzB+FjQRA2Q/YRJT8pQigslMaUpFyAG8TMlXigiqmAZX4xgijKjRlGpLE0GdplRfCaJo0JQaSxNBk6ZmMzcya0FmrcisDdn0Q3HI2sWSppYigmlM1XT/kLQZSNpMJG0WkjYbSZuDpM1F0uYhFc1HxU4m1QJjDK6iL0S5uSj5rgXc3RejEigtcRBtqYPQsiTskmO5vosV+q4VGIKbOkDg0jtRrq+Em1YloaTFar3EGr1EUC8R0kus1Uus00usL97ABr2BjXoDm/QGNhuWtMVBKOwg/i78lT7hBsAvDmwHc/ao3vmUbBmhjeYySZNWvGkfZAgISDSaDo1SVpzGDsAEkF8B+gEapViUoZgUWXcRIGFZNm6gWbAKk0bp0k1MHG9fLYtV4iS2SmLEQFARzRcnf9PUS0LVn05/J9MiRRBU3v2IrvW974v4N00L7ZMk0wXP1409CHo/an8zTRHD3eSJ6m8D4YMkZNl3M79sqeuAsr/m3f+8/yl7A50aiAEJgeBeMWzu7ui9UfUBCe2TIqZIoOd/3/udRBOQidQZUERzb2/VwZN1H/Sju82ew2H2Wfr6qvfVf3hqwDvAIpkQVFy4B9Pe9e4/XvPeceu7h3dvO56iJPf0+A6cqA2ip18ER+iFgggiuOkvj24bby0N9j2UHIkgqIt+sVgfodC4YghLSMjSZbH0VR/6dMDrYJeKHilKTemt6v6kvzvn3/RrdWtr0GoN/xL+Sex/cPYLUpepx9cz/D46UPU5KXgAQa+NDps1v6J3xP1i2HtaDB0M9aX2deA7SYff//+gUCovMmIK/qfsFcOk+4Y5ZN97XlG6zebqtMbKgeRFi51vnxTQYBUik2rS/Cn6PC8ADR8FGxsRPB82dzfND90gIcshOcYUkfjherBz53odpm6TP8txlwOZ71xmfHHOvq053qFF/MRlS3jP0ELudrf2OeN8DHvp6ZceLe8qKYvWz/7yp0u4dKPfli3CYq0O13Ih71mylJ80tOi10On8wi+F4+LWgDPeJ30msSQt9/vkmHq9/Lvo2b461mP801v3W4xTcs6CbvF9UDdrSt+A8OUbpSh55qAUFXWznBBfdeJ8a4d7ugT5tvxUza3h9m4H7ptTqiG4z0g5dc0X29OcGlhpGFMpQo9ytTS+NViZpNdvU4kWx+LKxNY10kQ1yqGXrhe4/1nvP7E+nd5A92TtaRplbHSqoIdOqtRWti+fkB5/n1+/VvCmz12pG1kpQWsfi1ftlBobm0bpngs16CHkbIwdLnParxtTV3QYRlfJ0KFskH7pdN/YDn+yRuSd7sNH3aO0DYPggk6uWuXrfOc+fa3VTxFVvKaNxHsiHmsXyCLIE5yuOeN3/Jdf8HBL/5M6shjyhxHx9BjB1O0+4NLOnjLLSxwO7ukN4jMbOIcD879KLSi6Pk61Oqm2377n8079PXEEQ7cy7OKEC9nbpet118fxweTafpt69x/Bt8UqGzNQt7aelpc44dn5cqhwf71+qKp/Zf/+a0zcizOUWpl/iBcSXip0pplkatCchoH5c5aUM8I7/dWxAej8WicPL1URFZ9BDJelUwEwTkGqUhgSlydVes95YdXvhh9Gfz/aeFWvgVb4tuLbcv4+wLdutVZv/cUonwBD/6eDlE0aSiKK/uoH3+J1wDE/jMVqY2ysGufN84oIXB0sPzy8ollX/LegY74DgJXJR57sn+VGza0x3DnuIgABFM15LmajjjsNlYj+JEZGbuRYcAMOWxFkPN2w6Wd46xo4gVWQR/X4lyI/R6K/YK0110GzudPRW7Y+UOBGTfNNzHeYT0fiH0taunBpq9HEW8OKSaBGj21L0MqenEmNRWBAWDWAk4CpNoEZJ2tTaPFgbQYj8HxtFilErs3BTRwT8uO1NXQaWfIotchmPkAF5mMBAliEmZiOGVgCG9LgRzpscMAOOwowlT3JhusdazXGSC/hxR3UlmWVwWHpOIKheqONvjyhSiTHIkVUco5bnji8m//zL7PKaT1Vl5I6UE609f+gkr6MZKVyKc7zJRmCahLsdlyA5fdQkRSan9LgnnLEyGSkaKJCJog0wAgvepWBt80+1yKln1bMVtCljfNWDueKLsWwaEbBSfSPTEmVRsUcYYMnEjcjeyCZzBXK9E9BYBXLKjOSpUDR+nEV3TFSUdQaz+ot98QxgXwx0GQ+EEUAKB2qZPkQQ0GqFD8UPFMqyaCHM24BZmSGic9EYMagKizOw9Hz50DMrDLrqqLkTAhplMictiCAx5S3BIUQdeJeLnBy2CNtMfz6cV4u8XKoFZQesbf9YZiIERiHjaNodDW6LgcirX/mPnJIkBGDUpTBhSa0EIr38D5hCIszhCM8URGBqImoWjpvpt1ebu/v3Gl3qJfMnNM+9V+kiRFyROTPHQWOcs1dNW94/ukKMPZBvDi55i5CttdeJz84DLngLqjcdwEZ87bFFR8CIG35OAkDVN6VRDZ7aq67NteYqZ2lpT8oYB2CytoBd6VuAx4WgiAsnuj3WohG+LugzXiQRDeM3XYXlULv4dp5VFYC) format("woff2"),url(/assets/KaTeX_Size3-Regular-CTq5MqoE.woff) format("woff"),url(/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2) format("woff2"),url(/assets/KaTeX_Size4-Regular-BF-4gkZK.woff) format("woff"),url(/assets/KaTeX_Size4-Regular-DWFBv043.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2) format("woff2"),url(/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff) format("woff"),url(/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf) format("truetype")}.katex{font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;position:relative;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.17.0"}.katex .katex-mathml{border:0;-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathboldfrak,.katex .textboldfrak{font-family:KaTeX_Fraktur;font-weight:700}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .mathsfit,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .smash{display:inline;line-height:0}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.2777777778em;margin-right:-.5555555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.1666666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.6666666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.4566666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.1466666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.7142857143em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.8571428571em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.1428571429em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.2857142857em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.4285714286em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.7142857143em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.0571428571em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.4685714286em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.9628571429em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.5542857143em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.7777777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.8888888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.1111111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.3044444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.7644444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.5833333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.7283333333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.0733333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.4861111111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.4402777778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.7277777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.2893518519em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.4050925926em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.462962963em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.5208333333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.2002314815em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.4398148148em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.2410800386em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.2892960463em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.337512054em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.3857280617em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.4339440694em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.4821600771em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.5785920926em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.6943105111em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.8331726133em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.1996142719em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.2009646302em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.2411575563em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.2813504823em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.3215434084em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.3617363344em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.4019292605em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.4823151125em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.578778135em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.6945337621em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.8336012862em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex svg{fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo}
