/* The chat: messages, the status tree, rendered answers and the composer.
 * Class names are the contract with static/js/chat_module.js and its helpers;
 * colours, spacing and type come from the kit tokens only. */

/* ---------------------------------------------------------------- messages */

.chat {
  width: 100%; max-width: 920px; margin: 0 auto;
  padding: var(--space-6) var(--space-6) var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-4);
}
.row { display: flex; }
.msg { min-width: 0; font-size: var(--text-md); line-height: 1.6; color: var(--text-primary); }

.msg.user {
  margin-left: auto; max-width: min(78%, 680px);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-3); border-radius: var(--radius-lg) var(--radius-lg) var(--radius-sm) var(--radius-lg);
  white-space: normal; overflow-wrap: anywhere;
}
.msg.user.continuation-msg { background: transparent; border: 1px dashed var(--border-default); }
.continuation-badge { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--text-xs); color: var(--text-muted); }
.continuation-text { color: var(--text-secondary); }
.continuation-reason { font-size: var(--text-xs); color: var(--text-muted); }

.msg.assistant { width: 100%; }
.msg.note { width: 100%; }
.note-text {
  margin: 0; padding: var(--space-3); white-space: pre-wrap;
  font: 400 var(--text-sm)/1.55 var(--font-mono); color: var(--text-secondary);
  background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
}

.user-image-previews { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.user-image-previews img { max-width: 180px; max-height: 140px; border-radius: var(--radius-md); border: 1px solid var(--border-subtle); cursor: zoom-in; object-fit: cover; }
.user-audio-previews, .user-text-file-previews { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); }
.attachment-toggle { align-self: flex-start; }
.attachment-text { max-height: 300px; }

.message-request-id, .operation-request-id {
  font: 400 11px/1 var(--font-mono); color: var(--text-muted);
}
.message-request-id { margin-top: var(--space-2); }
.message-request-id span { user-select: all; }

/* ------------------------------------------------ assistant block sections */

.container-section + .container-section { margin-top: var(--space-2); }
.container-header {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 2px var(--space-2) 2px var(--space-1); border-radius: var(--radius-sm);
  font-size: var(--text-xs); color: var(--text-muted); cursor: pointer; user-select: none;
}
.container-header:hover { color: var(--text-secondary); background: var(--surface-3); }
.toggle-arrow { display: inline-flex; }
.toggle-arrow .pk-icon { transition: transform var(--duration-fast); }
.container-section[data-open="true"] > .container-header .toggle-arrow .pk-icon { transform: rotate(90deg); }
.type-icon { display: inline-flex; color: var(--text-muted); }
.container-label { font-weight: 500; }
.container-body { padding: var(--space-1) 0 0 var(--space-5); }
.container-body > pre, .step-thinking > pre {
  margin: 0; padding: var(--space-3); max-height: 360px; overflow: auto; white-space: pre-wrap;
  font: 400 var(--text-xs)/1.6 var(--font-mono); color: var(--text-secondary);
  background: var(--surface-1); border-left: 2px solid var(--border-default); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
/* The response has no chrome: the answer is the content. */
.container-section:has(> [data-toggle="response"]) > .container-header { display: none; }
.container-section:has(> [data-toggle="response"]) > .container-body { padding: 0; }
/* A sub-agent's answer is not the conversation's: it folds under a header of its own, as
   a step does -- folded by default (chat.sub_agent_output), so answers streaming in several
   sub-agents at once do not push the chat about. */
.sub-run-body > .container-section > [data-toggle="response"] { display: inline-flex; }
.sub-run-body > .container-section:has(> [data-toggle="response"]) > .container-body { padding: var(--space-1) 0 0 var(--space-5); }

/* One section per LLM call, built as the run goes. The steps sit above the answer and
   keep it in view: folded, a thirty-step run is thirty lines rather than thirty walls. */
.steps:not(:empty) { margin-bottom: var(--space-2); }
.step-note { margin-left: var(--space-1); font-size: var(--text-xs); }

/* A call's thinking: a header of its own, the text folded or not as the viewer chose. */
.step-thinking { margin-bottom: var(--space-1); }
.step-thinking > pre { margin-top: 2px; }
.thinking-toggle {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 1px var(--space-2) 1px var(--space-1); border-radius: var(--radius-sm);
  font-size: var(--text-xs); color: var(--text-muted); cursor: pointer; user-select: none;
}
.thinking-toggle:hover { color: var(--text-secondary); background: var(--surface-3); }
.thinking-toggle .pk-icon, .sub-run-header .toggle-arrow .pk-icon { transition: transform var(--duration-fast); }
.thinking-toggle[aria-expanded="true"] .pk-icon,
.sub-run-header[aria-expanded="true"] .toggle-arrow .pk-icon { transform: rotate(90deg); }
.thinking-toggle:focus-visible, .sub-run-header:focus-visible, .step-section > .container-header:focus-visible,
.sub-run-body > .container-section > .container-header:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* A run started from a call: its own steps and answer, one level in, under the row of
   the call that started it -- in the step that started it, however late it reports.
   It sits inside a status row, so it takes back the chat's own type. */
.sub-run {
  margin: var(--space-1) 0 var(--space-2) var(--space-5); padding-left: var(--space-3);
  border-left: 2px solid var(--border-default);
  font: 400 var(--text-sm)/1.5 var(--font-ui);
}
.sub-run-header {
  display: inline-flex; align-items: center; gap: var(--space-2); max-width: 100%;
  padding: 2px var(--space-2) 2px var(--space-1); border-radius: var(--radius-sm);
  font-size: var(--text-xs); color: var(--text-secondary); cursor: pointer; user-select: none;
}
.sub-run-header:hover { background: var(--surface-3); }
.sub-run-icon { width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.sub-run-agent { font-weight: 500; color: var(--accent-text); flex: none; }
.sub-run-task { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sub-run-body { padding-top: var(--space-1); }

/* What a tool was asked and what it answered: ONE folded block under its status line,
   opened by clicking the status text itself. No control of its own — a line of status
   plus two link labels is mostly labels, and the two halves are one thing to read.
   Quiet on purpose: a row that has a detail looks like every other row until the
   pointer is on it, so a run is still read by its lines. */
.operation-progress.has-detail > .progress-line > .progress-message { cursor: pointer; }
.operation-progress.has-detail > .progress-line > .progress-message:hover,
.tool-detail-name:hover {
  color: var(--text-primary);
  text-decoration: underline dotted; text-underline-offset: 3px;
}
.operation-progress.has-detail > .progress-line > .progress-message:focus-visible,
.tool-detail-name:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm);
}
.tool-detail-body { margin: var(--space-1) 0 var(--space-2); }
.tool-detail-part + .tool-detail-part { margin-top: var(--space-2); }
.tool-detail-label {
  display: block; color: var(--text-muted);
  font: 400 var(--text-xs)/1.6 var(--font-mono);
}
.tool-detail-body pre {
  margin: 2px 0 0; padding: var(--space-2); max-height: 320px; overflow: auto;
  white-space: pre-wrap; font: 400 var(--text-xs)/1.5 var(--font-mono);
  color: var(--text-secondary); background: var(--surface-1);
  border-left: 2px solid var(--border-default); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
/* A call that opened no status scope has no line to click and brings one of its own. */
.tool-detail { padding-left: var(--space-5); }
.tool-detail-name {
  cursor: pointer; font: 400 var(--text-xs)/1.6 var(--font-mono); color: var(--text-muted);
}

/* ------------------------------------------------------------- status tree */

.operation-progress { font: 400 var(--text-xs)/1.5 var(--font-mono); }
.operation-progress.virtual-parent .progress-message { color: var(--text-muted); }
.progress-line { display: flex; align-items: center; gap: var(--space-2); padding: 2px 0; min-width: 0; }
.progress-icon { width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.spinner {
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid var(--border-default); border-top-color: var(--accent);
  animation: pk-spin 0.9s linear infinite;
}
.checkmark { color: var(--ok); font-weight: 600; }
.error-mark { color: var(--danger); font-weight: 600; }
.progress-time { color: var(--text-muted); flex: none; }
.progress-server { color: var(--accent-text); flex: none; }
.progress-message { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-secondary); }
.operation-progress.completed .progress-message { color: var(--text-secondary); }
.operation-progress.error .progress-message { color: var(--danger); }
/* Still open when the run ended -- deliberately neither of the two above. A
   checkmark would claim work finished that may still be running, and the red
   cross would call it a failure. It is simply nobody's business any more. */
.open-mark { color: var(--text-muted); font-weight: 600; }
.operation-progress.unfinished .progress-message { color: var(--text-muted); }
.progress-open-note { color: var(--text-muted); font-style: italic; flex: none; }

/* A question the run put to the person watching it, under the row that asks,
   drawn from its form whatever its kind (questionBox): what is asked, what
   answering gives up, text to read as it is, the choices, a field to write in. */
.question-actions {
  margin: var(--space-1) 0 var(--space-2) var(--space-5); padding: var(--space-2);
  border-left: 2px solid var(--accent); background: var(--surface-1);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.question-prompt {
  margin: 0 0 var(--space-2); white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: var(--text-sm); color: var(--text-primary);
}
.question-warning {
  margin-bottom: var(--space-2); padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm);
  background: var(--danger-subtle); color: var(--danger); font-size: var(--text-xs); font-weight: 600;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.question-detail {
  margin: 0 0 var(--space-2); max-height: 24em; overflow: auto; white-space: pre-wrap;
  overflow-wrap: anywhere; font: 400 var(--text-xs)/1.5 var(--font-mono); color: var(--text-secondary);
}
.question-choices { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-2); }
/* a choice is the run's text: it wraps rather than running out of the box */
.question-choices .pk-btn { height: auto; min-height: var(--control-h-sm); white-space: normal; text-align: left; }
label.question-choice {
  display: inline-flex; align-items: center; gap: var(--space-1); cursor: pointer;
  font-size: var(--text-xs); color: var(--text-secondary); overflow-wrap: anywhere;
}
.question-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.question-text { flex: 1 1 14em; min-width: 0; height: var(--control-h-sm); font-size: var(--text-xs); }
.question-note { color: var(--text-muted); font-size: var(--text-xs); }
/* A call a hook blocked: the reason is the point of the line, so it wraps. */
.operation-progress.blocked .progress-message { white-space: normal; overflow-wrap: anywhere; }

.tree-indicator { position: relative; display: inline-block; width: 16px; flex: none; }
.tree-expand-btn {
  position: absolute; left: -4px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm); cursor: pointer; color: var(--text-muted);
}
.tree-expand-btn:hover { background: var(--surface-3); }
.expand-icon { width: 12px; height: 12px; transition: transform var(--duration-fast); }
.operation-progress[data-expanded="true"] > .progress-line .expand-icon { transform: rotate(90deg); }
.tree-connector { position: absolute; left: -4px; top: -9px; color: var(--border-strong); user-select: none; }
.tree-indicator .tree-expand-btn[style*="inline-block"] + .tree-connector,
.tree-indicator .tree-expand-btn[style*="block"] + .tree-connector { display: none; }

/* ------------------------------------------------------------ the answer */

.response-text { font-size: var(--text-md); line-height: 1.65; color: var(--text-primary); overflow-wrap: anywhere; }
.response-text > :first-child { margin-top: 0; }
.response-text > :last-child { margin-bottom: 0; }
.response-text p { margin: 0 0 var(--space-3); }
.response-text h1, .response-text h2, .response-text h3, .response-text h4 { margin: var(--space-5) 0 var(--space-2); line-height: 1.3; }
.response-text h1 { font-size: var(--text-xl); }
.response-text h2 { font-size: var(--text-lg); }
.response-text h3, .response-text h4 { font-size: var(--text-md); }
.response-text ul, .response-text ol { margin: 0 0 var(--space-3); padding-left: var(--space-5); }
.response-text li { margin: 2px 0; }
.response-text blockquote {
  margin: 0 0 var(--space-3); padding: var(--space-1) var(--space-3);
  color: var(--text-secondary); border-left: 3px solid var(--border-strong);
}
.response-text hr { border: 0; border-top: 1px solid var(--border-subtle); margin: var(--space-4) 0; }
.response-text a { color: var(--accent-text); }
.response-text code { padding: 1px 5px; font-size: 0.88em; background: var(--surface-3); border-radius: var(--radius-sm); }
.response-text pre {
  position: relative; margin: 0 0 var(--space-3); padding: var(--space-3); overflow: auto;
  font: 400 var(--text-xs)/1.6 var(--font-mono);
  background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
}
.response-text pre code { padding: 0; background: none; font-size: inherit; }
.response-text table { width: 100%; margin: 0 0 var(--space-3); border-collapse: collapse; font-size: var(--text-sm); display: block; overflow-x: auto; }
.response-text th, .response-text td { padding: var(--space-1) var(--space-3); border: 1px solid var(--border-subtle); text-align: left; vertical-align: top; }
.response-text th { font-weight: 600; background: var(--surface-1); }

.response-text.streaming { white-space: pre-wrap; }
.response-text.error { color: var(--danger); }
.response-text.reconnect-info { color: var(--text-secondary); font-size: var(--text-sm); }
.typing-cursor { display: inline-block; margin-left: 1px; color: var(--accent-text); animation: chat-blink 1s steps(1) infinite; }
@keyframes chat-blink { 50% { opacity: 0; } }

/* syntax highlighting (Prism tokens) */
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: var(--text-muted); font-style: italic; }
.token.punctuation, .token.operator { color: var(--text-secondary); }
.token.keyword, .token.atrule, .token.important, .token.selector { color: var(--accent-text); }
.token.string, .token.char, .token.attr-value, .token.inserted { color: var(--ok); }
.token.number, .token.boolean, .token.constant, .token.symbol { color: var(--warn); }
.token.function, .token.class-name, .token.builtin { color: var(--info); }
.token.property, .token.tag, .token.attr-name, .token.variable { color: var(--text-primary); }
.token.deleted, .token.regex { color: var(--danger); }

/* ------------------------------------------------------------ read-only */

.read-only-banner {
  display: flex; gap: var(--space-3); align-items: flex-start; padding: var(--space-3);
  background: var(--warn-subtle); border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
}
.read-only-banner .banner-icon { color: var(--warn); display: inline-flex; }
.read-only-banner .banner-text strong { display: block; font-size: var(--text-sm); }
.read-only-banner .banner-text p { margin: 2px 0 0; font-size: var(--text-sm); color: var(--text-secondary); }

/* --------------------------------------------------------------- composer */

.inputBar { padding: 0 var(--space-6) var(--space-4); }
.composer {
  max-width: 920px; margin: 0 auto;
  background: var(--surface-2); border: 1px solid var(--border-default); border-radius: var(--radius-lg);
  box-shadow: 0 1px 0 var(--border-subtle);
}
.composer:focus-within { border-color: var(--focus-ring); box-shadow: 0 0 0 3px var(--accent-subtle); }
.input-container { position: relative; }
#task {
  display: block; width: 100%; min-height: 48px; max-height: 200px; resize: none;
  padding: var(--space-3) var(--space-3) var(--space-1);
  font: 400 var(--text-md)/1.5 var(--font-ui); color: var(--text-primary);
  background: transparent; border: 0; outline: none;
}
#task::placeholder { color: var(--text-muted); }
#task:disabled { opacity: 0.5; }
.composer-bar { display: flex; align-items: center; gap: var(--space-1); padding: var(--space-1) var(--space-2) var(--space-2); }
.composer-select {
  display: inline-flex; align-items: center; gap: var(--space-1); min-width: 0; max-width: 220px;
  height: var(--control-h-sm); padding: 0 var(--space-1) 0 var(--space-2);
  font: 500 var(--text-xs)/1 var(--font-ui); color: var(--text-secondary);
  background: transparent; border: 0; border-radius: var(--radius-md); cursor: pointer;
}
.composer-select:hover { background: var(--surface-3); color: var(--text-primary); }
.composer-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* A profile chosen for this chat, not the agent's own (selector_module.js): only the icon says so --
   a whole blue button read as "selected right now" */
.composer-select.is-custom > .pk-icon:first-child { color: var(--accent); }
.think-menu .pk-menu-item[aria-pressed="false"] > .pk-icon { visibility: hidden; }
/* Stop is red: the kit's danger button. Once a stop has an outcome the plain button comes
   back, and its icon says how it ended -- on red, the red of a failed stop would vanish. */
.stop-btn:not(.cancelled, .cancel-failed) {
  --btn-bg: var(--danger); --btn-fg: var(--text-on-accent); --btn-border: transparent; --btn-bg-hover: var(--danger-hover);
}
.stop-btn.cancelling { opacity: 0.6; }
.stop-btn.cancelled { --btn-fg: var(--ok); }
.stop-btn.cancel-failed { --btn-fg: var(--danger); }
.input-container.is-dragover #task { background: var(--accent-subtle); }

.attached-files { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-2) var(--space-3) 0; }
.attached-files:empty { display: none; }
.attached-file-item {
  display: inline-flex; align-items: center; gap: var(--space-2); max-width: 240px; height: 28px;
  padding: 0 var(--space-1) 0 var(--space-2); font-size: var(--text-xs);
  background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
}
.attached-file-item.is-invalid { color: var(--danger); border-color: var(--danger); }
.attached-file-icon { display: inline-flex; color: var(--text-muted); }
.attached-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attached-file-size { color: var(--text-muted); }
.attached-file-remove { width: 20px; height: 20px; padding: 0; color: var(--text-muted); background: none; border: 0; border-radius: var(--radius-sm); cursor: pointer; }
.attached-file-remove:hover { color: var(--text-primary); background: var(--surface-3); }

/* slash command suggestions */
.slash-suggestions {
  position: absolute; left: var(--space-2); right: var(--space-2); bottom: calc(100% + var(--space-2)); z-index: 20;
  max-height: 260px; overflow: auto; padding: var(--space-1);
  background: var(--surface-2); border: 1px solid var(--border-default); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-overlay);
}
.slash-suggestion { display: flex; gap: var(--space-3); align-items: baseline; padding: var(--space-2); border-radius: var(--radius-sm); cursor: pointer; }
.slash-suggestion.is-active, .slash-suggestion:hover { background: var(--surface-3); }
.slash-name { font: 500 var(--text-sm)/1.2 var(--font-mono); color: var(--text-primary); }
.slash-hint { font-size: var(--text-xs); color: var(--text-muted); }

/* ------------------------------------------------------------ start page */

.chat-welcome { display: flex; flex-direction: column; gap: var(--space-4); padding: 12vh 0 var(--space-4); }
.chat-welcome-brand { display: flex; align-items: center; gap: var(--space-3); color: var(--brand); }
.chat-welcome-brand h1 { color: var(--text-primary); font-size: 22px; }
.chat-welcome p { margin: 0; color: var(--text-secondary); }
.chat-welcome-recent { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-2); }
.chat-welcome-card {
  display: flex; flex-direction: column; gap: 2px; padding: var(--space-3); text-align: left;
  color: var(--text-primary); background: var(--surface-2); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg); cursor: pointer;
}
.chat-welcome-card:hover { border-color: var(--border-strong); }
.chat-welcome-card span { font-size: var(--text-xs); color: var(--text-muted); }

@media (max-width: 960px) {  /* the shell's narrow screen (shell.css) */
  .chat { padding: var(--space-4) var(--space-3); }
  .inputBar { padding: 0 var(--space-2) var(--space-2); }
  .msg.user { max-width: 92%; }
}

/* A session woken into a process this page cannot follow. Not an error and not
   a run: the page can only say so and wait, because that run's events never
   reach this server at all. */
.working-elsewhere {
  margin: var(--space-2) 0; padding: var(--space-2) var(--space-3);
  font: 400 var(--text-xs)/1.5 var(--font-ui); color: var(--text-muted);
  background: var(--surface-1); border-left: 2px solid var(--border-default);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
