/* ============================================
   JSON 渲染器样式
   包含所有卡片类型的样式定义
   ============================================ */

/* ============================================
   FC tag（ReAct trace 工具卡片复用）
   ============================================ */

.fc-tag {
  background: color-mix(in srgb, var(--brand-primary) 15%, transparent);
  color: var(--metro-blue);
  padding: 2px 8px;
  border-radius: var(--radius-lg);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  word-break: break-all;
  max-width: 100%;
}

.npc-reaction-item {
  margin-bottom: 8px;
  padding: 6px 8px;
  border-left: 3px solid var(--metro-teal);
  border: 1px solid var(--sheen-8);
  border-left-width: 3px;
  border-radius: var(--radius-xs);
  background: var(--surface-code-alt);
  color: var(--code-text);
}

.npc-reaction-item:last-child {
  margin-bottom: 0;
}

.npc-reaction-name {
  color: var(--metro-teal);
  font-weight: var(--weight-bold);
}

.npc-reaction-text {
  margin-top: 4px;
  color: var(--code-text);
  white-space: pre-wrap;
}

.reasoning-content-bar {
  margin: 2px 0 8px 0;
}

.reasoning-summary {
  cursor: pointer;
  font-size: var(--text-body-sm);
  color: var(--text-muted);
  padding: 4px 8px;
  user-select: none;
}

.reasoning-summary-meta {
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.reasoning-detail {
  padding: 8px 12px;
  font-size: var(--text-caption);
  color: var(--code-text);
  background: var(--surface-code-alt);
  border-radius: var(--radius-xs);
  margin-top: 4px;
  white-space: pre-wrap;
  max-height: 400px;
  overflow-y: auto;
  line-height: 1.5;
}

/* ============================================
   游戏输出容器
   ============================================ */
.game-output {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* 剧情正文 */
.game-narrative {
  line-height: 2;
  font-size: var(--text-title);
  color: var(--text-color);
}

.game-narrative p {
  margin-bottom: 12px;
}

.game-narrative p:last-child {
  margin-bottom: 0;
}

/* === 叙事着色 ===
   Local definitions removed — tokens now live in theme-tokens.css
   as --narrative-dialogue, --narrative-thought, --narrative-speaker,
   --narrative-action and are consumed via var() references below.
*/

.narrative-dialogue { color: var(--narrative-dialogue); }
.narrative-thought  { color: var(--narrative-thought); font-style: italic; }
.narrative-speaker  { color: var(--narrative-speaker); font-weight: var(--weight-semibold); }

.game-narrative em,
.chat-message-content em {
  color: var(--narrative-action);
  font-style: italic;
}

/* ============================================
   状态栏 HUD - Metro 风格
   ============================================ */
.game-status {
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  background-color: var(--hud-bg);
  border-radius: var(--radius-md);
  padding: 12px 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  border: 1px solid var(--hud-border);
  box-shadow: 0 2px 8px var(--overlay-4);
}

.status-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-body);
  color: var(--hud-text);
}

.status-icon {
  font-size: var(--text-body-lg);
  color: var(--brand-yellow);
}

.status-value {
  font-weight: var(--weight-semibold);
  color: var(--hud-value);
}

.status-item.datetime .status-value {
  font-family: var(--font-mono);
}

.status-item.location .status-value {
  color: var(--hud-value);
}

.status-item.money .status-value {
  font-family: var(--font-mono);
}

.status-item.objective .status-value {
  color: var(--hud-value);
}

/* 可编辑状态字段 */
.status-editable {
  cursor: pointer;
  border-bottom: 1px dashed var(--hud-value);
  transition: background-color var(--transition-fast);
}

.status-editable:hover {
  background-color: color-mix(in srgb, var(--brand-yellow) 10%, transparent);
}

.status-editable:focus {
  outline: none;
  background-color: color-mix(in srgb, var(--brand-yellow) 15%, transparent);
  border-bottom-style: solid;
}

/* 非法输入的抖动回滚提示 */
.status-editable.invalid {
  animation: status-field-shake 0.3s ease-in-out;
  background-color: color-mix(in srgb, var(--status-danger) 15%, transparent) !important;
}

@keyframes status-field-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px); }
  75% { transform: translateX(3px); }
}

/* 流式中禁用编辑（JS 有双保险，CSS 让用户一看就知道不可点） */
.chat-message.streaming-state .status-editable {
  pointer-events: none;
  cursor: default;
}

/* ============================================
   选项列表 - Metro 风格
   ============================================ */
.game-choices {
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  background-color: var(--choice-panel-bg);
  border: 1px solid var(--choice-panel-border);
  border-radius: var(--radius-md);
  padding: 16px;
}

.choices-header {
  font-size: var(--text-body-lg);
  color: var(--choice-title);
  margin-bottom: 10px;
}

.choices-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.choice-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 16px;
  background: var(--choice-item-bg);
  border-radius: var(--radius-md);
  border: 1px solid var(--choice-item-border);
  cursor: pointer;
  transition: all var(--transition-fast);
  font-size: var(--text-body-lg);
  line-height: 1.5;
  box-shadow: 0 2px 6px var(--overlay-4);
}

/* 第一行:ID + 类型 + 标题 */
.choice-row-1 {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* 第二行:描述 + cost(段落式连续显示)*/
.choice-row-2 {
  padding-left: 28px;
  /* 与ID对齐 */
}

.choice-detail,
.choice-cost {
  display: inline;
}

.choice-item:hover {
  border-color: var(--choice-panel-border);
  background: var(--choice-item-hover-bg);
  box-shadow: 0 4px 12px var(--overlay-6);
  transform: translateX(4px);
}

.choice-item:active {
  transform: translateY(2px) scale(0.98);
  box-shadow: inset 0 0 15px color-mix(in srgb, var(--brand-purple) 30%, transparent);
  background-color: var(--choice-item-active-bg);
  border-style: dashed;
}

.choice-id {
  font-weight: var(--weight-black);
  color: var(--choice-title);
  min-width: 20px;
  font-size: var(--text-heading);
}

.choice-type {
  font-weight: var(--weight-semibold);
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  font-size: var(--text-body-sm);
}

/* 交谈 - 蓝色 */
.choice-talk .choice-type {
  background: color-mix(in srgb, var(--brand-primary) 15%, transparent);
  color: var(--brand-primary);
}

/* 探索 - 绿色 */
.choice-explore .choice-type {
  background: color-mix(in srgb, var(--status-success) 15%, transparent);
  color: var(--status-success);
}

/* 交易 - 金色 */
.choice-trade .choice-type {
  background: color-mix(in srgb, var(--status-warning) 15%, transparent);
  color: var(--brand-yellow);
}

/* 旅行 - 紫色 */
.choice-travel .choice-type {
  background: color-mix(in srgb, var(--brand-primary) 15%, transparent);
  color: var(--metro-blue);
}

/* 打工 - 橙色 */
.choice-work .choice-type {
  background: color-mix(in srgb, var(--brand-accent) 15%, transparent);
  color: var(--brand-accent);
}

/* 行动 - 红色 */
.choice-action .choice-type {
  background: color-mix(in srgb, var(--status-danger) 15%, transparent);
  color: var(--status-danger);
}

.choice-default .choice-type {
  background: var(--choice-default-chip-bg);
  color: var(--choice-text-secondary);
}

.choice-short {
  font-weight: var(--weight-medium);
  color: var(--choice-text-primary);
}

.choice-detail {
  color: var(--choice-text-secondary);
}

.choice-cost {
  color: var(--brand-yellow);
  font-weight: var(--weight-medium);
  font-size: var(--text-body-sm);
}

/* NPC 卡片 NEW/UPDATE 标记 */
.npc-badge {
  position: absolute;
  top: 6px;
  right: 8px;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.npc-badge.new {
  background: linear-gradient(135deg, var(--status-success) 0%, color-mix(in srgb, var(--status-success) 55%, var(--text-invert)) 100%);
  color: var(--text-invert);
}

.npc-badge.update {
  background: linear-gradient(135deg, var(--brand-primary) 0%, color-mix(in srgb, var(--brand-primary) 55%, var(--text-invert)) 100%);
  color: var(--text-invert);
}

.npc-badge.restore {
  background: linear-gradient(135deg, var(--brand-magenta) 0%, color-mix(in srgb, var(--brand-magenta) 70%, var(--brand-primary)) 100%);
  color: var(--text-invert);
}

/* 响应式 */
@media (max-width: 480px) {
  .game-status {
    flex-direction: column;
    gap: 8px;
  }

  .choice-row-2 {
    padding-left: 0;
  }
}

/* 通用:多卡片并排容器 */
.json-cards-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0;
}

/* ============================================
   NPC 档案卡样式
   ============================================ */

/* 多卡片并排容器 */
.npc-cards-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0;
}

.npc-cards-row .npc-card,
.json-cards-row .npc-card {
  flex: 1 1 160px;
  max-width: 220px;
  margin: 0;
}

.npc-card {
  position: relative;
  background: linear-gradient(145deg, var(--surface-code-alt) 0%, color-mix(in srgb, var(--brand-primary) 15%, var(--surface-code)) 50%, var(--surface-code) 100%);
  color: var(--code-text);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--brand-secondary) 40%, transparent);
  box-shadow: 0 4px 15px var(--overlay-30);
  margin: 6px 0;
  font-family: var(--font-ui);
  max-width: 260px;
  container-type: inline-size;
}

/* 卡片宽度 >= 220px 时，Body 网格切为双列 */
@container (min-width: 220px) {
  .npc-item.half {
    flex: 0 0 calc(50% - 3px);
    max-width: calc(50% - 3px);
  }
}

.npc-card-header {
  background: linear-gradient(135deg, color-mix(in srgb, var(--brand-secondary) 30%, transparent), color-mix(in srgb, var(--brand-secondary) 20%, transparent));
  padding: 8px 10px;
  text-align: center;
  position: relative;
  border-bottom: 1px solid color-mix(in srgb, var(--brand-secondary) 30%, transparent);
}

.npc-card-header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--brand-secondary), var(--brand-secondary), var(--brand-primary), transparent);
}

.npc-id {
  position: absolute;
  top: 6px;
  left: 8px;
  font-size: var(--text-2xs);
  color: var(--text-on-accent);
  opacity: 0.5;
  font-family: var(--font-mono);
  background: var(--overlay-30);
  padding: 1px 5px;
  border-radius: var(--radius-sm);
}

.npc-name {
  font-size: var(--text-title, 1rem);
  font-weight: var(--weight-bold);
  color: var(--text-on-accent);
  margin-bottom: 1px;
  letter-spacing: 0.5px;
}

/* 认知状态（名字下方） */
.npc-cognitive {
  font-size: var(--text-caption, 0.65rem);
  margin-top: 2px;
  text-align: center;
}

/* 年龄印章效果 */
.npc-stamp {
  position: absolute;
  top: 63%;
  left: 10px;
  transform: translateY(-50%) rotate(-15deg);
  font-size: var(--text-caption, 0.7rem);
  font-weight: var(--weight-bold);
  color: var(--brand-secondary);
  border: 2px solid var(--brand-secondary);
  padding: 2px 4px;
  border-radius: var(--radius-xs);
  opacity: 0.85;
}

.npc-card-body {
  padding: 6px 8px;
}

.npc-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.npc-item {
  flex: 0 0 100%;
  max-width: 100%;
  background: var(--surface-chip);
  border-radius: var(--radius-xs);
  padding: 6px 8px;
  border: 1px solid var(--border-chip);
  box-sizing: border-box;
}

:root[data-skin='cyberpunk'][data-theme='dark'] .npc-item {
  box-shadow: 0 0 8px color-mix(in srgb, var(--brand-primary) 18%, transparent);
}

/* All dark themes — chip 内 label/value 默认走 --text-invert（dark 主题下都是深色），
   叠在 chip 浅 overlay 上不可读。换成 --text-secondary（每主题已定义的"软灰白"）。 */
:root[data-theme='dark'] .npc-label,
:root[data-theme='dark'] .npc-value {
  color: var(--text-secondary);
}

.npc-item.full {
  flex: 0 0 100%;
  max-width: 100%;
}

.npc-label {
  display: block;
  font-size: var(--text-2xs);
  color: var(--text-invert);
  letter-spacing: 0.3px;
  margin-bottom: 1px;
  text-transform: uppercase;
  opacity: 0.6;
}

.npc-value {
  font-size: var(--text-xs);
  color: var(--text-invert);
  line-height: 1.3;
  word-break: break-word;
}

.npc-tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--radius-lg);
  font-size: 0.65rem;
  font-weight: var(--weight-medium);
  word-break: break-word;
  max-width: 100%;
}

.tag-personality {
  background: linear-gradient(135deg, color-mix(in srgb, var(--brand-secondary) 30%, transparent), color-mix(in srgb, var(--brand-secondary) 10%, transparent));
  color: color-mix(in srgb, var(--brand-secondary) 50%, var(--text-invert));
  border: 1px solid color-mix(in srgb, var(--brand-secondary) 40%, transparent);
}

.tag-state {
  background: linear-gradient(135deg, color-mix(in srgb, var(--brand-secondary) 30%, transparent), color-mix(in srgb, var(--brand-secondary) 10%, transparent));
  color: color-mix(in srgb, var(--status-success) 55%, var(--text-on-accent));
  border: 1px solid color-mix(in srgb, var(--brand-secondary) 40%, transparent);
}

.tag-status {
  background: linear-gradient(135deg, color-mix(in srgb, var(--status-success) 30%, transparent), color-mix(in srgb, var(--status-success) 10%, transparent));
  color: color-mix(in srgb, var(--status-success) 55%, var(--text-invert));
  border: 1px solid color-mix(in srgb, var(--status-success) 40%, transparent);
  margin-left: 4px;
}

/* NPC Header 操作按键容器 */
.npc-header-actions {
  position: absolute;
  right: 6px;
  top: 24px;
  display: flex;
  flex-direction: row;
  gap: 3px;
  z-index: 10;
}

/* NPC 卡片删除按键 */
[data-action~="npc-delete-btn"] {
  width: 22px;
  height: 22px;
  border: none;
  background: color-mix(in srgb, var(--status-danger) 15%, transparent);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--text-caption);
  line-height: 1;
  opacity: 0.7;
  transition: all var(--transition-base);
  display: flex;
  align-items: center;
  justify-content: center;
}

.npc-card:hover [data-action~="npc-delete-btn"] {
  opacity: 1;
}

[data-action~="npc-delete-btn"]:hover {
  opacity: 1 !important;
  background: color-mix(in srgb, var(--status-danger) 40%, transparent);
  transform: scale(1.1);
}

/* NPC 卡片选中按键 */
[data-action~="npc-select-btn"] {
  width: 22px;
  height: 22px;
  border: none;
  background: color-mix(in srgb, var(--brand-primary) 15%, transparent);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--text-caption);
  line-height: 1;
  opacity: 0.8;
  transition: all var(--transition-base);
  display: flex;
  align-items: center;
  justify-content: center;
}

[data-action~="npc-select-btn"]:hover {
  opacity: 1;
  transform: scale(1.1);
}

[data-action~="npc-select-btn"].selected {
  background: color-mix(in srgb, var(--status-success) 25%, transparent);
}

[data-action~="npc-select-btn"]:not(.selected) {
  opacity: 0.4;
  filter: grayscale(1);
}

/* 未选中的卡片整体黑白 */
.npc-card-wrapper.unselected .npc-card {
  filter: grayscale(1);
  opacity: 0.6;
}

.npc-card-wrapper.unselected [data-action~="npc-select-btn"] {
  filter: none;
  opacity: 0.8;
}

/* 可编辑字段样式 */
.npc-editable {
  cursor: text;
  border-radius: var(--radius-xs);
  padding: 1px 3px;
  margin: -1px -3px;
  transition: all var(--transition-base);
  outline: none;
  min-width: 20px;
  display: inline-block;
}

.npc-editable:hover {
  background: color-mix(in srgb, var(--brand-primary) 15%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand-primary) 30%, transparent);
}

.npc-editable:focus {
  background: color-mix(in srgb, var(--brand-primary) 25%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-primary) 50%, transparent);
}

/* 编辑中的特殊样式 */
.npc-name.npc-editable:focus {
  background: color-mix(in srgb, var(--brand-secondary) 20%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-secondary) 50%, transparent);
}

.npc-stamp.npc-editable:hover,
.npc-stamp.npc-editable:focus {
  transform: translateY(-50%) rotate(-15deg);
}

/* 编辑提示图标 */
.npc-editable::after {
  content: '✎';
  font-size: 0.6em;
  opacity: 0;
  margin-left: 4px;
  transition: opacity var(--transition-base);
  color: var(--metro-blue);
}

.npc-editable:hover::after {
  opacity: 0.6;
}

.npc-editable:focus::after {
  opacity: 0;
}

/* NPC 卡片响应式 */
@media (max-width: 500px) {
  .npc-cards-row .npc-card,
  .json-cards-row .npc-card {
    flex: 1 1 100%;
    max-width: 100%;
  }
}

@media (max-width: 400px) {
  .npc-name {
    font-size: 1rem;
  }
}

/* ============================================
   NPC UPDATE 审批 UI 样式
   ============================================ */

/* 有待审批更新的卡片 */
.npc-card-wrapper.has-pending-update {
  box-shadow:
    0 0 0 2px var(--status-warning),
    0 4px 12px color-mix(in srgb, var(--status-warning) 30%, transparent);
}

/* 待审批 UI 容器 */
.npc-pending-update {
  background: linear-gradient(135deg, color-mix(in srgb, var(--status-warning) 20%, var(--text-invert)) 0%, color-mix(in srgb, var(--status-warning) 40%, var(--text-invert)) 100%);
  border: 1px solid var(--status-warning);
  border-radius: var(--radius-md);
  padding: 10px;
  margin-top: 10px;
  font-size: 0.85em;
}

/* 待审批头部 */
.pending-header {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px dashed color-mix(in srgb, var(--status-warning) 85%, var(--text-primary));
}

.pending-icon {
  font-size: 1.1em;
}

.pending-title {
  font-weight: var(--weight-semibold);
  color: var(--brand-accent);
  flex: 1;
}

.pending-count {
  font-size: 0.85em;
  color: var(--brand-accent);
  background: var(--sheen-60);
  padding: 2px 8px;
  border-radius: var(--radius-lg);
}

/* 变更列表 */
.pending-changes {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
  max-height: 200px;
  overflow-y: auto;
}

.pending-change-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 8px;
  background: var(--sheen-70);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 0.9em;
  transition: background var(--transition-base);
}

.pending-change-item:hover {
  background: var(--sheen-90);
}

.pending-change-info {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  flex: 1;
  min-width: 0;
}

.pending-field {
  color: var(--brand-primary);
  font-weight: var(--weight-semibold);
  min-width: 70px;
}

.pending-old {
  color: var(--status-danger);
  text-decoration: line-through;
  opacity: 0.8;
  word-break: break-word;
}

.pending-arrow {
  color: var(--text-secondary);
  margin: 0 4px;
  flex-shrink: 0;
}

.pending-new {
  color: color-mix(in srgb, var(--status-success) 85%, var(--text-primary));
  font-weight: var(--weight-semibold);
  word-break: break-word;
}

/* 单字段审批按键容器（按钮本身用 .btn-ghost.btn-icon.btn-sm / .btn-danger.btn-icon.btn-sm） */
.pending-field-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

/* APPROVED 标记样式 */
.npc-badge.approved {
  background: linear-gradient(135deg, var(--status-success) 0%, color-mix(in srgb, var(--status-success) 85%, var(--text-primary)) 100%);
  color: var(--text-invert);
}

/* ============================================
   NPC 卡片拖拽排序样式
   ============================================ */

/* 可拖拽的卡片 */
.npc-card-wrapper[draggable='true'] {
  position: relative;
  cursor: grab;
  transition:
    transform 0.2s ease,
    box-shadow 0.2s ease,
    opacity var(--transition-base);
}

.npc-card-wrapper[draggable='true']:hover {
  box-shadow: 0 4px 12px color-mix(in srgb, var(--brand-primary) 20%, transparent);
}

/* 拖拽中的卡片 */
.npc-card-wrapper.dragging {
  cursor: grabbing;
  opacity: 0.5;
  transform: scale(1.02);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--brand-primary) 30%, transparent);
  z-index: 1000;
}

/* 拖拽占位符 */
.npc-card-placeholder {
  background: linear-gradient(135deg, color-mix(in srgb, var(--brand-primary) 10%, transparent) 0%, color-mix(in srgb, var(--brand-primary) 5%, transparent) 100%);
  border: 2px dashed color-mix(in srgb, var(--brand-primary) 40%, transparent);
  border-radius: var(--radius-lg);
  margin-bottom: 12px;
  transition: height var(--transition-base);
  min-height: 100px;
}

/* 拖拽手柄视觉提示(卡片左侧) */
.npc-card-wrapper[draggable='true']::before {
  content: '......';
  position: absolute;
  left: -20px;
  top: 50%;
  transform: translateY(-50%);
  color: color-mix(in srgb, var(--brand-primary) 30%, transparent);
  font-size: var(--text-body-lg);
  letter-spacing: -2px;
  opacity: 0;
  transition: opacity var(--transition-base);
  pointer-events: none;
}

.npc-card-wrapper[draggable='true']:hover::before {
  opacity: 1;
}

/* 防止拖拽时选中文字 */
.npc-card-wrapper.dragging * {
  user-select: none;
}

/* 拖拽时禁用卡片内的可编辑区域 */
.npc-card-wrapper.dragging .npc-editable {
  pointer-events: none;
}

/* ============================================
   流式输出 (Stream Visualizer) 样式 v2.0
   增强版:骨架屏、平滑过渡、视觉反馈
   ============================================ */

/* ----------------------------------------
   流式状态的消息气泡
   ---------------------------------------- */
.chat-message.streaming-state {
  opacity: 1;
  /* 流式中的 bubble 内容尺寸频繁剧变（骨架→trace→narrative→status&choices），
     禁止它被浏览器选为 scroll anchor，让 anchoring 选稳定的旧 turn / 用户消息当锚 */
  overflow-anchor: none;
}

.chat-message.streaming-state .chat-message-content {
  min-height: 80px;
}

/* _markStaleChoices 会折叠/展开旧 turn 的 choices 区，结构性变化大；
   连同后代一并排除当锚，避免用户滚进上一 turn 选项区时锚点被折叠隐藏导致 fallback 失控 */
.game-choices,
.game-choices * {
  overflow-anchor: none;
}

.streaming-content {
  position: relative;
}

/* ----------------------------------------
   流式指示器(动态渐变圆环)
   ---------------------------------------- */
.streaming-indicator {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-left: 8px;
  border-radius: var(--radius-circle);
  background: conic-gradient(
    from 0deg,
    var(--status-success) 0%,
    color-mix(in srgb, var(--status-success) 70%, var(--text-invert)) 25%,
    color-mix(in srgb, var(--status-success) 50%, var(--text-invert)) 50%,
    color-mix(in srgb, var(--status-success) 70%, var(--text-invert)) 75%,
    var(--status-success) 100%
  );
  animation: streaming-spin 1.2s linear infinite;
  position: relative;
}

.streaming-indicator::after {
  content: '';
  position: absolute;
  inset: 2px;
  background: var(--stream-indicator-inner);
  border-radius: var(--radius-circle);
}

@keyframes streaming-spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

/* ----------------------------------------
   Streaming 取消按钮（嵌在 chat-user-label 里，绿圆圈后面）
   ---------------------------------------- */
.chat-user-label [data-action~="stream-cancel-btn"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 8px;
  padding: 2px 10px;
  height: 22px;
  border-radius: 12px;
  border: 1px solid var(--status-danger);
  background: var(--status-danger);
  color: var(--text-invert);
  cursor: pointer;
  vertical-align: middle;
  transition:
    background 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease,
    filter 0.15s ease;
}

.chat-user-label [data-action~="stream-cancel-btn"]:hover {
  filter: brightness(1.1);
}

.chat-user-label [data-action~="stream-cancel-btn"]:disabled {
  opacity: 0.5;
  cursor: default;
  pointer-events: none;
}

.chat-user-label [data-action~="stream-cancel-btn"] .material-symbols-outlined {
  font-size: 16px;
  line-height: 1;
}

/* ----------------------------------------
   非流式"正在思考..."指示器
   ---------------------------------------- */
.thinking-indicator {
  display: inline-block;
  margin-left: 8px;
  font-size: var(--text-body-sm);
  color: var(--thinking-text);
  animation: thinking-pulse 1.5s ease-in-out infinite;
}

@keyframes thinking-pulse {
  0%,
  100% {
    opacity: 0.4;
  }

  50% {
    opacity: 1;
  }
}

/* ----------------------------------------
   骨架屏加载效果
   ---------------------------------------- */
/* min-height 过渡：finalize 时释放 .streaming-state 上的 min-height，配合本过渡平滑收敛。
   流式期的视觉防塌缩由 CSS `.streaming-state .chat-message-content { min-height: 80px }` 兜底。 */
.chat-message .game-output {
  transition: min-height 220ms ease-out;
}

.streaming-skeleton {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 0;
}

.skeleton-thinking-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82em;
  color: var(--text-soft);
  margin-bottom: 4px;
}

.skeleton-thinking-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--brand-primary);
  animation: skeleton-thinking-pulse 1.4s ease-in-out infinite;
}

@keyframes skeleton-thinking-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.85); }
  50%      { opacity: 1;    transform: scale(1); }
}

.skeleton-thinking-label {
  font-family: var(--font-mono, monospace);
  font-weight: var(--weight-semibold);
}

.skeleton-line {
  height: 16px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--brand-primary) 8%, transparent) 0%,
    color-mix(in srgb, var(--brand-primary) 15%, transparent) 50%,
    color-mix(in srgb, var(--brand-primary) 8%, transparent) 100%
  );
  background-size: 200% 100%;
  border-radius: var(--radius-md);
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
}

/* nth-child 序号 +1 因为顶部多了 .skeleton-thinking-row */
.skeleton-line:nth-child(2) { animation-delay: 0s;   }
.skeleton-line:nth-child(3) { animation-delay: 0.1s; }
.skeleton-line:nth-child(4) { animation-delay: 0.2s; }

@keyframes skeleton-shimmer {
  0% {
    background-position: 200% 0;
  }

  100% {
    background-position: -200% 0;
  }
}

/* trace strip 出现后，骨架屏的"推理中"行被 strip 接管；
   下方叙事 shimmer 继续显示，等待真叙事到来 */
.game-output:has(.react-trace-summary-strip) > .streaming-skeleton > .skeleton-thinking-row {
  display: none;
}

.game-output.react-phase > .stream-slot[data-slot="status"]:not(.filled),
.game-output.react-phase > .stream-slot[data-slot="choices"]:not(.filled) {
  display: none;
}

/* ----------------------------------------
   ReAct 工具调用 trace（内联显示）
   ---------------------------------------- */
.react-trace {
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.react-tool-card {
  --tool-color: var(--brand-primary);
  font-family: var(--font-mono, monospace);
  font-size: 0.82em;
  line-height: 1.4;
  padding: 5px 10px;
  background: var(--surface-code);
  border-left: 3px solid var(--tool-color);
  border-radius: 0 var(--radius-2xs) var(--radius-2xs) 0;
  color: var(--code-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.react-tool-name {
  color: var(--tool-color);
  font-weight: var(--weight-semibold);
  flex-shrink: 0;
}

.react-tool-args {
  color: var(--text-soft);
  opacity: 0.8;
  flex-shrink: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.react-tool-arrow {
  margin: 0 4px;
  color: var(--text-soft);
  opacity: 0.5;
  flex-shrink: 0;
}

.react-tool-result {
  color: var(--text-main);
  opacity: 0.7;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.react-tool-expandable {
  cursor: pointer;
  transition: background 0.15s;
}

.react-tool-expandable:hover {
  /* code-surface-allow: hover 仅改背景，文字色继承父 .react-tool-card 的 --code-text */
  background: color-mix(in srgb, var(--tool-color) 8%, var(--surface-code));
}

.react-tool-expandable::after {
  content: '▸';
  margin-left: auto;
  color: var(--text-soft);
  opacity: 0.4;
  font-size: 0.8em;
  flex-shrink: 0;
  transition: transform 0.15s;
}

.react-tool-expanded::after {
  content: '▾';
}

.react-tool-expanded {
  white-space: pre-wrap;
  max-height: 300px;
  overflow-y: auto;
}

.react-tool-duplicate {
  opacity: 0.4;
  text-decoration: line-through;
}

.react-tool-error {
  --tool-color: var(--status-danger);
}

.react-tool-error .react-tool-result {
  color: var(--status-danger);
}

/* ----------------------------------------
   ReAct 交错显示区域
   ---------------------------------------- */
.react-interleaved {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}

.react-tool-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.react-narrative-segment {
  /* 继承 .game-narrative 的现有样式 */
}

/* ---- 迭代时间线 ---- */

.react-trace-wrapper {
  display: flex;
  flex-direction: column;
  gap: 0;
  position: relative;
  transition: max-height 0.3s ease;
}

/* ---- 折叠态摘要条 ---- */

/* 摘要条始终可见（一旦创建），扮演 trace 的持久头部 + 折叠/展开切换按钮 */
.react-trace-summary-strip {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82em;
  color: var(--text-soft);
  cursor: pointer;
  padding: 2px 0;
  user-select: none;
  transition: color var(--motion-base) ease-out;
}

.react-trace-summary-strip::after {
  content: '\25b8';
  font-size: 0.85em;
  margin-left: auto;
  opacity: 0.5;
  transition: transform var(--motion-base) ease-out;
}

.react-interleaved:not(.react-trace-collapsed) .react-trace-summary-strip::after {
  transform: rotate(90deg);
}

.react-trace-summary-strip:hover {
  color: var(--text-main);
}

/* 折叠态：隐藏迭代和分隔线，只保留摘要条 */
.react-trace-collapsed .react-iteration {
  display: none;
}

.react-trace-collapsed .react-trace-divider {
  display: none;
}

.react-iteration {
  display: flex;
  gap: 8px;
  position: relative;
  padding-bottom: 4px;
}

/* 时间线竖线 — 连接各迭代节点 */
.react-iteration::before {
  content: '';
  position: absolute;
  left: 8px;
  top: 16px;
  bottom: 0;
  width: 1px;
  background: var(--border-soft);
}

.react-iteration:last-child::before {
  display: none;
}

.react-timeline-node {
  flex-shrink: 0;
  width: 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 1px;
}

.react-timeline-dot {
  font-size: 0.72em;
  font-weight: var(--weight-medium);
  color: var(--text-soft);
  opacity: 0.5;
  z-index: 1;
  line-height: 1.4;
}

/* 流式时当前活跃迭代 */
.react-iteration--active .react-timeline-dot {
  color: var(--brand-primary);
  opacity: 0.8;
}

.react-iteration-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* ---- 叙事分隔线 ---- */

.react-trace-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 12px 0 16px 0;
  font-size: var(--text-caption);
  color: var(--text-soft);
  opacity: 0.6;
}

.react-trace-divider::before,
.react-trace-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in srgb, var(--brand-primary) 25%, transparent) 20%,
    color-mix(in srgb, var(--brand-primary) 25%, transparent) 80%,
    transparent
  );
}

/* ---- 迭代 thinking header（紧凑模式） ---- */

@keyframes thinking-dots {
  0%   { content: ''; }
  25%  { content: '.'; }
  50%  { content: '..'; }
  75%  { content: '...'; }
}

.react-thinking-header {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 0.82em;
  line-height: 1.4;
  padding: 0;
  cursor: pointer;
  user-select: none;
  transition: color 0.15s;
}

.react-thinking-header:hover {
  color: var(--text-main);
}

.react-thinking-tools {
  font-family: var(--font-mono, monospace);
  font-weight: var(--weight-semibold);
  color: var(--tool-color, var(--text-main));
}

.react-thinking-status {
  color: var(--text-soft);
  font-size: 0.9em;
}

.react-thinking-status--active::after {
  content: '';
  animation: thinking-dots 1.5s steps(1) infinite;
}

.react-thinking-status--done {
  opacity: 0.7;
}

/* 展开/收起指示器 */
.react-thinking-header .react-thinking-expand-icon {
  font-size: 0.75em;
  color: var(--text-soft);
  opacity: 0;
  transition: opacity 0.15s, transform 0.15s;
  margin-left: auto;
}

.react-thinking-header:hover .react-thinking-expand-icon {
  opacity: 0.5;
}

.react-thinking-header.expanded .react-thinking-expand-icon {
  opacity: 0.7;
  transform: rotate(90deg);
}

/* 可展开详情容器 */
.react-thinking-details {
  display: none;
}

.react-thinking-header.expanded ~ .react-thinking-details {
  display: block;
}

/* 详情内工具卡片允许换行显示完整内容 */
.react-thinking-details .react-tool-card {
  white-space: normal;
  flex-wrap: wrap;
}

.react-thinking-details .react-tool-result {
  overflow: visible;
  text-overflow: unset;
  color: var(--text-soft);
  opacity: 1;
  flex-basis: 100%;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ---- AI 内部推理/思考文本 ---- */

.react-commentary-segment {
  font-size: 0.8em;
  line-height: 1.45;
  color: var(--text-soft);
  padding: 1px 0;
  margin: 0;
  opacity: 0.7;
  transition: opacity 0.2s ease;
}

.react-commentary-segment:hover {
  opacity: 1;
}

.react-commentary-segment::before {
  display: none;
}

.react-commentary-reasoning,
.react-commentary-text {
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

.react-commentary-text {
  margin-top: 3px;
  padding-top: 4px;
  border-top: 1px dashed color-mix(in srgb, var(--brand-purple) 30%, var(--border-soft));
}

.react-commentary-segment > .react-commentary-text:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* ----------------------------------------
   流式叙事区域
   ---------------------------------------- */
.streaming-narrative {
  line-height: 1.8;
  font-size: var(--text-subtitle);
  color: var(--chat-bubble-text);
  min-height: 24px;
  animation: fade-in 0.3s ease-out;
}

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.streaming-narrative p {
  margin-bottom: 12px;
}

.streaming-narrative p:last-child {
  margin-bottom: 0;
}

/* ----------------------------------------
   打字光标(增强版)
   ---------------------------------------- */
.streaming-cursor {
  display: inline-block;
  width: 2px;
  height: 1.2em;
  background: linear-gradient(180deg, var(--metro-blue) 0%, color-mix(in srgb, var(--brand-primary) 60%, var(--brand-magenta)) 100%);
  margin-left: 2px;
  vertical-align: text-bottom;
  border-radius: 1px;
  animation: cursor-blink 0.6s ease-in-out infinite;
  box-shadow: 0 0 8px color-mix(in srgb, var(--brand-primary) 50%, transparent);
}

@keyframes cursor-blink {
  0%,
  100% {
    opacity: 1;
    box-shadow: 0 0 8px color-mix(in srgb, var(--brand-primary) 50%, transparent);
  }

  50% {
    opacity: 0.3;
    box-shadow: 0 0 4px color-mix(in srgb, var(--brand-primary) 20%, transparent);
  }
}

/* ----------------------------------------
   实时统计信息
   ---------------------------------------- */
.streaming-stats {
  display: flex;
  gap: 16px;
  margin-top: 12px;
  padding: 8px 12px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--brand-primary) 5%, transparent) 0%, color-mix(in srgb, var(--brand-purple) 8%, transparent) 100%);
  border-radius: var(--radius-md);
  border: 1px solid color-mix(in srgb, var(--brand-primary) 10%, transparent);
  font-size: var(--text-body-sm);
}


.stat-item {
  display: flex;
  align-items: center;
  gap: 4px;
  color: var(--text-secondary);
}

.stat-icon {
  font-size: var(--text-body-lg);
}

.stat-value {
  font-weight: var(--weight-semibold);
  color: var(--metro-blue);
  font-variant-numeric: tabular-nums;
  min-width: 28px;
}

/* ----------------------------------------
   性能指标栏
   ---------------------------------------- */
.metrics-bar {
  font-size: var(--text-caption);
  color: var(--text-soft);
  display: flex;
  flex-wrap: wrap;
  gap: 6px 12px;
  align-items: center;
  line-height: 1.4;
}

.metrics-bar span {
  white-space: nowrap;
}

/* 紧凑模式 - 悬停显示详情 */
.metrics-bar.metrics-compact {
  display: flex;
  align-items: center;
  gap: 4px;
}

.metric-item {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}

.metric-total {
  color: var(--text-soft);
}

.metric-tokens {
  color: var(--brand-purple);
}

.metric-cost {
  color: var(--status-success);
}

/* Metric Group - 包含指标和其 tooltip */
.metric-group {
  position: relative;
  display: inline-flex;
  align-items: center;
  cursor: help;
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  transition: background-color var(--transition-fast);
}

.metric-group:hover {
  background-color: var(--overlay-10);
}

.metric-group + .metric-group {
  margin-left: 8px;
}

/* 第一个 metric-group 的 tooltip 左对齐，避免超出左边界 */
.metric-group:first-child .metrics-tooltip {
  left: 0;
  transform: translateX(0) translateY(4px);
}

.metric-group:first-child:hover > .metrics-tooltip {
  transform: translateX(0) translateY(0);
}

.metric-group:first-child .metrics-tooltip::after,
.metric-group:first-child .metrics-tooltip::before {
  left: 20px;
  transform: none;
}

/* 自定义 Tooltip */
.metrics-tooltip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--surface-code-alt);
  color: var(--code-text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  min-width: 120px;
  box-shadow: 0 4px 12px var(--overlay-30);
  opacity: 0;
  visibility: hidden;
  transition: all var(--transition-fast);
  z-index: 100;
  pointer-events: none;
}

.metric-group:hover > .metrics-tooltip,
.metric-group.active > .metrics-tooltip {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

/* Tooltip 箭头 */
.metrics-tooltip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--surface-code-alt);
}

.metrics-tooltip::before {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 7px solid transparent;
  border-top-color: var(--border-strong);
}

/* Tooltip 行 */
.tooltip-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-size: var(--text-caption);
}

.tooltip-label {
  color: var(--text-invert);
  opacity: 0.7;
  min-width: 50px;
}

.tooltip-value {
  color: var(--text-invert);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}

.tooltip-divider {
  height: 1px;
  background: var(--border-strong);
  margin: 6px 0;
}

.tooltip-step .tooltip-label {
  min-width: 24px;
  color: var(--text-invert);
  opacity: 0.7;
}

/* ----------------------------------------
   Turn UID 悬浮 - 把 "Turn N" 文本本身做成 tooltip 触发点
   ---------------------------------------- */
.chat-user-label-text {
  display: inline;
}

/* DeepSeek 思考档位徽章：与设置里 thinking tab active 同色 */
.chat-user-label .label-thinking {
  color: var(--brand-accent);
  font-weight: var(--weight-medium);
}

.chat-user-label .turn-uid-group {
  display: inline-block;
  position: relative;
  z-index: 5;
  cursor: pointer;
  padding: 0;
}

.turn-uid-text {
  color: var(--status-success);
  border-bottom: 1px dashed transparent;
  border-radius: var(--radius-xs);
  transition:
    border-color var(--transition-fast),
    background-color var(--transition-fast),
    font-weight var(--transition-fast);
}

.turn-uid-group:hover .turn-uid-text,
.turn-uid-group.active .turn-uid-text {
  border-bottom-color: var(--status-success);
  background-color: var(--overlay-10);
}

.turn-uid-group.copied .turn-uid-text {
  background-color: color-mix(in srgb, var(--status-success) 20%, transparent);
  border-bottom-color: var(--status-success);
  font-weight: var(--weight-semibold);
}

.turn-uid-group .metrics-tooltip {
  pointer-events: auto;
  width: max-content;
  max-width: 360px;
  left: 0;
  transform: translateX(0) translateY(4px);
  /* 上一个气泡的 .chat-message-content 有 backdrop-filter，会创建 stacking context
     把默认 z-index: 100 的 tooltip 罩住——拔高一档确保浮在它之上 */
  z-index: 200;
}

.turn-uid-group:hover > .metrics-tooltip,
.turn-uid-group.active > .metrics-tooltip {
  transform: translateX(0) translateY(0);
}

.turn-uid-group .metrics-tooltip::after,
.turn-uid-group .metrics-tooltip::before {
  left: 16px;
  transform: none;
}

.turn-uid-group .tooltip-row {
  white-space: nowrap;
}

.turn-uid-group .tooltip-value {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  margin-left: 8px;
}

/* ----------------------------------------
   等待生成状态(已被骨架屏替代，保留兼容)
   ---------------------------------------- */
.streaming-waiting {
  color: var(--text-soft);
  font-style: italic;
  animation: pulse-opacity 1.5s ease-in-out infinite;
}

@keyframes pulse-opacity {
  0%,
  100% {
    opacity: 0.6;
  }

  50% {
    opacity: 1;
  }
}

/* ----------------------------------------
   流式错误状态
   ---------------------------------------- */
.streaming-error {
  color: var(--status-danger);
  padding: 12px 16px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--status-danger) 8%, transparent) 0%, color-mix(in srgb, var(--status-danger) 12%, transparent) 100%);
  border-radius: var(--radius-lg);
  border: 1px solid color-mix(in srgb, var(--status-danger) 20%, transparent);
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ----------------------------------------
   中止状态
   ---------------------------------------- */
.chat-message.streaming-aborted {
  opacity: 0.85;
}

.chat-message.streaming-aborted .chat-user-label {
  color: var(--brand-yellow);
}

.streaming-aborted-notice {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  margin-top: 12px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--status-warning) 8%, transparent) 0%, color-mix(in srgb, var(--status-warning) 12%, transparent) 100%);
  border: 1px solid color-mix(in srgb, var(--status-warning) 25%, transparent);
  border-radius: var(--radius-md);
  color: var(--brand-accent);
  font-size: var(--text-body);
}

.abort-icon {
  font-size: var(--text-title);
}

.abort-text {
  font-weight: var(--weight-medium);
}

/* ----------------------------------------
   完成过渡动画
   ---------------------------------------- */
.chat-message.streaming-finishing .chat-message-content {
  animation: content-transition 0.3s ease-out;
}

@keyframes content-transition {
  0% {
    opacity: 0.7;
  }

  100% {
    opacity: 1;
  }
}

.chat-message.streaming-complete {
  animation: complete-flash 0.5s ease-out;
}

@keyframes complete-flash {
  0% {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--status-success) 40%, transparent);
  }

  100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--status-success) 0%, transparent);
  }
}

/* ----------------------------------------
   代码块样式
   ---------------------------------------- */
.streaming-narrative pre {
  background: linear-gradient(135deg, var(--surface-code-alt) 0%, var(--surface-code) 100%);
  color: var(--code-text);
  border-radius: var(--radius-md);
  padding: 14px;
  overflow-x: auto;
  margin: 12px 0;
  border: 1px solid var(--overlay-20);
  box-shadow: inset 0 1px 3px var(--overlay-20);
}

.streaming-narrative code {
  font-family: var(--font-mono);
  font-size: 0.88em;
}

.streaming-narrative pre code {
  color: var(--text-primary);
  line-height: 1.6;
}

.streaming-narrative :not(pre) > code {
  background: color-mix(in srgb, var(--brand-primary) 10%, transparent);
  color: var(--metro-blue);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  font-size: 0.9em;
}

/* ----------------------------------------
   预留槽位样式(避免布局抖动)
   ---------------------------------------- */

/* 所有流式槽位的基础样式 */
.stream-slot {
  transition:
    opacity 0.2s ease,
    transform var(--transition-base);
}

/* 未填充的槽位显示骨架 */
.stream-slot:not(.filled) {
  opacity: 0.5;
}

/* 填充后的槽位动画 */
.stream-slot.filled {
  opacity: 1;
  animation: slot-fill 0.3s ease-out;
}

@keyframes slot-fill {
  from {
    opacity: 0.5;
  }

  to {
    opacity: 1;
  }
}

/* 状态栏槽位骨架 */
.stream-slot[data-slot='status']:not(.filled) {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  padding: 12px 16px;
  background: var(--sheen-40);
  backdrop-filter: blur(8px);
  border-radius: var(--radius-lg);
  border: 1px solid color-mix(in srgb, var(--brand-yellow) 30%, transparent);
}

.skeleton-status-item {
  width: 80px;
  height: 16px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--brand-primary) 8%, transparent) 0%,
    color-mix(in srgb, var(--brand-primary) 15%, transparent) 50%,
    color-mix(in srgb, var(--brand-primary) 8%, transparent) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-xs);
}

.skeleton-status-item:nth-child(1) {
  width: 120px;
  animation-delay: 0s;
}

.skeleton-status-item:nth-child(2) {
  width: 100px;
  animation-delay: 0.1s;
}

.skeleton-status-item:nth-child(3) {
  width: 80px;
  animation-delay: 0.2s;
}

/* 选项槽位骨架 */
.stream-slot[data-slot='choices']:not(.filled) .choices-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.stream-slot[data-slot='choices']:not(.filled) .choices-header {
  opacity: 0.5;
}

.skeleton-choice {
  height: 48px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--brand-primary) 3%, transparent) 0%,
    color-mix(in srgb, var(--brand-primary) 8%, transparent) 50%,
    color-mix(in srgb, var(--brand-primary) 3%, transparent) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-md);
  border: 1px solid color-mix(in srgb, var(--brand-primary) 10%, transparent);
}

.skeleton-choice:nth-child(1) {
  animation-delay: 0s;
}

.skeleton-choice:nth-child(2) {
  animation-delay: 0.15s;
}

.skeleton-choice:nth-child(3) {
  animation-delay: 0.3s;
}

/* Footer 槽位骨架 */
.stream-slot[data-slot='footer']:not(.filled) {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 4px;
  opacity: 0.4;
}

.skeleton-metrics {
  width: 100px;
  height: 12px;
  background: linear-gradient(
    90deg,
    var(--overlay-8) 0%,
    var(--overlay-15) 50%,
    var(--overlay-8) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-xs);
}

/* 阶段进度文本：放在 .streaming-stats pill 里，替代原来的空横杠 */
.stream-progress-text {
  font-size: var(--text-body-sm);
  color: var(--text-soft);
  font-style: italic;
  letter-spacing: 0.02em;
  animation: stream-progress-pulse 1.6s ease-in-out infinite;
}

@keyframes stream-progress-pulse {
  0%, 100% { opacity: 0.6; }
  50%      { opacity: 1; }
}

.skeleton-actions {
  display: flex;
  gap: 4px;
}

.skeleton-actions::before {
  content: '';
  display: flex;
  gap: 4px;
}

/* ----------------------------------------
   响应式调整
   ---------------------------------------- */
@media (max-width: 480px) {
  .streaming-stats {
    flex-direction: column;
    gap: 6px;
    padding: 6px 10px;
  }

  .streaming-skeleton .skeleton-line {
    height: 14px;
  }

  .skeleton-status-item {
    width: 60px !important;
  }

  .metrics-bar {
    font-size: var(--text-sm);
    gap: 4px 10px;
  }
}

/* ============================================
   iPhone 11 / 标准尺寸触控优化 (414px)
   ============================================ */
@media (max-width: 430px) {
  /* 游戏输出容器 */
  .game-output {
    gap: 14px;
  }

  /* 剧情正文可读性 */
  .game-narrative {
    font-size: var(--text-subtitle);
    line-height: 1.75;
  }

  .game-narrative p {
    margin-bottom: 14px;
  }

  /* 状态栏 HUD */
  .game-status {
    padding: 10px 14px;
    gap: 10px 16px;
  }

  .status-item {
    font-size: var(--text-body-sm);
    min-height: 28px;
  }

  /* 选项列表 - 触控优化 */
  .game-choices {
    padding: 10px 12px;
  }

  .choices-list {
    gap: 10px;
  }

  .choice-item {
    padding: 14px 12px;
    min-height: 48px;
    font-size: var(--text-body-lg);
    border-radius: var(--radius-lg);
    /* 触控反馈 */
    -webkit-tap-highlight-color: color-mix(in srgb, var(--brand-primary) 20%, transparent);
  }

  .choice-item:active {
    transform: scale(0.98);
    background: color-mix(in srgb, var(--brand-primary) 10%, transparent);
  }

  .choice-row-1 {
    gap: 6px;
  }

  .choice-row-2 {
    padding-left: 0;
    margin-top: 6px;
  }

  .choice-id {
    font-size: var(--text-subtitle);
    min-width: 24px;
  }

  .choice-type {
    font-size: var(--text-caption);
    padding: 3px 8px;
  }

  .choice-short {
    font-size: var(--text-body-lg);
  }

  .choice-detail {
    font-size: var(--text-body);
    line-height: 1.5;
  }

  /* NPC 卡片优化 */
  .npc-cards-row .npc-card,
  .json-cards-row .npc-card {
    flex: 1 1 100%;
    max-width: 100%;
  }

  .npc-card {
    margin: 4px 0;
  }

  .npc-header {
    padding: 8px 10px;
  }

  .npc-name {
    font-size: 0.95rem;
  }

  .npc-body {
    padding: 10px;
  }

  .npc-stat-row {
    padding: 4px 0;
    font-size: 0.8rem;
  }

  /* NPC 审批按键触控优化 */
  .pending-buttons {
    gap: 10px;
  }

  .btn-secondary.is-loading {
    padding: 10px 16px;
    min-height: 44px;
    font-size: var(--text-body);
    border-radius: var(--radius-md);
  }

  /* Function Calls 状态栏 */
  .function-calls-bar {
    padding: 6px 10px;
    font-size: var(--text-sm);
  }

  .fc-tag {
    padding: 3px 8px;
    font-size: var(--text-xs);
    word-break: break-all;
    max-width: 100%;
  }

  /* 流式输出优化 */
  .streaming-skeleton .skeleton-line {
    height: 12px;
    margin-bottom: 10px;
  }

  .streaming-stats {
    flex-direction: column;
    gap: 4px;
    padding: 8px 10px;
    font-size: var(--text-sm);
  }
}

/* ============================================
   骨架屏辅助类 (Remove Inline Styles)
   ============================================ */
.skeleton-line.w-90 {
  width: 90%;
}

.skeleton-line.w-85 {
  width: 85%;
}

.skeleton-line.w-80 {
  width: 80%;
}

.skeleton-line.w-75 {
  width: 75%;
}

.skeleton-line.w-70 {
  width: 70%;
}

.skeleton-line.w-65 {
  width: 65%;
}

.skeleton-line.w-60 {
  width: 60%;
}

.skeleton-summary {
  cursor: pointer;
  font-size: var(--text-body-sm);
  color: var(--thinking-text);
  padding: 4px 8px;
  user-select: none;
}

.skeleton-summary-hint {
  font-size: var(--text-sm);
  color: var(--thinking-text);
}

/* ============================================
   置顶状态栏 (Sticky Status Bar)
   ============================================ */
.sticky-status-bar {
  position: relative;
  flex-shrink: 0;
  margin: 6px 12px;
  background: var(--sticky-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--hud-border);
  border-radius: var(--radius-md);
  box-shadow: 0 2px 8px var(--overlay-6);
  cursor: pointer;
  transition:
    opacity 0.2s ease,
    margin var(--transition-base);
  z-index: 10;
}

.sticky-status-bar.hidden {
  display: none;
}

.sticky-status-bar.streaming {
  opacity: 0.55;
}

.sticky-status-inner {
  display: flex;
  align-items: center;
  padding: 7px 12px;
  gap: 6px 8px;
}

.sticky-turn-badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 20px;
  min-width: 28px;
  padding: 0 6px;
  background: color-mix(in srgb, var(--brand-yellow) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand-yellow) 40%, transparent);
  border-radius: var(--radius-xs);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--brand-yellow);
  font-family: var(--font-mono);
  letter-spacing: 0.3px;
  user-select: none;
}

.sticky-status-items-compact {
  display: flex;
  align-items: center;
  gap: 0 14px;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}

.sticky-status-items-compact .status-item {
  flex-shrink: 0;
}

.sticky-status-bar .status-item {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-caption);
  color: var(--sticky-text);
  white-space: nowrap;
}

.sticky-status-bar .status-icon {
  font-size: var(--text-body-sm);
  color: var(--brand-yellow);
  line-height: 1;
}

.sticky-status-bar .status-value {
  font-weight: var(--weight-semibold);
  color: var(--sticky-value);
  font-size: var(--text-caption);
  white-space: nowrap;
}

.sticky-status-bar .location-separator {
  color: var(--location-separator);
  font-weight: var(--weight-light);
}

.sticky-status-more {
  font-size: var(--text-caption);
  color: var(--sticky-text);
  opacity: 0.65;
  flex-shrink: 0;
}

.sticky-status-more.hidden {
  display: none;
}

.sticky-status-chevron {
  font-size: 16px;
  color: var(--sticky-text);
  opacity: 0.7;
  flex-shrink: 0;
  transition: transform var(--transition-base);
}

.sticky-status-bar.expanded .sticky-status-chevron {
  transform: rotate(180deg);
}

.sticky-status-popover {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--surface-elevated);
  border: 1px solid var(--hud-border);
  border-radius: var(--radius-md);
  box-shadow:
    0 8px 24px var(--overlay-12),
    0 2px 8px var(--overlay-6);
  padding: 10px 12px;
  max-height: min(50vh, 360px);
  overflow-y: auto;
  z-index: 20;
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition:
    opacity var(--transition-base),
    transform var(--transition-base);
}

.sticky-status-bar.expanded .sticky-status-popover {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.sticky-status-items-full {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.sticky-status-items-full .status-item {
  white-space: normal;
}

.sticky-status-items-full .status-value {
  white-space: normal;
  overflow-wrap: break-word;
}

@media (max-width: 480px) {
  .sticky-status-items-full .status-value {
    word-break: break-all;
    hyphens: auto;
  }
}

/* ============================================
   NPC 角色动态区块（叙事下方玩家可见）
   ============================================ */

.npc-actions-section {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}

.npc-actions-section-header {
  font-size: var(--text-body-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 8px;
}

.npc-action-card {
  display: flex;
  gap: 10px;
  padding: 8px 10px;
  margin-bottom: 6px;
  border-radius: var(--radius-xs);
  background: var(--sheen-3);
  transition: background var(--transition-fast);
}

.npc-action-card:hover {
  background: var(--sheen-5);
}

.npc-action-avatar {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-circle);
  background: var(--accent-primary);
  color: var(--text-invert);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-body-lg);
  font-weight: var(--weight-semibold);
}

.npc-action-content {
  flex: 1;
  min-width: 0;
}

.npc-action-header {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 2px;
}

.npc-action-name {
  font-weight: var(--weight-semibold);
  font-size: var(--text-body);
  color: var(--text-primary);
}

.npc-action-mood {
  font-size: var(--text-caption);
  padding: 1px 6px;
  border-radius: var(--radius-xs);
  background: var(--sheen-8);
  color: var(--text-secondary);
}

.npc-action-location {
  font-size: var(--text-caption);
  color: var(--text-tertiary);
}

.npc-action-location::before {
  content: '📍';
  margin-right: 2px;
}

.npc-action-desc {
  font-size: var(--text-body);
  color: var(--text-primary);
  line-height: 1.4;
  word-wrap: break-word;
  overflow-wrap: break-word;
}

.npc-action-thought {
  font-size: var(--text-body-sm);
  font-style: italic;
  color: var(--text-tertiary);
  margin-top: 2px;
  line-height: 1.3;
}

/* ============================================
   内联输入框（作为选项列表末尾的"自定义"项）
   ============================================ */

.choice-input-host {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 12px 16px;
  background: var(--choice-item-bg);
  border-radius: var(--radius-md);
  border: 1px solid var(--choice-item-border);
  box-shadow: 0 2px 6px var(--overlay-4);
}

.choice-input-host .choice-type {
  font-weight: var(--weight-semibold);
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  font-size: var(--text-body-sm);
  background: color-mix(in srgb, var(--brand-primary) 15%, transparent);
  color: var(--brand-primary);
}

.choice-input-slot {
  flex: 1 1 100%;
  display: flex;
  align-items: stretch;
  gap: 8px;
  min-width: 0;
}

.chat-input-area.inline-as-choice {
  flex: 1;
  padding: 0;
  padding-bottom: 0;
  background: transparent;
  backdrop-filter: none;
  border: none;
}

.choice-item.stale {
  opacity: 0.55;
  cursor: default;
  pointer-events: none;
  box-shadow: none;
}

.game-choices.collapsed > .choices-header,
.game-choices.collapsed > .choices-list {
  display: none;
}

.choices-collapsed-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  cursor: pointer;
  color: var(--text-soft);
  font-size: 0.9em;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  background: var(--surface-elevated);
  opacity: 0.75;
  transition: opacity 0.15s;
}

.choices-collapsed-summary:hover {
  opacity: 1;
}

.choices-collapsed-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.choices-collapsed-expand {
  transition: transform 0.15s;
  font-size: 0.8em;
}

.game-choices:not(.collapsed) > .choices-collapsed-summary .choices-collapsed-expand {
  transform: rotate(90deg);
}

@media (max-width: 430px) {
  .choice-input-host {
    padding: 14px 12px;
    border-radius: var(--radius-lg);
  }
}

/* ============================================
   Shape Token Consumption — chat bubbles + choices
   ============================================
   clip-path is applied to OUTER .chat-message to avoid known
   cross-browser conflict with backdrop-filter on inner
   .chat-message-content. ::after carries the directional
   tail decorator (cartoon's bubble pointer); `content: none`
   default suppresses pseudo-element generation entirely.
   ============================================ */

.chat-message.ai-message {
  clip-path: var(--shape-bubble-clip-ai, none);
}
.chat-message.user-message {
  clip-path: var(--shape-bubble-clip-user, none);
}
.chat-message.ai-message::after {
  content: var(--shape-bubble-tail-ai, none);
}
.chat-message.user-message::after {
  content: var(--shape-bubble-tail-user, none);
}

.choice-item {
  clip-path: var(--shape-choice-clip, none);
}

/* All dark themes — sticky 状态栏与选项面板需要更明显的轮廓。
   cyberpunk dark 单独把 background 改成 surface-card（因为它原 token 用了 background-color
   单值规则不支持的 padding-box/border-box 多层贴图），其他主题保留各自的 sticky-bg/
   choice-panel-bg，仅加强描边 + 轻发光。 */
:root[data-theme='dark'] .sticky-status-bar,
:root[data-theme='dark'] .game-choices {
  border-color: color-mix(in srgb, var(--text-primary) 24%, var(--border-soft));
  box-shadow:
    0 0 8px color-mix(in srgb, var(--text-primary) 10%, transparent),
    0 2px 8px var(--overlay-15);
}

:root[data-skin='cyberpunk'][data-theme='dark'] .sticky-status-bar,
:root[data-skin='cyberpunk'][data-theme='dark'] .game-choices {
  background-color: var(--surface-card);
  border-color: var(--border-soft);
  box-shadow:
    0 0 10px color-mix(in srgb, var(--brand-primary) 14%, transparent),
    0 2px 8px var(--overlay-12);
}

/* Cartoon — sticky 底色 = brand-yellow，原 .sticky-turn-badge 文字也是 brand-yellow，黄底上不可见。
   改用 sticky-text（light 深紫黑、dark 纯黑），与卡通 ink 语言一致。 */
:root[data-skin='cartoon'] .sticky-turn-badge {
  color: var(--sticky-text);
}

/* All dark themes — metrics 悬浮气泡内文字默认走 --text-invert（dark 主题下都是深色），
   叠在 --surface-code-alt 黑底上完全不可读。换成 --text-secondary。 */
:root[data-theme='dark'] .metrics-tooltip .tooltip-label,
:root[data-theme='dark'] .metrics-tooltip .tooltip-value,
:root[data-theme='dark'] .metrics-tooltip .tooltip-step .tooltip-label {
  color: var(--text-secondary);
}
