book-kit 0.0.0-stage → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE.md +72 -0
- package/README.md +251 -2
- package/bin/book-kit.js +115 -0
- package/commands/_emoji_io.py +32 -0
- package/commands/audit-chapter-lengths.js +244 -0
- package/commands/check-epub-size.js +68 -0
- package/commands/check-pdf-page-count.js +162 -0
- package/commands/composite-kindle-emoji.py +85 -0
- package/commands/composite-print-emoji.py +98 -0
- package/commands/conventions.js +76 -0
- package/commands/convert-pdfx.sh +194 -0
- package/commands/download-icc-profile.sh +105 -0
- package/commands/fonts.py +212 -0
- package/commands/generate-reference-docx.py +344 -0
- package/commands/kindle-fonts.js +173 -0
- package/commands/links-to-footnotes.js +366 -0
- package/commands/markdownlint.js +25 -0
- package/commands/minify-css.js +43 -0
- package/commands/optimize-images.js +73 -0
- package/commands/parity.sh +150 -0
- package/commands/postprocess-epub.js +541 -0
- package/commands/prep-print-src.js +77 -0
- package/commands/prose.js +38 -0
- package/commands/release-files.js +89 -0
- package/commands/reorder-print-frontmatter.js +79 -0
- package/commands/strip-page-rules.js +1168 -0
- package/commands/strip-property-rules.js +93 -0
- package/commands/update-key-takeaways.js +314 -0
- package/commands/validate.js +283 -0
- package/configs/markdownlint-cli2.jsonc +98 -0
- package/configs/textlintrc.json +22 -0
- package/css/theme/01-tokens.css +83 -0
- package/css/theme/02-fonts.css +79 -0
- package/css/theme/03-prose.css +53 -0
- package/css/theme/04-base.css +226 -0
- package/css/theme/05-components.css +546 -0
- package/css/theme/06-utilities.css +40 -0
- package/css/theme/07-ereader.css +245 -0
- package/css/theme/08-epub.css +865 -0
- package/css/theme/09-back-matter.css +47 -0
- package/css/theme/10-dark.css +302 -0
- package/css/theme/11-print.css +1229 -0
- package/css/theme.css +38 -0
- package/defaults/book.config.yml +318 -0
- package/defaults/pandoc-base.yml +19 -0
- package/defaults/pandoc-docx.yml +6 -0
- package/defaults/pandoc-epub-fonts.yml +6 -0
- package/defaults/pandoc-epub.yml +15 -0
- package/defaults/pandoc-kindle.yml +6 -0
- package/emoji/1f382.png +0 -0
- package/emoji/1f389.png +0 -0
- package/emoji/1f440.png +0 -0
- package/emoji/1f44d.png +0 -0
- package/emoji/1f44f.png +0 -0
- package/emoji/1f454.png +0 -0
- package/emoji/1f4a1.png +0 -0
- package/emoji/1f4bb.png +0 -0
- package/emoji/1f602.png +0 -0
- package/emoji/1f603.png +0 -0
- package/emoji/1f604.png +0 -0
- package/emoji/1f60a.png +0 -0
- package/emoji/1f60f.png +0 -0
- package/emoji/1f64c.png +0 -0
- package/emoji/1f64f.png +0 -0
- package/emoji/1f914.png +0 -0
- package/emoji/1f923.png +0 -0
- package/emoji/2714.png +0 -0
- package/emoji/274c.png +0 -0
- package/filters/add-div-titles.lua +196 -0
- package/filters/arc-notice.lua +36 -0
- package/filters/body-emoji-images.lua +48 -0
- package/filters/callout-classes.lua +40 -0
- package/filters/lib/book_kit.lua +110 -0
- package/filters/revision.lua +17 -0
- package/filters/strip-comments.lua +40 -0
- package/filters/strip-emoji-kindle.lua +134 -0
- package/fonts/LICENSE-source-code-pro.md +93 -0
- package/fonts/LICENSE-source-sans.md +93 -0
- package/fonts/LICENSE-source-serif.md +93 -0
- package/fonts/recipe.json +41 -0
- package/just/book-kit.just +229 -0
- package/lib/acronyms.js +47 -0
- package/lib/callouts.js +17 -0
- package/lib/config.js +211 -0
- package/lib/is-main.js +21 -0
- package/lib/lint.js +148 -0
- package/lib/pandoc.js +148 -0
- package/lib/paragraphs.js +173 -0
- package/lib/revision.js +35 -0
- package/lib/structure.js +39 -0
- package/lib/textlint-github-formatter.js +58 -0
- package/lib/validate.js +202 -0
- package/package.json +98 -4
- package/presets/business-nonfiction/CONVENTIONS.md +35 -0
- package/presets/business-nonfiction/preset.yml +128 -0
- package/profiles/pdfx-def.ps +42 -0
- package/requirements.txt +14 -0
- package/rules/no-ai-like-patterns.js +209 -0
- package/rules/no-assumptive.js +76 -0
- package/rules/no-bare-acronyms.js +129 -0
- package/rules/no-cliches.js +544 -0
- package/rules/no-cultural-idioms.js +422 -0
- package/rules/no-vague-intensifiers.js +94 -0
- package/templates/template-epub.html +79 -0
- package/templates/template.html +73 -0
- package/toolchain.json +42 -0
- package/validators/acronym-expansion.js +94 -0
- package/validators/bold-keywords.js +56 -0
- package/validators/callout-balance.js +74 -0
- package/validators/callout-divs.js +66 -0
- package/validators/callout-labels.js +102 -0
- package/validators/chapter-lengths.js +14 -0
- package/validators/chapter.js +57 -0
- package/validators/cross-references.js +45 -0
- package/validators/doubled-words.js +76 -0
- package/validators/duplicate-headings.js +52 -0
- package/validators/em-dashes.js +73 -0
- package/validators/escaped-smallcaps.js +46 -0
- package/validators/footnotes.js +78 -0
- package/validators/heading-hierarchy.js +58 -0
- package/validators/hypothetical-hooks.js +103 -0
- package/validators/index-integrity.js +28 -0
- package/validators/index.js +73 -0
- package/validators/list-punctuation.js +123 -0
- package/validators/min-opener-length.js +87 -0
- package/validators/no-bare-url-link-text.js +38 -0
- package/validators/no-todo-markers.js +49 -0
- package/validators/no-transition-todos.js +34 -0
- package/validators/number-range-dashes.js +72 -0
- package/validators/paragraph-length.js +62 -0
- package/validators/quote-punctuation.js +85 -0
- package/validators/section-intro-final-lead.js +90 -0
- package/validators/section-intro-has-lead.js +41 -0
- package/validators/section-intro-no-tldr.js +37 -0
- package/validators/section-intros.js +33 -0
- package/validators/sentence-starters.js +132 -0
- package/validators/smallcaps.js +67 -0
- package/validators/tldr-length.js +58 -0
|
@@ -0,0 +1,865 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
EPUB / E-READER OVERRIDES (@media not screen)
|
|
3
|
+
These rules apply to EPUB and Kindle output.
|
|
4
|
+
strip-page-rules.js unwraps this block so rules
|
|
5
|
+
apply unconditionally in dist/style-epub.css.
|
|
6
|
+
Key constraints:
|
|
7
|
+
• Use em (not rem) for heading sizes (Kindle)
|
|
8
|
+
• Body typography (line-height, text-align, etc.)
|
|
9
|
+
must be inherit/normal — e-readers control these
|
|
10
|
+
• font-weight 300 → 400 (e-ink can't render light)
|
|
11
|
+
============================================ */
|
|
12
|
+
|
|
13
|
+
/* Justified text with hyphenation for non-screen (EPUB/e-reader) builds.
|
|
14
|
+
Most modern EPUB readers (Apple Books, Kobo, Google Play Books) handle
|
|
15
|
+
justified text well with hyphens:auto. Kindle uses its own justification
|
|
16
|
+
engine regardless of CSS. However, per Amazon's Kindle Publishing
|
|
17
|
+
Guidelines, we should NOT override reader-controlled properties (line-height,
|
|
18
|
+
text-align, letter-spacing, word-spacing) globally — readers retain full
|
|
19
|
+
control. We set hyphens (which readers don't typically control) and let
|
|
20
|
+
the e-reader handle the rest. */
|
|
21
|
+
@media not screen {
|
|
22
|
+
body {
|
|
23
|
+
/* Force pure black text for e-ink readability.
|
|
24
|
+
Screen uses #495057 (--color-emphasis) which looks washed-out
|
|
25
|
+
on Kindle's 16-level grayscale display. */
|
|
26
|
+
color: #000;
|
|
27
|
+
hyphens: auto;
|
|
28
|
+
-webkit-hyphens: auto;
|
|
29
|
+
line-height: inherit;
|
|
30
|
+
text-align: inherit;
|
|
31
|
+
letter-spacing: normal;
|
|
32
|
+
word-spacing: normal;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Every EPUB chapter is <body class="prose">, and Tailwind Typography's
|
|
36
|
+
.prose { line-height: 1.75 } outranks the body rule above (class beats
|
|
37
|
+
element), so readers' line-spacing settings were ignored. Hand it back.
|
|
38
|
+
This also matches in print (WeasyPrint's print media is "not screen"),
|
|
39
|
+
where the print body rule's !important line-height still wins. */
|
|
40
|
+
.prose {
|
|
41
|
+
line-height: inherit;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Don't hyphenate headings or callout labels */
|
|
46
|
+
h1,
|
|
47
|
+
h2,
|
|
48
|
+
h3,
|
|
49
|
+
h4,
|
|
50
|
+
h5,
|
|
51
|
+
h6 {
|
|
52
|
+
hyphens: none;
|
|
53
|
+
-webkit-hyphens: none;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Section intro headings — decorative rule matching PDF style */
|
|
57
|
+
h1:not(.title) {
|
|
58
|
+
padding-top: 1.5em;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Give breathing room between chapter title and TL;DR */
|
|
62
|
+
h2 + .tldr {
|
|
63
|
+
margin-top: 1.5rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* First paragraph after TL;DR gets extra breathing room */
|
|
67
|
+
.tldr + p {
|
|
68
|
+
margin-top: 1.25rem;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* EPUB callout labels — injected by Lua filter (add-div-titles.lua).
|
|
72
|
+
PDF uses ::before pseudo-elements with font-variant-caps: all-small-caps
|
|
73
|
+
rendered via real OpenType smcp/c2sc features in Source Sans 3.
|
|
74
|
+
E-readers can't do proper small caps — they synthesize by uppercasing,
|
|
75
|
+
which looks crude. Instead, use sans-serif bold with letter-spacing
|
|
76
|
+
for a clean label that approximates PDF's refined small-caps look.
|
|
77
|
+
Keep the inline label itself on one line; actual pagination control must
|
|
78
|
+
happen at the source markup level, not via `page-break-*` on this span. */
|
|
79
|
+
.callout-label {
|
|
80
|
+
font-family: var(--font-heading);
|
|
81
|
+
font-weight: 700;
|
|
82
|
+
letter-spacing: 0.04em;
|
|
83
|
+
color: #333;
|
|
84
|
+
white-space: nowrap;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* EPUB-optimized callout boxes — shared base */
|
|
88
|
+
.tldr,
|
|
89
|
+
.callout,
|
|
90
|
+
.note,
|
|
91
|
+
.tip,
|
|
92
|
+
.warning,
|
|
93
|
+
.pro-tip,
|
|
94
|
+
.for-managers,
|
|
95
|
+
.for-ics,
|
|
96
|
+
.common-objection,
|
|
97
|
+
.takeaways {
|
|
98
|
+
/* Ensure callouts don't break across pages */
|
|
99
|
+
page-break-inside: avoid;
|
|
100
|
+
break-inside: avoid;
|
|
101
|
+
/* Override the components-layer `box-decoration-break: clone` for e-readers.
|
|
102
|
+
clone is wanted in the PDF (WeasyPrint draws a complete border on each
|
|
103
|
+
page fragment) but on Kindle it signals the box is splittable, which can
|
|
104
|
+
defeat `page-break-inside: avoid` — the reader allocates the callout's
|
|
105
|
+
top edge + a sliver at the bottom of the preceding page and flows the
|
|
106
|
+
rest over, leaving an orphaned left-border strip behind. slice (the
|
|
107
|
+
default) lets `avoid` keep the callout whole. Print keeps clone via the
|
|
108
|
+
components layer, which @media not screen doesn't touch. */
|
|
109
|
+
-webkit-box-decoration-break: slice;
|
|
110
|
+
box-decoration-break: slice;
|
|
111
|
+
/* Generous breathing room for e-readers */
|
|
112
|
+
margin-top: 1.5rem;
|
|
113
|
+
margin-bottom: 1.5rem;
|
|
114
|
+
padding: 1em 1.5em;
|
|
115
|
+
border-radius: 4px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* Distinct callout identities for e-readers
|
|
119
|
+
Each callout type uses a different color solid left border. */
|
|
120
|
+
.tldr {
|
|
121
|
+
border-left: 4px solid var(--color-summary-border);
|
|
122
|
+
background-color: var(--color-summary-bg);
|
|
123
|
+
/* Override the components-layer font-weight: 300 (light) for EPUB.
|
|
124
|
+
Light weights render poorly on e-ink displays and some readers
|
|
125
|
+
only support 400/700, so 300 may be indistinguishable from 400. */
|
|
126
|
+
font-weight: 400;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.pro-tip {
|
|
130
|
+
border-left: 3px solid var(--color-tip-accent);
|
|
131
|
+
background-color: #fafaf7;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.for-managers {
|
|
135
|
+
border-left: 3px solid var(--color-manager-accent);
|
|
136
|
+
background-color: #f5f8fc;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.for-ics {
|
|
140
|
+
border-left: 3px solid var(--color-ic-accent);
|
|
141
|
+
background-color: #f5fbf6;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.common-objection {
|
|
145
|
+
border-left: 3px solid var(--color-objection-accent);
|
|
146
|
+
background-color: #fdf5f7;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.takeaways {
|
|
150
|
+
border-left: 3px solid var(--color-takeaway-border);
|
|
151
|
+
background-color: var(--color-takeaway-bg);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.note,
|
|
155
|
+
.callout {
|
|
156
|
+
border-left: 3px solid var(--color-note-accent);
|
|
157
|
+
background-color: var(--color-note-bg);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.tip {
|
|
161
|
+
border-left: 3px solid var(--color-tip-accent);
|
|
162
|
+
background-color: #fafaf7;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.warning {
|
|
166
|
+
border-left: 3px solid var(--color-warning-accent);
|
|
167
|
+
background-color: var(--color-warning-bg);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Ensure callout paragraphs display as blocks in EPUB.
|
|
171
|
+
The components layer sets p:first-child to display:inline for ::before
|
|
172
|
+
flow, but EPUB strips ::before (Lua filter injects labels instead).
|
|
173
|
+
We need :first-child specificity to override the component rule. */
|
|
174
|
+
.tldr p:first-child,
|
|
175
|
+
.callout p:first-child,
|
|
176
|
+
.note p:first-child,
|
|
177
|
+
.tip p:first-child,
|
|
178
|
+
.warning p:first-child,
|
|
179
|
+
.pro-tip p:first-child,
|
|
180
|
+
.for-managers p:first-child,
|
|
181
|
+
.for-ics p:first-child,
|
|
182
|
+
.common-objection p:first-child {
|
|
183
|
+
display: inline;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.tldr p,
|
|
187
|
+
.callout p,
|
|
188
|
+
.note p,
|
|
189
|
+
.tip p,
|
|
190
|
+
.warning p,
|
|
191
|
+
.pro-tip p,
|
|
192
|
+
.for-managers p,
|
|
193
|
+
.for-ics p,
|
|
194
|
+
.common-objection p {
|
|
195
|
+
display: block;
|
|
196
|
+
margin-bottom: 0.5em;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.tldr p:last-child,
|
|
200
|
+
.callout p:last-child,
|
|
201
|
+
.note p:last-child,
|
|
202
|
+
.tip p:last-child,
|
|
203
|
+
.warning p:last-child,
|
|
204
|
+
.pro-tip p:last-child,
|
|
205
|
+
.for-managers p:last-child,
|
|
206
|
+
.for-ics p:last-child,
|
|
207
|
+
.common-objection p:last-child {
|
|
208
|
+
margin-bottom: 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.tldr p:first-child + p,
|
|
212
|
+
.callout p:first-child + p,
|
|
213
|
+
.note p:first-child + p,
|
|
214
|
+
.tip p:first-child + p,
|
|
215
|
+
.warning p:first-child + p,
|
|
216
|
+
.pro-tip p:first-child + p,
|
|
217
|
+
.for-managers p:first-child + p,
|
|
218
|
+
.for-ics p:first-child + p,
|
|
219
|
+
.common-objection p:first-child + p {
|
|
220
|
+
margin-top: 0.75em;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* Copyright page - bottom alignment for EPUB readers
|
|
224
|
+
EPUB readers don't reliably support viewport units (100vh) or flexbox,
|
|
225
|
+
so we use padding-top to push content toward the bottom of the page.
|
|
226
|
+
@media not screen scopes this to EPUB/e-readers only, leaving the
|
|
227
|
+
web build to use the flex/100vh approach in the @media screen block below. */
|
|
228
|
+
@media not screen {
|
|
229
|
+
#copyright-page {
|
|
230
|
+
display: block;
|
|
231
|
+
min-height: auto;
|
|
232
|
+
font-size: 0.85em;
|
|
233
|
+
margin-top: 3em;
|
|
234
|
+
padding-top: 75%;
|
|
235
|
+
text-align: center;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* Override Tailwind Typography's .prose max-width and color.
|
|
239
|
+
Typography sets max-width: 65ch (clips on narrow Kindles) and
|
|
240
|
+
color: #495057 (washed-out on 16-level e-ink grayscale).
|
|
241
|
+
strip-page-rules.js removes Typography's descendant rules
|
|
242
|
+
(.prose X:not(.not-prose)), but the .prose root rule survives. */
|
|
243
|
+
.prose {
|
|
244
|
+
max-width: none;
|
|
245
|
+
color: #000;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* KDP: Use lining numerals in EPUB. Kindle font subsets often lack
|
|
249
|
+
oldstyle numeral glyphs, causing fallback rendering. Lining nums
|
|
250
|
+
are more reliable across e-reader font engines. */
|
|
251
|
+
body {
|
|
252
|
+
font-variant-numeric: lining-nums proportional-nums;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* EPUB heading font — sans-serif for visual contrast.
|
|
256
|
+
Sans-serif headings create clear contrast with the serif body text,
|
|
257
|
+
improving scanability on e-readers. Matches screen heading treatment. */
|
|
258
|
+
h1,
|
|
259
|
+
h2,
|
|
260
|
+
h3,
|
|
261
|
+
h4,
|
|
262
|
+
h5,
|
|
263
|
+
h6 {
|
|
264
|
+
font-family: var(--font-heading);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* EPUB heading scale — use em instead of rem.
|
|
268
|
+
Kindle and older e-readers have inconsistent rem support. Using em
|
|
269
|
+
ensures headings scale relative to the reader's chosen body font
|
|
270
|
+
size, preserving the typographic hierarchy across all devices.
|
|
271
|
+
Every heading level must be >= 1em (body size) so headings never
|
|
272
|
+
appear smaller than body text. Differentiation at the bottom of
|
|
273
|
+
the scale (h5/h6) comes from style (uppercase, italic) set in the
|
|
274
|
+
base layer rather than from size alone.
|
|
275
|
+
|
|
276
|
+
Letter-spacing is reset to normal — negative tracking from the base
|
|
277
|
+
layer can cause cramped rendering on low-DPI e-ink displays. */
|
|
278
|
+
h1 {
|
|
279
|
+
font-size: 2em;
|
|
280
|
+
font-weight: 700;
|
|
281
|
+
line-height: 1.2;
|
|
282
|
+
margin-top: 0;
|
|
283
|
+
margin-bottom: 1em;
|
|
284
|
+
letter-spacing: normal;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* EPUB chapter headings — start at the top of the page.
|
|
288
|
+
.level1 already has page-break-before: always, so the heading appears
|
|
289
|
+
on a fresh screen. Zero out the drop spacing that makes sense for print
|
|
290
|
+
chapter openers but wastes precious screen real estate on e-readers. */
|
|
291
|
+
.level1 > h1 {
|
|
292
|
+
margin-top: 0;
|
|
293
|
+
padding-top: 0;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Also remove the generic h1 padding-top that creates a "drop" effect.
|
|
297
|
+
In print this is a traditional typographic convention; in EPUB it just
|
|
298
|
+
pushes the heading halfway down the small e-reader screen. */
|
|
299
|
+
h1:not(.title) {
|
|
300
|
+
padding-top: 0;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
h2 {
|
|
304
|
+
font-size: 1.5em;
|
|
305
|
+
font-weight: 600;
|
|
306
|
+
line-height: 1.2;
|
|
307
|
+
margin-top: 2em;
|
|
308
|
+
margin-bottom: 0.6em;
|
|
309
|
+
letter-spacing: normal;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
h3 {
|
|
313
|
+
font-size: 1.25em;
|
|
314
|
+
font-weight: 600;
|
|
315
|
+
line-height: 1.2;
|
|
316
|
+
margin-top: 1.5em;
|
|
317
|
+
margin-bottom: 0.4em;
|
|
318
|
+
letter-spacing: normal;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
h4 {
|
|
322
|
+
font-size: 1.1em;
|
|
323
|
+
font-weight: 600;
|
|
324
|
+
line-height: 1.2;
|
|
325
|
+
margin-top: 1.2em;
|
|
326
|
+
margin-bottom: 0.3em;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
h5 {
|
|
330
|
+
font-size: 1.05em;
|
|
331
|
+
margin-top: 1em;
|
|
332
|
+
margin-bottom: 0.2em;
|
|
333
|
+
}
|
|
334
|
+
h6 {
|
|
335
|
+
font-size: 1em;
|
|
336
|
+
margin-top: 1em;
|
|
337
|
+
margin-bottom: 0.2em;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* Override light font weights (300) for e-ink readability.
|
|
341
|
+
Many Kindle models only support weights 400 and 700. Weight 300
|
|
342
|
+
renders identically to 400 on e-ink, making the design intent
|
|
343
|
+
invisible. Use 400 (normal) instead of 300 (light). */
|
|
344
|
+
.subtitle,
|
|
345
|
+
.lead,
|
|
346
|
+
section.section-opener > p,
|
|
347
|
+
section.section-opener > ul,
|
|
348
|
+
section.section-opener > ol {
|
|
349
|
+
font-weight: 400;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* Override muted gray text for e-ink contrast.
|
|
353
|
+
E-ink displays use 16-level grayscale, so #555–#6c757d appears
|
|
354
|
+
washed out. Use near-black for reliable readability on Kindle.
|
|
355
|
+
#333 was still too light on e-ink — use #111 for strong contrast. */
|
|
356
|
+
.lead,
|
|
357
|
+
section.section-opener > p,
|
|
358
|
+
section.section-opener > ul,
|
|
359
|
+
section.section-opener > ol {
|
|
360
|
+
color: #111;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
p.subtitle {
|
|
364
|
+
color: #444;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
figcaption {
|
|
368
|
+
color: #444;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
blockquote {
|
|
372
|
+
color: #333;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* Small caps for EPUB — Kindle (and many e-readers) ignore both
|
|
376
|
+
font-variant-caps and OpenType smcp/c2sc, so all-small-caps is a no-op
|
|
377
|
+
there. Because every .smallcaps span holds an all-uppercase acronym, the
|
|
378
|
+
unstyled result is full-height capitals slightly LARGER than the
|
|
379
|
+
surrounding text — the opposite of small caps. Fake it with a font-size
|
|
380
|
+
reduction, which every reader honors: shrinking uppercase letters reads
|
|
381
|
+
as small caps. Explicitly reset font-variant-caps/font-feature-settings
|
|
382
|
+
so readers that DO support them don't scale the glyphs a second time.
|
|
383
|
+
(The print/PDF path uses real OpenType small caps via the @media print
|
|
384
|
+
rule, whose !important declarations override this.) */
|
|
385
|
+
span.smallcaps {
|
|
386
|
+
font-variant-caps: normal;
|
|
387
|
+
font-feature-settings: normal;
|
|
388
|
+
font-size: 0.82em;
|
|
389
|
+
letter-spacing: 0.05em;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* Callout emoji images — sized in em so they stay within the text
|
|
393
|
+
line box. A fixed px height taller than the reader's line box makes
|
|
394
|
+
Kindle inflate the leading of the entire first paragraph (the one
|
|
395
|
+
carrying the label), so it reads looser than the paragraphs below it.
|
|
396
|
+
Keeping the glyph at ~1em with a small negative vertical-align lets
|
|
397
|
+
it sit on the label's baseline without growing the line. */
|
|
398
|
+
img.callout-emoji {
|
|
399
|
+
width: 0.9em;
|
|
400
|
+
height: 0.9em;
|
|
401
|
+
vertical-align: -0.1em;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* Kindle emoji PNGs are transparent RGBA (see composite-kindle-emoji.py), so
|
|
405
|
+
they sit cleanly on any reading background — no per-callout background-bake
|
|
406
|
+
is applied. Keep emoji backgrounds explicitly transparent so nothing draws
|
|
407
|
+
a box behind them in any callout or in body text. */
|
|
408
|
+
img.callout-emoji,
|
|
409
|
+
img.emoji {
|
|
410
|
+
background-color: transparent !important;
|
|
411
|
+
background: transparent !important;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/* E-ink table readability — e-ink displays use 16-level grayscale,
|
|
415
|
+
so light borders (#ddd) and zebra stripes (#f8f8f8) can disappear.
|
|
416
|
+
Darken both for reliable visibility on Kindle and similar devices. */
|
|
417
|
+
table th,
|
|
418
|
+
table td {
|
|
419
|
+
border-bottom-color: #bbb;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
table tbody tr:nth-child(even) {
|
|
423
|
+
background-color: #ddd;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/* Prose content spacing — replaces Tailwind Typography's .prose-scoped
|
|
427
|
+
rules that are stripped from EPUB by strip-page-rules.js. These provide
|
|
428
|
+
the vertical rhythm and list formatting that Typography previously
|
|
429
|
+
generated as .prose X:not(.not-prose) selectors. Bare element selectors
|
|
430
|
+
are sufficient since Typography's competing rules are removed. */
|
|
431
|
+
p {
|
|
432
|
+
margin-top: 1.25em;
|
|
433
|
+
margin-bottom: 1.25em;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
ol {
|
|
437
|
+
list-style-type: decimal;
|
|
438
|
+
margin-top: 1.25em;
|
|
439
|
+
margin-bottom: 1.25em;
|
|
440
|
+
padding-left: 1.625em;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
ul {
|
|
444
|
+
list-style-type: disc;
|
|
445
|
+
margin-top: 1.25em;
|
|
446
|
+
margin-bottom: 1.25em;
|
|
447
|
+
padding-left: 1.625em;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
li {
|
|
451
|
+
margin-top: 0.5em;
|
|
452
|
+
margin-bottom: 0.5em;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
ol > li,
|
|
456
|
+
ul > li {
|
|
457
|
+
padding-left: 0.375em;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
ul ul,
|
|
461
|
+
ul ol,
|
|
462
|
+
ol ul,
|
|
463
|
+
ol ol {
|
|
464
|
+
margin-top: 0.75em;
|
|
465
|
+
margin-bottom: 0.75em;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
dl {
|
|
469
|
+
margin-top: 1.25em;
|
|
470
|
+
margin-bottom: 1.25em;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
dt {
|
|
474
|
+
font-weight: 600;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
dd {
|
|
478
|
+
margin-top: 0.5em;
|
|
479
|
+
padding-left: 1.625em;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
figure {
|
|
483
|
+
margin-top: 2em;
|
|
484
|
+
margin-bottom: 2em;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
figure > * {
|
|
488
|
+
margin-top: 0;
|
|
489
|
+
margin-bottom: 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
img {
|
|
493
|
+
margin-top: 2em;
|
|
494
|
+
margin-bottom: 2em;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/* Collapse margin after headings and horizontal rules so the first
|
|
498
|
+
element following a heading sits flush against it. */
|
|
499
|
+
h2 + *,
|
|
500
|
+
h3 + *,
|
|
501
|
+
h4 + * {
|
|
502
|
+
margin-top: 0;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
hr + * {
|
|
506
|
+
margin-top: 0;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/* Link styling for EPUB — underline with controlled thickness.
|
|
510
|
+
E-ink renders blue as gray, making color-only distinction unreliable. */
|
|
511
|
+
a {
|
|
512
|
+
text-decoration: underline;
|
|
513
|
+
text-decoration-thickness: 1px;
|
|
514
|
+
text-underline-offset: 0.15em;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/* Blockquote border and padding for EPUB. */
|
|
518
|
+
blockquote {
|
|
519
|
+
border-left: 3px solid #999;
|
|
520
|
+
padding-left: 1.25em;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/* Code: override Tailwind Typography bold (font-weight: 600) which
|
|
524
|
+
is stripped along with the rest of Typography's .prose rules. */
|
|
525
|
+
code {
|
|
526
|
+
font-weight: normal;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/* Tables — booktabs style to match PDF.
|
|
531
|
+
0.95em is more readable than 0.9em on 6" e-ink screens where
|
|
532
|
+
overflow-wrap: break-word already causes aggressive line wrapping. */
|
|
533
|
+
table {
|
|
534
|
+
font-size: 0.95em;
|
|
535
|
+
width: 100%;
|
|
536
|
+
border-collapse: collapse;
|
|
537
|
+
page-break-inside: avoid;
|
|
538
|
+
margin: 1.5em 0;
|
|
539
|
+
border-top: 2px solid #333;
|
|
540
|
+
border-bottom: 2px solid #333;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
table th,
|
|
544
|
+
table td {
|
|
545
|
+
padding: 0.4em 0.6em;
|
|
546
|
+
border: none;
|
|
547
|
+
border-bottom: 1px solid #ddd;
|
|
548
|
+
text-align: left;
|
|
549
|
+
vertical-align: top;
|
|
550
|
+
font-variant-numeric: lining-nums tabular-nums;
|
|
551
|
+
/* Prevent long URLs or text from overflowing on narrow e-reader screens */
|
|
552
|
+
overflow-wrap: break-word;
|
|
553
|
+
word-wrap: break-word;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
table th {
|
|
557
|
+
font-weight: 600;
|
|
558
|
+
border-bottom: 2px solid #333;
|
|
559
|
+
background-color: transparent;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
table tbody tr:last-child td {
|
|
563
|
+
border-bottom: none;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/* Code blocks — light theme for e-reader compatibility.
|
|
567
|
+
0.9em is the minimum readable size on 6" e-ink displays;
|
|
568
|
+
0.85em becomes ~8.5pt at default body size, straining older Kindles. */
|
|
569
|
+
pre {
|
|
570
|
+
font-size: 0.9em;
|
|
571
|
+
line-height: 1.45;
|
|
572
|
+
padding: 1em 1.25em;
|
|
573
|
+
white-space: pre-wrap;
|
|
574
|
+
word-wrap: break-word;
|
|
575
|
+
page-break-inside: avoid;
|
|
576
|
+
background-color: #f8f8f8;
|
|
577
|
+
color: #1a1a1a;
|
|
578
|
+
border: 1px solid #ddd;
|
|
579
|
+
border-radius: 4px;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
code {
|
|
583
|
+
font-size: 0.9em;
|
|
584
|
+
padding: 0.15em 0.35em;
|
|
585
|
+
background-color: #f5f5f5;
|
|
586
|
+
border: 1px solid #e0e0e0;
|
|
587
|
+
border-radius: 3px;
|
|
588
|
+
overflow-wrap: break-word;
|
|
589
|
+
color: #333;
|
|
590
|
+
font-variant-numeric: lining-nums tabular-nums;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
pre code {
|
|
594
|
+
padding: 0;
|
|
595
|
+
background-color: transparent;
|
|
596
|
+
border: none;
|
|
597
|
+
color: inherit;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/* Kindle line-box fixes (e-readers only). Placed after the shared top-level
|
|
601
|
+
`code` rule above so it wins on source order, and scoped to @media not
|
|
602
|
+
screen so the PDF/print and web builds keep their inline-code borders. */
|
|
603
|
+
@media not screen {
|
|
604
|
+
/* Inline code: Kindle inflates the leading of any line carrying an inline
|
|
605
|
+
element taller than the surrounding text, so a line with inline `code`
|
|
606
|
+
reads looser than its neighbors. Per spec, vertical padding/border on an
|
|
607
|
+
inline element shouldn't change line height — Kindle ignores that. Drop
|
|
608
|
+
the border and vertical padding (keep the background tint + horizontal
|
|
609
|
+
padding for distinction) so inline code stays inside the line box. The
|
|
610
|
+
more-specific `pre code` rule above keeps block code unaffected. */
|
|
611
|
+
code {
|
|
612
|
+
border: none;
|
|
613
|
+
padding: 0 0.3em;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/* Uniform line spacing inside callouts: the first paragraph is
|
|
617
|
+
display:inline (so the injected label flows onto its first line) and
|
|
618
|
+
takes the reader-controlled line-height, while the block paragraphs
|
|
619
|
+
below are pinned to 1.5 by the components layer — so on readers with
|
|
620
|
+
looser spacing the first paragraph reads looser than the rest. Let every
|
|
621
|
+
callout paragraph track the reader's line-height instead. */
|
|
622
|
+
.tldr p,
|
|
623
|
+
.callout p,
|
|
624
|
+
.note p,
|
|
625
|
+
.tip p,
|
|
626
|
+
.warning p,
|
|
627
|
+
.pro-tip p,
|
|
628
|
+
.for-managers p,
|
|
629
|
+
.for-ics p,
|
|
630
|
+
.common-objection p {
|
|
631
|
+
line-height: inherit;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/* Blockquotes — elegant style to match PDF */
|
|
636
|
+
blockquote {
|
|
637
|
+
margin: 1.25em 1em 1.25em 1.5em;
|
|
638
|
+
padding: 0 0 0 1em;
|
|
639
|
+
border-left: 2px solid #aaa;
|
|
640
|
+
background-color: transparent;
|
|
641
|
+
font-style: italic;
|
|
642
|
+
font-size: 0.95em;
|
|
643
|
+
line-height: 1.5;
|
|
644
|
+
page-break-inside: avoid;
|
|
645
|
+
color: #444;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
blockquote p {
|
|
649
|
+
margin: 0.5em 0;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
blockquote p:first-child {
|
|
653
|
+
margin-top: 0;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
blockquote p:last-child {
|
|
657
|
+
margin-bottom: 0;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/* Lists - improve spacing and ensure bullets/numbers display.
|
|
661
|
+
Tailwind's preflight reset sets list-style:none on all lists.
|
|
662
|
+
In HTML, the prose typography plugin overrides this via @layer,
|
|
663
|
+
but EPUB readers may not support complex selectors or layers,
|
|
664
|
+
so we set list-style-type explicitly here as a reliable fallback. */
|
|
665
|
+
ul {
|
|
666
|
+
list-style-type: disc;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
ol {
|
|
670
|
+
list-style-type: decimal;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
ul,
|
|
674
|
+
ol {
|
|
675
|
+
margin: 1em 0;
|
|
676
|
+
padding-left: 2em;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
li {
|
|
680
|
+
margin-bottom: 0.4em;
|
|
681
|
+
line-height: 1.55;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
li p {
|
|
685
|
+
margin: 0.25em 0;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/* Nested lists — tighter spacing, progressive indentation */
|
|
689
|
+
li ul,
|
|
690
|
+
li ol {
|
|
691
|
+
margin-top: 0.5em;
|
|
692
|
+
padding-left: 1.5em;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/* Images - responsive sizing */
|
|
696
|
+
img {
|
|
697
|
+
max-width: 100%;
|
|
698
|
+
height: auto;
|
|
699
|
+
page-break-inside: avoid;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/* Section breaks — subtle centered ornament */
|
|
703
|
+
hr {
|
|
704
|
+
border: none;
|
|
705
|
+
height: auto;
|
|
706
|
+
width: auto;
|
|
707
|
+
background: none;
|
|
708
|
+
margin: 2.5em auto;
|
|
709
|
+
text-align: center;
|
|
710
|
+
page-break-after: avoid;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
hr::after {
|
|
714
|
+
content: "⁕ ⁕ ⁕";
|
|
715
|
+
display: block;
|
|
716
|
+
/* #555 instead of #999 — visible on e-ink 16-level grayscale */
|
|
717
|
+
color: #555;
|
|
718
|
+
font-size: 0.9em;
|
|
719
|
+
letter-spacing: 0.15em;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
figure {
|
|
723
|
+
margin: 1.5em 0;
|
|
724
|
+
page-break-inside: avoid;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
figcaption {
|
|
728
|
+
font-size: 0.9em;
|
|
729
|
+
font-style: italic;
|
|
730
|
+
text-align: center;
|
|
731
|
+
margin-top: 0.5em;
|
|
732
|
+
/* #595959 provides 7:1 contrast ratio against white background (WCAG AAA) */
|
|
733
|
+
color: #595959;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/* Footnotes - compact formatting */
|
|
737
|
+
.footnotes {
|
|
738
|
+
font-size: 0.85em;
|
|
739
|
+
margin-top: 2em;
|
|
740
|
+
padding-top: 1em;
|
|
741
|
+
border-top: 1px solid #ccc;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
.footnotes ol {
|
|
745
|
+
padding-left: 1.5em;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
.footnotes li {
|
|
749
|
+
margin-bottom: 0.5em;
|
|
750
|
+
break-inside: avoid;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/* Footnote paragraphs inherit the base EPUB `p` margins (1.25em top and
|
|
754
|
+
bottom), which on Kindle pushes every note far apart and reads as
|
|
755
|
+
double-spaced. Collapse those margins so each note is a tight block,
|
|
756
|
+
with `.footnotes li` providing the only gap between entries. */
|
|
757
|
+
.footnotes li p {
|
|
758
|
+
margin-top: 0;
|
|
759
|
+
margin-bottom: 0;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/* Footnote reference markers — Kindle converts all external links to
|
|
763
|
+
footnotes, so readers encounter them frequently.
|
|
764
|
+
0.85em keeps markers clearly visible on e-ink without disrupting
|
|
765
|
+
line spacing.
|
|
766
|
+
EPUB footnote refs are plain <a> elements (no <sup> wrapper), so
|
|
767
|
+
target .footnote-ref directly. Use vertical-align: super for true
|
|
768
|
+
superscript — position: relative + top: -0.4em (from the base layer)
|
|
769
|
+
is unreliable on Kindle's inline layout engine. */
|
|
770
|
+
.footnote-ref {
|
|
771
|
+
font-size: 0.85em;
|
|
772
|
+
line-height: 1;
|
|
773
|
+
vertical-align: super;
|
|
774
|
+
font-variant-numeric: lining-nums;
|
|
775
|
+
/* Cancel the base-layer position: relative + top: -0.4em hack —
|
|
776
|
+
vertical-align: super handles superscript natively on EPUB readers. */
|
|
777
|
+
position: static;
|
|
778
|
+
top: auto;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/* Links - elegant and accessible.
|
|
782
|
+
Solid underline color — rgba/alpha is invisible on e-ink grayscale. */
|
|
783
|
+
a {
|
|
784
|
+
color: #0369a1;
|
|
785
|
+
text-decoration: underline;
|
|
786
|
+
text-decoration-color: #0369a1;
|
|
787
|
+
text-decoration-thickness: 1px;
|
|
788
|
+
text-underline-offset: 2px;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/* Title page — refined typography to match PDF quality. */
|
|
792
|
+
.title {
|
|
793
|
+
font-family: var(--font-heading);
|
|
794
|
+
font-size: 2.2em;
|
|
795
|
+
font-weight: 700;
|
|
796
|
+
text-align: center;
|
|
797
|
+
margin-top: 2em;
|
|
798
|
+
margin-bottom: 0.5em;
|
|
799
|
+
letter-spacing: -0.02em;
|
|
800
|
+
line-height: 1.15;
|
|
801
|
+
padding-top: 0.75rem;
|
|
802
|
+
border-top: 2px solid #333;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
.subtitle {
|
|
806
|
+
font-family: var(--font-heading);
|
|
807
|
+
font-size: 1.1em;
|
|
808
|
+
font-weight: 400;
|
|
809
|
+
font-style: italic;
|
|
810
|
+
text-align: center;
|
|
811
|
+
margin-bottom: 2em;
|
|
812
|
+
line-height: 1.5;
|
|
813
|
+
color: #555;
|
|
814
|
+
padding-bottom: 0.75rem;
|
|
815
|
+
border-bottom: 2px solid #333;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
.author {
|
|
819
|
+
font-family: var(--font-heading);
|
|
820
|
+
font-size: 1.1em;
|
|
821
|
+
font-weight: 500;
|
|
822
|
+
text-align: center;
|
|
823
|
+
margin-bottom: 0.5em;
|
|
824
|
+
letter-spacing: 0.04em;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/* Copyright page - bottom aligned */
|
|
828
|
+
#copyright-page {
|
|
829
|
+
font-size: 0.85em;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/* Screen-only: use flex to push copyright content to bottom of viewport */
|
|
833
|
+
@media screen {
|
|
834
|
+
#copyright-page {
|
|
835
|
+
display: flex;
|
|
836
|
+
align-items: flex-end;
|
|
837
|
+
min-height: 100vh;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/* Dedication — centered and styled */
|
|
842
|
+
.dedication {
|
|
843
|
+
text-align: center;
|
|
844
|
+
font-style: italic;
|
|
845
|
+
margin: 4em 2em;
|
|
846
|
+
font-size: 1.1em;
|
|
847
|
+
line-height: 1.65;
|
|
848
|
+
color: #555;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/* Publisher line on title page */
|
|
852
|
+
.publisher {
|
|
853
|
+
font-size: 0.9em;
|
|
854
|
+
text-align: center;
|
|
855
|
+
color: #555; /* ~7.5:1 contrast — readable on e-ink sepia */
|
|
856
|
+
margin-top: 1em;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/* Revision number (small, muted) */
|
|
860
|
+
.revision {
|
|
861
|
+
font-size: 0.8em;
|
|
862
|
+
text-align: center;
|
|
863
|
+
color: #666; /* ~5.7:1 contrast — passes WCAG AA on sepia */
|
|
864
|
+
margin-top: 0.5em;
|
|
865
|
+
}
|