@brandon_m_behring/book-scaffold-astro 3.0.0-alpha.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/CLAUDE.md +179 -0
- package/bin/book-scaffold.mjs +61 -0
- package/components/CaseStudy.astro +36 -0
- package/components/ChapterHeader.astro +61 -0
- package/components/ChapterNav.astro +29 -0
- package/components/ChapterTOC.astro +33 -0
- package/components/Citation.astro +94 -0
- package/components/Cite.astro +71 -0
- package/components/CodeBlock.astro +115 -0
- package/components/CodeRef.astro +49 -0
- package/components/ConceptBox.astro +26 -0
- package/components/Convergence.astro +41 -0
- package/components/CounterBox.astro +15 -0
- package/components/Divergence.astro +32 -0
- package/components/DynConnect.astro +15 -0
- package/components/ExampleBox.astro +15 -0
- package/components/Figure.astro +35 -0
- package/components/InsightBox.astro +15 -0
- package/components/KeyIdea.astro +21 -0
- package/components/MarginNote.astro +37 -0
- package/components/NoteBox.astro +15 -0
- package/components/OpenQuestion.astro +15 -0
- package/components/PaperBox.astro +15 -0
- package/components/PatternTimeline.astro +133 -0
- package/components/Recovery.astro +34 -0
- package/components/ResultBox.astro +15 -0
- package/components/Sidebar.astro +268 -0
- package/components/Sidenote.astro +26 -0
- package/components/SkillBox.astro +24 -0
- package/components/SourceArchive.astro +285 -0
- package/components/StatusBadge.astro +51 -0
- package/components/Tag.astro +60 -0
- package/components/Theorem.astro +65 -0
- package/components/TipBox.astro +15 -0
- package/components/ToolFilter.tsx +160 -0
- package/components/TryThis.astro +23 -0
- package/components/VersionSelector.tsx +85 -0
- package/components/WarnBox.astro +15 -0
- package/components/WeekRef.astro +51 -0
- package/components/XRef.astro +40 -0
- package/dist/index.d.ts +135 -0
- package/dist/index.mjs +369 -0
- package/dist/lib/katex-macros.d.ts +26 -0
- package/dist/lib/katex-macros.mjs +98 -0
- package/dist/schemas.d.ts +17 -0
- package/dist/schemas.mjs +160 -0
- package/dist/types-Cz-pwE1N.d.ts +61 -0
- package/examples/chapter-template-academic.mdx +100 -0
- package/examples/chapter-template-tools.mdx +90 -0
- package/layouts/Base.astro +250 -0
- package/layouts/Chapter.astro +37 -0
- package/package.json +137 -0
- package/pages/chapters.astro +371 -0
- package/pages/convergence.astro +96 -0
- package/pages/print.astro +39 -0
- package/pages/references.astro +160 -0
- package/pages/search.astro +87 -0
- package/pedagogy/kf-chapter-shape.md +96 -0
- package/pedagogy/source-tiers.md +121 -0
- package/pedagogy/volatility-classes.md +110 -0
- package/recipes/00-getting-started.md +77 -0
- package/recipes/01-add-math.md +71 -0
- package/recipes/02-bibliography-pipeline.md +82 -0
- package/recipes/03-asset-pipelines.md +84 -0
- package/recipes/04-component-library.md +118 -0
- package/recipes/05-deploy-cloudflare.md +74 -0
- package/recipes/06-mobile-first-layout.md +73 -0
- package/recipes/07-chapter-shapes.md +84 -0
- package/recipes/08-decisions-ledger.md +110 -0
- package/recipes/09-validation.md +106 -0
- package/recipes/10-custom-domain.md +72 -0
- package/recipes/README.md +43 -0
- package/scripts/build-bib.mjs +99 -0
- package/scripts/build-figures.mjs +179 -0
- package/scripts/render-notebooks.mjs +223 -0
- package/scripts/validate.mjs +179 -0
- package/styles/callouts.css +303 -0
- package/styles/chapter.css +209 -0
- package/styles/convergence.css +349 -0
- package/styles/layout.css +156 -0
- package/styles/print.css +203 -0
- package/styles/tokens.css +194 -0
- package/styles/tool-filter.css +135 -0
- package/styles/typography.css +147 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/* tokens.css — Design tokens for book-template-astro
|
|
2
|
+
* Two layers:
|
|
3
|
+
* 1. Raw palette (Warm Tol hybrid — inherited from the LaTeX book)
|
|
4
|
+
* 2. Semantic roles that reference the palette
|
|
5
|
+
* Dark mode overrides only the semantic layer.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
:root {
|
|
9
|
+
/* ===== Layer 1: Raw palette — Warm Tol hybrid =====
|
|
10
|
+
* Source: ~/Claude/claude-best-practices/claude-best-practices.sty lines 117-128
|
|
11
|
+
* Tol Bright relationships + Anthropic warmth. Colorblind-safe. */
|
|
12
|
+
--warm-blue: #3B6FA0; /* structural: headings, links, info */
|
|
13
|
+
--warm-rose: #C06858; /* attention: warnings, alerts */
|
|
14
|
+
--warm-green: #4A7E3F; /* positive: tips, practitioner */
|
|
15
|
+
--warm-plum: #8A4E82; /* authority: official, exercises */
|
|
16
|
+
--warm-gold: #C09840; /* insight: convergence, reasoning */
|
|
17
|
+
|
|
18
|
+
/* Warm neutrals (Anthropic-derived) */
|
|
19
|
+
--paper: #FDFCF9; /* page background — slightly off-white */
|
|
20
|
+
--code-bg: #F7F5F0; /* code block background */
|
|
21
|
+
--code-frame: #B5B3AA; /* code block border */
|
|
22
|
+
--dark-text: #1A1A19; /* body text */
|
|
23
|
+
|
|
24
|
+
/* Soft tints — used for callout backgrounds (5% blend with paper) */
|
|
25
|
+
--warm-blue-tint: color-mix(in srgb, var(--warm-blue) 6%, var(--paper));
|
|
26
|
+
--warm-rose-tint: color-mix(in srgb, var(--warm-rose) 6%, var(--paper));
|
|
27
|
+
--warm-green-tint: color-mix(in srgb, var(--warm-green) 6%, var(--paper));
|
|
28
|
+
--warm-plum-tint: color-mix(in srgb, var(--warm-plum) 6%, var(--paper));
|
|
29
|
+
--warm-gold-tint: color-mix(in srgb, var(--warm-gold) 6%, var(--paper));
|
|
30
|
+
|
|
31
|
+
/* ===== Layer 2: Semantic roles (light mode) ===== */
|
|
32
|
+
--color-bg: var(--paper);
|
|
33
|
+
--color-bg-subtle: var(--code-bg);
|
|
34
|
+
--color-text: var(--dark-text);
|
|
35
|
+
--color-text-muted: color-mix(in srgb, var(--dark-text) 55%, var(--paper));
|
|
36
|
+
--color-border: var(--code-frame);
|
|
37
|
+
--color-link: var(--warm-blue);
|
|
38
|
+
--color-heading: var(--warm-blue);
|
|
39
|
+
--color-code-bg: var(--code-bg);
|
|
40
|
+
--color-code-border: var(--code-frame);
|
|
41
|
+
|
|
42
|
+
/* Callout semantic roles (left-bar color, used with *-tint bg) */
|
|
43
|
+
--callout-info: var(--warm-blue);
|
|
44
|
+
--callout-warn: var(--warm-rose);
|
|
45
|
+
--callout-tip: var(--warm-green);
|
|
46
|
+
--callout-official: var(--warm-plum);
|
|
47
|
+
--callout-insight: var(--warm-gold);
|
|
48
|
+
|
|
49
|
+
/* ===== Typography scale ===== */
|
|
50
|
+
--font-body: 'Roboto Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
51
|
+
--font-code: 'Source Code Pro Variable', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
|
|
52
|
+
|
|
53
|
+
--text-xs: 0.75rem;
|
|
54
|
+
--text-sm: 0.875rem;
|
|
55
|
+
--text-base: 1rem;
|
|
56
|
+
--text-lg: 1.125rem;
|
|
57
|
+
--text-xl: 1.25rem;
|
|
58
|
+
--text-2xl: 1.5rem;
|
|
59
|
+
--text-3xl: 1.875rem;
|
|
60
|
+
--text-4xl: 2.25rem;
|
|
61
|
+
|
|
62
|
+
--leading-tight: 1.25;
|
|
63
|
+
--leading-normal: 1.5;
|
|
64
|
+
--leading-body: 1.6; /* target for long-form reading */
|
|
65
|
+
--leading-relaxed: 1.75;
|
|
66
|
+
|
|
67
|
+
/* ===== Layout measures =====
|
|
68
|
+
* Three-tier responsive measure tuned via Playwright comparison at
|
|
69
|
+
* 375 / 1280 / 1440 / 1920px viewports (post_transformers commit d9d085b).
|
|
70
|
+
*
|
|
71
|
+
* The classic 65ch Tufte measure feels narrow on wide desktops (≥1440px)
|
|
72
|
+
* where ~38% of the viewport sits as empty margin. The tiered approach
|
|
73
|
+
* keeps 65ch where it's typographically right (laptop) and expands to
|
|
74
|
+
* 80ch / 90ch on wider monitors without crossing the 90ch upper limit
|
|
75
|
+
* of comfortable line length.
|
|
76
|
+
*
|
|
77
|
+
* Tier values + utilization (verified):
|
|
78
|
+
* default (≤1440px): 65ch + 28ch → 70% at 1280px
|
|
79
|
+
* 1440px tier: 80ch + 24ch → 69% (with sidebar: 89%)
|
|
80
|
+
* 1920px tier: 90ch + 26ch → 57% (with sidebar: 72%)
|
|
81
|
+
*
|
|
82
|
+
* Sidenote column shrinks slightly at wider tiers (24ch / 26ch) to give
|
|
83
|
+
* main column more room while staying readable for short notes.
|
|
84
|
+
*
|
|
85
|
+
* Mobile (<48rem) handled separately in layout.css — sidenotes reflow
|
|
86
|
+
* inline; the tokens here don't apply below 48rem.
|
|
87
|
+
*
|
|
88
|
+
* Note: CSS custom properties cannot be used in @media expressions, so
|
|
89
|
+
* the breakpoints are encoded as literal rem values in the media queries
|
|
90
|
+
* (90rem ≈ 1440px, 120rem ≈ 1920px).
|
|
91
|
+
*/
|
|
92
|
+
--measure-main: 65ch; /* default: laptop-friendly typographic measure */
|
|
93
|
+
--measure-side: 28ch; /* right-margin sidenote column (desktop) */
|
|
94
|
+
--breakpoint-narrow: 48rem; /* ~768px — mobile fold (sidenotes inline) */
|
|
95
|
+
--breakpoint-wide: 90rem; /* ~1440px — wide-desktop tier */
|
|
96
|
+
--breakpoint-ultrawide: 120rem; /* ~1920px — ultrawide tier */
|
|
97
|
+
|
|
98
|
+
/* ===== Spacing scale ===== */
|
|
99
|
+
--space-1: 0.25rem;
|
|
100
|
+
--space-2: 0.5rem;
|
|
101
|
+
--space-3: 0.75rem;
|
|
102
|
+
--space-4: 1rem;
|
|
103
|
+
--space-5: 1.25rem;
|
|
104
|
+
--space-6: 1.5rem;
|
|
105
|
+
--space-8: 2rem;
|
|
106
|
+
--space-12: 3rem;
|
|
107
|
+
--space-16: 4rem;
|
|
108
|
+
|
|
109
|
+
/* ===== Borders / radii ===== */
|
|
110
|
+
--radius-sm: 2px;
|
|
111
|
+
--radius-md: 4px;
|
|
112
|
+
--border-bar: 3px; /* left-bar on callouts and sidenote asides */
|
|
113
|
+
|
|
114
|
+
/* ===== Shiki syntax highlighting (css-variables theme) =====
|
|
115
|
+
* Shiki's css-variables mode emits <span style="color:var(--astro-code-token-...)">
|
|
116
|
+
* for each token. Mapping to Warm Tol hues keeps code blocks in the
|
|
117
|
+
* same visual language as prose callouts. Dark mode overrides below. */
|
|
118
|
+
--astro-code-foreground: var(--color-text);
|
|
119
|
+
--astro-code-background: var(--color-code-bg);
|
|
120
|
+
--astro-code-token-constant: var(--warm-rose);
|
|
121
|
+
--astro-code-token-string: var(--warm-green);
|
|
122
|
+
--astro-code-token-string-expression: var(--warm-green);
|
|
123
|
+
--astro-code-token-comment: var(--color-text-muted);
|
|
124
|
+
--astro-code-token-keyword: var(--warm-plum);
|
|
125
|
+
--astro-code-token-parameter: var(--warm-blue);
|
|
126
|
+
--astro-code-token-function: var(--warm-gold);
|
|
127
|
+
--astro-code-token-punctuation: var(--color-text-muted);
|
|
128
|
+
--astro-code-token-link: var(--color-link);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* Tier 2: wide desktop (1440px+). Main 80ch, sidenote 24ch. */
|
|
132
|
+
@media (min-width: 90rem) {
|
|
133
|
+
:root {
|
|
134
|
+
--measure-main: 80ch;
|
|
135
|
+
--measure-side: 24ch;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Tier 3: ultrawide (1920px+). Main 90ch, sidenote 26ch. */
|
|
140
|
+
@media (min-width: 120rem) {
|
|
141
|
+
:root {
|
|
142
|
+
--measure-main: 90ch;
|
|
143
|
+
--measure-side: 26ch;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* ===== Dark mode ==========================================================
|
|
148
|
+
* Override only the raw neutral palette + a couple of accent brightenings
|
|
149
|
+
* for contrast. Because semantic roles (--color-bg, --color-text,
|
|
150
|
+
* --color-link, etc.) and tint calcs reference these via var(), they
|
|
151
|
+
* auto-update with no further work.
|
|
152
|
+
*
|
|
153
|
+
* Precedence: explicit [data-theme="light"] > explicit [data-theme="dark"]
|
|
154
|
+
* > prefers-color-scheme. A small inline script in Base.astro applies any
|
|
155
|
+
* user-saved preference from localStorage before first paint (no FOUC).
|
|
156
|
+
* ========================================================================== */
|
|
157
|
+
|
|
158
|
+
@media (prefers-color-scheme: dark) {
|
|
159
|
+
:root:not([data-theme="light"]) {
|
|
160
|
+
--paper: #1A1816; /* deep warm-neutral page background */
|
|
161
|
+
--code-bg: #26231F;
|
|
162
|
+
--code-frame: #3A3632;
|
|
163
|
+
--dark-text: #E8E5DD; /* cream body text */
|
|
164
|
+
|
|
165
|
+
/* Brighten headings + links for contrast against dark bg */
|
|
166
|
+
--color-heading: color-mix(in srgb, var(--warm-blue) 55%, white);
|
|
167
|
+
--color-link: color-mix(in srgb, var(--warm-blue) 55%, white);
|
|
168
|
+
|
|
169
|
+
/* Shiki token brightenings for contrast on dark code-block bg */
|
|
170
|
+
--astro-code-token-constant: color-mix(in srgb, var(--warm-rose) 60%, white);
|
|
171
|
+
--astro-code-token-string: color-mix(in srgb, var(--warm-green) 60%, white);
|
|
172
|
+
--astro-code-token-string-expression: color-mix(in srgb, var(--warm-green) 60%, white);
|
|
173
|
+
--astro-code-token-keyword: color-mix(in srgb, var(--warm-plum) 55%, white);
|
|
174
|
+
--astro-code-token-parameter: color-mix(in srgb, var(--warm-blue) 55%, white);
|
|
175
|
+
--astro-code-token-function: color-mix(in srgb, var(--warm-gold) 65%, white);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
:root[data-theme="dark"] {
|
|
180
|
+
--paper: #1A1816;
|
|
181
|
+
--code-bg: #26231F;
|
|
182
|
+
--code-frame: #3A3632;
|
|
183
|
+
--dark-text: #E8E5DD;
|
|
184
|
+
|
|
185
|
+
--color-heading: color-mix(in srgb, var(--warm-blue) 55%, white);
|
|
186
|
+
--color-link: color-mix(in srgb, var(--warm-blue) 55%, white);
|
|
187
|
+
|
|
188
|
+
--astro-code-token-constant: color-mix(in srgb, var(--warm-rose) 60%, white);
|
|
189
|
+
--astro-code-token-string: color-mix(in srgb, var(--warm-green) 60%, white);
|
|
190
|
+
--astro-code-token-string-expression: color-mix(in srgb, var(--warm-green) 60%, white);
|
|
191
|
+
--astro-code-token-keyword: color-mix(in srgb, var(--warm-plum) 55%, white);
|
|
192
|
+
--astro-code-token-parameter: color-mix(in srgb, var(--warm-blue) 55%, white);
|
|
193
|
+
--astro-code-token-function: color-mix(in srgb, var(--warm-gold) 65%, white);
|
|
194
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* tool-filter.css — ToolFilter chrome-button trigger + dropdown panel.
|
|
2
|
+
* Follows the same visual language as version-selector styles in Base.astro.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.tool-filter {
|
|
6
|
+
position: relative;
|
|
7
|
+
display: inline-block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.tool-filter-trigger {
|
|
11
|
+
position: relative;
|
|
12
|
+
}
|
|
13
|
+
.tool-filter-count {
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: -0.2em;
|
|
16
|
+
right: -0.2em;
|
|
17
|
+
min-width: 1.1em;
|
|
18
|
+
height: 1.1em;
|
|
19
|
+
padding: 0 0.3em;
|
|
20
|
+
border-radius: 999px;
|
|
21
|
+
background: var(--warm-blue);
|
|
22
|
+
color: #fff;
|
|
23
|
+
font-family: var(--font-code);
|
|
24
|
+
font-size: 0.65rem;
|
|
25
|
+
font-weight: 600;
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
line-height: 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.tool-filter-panel {
|
|
33
|
+
position: absolute;
|
|
34
|
+
top: calc(100% + var(--space-2));
|
|
35
|
+
right: 0;
|
|
36
|
+
min-width: 14rem;
|
|
37
|
+
padding: var(--space-3);
|
|
38
|
+
background: var(--color-bg);
|
|
39
|
+
border: 1px solid var(--color-border);
|
|
40
|
+
border-radius: var(--radius-md);
|
|
41
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
42
|
+
z-index: 20;
|
|
43
|
+
}
|
|
44
|
+
.tool-filter-heading {
|
|
45
|
+
margin: 0 0 var(--space-2) 0;
|
|
46
|
+
font-size: var(--text-xs);
|
|
47
|
+
text-transform: uppercase;
|
|
48
|
+
letter-spacing: 0.06em;
|
|
49
|
+
color: var(--color-text-muted);
|
|
50
|
+
font-family: var(--font-code);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.tool-filter-chips {
|
|
54
|
+
list-style: none;
|
|
55
|
+
padding: 0;
|
|
56
|
+
margin: 0 0 var(--space-3) 0;
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-wrap: wrap;
|
|
59
|
+
gap: var(--space-2);
|
|
60
|
+
}
|
|
61
|
+
.tool-filter-chips li {
|
|
62
|
+
margin: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.tool-filter-chip {
|
|
66
|
+
display: inline-flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
gap: 0.3em;
|
|
69
|
+
padding: 0.2em 0.7em;
|
|
70
|
+
min-height: 1.8em; /* mobile tap target */
|
|
71
|
+
border-radius: 999px;
|
|
72
|
+
background: transparent;
|
|
73
|
+
color: var(--color-text);
|
|
74
|
+
border: 1px solid var(--color-border);
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
font-family: var(--font-code);
|
|
77
|
+
font-size: var(--text-sm);
|
|
78
|
+
line-height: 1.4;
|
|
79
|
+
transition:
|
|
80
|
+
background 120ms ease,
|
|
81
|
+
border-color 120ms ease,
|
|
82
|
+
color 120ms ease,
|
|
83
|
+
transform 80ms ease;
|
|
84
|
+
}
|
|
85
|
+
.tool-filter-chip:hover {
|
|
86
|
+
border-color: var(--color-link);
|
|
87
|
+
}
|
|
88
|
+
.tool-filter-chip:active {
|
|
89
|
+
transform: scale(0.96);
|
|
90
|
+
}
|
|
91
|
+
.tool-filter-chip:focus-visible {
|
|
92
|
+
outline: 2px solid var(--color-link);
|
|
93
|
+
outline-offset: 2px;
|
|
94
|
+
}
|
|
95
|
+
.tool-filter-chip-on {
|
|
96
|
+
background: var(--warm-blue-tint);
|
|
97
|
+
color: var(--warm-blue);
|
|
98
|
+
border-color: var(--warm-blue);
|
|
99
|
+
font-weight: 500;
|
|
100
|
+
}
|
|
101
|
+
.tool-filter-chip-on::before {
|
|
102
|
+
content: '✓';
|
|
103
|
+
font-size: 0.8em;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.tool-filter-footer {
|
|
107
|
+
display: flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
gap: var(--space-2);
|
|
110
|
+
padding-top: var(--space-2);
|
|
111
|
+
border-top: 1px solid var(--color-border);
|
|
112
|
+
}
|
|
113
|
+
.tool-filter-clear {
|
|
114
|
+
padding: 0.1em 0.6em;
|
|
115
|
+
border-radius: var(--radius-sm);
|
|
116
|
+
background: transparent;
|
|
117
|
+
color: var(--color-link);
|
|
118
|
+
border: 1px solid var(--color-border);
|
|
119
|
+
font-family: var(--font-code);
|
|
120
|
+
font-size: var(--text-xs);
|
|
121
|
+
cursor: pointer;
|
|
122
|
+
transition: background 120ms ease;
|
|
123
|
+
}
|
|
124
|
+
.tool-filter-clear:hover:not(:disabled) {
|
|
125
|
+
background: var(--color-bg-subtle);
|
|
126
|
+
}
|
|
127
|
+
.tool-filter-clear:disabled {
|
|
128
|
+
opacity: 0.5;
|
|
129
|
+
cursor: not-allowed;
|
|
130
|
+
}
|
|
131
|
+
.tool-filter-note {
|
|
132
|
+
font-size: var(--text-xs);
|
|
133
|
+
color: var(--color-text-muted);
|
|
134
|
+
line-height: 1.3;
|
|
135
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/* typography.css — Base typographic rules
|
|
2
|
+
* Assumes tokens.css is loaded first for CSS custom properties.
|
|
3
|
+
* Font files are loaded via JS imports in Base.astro (commit 2).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
*,
|
|
7
|
+
*::before,
|
|
8
|
+
*::after {
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
html {
|
|
13
|
+
font-family: var(--font-body);
|
|
14
|
+
font-size: 100%; /* respect user root-size preference */
|
|
15
|
+
-webkit-font-smoothing: antialiased;
|
|
16
|
+
-moz-osx-font-smoothing: grayscale;
|
|
17
|
+
color: var(--color-text);
|
|
18
|
+
background: var(--color-bg);
|
|
19
|
+
text-rendering: optimizeLegibility;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
body {
|
|
23
|
+
font-size: var(--text-base);
|
|
24
|
+
line-height: var(--leading-body);
|
|
25
|
+
margin: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* ===== Paragraph rhythm (Tufte: indent, no parskip) =====
|
|
29
|
+
* No indent on the first paragraph after a heading — standard book rule.
|
|
30
|
+
* Indent every subsequent paragraph. */
|
|
31
|
+
p {
|
|
32
|
+
margin: 0 0 var(--space-4) 0;
|
|
33
|
+
text-indent: 1em;
|
|
34
|
+
hanging-punctuation: first last;
|
|
35
|
+
}
|
|
36
|
+
h1 + p,
|
|
37
|
+
h2 + p,
|
|
38
|
+
h3 + p,
|
|
39
|
+
h4 + p,
|
|
40
|
+
h5 + p,
|
|
41
|
+
h6 + p,
|
|
42
|
+
hr + p,
|
|
43
|
+
blockquote + p,
|
|
44
|
+
ul + p,
|
|
45
|
+
ol + p,
|
|
46
|
+
pre + p {
|
|
47
|
+
text-indent: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* ===== Headings — blue italic, distinctive ===== */
|
|
51
|
+
h1, h2, h3, h4, h5, h6 {
|
|
52
|
+
font-weight: 500;
|
|
53
|
+
font-style: italic;
|
|
54
|
+
color: var(--color-heading);
|
|
55
|
+
line-height: var(--leading-tight);
|
|
56
|
+
margin: var(--space-8) 0 var(--space-3) 0;
|
|
57
|
+
text-wrap: balance;
|
|
58
|
+
}
|
|
59
|
+
h1 { font-size: var(--text-4xl); margin-top: 0; }
|
|
60
|
+
h2 { font-size: var(--text-3xl); }
|
|
61
|
+
h3 { font-size: var(--text-2xl); }
|
|
62
|
+
h4 { font-size: var(--text-xl); }
|
|
63
|
+
h5 { font-size: var(--text-lg); }
|
|
64
|
+
h6 { font-size: var(--text-base); font-weight: 600; font-style: normal; }
|
|
65
|
+
|
|
66
|
+
/* ===== Code ===== */
|
|
67
|
+
code {
|
|
68
|
+
font-family: var(--font-code);
|
|
69
|
+
font-size: 0.92em;
|
|
70
|
+
background: var(--color-code-bg);
|
|
71
|
+
padding: 0.1em 0.3em;
|
|
72
|
+
border-radius: var(--radius-sm);
|
|
73
|
+
border: 1px solid var(--color-code-border);
|
|
74
|
+
}
|
|
75
|
+
pre {
|
|
76
|
+
font-family: var(--font-code);
|
|
77
|
+
background: var(--color-code-bg);
|
|
78
|
+
border: 1px solid var(--color-code-border);
|
|
79
|
+
border-radius: var(--radius-md);
|
|
80
|
+
padding: var(--space-4);
|
|
81
|
+
margin: var(--space-4) 0;
|
|
82
|
+
overflow-x: auto;
|
|
83
|
+
line-height: var(--leading-normal);
|
|
84
|
+
}
|
|
85
|
+
pre code {
|
|
86
|
+
background: transparent;
|
|
87
|
+
padding: 0;
|
|
88
|
+
border: 0;
|
|
89
|
+
font-size: var(--text-sm);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* ===== Links ===== */
|
|
93
|
+
a {
|
|
94
|
+
color: var(--color-link);
|
|
95
|
+
text-decoration: underline;
|
|
96
|
+
text-decoration-thickness: 1px;
|
|
97
|
+
text-underline-offset: 0.15em;
|
|
98
|
+
}
|
|
99
|
+
a:hover {
|
|
100
|
+
text-decoration-thickness: 2px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* ===== Lists ===== */
|
|
104
|
+
ul, ol {
|
|
105
|
+
margin: 0 0 var(--space-4) 0;
|
|
106
|
+
padding-left: var(--space-6);
|
|
107
|
+
}
|
|
108
|
+
li {
|
|
109
|
+
margin-bottom: var(--space-1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* ===== Text emphasis ===== */
|
|
113
|
+
small { font-size: var(--text-sm); }
|
|
114
|
+
em { font-style: italic; }
|
|
115
|
+
strong { font-weight: 600; }
|
|
116
|
+
|
|
117
|
+
/* ===== Blockquotes ===== */
|
|
118
|
+
blockquote {
|
|
119
|
+
margin: var(--space-4) 0;
|
|
120
|
+
padding: 0 var(--space-4);
|
|
121
|
+
border-left: var(--border-bar) solid var(--color-border);
|
|
122
|
+
color: var(--color-text-muted);
|
|
123
|
+
font-style: italic;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* ===== Horizontal rule ===== */
|
|
127
|
+
hr {
|
|
128
|
+
border: 0;
|
|
129
|
+
border-top: 1px solid var(--color-border);
|
|
130
|
+
margin: var(--space-8) 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* ===== Tables ===== */
|
|
134
|
+
table {
|
|
135
|
+
border-collapse: collapse;
|
|
136
|
+
margin: var(--space-4) 0;
|
|
137
|
+
font-size: var(--text-sm);
|
|
138
|
+
}
|
|
139
|
+
th, td {
|
|
140
|
+
text-align: left;
|
|
141
|
+
padding: var(--space-2) var(--space-3);
|
|
142
|
+
border-bottom: 1px solid var(--color-border);
|
|
143
|
+
}
|
|
144
|
+
th {
|
|
145
|
+
font-weight: 600;
|
|
146
|
+
color: var(--color-heading);
|
|
147
|
+
}
|