/* Chat workspace. Columns are separated by rules, not by gaps and cards. */

body { overflow: hidden; }

.shell {
  display: flex;
  flex-direction: column;
  height: 100vh;
  /* Mobile browsers count their collapsing toolbars out of dvh, so the composer
     stays on screen instead of sitting under the address bar. */
  height: 100dvh;
}

.workspace {
  display: grid;
  grid-template-columns: var(--col-side) minmax(0, 1fr) var(--col-aside);
  flex: 1;
  min-height: 0;
}

.col-side { border-right: var(--rule-width) solid var(--rule-strong); }
.col-activity { border-left: var(--rule-width) solid var(--rule-strong); }

/* The assistant block divides with a rule like the panels around it. */
.side > .assistant-card { border-bottom: var(--rule-width) solid var(--rule); }

/* ------------------------------------------------------------ assistant card */

.assistant-card {
  padding: var(--pad-panel);
  background: var(--paper);
}

/* Redesigned orb: larger, rounded, with subtle border */
.assistant-orb {
  width: 40px;
  height: 40px;
  margin: 0 auto var(--space-3);
  background: var(--paper-raised);
  border: 2px solid var(--rule-strong);
  border-radius: 50%;
  transition: all var(--duration) var(--ease);
  position: relative;
}

.assistant-orb::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 12px;
  height: 12px;
  background: var(--accent);
  border-radius: 50%;
  transition: all var(--duration) var(--ease);
}

.assistant-orb.thinking {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-wash);
}

.assistant-orb.thinking::before {
  width: 20px;
  height: 20px;
  animation: pulse-dot 1.5s ease-in-out infinite;
}

@keyframes pulse-dot {
  0%, 100% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }
  50% {
    transform: translate(-50%, -50%) scale(1.2);
    opacity: 0.8;
  }
}

.assistant-card h3 {
  margin: 0 0 var(--space-1);
  font-family: var(--font-ui);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  text-align: center;
  color: var(--ink);
}
.assistant-card p {
  margin: 0;
  font-family: var(--font-prose);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  text-align: center;
  color: var(--ink-muted);
}

/* --------------------------------------------------------------- graph list */

.graph-list { display: flex; flex-direction: column; }
.graph-group + .graph-group { margin-top: var(--space-3); }
.graph-group-label {
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: var(--space-1) 0;
}
.graph-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  font-size: var(--text-xs);
  color: var(--ink-muted);
  text-decoration: none;
  border-bottom: var(--rule-width) solid var(--rule);
  transition: color var(--duration) var(--ease);
}
.graph-group .graph-row:last-child { border-bottom: none; }
.graph-row:last-child { border-bottom: none; }
.graph-row:hover { color: var(--ink); }
.graph-swatch { width: var(--mark-swatch); height: var(--mark-swatch); flex: none; }
.graph-row .count { margin-left: auto; font-family: var(--font-ui); font-size: var(--text-2xs); color: var(--ink-faint); }
.graph-row.empty-graph { color: var(--ink-faint); }
.graph-row.empty-graph .graph-swatch { opacity: 0.4; }

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

.chat-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--paper);
  overflow: hidden;
}

.chat-ready-overlay {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
}

.chat-ready-overlay[hidden] {
  display: none;
}

.chat-ready-overlay .loading-content {
  gap: var(--space-6);
}

.chat-ready-overlay .loading-orb {
  width: 88px;
  height: 88px;
}

.chat-ready-overlay .loading-orb::after {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
}

.chat-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: var(--nav-height);
  padding: 0 var(--gutter);
  border-bottom: var(--rule-width) solid var(--rule);
  flex: none;
}

#private-chat,
#new-chat {
  border-color: var(--rule-strong);
}

#private-chat.active {
  color: var(--status-warn);
  border-color: var(--status-warn);
}

/* A column so a short conversation sits on the composer rather than leaving a
   field of empty paper between the two. */
.transcript {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: var(--space-4) var(--gutter) var(--space-2);
}
.transcript > :first-child { margin-top: auto; }

/* Each turn is a ruled record, not a floating bubble. */
.turn {
  display: flex;
  gap: var(--space-3);
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-4);
  border-bottom: var(--rule-width) solid var(--rule);
}
.turn:last-child { border-bottom: none; }

.avatar {
  width: var(--avatar-size);
  height: var(--avatar-size);
  flex: none;
  display: grid;
  place-items: center;
  font-family: var(--font-ui);
  font-size: var(--text-3xs);
  font-weight: var(--weight-medium);
  border-radius: var(--radius);
}
/* Assistant: monogram on accent with white text. User: initials in a hairline square. */
.avatar.ai { color: #ffffff; background: var(--accent); }
.avatar.me { color: var(--ink-muted); border: var(--rule-width) solid var(--rule-strong); }

.bubble { min-width: 0; flex: 1; }
.bubble .who {
  margin-bottom: var(--space-1);
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  font-weight: var(--weight-normal);
  letter-spacing: var(--tracking-none);
  color: var(--ink-faint);
}

/* Message body is the one place with real reading type. */
.bubble .body {
  font-family: var(--font-prose);
  font-size: var(--text-md);
  line-height: var(--leading-prose);
  color: var(--ink);
  max-width: var(--measure);
  overflow-wrap: break-word;
}
.bubble .body p { margin: 0 0 var(--space-2); }
.bubble .body p:last-child { margin-bottom: 0; }
.bubble .body ul, .bubble .body ol { margin: 0 0 var(--space-2); padding-left: var(--space-4); }
.bubble .body li { margin-bottom: var(--space-1); }
.bubble .body code {
  padding: 0 var(--space-1);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--ink);
  background: var(--paper-sunken);
  border-radius: var(--radius-sm);
}
.bubble .body pre {
  margin: 0 0 var(--space-2);
  padding: var(--space-2) var(--space-3);
  overflow-x: auto;
  background: var(--paper-sunken);
  border: var(--rule-width) solid var(--rule);
  border-radius: var(--radius);
}
.bubble .body pre code {
  background: none;
  padding: 0;
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
}
.bubble .body strong { font-weight: var(--weight-semibold); }
.bubble .body a { color: var(--accent); word-break: break-word; }
.bubble .body a:hover { color: var(--accent-strong); }

.bubble .body img.bubble-media {
  display: block;
  max-width: min(100%, 480px);
  height: auto;
  margin: var(--space-2) 0;
  border: var(--rule-width) solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-sunken);
}

.bubble-embed-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-width: min(100%, 480px);
  margin: var(--space-2) 0;
}

.bubble-embed {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  border: var(--rule-width) solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-sunken);
}

.bubble-embed-link {
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}

/* User turns read as quoted input: sunken well, square, no tail. */
.turn.user .bubble .body {
  padding: var(--space-2) var(--space-3);
  background: var(--paper-sunken);
  border-left: 2px solid var(--rule-strong);
}

/* Speech still being recognised: shown at once, but not yet the final wording. */
.turn.provisional .bubble .body { color: var(--ink-faint); }

.turn.blocked .bubble .body {
  padding: var(--space-2) var(--space-3);
  border-left: 2px solid var(--status-bad);
  background: var(--paper-sunken);
}

/* Activity tags inside an assistant turn. */
.trace { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: var(--space-2); }

/* Streaming caret: a hard block, terminal convention, no glow. */
.cursor-caret {
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 1px;
  vertical-align: text-bottom;
  background: var(--ink);
  animation: caret 1s step-end infinite;
}
@keyframes caret { 50% { opacity: 0; } }

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

.composer {
  flex: none;
  padding: var(--space-3) var(--gutter);
  border-top: var(--rule-width) solid var(--rule-strong);
}
.composer-box {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  padding: var(--space-2);
  background: var(--paper-raised);
  border: var(--rule-width) solid var(--rule-strong);
  border-radius: var(--radius);
  transition: border-color var(--duration) var(--ease);
}
.composer-box:focus-within { border-color: var(--accent); }
.composer-box textarea {
  flex: 1;
  min-height: var(--control-h);
  max-height: 180px;
  padding: var(--space-1) 0;
  font-family: var(--font-prose);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  background: none;
  border: none;
  resize: none;
  outline: none;
}
.composer-box textarea:focus { outline: none; border: none; }
.send-btn { width: var(--control-h); height: var(--control-h); padding: 0; flex: none; }

/* ---------------------------------------------------------------- live voice */

.mic-btn { width: var(--control-h); height: var(--control-h); padding: 0; flex: none; }
.mic-btn.active { color: var(--accent); border-color: var(--accent); }

/* A single status line above the composer while the microphone is open. */
.live-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  background: var(--paper-sunken);
  border: var(--rule-width) solid var(--rule);
}
.live-mark {
  width: var(--mark-status);
  height: var(--mark-status);
  flex: none;
  background: var(--status-idle);
}
.live-bar[data-state="listening"] .live-mark { background: var(--status-ok); }
.live-bar[data-state="thinking"] .live-mark,
.live-bar[data-state="working"] .live-mark { background: var(--status-warn); }
.live-bar[data-state="speaking"] .live-mark { background: var(--accent); }
.live-bar[data-state="reconnecting"] .live-mark { background: var(--status-warn); }
.live-state { flex: none; color: var(--ink); }

/* The words being said right now, trimmed to the tail by the caller. */
.live-caption {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-family: var(--font-prose);
  font-size: var(--text-xs);
  color: var(--ink-faint);
}
.live-bar .btn.active { color: var(--accent); }
.composer-foot {
  display: flex;
  justify-content: space-between;
  /* Match composer-box border + padding so hints share the textarea text edge. */
  margin-top: var(--space-2);
  padding: 0 calc(var(--rule-width) + var(--space-2));
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}

/* -------------------------------------------------------------- empty state */

/* The empty state is a page of its own rather than the head of a transcript, so
   it sits in the middle of the panel instead of leaving one long band of blank
   paper below it. Both auto margins collapse once it outgrows the panel. */
.welcome {
  width: 100%;
  margin: auto 0;
  padding: var(--space-4) 0;
}
.welcome h2 {
  margin: 0 0 var(--space-2);
  font-family: var(--font-prose);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
}
.welcome p {
  margin: 0 0 var(--space-4);
  max-width: 52ch;
  font-family: var(--font-prose);
  font-size: var(--text-md);
  line-height: var(--leading-prose);
  color: var(--ink-muted);
}
.starters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--rule-width);
  width: 100%;
  background: var(--rule);
  border: var(--rule-width) solid var(--rule);
}
.starter {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: var(--space-1);
  min-height: var(--space-16);
  padding: var(--space-3) var(--space-4);
  /* Prompts carry addresses and ticket URLs, which have no break opportunity. */
  overflow-wrap: anywhere;
  font-family: var(--font-prose);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--ink-muted);
  background: var(--paper);
  cursor: pointer;
  transition: color var(--duration) var(--ease), background-color var(--duration) var(--ease);
}
.starter:hover { color: var(--ink); background: var(--paper-sunken); }
.starter b {
  display: block;
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-none);
  color: var(--ink);
}

/* ----------------------------------------------------------------- inbox */

.inbox-card {
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
  border: var(--rule-width) solid var(--rule);
  border-left: 2px solid var(--accent);
}
.inbox-card .from {
  margin-bottom: var(--space-1);
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}
.inbox-card .body-text {
  font-family: var(--font-prose);
  font-size: var(--text-sm);
  line-height: var(--leading-prose);
}

.presence-line {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  background: var(--paper-sunken);
  border-left: 2px solid var(--rule-strong);
}
.presence-line.online { border-left-color: var(--status-ok); }
.presence-line.offline { border-left-color: var(--rule-strong); color: var(--ink-faint); }
.presence-line .hint { margin-left: auto; color: var(--ink-faint); }

/* --------------------------------------------------------- compose sidebar */

.compose-panel { flex: none; display: flex; flex-direction: column; }
/* The search box narrows the list below it, so the two read as one control. */
.compose-to input[type='search'] { margin-bottom: var(--space-1); }
#msg-match { margin: calc(-1 * var(--space-2)) 0 var(--space-3); }
.compose-panel .field-grow {
  margin-bottom: var(--space-3);
  display: flex;
  flex-direction: column;
}
.compose-panel .field-grow textarea {
  min-height: var(--space-16);
  padding: var(--space-2);
  resize: none;
}

/* -------------------------------------------------------------- activity log */

.activity { display: flex; flex-direction: column; overflow-y: auto; }
.activity > .empty { padding: var(--space-1) 0 0; }
.event {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  font-size: var(--text-2xs);
  border-bottom: var(--rule-width) solid var(--rule);
}
.event .icon { flex: none; display: flex; align-items: center; height: calc(var(--text-2xs) * var(--leading-snug)); }
.event .what { min-width: 0; }
.event .what b {
  display: block;
  font-weight: var(--weight-medium);
  color: var(--ink);
}
.event .what span { color: var(--ink-faint); overflow-wrap: break-word; }

/* ---------------------------------------------------------------- responsive
   Both side columns leave the grid together and return as drawers, so the
   assistant card, the message composer and the activity log stay reachable at
   any width. The chat itself is the only thing that keeps the page. */

@media (max-width: 1024px) {
  /* Both columns are taken out of flow by the drawer layer, so the grid is only
     ever the chat itself. */
  .workspace { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 820px) {
  /* Model name and graph counts are desk-side detail, not phone detail. */
  #llm-chip, #graph-summary { display: none; }

  .chat-head { gap: var(--space-2); }
  .composer-box textarea { font-size: 16px; }
  /* There is no Shift+Enter on a touch keyboard. */
  .kbd-hint { display: none; }
  .composer-foot { justify-content: flex-end; }

  .turn { gap: var(--space-2); padding-bottom: var(--space-3); margin-bottom: var(--space-3); }
  .welcome h2 { font-size: var(--text-lg); }
  .welcome p { margin-bottom: var(--space-3); font-size: var(--text-sm); }

  .starters { grid-template-columns: minmax(0, 1fr); }
  .starter { min-height: 0; padding: var(--space-2) var(--space-3); }
  /* Two lines each keeps all six suggestions in reach of one thumb scroll. */
  .starter .prompt {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
  }
}

@media (max-width: 560px) {
  /* The header keeps the two drawer keys and the two chat actions; the status
     tag is the first thing to go, since the composer already reports state. */
  .chat-head .tag-ok { display: none; }
  .live-bar { flex-wrap: wrap; }
  .live-caption { flex-basis: 100%; }
}

/* ----------------------------------------------------------- private chat
   Only the centre chatbox goes exact black; side columns keep the normal paper. */

html.private-chat .chat-panel {
  background: #000000;
  color: #f0ede6;
}

html.private-chat .chat-ready-overlay {
  background: var(--paper);
  color: var(--ink);
}

html.private-chat .chat-ready-overlay .loading-status {
  color: var(--ink-muted);
}

html.private-chat .chat-panel .chat-head {
  border-bottom-color: #222222;
}

html.private-chat .chat-panel .faint,
html.private-chat .chat-panel .tiny.faint,
html.private-chat .chat-panel .composer-foot {
  color: #7a756c;
}

html.private-chat .chat-panel .turn {
  border-bottom-color: #222222;
}

html.private-chat .chat-panel .avatar {
  color: #f0ede6;
  border-color: #3a3a3a;
  background: #0a0a0a;
}

html.private-chat .chat-panel .bubble .body {
  color: #f0ede6;
}

html.private-chat .chat-panel .bubble .who {
  color: #a8a29a;
}

html.private-chat .chat-panel .avatar.me {
  color: #a8a29a;
  border-color: #3a3a3a;
  background: #0a0a0a;
}

html.private-chat .chat-panel .turn.user .bubble .body,
html.private-chat .chat-panel .turn.blocked .bubble .body,
html.private-chat .chat-panel .bubble .body code,
html.private-chat .chat-panel .bubble .body pre {
  background: #0a0a0a;
  color: #f0ede6;
}

html.private-chat .chat-panel .composer {
  border-top-color: #222222;
  background: #000000;
}

html.private-chat .chat-panel .composer-box,
html.private-chat .chat-panel .composer-box textarea,
html.private-chat .chat-panel .live-bar {
  background: #0a0a0a;
  color: #f0ede6;
  border-color: #3a3a3a;
}

html.private-chat .chat-panel .composer-box textarea::placeholder {
  color: #7a756c;
}

html.private-chat .chat-panel .welcome {
  color: #a8a29a;
}

html.private-chat .chat-panel .starter {
  background: #0a0a0a;
  color: #a8a29a;
  border-color: #3a3a3a;
}

html.private-chat .chat-panel .starter:hover {
  color: #f0ede6;
  background: #111111;
}

html.private-chat #private-chat,
html.private-chat #new-chat {
  border-color: #3a3a3a;
}

html.private-chat #private-chat.active {
  color: var(--status-warn);
  border-color: var(--status-warn);
}
