:root{--ink:#28241e;--muted:#847d72;--paper:#f8f4eb;--accent:#c75d36;--line:#e8dfd0;--card:#fffdf8}*{box-sizing:border-box}body{margin:0;background:var(--paper);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei","PingFang SC",sans-serif}.topbar{height:56px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;padding:0 clamp(16px,5vw,72px);background:#fffdf8;position:sticky;top:0;z-index:2}.brand{font:bold 19px Georgia,serif;letter-spacing:.3px;background:none;border:0;color:var(--ink);cursor:pointer}.brand span{font:12px sans-serif;color:var(--accent);margin-left:7px;letter-spacing:1px}nav{display:flex;gap:17px}button{border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}nav button{color:var(--muted);padding:7px 1px}nav button.active{color:var(--accent);border-bottom:2px solid var(--accent)}main{max-width:1060px;margin:auto;padding:30px 24px}.page{display:none}.page.active{display:block}.section-head{display:flex;align-items:end;justify-content:space-between;margin-bottom:18px}.source-actions,.discover-controls,.category-list{display:flex;gap:10px}.discover-controls{margin-bottom:16px}.discover-controls select{max-width:360px}.category-list{flex-wrap:wrap;margin:14px 0}.category-list button{padding:6px 11px;border:1px solid var(--line);border-radius:4px;background:var(--card);font:13px sans-serif}.category-list button:hover{border-color:var(--accent);color:var(--accent)}.detail-head{margin:22px 0;display:flex;gap:24px;align-items:flex-start}.detail-head h1{margin:0 0 8px}.detail-head p{color:var(--muted)}.detail-cover{flex:0 0 auto;width:160px}.detail-cover img{width:100%;height:auto;border-radius:3px;display:block;background:var(--card)}.cover-placeholder{width:160px;aspect-ratio:2/3;border:1px solid var(--line);border-radius:3px;display:flex;align-items:center;justify-content:center;color:var(--muted);font:13px sans-serif;background:var(--card)}.detail-meta{flex:1;min-width:0}.detail-source{word-break:break-all}.detail-source a{color:var(--accent);text-decoration:none}.detail-source a:hover{text-decoration:underline}.chapter-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}.chapter-list button{background:var(--card);padding:14px;text-align:left;font:14px sans-serif}.chapter-list button:hover{color:var(--accent)}h1{font-size:22px;margin:0;font-weight:600;letter-spacing:.2px}.primary,.secondary{border-radius:4px;padding:8px 13px;font:13.5px sans-serif}.primary{background:var(--accent);color:#fff}.secondary{border:1px solid #d4c6b4;color:var(--accent);background:#fffdf8}.book-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(205px,1fr));gap:20px}.book{background:var(--card);border:1px solid var(--line);border-radius:5px;overflow:hidden;cursor:pointer;transition:border-color .15s}.book:hover{border-color:var(--accent)}.cover{height:168px;background:#b9572f;padding:16px;color:#fff;display:flex;align-items:end;font-size:19px;font-weight:600;line-height:1.35;position:relative}.badge{position:absolute;top:10px;right:10px;font:11px sans-serif;padding:3px 7px;border-radius:3px;color:#fff;background:rgba(0,0,0,.6)}.badge.reading{background:#d98e2b}.badge.read{background:#3e9d5f}.badge.update{background:var(--accent);box-shadow:0 2px 8px #c75d3660}.shelf-actions{display:flex;align-items:center;gap:10px}.update-status{font:12px sans-serif;color:var(--muted)}.book-info .reading-state{color:var(--accent)}.book-info{padding:15px}.book-info h3{margin:0 0 6px;font-size:16px}.book-info p{margin:0;color:var(--muted);font:13px sans-serif}.empty{border:1px solid var(--line);border-radius:4px;padding:34px 16px;text-align:center;color:var(--muted);font:14px sans-serif;background:var(--card)}.hint{color:var(--muted);font:12.5px/1.65 sans-serif;margin:8px 0}.source-list{display:grid;gap:12px;margin-top:20px}.source{padding:13px 15px;background:var(--card);border:1px solid var(--line);border-radius:4px;display:flex;align-items:center;gap:12px}.source-dot{width:10px;height:10px;border-radius:50%;background:#45a06c}.source div{flex:1}.source h3{margin:0 0 5px;font-size:17px}.source p{margin:0;color:var(--muted);font:12px monospace}.small{font:13px sans-serif;color:var(--accent)}.settings-card{max-width:640px;margin-bottom:14px;background:var(--card);border:1px solid var(--line);border-radius:4px;padding:16px 18px}.settings-card label{display:grid;grid-template-columns:1fr auto;gap:12px;margin-bottom:25px;font:15px sans-serif}.settings-card input,.settings-card select{grid-column:1/-1;accent-color:var(--accent)}output{color:var(--accent)}dialog{border:0;border-radius:6px;padding:0;width:min(620px,calc(100% - 30px));box-shadow:0 20px 70px #0004}dialog::backdrop{background:#261d17aa}#modal-form{padding:26px}menu{padding:0;margin:22px 0 0;display:flex;justify-content:flex-end;gap:10px}menu button{padding:10px 16px;border-radius:7px}input,textarea,select{width:100%;border:1px solid #d9cfbf;border-radius:3px;padding:8px 10px;background:#fff;font:14px sans-serif}textarea{min-height:120px;resize:vertical;tab-size:2}
textarea[name="sourceJson"]{font-family:Consolas,"SF Mono",ui-monospace,monospace;font-size:13px;line-height:1.55;min-height:340px;max-height:60vh;overflow:auto;white-space:pre}
.search-block{margin:28px 0;padding:14px 16px;background:var(--card);border:1px solid var(--line);border-radius:4px}.search-block-head{font:600 14px sans-serif;color:var(--muted);margin-bottom:14px;display:flex;align-items:center;gap:10px}.search-pager{display:flex;gap:6px;margin-top:14px;flex-wrap:wrap}.pg-num{min-width:28px;height:28px;padding:0 9px;border:1px solid var(--line);background:#fffdf8;color:var(--muted);border-radius:3px;font:13px sans-serif;cursor:pointer;transition:.15s}.pg-num:hover:not([data-future]){border-color:var(--accent);color:var(--accent)}.pg-num.active{background:var(--accent);color:#fff;border-color:var(--accent)}.pg-num[data-future]{opacity:.45;cursor:not-allowed}
textarea[name="content"]{min-height:180px;line-height:1.6}
/* T15：章节分页合并时插入的分隔标记，居中细线 + 灰字，不抢正文节奏 */
#reading-content .page-break-sep{text-align:center;font-size:.85em;color:var(--muted);margin:1.4em 0;padding:.55em 0;border:0;border-top:1px dashed var(--line);letter-spacing:.5em}
/* 模态框：dialog / form 在窗口高度紧张时可竖向滚动，避免 textarea 被外层裁断 */
dialog{max-height:90vh}#modal-form{max-height:80vh;overflow-y:auto}.field{display:block;font:13px sans-serif;margin-top:15px}.field span{display:block;margin-bottom:6px;color:#60594f}.form-error{display:none;margin:16px 0 0;color:#b23b2a;font:13px/1.5 sans-serif}.form-error.show{display:block}.reader-page{max-width:810px;margin:auto}.reader-tools,.reader-footer{display:flex;justify-content:space-between;align-items:center;color:var(--muted);font:13px sans-serif}/* 工具条常驻视口顶部：与 .reader-footer{sticky bottom} 完全对称的同一个理由 ——
 * 无缝续读把文档拉长到数千像素，「返回 / 加入书架 / 原网页 / 目录」若留在文档开头，
 * 读到中段就得一路滚回顶部才用得上；「加入书架」尤其如此，它是阅读页唯一的入架入口。
 * top 让开 .topbar 的 56px；背景与 body 同源（夜间模式不会出现一块亮底）。 */
.reader-tools{border-bottom:1px solid var(--line);padding-bottom:15px;position:sticky;top:56px;z-index:2;background:var(--reader-bg,#f8f4eb)}.reader-tools button,.reader-footer button{color:var(--accent)}#reading-content{max-width:min(760px,calc(100vw - 80px));min-height:65vh;margin:0 auto;padding:45px 4px;font-size:var(--reader-font,19px);line-height:var(--reader-line,1.9);text-align:justify;overflow-wrap:break-word;word-break:break-word}#reading-content p{margin:0 0 var(--reader-para-margin,1.35em);line-height:inherit;text-align:justify;text-indent:2em;overflow-wrap:break-word;word-break:break-word}#reading-content p:last-child{margin-bottom:0}.reader-footer{border-top:1px solid var(--line);padding-top:17px}.reader-mid{display:flex;flex-direction:column;align-items:center;gap:4px}.prefetch{font:12px sans-serif;color:var(--muted);display:inline-flex;align-items:center;gap:6px}.prefetch.ready{color:#3e9d5f}.prefetch.loading{color:var(--accent)}.prefetch.error{color:#b23b2a}.prefetch .retry{border:1px solid currentColor;border-radius:6px;padding:2px 8px;background:none;cursor:pointer;font:12px sans-serif;color:inherit}.load-error{text-align:center;padding:70px 20px;color:var(--muted);font:15px/1.8 sans-serif}.load-error button{margin-top:14px;padding:9px 20px;border:1px solid var(--line);border-radius:7px;background:var(--card);cursor:pointer;color:var(--accent);font:14px sans-serif}#toc-panel{position:fixed;top:0;right:0;bottom:0;width:min(340px,84vw);background:var(--card);border-left:1px solid var(--line);box-shadow:-12px 0 32px #5e4b3018;z-index:5;display:flex;flex-direction:column}#toc-panel[hidden]{display:none}.toc-head{display:flex;gap:8px;padding:14px 16px;border-bottom:1px solid var(--line)}#toc-search{flex:1;padding:8px 12px}#close-toc{border:0;background:none;font-size:18px;color:var(--muted);cursor:pointer;padding:4px 8px}.toc-list{flex:1;overflow-y:auto;padding:10px 8px 20px}.toc-list button{display:block;width:100%;text-align:left;padding:8px 11px;border:0;background:none;border-radius:3px;font:14px/1.6 sans-serif;color:var(--ink);cursor:pointer}.toc-list button:hover{background:#f3ecdd}.toc-list button.active{background:var(--accent);color:#fff}.toc-vol{font:12px sans-serif;letter-spacing:2px;color:var(--accent);padding:14px 12px 4px;font-weight:bold}.toc-empty{padding:22px;text-align:center;color:var(--muted);font:13px sans-serif}@media(max-width:560px){main{padding:28px 18px}.topbar{padding:0 18px}.brand span{display:none}.cover{height:145px}.source-actions{gap:6px}.source-actions button{padding:9px 10px}.discover-controls{flex-wrap:wrap}#reading-content{max-width:100%;padding-left:0;padding-right:0;overflow-wrap:break-word}}.discover-search{display:flex;gap:10px;margin-bottom:10px}.discover-search input{flex:1}.search-fail{color:#b23b2a;font:12px/1.6 sans-serif}.search-block{margin:0 0 26px}.search-block-head{font:13px sans-serif;letter-spacing:1px;color:var(--accent);margin:0 0 10px}.next-content-wrap{text-align:center;margin:34px 0 10px}.next-content-wrap button{border:1px solid var(--line);border-radius:4px;background:var(--card);padding:8px 20px;color:var(--accent);font:14px sans-serif;cursor:pointer}.next-content-wrap button:hover{border-color:var(--accent)}.next-content-wrap button+button{margin-left:16px}
.toc-list button,.chapter-list button{content-visibility:auto;contain-intrinsic-size:auto 34px}
.check-chip{display:inline-block;margin-left:8px;padding:1px 6px;border-radius:3px;font:11px/1.6 sans-serif;vertical-align:2px;font-weight:500}.check-chip[data-state="ok"]{background:rgba(42,157,95,.13);color:#258a52}.check-chip[data-state="bad"]{background:rgba(192,57,43,.12);color:#c0392b}.check-chip[data-state="warn"]{background:rgba(224,154,20,.15);color:#c98a00}.check-chip[data-state="running"]{background:rgba(47,111,214,.13);color:#2f6fd6}.check-chip[data-state="idle"]{background:rgba(120,120,120,.1);color:#999}.check-report{display:grid;gap:3px;margin-top:5px;max-width:560px}.check-report[hidden]{display:none}.check-head{font-size:11px;color:#aaa;margin-bottom:2px}.check-row{display:flex;gap:8px;font-size:12px;line-height:1.7;color:#555;min-width:0}.check-row b{flex:none;width:132px;font-weight:500}.check-row.ok b{color:#258a52}.check-row.bad b{color:#c0392b}.check-row span{min-width:0;word-break:break-all}\n.source.disabled{opacity:.55}.cf-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}.cf-actions .small{padding:5px 12px;border-radius:1px;text-decoration:none;display:inline-block}.cf-actions a{background:rgba(47,111,214,.08);color:#185FA5}.cf-actions button{background:rgba(192,57,43,.1);color:#c0392b;border:none;cursor:pointer;font:inherit}.cf-actions a:hover{background:rgba(47,111,214,.16)}.cf-actions button:hover{background:rgba(192,57,43,.18)}.cf-hint{margin:8px 0 0;color:#888;font-size:12px;line-height:1.6}.cf-hint code{background:rgba(0,0,0,.06);padding:1px 5px;border-radius:3px;font:12px/1.6 ui-monospace,Menlo,Consolas,monospace;color:#5F5E5A}
/* T20 书源网络策略标签：可点击循环切换（跟随全局 → 走代理 → 直连） */
.proxy-chip{cursor:pointer;border:1px solid transparent;transition:background .15s,border-color .15s;user-select:none}
.proxy-chip:hover{border-color:currentColor;opacity:.85}
.proxy-chip:active{transform:translateY(1px)}
.proxy-chip::after{content:" ⇄";font-size:10px;opacity:.55}
/* 发现页：搜索区与页面标题同行置于最顶，分类区独立成块在下方 */
.discover-head{flex-wrap:wrap;gap:12px 22px;align-items:flex-end;margin-bottom:20px}
.discover-search-bar{flex:1 1 320px;min-width:250px;margin:0}
.discover-search-bar input{flex:1}
.search-results{max-height:min(62vh,660px);overflow-y:auto;overscroll-behavior:contain;padding-right:4px;scrollbar-width:thin}
.search-results:empty{max-height:none;overflow:visible}
.search-results::-webkit-scrollbar{width:8px}
.search-results::-webkit-scrollbar-thumb{background:#ded1b9;border-radius:8px}
.search-results::-webkit-scrollbar-track{background:transparent}
.pane-title{display:block;margin:0 0 12px;padding-top:22px;border-top:1px solid var(--line);font-size:16px;font-weight:600;color:var(--ink)}

@media(max-width:560px){.discover-search-bar{flex:1 1 100%}.search-results{max-height:56vh}}
/* 书架删除：单本 ✕ 与批量管理模式 */
.book{position:relative}
.book-del{position:absolute;top:10px;left:10px;z-index:2;display:flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border-radius:50%;background:rgba(0,0,0,.45);color:#fff;font:14px/1 sans-serif;opacity:0;transition:opacity .15s,background .15s}
.book:hover .book-del,.book:focus-within .book-del{opacity:1}
.book-del:hover{background:#b23b2a}
@media(hover:none){.book-del{opacity:1}}
.book-check{display:none;position:absolute;top:10px;left:10px;z-index:2;width:24px;height:24px;border-radius:50%;border:2px solid #fff;background:rgba(0,0,0,.35);color:transparent;font:14px/1 sans-serif;text-align:center;pointer-events:none}
#book-grid.managing .book-check{display:flex;align-items:center;justify-content:center}
#book-grid.managing .book-del{display:none}
.book.selected{outline:2px solid var(--accent);outline-offset:2px}
.book.selected .book-check{background:var(--accent);border-color:var(--accent);color:#fff}
.shelf-bulkbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 18px;padding:10px 14px;background:#f4efe3;border:1px solid var(--line);border-radius:4px}
.shelf-bulkbar[hidden]{display:none}/* 作者样式的 display 会盖掉 UA 的 [hidden]{display:none}，必须显式补回 */
.shelf-bulkbar #shelf-sel-count{font:600 13px sans-serif;color:var(--muted);margin-right:auto}
.shelf-bulkbar .secondary{padding:7px 12px;font-size:13px}
.shelf-bulkbar .secondary:disabled{opacity:.45;cursor:not-allowed}
button.danger,#modal-save.danger{background:#b23b2a;border-color:#b23b2a;color:#fff}
/* 分类浏览：标题行（左标题 + 右视图切换） */
.pane-head{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;padding-top:34px;border-top:1px solid var(--line)}
.pane-head .pane-title{padding-top:0;border-top:0;margin-bottom:0}
.view-switch{display:flex;gap:3px;padding:3px;background:#f4efe3;border:1px solid var(--line);border-radius:3px}
.view-switch .view-btn{padding:4px 12px;border-radius:3px;color:var(--muted);font:13px/1 sans-serif;transition:.15s}
.view-switch .view-btn:hover{color:var(--accent)}
.view-switch .view-btn.active{background:var(--accent);color:#fff}
/* 分类结果：每页 9 本 —— 桌面 3 列正好 3×3 */
.explore-grid{grid-template-columns:repeat(3,1fr)}
/* 列表视图：每行一本，整行可点进详情 */
.book-list{display:flex;flex-direction:column;gap:10px}
.book-row{display:flex;align-items:center;gap:14px;padding:11px 14px;background:var(--card);border:1px solid var(--line);border-radius:4px;cursor:pointer;transition:border-color .15s}
.book-row:hover{border-color:var(--accent)}
.book-row .row-idx{flex:0 0 30px;text-align:center;color:var(--muted);font:12px/1 sans-serif}
.book-row .row-main{flex:1;min-width:0}
.book-row .row-main h3{margin:0 0 5px;font-size:17px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.book-row .row-main p{margin:0;color:var(--muted);font:13px/1.6 sans-serif;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.book-row .row-go{flex:0 0 auto;color:var(--accent);font:13px sans-serif}
/* 分类结果分页条 */
.explore-pager{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:22px 0 4px}
/* 分页条（分类结果 + 详情页章节目录）用 hidden 控制显隐：必须显式补 [hidden]，
   否则上面这条 display:flex 会盖掉 UA 的 [hidden]{display:none}，空分页条会常显成一段 22px 空白 */
.explore-pager[hidden]{display:none}
.pg-step{min-width:30px;height:30px;padding:0 12px;border:1px solid var(--line);background:#fffdf8;color:var(--muted);border-radius:8px;font:13px sans-serif;cursor:pointer;transition:.15s}
.pg-step:hover:not([disabled]){border-color:var(--accent);color:var(--accent)}
.pg-step[disabled]{opacity:.45;cursor:not-allowed}
.pg-gap{color:var(--muted);padding:0 2px;font:13px sans-serif}
.pg-info{margin-left:auto;color:var(--muted);font:13px sans-serif}
@media(max-width:900px){.explore-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.explore-grid{grid-template-columns:1fr}.book-row .row-go{display:none}.pg-info{margin-left:0;flex:1 1 100%}}
/* ===== T21 净化词管理（设置页） ===== */
.purify-card{max-width:720px;margin-top:22px;display:flex;flex-direction:column;gap:14px}
.purify-head{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;flex-wrap:wrap}
.purify-title{font-size:17px;margin:0;font-weight:600}
.purify-desc{margin:0;color:var(--muted);font:13px/1.7 sans-serif}
.purify-desc b{color:var(--accent)}
.settings-card label.purify-enable{display:flex;align-items:center;gap:7px;margin:0;font:13px sans-serif;grid-template-columns:none;white-space:nowrap}
.settings-card label.purify-enable input{width:auto;padding:0;margin:0;border:0;background:none;grid-column:auto}
.purify-add{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.purify-add input{flex:1 1 190px;width:auto}
.purify-add select{flex:0 0 106px;width:auto}
.purify-add .primary{flex:0 0 auto;padding:10px 18px}
.purify-error{margin:0;color:#4a6b3f;font:13px/1.6 sans-serif}
.purify-error.bad{color:#b23b2a;font-weight:600}
.purify-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border-top:1px solid var(--line);padding-top:13px}
.purify-count{color:var(--muted);font:13px sans-serif;margin-right:auto}
.purify-bar .secondary{padding:7px 12px;font-size:13px}
.purify-list{display:flex;flex-direction:column;gap:7px}
.purify-empty{margin:0;color:var(--muted);font:13px/1.7 sans-serif;padding:8px 0}
.purify-row{display:flex;align-items:center;gap:7px;flex-wrap:wrap;background:#fbf7ef;border:1px solid var(--line);border-radius:3px;padding:7px 9px}
.purify-row.off{opacity:.5}
.purify-row .purify-word{flex:1 1 170px;width:auto;padding:7px 9px;font-size:13px}
.purify-row select{flex:0 0 104px;width:auto;padding:7px 6px;font-size:13px}
.purify-row label.purify-enable{font-size:12px;color:var(--muted)}
.purify-row .purify-del{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:#efe6d5;border:1px solid var(--line);color:#8a7c68;font:13px/1 sans-serif}
.purify-row .purify-del:hover{background:#b23b2a;border-color:#b23b2a;color:#fff}
.purify-off .purify-add,.purify-off .purify-list,.purify-off .purify-test{opacity:.5}
.purify-test{border-top:1px solid var(--line);padding-top:12px;font:13px sans-serif}
.purify-test summary{cursor:pointer;color:var(--muted)}
.purify-test textarea{margin:10px 0 8px;font:13px/1.6 monospace}
.purify-test .secondary{padding:7px 12px;font-size:13px}
.purify-test-out{margin-top:10px;display:flex;flex-direction:column;gap:4px;max-height:260px;overflow:auto}
.pf-line{border-radius:3px;padding:4px 8px;font:13px/1.6 sans-serif;background:#f4efe3;overflow-wrap:break-word}
.pf-line span{margin-left:10px;font-size:11px;color:var(--muted);white-space:nowrap}
.pf-drop{background:#f7dcd6;color:#8f2f21;text-decoration:line-through}
.pf-drop span{color:#b23b2a;text-decoration:none}
.pf-edit{background:#e6efe4;color:#2f5a2a}
/* 阅读页底部的净化提示：不抢正文节奏（text-indent 需显式归零，否则被 #reading-content p 的 2em 缩进带偏） */
#reading-content .purify-note{margin:26px 0 0;padding:9px 12px;border-radius:3px;background:#f4efe3;color:var(--muted);font:12px/1.6 sans-serif;text-align:center;text-indent:0;letter-spacing:0}
@media(max-width:560px){.purify-add input{flex:1 1 100%}.purify-add select{flex:1 1 calc(50% - 4px)}.purify-row .purify-word{flex:1 1 100%}.purify-card{max-width:100%}}
/* ===== 无缝续读：章节流（预加载 + 到底自动拼接下一章） =====
 * #reading-content 内只放正文段（.chap-seg），换章按钮与状态提示放在其外的 #flow-tail，
 * 这样 #reading-content 的文本/段落断言仍然只反映「正文」。
 * overflow-anchor:none —— 位置完全由 JS 负责（flowRender 按锚点恢复 + flowMutateDom 守住不变量），
 * 浏览器自动滚动锚定两个方向都会出错，必须关干净：
 *   ① 回收旧章节会移除视口上方的内容 → 浏览器补偿与 flowRender 的补偿叠加（双重补偿 → 视口跳动）；
 *   ② **正文下方的元素也必须一起排除**。只关正文容器的话，滚动锚定的锚点会被赶到正文之下
 *      （尾部提示 #flow-tail / 页脚 .reader-footer）—— 而「往正文末尾插内容」正是把这两个元素推下去的动作，
 *      浏览器为了保持锚点的屏幕位置，会把 scrollY 一起推下去：视口被甩到**新的文档底部**，
 *      也就是刚拼进来那一章的末尾。用户口径：「正在预加载下一章，会跳到下一章的最末尾，导致一直在预加载下一章」。
 *      实测（4 段/章、视口 900、占位段 135px）：插占位段 y 381→614、正文落地 614→852，
 *      两次都精确落在新的 maxY（614 = 1514-900、852 = 1752-900）；
 *      而视口不在底部时做同样操作，y 完全不动 —— 「每次增长都恰好跟到新底部」就是「锚点在正文之下」的指纹。
 *      把这两块排除后，锚点只能落到 section#reader 及以上（正文变高不会推动它们），行为恢复正常。 */
#reading-content,.chap-seg,#flow-tail,.reader-footer{overflow-anchor:none}
.chap-seg + .chap-seg{margin-top:6px}
.chap-sep{display:flex;align-items:center;gap:14px;margin:54px 0 30px;font:600 15px/1.4 "Noto Serif SC","Songti SC",serif;color:var(--muted);text-align:center;text-indent:0;letter-spacing:.02em}
.chap-sep::before,.chap-sep::after{content:"";flex:1;height:1px;background:var(--line)}
.chap-sep span{flex:0 0 auto;max-width:72%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chap-loading{margin:44px 0;padding:22px 0;text-align:center;color:var(--muted);font:14px/1.7 sans-serif;border:1px solid var(--line);border-radius:4px;background:var(--card)}
.chap-loading::after{content:"…";animation:chap-blink 1.2s infinite}
@keyframes chap-blink{0%,100%{opacity:.3}50%{opacity:1}}
.chap-fail{margin:38px 0 8px;padding:18px 18px;text-align:center;color:#b23b2a;font:14px/1.8 sans-serif;border:1px solid #e6c8c0;border-radius:4px;background:#fbf1ee}
.chap-fail .secondary{margin-top:12px}
.flow-tail[hidden]{display:none}
.flow-hint{margin:34px 0 0;text-align:center;color:var(--muted);font:13px/1.7 sans-serif}
/* 页脚常驻视口底部：无缝续读把文档拉长到多章（数千像素），换章按钮 / 章节进度 / 「下一章已就绪」
 * 若留在文档末尾，就要一路滚到最后才能看到，而「滚到底」又会立刻自动接上下一章——等于看不见也用不上。
 * 背景用 --reader-bg（applyPrefs 里与 body 背景同源），夜间模式不会出现一块亮底；与顶部 .topbar{sticky top} 对称。 */
.reader-footer{position:sticky;bottom:0;z-index:3;background:var(--reader-bg,#f8f4eb);padding-bottom:12px}
/* ===== T24 后台控制（操作日志 / 常用参数 / 权限）===== */
.adm-card{background:var(--card);border:1px solid var(--line);border-radius:4px;padding:16px 18px;margin-bottom:16px;max-width:1000px}
.adm-card-head{display:flex;align-items:flex-end;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:12px}
.adm-h2{font-size:17px;margin:0;font-weight:600}
.adm-h3{font-size:14px;margin:0 0 8px;font-weight:600;color:var(--ink);display:flex;align-items:center;gap:8px}

.adm-desc{margin:0 0 14px;color:var(--muted);font:13px/1.75 sans-serif}
.adm-desc b{color:var(--accent)}
.adm-desc code,.adm-row-name code,.adm-code{font:12px/1.6 ui-monospace,Menlo,Consolas,monospace;background:rgba(0,0,0,.05);padding:1px 5px;border-radius:3px}
.adm-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.adm-actions button,.adm-form button,.adm-pager button,.adm-filters button{padding:6px 12px;border:1px solid var(--line);border-radius:3px;background:var(--card);font:13px sans-serif;color:var(--ink);cursor:pointer;transition:.15s}
.adm-actions button:hover:not(:disabled),.adm-pager button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.adm-actions button.primary,.adm-form button.primary,.adm-row-edit button.primary{padding:7px 15px;background:var(--accent);border-color:var(--accent);color:#fff;font:13px sans-serif}
.adm-actions button:disabled,.adm-form button:disabled,.adm-pager button:disabled,.adm-row-edit button:disabled,.adm-row-edit input:disabled,.adm-row-edit select:disabled{opacity:.45;cursor:not-allowed}
.adm-actions button.danger{color:#b23b2a;border-color:#e3c3bd}
.adm-chip{display:inline-block;padding:1px 6px;border-radius:3px;font:11px/1.7 sans-serif;background:rgba(120,120,120,.09);color:var(--muted);white-space:nowrap}
.adm-chip.ok{background:rgba(42,157,95,.13);color:#258a52}
.adm-chip.warn{background:rgba(224,154,20,.15);color:#c98a00}
.adm-form{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.adm-form input,.adm-reason input,.adm-filters input,.adm-filters select,.adm-row-edit input,.adm-row-edit select{padding:6px 10px;border:1px solid var(--line);border-radius:3px;background:#fffdf8;color:var(--ink);font:13px sans-serif;min-width:0}
.adm-form input{flex:1 1 200px}
.adm-msg{margin:12px 0 0;font:13px/1.7 sans-serif;color:var(--muted)}
.adm-msg.ok{color:#258a52}.adm-msg.err{color:#b23b2a}.adm-msg.warn{color:#c98a00}
.adm-msg[hidden]{display:none}
.adm-tabs{display:flex;gap:6px;border-bottom:1px solid var(--line);margin:0 0 18px;max-width:1000px}
.adm-tab{padding:9px 16px;border:0;background:none;color:var(--muted);font:14px sans-serif;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
.adm-tab.active{color:var(--accent);border-bottom-color:var(--accent)}
.adm-tab-n{display:inline-block;min-width:18px;padding:0 5px;border-radius:3px;background:rgba(0,0,0,.06);font:11px/1.7 sans-serif;color:var(--muted)}
.adm-filters{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;margin:6px 0 14px}
.adm-filters label{display:flex;flex-direction:column;gap:5px;font:12px sans-serif;color:var(--muted)}
.adm-filters input{min-width:170px}
.adm-stat{margin:0 0 12px;font:13px/1.7 sans-serif;color:var(--muted)}
.adm-stat b{color:var(--ink)}
.adm-stat.ok{color:#258a52}.adm-stat.err{color:#b23b2a}
.adm-table-wrap{max-height:min(58vh,620px);overflow:auto;border:1px solid var(--line);border-radius:4px}
.adm-table{width:100%;border-collapse:collapse;font:12.5px/1.7 sans-serif}
.adm-table th{position:sticky;top:0;background:#f3ece1;color:var(--muted);text-align:left;font-weight:600;padding:9px 11px;border-bottom:1px solid var(--line);white-space:nowrap;z-index:1}
.adm-table td{padding:8px 11px;border-bottom:1px solid var(--line);color:var(--ink);vertical-align:top}
.adm-table tr:last-child td{border-bottom:0}
.adm-nowrap{white-space:nowrap}
.adm-dim{color:var(--muted);font-size:12px;margin-left:6px}
.adm-code{display:block;margin:2px 0 0;font-size:11px;color:var(--muted);background:none;padding:0}
.adm-detail{max-width:340px;word-break:break-word;color:#5f574d}
.adm-empty{text-align:center;color:var(--muted);padding:26px 0}
.adm-res{display:inline-block;padding:1px 6px;border-radius:3px;font:11px/1.7 sans-serif}
.adm-res.ok{background:rgba(42,157,95,.13);color:#258a52}
.adm-res.fail{background:rgba(192,57,43,.12);color:#c0392b}
.adm-res.deny{background:rgba(224,154,20,.15);color:#c98a00}
.adm-pager{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-top:12px}
.adm-pager button.active{background:var(--accent);border-color:var(--accent);color:#fff}
.adm-group{margin-top:16px;border-top:1px solid var(--line);padding-top:13px}
.adm-reason{margin:4px 0 12px;padding:10px 12px;background:rgba(199,93,54,.04);border:1px solid var(--line);border-radius:4px}
.adm-reason label{display:flex;flex-direction:column;gap:6px;font:12.5px sans-serif;color:var(--muted)}
.adm-reason input{width:100%}
.adm-row{display:grid;grid-template-columns:1fr auto;gap:6px 18px;padding:13px 0;border-bottom:1px solid var(--line)}
.adm-row:last-child{border-bottom:0}
.adm-row-name{display:flex;align-items:center;gap:9px;flex-wrap:wrap;font:14.5px sans-serif}
.adm-row-name b{font-weight:600}
.adm-row-desc{margin-top:5px;color:var(--muted);font:12.5px/1.7 sans-serif;max-width:640px}
.adm-row-edit{display:flex;align-items:center;gap:7px;flex-wrap:wrap;justify-content:flex-end}
.adm-row-edit input{width:96px}.adm-row-edit select{min-width:104px}
.adm-row-edit button{padding:5px 10px;border:1px solid var(--line);border-radius:3px;background:var(--card);font:12.5px sans-serif;color:var(--ink);cursor:pointer}
.adm-row-edit button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.adm-unit{color:var(--muted);font:12px sans-serif}
.adm-row-meta{grid-column:1/-1;color:var(--muted);font:12px/1.7 sans-serif}
.adm-row-meta b{color:var(--ink);font-weight:600}
.adm-old{color:#b23b2a}.adm-new{color:#258a52;font-weight:600}
.adm-runtime{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:10px;margin:10px 0 16px}
.adm-runtime>div{display:flex;flex-direction:column;gap:3px;padding:8px 10px;background:rgba(0,0,0,.03);border-radius:3px}
.adm-runtime b{font:14px sans-serif}
@media(max-width:720px){.adm-row{grid-template-columns:1fr}.adm-row-edit{justify-content:flex-start}.adm-detail{max-width:180px}.adm-filters label{flex:1 1 100%}}


/* ===== 2026-09-13 去 AI 味 / 去模板味 收尾声明 =====
 * 界面字体改为无衬线（工具感），阅读正文仍用衬线——读小说时宋体更舒服。
 * 其余改动已就地写进上面各条规则里（圆角收紧、去掉投影与上浮、提示条不再是大色块）。 */
#reading-content{font-family:"Noto Serif SC","Songti SC",Georgia,serif}
/* 空态在网格里要占满一行（否则被 minmax(205px) 挤成窄条、文字折成三行） */
.book-grid>.empty{grid-column:1/-1}
/* 设置页的复选框按左对齐，不要落在 grid 第二列居中位置 */
.settings-card label input[type="checkbox"]{justify-self:start;width:auto;margin-top:6px}
/* 状态行没有内容时不占位（搜索框占位符、「加载分类」按钮已说明操作，不再补一行说明） */
#search-status:empty,#discover-status:empty{display:none}
/* 禁用态统一降透明度 + 禁点光标（净化词「清空全部」在 0 条时、分页首末页按钮都用它） */
button:disabled{opacity:.45;cursor:not-allowed}
/* ---- 账号与同步（sync.js 渲染进 #account-card） ---- */
.account-tabs{display:flex;gap:6px}
.account-tabs button.small{background:none;border:1px solid var(--line);color:var(--muted);padding:5px 11px;font-size:13px;border-radius:4px;cursor:pointer}
.account-tabs button.small.on{border-color:var(--accent);color:var(--accent)}
.account-form{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.account-form input{flex:1 1 170px;width:auto}
.account-form .primary{flex:0 0 auto;padding:10px 18px}
.account-who b{color:var(--accent);font-weight:600;margin-left:4px}
.account-scopes{display:flex;flex-direction:column;gap:11px}
/* 两行一列：复选框跨两行，右侧上为名称、下为说明。必须显式覆盖 .settings-card label 的
   grid-template-columns:1fr auto，否则复选框会被推到第二列居中。 */
.settings-card label.account-scope{display:grid;grid-template-columns:auto 1fr;gap:2px 9px;align-items:start;justify-items:start;margin:0;font:13px/1.5 sans-serif;border-top:1px solid var(--line);padding-top:11px}
.settings-card label.account-scope input[type="checkbox"]{grid-column:1;grid-row:1 / span 2;width:auto;margin:2px 0 0;padding:0}
.account-scope-name{grid-column:2;font-size:14px}
.account-scope-desc{grid-column:2;color:var(--muted)}
/* ---- 首页账号入口与弹窗 ----
   account-entry 是顶栏最右侧的登录入口；账户面板因此有**两处**渲染位置
   （这里打开的弹窗 + 设置页的 #account-card），两者共用 sync.js 的同一套渲染函数。 */
.topbar nav{margin-left:auto}
.account-entry{margin-left:18px;padding:5px 12px;border:1px solid var(--line);border-radius:4px;background:var(--card);color:var(--muted);font:13px sans-serif;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.account-entry:hover{border-color:var(--accent);color:var(--accent)}
.account-entry.signed{border-color:var(--accent);color:var(--accent)}
.account-dialog{width:min(470px,92vw);padding:22px 22px 20px;border:1px solid var(--line);border-radius:5px;background:var(--card);color:var(--ink);position:relative}
.account-dialog::backdrop{background:rgba(40,36,30,.32)}
.account-dialog-close{position:absolute;top:9px;right:11px;padding:4px 6px;font-size:15px;line-height:1;color:var(--muted)}
.account-dialog-close:hover{color:var(--accent)}
/* ---- 后台权限门 ----
   未通过服务端校验时后台页只渲染这一张卡片：任何后台内容（运行时、参数、日志）都不进 DOM，
   因此「看得到但改不了」与「能点进去看到数据」之间的差别对访客是可见的。 */
.adm-denied{max-width:560px}
.adm-denied .adm-actions{margin-top:16px}
.adm-denied .adm-msg{margin:14px 0 0}

/* ---- 账号表单：密码框旁的「显示」开关、改密码区（sync.js 渲染） ----
   .account-field 是「输入框 + 开关」的一行。这几条必须排在上面 .account-form input 之后：
   两者特异性相同（都是 .类 元素），靠先后顺序决胜，写在前面会被 flex:1 1 170px 顶掉。 */
.account-field{flex:1 1 170px;display:flex;gap:6px;align-items:stretch;min-width:0}
.account-field>input{flex:1 1 auto;min-width:0}
/* 开关只换边框色，不做背景填充 —— 与全站的悬停约定一致 */
.account-peek{flex:0 0 auto;display:flex;align-items:center;padding:0 9px;border:1px solid var(--line);border-radius:3px;background:var(--card);color:var(--muted);font:12px sans-serif;cursor:pointer}
.account-peek:hover,.account-peek[aria-pressed="true"]{border-color:var(--accent);color:var(--accent)}
.account-pw{margin-top:2px;border-top:1px solid var(--line);padding-top:12px}
.account-pw-toggle{background:none;border:1px solid var(--line);color:var(--muted);padding:5px 11px;font-size:13px;border-radius:4px;cursor:pointer}
.account-pw-toggle:hover{border-color:var(--accent);color:var(--accent)}
.account-pwform{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:10px}
.account-pwform .primary{flex:0 0 auto;padding:10px 18px}
/* 窄屏（首页弹窗在手机上就是这个宽度）：带开关的字段整行占满，别和用户名挤在一行 */
@media(max-width:560px){.account-field{flex:1 1 100%}}
