:root {
  --bg:rgba(255,255,255,.92); --bg2:#f4fbf7; --text:#14171f; --muted:#5b6472; --line:#e6e9ee;
  --accent:#18c98a; --accent2:#d9f8ea; --btn:#111111; --btntext:#ffffff;
  --ok:#12a06a; --err:#d9534f; --radius:18px; --radius-sm:10px;
  /* 页面底色 = **淡青色**,与 `home.html` 的 `--page` **同一个值**(用户 2026-10-30:
     "read.html 和 write.html 的背景颜色也改成淡青色,和 home.html 一样")。
     `--bg`(纯白)继续留给顶栏 / 按钮 / 卡片 —— 于是"白片压在淡青底上"这套观感与Home一致。 */
  --page:#e2f1f4;
  --page-image: url("/api/images/site/apriflute_home-bg.jpg");
  --shadow:0 1px 2px rgba(20,23,31,.05), 0 14px 34px -20px rgba(20,23,31,.22);
  color-scheme:light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:rgba(14,17,22,.92); --bg2:#141a20; --text:#f2f4f7; --muted:#9aa3b0; --line:#252c36;
    --accent:#2ee6a6; --accent2:#12352a; --btn:#ffffff; --btntext:#111111;
    --ok:#2ee6a6; --err:#ff8b8b;
    --page:#080d0e;
    --shadow:0 1px 2px rgba(0,0,0,.45), 0 16px 40px -22px rgba(0,0,0,.8);
    color-scheme:dark;
  }
}
:root[data-theme="dark"] {
  --bg:rgba(14,17,22,.92); --bg2:#141a20; --text:#f2f4f7; --muted:#9aa3b0; --line:#252c36;
  --accent:#2ee6a6; --accent2:#12352a; --btn:#ffffff; --btntext:#111111;
  --ok:#2ee6a6; --err:#ff8b8b;
  --page:#080d0e;
  --shadow:0 1px 2px rgba(0,0,0,.45), 0 16px 40px -22px rgba(0,0,0,.8);
  color-scheme:dark;
}
* { box-sizing:border-box; }
/* 2026-11-04:背景照片(与 home.html 同一套做法)。用 `background-color` 而不是
   `background` 简写 —— 简写会把 background-image 一并清掉。 */
body { margin:0; background-color:var(--page); background-image:var(--page-image, none);
  background-size:cover; background-position:center; background-attachment:fixed;
  color:var(--text); line-height:1.7;
  font-family:Inter, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing:antialiased; }
a { color:inherit; text-decoration:none; }
header { position:sticky; top:0; z-index:20; background:var(--bg);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line); }
.bar { max-width:1560px; margin:0 auto; height:64px; display:flex; align-items:center; gap:12px; padding:0 20px; }
.brand { display:flex; align-items:center; gap:8px; font-weight:700; font-size:19px; white-space:nowrap; }
.brand svg { width:28px; height:28px; }
.nav { display:flex; gap:4px; flex:1; }
.nav a { font-size:14px; color:var(--muted); padding:8px 12px; border-radius:8px; }
.nav a:hover { background:var(--bg2); color:var(--text); }
.who { font-size:13px; color:var(--muted); white-space:nowrap; }
/* 顶栏右端那三样 = **与 home.html 逐字相同**(同一个 `#me` / `#signOut` / `#signIn`,
   同一份 `App.renderTopbar()`:问候跟着一天走,昵称是**指向自己 user.html 的新标签页链接**)。
   2026-10-30 用户:"把 home.html 的欢迎词和Sign out链接拷贝到 read.html,放同样的位置。
   比如对Username demoN,是"Good evening, demoN  Sign out",其中Username demoN 指向其 user.html,
   Sign out是Sign outSign in"。 */
.right { display:flex; align-items:center; gap:8px; }
.me { display:inline-flex; align-items:baseline; gap:8px; color:var(--accent);
  font-size:16px; font-weight:600; white-space:nowrap; }
/* 昵称保持深色:`--accent` 是浅绿,16px 的文字全用它对比度不够(问候语有颜色就够"亮"了)。 */
.me-name { color:var(--text); text-decoration:none; }
.me-name:hover { color:var(--accent); text-decoration:underline; }
.btn { border:1px solid var(--line); border-radius:var(--radius-sm); padding:8px 15px; font:inherit;
  font-size:13.5px; font-weight:600; cursor:pointer; background:transparent; color:var(--text); }
.btn:hover { background:var(--bg2); }

/* 三栏 = **25 : 55 : 20**(2026-10-30 第二十九轮:用户先要 30:50:20,随后改为
   "read.html 左侧留白太大了,三栏宽度比例改成 25:55:20" —— 左栏是几行纯文字的
   书架 / 推荐列表,用不了 30% 那么宽;省下来的 5% 给正文)。
   在那之前是 `15% : 1fr : 15%`:右栏只有 ~210px(共享那套Search控件挤在里面),而中间那栏
   宽到 ~1100px、正文却由 `.reader { max-width:768px }` **居中** ⇒ 两边各剩一大块空白,
   看上去"Search离正文很远"。
   用 **fr 而不是 %**:百分比再加上 `gap` 会让总宽超过 100%,中间那栏被挤掉(比例就不再是
   25:55:20);写成 `minmax(0,25fr)` 这类,是让**扣掉 gap 之后的剩余宽度**按 25:55:20 分 ——
   and home.html 的 `2fr 2fr 1fr`(= 40:40:20)同一套做法。1560 上限下三栏约
   **366 / 805 / 293px**:右栏 293px and home.html 的右栏同量级;中栏 805px 略大于正文的
   768 上限 ⇒ 正文只留 ~18px 边距(几乎贴着),那道"多余的空白"自然没了。 */
.read-layout { max-width:1560px; margin:0 auto; padding:24px 20px 90px;
  display:grid; grid-template-columns:minmax(0,25fr) minmax(0,55fr) minmax(0,20fr); gap:28px;
  align-items:start; }
.rail { position:sticky; top:84px; display:flex; flex-direction:column; gap:22px;
  font-size:13px; max-height:calc(100vh - 110px); overflow:auto; }
.rail section { min-width:0; }
/* 三块各自的头 / 身间距。Title栏那条深一档的底色由共享表的
   `.panel.tint-* > .panel-head` 给(所以这里**不许自己写 background**,否则="半张脸")。 */
.rail .panel-head { padding: 9px 13px; }
.rail .panel-body { padding: 12px 13px 14px; }
.rail h4 { margin:0; font-size:12px; color:var(--muted); font-weight:600;
  letter-spacing:.02em; }
.rail ul { list-style:none; margin:0; padding:0; }
.rail li { margin:0 0 7px; line-height:1.45; }
.rail li a:hover { color:var(--accent); }
.rail .col { margin-bottom:12px; }
.rail .col-title { font-weight:600; font-size:12.5px; display:block; }
.rail .count { color:var(--muted); font-size:11.5px; }
.rail .empty { color:var(--muted); font-size:12.5px; }
.rail .why { color:var(--muted); font-size:11px; margin-left:4px; }
.rail .who-line { color:var(--muted); font-size:11.5px; display:block; }

/* 2026-11-04 用户:"read.html 里正文部分不能透明,用原来浅青色的背景色"
   ⇒ 正文卡片用实底 `--page`(#e2f1f4 浅青),照片只在两侧留白里露出来。 */
.reader { max-width:768px; margin:0 auto; min-width:0;
  background: var(--page); border: 1px solid var(--line); border-radius: 16px;
  padding: 28px 32px 36px; }
.reader h1 { font-size:31px; line-height:1.32; margin:0 0 12px; letter-spacing:-.02em; }
.byline { display:flex; flex-wrap:wrap; align-items:center; gap:10px;
  color:var(--muted); font-size:13px; padding-bottom:18px; margin-bottom:22px;
  border-bottom:1px solid var(--line); }
.byline a { color:var(--accent); }
.byline .vis { border:1px solid var(--line); border-radius:999px; padding:1px 8px;
  font-size:11.5px; }
.reader-body { font-size:16.5px; line-height:1.95; }
.reader-body img { max-width:100%; height:auto; border-radius:8px; }
.reader-body pre { overflow:auto; }
.reader-body .plain { white-space:pre-wrap; font:inherit; }
.tags { display:flex; flex-wrap:wrap; gap:8px; margin-top:34px; }
.tags span { background:var(--bg2); border:1px solid var(--line); border-radius:999px;
  padding:3px 11px; font-size:12px; color:var(--muted); }
.read-foot { margin-top:26px; padding-top:18px; border-top:1px solid var(--line);
  display:flex; flex-wrap:wrap; gap:14px; font-size:13px; color:var(--muted); }
.read-foot a { color:var(--accent); }
.msg { color:var(--muted); font-size:14px; }
.msg.err { color:var(--err); }

/* 右侧:最上面是**Search the site**(下面那个虚线框留给以后的广告)。
   Search控件**与 home.html / search.html 逐字相同**:标记是下面那六个 id、行为在共享的
   `App.mountSearch()`、样式在 `/app.css` —— 所以按下「Search」的行为也一致(见 boot 里那三行)。
   2026-10-30 第二十八轮:先做了一版"纯 HTML 表单",**那是错的** —— 本页 CSP 里的
   `form-action 'none'` 会把真实的表单提交直接拒掉(浏览器控制台报 "Refused to send form data
   … because it violates form-action 'none'"),也就是说那一版**点下去什么都不会发生**。
   换成 JS 接管的共享控件(`preventDefault` + `window.open`)后,`form-action` 根本不参与。
   ⚠️ 以后往这一页加任何 `<form>` 都记住这一条:本页的表单**只能**由 JS 拦下后自己发请求。 */
/* **2026-10-30:与另外四页同一条规矩** —— 面板**不留白底 / 描边 / 投影**,底色交给共享表的
   `.tint-*`(见 `prose/web/app.css`):左栏三块(Columns by the same author / More by the same author / You might also like)
   = `tint-sky`,右栏那个Search控件 = `tint-lilac`。**正文那一栏刻意不刷色** —— 读字的地方
   多一层底只会更难读,它直接坐在页面底色上。浮层与控件(抽屉 / 对话框 / 输入框 / 按钮)保持
   不透明。 */
.panel { background: transparent; border-radius: 16px; overflow: hidden; }
/* home.html 的按钮族里这一页用得着的几个(顶栏两个 + Search那个 + Comments那两个)——
   以前 `btn-primary` / `btn-ghost` 这一页**没有定义**,"Post comment"与"Show more comments"都长得像
   裸按钮;补上之后与 write.html 的「Publish」/ home.html 的按钮同族。 */
.btn-primary { background:var(--btn); border-color:transparent; color:var(--btntext); }
.btn-primary:hover { opacity:.86; transform:translateY(-1px); }
.btn-ghost { background:transparent; border-color:var(--line); color:var(--text); }
.btn-ghost:hover { background:var(--bg2); }
.btn-accent { background:var(--accent); border-color:transparent; color:#ffffff; }
.btn-accent:hover { opacity:.88; transform:translateY(-1px); }
.btn:disabled { opacity:.55; cursor:not-allowed; transform:none; }
.btn-sm { padding:6px 12px; font-size:13px; border-radius:8px; }
.ad-rail .ad-slot { min-height:560px; border:1px dashed var(--line); border-radius:var(--radius-sm);
  display:flex; align-items:center; justify-content:center; color:var(--muted); font-size:11px;
  letter-spacing:.08em; }

@media (max-width:1080px) {
  .read-layout { grid-template-columns:minmax(0,1fr); gap:22px; }
  .rail, .ad-rail { position:static; max-height:none; }
  .reader { max-width:none; }
  .ad-rail .ad-slot { min-height:96px; }
  .rail { order:2; } .reader { order:1; } .ad-rail { order:3; }
}
  /* ---------- 互动:Like + Comments ---------- */
  .engage { display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    margin: 26px 0 8px; padding-top: 18px; border-top: 1px solid var(--line); }
  .like-btn { display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
    background: var(--bg2); border: 1px solid var(--line); color: var(--text);
    border-radius: 999px; padding: 9px 16px; font: inherit; font-size: 14px; transition: .18s; }
  .like-btn:hover:not(:disabled) { border-color: var(--accent); transform: translateY(-1px); }
  .like-btn:disabled { opacity: .55; cursor: default; transform: none; }
  .like-btn .like-heart { font-size: 16px; color: var(--muted); transition: .18s; }
  .like-btn.on { border-color: var(--accent); background: var(--accent2); color: var(--accent); }
  .like-btn.on .like-heart { color: var(--accent); transform: scale(1.15); }
  .like-count { color: var(--muted); font-variant-numeric: tabular-nums; }
  .like-btn.on .like-count { color: var(--accent); }
  /* Save(2026-11-02):**作者名那一行、紧挨「Report」**(用户:"Save要在 read.html 里每一篇Articles加
     按钮,可以和'Report'按钮接近")⇒ 外形与 `.report-btn` 同一套(小而低调)。☆ = 未Save、★ = Saved。
     Save是**私密**的(作者看不到),所以这里**故意不显示任何计数**。`margin-left:auto` 让它先占掉
     那一行的自由空间(Report紧随其后),两者因此一起被推到右端。 */
  .collect-btn { margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
    border: 1px solid var(--line); background: transparent; color: var(--muted);
    border-radius: 999px; padding: 4px 12px; font: inherit; font-size: 12.5px; cursor: pointer; }
  .collect-btn:hover { border-color: var(--accent); color: var(--accent); }
  .collect-btn:disabled { opacity: .5; cursor: default; }
  .collect-btn.on { border-color: var(--accent); background: var(--accent2); color: var(--accent); }
  .collect-btn .bm-icon { font-size: 13px; }
  .engage-hint { color: var(--muted); font-size: 13px; }
/* 「Report」= 让审核器复审一次(2026-11-01)。低调一点:它是给读者的兜底,不是主操作。 */
.report-btn { margin-left: auto; border: 1px solid var(--line); background: transparent;
  color: var(--muted); border-radius: 999px; padding: 4px 12px; font: inherit;
  font-size: 12.5px; cursor: pointer; }
.report-btn:hover { border-color: var(--err); color: var(--err); }
.report-btn:disabled { opacity: .5; cursor: default; }
/* Report的**理由框**(2026-11-01 用户定:"任何人投诉都要提供 20 chars以上的理由。为了避免Reads
   太多,最多不超过 200 chars"):一个 <dialog>,打开就把焦点放进文本框,**不够 20 chars时提交键
   一直是禁用的**(与"前端先拦、服务端再验一遍"同一条思路)。编辑框就是普通 textarea、
   **Plain text**(用户后来定:"Report理由就不用加粗了")—— 服务端会去掉 `*` `_` 这类标记字符。 */
.report-sheet { border: 0; border-radius: 14px; padding: 0; width: 92vw; max-width: 520px;
  background: var(--bg); color: var(--text); box-shadow: 0 14px 44px rgba(8, 13, 14, .32); }
.report-sheet::backdrop { background: rgba(8, 13, 14, .5); }
.report-sheet form { margin: 0; padding: 18px 20px 16px; }
.report-sheet h3 { margin: 0 0 6px; font-size: 16px; }
.report-sheet .hint { color: var(--muted); font-size: 12.5px; margin: 0 0 10px; }
.report-sheet textarea { width: 100%; font: inherit; font-size: 14px; line-height: 1.6;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--bg2); color: var(--text); resize: vertical; }
.report-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.report-actions .counter { flex: 1; color: var(--muted); font-size: 12.5px; }
.report-actions .counter.warn { color: var(--err); }
  .comments { margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--line); }
  .comments-title { font-size: 17px; margin: 0 0 12px; }
  .comments-title span { color: var(--muted); font-weight: 400; font-size: 14px; }
  #commentInput { width: 100%; min-height: 84px; max-height: 260px; resize: vertical;
    background: var(--bg2); border: 1px solid var(--line); border-radius: 12px;
    padding: 11px 13px; color: var(--text); font: inherit; }
  #commentInput:focus { outline: none; border-color: var(--accent); }
  .comment-tools { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
  .tool-btn { width: 32px; height: 30px; border-radius: 8px; border: 1px solid var(--line);
    background: var(--bg2); color: var(--text); cursor: pointer; font: inherit; line-height: 1; }
  .tool-btn:hover { border-color: var(--accent); color: var(--accent); }
  .comment-tip { color: var(--muted); font-size: 12.5px; }
  .comment-preview { margin-top: 10px; padding: 10px 12px; border: 1px dashed var(--line);
    border-radius: 10px; background: var(--bg2); }
  .preview-label { display: block; color: var(--muted); font-size: 11.5px; margin-bottom: 4px; }
  .comment-body strong { font-weight: 700; }
  .comment-actions { display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-top: 10px; }
  .comment-han { color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; }
  .comment-han.ok { color: var(--ok); }
  .comments-login { color: var(--muted); font-size: 13.5px; }
  .comment-list { margin-top: 6px; }
  .comment { display: flex; gap: 12px; padding: 14px 0; border-top: 1px solid var(--line); }
  .comment-face { width: 34px; height: 34px; flex: none; border-radius: 11px; display: flex;
    align-items: center; justify-content: center; font-weight: 700; font-size: 14px;
    background: var(--accent2); color: var(--accent); }
  .comment-main { flex: 1; min-width: 0; }
  .comment-head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
  .comment-head b { font-size: 14px; }
  .comment-head time, .comment-head span { color: var(--muted); font-size: 12px; }
  .comment-body { margin: 5px 0 0; white-space: pre-wrap; word-break: break-word; }
  .comment-del { border: 0; background: none; color: var(--muted); cursor: pointer;
    font-size: 12.5px; padding: 2px 4px; margin-left: auto; }
  .comment-del:hover { color: var(--err); }
  /* CommentsLike:画的一律是服务端回来的数字(去重靠唯一索引,不由前端猜)。 */
  .comment-foot { display: flex; align-items: center; gap: 14px; margin-top: 6px; }
  .comment-like { border: 0; background: none; color: var(--muted); cursor: pointer;
    font: inherit; font-size: 12.5px; padding: 2px 6px; border-radius: 7px;
    display: inline-flex; align-items: center; gap: 5px; transition: .15s; }
  .comment-like:hover:not(:disabled) { color: var(--accent); background: var(--accent2); }
  .comment-like.on { color: var(--accent); font-weight: 600; }
  .comment-like:disabled { opacity: .5; cursor: default; }
  .comment-like .heart { font-size: 13px; line-height: 1; }
  /* Reply:所有层级的Reply**只缩进一次**(第三层在后端就被拉平到同一个顶层下面了)。 */
  .reply-list { margin: 6px 0 0 4px; padding-left: 14px; border-left: 2px solid var(--line); }
  .reply-list .comment { border-top: 0; padding: 8px 0 0; }
  .reply-list .comment-face { width: 26px; height: 26px; border-radius: 9px; font-size: 12px; }
  .reply-list .comment-body { font-size: 14.5px; }
  .comment-gone { color: var(--muted); font-style: italic; }
  .comment-reply-btn, .comment-more-replies { border: 0; background: none; color: var(--muted);
    cursor: pointer; font: inherit; font-size: 12.5px; padding: 2px 6px; border-radius: 7px; }
  .comment-reply-btn:hover:not(:disabled) { color: var(--accent); background: var(--accent2); }
  .comment-reply-btn:disabled { opacity: .5; cursor: default; }
  .comment-more-replies { color: var(--accent); padding: 7px 0 0; }
  /* Hot置顶:一条分隔Title + 每行一枚「Hot」小标 */
  .pinned-head { color: var(--muted); font-size: 12.5px; margin: 14px 0 0;
    padding-top: 12px; border-top: 1px solid var(--line); letter-spacing: .04em; }
  .pin-chip { border: 1px solid var(--accent); color: var(--accent); border-radius: 999px;
    padding: 0 6px; font-size: 11px; line-height: 1.5; }
  .reply-to { color: var(--muted); font-size: 12px; }
  .reply-form { margin-top: 9px; }
  .reply-input { width: 100%; min-height: 66px; max-height: 220px; resize: vertical;
    background: var(--bg2); border: 1px solid var(--line); border-radius: 10px;
    padding: 9px 11px; color: var(--text); font: inherit; font-size: 14px; }
  .reply-input:focus { outline: none; border-color: var(--accent); }
  .reply-form-foot { display: flex; align-items: center; gap: 10px; margin-top: 7px; }
  .reply-form-foot .comment-tip { margin-right: auto; }
  .reply-form-foot button { font-size: 13px; padding: 6px 13px; }

/* 2026-11-07:语言开关。中文页上写 English,英文页上写 中文。 */
.lang-switch { font-size: 13px; font-weight: 600; color: var(--accent);
  border: 1px solid var(--line); border-radius: 12px; padding: 4px 12px;
  white-space: nowrap; display: inline-block; }
.lang-switch:hover { border-color: var(--accent); background: var(--accent2); }