reader-content.css 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /* resources/css/modules/reader-content.css
  2. 阅读器正文排版。所有规则限定在 article.reader-body 作用域内。
  3. 包含:基础排版、Tufte sidenote 集成、响应式断点对齐。
  4. */
  5. /* ══════════════════════════════════════════
  6. 一、作用域根:正文必须用 <article class="reader-body"> 包裹
  7. ══════════════════════════════════════════ */
  8. article.reader-body {
  9. font-family: 'Noto Serif', Georgia, serif;
  10. font-size: 1.05rem;
  11. line-height: 1.75;
  12. color: inherit;
  13. counter-reset: sidenote-counter;
  14. }
  15. article.reader-body div.sentence {
  16. display: inline;
  17. }
  18. article.reader-body .para-block {
  19. margin-bottom: 1em;
  20. }
  21. /* ── 段落 ── */
  22. article.reader-body p {
  23. margin-bottom: 1.25rem;
  24. padding-right: 0;
  25. vertical-align: baseline;
  26. }
  27. /* ── 标题 ── */
  28. article.reader-body h1,
  29. article.reader-body h2,
  30. article.reader-body h3,
  31. article.reader-body h4 {
  32. font-weight: 600;
  33. line-height: 1.3;
  34. margin-top: 2rem;
  35. margin-bottom: 0.75rem;
  36. }
  37. /* ── 列表:只在正文内收缩,不影响外部 ── */
  38. article.reader-body ul,
  39. article.reader-body ol {
  40. padding-left: 1.5rem;
  41. margin-bottom: 1.25rem;
  42. }
  43. article.reader-body li {
  44. line-height: 1.7;
  45. margin-bottom: 0.25rem;
  46. }
  47. /* ── 引用块 ── */
  48. article.reader-body blockquote {
  49. margin: 1.5rem 0 1.5rem 0;
  50. padding: 0.75rem 1.25rem;
  51. border-left: 3px solid var(--tblr-border-color);
  52. color: var(--tblr-secondary);
  53. font-style: italic;
  54. }
  55. /* ── 分割线 ── */
  56. article.reader-body hr {
  57. display: block;
  58. height: 1px;
  59. border: 0;
  60. border-top: 1px solid #ccc;
  61. margin: 2em 0;
  62. }
  63. /* ── 代码块 ── */
  64. article.reader-body pre > code {
  65. display: block;
  66. overflow-x: auto;
  67. font-size: 0.9rem;
  68. line-height: 1.5;
  69. padding: 1rem;
  70. background: var(--tblr-bg-surface-secondary);
  71. border-radius: var(--tblr-border-radius);
  72. }
  73. /* ══════════════════════════════════════════
  74. 二、Tufte Sidenote / Marginnote
  75. 断点与 reader 对齐:>= 992px 浮动显示,< 992px 点击展开
  76. ══════════════════════════════════════════ */
  77. /* 触发标签(手机/平板用) */
  78. article.reader-body input.margin-toggle {
  79. display: none;
  80. }
  81. article.reader-body label.sidenote-number {
  82. display: inline-block;
  83. max-height: 1.75rem;
  84. }
  85. /* ≥ 992px:浮动 sidenote,右侧边栏同时存在,布局一致 */
  86. @media (min-width: 992px) {
  87. article.reader-body label.margin-toggle:not(.sidenote-number) {
  88. display: none;
  89. }
  90. article.reader-body .sidenote,
  91. article.reader-body .marginnote {
  92. float: right;
  93. clear: right;
  94. margin-right: -35%;
  95. width: 28%;
  96. margin-top: 0.3rem;
  97. margin-bottom: 0;
  98. font-size: 0.875rem;
  99. line-height: 1.4;
  100. vertical-align: baseline;
  101. position: relative;
  102. border: 1px solid wheat;
  103. padding: 6px;
  104. border-radius: 8px;
  105. background-color: #f5deb330;
  106. }
  107. .dark-mode article.reader-body .sidenote,
  108. .dark-mode article.reader-body .marginnote {
  109. border-color: #6b5a3e;
  110. background-color: rgba(139, 109, 56, 0.15);
  111. }
  112. }
  113. /* < 992px:与手机一致,点击展开 */
  114. @media (max-width: 991px) {
  115. article.reader-body label.margin-toggle:not(.sidenote-number) {
  116. display: inline;
  117. cursor: pointer;
  118. color: var(--tblr-primary);
  119. }
  120. article.reader-body .sidenote,
  121. article.reader-body .marginnote {
  122. display: none;
  123. }
  124. article.reader-body .margin-toggle:checked + .sidenote,
  125. article.reader-body .margin-toggle:checked + .marginnote {
  126. display: block;
  127. float: left;
  128. left: 0;
  129. clear: both;
  130. width: 95%;
  131. margin: 0.75rem 2.5%;
  132. position: relative;
  133. border: 1px solid wheat;
  134. padding: 6px;
  135. border-radius: 8px;
  136. background-color: #f5deb330;
  137. }
  138. }
  139. /* sidenote 编号上标:编号由 JS 按「段」分组写入 data-idx(见 reader.js 的
  140. numberAnnotations),与段后脚注的 [N] 一一对应,可互跳。 */
  141. article.reader-body .sidenote-number::after,
  142. article.reader-body .sidenote::before {
  143. position: relative;
  144. vertical-align: baseline;
  145. }
  146. article.reader-body .sidenote-number::after {
  147. content: '[' attr(data-idx) ']';
  148. font-size: 0.75rem;
  149. top: -0.5rem;
  150. left: 0.1rem;
  151. color: var(--tblr-primary);
  152. }
  153. article.reader-body .sidenote::before {
  154. content: attr(data-idx) ' ';
  155. font-size: 0.75rem;
  156. top: -0.5rem;
  157. }
  158. /* ══════════════════════════════════════════
  159. 三、Commentary 注释(点击展开,始终在句子下方)
  160. DOM 结构(由 JS 注入):
  161. div.sentence
  162. input.commentary-toggle#commentary-N
  163. div.commentary-note[data-uuid]
  164. ══════════════════════════════════════════ */
  165. /* checkbox 隐藏 */
  166. article.reader-body input.commentary-toggle {
  167. display: none;
  168. }
  169. /* icon label:行内,插在句子文字末尾 */
  170. article.reader-body label.commentary-icon {
  171. display: inline;
  172. cursor: pointer;
  173. margin-left: 4px;
  174. color: var(--tblr-primary);
  175. vertical-align: middle;
  176. font-size: 0.85rem;
  177. user-select: none;
  178. transition: opacity 0.15s;
  179. }
  180. article.reader-body label.commentary-icon:hover {
  181. opacity: 0.7;
  182. }
  183. /* 注释块默认隐藏 */
  184. article.reader-body .commentary-note {
  185. display: none;
  186. }
  187. /* 展开:checkbox checked → 相邻的 .commentary-note 显示 */
  188. article.reader-body .commentary-toggle:checked + .commentary-note {
  189. display: block;
  190. clear: both;
  191. width: 95%;
  192. margin: 0.5rem 2.5% 0.75rem;
  193. padding: 8px 12px;
  194. border-left: 3px solid var(--tblr-primary);
  195. border-radius: 0 6px 6px 0;
  196. background-color: #f5deb330;
  197. font-size: 0.875rem;
  198. line-height: 1.6;
  199. }
  200. .dark-mode article.reader-body .commentary-toggle:checked + .commentary-note {
  201. background-color: rgba(139, 109, 56, 0.15);
  202. }
  203. /* ══════════════════════════════════════════
  204. 三·五、注释呈现模式(行内 / 段后)
  205. 「段后」时正文保留角标 [N],注释以脚注列表缀在段后;「行内」沿用 sidenote 边注。
  206. DOM 结构与 wikipali-mobile 的 ReaderLayerPane 保持一致。
  207. ══════════════════════════════════════════ */
  208. /* 段后脚注列表:默认(行内模式)隐藏,段后模式由 [data-annotation-mode] 打开 */
  209. article.reader-body .anno-footnotes {
  210. display: none;
  211. margin: 0.5rem 0 1rem;
  212. }
  213. article.reader-body .anno-footnote {
  214. margin: 0.4rem 0;
  215. font-size: 0.875rem;
  216. line-height: 1.6;
  217. color: var(--tblr-secondary);
  218. border: 1px solid var(--tblr-border-color);
  219. border-radius: 6px;
  220. padding: 6px 10px;
  221. }
  222. article.reader-body .anno-fn-toggle {
  223. display: none;
  224. }
  225. article.reader-body .anno-fn-label {
  226. display: flex;
  227. align-items: flex-start;
  228. cursor: pointer;
  229. }
  230. article.reader-body .anno-fn-num {
  231. color: var(--tblr-primary);
  232. flex: none;
  233. margin-right: 0.45em;
  234. cursor: pointer;
  235. }
  236. /* 脚注正文默认收起为一行,点击展开 */
  237. article.reader-body .anno-fn-body {
  238. flex: 1;
  239. min-width: 0;
  240. display: -webkit-box;
  241. -webkit-line-clamp: 1;
  242. -webkit-box-orient: vertical;
  243. overflow: hidden;
  244. cursor: pointer;
  245. }
  246. article.reader-body .anno-fn-toggle:checked + .anno-fn-label .anno-fn-body {
  247. -webkit-line-clamp: unset;
  248. display: block;
  249. overflow: visible;
  250. }
  251. /* 义注跳转 cite:收起时隐藏,展开才显示 */
  252. article.reader-body .anno-footnote .anno-jump {
  253. display: none;
  254. margin-left: 0.4em;
  255. font-style: normal;
  256. color: var(--tblr-primary);
  257. }
  258. article.reader-body .anno-fn-toggle:checked ~ .anno-jump {
  259. display: inline;
  260. }
  261. /* 互跳高亮 */
  262. article.reader-body .anno-highlight {
  263. background: rgba(32, 107, 196, 0.16);
  264. border-radius: 3px;
  265. transition: background 0.5s;
  266. }
  267. /* 段后模式:显示段后脚注列表,隐藏 sidenote(角标保留) */
  268. article.reader-body[data-annotation-mode="footnote"] .anno-footnotes {
  269. display: block;
  270. }
  271. article.reader-body[data-annotation-mode="footnote"] .sidenote {
  272. display: none !important;
  273. }
  274. /* ══════════════════════════════════════════
  275. 四、正文内 origin(原文显示)
  276. ══════════════════════════════════════════ */
  277. article.reader-body .origin {
  278. color: darkred;
  279. }
  280. .dark-mode article.reader-body .origin {
  281. color: #ff8a8a;
  282. }
  283. /* ══════════════════════════════════════════
  284. 五、Epigraph(题词)
  285. ══════════════════════════════════════════ */
  286. article.reader-body div.epigraph {
  287. margin: 3em 0;
  288. }
  289. article.reader-body div.epigraph > blockquote,
  290. article.reader-body div.epigraph > blockquote > p {
  291. font-style: italic;
  292. }
  293. article.reader-body div.epigraph > blockquote > footer {
  294. font-style: normal;
  295. text-align: right;
  296. font-size: 0.9rem;
  297. }
  298. article.reader-body.evaluate-fatal {
  299. background-color: rgb(185 34 255 / 50%);
  300. }
  301. article.reader-body .evaluate-error {
  302. background-color: #ff232393;
  303. }
  304. article.reader-body .evaluate-warning {
  305. background-color: #e97a3086;
  306. }
  307. article.reader-body .evaluate-suggestion {
  308. background-color: #c4f8c6;
  309. }
  310. /* ══════════════════════════════════════════
  311. 六、偈颂(Gatha / Verse)排版
  312. 原文与译文共用的五类 class:hangnum / gatha1 / gatha2 / gatha3 / gathalast。
  313. 每首偈 = 一个 hangnum(偈颂号,可选)+ gatha1(首行)+ 若干中间行 + gathalast(末行)。
  314. 要求:偈颂之间的间隔 > 偈颂内部行之间的间隔;与散文混排时偈颂缩进、收紧行距以区分。
  315. ══════════════════════════════════════════ */
  316. /* 偈颂号(hangnum):悬挂在左侧页边,右对齐,字号缩小,与首行基线对齐。
  317. 原文的号是纯文本「 1.」,部分译文的号被 markdown 渲染成 <ol start="2"><li></li></ol>,
  318. 两种都归一化成同一个小号数字。 */
  319. article.reader-body .hangnum {
  320. float: left;
  321. clear: left;
  322. width: 2rem;
  323. margin-right: 0.5rem;
  324. text-align: right;
  325. font-size: 0.8125rem;
  326. line-height: 1.75;
  327. color: var(--tblr-secondary);
  328. user-select: none;
  329. }
  330. article.reader-body .hangnum .para-block {
  331. margin-bottom: 0;
  332. }
  333. article.reader-body .hangnum ol {
  334. list-style: decimal;
  335. list-style-position: inside;
  336. padding: 0;
  337. margin: 0;
  338. }
  339. article.reader-body .hangnum li {
  340. margin: 0;
  341. line-height: inherit;
  342. list-style-type: decimal;
  343. list-style-position: inside;
  344. }
  345. /* 偈颂行:整体缩进,让出偈颂号的空间 */
  346. article.reader-body .gatha1,
  347. article.reader-body .gatha2,
  348. article.reader-body .gatha3,
  349. article.reader-body .gathalast {
  350. margin-left: 2.5rem;
  351. }
  352. /* 偈颂内部行距收紧;折行时悬挂缩进,续行比首行再缩进 1.25em */
  353. article.reader-body .gatha1 .para-block,
  354. article.reader-body .gatha2 .para-block,
  355. article.reader-body .gatha3 .para-block,
  356. article.reader-body .gathalast .para-block {
  357. margin-bottom: 0.3em;
  358. padding-left: 1.25em;
  359. text-indent: -1.25em;
  360. }
  361. /* 偈颂末行:与下一偈(或散文)之间留更大间隔 */
  362. article.reader-body .gathalast .para-block {
  363. margin-bottom: 1.75em;
  364. }
  365. /* ══════════════════════════════════════════
  366. 七、居中文本(centered)
  367. 开头致敬语(Namo tassa…)与经末结语(… niṭṭhitaṃ / ……竟)。
  368. ══════════════════════════════════════════ */
  369. article.reader-body .centered {
  370. text-align: center;
  371. }
  372. article.reader-body .centered .para-block {
  373. margin-bottom: 1.5em;
  374. }
  375. /* ══════════════════════════════════════════
  376. 八、issue 标注
  377. PaliContentService::injectAnnotationNotes 注入:有位置的 issue 是 span.anno-issue(高亮原文),
  378. 没有位置的是句尾的 span.anno-issue-mark(三角叹号图标)。颜色按 severity:
  379. error 红、warning 橙、suggestion 蓝,没有 severity 的灰。点击由 reader.js 弹出内容。
  380. 与 .evaluate-*(整块底色)区分:这里用波浪下划线 + 淡底色。
  381. ══════════════════════════════════════════ */
  382. article.reader-body .anno-issue-error { --anno-issue-color: var(--tblr-danger); }
  383. article.reader-body .anno-issue-warning { --anno-issue-color: var(--tblr-warning); }
  384. article.reader-body .anno-issue-suggestion { --anno-issue-color: var(--tblr-info); }
  385. article.reader-body .anno-issue-none { --anno-issue-color: var(--tblr-secondary); }
  386. article.reader-body span.anno-issue {
  387. cursor: pointer;
  388. text-decoration: underline wavy var(--anno-issue-color);
  389. text-decoration-skip-ink: none;
  390. text-underline-offset: 0.25em;
  391. background-color: color-mix(in srgb, var(--anno-issue-color) 12%, transparent);
  392. border-radius: 2px;
  393. }
  394. article.reader-body span.anno-issue:hover,
  395. article.reader-body span.anno-issue.is-active {
  396. background-color: color-mix(in srgb, var(--anno-issue-color) 26%, transparent);
  397. }
  398. article.reader-body span.anno-issue-mark {
  399. cursor: pointer;
  400. margin-left: 0.15em;
  401. color: var(--anno-issue-color);
  402. font-size: 0.95em;
  403. vertical-align: -0.05em;
  404. }
  405. article.reader-body span.anno-issue-mark:hover,
  406. article.reader-body span.anno-issue-mark.is-active {
  407. filter: brightness(0.85);
  408. }
  409. /* 弹出层:桌面 popover 与手机抽屉共用的条目样式 */
  410. .anno-issue-list {
  411. max-height: 60vh;
  412. overflow-y: auto;
  413. }
  414. .anno-issue-item + .anno-issue-item {
  415. margin-top: 0.75rem;
  416. padding-top: 0.75rem;
  417. border-top: 1px solid var(--tblr-border-color);
  418. }
  419. .anno-issue-item-head {
  420. display: flex;
  421. align-items: center;
  422. gap: 0.4rem;
  423. font-weight: 600;
  424. }
  425. .anno-issue-item-head .ti {
  426. color: var(--anno-issue-color, var(--tblr-secondary));
  427. }
  428. .anno-issue-item-body {
  429. margin-top: 0.25rem;
  430. white-space: pre-line;
  431. }
  432. .anno-issue-item-meta {
  433. margin-top: 0.25rem;
  434. font-size: 0.8125rem;
  435. color: var(--tblr-secondary);
  436. }
  437. .anno-issue-popover {
  438. --bs-popover-max-width: 22rem;
  439. }
  440. .anno-issue-item.anno-issue-error { --anno-issue-color: var(--tblr-danger); }
  441. .anno-issue-item.anno-issue-warning { --anno-issue-color: var(--tblr-warning); }
  442. .anno-issue-item.anno-issue-suggestion { --anno-issue-color: var(--tblr-info); }