/**
 * @file inbox.css
 * @description Styles for the profile Inbox tab (human↔human direct messaging): a two-pane messenger
 *   — conversation/request list + thread pane with chat bubbles, avatars, date dividers, delivery
 *   ticks, and a sticky composer. All colors/spacing use theme.css variables (dark-mode safe).
 *   Classes are `inbox-` prefixed. NOTE: this file must be linked in spa.html (useViewCSS is a no-op).
 * @version-history
 *   v1.10.0 -- 2026-08-03 -- .inbox-thread-older: the "Show full history (N messages)" pill at the top
 *     of a thread showing only its newest page.
 *   v1.9.0 -- 2026-08-03 -- Mobile thread header space fix: ≤760px flattens the id column
 *     (display:contents) so subject / via / GHII become full-width rows under the avatar+name+buttons
 *     row, subject clamped to 2 lines — a long subject no longer wraps word-per-line in a narrow
 *     column and eats half the screen. Desktop header unchanged.
 *   v1.8.0 -- 2026-07-31 -- Read-aloud controls: the thread-head Listen/Pause/Continue pill
 *     (.inbox-speak-group/-btn/-ico/-stop) that speaks the open conversation. The per-message 🔊 reuses
 *     the existing .inbox-bubble-act pill.
 *   v1.7.0 -- 2026-07-21 -- Link-preview (unfurl) cards under a pasted link (.inbox-linkcard*) + the
 *     thread-head show/hide toggle (.inbox-linkprev-toggle).
 *   v1.6.0 -- 2026-07-18 -- TRUE full-screen mobile chat: ≤760px open panel becomes `position:fixed;inset:0`
 *     over the whole viewport (covers the app shell nav/menu/breadcrumb); body height var(--inbox-avail,
 *     100dvh) + safe-area padding under the composer. ← Back drops `.inbox--panel` → shell returns. Pairs
 *     with spa.html viewport interactive-widget=resizes-content + viewport-fit=cover.
 *   v1.5.0 -- 2026-07-18 -- Fix the keyboard dead-gap + heavy composer: ≤760px open-panel body height now
 *     uses measured `--inbox-avail` (body-top→visual-viewport-bottom) instead of the `dvh − keyboard`
 *     double-count that collapsed the pane on Android Chrome; new `.inbox-textarea--chat` = the mobile
 *     single-line auto-growing composer (no Toast UI toolbar). Drops the stale `--inbox-kb` var.
 *   v1.4.0 -- 2026-07-18 -- Mobile space reclaim: when a thread/compose panel is open (`.inbox--panel`),
 *     ≤760px hides the section header (title/desc/actions) and grows the body to ~full viewport; wider
 *     bubbles (85%), tighter message/composer padding, and the "Reply with AI" pill collapses to its ✨
 *     icon. Thread header id-block flexes so action buttons align right.
 *   v1.3.0 -- 2026-07-17 -- Reply-to quotes (`.inbox-bubble-quote`, `.inbox-replybar`, `.inbox-row--flash`)
 *     + mobile keyboard: ≤760px height subtracts --inbox-kb (visualViewport keyboard inset set by the tab)
 *     and the stale `.inbox-msgs{max-height:50vh}` cap from the pre-single-pane stacked layout is removed.
 *     Bubble hover actions float as a bordered pill above the bubble's corner instead of over the text.
 *   v1.3.1 -- 2026-07-17 -- Composer file chips align a ✕ remove button (inline-flex + gap).
 *   v1.2.0 -- 2026-07-17 -- Mobile single-pane: ≤760px shows one pane at a time (list, or an open
 *     thread/composer full-width with a ← Back button) instead of a list stacked above a squeezed
 *     thread. Adds `.inbox-back` + `.inbox-body--panel` rules; desktop two-pane unchanged.
 *   v1.1.0 -- 2026-06-16 -- Full messenger redesign (avatars, bubbles, ticks, date dividers, sticky composer).
 *   v1.0.0 -- 2026-06-16 -- Initial creation for user-to-user messaging (layer 5).
 *   v1.11.0 -- 2026-08-08 -- The message bubble's copy action is a shared <CopyButton>, so .inbox-bubble-act.copied
 *       joins --on: the component stamps `copied` itself.
 */

.inbox { display: flex; flex-direction: column; gap: 14px; }

.inbox-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* Two-pane messenger with its own internal scroll. */
.inbox-body {
  display: grid;
  grid-template-columns: minmax(260px, 340px) 1fr;
  height: calc(100vh - 300px);
  min-height: 480px;
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--card-bg);
}
/* mobile-only back button (single-pane switching); hidden on the desktop two-pane layout */
.inbox-back {
  display: none;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 11px 12px;
  border: 0;
  border-bottom: 1px solid var(--border-subtle);
  background: var(--card-bg);
  color: var(--accent);
  font-weight: 600;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}

@media (max-width: 760px) {
  /* single-pane: one column, tall enough to read a thread; the open pane fills it. */
  .inbox-body { grid-template-columns: 1fr; height: calc(100dvh - 168px); min-height: 240px; }
  /* no panel open → show the list full-height, hide the idle placeholder */
  .inbox-body:not(.inbox-body--panel) .inbox-panel { display: none; }
  .inbox-body:not(.inbox-body--panel) .inbox-list { height: 100%; }
  /* a panel is open → hide the list, reveal the back button, let the panel own the screen */
  .inbox-body--panel { grid-template-rows: auto minmax(0, 1fr); }
  .inbox-body--panel .inbox-list { display: none; }
  .inbox-body--panel .inbox-back { display: inline-flex; }

  /* FULL-SCREEN mobile chat: when a thread/compose panel is open, lift the whole messenger OUT of the
     profile shell and pin it over the ENTIRE viewport — the app bar, ☰ Menu, bell, Logout pill and the
     "Messages" breadcrumb all live in the shell above and are simply covered. ← Back closes the panel
     (mode → 'idle'), which drops `.inbox--panel` and reveals the app + menus again, exactly as before.
     z 1000 sits above the app nav but below the inbox's own 1200 modals (mdviewer / AI popover). Fixed
     inset:0 is the same pattern those modals already use, so no transformed-ancestor surprises. */
  .inbox--panel { position: fixed; inset: 0; z-index: 1000; gap: 0; margin: 0; background: var(--bg, var(--card-bg)); }
  /* Lock the shell behind the full-screen chat so it can't scroll under it (and drop its scrollbar so the
     overlay is truly edge-to-edge). Also hide the app's sticky top nav — it lives in a HIGHER stacking
     context than the profile subtree, so the overlay's z-index can't cover it; the chat has its own ←
     Back, and closing the thread (mode→idle) drops `.inbox--panel` and the nav returns. :has on body is
     supported by every browser that ships the modern viewport units this layout already needs. */
  body:has(.inbox--panel) { overflow: hidden; }
  body:has(.inbox--panel) .topnav { display: none; }
  .inbox--panel .inbox-head { display: none; }
  /* --inbox-avail = measured visual-viewport height (set by the tab's useMobileComposerKeyboard). With the
     viewport meta's interactive-widget=resizes-content, 100dvh already tracks the keyboard, so it's the
     fallback; either way the composer sits right on the keyboard with the thread filling the rest. */
  .inbox--panel .inbox-body { height: var(--inbox-avail, 100dvh); border: none; border-radius: 0; }
  /* Home-indicator / gesture-bar clearance under the composer. */
  .inbox--panel .inbox-composer { padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }

  /* Use the narrow screen: wider bubbles, tighter message padding, a compact thread header. */
  .inbox-msgs { padding: 12px 10px; }
  .inbox-bubble { max-width: 85%; }
  .inbox-thread-head { padding: 10px 12px; gap: 8px; }
  .inbox-composer { padding: 8px 10px; }
  .inbox-compose-fields { padding: 10px 10px 0; }
  /* Collapse the "Reply with AI" and "Listen" buttons to just their icon so they never crowd the header. */
  .inbox-ai-btn .inbox-ai-btn-label { display: none; }
  .inbox-speak-btn .inbox-ai-btn-label { display: none; }

  /* Thread header: on a phone the action buttons eat the row, so a long subject would wrap inside the
     leftover ~100px id column and grow the header to half the screen. Flatten the id column into the
     header row (display:contents), let the header wrap, and send the subject / via / GHII lines to
     their own full-width rows under the avatar+name+buttons row — subject clamped to 2 lines. */
  .inbox-thread-head { flex-wrap: wrap; row-gap: 2px; }
  .inbox-thread-head .inbox-thread-id { display: contents; }
  .inbox-thread-head .inbox-name { flex: 1 1 0; min-width: 0; }
  .inbox-thread-head .inbox-thread-subject,
  .inbox-thread-head .inbox-thread-via,
  .inbox-thread-head .inbox-sub { order: 1; flex: 0 0 100%; min-width: 0; margin-top: 0; }
  .inbox-thread-head .inbox-thread-subject {
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* ── Avatars ── */
.inbox-avatar {
  display: inline-flex;
  flex: none;
  border-radius: var(--radius-full);
  overflow: hidden;
  background: var(--card-bg-alt);
}
.inbox-avatar svg { width: 100%; height: 100%; }

/* ── Left list ── */
.inbox-list {
  border-right: 1px solid var(--border-subtle);
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
@media (max-width: 760px) { .inbox-list { border-right: none; } }

.inbox-list-section {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  padding: 10px 6px 4px;
}
.inbox-count {
  background: var(--accent);
  color: #fff;
  border-radius: var(--radius-full);
  font-size: 10px;
  padding: 1px 6px;
}
.inbox-empty-sm { color: var(--text-dim); font-size: 13px; padding: 6px; }

/* Request cards (first-contact gate). */
.inbox-request {
  border: 1px solid var(--accent-border);
  border-radius: var(--radius-sm);
  padding: 10px;
  background: var(--accent-subtle);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.inbox-request-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.inbox-request-id { min-width: 0; }
.inbox-request-preview {
  color: var(--text-dim);
  font-size: 13px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.inbox-request-actions { display: flex; gap: 8px; }

.inbox-name { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.inbox-sub { font-size: 11px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Conversation rows. */
.inbox-conv {
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  padding: 9px 8px;
  cursor: pointer;
  width: 100%;
}
.inbox-conv:hover { background: var(--card-bg-alt); }
.inbox-conv--active { background: var(--accent-subtle); }

/* A person group: header (the human) + their threads (human + agents) nested + indented beneath. */
.inbox-conv-group { margin-bottom: 2px; }
.inbox-conv-group-head {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px 2px; font-weight: 600;
}
.inbox-conv-group-head .inbox-name { flex: 1; min-width: 0; }
.inbox-conv--nested { padding-left: 18px; }
.inbox-conv--nested .inbox-name { font-weight: 400; }
.inbox-conv-subico {
  width: 28px; flex: none; text-align: center; font-size: 15px; opacity: 0.8;
}
/* Subject thread chips (conversation list + thread header). */
.inbox-conv-subject {
  flex: none; max-width: 60%; font-size: 11px; color: var(--accent);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.inbox-thread-subject { font-size: 12px; color: var(--accent); margin-top: 1px; }
/* "via <agent>" — an aggregated conversation one of the owner's agents sent (read-only). */
.inbox-via-chip {
  flex: none; font-size: 10.5px; padding: 1px 6px; border-radius: 999px;
  background: var(--bg-dim); color: var(--text-dim); border: 1px solid var(--border); white-space: nowrap;
}
.inbox-thread-via { font-size: 12px; color: var(--text-dim); margin-top: 1px; }
.inbox-conv-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.inbox-conv-line1, .inbox-conv-line2 { display: flex; align-items: center; gap: 6px; }
.inbox-conv-line1 .inbox-name { flex: 1; }
.inbox-conv-time { font-size: 11px; color: var(--text-dim); flex: none; }
.inbox-conv-preview {
  flex: 1;
  min-width: 0;
  color: var(--text-dim);
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.inbox-conv-badge {
  flex: none;
  background: var(--accent);
  color: #fff;
  border-radius: var(--radius-full);
  font-size: 11px;
  min-width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 5px;
}

/* ── Right pane ── */
/* min-height:0 lets this grid item respect the fixed .inbox-body height instead of growing to fit a tall
   thread (grid/flex items default to min-height:auto = content size). */
.inbox-panel { display: flex; flex-direction: column; min-width: 0; min-height: 0; height: 100%; }
.inbox-panel--empty { align-items: center; justify-content: center; }

.inbox-empty { text-align: center; color: var(--text-dim); display: flex; flex-direction: column; align-items: center; gap: 8px; }
.inbox-empty-ico { font-size: 40px; opacity: 0.7; }

.inbox-thread-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-subtle);
  flex: none;
}
.inbox-thread-id { min-width: 0; flex: 1; }
/* The "Reply with AI" pill in the thread header stays on one line (icon + label). */
.inbox-ai-btn { flex: none; white-space: nowrap; }

/* Message scroll area. */
.inbox-msgs {
  flex: 1;
  min-height: 0;            /* required so the flex child scrolls instead of growing past the composer */
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--bg, transparent);
}

/* "Show full history (N messages)" pill at the top of a thread showing only its newest page. */
.inbox-thread-older { text-align: center; padding: 2px 0 6px; }

/* Date divider. */
.inbox-day { text-align: center; margin: 8px 0; }
.inbox-day span {
  font-size: 11px;
  color: var(--text-dim);
  background: var(--card-bg-alt);
  padding: 3px 10px;
  border-radius: var(--radius-full);
}

/* Message rows + bubbles. */
.inbox-row { display: flex; align-items: flex-end; gap: 8px; max-width: 100%; }
.inbox-row--mine { justify-content: flex-end; }
.inbox-row--theirs { justify-content: flex-start; }

.inbox-bubble {
  max-width: 72%;
  padding: 8px 12px;
  border: 1px solid var(--card-border);
  border-radius: 16px;
}
.inbox-bubble--theirs { background: var(--card-bg-alt); border-bottom-left-radius: 5px; }
.inbox-bubble--mine { background: var(--accent-subtle); border-color: var(--accent-border); border-bottom-right-radius: 5px; }
.inbox-bubble-body { font-size: 14px; line-height: 1.45; word-break: break-word; }
.inbox-bubble-body .md-body > :first-child { margin-top: 0; }
.inbox-bubble-body .md-body > :last-child { margin-bottom: 0; }
.inbox-bubble-body img { max-width: 100%; border-radius: var(--radius-xs); margin-top: 6px; }

/* Reply-to quote at the top of a bubble — click jumps to (and flashes) the quoted original. */
.inbox-bubble-quote {
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: none; border-left: 3px solid var(--accent);
  border-radius: var(--radius-xs);
  background: var(--bg-dim);
  padding: 5px 9px; margin-bottom: 6px;
  font: inherit; color: inherit;
}
.inbox-quote-name { display: block; font-size: 11px; font-weight: 600; color: var(--accent); }
.inbox-quote-text {
  font-size: 12px; color: var(--text-dim);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.inbox-row--flash .inbox-bubble {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-subtle);
  transition: box-shadow 0.25s ease, border-color 0.25s ease;
}

.inbox-bubble-meta {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  margin-top: 3px;
  font-size: 10px;
  color: var(--text-dim);
}
.inbox-tick { font-size: 11px; }
.inbox-tick--read { color: var(--accent); }
.inbox-tick--err { color: var(--danger); }

/* Attachment chips. */
.inbox-attach-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.inbox-attach-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 220px;
  font-size: 12px;
  padding: 4px 9px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--card-bg);
  text-decoration: none;
  color: inherit;
}
.inbox-attach-chip--pending { opacity: 0.55; }
.inbox-attach-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.inbox-attach-pending { color: var(--text-dim); font-style: italic; }

/* The chip's main affordance (link or button) opens/views the file; the download button sits beside it. */
.inbox-attach-open {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  background: none; border: none; padding: 0; margin: 0; cursor: pointer;
  font: inherit; color: inherit; text-decoration: none;
}
.inbox-attach-open:hover .inbox-attach-name { text-decoration: underline; }
.inbox-attach-dl {
  flex-shrink: 0; text-decoration: none; color: var(--text-dim);
  font-size: 13px; line-height: 1; padding: 2px 4px; border-radius: var(--radius-xs);
}
.inbox-attach-dl:hover { color: var(--text); background: var(--bg-dim); }

/* Image attachment: thumbnail + caption row (name + download). */
.inbox-attach-item {
  display: inline-flex; flex-direction: column; gap: 4px; max-width: 200px;
}
.inbox-attach-thumb-link { display: block; line-height: 0; }
.inbox-attach-thumb {
  max-width: 200px; max-height: 160px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); object-fit: cover; cursor: zoom-in;
}
.inbox-attach-cap { display: flex; align-items: center; gap: 6px; font-size: 12px; max-width: 200px; }
.inbox-attach-cap .inbox-attach-name { flex: 1; min-width: 0; color: var(--text-dim); }

/* In-app markdown viewer overlay. */
.inbox-mdviewer-overlay {
  position: fixed; inset: 0; z-index: 1200; background: rgba(0, 0, 0, 0.6);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.inbox-mdviewer {
  display: flex; flex-direction: column; width: min(860px, 100%); max-height: 88vh;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden;
}
.inbox-mdviewer-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--surface);
}
.inbox-mdviewer-title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.inbox-mdviewer-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.inbox-mdviewer-body { padding: 18px 22px; overflow: auto; }

/* ── Reply with AI popover (TARGET-031) ── */
.inbox-ai-overlay {
  position: fixed; inset: 0; z-index: 1200; background: rgba(0, 0, 0, 0.6);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.inbox-ai-modal {
  display: flex; flex-direction: column; gap: 10px; width: min(720px, 100%); max-height: 88vh;
  padding: 16px 18px; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-md); overflow: hidden;
}
.inbox-ai-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.inbox-ai-title { font-weight: 600; }
.inbox-ai-modes { display: flex; gap: 6px; }
.inbox-ai-mode {
  border: 1px solid var(--border); background: var(--surface); cursor: pointer;
  padding: 5px 12px; border-radius: var(--radius-sm); font-size: 13px; color: var(--text-dim);
}
.inbox-ai-mode:hover { color: var(--text); }
.inbox-ai-mode--on { background: var(--accent-subtle); border-color: var(--accent-border); color: var(--accent); }
.inbox-ai-hint { font-size: 12.5px; color: var(--text-dim); line-height: 1.4; }
.inbox-ai-text {
  width: 100%; resize: vertical; font-family: var(--font-mono, monospace); font-size: 12.5px;
  line-height: 1.45; padding: 10px 12px; background: var(--bg-dim); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.inbox-ai-actions { display: flex; justify-content: flex-end; }

/* ── Composer ── */
/* "Replying to …" bar shown above the composer while a quoted reply (↩) is being written. */
.inbox-replybar {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  border-top: 1px solid var(--border-subtle);
  background: var(--card-bg-alt);
}
.inbox-replybar-main {
  flex: 1; min-width: 0; text-align: left; cursor: pointer;
  border: none; border-left: 3px solid var(--accent);
  background: transparent; padding: 2px 0 2px 8px;
  font: inherit; color: inherit;
}
.inbox-replybar-label { display: block; font-size: 11px; font-weight: 600; color: var(--accent); }
.inbox-replybar-text {
  display: block; font-size: 12px; color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.inbox-compose-fields { padding: 12px 12px 0; }
.inbox-composer {
  border-top: 1px solid var(--border-subtle);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: none;
}
.inbox-input,
.inbox-textarea {
  width: 100%;
  box-sizing: border-box;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  font: inherit;
  color: inherit;
}
.inbox-textarea { resize: vertical; min-height: 42px; }
/* Mobile chat input: a single auto-growing line (JS sets height up to a cap), no manual resize handle. */
.inbox-textarea--chat { resize: none; min-height: 40px; max-height: 132px; line-height: 1.4; overflow-y: auto; }
.inbox-input:focus, .inbox-textarea:focus { outline: none; border-color: var(--border-focus); }

/* Toast UI editor host + markdown fallback. */
.inbox-editor { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.inbox-editor .toastui-editor-defaultUI { border: none; }
.inbox-md-fallback { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 760px) { .inbox-md-fallback { grid-template-columns: 1fr; } }
.inbox-md-preview {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  overflow: auto;
  max-height: 160px;
  font-size: 14px;
}

/* Expanded composer (the ⤢ toggle): grow the fallback/simple textarea + preview to ~60vh so a long or
   formatted draft is fully visible. The rich Toast UI editor is resized in JS via setHeight instead. */
.inbox-composer--tall .inbox-textarea { min-height: 60vh; }
.inbox-composer--tall .inbox-textarea--chat { max-height: 60vh; }
.inbox-composer--tall .inbox-md-preview { max-height: 60vh; }

.inbox-composer-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.inbox-bar-left { display: flex; align-items: center; gap: 8px; }
.inbox-attach-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 16px;
}
.inbox-attach-btn:hover { border-color: var(--accent); }
.inbox-file-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.inbox-file-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; color: var(--text-dim); background: var(--card-bg-alt);
  padding: 3px 4px 3px 8px; border-radius: var(--radius-full);
}

/* ── Tracked Responses: per-message actions, approval banner, track modal ── */
.inbox-bubble { position: relative; }
/* Hover actions float as a pill ABOVE the bubble's top-right corner (own background + border) so the
   icons never sit on top of the message text. */
.inbox-bubble-actions {
  position: absolute; top: -13px; right: 8px; z-index: 1;
  display: flex; gap: 2px; opacity: 0; transition: opacity .12s ease;
  pointer-events: none;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 2px 6px;
  box-shadow: var(--shadow-md);
}
.inbox-row:hover .inbox-bubble-actions { opacity: 1; pointer-events: auto; }
/* Touch devices have no hover — the per-message actions (↩ reply, ⧉ copy, ⭐, 🔗, 📓, ✨) would be unreachable.
   Reveal them permanently there so a phone user can actually reply to / act on a message by tapping. */
@media (hover: none) {
  .inbox-bubble-actions { opacity: 1; pointer-events: auto; }
}
.inbox-bubble-act {
  border: none; background: transparent; cursor: pointer;
  font-size: 13px; line-height: 1; padding: 2px 3px; border-radius: var(--radius-xs);
  color: var(--text-dim);
}
.inbox-bubble-act:hover { background: var(--card-bg-alt); color: var(--accent); }
/* `copied` is <CopyButton>'s confirmed state (it stamps the class itself); the bubble's copy
   action is a CopyButton, so it lights up the same way --on does for the other toggles. */
.inbox-bubble-act--on,
.inbox-bubble-act.copied { color: var(--accent); }

.inbox-track-banner {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; margin: 6px 0;
  background: var(--accent-subtle); border: 1px solid var(--accent-border);
  border-radius: var(--radius-sm); font-size: 13px;
}
.inbox-track-banner-txt { flex: 1; }

/* A "reply ready" suggested-reply shown as a dashed draft bubble with approve/reject. */
.inbox-bubble--draft {
  border: 1px dashed var(--accent-border) !important;
  background: var(--accent-subtle) !important;
}
.inbox-draft-label { font-size: 11px; font-weight: 600; color: var(--accent); margin-bottom: 4px; }
.inbox-draft-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin-top: 8px; }

.inbox-track-form { display: flex; flex-direction: column; gap: 10px; }
.inbox-track-hint { color: var(--text-dim); font-size: 13px; margin: 0; }
.inbox-form-row { display: flex; flex-direction: column; gap: 4px; }
.inbox-form-label { font-size: 12px; color: var(--text-dim); }
.inbox-form-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.inbox-track-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; align-items: center; }
.inbox-track-classify { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 32px 16px; text-align: center; }
.inbox-track-classify-step { font-weight: 600; }
.inbox-track-classify-sub { font-size: 13px; color: var(--text-dim); }
.inbox-track-content { resize: vertical; font-family: inherit; }

/* Spinner shown on the create button while a tracked response is being created. */
.inbox-spinner {
  display: inline-block; width: 12px; height: 12px; vertical-align: -1px;
  border: 2px solid var(--border); border-top-color: var(--accent);
  border-radius: var(--radius-full); animation: inbox-spin 0.7s linear infinite;
}
@keyframes inbox-spin { to { transform: rotate(360deg); } }

/* Per-message "is tracked" badge + the tracked-responses dashboard. */
.inbox-head-actions { display: flex; align-items: center; gap: 8px; }
.btn-outline--active { border-color: var(--accent); color: var(--accent); }
.inbox-track-badge {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11px; padding: 1px 7px; border-radius: var(--radius-full);
  border: 1px solid var(--border); color: var(--text-dim); white-space: nowrap;
}
.inbox-track-badge--watch { border-color: var(--accent-border); color: var(--accent); }
.inbox-track-badge--ready { border-color: var(--accent-border); color: var(--accent); background: var(--accent-subtle); }
.inbox-track-badge--done  { border-color: var(--border); color: var(--text-dim); }
.inbox-track-badge--err   { border-color: var(--danger); color: var(--danger); }

/* The model an agent named for a message it wrote. Deliberately quiet: it belongs with the timestamp
   as a fact about the message, not as a status the reader has to act on. */
.inbox-model-badge {
  font-size: 11px; padding: 1px 6px; border-radius: var(--radius-full);
  border: 1px dashed var(--border); color: var(--text-dim); white-space: nowrap;
}

.inbox-tracked-list { display: flex; flex-direction: column; gap: 8px; padding: 12px; overflow-y: auto; }
.inbox-tracked-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--card-border); border-radius: var(--radius-sm);
  background: var(--card-bg);
}
.inbox-tracked-main { min-width: 0; flex: 1; }
.inbox-tracked-line1 { display: flex; align-items: center; gap: 8px; }
.inbox-tracked-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inbox-tracked-sub { font-size: 12px; color: var(--text-dim); margin-top: 3px; }
.inbox-tracked-sub code { font-size: 11px; background: var(--card-bg-alt); padding: 1px 5px; border-radius: var(--radius-xs); }
.inbox-tracked-err { color: var(--danger); }
.inbox-tracked-actions { display: flex; gap: 6px; flex-shrink: 0; }
.inbox-tracked-done { color: var(--text-dim); font-size: 12px; padding: 8px 6px 2px; border-top: 1px solid var(--border); margin-top: 4px; }

/* ── Interactive messages (federated AskUserQuestion): the inline question form ── */
.inbox-iform {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.inbox-iform-q { display: flex; flex-direction: column; gap: 6px; }
.inbox-iform-chip {
  align-self: flex-start;
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-subtle);
  border: 1px solid var(--accent-border);
  border-radius: var(--radius-full);
  padding: 1px 8px;
}
.inbox-iform-prompt { font-weight: 600; font-size: 13px; }
.inbox-iform-req { color: var(--accent); }
.inbox-iform-opts { display: flex; flex-direction: column; gap: 6px; }
.inbox-iform-opt {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  cursor: pointer;
  font-size: 13px;
  transition: border-color 0.12s, background 0.12s;
}
.inbox-iform-opt:hover { border-color: var(--accent-border); }
.inbox-iform-opt--on { border-color: var(--accent); background: var(--accent-subtle); }
.inbox-iform-opt input { accent-color: var(--accent); flex-shrink: 0; }
.inbox-iform-opt-label { min-width: 0; }
.inbox-iform-other {
  margin-top: 2px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-size: 13px;
}
.inbox-iform-other:focus { outline: none; border-color: var(--accent); }
.inbox-iform-submit { align-self: flex-start; margin-top: 2px; }

/* Read-only summary once the question has been answered. */
.inbox-iform--done { gap: 8px; }
.inbox-iform-answered { font-size: 13px; color: var(--text-dim); }

/* ── Broadcast / send-to-many compose ── */
.inbox-bc-mode { display: flex; gap: 8px; flex-wrap: wrap; }
.inbox-bc-modeopt {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card-bg); cursor: pointer; font-size: 13px;
}
.inbox-bc-modeopt input { accent-color: var(--accent); }
.inbox-bc-modeopt--on { border-color: var(--accent); background: var(--accent-subtle); }
.inbox-bc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.inbox-bc-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 6px 3px 10px; border: 1px solid var(--accent-border); border-radius: var(--radius-full);
  background: var(--accent-subtle); font-size: 12px; max-width: 100%;
}
.inbox-bc-chip-x {
  border: none; background: transparent; color: var(--text-dim); cursor: pointer;
  font-size: 12px; line-height: 1; padding: 2px 4px; border-radius: var(--radius-full);
}
.inbox-bc-chip-x:hover { color: var(--danger); background: var(--card-bg); }
.inbox-bc-add { display: flex; gap: 8px; }
.inbox-bc-add .inbox-input { flex: 1; }
/* Operator audience select (all node / all federation users). */
.inbox-bc-audience--on { border-color: var(--accent); background: var(--accent-subtle); }

/* Announcement note shown in place of the reply composer (read-only thread). */
.inbox-announce-note {
  border-top: 1px solid var(--border-subtle);
  padding: 12px 16px; color: var(--text-dim); font-size: 13px; text-align: center;
}

/* ── Poll builder (compose a poll broadcast) ── */
.inbox-poll-builder { display: flex; flex-direction: column; gap: 12px; }
.inbox-poll-q {
  display: flex; flex-direction: column; gap: 8px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px; background: var(--card-bg);
}
.inbox-poll-q-head { display: flex; align-items: center; gap: 8px; }
.inbox-poll-q-head .inbox-input { flex: 1; }
.inbox-poll-q-n { font-weight: 600; color: var(--text-dim); }
.inbox-poll-opts { display: flex; flex-direction: column; gap: 6px; padding-left: 12px; }
.inbox-poll-opt { display: flex; align-items: center; gap: 6px; }
.inbox-poll-opt .inbox-input { flex: 1; }
.inbox-poll-flags { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: var(--text-dim); }
.inbox-poll-flags label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.inbox-poll-flags input { accent-color: var(--accent); }

/* ── Broadcast / poll results ── */
.inbox-results-summary { font-size: 13px; color: var(--text-dim); padding-bottom: 8px; border-bottom: 1px solid var(--border-subtle); }
.inbox-results-q { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; }
.inbox-results-prompt { font-weight: 600; font-size: 14px; }
.inbox-results-bar { display: flex; flex-direction: column; gap: 3px; }
.inbox-results-bar-label { display: flex; justify-content: space-between; font-size: 13px; }
.inbox-results-bar-track { height: 8px; border-radius: var(--radius-full); background: var(--card-bg-alt); overflow: hidden; }
.inbox-results-bar-fill { height: 100%; width: var(--w, 0%); background: var(--accent); border-radius: var(--radius-full); transition: width 0.3s; }
.inbox-results-others { font-size: 12px; color: var(--text-dim); }
.inbox-results-reclist { display: flex; flex-direction: column; gap: 4px; padding-top: 8px; }
.inbox-results-rec { display: flex; justify-content: space-between; font-size: 13px; color: var(--text-dim); }

/* ── Agent capabilities in chat: command chips + fill-in form (Phase A) ── */
.inbox-cmdbar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  padding: 8px 12px; border-top: 1px solid var(--border-subtle);
}
.inbox-cmdbar-label { font-size: 12px; color: var(--text-dim); margin-right: 2px; }
.inbox-cmd-chip {
  border: 1px solid var(--accent-border); background: var(--accent-subtle); color: var(--text);
  font-size: 12px; padding: 4px 10px; border-radius: var(--radius-full); cursor: pointer;
}
.inbox-cmd-chip:hover { border-color: var(--accent); }
.inbox-cmdfill {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 12px; border-top: 1px solid var(--border-subtle); background: var(--card-bg-alt);
}
.inbox-cmdfill-head { display: flex; align-items: center; justify-content: space-between; font-weight: 600; font-size: 13px; }
.inbox-cmdfill-desc { font-size: 12px; color: var(--text-dim); }
.inbox-cmdfill-field { display: flex; flex-direction: column; gap: 3px; }
.inbox-cmdfill-pname { font-size: 12px; color: var(--text-dim); }
.inbox-cmdfill-go { align-self: flex-start; }

/* ── Agent schedule panel (Phase B — own agents only) ── */
.inbox-sched-btn { margin-left: auto; }
.inbox-sched-btn--on { background: var(--accent-subtle); border-color: var(--accent); }
.inbox-sched {
  display: flex; flex-direction: column; gap: 10px;
  padding: 10px 12px; border-top: 1px solid var(--border-subtle); background: var(--card-bg-alt);
}
.inbox-sched-head { display: flex; align-items: center; justify-content: space-between; font-weight: 600; font-size: 13px; }
.inbox-sched-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.inbox-sched-item { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; }
.inbox-sched-name { color: var(--text); }
.inbox-sched-cron { color: var(--text-dim); font-family: var(--font-mono, monospace); font-size: 12px; }
.inbox-sched-new { display: flex; flex-direction: column; gap: 6px; }
.inbox-sched-new .btn-primary { align-self: flex-start; }
.inbox-sched-desc { min-height: 38px; resize: vertical; }

/* ── Link previews (unfurl cards) — a rich card under a pasted link in a message bubble. The card is a
 *    clickable row (thumbnail · site · title · description) plus a ✕ to hide it. Theme tokens only. ── */
.inbox-linkcards { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.inbox-linkcard {
  position: relative; display: flex; align-items: stretch;
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  background: var(--card-bg-alt); overflow: hidden;
}
.inbox-linkcard-main {
  display: flex; align-items: stretch; gap: 10px; min-width: 0; flex: 1;
  padding: 8px 10px; text-decoration: none; color: inherit;
}
.inbox-linkcard-main:hover { background: var(--surface-hover); }
.inbox-linkcard-thumb { flex: none; width: 72px; display: flex; align-items: center; justify-content: center; }
.inbox-linkcard-thumb img {
  width: 72px; height: 72px; object-fit: cover; border-radius: var(--radius-xs); display: block; margin: 0;
}
.inbox-linkcard-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; justify-content: center; }
.inbox-linkcard-site { font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .02em; }
.inbox-linkcard-title {
  font-size: 13px; font-weight: 600; color: var(--text); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.inbox-linkcard-desc {
  font-size: 12px; color: var(--text-dim); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.inbox-linkcard-x {
  flex: none; align-self: flex-start; border: none; background: transparent; cursor: pointer;
  color: var(--text-dim); font-size: 12px; line-height: 1; padding: 6px 8px; border-radius: var(--radius-xs);
}
.inbox-linkcard-x:hover { color: var(--text); background: var(--surface-hover); }

/* Thread-head toggle: show/hide all link previews (persisted). --on marks the active state. */
.inbox-linkprev-toggle { flex: none; white-space: nowrap; }
.inbox-linkprev-toggle--on { background: var(--accent-subtle); border-color: var(--accent-border); color: var(--accent); }

/* ── Read aloud (Web Speech): thread-head Listen/Pause/Continue + ✕ stop. The per-bubble 🔊 reuses
   .inbox-bubble-act / --on, so it needs no rules of its own. --on marks a reading in progress. */
.inbox-speak-group { display: inline-flex; align-items: center; gap: 2px; flex: none; }
.inbox-speak-btn { flex: none; white-space: nowrap; display: inline-flex; align-items: center; gap: 5px; }
.inbox-speak-btn--on { background: var(--accent-subtle); border-color: var(--accent-border); color: var(--accent); }
.inbox-speak-ico { font-size: 13px; line-height: 1; }
.inbox-speak-stop { flex: none; padding-inline: 8px; }

/* ── Voice messages (2026-08-01) ──
   A voice message plays where it sits. It used to fall into the generic attachment chip and open in
   a new browser tab, which is a download, not a conversation. */
.inbox-attach-audio { display: flex; flex-direction: column; gap: 4px; width: 100%; max-width: 380px; }
.inbox-audio { width: 100%; height: 34px; }
.inbox-audio--chip { max-width: 190px; height: 30px; }
.inbox-audio-dur { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.inbox-file-chip--voice { align-items: center; gap: 6px; }
.inbox-chip-voice { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; }

/* Transcript: collapsed by default so a thread of voice messages stays scannable, and the label
   always says who produced the text — the sender's own transcript and one this reader paid for are
   not the same claim. */
.inbox-transcript { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 2px; }
.inbox-transcript-toggle {
  background: none; border: none; cursor: pointer; padding: 2px 0;
  font-size: 11px; color: var(--text-dim); display: inline-flex; align-items: center; gap: 6px;
}
.inbox-transcript-toggle:hover { color: var(--text); }
.inbox-transcript-src { color: var(--text-muted); }
.inbox-transcript-text {
  flex-basis: 100%; font-size: 13px; white-space: pre-wrap; word-break: break-word;
  padding: 8px; border-radius: var(--radius, 8px);
  background: var(--bg-dim); border: 1px solid var(--border);
}
.inbox-transcript-btn {
  background: none; border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  font-size: 11px; padding: 2px 10px; color: var(--text-dim);
}
.inbox-transcript-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.inbox-transcript-btn:disabled { opacity: .6; cursor: progress; }
.inbox-transcript-hint { font-size: 11px; color: var(--text-muted); }
.inbox-transcript-err { font-size: 11px; color: var(--danger); }

@media (max-width: 520px) {
  /* Full width on a phone: a 380px cap would leave the player floating in a narrow column. */
  .inbox-attach-audio { max-width: 100%; }
  .inbox-audio--chip { max-width: 100%; }
}
