/* ============================================================
   Textmolt Chat Pipeline Layer — s02 聊天核心管线（A 路 2026-07-02）
   区块: 1.A1 流式双区   2.B2 Thinking 上台
         3.B5 错误卡     4.B6 停止/继续   5.R1 空态 hero（s03）
   规范: 动效与色彩一律引用 tokens.css v2（T5: 本文件不定义 --tm-）;
         styles.css 冻结令——聊天管线新样式全部落本文件。
   Spec: docs/plans/FRONTEND_UIUX_OVERHAUL_2026-07-02/01_PLAN_CHAT_CORE.md
   ============================================================ */

/* ────────────────────────────────────────────────────────────
   1) A1 · 流式双区：已闭合块以富文本浮现（block-reveal 与既有
      blur-reveal 同族——轻位移 + 退模糊），活动尾块保持逐字弹入。
   ──────────────────────────────────────────────────────────── */
.stream-stable {
  display: flow-root;
}
.stream-stable:empty {
  display: none;
}
.stream-active {
  white-space: pre-wrap;
}
/* 活动区空时不占行高，caret 不悬空 */
.stream-active:empty {
  display: none;
}

.stream-block {
  animation: tm-block-reveal var(--tm-dur-normal) var(--tm-ease-out) both;
}
/* 块内首末元素 margin 收敛：流式块间视差贴近 finalize 后的连续排版（≤4px，plan A1 风险 1） */
.stream-block > :first-child {
  margin-top: 0;
}
.stream-block > :last-child {
  margin-bottom: 0;
}
.stream-block + .stream-block {
  margin-top: var(--tm-space-2);
}
@keyframes tm-block-reveal {
  from {
    opacity: 0;
    transform: translateY(4px);
    filter: blur(3px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

/* ────────────────────────────────────────────────────────────
   2) B2 · Thinking 上台：等待首 token 的生命感。
      dot 标 [data-motion-essential]（HTML 属性）——reduce 下由
      system.css 区块 1 退化为纯不透明度脉冲（reduce ≠ 无反馈）。
      thinking-pulse / thinking-fade keyframes 复用 styles.css 既有定义。
   ──────────────────────────────────────────────────────────── */
.stream-thinking {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 2px 0;
}
.thinking-core-dot {
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  border-radius: var(--tm-radius-full);
  background: rgba(var(--primary-glow-rgb), 0.9);
  box-shadow: 0 0 10px rgba(var(--primary-glow-rgb), 0.55);
  animation: thinking-pulse 1.5s ease-in-out infinite;
}
.thinking-label {
  font-size: var(--tm-text-sm);
  color: var(--text-muted);
  animation: thinking-fade 2s ease-in-out infinite;
}
.stream-thinking.leaving {
  opacity: 0;
  transition: opacity var(--tm-dur-fast) var(--tm-ease-out);
}

/* ────────────────────────────────────────────────────────────
   3) B5 · 错误卡：错误不再伪装成 AI 发言。
      语义色走 --tm-status-danger(-rgb)，双主题自适配。
   ──────────────────────────────────────────────────────────── */
.chat-error-card {
  display: grid;
  gap: var(--tm-space-2);
  padding: var(--tm-space-4);
  margin-top: 0;
  max-width: min(100%, calc(var(--tm-space-6) * 15));
  border-radius: var(--tm-radius-xl);
  background: color-mix(in srgb, var(--tm-status-danger) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--tm-status-danger) 22%, transparent);
  animation: tm-block-reveal var(--tm-dur-normal) var(--tm-ease-out) both;
}

.message-ai .message-bubble.message-bubble--error-card {
  padding: 0;
  white-space: normal;
  line-height: var(--tm-leading-normal);
}
.chat-error-heading {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  min-width: 0;
}
.chat-error-icon {
  flex-shrink: 0;
  width: var(--tm-space-4);
  height: var(--tm-space-4);
  color: var(--tm-status-danger);
}
.chat-error-title {
  min-width: 0;
  font-size: var(--tm-text-md);
  line-height: var(--tm-leading-tight);
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-primary);
}
.chat-error-msg {
  font-size: var(--tm-text-sm);
  line-height: var(--tm-leading-normal);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}
.chat-error-footer {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--tm-space-3);
  min-width: 0;
}
.chat-error-meta {
  min-width: 0;
}
.chat-error-code {
  font-size: var(--tm-text-2xs);
  letter-spacing: 0.04em;
  color: var(--text-muted);
  font-family: var(--tm-font-mono);
  line-height: var(--tm-leading-tight);
}
.chat-error-code + .chat-error-code {
  margin-top: var(--tm-space-1);
}
.chat-error-retry {
  flex-shrink: 0;
  align-self: flex-end;
  margin-left: auto;
  padding: var(--tm-space-2) var(--tm-space-3);
  border-radius: var(--tm-radius-full);
  font-size: var(--tm-text-xs);
  font-weight: var(--tm-weight-semibold);
  cursor: pointer;
  color: var(--tm-status-danger);
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--tm-status-danger) 35%, transparent);
  transition: background var(--tm-dur-fast) var(--tm-ease-out),
    border-color var(--tm-dur-fast) var(--tm-ease-out);
}
.chat-error-retry:hover {
  background: color-mix(in srgb, var(--tm-status-danger) 10%, transparent);
  border-color: color-mix(in srgb, var(--tm-status-danger) 45%, transparent);
}
.chat-error-retry:active {
  background: color-mix(in srgb, var(--tm-status-danger) 14%, transparent);
}

/* ────────────────────────────────────────────────────────────
   4) B6 · 停止/继续：止损不弃疗（A4-(5) stop-marker 除迁 cssText）。
      入场带一点 spring 物理感，与发送按钮 F2 家族同节奏。
   ──────────────────────────────────────────────────────────── */
.stop-marker {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  font-size: var(--tm-text-xs);
  color: var(--text-muted);
  opacity: 0.85;
  animation: tm-stop-settle var(--tm-dur-normal) var(--tm-ease-spring) both;
}
@keyframes tm-stop-settle {
  from {
    opacity: 0;
    transform: translateY(3px) scale(0.98);
  }
  to {
    opacity: 0.85;
    transform: translateY(0) scale(1);
  }
}
.stop-continue-btn {
  margin-left: 4px;
  padding: 3px 10px;
  border-radius: var(--tm-radius-full);
  font-size: var(--tm-text-2xs);
  font-weight: var(--tm-weight-semibold);
  cursor: pointer;
  color: rgb(var(--primary-glow-rgb));
  background: rgba(var(--primary-glow-rgb), 0.08);
  border: 1px solid rgba(var(--primary-glow-rgb), 0.25);
  transition: background var(--tm-dur-fast) var(--tm-ease-out),
    transform var(--tm-dur-fast) var(--tm-ease-spring);
}
.stop-continue-btn:hover {
  background: rgba(var(--primary-glow-rgb), 0.16);
  transform: translateY(-1px);
}
.stop-continue-btn:active {
  transform: translateY(0) scale(0.96);
}

/* ────────────────────────────────────────────────────────────
   5) R1 空态合并版 hero（s03 · E-3 架构 × A-B1 视觉 × 06§4 基准）：
      品牌 orb 呼吸 + 时段问候 + 文档感知 bento 行动牌（stagger 进场，
      玻璃卡 + 品牌紫强调 + spring 微交互）。#D97706 = 品牌金
      （与 modelDropdown PRODUCT_LOGO_SVG 内联色一致）。
      reduce 下动画由 system.css 全局层退化，离场 remove 归 messageList。
   ──────────────────────────────────────────────────────────── */
.chat-welcome-slot {
  display: contents;
}
.chat-welcome {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--tm-space-2);
  margin: auto 0;
  padding: 40px 16px 20px;
}
.chat-welcome-orb {
  width: 46px;
  height: 46px;
  color: #D97706;
  opacity: 0.92;
  animation: tm-welcome-orb-breathe var(--tm-dur-ambient) var(--tm-ease-out) infinite;
}
.chat-welcome-orb svg {
  width: 100%;
  height: 100%;
}
@keyframes tm-welcome-orb-breathe {
  0%,
  100% {
    transform: scale(1);
    filter: drop-shadow(0 0 6px rgba(var(--primary-glow-rgb), 0.22));
  }
  50% {
    transform: scale(1.06);
    filter: drop-shadow(0 0 14px rgba(var(--primary-glow-rgb), 0.42));
  }
}
.chat-welcome-title {
  font-size: var(--tm-text-lg);
  font-weight: var(--tm-weight-semibold);
  color: var(--text-primary);
  animation: tm-welcome-rise var(--tm-dur-slow) var(--tm-ease-expo) both;
}
.chat-welcome-sub {
  font-size: var(--tm-text-sm);
  color: var(--text-muted);
  max-width: 300px;
  animation: tm-welcome-rise var(--tm-dur-slow) var(--tm-ease-expo) 0.06s both;
}
.chat-welcome-chips {
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-2);
  margin-top: var(--tm-space-3);
  width: min(320px, 92%);
}
.chat-welcome-chip {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  padding: 12px 14px;
  border-radius: var(--tm-radius-xl);
  text-align: left;
  cursor: pointer;
  background: var(--tm-glass-bg-faint);
  border: 1px solid var(--tm-brand-purple-alpha-10);
  backdrop-filter: blur(var(--tm-glass-blur-soft)) saturate(var(--tm-glass-saturate));
  -webkit-backdrop-filter: blur(var(--tm-glass-blur-soft)) saturate(var(--tm-glass-saturate));
  transition: border-color var(--tm-dur-fast) var(--tm-ease-out),
    box-shadow var(--tm-dur-fast) var(--tm-ease-out),
    background var(--tm-dur-fast) var(--tm-ease-out),
    transform var(--tm-dur-fast) var(--tm-ease-spring);
  animation: tm-welcome-rise var(--tm-dur-slow) var(--tm-ease-expo) both;
}
.chat-welcome-chip:nth-child(1) {
  animation-delay: 0.1s;
}
.chat-welcome-chip:nth-child(2) {
  animation-delay: 0.16s;
}
.chat-welcome-chip:nth-child(3) {
  animation-delay: 0.22s;
}
.chat-welcome-chip:hover {
  border-color: var(--tm-brand-purple-alpha-28);
  box-shadow: 0 4px 16px var(--tm-brand-purple-alpha-10);
  transform: translateY(-1px);
}
.chat-welcome-chip:active {
  transform: translateY(0) scale(0.98);
}
.chat-welcome-chip.featured {
  background: var(--tm-glass-bg);
  border-color: var(--tm-brand-purple-alpha-28);
  box-shadow: 0 2px 10px var(--tm-brand-purple-alpha-08);
}
.chat-welcome-chip .chip-icon {
  flex-shrink: 0;
  display: inline-flex;
  color: var(--tm-brand-purple);
}
.chat-welcome-chip .chip-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.chat-welcome-chip .chip-title {
  font-size: var(--tm-text-md);
  font-weight: var(--tm-weight-medium);
  color: var(--text-primary);
}
.chat-welcome-chip .chip-hint {
  font-size: var(--tm-text-xs);
  color: var(--text-muted);
}
@keyframes tm-welcome-rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.chat-welcome.leaving {
  opacity: 0;
  transform: translateY(-10px) scale(0.98);
  transition: opacity var(--tm-dur-normal) var(--tm-ease-out),
    transform var(--tm-dur-normal) var(--tm-ease-out);
}
@supports not ((backdrop-filter: blur(1px))) {
  .chat-welcome-chip {
    background: var(--tm-glass-fallback-bg);
  }
}

/* ────────────────────────────────────────────────────────────
   6) s06 打磨批（01_PLAN C1/C2/C4/C8）：长会话性能 / 滚动语义 /
      代码块折叠 / 同模型分组与压缩段隐藏。
   ──────────────────────────────────────────────────────────── */

/* C1 · 恢复会话批量化：restoring 期间禁入场动画，瞬时呈现无群舞 */
.chat.restoring .message {
  animation: none;
  opacity: 1;
  transform: none;
}

/* C1 · 渐进渲染裁剪：视口外消息跳过渲染（Chromium 85+ 生效，旧内核忽略；
   入场动画只在视口内触发，与 slide-in-up 共存无冲突） */
.chat .message {
  content-visibility: auto;
  contain-intrinsic-size: auto 72px;
}

/* C2 · 离底期间收到新增量：scroll-status 按钮亮圆点 */
/* 定位祖先 = composer-container（按钮在 glass-panel 之外，免受其 overflow:hidden 裁切） */
.composer-container {
  position: relative;
}

.composer-glass-panel {
  position: relative;
}

#btn-scroll-status.scroll-status-btn {
  position: absolute;
  /* U8c：移至左列 "+" 按钮正上方（用户反馈恢复旧布局：↓ 在 ➕ 之上） */
  inset-inline-start: var(--tm-space-3);
  bottom: calc(100% + var(--tm-space-2));
  width: var(--tm-space-6);
  height: var(--tm-space-6);
  padding: 0;
  overflow: visible;
  color: var(--tm-brand-blue);
  background: var(--tm-glass-bg-strong);
  border: 1px solid color-mix(in srgb, var(--tm-brand-blue) 28%, transparent);
  box-shadow: var(--tm-shadow-2);
  opacity: 0;
  pointer-events: none;
  transform: translateY(var(--tm-space-2)) scale(0.96);
  transition:
    opacity var(--tm-dur-fast) var(--tm-ease-out),
    transform var(--tm-dur-fast) var(--tm-ease-out),
    background var(--tm-dur-fast) var(--tm-ease-out),
    border-color var(--tm-dur-fast) var(--tm-ease-out);
}

#btn-scroll-status.scroll-status-btn.scrolled-up {
  height: var(--tm-space-6);
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0) scale(1);
  background: var(--tm-glass-bg);
}

#btn-scroll-status.scroll-status-btn.scrolled-up:hover {
  background: var(--tm-glass-bg-strong);
  border-color: color-mix(in srgb, var(--tm-brand-blue) 42%, transparent);
  transform: translateY(0) scale(1);
}

.scroll-status-btn.has-new {
  position: relative;
}
.scroll-status-btn.has-new::after {
  content: "";
  position: absolute;
  top: 2px;
  right: 2px;
  width: 6px;
  height: 6px;
  border-radius: var(--tm-radius-full);
  background: rgb(var(--primary-glow-rgb));
  box-shadow: 0 0 6px rgba(var(--primary-glow-rgb), 0.8);
}

/* C4 · 代码块 sticky 语言头：wrapper 放开裁剪（圆角改由首尾元素自持），
   header 粘在 chat 视口顶；悬浮时背后是代码文字 → 底色必须不透明 */
.markdown-body .code-block-wrapper {
  overflow: visible;
}
.markdown-body .code-block-header {
  position: sticky;
  top: 0;
  z-index: 1;
  border-radius: 12px 12px 0 0;
  background: #1a212e; /* ≈ 原 3% white 叠加 #111827 的不透明合成值 */
}
:root[data-theme="dark"] .markdown-body .code-block-header {
  background: #161616; /* ≈ 原 rgba(30,30,30,.4) 叠加 #0a0a0a */
}
.markdown-body .code-block-wrapper pre {
  border-radius: 0 0 12px 12px;
}

/* C4 · 超长代码块折叠：380px 渐隐窗口 + 尾部展开按钮 */
.markdown-body .code-block-wrapper.collapsed pre {
  max-height: 380px;
  overflow: hidden;
  border-radius: 0;
  -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent);
  mask-image: linear-gradient(to bottom, #000 82%, transparent);
}
.markdown-body .code-expand-btn {
  width: 100%;
  padding: 8px;
  font-size: var(--tm-text-2xs);
  font-weight: var(--tm-weight-semibold);
  letter-spacing: 0.02em;
  color: var(--text-muted);
  background: transparent;
  border: none;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 0 0 12px 12px;
  cursor: pointer;
  transition: color var(--tm-dur-fast) var(--tm-ease-out),
    background var(--tm-dur-fast) var(--tm-ease-out);
}
.markdown-body .code-expand-btn:hover {
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.04);
}

/* C8 · 同模型连答折叠 sender：分组视觉（gap 28px 视觉折半） */
.message-ai--cont .message-sender {
  display: none;
}
.message-ai--cont {
  margin-top: -14px;
}

/* C8 · 压缩段隐藏（display:none 表达「已压缩不再计入上下文」的真实语义，
   直接减负渲染——与 C1 相辅）；show-compacted 下降透明恢复可见 */
.message.compacted {
  display: none;
}
.chat.show-compacted .message.compacted {
  display: flex;
  opacity: 0.55 !important; /* 压过 styles.css 的 0.22 !important 存量补丁 */
  filter: none;
}
.compacted-toggle {
  align-self: center;
  padding: 4px 12px;
  max-width: 800px;
  border-radius: var(--tm-radius-full);
  font-size: var(--tm-text-2xs);
  font-weight: var(--tm-weight-medium);
  color: var(--text-muted);
  background: var(--tm-glass-bg-faint);
  border: 1px solid var(--tm-brand-purple-alpha-10);
  cursor: pointer;
  transition: color var(--tm-dur-fast) var(--tm-ease-out),
    border-color var(--tm-dur-fast) var(--tm-ease-out),
    transform var(--tm-dur-fast) var(--tm-ease-spring);
}
.compacted-toggle:hover {
  color: var(--text-secondary);
  border-color: var(--tm-brand-purple-alpha-28);
  transform: translateY(-1px);
}
.compacted-toggle:active {
  transform: translateY(0) scale(0.97);
}

/* ────────────────────────────────────────────────────────────
   7) E§5.5 · 回访「上次进度」卡（>4h 回流时消息流末尾轻卡）：
      玻璃底 + 品牌紫点缀，与消息流形态区隔但不喧宾。
   ──────────────────────────────────────────────────────────── */
.resume-card {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 12px;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
  padding: 10px 14px;
  border-radius: var(--tm-radius-xl);
  background: var(--tm-glass-bg-faint);
  border: 1px solid var(--tm-brand-purple-alpha-10);
  animation: tm-block-reveal var(--tm-dur-normal) var(--tm-ease-out) both;
}
.resume-card-body {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.resume-card-clock {
  flex-shrink: 0;
  display: inline-flex;
  color: var(--tm-brand-purple);
  opacity: 0.85;
}
.resume-card-text {
  font-size: var(--tm-text-xs);
  line-height: 1.5;
  color: var(--text-muted);
}
.resume-card-actions {
  display: flex;
  gap: 8px;
  margin-left: auto;
}
.resume-card-btn {
  padding: 4px 12px;
  border-radius: var(--tm-radius-full);
  font-size: var(--tm-text-2xs);
  font-weight: var(--tm-weight-semibold);
  cursor: pointer;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid var(--tm-brand-purple-alpha-10);
  transition: color var(--tm-dur-fast) var(--tm-ease-out),
    border-color var(--tm-dur-fast) var(--tm-ease-out),
    transform var(--tm-dur-fast) var(--tm-ease-spring);
}
.resume-card-btn:hover {
  border-color: var(--tm-brand-purple-alpha-28);
  transform: translateY(-1px);
}
.resume-card-btn:active {
  transform: translateY(0) scale(0.97);
}
.resume-card-btn--primary {
  color: rgb(var(--primary-glow-rgb));
  background: rgba(var(--primary-glow-rgb), 0.08);
  border-color: rgba(var(--primary-glow-rgb), 0.25);
}
