@bendyline/squisq 2.1.0 → 2.2.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 (446) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +24 -0
  3. package/dist/{ContentContainer-BXUlIf18.d.ts → ContentContainer-B2w9sUoL.d.ts} +15 -0
  4. package/dist/{Doc-DynJleo-.d.ts → Doc-BubIpWsp.d.ts} +1 -1
  5. package/dist/{ImageEditDoc-Ca4Tr9uN.d.ts → ImageEditDoc-CGxk5CHc.d.ts} +1 -1
  6. package/dist/{annotationCoercion-Dr_DY9Hx.d.ts → annotationCoercion-PtRQhk5V.d.ts} +1 -1
  7. package/dist/chunk-2L55443L.js +0 -0
  8. package/dist/{chunk-VWCJ2WXC.js → chunk-2ZWIXGAC.js} +0 -1
  9. package/dist/{chunk-VYFRI7R6.js → chunk-32R2RZAO.js} +72 -3
  10. package/dist/chunk-3IGPAPQ7.js +645 -0
  11. package/dist/{chunk-QE7TWGVT.js → chunk-4VOD55SX.js} +0 -1
  12. package/dist/{chunk-3E5F2XMR.js → chunk-67L6WRJN.js} +0 -1
  13. package/dist/{chunk-5DKBFXPY.js → chunk-6ECMNUIP.js} +26 -18
  14. package/dist/{chunk-JI77MGAK.js → chunk-7ARJZYQY.js} +159 -120
  15. package/dist/{chunk-DBS6RIFL.js → chunk-7N4G32LG.js} +0 -1
  16. package/dist/{chunk-JOQYPRDZ.js → chunk-7YEZFHLS.js} +10 -8
  17. package/dist/{chunk-2UQOHYE2.js → chunk-7ZAAICW4.js} +0 -1
  18. package/dist/{chunk-66QO7XFB.js → chunk-ACZOVWX3.js} +117 -7
  19. package/dist/{chunk-5J4HKRJF.js → chunk-BAOV476U.js} +0 -1
  20. package/dist/chunk-BCCXTMN5.js +699 -0
  21. package/dist/{chunk-JHZWYRSW.js → chunk-C33GTPUZ.js} +11 -4
  22. package/dist/{chunk-QUUPYOSP.js → chunk-CB45YGAM.js} +2 -3
  23. package/dist/{chunk-XNLB57UD.js → chunk-DYPMOPIW.js} +18 -2
  24. package/dist/{chunk-VR7UPJ7C.js → chunk-FCG3BIZN.js} +12 -1
  25. package/dist/{chunk-5UYI3RJB.js → chunk-FDYDYL77.js} +54 -40
  26. package/dist/{chunk-OTKVFVL6.js → chunk-I2O6W7DX.js} +116 -44
  27. package/dist/{chunk-Q7LROV2H.js → chunk-NKNMGIIN.js} +0 -1
  28. package/dist/chunk-OPO5K4DZ.js +241 -0
  29. package/dist/{chunk-TUWMK62B.js → chunk-PUS54YU6.js} +45 -2
  30. package/dist/chunk-QKPXHDLR.js +0 -0
  31. package/dist/{chunk-GZY66SDN.js → chunk-R3KTTOMS.js} +0 -1
  32. package/dist/{chunk-ILWDXLUK.js → chunk-RS5AP3J4.js} +49 -10
  33. package/dist/chunk-WV5ARNDA.js +0 -0
  34. package/dist/{chunk-4X3JQXNM.js → chunk-XOFT65EX.js} +1 -2
  35. package/dist/{chunk-FVTQSNR7.js → chunk-XRW6P7IF.js} +13 -5
  36. package/dist/chunk-XWNNA3KE.js +0 -0
  37. package/dist/chunk-YZNGMV3G.js +0 -0
  38. package/dist/{chunk-R2YZTCLO.js → chunk-ZQKZSJAX.js} +1 -2
  39. package/dist/doc/index.d.ts +27 -12
  40. package/dist/doc/index.js +16 -17
  41. package/dist/generate/index.d.ts +2 -2
  42. package/dist/generate/index.js +2 -3
  43. package/dist/icons/index.js +3 -4
  44. package/dist/icons/inlineIconMarker.js +1 -2
  45. package/dist/imageEdit/index.d.ts +48 -17
  46. package/dist/imageEdit/index.js +3 -4
  47. package/dist/index.d.ts +11 -11
  48. package/dist/index.js +60 -33
  49. package/dist/jsonForm/index.d.ts +10 -3
  50. package/dist/jsonForm/index.js +8 -7
  51. package/dist/markdown/index.d.ts +75 -11
  52. package/dist/markdown/index.js +32 -7
  53. package/dist/{materializePageSection-DDzubQXo.d.ts → materializePageSection-wSLA2A1g.d.ts} +2 -2
  54. package/dist/narration/index.d.ts +16 -3
  55. package/dist/narration/index.js +13 -14
  56. package/dist/random/index.d.ts +11 -2
  57. package/dist/random/index.js +2 -3
  58. package/dist/recommend/index.d.ts +1 -1
  59. package/dist/recommend/index.js +3 -4
  60. package/dist/schemas/index.d.ts +5 -5
  61. package/dist/schemas/index.js +5 -6
  62. package/dist/spatial/index.d.ts +2 -1
  63. package/dist/spatial/index.js +1 -2
  64. package/dist/storage/index.d.ts +4 -2
  65. package/dist/storage/index.js +1 -2
  66. package/dist/{themeLibrary-B72m0W1y.d.ts → themeLibrary-DU9mUmVl.d.ts} +1 -1
  67. package/dist/timing/index.js +3 -4
  68. package/dist/transform/index.d.ts +3 -3
  69. package/dist/transform/index.js +6 -7
  70. package/dist/{types-C4kiRn_k.d.ts → types-8QjefM9J.d.ts} +38 -2
  71. package/dist/{types-BwMPl2CB.d.ts → types-CUNc9biN.d.ts} +24 -1
  72. package/dist/versions/index.d.ts +14 -11
  73. package/dist/versions/index.js +2 -3
  74. package/package.json +4 -2
  75. package/dist/chunk-2UQOHYE2.js.map +0 -1
  76. package/dist/chunk-3E5F2XMR.js.map +0 -1
  77. package/dist/chunk-4X3JQXNM.js.map +0 -1
  78. package/dist/chunk-5DKBFXPY.js.map +0 -1
  79. package/dist/chunk-5J4HKRJF.js.map +0 -1
  80. package/dist/chunk-5UYI3RJB.js.map +0 -1
  81. package/dist/chunk-66QO7XFB.js.map +0 -1
  82. package/dist/chunk-AMIR72JP.js +0 -380
  83. package/dist/chunk-AMIR72JP.js.map +0 -1
  84. package/dist/chunk-DBS6RIFL.js.map +0 -1
  85. package/dist/chunk-DNJKBAI7.js +0 -1
  86. package/dist/chunk-DNJKBAI7.js.map +0 -1
  87. package/dist/chunk-ET53IIEP.js +0 -1
  88. package/dist/chunk-ET53IIEP.js.map +0 -1
  89. package/dist/chunk-FVTQSNR7.js.map +0 -1
  90. package/dist/chunk-GZY66SDN.js.map +0 -1
  91. package/dist/chunk-ILWDXLUK.js.map +0 -1
  92. package/dist/chunk-JHZWYRSW.js.map +0 -1
  93. package/dist/chunk-JI77MGAK.js.map +0 -1
  94. package/dist/chunk-JOQYPRDZ.js.map +0 -1
  95. package/dist/chunk-OTKVFVL6.js.map +0 -1
  96. package/dist/chunk-PGGGKYWG.js +0 -1
  97. package/dist/chunk-PGGGKYWG.js.map +0 -1
  98. package/dist/chunk-Q7LROV2H.js.map +0 -1
  99. package/dist/chunk-QE7TWGVT.js.map +0 -1
  100. package/dist/chunk-QUUPYOSP.js.map +0 -1
  101. package/dist/chunk-R2GC6RLD.js +0 -344
  102. package/dist/chunk-R2GC6RLD.js.map +0 -1
  103. package/dist/chunk-R2YZTCLO.js.map +0 -1
  104. package/dist/chunk-S7A5D7ZJ.js +0 -174
  105. package/dist/chunk-S7A5D7ZJ.js.map +0 -1
  106. package/dist/chunk-TUWMK62B.js.map +0 -1
  107. package/dist/chunk-V543AI2F.js +0 -1
  108. package/dist/chunk-V543AI2F.js.map +0 -1
  109. package/dist/chunk-VR7UPJ7C.js.map +0 -1
  110. package/dist/chunk-VWCJ2WXC.js.map +0 -1
  111. package/dist/chunk-VYFRI7R6.js.map +0 -1
  112. package/dist/chunk-XNLB57UD.js.map +0 -1
  113. package/dist/chunk-ZLQKNOZQ.js +0 -1
  114. package/dist/chunk-ZLQKNOZQ.js.map +0 -1
  115. package/dist/doc/index.js.map +0 -1
  116. package/dist/generate/index.js.map +0 -1
  117. package/dist/icons/index.js.map +0 -1
  118. package/dist/icons/inlineIconMarker.js.map +0 -1
  119. package/dist/imageEdit/index.js.map +0 -1
  120. package/dist/index.js.map +0 -1
  121. package/dist/jsonForm/index.js.map +0 -1
  122. package/dist/markdown/index.js.map +0 -1
  123. package/dist/narration/index.js.map +0 -1
  124. package/dist/random/index.js.map +0 -1
  125. package/dist/recommend/index.js.map +0 -1
  126. package/dist/schemas/index.js.map +0 -1
  127. package/dist/spatial/index.js.map +0 -1
  128. package/dist/storage/index.js.map +0 -1
  129. package/dist/timing/index.js.map +0 -1
  130. package/dist/transform/index.js.map +0 -1
  131. package/dist/versions/index.js.map +0 -1
  132. package/src/__tests__/animationUtils.test.ts +0 -117
  133. package/src/__tests__/annotationCoercion.test.ts +0 -243
  134. package/src/__tests__/applyNarrationTiming.test.ts +0 -190
  135. package/src/__tests__/applyRenderStyle.test.ts +0 -146
  136. package/src/__tests__/asciiDiagramBattle.test.ts +0 -246
  137. package/src/__tests__/asciiDiagramDetect.test.ts +0 -162
  138. package/src/__tests__/asciiDiagramMapping.test.ts +0 -38
  139. package/src/__tests__/asciiDiagramParse.test.ts +0 -233
  140. package/src/__tests__/asciiDiagramPipeline.test.ts +0 -273
  141. package/src/__tests__/asciiDiagramRender.test.ts +0 -162
  142. package/src/__tests__/asciiDiagramRepair.test.ts +0 -84
  143. package/src/__tests__/asciiTimelineDetect.test.ts +0 -157
  144. package/src/__tests__/asciiTimelineParse.test.ts +0 -205
  145. package/src/__tests__/asciiTimelinePipeline.test.ts +0 -349
  146. package/src/__tests__/asciiTimelineRender.test.ts +0 -376
  147. package/src/__tests__/atmosphereLayers.test.ts +0 -108
  148. package/src/__tests__/attrTokens.test.ts +0 -167
  149. package/src/__tests__/colorUtils.test.ts +0 -112
  150. package/src/__tests__/contentContainer.test.ts +0 -325
  151. package/src/__tests__/contentExtractor.test.ts +0 -243
  152. package/src/__tests__/coverBlock.test.ts +0 -310
  153. package/src/__tests__/customTemplateSample.test.ts +0 -144
  154. package/src/__tests__/customTemplatesFrontmatter.test.ts +0 -221
  155. package/src/__tests__/customThemesFrontmatter.test.ts +0 -146
  156. package/src/__tests__/dataTable.test.ts +0 -145
  157. package/src/__tests__/diagramBlock.test.ts +0 -122
  158. package/src/__tests__/diagramLayout.test.ts +0 -134
  159. package/src/__tests__/diagramText.test.ts +0 -26
  160. package/src/__tests__/docToMarkdownMedia.test.ts +0 -83
  161. package/src/__tests__/drawing.test.ts +0 -109
  162. package/src/__tests__/drawingBlock.test.ts +0 -124
  163. package/src/__tests__/drawingLayout.test.ts +0 -171
  164. package/src/__tests__/fixtures/asciiDiagramBattle.ts +0 -512
  165. package/src/__tests__/fixtures/asciiDiagrams.ts +0 -287
  166. package/src/__tests__/fixtures/asciiTimelines.ts +0 -35
  167. package/src/__tests__/fixtures/treeviewFixtures.ts +0 -243
  168. package/src/__tests__/geohash.test.ts +0 -110
  169. package/src/__tests__/getLayers.test.ts +0 -243
  170. package/src/__tests__/getLayersFallback.test.ts +0 -103
  171. package/src/__tests__/haversine.test.ts +0 -63
  172. package/src/__tests__/iconResolve.test.ts +0 -122
  173. package/src/__tests__/imageEditExportSvg.test.ts +0 -70
  174. package/src/__tests__/imageEditState.test.ts +0 -74
  175. package/src/__tests__/imageEditVersions.test.ts +0 -243
  176. package/src/__tests__/inferDocumentTitle.test.ts +0 -50
  177. package/src/__tests__/inlineIconMarker.test.ts +0 -36
  178. package/src/__tests__/inputDescriptors.test.ts +0 -162
  179. package/src/__tests__/jsonForm.chooseControl.test.ts +0 -86
  180. package/src/__tests__/jsonForm.evaluateWhen.test.ts +0 -59
  181. package/src/__tests__/jsonForm.inferSchema.test.ts +0 -25
  182. package/src/__tests__/jsonForm.pointer.test.ts +0 -149
  183. package/src/__tests__/jsonForm.tokens.test.ts +0 -84
  184. package/src/__tests__/layoutBlock.test.ts +0 -83
  185. package/src/__tests__/layoutLayout.test.ts +0 -169
  186. package/src/__tests__/localForageAdapter.test.ts +0 -155
  187. package/src/__tests__/majorApiTypes.test.ts +0 -18
  188. package/src/__tests__/markdown.test.ts +0 -1009
  189. package/src/__tests__/markdownIcons.test.ts +0 -104
  190. package/src/__tests__/markdownSanitize.test.ts +0 -81
  191. package/src/__tests__/markdownToDoc.test.ts +0 -957
  192. package/src/__tests__/matchFontFamily.test.ts +0 -114
  193. package/src/__tests__/materializeBlockLayers.test.ts +0 -167
  194. package/src/__tests__/materializePageSections.test.ts +0 -404
  195. package/src/__tests__/materializeTestUtils.ts +0 -17
  196. package/src/__tests__/mediaAnnotations.test.ts +0 -91
  197. package/src/__tests__/mediaSchedule.test.ts +0 -118
  198. package/src/__tests__/narrationAlign.test.ts +0 -150
  199. package/src/__tests__/narrationFeatures.test.ts +0 -71
  200. package/src/__tests__/narrationNuclei.test.ts +0 -45
  201. package/src/__tests__/narrationPacing.test.ts +0 -189
  202. package/src/__tests__/narrationScript.test.ts +0 -149
  203. package/src/__tests__/narrationSessionRepro.test.ts +0 -62
  204. package/src/__tests__/narrationSidecar.test.ts +0 -88
  205. package/src/__tests__/narrationSyllables.test.ts +0 -65
  206. package/src/__tests__/narrationTestSignals.ts +0 -167
  207. package/src/__tests__/narrationVad.test.ts +0 -66
  208. package/src/__tests__/pageStyle.test.ts +0 -258
  209. package/src/__tests__/pandocAttrParse.test.ts +0 -187
  210. package/src/__tests__/recommendTemplates.test.ts +0 -183
  211. package/src/__tests__/resolveDocTheme.test.ts +0 -69
  212. package/src/__tests__/rootExports.test.ts +0 -61
  213. package/src/__tests__/scopedContentContainer.test.ts +0 -109
  214. package/src/__tests__/seededRandom.test.ts +0 -142
  215. package/src/__tests__/shapeGeometry.test.ts +0 -138
  216. package/src/__tests__/shapeVocabulary.test.ts +0 -133
  217. package/src/__tests__/storage.test.ts +0 -60
  218. package/src/__tests__/structuredData.test.ts +0 -249
  219. package/src/__tests__/surface.test.ts +0 -68
  220. package/src/__tests__/templateAnnotationParse.test.ts +0 -173
  221. package/src/__tests__/templateInputs.test.ts +0 -69
  222. package/src/__tests__/templateMetadata.test.ts +0 -32
  223. package/src/__tests__/templates.test.ts +0 -710
  224. package/src/__tests__/themeCompile.test.ts +0 -225
  225. package/src/__tests__/themeValidator.test.ts +0 -131
  226. package/src/__tests__/timing.test.ts +0 -167
  227. package/src/__tests__/transformProvenance.test.ts +0 -160
  228. package/src/__tests__/transformV2.test.ts +0 -163
  229. package/src/__tests__/transitionNormalize.test.ts +0 -61
  230. package/src/__tests__/treeviewBattle.test.ts +0 -76
  231. package/src/__tests__/treeviewDetect.test.ts +0 -168
  232. package/src/__tests__/treeviewParse.test.ts +0 -118
  233. package/src/__tests__/treeviewPipeline.test.ts +0 -183
  234. package/src/__tests__/treeviewRender.test.ts +0 -91
  235. package/src/__tests__/validateDoc.test.ts +0 -260
  236. package/src/__tests__/versions.test.ts +0 -459
  237. package/src/doc/annotationBlocks.ts +0 -117
  238. package/src/doc/applyNarrationTiming.ts +0 -244
  239. package/src/doc/asciiDiagram/chars.ts +0 -210
  240. package/src/doc/asciiDiagram/detect.ts +0 -175
  241. package/src/doc/asciiDiagram/index.ts +0 -38
  242. package/src/doc/asciiDiagram/mapping.ts +0 -225
  243. package/src/doc/asciiDiagram/parse.ts +0 -1095
  244. package/src/doc/asciiDiagram/render.ts +0 -963
  245. package/src/doc/asciiDiagram/repair.ts +0 -400
  246. package/src/doc/asciiDiagram/types.ts +0 -65
  247. package/src/doc/asciiTimeline/detect.ts +0 -138
  248. package/src/doc/asciiTimeline/index.ts +0 -26
  249. package/src/doc/asciiTimeline/mapping.ts +0 -43
  250. package/src/doc/asciiTimeline/parse.ts +0 -870
  251. package/src/doc/asciiTimeline/render.ts +0 -427
  252. package/src/doc/asciiTimeline/types.ts +0 -73
  253. package/src/doc/asciiTimeline/wrappedFlow.ts +0 -427
  254. package/src/doc/audioMapping.ts +0 -442
  255. package/src/doc/customTemplatesFrontmatter.ts +0 -273
  256. package/src/doc/customThemesFrontmatter.ts +0 -95
  257. package/src/doc/docToMarkdown.ts +0 -284
  258. package/src/doc/index.ts +0 -161
  259. package/src/doc/markdownToDoc.ts +0 -1054
  260. package/src/doc/materializeBlockLayers.ts +0 -465
  261. package/src/doc/mediaAnnotations.ts +0 -120
  262. package/src/doc/page/PageSection.ts +0 -174
  263. package/src/doc/page/materializePageSection.ts +0 -616
  264. package/src/doc/page/resolvePageBlock.ts +0 -108
  265. package/src/doc/page/sectionExtractors.ts +0 -466
  266. package/src/doc/pageCss.ts +0 -628
  267. package/src/doc/resolveDocTheme.ts +0 -56
  268. package/src/doc/standaloneAnnotation.ts +0 -58
  269. package/src/doc/structuredData.ts +0 -301
  270. package/src/doc/templateInputs.ts +0 -424
  271. package/src/doc/templates/__tests__/customTemplate.test.ts +0 -170
  272. package/src/doc/templates/__tests__/customTemplateRegistry.test.ts +0 -124
  273. package/src/doc/templates/__tests__/listBlock.test.ts +0 -64
  274. package/src/doc/templates/accentImage.ts +0 -362
  275. package/src/doc/templates/captionUtils.ts +0 -56
  276. package/src/doc/templates/comparisonBar.ts +0 -173
  277. package/src/doc/templates/coverBlock.ts +0 -255
  278. package/src/doc/templates/customTemplate.ts +0 -51
  279. package/src/doc/templates/dataTable.ts +0 -102
  280. package/src/doc/templates/dateEvent.ts +0 -147
  281. package/src/doc/templates/definitionCard.ts +0 -140
  282. package/src/doc/templates/diagramBlock.ts +0 -403
  283. package/src/doc/templates/diagramLayout.ts +0 -159
  284. package/src/doc/templates/drawingBlock.ts +0 -325
  285. package/src/doc/templates/drawingLayout.ts +0 -539
  286. package/src/doc/templates/factCard.ts +0 -146
  287. package/src/doc/templates/fallbackBlock.ts +0 -123
  288. package/src/doc/templates/featureBlock.ts +0 -209
  289. package/src/doc/templates/fullBleedQuote.ts +0 -83
  290. package/src/doc/templates/imageWithCaption.ts +0 -186
  291. package/src/doc/templates/index.ts +0 -642
  292. package/src/doc/templates/inputDescriptors.ts +0 -451
  293. package/src/doc/templates/layoutBlock.ts +0 -43
  294. package/src/doc/templates/layoutLayout.ts +0 -243
  295. package/src/doc/templates/listBlock.ts +0 -207
  296. package/src/doc/templates/mapBlock.ts +0 -138
  297. package/src/doc/templates/metadata.ts +0 -130
  298. package/src/doc/templates/persistentLayers.ts +0 -526
  299. package/src/doc/templates/photoGrid.ts +0 -190
  300. package/src/doc/templates/pullQuote.ts +0 -141
  301. package/src/doc/templates/quoteBlock.ts +0 -141
  302. package/src/doc/templates/registry.ts +0 -88
  303. package/src/doc/templates/sectionHeader.ts +0 -120
  304. package/src/doc/templates/statHighlight.ts +0 -146
  305. package/src/doc/templates/templateNames.ts +0 -22
  306. package/src/doc/templates/timelineBlock.ts +0 -613
  307. package/src/doc/templates/titleBlock.ts +0 -150
  308. package/src/doc/templates/tokens/__tests__/resolveTokens.test.ts +0 -487
  309. package/src/doc/templates/tokens/resolveTokens.ts +0 -453
  310. package/src/doc/templates/treeBlock.ts +0 -131
  311. package/src/doc/templates/twoColumn.ts +0 -263
  312. package/src/doc/templates/videoPullQuote.ts +0 -142
  313. package/src/doc/templates/videoWithCaption.ts +0 -135
  314. package/src/doc/treeview/chars.ts +0 -72
  315. package/src/doc/treeview/detect.ts +0 -145
  316. package/src/doc/treeview/index.ts +0 -30
  317. package/src/doc/treeview/mapping.ts +0 -95
  318. package/src/doc/treeview/parse.ts +0 -201
  319. package/src/doc/treeview/render.ts +0 -41
  320. package/src/doc/treeview/types.ts +0 -43
  321. package/src/doc/utils/animationUtils.ts +0 -399
  322. package/src/doc/utils/applyRenderStyle.ts +0 -106
  323. package/src/doc/utils/diagramText.ts +0 -78
  324. package/src/doc/utils/imageTreatment.ts +0 -70
  325. package/src/doc/utils/nearest.ts +0 -59
  326. package/src/doc/utils/shapeGeometry.ts +0 -614
  327. package/src/doc/utils/themeUtils.ts +0 -243
  328. package/src/doc/validate.ts +0 -575
  329. package/src/generate/contentExtractor.ts +0 -921
  330. package/src/generate/index.ts +0 -18
  331. package/src/generate/templateMapper.ts +0 -177
  332. package/src/icons/iconData.ts +0 -31
  333. package/src/icons/index.ts +0 -26
  334. package/src/icons/inlineIconMarker.ts +0 -73
  335. package/src/icons/resolve.ts +0 -139
  336. package/src/imageEdit/ImageEditVersionManager.ts +0 -73
  337. package/src/imageEdit/export.ts +0 -410
  338. package/src/imageEdit/index.ts +0 -72
  339. package/src/imageEdit/persistence.ts +0 -113
  340. package/src/imageEdit/state.ts +0 -112
  341. package/src/imageEdit/versionPaths.ts +0 -44
  342. package/src/imageEdit/versions.ts +0 -152
  343. package/src/index.ts +0 -15
  344. package/src/internal/immutable.ts +0 -58
  345. package/src/jsonForm/chooseControl.ts +0 -88
  346. package/src/jsonForm/evaluateWhen.ts +0 -59
  347. package/src/jsonForm/index.ts +0 -32
  348. package/src/jsonForm/inferSchema.ts +0 -25
  349. package/src/jsonForm/pointer.ts +0 -154
  350. package/src/jsonForm/tokens.ts +0 -78
  351. package/src/jsonForm/types.ts +0 -167
  352. package/src/markdown/annotationCoercion.ts +0 -295
  353. package/src/markdown/attrTokens.ts +0 -243
  354. package/src/markdown/convert.ts +0 -1353
  355. package/src/markdown/htmlParse.ts +0 -212
  356. package/src/markdown/index.ts +0 -152
  357. package/src/markdown/parse.ts +0 -103
  358. package/src/markdown/sanitize.ts +0 -318
  359. package/src/markdown/stringify.ts +0 -207
  360. package/src/markdown/types.ts +0 -710
  361. package/src/markdown/utils.ts +0 -459
  362. package/src/narration/align.ts +0 -514
  363. package/src/narration/features.ts +0 -231
  364. package/src/narration/index.ts +0 -86
  365. package/src/narration/nuclei.ts +0 -118
  366. package/src/narration/pacing.ts +0 -211
  367. package/src/narration/script.ts +0 -239
  368. package/src/narration/session.ts +0 -100
  369. package/src/narration/sidecar.ts +0 -187
  370. package/src/narration/syllables.ts +0 -85
  371. package/src/narration/trace.ts +0 -50
  372. package/src/narration/types.ts +0 -299
  373. package/src/narration/vad.ts +0 -131
  374. package/src/ngeohash.d.ts +0 -11
  375. package/src/random/SeededRandom.ts +0 -127
  376. package/src/random/index.ts +0 -1
  377. package/src/recommend/index.ts +0 -16
  378. package/src/recommend/numberHighlight.ts +0 -25
  379. package/src/recommend/templates.ts +0 -393
  380. package/src/schemas/BlockTemplates.ts +0 -1046
  381. package/src/schemas/CustomTemplates.ts +0 -126
  382. package/src/schemas/Doc.ts +0 -1073
  383. package/src/schemas/ImageEditDoc.ts +0 -102
  384. package/src/schemas/LayoutStrategy.ts +0 -178
  385. package/src/schemas/Media.ts +0 -179
  386. package/src/schemas/MediaProvider.ts +0 -70
  387. package/src/schemas/PageStyle.ts +0 -213
  388. package/src/schemas/Theme.ts +0 -413
  389. package/src/schemas/Transitions.ts +0 -224
  390. package/src/schemas/Types.ts +0 -15
  391. package/src/schemas/Viewport.ts +0 -91
  392. package/src/schemas/colorUtils.ts +0 -219
  393. package/src/schemas/fontStacks.ts +0 -339
  394. package/src/schemas/index.ts +0 -31
  395. package/src/schemas/pageStyleDefaults.ts +0 -204
  396. package/src/schemas/themeCompile.ts +0 -244
  397. package/src/schemas/themeConstants.ts +0 -2
  398. package/src/schemas/themeLibrary.ts +0 -60
  399. package/src/schemas/themeValidator.ts +0 -609
  400. package/src/schemas/themes/bold.json +0 -77
  401. package/src/schemas/themes/cinematic.json +0 -143
  402. package/src/schemas/themes/documentary.json +0 -125
  403. package/src/schemas/themes/gezellig.json +0 -123
  404. package/src/schemas/themes/index.ts +0 -53
  405. package/src/schemas/themes/magazine.json +0 -126
  406. package/src/schemas/themes/minimalist.json +0 -74
  407. package/src/schemas/themes/morning-light.json +0 -117
  408. package/src/schemas/themes/standard-dark.json +0 -109
  409. package/src/schemas/themes/standard.json +0 -98
  410. package/src/schemas/themes/tech-dark.json +0 -143
  411. package/src/schemas/themes/warm-earth.json +0 -74
  412. package/src/spatial/Geohash.ts +0 -196
  413. package/src/spatial/Haversine.ts +0 -59
  414. package/src/spatial/index.ts +0 -2
  415. package/src/storage/ContentContainer.ts +0 -220
  416. package/src/storage/LocalForageAdapter.ts +0 -103
  417. package/src/storage/LocalStorageAdapter.ts +0 -57
  418. package/src/storage/MediaProviderFromContainer.ts +0 -92
  419. package/src/storage/MemoryStorageAdapter.ts +0 -37
  420. package/src/storage/ScopedContentContainer.ts +0 -143
  421. package/src/storage/Storage.ts +0 -28
  422. package/src/storage/index.ts +0 -9
  423. package/src/timing/index.ts +0 -17
  424. package/src/timing/narrationTiming.ts +0 -220
  425. package/src/timing/readingTime.ts +0 -94
  426. package/src/transform/applyTransform.ts +0 -122
  427. package/src/transform/blockAnalyzer.ts +0 -181
  428. package/src/transform/index.ts +0 -23
  429. package/src/transform/registry.ts +0 -217
  430. package/src/transform/styles/dataDriven.ts +0 -18
  431. package/src/transform/styles/documentary.ts +0 -18
  432. package/src/transform/styles/index.ts +0 -5
  433. package/src/transform/styles/magazine.ts +0 -19
  434. package/src/transform/styles/minimal.ts +0 -18
  435. package/src/transform/styles/narrative.ts +0 -19
  436. package/src/transform/templateSelector.ts +0 -389
  437. package/src/transform/timingAllocator.ts +0 -257
  438. package/src/transform/types.ts +0 -158
  439. package/src/versions/DocumentVersionManager.ts +0 -70
  440. package/src/versions/gitignore.ts +0 -34
  441. package/src/versions/index.ts +0 -56
  442. package/src/versions/operations.ts +0 -144
  443. package/src/versions/paths.ts +0 -51
  444. package/src/versions/snapshotStore.ts +0 -202
  445. package/src/versions/timestamp.ts +0 -48
  446. package/src/versions/types.ts +0 -93
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/doc/utils/animationUtils.ts","../src/doc/utils/imageTreatment.ts","../src/doc/docToMarkdown.ts","../src/doc/resolveDocTheme.ts","../src/doc/page/resolvePageBlock.ts","../src/doc/page/sectionExtractors.ts","../src/doc/page/materializePageSection.ts","../src/doc/pageCss.ts","../src/doc/applyNarrationTiming.ts","../src/doc/audioMapping.ts","../src/doc/validate.ts","../src/doc/asciiDiagram/render.ts","../src/doc/asciiDiagram/repair.ts","../src/doc/asciiTimeline/render.ts","../src/doc/treeview/render.ts"],"sourcesContent":["/**\n * Animation Utilities\n *\n * Helper functions for mapping Doc animations to CSS classes and styles.\n * Generates the appropriate animation class names and CSS custom properties\n * for duration, delay, and easing.\n *\n * This is shared code used by both site and efb-app doc renderers.\n */\n\nimport type {\n Animation,\n AnimationType,\n TransitionDirection,\n TransitionType,\n} from '../../schemas/Doc.js';\n\ninterface AnimationResult {\n /** CSS class name to apply */\n className: string;\n /** Inline styles for CSS custom properties */\n style: Record<string, string>;\n}\n\n/**\n * Get CSS class and styles for an animation.\n */\nexport function getAnimationStyle(\n animation: Animation | undefined,\n _currentTime: number = 0,\n): AnimationResult {\n if (!animation || animation.type === 'none') {\n return { className: '', style: {} };\n }\n\n const className = getAnimationClassName(animation);\n const style = getAnimationCSSVars(animation);\n\n return { className, style };\n}\n\n/**\n * Map animation type to CSS class name.\n */\nfunction getAnimationClassName(animation: Animation): string {\n const { type, direction, panDirection } = animation;\n\n switch (type) {\n case 'fadeIn':\n return 'anim-fadeIn';\n case 'fadeOut':\n return 'anim-fadeOut';\n case 'slowZoom':\n // Slow zoom (Ken Burns style) has variants based on direction and pan\n if (panDirection === 'left') return 'anim-slowZoom-panLeft';\n if (panDirection === 'right') return 'anim-slowZoom-panRight';\n if (direction === 'out') return 'anim-slowZoom-out';\n return 'anim-slowZoom-in';\n case 'zoomIn':\n return 'anim-zoomIn';\n case 'zoomOut':\n return 'anim-zoomOut';\n case 'panLeft':\n return 'anim-panLeft';\n case 'panRight':\n return 'anim-panRight';\n case 'typewriter':\n return 'anim-typewriter';\n default:\n return '';\n }\n}\n\n/**\n * Generate CSS custom properties for animation timing.\n */\nfunction getAnimationCSSVars(animation: Animation): Record<string, string> {\n const vars: Record<string, string> = {};\n\n if (animation.duration !== undefined) {\n vars['--anim-duration'] = `${animation.duration}s`;\n }\n\n if (animation.delay !== undefined) {\n vars['--anim-delay'] = `${animation.delay}s`;\n }\n\n if (animation.easing) {\n vars['--anim-easing'] = animation.easing;\n }\n\n return vars;\n}\n\n/**\n * Get default duration for an animation type.\n */\nexport function getDefaultAnimationDuration(type: AnimationType): number {\n switch (type) {\n case 'slowZoom':\n case 'panLeft':\n case 'panRight':\n return 8; // Long, slow animations\n case 'typewriter':\n return 3;\n case 'fadeIn':\n case 'fadeOut':\n return 1;\n case 'zoomIn':\n case 'zoomOut':\n return 0.5;\n default:\n return 1;\n }\n}\n\n/**\n * Get transition class for slide entry/exit.\n */\nexport function getTransitionClass(\n type: TransitionType,\n entering: boolean,\n direction?: TransitionDirection,\n): string {\n if (type === 'cut') return '';\n const mode = entering ? 'enter' : 'exit';\n return `transition-${getTransitionVisualClass(type, direction)}-${mode}`;\n}\n\ntype TransitionVisualClass =\n | 'cut'\n | 'fade'\n | 'dissolve'\n | 'pushLeft'\n | 'pushRight'\n | 'pushUp'\n | 'pushDown'\n | 'wipeLeft'\n | 'wipeRight'\n | 'wipeUp'\n | 'wipeDown'\n | 'splitHorizontal'\n | 'splitVertical'\n | 'revealLeft'\n | 'revealRight'\n | 'revealUp'\n | 'revealDown'\n | 'random'\n | 'randomBarsHorizontal'\n | 'randomBarsVertical'\n | 'shapeCircle'\n | 'shapeDiamond'\n | 'shapePlus'\n | 'uncoverLeft'\n | 'uncoverRight'\n | 'uncoverUp'\n | 'uncoverDown'\n | 'coverLeft'\n | 'coverRight'\n | 'coverUp'\n | 'coverDown'\n | 'zoom'\n | 'panLeft'\n | 'panRight'\n | 'panUp'\n | 'panDown'\n | 'flash'\n | 'newsflash'\n | 'fallOver'\n | 'drape'\n | 'curtains'\n | 'wind'\n | 'prestige'\n | 'fracture'\n | 'crush'\n | 'peelOff'\n | 'pageCurl'\n | 'pageCurlDouble'\n | 'pageCurlSingle'\n | 'airplane'\n | 'origami'\n | 'checkerboard'\n | 'blindsHorizontal'\n | 'blindsVertical'\n | 'clock'\n | 'ripple'\n | 'honeycomb'\n | 'glitter'\n | 'vortex'\n | 'shred'\n | 'switch'\n | 'flip'\n | 'gallery'\n | 'cube'\n | 'doors'\n | 'box'\n | 'ferrisWheel'\n | 'conveyor'\n | 'rotate'\n | 'window'\n | 'orbit'\n | 'flyThrough'\n | 'morph'\n | 'combHorizontal'\n | 'combVertical'\n | 'pullLeft'\n | 'pullRight'\n | 'pullUp'\n | 'pullDown'\n | 'stripsLeft'\n | 'stripsRight'\n | 'stripsUp'\n | 'stripsDown'\n | 'wedge'\n | 'wheel'\n | 'wheelReverse'\n | 'prism'\n | 'warp'\n | 'slideLeft'\n | 'slideRight'\n | 'slideUp'\n | 'slideDown';\n\nconst TRANSITION_VISUAL_CLASS_BY_TYPE: Record<TransitionType, TransitionVisualClass> = {\n airplane: 'airplane',\n blinds: 'blindsHorizontal',\n box: 'box',\n checker: 'checkerboard',\n checkerboard: 'checkerboard',\n circle: 'shapeCircle',\n clock: 'clock',\n comb: 'combHorizontal',\n conveyor: 'conveyor',\n cover: 'coverLeft',\n crush: 'crush',\n cube: 'cube',\n curtains: 'curtains',\n cut: 'cut',\n diamond: 'shapeDiamond',\n dissolve: 'dissolve',\n doors: 'doors',\n drape: 'drape',\n fade: 'fade',\n fallOver: 'fallOver',\n ferris: 'ferrisWheel',\n ferrisWheel: 'ferrisWheel',\n flash: 'flash',\n flip: 'flip',\n flyThrough: 'flyThrough',\n flythrough: 'flyThrough',\n fracture: 'fracture',\n gallery: 'gallery',\n glitter: 'glitter',\n honeycomb: 'honeycomb',\n morph: 'morph',\n newsflash: 'newsflash',\n orbit: 'orbit',\n origami: 'origami',\n pageCurl: 'pageCurl',\n pageCurlDouble: 'pageCurlDouble',\n pageCurlSingle: 'pageCurlSingle',\n pan: 'panLeft',\n peelOff: 'peelOff',\n plus: 'shapePlus',\n prestige: 'prestige',\n prism: 'prism',\n pull: 'pullLeft',\n push: 'pushLeft',\n random: 'random',\n randomBar: 'randomBarsHorizontal',\n randomBars: 'randomBarsVertical',\n reveal: 'revealLeft',\n ripple: 'ripple',\n rotate: 'rotate',\n shape: 'shapeCircle',\n shred: 'shred',\n slideDown: 'slideDown',\n slideLeft: 'slideLeft',\n slideRight: 'slideRight',\n slideUp: 'slideUp',\n split: 'splitHorizontal',\n strips: 'stripsLeft',\n switch: 'switch',\n uncover: 'uncoverLeft',\n vortex: 'vortex',\n warp: 'warp',\n wedge: 'wedge',\n wheel: 'wheel',\n wheelReverse: 'wheelReverse',\n wind: 'wind',\n window: 'window',\n wipe: 'wipeLeft',\n zoom: 'zoom',\n};\n\nfunction getTransitionVisualClass(\n type: TransitionType,\n direction?: TransitionDirection,\n): TransitionVisualClass {\n switch (type) {\n case 'randomBars':\n case 'randomBar':\n return axisClass('randomBars', direction, type === 'randomBar' ? 'Horizontal' : 'Vertical');\n case 'comb':\n return axisClass('comb', direction, 'Horizontal');\n case 'blinds':\n return axisClass('blinds', direction, 'Horizontal');\n case 'split':\n return axisClass('split', direction, 'Horizontal');\n case 'push':\n return directionalClass('push', direction, 'Left');\n case 'wipe':\n return directionalClass('wipe', direction, 'Left');\n case 'cover':\n return directionalClass('cover', direction, 'Left');\n case 'uncover':\n return directionalClass('uncover', direction, 'Left');\n case 'pull':\n return directionalClass('pull', direction, 'Left');\n case 'reveal':\n return directionalClass('reveal', direction, 'Left');\n case 'strips':\n return directionalClass('strips', direction, 'Left');\n case 'pan':\n return directionalClass('pan', direction, 'Left');\n default:\n return TRANSITION_VISUAL_CLASS_BY_TYPE[type];\n }\n}\n\nfunction directionalClass(\n prefix: 'cover' | 'pan' | 'pull' | 'push' | 'reveal' | 'strips' | 'uncover' | 'wipe',\n direction: TransitionDirection | undefined,\n fallback: 'Left' | 'Right' | 'Up' | 'Down',\n): TransitionVisualClass {\n const suffix = directionSuffix(direction, fallback);\n return `${prefix}${suffix}` as TransitionVisualClass;\n}\n\nfunction axisClass(\n prefix: 'blinds' | 'comb' | 'randomBars' | 'split',\n direction: TransitionDirection | undefined,\n fallback: 'Horizontal' | 'Vertical',\n): TransitionVisualClass {\n const suffix = axisSuffix(direction, fallback);\n return `${prefix}${suffix}` as TransitionVisualClass;\n}\n\nfunction directionSuffix(\n direction: TransitionDirection | undefined,\n fallback: 'Left' | 'Right' | 'Up' | 'Down',\n): 'Left' | 'Right' | 'Up' | 'Down' {\n switch (direction) {\n case 'right':\n return 'Right';\n case 'up':\n return 'Up';\n case 'down':\n return 'Down';\n case 'left':\n default:\n return fallback;\n }\n}\n\nfunction axisSuffix(\n direction: TransitionDirection | undefined,\n fallback: 'Horizontal' | 'Vertical',\n): 'Horizontal' | 'Vertical' {\n switch (direction) {\n case 'vertical':\n case 'up':\n case 'down':\n return 'Vertical';\n case 'horizontal':\n case 'left':\n case 'right':\n return 'Horizontal';\n default:\n return fallback;\n }\n}\n\n/**\n * Calculate animation progress (0-1) based on current time.\n */\nexport function getAnimationProgress(\n animation: Animation,\n currentTime: number,\n slideDuration: number,\n): number {\n const delay = animation.delay || 0;\n const duration = animation.duration || slideDuration;\n\n if (currentTime < delay) return 0;\n if (currentTime >= delay + duration) return 1;\n\n return (currentTime - delay) / duration;\n}\n","/**\n * Image treatment → CSS filter derivation.\n *\n * Treatments are theme-level photographic grades (see `ImageTreatment` in\n * [Doc.ts](../../schemas/Doc.ts)). They compile to plain CSS `filter`\n * functions so the same string works on a foreignObject `<img>`, an SVG\n * `<image>` element, and in headless frame capture — no SVG filter defs to\n * coordinate, no renderer-specific code paths.\n */\n\nimport type { ImageTreatment } from '../../schemas/Doc.js';\nimport { hexHueDegrees } from '../../schemas/colorUtils.js';\n\n/** Sepia's intrinsic tint hue (deg) — duotone rotates from here to the target. */\nconst SEPIA_HUE_DEGREES = 40;\n\nconst clamp01 = (v: number) => Math.max(0, Math.min(1, v));\nconst r2 = (v: number) => Math.round(v * 100) / 100;\n\n/**\n * Build the CSS `filter` value for a treatment and/or blur.\n * Returns `undefined` when there is nothing to apply.\n */\nexport function cssFilterForTreatment(\n treatment?: ImageTreatment,\n blur?: number,\n): string | undefined {\n const parts: string[] = [];\n\n if (blur != null && blur > 0) {\n parts.push(`blur(${Math.round(blur)}px)`);\n }\n\n if (treatment && treatment.type !== 'none') {\n const s = clamp01(treatment.strength ?? 0.6);\n switch (treatment.type) {\n case 'mono':\n // Archival black & white with a whisper of contrast to keep depth.\n parts.push(`grayscale(${r2(s)})`, `contrast(${r2(1 + 0.05 * s)})`);\n break;\n case 'duotone': {\n // Classic CSS duotone approximation: flatten to gray, tint through\n // sepia (intrinsic hue ~40°), rotate to the target hue, re-saturate.\n const hue = hexHueDegrees(treatment.color ?? '#3d5a80');\n parts.push(\n 'grayscale(1)',\n `sepia(${r2(Math.max(0.35, s))})`,\n `hue-rotate(${Math.round(hue - SEPIA_HUE_DEGREES)}deg)`,\n `saturate(${r2(1 + s)})`,\n );\n break;\n }\n case 'warm':\n // Partial sepia is a well-behaved warmer; slight saturation lift.\n parts.push(`sepia(${r2(0.4 * s)})`, `saturate(${r2(1 + 0.15 * s)})`);\n break;\n case 'cool':\n // Desaturate a touch and nudge warm tones toward magenta/blue —\n // small rotations read as a grade, large ones wreck hues.\n parts.push(\n `saturate(${r2(1 - 0.25 * s)})`,\n `hue-rotate(${Math.round(-12 * s)}deg)`,\n `contrast(${r2(1 + 0.06 * s)})`,\n );\n break;\n }\n }\n\n return parts.length > 0 ? parts.join(' ') : undefined;\n}\n","/**\n * Doc → Markdown Conversion\n *\n * Converts a Doc with a heading-driven Block hierarchy back into a\n * MarkdownDocument. This is the reverse of markdownToDoc() and enables\n * round-tripping: edit a Doc's block tree, then serialize back to markdown.\n *\n * **Algorithm:**\n * Walk the block tree depth-first. For each block:\n * 1. If it has a `sourceHeading`, emit that heading node\n * 2. Emit all nodes in `contents`\n * 3. Recurse into `children`\n *\n * @example\n * ```ts\n * import { markdownToDoc, docToMarkdown } from '@bendyline/squisq/doc';\n * import { parseMarkdown, stringifyMarkdown } from '@bendyline/squisq/markdown';\n *\n * const md = '# Hello\\n\\nWorld\\n';\n * const doc = markdownToDoc(parseMarkdown(md));\n * const roundTripped = stringifyMarkdown(docToMarkdown(doc));\n * ```\n */\n\nimport type { Doc, Block } from '../schemas/Doc.js';\nimport type { MediaClip } from '../schemas/Media.js';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownHeading,\n MarkdownParagraph,\n} from '../markdown/types.js';\nimport { serializeAnnotation } from '../markdown/attrTokens.js';\nimport { flattenBlocks } from './markdownToDoc.js';\nimport {\n FRONTMATTER_CUSTOM_TEMPLATES_KEY,\n writeCustomTemplatesToFrontmatter,\n} from './customTemplatesFrontmatter.js';\nimport {\n FRONTMATTER_CUSTOM_THEMES_KEY,\n writeCustomThemesToFrontmatter,\n} from './customThemesFrontmatter.js';\n\nconst TRANSITION_PARAM_KEYS = ['transition', 'transitionDuration', 'transitionDirection'] as const;\n\n/**\n * Convert a Doc with heading-driven blocks back to a MarkdownDocument.\n *\n * Walks the block tree depth-first, emitting heading nodes and contents\n * in document order. Blocks without a `sourceHeading` (preamble blocks)\n * emit only their contents.\n *\n * If a block has a `template` or `templateOverrides` that aren't already\n * reflected in the heading's `templateAnnotation`, the annotation is\n * injected so the round-trip preserves template assignments.\n *\n * @param doc - A Doc whose blocks may have `sourceHeading`, `contents`, and `children`\n * @returns A MarkdownDocument that can be stringified back to markdown\n */\nexport function docToMarkdown(doc: Doc): MarkdownDocument {\n const children: MarkdownBlockNode[] = [];\n\n // Media clips were LIFTED out of block contents at parse time\n // (`extractMediaFromContents`); re-insert their authoring annotations so\n // the round-trip doesn't silently drop narration/clip references.\n // Doc-anchored clips whose home block still exists ride back into that\n // block's body; homeless ones (programmatic clips, or a preamble block\n // that was dropped once emptied) emit at the document top — the\n // canonical authored position.\n const blockIds = new Set(flattenBlocks(doc.blocks).map((b) => b.id));\n const docMediaByBlock = new Map<string, MediaClip[]>();\n const homelessDocMedia: MediaClip[] = [];\n for (const clip of doc.documentMedia ?? []) {\n if (clip.origin && blockIds.has(clip.origin.blockId)) {\n const list = docMediaByBlock.get(clip.origin.blockId) ?? [];\n list.push(clip);\n docMediaByBlock.set(clip.origin.blockId, list);\n } else {\n homelessDocMedia.push(clip);\n }\n }\n for (const clip of homelessDocMedia) {\n children.push(synthesizeMediaParagraph(clip));\n }\n\n function emitBlock(block: Block): void {\n // Emit the heading node if present\n if (block.sourceHeading) {\n const heading = ensureAnnotation(block, block.sourceHeading);\n children.push(heading);\n } else if (block.standaloneAnnotation) {\n // Heading-less standalone block: re-emit its `{[…]}` annotation as a\n // paragraph before its contents. The serializer's quoting is paired\n // with the tokenizer, and stringifyMarkdown un-escapes `{[…]}` spans,\n // so the annotation round-trips.\n children.push(synthesizeAnnotationParagraph(block));\n }\n\n // Emit body content, with this block's media annotations re-inserted\n // at their original positions. `origin.index` refers to the ORIGINAL\n // contents array (which included every annotation), so ascending\n // insertion into the stripped contents reproduces the source order.\n const clips = [...(block.media ?? []), ...(docMediaByBlock.get(block.id) ?? [])];\n if (clips.length > 0) {\n const contents = [...(block.contents ?? [])];\n const anchored = clips\n .filter((clip) => clip.origin)\n .sort((a, b) => a.origin!.index - b.origin!.index);\n for (const clip of anchored) {\n contents.splice(\n Math.min(clip.origin!.index, contents.length),\n 0,\n synthesizeMediaParagraph(clip),\n );\n }\n // Origin-less block clips (programmatic) sit right under the heading.\n for (const clip of clips.filter((c) => !c.origin).reverse()) {\n contents.unshift(synthesizeMediaParagraph(clip));\n }\n children.push(...contents);\n } else if (block.contents) {\n children.push(...block.contents);\n }\n\n // Recurse into children (sub-headings)\n if (block.children) {\n for (const child of block.children) {\n emitBlock(child);\n }\n }\n }\n\n for (const block of doc.blocks) {\n emitBlock(block);\n }\n\n // Merge `Doc.customTemplates` into the outgoing frontmatter so the\n // markdown remains the source-of-truth: edits made via the editor's\n // TemplateDesigner round-trip through `docToMarkdown` →\n // `stringifyMarkdown` and are visible to anyone reading the file.\n const customPayload = writeCustomTemplatesToFrontmatter(doc.customTemplates);\n let frontmatter = doc.frontmatter;\n if (customPayload) {\n frontmatter = { ...(frontmatter ?? {}), [FRONTMATTER_CUSTOM_TEMPLATES_KEY]: customPayload };\n } else if (frontmatter && FRONTMATTER_CUSTOM_TEMPLATES_KEY in frontmatter) {\n // The doc has no custom templates anymore — drop the stale\n // frontmatter key so the markdown reflects the current state.\n const { [FRONTMATTER_CUSTOM_TEMPLATES_KEY]: _drop, ...rest } = frontmatter;\n void _drop;\n frontmatter = rest;\n }\n\n // Mirror the same round-trip for `Doc.customThemes` (the theme analog).\n const customThemesPayload = writeCustomThemesToFrontmatter(doc.customThemes);\n if (customThemesPayload) {\n frontmatter = { ...(frontmatter ?? {}), [FRONTMATTER_CUSTOM_THEMES_KEY]: customThemesPayload };\n } else if (frontmatter && FRONTMATTER_CUSTOM_THEMES_KEY in frontmatter) {\n const { [FRONTMATTER_CUSTOM_THEMES_KEY]: _dropTheme, ...rest } = frontmatter;\n void _dropTheme;\n frontmatter = rest;\n }\n\n return {\n type: 'document',\n children,\n ...(frontmatter && Object.keys(frontmatter).length > 0 ? { frontmatter } : {}),\n };\n}\n\n/**\n * Build the synthesized annotation paragraph for a heading-less standalone\n * block: `{[templateName key=value …]}` from its `sourceAnnotation.template`\n * and current `templateOverrides` (edits round-trip through the latter).\n */\nfunction synthesizeAnnotationParagraph(block: Block): MarkdownParagraph {\n const text = serializeAnnotation(block.sourceAnnotation?.template, block.templateOverrides);\n return { type: 'paragraph', children: [{ type: 'text', value: text }] };\n}\n\n/**\n * Re-synthesize the authoring paragraph for a media clip. The extraction\n * kept the exact source text (`origin.raw`) — emit it verbatim so quoting,\n * param order, and `mm:ss` time forms stay byte-stable. Programmatic clips\n * (no raw) serialize canonically: src, anchor, then timing params.\n */\nfunction synthesizeMediaParagraph(clip: MediaClip): MarkdownParagraph {\n if (clip.origin?.raw) {\n return { type: 'paragraph', children: [{ type: 'text', value: clip.origin.raw }] };\n }\n const params: Record<string, string> = { src: clip.src };\n if (clip.anchor === 'document') params.anchor = 'document';\n if (clip.startAt) params.startAt = String(clip.startAt);\n if (clip.clipStart != null) params.clipStart = String(clip.clipStart);\n if (clip.clipEnd != null) params.clipEnd = String(clip.clipEnd);\n if (clip.spillover) params.spillover = 'true';\n return {\n type: 'paragraph',\n children: [{ type: 'text', value: serializeAnnotation(clip.kind, params) }],\n };\n}\n\n/**\n * Ensure the heading's `templateAnnotation` reflects the block's\n * template and templateOverrides. Returns a (possibly cloned) heading.\n */\nfunction ensureAnnotation(block: Block, heading: MarkdownHeading): MarkdownHeading {\n const { attributes, transitionParams } = ensureTransitionMetadata(block, heading);\n\n // If the block has a non-default template or overrides, inject an annotation\n const hasExplicitTemplate =\n block.template && block.template !== 'sectionHeader' && block.autoTemplate !== true;\n const hasOverrides = block.templateOverrides && Object.keys(block.templateOverrides).length > 0;\n\n let templateAnnotation = heading.templateAnnotation;\n if (!templateAnnotation && (hasExplicitTemplate || hasOverrides || transitionParams)) {\n templateAnnotation = {\n ...(hasExplicitTemplate ? { template: block.template ?? 'sectionHeader' } : {}),\n ...(hasOverrides ? { params: block.templateOverrides } : {}),\n };\n }\n\n if (transitionParams) {\n templateAnnotation = {\n ...(templateAnnotation ?? {}),\n params: {\n ...(templateAnnotation?.params ?? {}),\n ...transitionParams,\n },\n };\n }\n\n if (attributes === heading.attributes && templateAnnotation === heading.templateAnnotation) {\n return heading;\n }\n\n return { ...heading, children: [...heading.children], attributes, templateAnnotation };\n}\n\nfunction ensureTransitionMetadata(\n block: Block,\n heading: MarkdownHeading,\n): {\n attributes: MarkdownHeading['attributes'];\n transitionParams: Record<string, string> | undefined;\n} {\n const transition = block.transition;\n if (!transition) {\n return { attributes: heading.attributes, transitionParams: undefined };\n }\n\n // The transition is written to the squisq-native `{[…]}` params for\n // author-facing markdown, and to `attributes.blockMeta` for the in-memory\n // Doc → MarkdownDocument → Doc path (which does not re-parse string params).\n const attrs = removeTransitionParams(heading.attributes) ?? {};\n const attributes = {\n ...attrs,\n blockMeta: {\n ...(attrs.blockMeta ?? {}),\n transition,\n },\n };\n return {\n attributes,\n transitionParams: {\n transition: transition.type,\n ...(transition.duration !== undefined\n ? { transitionDuration: String(transition.duration) }\n : {}),\n ...(transition.direction ? { transitionDirection: transition.direction } : {}),\n },\n };\n}\n\nfunction removeTransitionParams(\n attrs: MarkdownHeading['attributes'],\n): MarkdownHeading['attributes'] {\n if (!attrs?.params) return attrs;\n const params = { ...attrs.params };\n for (const key of TRANSITION_PARAM_KEYS) delete params[key];\n return {\n ...attrs,\n ...(Object.keys(params).length > 0 ? { params } : { params: undefined }),\n };\n}\n","/**\n * Doc-scoped theme resolution.\n *\n * The theme analog of how `buildRegistry` resolves custom templates: pure and\n * doc-scoped, with no global state. `resolveThemeForDoc` looks up the active\n * theme id in the doc's own custom themes first, then falls back to an\n * optional caller-owned registry, then built-ins via `resolveTheme`.\n *\n * It accepts either a squisq `Doc` (which carries a typed `customThemes`\n * array) or anything with raw `frontmatter` — notably a `MarkdownDocument`,\n * which is the shape every export pipeline pivots through. In the latter case\n * the inline themes are decoded from the `squisq-custom-themes` frontmatter\n * payload. Inline custom themes ship with the doc, exactly like custom\n * templates; host-level themes can be supplied through an explicit registry.\n */\n\nimport type { Theme, ThemeRegistry } from '../schemas/Theme.js';\nimport { resolveTheme } from '../schemas/themeLibrary.js';\nimport { readFrontmatterThemeId } from '../markdown/utils.js';\nimport { readCustomThemesFromFrontmatter } from './customThemesFrontmatter.js';\n\n/**\n * The minimal shape `resolveThemeForDoc` needs. Satisfied by both the squisq\n * `Doc` (typed `customThemes` + `themeId`) and a `MarkdownDocument` (raw\n * `frontmatter` carrying the encoded payload).\n */\nexport interface ThemeResolvable {\n themeId?: string;\n customThemes?: Theme[];\n frontmatter?: Record<string, unknown>;\n}\n\n/**\n * Resolve the Theme a document should render with.\n *\n * @param doc - the document (may carry inline custom themes plus a `themeId`\n * / `squisq-theme` frontmatter selector).\n * @param explicitId - an id that overrides the doc's own selection (e.g. the\n * editor's theme dropdown, or an export `--theme` option). When omitted, the\n * doc's `themeId` / frontmatter theme id is used.\n * @returns the matching inline custom theme (doc-scoped) when present, else\n * the caller-registry or built-in theme for that id, else the default theme.\n */\nexport function resolveThemeForDoc(\n doc: ThemeResolvable | null | undefined,\n explicitId?: string,\n registry?: ThemeRegistry,\n): Theme {\n const id = explicitId ?? doc?.themeId ?? readFrontmatterThemeId(doc?.frontmatter);\n // Prefer the already-parsed list on a squisq Doc; otherwise decode the\n // frontmatter payload (the shape exports see on a MarkdownDocument).\n const inline = doc?.customThemes ?? readCustomThemesFromFrontmatter(doc?.frontmatter);\n const custom = id ? inline?.find((t) => t.id === id) : undefined;\n if (custom) return custom;\n return resolveTheme(id, registry);\n}\n","/**\n * Resolve a doc block into the typed template input the page pipeline\n * (and the SVG canvas embed) should render.\n *\n * This is the block-input merge that previously lived inline in\n * `LinearDocView` — hoisted into core so the React page view, the string\n * HTML exporter, and tests share one derivation:\n *\n * - Authored blocks with a heading `{[template]}` annotation derive typed\n * inputs from the heading/body (`deriveTemplateInputs` with placeholders),\n * then overlay `templateData` and coerced annotation params / overrides.\n * - Auto-templated blocks (`block.autoTemplate`) already carry derived\n * `templateData`; same overlay applies.\n * - Transform-generated blocks (no `sourceHeading`) already ARE typed\n * template inputs; overlay `templateData` / overrides like\n * `materializeBlockLayers` does.\n * - Everything else is prose.\n */\n\nimport type { Block } from '../../schemas/Doc.js';\nimport type { DocBlock, TemplateBlock } from '../../schemas/BlockTemplates.js';\nimport { isTemplateBlock } from '../../schemas/BlockTemplates.js';\nimport { extractPlainText } from '../../markdown/utils.js';\nimport { deriveTemplateInputs } from '../templateInputs.js';\nimport { coerceTemplateParams } from '../templates/inputDescriptors.js';\nimport { resolveTemplateName } from '../templates/templateNames.js';\n\n/** The page pipeline's view of one block. */\nexport interface ResolvedPageBlock {\n /** True when the block renders as a typed section (not prose). */\n templated: boolean;\n /** Canonical template id (post-alias). Only when `templated`. */\n templateName?: string;\n /**\n * Fully merged typed template input, ready for a section extractor or\n * `materializeBlockLayers`. Only when `templated`.\n */\n templateBlock?: TemplateBlock;\n}\n\n/**\n * True when the block should render as a typed template section in Page\n * mode: heading annotation, content-aware auto template, or a template\n * block without authoring nodes (transform output, standalone annotation).\n */\nexport function isTemplatedPageBlock(block: Block): boolean {\n if (block.sourceHeading?.templateAnnotation?.template) return true;\n if (block.autoTemplate && block.template) return true;\n return !block.sourceHeading && isTemplateBlock(block as DocBlock);\n}\n\n/** Template id as authored (pre-alias), when the block is templated. */\nfunction templatedName(block: Block): string | undefined {\n return block.sourceHeading?.templateAnnotation?.template ?? block.template;\n}\n\n/**\n * Merge a block into its typed template input. Mirrors the merge order\n * `materializeBlockLayers` applies at execution time:\n * derived inputs → `templateData` → coerced annotation params/overrides.\n */\nexport function resolvePageBlock(block: Block): ResolvedPageBlock {\n if (!isTemplatedPageBlock(block)) return { templated: false };\n\n const annotation = block.sourceHeading?.templateAnnotation;\n const rawName = templatedName(block) ?? 'sectionHeader';\n const templateName = resolveTemplateName(rawName);\n\n const rawParams: Record<string, string> = {\n ...(annotation?.params ?? {}),\n ...(block.templateOverrides ?? {}),\n };\n const coercedParams = coerceTemplateParams(rawName, rawParams).input;\n\n let base: Record<string, unknown>;\n if (annotation) {\n const headingText = extractPlainText(block.sourceHeading!);\n base = {\n id: block.id,\n template: rawName,\n startTime: 0,\n duration: 1,\n audioSegment: 0,\n title: headingText,\n contents: block.contents,\n children: block.children,\n ...(deriveTemplateInputs(rawName, headingText, block.contents, {\n placeholders: true,\n }) ?? {}),\n };\n } else {\n base = {\n ...block,\n startTime: block.startTime ?? 0,\n duration: block.duration ?? 1,\n audioSegment: block.audioSegment ?? 0,\n template: rawName,\n };\n }\n\n const templateBlock = {\n ...base,\n ...(block.templateData ?? {}),\n ...coercedParams,\n } as unknown as TemplateBlock;\n\n return { templated: true, templateName, templateBlock };\n}\n","/**\n * Per-template section extractors — the page analog of the SVG template\n * registry. Each extractor maps one typed template input onto a\n * `PageSection` draft: a section kind, a variant, and filled content slots.\n *\n * Inherently spatial templates (diagram/tree/timeline/map/drawing/layout)\n * become `canvas-embed` drafts that carry the merged template block; the\n * SVG pipeline renders those internally (including their own titles), so\n * canvas drafts deliberately leave the text slots empty.\n *\n * The registry is total over the built-in template registry — a coverage\n * test asserts every registered template id resolves to an extractor.\n */\n\nimport type { Block } from '../../schemas/Doc.js';\nimport type {\n AccentImage,\n ComparisonBarInput,\n DataTableInput,\n DateEventInput,\n DefinitionCardInput,\n FactCardInput,\n FullBleedQuoteInput,\n ImageWithCaptionInput,\n LeftFeatureInput,\n ListBlockInput,\n PhotoGridInput,\n PullQuoteInput,\n QuoteBlockInput,\n RightFeatureInput,\n SectionHeaderInput,\n StatHighlightInput,\n TemplateBlock,\n TitleBlockInput,\n TwoColumnInput,\n VideoPullQuoteInput,\n VideoWithCaptionInput,\n} from '../../schemas/BlockTemplates.js';\nimport type { MarkdownBlockNode } from '../../markdown/types.js';\nimport { extractPlainText } from '../../markdown/utils.js';\nimport type { PageEmphasis } from '../../schemas/PageStyle.js';\nimport type { PageMedia, PageRichText, PageSection, PageSpatialKind } from './PageSection.js';\n\n/** Extraction context passed to each extractor. */\nexport interface PageSectionContext {\n /** The source block (for canvas embeds and ids). */\n block: Block;\n /** Aspect reference for canvas embeds. */\n viewport: { width: number; height: number };\n}\n\n/** What an extractor produces before the art-direction pass. */\nexport interface PageSectionDraft {\n kind: PageSection['kind'];\n variant?: string;\n slots: PageSection['slots'];\n /** Suggested emphasis (default 'standard'); art direction may override. */\n emphasis?: PageEmphasis;\n /** True when the section sits on its own full-bleed media background. */\n mediaBackground?: boolean;\n /** Block-authored color-scheme name — wins over theme accent rotation. */\n colorScheme?: string;\n hints?: Record<string, string | number | boolean>;\n}\n\nexport type SectionExtractor = (input: TemplateBlock, ctx: PageSectionContext) => PageSectionDraft;\n\n/** Rich text from the merged input's body contents, when it has any. */\nfunction bodyRichText(input: TemplateBlock): PageRichText | undefined {\n const contents = (input as unknown as { contents?: MarkdownBlockNode[] }).contents;\n if (!contents || contents.length === 0) return undefined;\n const text = contents\n .map((node) => extractPlainText(node))\n .join('\\n')\n .trim();\n return text ? { text, markdown: contents } : undefined;\n}\n\nfunction accentImageMedia(accent?: AccentImage): PageMedia | undefined {\n if (!accent?.src) return undefined;\n return {\n type: 'image',\n src: accent.src,\n alt: accent.alt ?? '',\n credit: accent.credit,\n license: accent.license,\n };\n}\n\n/** Build a canvas-embed draft around the merged template block. */\nfunction canvasDraft(\n spatial: PageSpatialKind,\n ctx: PageSectionContext,\n block?: Block,\n): PageSectionDraft {\n return {\n kind: 'canvas-embed',\n variant: spatial,\n slots: {\n media: {\n type: 'canvas',\n spatial,\n block: block ?? ctx.block,\n aspect: { width: ctx.viewport.width, height: ctx.viewport.height },\n },\n },\n };\n}\n\nconst title: SectionExtractor = (input) => {\n const t = input as TitleBlockInput;\n // The slide template ignores body content (a title card's body only feeds\n // narration), but on a page that text would be silently lost — fall back\n // to the block's first paragraph as the hero subtitle.\n const contents = (input as unknown as { contents?: MarkdownBlockNode[] }).contents;\n const firstParagraph = contents?.find((node) => node.type === 'paragraph');\n const subtitle = t.subtitle ?? (firstParagraph ? extractPlainText(firstParagraph) : undefined);\n return {\n kind: 'hero',\n variant: 'title',\n slots: { title: t.title, subtitle },\n emphasis: 'lead',\n hints: t.backgroundColor ? { backgroundColor: t.backgroundColor } : undefined,\n };\n};\n\nconst sectionHeader: SectionExtractor = (input) => {\n const s = input as SectionHeaderInput;\n const media: PageMedia | undefined = s.imageSrc\n ? { type: 'image', src: s.imageSrc, alt: s.imageAlt ?? '' }\n : undefined;\n return {\n kind: 'banner',\n slots: { title: s.title, media },\n colorScheme: s.colorScheme,\n mediaBackground: !!s.imageSrc,\n };\n};\n\nconst statHighlight: SectionExtractor = (input) => {\n const s = input as StatHighlightInput;\n return {\n kind: 'stat-band',\n variant: 'single',\n slots: {\n items: [{ value: s.stat, title: s.description, body: s.detail }],\n media: accentImageMedia(s.accentImage),\n },\n emphasis: 'strong',\n colorScheme: s.colorScheme,\n };\n};\n\nconst quote: SectionExtractor = (input) => {\n const q = input as QuoteBlockInput;\n return {\n kind: 'quote-band',\n variant: 'plain',\n slots: {\n body: { text: q.quote ?? '' },\n attribution: q.attribution,\n media: accentImageMedia(q.accentImage),\n },\n };\n};\n\nconst factCard: SectionExtractor = (input) => {\n const f = input as FactCardInput;\n return {\n kind: 'callout',\n variant: 'fact',\n slots: {\n title: f.fact,\n body: { text: f.explanation ?? '' },\n meta: f.source,\n media: accentImageMedia(f.accentImage),\n },\n };\n};\n\nconst twoColumn: SectionExtractor = (input) => {\n const t = input as TwoColumnInput;\n return {\n kind: 'card-grid',\n variant: 'two-column',\n slots: {\n title: t.header,\n items: [\n { title: t.left?.label, body: t.left?.sublabel, accentScheme: t.leftColor },\n { title: t.right?.label, body: t.right?.sublabel, accentScheme: t.rightColor },\n ],\n },\n };\n};\n\nconst dateEvent: SectionExtractor = (input) => {\n const d = input as DateEventInput;\n return {\n kind: 'timeline-rail',\n slots: {\n milestone: {\n date: d.date ?? '',\n description: d.description ?? '',\n footer: d.footer,\n mood: d.mood,\n },\n media: accentImageMedia(d.accentImage),\n },\n };\n};\n\nconst imageWithCaption: SectionExtractor = (input) => {\n const i = input as ImageWithCaptionInput;\n const media: PageMedia = {\n type: 'image',\n src: i.imageSrc,\n alt: i.imageAlt ?? '',\n credit: i.imageCredit,\n license: i.imageLicense,\n };\n if (i.isTitle) {\n return {\n kind: 'hero',\n variant: 'media',\n slots: { title: i.caption, subtitle: i.subtitle, media },\n emphasis: 'lead',\n mediaBackground: true,\n };\n }\n return {\n kind: 'media-figure',\n variant: 'image',\n slots: { media, caption: i.caption },\n };\n};\n\nfunction featureDraft(\n input: LeftFeatureInput | RightFeatureInput,\n side: 'left' | 'right',\n): PageSectionDraft {\n return {\n kind: 'feature-split',\n variant: side === 'left' ? 'media-left' : 'media-right',\n slots: {\n title: input.title,\n body: input.body ? { text: input.body } : undefined,\n media: {\n type: 'image',\n src: input.imageSrc,\n alt: input.imageAlt ?? '',\n width: input.imageWidth,\n height: input.imageHeight,\n },\n },\n };\n}\n\nconst leftFeature: SectionExtractor = (input) => featureDraft(input as LeftFeatureInput, 'left');\nconst rightFeature: SectionExtractor = (input) => featureDraft(input as RightFeatureInput, 'right');\n\nconst fullBleedQuote: SectionExtractor = (input) => {\n const f = input as FullBleedQuoteInput;\n return {\n kind: 'quote-band',\n variant: 'display',\n slots: { body: { text: f.text ?? '' } },\n emphasis: 'strong',\n colorScheme: f.colorScheme,\n };\n};\n\nconst list: SectionExtractor = (input) => {\n const l = input as ListBlockInput;\n return {\n kind: 'item-list',\n slots: {\n title: l.title,\n items: (l.items ?? []).map((item) => ({ body: item })),\n media: accentImageMedia(l.accentImage),\n },\n colorScheme: l.colorScheme,\n };\n};\n\nconst photoGrid: SectionExtractor = (input) => {\n const p = input as PhotoGridInput;\n const images = p.images ?? [];\n // A gallery block whose body has no images yet would render as an empty\n // band — keep the authored heading/body text visible instead.\n const fallback =\n images.length === 0\n ? {\n title: (input as unknown as { title?: string }).title,\n body: bodyRichText(input),\n }\n : undefined;\n return {\n kind: 'gallery',\n slots: {\n ...fallback,\n caption: p.caption,\n items: images.map((img) => ({\n media: {\n type: 'image',\n src: img.src,\n alt: img.alt ?? '',\n credit: img.credit,\n license: img.license,\n } as PageMedia,\n })),\n },\n };\n};\n\nconst definitionCard: SectionExtractor = (input) => {\n const d = input as DefinitionCardInput;\n return {\n kind: 'callout',\n variant: 'definition',\n slots: {\n title: d.term,\n body: { text: d.definition ?? '' },\n meta: d.origin,\n media: accentImageMedia(d.accentImage),\n },\n colorScheme: d.colorScheme,\n };\n};\n\nconst comparisonBar: SectionExtractor = (input) => {\n const c = input as ComparisonBarInput;\n return {\n kind: 'stat-band',\n variant: 'comparison',\n slots: {\n items: [\n { title: c.leftLabel, value: c.leftValue },\n { title: c.rightLabel, value: c.rightValue },\n ],\n meta: c.unit,\n },\n emphasis: 'strong',\n colorScheme: c.colorScheme,\n };\n};\n\nconst pullQuote: SectionExtractor = (input) => {\n const p = input as PullQuoteInput;\n const bg = p.backgroundImage;\n return {\n kind: 'quote-band',\n variant: 'full-bleed',\n slots: {\n body: { text: p.text ?? '' },\n attribution: p.attribution,\n media: bg?.src\n ? { type: 'image', src: bg.src, alt: bg.alt ?? '', credit: bg.credit, license: bg.license }\n : undefined,\n },\n emphasis: 'strong',\n mediaBackground: !!bg?.src,\n };\n};\n\nconst videoWithCaption: SectionExtractor = (input) => {\n const v = input as VideoWithCaptionInput;\n return {\n kind: 'media-figure',\n variant: 'video',\n slots: {\n media: {\n type: 'video',\n src: v.videoSrc,\n posterSrc: v.posterSrc,\n alt: v.videoAlt ?? '',\n clipStart: v.clipStart,\n clipEnd: v.clipEnd,\n credit: v.videoCredit,\n license: v.videoLicense,\n },\n caption: v.caption,\n },\n };\n};\n\nconst videoPullQuote: SectionExtractor = (input) => {\n const v = input as VideoPullQuoteInput;\n const bg = v.backgroundVideo;\n return {\n kind: 'quote-band',\n variant: 'full-bleed',\n slots: {\n body: { text: v.text ?? '' },\n attribution: v.attribution,\n media: bg?.src\n ? {\n type: 'video',\n src: bg.src,\n posterSrc: bg.posterSrc,\n alt: bg.alt ?? '',\n clipStart: bg.clipStart,\n clipEnd: bg.clipEnd,\n credit: bg.credit,\n license: bg.license,\n }\n : undefined,\n },\n emphasis: 'strong',\n mediaBackground: !!bg?.src,\n };\n};\n\nconst dataTable: SectionExtractor = (input) => {\n const d = input as DataTableInput;\n return {\n kind: 'table-section',\n slots: {\n title: d.title,\n table: { headers: d.headers ?? [], rows: d.rows ?? [], align: d.align },\n },\n colorScheme: d.colorScheme,\n };\n};\n\nconst diagram: SectionExtractor = (input, ctx) =>\n canvasDraft('diagram', ctx, input as unknown as Block);\nconst tree: SectionExtractor = (input, ctx) => canvasDraft('tree', ctx, input as unknown as Block);\nconst timeline: SectionExtractor = (input, ctx) =>\n canvasDraft('timeline', ctx, input as unknown as Block);\nconst map: SectionExtractor = (input, ctx) => canvasDraft('map', ctx, input as unknown as Block);\nconst drawing: SectionExtractor = (input, ctx) =>\n canvasDraft('drawing', ctx, input as unknown as Block);\nconst layout: SectionExtractor = (input, ctx) =>\n canvasDraft('layout', ctx, input as unknown as Block);\n\n/**\n * Extractors keyed by canonical template id — 1:1 with the SVG template\n * registry (`templates/registry.ts`).\n */\nexport const sectionExtractors: Record<string, SectionExtractor> = {\n title,\n sectionHeader,\n statHighlight,\n quote,\n factCard,\n twoColumn,\n dateEvent,\n imageWithCaption,\n leftFeature,\n rightFeature,\n map,\n fullBleedQuote,\n list,\n photoGrid,\n definitionCard,\n comparisonBar,\n pullQuote,\n videoWithCaption,\n videoPullQuote,\n dataTable,\n diagram,\n tree,\n timeline,\n layout,\n drawing,\n};\n","/**\n * Canonical block-to-page-section materialization — the Page (linear) mode\n * sibling of `materializeBlockLayers`.\n *\n * `materializePageSections(doc, …)` is the primary entry point: it walks the\n * block tree pre-order, extracts a `PageSection` per block (cover hero,\n * typed template sections, prose, canvas embeds, visible fallbacks), and\n * then applies the theme's art direction across the sequence — background\n * rhythm, accent rotation, and the emphasis curve are sequence-scoped\n * decisions that per-block calls cannot make.\n *\n * Failures are data, not console side effects: an unknown template becomes\n * a visible `callout` section with a structured diagnostic (mirroring\n * `materializeBlockLayers`' fallback posture).\n */\n\nimport type { Block, Doc, StartBlockConfig } from '../../schemas/Doc.js';\nimport type { CustomTemplateDefinition } from '../../schemas/CustomTemplates.js';\nimport type { Theme, ThemeColorScheme } from '../../schemas/Theme.js';\nimport type { ViewportConfig } from '../../schemas/Viewport.js';\nimport type {\n PageBackground,\n PageEmphasis,\n PageSectionKind,\n PageSectionOverride,\n ThemePageStyle,\n} from '../../schemas/PageStyle.js';\nimport { DEFAULT_THEME } from '../../schemas/themeLibrary.js';\nimport { VIEWPORT_PRESETS } from '../../schemas/Viewport.js';\nimport { defaultPageStyle } from '../../schemas/pageStyleDefaults.js';\nimport { extractPlainText } from '../../markdown/utils.js';\nimport type { MarkdownBlockNode } from '../../markdown/types.js';\nimport { extractBodyPlainText } from '../templateInputs.js';\nimport { isContainerTemplate } from '../templates/templateNames.js';\nimport { isTemplatedPageBlock, resolvePageBlock } from './resolvePageBlock.js';\nimport { sectionExtractors, type PageSectionDraft } from './sectionExtractors.js';\nimport type {\n PageSection,\n PageSectionDiagnostic,\n PageSectionMaterialization,\n PageRichText,\n PageSectionSource,\n} from './PageSection.js';\n\n/**\n * Page-mode hints a transform style may carry (`TransformStyleConfig.page`).\n * Defined here (not in `transform/`) so the doc pipeline stays independent\n * of the transform module.\n */\nexport interface PageTransformHints {\n /** Overrides `pageStyle.tokens.sectionSpacing` for this rendition. */\n spacing?: 'compact' | 'comfortable' | 'generous';\n /** 'front-loaded' promotes the first sections' emphasis one step. */\n emphasisCurve?: 'even' | 'front-loaded';\n}\n\n/** Options shared by the per-block and doc-level entry points. */\nexport interface MaterializePageSectionOptions {\n /** Theme whose `pageStyle` art-directs the sections. */\n theme?: Theme;\n /** Aspect reference for canvas embeds. Defaults to the landscape preset. */\n viewport?: ViewportConfig;\n /** Zero-based position in the section sequence (per-block calls). */\n blockIndex?: number;\n /** Total sections in the sequence (per-block calls). */\n totalBlocks?: number;\n /** Document-scoped custom templates (render as canvas embeds). */\n customTemplates?: readonly CustomTemplateDefinition[];\n}\n\n/** Doc-level options. */\nexport interface MaterializePageSectionsOptions extends MaterializePageSectionOptions {\n /**\n * Cover hero: pass the doc's `startBlock` to synthesize a leading hero\n * section, `false`/undefined to omit. (The caller decides — the editor's\n * Cover toggle maps here.)\n */\n cover?: StartBlockConfig | false;\n /** Page hints from the active transform style, if any. */\n transformPage?: PageTransformHints;\n}\n\n/**\n * Resolve the effective page style for a theme: explicit `theme.pageStyle`\n * wins, else a derived default. Transform hints overlay spacing.\n * Never returns undefined.\n */\nexport function resolvePageStyle(theme?: Theme, hints?: PageTransformHints): ThemePageStyle {\n const base = theme?.pageStyle ?? defaultPageStyle(theme ?? DEFAULT_THEME);\n if (!hints?.spacing || hints.spacing === base.tokens.sectionSpacing) return base;\n return { ...base, tokens: { ...base.tokens, sectionSpacing: hints.spacing } };\n}\n\n/** Section kinds that carry a rotating accent scheme. */\nconst ACCENT_KINDS: ReadonlySet<PageSectionKind> = new Set([\n 'banner',\n 'stat-band',\n 'quote-band',\n 'callout',\n 'card-grid',\n 'item-list',\n 'timeline-rail',\n 'footer',\n]);\n\n/** Kinds rendered as full-width color bands under the accent-bands rhythm. */\nconst BAND_KINDS: ReadonlySet<PageSectionKind> = new Set([\n 'banner',\n 'quote-band',\n 'stat-band',\n 'footer',\n]);\n\n/** Kinds rendered as tinted panels under the tinted-panels rhythm. */\nconst PANEL_KINDS: ReadonlySet<PageSectionKind> = new Set([\n 'callout',\n 'card-grid',\n 'stat-band',\n 'item-list',\n 'timeline-rail',\n 'table-section',\n]);\n\ninterface DraftResult {\n draft: PageSectionDraft;\n source: PageSectionSource;\n templateName?: string;\n diagnostic?: PageSectionDiagnostic;\n}\n\nfunction isMermaidFence(node: MarkdownBlockNode): boolean {\n return node.type === 'code' && node.lang?.trim().toLowerCase() === 'mermaid';\n}\n\nfunction htmlTreeContainsMedia(nodes: unknown[]): boolean {\n for (const value of nodes) {\n if (!value || typeof value !== 'object') continue;\n const node = value as Record<string, unknown>;\n if (\n node.type === 'htmlElement' &&\n typeof node.tagName === 'string' &&\n ['img', 'video', 'audio'].includes(node.tagName.toLowerCase())\n ) {\n return true;\n }\n if (Array.isArray(node.children) && htmlTreeContainsMedia(node.children)) return true;\n }\n return false;\n}\n\nfunction markdownNodeContainsMedia(value: unknown): boolean {\n if (!value || typeof value !== 'object') return false;\n const node = value as Record<string, unknown>;\n if (node.type === 'image') return true;\n if (\n (node.type === 'htmlBlock' || node.type === 'htmlInline') &&\n Array.isArray(node.htmlChildren) &&\n htmlTreeContainsMedia(node.htmlChildren)\n ) {\n return true;\n }\n return Array.isArray(node.children) && node.children.some(markdownNodeContainsMedia);\n}\n\n/** Rich body content that a typed template has not already consumed. */\nfunction unconsumedRichContent(block: Block, draft: PageSectionDraft): PageRichText | undefined {\n if (!block.contents || block.contents.length === 0) return undefined;\n const templateHasMedia =\n Boolean(draft.slots.media) ||\n Boolean(draft.slots.items?.some((item) => item.media !== undefined));\n const markdown = block.contents.filter(\n (node) => isMermaidFence(node) || (!templateHasMedia && markdownNodeContainsMedia(node)),\n );\n if (markdown.length === 0) return undefined;\n return {\n text: markdown\n .map((node) => extractPlainText(node))\n .join('\\n')\n .trim(),\n markdown,\n };\n}\n\nfunction preserveRichContent(block: Block, draft: PageSectionDraft): PageSectionDraft {\n const richContent = unconsumedRichContent(block, draft);\n return richContent ? { ...draft, slots: { ...draft.slots, richContent } } : draft;\n}\n\n/** Extract the pre-art-direction draft for one block. */\nfunction draftForBlock(\n block: Block,\n viewport: ViewportConfig,\n customTemplates?: readonly CustomTemplateDefinition[],\n): DraftResult {\n if (isTemplatedPageBlock(block)) {\n const resolved = resolvePageBlock(block);\n const templateName = resolved.templateName!;\n const extractor = sectionExtractors[templateName];\n if (extractor) {\n return {\n draft: preserveRichContent(block, extractor(resolved.templateBlock!, { block, viewport })),\n source: 'template',\n templateName,\n };\n }\n\n const custom = customTemplates?.find((definition) => definition.name === templateName);\n if (custom) {\n const draft: PageSectionDraft = {\n kind: 'canvas-embed',\n variant: 'custom',\n slots: {\n media: {\n type: 'canvas',\n spatial: 'custom',\n block: resolved.templateBlock as unknown as Block,\n aspect: {\n width: custom.viewport?.width ?? viewport.width,\n height: custom.viewport?.height ?? viewport.height,\n },\n },\n },\n };\n return {\n draft: preserveRichContent(block, draft),\n source: 'custom-template',\n templateName,\n };\n }\n\n const diagnostic: PageSectionDiagnostic = {\n code: 'unknown-template',\n template: templateName,\n message: `Unknown template \"${templateName}\"`,\n };\n const headingText = block.sourceHeading ? extractPlainText(block.sourceHeading) : undefined;\n const draft: PageSectionDraft = {\n kind: 'callout',\n variant: 'diagnostic',\n slots: {\n title: headingText ?? diagnostic.message,\n body: { text: extractBodyPlainText(block.contents) },\n meta: diagnostic.message,\n },\n emphasis: 'quiet',\n };\n return {\n draft: preserveRichContent(block, draft),\n source: 'fallback',\n templateName,\n diagnostic,\n };\n }\n\n if (block.layers && block.layers.length > 0) {\n const draft: PageSectionDraft = {\n kind: 'canvas-embed',\n variant: 'authored',\n slots: {\n media: {\n type: 'canvas',\n spatial: 'authored',\n block,\n aspect: { width: viewport.width, height: viewport.height },\n },\n },\n };\n return {\n draft: preserveRichContent(block, draft),\n source: 'authored',\n };\n }\n\n const heading = block.sourceHeading;\n return {\n draft: {\n kind: 'prose',\n slots: {\n title: heading ? extractPlainText(heading) : undefined,\n headingLevel: heading?.depth,\n body:\n block.contents && block.contents.length > 0\n ? { text: extractBodyPlainText(block.contents), markdown: block.contents }\n : undefined,\n },\n },\n source: 'prose',\n };\n}\n\n/** Look up the theme override for a draft: per-template wins over per-kind. */\nfunction overrideFor(\n pageStyle: ThemePageStyle,\n kind: PageSectionKind,\n templateName?: string,\n): PageSectionOverride | undefined {\n const byTemplate = templateName ? pageStyle.templates?.[templateName] : undefined;\n const byKind = pageStyle.sections?.[kind];\n if (!byTemplate) return byKind;\n if (!byKind) return byTemplate;\n return {\n ...byKind,\n ...byTemplate,\n hints: { ...byKind.hints, ...byTemplate.hints },\n };\n}\n\ninterface SectionSeed {\n draft: PageSectionDraft;\n source: PageSectionSource;\n templateName?: string;\n diagnostic?: PageSectionDiagnostic;\n override?: PageSectionOverride;\n block?: Block;\n depth: number;\n}\n\n/** Build the final section from a seed + sequence-scoped decisions. */\nfunction buildSection(\n seed: SectionSeed,\n index: number,\n totalSections: number,\n background: PageBackground,\n emphasis: PageEmphasis,\n accent: PageSection['accent'],\n): PageSection {\n const { draft, override } = seed;\n const hints = { ...draft.hints, ...override?.hints };\n const section: PageSection = {\n kind: override?.kind ?? draft.kind,\n variant: override?.variant ?? draft.variant,\n blockId: seed.block?.id ?? 'cover',\n template:\n seed.source === 'template' || seed.source === 'custom-template' || seed.source === 'fallback'\n ? seed.templateName\n : undefined,\n slots: draft.slots,\n emphasis,\n accent,\n background,\n index,\n totalSections,\n depth: seed.depth,\n source: seed.source,\n };\n if (seed.diagnostic) section.diagnostic = seed.diagnostic;\n if (Object.keys(hints).length > 0) section.hints = hints;\n return section;\n}\n\nfunction resolveScheme(theme: Theme, schemeName: string | undefined): ThemeColorScheme | undefined {\n return schemeName ? theme.colorSchemes?.[schemeName] : undefined;\n}\n\n/** The names available for accent rotation, honoring `accentRotation.schemes`. */\nfunction rotationSchemeNames(pageStyle: ThemePageStyle, theme: Theme): string[] {\n const all = Object.keys(theme.colorSchemes ?? {});\n const requested = pageStyle.accentRotation.schemes;\n if (!requested || requested.length === 0) return all;\n return requested.filter((name) => all.includes(name));\n}\n\n/**\n * Materialize one block in isolation. Sequence-scoped art direction\n * (background rhythm, accent rotation, emphasis curve) does not apply —\n * use `materializePageSections` for whole-document rendering.\n */\nexport function materializePageSection(\n block: Block,\n options: MaterializePageSectionOptions = {},\n): PageSectionMaterialization {\n const theme = options.theme ?? DEFAULT_THEME;\n const viewport = options.viewport ?? VIEWPORT_PRESETS.landscape;\n const pageStyle = resolvePageStyle(theme);\n const result = draftForBlock(block, viewport, options.customTemplates);\n const override = overrideFor(pageStyle, result.draft.kind, result.templateName);\n\n const background: PageBackground =\n override?.background ?? (result.draft.mediaBackground ? 'media' : 'base');\n const emphasis: PageEmphasis = override?.emphasis ?? result.draft.emphasis ?? 'standard';\n const accent: PageSection['accent'] = result.draft.colorScheme\n ? {\n schemeName: result.draft.colorScheme,\n scheme: resolveScheme(theme, result.draft.colorScheme),\n role: 'block',\n }\n : { role: pageStyle.accentRotation.strategy === 'none' ? 'none' : 'primary' };\n\n const section = buildSection(\n { ...result, override, block, depth: 0 },\n options.blockIndex ?? 0,\n options.totalBlocks ?? 1,\n background,\n emphasis,\n accent,\n );\n return {\n section,\n block,\n source: result.source,\n diagnostic: result.diagnostic,\n };\n}\n\n/**\n * Materialize a whole document into its ordered page sections, applying\n * the theme's art direction across the sequence. The primary entry point\n * for Page (linear) mode renderers and exporters.\n */\nexport function materializePageSections(\n doc: Doc,\n options: MaterializePageSectionsOptions = {},\n): PageSectionMaterialization[] {\n const theme = options.theme ?? DEFAULT_THEME;\n const viewport = options.viewport ?? VIEWPORT_PRESETS.landscape;\n const pageStyle = resolvePageStyle(theme, options.transformPage);\n const customTemplates = options.customTemplates ?? doc.customTemplates;\n\n // ── Collect seeds pre-order ──────────────────────────────────────\n const seeds: SectionSeed[] = [];\n\n if (options.cover) {\n const cover = options.cover;\n seeds.push({\n draft: {\n kind: 'hero',\n variant: 'cover',\n slots: {\n title: cover.title,\n subtitle: cover.subtitle,\n media: cover.heroSrc\n ? {\n type: 'image',\n src: cover.heroSrc,\n alt: cover.heroAlt ?? '',\n credit: cover.heroCredit,\n license: cover.heroLicense,\n }\n : undefined,\n },\n emphasis: 'lead',\n mediaBackground: !!cover.heroSrc,\n },\n source: 'cover',\n depth: 0,\n });\n }\n\n const walk = (blocks: readonly Block[], depth: number): void => {\n for (const block of blocks) {\n const result = draftForBlock(block, viewport, customTemplates);\n seeds.push({ ...result, block, depth });\n // Container templates (diagram/drawing/layout) consume their children\n // inside the canvas; everything else recurses.\n const consumed =\n result.draft.kind === 'canvas-embed' && isContainerTemplate(result.templateName);\n if (!consumed && block.children && block.children.length > 0) {\n walk(block.children, depth + 1);\n }\n }\n };\n walk(doc.blocks ?? [], 0);\n\n // ── Cover dedupe ─────────────────────────────────────────────────\n // The auto-generated cover copies the first H1's title (and its first\n // paragraph as subtitle). On one scrolling page rendering both reads as\n // a duplicate, so suppress the mirrored content from the H1's own\n // section — and drop that section entirely when nothing remains.\n if (options.cover && seeds.length > 1) {\n const cover = options.cover;\n const first = seeds[1];\n if (first.draft.kind === 'hero' && first.draft.slots.title === cover.title) {\n // The author already opens with a title/hero block — that one wins.\n // Graft the cover's hero media onto it when it has none of its own.\n const coverSeed = seeds[0];\n const coverMedia = coverSeed.draft.slots.media;\n if (coverMedia && !first.draft.slots.media) {\n first.draft = {\n ...first.draft,\n slots: { ...first.draft.slots, media: coverMedia },\n mediaBackground: true,\n };\n }\n seeds.splice(0, 1);\n } else if (first.draft.kind === 'prose' && first.draft.slots.title === cover.title) {\n const slots = { ...first.draft.slots };\n delete slots.title;\n delete slots.headingLevel;\n let markdown = slots.body?.markdown;\n if (\n cover.subtitle &&\n markdown &&\n markdown.length > 0 &&\n markdown[0].type === 'paragraph' &&\n extractPlainText(markdown[0]) === cover.subtitle\n ) {\n markdown = markdown.slice(1);\n }\n if (markdown && markdown.length > 0) {\n slots.body = {\n text: markdown\n .map((node) => extractPlainText(node))\n .join('\\n')\n .trim(),\n markdown,\n };\n first.draft = { ...first.draft, slots };\n } else {\n seeds.splice(1, 1);\n }\n }\n }\n\n // ── Apply theme overrides + sequence art direction ───────────────\n for (const seed of seeds) {\n seed.override = overrideFor(pageStyle, seed.draft.kind, seed.templateName);\n }\n\n const totalSections = seeds.length;\n const rhythm = pageStyle.tokens.backgroundRhythm;\n const strategy = pageStyle.accentRotation.strategy;\n const schemeNames = rotationSchemeNames(pageStyle, theme);\n const rotationSize =\n strategy === 'alternate-two' ? Math.min(2, schemeNames.length) : schemeNames.length;\n\n let bandCounter = 0;\n let rotationCounter = 0;\n let promotedCount = 0;\n let eyebrowCounter = 0;\n const eyebrowTreatment = pageStyle.tokens.headingTreatment.eyebrow;\n\n const results: PageSectionMaterialization[] = [];\n for (let index = 0; index < seeds.length; index++) {\n const seed = seeds[index];\n const kind = seed.override?.kind ?? seed.draft.kind;\n\n // Background: explicit override > media background > rhythm.\n let background: PageBackground;\n if (seed.override?.background) {\n background = seed.override.background;\n } else if (seed.draft.mediaBackground) {\n background = 'media';\n } else if (kind === 'prose' || rhythm === 'flat') {\n background = 'base';\n } else if (rhythm === 'accent-bands' && BAND_KINDS.has(kind)) {\n background = 'accent';\n } else if (rhythm === 'tinted-panels') {\n background = PANEL_KINDS.has(kind) ? 'alternate' : 'base';\n } else if (rhythm === 'alternate' || rhythm === 'accent-bands') {\n background = bandCounter % 2 === 1 ? 'alternate' : 'base';\n bandCounter++;\n } else {\n background = 'base';\n }\n\n // Accent: block-authored scheme > rotation > primary.\n let accent: PageSection['accent'];\n if (seed.draft.colorScheme) {\n accent = {\n schemeName: seed.draft.colorScheme,\n scheme: resolveScheme(theme, seed.draft.colorScheme),\n role: 'block',\n };\n } else if (\n ACCENT_KINDS.has(kind) &&\n (strategy === 'cycle' || strategy === 'alternate-two') &&\n rotationSize > 0\n ) {\n const schemeName = schemeNames[rotationCounter % rotationSize];\n rotationCounter++;\n accent = { schemeName, scheme: resolveScheme(theme, schemeName), role: 'rotation' };\n } else if (strategy === 'none') {\n accent = { role: 'none' };\n } else {\n accent = { role: 'primary' };\n }\n\n // Emphasis: override > draft > standard, then the transform curve.\n let emphasis: PageEmphasis = seed.override?.emphasis ?? seed.draft.emphasis ?? 'standard';\n if (\n options.transformPage?.emphasisCurve === 'front-loaded' &&\n kind !== 'hero' &&\n kind !== 'prose' &&\n promotedCount < 2\n ) {\n if (emphasis === 'standard') emphasis = 'strong';\n promotedCount++;\n }\n\n // Numbered / mono-tag eyebrows: fill sequential ordinals on the\n // heading-bearing band sections so \"01 —\" chapter kickers count\n // contiguously down the page. Authored eyebrow text always wins.\n if (\n (eyebrowTreatment === 'numbered' || eyebrowTreatment === 'mono-tag') &&\n (kind === 'hero' || kind === 'banner')\n ) {\n eyebrowCounter++;\n if (!seed.draft.slots.eyebrow) {\n seed.draft.slots = {\n ...seed.draft.slots,\n eyebrow: String(eyebrowCounter).padStart(2, '0'),\n };\n }\n }\n\n const section = buildSection(seed, index, totalSections, background, emphasis, accent);\n results.push({\n section,\n block: seed.block,\n source: seed.source,\n diagnostic: seed.diagnostic,\n });\n }\n\n return results;\n}\n","/**\n * Page CSS — the single source of truth for Page (linear) mode styling.\n *\n * `PAGE_BASE_CSS` is structural and theme-independent: every color, font,\n * and dimension flows through `--squisq-page-*` custom properties\n * (`buildPageCssVars`) and the token data-attributes the renderer stamps on\n * the `.squisq-page` wrapper (`pageStyleDataAttributes`). One stylesheet\n * therefore serves all themes and all design families — a theme changes the\n * page's look purely through vars + data attributes, never through\n * generated CSS.\n *\n * Consumers:\n * - React `LinearDocView` injects `<style data-squisq-page>` with\n * `PAGE_BASE_CSS` and sets the vars inline (self-contained — no CSS\n * import needed, which keeps the standalone bundle and single-file HTML\n * exports working).\n * - A string-HTML exporter can call `buildPageCss(theme)` for the same\n * bytes plus a `.squisq-page { … }` var block.\n *\n * Responsive behavior uses container queries against the scroll container\n * (named `squisq-page`), with a media-query fallback for engines without\n * container support.\n */\n\nimport type { Theme } from '../schemas/Theme.js';\nimport type { ThemePageStyle } from '../schemas/PageStyle.js';\nimport { resolveFontFamily } from '../schemas/fontStacks.js';\nimport { DEFAULT_THEME } from '../schemas/themeLibrary.js';\nimport { resolvePageStyle } from './page/materializePageSection.js';\n\n/** Subtle noise texture (tiny inline SVG) for the `noise` page pattern. */\nconst NOISE_DATA_URI =\n \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.35'/%3E%3C/svg%3E\\\")\";\n\n/**\n * Custom-property values for a theme's page rendition. Set these inline on\n * the `.squisq-page` wrapper (React) or in a `.squisq-page { … }` rule\n * (string export). Per-section accent vars (`--squisq-page-accent*`) get\n * page-level defaults here and are overridden per section by the renderer.\n */\nexport function buildPageCssVars(\n theme?: Theme,\n pageStyle?: ThemePageStyle,\n): Record<string, string> {\n const t = theme ?? DEFAULT_THEME;\n const style = pageStyle ?? resolvePageStyle(t);\n const colors = t.colors;\n const typography = t.typography;\n return {\n '--squisq-page-bg': colors.background,\n '--squisq-page-bg-alt': colors.backgroundLight,\n '--squisq-page-text': colors.text,\n '--squisq-page-text-muted': colors.textMuted,\n '--squisq-page-primary': colors.primary,\n '--squisq-page-secondary': colors.secondary,\n '--squisq-page-highlight': colors.highlight,\n '--squisq-page-title-font': resolveFontFamily(typography.titleFont, 'Georgia, serif'),\n '--squisq-page-body-font': resolveFontFamily(typography.bodyFont, 'system-ui, sans-serif'),\n '--squisq-page-mono-font': resolveFontFamily(\n typography.monoFont,\n 'ui-monospace, SFMono-Regular, Menlo, monospace',\n ),\n '--squisq-page-line-height': String(typography.lineHeight ?? 1.65),\n '--squisq-page-title-weight': typography.titleWeight === 'normal' ? '400' : '700',\n '--squisq-page-content-max': `${style.tokens.contentMaxWidth}px`,\n '--squisq-page-wide-max': `${style.tokens.wideMaxWidth}px`,\n '--squisq-page-radius': `${style.tokens.cornerRadius}px`,\n // Per-section accent defaults; the renderer overrides these per section.\n '--squisq-page-accent': colors.primary,\n '--squisq-page-accent-bg': colors.backgroundLight,\n '--squisq-page-accent-text': colors.text,\n };\n}\n\n/**\n * The token data-attributes the renderer stamps on `.squisq-page` so the\n * structural CSS can branch per design decision. Shared by React and any\n * string exporter so both emit identical markup.\n */\nexport function pageStyleDataAttributes(pageStyle: ThemePageStyle): Record<string, string> {\n const tokens = pageStyle.tokens;\n const attrs: Record<string, string> = {\n 'data-family': pageStyle.family,\n 'data-spacing': tokens.sectionSpacing,\n 'data-divider': tokens.divider,\n 'data-rhythm': tokens.backgroundRhythm,\n 'data-hero-style': tokens.heroStyle,\n 'data-eyebrow': tokens.headingTreatment.eyebrow,\n 'data-heading-scale': tokens.headingTreatment.scale,\n 'data-framing': tokens.imageFraming,\n 'data-shadow': tokens.shadow,\n 'data-quote-mark': tokens.quoteMark,\n 'data-numerals': tokens.numeralStyle,\n };\n if (tokens.headingTreatment.case && tokens.headingTreatment.case !== 'none') {\n attrs['data-heading-case'] = tokens.headingTreatment.case;\n }\n if (tokens.headingTreatment.underline && tokens.headingTreatment.underline !== 'none') {\n attrs['data-underline'] = tokens.headingTreatment.underline;\n }\n if (tokens.pattern && tokens.pattern !== 'none') {\n attrs['data-pattern'] = tokens.pattern;\n }\n return attrs;\n}\n\n/** Shared responsive collapse rules (referenced from both query forms). */\nconst NARROW_RULES = `\n.squisq-page-hero-grid { grid-template-columns: 1fr; gap: 1.5rem; }\n.squisq-page-feature { grid-template-columns: 1fr; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 0; }\n.squisq-page-stats { flex-direction: column; gap: 1.75rem; }\n.squisq-page-cards { grid-template-columns: 1fr; }\n.squisq-page-gallery { grid-template-columns: repeat(2, 1fr); }\n.squisq-page-milestone { grid-template-columns: 1fr; gap: 0.5rem; }\n.squisq-page-milestone-rail { display: none; }\n.squisq-page-section-inner { padding-inline: 18px; }\n`;\n\n/**\n * Structural, theme-independent stylesheet for the page rendition.\n * Everything is scoped under `.squisq-page`.\n */\nexport const PAGE_BASE_CSS = `\n/* ── Base ─────────────────────────────────────────────────────────── */\n.squisq-page {\n background: var(--squisq-page-bg);\n color: var(--squisq-page-text);\n font-family: var(--squisq-page-body-font);\n line-height: var(--squisq-page-line-height);\n --squisq-page-divider-color: color-mix(in srgb, var(--squisq-page-text) 16%, transparent);\n --squisq-page-section-pad: 3.5rem;\n --squisq-page-shadow: none;\n}\n.squisq-page *, .squisq-page *::before, .squisq-page *::after { box-sizing: border-box; }\n.squisq-page img { max-width: 100%; height: auto; }\n\n/* Page pattern washes (very low intensity) */\n.squisq-page[data-pattern='dots'] {\n background-image: radial-gradient(color-mix(in srgb, var(--squisq-page-text) 7%, transparent) 1px, transparent 1px);\n background-size: 22px 22px;\n}\n.squisq-page[data-pattern='grid'] {\n background-image:\n linear-gradient(color-mix(in srgb, var(--squisq-page-primary) 7%, transparent) 1px, transparent 1px),\n linear-gradient(90deg, color-mix(in srgb, var(--squisq-page-primary) 7%, transparent) 1px, transparent 1px);\n background-size: 44px 44px;\n}\n.squisq-page[data-pattern='diagonal'] {\n background-image: repeating-linear-gradient(\n -45deg,\n color-mix(in srgb, var(--squisq-page-text) 4%, transparent) 0 1px,\n transparent 1px 14px\n );\n}\n.squisq-page[data-pattern='noise'] { background-image: ${NOISE_DATA_URI}; }\n\n/* Spacing scale */\n.squisq-page[data-spacing='compact'] { --squisq-page-section-pad: 2.25rem; }\n.squisq-page[data-spacing='comfortable'] { --squisq-page-section-pad: 3.5rem; }\n.squisq-page[data-spacing='generous'] { --squisq-page-section-pad: 5.25rem; }\n\n/* Shadow language */\n.squisq-page[data-shadow='soft'] { --squisq-page-shadow: 0 14px 36px color-mix(in srgb, var(--squisq-page-text) 14%, transparent); }\n.squisq-page[data-shadow='crisp'] { --squisq-page-shadow: 0 2px 10px color-mix(in srgb, var(--squisq-page-text) 26%, transparent); }\n.squisq-page[data-shadow='heavy'] { --squisq-page-shadow: 10px 10px 0 color-mix(in srgb, var(--squisq-page-text) 82%, transparent); }\n\n/* ── Sections ─────────────────────────────────────────────────────── */\n.squisq-page-section { position: relative; padding-block: var(--squisq-page-section-pad); }\n.squisq-page-section-inner {\n max-width: var(--squisq-page-content-max);\n margin-inline: auto;\n padding-inline: 24px;\n}\n/* Backdrops anchor to the section; these content roots stack above them. */\n.squisq-page-hero-body,\n.squisq-page-banner-body,\n.squisq-page-quote-figure { position: relative; }\n.squisq-page-section--feature-split .squisq-page-section-inner,\n.squisq-page-section--gallery .squisq-page-section-inner,\n.squisq-page-section--table-section .squisq-page-section-inner,\n.squisq-page-section--canvas-embed .squisq-page-section-inner,\n.squisq-page-section--stat-band .squisq-page-section-inner,\n.squisq-page-section--card-grid .squisq-page-section-inner,\n.squisq-page-section--media-figure .squisq-page-section-inner,\n.squisq-page-section--hero .squisq-page-section-inner {\n max-width: var(--squisq-page-wide-max);\n}\n\n/* Background rhythm */\n.squisq-page-section--bg-alternate { background: var(--squisq-page-bg-alt); }\n.squisq-page-section--bg-accent {\n background: var(--squisq-page-accent-bg);\n color: var(--squisq-page-accent-text);\n}\n.squisq-page-section--bg-media { color: #ffffff; }\n\n/* Dividers between adjacent sections */\n.squisq-page[data-divider='hairline'] .squisq-page-section + .squisq-page-section { border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page[data-divider='thick-rule'] .squisq-page-section + .squisq-page-section { border-top: 3px solid var(--squisq-page-primary); }\n.squisq-page[data-divider='double-rule'] .squisq-page-section + .squisq-page-section { border-top: 4px double var(--squisq-page-divider-color); }\n.squisq-page[data-divider='dotted'] .squisq-page-section + .squisq-page-section { border-top: 2px dotted var(--squisq-page-divider-color); }\n/* Banded sections carry their own edges; media sections never need rules. */\n.squisq-page .squisq-page-section--bg-media,\n.squisq-page .squisq-page-section--bg-media + .squisq-page-section,\n.squisq-page .squisq-page-section--timeline-rail + .squisq-page-section--timeline-rail { border-top: none; }\n\n/* ── Headings, eyebrows ───────────────────────────────────────────── */\n.squisq-page-section-title {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.15;\n margin: 0 0 0.5em;\n}\n.squisq-page[data-heading-case='uppercase'] .squisq-page-section-title { text-transform: uppercase; letter-spacing: 0.03em; }\n.squisq-page[data-underline='accent-bar'] .squisq-page-section-title::after {\n content: '';\n display: block;\n width: 56px;\n height: 4px;\n margin-top: 0.4em;\n border-radius: 2px;\n background: var(--squisq-page-accent);\n}\n.squisq-page[data-underline='full-rule'] .squisq-page-section-title {\n border-bottom: 1px solid var(--squisq-page-divider-color);\n padding-bottom: 0.35em;\n}\n\n.squisq-page-eyebrow {\n display: block;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--squisq-page-accent);\n margin: 0 0 0.9em;\n}\n.squisq-page[data-eyebrow='numbered'] .squisq-page-eyebrow::after { content: ' —'; color: var(--squisq-page-text-muted); }\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow {\n display: inline-block;\n font-family: var(--squisq-page-mono-font);\n text-transform: none;\n letter-spacing: 0.06em;\n border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 55%, transparent);\n border-radius: var(--squisq-page-radius);\n padding: 0.15em 0.6em;\n background: color-mix(in srgb, var(--squisq-page-accent) 10%, transparent);\n}\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow::before { content: '['; opacity: 0.6; }\n.squisq-page[data-eyebrow='mono-tag'] .squisq-page-eyebrow::after { content: ']'; opacity: 0.6; }\n\n/* ── Hero ─────────────────────────────────────────────────────────── */\n.squisq-page-section--hero { padding-block: calc(var(--squisq-page-section-pad) * 1.5); }\n.squisq-page-hero-title {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.08;\n margin: 0;\n font-size: 2.75rem;\n}\n.squisq-page[data-heading-scale='display'] .squisq-page-hero-title { font-size: 3.4rem; }\n.squisq-page[data-heading-scale='oversized'] .squisq-page-hero-title { font-size: 4rem; font-size: clamp(3rem, 9cqw, 6rem); line-height: 1.02; }\n.squisq-page[data-heading-case='uppercase'] .squisq-page-hero-title { text-transform: uppercase; letter-spacing: 0.02em; }\n.squisq-page-hero-subtitle {\n margin: 1.1em 0 0;\n font-size: 1.25rem;\n color: var(--squisq-page-text-muted);\n max-width: 42em;\n white-space: pre-line;\n}\n.squisq-page-section--bg-media .squisq-page-hero-subtitle { color: rgba(255, 255, 255, 0.88); }\n\n/* Stacked (default): centered column */\n.squisq-page[data-hero-style='stacked'] .squisq-page-hero-body { text-align: center; }\n.squisq-page[data-hero-style='stacked'] .squisq-page-hero-subtitle { margin-inline: auto; }\n\n/* Oversized type: hard left, no decoration */\n.squisq-page[data-hero-style='oversized-type'] .squisq-page-hero-title { font-size: 4.25rem; font-size: clamp(3.25rem, 10cqw, 6.5rem); line-height: 0.98; }\n\n/* Split: text and media side by side */\n.squisq-page-hero-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }\n.squisq-page-hero-grid .squisq-page-hero-media img { width: 100%; object-fit: cover; }\n\n/* Full-bleed & letterbox: media behind text */\n.squisq-page-section--hero-media {\n padding-block: 0;\n min-height: min(72svh, 620px);\n display: flex;\n align-items: flex-end;\n}\n.squisq-page[data-hero-style='letterbox'] .squisq-page-section--hero-media { min-height: min(52svh, 460px); }\n.squisq-page-hero-backdrop { position: absolute; inset: 0; overflow: hidden; }\n.squisq-page-hero-backdrop img { width: 100%; height: 100%; object-fit: cover; }\n.squisq-page-hero-backdrop::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.68) 100%);\n}\n.squisq-page[data-hero-style='letterbox'] .squisq-page-hero-backdrop img { filter: saturate(0.9); }\n.squisq-page-section--hero-media .squisq-page-section-inner { padding-block: 3rem; width: 100%; }\n\n/* ── Banner (sectionHeader) ───────────────────────────────────────── */\n.squisq-page-banner-title { font-size: 2rem; }\n.squisq-page[data-heading-scale='display'] .squisq-page-banner-title { font-size: 2.5rem; }\n.squisq-page[data-heading-scale='oversized'] .squisq-page-banner-title { font-size: 3rem; font-size: clamp(2.25rem, 6cqw, 3.75rem); }\n.squisq-page-section--banner.squisq-page-section--bg-media { padding-block: 0; min-height: 280px; display: flex; align-items: flex-end; }\n.squisq-page-section--banner.squisq-page-section--bg-media .squisq-page-section-inner { padding-block: 2rem; width: 100%; }\n.squisq-page-section--banner .squisq-page-section-title { margin-bottom: 0; }\n\n/* ── Stat band ────────────────────────────────────────────────────── */\n.squisq-page-stats { display: flex; gap: 3rem; justify-content: center; text-align: center; flex-wrap: wrap; }\n.squisq-page-stat { flex: 1 1 220px; max-width: 420px; }\n.squisq-page-stat-value {\n display: block;\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n font-size: 3.25rem;\n line-height: 1;\n color: var(--squisq-page-accent);\n}\n.squisq-page[data-numerals='oversized'] .squisq-page-stat-value { font-size: 4.5rem; font-size: clamp(3.5rem, 8cqw, 5.5rem); }\n.squisq-page[data-numerals='mono'] .squisq-page-stat-value { font-family: var(--squisq-page-mono-font); letter-spacing: -0.02em; }\n.squisq-page[data-numerals='boxed'] .squisq-page-stat-value {\n display: inline-block;\n border: 2px solid var(--squisq-page-accent);\n border-radius: var(--squisq-page-radius);\n padding: 0.18em 0.4em;\n}\n.squisq-page-stat-title { display: block; margin-top: 0.9em; font-size: 1.125rem; font-weight: 600; }\n.squisq-page-stat-body { display: block; margin-top: 0.45em; color: var(--squisq-page-text-muted); font-size: 0.95rem; }\n.squisq-page-stat-meta { text-align: center; margin-top: 1.5rem; color: var(--squisq-page-text-muted); font-size: 0.85rem; }\n.squisq-page-stat-bar { height: 10px; border-radius: 999px; background: var(--squisq-page-accent); margin-top: 0.8em; }\n.squisq-page-stat--bars { text-align: left; }\n\n/* ── Quote band ───────────────────────────────────────────────────── */\n.squisq-page-quote {\n margin: 0;\n font-family: var(--squisq-page-title-font);\n font-size: 1.6rem;\n line-height: 1.35;\n white-space: pre-line;\n}\n.squisq-page-section--em-strong .squisq-page-quote { font-size: 2.1rem; }\n.squisq-page-section--em-quiet .squisq-page-quote { font-size: 1.25rem; color: var(--squisq-page-text-muted); }\n.squisq-page-quote-attribution { margin-top: 1.1em; font-family: var(--squisq-page-body-font); font-size: 0.95rem; color: var(--squisq-page-text-muted); }\n.squisq-page-quote-attribution::before { content: '— '; }\n.squisq-page[data-quote-mark='accent-bar'] .squisq-page-quote-figure { border-left: 4px solid var(--squisq-page-accent); padding-left: 1.5rem; }\n.squisq-page[data-quote-mark='oversized-glyph'] .squisq-page-quote-figure { position: relative; padding-top: 1.25rem; }\n.squisq-page[data-quote-mark='oversized-glyph'] .squisq-page-quote-figure::before {\n content: '\\\\201C';\n position: absolute;\n top: -0.12em;\n left: -0.05em;\n font-family: var(--squisq-page-title-font);\n font-size: 5.5rem;\n line-height: 1;\n color: color-mix(in srgb, var(--squisq-page-accent) 42%, transparent);\n pointer-events: none;\n}\n.squisq-page-section--v-display .squisq-page-quote-figure { text-align: center; border-left: none; }\n.squisq-page-section--v-display .squisq-page-quote { font-size: 2.4rem; font-size: clamp(1.9rem, 5cqw, 3rem); }\n.squisq-page-section--v-editorial .squisq-page-quote-figure {\n border-block: 3px solid var(--squisq-page-primary);\n border-left: none;\n padding: 2rem 0.5rem;\n}\n/* Full-bleed quote over media */\n.squisq-page-section--quote-band.squisq-page-section--bg-media { padding-block: 0; min-height: 380px; display: flex; align-items: center; }\n.squisq-page-section--quote-band.squisq-page-section--bg-media .squisq-page-section-inner { padding-block: 3.5rem; }\n.squisq-page-quote-backdrop { position: absolute; inset: 0; overflow: hidden; }\n.squisq-page-quote-backdrop img, .squisq-page-quote-backdrop video { width: 100%; height: 100%; object-fit: cover; }\n.squisq-page-quote-backdrop::after { content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); }\n.squisq-page-section--quote-band[data-hint-vignette] .squisq-page-quote-backdrop::after {\n background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.35) 0%, rgba(0, 0, 0, 0.75) 100%);\n}\n.squisq-page-section--quote-band.squisq-page-section--bg-media .squisq-page-quote-figure { border: none; text-align: center; }\n\n/* ── Feature split ────────────────────────────────────────────────── */\n.squisq-page-feature { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }\n.squisq-page-feature--media-right .squisq-page-feature-media { order: 2; }\n.squisq-page-feature-media img { width: 100%; object-fit: cover; }\n.squisq-page-feature-title { font-size: 1.75rem; }\n.squisq-page-feature-body { color: var(--squisq-page-text-muted); font-size: 1.05rem; white-space: pre-line; margin: 0; }\n\n/* ── Media figure ─────────────────────────────────────────────────── */\n.squisq-page-figure { margin: 0; }\n.squisq-page-figure img, .squisq-page-figure video { width: 100%; display: block; }\n.squisq-page-figure figcaption { margin-top: 0.9em; font-size: 0.9rem; color: var(--squisq-page-text-muted); text-align: center; }\n.squisq-page-media-credit { font-size: 0.78rem; opacity: 0.75; }\n\n/* Media frame treatment (figures, features, gallery tiles, cards) */\n.squisq-page-media-frame { overflow: hidden; }\n.squisq-page[data-framing='rounded'] .squisq-page-media-frame { border-radius: var(--squisq-page-radius); }\n.squisq-page[data-framing='bordered'] .squisq-page-media-frame { border: 3px solid var(--squisq-page-text); }\n.squisq-page[data-framing='polaroid'] .squisq-page-media-frame {\n background: #ffffff;\n padding: 10px 10px 16px;\n border: 1px solid rgba(0, 0, 0, 0.12);\n border-radius: 2px;\n}\n.squisq-page[data-framing='letterboxed'] .squisq-page-media-frame img { aspect-ratio: 21 / 9; object-fit: cover; }\n.squisq-page[data-framing='circle-accent'] .squisq-page-media-frame { border-radius: calc(var(--squisq-page-radius) * 2); }\n.squisq-page .squisq-page-media-frame { box-shadow: var(--squisq-page-shadow); }\n\n/* Rich body nodes that the selected template did not consume. This universal\n * supplement keeps diagrams/media visible without making every template\n * duplicate the same preservation logic. */\n.squisq-page-rich-content {\n margin-top: clamp(1.5rem, 4vw, 3rem);\n padding-top: clamp(1.25rem, 3vw, 2rem);\n border-top: 1px solid var(--squisq-page-divider-color);\n}\n.squisq-page-rich-content :is(img, video) { display: block; max-width: 100%; height: auto; margin-inline: auto; }\n.squisq-page-rich-content .squisq-md-mermaid { min-height: min(520px, 62vh); margin-block: 0; }\n\n/* ── Gallery ──────────────────────────────────────────────────────── */\n.squisq-page-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.25rem; }\n.squisq-page-gallery .squisq-page-media-frame img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; }\n.squisq-page-gallery-caption { margin-top: 1.1rem; text-align: center; font-size: 0.9rem; color: var(--squisq-page-text-muted); }\n\n/* ── Callout ──────────────────────────────────────────────────────── */\n.squisq-page-callout {\n border-radius: var(--squisq-page-radius);\n border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 32%, transparent);\n border-left: 5px solid var(--squisq-page-accent);\n background: color-mix(in srgb, var(--squisq-page-accent) 7%, var(--squisq-page-bg));\n padding: 1.75rem 2rem;\n box-shadow: var(--squisq-page-shadow);\n display: flex;\n gap: 1.75rem;\n align-items: flex-start;\n}\n.squisq-page-callout-title { font-family: var(--squisq-page-title-font); font-size: 1.35rem; font-weight: 700; margin: 0 0 0.5em; }\n.squisq-page-callout-body { margin: 0; white-space: pre-line; }\n.squisq-page-callout-meta { margin-top: 0.9em; font-size: 0.82rem; color: var(--squisq-page-text-muted); }\n.squisq-page-callout .squisq-page-media-frame { flex: 0 0 132px; }\n.squisq-page-callout .squisq-page-media-frame img { width: 132px; height: 132px; object-fit: cover; }\n.squisq-page-callout[data-hint-framing='circle-accent'] .squisq-page-media-frame,\n.squisq-page-callout[data-hint-framing='circle-accent'] .squisq-page-media-frame img { border-radius: 50%; }\n.squisq-page-section--v-definition .squisq-page-callout-title { font-style: italic; }\n.squisq-page-section--v-diagnostic .squisq-page-callout { border-left-color: var(--squisq-page-highlight); }\n\n/* ── Card grid ────────────────────────────────────────────────────── */\n.squisq-page-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; }\n.squisq-page-card {\n border-radius: var(--squisq-page-radius);\n background: var(--squisq-page-bg-alt);\n border-top: 4px solid var(--squisq-page-card-accent, var(--squisq-page-accent));\n padding: 1.75rem 1.75rem 1.9rem;\n box-shadow: var(--squisq-page-shadow);\n}\n.squisq-page-card-title { font-family: var(--squisq-page-title-font); font-size: 1.3rem; margin: 0 0 0.4em; }\n.squisq-page-card-body { margin: 0; color: var(--squisq-page-text-muted); white-space: pre-line; }\n.squisq-page-cards-title { text-align: center; font-size: 1.9rem; margin-bottom: 1.75rem; }\n\n/* ── Item list ────────────────────────────────────────────────────── */\n.squisq-page-items { list-style: none; margin: 0; padding: 0; counter-reset: squisq-item; max-width: 40em; }\n.squisq-page-items li {\n counter-increment: squisq-item;\n position: relative;\n padding: 0.9em 0 0.9em 3.4em;\n font-size: 1.1rem;\n}\n.squisq-page-items li + li { border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-items li::before {\n content: counter(squisq-item, decimal-leading-zero);\n position: absolute;\n left: 0;\n top: 0.85em;\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n color: var(--squisq-page-accent);\n font-size: 1.15em;\n}\n.squisq-page[data-numerals='mono'] .squisq-page-items li::before { font-family: var(--squisq-page-mono-font); }\n.squisq-page-items-title { font-size: 1.9rem; }\n\n/* ── Timeline rail (dateEvent) ────────────────────────────────────── */\n.squisq-page-section--timeline-rail { padding-block: 1.4rem; }\n.squisq-page-section--timeline-rail:first-child { padding-top: var(--squisq-page-section-pad); }\n.squisq-page-milestone { display: grid; grid-template-columns: 150px 1fr; gap: 2rem; align-items: baseline; position: relative; }\n.squisq-page-milestone-date {\n font-family: var(--squisq-page-title-font);\n font-weight: 700;\n color: var(--squisq-page-accent);\n font-size: 1.05rem;\n text-align: right;\n}\n.squisq-page-milestone-rail {\n position: absolute;\n left: 166px;\n top: -1.4rem;\n bottom: -1.4rem;\n width: 2px;\n background: color-mix(in srgb, var(--squisq-page-accent) 35%, transparent);\n}\n.squisq-page-milestone-rail::after {\n content: '';\n position: absolute;\n left: 50%;\n top: 0.55em;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n transform: translateX(-50%);\n background: var(--squisq-page-accent);\n border: 2px solid var(--squisq-page-bg);\n}\n.squisq-page-milestone-body { padding-left: 2.25rem; white-space: pre-line; }\n.squisq-page-milestone-footer { margin-top: 0.5em; font-size: 0.85rem; color: var(--squisq-page-text-muted); }\n\n/* ── Table section ────────────────────────────────────────────────── */\n.squisq-page-table-title { font-size: 1.9rem; }\n.squisq-page-table-scroll { overflow-x: auto; border-radius: var(--squisq-page-radius); box-shadow: var(--squisq-page-shadow); }\n.squisq-page-table { width: 100%; border-collapse: collapse; font-size: 0.98rem; }\n.squisq-page-table th {\n background: var(--squisq-page-accent-bg);\n color: var(--squisq-page-accent-text);\n font-family: var(--squisq-page-title-font);\n text-align: left;\n padding: 0.8em 1em;\n}\n.squisq-page-table td { padding: 0.7em 1em; border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-table tbody tr:nth-child(even) { background: color-mix(in srgb, var(--squisq-page-text) 3.5%, transparent); }\n\n/* ── Canvas embed (spatial SVG) ───────────────────────────────────── */\n.squisq-page-canvas {\n width: 100%;\n margin-inline: auto;\n overflow: hidden;\n border-radius: var(--squisq-page-radius);\n}\n.squisq-page-canvas svg { display: block; width: 100%; height: 100%; }\n.squisq-page-canvas--framed { border: 1px solid var(--squisq-page-divider-color); box-shadow: var(--squisq-page-shadow); }\n.squisq-page-canvas--terminal { border: 1px solid color-mix(in srgb, var(--squisq-page-accent) 45%, transparent); }\n.squisq-page-canvas--terminal::before {\n content: '\\\\25CF \\\\25CF \\\\25CF';\n display: block;\n font-size: 9px;\n letter-spacing: 4px;\n padding: 6px 12px;\n color: color-mix(in srgb, var(--squisq-page-accent) 70%, transparent);\n background: color-mix(in srgb, var(--squisq-page-accent) 9%, var(--squisq-page-bg));\n border-bottom: 1px solid color-mix(in srgb, var(--squisq-page-accent) 30%, transparent);\n}\n\n/* ── Prose ────────────────────────────────────────────────────────── */\n.squisq-page-section--prose { padding-block: calc(var(--squisq-page-section-pad) * 0.45); }\n.squisq-page[data-divider] .squisq-page-section--prose + .squisq-page-section--prose { border-top: none; }\n.squisq-page-prose { font-size: 1.05rem; }\n.squisq-page-prose p { margin: 0; }\n.squisq-page-prose p + p { margin-top: 1.25em; }\n.squisq-page-prose > * + * { margin-top: 1.1em; }\n.squisq-page-prose a { color: var(--squisq-page-primary); text-decoration-color: color-mix(in srgb, var(--squisq-page-primary) 40%, transparent); }\n.squisq-page-prose code { font-family: var(--squisq-page-mono-font); font-size: 0.9em; background: color-mix(in srgb, var(--squisq-page-text) 8%, transparent); border-radius: 4px; padding: 0.12em 0.35em; }\n.squisq-page-prose pre { background: color-mix(in srgb, var(--squisq-page-text) 6%, transparent); border-radius: var(--squisq-page-radius); padding: 1em 1.25em; overflow-x: auto; }\n.squisq-page-prose pre code { background: none; padding: 0; }\n.squisq-page-prose blockquote { margin: 0; border-left: 4px solid var(--squisq-page-accent); padding-left: 1.25em; color: var(--squisq-page-text-muted); }\n.squisq-page-prose ul, .squisq-page-prose ol { padding-left: 1.5em; margin: 0; }\n.squisq-page-prose li + li { margin-top: 0.4em; }\n.squisq-page-prose hr { border: none; border-top: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-prose table { width: 100%; border-collapse: collapse; }\n.squisq-page-prose th { font-family: var(--squisq-page-title-font); text-align: left; padding: 0.6em 0.8em; border-bottom: 2px solid var(--squisq-page-divider-color); }\n.squisq-page-prose td { padding: 0.55em 0.8em; border-bottom: 1px solid var(--squisq-page-divider-color); }\n.squisq-page-prose img { border-radius: var(--squisq-page-radius); }\n.squisq-page-prose h1, .squisq-page-prose h2, .squisq-page-prose h3,\n.squisq-page-prose h4, .squisq-page-prose h5, .squisq-page-prose h6 {\n font-family: var(--squisq-page-title-font);\n font-weight: var(--squisq-page-title-weight);\n line-height: 1.2;\n margin: 0 0 0.45em;\n}\n.squisq-page-prose h1 { font-size: 2.1rem; }\n.squisq-page-prose h2 { font-size: 1.65rem; }\n.squisq-page-prose h3 { font-size: 1.35rem; }\n.squisq-page-prose h4, .squisq-page-prose h5, .squisq-page-prose h6 { font-size: 1.15rem; }\n.squisq-page-section--prose[data-hint-drop-cap] .squisq-page-prose > p:first-child::first-letter {\n font-family: var(--squisq-page-title-font);\n font-size: 3.4em;\n font-weight: 700;\n float: left;\n line-height: 0.85;\n padding-right: 0.12em;\n color: var(--squisq-page-accent);\n}\n\n/* ── Footer band ──────────────────────────────────────────────────── */\n.squisq-page-section--footer { text-align: center; }\n\n/* ── Thin-margin embedding (chat bubbles) ─────────────────────────── */\n.squisq-page--thin .squisq-page-section-inner { padding-inline: 0; }\n.squisq-page--thin .squisq-page-section { padding-block: 1.5rem; }\n\n/* Thumbnail image mode */\n.squisq-page--thumbnail-images .squisq-page-prose img,\n.squisq-page--thumbnail-images .squisq-page-figure img { max-width: 100px; max-height: 100px; object-fit: cover; }\n\n/* ── Reveal animation (progressive enhancement) ───────────────────── */\n@media (prefers-reduced-motion: no-preference) {\n .squisq-page-reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.55s ease, transform 0.55s ease; }\n .squisq-page-reveal--in { opacity: 1; transform: none; }\n}\n\n/* ── Responsive ───────────────────────────────────────────────────── */\n@container squisq-page (max-width: 720px) {\n${NARROW_RULES}\n}\n@supports not (container-type: inline-size) {\n @media (max-width: 720px) {\n${NARROW_RULES}\n }\n}\n`;\n\n/**\n * Complete stylesheet for a themed page: a `.squisq-page { … }` variable\n * block followed by the structural CSS. For string-HTML consumers; the\n * React view sets the vars inline instead.\n */\nexport function buildPageCss(theme?: Theme): string {\n const vars = buildPageCssVars(theme);\n const varLines = Object.entries(vars)\n .map(([name, value]) => ` ${name}: ${value};`)\n .join('\\n');\n return `.squisq-page {\\n${varLines}\\n}\\n${PAGE_BASE_CSS}`;\n}\n","/**\n * Apply narration timing from a document-anchored take to a Doc's block\n * timeline.\n *\n * When a doc carries a document-spanning narration clip (a preamble\n * `{[audio src=… anchor=document]}` → `doc.documentMedia`) whose\n * `.timing.json` sidecar has per-block ranges (v3, written by the\n * teleprompter's aligner), the blocks are re-timed so playback and\n * exports advance in sync with the recorded voice. Runs as step 0 of\n * `resolveAudioMapping`, so every surface that resolves audio gets it.\n *\n * Precedence: author-pinned `duration=`/`startTime=` heading attrs win\n * over narration ranges (a conflicting pin gets an `info` diagnostic);\n * narration ranges win over per-block audio-segment mapping and\n * reading-time estimates.\n */\n\nimport type { Block, Doc, DocDiagnostic } from '../schemas/Doc.js';\nimport type { MediaClip } from '../schemas/Media.js';\nimport type { ContentContainer } from '../storage/ContentContainer.js';\nimport { estimateTimeFromText } from '../timing/narrationTiming.js';\nimport { buildNarrationScript } from '../narration/script.js';\nimport {\n parseNarrationTimingJson,\n type NarrationTimingBlock,\n type NarrationTimingJsonV3,\n} from '../narration/sidecar.js';\nimport { flattenRenderableBlocks, getBlockBodyText, getPinnedBlockMeta } from './markdownToDoc.js';\nimport { scoreTextSimilarity } from './audioMapping.js';\n\nexport interface NarrationResolution {\n doc: Doc;\n /** False → the doc is returned unchanged (no clip / no sidecar / no match). */\n applied: boolean;\n /** The narration media path, for callers that bundle assets. */\n clipSrc?: string;\n}\n\n/** Minimum similarity for the fuzzy block-matching rung. */\nconst MIN_BLOCK_SIMILARITY = 0.5;\n/** Minimum whole-script similarity for the v1 proportional fallback. */\nconst MIN_V1_SCRIPT_SIMILARITY = 0.8;\n/** Pins that disagree with the narration range by more than this get a diagnostic. */\nconst PIN_CONFLICT_TOLERANCE_SEC = 1;\n\ninterface BlockRangeSec {\n startSec: number;\n endSec: number;\n}\n\n/** Spoken text of a block, mirroring the narration script builder. */\nfunction blockSpokenText(block: Block): string {\n const title = block.title ? block.title.trim() : '';\n const body = getBlockBodyText(block);\n if (title && body) return `${title}\\n${body}`;\n return title || body;\n}\n\n/**\n * Match sidecar block ranges to doc blocks with a deterministic ladder:\n * exact blockId → text similarity (greedy best-first, ≥ 0.5) →\n * in-order zip when the leftover counts agree. Unmatchable sidecar\n * blocks are dropped.\n */\nfunction matchSidecarBlocks(\n flat: Block[],\n timing: NarrationTimingJsonV3,\n): Map<string, BlockRangeSec> {\n const ranges = new Map<string, BlockRangeSec>();\n const remainingBlocks = new Set(flat.map((b) => b.id));\n const remainingSidecar: NarrationTimingBlock[] = [];\n\n const byId = new Map(flat.map((b) => [b.id, b]));\n for (const entry of timing.blocks) {\n if (entry.blockId && byId.has(entry.blockId) && remainingBlocks.has(entry.blockId)) {\n ranges.set(entry.blockId, { startSec: entry.startSec, endSec: entry.endSec });\n remainingBlocks.delete(entry.blockId);\n } else {\n remainingSidecar.push(entry);\n }\n }\n\n // Fuzzy rung: greedy best pair first, each side used once.\n if (remainingSidecar.length > 0 && remainingBlocks.size > 0) {\n const candidates: Array<{ score: number; entry: NarrationTimingBlock; blockId: string }> = [];\n for (const entry of remainingSidecar) {\n const slice = timing.sourceText.slice(entry.charStart, entry.charEnd);\n for (const block of flat) {\n if (!remainingBlocks.has(block.id)) continue;\n const score = scoreTextSimilarity(slice, blockSpokenText(block));\n if (score >= MIN_BLOCK_SIMILARITY) candidates.push({ score, entry, blockId: block.id });\n }\n }\n candidates.sort((a, b) => b.score - a.score || a.entry.blockIndex - b.entry.blockIndex);\n const usedEntries = new Set<NarrationTimingBlock>();\n for (const candidate of candidates) {\n if (usedEntries.has(candidate.entry) || !remainingBlocks.has(candidate.blockId)) continue;\n ranges.set(candidate.blockId, {\n startSec: candidate.entry.startSec,\n endSec: candidate.entry.endSec,\n });\n usedEntries.add(candidate.entry);\n remainingBlocks.delete(candidate.blockId);\n }\n // Order rung: leftover counts equal → zip in document/sidecar order.\n const leftoverEntries = remainingSidecar.filter((e) => !usedEntries.has(e));\n if (leftoverEntries.length > 0 && leftoverEntries.length === remainingBlocks.size) {\n const leftoverBlocks = flat.filter((b) => remainingBlocks.has(b.id));\n leftoverEntries.sort((a, b) => a.blockIndex - b.blockIndex);\n leftoverBlocks.forEach((block, i) => {\n const entry = leftoverEntries[i];\n ranges.set(block.id, { startSec: entry.startSec, endSec: entry.endSec });\n });\n }\n }\n\n return ranges;\n}\n\n/**\n * v1 fallback: no block ranges in the sidecar. If the take's source\n * text still narrates this doc (whole-script similarity ≥ 0.8), derive\n * per-block ranges by spoken-word proportion.\n */\nfunction proportionalRanges(\n doc: Doc,\n timing: NarrationTimingJsonV3,\n): Map<string, BlockRangeSec> | null {\n const script = buildNarrationScript(doc);\n if (script.blocks.length === 0) return null;\n if (scoreTextSimilarity(script.sourceText, timing.sourceText) < MIN_V1_SCRIPT_SIMILARITY) {\n return null;\n }\n const ranges = new Map<string, BlockRangeSec>();\n const starts = script.blocks.map((range) =>\n estimateTimeFromText(script.sourceText, range.charStart, timing.duration),\n );\n script.blocks.forEach((range, i) => {\n ranges.set(range.blockId, {\n startSec: starts[i],\n endSec: i + 1 < starts.length ? starts[i + 1] : timing.duration,\n });\n });\n return ranges;\n}\n\ninterface RetimeContext {\n clipStart: number;\n ranges: Map<string, BlockRangeSec>;\n diagnostics: DocDiagnostic[];\n /** Timeline cursor (doc seconds) for unmatched blocks. */\n cursor: number;\n}\n\n/** Recursively clone blocks, applying narration ranges to matched, unpinned blocks. */\nfunction retimeBlocks(blocks: Block[], ctx: RetimeContext): Block[] {\n return blocks.map((block) => {\n const range = ctx.ranges.get(block.id);\n const pinned = getPinnedBlockMeta(block);\n const next: Block = { ...block };\n\n if (range && pinned.duration == null && pinned.startTime == null) {\n next.startTime = ctx.clipStart + range.startSec;\n next.duration = Math.max(0, range.endSec - range.startSec);\n ctx.cursor = Math.max(ctx.cursor, next.startTime + next.duration);\n } else if (range) {\n // Author pins win; surface real disagreement as an info diagnostic.\n const pinnedStart = pinned.startTime ?? block.startTime;\n const pinnedDuration = pinned.duration ?? block.duration;\n const narrStart = ctx.clipStart + range.startSec;\n const narrDuration = Math.max(0, range.endSec - range.startSec);\n if (\n Math.abs(pinnedStart - narrStart) > PIN_CONFLICT_TOLERANCE_SEC ||\n Math.abs(pinnedDuration - narrDuration) > PIN_CONFLICT_TOLERANCE_SEC\n ) {\n ctx.diagnostics.push({\n severity: 'info',\n code: 'narration-pin-conflict',\n message:\n `Block timing is pinned (duration=/startTime=) but the recorded narration says ` +\n `~${narrDuration.toFixed(1)}s starting at ~${narrStart.toFixed(1)}s. The pin wins; ` +\n `remove it to follow the narration.`,\n blockId: block.id,\n });\n }\n ctx.cursor = Math.max(ctx.cursor, pinnedStart + pinnedDuration);\n } else {\n // No narration range (block added after the take, or unmatched):\n // keep its duration but place it at the running cursor so the\n // timeline stays monotonic.\n next.startTime = ctx.cursor;\n ctx.cursor += next.duration;\n }\n\n if (block.children && block.children.length > 0) {\n next.children = retimeBlocks(block.children, ctx);\n }\n return next;\n });\n}\n\n/**\n * Find the doc's document-anchored narration clip, load its timing\n * sidecar, and re-time the blocks from its ranges. Pure with respect to\n * the input doc — returns a new Doc (or the original when nothing\n * applies).\n */\nexport async function applyNarrationTiming(\n doc: Doc,\n container: ContentContainer,\n): Promise<NarrationResolution> {\n const clips: MediaClip[] = (doc.documentMedia ?? []).filter((c) => c.anchor === 'document');\n for (const clip of clips) {\n if (!clip.src) continue;\n const sidecarData = await container.readFile(`${clip.src}.timing.json`);\n if (!sidecarData) continue;\n const timing = parseNarrationTimingJson(sidecarData);\n if (!timing) continue;\n\n const flat = flattenRenderableBlocks(doc.blocks);\n const ranges =\n timing.blocks.length > 0 ? matchSidecarBlocks(flat, timing) : proportionalRanges(doc, timing);\n if (!ranges || ranges.size === 0) continue;\n\n const ctx: RetimeContext = {\n clipStart: clip.startAt,\n ranges,\n diagnostics: [],\n cursor: 0,\n };\n const blocks = retimeBlocks(doc.blocks, ctx);\n const duration = Math.max(clip.startAt + timing.duration, ctx.cursor);\n const retimed: Doc = {\n ...doc,\n blocks,\n duration,\n ...(ctx.diagnostics.length > 0\n ? { diagnostics: [...(doc.diagnostics ?? []), ...ctx.diagnostics] }\n : {}),\n };\n return { doc: retimed, applied: true, clipSrc: clip.src };\n }\n return { doc, applied: false };\n}\n","/**\n * Audio Mapping\n *\n * Associates audio segments (MP3 files) with document blocks.\n * Supports two modes:\n *\n * 1. **Explicit annotation**: Blocks with `{[audio=filename.mp3]}` in their\n * heading annotation are directly mapped to that audio file.\n *\n * 2. **Auto-matching**: When no annotations exist but the container has MP3s\n * with `.timing.json` files, matches MP3s to blocks by comparing the\n * timing.json `sourceText` against block text content (word overlap).\n * Falls back to filename-based matching (slugified title comparison).\n */\n\nimport type { Doc, Block, AudioSegment, AudioTimingData } from '../schemas/Doc.js';\nimport { resolveMediaSchedule } from '../schemas/Media.js';\nimport type { ContentContainer } from '../storage/ContentContainer.js';\nimport { extractPlainText } from '../markdown/utils.js';\nimport { applyNarrationTiming } from './applyNarrationTiming.js';\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\n/**\n * Parse a timing.json file from raw data.\n */\nfunction parseTimingJson(data: ArrayBuffer): AudioTimingData | null {\n try {\n const text = new TextDecoder().decode(data);\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed.sourceText === 'string' && typeof parsed.duration === 'number') {\n return {\n sourceText: parsed.sourceText,\n bookmarks: Array.isArray(parsed.bookmarks) ? parsed.bookmarks : [],\n duration: parsed.duration,\n };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Normalize text for comparison: lowercase, strip punctuation, split into word set.\n */\nfunction normalizeToWords(text: string): Set<string> {\n const words = text\n .toLowerCase()\n .replace(/[^\\w\\s]/g, ' ')\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n return new Set(words);\n}\n\n/**\n * Calculate Jaccard similarity between two texts (word overlap).\n * Returns 0–1 where 1 = identical word sets.\n */\nexport function scoreTextSimilarity(a: string, b: string): number {\n const wordsA = normalizeToWords(a);\n const wordsB = normalizeToWords(b);\n if (wordsA.size === 0 || wordsB.size === 0) return 0;\n\n let intersection = 0;\n for (const w of wordsA) {\n if (wordsB.has(w)) intersection++;\n }\n\n const union = new Set([...wordsA, ...wordsB]).size;\n return union > 0 ? intersection / union : 0;\n}\n\n/**\n * Slugify a title for filename comparison.\n * \"The Behring Gambit\" → \"the-behring-gambit\"\n */\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\n/**\n * Extract plain text from a block's contents and title.\n */\nfunction blockToPlainText(block: Block): string {\n const parts: string[] = [];\n if (block.title) parts.push(block.title);\n if (block.contents) {\n for (const node of block.contents) {\n parts.push(extractPlainText(node));\n }\n }\n return parts.join('\\n');\n}\n\n/**\n * Flatten a block tree into a linear array of leaf blocks\n * (blocks that represent actual content sections).\n */\nfunction flattenForAudio(blocks: Block[]): Block[] {\n const result: Block[] = [];\n for (const block of blocks) {\n if (block.children && block.children.length > 0) {\n result.push(...flattenForAudio(block.children));\n } else {\n result.push(block);\n }\n }\n return result;\n}\n\n/**\n * Info about a narration audio file found in the container.\n *\n * Covers MP3/WebM/MP4/Ogg/M4A audio files, including browser-recorder output.\n */\ninterface NarrationAudioInfo {\n /** Path in the container (e.g., \"audio/narration-2026.webm\"). */\n path: string;\n /** Filename without path (e.g., \"narration-2026.webm\"). */\n filename: string;\n /** Parsed timing data (if .timing.json exists). */\n timing: AudioTimingData | null;\n}\n\n/**\n * File extensions that unambiguously denote audio anywhere in the\n * container. These predate the recorder feature.\n */\nconst AUDIO_ONLY_EXTENSIONS = ['.mp3', '.wav', '.ogg', '.m4a'];\n\n/**\n * Extensions that could be audio or video — `.webm` and `.mp4` are the\n * containers `MediaRecorder` produces for browser-side narration, but\n * they're also used for video clips. Only treat them as narration when\n * they live under the `audio/` directory the recorder writes to.\n */\nconst AMBIGUOUS_EXTENSIONS = ['.webm', '.mp4'];\n\nfunction isNarrationAudioPath(path: string): boolean {\n const lower = path.toLowerCase();\n if (AUDIO_ONLY_EXTENSIONS.some((ext) => lower.endsWith(ext))) return true;\n if (AMBIGUOUS_EXTENSIONS.some((ext) => lower.endsWith(ext))) {\n return lower.startsWith('audio/');\n }\n return false;\n}\n\n/** Strip a known narration audio extension from a filename. */\nfunction stripAudioExtension(filename: string): string {\n const lower = filename.toLowerCase();\n for (const ext of [...AUDIO_ONLY_EXTENSIONS, ...AMBIGUOUS_EXTENSIONS]) {\n if (lower.endsWith(ext)) return filename.slice(0, -ext.length);\n }\n return filename;\n}\n\n// ── Core Functions ───────────────────────────────────────────────────\n\n/**\n * Parse a consolidated timing.json (version 2) which contains all section\n * timing data in a single file.\n */\nfunction parseConsolidatedTiming(data: ArrayBuffer): Record<string, AudioTimingData> | null {\n try {\n const text = new TextDecoder().decode(data);\n const parsed = JSON.parse(text);\n if (parsed && parsed.version === 2 && parsed.sections) {\n return parsed.sections as Record<string, AudioTimingData>;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Discover all narration audio files in a container and load their\n * timing data. Covers historical `.mp3`/`.wav`/`.ogg`/`.m4a` files\n * anywhere in the container plus `.webm`/`.mp4` files under `audio/`\n * (the destination the browser recorder writes to).\n *\n * Checks for a consolidated timing.json first, then falls back to\n * per-file `.timing.json` sidecars.\n */\nasync function discoverNarrationAudio(container: ContentContainer): Promise<NarrationAudioInfo[]> {\n const files = await container.listFiles();\n const audioFiles = files.filter((f) => isNarrationAudioPath(f.path));\n const results: NarrationAudioInfo[] = [];\n\n // Try to load consolidated timing.json\n let consolidatedSections: Record<string, AudioTimingData> | null = null;\n const consolidatedData = await container.readFile('timing.json');\n if (consolidatedData) {\n consolidatedSections = parseConsolidatedTiming(consolidatedData);\n }\n\n for (const file of audioFiles) {\n const filename = file.path.split('/').pop() ?? file.path;\n let timing: AudioTimingData | null = null;\n\n // Try consolidated timing first: match section name from filename\n if (consolidatedSections) {\n const audioBase = stripAudioExtension(filename);\n for (const [sectionName, sectionTiming] of Object.entries(consolidatedSections)) {\n if (audioBase.endsWith(`-${sectionName}`)) {\n timing = sectionTiming;\n break;\n }\n }\n }\n\n // Fall back to per-file .timing.json\n if (!timing) {\n const timingPath = `${file.path}.timing.json`;\n const timingData = await container.readFile(timingPath);\n if (timingData) {\n timing = parseTimingJson(timingData);\n }\n }\n\n results.push({ path: file.path, filename, timing });\n }\n\n return results;\n}\n\n/**\n * Resolve audio from explicit `{[audio=filename.mp3]}` annotations on blocks.\n * Returns the matched pairs or an empty array if no annotations found.\n */\nfunction resolveFromAnnotations(\n blocks: Block[],\n audioFiles: NarrationAudioInfo[],\n): Array<{ block: Block; audio: NarrationAudioInfo }> {\n const matches: Array<{ block: Block; audio: NarrationAudioInfo }> = [];\n const flat = flattenForAudio(blocks);\n\n for (const block of flat) {\n const audioRef = block.templateOverrides?.audio;\n if (!audioRef) continue;\n\n // Find the narration file by filename (exact or suffix match).\n const audio = audioFiles.find(\n (m) => m.filename === audioRef || m.path === audioRef || m.path.endsWith(`/${audioRef}`),\n );\n\n if (audio) {\n matches.push({ block, audio });\n }\n }\n\n return matches;\n}\n\n/** Minimum similarity score to consider a content match. */\nconst MIN_CONTENT_SIMILARITY = 0.35;\n\n/** Minimum similarity score for filename-based matching. */\nconst MIN_FILENAME_SIMILARITY = 0.5;\n\n/**\n * Auto-match narration files to blocks by content similarity.\n * Uses timing.json sourceText when available, falls back to filename matching.\n */\nfunction autoMatchBlocks(\n blocks: Block[],\n audioFiles: NarrationAudioInfo[],\n): Array<{ block: Block; audio: NarrationAudioInfo; score: number }> {\n const flat = flattenForAudio(blocks);\n if (flat.length === 0 || audioFiles.length === 0) return [];\n\n // Score all (audio, block) pairs.\n const scoredPairs: Array<{\n block: Block;\n blockIndex: number;\n audio: NarrationAudioInfo;\n audioIndex: number;\n score: number;\n }> = [];\n\n for (let audioIndex = 0; audioIndex < audioFiles.length; audioIndex++) {\n const audio = audioFiles[audioIndex];\n\n for (let bi = 0; bi < flat.length; bi++) {\n const block = flat[bi];\n const blockText = blockToPlainText(block);\n if (!blockText.trim()) continue;\n\n let score = 0;\n\n // Primary: content similarity via timing.json sourceText\n if (audio.timing?.sourceText) {\n score = scoreTextSimilarity(audio.timing.sourceText, blockText);\n }\n\n // Fallback: filename-based matching\n if (score < MIN_CONTENT_SIMILARITY && block.title) {\n const titleSlug = slugify(block.title);\n const fileSlug = slugify(stripAudioExtension(audio.filename));\n // Check if the title slug appears in the filename slug\n if (fileSlug.includes(titleSlug) && titleSlug.length >= 3) {\n score = Math.max(score, MIN_FILENAME_SIMILARITY + 0.1);\n }\n }\n\n if (score >= MIN_CONTENT_SIMILARITY) {\n scoredPairs.push({ block, blockIndex: bi, audio, audioIndex, score });\n }\n }\n }\n\n // Greedy assignment: highest score first, each audio file and block at most once.\n scoredPairs.sort((a, b) => b.score - a.score);\n const usedBlocks = new Set<number>();\n const usedAudio = new Set<number>();\n const matches: Array<{ block: Block; audio: NarrationAudioInfo; score: number }> = [];\n\n for (const pair of scoredPairs) {\n if (usedBlocks.has(pair.blockIndex) || usedAudio.has(pair.audioIndex)) continue;\n usedBlocks.add(pair.blockIndex);\n usedAudio.add(pair.audioIndex);\n matches.push({ block: pair.block, audio: pair.audio, score: pair.score });\n }\n\n return matches;\n}\n\n// ── Public API ───────────────────────────────────────────────────────\n\n/**\n * Resolve audio mapping for a Doc using a ContentContainer.\n *\n * Tries explicit `{[audio=filename.mp3]}` annotations first,\n * then falls back to auto-matching by content similarity.\n *\n * Returns a new Doc with `audio.segments` populated and blocks\n * assigned to the correct `audioSegment` indices.\n *\n * @param doc - The source Doc (not mutated).\n * @param container - ContentContainer with narration and timing files.\n * @returns New Doc with audio segments resolved, or original doc if no matches.\n */\nexport async function resolveAudioMapping(doc: Doc, container: ContentContainer): Promise<Doc> {\n // Step 0: a document-anchored narration take (preamble `{[audio src=…\n // anchor=document]}` + v3 timing sidecar) re-times the block timeline\n // to the recorded voice. See applyNarrationTiming for precedence.\n const narration = await applyNarrationTiming(doc, container);\n doc = narration.doc;\n\n const audioFiles = await discoverNarrationAudio(container);\n\n // Files already playing through the media schedule (documentMedia /\n // block clips) must not ALSO be auto-mapped into audio.segments —\n // that would play the narration twice.\n const scheduledSrcs = new Set(resolveMediaSchedule(doc).map((clip) => clip.src));\n const available = audioFiles.filter((f) => !scheduledSrcs.has(f.path));\n if (available.length === 0) return doc;\n\n // Try annotations first\n let matches = resolveFromAnnotations(doc.blocks, available);\n\n // Fall back to auto-matching if no annotations found. When narration\n // timing was applied, content auto-matching is skipped — the take owns\n // the timeline, and fuzzy matches against other files would fight it.\n if (matches.length === 0 && !narration.applied) {\n matches = autoMatchBlocks(doc.blocks, available).map((m) => ({\n block: m.block,\n audio: m.audio,\n }));\n }\n\n if (matches.length === 0) return doc;\n\n // Build audio segments in document order\n // Sort matches by the block's position in the flattened tree\n const flat = flattenForAudio(doc.blocks);\n const blockOrder = new Map(flat.map((b, i) => [b.id, i]));\n matches.sort((a, b) => (blockOrder.get(a.block.id) ?? 0) - (blockOrder.get(b.block.id) ?? 0));\n\n // Build segment list and assign indices\n const segments: AudioSegment[] = [];\n const blockToSegment = new Map<string, number>();\n let startTime = 0;\n\n for (let i = 0; i < matches.length; i++) {\n const { block, audio } = matches[i];\n const duration = audio.timing?.duration ?? 30; // Fallback duration if no timing\n\n segments.push({\n src: audio.path,\n name: block.title ?? block.id,\n duration,\n startTime,\n });\n\n blockToSegment.set(block.id, i);\n startTime += duration;\n }\n\n // Deep clone blocks and assign audioSegment indices\n const newBlocks = assignSegmentIndices(doc.blocks, blockToSegment);\n\n return {\n ...doc,\n blocks: newBlocks,\n // A narration take owns the overall duration; explicit per-block\n // segments only ever extend it.\n duration: narration.applied ? Math.max(doc.duration, startTime) : startTime,\n audio: { segments },\n };\n}\n\n/**\n * Recursively clone blocks and assign audioSegment indices.\n * Blocks not in the map keep their original audioSegment.\n * Children of a matched block inherit the parent's segment.\n */\nfunction assignSegmentIndices(\n blocks: Block[],\n blockToSegment: Map<string, number>,\n inheritedSegment?: number,\n): Block[] {\n return blocks.map((block) => {\n const segment = blockToSegment.get(block.id) ?? inheritedSegment ?? block.audioSegment;\n const newBlock: Block = {\n ...block,\n audioSegment: segment,\n };\n\n if (block.children) {\n newBlock.children = assignSegmentIndices(block.children, blockToSegment, segment);\n }\n\n return newBlock;\n });\n}\n","/**\n * Markdown document validation.\n *\n * `validateMarkdownSource()` gives authors and agents fast, structural\n * feedback on a squisq markdown document — the same checks the renderer\n * applies, surfaced as diagnostics instead of degraded slides:\n *\n * - unknown template names (with a did-you-mean suggestion)\n * - unknown drawing shapes, and shape annotations used outside a `{[drawing]}`\n * - `{[…]}` text that was not recognized as an annotation (bad quoting,\n * non-heading placement, unknown inline icon)\n * - malformed heading-attribute values (`x=abc`, bad `startTime`) and\n * non-numeric drawing-shape geometry\n * - `connectsTo` / drawing `from`/`to` targets that don't resolve,\n * duplicate block ids, unparseable data fences (reported by `markdownToDoc`)\n * - image references missing from the provided asset set (.dbk contents)\n *\n * The CLI exposes this as `squisq validate <input>`; agents can also call\n * it directly and iterate until the diagnostics list is empty.\n */\n\nimport type { Doc, Block, DocDiagnostic } from '../schemas/Doc.js';\nimport type {\n MarkdownDocument,\n MarkdownHeading,\n MarkdownNode,\n HtmlNode,\n} from '../markdown/types.js';\nimport { parseMarkdown } from '../markdown/parse.js';\nimport { getChildren, extractPlainText } from '../markdown/utils.js';\nimport { coerceAnnotationValues, KNOWN_BLOCK_META_KEYS } from '../markdown/annotationCoercion.js';\nimport { markdownToDoc, flattenBlocks } from './markdownToDoc.js';\nimport { parseStandaloneAnnotation } from './standaloneAnnotation.js';\nimport { isDataFence, parseDataFence } from './structuredData.js';\nimport { deriveTemplateInputs } from './templateInputs.js';\nimport { lintTemplateParams } from './templates/inputDescriptors.js';\nimport {\n templateRegistry,\n resolveTemplateName,\n isShapeName,\n normalizeShapeKind,\n SHAPE_NAMES,\n} from './templates/index.js';\nimport { TEMPLATE_ALIASES } from './templates/templateNames.js';\nimport { nearestName } from './utils/nearest.js';\n\n// ============================================\n// Options & result\n// ============================================\n\nexport interface ValidateOptions {\n /**\n * Known asset paths for image/video reference checks — typically the\n * file list of a .dbk container or the document's folder. Relative\n * references not present here produce a `missing-asset` warning.\n * When omitted, asset checks are skipped.\n */\n assets?: ReadonlySet<string> | ((path: string) => boolean);\n\n /**\n * Additional template names to accept beyond the built-in registry and\n * the document's own `customTemplates` (e.g. app-registered templates).\n */\n extraTemplates?: readonly string[];\n}\n\nexport interface MarkdownValidationResult {\n /** All findings, in source order where line information exists. */\n diagnostics: DocDiagnostic[];\n errorCount: number;\n warningCount: number;\n infoCount: number;\n /** The converted Doc (conversion diagnostics are included above). */\n doc: Doc;\n}\n\n// ============================================\n// Entry points\n// ============================================\n\n/**\n * Validate a squisq markdown source string. Parses, converts (collecting\n * the conversion's own diagnostics), and runs the structural checks above.\n */\nexport function validateMarkdownSource(\n source: string,\n options?: ValidateOptions,\n): MarkdownValidationResult {\n return validateMarkdownDoc(parseMarkdown(source), options);\n}\n\n/**\n * Validate an already-parsed MarkdownDocument. See {@link validateMarkdownSource}.\n */\nexport function validateMarkdownDoc(\n markdownDoc: MarkdownDocument,\n options?: ValidateOptions,\n): MarkdownValidationResult {\n const doc = markdownToDoc(markdownDoc);\n const diagnostics: DocDiagnostic[] = [...(doc.diagnostics ?? [])];\n const blocks = flattenBlocks(doc.blocks);\n\n const knownTemplates = collectKnownTemplates(doc, options);\n // Custom template names are skipped by the input linter — they carry\n // arbitrary author-defined inputs the built-in descriptors can't know about.\n const customNames = new Set<string>(doc.customTemplates?.map((t) => t.name) ?? []);\n\n // Parent-aware walk: a `{[shape]}` annotation is only meaningful on the\n // direct child of a `{[drawing]}` block, so the template check needs each\n // block's parent. Drawing connectors are validated against their siblings.\n const visit = (block: Block, parent: Block | undefined): void => {\n checkTemplate(block, parent, knownTemplates, diagnostics);\n checkAttributeCoercion(block, parent, diagnostics);\n checkConflictingAnnotationKeys(block, diagnostics);\n checkTemplateInputs(block, parent, customNames, diagnostics);\n checkPossibleDataFences(block, diagnostics);\n if (isDrawingBlock(block)) checkDrawingConnectors(block, diagnostics);\n for (const child of block.children ?? []) visit(child, block);\n };\n for (const block of doc.blocks) visit(block, undefined);\n\n checkUnrecognizedAnnotations(markdownDoc, diagnostics);\n\n if (options?.assets) {\n const hasAsset = normalizeAssetCheck(options.assets);\n checkAssets(markdownDoc, blocks, hasAsset, diagnostics);\n }\n\n diagnostics.sort(\n (a, b) => (a.line ?? Number.MAX_SAFE_INTEGER) - (b.line ?? Number.MAX_SAFE_INTEGER),\n );\n\n return {\n diagnostics,\n errorCount: diagnostics.filter((d) => d.severity === 'error').length,\n warningCount: diagnostics.filter((d) => d.severity === 'warning').length,\n infoCount: diagnostics.filter((d) => d.severity === 'info').length,\n doc,\n };\n}\n\n// ============================================\n// Template checks\n// ============================================\n\nfunction collectKnownTemplates(doc: Doc, options?: ValidateOptions): Set<string> {\n return new Set<string>([\n ...Object.keys(templateRegistry),\n ...Object.keys(TEMPLATE_ALIASES),\n ...(doc.customTemplates?.map((t) => t.name) ?? []),\n ...(options?.extraTemplates ?? []),\n ]);\n}\n\n/** True when `block` is a `{[drawing]}` container (after alias resolution). */\nfunction isDrawingBlock(block: Block): boolean {\n return resolveTemplateName(block.template ?? '') === 'drawing';\n}\n\nfunction checkTemplate(\n block: Block,\n parent: Block | undefined,\n known: Set<string>,\n diagnostics: DocDiagnostic[],\n): void {\n // Heading blocks carry the requested name on the heading annotation;\n // heading-less standalone blocks carry it on `sourceAnnotation` (raw,\n // un-resolved) — read whichever is present.\n const requested =\n block.sourceHeading?.templateAnnotation?.template ?? block.sourceAnnotation?.template;\n if (!requested) return;\n\n // Inside a drawing, the annotation names a shape primitive, not a template.\n if (parent && isDrawingBlock(parent)) {\n if (isShapeName(requested)) return;\n const suggestion = nearestName(requested, new Set(SHAPE_NAMES), {\n map: resolveTemplateName,\n });\n diagnostics.push({\n severity: 'warning',\n code: 'unknown-shape',\n message:\n `Unknown shape \"${requested}\" in drawing — the child will be skipped` +\n (suggestion ? `. Did you mean \"${suggestion}\"?` : ''),\n blockId: block.id,\n ...lineOf(block),\n });\n return;\n }\n\n // A shape annotation outside a drawing has no parent to interpret it.\n if (isShapeName(requested)) {\n diagnostics.push({\n severity: 'warning',\n code: 'shape-outside-drawing',\n message: `Shape \"${requested}\" is only recognized on a child heading of a {[drawing]} block`,\n blockId: block.id,\n ...lineOf(block),\n });\n return;\n }\n\n if (known.has(requested) || known.has(resolveTemplateName(requested))) return;\n\n const suggestion = nearestName(requested, known, { map: resolveTemplateName });\n diagnostics.push({\n severity: 'warning',\n code: 'unknown-template',\n message:\n `Unknown template \"${requested}\" — the block will render as a plain fallback card` +\n (suggestion ? `. Did you mean \"${suggestion}\"?` : ''),\n blockId: block.id,\n ...lineOf(block),\n });\n}\n\n/**\n * Lint a template block's `{[…]}` inputs against the built-in input\n * descriptors: unknown keys (with a did-you-mean), values outside a closed\n * enum / that fail coercion, and missing required inputs. All are warnings.\n *\n * Only built-in templates with descriptors are checked — shapes, drawing\n * children, custom templates, and not-yet-described built-ins are skipped\n * (`lintTemplateParams` returns `[]` for the latter). A `missing-input`\n * finding is suppressed when the value is actually satisfiable from the\n * block's own fields, structured data, or body derivation.\n */\nfunction checkTemplateInputs(\n block: Block,\n parent: Block | undefined,\n customNames: ReadonlySet<string>,\n diagnostics: DocDiagnostic[],\n): void {\n const requested = block.sourceHeading?.templateAnnotation?.template;\n if (!requested) return;\n // Inside a drawing, the annotation names a shape primitive, not a template.\n if (parent && isDrawingBlock(parent)) return;\n if (isShapeName(requested)) return;\n\n const canonical = resolveTemplateName(requested);\n if (customNames.has(requested) || customNames.has(canonical)) return;\n\n const params = block.sourceHeading?.templateAnnotation?.params ?? {};\n for (const finding of lintTemplateParams(canonical, params)) {\n if (finding.kind === 'missing-input' && isInputSatisfiable(canonical, block, finding.key)) {\n continue;\n }\n diagnostics.push({\n severity: 'warning',\n code: finding.kind,\n message: `Block \"${block.id}\": ${finding.message}`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n}\n\n/**\n * Whether a required template input is satisfiable even though it's absent\n * from the `{[…]}` params: present in a structured-data fence, carried as a\n * block-level field (e.g. `title` from the heading), or derivable from the\n * heading + body (`deriveTemplateInputs` in strict mode).\n */\nfunction isInputSatisfiable(canonical: string, block: Block, key: string): boolean {\n if (block.templateData && key in block.templateData) return true;\n if ((block as unknown as Record<string, unknown>)[key] != null) return true;\n const derived = deriveTemplateInputs(canonical, block.title ?? '', block.contents);\n return derived != null && key in derived;\n}\n\n/** Numeric geometry keys carried in a shape's `{[…]}` params. */\nconst NUMERIC_SHAPE_KEYS = ['x', 'y', 'width', 'height', 'w', 'h', 'strokeWidth', 'borderRadius'];\n\n/** Re-run heading-attribute coercion to surface its warnings with context. */\nfunction checkAttributeCoercion(\n block: Block,\n parent: Block | undefined,\n diagnostics: DocDiagnostic[],\n): void {\n // Pandoc `{#id key=value}` params (x/y/connectsTo/startTime/duration).\n const params = block.sourceHeading?.attributes?.params;\n if (params) {\n const { warnings } = coerceAnnotationValues(params);\n for (const warning of warnings) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-attribute',\n message: `Block \"${block.id}\": ${warning}`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n }\n\n // A drawing shape's geometry lives in its `{[shape …]}` params\n // (templateOverrides), not the Pandoc block — validate those numerics too.\n if (parent && isDrawingBlock(parent) && isShapeName(block.template)) {\n const overrides = block.templateOverrides ?? {};\n for (const key of NUMERIC_SHAPE_KEYS) {\n const raw = overrides[key];\n if (raw == null) continue;\n const value = raw.replace(/,\\s*$/, '').trim();\n if (value !== '' && !Number.isFinite(Number(value))) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-attribute',\n message: `Drawing shape \"${block.id}\": \"${key}\" is not a number (${JSON.stringify(raw)})`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n }\n }\n}\n\n/**\n * A heading can carry the same block-meta key in both the Pandoc `{k=v}`\n * block and the squiggly `{[tpl k=v]}` annotation. The Pandoc value wins\n * (same precedence as `makeBlock` in markdownToDoc), which is easy to miss\n * when the two disagree — surface an info diagnostic so the author knows\n * which value is in effect.\n */\nfunction checkConflictingAnnotationKeys(block: Block, diagnostics: DocDiagnostic[]): void {\n const annotationParams = block.sourceHeading?.templateAnnotation?.params;\n const pandocParams = block.sourceHeading?.attributes?.params;\n if (!annotationParams || !pandocParams) return;\n\n for (const key of Object.keys(KNOWN_BLOCK_META_KEYS)) {\n const fromAnnotation = annotationParams[key];\n const fromPandoc = pandocParams[key];\n if (fromAnnotation == null || fromPandoc == null || fromAnnotation === fromPandoc) continue;\n diagnostics.push({\n severity: 'info',\n code: 'conflicting-annotation-key',\n message:\n `\"${key}\" is set in both {[…]} (${fromAnnotation}) and {…} (${fromPandoc}) — ` +\n `the {…} value wins.`,\n blockId: block.id,\n ...lineOf(block),\n });\n }\n}\n\n/**\n * A drawing's `line`/`arrow` connectors reference sibling shapes by id via\n * `from`/`to`; flag any that don't resolve (mirrors the `connectsTo`\n * unresolved-connection check, but for the `{[…]}` param form).\n */\nfunction checkDrawingConnectors(block: Block, diagnostics: DocDiagnostic[]): void {\n const children = block.children ?? [];\n const ids = new Set(children.map((c) => c.id));\n for (const child of children) {\n const kind = normalizeShapeKind(child.sourceHeading?.templateAnnotation?.template);\n if (kind !== 'line' && kind !== 'arrow') continue;\n const overrides = child.templateOverrides ?? {};\n for (const key of ['from', 'to'] as const) {\n const raw = overrides[key];\n if (raw == null) continue;\n const ref = raw.replace(/,\\s*$/, '').trim();\n if (ref && !ids.has(ref)) {\n diagnostics.push({\n severity: 'warning',\n code: 'unresolved-connection',\n message: `Drawing connector \"${child.id}\" references unknown ${key} \"${ref}\"`,\n blockId: child.id,\n ...lineOf(child),\n });\n }\n }\n }\n}\n\n/**\n * A plain ```json / ```yaml fence (no `data` marker) inside a template-\n * annotated block, whose content parses as a top-level object, is almost\n * certainly meant as template input — surface an info nudge to add the\n * `data` marker. Deliberately scoped to *annotated* blocks so ordinary code\n * samples in prose sections never trigger it.\n */\nfunction checkPossibleDataFences(block: Block, diagnostics: DocDiagnostic[]): void {\n const annotated = !!(\n block.sourceHeading?.templateAnnotation?.template || block.sourceAnnotation?.template\n );\n if (!annotated) return;\n\n for (const node of block.contents ?? []) {\n if (node.type !== 'code') continue;\n const lang = node.lang?.toLowerCase();\n if (lang !== 'json' && lang !== 'yaml' && lang !== 'yml') continue;\n if (isDataFence(node)) continue; // already a data fence — nothing to nudge\n\n const result = parseDataFence(node);\n if (!result.data || Object.keys(result.data).length === 0) continue;\n\n diagnostics.push({\n severity: 'info',\n code: 'possible-data-fence',\n message:\n `This ${lang} block renders as code — add \"data\" to the fence ` +\n `(\\`\\`\\`${lang} data) if it's meant as template input.`,\n blockId: block.id,\n ...(node.position ? { line: node.position.start.line } : lineOf(block)),\n });\n }\n}\n\n// ============================================\n// Unrecognized `{[…]}` text\n// ============================================\n\nconst ANNOTATION_LIKE_RE = /\\{\\[/;\n\n/**\n * Flag literal `{[` text that survived parsing. On a heading this usually\n * means broken quoting; in body content it usually means the author\n * expected list-item/paragraph annotations, which only headings support\n * (or referenced an unknown inline icon).\n */\nfunction checkUnrecognizedAnnotations(\n markdownDoc: MarkdownDocument,\n diagnostics: DocDiagnostic[],\n): void {\n const walk = (node: MarkdownNode, headingLine: number | undefined, topLevel: boolean): void => {\n if (node.type === 'heading') {\n const heading = node as MarkdownHeading;\n const text = extractPlainText(heading);\n if (ANNOTATION_LIKE_RE.test(text)) {\n diagnostics.push({\n severity: 'warning',\n code: 'unparsed-annotation',\n message:\n `Heading \"${truncate(text)}\" contains \"{[…]}\" text that was not recognized — ` +\n `check the quoting, or whether the token is a known inline icon`,\n ...(heading.position ? { line: heading.position.start.line } : {}),\n });\n }\n return; // heading inline children already covered by extractPlainText\n }\n // A *top-level* paragraph that is exactly a `{[templateName …]}` /\n // `{[audio …]}` annotation is recognized (it becomes a standalone template\n // block or a media clip) — don't flag it, and don't descend into its text.\n // Nested paragraphs (inside a list / blockquote) are NOT extracted, so\n // they still warn.\n if (node.type === 'paragraph' && topLevel) {\n const parsed = parseStandaloneAnnotation(node);\n if (parsed && parsed.template != null) return;\n }\n if (node.type === 'text' && ANNOTATION_LIKE_RE.test(node.value)) {\n diagnostics.push({\n severity: 'warning',\n code: 'unparsed-annotation',\n message:\n `Body text contains \"{[…]}\" — template annotations are recognized on headings ` +\n `and as standalone paragraphs (or the token is not a known inline icon)`,\n ...(node.position\n ? { line: node.position.start.line }\n : headingLine != null\n ? { line: headingLine }\n : {}),\n });\n return;\n }\n if (node.type === 'code') return; // code blocks legitimately contain {[\n for (const child of getChildren(node)) {\n walk(child, headingLine, false);\n }\n };\n\n for (const child of markdownDoc.children) {\n walk(child, child.position?.start.line, true);\n }\n}\n\n// ============================================\n// Asset checks\n// ============================================\n\nfunction normalizeAssetCheck(\n assets: ReadonlySet<string> | ((path: string) => boolean),\n): (path: string) => boolean {\n if (typeof assets === 'function') return assets;\n return (path: string) => assets.has(path) || assets.has(path.replace(/^\\.\\//, ''));\n}\n\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\n\n/** A reference that should resolve inside the bundle: relative, no scheme. */\nfunction isBundleRelative(url: string): boolean {\n return (\n url.length > 0 && !URL_SCHEME_RE.test(url) && !url.startsWith('//') && !url.startsWith('#')\n );\n}\n\n/** Template param keys whose values reference media assets. */\nconst ASSET_PARAM_KEYS = ['src', 'imageSrc', 'videoSrc', 'poster', 'backgroundImage'];\n\nfunction checkAssets(\n markdownDoc: MarkdownDocument,\n blocks: Block[],\n hasAsset: (path: string) => boolean,\n diagnostics: DocDiagnostic[],\n): void {\n const report = (url: string, line?: number, blockId?: string) => {\n if (!isBundleRelative(url) || hasAsset(url)) return;\n diagnostics.push({\n severity: 'warning',\n code: 'missing-asset',\n message: `Referenced asset \"${url}\" was not found in the bundle`,\n ...(blockId ? { blockId } : {}),\n ...(line != null ? { line } : {}),\n });\n };\n\n // Markdown image nodes + raw-HTML <img src>.\n const walk = (node: MarkdownNode): void => {\n if (node.type === 'image') {\n report(node.url, node.position?.start.line);\n }\n if (node.type === 'htmlBlock' || node.type === 'htmlInline') {\n walkHtmlImages(node.htmlChildren, (src) => report(src, node.position?.start.line));\n }\n for (const child of getChildren(node)) walk(child);\n };\n for (const child of markdownDoc.children) walk(child);\n\n // Media references in template params / structured data.\n for (const block of blocks) {\n const sources: Array<Record<string, unknown> | undefined> = [\n block.templateOverrides,\n block.templateData,\n ];\n for (const source of sources) {\n if (!source) continue;\n for (const key of ASSET_PARAM_KEYS) {\n const value = source[key];\n if (typeof value === 'string') {\n report(value, block.sourceHeading?.position?.start.line, block.id);\n }\n }\n const images = source['images'];\n const list =\n typeof images === 'string'\n ? images.split(',').map((s) => s.trim())\n : Array.isArray(images)\n ? images.filter((i): i is string => typeof i === 'string')\n : [];\n for (const img of list) {\n report(img, block.sourceHeading?.position?.start.line, block.id);\n }\n }\n }\n}\n\nfunction walkHtmlImages(nodes: HtmlNode[], report: (src: string) => void): void {\n for (const node of nodes) {\n if (node.type !== 'htmlElement') continue;\n if (node.tagName === 'img' && node.attributes.src) {\n report(node.attributes.src);\n }\n walkHtmlImages(node.children, report);\n }\n}\n\n// ============================================\n// Helpers\n// ============================================\n\nfunction lineOf(block: Block): { line: number } | Record<string, never> {\n const line = block.sourceHeading?.position?.start.line;\n return line != null ? { line } : {};\n}\n\nfunction truncate(text: string, max = 40): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n","/**\n * ASCII diagram renderer: semantic nodes/edges → box-and-line art.\n *\n * Deterministic (no clock, no randomness; every iteration order is an\n * explicit sort) and designed as a fixpoint partner for `parse.ts`:\n *\n * - `parseAsciiDiagram(renderAsciiDiagram(d))` preserves node ids, labels,\n * containment, and the edge tuple set of `d`.\n * - After one normalization cycle the output is byte-stable:\n * `renderAsciiDiagram(parseAsciiDiagram(renderAsciiDiagram(d))) ===\n * renderAsciiDiagram(d)`.\n *\n * Grid positions come from the nodes; container rects are DERIVED from\n * their children each render (a container's own col/row are ignored), so\n * moving children can never orphan them outside their box.\n */\n\nimport { ASCII_VOCAB, UNICODE_VOCAB, type StyleVocab } from './chars.js';\nimport type { AsciiDiagram, AsciiDiagramEdge, AsciiDiagramNode } from './types.js';\n\nexport interface RenderAsciiDiagramOptions {\n /** Character vocabulary; defaults to the diagram's own detected style. */\n style?: 'unicode' | 'ascii';\n}\n\ninterface Rect {\n r0: number;\n c0: number;\n r1: number;\n c1: number;\n}\n\ninterface PlacedNode {\n node: AsciiDiagramNode;\n rect: Rect;\n labelLines: string[];\n isContainer: boolean;\n depth: number;\n}\n\nconst SIDE_MARGIN = 1; // blank cells kept between distinct sibling rects\n\nexport function renderAsciiDiagram(\n diagram: AsciiDiagram,\n options: RenderAsciiDiagramOptions = {},\n): string {\n const vocab = (options.style ?? diagram.style) === 'ascii' ? ASCII_VOCAB : UNICODE_VOCAB;\n if (diagram.nodes.length === 0) return '';\n\n const placed = layoutNodes(diagram.nodes, diagram.edges);\n const canvas = new Canvas();\n\n // Boxes: outermost containers first so children draw over their interior.\n const drawOrder = [...placed.values()].sort(\n (a, b) => a.depth - b.depth || a.rect.r0 - b.rect.r0 || a.rect.c0 - b.rect.c0,\n );\n for (const p of drawOrder) drawBox(canvas, p, vocab);\n\n drawEdges(canvas, diagram.edges, placed, vocab);\n\n return canvas.emit();\n}\n\n// ---------------------------------------------------------------------------\n// Layout\n// ---------------------------------------------------------------------------\n\n/**\n * Approximate per-side edge degree from the nodes' authored grid\n * positions (same side logic as `pickSides`, run before final layout).\n * Used to widen/heighten boxes so sibling attachments always land on\n * distinct, gapped cells — adjacent attachments (`┬┬`) route into each\n * other and collapse to one component on re-parse.\n */\nfunction computeSideDegrees(\n nodes: readonly AsciiDiagramNode[],\n edges: readonly AsciiDiagramEdge[],\n): Map<string, { top: number; bottom: number; left: number; right: number }> {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const deg = new Map<string, { top: number; bottom: number; left: number; right: number }>();\n for (const n of nodes) deg.set(n.id, { top: 0, bottom: 0, left: 0, right: 0 });\n const rectOf = (n: AsciiDiagramNode): Rect => ({\n r0: n.row,\n c0: n.col,\n r1: n.row + n.hRows - 1,\n c1: n.col + n.wCols - 1,\n });\n for (const e of edges) {\n const s = byId.get(e.source);\n const t = byId.get(e.target);\n if (!s || !t || s === t) continue;\n const { exit, enter } = pickSides(rectOf(s), rectOf(t));\n deg.get(e.source)![exit]++;\n deg.get(e.target)![enter]++;\n }\n return deg;\n}\n\nfunction layoutNodes(\n nodes: readonly AsciiDiagramNode[],\n edges: readonly AsciiDiagramEdge[],\n): Map<string, PlacedNode> {\n const byId = new Map<string, AsciiDiagramNode>();\n for (const node of nodes) byId.set(node.id, node);\n const sideDeg = computeSideDegrees(nodes, edges);\n\n const childIds = new Map<string, string[]>();\n const roots: string[] = [];\n for (const node of nodes) {\n if (node.containerId && byId.has(node.containerId) && node.containerId !== node.id) {\n const list = childIds.get(node.containerId) ?? [];\n list.push(node.id);\n childIds.set(node.containerId, list);\n } else {\n roots.push(node.id);\n }\n }\n\n const placed = new Map<string, PlacedNode>();\n\n const translateSubtree = (id: string, dRows: number, dCols: number): void => {\n const p = placed.get(id);\n if (p) p.rect = shiftRect(p.rect, dRows, dCols);\n for (const childId of childIds.get(id) ?? []) translateSubtree(childId, dRows, dCols);\n };\n\n // Place a set of sibling units (each may be a whole subtree) without overlap.\n const placeSiblings = (ids: string[], layoutUnit: (id: string) => Rect): Rect[] => {\n const order = [...ids].sort((a, b) => {\n const na = byId.get(a) as AsciiDiagramNode;\n const nb = byId.get(b) as AsciiDiagramNode;\n return na.row - nb.row || na.col - nb.col || na.id.localeCompare(nb.id);\n });\n const placedRects: Rect[] = [];\n for (const id of order) {\n let rect = layoutUnit(id);\n // Greedy deterministic collision resolution: shift along the axis\n // needing the smaller displacement (ties → down).\n let guard = 0;\n for (;;) {\n const hit = placedRects.find((p) => overlapsWithMargin(rect, p, SIDE_MARGIN));\n if (!hit || guard++ > 64) break;\n const dxRight = hit.c1 + SIDE_MARGIN + 1 - rect.c0;\n const dyDown = hit.r1 + SIDE_MARGIN + 1 - rect.r0;\n if (dxRight < dyDown) {\n translateSubtree(id, 0, dxRight);\n rect = shiftRect(rect, 0, dxRight);\n } else {\n translateSubtree(id, dyDown, 0);\n rect = shiftRect(rect, dyDown, 0);\n }\n }\n placedRects.push(rect);\n }\n return placedRects;\n };\n\n // Recursively size + place a subtree; returns its bounding rect.\n const layoutSubtree = (id: string, depth: number): Rect => {\n const node = byId.get(id) as AsciiDiagramNode;\n const labelLines = node.label.length > 0 ? node.label.split('\\n') : [];\n const children = childIds.get(id) ?? [];\n\n if (children.length === 0) {\n const innerW = labelLines.reduce((w, l) => Math.max(w, l.length), 0);\n // Attachment gap: a side with K edges needs ≥ 2K+1 inner cells so the\n // spread (`from + round((i+1)*inner/(K+1))`) leaves a blank column\n // between consecutive attachments and off the corners.\n const deg = sideDeg.get(id) ?? { top: 0, bottom: 0, left: 0, right: 0 };\n const horizDeg = Math.max(deg.top, deg.bottom);\n const vertDeg = Math.max(deg.left, deg.right);\n const wCols = Math.max(node.wCols, innerW + 4, 3, horizDeg > 0 ? 2 * horizDeg + 1 : 0);\n const hRows = Math.max(\n node.hRows,\n labelLines.length + 2,\n 3,\n vertDeg > 0 ? 2 * vertDeg + 1 : 0,\n );\n const rect: Rect = {\n r0: node.row,\n c0: node.col,\n r1: node.row + hRows - 1,\n c1: node.col + wCols - 1,\n };\n placed.set(id, { node, rect, labelLines, isContainer: false, depth });\n return rect;\n }\n\n // Container: children first, then derive our rect around them.\n const childRects = placeSiblings(children, (childId) => layoutSubtree(childId, depth + 1));\n const bbox = unionRects(childRects);\n const extraRows = Math.max(0, labelLines.length - 1);\n const titleLen = (labelLines[0] ?? '').length;\n const rect: Rect = {\n r0: bbox.r0 - 2 - extraRows,\n c0: bbox.c0 - 2,\n r1: bbox.r1 + 2,\n c1: bbox.c1 + 2,\n };\n // Top border must host `── Title ──` with ≥1 line char each side.\n const minW = titleLen > 0 ? titleLen + 6 : 3;\n if (rect.c1 - rect.c0 + 1 < minW) rect.c1 = rect.c0 + minW - 1;\n // Never shrink below the parsed size (visual stability for wide containers).\n if (rect.c1 - rect.c0 + 1 < node.wCols) rect.c1 = rect.c0 + node.wCols - 1;\n placed.set(id, { node, rect, labelLines, isContainer: true, depth });\n return rect;\n };\n\n placeSiblings(roots, (id) => layoutSubtree(id, 0));\n\n // Normalize into the positive quadrant (container margins can push past 0).\n let minR = Infinity;\n let minC = Infinity;\n for (const p of placed.values()) {\n minR = Math.min(minR, p.rect.r0);\n minC = Math.min(minC, p.rect.c0);\n }\n const dR = minR < 0 ? -minR : 0;\n const dC = minC < 0 ? -minC : 0;\n if (dR > 0 || dC > 0) {\n for (const p of placed.values()) p.rect = shiftRect(p.rect, dR, dC);\n }\n return placed;\n}\n\nfunction overlapsWithMargin(a: Rect, b: Rect, margin: number): boolean {\n return (\n a.r0 - margin <= b.r1 && b.r0 - margin <= a.r1 && a.c0 - margin <= b.c1 && b.c0 - margin <= a.c1\n );\n}\n\nfunction shiftRect(rect: Rect, dRows: number, dCols: number): Rect {\n return { r0: rect.r0 + dRows, c0: rect.c0 + dCols, r1: rect.r1 + dRows, c1: rect.c1 + dCols };\n}\n\nfunction unionRects(rects: Rect[]): Rect {\n return rects.reduce((acc, r) => ({\n r0: Math.min(acc.r0, r.r0),\n c0: Math.min(acc.c0, r.c0),\n r1: Math.max(acc.r1, r.r1),\n c1: Math.max(acc.c1, r.c1),\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Canvas\n// ---------------------------------------------------------------------------\n\ntype CellKind = 'empty' | 'border' | 'label' | 'line-h' | 'line-v' | 'turn' | 'arrow' | 'junction';\n\nclass Canvas {\n private rows: string[][] = [];\n private kinds: CellKind[][] = [];\n\n private ensure(r: number, c: number): void {\n while (this.rows.length <= r) {\n this.rows.push([]);\n this.kinds.push([]);\n }\n const row = this.rows[r];\n const kindRow = this.kinds[r];\n while (row.length <= c) {\n row.push(' ');\n kindRow.push('empty');\n }\n }\n\n kindAt(r: number, c: number): CellKind {\n return this.kinds[r]?.[c] ?? 'empty';\n }\n\n /** Unconditional write (boxes, labels, junction upgrades). */\n set(r: number, c: number, ch: string, kind: CellKind): void {\n if (r < 0 || c < 0) return;\n this.ensure(r, c);\n this.rows[r][c] = ch;\n this.kinds[r][c] = kind;\n }\n\n /** Edge-aware write: respects borders, upgrades crossings, lets arrows win. */\n drawEdgeCell(r: number, c: number, ch: string, kind: CellKind, vocab: StyleVocab): void {\n if (r < 0 || c < 0) return;\n this.ensure(r, c);\n const existing = this.kinds[r][c];\n if (existing === 'border' || existing === 'label' || existing === 'junction') return;\n if (kind === 'arrow') {\n this.rows[r][c] = ch;\n this.kinds[r][c] = kind;\n return;\n }\n if (existing === 'arrow') return;\n if (\n (existing === 'line-h' && kind === 'line-v') ||\n (existing === 'line-v' && kind === 'line-h')\n ) {\n this.rows[r][c] = vocab.cross;\n this.kinds[r][c] = 'turn';\n return;\n }\n if (existing === 'empty') {\n this.rows[r][c] = ch;\n this.kinds[r][c] = kind;\n }\n }\n\n emit(): string {\n const lines = this.rows.map((row) => row.join('').replace(/\\s+$/u, ''));\n while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();\n return lines.join('\\n');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Boxes\n// ---------------------------------------------------------------------------\n\nfunction drawBox(canvas: Canvas, p: PlacedNode, vocab: StyleVocab): void {\n const { rect, labelLines, isContainer } = p;\n const innerW = rect.c1 - rect.c0 - 1;\n\n // Top border (containers embed their first label line as a title).\n canvas.set(rect.r0, rect.c0, vocab.tl, 'border');\n canvas.set(rect.r0, rect.c1, vocab.tr, 'border');\n const title = isContainer && labelLines.length > 0 ? ` ${labelLines[0]} ` : null;\n if (title && title.length <= innerW - 2) {\n const left = Math.floor((innerW - title.length) / 2);\n for (let i = 0; i < innerW; i++) {\n const inTitle = i >= left && i < left + title.length;\n const ch = inTitle ? title[i - left] : vocab.h;\n canvas.set(rect.r0, rect.c0 + 1 + i, ch, inTitle ? 'label' : 'border');\n }\n } else {\n for (let c = rect.c0 + 1; c <= rect.c1 - 1; c++) canvas.set(rect.r0, c, vocab.h, 'border');\n }\n\n // Bottom border + sides.\n canvas.set(rect.r1, rect.c0, vocab.bl, 'border');\n canvas.set(rect.r1, rect.c1, vocab.br, 'border');\n for (let c = rect.c0 + 1; c <= rect.c1 - 1; c++) canvas.set(rect.r1, c, vocab.h, 'border');\n for (let r = rect.r0 + 1; r <= rect.r1 - 1; r++) {\n canvas.set(r, rect.c0, vocab.v, 'border');\n canvas.set(r, rect.c1, vocab.v, 'border');\n }\n\n // Interior label lines: leaves get all lines (vertically centered),\n // containers the lines after the embedded title, directly below the top.\n const interiorLines = isContainer ? labelLines.slice(1) : labelLines;\n if (interiorLines.length > 0) {\n const innerH = rect.r1 - rect.r0 - 1;\n const startRow = isContainer\n ? rect.r0 + 1\n : rect.r0 + 1 + Math.max(0, Math.floor((innerH - interiorLines.length) / 2));\n interiorLines.forEach((line, i) => {\n const pad = Math.max(0, Math.floor((innerW - line.length) / 2));\n for (let j = 0; j < line.length && pad + j < innerW; j++) {\n canvas.set(startRow + i, rect.c0 + 1 + pad + j, line[j], 'label');\n }\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Edges\n// ---------------------------------------------------------------------------\n\ntype Side = 'top' | 'bottom' | 'left' | 'right';\n\ninterface RoutePlan {\n edge: AsciiDiagramEdge;\n sourceId: string;\n targetId: string;\n exitSide: Side;\n enterSide: Side;\n biDir: boolean;\n}\n\nfunction drawEdges(\n canvas: Canvas,\n edges: readonly AsciiDiagramEdge[],\n placed: Map<string, PlacedNode>,\n vocab: StyleVocab,\n): void {\n // Merge reciprocal directed pairs into single double-arrow lines.\n const sorted = [...edges].sort(\n (a, b) =>\n a.source.localeCompare(b.source) ||\n a.target.localeCompare(b.target) ||\n (a.label ?? '').localeCompare(b.label ?? ''),\n );\n const skip = new Set<number>();\n const plans: RoutePlan[] = [];\n for (let i = 0; i < sorted.length; i++) {\n if (skip.has(i)) continue;\n const e = sorted[i];\n if (!placed.has(e.source) || !placed.has(e.target)) continue;\n let biDir = false;\n if (e.directed) {\n const j = sorted.findIndex(\n (o, k) =>\n k > i &&\n !skip.has(k) &&\n o.directed &&\n o.source === e.target &&\n o.target === e.source &&\n (o.label ?? '') === (e.label ?? ''),\n );\n if (j >= 0) {\n skip.add(j);\n biDir = true;\n }\n }\n const sides = pickSides(\n (placed.get(e.source) as PlacedNode).rect,\n (placed.get(e.target) as PlacedNode).rect,\n );\n plans.push({\n edge: e,\n sourceId: e.source,\n targetId: e.target,\n exitSide: sides.exit,\n enterSide: sides.enter,\n biDir,\n });\n }\n\n const attachment = assignAttachments(plans, placed);\n const sideLabelRequests: SideLabelRequest[] = [];\n plans.forEach((plan, i) =>\n routeEdge(canvas, plan, i, placed, attachment, vocab, (candidates, label) =>\n sideLabelRequests.push({ candidates, label }),\n ),\n );\n\n // Side labels last, so they can never break another edge's line: each\n // label lands beside the first candidate whose anchor is still a plain\n // vertical and whose neighboring cells are all free — right side\n // (`│ label`) preferred, left side (`label │`) as fallback.\n for (const req of sideLabelRequests) {\n let done = false;\n for (const side of ['right', 'left'] as const) {\n if (done) break;\n for (const { row, col } of req.candidates) {\n if (canvas.kindAt(row, col) !== 'line-v') continue;\n const startCol = side === 'right' ? col + 2 : col - 1 - req.label.length;\n if (startCol < 0) continue;\n const gapCol = side === 'right' ? col + 1 : col - 1;\n let free = canvas.kindAt(row, gapCol) === 'empty';\n for (let i = 0; free && i < req.label.length; i++) {\n if (canvas.kindAt(row, startCol + i) !== 'empty') free = false;\n }\n // Left-side runs must not merge into earlier art on their left.\n if (free && side === 'left' && startCol > 0) {\n free = canvas.kindAt(row, startCol - 1) === 'empty';\n }\n if (!free) continue;\n for (let i = 0; i < req.label.length; i++) {\n canvas.set(row, startCol + i, req.label[i], 'label');\n }\n done = true;\n break;\n }\n }\n }\n}\n\ninterface SideLabelRequest {\n /** Candidate anchor cells in preference order (middle-out per leg). */\n candidates: Array<{ row: number; col: number }>;\n label: string;\n}\n\nfunction pickSides(s: Rect, t: Rect): { exit: Side; enter: Side } {\n if (t.r0 > s.r1) return { exit: 'bottom', enter: 'top' };\n if (t.r1 < s.r0) return { exit: 'top', enter: 'bottom' };\n if (t.c0 > s.c1) return { exit: 'right', enter: 'left' };\n if (t.c1 < s.c0) return { exit: 'left', enter: 'right' };\n // Overlapping / containment: connect the closest pair of parallel borders.\n const gaps: Array<{ side: Side; gap: number }> = [\n { side: 'top', gap: Math.abs(s.r0 - t.r0) },\n { side: 'bottom', gap: Math.abs(t.r1 - s.r1) },\n { side: 'left', gap: Math.abs(s.c0 - t.c0) },\n { side: 'right', gap: Math.abs(t.c1 - s.c1) },\n ];\n gaps.sort((a, b) => a.gap - b.gap);\n return { exit: gaps[0].side, enter: gaps[0].side };\n}\n\ninterface AttachmentSlot {\n pos: number;\n /** 0-based order within the (node, side) group + group size — used to\n * stagger Z-route jog rows so parallel routes never touch (touching\n * turns would merge into one component on re-parse). */\n index: number;\n count: number;\n}\n\n/** Deterministic per-(node, side) attachment positions, spread across the side. */\nfunction assignAttachments(\n plans: RoutePlan[],\n placed: Map<string, PlacedNode>,\n): Map<string, AttachmentSlot> {\n interface Request {\n key: string; // `${planIndex}:exit` | `${planIndex}:enter`\n otherId: string;\n }\n const bySide = new Map<string, Request[]>();\n plans.forEach((plan, i) => {\n const exitKey = `${plan.sourceId}|${plan.exitSide}`;\n const enterKey = `${plan.targetId}|${plan.enterSide}`;\n bySide.set(exitKey, [\n ...(bySide.get(exitKey) ?? []),\n { key: `${i}:exit`, otherId: plan.targetId },\n ]);\n bySide.set(enterKey, [\n ...(bySide.get(enterKey) ?? []),\n { key: `${i}:enter`, otherId: plan.sourceId },\n ]);\n });\n const result = new Map<string, AttachmentSlot>();\n for (const [sideKey, list] of [...bySide.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n const [nodeId, side] = sideKey.split('|') as [string, Side];\n const node = placed.get(nodeId) as PlacedNode;\n list.sort((a, b) => {\n const ra = (placed.get(a.otherId) as PlacedNode).rect;\n const rb = (placed.get(b.otherId) as PlacedNode).rect;\n return ra.r0 - rb.r0 || ra.c0 - rb.c0 || a.otherId.localeCompare(b.otherId);\n });\n const horizontal = side === 'top' || side === 'bottom';\n const from = horizontal ? node.rect.c0 + 1 : node.rect.r0 + 1;\n const to = horizontal ? node.rect.c1 - 1 : node.rect.r1 - 1;\n const inner = Math.max(1, to - from + 1);\n const k = list.length;\n if (k === 1) {\n // Single attachment lands on the side's center cell.\n result.set(list[0].key, { pos: from + Math.floor((inner - 1) / 2), index: 0, count: 1 });\n } else {\n // Stride-2 centered placement guarantees a blank cell between\n // consecutive attachments (min box sizing reserves the room), so\n // sibling routes never share adjacent columns and collapse on\n // re-parse. Span = 2k-1; clamp into the side if a tiny box can't fit.\n const span = 2 * k - 1;\n const start = from + Math.max(0, Math.floor((inner - span) / 2));\n list.forEach((req, i) => {\n result.set(req.key, { pos: Math.min(to, start + 2 * i), index: i, count: k });\n });\n }\n }\n return result;\n}\n\nfunction routeEdge(\n canvas: Canvas,\n plan: RoutePlan,\n planIdx: number,\n placed: Map<string, PlacedNode>,\n attachment: Map<string, AttachmentSlot>,\n vocab: StyleVocab,\n deferSideLabel: (candidates: Array<{ row: number; col: number }>, label: string) => void,\n): void {\n const s = (placed.get(plan.sourceId) as PlacedNode).rect;\n const t = (placed.get(plan.targetId) as PlacedNode).rect;\n const exitSlot = attachment.get(`${planIdx}:exit`) as AttachmentSlot;\n const enterSlot = attachment.get(`${planIdx}:enter`) as AttachmentSlot;\n const exitPos = exitSlot.pos;\n const enterPos = enterSlot.pos;\n // Deterministic jog stagger: routes sharing a side (either end — fan-outs\n // AND fan-ins) each get a distinct mid-line so their turns/segments can\n // never touch or overlap on the same row/column.\n const basis = enterSlot.count > exitSlot.count ? enterSlot : exitSlot;\n const stagger = basis.index - Math.floor((basis.count - 1) / 2);\n\n const junction = (r: number, c: number, side: Side): void => {\n const ch =\n side === 'top'\n ? vocab.stemUp\n : side === 'bottom'\n ? vocab.stemDown\n : side === 'left'\n ? vocab.stemLeft\n : vocab.stemRight;\n canvas.set(r, c, ch, 'junction');\n };\n\n const args: EdgeDrawArgs = {\n canvas,\n directed: plan.edge.directed,\n biDir: plan.biDir,\n label: plan.edge.label,\n vocab,\n junction,\n stagger,\n deferSideLabel,\n };\n\n if (plan.exitSide === 'bottom' && plan.enterSide === 'top') {\n drawVertical(args, s, t, exitPos, enterPos, 1);\n } else if (plan.exitSide === 'top' && plan.enterSide === 'bottom') {\n drawVertical(args, s, t, exitPos, enterPos, -1);\n } else if (plan.exitSide === 'right' && plan.enterSide === 'left') {\n drawHorizontal(args, s, t, exitPos, enterPos, 1);\n } else if (plan.exitSide === 'left' && plan.enterSide === 'right') {\n drawHorizontal(args, s, t, exitPos, enterPos, -1);\n } else {\n drawNested(args, s, t, plan.exitSide);\n }\n}\n\ninterface EdgeDrawArgs {\n canvas: Canvas;\n directed: boolean;\n biDir: boolean;\n label: string | undefined;\n vocab: StyleVocab;\n junction: (r: number, c: number, side: Side) => void;\n /** Jog offset for Z-routes so sibling routes never share a mid-line. */\n stagger: number;\n /** Queue a `│ label` placement for the deferred final pass. */\n deferSideLabel: (candidates: Array<{ row: number; col: number }>, label: string) => void;\n}\n\n/** Order candidate rows middle-out so labels prefer a run's midpoint. */\nfunction middleOut(from: number, to: number): number[] {\n const lo = Math.min(from, to);\n const hi = Math.max(from, to);\n const rows: number[] = [];\n for (let r = lo; r <= hi; r++) rows.push(r);\n const mid = Math.floor((lo + hi) / 2);\n return rows.sort((a, b) => Math.abs(a - mid) - Math.abs(b - mid) || a - b);\n}\n\nfunction clamp(value: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, value));\n}\n\nfunction drawVertical(\n args: EdgeDrawArgs,\n s: Rect,\n t: Rect,\n exitCol: number,\n enterCol: number,\n dir: 1 | -1,\n): void {\n const { canvas, directed, biDir, label, vocab, junction, stagger } = args;\n // dir 1: exit bottom of s, enter top of t (t below); dir -1 mirrored.\n const exitRow = dir === 1 ? s.r1 : s.r0;\n const enterRow = dir === 1 ? t.r0 : t.r1;\n const firstFree = exitRow + dir;\n const lastFree = enterRow - dir;\n const gap = (lastFree - firstFree) * dir + 1;\n\n const drawV = (col: number, rA: number, rB: number): void => {\n const lo = Math.min(rA, rB);\n const hi = Math.max(rA, rB);\n for (let r = lo; r <= hi; r++) canvas.drawEdgeCell(r, col, vocab.v, 'line-v', vocab);\n };\n\n const straightOk =\n exitCol >= t.c0 + 1 && exitCol <= t.c1 - 1 && exitCol >= s.c0 + 1 && exitCol <= s.c1 - 1;\n\n if (straightOk || gap < 2) {\n // Straight (or no room to jog): one column, clamped onto both borders.\n const sCol = clamp(exitCol, s.c0 + 1, s.c1 - 1);\n const tCol = clamp(exitCol, t.c0 + 1, t.c1 - 1);\n junction(exitRow, sCol, dir === 1 ? 'bottom' : 'top');\n junction(enterRow, tCol, dir === 1 ? 'top' : 'bottom');\n if (sCol === tCol && gap >= 1) {\n drawV(sCol, firstFree, lastFree);\n if (directed) {\n canvas.drawEdgeCell(\n lastFree,\n sCol,\n dir === 1 ? vocab.arrowDown : vocab.arrowUp,\n 'arrow',\n vocab,\n );\n }\n if (biDir && gap >= 2) {\n canvas.drawEdgeCell(\n firstFree,\n sCol,\n dir === 1 ? vocab.arrowUp : vocab.arrowDown,\n 'arrow',\n vocab,\n );\n }\n // `│ label` beside the run (deferred pass finds a free plain row).\n if (label) {\n args.deferSideLabel(\n middleOut(firstFree, lastFree).map((row) => ({ row, col: sCol })),\n label,\n );\n }\n }\n return;\n }\n\n // Z-route with a horizontal jog (also hosts the label when present).\n // Sibling routes stagger their jog rows so turns never touch (touching\n // turns would merge into one polyline on re-parse).\n const midRow = clamp(\n Math.floor((exitRow + enterRow) / 2) + stagger,\n Math.min(firstFree, lastFree),\n Math.max(firstFree, lastFree),\n );\n junction(exitRow, exitCol, dir === 1 ? 'bottom' : 'top');\n junction(enterRow, enterCol, dir === 1 ? 'top' : 'bottom');\n if (Math.abs(midRow - exitRow) >= 2) drawV(exitCol, firstFree, midRow - dir);\n if (Math.abs(enterRow - midRow) >= 2) drawV(enterCol, midRow + dir, lastFree);\n let labelEmbedded = false;\n if (exitCol === enterCol) {\n canvas.drawEdgeCell(midRow, exitCol, vocab.v, 'line-v', vocab);\n } else {\n const goingRight = enterCol > exitCol;\n // Turn glyph names describe the corner's two open sides.\n const exitTurn =\n dir === 1\n ? goingRight\n ? vocab.turnUpRight\n : vocab.turnUpLeft\n : goingRight\n ? vocab.turnDownRight\n : vocab.turnDownLeft;\n const enterTurn =\n dir === 1\n ? goingRight\n ? vocab.turnDownLeft\n : vocab.turnDownRight\n : goingRight\n ? vocab.turnUpLeft\n : vocab.turnUpRight;\n canvas.drawEdgeCell(midRow, exitCol, exitTurn, 'turn', vocab);\n canvas.drawEdgeCell(midRow, enterCol, enterTurn, 'turn', vocab);\n const lo = Math.min(exitCol, enterCol);\n const hi = Math.max(exitCol, enterCol);\n let segment: string[] = [];\n for (let c = lo + 1; c <= hi - 1; c++) segment.push(vocab.h);\n // `+ 4` (not `+ 2`): at least one line char must survive on each side\n // of ` label `, or the re-parse bridge can't glue the run back together.\n if (label && segment.length >= label.length + 4) {\n const text = ` ${label} `;\n const left = Math.floor((segment.length - text.length) / 2);\n segment = segment.map((ch, i) => (i >= left && i < left + text.length ? text[i - left] : ch));\n labelEmbedded = true;\n }\n segment.forEach((ch, i) => {\n canvas.drawEdgeCell(midRow, lo + 1 + i, ch, ch === vocab.h ? 'line-h' : 'label', vocab);\n });\n }\n if (directed) {\n canvas.drawEdgeCell(\n lastFree,\n enterCol,\n dir === 1 ? vocab.arrowDown : vocab.arrowUp,\n 'arrow',\n vocab,\n );\n }\n if (biDir) {\n canvas.drawEdgeCell(\n firstFree,\n exitCol,\n dir === 1 ? vocab.arrowUp : vocab.arrowDown,\n 'arrow',\n vocab,\n );\n }\n // Label that couldn't embed in the jog: queue a `│ label` placement\n // beside a vertical leg (exit leg preferred — its cells are all plain;\n // the deferred pass skips arrowhead/cross rows automatically).\n if (label && !labelEmbedded) {\n const candidates: Array<{ row: number; col: number }> = [];\n if (exitCol === enterCol) {\n for (const row of middleOut(firstFree, lastFree)) candidates.push({ row, col: exitCol });\n } else {\n const exitLegLen = (midRow - dir - firstFree) * dir + 1;\n const enterLegLen = (lastFree - (midRow + dir)) * dir + 1;\n if (exitLegLen >= 1) {\n for (const row of middleOut(firstFree, midRow - dir)) {\n candidates.push({ row, col: exitCol });\n }\n }\n if (enterLegLen >= 1) {\n for (const row of middleOut(midRow + dir, lastFree)) {\n candidates.push({ row, col: enterCol });\n }\n }\n }\n if (candidates.length > 0) args.deferSideLabel(candidates, label);\n }\n}\n\nfunction drawHorizontal(\n args: EdgeDrawArgs,\n s: Rect,\n t: Rect,\n exitRow: number,\n enterRow: number,\n dir: 1 | -1,\n): void {\n const { canvas, directed, biDir, label, vocab, junction } = args;\n // dir 1: exit right of s, enter left of t (t to the right); dir -1 mirrored.\n const exitCol = dir === 1 ? s.c1 : s.c0;\n const enterCol = dir === 1 ? t.c0 : t.c1;\n const firstFree = exitCol + dir;\n const lastFree = enterCol - dir;\n const gap = (lastFree - firstFree) * dir + 1;\n\n const drawH = (row: number, cA: number, cB: number, hostLabel: boolean): void => {\n const lo = Math.min(cA, cB);\n const hi = Math.max(cA, cB);\n let segment: string[] = [];\n for (let c = lo; c <= hi; c++) segment.push(vocab.h);\n if (hostLabel && label && segment.length >= label.length + 4) {\n const text = ` ${label} `;\n const left = Math.floor((segment.length - text.length) / 2);\n segment = segment.map((ch, i) => (i >= left && i < left + text.length ? text[i - left] : ch));\n }\n segment.forEach((ch, i) => {\n canvas.drawEdgeCell(row, lo + i, ch, ch === vocab.h ? 'line-h' : 'label', vocab);\n });\n };\n\n const straightOk =\n exitRow >= t.r0 + 1 && exitRow <= t.r1 - 1 && exitRow >= s.r0 + 1 && exitRow <= s.r1 - 1;\n\n if (straightOk || gap < 2) {\n const sRow = clamp(exitRow, s.r0 + 1, s.r1 - 1);\n const tRow = clamp(exitRow, t.r0 + 1, t.r1 - 1);\n junction(sRow, exitCol, dir === 1 ? 'right' : 'left');\n junction(tRow, enterCol, dir === 1 ? 'left' : 'right');\n if (sRow === tRow && gap >= 1) {\n drawH(sRow, firstFree, lastFree, true);\n if (directed) {\n canvas.drawEdgeCell(\n sRow,\n lastFree,\n dir === 1 ? vocab.arrowRight : vocab.arrowLeft,\n 'arrow',\n vocab,\n );\n }\n if (biDir && gap >= 2) {\n canvas.drawEdgeCell(\n sRow,\n firstFree,\n dir === 1 ? vocab.arrowLeft : vocab.arrowRight,\n 'arrow',\n vocab,\n );\n }\n }\n return;\n }\n\n // Horizontal Z-route (staggered like the vertical case).\n const midCol = clamp(\n Math.floor((exitCol + enterCol) / 2) + args.stagger,\n Math.min(firstFree, lastFree),\n Math.max(firstFree, lastFree),\n );\n junction(exitRow, exitCol, dir === 1 ? 'right' : 'left');\n junction(enterRow, enterCol, dir === 1 ? 'left' : 'right');\n if (Math.abs(midCol - exitCol) >= 2) drawH(exitRow, firstFree, midCol - dir, true);\n if (Math.abs(enterCol - midCol) >= 2) drawH(enterRow, midCol + dir, lastFree, false);\n if (exitRow === enterRow) {\n canvas.drawEdgeCell(exitRow, midCol, vocab.h, 'line-h', vocab);\n } else {\n const goingDown = enterRow > exitRow;\n const exitTurn =\n dir === 1\n ? goingDown\n ? vocab.turnDownLeft\n : vocab.turnUpLeft\n : goingDown\n ? vocab.turnDownRight\n : vocab.turnUpRight;\n const enterTurn =\n dir === 1\n ? goingDown\n ? vocab.turnUpRight\n : vocab.turnDownRight\n : goingDown\n ? vocab.turnUpLeft\n : vocab.turnDownLeft;\n canvas.drawEdgeCell(exitRow, midCol, exitTurn, 'turn', vocab);\n canvas.drawEdgeCell(enterRow, midCol, enterTurn, 'turn', vocab);\n const lo = Math.min(exitRow, enterRow);\n const hi = Math.max(exitRow, enterRow);\n for (let r = lo + 1; r <= hi - 1; r++) {\n canvas.drawEdgeCell(r, midCol, vocab.v, 'line-v', vocab);\n }\n }\n if (directed) {\n canvas.drawEdgeCell(\n enterRow,\n lastFree,\n dir === 1 ? vocab.arrowRight : vocab.arrowLeft,\n 'arrow',\n vocab,\n );\n }\n if (biDir) {\n canvas.drawEdgeCell(\n exitRow,\n firstFree,\n dir === 1 ? vocab.arrowLeft : vocab.arrowRight,\n 'arrow',\n vocab,\n );\n }\n}\n\n/** Containment / overlap: a short straight run between the closest parallel borders. */\nfunction drawNested(args: EdgeDrawArgs, s: Rect, t: Rect, side: Side): void {\n const { canvas, directed, vocab, junction } = args;\n if (side === 'top' || side === 'bottom') {\n const overlapLo = Math.max(s.c0 + 1, t.c0 + 1);\n const overlapHi = Math.min(s.c1 - 1, t.c1 - 1);\n if (overlapLo > overlapHi) return;\n const col = Math.floor((overlapLo + overlapHi) / 2);\n const sRow = side === 'top' ? s.r0 : s.r1;\n const tRow = side === 'top' ? t.r0 : t.r1;\n if (sRow === tRow) return;\n junction(sRow, col, side);\n junction(tRow, col, side);\n const lo = Math.min(sRow, tRow);\n const hi = Math.max(sRow, tRow);\n for (let r = lo + 1; r <= hi - 1; r++) canvas.drawEdgeCell(r, col, vocab.v, 'line-v', vocab);\n if (directed && hi - lo >= 2) {\n const arrowRow = tRow > sRow ? tRow - 1 : tRow + 1;\n canvas.drawEdgeCell(\n arrowRow,\n col,\n tRow > sRow ? vocab.arrowDown : vocab.arrowUp,\n 'arrow',\n vocab,\n );\n }\n } else {\n const overlapLo = Math.max(s.r0 + 1, t.r0 + 1);\n const overlapHi = Math.min(s.r1 - 1, t.r1 - 1);\n if (overlapLo > overlapHi) return;\n const row = Math.floor((overlapLo + overlapHi) / 2);\n const sCol = side === 'left' ? s.c0 : s.c1;\n const tCol = side === 'left' ? t.c0 : t.c1;\n if (sCol === tCol) return;\n junction(row, sCol, side);\n junction(row, tCol, side);\n const lo = Math.min(sCol, tCol);\n const hi = Math.max(sCol, tCol);\n for (let c = lo + 1; c <= hi - 1; c++) canvas.drawEdgeCell(row, c, vocab.h, 'line-h', vocab);\n if (directed && hi - lo >= 2) {\n const arrowCol = tCol > sCol ? tCol - 1 : tCol + 1;\n canvas.drawEdgeCell(\n row,\n arrowCol,\n tCol > sCol ? vocab.arrowRight : vocab.arrowLeft,\n 'arrow',\n vocab,\n );\n }\n }\n}\n","/**\n * ASCII diagram REPAIR — an opt-in, best-effort pass that reconstructs a\n * clean, well-formed diagram from broken box-and-line art.\n *\n * The motivating case: hand-drawn architecture art whose labels overflow\n * their boxes and shove every following column out of alignment row-to-row\n * (e.g. a rename widened the labels). Conservative detection correctly\n * declines such art (`garbled-labels`) so it renders as a faithful code\n * block — but a user can then ask to \"repair\" it. This is that repair.\n *\n * It is deliberately AGGRESSIVE and lossy — never on the auto-detection path\n * (a mistake there would hide real code). It is only invoked when the user\n * explicitly opts in, and the result is a fully editable diagram, so an\n * imperfect edge or two is fine (the canvas lets the user fix them).\n *\n * Pipeline:\n * 1. Aggressive box tracing (walls may cross edge routing).\n * 2. Row-band label recovery — the key trick: even when a box's columns are\n * desynced from its borders, each label ROW is internally consistent, so\n * its `│…│` segments map to the band's boxes by reading order.\n * 3. Best-effort edge recovery (facing-border adjacency + arrowhead\n * direction).\n * 4. Re-render clean via `renderAsciiDiagram` — the output re-parses cleanly.\n */\n\nimport { isHoriz, isVert, isJunction, arrowDirection } from './chars.js';\nimport { toGrid, traceBoxes, type TracedRect } from './parse.js';\nimport { renderAsciiDiagram } from './render.js';\nimport { detectAsciiDiagram } from './detect.js';\nimport type { AsciiDiagram, AsciiDiagramEdge, AsciiDiagramNode } from './types.js';\n\nexport interface RepairResult {\n /** The reconstructed diagram model (grid-native coordinates). */\n diagram: AsciiDiagram;\n /** Clean, re-rendered box-and-line art — re-parses to `diagram`. */\n art: string;\n}\n\n/** Minimum boxes for a repair to be worthwhile. */\nconst MIN_REPAIR_BOXES = 2;\n/** Max vertical gap (rows) between two boxes to infer a connecting edge. */\nconst MAX_EDGE_ROW_GAP = 8;\n/** Max horizontal gap (cols) between two boxes to infer a connecting edge. */\nconst MAX_EDGE_COL_GAP = 12;\n/** Blank rows inserted between stacked bands so edges route without overlap. */\nconst BAND_ROW_GAP = 4;\n/** Blank cols inserted between boxes in a band so edges route without overlap. */\nconst BAND_COL_GAP = 4;\n\n/**\n * True when a fence is a box diagram too broken for clean detection but worth\n * offering to repair: it has box corners and aggressively traces ≥2 boxes,\n * yet conservative detection declines it. Clean diagrams (already detected)\n * and non-box art both return false, so the three states partition cleanly.\n */\nexport function isRepairableDiagram(text: string): boolean {\n // Already a clean diagram → not a repair candidate (the canvas handles it).\n if (detectAsciiDiagram(text).isDiagram) return false;\n const grid = toGrid(text);\n const rects = traceBoxes(grid, true);\n return dedupeRects(rects).length >= MIN_REPAIR_BOXES;\n}\n\n/**\n * Reconstruct a clean diagram from broken art. Returns `null` when fewer than\n * two boxes can be recovered (nothing worth repairing).\n */\nexport function repairAsciiDiagram(text: string): RepairResult | null {\n const grid = toGrid(text);\n const rects = dedupeRects(traceBoxes(grid, true));\n if (rects.length < MIN_REPAIR_BOXES) return null;\n\n const nodes = buildNodes(grid, rects);\n const edges = recoverEdges(grid, rects, nodes);\n const style = detectGridStyle(grid);\n const diagram: AsciiDiagram = { nodes, edges, style, warnings: ['repaired'] };\n return { diagram, art: renderAsciiDiagram(diagram) };\n}\n\n// ---------------------------------------------------------------------------\n// Box de-duplication (aggressive tracing can emit the same rect twice, and\n// nested duplicates where a container and a decomposed cell coincide).\n// ---------------------------------------------------------------------------\n\nfunction dedupeRects(rects: TracedRect[]): TracedRect[] {\n const seen = new Set<string>();\n const out: TracedRect[] = [];\n for (const r of rects) {\n const key = `${r.r0},${r.c0},${r.r1},${r.c1}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(r);\n }\n // Reading order (row, then col).\n return out.sort((a, b) => a.r0 - b.r0 || a.c0 - b.c0);\n}\n\n// ---------------------------------------------------------------------------\n// Label recovery (row-band segment matching)\n// ---------------------------------------------------------------------------\n\nfunction buildNodes(grid: string[][], rects: TracedRect[]): AsciiDiagramNode[] {\n const W = grid[0]?.length ?? 0;\n const labels = rects.map(() => [] as string[]);\n const index = new Map(rects.map((r, i) => [r, i] as const));\n\n // Group boxes into horizontal bands (row ranges overlap).\n const bands: TracedRect[][] = [];\n for (const r of rects) {\n let band = bands.find((bd) => bd.some((x) => x.r0 <= r.r1 && r.r0 <= x.r1));\n if (!band) {\n band = [];\n bands.push(band);\n }\n band.push(r);\n }\n\n for (const band of bands) {\n band.sort((a, b) => a.c0 - b.c0);\n const minR = Math.min(...band.map((b) => b.r0 + 1));\n const maxR = Math.max(...band.map((b) => b.r1 - 1));\n for (let r = minR; r <= maxR; r++) {\n const inRow = band.filter((b) => r > b.r0 && r < b.r1);\n if (inRow.length === 0) continue;\n const rowText = grid[r].join('');\n // Split the row into `│`-delimited segments; a clean band row yields one\n // non-empty segment per box, matched by reading order.\n const segs = rowText\n .split(/[│┃║]/)\n .map(cleanLabelText)\n .filter((s) => s.length > 0);\n if (segs.length === inRow.length) {\n inRow.forEach((b, i) => {\n const idx = index.get(b);\n if (idx !== undefined && segs[i]) labels[idx].push(segs[i]);\n });\n } else {\n // Fallback: slice each box's own columns (works when its border cols\n // still line up — isolated boxes, or when the band-split is ambiguous).\n for (const b of inRow) {\n const idx = index.get(b);\n if (idx === undefined) continue;\n const t = cleanLabelText(grid[r].slice(b.c0 + 1, Math.min(b.c1, W)).join(''));\n if (t) labels[idx].push(t);\n }\n }\n }\n }\n\n // Normalize rows onto well-spaced band offsets. Preserving the original\n // (tight, broken) row positions makes the renderer route edges THROUGH\n // boxes; stacking bands with a routing gap gives every band-to-band edge\n // clean vertical space so the rendered art re-parses losslessly. Columns\n // keep their original relative order (the horizontal layout was fine).\n const bandRow = new Map<TracedRect[], number>();\n const orderedBands = [...bands].sort(\n (a, b) => Math.min(...a.map((x) => x.r0)) - Math.min(...b.map((x) => x.r0)),\n );\n let rowCursor = 0;\n for (const band of orderedBands) {\n bandRow.set(band, rowCursor);\n const bandHeight = Math.max(...band.map((b) => b.r1 - b.r0 + 1));\n rowCursor += bandHeight + BAND_ROW_GAP;\n }\n const rectBand = new Map<TracedRect, TracedRect[]>();\n for (const band of bands) for (const r of band) rectBand.set(r, band);\n\n // Normalize columns within each band by the boxes' FITTED widths. Recovered\n // labels are usually wider than the broken art's boxes, so the original\n // column spacing would make fitted boxes overlap — the renderer would then\n // shove a box into the wrong band and route edges through it. Laying each\n // band out left-to-right by fitted width + a routing gap keeps bands intact.\n const fittedW = rects.map((rect, i) =>\n Math.max(rect.c1 - rect.c0 + 1, ...labels[i].map((l) => l.length + 4), 3),\n );\n const rectIndex = new Map(rects.map((r, i) => [r, i] as const));\n const bandCol = new Map<TracedRect, number>();\n for (const band of bands) {\n const ordered = [...band].sort((a, b) => a.c0 - b.c0);\n let colCursor = Math.min(...band.map((b) => b.c0));\n for (const r of ordered) {\n bandCol.set(r, colCursor);\n colCursor += (fittedW[rectIndex.get(r) ?? 0] ?? 3) + BAND_COL_GAP;\n }\n }\n\n // Assign ids (slug of the first label line, deduped), then resolve\n // containment (a box strictly inside another becomes its child).\n const parentIdx = rects.map((_, i) => smallestContainer(rects, i));\n const usedIds = new Map<string, number>();\n const nodes: AsciiDiagramNode[] = rects.map((rect, i) => {\n let id = slugify(labels[i][0] ?? '');\n const n = usedIds.get(id) ?? 0;\n usedIds.set(id, n + 1);\n if (n > 0) id = `${id}-${n + 1}`;\n const band = rectBand.get(rect);\n const nested = parentIdx[i] >= 0;\n const row = band && !nested ? (bandRow.get(band) ?? rect.r0) : rect.r0;\n const col = !nested ? (bandCol.get(rect) ?? rect.c0) : rect.c0;\n return {\n id,\n label: labels[i].join('\\n'),\n col,\n row,\n wCols: rect.c1 - rect.c0 + 1,\n hRows: rect.r1 - rect.r0 + 1,\n };\n });\n nodes.forEach((node, i) => {\n if (parentIdx[i] >= 0) node.containerId = nodes[parentIdx[i]].id;\n });\n return nodes;\n}\n\n/**\n * Strip UNICODE box-drawing chars and arrowheads (edge routing that bled into\n * a label). ASCII `-`/`|`/`+` are kept — they're common in real label text\n * (`molen-tooling`, `read-only`, `stdin | stdout`), and a unicode diagram\n * (the common case) never uses them as borders anyway.\n */\nfunction cleanLabelText(seg: string): string {\n let out = '';\n for (const ch of seg) {\n const code = ch.codePointAt(0) ?? 0;\n const box = code >= 0x2500 && code <= 0x257f; // Box Drawing block\n if (box || arrowDirection(ch) !== null) out += ' ';\n else out += ch;\n }\n return out.replace(/\\s+/g, ' ').trim();\n}\n\nfunction smallestContainer(rects: TracedRect[], i: number): number {\n const child = rects[i];\n let best = -1;\n let bestArea = Infinity;\n for (let j = 0; j < rects.length; j++) {\n if (j === i) continue;\n const p = rects[j];\n if (p.r0 < child.r0 && p.c0 < child.c0 && p.r1 > child.r1 && p.c1 > child.c1) {\n const a = (p.r1 - p.r0) * (p.c1 - p.c0);\n if (a < bestArea) {\n bestArea = a;\n best = j;\n }\n }\n }\n return best;\n}\n\nfunction slugify(s: string): string {\n const slug = s\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || 'node';\n}\n\n// ---------------------------------------------------------------------------\n// Edge recovery (facing-border adjacency + arrowhead direction)\n// ---------------------------------------------------------------------------\n\nfunction recoverEdges(\n grid: string[][],\n rects: TracedRect[],\n nodes: AsciiDiagramNode[],\n): AsciiDiagramEdge[] {\n const H = grid.length;\n const W = grid[0]?.length ?? 0;\n const at = (r: number, c: number): string =>\n r >= 0 && r < H && c >= 0 && c < W ? grid[r][c] : ' ';\n const isConnector = (ch: string): boolean =>\n isVert(ch) || isHoriz(ch) || isJunction(ch) || arrowDirection(ch) !== null;\n\n const colOverlap = (a: TracedRect, b: TracedRect): boolean =>\n Math.max(a.c0, b.c0) <= Math.min(a.c1, b.c1);\n const rowOverlap = (a: TracedRect, b: TracedRect): boolean =>\n Math.max(a.r0, b.r0) <= Math.min(a.r1, b.r1);\n\n const edges: AsciiDiagramEdge[] = [];\n const seen = new Set<string>();\n const push = (s: number, t: number, directed: boolean) => {\n if (s === t) return;\n const key = `${nodes[s].id}|${nodes[t].id}`;\n if (seen.has(key)) return;\n seen.add(key);\n edges.push({ source: nodes[s].id, target: nodes[t].id, directed });\n };\n\n for (let i = 0; i < rects.length; i++) {\n for (let j = 0; j < rects.length; j++) {\n if (i === j) continue;\n const A = rects[i];\n const B = rects[j];\n\n // Vertical: A above B, columns overlap, a connector spans the gap, and\n // no third box sits directly between them in that column band.\n if (A.r1 < B.r0 && B.r0 - A.r1 <= MAX_EDGE_ROW_GAP && colOverlap(A, B)) {\n const lo = Math.max(A.c0, B.c0);\n const hi = Math.min(A.c1, B.c1);\n if (\n gapHasConnector(at, A.r1 + 1, B.r0 - 1, lo - 1, hi + 1, isConnector) &&\n !boxBetweenVert(rects, i, j, lo, hi)\n ) {\n const directed = gapHasArrow(at, A.r1 + 1, B.r0, lo - 1, hi + 1, 'down');\n push(i, j, directed);\n }\n }\n\n // Horizontal: A left of B, rows overlap. Require an actual arrowhead in\n // the gap — a label that overflowed its box leaks `│`/text into the gap\n // between horizontally-adjacent boxes, which a plain-connector test\n // would read as a phantom edge. A real horizontal edge carries `►`/`◄`.\n if (A.c1 < B.c0 && B.c0 - A.c1 <= MAX_EDGE_COL_GAP && rowOverlap(A, B) && i < j) {\n const lo = Math.max(A.r0, B.r0);\n const hi = Math.min(A.r1, B.r1);\n const rightArrow = gapHasArrow(at, lo - 1, hi + 1, A.c1 + 1, B.c0, 'right');\n const leftArrow = gapHasArrow(at, lo - 1, hi + 1, A.c1 + 1, B.c0, 'left');\n if ((rightArrow || leftArrow) && !boxBetweenHoriz(rects, i, j, lo, hi)) {\n if (leftArrow && !rightArrow) push(j, i, true);\n else push(i, j, true);\n }\n }\n }\n }\n return edges;\n}\n\nfunction gapHasConnector(\n at: (r: number, c: number) => string,\n r0: number,\n r1: number,\n c0: number,\n c1: number,\n isConnector: (ch: string) => boolean,\n): boolean {\n for (let r = r0; r <= r1; r++)\n for (let c = c0; c <= c1; c++) if (isConnector(at(r, c))) return true;\n return false;\n}\n\nfunction gapHasArrow(\n at: (r: number, c: number) => string,\n r0: number,\n r1: number,\n c0: number,\n c1: number,\n dir: 'down' | 'up' | 'left' | 'right',\n): boolean {\n for (let r = r0; r <= r1; r++) {\n for (let c = c0; c <= c1; c++) {\n if (arrowDirection(at(r, c)) === dir) return true;\n }\n }\n return false;\n}\n\nfunction boxBetweenVert(\n rects: TracedRect[],\n i: number,\n j: number,\n lo: number,\n hi: number,\n): boolean {\n const A = rects[i];\n const B = rects[j];\n return rects.some((k, ki) => {\n if (ki === i || ki === j) return false;\n return k.r0 > A.r1 && k.r1 < B.r0 && Math.max(k.c0, lo) <= Math.min(k.c1, hi);\n });\n}\n\nfunction boxBetweenHoriz(\n rects: TracedRect[],\n i: number,\n j: number,\n lo: number,\n hi: number,\n): boolean {\n const A = rects[i];\n const B = rects[j];\n return rects.some((k, ki) => {\n if (ki === i || ki === j) return false;\n return k.c0 > A.c1 && k.c1 < B.c0 && Math.max(k.r0, lo) <= Math.min(k.r1, hi);\n });\n}\n\n// ---------------------------------------------------------------------------\n\nfunction detectGridStyle(grid: string[][]): 'unicode' | 'ascii' {\n let unicode = 0;\n let ascii = 0;\n for (const row of grid) {\n for (const ch of row) {\n const code = ch.codePointAt(0) ?? 0;\n if (code >= 0x2500 && code <= 0x257f) unicode++;\n else if (ch === '+' || ch === '|' || ch === '-') ascii++;\n }\n }\n return ascii > unicode ? 'ascii' : 'unicode';\n}\n","/**\n * ASCII timeline renderer: semantic tracks/events -> canonical timeline art.\n *\n * The canonical authored form keeps the rail visually continuous and moves\n * event payloads onto pointer callouts:\n *\n * ▲ T28 :: delta 28 {#t28 column=12}\n * Kernel {#kernel start=8 end=72}: ───●────────────────○────►\n * ▼ T29 {#t29 column=36}\n *\n * Links follow the tracks as declarations. This form is compact, readable in\n * raw Markdown, and is the exact grammar consumed by `parse.ts`. Rendering is\n * deterministic and normalizes parser-sensitive text/ids up front, so it is a\n * byte fixpoint after one render:\n *\n * renderAsciiTimeline(parseAsciiTimeline(renderAsciiTimeline(t))) ===\n * renderAsciiTimeline(t)\n */\n\nimport type {\n AsciiTimeline,\n AsciiTimelineMarker,\n AsciiTimelineSide,\n AsciiTimelineStyle,\n} from './types.js';\n\nexport interface RenderAsciiTimelineOptions {\n /** Character vocabulary; defaults to the timeline's detected style. */\n style?: AsciiTimelineStyle;\n}\n\ninterface TimelineVocab {\n rail: string;\n arrow: string;\n marker: Record<AsciiTimelineMarker, string>;\n}\n\ninterface PreparedEvent {\n id: string;\n label: string;\n description?: string;\n descriptionSide?: AsciiTimelineSide;\n column: number;\n side: AsciiTimelineSide;\n callout?: boolean;\n marker: AsciiTimelineMarker;\n}\n\ninterface PreparedTrack {\n id: string;\n label?: string;\n endLabel?: string;\n startColumn: number;\n endColumn: number;\n events: PreparedEvent[];\n}\n\ninterface PreparedLink {\n source: string;\n target: string;\n label?: string;\n}\n\nconst UNICODE_VOCAB: TimelineVocab = {\n rail: '\\u2500',\n arrow: '\\u25ba',\n marker: {\n filled: '\\u25cf',\n hollow: '\\u25cb',\n diamond: '\\u25c6',\n },\n};\n\nconst ASCII_VOCAB: TimelineVocab = {\n rail: '-',\n arrow: '>',\n marker: {\n filled: '*',\n hollow: 'o',\n // The parser's ASCII vocabulary has no distinct diamond point. Folding\n // it to `*` is the canonical ASCII representation and is byte-stable.\n diamond: '*',\n },\n};\n\nconst MIN_AXIS_WIDTH = 48;\nconst MAX_COORDINATE_AXIS_WIDTH = 64;\nconst EVENT_SPACING = 3;\nconst TERMINAL_RAIL_LENGTH = 3;\n\n/** Render a timeline into deterministic, parser-canonical ASCII/Unicode art. */\nexport function renderAsciiTimeline(\n timeline: AsciiTimeline,\n options: RenderAsciiTimelineOptions = {},\n): string {\n const style = options.style ?? timeline.style;\n const vocab = style === 'ascii' ? ASCII_VOCAB : UNICODE_VOCAB;\n const { tracks, links } = prepareTimeline(timeline, style);\n if (tracks.length === 0) return '';\n\n const globalStart = Math.min(...tracks.map((track) => track.startColumn));\n const globalEnd = Math.max(...tracks.map((track) => track.endColumn));\n const globalSpan = Math.max(1, globalEnd - globalStart);\n const axisWidth = Math.max(\n MIN_AXIS_WIDTH,\n Math.min(MAX_COORDINATE_AXIS_WIDTH, Math.ceil(globalSpan)),\n ...tracks.map((track) => track.events.length * EVENT_SPACING),\n );\n const prefixes = tracks.map((track) => renderTrackPrefix(track));\n const prefixWidth = Math.max(...prefixes.map(displayWidth));\n const lines: string[] = [];\n\n tracks.forEach((track, index) => {\n if (index > 0) lines.push('');\n lines.push(\n ...renderTrack(\n track,\n style,\n vocab,\n prefixes[index],\n prefixWidth,\n axisWidth,\n globalStart,\n globalSpan,\n ),\n );\n });\n\n if (links.length > 0) {\n lines.push('');\n for (const link of links) lines.push(renderLink(link, style));\n }\n\n return lines.join('\\n');\n}\n\nfunction renderTrack(\n track: PreparedTrack,\n style: AsciiTimelineStyle,\n vocab: TimelineVocab,\n prefix: string,\n prefixWidth: number,\n axisWidth: number,\n globalStart: number,\n globalSpan: number,\n): string[] {\n const paddedPrefix = `${prefix}${' '.repeat(Math.max(0, prefixWidth - displayWidth(prefix)))}`;\n const positioned = positionEvents(track.events, axisWidth, globalStart, globalSpan);\n const rail = Array.from({ length: axisWidth + 1 }, () => vocab.rail);\n for (const { event, offset } of positioned) rail[offset] = vocab.marker[event.marker];\n\n const callouts = positioned.map(({ event, offset }) => ({\n event,\n column: prefixWidth + offset,\n text: renderEventPayload(event),\n }));\n const pointer = style === 'ascii' ? { above: '^', below: 'v' } : { above: '▲', below: '▼' };\n const above = renderCalloutLanes(\n callouts.filter(({ event }) => event.side === 'above'),\n pointer.above,\n );\n const below = renderCalloutLanes(\n callouts.filter(({ event }) => event.side === 'below'),\n pointer.below,\n );\n const axis = `${paddedPrefix}${rail.join('')}${vocab.rail.repeat(TERMINAL_RAIL_LENGTH)}${vocab.arrow}${track.endLabel ? ` ${track.endLabel}` : ''}`;\n return [...above, axis, ...below];\n}\n\nfunction renderEventPayload(event: PreparedEvent): string {\n const body = event.description ? `${event.label} :: ${event.description}` : event.label;\n const descriptionSide = event.descriptionSide ? ` descriptionSide=${event.descriptionSide}` : '';\n const callout = event.callout === false ? ' callout=false' : '';\n return `${body} {#${event.id} column=${formatCoordinate(event.column)}${descriptionSide}${callout}}`;\n}\n\nfunction renderTrackPrefix(track: PreparedTrack): string {\n const metadata = `{#${track.id} start=${formatCoordinate(track.startColumn)} end=${formatCoordinate(track.endColumn)}}`;\n return track.label ? `${track.label} ${metadata}: ` : `${metadata}: `;\n}\n\nfunction positionEvents(\n events: readonly PreparedEvent[],\n axisWidth: number,\n globalStart: number,\n globalSpan: number,\n): Array<{ event: PreparedEvent; offset: number }> {\n let previous = -1;\n return events.map((event, index) => {\n const ideal = Math.round(((event.column - globalStart) / globalSpan) * axisWidth);\n const remaining = events.length - index - 1;\n const latest = Math.max(0, axisWidth - remaining);\n const offset = Math.max(previous + 1, Math.min(latest, Math.max(0, ideal)));\n previous = offset;\n return { event, offset };\n });\n}\n\nfunction renderCalloutLanes(\n callouts: ReadonlyArray<{ column: number; text: string }>,\n pointer: string,\n): string[] {\n const lanes: Array<Array<{ column: number; text: string }>> = [];\n const laneEnds: number[] = [];\n for (const callout of callouts) {\n const end = callout.column + 2 + displayWidth(callout.text);\n let lane = laneEnds.findIndex((laneEnd) => callout.column > laneEnd + 1);\n if (lane < 0) {\n lane = lanes.length;\n lanes.push([]);\n laneEnds.push(-1);\n }\n lanes[lane].push(callout);\n laneEnds[lane] = end;\n }\n return lanes.map((lane) => {\n const chars: string[] = [];\n for (const callout of lane) {\n while (chars.length < callout.column) chars.push(' ');\n chars.push(pointer, ' ', ...Array.from(callout.text));\n }\n return chars.join('').trimEnd();\n });\n}\n\nfunction displayWidth(value: string): number {\n return Array.from(value).length;\n}\n\nfunction renderLink(link: PreparedLink, style: AsciiTimelineStyle): string {\n const arrow = style === 'ascii' ? '->' : '\\u2192';\n return `branch: ${link.source} ${arrow} ${link.target}${link.label ? ` : ${link.label}` : ''}`;\n}\n\nfunction prepareTimeline(\n timeline: AsciiTimeline,\n style: AsciiTimelineStyle,\n): { tracks: PreparedTrack[]; links: PreparedLink[] } {\n const sourceTracks = timeline.tracks\n .map((track, index) => ({ track, index }))\n .filter(({ track }) => Array.isArray(track.events) && track.events.length > 0)\n .sort(\n (a, b) =>\n finiteOr(a.track.row, a.index) - finiteOr(b.track.row, b.index) ||\n a.index - b.index ||\n a.track.id.localeCompare(b.track.id),\n );\n\n const usedTrackIds = new Set<string>();\n const usedEventIds = new Set<string>();\n const endpointIds = new Map<string, string>();\n const labelIds = new Map<string, string>();\n const tracks: PreparedTrack[] = [];\n let fallbackIndex = 0;\n\n for (const { track } of sourceTracks) {\n const trackLabel = canonicalInlineText(track.label);\n const endLabel = canonicalInlineText(track.endLabel);\n const trackId = uniqueId(\n canonicalId(track.id, canonicalId(trackLabel, `track_${tracks.length + 1}`)),\n usedTrackIds,\n );\n const sortedEvents = track.events\n .map((event, index) => ({ event, index }))\n .sort(\n (a, b) =>\n finiteOr(a.event.column, a.index) - finiteOr(b.event.column, b.index) ||\n a.index - b.index ||\n a.event.id.localeCompare(b.event.id),\n );\n const events: PreparedEvent[] = [];\n\n for (let index = 0; index < sortedEvents.length; index++) {\n const event = sortedEvents[index].event;\n const fallbackLabel = `Event ${index + 1}`;\n const label = canonicalInlineText(event.label) || fallbackLabel;\n const idBase = canonicalId(event.id, canonicalId(label, `event_${++fallbackIndex}`));\n const id = uniqueId(idBase, usedEventIds);\n const description = canonicalInlineText(event.description);\n const descriptionSide =\n description && (event.descriptionSide === 'above' || event.descriptionSide === 'below')\n ? event.descriptionSide\n : undefined;\n const column = canonicalCoordinate(event.column, index);\n const side: AsciiTimelineSide =\n event.side === 'below'\n ? 'below'\n : event.side === 'above'\n ? 'above'\n : index % 2 === 0\n ? 'above'\n : 'below';\n const marker = canonicalMarker(event.marker, style);\n\n events.push({\n id,\n label,\n ...(description ? { description } : {}),\n ...(descriptionSide ? { descriptionSide } : {}),\n column,\n side,\n ...(event.callout === false ? { callout: false } : {}),\n marker,\n });\n\n // Source ids are normally unique. Preserve the first target when a\n // malformed runtime value duplicates one; the rendered ids themselves\n // are always unique and are also valid branch endpoints.\n if (event.id && !endpointIds.has(event.id)) endpointIds.set(event.id, id);\n endpointIds.set(id, id);\n labelIds.set(slug(label), id);\n }\n\n const eventColumns = events.map((event) => event.column);\n const fallbackStart = eventColumns.length > 0 ? Math.min(...eventColumns) : 0;\n const fallbackEnd = eventColumns.length > 0 ? Math.max(...eventColumns) : fallbackStart + 1;\n tracks.push({\n id: trackId,\n ...(trackLabel ? { label: trackLabel } : {}),\n ...(endLabel ? { endLabel } : {}),\n startColumn: canonicalCoordinate(track.startColumn, fallbackStart),\n endColumn: canonicalCoordinate(track.endColumn, fallbackEnd),\n events,\n });\n }\n\n const resolveEndpoint = (value: string): string | undefined =>\n endpointIds.get(value) ?? labelIds.get(slug(value));\n const links: PreparedLink[] = [];\n for (const link of Array.isArray(timeline.links) ? timeline.links : []) {\n const source = resolveEndpoint(link.source);\n const target = resolveEndpoint(link.target);\n // Unresolved declarations would be dropped by the parser anyway. Drop\n // them before the first render so the emitted form is already a fixpoint.\n if (!source || !target) continue;\n const label = canonicalBranchText(link.label);\n links.push({ source, target, ...(label ? { label } : {}) });\n }\n links.sort(\n (a, b) =>\n a.source.localeCompare(b.source) ||\n a.target.localeCompare(b.target) ||\n (a.label ?? '').localeCompare(b.label ?? ''),\n );\n\n return { tracks, links };\n}\n\nfunction canonicalMarker(\n marker: AsciiTimelineMarker | undefined,\n style: AsciiTimelineStyle,\n): AsciiTimelineMarker {\n if (marker === 'hollow') return 'hollow';\n if (marker === 'diamond' && style !== 'ascii') return 'diamond';\n return 'filled';\n}\n\n/**\n * Normalize point glyphs that would accidentally create another event. Rails,\n * prose arrows, and hyphens are preserved: `parse.ts` only strips separator\n * rails at the payload edges, so `A > B` and `release--candidate` round-trip.\n */\nfunction canonicalInlineText(value: string | undefined): string {\n if (!value) return '';\n const normalized = value\n .normalize('NFC')\n .replace(/[\\r\\n\\t]+/g, ' ')\n .replace(/[\\u25cf\\u25cb\\u25c9\\u25c6\\u25c7\\u2022]+/gu, '\\u00b7')\n .replace(/\\*/g, '\\u2217')\n .replace(/::/g, '\\u2236')\n .replace(/\\s+/g, ' ')\n .trim();\n // A leading authored rail is otherwise indistinguishable from the\n // renderer's separator prefix to `stripEdgeRails`. Keep the punctuation\n // visible with non-structural lookalikes so `--watch`, `-1.5`, and\n // `─phase` survive the very first render/parse normalization cycle.\n return normalized.replace(/^[\\u2500\\u2501\\u2550\\u254c\\u254d\\u2504\\u2505\\u2508\\u2509-]+/u, (run) =>\n Array.from(run, (character) => (character === '-' ? '\\u2212' : '\\u2013')).join(''),\n );\n}\n\nfunction canonicalBranchText(value: string | undefined): string {\n return canonicalInlineText(value).replace(/\\s+/g, ' ').trim();\n}\n\nfunction canonicalId(value: string | undefined, fallback: string): string {\n const normalized = (value ?? '')\n .normalize('NFC')\n .replace(/[\\r\\n\\t\\s]+/g, '_')\n .replace(/[^A-Za-z0-9_.~-]+/g, '_')\n .replace(/^_+|_+$/g, '');\n return normalized || fallback;\n}\n\nfunction uniqueId(base: string, used: Set<string>): string {\n if (!used.has(base)) {\n used.add(base);\n return base;\n }\n let suffix = 2;\n let candidate = `${base}_${suffix}`;\n while (used.has(candidate)) candidate = `${base}_${++suffix}`;\n used.add(candidate);\n return candidate;\n}\n\nfunction slug(value: string): string {\n return (\n value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '') || 'event'\n );\n}\n\nfunction finiteOr(value: number, fallback: number): number {\n return Number.isFinite(value) ? value : fallback;\n}\n\nfunction canonicalCoordinate(value: number, fallback: number): number {\n const finite = finiteOr(value, fallback);\n return Math.max(0, Object.is(finite, -0) ? 0 : finite);\n}\n\nfunction formatCoordinate(value: number): string {\n return String(Object.is(value, -0) ? 0 : value);\n}\n","/**\n * ASCII tree renderer: nested nodes → clean tree art.\n *\n * A deterministic depth-first walk emitting rail/branch prefixes. The\n * fixpoint is structural: `parseTree(renderTree(t))` preserves the node\n * hierarchy + labels + comments, and `renderTree(parseTree(renderTree(t)))`\n * is byte-identical (idempotent after one normalization cycle). Unlike the\n * diagram renderer there is no spatial layout, so jitter is impossible.\n */\n\nimport { ASCII_TREE_VOCAB, UNICODE_TREE_VOCAB } from './chars.js';\nimport type { Tree, TreeNode } from './types.js';\n\nexport interface RenderTreeOptions {\n /** Character vocabulary; defaults to the tree's own detected style. */\n style?: 'unicode' | 'ascii';\n}\n\nexport function renderTree(tree: Tree, options: RenderTreeOptions = {}): string {\n const vocab = (options.style ?? tree.style) === 'ascii' ? ASCII_TREE_VOCAB : UNICODE_TREE_VOCAB;\n const lines: string[] = [];\n\n const label = (node: TreeNode): string =>\n node.comment ? `${node.label} # ${node.comment}` : node.label;\n\n const walk = (nodes: readonly TreeNode[], prefix: string): void => {\n nodes.forEach((node, i) => {\n const last = i === nodes.length - 1;\n lines.push(prefix + (last ? vocab.elbow : vocab.tee) + label(node));\n walk(node.children, prefix + (last ? vocab.gap : vocab.rail));\n });\n };\n\n // Roots sit at column 0 with no connector; their children get branches.\n for (const root of tree.roots) {\n lines.push(label(root));\n walk(root.children, '');\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA,yDAgC4B,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["list","draft","title","suggestion","list","diagram","list","rect","title","diagram","slugify","slug","UNICODE_VOCAB","ASCII_VOCAB","timeline","tree"]}