/* ==========================================================================
   Shultimate · 飞盘规则助手
   布局参照 DeepSeek Harness 桌面端（owner 2026-10-05 给的截图）：
     窗口三灯 → 品牌 → 新对话 → 工作区（标题旁 3 个小图标）→ 默认工作区 + 会话 → 底部账号行
   设计约定（沿用 owner 一贯审美，勿改）：
     白底、极简黑白灰、1px 发丝分隔（#ECECEC）、无阴影、充分留白
     紫 #7B4EE6 仅作点缀（条款号、链接、按钮描边、状态点）
   无 CDN、无字体文件、无框架
   ========================================================================== */

:root{
  --ink:#1a1a1a; --ink-2:#5c5c5c; --ink-3:#9a9a9a; --ink-4:#c2c2c2;
  --line:#ececec; --line-2:#f5f5f5;
  --purple:#7B4EE6; --purple-soft:#f5f1fe; --purple-line:rgba(123,78,230,.34);
  --bg:#fff; --bg-2:#f2f3f4; --bg-3:#e9eaec;
  /* ⭐ 侧栏与标题栏底色：对标 DeepSeek Harness 的 --dsw-specific-sidebar-fill，
     浅色主题 = --dsw-static-neutral-bluish-50 = rgb(249,250,251)。
     关键不是"浅灰"这个形容，而是**它和主区不是同一个颜色**：
     官方把侧栏画成 #f9fafb、中心区画成 #fff，只差 6 个灰阶，
     靠这 6 级把"这是两栏"说出来，而不是靠一条竖线。
     我们之前两边都 #fff，只有 1px 分隔线撑着，视觉上像一整块白。
     ⚠️ 联动：desktop/main.js 的 titleBarOverlay.color 必须同值，
        否则系统窗口按钮那一行是白的、下面侧栏是灰的，接缝看得出来。 */
  --chrome:#f9fafb;
  --hover:#eceef0;          /* 在 #f9fafb 上要看得见，所以比 --bg-2 更深一档 */
  --danger:#b23b2e; --ok:#2e7d5b;
  --nav-w:280px;        /* 对标 DeepSeek Harness SIDEBAR_DEFAULT=280 */
  --titlebar-h:0px;     /* 客户端由 body.is-desktop 覆盖为 40，须与 main.js 一致 */
  --sans:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Courier New",monospace;
}

*{box-sizing:border-box;margin:0;padding:0;}
html,body{height:100%;}
body{
  background:var(--bg); color:var(--ink); font-family:var(--sans);
  font-size:14px; line-height:1.75; -webkit-font-smoothing:antialiased;
}
button,input,textarea,select{font:inherit;color:inherit;}
button{background:none;border:0;cursor:pointer;}
button:disabled{cursor:default;}
a{color:var(--purple);text-decoration:none;}
a:hover{text-decoration:underline;}
::-webkit-scrollbar{width:9px;height:9px;}
::-webkit-scrollbar-thumb{background:#e2e2e2;border-radius:6px;border:2px solid transparent;background-clip:content-box;}
::-webkit-scrollbar-thumb:hover{background:#d2d2d2;background-clip:content-box;}
::-webkit-scrollbar-track{background:transparent;}
.num{font-variant-numeric:tabular-nums;}

/* ============================ 骨架 ============================ */
/* ⭐ 客户端整体下移一个标题栏高度，露出的那一条用 --chrome 铺底
   —— 对标官方 AppFrame.module.css 的 `[data-windows-titlebar] .frame`
   （padding-top: titlebar-height + background: sidebar-fill）。
   这样「应用 / 编辑」两个菜单和系统窗口按钮在同一行，
   而主区白色面板从这条线**下面**开始，左上角带 16px 圆角。
   网页版 --titlebar-h:0，什么都不占，同一份 CSS 照跑。 */
.app{display:flex;height:100vh;overflow:hidden;position:relative;}
body.is-desktop .app{ padding-top:var(--titlebar-h); background:var(--chrome); }
body.is-desktop .body{ background:var(--bg); border-radius:16px 0 0 0; overflow:hidden; }

/* 标题栏层：横跨整宽的一条，右侧给系统按钮留出空间。
   整条是拖拽区，只有「应用 / 编辑」两个按钮是 no-drag。 */
.titlebar{
  position:absolute;left:0;right:0;top:0;height:var(--titlebar-h);z-index:40;
  display:none;align-items:center;-webkit-app-region:drag;
  /* 显式写 --chrome，不靠 .app 透出来：
     .app 以后若改背景（比如做暗色主题），这一行会跟着变，
     而它必须始终与侧栏、与 main.js 的 WINDOWS_TITLEBAR_COLOR 同值。 */
  background:var(--chrome);
}
body.is-desktop .titlebar{ display:flex; }
.titlebar .mbtn{
  -webkit-app-region:no-drag;
  height:24px;padding:0 9px;margin-left:4px;border-radius:6px;
  font-size:13px;color:var(--ink-2);letter-spacing:.2px;
  display:flex;align-items:center;
}
.titlebar .mbtn:hover{ background:var(--hover); color:var(--ink); }
/* 菜单弹层（主进程 Menu.popup 的落点提示）：真菜单由系统画，
   这里只保证点击后不会误触发拖窗口。 */
.titlebar .mspacer{flex:1;-webkit-app-region:drag;}

/* ======================= 侧栏 =======================
   结构照 DeepSeek Harness：品牌 / 新对话 / 工作区 / 底部账号行。
   ⚠️ 功能入口仍然只在左下角账号行里 —— 菜单项位置对标，但不等于把
   规则原文、检索测试这些塞进「工作区」标题旁。工作区 = 对话的容器，
   不是功能导航。 */
.nav{
  width:var(--nav-w);flex:0 0 var(--nav-w);background:var(--chrome);
  border-right:0.5px solid var(--line);display:flex;flex-direction:column;min-height:0;
  font-size:14px;   /* 对标DeepSeek Harness SidebarRoot .root */
  padding:0;        /* 官方是 padding:6px 12px，brand 行自己带margin */
}
/* ---- 窗口控制：交给系统，HTML 不再画 ----
   桌面客户端用 titleBarStyle:'hidden' + titleBarOverlay（对标 DeepSeek Harness），
   减号/方框/叉由Windows 自己绘制：命中区域、悬停态、最大化后变「还原」都不用我们维护，
   无障碍树和键盘导航也天然可用。
   ⚠️ 这里换过三版方案，都留了教训：
   ① 照抄 DeepSeek Harness 做成 macOS 红黄绿圆点 —— 那是 macOS 惯例，
      Windows 用户按肌肉记忆去右上角找，找不到就以为没有窗口控制。
   ② 改成右上角自绘 — 位置对了，但只是"长得像"：无障碍树里没有它。
   ⇒ 布局可以照抄，**平台惯例交给平台**。

   高度 40 = WINDOWS_TITLEBAR_HEIGHT（desktop/main.js 里的同名常量，两边必须一致）。
   ⚠️ 侧栏不再需要自己垫 ::before 假标题栏：整条标题栏现在是 .titlebar 层，
      .app 整体下移，侧栏从标题栏下沿开始。 */
:root{ --titlebar-h:0px; }            /* 网页版不占高度 */
body.is-desktop{ --titlebar-h:40px; } /* 客户端：让开系统按钮那一行 */
/* 主区（非对话页）的顶栏要能被拖：.phead 空白处即拖拽带，
   但里面的按钮和文字必须 no-drag，否则点标题改不了字、拖不动窗。 */
body.is-desktop .phead{ -webkit-app-region:drag; }
body.is-desktop .phead .burger,
body.is-desktop .phead .tt,
body.is-desktop .phead .act{ -webkit-app-region:no-drag; }

/* ---- 品牌：飞盘 + Shultimate ---- */
.nav-brand{
  /* 官方 .logoRow: height 60 / padding 8px 0 8px 4px / margin-bottom 4px
     .brandIdentity: gap 8 / height 24   .brandName: 18px / 600 / line-height 24 */
  height:60px;flex:none;margin-bottom:4px;
  padding:8px 0 8px 16px;display:flex;align-items:center;gap:8px;
  box-sizing:border-box;
}
.nav-brand .logo{
  width:24px;height:24px;flex:0 0 24px;display:flex;align-items:center;justify-content:center;
  color:var(--ink);
}
.nav-brand .logo svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.5;}
.nav-brand b{
  font-size:18px;font-weight:600;line-height:24px;letter-spacing:.04em;
  display:flex;align-items:center;gap:6px;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* ---- 圆角图标底座 ----
   owner 要求：「不是一个长方形，而是在对角这里做了圆润的过渡」。
   做法：正方容器 + 大圆角（接近 squircle），图标本身描边、1.5px，圆头圆角。 */
.ic{
  width:22px;height:22px;flex:0 0 22px;border-radius:7px;
  display:flex;align-items:center;justify-content:center;
  background:var(--bg-3);color:var(--ink-2);transition:background .12s,color .12s;
}
.ic svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;display:block;}
button:hover > .ic{background:var(--purple-soft);color:var(--purple);}

/* ---- 新对话 / 换一种讲法 ---- */
.nav-chat{padding:0 12px 12px;display:flex;flex-direction:column;gap:6px;}
.nav-chat .newc{
  /* 官方 .newSession: height38 / radius-md / 0.5px border-l3 / 14px 500 */
  width:100%;height:38px;display:flex;align-items:center;justify-content:center;gap:6px;
  border:0.5px solid var(--line);background:#fff;border-radius:12px;padding:0 12px;
  font-size:14px;font-weight:500;
  color:var(--ink);transition:background .12s,color .12s;
}
.nav-chat .newc:hover{background:var(--hover);color:var(--purple);}
.nav-chat .newc .ic{background:var(--bg-3);}
.nav-chat .newc:hover .ic{background:#fff;color:var(--purple);}
.ast-pick{
  width:100%;min-height:36px;border:0;background:transparent;border-radius:12px;padding:7px 8px;
  font-size:14px;cursor:pointer;display:flex;align-items:center;gap:8px;text-align:left;
  color:var(--ink);transition:background .12s;
}
.ast-pick:hover{background:var(--hover);}
.ast-pick .an{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:500;}
.ast-pick .caret{font-size:9px;color:var(--ink-4);}

/* ---- 工作区：标题行 + 3 个小图标 ---- */
.ws-head{
  display:flex;align-items:center;padding:2px 16px 6px;
}
.ws-head .ws-t{flex:1;font-size:14px;color:var(--ink);font-weight:500;}
.ws-head .ws-acts{display:flex;gap:2px;}
.ws-head .ws-acts button{
  /* 官方 .iconButton 28x28 / radius-sm */
  width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;
  color:var(--ink-2);transition:background .12s,color .12s;
}
.ws-head .ws-acts button:hover{background:var(--bg-3);color:var(--ink);}
.ws-head .ws-acts button.on{background:var(--purple-soft);color:var(--purple);}
.ws-head .ws-acts .ic{width:28px;height:28px;flex:0 0 28px;border-radius:8px;background:transparent;}
.ws-head .ws-acts .ic svg{width:16px;height:16px;}
.ws-head .ws-acts button:hover .ic{background:transparent;color:var(--ink);}
.ws-head .ws-acts button.on .ic{color:var(--purple);}

/* 搜索框：默认收起，点放大镜才展开（对标 DeepSeek，不占常态空间） */
.hist-search{padding:0 12px 6px;display:none;}
.hist-search.on{display:block;}
.hist-search input{
  width:100%;border:1px solid var(--line);background:var(--bg-2);border-radius:7px;
  padding:6px 10px;font-size:12.5px;color:var(--ink);outline:none;
}
.hist-search input::placeholder{color:var(--ink-4);}
.hist-search input:focus{border-color:var(--purple);background:#fff;}

/* 对话列表的组标题 = 收起/展开开关。**它是个真按钮，不是装饰标签。**
   ⚠️ 2026-10-06 之前这里是 `div.ws-item.on`「默认工作区」：带图标、带选中底色、
   加粗文字 —— 一个按钮的全部特征，但既没有 hover 也没有 click。
   owner 点了没反应，第一反应是"程序坏了"。**长得像按钮而不响应，比没有它更糟。**
   现在它干的是标题行那个折叠图标原来干的事（所以那个图标被删了 —— 一件事两个入口
   必然有一天走得不一样）。顺带把条数显示出来，标题行就成了一句实话。 */
.ws-item{
  display:flex;align-items:center;gap:8px;width:calc(100% - 20px);margin:0 10px 4px;
  padding:5px 6px;border-radius:8px;text-align:left;
  font-size:12.5px;color:var(--ink);font-weight:500;
  transition:background .12s;
}
.ws-item:hover{background:var(--hover);}
.ws-item .ic{width:20px;height:20px;flex:0 0 20px;border-radius:6px;background:transparent;color:var(--ink-2);}
.ws-item .ic svg{width:13px;height:13px;}
.ws-item .ws-n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.ws-item .ws-c{font-style:normal;font-size:11px;color:var(--ink-4);font-variant-numeric:tabular-nums;}
.ws-item .arw{font-size:9px;color:var(--ink-4);transition:transform .15s;}
body.folded .ws-item .arw{transform:rotate(-90deg);}

.nav-scroll{flex:1;overflow-y:auto;min-height:0;padding:0 10px 10px;}
/* ⚠️ 折叠态**只藏列表和搜索框，不许藏 .ws-item** —— 它就是那个开关，
   把它一起藏掉 = 收起之后没法再展开（上一版就是靠标题行第三个图标兜的，
   那个图标现在已经删了）。 */
body.folded .nav-scroll,body.folded .hist-search{display:none;}

/* ---- 底部账号行 = 全部功能的唯一入口 ----
   视觉上就是普通的账号行，不写"设置"两个字 ——
   免得让人以为要先配置才能用。 */
.nav-me{
  /* ⚠️⚠️ margin-top:auto 是「钉在侧栏底部」的那一句，不是装饰，别删。
     侧栏里唯一的 flex:1 是 .nav-scroll；而 body.folded（收起历史）会把它
     连同 .hist-search 一起 display:none ⇒ 剩余空间没人认领，
     账号行就跟着「工作区」标题一路往上跑：
       实测 1280×704 → 底边 704 跳到 249，凭空上移 455px（客户端外观下 415px），
       顶上那条 border-top 还悬在半空 —— 看着就像头像"浮"起来了。
     auto 与 flex:1 是互补关系，不是重复：展开时 nav-scroll 已吃满剩余空间，
     剩余为 0 ⇒ auto 归 0，完全无副作用（实测四种状态 gap 全为 0）。
     ⚠️ 修法是"把底部行自己钉住"，而不是"折叠时别隐藏 nav-scroll" ——
        后者会让被收起的列表仍然占位，等于没收起。
     flex:none 同理：窗口很矮时也不许这一行被压扁。 */
  margin-top:auto;flex:none;
  display:flex;align-items:center;gap:9px;width:100%;
  border-top:1px solid var(--line);padding:10px 16px;text-align:left;
  transition:background .12s;
}
.nav-me:hover{background:var(--hover);}
.nav-me .ava{
  width:26px;height:26px;border-radius:8px;flex:0 0 26px;display:block;
  background:var(--purple-soft);
}
.nav-me .ava .ic{width:26px;height:26px;flex:0 0 26px;border-radius:8px;
  background:transparent;color:var(--purple);}
.nav-me .ava .ic svg{width:15px;height:15px;}
.nav-me:hover .ava .ic{background:transparent;color:var(--purple);}
.nav-me .mt{flex:1;min-width:0;line-height:1.45;}
.nav-me .mn{display:block;font-size:12.5px;color:var(--ink);}
.nav-me .ms{
  display:block;font-size:10.5px;color:var(--ink-4);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.nav-me .st{margin:0;padding:0;border:0;display:flex;align-items:center;}
.nav-me .st i{width:6px;height:6px;border-radius:50%;background:var(--ink-4);flex:0 0 6px;}
.nav-me .st.ok i{background:var(--purple);}
.nav-me .st.warn i{background:#d19a2a;}

/* 头像浮层：一行一项，宽度按内容而不是撑满。
   早先 min-width:280px + 每项一句解释，浮层比侧栏还宽，人得逐行读。
   现在宽度交给最长的一项（"召回测试"），字号与侧栏菜单一致。 */
.me-pop{
  min-width:0;width:max-content;max-width:260px;padding:5px;
  transform-origin:bottom left;
}
/* 行高与圆角对齐官方 .panelRow（min-height 36 / radius-md），
   字号跟侧栏一致 —— 菜单和列表用同一套视觉语言，才像同一个软件。 */
.me-pop .pop-i{
  display:flex;align-items:center;min-height:36px;
  padding:7px 8px;font-size:14px;color:var(--ink);border-radius:12px;
}
.me-pop .pop-i:hover{background:var(--hover);}
.me-pop .pop-i.on{background:var(--hover);color:var(--purple);}
/* 分组间距：七项按"知识 / 质量 / 系统"分三段。
   只用留白，不写小标题 —— 写出来就变说明书了，用户得先读完才知道该点哪。 */
.me-pop .pop-gap{height:5px;}
.pop-i.more{border-top:1px solid var(--line-2);margin-top:4px;border-radius:0 0 6px 6px;}

/* ============================ 主区 ============================ */
.body{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0;}
/* 主区顶部也要一块拖拽区，否则 frameless 窗口在内容区空白处拖不动。
   对话页顶栏整条隐藏，聊天区自己顶部留 30px 拖拽带。 */
body.is-desktop .chat .stream{ -webkit-app-region:drag; }
body.is-desktop .chat .stream .inner{ -webkit-app-region:no-drag; }
.body.flush{overflow:hidden;}

.phead{
  flex:0 0 auto;border-bottom:1px solid var(--line);padding:0 26px;
  min-height:56px;display:flex;align-items:center;gap:14px;
}
.phead .burger{display:none;font-size:16px;color:var(--ink-2);padding:4px 7px;border-radius:4px;}
.phead .burger:hover{background:var(--bg-3);}
.phead .tt{flex:1;min-width:0;}
.phead .tt h2{font-size:15px;font-weight:600;letter-spacing:.2px;line-height:1.5;}
.phead .tt .ds{font-size:12px;color:var(--ink-3);margin-top:1px;}
.phead .act{display:flex;align-items:center;gap:9px;flex:0 0 auto;}
/* 侧栏已经没有功能导航了，"回到对话"是离开子页的唯一出口 ——
   这个按钮必须一直在，否则用户在规则原文/设置里会迷路。 */
.back2chat{color:var(--ink-2);}
.back2chat:hover{color:var(--purple);}

.pbody{flex:1;overflow-y:auto;min-height:0;}
/* 对话页要占满高度、自己管滚动，所以这里不滚 */
.pbody.flush{display:flex;overflow:hidden;padding:0;}
.pbody.flush > .chat{flex:1;min-width:0;height:auto;min-height:0;}
.wrap{max-width:1000px;margin:0 auto;padding:26px 26px 56px;}
.wrap.wide{max-width:1200px;}

/* ============================ 通用件 ============================ */
.btn{
  border:1px solid var(--line);background:#fff;border-radius:6px;padding:6px 14px;
  font-size:13px;color:var(--ink);transition:border-color .14s,color .14s,background .14s;
  display:inline-flex;align-items:center;gap:6px;
}
.btn:hover:not(:disabled){border-color:var(--purple);color:var(--purple);}
.btn:disabled{opacity:.4;}
.btn.pri{border-color:var(--purple);color:var(--purple);}
.btn.pri:hover:not(:disabled){background:var(--purple);color:#fff;}
.btn.sm{padding:4px 10px;font-size:12.5px;}
.btn.qk{border-color:transparent;padding:5px 9px;color:var(--ink-3);}
.btn.qk:hover:not(:disabled){border-color:var(--line);color:var(--purple);}

.badge{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--ink-2);}
.badge i{width:5px;height:5px;border-radius:50%;background:var(--purple);flex:0 0 5px;}
.badge.gray i{background:var(--ink-4);}
.badge.ok i{background:var(--ok);}
.badge.warn i{background:#d19a2a;}

.tag{display:inline-block;font-size:11px;color:var(--purple);background:var(--purple-soft);
  border-radius:4px;padding:2px 7px;white-space:nowrap;}
.tag.gray{color:var(--ink-3);background:var(--bg-3);}

.card{border:1px solid var(--line);border-radius:8px;background:#fff;}
.card-h{padding:13px 18px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;}
.card-h h3{font-size:13.5px;font-weight:600;flex:1;}
.card-h .hint{font-size:11.5px;color:var(--ink-3);font-weight:400;}
.card-b{padding:16px 18px;}

.sec{margin-bottom:26px;}
.sec:last-child{margin-bottom:0;}
.sec-t{font-size:12px;color:var(--ink-3);letter-spacing:.3px;margin-bottom:11px;display:flex;align-items:center;gap:9px;}
.sec-t .ln{flex:1;height:1px;background:var(--line-2);}

/* 统计卡 */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;}
.stat{border:1px solid var(--line);border-radius:8px;padding:15px 16px;background:#fff;}
.stat .k{font-size:11.5px;color:var(--ink-3);margin-bottom:6px;display:flex;align-items:center;gap:6px;}
.stat .v{font-size:24px;font-weight:600;line-height:1.25;font-variant-numeric:tabular-nums;}
.stat .u{font-size:12px;color:var(--ink-4);font-weight:400;margin-left:3px;}
.stat .n{font-size:11.5px;color:var(--ink-4);margin-top:3px;}

/* 功能入口卡（抄 RAGFlow 首页核心功能入口） */
.feats{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px;}
.feat{
  border:1px solid var(--line);border-radius:8px;padding:16px 16px 15px;background:#fff;
  text-align:left;transition:border-color .14s;display:block;width:100%;
}
.feat:hover{border-color:var(--purple);}
.feat .fi{width:26px;height:26px;border-radius:6px;background:var(--purple-soft);color:var(--purple);
  display:flex;align-items:center;justify-content:center;margin-bottom:10px;}
.feat .fi svg{width:14px;height:14px;display:block;}
.feat .ft{font-size:13.5px;font-weight:600;margin-bottom:3px;}
.feat .fd{font-size:12px;color:var(--ink-3);line-height:1.65;}

/* 表格 */
.tbl{width:100%;border-collapse:collapse;font-size:13px;}
.tbl th{
  text-align:left;font-weight:500;font-size:11.5px;color:var(--ink-3);letter-spacing:.2px;
  padding:9px 12px;border-bottom:1px solid var(--line);white-space:nowrap;background:var(--bg-2);
}
.tbl td{padding:10px 12px;border-bottom:1px solid var(--line-2);vertical-align:top;}
.tbl tr:last-child td{border-bottom:0;}
.tbl tbody tr:hover td{background:var(--bg-2);}
.tbl .r{text-align:right;font-variant-numeric:tabular-nums;}
.tbl .mono{font-family:var(--mono);font-size:12px;}

/* 键值表 */
.kv{font-size:13px;}
.kv .r{display:flex;gap:16px;padding:10px 0;border-bottom:1px solid var(--line-2);}
.kv .r:last-child{border-bottom:0;}
.kv .k{flex:0 0 172px;color:var(--ink-3);font-size:12.5px;}
.kv .v{flex:1;min-width:0;word-break:break-word;}
.kv .v .sub{font-size:12px;color:var(--ink-3);line-height:1.7;margin-top:3px;}

/* 空态 / 加载 */
.empty{color:var(--ink-3);font-size:13px;line-height:1.9;padding:22px 0;}
.empty b{display:block;color:var(--ink-2);font-weight:500;margin-bottom:5px;}
.loading{color:var(--ink-3);font-size:13px;display:flex;align-items:center;gap:9px;}
.loading .bar{width:64px;height:1px;background:var(--line);position:relative;overflow:hidden;}
.loading .bar::after{content:"";position:absolute;left:-30%;top:0;bottom:0;width:30%;
  background:var(--purple);animation:sweep 1.1s ease-in-out infinite;}
@keyframes sweep{0%{left:-30%}100%{left:100%}}
.err{color:var(--danger);font-size:13px;}

/* 提示条 */
.note{border-left:2px solid var(--purple);background:var(--purple-soft);border-radius:0 6px 6px 0;
  padding:11px 14px;font-size:12.5px;color:var(--ink-2);line-height:1.75;}
.note.warn{border-left-color:#d19a2a;background:#fdf8ec;}
.note b{color:var(--ink);font-weight:600;}

/* ============================ 对话页 ============================ */
/* 纯白：整块对话区（消息流 + 输入框）不铺任何底色，靠留白和发丝线分层。 */
.chat{display:flex;height:100%;min-height:0;background:#fff;position:relative;}

/* 历史对话：现在住在侧栏的滚动区里，不再是独立面板 */
.hist{padding:0 0 4px;}
.hist .grp{font-size:10.5px;color:var(--ink-4);padding:0 6px 5px;letter-spacing:.3px;}
.hist .grp:not(:first-child){margin-top:12px;}
.hist-empty{font-size:11.5px;color:var(--ink-4);padding:2px 8px;line-height:1.7;}
.hitem{
  display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:5px;font-size:12.5px;
  color:var(--ink-2);cursor:pointer;transition:background .12s,color .12s;
}
.hitem:hover{background:var(--hover);color:var(--ink);}
.hitem.on{background:#fff;color:var(--ink);border:1px solid var(--line);padding:5px 7px;}
.hitem .tx{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.hitem .del{opacity:0;font-size:13px;color:var(--ink-3);line-height:1;padding:1px 3px;border-radius:3px;}
.hitem:hover .del{opacity:1;}
.hitem .del:hover{color:var(--danger);}

.chat-mid{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0;}
.stream{flex:1;overflow-y:auto;min-height:0;padding:0 24px;}
/* 对话页顶部现在由 .app 整体下移让出标题栏，.stream 自己不再垫。
   保留一条 drag 是为了拖窗口（对话页顶栏整条隐藏，没有 .phead 可拖）。 */
body.is-desktop .stream{ -webkit-app-region:drag; }
body.is-desktop .stream .inner{ -webkit-app-region:no-drag; }
.inner{max-width:730px;margin:0 auto;padding:26px 0 32px;}

/* 空态容器：不渲染任何内容，只是把输入框顶到中线用的占位 */
.hero{padding:0;}

/* 空态：屏幕上半部完全空白，输入框固定在**底部**。
   owner 2026-10-05 指正：「你做的有点偏中了…应该把它放最底下」——
   对标 DeepSeek Harness：它是聊天窗，输入框永远贴着底，
   上面的留白是消息区该有的样子，不是"把输入框摆在中线"。
   实现差别只有一行：composer 不再 flex:1 + align-items:center，
   而是让 stream 自己撑满，composer 跟在它后面。 */
.chat.empty .stream{flex:1;min-height:0;overflow:hidden;padding-top:0;}
/* ⚠️ 必须显式给宽度：composer 是 flex 容器时，.cbox 作为 flex item
   会按内容撑开而不是按 max-width 收窄，窄屏下 textarea 的 min-content
   会把整块顶出右边缘。min-width:0 是让 textarea 能正常收缩的前提。 */
.chat.empty .cbox{width:100%;max-width:730px;min-width:0;}
/* 空态右栏原先由 CSS 硬藏。现在不能这么做了 ——「我的笔记」在空态也必须能打开，
   所以「该不该出现」不再是 CSS 能判断的事，改由 JS 单点决定（见 app.js:panelOpen）。
   那条规则现在只剩一个后果：右栏默认收起，靠 .hide 类表达。 */

/* 顶栏收起后补回来的汉堡：只在窄屏出现（宽屏侧栏常驻，不需要）。
   position:absolute 挂在 .chat 上，不占布局高度。 */
.c-burger{
  display:none;position:absolute;top:9px;left:12px;z-index:5;
  font-size:16px;color:var(--ink-2);background:#fff;
  border:1px solid var(--line);border-radius:5px;padding:3px 8px;
}
.c-burger:hover{color:var(--purple);border-color:var(--purple);}

/* 右栏收起后「笔记」的入口：钉在对话区右上角。
   ⚠️ 只在右栏收起时出现（.chat.no-rail）—— 展开时由头部标签切换。
   两个入口同时存在就是"同一功能两处都能点"，那正是导航分裂的老毛病。 */
.c-note{
  display:none;position:absolute;top:9px;right:12px;z-index:5;
  align-items:center;gap:5px;font-size:12px;color:var(--ink-2);background:#fff;
  border:1px solid var(--line);border-radius:5px;padding:4px 11px;
}
.c-note:hover{color:var(--purple);border-color:var(--purple);}
.chat.no-rail .c-note{display:inline-flex;}

@media (max-width:1000px){
  .c-burger{display:inline-flex;}
}

/* 对话页：整条顶栏收起。顶栏那行"对话 / 用大白话问…"在首屏最显眼的位置
   重复了输入框已经表达的事，看到它会先理解"这是个功能"再开始提问。 */
.body.bare > .phead{display:none;}

/* 消息 */
.msg{margin-bottom:28px;}
.msg.user{display:flex;justify-content:flex-end;}
.msg.user .bub{background:var(--bg-3);border-radius:11px;padding:9px 14px;max-width:78%;
  font-size:14px;white-space:pre-wrap;word-break:break-word;}
.msg.bot .who{font-size:11px;color:var(--ink-4);letter-spacing:.3px;margin-bottom:8px;
  display:flex;align-items:center;gap:7px;}
.msg.bot .who i{width:5px;height:5px;border-radius:50%;background:var(--purple);flex:0 0 5px;}
.msg.bot.gated .who i{background:var(--ink-4);}
.md p{margin-bottom:8px;}
.md p:last-child{margin-bottom:0;}
.md ul{list-style:none;margin:3px 0 9px;}
.md ul li{position:relative;padding-left:15px;margin-bottom:2px;}
.md ul li::before{content:"";position:absolute;left:0;top:.76em;width:5px;height:1px;background:var(--ink-4);}
.md strong{font-weight:600;}
.md code{background:var(--bg-2);border:1px solid var(--line-2);padding:0 5px;border-radius:3px;font-size:12.5px;}
.md blockquote{border-left:2px solid var(--line);padding-left:12px;color:var(--ink-2);margin:7px 0;}
/* 「展开细节」：直答之下的入口 + 可折叠的细节区。
   ⚠️ 常驻可见，**不做** hover 才出现（那是"用户找不到的功能 = 不存在"）。
   ⚠️ 不放进 .tools（那里 opacity:0）。
   做得轻 —— 小字、无边框、无底色：它是个入口，不是内容本身。
   （`.lb` 那条旧的"小节标题"样式已随五段结构一起删除，别再引用。） */
.more{margin-top:11px;}
.more-btn{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;color:var(--ink-3);
  padding:0;cursor:pointer;transition:color .12s;}
.more-btn:hover{color:var(--purple);}
.more-btn.on{color:var(--ink-2);}
.more-btn .arw{font-size:9px;transition:transform .15s;display:inline-block;}
.more-btn.on .arw{transform:rotate(90deg);}
.more-body{display:none;margin-top:10px;padding-top:11px;border-top:1px solid var(--line-2);}
.more-body.on{display:block;}
/* ---- 术语白话解释块（2026-10-10） ----
   解决的问题：官方规则正文（含模型生成的解释）里满是「确立盘权」「非轻微接触」
   这类词，零基础新手读完还是不懂规则 —— 检索答得上 ≠ 人读得懂。
   做法：答案下方附官方名词定义（data/definitions.jsonl，零编造）。

   视觉口径：**必须和正文明确分开**，但不能做得像报错或像告警。
   它是"补充读物"，不是"警告"。所以：左侧一条细发丝 + 极浅底，
   不加边框、不加阴影（遵循全站极简约定）。 */
.gloss{margin-top:13px;padding:11px 0 2px 12px;border-left:2px solid var(--purple-line);}
.gloss-h{font-size:12px;color:var(--ink-3);margin-bottom:5px;letter-spacing:.01em;}
.gloss .md{font-size:14px;color:var(--ink-2);line-height:1.72;}
.gloss .md p{margin:5px 0;}
.gloss .md strong{color:var(--ink-1);font-weight:600;}
.cite{color:var(--purple);border-bottom:1px dashed var(--purple-line);cursor:pointer;
  font-variant-numeric:tabular-nums;padding:0 1px;white-space:nowrap;}
.cite:hover{background:var(--purple-soft);}
.cites{display:flex;flex-wrap:wrap;gap:6px;margin-top:14px;}
.cchip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:5px;
  background:#fff;padding:4px 9px;font-size:12px;color:var(--ink-2);transition:border-color .12s,color .12s;}
.cchip:hover{border-color:var(--purple);color:var(--purple);}
.cchip.on{border-color:var(--purple);color:var(--purple);background:var(--purple-soft);}
.cchip b{font-weight:500;color:var(--purple);font-variant-numeric:tabular-nums;}
.cchip .cos{color:var(--ink-4);font-variant-numeric:tabular-nums;}
.cchip.on .cos{color:var(--purple);opacity:.7;}
.meta{margin-top:13px;padding-top:10px;border-top:1px solid var(--line-2);display:flex;
  align-items:center;gap:14px;flex-wrap:wrap;font-size:11.5px;color:var(--ink-3);}
.meta .sp{flex:1;}
.tools{display:flex;gap:12px;opacity:0;transition:opacity .12s;}
.msg.bot:hover .tools{opacity:1;}
.tools button{font-size:11.5px;color:var(--ink-3);}
.tools button:hover{color:var(--purple);}
/* 「记进笔记」：常驻可见。
   ⚠️ 刻意不放进 .tools —— 那里是 opacity:0、hover 才出现的（"复制回答"是
   顺手动作，藏起来没关系）。而"记下来以后回看"是目的本身，藏起来就没人用。 */
.nbtn{font-size:11.5px;color:var(--ink-3);}
.nbtn:hover{color:var(--purple);}
.rw{margin-top:9px;font-size:11.5px;color:var(--ink-3);}
.rw b{font-weight:400;color:var(--ink-2);}

/* 每条回答的反馈：**两个图标，鼠标停在回答上才出现。**
   ⚠️ 2026-10-06 之前这里是常驻的一行「这个回答有用吗？ 有用 没用」——
   owner 报「提的每一个问题都写个『这东西』，感觉很烦」。
   那条文案会在每一条回答下面重复一次，是纯噪音。
   现在的形态 = 行业做法（ChatGPT / Claude / Gemini 的回答工具条）：
   只有图标、没有文案、hover 才出、和「复制回答」同一处。
   ⚠️ 交互过之后（.acted）即使鼠标移开也保持可见 —— 否则用户点了「没用」、
   选完原因、一移开鼠标，那个面板连同"已记录"就凭空消失了。 */
.fb{margin-top:10px;opacity:0;transition:opacity .12s;}
.msg.bot:hover .fb,.fb.acted{opacity:1;}
.fb-bar{display:flex;align-items:center;gap:4px;}
.fb-i{border:0;background:transparent;padding:2px;border-radius:6px;line-height:1;color:var(--ink-4);
  transition:color .12s,background .12s;}
.fb-i:hover{color:var(--purple);background:var(--purple-soft);}
.fb-i.on{color:var(--purple);}
.fb-i .ic{width:20px;height:20px;flex:0 0 20px;border-radius:6px;background:transparent;}
.fb-i .ic svg{width:14px;height:14px;}
.fb-body:empty{display:none;}
.fb-head{font-size:11.5px;color:var(--ink-2);margin:10px 0 7px;}
.fb-opts{display:flex;flex-wrap:wrap;gap:6px;}
.fb-opt{border:1px solid var(--line);border-radius:5px;background:#fff;padding:3px 9px;
  font-size:11.5px;color:var(--ink-2);transition:border-color .12s,color .12s,background .12s;}
.fb-opt:hover{border-color:var(--purple-line);color:var(--purple);}
.fb-opt.on{border-color:var(--purple);color:var(--purple);background:var(--purple-soft);}
.fb-ta{display:block;width:100%;max-width:520px;margin-top:9px;border:1px solid var(--line);
  border-radius:7px;padding:8px 11px;font-size:12px;line-height:1.6;resize:vertical;
  min-height:56px;outline:0;color:var(--ink);background:#fff;font-family:inherit;}
.fb-ta:focus{border-color:var(--purple);}
.fb-ta::placeholder{color:var(--ink-4);}
.fb-row{display:flex;align-items:center;gap:10px;margin-top:9px;}
.fb-sub{border:1px solid var(--purple);border-radius:5px;background:var(--purple-soft);
  padding:3px 13px;font-size:11.5px;color:var(--purple);transition:background .12s,color .12s;}
.fb-sub:hover:not(:disabled){background:var(--purple);color:#fff;}
.fb-sub:disabled{border-color:var(--line);background:#fff;color:var(--ink-4);cursor:not-allowed;}
.fb-note{font-size:11px;color:var(--ink-4);}
.fb-done{font-size:11.5px;color:var(--ok);}
.fb-err{font-size:11.5px;color:var(--danger);margin-top:7px;}

.composer{flex:0 0 auto;padding:0 24px 14px;}
.cbox{max-width:730px;margin:0 auto;}
.field{border:1px solid var(--line);border-radius:9px;background:#fff;transition:border-color .14s;}
.field:focus-within{border-color:var(--purple);}
.field textarea{width:100%;border:0;outline:0;resize:none;font:inherit;color:var(--ink);
  background:transparent;padding:12px 15px 2px;min-height:50px;max-height:180px;line-height:1.7;display:block;}
.field textarea::placeholder{color:var(--ink-4);}
.frow{display:flex;align-items:center;gap:10px;padding:5px 8px 8px 15px;}
.frow .hint{font-size:11.5px;color:var(--ink-4);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.send{border:1px solid var(--purple);color:var(--purple);background:#fff;border-radius:6px;
  font-size:13px;padding:5px 17px;transition:background .14s,color .14s;}
.send:hover:not(:disabled){background:var(--purple);color:#fff;}
.send:disabled{opacity:.35;}
.send.stop{border-color:var(--ink-3);color:var(--ink-2);}
.send.stop:hover{background:var(--bg-3);color:var(--ink);}

/* ==================== 右侧面板：来源与引用 / 我的笔记 ====================
   一个槽位、两个视图（顶部标签切换），**不并排开两栏**。
   理由：两者都是「看旁边的材料」，而对话区本来就不宽 ——
   侧栏 240 + 引用栏 326 + 笔记栏 326 会让正文挤到没法读。
   ⭐ 开合只有一处真相：`.hide`（app.js:syncRail 单点写入）。
      旧的 `.open`（窄屏抽屉）已并入 `.hide` 的反面，不再单独使用。
   ⭐ 收起动画靠 `.rail-in` 撑固定宽度 + 外层 width 归零 ——
      直接缩外层宽度会让里面的文字在动画中反复折行重排，看着像抖动。 */
.rail{width:326px;flex:0 0 326px;border-left:1px solid var(--line);overflow:hidden;
  transition:flex-basis .22s ease,width .22s ease,border-color .22s ease;}
.rail.hide{width:0;flex:0 0 0;border-left-color:transparent;}
.rail-in{width:326px;height:100%;display:flex;flex-direction:column;min-height:0;background:#fff;}

.rail-head{flex:0 0 auto;height:44px;display:flex;align-items:center;gap:6px;padding:0 8px 0 10px;
  border-bottom:1px solid var(--line);}
.rtabs{display:flex;align-items:center;gap:1px;flex:1;min-width:0;}
.rtab{font-size:12.5px;color:var(--ink-3);padding:4px 9px;border-radius:5px;
  transition:background .12s,color .12s;white-space:nowrap;}
.rtab:hover{background:var(--hover);color:var(--ink);}
.rtab.on{background:var(--purple-soft);color:var(--purple);font-weight:500;}
.rail-head .cnt{font-size:11px;color:var(--ink-3);font-weight:400;border:1px solid var(--line);
  border-radius:9px;padding:0 7px;line-height:1.7;font-variant-numeric:tabular-nums;flex:0 0 auto;}
.rail-head .x{flex:0 0 auto;font-size:15px;color:var(--ink-3);padding:2px 7px;border-radius:5px;line-height:1;}
.rail-head .x:hover{background:var(--hover);color:var(--purple);}
.rail-body{flex:1;overflow-y:auto;min-height:0;padding:14px 16px 26px;}
.rail-empty{color:var(--ink-3);font-size:12.5px;line-height:1.9;padding-top:4px;}
.rail-empty b{font-weight:500;color:var(--ink-2);}

/* ---- 我的笔记 ----
   用户的私人本子：本机 localStorage，不上服务器、不进反馈统计。
   刻意做成"打开就能写"——没有标题栏、没有保存按钮、没有首次引导文案，
   输进去就存（400ms 防抖）。写笔记这件事不该先学一遍怎么用。 */
.nt-add{display:block;width:100%;border:1px dashed var(--line);border-radius:7px;
  background:#fff;padding:7px;font-size:12.5px;color:var(--ink-3);
  transition:border-color .12s,color .12s;}
.nt-add:hover{border-color:var(--purple);color:var(--purple);border-style:solid;}
.nt-list{margin-top:4px;}
.nt-item{border-bottom:1px solid var(--line-2);padding:12px 0;}
.nt-item:last-child{border-bottom:0;padding-bottom:2px;}
.nt-h{display:flex;align-items:center;gap:6px;}
.nt-t{flex:1;min-width:0;border:0;outline:0;font:inherit;font-size:12.5px;font-weight:500;
  color:var(--ink);background:transparent;padding:2px 0;}
.nt-t::placeholder{color:var(--ink-4);font-weight:400;}
.nt-del{flex:0 0 auto;font-size:13px;color:var(--ink-4);padding:1px 5px;border-radius:4px;line-height:1;}
.nt-del:hover{color:var(--danger);background:var(--bg-2);}
/* 正文。⚠️ 2026-10-07 从 textarea 换成 contenteditable：
   ① resize/overflow 失效（div 没有滚动条），min-height 从"撑高"变成"下限" ——
      contenteditable 天然随内容长高，这行只剩"空笔记时也留出可点的位置"。
   ② placeholder 要靠 :empty::before 手动画（contenteditable 无原生支持）。 */
.nt-b{display:block;width:100%;border:0;outline:0;font:inherit;
  font-size:12.5px;line-height:1.78;color:var(--ink-2);background:transparent;
  padding:2px 0;min-height:50px;
  /* ⚠️ contenteditable 里按 Enter 会留下嵌套 div，
     不限制 max-width 的话长列表会撑破布局。 */
  overflow-wrap:anywhere;word-break:break-word;}
/* placeholder。只在**真正空**时出现 —— :empty 判定的是没有任何子节点，
   正好对应"没打过字"；一旦有内容（包括只有 <br>）就不显示。 */
.nt-b:empty::before{content:attr(data-ph);color:var(--ink-4);pointer-events:none;}
/* 正文里的排版元素：字号全部跟着父级走，只改字重和缩进，
   免得一条笔记里的标题比标题还大。 */
.nt-b h2,.nt-b h3{font-size:1em;font-weight:600;margin:6px 0 2px;color:var(--ink);}
.nt-b ul,.nt-b ol{margin:4px 0;padding-left:1.5em;}
.nt-b li{margin:1px 0;}
.nt-b b,.nt-b strong{font-weight:600;color:var(--ink);}
.nt-b blockquote{border-left:2px solid var(--line);margin:4px 0;padding-left:8px;color:var(--ink-3);}
.nt-b code{font-family:ui-monospace,Consolas,monospace;font-size:.94em;
  background:var(--bg-2);padding:0 3px;border-radius:3px;}
/* 待办的勾选框：禁用的（用户打勾后要跟着文字存下来），
   但仍然可点 —— 否则打完勾就没法取消。 */
.nt-b input[type=checkbox]{margin:0 4px 0 0;vertical-align:-1px;cursor:pointer;}

/* ---- 正文工具栏（2026-10-07）
   位置在正文**下方**、静态占位（不是 hover 才出现）：
   hover 才出现的话，用户得先猜"这行能点"，而它恰恰是最需要被看见的功能。
   样式走极简：无边框、发丝分隔、灰阶，只有选中/悬停才落到紫色。 */
.nt-bar{display:flex;align-items:center;gap:1px;height:0;overflow:hidden;
  opacity:0;transition:height .16s ease,opacity .16s ease;margin-bottom:0;}
/* 有内容、或者编辑区正被点着/聚焦时才展开 */
.nt-item:hover .nt-bar,.nt-item:focus-within .nt-bar,.nt-bar.on{height:26px;opacity:1;margin-bottom:4px;}
.nt-tb{display:inline-flex;align-items:center;justify-content:center;
  min-width:24px;height:22px;padding:0 5px;border:0;background:transparent;
  border-radius:4px;font:inherit;font-size:12px;color:var(--ink-4);cursor:pointer;
  line-height:1;}
.nt-tb:hover{background:var(--bg-2);color:var(--ink-2);}
.nt-tb:focus-visible{outline:2px solid var(--purple);outline-offset:1px;}
.nt-tb b{font-weight:700;font-size:12.5px;}
/* 工具栏右端留白，避免和右上角的星标/删除挤在一起 */
.nt-bar::after{content:"";flex:1;}
/* ---- 结构：分组标题 + 连续编号（2026-10-06 owner：「没有一二三四的条理」）-----
   分组标题是"我现在看的是哪一批"，编号是"我本子上的第几条"。
   两者都只用最轻的字重和灰阶 —— 它们是秩序，不是内容。 */
.nt-grp{font-size:11px;color:var(--ink-4);letter-spacing:.6px;margin:14px 0 2px;}
.nt-grp:first-child{margin-top:4px;}
.nt-no{flex:0 0 auto;min-width:15px;font-size:10.5px;color:var(--ink-4);
  font-variant-numeric:tabular-nums;text-align:right;}
.nt-item.star .nt-no{color:var(--purple);}

/* 星标 = 重点。点亮后这一条会浮到最上面的「重点」组里。 */
.nt-star{flex:0 0 auto;font-size:13px;color:var(--ink-4);padding:1px 4px;border-radius:4px;line-height:1;}
.nt-star:hover{color:var(--purple);background:var(--bg-2);}
.nt-star.on{color:var(--purple);}

/* 页脚：来源可点（回到那次对话 / 跳到那条原文）+ 时间。
   原来这里是一行死文本 —— 「依据 2.1」看得见、点不动。 */
.nt-m{display:flex;align-items:center;gap:5px;flex-wrap:wrap;margin-top:7px;
  font-size:10.5px;color:var(--ink-4);line-height:1.7;}
.nt-by{color:var(--ink-4);}
.nt-src,.nt-cite{border:0;background:transparent;padding:0;font:inherit;font-size:10.5px;
  color:var(--ink-3);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.nt-cite{font-variant-numeric:tabular-nums;padding:0 1px;}
.nt-src:hover,.nt-cite:hover{color:var(--purple);text-decoration:underline;}
.nt-time{margin-left:auto;color:var(--ink-4);font-variant-numeric:tabular-nums;}
.nt-empty{font-size:12.5px;color:var(--ink-3);line-height:1.9;padding-top:12px;}

/* ------------------------------ 我的笔记（整页 #/notes） ------------------------------
   与右栏那个面板**共用同一套 .nt-* 节点**（见 app.js 的 noteNode）——
   这里只补"整页"多出来的那条工具行和外层宽度。
   ⚠️ 不另写一套 .np-item 之类的样式：两套渲染早晚会不一致。 */
.notes-page{max-width:760px;}
.np-bar{display:flex;align-items:center;gap:10px;padding-bottom:12px;
  border-bottom:0.5px solid var(--line);margin-bottom:2px;}
.np-q{flex:1;min-width:0;height:32px;padding:0 11px;border:0.5px solid var(--line);
  border-radius:8px;background:var(--bg-2);font:inherit;font-size:13px;color:var(--ink);outline:0;}
.np-q:focus{border-color:var(--purple);background:var(--bg);}
.np-q::placeholder{color:var(--ink-4);}
.np-count{flex:0 0 auto;font-size:11.5px;color:var(--ink-4);white-space:nowrap;}
/* 保存回执：写完闪一下就走，不占常态注意力。
   ⚠️ 必须存在 —— 自动保存如果没有回执，体感上等于没保存（见 app.js 的 flashSaved）。 */
.np-saved{flex:0 0 auto;font-size:11.5px;color:var(--ok);opacity:0;transition:opacity .25s;}
.np-saved.on{opacity:1;}
/* 整页里每条笔记的正文比右栏宽松一点 —— 这里宽度够，没必要挤成 12.5px。 */
.notes-page .nt-item{padding:16px 0;}
.notes-page .nt-t{font-size:14px;}
.notes-page .nt-b{font-size:14px;line-height:1.85;}

/* ==========================================================================
   笔记三视图 + 复习（2026-10-07）
   --------------------------------------------------------------------------
   设计约束（**故意不给的东西比给的更重要**）：
   · 不加阴影 —— 评审把"三字体五渐变一carousel"列为业余 premium 的典型特征，
     而阴影一旦上桌，整页就开始往"廉价高级"滑。层次全靠 **发丝线 + 字阶**。
   · 紫色只出现在"可点的、选中的、需要你决定的"三类元素上，
     绝不铺底、绝不做大面积高亮 —— 一旦泛滥，点睛就失效了。
   · 每个交互都要有状态：hover / focus / active / selected / disabled 全部定义。
     Awwwards 开发奖的六轴里 **accessibility 得分最低（6.82）**，
     focus 环与 aria 是最便宜的补分项 —— 这里不省。 */

/* ---- 视图切换（按时间 / 按规则章 / 回收站）----
   用「下划线指示」而不是「胶囊底色」：胶囊底色是 2015 年的 tab，
   下划线能把视觉重量让给下面的内容 —— 笔记页的主角是笔记，不是导航。 */
.np-modes{display:flex;align-items:center;gap:16px;margin-bottom:2px;}
.np-mode{position:relative;border:0;background:transparent;padding:10px 1px 9px;
  font:inherit;font-size:13px;color:var(--ink-4);cursor:pointer;
  transition:color .15s;}
/* focus-visible 而不是 focus —— 鼠标点不该在按钮上留一圈高亮，
   键盘 Tab 过来必须看得见在哪。这是"能用"和"好用"的分界。 */
.np-mode:focus{outline:0;}
.np-mode:focus-visible{outline:2px solid var(--purple);outline-offset:2px;border-radius:3px;}
.np-mode:hover{color:var(--ink-2);}
.np-mode.on{color:var(--ink);font-weight:500;}
.np-mode.on::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1.5px;
  background:var(--purple);border-radius:2px;animation:npSlide .22s cubic-bezier(.2,.7,.3,1);}
@keyframes npSlide{from{transform:scaleX(.2);opacity:0}to{transform:scaleX(1);opacity:1}}
/* 尊重系统的"减少动态效果"设置 —— 前庭功能障碍用户会因为位移动画难受。 */
@media (prefers-reduced-motion:reduce){
  .np-mode.on::after{animation:none;}
  .rv-a{transition:none;}
}

/* 「N 条该复习」—— 全站唯一一处"主动召唤你"的提示。
   它挂在 tab 行右侧而不是做成横幅：横幅要你点掉，标签只是多看一眼。 */
.np-rev{margin-left:auto;font-size:11.5px;color:var(--purple);cursor:pointer;
  padding:3px 9px;border-radius:20px;background:var(--purple-soft);
  transition:filter .15s;border:0;font-family:inherit;line-height:inherit;}
.np-rev[hidden]{display:none;}
.np-rev:hover{filter:brightness(.96);}
.np-rev:focus-visible{outline:2px solid var(--purple);outline-offset:2px;}

/* 导入导出：两个次级动作，收在工具行右端。默认安静，hover 才显出可点。 */
.np-io{display:inline-flex;gap:4px;}
.btn.sm.ghost{background:transparent;color:var(--ink-4);border:0.5px solid transparent;}
.btn.sm.ghost:hover{color:var(--purple);border-color:var(--line);background:var(--bg-2);}
.btn.sm.ghost.danger:hover{color:var(--danger);border-color:var(--danger);background:transparent;}

/* ---- 主动回忆卡片 ----
   一屏一卡、问在上答案在下 —— 模仿"考试卷"而不是"聊天记录"，
   因为它要唤起的是"作答"这个动作。 */
.rv-body{margin:4px 0 22px;padding:26px 24px 22px;border:0.5px solid var(--line);
  border-radius:12px;background:var(--bg);animation:rvIn .26s cubic-bezier(.2,.7,.3,1);}
@keyframes rvIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.rv-q{font-size:17px;line-height:1.6;color:var(--ink);font-weight:500;margin-bottom:9px;}
.rv-clue{font-size:11.5px;color:var(--ink-4);margin-bottom:16px;}
.rv-clue::before{content:"";display:inline-block;width:14px;height:1px;background:var(--line);
  vertical-align:middle;margin-right:7px;}
.rv-reveal{border:0.5px solid var(--line);background:var(--bg-2);border-radius:7px;
  padding:7px 15px;font:inherit;font-size:12.5px;color:var(--ink-2);cursor:pointer;
  transition:border-color .15s,color .15s,background .15s;}
.rv-reveal:hover{border-color:var(--purple);color:var(--purple);background:var(--bg);}
.rv-reveal:focus-visible{outline:2px solid var(--purple);outline-offset:2px;}
/* 答案展开用 max-height 过渡而不是 display:none —— 高度变化能被眼睛跟到，
   这就是所谓的"motion serves meaning"。 */
.rv-a{max-height:0;overflow:hidden;opacity:0;
  transition:max-height .3s cubic-bezier(.2,.7,.3,1),opacity .22s,margin-top .3s;}
.rv-a.on{max-height:520px;opacity:1;margin-top:16px;}
.rv-ab{font-size:13.5px;line-height:1.85;color:var(--ink-2);white-space:pre-wrap;
  padding:13px 15px;border-left:2px solid var(--purple);background:var(--bg-2);border-radius:0 7px 7px 0;}
.rv-src{display:block;margin-top:10px;border:0;background:transparent;padding:0;font:inherit;
  font-size:11.5px;color:var(--ink-3);cursor:pointer;text-align:left;line-height:1.7;}
.rv-src:hover{color:var(--purple);text-decoration:underline;}
.rv-act{display:flex;gap:8px;margin-top:16px;}
.rv-btn{border:0.5px solid var(--line);background:var(--bg);border-radius:7px;padding:6px 14px;
  font:inherit;font-size:12.5px;color:var(--ink-2);cursor:pointer;transition:all .15s;}
.rv-btn:hover{border-color:var(--ink-3);color:var(--ink);}
.rv-btn.ok:hover{border-color:var(--ok);color:var(--ok);}
.rv-btn:not(.ok):hover{border-color:var(--danger);color:var(--danger);}
.rv-btn:focus-visible{outline:2px solid var(--purple);outline-offset:2px;}
.rv-tip{margin-top:12px;font-size:11.5px;color:var(--ink-4);text-align:center;}

/* ---- 回收站 ----
   刻意**不像**一个管理后台：每行只有"标题 + 多久前 + 两个动作"，
   没有表头、没有复选框、没有批量按钮 —— 回收站是一次性善后，不是日常操作。 */
.trash-list{margin-top:4px;}
.tr-item{display:flex;align-items:center;gap:10px;padding:13px 0;
  border-bottom:1px solid var(--line-2);}
.tr-item:last-child{border-bottom:0;}
.tr-info{flex:1;min-width:0;font-size:13px;color:var(--ink-2);line-height:1.5;}
.tr-sub{font-size:11px;color:var(--ink-4);margin-top:3px;}

.rsec{font-size:11px;color:var(--ink-4);letter-spacing:.3px;margin:2px 0 10px;}
.rcard{border-bottom:1px solid var(--line);padding:11px 0 12px;cursor:pointer;transition:background .12s;}
.rcard:first-of-type{padding-top:4px;}
.rcard:hover{background:var(--bg-2);}
.rcard.on{background:var(--purple-soft);border-radius:6px;padding-left:10px;padding-right:10px;
  margin:0 -10px;border-bottom-color:transparent;}
.rcard .rh{display:flex;align-items:baseline;gap:8px;margin-bottom:5px;}
.rcard .rh b{color:var(--purple);font-weight:500;font-size:12.5px;font-variant-numeric:tabular-nums;}
.rcard .rh em{font-style:normal;color:var(--ink-4);font-size:11px;flex:1;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;}
.rcard .rh .sc{color:var(--ink-3);font-size:11px;font-variant-numeric:tabular-nums;}
.rcard .rt{font-size:12.5px;color:var(--ink-2);line-height:1.72;overflow:hidden;display:-webkit-box;
  -webkit-line-clamp:3;-webkit-box-orient:vertical;}
.rcard.open .rt{-webkit-line-clamp:unset;display:block;}
.rcard .par{margin-top:8px;padding-left:10px;border-left:2px solid var(--line);font-size:12px;
  color:var(--ink-3);line-height:1.7;display:none;}
.rcard.open .par{display:block;}
/* 附录注解：正文把答案外包给图/附录时，事实在这里。发丝级紫边做点缀，不抢读。 */
.rcard .fig{margin-top:8px;padding-left:10px;border-left:2px solid var(--purple);font-size:12px;
  color:var(--ink-2);line-height:1.7;display:none;}
.rcard.open .fig{display:block;}
.rcard .fig b{display:block;font-weight:500;color:var(--purple);font-size:11.5px;margin-bottom:3px;}
.meter{height:2px;background:var(--line-2);border-radius:2px;margin-top:9px;overflow:hidden;}
.meter span{display:block;height:100%;background:var(--purple);opacity:.55;}
.rcard .src{margin-top:7px;font-size:10.5px;color:var(--ink-4);display:none;}
.rcard.open .src{display:block;}
.dbg{margin-top:22px;border-top:1px solid var(--line);padding-top:12px;}
.dbg summary{list-style:none;cursor:pointer;font-size:11.5px;color:var(--ink-3);display:flex;align-items:center;gap:7px;}
.dbg summary::-webkit-details-marker{display:none;}
.dbg summary .arw{font-size:9px;transition:transform .14s;}
.dbg[open] summary .arw{transform:rotate(90deg);}
.dbg summary:hover{color:var(--purple);}
.dbg .kv2{margin-top:10px;font-size:11.5px;color:var(--ink-2);}
.dbg .kv2 div{display:flex;justify-content:space-between;gap:12px;padding:4px 0;border-bottom:1px solid var(--line-2);}
.dbg .kv2 div:last-child{border-bottom:0;}
.dbg .kv2 span:first-child{color:var(--ink-3);flex:0 0 auto;}
.dbg .kv2 span:last-child{text-align:right;word-break:break-word;font-variant-numeric:tabular-nums;}
.dbg .tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:10px;}

/* 助手下拉浮层 */
.pop{position:fixed;z-index:60;background:#fff;border:1px solid var(--line);border-radius:8px;
  min-width:250px;padding:5px;display:none;}
.pop.open{display:block;}
.pop-i{display:block;width:100%;text-align:left;padding:8px 10px;border-radius:6px;transition:background .12s;}
.pop-i:hover{background:var(--hover);}
.pop-i.on{background:var(--purple-soft);}
.pop-i .pn{font-size:13px;font-weight:500;display:flex;align-items:center;gap:7px;}
.pop-i .pd{font-size:11.5px;color:var(--ink-3);line-height:1.6;margin-top:2px;}
.pop-head{font-size:10.5px;color:var(--ink-4);letter-spacing:.3px;padding:7px 10px 4px;}

/* ============================ 设置：左目录 + 右内容 ============================
   为什么不是一排横向 tab：12 个入口在 1280 宽里排不下，换行后既挤又和
   页面标题重复，看着像控制台。系统设置那种「左列目录 / 右列内容」一屏
   看完全部入口，而且目录常驻 —— 用户随时看得见还有哪些设置，不会以为
   「设置只有外观」而把该调的漏掉。 */
.pbody.twocol{overflow:hidden;}
.setwrap{display:flex;height:100%;min-height:0;}
.setnav{
  width:212px;flex:0 0 212px;overflow-y:auto;padding:14px 10px 26px 20px;
  border-right:0.5px solid var(--line);
}
.setnav-t{
  font-size:10.5px;color:var(--ink-4);letter-spacing:.4px;
  padding:14px 8px 5px;
}
.setnav-t:first-child{padding-top:0;}
/* 可折叠的分组标题（「开发者选项」）。它是个 <button>，所以要显式清掉浏览器样式，
   否则会变成一颗灰底圆角按钮，和上面那几个纯文字的组标题不是一套东西。 */
.setnav-t.dev{
  display:flex;align-items:center;gap:4px;width:100%;text-align:left;
  background:none;border:0;cursor:pointer;
  font-size:10.5px;color:var(--ink-4);letter-spacing:.4px;padding:14px 8px 5px;
}
.setnav-t.dev:hover{color:var(--ink-3);}
.setnav-t.dev .cv{font-style:normal;font-size:9px;width:9px;flex:0 0 9px;}
.setnav-i{
  display:block;width:100%;text-align:left;
  min-height:32px;padding:6px 9px;border-radius:8px;
  font-size:13.5px;color:var(--ink-2);transition:background .12s,color .12s;
}
.setnav-i:hover{background:var(--hover);color:var(--ink);}
.setnav-i.on{background:var(--purple-soft);color:var(--purple);font-weight:500;}
.setmain{flex:1;min-width:0;overflow-y:auto;display:flex;}
.setmain > .wrap{flex:1;min-width:0;}

/* ============================ 弹窗 ============================
   自绘遮罩，不走 Electron 的 dialog.showMessageBox：
   那个是 Windows 灰色系统框，和这套浅色界面打架，
   而且它的标题栏按钮会盖住我们自己的「应用 / 编辑」。
   官方 DeepSeek Harness 同样是自绘（DesktopUpdateDialog + 遮罩）。 */
.dlg-mask{
  position:fixed;inset:0;z-index:200;display:flex;align-items:center;justify-content:center;
  background:rgba(15,17,21,.34);padding:24px;
}
.dlg{
  position:relative;width:400px;max-width:100%;max-height:80vh;overflow-y:auto;
  background:#fff;border-radius:12px;border:0.5px solid var(--line);
  padding:22px 24px 18px;box-shadow:0 12px 40px rgba(15,17,21,.16);
}
.dlg-t{font-size:14.5px;font-weight:600;letter-spacing:.2px;padding-right:26px;}
.dlg-b{margin-top:10px;font-size:13px;color:var(--ink-2);line-height:1.85;}
.dlg-b p{margin:0 0 8px;}
.dlg-b p:last-child{margin-bottom:0;}
.dlg-ver{font-size:19px;font-weight:600;color:var(--ink);margin-bottom:8px;letter-spacing:.2px;}
.dlg-x{
  position:absolute;right:10px;top:10px;width:26px;height:26px;border-radius:7px;
  font-size:13px;color:var(--ink-3);display:flex;align-items:center;justify-content:center;
}
.dlg-x:hover{background:var(--hover);color:var(--ink);}
/* 次要按钮与主按钮之间要有间距，否则两按钮贴在一起像一块。
   gap 放在容器上而不是 margin：以后加第三个按钮（比如"稍后提醒我"）自动也有间距。 */
.dlg-f{margin-top:18px;display:flex;justify-content:flex-end;gap:8px;}

/* ---- 更新弹窗 ----
   进度条刻意做得很细（4px）且不带百分比数字动画：
   下载是等待，等待不需要被强调。数字够用就够（已经放在进度条上方）。 */
.dlg-bar{
  height:4px;border-radius:2px;background:var(--bg-3);overflow:hidden;margin:12px 0 8px;
}
.dlg-bar-fill{height:100%;width:0;background:var(--ink);border-radius:2px;transition:width .2s linear;}
.dlg-sub{font-size:12px;color:var(--ink-3);font-variant-numeric:tabular-nums;}
/* 更新说明。留白区分隔，不画边框 —— 一个段落一块底色比一堆线更吵 */
.dlg-notes{
  font-size:12.5px;color:var(--ink-2);line-height:1.8;background:var(--bg-2);
  border-radius:8px;padding:9px 11px;margin-bottom:10px;
}
/* 免安装版的提示：这是"你的版本做不到某事"，不是"出错了"。
   用底色不用红字 —— 用户没做错任何事，不该被当成错误。 */
.dlg-warn{
  font-size:12.5px;line-height:1.8;color:var(--ink-2);
  background:#fdf6e8;border-radius:8px;padding:9px 11px;margin-bottom:10px;
}
.dlg-busy{font-size:13px;color:var(--ink-3);}
/* 更新弹窗的进度百分比：字形等宽，数字跳动时不会左右抖 */
.dlg-b .dlg-ver{min-height:26px;display:flex;align-items:center;font-variant-numeric:tabular-nums;}

/* 意见反馈页 */
.fbKindWrap{margin-bottom:2px;}
#fbText{line-height:1.8;min-height:96px;}
.fbSendRow{margin-top:12px;display:flex;align-items:center;gap:9px;}

/* 头像浮层里的「退出登录」：唯一一条用警示色的项。
   不是为了吓唬人 —— 菜单里三项，它是唯一不可逆的，位置就该能一眼区分。 */
.pop-i.danger{color:var(--danger);}
.pop-i.danger:hover{background:rgba(178,59,46,.07);color:var(--danger);}

/* ============================ 知识库 ============================ */
/* 「查规则」页内的两个 tab（2026-10-10 合并页）
   视觉口径与 .tabs 一致，但独立一套：那一套带页面级 padding，
   这里在 .wrap.wide 内部，得自己控制边距。 */
.rules-tabs{display:flex;gap:2px;margin-bottom:16px;border-bottom:1px solid var(--line);}
.rules-tab{padding:8px 13px;font-size:13px;color:var(--ink-3);border-bottom:2px solid transparent;
  background:none;border-top:0;border-left:0;border-right:0;cursor:pointer;font-family:inherit;
  transition:color .12s,border-color .12s;}
.rules-tab:hover{color:var(--ink);}
.rules-tab.on{color:var(--purple);border-bottom-color:var(--purple);font-weight:500;}
.rules-body{min-height:180px;}

.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);padding:0 26px;}
.tab{padding:9px 13px;font-size:13px;color:var(--ink-3);border-bottom:2px solid transparent;
  margin-bottom:-1px;transition:color .12s,border-color .12s;}
.tab:hover{color:var(--ink);}
.tab.on{color:var(--purple);border-bottom-color:var(--purple);font-weight:500;}

.split{display:flex;gap:0;border:1px solid var(--line);border-radius:8px;overflow:hidden;min-height:520px;}
.split-l{width:236px;flex:0 0 236px;border-right:1px solid var(--line);background:var(--bg-2);
  overflow-y:auto;max-height:660px;}
.split-l .ch{
  display:block;width:100%;text-align:left;padding:9px 14px;border-bottom:1px solid var(--line-2);
  font-size:12.5px;color:var(--ink-2);transition:background .12s,color .12s;
}
.split-l .ch:hover{background:var(--hover);color:var(--ink);}
.split-l .ch.on{background:#fff;color:var(--ink);font-weight:500;border-left:2px solid var(--purple);padding-left:12px;}
.split-l .ch .cn{font-size:10.5px;color:var(--ink-4);margin-right:6px;font-variant-numeric:tabular-nums;}
.split-r{flex:1;min-width:0;overflow-y:auto;max-height:660px;}
.item{padding:11px 16px;border-bottom:1px solid var(--line-2);}
.item:last-child{border-bottom:0;}
.item .ih{display:flex;align-items:baseline;gap:9px;margin-bottom:3px;}
.item .ih b{color:var(--purple);font-size:12.5px;font-weight:500;font-variant-numeric:tabular-nums;flex:0 0 auto;}
.item .ih .tag{font-size:10.5px;}
.item .ih .d{font-size:10.5px;color:var(--ink-4);margin-left:auto;white-space:nowrap;}
.item .it{font-size:13px;color:var(--ink-2);line-height:1.75;}
.item.d1 .it{color:var(--ink);font-weight:500;}
.item .par{font-size:11.5px;color:var(--ink-4);margin-top:4px;}

.searchbox{display:flex;gap:9px;margin-bottom:14px;}
.inp{border:1px solid var(--line);border-radius:7px;padding:8px 13px;font-size:13.5px;
  flex:1;min-width:0;outline:0;transition:border-color .14s;background:#fff;}
.inp:focus{border-color:var(--purple);}
.inp.sm{padding:6px 11px;font-size:12.5px;}

/* 检索测试结果 */
.hit{border:1px solid var(--line);border-radius:8px;padding:12px 15px;margin-bottom:9px;background:#fff;}
.hit.top{border-color:var(--purple-line);}
.hit .hh{display:flex;align-items:center;gap:10px;margin-bottom:5px;}
.hit .rk{font-size:11px;color:var(--ink-4);font-variant-numeric:tabular-nums;flex:0 0 auto;
  width:20px;text-align:right;}
.hit .id{color:var(--purple);font-size:12.5px;font-weight:500;font-variant-numeric:tabular-nums;}
.hit .ch{font-size:11.5px;color:var(--ink-4);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.hit .sc{font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums;white-space:nowrap;}
.hit .tx{font-size:13px;color:var(--ink-2);line-height:1.75;}
.hit .mt{height:2px;background:var(--line-2);border-radius:2px;margin-top:9px;overflow:hidden;}
.hit .mt span{display:block;height:100%;background:var(--purple);opacity:.5;}

.gauge{display:flex;align-items:center;gap:10px;font-size:12.5px;padding:11px 14px;
  border:1px solid var(--line);border-radius:7px;background:var(--bg-2);margin-bottom:14px;}
.gauge .g1{flex:1;}
.gauge b{font-weight:600;}

/* ============================ 响应式 ============================ */
.scrim{display:none;position:fixed;inset:0;background:rgba(0,0,0,.16);z-index:25;}
@media (max-width:1280px){
  /* 窄屏：右栏变成抽屉，从右侧滑出 / 收回。
     这里 `.hide` 的语义从「宽度归零」改成「推到屏幕外」——
     固定定位下宽度必须保持 326，否则滑出来的是个零宽的壳。
     ⚠️ top 必须让开标题栏高度（网页版该变量为 0，等于不变）：
        标题栏是 absolute/z-index:40 的不透明条，右栏是 fixed/z-index:30，
        `top:0` 会让**面板头（来源/笔记 标签 + 收起按钮）整条被它盖住** ——
        表现是"看得见内容、点不到按钮"。客户端窗口宽 1280，正好落在这个断点里，
        所以这条不是理论风险，是必现的。 */
  .rail{position:fixed;right:0;top:var(--titlebar-h);bottom:0;z-index:30;background:#fff;
    width:326px;flex:0 0 326px;border-left:1px solid var(--line);
    transform:translateX(100%);transition:transform .22s ease;}
  .rail:not(.hide){transform:none;}
  .rail.hide{width:326px;flex:0 0 326px;border-left-color:var(--line);transform:translateX(100%);}
}
@media (max-width:1000px){
  .nav{position:fixed;left:0;top:0;bottom:0;z-index:40;background:#fff;
    transform:translateX(-100%);transition:transform .2s ease;}
  .nav.open{transform:none;}
  .phead .burger{display:inline-flex;}
  .tabs,.phead{padding-left:15px;padding-right:15px;}
  .wrap{padding:20px 15px 44px;}
  .stream,.composer{padding-left:15px;padding-right:15px;}
  .split{flex-direction:column;}
  .split-l{width:100%;flex:0 0 auto;max-height:220px;border-right:0;border-bottom:1px solid var(--line);}
  .msg.user .bub{max-width:88%;}
  .kv .r{flex-direction:column;gap:3px;}
  .kv .k{flex:0 0 auto;}
}

/* ============================ 疑问库 ============================ */
.cur-bar{display:flex;align-items:center;gap:14px;margin-bottom:14px;}
.cur-stats{flex:1;font-size:13px;color:var(--ink-2);}
.cur-stats b{color:var(--purple);font-variant-numeric:tabular-nums;}

.cur-form{padding:16px 18px;}
.fl{display:block;font-size:12px;color:var(--ink-3);margin-bottom:12px;}
.fl input,.fl textarea{
  display:block;width:100%;margin-top:6px;border:1px solid var(--line);border-radius:7px;
  padding:8px 13px;font-size:13.5px;color:var(--ink);background:#fff;resize:vertical;
  font-family:inherit;line-height:1.7;
}
.fl input:focus,.fl textarea:focus{outline:none;border-color:var(--purple);}
.row2{display:flex;gap:14px;flex-wrap:wrap;}
.row2 .fl{flex:1;min-width:220px;}
.cur-tip{font-size:12px;line-height:1.75;margin-top:2px;}

.cur-item{border-bottom:1px solid var(--line-2);}
.cur-item:last-child{border-bottom:0;}
.cur-h{padding:13px 18px;cursor:pointer;transition:background .12s;}
.cur-h:hover{background:var(--bg-2);}
.cur-q{font-size:13.5px;color:var(--ink);margin-bottom:6px;}
.cur-m{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11.5px;}
.cur-b{padding:0 18px 15px;border-top:1px solid var(--line-2);}
.cur-a{margin-top:13px;font-size:13.5px;line-height:1.85;color:var(--ink);white-space:pre-wrap;}
.cur-kw{margin-top:10px;font-size:12px;color:var(--ink-3);display:flex;align-items:center;gap:7px;flex-wrap:wrap;}
.cur-kw .kw{border:1px solid var(--line);border-radius:4px;padding:1px 7px;font-size:11.5px;color:var(--ink-2);}
.cur-acts{margin-top:14px;display:flex;align-items:center;gap:9px;}
.btn.danger{color:var(--danger);border-color:transparent;padding:6px 10px;}
.btn.danger:hover:not(:disabled){border-color:var(--danger);color:var(--danger);}

.tag{display:inline-flex;align-items:center;border-radius:4px;padding:1px 8px;font-size:11.5px;}
.tag.t-own{background:var(--purple-soft);color:var(--purple);}
.tag.t-web{background:#fdf8ec;color:#a8730f;}
.dim{color:var(--ink-3);}

/* 对话页里的 Owner 裁定标记 */
.cur-note{margin-top:11px;padding-top:10px;border-top:1px solid var(--line-2);
  display:flex;align-items:center;gap:9px;flex-wrap:wrap;font-size:11.5px;}

/* 「我来裁定」入口 */
.own-ask{margin-top:11px;display:flex;align-items:center;gap:12px;font-size:12px;}

/* ============================ 联网兜底区 ============================ */
/* 刻意用警示底色 + 独立边框，和 citesRow（规则引用）明确区分：
   规则引用 = 可溯源的一手依据；这里 = 机器抓来的网络内容，二手。 */
.web-box{margin-top:13px;border:1px solid #e8dcc0;background:#fdfaf2;border-radius:7px;padding:12px 14px;}
.web-h{display:flex;align-items:center;gap:8px;font-size:12.5px;color:#8a6410;flex-wrap:wrap;}
.web-warn{font-size:13px;}
.web-link{margin-left:auto;font-size:12px;color:#8a6410;border-bottom:1px solid rgba(138,100,16,.3);}
.web-link:hover{color:var(--purple);border-color:var(--purple);}
.web-list{margin-top:9px;display:flex;flex-direction:column;gap:7px;}
.web-snip{font-size:12.5px;line-height:1.75;color:var(--ink-2);padding-left:11px;
  border-left:2px solid #e8dcc0;}
.web-tip{margin-top:10px;font-size:11.5px;line-height:1.7;color:#9a7a2e;}

/* toast */
.toast{
  position:fixed;left:50%;bottom:34px;transform:translate(-50%,10px);
  background:var(--ink);color:#fff;font-size:13px;padding:9px 18px;border-radius:7px;
  max-width:min(560px,86vw);line-height:1.6;opacity:0;pointer-events:none;
  transition:opacity .18s,transform .18s;z-index:90;
}
.toast.on{opacity:.95;transform:translate(-50%,0);}
/* ⚠️ 有「撤销」浮条时把 toast 抬高（2026-10-07 修）。
   两者原本同坐标（bottom:34px / left:50%）且**都不透明** ⇒
   删一条笔记后 5 秒内点「导出」，"已导出 N 条"那个 toast
   被浮条严严实实盖住，用户完全看不到反馈 —— 不是不好看，是信息丢了。 */
body:has(.undo-bar.on) .toast{bottom:88px;}

/* 「撤销」浮条：贴在 toast 的位置，但**它可点**，所以 pointer-events 必须开。
   视觉上刻意比 toast 轻一档（白底 + 发丝边，不是一块黑）——
   因为它不是"通知你发生了什么"，而是"给你一个还没过期的机会"。 */.undo-bar{position:fixed;left:50%;bottom:34px;transform:translate(-50%,10px);
  display:flex;align-items:center;gap:14px;max-width:min(560px,86vw);
  background:var(--bg);color:var(--ink);font-size:12.5px;
  padding:9px 10px 9px 17px;border:0.5px solid var(--line);border-radius:8px;
  box-shadow:0 6px 24px rgba(0,0,0,.1);          /* 唯一一处阴影：浮层需要脱离文档流 */
  opacity:0;pointer-events:none;z-index:91;
  transition:opacity .2s,transform .2s cubic-bezier(.2,.7,.3,1);}
.undo-bar.on{opacity:1;transform:translate(-50%,0);pointer-events:auto;}
.undo-t{line-height:1.6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.undo-b{flex:0 0 auto;border:0;background:transparent;padding:4px 10px;border-radius:6px;
  font:inherit;font-size:12.5px;color:var(--purple);cursor:pointer;transition:background .15s;}
.undo-b:hover{background:var(--purple-soft);}
.undo-b:focus-visible{outline:2px solid var(--purple);outline-offset:1px;}

/* ==================== 外观偏好（字号 / 技术细节 / 紧凑度） ====================
   这些开关的唯一目的：**让不懂术语的人可以不看见术语。**
   字号只放大"内容区"（正文、条款原文、设置项），不动侧栏和顶栏 ——
   导航骨架是固定的，放大它只会把内容挤掉。 */
body[data-size="lg"] .pbody,
body[data-size="lg"] .rail{font-size:16px;}
body[data-size="lg"] .pbody .md p,
body[data-size="lg"] .pbody .md li{font-size:16.5px;line-height:1.85;}
body[data-size="lg"] .pbody .kv .v{font-size:15px;}
body[data-size="lg"] .pbody .rt,
body[data-size="lg"] .rail .rt{font-size:15px;line-height:1.8;}
/* 笔记是用户自己写的字，跟条款原文一样属于"内容区"，跟着字号档位一起放大。 */
body[data-size="lg"] .rail .nt-t,
body[data-size="lg"] .rail .nt-b{font-size:15px;line-height:1.85;}
body[data-size="lg"] .notes-page .nt-t,
body[data-size="lg"] .notes-page .nt-b{font-size:15px;line-height:1.85;}
body[data-size="lg"] .wrap{font-size:15.5px;}

/* 关掉 = 把 class="tech" 的元素（相关度分数、耗时、我理解成、检索详情）整体隐藏 */
body[data-tech="0"] .tech{display:none !important;}

/* 紧凑排版：压掉留白，一屏多看一点。默认关。 */
body[data-dense="1"] .wrap{padding-top:18px;padding-bottom:34px;}
body[data-dense="1"] .sec{margin-bottom:16px;}
body[data-dense="1"] .card-b{padding:12px 15px;}
body[data-dense="1"] .msg.bot .md p{margin-bottom:7px;}

/* ---- 外观设置页的组件 ---- */
/* 分段选择（字号） */
.seg{display:inline-flex;border:1px solid var(--line);border-radius:7px;overflow:hidden;}
.seg button{
  padding:8px 22px;font-size:13px;color:var(--ink-2);background:#fff;
  border-right:1px solid var(--line);transition:background .12s,color .12s;
}
.seg button:last-child{border-right:0;}
.seg button:hover{background:var(--bg-2);}
.seg button.on{background:var(--purple-soft);color:var(--purple);font-weight:500;}
/* 让两个按钮分别长成"标准"和"大"的视觉大小，所见即所得 */
.seg button.s2{font-size:15px;}

/* 一行开关 */
.opt{
  display:flex;align-items:flex-start;gap:16px;
  padding:13px 0;border-bottom:1px solid var(--line-2);
}
.opt:first-child{padding-top:0;}
.opt:last-child{border-bottom:0;padding-bottom:0;}
.opt .ov{flex:1;min-width:0;}
.opt .on{font-size:13.5px;font-weight:500;margin-bottom:3px;}
.opt .od{font-size:12.5px;color:var(--ink-3);line-height:1.7;}
.opt .od b{color:var(--ink-2);font-weight:600;}
.sw{
  flex:0 0 38px;width:38px;height:22px;border-radius:11px;background:var(--bg-3);
  border:1px solid var(--line);position:relative;cursor:pointer;margin-top:2px;
  transition:background .16s,border-color .16s;
  /* 它现在是 <button>（2026-10-07，为键盘可达）⇒ 必须清掉按钮默认外观，
     否则浏览器会加背景、内边距、字体与 2px outset 边框，样子全变了。 */
  padding:0;appearance:none;-webkit-appearance:none;font:inherit;
}
.sw:focus-visible{outline:2px solid var(--purple);outline-offset:2px;}
.sw i{
  position:absolute;left:2px;top:2px;width:16px;height:16px;border-radius:50%;
  background:#fff;border:1px solid var(--line);transition:left .16s;
}
.sw.on{background:var(--purple);border-color:var(--purple);}
.sw.on i{left:18px;border-color:var(--purple);}

/* 步骤条（怎么用） */
.steps{display:flex;flex-direction:column;gap:15px;}
.stp{display:flex;gap:12px;align-items:flex-start;}
.stp > b{
  flex:0 0 21px;width:21px;height:21px;border-radius:50%;
  background:var(--purple-soft);color:var(--purple);
  display:flex;align-items:center;justify-content:center;font-size:12px;margin-top:2px;
}
.stp .sh{font-size:13.5px;font-weight:600;margin-bottom:3px;}
.stp .sd{font-size:12.5px;color:var(--ink-2);line-height:1.75;}
.stp .sd b{color:var(--ink);font-weight:600;}

/* 帮助页底部的入口网格 */
.megrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px;}
.meitem{
  text-align:left;border:1px solid var(--line);border-radius:7px;background:#fff;
  padding:11px 13px;transition:border-color .12s;
}
.meitem:hover{border-color:var(--purple);}
.meitem .mt2{font-size:13px;font-weight:500;margin-bottom:2px;}
.meitem .md2{font-size:11.5px;color:var(--ink-3);line-height:1.6;}

/* 右栏无引用时的空态：只说事实，不解释自己 */
.rail-empty{color:var(--ink-3);font-size:12.5px;line-height:1.9;padding:4px 2px;}
.rail-empty b{font-weight:500;color:var(--ink-2);}

@media (max-width:720px){
  .row2 .fl{min-width:0;}
  .web-link{margin-left:0;width:100%;}
  .me-pop{min-width:0;width:calc(100vw - 24px);max-width:none;}
}
.rv-bar{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--ink-4);letter-spacing:.6px;margin-bottom:14px;}
.rv-quit{margin-left:auto;border:0;background:transparent;padding:2px 6px;border-radius:5px;
  font:inherit;font-size:11px;color:var(--ink-4);cursor:pointer;letter-spacing:0;transition:color .15s,background .15s;}
.rv-quit:hover{color:var(--purple);background:var(--purple-soft);}
.rv-quit:focus-visible{outline:2px solid var(--purple);outline-offset:1px;}

/* ==========================================================================
   练规则（练习器）· 2026-10-12
   --------------------------------------------------------------------------
   ⚠️ 色值只用既有变量（--ok / --danger / --purple / --line …），
      不新造色 —— 新造一个就会和别处不一致，且 next 换肤要改两处。
   ⚠️ "答对/答错"两个状态**不能只靠颜色**区分（色盲用户、以及打印/灰度场景）：
      文字本身已经写明「答对了」/「不对 —— 正确答案是…」，颜色只是强化。
   ========================================================================== */
.prac-bar{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--ink-4);
  letter-spacing:.6px;margin-bottom:14px;}
.prac-score{margin-left:auto;}
.prac-score b,.prac-bar b{color:var(--ink-2);font-variant-numeric:tabular-nums;}
.prac-prompt{white-space:pre-wrap;line-height:1.75;font-size:15px;color:var(--ink);
  padding:16px 18px;background:var(--bg-2);border-radius:10px;margin-bottom:16px;}
.prac-opts{display:flex;flex-direction:column;gap:8px;}
.prac-opt{display:block;width:100%;text-align:left;padding:11px 14px;border-radius:9px;
  border:1px solid var(--line);background:var(--bg);color:var(--ink);font:inherit;
  font-size:13.5px;line-height:1.6;cursor:pointer;transition:border-color .15s,background .15s;}
.prac-opt:hover:not(:disabled){border-color:var(--purple-line);background:var(--purple-soft);}
.prac-opt:focus-visible{outline:2px solid var(--purple);outline-offset:1px;}
.prac-opt:disabled{cursor:default;opacity:.72;}
.prac-opt.ok{border-color:var(--ok);background:rgba(46,125,91,.07);opacity:1;}
.prac-opt.no{border-color:var(--danger);background:rgba(178,59,46,.06);opacity:1;}
.prac-fb{margin-top:18px;padding:14px 16px;border-radius:10px;border:1px solid var(--line);}
.prac-fb.ok{border-color:var(--ok);background:rgba(46,125,91,.05);}
.prac-fb.no{border-color:var(--danger);background:rgba(178,59,46,.04);}
.prac-fb-h{font-size:13.5px;font-weight:600;color:var(--ink);margin-bottom:8px;}
.prac-fb-t{font-size:12px;color:var(--ink-3);margin-bottom:6px;}
.prac-clauses{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px;}
.prac-clause{border:1px solid var(--line);background:var(--bg);border-radius:7px;
  padding:5px 10px;font:inherit;font-size:12px;color:var(--ink-2);cursor:pointer;
  transition:border-color .15s,color .15s;}
.prac-clause:hover{border-color:var(--purple-line);color:var(--purple);}
.prac-clause:focus-visible{outline:2px solid var(--purple);outline-offset:1px;}
.prac-done{padding:22px 20px;border:1px solid var(--line);border-radius:10px;text-align:center;}
.prac-done-h{font-size:16px;font-weight:600;color:var(--ink);margin-bottom:8px;
  font-variant-numeric:tabular-nums;}
.prac-done .btn{margin-top:14px;}

/* ⚡ 流式答案的容器（2026-10-13 加）。
   ⚠️ 它替代的是 `.loading`（"正在理解你的问题"），
      所以必须**保留与正文一致的排版**，否则字一出来会跳一下。
   ⚠️ `white-space: pre-wrap`：模型返回的换行要真的换行 ——
      否则整段会挤成一行（实测过）。 */
.streaming{white-space:pre-wrap;word-break:break-word;line-height:1.75;color:var(--tx);font-size:15px}
