/* MyNexus 知识库控制台（浅色主题） */
:root {
  --bg: #f5f6f8; --panel: #ffffff; --border: #e5e7eb; --border-strong: #d1d5db;
  --text: #111827; --muted: #6b7280; --primary: #2563eb; --primary-soft: #eff6ff;
  --danger: #dc2626; --danger-soft: #fef2f2; --ok: #16a34a; --warn: #b45309;
  --warn-soft: #fffbeb; --radius: 10px;
  /* 全局字号基准（16 = 默认）。所有字号都写成 calc(n / 16 * 1rem)，
     所以改 --fs-base 一个值，整站文字按比例缩放（设置页「界面字体」即时修改它） */
  --fs-base: 16px;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
html { font-size: var(--fs-base, 16px); }   /* 1rem 的锚点，JS 只改这一个变量 */
body {
  margin: 0; background: var(--bg); color: var(--text);
  font-family: -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  font-size: 1rem; line-height: 1.55;
  display: flex; flex-direction: column; overflow: hidden;
}
code, .mono { font-family: ui-monospace, Menlo, Consolas, monospace; }
.muted { color: var(--muted); font-size: calc(12 / 16 * 1rem); font-weight: 400; }
.spacer { flex: 1; }

/* ---------- 顶栏 ---------- */
.topbar {
  display: flex; align-items: center; gap: 14px; padding: 8px 16px;
  background: var(--panel); border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.brand { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: calc(15 / 16 * 1rem); white-space: nowrap; }
.brand .logo { width: calc(20 / 16 * 1rem); height: calc(20 / 16 * 1rem); border-radius: 5px; flex: none; display: block; }
.brand-sub { margin-left: 8px; font-weight: 400; font-size: calc(12 / 16 * 1rem); color: var(--muted); }
.nav { display: flex; gap: 2px; }
.nav-btn {
  border: none; background: transparent; padding: 7px 13px; border-radius: 8px;
  font: inherit; color: var(--muted); cursor: pointer; white-space: nowrap;
}
.nav-btn:hover { background: #f3f4f6; color: var(--text); }
.nav-btn.active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
/* 侧边栏精简导航：默认隐藏，embed=1 时替换掉全功能导航 */
.nav-embed { display: none; }
body.embed #nav { display: none; }
body.embed #navEmbed { display: flex; }
body.embed .modebar { display: none; }   /* 三个模式已提升为一级 Tab */
.auth { margin-left: auto; display: flex; align-items: center; gap: 6px; }
/* 鉴权关闭时令牌控件被隐藏，只剩健康点 —— 让它跟着品牌行右对齐，不要单独占一行 */
body.no-auth .auth { margin-left: auto; }
.dot { font-size: calc(12 / 16 * 1rem); color: #d1d5db; }
.tmsg { font-size: calc(12 / 16 * 1rem); color: var(--ok); max-width: 240px; }
.tmsg.warn { color: var(--danger); }

/* ---------- 表单控件 ---------- */
input, select, textarea, .btn {
  font: inherit; padding: 7px 10px; border: 1px solid var(--border);
  border-radius: 8px; background: #fff; color: var(--text); outline: none;
}
input:focus, select:focus, textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(37,99,235,.1); }
input[type="checkbox"] { width: auto; padding: 0; }
input[disabled] { background: #f9fafb; color: var(--muted); }
.btn { cursor: pointer; background: #fff; white-space: nowrap; }
.btn:hover { border-color: var(--border-strong); }
.btn.primary { background: var(--primary); color: #fff; border-color: var(--primary); }
.btn.primary:hover { background: #1d4ed8; }
.btn.danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn.danger[disabled] { opacity: .45; cursor: not-allowed; }
.btn.ghost { background: transparent; }
.btn.sm { padding: 4px 9px; font-size: calc(12 / 16 * 1rem); }
.btn.sm[disabled] { opacity: .45; cursor: not-allowed; }
.chk { display: inline-flex; align-items: center; gap: 6px; font-size: calc(13 / 16 * 1rem); color: var(--text); cursor: pointer; }
.sel { padding: 6px 8px; font-size: calc(13 / 16 * 1rem); }
.search { flex: 1; min-width: 160px; }

/* ---------- 主区域 ---------- */
main { flex: 1; min-height: 0; padding: 14px 16px; display: flex; flex-direction: column; }
.panel { display: none; }
#tab-qa.active { display: flex; flex-direction: column; flex: 1; min-height: 0; }
#tab-kb.active, #tab-settings.active, #tab-system.active { display: block; flex: 1; min-height: 0; overflow-y: auto; }
/* 内容列居中（宽屏不贴左），卡片宽度上限 1080 */
#tab-settings.active > *, #tab-system.active > * { max-width: 1080px; margin-left: auto; margin-right: auto; }

/* 卡片 */
.card {
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 16px; margin-bottom: 14px;
}
.card h3 { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 6px; font-size: calc(15 / 16 * 1rem); }
.card h3 .test-btn { margin: 0; flex: none; }
.card .hint { margin: 0 0 10px; color: var(--muted); font-size: calc(12 / 16 * 1rem); }

/* ---------- 设置页（P2-2）：三大分类 Tab + 手风琴卡片 + 服务状态灯 ---------- */
.set-tabs { display: flex; gap: 6px; margin: 0 0 12px; border-bottom: 1px solid var(--border); }
.set-tab {
  padding: 7px 14px; border: 1px solid transparent; border-bottom: none; background: transparent;
  border-radius: 8px 8px 0 0; cursor: pointer; font: inherit; color: var(--muted);
}
.set-tab:hover { color: var(--text); }
.set-tab.active { color: var(--primary); border-color: var(--border); background: var(--panel); font-weight: 600; }

/* 手风琴卡片用原生 <details>：收起时只显示「服务名 + 状态灯」 */
.card.acc { padding: 0; overflow: hidden; }
.card.acc > summary {
  display: flex; align-items: center; gap: 8px; padding: 12px 16px;
  cursor: pointer; list-style: none; user-select: none;
}
.card.acc > summary::-webkit-details-marker { display: none; }
.card.acc > summary::after {
  content: '▸'; margin-left: auto; color: var(--muted); font-size: calc(12 / 16 * 1rem);
  transition: transform .15s ease;
}
.card.acc[open] > summary::after { transform: rotate(90deg); }
.card.acc > summary:hover { background: var(--primary-soft); }
.acc-title { font-size: calc(15 / 16 * 1rem); font-weight: 600; }
.acc-sub { font-size: calc(12 / 16 * 1rem); }
.acc-body { padding: 12px 16px 14px; border-top: 1px solid var(--border); }
.acc-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--border);
}

/* 问答输入框旁的麦克风占位（P2 Task 3） */
.btn.mic { padding: 6px 10px; font-size: calc(15 / 16 * 1rem); line-height: 1; }

/* 服务状态灯：绿=在线 红=离线 灰=未启用（卡片收起时依然可见，15s 自动刷新） */
.sdot { font-size: calc(12 / 16 * 1rem); color: #d1d5db; flex: none; }
.sdot.ok { color: var(--ok); }
.sdot.down { color: var(--danger); }
.sdot.idle { color: #d1d5db; }

.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.msg { color: var(--ok); font-size: calc(13 / 16 * 1rem); min-height: 18px; margin-top: 6px; }
.err { color: var(--danger); }

/* ---------- 问答 ---------- */
.modebar { display: flex; gap: 8px; margin-bottom: 10px; flex-shrink: 0; }
.mode-btn {
  flex: 1; text-align: left; padding: 8px 12px; border: 1px solid var(--border);
  background: var(--panel); border-radius: var(--radius); cursor: pointer; font: inherit;
  display: flex; flex-direction: column; gap: 1px; min-width: 0;
}
.mode-btn b { font-size: calc(13 / 16 * 1rem); font-weight: 600; }
.mode-btn span { font-size: calc(11 / 16 * 1rem); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mode-btn:hover { border-color: var(--border-strong); }
.mode-btn.active { border-color: var(--primary); background: var(--primary-soft); }
.mode-btn.active b { color: var(--primary); }

.chat {
  flex: 1; min-height: 0; overflow-y: auto; background: var(--panel);
  border: 1px solid var(--border); border-radius: 12px; padding: 16px; margin-bottom: 10px;
}
.empty-hint { text-align: center; color: var(--muted); margin-top: 12vh; }
.eh-title { font-size: calc(16 / 16 * 1rem); color: var(--text); margin-bottom: 4px; }
.eh-sub { font-size: calc(13 / 16 * 1rem); }

.msg-row { margin-bottom: 16px; }
.msg-row.user { display: flex; justify-content: flex-end; }
.msg-row.user .bubble {
  background: var(--primary); color: #fff; padding: 8px 13px; border-radius: 12px 12px 2px 12px;
  max-width: 82%; white-space: pre-wrap; word-break: break-word;
}
.msg-row.assistant .bubble { max-width: 100%; }
.bubble { word-break: break-word; }

/* Markdown 渲染 */
.md { white-space: normal; }
.md > :first-child { margin-top: 0; }
.md h1, .md h2 { font-size: calc(17 / 16 * 1rem); margin: 14px 0 6px; }
.md h3, .md h4 { font-size: calc(15 / 16 * 1rem); margin: 12px 0 5px; }
.md p { margin: 6px 0; }
.md table { border-collapse: collapse; width: 100%; margin: 8px 0; font-size: calc(13 / 16 * 1rem); }
.md th, .md td { border: 1px solid var(--border); padding: 6px 9px; text-align: left; vertical-align: top; }
.md th { background: #f3f4f6; font-weight: 600; }
.md ul, .md ol { margin: 6px 0; padding-left: 22px; }
.md li { margin: 2px 0; }
.md code { background: #f3f4f6; padding: 1px 5px; border-radius: 4px; font-size: calc(12.5 / 16 * 1rem); }
.md pre { background: #f8fafc; border: 1px solid var(--border); padding: 10px 12px; border-radius: 8px; overflow-x: auto; }
.md pre code { background: none; padding: 0; }
.md blockquote { border-left: 3px solid var(--border-strong); margin: 8px 0; padding: 2px 12px; color: var(--muted); }
.md hr { border: none; border-top: 1px solid var(--border); margin: 12px 0; }
.md a { color: var(--primary); }

.thinking { margin: 0 0 8px; border: 1px dashed var(--border-strong); border-radius: 8px; background: #fafafa; }
.thinking summary { cursor: pointer; padding: 5px 10px; font-size: calc(12 / 16 * 1rem); color: var(--muted); }
.thinking .t-body { padding: 0 10px 8px; font-size: calc(12 / 16 * 1rem); color: var(--muted); white-space: pre-wrap; max-height: 220px; overflow-y: auto; }

.fallback { background: var(--warn-soft); border: 1px solid #fde68a; color: #92400e; padding: 10px 12px; border-radius: 8px; }
.sources { margin-top: 10px; border-top: 1px dashed var(--border); padding-top: 6px; max-height: 220px; overflow-y: auto; }
.sources summary { cursor: pointer; font-size: calc(12 / 16 * 1rem); color: var(--muted); }
.src { border-left: 3px solid var(--border); padding: 3px 10px; margin: 6px 0; font-size: calc(13 / 16 * 1rem); }
.src .snip { color: var(--muted); font-size: calc(12 / 16 * 1rem); margin-top: 2px; }
.src a { color: var(--primary); text-decoration: none; }

/* 输入区：textarea 占满一行（默认 4 行），下面一条紧凑操作区（左上传 / 右发送）。
   竖向排布是为了窄屏（420px 侧边栏）下两者永不互相挤压。 */
.askbar { display: flex; flex-direction: column; gap: 6px; flex-shrink: 0; }
.askbar textarea { width: 100%; resize: none; max-height: 33vh; overflow-y: auto; line-height: 1.5; }
.ask-actions { display: flex; align-items: center; gap: 8px; }
.ask-actions .attach { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
@media (max-width: 720px) {
  .askbar { gap: 5px; }
  .ask-actions { gap: 6px; }
}

/* 轻提示（上传结果等） */
.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%) translateY(10px);
  background: #111827; color: #fff; padding: 8px 14px; border-radius: 10px;
  font-size: calc(12.5 / 16 * 1rem); opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s;
  z-index: 60; max-width: 80vw; text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.ok { background: #16a34a; }
.toast.err { background: #b91c1c; }

/* 嵌入侧边栏（?embed=1）：浏览器已显示扩展标题，页内不再重复品牌名 */
body.embed .brand { display: none; }
body.embed .topbar { padding-left: 8px; }
body.embed .nav { margin-left: 0; }

/* ---------- 侧边栏（窄屏）专属布局：与宽屏控制台彻底解耦 ----------
 * 字号不由这里写死：embed 下 app.js 会强制 --fs-base = 14px（忽略 Web 端"特大"设置），
 * 保证窄屏信息密度；这里只负责"把宽屏布局压成单列、列表满宽"。 */
body.embed main { padding: 10px 8px; }
body.embed .card { padding: 12px 10px; border-radius: 10px; }
/* 1) 工具栏竖排：窄屏横排必然挤成一团（图10 的拥挤根因） */
body.embed .kbtoolbar { flex-direction: column; align-items: stretch; gap: 6px; margin-bottom: 8px; }
body.embed .kbtoolbar .search,
body.embed .kbtoolbar .sel,
body.embed .kbtoolbar .btn { width: 100%; flex: none; min-width: 0; }
body.embed .kbbar { flex-wrap: wrap; gap: 6px; padding: 8px 10px; border-radius: 0; }
body.embed .kbstats { padding: 6px 10px; border-left: 0; border-right: 0; }
/* 2) 列表项满宽：去掉左右多余留白，卡片顶到边缘 */
body.embed .kblist { border-left: 0; border-right: 0; border-radius: 0; }
body.embed .kb-head { padding: 10px 8px; gap: 8px; }
body.embed .kb-expand { padding: 0 8px 10px; }
body.embed .kb-bubble { max-width: 100%; }
body.embed .kb-actions { gap: 5px; }
body.embed .kb-actions .btn { padding: 4px 8px; }
body.embed .kb-right { text-align: right; }

/* ---------- 知识库 ---------- */
.kbtoolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }
.kbbar {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px; background: var(--panel);
  border: 1px solid var(--border); border-radius: 10px 10px 0 0; border-bottom: none;
}
.kbstats { padding: 6px 12px; background: var(--panel); border-left: 1px solid var(--border); border-right: 1px solid var(--border); font-size: calc(12 / 16 * 1rem); color: var(--muted); }
.kblist { background: var(--panel); border: 1px solid var(--border); border-radius: 0 0 10px 10px; overflow: hidden; }
/* 列表项 = 可展开卡片（手风琴），不再是"点击弹抽屉" */
.kbrow { border-bottom: 1px solid var(--border); }
.kbrow:last-child { border-bottom: none; }
.kb-head { display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: pointer; }
.kbrow:hover .kb-head { background: #f9fafb; }
.kbrow.open .kb-head { background: #fbfcfe; }
.kbrow.sel .kb-head { background: var(--primary-soft); }
.kbrow .cbx { flex-shrink: 0; }
.kb-chevron { flex-shrink: 0; width: 12px; color: var(--muted); font-size: calc(10 / 16 * 1rem); transition: transform .15s; user-select: none; }
.kbrow.open .kb-chevron { transform: rotate(90deg); }
.kb-main { flex: 1; min-width: 0; }
.kb-title { font-size: calc(13.5 / 16 * 1rem); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-sub { font-size: calc(11.5 / 16 * 1rem); color: var(--muted); margin-top: 2px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.badge {
  display: inline-block; padding: 0 6px; border-radius: 4px; font-size: calc(11 / 16 * 1rem);
  background: #f3f4f6; color: #4b5563; border: 1px solid var(--border);
}
.badge.deepseek { background: #eef2ff; color: #4338ca; border-color: #c7d2fe; }
.badge.doubao { background: #fdf2f8; color: #be185d; border-color: #fbcfe8; }
.badge.kimi { background: #ecfdf5; color: #047857; border-color: #a7f3d0; }
.badge.qianwen { background: #f5f3ff; color: #6d28d9; border-color: #ddd6fe; }
.badge.doc { background: #fffbeb; color: #b45309; border-color: #fde68a; }
.badge.del { background: var(--danger-soft); color: var(--danger); border-color: #fecaca; }
/* ★ AI 打标标签胶囊徽章（浅蓝、圆角、小号） */
.tagrow { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; }
.tag {
  display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: calc(11 / 16 * 1rem);
  background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe;
}
/* ★ 语义分类徽章（绿色 = 20 类人工枚举，这才是"标签"；蓝色 .tag 是"关键词"） */
.topic {
  display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: calc(11 / 16 * 1rem);
  background: #ecfdf5; color: #047857; border: 1px solid #a7f3d0; font-weight: 600;
}
/* ★ 实体徽章（紫色，区别于蓝色 tag；点击弹关联会话） */
.ent {
  display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: calc(11 / 16 * 1rem);
  background: #faf5ff; color: #7c3aed; border: 1px solid #ddd6fe; cursor: pointer;
}
.ent:hover { background: #f3e8ff; border-color: #c4b5fd; }
/* ★ 知识图谱面板：高频实体网格 */
.graphgrid { display: flex; flex-wrap: wrap; gap: 8px; padding: 4px 0; }
.gent {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 999px;
  font-size: calc(12 / 16 * 1rem); background: #faf5ff; color: #7c3aed; border: 1px solid #ddd6fe; cursor: pointer;
}
.gent:hover { background: #f3e8ff; border-color: #c4b5fd; }
.gent em { font-style: normal; font-size: calc(10 / 16 * 1rem); color: #a78bfa; }
/* ★ 实体关联弹窗 */
.ent-rel-title { font-weight: 600; font-size: calc(12 / 16 * 1rem); margin: 8px 0 4px; color: var(--muted); }
.ent-rel-row { padding: 3px 0; font-size: calc(12.5 / 16 * 1rem); }
.ent-conv-row { padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 6px; cursor: pointer; font-size: calc(12 / 16 * 1rem); word-break: break-all; }
.ent-conv-row:hover { background: #faf5ff; }
.kb-right { text-align: right; flex-shrink: 0; font-size: calc(11.5 / 16 * 1rem); color: var(--muted); }
.pager { display: flex; gap: 8px; align-items: center; justify-content: center; padding: 12px 0; }

/* ---------- 知识库：手风琴原地展开 ---------- */
.kb-expand { padding: 0 12px 12px; }
.kb-expand[hidden] { display: none; }
.kb-msgs { max-height: 44vh; overflow-y: auto; padding: 10px 0 2px; }
.kb-msg { margin-bottom: 10px; display: flex; flex-direction: column; }
.kb-msg.user { align-items: flex-end; }
.kb-msg.assistant { align-items: flex-start; }
.kb-role { font-size: calc(11 / 16 * 1rem); color: var(--muted); margin-bottom: 3px; display: flex; gap: 6px; align-items: center; }
.kb-bubble { font-size: calc(13 / 16 * 1rem); line-height: 1.62; padding: 7px 11px; border-radius: 10px; max-width: 92%; word-break: break-word; }
.kb-msg.user .kb-bubble { background: var(--primary-soft); border: 1px solid #dbeafe; border-bottom-right-radius: 3px; white-space: pre-wrap; }
.kb-msg.assistant .kb-bubble { background: #f9fafb; border: 1px solid var(--border); border-bottom-left-radius: 3px; }
/* 上传资料（role=doc）：琥珀色气泡 + 原文换行，区别于 AI 回答的 Markdown 渲染 */
.kb-msg.doc .kb-bubble { background: #fffbeb; border: 1px solid #fde68a; white-space: pre-wrap; }
.kb-msg.deleted .kb-bubble { opacity: .55; }
.kb-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; padding-top: 8px; border-top: 1px dashed var(--border); }
.kb-actions .muted { margin-left: auto; }
.kb-loading, .kb-empty { font-size: calc(12 / 16 * 1rem); color: var(--muted); padding: 10px 0; }

/* ---------- 设置 ---------- */
.form2 { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px 14px; }
.form2 label, label.full { display: flex; flex-direction: column; gap: 4px; font-size: calc(12 / 16 * 1rem); color: var(--muted); }
/* 只给文本类输入框铺满，checkbox 不能设 100%（否则会被拉成一个大方块、把文字挤到右边） */
.form2 label input:not([type="checkbox"]) { width: 100%; font-size: calc(13 / 16 * 1rem); }
/* 勾选行横跨整行。⚠️ 必须写 1 / -1 而不是 span 2：后者会在单列布局（窄屏 / 侧边栏）
   下**凭空造出一条隐式列**（实测 420px 宽被切成 170px+151px 两列，输入框被挤扁）。
   1 / -1 只跨显式轨道，单列时就是单列。 */
.form2 label.chk { flex-direction: row; align-items: center; gap: 6px; color: var(--text); font-size: calc(13 / 16 * 1rem); grid-column: 1 / -1; }
.form2 label.chk input[type="checkbox"] { width: auto; margin: 0; flex-shrink: 0; }
label.full { margin-top: 10px; }
label.full textarea { width: 100%; resize: vertical; font-size: calc(13 / 16 * 1rem); }
.mt { margin-top: 12px; }
.savebar { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }

/* ---------- 系统 ---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
.stat { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; background: #fcfcfd; }
.stat .k { font-size: calc(11.5 / 16 * 1rem); color: var(--muted); }
.stat .v { font-size: calc(20 / 16 * 1rem); font-weight: 700; margin-top: 2px; }
.tbl { width: 100%; border-collapse: collapse; }
.tbl th, .tbl td { text-align: left; padding: 7px 8px; border-bottom: 1px solid var(--border); font-size: calc(12.5 / 16 * 1rem); }
.tbl th { color: var(--muted); font-weight: 500; }
.uploadbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.uploadbar input[type="text"], .uploadbar #fileTitle { flex: 1; min-width: 180px; }
a.btn { text-decoration: none; }

/* ---------- 窄屏（浏览器侧边栏 / 小窗） ---------- */
@media (max-width: 720px) {
  .topbar { flex-wrap: wrap; gap: 8px; padding: 8px 10px; }
  .brand-sub { display: none; }
  .nav { order: 3; width: 100%; }
  .nav-btn { flex: 1; padding: 6px 4px; font-size: calc(13 / 16 * 1rem); }
  .auth { margin-left: 0; width: 100%; }
  body.no-auth .auth { width: auto; margin-left: auto; }
  .auth #token { flex: 1; width: auto; }
  main { padding: 10px; }
  .modebar { flex-direction: column; gap: 6px; }
  .mode-btn { padding: 6px 10px; }
  .kbtoolbar .sel { flex: 1; }
  .kb-msgs { max-height: 60vh; }
  .kb-chevron { width: 14px; }
  .form2 { grid-template-columns: 1fr; }
  #tab-settings.active > *, #tab-system.active > * { max-width: none; }
}

/* ---------- 会话详情弹窗（点「查看」页内弹出，替代新开标签页） ----------
 * 侧边栏是 iframe 复用本页：position:fixed 相对 iframe 视口，所以窄屏只需收窄宽度与边距。 */
.modal-mask {
  position: fixed; inset: 0; z-index: 60; display: none;
  background: rgba(17, 24, 39, .45); padding: 24px;
  align-items: center; justify-content: center;
}
.modal-mask.open { display: flex; }
.modal {
  display: flex; flex-direction: column; width: min(760px, 100%); max-height: min(84vh, 760px);
  background: #fff; border-radius: 12px; box-shadow: 0 24px 64px rgba(17, 24, 39, .32);
  overflow: hidden;
}
.m-head {
  display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px;
  border-bottom: 1px solid var(--border); background: #fbfcfe;
}
.m-titles { min-width: 0; flex: 1; }
.m-title { font-weight: 700; font-size: calc(15 / 16 * 1rem); line-height: 1.35; word-break: break-word; }
.m-meta { margin-top: 3px; font-size: calc(11.5 / 16 * 1rem); color: var(--muted); word-break: break-all; }
.m-close {
  flex: none; width: 28px; height: 28px; line-height: 1; padding: 0; border-radius: 8px;
  border: 1px solid var(--border); background: #fff; color: var(--muted);
  font-size: calc(17 / 16 * 1rem); cursor: pointer;
}
.m-close:hover { background: #f3f4f6; color: var(--text); }
.m-body { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 14px; }
/* 弹窗里复用列表气泡样式，但去掉手风琴的 44vh 上限（滚动交给 .m-body） */
.m-body .kb-msgs { max-height: none; overflow: visible; padding: 0; }
.m-foot {
  display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
  padding: 10px 14px; border-top: 1px solid var(--border); background: #fbfcfe;
}
.m-foot .muted { margin-left: auto; font-size: calc(11.5 / 16 * 1rem); }
body.embed .modal-mask { padding: 0; align-items: stretch; }
body.embed .modal { width: 100%; max-height: 100%; border-radius: 0; }
body.embed .m-head { padding: 10px 10px; }
body.embed .m-body { padding: 8px 10px; }
body.embed .m-foot { padding: 8px 10px; gap: 5px; }
body.embed .m-foot .btn { padding: 4px 8px; }
body.embed .m-foot .muted { display: none; }

/* ---------- 展开区只剩「操作条」（内联气泡预览已取消，正文只在弹窗里读） ---------- */
.kb-expand > .kb-actions:only-child { border-top: none; padding-top: 0; }
body.embed .kb-expand > .kb-actions:only-child { padding: 0 0 8px; }

/* ---------- 系统状态 Banner（维护中 / 核心依赖掉线） ---------- */
.banner {
  flex-shrink: 0; display: flex; align-items: center; gap: 10px;
  padding: 8px 16px; font-size: calc(13 / 16 * 1rem); border-bottom: 1px solid transparent;
}
.banner[hidden] { display: none; }
.banner.warn { background: var(--warn-soft); color: #92400e; border-bottom-color: #fde68a; }
.banner.danger { background: var(--danger-soft); color: #991b1b; border-bottom-color: #fecaca; }
.banner .btn { margin-left: auto; flex: none; }

/* ---------- 按钮 Loading（转圈）/ 成功 / 失败 ---------- */
.btn.loading { position: relative; color: transparent !important; }
.btn.loading::after {
  content: ''; position: absolute; top: 50%; left: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px;
  border: 2px solid var(--primary); border-right-color: transparent; border-radius: 50%;
  animation: mspin .7s linear infinite;
}
.btn.ok { border-color: var(--ok) !important; color: var(--ok) !important; background: #f0fdf4 !important; }
.btn.fail { border-color: var(--danger) !important; color: var(--danger) !important; background: var(--danger-soft) !important; }
@keyframes mspin { to { transform: rotate(360deg); } }

/* ---------- 全局拖拽上传覆盖层 ---------- */
#dropOverlay {
  position: fixed; inset: 0; z-index: 80; display: none;
  align-items: center; justify-content: center; pointer-events: none;
  background: rgba(37, 99, 235, .08); border: 3px dashed var(--primary);
}
#dropOverlay.show { display: flex; }
#dropOverlay .drop-card {
  background: #fff; border: 1px solid var(--primary); color: var(--primary);
  padding: 16px 26px; border-radius: 14px; font-size: calc(15 / 16 * 1rem); font-weight: 600;
  box-shadow: 0 12px 32px rgba(37, 99, 235, .18);
}

/* ---------- 手风琴：展开动画 + 摘要预览 ---------- */
@keyframes kbIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.kbrow.open .kb-expand { animation: kbIn .18s ease; }
.kb-preview { display: flex; flex-direction: column; gap: 6px; padding: 8px 0 4px; }
.kb-pv {
  font-size: calc(12.5 / 16 * 1rem); color: var(--text); background: #f9fafb;
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; line-height: 1.5;
}
.kb-pv-role {
  display: inline-block; font-size: calc(10.5 / 16 * 1rem); color: var(--muted);
  background: #fff; border: 1px solid var(--border); border-radius: 4px; padding: 0 5px; margin-right: 6px;
}
.kb-pv-more { font-size: calc(11.5 / 16 * 1rem); color: var(--muted); }

/* ---------- 上传进度条（2026-10-26 Step1：XHR upload.onprogress） ---------- */
.mn-progress {
  height: 6px; margin-top: 8px; border-radius: 999px;
  background: var(--border); overflow: hidden;
}
.mn-progress > div {
  height: 100%; width: 0; background: var(--primary);
  transition: width .15s linear;
}

/* ---------- 任务队列面板（系统页） ---------- */
.tag-warn {
  display: inline-block; font-size: calc(10.5 / 16 * 1rem); color: var(--warn);
  background: var(--warn-soft); border: 1px solid #fde68a; border-radius: 4px; padding: 0 5px;
}
@keyframes jobsHl { from { box-shadow: 0 0 0 3px rgba(37, 99, 235, .35); } to { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0); } }
.flash-hl { animation: jobsHl 1.6s ease; border-radius: var(--radius); }

/* Markdown：链接协议不在白名单时的降级展示（原文本，不可点） */
.md .md-unsafe { color: var(--muted); text-decoration: line-through; }
.md img { max-width: 100%; }

/* ---------- 能力卡：本地服务启停一行 ---------- */
.cap-service {
  display: flex; align-items: center; gap: 8px; margin: 6px 0 10px; padding: 8px 10px;
  border: 1px dashed var(--border); border-radius: 8px; background: #fcfcfd;
}
.cap-service .cap-dot { font-size: calc(12 / 16 * 1rem); }

/* ---------- 「一键全量打标」云端费用警告（2026-10-27 防爆） ----------
 * 打标走云端时按 token 计费，库里有几万片就是真金白银。
 * 这条警示条常驻在按钮上方（不只靠弹窗），让用户在点之前就看见。 */
.cloud-warn {
  margin: 10px 0 0; padding: 10px 12px; border-radius: 8px;
  background: var(--danger-soft); border: 1px solid #fecaca; color: #991b1b;
  font-size: calc(13 / 16 * 1rem); line-height: 1.65;
}
.cloud-warn[hidden] { display: none; }
.cloud-warn b { color: #b91c1c; }
.cloud-warn .cw-tag {
  display: inline-block; padding: 1px 6px; margin-right: 7px; border-radius: 4px;
  background: #dc2626; color: #fff; font-size: 11px; font-weight: 700; letter-spacing: .5px;
  vertical-align: 1px;
}
/* 本地零成本模式（tagging.mode=vocab）：同一条横幅换个绿皮，告诉用户「这个不花钱」 */
.cloud-warn.ok {
  background: var(--ok-soft, #f0fdf4); border-color: #bbf7d0; color: #166534;
}
.cloud-warn.ok b { color: #15803d; }
.cloud-warn.ok .cw-tag.ok { background: #16a34a; }
