@andrewxhill/graphics-press-css 4.2.1
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/README.md +117 -0
- package/css/graphics-press.css +1149 -0
- package/css/graphics-press.min.css +1 -0
- package/package.json +51 -0
- package/tailwind/index.js +1739 -0
|
@@ -0,0 +1,1149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graphics Press CSS v4.2.1
|
|
3
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
* A typographic and data-visualization CSS library derived from the books
|
|
5
|
+
* of Edward Tufte, the cartographic color principles of Eduard Imhof, and
|
|
6
|
+
* the typographic standards of Robert Bringhurst.
|
|
7
|
+
*
|
|
8
|
+
* Primary sources
|
|
9
|
+
* The Visual Display of Quantitative Information (Tufte, 1983/2001)
|
|
10
|
+
* Envisioning Information (Tufte, 1990)
|
|
11
|
+
* Visual Explanations (Tufte, 1997)
|
|
12
|
+
* Beautiful Evidence (Tufte, 2006)
|
|
13
|
+
* Cartographic Relief Presentation (Imhof, 1982)
|
|
14
|
+
* The Elements of Typographic Style (Bringhurst, 3rd ed.)
|
|
15
|
+
*
|
|
16
|
+
* Modern CSS used throughout
|
|
17
|
+
* @layer — specificity-safe cascade; consumer overrides require
|
|
18
|
+
* no !important and no selector wrestling
|
|
19
|
+
* oklch() — perceptually uniform color; categorical palette at
|
|
20
|
+
* equal lightness per Imhof's equal-weight principle
|
|
21
|
+
* clamp() — fluid type scale; body scales 14px → 16px with viewport
|
|
22
|
+
* font-variant-numeric — oldstyle figures in prose, tabular lining in tables
|
|
23
|
+
* position: sticky — sidenotes remain visible while scrolling their section
|
|
24
|
+
* prefers-reduced-motion — sparkline animation gated correctly
|
|
25
|
+
* prefers-color-scheme — dark mode: warm paper inverted, not naive black
|
|
26
|
+
*
|
|
27
|
+
* SVG color note
|
|
28
|
+
* CSS custom properties inside @layer do not reliably cascade into SVG
|
|
29
|
+
* element style="" attributes in all browsers. For inline SVG charts:
|
|
30
|
+
* use hardcoded hex presentation attributes (stroke="#b5322a").
|
|
31
|
+
* CSS vars work normally on HTML elements. Heat table cells use
|
|
32
|
+
* precomputed oklch() values set as inline style="background:oklch(...)".
|
|
33
|
+
*
|
|
34
|
+
* MIT License. See LICENSE for details.
|
|
35
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/* ── ET Book (Tufte's open-source Bembo digitisation) ───────────────────── */
|
|
39
|
+
|
|
40
|
+
@font-face {
|
|
41
|
+
font-family: "ET Book";
|
|
42
|
+
src: url("https://edwardtufte.github.io/et-book/et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.woff") format("woff"),
|
|
43
|
+
url("https://edwardtufte.github.io/et-book/et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.ttf") format("truetype");
|
|
44
|
+
font-weight: normal; font-style: normal; font-display: swap;
|
|
45
|
+
}
|
|
46
|
+
@font-face {
|
|
47
|
+
font-family: "ET Book";
|
|
48
|
+
src: url("https://edwardtufte.github.io/et-book/et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.woff") format("woff"),
|
|
49
|
+
url("https://edwardtufte.github.io/et-book/et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.ttf") format("truetype");
|
|
50
|
+
font-weight: normal; font-style: italic; font-display: swap;
|
|
51
|
+
}
|
|
52
|
+
@font-face {
|
|
53
|
+
font-family: "ET Book";
|
|
54
|
+
src: url("https://edwardtufte.github.io/et-book/et-book/et-book-bold-line-figures/et-book-bold-line-figures.woff") format("woff"),
|
|
55
|
+
url("https://edwardtufte.github.io/et-book/et-book/et-book-bold-line-figures/et-book-bold-line-figures.ttf") format("truetype");
|
|
56
|
+
font-weight: bold; font-style: normal; font-display: swap;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ── Layer order ─────────────────────────────────────────────────────────────
|
|
60
|
+
Consumer overrides: write unlayered CSS or add a later named @layer.
|
|
61
|
+
@layer my-theme { :root { --gp-red: oklch(55% 0.18 340); } } */
|
|
62
|
+
|
|
63
|
+
@layer gp.reset, gp.tokens, gp.base, gp.layout, gp.components, gp.dataviz, gp.utilities;
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
67
|
+
TOKENS — override any variable at :root to retheme without forking
|
|
68
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
69
|
+
|
|
70
|
+
@layer gp.tokens {
|
|
71
|
+
|
|
72
|
+
:root {
|
|
73
|
+
color-scheme: light;
|
|
74
|
+
|
|
75
|
+
/* Layout ─────────────────────────────────────────────────────── */
|
|
76
|
+
/* Layout ─────────────────────────────────────────────────────── */
|
|
77
|
+
--gp-text-width: 640px; /* reading column; ~60 chars at 15px */
|
|
78
|
+
--gp-margin-width: 260px; /* sidenote / margin figure column */
|
|
79
|
+
--gp-gutter: 48px; /* gap between text and margin */
|
|
80
|
+
|
|
81
|
+
/* Outer margin: fluid, scales with viewport.
|
|
82
|
+
clamp(floor, preferred, ceiling):
|
|
83
|
+
48px at ≤600px — always enough to breathe, never touch the edge
|
|
84
|
+
64px at 800px — comfortable on tablet/narrow desktop
|
|
85
|
+
80px at 1000px — book-like on typical desktop
|
|
86
|
+
96px at 1200px+ — generous; Tufte's print outer margin ≈ 15–20% of width
|
|
87
|
+
|
|
88
|
+
In print, Tufte's outer margins are roughly 1–1.5 inches on a 9" page
|
|
89
|
+
(~11–17% of page width). 8vw at 1000px = 80px = 8% — screen is less
|
|
90
|
+
generous than print by design, but still clearly intentional. */
|
|
91
|
+
--gp-outer-margin: clamp(3rem, 8vw, 6rem);
|
|
92
|
+
|
|
93
|
+
--gp-page-width: calc(var(--gp-text-width) + var(--gp-gutter) + var(--gp-margin-width));
|
|
94
|
+
|
|
95
|
+
/* Typefaces ──────────────────────────────────────────────────── */
|
|
96
|
+
--gp-serif: "ET Book", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
|
|
97
|
+
--gp-sans: "Gill Sans", "Gill Sans MT", Calibri, Optima, "Trebuchet MS", sans-serif;
|
|
98
|
+
--gp-mono: "Lucida Console", "Andale Mono", Monaco, Consolas, monospace;
|
|
99
|
+
|
|
100
|
+
/* Fluid type scale ───────────────────────────────────────────── */
|
|
101
|
+
--gp-font-size: clamp(14px, 1vw + 10px, 16px);
|
|
102
|
+
--gp-line-height: clamp(1.58, 1.5 + 0.4vw, 1.68);
|
|
103
|
+
--gp-small: 0.8em;
|
|
104
|
+
--gp-caption: 0.77em;
|
|
105
|
+
--gp-micro: 0.69em;
|
|
106
|
+
|
|
107
|
+
/* Spacing ────────────────────────────────────────────────────── */
|
|
108
|
+
--gp-space-xs: 0.25rem;
|
|
109
|
+
--gp-space-sm: 0.5rem;
|
|
110
|
+
--gp-space-md: 1rem;
|
|
111
|
+
--gp-space-lg: 2rem;
|
|
112
|
+
--gp-space-xl: 4rem;
|
|
113
|
+
|
|
114
|
+
/* Surface — warm cream, not pure white ───────────────────────── */
|
|
115
|
+
--gp-paper: oklch(99.4% 0.008 98); /* ≈ #fffff8 */
|
|
116
|
+
--gp-ink: oklch(17% 0.004 60); /* ≈ #111111 */
|
|
117
|
+
--gp-margin-ink: oklch(43% 0.003 60); /* ≈ #555555 */
|
|
118
|
+
--gp-ghost-ink: oklch(69% 0.003 60); /* ≈ #aaaaaa */
|
|
119
|
+
--gp-rule: oklch(62% 0.002 60); /* ≈ #999999 */
|
|
120
|
+
--gp-light-rule: oklch(84% 0.005 95); /* ≈ #d4d4c8 */
|
|
121
|
+
--gp-code-bg: oklch(95% 0.006 95); /* ≈ #f0f0e8 */
|
|
122
|
+
|
|
123
|
+
/* Categorical palette — all at equal perceptual lightness ───────
|
|
124
|
+
Imhof's equal-weight principle: every series reads the same
|
|
125
|
+
visual weight. Green/ochre ↑ slightly for Helmholtz-Kohlrausch. */
|
|
126
|
+
--gp-red: oklch(44% 0.14 27); /* muted crimson ≈ #b5322a */
|
|
127
|
+
--gp-red-light: oklch(64% 0.10 27); /* ≈ #d98080 */
|
|
128
|
+
--gp-blue: oklch(44% 0.09 251); /* slate blue ≈ #3a5a8c */
|
|
129
|
+
--gp-blue-light: oklch(64% 0.07 251); /* ≈ #90a8c8 */
|
|
130
|
+
--gp-green: oklch(50% 0.08 149); /* sage green ≈ #4a7a50 */
|
|
131
|
+
--gp-green-light: oklch(67% 0.06 149); /* ≈ #92b897 */
|
|
132
|
+
--gp-ochre: oklch(49% 0.10 72); /* warm ochre ≈ #8b6914 */
|
|
133
|
+
--gp-ochre-light: oklch(67% 0.08 72); /* ≈ #c8a85a */
|
|
134
|
+
--gp-brown: oklch(42% 0.09 52); /* warm brown ≈ #6b4423 */
|
|
135
|
+
--gp-gray-data: oklch(51% 0.002 60); /* context gray ≈ #777777 */
|
|
136
|
+
|
|
137
|
+
/* Sequential ramp — uniform lightness steps, single ochre hue ── */
|
|
138
|
+
--gp-seq-1: oklch(95% 0.04 80);
|
|
139
|
+
--gp-seq-2: oklch(82% 0.07 76);
|
|
140
|
+
--gp-seq-3: oklch(68% 0.09 72);
|
|
141
|
+
--gp-seq-4: oklch(55% 0.10 68);
|
|
142
|
+
--gp-seq-5: oklch(42% 0.10 65);
|
|
143
|
+
|
|
144
|
+
/* Diverging ramp — blue ← midpoint → red ───────────────────── */
|
|
145
|
+
--gp-div-lo-2: oklch(44% 0.09 251);
|
|
146
|
+
--gp-div-lo-1: oklch(64% 0.07 251);
|
|
147
|
+
--gp-div-mid: oklch(92% 0.004 95);
|
|
148
|
+
--gp-div-hi-1: oklch(64% 0.10 27);
|
|
149
|
+
--gp-div-hi-2: oklch(44% 0.14 27);
|
|
150
|
+
|
|
151
|
+
/* Animation ──────────────────────────────────────────────────── */
|
|
152
|
+
--gp-ease: cubic-bezier(0.4, 0, 0.2, 1);
|
|
153
|
+
--gp-ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Dark mode — prefers-color-scheme ───────────────────────────────
|
|
157
|
+
Warm dark paper (not pure black). Data colors at L=66% to
|
|
158
|
+
maintain contrast and equal weight against dark background. */
|
|
159
|
+
@media (prefers-color-scheme: dark) {
|
|
160
|
+
:root:not(.light) {
|
|
161
|
+
color-scheme: dark;
|
|
162
|
+
--gp-paper: oklch(17% 0.008 80);
|
|
163
|
+
--gp-ink: oklch(90% 0.005 85);
|
|
164
|
+
--gp-margin-ink: oklch(63% 0.005 85);
|
|
165
|
+
--gp-ghost-ink: oklch(40% 0.004 85);
|
|
166
|
+
--gp-rule: oklch(35% 0.003 85);
|
|
167
|
+
--gp-light-rule: oklch(27% 0.005 85);
|
|
168
|
+
--gp-code-bg: oklch(22% 0.007 80);
|
|
169
|
+
--gp-red: oklch(66% 0.13 27);
|
|
170
|
+
--gp-red-light: oklch(76% 0.09 27);
|
|
171
|
+
--gp-blue: oklch(66% 0.09 251);
|
|
172
|
+
--gp-blue-light: oklch(76% 0.06 251);
|
|
173
|
+
--gp-green: oklch(66% 0.08 149);
|
|
174
|
+
--gp-green-light: oklch(76% 0.06 149);
|
|
175
|
+
--gp-ochre: oklch(66% 0.09 72);
|
|
176
|
+
--gp-ochre-light: oklch(76% 0.07 72);
|
|
177
|
+
--gp-gray-data: oklch(58% 0.002 60);
|
|
178
|
+
--gp-seq-1: oklch(35% 0.06 72); --gp-seq-2: oklch(47% 0.08 72);
|
|
179
|
+
--gp-seq-3: oklch(59% 0.09 72); --gp-seq-4: oklch(71% 0.09 72);
|
|
180
|
+
--gp-seq-5: oklch(83% 0.07 72);
|
|
181
|
+
--gp-div-lo-2: oklch(66% 0.09 251); --gp-div-lo-1: oklch(76% 0.06 251);
|
|
182
|
+
--gp-div-mid: oklch(25% 0.004 85);
|
|
183
|
+
--gp-div-hi-1: oklch(76% 0.09 27); --gp-div-hi-2: oklch(66% 0.13 27);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* ── Dark mode manual class — OUTSIDE @layer so it beats everything ─────────
|
|
190
|
+
Unlayered CSS wins over all @layer rules regardless of specificity.
|
|
191
|
+
Apply .dark to <html> via JavaScript to activate.
|
|
192
|
+
@media prefers-color-scheme still applies when .light class is absent. */
|
|
193
|
+
|
|
194
|
+
.dark {
|
|
195
|
+
color-scheme: dark;
|
|
196
|
+
--gp-paper: oklch(17% 0.008 80);
|
|
197
|
+
--gp-ink: oklch(90% 0.005 85);
|
|
198
|
+
--gp-margin-ink: oklch(63% 0.005 85);
|
|
199
|
+
--gp-ghost-ink: oklch(40% 0.004 85);
|
|
200
|
+
--gp-rule: oklch(35% 0.003 85);
|
|
201
|
+
--gp-light-rule: oklch(27% 0.005 85);
|
|
202
|
+
--gp-code-bg: oklch(22% 0.007 80);
|
|
203
|
+
--gp-red: oklch(66% 0.13 27);
|
|
204
|
+
--gp-red-light: oklch(76% 0.09 27);
|
|
205
|
+
--gp-blue: oklch(66% 0.09 251);
|
|
206
|
+
--gp-blue-light: oklch(76% 0.06 251);
|
|
207
|
+
--gp-green: oklch(66% 0.08 149);
|
|
208
|
+
--gp-green-light: oklch(76% 0.06 149);
|
|
209
|
+
--gp-ochre: oklch(66% 0.09 72);
|
|
210
|
+
--gp-ochre-light: oklch(76% 0.07 72);
|
|
211
|
+
--gp-gray-data: oklch(58% 0.002 60);
|
|
212
|
+
--gp-seq-1: oklch(35% 0.06 72); --gp-seq-2: oklch(47% 0.08 72);
|
|
213
|
+
--gp-seq-3: oklch(59% 0.09 72); --gp-seq-4: oklch(71% 0.09 72);
|
|
214
|
+
--gp-seq-5: oklch(83% 0.07 72);
|
|
215
|
+
--gp-div-lo-2: oklch(66% 0.09 251); --gp-div-lo-1: oklch(76% 0.06 251);
|
|
216
|
+
--gp-div-mid: oklch(25% 0.004 85);
|
|
217
|
+
--gp-div-hi-1: oklch(76% 0.09 27); --gp-div-hi-2: oklch(66% 0.13 27);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* ── SVG color tokens — outside @layer so they cascade into SVG style="" attributes ───
|
|
221
|
+
CSS custom properties inside @layer don't reliably resolve in SVG.
|
|
222
|
+
These are defined at brace depth 0 and cascade correctly everywhere.
|
|
223
|
+
Light values match the hardcoded hex in the original Tufte palette.
|
|
224
|
+
Dark values shift:
|
|
225
|
+
Ink/text → warm near-white for legibility on dark paper
|
|
226
|
+
Neutrals → inverted: light grays become dark grays
|
|
227
|
+
Data colors → L=66% per the dark mode palette (equal-weight principle) */
|
|
228
|
+
|
|
229
|
+
:root {
|
|
230
|
+
/* Structural — ink, axes, labels */
|
|
231
|
+
--svg-ink: #111111; /* body text weight lines, axes */
|
|
232
|
+
--svg-margin: #555555; /* secondary labels, tick values */
|
|
233
|
+
--svg-mid: #777777; /* chart titles, mid-weight annotations */
|
|
234
|
+
--svg-rule-mid: #999999; /* medium rules, some axis lines */
|
|
235
|
+
|
|
236
|
+
/* Ghost / neutral tracks */
|
|
237
|
+
--svg-ghost: #aaaaaa; /* ghost lines, track backgrounds */
|
|
238
|
+
--svg-rule: #cccccc; /* light rules, grid lines */
|
|
239
|
+
--svg-light-rule: #d4d4c8; /* very light rules, track lines */
|
|
240
|
+
--svg-soft: #dddddd; /* soft separators */
|
|
241
|
+
--svg-faint: #eeeeee; /* barely-there backgrounds */
|
|
242
|
+
--svg-dim: #888888; /* ghosted comparison lines */
|
|
243
|
+
--svg-dark-rule: #333333; /* stronger rules on some charts */
|
|
244
|
+
|
|
245
|
+
/* Data — categorical, equal perceptual lightness */
|
|
246
|
+
--svg-red: #b5322a; /* primary highlight / decrease */
|
|
247
|
+
--svg-blue: #3a5a8c; /* primary comparison / before */
|
|
248
|
+
--svg-green: #4a7a50; /* positive / growth */
|
|
249
|
+
--svg-ochre: #8b6914; /* fourth category */
|
|
250
|
+
--svg-blue-light: #90a8c8; /* muted blue connector (dumbbell UK) */
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* Dark mode overrides — same selector as .dark for tokens, brace depth 0 */
|
|
254
|
+
.dark {
|
|
255
|
+
--svg-ink: #e6e0d8;
|
|
256
|
+
--svg-margin: #a09898;
|
|
257
|
+
--svg-mid: #8a8480;
|
|
258
|
+
--svg-rule-mid: #606060;
|
|
259
|
+
--svg-ghost: #505050;
|
|
260
|
+
--svg-rule: #404040;
|
|
261
|
+
--svg-light-rule: #383430;
|
|
262
|
+
--svg-soft: #353030;
|
|
263
|
+
--svg-faint: #2e2a26;
|
|
264
|
+
--svg-dim: #585450;
|
|
265
|
+
--svg-dark-rule: #888480;
|
|
266
|
+
--svg-red: #e07070;
|
|
267
|
+
--svg-blue: #7090c8;
|
|
268
|
+
--svg-green: #70b078;
|
|
269
|
+
--svg-ochre: #c8a040;
|
|
270
|
+
--svg-blue-light: #7090c8;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* ── Heat table dark mode — darken inline oklch backgrounds ──────────────────
|
|
274
|
+
Inline background:oklch() values are hardcoded for light mode. In dark mode
|
|
275
|
+
the cool end (L≈95%) produces near-white cells with near-white text → unreadable.
|
|
276
|
+
An inset box-shadow overlays a dark wash on the background without affecting
|
|
277
|
+
text color. Text is forced to light. The hue ramp is preserved. */
|
|
278
|
+
.dark .heat-table td.heat,
|
|
279
|
+
.dark .heat-table td.heat-div { color: oklch(93% 0.005 85) !important; box-shadow: inset 0 0 0 100vmax oklch(17% 0.008 80 / 0.6); }
|
|
280
|
+
|
|
281
|
+
@media (prefers-color-scheme: dark) {
|
|
282
|
+
:root:not(.light) .heat-table td.heat,
|
|
283
|
+
:root:not(.light) .heat-table td.heat-div { color: oklch(93% 0.005 85) !important; box-shadow: inset 0 0 0 100vmax oklch(17% 0.008 80 / 0.6); }
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
287
|
+
RESET
|
|
288
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
289
|
+
|
|
290
|
+
@layer gp.reset {
|
|
291
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
292
|
+
html {
|
|
293
|
+
font-size: var(--gp-font-size);
|
|
294
|
+
background: var(--gp-paper); color: var(--gp-ink);
|
|
295
|
+
transition: background-color 0.25s var(--gp-ease), color 0.25s var(--gp-ease);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
301
|
+
BASE — typography, prose, and structural HTML elements
|
|
302
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
303
|
+
|
|
304
|
+
@layer gp.base {
|
|
305
|
+
|
|
306
|
+
body {
|
|
307
|
+
font-family: var(--gp-serif);
|
|
308
|
+
font-weight: normal;
|
|
309
|
+
line-height: var(--gp-line-height);
|
|
310
|
+
background: var(--gp-paper); color: var(--gp-ink);
|
|
311
|
+
margin: 0; padding: 0;
|
|
312
|
+
counter-reset: sidenote-counter;
|
|
313
|
+
text-align: left;
|
|
314
|
+
hyphens: none; -webkit-hyphens: none;
|
|
315
|
+
font-variant-numeric: oldstyle-nums proportional-nums;
|
|
316
|
+
font-optical-sizing: auto;
|
|
317
|
+
/* Minimum page breathing room — applies even when <article> is absent.
|
|
318
|
+
Ensures text is never flush against the viewport edge regardless of
|
|
319
|
+
how the library is used. The article's own padding adds on top. */
|
|
320
|
+
min-height: 100dvh;
|
|
321
|
+
padding-left: env(safe-area-inset-left);
|
|
322
|
+
padding-right: env(safe-area-inset-right);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* Headings — italic, never bold; hierarchy through size not weight */
|
|
326
|
+
h1 { font-size: clamp(1.7rem, 3vw + 0.8rem, 2.4rem); font-style: italic; font-weight: normal; line-height: 1.18; font-optical-sizing: auto; margin: 0 0 var(--gp-space-sm); max-width: var(--gp-text-width); }
|
|
327
|
+
h2 { font-size: clamp(1rem, 0.8vw + 0.75rem, 1.1rem); font-style: italic; font-weight: normal; margin: var(--gp-space-lg) 0 var(--gp-space-sm); max-width: var(--gp-text-width); }
|
|
328
|
+
h3 { font-size: 1rem; font-style: italic; font-weight: normal; margin: var(--gp-space-md) 0 var(--gp-space-xs); max-width: var(--gp-text-width); }
|
|
329
|
+
h4, h5, h6 { font-size: 0.94rem; font-weight: normal; font-variant: small-caps; letter-spacing: 0.06em; margin: var(--gp-space-md) 0 var(--gp-space-xs); max-width: var(--gp-text-width); }
|
|
330
|
+
|
|
331
|
+
.subtitle { font-size: 1.04rem; font-style: italic; margin: calc(-1 * var(--gp-space-xs)) 0 var(--gp-space-lg); color: var(--gp-margin-ink); max-width: var(--gp-text-width); }
|
|
332
|
+
.author { font-family: var(--gp-sans); font-size: var(--gp-small); letter-spacing: 0.04em; color: var(--gp-margin-ink); margin: calc(-1 * var(--gp-space-md)) 0 var(--gp-space-xl); font-variant-numeric: lining-nums; max-width: var(--gp-text-width); }
|
|
333
|
+
|
|
334
|
+
p { margin: 0 0 var(--gp-space-md); max-width: var(--gp-text-width); }
|
|
335
|
+
p + p { margin-top: calc(-1 * var(--gp-space-sm)); text-indent: 1.5em; }
|
|
336
|
+
h1 + p, h2 + p, h3 + p, h4 + p, blockquote + p, figure + p, hr + p { text-indent: 0; }
|
|
337
|
+
p.lead { font-size: 1.06rem; text-indent: 0; }
|
|
338
|
+
p.drop-cap::first-letter { font-size: 3.6em; line-height: 0.72; float: left; padding-right: 0.06em; margin-top: 0.06em; font-style: normal; }
|
|
339
|
+
|
|
340
|
+
abbr, .small-caps { font-variant: small-caps; letter-spacing: 0.06em; font-size: 0.9em; }
|
|
341
|
+
em { font-style: italic; }
|
|
342
|
+
strong { font-weight: bold; }
|
|
343
|
+
sup, sub { font-size: 0.7em; line-height: 0; position: relative; vertical-align: baseline; font-variant-numeric: lining-nums; }
|
|
344
|
+
sup { top: -0.5em; } sub { bottom: -0.25em; }
|
|
345
|
+
|
|
346
|
+
a { color: var(--gp-ink); text-decoration: underline; text-decoration-color: var(--gp-light-rule); text-underline-offset: 2px; transition: text-decoration-color 0.15s; }
|
|
347
|
+
a:hover { text-decoration-color: var(--gp-ink); }
|
|
348
|
+
.sidenote a, .marginnote a, figcaption a { color: var(--gp-margin-ink); }
|
|
349
|
+
|
|
350
|
+
hr { border: none; margin: var(--gp-space-xl) 0; max-width: var(--gp-text-width); }
|
|
351
|
+
hr::after { content: "· · ·"; display: block; text-align: center; color: var(--gp-light-rule); letter-spacing: 0.5em; }
|
|
352
|
+
.rule-thin { border: none; border-top: 0.5px solid var(--gp-light-rule); margin: var(--gp-space-md) 0; max-width: var(--gp-text-width); }
|
|
353
|
+
|
|
354
|
+
/* Numeric OpenType features — tables override body's oldstyle setting */
|
|
355
|
+
table, .lnf { font-variant-numeric: lining-nums tabular-nums; }
|
|
356
|
+
.unit { font-size: 0.82em; color: var(--gp-margin-ink); font-variant-numeric: lining-nums; }
|
|
357
|
+
.datum { font-variant-numeric: lining-nums tabular-nums; font-family: var(--gp-sans); font-size: 0.9em; letter-spacing: -0.01em; }
|
|
358
|
+
.data-label { font-family: var(--gp-sans); font-size: var(--gp-micro); color: var(--gp-margin-ink); }
|
|
359
|
+
.source-line { font-family: var(--gp-sans); font-size: var(--gp-micro); color: var(--gp-ghost-ink); margin-top: var(--gp-space-xs); max-width: var(--gp-text-width); }
|
|
360
|
+
.source-line::before { content: "Source: "; }
|
|
361
|
+
|
|
362
|
+
ul, ol { padding-left: 1.5em; margin: 0 0 var(--gp-space-md); max-width: var(--gp-text-width); }
|
|
363
|
+
li { margin-bottom: var(--gp-space-xs); line-height: var(--gp-line-height); }
|
|
364
|
+
li > ul, li > ol { margin: var(--gp-space-xs) 0; }
|
|
365
|
+
dl { margin: 0 0 var(--gp-space-md); max-width: var(--gp-text-width); }
|
|
366
|
+
dt { font-variant: small-caps; letter-spacing: 0.05em; margin-top: var(--gp-space-sm); }
|
|
367
|
+
dd { margin-left: 1.5em; margin-bottom: var(--gp-space-xs); color: var(--gp-margin-ink); font-size: var(--gp-small); }
|
|
368
|
+
|
|
369
|
+
blockquote { font-style: italic; margin: var(--gp-space-md) 0 var(--gp-space-md) 2em; padding: 0; border: none; max-width: calc(var(--gp-text-width) - 2em); }
|
|
370
|
+
blockquote footer, blockquote cite { font-style: normal; font-size: var(--gp-small); color: var(--gp-margin-ink); display: block; margin-top: var(--gp-space-xs); }
|
|
371
|
+
blockquote footer::before { content: "— "; }
|
|
372
|
+
|
|
373
|
+
.epigraph { margin: var(--gp-space-xl) 0 var(--gp-space-xl) 5%; max-width: var(--gp-text-width); }
|
|
374
|
+
.epigraph > blockquote { font-style: italic; font-size: 1.04rem; margin: 0; padding: 0; border: none; }
|
|
375
|
+
.epigraph > blockquote footer { font-style: normal; font-size: var(--gp-small); color: var(--gp-margin-ink); display: block; margin-top: var(--gp-space-sm); }
|
|
376
|
+
|
|
377
|
+
code, kbd, samp { font-family: var(--gp-mono); font-size: 0.84em; background: var(--gp-code-bg); padding: 0.06em 0.28em; border-radius: 2px; font-variant-numeric: lining-nums; transition: background-color 0.25s; }
|
|
378
|
+
pre { background: var(--gp-code-bg); padding: var(--gp-space-md); overflow-x: auto; margin: var(--gp-space-md) 0; border-left: 2px solid var(--gp-light-rule); max-width: var(--gp-text-width); transition: background-color 0.25s, border-color 0.25s; }
|
|
379
|
+
pre code { background: none; padding: 0; font-size: var(--gp-small); line-height: 1.5; }
|
|
380
|
+
|
|
381
|
+
.new-thought { font-variant: small-caps; letter-spacing: 0.08em; }
|
|
382
|
+
.callout { font-size: var(--gp-small); color: var(--gp-margin-ink); font-style: italic; padding-left: 1em; border-left: 1px solid var(--gp-light-rule); margin: var(--gp-space-sm) 0; max-width: var(--gp-text-width); }
|
|
383
|
+
|
|
384
|
+
/* data-note: on-demand methodology / source notes */
|
|
385
|
+
details.data-note { font-size: var(--gp-small); color: var(--gp-margin-ink); margin: var(--gp-space-sm) 0; border-left: 1px solid var(--gp-light-rule); padding-left: var(--gp-space-sm); max-width: var(--gp-text-width); }
|
|
386
|
+
details.data-note summary { cursor: pointer; font-family: var(--gp-sans); font-size: var(--gp-micro); letter-spacing: 0.08em; text-transform: uppercase; color: var(--gp-ghost-ink); list-style: none; padding: var(--gp-space-xs) 0; transition: color 0.15s; user-select: none; }
|
|
387
|
+
details.data-note summary::-webkit-details-marker { display: none; }
|
|
388
|
+
details.data-note summary::before { content: "▸ "; font-size: 0.8em; }
|
|
389
|
+
details.data-note[open] summary::before { content: "▾ "; }
|
|
390
|
+
details.data-note summary:hover { color: var(--gp-margin-ink); }
|
|
391
|
+
|
|
392
|
+
.bibliography { margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); }
|
|
393
|
+
.bibliography ol, .bibliography ul { padding-left: 0; list-style: none; }
|
|
394
|
+
.bibliography li { font-size: var(--gp-small); padding-left: 2em; text-indent: -2em; margin-bottom: var(--gp-space-sm); color: var(--gp-margin-ink); line-height: 1.5; }
|
|
395
|
+
.bibliography .title { font-style: italic; }
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
400
|
+
LAYOUT
|
|
401
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
402
|
+
|
|
403
|
+
@layer gp.layout {
|
|
404
|
+
|
|
405
|
+
article {
|
|
406
|
+
position: relative;
|
|
407
|
+
max-width: var(--gp-page-width);
|
|
408
|
+
margin: 0 auto;
|
|
409
|
+
/* Vertical: generous top/bottom breathing.
|
|
410
|
+
Horizontal: the fluid --gp-outer-margin does the work.
|
|
411
|
+
On wide screens this naturally centers the text column with
|
|
412
|
+
substantial white space on both sides — exactly as intended. */
|
|
413
|
+
padding: var(--gp-space-xl) var(--gp-outer-margin);
|
|
414
|
+
}
|
|
415
|
+
section { padding-top: var(--gp-space-lg); }
|
|
416
|
+
|
|
417
|
+
.running-header {
|
|
418
|
+
font-family: var(--gp-sans); font-size: var(--gp-micro); letter-spacing: 0.12em;
|
|
419
|
+
text-transform: uppercase; color: var(--gp-ghost-ink);
|
|
420
|
+
max-width: var(--gp-page-width);
|
|
421
|
+
display: flex; justify-content: space-between;
|
|
422
|
+
border-bottom: 0.5px solid var(--gp-light-rule);
|
|
423
|
+
padding-bottom: var(--gp-space-sm); margin-bottom: var(--gp-space-xl);
|
|
424
|
+
transition: border-color 0.25s, color 0.25s;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Two-column figure comparison */
|
|
428
|
+
.figure-compare { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gp-space-md); max-width: var(--gp-text-width); margin: var(--gp-space-lg) 0; align-items: start; }
|
|
429
|
+
.figure-compare.figure-compare-full { max-width: var(--gp-page-width); }
|
|
430
|
+
.figure-compare figure { margin: 0; max-width: none; }
|
|
431
|
+
.figure-compare figcaption { float: none !important; width: auto !important; margin-right: 0 !important; margin-top: var(--gp-space-xs); }
|
|
432
|
+
|
|
433
|
+
/* Before/after columns */
|
|
434
|
+
.compare-wrap { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gp-space-lg); max-width: var(--gp-text-width); margin: var(--gp-space-lg) 0; border-top: 0.75px solid var(--gp-rule); padding-top: var(--gp-space-md); }
|
|
435
|
+
.compare-wrap.compare-wrap-full { max-width: var(--gp-page-width); }
|
|
436
|
+
.compare-col { font-size: var(--gp-small); }
|
|
437
|
+
.compare-col__header { font-family: var(--gp-sans); font-size: var(--gp-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--gp-margin-ink); margin-bottom: var(--gp-space-sm); padding-bottom: 2px; border-bottom: 0.5px solid var(--gp-light-rule); }
|
|
438
|
+
.compare-col.before { color: var(--gp-margin-ink); }
|
|
439
|
+
|
|
440
|
+
/* Pull statistics grid */
|
|
441
|
+
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: var(--gp-space-md) var(--gp-space-lg); border-top: 1.5px solid var(--gp-ink); padding-top: var(--gp-space-md); margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); transition: border-color 0.25s; }
|
|
442
|
+
|
|
443
|
+
/* Evidence layout (Beautiful Evidence pp. 82–97)
|
|
444
|
+
Image + analysis column side by side as a unified analytical object. */
|
|
445
|
+
.evidence { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--gp-space-lg); max-width: var(--gp-page-width); margin: var(--gp-space-lg) 0; align-items: start; }
|
|
446
|
+
.evidence__image { margin: 0; max-width: none; }
|
|
447
|
+
.evidence__image img, .evidence__image svg { max-width: 100%; height: auto; display: block; }
|
|
448
|
+
.evidence__image figcaption { float: none; width: auto; margin-right: 0; margin-top: var(--gp-space-xs); font-size: var(--gp-caption); font-family: var(--gp-sans); color: var(--gp-margin-ink); }
|
|
449
|
+
.evidence__analysis { font-size: var(--gp-small); line-height: 1.6; color: var(--gp-ink); padding-top: 0.1rem; }
|
|
450
|
+
.evidence__analysis p { max-width: none; }
|
|
451
|
+
.evidence__analysis p + p { text-indent: 1.2em; }
|
|
452
|
+
.evidence__caption { grid-column: 1 / -1; font-family: var(--gp-sans); font-size: var(--gp-caption); color: var(--gp-margin-ink); border-top: 0.5px solid var(--gp-light-rule); padding-top: var(--gp-space-xs); margin-top: var(--gp-space-xs); }
|
|
453
|
+
|
|
454
|
+
/* Analytical brief framing for dashboard-like narrative pages */
|
|
455
|
+
.brief-header { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--gp-space-md) var(--gp-space-lg); align-items: end; max-width: var(--gp-page-width); margin: var(--gp-space-lg) 0; padding-bottom: var(--gp-space-sm); border-bottom: 0.75px solid var(--gp-rule); }
|
|
456
|
+
.brief-header__meta { margin: 0 0 0.4rem; font-family: var(--gp-sans); font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gp-ghost-ink); }
|
|
457
|
+
.brief-header__title { margin: 0; max-width: none; font-size: clamp(1.5rem, 2vw + 1rem, 2.2rem); }
|
|
458
|
+
.brief-header__dek { margin: 0.45rem 0 0; max-width: 52rem; font-size: var(--gp-small); color: var(--gp-margin-ink); text-indent: 0; }
|
|
459
|
+
.brief-header__stat { text-align: right; align-self: start; min-width: 12rem; }
|
|
460
|
+
.brief-header__label { display: block; margin-bottom: 0.2rem; font-family: var(--gp-sans); font-size: 0.74rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--gp-ghost-ink); }
|
|
461
|
+
.brief-header__value { display: block; font-size: clamp(2rem, 3vw + 0.7rem, 3.1rem); line-height: 0.95; color: var(--gp-green); font-style: italic; font-variant-numeric: lining-nums tabular-nums; }
|
|
462
|
+
.brief-header__subvalue { display: block; margin-top: 0.2rem; font-family: var(--gp-sans); font-size: var(--gp-caption); color: var(--gp-margin-ink); }
|
|
463
|
+
.brief-backlink { display: inline-block; margin-bottom: var(--gp-space-sm); font-family: var(--gp-sans); font-size: 0.8rem; letter-spacing: 0.04em; color: var(--gp-ghost-ink); text-decoration: none; }
|
|
464
|
+
.brief-backlink:hover { color: var(--gp-ink); }
|
|
465
|
+
|
|
466
|
+
/* Narrative slippy-map frame: map, inset key, and supporting summary */
|
|
467
|
+
.gp-map-block { max-width: var(--gp-page-width); margin: var(--gp-space-lg) 0; }
|
|
468
|
+
.gp-map-frame {
|
|
469
|
+
position: relative;
|
|
470
|
+
border: 0.5px solid var(--gp-light-rule);
|
|
471
|
+
background: var(--gp-code-bg);
|
|
472
|
+
min-height: 28rem;
|
|
473
|
+
overflow: hidden;
|
|
474
|
+
box-shadow: 0 10px 30px oklch(from var(--gp-ink) l c h / 0.08);
|
|
475
|
+
transition: border-color 0.25s, background-color 0.25s, box-shadow 0.25s;
|
|
476
|
+
}
|
|
477
|
+
.gp-map { width: 100%; min-height: 28rem; background: oklch(from var(--gp-paper) calc(l - 0.02) c h); }
|
|
478
|
+
.gp-map-panel {
|
|
479
|
+
position: absolute;
|
|
480
|
+
left: var(--gp-space-md);
|
|
481
|
+
top: var(--gp-space-md);
|
|
482
|
+
z-index: 2;
|
|
483
|
+
width: min(19rem, calc(100% - 2rem));
|
|
484
|
+
padding: 0.8rem 0.9rem;
|
|
485
|
+
background: oklch(from var(--gp-paper) l c h / 0.92);
|
|
486
|
+
border: 0.5px solid oklch(from var(--gp-rule) l c h / 0.5);
|
|
487
|
+
backdrop-filter: blur(10px);
|
|
488
|
+
}
|
|
489
|
+
.gp-map-kicker {
|
|
490
|
+
display: block;
|
|
491
|
+
margin-bottom: 0.35rem;
|
|
492
|
+
font-family: var(--gp-sans);
|
|
493
|
+
font-size: var(--gp-micro);
|
|
494
|
+
letter-spacing: 0.12em;
|
|
495
|
+
text-transform: uppercase;
|
|
496
|
+
color: var(--gp-ghost-ink);
|
|
497
|
+
}
|
|
498
|
+
.gp-map-title {
|
|
499
|
+
margin: 0 0 0.45rem;
|
|
500
|
+
font-size: 1rem;
|
|
501
|
+
line-height: 1.3;
|
|
502
|
+
color: var(--gp-ink);
|
|
503
|
+
max-width: none;
|
|
504
|
+
}
|
|
505
|
+
.gp-map-panel p {
|
|
506
|
+
margin: 0;
|
|
507
|
+
max-width: none;
|
|
508
|
+
font-family: var(--gp-sans);
|
|
509
|
+
font-size: var(--gp-small);
|
|
510
|
+
line-height: 1.45;
|
|
511
|
+
color: var(--gp-margin-ink);
|
|
512
|
+
text-indent: 0;
|
|
513
|
+
}
|
|
514
|
+
.gp-map-key {
|
|
515
|
+
display: flex;
|
|
516
|
+
flex-wrap: wrap;
|
|
517
|
+
gap: 0.5rem 0.9rem;
|
|
518
|
+
margin: 0.7rem 0 0;
|
|
519
|
+
padding: 0;
|
|
520
|
+
list-style: none;
|
|
521
|
+
}
|
|
522
|
+
.gp-map-key li {
|
|
523
|
+
display: inline-flex;
|
|
524
|
+
align-items: center;
|
|
525
|
+
gap: 0.35rem;
|
|
526
|
+
margin: 0;
|
|
527
|
+
font-family: var(--gp-sans);
|
|
528
|
+
font-size: var(--gp-micro);
|
|
529
|
+
letter-spacing: 0.02em;
|
|
530
|
+
color: var(--gp-margin-ink);
|
|
531
|
+
}
|
|
532
|
+
.gp-map-swatch {
|
|
533
|
+
width: 0.72rem;
|
|
534
|
+
height: 0.72rem;
|
|
535
|
+
border-radius: 999px;
|
|
536
|
+
border: 1px solid oklch(from var(--gp-paper) calc(l - 0.18) c h / 0.55);
|
|
537
|
+
flex: 0 0 auto;
|
|
538
|
+
}
|
|
539
|
+
.gp-map-swatch.red { background: var(--gp-red); }
|
|
540
|
+
.gp-map-swatch.blue { background: var(--gp-blue); }
|
|
541
|
+
.gp-map-swatch.ochre { background: var(--gp-ochre); }
|
|
542
|
+
.gp-map-meta {
|
|
543
|
+
display: grid;
|
|
544
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
545
|
+
gap: 0.75rem;
|
|
546
|
+
margin-top: var(--gp-space-sm);
|
|
547
|
+
padding-top: var(--gp-space-sm);
|
|
548
|
+
border-top: 0.5px solid var(--gp-light-rule);
|
|
549
|
+
font-family: var(--gp-sans);
|
|
550
|
+
}
|
|
551
|
+
.gp-map-stat {
|
|
552
|
+
font-size: var(--gp-micro);
|
|
553
|
+
color: var(--gp-ghost-ink);
|
|
554
|
+
letter-spacing: 0.06em;
|
|
555
|
+
text-transform: uppercase;
|
|
556
|
+
}
|
|
557
|
+
.gp-map-stat strong {
|
|
558
|
+
display: block;
|
|
559
|
+
margin-top: 0.12rem;
|
|
560
|
+
font-size: 1rem;
|
|
561
|
+
line-height: 1.2;
|
|
562
|
+
letter-spacing: normal;
|
|
563
|
+
text-transform: none;
|
|
564
|
+
color: var(--gp-ink);
|
|
565
|
+
font-weight: normal;
|
|
566
|
+
font-variant-numeric: lining-nums tabular-nums;
|
|
567
|
+
}
|
|
568
|
+
.gp-map-frame .maplibregl-ctrl-group {
|
|
569
|
+
border-radius: 0;
|
|
570
|
+
box-shadow: none;
|
|
571
|
+
border: 0.5px solid var(--gp-light-rule);
|
|
572
|
+
background: oklch(from var(--gp-paper) l c h / 0.9);
|
|
573
|
+
}
|
|
574
|
+
.gp-map-frame .maplibregl-ctrl button .maplibregl-ctrl-icon { filter: grayscale(1); }
|
|
575
|
+
.gp-map-frame .maplibregl-popup-content {
|
|
576
|
+
border-radius: 0;
|
|
577
|
+
padding: 0.55rem 0.65rem;
|
|
578
|
+
font-family: var(--gp-sans);
|
|
579
|
+
font-size: var(--gp-small);
|
|
580
|
+
color: var(--gp-ink);
|
|
581
|
+
background: oklch(from var(--gp-paper) l c h / 0.96);
|
|
582
|
+
box-shadow: 0 6px 20px oklch(from var(--gp-ink) l c h / 0.12);
|
|
583
|
+
}
|
|
584
|
+
.gp-map-frame .maplibregl-popup-tip { border-top-color: oklch(from var(--gp-paper) l c h / 0.96); }
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
589
|
+
COMPONENTS — sidenotes, figures, tables, sparklines
|
|
590
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
591
|
+
|
|
592
|
+
@layer gp.components {
|
|
593
|
+
|
|
594
|
+
/* ── Sidenotes & Margin Notes ─────────────────────────────────────────────
|
|
595
|
+
The structural innovation of Tufte's books. Notes appear beside the text
|
|
596
|
+
they annotate, not below the page. position:sticky keeps them visible
|
|
597
|
+
while scrolling long sections.
|
|
598
|
+
|
|
599
|
+
Sidenote (numbered):
|
|
600
|
+
<label for="sn-1" class="sidenote-toggle sidenote-number"></label>
|
|
601
|
+
<input type="checkbox" id="sn-1" class="sidenote-toggle">
|
|
602
|
+
<span class="sidenote">Content.</span>
|
|
603
|
+
|
|
604
|
+
Margin note (unnumbered):
|
|
605
|
+
<label for="mn-1" class="sidenote-toggle">⊕</label>
|
|
606
|
+
<input type="checkbox" id="mn-1" class="sidenote-toggle">
|
|
607
|
+
<span class="marginnote">Content.</span> */
|
|
608
|
+
|
|
609
|
+
.sidenote-number { counter-increment: sidenote-counter; }
|
|
610
|
+
.sidenote-number::after, .sidenote::before { content: counter(sidenote-counter); font-size: 0.68rem; vertical-align: super; line-height: 0; font-variant-numeric: lining-nums; }
|
|
611
|
+
.sidenote-number::after { color: var(--gp-margin-ink); padding-left: 1px; }
|
|
612
|
+
.sidenote::before { color: var(--gp-margin-ink); padding-right: 4px; }
|
|
613
|
+
input.sidenote-toggle { display: none; }
|
|
614
|
+
|
|
615
|
+
.sidenote, .marginnote {
|
|
616
|
+
float: right; clear: right;
|
|
617
|
+
margin-right: calc(-1 * (var(--gp-margin-width) + var(--gp-gutter)));
|
|
618
|
+
width: var(--gp-margin-width);
|
|
619
|
+
font-size: var(--gp-small); line-height: 1.5;
|
|
620
|
+
color: var(--gp-margin-ink); font-style: normal;
|
|
621
|
+
vertical-align: baseline;
|
|
622
|
+
position: sticky; top: 2rem;
|
|
623
|
+
padding-top: 0.08rem;
|
|
624
|
+
transition: color 0.25s;
|
|
625
|
+
}
|
|
626
|
+
.marginnote img, .marginnote svg { max-width: 100%; height: auto; display: block; margin-bottom: var(--gp-space-xs); }
|
|
627
|
+
.marginnote svg { overflow: visible; }
|
|
628
|
+
.marginnote-label { font-family: var(--gp-sans); font-size: var(--gp-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--gp-ghost-ink); display: block; margin-bottom: 2px; }
|
|
629
|
+
label.sidenote-toggle { display: none; cursor: pointer; }
|
|
630
|
+
label.sidenote-number { display: inline; }
|
|
631
|
+
|
|
632
|
+
.section-marker { float: right; clear: right; margin-right: calc(-1 * (var(--gp-margin-width) + var(--gp-gutter))); width: var(--gp-margin-width); font-family: var(--gp-sans); font-size: var(--gp-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--gp-ghost-ink); padding-top: 0.2rem; position: sticky; top: 2rem; }
|
|
633
|
+
|
|
634
|
+
/* ── Figures ─────────────────────────────────────────────────────────────
|
|
635
|
+
Three widths:
|
|
636
|
+
<figure> — column-width (default)
|
|
637
|
+
<figure class="figure-full"> — spans into margin
|
|
638
|
+
<figure class="figure-margin"> — margin only, floated */
|
|
639
|
+
|
|
640
|
+
figure { max-width: var(--gp-text-width); margin: var(--gp-space-lg) 0; padding: 0; }
|
|
641
|
+
figure img, figure svg, figure canvas { max-width: 100%; height: auto; display: block; }
|
|
642
|
+
figure.figure-full { max-width: var(--gp-page-width); }
|
|
643
|
+
figure.figure-margin { float: right; clear: right; margin-right: calc(-1 * (var(--gp-margin-width) + var(--gp-gutter))); width: var(--gp-margin-width); margin-top: 0; margin-bottom: var(--gp-space-md); }
|
|
644
|
+
|
|
645
|
+
figcaption { font-size: var(--gp-caption); font-family: var(--gp-sans); font-optical-sizing: auto; line-height: 1.45; color: var(--gp-margin-ink); margin-top: var(--gp-space-xs); transition: color 0.25s; }
|
|
646
|
+
figure:not(.figure-margin):not(.figure-full):not(.evidence__image) figcaption { float: right; clear: right; margin-right: calc(-1 * (var(--gp-margin-width) + var(--gp-gutter))); width: var(--gp-margin-width); margin-top: 0; }
|
|
647
|
+
figure.figure-full figcaption { float: right; width: var(--gp-margin-width); margin-top: var(--gp-space-xs); }
|
|
648
|
+
figure.figure-margin figcaption { float: none; width: auto; font-size: 0.71em; }
|
|
649
|
+
|
|
650
|
+
/* ── Tables — Booktabs ───────────────────────────────────────────────────
|
|
651
|
+
Three rules only: top 1.5px, mid 0.75px, bottom 1.5px.
|
|
652
|
+
No vertical lines. Numeric columns right-aligned, tabular figures.
|
|
653
|
+
Set in Gill Sans — exactly as Tufte's books. */
|
|
654
|
+
|
|
655
|
+
table { max-width: var(--gp-text-width); width: 100%; border-collapse: collapse; font-family: var(--gp-sans); font-size: var(--gp-small); font-variant-numeric: lining-nums tabular-nums; margin: var(--gp-space-lg) 0; line-height: 1.4; transition: color 0.25s; }
|
|
656
|
+
thead { border-top: 1.5px solid var(--gp-ink); border-bottom: 0.75px solid var(--gp-ink); }
|
|
657
|
+
tbody tr:last-child td { border-bottom: 1.5px solid var(--gp-ink); padding-bottom: var(--gp-space-sm); }
|
|
658
|
+
tbody tr.midrule td { border-top: 0.75px solid var(--gp-rule); padding-top: var(--gp-space-sm); }
|
|
659
|
+
tbody tr.midrule-above td { padding-bottom: var(--gp-space-sm); }
|
|
660
|
+
th { font-weight: normal; font-variant: small-caps; letter-spacing: 0.06em; text-align: left; padding: var(--gp-space-xs) var(--gp-space-sm); vertical-align: bottom; }
|
|
661
|
+
td { padding: var(--gp-space-xs) var(--gp-space-sm); vertical-align: top; }
|
|
662
|
+
td.num, th.num { text-align: right; }
|
|
663
|
+
td.neg { color: var(--gp-red); } td.pos { color: var(--gp-green); }
|
|
664
|
+
tr.highlight td { background: var(--gp-code-bg); font-style: italic; }
|
|
665
|
+
.table-dense th, .table-dense td { padding: 2px var(--gp-space-xs); font-size: var(--gp-micro); }
|
|
666
|
+
table.table-full { max-width: var(--gp-page-width); }
|
|
667
|
+
table.table-striped tbody tr:nth-child(even) td { background: oklch(from var(--gp-paper) calc(l - 0.02) c h); }
|
|
668
|
+
caption { font-size: var(--gp-caption); font-family: var(--gp-sans); color: var(--gp-margin-ink); text-align: left; caption-side: top; padding-bottom: var(--gp-space-xs); }
|
|
669
|
+
|
|
670
|
+
/* ── Sparklines ──────────────────────────────────────────────────────────
|
|
671
|
+
Word-sized inline charts. Draw animation gated by prefers-reduced-motion. */
|
|
672
|
+
|
|
673
|
+
.sparkline { display: inline-block; vertical-align: middle; line-height: 1; position: relative; top: -1px; }
|
|
674
|
+
.sparkline svg { overflow: visible; }
|
|
675
|
+
|
|
676
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
677
|
+
.sp-draw { stroke-dasharray: 300; stroke-dashoffset: 300; animation: gp-draw 0.9s var(--gp-ease-out) forwards; }
|
|
678
|
+
@keyframes gp-draw { to { stroke-dashoffset: 0; } }
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/* Sparkline table — Tufte's canonical high-density format (Beautiful Evidence pp. 47–63) */
|
|
682
|
+
table.sparkline-table { font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
683
|
+
table.sparkline-table .sp-cell { padding-top: 2px; padding-bottom: 2px; }
|
|
684
|
+
table.sparkline-table .sp-cell svg { display: block; overflow: visible; }
|
|
685
|
+
|
|
686
|
+
/* ── Small Multiples ──────────────────────────────────────────────────── */
|
|
687
|
+
|
|
688
|
+
.small-multiples { max-width: var(--gp-page-width); display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: var(--gp-space-md); margin: var(--gp-space-lg) 0; }
|
|
689
|
+
.small-multiples-3 { grid-template-columns: repeat(3, 1fr); }
|
|
690
|
+
.small-multiples-4 { grid-template-columns: repeat(4, 1fr); }
|
|
691
|
+
.small-multiples-6 { grid-template-columns: repeat(6, 1fr); }
|
|
692
|
+
.small-multiples figure { margin: 0; max-width: none; }
|
|
693
|
+
.small-multiples figure figcaption { float: none !important; width: auto !important; margin-right: 0 !important; margin-top: var(--gp-space-xs); font-size: 0.7em; }
|
|
694
|
+
.small-multiples-xlabel { grid-column: 1 / -1; font-family: var(--gp-sans); font-size: var(--gp-micro); color: var(--gp-margin-ink); text-align: center; margin-top: calc(-1 * var(--gp-space-sm)); }
|
|
695
|
+
|
|
696
|
+
/* ── Pull statistics ──────────────────────────────────────────────────── */
|
|
697
|
+
|
|
698
|
+
.pull-stat { margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); }
|
|
699
|
+
.pull-stat__number { font-size: clamp(2.4rem, 4vw + 1rem, 3.5rem); line-height: 1; font-style: italic; font-weight: normal; display: block; font-variant-numeric: lining-nums; }
|
|
700
|
+
.pull-stat__label { font-family: var(--gp-sans); font-size: var(--gp-small); color: var(--gp-margin-ink); letter-spacing: 0.04em; display: block; margin-top: 0.2em; }
|
|
701
|
+
.pull-stat__context { font-size: var(--gp-small); color: var(--gp-ghost-ink); font-style: italic; display: block; }
|
|
702
|
+
.pull-quote { font-size: clamp(1.2rem, 2vw + 0.6rem, 1.45rem); font-style: italic; line-height: 1.35; margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); }
|
|
703
|
+
|
|
704
|
+
.metric-strip { max-width: var(--gp-page-width); display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 0; border-top: 0.75px solid var(--gp-rule); border-bottom: 0.75px solid var(--gp-rule); margin: var(--gp-space-md) 0; }
|
|
705
|
+
.metric-strip__item { padding: 0.55rem 0.8rem 0.5rem 0; font-family: var(--gp-sans); }
|
|
706
|
+
.metric-strip__label { display: block; font-size: 0.74rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--gp-ghost-ink); }
|
|
707
|
+
.metric-strip__value { display: block; margin-top: 0.14rem; font-size: 1.05rem; color: var(--gp-ink); font-style: italic; font-variant-numeric: lining-nums tabular-nums; }
|
|
708
|
+
.metric-strip__value.green { color: var(--gp-green); }
|
|
709
|
+
.metric-strip__value.red { color: var(--gp-red); }
|
|
710
|
+
.metric-strip__value.blue { color: var(--gp-blue); }
|
|
711
|
+
|
|
712
|
+
.tab-nav { max-width: var(--gp-page-width); display: flex; flex-wrap: wrap; gap: 0.1rem 0.9rem; margin: 0 0 var(--gp-space-md); padding: 0 0 var(--gp-space-xs); border-bottom: 0.5px solid var(--gp-light-rule); list-style: none; }
|
|
713
|
+
.tab-nav li { margin: 0; }
|
|
714
|
+
.tab-nav a, .tab-nav button { display: inline-block; padding: 0.32rem 0; border: 0; border-bottom: 1.5px solid transparent; background: none; font-family: var(--gp-sans); font-size: 0.76rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--gp-ghost-ink); text-decoration: none; cursor: pointer; }
|
|
715
|
+
.tab-nav .is-active, .tab-nav a[aria-current="page"], .tab-nav button[aria-selected="true"] { color: var(--gp-ink); border-bottom-color: var(--gp-ink); }
|
|
716
|
+
.tab-nav.tab-nav--filled { gap: 0.25rem 0.55rem; border-bottom-color: var(--gp-rule); }
|
|
717
|
+
.tab-nav.tab-nav--filled a, .tab-nav.tab-nav--filled button { padding: 0.45rem 0.8rem; border-bottom-width: 0; color: var(--gp-margin-ink); }
|
|
718
|
+
.tab-nav.tab-nav--filled .is-active,
|
|
719
|
+
.tab-nav.tab-nav--filled a[aria-current="page"],
|
|
720
|
+
.tab-nav.tab-nav--filled button[aria-selected="true"] { background: var(--gp-ink); color: var(--gp-paper); }
|
|
721
|
+
|
|
722
|
+
.analytic-grid { max-width: var(--gp-page-width); display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--gp-space-sm); margin: var(--gp-space-md) 0; }
|
|
723
|
+
.analytic-card { position: relative; min-height: 8.5rem; padding: 0.75rem 0.8rem 0.7rem; border: 0.5px solid var(--gp-light-rule); background: linear-gradient(180deg, oklch(from var(--gp-paper) calc(l - 0.005) c h), oklch(from var(--gp-paper) calc(l - 0.018) c h)); box-shadow: inset 0 1px 0 oklch(from var(--gp-paper) calc(l - 0.001) c h / 0.9); }
|
|
724
|
+
.analytic-card::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--gp-ghost-ink); }
|
|
725
|
+
.analytic-card.red::before { background: var(--gp-red); }
|
|
726
|
+
.analytic-card.blue::before { background: var(--gp-blue); }
|
|
727
|
+
.analytic-card.green::before { background: var(--gp-green); }
|
|
728
|
+
.analytic-card.ochre::before { background: var(--gp-ochre); }
|
|
729
|
+
.analytic-card__eyebrow { display: block; margin: 0 0 0.25rem; padding-left: 0.35rem; font-family: var(--gp-sans); font-size: 0.74rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--gp-ghost-ink); }
|
|
730
|
+
.analytic-card__title { margin: 0; padding-left: 0.35rem; max-width: none; font-size: 0.98rem; line-height: 1.25; }
|
|
731
|
+
.analytic-card__value { display: block; margin: 0.5rem 0 0.18rem; padding-left: 0.35rem; font-size: 1.35rem; line-height: 1; color: var(--gp-ink); font-style: italic; font-variant-numeric: lining-nums tabular-nums; }
|
|
732
|
+
.analytic-card__meta { display: block; padding-left: 0.35rem; font-family: var(--gp-sans); font-size: var(--gp-caption); color: var(--gp-margin-ink); }
|
|
733
|
+
|
|
734
|
+
.algorithm-panel { max-width: var(--gp-text-width); margin: var(--gp-space-lg) 0; border: 0.5px solid var(--gp-light-rule); background: var(--gp-code-bg); padding: var(--gp-space-md); }
|
|
735
|
+
.algorithm-panel__title { margin: 0 0 0.55rem; font-family: var(--gp-sans); font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gp-ghost-ink); }
|
|
736
|
+
.algorithm-panel pre { margin: 0; max-width: none; border-left: 0; padding: 0; background: transparent; }
|
|
737
|
+
|
|
738
|
+
.activity-timeline { max-width: var(--gp-page-width); margin: var(--gp-space-lg) 0; padding-top: var(--gp-space-xs); border-top: 0.5px solid var(--gp-light-rule); }
|
|
739
|
+
.activity-timeline__header { display: flex; justify-content: space-between; gap: var(--gp-space-sm); margin-bottom: var(--gp-space-sm); font-family: var(--gp-sans); font-size: 0.74rem; color: var(--gp-ghost-ink); }
|
|
740
|
+
.activity-timeline__lane { display: grid; grid-template-columns: 92px 1fr auto; align-items: center; gap: var(--gp-space-sm); margin-bottom: 0.45rem; font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
741
|
+
.activity-timeline__label { color: var(--gp-margin-ink); text-align: right; white-space: nowrap; }
|
|
742
|
+
.activity-timeline__track { position: relative; height: 0.85rem; background: oklch(from var(--gp-paper) calc(l - 0.05) c h); overflow: hidden; }
|
|
743
|
+
.activity-timeline__span { position: absolute; left: var(--at-start, 0%); width: var(--at-width, 50%); height: 100%; background: var(--gp-ghost-ink); }
|
|
744
|
+
.activity-timeline__span.red { background: var(--gp-red); }
|
|
745
|
+
.activity-timeline__span.blue { background: var(--gp-blue); }
|
|
746
|
+
.activity-timeline__span.green { background: var(--gp-green); }
|
|
747
|
+
.activity-timeline__span.ochre { background: var(--gp-ochre); }
|
|
748
|
+
.activity-timeline__value { color: var(--gp-ghost-ink); font-size: 0.74rem; white-space: nowrap; }
|
|
749
|
+
|
|
750
|
+
/* ── Minimal bar chart ────────────────────────────────────────────────── */
|
|
751
|
+
|
|
752
|
+
.bar-chart { list-style: none; padding: 0; margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); }
|
|
753
|
+
.bar-chart li { display: grid; grid-template-columns: 160px 1fr auto; align-items: center; gap: var(--gp-space-sm); margin-bottom: var(--gp-space-xs); font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
754
|
+
.bar-label { text-align: right; color: var(--gp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
755
|
+
.bar { position: relative; height: 1px; background: var(--gp-ghost-ink); }
|
|
756
|
+
.bar::after { content: ""; position: absolute; left: var(--bar-value, 50%); top: -3px; width: 1px; height: 7px; background: var(--gp-ink); }
|
|
757
|
+
.bar-chart.filled .bar { height: 8px; background: none; }
|
|
758
|
+
.bar-chart.filled .bar::before { content: ""; position: absolute; left: 0; top: 0; height: 100%; width: var(--bar-value, 0%); background: var(--gp-gray-data); }
|
|
759
|
+
.bar-chart.filled .bar::after { display: none; }
|
|
760
|
+
.bar-value { color: var(--gp-margin-ink); white-space: nowrap; font-variant-numeric: tabular-nums lining-nums; }
|
|
761
|
+
.bar.red::after, .bar-chart.filled .bar.red::before { background: var(--gp-red); }
|
|
762
|
+
.bar.blue::after, .bar-chart.filled .bar.blue::before { background: var(--gp-blue); }
|
|
763
|
+
.bar.green::after, .bar-chart.filled .bar.green::before { background: var(--gp-green); }
|
|
764
|
+
.bar.ochre::after, .bar-chart.filled .bar.ochre::before { background: var(--gp-ochre); }
|
|
765
|
+
|
|
766
|
+
/* ── Ghosting / emphasis ──────────────────────────────────────────────── */
|
|
767
|
+
.ghost { opacity: 0.22; } .near-ghost { opacity: 0.40; } .focal { opacity: 1; }
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
772
|
+
DATA VISUALIZATION — chart-specific components
|
|
773
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
774
|
+
|
|
775
|
+
@layer gp.dataviz {
|
|
776
|
+
|
|
777
|
+
/* ── Dot Chart (VDQI p. 178) ─────────────────────────────────────────────
|
|
778
|
+
Tufte's replacement for bar charts. Dots encode individual values;
|
|
779
|
+
no wasted ink of bar fills.
|
|
780
|
+
|
|
781
|
+
<ul class="dot-chart">
|
|
782
|
+
<li>
|
|
783
|
+
<span class="dc-label">Country A</span>
|
|
784
|
+
<span class="dc-track"><span class="dc-dot" style="--dc-pos:72%"></span></span>
|
|
785
|
+
<span class="dc-value">72</span>
|
|
786
|
+
</li>
|
|
787
|
+
</ul> */
|
|
788
|
+
|
|
789
|
+
.dot-chart { list-style: none; padding: 0; margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); }
|
|
790
|
+
.dot-chart li { display: grid; grid-template-columns: 160px 1fr auto; align-items: center; gap: var(--gp-space-sm); margin-bottom: var(--gp-space-xs); font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
791
|
+
.dc-label { text-align: right; color: var(--gp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
792
|
+
.dc-track { position: relative; height: 1px; background: var(--gp-light-rule); }
|
|
793
|
+
.dc-dot { position: absolute; left: var(--dc-pos, 50%); top: 50%; transform: translate(-50%, -50%); width: 6px; height: 6px; border-radius: 50%; background: var(--gp-ink); transition: background 0.25s; }
|
|
794
|
+
.dc-dot.red { background: var(--gp-red); }
|
|
795
|
+
.dc-dot.blue { background: var(--gp-blue); }
|
|
796
|
+
.dc-dot.green { background: var(--gp-green); }
|
|
797
|
+
.dc-dot.open { background: var(--gp-paper); border: 1.5px solid var(--gp-ink); }
|
|
798
|
+
.dc-value { color: var(--gp-margin-ink); font-variant-numeric: tabular-nums lining-nums; }
|
|
799
|
+
|
|
800
|
+
/* ── Dumbbell Chart (connected dot plot) ────────────────────────────────
|
|
801
|
+
Before/after: two dots connected by a line. Shows start, end, and
|
|
802
|
+
magnitude of change simultaneously.
|
|
803
|
+
|
|
804
|
+
<ul class="dumbbell">
|
|
805
|
+
<li>
|
|
806
|
+
<span class="db-label">Item A</span>
|
|
807
|
+
<span class="db-track" style="--db-l:34%;--db-r:68%">
|
|
808
|
+
<span class="db-dot db-dot--left" style="--db-l:34%"></span>
|
|
809
|
+
<span class="db-dot db-dot--right" style="--db-r:68%"></span>
|
|
810
|
+
</span>
|
|
811
|
+
<span class="db-value">34 → 68</span>
|
|
812
|
+
</li>
|
|
813
|
+
</ul> */
|
|
814
|
+
|
|
815
|
+
.dumbbell { list-style: none; padding: 0; margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); }
|
|
816
|
+
.dumbbell li { display: grid; grid-template-columns: 160px 1fr auto; align-items: center; gap: var(--gp-space-sm); margin-bottom: var(--gp-space-sm); font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
817
|
+
.db-label { text-align: right; color: var(--gp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
818
|
+
.db-track { position: relative; height: 1px; }
|
|
819
|
+
.db-track::before { content: ""; position: absolute; top: 0; left: var(--db-l, 30%); right: calc(100% - var(--db-r, 70%)); height: 1px; background: var(--gp-ghost-ink); }
|
|
820
|
+
.db-dot { position: absolute; top: 50%; width: 8px; height: 8px; border-radius: 50%; }
|
|
821
|
+
.db-dot--left { left: var(--db-l, 30%); transform: translate(-50%, -50%); background: var(--gp-blue); }
|
|
822
|
+
.db-dot--right { left: var(--db-r, 70%); transform: translate(-50%, -50%); background: var(--gp-red); }
|
|
823
|
+
.db-value { color: var(--gp-margin-ink); font-size: var(--gp-micro); white-space: nowrap; font-variant-numeric: lining-nums; }
|
|
824
|
+
|
|
825
|
+
/* ── Strip Plot (one-way scatter) ───────────────────────────────────────
|
|
826
|
+
Shows all observations; no invented distribution shapes.
|
|
827
|
+
|
|
828
|
+
<ul class="strip-plot">
|
|
829
|
+
<li>
|
|
830
|
+
<span class="sp-label">Group A</span>
|
|
831
|
+
<span class="sp-track">
|
|
832
|
+
<span class="sp-dot" style="--sp-pos:23%"></span>
|
|
833
|
+
<span class="sp-dot" style="--sp-pos:41%"></span>
|
|
834
|
+
</span>
|
|
835
|
+
</li>
|
|
836
|
+
</ul>
|
|
837
|
+
<div class="sp-axis-labels"><span>0</span><span>50</span><span>100</span></div> */
|
|
838
|
+
|
|
839
|
+
.strip-plot { list-style: none; padding: 0; margin: var(--gp-space-lg) 0; max-width: var(--gp-text-width); }
|
|
840
|
+
.strip-plot li { display: grid; grid-template-columns: 160px 1fr; align-items: center; gap: var(--gp-space-sm); margin-bottom: 10px; font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
841
|
+
.sp-label { text-align: right; color: var(--gp-ink); white-space: nowrap; }
|
|
842
|
+
.sp-track { position: relative; height: 1px; background: var(--gp-light-rule); }
|
|
843
|
+
.sp-dot { position: absolute; left: var(--sp-pos, 50%); top: 50%; transform: translate(-50%, -50%); width: 5px; height: 5px; border-radius: 50%; background: var(--gp-ink); opacity: 0.65; }
|
|
844
|
+
.sp-dot.red { background: var(--gp-red); }
|
|
845
|
+
.sp-dot.blue { background: var(--gp-blue); }
|
|
846
|
+
.sp-dot.green { background: var(--gp-green); }
|
|
847
|
+
.sp-axis-labels { display: flex; justify-content: space-between; margin-left: calc(160px + var(--gp-space-sm)); font-family: var(--gp-sans); font-size: var(--gp-micro); color: var(--gp-margin-ink); margin-top: 4px; font-variant-numeric: lining-nums; }
|
|
848
|
+
|
|
849
|
+
/* ── Stem-and-Leaf (VDQI p. 140) ────────────────────────────────────────
|
|
850
|
+
Histogram using the actual data digits. Use a real HTML <table> for
|
|
851
|
+
reliable three-column layout — display:table on divs is inconsistent.
|
|
852
|
+
|
|
853
|
+
<table class="stem-leaf">
|
|
854
|
+
<thead>
|
|
855
|
+
<tr>
|
|
856
|
+
<th class="sl-col-left">Group A</th>
|
|
857
|
+
<th class="sl-col-stem">Stem</th>
|
|
858
|
+
<th class="sl-col-right">Group B</th>
|
|
859
|
+
</tr>
|
|
860
|
+
</thead>
|
|
861
|
+
<tbody>
|
|
862
|
+
<tr>
|
|
863
|
+
<td class="sl-col-left">8 5 3</td>
|
|
864
|
+
<td class="sl-col-stem">4</td>
|
|
865
|
+
<td class="sl-col-right">0 2 6</td>
|
|
866
|
+
</tr>
|
|
867
|
+
</tbody>
|
|
868
|
+
</table>
|
|
869
|
+
<p class="sl-unit">Leaf unit = ...</p> */
|
|
870
|
+
|
|
871
|
+
table.stem-leaf {
|
|
872
|
+
font-family: var(--gp-mono);
|
|
873
|
+
font-size: var(--gp-small);
|
|
874
|
+
font-variant-numeric: lining-nums tabular-nums;
|
|
875
|
+
max-width: var(--gp-text-width);
|
|
876
|
+
margin: var(--gp-space-lg) 0;
|
|
877
|
+
line-height: 1.9;
|
|
878
|
+
border-collapse: collapse;
|
|
879
|
+
width: 100%;
|
|
880
|
+
border: none;
|
|
881
|
+
}
|
|
882
|
+
table.stem-leaf thead { border-bottom: 0.75px solid var(--gp-rule); }
|
|
883
|
+
table.stem-leaf thead th {
|
|
884
|
+
font-family: var(--gp-sans);
|
|
885
|
+
font-size: var(--gp-micro);
|
|
886
|
+
letter-spacing: 0.06em;
|
|
887
|
+
text-transform: uppercase;
|
|
888
|
+
color: var(--gp-ghost-ink);
|
|
889
|
+
font-weight: normal;
|
|
890
|
+
padding-bottom: 3px;
|
|
891
|
+
}
|
|
892
|
+
table.stem-leaf .sl-col-left { width: 43%; text-align: right; padding-right: 8px; color: var(--gp-blue); }
|
|
893
|
+
table.stem-leaf .sl-col-stem {
|
|
894
|
+
width: 14%; text-align: center; color: var(--gp-margin-ink);
|
|
895
|
+
border-left: 0.5px solid var(--gp-rule);
|
|
896
|
+
border-right: 0.5px solid var(--gp-rule);
|
|
897
|
+
padding: 0 4px;
|
|
898
|
+
}
|
|
899
|
+
table.stem-leaf thead .sl-col-stem { color: var(--gp-margin-ink); }
|
|
900
|
+
table.stem-leaf .sl-col-right { width: 43%; text-align: left; padding-left: 8px; }
|
|
901
|
+
.sl-unit { font-family: var(--gp-sans); font-size: var(--gp-micro); color: var(--gp-ghost-ink); margin-top: var(--gp-space-xs); }
|
|
902
|
+
|
|
903
|
+
/* ── Bullet Graph (Beautiful Evidence p. 176) ───────────────────────────
|
|
904
|
+
Tufte's replacement for gauge/speedometer charts.
|
|
905
|
+
RECOMMENDED: implement as inline SVG (see index.html for working example).
|
|
906
|
+
The CSS/HTML approach below uses position:absolute which is fragile.
|
|
907
|
+
SVG approach: three <rect> for qualitative bands, one <rect> for featured
|
|
908
|
+
bar, one <line> for the target tick. Fully reliable across browsers.
|
|
909
|
+
|
|
910
|
+
CSS/HTML fallback (may be unreliable in some rendering contexts):
|
|
911
|
+
<div class="bullet-graphs">
|
|
912
|
+
<div class="bullet-graph">
|
|
913
|
+
<span class="bg-label">Revenue</span>
|
|
914
|
+
<div class="bg-track">
|
|
915
|
+
<span class="bg-range bg-range-1" style="width:33%"></span>
|
|
916
|
+
<span class="bg-range bg-range-2" style="width:34%"></span>
|
|
917
|
+
<span class="bg-range bg-range-3" style="width:33%"></span>
|
|
918
|
+
<span class="bg-bar green" style="width:72%"></span>
|
|
919
|
+
<span class="bg-target" style="left:85%"></span>
|
|
920
|
+
</div>
|
|
921
|
+
<span class="bg-value">$72M</span>
|
|
922
|
+
</div>
|
|
923
|
+
</div>
|
|
924
|
+
<div class="bg-axis"><span>Poor</span><span>Satisfactory</span><span>Good</span></div> */
|
|
925
|
+
|
|
926
|
+
.bullet-graphs { max-width: var(--gp-text-width); margin: var(--gp-space-lg) 0; display: flex; flex-direction: column; gap: var(--gp-space-md); }
|
|
927
|
+
.bullet-graph { display: grid; grid-template-columns: 140px 1fr auto; align-items: center; gap: var(--gp-space-sm); font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
928
|
+
.bg-label { text-align: right; color: var(--gp-ink); }
|
|
929
|
+
.bg-track { position: relative; height: 16px; background: transparent; }
|
|
930
|
+
.bg-range { position: absolute; top: 0; height: 100%; display: inline-block; }
|
|
931
|
+
.bg-range-1 { left: 0; background: var(--gp-ghost-ink); opacity: 0.35; }
|
|
932
|
+
.bg-range-2 { left: 33%; background: var(--gp-ghost-ink); opacity: 0.22; }
|
|
933
|
+
.bg-range-3 { left: 66%; background: var(--gp-ghost-ink); opacity: 0.12; }
|
|
934
|
+
.bg-bar { position: absolute; left: 0; top: 25%; height: 50%; background: var(--gp-ink); z-index: 2; transition: background 0.25s; }
|
|
935
|
+
.bg-bar.red { background: var(--gp-red); }
|
|
936
|
+
.bg-bar.blue { background: var(--gp-blue); }
|
|
937
|
+
.bg-bar.green { background: var(--gp-green); }
|
|
938
|
+
.bg-target { position: absolute; top: 10%; height: 80%; width: 2px; background: var(--gp-ink); z-index: 3; transform: translateX(-50%); }
|
|
939
|
+
.bg-value { color: var(--gp-margin-ink); font-variant-numeric: tabular-nums lining-nums; }
|
|
940
|
+
.bg-axis { margin-left: calc(140px + var(--gp-space-sm)); display: flex; justify-content: space-between; font-family: var(--gp-sans); font-size: var(--gp-micro); color: var(--gp-ghost-ink); border-top: 0.5px solid var(--gp-light-rule); padding-top: 2px; }
|
|
941
|
+
|
|
942
|
+
/* ── Heat Table ──────────────────────────────────────────────────────────
|
|
943
|
+
Cell color encodes magnitude. Data is both visual and label.
|
|
944
|
+
Set background via inline style with precomputed oklch() values.
|
|
945
|
+
Note: calc() inside oklch() is not yet supported; precompute values.
|
|
946
|
+
|
|
947
|
+
Ochre sequential ramp guide (val 0.0=cool → 1.0=warm):
|
|
948
|
+
val 0.00 → oklch(95% 0.04 80) val 0.25 → oklch(82% 0.07 76)
|
|
949
|
+
val 0.50 → oklch(68% 0.09 72) val 0.75 → oklch(55% 0.10 68)
|
|
950
|
+
val 1.00 → oklch(42% 0.10 65)
|
|
951
|
+
|
|
952
|
+
<td class="heat num" style="background:oklch(57% 0.09 72)">27</td>
|
|
953
|
+
Dark cells: add data-dark attribute for automatic light text. */
|
|
954
|
+
|
|
955
|
+
.heat-table td.heat { color: var(--gp-ink); transition: background 0.2s; text-align: right; }
|
|
956
|
+
.heat-table td.heat[data-dark] { color: oklch(93% 0.005 85); }
|
|
957
|
+
.heat-table td.heat-div { text-align: right; transition: background 0.2s; }
|
|
958
|
+
|
|
959
|
+
/* ── Ranked Table ────────────────────────────────────────────────────────
|
|
960
|
+
Dotted leaders from label to value. Rank numbers recessive.
|
|
961
|
+
|
|
962
|
+
<table class="ranked-table">
|
|
963
|
+
<tbody>
|
|
964
|
+
<tr>
|
|
965
|
+
<td class="rank">1</td>
|
|
966
|
+
<td class="rank-label"><span>Entry Name</span></td>
|
|
967
|
+
<td class="num rank-value">42.1%</td>
|
|
968
|
+
</tr>
|
|
969
|
+
<tr class="rank-highlight">...</tr>
|
|
970
|
+
</tbody>
|
|
971
|
+
</table> */
|
|
972
|
+
|
|
973
|
+
table.ranked-table td.rank { color: var(--gp-ghost-ink); text-align: right; padding-right: var(--gp-space-sm); font-variant-numeric: lining-nums tabular-nums; width: 2em; }
|
|
974
|
+
table.ranked-table td.rank-label { background-image: radial-gradient(circle, var(--gp-light-rule) 1px, transparent 1px); background-size: 6px 1px; background-position: 0 0.9em; background-repeat: repeat-x; padding-right: var(--gp-space-sm); }
|
|
975
|
+
table.ranked-table td.rank-label span { background: var(--gp-paper); padding-right: 4px; transition: background 0.25s; }
|
|
976
|
+
table.ranked-table td.rank-value { font-variant-numeric: tabular-nums lining-nums; text-align: right; }
|
|
977
|
+
table.ranked-table tr.rank-highlight td.rank-label span,
|
|
978
|
+
table.ranked-table tr.rank-highlight td.rank-label { font-style: italic; }
|
|
979
|
+
|
|
980
|
+
/* ── Timeline ────────────────────────────────────────────────────────────
|
|
981
|
+
Horizontal display of events (dots) and periods (bars).
|
|
982
|
+
|
|
983
|
+
<div class="timeline">
|
|
984
|
+
<div class="tl-track">
|
|
985
|
+
<div class="tl-period blue" style="--tl-start:10%;--tl-end:40%">
|
|
986
|
+
<span class="tl-period-label">Period A</span>
|
|
987
|
+
</div>
|
|
988
|
+
<div class="tl-event" style="--tl-pos:25%">
|
|
989
|
+
<span class="tl-event-label">Event B</span>
|
|
990
|
+
</div>
|
|
991
|
+
</div>
|
|
992
|
+
<div class="tl-axis"><span>2010</span><span>2015</span><span>2020</span></div>
|
|
993
|
+
</div> */
|
|
994
|
+
|
|
995
|
+
.timeline { max-width: var(--gp-text-width); margin: var(--gp-space-lg) 0; font-family: var(--gp-sans); font-size: var(--gp-small); }
|
|
996
|
+
.tl-track { position: relative; height: 48px; border-bottom: 1px solid var(--gp-ink); }
|
|
997
|
+
.tl-event { position: absolute; left: var(--tl-pos, 50%); bottom: 0; transform: translateX(-50%); display: flex; flex-direction: column-reverse; align-items: center; }
|
|
998
|
+
.tl-event::after { content: ""; display: block; width: 6px; height: 6px; border-radius: 50%; background: var(--gp-ink); }
|
|
999
|
+
.tl-event-label { font-size: var(--gp-micro); color: var(--gp-ink); white-space: nowrap; margin-bottom: 4px; text-align: center; }
|
|
1000
|
+
.tl-period { position: absolute; bottom: 4px; left: var(--tl-start, 0%); right: calc(100% - var(--tl-end, 50%)); height: 8px; background: var(--gp-ghost-ink); opacity: 0.4; }
|
|
1001
|
+
.tl-period-label { position: absolute; top: -18px; left: 0; font-size: var(--gp-micro); color: var(--gp-margin-ink); white-space: nowrap; }
|
|
1002
|
+
.tl-period.red { background: var(--gp-red); opacity: 0.5; }
|
|
1003
|
+
.tl-period.blue { background: var(--gp-blue); opacity: 0.5; }
|
|
1004
|
+
.tl-period.green { background: var(--gp-green); opacity: 0.5; }
|
|
1005
|
+
.tl-period.ochre { background: var(--gp-ochre); opacity: 0.5; }
|
|
1006
|
+
.tl-axis { display: flex; justify-content: space-between; margin-top: 4px; font-size: var(--gp-micro); color: var(--gp-margin-ink); font-variant-numeric: lining-nums; }
|
|
1007
|
+
.tl-axis span::before { content: ""; display: block; width: 1px; height: 4px; background: var(--gp-rule); margin: 0 auto 2px; }
|
|
1008
|
+
|
|
1009
|
+
/* ── Slopegraph (VDQI p. 158) ────────────────────────────────────────── */
|
|
1010
|
+
.slopegraph-wrap { max-width: var(--gp-text-width); margin: var(--gp-space-lg) 0; }
|
|
1011
|
+
|
|
1012
|
+
/* ── Parallel Coordinates skeleton ──────────────────────────────────────
|
|
1013
|
+
CSS classes for SVG parallel coordinates charts. */
|
|
1014
|
+
.parallel-coords { max-width: var(--gp-page-width); margin: var(--gp-space-lg) 0; overflow-x: auto; }
|
|
1015
|
+
.parallel-coords svg { display: block; overflow: visible; }
|
|
1016
|
+
.pc-line { fill: none; stroke: var(--gp-ghost-ink); stroke-width: 0.75; opacity: 0.5; }
|
|
1017
|
+
.pc-line.highlight { stroke: var(--gp-red); stroke-width: 1.5; opacity: 1; }
|
|
1018
|
+
.pc-line.blue-hl { stroke: var(--gp-blue); stroke-width: 1.5; opacity: 1; }
|
|
1019
|
+
.pc-axis { stroke: var(--gp-rule); stroke-width: 0.75; }
|
|
1020
|
+
|
|
1021
|
+
/* ── SVG annotation conventions ──────────────────────────────────────── */
|
|
1022
|
+
.ann-line { stroke: var(--gp-ghost-ink); stroke-width: 0.6; fill: none; }
|
|
1023
|
+
.ann-text { font-family: var(--gp-sans); font-size: 8px; fill: var(--gp-margin-ink); font-style: italic; }
|
|
1024
|
+
.ref-band { fill: var(--gp-ghost-ink); fill-opacity: 0.10; stroke: none; }
|
|
1025
|
+
.ref-line { stroke: var(--gp-rule); stroke-width: 0.75; stroke-dasharray: 2 4; fill: none; }
|
|
1026
|
+
.zero-line { stroke: var(--gp-rule); stroke-width: 0.75; stroke-dasharray: 2 4; fill: none; }
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
1031
|
+
UTILITIES
|
|
1032
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
1033
|
+
|
|
1034
|
+
@layer gp.utilities {
|
|
1035
|
+
.gp-red { color: var(--gp-red); } .gp-blue { color: var(--gp-blue); }
|
|
1036
|
+
.gp-green { color: var(--gp-green); } .gp-ochre { color: var(--gp-ochre); }
|
|
1037
|
+
|
|
1038
|
+
.full-bleed { max-width: var(--gp-page-width) !important; }
|
|
1039
|
+
.align-right { text-align: right; } .align-center { text-align: center; }
|
|
1040
|
+
.sans { font-family: var(--gp-sans); } .mono { font-family: var(--gp-mono); }
|
|
1041
|
+
.italic { font-style: italic; }
|
|
1042
|
+
.muted { color: var(--gp-margin-ink); } .very-muted { color: var(--gp-ghost-ink); }
|
|
1043
|
+
.small { font-size: var(--gp-small); } .micro { font-size: var(--gp-micro); }
|
|
1044
|
+
.cf::after { content: ""; display: table; clear: both; }
|
|
1045
|
+
|
|
1046
|
+
.mt-sm { margin-top: var(--gp-space-sm); } .mt-md { margin-top: var(--gp-space-md); }
|
|
1047
|
+
.mt-lg { margin-top: var(--gp-space-lg); } .mt-xl { margin-top: var(--gp-space-xl); }
|
|
1048
|
+
.mb-sm { margin-bottom: var(--gp-space-sm); } .mb-md { margin-bottom: var(--gp-space-md); }
|
|
1049
|
+
.mb-lg { margin-bottom: var(--gp-space-lg); } .mb-xl { margin-bottom: var(--gp-space-xl); }
|
|
1050
|
+
|
|
1051
|
+
.seq-1 { color: var(--gp-seq-1); } .seq-2 { color: var(--gp-seq-2); }
|
|
1052
|
+
.seq-3 { color: var(--gp-seq-3); } .seq-4 { color: var(--gp-seq-4); }
|
|
1053
|
+
.seq-5 { color: var(--gp-seq-5); }
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
1058
|
+
RESPONSIVE — outside @layer (wins over all layered rules)
|
|
1059
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
1060
|
+
|
|
1061
|
+
@media (max-width: 960px) {
|
|
1062
|
+
/* Reduce vertical rhythm at narrow widths; horizontal uses the fluid token
|
|
1063
|
+
which already computes down to ~24px at mobile — no override needed. */
|
|
1064
|
+
article { padding-top: var(--gp-space-lg); padding-bottom: var(--gp-space-lg); }
|
|
1065
|
+
|
|
1066
|
+
label.sidenote-toggle:not(.sidenote-number) { display: inline; cursor: pointer; color: var(--gp-red); font-size: 0.85em; }
|
|
1067
|
+
.sidenote, .marginnote {
|
|
1068
|
+
display: none; float: none; position: static;
|
|
1069
|
+
margin: var(--gp-space-sm) 0; width: 100%;
|
|
1070
|
+
background: var(--gp-code-bg);
|
|
1071
|
+
padding: var(--gp-space-sm) var(--gp-space-md);
|
|
1072
|
+
border-left: 2px solid var(--gp-light-rule);
|
|
1073
|
+
font-size: var(--gp-small); color: var(--gp-margin-ink);
|
|
1074
|
+
}
|
|
1075
|
+
.sidenote-toggle:checked + .sidenote,
|
|
1076
|
+
.sidenote-toggle:checked + .marginnote { display: block; }
|
|
1077
|
+
|
|
1078
|
+
figure.figure-margin { float: none; margin-right: 0; width: 100%; }
|
|
1079
|
+
figure:not(.figure-margin):not(.figure-full):not(.evidence__image) figcaption { float: none; margin-right: 0; width: 100%; margin-top: var(--gp-space-xs); }
|
|
1080
|
+
figure.figure-full, figure.figure-full figcaption { max-width: 100%; float: none; width: 100%; }
|
|
1081
|
+
|
|
1082
|
+
.figure-compare, .compare-wrap, .evidence { grid-template-columns: 1fr; }
|
|
1083
|
+
.evidence__caption { grid-column: 1; }
|
|
1084
|
+
.brief-header { grid-template-columns: 1fr; }
|
|
1085
|
+
.brief-header__stat { text-align: left; min-width: 0; }
|
|
1086
|
+
.gp-map-frame, .gp-map { min-height: 24rem; }
|
|
1087
|
+
.gp-map-panel { width: min(18rem, calc(100% - 2rem)); }
|
|
1088
|
+
.gp-map-meta { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
1089
|
+
.small-multiples-3, .small-multiples-4 { grid-template-columns: repeat(2, 1fr); }
|
|
1090
|
+
.small-multiples-6 { grid-template-columns: repeat(3, 1fr); }
|
|
1091
|
+
.running-header { flex-direction: column; }
|
|
1092
|
+
|
|
1093
|
+
.dot-chart li, .dumbbell li, .bar-chart li { grid-template-columns: 100px 1fr auto; }
|
|
1094
|
+
.strip-plot li { grid-template-columns: 100px 1fr; }
|
|
1095
|
+
.sp-axis-labels { margin-left: calc(100px + var(--gp-space-sm)); }
|
|
1096
|
+
.bullet-graph { grid-template-columns: 100px 1fr auto; }
|
|
1097
|
+
.bg-axis { margin-left: calc(100px + var(--gp-space-sm)); }
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
@media (max-width: 560px) {
|
|
1101
|
+
article { padding-top: var(--gp-space-md); padding-bottom: var(--gp-space-md); }
|
|
1102
|
+
.stat-grid { grid-template-columns: repeat(2, 1fr); }
|
|
1103
|
+
.metric-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
1104
|
+
.activity-timeline__lane { grid-template-columns: 70px 1fr; }
|
|
1105
|
+
.activity-timeline__value { grid-column: 2; }
|
|
1106
|
+
.gp-map-frame, .gp-map { min-height: 21rem; }
|
|
1107
|
+
.gp-map-panel {
|
|
1108
|
+
left: var(--gp-space-sm);
|
|
1109
|
+
right: var(--gp-space-sm);
|
|
1110
|
+
top: var(--gp-space-sm);
|
|
1111
|
+
width: auto;
|
|
1112
|
+
padding: 0.7rem 0.75rem;
|
|
1113
|
+
}
|
|
1114
|
+
.gp-map-meta { grid-template-columns: 1fr; gap: 0.45rem; }
|
|
1115
|
+
.dot-chart li, .dumbbell li, .bar-chart li { grid-template-columns: 70px 1fr auto; }
|
|
1116
|
+
.strip-plot li { grid-template-columns: 70px 1fr; }
|
|
1117
|
+
.sp-axis-labels { margin-left: calc(70px + var(--gp-space-sm)); }
|
|
1118
|
+
.bullet-graph { grid-template-columns: 70px 1fr auto; }
|
|
1119
|
+
.bg-axis { margin-left: calc(70px + var(--gp-space-sm)); }
|
|
1120
|
+
.small-multiples-3, .small-multiples-4, .small-multiples-6 { grid-template-columns: repeat(2, 1fr); }
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
1125
|
+
PRINT
|
|
1126
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
1127
|
+
|
|
1128
|
+
@media print {
|
|
1129
|
+
:root {
|
|
1130
|
+
--gp-font-size: 11pt;
|
|
1131
|
+
--gp-text-width: 120mm;
|
|
1132
|
+
--gp-margin-width: 50mm;
|
|
1133
|
+
--gp-gutter: 10mm;
|
|
1134
|
+
--gp-outer-margin: 0mm;
|
|
1135
|
+
}
|
|
1136
|
+
html { color-scheme: light; }
|
|
1137
|
+
body { background: white; color: black; }
|
|
1138
|
+
article { max-width: none; padding: 0; }
|
|
1139
|
+
a { text-decoration: none; color: black; }
|
|
1140
|
+
.sidenote, .marginnote {
|
|
1141
|
+
display: block !important; float: right; position: static;
|
|
1142
|
+
margin-right: calc(-1 * (var(--gp-margin-width) + var(--gp-gutter)));
|
|
1143
|
+
width: var(--gp-margin-width); font-size: 8pt;
|
|
1144
|
+
background: none; border: none; padding: 0;
|
|
1145
|
+
}
|
|
1146
|
+
input.sidenote-toggle, label.sidenote-toggle:not(.sidenote-number) { display: none; }
|
|
1147
|
+
figure, table { break-inside: avoid; }
|
|
1148
|
+
h1, h2, h3 { break-after: avoid; }
|
|
1149
|
+
}
|