:root {
  --bg: #14161a;
  --bg-panel: #1d2026;
  --bg-card: #242830;
  --border: #333845;
  --text: #e6e8ec;
  --text-dim: #9aa0ad;
  --accent: #4c8dff;
  --green: #3fbf7f;
  --red: #e25555;
  --amber: #d9a03f;
    --radius: 10px;
    /* AI 正文的行宽上限（2026-10-15 版式改版）。用 ch 而不是百分比：
       百分比在手机上过窄、宽屏上又会拉到一百多字符一行，两头都不好读。
       68ch ≈ 70 个英文字符，落在公认的舒适区间 45–75 内。想调只改这一个值。 */
    --ai-line: 68ch;
  }

/* 全局隐藏兜底。
   坑的来历：本项目一直靠「逐个写 #id.hidden { display:none }」来隐藏元素，
   因为 #id（1-0-0）会压过 .hidden（0-1-0）。但漏写一个就是一整块黑幕盖在页面上——
   页面看起来只是灰的，点什么都没反应，比直接报错难查十倍。
   这里补一条带 !important 的全局规则当安全网，新元素只要加 .hidden 就一定藏得住。 */
.hidden { display: none !important; }

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
  font-size: 14px;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-panel);
}

header h1 { font-size: 17px; font-weight: 600; }
.session-bar { display: flex; align-items: center; gap: 12px; }
#session-status { color: var(--text-dim); }

button {
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  border-radius: var(--radius);
  padding: 7px 16px;
  cursor: pointer;
  font-size: 13px;
}
button:hover { border-color: var(--accent); }
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
button:disabled { opacity: 0.45; cursor: not-allowed; }

/* 顶栏“管理”入口是链接，需显式套用按钮外观 */
.session-bar a#btn-admin {
  display: inline-block;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  border-radius: var(--radius);
  padding: 7px 16px;
  font-size: 13px;
  line-height: 18px;
  text-decoration: none;
}
.session-bar a#btn-admin:hover { border-color: var(--accent); color: var(--accent); }
/* 目标词面板展开时，顶栏入口高亮 */
.session-bar button.on { border-color: var(--accent); color: var(--accent); }

/* ---------- 我的弹窗：导入折叠区 ---------- */
.import-toggle {
  width: 100%;
  text-align: left;
  font-size: 13px;
  padding: 8px 10px;
  margin-bottom: 10px;
  background: var(--bg-card);
  color: var(--text);
}
.import-toggle:hover { border-color: var(--accent); }
.import-box { margin-bottom: 14px; }
.import-box.hidden { display: none; }
.import-box textarea, .import-box input {
  width: 100%;
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 10px;
  font-size: 13px;
  margin-bottom: 8px;
  font-family: inherit;
}
.import-box textarea { height: 70px; resize: vertical; }
#import-result { margin-left: 10px; color: var(--text-dim); }

/* ---------- 历史对话 ---------- */
.sess-item {
  padding: 8px 10px;
  margin-bottom: 6px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.sess-item:hover { border-color: var(--accent); }
.sess-item.current { border-color: var(--accent); }
.sess-item .s-prev { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sess-item .s-meta { font-size: 11px; color: var(--text-dim); margin-top: 3px; }
.sess-item .badge { margin-left: 6px; }
.sess-item .badge.done { color: var(--green); border-color: var(--green); }

main {
  flex: 1;
  display: flex;
  gap: 12px;
  padding: 0 18px 14px;
  min-height: 0;
}

#stack-panel {
  width: 250px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
  overflow-y: auto;
}
#stack-panel h2 { font-size: 13px; font-weight: 500; color: var(--text-dim); margin-bottom: 10px; }
.stack-empty {
  display: none;
  margin-top: 24px;
  text-align: center;
  font-size: 12px;
  color: var(--text-dim);
  line-height: 2;
}
.stack-empty span { font-size: 11px; opacity: 0.75; }
#stack-done-wrap.hidden { display: none; }
#stack-done-wrap h2 { margin-top: 14px; }
#stack-done { display: flex; flex-wrap: wrap; gap: 5px; }
.done-chip {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 9px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text-dim);
  cursor: pointer;
}
.done-chip:hover { color: var(--text); border-color: var(--accent); }
.done-hint { font-size: 10px; color: var(--text-dim); opacity: 0.7; margin-top: 6px; }
.hist-title { margin-top: 16px; padding-top: 12px; border-top: 1px dashed var(--border); }
.side-sess {
  padding: 6px 8px;
  margin-bottom: 5px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
}
.side-sess:hover { border-color: var(--accent); }
.side-sess.current { border-color: var(--accent); }
.side-sess .ss-prev {
  font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-sess .ss-meta { font-size: 10px; color: var(--text-dim); margin-top: 2px; }
#stack-list, #word-list { list-style: none; }
#stack-list li, #word-list li {
  padding: 8px 10px;
  margin-bottom: 6px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
#stack-list li:hover, #word-list li:hover { border-color: var(--accent); }
#stack-list li .lemma, #word-list li .lemma { font-weight: 600; font-size: 13px; }
#stack-list li .meta, #word-list li .meta { display: flex; justify-content: space-between; margin-top: 4px; font-size: 11px; color: var(--text-dim); }
#stack-list li .bar, #word-list li .bar { height: 4px; background: #333; border-radius: 2px; margin-top: 5px; overflow: hidden; }
#stack-list li .bar i, #word-list li .bar i { display: block; height: 100%; background: var(--accent); }
#word-list li.graduated { border-color: var(--green); }
#word-list li.graduated .lemma::after { content: " ✓"; color: var(--green); }
.badge { font-size: 10px; padding: 1px 6px; border-radius: 8px; background: var(--bg); border: 1px solid var(--border); }
.badge.due { color: var(--amber); border-color: var(--amber); }

#chat-panel {
  position: relative; /* 给 #btn-jump 当定位父级（不能给 chat-box 加滚动容器外的定位） */
  flex: 1;
  display: flex;
  flex-direction: column;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-width: 0;
}

#chat-box { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 20px; }

/* 【2026-10-15 版式改版】AI 回复不再装气泡。
   原先双方都用气泡 + max-width:78%，气泡的 padding/边框再吃掉一圈宽度，手机上
   一行只剩三十来字符，读起来是碎的；拜 ChatGPT/Claude/Gemini 所赐的行业做法是：
   气泡只留给**用户**，AI 回复是全宽正文，角色靠对齐和间距区分，行宽由 ch 锁定。
   注意下面这条 max-width 是给双方兜底的默认值，具体情况在各自的类里覆盖。 */
.msg { max-width: 78%; padding: 10px 14px; border-radius: var(--radius); line-height: 1.65; white-space: pre-wrap; font-size: var(--font-chat, 14px); }
.msg.user { align-self: flex-end; background: var(--accent); color: #fff; border-bottom-right-radius: 3px; max-width: min(62%, 520px); }
.msg.ai {
  align-self: stretch;   /* 整行都是它的，正文宽度交给 --ai-line 控制 */
  max-width: 100%;
  background: transparent;
  border: none;
  padding: 0 2px;
  border-radius: 0;
}
/* AI 回复里的每一块都跟正文同宽：不同宽的话，短消息前面会显得左边重、右边空一大片。
   .thinking 是思考面板、.rewrites 是「换个说法」，它们通过 innerHTML 注入，
   与 .reply / .notes 平级，所以统一按子元素来限宽。 */
.msg.ai > .reply, .msg.ai > .notes, .msg.ai > .rewrites,
.msg.ai > .thinking, .msg.ai > .empty-hint {
  max-width: var(--ai-line);
}
.msg.ai > .reply { line-height: 1.78; }   /* 行宽变宽了，行距要跟着松一点，否则贴太紧 */
.msg.ai > .notes, .msg.ai > .rewrites { margin-top: 10px; }
.msg .msg-tools { margin-top: 6px; text-align: right; }
/* AI 的工具条（朗读/换个说法）改成左对齐并跟正文同宽：右对齐会飘到屏幕边上，
   跟正文脱开——而这条工具条本来就是针对这段正文的。 */
.msg.ai .msg-tools { margin-top: 10px; text-align: left; max-width: var(--ai-line); }
.msg .msg-tools button { padding: 2px 8px; font-size: 11px; border-radius: 6px; }

.msg .target {
  color: var(--amber);
  font-weight: 600;
  cursor: pointer;
  border-bottom: 1px dashed var(--amber);
}
.msg .notes { margin-top: 8px; border-top: 1px dashed var(--border); padding-top: 6px; font-size: 12px; }
.note { margin-top: 4px; color: var(--text-dim); }
.note .ok { color: var(--green); font-weight: 600; }
.note .bad { color: var(--red); font-weight: 600; }

.msg .correction {
  margin-top: 8px;
  padding: 8px 10px;
  background: rgba(226, 85, 85, 0.08);
  border: 1px solid rgba(226, 85, 85, 0.35);
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--text);
}
.msg .correction .c-badge {
  color: var(--red);
  font-weight: 600;
  margin-right: 6px;
}
/* 内联 diff：错误红字+删除线就地划掉，紧接绿色正确表达 */
.msg .correction .cx-del {
  color: var(--red);
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
}
.msg .correction .cx-add {
  color: var(--green);
  font-weight: 600;
  margin-left: 4px;
}
.msg .correction .cx-ins {
  color: var(--text-dim);
  font-size: 10px;
  border: 1px dashed var(--text-dim);
  border-radius: 3px;
  padding: 0 2px;
}
/* 纠错挂在用户气泡里（用户拍板：改的是他写的句子，就贴着原句看）。
   用户气泡是蓝底白字，直接套上面那套淡色板会糊成一片，这里换成中性卡片底，
   红删绿增与 amber chip 全部沿用原配色，深浅主题都不用改。 */
.msg.user .correction {
  background: var(--bg-card);
  border-color: rgba(226, 85, 85, 0.45);
  color: var(--text);
}
.msg.user .correction .c-badge { color: var(--red); }
.msg.user .correction .cx-del { color: var(--red); }
.msg.user .correction .cx-add { color: var(--green); }
.msg.user .correction .cx-ins { color: var(--text-dim); border-color: var(--text-dim); }
.msg.user .correction .cx-points-label { color: var(--amber); }
.msg.user .correction .cx-chip {
  color: var(--amber);
  background: rgba(217, 160, 63, 0.12);
  border-color: rgba(217, 160, 63, 0.4);
}

/* 薄弱知识点：amber chip 标签行 */
.msg .correction .cx-points {
  margin-top: 6px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}
.msg .correction .cx-points-label {
  color: var(--amber);
  font-size: 11px;
  margin-right: 2px;
}
.msg .correction .cx-chip {
  font-size: 11px;
  color: var(--amber);
  background: rgba(217, 160, 63, 0.12);
  border: 1px solid rgba(217, 160, 63, 0.4);
  border-radius: 999px;
  padding: 1px 8px;
}

/* AI 回复排版系统：结构化块级元素，间距节奏以 8px 为基准 */
.msg.ai { max-width: 88%; white-space: normal; }
/* AI 消息模板是多行缩进的 HTML，pre-wrap 会把每个换行渲染成一行空白——
   「换个说法」列表被撑出大片空隙就是这个原因。气泡里的结构化内容一律按普通空白折叠；
   用户的纯文本消息（.msg.user）保留 pre-wrap，换行照常显示。 */
.msg .reply { white-space: normal; line-height: 1.75; }
/* 流式输出打字光标 */
.cursor {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 2px;
  vertical-align: -0.15em;
  background: var(--accent);
  animation: cursor-blink 1s steps(1) infinite;
}
@keyframes cursor-blink { 50% { opacity: 0; } }

/* 思考过程（reasoning_content）折叠区：正文首字前那十几秒，屏幕上总得有点东西。
   默认是展开的——用户正在等，就是要给他看这个过程；正文一到由 JS 自动折叠。 */
.msg.ai .thinking {
  margin: 0 0 8px;
  border-left: 2px solid rgba(255, 255, 255, 0.22);
  padding: 2px 0 2px 10px;
}
.msg.ai .thinking > summary {
  cursor: pointer;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
  list-style: none;
}
.msg.ai .thinking > summary::-webkit-details-marker { display: none; }
.msg.ai .thinking > summary::before { content: "▸ "; }
.msg.ai .thinking[open] > summary::before { content: "▾ "; }
.msg.ai .thinking .thinking-body {
  margin-top: 6px;
  max-height: 9em;
  overflow-y: auto;
  font-size: 12.5px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.62);
  white-space: pre-wrap;
  word-break: break-word;
}
.msg .reply p { margin: 7px 0; }
.msg .reply p:first-child { margin-top: 0; }
.msg .reply p:last-child { margin-bottom: 0; }
.msg .reply strong { color: #fff; font-weight: 600; }
.msg .reply em { color: var(--text); }

.msg .reply .md-h { font-weight: 600; margin: 14px 0 6px; line-height: 1.4; }
.msg .reply .md-h:first-child { margin-top: 2px; }
.msg .reply .md-h1 { font-size: 15.5px; }
.msg .reply .md-h2 { font-size: 14.5px; }
.msg .reply .md-h3 { font-size: 13.5px; }

.msg .reply ul, .msg .reply ol { margin: 6px 0; padding-left: 22px; }
.msg .reply li { margin: 3px 0; line-height: 1.7; }
.msg .reply li::marker { color: var(--text-dim); }

.msg .reply .md-quote {
  border-left: 3px solid var(--accent);
  background: rgba(76, 141, 255, 0.07);
  border-radius: 0 6px 6px 0;
  padding: 6px 12px;
  margin: 8px 0;
  color: var(--text-dim);
  line-height: 1.7;
}
.msg .reply .md-quote + .md-quote { margin-top: -6px; border-top-left-radius: 0; }

.msg .reply hr { border: none; border-top: 1px solid var(--border); margin: 12px 0; }

.msg .reply code {
  background: rgba(76, 141, 255, 0.12);
  border: 1px solid rgba(76, 141, 255, 0.25);
  border-radius: 4px;
  padding: 0 4px;
  font-size: 12.5px;
  font-family: Consolas, "Courier New", monospace;
}
.msg .reply pre {
  background: #16181d;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  margin: 10px 0;
  overflow-x: auto;
  white-space: pre;
}
.msg .reply pre code {
  background: none;
  border: none;
  padding: 0;
  font-size: 12.5px;
  line-height: 1.65;
}

/* 难度档切换条（输入框上方）：仅影响英文回复难度 */
#diff-bar {
  display: flex;
  gap: 6px;
  padding: 10px 12px 0;
  border-top: 1px solid var(--border);
}
.diff-btn {
  background: var(--bg-card);
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 14px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.diff-btn:hover { color: var(--text); border-color: var(--accent); }
.diff-btn.on {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}
/* 底部输入行：输入框吃掉剩余宽度，两个按钮按内容宽度排在右边。
   align-items:flex-end 是关键——#chat-input 已经是多行 textarea（2026-10-15 改），
   用 stretch 会把发送按钮拉成跟输入框一样高（写三行字时按钮变成一根长条）。 */
#input-bar {
  display: flex;
  gap: 10px;
  padding: 12px;
  border-top: 1px solid var(--border);
  align-items: flex-end;
}

/* ---------- 思考模式开关【2026-10-15 停用，整块注释保留】 ----------
   用户实测定案：开思考什么问题都没有、关思考一堆问题，主调用回到「固定开思考」，
   前端的关思考入口不再提供。想重启该特性时取消本块注释，并同步放开：
   index.html 的 #btn-think、app.js 的 renderThinkingToggle / initThinkingToggle
   与请求体里的 thinking 透传、后端 ai.main_plain_text。
   原说明：圆角胶囊，跟难度档那排 .diff-btn 同一套视觉语言（同圆角、同字号、同过渡），
   只是配色走琥珀色——难度是"怎么回复"，思考是"要不要先想"，别混成一类。
   图标同时从 ◍ 变 ◌（实心/空心），色弱用户也能分辨。

.toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--bg-card);
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 14px;
  font-size: 12px;
  font-family: inherit;
  line-height: 20px;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.toggle-btn:hover { color: var(--text); border-color: var(--amber); }
.toggle-btn.on {
  color: #14161a;
  background: var(--amber);
  border-color: var(--amber);
}
.toggle-btn.on .tb-icon { font-weight: 700; }
.toggle-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  color: var(--text-dim);
  background: var(--bg-card);
  border-color: var(--border);
}
.toggle-btn:disabled:hover { color: var(--text-dim); border-color: var(--border); }
---------- 思考模式开关 结束 ---------- */

/* ---------- 句式推荐：输入框上方折叠区 ---------- */
#expr-bar {
  border-top: 1px solid var(--border);
  background: rgba(76, 141, 255, 0.04);
}
#expr-bar.hidden { display: none; }
#expr-toggle {
  padding: 7px 14px;
  font-size: 12px;
  color: var(--accent);
  cursor: pointer;
  user-select: none;
}
#expr-toggle:hover { background: rgba(76, 141, 255, 0.08); }
#expr-list { padding: 0 14px 10px; }
#expr-list.hidden { display: none; }
.expr-item {
  margin-top: 6px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-card);
  cursor: pointer;
  transition: border-color 0.15s;
}
.expr-item:hover { border-color: var(--accent); }
.expr-tpl {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  font-family: "Consolas", "Courier New", monospace;
}
.expr-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; }
.expr-note { font-size: 11px; color: var(--text-dim); line-height: 1.6; }
.expr-fill { font-size: 11px; color: var(--accent); margin-left: auto; }
.expr-empty { padding: 6px 0; font-size: 12px; color: var(--text-dim); line-height: 1.6; }
/* 熟练等级徽标：0 生疏（给得多）→ 3 掌握（挖得狠），颜色由冷到暖 */
.expr-stage {
  font-size: 11px;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-dim);
  white-space: nowrap;
}
.expr-stage.s0 { color: #6ea8fe; border-color: rgba(110, 168, 254, 0.5); }
.expr-stage.s1 { color: #4cd4a0; border-color: rgba(76, 212, 160, 0.5); }
.expr-stage.s2 { color: #ffc86b; border-color: rgba(255, 200, 107, 0.5); }
.expr-stage.s3 { color: #ff8f6b; border-color: rgba(255, 143, 107, 0.5); }
.expr-hint {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-dim);
  line-height: 1.6;
  opacity: 0.85;
}

/* ---------- 管理员后台 ---------- */
.admin-head { display: flex; align-items: center; gap: 12px; font-size: 12px; color: var(--text-dim); }
.admin-back { color: var(--accent); text-decoration: none; }
.admin-back:hover { text-decoration: underline; }
#panel { padding: 16px 20px 40px; overflow-y: auto; }
.admin-card {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 14px;
}
#login-card { width: 360px; margin: 60px auto; }
.admin-card h2 { font-size: 15px; font-weight: 600; margin-bottom: 10px; }
.admin-tip { font-size: 12px; color: var(--text-dim); line-height: 1.7; margin-bottom: 12px; }
.admin-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.admin-row label { width: 70px; font-size: 13px; color: var(--text-dim); }
.admin-row input { flex: 1; }
.admin-actions { display: flex; gap: 10px; margin-top: 12px; }
.admin-err { color: var(--red); font-size: 12px; margin-top: 10px; }
.admin-warn {
  background: rgba(217, 160, 63, 0.12);
  border: 1px solid var(--amber);
  color: var(--amber);
  border-radius: var(--radius);
  padding: 8px 12px;
  font-size: 12px;
  margin-bottom: 12px;
}
.admin-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.admin-state { font-size: 12px; color: var(--text-dim); margin-left: auto; }
.admin-item {
  border-top: 1px solid var(--border);
  padding: 10px 0;
}
.admin-item:first-of-type { border-top: none; }
.admin-item.modified .admin-label { color: var(--accent); }
.admin-item.changed { background: rgba(76, 141, 255, 0.06); }
.admin-item-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.admin-label { font-size: 13px; font-weight: 500; }
.admin-key { font-size: 11px; color: var(--text-dim); }
.admin-item input { width: 220px; font-size: 13px; }
.admin-item-foot { display: flex; gap: 12px; margin-top: 5px; align-items: baseline; }
.admin-help { font-size: 12px; color: var(--text-dim); line-height: 1.6; flex: 1; }
.admin-default { font-size: 11px; color: var(--text-dim); opacity: 0.75; white-space: nowrap; }
.admin-dim { font-size: 12px; color: var(--text-dim); }
.admin-prev-row { font-size: 13px; line-height: 1.8; }
button.mini { font-size: 11px; padding: 2px 8px; margin-left: auto; }
#pwd-mask {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex; align-items: center; justify-content: center;
  z-index: 20;
}
/* 必须显式覆盖：ID 选择器的 display 会压过 .hidden，弹窗否则永远盖在页面上 */
#pwd-mask.hidden { display: none; }
.admin-modal { width: 380px; }

/* 【2026-10-15】单行 input → 多行 textarea：练口语的长句要看得见全句。
   高度由 app.js 的 autoGrowInput() 撑（上限 40vh，再长就内部滚动），
   这里只负责"不能超过、必须能滚"的兜底。 */
#chat-input {
  flex: 1;
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px;
  font-size: var(--font-chat, 14px);
  font-family: inherit;
  line-height: 1.5;
  resize: none;
  min-height: 42px;
  max-height: 40vh;
  overflow-y: hidden;
  white-space: pre-wrap;
  word-break: break-word;
}
#chat-input:focus { outline: none; border-color: var(--accent); }

/* 「回到最新」入口：用户往上翻时出现，点一下回到对话最底部。
   挂在 #chat-panel 上绝对定位，不能挤占 chat-box 的高度。 */
#btn-jump {
  position: absolute;
  right: 18px;
  bottom: 96px;
  z-index: 5;
  padding: 6px 12px;
  font-size: 12px;
  border-radius: 999px;
  background: var(--bg-card);
  color: var(--accent);
  border: 1px solid var(--accent);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}
#btn-jump:hover { background: var(--accent); color: #fff; }

#modal-mask {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 10;
}
#modal-mask.hidden { display: none; }
#modal {
  width: 420px; max-width: 92vw;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px;
}
.modal-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
#modal-lemma { font-size: 20px; font-weight: 600; flex: 1; }
#modal-senses { color: var(--text); line-height: 1.7; margin-bottom: 12px; }
#modal-stats { font-size: 12px; color: var(--text-dim); line-height: 1.9; }
#modal-lookup-note { margin-top: 8px; font-size: 12px; color: var(--amber); }

#modal-senses { margin-bottom: 12px; }
.sense { padding: 8px 10px; margin-bottom: 6px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; }
.sense.dim { opacity: 0.55; }
.sense .s-head { font-size: 13px; }
.sense .s-tag { font-size: 10px; margin-left: 6px; padding: 1px 6px; border-radius: 8px; border: 1px solid var(--border); color: var(--text-dim); }
.sense .s-example { margin-top: 4px; font-size: 12px; color: var(--text-dim); font-style: italic; }
.sense .s-bar { height: 3px; background: #333; border-radius: 2px; margin-top: 6px; overflow: hidden; }
.sense .s-bar i { display: block; height: 100%; background: var(--green); }

.deep-box { display: none; margin-top: 12px; padding: 10px; background: rgba(76, 141, 255, 0.07); border: 1px solid rgba(76, 141, 255, 0.35); border-radius: 8px; }
.deep-box .deep-q { font-size: 13px; line-height: 1.6; margin-bottom: 8px; }
.deep-box textarea {
  width: 100%;
  min-height: 56px;
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 13px;
  font-family: inherit;
  resize: vertical;
}
.deep-box .deep-actions { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.deep-box #deep-result { font-size: 12px; color: var(--text-dim); }
.deep-box #deep-result .ok { color: var(--green); font-weight: 600; }
.deep-box #deep-result .bad { color: var(--red); font-weight: 600; }

.empty-hint { color: var(--text-dim); text-align: center; margin-top: 40px; }

/* ---------- 通用弹窗（画像 / 统计） ---------- */
.mask {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 10;
}
.mask.hidden { display: none; }
.dialog {
  width: 480px; max-width: 92vw; max-height: 82vh; overflow-y: auto;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px;
}
.dialog-title { font-size: 16px; font-weight: 600; flex: 1; }
.dialog-sub { font-size: 12px; font-weight: 400; color: var(--text-dim); margin-left: 4px; }

/* ---------- 我的词库弹窗 ---------- */
.dialog-wide { width: 520px; }
#me-stats { margin: 10px 0 12px; }
#me-mask #word-list {
  max-height: calc(82vh - 160px);
  overflow-y: auto;
  padding-right: 4px;
}
#me-mask #me-stats:empty + #word-list:empty::after {
  content: "词库为空";
  display: block;
  text-align: center;
  color: var(--text-dim);
  padding: 24px 0;
  font-size: 13px;
}

/* ---------- 画像弹窗 ---------- */
.p-section { margin-bottom: 14px; }
.p-label { font-size: 12px; color: var(--text-dim); margin-bottom: 6px; }
.p-summary { line-height: 1.8; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; }
.p-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.p-tag { font-size: 12px; padding: 2px 10px; border-radius: 10px; background: var(--bg-card); border: 1px solid var(--border); }
.p-tag b { color: var(--accent); font-weight: 600; margin-left: 2px; }
.p-recent { font-size: 12px; color: var(--text-dim); line-height: 1.9; }
.p-recent .r-date { color: var(--amber); margin-right: 6px; }
.p-empty { color: var(--text-dim); text-align: center; padding: 20px 0; }

/* ---------- 统计弹窗 ---------- */
.stat-grid { display: flex; gap: 10px; margin-bottom: 14px; }
.stat-card { flex: 1; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 10px; text-align: center; }
.stat-card .num { font-size: 20px; font-weight: 600; color: var(--accent); }
.stat-card .lbl { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
.stat-section { margin-bottom: 14px; }
.bar-row { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; font-size: 11px; }
.bar-row .b-lbl { width: 44px; color: var(--text-dim); text-align: right; flex-shrink: 0; }
.bar-row .b-track { flex: 1; height: 10px; background: #2a2e37; border-radius: 5px; overflow: hidden; display: flex; }
.bar-row .b-track i { display: block; height: 100%; }
.bar-row .b-val { width: 30px; color: var(--text-dim); flex-shrink: 0; }
.b-correct { background: var(--green); }
.b-wrong { background: var(--red); }
.b-lookup { background: var(--amber); }
.b-passive { background: var(--accent); }
.stat-legend { display: flex; gap: 14px; font-size: 11px; color: var(--text-dim); margin: 6px 0 10px; }
.stat-legend i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 4px; }

/* ---------- 归档恢复按钮 ---------- */
#modal-restore { margin-top: 10px; }
#modal-restore button { font-size: 12px; padding: 5px 12px; }
#modal-restore .r-note { margin-left: 8px; font-size: 12px; color: var(--green); }

/* ---------- 全词点击：.w 无痕标记 + 气泡 ---------- */

.msg .w {
  cursor: pointer;
  border-bottom: 1px dotted transparent;
  transition: background 0.12s, border-color 0.12s;
}
.msg .w:hover {
  background: rgba(76, 141, 255, 0.16);
  border-bottom: 1px dotted var(--accent);
}

#word-pop {
  display: none;
  position: fixed;
  z-index: 300;
  width: 300px;
  max-width: calc(100vw - 16px);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
  padding: 12px 14px;
  font-size: 13px;
}
#word-pop .wp-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
#word-pop .wp-word { font-size: 16px; font-weight: 700; }
#word-pop .wp-tts {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  padding: 2px 4px;
  opacity: 0.75;
}
#word-pop .wp-tts:hover { opacity: 1; }
#word-pop .wp-dict, #word-pop .wp-lemma {
  font-size: 11px;
  color: var(--text-dim);
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
}
#word-pop .wp-gloss {
  margin: 8px 0;
  line-height: 1.6;
  color: var(--text);
}
#word-pop .wp-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
#word-pop .wp-detail {
  color: var(--accent);
  cursor: pointer;
  font-size: 12px;
}
#word-pop .wp-detail:hover { text-decoration: underline; }
#word-pop .wp-add {
  font-size: 12px;
  padding: 4px 12px;
  background: var(--accent);
  border: none;
  border-radius: 6px;
  color: #fff;
  cursor: pointer;
}
#word-pop .wp-add:disabled { opacity: 0.5; cursor: default; }
#word-pop .wp-status { font-size: 12px; color: var(--text-dim); }

/* ---------- 高阶改写：默认折叠，避免遮挡正文 ---------- */
.msg .rewrites {
  margin-top: 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(76, 141, 255, 0.05);
  overflow: hidden;
}
.msg .rewrites .rw-toggle {
  padding: 6px 10px;
  font-size: 12px;
  color: var(--accent);
  cursor: pointer;
  user-select: none;
}
.msg .rewrites .rw-toggle:hover { background: rgba(76, 141, 255, 0.1); }
.msg .rewrites.collapsed .rw-list { display: none; }
.msg .rewrites .rw-item {
  padding: 8px 10px;
  border-top: 1px solid var(--border);
}
.msg .rewrites .rw-text { font-size: calc(var(--font-chat, 14px) - 1px); line-height: 1.6; color: var(--text); }
.msg .rewrites .rw-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.msg .rewrites .rw-level {
  font-size: 10px;
  padding: 1px 7px;
  border-radius: 999px;
  color: var(--amber);
  background: rgba(217, 160, 63, 0.12);
  border: 1px solid rgba(217, 160, 63, 0.4);
}
.msg .rewrites .rw-note { font-size: 11px; color: var(--text-dim); line-height: 1.6; }
.msg .rewrites .rw-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.msg .rewrites .rw-add {
  font-size: 11px;
  padding: 2px 10px;
  border-radius: 6px;
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #fff;
  cursor: pointer;
}
.msg .rewrites .rw-add:disabled { opacity: 0.55; cursor: default; }
.msg .rewrites .rw-status { font-size: 11px; color: var(--text-dim); }

/* ---------- 语法库 / 表达库列表（「我的」弹窗内） ---------- */
#grammar-list, #rewrite-list { margin-bottom: 14px; }
.gr-item {
  padding: 7px 10px;
  margin-bottom: 6px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px;
}
.gr-item.disputed { opacity: 0.55; }
.gr-head { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.gr-text { color: var(--text); line-height: 1.6; }
.gr-note { margin-top: 3px; color: var(--text-dim); line-height: 1.6; }
.gr-meta { margin-top: 3px; font-size: 11px; color: var(--text-dim); }
.gr-meta b { color: var(--amber); font-weight: 600; }


/* ---------- 主站改版：沉浸单栏 + 左侧抽屉 + 设置页 ---------- */

/* 顶栏：汉堡 + 标题 左，状态 右 */
.hd-left { display: flex; align-items: center; gap: 12px; }
.hd-right { display: flex; align-items: center; gap: 10px; }
#hd-status { font-size: 12px; color: var(--text-dim); }
#btn-menu {
  width: 34px; height: 32px; padding: 0;
  display: inline-flex; flex-direction: column; justify-content: center; align-items: center; gap: 4px;
  background: transparent; border: none;
}
#btn-menu span { display: block; width: 18px; height: 2px; background: var(--text-dim); border-radius: 2px; }
#btn-menu:hover span { background: var(--accent); }

/* 左侧抽屉 */
#drawer {
  position: fixed; top: 0; left: 0; bottom: 0; width: 280px; z-index: 60;
  background: var(--bg-panel); border-right: 1px solid var(--border);
  transform: translateX(-100%); transition: transform 0.18s ease;
  display: flex; flex-direction: column; padding: 14px 12px 10px;
}
#drawer.open { transform: translateX(0); }
#drawer-mask { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45); z-index: 55; }
#drawer-mask.hidden { display: none; }
.drawer-new { width: 100%; margin-bottom: 14px; }
.drawer-label { font-size: 12px; color: var(--text-dim); margin: 2px 4px 8px; }
#side-history { flex: 1; overflow-y: auto; }
.drawer-foot {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 12px 4px 2px; text-align: left; font-size: 13px; color: var(--text);
  background: transparent; border: none; border-top: 1px solid var(--border);
  border-radius: 0; cursor: pointer;
}
.drawer-foot:hover { color: var(--accent); }
.avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--bg-card); border: 1px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; color: var(--text-dim);
}

/* 沉浸单栏：对话居中限宽，去掉面板底色 */
main { justify-content: center; padding: 0 18px 14px; }
#chat-panel {
  max-width: 860px; width: 100%; margin: 0 auto;
  background: transparent; border: none; border-radius: 0;
}

/* 目标词标签条：对话区上方一排 chips，有词才出现 */
#stack-strip {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 12px 2px 0; padding: 8px 12px;
  background: var(--bg-panel); border: 1px solid var(--border); border-radius: 10px;
}
#stack-strip.hidden { display: none; }
#stack-chips { display: flex; flex-wrap: wrap; gap: 7px; flex: 1; }
#stack-chips .chip { cursor: pointer; font-size: 12.5px; }
#stack-chips .chip:hover { border-color: var(--accent); color: var(--accent); }
.strip-hint { font-size: 11.5px; color: var(--text-dim); }

/* 本场巩固：回场词用琥珀色描边 + 前缀小圆点，跟新入栈的词区分开。
   用户看到老面孔会先怀疑"是不是轮换坏了"，得让他一眼看出这是刻意的。 */
#stack-chips .chip.reinforced {
  border-color: var(--amber); color: var(--amber);
}
#stack-chips .chip.reinforced::before {
  content: ""; display: inline-block;
  width: 5px; height: 5px; margin-right: 5px;
  border-radius: 50%; background: var(--amber);
  vertical-align: middle;
}

/* 设置页（全屏弹层） */
#settings-mask {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.6);
  display: flex; align-items: center; justify-content: center; z-index: 70;
}
#settings-mask.hidden { display: none; }
.settings-page {
  position: relative; width: min(920px, 94vw); height: min(620px, 90vh);
  background: var(--bg-panel); border: 1px solid var(--border); border-radius: 14px;
  display: flex; overflow: hidden;
}
.settings-side {
  width: 170px; flex: none; border-right: 1px solid var(--border);
  padding: 16px 10px; display: flex; flex-direction: column; gap: 4px;
}
.settings-title { font-size: 15px; font-weight: 500; padding: 0 8px 12px; }
.settings-tab {
  text-align: left; background: transparent; border: none;
  color: var(--text-dim); padding: 9px 10px; border-radius: 8px;
  font-size: 13px; cursor: pointer;
}
.settings-tab:hover { color: var(--text); background: var(--bg-card); }
.settings-tab.on { color: var(--accent); background: rgba(76, 141, 255, 0.12); }
.settings-main { flex: 1; overflow-y: auto; padding: 18px 20px; }
.tab-pane { display: none; }
.tab-pane.on { display: block; }
.pane-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.pane-head .p-label { margin: 0; flex: 1; }
#btn-close-settings { position: absolute; top: 10px; right: 10px; }
#tab-admin p { font-size: 13px; color: var(--text-dim); line-height: 1.7; margin: 0 0 14px; }
.btn-link {
  display: inline-block; background: var(--accent); color: #fff;
  border-radius: var(--radius); padding: 8px 16px;
  font-size: 13px; text-decoration: none;
}
.btn-link:hover { opacity: 0.9; }

/* 启动守卫条：脚本抛错时把原因摆到台面上，避免页面静默变砖 */
#boot-error {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 99;
  background: #7a1f1f; color: #fff; padding: 10px 14px;
  font-size: 12px; line-height: 1.6; white-space: pre-wrap;
}
#boot-error.hidden { display: none; }

/* ---------- 设置 · 显示页（正文字号） ---------- */
.font-row { display: flex; align-items: center; gap: 12px; margin: 12px 0 14px; flex-wrap: wrap; }
#font-range { flex: 1; max-width: 280px; accent-color: var(--accent); cursor: pointer; }
#font-value { font-size: 12px; color: var(--text-dim); min-width: 40px; }
.font-preview {
  font-size: var(--font-chat, 14px);
  line-height: 1.7;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  max-width: 560px;
  margin-bottom: 10px;
}
.settings-note { font-size: 12px; color: var(--text-dim); line-height: 1.7; }

/* ---------- 移动端适配（2026-10-15 首次引入；此前全表 0 条 @media） ----------
   背景：body 原来是死值 height:100vh。手机浏览器的地址栏会随滚动伸缩，100vh
   算的是"永远展开"的高度，于是页面底部被地址栏吃掉一块——输入框正好卡在最底下，
   键盘弹出时被顶到视口外。dvh 会跟着实际可视高度变，再垫一层 safe-area
   避开 iPhone 底部小黑条。
   第二条更重要：11px 的徽标、10px 的提示在手机上属于"看得见但费劲"，一律提到
   12px 以上；卡片式按钮的热区补到 40px 以上，指头点得中。 */
@media (max-width: 640px) {
  body {
    height: 100dvh;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  header { padding: 8px 12px; }
  header h1 { font-size: 16px; }
  main { padding: 0 8px 8px; }
  #chat-box { padding: 12px 10px; gap: 16px; }
  /* 用户气泡在小屏上要放宽：桌面的 min(62%,520px) 落在 360px 屏上只有两百来像素，
     一句英文会被切成七八行。AI 那边不用管——它已经不限宽，由 --ai-line 兜着。 */
  .msg.user { max-width: 88%; }
  .msg.ai { padding: 0; }

  /* 热区：原来的 .diff-btn / 历史条目只有三十来像素高，手指容易点偏 */
  .diff-btn, .done-chip, .side-sess, .sess-item { min-height: 40px; }
  .diff-btn { padding: 8px 12px; }

  /* 字号：10/11px 在手机上偏吃力 */
  .badge, .done-hint, .sess-item .s-meta, .side-sess .ss-meta { font-size: 12px; }
  .hist-title, .note, .msg .notes { font-size: 12px; }

  #input-bar { padding: 8px; gap: 8px; }
  #btn-send { min-width: 60px; min-height: 40px; }
  #chat-input { min-height: 40px; }

  #btn-jump { right: 12px; bottom: 84px; }
  #drawer { width: 82vw; }
  .settings-page { width: 100vw; }
  .settings-side { width: 84px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ---------- 发送 / 停止 与页内提示条（2026-10-15） ---------- */
/* 停止按钮顶替发送按钮的位置，宽度必须一致，否则点下去的瞬间布局会跳一下 */
#btn-stop {
  background: var(--bg-card);
  border: 1px solid var(--red);
  color: var(--red);
  min-width: 60px;
  min-height: 40px;
}
#btn-stop:hover { background: var(--red); color: #fff; }

/* 提示条：替掉原生 alert。贴在底部输入行上方，不遮输入框，也不抢焦点。 */
#toast-wrap {
  position: fixed;
  left: 50%;
  bottom: 84px;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  width: min(92vw, 520px);
  pointer-events: none; /* 容器本身不挡点击，只有里面的条要能点 */
}
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  font-size: 13px;
  line-height: 1.5;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
}
.toast-error { border-color: var(--red); color: var(--red); }
.toast-text { flex: 1; min-width: 0; word-break: break-word; }
.toast-action, .toast-close {
  flex: none;
  padding: 3px 10px;
  font-size: 12px;
  border-radius: 6px;
  background: var(--bg-card);
}
.toast-action { color: var(--accent); border: 1px solid var(--accent); }
.toast-close { color: var(--text-dim); border: 1px solid var(--border); }
.toast-action:hover { background: var(--accent); color: #fff; }
.toast-close:hover { border-color: var(--accent); color: var(--text); }

@media (max-width: 640px) {
  #toast-wrap { bottom: 76px; width: calc(100vw - 24px); }
  #btn-stop { min-width: 56px; }
}
