.chat-container {
  max-width: 900px;
  margin: 0 auto;
  height: calc(100vh - 80px);
  display: flex;
  flex-direction: column;
  padding: 10px;
}

.chat-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 10px;
  border-bottom: 2px solid #e5e7eb;
  margin-bottom: 10px;

  h1 {
    margin: 0;
    font-size: 24px;
    color: #1f2937;
  }
}

.clear-button {
  background-color: #ef4444;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.2s;

  &:hover {
    background-color: #dc2626;
  }
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
  background-color: #f9fafb;
  border-radius: 8px;
  margin-bottom: 10px;

  /* Scrollbar style */
  &::-webkit-scrollbar {
    width: 8px;
  }

  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background: #cbd5e1;
    border-radius: 4px;

    &:hover {
      background: #94a3b8;
    }
  }
}

.empty-state {
  text-align: center;
  color: #6b7280;
  padding: 20px;
  font-size: 16px;
}

.message {
  position: relative;
  margin-bottom: 6px;
  padding: 6px 10px;
  border-radius: 8px;
  max-width: 85%;

  &.user {
    background-color: #dbeafe;
    margin-left: auto;
    border: 1px solid #bfdbfe;
  }

  &.assistant {
    background-color: #ffffff;
    margin-right: auto;
    border: 1px solid #e5e7eb;
  }
}

.message-role {
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 2px;
  color: #374151;
}

.message-thinking,
.tool-calls-section {
  margin: 0.5em 0;
  padding: 0.5em 0.75em;
  background: #f3f4f6;
  border-left: 3px solid #9ca3af;
  border-radius: 4px;
  font-size: 0.9em;

  summary {
    cursor: pointer;
    color: #6b7280;
    font-weight: 500;
    user-select: none;
  }
}

.message-thinking .message-thinking-content {
  margin-top: 0.5em;
  color: #4b5563;
  white-space: pre-wrap;
  font-family: ui-monospace, "SF Mono", monospace;
  font-size: 0.9em;
  line-height: 1.5;
  /* Cap the visible height so long reasoning doesn't push the actual
   * answer off the screen. The body scrolls internally; the controller
   * keeps it pinned to the bottom while new deltas arrive. */
  max-height: 12em;
  overflow-y: auto;
}

/* The role label's spinner while a turn is in flight. The wait is often long
 * on local models — a tool round has to re-process the whole prompt plus the
 * tool results before the first token — so a still label reads as a hang.
 * Rotation makes it visibly alive without adding another block to the page. */
.message-role .role-spinner {
  display: inline-block;
  animation: role-working-spin 1.8s linear infinite;
  transform-origin: 50% 50%;
}

@keyframes role-working-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Respect a reader's motion preference: keep the label, drop the spin. */
@media (prefers-reduced-motion: reduce) {
  .message-role .role-spinner { animation: none; }
}

/* Staggered three-dot "typing" indicator after the Reasoning summary
 * while thinking is still streaming. The .thinking-active class is set
 * by message_stream_controller when the thinking block is created and
 * removed by #foldTransientSections at end-of-stream — the dots are
 * hidden whenever the class is absent. */
.thinking-dots {
  display: none;
  margin-left: 0.35em;
  letter-spacing: 0.15em;
  font-weight: bold;
}

.message-thinking.thinking-active .thinking-dots {
  display: inline-block;
}

.message-thinking.thinking-active .thinking-dots span {
  display: inline-block;
  opacity: 0.25;
  animation: thinking-dot 1.4s ease-in-out infinite;
}

.message-thinking.thinking-active .thinking-dots span:nth-child(2) {
  animation-delay: 0.2s;
}

.message-thinking.thinking-active .thinking-dots span:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes thinking-dot {
  0%, 60%, 100% { opacity: 0.25; }
  30%           { opacity: 1; }
}

.tool-calls-section ul {
  margin: 0.5em 0 0;
  padding-left: 1.25em;
}

.message-content {
  color: #1f2937;
  line-height: 1.4;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  min-width: 0;

  p {
    margin: 0 0 0.5em 0;

    &:last-child {
      margin-bottom: 0;
    }
  }

  h1, h2, h3, h4, h5, h6 {
    margin: 0.5em 0 0.25em 0;
    line-height: 1.25;
  }

  ul, ol {
    margin: 0.25em 0 0.5em 1.25em;
    padding: 0;
  }

  li {
    margin: 0.1em 0;
  }

  blockquote {
    border-left: 3px solid #d1d5db;
    margin: 0.5em 0;
    padding: 0.1em 0.75em;
    color: #4b5563;
  }

  code {
    background-color: #f3f4f6;
    padding: 1px 4px;
    border-radius: 4px;
    font-size: 0.9em;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  }

  pre {
    background-color: #f3f4f6;
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    padding: 8px 10px;
    margin: 0.5em 0;
    overflow-x: auto;
    max-width: 100%;
    white-space: pre;

    code {
      background: none;
      padding: 0;
    }
  }

  table {
    border-collapse: collapse;
    margin: 0.5em 0;
    display: block;
    overflow-x: auto;
    max-width: 100%;
  }

  th, td {
    border: 1px solid #d1d5db;
    padding: 4px 8px;
  }

  th {
    background-color: #f3f4f6;
  }

  a {
    color: #2563eb;
    text-decoration: underline;
  }

  img {
    max-width: 100%;
    height: auto;
  }
}

/* simple_format() handles user-typed newlines (→ <br>/<p>); no need
   for pre-wrap, which would also render the template's surrounding
   indentation as visible whitespace inside the bubble. */

.chat-input-container {
  background-color: white;
  border: 2px solid #e5e7eb;
  border-radius: 8px;
  padding: 12px;
}

.chat-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.input-wrapper {
  position: relative;
  flex: 1;
}

.chat-input {
  width: 100%;
  padding: 12px;
  padding-right: 56px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 15px;
  font-family: inherit;
  resize: vertical;
  min-height: 44px;
  transition: border-color 0.2s;
  box-sizing: border-box;

  &:focus {
    outline: none;
    border-color: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
  }
}

/* Input controls (LLM + Tools + Settings — mutually exclusive) */
.input-controls {
  position: relative;
  margin-bottom: 10px;
}

.input-controls-buttons {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* LLM toggle */
.llm-toggle-field {
  display: inline-flex;
}

.llm-toggle-button {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  cursor: pointer;
  transition: border-color 0.2s, background-color 0.2s;
}

.llm-toggle-button:hover {
  background-color: #f9fafb;
  border-color: #9ca3af;
}

.llm-toggle-panel {
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  margin-bottom: 4px;
  /* These float above the page, and the page body is #f9fafb too — the same
     colour the panels used, with only a 1px hairline between them. Nothing
     read as an edge. Elevation (shadow) is what says "above", so that carries
     the separation; the surface stays light so the white provider cards
     inside it still stand out. */
  border: 1px solid #cbd5e1;
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.16), 0 2px 6px rgba(15, 23, 42, 0.07);
  border-radius: 8px;
  background-color: #f9fafb;
  padding: 12px 16px;
  z-index: 10;
  box-sizing: border-box;
}

/* Tool Selector */
.tool-selector-field {
  margin-bottom: 0;
}

.tool-toggle-button {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  cursor: pointer;
  transition: border-color 0.2s, background-color 0.2s;

  &:hover {
    background-color: #f9fafb;
    border-color: #9ca3af;
  }
}

.tool-count-badge {
  background-color: #3b82f6;
  color: white;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 10px;
  min-width: 18px;
  text-align: center;
}

.toggle-icon {
  font-size: 11px;
  transition: transform 0.2s;
}

.tool-selector-panel {
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  margin-bottom: 4px;
  /* These float above the page, and the page body is #f9fafb too — the same
     colour the panels used, with only a 1px hairline between them. Nothing
     read as an edge. Elevation (shadow) is what says "above", so that carries
     the separation; the surface stays light so the white provider cards
     inside it still stand out. */
  border: 1px solid #cbd5e1;
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.16), 0 2px 6px rgba(15, 23, 42, 0.07);
  border-radius: 8px;
  background-color: #f9fafb;
  max-height: 300px;
  overflow-y: auto;
  z-index: 10;
}

.tool-loading {
  padding: 12px;
  text-align: center;
  color: #6b7280;
  font-size: 13px;
}

.no-servers,
.no-tools {
  padding: 10px 12px;
  color: #9ca3af;
  font-size: 13px;
  font-style: italic;
}

.mcp-server-item {
  border-bottom: 1px solid #e5e7eb;

  &:last-child {
    border-bottom: none;
  }
}

.mcp-server-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  transition: background-color 0.15s;

  &:hover {
    background-color: #f3f4f6;
  }

  .server-toggle-icon {
    font-size: 11px;
    color: #6b7280;
  }

  .bi-server {
    color: #6b7280;
  }

  .mcp-server-select-all {
    cursor: pointer;
    margin: 0 0 0 auto; /* push to the far right of the header row */
    accent-color: #2563eb;
  }
  .mcp-server-select-all:disabled {
    cursor: not-allowed;
    opacity: 0.4;
  }
}

.mcp-server-name {
  /* No `flex: 1` — the name hugs its neighbors on the left so the
     "n tools" indicator sits right next to it. The select-all checkbox
     uses `margin-left: auto` to float to the far right. */
}

.tool-available-count {
  font-size: 11px;
  font-weight: 400;
  color: #9ca3af;
}

.mcp-server-shared-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 600;
  line-height: 1.4;
  border-radius: 8px;
  background-color: #ede9fe;
  color: #6d28d9;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;

  i { font-size: 9px; }
}

.mcp-server-tools {
  padding-left: 24px;
}

.tool-loading-inline {
  padding: 8px 12px;
  color: #6b7280;
  font-size: 12px;
}

.tool-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 6px 12px;
  cursor: pointer;
  transition: background-color 0.15s;

  &:hover {
    background-color: #f3f4f6;
  }

  input[type="checkbox"] {
    margin-top: 2px;
    accent-color: #3b82f6;
  }
}

.tool-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tool-name-row {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
}

.tool-name {
  font-size: 13px;
  font-weight: 500;
  color: #1f2937;
}

.tool-description {
  font-size: 11px;
  color: #6b7280;
  line-height: 1.3;
}

/* MCP tool annotation badges (mirrors the server-side pane badges). */
.tool-badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 500;
  line-height: 1.4;
  border: 1px solid transparent;
  white-space: nowrap;
}
.tool-badge-readonly    { background: #ecfdf5; color: #047857; border-color: #a7f3d0; }
.tool-badge-destructive { background: #fef2f2; color: #b91c1c; border-color: #fecaca; }
.tool-badge-idempotent  { background: #f8fafc; color: #334155; border-color: #cbd5e1; }
.tool-badge-openworld   { background: #eff6ff; color: #1d4ed8; border-color: #bfdbfe; }

/* Generation Settings */
.generation-settings-field {
  margin-bottom: 0;
}

.generation-settings-toggle-button {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  cursor: pointer;
  transition: border-color 0.2s, background-color 0.2s;

  &:hover {
    background-color: #f9fafb;
    border-color: #9ca3af;
  }
}

.generation-settings-panel {
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  margin-bottom: 4px;
  /* These float above the page, and the page body is #f9fafb too — the same
     colour the panels used, with only a 1px hairline between them. Nothing
     read as an edge. Elevation (shadow) is what says "above", so that carries
     the separation; the surface stays light so the white provider cards
     inside it still stand out. */
  border: 1px solid #cbd5e1;
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.16), 0 2px 6px rgba(15, 23, 42, 0.07);
  border-radius: 8px;
  background-color: #f9fafb;
  padding: 12px 16px;
  z-index: 10;
  box-sizing: border-box;
}

.generation-settings-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  margin-bottom: 6px;
}

.generation-settings-json-input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 13px;
  font-family: "SFMono-Regular", "Consolas", "Liberation Mono", "Menlo", monospace;
  background-color: white;
  resize: vertical;
  transition: border-color 0.2s;
  box-sizing: border-box;

  &:focus {
    outline: none;
    border-color: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
  }

  &::placeholder {
    color: #9ca3af;
  }
}

.generation-settings-json-input--invalid {
  border-color: #ef4444;

  &:focus {
    border-color: #ef4444;
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
  }
}

.generation-settings-error {
  font-size: 12px;
  color: #ef4444;
  margin-top: 4px;
}

.generation-settings-hint {
  font-size: 11px;
  color: #9ca3af;
  margin-top: 4px;
}

/* Drag-and-drop image attachment: highlight the form while dragging. */
.chat-form.drag-over {
  outline: 2px dashed #3b82f6;
  outline-offset: 4px;
  background-color: rgba(59, 130, 246, 0.04);
  border-radius: 8px;
}

/* Image attachment: paperclip button inside the input + thumbnail preview above it. */
.attach-button {
  position: absolute;
  bottom: 10px;
  right: 56px; /* sits to the left of the send button */
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: transparent;
  border-radius: 6px;
  color: #6b7280;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease, opacity 0.15s ease;

  i { font-size: 16px; }

  &:hover:not(:disabled) {
    color: #3b82f6;
    background-color: rgba(59, 130, 246, 0.1);
  }

  &:disabled {
    opacity: 0.35;
    cursor: not-allowed;
  }
}

/* User-attached image inside the message bubble (post-send / on reload). */
.user-attached-image {
  display: block;
  max-width: 100%;
  max-height: 320px;
  border-radius: 6px;
  margin-bottom: 6px;
  object-fit: contain;
}

.image-preview {
  position: relative;
  display: inline-block;
  margin-bottom: 6px;
  padding: 4px;
  background-color: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
}

.image-preview img {
  display: block;
  max-width: 160px;
  max-height: 160px;
  border-radius: 4px;
  object-fit: contain;
}

.image-clear-button {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: #fff;
  border-radius: 50%;
  color: #6b7280;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);

  &:hover { color: #dc2626; }
  i { font-size: 14px; }
}

/* Document attachment preview (pre-send) and chip (in message bubble). */
.document-preview {
  position: relative;
  display: inline-block;
  margin-bottom: 6px;
  padding: 6px 10px;
  background-color: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  font-size: 13px;
  color: #374151;
}

.user-attached-document {
  display: inline-block;
  margin-bottom: 6px;
  padding: 4px 8px;
  background-color: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: 4px;
  font-size: 13px;
  color: #1f2937;
  text-decoration: none;

  &:hover { background-color: #e5e7eb; }
}

/* Errored assistant bubble — visible signal that the stream failed. */
.message.stream-errored {
  border-color: #fecaca;
  background-color: #fef2f2;

  .message-role {
    color: #b91c1c;
  }
}

.stream-error {
  color: #b91c1c;
  font-size: 13px;
  font-style: italic;
  margin: 4px 0 0 0;
}

/* Cancel button on the live streaming bubble. */
.stream-cancel-button {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: transparent;
  border-radius: 4px;
  color: #888;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;

  i {
    font-size: 14px;
  }

  &:hover {
    color: #dc2626;
    background-color: rgba(220, 38, 38, 0.1);
  }
}

.send-button {
  position: absolute;
  bottom: 10px;
  right: 10px;
  background-color: #3b82f6;
  color: white;
  border: none;
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.2s, opacity 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover:not(:disabled) {
    background-color: #2563eb;
  }

  &:active:not(:disabled) {
    background-color: #1d4ed8;
  }

  &:disabled {
    background-color: #9ca3af;
    cursor: not-allowed;
    opacity: 0.6;
  }
}

/* === Grid-view model picker ============================================ */

/* Quick-picks row sits directly below the prompt textarea (above input-controls). */
.quick-picks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 6px 0;
}

.quick-pick-button {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 500;
  color: #1f2937;
  background-color: #fff;
  border: 1px solid #d1d5db;
  border-radius: 14px;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;

  i { font-size: 11px; color: #f59e0b; }

  &:hover {
    color: #1d4ed8;
    border-color: #3b82f6;
    background-color: rgba(59, 130, 246, 0.05);
  }

  &.is-default {
    border-color: #f59e0b;
    background-color: #fffbeb;
  }

  &.is-transient {
    border-style: dashed;
    color: #4b5563;
  }

  &.is-selected {
    color: #1f2937;
    background-color: #f3f4f6;
    border-color: #9ca3af;
    border-style: solid;
  }
}

/* The "Other models" grid panel */
.model-grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.model-grid-columns {
  display: grid;
  /* Two provider cards per row (2x2 for the usual four providers). One
     column per provider fitted four across, which left each card too narrow
     to read a model name in — the names ellipsised and every column looked
     alike. Half as many columns, twice the width. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  align-items: start;
}

.model-grid-column {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background-color: #fff;
  border: 1px solid #dbe1e8;
  border-radius: 8px;
  overflow: hidden;
  /* Page (#f9fafb) < panel (#f9fafb + shadow) < card (white). Without the
     faint lift the card edge was the same hairline as everything else. */
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}

.model-grid-header {
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 700;
  color: #374151;
  background-color: #f3f4f6;
  border-bottom: 1px solid #e5e7eb;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.model-grid-list {
  list-style: none;
  margin: 0;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.model-grid-cell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
  padding: 5px 8px;
  font-size: 12px;
  text-align: left;
  color: #1f2937;
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;

  &:hover {
    background-color: rgba(59, 130, 246, 0.06);
    border-color: #93c5fd;
  }

  &.is-selected {
    color: #fff;
    background-color: #2563eb;
    border-color: #2563eb;
  }
}

.model-grid-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex: 1 1 auto;
}

.model-grid-badges {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex: 0 0 auto;
}

/* Capability/state badges rendered as Bootstrap icons (lightweight,
   no text → keeps the cell narrow). */
.model-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  font-size: 12px;
  line-height: 1;
  color: #6b7280;
}

.model-badge-vision   { color: #2563eb; }
.model-badge-image    { color: #7c3aed; }
.model-badge-tools    { color: #059669; }
.model-badge-favorite { color: #f59e0b; }
.model-badge-default  { color: #d97706; }

/* Pricing tier badge — text-only ($/$$/$$$), narrower than icon badges.
   Cursor: help so the hover tooltip discoverability is obvious. */
.model-badge-price {
  width: auto;
  padding: 0 4px;
  font-size: 11px;
  font-weight: 700;
  color: #475569;
  cursor: help;
}

.model-grid-cell.is-selected .model-badge { color: #fff; }
.model-grid-cell.is-selected .model-badge-favorite,
.model-grid-cell.is-selected .model-badge-default { color: #fde68a; }

/* Providers the visitor has no API key for: readable, obviously inert.
   Dimmed rather than blurred so the model names — the reason to sign in —
   stay legible, and so the state does not depend on a hover tooltip. */
.model-grid-column.is-locked {
  background-color: #fafafa;
  border-style: dashed;
}

.model-grid-column.is-locked .model-grid-header {
  color: #6b7280;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

.model-grid-lock { font-size: 11px; color: #9ca3af; }

/* One call to action for the whole locked section, rather than the same
   sentence repeated on every card. Sits between the visitor's own providers
   and the ones they cannot use yet, so it reads as the boundary between
   them. */
.model-grid-locked-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 9px 12px;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
  color: #92400e;
  background-color: #fef3c7;
  border: 1px solid #fde68a;
  border-radius: 8px;
}

.model-grid-locked-banner i { font-size: 14px; flex: 0 0 auto; }

/* Informational variant, shown once every provider is unlocked. Amber says
   "something needs doing"; this only offers personalisation, so it is calm. */
.model-grid-locked-banner.is-info {
  color: #334155;
  background-color: #f1f5f9;
  border-color: #e2e8f0;
  font-weight: 500;
}

.model-grid-locked-banner.is-info .model-grid-locked-link,
.model-grid-locked-banner.is-info .model-grid-locked-link:visited { color: #1d4ed8; }
.model-grid-locked-banner.is-info .model-grid-locked-link:hover { color: #1e40af; }

/* The banner's call to action. For a signed-in visitor a link to the hub;
   for a signed-out one a real sign-in submit (omniauth needs a POST), styled
   to read as part of the sentence rather than as a separate button. */
.model-grid-locked-link,
.model-grid-locked-link:visited {
  color: #92400e;
  font-weight: 700;
  text-decoration: underline;
}

.model-grid-locked-link:hover { color: #78350f; }

.model-grid-locked-form { display: inline; }

button.model-grid-locked-link {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

.model-grid-cell.is-disabled {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 5px 8px;
  border-radius: 6px;
  color: #9ca3af;
  cursor: not-allowed;
  background: transparent;
}

.model-grid-cell.is-disabled:hover { background: transparent; }
.model-grid-cell.is-disabled .model-badge { color: #d1d5db; }

.model-grid-empty {
  padding: 8px;
  font-size: 12px;
  color: #6b7280;
  text-align: center;
}

.model-grid-footer {
  margin: 0;
  font-size: 11px;
  color: #6b7280;

  i { margin-right: 4px; }
  a { color: #2563eb; text-decoration: none; }
  a:hover { text-decoration: underline; }
}

/* Two-up is the default; drop to a single column once two cards no longer
   fit side by side. */
@media (max-width: 560px) {
  .model-grid-columns { grid-template-columns: 1fr; }
}

/* Local override of prompt_navigator's history.css — drop once the engine
   ships the same value. Adds breathing room between the "History" heading
   and the first history card. */
#history-sidebar .history-stack { margin-top: 20px; }

/* Local override of chat_manager's chat.css — drop once the engine ships
   the same rule. Pins the chat-list toolbar (heading + bulk actions) to
   the top of the scrollable sidebar so it stays visible when the list
   is long. The negative top/left/right margins extend the toolbar over
   the sidebar's 8px padding so scrolling cards can't peek through the
   gap; equal padding keeps the toolbar's content in its natural place. */
#chat-sidebar .chat-list-toolbar {
  position: sticky;
  top: 0;
  background-color: #ffffff;
  z-index: 2;
  margin: -8px -8px 6px;
  padding: 8px 8px 0;
}

/* === Download / Copy overlay for assistant-generated assets ============ */
/* Markup emitted by ApplicationHelper::AssistantResponseRenderer for
   images and copyable code blocks (json / csv). */
.response-asset {
  position: relative;
  margin: 8px 0;
}

.response-asset-image {
  display: inline-block;
}

.response-asset-code pre {
  margin: 0;
}

.asset-actions {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  gap: 4px;
  opacity: 0.35;
  transition: opacity 0.15s ease;
  z-index: 1;
}

.response-asset:hover .asset-actions,
.response-asset:focus-within .asset-actions {
  opacity: 1;
}

.asset-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  background-color: rgba(255, 255, 255, 0.92);
  color: #374151;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;

  &:hover {
    background-color: #2563eb;
    color: #fff;
    border-color: #2563eb;
  }

  &:active {
    transform: translateY(1px);
  }

  i { font-size: 13px; }
}

/* When the overlay sits on top of a dark code block, give the button
   a slightly tinted background instead of pure white for contrast. */
.response-asset-code .asset-action {
  background-color: rgba(249, 250, 251, 0.95);
}

/* === Super-user admin dashboard ===================================== */

.admin-page {
  max-width: 1100px;
  margin: 24px auto;
  padding: 0 16px 32px;
  color: #1f2937;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.admin-header h1 {
  font-size: 22px;
  font-weight: 700;
  margin: 0;
}

.admin-subhead {
  margin: 4px 0 24px;
  font-size: 12px;
  color: #6b7280;
}

.admin-section {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 16px 20px;
  margin-bottom: 16px;
}

.admin-section h2 {
  font-size: 16px;
  font-weight: 600;
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 6px;
  color: #374151;
}

.admin-section h2 i { color: #6b7280; font-size: 14px; }

.admin-section h3 {
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  margin: 18px 0 6px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.admin-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px;
  margin: 4px 0 8px;
}

.admin-card {
  border: 1px solid #f3f4f6;
  border-radius: 6px;
  padding: 10px 12px;
  background: #fafafa;
}

.admin-card-label {
  font-size: 10px;
  font-weight: 600;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.admin-card-value {
  font-size: 20px;
  font-weight: 600;
  color: #111827;
  margin-top: 2px;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.admin-table th, .admin-table td {
  padding: 6px 8px;
  text-align: left;
  border-bottom: 1px solid #f3f4f6;
}

.admin-table th {
  font-weight: 600;
  color: #6b7280;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.admin-table code {
  background: #f3f4f6;
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 12px;
}

.admin-empty {
  margin: 4px 0;
  color: #9ca3af;
  font-size: 13px;
}

.admin-error {
  margin: 8px 0;
  padding: 8px 12px;
  background: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: 6px;
  color: #991b1b;
  font-size: 13px;
}

/* Demo chats pane — read-only list of admin-curated public chats, sits
   above the user's own "Chats" pane in the left sidebar. Deliberately
   understated so it doesn't compete with the user's own chat list. */
.demo-chats-pane {
  padding: 8px 12px 12px;
  border-bottom: 1px solid #e5e7eb;
  margin-bottom: 8px;
}
.demo-chats-pane h2 {
  font-size: 13px;
  font-weight: 600;
  color: #6b7280;
  margin: 0 0 6px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.demo-chats-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.demo-chats-list li {
  margin: 2px 0;
}
.demo-chats-link {
  display: block;
  padding: 4px 6px;
  color: #374151;
  text-decoration: none;
  font-size: 13px;
  border-radius: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.demo-chats-link:hover {
  background: #f3f4f6;
  color: #111827;
}

/* Landing hero — first-run pitch in the empty dialog area. Removed via
   Turbo Stream on first message send (chats/create.turbo_stream.erb). */
.landing-hero {
  max-width: 640px;
  margin: 40px auto;
  padding: 32px 28px;
  background: linear-gradient(135deg, #f0fdfa 0%, #eff6ff 100%);
  /* Same depth order as the composer popovers: the page is #f9fafb, so a pale
     mint hairline gave this no edge. Border firm enough to read, shadow to
     place it above the page rather than painted onto it. */
  border: 1px solid #bfdbfe;
  border-radius: 12px;
  box-shadow: 0 4px 14px rgba(15, 23, 42, 0.07), 0 1px 3px rgba(15, 23, 42, 0.05);
  text-align: center;
}
.landing-hero h1 {
  font-size: 22px;
  font-weight: 700;
  color: #0f172a;
  margin: 0 0 12px;
}
.landing-hero-tagline {
  font-size: 15px;
  color: #334155;
  line-height: 1.5;
  margin: 0 0 20px;
}
.landing-hero-cta {
  font-size: 15px;
  color: #0f172a;
  margin: 16px 0 8px;
}
.landing-hero-cta-link {
  color: #0f766e;
  font-weight: 600;
  text-decoration: underline;
}
.landing-hero-cta-link:hover {
  color: #115e59;
}
.landing-hero-hint {
  font-size: 13px;
  color: #64748b;
  margin: 12px 0 0;
}

/* Landing-hero example cards — three side-by-side mini-mockups illustrating
   the platform's core features (branching, model switching, MCP tools). */
.landing-hero-examples {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin: 24px 0;
}
@media (max-width: 720px) {
  .landing-hero-examples { grid-template-columns: 1fr; }
}
.landing-hero-example {
  background: #ffffff;
  /* One level above the hero, matching the provider cards inside the picker. */
  border: 1px solid #dbe1e8;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
}
.lh-viz {
  min-height: 120px;
  padding: 8px;
  background: #f8fafc;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
  color: #334155;
}
.lh-caption { font-size: 12px; color: #475569; line-height: 1.4; }
.lh-caption strong { display: block; color: #0f172a; font-size: 13px; margin-bottom: 2px; }

/* --- Branching viz — mirrors the app's History pane visual language.
   Single vertical column of prompt-cards; straight ↑ between adjacent
   parent→child pairs; a curved SVG arrow arcs to the LEFT for the
   non-adjacent parent→child (the branch). --- */
.lh-viz-branch {
  flex-direction: row;
  align-items: stretch;
  gap: 0;
  padding: 8px 8px 8px 4px;
}
.lh-branch-arc {
  width: 22px;
  flex-shrink: 0;
  align-self: stretch;
}
.lh-branch-stack {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.lh-node {
  padding: 4px 8px;
  background: #fff;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 12px;
  color: #334155;
}
.lh-node-active { border-color: #0ea5e9; box-shadow: 0 0 0 2px #bae6fd; }
.lh-node-alt    { border-color: #f59e0b; background: #fffbeb; color: #78350f; }
.lh-branch-updown {
  align-self: center;
  color: #64748b;
  font-size: 11px;
  line-height: 1;
  padding: 1px 0;
}
.lh-branch-gap {
  /* Vertical whitespace that separates the "current thread" from the
     "branched-off alternate" — same visual break the History pane uses
     to signal a fork. */
  height: 10px;
}

/* --- Model-switch viz --- */
.lh-msg { padding: 3px 6px; border-radius: 4px; font-size: 11px; line-height: 1.4; }
.lh-msg-user { background: #dbeafe; color: #1e3a8a; align-self: flex-end; max-width: 85%; }
.lh-msg-asst { background: #fff; border: 1px solid #e5e7eb; color: #334155; max-width: 90%; }
.lh-badge {
  display: inline-block;
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 600;
  margin-right: 4px;
}
.lh-badge-claude { background: #fef3c7; color: #92400e; }
.lh-badge-gpt    { background: #dcfce7; color: #14532d; }

/* --- MCP tools viz --- */
.lh-viz-tools { padding-top: 6px; }
.lh-tool-header {
  font-weight: 600;
  color: #0f172a;
  padding: 4px 6px;
  border-bottom: 1px solid #e5e7eb;
  margin-bottom: 4px;
}
.lh-tool-count {
  display: inline-block;
  background: #0ea5e9;
  color: #fff;
  font-size: 10px;
  padding: 0 5px;
  border-radius: 10px;
  margin-left: 4px;
}
.lh-tool-item { padding: 3px 6px; display: flex; align-items: center; gap: 6px; }
.lh-tool-item-off { color: #94a3b8; }
.lh-check {
  display: inline-block;
  width: 14px;
  height: 14px;
  line-height: 14px;
  text-align: center;
  border: 1px solid #cbd5e1;
  border-radius: 3px;
  font-size: 11px;
  color: #cbd5e1;
}
.lh-check-on { background: #0ea5e9; border-color: #0ea5e9; color: #fff; }

/* Synthetic root node in the history pane.
   It keeps .history-card's box so the tree reads as one shape with a single
   visible origin — every root names it as parent and gets an arrow from it.
   Everything inside the box is then deliberately unlike a prompt card: a
   tinted ground, a centred label (there is no delete button or model badge
   competing for the row), and the serif stack used elsewhere in the app, so
   it reads as a marker rather than something someone typed.

   Selectors are doubled up (.history-card.history-card-start) because the
   gem's own .history-card rules carry equal specificity and would otherwise
   win on source order. */
.history-card.history-card-start {
  background: #f1f5f9;
  border-color: #cbd5e1;
}

.history-card.history-card-start .history-card-prompt {
  text-align: center;
  font-family: Georgia, "Charter", "Iowan Old Style", "Source Serif Pro", serif;
  font-size: 13px;
  letter-spacing: 0.06em;
  color: #475569;
}

.history-card.history-card-start.is-active {
  background: #e8f0ff;
}

.history-card.history-card-start.is-active .history-card-prompt {
  color: #0b5ed7;
  font-weight: 600;
}

/* Cited history nodes ("supplements").
   Violet throughout, matching the dotted arrows history_controller draws for
   these edges — the colour is the only thing tying the card in the pane to the
   chip above the composer, so the two must not drift. */
.history-card.is-supplement {
  border-color: #7c3aed;
  box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.18);
}

.supplement-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}

/* `hidden` is honoured by the UA rule `[hidden] { display: none }`, which an
   author `display: flex` silently outranks — so both containers stayed visible
   whatever the controller set. Restate it here at author level. */
.supplement-chips[hidden],
.supplement-presets[hidden],
.supplement-note[hidden],
.supplement-preview[hidden] {
  display: none;
}

/* The assembled block, exactly as the model will receive it. Monospace and
   scrollable: it is machine text, and a long citation should not push the
   composer off screen. */
.supplement-preview {
  max-height: 180px;
  margin: 0 0 6px;
  padding: 8px 10px;
  overflow: auto;
  border: 1px solid #ddd6fe;
  border-radius: 6px;
  background: #faf9ff;
  color: #3c366b;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.72rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}

.supplement-reveal {
  padding: 0;
  border: none;
  background: transparent;
  color: #7c3aed;
  font-size: 0.72rem;
  text-decoration: underline;
  cursor: pointer;
}

/* Says where a citation actually goes. Deliberately quiet — it is an
   explanation, not a control. */
.supplement-note {
  margin-bottom: 6px;
  font-size: 0.72rem;
  line-height: 1.35;
  color: var(--muted-text, #666);
}

.supplement-chips-label,
.supplement-presets-label {
  font-size: 0.78rem;
  color: var(--muted-text, #666);
}

.supplement-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 220px;
  padding: 2px 6px;
  border: 1px solid #ddd6fe;
  border-radius: 999px;
  background: #f5f3ff;
  font-size: 0.78rem;
  color: #4c1d95;
}

.supplement-chip-index {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: #7c3aed;
}

/* The chip carries a prompt preview, which can be arbitrarily long. */
.supplement-chip-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.supplement-chip-remove {
  padding: 0;
  border: none;
  background: transparent;
  color: #7c3aed;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
}

.supplement-chip-remove:hover {
  color: #4c1d95;
}

.supplement-presets {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}

.supplement-preset {
  padding: 2px 10px;
  border: 1px solid #ddd6fe;
  border-radius: 999px;
  background: #fff;
  color: #5b21b6;
  font-size: 0.78rem;
  cursor: pointer;
}

.supplement-preset:hover {
  background: #f5f3ff;
  border-color: #7c3aed;
}

/* What a user turn actually carried, beyond what was typed. Collapsed by
   default and styled like the assistant's reasoning block: available on
   demand, never in the way. It exists because the stored prompt is only the
   typed text — without it the transcript showed less than the model got. */
.message-references {
  margin-bottom: 8px;
  font-size: 0.78rem;
}

.message-references > summary {
  color: #7c3aed;
  cursor: pointer;
}

.message-references-content {
  max-height: 220px;
  margin: 6px 0 0;
  padding: 8px 10px;
  overflow: auto;
  border: 1px solid #ddd6fe;
  border-radius: 6px;
  background: #faf9ff;
  color: #3c366b;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.72rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}
