/* Vici shared messages - the conversation row and its parts.
   The modal is the master copy: rules moved verbatim, in source order, from
   dock/panel/panel.css; loaded after shared-tokens.css and before the host's
   own sheet (panel.css here, styles.css on the web under /panel/).
   The row, its meta line and time, lifecycle badges, the body and the
   person's bubble, the row's icon actions. The list container
   (.conversation-messages, its scrolling and centring) is the host's.
   Shared files (dock/HANDOFF.md, "Shared files"): they hold exactly what the
   modal ships; a host need is a selector in the host's own sheet; no
   transition, animation, filter or blur, and no CSS the board's WebKit has
   not already shipped; every rule renders right with no host-toggled class.
   An edit here is a dock landing (live first) that also deploys the web. */

.conversation-message {
  width: 86%;
  display: flex;
  flex-direction: column;
  gap: 5px;
  align-self: flex-start;
}
.conversation-message.human { align-self: flex-end; margin-left: auto; }
.conversation-message-meta {
  display: flex;
  gap: 7px;
  align-items: baseline;
  color: var(--muted);
  font-size: 10.5px;
}
.conversation-message.human > .conversation-message-meta { justify-content: flex-end; }
/* Timestamps are hover-only (KAN-334): the strip keeps its place so
   nothing jumps, and the probe's kb-hover is the glass twin of :hover.
   Lifecycle badges stay visible — they are state, not bookkeeping. */
/* W3 hover: the row's hover state is two opacity changes (the stamp, the action bar). On their own
   compositing layers those are composite-only changes; without them WebKit repainted the row's
   tiles on every crossing (22-31 ms of the crossing's 60 on the board). */
.conversation-message-meta time { opacity: 0; }
.conversation-message:hover time,
.conversation-message.kb-hover time { opacity: 1; }
/* Claude-style stamps: the row's hover shows "10 min ago"; hovering
   the stamp itself swaps in the account-zone moment. */
.conversation-message-meta time .t-abs { display: none; }
.conversation-message-meta time:hover .t-rel,
.conversation-message-meta time.kb-hover .t-rel { display: none; }
.conversation-message-meta time:hover .t-abs,
.conversation-message-meta time.kb-hover .t-abs { display: inline; }
.conversation-message-lifecycle {
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  text-transform: lowercase;
}
/* no streaming badge — the thread mark is that notice */
.conversation-message.queued .conversation-message-lifecycle {
  color: var(--accent-link);
  border-color: var(--accent-link);
}
.conversation-message.failed .conversation-message-lifecycle {
  color: var(--danger);
  border-color: var(--danger);
}
/* Cancellation is a quiet receipt under the message, never a full-width
   lifecycle pill. The same still note belongs to both the modal and web. */
.conversation-cancelled {
  display: flex;
  align-items: center;
  align-self: flex-start;
  gap: 7px;
  padding: 3px 2px;
  color: var(--muted);
  font-size: 12px;
  line-height: 18px;
}
.conversation-message.human > .conversation-cancelled { align-self: flex-end; }
.conversation-cancelled-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 14px;
  height: 14px;
  box-sizing: border-box;
  border: 1px solid currentColor;
  border-radius: 50%;
}
.conversation-cancelled-icon::before {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 1px;
  background: currentColor;
}
/* The reply sits on the panel itself — no bubble chrome around
 * Vici's words (Max 2026-08-25); the human's turn keeps its accent
 * bubble so the two voices still read apart. */
.conversation-message-body {
  padding: 2px 0;
  white-space: pre-wrap;
  overflow-wrap: break-word; /* break-word, not anywhere: the same wrap
                                for a token that overflows, without every
                                character weighed as a break (the pane's
                                layout is the switch's largest leg) */
  user-select: text;
  min-width: 0;              /* a wide code block scrolls/wraps inside,
                               never forces the bubble past the card */
}
.conversation-message.human > .conversation-message-body:not(.virtual-answer) {
  /* Short messages hug their words. Virtual documents keep a stable width
     as scrolling replaces the fragments currently mounted in the page. */
  align-self: flex-end;
  width: fit-content;
  max-width: 100%;
  box-sizing: border-box;
}
.conversation-message.human > .conversation-message-body {
  padding: 10px 13px;
  border: 1px solid var(--accent);
  border-radius: 13px 13px 4px 13px;
  background: var(--accent-soft);
}
/* Rendered assistant markdown: the module supplies paragraph structure,
 * so the plain-text pre-wrap must not double every newline. Human turns
 * keep pre-wrap — their words render verbatim. */
.conversation-message-body.markdown { white-space: normal; }
/* Per-message actions: icon row, Claude-style (no words — Max
   2026-08-28). A hover names each icon (.action-tooltip) and Copy
   answers with a check, never a toast (Max 2026-09-10).
   Hover-only (Max 2026-08-25): chrome on every message dirtied the
   chat. Space stays reserved so nothing jumps; the probe's kb-hover
   is the glass twin of :hover. */
.msg-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
  min-height: 24px;
  pointer-events: none;
}
/* At rest the bar's buttons are out of the layout (display: none): an
   opacity-0 bar was painted through a transparency layer per row per
   frame on the board's CPU rasterizer, a third of a switch's frame on
   short rows (fabric 2026-09-09-w16-drags.md), and its buttons a fifth
   of the rows' layout. The bar keeps its height so nothing jumps; the
   hover (and the probe's kb-hover twin) shows the buttons, the same
   reveal the admission already treats as a new control. */
.msg-actions > .msg-icon-btn { display: none; }
.conversation-message.human > .msg-actions { justify-content: flex-end; }
.conversation-message:hover .msg-actions,
.conversation-message.kb-hover .msg-actions { pointer-events: auto; }
.conversation-message:hover .msg-actions > .msg-icon-btn,
.conversation-message.kb-hover .msg-actions > .msg-icon-btn { display: grid; }
/* The reply you copied holds its icons after the pointer leaves, until
   another reply is copied (Max 2026-09-10) — one row at a time. */
.conversation-message.actions-held .msg-actions { pointer-events: auto; }
.conversation-message.actions-held .msg-actions > .msg-icon-btn { display: grid; }
.msg-icon-btn {
  appearance: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.msg-icon-btn:hover,
.msg-icon-btn.kb-hover {
  color: var(--text);
  background: var(--surface-2);
  border-color: var(--border);
}
.msg-icon-btn svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Awaiting reply: the same compact icon and secondary type as the
 * Pearl/Graphite controls. Only the 18px arc moves, on the shared clock. */
.conversation-message-body.thinking {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 23px;
}
.conversation-message-during { font-size: 11px; opacity: 0.7; margin-left: 6px; font-variant-numeric: tabular-nums; }
.copy-labeled { width:auto!important; display:inline-flex!important; align-items:center; gap:6px; padding:4px 6px!important; }
.copy-labeled .copy-label { display:inline; font-size:12px; }
.conversation-message { max-width:720px; }
.conversation-message-body { font-size:15px; line-height:23px; }
.conversation-message.human > .conversation-message-body { background:var(--user-bubble); border:0; border-radius:10px; padding:10px 14px; }
:root:not([data-theme="dark"]) .conversation-message.human > .conversation-message-body {
  background: #E2EAF7;
  border: 1px solid #D3DEEF;
  border-radius: 18px 18px 6px 18px;
  padding: 11px 16px;
}
.conversation-message-meta { color:var(--muted); font-size:11.5px; }
/* The page sets .labeled on a bar that holds the worded Copy. Not :has(): the surface reuses
   geometry for paint-only changes only while every rule in the page's sheets is plain
   (surface.js decorationSelectorsSafe), and one :has() switches that off page-wide. */
.msg-actions.labeled { pointer-events:auto; min-height:32px; }
.copy-labeled { height:32px!important; color:var(--muted); }
