/* 聊天页（index.html）自己的布局和组件。只有聊天页加载这个文件（base.css 之后），所以
   这里的元素选择器（body / main / footer）不会影响管理台和接入页。 */

body {
  display: flex;
  flex-direction: row;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  position: relative;
}

header,
main,
footer,
.sidebar {
  position: relative;
  z-index: 1;
}

/* ---------- 顶栏 ---------- */

/* 对话顶栏：当前对话标题 + 只作用于这个对话的操作（对话设置、清空）；窄屏多出打开侧栏、
   新对话两个按钮。只用 .chat-header 选择，不写裸的 header——管理台、弹窗里也有 <header>。 */
.chat-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
}

.chat-title {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chat-header-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

/* 顶栏里的图标按钮比侧栏那几个圆形按钮更轻：平时没有底色和描边，悬停才出现。 */
.icon-btn.header-btn {
  width: 34px;
  height: 34px;
  background: transparent;
  border-color: transparent;
  border-radius: 9px;
  color: var(--ink-dim);
}

.icon-btn.header-btn:hover,
.icon-btn.header-btn:active {
  background: var(--surface-hover);
  border-color: transparent;
  color: var(--ink);
}

.icon-btn.header-btn svg {
  width: 17px;
  height: 17px;
}

/* 对话有自定义设置时，"对话设置"图标右上角一个小圆点。 */
.header-btn .badge-dot {
  position: absolute;
  top: 6px;
  right: 6px;
  margin: 0;
  width: 7px;
  height: 7px;
  box-shadow: 0 0 0 2px var(--ground);
}

.header-new-chat {
  display: none;
}

/* 桌面端顶栏浮在消息区上面（绝对定位 + 往下渐隐的底色），不占 flex 位置——
   新对话时 .app-main--empty 把欢迎语和输入框整体垂直居中，顶栏要是占位就会被一起
   拖离顶部。消息区相应留出顶栏的高度。 */
@media (min-width: 901px) {
  .app-main {
    position: relative;
  }

  .chat-header {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 5;
    height: 56px;
    padding: 0 20px;
    background: linear-gradient(var(--ground) 55%, transparent);
  }

  body.sidebar-collapsed .chat-header {
    padding-left: 60px;
  }

  /* 带上 .app-main：后面消息区那条基础 main 规则会覆盖同等特异性的 padding。 */
  .app-main main {
    padding-top: 68px;
  }
}


/* 具体模型跟附件按钮一起放进输入框卡片下面那条工具栏——细粒度、经常换，
   一个紧凑的触发按钮（当前模型名 + 箭头），点开才弹出这个服务商名下的模型
   列表，不占永久空间；参考 ChatGPT/Claude 网页版把模型选择放进输入框工具栏
   的做法。弹出层朝上开、左边对齐触发按钮，因为按钮贴在视口底部靠左的位置。 */
.model-picker {
  position: relative;
}

.model-trigger {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--ink-dim);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}

.model-trigger:hover,
.model-trigger[aria-expanded="true"] {
  border-color: var(--violet-line);
  color: var(--ink);
}

.model-trigger:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.model-chevron {
  width: 12px;
  height: 12px;
  transition: transform 140ms ease;
}

.model-trigger[aria-expanded="true"] .model-chevron {
  transform: rotate(180deg);
}

/* 模型菜单：顶部"自动选择"，下面左栏服务商、右栏这家的模型。宽度固定，切服务商时
   菜单不会忽宽忽窄地跳。 */
.model-menu {
  position: absolute;
  bottom: 100%;
  left: 0;
  margin: 0 0 10px;
  width: min(540px, calc(100vw - 32px));
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  box-shadow: 0 24px 48px -16px rgba(20, 22, 26, 0.28), 0 0 0 1px rgba(0, 0, 0, 0.02);
  z-index: 20;
  animation: menu-in 160ms cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes menu-in {
  from {
    opacity: 0;
    transform: translateY(4px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.model-menu[hidden] {
  display: none;
}

.model-menu-auto {
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--hairline);
}

.model-menu-body {
  display: grid;
  grid-template-columns: 148px minmax(0, 1fr);
  gap: 6px;
  height: min(300px, 50vh);
}

.model-menu-providers {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 6px;
  border-right: 1px solid var(--hairline);
  overflow-y: auto;
}

.provider-tab {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--ink-dim);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}

.provider-tab:hover {
  background: var(--surface-hover);
  color: var(--ink);
}

.provider-tab[aria-selected="true"] {
  background: var(--surface-hover);
  color: var(--ink);
  font-weight: 600;
}

.provider-tab-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.provider-tab-count {
  font-size: 11px;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* 当前选中的模型属于这一家：左边一道主色竖条，翻到别家看的时候也知道"我现在用的是哪家"。 */
.provider-tab.has-selection::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 2px;
  background: var(--violet);
}

.model-menu-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  min-width: 0;
}

.model-option-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 0;
}

.model-option-title {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12.5px;
}

.model-option--auto .model-option-title {
  font-family: inherit;
  font-size: 13.5px;
}

.model-option-hint {
  font-size: 11.5px;
  color: var(--ink-faint);
  font-weight: 400;
  text-align: left;
  line-height: 1.45;
}

.model-option-badges {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.model-status {
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--ground-2);
  border: 1px solid var(--hairline);
  color: var(--ink-faint);
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}

/* 眼下每个 key 都在冷却的模型：变淡提示，但照样能点。 */
.model-option--unavailable .model-option-text {
  opacity: 0.55;
}

.model-option {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease;
}

.model-option:hover,
.model-option:active {
  background: var(--surface-hover);
}

/* 选中态要一眼看出来：主色描边 + 浅主色底 + 右边一个勾。 */
.model-option[aria-selected="true"] {
  background: var(--violet-soft);
  border-color: var(--violet-line);
}

.model-option[aria-selected="true"] .model-option-title {
  color: var(--violet-strong);
  font-weight: 650;
}

.model-option[aria-selected="true"]::after {
  content: "";
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  background: var(--violet);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / contain no-repeat;
}

@media (max-width: 560px) {
  .model-menu-body {
    grid-template-columns: 118px minmax(0, 1fr);
  }

  .provider-tab {
    padding: 8px;
    gap: 6px;
  }

  .provider-tab-count {
    display: none;
  }
}

/* 支持读图的模型旁边的小图标——服务商列表、模型胶囊都用这个，颜色用暖色调
   跟渠道色点区分开，一眼能看出"这个是能力标签，不是渠道标识"。 */
.capability-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--amber-strong);
}

.capability-icon svg {
  width: 13px;
  height: 13px;
}

.provider-dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  /* 渠道色由 modelPicker 按 providerColor() 设到 --dot-color 上 */
  background: var(--dot-color, var(--ink-faint));
}

/* 自动选择：不属于任何一家，用主色 + 琥珀的渐变，跟各家的纯色点区分开。 */
.provider-dot--auto {
  background: linear-gradient(135deg, var(--violet), var(--amber));
}



/* 圆形而不是 8px 圆角的方块——这几个（收起/展开侧栏、关闭抽屉、汉堡菜单）
   都是纯图标的小按钮，8px 圆角相对 34px 的尺寸太小，看着还是接近直角；
   参考主流产品图标按钮基本都是正圆。 */
.icon-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  background: var(--ground-2);
  color: var(--ink-dim);
  border: 1px solid var(--hairline);
  border-radius: 50%;
  cursor: pointer;
  transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}

.icon-btn svg {
  width: 16px;
  height: 16px;
}

.icon-btn:hover,
.icon-btn:active {
  border-color: var(--violet-line);
  color: var(--ink);
  background: var(--surface-hover);
}

/* 当前对话配了系统提示词时，在"系统提示词"这一行文字后面点一个小圆点——不用
   点进去看就知道这个对话"有没有"套自定义提示词，不知道内容是什么没关系，
   知道"有没有"就够了。跟着文字内联摆放，不是绝对定位的角标（那是给方形小
   图标按钮用的画法，这里是侧边栏里的整行按钮，跟文字排在一起更自然）。 */
.badge-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--violet-strong);
  margin-left: 2px;
}

/* 同 .provider-list[hidden]：上面的 display 会盖过 UA 的 [hidden] 规则，不显式
   声明的话小圆点在所有对话上都常亮，起不到"这个对话有自定义设置"的提示作用。 */
.badge-dot[hidden] {
  display: none;
}

/* ---------- 消息区 ---------- */

main {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 28px 20px 12px;
  scroll-behavior: smooth;
}

main::-webkit-scrollbar {
  width: 10px;
}

main::-webkit-scrollbar-thumb {
  background: var(--hairline);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: padding-box;
}

main::-webkit-scrollbar-thumb:hover {
  background: var(--hairline-soft);
  background-clip: padding-box;
}

.empty-state {
  max-width: 640px;
  margin: 12vh auto 0;
  text-align: center;
  color: var(--ink-faint);
}

.empty-state[hidden] {
  display: none;
}

.empty-mark {
  position: relative;
  display: inline-flex;
  width: 56px;
  height: 56px;
  align-items: center;
  justify-content: center;
  border-radius: 16px;
  background: linear-gradient(155deg, var(--violet-soft), var(--amber-soft));
  color: var(--violet-strong);
  margin-bottom: 18px;
}

/* 图标后面加一圈模糊的柔光，比一个纯色方块块头更有点"这是个产品"的意思。 */
.empty-mark::before {
  content: "";
  position: absolute;
  inset: -18px;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, var(--violet-soft), transparent 70%);
  filter: blur(4px);
}

.empty-mark svg {
  width: 26px;
  height: 26px;
}

.empty-title {
  font-size: 26px;
  font-weight: 650;
  letter-spacing: -0.01em;
  margin: 0 0 8px;
  background: linear-gradient(120deg, var(--ink), var(--violet-strong) 60%, var(--amber-strong));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.empty-hint {
  font-size: 14px;
  line-height: 1.6;
  margin: 0;
}

.suggestions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-top: 26px;
  text-align: left;
}

.suggestion {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}

.suggestion:hover {
  border-color: var(--violet-line);
  background: var(--violet-soft);
  transform: translateY(-1px);
  box-shadow: var(--shadow-lift);
}

.suggestion-kicker {
  font-size: 12px;
  font-weight: 600;
  color: var(--violet-strong);
}

@media (max-width: 560px) {
  .suggestions {
    grid-template-columns: 1fr;
  }

  .suggestion:nth-child(n + 3) {
    display: none;
  }
}

.row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  max-width: 760px;
  margin: 0 auto 22px;
}

.row-user {
  justify-content: flex-end;
}

/* 气泡 + 操作按钮栏竖着摞在一起的容器——气泡本身的宽度/对齐规则从 .row 挪到这层，
   这样"复制/编辑/重新生成"那排小按钮才能画在气泡下面而不是气泡旁边。 */
.msg-column {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: min(600px, 100%);
}

.row-user .msg-column {
  align-items: flex-end;
}

.row-assistant .msg-column {
  align-items: flex-start;
  /* 助手回复不再是限宽卡片：占满整栏（跟 ChatGPT/Claude 一样），代码和表格不用挤。 */
  flex: 1;
  max-width: 100%;
}

.row-user .msg-column {
  max-width: min(600px, 85%);
}

.msg-note {
  margin-top: 4px;
  font-size: 12px;
  color: var(--ink-faint);
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* 信息行末尾的"详情"：跟这行字一样小、一样淡，悬停 / 键盘聚焦时才显出是个按钮 */
.msg-meta-toggle {
  margin-left: 6px;
  padding: 0 4px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--ink-dim);
  font: inherit;
  cursor: pointer;
}

.msg-meta-toggle:hover {
  color: var(--violet);
  background: var(--violet-soft);
}

.msg-meta-toggle:focus-visible {
  outline: 2px solid var(--violet-line);
  outline-offset: 1px;
}

.msg-meta-details {
  margin-top: 2px;
}

.msg-meta-details[hidden] {
  display: none;
}

.msg-actions {
  display: flex;
  gap: 2px;
  margin-top: 3px;
  opacity: 0.75;
}

.msg-action {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: none;
  border: none;
  color: var(--ink-faint);
  cursor: pointer;
  border-radius: 6px;
  transition: color 140ms ease, background 140ms ease;
}

.msg-action::after {
  content: attr(data-tooltip);
  position: absolute;
  z-index: 20;
  left: 50%;
  bottom: calc(100% + 7px);
  padding: 5px 8px;
  border: 1px solid var(--hairline);
  border-radius: 7px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-lift);
  font-size: 11px;
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 3px);
  transition: opacity 120ms ease, transform 120ms ease, visibility 120ms ease;
}

.msg-action:hover::after,
.msg-action:focus-visible::after {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}

.msg-action:hover {
  color: var(--ink);
  background: var(--surface-hover);
  opacity: 1;
}

.msg-action svg {
  width: 13px;
  height: 13px;
}

/* 回复输出期间：编辑、重新生成、编辑后的"保存并重新生成"都点不动（逻辑上也会忽略）。 */
.is-busy [data-needs-idle] {
  opacity: 0.3;
  pointer-events: none;
}

.icon-btn.header-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.edit-textarea {
  width: min(600px, 100%);
  min-height: 64px;
  padding: 10px 12px;
  background: var(--ground-2);
  color: var(--ink);
  border: 1px solid var(--violet-line);
  border-radius: var(--radius-md);
  font: inherit;
  font-size: 15px;
  line-height: 1.5;
  resize: vertical;
}

.edit-textarea:focus {
  outline: none;
  border-color: var(--violet);
}

.edit-controls {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}

.edit-controls button {
  padding: 6px 12px;
  font-size: 12.5px;
}

.msg-text-part {
  margin: 0 0 8px;
}

.msg-text-part:last-child {
  margin-bottom: 0;
}

.msg-image {
  display: block;
  max-width: 100%;
  max-height: 260px;
  border-radius: var(--radius-sm);
  margin-bottom: 6px;
}

.msg-image:last-child {
  margin-bottom: 0;
}

.avatar {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(155deg, var(--violet-soft), var(--amber-soft));
  color: var(--violet-strong);
  margin-top: 2px;
}

.avatar svg {
  width: 15px;
  height: 15px;
}

.msg {
  max-width: min(600px, 100%);
  padding: 12px 16px;
  border-radius: var(--radius-md);
  white-space: pre-wrap;
  word-break: break-word;
  overflow-wrap: anywhere;
  line-height: 1.65;
  font-size: 15px;
  animation: rise 240ms cubic-bezier(0.16, 1, 0.3, 1);
}


.msg-user {
  background: var(--violet);
  color: #fff;
  border-radius: 18px 18px 6px 18px;
  padding: 10px 16px;
  box-shadow: 0 6px 16px -10px var(--violet);
}

.msg-file-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 8px;
}

.msg-file-attachment {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  max-width: min(320px, 100%);
  padding: 7px 10px;
  border: 1px solid rgb(255 255 255 / 24%);
  border-radius: 10px;
  background: rgb(20 20 35 / 20%);
}

.msg-file-icon {
  display: inline-flex;
  flex: 0 0 20px;
  opacity: 0.9;
}

.msg-file-icon svg {
  width: 20px;
  height: 20px;
}

.msg-file-details {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.35;
}

.msg-file-name {
  overflow: hidden;
  font-size: 12px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.msg-file-size {
  margin-top: 2px;
  font-size: 10px;
  opacity: 0.72;
}

.msg-assistant {
  /* 内容是 marked 输出的真 HTML 块级元素了，标签之间的换行不该再当"用户手敲的
     换行"渲染成空行——继承自 .msg 的 pre-wrap 是给纯文本气泡（用户/错误/提示）用的。 */
  white-space: normal;
  /* 不画卡片：正文直接铺在背景上，跟头像顶端对齐。出错时 .msg-error 再把框画回来。 */
  max-width: 100%;
  width: 100%;
  padding: 3px 0 0;
  border-radius: 0;
  line-height: 1.75;
}

.msg-assistant.msg-error {
  padding: 12px 16px;
  border: 1px solid var(--error-line);
  border-radius: var(--radius-md);
}

/* 出错气泡的三段：标题（发生了什么）、建议（怎么办）、细节（状态码 + 请求 ID，报问题用）。 */
.msg-error-title {
  font-weight: 600;
}

.msg-error-hint {
  margin-top: 4px;
  color: var(--ink);
}

.msg-error-detail {
  margin-top: 8px;
  font-size: 12px;
  color: var(--ink-faint);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}

.msg-error-action {
  margin-top: 10px;
  padding: 6px 14px;
  border: 1px solid var(--error-line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--error);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.msg-error-action:hover {
  background: var(--error-soft);
}

.msg-assistant.is-streaming::after {
  content: "";
  display: inline-block;
  width: 7px;
  height: 15px;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: var(--violet);
  border-radius: 1px;
  animation: blink 900ms ease-in-out infinite;
}

/* 推理模型的思考过程：比正文弱一级的视觉（虚线描边、次级文字色），思考期间
   展开，正文开始后自动收起成一行"已思考 N 秒"。正文区限高并内部滚动，几千字
   的思考不会把整个对话撑得很长。 */
.msg-reasoning {
  align-self: stretch;
  margin-bottom: 8px;
  border: 1px dashed var(--hairline);
  border-radius: var(--radius-md);
  background: var(--ground-2);
  font-size: 13px;
  color: var(--ink-dim);
}

.msg-reasoning summary {
  cursor: pointer;
  padding: 8px 12px;
  user-select: none;
}

.msg-reasoning[open] summary {
  border-bottom: 1px dashed var(--hairline);
}

.msg-reasoning-body {
  max-height: 240px;
  overflow-y: auto;
  padding: 8px 12px 10px;
  white-space: pre-wrap;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

@keyframes blink {
  0%,
  100% {
    opacity: 0.9;
  }
  50% {
    opacity: 0.15;
  }
}

.msg-error {
  color: var(--error);
  background: var(--error-soft);
  border-color: var(--error-line);
}

.msg-notice {
  max-width: 720px;
  margin: 0 auto 16px;
  text-align: center;
  color: var(--ink-faint);
  font-size: 13px;
  padding: 2px 10px;
  animation: none;
}

/* 助手消息里 Markdown 渲染出来的富文本排版，就地覆盖浏览器默认样式，跟气泡的
   字号/行高对齐，别让 <p>/<ul> 之类自带的 margin 把气泡撑得忽大忽小。 */

.msg-assistant p {
  margin: 0 0 12px;
}

.msg-assistant p:last-child {
  margin-bottom: 0;
}

.msg-assistant ul,
.msg-assistant ol {
  margin: 0 0 10px;
  padding-left: 22px;
}

.msg-assistant li {
  margin-bottom: 4px;
}

.msg-assistant h1,
.msg-assistant h2,
.msg-assistant h3,
.msg-assistant h4 {
  font-weight: 650;
  line-height: 1.4;
  margin: 22px 0 10px;
  color: var(--ink);
}

.msg-assistant h1 {
  font-size: 1.35em;
}

.msg-assistant h2 {
  font-size: 1.2em;
}

.msg-assistant h3,
.msg-assistant h4 {
  font-size: 1.06em;
}

.msg-assistant h1:first-child,
.msg-assistant h2:first-child,
.msg-assistant h3:first-child {
  margin-top: 0;
}

.msg-assistant strong {
  color: var(--ink);
  font-weight: 600;
}

.msg-assistant a {
  color: var(--violet-strong);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.msg-assistant blockquote {
  margin: 0 0 12px;
  padding: 8px 14px;
  border-left: 3px solid var(--violet);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--violet-soft);
  color: var(--ink-dim);
}

.msg-assistant hr {
  border: none;
  border-top: 1px solid var(--hairline);
  margin: 12px 0;
}

.msg-assistant table {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  margin: 0 0 12px;
  font-size: 0.92em;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.msg-assistant th,
.msg-assistant td {
  border: none;
  border-bottom: 1px solid var(--hairline);
  padding: 8px 12px;
  text-align: left;
}

.msg-assistant th {
  color: var(--ink);
  font-weight: 600;
  background: var(--ground-2);
}

.msg-assistant tr:last-child td {
  border-bottom: none;
}

.msg-assistant code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.88em;
  background: var(--ground-2);
  border: 1px solid var(--hairline);
  border-radius: 4px;
  padding: 1px 5px;
}

.msg-assistant pre {
  margin: 0 0 14px;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid var(--hairline);
  background: var(--ground-2);
}

/* 选择器带上 .hljs：高亮主题的 CSS 排在 chat.css 后面加载，同等特异性会被它的
   padding/背景盖掉。背景交给 pre，主题只管文字配色。 */
.msg-assistant pre code,
.msg-assistant pre code.hljs {
  display: block;
  padding: 12px 14px;
  border: none;
  border-radius: 0;
  background: transparent;
  font-size: 13px;
  line-height: 1.55;
  overflow-x: auto;
  white-space: pre;
}

.code-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 8px 6px 14px;
  background: var(--surface-hover);
  border-bottom: 1px solid var(--hairline);
  font-size: 12px;
}

.code-lang {
  color: var(--ink-faint);
  text-transform: lowercase;
  letter-spacing: 0.03em;
}

.code-copy {
  background: none;
  border: none;
  color: var(--ink-dim);
  cursor: pointer;
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 12px;
  transition: color 140ms ease, background 140ms ease;
}

.code-copy:hover {
  color: var(--ink);
  background: var(--surface-hover);
}

/* ---------- 输入区 ---------- */

/* 不再单独给输入区一条背景色/上边框——跟消息区共用同一块背景，靠 .composer
   自己的边框和圆角来定义"这是个输入框"，不需要整条 footer 单独成一层。 */
footer {
  padding: 14px 20px;
  padding-bottom: max(14px, env(safe-area-inset-bottom));
}

/* 保存失败（localStorage 满了）的警告：跟输入框同宽，贴在它上面，保存成功就收起。 */
.storage-warning {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 720px;
  margin: 0 auto 10px;
  padding: 10px 14px;
  border: 1px solid var(--error-line);
  background: var(--error-soft);
  color: var(--error);
  border-radius: var(--radius-md);
  font-size: 13px;
  line-height: 1.5;
}

.storage-warning[hidden] {
  display: none;
}

.storage-warning button {
  flex-shrink: 0;
  padding: 6px 12px;
  font-size: 12.5px;
}

@media (max-width: 560px) {
  .storage-warning {
    flex-direction: column;
    align-items: stretch;
  }
}

.attachment-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-width: 720px;
  margin: 0 auto 10px;
}

.attachment-preview[hidden] {
  display: none;
}

.attachment-thumb {
  position: relative;
  width: 52px;
  height: 52px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--hairline);
}

.attachment-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.attachment-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  font-size: 12px;
  border: none;
  border-radius: 50%;
  /* 这个角标永远叠在缩略图上面，不是页面背景——背景故意写死成深色好压住任意
     图片内容，图标颜色也得跟着写死成白色，不能跟 --ink 走主题（浅色主题下
     --ink 是近黑色，黑字叠深色背景会看不见，这是从暖色主题搬过来时漏掉的坑）。 */
  background: rgba(10, 10, 14, 0.75);
  color: #fff;
  cursor: pointer;
}

.attachment-remove:hover {
  background: var(--error);
  color: #fff;
}

/* 两行布局（文本框在上，工具栏在下）——附件、模型选择都在同一张卡片里，跟
   ChatGPT/Claude/Perplexity 这类主流产品的输入框布局一致，不是摆在卡片外面。 */
.composer {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 720px;
  margin: 0 auto;
  padding: 10px 10px 8px 16px;
  background: var(--ground-2);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  transition: border-color 160ms ease;
}

.composer:focus-within {
  border-color: var(--violet-line);
}

.composer-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.composer-tools {
  display: flex;
  align-items: center;
  gap: 4px;
}

.composer-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

#input {
  width: 100%;
  resize: none;
  min-height: 26px;
  max-height: 200px;
  padding: 6px 0;
  background: transparent;
  color: var(--ink);
  border: none;
  font-size: 15px;
  line-height: 1.5;
  font-family: inherit;
}

#input::placeholder {
  color: var(--ink-faint);
}

#input:focus {
  outline: none;
}

.composer-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  transition: filter 160ms ease, opacity 160ms ease, transform 120ms ease;
}

/* `display: flex` above beats the UA [hidden] rule in the cascade, so #send/#stop
   toggling via the `hidden` attribute (see main.js setBusy) needs this spelled out again. */
.composer-btn[hidden] {
  display: none;
}

.composer-btn svg {
  width: 17px;
  height: 17px;
}

.composer-btn:active {
  transform: scale(0.94);
}

.composer-send {
  background: var(--violet);
  color: var(--ground);
}

.composer-send:hover:not(:disabled) {
  filter: brightness(1.08);
}

.composer-send:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.composer-stop {
  background: var(--ground);
  color: var(--ink);
  border: 1px solid var(--hairline);
}

.composer-stop:hover {
  border-color: var(--violet-line);
}

.composer-attach {
  background: none;
  color: var(--ink-faint);
}

.composer-attach:hover:not(:disabled) {
  color: var(--ink);
  background: var(--surface-hover);
}

.composer-attach:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* 生成图片模式打开时：按钮高亮成主色，输入框描边也换成主色，一眼能看出现在发出去的是图片描述。 */
.composer-image-mode[aria-pressed="true"],
.composer-image-mode[aria-pressed="true"]:hover:not(:disabled) {
  color: var(--violet-strong);
  background: var(--violet-soft);
}

.composer.is-image-mode {
  border-color: var(--violet-line);
}

/* 生成的图片比贴进来的参考图显示得大一些；要原图用消息下面的"下载"按钮（浏览器不让
   在新标签页里直接打开 data: 地址）。 */
.msg-generated-image {
  max-height: 420px;
}

/* 语音输入：录音中按钮变红并呼吸闪烁，旁边显示已录时长；识别中转圈、不可点。 */
.composer-mic.is-recording {
  color: var(--ground);
  background: var(--error);
  animation: mic-pulse 1.4s ease-in-out infinite;
}

.composer-mic.is-recording:hover:not(:disabled) {
  color: var(--ground);
  background: var(--error);
}

.composer-mic.is-transcribing svg {
  animation: mic-spin 0.9s linear infinite;
}

@keyframes mic-pulse {
  50% {
    box-shadow: 0 0 0 6px var(--error-soft);
  }
}

@keyframes mic-spin {
  to {
    transform: rotate(360deg);
  }
}

.mic-timer {
  align-self: center;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--error);
  margin-right: 2px;
}

.mic-timer[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .composer-mic.is-recording,
  .composer-mic.is-transcribing svg {
    animation: none;
  }
}

/* ---------- 设置弹层 ---------- */

.overlay[hidden] {
  display: none;
}

.overlay {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 10;
  animation: fade 160ms ease;
}


/* 内容多的面板（对话设置、设置里的数据区）在矮屏幕上会比视口还高，overlay 又是
   居中 flex，超出的部分既看不到也滚不到——"保存"按钮就被挡住了。限高 + 内部滚动。 */
.panel {
  width: 100%;
  max-width: 440px;
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 18px;
  padding: 24px;
  box-shadow: 0 32px 64px -24px rgba(10, 10, 20, 0.35);
  animation: rise 220ms cubic-bezier(0.16, 1, 0.3, 1);
}

.panel h2 {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}

.panel-head h2 {
  margin: 0;
}

.panel .panel-subtitle {
  margin: 3px 0 0;
  font-size: 12.5px;
  color: var(--ink-faint);
}

.panel-close {
  margin: -6px -8px 0 0;
}

/* 设置类面板：一节一节用细线隔开，每节一个小标题 + 一行灰色说明，长段解释收进 <details>。 */
.settings-panel {
  max-width: 480px;
}

.settings-section {
  padding: 16px 0;
  border-top: 1px solid var(--hairline);
}

.panel-head + .settings-section {
  border-top: none;
  padding-top: 10px;
}

.settings-section-title {
  display: block;
  margin: 0 0 8px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}

.panel .settings-hint,
.settings-hint {
  display: block;
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-faint);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--ink-dim);
  font: inherit;
  font-size: 12px;
  line-height: 1.4;
  cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease, background 140ms ease;
}

button.chip:hover {
  border-color: var(--violet-line);
  color: var(--violet-strong);
  background: var(--violet-soft);
}

.chip--static {
  cursor: default;
  background: var(--ground-2);
}

/* 今日用量卡片 */
.usage-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 14px;
  padding: 14px;
  background: var(--ground-2);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
}

.usage-card[hidden] {
  display: none;
}

.usage-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-dim);
}

.usage-meter-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 12.5px;
  color: var(--ink-dim);
}

.usage-meter-value {
  font-variant-numeric: tabular-nums;
}

.usage-meter-value strong {
  font-size: 15px;
  font-weight: 650;
  color: var(--ink);
}

.usage-unlimited {
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--violet-soft);
  color: var(--violet-strong);
  font-size: 11px;
  font-weight: 600;
}

.usage-bar,
.storage-meter {
  height: 6px;
  margin-top: 6px;
  border-radius: 999px;
  background: var(--hairline);
  overflow: hidden;
}

.usage-bar span,
.storage-meter span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--violet);
  transition: width 300ms ease;
}

.usage-bar.is-warning span,
.storage-meter.is-warning span {
  background: var(--amber);
}

.usage-bar.is-danger span {
  background: var(--error);
}

.usage-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* token 输入框 + 右侧"显示/隐藏"眼睛按钮 */
.token-field {
  position: relative;
}

.panel .token-field input {
  margin-bottom: 0;
  padding-right: 44px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
}

.token-reveal {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  background: none;
  border: none;
  border-radius: 8px;
  color: var(--ink-faint);
  cursor: pointer;
}

.token-reveal:hover,
.token-reveal[aria-pressed="true"] {
  color: var(--violet-strong);
  background: var(--violet-soft);
}

.token-reveal svg {
  width: 16px;
  height: 16px;
}

/* 开关（云端同步）：原生 checkbox 藏起来只负责状态和键盘，外观是一条胶囊 + 圆钮。 */
.switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.switch-row .settings-section-title {
  margin-bottom: 0;
}

.panel .switch-row .settings-hint {
  margin-top: 2px;
}

.switch {
  position: relative;
  flex-shrink: 0;
  display: inline-flex;
  cursor: pointer;
}

.panel .switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}

.switch-track {
  position: relative;
  width: 42px;
  height: 24px;
  border-radius: 999px;
  background: var(--hairline);
  transition: background 180ms ease;
}

.switch-track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  transition: transform 180ms cubic-bezier(0.16, 1, 0.3, 1);
}

.switch input:checked + .switch-track {
  background: var(--violet);
}

.switch input:checked + .switch-track::after {
  transform: translateX(18px);
}

.switch input:focus-visible + .switch-track {
  outline: 2px solid var(--violet);
  outline-offset: 2px;
}

.settings-more {
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--ink-dim);
}

.settings-more summary {
  cursor: pointer;
  color: var(--violet-strong);
  width: fit-content;
}

.panel .settings-more p {
  margin: 8px 0 0;
  font-size: 12.5px;
}

/* 对话设置：左边标题 + 说明，右边分段按钮；窄屏上下排。 */
.setting-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.setting-row + input + .setting-row {
  margin-top: 16px;
}

.setting-row-text {
  min-width: 0;
}

.setting-row-text .settings-section-title {
  margin-bottom: 0;
}

.panel .setting-row-text .settings-hint {
  margin-top: 2px;
}

.segmented {
  display: inline-flex;
  flex-shrink: 0;
  padding: 3px;
  gap: 2px;
  background: var(--ground-2);
  border: 1px solid var(--hairline);
  border-radius: 10px;
}

.segment {
  padding: 6px 11px;
  background: none;
  border: none;
  border-radius: 7px;
  color: var(--ink-dim);
  font: inherit;
  font-size: 12.5px;
  white-space: nowrap;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}

.segment:hover {
  color: var(--ink);
}

/* 选中态用实心主色——淡色底的选中态之前被嫌"一点都不明显"。 */
.segment[aria-checked="true"] {
  background: var(--violet);
  color: #fff;
  font-weight: 600;
  box-shadow: 0 2px 6px -2px var(--violet);
}

@media (max-width: 560px) {
  .setting-row {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }

  .segmented {
    display: flex;
  }

  .segment {
    flex: 1;
    padding: 7px 4px;
  }
}

.prompt-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: -6px;
}

/* 首次打开的欢迎页：底下不透出页面（还没有 token，后面也没什么可看的）。 */
.overlay--solid {
  background: var(--ground);
  backdrop-filter: none;
}

@media (prefers-color-scheme: light) {
  .overlay--solid {
    background: radial-gradient(1200px 600px at 50% -10%, var(--violet-soft), transparent 60%), var(--ground-2);
  }
}

@media (prefers-color-scheme: dark) {
  .overlay--solid {
    background: radial-gradient(1200px 600px at 50% -10%, var(--violet-soft), transparent 60%), var(--ground);
  }
}

.onboarding-panel {
  max-width: 420px;
  padding: 36px 32px 28px;
  text-align: center;
}

.onboarding-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin-bottom: 18px;
  border-radius: 16px;
  background: linear-gradient(155deg, var(--violet), #8b5cf6);
  color: #fff;
  box-shadow: 0 12px 28px -10px var(--violet);
}

.onboarding-mark svg {
  width: 26px;
  height: 26px;
}

.onboarding-panel h2 {
  font-size: 22px;
  margin-bottom: 8px;
}

.panel .onboarding-sub {
  margin: 0 auto 22px;
  max-width: 320px;
  font-size: 13.5px;
}

.onboarding-form {
  text-align: left;
}

.panel .onboarding-form input {
  margin-bottom: 10px;
  padding: 12px 14px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13.5px;
}

.panel input.is-invalid {
  border-color: var(--error);
}

.panel .field-note {
  margin: -2px 0 10px;
  font-size: 12.5px;
  color: var(--violet-strong);
}

.panel .field-note[hidden] {
  display: none;
}

/* 往上翻看前面的内容时，输入框上方居中出现"回到最新"。 */
.jump-latest {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-dim);
  font: inherit;
  font-size: 12.5px;
  box-shadow: var(--shadow-lift);
  cursor: pointer;
}

.jump-latest[hidden] {
  display: none;
}

.jump-latest svg {
  width: 14px;
  height: 14px;
}

.jump-latest:hover {
  color: var(--ink);
  border-color: var(--violet-line);
}

.md-fallback {
  white-space: pre-wrap;
}

.panel .field-error {
  margin: -2px 0 10px;
  font-size: 12.5px;
  color: var(--error);
}

.onboarding-submit {
  width: 100%;
  padding: 12px 18px;
}

.onboarding-submit:disabled {
  opacity: 0.7;
  cursor: progress;
}

.onboarding-features,
.welcome-list {
  list-style: none;
  margin: 26px 0 0;
  padding: 20px 0 0;
  border-top: 1px solid var(--hairline);
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: left;
}

.onboarding-features li,
.welcome-list li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-faint);
}

.onboarding-features strong,
.welcome-list strong {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}

.feature-icon {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: var(--violet-soft);
  color: var(--violet-strong);
}

.feature-icon svg {
  width: 16px;
  height: 16px;
}

.welcome-list {
  margin: 8px 0 22px;
  padding-top: 0;
  border-top: none;
}

.confirm-panel {
  max-width: 400px;
}

.panel p {
  margin: 0 0 14px;
  color: var(--ink-dim);
  font-size: 13px;
  line-height: 1.65;
}

.panel p code {
  color: var(--ink);
  background: var(--ground);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 12px;
}

.panel input {
  width: 100%;
  padding: 10px 12px;
  background: var(--ground-2);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  font-size: 14px;
  margin-bottom: 16px;
}

.panel input:focus {
  outline: none;
  border-color: var(--violet);
}

.field-label {
  display: block;
  margin: -4px 0 6px;
  font-size: 12px;
  color: var(--ink-dim);
}

.system-prompt-input {
  width: 100%;
  padding: 10px 12px;
  background: var(--ground-2);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 13.5px;
  line-height: 1.5;
  resize: vertical;
  margin-bottom: 16px;
}

.system-prompt-input:focus {
  outline: none;
  border-color: var(--violet);
}

.panel-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 16px;
  border-top: 1px solid var(--hairline);
}

.confirm-panel .panel-actions,
#welcome .panel-actions {
  border-top: none;
  padding-top: 4px;
}

button.primary {
  background: var(--violet);
  color: var(--ground);
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: filter 160ms ease;
}

button.primary:hover {
  filter: brightness(1.08);
}

button.secondary {
  background: var(--ground-2);
  color: var(--ink-dim);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  padding: 10px 18px;
  font-size: 14px;
  cursor: pointer;
  transition: border-color 160ms ease, color 160ms ease;
}

button.secondary:hover {
  border-color: var(--violet-line);
  color: var(--ink);
}

button.secondary.danger {
  color: var(--error);
}

button.secondary.danger:hover {
  border-color: var(--error-line);
  background: var(--error-soft);
}

button.primary.danger {
  background: var(--error);
}

/* ---------- 对话数据：导出 / 导入（设置面板里） ---------- */

.data-section .storage-meter {
  margin: 0 0 8px;
}


.panel .data-section p {
  margin: 0 0 10px;
  font-size: 12.5px;
}

.data-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.data-actions button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  font-size: 12.5px;
}

.data-actions button svg {
  width: 14px;
  height: 14px;
}

/* 上面的 display 会盖过 UA 的 [hidden] 规则（同步关着时"立即同步"之类不该出现）。 */
.data-actions button[hidden] {
  display: none;
}

.panel .data-section .storage-usage {
  color: var(--ink-dim);
}

.panel .data-section .storage-usage.is-warning {
  color: var(--amber-strong);
}

/* 选择器要比上面的 .panel .data-section p 更具体，不然上边距会被它的 margin 盖掉。 */
.panel .data-section .data-status {
  margin: 10px 0 0;
  color: var(--ink-dim);
}

.panel .data-section .data-status.is-error {
  color: var(--error);
}

/* ---------- 侧边栏：桌面端常驻，窄屏才变成滑出抽屉 ---------- */

.sidebar {
  width: 272px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 12px;
  /* 纯色而不是渐变——"现代 SaaS 那种干净感"用纯色面板更贴，渐变是上一版暖色
     主题的语言。侧边栏用 --ground-2（比主内容区的 --ground 稍暗一点点），
     两块面之间靠色差 + 右边框区分，不需要靠渐变增加"质感"。 */
  background: var(--ground-2);
  border-right: 1px solid var(--hairline);
  /* 不能用 overflow:hidden——模型下拉菜单现在挂在侧边栏里，绝对定位展开的
     下拉列表会被裁掉。侧边栏自己不需要靠 overflow 限制滚动，真正需要滚动的
     只有 .conversation-list（它自己有 min-height:0 + overflow-y:auto）。 */
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 4px;
}

.sidebar-brand h1 {
  flex: 1;
  min-width: 0;
  font-size: 15.5px;
  font-weight: 650;
  margin: 0;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar-close {
  display: none;
}

/* 收起整个侧边栏是桌面端才有意义的操作——窄屏本来就是滑出抽屉，用
   .sidebar-close（那个 X）关掉就够了，两套收起入口挤在一起没必要。 */
.sidebar-collapse-btn {
  display: flex;
}

/* 展开按钮默认不占地方——只有侧边栏被收起时才需要它，见下面
   @media (min-width: 901px) 里配合 body.sidebar-collapsed 一起生效。 */
.sidebar-expand-btn {
  display: none;
  position: fixed;
  top: 14px;
  left: 14px;
  z-index: 15;
}

.sidebar-new {
  width: 100%;
}

.sidebar-new-temporary {
  width: 100%;
  margin-top: -7px;
}

.conversation-temporary-badge {
  flex: 0 0 auto;
  margin-left: 7px;
  padding: 1px 6px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--ink-faint);
  font-size: 10px;
}

.temporary-chat-badge {
  flex: 0 0 auto;
  color: var(--ink-faint);
  font-size: 11px;
}

.file-attachment-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 10px 8px;
}

.attachment-file-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid var(--hairline);
  border-radius: 9px;
  background: var(--surface);
  color: var(--ink-dim);
  font-size: 12px;
}

.attachment-file-icon {
  display: inline-flex;
  flex: 0 0 18px;
  color: var(--ink-faint);
}

.attachment-file-icon svg {
  width: 18px;
  height: 18px;
}

.attachment-file-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attachment-file-remove {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}

.attachment-file-remove:hover {
  background: var(--surface-hover);
  color: var(--ink);
}

.prompt-template-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
}

.prompt-template-controls select,
.prompt-template-controls input {
  min-width: 150px;
  flex: 1 1 150px;
  padding: 7px 9px;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: var(--ground-2);
  color: var(--ink);
  font: inherit;
  font-size: 12px;
}

.conversation-search {
  position: relative;
}

.conversation-search-icon {
  position: absolute;
  left: 13px;
  top: 50%;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  color: var(--ink-faint);
  pointer-events: none;
}

.conversation-search input {
  width: 100%;
  padding: 9px 12px 9px 34px;
  background: var(--ground-2);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font: inherit;
  font-size: 13.5px;
}

.conversation-search input:focus {
  outline: none;
  border-color: var(--violet-line);
  background: var(--surface);
}

.conversation-search input::placeholder {
  color: var(--ink-faint);
}

.conversation-list {
  flex: 1;
  min-height: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* `display: flex` 上面那条会盖过 UA 的 [hidden] 规则，跟 .provider-list[hidden]
   是同一个坑，收起对话记录的时候得显式声明一遍。 */
.conversation-list[hidden] {
  display: none;
}

.conversation-views {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 4px;
  margin: 10px 0 8px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
}

.conversation-view {
  min-width: 0;
  padding: 6px 3px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-dim);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.conversation-view.is-active {
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
}

.row.is-search-match .msg {
  outline: 2px solid var(--violet);
  outline-offset: 3px;
}

/* .conversation-item 现在只是纯布局容器——真正可交互的是里面的两个 <button>
   （切换 / 删除），键盘 Tab 天然能到达，不用自己补 tabindex/keydown。 */
.conversation-item {
  display: flex;
  align-items: center;
  gap: 4px;
  border-radius: var(--radius-sm);
}

.conversation-switch {
  flex: 1;
  min-width: 0;
  display: block;
  text-align: left;
  padding: 9px 10px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--ink-dim);
  font: inherit;
  font-size: 13.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}

/* 搜索时只是内容命中的对话：标题下面一行小字，是命中位置附近的原文。 */
.conversation-snippet {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-weight: 400;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
}

.conversation-switch:hover,
.conversation-switch:active {
  background: var(--surface-hover);
  color: var(--ink);
}

.conversation-item.active .conversation-switch {
  background: var(--violet-soft);
  color: var(--violet-strong);
  font-weight: 600;
}

/* 删除按钮平时藏起来，悬停/键盘聚焦到这一行、或者是当前对话时才出现——每行都常亮
   一个 × 既乱又容易误点。触屏没有悬停，见文件末尾 (pointer: coarse) 里常显。 */
.conversation-more {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--ink-faint);
  border-radius: 6px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 140ms ease, color 140ms ease, background 140ms ease;
}

.conversation-more svg {
  width: 15px;
  height: 15px;
}

.conversation-item:hover .conversation-more,
.conversation-item:focus-within .conversation-more,
.conversation-item.active .conversation-more,
.conversation-more[aria-expanded="true"] {
  opacity: 1;
}

.conversation-more:hover,
.conversation-more[aria-expanded="true"] {
  color: var(--ink);
  background: var(--surface-hover);
}

/* 置顶的对话：标题前一枚小图钉，跟"置顶"分组标题呼应。 */
.conversation-item.is-pinned .conversation-switch::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--violet);
  vertical-align: middle;
}

/* 改名时这一行变成输入框，占满整行。 */
.conversation-rename {
  flex: 1;
  min-width: 0;
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--violet);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  box-shadow: 0 0 0 3px var(--violet-soft);
  outline: none;
}

/* "⋯"弹出的菜单：重命名 / 置顶 / 删除。 */
.conversation-menu {
  position: fixed;
  z-index: 60;
  min-width: 148px;
  padding: 5px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.16), 0 2px 6px rgba(15, 23, 42, 0.08);
  animation: conversation-menu-in 120ms ease-out;
}

.conversation-menu[hidden] {
  display: none;
}

@keyframes conversation-menu-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
}

.conversation-menu-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}

.conversation-menu-item svg {
  width: 15px;
  height: 15px;
  color: var(--ink-faint);
}

.conversation-menu-item:hover,
.conversation-menu-item:focus-visible {
  background: var(--surface-hover);
  outline: none;
}

.conversation-menu-item.is-danger,
.conversation-menu-item.is-danger svg {
  color: var(--error);
}

.conversation-menu-item.is-danger:hover,
.conversation-menu-item.is-danger:focus-visible {
  background: var(--error-soft);
}

.conversation-group {
  padding: 14px 10px 4px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-faint);
}

.conversation-group:first-child {
  padding-top: 4px;
}

.conversation-empty {
  padding: 16px 10px;
  font-size: 13px;
  color: var(--ink-faint);
  text-align: center;
}

.sidebar-footer-btn[hidden] {
  display: none;
}

/* 设置/使用说明始终贴在侧边栏最下面——原来靠 .conversation-list 的 flex:1
   把它挤到底部，但服务商/对话记录都能折叠起来了，折叠之后 .conversation-list
   不再撑开剩余空间，这条 margin-top:auto 才是真正跟"折没折叠"无关、始终生效
   的锚点：它会吃掉前面所有兄弟元素没用完的空间，把自己摁在容器最底下。 */
.sidebar-footer {
  margin-top: auto;
}

/* 返回首页入口（样式在首页的 /assets/shared/home-link-v1.css），跟上面几个按钮左对齐 */
.sidebar-home-link {
  margin: 8px 10px 2px;
}


.sidebar-footer-btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--ink-dim);
  font-size: 13.5px;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}

/* "接入客户端"是跳到另一页的链接（<a>），长得跟旁边的按钮一样。 */
a.sidebar-footer-btn {
  box-sizing: border-box;
  text-decoration: none;
}

.sidebar-footer-btn:hover,
.sidebar-footer-btn:active {
  background: var(--surface-hover);
  color: var(--ink);
}

.sidebar-footer-btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* 主内容区（顶栏 + 消息 + 输入框）跟侧边栏左右并排，自己是一列纵向 flex，
   结构上跟侧边栏出现之前的 body 是同一套（header/main/footer 纵向堆叠），
   只是外面多包了一层，好跟侧边栏横向并排。 */
.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* 新对话（还没有消息）时，欢迎语 + 输入框一起在视口正中间，跟 DeepSeek 网页版
   的空状态一样，不是常规的"消息区顶部 + 输入框贴底部"。发出第一条消息之后
   （main.js 一检测到 history 不再是空的）就切回正常布局，输入框回落到底部。
   只在桌面端做——桌面下 header 是 display:none，.app-main 的 flex 子元素实际
   只有 main/footer 两个，justify-content:center 正好把这两个当一组居中；窄屏
   header 会占一个真实的 flex 位置，center 会把它也拖离顶部，所以窄屏不做这个
   效果，保留原来"顶栏贴顶、下面正常滚动"的样子。 */
@media (min-width: 901px) {
  .app-main.app-main--empty {
    justify-content: center;
  }

  .app-main--empty main {
    flex: 0 1 auto;
    overflow: visible;
  }

  .app-main--empty .empty-state {
    margin: 0 auto 28px;
  }
}

.sidebar-toggle {
  display: none;
}

/* 窄屏（平板竖屏/手机）放不下"侧边栏 + 聊天区"两栏，侧边栏退化成盖在最上面的
   滑出抽屉：默认移出屏幕外（translateX(-100%)），点顶栏的按钮或侧边栏自己的
   收起按钮切一个 .open class 滑进来，同时铺一层半透明背景挡住后面的内容、
   点一下就能关掉。 */
@media (max-width: 900px) {
  /* 抽屉不是"侧边栏从屏幕外滑进来盖在聊天区上面"——用户实测跟 DeepSeek 对比
     发现人家是反过来的：侧边栏本来就静静铺在下面一整片（没有自己的圆角/
     阴影），平时被同样铺满屏幕的 .app-main 盖住看不见；点开抽屉，动的是
     .app-main——它缩小、右移，变成一张带圆角阴影的"浮动窗口"，露出原本
     压在它下面的侧边栏。所以侧边栏自己不需要任何位移/形变，只要老老实实
     待在原地，该动画的是 .app-main（见下面）。 */
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 2;
    width: min(280px, 82vw);
  }

  /* .app-main 圆角拐弯露出来的那一小片"缺口"，背后得有点颜色垫着才看得出来
     （不然就是白露白，等于没裁）——但直接把 .sidebar 本身撑宽 28px 补这个
     颜色，会把它的内容（对话记录的删除按钮、"服务商"这些靠右对齐的东西）
     也一起挤宽，挤到 .app-main 直边覆盖的区域里被盖住一截。改成一条纯背景
     色的"垫片"，只负责在侧边栏本身宽度之外再垫 28px 颜色，不参与侧边栏的
     内容布局，两不耽误。 */
  .sidebar::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 100%;
    width: 28px;
    background: var(--ground-2);
  }

  .sidebar-close {
    display: flex;
  }

  /* 窄屏下侧边栏默认收起，得留一条能点开它的顶栏——桌面端不需要，见上面
     header 的默认 display: none。 */
  .chat-header {
    display: flex;
  }

  .sidebar-toggle {
    display: flex;
  }

  .header-new-chat {
    display: flex;
  }

  /* 窄屏已经是滑出抽屉 + 顶栏汉堡按钮这一套了，桌面端"整个收起侧边栏"的
     入口和悬浮展开按钮在这里都没有意义，藏起来。 */
  .sidebar-collapse-btn,
  .sidebar-expand-btn {
    display: none;
  }

  /* 平时盖住整个屏幕（包括侧边栏那部分）——z-index 比侧边栏高、背景不透明，
     静止状态下天然把侧边栏整个遮住，不需要侧边栏自己再做"隐藏"的动画。
     点开抽屉时缩小 + 右移，露出原本盖住的侧边栏，边角/阴影让它看起来像一张
     浮在侧边栏上层的独立窗口，而不是简单叠一层半透明遮罩——参考 DeepSeek
     实测比对：聊天区亮度基本不变（没有额外遮罩调暗），层次感全靠这张
     "窗口"自己的圆角 + 阴影 + 缩小挪开来表现。点这张窗口能关掉抽屉，见
     main.js 里 #appMain 的 click 监听。 */
  .app-main {
    position: relative;
    z-index: 3;
    background: var(--ground);
    transition: transform 240ms cubic-bezier(0.16, 1, 0.3, 1), border-radius 240ms ease, box-shadow 240ms ease;
  }

  /* 底下那层（侧边栏）是铺满整个屏幕高度的静态背景，露出来的部分应该跟它
     严丝合缝地贴在一起，不能有缝。之前用 scaleX 收一点宽度，但 scaleX 默认
     从中心缩放，卡片左边缘会往右缩进去一截，跟侧边栏右边缘之间露出一条
     看得见的缝（"左边是左边、右边是右边"，两块明显分开）。干脆不缩放了，
     只做水平位移——卡片左边缘正好精确落在侧边栏边缘上，贴合、没有缝隙，
     高度也天然还是 100%。 */
  .sidebar.open ~ .app-main {
    transform: translateX(min(280px, 82vw));
    border-radius: 20px;
    box-shadow: var(--shadow-lift);
    overflow: hidden;
    /* 光靠 overflow:hidden 在这儿不裁——.app-main 的直接子元素（header/main/
       footer）各自带着 position:relative + z-index（另一条通用规则），自己
       建了层叠上下文，跟这里的 transform 撞在一起时，Safari 实测不会把它们
       按父元素的圆角裁掉，边缘看着还是直的。clip-path 是纯几何裁切，不受
       子元素自己开不开层叠上下文影响，实测能裁对——同时留着 overflow:hidden
       给不支持 clip-path 的场合兜底。 */
    clip-path: inset(0 round 20px);
  }
}

/* 桌面端把整个侧边栏收起来腾地方给聊天区——跟窄屏那套滑出抽屉是两回事
   （那个默认收起、靠顶栏汉堡按钮展开），这里默认展开、由 body.sidebar-collapsed
   这个 JS 切的 class 控制，只在桌面宽度生效。 */
@media (min-width: 901px) {
  body.sidebar-collapsed .sidebar {
    display: none;
  }

  body.sidebar-collapsed .sidebar-expand-btn {
    display: flex;
  }
}

/* 触屏设备（不管屏幕多宽，包括触屏笔记本/平板分屏）把关键点按目标撑到接近
   44px 的推荐触控尺寸——鼠标精度下 34px 的图标按钮完全够用，手指点这个尺寸
   容易点偏，两种输入方式给两种尺寸，用 pointer:coarse 而不是屏幕宽度判断，
   判断的是"这是不是用手指点"，不是"屏幕多大"。 */
@media (pointer: coarse) {
  .icon-btn,
  .composer-btn {
    width: 44px;
    height: 44px;
  }

  .msg-action {
    width: 32px;
    height: 32px;
  }

  .msg-action svg {
    width: 15px;
    height: 15px;
  }

  .attachment-remove {
    width: 22px;
    height: 22px;
    font-size: 14px;
  }

  .conversation-more {
    width: 32px;
    height: 32px;
    opacity: 1;
  }

  .sidebar-footer-btn,
  .conversation-switch,
  .provider-switch,
  .model-trigger {
    min-height: 44px;
  }

  .model-option {
    min-height: 40px;
  }
}

/* ---------- 键盘快捷键说明 ---------- */

.shortcut-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}

.shortcut-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--hairline);
  font-size: 14px;
  color: var(--ink);
}

.shortcut-list li:last-child {
  border-bottom: none;
}

.shortcut-keys {
  display: inline-flex;
  gap: 4px;
  flex-shrink: 0;
}

.shortcuts-panel kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 24px;
  padding: 0 7px;
  border: 1px solid var(--hairline);
  border-bottom-width: 2px;
  border-radius: 6px;
  background: var(--ground-2);
  color: var(--ink);
  font: 600 12px/1 ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

.shortcut-foot {
  margin: 14px 0 0;
  font-size: 12.5px;
  color: var(--ink-faint);
}

/* 触屏设备没有键盘可言，侧栏底部的"快捷键"入口藏起来。 */
@media (pointer: coarse) {
  .sidebar-footer-btn--keyboard {
    display: none;
  }
}

/* ---------- 数学公式（math.js，KaTeX 输出的 MathML，浏览器原生排版） ---------- */

.msg-assistant math {
  font-size: 1.08em;
  /* 有 OpenType MATH 表的字体，积分号、根号这类才能按公式高度伸缩；系统没有就退回通用的 math。 */
  font-family: "STIX Two Math", "Cambria Math", "Latin Modern Math", math;
}

/* 独占一行的公式：居中，太宽的横向滚动，不撑破气泡。 */
.math-display {
  display: block;
  margin: 0.6em 0;
  overflow-x: auto;
  overflow-y: hidden;
  text-align: center;
}

/* ---------- 流程图（```mermaid，mermaid.html 沙箱 iframe 里画） ---------- */

.diagram-block {
  margin: 0.8em 0;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  background: var(--surface);
  overflow: hidden;
}

.diagram-block .code-bar {
  border-bottom: 1px solid var(--hairline);
}

.diagram-actions {
  display: flex;
  gap: 4px;
}

.diagram-frame {
  display: block;
  width: 100%;
  height: 160px;
  border: none;
  background: transparent;
}

.diagram-frame[hidden] {
  display: none;
}

/* 还在画：先占一块高度，上面一道流光，避免图出来时整段文字往下跳一大截。 */
.diagram-block.is-loading .diagram-frame {
  background: linear-gradient(90deg, transparent, var(--surface-hover), transparent) 0 0 / 200% 100%;
  animation: diagram-shimmer 1.4s linear infinite;
}

@keyframes diagram-shimmer {
  to {
    background-position: -200% 0;
  }
}

.diagram-source {
  margin: 0;
  border-radius: 0;
}

.diagram-source[hidden] {
  display: none;
}

.diagram-note {
  padding: 8px 14px;
  border-top: 1px solid var(--hairline);
  font-size: 12.5px;
  color: var(--ink-faint);
}

.diagram-note[hidden] {
  display: none;
}
