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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +72 -0
  3. package/README.md +251 -2
  4. package/bin/book-kit.js +115 -0
  5. package/commands/_emoji_io.py +32 -0
  6. package/commands/audit-chapter-lengths.js +244 -0
  7. package/commands/check-epub-size.js +68 -0
  8. package/commands/check-pdf-page-count.js +162 -0
  9. package/commands/composite-kindle-emoji.py +85 -0
  10. package/commands/composite-print-emoji.py +98 -0
  11. package/commands/conventions.js +76 -0
  12. package/commands/convert-pdfx.sh +194 -0
  13. package/commands/download-icc-profile.sh +105 -0
  14. package/commands/fonts.py +212 -0
  15. package/commands/generate-reference-docx.py +344 -0
  16. package/commands/kindle-fonts.js +173 -0
  17. package/commands/links-to-footnotes.js +366 -0
  18. package/commands/markdownlint.js +25 -0
  19. package/commands/minify-css.js +43 -0
  20. package/commands/optimize-images.js +73 -0
  21. package/commands/parity.sh +150 -0
  22. package/commands/postprocess-epub.js +541 -0
  23. package/commands/prep-print-src.js +77 -0
  24. package/commands/prose.js +38 -0
  25. package/commands/release-files.js +89 -0
  26. package/commands/reorder-print-frontmatter.js +79 -0
  27. package/commands/strip-page-rules.js +1168 -0
  28. package/commands/strip-property-rules.js +93 -0
  29. package/commands/update-key-takeaways.js +314 -0
  30. package/commands/validate.js +283 -0
  31. package/configs/markdownlint-cli2.jsonc +98 -0
  32. package/configs/textlintrc.json +22 -0
  33. package/css/theme/01-tokens.css +83 -0
  34. package/css/theme/02-fonts.css +79 -0
  35. package/css/theme/03-prose.css +53 -0
  36. package/css/theme/04-base.css +226 -0
  37. package/css/theme/05-components.css +546 -0
  38. package/css/theme/06-utilities.css +40 -0
  39. package/css/theme/07-ereader.css +245 -0
  40. package/css/theme/08-epub.css +865 -0
  41. package/css/theme/09-back-matter.css +47 -0
  42. package/css/theme/10-dark.css +302 -0
  43. package/css/theme/11-print.css +1229 -0
  44. package/css/theme.css +38 -0
  45. package/defaults/book.config.yml +318 -0
  46. package/defaults/pandoc-base.yml +19 -0
  47. package/defaults/pandoc-docx.yml +6 -0
  48. package/defaults/pandoc-epub-fonts.yml +6 -0
  49. package/defaults/pandoc-epub.yml +15 -0
  50. package/defaults/pandoc-kindle.yml +6 -0
  51. package/emoji/1f382.png +0 -0
  52. package/emoji/1f389.png +0 -0
  53. package/emoji/1f440.png +0 -0
  54. package/emoji/1f44d.png +0 -0
  55. package/emoji/1f44f.png +0 -0
  56. package/emoji/1f454.png +0 -0
  57. package/emoji/1f4a1.png +0 -0
  58. package/emoji/1f4bb.png +0 -0
  59. package/emoji/1f602.png +0 -0
  60. package/emoji/1f603.png +0 -0
  61. package/emoji/1f604.png +0 -0
  62. package/emoji/1f60a.png +0 -0
  63. package/emoji/1f60f.png +0 -0
  64. package/emoji/1f64c.png +0 -0
  65. package/emoji/1f64f.png +0 -0
  66. package/emoji/1f914.png +0 -0
  67. package/emoji/1f923.png +0 -0
  68. package/emoji/2714.png +0 -0
  69. package/emoji/274c.png +0 -0
  70. package/filters/add-div-titles.lua +196 -0
  71. package/filters/arc-notice.lua +36 -0
  72. package/filters/body-emoji-images.lua +48 -0
  73. package/filters/callout-classes.lua +40 -0
  74. package/filters/lib/book_kit.lua +110 -0
  75. package/filters/revision.lua +17 -0
  76. package/filters/strip-comments.lua +40 -0
  77. package/filters/strip-emoji-kindle.lua +134 -0
  78. package/fonts/LICENSE-source-code-pro.md +93 -0
  79. package/fonts/LICENSE-source-sans.md +93 -0
  80. package/fonts/LICENSE-source-serif.md +93 -0
  81. package/fonts/recipe.json +41 -0
  82. package/just/book-kit.just +229 -0
  83. package/lib/acronyms.js +47 -0
  84. package/lib/callouts.js +17 -0
  85. package/lib/config.js +211 -0
  86. package/lib/is-main.js +21 -0
  87. package/lib/lint.js +148 -0
  88. package/lib/pandoc.js +148 -0
  89. package/lib/paragraphs.js +173 -0
  90. package/lib/revision.js +35 -0
  91. package/lib/structure.js +39 -0
  92. package/lib/textlint-github-formatter.js +58 -0
  93. package/lib/validate.js +202 -0
  94. package/package.json +98 -4
  95. package/presets/business-nonfiction/CONVENTIONS.md +35 -0
  96. package/presets/business-nonfiction/preset.yml +128 -0
  97. package/profiles/pdfx-def.ps +42 -0
  98. package/requirements.txt +14 -0
  99. package/rules/no-ai-like-patterns.js +209 -0
  100. package/rules/no-assumptive.js +76 -0
  101. package/rules/no-bare-acronyms.js +129 -0
  102. package/rules/no-cliches.js +544 -0
  103. package/rules/no-cultural-idioms.js +422 -0
  104. package/rules/no-vague-intensifiers.js +94 -0
  105. package/templates/template-epub.html +79 -0
  106. package/templates/template.html +73 -0
  107. package/toolchain.json +42 -0
  108. package/validators/acronym-expansion.js +94 -0
  109. package/validators/bold-keywords.js +56 -0
  110. package/validators/callout-balance.js +74 -0
  111. package/validators/callout-divs.js +66 -0
  112. package/validators/callout-labels.js +102 -0
  113. package/validators/chapter-lengths.js +14 -0
  114. package/validators/chapter.js +57 -0
  115. package/validators/cross-references.js +45 -0
  116. package/validators/doubled-words.js +76 -0
  117. package/validators/duplicate-headings.js +52 -0
  118. package/validators/em-dashes.js +73 -0
  119. package/validators/escaped-smallcaps.js +46 -0
  120. package/validators/footnotes.js +78 -0
  121. package/validators/heading-hierarchy.js +58 -0
  122. package/validators/hypothetical-hooks.js +103 -0
  123. package/validators/index-integrity.js +28 -0
  124. package/validators/index.js +73 -0
  125. package/validators/list-punctuation.js +123 -0
  126. package/validators/min-opener-length.js +87 -0
  127. package/validators/no-bare-url-link-text.js +38 -0
  128. package/validators/no-todo-markers.js +49 -0
  129. package/validators/no-transition-todos.js +34 -0
  130. package/validators/number-range-dashes.js +72 -0
  131. package/validators/paragraph-length.js +62 -0
  132. package/validators/quote-punctuation.js +85 -0
  133. package/validators/section-intro-final-lead.js +90 -0
  134. package/validators/section-intro-has-lead.js +41 -0
  135. package/validators/section-intro-no-tldr.js +37 -0
  136. package/validators/section-intros.js +33 -0
  137. package/validators/sentence-starters.js +132 -0
  138. package/validators/smallcaps.js +67 -0
  139. 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
+ }