/* ==========================================================================
   聊天区：气泡、Markdown 正文、日期分隔、多选导出、输入器、成员面板
   自己发的靠右=微信绿，对方靠左=系统蓝
   ========================================================================== */

.chat__stream {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-bottom: var(--sp-sm);
}

/* ---------------- 日期分隔 ---------------- */

.day-divider {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-md) 0 var(--sp-sm);
  font-size: var(--fs-fine);
  color: var(--c-secondary);
  letter-spacing: 0;
}

/* ---------------- 消息行 ---------------- */

.msg {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-xs);
  /* 和 .chat__stream 的 gap 一起构成消息之间的缝（两边合计 8px）。
     多留一点是给选中态那圈描边用的，也免得连着几条挤成一块 */
  padding: 2px 0;
  scroll-margin-top: var(--sp-md);
}

.msg--own {
  flex-direction: row-reverse;
}

.msg__avatar {
  flex: 0 0 auto;
  margin-top: 2px;
}

.msg__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* 列方向上的交叉轴默认是 stretch：左边那侧没写对齐的话，气泡会被拉成
     「昵称 + 设备」那一行的宽度，"嗯""好的"这种短句就成了一条长条。
     两头都按内容宽度贴边，气泡才跟着字走 */
  align-items: flex-start;
  max-width: min(620px, 74%);
}

.msg--own .msg__body {
  align-items: flex-end;
}

/* 只在连续消息的第一条显示昵称 */
.msg__head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 4px 3px;
  font-size: var(--fs-fine);
  color: var(--c-secondary);
  letter-spacing: 0;
}

.msg__system {
  align-self: center;
  max-width: 80%;
  margin: var(--sp-xs) 0;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  background: var(--c-fill);
  font-size: var(--fs-fine);
  color: var(--c-secondary);
  text-align: center;
  letter-spacing: 0;
}

/* ---------------- 气泡 ---------------- */

.bubble {
  position: relative;
  /* .msg__body 上的 max-width 管不到里面的 flex 项：项有多宽全看内容，
     一行特长的代码就能把气泡撑到 1494px，自己这侧又是右对齐，多出来的部分
     就往左边溢出、被聊天区裁掉（代码开头直接看不见）。这里自己封个顶，
     超宽的内容交给 pre / table 内部横向滚 */
  max-width: 100%;
  padding: 8px 12px;
  border-radius: var(--r-lg);
  background: var(--c-bubble-other-bg);
  color: var(--c-bubble-other-fg);
  font-size: var(--fs-body);
  line-height: 1.42;
  letter-spacing: var(--ls-body);
  overflow-wrap: anywhere;
}

/* 靠边和颜色同一个判据：本设备发的（.msg--own）。我账号在另一台设备上发的那条
   靠左、而且是蓝的 —— 看着就该像另一个人发的 */
.msg--own .bubble {
  background: var(--c-bubble-own-bg);
  color: var(--c-bubble-own-fg);
}

/* 只发了一张图的消息不套气泡，图片直接铺在聊天流里。
   保留 .bubble 这个壳是为了搜索结果闪烁还有地方挂。
   这里要连 .msg--own 一起写 —— 自己的气泡那条规则权重更高，只写 .bubble--media 盖不住 */
.bubble--media,
.msg--own .bubble--media {
  min-width: 0;
  padding: 0;
  background: none;
  box-shadow: none;
}

.bubble--media .md img {
  max-height: min(60vh, 420px);
}

.msg__foot {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 3px 4px 0;
  font-size: var(--fs-fine);
  color: var(--c-secondary);
  letter-spacing: 0;
}

.msg__state {
  color: var(--c-danger);
}

.bubble--sending {
  opacity: 0.55;
}

.bubble--failed {
  box-shadow: inset 0 0 0 1px var(--c-danger);
}

/* 多选模式 */
.msg__check {
  display: none;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-top: 8px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px var(--c-hairline);
  background: var(--c-surface);
  color: transparent;
}

.chat--selecting .msg__check {
  display: inline-flex;
}

.msg--selected .msg__check {
  background: var(--c-primary);
  box-shadow: none;
  color: #fff;
}

.msg__check svg {
  width: 12px;
  height: 12px;
  display: block;
}

/*
 * 多选时每条都要单独点，把本来就紧的行距撑开一点。
 * 平时消息之间只有 1px padding + 2px gap —— 成组的时候那个疏密是对的，
 * 但多选时圆勾贴着上下两条、点哪一条都不好分，看着就像"挨到一起了"
 */
.chat--selecting .msg {
  cursor: pointer;
  padding: var(--sp-xs) 0;
}

/* 选中不给气泡描边：勾选状态由行外侧那个圆勾表达就够了，
   气泡再套一圈主色边框，一条消息上就是两处高亮，吵 */

/* 从搜索结果跳转过来时的闪烁定位 */
.msg--flash .bubble {
  animation: dnm-flash 1.1s ease-out;
}

@keyframes dnm-flash {
  0%,
  60% {
    box-shadow: 0 0 0 2px var(--c-primary);
  }
  100% {
    box-shadow: 0 0 0 2px transparent;
  }
}

/* 多选工具栏 */
.selbar {
  display: flex;
  align-items: center;
  gap: var(--sp-xs);
  height: var(--nav-height);
  padding: 0 var(--sp-md);
  border-bottom: 1px solid var(--c-hairline);
  background: var(--c-surface);
}

.selbar__count {
  flex: 1;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  letter-spacing: -0.2px;
}

/* ---------------- Markdown 正文 ---------------- */

.md {
  font-size: var(--fs-body);
  line-height: 1.45;
}

.md > *:first-child {
  margin-top: 0;
}

.md > *:last-child {
  margin-bottom: 0;
}

.md p {
  margin: 0 0 6px;
}

.md h1,
.md h2,
.md h3,
.md h4 {
  margin: 12px 0 5px;
  font-weight: var(--fw-semibold);
  line-height: 1.3;
}

.md h1 {
  font-size: 21px;
}
.md h2 {
  font-size: 19px;
}
.md h3 {
  font-size: 17px;
}
.md h4 {
  font-size: 15px;
}

.md ul,
.md ol {
  margin: 4px 0 6px;
  padding-left: 20px;
}

.md ul {
  list-style: disc;
}

.md ol {
  list-style: decimal;
}

.md li {
  margin: 2px 0;
}

.md blockquote {
  margin: 5px 0;
  padding: 2px 0 2px 10px;
  border-left: 3px solid var(--c-bubble-other-quote-border);
  color: var(--c-bubble-other-muted);
}

.msg--own .md blockquote {
  border-color: var(--c-bubble-own-quote-border);
  color: var(--c-bubble-own-muted);
}

.md a {
  color: var(--c-bubble-other-link);
  text-decoration: underline;
}

.msg--own .md a {
  color: var(--c-bubble-own-link);
}

.md hr {
  margin: 10px 0;
  border: none;
  border-top: 1px solid var(--c-divider-inset);
}

/* 行内代码跟着气泡底色走，代码块不行（见下） */
.md :not(pre) > code {
  padding: 1px 5px;
  border-radius: var(--r-xs);
  background: var(--c-bubble-other-code-bg);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
}

.msg--own .md :not(pre) > code {
  background: var(--c-bubble-own-code-bg);
}

/* 代码块统一用跟随主题的卡片底色，蓝气泡里也一样 —— 高亮配色是按浅底设计的，
   压在气泡底色上会糊成一团。要和 highlight.js 的主题底色保持一致 */
.md pre,
.msg--own .md pre {
  margin: 6px 0;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: var(--c-code-bg);
  color: var(--c-code-fg);
  border: 1px solid var(--c-code-border);
  overflow-x: auto;
  max-width: 100%;
}

.md pre code {
  padding: 0;
  background: none;
  color: inherit;
  font-size: var(--fs-mono);
  line-height: 1.5;
}

/* 高亮主题只作用于气泡内；浅色主题下对方的深色气泡里代码也要能看清 */
.md table {
  display: block;
  width: max-content;
  max-width: 100%;
  margin: 6px 0;
  border-collapse: collapse;
  overflow-x: auto;
  font-size: var(--fs-caption);
}

.md th,
.md td {
  padding: 4px 9px;
  border: 1px solid var(--c-divider-inset);
}

.md th {
  background: var(--c-bubble-other-code-bg);
  font-weight: var(--fw-semibold);
}

.md img {
  max-width: 100%;
  max-height: 320px;
  border-radius: var(--r-sm);
  cursor: zoom-in;
  object-fit: contain;
}

/* 自己发的消息整条靠右，图也得跟着贴右边。
   图旁边挂着比它宽的文字时气泡会被文字撑开（图才 206px、气泡能有 490px），
   图却还留在气泡左侧，右下角空出一大块，看着像是跟头像断开了 ——
   所以自己这侧把独占一段的图推到右边。多图并排的"相册"行不动它：
   那种情况图已经撑满气泡，一张张改块级反倒会把它们竖着摞起来
   （:has 用不了的老浏览器只是退回原来的左对齐，不会坏） */
.msg--own .md p:has(> img:only-of-type) > img {
  display: block;
  margin-left: auto;
}

/* 代码块右上角的复制按钮 */
.code-wrap {
  position: relative;
}

.code-copy {
  position: absolute;
  top: 5px;
  right: 5px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 24px;
  padding: 0 8px;
  border-radius: var(--r-xs);
  background: rgba(127, 127, 127, 0.24);
  color: inherit;
  font-size: var(--fs-fine);
  opacity: 0;
  transition: opacity var(--dur-fast), background var(--dur-fast);
}

.code-wrap:hover .code-copy {
  opacity: 1;
}

.code-copy:active {
  background: rgba(127, 127, 127, 0.4);
}

.code-copy svg {
  width: 12px;
  height: 12px;
  display: block;
}

/* ---------------- 输入器 ---------------- */

.composer__box {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-xs);
  padding: 5px 5px 5px var(--sp-sm);
  background: var(--c-fill);
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  transition: border-color var(--dur-fast), background var(--dur-fast);
}

.composer__box--focus {
  background: var(--c-surface);
  border-color: var(--c-primary);
}

/* 框里那两个工具按钮（代码块 / 图片）比顶栏图标大一点。
   位置不动 —— 跟发送键同在一条底线（.composer__box 的 flex-end） */
.composer__box .icon-btn svg {
  width: 21px;
  height: 21px;
}

/* AI 跟旁边两个同高。这一排是 flex-end 对齐的，只要有一个比别的高，
   它就会往上支棱出来、圆心跟旁边错开半档 —— 所以尺寸必须一刀切齐 */
.composer__box .icon-btn--ai {
  width: 32px;
  height: 32px;
}

/* 但图标放宽一档：sparkle 只画在 24 视口正中那一小块（14/24），
   跟旁边同样 21px 缩出来会比旁边细一圈 */
.composer__box .icon-btn--ai svg {
  width: 27px;
  height: 27px;
}

/* AI 按钮在等回包：图标换成转圈，顺手锁住不让连点（一次点击就是一笔 token） */
.composer__box .icon-btn--ai.icon-btn--busy {
  pointer-events: none;
  opacity: 0.55;
}

.composer__box .icon-btn--busy .spinner {
  width: 20px;
  height: 20px;
}

.composer__input {
  flex: 1;
  min-width: 0;
  max-height: 180px;
  padding: 8px 0;
  background: none;
  border: none;
  font-size: var(--fs-body);
  line-height: 1.42;
  letter-spacing: var(--ls-body);
  color: var(--c-ink);
  resize: none;
  overflow-y: auto;
}

.composer__input::placeholder {
  color: var(--c-placeholder);
}

.composer__send {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--c-primary);
  color: var(--c-on-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast);
}

.composer__send:active {
  transform: scale(0.9);
}

.composer__send:disabled {
  background: var(--c-fill-strong);
  color: var(--c-secondary);
}

.composer__send svg {
  width: 17px;
  height: 17px;
  display: block;
}

.composer__hint {
  margin-top: 5px;
  padding: 0 var(--sp-xs);
  font-size: var(--fs-fine);
  color: var(--c-disabled);
  letter-spacing: 0;
}

/* 对方正在输入 */
.typing {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 var(--sp-xs) var(--sp-xs);
  font-size: var(--fs-fine);
  color: var(--c-secondary);
  letter-spacing: 0;
}

.typing__dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--c-tertiary);
  animation: dnm-typing 1.2s infinite ease-in-out;
}

.typing__dot:nth-child(2) {
  animation-delay: 0.18s;
}

.typing__dot:nth-child(3) {
  animation-delay: 0.36s;
}

.typing__text {
  margin-left: 3px;
}

@keyframes dnm-typing {
  0%,
  60%,
  100% {
    transform: translateY(0);
    opacity: 0.5;
  }
  30% {
    transform: translateY(-3px);
    opacity: 1;
  }
}

/* ---------------- 图片查看器 ---------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 940;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-lg);
  background: rgba(0, 0, 0, 0.86);
  animation: dnm-fade-in 160ms ease-out;
  cursor: zoom-out;
}

.lightbox img {
  max-width: 100%;
  max-height: 100%;
  border-radius: var(--r-sm);
  animation: dnm-pop-in 200ms var(--ease-out);
}

/* ---------------- 成员面板（右侧抽屉） ---------------- */

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 880;
  width: 300px;
  display: flex;
  flex-direction: column;
  background: var(--c-surface);
  box-shadow: var(--shadow-modal);
  animation: dnm-slide-left 220ms var(--ease-out);
}

@keyframes dnm-slide-left {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}

.drawer__header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  height: var(--nav-height);
  padding: 0 var(--sp-xs) 0 var(--sp-md);
  border-bottom: 1px solid var(--c-hairline);
}

.drawer__title {
  flex: 1;
  font-family: var(--font-display);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  letter-spacing: -0.2px;
}

.drawer__body {
  flex: 1;
  min-height: 0;
  padding: var(--sp-xs) var(--sp-sm) var(--sp-lg);
}

.drawer__section {
  padding: var(--sp-sm) var(--sp-sm) 4px;
  font-size: var(--fs-fine);
  font-weight: var(--fw-semibold);
  color: var(--c-secondary);
  letter-spacing: 0;
}

.member-row {
  display: flex;
  align-items: center;
  gap: var(--sp-sm);
  padding: 8px;
  border-radius: var(--r-md);
}

.member-row__main {
  flex: 1;
  min-width: 0;
}

.member-row__name {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-caption);
}

.member-row__sub {
  font-size: var(--fs-fine);
  color: var(--c-secondary);
  letter-spacing: 0;
}

.tag-owner {
  padding: 1px 5px;
  border-radius: var(--r-xs);
  background: var(--c-primary-soft);
  color: var(--c-primary);
  font-size: var(--fs-fine);
  font-weight: var(--fw-semibold);
}

/* 邀请码 */
.invite {
  margin: var(--sp-xs) var(--sp-sm) var(--sp-md);
  padding: var(--sp-sm);
  border-radius: var(--r-md);
  background: var(--c-fill);
  text-align: center;
}

.invite__label {
  font-size: var(--fs-fine);
  color: var(--c-secondary);
  letter-spacing: 0;
}

.invite__code {
  margin: 4px 0 8px;
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: var(--fw-semibold);
  letter-spacing: 4px;
  color: var(--c-ink);
}

.invite__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-xs);
  justify-content: center;
}

/* ---------------- 标签行（聊天头部下方） ---------------- */

/* AI 标签（只读展示，在"查看标签"弹窗里） */
.tag-view {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  /* 流式折行，最多三行：chip 高约 21px，外加两道行距 */
  max-height: calc(21px * 3 + 6px * 2);
  overflow: hidden;
}

.tag-view--empty {
  color: var(--c-tertiary);
  font-size: var(--fs-fine);
}

.tag-view__item {
  background: var(--c-primary-soft);
  color: var(--c-primary);
}

.tag-view__time {
  margin-top: var(--sp-xs);
  font-size: var(--fs-fine);
  color: var(--c-tertiary);
}

/* ---------------- 状态切换（聊天头部） ---------------- */

.status-menu__item[aria-checked='true'] .menu__label {
  font-weight: var(--fw-semibold);
}

.status-menu__item[aria-checked='true'] {
  color: var(--c-primary);
}
