/* Qubis OS — the chat page (public/chat.js, execution.js, chatMedia.js).
   Split out of style.css on 2026-09-10; see the header there for the seam and
   why the <link> order in index.html is load-bearing. */

/* ---------- chat ---------- */
#page-chat { animation: fadeUp 0.3s ease both; }
.chat-header {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 28px; border-bottom: 1px solid var(--color-divider);
}
.chat-header-text { flex: 1; }
.chat-agent-name { font-size: 15px; font-weight: 500; }
.chat-agent-role { font-size: 12.5px; color: var(--color-neutral-400); }

.kill-btn {
  background: transparent; border: 1px solid var(--color-divider); color: var(--color-neutral-400);
  border-radius: var(--radius-md); padding: 8px 14px; font-size: 12.5px;
  display: flex; align-items: center; gap: 7px;
}
.kill-btn:hover { border-color: var(--warn); }
.kill-btn.active { background: color-mix(in srgb, var(--warn) 16%, transparent); border-color: var(--warn); color: color-mix(in srgb, var(--warn) 70%, var(--color-text)); }

.messages-wrap { flex: 1; overflow-y: auto; padding: 0 28px; }
.chat-hero { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 26px; position: relative; text-align: center; }
.hero-greeting { font-size: 26px; font-weight: 500; letter-spacing: -0.015em; }
.hero-sub { margin-top: 6px; font-size: 15px; }
.hero-suggestions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; max-width: 620px; }
.hero-chip {
  background: transparent; border: 1px solid var(--color-divider); color: var(--color-neutral-300);
  border-radius: 999px; padding: 9px 18px; font-size: 13.5px;
}

.messages { max-width: 720px; margin: 0 auto; padding: 26px 0; display: flex; flex-direction: column; gap: 18px; }
.msg { display: flex; flex-direction: column; gap: 4px; animation: msgIn 0.25s ease both; }
.msg-user { align-items: flex-end; }
.msg-qubis { align-items: flex-start; }
.msg-agent-label { font-size: 11.5px; color: var(--color-accent-300); padding-left: 2px; }
.msg-bubble { max-width: 78%; border-radius: 16px; padding: 12px 16px; font-size: 15.5px; line-height: 1.6; white-space: pre-wrap; }
.msg-user .msg-bubble { background: color-mix(in srgb, var(--color-accent) 14%, transparent); border: 1px solid color-mix(in srgb, var(--color-accent) 30%, transparent); }
.msg-qubis .msg-bubble { background: var(--color-surface); border: 1px solid var(--color-divider); }
.msg-qubis.streaming .msg-bubble::after { content: "▌"; opacity: 0.6; animation: blink 1s step-end infinite; }

/* ---------- execution details (execution.js) ---------- */
/* One <details> per reply, above its bubble. Collapsed it is one quiet line;
   the caret turns when it opens. Steps grey to "done" behind the newest, a
   notice (fallback, continuity) never greys because it stays true, and an
   error row is the last thing in a failed trace. */
.execution {
  max-width: 78%; margin: 0 0 6px; border: 1px solid var(--color-divider); border-radius: var(--radius-md);
  padding: 8px 12px; font-size: 12.5px; animation: msgIn 0.25s ease both;
}
.execution-failed { border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.execution-summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 6px; color: var(--color-neutral-400); user-select: none; }
.execution-summary::-webkit-details-marker { display: none; }
.execution-caret { font-size: 12px; transition: transform 0.15s; }
.execution[open] .execution-caret { transform: rotate(90deg); }
.execution-title { font-weight: 500; color: var(--color-text); }
.execution-meta { color: var(--color-neutral-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.execution-steps { list-style: none; margin: 10px 0 2px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.execution-steps li { font-size: 13px; color: var(--color-text); display: flex; align-items: flex-start; gap: 8px; }
.execution-steps li::before { font-family: "Phosphor"; content: "\e2c8"; color: var(--color-accent-300); flex: none; }
.execution-steps li.done { color: var(--color-neutral-500); }
.execution-steps li.done::before { content: "\e134"; color: var(--signal); }
/* The degraded-model / continuity notice. Same warm treatment as an approval:
   it is the one line about the system rather than the work, it never greys to
   "done" (it stays true for the whole answer), and it must not look like an
   error — the system is working. */
.execution-steps li.execution-notice {
  font-size: 12px; line-height: 1.5; padding: 8px 10px; margin: 2px 0; border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--warn) 10%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
}
.execution-steps li.execution-notice::before { content: none; }
.execution-steps li.execution-error { color: color-mix(in srgb, var(--warn) 70%, var(--color-text)); }
.execution-steps li.execution-error::before { content: "\e4e4"; color: var(--warn); }
/* The routing step's "why" clause — quieter than the label it follows, and it
   wraps rather than truncating. The text block keeps the li at two children
   so a wrapping label cannot orphan the status icon. */
.execution-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.execution-why { color: var(--color-neutral-500); font-size: 12px; line-height: 1.4; }

/* ---------- message actions ---------- */
/* Time plus two icons, shown on hover or keyboard focus, hidden while a reply
   streams. Space is reserved so rows do not jump when the bar appears. */
.msg-actions { display: flex; align-items: center; gap: 2px; min-height: 22px; padding: 0 2px; opacity: 0; transition: opacity 0.15s; }
.msg:hover .msg-actions, .msg:focus-within .msg-actions { opacity: 1; }
.msg-qubis.streaming .msg-actions { visibility: hidden; }
/* Landing from the Work drawer: the exchange lights briefly so the eye finds it. */
.msg-focus .msg-bubble { box-shadow: 0 0 0 2px var(--color-accent); transition: box-shadow 0.4s; }
.msg-time { font-size: 11px; color: var(--color-neutral-500); margin-right: 4px; }
.msg-action {
  background: transparent; border: none; color: var(--color-neutral-500); padding: 3px 5px; border-radius: 6px;
  display: inline-flex; align-items: center; font-size: 14px; cursor: pointer;
}
.msg-action:hover, .msg-action:focus-visible { color: var(--color-text); background: color-mix(in srgb, var(--color-text) 7%, transparent); outline: none; }

/* ---------- composer ---------- */
.chat-input-wrap { position: relative; padding: 14px 28px 20px; }
.kill-banner {
  max-width: 720px; margin: 0 auto 10px; display: flex; align-items: center; gap: 9px;
  border: 1px solid color-mix(in srgb, var(--warn) 50%, transparent); border-radius: var(--radius-md);
  padding: 9px 14px; font-size: 13px; color: color-mix(in srgb, var(--warn) 70%, var(--color-text));
}
/* One surface: the field on top, a toolbar under it. The border brightens on
   focus-within rather than on the textarea, because the whole card is the
   control. */
.composer {
  max-width: 720px; margin: 0 auto; display: flex; flex-direction: column; gap: 6px;
  background: var(--color-surface); border: 1px solid var(--color-divider); border-radius: 16px;
  padding: 12px 12px 8px 16px; box-shadow: var(--shadow-sm); transition: border-color 0.15s, box-shadow 0.15s;
}
.composer:focus-within { border-color: color-mix(in srgb, var(--color-accent) 60%, var(--color-divider)); box-shadow: var(--shadow-md); }
/* max-height is the growth cap (~8 lines); past it the field scrolls. The
   height itself is set by chat.js from scrollHeight on every input. The id
   selector outranks the app-wide control rule above on purpose: inside the
   composer the card is the border, so the field has none. */
#chatInput {
  width: 100%; background: transparent; border: none; outline: none; color: var(--color-text); box-shadow: none;
  font: inherit; font-size: 15px; line-height: 1.5; resize: none; overflow-y: auto;
  max-height: 180px; padding: 4px 0;
}
#chatInput:disabled { opacity: 0.6; cursor: not-allowed; }
.composer-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.composer-tools { display: flex; align-items: center; gap: 2px; }
.composer-tools .icon-btn-flat { width: 32px; height: 32px; padding: 0; border-radius: 8px; font-size: 18px; }
.composer-tools .icon-btn-flat:hover:not(:disabled) { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
/* Send is the .btn language at its most compact: filled, round, icon only. */
.send-btn { width: 34px; height: 34px; padding: 0; border-radius: 50%; font-size: 17px; flex: none; }

/* The way back to the newest message, floating above the composer. */
.jump-latest {
  position: absolute; left: 50%; top: -12px; transform: translate(-50%, -100%); z-index: 2;
  width: 34px; height: 34px; border-radius: 50%; padding: 0;
  background: var(--color-surface); border: 1px solid var(--color-divider); color: var(--color-neutral-300);
  box-shadow: var(--shadow-md); display: flex; align-items: center; justify-content: center; font-size: 16px;
  animation: fadeUp 0.2s ease both;
}
.jump-latest:hover { color: var(--color-text); border-color: var(--color-accent); }
.jump-latest:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* ---------- chat attachments ---------- */
.attach-tray { display: flex; flex-wrap: wrap; gap: 6px; padding-bottom: 4px; }
.attach-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 260px;
  background: var(--color-surface-2); border: 1px solid var(--color-divider); border-radius: 10px;
  padding: 5px 8px; font-size: 12px; color: var(--color-text);
}
/* An image chip is its thumbnail: the name becomes the tooltip. */
.attach-chip-image { padding: 3px; gap: 0; position: relative; }
.attach-chip-image .attach-chip-name { position: absolute; left: -9999px; }
/* The per-file sensitivity pick on a staged attachment (queue item 37(c)). */
.attach-chip-sensitivity { margin-left: 6px; font-size: 11px; max-width: 170px; }
.attach-thumb { width: 56px; height: 56px; object-fit: cover; border-radius: 7px; display: block; }
.attach-chip-image .attach-chip-remove, .attach-chip-image .attach-chip-busy {
  position: absolute; top: -6px; right: -6px; background: var(--color-surface); border: 1px solid var(--color-divider);
  border-radius: 50%; width: 18px; height: 18px; align-items: center; justify-content: center; font-size: 11px;
}
.attach-chip-image .attach-chip-busy { display: flex; }
.attach-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attach-chip-error { border-color: var(--warn); color: color-mix(in srgb, var(--warn) 70%, var(--color-text)); }
.attach-chip-busy { animation: attachSpin 1s linear infinite; }
@keyframes attachSpin { to { transform: rotate(360deg); } }
.attach-chip-remove { background: none; border: none; color: var(--color-text-muted); cursor: pointer; display: flex; }
.attach-chip-remove:hover { color: var(--color-text); }
.msg-attachments { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.msg-attachment { max-width: 320px; max-height: 240px; border-radius: 10px; border: 1px solid var(--color-divider); }
audio.msg-attachment { max-height: none; }
/* A generated clip or image and its own download link, stacked as one item so
   the link belongs to the thing above it rather than to the row. */
.msg-media { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.msg-download { font-size: 12px; color: var(--color-text-muted); text-decoration: none; }
.msg-download:hover { color: var(--color-text); text-decoration: underline; }
/* A clip still rendering (chatMedia.js watchRendering): the spinner tag is
   what shows; the erroring player and its download link — which would fetch
   the route's 404 as a file — wait behind it until metadata arrives. */
.msg-generating { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--color-text-muted); }
.msg-media-rendering .msg-attachment, .msg-media-rendering .msg-download { display: none; }
.msg-attachment-image { cursor: zoom-in; }
.msg-attachment-image:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
#page-chat.drop-target .composer { border-style: dashed; border-color: var(--color-accent); }

/* ---------- lightbox (chatMedia.js) ---------- */
.lightbox { background: color-mix(in srgb, var(--color-bg) 88%, transparent); cursor: zoom-out; }
.lightbox-img { max-width: min(92vw, 1400px); max-height: 90vh; border-radius: var(--radius-md); box-shadow: var(--shadow-lg); animation: fadeUp 0.2s ease both; }
.lightbox-close {
  position: absolute; top: 18px; right: 22px; width: 36px; height: 36px; border-radius: 50%; padding: 0;
  background: var(--color-surface); border: 1px solid var(--color-divider); color: var(--color-text);
  display: flex; align-items: center; justify-content: center; font-size: 18px;
}
.lightbox-close:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }


/* The one-line undo offered right after a clear (42.1.1). */
.chat-restore-bar { text-align: center; font-size: 13px; padding: 10px 0; }
