mdeck 2.3.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 (268) hide show
  1. package/CHANGELOG.md +259 -0
  2. package/LICENSE +21 -0
  3. package/README.md +156 -0
  4. package/assets/base.css +196 -0
  5. package/assets/extensions/layouts/chapter/extension.toml +26 -0
  6. package/assets/extensions/layouts/chapter/layout.jsx +21 -0
  7. package/assets/extensions/layouts/chapter/starter.md +8 -0
  8. package/assets/extensions/layouts/focus/extension.toml +8 -0
  9. package/assets/extensions/layouts/focus/layout.jsx +10 -0
  10. package/assets/extensions/layouts/focus/starter.md +4 -0
  11. package/assets/extensions/layouts/full-bleed-image/extension.toml +31 -0
  12. package/assets/extensions/layouts/full-bleed-image/layout.jsx +19 -0
  13. package/assets/extensions/layouts/full-bleed-image/starter.md +6 -0
  14. package/assets/extensions/layouts/generic/extension.toml +8 -0
  15. package/assets/extensions/layouts/generic/layout.jsx +8 -0
  16. package/assets/extensions/layouts/generic/starter.md +4 -0
  17. package/assets/extensions/layouts/image-text/extension.toml +25 -0
  18. package/assets/extensions/layouts/image-text/layout.jsx +17 -0
  19. package/assets/extensions/layouts/image-text/starter.md +6 -0
  20. package/assets/extensions/layouts/split/extension.toml +25 -0
  21. package/assets/extensions/layouts/split/layout.jsx +19 -0
  22. package/assets/extensions/layouts/split/starter.md +14 -0
  23. package/assets/extensions/layouts/title/extension.toml +26 -0
  24. package/assets/extensions/layouts/title/layout.jsx +14 -0
  25. package/assets/extensions/layouts/title/starter.md +5 -0
  26. package/assets/extensions/palettes/brand/extension.toml +29 -0
  27. package/assets/extensions/palettes/cobalt/extension.toml +27 -0
  28. package/assets/extensions/palettes/ember/extension.toml +27 -0
  29. package/assets/extensions/palettes/forest/extension.toml +27 -0
  30. package/assets/extensions/palettes/graphite/extension.toml +27 -0
  31. package/assets/extensions/palettes/lagoon/extension.toml +27 -0
  32. package/assets/extensions/palettes/neon/extension.toml +27 -0
  33. package/assets/extensions/palettes/nordic/extension.toml +27 -0
  34. package/assets/extensions/palettes/pastel/extension.toml +30 -0
  35. package/assets/extensions/palettes/phosphor/extension.toml +27 -0
  36. package/assets/extensions/palettes/swiss/extension.toml +27 -0
  37. package/assets/extensions/palettes/terra/extension.toml +27 -0
  38. package/assets/extensions/themes/academic/extension.toml +53 -0
  39. package/assets/extensions/themes/academic/styles.css +631 -0
  40. package/assets/extensions/themes/aurora/extension.toml +37 -0
  41. package/assets/extensions/themes/aurora/styles.css +644 -0
  42. package/assets/extensions/themes/duet/extension.toml +46 -0
  43. package/assets/extensions/themes/duet/styles.css +573 -0
  44. package/assets/extensions/themes/editorial/extension.toml +46 -0
  45. package/assets/extensions/themes/editorial/styles.css +574 -0
  46. package/assets/extensions/themes/fhnw/extension.toml +61 -0
  47. package/assets/extensions/themes/fhnw/styles.css +604 -0
  48. package/assets/extensions/themes/neue/extension.toml +46 -0
  49. package/assets/extensions/themes/neue/styles.css +489 -0
  50. package/assets/extensions/themes/sketch/extension.toml +48 -0
  51. package/assets/extensions/themes/sketch/styles.css +633 -0
  52. package/assets/extensions/themes/terminal/extension.toml +38 -0
  53. package/assets/extensions/themes/terminal/styles.css +550 -0
  54. package/assets/logo/avatar.png +0 -0
  55. package/assets/logo/logo-dark.svg +10 -0
  56. package/assets/logo/logo-light.svg +10 -0
  57. package/assets/logo/mark.svg +15 -0
  58. package/bin/mdeck.js +2 -0
  59. package/docs/README.md +8 -0
  60. package/docs/reference/authoring.md +795 -0
  61. package/docs/reference/claude-skill.md +96 -0
  62. package/docs/reference/extensions.md +250 -0
  63. package/docs/reference/layouts.md +153 -0
  64. package/docs/reference/palettes.md +106 -0
  65. package/docs/reference/structured-slides.md +120 -0
  66. package/docs/reference/themes.md +133 -0
  67. package/docs/site/assets/favicon.svg +15 -0
  68. package/docs/site/assets/github-logo.svg +1 -0
  69. package/docs/site/assets/site.css +162 -0
  70. package/docs/site/assets/site.js +123 -0
  71. package/docs/site/build.js +148 -0
  72. package/docs/site/content/appearance.md +203 -0
  73. package/docs/site/content/audience.md +178 -0
  74. package/docs/site/content/commands.md +153 -0
  75. package/docs/site/content/components.md +134 -0
  76. package/docs/site/content/drawing.md +72 -0
  77. package/docs/site/content/editing.md +59 -0
  78. package/docs/site/content/getting-started.md +103 -0
  79. package/docs/site/content/layouts.md +126 -0
  80. package/docs/site/content/media.md +107 -0
  81. package/docs/site/content/more-content.md +130 -0
  82. package/docs/site/content/presenting.md +93 -0
  83. package/docs/site/content/reusable-layouts.md +74 -0
  84. package/docs/site/content/sharing.md +88 -0
  85. package/docs/site/content/theme-authoring.md +144 -0
  86. package/docs/site/content/theme-repository.md +76 -0
  87. package/docs/site/content/troubleshooting.md +92 -0
  88. package/docs/site/content/views.md +56 -0
  89. package/docs/site/content/welcome.md +71 -0
  90. package/docs/site/content/writing.md +121 -0
  91. package/docs/site/examples/first-talk.md +88 -0
  92. package/docs/site/examples/notebook.svg +58 -0
  93. package/docs/site/images/themes/academic-dark.webp +0 -0
  94. package/docs/site/images/themes/academic-light.webp +0 -0
  95. package/docs/site/images/themes/academic.webp +0 -0
  96. package/docs/site/images/themes/aurora-dark.webp +0 -0
  97. package/docs/site/images/themes/aurora-light.webp +0 -0
  98. package/docs/site/images/themes/aurora.webp +0 -0
  99. package/docs/site/images/themes/duet-dark.webp +0 -0
  100. package/docs/site/images/themes/duet-light.webp +0 -0
  101. package/docs/site/images/themes/duet.webp +0 -0
  102. package/docs/site/images/themes/editorial-dark.webp +0 -0
  103. package/docs/site/images/themes/editorial-light.webp +0 -0
  104. package/docs/site/images/themes/editorial.webp +0 -0
  105. package/docs/site/images/themes/fhnw.webp +0 -0
  106. package/docs/site/images/themes/neue-dark.webp +0 -0
  107. package/docs/site/images/themes/neue-light.webp +0 -0
  108. package/docs/site/images/themes/neue.webp +0 -0
  109. package/docs/site/images/themes/sketch-dark.webp +0 -0
  110. package/docs/site/images/themes/sketch-light.webp +0 -0
  111. package/docs/site/images/themes/sketch.webp +0 -0
  112. package/docs/site/images/themes/terminal-dark.webp +0 -0
  113. package/docs/site/images/themes/terminal-light.webp +0 -0
  114. package/docs/site/images/themes/terminal.webp +0 -0
  115. package/docs/site/package.json +9 -0
  116. package/docs/site/pages.js +27 -0
  117. package/docs/site/server.js +58 -0
  118. package/examples/custom-layouts/extensions/comparison/extension.toml +35 -0
  119. package/examples/custom-layouts/extensions/comparison/layout.jsx +15 -0
  120. package/examples/custom-layouts/extensions/comparison/starter.md +17 -0
  121. package/examples/custom-layouts/extensions/comparison/styles.css +4 -0
  122. package/examples/custom-layouts/slides.md +60 -0
  123. package/examples/poll/slides.md +127 -0
  124. package/examples/python/.mdeck-backups/slides.drawings-2026-10-06T08-36-47Z.json +19 -0
  125. package/examples/python/.mdeck-backups/slides.drawings-2026-10-06T11-27-30Z.json +6 -0
  126. package/examples/python/slides.drawings.json +6 -0
  127. package/examples/python/slides.md +493 -0
  128. package/examples/showcase/.mdeck-backups/slides.drawings-2026-10-06T08-08-30Z.json +10 -0
  129. package/examples/showcase/.mdeck-backups/slides.drawings-2026-10-06T11-41-35Z.json +13 -0
  130. package/examples/showcase/img/image.jpg +0 -0
  131. package/examples/showcase/img/mdeck.svg +66 -0
  132. package/examples/showcase/slides.drawings.json +11 -0
  133. package/examples/showcase/slides.md +427 -0
  134. package/package.json +75 -0
  135. package/skills/write-slides/SKILL.md +144 -0
  136. package/src/build/check.js +49 -0
  137. package/src/build/chrome.js +130 -0
  138. package/src/build/components.js +44 -0
  139. package/src/build/config.js +61 -0
  140. package/src/build/drawings.js +14 -0
  141. package/src/build/editorPlugin.js +272 -0
  142. package/src/build/editorServer.js +36 -0
  143. package/src/build/fonts.js +84 -0
  144. package/src/build/homePlugin.js +208 -0
  145. package/src/build/inkPlugin.js +192 -0
  146. package/src/build/ownWrites.js +18 -0
  147. package/src/build/pairing.js +81 -0
  148. package/src/build/pdf.js +34 -0
  149. package/src/build/relayAccess.js +85 -0
  150. package/src/build/slidesPlugin.js +371 -0
  151. package/src/build/themeCheck.js +151 -0
  152. package/src/build/tunnelClient.js +184 -0
  153. package/src/cli/args.js +76 -0
  154. package/src/cli/index.js +758 -0
  155. package/src/cli/migrate.js +123 -0
  156. package/src/cli/skill.js +40 -0
  157. package/src/cli/themes.js +140 -0
  158. package/src/components/CodeBlock.jsx +168 -0
  159. package/src/components/ConnectedViews.jsx +25 -0
  160. package/src/components/Icon.jsx +8 -0
  161. package/src/components/Poll.jsx +67 -0
  162. package/src/components/QrCode.jsx +29 -0
  163. package/src/components/QrCodeTag.jsx +27 -0
  164. package/src/components/Question.jsx +28 -0
  165. package/src/components/Scale.jsx +47 -0
  166. package/src/components/VideoPlayer.jsx +108 -0
  167. package/src/components/WordCloud.jsx +106 -0
  168. package/src/components/activity.jsx +35 -0
  169. package/src/components/callout.css +78 -0
  170. package/src/components/code-block.css +123 -0
  171. package/src/components/columns.css +11 -0
  172. package/src/components/poll.css +81 -0
  173. package/src/components/video-player.css +14 -0
  174. package/src/core/devPath.js +4 -0
  175. package/src/core/editDeck.js +230 -0
  176. package/src/core/icons.js +69 -0
  177. package/src/core/ink.js +221 -0
  178. package/src/core/labels.js +144 -0
  179. package/src/core/outline.js +33 -0
  180. package/src/core/parseSlides.js +152 -0
  181. package/src/core/source.js +137 -0
  182. package/src/core/urls.js +34 -0
  183. package/src/core/validateDeck.js +139 -0
  184. package/src/editor/api.js +67 -0
  185. package/src/editor/components/App.jsx +75 -0
  186. package/src/editor/components/ConflictBanner.jsx +10 -0
  187. package/src/editor/components/DeckSettings.jsx +108 -0
  188. package/src/editor/components/DesignApp.jsx +252 -0
  189. package/src/editor/components/Diagnostics.jsx +10 -0
  190. package/src/editor/components/ExtensionEditor.jsx +66 -0
  191. package/src/editor/components/ExtensionForms.jsx +134 -0
  192. package/src/editor/components/ExtensionsPanel.jsx +114 -0
  193. package/src/editor/components/Field.jsx +24 -0
  194. package/src/editor/components/Inspector.jsx +36 -0
  195. package/src/editor/components/LayoutPicker.jsx +23 -0
  196. package/src/editor/components/LayoutSelect.jsx +25 -0
  197. package/src/editor/components/LookThumbnail.jsx +8 -0
  198. package/src/editor/components/MetaFields.jsx +24 -0
  199. package/src/editor/components/Outline.jsx +28 -0
  200. package/src/editor/components/PalettePicker.jsx +32 -0
  201. package/src/editor/components/Preview.jsx +63 -0
  202. package/src/editor/components/PropsForm.jsx +46 -0
  203. package/src/editor/components/RawSlideEditor.jsx +9 -0
  204. package/src/editor/components/RegionEditor.jsx +15 -0
  205. package/src/editor/components/Resizer.jsx +18 -0
  206. package/src/editor/designLink.js +19 -0
  207. package/src/editor/editor.css +139 -0
  208. package/src/editor/extensions.js +86 -0
  209. package/src/editor/keyboard.js +21 -0
  210. package/src/editor/model.js +38 -0
  211. package/src/editor/sampleDeck.js +165 -0
  212. package/src/editor/saveQueue.js +47 -0
  213. package/src/editor/schema.js +36 -0
  214. package/src/editor/state.js +92 -0
  215. package/src/editor/useDeckDocument.js +67 -0
  216. package/src/extensions/appearance.js +79 -0
  217. package/src/extensions/contrast.js +57 -0
  218. package/src/extensions/discover.js +126 -0
  219. package/src/extensions/manifest.js +209 -0
  220. package/src/extensions/packs.js +268 -0
  221. package/src/extensions/tokens.js +25 -0
  222. package/src/home/Home.jsx +362 -0
  223. package/src/home/home.css +148 -0
  224. package/src/layouts/layoutApi.jsx +205 -0
  225. package/src/layouts/layoutProps.js +30 -0
  226. package/src/layouts/renderSlide.jsx +17 -0
  227. package/src/live/answer/answer.css +34 -0
  228. package/src/live/answer/answer.html +14 -0
  229. package/src/live/answer/answer.js +130 -0
  230. package/src/live/client.js +290 -0
  231. package/src/live/code.js +19 -0
  232. package/src/live/follow.js +17 -0
  233. package/src/live/pairing.js +34 -0
  234. package/src/live/presence.js +33 -0
  235. package/src/live/roomTag.js +38 -0
  236. package/src/live/rooms.js +249 -0
  237. package/src/live/server.js +82 -0
  238. package/src/live/tunnel.js +180 -0
  239. package/src/paths.js +9 -0
  240. package/src/runtime/ReaderView.jsx +193 -0
  241. package/src/runtime/SlideErrorBoundary.jsx +28 -0
  242. package/src/runtime/chrome.jsx +55 -0
  243. package/src/runtime/deck-stage.js +1533 -0
  244. package/src/runtime/design.html +12 -0
  245. package/src/runtime/design.jsx +5 -0
  246. package/src/runtime/editor.html +12 -0
  247. package/src/runtime/editor.jsx +5 -0
  248. package/src/runtime/editorBridge.js +58 -0
  249. package/src/runtime/fit.js +149 -0
  250. package/src/runtime/home.html +13 -0
  251. package/src/runtime/home.jsx +5 -0
  252. package/src/runtime/index.html +15 -0
  253. package/src/runtime/ink/InkLayer.jsx +17 -0
  254. package/src/runtime/ink/Toolbar.jsx +145 -0
  255. package/src/runtime/ink/attach.js +69 -0
  256. package/src/runtime/ink/bus.js +126 -0
  257. package/src/runtime/ink/controller.js +132 -0
  258. package/src/runtime/ink/room.js +101 -0
  259. package/src/runtime/ink/select.js +124 -0
  260. package/src/runtime/ink/server.js +75 -0
  261. package/src/runtime/ink/store.js +55 -0
  262. package/src/runtime/ink/toolbar.css +79 -0
  263. package/src/runtime/main.jsx +863 -0
  264. package/src/runtime/markedSetup.js +147 -0
  265. package/src/runtime/reader.css +59 -0
  266. package/src/runtime/registry.jsx +26 -0
  267. package/src/runtime/syncOrder.js +32 -0
  268. package/src/runtime/themeLoader.js +68 -0
@@ -0,0 +1,644 @@
1
+ /* Aurora — northern lights.
2
+ Soft curtains of light in the palette's two accents and their blend move
3
+ across the slides: as a faint shimmer at the edge of content slides, and
4
+ at full strength on title, chapter and statement slides. Chapter and
5
+ statement slides are night skies, in the palette's other variant, so a
6
+ talk alternates between day and night. Surfaces are frosted glass with a
7
+ fine gradient edge; key words glow in the accent gradient. All colours
8
+ come from the palette's roles, so every palette works. */
9
+
10
+ .slide {
11
+ --aurora-a: var(--accent);
12
+ --aurora-b: var(--accent-2);
13
+ --aurora-c: color-mix(in oklab, var(--accent) 50%, var(--accent-2));
14
+ --aurora-gradient: linear-gradient(120deg, var(--aurora-a) 0%, var(--aurora-c) 50%, var(--aurora-b) 100%);
15
+ --glass: color-mix(in oklab, var(--bg) 72%, transparent);
16
+ --glass-edge: linear-gradient(135deg, color-mix(in oklab, var(--aurora-a) 70%, transparent), color-mix(in oklab, var(--rule) 60%, transparent) 45%, color-mix(in oklab, var(--aurora-b) 70%, transparent));
17
+ }
18
+
19
+ /* The curtains: narrow, tall bands of light hanging from the top of the
20
+ sky and fading downwards, slanted like an aurora. Every slide has them;
21
+ how strong is set per slide type with --aurora-strength. */
22
+ .slide::before {
23
+ content: '';
24
+ position: absolute;
25
+ inset: -12% -16% 0;
26
+ background:
27
+ radial-gradient(ellipse 4.5% 62% at 8% 6%, var(--aurora-a), transparent 100%),
28
+ radial-gradient(ellipse 7% 78% at 20% 0%, var(--aurora-c), transparent 100%),
29
+ radial-gradient(ellipse 3.5% 54% at 31% 10%, var(--aurora-a), transparent 100%),
30
+ radial-gradient(ellipse 8% 86% at 45% 0%, var(--aurora-b), transparent 100%),
31
+ radial-gradient(ellipse 4% 58% at 58% 8%, var(--aurora-c), transparent 100%),
32
+ radial-gradient(ellipse 6.5% 74% at 72% 2%, var(--aurora-a), transparent 100%),
33
+ radial-gradient(ellipse 5% 66% at 88% 4%, var(--aurora-b), transparent 100%),
34
+ radial-gradient(ellipse 60% 22% at 50% 0%, color-mix(in oklab, var(--aurora-c) 60%, transparent), transparent 80%);
35
+ /* Soft by their gradients alone, not a blur filter: that stays vector in a
36
+ PDF (a blurred layer prints as a huge image) and draws faster. */
37
+ transform: skewX(-18deg);
38
+ opacity: var(--aurora-strength, 0);
39
+ pointer-events: none;
40
+ z-index: 0;
41
+ -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 var(--aurora-reach, 40%), transparent calc(var(--aurora-reach, 40%) + 40%));
42
+ mask-image: linear-gradient(to bottom, #000 0%, #000 var(--aurora-reach, 40%), transparent calc(var(--aurora-reach, 40%) + 40%));
43
+ }
44
+ /* Content stays above the light. */
45
+ .slide > .slide-header, .slide > .slide-body, .slide > .slide-footer { position: relative; z-index: 1; }
46
+ .slide > .slide-logo { z-index: 1; }
47
+
48
+ /* The light drifts slowly while presenting; never in print or for people
49
+ who prefer less motion. */
50
+ @media (prefers-reduced-motion: no-preference) {
51
+ .slide--title::before, .slide--chapter::before, .slide--focus::before { animation: aurora-drift 26s ease-in-out infinite alternate; }
52
+ }
53
+ @keyframes aurora-drift {
54
+ from { transform: skewX(-18deg) translateX(-2.5%); }
55
+ to { transform: skewX(-11deg) translateX(2.5%); }
56
+ }
57
+ deck-stage[data-deck-static] .slide::before { animation: none; }
58
+ /* In a PDF the curtains print as images (Chrome rasterizes see-through
59
+ gradients, about 800 KB a slide), so only the slides that carry the look
60
+ keep them; a mask would print as an image too. */
61
+ @media print {
62
+ .slide::before { animation: none; -webkit-mask-image: none; mask-image: none; }
63
+ .slide:not(.slide--title):not(.slide--chapter):not(.slide--focus)::before { display: none; }
64
+ }
65
+
66
+ /* Print and PDF: gradient text prints with a hairline box around it, and
67
+ glows print as dark halos; solid colours instead. */
68
+ @media print {
69
+ em, .slide-footer > span:last-child:not(:first-child), .chapter-num, .slide-body ol li::before {
70
+ background: none !important;
71
+ -webkit-text-fill-color: currentColor !important;
72
+ color: var(--aurora-a) !important;
73
+ filter: none !important;
74
+ }
75
+ .slide-body ul li::before, .focus-eyebrow::before, .slide-header > span:last-child:not(:empty)::after { box-shadow: none !important; }
76
+ /* Frosted glass blurs what lies behind it, which prints as an image. */
77
+ .slide *, .slide *::before { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
78
+ }
79
+
80
+ /* Content slides: a shimmer along the upper edge only. */
81
+ .slide { --aurora-strength: 0.2; --aurora-reach: 0%; }
82
+
83
+ /* Night slides: the palette's other variant (dark on a light deck). */
84
+ .slide--chapter, .slide--focus {
85
+ --bg: var(--inverse-bg);
86
+ --surface: var(--inverse-surface);
87
+ --ink: var(--inverse-ink);
88
+ --ink-soft: var(--inverse-ink-soft);
89
+ --muted: var(--inverse-muted);
90
+ --rule: var(--inverse-rule);
91
+ --accent: var(--inverse-accent);
92
+ --accent-2: var(--inverse-accent-2);
93
+ --on-accent: var(--inverse-on-accent);
94
+ background: var(--bg);
95
+ color: var(--ink);
96
+ }
97
+
98
+ /* ─────────────────────────────────────────────
99
+ HEADER / FOOTER
100
+ ───────────────────────────────────────────── */
101
+ .slide-header {
102
+ font-weight: 600;
103
+ letter-spacing: 0.10em;
104
+ text-transform: uppercase;
105
+ color: var(--ink-soft);
106
+ }
107
+ .slide-header .brand { color: var(--ink); }
108
+ /* The section label as a small glass pill with a glowing dot. */
109
+ .slide-header > span:last-child:not(:empty) {
110
+ display: inline-flex;
111
+ align-items: center;
112
+ gap: 12px;
113
+ padding: 8px 22px 8px 16px;
114
+ border-radius: 999px;
115
+ background: var(--glass-edge) border-box;
116
+ border: 1px solid transparent;
117
+ background-clip: border-box;
118
+ position: relative;
119
+ isolation: isolate;
120
+ }
121
+ .slide-header > span:last-child:not(:empty)::before {
122
+ content: '';
123
+ position: absolute;
124
+ inset: 1px;
125
+ border-radius: inherit;
126
+ background: var(--glass);
127
+ -webkit-backdrop-filter: blur(18px);
128
+ backdrop-filter: blur(18px);
129
+ z-index: -1;
130
+ }
131
+ .slide-header > span:last-child:not(:empty)::after {
132
+ content: '';
133
+ order: -1;
134
+ width: 9px;
135
+ height: 9px;
136
+ border-radius: 50%;
137
+ background: var(--aurora-gradient);
138
+ box-shadow: 0 0 12px var(--aurora-a);
139
+ }
140
+
141
+ .slide-logo {
142
+ position: absolute;
143
+ top: var(--pad-y);
144
+ right: var(--pad-x);
145
+ height: 96px;
146
+ width: auto;
147
+ max-width: 360px;
148
+ object-fit: contain;
149
+ filter: var(--logo-filter, none);
150
+ transform: translateY(calc(var(--fs-eyebrow) * 0.5 - 50%));
151
+ }
152
+
153
+ .slide-footer {
154
+ font-family: var(--font-body);
155
+ font-size: var(--fs-small);
156
+ font-weight: 400;
157
+ letter-spacing: 0.06em;
158
+ text-transform: uppercase;
159
+ color: var(--muted);
160
+ padding-top: 24px;
161
+ }
162
+ .slide-footer > span:last-child:not(:first-child) {
163
+ font-weight: 800;
164
+ letter-spacing: 0;
165
+ background: var(--aurora-gradient);
166
+ -webkit-background-clip: text;
167
+ -webkit-text-fill-color: transparent;
168
+ background-clip: text;
169
+ }
170
+
171
+ /* ─────────────────────────────────────────────
172
+ TYPOGRAPHY
173
+ ───────────────────────────────────────────── */
174
+ .eyebrow {
175
+ font-family: var(--font-body);
176
+ font-size: var(--fs-eyebrow);
177
+ font-weight: 700;
178
+ letter-spacing: 0.14em;
179
+ text-transform: uppercase;
180
+ color: var(--muted);
181
+ margin: 0 0 var(--gap-title) 0;
182
+ }
183
+ .display {
184
+ font-family: var(--font-display);
185
+ font-size: var(--fs-display);
186
+ font-weight: 800;
187
+ line-height: 0.98;
188
+ letter-spacing: -0.045em;
189
+ margin: 0;
190
+ color: var(--ink);
191
+ text-wrap: balance;
192
+ }
193
+ .title {
194
+ font-family: var(--font-display);
195
+ font-size: var(--fs-h);
196
+ font-weight: 800;
197
+ line-height: 1.04;
198
+ letter-spacing: -0.03em;
199
+ margin: 0;
200
+ color: var(--ink);
201
+ text-wrap: balance;
202
+ }
203
+ .subtitle {
204
+ font-family: var(--font-body);
205
+ font-size: var(--fs-sub);
206
+ font-weight: 400;
207
+ line-height: 1.3;
208
+ letter-spacing: -0.01em;
209
+ color: var(--ink-soft);
210
+ margin: 0;
211
+ text-wrap: pretty;
212
+ }
213
+ .body-text {
214
+ font-family: var(--font-body);
215
+ font-size: var(--fs-body);
216
+ font-weight: 400;
217
+ line-height: 1.5;
218
+ color: var(--ink-soft);
219
+ margin: 0;
220
+ text-wrap: pretty;
221
+ }
222
+ .meta {
223
+ font-family: var(--font-body);
224
+ font-size: var(--fs-small);
225
+ color: var(--muted);
226
+ }
227
+ /* Key words glow in the accent gradient. */
228
+ em {
229
+ font-style: normal;
230
+ background: var(--aurora-gradient);
231
+ -webkit-background-clip: text;
232
+ -webkit-text-fill-color: transparent;
233
+ background-clip: text;
234
+ }
235
+ strong { color: var(--ink); font-weight: 700; }
236
+
237
+ /* ─────────────────────────────────────────────
238
+ LAYOUT: TITLE — the full aurora over the sky
239
+ ───────────────────────────────────────────── */
240
+ .slide--title { --aurora-strength: 0.5; --aurora-reach: 30%; }
241
+ .slide--title .slide-body {
242
+ justify-content: center;
243
+ align-items: center;
244
+ text-align: center;
245
+ }
246
+ .slide--title .display {
247
+ font-size: var(--fs-display);
248
+ max-width: 1500px;
249
+ }
250
+ .slide--title .title-text { display: flex; flex-direction: column; align-items: center; }
251
+ .slide--title .subtitle {
252
+ margin-top: 56px;
253
+ max-width: 1100px;
254
+ }
255
+ /* With an image: the image fills the right half, the title stands at the
256
+ lower left, below the brightest light, instead of being pushed up into it. */
257
+ .slide--title.has-image .slide-body {
258
+ display: grid;
259
+ grid-template-columns: 1.1fr 1fr;
260
+ column-gap: 88px;
261
+ align-items: stretch;
262
+ text-align: left;
263
+ padding-bottom: 32px;
264
+ }
265
+ .slide--title.has-image .title-text {
266
+ align-items: flex-start;
267
+ justify-content: flex-end;
268
+ min-width: 0;
269
+ }
270
+ .slide--title.has-image .display { font-size: calc(var(--fs-display) * 0.62); }
271
+ .slide--title.has-image .subtitle { margin-top: 40px; }
272
+ .slide--title.has-image .title-image {
273
+ width: 100%;
274
+ height: 100%;
275
+ min-height: 0;
276
+ object-fit: cover;
277
+ border-radius: 24px;
278
+ }
279
+
280
+ /* ─────────────────────────────────────────────
281
+ LAYOUT: CHAPTER — a night sky with bright curtains
282
+ ───────────────────────────────────────────── */
283
+ .slide--chapter { --aurora-strength: 0.85; --aurora-reach: 35%; }
284
+ .slide--chapter .slide-body {
285
+ justify-content: flex-end;
286
+ align-items: flex-start;
287
+ padding-bottom: 24px;
288
+ }
289
+ .chapter-num {
290
+ font-family: var(--font-display);
291
+ font-size: 340px;
292
+ font-weight: 800;
293
+ /* Gradient text is painted only inside the element's box: a line height
294
+ below the glyphs' height cut off the bottom of the digits. The full line
295
+ height, with the spacing taken back by the margins. */
296
+ line-height: 1.05;
297
+ padding-right: 0.04em;
298
+ letter-spacing: -0.06em;
299
+ background: var(--aurora-gradient);
300
+ -webkit-background-clip: text;
301
+ -webkit-text-fill-color: transparent;
302
+ background-clip: text;
303
+ filter: drop-shadow(0 0 40px color-mix(in oklab, var(--aurora-c) 45%, transparent));
304
+ margin: -0.12em 0 -0.06em -12px;
305
+ }
306
+ .chapter-meta {
307
+ font-family: var(--font-body);
308
+ font-size: var(--fs-eyebrow);
309
+ font-weight: 700;
310
+ letter-spacing: 0.14em;
311
+ text-transform: uppercase;
312
+ color: var(--ink-soft);
313
+ margin: 0 0 20px 0;
314
+ }
315
+ .slide--chapter .chapter-title {
316
+ font-family: var(--font-display);
317
+ font-size: var(--fs-title);
318
+ font-weight: 800;
319
+ line-height: 1.0;
320
+ letter-spacing: -0.04em;
321
+ margin: 0 0 40px 0;
322
+ color: var(--ink);
323
+ max-width: 1400px;
324
+ text-wrap: balance;
325
+ }
326
+ .slide--chapter .chapter-desc {
327
+ font-family: var(--font-body);
328
+ font-size: var(--fs-sub);
329
+ font-weight: 400;
330
+ line-height: 1.35;
331
+ color: var(--ink-soft);
332
+ max-width: 1100px;
333
+ margin: 0;
334
+ }
335
+ .slide--chapter.has-image .slide-body {
336
+ display: grid;
337
+ grid-template-columns: 1fr 1fr;
338
+ column-gap: 80px;
339
+ align-items: stretch;
340
+ }
341
+ .slide--chapter.has-image .chapter-content {
342
+ display: flex;
343
+ flex-direction: column;
344
+ justify-content: flex-end;
345
+ align-items: flex-start;
346
+ }
347
+ .slide--chapter.has-image .chapter-image {
348
+ width: 100%;
349
+ height: 100%;
350
+ object-fit: cover;
351
+ border-radius: 24px;
352
+ }
353
+
354
+ /* ─────────────────────────────────────────────
355
+ LAYOUT: FOCUS — a statement under the night sky
356
+ ───────────────────────────────────────────── */
357
+ .slide--focus { --aurora-strength: 0.6; --aurora-reach: 20%; }
358
+ .slide--focus .slide-body {
359
+ justify-content: center;
360
+ align-items: center;
361
+ text-align: center;
362
+ }
363
+ .focus-eyebrow {
364
+ display: inline-flex;
365
+ align-items: center;
366
+ gap: 12px;
367
+ padding: 10px 28px 10px 20px;
368
+ border-radius: 999px;
369
+ background: var(--glass);
370
+ -webkit-backdrop-filter: blur(20px);
371
+ backdrop-filter: blur(20px);
372
+ border: 1px solid color-mix(in oklab, var(--rule) 70%, transparent);
373
+ font-family: var(--font-body);
374
+ font-size: var(--fs-eyebrow);
375
+ font-weight: 700;
376
+ letter-spacing: 0.12em;
377
+ text-transform: uppercase;
378
+ color: var(--ink-soft);
379
+ margin: 0 0 56px 0;
380
+ }
381
+ .focus-eyebrow::before {
382
+ content: '';
383
+ width: 10px;
384
+ height: 10px;
385
+ border-radius: 50%;
386
+ background: var(--aurora-gradient);
387
+ box-shadow: 0 0 12px var(--aurora-a);
388
+ }
389
+ .focus-statement,
390
+ .slide--focus .focus-content h1,
391
+ .slide--focus .focus-content p {
392
+ font-family: var(--font-display);
393
+ font-size: var(--fs-focus);
394
+ font-weight: 800;
395
+ line-height: 1.06;
396
+ letter-spacing: -0.04em;
397
+ color: var(--ink);
398
+ max-width: 1500px;
399
+ margin: 0;
400
+ text-wrap: balance;
401
+ text-align: center;
402
+ }
403
+ .focus-content {
404
+ display: flex;
405
+ flex-direction: column;
406
+ align-items: center;
407
+ width: 100%;
408
+ }
409
+ .focus-attribution {
410
+ font-family: var(--font-body);
411
+ font-size: var(--fs-small);
412
+ font-weight: 600;
413
+ letter-spacing: 0.12em;
414
+ text-transform: uppercase;
415
+ color: var(--muted);
416
+ margin: 56px 0 0 0;
417
+ }
418
+
419
+ /* ─────────────────────────────────────────────
420
+ LAYOUT: IMAGE + TEXT
421
+ ───────────────────────────────────────────── */
422
+ .image-pane {
423
+ flex: 1.15;
424
+ min-width: 0;
425
+ display: flex;
426
+ align-items: center;
427
+ justify-content: center;
428
+ background: var(--surface);
429
+ overflow: hidden;
430
+ position: relative;
431
+ border-radius: 28px;
432
+ box-shadow: 0 24px 60px -24px color-mix(in oklab, var(--aurora-c) 45%, transparent);
433
+ }
434
+ .image-placeholder {
435
+ width: 100%;
436
+ height: 100%;
437
+ background: repeating-linear-gradient(135deg, var(--surface) 0 22px, var(--bg) 22px 44px);
438
+ display: flex;
439
+ align-items: center;
440
+ justify-content: center;
441
+ }
442
+ .image-placeholder span {
443
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
444
+ font-size: 22px;
445
+ color: var(--muted);
446
+ letter-spacing: 0.08em;
447
+ text-transform: uppercase;
448
+ background: var(--bg);
449
+ padding: 14px 20px;
450
+ border: 1px solid var(--rule);
451
+ border-radius: 999px;
452
+ }
453
+ .text-pane .title { font-size: var(--fs-h); }
454
+ .text-pane .body-text + .body-text { margin-top: 8px; }
455
+ .text-pane .eyebrow { margin-bottom: 8px; }
456
+
457
+ /* ─────────────────────────────────────────────
458
+ LISTS — glowing dots, gradient numbers
459
+ ───────────────────────────────────────────── */
460
+ .slide-body ul li {
461
+ font-weight: 400;
462
+ line-height: 1.35;
463
+ padding-left: 46px;
464
+ position: relative;
465
+ }
466
+ .slide-body ul li::before {
467
+ content: '';
468
+ position: absolute;
469
+ left: 0;
470
+ top: 0.42em;
471
+ width: 14px;
472
+ height: 14px;
473
+ border-radius: 50%;
474
+ background: var(--aurora-gradient);
475
+ box-shadow: 0 0 14px color-mix(in oklab, var(--aurora-a) 55%, transparent);
476
+ }
477
+ .slide-body ol li {
478
+ padding-left: 60px;
479
+ position: relative;
480
+ }
481
+ .slide-body ol li::before {
482
+ content: counter(slide-ol);
483
+ position: absolute;
484
+ left: 0;
485
+ top: 0;
486
+ font-family: var(--font-display);
487
+ font-weight: 800;
488
+ line-height: 1.35;
489
+ background: var(--aurora-gradient);
490
+ -webkit-background-clip: text;
491
+ -webkit-text-fill-color: transparent;
492
+ background-clip: text;
493
+ }
494
+
495
+ /* ─────────────────────────────────────────────
496
+ LAYOUT: FULL-BLEED IMAGE
497
+ ───────────────────────────────────────────── */
498
+ .slide--full-bleed-image::before { display: none; }
499
+ .slide--full-bleed-image.has-overlay .slide-bg::after {
500
+ content: '';
501
+ position: absolute;
502
+ inset: 0;
503
+ background: linear-gradient(to top, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.15));
504
+ }
505
+ .slide--full-bleed-image .overlay-title {
506
+ font-family: var(--font-display);
507
+ font-size: calc(var(--fs-h) * 1.26);
508
+ font-weight: 800;
509
+ line-height: 1.02;
510
+ letter-spacing: -0.04em;
511
+ color: #fff;
512
+ margin: 0;
513
+ max-width: 1300px;
514
+ text-wrap: balance;
515
+ }
516
+
517
+ /* ─────────────────────────────────────────────
518
+ CONTENT SLIDE
519
+ ───────────────────────────────────────────── */
520
+ .slide-body h1 {
521
+ font-family: var(--font-display);
522
+ font-size: var(--fs-h);
523
+ font-weight: 800;
524
+ line-height: 1.04;
525
+ letter-spacing: -0.035em;
526
+ color: var(--ink);
527
+ margin: 0 0 var(--gap-title) 0;
528
+ max-width: 1500px;
529
+ text-wrap: balance;
530
+ }
531
+ .slide-body h2 {
532
+ font-family: var(--font-display);
533
+ font-size: var(--fs-sub);
534
+ font-weight: 700;
535
+ line-height: 1.15;
536
+ letter-spacing: -0.02em;
537
+ color: var(--ink);
538
+ margin: 0 0 var(--gap-item) 0;
539
+ }
540
+ .slide-body p {
541
+ font-family: var(--font-body);
542
+ font-size: var(--fs-body);
543
+ font-weight: 400;
544
+ line-height: 1.5;
545
+ color: var(--ink-soft);
546
+ margin: 0 0 var(--gap-item) 0;
547
+ text-wrap: pretty;
548
+ }
549
+
550
+ /* ─────────────────────────────────────────────
551
+ GLASS — callouts and code as frosted panes with a gradient edge
552
+ ───────────────────────────────────────────── */
553
+ .slide-body .callout {
554
+ position: relative;
555
+ isolation: isolate;
556
+ border: 1.5px solid transparent;
557
+ border-radius: 22px;
558
+ background: var(--glass-edge) border-box;
559
+ padding: 26px 34px 28px;
560
+ margin: 36px 0 0;
561
+ max-width: 1300px;
562
+ box-shadow: 0 18px 50px -24px color-mix(in oklab, var(--aurora-c) 50%, transparent);
563
+ }
564
+ .slide-body .callout::before {
565
+ content: '';
566
+ position: absolute;
567
+ inset: 0;
568
+ border-radius: 20px;
569
+ background: color-mix(in oklab, var(--bg) 88%, transparent);
570
+ -webkit-backdrop-filter: blur(20px);
571
+ backdrop-filter: blur(20px);
572
+ z-index: -1;
573
+ }
574
+ .slide-body .callout-title {
575
+ display: flex;
576
+ align-items: center;
577
+ gap: 12px;
578
+ font-family: var(--font-body);
579
+ font-size: var(--fs-eyebrow);
580
+ font-weight: 700;
581
+ letter-spacing: 0.12em;
582
+ text-transform: uppercase;
583
+ margin: 0 0 10px 0;
584
+ }
585
+ .slide-body .callout-title::before {
586
+ content: '';
587
+ width: 10px;
588
+ height: 10px;
589
+ border-radius: 50%;
590
+ background: currentColor;
591
+ box-shadow: 0 0 10px currentColor;
592
+ }
593
+ .slide-body .callout p { padding-left: 0; color: var(--ink); font-size: var(--fs-body); }
594
+ .slide-body .callout-tip .callout-title { color: var(--accent); }
595
+ /* Signal colours mixed with the text colour, readable on the glass in light and dark */
596
+ .slide-body .callout-note .callout-title { color: color-mix(in oklab, var(--callout-note) 65%, var(--ink)); }
597
+ .slide-body .callout-important .callout-title { color: color-mix(in oklab, var(--callout-important) 65%, var(--ink)); }
598
+ .slide-body .callout-warning .callout-title { color: color-mix(in oklab, var(--callout-warning) 45%, var(--ink)); }
599
+ .slide-body .callout-caution .callout-title { color: color-mix(in oklab, var(--callout-caution) 65%, var(--ink)); }
600
+ /* Lecture blocks: theorems glow in the accent, definitions in the second */
601
+ .slide-body :is(.callout-theorem, .callout-lemma, .callout-corollary) .callout-title { color: var(--accent); }
602
+ .slide-body .callout-definition .callout-title { color: var(--accent-2); }
603
+
604
+ .code-block {
605
+ --code-bg: color-mix(in oklab, var(--surface) 92%, transparent);
606
+ --code-radius: 20px;
607
+ --code-size: 30px;
608
+ background: var(--code-bg);
609
+ border-radius: var(--code-radius);
610
+ padding: 40px 48px;
611
+ position: relative;
612
+ margin: 0;
613
+ overflow: hidden;
614
+ font-size: var(--code-size);
615
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
616
+ line-height: 1.6;
617
+ border: 1px solid color-mix(in oklab, var(--rule) 70%, transparent);
618
+ box-shadow: 0 18px 50px -24px color-mix(in oklab, var(--aurora-c) 45%, transparent);
619
+ }
620
+ .code-block code {
621
+ font-family: inherit;
622
+ font-size: inherit;
623
+ background: none;
624
+ padding: 0;
625
+ }
626
+
627
+ /* ─────────────────────────────────────────────
628
+ AUDIENCE QUESTIONS — bars of light, glass cards
629
+ ───────────────────────────────────────────── */
630
+ .slide .poll-track, .slide .scale-track { border-radius: 999px; background: color-mix(in oklab, var(--rule) 55%, transparent); }
631
+ .slide .poll-fill { border-radius: 999px; background: var(--aurora-gradient); box-shadow: 0 0 18px color-mix(in oklab, var(--aurora-a) 45%, transparent); }
632
+ .slide .scale-fill { border-radius: 12px 12px 0 0; background: linear-gradient(to top, var(--aurora-a), var(--aurora-b)); }
633
+ .slide .question-cards li { border-radius: 18px; border-left: 0; background: var(--glass); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--rule) 70%, transparent); }
634
+ .slide .poll-join { border-radius: 24px; }
635
+
636
+ /* ─────────────────────────────────────────────
637
+ MATH (KaTeX)
638
+ ───────────────────────────────────────────── */
639
+ .slide .katex-display {
640
+ font-size: var(--fs-sub);
641
+ margin: 48px 0;
642
+ overflow-x: auto;
643
+ overflow-y: hidden;
644
+ }
@@ -0,0 +1,46 @@
1
+ schema = 1
2
+ kind = "theme"
3
+ id = "duet"
4
+ title = "Duet"
5
+ description = "Two voices: heavy slab headings, and two accents that take turns, as split fields, diagonal chapters and alternating markers."
6
+ # The palette this theme uses unless the deck sets one; colours come only from palettes.
7
+ palette = "cobalt"
8
+ fonts = [
9
+ "https://fonts.googleapis.com/css2?family=Zilla+Slab:wght@500;700&family=DM+Sans:wght@400;500;700&display=swap",
10
+ ]
11
+
12
+ [files]
13
+ styles = "styles.css"
14
+
15
+ # Type, spacing and fonts used by styles.css; colours come from the palette.
16
+ # Deck settings (params) override these.
17
+ [tokens]
18
+
19
+ # Type scale (px) — projection-appropriate at 1920×1080
20
+ "--fs-display" = "150px"
21
+ "--fs-title" = "112px"
22
+ "--fs-focus" = "88px"
23
+ "--fs-h" = "68px"
24
+ "--fs-sub" = "44px"
25
+ "--fs-body" = "34px"
26
+ "--fs-small" = "28px"
27
+ "--fs-eyebrow" = "24px"
28
+
29
+ # Spacing
30
+ "--pad-x" = "140px"
31
+ "--pad-y" = "72px"
32
+ "--gap-title" = "52px"
33
+ "--gap-item" = "28px"
34
+
35
+ # Type families
36
+ "--font-display" = "\"Zilla Slab\", Georgia, \"Times New Roman\", serif"
37
+ "--font-body" = "\"DM Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif"
38
+
39
+ # Settings authors can change under `params:` in the deck; each points at a token above.
40
+ [params.fontDisplay]
41
+ token = "--font-display"
42
+ title = "Display font"
43
+
44
+ [params.fontBody]
45
+ token = "--font-body"
46
+ title = "Body font"