/* ==========================================================================
   Obsidian Reserve —— 新版设计系统
   与旧 public/css/style.css 并存：新外壳与新页面只引本文件，
   旧页面（蛋库/彩蛋/农场/后台等）继续用 style.css，等各自适配时再切换。

   设计基调：石墨单色、四层表面、无投影靠明度分层、圆角 8/12/16。
   只用一组低饱和微彩强调色表达状态（在线/待处理/故障），不做高彩装饰。
   ========================================================================== */

/* ---------- 字体 ----------
   自托管字体的 @font-face 与字体栈 token（--ob-font / --ob-mono / --ob-emoji）统一在
   public/css/fonts.css 里定义，本文件不再自带一份——两处各写一份就是「站内两套字体」的来源。
   fonts.css 由每个外壳的 <head> 在样式表之前引入（见 partials/shell_head.ejs）。 */

:root {
  /* 表面层级 */
  --ob-surface-0: #121316;
  --ob-surface-1: #18191d;
  --ob-surface-2: #202227;
  --ob-surface-3: #282a30;
  /* 描边 */
  --ob-line: #2e3138;
  --ob-line-strong: #3b3f48;
  /* 文本 */
  --ob-text: #f0f1f3;
  --ob-text-2: #c5c8d0;
  --ob-text-3: #8b909a;
  /* 状态色（克制使用） */
  --ob-ok: #88998d;
  --ob-ok-bg: #1a1d1b;
  --ob-ok-line: #28302a;
  /* 「活的」信号单独一族：在场人数、在线点、正在讨论、READY、数字农场的脉冲点。
     原来这些都用 --ob-ok（#88998d 鼠尾草灰），在暗底上几乎看不出是绿的，
     「在线」这类信息要一眼可见，所以给它们一个鲜亮的绿。 */
  --ob-live: #2ecc71;
  --ob-live-bg: rgba(46, 204, 113, .14);
  --ob-live-line: rgba(46, 204, 113, .42);
  /* 「进行中」的中性蓝：反馈状态、需要与「已完成(绿)」「待处理(粘土)」区分开 */
  --ob-info: #3b9cf0;
  --ob-info-bg: rgba(59, 156, 240, .14);
  --ob-info-line: rgba(59, 156, 240, .42);
  --ob-warn: #b89b72;
  --ob-warn-bg: #1f1c18;
  --ob-warn-line: #332d24;
  --ob-err: #b37575;
  --ob-err-bg: #231a1b;
  --ob-err-line: #3a2a2c;
  /* 投票选中态：香=绿、臭=红。比 --ob-ok/--ob-err 更明确一点，
     因为这两个按钮的选中与否是用户最需要一眼确认的反馈 */
  --ob-up: #45c07d;
  --ob-up-bg: rgba(69, 192, 125, .16);
  --ob-up-line: rgba(69, 192, 125, .52);
  --ob-down: #e2656a;
  --ob-down-bg: rgba(226, 101, 106, .16);
  --ob-down-line: rgba(226, 101, 106, .52);

  --ob-radius-sm: 6px;
  --ob-radius: 8px;
  --ob-radius-md: 10px;
  --ob-radius-lg: 12px;
  --ob-radius-xl: 16px;

  /* 字体栈（--ob-font / --ob-mono / --ob-emoji）见 public/css/fonts.css：全站唯一来源，
     每个外壳的 <head> 都会引它。这里不要再写一份，否则老壳/新壳会各用各的字体。 */

  --ob-margin: 2rem;
  /* 正文两侧的间隙：侧栏→正文、正文→右栏都用它，两边必须相等，正文才在中间。
     （侧栏贴视口左边、右栏还要留 --ob-margin 到视口右边，这 32px 的差是「侧栏贴边」这个形态
       自带的，无法消掉；正文中心相对视口中心只偏 16px，肉眼基本看不出。） */
  --ob-gutter: 2rem;
  /* 顶栏（桌面 .ob-top）高度：它是常驻视口顶部的 sticky 横条，侧栏的品牌头、
     右栏的钉住位置、页内锚点的避让都要跟它对齐，所以高度只在这里写一份。
     改这里 = 顶栏、侧栏头、右栏、发帖编辑器工具栏整条线一起挪。 */
  --ob-top-h: 60px;
  /* 左侧导航栏：展开 240px（默认）/ 收起 72px 图标栏。
     --ob-side-cur 是「当前宽度」：侧栏宽度与正文让位都读它，
     html.ob-side-min 一挂上去两处同时换值，收起/展开才不会各自跳一下。 */
  --ob-side-w: 240px;
  --ob-side-min-w: 72px;
  --ob-side-cur: var(--ob-side-w);
  /* 收展的节奏：侧栏宽度（shell.css 的 .ob-side）与正文让位（.ob-body 的 padding-left）
     必须共用这组值——两边各写一份时长/曲线就会不同步，看着是正文与侧栏「错位」。 */
  --ob-side-dur: .34s;
  --ob-side-ease: cubic-bezier(.33, .75, .12, 1);
  /* 右栏列宽。2026-10-13 起 = 侧栏 240 + 32：页面最右侧那条 --ob-margin 留白取消了，
     那份宽度并进右栏、右栏贴到视口右缘（见 shell.css 里 .ob-main:has(...) 的 padding-right: 0）。
     所以右栏比侧栏宽 32px——不再严格同宽，是用户明确要的「右侧不留空白、宽度给右栏」。
     侧栏收起成 72px 时右栏不动（那是用户的一次性偏好吗，不该跟着缩）。 */
  --ob-rail-w: 272px;
  /* 宽度上限：**故意不设**。缩放或拉宽窗口时，间隙（--ob-margin / --ob-gutter）保持不变，
     多出来的宽度全部让正文自己变长去填（同 nodeloc 那类论坛的策略）。
     早先这里有个 1600px 的上限，超宽屏下间隙会涨到 350px、正文被夹窄，与这条策略相反。 */

  /* 整站背景图（后台「默认封面」）上面的遮罩：只压画布这一层，
     卡片本身是不透明表面，所以这个值决定「照片透出多少」而不是「文字看不看得清」。
     想更透就把 alpha 调小，亮色主题在 obsidian-light.css 里另有一个值。 */
  --ob-page-scrim: rgba(18, 19, 22, .80);

  color-scheme: dark;
}

/* ---------- 基础 ---------- */
*, *::before, *::after { box-sizing: border-box; }

.ob-body {
  margin: 0;
  background: var(--ob-surface-0);
  color: var(--ob-text);
  font-family: var(--ob-font);
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* 桌面端左侧固定导航栏需要留出空间（≤900px 由 shell.css 的媒体查询归零） */
  padding-left: var(--ob-side-cur);
  transition: padding-left var(--ob-side-dur) var(--ob-side-ease);
}

/* 侧边栏收起态：整份布局只认这一个类，宽度变量换成图标栏的值 */
html.ob-side-min { --ob-side-cur: var(--ob-side-min-w); }

/* 基础重置一律用 :where() 把特异性压到最低（只剩元素本身，0,0,1）。
   否则 `.ob-body a`（0,1,1）会压过所有单类组件规则——表现是组件自己写的颜色全部失效，
   链接一律变回正文色。踩过一次，别改成普通后代选择器。 */
:where(.ob-body) a { color: inherit; text-decoration: none; }
:where(.ob-body) a:hover { color: var(--ob-text); }
:where(.ob-body) button { font: inherit; color: inherit; }
/* 标题必须给行高：只重置 margin 的话行高会继承正文的 20px，
   字号大于 20px 的标题就会挤在一起（表单页的 h1 与简介一度直接重叠）。 */
:where(.ob-body) h1 { margin: 0; font-weight: 600; line-height: 1.4; }
:where(.ob-body) h2 { margin: 0; font-weight: 600; line-height: 1.45; }
:where(.ob-body) h3 { margin: 0; font-weight: 600; line-height: 1.5; }
:where(.ob-body) h4 { margin: 0; font-weight: 600; line-height: 1.5; }
:where(.ob-body) p { margin: 0; }
:where(.ob-body) ul, :where(.ob-body) ol { margin: 0; padding: 0; list-style: none; }
:where(.ob-body) img { max-width: 100%; }
:where(.ob-body) input, :where(.ob-body) textarea, :where(.ob-body) select { font: inherit; color: inherit; }
.ob-body ::selection { background: #3b3f48; color: var(--ob-text); }

/* 焦点环：不用亮蓝，只用描边色加粗，避免破坏单色平衡 */
.ob-body :focus-visible {
  outline: 2px solid var(--ob-line-strong);
  outline-offset: 1px;
}

/* 显示层级：作者样式里的 display:flex 会盖掉 [hidden] 的 UA 规则（.ob-sheet 这类浮层
   就是这种情况），所以统一在这里把 hidden 重新钉死，否则首屏会被浮层糊住。 */
.ob-body [hidden] { display: none !important; }

/* 滚动条压暗，避免浅色滚动条在暗底上格外刺眼 */
.ob-body { scrollbar-color: #3b3f48 var(--ob-surface-0); }
.ob-body ::-webkit-scrollbar { width: 10px; height: 10px; }
.ob-body ::-webkit-scrollbar-track { background: transparent; }
.ob-body ::-webkit-scrollbar-thumb { background: #31343b; border-radius: 9999px; border: 2px solid var(--ob-surface-0); }
.ob-body ::-webkit-scrollbar-thumb:hover { background: #3b3f48; }

/* ---------- 排版工具类 ---------- */
.ob-mono { font-family: var(--ob-mono); font-variant-numeric: tabular-nums; }
.ob-label {
  font-family: var(--ob-mono);
  font-size: 11px;
  font-weight: 400;
  line-height: 14px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ob-text-3);
}
.ob-muted { color: var(--ob-text-3); }
.ob-dim { color: var(--ob-text-2); }
.ob-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.ob-num { font-family: var(--ob-mono); font-variant-numeric: tabular-nums; }
.ob-tabular { font-variant-numeric: tabular-nums; }
.ob-nowrap { white-space: nowrap; }
.ob-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ob-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ob-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* ---------- 按钮 ---------- */
.ob-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid transparent;
  border-radius: var(--ob-radius);
  background: transparent;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .15s, border-color .15s, color .15s;
}
.ob-btn:disabled { opacity: .45; cursor: not-allowed; }
.ob-btn-primary { background: var(--ob-text); color: var(--ob-surface-0); }
.ob-btn-primary:hover:not(:disabled) { background: var(--ob-text-2); color: var(--ob-surface-0); }
.ob-btn-secondary { background: var(--ob-surface-2); border-color: var(--ob-line); color: var(--ob-text); }
.ob-btn-secondary:hover:not(:disabled) { background: var(--ob-surface-3); border-color: var(--ob-line-strong); }
.ob-btn-ghost { color: var(--ob-text-3); }
.ob-btn-ghost:hover:not(:disabled) { background: var(--ob-surface-1); color: var(--ob-text); }
.ob-btn-danger { color: var(--ob-err); border-color: var(--ob-err-line); background: var(--ob-err-bg); }
.ob-btn-danger:hover:not(:disabled) { border-color: var(--ob-err); }
.ob-btn-sm { height: 30px; padding: 0 10px; font-size: 13px; border-radius: var(--ob-radius-sm); }
.ob-btn-xs { height: 26px; padding: 0 8px; font-size: 12px; border-radius: var(--ob-radius-sm); }
.ob-btn-block { width: 100%; }
.ob-btn-icon { width: 36px; padding: 0; }
.ob-btn-icon.ob-btn-sm { width: 30px; }

/* 图标按钮：只有悬停才浮出底色，静止时与背景齐平 */
.ob-iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid transparent;
  border-radius: var(--ob-radius);
  background: transparent;
  color: var(--ob-text-3);
  cursor: pointer;
  position: relative;
  transition: background-color .15s, color .15s, border-color .15s;
}
.ob-iconbtn:hover { background: var(--ob-surface-2); color: var(--ob-text); }
.ob-iconbtn.is-active { background: var(--ob-surface-2); color: var(--ob-text); border-color: var(--ob-line); }
.ob-iconbtn svg { width: 17px; height: 17px; }

/* ---------- 表单 ---------- */
.ob-input, .ob-textarea, .ob-select {
  width: 100%;
  min-height: 36px;
  padding: 7px 12px;
  background: var(--ob-surface-1);
  border: 1px solid var(--ob-line);
  border-radius: var(--ob-radius);
  color: var(--ob-text);
  transition: border-color .15s, box-shadow .15s;
}
.ob-input::placeholder, .ob-textarea::placeholder { color: var(--ob-text-3); }
.ob-input:focus, .ob-textarea:focus, .ob-select:focus {
  outline: none;
  border-color: var(--ob-line-strong);
  box-shadow: 0 0 0 1px var(--ob-line-strong);
}
.ob-textarea { resize: vertical; line-height: 22px; }
.ob-select { appearance: none; padding-right: 30px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ob-text-3) 50%), linear-gradient(135deg, var(--ob-text-3) 50%, transparent 50%);
  background-position: calc(100% - 16px) 15px, calc(100% - 11px) 15px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.ob-field { display: flex; flex-direction: column; gap: 6px; }
.ob-field-label { font-size: 12px; color: var(--ob-text-2); }
.ob-hint { font-size: 12px; color: var(--ob-text-3); }
.ob-check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; color: var(--ob-text-2); }
.ob-check input[type="checkbox"] {
  appearance: none; width: 16px; height: 16px; margin: 0; flex: none;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line-strong); border-radius: 4px; cursor: pointer;
}
.ob-check input[type="checkbox"]:checked { background: var(--ob-text); border-color: var(--ob-text); }
.ob-check input[type="checkbox"]:checked::after {
  content: ''; display: block; width: 4px; height: 8px; margin: 1px 0 0 5px;
  border: solid var(--ob-surface-0); border-width: 0 2px 2px 0; transform: rotate(45deg);
}

/* ---------- chip / 徽章 ---------- */
.ob-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 9px;
  border: 1px solid var(--ob-line);
  border-radius: 9999px;
  background: var(--ob-surface-2);
  color: var(--ob-text-2);
  font-size: 12px;
  white-space: nowrap;
}
.ob-chip-mono { font-family: var(--ob-mono); font-size: 11px; letter-spacing: 0.02em; text-transform: uppercase; }
.ob-chip-link:hover { border-color: var(--ob-line-strong); color: var(--ob-text); background: var(--ob-surface-3); }
.ob-chip.is-active { background: var(--ob-surface-3); border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-chip-dot::before { content: ''; width: 6px; height: 6px; border-radius: 9999px; background: var(--ob-text-3); flex: none; }
.ob-chip-ok { background: var(--ob-ok-bg); border-color: var(--ob-ok-line); color: var(--ob-text-2); }
.ob-chip-ok::before { background: var(--ob-ok); }
/* 实时的状态用鲜绿：正在讨论、在场、READY 都属于「此刻活着」的信号，
   与「已完成/中性」（ok）和「角色徽章」（也用 ok）分开，避免管理员徽章跟在线指示撞色 */
.ob-chip-live { background: var(--ob-live-bg); border-color: var(--ob-live-line); color: var(--ob-live); }
.ob-chip-live::before { background: var(--ob-live); box-shadow: 0 0 6px var(--ob-live-line); }
.ob-chip-warn { background: var(--ob-warn-bg); border-color: var(--ob-warn-line); color: var(--ob-warn); }
.ob-chip-warn::before { background: var(--ob-warn); }
.ob-chip-err { background: var(--ob-err-bg); border-color: var(--ob-err-line); color: var(--ob-err); }
.ob-chip-err::before { background: var(--ob-err); }
/* 等级章：Lv.N 用等宽字，读起来像读数而不是文案 */
.ob-lv {
  display: inline-flex; align-items: center; height: 20px; padding: 0 7px;
  border: 1px solid var(--ob-line); border-radius: 5px; background: var(--ob-surface-1);
  color: var(--ob-text-2); font-family: var(--ob-mono); font-size: 11px; letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
/* 称号：沿用称号系统自带的颜色，只把形状拉进新体系 */
.ob-title {
  display: inline-flex; align-items: center; height: 20px; padding: 0 7px;
  border: 1px solid currentColor; border-radius: 5px; font-size: 11px; line-height: 1;
}
.ob-title img { height: 18px; display: block; }
.ob-badge-host {
  display: inline-flex; align-items: center; height: 18px; padding: 0 5px;
  border-radius: 4px; background: var(--ob-text); color: var(--ob-surface-0);
  font-family: var(--ob-mono); font-size: 10px; letter-spacing: .04em;
}

/* ---------- 头像 ---------- */
.ob-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 9999px; overflow: hidden; flex: none;
  color: #fff; font-size: 13px; font-weight: 500; background: var(--ob-surface-3);
  user-select: none;
}
.ob-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ob-avatar-sm { width: 26px; height: 26px; font-size: 11px; }
.ob-avatar-lg { width: 44px; height: 44px; font-size: 17px; }
.ob-avatar-xl { width: 72px; height: 72px; font-size: 26px; }
.ob-avatar-wrap { position: relative; flex: none; }
/* 在线绿点：带一圈底色描边，压在头像或列表行上都不糊 */
.ob-presence {
  position: absolute; right: -1px; bottom: -1px; width: 10px; height: 10px;
  border-radius: 9999px; background: var(--ob-live); border: 2px solid var(--ob-surface-1);
}
.ob-presence.is-off { background: var(--ob-text-3); }

/* ---------- 卡片 ---------- */
.ob-card {
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  border: 1px solid var(--ob-line);
  border-radius: var(--ob-radius-lg);
  backdrop-filter: blur(8px);
  transition: border-color .15s;
}
.ob-card-hover:hover { border-color: var(--ob-line-strong); }
.ob-card-pad { padding: 16px; }

/* ---------- 讨论卡片（partials/ob_topic_card）----------
   首页、搜索页、分区页共用同一份卡片 partial，所以样式必须放在这里（共享层）——
   原先只在 home.css 里，搜索页没加载那份样式，结果卡片就丢了内边距与排布（文字贴着卡片边）。
   注意 room.css 也给 .ob-stream 设了自己的 gap（讨论室的消息流用 2px），它后加载、依然生效。 */
.ob-stream { display: flex; flex-direction: column; gap: 10px; }
.ob-tcard { padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; }
.ob-tcard.is-pinned { border-color: var(--ob-warn-line); }
.ob-tcard-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; color: var(--ob-text-3); }
.ob-tcard-author { color: var(--ob-text-2); font-size: 13px; font-weight: 500; }
.ob-tcard-author:hover { color: var(--ob-text); }
.ob-tcard-time { margin-left: auto; font-size: 11.5px; white-space: nowrap; }
.ob-tcard-title { font-size: 16px; line-height: 24px; font-weight: 600; }
.ob-tcard-title a:hover { color: var(--ob-text-2); }
.ob-tcard-excerpt { font-size: 13px; line-height: 20px; color: var(--ob-text-3); }
.ob-tcard-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 2px; }
.ob-tcard-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; flex: 1; min-width: 0; }
.ob-tcard-metrics { display: flex; align-items: center; gap: 14px; color: var(--ob-text-3); font-size: 12px; }
.ob-tcard-actions { display: flex; align-items: center; gap: 8px; }
/* 卡片上的「总结」是原生表单（无 JS 也要能提交），display:contents 让它的按钮
   直接当 .ob-tcard-actions 的 flex 子项，不额外占一层盒子 */
.ob-tcard-summary { display: contents; }
@media (max-width: 900px) {
  .ob-tcard-tags { flex-wrap: nowrap; overflow: hidden; }
  .ob-tcard-tags .ob-chip { flex: none; }
  .ob-tcard { padding: 13px 14px; }
  .ob-tcard-title { font-size: 15px; line-height: 22px; }
  .ob-tcard-foot { gap: 10px; }
  .ob-tcard-actions { width: 100%; }
  .ob-tcard-actions .ob-btn { flex: 1; }
}
.ob-panel { background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg); }
.ob-section-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px; border-bottom: 1px solid var(--ob-line);
}
.ob-section-title { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; }
.ob-divider { height: 1px; background: var(--ob-line); border: 0; margin: 0; }
/* 侧栏口径注脚：卡片底部的说明条，首页「在线统计」与讨论室「讨论者」共用。
   原先只写在 home.css 里，讨论室那页没加载那份样式，这条说明就成了没有内边距、
   没有分隔线的裸文本贴在卡片边缘上（看起来像溢出了卡片）。 */
.ob-live-note { padding: 10px 16px 14px; font-size: 11.5px; line-height: 17px; color: var(--ob-text-3); border-top: 1px solid var(--ob-line); }

/* 呼吸点：只用在「正在直播」这类真的在变的指标上 */
.ob-pulse { width: 7px; height: 7px; border-radius: 9999px; background: var(--ob-live); box-shadow: 0 0 8px var(--ob-live-line); flex: none; position: relative; }
.ob-pulse::after {
  content: ''; position: absolute; inset: -3px; border-radius: 9999px;
  border: 1px solid var(--ob-live); opacity: .6; animation: ob-pulse 2s ease-out infinite;
}
@keyframes ob-pulse { 0% { transform: scale(.7); opacity: .55; } 70% { transform: scale(1.5); opacity: 0; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .ob-pulse::after { animation: none; } }

/* ---------- 指标与小组件（首页卡片、讨论室统计行共用） ---------- */
.ob-metric { display: inline-flex; align-items: center; gap: 5px; color: var(--ob-text-3); font-size: 12px; }
.ob-metric em { font-style: normal; font-family: var(--ob-mono); font-variant-numeric: tabular-nums; color: var(--ob-text-2); }
.ob-metric-live { color: var(--ob-warn); }
.ob-metric-live em { color: var(--ob-warn); }

/* 垂直堆叠：卡片内部的小块间距 */
.ob-stack { display: flex; flex-direction: column; gap: 10px; }
.ob-inline-form { display: inline-flex; }
.ob-mini {
  display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 9px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: transparent; color: var(--ob-text-3); font-size: 12px; cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s;
}
.ob-mini:hover { color: var(--ob-text); border-color: var(--ob-line-strong); background: var(--ob-surface-1); }
.ob-mini.is-on { color: var(--ob-text); border-color: var(--ob-line-strong); background: var(--ob-surface-2); }
.ob-mini-danger { color: var(--ob-err); border-color: var(--ob-err-line); }
/* 举报是折叠表单：summary 收起时只显示一个 mini 按钮 */
.ob-rpt { display: inline-block; }
.ob-rpt > summary { list-style: none; }
.ob-rpt > summary::-webkit-details-marker { display: none; }
.ob-rpt form { display: flex; gap: 6px; margin-top: 8px; }
.ob-rpt input {
  flex: 1; min-width: 160px; min-height: 28px; padding: 3px 9px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm); font-size: 12px;
}

/* ---------- 进度 ---------- */
/* 轨道统一描一圈边：不加边框时，轨道底色与卡片底色在亮色主题下几乎同色，
   看不出「已填 / 未填」的分界，进度条等于白给。 */
.ob-progress { height: 6px; border-radius: 9999px; background: var(--ob-surface-3); border: 1px solid var(--ob-line); overflow: hidden; }
.ob-progress > i { display: block; height: 100%; border-radius: 9999px; background: var(--ob-text); transition: width .3s; }
.ob-progress-sm { height: 5px; }
.ob-progress-ok > i { background: var(--ob-ok); }

/* ---------- 表格 ---------- */
.ob-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ob-table th {
  height: 36px; padding: 0 16px; text-align: left;
  font-family: var(--ob-mono); font-size: 11px; font-weight: 400; letter-spacing: .03em; text-transform: uppercase;
  color: var(--ob-text-3); border-bottom: 1px solid var(--ob-line); white-space: nowrap;
}
.ob-table td { padding: 12px 16px; border-bottom: 1px solid var(--ob-surface-1); vertical-align: middle; }
.ob-table tbody tr:hover { background: color-mix(in srgb, var(--ob-surface-1) 60%, transparent); }
.ob-table .ob-num { font-variant-numeric: tabular-nums; }

/* ---------- 列表行 ---------- */
.ob-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--ob-surface-1);
}
.ob-row:last-child { border-bottom: 0; }
.ob-row-hover:hover { background: color-mix(in srgb, var(--ob-surface-1) 60%, transparent); }

/* ---------- 骨架屏与空态 ---------- */
.ob-skeleton {
  background: linear-gradient(90deg, var(--ob-surface-2) 25%, var(--ob-surface-3) 37%, var(--ob-surface-2) 63%);
  background-size: 400% 100%; animation: ob-shimmer 1.4s ease infinite; border-radius: 6px;
}
@keyframes ob-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

.ob-empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 40px 20px; text-align: center; color: var(--ob-text-3);
}
.ob-empty-icon {
  width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg); background: var(--ob-surface-1);
  color: var(--ob-text-3); margin-bottom: 2px;
}
.ob-empty-icon svg { width: 19px; height: 19px; }
.ob-empty-title { color: var(--ob-text-2); font-size: 14px; }
.ob-empty-text { font-size: 13px; max-width: 42ch; line-height: 20px; }

/* ---------- 站标：剖开的蛋 ----------
   icon('yolk') = 蛋壳轮廓 + 实心蛋黄；蛋黄那颗圆单独挂 .ic-yolk，
   默认跟文字色走——暗色主题刻意保持灰阶（DESIGN.md 里 accent 只给运行状态），
   亮色主题在 obsidian-light.css 里换成蛋黄主题色。 */
.ic-yolk { fill: currentColor; }

/* 预留能力：明确告知「接入中」，不用假数字占位 */
.ob-pending {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border: 1px dashed var(--ob-line-strong); border-radius: var(--ob-radius);
  background: color-mix(in srgb, var(--ob-surface-1) 70%, transparent);
  color: var(--ob-text-3); font-size: 12px; line-height: 18px;
}
.ob-pending strong { color: var(--ob-text-2); font-weight: 500; display: block; margin-bottom: 2px; }

/* ---------- 提示页（改版中 / 404 / 403 / 500）----------
   放在设计系统里而不是某个页面的样式表里：提示页不加载任何页面级 CSS，
   之前放在 home.css 时元素会挤成一团。 */

.ob-uc { max-width: 620px; margin: 8vh auto 0; }
.ob-uc-card { padding: 28px; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.ob-uc-icon {
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg); background: var(--ob-surface-1); color: var(--ob-text-3);
}
.ob-uc-title { font-size: 20px; line-height: 28px; }
.ob-uc-text { font-size: 13.5px; line-height: 21px; color: var(--ob-text-2); }
.ob-uc-text.ob-muted { color: var(--ob-text-3); }
.ob-uc-actions { display: flex; gap: 10px; margin-top: 6px; }
@media (max-width: 900px) {
  .ob-uc { margin-top: 4vh; }
}

/* ---------- 提示条 ---------- */
.ob-notice { padding: 10px 14px; border-radius: var(--ob-radius); font-size: 13px; border: 1px solid var(--ob-line); background: var(--ob-surface-1); color: var(--ob-text-2); }
.ob-notice-ok { border-color: var(--ob-ok-line); background: var(--ob-ok-bg); color: var(--ob-text-2); }
.ob-notice-warn { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-notice-err { border-color: var(--ob-err-line); background: var(--ob-err-bg); color: var(--ob-err); }

/* ---------- Toast ---------- */
.ob-toasts {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 8px; z-index: 90; pointer-events: none;
}
.ob-toast {
  padding: 9px 16px; border-radius: 9999px;
  background: var(--ob-surface-3); border: 1px solid var(--ob-line-strong); color: var(--ob-text);
  font-size: 13px; box-shadow: 0 8px 32px -4px rgba(0, 0, 0, .45);
}
.ob-toast.is-err { border-color: var(--ob-err); color: #ffdad6; }

/* ---------- Markdown 正文（新版排版） ---------- */
.ob-prose { font-size: 15px; line-height: 26px; color: var(--ob-text-2); word-wrap: break-word; }
.ob-prose > *:first-child { margin-top: 0; }
.ob-prose > *:last-child { margin-bottom: 0; }
.ob-prose h1, .ob-prose h2, .ob-prose h3, .ob-prose h4 { color: var(--ob-text); margin: 22px 0 10px; line-height: 1.4; }
.ob-prose h1 { font-size: 21px; }
.ob-prose h2 { font-size: 18px; }
.ob-prose h3 { font-size: 16px; }
.ob-prose h4 { font-size: 15px; }
.ob-prose p { margin: 0 0 12px; }
.ob-prose a { color: var(--ob-text); text-decoration: underline; text-decoration-color: var(--ob-line-strong); text-underline-offset: 3px; }
.ob-prose a:hover { text-decoration-color: var(--ob-text); }
.ob-prose strong { color: var(--ob-text); font-weight: 600; }
.ob-prose ul, .ob-prose ol { margin: 0 0 12px; padding-left: 22px; list-style: revert; }
.ob-prose li { margin: 4px 0; }
.ob-prose blockquote {
  margin: 0 0 12px; padding: 2px 0 2px 14px;
  border-left: 2px solid var(--ob-line-strong); color: var(--ob-text-3);
}
.ob-prose hr { border: 0; border-top: 1px solid var(--ob-line); margin: 18px 0; }
.ob-prose code {
  font-family: var(--ob-mono); font-size: 13px;
  background: var(--ob-surface-3); border: 1px solid var(--ob-line);
  border-radius: 5px; padding: 1px 5px; color: var(--ob-text);
}
.ob-prose pre {
  margin: 0 0 14px; padding: 14px 16px; overflow-x: auto;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
}
.ob-prose pre code { background: none; border: 0; padding: 0; font-size: 12.5px; line-height: 20px; color: var(--ob-text-2); }
.ob-prose img { border-radius: var(--ob-radius); border: 1px solid var(--ob-line); margin: 6px 0; }
.ob-prose table { width: 100%; border-collapse: collapse; margin: 0 0 14px; font-size: 13px; }
.ob-prose th, .ob-prose td { border: 1px solid var(--ob-line); padding: 7px 10px; text-align: left; }
.ob-prose .mention { color: var(--ob-text); background: var(--ob-surface-2); border-radius: 4px; padding: 0 4px; }

/* ==========================================================================
   旧页面桥接
   已放行的 /notifications、/profile、/settings、/search、/edit 仍复用既有模板结构，
   这里把旧类名映射到新 token，避免为了 4 个页面重写全部标记。
   注意：这不是给旧页面用的兜底样式层，而是过渡期让「已迁移页面 + 既有表单结构」成立的最小集合。
   ========================================================================== */
.ob-body .container { padding: 0 var(--ob-margin); }
.ob-body .single-col { max-width: 940px; margin: 0 auto; padding: 24px 0 48px; }
.ob-body .muted { color: var(--ob-text-3); }
.ob-body .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.ob-body .dot { width: 7px; height: 7px; border-radius: 9999px; display: inline-block; flex: none; }
.ob-body .dot.big { width: 9px; height: 9px; }
.ob-body .dot-sep { color: var(--ob-text-3); }

/* 卡片与分区 */
.ob-body .section-card, .ob-body .side-card, .ob-body .form-page-card, .ob-body .notice-card,
.ob-body .topic-card, .ob-body .reply-form-card, .ob-body .post-card, .ob-body .auth-card {
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  padding: 16px; margin-bottom: 14px; backdrop-filter: blur(8px);
}
.ob-body .section-card h3, .ob-body .side-card h3 {
  font-size: 13px; font-family: var(--ob-mono); letter-spacing: .03em; text-transform: uppercase;
  color: var(--ob-text-3); font-weight: 400; margin-bottom: 12px;
}
.ob-body .section-h1 { font-size: 19px; margin-bottom: 14px; }

/* 旧按钮类 → 新按钮 */
.ob-body .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 36px; padding: 0 14px; border-radius: var(--ob-radius); border: 1px solid var(--ob-line);
  background: var(--ob-surface-2); color: var(--ob-text); font-size: 14px; font-weight: 500;
  cursor: pointer; white-space: nowrap; transition: background-color .15s, border-color .15s, color .15s;
}
.ob-body .btn:hover { background: var(--ob-surface-3); border-color: var(--ob-line-strong); }
.ob-body .btn-primary { background: var(--ob-text); color: var(--ob-surface-0); border-color: var(--ob-text); }
.ob-body .btn-primary:hover { background: var(--ob-text-2); border-color: var(--ob-text-2); color: var(--ob-surface-0); }
.ob-body .btn-ghost { background: transparent; color: var(--ob-text-2); }
.ob-body .btn-ghost:hover { background: var(--ob-surface-1); color: var(--ob-text); }
.ob-body .btn-sm { height: 30px; padding: 0 10px; font-size: 13px; }
.ob-body .btn-block { width: 100%; }
.ob-body .btn-checkin-done { background: var(--ob-ok-bg); border-color: var(--ob-ok-line); color: var(--ob-text-2); }
.ob-body .mini-btn {
  display: inline-flex; align-items: center; height: 26px; padding: 0 9px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: transparent; color: var(--ob-text-3); font-size: 12px; cursor: pointer;
}
.ob-body .mini-btn:hover { color: var(--ob-text); border-color: var(--ob-line-strong); background: var(--ob-surface-1); }
.ob-body .mini-btn.danger { color: var(--ob-err); border-color: var(--ob-err-line); }
.ob-body .mini-link { color: var(--ob-text-2); font-size: 12px; text-decoration: underline; text-underline-offset: 3px; }

/* 旧 chip 类 → 新 chip */
.ob-body .cat-chip, .ob-body .tag-chip, .ob-body .lv-chip, .ob-body .admin-chip,
.ob-body .pin-chip, .ob-body .lock-chip, .ob-body .kind-chip, .ob-body .profile-chip {
  display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  color: var(--ob-text-2); font-size: 11.5px; white-space: nowrap;
}
.ob-body .lv-chip { font-family: var(--ob-mono); font-size: 11px; }
.ob-body .admin-chip { background: var(--ob-surface-3); border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .pin-chip { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .lock-chip { border-color: var(--ob-err-line); background: var(--ob-err-bg); color: var(--ob-err); }
.ob-body .kind-chip { border-style: dashed; color: var(--ob-text-3); }
.ob-body .title-chip { display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border: 1px solid currentColor; border-radius: 9999px; font-size: 11.5px; }
.ob-body .title-art img { height: 22px; display: block; }

/* 旧头像类 → 新头像（.avatar 由 avatarTag 生成，可能是 img 也可能是 span） */
.ob-body .avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 9999px; object-fit: cover; flex: none;
  color: #fff; font-size: 13px; font-weight: 500; overflow: hidden; user-select: none;
}
.ob-body .avatar-xs { width: 24px; height: 24px; font-size: 11px; }
.ob-body .avatar-s { width: 26px; height: 26px; font-size: 11px; }
.ob-body .avatar-m { width: 36px; height: 36px; font-size: 14px; }
.ob-body .avatar-l { width: 56px; height: 56px; font-size: 20px; }
.ob-body .avatar-xl { width: 72px; height: 72px; font-size: 26px; }

/* 旧表单结构 → 新表单 */
.ob-body .form-row { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.ob-body .form-row > label { font-size: 12px; color: var(--ob-text-2); }
.ob-body .form-row-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.ob-body .form-row input[type="text"], .ob-body .form-row input[type="password"], .ob-body .form-row input[type="email"],
.ob-body .form-row input[type="search"], .ob-body .form-row input[type="url"], .ob-body .form-row input[type="number"],
.ob-body .form-row select, .ob-body .form-row textarea,
.ob-body .search-page-form input[type="search"] {
  width: 100%; min-height: 36px; padding: 7px 12px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius);
  color: var(--ob-text);
}
.ob-body .form-row textarea { line-height: 22px; resize: vertical; }
.ob-body .form-row input:focus, .ob-body .form-row select:focus, .ob-body .form-row textarea:focus,
.ob-body .search-page-form input:focus {
  outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong);
}
.ob-body .form-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 6px; }
.ob-body .field-hint { font-size: 12px; }
.ob-body .check-line { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ob-text-2); }
.ob-body .empty { padding: 36px 20px; text-align: center; color: var(--ob-text-3); }

/* 旧列表 / 话题行（搜索页复用 topic_rows） */
.ob-body .topic-row { padding: 14px 16px; border-bottom: 1px solid var(--ob-surface-1); }
.ob-body .topic-row:last-child { border-bottom: 0; }
.ob-body .topic-row:hover { background: color-mix(in srgb, var(--ob-surface-1) 60%, transparent); }
.ob-body .tr-main { display: flex; gap: 14px; align-items: flex-start; }
.ob-body .tr-content { flex: 1; min-width: 0; }
.ob-body .tr-author-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; font-size: 12px; color: var(--ob-text-3); }
.ob-body .tr-author { color: var(--ob-text-2); font-size: 13px; }
.ob-body .tr-title-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .tr-title { font-size: 15.5px; font-weight: 600; color: var(--ob-text); }
.ob-body .tr-thumb { width: 88px; height: 66px; border-radius: var(--ob-radius); overflow: hidden; border: 1px solid var(--ob-line); flex: none; }
.ob-body .tr-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ob-body .tr-footer-line { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 10px; flex-wrap: wrap; }
.ob-body .tr-tags-area { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ob-body .tr-stats-icons { display: flex; align-items: center; gap: 14px; color: var(--ob-text-3); font-size: 12px; }
.ob-body .stat-icon { display: inline-flex; align-items: center; gap: 5px; }
.ob-body .stat-icon em { font-style: normal; font-family: var(--ob-mono); font-variant-numeric: tabular-nums; }
.ob-body .topic-crumb { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ob-text-3); margin-bottom: 14px; }

/* 旧帖子 / 回复结构（编辑页与旧 AJAX 片段复用） */
.ob-body .post-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; font-size: 12px; color: var(--ob-text-3); }
.ob-body .post-author { color: var(--ob-text); font-size: 13px; font-weight: 500; }
.ob-body .post-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.ob-body .post-side { flex: none; }
.ob-body .post-body { flex: 1; min-width: 0; }
.ob-body .inline-form { display: inline; }
.ob-body .vote-btn {
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: transparent;
  color: var(--ob-text-2); font-size: 12.5px; cursor: pointer;
}
.ob-body .vote-btn:hover { border-color: var(--ob-line-strong); background: var(--ob-surface-1); }
.ob-body .vote-btn.active { border-color: var(--ob-text); color: var(--ob-text); background: var(--ob-surface-3); }
.ob-body .vote-btn .vc { font-family: var(--ob-mono); font-variant-numeric: tabular-nums; }
.ob-body .egg-ic::before { content: '香'; font-size: 11px; opacity: .7; }
.ob-body .egg-ic.rotten::before { content: '臭'; }
.ob-body .rpt, .ob-body .adm-menu { display: inline-block; }
.ob-body .rpt > summary, .ob-body .adm-menu > summary { list-style: none; }
.ob-body .rpt > summary::-webkit-details-marker, .ob-body .adm-menu > summary::-webkit-details-marker { display: none; }
.ob-body .rpt form { display: flex; gap: 6px; margin-top: 8px; }
.ob-body .rpt input { flex: 1; min-height: 30px; padding: 4px 10px; background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm); font-size: 12px; }
.ob-body .adm-menu-list { position: absolute; z-index: 20; margin-top: 6px; padding: 6px; display: flex; flex-direction: column; gap: 4px;
  background: var(--ob-surface-3); border: 1px solid var(--ob-line-strong); border-radius: var(--ob-radius);
  box-shadow: 0 8px 32px -4px rgba(0, 0, 0, .45); }
.ob-body .notice-card { color: var(--ob-text-2); font-size: 13px; }

/* 旧 tabs / pager */
.ob-body .tabs-card { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.ob-body .tabs { display: inline-flex; gap: 4px; padding: 3px; background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); }
.ob-body .tabs a, .ob-body .tabs span {
  display: inline-flex; align-items: center; height: 28px; padding: 0 12px;
  border-radius: var(--ob-radius-sm); font-size: 13px; color: var(--ob-text-3);
}
.ob-body .tabs a:hover { color: var(--ob-text); background: var(--ob-surface-2); }
.ob-body .tabs a.active, .ob-body .tabs span.active { background: var(--ob-surface-3); color: var(--ob-text); }
.ob-body .pager { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 18px 0; font-size: 13px; }

/* 旧搜索页 */
.ob-body .search-page-form { display: flex; gap: 10px; margin-bottom: 16px; }
.ob-body .result-count { font-size: 12px; margin-bottom: 10px; }
.ob-body .hp-search-list { display: flex; flex-direction: column; }
.ob-body .hp-search-list li { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--ob-surface-1); }
.ob-body .hp-search-name { color: var(--ob-text); font-size: 13.5px; }
.ob-body .hp-search-meta { font-size: 12px; }

/* 旧通知列表 */
.ob-body .notif-item { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--ob-surface-1); }
.ob-body .notif-item:last-child { border-bottom: 0; }
.ob-body .notif-item.unread { background: color-mix(in srgb, var(--ob-surface-1) 55%, transparent); }
.ob-body .notif-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ob-body .notif-line { font-size: 13.5px; color: var(--ob-text-2); }
.ob-body .notif-line strong { color: var(--ob-text); font-weight: 500; }
.ob-body .notif-excerpt { font-size: 12px; }
.ob-body .notif-time { font-size: 11.5px; font-family: var(--ob-mono); flex: none; }

/* 旧个人主页 */
.ob-body .profile-card { overflow: hidden; border: 1px solid var(--ob-line); border-radius: var(--ob-radius-xl); background: var(--ob-surface-1); margin-bottom: 16px; }
.ob-body .profile-cover { height: 132px; background: linear-gradient(135deg, hsl(calc(var(--cover-h, 0) * 1deg), 12%, 18%), hsl(calc((var(--cover-h, 0) + 40) * 1deg), 10%, 11%)); background-size: cover; background-position: center; position: relative; }
.ob-body .profile-cover-mesh { position: absolute; inset: 0; background: linear-gradient(180deg, transparent 40%, var(--ob-surface-1)); }
.ob-body .cover-edit-wrap { position: absolute; right: 12px; bottom: 12px; display: flex; gap: 8px; z-index: 2; }
.ob-body .cover-edit-btn { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
  background: rgba(18, 19, 22, .72); border: 1px solid var(--ob-line-strong); border-radius: var(--ob-radius-sm);
  color: var(--ob-text-2); font-size: 12px; cursor: pointer; backdrop-filter: blur(6px); }
.ob-body .profile-user-bar { display: flex; gap: 16px; padding: 0 20px 18px; margin-top: -34px; position: relative; flex-wrap: wrap; }
.ob-body .profile-avatar-wrap { flex: none; border: 3px solid var(--ob-surface-1); border-radius: 9999px; background: var(--ob-surface-1); }
.ob-body .ph-info { flex: 1; min-width: 240px; padding-top: 38px; }
.ob-body .ph-name { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .ph-name h1 { font-size: 20px; }
.ob-body .profile-chips-row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.ob-body .profile-chip .chip-ic { font-size: 11px; opacity: .75; }
.ob-body .ph-bio { margin-top: 10px; color: var(--ob-text-2); font-size: 13.5px; line-height: 21px; }
.ob-body .lv-progress { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; font-size: 12px; }
.ob-body .lv-bar { height: 6px; border-radius: 9999px; background: var(--ob-surface-3); border: 1px solid var(--ob-line); overflow: hidden; }
.ob-body .lv-bar span { display: block; height: 100%; background: var(--ob-text); border-radius: 9999px; }
.ob-body .profile-actions { display: flex; align-items: flex-start; gap: 8px; padding-top: 38px; }
.ob-body .stats-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1px; background: var(--ob-line); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg); overflow: hidden; margin-bottom: 16px; }
.ob-body .stat-box { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px; background: var(--ob-surface-2); }
.ob-body .stat-box strong { font-size: 19px; font-family: var(--ob-mono); font-variant-numeric: tabular-nums; font-weight: 500; }
.ob-body .stat-box span { font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .profile-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; align-items: start; }
.ob-body .profile-main { display: flex; flex-direction: column; gap: 14px; }
.ob-body .profile-side { display: flex; flex-direction: column; gap: 14px; }
.ob-body .mini-topic { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--ob-surface-1); font-size: 13.5px; }
.ob-body .mini-topic:last-child { border-bottom: 0; }
.ob-body .mini-topic a { color: var(--ob-text); }
.ob-body .re-excerpt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.ob-body .lv-list { display: flex; flex-direction: column; gap: 8px; }
.ob-body .lv-list li { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 12.5px; }
.ob-body .tag-cloud { display: flex; flex-wrap: wrap; gap: 7px; }

/* 旧设置 / 认证页结构 */
.ob-body .auth-wrap { max-width: 720px; margin: 0 auto; padding: 28px 0 56px; }
.ob-body .settings-card { padding: 22px; }
.ob-body .settings-tip { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 14px; margin-bottom: 16px; font-size: 12.5px; color: var(--ob-warn);
  background: var(--ob-warn-bg); border: 1px solid var(--ob-warn-line); border-radius: var(--ob-radius); }
.ob-body .settings-tip strong { color: var(--ob-text); white-space: nowrap; font-weight: 500; }
.ob-body .avatar-row .avatar-editor { display: flex; align-items: center; gap: 14px; }
.ob-body .avatar-actions, .ob-body .cover-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .settings-cover-preview { height: 96px; border-radius: var(--ob-radius); border: 1px solid var(--ob-line); background: var(--ob-surface-1) center/cover; display: flex; align-items: center; justify-content: center; margin-bottom: 10px; }
.ob-body .cover-editor { display: flex; flex-direction: column; }
.ob-body .sec-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 26px 0 10px; }
.ob-body .sec-head h2 { font-size: 14px; }

/* 桥接兜底：旧模板里散落的 details/summary 与 inline 表单 */
.ob-body summary { cursor: pointer; }
.ob-body .auth-card h1 { font-size: 20px; margin-bottom: 18px; }

/* ---------- 响应式 ---------- */
@media (max-width: 900px) {
  .ob-body .container { padding: 0 1rem; }
  .ob-body .single-col { max-width: 100%; }
  .ob-body .form-row-grid { grid-template-columns: 1fr; }
  .ob-body .stats-row { grid-template-columns: repeat(3, 1fr); }
  .ob-body .profile-layout { grid-template-columns: 1fr; }
  .ob-body .profile-actions { padding-top: 0; }
}

/* ==========================================================================
   第二批桥接：称号 / 邀请 / 反馈 / 签到 / 榜单 / 中转站测评
   这些页面的模板都是照着 style.css 的通用类写的，没有自己的样式表。
   这里把那一套类名整体映射到新 token 上，模板不动——比逐个重写模板安全得多
   （这些页面里混着不少表单校验与状态分支，重写容易漏）。
   命名沿用原类名，不要改，否则模板里的 class 会对不上。
   ========================================================================== */

/* 主区 + 右栏的两栏布局（反馈 / 签到 / 中转站 / 榜单 / 蛋库 / 后台都用它）。
   右栏宽度与间隙都走全局变量，和首页右栏、左侧边栏保持一致（左右对称的那套口径） */
.ob-body .page-layout {
  padding: 24px 0 48px;
  display: grid; grid-template-columns: minmax(0, 1fr) var(--ob-rail-w); gap: var(--ob-gutter); align-items: start;
}
.ob-body .main-col { min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.ob-body .side-col { display: flex; flex-direction: column; gap: 14px; }

/* 规则条目列表（右栏说明卡、公约页都用） */
.ob-body .rule-list { display: flex; flex-direction: column; gap: 8px; }
.ob-body .rule-list li {
  position: relative; padding-left: 14px; font-size: 12.5px; line-height: 19px; color: var(--ob-text-2);
}
.ob-body .rule-list li::before {
  content: ''; position: absolute; left: 0; top: 7px;
  width: 4px; height: 4px; border-radius: 9999px; background: var(--ob-line-strong);
}

/* 数据表格：与设计系统的 .ob-table 同一套观感（表头等宽大写、行分隔压暗） */
.ob-body .data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ob-body .data-table th {
  height: 36px; padding: 0 12px; text-align: left; white-space: nowrap;
  font-family: var(--ob-mono); font-size: 11px; font-weight: 400; letter-spacing: .03em; text-transform: uppercase;
  color: var(--ob-text-3); border-bottom: 1px solid var(--ob-line);
}
.ob-body .data-table td { padding: 10px 12px; border-bottom: 1px solid var(--ob-surface-1); vertical-align: middle; }
.ob-body .data-table tbody tr:hover { background: color-mix(in srgb, var(--ob-surface-1) 60%, transparent); }
.ob-body .data-table td strong { font-family: var(--ob-mono); font-weight: 500; }
/* 前三名用金/银/铜，与今日香蛋 TOP3 的配色保持一致 */
.ob-body .data-table .rank, .ob-body .ar-rank, .ob-body .rk-top .ar-rank {
  font-family: var(--ob-mono); font-variant-numeric: tabular-nums; color: var(--ob-text-3);
}
.ob-body .rank-1, .ob-body .ar-rank.r1 { color: #e0b34e; font-weight: 600; }
.ob-body .rank-2, .ob-body .ar-rank.r2 { color: #c3c8d1; font-weight: 600; }
.ob-body .rank-3, .ob-body .ar-rank.r3 { color: #c58a5b; font-weight: 600; }

/* 大按钮（签到页主按钮） */
.ob-body .btn-lg { height: 44px; padding: 0 22px; font-size: 15px; border-radius: var(--ob-radius-md); }

/* 状态胶囊：待处理=粘士色、处理中=蓝、已解决=鲜绿。色相即语义，别再靠文字读 */
.ob-body .status-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  font-size: 11.5px; color: var(--ob-text-3); white-space: nowrap;
}
.ob-body .status-chip::before { content: ''; width: 6px; height: 6px; border-radius: 9999px; background: currentColor; flex: none; }
.ob-body .status-open { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .status-processing { border-color: var(--ob-info-line); background: var(--ob-info-bg); color: var(--ob-info); }
.ob-body .status-resolved { border-color: var(--ob-live-line); background: var(--ob-live-bg); color: var(--ob-live); }

/* 页面引导卡（称号 / 反馈 / 蛋库 / 彩蛋共用同一形态） */
.ob-body .feedback-intro-card, .ob-body .egg-intro-card {
  padding: 18px 20px; margin-bottom: 14px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background:
    radial-gradient(120% 140% at 0% 0%, rgba(136, 153, 141, .10), transparent 55%),
    color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
}
.ob-body .feedback-intro-card h1, .ob-body .egg-intro-card h1 { font-size: 20px; margin-bottom: 6px; }
.ob-body .egg-intro-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ob-body .egg-intro-desc { font-size: 12.5px; line-height: 19px; color: var(--ob-text-3); }
/* 介绍卡标题里的「在架 N 枚」实时胶囊（与原型顶部的实时监控胶囊同形） */
.ob-body .egg-live {
  display: inline-flex; align-items: center; gap: 6px; margin-left: 10px; vertical-align: middle;
  padding: 3px 10px; border-radius: 9999px; border: 1px solid var(--ob-line); background: var(--ob-surface-1);
  font-family: var(--ob-mono); font-size: 11px; font-weight: 400; color: var(--ob-text-3);
}
.ob-body .egg-live i { position: relative; width: 7px; height: 7px; border-radius: 9999px; background: var(--ob-live); flex: none; }
.ob-body .egg-live i::after {
  content: ''; position: absolute; inset: 0; border-radius: 9999px;
  border: 1px solid var(--ob-live); opacity: .6; animation: ob-pulse 2s ease-out infinite;
}
@media (prefers-reduced-motion: reduce) { .ob-body .egg-live i::after { animation: none; } }
.ob-body .egg-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.ob-body .egg-publish { display: inline-flex; }

/* ---------- 称号中心（/titles）---------- */
.ob-body .equipped-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ob-body .eq-now { display: flex; align-items: center; gap: 9px; }
.ob-body .titles-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.ob-body .title-card {
  display: flex; flex-direction: column; gap: 10px; padding: 14px 16px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  transition: border-color .15s;
}
.ob-body .title-card:hover { border-color: var(--ob-line-strong); }
/* 已解锁的卡片用一条左侧亮边区分，而不是整卡变色（整卡变色会把徽章图压住） */
.ob-body .title-card.earned { border-left: 2px solid var(--ob-live); }
.ob-body .tc-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.ob-body .tc-name { display: flex; flex-direction: column; gap: 6px; }
.ob-body .tc-name strong { font-size: 15px; }
.ob-body .tc-desc { font-size: 12px; line-height: 18px; }
.ob-body .title-art-lg img { height: 30px; display: block; }
.ob-body .tc-progress { margin-top: 2px; }
.ob-body .tc-equip { margin-top: auto; }
.ob-body .tc-equip .btn { width: 100%; }
.ob-body .tc-wearing { font-size: 12px; margin-top: auto; }

/* ---------- 邀请中心（/invite）---------- */
.ob-body .admin-stats { margin-bottom: 14px; }
.ob-body .ic-code-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin-top: 12px; }
.ob-body .ic-code-card {
  display: flex; flex-direction: column; gap: 9px; padding: 12px 14px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius); background: var(--ob-surface-1);
}
.ob-body .ic-code-card.used { opacity: .6; }
.ob-body .ic-code {
  font-family: var(--ob-mono); font-size: 15px; letter-spacing: .06em; color: var(--ob-text);
  user-select: all;
}
.ob-body .ic-code-card.used .ic-code { text-decoration: line-through; color: var(--ob-text-3); }
.ob-body .ic-code-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .copy-btn { cursor: pointer; }

/* ---------- 问题反馈（/feedback）---------- */
.ob-body .feedback-item { padding: 14px 0; border-bottom: 1px solid var(--ob-surface-1); }
.ob-body .feedback-item:last-child { border-bottom: 0; }
.ob-body .fi-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; font-size: 12px; color: var(--ob-text-3); }
.ob-body .fb-type {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 9999px;
  border: 1px solid var(--ob-line); background: var(--ob-surface-3); color: var(--ob-text-2); font-size: 11.5px;
}
.ob-body .fi-content { margin-top: 9px; font-size: 13.5px; line-height: 22px; color: var(--ob-text-2); }
.ob-body .fi-reply {
  margin-top: 10px; padding: 10px 12px; font-size: 13px; line-height: 21px;
  border-left: 2px solid var(--ob-live); background: var(--ob-live-bg); border-radius: 0 var(--ob-radius) var(--ob-radius) 0;
  color: var(--ob-text-2);
}
.ob-body .fi-reply strong { color: var(--ob-text); }
.ob-body .fi-admin { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.ob-body .fi-admin select, .ob-body .fi-admin input {
  min-height: 32px; padding: 5px 10px; font-size: 12.5px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm); color: var(--ob-text);
}
.ob-body .fi-admin input { flex: 1; min-width: 180px; }

/* ---------- 榜单（/rank）----------
   这些 ar-* / rk-* 原本由 arena.css 提供，而那份样式走的是旧主题变量（--card/--text…），
   新页面不加载 style.css 因而取不到值。直接把类名桥接到新 token，并在模板里去掉 arena.css 引用。 */
.ob-body .ar-card {
  padding: 16px; margin-bottom: 14px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
}
.ob-body .ar-card h3 { font-size: 14px; margin-bottom: 4px; }
.ob-body .ar-intro h1 { font-size: 22px; margin-bottom: 8px; }
.ob-body .ar-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.ob-body .ar-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  font-size: 12px; color: var(--ob-text-2);
}
.ob-body a.ar-chip:hover { border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .ar-list { display: flex; flex-direction: column; gap: 2px; margin-top: 10px; }
.ob-body .ar-row { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--ob-surface-1); }
.ob-body .ar-row:last-child { border-bottom: 0; }
.ob-body .ar-rank { flex: none; min-width: 20px; font-size: 13px; padding-top: 1px; }
.ob-body .ar-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 9px; }
.ob-body .ar-line1 { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.ob-body .ar-dot { width: 8px; height: 8px; border-radius: 9999px; flex: none; }
.ob-body .ar-name { font-size: 14.5px; font-weight: 600; color: var(--ob-text); }
.ob-body .ar-name:hover { color: var(--ob-text-2); }
.ob-body .ar-score { font-family: var(--ob-mono); font-size: 15px; font-weight: 500; }
.ob-body .ar-voters { font-size: 11.5px; }
/* 五（八）维小条形图：--v 是 0-10 的分值，宽度按 --v*10% 算。
   列数改成自适应：维度从 5 扩到 8 后，写死列数会在窄栏里挤成两层。 */
.ob-body .ar-bars { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.ob-body .ar-cell { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.ob-body .ar-cell-top { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; font-size: 11px; color: var(--ob-text-3); }
.ob-body .ar-cell-top em { font-style: normal; font-family: var(--ob-mono); font-size: 11.5px; color: var(--ob-text-2); }
/* display: block 是必须的：榜单里它靠 flex 自动块化，详情页表格里它是 span，
   保持 inline 会让高度被忽略、整条看不见（踩过一次）。 */
.ob-body .ar-track { display: block; height: 6px; border-radius: 9999px; background: var(--ob-surface-3); border: 1px solid var(--ob-line); overflow: hidden; }
.ob-body .ar-track i { display: block; height: 100%; border-radius: 9999px; width: calc(var(--v, 0) * 10%); background: var(--mc, var(--ob-text-2)); }
.ob-body .rk-boards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.ob-body .rk-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--ob-surface-1); }
.ob-body .rk-row:last-child { border-bottom: 0; }
.ob-body .rk-name { flex: 1; min-width: 0; font-size: 13.5px; color: var(--ob-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ob-body .rk-val { font-family: var(--ob-mono); font-size: 14px; }
.ob-body .rk-unit { font-size: 11px; font-family: var(--ob-font); }
.ob-body .rk-sub { font-size: 12px; margin-top: 2px; }

/* ---------- 中转站测评详情（/review/:id）---------- */
.ob-body .topic-head-card {
  padding: 16px; margin-bottom: 14px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
}
.ob-body .th-title-line { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ob-body .th-title { font-size: 21px; }
.ob-body .th-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 9px; font-size: 12px; color: var(--ob-text-3); }
.ob-body .rv-overall { font-family: var(--ob-mono); font-size: 24px; font-weight: 500; color: var(--ob-live); }
.ob-body .review-grid { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 14px; align-items: start; }
.ob-body .radar-wrap { display: flex; align-items: center; justify-content: center; padding: 10px; color: var(--ob-text-3); }
.ob-body .radar-wrap svg text { font-family: var(--ob-mono); fill: var(--ob-text-3); }
.ob-body .rate-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; margin-bottom: 14px; }
.ob-body .rate-item { display: flex; flex-direction: column; gap: 6px; }
.ob-body .rate-item label { font-size: 12.5px; color: var(--ob-text-2); }
.ob-body .rv-comment { max-width: 320px; }

/* ---------- 响应式 ---------- */
@media (max-width: 900px) {
  .ob-body .page-layout { grid-template-columns: minmax(0, 1fr); padding: 16px 0 32px; }
  .ob-body .review-grid { grid-template-columns: minmax(0, 1fr); }
  .ob-body .ar-bars { grid-template-columns: repeat(3, 1fr); }
  .ob-body .titles-grid { grid-template-columns: minmax(0, 1fr); }
  .ob-body .radar-wrap svg { width: 100%; height: auto; }
}
/* ---------- 鸡棚（/coop）与孵化区（/hatch）----------
   两者的标记都靠 egg.css，而那份样式走旧主题变量（--line/--text/--ok/--card…），
   新外壳不加载 style.css，所以模板里去掉 egg.css 引用、类名由这里接管。 */
.ob-body .egg-login-hint { font-size: 12.5px; }
.ob-body .coop-review-hint { font-size: 12.5px; }

/* 状态小标签（蛋库 / 彩蛋 / 鸡棚 / 孵化区共用同一族） */
.ob-body .rc-chip {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-3);
  font-size: 11px; color: var(--ob-text-3); white-space: nowrap;
}
.ob-body .rc-chip-ok { border-color: var(--ob-live-line); background: var(--ob-live-bg); color: var(--ob-live); }
.ob-body .rc-chip-low { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .rc-chip-sold { border-color: var(--ob-err-line); background: var(--ob-err-bg); color: var(--ob-err); }
/* 领取积分胶囊：语义同福利中心的「可支配积分 / 进账」= 绿，数字走等宽 */
.ob-body .rc-chip-cost { border-color: var(--ob-live-line); background: var(--ob-live-bg); color: var(--ob-live); font-family: var(--ob-mono); font-size: 11px; }
.ob-body .rc-chip-cost b { font-weight: 500; }

/* 折叠式发布表单：收起时是一条虚线框提示，展开后与表单连成一张卡 */
.ob-body .egg-publish > summary {
  list-style: none; cursor: pointer; padding: 10px 14px;
  border: 1px dashed var(--ob-line-strong); border-radius: var(--ob-radius);
  color: var(--ob-text-2); font-size: 13px;
}
.ob-body .egg-publish > summary::-webkit-details-marker { display: none; }
.ob-body .egg-publish > summary:hover { border-color: var(--ob-text-3); color: var(--ob-text); }
.ob-body .egg-publish[open] > summary {
  border-style: solid; border-color: var(--ob-line);
  border-radius: var(--ob-radius) var(--ob-radius) 0 0; color: var(--ob-text);
}
.ob-body .egg-publish form {
  padding: 14px; border: 1px solid var(--ob-line); border-top: 0;
  border-radius: 0 0 var(--ob-radius) var(--ob-radius); background: var(--ob-surface-1);
}

/* 鸡棚卡片：左侧状态色竖边表示审查结果（待审查/已上架/已驳回） */
.ob-body .coop-card {
  padding: 14px 16px; margin-bottom: 10px;
  border: 1px solid var(--ob-line); border-left: 2px solid var(--ob-line);
  border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  transition: border-color .15s;
}
.ob-body .coop-card:hover { border-color: var(--ob-line-strong); }
.ob-body .coop-card.status-pending { border-left-color: var(--ob-warn); }
.ob-body .coop-card.status-approved { border-left-color: var(--ob-live); }
.ob-body .coop-card.status-rejected { border-left-color: var(--ob-err); }
.ob-body .cc-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ob-body .cc-name { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 15px; }
.ob-body .cc-desc { margin-top: 8px; font-size: 13.5px; line-height: 22px; color: var(--ob-text-2); }
.ob-body .cc-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; font-size: 12px; color: var(--ob-text-3); }
.ob-body .cc-url {
  color: var(--ob-text); text-decoration: underline;
  text-decoration-color: var(--ob-line-strong); text-underline-offset: 3px;
}
.ob-body .cc-review { display: flex; align-items: center; gap: 8px; }

/* 孵化区卡片：左边竖排投票柱，右边提案内容；已支持时整条描边转绿 */
.ob-body .hatch-card {
  display: flex; gap: 14px; padding: 14px 16px; margin-bottom: 10px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  transition: border-color .15s;
}
.ob-body .hatch-card.voted { border-color: var(--ob-live-line); }
.ob-body .hc-vote { flex: none; }
.ob-body .vote-pill {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  width: 58px; padding: 8px 0;
  border: 1px solid var(--ob-line); border-radius: 10px; background: var(--ob-surface-1);
  color: var(--ob-text-3); cursor: pointer;
  transition: border-color .15s, background-color .15s, color .15s, transform .15s;
}
.ob-body .vote-pill:hover { border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .vote-pill:active { transform: scale(.96); }
.ob-body .vote-pill.on { border-color: var(--ob-live-line); background: var(--ob-live-bg); color: var(--ob-live); }
.ob-body .vote-num { font-family: var(--ob-mono); font-size: 17px; font-variant-numeric: tabular-nums; }
.ob-body .vote-ic { font-size: 10.5px; }
.ob-body .hc-main { flex: 1; min-width: 0; }
.ob-body .hc-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 15px; }
.ob-body .hc-desc { margin-top: 8px; font-size: 13.5px; line-height: 22px; color: var(--ob-text-2); }
.ob-body .hc-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; font-size: 12px; color: var(--ob-text-3); }

@media (max-width: 900px) {
  .ob-body .hatch-card { gap: 10px; padding: 12px; }
  .ob-body .vote-pill { width: 48px; }
}

/* ==========================================================================
   蛋库（/dan 列表 + /dan/:id 讨论区 + /dan/new 提交表单）
   这三页原来靠 egg.css，而那份样式走旧主题变量（--line/--card/--text/--muted/--yolk…），
   新外壳不加载 style.css 因而取不到值。这里把用到的类名整体桥接到新 token；
   模板只换外壳 include —— 讨论区的 AJAX 片段（#dan-agg / #dan-rev-form / #dan-posts）
   依赖固定 DOM 结构，重写模板风险太大。
   类名照抄原模板，不要改名，否则模板里的 class 会对不上。
   ========================================================================== */

/* ---------- 筛选条与面包屑 ---------- */
.ob-body .egg-filter {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 14px; margin-bottom: 12px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg); background: var(--ob-surface-1);
}
.ob-body .eg-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.ob-body .eg-tab {
  display: inline-flex; align-items: center; height: 30px; padding: 0 13px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  color: var(--ob-text-3); font-size: 13px;
}
.ob-body .eg-tab:hover { color: var(--ob-text); border-color: var(--ob-line-strong); }
.ob-body .eg-tab.active { background: var(--ob-text); border-color: var(--ob-text); color: var(--ob-surface-0); }
.ob-body .eg-tab .ob-num { font-style: normal; margin-left: 5px; font-size: 11.5px; opacity: .72; }
.ob-body .eg-tab.active .ob-num { opacity: .9; }
.ob-body .eg-right { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .eg-q {
  width: 200px; height: 34px; padding: 0 12px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius);
  color: var(--ob-text); font-size: 13.5px;
}
.ob-body .eg-q::placeholder { color: var(--ob-text-3); }
.ob-body .eg-q:focus { outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }
.ob-body .eg-sort {
  height: 34px; padding: 0 10px; background: var(--ob-surface-1);
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text); font-size: 13px;
}
.ob-body .crumb { margin-bottom: 10px; font-size: 12.5px; color: var(--ob-text-3); }
.ob-body .crumb a:hover { color: var(--ob-text-2); }

/* ---------- 收录卡片 ---------- */
.ob-body .egg-card {
  position: relative; padding: 16px 18px 12px; margin-bottom: 12px;
  border: 1px solid var(--ob-line); border-left: 2px solid var(--ob-line);
  border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  transition: border-color .15s;
}
.ob-body .egg-card:hover { border-color: var(--ob-line-strong); }
.ob-body .egg-card.is-stink { border-left-color: var(--ob-err); }
.ob-body .egg-card.is-pending { border-left-color: var(--ob-warn); }
/* 角标改成右上角的实心小芯片：原来那种斜着贴的缎带在等宽字体系里太跳 */
.ob-body .ec-ribbon {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  height: 20px; padding: 0 8px; border-radius: 5px; line-height: 20px;
  font-family: var(--ob-mono); font-size: 10px; font-weight: 500; letter-spacing: .06em; color: #fff;
}
.ob-body .ec-ribbon.hot { background: #f5a524; color: #241a05; }
.ob-body .ec-ribbon.stink { background: var(--ob-err); }

.ob-body .ec-head { display: flex; align-items: flex-start; gap: 12px; }
.ob-body .ec-avatar {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: 12px; color: #fff;
  font-size: 18px; font-weight: 600; user-select: none;
}
.ob-body .ec-id { flex: 1; min-width: 0; }
.ob-body .ec-name { font-size: 16.5px; line-height: 1.4; }
.ob-body .ec-sub { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 5px; font-size: 12px; color: var(--ob-text-3); }
.ob-body .ec-provider { color: var(--ob-text-2); }
.ob-body .ec-type {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-3);
  font-size: 11px; color: var(--ob-text-2);
}
.ob-body .ec-type.type-official { border-color: var(--ob-live-line); background: var(--ob-live-bg); color: var(--ob-live); }
.ob-body .ec-type.type-relay { border-color: var(--ob-info-line); background: var(--ob-info-bg); color: var(--ob-info); }
.ob-body .ec-type.type-free { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .ec-kinds { display: inline-flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.ob-body .kind-badge {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px;
  border: 1px solid var(--ob-line-strong); border-radius: 5px;
  font-family: var(--ob-mono); font-size: 10.5px; letter-spacing: .03em; color: var(--ob-text-2);
}
.ob-body .ec-claim { flex: none; }
.ob-body .ec-own { font-size: 12px; }
.ob-body .btn-caution { background: var(--ob-warn); border-color: var(--ob-warn); color: #241a05; }
.ob-body .btn-caution:hover { background: #c9a97c; border-color: #c9a97c; color: #241a05; }

.ob-body .ec-stink-banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 12px; padding: 9px 12px; border-radius: var(--ob-radius);
  border: 1px solid var(--ob-err-line); background: var(--ob-err-bg);
  font-size: 12.5px; line-height: 19px; color: #ffdad6;
}
.ob-body .ec-stink-banner strong { color: var(--ob-err); }
.ob-body .ec-desc { margin-top: 11px; font-size: 13.5px; line-height: 22px; color: var(--ob-text-2); }
.ob-body .ec-desc > *:first-child { margin-top: 0; }
.ob-body .ec-desc > *:last-child { margin-bottom: 0; }
.ob-body .ec-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
/* 列表里的内联代码在卡片正文里也要压住对比度 */
.ob-body .ec-desc code, .ob-body .rev-text code, .ob-body .cc-body code {
  font-family: var(--ob-mono); font-size: 12.5px; padding: 1px 5px; border-radius: 5px;
  background: var(--ob-surface-3); border: 1px solid var(--ob-line); color: var(--ob-text);
}

/* 四格元信息：与首页/个人页的信息网格同一套做法（1px 分线由底色透出） */
.ob-body .ec-meta {
  /* 三列：价格 / 档位 · 计费方式 · 新用户权益（领取难度与稳定度已下线，别回到四列） */
  display: grid; grid-template-columns: 1.3fr 1fr 1.2fr; gap: 1px; margin-top: 12px;
  background: var(--ob-line); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); overflow: hidden;
}
.ob-body .ec-m { display: flex; flex-direction: column; gap: 2px; padding: 8px 12px; background: var(--ob-surface-2); }
.ob-body .ec-m label { font-family: var(--ob-mono); font-size: 10.5px; letter-spacing: .03em; color: var(--ob-text-3); }
.ob-body .ec-m b { font-size: 13.5px; font-weight: 500; }
.ob-body .ec-m b.free { color: var(--ob-live); }
.ob-body .ec-m s { font-size: 12px; font-weight: 400; color: var(--ob-text-3); }
.ob-body .ec-stars { font-size: 12.5px; letter-spacing: 1px; color: #f5a524; }
.ob-body .ec-stars i { font-style: normal; }
.ob-body .ec-stars i.off { color: var(--ob-text-3); opacity: .5; }
.ob-body .ec-stars.none { color: var(--ob-text-3); letter-spacing: 0; font-size: 12px; }

/* 模型类型 / 厂商 / 支持模型：键值两列 */
.ob-body .ec-models { display: flex; flex-direction: column; gap: 7px; margin-top: 12px; }
.ob-body .ec-models-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ob-body .ec-models-row label { flex: none; font-family: var(--ob-mono); font-size: 10.5px; letter-spacing: .03em; color: var(--ob-text-3); }
.ob-body .ec-models-val { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ob-body .chip {
  display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 10px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  font-size: 12.5px; color: var(--ob-text);
}
/* 胶囊里有删除叉时，右侧少留一点，叉本身再往外挪半格，视觉上才对称 */
.ob-body .chip .chip-x { margin-right: -5px; }
/* 已选胶囊上的删除叉：默认很淡，悬停才提示危险色 */
.ob-body .chip-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0; border: 0; border-radius: 9999px;
  background: transparent; color: var(--ob-text-3); font-size: 13px; line-height: 1; cursor: pointer;
}
.ob-body .chip-x:hover { background: var(--ob-err-bg); color: var(--ob-err); }

.ob-body .ec-review-row { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-top: 12px; font-size: 12.5px; }
.ob-body .dup-flag {
  display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 5px 10px; border: 1px solid var(--ob-warn-line); background: var(--ob-warn-bg);
  border-radius: var(--ob-radius-sm); font-size: 12px; color: var(--ob-warn);
}
.ob-body .dup-flag a { color: var(--ob-text); text-decoration: underline; text-underline-offset: 3px; }

/* 香臭比与投票：选中色沿用讨论室那套「香=绿 / 臭=红」 */
.ob-body .ec-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--ob-surface-1);
}
.ob-body .ec-ratio { display: flex; align-items: center; gap: 9px; flex: 1; min-width: 200px; }
/* 香臭条：绿 = 香的比例，剩下的一截是红（臭）。没有票时退回中性灰轨道。 */
.ob-body .ec-ratio-track {
  flex: 1; max-width: 180px; height: 8px; border-radius: 9999px; overflow: hidden;
  background: color-mix(in srgb, var(--ob-down) 30%, var(--ob-surface-3));
  border: 1px solid color-mix(in srgb, var(--ob-down) 26%, var(--ob-line));
}
.ob-body .ec-ratio-track:has(> i.none) { background: var(--ob-surface-3); border-color: var(--ob-line); }
.ob-body .ec-ratio-track i { display: block; height: 100%; border-radius: 9999px; background: var(--ob-up); }
.ob-body .ec-ratio-track i.good,
.ob-body .ec-ratio-track i.mid,
.ob-body .ec-ratio-track i.bad { background: var(--ob-up); }
.ob-body .ec-ratio-track i.none { background: transparent; }
.ob-body .ec-ratio-num { font-size: 12px; color: var(--ob-text-3); }
.ob-body .ec-ratio-num b { font-family: var(--ob-mono); font-size: 13px; color: var(--ob-text-2); }
.ob-body .ec-ratio-num b.good, .ob-body .ec-ratio-num b.mid { color: var(--ob-up); }
.ob-body .ec-ratio-num b.bad { color: var(--ob-down); }
.ob-body .ec-votes { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.ob-body .ec-vote-hint { font-size: 12px; }
/* 香=绿、臭=红：未选中就是淡淡的同色，选中填实 */
.ob-body .vote-pill-x {
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 11px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: transparent;
  color: var(--ob-text-3); font-size: 12.5px; cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s;
}
.ob-body .vote-pill-x b { font-family: var(--ob-mono); font-weight: 500; }
.ob-body .vote-pill-x.good { color: color-mix(in srgb, var(--ob-up) 72%, var(--ob-text-3)); border-color: color-mix(in srgb, var(--ob-up) 26%, var(--ob-line)); }
.ob-body .vote-pill-x.bad { color: color-mix(in srgb, var(--ob-down) 72%, var(--ob-text-3)); border-color: color-mix(in srgb, var(--ob-down) 26%, var(--ob-line)); }
.ob-body .vote-pill-x.good:hover { color: var(--ob-up); border-color: var(--ob-up-line); background: color-mix(in srgb, var(--ob-up) 8%, transparent); }
.ob-body .vote-pill-x.bad:hover { color: var(--ob-down); border-color: var(--ob-down-line); background: color-mix(in srgb, var(--ob-down) 8%, transparent); }
.ob-body .vote-pill-x.good.active { color: var(--ob-up); border-color: var(--ob-up-line); background: var(--ob-up-bg); }
.ob-body .vote-pill-x.bad.active { color: var(--ob-down); border-color: var(--ob-down-line); background: var(--ob-down-bg); }

.ob-body .ec-bottom {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-top: 10px; font-size: 12px; color: var(--ob-text-3);
}
.ob-body .ec-by { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ob-body .ec-bottom-right { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ob-body .ec-stink-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.ob-body .ec-stink-form input[type="text"] {
  flex: 1; min-width: 200px; min-height: 30px; padding: 4px 10px; font-size: 12.5px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm); color: var(--ob-text);
}

/* 综合分条：列表卡片底部的一行摘要，把「分数 + 五维 + 讨论入口」压在一起 */
.ob-body .ec-agg {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 11px; padding: 9px 12px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius); background: var(--ob-surface-1);
}
.ob-body .ec-ov { display: inline-flex; align-items: baseline; gap: 6px; font-size: 12px; color: var(--ob-text-3); }
.ob-body .ec-ov b { font-family: var(--ob-mono); font-size: 19px; font-weight: 500; color: var(--sc, var(--ob-live)); }
.ob-body .ec-eo { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 11.5px; color: var(--ob-text-3); }
/* 五维小字前各点一颗同色小圆点，数值也走同一维度色（与悬浮层、点评小片同一套色） */
.ob-body .ec-eo > span { display: inline-flex; align-items: center; gap: 5px; }
.ob-body .ec-eo > span:nth-child(1) { --dc: var(--dan-d1); }
.ob-body .ec-eo > span:nth-child(2) { --dc: var(--dan-d2); }
.ob-body .ec-eo > span:nth-child(3) { --dc: var(--dan-d3); }
.ob-body .ec-eo > span:nth-child(4) { --dc: var(--dan-d4); }
.ob-body .ec-eo > span:nth-child(5) { --dc: var(--dan-d5); }
.ob-body .ec-eo > span::before {
  content: ''; width: 6px; height: 6px; border-radius: 9999px; background: var(--dc, var(--ob-line-strong)); flex: none;
}
.ob-body .ec-eo > span.muted::before { display: none; }
.ob-body .ec-eo b { font-family: var(--ob-mono); font-weight: 700; color: var(--dc, var(--ob-text-2)); }
.ob-body .ec-discuss { margin-left: auto; white-space: nowrap; }

/* ---------- 讨论区：聚合分面板 ----------
   样式在文件后段「聚合分块」一节定义（本块为旧版结构，已随 #dan-agg 合并进渠道头移除） */
.ob-body .rv-empty { margin-bottom: 14px; }

/* ---------- 讨论区：我的打分表单 ----------
   五维沿用斗鸡台那套「每维一张小卡 + 彩色图标 + 滑块 + 两端刻度」，尺度仍是 1 - 5 星；
   卡片本体（.ar-dim / .ar-dim-head / .ar-sl）与斗鸡台共用同一份样式，这里只补栅格与色板。
   蛋库五维色板：广场卡 / 点评小片 / 均分弹层 / 打分卡共用一份（与斗鸡台八维同一批亮色）。 */
.ob-body {
  --dan-d1: #34d399; --dan-d2: #38bdf8; --dan-d3: #f5a524; --dan-d4: #2dd4bf; --dan-d5: #a78bfa;
}
.ob-body .rv-h { margin-bottom: 10px; font-size: 15px; }
.ob-body .rev-form { display: flex; flex-direction: column; gap: 12px; }
.ob-body .rev-form textarea {
  width: 100%; min-height: 76px; padding: 8px 11px; font-size: 13.5px; line-height: 22px; resize: vertical;
  background: var(--ob-surface-2); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
}
.ob-body .rev-form textarea:focus { outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }
.ob-body .rev-form-dims { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
.ob-body .rev-form-dims .ar-dim:nth-child(1) { --dim: var(--dan-d1); }
.ob-body .rev-form-dims .ar-dim:nth-child(2) { --dim: var(--dan-d2); }
.ob-body .rev-form-dims .ar-dim:nth-child(3) { --dim: var(--dan-d3); }
.ob-body .rev-form-dims .ar-dim:nth-child(4) { --dim: var(--dan-d4); }
.ob-body .rev-form-dims .ar-dim:nth-child(5) { --dim: var(--dan-d5); }
.ob-body .rev-ov { display: inline-flex; align-items: baseline; gap: 6px; margin: 8px 0 2px; font-size: 14px; color: var(--ob-text-3); }
.ob-body .rev-ov b { font-family: var(--ob-mono); font-size: 17px; font-weight: 500; color: var(--ob-live); }
/* 每条点评的五维：灰底小片（与斗鸡台八维格同一套语言），数值按维度色加粗 */
.ob-body .rev-dims { display: flex; gap: 6px; flex-wrap: wrap; font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .rev-dims > span {
  display: inline-flex; align-items: baseline; gap: 5px; padding: 2px 8px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm); background: var(--ob-surface-1);
}
.ob-body .rev-dims > span:nth-child(1) { --dc: var(--dan-d1); }
.ob-body .rev-dims > span:nth-child(2) { --dc: var(--dan-d2); }
.ob-body .rev-dims > span:nth-child(3) { --dc: var(--dan-d3); }
.ob-body .rev-dims > span:nth-child(4) { --dc: var(--dan-d4); }
.ob-body .rev-dims > span:nth-child(5) { --dc: var(--dan-d5); }
.ob-body .rev-dims b { font-family: var(--ob-mono); font-weight: 700; color: var(--dc, var(--ob-text-2)); }
.ob-body .rev-noscore { margin: 4px 0 0; font-size: 12.5px; }
.ob-body .rev-text { margin: 8px 0 4px; font-size: 14px; line-height: 23px; color: var(--ob-text-2); }

/* ---------- 讨论区：点评帖与两级楼中楼 ---------- */
/* 点评流：一人一帖平铺，用分隔线断开（与斗鸡台「大家的评分」同一套），不再一人一张灰底卡 */
.ob-body .rev-post {
  padding: 14px 2px; margin-bottom: 0;
  border: 0; border-bottom: 1px solid color-mix(in srgb, var(--ob-line) 75%, transparent);
  border-radius: 0; background: none; box-shadow: none;
}
.ob-body #dan-posts .rev-post:first-child { padding-top: 4px; }
.ob-body #dan-posts .rev-post:last-child { border-bottom: 0; padding-bottom: 2px; }
/* 亮色主题里 [data-theme=light] .topic-card 会把卡片刷成实白底（特异性 0,3,0，压过上面那条），
   这里靠 #dan-posts 提一级，保证平铺行在亮暗两套主题下都是透明底，不会变成一条条白带 */
.ob-body #dan-posts .rev-post { background: none; }
.ob-body .rv-head { display: flex; align-items: center; gap: 10px; }
.ob-body .rv-id { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.ob-body .rv-author { font-size: 14px; font-weight: 600; color: var(--ob-text); }
.ob-body .rv-time { font-size: 12px; }
.ob-body .dr-mine {
  margin-left: 4px; padding: 0 7px; border: 1px solid var(--ob-line); border-radius: 9999px;
  font-size: 11px; color: var(--ob-text-3); white-space: nowrap;
}
.ob-body .cc-tree { margin-top: 8px; }
.ob-body .cc-tree > li { margin-bottom: 8px; }
.ob-body .cc-kids { margin: 6px 0 0 22px; padding-left: 12px; border-left: 2px solid var(--ob-surface-1); }
.ob-body .cc-kids .cc-node { margin: 6px 0; }
.ob-body .cc-node { padding: 8px 0; border-bottom: 1px solid var(--ob-surface-1); }
.ob-body .cc-node:last-child { border-bottom: 0; }
.ob-body .cc-line { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 12.5px; color: var(--ob-text-3); }
.ob-body .cc-line strong { color: var(--ob-text); }
.ob-body .cc-rt { font-size: 12px; color: var(--ob-text-2); }
.ob-body .cc-body { margin: 3px 0; font-size: 13.5px; line-height: 22px; color: var(--ob-text-2); }
.ob-body .cc-ops { display: flex; align-items: center; gap: 8px; }
.ob-body .cc-ops form { display: inline-flex; }
.ob-body .cc-reply { cursor: pointer; }
.ob-body .cc-count { font-family: var(--ob-mono); }
.ob-body .cc-form { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.ob-body .cc-form textarea {
  width: 100%; min-height: 34px; padding: 7px 10px; font-size: 13px; line-height: 20px; resize: vertical;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
}
.ob-body .cc-form textarea:focus { outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }

/* ---------- 提交收录表单（/dan/new）----------
   chip / seg 选择器是「隐藏 radio + span 外观、靠 label 联动」的老做法（无 JS 也能用），
   这里把 input 彻底移出可交互层，样式全落在相邻的 span 上。 */
.ob-body .egg-form { display: flex; flex-direction: column; gap: 16px; }
.ob-body .egg-fs { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 0; border: 0; }
.ob-body .egg-fs > legend {
  margin-bottom: 2px; font-family: var(--ob-mono); font-size: 11px;
  letter-spacing: .04em; text-transform: uppercase; color: var(--ob-text-3);
}
.ob-body .fs-hint { font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .req { color: var(--ob-down); }
.ob-body .egg-form input[type="text"], .ob-body .egg-form input[type="url"],
.ob-body .egg-form input[type="number"], .ob-body .egg-form textarea, .ob-body .egg-form select {
  width: 100%; min-height: 36px; padding: 7px 12px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
}
.ob-body .egg-form textarea { line-height: 22px; resize: vertical; }
.ob-body .egg-form input:focus, .ob-body .egg-form textarea:focus, .ob-body .egg-form select:focus {
  outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong);
}
.ob-body .form-row-grid.three { grid-template-columns: repeat(3, 1fr); }
.ob-body .seg-group, .ob-body .chip-list { display: flex; flex-wrap: wrap; gap: 8px; }
.ob-body .seg-item, .ob-body .chip-item { position: relative; display: inline-flex; cursor: pointer; }
.ob-body .seg-item > input, .ob-body .chip-item > input { position: absolute; opacity: 0; pointer-events: none; }
.ob-body .seg-item > span, .ob-body .chip-item > span {
  display: inline-flex; align-items: center; height: 32px; padding: 0 13px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  font-size: 13px; color: var(--ob-text-2); transition: all .15s;
}
.ob-body .seg-item > span:hover, .ob-body .chip-item > span:hover { border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .seg-item > input:checked + span, .ob-body .chip-item > input:checked + span {
  background: var(--ob-text); border-color: var(--ob-text); color: var(--ob-surface-0);
}
.ob-body .seg-item > input:focus-visible + span, .ob-body .chip-item > input:focus-visible + span {
  outline: 2px solid var(--ob-line-strong); outline-offset: 1px;
}
/* 多选胶囊输入（厂商 / 支持模型）：候选是输入框下方**常驻**的一行虚线胶囊，
   点一下就加；不是下拉浮层。早前按下拉做成了绝对定位，结果它盖住下面的提示文字。 */
.ob-body .chip-picker { display: flex; flex-wrap: wrap; gap: 8px; }
.ob-body .chip-field { display: flex; flex-direction: column; gap: 8px; }
.ob-body .chip-list { display: flex; flex-wrap: wrap; gap: 6px; }
.ob-body .chip-input {
  width: 100%; box-sizing: border-box; min-height: 34px; padding: 6px 11px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
}
.ob-body .chip-field.chip-full .chip-input { border-color: var(--ob-err-line); }
.ob-body .chip-sug { display: flex; flex-wrap: wrap; gap: 6px; max-height: 84px; overflow-y: auto; }
/* 按厂商分组的候选：一行一个厂商，厂商名在左、模型 chips 在行内自动换行。
   flex-wrap 必须显式写 nowrap——父类 .chip-sug 是 wrap，纵向排列时「换行」会变成
   「另起一列」，于是整块横向溢出并冒出横向滚动条（用户报过）。 */
.ob-body .chip-sug-grouped {
  flex-direction: column; flex-wrap: nowrap; align-items: stretch;
  gap: 6px; max-height: 208px; overflow-y: auto; padding-right: 4px;
}
.ob-body .chip-grp { display: flex; gap: 8px; align-items: baseline; }
.ob-body .chip-grp-name { flex: none; width: 76px; text-align: right; font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .chip-grp-items { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
.ob-body .chip-opt {
  display: inline-flex; align-items: center; height: 24px; padding: 0 10px;
  border: 1px dashed var(--ob-line); border-radius: 9999px; background: transparent;
  color: var(--ob-text-3); font-size: 12px; cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s;
}
.ob-body .chip-opt:hover { color: var(--ob-text); border-style: solid; border-color: var(--ob-line-strong); }
.ob-body .chip-opt.on {
  border-style: solid; border-color: var(--ob-text); background: var(--ob-text); color: var(--ob-surface-0);
}
.ob-body .chip-narrow-hint { font-size: 11.5px; color: var(--ob-text-3); }

/* ---------- 蛋库「提交收录 / 编辑条目」表单 ----------
   分区卡片 + 底部常驻操作条：表单较长，滚到底才知道能不能提交体验很差。 */
.ob-body .egg-form > .egg-fs {
  padding: 16px 18px; margin: 0 0 14px;
  border: 1px solid var(--ob-line); border-left: 2px solid var(--ob-line-strong);
  border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
.ob-body .egg-form > .egg-fs > legend {
  padding: 0 8px; margin-left: -2px;
  font-family: var(--ob-mono); font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ob-text-2);
}
.ob-body .egg-form .form-row > label { font-size: 12.5px; color: var(--ob-text-2); }
.ob-body .egg-form-actions {
  position: sticky; bottom: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  padding: 12px 16px; margin-top: 4px;
  border: 1px solid var(--ob-line-strong); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 92%, transparent);
  backdrop-filter: blur(12px);
  box-shadow: 0 -8px 24px -18px rgba(0, 0, 0, .6);
}
.ob-body .egg-form-actions .muted { font-size: 12px; }
.ob-body .egg-form-actions-btns { display: inline-flex; align-items: center; gap: 8px; }

/* ---------- 蛋库页签的列表头：做成一条玻璃工具条 ----------
   原来「已收录 / 排序 / 提交收录」三者挤在标题右侧各自换行，看着像没对齐。 */
.ob-body .ob-feedhead.ob-feedhead-dan {
  padding: 12px 14px; margin-bottom: 2px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 80%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
.ob-body .ob-feedhead-ops { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ob-body .ob-feedhead-ops .ob-label { display: inline-flex; align-items: center; gap: 5px; }
.ob-body .ob-feedhead-ops .ob-sortwrap { padding-left: 12px; border-left: 1px solid var(--ob-line); }

@media (max-width: 900px) {
  .ob-body .ob-feedhead-dan { flex-direction: column; align-items: stretch; }
  .ob-body .ob-feedhead-ops { justify-content: space-between; }
  .ob-body .ob-feedhead-ops .ob-sortwrap { padding-left: 0; border-left: 0; }
  .ob-body .chip-grp-name { width: 100%; text-align: left; }
  .ob-body .chip-grp { flex-direction: column; gap: 4px; }
  .ob-body .egg-form > .egg-fs { padding: 14px; }
}

/* ---------- 响应式 ---------- */
@media (max-width: 900px) {
  .ob-body .ec-meta { grid-template-columns: 1fr 1fr; }
  .ob-body .ec-meta .ec-m:last-child { grid-column: 1 / -1; }
  .ob-body .ec-head { flex-wrap: wrap; }
  .ob-body .ec-claim { width: 100%; }
  .ob-body .ec-claim .btn { width: 100%; }
  .ob-body .form-row-grid.three { grid-template-columns: 1fr; }
  .ob-body .eg-right { width: 100%; margin-left: 0; }
  .ob-body .eg-q { flex: 1; width: auto; }
  .ob-body .ec-discuss { margin-left: 0; }
}
/* ---------- 彩蛋筐（/egg、/egg/new）----------
   这两页原来靠 egg.css（同样走旧主题变量），新外壳下取不到值，所以模板去掉引用、
   类名由这里接管。奖励卡的状态色沿用全站语义：可领=鲜绿、快没了=粘土、定时=蓝、抢完=灰。 */
.ob-body .reward-card {
  position: relative; padding: 16px 18px; margin-bottom: 12px;
  border: 1px solid var(--ob-line); border-left: 2px solid var(--ob-line);
  border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 85%, transparent);
  transition: border-color .15s;
}
.ob-body .reward-card:hover { border-color: var(--ob-line-strong); }
.ob-body .reward-card.state-ok { border-left-color: var(--ob-live); }
.ob-body .reward-card.state-low { border-left-color: var(--ob-warn); }
.ob-body .reward-card.state-upcoming { border-left-color: var(--ob-info); }
.ob-body .reward-card.state-sold { border-left-color: var(--ob-line-strong); opacity: .78; }

.ob-body .rc-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ob-body .rc-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 16.5px; line-height: 1.4; }
.ob-body .rc-desc { margin-top: 11px; font-size: 13.5px; line-height: 22px; color: var(--ob-text-2); }
.ob-body .rc-desc > *:first-child { margin-top: 0; }
.ob-body .rc-desc > *:last-child { margin-bottom: 0; }
.ob-body .ec-wait { cursor: default; }
.ob-body .ec-countdown { font-family: var(--ob-mono); font-variant-numeric: tabular-nums; }

/* 兑换内容：可领后是一块等宽字体的「密文」区，未领时只是一行灰字提示。
   这块是全站唯一的机密字段（仅分享者/管理员/已领取者可见），视觉上给足区分度。 */
.ob-body .rc-secret {
  display: flex; flex-direction: column; gap: 6px; margin-top: 12px;
  padding: 11px 13px; border-radius: var(--ob-radius);
  border: 1px solid var(--ob-live-line); background: var(--ob-live-bg);
}
.ob-body .rc-secret-label { font-family: var(--ob-mono); font-size: 10.5px; letter-spacing: .04em; color: var(--ob-live); }
.ob-body .rc-secret-body {
  margin: 0; font-family: var(--ob-mono); font-size: 13px; line-height: 20px;
  color: var(--ob-text); white-space: pre-wrap; word-break: break-all;
}
.ob-body .rc-secret-locked { border-color: var(--ob-line); background: var(--ob-surface-1); }
.ob-body .rc-secret-locked .rc-secret-label { color: var(--ob-text-3); }
.ob-body .rc-secret-hint { font-size: 12px; }

.ob-body .rc-progress { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.ob-body .rc-bar { flex: 1; max-width: 320px; height: 8px; border-radius: 9999px; overflow: hidden; background: var(--ob-surface-3); border: 1px solid var(--ob-line); }
.ob-body .rc-bar span { display: block; height: 100%; border-radius: 9999px; background: var(--ob-text-2); transition: width .3s; }
.ob-body .state-ok .rc-bar span { background: var(--ob-live); }
.ob-body .state-low .rc-bar span { background: var(--ob-warn); }
.ob-body .rc-nums { font-size: 12px; }

/* 社区存疑提醒条（卡片顶部）：红 = 失效标记过半（大概率失效），黄 = 臭标记达四成（需要仔细甄别）。
   阈值与最小样本在 lib/egg.js 的 markSummary 判定，这里只负责上色与排布。 */
.ob-body .rc-flag-slot:empty { display: none; }
.ob-body .rc-flag {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 0 0 12px; padding: 9px 12px;
  border: 1px solid var(--ob-err-line); border-radius: var(--ob-radius); background: var(--ob-err-bg);
}
.ob-body .rc-flag-title { font-size: 13px; font-weight: 600; color: var(--ob-err); }
.ob-body .rc-flag-text { font-size: 12.5px; line-height: 19px; color: var(--ob-text-2); }
.ob-body .rc-flag-text b { font-family: var(--ob-mono); font-weight: 600; color: var(--ob-err); }
.ob-body .rc-flag.is-stinky { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); }
.ob-body .rc-flag.is-stinky .rc-flag-title { color: var(--ob-warn); }
.ob-body .rc-flag.is-stinky .rc-flag-text b { color: var(--ob-warn); }

/* 实测标记区（卡片底部）：香 / 臭 / 失效的计数、比例条与标记按钮。
   颜色沿用全站口径——香=绿（--ob-up）、臭=红（--ob-down），失效用中性灰：
   它表达的是「兑不出来」，不该跟「臭」抢同一个红色。 */
.ob-body .rc-marks {
  margin-top: 12px; padding: 10px 12px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius); background: var(--ob-surface-1);
}
.ob-body .rc-marks-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
/* 存疑时标记区边框跟着提醒条同色，扫一眼就知道这张卡正被社区标记 */
.ob-body .rc-marks.is-flag-invalid { border-color: color-mix(in srgb, var(--ob-err) 30%, var(--ob-line)); }
.ob-body .rc-marks.is-flag-stinky { border-color: color-mix(in srgb, var(--ob-warn) 34%, var(--ob-line)); }
.ob-body .rc-marks-title { font-family: var(--ob-mono); font-size: 10.5px; letter-spacing: .04em; color: var(--ob-text-3); }
.ob-body .rc-marks-note { font-size: 11.5px; }
.ob-body .rc-mark-bar {
  display: flex; height: 8px; margin-top: 8px;
  border-radius: 9999px; overflow: hidden; background: var(--ob-surface-3); border: 1px solid var(--ob-line);
}
.ob-body .rc-mark-bar .seg { display: block; height: 100%; transition: width .3s; }
.ob-body .rc-mark-bar .is-sweet { background: var(--ob-up); }
.ob-body .rc-mark-bar .is-stinky { background: var(--ob-down); }
.ob-body .rc-mark-bar .is-invalid { background: var(--ob-text-3); }
.ob-body .rc-marks-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-top: 9px; }
.ob-body .rc-marks-vote { display: flex; align-items: center; gap: 6px; }
.ob-body .rc-marks-vote .inline-form { display: inline-flex; }
.ob-body .rc-marks-hint { font-size: 11.5px; }
.ob-body .vote-pill-x.dead { color: color-mix(in srgb, var(--ob-text-3) 90%, var(--ob-text)); border-color: color-mix(in srgb, var(--ob-text-3) 30%, var(--ob-line)); }
.ob-body .vote-pill-x.dead:hover { color: var(--ob-text-2); border-color: var(--ob-line-strong); background: color-mix(in srgb, var(--ob-text-3) 8%, transparent); }
.ob-body .vote-pill-x.dead.active { color: var(--ob-text); border-color: var(--ob-line-strong); background: var(--ob-surface-3); }
.ob-body .vote-pill-x:disabled { cursor: default; opacity: .6; }
.ob-body .vote-pill-x:disabled:hover { background: transparent; border-color: var(--ob-line); }
.ob-body .vote-pill-x.good:disabled:hover { color: color-mix(in srgb, var(--ob-up) 72%, var(--ob-text-3)); }
.ob-body .vote-pill-x.bad:disabled:hover { color: color-mix(in srgb, var(--ob-down) 72%, var(--ob-text-3)); }
.ob-body .vote-pill-x.dead:disabled:hover { color: color-mix(in srgb, var(--ob-text-3) 90%, var(--ob-text)); }

/* 右栏贡献者排行榜：名次沿用蛋库口碑榜那套 .ch-top（排名胶囊 + 名字 + 右侧数字） */
.ob-body .ch-top-score i { margin-left: 2px; font-style: normal; font-size: 10.5px; opacity: .65; }

.ob-body .rc-meta {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--ob-surface-1);
  font-size: 12px; color: var(--ob-text-3);
}
.ob-body .rc-meta .mini-link { font-size: 12px; }
.ob-body .rc-meta .inline-form { display: inline-flex; }

/* 彩蛋袋（右栏）：已领取的清单 */
.ob-body .bag-list { display: flex; flex-direction: column; gap: 8px; }
.ob-body .bag-list li { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 13px; }
.ob-body .bag-list a { color: var(--ob-text); }
.ob-body .bag-list a:hover { color: var(--ob-text-2); }
.ob-body .bag-list .muted { font-size: 11.5px; white-space: nowrap; }

/* 使用反馈区沿用蛋库点评那套折叠样式（rc-chat / rc-fb-* 已在前面桥接） */
.ob-body .rc-chat { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--ob-surface-1); }
.ob-body .rc-chat > summary { cursor: pointer; font-size: 13px; color: var(--ob-text-2); list-style: none; }
.ob-body .rc-chat > summary::-webkit-details-marker { display: none; }
.ob-body .rc-chat > summary:hover { color: var(--ob-text); }
.ob-body .rc-chat[open] > summary { color: var(--ob-text); margin-bottom: 10px; }
.ob-body .rc-feedbacks { display: flex; flex-direction: column; gap: 10px; }
.ob-body .rc-feedbacks li { display: flex; gap: 8px; }
.ob-body .rc-fb-body { display: flex; flex-direction: column; gap: 2px; }
.ob-body .rc-fb-line { font-size: 12.5px; color: var(--ob-text-3); }
.ob-body .rc-fb-line strong { color: var(--ob-text); }
.ob-body .rc-fb-text { font-size: 13.5px; line-height: 22px; color: var(--ob-text-2); }
.ob-body .rc-fb-form { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.ob-body .rc-fb-form textarea {
  width: 100%; min-height: 60px; padding: 8px 11px; font-size: 13.5px; line-height: 22px; resize: vertical;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
}
.ob-body .rc-fb-form textarea:focus { outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }
.ob-body .rc-feedback-empty { font-size: 12.5px; margin-top: 10px; }

@media (max-width: 900px) {
  .ob-body .rc-head { flex-direction: column; }
  .ob-body .ec-claim { width: 100%; }
  .ob-body .ec-claim .btn { width: 100%; }
  .ob-body .rc-bar { max-width: none; }
}
/* ---------- 模型库（/arena、/arena/:id、/rank）----------
   这三页原来靠 arena.css，而那份样式走旧主题变量（--card/--text/--line/--muted/--link…），
   新外壳不加载 style.css 因而取不到值。这里把用到的类名整体桥接到新 token；
   榜单那批（ar-card / ar-row / ar-bars / rk-* …）已在前面桥接过，这里是模型库页面额外的部分。
   八维打分界面按亮色设计稿 ai_ranking_pc_light：社区评分表 + 每维一张小卡的打分卡，
   不画雷达图（radar 相关规则已随雷达一起删除）。
   ========================================================================== */
.ob-body .ar-flash { padding: 11px 14px; margin-bottom: 12px; font-size: 13px; }
.ob-body .ar-flash-ok { border-color: var(--ob-live-line); background: var(--ob-live-bg); color: var(--ob-text-2); }
.ob-body .ar-flash-err { border-color: var(--ob-err-line); background: var(--ob-err-bg); color: #ffdad6; }

/* 社区评分表：表头信息条 + 宽表 */
.ob-body .ar-scorehead {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  padding: 12px 14px; margin-bottom: 12px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 72%, transparent);
  backdrop-filter: blur(10px);
}
.ob-body .ar-scorehead-main { display: flex; align-items: center; gap: 11px; min-width: 0; }
.ob-body .ar-scorehead-ic {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--ob-radius); color: var(--ob-info);
  background: var(--ob-info-bg); border: 1px solid var(--ob-info-line);
}
.ob-body .ar-scorehead-title { font-size: 14px; font-weight: 600; color: var(--ob-text); }
.ob-body .ar-scorehead-sub { margin-top: 2px; font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ar-scorehead-side { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ar-scorehead-num {
  padding: 2px 8px; border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: var(--ob-surface-3); color: var(--ob-text);
  font-family: var(--ob-mono); font-size: 12px; font-weight: 500;
}
.ob-body .ar-tablewrap {
  overflow-x: auto; border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  /* 纯色底（亮色=纯白、暗色=卡片色）：设计稿的表容器是 surface-container-lowest，
     灰底只留给八维小片，整表上灰会把「数据格」和「底色」混在一起。 */
  background: var(--ob-surface-2);
}
.ob-body .ar-table { width: 100%; min-width: 1080px; border-collapse: collapse; font-size: 13px; }
.ob-body .ar-table th {
  padding: 10px 9px; text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--ob-line); background: var(--ob-surface-2);
  font-family: var(--ob-mono); font-size: 11px; font-weight: 400; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ob-text-3);
}
.ob-body .ar-table td { padding: 12px 9px; border-bottom: 1px solid color-mix(in srgb, var(--ob-line) 60%, transparent); vertical-align: middle; }
.ob-body .ar-table tr:last-child td { border-bottom: 0; }
.ob-body .ar-table tbody tr { transition: background-color .16s ease; }
/* 行悬停：用文字色的低透明叠加，亮/暗两种主题下都稳定可见（原来亮色下几乎看不出变化） */
.ob-body .ar-table tbody tr:hover { background: color-mix(in srgb, var(--ob-text) 6%, transparent); }
.ob-body .ar-thname { min-width: 220px; }
.ob-body .ar-thscore, .ob-body .ar-tdscore { text-align: center; }
.ob-body .ar-thsat, .ob-body .ar-tdsat { min-width: 128px; }
.ob-body .ar-thdim, .ob-body .ar-tddim { text-align: center; padding-left: 7px; padding-right: 7px; white-space: nowrap; }
.ob-body .ar-thact, .ob-body .ar-tdact { text-align: right; white-space: nowrap; }
.ob-body .ar-namecell { display: flex; align-items: center; gap: 11px; min-width: 0; }
.ob-body .ar-rankchip {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  min-width: 30px; height: 24px; padding: 0 6px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: var(--ob-surface-3); color: var(--ob-text-2);
  font-family: var(--ob-mono); font-size: 11.5px; font-weight: 500;
}
.ob-body .ar-rankchip.is-gold { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .ar-rankchip.is-silver { border-color: var(--ob-line-strong); background: var(--ob-surface-2); color: var(--ob-text); }
.ob-body .ar-rankchip.is-bronze { border-color: var(--ob-line-strong); background: var(--ob-surface-1); color: var(--ob-text-2); }
.ob-body .ar-modelcol { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ob-body .ar-modelhead { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.ob-body .ar-mdot { flex: none; width: 8px; height: 8px; border-radius: 9999px; }
.ob-body .ar-modelname { font-size: 14px; font-weight: 500; color: var(--ob-text); }
/* 悬停（含行悬停，设计稿是 group-hover）把模型名染成主题色；暗色主题没有 accent 变量，回退品牌橙 */
.ob-body .ar-modelname:hover,
.ob-body .ar-table tbody tr:hover .ar-modelname { color: var(--ob-accent, #ff9e1b); }
.ob-body .ar-modeldesc { max-width: 250px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ar-badge {
  flex: none; padding: 1px 6px; border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: var(--ob-surface-3); font-size: 10.5px; color: var(--ob-text-2);
}
.ob-body .ar-badge.is-info { border-color: var(--ob-info-line); background: var(--ob-info-bg); color: var(--ob-info); }
.ob-body .ar-badge.is-ok { border-color: var(--ob-ok-line); background: var(--ob-ok-bg); color: var(--ob-ok); }
.ob-body .ar-badge.is-warn { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
/* 社区综合分胶囊：完全对齐设计稿的 emerald 系（bg emerald-500/15、描边 emerald-400/40、
   文字 emerald-400 + 实心星）；原来的 --ob-up 深绿在白底上偏重，薄荷绿更亮更轻。 */
.ob-body .ar-scorepill {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px;
  border: 1px solid rgba(52, 211, 153, .4); border-radius: 9999px;
  background: rgba(16, 185, 129, .15); color: #34d399;
  font-family: var(--ob-mono); font-size: 14px; font-weight: 700;
}
.ob-body .ar-scorepill > svg { width: 15px; height: 15px; fill: currentColor; }
.ob-body .ar-sat { display: flex; flex-direction: column; gap: 4px; width: 112px; }
.ob-body .ar-sat-top { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; font-family: var(--ob-mono); font-size: 11px; }
.ob-body .ar-sat-top b { font-weight: 500; color: var(--ob-text); }
.ob-body .ar-sat-top span { color: var(--ob-text-3); }
/* 满意度进度条：设计稿是 h-1.5（6px）的实心条；我们这条带 1px 描边（亮色下轨道要看得见），
   所以整体做 8px，扣掉描边后的填充正好 6px，跟设计稿一样粗 */
.ob-body .ar-satbar { height: 8px; border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-3); overflow: hidden; }
/* 满意度进度条：与设计稿同色（emerald-400），比主题的深绿更亮，和上面的综合分胶囊成一套 */
.ob-body .ar-satbar i { display: block; height: 100%; border-radius: 9999px; background: #34d399; animation: ob-bar-grow .6s cubic-bezier(.2, .8, .3, 1) both; }
.ob-body .ar-dimcell {
  display: inline-flex; align-items: baseline; gap: 5px; padding: 3px 8px; white-space: nowrap;
  /* 八维分数格：设计稿给的是灰底小片（surface-container-high + highest 描边），整表明亮、格子沉下去 */
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm); background: var(--ob-surface-1);
  font-family: var(--ob-mono);
}
.ob-body .ar-dimcell b { font-size: 12.5px; font-weight: 500; color: var(--ob-text); }
.ob-body .ar-dimcell em { font-style: normal; font-size: 10px; color: var(--ob-text-3); }
/* 顶峰档（≥9.5，判定见 lib/arena.js 的 dimWord）：设计稿给这档换深色描边 + 数字加粗 */
.ob-body .ar-dimcell.is-top { border-color: var(--ob-text-2); }
.ob-body .ar-dimcell.is-top b { font-weight: 700; }
.ob-body .ar-dimcell::before { content: ''; width: 5px; height: 5px; border-radius: 9999px; background: var(--dim, var(--ob-text-3)); }
.ob-body .ar-people { display: inline-flex; align-items: center; gap: 5px; font-family: var(--ob-mono); font-size: 11.5px; color: var(--ob-text-2); }
.ob-body .ar-tip { font-size: 11.5px; line-height: 18px; }
.ob-body .ar-tip b { font-weight: 500; color: var(--ob-text-2); }

/* 榜单（/rank）里的六（八）列分数格：--v 是 0-10 分值，条宽按 --v*10% */
.ob-body .ar-cell.is-unrated .ar-cell-top em { color: var(--ob-text-3); }
.ob-body .ar-open { font-size: 12.5px; color: var(--ob-text-2); white-space: nowrap; }
.ob-body .ar-open:hover { color: var(--ob-text); }

/* 提名面板与待孵化队列 */
.ob-body .ar-nominate > summary, .ob-body .ar-admin > summary {
  cursor: pointer; font-size: 13.5px; font-weight: 500; color: var(--ob-text); list-style: none;
}
.ob-body .ar-nominate > summary::-webkit-details-marker, .ob-body .ar-admin > summary::-webkit-details-marker { display: none; }
.ob-body .ar-nominate > summary::after, .ob-body .ar-admin > summary::after { content: ' ▾'; color: var(--ob-text-3); }
.ob-body .ar-nominate[open] > summary::after, .ob-body .ar-admin[open] > summary::after { content: ' ▴'; }
.ob-body .ar-pend { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.ob-body .ar-pend-btns { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .ar-colors { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .ar-cdot { position: relative; display: inline-flex; cursor: pointer; }
.ob-body .ar-cdot input { position: absolute; opacity: 0; pointer-events: none; }
.ob-body .ar-cdot span {
  display: block; width: 22px; height: 22px; border-radius: 6px;
  border: 2px solid transparent; box-shadow: 0 0 0 1px var(--ob-line);
}
.ob-body .ar-cdot input:checked + span { border-color: var(--ob-surface-0); box-shadow: 0 0 0 2px var(--ob-text); }
.ob-body .ar-cdot input:focus-visible + span { outline: 2px solid var(--ob-line-strong); outline-offset: 2px; }

/* ---------- 模型详情：八维均分表 + 满意度侧卡、状态标签、多人评分列表 ---------- */
.ob-body .ar-dimgrid { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 14px; align-items: start; }
/* 八维均分表：**单元格不能设 display: flex**——那会让 <td> 脱离表格布局，
   中间的横条列塌缩到内容宽（实测 632px 的表里只剩 40px），看起来就是「条形都很短」。
   圆点改成 inline-block 排在文字前，列宽交给 table-layout: fixed 分配。 */
.ob-body .ar-dimtable { width: 100%; table-layout: fixed; border-collapse: collapse; }
.ob-body .ar-dimtable td { padding: 7px 4px; border-bottom: 1px solid color-mix(in srgb, var(--ob-line) 55%, transparent); }
.ob-body .ar-dimtable tr:last-child td { border-bottom: 0; }
.ob-body .ar-dimname { width: 150px; font-size: 12.5px; font-weight: 500; color: var(--dim, var(--ob-text-2)); white-space: nowrap; }
/* 图标与文字按盒子中线对齐（原来用 inline-block + vertical-align 微调，不同图标的视觉重心对不齐） */
.ob-body .ar-dimname-in { display: inline-flex; align-items: center; gap: 8px; }
.ob-body .ar-dimname .ar-dim-ic { display: inline-flex; flex: none; color: var(--dim, var(--ob-text-3)); }
.ob-body .ar-dimbar { padding-right: 12px !important; }
/* 均分条：和打分卡的滑块同款（8px、已填充走维度色、余量压深），只读展示 */
.ob-body .ar-dimtable .ar-track {
  height: 8px; border: 1px solid var(--ob-line); background: color-mix(in srgb, var(--ob-text) 72%, transparent);
}
.ob-body .ar-dimval { width: 96px; text-align: right; white-space: nowrap; }
.ob-body .ar-dimval b { font-family: var(--ob-mono); font-size: 13.5px; font-weight: 700; color: var(--dim, var(--ob-text)); }
.ob-body .ar-dimval em { margin-left: 6px; font-style: normal; font-size: 10.5px; color: var(--ob-text-3); }
.ob-body .ar-dimside { display: flex; flex-direction: column; gap: 9px; align-items: flex-start; }
.ob-body .ar-satbig { display: flex; align-items: baseline; gap: 8px; }
.ob-body .ar-satbig b { font-family: var(--ob-mono); font-size: 26px; font-weight: 600; color: var(--ob-up); }
.ob-body .ar-satbig span { font-size: 12px; color: var(--ob-text-3); }
.ob-body .ar-dimside .ar-satbar { width: 100%; }
.ob-body .ar-dimside-note { font-size: 11.5px; line-height: 18px; }
.ob-body .ar-dimside-meta { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--ob-text-3); }
.ob-body .ar-dimside-meta b { font-family: var(--ob-mono); color: var(--ob-text-2); font-weight: 500; }
.ob-body .ar-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  font-size: 11.5px; color: var(--ob-text-2);
}
.ob-body .ar-pending { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .ar-active { border-color: var(--ob-live-line); background: var(--ob-live-bg); color: var(--ob-live); }
.ob-body .ar-adminbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .ar-comment-form { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
/* 输入框走纯色底（与顶栏搜索一致），不要灰块 */
.ob-body .ar-comment-form textarea {
  width: 100%; min-height: 56px; padding: 8px 11px; font-size: 13.5px; line-height: 22px; resize: vertical;
  background: var(--ob-surface-2); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
}
.ob-body .ar-comment-form textarea:focus { outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }

.ob-body .ar-ratings-scroll { display: flex; flex-direction: column; gap: 10px; max-height: 460px; overflow-y: auto; padding-right: 4px; }
/* 大家的评分：一人一条平铺的评论，用分隔线断开，不再一人一块灰底卡（灰块整片看着发闷） */
.ob-body .arc-item { padding: 13px 2px; border: 0; border-bottom: 1px solid color-mix(in srgb, var(--ob-line) 75%, transparent); border-radius: 0; background: none; }
.ob-body .arc-item:first-child { padding-top: 4px; }
.ob-body .arc-item:last-child { border-bottom: 0; padding-bottom: 2px; }
.ob-body .arc-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 7px; }
.ob-body .arc-head strong { font-size: 13.5px; }
.ob-body .arc-score { margin-left: auto; font-family: var(--ob-mono); font-size: 14px; font-weight: 500; color: var(--ob-live); }
.ob-body .arc-time { font-size: 11.5px; }
.ob-body .arc-dims { font-size: 11.5px; line-height: 18px; }
.ob-body .arc-comment { margin-top: 8px; font-size: 13px; line-height: 21px; color: var(--ob-text-2); }
.ob-body .ar-ratings-more { margin-top: 10px; font-size: 12px; }

/* ---------- 八维打分：设计稿那套「每维一张小卡 + 滑块 + 两端语义」 ---------- */
.ob-body .ar-rate-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ob-body .ar-rate-sub { margin-top: 6px; font-size: 12px; line-height: 19px; }
.ob-body .ar-rate-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px; margin: 14px 0;
}
/* 打分卡：每维一张白卡（设计稿是 bg-surface-container-lowest + 浅描边），
   标题带该维度的彩色图标、数值同色加粗，一眼能对上雷达的哪根轴 */
.ob-body .ar-dim {
  display: flex; flex-direction: column; gap: 8px; padding: 12px 13px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg); background: var(--ob-surface-2);
}
.ob-body .ar-dim-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ob-body .ar-dim-name { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 500; color: var(--dim, var(--ob-text)); }
.ob-body .ar-dim-ic { display: inline-flex; flex: none; color: var(--dim, var(--ob-text-3)); }
.ob-body .ar-dim-val { font-family: var(--ob-mono); font-size: 15px; font-weight: 700; color: var(--dim, var(--ob-text)); }
.ob-body .ar-dim-ends { display: flex; align-items: center; justify-content: space-between; font-size: 10.5px; color: var(--ob-text-3); }
/* 滑块：已填充部分与滑块用该维度的强调色（--p 是已填充比例，模板首屏写入、拖动时脚本同步），
   未填充段用「文字色的高透明叠加」压深——与设计稿那条深灰轨道一致，亮暗两主题都稳定 */
.ob-body .ar-sl { width: 100%; height: 20px; margin: 0; background: none; appearance: none; cursor: pointer; }
.ob-body .ar-sl:disabled { cursor: not-allowed; opacity: .5; }
.ob-body .ar-sl::-webkit-slider-runnable-track {
  height: 8px; border-radius: 9999px; border: 1px solid var(--ob-line);
  background: linear-gradient(to right,
    var(--dim, var(--ob-text)) var(--p, 0%),
    color-mix(in srgb, var(--ob-text) 72%, transparent) var(--p, 0%));
}
.ob-body .ar-sl::-moz-range-track {
  height: 8px; border-radius: 9999px; border: 1px solid var(--ob-line);
  background: linear-gradient(to right,
    var(--dim, var(--ob-text)) var(--p, 0%),
    color-mix(in srgb, var(--ob-text) 72%, transparent) var(--p, 0%));
}
.ob-body .ar-sl::-webkit-slider-thumb {
  appearance: none; width: 17px; height: 17px; margin-top: -4.5px;
  border-radius: 9999px; background: var(--dim, var(--ob-text)); border: 2px solid var(--ob-surface-0);
  box-shadow: 0 0 0 1px var(--ob-line-strong);
}
.ob-body .ar-sl::-moz-range-thumb {
  width: 17px; height: 17px; border-radius: 9999px;
  background: var(--dim, var(--ob-text)); border: 2px solid var(--ob-surface-0);
}
/* 印象标签 */
.ob-body .ar-impress { display: flex; flex-direction: column; gap: 9px; margin-bottom: 14px; }
.ob-body .ar-impress-list { display: flex; flex-wrap: wrap; gap: 8px; }
.ob-body .ar-rating-card, .ob-body .ar-rate { margin-bottom: 14px; }

@media (max-width: 900px) {
  .ob-body .ar-dimgrid { grid-template-columns: minmax(0, 1fr); }
  .ob-body .ar-table { min-width: 980px; }
}
/* ---------- 悬停资料卡（public/js/usercard.js 生成的 DOM）----------
   旧卡片按旧 token 写死在 style.css 里，新外壳不加载那个文件，
   所以把它的类名在这边补一份，保证头像悬停还是能出卡片。 */
.ob-body .usercard {
  position: fixed; z-index: 95; width: 300px; padding: 14px;
  background: var(--ob-surface-3); border: 1px solid var(--ob-line-strong);
  border-radius: var(--ob-radius-lg); box-shadow: 0 8px 32px -4px rgba(0, 0, 0, .45);
  opacity: 0; transform: translateY(-4px); pointer-events: none; transition: opacity .14s, transform .14s;
}
.ob-body .usercard.show { opacity: 1; transform: none; pointer-events: auto; }
.ob-body .uc-loading { font-size: 12.5px; padding: 8px 0; }
.ob-body .uc-head { display: flex; gap: 11px; align-items: center; }
.ob-body .uc-id { min-width: 0; }
.ob-body .uc-name { font-size: 14.5px; font-weight: 600; color: var(--ob-text); }
.ob-body .uc-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 5px; }
.ob-body .uc-bio { margin: 10px 0 0; font-size: 12.5px; line-height: 19px; color: var(--ob-text-2); }
.ob-body .uc-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; margin: 12px 0 0; background: var(--ob-line); border-radius: var(--ob-radius-sm); overflow: hidden; }
.ob-body .uc-stats > span { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px 2px; background: var(--ob-surface-2); }
.ob-body .uc-stats strong { font-family: var(--ob-mono); font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 500; color: var(--ob-text); }
.ob-body .uc-stats em { font-style: normal; font-size: 10.5px; color: var(--ob-text-3); }
.ob-body .uc-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 11px; font-size: 11.5px; }

/* ---------- 搜索页 ---------- */
.ob-search { max-width: 900px; }
.ob-search-form {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px; margin-bottom: 16px;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  color: var(--ob-text-3);
}
.ob-search-form:focus-within { border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }
.ob-search-form input { flex: 1; min-height: 32px; background: none; border: 0; outline: none; color: var(--ob-text); font-size: 15px; }
.ob-search-form input::placeholder { color: var(--ob-text-3); }
.ob-search-count { display: block; margin-bottom: 10px; }
.ob-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ---------- 图片上传按钮（public/js/upload.js 注入）----------
   它会往每个 textarea 前面插一个 .upl-btn + 隐藏 file input（不改动模板）。
   新版外壳没有 style.css 里那套旧定位，所以在这里给它安排位置：
   编辑器里并进工具条右侧，讨论室输入台里右对齐成一个小按钮。 */
.ob-body .upl-btn {
  align-self: flex-end; height: 26px; padding: 0 9px; margin: 0;
  font-size: 12px; border-radius: var(--ob-radius-sm);
}
.ob-editor { position: relative; }
.ob-editor .upl-btn {
  position: absolute; top: 6px; right: 8px; z-index: 2;
  height: 28px; padding: 0 10px;
}
.ob-editor .ob-editor-bar { padding-right: 112px; }
.ob-composer .upl-btn { margin: 0 0 6px; }
/* 拖拽高亮：旧样式用的是 style.css 的 --primary，在新外壳里取不到，这里补一份 */
.ob-body .upl-drag { outline: 2px dashed var(--ob-ok); outline-offset: 2px; border-radius: var(--ob-radius); }

/* 标签 chip 上的移除按钮（发帖页标签选择器） */
.ob-chip-x { background: none; border: 0; padding: 0 0 0 2px; color: var(--ob-text-3); cursor: pointer; font-size: 13px; line-height: 1; }
.ob-chip-x:hover { color: var(--ob-err); }

/* ---------- 公告弹窗（views/partials/announce-modal.ejs）----------
   与旧 style.css 的 .ann-* 同一套结构，配色换成新版 token。 */
.ob-body .ann-overlay {
  position: fixed; inset: 0; z-index: 90; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: rgba(9, 10, 12, .66);
}
.ob-body .ann-box {
  width: min(560px, 94vw); max-height: 82vh; overflow-y: auto; padding: 22px;
  background: var(--ob-surface-2); border: 1px solid var(--ob-line-strong);
  border-radius: var(--ob-radius-xl); box-shadow: 0 8px 32px -4px rgba(0, 0, 0, .45);
}
.ob-body .ann-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.ob-body .ann-head h3 { margin: 0; font-size: 16px; min-width: 0; }
.ob-body .ann-tag {
  flex: none; padding: 2px 8px; border-radius: 9999px; font-family: var(--ob-mono);
  font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase;
  background: var(--ob-surface-3); border: 1px solid var(--ob-line-strong); color: var(--ob-text-2);
}
.ob-body .ann-body { font-size: 14px; line-height: 24px; color: var(--ob-text-2); }
.ob-body .ann-body > *:first-child { margin-top: 0; }
.ob-body .ann-body > *:last-child { margin-bottom: 0; }
.ob-body .ann-foot { display: flex; justify-content: flex-end; margin-top: 18px; }
.ob-body.ann-open { overflow: hidden; }

/* ==========================================================================
   玻璃质感 + 交互动效（第五批的视觉打磨）
   原则：可读性优先。玻璃只做「层次」不做「滤镜秀」——
   用半透明表面 + 描边 + 上沿内高光 + 轻微模糊，让人看出层次，但不影响文字对比度。
   动效只做「有机会被感知」的那几处：卡片悬停、按钮按下、雷达与进度条入场；
   并在 prefers-reduced-motion 下全部关闭。
   ========================================================================== */

/* ---------- 环境光：给玻璃一个能折射的背景 ----------
   纯平底色下 backdrop-filter 是看不见的（后面没有东西可糊），
   所以画布上铺两层极低透明的光晕，玻璃表面才有层次。亮色主题由覆盖层自行决定是否保留。 */
.ob-body {
  background-image:
    radial-gradient(60rem 40rem at 8% -6%, rgba(136, 153, 141, .07), transparent 62%),
    radial-gradient(52rem 36rem at 108% 4%, rgba(184, 155, 114, .06), transparent 60%);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

/* ---------- 整站背景图（后台「默认封面」那张）----------
   有设置时，图片铺满视口、固定不随滚动，上面压一层 --ob-page-scrim 遮罩；
   画布交给 html，body 自己的底色让开，于是卡片之间的空隙能透出这张图。
   卡片是不透明表面、正文色也不变，所以照片只影响氛围，不参与文字对比度。
   没有设置时 html 上不带 .has-page-bg，以下规则完全不参与渲染。 */
html.has-page-bg {
  background-image: linear-gradient(var(--ob-page-scrim), var(--ob-page-scrim)), var(--ob-page-bg);
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
  background-repeat: no-repeat;
}
html.has-page-bg .ob-body { background: transparent; }
/* 顶栏别做成一整条实心板：留一点透明 + 模糊，背景图在顶栏下也透得出来 */
html.has-page-bg .ob-top {
  background: color-mix(in srgb, var(--ob-surface-0) 80%, transparent);
  backdrop-filter: blur(14px);
}

/* ---------- 卡片统一玻璃质感 ----------
   把桥接段里那些只有半透明表面的卡片（ar-card / egg-card / reward-card / title-card …）
   补上模糊与上沿内高光，与设计系统里 .ob-card 的做法对齐。
   内高光刻意压到 5%：亮色主题下等于看不见，暗色主题下只勾一道边。 */
.ob-body .ar-card,
.ob-body .egg-card,
.ob-body .reward-card,
.ob-body .title-card,
.ob-body .coop-card,
.ob-body .hatch-card,
.ob-body .checkin-card,
.ob-body .feedback-intro-card,
.ob-body .egg-intro-card,
.ob-body .ic-code-card,
.ob-body .topic-head-card,
.ob-body .ar-dim,
.ob-body .section-card,
.ob-body .side-card {
  backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
/* 卡片悬停：描边提亮 + 1px 抬升，用与 dock 同一根弹性曲线，不做投影 */
.ob-body .ar-card,
.ob-body .egg-card,
.ob-body .reward-card,
.ob-body .title-card,
.ob-body .coop-card,
.ob-body .hatch-card,
.ob-body .topic-head-card {
  transition: border-color .18s ease, transform .22s cubic-bezier(.34, 1.4, .64, 1), box-shadow .18s ease;
}
.ob-body .ar-card:hover,
.ob-body .egg-card:hover,
.ob-body .reward-card:hover,
.ob-body .title-card:hover,
.ob-body .coop-card:hover,
.ob-body .hatch-card:hover,
.ob-body .topic-head-card:hover {
  transform: translateY(-1px);
  /* 无投影：抬升感靠 1px 位移 + 描边提亮 + 上沿内高光（设计系统里没有投影这一层） */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07);
}

/* 按钮按下回弹（与 dock 的 active:scale 一套语汇） */
.ob-body .btn:active:not(:disabled),
.ob-body .mini-btn:active:not(:disabled),
.ob-body .ob-btn:active:not(:disabled),
.ob-body .vote-pill-x:active:not(:disabled) { transform: scale(.975); }

/* ---------- 雷达：加边框容器，做成一块玻璃面板 ----------
   原来雷达只是几条线悬在卡片里，没有边界；这里给容器描边 + 轻微内凹底色 + 中线光晕。
   模型库（/arena）的雷达已按新设计稿撤掉，剩下的 radar-wrap 是评审页（/review）在用。 */
.ob-body .radar-wrap {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 14px;
  border: 1px solid var(--ob-line);
  border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-1) 72%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05), inset 0 -18px 30px -24px rgba(0, 0, 0, .5);
  overflow: hidden;
}
/* 面板中央的柔光：用当前模型的主色（--mc 由模板给出），没有就退回中性色 */
.ob-body .radar-wrap::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--mc, var(--ob-text-3)) 12%, transparent), transparent 62%);
}
.ob-body .radar-wrap > svg { position: relative; z-index: 1; }
/* 雷达多边形入场：淡入 + 轻微放大，只播一次，不循环 */
.ob-body .radar-wrap svg polygon,
.ob-body .radar-wrap svg circle {
  transform-origin: 150px 156px;
  animation: ob-radar-in .55s cubic-bezier(.2, .8, .3, 1) both;
}
@keyframes ob-radar-in {
  from { opacity: 0; transform: scale(.86); }
  to { opacity: 1; transform: scale(1); }
}

/* ---------- 八维条形入场：从 0 长到目标值 ----------
   --v 是 0-10 的分值，宽度按 --v*10% 算；用动画而不是过渡，这样首屏也能看到一次生长。 */
.ob-body .ar-track i,
.ob-body .rc-bar span,
.ob-body .ec-ratio-track i,
.ob-body .lv-bar span,
.ob-body .ob-progress > i {
  animation: ob-bar-grow .6s cubic-bezier(.2, .8, .3, 1) both;
}
@keyframes ob-bar-grow {
  from { width: 0; }
}
/* 分段错开，视觉上像在逐个读数 */
.ob-body .ar-cell:nth-child(2) .ar-track i { animation-delay: .04s; }
.ob-body .ar-cell:nth-child(3) .ar-track i { animation-delay: .08s; }
.ob-body .ar-cell:nth-child(4) .ar-track i { animation-delay: .12s; }
.ob-body .ar-cell:nth-child(5) .ar-track i { animation-delay: .16s; }
.ob-body .ar-cell:nth-child(6) .ar-track i { animation-delay: .20s; }
.ob-body .ar-cell:nth-child(7) .ar-track i { animation-delay: .24s; }
.ob-body .ar-cell:nth-child(8) .ar-track i { animation-delay: .28s; }

/* ---------- 榜单行：悬停时给一点「被选中」的反馈 ---------- */
.ob-body .ar-row { transition: background-color .16s ease, padding-left .22s cubic-bezier(.34, 1.4, .64, 1); }
.ob-body .ar-row:hover { background: color-mix(in srgb, var(--ob-surface-1) 65%, transparent); padding-left: 6px; }

/* ---------- 八维打分卡：悬停提亮，滑块拇指加大热区 ---------- */
.ob-body .ar-dim { transition: border-color .16s ease, background-color .16s ease; }
.ob-body .ar-dim:hover { border-color: var(--ob-line-strong); background: color-mix(in srgb, var(--ob-surface-2) 60%, transparent); }
.ob-body .ar-sl::-webkit-slider-thumb { transition: transform .14s ease; }
.ob-body .ar-sl:hover::-webkit-slider-thumb { transform: scale(1.12); }
.ob-body .ar-sl:active::-webkit-slider-thumb { transform: scale(1.2); }

/* ---------- 印象标签：选中时轻微弹一下 ---------- */
.ob-body .ar-impress-list .chip-item > input:checked + span { animation: ob-pop .26s cubic-bezier(.34, 1.56, .64, 1); }
@keyframes ob-pop {
  0% { transform: scale(.92); }
  60% { transform: scale(1.04); }
  100% { transform: scale(1); }
}

/* ---------- 减少动态效果：全部退化为静态 ---------- */
@media (prefers-reduced-motion: reduce) {
  .ob-body { background-image: none; }
  .ob-body .ar-card:hover,
  .ob-body .egg-card:hover,
  .ob-body .reward-card:hover,
  .ob-body .title-card:hover,
  .ob-body .coop-card:hover,
  .ob-body .hatch-card:hover,
  .ob-body .topic-head-card:hover { transform: none; }
  .ob-body .btn:active:not(:disabled),
  .ob-body .mini-btn:active:not(:disabled),
  .ob-body .ob-btn:active:not(:disabled),
  .ob-body .vote-pill-x:active:not(:disabled) { transform: none; }
  .ob-body .radar-wrap svg polygon,
  .ob-body .radar-wrap svg circle,
  .ob-body .ar-track i,
  .ob-body .rc-bar span,
  .ob-body .ec-ratio-track i,
  .ob-body .lv-bar span,
  .ob-body .ob-progress > i,
  .ob-body .ar-impress-list .chip-item > input:checked + span { animation: none; }
  .ob-body .ar-row { transition: none; }
  .ob-body .ar-row:hover { padding-left: 0; }
}

/* ---------- 蛋库 · 渠道广场（/dan）与渠道点评页（/dan/:id）----------
   设计稿是 UI(2)/UI/渠道_pc 与 模型评论_pc：广场 = 标题 + 统计 + 筛选 + 卡片流 + 右栏（口碑榜/热评动态/类型甄别），
   点评页 = 渠道头（身份 + 大分数 + 五维小格 + 指标胶囊）+ 评价筛选 + 点评流 + 右栏（口碑榜/打分守则）。
   卡片与点评帖仍复用 ec-* / rev-* 那套类名（上面已桥接过），这里补的是设计稿新增的块：ch-* 与 rv-ops。 */

/* 广场头部统计 */
.ob-body .ch-hero { display: flex; flex-direction: column; gap: 14px; }
.ob-body .ch-stats { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.ob-body .ch-stat { display: flex; align-items: baseline; gap: 6px; }
.ob-body .ch-stat label { font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ch-stat b { font-family: var(--ob-mono); font-size: 20px; font-weight: 600; color: var(--ob-text); }
.ob-body .ch-stat b.is-score { display: inline-flex; align-items: center; gap: 4px; font-size: 18px; color: var(--ob-up); }
.ob-body .ch-stat span { font-size: 11.5px; }
.ob-body .eg-tab-label { font-size: 11.5px; color: var(--ob-text-3); margin-right: 2px; }

/* 卡片流：设计稿是一条竖排列表 */
.ob-body .ch-list { display: flex; flex-direction: column; gap: 12px; }

/* 卡片：评分与「打分」入口进头部（设计稿把星级放在厂商名右侧） */
.ob-body .ec-name a { color: inherit; }
.ob-body .ec-name a:hover { color: var(--ob-text-2); }
.ob-body .ec-score { display: flex; align-items: center; gap: 8px; flex: none; margin-left: auto; }
.ob-body .ec-stars-num {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--ob-mono); font-size: 15px; font-weight: 600; color: var(--sc, var(--ob-up));
  /* 一点点同色晕：让分数在卡片头部先跳出来（列表页卡片会有 tier-* 类给出 --sc） */
  text-shadow: 0 0 14px color-mix(in srgb, var(--sc, var(--ob-up)) 42%, transparent);
}
.ob-body .ec-score-n { font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ec-rate-btn {
  display: inline-flex; align-items: center; height: 26px; padding: 0 10px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: var(--ob-surface-2); color: var(--ob-text-2); font-size: 12px;
}
.ob-body .ec-rate-btn:hover { border-color: var(--ob-line-strong); color: var(--ob-text); }
/* 覆盖项：模型名一行排开，多了折行 */
.ob-body .ec-cover { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; padding: 2px 0 6px; }
.ob-body .ec-cover-h { flex: none; font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ec-cover-list { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* 右栏：口碑榜 / 热评动态 / 类型甄别 */
.ob-body .ch-rail .side-card { display: flex; flex-direction: column; gap: 10px; }
.ob-body .ch-rail .side-card h3 { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ob-body .ch-top { display: flex; flex-direction: column; gap: 2px; }
.ob-body .ch-top li { display: flex; align-items: center; gap: 8px; padding: 7px 0; border-bottom: 1px solid color-mix(in srgb, var(--ob-line) 55%, transparent); }
.ob-body .ch-top li:last-child { border-bottom: 0; }
.ob-body .ch-top-rank {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: var(--ob-radius-sm);
  border: 1px solid var(--ob-line); background: var(--ob-surface-2);
  font-family: var(--ob-mono); font-size: 11px; color: var(--ob-text-2);
}
.ob-body .ch-top-rank.r1 { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .ch-top-rank.r2 { border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .ch-top-rank.r3 { border-color: var(--ob-line-strong); color: var(--ob-text-2); }
.ob-body .ch-top-name { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ob-body .ch-top-name strong { font-weight: 500; font-size: 13px; color: var(--ob-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ob-body .ch-top-name .muted { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ob-body a.ch-top-name:hover { text-decoration: none; }
.ob-body a.ch-top-name:hover strong { color: var(--ob-text-2); }
.ob-body .ch-top-score { display: inline-flex; align-items: center; gap: 3px; font-family: var(--ob-mono); font-size: 12.5px; color: var(--sc, var(--ob-up)); }
.ob-body .ch-top li.is-cur .ch-top-name { font-weight: 600; }
/* 实测热评动态：作者行（加粗领读）+ 正文引用块，两层分开；正文两行截断 */
.ob-body .ch-recent { display: flex; flex-direction: column; gap: 12px; }
.ob-body .ch-recent li { display: flex; flex-direction: column; gap: 7px; padding-bottom: 11px; border-bottom: 1px solid color-mix(in srgb, var(--ob-line) 55%, transparent); }
.ob-body .ch-recent li:last-child { border-bottom: 0; padding-bottom: 0; }
/* 作者行锁死一行（不能 wrap）：标题一长就把「点赞 / 时间」挤到第二行，几张卡片高度参差不齐。
   收窄的活儿只交给标题（.ch-recent-item 是这里唯一可伸缩的项），其余一律 flex: none 保持原样。 */
.ob-body .ch-recent-head { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; min-width: 0; font-size: 11.5px; }
.ob-body .ch-recent-who { flex: none; color: var(--ob-text); font-size: 12.5px; font-weight: 600; }
.ob-body .ch-recent-who:hover { text-decoration: underline; text-underline-offset: 3px; }
.ob-body .ch-recent-act { flex: none; font-size: 11px; color: var(--ob-text-3); }
/* 标题单行 + 超出省略：截断交给 CSS（按可用宽度自适应），模板里不再切 12 个字，
   否则会出现「模板已加…、CSS 再切一刀」的双重截断，连书名号都留不下 */
.ob-body .ch-recent-item {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ob-text-2); font-size: 11.5px;
}
.ob-body .ch-recent-item:hover { color: var(--ob-text); text-decoration: underline; text-underline-offset: 3px; }
.ob-body .ch-recent-like { flex: none; display: inline-flex; align-items: center; gap: 3px; font-family: var(--ob-mono); font-size: 11.5px; color: var(--ob-up); }
.ob-body .ch-recent-time { flex: none; margin-left: auto; font-size: 11px; color: var(--ob-text-3); }
.ob-body .ch-recent-text {
  margin: 0; padding: 7px 9px;
  background: var(--ob-surface-1);
  border-left: 2px solid var(--ob-line-strong);
  border-radius: 0 var(--ob-radius-sm) var(--ob-radius-sm) 0;
  color: var(--ob-text-2); font-size: 11.5px; line-height: 17.5px;
}
/* 两行截断放在内层 span：和外层的 padding 同框时，line-clamp 会漏出第三行的半截字 */
.ob-body .ch-recent-text > span {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ob-body .ch-kinds li b { color: var(--ob-text-2); }
.ob-body .ch-rail-note { font-size: 11px; line-height: 17px; margin: 0; }

/* ---------- 渠道点评页：渠道头 ---------- */
.ob-body .ch-switch {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 12px; margin-bottom: 12px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-1) 80%, transparent);
}
.ob-body .ch-switch-cur { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ob-text); }
.ob-body .ch-switch-cur em { font-style: normal; font-size: 10.5px; color: var(--ob-text-3); }
.ob-body .ch-switch-item {
  height: 24px; padding: 0 9px; display: inline-flex; align-items: center;
  border: 1px dashed var(--ob-line); border-radius: 9999px; font-size: 12px; color: var(--ob-text-3);
}
.ob-body .ch-switch-item:hover { border-style: solid; border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .ch-switch-more { margin-left: auto; font-size: 12px; color: var(--ob-text-2); }
/* 渠道头（第一部分）：左边平台信息，右边「右上角综合分 + 主操作」上下排布。
   综合分整块住在 #dan-agg 里（AJAX 就地刷新），五维明细收在 .agg-pop 悬浮层。 */
.ob-body .ch-hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(268px, 306px); gap: 18px 26px; align-items: start; }
.ob-body .ch-hero-info { min-width: 0; display: flex; flex-direction: column; gap: 9px; }
.ob-body .ch-hero-side { position: relative; display: flex; flex-direction: column; gap: 10px; align-items: stretch; }
.ob-body .ch-vendor-badges { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .ch-vendor-flag { font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ch-vendor-name { margin: 0; font-size: 24px; line-height: 1.3; font-weight: 600; color: var(--ob-text); }
.ob-body .ch-vendor-sub { margin: 0; font-size: 12.5px; line-height: 20px; color: var(--ob-text-3); }
.ob-body .ch-vendor-agg { position: relative; display: flex; flex-direction: column; align-items: flex-end; }
.ob-body .ch-vendor-cta { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.ob-body .ch-vendor-cta .btn { white-space: nowrap; }
/* 指标胶囊 */
.ob-body .ch-vendor-metrics { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ob-body .ch-metric {
  display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  font-size: 12px; color: var(--ob-text-3);
  transition: border-color .18s ease, background-color .18s ease, box-shadow .22s ease, transform .22s cubic-bezier(.34, 1.4, .64, 1);
}
.ob-body .ch-metric:hover {
  border-color: var(--ob-line-strong); color: var(--ob-text-2); transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06);
}
.ob-body .ch-metric b { font-family: var(--ob-mono); font-weight: 500; color: var(--ob-text); }
/* 指标胶囊按语义上色：香绿臭红、计费按 Token Plan(蓝)/API 计费(琥珀)、新用户权益绿、运营方中性 */
.ob-body .ch-metric .c-up { color: var(--ob-up); }
.ob-body .ch-metric .c-down { color: var(--ob-down); }
.ob-body .ch-metric.is-vote { border-color: color-mix(in srgb, var(--ob-line-strong) 80%, transparent); }
.ob-body .ch-metric.is-billing.billing-plan { border-color: var(--ob-info-line); background: var(--ob-info-bg); color: var(--ob-info); }
.ob-body .ch-metric.is-billing.billing-plan b { color: var(--ob-info); }
.ob-body .ch-metric.is-billing.billing-api { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }
.ob-body .ch-metric.is-billing.billing-api b { color: var(--ob-warn); }
.ob-body .ch-metric.is-quota { border-color: var(--ob-up-line); background: var(--ob-up-bg); color: var(--ob-up); }
.ob-body .ch-metric.is-quota b { color: var(--ob-up); }
.ob-body .ch-vendor-tags { margin-top: 2px; }

/* 蛋库标签：#中转站 #优惠 这类给一层信息蓝的淡底，别和灰胶囊糊成一片 */
.ob-body .ec-tags .tag-chip,
.ob-body .ch-vendor-tags .tag-chip {
  border-color: color-mix(in srgb, var(--ob-info) 30%, var(--ob-line));
  background: color-mix(in srgb, var(--ob-info) 9%, transparent);
  color: var(--ob-info);
}
.ob-body .ec-tags .tag-chip:hover,
.ob-body .ch-vendor-tags .tag-chip:hover {
  border-color: color-mix(in srgb, var(--ob-info) 55%, var(--ob-line));
  background: color-mix(in srgb, var(--ob-info) 15%, transparent);
}

/* 评价筛选条 */
.ob-body .ch-filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 4px 0 12px; }
.ob-body .ch-filter {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px;
  border: 1px solid var(--ob-line); border-radius: 9999px; background: var(--ob-surface-2);
  color: var(--ob-text-2); font-size: 12.5px; cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s;
}
.ob-body .ch-filter b { font-family: var(--ob-mono); font-size: 11.5px; color: var(--ob-text-3); }
.ob-body .ch-filter:hover { border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .ch-filter.active { border-color: var(--ob-up-line); background: var(--ob-up-bg); color: var(--ob-text); }
.ob-body .ch-filter.active b { color: var(--ob-up); }
.ob-body .ch-filter-empty { font-size: 12px; }
.ob-body .ch-posts-note { margin-top: 12px; font-size: 11.5px; text-align: center; }

/* 点评帖：等级、测试模型、分数、有用/踩、追评 */
.ob-body .rev-post.is-critic { border-left: 2px solid var(--ob-down-line); padding-left: 10px; }
.ob-body .rv-model-tag {
  padding: 1px 7px; border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: var(--ob-surface-2); font-size: 11px; color: var(--ob-text-3);
}
.ob-body .rv-score { margin-left: auto; display: flex; align-items: center; gap: 7px; }
.ob-body .rv-score b { font-family: var(--ob-mono); font-size: 17px; font-weight: 600; color: var(--sc, var(--ob-up)); }
.ob-body .rv-ops { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.ob-body .rv-ops > form { display: inline-flex; }
.ob-body .rv-op {
  display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 10px;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  background: transparent; color: var(--ob-text-3); font-size: 12px; cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s;
}
.ob-body .rv-op b { font-family: var(--ob-mono); font-weight: 500; }
/* 有用=绿、踩=红（默认淡一点，悬停加重，选中填色） */
.ob-body .rv-vote.is-use .rv-op { color: color-mix(in srgb, var(--ob-up) 70%, var(--ob-text-3)); border-color: color-mix(in srgb, var(--ob-up) 24%, var(--ob-line)); }
.ob-body .rv-vote.is-use .rv-op:hover { color: var(--ob-up); border-color: var(--ob-up-line); }
.ob-body .rv-vote.is-use .rv-op.active { color: var(--ob-up); border-color: var(--ob-up-line); background: var(--ob-up-bg); }
.ob-body .rv-vote.is-dis .rv-op { color: color-mix(in srgb, var(--ob-down) 70%, var(--ob-text-3)); border-color: color-mix(in srgb, var(--ob-down) 24%, var(--ob-line)); }
.ob-body .rv-vote.is-dis .rv-op:hover { color: var(--ob-down); border-color: var(--ob-down-line); }
.ob-body .rv-vote.is-dis .rv-op.active { color: var(--ob-down); border-color: var(--ob-down-line); background: var(--ob-down-bg); }
/* 追评折叠块：闭合态必须是 inline-flex 且清掉 .rc-chat 桥接段带来的 padding-top / border-top
   （那 10px 会把整块撑高、把胶囊往下挤 5px，看起来就是「追评没和有用/踩对齐」；
   展开后再把分隔线加回来，面板内部观感不变）。 */
.ob-body .rv-chat { display: inline-flex; align-items: center; margin-top: 0; padding-top: 0; border-top: 0; }
.ob-body .rv-chat > summary {
  display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 10px; list-style: none;
  border: 1px solid var(--ob-line); border-radius: var(--ob-radius-sm);
  color: var(--ob-text-3); font-size: 12px; cursor: pointer;
}
.ob-body .rv-chat > summary::-webkit-details-marker { display: none; }
.ob-body .rv-chat > summary:hover { border-color: var(--ob-line-strong); color: var(--ob-text); }
.ob-body .rv-chat[open] > summary { border-color: var(--ob-line-strong); color: var(--ob-text); margin-bottom: 8px; }
.ob-body .rv-chat[open] {
  display: flex; flex-direction: column; align-items: stretch; width: 100%;
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--ob-surface-1);
}
/* 打分表单：标题行 + 测试模型输入 */
.ob-body .rv-h-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ob-body .rv-sub { margin: 6px 0 12px; font-size: 12px; line-height: 19px; }
.ob-body .rv-model { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.ob-body .rv-model label { flex: none; font-size: 12.5px; color: var(--ob-text-2); }
.ob-body .rv-model input {
  flex: 1; min-width: 200px; height: 34px; padding: 0 11px;
  background: var(--ob-surface-2); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
}
.ob-body .rv-model input:focus { outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }

/* 评分分档配色（--sc 由该块自己的 tier-* 类给出）：≥4.5 优秀绿 / ≥3.5 良好蓝 / ≥2.5 一般琥珀 / 其余红 */
.ob-body .tier-great { --sc: #2da44e; }
.ob-body .tier-good { --sc: #1668dc; }
.ob-body .tier-mid { --sc: #d48806; }
.ob-body .tier-low { --sc: #e5534b; }

/* 聚合分块：右上角一块「综合分玻璃片」，五维明细在悬浮/聚焦时从下面弹出来。
   开关是纯 CSS（:hover / :focus-within），AJAX 整体替换 #dan-agg 后交互不会丢。
   注意：.agg-ov > b 的结构被 test/dan.test.js 断言，改样式别改结构。 */
.ob-body .agg-score {
  --sc: var(--ob-up);
  position: relative; align-self: flex-end; display: flex; flex-direction: column; align-items: flex-end; gap: 3px;
  max-width: 100%; padding: 12px 16px 11px; border-radius: var(--ob-radius-lg); cursor: help;
  border: 1px solid color-mix(in srgb, var(--sc) 30%, var(--ob-line));
  background:
    radial-gradient(20rem 10rem at 100% 0%, color-mix(in srgb, var(--sc) 15%, transparent), transparent 62%),
    color-mix(in srgb, var(--ob-surface-1) 84%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06);
  transition: border-color .2s ease, box-shadow .26s ease, transform .26s cubic-bezier(.34, 1.4, .64, 1);
}
.ob-body .agg-score:hover,
.ob-body .agg-score:focus-within {
  border-color: color-mix(in srgb, var(--sc) 58%, var(--ob-line));
  transform: translateY(-1px);
  /* 只用一圈同色描边+内高光做「浮起」，全站不用投影 */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .09), 0 0 0 1px color-mix(in srgb, var(--sc) 42%, transparent);
  outline: none;
}
.ob-body .agg-ov { display: flex; align-items: baseline; gap: 5px; }
.ob-body .agg-ov b { font-family: var(--ob-mono); font-size: 36px; font-weight: 600; line-height: 1; color: var(--sc); letter-spacing: -.02em; }
.ob-body .agg-ov-meta { font-size: 12px; color: var(--ob-text-3); }
.ob-body .agg-stars { display: inline-flex; }
.ob-body .ob-stars { display: inline-flex; align-items: center; gap: 2px; color: var(--sc, var(--ob-up)); }
.ob-body .ob-stars .on svg { fill: currentColor; }
.ob-body .ob-stars .off { color: var(--ob-line-strong); }
.ob-body .agg-ov-note { font-style: normal; font-size: 11px; color: var(--ob-text-3); }
.ob-body .agg-hint { display: inline-flex; align-items: center; gap: 4px; margin-top: 2px; font-size: 10.5px; color: var(--ob-text-3); opacity: .75; }

/* 悬浮层：五维明细（玻璃卡片 + 逐条彩色横条）。从分数块左侧弹出：
   右侧那列下面就是两个按钮，只有左侧（平台信息）是空的，且按钮收成自然宽度后互不遮挡。 */
.ob-body .agg-pop {
  position: absolute; top: 0; right: calc(100% + 12px); z-index: 20; width: 306px; max-width: 78vw;
  display: flex; flex-direction: column; gap: 9px; padding: 13px 14px 11px;
  border: 1px solid var(--ob-line-strong); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-2) 93%, transparent);
  backdrop-filter: blur(18px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07);
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translateX(8px) scale(.98); transform-origin: 100% 0;
  transition: opacity .2s ease, transform .28s cubic-bezier(.34, 1.4, .64, 1), visibility .2s;
}
.ob-body .agg-score:hover .agg-pop,
.ob-body .agg-score:focus-within .agg-pop { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(0) scale(1); }
.ob-body .agg-pop-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: 12px; color: var(--ob-text-2); }
.ob-body .agg-dims { display: flex; flex-direction: column; gap: 8px; }
.ob-body .agg-d { display: grid; grid-template-columns: 15px 58px minmax(0, 1fr) 34px; align-items: center; gap: 9px; }
/* 每个维度一个色相，与广场卡 / 点评小片 / 打分卡共用 --dan-dN 那一份 */
.ob-body .agg-d:nth-child(1) { --dc: var(--dan-d1); }
.ob-body .agg-d:nth-child(2) { --dc: var(--dan-d2); }
.ob-body .agg-d:nth-child(3) { --dc: var(--dan-d3); }
.ob-body .agg-d:nth-child(4) { --dc: var(--dan-d4); }
.ob-body .agg-d:nth-child(5) { --dc: var(--dan-d5); }
/* 维度色图标 + 维度色名称/数值，条形是斗鸡台同款（8px、维度色填充、余量压深） */
.ob-body .agg-d-ic { display: inline-flex; width: 15px; height: 15px; color: var(--dc, var(--ob-up)); }
.ob-body .agg-d label { font-size: 12px; font-weight: 500; color: var(--dc, var(--ob-text-3)); }
.ob-body .agg-d-bar { height: 8px; border: 1px solid var(--ob-line); border-radius: 9999px; background: color-mix(in srgb, var(--ob-text) 72%, transparent); overflow: hidden; }
.ob-body .agg-d-bar i {
  display: block; height: 100%; border-radius: 9999px;
  background: var(--dc, var(--ob-up));
  animation: ob-bar-grow .6s cubic-bezier(.2, .8, .3, 1) both;
}
.ob-body .agg-d:nth-child(2) .agg-d-bar i { animation-delay: .05s; }
.ob-body .agg-d:nth-child(3) .agg-d-bar i { animation-delay: .1s; }
.ob-body .agg-d:nth-child(4) .agg-d-bar i { animation-delay: .15s; }
.ob-body .agg-d:nth-child(5) .agg-d-bar i { animation-delay: .2s; }
.ob-body .agg-d:hover .agg-d-bar i { filter: brightness(1.18) saturate(1.1); }
.ob-body .agg-d b { font-family: var(--ob-mono); font-size: 14px; font-weight: 700; color: var(--dc, var(--ob-text)); text-align: right; }
.ob-body .agg-pop-foot { display: flex; justify-content: flex-end; border-top: 1px solid var(--ob-line); padding-top: 8px; }
.ob-body .agg-pop-foot a { font-size: 11.5px; color: var(--ob-text-2); }
.ob-body .agg-pop-foot a:hover { color: var(--ob-text); }
.ob-body .agg-empty h3 { margin: 0 0 6px; font-size: 15px; }
.ob-body .agg-empty p { margin: 0; font-size: 12.5px; line-height: 20px; }

@media (max-width: 900px) {
  .ob-body .ch-hero { grid-template-columns: 1fr; gap: 16px; }
  .ob-body .ch-hero-side { align-items: stretch; }
  .ob-body .agg-score { align-self: stretch; align-items: flex-start; }
  .ob-body .agg-pop { top: calc(100% + 10px); right: auto; left: 0; width: 100%; transform-origin: 0 0; transform: translateY(-6px) scale(.98); }
  .ob-body .agg-score:hover .agg-pop,
  .ob-body .agg-score:focus-within .agg-pop { transform: translateY(0) scale(1); }
  .ob-body .ch-vendor-cta { flex-direction: row; flex-wrap: wrap; }
  .ob-body .ch-vendor-cta .btn { flex: 1; }
  .ob-body .ec-score { margin-left: 0; }
  .ob-body .rv-score { margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ob-body .agg-d-bar i { animation: none; }
  .ob-body .agg-score, .ob-body .agg-pop, .ob-body .ch-metric { transition: none; }
  .ob-body .agg-score:hover { transform: none; }
}

/* ---------- 计费方式（Token Plan / API 计费）----------
   表单里的套餐编辑器、卡片/详情页的计费徽章与套餐表、API 计费的优惠与规则块。
   plan 与 api 用两种强调色区分：套餐偏 info（蓝），按量偏 warn（琥珀），与设计系统其余部分一致。 */
.ob-body .ec-billing {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px;
  border: 1px solid var(--ob-info-line); border-radius: var(--ob-radius-sm);
  background: var(--ob-info-bg); color: var(--ob-info); font-size: 11px;
}
.ob-body .ec-billing.type-api { border-color: var(--ob-warn-line); background: var(--ob-warn-bg); color: var(--ob-warn); }

/* 表单：两类字段块 */
.ob-body .billing-block { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 14px; }
.ob-body .billing-block[hidden] { display: none; }
.ob-body .plan-head { display: flex; align-items: baseline; gap: 8px; }
.ob-body .plan-rows { display: flex; flex-direction: column; gap: 8px; }
.ob-body .plan-row { display: grid; grid-template-columns: 1fr 1fr 1.6fr auto; gap: 8px; align-items: center; }
.ob-body .plan-row input {
  height: 34px; padding: 0 11px; min-width: 0;
  background: var(--ob-surface-1); border: 1px solid var(--ob-line); border-radius: var(--ob-radius); color: var(--ob-text);
  font-size: 13px;
}
.ob-body .plan-row input:focus { outline: none; border-color: var(--ob-line-strong); box-shadow: 0 0 0 1px var(--ob-line-strong); }
.ob-body .plan-del[hidden] { visibility: hidden; }
.ob-body .plan-foot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ob-body .plan-foot .muted { font-size: 11.5px; line-height: 17px; flex: 1; min-width: 200px; }
.ob-body .plan-foot [data-plan-add][hidden] { display: none; }

/* AJAX 提交中的按钮：只降透明度 + 禁点，不换文案（换文案会抹掉按钮里的图标/计数节点） */
.ob-body .is-busy { opacity: .55; }

/* 详情页：套餐档位卡 / API 计费块
   套餐原来是三列表格，2 - 6 档挤在一张窄表里读不出重点；改成自适应的档位卡：
   价格用等宽字体放大当视觉锚点，用量降到卡片底部的次级行，档位多时自动换行。 */
.ob-body .ch-plans {
  display: flex; flex-direction: column; gap: 10px; margin: 12px 0;
  padding: 12px 14px; border: 1px solid var(--ob-line); border-radius: var(--ob-radius-lg);
  background: color-mix(in srgb, var(--ob-surface-1) 85%, transparent);
}
.ob-body .ch-plans-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ob-body .ch-plans-head .muted { font-size: 11.5px; }
.ob-body .ch-plan-grid {
  display: grid; gap: 10px; margin: 0; padding: 0; list-style: none;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.ob-body .ch-plan-card {
  display: flex; flex-direction: column; gap: 6px;
  padding: 11px 13px; border: 1px solid var(--ob-line); border-radius: var(--ob-radius);
  background: var(--ob-surface-2);
  transition: border-color .18s, background-color .18s;
}
.ob-body .ch-plan-card:hover { border-color: var(--ob-line-strong); }
.ob-body .ch-plan-name { font-size: 13px; font-weight: 600; color: var(--ob-text); }
.ob-body .ch-plan-price {
  display: flex; align-items: baseline; gap: 5px;
  font-family: var(--ob-mono); font-size: 20px; font-weight: 700; line-height: 1.15;
  letter-spacing: -.02em; color: var(--ob-text);
}
.ob-body .ch-plan-price em {
  font-style: normal; font-family: var(--ob-font);
  font-size: 11.5px; font-weight: 500; color: var(--ob-text-3);
}
.ob-body .ch-plan-quota {
  display: flex; align-items: baseline; gap: 6px; margin-top: 2px; padding-top: 7px;
  border-top: 1px dashed color-mix(in srgb, var(--ob-line) 80%, transparent);
  font-size: 12.5px; color: var(--ob-text-2);
}
.ob-body .ch-plan-quota-label {
  flex: none; font-size: 11px; letter-spacing: .04em; color: var(--ob-text-3);
}
.ob-body .ch-plans-note { margin: 0; font-size: 11.5px; }
.ob-body .ch-api-row { display: flex; gap: 10px; align-items: flex-start; }
.ob-body .ch-api-row label { flex: none; width: 64px; font-size: 11.5px; color: var(--ob-text-3); padding-top: 2px; }
.ob-body .ch-api-row p { margin: 0; font-size: 13px; line-height: 21px; color: var(--ob-text-2); }
.ob-body .ch-billing-none { font-size: 12px; }

@media (max-width: 900px) {
  .ob-body .plan-row { grid-template-columns: 1fr; }
  .ob-body .plan-del[hidden] { display: none; }
  .ob-body .ch-api-row { flex-direction: column; gap: 4px; }
  .ob-body .ch-api-row label { width: auto; }
}

/* ==========================================================================
   蛋库：打分弹窗 + 玻璃光晕与过渡（在第五批玻璃语汇上补的一层）
   原则同前：玻璃只做层次、光晕只做反馈，不遮内容；动效全部在
   prefers-reduced-motion 下关闭。
   ========================================================================== */

/* ---------- 打分弹窗（views/dan_detail.ejs 的 #dan-review-modal） ---------- */
.ob-body .ob-modal-overlay {
  position: fixed; inset: 0; z-index: 95;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(9, 10, 12, .62);
  backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .22s ease;
}
.ob-body .ob-modal-overlay[hidden] { display: none; }
.ob-body .ob-modal-overlay.is-open { opacity: 1; }
.ob-body .ob-modal {
  width: min(660px, 94vw); max-height: 86vh; overflow-y: auto;
  border: 1px solid var(--ob-line-strong); border-radius: var(--ob-radius-xl);
  /* 纯色底：不用半透明叠灰，避免整块发灰、输入框看着脏 */
  background: var(--ob-surface-2);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08);
  opacity: 0; transform: translateY(12px) scale(.975);
  transition: opacity .24s ease, transform .32s cubic-bezier(.34, 1.4, .64, 1);
}
.ob-body .ob-modal-overlay.is-open .ob-modal { opacity: 1; transform: none; }
.ob-body .ob-modal-head {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 18px; border-bottom: 1px solid var(--ob-line);
  background: var(--ob-surface-2);
}
.ob-body .ob-modal-title { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 600; color: var(--ob-text); }
.ob-body .ob-modal-body { padding: 16px 18px 18px; }
/* 弹窗自己就是卡片，里面的表单卡片壳子去掉，避免卡中卡 */
.ob-body .ob-modal .rv-card { margin: 0; padding: 0; border: 0; background: none; box-shadow: none; backdrop-filter: none; }
.ob-body .ob-modal .rv-card:hover { transform: none; box-shadow: none; }
/* 弹窗里的输入区也用纯色底（+描边），不要灰底 */
.ob-body .ob-modal .rev-form textarea { background: var(--ob-surface-2); }
/* 弹窗打开时锁滚动 */
html.ob-lock, html.ob-lock .ob-body { overflow: hidden; }

/* ---------- 渠道头：悬停时一层与评分同色的柔光（玻璃片被环境光扫过的感觉） ---------- */
.ob-body .ch-vendor { transition: border-color .2s ease, box-shadow .28s ease; }
.ob-body .ch-vendor::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(38rem 15rem at 100% 0%, color-mix(in srgb, var(--ob-up) 10%, transparent), transparent 64%);
  opacity: 0; transition: opacity .3s ease;
}
.ob-body .ch-vendor:hover::after { opacity: 1; }
.ob-body .ch-vendor:hover { border-color: var(--ob-line-strong); }

/* ---------- 按钮 / 筛选 / 标签：统一到一根弹性曲线，并给主按钮一点光 ---------- */
.ob-body .btn,
.ob-body .ob-btn,
.ob-body .mini-btn,
.ob-body .tag-chip,
.ob-body .ob-chip,
.ob-body .ch-switch-item,
.ob-body .ch-filter,
.ob-body .eg-tab,
.ob-body .ec-rate-btn {
  transition: color .18s ease, background-color .18s ease, border-color .18s ease,
              box-shadow .24s ease, transform .24s cubic-bezier(.34, 1.4, .64, 1);
}
.ob-body .btn:hover,
.ob-body .ob-btn:hover,
.ob-body .tag-chip:hover,
.ob-body .ob-chip:hover,
.ob-body .ch-switch-item:hover,
.ob-body .ch-filter:hover,
.ob-body .eg-tab:hover,
.ob-body .ec-rate-btn:hover { transform: translateY(-1px); }
.ob-body .btn-primary:hover,
.ob-body .ob-btn-primary:hover,
.ob-body .ec-rate-btn:hover {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ob-up) 24%, transparent);
}
/* 会打开弹窗的那个按钮：给一点持续的光（描边），指明它是主要入口 */
.ob-body .ch-rate-open { border-color: color-mix(in srgb, var(--ob-up) 34%, var(--ob-line)); }
.ob-body .ch-rate-open:hover {
  border-color: color-mix(in srgb, var(--ob-up) 62%, var(--ob-line));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ob-up) 30%, transparent);
}

/* ---------- 点评帖 / 榜单行：悬停反馈更轻一点 ---------- */
.ob-body .rev-post:hover { border-color: var(--ob-line-strong); }
.ob-body .ch-top li { transition: background-color .18s ease, padding-left .24s cubic-bezier(.34, 1.4, .64, 1); border-radius: var(--ob-radius-sm); }
.ob-body .ch-top li:hover { background: color-mix(in srgb, var(--ob-surface-1) 62%, transparent); padding-left: 6px; }

@media (prefers-reduced-motion: reduce) {
  .ob-body .ob-modal, .ob-body .ob-modal-overlay { transition: none; }
  .ob-body .btn:hover, .ob-body .ob-btn:hover, .ob-body .tag-chip:hover, .ob-body .ob-chip:hover,
  .ob-body .ch-switch-item:hover, .ob-body .ch-filter:hover, .ob-body .eg-tab:hover,
  .ob-body .ch-top li:hover { transform: none; }
  .ob-body .ch-vendor::after { transition: none; }
}
