explico 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/CHANGELOG.md +1137 -1
  2. package/README.md +91 -13
  3. package/dist/compiler/astro.d.ts +4 -3
  4. package/dist/compiler/astro.js +45 -15
  5. package/dist/compiler/cli.d.ts +26 -12
  6. package/dist/compiler/cli.js +96 -25
  7. package/dist/compiler/collections.d.ts +9 -1
  8. package/dist/compiler/collections.js +55 -16
  9. package/dist/compiler/content-schema.d.ts +31 -0
  10. package/dist/compiler/content-schema.js +82 -0
  11. package/dist/compiler/content-schemas.d.ts +422 -0
  12. package/dist/compiler/content-schemas.js +229 -0
  13. package/dist/compiler/course-config.d.ts +1 -1
  14. package/dist/compiler/course-config.js +30 -2
  15. package/dist/compiler/exports/combined-html.d.ts +97 -0
  16. package/dist/compiler/exports/combined-html.js +492 -0
  17. package/dist/compiler/exports/download-index.d.ts +9 -0
  18. package/dist/compiler/exports/download-index.js +33 -0
  19. package/dist/compiler/exports/export-chapters.d.ts +98 -0
  20. package/dist/compiler/exports/export-chapters.js +164 -0
  21. package/dist/compiler/exports/export-pages.d.ts +48 -0
  22. package/dist/compiler/exports/export-pages.js +22 -0
  23. package/dist/compiler/exports/html-tree.d.ts +22 -0
  24. package/dist/compiler/exports/html-tree.js +47 -0
  25. package/dist/compiler/exports/latex/capture.d.ts +106 -0
  26. package/dist/compiler/exports/latex/capture.js +435 -0
  27. package/dist/compiler/exports/latex/compile.d.ts +73 -0
  28. package/dist/compiler/exports/latex/compile.js +115 -0
  29. package/dist/compiler/exports/latex/document.d.ts +102 -0
  30. package/dist/compiler/exports/latex/document.js +349 -0
  31. package/dist/compiler/exports/latex/explico.cls +415 -0
  32. package/dist/compiler/exports/latex/numbering.d.ts +18 -0
  33. package/dist/compiler/exports/latex/numbering.js +57 -0
  34. package/dist/compiler/exports/latex/serialize.d.ts +112 -0
  35. package/dist/compiler/exports/latex/serialize.js +606 -0
  36. package/dist/compiler/exports/latex-export.d.ts +44 -0
  37. package/dist/compiler/exports/latex-export.js +169 -0
  38. package/dist/compiler/exports/markdown/serialize.d.ts +51 -0
  39. package/dist/compiler/exports/markdown/serialize.js +527 -0
  40. package/dist/compiler/exports/markdown-export.d.ts +39 -0
  41. package/dist/compiler/exports/markdown-export.js +240 -0
  42. package/dist/compiler/exports/standalone-html.d.ts +14 -5
  43. package/dist/compiler/exports/standalone-html.js +23 -51
  44. package/dist/compiler/exports/static-tree.d.ts +253 -0
  45. package/dist/compiler/exports/static-tree.js +625 -0
  46. package/dist/compiler/exports/zip.d.ts +16 -0
  47. package/dist/compiler/exports/zip.js +72 -0
  48. package/dist/compiler/lesson-derivation.d.ts +8 -2
  49. package/dist/compiler/lesson-derivation.js +6 -7
  50. package/dist/compiler/manifest.d.ts +87 -6
  51. package/dist/compiler/manifest.js +174 -31
  52. package/dist/compiler/render-diagnostics.d.ts +65 -0
  53. package/dist/compiler/render-diagnostics.js +56 -0
  54. package/dist/compiler/resolution-report.d.ts +2 -1
  55. package/dist/{course-config-Dsnri9Tk.d.ts → course-config-rRtME5UV.d.ts} +56 -13
  56. package/dist/curriculum/validation.d.ts +9 -3
  57. package/dist/curriculum/validation.js +35 -17
  58. package/dist/reference/base-abbreviations.d.mts +2 -2
  59. package/dist/reference/base-abbreviations.mjs +2 -2
  60. package/dist/reference/base-operators.d.mts +2 -2
  61. package/dist/reference/base-operators.mjs +2 -2
  62. package/dist/reference/base-roman-labels.d.mts +4 -3
  63. package/dist/reference/base-roman-labels.mjs +4 -3
  64. package/dist/reference/citation-format.d.mts +35 -0
  65. package/dist/reference/citation-format.mjs +74 -0
  66. package/dist/reference/consistency.d.ts +5 -9
  67. package/dist/reference/consistency.js +34 -38
  68. package/dist/reference/curriculum-alignment.js +3 -24
  69. package/dist/reference/derived-entries.d.ts +45 -0
  70. package/dist/reference/derived-entries.js +50 -0
  71. package/dist/reference/derived-notation.d.mts +125 -0
  72. package/dist/reference/derived-notation.mjs +121 -0
  73. package/dist/reference/diagram-fit.d.ts +45 -0
  74. package/dist/reference/diagram-fit.js +54 -0
  75. package/dist/reference/diagram-layout.d.ts +59 -10
  76. package/dist/reference/diagram-layout.js +85 -24
  77. package/dist/reference/diagrams-validate.d.ts +1 -1
  78. package/dist/reference/equations-validate.d.ts +1 -1
  79. package/dist/reference/equations-validate.js +26 -1
  80. package/dist/reference/equations.d.mts +27 -0
  81. package/dist/reference/equations.mjs +120 -22
  82. package/dist/reference/examples-validate.d.ts +1 -1
  83. package/dist/reference/figure-fit.d.ts +70 -0
  84. package/dist/reference/figure-fit.js +60 -0
  85. package/dist/reference/figure-pictures.d.ts +27 -0
  86. package/dist/reference/figure-pictures.js +49 -0
  87. package/dist/reference/figures-validate.d.ts +1 -1
  88. package/dist/reference/gate-abbreviations.d.ts +1 -1
  89. package/dist/reference/gate-abbreviations.js +1 -1
  90. package/dist/reference/gate-course-rules.d.ts +4 -3
  91. package/dist/reference/gate-course-rules.js +9 -4
  92. package/dist/reference/gate-heading-length.d.ts +2 -0
  93. package/dist/reference/gate-heading-length.js +7 -5
  94. package/dist/reference/gate-heading-structure.js +26 -0
  95. package/dist/reference/gate-indices.d.ts +35 -0
  96. package/dist/reference/gate-indices.js +299 -0
  97. package/dist/reference/gate-math.d.ts +32 -2
  98. package/dist/reference/gate-math.js +68 -12
  99. package/dist/reference/gate-mdx-expression.d.ts +17 -0
  100. package/dist/reference/gate-mdx-expression.js +29 -0
  101. package/dist/reference/gate-part-pages.d.ts +1 -1
  102. package/dist/reference/gate-prop-text.d.ts +28 -0
  103. package/dist/reference/gate-prop-text.js +106 -0
  104. package/dist/reference/gate-prose-notation.d.ts +3 -1
  105. package/dist/reference/gate-prose-notation.js +4 -2
  106. package/dist/reference/gate-retired-keys.d.ts +35 -0
  107. package/dist/reference/gate-retired-keys.js +58 -0
  108. package/dist/reference/gloss.d.ts +2 -0
  109. package/dist/reference/katex-measure.d.ts +17 -0
  110. package/dist/reference/katex-measure.js +223 -0
  111. package/dist/reference/keyed-float-validate.js +12 -0
  112. package/dist/reference/keyed-jsx-floats.d.mts +2 -2
  113. package/dist/reference/keyed-jsx-floats.mjs +11 -14
  114. package/dist/reference/lab-math-scope.d.ts +1 -0
  115. package/dist/reference/lab-math-scope.js +13 -2
  116. package/dist/reference/math-glyphs.d.mts +94 -2
  117. package/dist/reference/math-glyphs.mjs +851 -46
  118. package/dist/reference/mixed-content.d.ts +8 -3
  119. package/dist/reference/mixed-content.js +4 -2
  120. package/dist/reference/page-notation.d.ts +34 -4
  121. package/dist/reference/page-notation.js +54 -2
  122. package/dist/reference/references.d.ts +11 -1
  123. package/dist/reference/references.js +6 -0
  124. package/dist/reference/registry.js +104 -10
  125. package/dist/reference/rehype-fail-katex-errors.d.mts +9 -0
  126. package/dist/reference/rehype-fail-katex-errors.mjs +19 -0
  127. package/dist/reference/rehype-heading-anchors.mjs +11 -1
  128. package/dist/reference/remark-citation.mjs +0 -0
  129. package/dist/reference/remark-notation.mjs +84 -20
  130. package/dist/reference/render-lab-math.d.ts +2 -0
  131. package/dist/reference/render-lab-math.js +17 -5
  132. package/dist/reference/sections-validate.d.ts +28 -3
  133. package/dist/reference/sections-validate.js +31 -4
  134. package/dist/reference/sections.d.mts +24 -6
  135. package/dist/reference/sections.mjs +92 -17
  136. package/dist/reference/tables-validate.d.ts +1 -1
  137. package/dist/reference/tables-validate.js +24 -1
  138. package/dist/reference/text-measure.d.ts +10 -0
  139. package/dist/reference/text-measure.js +41 -0
  140. package/dist/reference/text-widths.d.ts +10 -0
  141. package/dist/reference/text-widths.js +1238 -0
  142. package/dist/reference/types.d.ts +64 -8
  143. package/dist/rules/catalog.js +191 -30
  144. package/dist/rules/in-effect.d.ts +1 -1
  145. package/dist/rules/rules.schema.json +79 -24
  146. package/dist/rules/settings.d.ts +1 -1
  147. package/dist/rules/settings.js +7 -0
  148. package/dist/session/PreferenceStore.d.ts +18 -1
  149. package/dist/session/PreferenceStore.js +29 -1
  150. package/docs/authoring/README.md +32 -21
  151. package/docs/authoring/agents.md +38 -7
  152. package/docs/authoring/components.md +111 -6
  153. package/docs/authoring/migrating.md +707 -0
  154. package/docs/authoring/notation.md +281 -29
  155. package/docs/authoring/retired.md +1 -0
  156. package/docs/authoring/structure-rules.md +10 -41
  157. package/docs/authoring/structure.md +53 -2
  158. package/docs/authoring/visualizations.md +144 -18
  159. package/package.json +12 -7
  160. package/src/compiler/astro.ts +57 -17
  161. package/src/compiler/cli.ts +143 -35
  162. package/src/compiler/collections.ts +92 -19
  163. package/src/compiler/content-schema.ts +108 -0
  164. package/src/compiler/content-schemas.ts +391 -0
  165. package/src/compiler/course-config.ts +86 -15
  166. package/src/compiler/exports/combined-html.ts +669 -0
  167. package/src/compiler/exports/download-index.ts +36 -0
  168. package/src/compiler/exports/export-chapters.ts +233 -0
  169. package/src/compiler/exports/export-pages.ts +44 -0
  170. package/src/compiler/exports/html-tree.ts +62 -0
  171. package/src/compiler/exports/latex/capture.ts +651 -0
  172. package/src/compiler/exports/latex/compile.ts +168 -0
  173. package/src/compiler/exports/latex/document.ts +479 -0
  174. package/src/compiler/exports/latex/explico.cls +415 -0
  175. package/src/compiler/exports/latex/numbering.ts +74 -0
  176. package/src/compiler/exports/latex/serialize.ts +787 -0
  177. package/src/compiler/exports/latex/texlive-packages.txt +76 -0
  178. package/src/compiler/exports/latex-export.ts +255 -0
  179. package/src/compiler/exports/markdown/serialize.ts +632 -0
  180. package/src/compiler/exports/markdown-export.ts +329 -0
  181. package/src/compiler/exports/standalone-html.ts +39 -70
  182. package/src/compiler/exports/static-tree.ts +944 -0
  183. package/src/compiler/exports/zip.ts +88 -0
  184. package/src/compiler/lesson-derivation.ts +13 -8
  185. package/src/compiler/manifest.ts +299 -28
  186. package/src/compiler/render-diagnostics.ts +111 -0
  187. package/src/components/HoverPanel.astro +204 -6
  188. package/src/components/PartOverview.astro +12 -9
  189. package/src/components/abbreviation/AbbreviationLayer.astro +21 -12
  190. package/src/components/assessments/AssessmentRunner.tsx +7 -1
  191. package/src/components/assessments/AssessmentSet.astro +14 -1
  192. package/src/components/block-heading.ts +38 -0
  193. package/src/components/card-arrow.ts +18 -4
  194. package/src/components/card-carry.ts +406 -0
  195. package/src/components/card-drag.ts +1 -30
  196. package/src/components/card-fetch.ts +87 -0
  197. package/src/components/card-manager.ts +1222 -38
  198. package/src/components/card-memory.ts +5 -1
  199. package/src/components/card-placement.ts +211 -13
  200. package/src/components/card-side.ts +281 -31
  201. package/src/components/citation/CitationLayer.astro +45 -40
  202. package/src/components/diagram/Diagram.astro +123 -44
  203. package/src/components/figure/Figure.astro +11 -0
  204. package/src/components/figure/FloatCaption.astro +4 -17
  205. package/src/components/float-toolbar.ts +274 -0
  206. package/src/components/memo/Memo.astro +21 -10
  207. package/src/components/memo/ShortNote.astro +4 -0
  208. package/src/components/notation/NotationGlossary.astro +22 -17
  209. package/src/components/notation/NotationLayer.astro +321 -79
  210. package/src/components/notation/NotationMath.astro +8 -1
  211. package/src/components/notation/render-notation-math.ts +51 -5
  212. package/src/components/readable-text.ts +25 -0
  213. package/src/components/reference/FloatRefLayer.astro +162 -89
  214. package/src/components/starlight/HeadingAnchorEnhancer.astro +13 -8
  215. package/src/components/starlight/KeyedFloatEnhancer.astro +28 -9
  216. package/src/components/starlight/LayoutPageSidebar.astro +17 -3
  217. package/src/components/starlight/LayoutSocialIcons.astro +79 -29
  218. package/src/components/starlight/LessonExportActions.astro +384 -310
  219. package/src/components/starlight/LessonFooter.astro +47 -9
  220. package/src/components/starlight/PrintController.astro +28 -0
  221. package/src/components/starlight/TextSizeControl.astro +137 -0
  222. package/src/components/starlight/print-controller.ts +380 -0
  223. package/src/components/starlight/section-summary.ts +13 -5
  224. package/src/components/table/Table.astro +13 -21
  225. package/src/components/table/table-truncation.ts +15 -0
  226. package/src/content-config.ts +20 -312
  227. package/src/curriculum/validation.ts +72 -24
  228. package/src/reference/base-abbreviations.mjs +2 -2
  229. package/src/reference/base-operators.mjs +2 -2
  230. package/src/reference/base-roman-labels.mjs +4 -3
  231. package/src/reference/citation-format.mjs +74 -0
  232. package/src/reference/consistency.ts +47 -61
  233. package/src/reference/curriculum-alignment.ts +4 -41
  234. package/src/reference/derived-entries.ts +68 -0
  235. package/src/reference/derived-notation.mjs +121 -0
  236. package/src/reference/diagram-fit.ts +104 -0
  237. package/src/reference/diagram-layout.ts +182 -51
  238. package/src/reference/diagrams-validate.ts +2 -1
  239. package/src/reference/equations-validate.ts +41 -2
  240. package/src/reference/equations.mjs +120 -22
  241. package/src/reference/examples-validate.ts +1 -0
  242. package/src/reference/figure-fit.ts +139 -0
  243. package/src/reference/figure-pictures.ts +96 -0
  244. package/src/reference/figures-validate.ts +2 -1
  245. package/src/reference/gate-abbreviations.ts +1 -1
  246. package/src/reference/gate-course-rules.ts +22 -7
  247. package/src/reference/gate-heading-length.ts +25 -7
  248. package/src/reference/gate-heading-structure.ts +40 -1
  249. package/src/reference/gate-indices.ts +470 -0
  250. package/src/reference/gate-math.ts +102 -13
  251. package/src/reference/gate-mdx-expression.ts +45 -0
  252. package/src/reference/gate-prop-text.ts +145 -0
  253. package/src/reference/gate-prose-notation.ts +19 -5
  254. package/src/reference/gate-retired-keys.ts +101 -0
  255. package/src/reference/gloss.ts +2 -0
  256. package/src/reference/katex-measure.ts +384 -0
  257. package/src/reference/keyed-float-validate.ts +22 -0
  258. package/src/reference/keyed-jsx-floats.mjs +11 -14
  259. package/src/reference/lab-math-scope.ts +15 -1
  260. package/src/reference/math-glyphs.mjs +851 -46
  261. package/src/reference/mixed-content.ts +11 -2
  262. package/src/reference/page-notation.ts +100 -3
  263. package/src/reference/references.ts +14 -0
  264. package/src/reference/registry.ts +154 -8
  265. package/src/reference/rehype-fail-katex-errors.mjs +19 -0
  266. package/src/reference/rehype-heading-anchors.mjs +11 -1
  267. package/src/reference/remark-citation.mjs +0 -0
  268. package/src/reference/remark-notation.mjs +84 -20
  269. package/src/reference/render-lab-math.ts +29 -5
  270. package/src/reference/sections-validate.ts +67 -3
  271. package/src/reference/sections.mjs +92 -17
  272. package/src/reference/tables-validate.ts +40 -2
  273. package/src/reference/text-measure.ts +63 -0
  274. package/src/reference/text-widths.ts +133 -0
  275. package/src/reference/types.ts +75 -8
  276. package/src/rules/catalog.ts +205 -29
  277. package/src/rules/settings.ts +10 -0
  278. package/src/session/PreferenceStore.ts +53 -0
  279. package/src/styles/global.css +291 -75
@@ -117,7 +117,7 @@ prints `§ 1.1.2` ([structure.md § Section numbers](structure.md#section-number
117
117
  | --- | --- | --- | --- |
118
118
  | `<Table id="…" caption="…" short="…">` | `explico/components/table/Table.astro` | `tab-` | [structure.md](structure.md#numbering), [V rules](visualizations.md) |
119
119
  | `<Figure id="…" caption="…" short="…" previewable defaultOpen rememberState>`, with an optional `slot="tools"` | `explico/components/figure/Figure.astro` | `fig-` | [structure.md](structure.md#numbering), [V2](visualizations.md#v2)/[V3](visualizations.md#v3) |
120
- | `<Diagram id="…" caption="…" short="…" nodes={…} edges={…}>` | `explico/components/diagram/Diagram.astro` | `dia-` | [V1](visualizations.md#v1) |
120
+ | `<Diagram id="…" caption="…" short="…" nodes={…} edges={…}>` | `explico/components/diagram/Diagram.astro` | `dia-` | [V1](visualizations.md#v1)/[V8](visualizations.md#v8) |
121
121
  | A display equation with `\label{eq:key}` and `\caption{…}` | `remark-math` (built in) | `eq-` | [N5](notation.md#n5), [structure.md](structure.md#numbering) |
122
122
 
123
123
  ### The caption pair
@@ -129,16 +129,31 @@ title bar: its number sits in its caption line.
129
129
 
130
130
  | Float | Long caption — where it shows | Short caption — where it shows |
131
131
  | --- | --- | --- |
132
- | `<Figure>` | `caption`: below the figure, after `Figure 2.2.1` and its chain icon | `short`: opens the caption line as its bold title, and heads the `[[fig-…]]` preview card |
132
+ | `<Figure>` | `caption`: below the figure, after `Figure 2.2.1` | `short`: opens the caption line as its bold title, and heads the `[[fig-…]]` preview card |
133
133
  | `<Diagram>` | `caption`: below the graph, the same caption line as a figure; its right end holds a widen button ↔ while the graph is wider than the column | `short`: opens the caption line as its bold title, and heads the `[[dia-…]]` preview card |
134
134
  | `<Table>` | `caption`: above the table (the LaTeX table convention), after `Table 2.2.1`; its right end holds the fold button (and a widen button ↔ when the table is wider than the column); stays with the header row when the table is folded | `short`: opens the caption line as its bold title, and heads the `[[tab-…]]` preview card |
135
135
  | Display equation | none — an equation takes a short caption only | `\caption{…}` inside the `$$…$$`, stripped before KaTeX like `\label{}`: heads the `[[eq-…]]` preview card and names the copy action ("Copy LaTeX — Range formula") |
136
136
  | `<Memo>` | `caption` (required): the memo's bar, and the head of its marker's preview | `short`: the marker's tooltip |
137
137
  | `<CompactExamples>` | none | `short` (required, with `id`): the set's topic — its heading, after the engine's "Example" badge and number |
138
138
 
139
+ **A float's number has a toolbar.** Hovering or focusing the number of an
140
+ equation, a figure, a table or a diagram shows Pin and Dock just above it
141
+ and Copy link just below it; none of them covers the number. Pin and Dock
142
+ keep the float's own preview card, next to the float or beside the article;
143
+ Copy link copies the float's link, named by its number and short caption,
144
+ as a heading's chain icon does. A click on the number itself only puts its
145
+ anchor in the address bar. An equation's Copy LaTeX sits on its bottom
146
+ border, under the number, and shows while the equation is hovered. A touch
147
+ screen has no toolbar: a long press on the number offers the browser's own
148
+ "Copy link" (`float-toolbar.ts`).
149
+
139
150
  `caption` is required wherever it exists; `short` is optional everywhere but
140
151
  on a `<CompactExamples>`, whose heading it is, and is what
141
152
  [rule S1](structure-rules.md#s1) measures — the long caption is never capped.
153
+ Write both as quoted strings: `short={"…"}` renders, but the manifest reads
154
+ only a quoted prop, so a reference's card, a copied link and the "Figures and
155
+ tables" page would name the float without it (`fig-unread-prop` and its kin,
156
+ a warning). Use typographic quotes (‘’ “”) inside one.
142
157
 
143
158
  A figure's, a table's or a diagram's `short` is its name wherever the page
144
159
  names it: the bold title that opens its caption line — "**Sampled flight
@@ -156,7 +171,7 @@ is shown.
156
171
 
157
172
  - **A figure or a diagram never hides by itself.** It is laid out as LaTeX
158
173
  lays a figure out, in every state: its picture, then its caption line —
159
- number, chain icon, caption. To let a reader fold one away, wrap it in a
174
+ number, caption. To let a reader fold one away, wrap it in a
160
175
  [`<Fold>`](#folding-content-away-fold) or put it in a collapsible (or
161
176
  `[card]`) section ([structure.md § Collapsing](structure.md#collapsing-two-mechanisms)).
162
177
  - **A lab's tools follow the caption, and only they fold.** A `<Figure>`'s
@@ -184,7 +199,38 @@ _Enforcement._ A `<Figure title>`, a `<Diagram label>` (or `title`,
184
199
  `ex-removed-prop` in `pnpm validate:content` (the keyed-floats invariant),
185
200
  and the component itself when it renders. A `<CompactExamples>` with no `id`
186
201
  or no `short` fails the same way (`ex-missing-prop`). An equation's `\caption{}` that is inline, repeated
187
- or empty fails the page build.
202
+ or empty fails the page build. A `<Table>` holds one table: a second
203
+ inside it fails `pnpm validate:content` (`tab-several-tables`), since the float
204
+ has one number and one caption and every export would keep only the first.
205
+
206
+ ### Props are plain text
207
+
208
+ A quoted prop — `caption="…"`, `short="…"`, a `<Memo>`'s `caption`, a
209
+ `<ShortNote>`'s `title`, a `<Fold>`'s `label` — reaches the page as the
210
+ text it holds. KaTeX, `[[…]]` references and `[@…]` citations run on the
211
+ lesson's Markdown, never inside a prop, so `short="Speed $v$"` would show
212
+ "Speed $v$" in the caption line, the preview card and the "Figures and
213
+ tables" page. Write a symbol in a prop in Unicode or words
214
+ (`short="Launch speed v₀"`), and reference or cite from the prose next to
215
+ the component, where the symbol, the link and the citation render. Rule N9
216
+ does not apply in a prop for the same reason.
217
+
218
+ _Enforcement._ Always on (invariant `prop-text`): `$…$`, `[[…]]` or `[@…]`
219
+ in a quoted prop of a lesson's JSX fails `pnpm validate:content` with
220
+ `markup-in-prop` at its line (`gate-prop-text.ts`). The math gates do not
221
+ read prop strings, so the symbol in one needs no notation entry.
222
+
223
+ ### Braces in prose
224
+
225
+ MDX reads `{…}` in a lesson's text as JavaScript: `The set {a} has one
226
+ element` renders nothing for `{a}` and fails the build with "a is not
227
+ defined". Write `\{a\}` for braces in the text, and a set as math,
228
+ `$\{a\}$` (in LaTeX, plain braces only group: `${a}$` reads "a"). A
229
+ directive's attributes, `:::note{icon=""}`, are not prose.
230
+
231
+ _Enforcement._ Always on (invariant `prop-text`): a brace pair in the
232
+ prose fails `pnpm validate:content` with `mdx-expression` at its line
233
+ (`gate-mdx-expression.ts`).
188
234
 
189
235
  ### The "Figures and tables" page
190
236
 
@@ -200,7 +246,6 @@ group lists the page beside the curriculum map and the glossary:
200
246
  ---
201
247
  title: Figures and tables
202
248
  description: Every numbered figure, table and diagram of the course.
203
- editorialStatus: draft
204
249
  ---
205
250
 
206
251
  import FloatIndex from 'explico/components/FloatIndex.astro';
@@ -218,11 +263,71 @@ elsewhere — the machinery a bare `title` tooltip deliberately skips.
218
263
  | `[[key]]` in prose, before first math use | `content/notation/*.md` entry | One-meaning-per-glyph hover card everywhere `$key$`-bound math appears on the page | [N4](notation.md#n4) |
219
264
  | `\explain{key}{latex}` inside `$…$` | Same notation entry | Escape hatch for a compound/colliding symbol only, not the default bind | [N4](notation.md#n4) |
220
265
  | A bare all-caps/dotted term (`OLS`, `w.r.t.`) in prose | `content/abbreviations/*.md`, or `course.settings.json` `rules.N14.allow` | Hover/click card on first occurrence, linked to the glossary page | [N14](notation.md#n14) |
221
- | `[@source-id]` or `[@source-id; §1.2]` | `content/sources/*.json` | Numbered `[n]` superscript linking to a References section, with a hover/pin panel | `src/reference/remark-citation.mjs` |
266
+ | `[@source-id]`, `[@source-id; §1.2]`, or several as Pandoc writes them, `[@a; @b; p. 7]` | `content/sources/*.json` | Numbered `[n]` superscript linking to a References section, with a hover/pin panel; one per source | `src/reference/remark-citation.mjs` |
222
267
  | `[[sec-slug]]` or `[[lesson/slug#sec-slug]]` | A top-level heading; its anchor is the slug | `§ 1.1.2` linking to the section, with a hover card of its title and first paragraph | [structure.md § Section numbers](structure.md#section-numbers) |
223
268
  | `[[ex-id]]` or `[[lesson/slug#ex-id]]` | A `<CompactExamples id>` | `Example 1.1.1` linking to the set, with a hover card of its title and its examples' names | [§ Knowledge checks and worked examples](#knowledge-checks-and-worked-examples) |
224
269
  | `[[check-id]]` or `[[lesson/slug#check-id]]` | An assessment id in the lesson's `.checks.yml` | `Knowledge check 1.1.1` linking to the check, with a hover card of its title and its number of questions | [structure.md § Knowledge checks](structure.md#knowledge-checks) |
225
270
 
271
+ A reference to another lesson's float, `[[lesson/slug#eq-…]]` and the rest,
272
+ previews it from that lesson, symbols and all: each symbol in the preview
273
+ opens the card that lesson gives it, even one the citing page never uses, so
274
+ there is no notation to copy over. One of that lesson's own symbols says so
275
+ on its card: "Defined in Position and Coordinate Systems · means this only
276
+ there".
277
+
278
+ A citation is a link of its own, so it cannot sit in a link's text:
279
+ `[as measured in [@id]](https://…)` fails `pnpm validate:content`
280
+ (`citation-in-link`); cite after the link, `[as measured](https://…) [@id]`.
281
+
282
+ The prefixes `eq-`, `tab-`, `fig-`, `dia-`, `ex-`, `check-`, `sec-` and
283
+ `memo-` belong to these references, so no notation key starts with one: a
284
+ `[[ex-ante]]` is read as a worked-example reference and never reaches an
285
+ `ex-ante` entry. Such a key fails `validate:content` where it is defined
286
+ (`invalid-key`), and `pnpm content new term` refuses it; name the entry
287
+ `exante` or `ante-expectation` instead.
288
+
289
+ ### Carrying cards
290
+
291
+ A reader keeps a card by clicking its trigger (pinned), docking it beside the
292
+ article, or dragging it somewhere. A pinned card whose trigger the reader
293
+ folds away — its section collapsed, its fold closed — waits out of sight and
294
+ comes back beside the trigger when it opens again; a docked or dragged card
295
+ stays where the reader put it. With **Carry cards** on, a kept card stays
296
+ on screen: it scrolls with its trigger until it reaches the top or the bottom
297
+ edge of the window and stays there, and follows its trigger again once the
298
+ trigger comes back. Cards held at one edge stack in the order they were
299
+ opened; when they are taller than the window, the older ones collapse to
300
+ their header row, and a click opens one again.
301
+
302
+ The switch sits with the side column's controls, beside "Article left", while
303
+ the column is in use; otherwise it shows alone at the article's top right
304
+ while a card is kept. Its tooltip says what it does. It is off until a reader
305
+ turns it on, and their choice is remembered. A course can start every reader
306
+ with it on:
307
+
308
+ ```json
309
+ "cards": { "carry": true }
310
+ ```
311
+
312
+ in `course.settings.json` (`CourseConfig.cards`).
313
+
314
+ With carrying on, the kept cards also come along to every page of the course,
315
+ however the reader gets there. On the page a card was opened on, it attaches
316
+ to its trigger again; on any other page it is rebuilt from that page and held
317
+ at the edge of the window it was at. A figure card brings its plot as it was
318
+ drawn. Closing a card ends its journey. Each browser tab keeps its own cards,
319
+ and a new tab starts with the ones the reader carried last.
320
+
321
+ With carrying on, every kept card also links back to where it was opened:
322
+ "Opened at § 2.1.1" beside its "Go to …" link, or "Opened at (2.1.3)" for a
323
+ card opened from inside a numbered equation. The link goes to the section's
324
+ anchor, and with JavaScript to the trigger itself, which lights up a moment.
325
+
326
+ Nothing in a course's content has to change for this: every card layer
327
+ registers on every page (`LessonFooter.astro`) and can rebuild its cards from
328
+ another page (`CardSource.build`). The rules are K1–K8 in
329
+ `src/components/card-carry.ts` and `heldAt` in `card-placement.ts`.
330
+
226
331
  ## Knowledge checks and worked examples
227
332
 
228
333
  | Component | Import | Notes | Doc |