/* ── JSONL transcript panel (phase 1) ───────────────────────────────────
 * Renders above the xterm when localStorage['picker-transcript-mode']==='jsonl'.
 * Phase 1 = additive panel; phase 2 will restructure the .term-pane layout.
 * Theme-aware via --bg / --surface / --text / --text-dim / --border / --cyan,
 * etc. (declared at the top of style.css). The default 'tui'-mode user
 * never has the .jsonl-mode class so these rules are inert.
 */

/* ── Swap mode (Phase 2.x rework) ─────────────────────────────────────
 * Both surfaces are absolutely positioned full-pane; only one is visible
 * at a time controlled by .read-mode on the pane. xterm = live default;
 * .read-mode swaps to the rendered transcript overlay. */
.term-pane.jsonl-mode {
  /* inherits position:absolute; inset:0 from base .term-pane in style.css */
}
.term-pane.jsonl-mode > .xterm {
  position: absolute; inset: 0;
  z-index: 1;
}
.term-pane.jsonl-mode.read-mode > .xterm {
  visibility: hidden;        /* keep layout/measurement; just hide pixels */
}

.tab-transcript {
  position: absolute; inset: 0;
  display: none;             /* hidden by default; .read-mode reveals it */
  flex-direction: column;
  background: var(--bg);
  font: 14px/1.55 var(--font-ui);
  color: var(--text);
  z-index: 5;
  /* iOS-safe overscroll containment so swiping past the top/bottom
   * doesn't bounce the whole page. */
  overscroll-behavior: contain;
}
.term-pane.jsonl-mode.read-mode > .tab-transcript {
  display: flex;
}

.tab-transcript .transcript-header {
  flex: 0 0 auto;
  padding: 6px 12px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 12px;
}

.tab-transcript .transcript-title {
  font-weight: 600;
  letter-spacing: 0.02em;
}

.tab-transcript .transcript-totals {
  margin-left: auto;
  font: 11px/1 var(--font-mono);
  color: var(--text-dim);
}

.tab-transcript .transcript-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px 12px 16px;
}

/* ── Turn cards ───────────────────────────────────────────────────────── */
/* Base — assistant style (no background, subtle left rule).
 * Default-styled turns read as the conversation body. */
.tab-transcript .turn {
  margin: 10px 0;
  padding: 6px 12px 6px 14px;
  border-radius: 0;
  background: transparent;
  border-left: 2px solid rgba(63, 185, 80, 0.35);    /* assistant: faint green */
}
.tab-transcript .turn.assistant {
  /* inherits */
}

/* User turns — visually distinct from assistant: user-bubble-stronger.
 * Indented from the right, brighter background tint, thicker accent rule,
 * bolder label. The goal: scanning the transcript the eye instantly
 * separates "who-said-what". */
.tab-transcript .turn.user {
  margin-left: 0;
  margin-right: 24px;
  padding: 10px 14px 10px 16px;
  border-left: 4px solid var(--cyan);
  background: rgba(124, 192, 240, 0.10);      /* faint blue tint */
  border-radius: 4px 8px 8px 4px;
  box-shadow: inset 0 0 0 1px rgba(124, 192, 240, 0.18);
}
.tab-transcript .turn.user .turn-who {
  color: var(--cyan);
  text-transform: uppercase;
  font-weight: 800;
  letter-spacing: 0.06em;
}
.tab-transcript .turn.user .turn-body {
  font-weight: 500;
}

/* Synthetic / meta turns — kept faint and out of the way. */
.tab-transcript .turn.synthetic {
  border-left-color: var(--text-dim);
  background: transparent;
  opacity: 0.55;
}
.tab-transcript .turn.synthetic.user {
  background: transparent;
  box-shadow: none;
  margin-right: 0;
}

.tab-transcript .turn-header {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 6px;
}

.tab-transcript .turn-who { font-weight: 700; }

.tab-transcript .token-chip {
  font: 11px/1 var(--font-mono);
  color: var(--text-dim);
  text-transform: none;
  letter-spacing: 0;
  background: var(--bg);
  padding: 2px 6px;
  border-radius: 3px;
}

.tab-transcript .turn-meta {
  font-size: 10px;
  color: var(--text-dim);
  background: var(--bg);
  padding: 1px 5px;
  border-radius: 3px;
}

.tab-transcript .turn-body {
  color: var(--text);
  word-wrap: break-word;
  overflow-wrap: anywhere;
}

/* ── Inline markdown styling ─────────────────────────────────────────── */
.tab-transcript .turn-body > .block { margin: 6px 0; }
.tab-transcript .turn-body p { margin: 6px 0; }
.tab-transcript .turn-body h1,
.tab-transcript .turn-body h2,
.tab-transcript .turn-body h3,
.tab-transcript .turn-body h4 { margin: 12px 0 4px; }
.tab-transcript .turn-body ul,
.tab-transcript .turn-body ol { margin: 6px 0; padding-left: 22px; }
.tab-transcript .turn-body li { margin: 2px 0; }
.tab-transcript .turn-body blockquote {
  margin: 6px 0;
  padding-left: 10px;
  border-left: 3px solid var(--border);
  color: var(--text-dim);
}
.tab-transcript .turn-body code {
  font: 12.5px/1.4 var(--font-mono);
  background: var(--bg);
  padding: 0.5px 4px;
  border-radius: 3px;
}
.tab-transcript .turn-body pre {
  font: 12.5px/1.4 var(--font-mono);
  background: var(--bg);
  padding: 8px 10px;
  border-radius: 4px;
  overflow-x: auto;
  margin: 6px 0;
}
.tab-transcript .turn-body pre code {
  background: none;
  padding: 0;
  border-radius: 0;
}
.tab-transcript .turn-body a {
  color: var(--cyan);
  text-decoration: underline;
}
.tab-transcript .turn-body .unsafe-link {
  color: var(--red);
  text-decoration: line-through;
  cursor: not-allowed;
}
.tab-transcript .turn-body .md-image {
  font: 12px/1.4 var(--font-mono);
  color: var(--text-dim);
  background: var(--bg);
  padding: 2px 5px;
  border-radius: 3px;
}

/* ── Tool-use cards (collapsed by default) ───────────────────────────── */
.tab-transcript .toolcard {
  margin: 6px 0;
  border-radius: 4px;
  background: var(--bg);
  border-left: 2px solid var(--blue);
}

.tab-transcript .toolcard.status-error { border-left-color: var(--red); }
.tab-transcript .toolcard.status-pending { border-left-color: var(--yellow); }

.tab-transcript .toolcard > summary {
  list-style: none;
  cursor: pointer;
  padding: 5px 10px;
  font: 12px/1.3 var(--font-mono);
  color: var(--text);
  user-select: none;
  display: flex;
  align-items: center;
  gap: 4px;
}
.tab-transcript .toolcard > summary::-webkit-details-marker { display: none; }
.tab-transcript .toolcard > summary::marker { content: ''; }

.tab-transcript .toolcard .tool-dot { color: var(--blue); }
.tab-transcript .toolcard.status-error .tool-dot { color: var(--red); }
.tab-transcript .toolcard.status-pending .tool-dot { color: var(--yellow); }
.tab-transcript .toolcard .tool-name { font-weight: 700; }
.tab-transcript .toolcard .tool-summary {
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1 1 auto;
  min-width: 0;
}
.tab-transcript .toolcard .tool-glyph { color: var(--text-dim); }
.tab-transcript .toolcard.status-ok .tool-glyph { color: var(--green); }
.tab-transcript .toolcard.status-error .tool-glyph { color: var(--red); }

.tab-transcript .tool-body {
  padding: 4px 10px 10px;
  font: 12px/1.4 var(--font-mono);
}
.tab-transcript .tool-label {
  color: var(--text-dim);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 6px 0 3px;
}
.tab-transcript .tool-input,
.tab-transcript .tool-result {
  margin: 0;
  padding: 6px 8px;
  background: var(--surface);
  border-radius: 3px;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 280px;
  overflow-y: auto;
}
.tab-transcript .tool-result.is-error { color: var(--red); }
.tab-transcript .tool-pending { color: var(--text-dim); font-style: italic; }

/* ── Thinking blocks ──────────────────────────────────────────────────── */
.tab-transcript .thinking {
  margin: 6px 0;
  border-radius: 4px;
  background: var(--bg);
  border-left: 2px solid var(--purple);
}
.tab-transcript .thinking > summary {
  list-style: none;
  cursor: pointer;
  padding: 4px 10px;
  font-size: 12px;
  color: var(--text-dim);
  user-select: none;
}
.tab-transcript .thinking > summary::-webkit-details-marker { display: none; }
.tab-transcript .thinking > summary::marker { content: ''; }
.tab-transcript .thinking-body {
  padding: 4px 10px 10px;
  color: var(--text-dim);
  font-size: 13px;
}

/* ── "Show full…" buttons ────────────────────────────────────────────── */
.tab-transcript .transcript-show-full {
  display: inline-block;
  margin: 4px 0 0;
  padding: 3px 9px;
  font: 11px/1 var(--font-ui);
  background: var(--surface);
  color: var(--cyan);
  border: 1px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
}
.tab-transcript .transcript-show-full:hover { color: var(--text); }
.tab-transcript .transcript-show-full:disabled { color: var(--text-dim); cursor: wait; }

/* ── Mobile: keep the panel a smaller fraction so the xterm still has
 *    room. Phase 2 will restructure this entirely (transcript = primary
 *    scroll region, xterm = small live dock at bottom). */
@media (max-width: 768px) {
  .term-pane.jsonl-mode { --dock-height: 240px; }
  .tab-transcript .turn { padding: 6px 9px; }
  .tab-transcript .transcript-header { padding: 4px 9px; }
}


/* ── Phase 3 — specialized tool-card content styles ──────────────────── */

.tab-transcript .tool-input-rendered {
  margin: 4px 0 6px;
  font: 12px/1.45 var(--font-mono);
}

.tab-transcript .tool-file-path {
  color: var(--cyan);
  font-weight: 600;
  margin-bottom: 4px;
  word-break: break-all;
}

.tab-transcript .tool-meta {
  color: var(--text-dim);
  font-size: 11px;
  margin: 2px 0;
}

/* Bash */
.tab-transcript .tool-bash-desc {
  color: var(--text-dim);
  font-style: italic;
  margin-bottom: 3px;
}
.tab-transcript .tool-bash-cmd {
  background: var(--surface);
  border-left: 3px solid var(--green);
  padding: 5px 8px;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  border-radius: 2px;
}

/* Edit / MultiEdit / Write */
.tab-transcript .tool-edit-label {
  color: var(--text-dim);
  font-size: 11px;
  margin-top: 6px;
  margin-bottom: 2px;
}
.tab-transcript .tool-diff {
  margin: 3px 0;
  border-radius: 2px;
  overflow: hidden;
}
.tab-transcript .diff-old {
  background: rgba(244, 71, 71, 0.10);
  border-left: 3px solid var(--red, #ff6b6b);
  color: var(--text);
  padding: 4px 8px;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
}
.tab-transcript .diff-new {
  background: rgba(63, 185, 80, 0.10);
  border-left: 3px solid var(--green, #3fb950);
  color: var(--text);
  padding: 4px 8px;
  margin: 1px 0 0;
  white-space: pre-wrap;
  word-break: break-word;
}
.tab-transcript .tool-write-content {
  background: var(--surface);
  border-left: 3px solid var(--cyan);
  padding: 5px 8px;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 320px;
  overflow-y: auto;
}

/* Pattern (Grep/Glob) */
.tab-transcript .tool-pattern-line { display: block; }
.tab-transcript .tool-pattern-name {
  color: var(--text-dim);
  font-size: 11px;
}
.tab-transcript .tool-pattern code {
  background: var(--surface);
  padding: 1px 5px;
  border-radius: 2px;
  color: var(--yellow);
}

/* URL / Text / Task */
.tab-transcript .tool-url-link {
  color: var(--cyan);
  text-decoration: underline;
  word-break: break-all;
}
.tab-transcript .tool-text-label {
  color: var(--text-dim);
  font-size: 11px;
}
.tab-transcript .tool-task-desc {
  color: var(--text);
  font-weight: 600;
  margin: 2px 0;
}
.tab-transcript .tool-task-prompt {
  background: var(--surface);
  padding: 5px 8px;
  margin: 3px 0;
  white-space: pre-wrap;
  word-break: break-word;
  border-radius: 2px;
  max-height: 240px;
  overflow-y: auto;
}

/* jsonl-mode rail (Phase 2.x) — reuses .prompt-rail base from style.css. */
.term-pane.jsonl-mode .prompt-rail.jsonl-rail.on { display: block; }
/* Task 10: under Path Z (data-dock-state present), the jsonl-rail is the sole rail */
.term-pane.jsonl-mode[data-dock-state] .prompt-rail.jsonl-rail {
  display: block;
}

/* ── Swap mode toggle (FAB) ──────────────────────────────────────────
 * Mobile: bottom-right FAB above the existing scroll-top FAB.
 * Desktop: joins the left-column FAB rail (above the mic). */
.term-pane.jsonl-mode .swap-toggle {
  position: fixed;
  right: 16px;
  bottom: 272px;
  z-index: 91;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font: 600 18px/1 var(--font-ui);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px var(--shadow, rgba(0,0,0,0.4));
  user-select: none;
  -webkit-user-select: none;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
.term-pane.jsonl-mode .swap-toggle:hover { border-color: var(--text-dim); }
.term-pane.jsonl-mode .swap-toggle:active { transform: scale(0.94); }
.term-pane.jsonl-mode.read-mode .swap-toggle {
  background: rgba(60, 90, 60, 0.92);
  border-color: var(--green, #3fb950);
}

/* Desktop: join the left FAB column (above the mic). */
@media (min-width: 769px) {
  .term-pane.jsonl-mode .swap-toggle {
    right: auto;
    left: 4px;
    bottom: 272px;
  }
}

/* Per-turn timestamp in header */
.tab-transcript .turn-header .turn-time {
  font-size: 11px;
  color: var(--text-dim);
  font-weight: 400;
  font-family: var(--font-mono);
  cursor: help;
}

/* ── Path Z dock state machine (Phase 2) ──────────────────────────────
 * Activated when `data-dock-state` is set on `.term-pane.jsonl-mode` by
 * setDockState() (app.js). When the attribute is absent (default), these
 * rules are inert and the existing swap-mode layout applies unchanged.
 * Values from DESIGN.md §0 (2026-05-14 spike findings).
 */
:root {
  --z-dock-line-height: 17px;
  --z-dock-streaming-rows: 6;
  --z-dock-ms: 200ms;
  --z-dock-ease: cubic-bezier(0.2, 0, 0, 1);
  --z-flash-ms: 800ms;
}

.term-pane.jsonl-mode[data-dock-state] {
  display: flex;
  flex-direction: column;
}
.term-pane.jsonl-mode[data-dock-state] .tab-transcript {
  display: flex;                         /* always visible in Z mode */
  flex: 1 1 auto;
  position: relative;                    /* not absolute — we share the column */
  inset: auto;
  min-height: 0;                         /* let flex shrink below content size, so .transcript-list can scroll */
  overflow: hidden;                      /* clip outer wrapper; inner .transcript-list does the actual scroll */
}
.term-pane.jsonl-mode[data-dock-state] > .xterm {
  flex: 0 0 auto;
  position: relative; inset: auto;
  overflow: hidden;
  will-change: height;
}
/* Transition on idle/streaming only — widget is rare and snap looks fine. */
.term-pane.jsonl-mode[data-dock-state="idle"] > .xterm,
.term-pane.jsonl-mode[data-dock-state="streaming"] > .xterm {
  transition: height var(--z-dock-ms) var(--z-dock-ease);
}
.term-pane.jsonl-mode[data-dock-state="idle"]      > .xterm { height: 0; }
.term-pane.jsonl-mode[data-dock-state="streaming"] > .xterm {
  height: calc(var(--z-dock-line-height) * var(--z-dock-streaming-rows));
}
.term-pane.jsonl-mode[data-dock-state="widget"]    > .xterm {
  height: 50vh; max-height: 60vh;
}

/* Flash on newly-promoted turn (DESIGN §0 spike value: 800ms blue tint). */
.tab-transcript .turn.z-fresh {
  animation: zCardFlash var(--z-flash-ms) ease-out;
}
@keyframes zCardFlash {
  0%   { background: rgba(124, 192, 240, 0.16); box-shadow: 0 0 0 2px rgba(124, 192, 240, 0.55); }
  60%  { background: rgba(124, 192, 240, 0.08); box-shadow: 0 0 0 1px rgba(124, 192, 240, 0.30); }
  100% { background: transparent;                box-shadow: 0 0 0 0 rgba(124, 192, 240, 0.00); }
}

/* ── Task 3: Compose-bar as primary input in Path Z (Phase 2) ────────────
   The compose-bar (#compose-bar / .compose-bar) is a sibling of #terminals,
   not a descendant of .term-pane. Use :has() on the shared ancestor
   (#terminal-view) to scope by the active tab's dock state.
   NOTE: plan selectors assumed per-tab markup; adjusted for global element. */

#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state="idle"])      .compose-bar { display: flex; opacity: 1; }
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state="streaming"]) .compose-bar,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state="widget"])    .compose-bar {
  display: flex; opacity: 0.5; pointer-events: none;
}
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state="streaming"]) .compose-bar textarea,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state="widget"])    .compose-bar textarea {
  pointer-events: none;
}
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state="idle"]) .compose-bar textarea::placeholder {
  content: "Type a message\2026";
}

/* ── Task 9: Show-terminal override (pinned state) ───────────────────── */
.term-pane.jsonl-mode[data-dock-state="pinned"] > .xterm {
  height: 40vh;       /* generous; user explicitly asked to see it */
}
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state="pinned"]) .compose-bar {
  display: flex; opacity: 0.5; pointer-events: none;  /* dock owns the input */
}

/* Phase 3: attachment chips on user turns ─────────────────────────────── */
.tab-transcript .attachment-chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 4px 0 6px;
}
.tab-transcript .attachment-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px;
  background: var(--surface, #161922);
  border: 1px solid var(--border, #262b38);
  border-radius: 12px;
  font: 11.5px/1.3 var(--font-mono);
  color: var(--text-dim, #8a93a4);
  text-decoration: none;
  max-width: 100%;
}
a.attachment-chip:hover {
  color: var(--text, #e6e9ef);
  border-color: var(--text-dim, #8a93a4);
}
.tab-transcript .attachment-name {
  max-width: 240px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tab-transcript .attachment-size {
  color: var(--text-dim, #8a93a4); opacity: 0.7;
}
.tab-transcript .attachment-icon { font-size: 12px; }

/* Fix: hide swap-toggle on non-active panes (it is position:fixed so per-pane
   instances stack at the same viewport coords — caught during dogfood 2026-05-14). */
.term-pane.jsonl-mode:not(.active) .swap-toggle { display: none; }

/* Fix: shrink the pane bottom under Path Z so the position:fixed compose-bar
   does not overlap the transcript scroll region.
   Caught during dogfood 2026-05-14. The compose-bar is global (sibling of
   .term-pane) and floats — so the cleanest fix is to make the pane end above it.
   The pane is position:absolute inset:0 by default; we override bottom only. */
.term-pane.jsonl-mode[data-dock-state] {
  bottom: calc(56px + env(safe-area-inset-bottom, 0px));
}
.term-pane.jsonl-mode[data-dock-state] .transcript-list {
  padding-bottom: 8px;   /* small inner gap; no longer needs to clear compose */
}

/* ── Density pass (2026-05-14): hide turn-header, tighten spacing ────────
   Header data (role / time / tokens / meta) now lives in the .turn'''s
   hover title (see transcript.js). Role is still visually distinguished
   by the left-border color and the user-turn background tint. */
.tab-transcript .turn-header { display: none; }
.tab-transcript .turn {
  margin: 4px 0;
  padding: 3px 10px 3px 12px;
}
.tab-transcript .turn.user {
  margin: 4px 0;
  padding: 5px 12px 5px 14px;
  margin-right: 12px;                     /* less aggressive indent */
  box-shadow: none;                       /* drop inner ring; border+tint is enough */
}
.tab-transcript .turn-body > .block { margin: 4px 0; }
.tab-transcript .turn-body p { margin: 4px 0; }
.tab-transcript .turn-body h1,
.tab-transcript .turn-body h2,
.tab-transcript .turn-body h3,
.tab-transcript .turn-body h4 { margin: 8px 0 2px; }
.tab-transcript .turn-body ul,
.tab-transcript .turn-body ol { margin: 4px 0; padding-left: 22px; }
.tab-transcript .turn-body li { margin: 2px 0; }
.tab-transcript .toolcard { margin: 3px 0; }
.tab-transcript .attachment-chips { margin: 3px 0 4px; }

/* ── Density pass 2 (2026-05-14): flatten user bubble, compact tool cards ── */
.tab-transcript .turn.user {
  /* Drop the rounded iOS-bubble look — flush left, just a thicker cyan border + tint.
     Keeps the visual differentiation but stops the wasted right margin + radius. */
  margin: 4px 0;
  margin-right: 0;
  padding: 4px 12px 4px 14px;
  border-left: 3px solid var(--cyan);
  border-radius: 0;
  box-shadow: none;
  background: rgba(124, 192, 240, 0.07);    /* slightly fainter tint */
}
.tab-transcript .toolcard {
  margin: 3px 0;                            /* down from 6 */
}
.tab-transcript .toolcard > summary {
  padding: 3px 8px;                         /* down from 5x10 */
  font-size: 11.5px;
}
/* Compact inter-block spacing inside an assistant turn body (overrides density pass 1). */
.tab-transcript .turn-body > .block { margin: 3px 0; }
.tab-transcript .turn-body p { margin: 3px 0; }

/* Density pass 2b: shift the FAB column up to clear the position:fixed compose-bar
   under Path Z. Compose is ~51px + safe-area; FAB column is bottom-anchored
   starting at 16px, so without this they overlap. */
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) .mic-float {
  bottom: calc(72px + env(safe-area-inset-bottom, 0px));
}
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #clear-prompt-float {
  bottom: calc(136px + env(safe-area-inset-bottom, 0px));
}
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #scroll-bottom-float {
  bottom: calc(200px + env(safe-area-inset-bottom, 0px));
}
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #scroll-top-float {
  bottom: calc(264px + env(safe-area-inset-bottom, 0px));
}

/* Stack the swap-toggle above the scroll-top FAB under Path Z so they do not
   overlap. Original rule pinned it at bottom:272px which collided with our
   shifted scroll-top at bottom:264+safe-area. */
.term-pane.jsonl-mode[data-dock-state] .swap-toggle {
  bottom: calc(328px + env(safe-area-inset-bottom, 0px));
}
@media (min-width: 769px) {
  .term-pane.jsonl-mode[data-dock-state] .swap-toggle {
    bottom: calc(328px + env(safe-area-inset-bottom, 0px));
  }
}

/* FOUC guard: under html.path-z, hide the xterm BEFORE JS sets data-dock-state.
   Without this, the xterm renders at default size for a beat on page load, then
   collapses to height:0 when setDockState(tab, idle) fires — visible flash. */
html.path-z .term-pane.jsonl-mode:not([data-dock-state]) > .xterm { height: 0; overflow: hidden; }
html.path-z .term-pane.jsonl-mode { display: flex; flex-direction: column; }

/* ── Path Z compose-bar visual blend with transcript ───────────────────
   Make the compose-bar look like the next line of the conversation, not a
   floating panel. Background matches transcript; remove the top border;
   strip the textarea chrome; add a ❯ prefix that picks up the same cyan
   accent the user-turn left-border uses. */
html.path-z #compose-bar,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #compose-bar {
  background: var(--bg);
  border-top: none;
  padding: 4px 12px 8px 12px;
  align-items: center;
}
html.path-z #compose-bar::before,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #compose-bar::before {
  content: "❯";
  color: var(--cyan, #7cc0f0);
  font: 600 16px/1 var(--font-mono, ui-monospace);
  padding-right: 4px;
  flex: 0 0 auto;
  align-self: center;
}
html.path-z #compose-bar textarea,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #compose-bar textarea {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 4px 6px;
  font: 15px/1.4 var(--font-mono, ui-monospace);
  height: 30px;
  min-height: 30px;
}
html.path-z #compose-bar textarea:focus,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #compose-bar textarea:focus {
  border: none;
  outline: 1px dashed rgba(124, 192, 240, 0.35);
  outline-offset: -2px;
}
html.path-z #compose-bar button#compose-send,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #compose-bar button#compose-send {
  height: 30px;
  width: 36px;
  font-size: 16px;
  background: transparent;
  color: var(--cyan, #7cc0f0);
  border: 1px solid rgba(124, 192, 240, 0.45);
}
html.path-z #compose-bar button#compose-clear,
#terminal-view:has(.term-pane.active.jsonl-mode[data-dock-state]) #compose-bar button#compose-clear {
  height: 30px;
  width: 30px;
}

/* FOUC guard for the compose-bar: under html.path-z, force visible/active
   IMMEDIATELY on first paint, before JS gets a chance to set data-dock-state
   or remove the .hidden class from the global compose-bar element. */
html.path-z #compose-bar,
html.path-z #compose-bar.hidden {
  display: flex !important;
  opacity: 1;
  pointer-events: auto;
}
html.path-z #compose-bar textarea {
  pointer-events: auto;
}


/* ── Path Z dual UI mode (chat vs terminal) ─────────────────────────────
   data-ui-mode="terminal" on the active jsonl-mode pane: the xterm fills
   the pane; transcript is hidden; compose-bar is hidden; xterm has focus.
   Triggered by typing /@! in compose or by the swap-toggle button. */

/* Terminal mode: xterm fills the pane */
.term-pane.jsonl-mode[data-ui-mode="terminal"] > .xterm {
  height: 100%;
  max-height: 100%;
}

/* Terminal mode: transcript hidden */
.term-pane.jsonl-mode[data-ui-mode="terminal"] .tab-transcript {
  display: none;
}

/* Terminal mode: compose-bar hidden (active pane only — :has() scope) */
#terminal-view:has(.term-pane.active.jsonl-mode[data-ui-mode="terminal"]) .compose-bar {
  display: none !important;
}

/* Terminal mode: rail also hidden (rail is for transcript navigation) */
.term-pane.jsonl-mode[data-ui-mode="terminal"] .prompt-rail.jsonl-rail {
  display: none;
}

/* When in terminal mode, the pane can use its full bottom — undo the
   compose-bar gap from dcde8a8. */
.term-pane.jsonl-mode[data-ui-mode="terminal"] {
  bottom: 0 !important;
}
