/* 说话页：一屏就是一个对话，顶栏之下全归它。
   老内核（AGENTS.md）：布局只用普遍支持的写法——flex、百分比、vh。
   新语法只在能自己站住的旧写法之后当增强线出现，掉了也不影响布局。 */

.chat-body {
  height: 100vh;
  /* 手机上地址栏收放会改 100vh；dvh 认得就跟着走，不认得仍是上面那行。 */
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 手机上顶栏会换成两排（招牌一排、页签一排）。body 是 flex 列，而 flex 项默认
   可以被压缩：不写死这一行，下面那块会把顶栏挤扁，页签那排就被对话内容盖住。 */
.chat-body .topbar {
  flex: 0 0 auto;
}

/* 母版那层壳（Core 的 .shell-body：宽屏上左侧栏 + 内容）在这一页也要满高，
   不然对话被压成一行。默认它是个普通的块，这里让它跟着 body 一起铺满。 */
.chat-body .shell-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: row;
}

/* 顶栏之下的一整块都是对话。container 的上下留白和 1280 的宽度是给文档页
   的，这里要的是满宽、满高：左栏贴着窗口左边缘（业主 2026-09-14 真机截图：
   2000 宽的屏上清单悬在中间偏左，左边空出一大块），对话栏在剩下的空间里居中。 */
.chat-main.container {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  max-width: none;
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* 对话本身（业主 2026-09-14：跟主流对话产品一致，随时新建会话）。会话清单
   2026-09-19 搬去了左侧栏，所以这里剩下的是对话栏和它两侧的留白。 */
.chat-shell {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: row;
  /* 对话区最深：对话栏居中，两侧的留白也是它的一部分，所以底色铺在整块上，左栏盖住自己那条。 */
  background: var(--surface-sunken);
}

/* ---- 会话清单：住在 Core 那条左侧栏的中段（业主 2026-09-19）--------------
   宽屏上它是 .railbar-page 里唯一的孩子，宽度由栏说了算（--rail-w），高度把中段
   占满、自己内部滚动——原来的 flex:0 0 260px 是「在一排里占 260」，在竖着排的栏
   里那个数会变成高度，清单就只剩 260 高。
   手机上它仍然是自己的抽屉（position:fixed，见文件末尾那段媒体查询），跟栏无关。 */

.chat-side {
  flex: 1 1 auto;
  width: auto;
  /* flex 项的 min-width 默认是 auto＝内容最小宽：一条不折行的标题会把整栏撑到
     347 像素（2026-09-14 直渲量出来的），这一行才让栏宽是栏宽。 */
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* 三块面各一档、不描线：对话区最深，左栏是页底那档（业主 2026-09-15：
     「应该聊天内容窗口的背景色最深，现在是会话列表最深，信息层级错误」）。
     栏本身就是这一档，所以这里不再自己铺一层。 */
  background: transparent;
}

/* 头：一条工具栏——收起、搜索，右边一颗「新会话」钮（A2，业主 2026-09-15）。 */
.chat-side-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-3) 0;
}

/* 两行动作：新会话、搜索（业主 2026-09-15：各自单独一行）。同一个样子，第二行是个输入框。 */
.chat-side-actions {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 var(--space-2) var(--space-1);
}

/* 这两行是「做什么」，上面那两项是「去哪儿」——排成一摞就该至少一样大。字号
   原来是 13，而导航是 15，于是整条栏里最常按的「新会话」字最小（业主 2026-09-19
   的设计评审）。「去哪儿」那两行（技能库、任务）是 aimy.css 的 .railbar-go-link，
   抄的是这里同一套数——任务页、用量页不带这份样式表；改这里就一起改那里。 */
.chat-side-action {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: var(--text-base);
  text-decoration: none;
}

.chat-side-action:hover {
  background: var(--surface-2);
  color: var(--fg);
  text-decoration: none;
}

/* 「新会话」比旁边几行重一档：字是亮的、字重高一档。2026-09-19 给它加过一条
   边框，业主当天就撤了——「移除边框样式（没必要加强）」。字号已经跟导航齐了，
   再框一道就是第二次强调同一件事。 */
.chat-side-new {
  color: var(--fg);
  font-weight: var(--weight-medium);
}

.chat-side-new:hover {
  color: var(--gold-bright);
}

.chat-side-tool,
.chat-rail-btn {
  flex: 0 0 auto;
  width: var(--control-md);
  height: var(--control-md);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--muted);
  cursor: pointer;
  text-decoration: none;
}

.chat-side-tool:hover,
.chat-rail-btn:hover {
  background: var(--surface-2);
  color: var(--fg);
  text-decoration: none;
}

/* 「展开」跟「收起」同住栏头那一格，一次只露一个。展开的那一颗平时不在——
   栏是开着的，没什么可展。收起来之后它才出场，样子见文件下面 641 那一段。 */
.chat-side-unfold {
  display: none;
}

/* 两行动作：新会话、搜会话。同一个样子，第二行是个输入框。 */
/* 栏底一行小字：已归档。 */
.chat-side-foot {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2) var(--space-3);
}

/* 文件夹与平铺会话之间的一道细线。 */
.chat-side-divider {
  height: 1px;
  margin: 6px var(--space-3);
  background: var(--line-soft);
}

.chat-side-divider[hidden] {
  display: none;
}

/* 抽屉的关闭钮只在手机上出现（见下面的媒体查询）。 */
/* 按钮只有三种高（28/32/40，2026-09-15 设计评审第二批）：清单的开合钮是中一档。 */
.chat-side-close {
  display: none;
  flex: 0 0 auto;
  width: var(--control-md);
  height: var(--control-md);
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--muted);
  cursor: pointer;
}

.chat-side-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 0 var(--space-2) var(--space-2);
}

.chat-session {
  display: flex;
  align-items: baseline;
  min-width: 0;
  overflow: hidden;
  gap: var(--space-2);
  margin-bottom: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: var(--text-sm);
  text-decoration: none;
  transition:
    background-color 0.15s ease,
    color 0.15s ease;
}

/* display 会压过浏览器自己的 [hidden]：搜索筛清单时脚本按 hidden 藏行，
   没有这一条，直接挂在清单下的那一行（还没入库的新会话）藏不掉。 */
.chat-session[hidden] {
  display: none;
}

.chat-session:hover {
  background: var(--surface-2);
  color: var(--fg);
  text-decoration: none;
}

.chat-session.is-current {
  background: var(--gold-soft);
  color: var(--fg);
  font-weight: var(--weight-medium);
}

.chat-session.is-current .chat-session-when {
  color: var(--muted);
}

.chat-session-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.chat-session-when {
  flex: 0 0 auto;
  color: var(--faint);
  font-size: var(--text-2xs);
}

/* 一行 = 链接 + 尾巴上的「···」。按钮压在时刻那个位置上，鼠标停上去时刻让位；
   当前这一间常显（手机没有 hover，至少当前这间能动）。 */
.chat-session-row {
  position: relative;
}

.chat-session-more {
  position: absolute;
  top: 50%;
  right: var(--space-2);
  width: var(--control-sm);
  height: var(--control-sm);
  margin-top: -14px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  transition:
    opacity 0.12s ease,
    background-color 0.15s ease;
}

.chat-session-more svg {
  display: block;
}

.chat-session-row:hover .chat-session-more,
.chat-session-row.is-current .chat-session-more,
.chat-session-row.is-open .chat-session-more,
.chat-session-more:focus {
  opacity: 1;
}

.chat-session-more:hover,
.chat-session-row.is-open .chat-session-more {
  background: var(--surface-3);
  color: var(--fg);
}

.chat-session-row:hover .chat-session-when,
.chat-session-row.is-current .chat-session-when,
.chat-session-row.is-open .chat-session-when {
  visibility: hidden;
}

/* 共用的那张菜单：fixed，脚本按点的那颗按钮摆位置。 */
.chat-session-menu {
  position: fixed;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 8rem;
  padding: var(--space-1);
  border-radius: var(--radius);
  background: var(--surface-2);
  box-shadow: var(--shadow-2);
}

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

.chat-session-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  box-sizing: border-box;
  height: var(--control-md);
  padding: 0 var(--space-3) 0 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--fg-soft);
  font-size: var(--text-sm);
  font-weight: var(--weight-normal);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.chat-session-menu-item[hidden] {
  display: none;
}

.chat-session-menu-item:hover {
  background: var(--surface-3);
  color: var(--fg);
}

.chat-session-menu-item .chat-icon {
  color: var(--muted);
}

.chat-session-menu-danger,
.chat-session-menu-danger .chat-icon {
  color: var(--red);
}

/* 「归到项目」底下折着的项目名：缩进一格，当前归的那个前面一个勾。 */
.chat-session-menu-sub {
  border-top: 1px solid var(--line-soft);
  margin-top: 2px;
  padding-top: 2px;
  max-height: 14rem;
  overflow-y: auto;
}

.chat-session-menu-sub[hidden] {
  display: none;
}

.chat-session-menu-project {
  position: relative;
  padding-left: var(--space-6);
}

.chat-session-menu-project.is-current::before {
  content: "✓";
  position: absolute;
  left: var(--space-3);
  color: var(--gold);
}

.chat-session-menu-unfile {
  color: var(--muted);
}

/* 整块项目的总开关（业主 2026-09-16）：一行「项目 N」，小三角开着朝下、合上朝右，
   收起后底下所有文件夹一起藏。字跟会话行一样大、比文件夹名深一档（业主同日：「『项目』文字
   好像小了」），底下的文件夹缩进一格，看得出是它的下级。 */
.chat-side-projects[hidden] {
  display: none;
}

.chat-side-projects > summary {
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--fg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  user-select: none;
}

.chat-side-projects > summary::-webkit-details-marker {
  display: none;
}

.chat-side-projects > summary:hover {
  background: var(--surface-2);
}

.chat-side-projects > .chat-side-folder {
  margin-left: 12px;
}

.chat-side-projects-caret {
  flex: none;
  transition: transform 0.12s ease;
}

.chat-side-projects[open] > summary .chat-side-projects-caret {
  transform: rotate(90deg);
}

/* 项目文件夹（业主 2026-09-15）：段名是 summary，前面一个会转的小三角，右边一个「+」。
   段名比时间段名深一档：它是名字，不是日期。 */
.chat-side-folder[hidden] {
  display: none;
}

.chat-side-folder > summary {
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--fg-soft);
  font-size: var(--text-sm);
  cursor: pointer;
  user-select: none;
}

.chat-side-folder > summary::-webkit-details-marker {
  display: none;
}

.chat-side-folder > summary:hover {
  background: var(--surface-2);
  color: var(--fg);
}

/* 打开的那个项目：字重一档、图标变金；里面的会话靠一根竖线缩进（A2）。 */
.chat-side-folder[open] > summary {
  color: var(--fg);
  font-weight: var(--weight-medium);
}

.chat-side-folder-icon {
  flex: none;
  color: var(--muted);
}

.chat-side-folder[open] > summary .chat-side-folder-icon {
  color: var(--gold);
}

.chat-side-folder-body {
  margin: 0 0 var(--space-1) 19px;
  padding-left: var(--space-1);
  border-left: 1px solid var(--line);
}

.chat-side-folder-body .chat-session {
  padding-left: 10px;
}

.chat-side-folder-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 「+」：电脑上悬停才出，手机没有悬停所以常显（见手机那段）。图标是画的不是打的。 */
.chat-side-folder-new {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-left: auto;
  border-radius: var(--radius-sm);
  color: var(--muted);
  opacity: 0;
  transition: opacity 0.12s ease;
}

.chat-side-folder > summary:hover .chat-side-folder-new,
.chat-side-folder-new:focus {
  opacity: 1;
}

.chat-side-folder-new:hover {
  background: var(--surface-3);
  color: var(--fg);
}

/* 收起态（方案 A）：整栏缩成 56 宽的窄轨，只剩展开、新会话、搜索三个钮。只在电脑上——
   手机上清单是抽屉，这一套不生效。用 min-width 的媒体查询，老内核都认。
   2026-09-19 起收的是整条左侧栏：宽度归 aimy.css 的 .is-rail-folded 管（栏是
   fixed 的，占位的是 .shell-body，CSS 读不到孩子的状态，所以记号挂在 body 上，
   由 chat-sessions.js 一并挂）。这里只管清单自己里面收起来什么、露出什么。 */
.chat-rail {
  display: none;
}

@media (min-width: 641px) {
  /* 这一行只剩抽屉的关闭钮，而关闭钮只在手机上出现——电脑上留着它就是清单顶上
     一道十二像素的空档（2026-09-19 把「收起清单」搬去栏头之后剩下的）。 */
  .chat-side-head {
    display: none;
  }

  .chat-side.is-folded > .chat-side-head,
  .chat-side.is-folded > .chat-side-actions,
  .chat-side.is-folded > .chat-search-results,
  .chat-side.is-folded > .chat-side-list,
  .chat-side.is-folded > .chat-side-foot {
    display: none;
  }

  .chat-side.is-folded > .chat-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-3) 0;
  }

  /* 收起来之后，栏头那一格换成「展开」，排在头像正下方自己一行（业主 2026-09-19：
     「展开按钮独立，放在 aimy 头像下方就行」）。栏头怎么变成一列在 aimy.css 的
     `.is-rail-folded .railbar-head`；这里只管两颗钮谁露面。

     收和展都在栏头，位置差一行——它原来是窄轨的第一颗，排在招牌和三项导航底下，
     收的时候手在最上面，展的时候得往下走近两百像素再找一遍。中间试过让头像
     hover 变成展开，业主当场否了：招牌和开关是两件事，不该是同一个东西。 */
  .is-rail-folded .chat-side-fold {
    display: none;
  }

  .is-rail-folded .chat-side-unfold {
    display: flex;
  }
}

.chat-rail-btn {
  position: relative;
}

.chat-rail-sep {
  width: 24px;
  height: 1px;
  margin: var(--space-2) 0;
  background: var(--line-soft);
}

.chat-rail-dot {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--gold);
}

.chat-rail-dot[hidden] {
  display: none;
}

.chat-session-menu-danger:hover {
  background: var(--red-soft);
  color: var(--red);
}

.chat-side-empty {
  margin: var(--space-4) var(--space-3);
  color: var(--faint);
  font-size: var(--text-xs);
}

.chat-side-archived {
  flex: 1 1 auto;
  min-width: 0;
  max-height: 40vh;
  overflow-y: auto;
}

.chat-side-archived > summary {
  padding: var(--space-2) var(--space-3);
  color: var(--faint);
  font-size: var(--text-xs);
  cursor: pointer;
  list-style: none;
}

.chat-side-archived > summary::-webkit-details-marker {
  display: none;
}

.chat-side-count {
  color: var(--faint);
}

.chat-session.is-archived {
  color: var(--faint);
}

/* ---- 右边：这一个会话 ------------------------------------------------- */

/* 780：一行正文 740 像素，约 49 个汉字（业主 2026-09-22：「整体显示的宽度可以再稍微
   加一点，多显示内容」）。09-19 的设计评审从 860（55 字）收到 700（44 字），理由是中文
   舒服的区间在 35–45；业主用下来要的是一屏多装一点，于是退回一半。输入框跟着这一栏走。 */
.chat-pane {
  position: relative;
  /* 基准就是它的上限：多出来的空余一分不留给它，全归两边的垫子；窄了它自己缩。 */
  flex: 1 1 780px;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  max-width: 780px;
  order: 2;
}

/* 对话栏居中：左栏右边的空余左右对半分（业主 2026-09-19：「去掉，保持简单」）。
   09-17 它是一比二——右边留两份给将来的画布、预览；同一天正文从 860 收到 700 之后
   我问他那块地要不要留，他说不留。于是这里只剩一条规矩：这一栏在它自己那块地方
   正中间，没有第二种解释。

   垫子是 .chat-shell 的两个伪元素，用 order 排到左栏之后、对话栏两侧（伪元素本身
   生在首尾）；文件抽屉是 absolute，不参与。窄屏上空余是负的，垫子基准为零缩不动，
   缩的是对话栏，跟以前一样。 */
.chat-shell::before,
.chat-shell::after {
  content: "";
  flex: 1 1 0;
  min-width: 0;
}

.chat-shell::before {
  order: 1;
}

.chat-shell::after {
  order: 3;
}

/* 清单抽屉的钮住在输入框第二行最左边（手机上才出现，见底下的媒体查询）；
   样子是输入框里的工具钮（.chat-tool），角上挂在跑的会话数。 */
.chat-tool.chat-side-toggle {
  display: none;
  position: relative;
}

/* ---- 滚动区 ---------------------------------------------------------- */

.chat-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* 头部那一行拿掉了（业主 2026-09-15），第一条消息离顶栏留一口气。 */
  padding: var(--space-6) var(--space-5) var(--space-2);
  /* 一句话长出来时不要把整页往上顶着抖。 */
  overflow-anchor: none;
}

/* 竖向的间距是量过再定的，三次：
   08-29（「竖向空间使用不够紧凑」）一轮问答 136 像素里字只有 50，压到 96。
   09-19 换人的间距加到 32，让「新的一条」和「段落之间」（12）分得开。
   09-22（业主：「竖向各种间隙，你复盘一下，看能否稍微紧凑一点，但是不要牺牲不同
   信息之间必要的间隔」）量出来的大头不在这里写的任何一个数，而在每条消息底下那一行
   时刻／复制／重答：平时看不见（只在鼠标停上去时出现），却照样占着 28＋4——看不见的
   一行跟后面的间距叠在一起，换人时的空白实际是 64，同一个人连说是 40；「派单机制
   说明」那一段 1650 像素里空白 540，一半多是这些看不见的行。
   现在那一行只自己占 8，另外 20 伸进下面的间距里（见下面的 .chat-column > .chat-meta）；
   代价是间距不能再小于 20，否则鼠标停上去时那一行会压到下一条上。于是：同一个人
   连说 20、换人 32（下一条），看到的空白分别是 28 和 40，都还是段落间距的两倍以上。 */
.chat-thread {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  /* 最后一条底下那一行伸出来的 20，由这里接住，不然它盖到底下那张脸上。 */
  padding-bottom: var(--space-5);
}

/* 20 这个数跟上面的间距是同一个：伸出去多少，间距就至少留多少。 */
.chat-column > .chat-meta {
  margin-top: 0;
  margin-bottom: -20px;
}

/* 带了附件的回执（最常见的就是派单交回：一句话加一张成品卡）按普通的一条排。
   回执的「整条行内、签跟在句尾」（messages.css）是给一句话的；里面一放进块级的卡，
   行内的气泡就被拆成三段，头尾各剩一行空的——上面 24、卡下面 28，都是看不见的
   空行（2026-09-22 量出来的：「派出去了」到「回来了」之间空了 55）。一句话的回执
   不带附件，照旧行内。 */
.chat-turn-receipt.has-attachments .chat-column {
  display: flex;
}

.chat-turn-receipt.has-attachments .chat-bubble {
  display: block;
}

.chat-turn-receipt.has-attachments .chat-bubble > p:last-child {
  display: block;
}

.chat-turn-receipt.has-attachments .chat-meta {
  display: flex;
  margin-left: 0;
  padding-left: var(--space-1);
}

/* 同一个人连着说贴紧（上面那 20），换人时多留一档（业主 2026-09-14：Aimy 连说
   三句和「说完换你说」一个间距，整段读起来是一整块字）。相邻选择器老内核认；
   回执行是 Aimy 那一边的，跟它同侧。 */
.chat-turn-aimy + .chat-turn-mine,
.chat-turn-aimy + .chat-turn-other,
.chat-turn-mine + .chat-turn-aimy,
.chat-turn-mine + .chat-turn-other,
.chat-turn-other + .chat-turn-aimy,
.chat-turn-other + .chat-turn-mine {
  /* 12（加上 .chat-thread 自己那 20）＝换人时 32，而同一条回复里段落之间是 12
     ——业主 2026-09-19 的设计评审定的 32：原来合计 20，跟段落间距只差 1.8 倍，
     于是「这是新的一条」和「上一条还没说完」读起来一个样。 */
  margin-top: var(--space-3);
}

/* 空手进来的时候，滚动区里只有问候那一格，让它坐在正中。 */
.chat-scroll.is-empty {
  display: flex;
  flex-direction: column;
}

.chat-scroll.is-empty .chat-thread {
  flex: 1 1 auto;
  justify-content: center;
}

/* 而且只有一张脸：底下那一格连同它的脸一起让位——问候那张已经在说
   「它在这儿」了，两张脸同时看着你只是重复。 */
.chat-scroll.is-empty .chat-doing {
  display: none;
}

.chat-older {
  align-self: center;
  color: var(--faint);
  font-size: var(--text-xs);
  padding: var(--space-2) 0;
}

/* 上下文重新开始的那道线：比日期线醒目一档，横贯整栏。 */
.chat-reset {
  align-self: stretch;
  margin: var(--space-3) 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-1);
  color: var(--muted);
  font-size: var(--text-xs);
  text-align: center;
}

/* 只留底色，不描边（业主 2026-08-29）：一句话已经靠底色和位置说清了是谁说的，
   再框一圈就是把同一件事说两遍。角比正文里的卡片大一档：一句话的气泡矮，
   12 的角在 40 高的框上看着是方的。 */
.chat-turn-mine .chat-bubble {
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--gold-soft);
  border: 0;
}

/* 时刻跟复制、编辑、重答同待遇：读的时候一个灰数字都没有，鼠标停上去才出现
   （业主 2026-08-29 两次说太占地方）。 */
.chat-when,
.chat-meta .chat-act {
  opacity: 0;
  transition:
    opacity 0.15s ease,
    color 0.15s ease,
    background-color 0.15s ease;
}

.chat-turn:hover .chat-when,
.chat-turn:hover .chat-act {
  opacity: 1;
}

/* 键盘走到钮上也要看得见。单独一条：旧内核（EdgeHTML 18）不认 :focus-visible，
   写进上面那个选择器列表就会把整条规则——连同悬停显示——一起作废，于是
   「复制／时刻」在那台机器上永远出不来。 */
.chat-meta .chat-act:focus-visible {
  opacity: 1;
}

/* 手机上没有 hover：钮一直在，提示条不出（点一下就是按下去了，没有「停上去」
   这回事）。时刻仍然不出现——它正是占地方的那个，而手机上更缺地方。 */
@media (hover: none) {
  .chat-meta .chat-act {
    opacity: 1;
  }
}

/* ---- 它此刻在干什么 -------------------------------------------------- */
/* 一张脸，跟在消息流最下方。42 像素——一屏只有这一张，所以看得清表情：
   在想是眯着眼歪着头，在查是爪子从两边伸进来，在说是嘴跟着音量动。头顶那三个
   点在这一页不画（业主 2026-09-22）：旁边那个颜文字已经在动，语音房照旧有。 */

.chat-doing {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding-left: var(--space-1);
  /* 它是读数，不是控件。 */
  pointer-events: none;
  user-select: none;
}

/* 60 不是 42：那张脸的画布是 140 见方而头只有 100（呼吸、点头、语音房思考的点
   都要留在画布里，Safari 会裁掉越界的部分；这一页不画点，画布照旧）。所以框
   60 出来的头才是 43 —— 原来那版的尺寸。按框写就会一直觉得「怎么还是小」。 */
/* 歇着的时候它退后一档（业主 2026-09-19 的设计评审）：说完就停在最后一条回复
   底下、旁边一个字都没有，68 见方一张脸读起来像一件没说明的东西。它是「我在
   这儿」的指示，不是对话的一部分——有话说时自己长回来（chat.js 挂 is-idle）。
   退得太快太狠读起来像说完就跑（业主 2026-09-22）：chat.js 先等三秒再挂
   is-idle，这里退得慢（1.2 秒），也只退到 52（原来 40，是说话时 68 的六成，
   现在是四分之三）。慢只慢在退的这一下：transition 取的是「要去的那个状态」上
   写的，所以摘掉 is-idle、长回来时用的仍是 .chat-face 上那个快的。
   margin 跟着尺寸按比例收（画布每边空出七分之一），不然退的时候整行会跳一下。 */
.chat-doing.is-idle .chat-face {
  width: 52px;
  height: 52px;
  margin: 0 -7px -8px -8px;
  opacity: 0.45;
  transition:
    width 1.2s cubic-bezier(0.4, 0, 0.2, 1),
    height 1.2s cubic-bezier(0.4, 0, 0.2, 1),
    margin 1.2s cubic-bezier(0.4, 0, 0.2, 1),
    opacity 1.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.chat-face {
  flex: 0 0 auto;
  width: 68px;
  height: 68px;
  transition:
    width var(--motion-base) var(--ease-out),
    height var(--motion-base) var(--ease-out),
    margin var(--motion-base) var(--ease-out),
    opacity var(--motion-base) var(--ease-out);
  /* 画布 140 见方而头只有 100：四边各有 8.5 像素是空的（留给呼吸、点头和
     挂在头顶的东西）。布局上把左右和下面收回来——脸一点没小，那一格从 60 变
     46。上面不收：出错时那滴汗长在那儿（在想的三个点这一页不画了，业主
     2026-09-22）。 */
  margin: 0 -9px -10px -10px;
}

.chat-face svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

/* 字是脸说的，用它眼睛的颜色（业主 2026-09-14）。 */
.chat-doing-word {
  color: var(--face-eye);
  font-size: var(--text-xs);
}

/* 字后面原来跟着秒数，业主 2026-09-22 换成一个会自己动的颜文字（秒数让人着急）。
   分隔点淡一档：它只是把两样东西隔开，不是要读的字。 */
.chat-doing-sep {
  opacity: 0.55;
}

/* 颜文字大一档：它的笔画比汉字碎，同一个字号看着比旁边的字小。单独一个
   inline-block——换上新的时要弹一下，而 transform 对行内元素不起作用。
   pre：「( ･ω･)」里的空格是脸的一部分，也不许在脸中间折行。 */
.chat-kaomoji {
  display: inline-block;
  font-size: var(--text-sm);
  white-space: pre;
  transform-origin: 20% 60%;
}

/* 上面一设 display，hidden 属性就不管用了（AGENTS.md 那条）——光有字的时候
   （在说、在听）它得真的不在。 */
.chat-kaomoji[hidden] {
  display: none;
}

/* 新换上的那一个轻轻弹一下（业主 2026-09-22 看过预览选的）；帧切换只换字，不弹。 */
.chat-kaomoji.is-new {
  animation: chat-kaomoji-pop 0.42s cubic-bezier(0.3, 1.6, 0.5, 1);
}

@keyframes chat-kaomoji-pop {
  from {
    opacity: 0;
    transform: scale(0.4) translateY(3px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-kaomoji.is-new {
    animation: none;
  }

  .chat-face,
  .chat-doing.is-idle .chat-face {
    transition: none;
  }
}

/* 只给读屏的字：光在想时这一行看得见的只有颜文字，而颜文字对读屏是藏起来的
   （它每几百毫秒换一帧），所以留一句看不见的「在想」。aimy.css 没有这样的类。 */
.chat-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---- 空手进来的时候 -------------------------------------------------- */
/* 一句问候，脸大一档，跟输入框一起坐在中间——比一条「还没有消息」有礼貌，
   也是这一页第一次见面时唯一该说的话。 */

.chat-hello {
  margin: auto 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-12) var(--space-4);
  text-align: center;
}

.chat-hello .chat-face {
  width: 100px;
  height: 100px;
  margin-left: 0;
}

.chat-hello-word {
  margin: 0;
  color: var(--fg-soft);
  font-size: var(--text-lg);
  font-weight: var(--weight-normal);
  letter-spacing: 0.01em;
}

/* ---- 审批卡 ---------------------------------------------------------- */
/* 打字说「批准」在 2026-07-26 就退役了，卡片是唯一的路。这张卡点下去构造的
   是一个带 approval_id 的回合，跟企微那张卡走同一条路。 */

.chat-approval {
  margin-top: var(--space-2);
  padding: var(--space-4);
  border-radius: var(--radius);
  background: var(--gold-soft);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 100%;
}

.chat-approval-head {
  font-weight: var(--weight-semi);
}

.chat-approval-what {
  margin: 0;
  color: var(--fg-soft);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: break-word;
  max-height: 220px;
  overflow-y: auto;
}

.chat-approval-when {
  color: var(--muted);
  font-size: var(--text-xs);
}

.chat-approval-row {
  display: flex;
  gap: var(--space-2);
}

.chat-approval-ok {
  background: var(--gold);
  border-color: transparent;
  color: var(--surface-0);
  font-weight: var(--weight-medium);
}

.chat-approval-ok:hover {
  background: var(--gold-bright);
  border-color: transparent;
}

.chat-approval-done {
  color: var(--muted);
  font-size: var(--text-sm);
}

/* ---- 对话区里的卡：比页底只亮一档 ------------------------------------ */
/* 成品卡（样式在 messages.css）和派单卡取 surface-0，卡上的钮跟着降一档到 surface-1
   （业主 2026-09-22：「这些派单、文件的卡片，背景色和输入框还是太接近了，稍微改的暗
   一点」）。对话区是 sunken，卡片浮起来一档就够了；原来的 surface-1 是两档，输入框
   抬到 surface-3 之后它们只差两档，看着是一家的。钮和卡还是差一档，跟原来一样。
   写在这份而不是 messages.css：会话记录页也用那一份，它的页底本身就是 surface-0，
   卡片降过去在那一页就看不见了。 */
.chat-deliverable,
.chat-job {
  background: var(--surface-0);
}

.chat-deliverable-cover {
  background: var(--surface-1);
}

.chat-bubble a.chat-deliverable-btn,
.chat-deliverable-btn {
  background: var(--surface-1);
}

.chat-bubble a.chat-deliverable-btn:hover,
.chat-deliverable-btn:hover {
  background: var(--surface-2);
}

/* ---- 派单卡 ---------------------------------------------------------- */
/* 派出去的活在对话里有一张卡（2026-09-14），回执是另一条消息，卡只说结果。
   2026-09-22 照成品卡重排（业主：「重新设计这个派单完成的卡片，更简洁美观。去任务页看
   做成按钮的形式，和文件卡片一样……一定要保持整体视觉的统一」）：同宽、同底、同角；
   标题跟成品名同一档（亮字、半粗），说明那行跟成品卡的小字同一档，两颗钮就是成品卡
   的钮（chat.js 借的是同一个类）。
   在跑的那张原来整块泛金，现在跟别的卡同一个底：金只留在会呼吸的点和状态词上——
   一屏几张卡各一个底色，统一就没了；「此刻正在发生」由那颗在动的点说。跑完的那颗
   灰点撤掉：它不动也不变色，是一颗不说话的装饰。 */

/* 不另加上边距：它在对话里的位置跟 Aimy 连着说的下一条一样，间距归 .chat-thread。 */
.chat-job {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-width: 560px;
}

.chat-job-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.chat-job-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--gold);
  animation: chat-job-breath 1.6s ease-in-out infinite;
}

.chat-job.is-done .chat-job-dot {
  display: none;
}

@keyframes chat-job-breath {
  50% {
    opacity: 0.3;
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-job-dot {
    animation: none;
  }
}

.chat-job-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--fg);
  font-weight: var(--weight-semi);
}

.chat-job-label {
  flex: 0 0 auto;
  color: var(--gold);
  font-size: var(--text-xs);
  white-space: nowrap;
}

.chat-job.is-done .chat-job-label {
  color: var(--faint);
}

/* 结论的语气跟任务页那一格同一套（`task_room.html` 的 .task-card-outcome）：
   坏了是红、要留意的是亮一档的字、干净的不上色。选择器多一层 .chat-job，才压得住
   上面结束态把标签整体调暗的那条。 */
.chat-job .chat-job-label[data-tone="bad"] {
  color: var(--red);
  font-weight: var(--weight-medium);
}

.chat-job .chat-job-label[data-tone="warn"] {
  color: var(--fg-soft);
}

/* 跟成品卡的 .chat-deliverable-meta 同一档：12 号、最弱的字。 */
.chat-job-line {
  margin: 0;
  color: var(--faint);
  font-size: var(--text-2xs);
}

/* 为什么是这个结论的那一行：验收没过的第一条、施工队说的「卡在：」、Aimy 停它
   的理由。块级段落不设 display，hidden 属性自己就管用；下面那条是防以后有人加。 */
.chat-job-reason {
  margin: 0;
  color: var(--fg-soft);
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
  word-wrap: break-word;
}

.chat-job-reason[hidden] {
  display: none;
}

/* 钮那一排跟成品卡的 .chat-deliverable-actions 同一个间距。 */
.chat-job-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding-top: var(--space-2);
}

/* 停下是成品卡的钮加一个红的悬停。.chat-deliverable-btn 设了 display:flex，会压掉
   hidden 属性（AGENTS.md 那条），所以 [hidden] 要自己写回来，而且得比它重。 */
.chat-job .chat-job-stop:hover {
  background: var(--red-soft);
  color: var(--red);
}

.chat-job .chat-job-stop[hidden] {
  display: none;
}

/* ---- 底下的输入框 ---------------------------------------------------- */

/* 一行的时候所有东西都在框的正中，多行的时候按钮留在底下跟最后一行齐——这靠
   一个数：按钮 40 高、单行的输入框也是 40 高（22 的行高加上下各 9），于是
   flex-end 在单行时就是居中。2026-09-14 业主截图「元素有点靠下」量出来是回形针
   多了 8 像素上边距：它和气泡里的附件链接共用了 .chat-attach 这个类名，附件那条
   规则的 margin-top 落到了按钮上。框里那颗钮后来叫 .chat-clip，09-22 起是「＋」
   （.chat-add）；.chat-attach 这个类名只归气泡里的附件链接。 */
.chat-dock {
  position: relative;
  flex: 0 0 auto;
  padding: var(--space-2) var(--space-5) var(--space-3);
  background: var(--surface-sunken);
}

/* 输入框上方的一行：提醒条（没有就不占地方——它自己是 hidden，底边距长在它身上）。 */
.chat-dock-strip {
  display: flex;
  justify-content: flex-start;
}

.chat-dock-strip .chat-reminders {
  margin: 0 0 var(--space-2) var(--space-1);
}

/* 头部那枚「已归档」签拿掉后，归档的会话在输入框上方说一句。 */
.chat-archived-note {
  margin: 0 0 var(--space-2);
  color: var(--faint);
  font-size: var(--text-xs);
  text-align: center;
}

/* 输入框比卡片亮两档（业主 2026-09-22：「输入框内部的颜色和其他卡片颜色太像了，
   不够强调……也可以更大一点点，让人想要输入的感觉加强」）。原来它和交付卡、任务卡
   同是 surface-1，一屏几块一样的面，眼睛找不到哪块是给你打字的。仍然只靠面的深浅
   说话、不描边——「谁要描边，说明它要的其实是再亮一档的面」（设计系统开头那条）。
   高度从 56 抬到 64：多出来的 8 全给上下内衬，框里的字、工具钮、发送键仍在同一条
   中线上。 */
.chat-box {
  display: flex;
  align-items: flex-end;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
  /* 64 高的一半：单行时两头正圆（业主 2026-09-22：「圆角不好看了，不够圆了」——高度
     从 56 抬到 64 时角还是 24，就从胶囊变成了圆角方块）。不写 pill：打到多行时框会
     长到两百多高，pill 会把它变成一根两头圆的柱子。 */
  border-radius: 32px;
  background: var(--surface-3);
  box-shadow: var(--shadow-1);
  transition: background-color 0.15s ease;
}

/* 落焦时再亮一档，不描金圈：光标本身已经在说「在这儿打字」。 */
.chat-box:focus-within {
  background: var(--surface-4);
}

.chat-text {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 40px;
  max-height: 180px;
  padding: 9px var(--space-2);
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--fg);
  font: inherit;
  font-size: var(--text-base);
  line-height: 22px;
  resize: none;
  overflow-y: auto;
}

/* 提示字用 muted 不用 faint：faint 在亮两档的面上只剩 3.9 的对比度（surface-4 上
   3.4），低于读得清的 4.5；muted 在 surface-3 上 5.1、surface-4 上 4.5。 */
.chat-text::placeholder {
  color: var(--muted);
}

.chat-text:focus {
  outline: none;
}

/* 同样单独一条，理由见上面的 .chat-copy:focus-visible。 */
.chat-text:focus-visible {
  outline: none;
}

/* 输入框里三类钮，长得不一样是因为干的事不一样（业主 2026-09-15：「文件按钮整合到
   底部的输入框……不同的功能样式设计合理」）：
   - 工具钮 .chat-tool（「＋」、正在听时的麦克风、手机上的清单）：往这句话里放东西、或拉出抽屉。
     40 见方的安静圆图标，平时不铺底，悬停才亮一档——框里一排圈圈比发送键还抢眼。
   - 视图胶囊 .chat-chip（文件、输入框上方的提醒条）：打开这个会话的一块面板。
     带字的小胶囊、铺一档底，开着时泛金——它说的是「这里有一栏东西」，不是一个动作。
   - 发送 .chat-send：这一页唯一的实心金。
   上传口是 2026-09-06 加的（那时是回形针）——网页聊天主页一直没有，策展人说「这里不让
   上传」是真的；09-22 它和语音一起收进了「＋」。 */
.chat-tool,
.chat-mic {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: var(--radius-pill);
  background: none;
  border: 1px solid transparent;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    background-color 0.15s ease,
    color 0.15s ease;
}

.chat-tool[hidden],
.chat-mic[hidden] {
  display: none;
}

.chat-tool:hover,
.chat-mic:hover {
  border-color: transparent;
  background: var(--surface-2);
  color: var(--fg);
}

/* 框里的工具钮悬停时不能取某一档面：框自己在 surface-3 和落焦的 surface-4 之间换，
   取哪一档都会在其中一种状态下比框还暗或跟框一样。铺一层薄薄的字色，在哪一档上
   都是「亮一点」。 */
.chat-box .chat-tool:hover,
.chat-box .chat-mic:hover,
.chat-box .chat-add[aria-expanded="true"] {
  background: rgba(236, 233, 228, 0.08);
}

.chat-box .chat-add[aria-expanded="true"] {
  color: var(--fg);
}

/* 「＋」的菜单：从框的左上角往上弹，盖在消息流上。长相跟左栏每行「···」那份
   菜单（.chat-session-menu）一样——同一档面、同一个影子、同一种条目（条目直接借
   .chat-session-menu-item）；只是那份是 fixed、由脚本量位置，这份跟着框走。 */
.chat-box {
  position: relative;
}

.chat-add-menu {
  position: absolute;
  left: 0;
  bottom: 100%;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 8rem;
  margin-bottom: var(--space-2);
  padding: var(--space-1);
  border-radius: var(--radius);
  background: var(--surface-2);
  box-shadow: var(--shadow-2);
}

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

/* 左边那一组工具排一排；单行时整排跟输入框一样 40 高、垂直居中。
   右边原来还有一组「视图」，里面只住着「文件」那一颗——2026-09-19 它搬去了对话区的
   右上角（业主：「按照你的推荐做」），那一组就空了，连着手机上给它写的那条
   margin-left: auto 一起删掉。 */
.chat-box-tools {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 2px;
  min-height: var(--control-lg);
}

/* 把手：整个对话区的右上角，抽屉出来的那一侧。它挂在 .chat-shell 上而不是
   .chat-pane 上——对话栏居中之后两边各有一百多的留白，挂在对话栏上就成了正文的
   右边缘，跟聊天内容混在一起（业主 2026-09-19：「不够靠右，要靠近右上角」）。
   样子仍是那颗胶囊（开着时泛金），只是换了个地方站。z-index 压过正文（正文不
   定位），让给抽屉（20）和弹窗。 */
.chat-files-toggle {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  z-index: 6;
}

.chat-chip {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  box-sizing: border-box;
  height: var(--control-md);
  padding: 0 var(--space-3) 0 10px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--fg-soft);
  font-size: var(--text-sm);
  font-weight: var(--weight-normal);
  line-height: 18px;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    color 0.15s ease;
}

.chat-chip[hidden] {
  display: none;
}

.chat-chip:hover {
  background: var(--surface-3);
  color: var(--fg);
}

.chat-chip .chat-icon {
  color: var(--muted);
}

.chat-chip[aria-expanded="true"] {
  background: var(--gold-soft);
  color: var(--gold);
}

.chat-chip[aria-expanded="true"] .chat-icon {
  color: var(--gold);
}

/* 在听：亮起来并且一直在呼吸——它是这一页唯一自己会动的控件，因为它是唯一
   一个「此刻正在发生」的控件。 */
.chat-mic.is-on {
  border-color: transparent;
  background: var(--gold-wash);
  color: var(--gold);
  animation: chat-mic-breath 1.6s ease-in-out infinite;
}

@keyframes chat-mic-breath {
  50% {
    box-shadow: 0 0 0 5px var(--gold-soft);
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-mic.is-on {
    animation: none;
  }
}

/* 还没说完的那半句：是听见的，不是你打的，所以压一档。 */
.chat-text.is-interim {
  color: var(--muted);
}

/* 发送键 36 见方，外边距 2 凑成 40 的格：跟工具键同一条中线，实心的那颗比
   描边的那两颗小一号才不压人。 */
.chat-send {
  flex: 0 0 auto;
  width: var(--control-lg);
  height: var(--control-lg);
  margin: 0;
  padding: 0;
  border-radius: var(--radius-pill);
  background: var(--gold);
  border-color: transparent;
  color: var(--surface-0);
  /* 图标居中靠 flex，不靠字形的基线。 */
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease;
}

.chat-send:hover {
  background: var(--gold-bright);
}

/* 按不动的发送键和「停下」取的是框里那层薄字色，不是某一档面：框本身已经是
   surface-3（落焦 surface-4），取一档面就跟框融成一片。 */
.chat-send:disabled {
  background: rgba(236, 233, 228, 0.1);
  color: var(--faint);
}

.chat-status {
  margin: var(--space-2) 0 0;
  min-height: 1em;
  padding: 0 var(--space-3);
  color: var(--muted);
  font-size: var(--text-xs);
  text-align: center;
}

/* 这一行只在有话要说时出现（连接中、麦克风为什么没露面）。键位提示不印：
   业主 2026-09-14「这些提示文字移除，更简单一些」。高度留着，免得状态一来
   一去输入框上下跳。 */
.chat-status[data-tone="bad"] {
  color: var(--red);
}

/* 整个系统暂停或正在更新：框上面一条横幅，发之前就看得见。 */
.chat-system {
  margin: 0 0 var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--gold-wash);
  color: var(--gold-bright);
  font-size: var(--text-xs);
  text-align: center;
}

.chat-system[hidden] {
  display: none;
}

/* 被服务端拒掉、没进记录的那一句：淡下去，底下说清字和文件去哪了。 */
.chat-turn.is-unsent .chat-bubble {
  opacity: 0.55;
}

.chat-unsent {
  color: var(--red);
  font-size: var(--text-2xs);
}

/* ---- 灯箱 ------------------------------------------------------------ */

.chat-lightbox {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0, 0.88);
}

.chat-lightbox[hidden] {
  display: none;
}

.chat-lightbox-stage {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}

.chat-lightbox-stage img {
  max-width: 100%;
  max-height: 100%;
  border-radius: var(--radius-sm);
}

.chat-lightbox-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4) var(--space-5);
  color: var(--fg-soft);
  font-size: var(--text-sm);
}

.chat-lightbox-caption {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 灯箱底栏：翻页、关闭是大一档（40）的圆钮，下载带字。压过 .chat-act 的小钮尺寸、
   悬停才出现，它们在这里一直在。 */
.chat-lightbox-btn,
.chat-lightbox-btn.chat-act {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: var(--control-lg);
  height: var(--control-lg);
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--fg);
  font-size: var(--text-sm);
  text-decoration: none;
  white-space: nowrap;
  opacity: 1;
  cursor: pointer;
}

.chat-lightbox-btn.is-wide {
  width: auto;
  padding: 0 var(--space-4) 0 14px;
}

.chat-lightbox-btn:hover,
.chat-lightbox-btn.chat-act:hover {
  background: var(--surface-3);
  color: var(--gold);
  text-decoration: none;
}

/* 底栏贴着屏幕下沿，提示条往上开。 */
.chat-lightbox-btn.chat-act::after {
  top: auto;
  bottom: 100%;
  margin: 0 0 6px;
}

/* ---- 回到底部 -------------------------------------------------------- */

.chat-jump {
  position: absolute;
  right: var(--space-5);
  /* 挂在输入区（dock）的上沿之上：头部拿掉、提醒条出没，输入区高低会变，
     原来量死的 112 像素就不对了（2026-09-15）。 */
  bottom: 100%;
  margin-bottom: var(--space-2);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 6px;
  box-sizing: border-box;
  height: var(--control-sm);
  padding: 0 var(--space-3) 0 10px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  box-shadow: var(--shadow-2);
  color: var(--fg);
  font-size: var(--text-xs);
  font-weight: var(--weight-normal);
  line-height: 1.3;
  cursor: pointer;
}

.chat-jump:hover {
  background: var(--surface-4);
  color: var(--gold-bright);
}

.chat-jump .chat-icon {
  color: var(--gold);
}

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

/* ---- 待发的文件 ------------------------------------------------------ */

.chat-pending {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0 0 var(--space-2);
}

.chat-pending[hidden] {
  display: none;
}

.chat-pending-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 240px;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-1);
  font-size: var(--text-xs);
}

.chat-pending-chip.is-uploading {
  opacity: 0.6;
}

.chat-pending-chip img {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-xs);
  object-fit: cover;
}

.chat-pending-name {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.chat-pending-remove {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--faint);
  cursor: pointer;
}

.chat-pending-remove:hover {
  background: var(--surface-3);
  color: var(--fg);
}

.chat-shell.is-dropping .chat-box {
  background: var(--gold-wash);
}

/* ---- 停下、停单、文件栏、搜索、重答（2026-09-14 第二批） ---------------- */

/* 发送键在回合里变成「停下」：一个画出来的方块，不是字符。 */
.chat-send.is-stop {
  background: rgba(236, 233, 228, 0.12);
  border-color: transparent;
  color: var(--fg);
}

.chat-send.is-stop svg {
  display: none;
}

.chat-send.is-stop::before {
  content: "";
  display: block;
  width: 12px;
  height: 12px;
  border-radius: 2px;
  background: currentColor;
}


/* 右侧的文件栏是一扇抽屉（业主 2026-09-17：「做成抽屉」）：从窗口右边浮出来盖在
   对话区上，对话栏一动不动。之前是第三列，一开文件对话栏就在剩下的空间里重新居中、
   整个往左挪（业主：「聊天区域往左挤压」）。宽屏上对话栏右边本来就空着，抽屉落在空处
   什么都不盖；笔记本宽度会盖住消息右边一截，但抽屉是临时的：点外面、按 Esc、点 × 都收。
   带一道影子分开，宽窄屏一个规矩。 */
.chat-files {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  width: 360px;
  max-width: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  box-shadow: -12px 0 32px rgba(0, 0, 0, 0.35);
}

.chat-files[hidden] {
  display: none;
}

.chat-files-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 跟对话栏的头部一样高，两条顶边对齐。 */
  min-height: 44px;
  padding: var(--space-3) var(--space-4) var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.chat-files-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-2) var(--space-3);
}

.chat-files-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-sm);
}

.chat-files-row:hover {
  background: var(--surface-2);
}

/* 基准宽度从 0 起算：行会折行（第二层要换到名字下面），长名字按内容宽度算
   会把下载钮挤到自己的一行上，名字和摘要之间空出一截。 */
.chat-files-open {
  flex: 1 1 0%;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--fg-soft);
  text-decoration: none;
}

/* 类型角标等宽：「图」和「PPT」一样宽，名字才排成一条竖线。 */
.chat-files-open .chat-file-kind {
  min-width: 38px;
  box-sizing: border-box;
  text-align: center;
}

.chat-files-open:hover .chat-file-name {
  color: var(--gold);
}

.chat-files-down,
.chat-files-close {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-md);
  height: var(--control-md);
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--faint);
  cursor: pointer;
}

.chat-files-down:hover,
.chat-files-close:hover {
  background: var(--surface-3);
  color: var(--fg);
}

/* 下载钮平时只在停上去的那一行亮出来，一栏二十个下载图标是噪音；手机上一直在。 */
.chat-files-down {
  opacity: 0;
}

.chat-files-row:hover .chat-files-down,
.chat-files-down:focus {
  opacity: 1;
}

@media (hover: none) {
  .chat-files-down {
    opacity: 1;
  }
}

.chat-files-empty {
  margin: var(--space-4) var(--space-2);
  color: var(--faint);
  font-size: var(--text-sm);
}

/* 文件行的第二层（2026-09-15）：是份什么、读透没有、在对话里的哪句。整块折到
   名字下面，左边跟名字对齐（38 的角标 + 8 的间距）。 */
.chat-files-more {
  flex: 1 0 100%;
  display: block;
  min-width: 0;
  box-sizing: border-box;
  padding-left: 46px;
}

.chat-files-more[hidden],
.chat-files-state[hidden],
.chat-files-reading[hidden] {
  display: none;
}

/* 摘要最多两行，整句在悬停提示里。 */
.chat-files-digest {
  overflow: hidden;
  max-height: 3em;
  color: var(--muted);
  font-size: var(--text-2xs);
  line-height: var(--leading-snug);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.chat-files-state {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 2px;
  font-size: var(--text-2xs);
  line-height: var(--leading-snug);
}

.chat-files-reading {
  display: inline-flex;
  align-items: center;
  margin-right: var(--space-3);
  color: var(--fg-soft);
}

.chat-files-reading.is-bad {
  color: var(--red);
}

.chat-files-reading-dot {
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  margin-right: 5px;
  border-radius: 50%;
  background: var(--gold);
  animation: chat-files-breath 1.6s ease-in-out infinite;
}

@keyframes chat-files-breath {
  50% {
    opacity: 0.3;
  }
}

.chat-files-report {
  margin-left: var(--space-2);
  color: var(--gold);
  text-decoration: none;
}

.chat-files-report:hover {
  text-decoration: underline;
}

.chat-files-jump {
  padding: 0;
  border: 0;
  background: none;
  color: var(--faint);
  font: inherit;
  cursor: pointer;
}

.chat-files-jump:hover {
  color: var(--gold);
}

/* 从文件栏跳过去的那句话：底下铺一层淡金，一两秒后退掉。 */
.chat-files-found {
  border-radius: var(--radius-sm);
  animation: chat-files-found 1.8s ease-out;
}

@keyframes chat-files-found {
  0%,
  40% {
    background-color: var(--gold-wash);
  }
  100% {
    background-color: transparent;
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-files-reading-dot {
    animation: none;
  }

  .chat-files-found {
    animation: none;
    background-color: var(--gold-wash);
  }
}

/* 左栏的搜索框：放大镜压在框里左边，字从它右边开始。框占满这一格的宽，
   外边距挪到外面那层 label 上。 */
/* 搜索行：长得跟「新会话」那行一样，只是它是个输入框；焦点由整行的底色说。 */
.chat-search-wrap {
  cursor: text;
}

.chat-search-wrap:focus-within {
  background: var(--surface-2);
}

.chat-search-wrap .chat-icon {
  flex: none;
  color: var(--muted);
  pointer-events: none;
}

/* 输入框本身透明，长得像上面那一行；焦点由整行的底色说。 */
.chat-search {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--fg);
  font-size: var(--text-sm);
}

.chat-search:focus {
  outline: none;
}

.chat-search-results {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 0 var(--space-2) var(--space-2);
}

.chat-search-results[hidden],
.chat-side-list[hidden] {
  display: none;
}

.chat-search-head {
  margin: var(--space-2) var(--space-3);
  color: var(--faint);
  font-size: var(--text-xs);
}

.chat-search-hit {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--muted);
  text-decoration: none;
}

.chat-search-hit:hover {
  background: var(--surface-2);
  text-decoration: none;
}

.chat-search-title {
  color: var(--fg-soft);
  font-size: var(--text-xs);
}

.chat-search-snippet {
  font-size: var(--text-xs);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.chat-again[hidden] {
  display: none;
}

/* ---- 在跑的会话：一颗会动的点（2026-09-14） --------------------------- */

.chat-session-dot {
  display: none;
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold);
}

.chat-session.is-busy .chat-session-dot {
  display: inline-block;
  animation: chat-session-breath 1.4s ease-in-out infinite;
}

@keyframes chat-session-breath {
  50% {
    opacity: 0.25;
    transform: scale(0.7);
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-session.is-busy .chat-session-dot {
    animation: none;
  }
}

/* ---- 有派单在跑的会话：转圈的记号带单数（2026-09-14） ------------------ */

.chat-session-tasks {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 3px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  background: var(--gold-wash);
  color: var(--gold);
  font-size: var(--text-2xs);
  line-height: 18px;
  font-variant-numeric: tabular-nums;
}

.chat-session-tasks[hidden] {
  display: none;
}

/* 等你点头：比任务记号急（半小时就作废），红一档；未读：金底小数字。 */
.chat-session-approval {
  flex: 0 0 auto;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  color: var(--red);
  font-size: var(--text-2xs);
  line-height: 18px;
  white-space: nowrap;
}

.chat-session-approval[hidden] {
  display: none;
}

.chat-session-unread {
  flex: 0 0 auto;
  min-width: 16px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--gold);
  color: var(--bg);
  font-size: var(--text-2xs);
  font-weight: 600;
  line-height: 16px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.chat-session-unread[hidden] {
  display: none;
}

.chat-side-archived-tasks {
  margin-left: var(--space-1);
  vertical-align: 1px;
}

.chat-session-tasks-spin {
  display: block;
  animation: chat-session-spin 1.1s linear infinite;
}

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

.chat-side-toggle {
  position: relative;
}

.chat-side-toggle-count {
  position: absolute;
  top: 2px;
  right: 0;
  min-width: 15px;
  padding: 0 4px;
  border-radius: var(--radius-pill);
  background: var(--gold);
  color: var(--bg);
  font-size: var(--text-2xs);
  font-weight: 600;
  line-height: 15px;
  text-align: center;
}

.chat-side-toggle-count[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .chat-session-tasks-spin {
    animation: none;
  }
}

/* ---- 不许折行的小件 --------------------------------------------------- */
/* 标签、角标、时刻、卡上的钮：都是一两个词，折成两行只会是被挤的，不会是
   写长了。flex 项默认能被压缩，中文逐字可断，一压就是「复／制」那种竖排
   （业主 2026-09-14）。 */
.chat-session-when,
.chat-approval-row button,
.chat-session-menu-item span {
  flex-shrink: 0;
  white-space: nowrap;
}

/* ---- 手机 ------------------------------------------------------------ */

@media (max-width: 640px) {
  .chat-scroll {
    padding: var(--space-4) var(--space-3) var(--space-3);
  }

  .chat-column {
    max-width: 90%;
  }

  .chat-dock {
    padding: var(--space-2) var(--space-3) var(--space-3);
  }

  /* 宽屏上清单住在 Core 的左侧栏里；手机上那条栏整条不出现（aimy.css），可是
     清单还在它里面——所以这里把栏退成一个零宽、什么都不画的壳。抽屉自己是
     fixed 的，不靠它排版，但得有一个没被 display:none 掉的祖先。 */
  .chat-body .railbar {
    display: block;
    position: static;
    width: 0;
    padding: 0;
    border: 0;
    background: none;
  }

  .chat-body .railbar-head,
  .chat-body .railbar-foot {
    display: none;
  }

  /* 清单收成抽屉：平时藏在左边屏幕外，头部的按钮拉出来。只用 position +
     left，老内核都认；transform 那行是增强，掉了也只是没有滑动。 */
  .chat-side {
    position: fixed;
    top: 0;
    bottom: 0;
    left: -100%;
    z-index: 30;
    width: 82%;
    max-width: 320px;
    /* 抽屉浮在对话上面，得有自己的面——宽屏上这一层是栏铺的。 */
    background: var(--surface-0);
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.5);
    transition: left 0.2s ease;
  }

  .chat-side.is-open {
    left: 0;
  }

  .chat-side-close,
  .chat-tool.chat-side-toggle {
    display: flex;
  }

  .chat-side-fold {
    display: none;
  }

  .chat-side-folder-new {
    opacity: 1;
  }

  /* 手机上输入框两行（2026-09-15）：字在上面占满一行，底下左边清单、麦克风、回形针，
     右边文件和发送。一行里挤六样东西，打字的地方只剩一百多像素。 */
  .chat-box {
    flex-wrap: wrap;
    padding: var(--space-1) var(--space-2) var(--space-2);
  }

  .chat-text {
    order: -1;
    flex: 1 1 100%;
    padding-left: var(--space-3);
  }

  /* 第二行：工具在左，发送靠右。原来右边有「文件」那一组把它顶过去，09-19 那一组
     搬走以后发送就贴在了回形针后面（业主 2026-09-22）。 */
  .chat-send {
    margin-left: auto;
  }

  .chat-jump {
    right: var(--space-3);
  }
}

/* ---- 提醒条：到点提醒和待办 ------------------------------------------- */
/* 输入框上方的一句「2 个提醒 · 1 个待办」（2026-09-15；原在头部，头部拿掉后挪到这里）。
   借文件那颗胶囊的样子（.chat-chip），这里只补它自己的。 */
/* 三样都有时（「已预授权 · 剩 3 单 · 2 个提醒 · 1 个待办」）手机上一行放不下：条子
   可以让出宽度、字尾收成省略号，不把「文件」挤出屏幕——全文在面板里。 */
.chat-reminders {
  flex: 0 1 auto;
  min-width: 0;
}

.chat-reminders[hidden] {
  display: none;
}

.chat-reminders .chat-icon {
  flex: 0 0 auto;
  color: var(--gold);
}

.chat-reminders-words {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 点开的小面板：跟清单「···」那张菜单一个样子（fixed、亮一档的面、影子），脚本按
   条子的位置摆。宽 360，窄屏上两边各留 8 像素。 */
.chat-reminders-panel {
  position: fixed;
  z-index: 40;
  display: flex;
  flex-direction: column;
  width: 360px;
  max-width: 94%;
  max-width: calc(100vw - 16px);
  max-height: 70vh;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-2);
  box-shadow: var(--shadow-2);
}

.chat-reminders-panel[hidden] {
  display: none;
}

.chat-reminders-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-2) var(--space-1) var(--space-4);
  color: var(--fg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.chat-reminders-close {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-md);
  height: var(--control-md);
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--faint);
  cursor: pointer;
}

.chat-reminders-close:hover {
  background: var(--surface-3);
  color: var(--fg);
}

.chat-reminders-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 0 var(--space-2) var(--space-2);
}

.chat-reminders-section {
  margin: var(--space-2) var(--space-2) 2px;
  color: var(--faint);
  font-size: var(--text-2xs);
}

.chat-reminders-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
}

.chat-reminders-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* 先说什么时候，再说是什么事：一眼扫下去是一列时刻。 */
.chat-reminders-meta {
  color: var(--fg);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
}

.chat-reminders-meta.is-late {
  color: var(--red);
}

/* 提醒的内容是写给 Aimy 自己看的，可能很长：最多三行，停上去看全文。 */
.chat-reminders-what {
  max-height: 4.5em;
  overflow: hidden;
  color: var(--fg-soft);
  font-size: var(--text-sm);
  line-height: 1.5;
  word-wrap: break-word;
}

.chat-reminders-drop {
  flex: 0 0 auto;
  box-sizing: border-box;
  height: var(--control-sm);
  margin-top: 2px;
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  color: var(--fg-soft);
  font: inherit;
  font-size: var(--text-xs);
  line-height: 1.3;
  white-space: nowrap;
  cursor: pointer;
}

.chat-reminders-drop:hover {
  background: var(--surface-4);
  color: var(--fg);
}

.chat-reminders-drop:disabled {
  opacity: 0.5;
  cursor: default;
}

.chat-reminders-note {
  margin: var(--space-2);
  color: var(--red);
  font-size: var(--text-xs);
}

/* ---- 打开的动效（业主 2026-09-17）---------------------------------------
   关键帧和时长都取 aimy.css 的（aimy-rise / aimy-fade / aimy-slide-right / aimy-dialog-in，
   --motion-* / --ease-out）。这里只说「谁用哪个」。都是出场：元素从 hidden／details 关着
   变成可见那一刻动画自然起跑，关闭瞬间消失。整段只在没要求「减少动态」时生效。 */
@media (prefers-reduced-motion: no-preference) {
  /* 文件抽屉从右边滑进来。 */
  .chat-files {
    animation: aimy-slide-right var(--motion-base) var(--ease-out);
  }

  /* 抽屉里的文件行一行接一行浮起（前六行错开，后面的一起）。 */
  .chat-files-row {
    animation: aimy-rise var(--motion-base) var(--ease-out) backwards;
  }

  .chat-files-row:nth-child(2) { animation-delay: 0.03s; }
  .chat-files-row:nth-child(3) { animation-delay: 0.06s; }
  .chat-files-row:nth-child(4) { animation-delay: 0.09s; }
  .chat-files-row:nth-child(5) { animation-delay: 0.12s; }
  .chat-files-row:nth-child(n + 6) { animation-delay: 0.15s; }

  /* 「···」菜单和它的「归到项目」子单：和顶栏菜单同一个弹法。 */
  .chat-session-menu {
    transform-origin: top left;
    animation: menu-pop var(--motion-quick) ease-out;
  }

  .chat-session-menu-sub {
    animation: aimy-rise var(--motion-quick) var(--ease-out);
  }

  /* 折叠段打开：项目总开关下的文件夹、文件夹里的会话、已归档的清单、收起的窄轨。
     details 关着时内容在新内核里不是 display:none，只是不可见，再打开动画不会自己重跑，
     所以打开那一下由 chat-sessions.js 盖一个 is-opening（动画完就摘），动画钉在它上面；
     首屏本来就开着的段不带这个类，不动。 */
  .chat-side-projects.is-opening > .chat-side-folder,
  .chat-side-folder.is-opening > .chat-side-folder-body,
  .chat-side-archived.is-opening > :not(summary),
  .chat-side.is-folded > .chat-rail {
    animation: aimy-rise var(--motion-base) var(--ease-out);
  }

  /* 搜索结果、待发文件条、系统条幅：出现时浮起。 */
  .chat-search-results,
  .chat-pending,
  .chat-system {
    animation: aimy-rise var(--motion-base) var(--ease-out);
  }

  /* 实时进来的一行（自己发的、Aimy 回的、回执）浮起；首屏历史不动（它不经 appendTurn）。 */
  .chat-turn.is-arriving {
    animation: aimy-rise var(--motion-slow) var(--ease-out);
  }

  /* 新会话的问候：打开这一页时浮起来。 */
  .chat-hello {
    animation: aimy-rise var(--motion-slow) var(--ease-out);
  }

  /* 灯箱：底色淡入，图从略小处浮起。 */
  .chat-lightbox {
    animation: aimy-fade var(--motion-quick) ease-out;
  }

  .chat-lightbox-stage img {
    animation: aimy-dialog-in var(--motion-base) var(--ease-out);
  }
}
