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,573 @@
1
+ /* Duet — two voices.
2
+ Two accents for contrasting ideas, on every slide: the footer rule changes
3
+ colour halfway, list markers take turns, a split slide is a dialogue of two
4
+ colour fields, and a chapter slide is cut diagonally between the two.
5
+ Headings are heavy, tight slab serif; body text a quiet grotesque.
6
+ The second accent is only guaranteed 3:1 on the background, so it carries
7
+ headings, markers and surfaces, never body text, and nothing is written on
8
+ it except the background colour. Colours come only from the palette roles. */
9
+
10
+ .slide {
11
+ --tint-1: color-mix(in oklab, var(--accent) 9%, var(--bg));
12
+ --tint-2: color-mix(in oklab, var(--accent-2) 12%, var(--bg));
13
+ }
14
+
15
+ /* ─────────────────────────────────────────────
16
+ HEADER / FOOTER — the footer rule is two-tone, split at the middle
17
+ ───────────────────────────────────────────── */
18
+ .slide-header {
19
+ font-weight: 500;
20
+ letter-spacing: 0.1em;
21
+ text-transform: uppercase;
22
+ }
23
+ .slide-header .brand { color: var(--muted); }
24
+ .slide-header .section { color: var(--accent); font-weight: 700; }
25
+
26
+ .slide-logo {
27
+ position: absolute;
28
+ top: var(--pad-y);
29
+ right: var(--pad-x);
30
+ height: 120px;
31
+ width: auto;
32
+ max-width: 480px;
33
+ object-fit: contain;
34
+ filter: var(--logo-filter, none);
35
+ transform: translateY(calc(var(--fs-eyebrow) * 0.5 - 50%));
36
+ }
37
+
38
+ .slide-footer {
39
+ font-family: var(--font-body);
40
+ font-size: var(--fs-small);
41
+ font-weight: 400;
42
+ color: var(--muted);
43
+ border-top: 4px solid;
44
+ border-image: linear-gradient(to right, var(--accent) 50%, var(--accent-2) 50%) 1;
45
+ padding-top: 24px;
46
+ }
47
+ /* The page number in the slab face (a title slide's footer has only the author line). */
48
+ .slide-footer > span:last-child:not(:first-child) {
49
+ font-family: var(--font-display);
50
+ font-weight: 700;
51
+ color: var(--ink);
52
+ }
53
+
54
+ /* ─────────────────────────────────────────────
55
+ TYPOGRAPHY HELPERS
56
+ ───────────────────────────────────────────── */
57
+ .eyebrow {
58
+ font-family: var(--font-body);
59
+ font-size: var(--fs-eyebrow);
60
+ font-weight: 700;
61
+ letter-spacing: 0.16em;
62
+ text-transform: uppercase;
63
+ color: var(--accent);
64
+ margin: 0 0 var(--gap-title) 0;
65
+ }
66
+ .display {
67
+ font-family: var(--font-display);
68
+ font-size: var(--fs-display);
69
+ font-weight: 700;
70
+ line-height: 0.98;
71
+ letter-spacing: -0.03em;
72
+ margin: 0;
73
+ color: var(--ink);
74
+ text-wrap: balance;
75
+ }
76
+ .title {
77
+ font-family: var(--font-display);
78
+ font-size: var(--fs-h);
79
+ font-weight: 700;
80
+ line-height: 1.02;
81
+ letter-spacing: -0.025em;
82
+ margin: 0;
83
+ color: var(--ink);
84
+ text-wrap: balance;
85
+ }
86
+ .subtitle {
87
+ font-family: var(--font-body);
88
+ font-size: var(--fs-sub);
89
+ font-weight: 400;
90
+ line-height: 1.25;
91
+ letter-spacing: -0.01em;
92
+ color: var(--ink-soft);
93
+ margin: 0;
94
+ text-wrap: pretty;
95
+ }
96
+ .body-text {
97
+ font-family: var(--font-body);
98
+ font-size: var(--fs-body);
99
+ font-weight: 400;
100
+ line-height: 1.5;
101
+ color: var(--ink-soft);
102
+ margin: 0;
103
+ text-wrap: pretty;
104
+ }
105
+ .meta {
106
+ font-family: var(--font-body);
107
+ font-size: var(--fs-small);
108
+ color: var(--muted);
109
+ }
110
+
111
+ /* Emphasis: the first voice in running text, the second in large type. */
112
+ em {
113
+ font-style: normal;
114
+ font-weight: 500;
115
+ color: var(--accent);
116
+ }
117
+ :is(h1, h2, .display, .title, .chapter-title, .focus-content) em {
118
+ font-weight: inherit;
119
+ color: var(--accent-2);
120
+ }
121
+ strong { color: var(--ink); font-weight: 700; }
122
+
123
+ /* ─────────────────────────────────────────────
124
+ LAYOUT: TITLE — the boldest slide: all of it in the first accent, a band
125
+ of the second slanted like the chapter seam, the headline in the
126
+ accent's own text colour
127
+ ───────────────────────────────────────────── */
128
+ .slide--title {
129
+ background: var(--accent);
130
+ color: var(--on-accent);
131
+ }
132
+ .slide--title::after {
133
+ content: '';
134
+ position: absolute;
135
+ inset: 0;
136
+ background: var(--accent-2);
137
+ clip-path: polygon(85% 0, 91% 0, 81% 100%, 75% 100%);
138
+ pointer-events: none;
139
+ }
140
+ .slide--title > :not(.slide-logo, .slide-ink) { position: relative; z-index: 1; }
141
+ .slide--title .slide-logo { z-index: 1; }
142
+ .slide--title :is(.slide-header, .slide-header .brand, .slide-footer) { color: var(--on-accent); }
143
+ .slide--title .slide-footer { border-image-source: none; border-top-color: transparent; }
144
+ .slide--title .slide-body {
145
+ justify-content: center;
146
+ align-items: flex-start;
147
+ }
148
+ /* The duet mark: a bar in the slide's text colour, one in the second accent. */
149
+ .slide--title .title-text::before {
150
+ content: '';
151
+ display: block;
152
+ width: 244px;
153
+ height: 52px;
154
+ background:
155
+ linear-gradient(var(--on-accent), var(--on-accent)) 0 0 / 180px 20px no-repeat,
156
+ linear-gradient(var(--accent-2), var(--accent-2)) 64px 32px / 180px 20px no-repeat;
157
+ margin-bottom: 64px;
158
+ }
159
+ .slide--title .display {
160
+ font-size: var(--fs-display);
161
+ color: var(--on-accent);
162
+ /* Clear of the band on the right. */
163
+ max-width: 1280px;
164
+ }
165
+ /* The second accent is not readable on the first: emphasis keeps the
166
+ slide's text colour and is underlined in the second accent. */
167
+ .slide--title :is(.display, .subtitle) em {
168
+ color: inherit;
169
+ text-decoration: underline;
170
+ text-decoration-color: var(--accent-2);
171
+ text-decoration-thickness: 0.09em;
172
+ text-underline-offset: 0.12em;
173
+ text-decoration-skip-ink: none;
174
+ }
175
+ .slide--title .subtitle {
176
+ margin-top: 48px;
177
+ max-width: 1100px;
178
+ color: var(--on-accent);
179
+ }
180
+ .slide--title.has-image .slide-body {
181
+ display: grid;
182
+ grid-template-columns: 1fr 1fr;
183
+ column-gap: 80px;
184
+ align-items: center;
185
+ }
186
+ .slide--title.has-image .display { font-size: calc(var(--fs-display) * 0.65); }
187
+ .slide--title.has-image .title-image {
188
+ width: 100%;
189
+ height: 600px;
190
+ object-fit: cover;
191
+ }
192
+ .slide--title.has-image .display { max-width: none; }
193
+
194
+ /* ─────────────────────────────────────────────
195
+ LAYOUT: CHAPTER — cut diagonally: a field of the first accent with the
196
+ number, a seam of the second, and the title on the background
197
+ ───────────────────────────────────────────── */
198
+ .slide--chapter:not(.has-image)::before,
199
+ .slide--chapter:not(.has-image)::after {
200
+ content: '';
201
+ position: absolute;
202
+ inset: 0;
203
+ pointer-events: none;
204
+ }
205
+ .slide--chapter:not(.has-image)::before {
206
+ background: var(--accent);
207
+ clip-path: polygon(0 0, 40% 0, 30% 100%, 0 100%);
208
+ }
209
+ .slide--chapter:not(.has-image)::after {
210
+ background: var(--accent-2);
211
+ clip-path: polygon(40% 0, 43% 0, 33% 100%, 30% 100%);
212
+ }
213
+ .slide--chapter > * { position: relative; z-index: 1; }
214
+ .slide--chapter > .slide-ink { position: absolute; z-index: 50; }
215
+ .slide--chapter:not(.has-image) .slide-header .brand,
216
+ .slide--chapter:not(.has-image) .slide-footer > span:first-child { color: var(--on-accent); }
217
+ .slide--chapter:not(.has-image) .slide-footer { border-image-source: none; border-top-color: transparent; }
218
+
219
+ .slide--chapter .slide-body {
220
+ justify-content: center;
221
+ align-items: flex-start;
222
+ position: static;
223
+ }
224
+ /* The title starts clear of the seam (the slide is 1920 px wide). */
225
+ .slide--chapter:not(.has-image) .slide-body { padding-left: calc(880px - var(--pad-x)); }
226
+ .chapter-num {
227
+ position: absolute;
228
+ left: var(--pad-x);
229
+ bottom: calc(var(--pad-y) + 110px);
230
+ font-family: var(--font-display);
231
+ font-size: 360px;
232
+ font-weight: 700;
233
+ line-height: 0.75;
234
+ letter-spacing: -0.02em;
235
+ color: var(--on-accent);
236
+ margin: 0;
237
+ pointer-events: none;
238
+ }
239
+ .chapter-meta {
240
+ font-family: var(--font-body);
241
+ font-size: var(--fs-eyebrow);
242
+ font-weight: 700;
243
+ letter-spacing: 0.16em;
244
+ text-transform: uppercase;
245
+ color: var(--accent-2);
246
+ margin: 0 0 28px 0;
247
+ }
248
+ .slide--chapter .chapter-title {
249
+ font-family: var(--font-display);
250
+ font-size: var(--fs-title);
251
+ font-weight: 700;
252
+ line-height: 1.0;
253
+ letter-spacing: -0.03em;
254
+ margin: 0 0 40px 0;
255
+ color: var(--ink);
256
+ max-width: 900px;
257
+ text-wrap: balance;
258
+ }
259
+ .slide--chapter .chapter-desc {
260
+ font-family: var(--font-body);
261
+ font-size: var(--fs-sub);
262
+ font-weight: 400;
263
+ line-height: 1.3;
264
+ color: var(--ink-soft);
265
+ max-width: 860px;
266
+ margin: 0;
267
+ }
268
+ .slide--chapter.has-image .slide-body {
269
+ display: grid;
270
+ grid-template-columns: 1fr 1fr;
271
+ column-gap: 80px;
272
+ align-items: center;
273
+ }
274
+ .slide--chapter.has-image .chapter-num {
275
+ position: static;
276
+ font-size: 200px;
277
+ color: var(--accent);
278
+ margin-bottom: 24px;
279
+ }
280
+ .slide--chapter.has-image .chapter-image {
281
+ width: 100%;
282
+ height: 100%;
283
+ max-height: 760px;
284
+ object-fit: cover;
285
+ }
286
+
287
+ /* ─────────────────────────────────────────────
288
+ LAYOUT: FOCUS — a statement beside a thick bar in each accent
289
+ ───────────────────────────────────────────── */
290
+ .slide--focus .slide-body {
291
+ justify-content: center;
292
+ align-items: flex-start;
293
+ }
294
+ .focus-eyebrow {
295
+ font-family: var(--font-body);
296
+ font-size: var(--fs-eyebrow);
297
+ font-weight: 700;
298
+ letter-spacing: 0.16em;
299
+ text-transform: uppercase;
300
+ color: var(--accent);
301
+ margin: 0 0 48px 96px;
302
+ }
303
+ .focus-content {
304
+ display: flex;
305
+ flex-direction: column;
306
+ width: 100%;
307
+ padding-left: 96px;
308
+ box-sizing: border-box;
309
+ }
310
+ /* The bars stand beside the statement only, not beside code or a list below it. */
311
+ .focus-content > :is(h1, h2, h3, p, blockquote):first-child { position: relative; }
312
+ .focus-content > :is(h1, h2, h3, p, blockquote):first-child::before {
313
+ content: '';
314
+ position: absolute;
315
+ left: -96px;
316
+ top: 0.08em;
317
+ bottom: 0.08em;
318
+ width: 50px;
319
+ background:
320
+ linear-gradient(var(--accent), var(--accent)) 0 0 / 18px 100% no-repeat,
321
+ linear-gradient(var(--accent-2), var(--accent-2)) 32px 0 / 18px 100% no-repeat;
322
+ }
323
+ .focus-statement,
324
+ .slide--focus .focus-content h1,
325
+ .slide--focus .focus-content p {
326
+ font-family: var(--font-display);
327
+ font-size: var(--fs-focus);
328
+ font-weight: 700;
329
+ line-height: 1.08;
330
+ letter-spacing: -0.025em;
331
+ color: var(--ink);
332
+ max-width: 1450px;
333
+ margin: 0;
334
+ text-wrap: balance;
335
+ }
336
+ .focus-attribution {
337
+ font-family: var(--font-body);
338
+ font-size: var(--fs-small);
339
+ font-weight: 700;
340
+ letter-spacing: 0.12em;
341
+ text-transform: uppercase;
342
+ color: var(--muted);
343
+ margin: 56px 0 0 96px;
344
+ }
345
+
346
+ /* ─────────────────────────────────────────────
347
+ LAYOUT: IMAGE + TEXT
348
+ ───────────────────────────────────────────── */
349
+ .image-pane {
350
+ flex: 1.15;
351
+ min-width: 0;
352
+ display: flex;
353
+ align-items: center;
354
+ justify-content: center;
355
+ background: var(--tint-1);
356
+ overflow: hidden;
357
+ position: relative;
358
+ }
359
+ .image-placeholder {
360
+ width: 100%;
361
+ height: 100%;
362
+ background: repeating-linear-gradient(135deg, var(--tint-1) 0 22px, var(--tint-2) 22px 44px);
363
+ display: flex;
364
+ align-items: center;
365
+ justify-content: center;
366
+ }
367
+ .image-placeholder span {
368
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
369
+ font-size: 22px;
370
+ color: var(--muted);
371
+ letter-spacing: 0.08em;
372
+ text-transform: uppercase;
373
+ background: var(--bg);
374
+ padding: 14px 20px;
375
+ border: 1px solid var(--rule);
376
+ }
377
+ .text-pane .title { font-size: calc(var(--fs-h) * 1.05); }
378
+ .text-pane .body-text + .body-text { margin-top: 8px; }
379
+ .text-pane .eyebrow { margin-bottom: 12px; }
380
+
381
+ /* ─────────────────────────────────────────────
382
+ LAYOUT: SPLIT — a dialogue: two colour fields side by side, the heading
383
+ above the seam, each column's first heading in its side's accent
384
+ ───────────────────────────────────────────── */
385
+ .slide--split .split-columns { gap: 0; }
386
+ .slide--split .split-left,
387
+ .slide--split .split-right {
388
+ padding: 48px 56px;
389
+ justify-content: safe center;
390
+ }
391
+ .slide--split .split-left { background: var(--tint-1); box-shadow: inset 0 6px 0 var(--accent); }
392
+ .slide--split .split-right { background: var(--tint-2); box-shadow: inset 0 6px 0 var(--accent-2); }
393
+ .slide--split .split-left > :is(h1, h2, h3):first-child { color: var(--accent); }
394
+ .slide--split .split-right > :is(h1, h2, h3):first-child { color: var(--accent-2); }
395
+ .slide--split :is(.split-left, .split-right) > :last-child { margin-bottom: 0; }
396
+ /* In a field, code needs no box of its own: the field is its surface. */
397
+ .slide--split .code-block {
398
+ background: none;
399
+ border: 0;
400
+ padding: 0;
401
+ }
402
+
403
+ /* ─────────────────────────────────────────────
404
+ LISTS — markers take turns between the two accents
405
+ ───────────────────────────────────────────── */
406
+ .slide-body ul li {
407
+ font-weight: 400;
408
+ line-height: 1.32;
409
+ padding-left: 48px;
410
+ position: relative;
411
+ }
412
+ .slide-body ul li::before {
413
+ content: '';
414
+ position: absolute;
415
+ left: 0;
416
+ top: 0.55em;
417
+ width: 24px;
418
+ height: 7px;
419
+ background: var(--accent);
420
+ }
421
+ .slide-body ol li {
422
+ counter-increment: slide-ol;
423
+ padding-left: 56px;
424
+ position: relative;
425
+ }
426
+ .slide-body ol li::before {
427
+ content: counter(slide-ol);
428
+ position: absolute;
429
+ left: 0;
430
+ top: -0.04em;
431
+ font-family: var(--font-display);
432
+ font-size: calc(var(--fs-body) * 1.15);
433
+ font-weight: 700;
434
+ color: var(--accent);
435
+ line-height: 1.3;
436
+ }
437
+ .slide-body ul > li:nth-child(even)::before { background: var(--accent-2); }
438
+ .slide-body ol > li:nth-child(even)::before { color: var(--accent-2); }
439
+
440
+ /* ─────────────────────────────────────────────
441
+ LAYOUT: FULL-BLEED IMAGE
442
+ ───────────────────────────────────────────── */
443
+ .slide--full-bleed-image.has-overlay .slide-bg::after {
444
+ content: '';
445
+ position: absolute;
446
+ inset: 0;
447
+ background: rgba(0, 0, 0, 0.45);
448
+ }
449
+ .slide--full-bleed-image .overlay-title {
450
+ font-family: var(--font-display);
451
+ font-size: calc(var(--fs-h) * 1.15);
452
+ font-weight: 700;
453
+ line-height: 1.02;
454
+ letter-spacing: -0.025em;
455
+ color: #fff;
456
+ margin: 0;
457
+ max-width: 1300px;
458
+ text-wrap: balance;
459
+ }
460
+
461
+ /* ─────────────────────────────────────────────
462
+ GENERIC / CONTENT SLIDE
463
+ ───────────────────────────────────────────── */
464
+ .slide-body h1 {
465
+ font-family: var(--font-display);
466
+ font-size: var(--fs-h);
467
+ font-weight: 700;
468
+ line-height: 1.02;
469
+ letter-spacing: -0.025em;
470
+ color: var(--ink);
471
+ margin: 0 0 var(--gap-title) 0;
472
+ max-width: 1500px;
473
+ text-wrap: balance;
474
+ }
475
+ .slide-body h2 {
476
+ font-family: var(--font-display);
477
+ font-size: var(--fs-sub);
478
+ font-weight: 700;
479
+ line-height: 1.12;
480
+ letter-spacing: -0.02em;
481
+ color: var(--accent-2);
482
+ margin: 0 0 var(--gap-item) 0;
483
+ }
484
+ .slide-body p {
485
+ font-family: var(--font-body);
486
+ font-size: var(--fs-body);
487
+ font-weight: 400;
488
+ line-height: 1.5;
489
+ color: var(--ink-soft);
490
+ margin: 0 0 var(--gap-item) 0;
491
+ text-wrap: pretty;
492
+ }
493
+ .slide-body > p { max-width: 1500px; }
494
+
495
+ /* ─────────────────────────────────────────────
496
+ CALLOUTS — a tinted field with its title as a tab: tips (and notes) in
497
+ the first accent, warnings (and cautions) in the second
498
+ ───────────────────────────────────────────── */
499
+ .slide-body .callout {
500
+ --tab: var(--accent);
501
+ --tab-ink: var(--on-accent);
502
+ background: var(--tint-1);
503
+ border-left: 0;
504
+ border-top: 6px solid var(--tab);
505
+ padding: 0 36px 28px;
506
+ margin: 44px 0 0;
507
+ max-width: 1300px;
508
+ }
509
+ .slide-body :is(.callout-warning, .callout-caution, .callout-definition) {
510
+ --tab: var(--accent-2);
511
+ --tab-ink: var(--bg);
512
+ background: var(--tint-2);
513
+ }
514
+ /* Lecture blocks: theorems in the first voice, definitions in the second (above) */
515
+ .slide-body .callout:is(.callout-theorem, .callout-lemma, .callout-corollary, .callout-definition) .callout-title { color: var(--tab-ink); }
516
+ .slide-body .callout .callout-title {
517
+ display: inline-block;
518
+ background: var(--tab);
519
+ color: var(--tab-ink);
520
+ font-weight: 700;
521
+ letter-spacing: 0.14em;
522
+ padding: 6px 18px 8px;
523
+ margin: 0 0 20px;
524
+ }
525
+ .slide-body .callout p { padding-left: 0; color: var(--ink); font-size: var(--fs-body); }
526
+
527
+ /* ─────────────────────────────────────────────
528
+ CODE BLOCK — a tinted surface with a rule of the first accent on top
529
+ ───────────────────────────────────────────── */
530
+ .code-block {
531
+ --code-bg: var(--surface);
532
+ --code-radius: 0;
533
+ --code-size: 28px;
534
+ background: var(--code-bg);
535
+ border-radius: 0;
536
+ border-top: 6px solid var(--accent);
537
+ padding: 40px 48px;
538
+ margin: 0;
539
+ overflow: hidden;
540
+ font-size: var(--code-size);
541
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
542
+ line-height: 1.6;
543
+ color: var(--ink);
544
+ }
545
+ .code-block code {
546
+ font-family: inherit;
547
+ font-size: inherit;
548
+ background: none;
549
+ padding: 0;
550
+ }
551
+
552
+ /* ─────────────────────────────────────────────
553
+ AUDIENCE QUESTIONS — bars take turns between the two accents
554
+ ───────────────────────────────────────────── */
555
+ .slide .poll-track, .slide .poll-fill, .slide .scale-track, .slide .scale-fill { border-radius: 0; }
556
+ .slide .poll-track, .slide .scale-track { background: var(--tint-1); }
557
+ .slide .poll-row:nth-child(even) .poll-track { background: var(--tint-2); }
558
+ .slide .poll-row:nth-child(even) .poll-fill,
559
+ .slide .scale-column:nth-child(even) .scale-fill { background: var(--accent-2); }
560
+ .slide .question-cards li { border-radius: 0; background: var(--tint-1); }
561
+ .slide .question-cards li:nth-child(even) { background: var(--tint-2); border-left-color: var(--accent-2); }
562
+ .slide .question-cards li:first-child { border-left-color: var(--accent); }
563
+ .slide .poll-join { border-radius: 0; border: 3px solid var(--accent); }
564
+
565
+ /* ─────────────────────────────────────────────
566
+ MATH (KaTeX)
567
+ ───────────────────────────────────────────── */
568
+ .slide .katex-display {
569
+ font-size: var(--fs-sub);
570
+ margin: 48px 0;
571
+ overflow-x: auto;
572
+ overflow-y: hidden;
573
+ }
@@ -0,0 +1,46 @@
1
+ schema = 1
2
+ kind = "theme"
3
+ id = "editorial"
4
+ title = "Editorial"
5
+ description = "A magazine spread: Newsreader headlines, Lora text, drop caps, pull quotes and Roman chapter numerals."
6
+ # The palette this theme uses unless the deck sets one; colours come only from palettes.
7
+ palette = "terra"
8
+ fonts = [
9
+ "https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400..800;1,6..72,400..800&family=Lora:ital,wght@0,400;0,600;1,400;1,600&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" = "148px"
21
+ "--fs-title" = "112px"
22
+ "--fs-focus" = "80px"
23
+ "--fs-h" = "68px"
24
+ "--fs-sub" = "40px"
25
+ "--fs-body" = "32px"
26
+ "--fs-small" = "24px"
27
+ "--fs-eyebrow" = "22px"
28
+
29
+ # Spacing
30
+ "--pad-x" = "128px"
31
+ "--pad-y" = "72px"
32
+ "--gap-title" = "48px"
33
+ "--gap-item" = "24px"
34
+
35
+ # Type families
36
+ "--font-display" = "\"Newsreader\", Georgia, \"Times New Roman\", serif"
37
+ "--font-body" = "\"Lora\", Georgia, \"Times New Roman\", 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"