/* ══════════════════════════════════════════════════════════
   AI 助手 · 悬浮球 + 侧边抽屉  (v3.39)
   独立样式文件 —— 不修改 style.css（51KB），避免污染现有样式
   z-index 层级：9993 遮罩 / 9994 抽屉 / 9995 悬浮球
     · 高于 999（回到顶部按钮），所以不会被压住
     · 低于 9999/10000（登录弹框、Toast），所以弹框仍能覆盖助手
   命名前缀统一 ai- / #ai-，与工作台现有 class 零冲突
   ══════════════════════════════════════════════════════════ */

:root{
  /* 抽屉宽度，由 JS 按模式切换（compact/wide/fullscreen） */
  --ai-w: 400px;
  /* 以下变量 style.css 已定义，这里只做兜底（防独立页面引用时变量缺失） */
  --ai-primary: #4361ee;
  --ai-purple: #7c3aed;
  --ai-success: #10b981;
  --ai-warning: #f59e0b;
  --ai-danger: #ef4444;
  --ai-g50: #f9fafb;  --ai-g100: #f3f4f6; --ai-g200: #e5e7eb;
  --ai-g300: #d1d5db; --ai-g400: #9ca3af; --ai-g500: #6b7280;
  --ai-g600: #4b5563; --ai-g700: #374151; --ai-g800: #1f2937; --ai-g900: #111827;
  --ai-primary-bg: #eef2ff;
  --ai-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}

/* ============ 悬浮球 ============ */
#ai-float-ball{
  position: fixed; right: 20px; bottom: 190px; z-index: 9995;
  width: 60px; height: 60px; border-radius: 50%; border: none; cursor: pointer;
  background: linear-gradient(135deg, var(--ai-primary), var(--ai-purple));
  box-shadow: 0 4px 15px rgba(67,97,238,.45);
  display: flex; align-items: center; justify-content: center;
  transition: transform .2s, box-shadow .2s, opacity .2s;
  padding: 0;
}
#ai-float-ball:hover{ transform: scale(1.1); box-shadow: 0 6px 20px rgba(67,97,238,.5); }
#ai-float-ball:active{ transform: scale(.95); }
#ai-float-ball svg{
  width: 28px; height: 28px; fill: none; stroke: #fff;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
/* 状态点：绿=就绪 / 橙=对话中 / 红=后端异常 */
#ai-float-ball .ai-status-dot{
  position: absolute; top: 2px; right: 2px; width: 12px; height: 12px;
  background: var(--ai-success); border: 2px solid #fff; border-radius: 50%;
  animation: ai-pulse-dot 2s infinite;
}
#ai-float-ball .ai-status-dot.busy{ background: var(--ai-warning); animation: ai-pulse-dot 1s infinite; }
#ai-float-ball .ai-status-dot.down{ background: var(--ai-danger); animation: none; }
@keyframes ai-pulse-dot{ 0%,100%{opacity:1} 50%{opacity:.5} }
/* 未登录时隐藏（JS 控制），避免点了才提示"请先登录" */
#ai-float-ball.ai-hidden{ display: none; }
/* v3.60：弹窗打开时隐藏悬浮球（modal-overlay z-index 500 < 悬浮球 9995，
   不隐藏会盖住弹窗右下角按钮——改进中心详情等弹窗的操作键被遮挡） */
#ai-float-ball.ai-modal-hidden{ display: none; }
/* v3.60：拖拽手感（抓手光标 + 拖动时禁文本选中） */
#ai-float-ball{ cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
#ai-float-ball:active{ cursor: grabbing; }

/* ============ 抽屉容器 ============ */
#ai-drawer{
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 9994;
  width: var(--ai-w); background: #fff; box-shadow: -4px 0 24px rgba(0,0,0,.08);
  display: flex; flex-direction: column;
  transition: transform .28s cubic-bezier(.4,0,.2,1);
}
#ai-drawer.closed{ transform: translateX(100%); }

/* ============ 拖拽上传高亮（v3.71） ============ */
#ai-drawer.drag-over::after{
  content: "松开即可上传附件（单个不超过 20MB）";
  position: absolute; inset: 12px; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  border: 2px dashed #378ADD; border-radius: 14px;
  background: rgba(230,241,251,.92);
  color: #0C447C; font-size: 15px; font-weight: 500;
  letter-spacing: .5px; pointer-events: none;
}

/* ============ 左边缘收起把手（v3.42.17） ============
   为什么放左边缘中部：抽屉从右侧滑出，用户视线和鼠标都在左边的主内容区，
   原来收起只能点右上角的 ×，宽屏 560px / 全屏 1100px 时要横跨整个面板。
   把手贴左边缘垂直居中，是鼠标最短路径的落点。
   注意 #ai-drawer 必须能让子元素溢出显示，否则 left:-28px 会被裁掉 —— 
   容器本身没有 overflow:hidden（默认 visible），所以直接定位即可，不用额外声明。 */
#ai-collapse-handle{
  position: absolute; left: -28px; top: 50%; transform: translateY(-50%);
  width: 28px; height: 64px; padding: 0; border: none; cursor: pointer;
  /* 只在左侧留圆角，右侧贴合抽屉边缘做成"长在抽屉上"的一体感 */
  border-radius: 8px 0 0 8px;
  background: #fff; color: var(--ai-g400);
  /* 阴影只朝左散，右侧用 0 偏移避免和抽屉自身阴影叠出脏边 */
  box-shadow: -3px 0 10px rgba(0,0,0,.08);
  display: flex; align-items: center; justify-content: center;
  transition: color .15s, background .15s, width .15s;
}
#ai-collapse-handle svg{ width: 15px; height: 15px; }
#ai-collapse-handle:hover{
  background: var(--ai-primary-bg); color: var(--ai-primary);
  width: 32px; left: -32px;
}
#ai-collapse-handle:active{ background: var(--ai-g100); }
/* 抽屉收起时把手跟着一起划走：它是 #ai-drawer 的子元素，
   父级 translateX(100%) 已经带走了，这里只需保证不残留可点击区域。 */
#ai-drawer.closed #ai-collapse-handle{ pointer-events: none; opacity: 0; }

/* 精简/宽屏模式下主内容右移（避免遮挡工作台） */
main.main.ai-padded-right{
  padding-right: calc(var(--ai-w) + 20px);
  transition: padding-right .28s cubic-bezier(.4,0,.2,1);
}

/* 全屏模式遮罩 */
#ai-overlay{
  position: fixed; inset: 0; z-index: 9993; background: rgba(0,0,0,.25);
  opacity: 0; pointer-events: none; transition: opacity .28s;
}
#ai-overlay.show{ opacity: 1; pointer-events: auto; }

/* ============ 抽屉头部 ============ */
/* v3.42.23：加了「导出会话」后头部变 5 个图标，精简模式(400px)实测溢出。
   实测预算：400 - 32(padding) = 368，而 5图标(160) + 模式组(94) + 8个gap(64)
   = 318 已占死，留给「图标+标题+标签」只剩 50px —— 标题"AI 助手"自己就 48.6px。
   根因不是"多了一个按钮"，而是头部里没有任何元素被允许收缩：
   图标和模式组是 flex-shrink:0，标题和标签是 white-space:nowrap，
   加上 flex 项默认 min-width:auto，任何一项超了就只能往外顶。
   这里先把固定开销压下来（padding 16→12 省 8px，gap 8→6 省 16px），
   再配合下面给标签开收缩口。 */
#ai-header{
  height: 52px; min-height: 52px; display: flex; align-items: center;
  padding: 0 12px; border-bottom: 1px solid var(--ai-g200); gap: 6px;
}
/* v3.42.23：标题图标补尺寸。原来只有 <span class="ai-title-icon"> 这个壳，
   CSS 里从没给它和内部 svg 写过宽高 —— 实测 svgW/svgH 都是 0px，
   也就是说这个机器人图标从 v3.39 起就一直没显示出来（既存 bug，非本次引入）。
   inline svg 没有内在尺寸时不会按 viewBox 撑开，必须显式给。 */
#ai-header .ai-title-icon{
  display: flex; align-items: center; justify-content: center;
  color: var(--ai-primary); flex-shrink: 0;
}
#ai-header .ai-title-icon svg{ width: 18px; height: 18px; }
#ai-header .ai-title{
  font-weight: 600; font-size: 15px; color: var(--ai-g900);
  margin-right: auto; white-space: nowrap;
  /* 标题不参与收缩（截断很难看），但也不能把别人顶出去 ——
     它排在最左，flex 溢出时最后才轮到它，实际不会被压。 */
  flex-shrink: 0;
}
/* v3.42.23：模型标签是头部里唯一「截断了也不影响使用」的元素 ——
   图标少一个就少一个功能，标题截断很难看，只有模型名可以省略号收尾
   （鼠标悬停有 title 兜底，看得到全名）。所以把收缩压力全导到这里：
     · flex:0 1 auto + overflow/ellipsis —— 超了截断而不是把别人顶出去。
     · min-width 给 54px 而不是 0 —— 实测给 0 时标签被压到 19px
       （padding 就占 16px，内容只剩 3px），连"—"都显示不全，标签形同虚设。
       54px 能稳定放下 5~6 个字符（"GLM-4…"），仍可辨识是哪一族模型。
   实测：claude-sonnet-4-5-20250929 这种超长名在 400px 下也不再溢出。 */
#ai-header .ai-model-tag{
  font-size: 11px; background: var(--ai-primary-bg); color: var(--ai-primary);
  padding: 2px 8px; border-radius: 10px; font-weight: 500;
  flex: 0 1 auto; min-width: 54px; max-width: 120px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-align: center;
}
/* v3.42.23：32→28px。实测头部总需求 435px 而精简模式只有 400px，缺 35px；
   逐项看下来图标按钮是最该省的一处 —— 里面的 svg 只有 16px，
   32px 的按钮有一半是纯空白 padding。缩到 28px 后 svg 两侧仍各留 6px，
   点击热区 28×28 也高于常见的 24px 可用性下限，手感几乎无差别。
   5 个按钮共省 20px，是本次唯一不牺牲信息量的让位方式。 */
#ai-header .ai-btn-icon{
  width: 28px; height: 28px; border: none; border-radius: 4px;
  background: transparent; cursor: pointer; color: var(--ai-g500); font-size: 15px;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s; flex-shrink: 0; padding: 0;
}
#ai-header .ai-btn-icon:hover{ background: var(--ai-g100); color: var(--ai-g700); }
/* v3.42.23：相邻图标之间收到 2px。它们是同一组操作按钮（导出/新建/历史/清空/关闭），
   本来就该比「标题↔标签↔模式组」这些跨语义分组的间距更紧凑；
   靠 :not(:first-of-type) 只作用于图标之间，不影响模式组到第一个图标的间距。
   4 个间隙 × 省 4px = 16px，补上最后的缺口。 */
#ai-header .ai-btn-icon + .ai-btn-icon{ margin-left: -4px; }

/* 模式切换按钮组 */
#ai-mode-group{
  display: flex; gap: 1px; background: var(--ai-g200);
  border-radius: 4px; padding: 1px; flex-shrink: 0;
}
#ai-mode-group button{
  /* v3.42.23：左右 padding 8→6。三个按钮共省 12px，
     是在不动图标数量的前提下最无感的一处让位。 */
  border: none; background: transparent; padding: 2px 6px; font-size: 12px;
  border-radius: 3px; cursor: pointer; color: var(--ai-g500); transition: all .15s;
}
#ai-mode-group button.active{ background: #fff; color: var(--ai-primary); box-shadow: 0 1px 2px rgba(0,0,0,.05); }

/* ============ 历史会话下拉 ============ */
#ai-history-pop{
  position: absolute; top: 50px; right: 12px; z-index: 10;
  width: 280px; max-height: 340px; overflow-y: auto;
  background: #fff; border: 1px solid var(--ai-g200); border-radius: 8px;
  box-shadow: 0 10px 15px -3px rgba(0,0,0,.1); display: none; padding: 4px;
}
#ai-history-pop.show{ display: block; }
#ai-history-pop .ai-hs-empty{ padding: 16px; text-align: center; color: var(--ai-g400); font-size: 12px; }
#ai-history-pop .ai-hs-item{
  padding: 8px 10px; border-radius: 6px; cursor: pointer; transition: background .15s;
}
#ai-history-pop .ai-hs-item:hover{ background: var(--ai-g50); }
#ai-history-pop .ai-hs-item.active{ background: var(--ai-primary-bg); }
#ai-history-pop .ai-hs-title{
  font-size: 13px; color: var(--ai-g800); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#ai-history-pop .ai-hs-meta{ font-size: 11px; color: var(--ai-g400); margin-top: 2px; }

/* ============ 消息区域 ============ */
#ai-msgs-wrap{ flex: 1; position: relative; display: flex; min-height: 0; }
/* v3.42.10.14：去掉 scroll-behavior: smooth
   原因：JS 里 `box.scrollTop = box.scrollHeight` 在 smooth 模式下是**异步动画**，
   动画过程中会连续触发 scroll 事件。bindScroll 的监听器用
   `scrollTop + clientHeight >= scrollHeight - 40` 判断"是否在底部"，
   动画刚开始时这个值离底部还很远 → _followScroll 被误置为 false。
   一旦 false，后续非 force 的 scrollToBottom() 就拒绝滚动、只弹"新消息"按钮，
   于是最终回复（长表格）永远停在视野外 → 用户看到"调用完工具没返回回复"。
   改成瞬时滚动：赋值即到位，scroll 事件读到的已是终值，判断结果正确。 */
#ai-msgs{
  flex: 1; overflow-y: auto; padding: 16px;
  display: flex; flex-direction: column; gap: 8px;
}
#ai-msgs::-webkit-scrollbar{ width: 5px; }
#ai-msgs::-webkit-scrollbar-thumb{ background: var(--ai-g300); border-radius: 10px; }
#ai-msgs::-webkit-scrollbar-track{ background: transparent; }

/* === 气泡通用 === */
.ai-msg{
  max-width: 88%; display: flex; flex-direction: column; gap: 4px;
  animation: ai-msg-in .2s ease-out;
}
@keyframes ai-msg-in{ from{opacity:0;transform:translateY(6px)} to{opacity:1;transform:translateY(0)} }
.ai-msg .ai-bubble{
  padding: 10px 14px; border-radius: 12px; font-size: 13px; line-height: 1.7;
  word-break: break-word;
}
/* 空 bubble 不占位（工具卡片先到、文字还没来的中间态） */
.ai-msg .ai-bubble:empty{ display: none; }
.ai-msg .ai-time{ font-size: 11px; color: var(--ai-g400); padding: 0 4px; }

/* 用户气泡 */
.ai-msg.user{ align-self: flex-end; }
.ai-msg.user .ai-bubble{
  background: var(--ai-primary); color: #fff; border-bottom-right-radius: 4px;
  white-space: pre-wrap;
}
.ai-msg.user .ai-time{ text-align: right; }

/* 助手气泡 */
.ai-msg.assistant{ align-self: flex-start; max-width: 94%; }
.ai-msg.assistant .ai-bubble{
  background: var(--ai-g50); border: 1px solid var(--ai-g200);
  border-bottom-left-radius: 4px; color: var(--ai-g800);
}

/* === 单条消息操作：复制 / 重新生成（v3.61） === */
/* 默认隐藏，hover 消息时浮现；流式生成中不显示（避免误点重发） */
.ai-msg-actions{
  display: none; gap: 4px; padding: 0 4px; margin-top: -2px;
}
.ai-msg.user .ai-msg-actions{ justify-content: flex-end; }
.ai-msg:hover .ai-msg-actions{ display: flex; }
.ai-msg.streaming .ai-msg-actions{ display: none !important; }
.ai-msg-act{
  border: 1px solid var(--ai-g200); background: var(--ai-white, #fff);
  color: var(--ai-g600); font-size: 11px; line-height: 1;
  padding: 3px 8px; border-radius: 10px; cursor: pointer;
  transition: all .15s ease;
}
.ai-msg-act:hover{ background: var(--ai-g50); color: var(--ai-g800); border-color: var(--ai-g300); }
.ai-msg-act:active{ transform: scale(.96); }
/* 错误气泡 */
.ai-msg.error .ai-bubble{
  background: #fef2f2; border: 1px solid #fecaca; color: #991b1b;
}

/* markdown 轻量渲染后的内联元素 */
.ai-msg .ai-bubble strong{ font-weight: 600; color: var(--ai-g900); }
.ai-msg .ai-bubble code{
  font-family: var(--ai-mono); font-size: 12px;
  background: var(--ai-g100); padding: 1px 5px; border-radius: 3px; color: #be185d;
}
.ai-msg .ai-bubble pre{
  background: var(--ai-g100); border: 1px solid var(--ai-g200); border-radius: 6px;
  padding: 8px 10px; margin: 6px 0; overflow-x: auto;
  font-family: var(--ai-mono); font-size: 11px; line-height: 1.6;
}
.ai-msg .ai-bubble pre code{ background: transparent; padding: 0; color: var(--ai-g700); }
.ai-msg .ai-bubble table{
  border-collapse: collapse; width: 100%; margin: 6px 0; font-size: 12px;
  display: block; overflow-x: auto;
}
.ai-msg .ai-bubble th, .ai-msg .ai-bubble td{
  border: 1px solid var(--ai-g200); padding: 4px 8px; text-align: left;
}
.ai-msg .ai-bubble th{ background: var(--ai-g100); font-weight: 600; }
.ai-msg .ai-bubble ul, .ai-msg .ai-bubble ol{ margin: 4px 0 4px 18px; }
.ai-msg .ai-bubble li{ margin: 2px 0; }
.ai-msg .ai-bubble a{ color: var(--ai-primary); text-decoration: none; }
.ai-msg .ai-bubble a:hover{ text-decoration: underline; }

/* 正在生成的光标 */
.ai-msg.assistant.streaming .ai-bubble::after{
  content: ""; display: inline-block; width: 6px; height: 14px;
  background: var(--ai-primary); margin-left: 2px;
  animation: ai-blink 1s step-end infinite; vertical-align: middle;
}
@keyframes ai-blink{ 0%,100%{opacity:1} 50%{opacity:0} }

/* === thinking 思考过程（v3.42.22 重构为可折叠时间线） ===
   旧版是「一行静态转圈 + 结束后 display:none」，过程不可见、结束即丢失。
   新版：实时追加步骤 + 总计时；出结果后折叠成一行摘要，可点开回看。 */
.ai-msg .ai-thinking{
  margin: 2px 0 6px; padding: 6px 8px;
  background: var(--ai-g50); border: 1px solid var(--ai-g200);
  border-radius: 6px; font-size: 12px; color: var(--ai-g400);
}
.ai-msg .ai-thinking .ai-think-head{
  display: flex; align-items: center; gap: 6px;
  user-select: none;
}
.ai-msg .ai-thinking .ai-think-title{ flex: 1; min-width: 0; }
.ai-msg .ai-thinking .ai-think-timer{
  font-variant-numeric: tabular-nums;   /* 数字等宽，跳秒时不左右抖 */
  color: var(--ai-g300); font-size: 11px;
}
.ai-msg .ai-thinking .ai-spin{
  width: 12px; height: 12px; border: 2px solid var(--ai-g200);
  border-top-color: var(--ai-primary); border-radius: 50%;
  animation: ai-spin .8s linear infinite; flex-shrink: 0;
}
@keyframes ai-spin{ to{ transform: rotate(360deg) } }

/* 步骤流 */
.ai-msg .ai-thinking .ai-think-steps{
  margin-top: 6px; padding-left: 4px;
  display: flex; flex-direction: column; gap: 3px;
}
.ai-msg .ai-think-step{
  display: flex; align-items: center; gap: 6px;
  line-height: 1.5;
  animation: ai-step-in .18s ease-out;
}
@keyframes ai-step-in{
  from{ opacity: 0; transform: translateY(-2px) }
  to{ opacity: 1; transform: none }
}
.ai-msg .ai-step-dot{
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--ai-g300); flex-shrink: 0;
}
.ai-msg .ai-step-dot.done{ background: var(--ai-success); }
.ai-msg .ai-think-step.active .ai-step-dot{
  background: var(--ai-primary); animation: ai-pulse-dot 1s infinite;
}
.ai-msg .ai-step-icon{ flex-shrink: 0; font-size: 11px; }
.ai-msg .ai-step-text{
  flex: 1; min-width: 0;
  /* v3.54.3：去掉 nowrap+ellipsis 单行截断，改多行完整显示。
     思考步骤文本长了用省略号截断会让用户看不到关键内容（工具参数/查询条件）。 */
  white-space: normal; word-break: break-word; overflow-wrap: anywhere;
  line-height: 1.5;
}
.ai-msg .ai-think-step.active .ai-step-text{ color: var(--ai-g500); }
.ai-msg .ai-think-step.failed .ai-step-text{ color: var(--ai-danger); }
.ai-msg .ai-step-cost{
  flex-shrink: 0; font-size: 11px; color: var(--ai-g300);
  font-variant-numeric: tabular-nums;
}

/* 折叠态：只留一行「已思考 3.4s · 4 步」，点头部展开 */
.ai-msg .ai-thinking.collapsed .ai-think-steps{ display: none; }
.ai-msg .ai-thinking.collapsed .ai-spin{
  animation: none; border: 2px solid var(--ai-g200);
  border-top-color: var(--ai-g200);   /* 停转，避免"还在跑"的错觉 */
}
.ai-msg .ai-thinking.collapsed{ background: transparent; border-color: transparent; padding: 2px 4px; }
.ai-msg .ai-thinking.collapsed:hover{ background: var(--ai-g50); }
.ai-msg .ai-thinking.collapsed .ai-think-title{ color: var(--ai-g300); }

/* 无步骤（历史消息回填）→ 整块不显示，否则每条历史回复顶一个空壳 */
.ai-msg .ai-thinking.done{ display: none; }

/* === 工具调用卡片 === */
.ai-msg .ai-tool-call{
  margin-top: 4px; background: var(--ai-g50); border: 1px solid var(--ai-g200);
  border-radius: 8px; font-size: 12px; overflow: hidden;
}
/* 用户确认后执行的工具 —— 左侧琥珀条，与 LLM 自主调用区分 */
.ai-msg .ai-tool-call.confirmed{
  border-left: 3px solid var(--ai-warning); background: #fffdf7;
}
.ai-msg .ai-tool-call .ai-tc-header{
  padding: 6px 10px; display: flex; align-items: center; gap: 5px;
  cursor: pointer; user-select: none; color: var(--ai-g600);
}
.ai-msg .ai-tool-call .ai-tc-header svg{ width: 14px; height: 14px; flex-shrink: 0; transition: transform .2s; }
.ai-msg .ai-tool-call .ai-tc-header svg.open{ transform: rotate(90deg); }
.ai-msg .ai-tool-call .ai-tc-name{
  font-family: var(--ai-mono); font-size: 11px; font-weight: 600; color: var(--ai-g700);
}
/* v3.62：工具调用对象摘要（读哪个文件/搜什么词），弱化色不抢工具名 */
.ai-msg .ai-tool-call .ai-tc-summary{
  font-weight: 400; color: var(--ai-g400); font-family: var(--ai-mono);
  font-size: 10px; margin-left: 2px;
}
.ai-msg .ai-tool-call .ai-tc-label{
  color: var(--ai-g400); margin-left: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ai-msg .ai-tool-call .ai-tc-status{
  width: 8px; height: 8px; border-radius: 50%; margin-left: auto; flex-shrink: 0;
}
.ai-msg .ai-tool-call .ai-tc-status.done{ background: var(--ai-success); }
.ai-msg .ai-tool-call .ai-tc-status.error{ background: var(--ai-danger); }
.ai-msg .ai-tool-call .ai-tc-status.running{ background: var(--ai-warning); animation: ai-pulse-dot 1s infinite; }
.ai-msg .ai-tool-call .ai-tc-body{
  display: none; padding: 8px 10px; border-top: 1px solid var(--ai-g200);
  background: var(--ai-g100); font-family: var(--ai-mono); font-size: 11px;
  line-height: 1.5; white-space: pre-wrap; word-break: break-all;
  max-height: 300px; overflow-y: auto; color: var(--ai-g700);
}
.ai-msg .ai-tool-call .ai-tc-body.open{ display: block; }

/* === 写操作确认卡片（琥珀色，原型已确认配色） === */
.ai-msg .ai-confirm-card{
  margin-top: 4px; background: #fffbeb; border: 1px solid #fcd34d;
  border-radius: 8px; padding: 10px 12px; font-size: 12px;
}
.ai-msg .ai-confirm-card .ai-cc-title{
  font-weight: 600; color: #92400e; margin-bottom: 4px;
  display: flex; align-items: center; gap: 4px;
}
.ai-msg .ai-confirm-card .ai-cc-msg{ color: var(--ai-g700); line-height: 1.6; margin-bottom: 6px; }
.ai-msg .ai-confirm-card .ai-cc-detail{
  color: var(--ai-g600); line-height: 1.6; margin-bottom: 8px;
  font-family: var(--ai-mono); font-size: 11px;
  background: rgba(255,255,255,.6); padding: 6px 8px; border-radius: 4px;
  white-space: pre-wrap; word-break: break-all; max-height: 160px; overflow-y: auto;
}
.ai-msg .ai-confirm-card .ai-cc-actions{ display: flex; gap: 8px; }
.ai-msg .ai-confirm-card button{
  flex: 1; padding: 5px 10px; border-radius: 4px; font-size: 12px;
  cursor: pointer; border: 1px solid; transition: all .15s;
}
.ai-msg .ai-confirm-card .ai-btn-ok{ background: var(--ai-primary); color: #fff; border-color: var(--ai-primary); }
.ai-msg .ai-confirm-card .ai-btn-ok:hover{ filter: brightness(1.08); }
.ai-msg .ai-confirm-card .ai-btn-no{ background: #fff; color: var(--ai-g600); border-color: var(--ai-g300); }
.ai-msg .ai-confirm-card .ai-btn-no:hover{ background: var(--ai-g50); }
.ai-msg .ai-confirm-card .ai-cc-resolved{ font-weight: 500; }

/* v3.90 整轮聚合确认卡（多个写操作一张卡） */
.ai-msg .ai-confirm-batch .ai-cc-batch-detail{
  margin-bottom: 8px; max-height: 300px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
}
.ai-msg .ai-confirm-batch .ai-cc-item{
  background: rgba(255,255,255,.65); border: 1px solid #fde68a;
  border-radius: 6px; padding: 6px 8px;
}
.ai-msg .ai-confirm-batch .ai-cc-item-title{
  font-weight: 600; color: #92400e; margin-bottom: 3px; font-size: 12px;
}
.ai-msg .ai-confirm-batch .ai-cc-item-detail{
  color: var(--ai-g600); line-height: 1.55;
  font-family: var(--ai-mono); font-size: 11px;
  white-space: pre-wrap; word-break: break-all;
  max-height: 130px; overflow-y: auto;
}

/* === 空状态 === */
#ai-empty{
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center; color: var(--ai-g400);
  gap: 8px; padding: 24px;
}
#ai-empty .ai-big-icon{
  width: 56px; height: 56px; border-radius: 50%;
  background: linear-gradient(135deg, var(--ai-primary-bg), #f3e8ff);
  display: flex; align-items: center; justify-content: center;
}
#ai-empty .ai-big-icon svg{ width: 28px; height: 28px; fill: none; stroke: var(--ai-primary); stroke-width: 2; }
#ai-empty h4{ font-size: 15px; color: var(--ai-g700); font-weight: 600; margin: 0; }
#ai-empty p{ font-size: 12px; line-height: 1.8; max-width: 280px; margin: 0; }
#ai-empty .ai-cap-hint{
  font-size: 11px; color: var(--ai-g400); background: var(--ai-g50);
  border: 1px solid var(--ai-g200); border-radius: 6px; padding: 6px 10px; cursor: pointer;
}
#ai-empty .ai-cap-hint:hover{ border-color: var(--ai-primary); color: var(--ai-primary); }

/* === 新消息按钮 === */
#ai-new-msg-btn{
  position: absolute; right: 16px; bottom: 20px;
  background: #fff; border: 1px solid var(--ai-g300); border-radius: 16px;
  padding: 4px 12px; font-size: 12px; color: var(--ai-primary); cursor: pointer;
  box-shadow: 0 4px 6px -1px rgba(0,0,0,.1); display: none;
  align-items: center; gap: 4px; z-index: 5;
}
#ai-new-msg-btn.show{ display: flex; }

/* ============ 快捷指令区 ============ */
#ai-quick{
  border-top: 1px solid var(--ai-g200); background: var(--ai-g50);
  transition: max-height .22s ease; overflow: hidden; flex-shrink: 0;
}
#ai-quick .ai-qk-header{
  padding: 6px 16px; display: flex; align-items: center;
  font-size: 11px; color: var(--ai-g500); cursor: pointer; user-select: none; gap: 4px;
}
#ai-quick .ai-qk-header svg{ width: 12px; height: 12px; transition: transform .2s; }
#ai-quick.collapsed .ai-qk-header svg{ transform: rotate(-90deg); }
#ai-quick .ai-qk-header .ai-qk-count{ margin-left: auto; font-size: 10px; color: var(--ai-g400); }
#ai-quick .ai-qk-body{ padding: 0 16px 8px; }
#ai-quick.collapsed .ai-qk-body{ display: none; }

#ai-quick .ai-qk-tabs{ display: flex; gap: 4px; margin-bottom: 6px; flex-wrap: wrap; }
#ai-quick .ai-qk-tabs button{
  border: none; background: transparent; font-size: 11px; color: var(--ai-g500);
  padding: 2px 8px; border-radius: 10px; cursor: pointer; transition: all .15s;
}
#ai-quick .ai-qk-tabs button.active{ background: var(--ai-primary); color: #fff; }
#ai-quick .ai-qk-tabs button:not(.active):hover{ background: var(--ai-g200); }

#ai-quick .ai-qk-chips{ display: flex; gap: 6px; flex-wrap: wrap; }
#ai-quick .ai-chip{
  background: #fff; border: 1px solid var(--ai-g200); border-radius: 14px;
  padding: 4px 11px; font-size: 12px; color: var(--ai-g700); cursor: pointer;
  transition: all .15s; display: flex; align-items: center; gap: 4px; white-space: nowrap;
}
#ai-quick .ai-chip:hover{ border-color: var(--ai-primary); color: var(--ai-primary); background: var(--ai-primary-bg); }
#ai-quick .ai-chip:disabled{ opacity: .5; cursor: not-allowed; }
/* v3.42.2：用户最常用的"问知识库"按钮 —— 主题色 + 加大 + 阴影，比普通 chip 更显眼 */
#ai-quick .ai-chip-primary{
  background: var(--ai-primary); color: #fff; border-color: var(--ai-primary);
  padding: 6px 14px; font-size: 13px; font-weight: 600;
  box-shadow: 0 2px 6px rgba(67, 97, 238, .25);
  border-radius: 16px;
}
#ai-quick .ai-chip-primary:hover{
  background: var(--ai-primary); color: #fff; border-color: var(--ai-primary);
  filter: brightness(1.08); box-shadow: 0 3px 10px rgba(67, 97, 238, .35);
}

/* ============ 输入区 ============ */
#ai-input-zone{
  border-top: 1px solid var(--ai-g200); padding: 8px 16px 16px;
  background: #fff; flex-shrink: 0;
}
#ai-input-wrap{
  border: 1px solid var(--ai-g300); border-radius: 12px;
  padding: 8px 10px; transition: border-color .15s, box-shadow .15s; background: #fff;
}
#ai-input-wrap:focus-within{ border-color: var(--ai-primary); box-shadow: 0 0 0 3px rgba(67,97,238,.08); }
#ai-textarea{
  width: 100%; border: none; outline: none; resize: none;
  font-family: inherit; font-size: 13px; line-height: 1.6;
  max-height: 120px; min-height: 22px; color: var(--ai-g800); background: transparent;
  display: block;
}
#ai-textarea::placeholder{ color: var(--ai-g400); }
#ai-input-bar{ display: flex; align-items: center; gap: 4px; margin-top: 6px; }
#ai-input-bar .ai-tool-btn{
  width: 26px; height: 26px; border: none; background: transparent; border-radius: 4px;
  cursor: pointer; color: var(--ai-g400); font-size: 14px;
  display: flex; align-items: center; justify-content: center; transition: all .15s; padding: 0;
}
#ai-input-bar .ai-tool-btn:hover{ background: var(--ai-g100); color: var(--ai-g600); }
#ai-input-bar .ai-tool-btn.recording{ color: #e24b4a; animation: aiMicPulse 1.2s ease-in-out infinite; }
#ai-input-bar .ai-tool-btn:disabled{ cursor: wait; opacity: .6; }
@keyframes aiMicPulse{ 0%,100%{ opacity:1 } 50%{ opacity:.45 } }
#ai-input-bar .ai-hint{ margin-left: auto; font-size: 11px; color: var(--ai-g400); margin-right: 4px; }
#ai-send{
  width: 30px; height: 30px; border: none; border-radius: 50%; cursor: pointer;
  background: var(--ai-primary); color: #fff;
  display: flex; align-items: center; justify-content: center;
  transition: all .15s; flex-shrink: 0; padding: 0;
}
#ai-send:hover:not(:disabled){ filter: brightness(1.1); }
#ai-send:disabled{ background: var(--ai-g300); cursor: not-allowed; }
#ai-send svg{
  width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
}
#ai-send.stop{ background: var(--ai-danger); }

/* ============ 附件卡片（v3.42.25 美化） ============ */
#ai-attach-chips{ display: none; }
#ai-attach-chips.has-files{
  display: flex; flex-direction: column; gap: 6px;
  margin-bottom: 8px; max-height: 156px; overflow-y: auto;
}
#ai-attach-chips::-webkit-scrollbar{ width: 6px; }
#ai-attach-chips::-webkit-scrollbar-thumb{ background: var(--ai-g200); border-radius: 3px; }

.ai-attach-chip{
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 7px 8px 7px 8px; border: 1px solid var(--ai-g200); border-radius: 10px;
  background: var(--ai-g50); overflow: hidden;
  transition: border-color .15s, background .15s, box-shadow .15s;
  animation: ai-attach-in .18s ease-out;
}
.ai-attach-chip:hover{
  border-color: var(--ai-g300); background: #fff;
  box-shadow: 0 1px 4px rgba(17,24,39,.06);
}
@keyframes ai-attach-in{ from{ opacity: 0; transform: translateY(-4px); } to{ opacity: 1; transform: none; } }

/* ── 类型徽标 ── */
.ai-attach-badge{
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; letter-spacing: .2px; line-height: 1;
  user-select: none;
}
.ai-attach-badge.kind-pdf{   background: #fee2e2; color: #dc2626; }
.ai-attach-badge.kind-excel{ background: #dcfce7; color: #16a34a; }
.ai-attach-badge.kind-word{  background: #dbeafe; color: #2563eb; }
.ai-attach-badge.kind-ppt{   background: #ffedd5; color: #ea580c; }
.ai-attach-badge.kind-text{  background: #f3f4f6; color: #6b7280; }
.ai-attach-badge.kind-code{  background: #ede9fe; color: #7c3aed; }
.ai-attach-badge.kind-zip{   background: #fef3c7; color: #d97706; }
.ai-attach-badge.kind-image{ background: #fce7f3; color: #db2777; }
.ai-attach-badge.kind-file{  background: #f1f5f9; color: #64748b; }
.ai-attach-badge.is-loading{ background: var(--ai-primary-bg); color: var(--ai-primary); }
.ai-attach-spin{
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(67,97,238,.25); border-top-color: var(--ai-primary);
  animation: ai-attach-rot .7s linear infinite;
}
@keyframes ai-attach-rot{ to{ transform: rotate(360deg); } }

/* ── 文件名 / 大小 / 状态 ── */
.ai-attach-meta{ flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ai-attach-name{
  font-size: 12.5px; font-weight: 500; color: var(--ai-g800); line-height: 1.35;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ai-attach-sub{ display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--ai-g400); }
.ai-attach-size{ white-space: nowrap; }
.ai-attach-state{ display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.ai-attach-state.ready{ color: var(--ai-success); }
.ai-attach-state.ready svg{ width: 11px; height: 11px; }
.ai-attach-state.uploading{ color: var(--ai-g400); }

/* ── 移除按钮（圆形，hover 变红） ── */
.ai-attach-del{
  flex-shrink: 0; width: 22px; height: 22px; border: none; border-radius: 50%;
  background: transparent; color: var(--ai-g400); cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, color .15s;
}
.ai-attach-del svg{ width: 12px; height: 12px; }
.ai-attach-del:hover{ background: #fee2e2; color: var(--ai-danger); }

/* ── 上传中底部 indeterminate 进度条 ── */
.ai-attach-progress{
  position: absolute; left: 0; bottom: 0; height: 2px; width: 40%;
  background: linear-gradient(90deg, transparent, var(--ai-primary), transparent);
  animation: ai-attach-slide 1s ease-in-out infinite;
}
@keyframes ai-attach-slide{
  0%{ transform: translateX(-100%); }
  100%{ transform: translateX(320%); }
}
.ai-attach-chip.uploading{ background: #fff; border-color: var(--ai-g200); }
#ai-send.stop:hover{ background: #dc2626; }
#ai-send.stop svg{ fill: currentColor; stroke: none; }

/* ============ 移动端降级：底部 sheet ============ */
@media (max-width: 768px){
  #ai-float-ball{ width: 52px; height: 52px; bottom: 80px; right: 16px; }
  #ai-float-ball svg{ width: 24px; height: 24px; }
  #ai-drawer{
    top: auto; left: 0; right: 0; bottom: 0; width: 100% !important; height: 85vh;
    border-radius: 16px 16px 0 0; box-shadow: 0 -4px 24px rgba(0,0,0,.15);
  }
  #ai-drawer.closed{ transform: translateY(100%); }
  #ai-mode-group{ display: none; }
  /* 移动端不做右移，否则内容被挤成一条 */
  main.main.ai-padded-right{ padding-right: 16px; }
  /* 顶部小横条（sheet 的抓手视觉） */
  #ai-drawer::before{
    content: ""; position: absolute; top: 6px; left: 50%; transform: translateX(-50%);
    width: 36px; height: 4px; background: var(--ai-g300); border-radius: 2px;
  }
  #ai-header{ margin-top: 6px; }
  /* v3.42.17：移动端抽屉是底部 sheet（从下往上弹），左边缘把手没有语义，
     且会挡住内容。改成藏起来 —— 顶部本来就有 ::before 抓手横条，
     配合下面的向下箭头覆盖"收起"这个动作。 */
  #ai-collapse-handle{
    left: 50%; top: -30px; transform: translateX(-50%);
    width: 56px; height: 26px; border-radius: 8px 8px 0 0;
    box-shadow: 0 -3px 10px rgba(0,0,0,.08);
  }
  /* 箭头转 90° 朝下，对应"往下收起" */
  #ai-collapse-handle svg{ transform: rotate(90deg); }
  #ai-collapse-handle:hover{ width: 56px; left: 50%; }
  #ai-history-pop{ width: calc(100% - 24px); right: 12px; }
  .ai-msg{ max-width: 92%; }
}

/* 打印时不显示助手 */
@media print{
  #ai-float-ball, #ai-drawer, #ai-overlay{ display: none !important; }
  main.main.ai-padded-right{ padding-right: 0 !important; }
}

/* ============ v3.42.10 图标尺寸统一 ============ */
/* 所有 icon 容器内的 svg/emoji 强制统一尺寸，避免浏览器默认渲染不一致 */
#ai-float-ball svg{ width: 28px; height: 28px; }
#ai-header .ai-btn-icon svg{ width: 16px; height: 16px; }
#ai-mode-group button svg{ width: 14px; height: 14px; }
#ai-input-bar .ai-tool-btn svg{ width: 14px; height: 14px; }
#ai-send svg{ width: 16px; height: 16px; }
#ai-send.stop svg{ width: 12px; height: 12px; fill: currentColor; }
#ai-new-msg-btn svg{ width: 12px; height: 12px; }
#ai-quick .ai-qk-header svg{ width: 12px; height: 12px; }
#ai-quick.collapsed .ai-qk-header svg{ transform: rotate(-90deg); }
#ai-empty .ai-big-icon svg{ width: 28px; height: 28px; }
/* chip 内的 emoji 也要统一大小（跟 SVG 视觉接近） */
.ai-qk-icon{ font-size: 14px; line-height: 1; display: inline-flex; align-items: center; }
