/* ============================================================
   Coding Console - Dark Theme, dichte Darstellung, dreispaltig.
   Keine externen Ressourcen (offline-faehig hinter nginx).
   ============================================================ */

:root {
  /* Flaechen */
  --bg:      #0d1117;
  --bg-1:    #131a23;
  --bg-2:    #182029;
  --bg-3:    #212b36;
  --bg-hi:   #2a3542;

  /* Schrift */
  --fg:      #dce4ee;
  --fg-dim:  #93a1b1;
  --fg-mute: #64717f;

  /* Linien */
  --line:      #222c38;
  --line-soft: #1a232d;

  /* Ruhige Akzentfarbe: gedaempftes Stahlblau */
  --accent:      #5b8fd6;
  --accent-soft: rgba(91, 143, 214, 0.30);
  --accent-bg:   rgba(91, 143, 214, 0.12);

  /* Statusfarben */
  --ok:    #4cae7f;
  --warn:  #d3a34a;
  --err:   #e0656f;
  --run:   #5b8fd6;
  --pause: #b184d0;

  /* Typografie */
  --mono: ui-monospace, "SFMono-Regular", "JetBrains Mono", "Fira Code", Menlo, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --radius: 6px;

  /* Hoehe des visuellen Viewports. Vorbelegung 100vh, damit jede
     Rueckfallebene traegt: eine Deklaration mit var() gilt beim Parsen IMMER
     als gueltig und verdraengt vorher notierte Werte aus der Kaskade - waere
     --vvh ungesetzt und die eingesetzte Ersatzangabe (100dvh) der Engine
     unbekannt, fiele die Eigenschaft auf 'unset' statt auf die vh-Zeile
     zurueck. app.js ersetzt den Wert auf schmalen Viewports durch die
     tatsaechliche Hoehe (visualViewport), sobald es laeuft. */
  --vvh: 100vh;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

/* Zwei desktopneutrale Basisregeln fuer die mobile Fassung. Die Bedienleiste
   ist per display:none KEIN Grid-Item und erzeugt oben keine dritte Zeile;
   erst die @media-Bloecke am Dateiende blenden sie ein. Bewusst kein
   hidden-Attribut im Markup - das liesse sich per @media nicht aufheben. */
.mobilebar { display: none; }
.lbl-short { display: none; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.45;
  overflow: hidden;
}

.mono { font-family: var(--mono); }
.muted { color: var(--fg-dim); }
.spacer { flex: 1 1 auto; }

::selection { background: var(--accent-soft); }

/* Scrollbars dezent */
* { scrollbar-width: thin; scrollbar-color: var(--bg-hi) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--bg-hi); border-radius: 6px; border: 2px solid var(--bg); }
*::-webkit-scrollbar-thumb:hover { background: #35424f; }

/* ---------------- Grundelemente ---------------- */

.btn {
  font: inherit;
  font-size: 12px;
  color: var(--fg);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 10px;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.btn:hover:not(:disabled) { background: var(--bg-hi); border-color: #37434f; }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #08121d; font-weight: 600; }
.btn.primary:hover:not(:disabled) { background: #6d9edf; border-color: #6d9edf; }
.btn.danger { background: transparent; border-color: #5a2a2f; color: var(--err); }
.btn.danger:hover:not(:disabled) { background: rgba(224, 101, 111, .14); }
.btn.warnbtn { background: transparent; border-color: #5a4a24; color: var(--warn); }
.btn.warnbtn:hover:not(:disabled) { background: rgba(211, 163, 74, .14); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--fg-dim); }
.btn.ghost:hover:not(:disabled) { background: var(--bg-2); color: var(--fg); }
.btn.small { padding: 3px 8px; font-size: 11.5px; }
.btn.tiny { padding: 2px 6px; font-size: 11px; line-height: 1.3; }
.btn.icon { padding: 2px 6px; font-size: 12px; background: transparent; border-color: transparent; color: var(--fg-mute); }
.btn.icon:hover:not(:disabled) { background: var(--bg-3); color: var(--fg); }

input[type="text"], input[type="password"], input[type="number"], select, textarea {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 8px;
  width: 100%;
  outline: none;
}
textarea { font-family: var(--mono); font-size: 12.5px; line-height: 1.5; resize: vertical; }
input:focus, select:focus, textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-bg); }
select { cursor: pointer; }
input::placeholder, textarea::placeholder { color: var(--fg-mute); }

.field { display: flex; flex-direction: column; gap: 3px; }
.field > span { font-size: 11px; color: var(--fg-dim); text-transform: uppercase; letter-spacing: .05em; }
.field.row { flex-direction: row; align-items: center; gap: 8px; }
.field.row > span { text-transform: none; letter-spacing: 0; white-space: nowrap; }
.field.row > input { width: 70px; }
.check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--fg-dim); cursor: pointer; }
.check input { width: auto; }

.hint { margin: 0; font-size: 11px; color: var(--fg-mute); line-height: 1.5; }
.hint em { font-style: normal; color: var(--fg-dim); }

/* Textlink-Optik fuer Buttons, die nur einen Dialog oeffnen. */
.linkbtn {
  font: inherit;
  font-size: inherit;
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.linkbtn:hover { color: #7ba9e4; }

.error {
  color: var(--err);
  font-size: 12px;
  background: rgba(224, 101, 111, .1);
  border: 1px solid #5a2a2f;
  border-radius: var(--radius);
  padding: 5px 8px;
  margin: 0;
}

.chip {
  font-size: 10.5px;
  padding: 1px 6px;
  border-radius: 10px;
  background: var(--bg-3);
  color: var(--fg-dim);
  white-space: nowrap;
}
.chip.step { background: var(--accent-bg); color: var(--accent); }
.chip.warn { background: rgba(211, 163, 74, .16); color: var(--warn); }
.chip.err  { background: rgba(224, 101, 111, .16); color: var(--err); }
.chip.live { background: rgba(91, 143, 214, .16); color: var(--accent); }

/* ---------------- Layout ---------------- */

.app {
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr) 380px;
  grid-template-rows: auto minmax(0, 1fr);
  /* 100vh ist auf Mobilgeraeten wegen der ein- und ausfahrenden Browserleisten
     zu gross; dvh trifft die tatsaechliche Hoehe. Auf dem Desktop sind beide
     Werte identisch, Engines ohne dvh verwerfen die zweite Zeile. */
  height: 100vh;
  height: 100dvh;
}

.topbar {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 12px;
  height: 40px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

.brand {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
  font-size: 12.5px;
  letter-spacing: .02em;
  color: var(--fg);
  white-space: nowrap;
}
.brand .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent);
}

.ctx {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
}
.ctx-name { font-weight: 600; white-space: nowrap; }
.ctx-dir {
  font-size: 11.5px;
  color: var(--fg-mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40%;
}
.badge {
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 4px;
  background: var(--bg-3);
  color: var(--fg-dim);
  border: 1px solid var(--line);
  white-space: nowrap;
}
.badge.warn { background: rgba(211, 163, 74, .13); color: var(--warn); border-color: #5a4a24; }
.badge.err  { background: rgba(224, 101, 111, .13); color: var(--err); border-color: #5a2a2f; }
/* Klickbares Badge (oeffnet die Einstellungen) - sieht aus wie ein Badge, verhaelt sich wie ein Button. */
button.badge { font: inherit; font-size: 11px; line-height: 1.45; cursor: pointer; }
button.badge:hover { background: rgba(211, 163, 74, .24); color: #e8c078; }
button.badge:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-bg); border-color: var(--accent); }

.topright { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.cost { font-family: var(--mono); font-size: 12px; color: var(--fg-dim); }
.conn {
  font-size: 11px;
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--fg-mute);
}
.conn::before {
  content: "";
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--fg-mute);
}
.conn[data-state="on"] { color: var(--ok); }
.conn[data-state="on"]::before { background: var(--ok); }
.conn[data-state="wait"] { color: var(--warn); }
.conn[data-state="wait"]::before { background: var(--warn); animation: pulse 1.1s infinite; }
.conn[data-state="off"] { color: var(--err); }
.conn[data-state="off"]::before { background: var(--err); }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .25; } }

/* ---------------- Sidebar ---------------- */

.sidebar {
  background: var(--bg-1);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px 6px;
  border-bottom: 1px solid var(--line-soft);
}
.panel-head h2 {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--fg-mute);
  display: flex;
  align-items: center;
  gap: 6px;
}

.list { list-style: none; margin: 0; padding: 4px 0; overflow-y: auto; }
#projectList { flex: 0 1 auto; max-height: 45%; }
#sessionList { flex: 1 1 auto; }

.item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  cursor: pointer;
  border-left: 2px solid transparent;
}
.item:hover { background: var(--bg-2); }
.item.active { background: var(--bg-2); border-left-color: var(--accent); }
.item .main { min-width: 0; flex: 1 1 auto; }
.item .title {
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.item.active .title { color: #fff; }
.item .sub {
  font-size: 10.5px;
  color: var(--fg-mute);
  font-family: var(--mono);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.item .tools { display: none; gap: 2px; }
.item:hover .tools, .item.active .tools { display: flex; }
.empty { padding: 10px; font-size: 11.5px; color: var(--fg-mute); }

.inline-form { padding: 6px 10px; border-bottom: 1px solid var(--line-soft); }
/* Nur fuer das kompakte Band gedacht (siehe dort) - auf dem Desktop bleibt
   die Zeile unveraendert, dort taugt Esc als Abbruchweg. */
#sessionCancel { display: none; }

/* ---------------- Mitte: Stream ---------------- */

.center {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  position: relative;
  background: var(--bg);
}

.stream {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 10px 14px 4px;
  min-height: 0;
  scroll-behavior: auto;
}

.turn {
  border-left: 2px solid var(--line);
  background: var(--bg-1);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 7px 12px 9px;
  margin: 0 0 10px;
}
.turn.user { border-left-color: var(--accent); background: var(--bg-2); }
.turn.assistant { border-left-color: #33404d; }
.turn.assistant.live { border-left-color: var(--accent); }
.turn.error { border-left-color: var(--err); }
.turn.aborted { opacity: .8; border-left-color: var(--warn); }

.turn-head {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 10.5px;
  color: var(--fg-mute);
  margin-bottom: 5px;
}
.turn-head .role {
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 600;
  color: var(--fg-dim);
}
.turn.user .turn-head .role { color: var(--accent); }
.turn-head .ts { font-family: var(--mono); }

.turn-body { font-size: 13px; }
.turn-body .txt { white-space: pre-wrap; overflow-wrap: anywhere; }
.turn-body .txt + .txt { margin-top: 0; }
.turn-body pre.code {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 8px 10px;
  margin: 6px 0;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  white-space: pre;
  position: relative;
}
.turn-body pre.code[data-lang]::before {
  content: attr(data-lang);
  position: absolute;
  top: 2px; right: 6px;
  font-size: 9.5px;
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.turn-body code {
  font-family: var(--mono);
  font-size: .92em;
  background: var(--bg-3);
  padding: 1px 4px;
  border-radius: 3px;
}

.tools-line, .tool {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--fg-mute);
  margin-top: 4px;
  display: flex;
  gap: 6px;
  align-items: baseline;
}
.tool .tname { color: var(--fg-dim); }
.tool .targs {
  color: var(--fg-mute);
  opacity: .75;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.live-tools { display: flex; flex-direction: column; gap: 1px; }
.live-tools:not(:empty) { margin-top: 4px; }

.turn-meta {
  margin-top: 5px;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--fg-mute);
  display: flex;
  gap: 10px;
}

.cursor-blink {
  display: inline-block;
  width: 7px;
  background: var(--accent);
  animation: blink 1s steps(2) infinite;
  color: transparent;
}
@keyframes blink { 0%,49% { opacity: 1; } 50%,100% { opacity: 0; } }

.stream-empty {
  color: var(--fg-mute);
  font-size: 12.5px;
  text-align: center;
  padding: 40px 20px;
  line-height: 1.8;
}

.scroll-down {
  position: absolute;
  right: 18px;
  bottom: 150px;
  z-index: 5;
  border-radius: 20px;
  box-shadow: 0 3px 10px rgba(0,0,0,.5);
}

/* ---------------- Log-Leiste ---------------- */

.logbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 10px;
  background: var(--bg-1);
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  min-height: 26px;
}
.logline {
  flex: 1 1 auto;
  font-family: var(--mono);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--fg-dim);
}
.logline[data-level="warn"]  { color: var(--warn); }
.logline[data-level="error"] { color: var(--err); }
.logline[data-level="info"]  { color: var(--fg-dim); }

.loghistory {
  max-height: 160px;
  overflow-y: auto;
  background: var(--bg);
  border-top: 1px solid var(--line-soft);
  padding: 4px 10px;
  font-family: var(--mono);
  font-size: 11px;
}
.logrow { display: flex; gap: 8px; padding: 1px 0; }
.logrow .lt { color: var(--fg-mute); flex: 0 0 auto; }
.logrow .lm { overflow-wrap: anywhere; }
.logrow[data-level="warn"] .lm  { color: var(--warn); }
.logrow[data-level="error"] .lm { color: var(--err); }
.logrow[data-level="info"] .lm  { color: var(--fg-dim); }

/* ---------------- Composer ---------------- */

.composer {
  border-top: 1px solid var(--line);
  background: var(--bg-1);
  padding: 8px 10px 9px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.composer textarea { background: var(--bg); min-height: 58px; max-height: 40vh; }
.composer-actions { display: flex; align-items: center; gap: 8px; }
.composer .hint { font-size: 11px; color: var(--fg-mute); flex: 1 1 auto; }
.composer.busy textarea { opacity: .55; }

/* ---------------- Queue-Panel ---------------- */

.queuepanel {
  background: var(--bg-1);
  border-left: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.qstatus {
  font-size: 10.5px;
  padding: 1px 7px;
  border-radius: 10px;
  background: var(--bg-3);
  color: var(--fg-dim);
  text-transform: none;
  letter-spacing: 0;
}
.qstatus[data-status="running"] { background: rgba(91,143,214,.18); color: var(--run); }
.qstatus[data-status="done"]    { background: rgba(76,174,127,.16); color: var(--ok); }
.qstatus[data-status="paused"]  { background: rgba(177,132,208,.16); color: var(--pause); }
.qstatus[data-status="failed"], .qstatus[data-status="error"] { background: rgba(224,101,111,.16); color: var(--err); }
.qstatus[data-status="stopped"] { background: rgba(211,163,74,.16); color: var(--warn); }

.queue-steps {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
}

.step {
  border: 1px solid var(--line);
  border-left: 3px solid var(--fg-mute);
  border-radius: var(--radius);
  background: var(--bg-2);
  padding: 6px 8px 8px;
}
.step[data-status="pending"] { border-left-color: #3a4753; }
.step[data-status="running"] { border-left-color: var(--run); box-shadow: 0 0 0 1px var(--accent-bg); }
.step[data-status="done"]    { border-left-color: var(--ok); }
.step[data-status="failed"]  { border-left-color: var(--err); }
.step[data-status="paused"]  { border-left-color: var(--pause); }

.step-head { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.step-num {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--fg-mute);
  background: var(--bg);
  border-radius: 3px;
  padding: 0 5px;
}
.step-state { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-mute); }
.step[data-status="running"] .step-state { color: var(--run); }
.step[data-status="done"] .step-state    { color: var(--ok); }
.step[data-status="failed"] .step-state  { color: var(--err); }
.step[data-status="paused"] .step-state  { color: var(--pause); }
.step-tools { margin-left: auto; display: flex; gap: 1px; }

.step textarea.step-prompt { min-height: 52px; background: var(--bg); }
.crit-toggle {
  background: none;
  border: none;
  color: var(--fg-mute);
  font: inherit;
  font-size: 11px;
  padding: 4px 0 2px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 4px;
}
.crit-toggle:hover { color: var(--fg-dim); }
.crit-toggle .caret { transition: transform .12s ease; display: inline-block; }
.crit-toggle[aria-expanded="true"] .caret { transform: rotate(90deg); }
.step textarea.step-criteria { min-height: 44px; background: var(--bg); border-color: #2c3a2f; }

.step-meta {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--fg-mute);
  margin-top: 5px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.verdicts { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.verdict {
  font-size: 11.5px;
  border-radius: 4px;
  padding: 4px 6px;
  border: 1px solid var(--line);
  background: var(--bg);
  overflow-wrap: anywhere;
}
.verdict[data-ok="true"]  { border-color: #2d5241; background: rgba(76,174,127,.08); }
.verdict[data-ok="false"] { border-color: #5a2a2f; background: rgba(224,101,111,.07); }
.verdict .vhead {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--fg-mute);
  margin-bottom: 2px;
  display: flex;
  gap: 6px;
}
.verdict[data-ok="true"] .vhead  { color: var(--ok); }
.verdict[data-ok="false"] .vhead { color: var(--err); }
.verdict .vreason { color: var(--fg-dim); }
.verdict .vfix {
  margin-top: 3px;
  color: var(--warn);
  font-family: var(--mono);
  font-size: 11px;
}

.queue-foot {
  border-top: 1px solid var(--line);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--bg-1);
}
.queue-foot .row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* Seit das Pruefmodus-Feld dazugekommen ist, passen Modus, Retries und Auto-Run
   auf schmalen Schirmen nicht mehr in eine Zeile - sie umbrechen jetzt, statt
   rechts aus dem Panel zu laufen. */
.queue-hint {
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--warn);
  background: rgba(211, 163, 74, .09);
  border: 1px solid #5a4a24;
  border-radius: var(--radius);
  padding: 5px 8px;
}
.queue-hint .linkbtn { color: var(--warn); }
.queue-hint .linkbtn:hover { color: #e8c078; }

/* Schaerfere Variante fuer den Modus "Pruefung aus": dort steht nichts mehr
   zwischen Claude und dem Arbeitsbaum, das darf nicht wie ein Nebensatz aussehen. */
.queue-hint.warn {
  color: var(--danger, #e0736a);
  background: rgba(224, 115, 106, .10);
  border-color: #5f3230;
}

/* Das Pruefmodus-Feld braucht mehr Platz als die schmalen Zahlenfelder
   (.field.row > input ist auf 70px begrenzt, das gilt fuer select nicht). */
.field.row > #pruefmodus { width: 150px; flex: 0 0 auto; }
.queue-buttons { display: flex; gap: 6px; flex-wrap: wrap; }
/* Der Protokoll-Download ist ein <a>, kein <button> - damit er sich in der
   Knopfreihe gleich verhaelt, bekommt er dieselbe Zeilenausrichtung, und
   ohne Session sieht er aus wie ein gesperrter Knopf. */
.queue-buttons a.btn { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
.btn.disabled, a.btn[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.queue-buttons .btn { flex: 1 1 auto; }
.dirty { font-size: 11px; color: var(--warn); }

/* ---------------- Login-Overlay ---------------- */

.overlay {
  position: fixed;
  inset: 0;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
.loginbox {
  width: 320px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 22px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 12px 40px rgba(0,0,0,.6);
}
.loginbox h1 {
  margin: 0;
  font-size: 16px;
  letter-spacing: .02em;
  display: flex;
  align-items: center;
  gap: 8px;
}
.loginbox p { margin: 0; font-size: 12px; }

/* ---------------- Dialog ---------------- */

dialog.dlg {
  width: 560px;
  max-width: calc(100vw - 32px);
  background: var(--bg-1);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0;
  box-shadow: 0 16px 50px rgba(0,0,0,.65);
}
dialog.dlg[open] { position: fixed; inset: 0; margin: auto; height: fit-content; z-index: 200; }
dialog.dlg::backdrop { background: rgba(0,0,0,.6); }
dialog.dlg form { padding: 16px 18px 14px; display: flex; flex-direction: column; gap: 10px; }
dialog.dlg h2 { margin: 0 0 2px; font-size: 14px; }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.dlg-actions { display: flex; justify-content: flex-end; gap: 8px; margin: 4px 0 0; padding: 0; }

/* --- Einstellungs-Dialog --- */

.keyrow { display: flex; align-items: center; gap: 6px; }
.keyrow input { flex: 1 1 auto; min-width: 0; font-size: 12px; }
.keyrow .btn { flex: 0 0 auto; }
.keyrow input::placeholder { font-family: var(--mono); font-size: 11.5px; }

.settings-state {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 11.5px;
  color: var(--fg-dim);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 8px;
}
.settings-state .sdot { width: 7px; height: 7px; border-radius: 50%; background: var(--fg-mute); flex: 0 0 auto; }
.settings-state[data-source="ui"]  .sdot { background: var(--ok); }
.settings-state[data-source="env"] .sdot { background: var(--accent); }
.settings-state[data-source="none"] .sdot { background: var(--warn); }
.settings-state[data-source="none"] .slabel { color: var(--warn); }
.settings-state code { font-size: 11px; color: var(--fg-mute); background: var(--bg); padding: 1px 5px; border-radius: 3px; }
.settings-state .muted { font-size: 11px; color: var(--fg-mute); margin-left: auto; }

details.adv { border-top: 1px solid var(--line-soft); padding-top: 8px; }
details.adv > summary {
  cursor: pointer;
  font-size: 11px;
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: .06em;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 5px;
}
details.adv > summary::-webkit-details-marker { display: none; }
details.adv > summary::before { content: "\25b8"; display: inline-block; transition: transform .12s ease; }
details.adv[open] > summary::before { transform: rotate(90deg); }
details.adv > summary:hover { color: var(--fg-dim); }
details.adv > *:not(summary) { margin-top: 8px; }

.testresult {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 11.5px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 8px;
  background: var(--bg);
  overflow-wrap: anywhere;
}
.testresult .slabel { font-weight: 600; flex: 0 0 auto; }
.testresult .muted { color: var(--fg-dim); }
.testresult[data-state="wait"] { color: var(--fg-mute); }
.testresult[data-state="ok"]   { border-color: #2d5241; background: rgba(76,174,127,.08); color: var(--ok); }
.testresult[data-state="err"]  { border-color: #5a2a2f; background: rgba(224,101,111,.07); color: var(--err); }
.testresult code { font-family: var(--mono); font-size: 11px; color: var(--fg-dim); }

.errlist { margin: 0; padding-left: 16px; }
.errlist li + li { margin-top: 2px; }

dialog.dlg.busy { cursor: progress; }

.fsbrowser {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  overflow: hidden;
}
.fs-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--bg-2);
}
.fs-head code {
  flex: 1 1 auto;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--fg-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fs-list {
  list-style: none;
  margin: 0;
  padding: 2px 0;
  height: 190px;
  overflow-y: auto;
}
.fs-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 10px;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 12px;
}
.fs-item:hover { background: var(--bg-2); }
.fs-item .ficon { color: var(--fg-mute); }
.fs-item .fname { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fs-item .frepo { font-size: 10px; color: var(--ok); background: rgba(76,174,127,.12); padding: 0 5px; border-radius: 8px; }
.fs-empty { padding: 8px 10px; color: var(--fg-mute); font-size: 11.5px; }

/* ---------------- Schmale Fenster ---------------- */

@media (max-width: 1280px) {
  .app { grid-template-columns: 210px minmax(0, 1fr) 330px; }
}

/* ============================================================
   Mobile Fassung - Telefon und Tablet.

   Alle Regeln stehen bewusst am DATEIENDE: Media-Queries erhoehen die
   Spezifitaet NICHT, es entscheidet allein die Quellreihenfolge. Nur so
   schlagen die 16px-Regeln weiter unten das textarea{font-size:12.5px}
   und .keyrow input{font-size:12px} aus dem oberen Teil der Datei.

   Alle Grenzen mit .98px, damit zwischen den Baendern kein 1px-Loch bleibt.
   Ab 1100px greift keine dieser Regeln - das Desktop-Bild ist unveraendert.
   ============================================================ */

/* ---------------- Tablet und schmale Fenster (bis 1099.98px) ----------------
   Zwei Spalten: die Sidebar bleibt stehen, Stream und Queue teilen sich
   Spalte 2 und werden ueber die Tableiste umgeschaltet. Bis hierher war das
   Queue-Panel unterhalb 1000px ueberhaupt nicht erreichbar. */

@media (max-width: 1099.98px) {
  .app {
    grid-template-columns: 190px minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    /* 100vh ist auf Mobilgeraeten wegen der Browserleisten falsch; dvh ist
       korrekt, vh bleibt als Rueckfallebene fuer aeltere Engines stehen. */
    height: 100vh;
    height: 100dvh;
  }
  .sidebar    { grid-column: 1; grid-row: 2; }
  .center     { grid-column: 2; grid-row: 2; }
  .queuepanel { grid-column: 2; grid-row: 2; display: none; }
  /* Lange Pfade und Object-Keys duerfen die Spalten nicht aufblasen. */
  .sidebar, .center, .queuepanel { min-width: 0; }

  .app[data-view="queue"] .center     { display: none; }
  .app[data-view="queue"] .queuepanel { display: flex; }

  /* --- Seitliche Safe-Area-Insets: hier, nicht erst im Telefon-Block ---
     Notch, Dynamic Island und abgerundete Ecken erzeugen seitliche Insets
     praktisch nur im Querformat - und dort ist JEDES Telefon breiter als
     700px (iPhone 14: 844x390, 15 Pro Max: 932x430). Es landet damit in
     diesem Band, nicht im Telefon-Block. Standen die Regeln nur dort,
     griffen sie genau da nicht, wo sie etwas bewirken. Links steht in
     diesem Band die Sidebar, rechts die Mittelspalte bzw. das Queue-Panel;
     der Telefon-Block ergaenzt die jeweils andere Seite. */
  .sidebar    { padding-left: env(safe-area-inset-left); }
  .queuepanel { padding-right: env(safe-area-inset-right); }
  .topbar {
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
  }
  .stream   { padding-right: max(14px, env(safe-area-inset-right)); }
  .logbar   { padding-right: max(10px, env(safe-area-inset-right)); }
  .composer { padding-right: max(10px, env(safe-area-inset-right)); }

  /* --- Bedienleiste am unteren Rand: Lauf-Anzeige plus Bereichswechsel --- */
  .mobilebar {
    display: block;
    grid-column: 1 / -1;
    grid-row: 3;
    background: var(--bg-1);
    border-top: 1px solid var(--line);
    /* Notch, abgerundete Ecken und Home-Indicator freihalten. */
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
    padding-bottom: env(safe-area-inset-bottom);
  }
  #tabProjects { display: none; }   /* die Sidebar steht in diesem Band dauerhaft */

  .tabbar { display: flex; }
  .tab {
    flex: 1 1 0;
    min-height: 56px;               /* Beruehrungsziel deutlich ueber 44px */
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    background: transparent;
    border: 0;
    color: var(--fg-mute);
    font: inherit;
    font-size: 11px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .tab:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent-bg); }
  .tab[aria-selected="true"] { color: var(--accent); background: var(--bg-2); }
  /* Aktivmarke oben, nicht unten: unten liegt die Home-Indicator-Zone. */
  .tab[aria-selected="true"]::before {
    content: "";
    position: absolute;
    top: 0; left: 12%; right: 12%;
    height: 2px;
    background: var(--accent);
  }
  .tab-ico { font-size: 17px; line-height: 1; }
  .tab-badge {
    position: absolute;
    top: 6px;
    left: calc(50% + 6px);
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    font-size: 10.5px;
    line-height: 18px;
    text-align: center;
    background: var(--bg-3);
    color: var(--fg-dim);
  }
  .tab-badge[data-state="running"] { background: rgba(91,143,214,.22); color: var(--run); }
  .tab-badge[data-state="paused"]  { background: rgba(177,132,208,.22); color: var(--pause); }
  .tab-badge[data-state="error"]   { background: rgba(224,101,111,.22); color: var(--err); }
  /* Punkt auf der Session-Lasche: zeigt einen laufenden Turn auch dann an,
     wenn man gerade in einem anderen Bereich steht. */
  .tab-dot {
    position: absolute;
    top: 8px;
    left: calc(50% + 8px);
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--run);
    animation: pulse 1.1s infinite;
  }

  /* Lauf-Leiste: sichtbar NUR, wenn etwas laeuft und der Composer mit seinem
     Stop-Button gerade nicht im Bild ist. Reine CSS-Logik aus .app.busy -
     es gibt damit keine zweite Sichtbarkeitslogik, die mit #btnStop
     auseinanderlaufen koennte. Klasse heisst 'busy' am .app-Element;
     .composer.busy und dialog.dlg.busy existieren unabhaengig davon. */
  .runbar { display: none; }
  .app.busy:not([data-view="stream"]) .runbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-bottom: 1px solid var(--line-soft);
    font-size: 12px;
  }
  .runbar-dot {
    flex: 0 0 auto;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--run);
    animation: pulse 1.1s infinite;
  }
  .runbar-text {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--fg-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Sicherheitsrelevante Badges nach vorn holen. .ctx hat overflow:hidden und
     die Badges stehen im DOM HINTER #ctxProject - ohne order schiebt ein
     langer Projektname sie aus dem sichtbaren Bereich; flex:0 0 auto allein
     reicht dafuer nicht. Betrifft ausdruecklich auch das Tablet-Band. */
  #badgeBypass    { order: -3; flex: 0 0 auto; }
  #badgeClaude    { order: -2; flex: 0 0 auto; }
  #badgeValidator { order: -1; flex: 0 0 auto; }
  /* Der Projekt-/Sessionname darf nicht das einzige schrumpfbare Element
     sein: die Badges stehen auf flex:0 0 auto, #ctxModel/#ctxPerm sind wegen
     white-space:nowrap faktisch unschrumpfbar - der Name fiel im Tablet-Band
     dadurch auf 0px, die Kopfzeile zeigte Badges ohne jeden Kontext.
     Untergrenze fuer den Namen, und die unkritischen Angaben weichen der
     Reihe nach hinter ihn. */
  .ctx-name { order: 0; flex: 1 1 auto; min-width: 8ch; overflow: hidden; text-overflow: ellipsis; }
  #ctxDir   { order: 1; flex: 0 1 auto; min-width: 0; }
  #ctxModel { order: 2; }
  #ctxPerm  { order: 3; }
  /* Die Wortmarke ist rein dekorativ und kostet gemessene 127px - genau die
     fehlen dem Namen. Sie weicht deshalb im ganzen kompakten Band, nicht
     erst auf dem Telefon. Ab 1100px bleibt sie unberuehrt. */
  .brand { display: none; }

  /* Abbruchweg fuer das Inline-Formular "Neue Session": Esc gibt es auf
     Bildschirmtastaturen nicht, und das Formular blendete sich sonst nur
     beim Absenden aus - der einzige Ausweg waere eine ungewollte Session
     gewesen. */
  .inline-form { display: flex; align-items: center; gap: 8px; }
  #sessionCancel { display: inline-block; flex: 0 0 auto; }

  /* 16px in JEDEM Eingabefeld - sonst zoomt iOS/iPadOS Safari beim
     Fokussieren die ganze Seite. Die beiden Nachzuegler sind noetig, um
     textarea{12.5px} und .keyrow input{12px} von weiter oben zu schlagen. */
  input[type="text"], input[type="password"], input[type="number"], select, textarea { font-size: 16px; }
  .keyrow input { font-size: 16px; }
  .composer textarea, .step textarea.step-prompt, .step textarea.step-criteria { font-size: 16px; }
  .field.row > input { width: 96px; }   /* #maxRetries braucht mit 16px mehr als die 70px der Basis */

  /* Dialoge: dialog.dlg[open] hat height:fit-content ohne Hoehenbegrenzung,
     die UA-Regel deckelt die Hoehe aber trotzdem - ohne scrollenden Inhalt
     waeren die Knoepfe auf kurzen Viewports (Querformat, kleines Tablet)
     unerreichbar. Deshalb Spalte mit eigenem Scrollbereich und klebender
     Knopfleiste. BEWUSST zentriert und kein Bottom-Sheet: ein an den
     Unterrand geklebter Dialog zerbricht, sobald die Tastatur aufgeht. */
  /* Der Deckel haengt am VISUELLEN Viewport, nicht an dvh: iOS Safari
     verkleinert bei offener Bildschirmtastatur nur diesen, dvh bleibt gross.
     Sonst rutscht die klebende Knopfleiste (.dlg-actions) unter die Tastatur
     und "Testen"/"Schliessen"/"Abbrechen" sind nicht mehr antippbar.
     --vvh ist auf :root vorbelegt, die beiden Zeilen darueber bleiben
     Rueckfallebene fuer Engines ohne visualViewport. */
  dialog.dlg[open] {
    max-height: calc(100vh - 16px);
    max-height: calc(100dvh - 16px);
    max-height: calc(var(--vvh) - 16px);
    display: flex;
    flex-direction: column;
  }
  dialog.dlg form {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .dlg-actions {
    position: sticky;
    bottom: 0;
    z-index: 1;
    background: var(--bg-1);
    padding: 8px 0 0;
    margin-top: 4px;
    border-top: 1px solid var(--line-soft);
  }
  .fs-list { height: auto; max-height: 32vh; max-height: 32dvh; min-height: 140px; }

  /* "Neueste"-Knopf: im Basislayout haengt er absolut an .center, sein
     bottom-Wert wird also von der UNTERKANTE DES COMPOSERS gemessen. Mobil
     waechst der Composer (16px-Schrift, 44px-Knoepfe, aufziehbare Textarea)
     und die Logleiste dazu - jeder feste Pixelwert landet frueher oder
     spaeter in der Prompt-Textarea und faengt dort mit z-index:5 die
     Beruehrungen ab (gemessen: elementFromPoint traf den Knopf statt das
     Feld). Deshalb steht er hier IM FLUSS zwischen .stream und .logbar und
     wird per negativem Rand ueber die Unterkante des Streams gezogen. Die
     feste Hoehe haelt die Rechnung -52 + 44 + 8 = 0 exakt, der Knopf
     verbraucht also keinen Platz und der Abstand stimmt in jedem Band und
     bei jeder Textarea-Hoehe. */
  .scroll-down {
    position: relative;
    inset: auto;
    align-self: flex-end;
    flex: 0 0 auto;
    height: 44px;
    margin: -52px 12px 8px 0;
  }

  /* Restliche Ueberlaufquellen. Bewusst kein globales overflow-x:hidden -
     das wuerde echte Layoutfehler nur kaschieren. */
  .turn-body code { overflow-wrap: anywhere; }
  .turn-body pre.code { max-width: 100%; }
  .tool { min-width: 0; flex-wrap: wrap; }
  .settings-state code, .testresult code { overflow-wrap: anywhere; }
  .step-head { flex-wrap: wrap; }
}

/* ---------------- Beruehrungsziele (Touch, bis 1099.98px) ----------------
   Bewusst an (pointer: coarse) UND an die Breite gekoppelt: ein Touch-Notebook
   oberhalb 1100px bleibt unveraendert, ein Tablet mit Maus ebenfalls. Der Block
   steht VOR dem Telefon-Block, damit dessen bewusste Ausnahmen (flache
   Log-Leiste, Safe-Area in der Kopfzeile) bei gleicher Spezifitaet gewinnen. */

@media (pointer: coarse) and (max-width: 1099.98px) {
  /* Pro Klasse einzeln aufgezaehlt, sonst rutschen .small/.tiny/.icon durch. */
  .btn, .btn.small, .btn.tiny { min-height: 44px; padding: 8px 12px; font-size: 13px; }
  .btn.icon {
    min-width: 44px; min-height: 44px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .item        { min-height: 44px; padding: 8px 10px; }
  .fs-item     { min-height: 44px; padding: 8px 10px; }
  .crit-toggle { min-height: 44px; }
  .check       { min-height: 44px; }
  /* flex:0 0 auto ist noetig: .check ist ein Flex-Container, ohne die Sperre
     quetscht ein langer Beschriftungstext das Kaestchen schmaler als hoch
     (auf 375px gemessen 14.6x20 statt 20x20). */
  .check input { width: 20px; height: 20px; flex: 0 0 auto; }
  .linkbtn     { display: inline-block; padding: 10px 0; min-height: 44px; }
  /* Der Aufklapper "Erweitert" im Einstellungs-Dialog war nur 16px hoch. */
  details.adv > summary { min-height: 44px; }
  #btnSettings, #btnLogout { min-width: 44px; min-height: 44px; }

  /* Das Validator-Badge ist ein echter Button (oeffnet die Einstellungen) und
     braucht daher 44px. Eine bloss vergroesserte Trefferflaeche per
     ::after-Pseudo-Element funktioniert hier NICHT: .topbar und .ctx haben
     beide overflow:hidden und schneiden alles ab, was ueber die 32px hohe
     Badge-Box hinausragt - nachgemessen mit elementFromPoint. Also waechst
     das Badge wirklich, und die Kopfzeile bekommt unten die noetige Hoehe.
     Die beiden reinen Anzeige-Badges wachsen mit: sie sind zwar keine
     Beruehrungsziele, aber ein 32px-Badge neben einem 44px-Badge sieht in
     derselben Zeile nach Fehler aus. */
  #badgeValidator, #badgeBypass, #badgeClaude {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    /* inline-flex schluckt den Leerraum zwischen Warnzeichen und Text
       ("&#9888;<span>bypass</span>" wurde zu "!bypass") - gap ersetzt ihn. */
    gap: 4px;
  }
  /* Eingabefelder sind ebenfalls Beruehrungsziele; textarea bleibt aussen vor,
     die haben eigene min-height-Werte. */
  input[type="text"], input[type="password"], input[type="number"], select { min-height: 44px; }
  /* Die Kopfzeile ist mit 40px zu flach fuer 44px-Ziele und schneidet sie
     wegen overflow:hidden ab. 56px statt 48px, damit das 44px hohe
     Validator-Badge nicht die ganze Leiste ausfuellt. */
  .topbar { height: auto; min-height: 56px; }
}

/* ---------------- Telefon (bis 699.98px) ----------------
   Eine Spalte, umgeschaltet statt nebeneinander. Der Stream ist Standard. */

@media (max-width: 699.98px) {
  .app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    height: 100vh;      /* Rueckfallebene fuer alte Engines */
    height: 100dvh;     /* moderne Engines */
    height: var(--vvh); /* exakte Hoehe des visuellen Viewports, siehe app.js.
                           Ohne Ersatzangabe im var(): --vvh ist auf :root mit
                           100vh vorbelegt, die Kette bleibt damit intakt. */
  }
  /* iOS Safari schrumpft bei offener Tastatur NUR den visuellen Viewport.
     Der fixierte Body zusammen mit --vvh haelt Kopfzeile, Composer und
     Bedienleiste trotzdem im sichtbaren Bereich. */
  body { position: fixed; inset: 0; overscroll-behavior: none; }

  .sidebar, .center, .queuepanel { grid-column: 1; grid-row: 2; display: none; }
  .app[data-view="projects"] .sidebar    { display: flex; }
  .app[data-view="stream"]   .center     { display: flex; }
  .app[data-view="queue"]    .queuepanel { display: flex; }
  /* Hier ist jeder Bereich bildschirmbreit, also braucht jeder BEIDE Seiten -
     im Tablet-Band oben deckt die jeweils andere Spalte die zweite Seite ab. */
  .sidebar {
    border-right: none;
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }
  .queuepanel {
    border-left: none;
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }
  .stream { padding-left: max(14px, env(safe-area-inset-left)); }
  #tabProjects { display: flex; }   /* hebt das Ausblenden aus dem Tablet-Band wieder auf */
  #projectList { max-height: 40%; }

  /* --- Kopfzeile verdichten --- */
  .topbar {
    height: auto;
    min-height: calc(56px + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
    padding-left: max(10px, env(safe-area-inset-left));
    padding-right: max(10px, env(safe-area-inset-right));
    gap: 8px;
  }
  /* .brand weicht bereits im kompakten Band. */
  #ctxDir, #ctxModel, #ctxPerm { display: none; }
  .ctx { gap: 6px; }
  /* Kurzform der Beschriftungen. Die Langform bleibt als aria-label erhalten
     (siehe index.html), display:none nimmt sie sonst aus dem A11y-Baum. */
  .lbl-long  { display: none; }
  .lbl-short { display: inline; }
  .topright { gap: 6px; }
  .cost { font-size: 11px; }
  /* Text weg, der 7px-Punkt aus .conn::before traegt Farbe und Puls. Den
     Klartext liefert setConn() als title und aria-label nach. */
  .conn { font-size: 0; gap: 0; }
  #btnSettings, #btnLogout { padding: 0 8px; font-size: 15px; }

  /* Beruehrungsziele stehen im (pointer: coarse)-Block weiter oben.
     Die Log-Leiste bekommt volle 44px: ein Pseudo-Element wie beim
     Validator-Badge waere hier gefaehrlich, weil es nach unten in die
     Prompt-Textarea ragen und deren Beruehrungen abfangen wuerde
     (positionierte Elemente malen ueber statischen Inhalt). Die 12px, die
     der Stream dadurch auf einem 667px-Schirm verliert, sind es wert.
     #logClear entfaellt mobil und schafft den noetigen Platz. */
  .logbar {
    min-height: 44px;
    padding: 2px max(8px, env(safe-area-inset-right)) 2px max(8px, env(safe-area-inset-left));
  }
  #logToggle { min-width: 44px; min-height: 44px; }
  #logClear  { display: none; }
  .loghistory { max-height: 30vh; max-height: 30dvh; }

  /* --- Composer: muss immer erreichbar bleiben, auch bei offener Tastatur --- */
  .composer {
    /* Reihenfolge oben/rechts/unten/links - rechts gehoert inset-right. */
    padding: 8px max(10px, env(safe-area-inset-right)) 9px max(10px, env(safe-area-inset-left));
  }
  .composer textarea { min-height: 44px; max-height: 26vh; max-height: 26dvh; }
  .composer-actions { gap: 8px; }
  #composerHint { font-size: 11px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #btnSend { flex: 0 0 auto; min-width: 92px; }
  #btnStop { flex: 0 0 auto; }
  /* Bei offener Bildschirmtastatur weicht die Tableiste, der Composer nimmt
     den Platz. Die Lauf-Leiste bleibt stehen - sie ist nur eine Zeile hoch. */
  body.kb-open .tabbar { display: none; }
  body.kb-open .composer { padding-bottom: calc(9px + env(safe-area-inset-bottom)); }

  /* --- Dialoge auf 375px: volle Breite, Rest kommt aus dem kompakten Band --- */
  dialog.dlg { width: 100%; max-width: calc(100vw - 16px); }
  dialog.dlg[open] { inset: 0; margin: 8px auto; height: auto; }
  dialog.dlg form { padding: 14px 14px calc(12px + env(safe-area-inset-bottom)); }
  .dlg-actions { flex-wrap: wrap; }
  .dlg-actions .btn { flex: 1 1 auto; }
  .row2 { grid-template-columns: 1fr; }
  .fs-head { flex-wrap: wrap; }
  #fsPath { flex: 1 1 100%; order: -1; min-width: 0; }
  .keyrow { flex-wrap: wrap; }
  .keyrow input { flex: 1 1 100%; }

  /* --- Login-Overlay --- */
  .overlay  { align-items: flex-start; padding: max(10vh, env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom)); }
  .loginbox { width: 100%; max-width: calc(100vw - 32px); }

  /* --- Queue-Fuss: Platz fuer den Home-Indicator, wenn die Tableiste weicht --- */
  .queue-foot { padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
}

/* Gestaffelter Rueckzug in der Kopfzeile. Unterhalb 900px reicht der Platz
   nicht mehr fuer Pfad, Modell UND Permission-Badge: gemessen bleiben dem
   Projekt-/Sessionnamen dann nur seine 8ch-Untergrenze, und #ctxPerm wird von
   .ctx{overflow:hidden} mitten im Wort abgeschnitten. Die unkritischen
   Angaben weichen deshalb hier schon - Pfad und Modell stehen im
   Projekt-Dialog, und der Fall permissionMode=bypassPermissions ist ueber
   #badgeBypass abgedeckt. Die sicherheitsrelevanten Badges (bypass,
   Validator, fehlende CLI) bleiben in JEDEM Band stehen.
   min-width:700px klammert den Block gegen den Telefon-Block darueber. */
@media (min-width: 700px) and (max-width: 899.98px) {
  #ctxDir, #ctxModel, #ctxPerm { display: none; }
}

/* Sehr schmal: letzte Verdichtung. */
@media (max-width: 380px) {
  .tab-label { font-size: 10px; }
  #ctxCost { display: none; }
}

/* Flaches Telefon im Querformat: es matcht sonst faelschlich die Tablet-Stufe
   und hat trotzdem keine Hoehe mehr. */
@media (max-width: 1099.98px) and (max-height: 500px) {
  /* 48px statt 40px: darunter wuerde .topbar{overflow:hidden} das 44px hohe
     Validator-Badge wieder anschneiden. */
  .topbar { min-height: calc(48px + env(safe-area-inset-top)); }
  .logbar, .loghistory { display: none; }
  .composer textarea { min-height: 40px; max-height: 20vh; max-height: 20dvh; }
  .tab { min-height: 44px; }
  .tab-label { font-size: 10px; }
}

/* Kein Hover auf Touch: die Werkzeug-Buttons der Listenzeilen sind sonst nur
   bei :hover/.active eingeblendet und damit fuer jedes nicht aktive Projekt
   unerreichbar. Die Breitengrenze schuetzt Touch-Notebooks oberhalb 1100px
   vor jeder sichtbaren Aenderung. */
@media (hover: none) and (max-width: 1099.98px) {
  .item .tools { display: flex; }
}

/* Folgekosten der Regel darueber, nur im Tablet-Band: dort ist die Sidebar
   190px breit und die dauerhaft sichtbaren Werkzeuge belegen mit ihren
   44px-Zielen davon 90px - fuer Name UND Pfad blieben gemessene 71px. Die
   Spalte waechst deshalb auf 250px. Bewusst mit min-width:700px geklammert:
   ohne die Klammer wuerde dieser Block, der NACH dem Telefon-Block steht,
   dessen einspaltiges Raster wieder ueberschreiben. Ab 1100px greift nichts
   davon, das Desktop-Bild bleibt unberuehrt. */
@media (hover: none) and (min-width: 700px) and (max-width: 1099.98px) {
  .app { grid-template-columns: 250px minmax(0, 1fr); }
}

/* Bewegungsarme Darstellung respektieren. Fuer den Ansichtswechsel selbst
   werden bewusst gar keine Uebergaenge eingefuehrt - harter display-Wechsel. */
@media (prefers-reduced-motion: reduce) {
  .tab-dot, .runbar-dot, .conn[data-state="wait"]::before { animation: none; }
  .cursor-blink { animation: none; opacity: 1; }
  .btn, .crit-toggle .caret, details.adv > summary::before { transition: none; }
  .btn:active:not(:disabled) { transform: none; }
}

/* ---- Dokumente-Dialog ---------------------------------------------------- */

.dlg-sub {
  margin: -6px 0 4px;
  font-size: 11px;
  color: var(--fg-dim);
  font-family: var(--mono, monospace);
  word-break: break-all;
}

.upload-log {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  max-height: 140px;
  overflow-y: auto;
  font-size: 11.5px;
  font-family: var(--mono, monospace);
}
.upload-log li {
  padding: 3px 6px;
  border-radius: var(--radius);
  word-break: break-all;
}
.upload-log .up-ok { color: var(--ok, #6fbf73); background: rgba(111, 191, 115, .08); }
.upload-log .up-fehler { color: #e0736a; background: rgba(224, 115, 106, .08); }

/* Der Dateiwaehler ist auf Telefonen sonst kaum zu treffen. */
@media (pointer: coarse) and (max-width: 1099.98px) {
  #uFiles { min-height: 44px; padding: 9px 8px; }
}

/* ---- Merge-Anerbieten nach dem Lauf -------------------------------------- */

.merge-box {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.merge-head { margin: 0; font-size: 12px; }
.merge-info { margin: 0; font-size: 11px; color: var(--fg-dim); line-height: 1.5; }
.merge-info.gut { color: var(--ok, #6fbf73); }
.merge-info.schlecht { color: #e0736a; }
.merge-files {
  list-style: none; margin: 0; padding: 0;
  max-height: 110px; overflow-y: auto;
  font-family: var(--mono, monospace); font-size: 11px;
}
.merge-files li { padding: 1px 0; color: var(--fg-dim); word-break: break-all; }
.merge-files .mf-status { display: inline-block; width: 1.4em; color: var(--accent); }
