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,633 @@
1
+ /* Sketch — a sketchbook.
2
+ Caveat for headings, Patrick Hand for text, on dotted paper that becomes
3
+ a chalkboard in the dark. The drawn marks (the scribble under a heading,
4
+ the circle round a number, the arrows of a list) are SVG masks filled
5
+ with palette colours, so they follow every palette. Callouts are sticky
6
+ notes, pictures are photos taped in, and a focus slide is a speech
7
+ bubble. Everything takes its colours from the palette's roles (--bg,
8
+ --ink, --accent …), so every palette works on it. */
9
+
10
+ .slide {
11
+ --hairline: color-mix(in oklab, var(--ink) 22%, var(--bg));
12
+ --marker: color-mix(in oklab, var(--accent-2) 34%, transparent);
13
+ --paper-dot: color-mix(in oklab, var(--ink) 13%, transparent);
14
+ /* A hand-drawn outline: corners of different radii on every side */
15
+ --wobble: 18px 225px 14px 255px / 255px 16px 225px 20px;
16
+ --scribble: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 30' preserveAspectRatio='none'><path d='M5 17 C 60 7 120 21 180 13 S 270 8 295 12 M 22 25 C 90 17 170 26 282 18' fill='none' stroke='black' stroke-width='5' stroke-linecap='round'/></svg>");
17
+ --circle: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200' preserveAspectRatio='none'><path d='M150 28 C 108 6 38 20 20 82 C 4 142 62 190 122 178 C 180 166 198 108 178 64 C 164 34 126 16 84 26' fill='none' stroke='black' stroke-width='6' stroke-linecap='round'/></svg>");
18
+ --arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 24'><path d='M3 13 C 12 11 22 12 34 12 M25 4 C 29 8 32 10 36 12 C 31 15 28 18 25 21' fill='none' stroke='black' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
19
+ --tick: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 20' preserveAspectRatio='none'><path d='M3 12 C 10 6 16 15 22 9 S 32 6 37 10' fill='none' stroke='black' stroke-width='3.5' stroke-linecap='round'/></svg>");
20
+
21
+ background-color: var(--bg);
22
+ background-image: radial-gradient(var(--paper-dot) 1.6px, transparent 1.9px);
23
+ background-size: 44px 44px;
24
+ background-position: 22px 22px;
25
+ }
26
+
27
+ /* ─────────────────────────────────────────────
28
+ HEADER AND FOOTER: written in the margin; the slide number circled
29
+ ───────────────────────────────────────────── */
30
+ .slide-header {
31
+ font-family: var(--font-display);
32
+ font-size: calc(var(--fs-eyebrow) * 1.25);
33
+ font-weight: 600;
34
+ color: var(--muted);
35
+ }
36
+ .slide-header .brand { color: var(--ink); font-weight: 700; }
37
+
38
+ .slide-logo {
39
+ position: absolute;
40
+ top: var(--pad-y);
41
+ right: var(--pad-x);
42
+ height: 88px;
43
+ width: auto;
44
+ max-width: 340px;
45
+ object-fit: contain;
46
+ filter: var(--logo-filter, none);
47
+ transform: rotate(-2deg);
48
+ }
49
+
50
+ .slide-footer {
51
+ font-family: var(--font-display);
52
+ font-size: var(--fs-eyebrow);
53
+ font-weight: 600;
54
+ color: var(--muted);
55
+ }
56
+ .slide-footer > span:last-child:not(:first-child) {
57
+ position: relative;
58
+ min-width: 1.9em;
59
+ text-align: center;
60
+ color: var(--ink);
61
+ padding: 0.15em 0.3em;
62
+ }
63
+ .slide-footer > span:last-child:not(:first-child)::before {
64
+ content: '';
65
+ position: absolute;
66
+ inset: -0.12em -0.2em;
67
+ background: var(--accent);
68
+ mask: var(--circle) center / 100% 100% no-repeat;
69
+ }
70
+
71
+ /* ─────────────────────────────────────────────
72
+ TYPOGRAPHY HELPERS
73
+ ───────────────────────────────────────────── */
74
+ .eyebrow {
75
+ font-family: var(--font-display);
76
+ font-size: var(--fs-eyebrow);
77
+ font-weight: 700;
78
+ color: var(--accent);
79
+ margin: 0;
80
+ }
81
+
82
+ .display {
83
+ font-family: var(--font-display);
84
+ font-size: var(--fs-display);
85
+ font-weight: 700;
86
+ line-height: 0.95;
87
+ margin: 0;
88
+ color: var(--ink);
89
+ text-wrap: balance;
90
+ }
91
+
92
+ .title {
93
+ font-family: var(--font-display);
94
+ font-size: var(--fs-h);
95
+ font-weight: 700;
96
+ line-height: 1;
97
+ margin: 0;
98
+ color: var(--ink);
99
+ text-wrap: balance;
100
+ }
101
+
102
+ .subtitle {
103
+ font-family: var(--font-body);
104
+ font-size: var(--fs-sub);
105
+ line-height: 1.3;
106
+ color: var(--ink-soft);
107
+ margin: 0;
108
+ text-wrap: pretty;
109
+ }
110
+
111
+ .body-text {
112
+ font-family: var(--font-body);
113
+ font-size: var(--fs-body);
114
+ line-height: 1.4;
115
+ color: var(--ink-soft);
116
+ margin: 0;
117
+ text-wrap: pretty;
118
+ }
119
+
120
+ .meta {
121
+ font-family: var(--font-body);
122
+ font-size: var(--fs-small);
123
+ color: var(--muted);
124
+ }
125
+
126
+ /* Emphasis is written in the accent pen; bold is gone over with a
127
+ highlighter. */
128
+ em { font-style: normal; color: var(--accent); }
129
+ strong {
130
+ font-weight: inherit;
131
+ color: var(--ink);
132
+ background: linear-gradient(176deg, transparent 0 42%, var(--marker) 42% 88%, transparent 88%);
133
+ box-decoration-break: clone;
134
+ -webkit-box-decoration-break: clone;
135
+ padding: 0 0.12em;
136
+ margin: 0 -0.06em;
137
+ }
138
+
139
+ /* ─────────────────────────────────────────────
140
+ CONTENT SLIDES — a heading with a scribble under it
141
+ ───────────────────────────────────────────── */
142
+ .slide-body h1 {
143
+ font-family: var(--font-display);
144
+ font-size: var(--fs-h);
145
+ font-weight: 700;
146
+ line-height: 1;
147
+ color: var(--ink);
148
+ margin: 0 0 var(--gap-title) 0;
149
+ max-width: 1500px;
150
+ text-wrap: balance;
151
+ }
152
+ .slide-body h1::after {
153
+ content: '';
154
+ display: block;
155
+ width: min(340px, 60%);
156
+ height: 22px;
157
+ margin-top: 6px;
158
+ background: var(--accent);
159
+ mask: var(--scribble) center / 100% 100% no-repeat;
160
+ }
161
+ .slide-body h2 {
162
+ font-family: var(--font-display);
163
+ font-size: calc(var(--fs-sub) * 1.25);
164
+ font-weight: 700;
165
+ line-height: 1.1;
166
+ color: var(--accent);
167
+ margin: 0 0 var(--gap-item) 0;
168
+ text-wrap: balance;
169
+ }
170
+ .slide-body p {
171
+ font-family: var(--font-body);
172
+ font-size: var(--fs-body);
173
+ line-height: 1.4;
174
+ color: var(--ink-soft);
175
+ margin: 0 0 var(--gap-item) 0;
176
+ text-wrap: pretty;
177
+ }
178
+ .slide-body > p { max-width: 1500px; }
179
+
180
+ /* ─────────────────────────────────────────────
181
+ LISTS — drawn arrows; numbers written and circled
182
+ ───────────────────────────────────────────── */
183
+ .slide-body ul, .slide-body ol { max-width: 1500px; }
184
+ .slide-body ul li {
185
+ line-height: 1.35;
186
+ padding-left: 72px;
187
+ }
188
+ .slide-body ul li::before {
189
+ content: '';
190
+ position: absolute;
191
+ left: 0;
192
+ top: 0.3em;
193
+ width: 48px;
194
+ height: 0.75em;
195
+ background: var(--accent);
196
+ mask: var(--arrow) center / contain no-repeat;
197
+ }
198
+ .slide-body ol li {
199
+ line-height: 1.35;
200
+ padding-left: 80px;
201
+ }
202
+ .slide-body ol li::before {
203
+ content: counter(slide-ol);
204
+ position: absolute;
205
+ left: 0;
206
+ top: -0.12em;
207
+ width: 1.5em;
208
+ height: 1.5em;
209
+ display: grid;
210
+ place-items: center;
211
+ font-family: var(--font-display);
212
+ font-weight: 700;
213
+ font-size: 1.15em;
214
+ color: var(--accent);
215
+ background: none;
216
+ }
217
+ .slide-body ol li::after {
218
+ content: '';
219
+ position: absolute;
220
+ left: -0.1em;
221
+ top: -0.2em;
222
+ width: 1.55em;
223
+ height: 1.55em;
224
+ background: var(--accent);
225
+ mask: var(--circle) center / 100% 100% no-repeat;
226
+ opacity: 0.8;
227
+ }
228
+ .slide-body li :is(ul, ol) { margin-top: 10px; gap: 8px; font-size: 0.9em; }
229
+ .slide-body li ul li::before { mask-image: var(--tick); width: 36px; top: 0.45em; height: 0.5em; background: var(--muted); }
230
+
231
+ /* ─────────────────────────────────────────────
232
+ LAYOUT: TITLE — big handwriting, a double scribble under it
233
+ ───────────────────────────────────────────── */
234
+ .slide--title .slide-body { justify-content: center; }
235
+ .slide--title .display {
236
+ font-size: var(--fs-display);
237
+ max-width: 1500px;
238
+ }
239
+ .slide--title .display::after {
240
+ content: '';
241
+ display: block;
242
+ width: min(720px, 70%);
243
+ height: 40px;
244
+ margin-top: 8px;
245
+ background: var(--accent);
246
+ mask: var(--scribble) center / 100% 100% no-repeat;
247
+ }
248
+ .slide--title .subtitle {
249
+ margin-top: 40px;
250
+ max-width: 1200px;
251
+ }
252
+ .slide--title .slide-footer {
253
+ font-family: var(--font-body);
254
+ font-size: var(--fs-body);
255
+ font-weight: 400;
256
+ color: var(--ink-soft);
257
+ }
258
+ /* TITLE + image: the title on the left, the picture taped in on the right */
259
+ .slide--title.has-image .slide-body {
260
+ display: grid;
261
+ grid-template-columns: 1.15fr 1fr;
262
+ column-gap: 72px;
263
+ align-items: center;
264
+ }
265
+ .slide--title.has-image .display { font-size: calc(var(--fs-display) * 0.8); }
266
+ .slide--title.has-image .title-image {
267
+ width: 100%;
268
+ height: 100%;
269
+ max-height: 760px;
270
+ object-fit: contain;
271
+ transform: rotate(2deg);
272
+ }
273
+
274
+ /* ─────────────────────────────────────────────
275
+ LAYOUT: CHAPTER — the number circled in the accent, the title beside it
276
+ ───────────────────────────────────────────── */
277
+ .slide--chapter .slide-body {
278
+ justify-content: center;
279
+ align-items: flex-start;
280
+ }
281
+ .slide--chapter .chapter-content {
282
+ display: grid;
283
+ grid-template-columns: auto 1fr;
284
+ column-gap: 72px;
285
+ align-items: center;
286
+ align-self: stretch;
287
+ }
288
+ .chapter-num {
289
+ grid-row: 1 / span 3;
290
+ position: relative;
291
+ min-width: 320px;
292
+ height: 320px;
293
+ display: grid;
294
+ place-items: center;
295
+ padding: 0 40px;
296
+ box-sizing: border-box;
297
+ font-family: var(--font-display);
298
+ font-size: 220px;
299
+ font-weight: 700;
300
+ line-height: 1;
301
+ color: var(--accent);
302
+ user-select: none;
303
+ }
304
+ .chapter-num::before {
305
+ content: '';
306
+ position: absolute;
307
+ inset: 0;
308
+ background: var(--accent);
309
+ mask: var(--circle) center / 100% 100% no-repeat;
310
+ transform: rotate(-6deg);
311
+ }
312
+ .chapter-meta {
313
+ grid-column: 2;
314
+ align-self: end;
315
+ font-family: var(--font-display);
316
+ font-size: calc(var(--fs-eyebrow) * 1.4);
317
+ font-weight: 700;
318
+ color: var(--muted);
319
+ margin: 0;
320
+ }
321
+ .slide--chapter .chapter-title {
322
+ grid-column: 2;
323
+ font-family: var(--font-display);
324
+ font-size: var(--fs-title);
325
+ font-weight: 700;
326
+ line-height: 0.95;
327
+ margin: 4px 0 20px 0;
328
+ color: var(--ink);
329
+ max-width: 1200px;
330
+ text-wrap: balance;
331
+ }
332
+ .slide--chapter .chapter-desc {
333
+ grid-column: 2;
334
+ align-self: start;
335
+ font-family: var(--font-body);
336
+ font-size: var(--fs-sub);
337
+ line-height: 1.3;
338
+ color: var(--ink-soft);
339
+ max-width: 1050px;
340
+ margin: 0;
341
+ }
342
+ .slide--chapter .chapter-content > :not(.chapter-num, .chapter-meta, .chapter-title, .chapter-desc) { grid-column: 2; }
343
+ .slide--chapter.has-image .slide-body {
344
+ display: grid;
345
+ grid-template-columns: 1.3fr 1fr;
346
+ column-gap: 72px;
347
+ align-items: center;
348
+ }
349
+ .slide--chapter.has-image .chapter-num { min-width: 220px; height: 220px; font-size: 150px; }
350
+ .slide--chapter.has-image .chapter-title { font-size: calc(var(--fs-title) * 0.75); }
351
+ .slide--chapter.has-image .chapter-image { width: 100%; height: 100%; max-height: 760px; object-fit: contain; transform: rotate(-2deg); }
352
+
353
+ /* ─────────────────────────────────────────────
354
+ LAYOUT: FOCUS — a speech bubble with a hand-drawn outline; the
355
+ label written above it, the name below the tail
356
+ ───────────────────────────────────────────── */
357
+ .slide--focus .slide-body {
358
+ justify-content: center;
359
+ align-items: flex-start;
360
+ }
361
+ .focus-eyebrow {
362
+ font-family: var(--font-display);
363
+ font-size: calc(var(--fs-eyebrow) * 1.3);
364
+ font-weight: 700;
365
+ color: var(--accent);
366
+ margin: 0 0 20px 40px;
367
+ transform: rotate(-3deg);
368
+ }
369
+ .focus-content {
370
+ position: relative;
371
+ display: flex;
372
+ flex-direction: column;
373
+ gap: var(--gap-item);
374
+ max-width: 1500px;
375
+ padding: 64px 88px;
376
+ border: 5px solid var(--ink);
377
+ border-radius: var(--wobble);
378
+ background: var(--bg);
379
+ }
380
+ /* The tail */
381
+ .focus-content::after {
382
+ content: '';
383
+ position: absolute;
384
+ left: 140px;
385
+ bottom: -44px;
386
+ width: 64px;
387
+ height: 64px;
388
+ background: var(--bg);
389
+ border-right: 5px solid var(--ink);
390
+ border-bottom: 5px solid var(--ink);
391
+ transform: skewX(-28deg) rotate(42deg);
392
+ border-bottom-right-radius: 12px;
393
+ }
394
+ .focus-statement,
395
+ .slide--focus .focus-content h1,
396
+ .slide--focus .focus-content p {
397
+ font-family: var(--font-display);
398
+ font-size: var(--fs-focus);
399
+ font-weight: 700;
400
+ line-height: 1.05;
401
+ color: var(--ink);
402
+ margin: 0;
403
+ text-wrap: balance;
404
+ }
405
+ .slide--focus .focus-content h1::after { display: none; }
406
+ .focus-attribution {
407
+ font-family: var(--font-body);
408
+ font-size: var(--fs-body);
409
+ color: var(--muted);
410
+ margin: 64px 0 0 240px;
411
+ }
412
+
413
+ /* ─────────────────────────────────────────────
414
+ LAYOUT: IMAGE + TEXT — a photo taped into the book
415
+ ───────────────────────────────────────────── */
416
+ .slide--image-text .slide-body { gap: 96px; }
417
+ .image-pane {
418
+ flex: 1.05;
419
+ min-width: 0;
420
+ display: flex;
421
+ align-items: center;
422
+ justify-content: center;
423
+ position: relative;
424
+ background: color-mix(in oklab, var(--bg) 70%, white);
425
+ padding: 22px 22px 72px;
426
+ box-shadow: 0 14px 28px rgba(0, 0, 0, 0.16), 0 2px 6px rgba(0, 0, 0, 0.1);
427
+ transform: rotate(-1.5deg);
428
+ margin: 12px 0 24px;
429
+ }
430
+ /* Tape across the top edge */
431
+ .image-pane::before {
432
+ content: '';
433
+ position: absolute;
434
+ top: -22px;
435
+ left: 50%;
436
+ width: 180px;
437
+ height: 46px;
438
+ transform: translateX(-50%) rotate(3deg);
439
+ background: color-mix(in oklab, var(--accent-2) 30%, transparent);
440
+ z-index: 1;
441
+ }
442
+ .image-pane img, .image-pane .themed-picture { width: 100%; height: 100%; }
443
+ .image-placeholder {
444
+ background: repeating-linear-gradient(135deg, var(--surface) 0 24px, var(--bg) 24px 48px);
445
+ }
446
+ .image-placeholder span {
447
+ font-family: var(--font-display);
448
+ font-size: var(--fs-eyebrow);
449
+ color: var(--muted);
450
+ }
451
+ .text-pane .title { font-size: var(--fs-h); color: var(--ink); }
452
+ .text-pane .title::after { display: none; }
453
+
454
+ /* The split layout's shared heading */
455
+ .split-heading { margin-bottom: var(--gap-item); }
456
+
457
+ /* ─────────────────────────────────────────────
458
+ LAYOUT: FULL-BLEED IMAGE
459
+ ───────────────────────────────────────────── */
460
+ .slide--full-bleed-image { background-image: none; }
461
+ .slide--full-bleed-image.has-overlay .slide-bg::after {
462
+ content: '';
463
+ position: absolute;
464
+ inset: 0;
465
+ background: linear-gradient(to top, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0.15) 55%, transparent 100%);
466
+ }
467
+ .slide--full-bleed-image .overlay-title {
468
+ font-family: var(--font-display);
469
+ font-size: calc(var(--fs-h) * 1.2);
470
+ font-weight: 700;
471
+ line-height: 1;
472
+ color: #fff;
473
+ margin: 0;
474
+ max-width: 1300px;
475
+ text-wrap: balance;
476
+ }
477
+ .slide--full-bleed-image .overlay-title em { color: inherit; }
478
+ .slide--full-bleed-image .overlay-title::after { display: none; }
479
+
480
+ /* ─────────────────────────────────────────────
481
+ CALLOUTS — sticky notes, slightly turned, with a strip of tape
482
+ ───────────────────────────────────────────── */
483
+ .slide-body .callout {
484
+ --note: var(--accent-2);
485
+ position: relative;
486
+ /* Brighter on the chalkboard, so the note still reads as paper */
487
+ background: light-dark(color-mix(in oklab, var(--note) 24%, var(--bg)), color-mix(in oklab, var(--note) 40%, var(--bg)));
488
+ border: 0;
489
+ border-radius: 2px 2px 18px 2px;
490
+ padding: 26px 36px 22px;
491
+ margin: 22px 0 var(--gap-item);
492
+ max-width: 1100px;
493
+ box-shadow: 0 10px 22px rgba(0, 0, 0, 0.14), 0 2px 4px rgba(0, 0, 0, 0.08);
494
+ transform: rotate(-1deg);
495
+ align-self: flex-start;
496
+ }
497
+ .slide-body .callout:nth-of-type(even) { transform: rotate(0.8deg); }
498
+ .slide-body .callout::before {
499
+ content: '';
500
+ position: absolute;
501
+ top: -18px;
502
+ left: 50%;
503
+ width: 150px;
504
+ height: 36px;
505
+ transform: translateX(-50%) rotate(-2deg);
506
+ background: color-mix(in oklab, var(--surface) 60%, transparent);
507
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
508
+ }
509
+ .slide-body .callout-title {
510
+ font-family: var(--font-display);
511
+ font-size: calc(var(--fs-eyebrow) * 1.35);
512
+ font-weight: 700;
513
+ letter-spacing: 0;
514
+ text-transform: none;
515
+ color: var(--ink);
516
+ margin: 0 0 6px 0;
517
+ }
518
+ .slide-body .callout p { padding-left: 0; color: var(--ink); margin-bottom: 0; }
519
+ .slide-body .callout > * + * { margin-top: 10px; }
520
+ .slide-body :is(.callout-tip, .callout-theorem, .callout-lemma, .callout-corollary) { --note: var(--accent); }
521
+ .slide-body .callout-note { --note: var(--callout-note); }
522
+ .slide-body .callout-important { --note: var(--callout-important); }
523
+ .slide-body .callout-warning { --note: var(--callout-warning); }
524
+ .slide-body .callout-caution { --note: var(--callout-caution); }
525
+
526
+ /* A proof is written on the page, not stuck on it: "Proof." and a
527
+ square at the end. */
528
+ .slide-body .callout.callout-proof {
529
+ background: none;
530
+ box-shadow: none;
531
+ transform: none;
532
+ padding: 0;
533
+ max-width: 1500px;
534
+ }
535
+ .slide-body .callout.callout-proof::before { display: none; }
536
+ .slide-body .callout.callout-proof .callout-title {
537
+ float: left;
538
+ margin: 0 0.3em 0 0;
539
+ font-size: calc(var(--fs-body) * 1.2);
540
+ line-height: 1.15;
541
+ color: var(--accent);
542
+ }
543
+ .slide-body .callout.callout-proof .callout-title::after { content: '.'; }
544
+ .slide-body .callout.callout-proof p { color: var(--ink-soft); }
545
+ .slide-body .callout.callout-proof > :last-child::after { content: '\25A1'; margin-left: 0.5em; color: var(--accent); }
546
+
547
+ /* ─────────────────────────────────────────────
548
+ CODE — a box drawn round the listing
549
+ ───────────────────────────────────────────── */
550
+ .code-block {
551
+ --code-bg: color-mix(in oklab, var(--surface) 80%, transparent);
552
+ --code-radius: 0;
553
+ --code-size: 28px;
554
+ background: var(--code-bg);
555
+ border: 3px solid var(--ink);
556
+ border-radius: var(--wobble);
557
+ padding: 32px 44px;
558
+ margin: 0;
559
+ overflow: hidden;
560
+ font-size: var(--code-size);
561
+ font-family: var(--font-mono);
562
+ line-height: 1.5;
563
+ }
564
+ .code-block code {
565
+ font-family: inherit;
566
+ font-size: inherit;
567
+ background: none;
568
+ padding: 0;
569
+ }
570
+ /* Inline code: a word boxed in pencil on a scrap of paper */
571
+ .slide-body :not(pre) > code {
572
+ font-family: var(--font-mono);
573
+ font-size: 0.8em;
574
+ background: color-mix(in oklab, var(--surface) 75%, transparent);
575
+ border: 2px solid color-mix(in oklab, var(--ink) 40%, transparent);
576
+ border-radius: 4px 14px 5px 12px / 12px 5px 14px 4px;
577
+ padding: 0.02em 0.28em;
578
+ box-decoration-break: clone;
579
+ -webkit-box-decoration-break: clone;
580
+ }
581
+
582
+ /* ─────────────────────────────────────────────
583
+ TABLES — ruled by hand: a heavy stroke under the head, dashed rows
584
+ ───────────────────────────────────────────── */
585
+ .slide-body table { font-size: var(--fs-body); }
586
+ .slide-body th,
587
+ .slide-body td {
588
+ padding: 10px 28px 10px 0;
589
+ border-bottom: 2px dashed var(--hairline);
590
+ }
591
+ .slide-body th {
592
+ font-family: var(--font-display);
593
+ font-size: 1.2em;
594
+ font-weight: 700;
595
+ color: var(--accent);
596
+ border-bottom: 4px solid var(--ink);
597
+ border-radius: 0 0 40px 4px / 0 0 6px 2px;
598
+ }
599
+
600
+ /* ─────────────────────────────────────────────
601
+ FOOTNOTES
602
+ ───────────────────────────────────────────── */
603
+ .slide-footnotes {
604
+ font-family: var(--font-body);
605
+ border-top: 2px dashed var(--hairline);
606
+ }
607
+
608
+ /* ─────────────────────────────────────────────
609
+ AUDIENCE QUESTIONS — bars with drawn outlines
610
+ ───────────────────────────────────────────── */
611
+ .slide .poll-track, .slide .scale-track {
612
+ background: transparent;
613
+ border: 3px solid var(--ink);
614
+ border-radius: var(--wobble);
615
+ }
616
+ .slide .poll-fill, .slide .scale-fill { border-radius: var(--wobble); }
617
+ .slide .question-cards li {
618
+ border-radius: 2px 2px 14px 2px;
619
+ background: color-mix(in oklab, var(--accent-2) 22%, var(--bg));
620
+ box-shadow: 0 6px 14px rgba(0, 0, 0, 0.12);
621
+ }
622
+ .slide .question-cards li:nth-child(odd) { transform: rotate(-1deg); }
623
+ .slide .question-cards li:nth-child(even) { transform: rotate(1deg); }
624
+ .slide .poll-join { border-radius: var(--wobble); border: 3px solid var(--ink); }
625
+
626
+ /* ─────────────────────────────────────────────
627
+ MATH (KaTeX)
628
+ ───────────────────────────────────────────── */
629
+ .slide .katex-display {
630
+ margin: 24px 0;
631
+ overflow-x: auto;
632
+ overflow-y: hidden;
633
+ }
@@ -0,0 +1,38 @@
1
+ schema = 1
2
+ kind = "theme"
3
+ id = "terminal"
4
+ title = "Terminal"
5
+ description = "A terminal session: JetBrains Mono, headings at a prompt, a blinking cursor, log-line callouts and a tmux status bar; dark by default."
6
+ # The palette this theme uses unless the deck sets one; colours come only from palettes.
7
+ palette = "phosphor"
8
+ appearance = "dark"
9
+ fonts = [
10
+ "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700;800&display=swap",
11
+ ]
12
+
13
+ [files]
14
+ styles = "styles.css"
15
+
16
+ # Type, spacing and fonts used by styles.css; colours come from the palette.
17
+ # Deck settings (params) override these.
18
+ [tokens]
19
+
20
+ # Type families — monospace throughout
21
+ "--font-display" = "'JetBrains Mono', ui-monospace, monospace"
22
+ "--font-body" = "'JetBrains Mono', ui-monospace, monospace"
23
+
24
+ # Type scale (px) — projection-appropriate at 1920×1080
25
+ "--fs-display" = "112px"
26
+ "--fs-h" = "60px"
27
+ "--fs-sub" = "36px"
28
+ "--fs-body" = "29px"
29
+ "--fs-eyebrow" = "24px"
30
+ "--fs-small" = "24px"
31
+ "--fs-focus" = "72px"
32
+ "--fs-title" = "96px"
33
+
34
+ # Spacing
35
+ "--pad-x" = "120px"
36
+ "--pad-y" = "72px"
37
+ "--gap-title" = "44px"
38
+ "--gap-item" = "24px"