/* bandu · 气泡批注阅读器
   顶栏 → 拖放区 → 阅读布局 → 正文 → beat 容器 → 气泡 → 结构层横幅 */

:root {
  --bg: #faf8f4;
  --panel: #ffffff;
  --ink: #23201c;
  --ink-soft: #6b6459;
  --line: #e6e0d6;
  --mentor: #b07d2b;
  --mentor-bg: #fdf5e6;
  --student: #3f72a4;
  --student-bg: #eef4fb;
  --self: #3d7a5f;
  --self-bg: #eaf4ee;
  --hook: #6d5b8e;
  --hook-bg: #f4f0f9;
  --gutter: 340px;
  --gap: 40px;
}

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Source Han Serif SC", "Songti SC", "Noto Serif CJK SC", Georgia, serif;
  -webkit-font-smoothing: antialiased;
}

button, input, select { font: inherit; }

/* ---------- top bar ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px 24px;
  background: rgba(250, 248, 244, .93);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
}

.brand { font-weight: 700; letter-spacing: .5px; margin-right: 4px; font-size: 15px; }
/* 读的时候书名就是回家的按钮，但它得看着像标题，不像控件 */
.brand.as-link {
  border: none; background: none; padding: 0; cursor: pointer;
  color: inherit; font-family: inherit;
  transition: opacity .15s;
}
.brand.as-link:hover { opacity: .55; }

.spacer { flex: 1; }

.btn {
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink);
  border-radius: 999px;
  padding: 5px 14px;
  font-size: 13px;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.btn:hover { border-color: #c9bfae; }
.btn[disabled] { opacity: .45; cursor: default; }

.toggle {
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: 999px;
  padding: 5px 13px;
  font-size: 13px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.toggle .dot { width: 8px; height: 8px; border-radius: 50%; background: #cfc7ba; }
.toggle.on { background: #fff; border-color: #cbbfa8; }
.toggle.on.mentor .dot { background: var(--mentor); }
.toggle.on.student .dot { background: var(--student); }
.toggle.on.self .dot { background: var(--self); }
.toggle.on.progressive .dot { background: var(--hook); }
.toggle.off { opacity: .5; }

.status { font-size: 12px; color: var(--ink-soft); }
.status b { color: var(--ink); font-weight: 600; }

/* ---------- dropzone ---------- */

.drop {
  max-width: 720px;
  margin: 72px auto;
  padding: 48px 40px;
  background: var(--panel);
  border: 1.5px dashed var(--line);
  border-radius: 16px;
  text-align: center;
  font-family: -apple-system, "PingFang SC", sans-serif;
}
.drop.hot { border-color: var(--mentor); background: var(--mentor-bg); }
.drop h1 { font-size: 26px; margin: 0 0 6px; letter-spacing: .5px; }
.drop .lead { font-size: 15px; color: var(--ink); margin: 0 0 26px; }
.drop p { color: var(--ink-soft); font-size: 14px; line-height: 1.8; margin: 0 0 6px; }
/* 两个按钮就是全部入口，别让别的东西抢在它们前面 */
.drop .files { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.drop .btn { padding: 8px 20px; font-size: 14px; }
.drop .btn.primary { background: var(--ink); color: #fbf9f5; border-color: var(--ink); }
.drop .btn.primary:hover { background: #3a352d; border-color: #3a352d; }
.drop .aside { margin-top: 14px; font-size: 12.5px; color: #9c9385; }
.drop code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  background: #f3efe7;
  padding: 1px 6px;
  border-radius: 4px;
}
/* 只在「拖进来一部分、还缺东西」时出现，所以它是进度条，不是说明书 */
.slots { margin-top: 30px; display: grid; gap: 8px; text-align: left; max-width: 480px; margin-inline: auto; }
.slots-head { font-size: 12.5px; color: #8d8474; padding-left: 2px; }
/* 全部限定在 .slots 下：右侧栏的格子曾经也叫 .slot，这里的边框和背景漏了过去，
   在气泡外面套了一个框。现在那边改叫 .beat-slot，这边也收进父级里，不再撞名。 */
.slots .slot {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 10px; padding: 9px 13px;
  background: #fdfcfa;
}
.slots .slot .tick { width: 18px; text-align: center; }
.slots .slot.filled { color: var(--ink); border-color: #d8cfbc; background: #fff; }
.slots .slot .what { display: grid; gap: 2px; min-width: 0; }
.slots .slot .line1 { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.slots .slot .line1 b { color: var(--ink); font-weight: 700; }
.slots .slot .line1 code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; color: #a29885; background: none; padding: 0;
}
.slots .slot .hint { font-size: 11.5px; opacity: .75; }
.slots .slot .name { margin-left: auto; padding-left: 10px; font-size: 12px; color: var(--ink-soft); max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.err {
  max-width: 720px; margin: 0 auto 20px; padding: 12px 16px;
  border: 1px solid #e5c6c0; background: #fdf1ef; color: #8d3b2c;
  border-radius: 10px; font-size: 13px;
  font-family: -apple-system, "PingFang SC", sans-serif;
}

/* ---------- reading layout ---------- */

.stage { padding: 32px 24px 200px; }

.layout {
  position: relative;
  margin: 0 auto;
  max-width: calc(720px + var(--gutter) + var(--gap));
}

.article {
  width: 720px;
  max-width: 100%;
  font-size: 17px;
  line-height: 1.95;
}

.gutter {
  position: absolute;
  top: 0;
  left: calc(720px + var(--gap));
  width: var(--gutter);
}

.layout.inline .gutter { position: static; width: auto; left: auto; }
.layout.inline .article { width: 100%; }

.connectors { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.layout.inline .connectors { display: none; }

/* ---------- prose ---------- */

.article h1 { font-size: 30px; line-height: 1.4; margin: 0 0 4px; }
.article h2 { font-size: 23px; line-height: 1.5; margin: 8px 0 4px; }
.article h3 { font-size: 19px; margin: 6px 0 2px; }
.article h1.zh, .article h2.zh, .article h3.zh { color: var(--ink-soft); font-weight: 600; margin-top: 0; }
.article p { margin: 0 0 14px; }
.article p.zh { color: #4a443c; }
.article ul, .article ol { margin: 0 0 14px; padding-left: 26px; }
.article li { margin-bottom: 6px; }
.article img { max-width: 100%; border-radius: 8px; border: 1px solid var(--line); }
.article a { color: #2f6d8c; text-underline-offset: 3px; }
.article code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .87em;
  background: #f2eee6;
  padding: 1px 5px;
  border-radius: 4px;
}
.article pre {
  background: #2b2822;
  color: #ede7dc;
  padding: 15px 17px;
  border-radius: 10px;
  overflow-x: auto;
  font-size: 13px;
  line-height: 1.65;
  margin: 0 0 16px;
}
.article pre code { background: none; padding: 0; color: inherit; font-size: 13px; }
.article table { border-collapse: collapse; width: 100%; font-size: 14.5px; margin: 0 0 16px; }
.article th, .article td { border: 1px solid var(--line); padding: 7px 11px; text-align: left; vertical-align: top; }
.article th { background: #f4f0e8; }
.article blockquote {
  margin: 0 0 14px; padding: 2px 0 2px 16px;
  border-left: 3px solid var(--line); color: var(--ink-soft);
}
.article hr { border: none; border-top: 1px solid var(--line); margin: 24px 0; }

/* ---------- beat containers ---------- */

.beat {
  position: relative;
  padding: 2px 14px 2px 14px;
  margin: 0 -14px 4px;
  border-radius: 8px;
  transition: background .18s;
}
/* 正文 hover 与气泡 hover 用同一套高亮，两边互相点亮 */
.beat.has-bubbles { cursor: default; }
.beat.active { background: #f4efe3; box-shadow: inset 3px 0 0 #d8c9a6; }
.beat.dim { opacity: .42; }

.beat .beat-tag {
  position: absolute;
  left: -84px;
  top: 4px;
  width: 74px;
  text-align: right;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 10.5px;
  color: #c2b8a6;
  opacity: 0;
  transition: opacity .18s;
  user-select: none;
}
.beat:hover .beat-tag, .beat.active .beat-tag { opacity: 1; }

.cont-mark {
  font-family: -apple-system, "PingFang SC", sans-serif;
  font-size: 11px; color: #b3a894; margin-bottom: 4px;
}

.loose { padding: 0 14px; margin: 0 -14px; }

/* ---------- bubbles ---------- */

/* 右侧栏按 beat 切成一格一格的 .beat-slot：每格从「该 beat 的静止位置」延伸到
   「该 beat 结束」，格与格首尾相接、不重叠。一个 beat 的气泡装在 .beat-slot-group
   里整体 sticky —— 所以两条气泡的相对间距永远是布局给的那个，也不可能各自
   钉到同一条线上叠起来。钉住由合成器完成，不经过 JS，滚动时零延迟。
   （名字带 beat- 前缀是因为拖放区的文件行已经叫 .slot 了。） */
.beat-slot {
  position: absolute;
  left: 0;
  width: 100%;
  pointer-events: none;         /* 占位块不吃鼠标事件，只有气泡吃 */
}
.beat-slot-group { position: sticky; }

.bubble {
  position: relative;
  width: 100%;
  pointer-events: auto;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 12px 15px 13px;
  margin-bottom: 12px;
  font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
  font-size: 13.5px;
  line-height: 1.78;
  box-shadow: 0 1px 2px rgba(60, 48, 30, .05);
  transition: box-shadow .18s, border-color .18s, opacity .18s;
  cursor: default;
}
.bubble:last-child { margin-bottom: 0; }

.layout.inline .beat-slot {
  position: static;
  height: auto !important;
}
.layout.inline .beat-slot-group { position: static; }
.layout.inline .bubble {
  width: auto;
  margin: 10px 0 14px;
}

.bubble.mentor { border-color: #ecd9b0; background: var(--mentor-bg); }
.bubble.student { border-color: #cddef1; background: var(--student-bg); }
.bubble.self { border-color: #cfe3d6; background: var(--self-bg); }

.bubble:hover { box-shadow: 0 4px 14px rgba(60, 48, 30, .1); }
.bubble.active { border-color: #b9a67f; box-shadow: 0 4px 16px rgba(60, 48, 30, .13); }
.bubble.dim { opacity: .3; }

/* 跟随滚动钉住：气泡的 beat 还在屏幕上时，气泡贴在顶栏下方（sticky 的 top 由
   JS 量一次顶栏高度给出，滚动时不变）。beat 读完，slot 也就结束，气泡随之离场。 */

/* bubble tail pointing back at the text */
.bubble::before,
.bubble::after {
  content: "";
  position: absolute;
  left: -8px;
  top: 17px;
  width: 0; height: 0;
  border-style: solid;
  border-width: 7px 8px 7px 0;
}
.bubble::before { border-color: transparent #e6e0d6 transparent transparent; }
.bubble::after { left: -6.5px; border-color: transparent var(--panel) transparent transparent; }
.bubble.mentor::before { border-right-color: #ecd9b0; }
.bubble.mentor::after { border-right-color: var(--mentor-bg); }
.bubble.student::before { border-right-color: #cddef1; }
.bubble.student::after { border-right-color: var(--student-bg); }
.bubble.self::before { border-right-color: #cfe3d6; }
.bubble.self::after { border-right-color: var(--self-bg); }
.layout.inline .bubble::before, .layout.inline .bubble::after { display: none; }

.bubble .head {
  display: flex; align-items: center; gap: 7px;
  font-size: 11.5px; margin-bottom: 6px; letter-spacing: .3px;
}
.bubble.mentor .head { color: var(--mentor); }
.bubble.student .head { color: var(--student); }
.bubble.self .head { color: var(--self); }
.bubble .head .who { font-weight: 700; }
/* 体例标签平时藏起来：它约束的是「这条批注该写成什么形状」，读者看文字本身
   就已经看到那个形状了，摆出来只是噪音。停在气泡上才露出来，供校对时看。 */
.bubble .head .form {
  margin-left: auto; font-size: 10.5px; color: #a89c88;
  font-family: -apple-system, "PingFang SC", sans-serif;
  opacity: 0; transition: opacity .18s;
}
.bubble:hover .head .form, .bubble.active .head .form { opacity: 1; }

/* 写笔记入口：挂在该段评论气泡下方的小圆气泡，悬停原文（或摸到它）才浮现。
   隐形时保留 pointer-events，摸到它自己也能现身；隐去带一点延迟，
   让鼠标从正文跨过栏间空隙的路上它不至于先消失。 */
.write-note {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin: 2px 0 10px 4px;
  padding: 0;
  border-radius: 50%;
  /* 与正文悬停高亮同色（.beat.active）：入口出现的时机就是原文点亮的时机 */
  background: #f4efe3;
  border: 1px solid #d8c9a6;
  color: var(--ink);
  font-family: "Yuanti SC", "PingFang SC", "Hiragino Sans GB", sans-serif;
  font-size: 12.5px;
  cursor: pointer;
  pointer-events: auto;
  opacity: 0;
  transition: opacity .18s ease .2s;
}
.write-note.on { opacity: 1; transition-delay: 0s; }
.write-note:hover {
  background: #efe7d3;
  box-shadow: 0 2px 10px rgba(120, 100, 60, .18);
}

/* 删除钮：平时几乎隐形，悬停气泡才出现；确认态变红加粗 */
.note-del {
  margin-left: auto;
  font-size: 10.5px;
  color: var(--ink-soft);
  background: none;
  border: none;
  padding: 0 2px;
  cursor: pointer;
  opacity: 0;
  transition: opacity .18s;
}
.bubble.self:hover .note-del { opacity: 1; }
.note-del.confirm { color: #b3402e; font-weight: 700; opacity: 1; }

/* commentary 文本里的换行是结构性的（arrow_chain 的节点、对话轮次、清单项）。
   若只靠 white-space:pre-line，换行间距 == 行高，和意外折行看不出区别。
   这里按 \n 切成块，让「换行」比「折行」明显宽一档。 */
.bubble .text .ln,
.banner .body .ln { margin: 0 0 7px; }
.bubble .text .ln:last-child,
.banner .body .ln:last-child { margin-bottom: 0; }
.bubble .text { color: #322d26; }
.banner .body { color: inherit; }

/* 编辑气泡 */
.note-editor textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 9px;
  font: inherit;
  font-size: 12.5px;
  line-height: 1.55;
  resize: vertical;
  background: rgba(255, 255, 255, .75);
}
.note-editor-actions { display: flex; gap: 6px; align-items: center; margin-top: 6px; }
.note-editor-actions .spacer { flex: 1; }
.note-editor-actions .btn { font-size: 12px; padding: 5px 10px; }
.note-preview {
  margin-top: 6px;
  font-size: 12.5px;
  line-height: 1.55;
  padding: 6px 9px;
  border-radius: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  white-space: pre-wrap;
}

/* ---------- structural banners ---------- */

.banner {
  border-left: 3px solid #cfc0e0;
  background: var(--hook-bg);
  border-radius: 0 10px 10px 0;
  padding: 11px 16px 12px;
  margin: 18px 0 20px;
  font-family: -apple-system, "PingFang SC", sans-serif;
  font-size: 14px;
  line-height: 1.85;
}
.banner .label {
  font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--hook); margin-bottom: 5px; font-weight: 700;
}
.banner.close { border-left-color: #d6cbb4; background: #f7f4ec; }
.banner.close .label { color: #8a7a55; }
/* book / chapter hooks read heavier than section hooks */
.banner.d0 { font-size: 15px; border-left-width: 4px; }
.banner.d0, .banner.d1 { background: #f1ecf8; }
.banner.d0.close, .banner.d1.close { background: #f5f1e7; }

@media (max-width: 1150px) {
  .beat .beat-tag { display: none; }
}

/* ---- 气泡内嵌对话 ---- */
.ichat { margin-top: 8px; border-top: 1px dashed var(--line); padding-top: 6px; }

.ichat-bar { display: flex; align-items: center; margin-bottom: 4px; }
.ichat-count { font-size: 11.5px; color: var(--ink-soft); }
.ichat-expand {
  margin-left: auto; border: 0; background: none; cursor: pointer;
  font-size: 11.5px; color: var(--ink-soft); opacity: .7;
}
.ichat-expand:hover { opacity: 1; }

/* 高度固定、内部滚动：对话再长气泡也不长高；「展开」才放大 */
.ichat-body {
  max-height: 170px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
  padding: 2px 0 6px;
}
.ichat.expanded .ichat-body { max-height: 60vh; }

.chat-msg { font-size: 12.5px; line-height: 1.55; padding: 6px 9px; border-radius: 8px; white-space: pre-wrap; }
.chat-msg.user { align-self: flex-end; max-width: 88%; background: rgba(255, 255, 255, .75); border: 1px solid var(--line); }
.chat-msg.assistant { align-self: flex-start; max-width: 94%; background: var(--panel); border: 1px solid var(--line); }
.chat-msg.assistant code {
  padding: 1px 4px; border-radius: 4px; background: rgba(70, 61, 49, .08);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .94em;
}
.chat-err { font-size: 12px; color: #b3502d; }

.ichat-input { display: flex; gap: 6px; align-items: flex-end; }
.ichat-input textarea {
  flex: 1; resize: none; font: inherit; font-size: 12.5px; line-height: 1.5;
  border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px;
  background: var(--panel); color: var(--ink);
}
.ichat-input textarea:disabled { background: transparent; color: var(--ink-soft); }
.ichat-send { font-size: 12px; padding: 5px 10px; white-space: nowrap; }
.ichat-send:disabled { opacity: .45; cursor: default; }

/* banner 内的对话区：横幅是全宽横条，输入区不铺满整行才舒服 */
.banner .ichat { max-width: 620px; }

/* @ 切换钮：本轮问谁。配色与气泡的导师金/朋友蓝一致 */
.ichat-at {
  font-size: 12px; padding: 5px 8px; border-radius: 8px;
  border: 1px solid var(--line); background: transparent;
  cursor: pointer; white-space: nowrap;
}
.ichat-at.mentor { color: var(--mentor); border-color: #ecd9b0; background: var(--mentor-bg); }
.ichat-at.student { color: var(--student); border-color: #cddef1; background: var(--student-bg); }
.ichat-at.none { color: var(--ink-soft); border-color: var(--line); background: transparent; }
.ichat-at:disabled { opacity: .45; cursor: default; }

/* 群聊式历史里标注每条回复是谁说的 */
.chat-tag {
  display: inline-block; margin-right: 6px; padding: 0 5px;
  border-radius: 6px; font-size: 10.5px; line-height: 1.6;
}
.chat-tag.mentor { color: var(--mentor); background: var(--mentor-bg); border: 1px solid #ecd9b0; }
.chat-tag.student { color: var(--student); background: var(--student-bg); border: 1px solid #cddef1; }
.chat-tag.self { color: var(--self); background: var(--self-bg); border: 1px solid #cfe3d6; }

/* ---------- 记忆面板（memory.jsx）---------- */

.memory-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(35, 32, 28, .35);
  backdrop-filter: blur(2px);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 56px 16px;
  overflow-y: auto;
}

.memory-panel {
  width: min(560px, 92vw);
  max-height: calc(100vh - 112px);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 14px 44px rgba(35, 30, 20, .22);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
}

.memory-head {
  display: flex;
  align-items: center;
  padding: 15px 20px;
  border-bottom: 1px solid var(--line);
}
.memory-title { font-weight: 700; font-size: 14.5px; }
.memory-close {
  margin-left: auto;
  border: none; background: none; cursor: pointer;
  font-size: 20px; line-height: 1; color: var(--ink-soft);
  padding: 0 2px;
}
.memory-close:hover { color: var(--ink); }

.memory-body { overflow-y: auto; padding: 6px 20px 22px; }

.memory-section { margin-top: 22px; }
.memory-section:first-child { margin-top: 6px; }
.memory-section-title {
  font-size: 12px; letter-spacing: .8px; text-transform: uppercase;
  color: var(--ink-soft); margin: 0 0 10px; font-weight: 700;
}

.memory-loading, .memory-empty {
  font-size: 13px; color: var(--ink-soft); line-height: 1.75; padding: 4px 0 10px;
}
.memory-err { font-size: 12.5px; color: #b3502d; padding: 5px 0; }

/* 画像字段：一行标签 + 值（点击进入行内编辑）*/
.memory-field {
  display: flex; align-items: baseline; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid #f1ece1;
  font-size: 13.5px;
}
.memory-field:last-child { border-bottom: none; }
.memory-field-label { flex: 0 0 76px; color: var(--ink-soft); }
.memory-field-row {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  cursor: pointer;
}
.memory-field-domain { font-weight: 700; color: var(--ink); flex: 0 0 auto; }
.memory-field-value { flex: 1; min-width: 0; color: var(--ink); overflow-wrap: break-word; }
.memory-field-row:hover .memory-field-value { text-decoration: underline dotted; text-underline-offset: 3px; }
.memory-badge {
  flex: 0 0 auto;
  font-size: 10.5px; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--ink-soft); white-space: nowrap;
}
.memory-badge.user { color: var(--self); border-color: #cfe3d6; background: var(--self-bg); }
.memory-badge.inferred { color: var(--student); border-color: #cddef1; background: var(--student-bg); }
.memory-field-input {
  flex: 1; font: inherit; font-size: 13.5px;
  border: 1px solid var(--mentor); border-radius: 6px;
  padding: 3px 8px; background: #fff; color: var(--ink);
}

.memory-foundation { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.memory-foundation .memory-field-row { padding: 1px 0; }
.memory-add-domain {
  align-self: flex-start; border: none; background: none; cursor: pointer;
  font-size: 12.5px; color: var(--mentor); padding: 3px 0;
}
.memory-add-domain:hover { text-decoration: underline; }
.memory-foundation-add { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.memory-foundation-add input {
  border: 1px solid var(--line); border-radius: 6px; padding: 4px 8px;
  font: inherit; font-size: 12.5px; background: #fff; color: var(--ink);
}
.memory-foundation-add input:first-child { flex: 0 0 100px; }
.memory-foundation-add input:nth-child(2) { flex: 1; min-width: 120px; }
.memory-foundation-add .btn { font-size: 11.5px; padding: 4px 9px; }

/* 记忆条目 */
.memory-kind-group { margin-bottom: 14px; }
.memory-kind-label {
  font-size: 11px; letter-spacing: .5px; color: #a89c88;
  text-transform: uppercase; margin-bottom: 6px;
}
.memory-row {
  border: 1px solid var(--line); border-radius: 10px;
  padding: 9px 12px; margin-bottom: 8px; background: #fdfcfa;
}
.memory-row-head { display: flex; align-items: center; gap: 8px; font-size: 11.5px; margin-bottom: 5px; }
.memory-cat {
  padding: 1px 8px; border-radius: 999px; font-weight: 600;
  background: #f4efe3; color: var(--mentor);
}
.memory-date { color: var(--ink-soft); }
.memory-scope { color: var(--ink-soft); font-style: italic; }
.memory-del {
  margin-left: auto; border: none; background: none; cursor: pointer;
  font-size: 11px; color: var(--ink-soft);
}
.memory-del:hover { color: #b3402e; }
.memory-del.confirm { color: #b3402e; font-weight: 700; }
.memory-row-text { font-size: 13px; line-height: 1.7; color: #322d26; white-space: pre-wrap; }

.memory-add { margin-top: 4px; display: flex; flex-direction: column; gap: 6px; }
.memory-add-input {
  width: 100%; border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 10px; font: inherit; font-size: 13px; line-height: 1.6;
  resize: vertical; background: #fff; color: var(--ink);
}
.memory-add .btn { align-self: flex-end; }

/* ---- 渐进解锁：正文末尾的「解锁下一单元」气泡按钮 ---- */
.unlock-row { display: flex; justify-content: center; margin: 26px 0 34px; }
.unlock-next {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink);
  border-radius: 999px;
  padding: 9px 22px;
  font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
  font-size: 14px;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(60, 48, 30, .05);
  transition: border-color .15s, box-shadow .15s;
}
.unlock-next:hover { border-color: #c9bfae; box-shadow: 0 2px 6px rgba(60, 48, 30, .08); }
.unlock-next .count { font-size: 12px; color: var(--ink-soft); }

/* ---------- 共享口令浮层（app.jsx）---------- */

.gate-mask {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: rgba(35, 32, 28, .35);
  backdrop-filter: blur(2px);
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 24px;
}

.gate {
  width: min(360px, 92vw);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 14px 44px rgba(35, 30, 20, .22);
  padding: 22px 24px 18px;
  font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
}
.gate h2 { margin: 0 0 6px; font-size: 16px; font-weight: 600; color: var(--ink); }
.gate-lead { margin: 0 0 14px; font-size: 13px; line-height: 1.7; color: var(--ink-soft); }
.gate-input {
  width: 100%; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 10px; font: inherit; font-size: 14px;
  background: #fff; color: var(--ink);
}
.gate-input:focus { outline: none; border-color: #c9bfae; }
.gate-err { margin-top: 8px; font-size: 12.5px; color: #b3402e; }
.gate-actions { margin-top: 14px; display: flex; justify-content: flex-end; gap: 8px; }
