mdeck 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/assets/extensions/palettes/cobalt/extension.toml +30 -0
  4. package/assets/extensions/palettes/greyscale/extension.toml +57 -0
  5. package/assets/extensions/themes/glass/extension.toml +59 -0
  6. package/assets/extensions/themes/glass/styles.css +754 -0
  7. package/assets/extensions/themes/plain/extension.toml +58 -0
  8. package/assets/extensions/themes/plain/styles.css +471 -0
  9. package/assets/extensions/themes/work/extension.toml +57 -0
  10. package/assets/extensions/themes/work/styles.css +512 -0
  11. package/docs/reference/authoring.md +25 -8
  12. package/docs/reference/palettes.md +4 -3
  13. package/docs/reference/themes.md +5 -3
  14. package/docs/site/content/appearance.md +24 -10
  15. package/docs/site/content/audience.md +14 -0
  16. package/docs/site/content/theme-repository.md +7 -7
  17. package/docs/site/images/themes/academic-dark.webp +0 -0
  18. package/docs/site/images/themes/academic-light.webp +0 -0
  19. package/docs/site/images/themes/academic.webp +0 -0
  20. package/docs/site/images/themes/glass-dark.webp +0 -0
  21. package/docs/site/images/themes/glass-light.webp +0 -0
  22. package/docs/site/images/themes/glass.webp +0 -0
  23. package/docs/site/images/themes/minimal-dark.webp +0 -0
  24. package/docs/site/images/themes/minimal-light.webp +0 -0
  25. package/docs/site/images/themes/minimal.webp +0 -0
  26. package/docs/site/images/themes/neue-dark.webp +0 -0
  27. package/docs/site/images/themes/neue-light.webp +0 -0
  28. package/docs/site/images/themes/neue.webp +0 -0
  29. package/docs/site/images/themes/plain-dark.webp +0 -0
  30. package/docs/site/images/themes/plain-light.webp +0 -0
  31. package/docs/site/images/themes/plain.webp +0 -0
  32. package/docs/site/images/themes/work-dark.webp +0 -0
  33. package/docs/site/images/themes/work-light.webp +0 -0
  34. package/docs/site/images/themes/work.webp +0 -0
  35. package/examples/showcase/slides.md +2 -2
  36. package/package.json +4 -1
  37. package/skills/write-slides/SKILL.md +2 -2
  38. package/src/build/slidesPlugin.js +16 -15
  39. package/src/components/Poll.jsx +17 -5
  40. package/src/components/inlineText.js +38 -15
  41. package/src/components/poll.css +3 -0
  42. package/src/core/editDeck.js +4 -5
  43. package/src/core/pollList.js +66 -0
  44. package/src/core/tags.js +195 -0
  45. package/src/extensions/discover.js +2 -2
  46. package/src/extensions/moved.js +4 -4
  47. package/src/layouts/layoutApi.jsx +20 -10
  48. package/src/live/roomTag.js +11 -19
  49. package/src/runtime/main.jsx +2 -1
  50. package/src/runtime/markedSetup.js +3 -0
  51. package/assets/extensions/palettes/neon/extension.toml +0 -30
  52. package/assets/extensions/themes/aurora/extension.toml +0 -40
  53. package/assets/extensions/themes/aurora/styles.css +0 -670
  54. package/docs/site/images/themes/aurora-dark.webp +0 -0
  55. package/docs/site/images/themes/aurora-light.webp +0 -0
  56. package/docs/site/images/themes/aurora.webp +0 -0
@@ -0,0 +1,754 @@
1
+ /* Glass — liquid glass.
2
+ Soft pools of light in the palette's accents lie behind every slide, so
3
+ the slide itself reads as a sheet of glass, and content stands on it
4
+ without frames. Only a title gets a raised pane of frosted glass: it
5
+ blurs and brightens what lies behind it, catches light along its upper
6
+ edge and has a bright rim that fades round its sides. Labels are glass
7
+ capsules, list markers glass beads, a chapter number sits in a round glass
8
+ lens. Quiet by design: the light is a tint, not a picture.
9
+ Dark by default; in light the glass is milky. All colours are the
10
+ palette's: light-dark() picks the bright side of the palette (--bg in
11
+ light, --ink in dark) for highlights. */
12
+
13
+ /* The light drifts while presenting (title, chapter and statement slides). */
14
+ @property --dx { syntax: '<length>'; inherits: true; initial-value: 0px; }
15
+ @property --dy { syntax: '<length>'; inherits: true; initial-value: 0px; }
16
+
17
+ .slide {
18
+ /* The bright and the dark side of the palette, whichever appearance. */
19
+ --hi: light-dark(var(--bg), var(--ink));
20
+ --lo: light-dark(var(--ink), var(--bg));
21
+ --canvas: light-dark(color-mix(in oklab, var(--surface) 75%, var(--bg)), var(--bg));
22
+ /* A hairline that shows on glass in both appearances. */
23
+ --edge: light-dark(color-mix(in oklab, var(--ink) 13%, transparent), color-mix(in oklab, var(--ink) 22%, transparent));
24
+ --hairline: color-mix(in oklab, var(--ink) 16%, transparent);
25
+
26
+ /* Pools of light: the accents, barely there, mixed into the background. */
27
+ --wash-a: light-dark(color-mix(in oklab, var(--accent) 26%, var(--bg)), color-mix(in oklab, var(--accent) 30%, var(--bg)));
28
+ --wash-b: light-dark(color-mix(in oklab, var(--accent-2) 22%, var(--bg)), color-mix(in oklab, var(--accent-2) 24%, var(--bg)));
29
+ --wash-c: light-dark(color-mix(in oklab, var(--bg) 70%, transparent), color-mix(in oklab, var(--ink) 9%, transparent));
30
+
31
+ /* The glass itself. */
32
+ --glass-fill: light-dark(color-mix(in oklab, var(--bg) 54%, transparent), color-mix(in oklab, var(--bg) 42%, transparent));
33
+ --glass-sheen: linear-gradient(170deg, color-mix(in oklab, var(--hi) 14%, transparent) 0%, transparent 34%, transparent 72%, color-mix(in oklab, var(--hi) 5%, transparent) 100%);
34
+ --glass-filter: blur(var(--glass-blur)) saturate(170%);
35
+ --glass-rim:
36
+ inset 0 1.5px 0 0 color-mix(in oklab, var(--hi) 55%, transparent),
37
+ inset 0 0 0 1px var(--edge),
38
+ inset 0 -1px 0 0 color-mix(in oklab, var(--lo) 14%, transparent),
39
+ inset 0 0 36px 0 color-mix(in oklab, var(--hi) 6%, transparent);
40
+ --glass-drop: 0 40px 80px -40px color-mix(in oklab, var(--lo) 50%, transparent);
41
+ /* A picture in a glass bezel: a see-through ring and a hairline round it. */
42
+ --bezel: 0 0 0 10px color-mix(in oklab, var(--hi) 10%, transparent), 0 0 0 11px var(--edge), var(--glass-drop);
43
+
44
+ --em: light-dark(var(--accent), color-mix(in oklab, var(--accent) 72%, var(--ink)));
45
+ --shine: linear-gradient(100deg, var(--accent) 10%, color-mix(in oklab, var(--accent) 50%, var(--accent-2)) 55%, var(--accent-2) 95%);
46
+
47
+ /* Where the light falls (per layout and slide below). */
48
+ --a-x: 90%; --a-y: 20%; --a-r: 300px;
49
+ --b-x: 5%; --b-y: 80%; --b-r: 260px;
50
+ --c-x: 45%; --c-y: 0%; --c-r: 220px;
51
+
52
+ /* Large, soft pools of light with no edge: something quiet for the glass
53
+ to tint. Radial gradients only (no blur filter): they stay vector in a
54
+ PDF and are cheap to draw. */
55
+ background:
56
+ radial-gradient(circle max(var(--a-r) * 2.8, 720px) at calc(var(--a-x) + var(--dx)) calc(var(--a-y) + var(--dy)), var(--wash-a) 0%, color-mix(in oklab, var(--wash-a) 55%, transparent) 40%, transparent 100%),
57
+ radial-gradient(circle max(var(--b-r) * 2.8, 640px) at calc(var(--b-x) - var(--dx)) calc(var(--b-y) - var(--dy)), var(--wash-b) 0%, color-mix(in oklab, var(--wash-b) 55%, transparent) 40%, transparent 100%),
58
+ radial-gradient(circle max(var(--c-r) * 2.6, 520px) at calc(var(--c-x) + var(--dy)) calc(var(--c-y) + var(--dx)), var(--wash-c) 0%, transparent 100%),
59
+ var(--canvas);
60
+ }
61
+
62
+ /* Every other slide and every third one moves the light a little, so a
63
+ talk moves through one lit space. */
64
+ /* :where keeps these as weak as a layout's own placement below. */
65
+ .slide:where(:nth-of-type(even)) {
66
+ --a-x: 8%; --a-y: 30%; --a-r: 280px;
67
+ --b-x: 94%; --b-y: 72%; --b-r: 200px;
68
+ --c-x: 40%; --c-y: 4%; --c-r: 120px;
69
+ }
70
+ .slide:where(:nth-of-type(3n)) {
71
+ --a-x: 96%; --a-y: 84%; --a-r: 260px;
72
+ --b-x: 12%; --b-y: 16%; --b-r: 210px;
73
+ --c-x: 78%; --c-y: 6%; --c-r: 100px;
74
+ }
75
+
76
+ /* ─────────────────────────────────────────────
77
+ THE GLASS — the title pane, capsules, a lens
78
+ ───────────────────────────────────────────── */
79
+ .slide--title .title-text,
80
+ .slide-header > span:not(:empty),
81
+ .slide-footer > span:not(:empty),
82
+ .focus-eyebrow,
83
+ .chapter-num {
84
+ position: relative;
85
+ background: var(--glass-sheen), var(--glass-fill);
86
+ -webkit-backdrop-filter: var(--glass-filter);
87
+ backdrop-filter: var(--glass-filter);
88
+ box-shadow: var(--glass-rim), var(--glass-drop);
89
+ }
90
+
91
+ /* The panes: a rim of light, bright at the upper left and lower right,
92
+ fading along the sides, as light runs round the edge of thick glass. */
93
+ .slide--title .title-text,
94
+ .chapter-num {
95
+ border-radius: var(--glass-radius);
96
+ }
97
+ .slide--title .title-text::before,
98
+ .chapter-num::before {
99
+ content: '';
100
+ position: absolute;
101
+ inset: 0;
102
+ border-radius: inherit;
103
+ padding: 1.5px;
104
+ background: linear-gradient(135deg,
105
+ color-mix(in oklab, var(--hi) 90%, transparent) 0%,
106
+ color-mix(in oklab, var(--hi) 12%, transparent) 28%,
107
+ transparent 50%,
108
+ color-mix(in oklab, var(--hi) 10%, transparent) 72%,
109
+ color-mix(in oklab, var(--hi) 55%, transparent) 100%);
110
+ -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
111
+ -webkit-mask-composite: xor;
112
+ mask-composite: exclude;
113
+ pointer-events: none;
114
+ }
115
+
116
+ /* ─────────────────────────────────────────────
117
+ HEADER / FOOTER — glass capsules
118
+ ───────────────────────────────────────────── */
119
+ .slide-header, .slide-footer {
120
+ position: relative;
121
+ z-index: 1;
122
+ font-family: var(--font-body);
123
+ font-size: var(--fs-eyebrow);
124
+ font-weight: 500;
125
+ letter-spacing: 0.02em;
126
+ color: var(--ink-soft);
127
+ min-height: 44px;
128
+ }
129
+ .slide-header { margin-bottom: 20px; }
130
+ .slide-footer { margin-top: 20px; font-variant-numeric: tabular-nums; }
131
+ .slide-header > span:not(:empty),
132
+ .slide-footer > span:not(:empty) {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ gap: 12px;
136
+ padding: 10px 24px;
137
+ border-radius: 999px;
138
+ line-height: 1.2;
139
+ }
140
+ .slide-header .brand { color: var(--ink); font-weight: 600; }
141
+ /* The section capsule carries a droplet of the accent. */
142
+ .slide-header > span:last-child:not(:empty):not(.brand)::before {
143
+ content: '';
144
+ width: 10px;
145
+ height: 10px;
146
+ border-radius: 50%;
147
+ background: var(--accent);
148
+ box-shadow: 0 0 10px color-mix(in oklab, var(--accent) 70%, transparent);
149
+ }
150
+ .slide-footer > span:last-child:not(:first-child):not(:empty) { font-weight: 650; color: var(--ink); min-width: 1.6em; justify-content: center; }
151
+
152
+ .slide-logo {
153
+ position: absolute;
154
+ top: var(--pad-y);
155
+ right: var(--pad-x);
156
+ height: 80px;
157
+ width: auto;
158
+ max-width: 320px;
159
+ object-fit: contain;
160
+ filter: var(--logo-filter, none);
161
+ }
162
+
163
+ /* ─────────────────────────────────────────────
164
+ TYPOGRAPHY
165
+ ───────────────────────────────────────────── */
166
+ .eyebrow {
167
+ font-family: var(--font-body);
168
+ font-size: var(--fs-eyebrow);
169
+ font-weight: 600;
170
+ letter-spacing: 0.14em;
171
+ text-transform: uppercase;
172
+ color: var(--muted);
173
+ margin: 0;
174
+ }
175
+ .display {
176
+ font-family: var(--font-display);
177
+ font-size: var(--fs-display);
178
+ font-weight: 700;
179
+ line-height: 1.0;
180
+ letter-spacing: -0.045em;
181
+ color: var(--ink);
182
+ margin: 0;
183
+ text-wrap: balance;
184
+ }
185
+ .title {
186
+ font-family: var(--font-display);
187
+ font-size: var(--fs-h);
188
+ font-weight: 700;
189
+ line-height: 1.05;
190
+ letter-spacing: -0.035em;
191
+ color: var(--ink);
192
+ margin: 0;
193
+ text-wrap: balance;
194
+ }
195
+ .subtitle {
196
+ font-family: var(--font-body);
197
+ font-size: var(--fs-sub);
198
+ font-weight: 400;
199
+ line-height: 1.3;
200
+ letter-spacing: -0.01em;
201
+ color: var(--ink-soft);
202
+ margin: 0;
203
+ text-wrap: pretty;
204
+ }
205
+ .body-text {
206
+ font-family: var(--font-body);
207
+ font-size: var(--fs-body);
208
+ line-height: 1.5;
209
+ color: var(--ink-soft);
210
+ margin: 0;
211
+ text-wrap: pretty;
212
+ }
213
+ .meta { font-family: var(--font-body); font-size: var(--fs-small); color: var(--muted); }
214
+
215
+ em { font-style: normal; font-weight: 600; color: var(--em); }
216
+ /* In headings, emphasis shines in both accents. */
217
+ :is(.display, .title, .chapter-title, .focus-content, .slide-body h1) em {
218
+ font-weight: inherit;
219
+ background: var(--shine);
220
+ -webkit-background-clip: text;
221
+ background-clip: text;
222
+ -webkit-text-fill-color: transparent;
223
+ color: var(--accent);
224
+ padding-right: 0.04em;
225
+ }
226
+ strong { font-weight: 650; color: var(--ink); }
227
+
228
+ /* ─────────────────────────────────────────────
229
+ CONTENT SLIDE — straight on the slide, which is the glass
230
+ ───────────────────────────────────────────── */
231
+ .slide-body h1 {
232
+ font-family: var(--font-display);
233
+ font-size: var(--fs-h);
234
+ font-weight: 700;
235
+ line-height: 1.05;
236
+ letter-spacing: -0.035em;
237
+ color: var(--ink);
238
+ margin: 0 0 var(--gap-title) 0;
239
+ max-width: 1500px;
240
+ text-wrap: balance;
241
+ }
242
+ .slide-body h2 {
243
+ font-family: var(--font-display);
244
+ font-size: var(--fs-sub);
245
+ font-weight: 650;
246
+ line-height: 1.15;
247
+ letter-spacing: -0.02em;
248
+ color: var(--ink);
249
+ margin: 0 0 var(--gap-item) 0;
250
+ }
251
+ .slide-body p {
252
+ font-family: var(--font-body);
253
+ font-size: var(--fs-body);
254
+ line-height: 1.5;
255
+ color: var(--ink-soft);
256
+ margin: 0 0 var(--gap-item) 0;
257
+ text-wrap: pretty;
258
+ }
259
+ .slide-body :not(pre) > code {
260
+ font-family: var(--font-mono);
261
+ font-size: 0.86em;
262
+ padding: 0.08em 0.4em;
263
+ border-radius: 0.5em;
264
+ background: color-mix(in oklab, var(--hi) 10%, transparent);
265
+ box-shadow: inset 0 0 0 1px var(--edge);
266
+ color: var(--ink);
267
+ }
268
+
269
+ /* ─────────────────────────────────────────────
270
+ LISTS — glass beads: a clear bead tinted with the accent, a catch of
271
+ light at the top, light gathering at the bottom, a fine rim
272
+ ───────────────────────────────────────────── */
273
+ .slide-body li::before {
274
+ --tint: var(--accent);
275
+ border-radius: 50%;
276
+ background:
277
+ radial-gradient(circle at 50% 16%, color-mix(in oklab, var(--hi) 60%, transparent) 0, transparent 42%),
278
+ radial-gradient(circle at 50% 115%, color-mix(in oklab, var(--tint) 50%, transparent), transparent 68%),
279
+ color-mix(in oklab, var(--tint) 14%, transparent);
280
+ -webkit-backdrop-filter: blur(6px) saturate(160%);
281
+ backdrop-filter: blur(6px) saturate(160%);
282
+ box-shadow:
283
+ inset 0 1px 0 0 color-mix(in oklab, var(--hi) 70%, transparent),
284
+ inset 0 0 0 1px color-mix(in oklab, var(--tint) 42%, transparent),
285
+ 0 3px 8px -3px color-mix(in oklab, var(--lo) 45%, transparent);
286
+ }
287
+ .slide-body ul > li { line-height: 1.38; padding-left: 48px; }
288
+ .slide-body ul > li::before {
289
+ content: '';
290
+ position: absolute;
291
+ left: 0;
292
+ top: calc(0.69em - 11px);
293
+ width: 22px;
294
+ height: 22px;
295
+ }
296
+ /* A point inside a point: a smaller bead in the second accent. */
297
+ .slide-body li ul > li { padding-left: 38px; }
298
+ .slide-body li ul > li::before {
299
+ --tint: var(--accent-2);
300
+ width: 14px;
301
+ height: 14px;
302
+ top: calc(0.69em - 7px);
303
+ }
304
+ .slide-body ol > li { line-height: 1.38; padding-left: 66px; }
305
+ .slide-body ol > li::before {
306
+ content: counter(slide-ol);
307
+ position: absolute;
308
+ left: 0;
309
+ top: calc(0.69em - 20px);
310
+ width: 44px;
311
+ height: 44px;
312
+ display: grid;
313
+ place-items: center;
314
+ font-family: var(--font-display);
315
+ font-size: 22px;
316
+ font-weight: 700;
317
+ font-variant-numeric: tabular-nums;
318
+ color: var(--em);
319
+ /* The catch of light flattened to the top edge, clear of the number. */
320
+ background:
321
+ radial-gradient(64% 26% at 50% 4%, color-mix(in oklab, var(--hi) 55%, transparent), transparent 100%),
322
+ radial-gradient(circle at 50% 115%, color-mix(in oklab, var(--tint) 42%, transparent), transparent 66%),
323
+ color-mix(in oklab, var(--tint) 14%, transparent);
324
+ }
325
+
326
+ /* ─────────────────────────────────────────────
327
+ LAYOUT: TITLE — a lens in front of the light
328
+ ───────────────────────────────────────────── */
329
+ .slide--title { --a-x: 24%; --a-y: 30%; --a-r: 270px; --b-x: 80%; --b-y: 76%; --b-r: 210px; --c-x: 88%; --c-y: 16%; --c-r: 90px; }
330
+ .slide--title .slide-body {
331
+ justify-content: center;
332
+ align-items: center;
333
+ text-align: center;
334
+ }
335
+ .slide--title .title-text {
336
+ display: flex;
337
+ flex-direction: column;
338
+ align-items: center;
339
+ max-width: 1560px;
340
+ padding: 72px 104px 80px;
341
+ border-radius: calc(var(--glass-radius) * 1.4);
342
+ }
343
+ /* The title is an h1: as large as .display, not a content heading. */
344
+ .slide--title .display { font-size: var(--fs-display); margin: 0; max-width: 1400px; }
345
+ .slide--title .subtitle { margin-top: 32px; max-width: 1100px; }
346
+
347
+ /* With a picture: the picture in a bezel at the right, the pane at the left. */
348
+ .slide--title.has-image { --a-x: 50%; --a-y: 20%; --a-r: 220px; --b-x: 4%; --b-y: 90%; --b-r: 170px; }
349
+ .slide--title.has-image .slide-body {
350
+ display: grid;
351
+ grid-template-columns: 1.05fr 1fr;
352
+ column-gap: 72px;
353
+ align-items: center;
354
+ text-align: left;
355
+ padding: 13px;
356
+ }
357
+ .slide--title.has-image .title-text {
358
+ align-items: flex-start;
359
+ padding: 56px 64px 64px;
360
+ border-radius: var(--glass-radius);
361
+ min-width: 0;
362
+ }
363
+ .slide--title.has-image .display { font-size: calc(var(--fs-display) * 0.6); }
364
+ .slide--title.has-image .subtitle { margin-top: 24px; }
365
+ .slide--title.has-image .title-image {
366
+ align-self: stretch;
367
+ width: 100%;
368
+ height: 100%;
369
+ min-height: 0;
370
+ object-fit: cover;
371
+ border-radius: var(--glass-radius);
372
+ box-shadow: var(--bezel);
373
+ }
374
+
375
+ /* ─────────────────────────────────────────────
376
+ LAYOUT: CHAPTER — the number in a glass lens, a glow behind it
377
+ ───────────────────────────────────────────── */
378
+ .slide--chapter { --a-x: 94%; --a-y: 10%; --a-r: 230px; --b-x: 72%; --b-y: 104%; --b-r: 220px; --c-x: 4%; --c-y: 92%; --c-r: 80px; }
379
+ .slide--chapter .slide-body { justify-content: center; }
380
+ .slide--chapter .chapter-content {
381
+ --disc: 340px;
382
+ position: relative;
383
+ isolation: isolate;
384
+ }
385
+ .slide--chapter .chapter-content:has(> .chapter-num) {
386
+ display: grid;
387
+ grid-template-columns: var(--disc) minmax(0, 1fr);
388
+ column-gap: 88px;
389
+ align-items: center;
390
+ align-content: center;
391
+ }
392
+ .slide--chapter .chapter-content:has(> .chapter-num) > :not(.chapter-num) { grid-column: 2; }
393
+ /* A glow behind the lens, up and to the right of it. */
394
+ .slide--chapter .chapter-content:has(> .chapter-num)::before {
395
+ content: '';
396
+ position: absolute;
397
+ z-index: -1;
398
+ left: calc(var(--disc) * 0.3);
399
+ top: calc(50% - var(--disc) * 0.95);
400
+ width: calc(var(--disc) * 1.3);
401
+ aspect-ratio: 1;
402
+ border-radius: 50%;
403
+ background: radial-gradient(circle closest-side, color-mix(in oklab, var(--accent-2) 34%, transparent), color-mix(in oklab, var(--accent-2) 12%, transparent) 55%, transparent 100%);
404
+ }
405
+ .chapter-num {
406
+ grid-column: 1;
407
+ grid-row: 1 / span 9;
408
+ align-self: center;
409
+ width: var(--disc);
410
+ height: var(--disc);
411
+ border-radius: 50%;
412
+ display: grid;
413
+ place-items: center;
414
+ font-family: var(--font-display);
415
+ font-size: calc(var(--disc) * 0.46);
416
+ font-weight: 700;
417
+ letter-spacing: -0.05em;
418
+ line-height: 1;
419
+ font-variant-numeric: tabular-nums;
420
+ color: var(--ink);
421
+ }
422
+ .chapter-meta {
423
+ font-family: var(--font-body);
424
+ font-size: var(--fs-eyebrow);
425
+ font-weight: 600;
426
+ letter-spacing: 0.16em;
427
+ text-transform: uppercase;
428
+ color: var(--muted);
429
+ margin: 0 0 20px 0;
430
+ }
431
+ .slide--chapter .chapter-title {
432
+ font-family: var(--font-display);
433
+ font-size: var(--fs-title);
434
+ font-weight: 700;
435
+ line-height: 1.0;
436
+ letter-spacing: -0.045em;
437
+ color: var(--ink);
438
+ margin: 0 0 32px 0;
439
+ max-width: 1200px;
440
+ text-wrap: balance;
441
+ }
442
+ .slide--chapter .chapter-desc {
443
+ font-family: var(--font-body);
444
+ font-size: var(--fs-sub);
445
+ line-height: 1.35;
446
+ color: var(--ink-soft);
447
+ max-width: 1000px;
448
+ margin: 0;
449
+ }
450
+ /* With a picture: the lens above the title, the picture in a bezel at the right. */
451
+ .slide--chapter.has-image .slide-body {
452
+ display: grid;
453
+ grid-template-columns: 1fr 1fr;
454
+ column-gap: 72px;
455
+ align-items: stretch;
456
+ padding: 13px;
457
+ }
458
+ .slide--chapter.has-image .chapter-content { --disc: 210px; align-self: center; }
459
+ .slide--chapter.has-image .chapter-content:has(> .chapter-num) { display: flex; flex-direction: column; align-items: flex-start; }
460
+ .slide--chapter.has-image .chapter-content:has(> .chapter-num)::before { top: calc(var(--disc) * -0.45); left: calc(var(--disc) * 0.3); }
461
+ .slide--chapter.has-image .chapter-num { align-self: flex-start; margin-bottom: 44px; }
462
+ .slide--chapter.has-image .chapter-title { font-size: calc(var(--fs-title) * 0.78); }
463
+ .slide--chapter.has-image .chapter-image {
464
+ width: 100%;
465
+ height: 100%;
466
+ min-height: 0;
467
+ object-fit: cover;
468
+ border-radius: var(--glass-radius);
469
+ box-shadow: var(--bezel);
470
+ }
471
+
472
+ /* ─────────────────────────────────────────────
473
+ LAYOUT: FOCUS — the statement in the open, the light round it
474
+ ───────────────────────────────────────────── */
475
+ .slide--focus { --a-x: 8%; --a-y: 14%; --a-r: 230px; --b-x: 93%; --b-y: 88%; --b-r: 250px; --c-x: 86%; --c-y: 12%; --c-r: 80px; }
476
+ .slide--focus .slide-body {
477
+ justify-content: center;
478
+ align-items: center;
479
+ text-align: center;
480
+ }
481
+ .focus-eyebrow {
482
+ display: inline-flex;
483
+ align-items: center;
484
+ gap: 12px;
485
+ padding: 11px 28px 11px 22px;
486
+ border-radius: 999px;
487
+ font-family: var(--font-body);
488
+ font-size: var(--fs-eyebrow);
489
+ font-weight: 600;
490
+ letter-spacing: 0.14em;
491
+ text-transform: uppercase;
492
+ color: var(--ink-soft);
493
+ margin: 0 0 52px 0;
494
+ }
495
+ .focus-eyebrow::before {
496
+ content: '';
497
+ width: 10px;
498
+ height: 10px;
499
+ border-radius: 50%;
500
+ background: var(--accent-2);
501
+ box-shadow: 0 0 10px color-mix(in oklab, var(--accent-2) 70%, transparent);
502
+ }
503
+ .focus-content { display: flex; flex-direction: column; align-items: center; width: 100%; }
504
+ .focus-statement,
505
+ .slide--focus .focus-content h1,
506
+ .slide--focus .focus-content p {
507
+ font-family: var(--font-display);
508
+ font-size: var(--fs-focus);
509
+ font-weight: 650;
510
+ line-height: 1.08;
511
+ letter-spacing: -0.035em;
512
+ color: var(--ink);
513
+ max-width: 1500px;
514
+ margin: 0;
515
+ text-wrap: balance;
516
+ text-align: center;
517
+ }
518
+ .focus-attribution {
519
+ font-family: var(--font-body);
520
+ font-size: var(--fs-small);
521
+ font-weight: 500;
522
+ letter-spacing: 0.1em;
523
+ text-transform: uppercase;
524
+ color: var(--muted);
525
+ margin: 52px 0 0 0;
526
+ }
527
+
528
+ /* The light drifts slowly while presenting; never in print or for people
529
+ who prefer less motion. */
530
+ @media (prefers-reduced-motion: no-preference) {
531
+ .slide:is(.slide--title, .slide--chapter, .slide--focus) { animation: glass-drift 22s ease-in-out infinite alternate; }
532
+ }
533
+ @keyframes glass-drift {
534
+ from { --dx: -24px; --dy: 10px; }
535
+ to { --dx: 28px; --dy: -14px; }
536
+ }
537
+ deck-stage[data-deck-static] .slide { animation: none; }
538
+
539
+ /* ─────────────────────────────────────────────
540
+ LAYOUT: IMAGE + TEXT — a picture in a bezel, the words beside it
541
+ ───────────────────────────────────────────── */
542
+ .slide--image-text .slide-body { gap: 88px; padding: 13px; }
543
+ .image-pane {
544
+ flex: 1.1;
545
+ min-width: 0;
546
+ display: flex;
547
+ align-items: center;
548
+ justify-content: center;
549
+ overflow: hidden;
550
+ position: relative;
551
+ border-radius: var(--glass-radius);
552
+ background: var(--surface);
553
+ box-shadow: var(--bezel);
554
+ }
555
+ .image-placeholder {
556
+ width: 100%;
557
+ height: 100%;
558
+ background: repeating-linear-gradient(135deg, var(--surface) 0 22px, var(--bg) 22px 44px);
559
+ }
560
+ .image-placeholder span {
561
+ font-family: var(--font-mono);
562
+ font-size: 22px;
563
+ color: var(--muted);
564
+ letter-spacing: 0.08em;
565
+ text-transform: uppercase;
566
+ background: var(--bg);
567
+ padding: 14px 22px;
568
+ border-radius: 999px;
569
+ }
570
+ .text-pane .title { font-size: var(--fs-h); }
571
+ .text-pane .body-text + .body-text { margin-top: 8px; }
572
+
573
+ /* ─────────────────────────────────────────────
574
+ LAYOUT: SPLIT — two columns, no frames
575
+ ───────────────────────────────────────────── */
576
+ /* The heading stands in the open, the light away from it. */
577
+ .slide--split { --a-x: 94%; --a-y: 34%; --a-r: 280px; --b-x: 6%; --b-y: 94%; --b-r: 190px; --c-x: 62%; --c-y: 100%; --c-r: 110px; }
578
+ .split-columns { gap: 88px; }
579
+ .slide--split .split-heading { margin-bottom: 32px; }
580
+
581
+ /* ─────────────────────────────────────────────
582
+ LAYOUT: FULL-BLEED IMAGE — the title on smoked glass over the picture
583
+ ───────────────────────────────────────────── */
584
+ .slide--full-bleed-image .slide-body { align-items: flex-start; }
585
+ .slide--full-bleed-image.has-overlay .slide-bg::after {
586
+ content: '';
587
+ position: absolute;
588
+ inset: 0;
589
+ background: linear-gradient(to top, color-mix(in oklab, var(--lo) 45%, transparent), transparent 55%);
590
+ }
591
+ .slide--full-bleed-image .overlay-title {
592
+ font-family: var(--font-display);
593
+ font-size: var(--fs-h);
594
+ font-weight: 700;
595
+ line-height: 1.05;
596
+ letter-spacing: -0.035em;
597
+ color: var(--hi);
598
+ margin: 0;
599
+ max-width: 1300px;
600
+ text-wrap: balance;
601
+ padding: 36px 52px 40px;
602
+ border-radius: var(--glass-radius);
603
+ background: var(--glass-sheen), color-mix(in oklab, var(--lo) 36%, transparent);
604
+ -webkit-backdrop-filter: var(--glass-filter);
605
+ backdrop-filter: var(--glass-filter);
606
+ box-shadow: inset 0 1.5px 0 0 color-mix(in oklab, var(--hi) 45%, transparent), inset 0 0 0 1px color-mix(in oklab, var(--hi) 20%, transparent), var(--glass-drop);
607
+ }
608
+ .slide--full-bleed-image .overlay-title em { color: inherit; -webkit-text-fill-color: currentColor; background: none; }
609
+
610
+ /* ─────────────────────────────────────────────
611
+ CALLOUTS — tinted glass
612
+ ───────────────────────────────────────────── */
613
+ .slide-body .callout {
614
+ --tint: var(--accent);
615
+ border: 0;
616
+ border-radius: 26px;
617
+ padding: 22px 32px 24px;
618
+ margin: 18px 0 0;
619
+ max-width: 1400px;
620
+ background: radial-gradient(120% 140% at 0% 0%, color-mix(in oklab, var(--tint) 18%, transparent), transparent 70%), color-mix(in oklab, var(--hi) 6%, transparent);
621
+ box-shadow: inset 0 1px 0 0 color-mix(in oklab, var(--hi) 40%, transparent), inset 0 0 0 1px color-mix(in oklab, var(--tint) 30%, transparent);
622
+ }
623
+ .slide-body .callout-title {
624
+ display: flex;
625
+ align-items: center;
626
+ gap: 12px;
627
+ font-family: var(--font-body);
628
+ font-size: var(--fs-eyebrow);
629
+ font-weight: 650;
630
+ letter-spacing: 0.12em;
631
+ text-transform: uppercase;
632
+ margin: 0 0 8px 0;
633
+ }
634
+ .slide-body .callout-title::before {
635
+ content: '';
636
+ width: 10px;
637
+ height: 10px;
638
+ border-radius: 50%;
639
+ background: currentColor;
640
+ box-shadow: 0 0 10px currentColor;
641
+ }
642
+ .slide-body .callout p { padding-left: 0; margin: 0; color: var(--ink); }
643
+ .slide-body .callout-note { --tint: var(--callout-note); }
644
+ .slide-body .callout-tip { --tint: var(--callout-tip); }
645
+ .slide-body .callout-important { --tint: var(--callout-important); }
646
+ .slide-body .callout-warning { --tint: var(--callout-warning); }
647
+ .slide-body .callout-caution { --tint: var(--callout-caution); }
648
+ .slide-body .callout-definition { --tint: var(--accent-2); }
649
+ .slide-body .callout-tip .callout-title { color: color-mix(in oklab, var(--callout-tip) 60%, var(--ink)); }
650
+ .slide-body :is(.callout-theorem, .callout-lemma, .callout-corollary) .callout-title { color: var(--em); }
651
+ .slide-body .callout-definition .callout-title { color: light-dark(color-mix(in oklab, var(--accent-2) 80%, var(--ink)), var(--accent-2)); }
652
+
653
+ /* ─────────────────────────────────────────────
654
+ CODE — smoked glass
655
+ ───────────────────────────────────────────── */
656
+ .code-block {
657
+ --code-bg: light-dark(color-mix(in oklab, var(--surface) 82%, transparent), color-mix(in oklab, var(--bg) 74%, transparent));
658
+ --code-radius: 26px;
659
+ --code-size: 26px;
660
+ background: var(--code-bg);
661
+ border-radius: var(--code-radius);
662
+ padding: 32px 40px;
663
+ margin: 0;
664
+ overflow: hidden;
665
+ font-family: var(--font-mono);
666
+ font-size: var(--code-size);
667
+ line-height: 1.6;
668
+ box-shadow: inset 0 1px 0 0 color-mix(in oklab, var(--hi) 22%, transparent), inset 0 0 0 1px var(--edge);
669
+ }
670
+ .code-block code { font-family: inherit; font-size: inherit; background: none; padding: 0; box-shadow: none; }
671
+ .slide-body .code-block-wrapper { margin: 28px 0; }
672
+
673
+ /* ─────────────────────────────────────────────
674
+ TABLES, QUOTES, FOOTNOTES, MATH
675
+ ───────────────────────────────────────────── */
676
+ .slide-body table { font-variant-numeric: tabular-nums; }
677
+ .slide-body th {
678
+ font-weight: 600;
679
+ color: var(--ink);
680
+ border-bottom: 1.5px solid color-mix(in oklab, var(--ink) 40%, transparent);
681
+ background: color-mix(in oklab, var(--hi) 7%, transparent);
682
+ }
683
+ .slide-body th:first-child { border-top-left-radius: 16px; }
684
+ .slide-body th:last-child { border-top-right-radius: 16px; }
685
+ .slide-body td { border-bottom: 1px solid var(--hairline); }
686
+ .slide-body tr:last-child td { border-bottom: 0; }
687
+
688
+ /* A quote hangs from a rod of light in both accents. */
689
+ .slide-body blockquote {
690
+ position: relative;
691
+ border: 0;
692
+ padding: 4px 0 4px 40px;
693
+ margin: 0 0 var(--gap-item);
694
+ color: var(--ink);
695
+ }
696
+ .slide-body blockquote::before {
697
+ content: '';
698
+ position: absolute;
699
+ left: 0;
700
+ top: 0;
701
+ bottom: 0;
702
+ width: 6px;
703
+ border-radius: 999px;
704
+ background: linear-gradient(to bottom, var(--accent), var(--accent-2));
705
+ box-shadow: 0 0 14px color-mix(in oklab, var(--accent) 40%, transparent);
706
+ }
707
+
708
+ .slide-footnotes, .slide-citations {
709
+ position: relative;
710
+ z-index: 1;
711
+ font-family: var(--font-body);
712
+ border: 0;
713
+ border-top: 1px solid var(--hairline);
714
+ padding: 14px 0 0;
715
+ margin-top: 18px;
716
+ font-size: var(--fs-small);
717
+ color: var(--ink-soft);
718
+ }
719
+
720
+ .slide .katex-display { font-size: var(--fs-sub); margin: 36px 0; overflow-x: auto; overflow-y: hidden; }
721
+
722
+ /* ─────────────────────────────────────────────
723
+ AUDIENCE QUESTIONS — glass tracks, bars of light
724
+ ───────────────────────────────────────────── */
725
+ .slide .poll-track, .slide .scale-track { border-radius: 999px; background: color-mix(in oklab, var(--hi) 8%, transparent); box-shadow: inset 0 0 0 1px var(--edge); }
726
+ .slide .poll-fill { border-radius: 999px; background: var(--shine); box-shadow: 0 0 18px color-mix(in oklab, var(--accent) 40%, transparent); }
727
+ .slide .scale-fill { border-radius: 14px 14px 0 0; background: linear-gradient(to top, var(--accent), var(--accent-2)); }
728
+ .slide .question-cards li { border-radius: 22px; border-left: 0; background: var(--glass-sheen), var(--glass-fill); box-shadow: var(--glass-rim); }
729
+ .slide .poll-join { border-radius: 28px; }
730
+
731
+ /* ─────────────────────────────────────────────
732
+ PRINT AND PDF — glass that prints
733
+ A blur prints as a huge picture, so does a mask, and see-through
734
+ gradients do too: the panes become plain tinted glass, and only the title,
735
+ chapter and statement slides keep their light.
736
+ ───────────────────────────────────────────── */
737
+ @media print {
738
+ .slide { animation: none !important; --dx: 0px; --dy: 0px; }
739
+ .slide *, .slide *::before { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
740
+ .slide :is(.title-text, .chapter-num)::before { -webkit-mask: none !important; mask: none !important; display: none; }
741
+ .slide--chapter .chapter-content::before { display: block !important; }
742
+ .slide:not(.slide--title, .slide--chapter, .slide--focus) { background: var(--canvas); }
743
+ .slide {
744
+ --glass-fill: light-dark(color-mix(in oklab, var(--bg) 82%, var(--surface)), color-mix(in oklab, var(--surface) 70%, var(--bg)));
745
+ --glass-sheen: linear-gradient(transparent, transparent);
746
+ --glass-drop: 0 0 0 0 transparent;
747
+ }
748
+ :is(.display, .title, .chapter-title, .focus-content, .slide-body h1) em {
749
+ background: none !important;
750
+ -webkit-text-fill-color: currentColor !important;
751
+ color: var(--em) !important;
752
+ }
753
+ .slide-header > span::before, .focus-eyebrow::before, .slide-body .callout-title::before, .slide-body blockquote::before, .slide .poll-fill { box-shadow: none !important; }
754
+ }