/* ============================================================================
   MaxMind 控制台 · 对话消息区 · 新视觉层（chat-thread-v2.css）

   这一层只负责「消息区」的长相，范围（2026-09-18 用户口径）：
     用户气泡 / AI 回答排版 / 思考行 / 复制键。
   输入框与模型选择器（chat-selector.css）一个字都不碰。

   新视觉关键词：**静纸 + 一条蓝**。
     · 画布保持中性（深 #121214 / 浅 #f2f2f7），正文仍是无气泡的「整幅」；
     · 只有「用户自己的话」落成一枚蓝色气泡（复用选择器那套蓝的同族色）；
     · 链接 / 列表标记 / 引用侧线，统一用同一枚蓝，整页只认这一种强调色。

   加载顺序（必须）：styles.css → admin.css → chat.css → chat-selector.css
                     → 本文件 → mobile.css。
   本文件排在 chat.css 之后：同权重下靠后赢，用来——
     · 接管消息区的间距/动画（清掉 styles.css 旧 .message 的 400ms translateY
       与 gap:12px 漏进来的影响）；
     · 给消息区立一份自己的排版契约，不再偷偷依赖旧表。

   铁律沿用（与 CHAT-UI.md / admin.css 一致）：
     · 只消费 --adm-* token，另造只在消息区用到的派生 token（--cx2-*），
       颜色主源仍是那套蓝，不新开一套色板；
     · 深浅色两套都跟；玻璃仍只给控制层，正文不透明；
     · 动画只动 transform / opacity / filter，绝不用 scale(0)，≤300ms；
     · 「消失」linear、「出现」ease-out；hover 全部包在能力查询里；
     · prefers-reduced-motion / -transparency / -contrast 三档兜底。
   ============================================================================ */

/* ── 消息区派生 token（颜色只有「一枚蓝」）────────────────────────────
   暗底：气泡用稍深的蓝（白字对比 5.3:1），链接用亮蓝（7.1:1）才看得清；
   浅底：两者都落到 #0071e3（白底 4.7:1）。同族、同气质，只是深浅各就各位。
   2026-09-23 对齐 mm 新视觉：链接蓝与 --mm-blue 同源（#4d9eff），画布已由
   mm.css 重映射加深，本层只管消息区自己的两枚蓝。 */
:root {
  --cx2-user:    #0a6cc9;                 /* 用户气泡底色（深） */
  --cx2-user-fg: #ffffff;                 /* 气泡上的字 */
  --cx2-accent:  #4d9eff;                 /* 链接 / 标记 / 引用侧线（暗底亮蓝） */
  --cx2-glow:    rgba(10, 108, 201, 0.38);/* 气泡下缘柔光 */
}
[data-theme="light"] {
  --cx2-user:    #0071e3;
  --cx2-user-fg: #ffffff;
  --cx2-accent:  #0071e3;
  --cx2-glow:    rgba(0, 113, 227, 0.20);
}

/* ============================================================================
   1. 消息列表节奏
   ============================================================================ */

/* 旧的 .chat-messages 靠 styles.css 的 gap:26px 排布，一问一答之间的间距
   和「两轮之间」一样大，读不出「这是一对」。改成 margin 驱动：
   轮与轮 30px、一问一答 10px，谁近谁远一眼分明。 */
.chat-messages {
  gap: 0;
  padding-bottom: 28px;
}
.cx-msg {
  gap: 0;                                  /* 清掉旧 .message 的 gap:12px 漏入 */
  margin-top: 30px;
}
.cx-msg:first-child { margin-top: 0; }
.cx-msg-user + .cx-msg-ai { margin-top: 10px; }   /* 一问一答读作一对 */
/* 「等待正文」那三个点：它是上一条 AI 消息的【续行】（表示正文还没到），
   不是新的一轮，所以不能吃上面那 30px 的轮间距 —— 否则它和「已耗时」那一行
   中间空出一大截，看着像两条不相干的消息。 */
.cx-msg-ai.is-loading { margin-top: 8px; }

/* ============================================================================
   2. 用户消息：一枚蓝色气泡
   ============================================================================ */

.cx-bubble {
  max-width: min(78%, 560px);
  padding: 10px 14px;
  border-radius: var(--adm-r-lg) var(--adm-r-lg) 6px var(--adm-r-lg); /* 右下小尾 */
  background: var(--cx2-user);
  color: var(--cx2-user-fg);
  font-size: var(--adm-t-body);
  letter-spacing: var(--adm-ls-body);
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  /* 顶部一道极细的高光（材质「到货」感）+ 下缘一层蓝柔光 */
  box-shadow:
    inset 0 0.5px 0 rgba(255, 255, 255, 0.22),
    0 8px 20px -12px var(--cx2-glow);
}
.cx-bubble a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* ============================================================================
   3. AI 回答 + 复制键
   ============================================================================ */

/* 正文紧贴上面的灰线（用户口径：离分隔线太远）—— 动作行收到 4px。 */
.cx-msg-actions {
  gap: 2px;
  margin-top: 4px;
  margin-left: -7px;
  opacity: 1;
  transition: opacity 160ms var(--adm-ease-out);
}

/* 复制键：依旧是一枚安静的小图标。悬停（仅精确指针）才浮起，
   成功时图标轻轻「弹」一下（scale 1.15，绝不 scale(0)）。 */
.cx-copy-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: var(--adm-r-sm);
  background: transparent;
  color: var(--adm-label-3);
  cursor: pointer;
  transition: color 140ms var(--adm-ease-out), background-color 140ms var(--adm-ease-out);
}
.cx-copy-btn svg {
  width: 15px;
  height: 15px;
  /* 复位：干脆，不过冲（系统把反馈收回去，不该再晃一下） */
  transition: transform 160ms var(--adm-ease-out);
}
.cx-copy-btn::after { content: ''; position: absolute; inset: -8px -7px; } /* 命中区 44px */
.cx-copy-btn:active { background: var(--adm-fill-2); color: var(--adm-label); }
.cx-copy-btn.is-done { color: var(--adm-ok); }
/* 成功那一下带一点点过冲 —— 复用选择器那套手感令牌（--ms-spring，同一种「嗒」的语言），
   过冲只出现在「系统确认」这一刻，复位时没有：非对称，标准 #9。
   过冲幅度从 1.12 收到 1.08：一个 15px 的小图标放大 12% 已经算「蹦」了。 */
.cx-copy-btn.is-done svg {
  transform: scale(1.08);
  transition: transform 240ms var(--ms-spring);
}
@media (hover: hover) and (pointer: fine) {
  .cx-copy-btn:hover { background: var(--adm-fill-3); color: var(--adm-label); }
}

/* ============================================================================
   4. 思考行（灰字 + 灰线，无胶囊、无色块、无左边竖线 —— 用户口径不变）
   ============================================================================ */

/* 那条灰线改成「向右渐隐」的细线：仍是一条线，但尾端化开，不再是一根硬杠。 */
.cx-think {
  margin: 0 0 8px;
  padding-bottom: 0;
  border-bottom: 0;
}
.cx-think::after {
  content: '';
  display: block;
  height: 1px;
  margin-top: 9px;
  background: linear-gradient(90deg,
    var(--adm-sep) 0%, var(--adm-sep-soft) 46%, transparent 100%);
}

.cx-think-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 30px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--adm-label-2);
  font: inherit;
  font-size: var(--adm-t-footnote);
  font-weight: 500;
  letter-spacing: 0.004rem;
  cursor: pointer;
  transition: color 160ms var(--adm-ease-out);
}
.cx-think-toggle::after { content: ''; position: absolute; inset: -7px -10px; }
.cx-think-toggle:active { color: var(--adm-label); }
.cx-think-time { font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.cx-think-chevron { display: flex; color: var(--adm-label-2); transition: transform 240ms var(--adm-ease-out); }
.cx-think-chevron svg { width: 14px; height: 14px; }
.cx-think:not([data-open="1"]) .cx-think-chevron { transform: rotate(-90deg); }
.cx-think[data-open="1"] .cx-think-chevron { transform: rotate(0deg); }

/* 折叠/展开用 grid-template-rows，不动 height。
   ⚠️ 非对称：**收得快、放得慢**（标准 #9 + 仓库自己的规矩）。
      过渡写在「目的状态」上 —— 收起态那条 140ms linear 管「怎么关」，
      展开态那条 220ms ease-out 管「怎么开」。
   ⚠️ 上一版给内容加过 translateY(-3px)「落进来」，同时 260ms —— 两处一起动就是「飘」。
      这一版只留一次高度变化 + 一次淡入，两个时长贴着走，读起来是一个动作。 */
.cx-think-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 140ms linear, opacity 120ms linear;
  opacity: 0;
}
.cx-think[data-open="1"] .cx-think-body {
  grid-template-rows: 1fr;
  opacity: 1;
  transition: grid-template-rows 220ms var(--adm-ease-out), opacity 180ms var(--adm-ease-out);
}
.cx-think-inner { min-height: 0; overflow: hidden; }
.cx-think-text {
  margin: 10px 0 0;
  padding: 0;
  border: 0;
  color: var(--adm-label-2);
  font-size: var(--adm-t-footnote);
  line-height: 1.62;
  overflow-wrap: anywhere;
  white-space: normal;
  max-height: 300px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

/* ============================================================================
   5. Markdown 排版
   ============================================================================ */

.cx-md > *:first-child { margin-top: 0; }
.cx-md > *:last-child { margin-bottom: 0; }
.cx-md p { margin: 0 0 14px; }
.cx-md h1, .cx-md h2, .cx-md h3, .cx-md h4 {
  margin: 20px 0 10px;
  line-height: 1.3;
  letter-spacing: var(--adm-ls-title3);
  font-weight: 650;
}
.cx-md h1 { font-size: var(--adm-t-title3); }
.cx-md h2 { font-size: var(--adm-t-title3); }
.cx-md h3 { font-size: var(--adm-t-headline); }
.cx-md h4 { font-size: var(--adm-t-body); }

/* 无序列表：默认圆点换成「一枚蓝点」，跟整页的蓝呼应。 */
.cx-md ul { list-style: none; margin: 0 0 14px; padding-left: 1.4em; }
.cx-md ul > li { position: relative; margin: 5px 0; }
.cx-md ul > li::before {
  content: '';
  position: absolute;
  left: -1.05em;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--cx2-accent);
}
.cx-md ol { margin: 0 0 14px; padding-left: 1.6em; }
.cx-md ol > li::marker { color: var(--cx2-accent); font-weight: 600; }
.cx-md li { margin: 5px 0; }
.cx-md li > p { margin: 0 0 6px; }

.cx-md blockquote {
  margin: 0 0 14px;
  padding: 2px 0 2px 14px;
  border-left: 2px solid var(--cx2-accent);
  color: var(--adm-label-2);
}
.cx-md hr { height: 1px; margin: 20px 0; border: 0; background: var(--adm-sep-soft); }
.cx-md a {
  color: var(--cx2-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
@media (hover: hover) and (pointer: fine) {
  .cx-md a:hover { text-decoration-thickness: 1.5px; }
}
.cx-md strong { font-weight: 650; }

/* 表格：整张网格改成「只画行线」，更轻，也更耐手机横滚。 */
.cx-md table {
  display: block;
  width: max-content;
  max-width: 100%;
  margin: 0 0 14px;
  border-collapse: collapse;
  font-size: var(--adm-t-subhead);
  overflow-x: auto;
}
.cx-md th, .cx-md td {
  padding: 8px 12px;
  border: 0;
  border-bottom: 0.5px solid var(--adm-sep-soft);
  text-align: left;
}
.cx-md th {
  background: transparent;
  font-weight: 600;
  color: var(--adm-label-2);
  border-bottom: 1px solid var(--adm-sep);
}
.cx-md tr:last-child td { border-bottom: 0; }
.cx-md img { max-width: 100%; height: auto; border-radius: var(--adm-r-md); box-shadow: 0 0 0 0.5px var(--adm-sep-soft); }

/* 行内代码：一条极细发丝线，把代码和正文轻轻隔开。 */
.cx-icode {
  padding: 0.15em 0.42em;
  border-radius: 6px;
  background: var(--adm-fill-3);
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
  font-family: var(--adm-mono);
  font-size: 0.85em;
  color: var(--adm-label);
  overflow-wrap: anywhere;
}

/* ============================================================================
   6. 代码块
   ============================================================================ */

.cx-code {
  position: relative;
  margin: 0 0 14px;
  border-radius: var(--adm-r-md);
  background: var(--adm-surface);
  box-shadow: 0 0 0 0.5px var(--adm-sep-soft);
  overflow: hidden;
}
.cx-code-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 8px 6px 12px;
  background: var(--adm-fill-3);
  border-bottom: 0.5px solid var(--adm-sep-soft);
  font-size: var(--adm-t-caption2);
  color: var(--adm-label-2);
}
.cx-code-lang { font-family: var(--adm-mono); letter-spacing: 0.02rem; text-transform: lowercase; }
.cx-code-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 22px;
  padding: 0 5px;
  border: 0;
  border-radius: var(--adm-r-sm);
  background: transparent;
  color: var(--adm-label-2);
  font: inherit;
  font-size: var(--adm-t-caption2);
  cursor: pointer;
  transition: background-color 140ms var(--adm-ease-out), color 140ms var(--adm-ease-out);
}
.cx-code-copy svg { width: 13px; height: 13px; }
.cx-code-copy::after { content: ''; position: absolute; inset: 0; }
.cx-code-copy:active { background: var(--adm-fill-2); color: var(--adm-label); }
.cx-pre {
  margin: 0;
  padding: 13px 14px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  font-family: var(--adm-mono);
  font-size: var(--adm-t-footnote);
  line-height: 1.6;
  color: var(--adm-label);
  tab-size: 2;
}

/* ============================================================================
   7. 流式状态：光标 + 等待指示
   ============================================================================ */

/* 光标：不用 steps(2) 硬闪 —— 硬闪正是「一卡一卡」的来源。
   改成 ease-in-out 的柔和呼吸：还是有明暗节律，但不「啪、啪」地砸。 */
.cx-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 2px;
  border-radius: 1px;
  vertical-align: -0.15em;
  background: var(--cx2-accent);
  animation: cx2Caret 1.25s var(--adm-ease-in-out) infinite;
}
@keyframes cx2Caret { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } }

/* 等待首个 token 的三点：只让透明度和 2px 位移说话。
   ⚠️ 上一版还叠了一个 scale(0.92→1)，三个点各动两处（位移 + 大小），
      看着就是在「蹦」。动的东西越少越耐看。 */
.cx-typing { display: inline-flex; gap: 4px; align-items: center; padding: 4px 0; }
.cx-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--adm-label-2);
  animation: cx2Pulse 1.3s var(--adm-ease-in-out) infinite;
}
.cx-typing span:nth-child(2) { animation-delay: 0.13s; }
.cx-typing span:nth-child(3) { animation-delay: 0.26s; }
@keyframes cx2Pulse {
  0%, 100% { opacity: 0.3; transform: translateY(0); }
  50%      { opacity: 0.9; transform: translateY(-2px); }
}

/* ============================================================================
   8. 进场动画：缩放 0.96 + 淡入 + 散焦（用户偏好口径），但三条分开收
   ============================================================================ */

/* ★ 只有【当场新到】的消息才动 —— `.cx-msg-in` 由 app.js 在 appendMessage 时挂上。
   历史回放（打开旧会话 / 切会话）一律不带这个类，于是**完全不动**。
   上一版是先做、后栽在这上面：几十条历史一起缩放 + 散焦，眼睛看到的是
   「整页文字糊一下」，一点信息量都没有，纯噪音。

   ⚠️ 三条属性**一起收**，不要错开 —— 用户口径原文是
   「缩放 0.96 + 淡入 + 散焦**一起收**」。上一版把它们拆成 170/200/260ms 三条独立动画，
   属性各自落定，看着就是「散」的、不协调。合成一条，同时起步、同时到位。

   覆盖旧 .message 的 400ms translateY(10px)：同权重、本文件靠后，赢。
   填充模式用 backwards：结束后不留 filter（both 会把 blur(0) 永久挂上去，
   等于给每条消息白加一个合成层）。 */
.cx-msg-in {
  animation: cx2In 200ms var(--adm-ease-out) backwards;
}
@keyframes cx2In {
  from { opacity: 0; transform: scale(0.98); filter: blur(1.5px); }
  to   { opacity: 1; transform: scale(1);    filter: blur(0); }
}

/* ============================================================================
   9. 三档兜底
   ============================================================================ */

/* 减少动效：只留 opacity 交叉淡入，去掉位移 / 缩放 / 散焦。
   「少而柔」不是「全零」—— 帮理解的淡入留着，会晕的位移和缩放去掉。 */
@media (prefers-reduced-motion: reduce) {
  .cx-msg-in { animation: cx2InReduce 140ms linear backwards; }
  /* 思考块：行高变化直接到位，只保留淡入；内容不再额外做位移 */
  .cx-think-body { transition: opacity 140ms linear; }
  .cx-think[data-open="1"] .cx-think-body { transition: opacity 140ms linear; }
  .cx-think-chevron, .cx-copy-btn svg,
  .cx-copy-btn.is-done svg { transition: none; }
  .cx-typing span { animation: none; opacity: 0.6; transform: none; }
  .cx-caret { animation: none; opacity: 1; }
}
@keyframes cx2InReduce { from { opacity: 0; } to { opacity: 1; } }

/* 减少透明度：去掉气泡的柔光（只留顶部一道实心高光），虚线仍清晰。 */
@media (prefers-reduced-transparency: reduce) {
  .cx-bubble { box-shadow: inset 0 0.5px 0 rgba(255, 255, 255, 0.22); }
}

/* 高对比：灰字提亮、分隔线加深，别让低对比吃掉层次。 */
@media (prefers-contrast: more) {
  .cx-think-time, .cx-think-chevron, .cx-think-text { color: var(--adm-label); }
  .cx-think::after { background: var(--adm-label-4); }
  .cx-copy-btn { color: var(--adm-label-2); }
}
