@awc-ui/core 1.0.0-beta.2 → 1.0.0-beta.4

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 (833) hide show
  1. package/README.md +18 -0
  2. package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
  3. package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
  4. package/dist/cjs/engine.wasm-9JtXME10.js +12 -0
  5. package/dist/cjs/engine.wasm-9JtXME10.js.map +1 -0
  6. package/dist/cjs/{index-DlQ_5_Mv.js → index-Bm07YAg9.js} +4 -15
  7. package/dist/cjs/index-Bm07YAg9.js.map +1 -0
  8. package/dist/cjs/lazy-loading-indicator-CoC-_DMs.js +69 -0
  9. package/dist/cjs/lazy-loading-indicator-CoC-_DMs.js.map +1 -0
  10. package/dist/cjs/loader.cjs.js +4 -3
  11. package/dist/cjs/loader.cjs.js.map +1 -1
  12. package/dist/cjs/md-accordion-item.cjs.entry.js +4 -4
  13. package/dist/cjs/md-accordion.cjs.entry.js +1 -1
  14. package/dist/cjs/md-app-bar.cjs.entry.js +2 -2
  15. package/dist/cjs/md-area-chart.cjs.entry.js +3 -3
  16. package/dist/cjs/md-autocomplete.cjs.entry.js +6 -5
  17. package/dist/cjs/md-autocomplete.cjs.entry.js.map +1 -1
  18. package/dist/cjs/md-avatar_2.cjs.entry.js +4 -4
  19. package/dist/cjs/md-badge.cjs.entry.js +3 -3
  20. package/dist/cjs/md-bar-chart.cjs.entry.js +3 -3
  21. package/dist/cjs/md-bottom-sheet.cjs.entry.js +5 -5
  22. package/dist/cjs/md-breadcrumb-item.cjs.entry.js +1 -1
  23. package/dist/cjs/md-breadcrumbs.cjs.entry.js +3 -3
  24. package/dist/cjs/md-button-group.cjs.entry.js +3 -3
  25. package/dist/cjs/{md-button_7.cjs.entry.js → md-button_6.cjs.entry.js} +14 -39
  26. package/dist/cjs/md-button_6.cjs.entry.js.map +1 -0
  27. package/dist/cjs/md-checkbox.cjs.entry.js +3 -3
  28. package/dist/cjs/md-chip.cjs.entry.js +3 -3
  29. package/dist/cjs/md-color-picker.cjs.entry.js +1 -1
  30. package/dist/cjs/md-date-picker.cjs.entry.js +2 -2
  31. package/dist/cjs/md-dialog.cjs.entry.js +3 -3
  32. package/dist/cjs/md-divider.cjs.entry.js +3 -3
  33. package/dist/cjs/md-fab-menu-item.cjs.entry.js +3 -3
  34. package/dist/cjs/md-fab-menu.cjs.entry.js +3 -3
  35. package/dist/cjs/md-fab.cjs.entry.js +3 -3
  36. package/dist/cjs/md-line-chart.cjs.entry.js +3 -3
  37. package/dist/cjs/md-list-item.cjs.entry.js +4 -4
  38. package/dist/cjs/md-list.cjs.entry.js +4 -4
  39. package/dist/cjs/md-loading-indicator-CmzdcYLR.js +33 -0
  40. package/dist/cjs/md-loading-indicator-CmzdcYLR.js.map +1 -0
  41. package/dist/cjs/md-loading-indicator.cjs.entry.js +11 -0
  42. package/dist/cjs/md-loading-indicator.cjs.entry.js.map +1 -0
  43. package/dist/cjs/md-menu-item-group.cjs.entry.js +1 -1
  44. package/dist/cjs/md-menu_2.cjs.entry.js +6 -6
  45. package/dist/cjs/md-meter.cjs.entry.js +1 -1
  46. package/dist/cjs/md-multi-select.cjs.entry.js +7 -6
  47. package/dist/cjs/md-multi-select.cjs.entry.js.map +1 -1
  48. package/dist/cjs/md-navigation-bar.cjs.entry.js +2 -2
  49. package/dist/cjs/md-navigation-rail-tab.cjs.entry.js +1 -1
  50. package/dist/cjs/md-navigation-rail.cjs.entry.js +1 -1
  51. package/dist/cjs/md-navigation-tab.cjs.entry.js +3 -3
  52. package/dist/cjs/md-number-field.cjs.entry.js +3 -3
  53. package/dist/cjs/md-organization-chart.cjs.entry.js +3 -3
  54. package/dist/cjs/md-otp-field.cjs.entry.js +4 -4
  55. package/dist/cjs/md-pie-chart.cjs.entry.js +1 -1
  56. package/dist/cjs/md-progress-indicator.cjs.entry.js +1 -1
  57. package/dist/cjs/md-rating.cjs.entry.js +1 -1
  58. package/dist/cjs/md-search.cjs.entry.js +8 -7
  59. package/dist/cjs/md-search.cjs.entry.js.map +1 -1
  60. package/dist/cjs/md-segmented-button-set.cjs.entry.js +1 -1
  61. package/dist/cjs/md-segmented-button.cjs.entry.js +1 -1
  62. package/dist/cjs/md-select-option.cjs.entry.js +2 -2
  63. package/dist/cjs/md-select.cjs.entry.js +7 -6
  64. package/dist/cjs/md-select.cjs.entry.js.map +1 -1
  65. package/dist/cjs/md-side-sheet.cjs.entry.js +1 -1
  66. package/dist/cjs/md-skeleton.cjs.entry.js +1 -1
  67. package/dist/cjs/md-slider.cjs.entry.js +3 -3
  68. package/dist/cjs/md-sparkline.cjs.entry.js +3 -3
  69. package/dist/cjs/md-split-button.cjs.entry.js +1 -1
  70. package/dist/cjs/md-status-dot.cjs.entry.js +2 -2
  71. package/dist/cjs/md-step.cjs.entry.js +1 -1
  72. package/dist/cjs/md-stepper.cjs.entry.js +1 -1
  73. package/dist/cjs/md-sub-menu-item.cjs.entry.js +1 -1
  74. package/dist/cjs/md-switch.cjs.entry.js +1 -1
  75. package/dist/cjs/md-tab-panel.cjs.entry.js +1 -1
  76. package/dist/cjs/md-tab-panels.cjs.entry.js +1 -1
  77. package/dist/cjs/md-tab.cjs.entry.js +1 -1
  78. package/dist/cjs/md-table-body.cjs.entry.js +1 -1
  79. package/dist/cjs/md-table-cell.cjs.entry.js +1 -1
  80. package/dist/cjs/md-table-container.cjs.entry.js +1 -1
  81. package/dist/cjs/md-table-expand-toggle.cjs.entry.js +1 -1
  82. package/dist/cjs/md-table-foot.cjs.entry.js +1 -1
  83. package/dist/cjs/md-table-head.cjs.entry.js +1 -1
  84. package/dist/cjs/md-table-pagination.cjs.entry.js +1 -1
  85. package/dist/cjs/md-table-row.cjs.entry.js +1 -1
  86. package/dist/cjs/md-table-sort-label.cjs.entry.js +1 -1
  87. package/dist/cjs/md-table-toolbar.cjs.entry.js +1 -1
  88. package/dist/cjs/md-table.cjs.entry.js +4 -4
  89. package/dist/cjs/md-tabs.cjs.entry.js +1 -1
  90. package/dist/cjs/md-text-field.cjs.entry.js +8 -8
  91. package/dist/cjs/md-time-picker.cjs.entry.js +2 -2
  92. package/dist/cjs/md-toolbar.cjs.entry.js +1 -1
  93. package/dist/cjs/md-transfer-list.cjs.entry.js +2 -2
  94. package/dist/cjs/md3.cjs.js +4 -3
  95. package/dist/cjs/md3.cjs.js.map +1 -1
  96. package/dist/cjs/{virtual-select-controller-CqriaZgm.js → virtual-select-controller-C5cSoKfB.js} +10 -9
  97. package/dist/cjs/virtual-select-controller-C5cSoKfB.js.map +1 -0
  98. package/dist/collection/collection-manifest.json +1 -1
  99. package/dist/collection/components/md-accordion-item/md-accordion-item.js +3 -3
  100. package/dist/collection/components/md-app-bar/md-app-bar.js +1 -1
  101. package/dist/collection/components/md-area-chart/md-area-chart.js +2 -2
  102. package/dist/collection/components/md-autocomplete/md-autocomplete.js +4 -3
  103. package/dist/collection/components/md-autocomplete/md-autocomplete.js.map +1 -1
  104. package/dist/collection/components/md-avatar/md-avatar.js +2 -2
  105. package/dist/collection/components/md-badge/md-badge.js +2 -2
  106. package/dist/collection/components/md-bar-chart/md-bar-chart.js +2 -2
  107. package/dist/collection/components/md-bottom-sheet/md-bottom-sheet.js +4 -4
  108. package/dist/collection/components/md-breadcrumbs/md-breadcrumbs.js +2 -2
  109. package/dist/collection/components/md-button/md-button.js +4 -3
  110. package/dist/collection/components/md-button/md-button.js.map +1 -1
  111. package/dist/collection/components/md-button-group/md-button-group.js +2 -2
  112. package/dist/collection/components/md-card/md-card.js +2 -2
  113. package/dist/collection/components/md-checkbox/md-checkbox.js +2 -2
  114. package/dist/collection/components/md-chip/md-chip.js +2 -2
  115. package/dist/collection/components/md-date-picker/md-date-picker.js +1 -1
  116. package/dist/collection/components/md-dialog/md-dialog.js +2 -2
  117. package/dist/collection/components/md-divider/md-divider.js +2 -2
  118. package/dist/collection/components/md-fab/md-fab.js +2 -2
  119. package/dist/collection/components/md-fab-menu/md-fab-menu.js +2 -2
  120. package/dist/collection/components/md-fab-menu-item/md-fab-menu-item.js +2 -2
  121. package/dist/collection/components/md-icon-button/md-icon-button.js +4 -4
  122. package/dist/collection/components/md-line-chart/md-line-chart.js +2 -2
  123. package/dist/collection/components/md-list/md-list.js +3 -3
  124. package/dist/collection/components/md-list-item/md-list-item.js +3 -3
  125. package/dist/collection/components/md-loading-indicator/md-loading-indicator.js +2 -2
  126. package/dist/collection/components/md-menu/md-menu.js +3 -3
  127. package/dist/collection/components/md-menu-item/md-menu-item.js +2 -2
  128. package/dist/collection/components/md-multi-select/md-multi-select.js +5 -4
  129. package/dist/collection/components/md-multi-select/md-multi-select.js.map +1 -1
  130. package/dist/collection/components/md-navigation-bar/md-navigation-bar.js +1 -1
  131. package/dist/collection/components/md-navigation-tab/md-navigation-tab.js +2 -2
  132. package/dist/collection/components/md-number-field/md-number-field.js +2 -2
  133. package/dist/collection/components/md-organization-chart/md-organization-chart.js +2 -2
  134. package/dist/collection/components/md-otp-field/md-otp-field.js +3 -3
  135. package/dist/collection/components/md-ripple/md-ripple.js +1 -1
  136. package/dist/collection/components/md-search/md-search.js +7 -6
  137. package/dist/collection/components/md-search/md-search.js.map +1 -1
  138. package/dist/collection/components/md-select/md-select.js +5 -4
  139. package/dist/collection/components/md-select/md-select.js.map +1 -1
  140. package/dist/collection/components/md-select-option/md-select-option.js +1 -1
  141. package/dist/collection/components/md-slider/md-slider.js +2 -2
  142. package/dist/collection/components/md-sparkline/md-sparkline.js +2 -2
  143. package/dist/collection/components/md-status-dot/md-status-dot.js +1 -1
  144. package/dist/collection/components/md-table/md-table.js +3 -3
  145. package/dist/collection/components/md-text-field/md-text-field.js +7 -7
  146. package/dist/collection/components/md-time-picker/md-time-picker.js +1 -1
  147. package/dist/collection/components/md-tooltip/md-tooltip.js +1 -1
  148. package/dist/collection/components/md-transfer-list/md-transfer-list.js +1 -1
  149. package/dist/collection/utils/lazy-loading-indicator.js +62 -0
  150. package/dist/collection/utils/lazy-loading-indicator.js.map +1 -0
  151. package/dist/collection/wasm/engine-abi.js +8 -2
  152. package/dist/collection/wasm/engine-abi.js.map +1 -1
  153. package/dist/components/index.js +1 -1
  154. package/dist/components/md-accordion-item.js +1 -1
  155. package/dist/components/md-accordion.js +1 -1
  156. package/dist/components/md-app-bar.js +1 -1
  157. package/dist/components/md-area-chart.js +1 -1
  158. package/dist/components/md-autocomplete.js +1 -1
  159. package/dist/components/md-autocomplete.js.map +1 -1
  160. package/dist/components/md-avatar.js +1 -1
  161. package/dist/components/md-badge.js +1 -1
  162. package/dist/components/md-bar-chart.js +1 -1
  163. package/dist/components/md-bottom-sheet.js +1 -1
  164. package/dist/components/md-breadcrumb-item.js +1 -1
  165. package/dist/components/md-breadcrumbs.js +1 -1
  166. package/dist/components/md-button-group.js +1 -1
  167. package/dist/components/md-button.js +1 -1
  168. package/dist/components/md-card.js +1 -1
  169. package/dist/components/md-checkbox.js +1 -1
  170. package/dist/components/md-chip.js +1 -1
  171. package/dist/components/md-color-picker.js +1 -1
  172. package/dist/components/md-date-picker.js +1 -1
  173. package/dist/components/md-date-picker.js.map +1 -1
  174. package/dist/components/md-dialog.js +1 -1
  175. package/dist/components/md-dialog.js.map +1 -1
  176. package/dist/components/md-divider.js +1 -1
  177. package/dist/components/md-divider.js.map +1 -1
  178. package/dist/components/md-fab-menu-item.js +1 -1
  179. package/dist/components/md-fab-menu.js +1 -1
  180. package/dist/components/md-fab.js +1 -1
  181. package/dist/components/md-icon-button.js +1 -1
  182. package/dist/components/md-line-chart.js +1 -1
  183. package/dist/components/md-line-chart.js.map +1 -1
  184. package/dist/components/md-list-item.js +1 -1
  185. package/dist/components/md-list.js +1 -1
  186. package/dist/components/md-loading-indicator.js +1 -1
  187. package/dist/components/md-menu-item-group.js +1 -1
  188. package/dist/components/md-menu-item.js +1 -1
  189. package/dist/components/md-menu.js +1 -1
  190. package/dist/components/md-meter.js +1 -1
  191. package/dist/components/md-multi-select.js +1 -1
  192. package/dist/components/md-multi-select.js.map +1 -1
  193. package/dist/components/md-navigation-bar.js +1 -1
  194. package/dist/components/md-navigation-rail-tab.js +1 -1
  195. package/dist/components/md-navigation-rail.js +1 -1
  196. package/dist/components/md-navigation-tab.js +1 -1
  197. package/dist/components/md-number-field.js +1 -1
  198. package/dist/components/md-organization-chart.js +1 -1
  199. package/dist/components/md-otp-field.js +1 -1
  200. package/dist/components/md-pie-chart.js +1 -1
  201. package/dist/components/md-progress-indicator.js +1 -1
  202. package/dist/components/md-radio.js +1 -1
  203. package/dist/components/md-rating.js +1 -1
  204. package/dist/components/md-ripple.js +1 -1
  205. package/dist/components/md-search.js +1 -1
  206. package/dist/components/md-search.js.map +1 -1
  207. package/dist/components/md-segmented-button-set.js +1 -1
  208. package/dist/components/md-segmented-button.js +1 -1
  209. package/dist/components/md-select-option.js +1 -1
  210. package/dist/components/md-select.js +1 -1
  211. package/dist/components/md-side-sheet.js +1 -1
  212. package/dist/components/md-skeleton.js +1 -1
  213. package/dist/components/md-slider.js +1 -1
  214. package/dist/components/md-snackbar.js +1 -1
  215. package/dist/components/md-snackbar.js.map +1 -1
  216. package/dist/components/md-sparkline.js +1 -1
  217. package/dist/components/md-split-button.js +1 -1
  218. package/dist/components/md-status-dot.js +1 -1
  219. package/dist/components/md-step.js +1 -1
  220. package/dist/components/md-step.js.map +1 -1
  221. package/dist/components/md-stepper.js +1 -1
  222. package/dist/components/md-stepper.js.map +1 -1
  223. package/dist/components/md-sub-menu-item.js +1 -1
  224. package/dist/components/md-switch.js +1 -1
  225. package/dist/components/md-tab-panel.js +1 -1
  226. package/dist/components/md-tab-panels.js +1 -1
  227. package/dist/components/md-tab.js +1 -1
  228. package/dist/components/md-table-body.js +1 -1
  229. package/dist/components/md-table-cell.js +1 -1
  230. package/dist/components/md-table-container.js +1 -1
  231. package/dist/components/md-table-expand-toggle.js +1 -1
  232. package/dist/components/md-table-foot.js +1 -1
  233. package/dist/components/md-table-head.js +1 -1
  234. package/dist/components/md-table-pagination.js +1 -1
  235. package/dist/components/md-table-pagination.js.map +1 -1
  236. package/dist/components/md-table-row.js +1 -1
  237. package/dist/components/md-table-sort-label.js +1 -1
  238. package/dist/components/md-table-toolbar.js +1 -1
  239. package/dist/components/md-table.js +1 -1
  240. package/dist/components/md-tabs.js +1 -1
  241. package/dist/components/md-text-field.js +1 -1
  242. package/dist/components/md-time-picker.js +1 -1
  243. package/dist/components/md-time-picker.js.map +1 -1
  244. package/dist/components/md-toolbar.js +1 -1
  245. package/dist/components/md-tooltip.js +1 -1
  246. package/dist/components/md-transfer-list.js +1 -1
  247. package/dist/components/p-1RSrsLOs.js +2 -0
  248. package/dist/components/p-1RSrsLOs.js.map +1 -0
  249. package/dist/components/p-2HV152w7.js +2 -0
  250. package/dist/components/p-2HV152w7.js.map +1 -0
  251. package/dist/components/p-6ZDAcEKN.js +2 -0
  252. package/dist/components/p-6ZDAcEKN.js.map +1 -0
  253. package/dist/components/p-B2fYoYe9.js +2 -0
  254. package/dist/components/p-B2fYoYe9.js.map +1 -0
  255. package/dist/components/p-BR6gfOQH.js +2 -0
  256. package/dist/components/p-BR6gfOQH.js.map +1 -0
  257. package/dist/components/p-Bz-JaJcA.js +2 -0
  258. package/dist/components/p-Bz-JaJcA.js.map +1 -0
  259. package/dist/components/p-C77M30dm.js +2 -0
  260. package/dist/components/p-C77M30dm.js.map +1 -0
  261. package/dist/components/p-CNgkGl_1.js +2 -0
  262. package/dist/components/p-CNgkGl_1.js.map +1 -0
  263. package/dist/components/p-CfBPnYW7.js +2 -0
  264. package/dist/components/p-CfBPnYW7.js.map +1 -0
  265. package/dist/components/p-D5Ht729E.js +2 -0
  266. package/dist/components/p-D5Ht729E.js.map +1 -0
  267. package/dist/components/p-DPqGg8C1.js +2 -0
  268. package/dist/components/p-DPqGg8C1.js.map +1 -0
  269. package/dist/components/p-De3E5Q8v.js +2 -0
  270. package/dist/components/p-De3E5Q8v.js.map +1 -0
  271. package/dist/components/p-Dm_7DA1f.js +2 -0
  272. package/dist/components/p-Dm_7DA1f.js.map +1 -0
  273. package/dist/components/p-Dz3R-2Wn.js +2 -0
  274. package/dist/components/p-Dz3R-2Wn.js.map +1 -0
  275. package/dist/components/p-Zjf9uhOr.js +2 -0
  276. package/dist/components/p-Zjf9uhOr.js.map +1 -0
  277. package/dist/components/p-ssLobpGS.js +2 -0
  278. package/dist/components/p-ssLobpGS.js.map +1 -0
  279. package/dist/components/p-tSoecrcz.js +2 -0
  280. package/dist/components/p-tSoecrcz.js.map +1 -0
  281. package/dist/components/p-zMR3UIR_.js +2 -0
  282. package/dist/components/p-zMR3UIR_.js.map +1 -0
  283. package/dist/components-csr/index.js +2 -0
  284. package/dist/components-csr/index.js.map +1 -0
  285. package/dist/components-csr/md-accordion-item.js +2 -0
  286. package/dist/components-csr/md-accordion-item.js.map +1 -0
  287. package/dist/components-csr/md-accordion.js +2 -0
  288. package/dist/components-csr/md-accordion.js.map +1 -0
  289. package/dist/components-csr/md-app-bar.js +2 -0
  290. package/dist/components-csr/md-app-bar.js.map +1 -0
  291. package/dist/components-csr/md-area-chart.js +2 -0
  292. package/dist/components-csr/md-area-chart.js.map +1 -0
  293. package/dist/components-csr/md-autocomplete.js +2 -0
  294. package/dist/components-csr/md-autocomplete.js.map +1 -0
  295. package/dist/components-csr/md-avatar.js +2 -0
  296. package/dist/components-csr/md-avatar.js.map +1 -0
  297. package/dist/components-csr/md-badge.js +2 -0
  298. package/dist/components-csr/md-badge.js.map +1 -0
  299. package/dist/components-csr/md-bar-chart.js +2 -0
  300. package/dist/components-csr/md-bar-chart.js.map +1 -0
  301. package/dist/components-csr/md-bottom-sheet.js +2 -0
  302. package/dist/components-csr/md-bottom-sheet.js.map +1 -0
  303. package/dist/components-csr/md-breadcrumb-item.js +2 -0
  304. package/dist/components-csr/md-breadcrumb-item.js.map +1 -0
  305. package/dist/components-csr/md-breadcrumbs.js +2 -0
  306. package/dist/components-csr/md-breadcrumbs.js.map +1 -0
  307. package/dist/components-csr/md-button-group.js +2 -0
  308. package/dist/components-csr/md-button-group.js.map +1 -0
  309. package/dist/components-csr/md-button.js +2 -0
  310. package/dist/components-csr/md-button.js.map +1 -0
  311. package/dist/components-csr/md-card.js +2 -0
  312. package/dist/components-csr/md-card.js.map +1 -0
  313. package/dist/components-csr/md-checkbox.js +2 -0
  314. package/dist/components-csr/md-checkbox.js.map +1 -0
  315. package/dist/components-csr/md-chip.js +2 -0
  316. package/dist/components-csr/md-chip.js.map +1 -0
  317. package/dist/components-csr/md-color-picker.js +2 -0
  318. package/dist/components-csr/md-color-picker.js.map +1 -0
  319. package/dist/components-csr/md-date-picker.js +2 -0
  320. package/dist/components-csr/md-date-picker.js.map +1 -0
  321. package/dist/components-csr/md-dialog.js +2 -0
  322. package/dist/components-csr/md-dialog.js.map +1 -0
  323. package/dist/components-csr/md-divider.js +2 -0
  324. package/dist/components-csr/md-divider.js.map +1 -0
  325. package/dist/components-csr/md-fab-menu-item.js +2 -0
  326. package/dist/components-csr/md-fab-menu-item.js.map +1 -0
  327. package/dist/components-csr/md-fab-menu.js +2 -0
  328. package/dist/components-csr/md-fab-menu.js.map +1 -0
  329. package/dist/components-csr/md-fab.js +2 -0
  330. package/dist/components-csr/md-fab.js.map +1 -0
  331. package/dist/components-csr/md-icon-button.js +2 -0
  332. package/dist/components-csr/md-icon-button.js.map +1 -0
  333. package/dist/components-csr/md-line-chart.js +2 -0
  334. package/dist/components-csr/md-line-chart.js.map +1 -0
  335. package/dist/components-csr/md-list-item.js +2 -0
  336. package/dist/components-csr/md-list-item.js.map +1 -0
  337. package/dist/components-csr/md-list.js +2 -0
  338. package/dist/components-csr/md-list.js.map +1 -0
  339. package/dist/components-csr/md-loading-indicator.js +2 -0
  340. package/dist/components-csr/md-loading-indicator.js.map +1 -0
  341. package/dist/components-csr/md-menu-item-group.js +2 -0
  342. package/dist/components-csr/md-menu-item-group.js.map +1 -0
  343. package/dist/components-csr/md-menu-item.js +2 -0
  344. package/dist/components-csr/md-menu-item.js.map +1 -0
  345. package/dist/components-csr/md-menu.js +2 -0
  346. package/dist/components-csr/md-menu.js.map +1 -0
  347. package/dist/components-csr/md-meter.js +2 -0
  348. package/dist/components-csr/md-meter.js.map +1 -0
  349. package/dist/components-csr/md-multi-select.js +2 -0
  350. package/dist/components-csr/md-multi-select.js.map +1 -0
  351. package/dist/components-csr/md-navigation-bar.js +2 -0
  352. package/dist/components-csr/md-navigation-bar.js.map +1 -0
  353. package/dist/components-csr/md-navigation-rail-tab.js +2 -0
  354. package/dist/components-csr/md-navigation-rail-tab.js.map +1 -0
  355. package/dist/components-csr/md-navigation-rail.js +2 -0
  356. package/dist/components-csr/md-navigation-rail.js.map +1 -0
  357. package/dist/components-csr/md-navigation-tab.js +2 -0
  358. package/dist/components-csr/md-navigation-tab.js.map +1 -0
  359. package/dist/components-csr/md-number-field.js +2 -0
  360. package/dist/components-csr/md-number-field.js.map +1 -0
  361. package/dist/components-csr/md-organization-chart.js +2 -0
  362. package/dist/components-csr/md-organization-chart.js.map +1 -0
  363. package/dist/components-csr/md-otp-field.js +2 -0
  364. package/dist/components-csr/md-otp-field.js.map +1 -0
  365. package/dist/components-csr/md-pie-chart.js +2 -0
  366. package/dist/components-csr/md-pie-chart.js.map +1 -0
  367. package/dist/components-csr/md-progress-indicator.js +2 -0
  368. package/dist/components-csr/md-progress-indicator.js.map +1 -0
  369. package/dist/components-csr/md-radio.js +2 -0
  370. package/dist/components-csr/md-radio.js.map +1 -0
  371. package/dist/components-csr/md-rating.js +2 -0
  372. package/dist/components-csr/md-rating.js.map +1 -0
  373. package/dist/components-csr/md-ripple.js +2 -0
  374. package/dist/components-csr/md-ripple.js.map +1 -0
  375. package/dist/components-csr/md-search.js +2 -0
  376. package/dist/components-csr/md-search.js.map +1 -0
  377. package/dist/components-csr/md-segmented-button-set.js +2 -0
  378. package/dist/components-csr/md-segmented-button-set.js.map +1 -0
  379. package/dist/components-csr/md-segmented-button.js +2 -0
  380. package/dist/components-csr/md-segmented-button.js.map +1 -0
  381. package/dist/components-csr/md-select-option.js +2 -0
  382. package/dist/components-csr/md-select-option.js.map +1 -0
  383. package/dist/components-csr/md-select.js +2 -0
  384. package/dist/components-csr/md-select.js.map +1 -0
  385. package/dist/components-csr/md-side-sheet.js +2 -0
  386. package/dist/components-csr/md-side-sheet.js.map +1 -0
  387. package/dist/components-csr/md-skeleton.js +2 -0
  388. package/dist/components-csr/md-skeleton.js.map +1 -0
  389. package/dist/components-csr/md-slider.js +2 -0
  390. package/dist/components-csr/md-slider.js.map +1 -0
  391. package/dist/components-csr/md-snackbar.js +2 -0
  392. package/dist/components-csr/md-snackbar.js.map +1 -0
  393. package/dist/components-csr/md-sparkline.js +2 -0
  394. package/dist/components-csr/md-sparkline.js.map +1 -0
  395. package/dist/components-csr/md-split-button.js +2 -0
  396. package/dist/components-csr/md-split-button.js.map +1 -0
  397. package/dist/components-csr/md-status-dot.js +2 -0
  398. package/dist/components-csr/md-status-dot.js.map +1 -0
  399. package/dist/components-csr/md-step.js +2 -0
  400. package/dist/components-csr/md-step.js.map +1 -0
  401. package/dist/components-csr/md-stepper.js +2 -0
  402. package/dist/components-csr/md-stepper.js.map +1 -0
  403. package/dist/components-csr/md-sub-menu-item.js +2 -0
  404. package/dist/components-csr/md-sub-menu-item.js.map +1 -0
  405. package/dist/components-csr/md-switch.js +2 -0
  406. package/dist/components-csr/md-switch.js.map +1 -0
  407. package/dist/components-csr/md-tab-panel.js +2 -0
  408. package/dist/components-csr/md-tab-panel.js.map +1 -0
  409. package/dist/components-csr/md-tab-panels.js +2 -0
  410. package/dist/components-csr/md-tab-panels.js.map +1 -0
  411. package/dist/components-csr/md-tab.js +2 -0
  412. package/dist/components-csr/md-tab.js.map +1 -0
  413. package/dist/components-csr/md-table-body.js +2 -0
  414. package/dist/components-csr/md-table-body.js.map +1 -0
  415. package/dist/components-csr/md-table-cell.js +2 -0
  416. package/dist/components-csr/md-table-cell.js.map +1 -0
  417. package/dist/components-csr/md-table-container.js +2 -0
  418. package/dist/components-csr/md-table-container.js.map +1 -0
  419. package/dist/components-csr/md-table-expand-toggle.js +2 -0
  420. package/dist/components-csr/md-table-expand-toggle.js.map +1 -0
  421. package/dist/components-csr/md-table-foot.js +2 -0
  422. package/dist/components-csr/md-table-foot.js.map +1 -0
  423. package/dist/components-csr/md-table-head.js +2 -0
  424. package/dist/components-csr/md-table-head.js.map +1 -0
  425. package/dist/components-csr/md-table-pagination.js +2 -0
  426. package/dist/components-csr/md-table-pagination.js.map +1 -0
  427. package/dist/components-csr/md-table-row.js +2 -0
  428. package/dist/components-csr/md-table-row.js.map +1 -0
  429. package/dist/components-csr/md-table-sort-label.js +2 -0
  430. package/dist/components-csr/md-table-sort-label.js.map +1 -0
  431. package/dist/components-csr/md-table-toolbar.js +2 -0
  432. package/dist/components-csr/md-table-toolbar.js.map +1 -0
  433. package/dist/components-csr/md-table.js +2 -0
  434. package/dist/components-csr/md-table.js.map +1 -0
  435. package/dist/components-csr/md-tabs.js +2 -0
  436. package/dist/components-csr/md-tabs.js.map +1 -0
  437. package/dist/components-csr/md-text-field.js +2 -0
  438. package/dist/components-csr/md-text-field.js.map +1 -0
  439. package/dist/components-csr/md-time-picker.js +2 -0
  440. package/dist/components-csr/md-time-picker.js.map +1 -0
  441. package/dist/components-csr/md-toolbar.js +2 -0
  442. package/dist/components-csr/md-toolbar.js.map +1 -0
  443. package/dist/components-csr/md-tooltip.js +2 -0
  444. package/dist/components-csr/md-tooltip.js.map +1 -0
  445. package/dist/components-csr/md-transfer-list.js +2 -0
  446. package/dist/components-csr/md-transfer-list.js.map +1 -0
  447. package/dist/components-csr/p-6WgHjhDg.js +2 -0
  448. package/dist/components-csr/p-6WgHjhDg.js.map +1 -0
  449. package/dist/{components/p-uTEkf0sE.js → components-csr/p-BEmwDSzw.js} +2 -2
  450. package/dist/{components/p-C8EP4S21.js → components-csr/p-BQKzjYcY.js} +2 -2
  451. package/dist/{components/p-BwXpiUsu.js → components-csr/p-BWMwewtY.js} +2 -2
  452. package/dist/{components/p-DXXUoRSH.js → components-csr/p-BZakoRau.js} +2 -2
  453. package/dist/components-csr/p-BZakoRau.js.map +1 -0
  454. package/dist/{md3/p-BjYKc1Ge.js → components-csr/p-BdEoSBtL.js} +2 -2
  455. package/dist/components-csr/p-BdEoSBtL.js.map +1 -0
  456. package/dist/{components/p-B0Opn6dK.js → components-csr/p-Bkt_X-6v.js} +2 -2
  457. package/dist/components-csr/p-Bx6--dQF.js.map +1 -0
  458. package/dist/components-csr/p-Bz-JaJcA.js +2 -0
  459. package/dist/components-csr/p-Bz-JaJcA.js.map +1 -0
  460. package/dist/{components/p-stybaFzj.js → components-csr/p-C3vB0Hd9.js} +2 -2
  461. package/dist/{components/p-B3MWYEEJ.js → components-csr/p-CF7mq5T7.js} +2 -2
  462. package/dist/{components/p-7fN_yCXW.js → components-csr/p-CVMM-tdC.js} +2 -2
  463. package/dist/components-csr/p-C_ogF68H.js.map +1 -0
  464. package/dist/components-csr/p-Cch_V1vi.js +2 -0
  465. package/dist/components-csr/p-Cch_V1vi.js.map +1 -0
  466. package/dist/components-csr/p-CfBPnYW7.js +2 -0
  467. package/dist/components-csr/p-CfBPnYW7.js.map +1 -0
  468. package/dist/components-csr/p-CxhZdOPw.js +2 -0
  469. package/dist/components-csr/p-CxhZdOPw.js.map +1 -0
  470. package/dist/{components/p-Ch2-tttM.js → components-csr/p-DMQ-6aj8.js} +2 -2
  471. package/dist/components-csr/p-DWxN44zD.js +2 -0
  472. package/dist/components-csr/p-DWxN44zD.js.map +1 -0
  473. package/dist/components-csr/p-DYBUr7K_.js +2 -0
  474. package/dist/components-csr/p-DYBUr7K_.js.map +1 -0
  475. package/dist/{components/p-e2HRV63Y.js → components-csr/p-DfcpeJAu.js} +2 -2
  476. package/dist/{components/p-Dp-w93ot.js → components-csr/p-DjKPc5EU.js} +2 -2
  477. package/dist/components-csr/p-DvOKnoqK.js.map +1 -0
  478. package/dist/components-csr/p-DzPKu-Ma.js.map +1 -0
  479. package/dist/{components/p-UdGDg2oJ.js → components-csr/p-If0JHsYV.js} +2 -2
  480. package/dist/components-csr/p-If0JHsYV.js.map +1 -0
  481. package/dist/components-csr/p-RLxbNqRv.js.map +1 -0
  482. package/dist/{components/p-6wZSqm_2.js → components-csr/p-R_guULjT.js} +2 -2
  483. package/dist/components-csr/p-bSpXNc5J.js +2 -0
  484. package/dist/components-csr/p-bSpXNc5J.js.map +1 -0
  485. package/dist/{components/p-Ddiw2Kjw.js → components-csr/p-uSMrgqAy.js} +2 -2
  486. package/dist/components-csr/package.json +3 -0
  487. package/dist/esm/{a11y-C6CRqodW.js → a11y-BckJ95d7.js} +3 -3
  488. package/dist/esm/{a11y-C6CRqodW.js.map → a11y-BckJ95d7.js.map} +1 -1
  489. package/dist/esm/app-globals-DQuL1Twl.js +6 -0
  490. package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
  491. package/dist/esm/{bar-chart-ZZrajEkM.js → bar-chart-BuTyuCbt.js} +4 -4
  492. package/dist/esm/{bar-chart-ZZrajEkM.js.map → bar-chart-BuTyuCbt.js.map} +1 -1
  493. package/dist/esm/{chart-32olae06.js → chart-ByIhkqsG.js} +4 -4
  494. package/dist/esm/{chart-32olae06.js.map → chart-ByIhkqsG.js.map} +1 -1
  495. package/dist/esm/engine.wasm-CfBPnYW7.js +10 -0
  496. package/dist/esm/engine.wasm-CfBPnYW7.js.map +1 -0
  497. package/dist/esm/{hit-test-DHldf5Lm.js → hit-test-c_hI-yCX.js} +3 -3
  498. package/dist/esm/{hit-test-DHldf5Lm.js.map → hit-test-c_hI-yCX.js.map} +1 -1
  499. package/dist/esm/{index-DTaX19_O.js → index-WmvQpZnM.js} +5 -15
  500. package/dist/esm/index-WmvQpZnM.js.map +1 -0
  501. package/dist/esm/lazy-loading-indicator-BWFcjJiK.js +67 -0
  502. package/dist/esm/lazy-loading-indicator-BWFcjJiK.js.map +1 -0
  503. package/dist/esm/loader.js +4 -3
  504. package/dist/esm/loader.js.map +1 -1
  505. package/dist/esm/md-accordion-item.entry.js +4 -4
  506. package/dist/esm/md-accordion.entry.js +1 -1
  507. package/dist/esm/md-app-bar.entry.js +2 -2
  508. package/dist/esm/md-area-chart.entry.js +7 -7
  509. package/dist/esm/md-autocomplete.entry.js +6 -5
  510. package/dist/esm/md-autocomplete.entry.js.map +1 -1
  511. package/dist/esm/md-avatar_2.entry.js +4 -4
  512. package/dist/esm/md-badge.entry.js +3 -3
  513. package/dist/esm/md-bar-chart.entry.js +7 -7
  514. package/dist/esm/md-bottom-sheet.entry.js +5 -5
  515. package/dist/esm/md-breadcrumb-item.entry.js +2 -2
  516. package/dist/esm/md-breadcrumbs.entry.js +3 -3
  517. package/dist/esm/md-button-group.entry.js +3 -3
  518. package/dist/esm/{md-button_7.entry.js → md-button_6.entry.js} +16 -40
  519. package/dist/esm/md-button_6.entry.js.map +1 -0
  520. package/dist/esm/md-checkbox.entry.js +3 -3
  521. package/dist/esm/md-chip.entry.js +3 -3
  522. package/dist/esm/md-color-picker.entry.js +1 -1
  523. package/dist/esm/md-date-picker.entry.js +2 -2
  524. package/dist/esm/md-dialog.entry.js +3 -3
  525. package/dist/esm/md-divider.entry.js +3 -3
  526. package/dist/esm/md-fab-menu-item.entry.js +3 -3
  527. package/dist/esm/md-fab-menu.entry.js +3 -3
  528. package/dist/esm/md-fab.entry.js +3 -3
  529. package/dist/esm/md-line-chart.entry.js +7 -7
  530. package/dist/esm/md-list-item.entry.js +5 -5
  531. package/dist/esm/md-list.entry.js +4 -4
  532. package/dist/esm/md-loading-indicator-Bf-Pt29l.js +31 -0
  533. package/dist/esm/md-loading-indicator-Bf-Pt29l.js.map +1 -0
  534. package/dist/esm/md-loading-indicator.entry.js +5 -0
  535. package/dist/esm/md-loading-indicator.entry.js.map +1 -0
  536. package/dist/esm/md-menu-item-group.entry.js +1 -1
  537. package/dist/esm/md-menu_2.entry.js +6 -6
  538. package/dist/esm/md-meter.entry.js +1 -1
  539. package/dist/esm/md-multi-select.entry.js +7 -6
  540. package/dist/esm/md-multi-select.entry.js.map +1 -1
  541. package/dist/esm/md-navigation-bar.entry.js +2 -2
  542. package/dist/esm/md-navigation-rail-tab.entry.js +2 -2
  543. package/dist/esm/md-navigation-rail.entry.js +1 -1
  544. package/dist/esm/md-navigation-tab.entry.js +4 -4
  545. package/dist/esm/md-number-field.entry.js +3 -3
  546. package/dist/esm/md-organization-chart.entry.js +3 -3
  547. package/dist/esm/md-otp-field.entry.js +4 -4
  548. package/dist/esm/md-pie-chart.entry.js +3 -3
  549. package/dist/esm/md-progress-indicator.entry.js +1 -1
  550. package/dist/esm/md-rating.entry.js +1 -1
  551. package/dist/esm/md-search.entry.js +8 -7
  552. package/dist/esm/md-search.entry.js.map +1 -1
  553. package/dist/esm/md-segmented-button-set.entry.js +1 -1
  554. package/dist/esm/md-segmented-button.entry.js +1 -1
  555. package/dist/esm/md-select-option.entry.js +2 -2
  556. package/dist/esm/md-select.entry.js +7 -6
  557. package/dist/esm/md-select.entry.js.map +1 -1
  558. package/dist/esm/md-side-sheet.entry.js +1 -1
  559. package/dist/esm/md-skeleton.entry.js +1 -1
  560. package/dist/esm/md-slider.entry.js +3 -3
  561. package/dist/esm/md-sparkline.entry.js +7 -7
  562. package/dist/esm/md-split-button.entry.js +1 -1
  563. package/dist/esm/md-status-dot.entry.js +2 -2
  564. package/dist/esm/md-step.entry.js +1 -1
  565. package/dist/esm/md-stepper.entry.js +1 -1
  566. package/dist/esm/md-sub-menu-item.entry.js +1 -1
  567. package/dist/esm/md-switch.entry.js +1 -1
  568. package/dist/esm/md-tab-panel.entry.js +1 -1
  569. package/dist/esm/md-tab-panels.entry.js +1 -1
  570. package/dist/esm/md-tab.entry.js +1 -1
  571. package/dist/esm/md-table-body.entry.js +1 -1
  572. package/dist/esm/md-table-cell.entry.js +1 -1
  573. package/dist/esm/md-table-container.entry.js +1 -1
  574. package/dist/esm/md-table-expand-toggle.entry.js +1 -1
  575. package/dist/esm/md-table-foot.entry.js +1 -1
  576. package/dist/esm/md-table-head.entry.js +1 -1
  577. package/dist/esm/md-table-pagination.entry.js +1 -1
  578. package/dist/esm/md-table-row.entry.js +1 -1
  579. package/dist/esm/md-table-sort-label.entry.js +1 -1
  580. package/dist/esm/md-table-toolbar.entry.js +1 -1
  581. package/dist/esm/md-table.entry.js +4 -4
  582. package/dist/esm/md-tabs.entry.js +1 -1
  583. package/dist/esm/md-text-field.entry.js +8 -8
  584. package/dist/esm/md-time-picker.entry.js +2 -2
  585. package/dist/esm/md-toolbar.entry.js +1 -1
  586. package/dist/esm/md-transfer-list.entry.js +2 -2
  587. package/dist/esm/md3.js +4 -3
  588. package/dist/esm/md3.js.map +1 -1
  589. package/dist/esm/{rtl-DvOKnoqK.js → rtl-CVFH1DkU.js} +3 -3
  590. package/dist/esm/{rtl-DvOKnoqK.js.map → rtl-CVFH1DkU.js.map} +1 -1
  591. package/dist/esm/{url-BjYKc1Ge.js → url-BdEoSBtL.js} +3 -3
  592. package/dist/esm/{url-BjYKc1Ge.js.map → url-BdEoSBtL.js.map} +1 -1
  593. package/dist/esm/{virtual-select-controller-BEWIC0pC.js → virtual-select-controller-CR60w6DO.js} +10 -9
  594. package/dist/esm/virtual-select-controller-CR60w6DO.js.map +1 -0
  595. package/dist/md3/md3.css +1 -1
  596. package/dist/md3/md3.esm.js +1 -1
  597. package/dist/md3/md3.esm.js.map +1 -1
  598. package/dist/md3/p-08f1c469.entry.js +2 -0
  599. package/dist/md3/{p-4d82132d.entry.js.map → p-08f1c469.entry.js.map} +1 -1
  600. package/dist/md3/{p-9ddbf247.entry.js → p-108f89d7.entry.js} +2 -2
  601. package/dist/md3/p-1112bffc.entry.js +2 -0
  602. package/dist/md3/{p-cf07e761.entry.js.map → p-1112bffc.entry.js.map} +1 -1
  603. package/dist/md3/{p-c6a12344.entry.js → p-114c270b.entry.js} +2 -2
  604. package/dist/md3/p-1835fe36.entry.js +2 -0
  605. package/dist/md3/{p-a3308c40.entry.js.map → p-1835fe36.entry.js.map} +1 -1
  606. package/dist/md3/{p-396089fd.entry.js → p-1edb5a0d.entry.js} +2 -2
  607. package/dist/md3/p-2ba2db3b.entry.js +2 -0
  608. package/dist/md3/{p-6b2871a0.entry.js.map → p-2ba2db3b.entry.js.map} +1 -1
  609. package/dist/md3/p-3508d0e0.entry.js +2 -0
  610. package/dist/md3/{p-f31ab454.entry.js.map → p-3508d0e0.entry.js.map} +1 -1
  611. package/dist/md3/{p-b34d385b.entry.js → p-35b05b45.entry.js} +2 -2
  612. package/dist/md3/{p-c2dd8c8c.entry.js → p-38e9a583.entry.js} +2 -2
  613. package/dist/md3/{p-be02624e.entry.js → p-3c0469aa.entry.js} +2 -2
  614. package/dist/md3/p-3f64a27d.entry.js +2 -0
  615. package/dist/md3/{p-fb61868c.entry.js.map → p-3f64a27d.entry.js.map} +1 -1
  616. package/dist/md3/{p-63b8c8d1.entry.js → p-408ee4be.entry.js} +2 -2
  617. package/dist/md3/{p-edb34a6d.entry.js → p-43c708ad.entry.js} +2 -2
  618. package/dist/md3/{p-3015c7e3.entry.js → p-4770b534.entry.js} +2 -2
  619. package/dist/md3/{p-c861d774.entry.js → p-4b7cf934.entry.js} +2 -2
  620. package/dist/md3/{p-2e09a7b7.entry.js → p-4f26bd60.entry.js} +2 -2
  621. package/dist/md3/{p-7b463fbe.entry.js → p-4f2e82cb.entry.js} +2 -2
  622. package/dist/md3/{p-be412e3f.entry.js → p-501bf161.entry.js} +2 -2
  623. package/dist/md3/{p-c063c823.entry.js → p-56c7c570.entry.js} +2 -2
  624. package/dist/md3/{p-2e9503d7.entry.js → p-56ca0c3c.entry.js} +2 -2
  625. package/dist/md3/{p-ac8762e5.entry.js → p-5b63149a.entry.js} +2 -2
  626. package/dist/md3/{p-c5af701b.entry.js → p-5f668b0a.entry.js} +2 -2
  627. package/dist/md3/p-6237ddac.entry.js +2 -0
  628. package/dist/md3/{p-e7dc5a32.entry.js.map → p-6237ddac.entry.js.map} +1 -1
  629. package/dist/md3/{p-8eb0b6a4.entry.js → p-6d65fc6a.entry.js} +2 -2
  630. package/dist/md3/{p-e3124e1e.entry.js → p-707b6d7c.entry.js} +2 -2
  631. package/dist/md3/{p-a5fee424.entry.js → p-71f1660b.entry.js} +2 -2
  632. package/dist/md3/{p-1a8ec5bc.entry.js → p-7501170f.entry.js} +2 -2
  633. package/dist/md3/p-7c8842bf.entry.js +2 -0
  634. package/dist/md3/{p-ba2ebde1.entry.js.map → p-7c8842bf.entry.js.map} +1 -1
  635. package/dist/md3/{p-4e3d6e40.entry.js → p-7d1686a7.entry.js} +2 -2
  636. package/dist/md3/p-7e7f0e45.entry.js +2 -0
  637. package/dist/md3/p-7e7f0e45.entry.js.map +1 -0
  638. package/dist/md3/p-80379565.entry.js +2 -0
  639. package/dist/md3/{p-6c44cf13.entry.js.map → p-80379565.entry.js.map} +1 -1
  640. package/dist/md3/p-830724e4.entry.js +2 -0
  641. package/dist/md3/p-830724e4.entry.js.map +1 -0
  642. package/dist/md3/{p-4dda4cb0.entry.js → p-845ca9cc.entry.js} +2 -2
  643. package/dist/md3/{p-77a01bcc.entry.js → p-87f88d62.entry.js} +2 -2
  644. package/dist/md3/{p-5b74694e.entry.js → p-89d47130.entry.js} +2 -2
  645. package/dist/md3/p-8a6fed13.entry.js +2 -0
  646. package/dist/md3/{p-a803da99.entry.js.map → p-8a6fed13.entry.js.map} +1 -1
  647. package/dist/md3/p-8a7e0297.entry.js +2 -0
  648. package/dist/md3/p-8a7e0297.entry.js.map +1 -0
  649. package/dist/md3/{p-b0431a5c.entry.js → p-8bdcda53.entry.js} +2 -2
  650. package/dist/md3/{p-c10a33c2.entry.js → p-8e7df348.entry.js} +2 -2
  651. package/dist/md3/p-9003a7d4.entry.js +2 -0
  652. package/dist/md3/p-9003a7d4.entry.js.map +1 -0
  653. package/dist/md3/{p-05ae91b6.entry.js → p-90ccf4c3.entry.js} +2 -2
  654. package/dist/md3/p-BdEoSBtL.js +2 -0
  655. package/dist/md3/{p-BjYKc1Ge.js.map → p-BdEoSBtL.js.map} +1 -1
  656. package/dist/md3/p-Bz-JaJcA.js +2 -0
  657. package/dist/md3/p-Bz-JaJcA.js.map +1 -0
  658. package/dist/md3/p-CGqeEMjY.js +2 -0
  659. package/dist/md3/{p-DzPKu-Ma.js.map → p-CGqeEMjY.js.map} +1 -1
  660. package/dist/md3/p-CVFH1DkU.js +2 -0
  661. package/dist/md3/{p-DvOKnoqK.js.map → p-CVFH1DkU.js.map} +1 -1
  662. package/dist/md3/p-Cch92tDM.js +2 -0
  663. package/dist/md3/{p-RLxbNqRv.js.map → p-Cch92tDM.js.map} +1 -1
  664. package/dist/md3/p-CfBPnYW7.js +2 -0
  665. package/dist/md3/p-CfBPnYW7.js.map +1 -0
  666. package/dist/md3/p-D17cVKxS.js +2 -0
  667. package/dist/md3/p-D17cVKxS.js.map +1 -0
  668. package/dist/md3/p-DGtztV3K.js +2 -0
  669. package/dist/md3/{p-Bx6--dQF.js.map → p-DGtztV3K.js.map} +1 -1
  670. package/dist/md3/p-DQuL1Twl.js +2 -0
  671. package/dist/md3/p-DQuL1Twl.js.map +1 -0
  672. package/dist/md3/p-DnKDoE8K.js +2 -0
  673. package/dist/md3/p-DnKDoE8K.js.map +1 -0
  674. package/dist/md3/p-WmvQpZnM.js +3 -0
  675. package/dist/md3/p-WmvQpZnM.js.map +1 -0
  676. package/dist/md3/p-a3623653.entry.js +2 -0
  677. package/dist/md3/{p-19ee9c33.entry.js.map → p-a3623653.entry.js.map} +1 -1
  678. package/dist/md3/{p-da4e27d4.entry.js → p-a4d4cfed.entry.js} +2 -2
  679. package/dist/md3/{p-5394254f.entry.js → p-a976498b.entry.js} +2 -2
  680. package/dist/md3/{p-6038b907.entry.js → p-ab568d1c.entry.js} +2 -2
  681. package/dist/md3/{p-bf7842f8.entry.js → p-adf8a415.entry.js} +2 -2
  682. package/dist/md3/p-ae30e899.entry.js +2 -0
  683. package/dist/md3/p-ae30e899.entry.js.map +1 -0
  684. package/dist/md3/{p-45280bf4.entry.js → p-b2d88292.entry.js} +2 -2
  685. package/dist/md3/{p-796f79f8.entry.js → p-b3b5247b.entry.js} +2 -2
  686. package/dist/md3/{p-5b799707.entry.js → p-b4266f6b.entry.js} +2 -2
  687. package/dist/md3/p-b54bbf88.entry.js +2 -0
  688. package/dist/md3/p-b54bbf88.entry.js.map +1 -0
  689. package/dist/md3/{p-c00f7514.entry.js → p-ba011453.entry.js} +2 -2
  690. package/dist/md3/{p-6ba63c73.entry.js → p-bc24f0c9.entry.js} +2 -2
  691. package/dist/md3/{p-0c2e824d.entry.js → p-c20fbb9e.entry.js} +2 -2
  692. package/dist/md3/{p-fc0b325d.entry.js → p-c2944c87.entry.js} +2 -2
  693. package/dist/md3/{p-4e45b2ff.entry.js → p-c58c68d0.entry.js} +2 -2
  694. package/dist/md3/p-cc6e8afd.entry.js +2 -0
  695. package/dist/md3/{p-72457a85.entry.js.map → p-cc6e8afd.entry.js.map} +1 -1
  696. package/dist/md3/{p-0f764a1e.entry.js → p-d2e39c6e.entry.js} +2 -2
  697. package/dist/md3/{p-50555bb7.entry.js → p-d8885f53.entry.js} +2 -2
  698. package/dist/md3/{p-c1ca6f6c.entry.js → p-db6fb4e1.entry.js} +2 -2
  699. package/dist/md3/{p-81843ff7.entry.js → p-dcba2857.entry.js} +2 -2
  700. package/dist/md3/{p-65195996.entry.js → p-e357e8ac.entry.js} +2 -2
  701. package/dist/md3/{p-39cb7c24.entry.js → p-e5c6795e.entry.js} +2 -2
  702. package/dist/md3/p-e871663b.entry.js +2 -0
  703. package/dist/md3/{p-aaec2698.entry.js.map → p-e871663b.entry.js.map} +1 -1
  704. package/dist/md3/p-f1b69181.entry.js +2 -0
  705. package/dist/md3/{p-a986fd24.entry.js.map → p-f1b69181.entry.js.map} +1 -1
  706. package/dist/md3/p-f297d786.entry.js +2 -0
  707. package/dist/md3/{p-3cce1de3.entry.js.map → p-f297d786.entry.js.map} +1 -1
  708. package/dist/md3/{p-e6d7f0ff.entry.js → p-f403ad20.entry.js} +2 -2
  709. package/dist/md3/p-f5399b73.entry.js +2 -0
  710. package/dist/md3/{p-04e97f5d.entry.js.map → p-f5399b73.entry.js.map} +1 -1
  711. package/dist/md3/{p-708a9313.entry.js → p-f5fd9a0b.entry.js} +2 -2
  712. package/dist/md3/{p-aa0e7d4d.entry.js → p-f71af38f.entry.js} +2 -2
  713. package/dist/md3/{p-757e3aaf.entry.js → p-fac6da4c.entry.js} +2 -2
  714. package/dist/md3/{p-134b670a.entry.js → p-fc864f96.entry.js} +2 -2
  715. package/dist/md3/{p-32bdd439.entry.js → p-fd686966.entry.js} +2 -2
  716. package/dist/md3/p-nhfFYWzy.js +2 -0
  717. package/dist/md3/{p-C_ogF68H.js.map → p-nhfFYWzy.js.map} +1 -1
  718. package/dist/types/utils/lazy-loading-indicator.d.ts +7 -0
  719. package/dist/types/wasm/engine-abi.d.ts +14 -0
  720. package/hydrate/index.js +191 -113
  721. package/hydrate/index.mjs +191 -113
  722. package/package.json +30 -5
  723. package/dist/cjs/index-DlQ_5_Mv.js.map +0 -1
  724. package/dist/cjs/md-button_7.cjs.entry.js.map +0 -1
  725. package/dist/cjs/virtual-select-controller-CqriaZgm.js.map +0 -1
  726. package/dist/components/p-BEWIC0pC.js +0 -2
  727. package/dist/components/p-BEWIC0pC.js.map +0 -1
  728. package/dist/components/p-DXXUoRSH.js.map +0 -1
  729. package/dist/components/p-MWBNn6Lj.js +0 -2
  730. package/dist/components/p-MWBNn6Lj.js.map +0 -1
  731. package/dist/components/p-UdGDg2oJ.js.map +0 -1
  732. package/dist/esm/index-DTaX19_O.js.map +0 -1
  733. package/dist/esm/md-button_7.entry.js.map +0 -1
  734. package/dist/esm/virtual-select-controller-BEWIC0pC.js.map +0 -1
  735. package/dist/md3/p-04e97f5d.entry.js +0 -2
  736. package/dist/md3/p-19ee9c33.entry.js +0 -2
  737. package/dist/md3/p-21772851.entry.js +0 -2
  738. package/dist/md3/p-21772851.entry.js.map +0 -1
  739. package/dist/md3/p-3cce1de3.entry.js +0 -2
  740. package/dist/md3/p-47af9819.entry.js +0 -2
  741. package/dist/md3/p-47af9819.entry.js.map +0 -1
  742. package/dist/md3/p-4d82132d.entry.js +0 -2
  743. package/dist/md3/p-6b2871a0.entry.js +0 -2
  744. package/dist/md3/p-6c44cf13.entry.js +0 -2
  745. package/dist/md3/p-72457a85.entry.js +0 -2
  746. package/dist/md3/p-BEWIC0pC.js +0 -2
  747. package/dist/md3/p-BEWIC0pC.js.map +0 -1
  748. package/dist/md3/p-DTaX19_O.js +0 -3
  749. package/dist/md3/p-DTaX19_O.js.map +0 -1
  750. package/dist/md3/p-a3308c40.entry.js +0 -2
  751. package/dist/md3/p-a7ffb779.entry.js +0 -2
  752. package/dist/md3/p-a7ffb779.entry.js.map +0 -1
  753. package/dist/md3/p-a803da99.entry.js +0 -2
  754. package/dist/md3/p-a986fd24.entry.js +0 -2
  755. package/dist/md3/p-aaec2698.entry.js +0 -2
  756. package/dist/md3/p-ac35ac5f.entry.js +0 -2
  757. package/dist/md3/p-ac35ac5f.entry.js.map +0 -1
  758. package/dist/md3/p-b4631a55.entry.js +0 -2
  759. package/dist/md3/p-b4631a55.entry.js.map +0 -1
  760. package/dist/md3/p-ba2ebde1.entry.js +0 -2
  761. package/dist/md3/p-cf07e761.entry.js +0 -2
  762. package/dist/md3/p-e7dc5a32.entry.js +0 -2
  763. package/dist/md3/p-f31ab454.entry.js +0 -2
  764. package/dist/md3/p-fb61868c.entry.js +0 -2
  765. /package/dist/{components/p-uTEkf0sE.js.map → components-csr/p-BEmwDSzw.js.map} +0 -0
  766. /package/dist/{components/p-C8EP4S21.js.map → components-csr/p-BQKzjYcY.js.map} +0 -0
  767. /package/dist/{components/p-BwXpiUsu.js.map → components-csr/p-BWMwewtY.js.map} +0 -0
  768. /package/dist/{components/p-B0Opn6dK.js.map → components-csr/p-Bkt_X-6v.js.map} +0 -0
  769. /package/dist/{md3 → components-csr}/p-Bx6--dQF.js +0 -0
  770. /package/dist/{components/p-stybaFzj.js.map → components-csr/p-C3vB0Hd9.js.map} +0 -0
  771. /package/dist/{components/p-B3MWYEEJ.js.map → components-csr/p-CF7mq5T7.js.map} +0 -0
  772. /package/dist/{components/p-7fN_yCXW.js.map → components-csr/p-CVMM-tdC.js.map} +0 -0
  773. /package/dist/{md3 → components-csr}/p-C_ogF68H.js +0 -0
  774. /package/dist/{components/p-Ch2-tttM.js.map → components-csr/p-DMQ-6aj8.js.map} +0 -0
  775. /package/dist/{components/p-e2HRV63Y.js.map → components-csr/p-DfcpeJAu.js.map} +0 -0
  776. /package/dist/{components/p-Dp-w93ot.js.map → components-csr/p-DjKPc5EU.js.map} +0 -0
  777. /package/dist/{md3 → components-csr}/p-DvOKnoqK.js +0 -0
  778. /package/dist/{md3 → components-csr}/p-DzPKu-Ma.js +0 -0
  779. /package/dist/{md3 → components-csr}/p-RLxbNqRv.js +0 -0
  780. /package/dist/{components/p-6wZSqm_2.js.map → components-csr/p-R_guULjT.js.map} +0 -0
  781. /package/dist/{components/p-Ddiw2Kjw.js.map → components-csr/p-uSMrgqAy.js.map} +0 -0
  782. /package/dist/md3/{p-9ddbf247.entry.js.map → p-108f89d7.entry.js.map} +0 -0
  783. /package/dist/md3/{p-c6a12344.entry.js.map → p-114c270b.entry.js.map} +0 -0
  784. /package/dist/md3/{p-396089fd.entry.js.map → p-1edb5a0d.entry.js.map} +0 -0
  785. /package/dist/md3/{p-b34d385b.entry.js.map → p-35b05b45.entry.js.map} +0 -0
  786. /package/dist/md3/{p-c2dd8c8c.entry.js.map → p-38e9a583.entry.js.map} +0 -0
  787. /package/dist/md3/{p-be02624e.entry.js.map → p-3c0469aa.entry.js.map} +0 -0
  788. /package/dist/md3/{p-63b8c8d1.entry.js.map → p-408ee4be.entry.js.map} +0 -0
  789. /package/dist/md3/{p-edb34a6d.entry.js.map → p-43c708ad.entry.js.map} +0 -0
  790. /package/dist/md3/{p-3015c7e3.entry.js.map → p-4770b534.entry.js.map} +0 -0
  791. /package/dist/md3/{p-c861d774.entry.js.map → p-4b7cf934.entry.js.map} +0 -0
  792. /package/dist/md3/{p-2e09a7b7.entry.js.map → p-4f26bd60.entry.js.map} +0 -0
  793. /package/dist/md3/{p-7b463fbe.entry.js.map → p-4f2e82cb.entry.js.map} +0 -0
  794. /package/dist/md3/{p-be412e3f.entry.js.map → p-501bf161.entry.js.map} +0 -0
  795. /package/dist/md3/{p-c063c823.entry.js.map → p-56c7c570.entry.js.map} +0 -0
  796. /package/dist/md3/{p-2e9503d7.entry.js.map → p-56ca0c3c.entry.js.map} +0 -0
  797. /package/dist/md3/{p-ac8762e5.entry.js.map → p-5b63149a.entry.js.map} +0 -0
  798. /package/dist/md3/{p-c5af701b.entry.js.map → p-5f668b0a.entry.js.map} +0 -0
  799. /package/dist/md3/{p-8eb0b6a4.entry.js.map → p-6d65fc6a.entry.js.map} +0 -0
  800. /package/dist/md3/{p-e3124e1e.entry.js.map → p-707b6d7c.entry.js.map} +0 -0
  801. /package/dist/md3/{p-a5fee424.entry.js.map → p-71f1660b.entry.js.map} +0 -0
  802. /package/dist/md3/{p-1a8ec5bc.entry.js.map → p-7501170f.entry.js.map} +0 -0
  803. /package/dist/md3/{p-4e3d6e40.entry.js.map → p-7d1686a7.entry.js.map} +0 -0
  804. /package/dist/md3/{p-4dda4cb0.entry.js.map → p-845ca9cc.entry.js.map} +0 -0
  805. /package/dist/md3/{p-77a01bcc.entry.js.map → p-87f88d62.entry.js.map} +0 -0
  806. /package/dist/md3/{p-5b74694e.entry.js.map → p-89d47130.entry.js.map} +0 -0
  807. /package/dist/md3/{p-b0431a5c.entry.js.map → p-8bdcda53.entry.js.map} +0 -0
  808. /package/dist/md3/{p-c10a33c2.entry.js.map → p-8e7df348.entry.js.map} +0 -0
  809. /package/dist/md3/{p-05ae91b6.entry.js.map → p-90ccf4c3.entry.js.map} +0 -0
  810. /package/dist/md3/{p-da4e27d4.entry.js.map → p-a4d4cfed.entry.js.map} +0 -0
  811. /package/dist/md3/{p-5394254f.entry.js.map → p-a976498b.entry.js.map} +0 -0
  812. /package/dist/md3/{p-6038b907.entry.js.map → p-ab568d1c.entry.js.map} +0 -0
  813. /package/dist/md3/{p-bf7842f8.entry.js.map → p-adf8a415.entry.js.map} +0 -0
  814. /package/dist/md3/{p-45280bf4.entry.js.map → p-b2d88292.entry.js.map} +0 -0
  815. /package/dist/md3/{p-796f79f8.entry.js.map → p-b3b5247b.entry.js.map} +0 -0
  816. /package/dist/md3/{p-5b799707.entry.js.map → p-b4266f6b.entry.js.map} +0 -0
  817. /package/dist/md3/{p-c00f7514.entry.js.map → p-ba011453.entry.js.map} +0 -0
  818. /package/dist/md3/{p-6ba63c73.entry.js.map → p-bc24f0c9.entry.js.map} +0 -0
  819. /package/dist/md3/{p-0c2e824d.entry.js.map → p-c20fbb9e.entry.js.map} +0 -0
  820. /package/dist/md3/{p-fc0b325d.entry.js.map → p-c2944c87.entry.js.map} +0 -0
  821. /package/dist/md3/{p-4e45b2ff.entry.js.map → p-c58c68d0.entry.js.map} +0 -0
  822. /package/dist/md3/{p-0f764a1e.entry.js.map → p-d2e39c6e.entry.js.map} +0 -0
  823. /package/dist/md3/{p-50555bb7.entry.js.map → p-d8885f53.entry.js.map} +0 -0
  824. /package/dist/md3/{p-c1ca6f6c.entry.js.map → p-db6fb4e1.entry.js.map} +0 -0
  825. /package/dist/md3/{p-81843ff7.entry.js.map → p-dcba2857.entry.js.map} +0 -0
  826. /package/dist/md3/{p-65195996.entry.js.map → p-e357e8ac.entry.js.map} +0 -0
  827. /package/dist/md3/{p-39cb7c24.entry.js.map → p-e5c6795e.entry.js.map} +0 -0
  828. /package/dist/md3/{p-e6d7f0ff.entry.js.map → p-f403ad20.entry.js.map} +0 -0
  829. /package/dist/md3/{p-708a9313.entry.js.map → p-f5fd9a0b.entry.js.map} +0 -0
  830. /package/dist/md3/{p-aa0e7d4d.entry.js.map → p-f71af38f.entry.js.map} +0 -0
  831. /package/dist/md3/{p-757e3aaf.entry.js.map → p-fac6da4c.entry.js.map} +0 -0
  832. /package/dist/md3/{p-134b670a.entry.js.map → p-fc864f96.entry.js.map} +0 -0
  833. /package/dist/md3/{p-32bdd439.entry.js.map → p-fd686966.entry.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isDomNode","value","nodeType","nodeName","parseHexOrRgb","s","startsWith","h","slice","length","split","map","c","join","r","parseInt","g","b","a","Number","isNaN","m","match","parts","p","trim","chan","v","endsWith","parseFloat","normCtx","normalizeColor","css","undefined","document","createElement","getContext","fillStyle","resolved","toLowerCase","withAlpha","factor","parseColor","alpha","Math","round","direct","norm","parsed","onColorFor","fill","mixColor","target","amount","t","max","min","ch","i","DEFAULT_ROLE_CYCLE","TOKEN_PROP","primary","secondary","tertiary","error","success","warning","info","FALLBACKS","resolveMdColor","host","role","computed","cs","getComputedStyle","val","getPropertyValue","harmonicPalette","anchors","n","contrast","usable","filter","Boolean","Array","from","ramp","push","lo","floor","hi","f","dark","light","resolveSeriesColor","color","fallback","isCssColor","console","warn","Object","keys","CSS","supports","resolveComputedColor","test","doc","ownerDocument","parent","shadowRoot","probe","style","cssText","appendChild","out","remove","resolveAxisBands","bands","to","label","labelAlign","labelColor","fontFamilyOf","font","readVar","name","readNumberVar","raw","isFinite","pickEasing","rawCubicBezier","d","abs","readMdChartTheme","palette","motionDuration","easingRaw","reducedMotion","window","matchMedia","matches","forcedColors","background","textColor","textColorMuted","gridColor","override","axisLineColor","surface","tooltipSurface","tooltipTextColor","tooltipBorderColor","tooltipShadow","tooltipRadius","fontFamily","labelSize","titleSize","motionEasing","pickPaletteColor","seriesIndex","defaultValueFormatter","locale","l","Date","toLocaleString","String","toNumeric","scale","getTime","asNum","asDate","parse","makeLinearScale","domain","size","type","span","bandwidth","invert","px","makeLogScale","positiveMax","safeMin","MIN_VALUE","log10","pow","makeCategoryScale","count","alignWithLabel","offset","DEFAULT_BREAK_GAP","normalizeBreaks","breaks","clipped","gap","sort","merged","last","openTopSection","ranges","belowFrom","belowRange","niceLinearTicks","outlierStep","range","newTo","autoBreaks","values","opts","minGap","maxBreaks","sorted","Set","gaps","sizes","median","chosen","makeBrokenScale","sizing","base","cuts","fromPx","toPx","reduce","sum","spans","cursor","totalSpan","sections","width","outCursor","placed","sec","start","outStart","scaleBreaks","end","resolveAxisBreaks","auto","isArray","explicit","found","SECTION_MIN_TICKS","sectionedTicks","ticksFor","logTicks","timeTicks","per","sectionTicks","ticks","inBreak","some","step","niceNum","niceMin","niceMax","ceil","maxTicks","exp","frac","nice","e","minMs","maxMs","S","M","H","D","steps","ideal","idx","findIndex","finer","computeDomain","isLog","dataLo","Infinity","dataHi","hasFinite","loExplicit","hiExplicit","includeZero","MARKER_ANGLES","square","diamond","triangle","markerPolygon","symbol","cx","cy","angles","deg","PI","x","cos","y","sin","CURVE_SAMPLES","DECIMATE_PER_PX","decimateMinMax","points","plotWidth","col","firstI","lastI","minI","maxI","flush","picked","prev","clampToRect","w","x2","y2","dirty","interpolate","curve","stepPoints","monotone","catmullRom","pts","mode","mx","p0","p1","p2","p3","t2","t3","dx","slope","w1","w2","h00","h10","h01","h11","splitRuns","data","connectNulls","runs","current","index","stackSeries","seriesData","stackKeys","rows","centred","signedTotal","Map","posTotal","negTotal","add","k","set","get","si","posCursor","negCursor","key","stacked","has","pos","neg","hasAnchor","strokes","stroke","marks","showMarks","markIndices","pointSymbols","AXIS_TICK_LEN","approxWidth","text","fontSize","estimateLegendRows","labels","availW","rowW","iw","dashPattern","dash","BREAK_WAVE_LEN","BREAK_WAVE_STEP","BREAK_WAVE_AMP","breakBandSegments","axis","gapLo","gapHi","spanFrom","spanTo","segs","len","mid","amp","at","off","cur","x1","y1","axisLineWithBreaks","along","seg","BAND_LABEL_PAD","buildAxisBands","plot","theme","keyPrefix","rects","horizontal","height","forEach","z","hexToRgba","align","baseline","hex","replace","computeLayout","spec","inverted","computeInvertedLayout","yAxes","computeMultiAxisLayout","series","hidden","xValues","stack","yVals","yDomain","yMin","yMax","yScale","xNums","xScale","xDomain","noBreaks","yFound","compact","yBreaks","xFound","xBreaks","yTickVals","yTickLabels","yTickFormatter","yFormatter","maxYLabelW","yHidden","yHideTicks","subtitleH","subtitle","titleH","title","xLabelH","xHidden","xHideTicks","yAxisLabelW","yLabel","xAxisLabelH","xLabel","legendActive","legend","legendSide","legendAtBottom","legendTopRow","legendRows","legendBandH","legendExtent","legendBandTop","legendBandBottom","legendSideW","seriesLabelW","seriesLabels","markPad","markerRadius","markSize","padTop","padRight","padBottom","padLeft","toPxY","toPxX","bandLabels","axisBands","onY","yBands","onX","xBands","gridlines","axisLines","yGridDash","xGridDash","yAxisDash","yDash","xAxisDash","xDash","py","gridY","gridLineColor","axisTicks","yCuts","yb","xCuts","lines","areas","markers","glyphs","endLabelCands","hoverPoints","baselineY","splitAtBreaks","run","prevSection","pt","xv","section","flatMap","byIndex","endPt","hoverSym","band","low","high","poly","splitAt","dashAfter","lw","lineWidth","area","fo","fillOpacity","basePoints","colorTop","colorBottom","markSet","showDefault","sym","isShapeSymbol","hollow","GLYPH_SIZE","showLabels","above","weight","dy","anchorX","anchorY","visible","unanchored","lastY","bars","refBands","bx1","bx2","bx","bw","radius","dataIndex","texts","tt","titlePlacement","titleAlign","fontWeight","markLines","ml","mv","xPositions","xAnchors","xFormatter","xd","xTicks","tv","gridX","rotate","xLabels","slices","endLabels","legendPosition","axesSpec","axisIndexOf","yAxisIndex","axes","ai","seriesOn","vals","tickVals","tickLabels","formatter","side","position","labelW","hideTicks","titleW","gutterW","tint","hasData","leftAxes","rightAxes","sumGut","arr","lastXText","xOverhang","makeAxisScale","offL","axisX","offR","built","find","gridDash","dir","ax","zeroInDomain","valueFormat","outerX","category","valVals","valDomain","valTicks","valTickLabels","mainDomain","mainTickIdx","_","mainTickLabels","maxMainLabelW","valLabelH","mainAxisTitleW","valAxisTitleH","valScale","mainScale","toPxYval","coord","toPxYidx","baselineX","banded","SHAPE_SYMBOLS","plotX","CHEVRON_MAX_TIP","chevronTipDepth","thickness","traceChevron","ctx","cut","notch","my","arrow","moveTo","lineTo","closePath","traceSlice","fresh","innerR","outerR","startAngle","a0","endAngle","a1","ccw","towards","sweep","lone","insetAt","R","asin","b0","b1","edgeAt","maxByBand","maxBySweep","tan","maxBySweepInner","cornerRadius","n0","n1","beginPath","rim0","arc","back","rhoO","dO","footO","sqrt","c0","c1","donut","rhoI","dI","footI","i0","i1","e0","e1","off0","off1","inner","tip","areaGradient","hasBase","horiz","coords","grad","createLinearGradient","addColorStop","SENTINEL","drawSceneCanvas","scene","clear","clearRect","fillRect","strokeStyle","setLineDash","maxR","rr","roundRect","rect","backed","pill","gapColor","perEnd","capStart","capEnd","lineCap","cap","angle","gradient","rip","ripple","save","clip","globalAlpha","restore","lineJoin","line","LEGEND_SIDE_MAX_FRACTION","ALIGN_X","center","ALIGN_Y","top","middle","bottom","isCorner","includes","renderEndLabels","layer","seen","el","querySelector","dataset","getBoundingClientRect","textContent","transform","left","opacity","children","gone","setTimeout","removeAttribute","renderGlyphs","lbl","renderBarLabels","barLabels","bl","pieces","loX","hiX","loY","hiY","inside","shift","atLowEnd","chipItem","WeakMap","navCallbacks","syncOverlay","cb","rtl","legendLayer","keptNav","getAttribute","child","childNodes","insertBefore","parentNode","visibleLegend","isSide","atBottom","logicalStart","atStart","nav","setAttribute","addEventListener","ev","chip","closest","item","onLegendClick","existing","append","delete","dot","txt","INTRO_MS","clamp01","expressiveEase","easeOutCubic","easeInOutCubic","cubicBezier","by","ay","sampleX","sampleY","slopeX","err","emphasizedDecelerate","easingFor","variant","prefersReducedMotion","isHorizontalBar","growBar","x0","y0","animateSlices","polar","s0","easeScene","baseY","lift","liftPts","radial","barBaseline","DRILL_CROSSFADE","ringSlices","splitScene","outer","pivotIndex","pRaw","outs","ins","pivot","ringStart","total","acc","pivotSpan","rest","w0","order","indexOf","innerStart","innerTotal","over","overAlpha","trimPolylineX","cutX","DRILL_STAGGER","drillScene","tc","maxDi","lag","revealScene","ec","cutY","localE","seriesOrder","staggerReveal","tRaw","rank","cutXFor","globalCut","resolveIntro","animation","animate","requested","animationDuration","ok","duration","fadeGrid","stepAnimation","clearHover","hoverIndex","SURFACE","SHAPE_KEYS","SHAPE_CLIP","buildHoverMarker","outline","popMarker","easing","tooltipCardCss","appendTooltipContent","content","unsafeHtml","innerHTML","renderHover","orient","focusSeries","isNewPoint","animateDots","hp","wantContext","render","present","absent","itemOnly","trigger","format","focused","swatch","marker","dimmed","formattedValue","missing","missingFormatter","context","axisValue","axisLabel","focusedSeriesIndex","custom","positionTooltip","header","row","sw","tw","offsetWidth","th","offsetHeight","overflow","box","roomAbove","plotBottom","watchDevicePixelRatio","onChange","mql","listener","armed","update","dpr","devicePixelRatio","removeEventListener","dispose","mirrorLegend","flipAlign","mirrorScene","W","mPts","mSeg","fromEntries","entries","isRtl","direction","dirListeners","dirObserver","watchDirection","MutationObserver","fn","observe","documentElement","attributes","attributeFilter","subtree","disconnect","ascending","reverse"],"sources":["src/utils/charts/tooltip.ts","src/utils/charts/engine/color.ts","src/utils/charts/theme.ts","src/utils/charts/options.ts","src/utils/charts/engine/scale.ts","src/utils/charts/engine/geometry.ts","src/utils/charts/engine/layout.ts","src/utils/charts/engine/renderer-canvas.ts","src/utils/charts/engine/scene.ts","src/utils/charts/engine/overlay.ts","src/utils/charts/engine/animate.ts","src/utils/charts/engine/hover.ts","src/utils/charts/engine/dpr.ts","src/utils/charts/engine/rtl.ts"],"sourcesContent":["/*\n * Developer-injectable chart tooltips\n * ===========================================================\n * The built-in tooltip is a small MD3 card: the x label, then one\n * row per series (swatch · label · value). `tooltipRenderer` lets a\n * consumer replace that content entirely while the engine keeps\n * owning *placement* — the card is still the `tooltip` CSS part and\n * still flips away from the right/bottom edges.\n *\n * The contract is deliberately plain DOM rather than JSX, so the\n * same callback works from HTML/JS, React, Angular and Vue. A\n * framework renders into a detached node and hands that node back:\n *\n * React createRoot(el).render(<Card …/>); return el;\n * Vue render(h(Card, …), el); return el;\n * Angular createComponent(Card, …); return el;\n * plain JS build it with document.createElement, or return a string\n *\n * SAFETY: a returned string is set as TEXT (`textContent`), never\n * parsed, so untrusted data can't inject markup. Opting into HTML is\n * explicit and named for what it is — `{ unsafeHtml }` — because the\n * string is assigned to `innerHTML` verbatim, with no sanitising. Do\n * not build it from user-controlled data.\n * ===========================================================\n */\n\nimport type { MdChartAxisValue } from './types';\n\n/**\n * One series' state at the hovered x position.\n *\n * Appears in {@link MdChartTooltipContext.series} when the series has a real\n * value there, and in {@link MdChartTooltipContext.missing} when it does not\n * (an authored `null` gap, or no datum at all — see `value`).\n */\nexport interface MdChartTooltipSeries {\n /** Index into the chart's `series` prop (0-based). Stable across hides:\n * hidden series are omitted entirely rather than renumbered. */\n seriesIndex: number;\n /** Series label — what the legend and the default tooltip show. */\n label: string;\n /** The series' resolved CSS colour (MD3 roles are already mapped to a real\n * colour, so this can go straight into a style). */\n color: string;\n /**\n * Raw y value at the hovered x.\n * • `number` — a real reading (entries in `series`)\n * • `null` — the series HAS a datum here and it is null/non-finite:\n * \"measured, no value\"\n * • `undefined` — the series has no datum here at all: it starts later,\n * ends earlier, or was never sampled at this x\n */\n value: number | null | undefined;\n /** `value` run through the chart's `valueFormatter` (or the series' own axis\n * formatter on a multi-axis chart). `''` for a missing value the formatter\n * chose not to name. */\n formattedValue: string;\n /** True for the series the pointer is nearest — the one the chart emphasises\n * while the others dim. At most one entry is focused. */\n focused: boolean;\n /** True for entries in `missing` — i.e. `value` is `null` or `undefined`. */\n missing: boolean;\n}\n\n/** Everything the chart knows about the hovered x position. */\nexport interface MdChartTooltipContext {\n /** Index of the hovered x slot. On a chart whose series carry their own x,\n * this indexes the merged axis (see `utils/charts/xy.ts`), which is also\n * what `axisValue` is read from. */\n dataIndex: number;\n /** Raw x value at that slot — a category string, a number, or a Date. */\n axisValue: MdChartAxisValue | undefined;\n /** `axisValue` run through the x-axis `valueFormatter` — the string the\n * default tooltip uses as its header. */\n axisLabel: string;\n /** Visible series that HAVE a value at this x, in series order. A series with\n * no sample here is absent from this list (it is in `missing` instead). */\n series: MdChartTooltipSeries[];\n /** Visible series with NO value at this x, in series order. Usually empty;\n * populated for partial / irregular data, where it lets you render your own\n * \"no reading\" treatment. */\n missing: MdChartTooltipSeries[];\n /** Index of the emphasised series, or `-1` when nothing is emphasised (a\n * single-series chart never emphasises). */\n focusedSeriesIndex: number;\n}\n\n/**\n * What a {@link MdChartTooltipRenderer} may return.\n * • `Node` — inserted as-is. The safest option, and the one\n * framework renderers produce.\n * • `string` — set as TEXT. Markup in it is shown, not parsed.\n * • `{ unsafeHtml }` — assigned to `innerHTML` with NO sanitising. Only\n * for markup you fully control.\n * • `undefined` — fall back to the built-in tooltip for this x.\n * • `null` — render no tooltip at all for this x.\n */\nexport type MdChartTooltipContent = Node | string | { unsafeHtml: string } | null | undefined;\n\n/**\n * Builds the tooltip body for the hovered x position. Called on every hover\n * frame, so keep it cheap — and note the engine positions whatever you return,\n * so don't set `position` / `left` / `top` on the outermost node.\n *\n * ```ts\n * chart.tooltipRenderer = (ctx) => {\n * const el = document.createElement('div');\n * el.textContent = `${ctx.axisLabel}: ${ctx.series.map((s) => s.formattedValue).join(', ')}`;\n * return el;\n * };\n * ```\n */\nexport type MdChartTooltipRenderer = (context: MdChartTooltipContext) => MdChartTooltipContent;\n\n/**\n * Formats a series' MISSING value at the hovered x — `null` for an authored\n * gap, `undefined` for \"no datum here\". This is the chart's own\n * `valueFormatter`, which the tooltip consults for series it would otherwise\n * omit; returning a non-empty string opts that series into a row.\n */\nexport type MdChartMissingFormatter = (value: null | undefined) => string;\n\n/** Duck-typed `instanceof Node`, so a node built in another document (an\n * iframe, a template, a framework's detached renderer) is still recognised. */\nexport function isDomNode(value: unknown): value is Node {\n return (\n !!value &&\n typeof value === 'object' &&\n typeof (value as Node).nodeType === 'number' &&\n typeof (value as Node).nodeName === 'string'\n );\n}\n","/*\n * Chart engine — CSS colour → RGBA parsing\n * ===========================================================\n * For anywhere a resolved colour string must become numbers. Handles\n * #rgb / #rrggbb / #rrggbbaa and rgb()/rgba() directly (DOM-less,\n * unit-testable), and normalises any other CSS colour (named, hsl(),\n * hwb(), lab(), color-mix(), …) through a shared canvas 2D context\n * so every consumer agrees on a colour. Falls back to mid-grey only\n * when no canvas is available (headless unit-test env).\n * ===========================================================\n */\n\n/** RGBA components in 0..1. */\nexport type Rgba = [number, number, number, number];\n\n/** Parse a #hex / rgb() / rgba() string, or null if it's neither. */\nfunction parseHexOrRgb(s: string): Rgba | null {\n if (s.startsWith('#')) {\n let h = s.slice(1);\n if (h.length === 3) h = h.split('').map((c) => c + c).join('');\n if (h.length === 4) h = h.split('').map((c) => c + c).join('');\n if (h.length < 6) return null;\n const r = parseInt(h.slice(0, 2), 16) / 255;\n const g = parseInt(h.slice(2, 4), 16) / 255;\n const b = parseInt(h.slice(4, 6), 16) / 255;\n const a = h.length >= 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1;\n if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) return null;\n return [r, g, b, a];\n }\n const m = s.match(/rgba?\\(([^)]+)\\)/);\n if (m) {\n const parts = m[1].split(/[,/]/).map((p) => p.trim());\n const chan = (v: string) => (v.endsWith('%') ? (parseFloat(v) / 100) * 255 : parseFloat(v));\n const r = chan(parts[0]) / 255;\n const g = chan(parts[1]) / 255;\n const b = chan(parts[2]) / 255;\n const a = parts[3] != null ? (parts[3].endsWith('%') ? parseFloat(parts[3]) / 100 : parseFloat(parts[3])) : 1;\n return [r, g, b, Number.isNaN(a) ? 1 : a];\n }\n return null;\n}\n\n// A single reusable 2D context that resolves any CSS colour to #hex / rgb().\n// `undefined` = not yet probed; `null` = no canvas (unit-test env).\nlet normCtx: CanvasRenderingContext2D | null | undefined;\n\nfunction normalizeColor(css: string): string | null {\n if (normCtx === undefined) {\n try {\n normCtx = typeof document !== 'undefined' ? document.createElement('canvas').getContext('2d') : null;\n } catch {\n normCtx = null;\n }\n }\n if (!normCtx) return null;\n try {\n // Setting an INVALID colour leaves fillStyle unchanged, so seed a sentinel\n // and treat \"unchanged\" as unparseable.\n normCtx.fillStyle = '#000000';\n normCtx.fillStyle = css;\n const resolved = normCtx.fillStyle;\n if (typeof resolved !== 'string') return null;\n if (resolved === '#000000' && css.trim().toLowerCase() !== 'black' && css.trim() !== '#000000' && css.trim() !== '#000') {\n return null; // invalid input the browser rejected\n }\n return resolved;\n } catch {\n return null;\n }\n}\n\n/** Re-express a colour as an `rgba()` string with its alpha scaled by `factor`\n * (for hover emphasis dimming). Resolves named/hsl/hex/rgb inputs. */\nexport function withAlpha(css: string, factor: number): string {\n const [r, g, b, a] = parseColor(css);\n const alpha = Math.round(a * factor * 1000) / 1000; // avoid float dust in the string\n return `rgba(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(b * 255)}, ${alpha})`;\n}\n\nexport function parseColor(css: string): Rgba {\n const s = css.trim();\n const direct = parseHexOrRgb(s);\n if (direct) return direct;\n // Named / hsl() / lab() / color-mix() etc. — resolve via canvas, then parse\n // the browser-normalised #hex / rgb() form.\n const norm = normalizeColor(s);\n if (norm) {\n const parsed = parseHexOrRgb(norm);\n if (parsed) return parsed;\n }\n // No canvas (headless test) or unparseable — mid-grey so at least something draws.\n return [0.5, 0.5, 0.5, 1];\n}\n\n/**\n * Black or white, whichever reads on top of `fill`.\n *\n * For anything drawn ON a series colour — a value label inside its slice, a\n * press ripple clipped to it. The threshold is above 0.5 because a mid-tone\n * carries white better than black at small sizes.\n */\nexport function onColorFor(fill: string): '#000000' | '#ffffff' {\n const [r, g, b] = parseColor(fill);\n return 0.299 * r + 0.587 * g + 0.114 * b > 0.62 ? '#000000' : '#ffffff';\n}\n\n/**\n * Blend `css` toward `target` by `amount` (0 = unchanged, 1 = fully target).\n *\n * Used to derive a slice's hover states from its own colour: a deeper shade for\n * the raised outer ring, and a faded one for the slices the pointer is NOT on —\n * so a palette change carries into both without anyone restating them.\n */\nexport function mixColor(css: string, target: string, amount: number): string {\n const a = parseColor(css);\n const b = parseColor(target);\n const t = Math.max(0, Math.min(1, amount));\n const ch = (i: number) => Math.round((a[i] + (b[i] - a[i]) * t) * 255);\n // Alpha follows the source: blending toward an opaque target should not make\n // a translucent slice suddenly solid.\n return `rgba(${ch(0)}, ${ch(1)}, ${ch(2)}, ${a[3]})`;\n}\n","/*\n * MD3 → chart theme bridge\n * ===========================================================\n * Reads the MD3 design tokens out of the host element's\n * computed style and shapes them into a small \"MdChartTheme\"\n * object that every chart component uses to colour series,\n * size text, choose easing curves, and pick gridline colours.\n *\n * Tokens are resolved per-host (so each chart reacts to its own\n * CSS variables / theme) and handed to the in-house engine's\n * EngineTheme, which the Canvas renderer draws from.\n * That lets the same `<md-line-chart>` use different colours\n * inside a `[data-theme=\"dark\"]` subtree vs. the default scope\n * without any consumer wiring.\n *\n * Token reads are batched in `readMdChartTheme()` so we only\n * touch `getComputedStyle()` once per re-theme; ECharts then\n * re-uses the cached object across animation frames.\n * ===========================================================\n */\n\nimport type { MdChartAxisBand, MdChartColorRole } from './types';\nimport type { AxisBandSpec } from './engine/layout';\nimport { withAlpha, mixColor } from './engine/color';\n\nexport interface MdChartTheme {\n /** Background of the plot surface. Usually `transparent` so the\n * host's own background bleeds through (cards, panels, etc.). */\n background: string;\n /** Default text colour for tick labels, legend, tooltip body. */\n textColor: string;\n /** Secondary text colour (axis names, tooltip captions). */\n textColorMuted: string;\n /** Major gridline colour. */\n gridColor: string;\n /** Axis line colour. */\n axisLineColor: string;\n /** Surface colour — the interior fill for hollow (open) markers. */\n surface: string;\n /** Tooltip surface colour. */\n tooltipSurface: string;\n /** Tooltip text colour (contrasts with `tooltipSurface`). */\n tooltipTextColor: string;\n /** Tooltip border colour. */\n tooltipBorderColor: string;\n /** Tooltip shadow (CSS box-shadow string). */\n tooltipShadow: string;\n /** Tooltip corner radius (px). */\n tooltipRadius: number;\n /** Default series palette (resolved CSS colour strings). */\n palette: string[];\n /** Font-family stack to use for all chart text. */\n fontFamily: string;\n /** Label-small font-size (px) — tick labels, legend. */\n labelSize: number;\n /** Title-small font-size (px) — axis names, tooltip header. */\n titleSize: number;\n /** Motion duration (ms) for entry / data-update animations. */\n motionDuration: number;\n /** Motion easing — ECharts-compatible name. */\n motionEasing: string;\n /** Whether the user prefers reduced motion. */\n reducedMotion: boolean;\n /** Whether the host is in a high-contrast / forced-colors mode. */\n forcedColors: boolean;\n}\n\n/** Default MD3 palette cycle order — primary leads, then the\n * expressive accents so a 2-series chart reads as a primary\n * vs. an accent rather than two siblings of equal weight. */\nconst DEFAULT_ROLE_CYCLE: MdChartColorRole[] = [\n 'primary',\n 'tertiary',\n 'secondary',\n 'error',\n 'primary-container',\n 'tertiary-container',\n 'secondary-container',\n 'error-container',\n];\n\nconst TOKEN_PROP: Record<MdChartColorRole, string> = {\n primary: '--md-sys-color-primary',\n secondary: '--md-sys-color-secondary',\n tertiary: '--md-sys-color-tertiary',\n error: '--md-sys-color-error',\n 'primary-container': '--md-sys-color-primary-container',\n 'secondary-container': '--md-sys-color-secondary-container',\n 'tertiary-container': '--md-sys-color-tertiary-container',\n 'error-container': '--md-sys-color-error-container',\n 'surface-variant': '--md-sys-color-surface-variant',\n success: '--md-sys-color-success',\n warning: '--md-sys-color-warning',\n info: '--md-sys-color-info',\n 'success-container': '--md-sys-color-success-container',\n 'warning-container': '--md-sys-color-warning-container',\n 'info-container': '--md-sys-color-info-container',\n};\n\nconst FALLBACKS: Record<MdChartColorRole, string> = {\n primary: '#6750A4',\n secondary: '#625B71',\n tertiary: '#7D5260',\n error: '#B3261E',\n 'primary-container': '#EADDFF',\n 'secondary-container': '#E8DEF8',\n 'tertiary-container': '#FFD8E4',\n 'error-container': '#F9DEDC',\n 'surface-variant': '#E7E0EC',\n success: '#2E6B4F',\n warning: '#7A5900',\n info: '#38608F',\n 'success-container': '#B8F0CE',\n 'warning-container': '#FFDF9B',\n 'info-container': '#D3E4FF',\n};\n\n/**\n * Resolve a single colour role to a CSS colour string by reading\n * the matching `--md-sys-color-*` variable off the host.\n * Falls back to the M3 baseline if the token is unset.\n */\nexport function resolveMdColor(\n host: HTMLElement,\n role: MdChartColorRole,\n computed?: CSSStyleDeclaration,\n): string {\n const cs = computed ?? getComputedStyle(host);\n const val = cs.getPropertyValue(TOKEN_PROP[role]).trim();\n return val || FALLBACKS[role];\n}\n\n/**\n * A harmonious categorical palette of `n` colours drawn from the scheme's\n * non-semantic accents.\n *\n * The default role cycle reaches for `error` as its fourth colour, which is the\n * only other saturated hue in an MD3 scheme — but red is the scheme's signal\n * for something being wrong, so a five-category pie ends up implying one of its\n * categories is a fault. This walks primary → tertiary → secondary instead and\n * blends between them for the extra steps, so more categories means finer\n * gradations of the SAME scheme rather than borrowing a semantic colour.\n */\nexport function harmonicPalette(\n anchors: string[],\n n: number,\n /** Light / dark ends of the scheme, used to separate adjacent entries. */\n contrast?: { light: string; dark: string },\n): string[] {\n const usable = anchors.filter(Boolean);\n if (n <= 0 || usable.length === 0) return [];\n if (usable.length === 1) return Array.from({ length: n }, () => usable[0]);\n const ramp: string[] = [];\n for (let i = 0; i < n; i++) {\n if (n === 1) {\n ramp.push(usable[0]);\n continue;\n }\n // Spread across the WHOLE ramp rather than taking the first n anchors: two\n // categories should get the two most separated accents, not two adjacent\n // ones. Land exactly on an anchor and it is returned untouched, so an\n // unblended entry keeps the caller's own colour notation.\n const t = (i / (n - 1)) * (usable.length - 1);\n const lo = Math.floor(t);\n const hi = Math.min(usable.length - 1, lo + 1);\n const f = t - lo;\n ramp.push(f === 0 ? usable[lo] : f === 1 ? usable[hi] : mixColor(usable[lo], usable[hi], f));\n }\n if (!contrast || n <= usable.length) return ramp;\n // Hue alone runs out: an MD3 scheme's three accents are tonally close, so\n // five steps between them leave neighbours nearly identical. Alternating a\n // small lightness shift separates each entry from the one beside it while\n // keeping every colour inside the scheme.\n return ramp.map((c, i) => (i % 2 === 0 ? c : mixColor(c, i % 4 === 1 ? contrast.dark : contrast.light, 0.22)));\n}\n\n/**\n * Resolve a series colour spec to a concrete CSS colour string.\n * Accepts either an MD3 role (auto-themed) or a raw colour string\n * (hex / rgb / hsl / named colours / `currentColor`).\n */\nexport function resolveSeriesColor(\n host: HTMLElement,\n color: string | MdChartColorRole | undefined,\n fallback: string,\n computed?: CSSStyleDeclaration,\n): string {\n if (!color) return fallback;\n if (color in TOKEN_PROP) {\n return resolveMdColor(host, color as MdChartColorRole, computed);\n }\n // Anything else is treated as a raw CSS colour — but it has to actually BE\n // one. Canvas does not throw on `fillStyle = 'info'`; it ignores the\n // assignment and keeps whatever colour the context last used, so a bad role\n // name or a typo renders as a black (or arbitrarily-coloured) series with\n // nothing in the console. Validate here so it degrades to the palette\n // fallback instead, and say why.\n if (!isCssColor(color)) {\n console.warn(\n `[md-chart] \"${color}\" is not a colour role or a valid CSS colour — falling back. ` +\n `Roles: ${Object.keys(TOKEN_PROP).join(', ')}.`,\n );\n return fallback;\n }\n return color;\n}\n\n/** `CSS.supports` is the cheapest parser available and is safe in every\n * browser we target; SSR/jsdom lacks it, where the value is passed through\n * unchanged because nothing paints there anyway. */\nfunction isCssColor(value: string): boolean {\n if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function') return true;\n return CSS.supports('color', value);\n}\n\n/**\n * Resolve a CSS colour that references custom properties.\n *\n * Canvas cannot: assigning `color-mix(in srgb, var(--md-sys-color-error) 6%,\n * transparent)` to `fillStyle` is REJECTED outright, and the context then keeps\n * whatever colour it last used — so an axis band painted itself in the previous\n * series' fill and changed appearance whenever unrelated colours changed. It\n * has no custom-property scope of its own, so the value has to be computed\n * against a real element first.\n *\n * The probe goes in the shadow root rather than the light DOM: custom\n * properties inherit through the boundary, and adding a child to the host would\n * disturb slot assignment.\n */\nfunction resolveComputedColor(host: HTMLElement, value: string): string {\n if (!/var\\(|color-mix\\(/i.test(value)) return value;\n const doc = host.ownerDocument;\n const parent: Node | null = host.shadowRoot ?? host;\n if (!doc || typeof getComputedStyle !== 'function') return value;\n const probe = doc.createElement('span');\n probe.style.cssText = 'position:absolute;inline-size:0;block-size:0;visibility:hidden';\n probe.style.color = value;\n parent.appendChild(probe);\n const out = getComputedStyle(probe).color;\n probe.remove();\n return out || value;\n}\n\n/**\n * Resolve an axis' shaded bands into engine specs, mapping MD3 colour roles to\n * live token values. Colours left unset stay undefined so the engine can fall\n * back to a themed tint that works on light and dark.\n */\nexport function resolveAxisBands(\n host: HTMLElement,\n bands: MdChartAxisBand[] | undefined,\n): AxisBandSpec[] | undefined {\n if (!bands?.length) return undefined;\n return bands.map((b) => ({\n from: b.from,\n to: b.to,\n color: b.color != null ? resolveComputedColor(host, resolveSeriesColor(host, b.color, b.color)) : undefined,\n label: b.label,\n labelAlign: b.labelAlign,\n labelColor:\n b.labelColor != null ? resolveComputedColor(host, resolveSeriesColor(host, b.labelColor, b.labelColor)) : undefined,\n }));\n}\n\n/**\n * Read a single chart-level CSS custom property with a fallback.\n * Public chart vars look like `--md-{chart}-{prop}`, while\n * shared chart vars use the `--md-chart-{prop}` namespace; both\n * are resolved with the same helper for consistency.\n */\n/**\n * The MD3 typescale `*-font` tokens are full CSS `font` SHORTHANDS\n * (e.g. `\"400 14px/20px Roboto, sans-serif\"`), not a bare family. The\n * chart engine needs just the family list (it composes its own\n * `font: <weight> <size>px <family>`), so extract everything after the\n * `<size>[/<line-height>]` token. A value with no size is assumed to\n * already be a family list and passed through.\n */\nexport function fontFamilyOf(font: string): string {\n const m = font.match(/\\d*\\.?\\d+(?:px|rem|em|pt|%)(?:\\s*\\/\\s*\\S+)?\\s+(.+)$/);\n return (m ? m[1] : font).trim();\n}\n\nfunction readVar(cs: CSSStyleDeclaration, name: string, fallback: string): string {\n const v = cs.getPropertyValue(name).trim();\n return v || fallback;\n}\n\nfunction readNumberVar(cs: CSSStyleDeclaration, name: string, fallback: number): number {\n const raw = cs.getPropertyValue(name).trim();\n if (!raw) return fallback;\n const n = parseFloat(raw);\n return Number.isFinite(n) ? n : fallback;\n}\n\n/**\n * Map an MD3 motion-easing token (`cubic-bezier(...)`) into an\n * ECharts easing identifier. ECharts only ships a fixed set of\n * named easings (no raw cubic-bezier support), so we approximate\n * the M3 standard / emphasized / decelerated / accelerated\n * families with the closest built-in.\n *\n * Reference:\n * • M3 standard ≈ cubic-bezier(0.2, 0, 0, 1) → cubicInOut\n * • M3 emphasized ≈ cubic-bezier(0.2, 0, 0, 1) (anticipating overshoot) → cubicOut\n * • M3 decelerated ≈ cubic-bezier(0, 0, 0, 1) → cubicOut\n * • M3 accelerated ≈ cubic-bezier(0.3, 0, 1, 1) → cubicIn\n *\n * Pickers / panels / charts share the \"emphasized\" family by\n * default — it conveys \"this responded to me\" without feeling\n * mechanical, matching MUI X's spring-loaded enter feel.\n */\nfunction pickEasing(rawCubicBezier: string): string {\n if (!rawCubicBezier) return 'cubicOut';\n const m = rawCubicBezier.match(/cubic-bezier\\(([^)]+)\\)/);\n if (!m) return 'cubicOut';\n const [a, b, c, d] = m[1].split(',').map(s => parseFloat(s.trim()));\n // Roughly: x1 near 0 + y2 near 1 → decelerated/standard family.\n if (a < 0.25 && d > 0.95) return 'cubicOut';\n // x1 ≥ 0.3 + y1 ≈ 0 → accelerated.\n if (a >= 0.3 && b < 0.1) return 'cubicIn';\n // Default to in-out for symmetric easings.\n if (Math.abs(a - (1 - d)) < 0.15 && Math.abs(b - (1 - c)) < 0.15) return 'cubicInOut';\n return 'cubicOut';\n}\n\n/**\n * Build the per-render theme object by reading the host's tokens.\n * Cheap enough to call on every `componentDidLoad` and on the\n * `themechange` event that the global theme switcher dispatches.\n */\nexport function readMdChartTheme(host: HTMLElement): MdChartTheme {\n const cs = getComputedStyle(host);\n\n const palette = DEFAULT_ROLE_CYCLE.map(r => resolveMdColor(host, r, cs));\n\n const motionDuration = readNumberVar(cs, '--md-sys-motion-duration-medium2', 300);\n const easingRaw = readVar(cs, '--md-sys-motion-easing-emphasized', 'cubic-bezier(0.2, 0, 0, 1)');\n\n // Reduced-motion + forced-colors are environment-level, not\n // tokens — query them via window.matchMedia at theme-read\n // time so chart respects OS-level preferences without an\n // explicit prop.\n const reducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const forcedColors =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(forced-colors: active)').matches;\n\n return {\n background: 'transparent',\n textColor: readVar(cs, '--md-sys-color-on-surface', '#1C1B1F'),\n textColorMuted: readVar(cs, '--md-sys-color-on-surface-variant', '#49454F'),\n // `--md-chart-grid-color` / `--md-chart-axis-color` let a consumer override\n // the gridline / axis-line colour per chart. MD3 data-viz keeps these light:\n // both default to `outline-variant`, and the gridlines sit at a lower opacity\n // so they read as faint guides beneath a slightly more present axis line —\n // no heavy chart frame. A consumer override is used verbatim (not dimmed).\n gridColor: (() => {\n const override = readVar(cs, '--md-chart-grid-color', '');\n return override || withAlpha(readVar(cs, '--md-sys-color-outline-variant', '#CAC4D0'), 0.5);\n })(),\n axisLineColor: readVar(cs, '--md-chart-axis-color', readVar(cs, '--md-sys-color-outline-variant', '#CAC4D0')),\n surface: readVar(cs, '--md-sys-color-surface', '#FFFBFE'),\n tooltipSurface: readVar(cs, '--md-sys-color-inverse-surface', readVar(cs, '--md-sys-color-on-surface', '#322F35')),\n tooltipTextColor: readVar(cs, '--md-sys-color-inverse-on-surface', readVar(cs, '--md-sys-color-surface', '#F5EFF7')),\n tooltipBorderColor: 'transparent',\n tooltipShadow: readVar(cs, '--md-sys-elevation-2', '0px 1px 2px rgba(0,0,0,0.3), 0px 2px 6px 2px rgba(0,0,0,0.15)'),\n tooltipRadius: readNumberVar(cs, '--md-sys-shape-corner-small', 8),\n palette,\n fontFamily: fontFamilyOf(readVar(cs, '--md-sys-typescale-label-medium-font', '\"Roboto\", system-ui, sans-serif')),\n labelSize: Math.max(9, readNumberVar(cs, '--md-sys-typescale-label-small-size', 11) + readNumberVar(cs, '--md-sys-density-scale', 0) * 0.5),\n titleSize: Math.max(11, readNumberVar(cs, '--md-sys-typescale-title-small-size', 14) + readNumberVar(cs, '--md-sys-density-scale', 0) * 0.5),\n motionDuration: reducedMotion ? 0 : motionDuration,\n motionEasing: pickEasing(easingRaw),\n reducedMotion,\n forcedColors,\n };\n}\n\n/**\n * Build a tooltip formatter that produces MD3-styled HTML.\n * Used by every chart so the surface/typography/contrast match.\n *\n * The `inverse-surface` tokens give us the MD3 \"tooltip\" scheme\n * out of the box — dark surface on light theme, light surface\n * on dark theme — so the formatter doesn't need a separate\n * dark-mode branch.\n */\nexport function buildTooltipStyle(theme: MdChartTheme): {\n backgroundColor: string;\n borderColor: string;\n borderRadius: number;\n extraCssText: string;\n textStyle: { color: string; fontFamily: string; fontSize: number };\n} {\n return {\n backgroundColor: theme.tooltipSurface,\n borderColor: theme.tooltipBorderColor,\n borderRadius: theme.tooltipRadius,\n extraCssText: `box-shadow: ${theme.tooltipShadow}; padding: 8px 12px; max-inline-size: 280px;`,\n textStyle: {\n color: theme.tooltipTextColor,\n fontFamily: theme.fontFamily,\n fontSize: theme.labelSize,\n },\n };\n}\n","/*\n * Shared chart helpers (renderer-agnostic)\n * ===========================================================\n * What remains of the old ECharts option module after the charts\n * moved to the in-house engine: two small, pure helpers still used\n * across every md-* chart. The engine's own layout/scale/geometry\n * live under `./engine`.\n * ===========================================================\n */\n\nimport type { MdChartAxisValue } from './types';\n\n/**\n * Stable colour selector. Cycles through the palette for series\n * that didn't supply a colour. Series colour spec is resolved\n * separately via `resolveSeriesColor()` (theme.ts).\n */\nexport function pickPaletteColor(palette: string[], seriesIndex: number): string {\n return palette[seriesIndex % palette.length];\n}\n\n/**\n * Default value formatter — locale-aware. Used by tooltips,\n * axis labels, and a11y text when the consumer doesn't supply\n * one of their own.\n */\nexport function defaultValueFormatter(v: MdChartAxisValue, locale?: string): string {\n if (v == null) return '';\n // An empty/absent locale means \"whatever Intl resolves\" — the browser's, which\n // is the right default when the page hasn't said otherwise.\n const l = locale || undefined;\n if (v instanceof Date) return v.toLocaleString(l);\n if (typeof v === 'number') return v.toLocaleString(l);\n return String(v);\n}\n","/*\n * Chart engine — scales & tick generation\n * ===========================================================\n * The pure-math foundation of the from-scratch chart engine\n * (replacing ECharts). The renderer and the DOM text\n * overlay consume these — nothing\n * here touches the DOM, so it's fully unit-testable and shared.\n *\n * A \"scale\" maps a DATA value (a number, a Date's epoch ms, or a\n * category index) to a PIXEL coordinate within a [0, size] plot\n * range, and back. Tick generators pick human-friendly gridline\n * positions (\"nice\" round numbers, sensible time steps).\n * ===========================================================\n */\n\nimport type { MdChartAxisBreakOptions, MdChartAxisBreaks, MdChartAxisValue, MdChartScaleType } from '../types';\n\n/** A resolved numeric domain `[min, max]` in data space. */\nexport type Domain = readonly [number, number];\n\n/**\n * Maps data ↔ pixels for a continuous or banded axis. `range` is\n * always in ascending pixel order `[0, size]`; `reverse` and the\n * plot's own origin flip are applied by the caller when drawing.\n */\nexport interface Scale {\n readonly type: MdChartScaleType;\n /** Data value → pixel offset within `[0, size]`. */\n scale(value: number): number;\n /** Pixel offset → data value (inverse; for hit-testing/zoom). */\n invert(pixel: number): number;\n /** The pixel a category index / value sits at, for markers. */\n readonly size: number;\n /** Resolved numeric domain the scale spans. */\n readonly domain: Domain;\n /** For category scales: the pixel band width per category. */\n readonly bandwidth: number;\n}\n\n/** Coerce any axis value to the number the scales operate on. */\nexport function toNumeric(value: MdChartAxisValue, scale: MdChartScaleType): number {\n if (scale === 'category') return typeof value === 'number' ? value : 0;\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'number') return value;\n // ISO-8601 / date-like string for time; numeric string for value/log.\n const asNum = Number(value);\n if (!Number.isNaN(asNum) && scale !== 'time') return asNum;\n const asDate = Date.parse(value);\n return Number.isNaN(asDate) ? 0 : asDate;\n}\n\n/**\n * Continuous linear scale. `time` reuses this (epoch ms are\n * linear); `log` is handled by {@link makeLogScale}.\n */\nexport function makeLinearScale(\n domain: Domain,\n size: number,\n type: MdChartScaleType = 'value',\n): Scale {\n let [min, max] = domain;\n if (min === max) {\n // Degenerate domain (single value / all-equal series): pad so\n // the point lands mid-plot instead of dividing by zero.\n min -= 1;\n max += 1;\n }\n const span = max - min;\n return {\n type,\n size,\n domain: [min, max],\n bandwidth: 0,\n scale: (v) => ((v - min) / span) * size,\n invert: (px) => min + (px / size) * span,\n };\n}\n\n/** Continuous base-10 log scale (positive domain only). */\nexport function makeLogScale(domain: Domain, size: number): Scale {\n // Guard non-positive mins — log10 is undefined at/below 0. Clamp to a small\n // positive floor derived from the max so the axis is still meaningful for\n // datasets that dip to 0. If the WHOLE domain is <= 0 (unsupported garbage-in),\n // fall back to a benign [1e-6, 1] range instead of a denormal ~1e-323 axis.\n const positiveMax = domain[1] > 0 ? domain[1] : 1;\n const safeMin = domain[0] > 0 ? domain[0] : Math.max(positiveMax / 1e6, Number.MIN_VALUE);\n const lo = Math.log10(safeMin);\n const hi = Math.log10(Math.max(positiveMax, safeMin * 10));\n const span = hi - lo || 1;\n return {\n type: 'log',\n size,\n domain: [safeMin, Math.pow(10, hi)],\n bandwidth: 0,\n scale: (v) => ((Math.log10(v <= 0 ? safeMin : v) - lo) / span) * size,\n invert: (px) => Math.pow(10, lo + (px / size) * span),\n };\n}\n\n/**\n * Category (band) scale. `count` evenly-spaced categories over\n * `size`. `alignWithLabel` centers a category's point in its band\n * (line/area: point sits AT the category) vs the band's leading\n * edge (bars: sit BETWEEN ticks).\n */\nexport function makeCategoryScale(count: number, size: number, alignWithLabel = true): Scale {\n const n = Math.max(count, 1);\n // Line/area put points at category centers with a half-band inset\n // at each end; ECharts' `boundaryGap:false` equivalent centers the\n // first/last points on the axis ends. We use the centered model.\n const bandwidth = size / n;\n const offset = alignWithLabel ? bandwidth / 2 : 0;\n return {\n type: 'category',\n size,\n domain: [0, n - 1],\n bandwidth,\n scale: (i) => offset + i * bandwidth,\n invert: (px) => Math.round((px - offset) / bandwidth),\n };\n}\n\n// ─────────────────── axis breaks ───────────────────\n\n/** Default pixels an axis break occupies — enough to read as a cut. */\nexport const DEFAULT_BREAK_GAP = 14;\n\n/** A break resolved into numbers on the axis' own scale. */\nexport interface BreakRange {\n from: number;\n to: number;\n /** Pixels the cut occupies on the axis. */\n gap: number;\n}\n\n/** A break as positioned on the axis, for drawing the cut. */\nexport interface ScaleBreak extends BreakRange {\n /** Pixel offset (within `[0, size]`) where the cut starts. */\n px: number;\n}\n\n/** A scale that has had one or more ranges cut out of it. */\nexport interface BrokenScale extends Scale {\n /** The cuts, in ascending order, with their pixel positions. */\n readonly breaks: readonly ScaleBreak[];\n}\n\n/**\n * Clip breaks to the domain, drop degenerate ones, sort, and merge any that\n * overlap or touch — so the scale can walk them in one pass and two authored\n * ranges that happen to abut don't double-count their gaps.\n */\nexport function normalizeBreaks(breaks: readonly BreakRange[], domain: Domain): BreakRange[] {\n const [lo, hi] = domain[0] <= domain[1] ? domain : [domain[1], domain[0]];\n const clipped = breaks\n .map((b) => ({\n from: Math.max(lo, Math.min(b.from, b.to)),\n to: Math.min(hi, Math.max(b.from, b.to)),\n gap: b.gap ?? DEFAULT_BREAK_GAP,\n }))\n // A cut that starts at the very bottom would just shift the axis up, and a\n // zero-width one has nothing to remove. A cut reaching the TOP is kept: the\n // literal \"one point at 1, one at 1e12\" case ends exactly at the domain\n // max, and dropping it would leave the small point pinned to the axis.\n .filter((b) => b.to > b.from && b.from > lo && b.to <= hi)\n .sort((a, b) => a.from - b.from);\n\n const merged: BreakRange[] = [];\n for (const b of clipped) {\n const last = merged[merged.length - 1];\n if (last && b.from <= last.to) {\n last.to = Math.max(last.to, b.to);\n last.gap = Math.max(last.gap, b.gap);\n } else {\n merged.push({ ...b });\n }\n }\n return merged;\n}\n\n/**\n * A cut that runs to the very top of the domain leaves the section ABOVE it a\n * single point — the outlier pinned to the axis top, with no ticks or gridlines\n * to read it against. Pull that cut's top edge DOWN so the outlier sits in a real\n * top section, of the same value-range as the plain section just below the cut,\n * so both sections tick at the same density.\n *\n * Only touches a top-edge cut on a linear axis; a normal in-range cut, a log\n * axis, or a section that already has range is left exactly as it was.\n */\nexport function openTopSection(ranges: readonly BreakRange[], domain: Domain, scale: MdChartScaleType): BreakRange[] {\n const out = ranges.map((r) => ({ ...r }));\n if (!out.length || scale === 'log') return out;\n const last = out[out.length - 1];\n if (domain[1] - last.to > 1e-9) return out; // the top section already has a range\n const belowFrom = out.length > 1 ? out[out.length - 2].to : domain[0];\n const belowRange = last.from - belowFrom; // the plain section just under this cut\n if (!(belowRange > 0)) return out;\n // Range for the opened section: at least the section below it (so the two tick\n // at the same density), but no finer than a nice step of the OUTLIER's own\n // magnitude — otherwise, at a huge outlier, ticks a few units apart round to\n // identical labels (…000, …000, …000).\n const t = niceLinearTicks(0, domain[1], 6);\n const outlierStep = t.length > 1 ? t[1] - t[0] : 0;\n const range = Math.max(belowRange, outlierStep);\n const newTo = domain[1] - range;\n if (newTo > last.from + 1e-9) last.to = newTo;\n return out;\n}\n\n/**\n * Find the empty stretches worth cutting out of `values`.\n *\n * A gap qualifies when it is at least `minGap`× the median gap between\n * neighbouring values — the \"one cluster at 1, another at a trillion\" shape.\n * The widest qualifying gaps win, capped at `maxBreaks`, and each cut stops\n * short of the data on either side so the outermost points aren't sitting on\n * the cut itself.\n */\nexport function autoBreaks(\n values: readonly number[],\n opts: { minGap?: number; maxBreaks?: number; gap?: number } = {},\n): BreakRange[] {\n const minGap = opts.minGap ?? 8;\n const maxBreaks = opts.maxBreaks ?? 2;\n const sorted = [...new Set(values.filter((v) => Number.isFinite(v)))].sort((a, b) => a - b);\n if (sorted.length < 4) return [];\n const gaps: { from: number; to: number; size: number }[] = [];\n for (let i = 1; i < sorted.length; i++) {\n gaps.push({ from: sorted[i - 1], to: sorted[i], size: sorted[i] - sorted[i - 1] });\n }\n const sizes = gaps.map((g) => g.size).sort((a, b) => a - b);\n const median = sizes[Math.floor(sizes.length / 2)] || 0;\n if (median <= 0) return [];\n const chosen = gaps\n .filter((g) => g.size >= median * minGap)\n .sort((a, b) => b.size - a.size)\n .slice(0, maxBreaks);\n // Cut exactly from the last value below to the first value above — the cut's\n // own pixel gap is the visual separation. Padding the cut by a fraction OF\n // THE GAP would be self-defeating here: 10% of the emptiness between 18 and\n // 8e11 is 8e10, which swallows the very cluster the break exists to rescue.\n // Detection only — clipping and merging happen in makeBrokenScale, against\n // the real AXIS domain. Normalising here against the data extent would drop\n // a gap that ends on the last data value, even though the axis runs past it.\n return chosen\n .map((g) => ({ from: g.from, to: g.to, gap: opts.gap ?? DEFAULT_BREAK_GAP }))\n .sort((a, b) => a.from - b.from);\n}\n\n/**\n * How the axis divides the pixels between the sections a break leaves behind.\n *\n * • `equal` (default) — every section gets the same share. This is what makes\n * a break worth having when the clusters are orders of magnitude apart: a\n * point at 1 and a point at 1e12 each land in a readable half, instead of\n * the small one collapsing onto the axis. Sections of similar width look\n * the same as `proportional`, so it only differs where it matters.\n * • `proportional` — one unit-per-pixel across the whole axis, so widths stay\n * comparable between sections; only the cut ranges are removed. Classic\n * break behaviour. Note this leaves a tiny section tiny: breaking the empty\n * middle out of 1 … 1e12 does NOT rescue the low end.\n */\nexport type BreakSizing = 'equal' | 'proportional';\n\n/**\n * Wrap a scale so the given ranges are cut out of it. Each cut costs its `gap`\n * in pixels instead of its true width, and what is left is divided between the\n * surviving sections per {@link BreakSizing}.\n *\n * A value *inside* a cut has no honest position — it maps to the near edge, and\n * callers are expected to drop such data rather than draw it (the line layout\n * splits its polylines at the cut).\n */\nexport function makeBrokenScale(\n domain: Domain,\n size: number,\n type: MdChartScaleType,\n breaks: readonly BreakRange[],\n sizing: BreakSizing = 'equal',\n): BrokenScale {\n const base = type === 'log' ? makeLogScale(domain, size) : makeLinearScale(domain, size, type);\n const ranges = normalizeBreaks(breaks, base.domain);\n if (!ranges.length) return { ...base, breaks: [] };\n\n // Work in the base scale's pixel space, so a log axis breaks in log space.\n const cuts = ranges.map((b) => ({ ...b, fromPx: base.scale(b.from), toPx: base.scale(b.to) }));\n const gaps = cuts.reduce((sum, c) => sum + c.gap, 0);\n\n // The surviving stretches of the axis, in base pixels.\n const spans: { from: number; to: number }[] = [];\n let cursor = 0;\n for (const c of cuts) {\n spans.push({ from: cursor, to: c.fromPx });\n cursor = c.toPx;\n }\n spans.push({ from: cursor, to: size });\n\n const usable = Math.max(0, size - gaps);\n const totalSpan = spans.reduce((sum, s) => sum + Math.max(0, s.to - s.from), 0);\n // Each section's output width, and where it starts.\n const sections = spans.map((s) => {\n const width = Math.max(0, s.to - s.from);\n const out =\n sizing === 'equal'\n ? usable / spans.length\n : totalSpan > 0\n ? (width / totalSpan) * usable\n : usable / spans.length;\n return { ...s, width, out };\n });\n let outCursor = 0;\n const placed = sections.map((sec, i) => {\n const start = outCursor;\n outCursor += sec.out + (cuts[i]?.gap ?? 0);\n return { ...sec, outStart: start };\n });\n\n const scaleBreaks: ScaleBreak[] = cuts.map((c, i) => ({\n from: c.from,\n to: c.to,\n gap: c.gap,\n px: placed[i].outStart + placed[i].out,\n }));\n\n return {\n type,\n size,\n domain: base.domain,\n bandwidth: 0,\n breaks: scaleBreaks,\n scale: (v) => {\n const px = base.scale(v);\n for (let i = 0; i < placed.length; i++) {\n const sec = placed[i];\n if (px <= sec.to || i === placed.length - 1) {\n // Inside the preceding cut: pin to its near edge (the end of the\n // section before it), per this function's contract.\n if (px < sec.from) return i > 0 ? placed[i - 1].outStart + placed[i - 1].out : sec.outStart;\n // A section with no width holds a single value (a lone high point at\n // the domain max): put it at the section's far end, not its start.\n const t = sec.width > 0 ? (px - sec.from) / sec.width : 1;\n return sec.outStart + t * sec.out;\n }\n }\n return size;\n },\n invert: (px) => {\n for (let i = 0; i < placed.length; i++) {\n const sec = placed[i];\n const end = sec.outStart + sec.out;\n if (px <= end || i === placed.length - 1) {\n const t = sec.out > 0 ? (Math.max(px, sec.outStart) - sec.outStart) / sec.out : 0;\n return base.invert(sec.from + t * sec.width);\n }\n }\n return base.domain[1];\n },\n };\n}\n\n/**\n * Turn an axis' public `breaks` config into concrete ranges on this axis'\n * numbers, combining any explicit cuts with automatically-found ones.\n *\n * `values` are the data values on this axis, needed for the automatic pass.\n */\nexport function resolveAxisBreaks(\n breaks: MdChartAxisBreaks | undefined,\n values: readonly number[],\n scale: MdChartScaleType,\n): { ranges: BreakRange[]; sizing: BreakSizing } {\n if (!breaks) return { ranges: [], sizing: 'equal' };\n const opts: MdChartAxisBreakOptions =\n breaks === 'auto' ? { auto: true } : Array.isArray(breaks) ? { ranges: breaks } : breaks;\n const gap = opts.gap ?? DEFAULT_BREAK_GAP;\n const explicit: BreakRange[] = (opts.ranges ?? []).map((b) => ({\n from: toNumeric(b.from, scale),\n to: toNumeric(b.to, scale),\n gap: b.gap ?? gap,\n }));\n const found = opts.auto\n ? autoBreaks(values, { minGap: opts.minGap, maxBreaks: opts.maxBreaks, gap })\n : [];\n return { ranges: [...explicit, ...found], sizing: opts.sizing ?? 'equal' };\n}\n\n/**\n * How many ticks a section should end up with before we stop asking for more.\n * Three is what makes a section read as ruled rather than as a bare pair of\n * edges — roughly the density an unbroken axis of that pixel height would have,\n * since each section holds `target / sections` of the axis.\n */\nconst SECTION_MIN_TICKS = 3;\n\n/**\n * Ticks for an axis that has been cut, generated PER SECTION.\n *\n * A broken axis needs this: run the usual tick algorithm over the whole domain\n * and every tick can land in the big section, leaving the rescued cluster with\n * nothing to read against — which defeats the break. Each surviving section\n * gets its own share of the tick budget instead.\n */\nexport function sectionedTicks(\n domain: Domain,\n breaks: readonly BreakRange[],\n scale: MdChartScaleType,\n target = 6,\n): number[] {\n const ticksFor = (lo: number, hi: number, n: number) =>\n scale === 'log' ? logTicks(lo, hi) : scale === 'time' ? timeTicks(lo, hi, n) : niceLinearTicks(lo, hi, n);\n // Against the AXIS domain, exactly as makeBrokenScale does: a cut the domain\n // rejects (one starting at the very bottom, say) is not drawn, so it must not\n // section the ticks either — that ruled only the ghost section and left the\n // rest of the axis bare.\n const ranges = normalizeBreaks(breaks, domain);\n if (!ranges.length) return ticksFor(domain[0], domain[1], target);\n\n const sections: [number, number][] = [];\n let cursor = domain[0];\n for (const b of ranges) {\n sections.push([cursor, b.from]);\n cursor = b.to;\n }\n sections.push([cursor, domain[1]]);\n\n // Floor of 3: the nice-tick algorithm asked for 2 returns a single usable\n // tick (it rounds the step up past the section), which would leave a rescued\n // cluster unlabelled — the very thing per-section ticks exist to prevent.\n const per = Math.max(3, Math.round(target / sections.length));\n\n /**\n * One section's ticks, asking for more until the section is actually ruled.\n *\n * Nice-step rounding overshoots badly on a section that is narrow relative to\n * where it sits, and the ticks that fall outside the section are then dropped:\n * 810B…1.1T asked for 3 rounds the step to 200B, whose grid (800B, 1T, 1.2T)\n * leaves ONE value inside — a band with a single gridline and nothing to read\n * the rescued cluster against. 0…18 asked for 3 lands only 0 and 10, so the\n * top third of that band is blank too.\n *\n * Asking again with a bigger count halves the step (100B → 900B/1T/1.1T;\n * 5 → 0/5/10/15) without giving up round numbers, which is what makes each\n * section read like a normal axis of its own size. Log ticks ignore the\n * count, so they are taken as they come.\n */\n const sectionTicks = (lo: number, hi: number): number[] => {\n let ticks: number[] = [];\n for (const n of [per, per * 2, per * 4]) {\n // Keep ticks to their own section; the cut edges themselves are useful\n // labels, so they are allowed through.\n ticks = ticksFor(lo, hi, n).filter((t) => t >= lo - 1e-9 && t <= hi + 1e-9);\n if (ticks.length >= SECTION_MIN_TICKS || scale === 'log') break;\n }\n return ticks;\n };\n\n const out: number[] = [];\n for (const [lo, hi] of sections) {\n if (hi <= lo) continue;\n out.push(...sectionTicks(lo, hi));\n }\n return [...new Set(out)].sort((a, b) => a - b);\n}\n\n/** Is this value inside one of the cuts (and so unplottable)? */\nexport function inBreak(breaks: readonly BreakRange[], v: number): boolean {\n return breaks.some((b) => v > b.from && v < b.to);\n}\n\n// ─────────────────── tick generation ───────────────────\n\n/** A resolved tick: its numeric position + preformatted label. */\nexport interface Tick {\n value: number;\n /** Original axis value (for the user's valueFormatter). */\n raw: MdChartAxisValue;\n}\n\n/**\n * \"Nice\" linear ticks — round step sizes (1/2/5 × 10ⁿ) covering\n * `[min, max]` with ~`target` ticks. The staple axis algorithm\n * (Heckbert). Returns tick values within the domain.\n */\nexport function niceLinearTicks(min: number, max: number, target = 6): number[] {\n // Order-independent: ticks span the same nice values whichever way the domain\n // runs (a reversed [max,min] override still yields a populated axis; the scale\n // handles the inversion). niceNum(negative) would otherwise NaN-cascade to [].\n const lo = Math.min(min, max);\n const hi = Math.max(min, max);\n if (lo === hi) return [lo];\n // Step from the ACTUAL span, not a \"nice\"-rounded one. Rounding the span up\n // first (23.8 → 50) then dividing inflates the step by a whole notch, and\n // since the outermost nice ticks are clipped back to the data below, a domain\n // like [-6, 18] was left with just 0 and 10 — no negative label at all on a\n // chart whose whole point was that it crosses zero.\n const step = niceNum((hi - lo) / Math.max(target - 1, 1), true);\n const niceMin = Math.floor(lo / step) * step;\n const niceMax = Math.ceil(hi / step) * step;\n const ticks: number[] = [];\n // Guard against fp accumulation with an explicit bound.\n const maxTicks = Math.round((niceMax - niceMin) / step) + 1;\n for (let i = 0; i < maxTicks; i++) {\n const v = niceMin + i * step;\n // Snap tiny fp residue to 0.\n ticks.push(Math.abs(v) < step / 1e6 ? 0 : v);\n }\n return ticks.filter((v) => v >= lo - step / 1e6 && v <= hi + step / 1e6);\n}\n\n/** Round a range to a \"nice\" value; `round` snaps to nearest vs ceil. */\nfunction niceNum(range: number, round: boolean): number {\n const exp = Math.floor(Math.log10(range));\n const frac = range / Math.pow(10, exp);\n let nice: number;\n if (round) {\n nice = frac < 1.5 ? 1 : frac < 3 ? 2 : frac < 7 ? 5 : 10;\n } else {\n nice = frac <= 1 ? 1 : frac <= 2 ? 2 : frac <= 5 ? 5 : 10;\n }\n return nice * Math.pow(10, exp);\n}\n\n/** Powers-of-ten ticks for a log axis, within `[min, max]`. */\nexport function logTicks(min: number, max: number): number[] {\n const lo = Math.floor(Math.log10(min > 0 ? min : max / 1e6));\n const hi = Math.ceil(Math.log10(max));\n const ticks: number[] = [];\n for (let e = lo; e <= hi; e++) ticks.push(Math.pow(10, e));\n return ticks.filter((v) => v >= min && v <= max);\n}\n\n/** Nice time-interval ticks. Picks a step from a human ladder. */\nexport function timeTicks(minMs: number, maxMs: number, target = 6): number[] {\n const span = maxMs - minMs;\n if (span <= 0) return [minMs];\n const S = 1000, M = 60 * S, H = 60 * M, D = 24 * H;\n const steps = [S, 5 * S, 15 * S, 30 * S, M, 5 * M, 15 * M, 30 * M, H, 3 * H, 6 * H, 12 * H, D, 2 * D, 7 * D, 14 * D, 30 * D, 90 * D, 180 * D, 365 * D];\n const ideal = span / Math.max(target - 1, 1);\n const idx = steps.findIndex((s) => s >= ideal);\n let step = idx === -1 ? steps[steps.length - 1] : steps[idx];\n // The ladder is coarse at the top (a month, then a quarter), so rounding up\n // can triple the spacing: seven months of data asks for a ~35-day step and\n // would get quarters. Drop to the next finer step when it still lands near\n // the target count (never more than ~1.4x it, so labels can't crowd).\n const finer = idx > 0 ? steps[idx - 1] : undefined;\n if (finer && span / finer <= Math.max(target - 1, 1) * 1.4) step = finer;\n const start = Math.ceil(minMs / step) * step;\n const ticks: number[] = [];\n for (let t = start; t <= maxMs; t += step) ticks.push(t);\n return ticks;\n}\n\n/**\n * Compute the numeric domain for a value/log/time axis from the\n * series data, honoring explicit `min`/`max` overrides and (for\n * value axes) extending to a nice zero-anchored range.\n */\nexport function computeDomain(\n values: number[],\n opts: { min?: number; max?: number; scale: MdChartScaleType; includeZero?: boolean } = { scale: 'value' },\n): Domain {\n // Loop over the data rather than spreading into Math.min/Math.max: the spread\n // overflows the call-stack past ~1e5 args, and a single NaN/Infinity would\n // otherwise poison the whole aggregate. Only finite values feed the extent.\n const isLog = opts.scale === 'log';\n let dataLo = Infinity;\n let dataHi = -Infinity;\n let hasFinite = false;\n for (let i = 0; i < values.length; i++) {\n const v = values[i];\n if (!Number.isFinite(v)) continue;\n // A log axis is undefined at/below 0, and stacked bands contribute a 0\n // baseline; ignore non-positive values so the extent reflects the data.\n if (isLog && v <= 0) continue;\n hasFinite = true;\n if (v < dataLo) dataLo = v;\n if (v > dataHi) dataHi = v;\n }\n if (!hasFinite) {\n dataLo = isLog ? 1 : 0;\n dataHi = isLog ? 10 : 1;\n }\n\n // Explicit overrides win outright; `includeZero` only ever extends a\n // DATA-derived bound toward zero, never a user-supplied min/max.\n const loExplicit = opts.min != null && Number.isFinite(opts.min);\n const hiExplicit = opts.max != null && Number.isFinite(opts.max);\n let lo = loExplicit ? (opts.min as number) : dataLo;\n let hi = hiExplicit ? (opts.max as number) : dataHi;\n\n if (isLog) {\n // Snap a data-derived bound out to its enclosing decade (10ⁿ) so the data\n // sits cleanly between power-of-ten gridlines (10 → 100 → 1k → 10k …).\n if (!loExplicit && lo > 0) lo = Math.pow(10, Math.floor(Math.log10(lo)));\n if (!hiExplicit && hi > 0) hi = Math.pow(10, Math.ceil(Math.log10(hi)));\n if (lo === hi) {\n lo /= 10;\n hi *= 10;\n }\n return [lo, hi];\n }\n\n if (opts.includeZero) {\n if (!loExplicit && lo > 0) lo = 0;\n if (!hiExplicit && hi < 0) hi = 0;\n }\n if (lo === hi) {\n lo -= 1;\n hi += 1;\n }\n return [lo, hi];\n}\n","/*\n * Chart engine — geometry (curves, stacking, gaps)\n * ===========================================================\n * Pure data→shape math shared by both renderer backends. Curves\n * are TESSELLATED into flat polyline points (not left as bezier\n * segments) so the shape is decided once, in one place, and the\n * renderer just\n * lineTo's through them. No DOM here; fully unit-testable.\n * ===========================================================\n */\n\nimport type { MdChartCurve, MdChartDataPoint, MdChartStackMode, MdChartSymbol } from '../types';\n\nexport interface Pt {\n x: number;\n y: number;\n}\n\n/**\n * Vertex angles (degrees, screen space where +y is down) for each\n * polygonal marker symbol, measured from the marker centre at the\n * circumradius. `circle`/`none` have no polygon.\n */\nconst MARKER_ANGLES: Partial<Record<MdChartSymbol, number[]>> = {\n square: [45, 135, 225, 315], // corners on the diagonals → axis-aligned square\n diamond: [0, 90, 180, 270],\n triangle: [-90, 150, 30], // apex up\n 'triangle-down': [90, -30, 210], // apex down\n};\n\n/** Convex polygon vertices for a marker symbol, or `null` for circle/none. */\nexport function markerPolygon(symbol: MdChartSymbol | undefined, cx: number, cy: number, r: number): Pt[] | null {\n const angles = symbol ? MARKER_ANGLES[symbol] : undefined;\n if (!angles) return null;\n return angles.map((deg) => {\n const a = (deg * Math.PI) / 180;\n return { x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) };\n });\n}\n\n/** Substeps used to sample smooth/monotone curve segments. */\nconst CURVE_SAMPLES = 20;\n\n/**\n * Only decimate once a run carries this many points per horizontal pixel.\n * Below it every point still lands in the polyline, so ordinary charts are\n * untouched; above it the extra points cannot be resolved on screen anyway.\n */\nconst DECIMATE_PER_PX = 4;\n\n/**\n * Collapse a dense run to its per-pixel-column min/max envelope.\n *\n * A 500k-point run over a ~900px plot is ~550 points per column: the stroke\n * spends all its time drawing sub-pixel detail nobody can see, and a noisy\n * series turns that into tens of seconds of overdraw. Emitting the first,\n * lowest, highest and last point of each column keeps the silhouette — the\n * vertical extent a dense series reads as — while bounding the polyline to\n * ~4x the plot width. Same trick as Highcharts' Boost and uPlot.\n *\n * Returns the input untouched when it isn't dense enough to matter. Only the\n * DRAWN polyline is decimated; hover lookup and markers keep the full run, so\n * tooltips still report real datapoints.\n */\nexport function decimateMinMax(points: Pt[], plotWidth: number): Pt[] {\n const width = Math.max(1, Math.floor(plotWidth));\n if (points.length <= width * DECIMATE_PER_PX) return points;\n\n const out: Pt[] = [];\n let col = Math.round(points[0].x);\n let firstI = 0;\n let lastI = 0;\n let minI = 0;\n let maxI = 0;\n\n // Emit one column: its first point, the two extremes in the order they\n // occurred (the polyline is stroked in sequence, so occurrence order is what\n // keeps the zig-zag faithful), then its last point. Indices that coincide are\n // emitted once.\n const flush = () => {\n const picked = [firstI, minI < maxI ? minI : maxI, minI < maxI ? maxI : minI, lastI];\n let prev = -1;\n for (const i of picked) {\n if (i !== prev) out.push(points[i]);\n prev = i;\n }\n };\n\n for (let i = 1; i < points.length; i++) {\n const c = Math.round(points[i].x);\n if (c !== col) {\n flush();\n col = c;\n firstI = minI = maxI = i;\n } else {\n if (points[i].y < points[minI].y) minI = i;\n if (points[i].y > points[maxI].y) maxI = i;\n }\n lastI = i;\n }\n flush();\n return out;\n}\n\n/**\n * Interpolate a run of on-screen points per the curve type,\n * returning the polyline the renderers stroke. `linear` returns\n * the input; `smooth`/`monotone` tessellate; `step*` insert the\n * corner points.\n */\n/**\n * Clamp interpolated points into a rect.\n *\n * A Catmull-Rom spline (`smooth`) is an INTERPOLATING curve, not a hull-bounded\n * one: it passes through every sample but its control tangents can bulge past\n * them. Where a stacked series collapses onto the axis the bulge lands outside\n * the plot — measured at ~1.7px past 0% on a composition profile — which paints\n * a stray line over the axis. Clamping the emitted points keeps the curve inside\n * the box it belongs to; `monotone` and `linear` never overshoot and are\n * unaffected.\n */\nexport function clampToRect(points: Pt[], x: number, y: number, w: number, h: number): Pt[] {\n const x2 = x + w;\n const y2 = y + h;\n let dirty = false;\n for (const p of points) {\n if (p.x < x || p.x > x2 || p.y < y || p.y > y2) {\n dirty = true;\n break;\n }\n }\n if (!dirty) return points;\n return points.map((p) => ({\n x: p.x < x ? x : p.x > x2 ? x2 : p.x,\n y: p.y < y ? y : p.y > y2 ? y2 : p.y,\n }));\n}\n\nexport function interpolate(points: Pt[], curve: MdChartCurve): Pt[] {\n if (points.length < 2) return points.slice();\n switch (curve) {\n case 'linear':\n return points.slice();\n case 'step':\n case 'step-before':\n case 'step-middle':\n return stepPoints(points, curve);\n case 'monotone':\n return monotone(points);\n case 'smooth':\n default:\n return catmullRom(points);\n }\n}\n\n/** Step interpolation — insert the corner vertices. */\nfunction stepPoints(pts: Pt[], mode: MdChartCurve): Pt[] {\n const out: Pt[] = [pts[0]];\n for (let i = 1; i < pts.length; i++) {\n const a = pts[i - 1];\n const b = pts[i];\n if (mode === 'step' /* step-after: hold a.y then jump */) {\n out.push({ x: b.x, y: a.y }, b);\n } else if (mode === 'step-before' /* jump then hold */) {\n out.push({ x: a.x, y: b.y }, b);\n } else {\n // step-middle: jump at the horizontal midpoint.\n const mx = (a.x + b.x) / 2;\n out.push({ x: mx, y: a.y }, { x: mx, y: b.y }, b);\n }\n }\n return out;\n}\n\n/**\n * Catmull-Rom spline sampled into a polyline. A centripetal-ish\n * uniform Catmull-Rom gives the MD3 \"smooth\" look without the\n * overshoot of a naive cubic through sparse points.\n */\nfunction catmullRom(pts: Pt[]): Pt[] {\n const out: Pt[] = [pts[0]];\n for (let i = 0; i < pts.length - 1; i++) {\n const p0 = pts[i - 1] ?? pts[i];\n const p1 = pts[i];\n const p2 = pts[i + 1];\n const p3 = pts[i + 2] ?? p2;\n for (let s = 1; s <= CURVE_SAMPLES; s++) {\n const t = s / CURVE_SAMPLES;\n const t2 = t * t;\n const t3 = t2 * t;\n // Uniform Catmull-Rom basis (tension 0.5).\n const x =\n 0.5 *\n (2 * p1.x +\n (-p0.x + p2.x) * t +\n (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 +\n (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3);\n const y =\n 0.5 *\n (2 * p1.y +\n (-p0.y + p2.y) * t +\n (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +\n (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);\n out.push({ x, y });\n }\n }\n return out;\n}\n\n/**\n * Monotone cubic Hermite (Fritsch-Carlson tangents) sampled into\n * a polyline — never overshoots, so it won't invent peaks between\n * monotonically-increasing points (good for cumulative series).\n */\nfunction monotone(pts: Pt[]): Pt[] {\n const n = pts.length;\n const dx: number[] = [];\n const slope: number[] = [];\n for (let i = 0; i < n - 1; i++) {\n const h = pts[i + 1].x - pts[i].x || 1e-6;\n dx.push(h);\n slope.push((pts[i + 1].y - pts[i].y) / h);\n }\n // Tangents m[i].\n const m: number[] = [slope[0]];\n for (let i = 1; i < n - 1; i++) {\n if (slope[i - 1] * slope[i] <= 0) {\n m.push(0); // local extremum → flat tangent (no overshoot)\n } else {\n const w1 = 2 * dx[i] + dx[i - 1];\n const w2 = dx[i] + 2 * dx[i - 1];\n m.push((w1 + w2) / (w1 / slope[i - 1] + w2 / slope[i]));\n }\n }\n m.push(slope[n - 2]);\n\n const out: Pt[] = [pts[0]];\n for (let i = 0; i < n - 1; i++) {\n const p0 = pts[i];\n const p1 = pts[i + 1];\n const h = dx[i];\n for (let s = 1; s <= CURVE_SAMPLES; s++) {\n const t = s / CURVE_SAMPLES;\n const t2 = t * t;\n const t3 = t2 * t;\n // Hermite basis.\n const h00 = 2 * t3 - 3 * t2 + 1;\n const h10 = t3 - 2 * t2 + t;\n const h01 = -2 * t3 + 3 * t2;\n const h11 = t3 - t2;\n out.push({\n x: p0.x + t * h,\n y: h00 * p0.y + h10 * h * m[i] + h01 * p1.y + h11 * h * m[i + 1],\n });\n }\n }\n return out;\n}\n\n/**\n * Split a series' data into contiguous runs, breaking at `null`\n * gaps unless `connectNulls`. Each run is a list of\n * `{ index, value }` so the caller can map through scales. When\n * bridging, nulls are simply dropped (the line spans the gap).\n *\n * `undefined` is a HOLE, not a gap: the slot exists because some *other*\n * series was sampled there (see `utils/charts/xy.ts`). Holes never break a\n * run — the line runs straight through to this series' next real sample —\n * whereas an authored `null` still means \"measured, no value\".\n */\nexport function splitRuns(\n data: readonly (MdChartDataPoint | undefined)[],\n connectNulls: boolean,\n): { index: number; value: number }[][] {\n const runs: { index: number; value: number }[][] = [];\n let current: { index: number; value: number }[] = [];\n for (let i = 0; i < data.length; i++) {\n const v = data[i];\n if (v === undefined) continue;\n // null AND non-finite (NaN/±Infinity) are gaps — otherwise a stray NaN\n // becomes a real vertex at toPxY(NaN) and corrupts the polyline.\n if (v == null || !Number.isFinite(v)) {\n if (connectNulls) continue;\n if (current.length) {\n runs.push(current);\n current = [];\n }\n continue;\n }\n current.push({ index: i, value: v });\n }\n if (current.length) runs.push(current);\n return runs;\n}\n\n/**\n * Stack series' values. Returns, per series, an array of\n * `[base, top]` bands (null / non-finite preserved as `null`,\n * holes as `undefined` — see {@link splitRuns}).\n * Non-stacked series get `[0, value]`. Percentage rescales each\n * column so each sign fills its own 0..±100 envelope; silhouette\n * and wiggle centre the column around 0 (streamgraph baselines).\n */\nexport function stackSeries(\n seriesData: readonly (readonly (MdChartDataPoint | undefined)[])[],\n mode: MdChartStackMode,\n stackKeys: (string | undefined)[],\n): ([number, number] | null | undefined)[][] {\n const rows = Math.max(0, ...seriesData.map((s) => s.length));\n const out: ([number, number] | null | undefined)[][] = seriesData.map(() => []);\n // silhouette + wiggle both render a centred (streamgraph) baseline.\n const centred = mode === 'silhouette' || mode === 'wiggle';\n\n for (let r = 0; r < rows; r++) {\n // Column totals from FINITE values only: signed total centres streamgraphs;\n // per-sign totals normalise percentage so positives top out at +100% and\n // negatives bottom out at -100% (dividing by the signed total would flip\n // an all-negative column into positive bars and overshoot mixed columns).\n // Totals and cursors are kept PER STACK KEY, so several named stacks in one\n // column each start at the baseline and each normalise against their own\n // total. A chart with `stack: 'a'` and `stack: 'b'` series is two stacks\n // that happen to share a category, not one tall one.\n const signedTotal = new Map<string, number>();\n const posTotal = new Map<string, number>();\n const negTotal = new Map<string, number>();\n const add = (m: Map<string, number>, k: string, v: number) => m.set(k, (m.get(k) ?? 0) + v);\n for (let si = 0; si < seriesData.length; si++) {\n const v = seriesData[si][r];\n const k = stackKeys[si] ?? 'stacked';\n // An unstacked series sits on the baseline on its own; letting it into the\n // totals would renormalise everyone else's percentage against a bar that\n // is not part of the stack.\n if (k === '__unstacked__' || v == null || !Number.isFinite(v)) continue;\n add(signedTotal, k, v);\n if (v >= 0) add(posTotal, k, v);\n else add(negTotal, k, -v);\n }\n\n const posCursor = new Map<string, number>();\n const negCursor = new Map<string, number>();\n\n for (let si = 0; si < seriesData.length; si++) {\n const raw = seriesData[si][r];\n // A hole contributes nothing to the column and stays a hole downstream.\n if (raw === undefined) {\n out[si][r] = undefined;\n continue;\n }\n if (raw == null || !Number.isFinite(raw)) {\n out[si][r] = null;\n continue;\n }\n const key = stackKeys[si] ?? 'stacked';\n const stacked = mode !== 'none' && key !== '__unstacked__';\n if (!stacked) {\n out[si][r] = [0, raw];\n continue;\n }\n const base = centred ? -(signedTotal.get(key) ?? 0) / 2 : 0;\n if (!posCursor.has(key)) posCursor.set(key, base);\n if (!negCursor.has(key)) negCursor.set(key, base);\n const pos = posTotal.get(key) ?? 0;\n const neg = negTotal.get(key) ?? 0;\n let v = raw;\n if (mode === 'percentage') {\n v = raw >= 0 ? (pos > 0 ? (raw / pos) * 100 : 0) : neg > 0 ? (raw / neg) * 100 : 0;\n }\n if (v >= 0) {\n const c = posCursor.get(key)!;\n out[si][r] = [c, c + v];\n posCursor.set(key, c + v);\n } else {\n const c = negCursor.get(key)!;\n out[si][r] = [c + v, c];\n negCursor.set(key, c + v);\n }\n }\n }\n return out;\n}\n","/*\n * Chart engine — layout (spec → RenderScene)\n * ===========================================================\n * The brain: turns a resolved line-chart spec + theme + pixel\n * size into a backend-agnostic {@link RenderScene}. Owns axis\n * gutter sizing, scale + tick selection, series→polyline mapping\n * (via scale + geometry), gridlines, and text-item placement for\n * the DOM overlay. Pure — no DOM, no canvas — so it's unit-tested\n * on its numeric output.\n * ===========================================================\n */\n\nimport type { MdChartAnimation, MdChartAxisBreaks, MdChartAxisValue, MdChartCurve, MdChartDataPoint, MdChartLegendPosition, MdChartLineStyle, MdChartScaleType, MdChartStackMode, MdChartSymbol, MdChartTitleAlign } from '../types';\nimport {\n computeDomain,\n inBreak,\n logTicks,\n makeBrokenScale,\n makeCategoryScale,\n makeLinearScale,\n makeLogScale,\n niceLinearTicks,\n normalizeBreaks,\n resolveAxisBreaks,\n sectionedTicks,\n timeTicks,\n toNumeric,\n type BreakRange,\n type BrokenScale,\n type Scale,\n} from './scale';\nimport { decimateMinMax, interpolate, splitRuns, stackSeries, type Pt, clampToRect } from './geometry';\nimport type { EndLabel, GlyphMarker, HoverPoint, HoverSeries, LegendItem, Rect, RenderScene, SceneArea, SceneBand, SceneBar, SceneMarker, ScenePolyline, SceneSegment, TextItem } from './scene';\n\nexport interface EngineTheme {\n background: string;\n textColor: string;\n textColorMuted: string;\n axisLineColor: string;\n gridLineColor: string;\n /** Surface colour — the interior fill for hollow (open) markers. */\n surface: string;\n fontFamily: string;\n labelSize: number;\n titleSize: number;\n}\n\nexport interface LineSeriesSpec {\n label: string;\n /** Resolved CSS colour. */\n color: string;\n /**\n * Values aligned to `LineChartSpec.xValues`. `null` is a gap (breaks the\n * line unless `connectNulls`); `undefined` is a HOLE — a slot that exists\n * only because another series was sampled there, which the line bridges.\n * See `utils/charts/xy.ts`.\n */\n data: (MdChartDataPoint | undefined)[];\n /** `false` opts this series out of the area fill (a line over a band). */\n fill?: boolean;\n /** `false` draws no line for this series — fill only (streamgraphs). */\n stroke?: boolean;\n /**\n * Low/high band per row, aligned to `xValues`. When present the series is a\n * RANGE: it fills between the two edges instead of down to the baseline, is\n * left out of stacking (a band has no single value to stack), and is drawn\n * with no stroke so a line layered over it stays readable. `null` is a gap.\n */\n range?: ([number, number] | null | undefined)[];\n curve: MdChartCurve;\n connectNulls: boolean;\n showMarks: boolean;\n hidden: boolean;\n /** Marker for shown marks: a shape keyword, or an emoji/text glyph. Default circle. */\n symbol?: MdChartSymbol | (string & {});\n /** Per-index marker override (shape or emoji); shows even when marks are off. */\n pointSymbols?: Record<number, MdChartSymbol | string>;\n /** Draw markers only at these data indices (sparkline extremes/edges). */\n markIndices?: number[];\n /** Line style — `'dotted'` for average / reference lines. */\n dash?: 'solid' | 'dashed' | 'dotted';\n /** Index into `LineChartSpec.yAxes` this series is measured against (multi-axis\n * charts). Out-of-range / omitted falls back to axis 0. */\n yAxisIndex?: number;\n /** Draw the line solid up to this data index, then dotted after it (a shared\n * boundary point). For past-vs-forecast lines (the segment beyond \"now\"). */\n dashAfter?: number;\n /** Open (ring) markers — stroked in the series colour with a surface-filled\n * centre — instead of filled dots. */\n hollow?: boolean;\n /** Stroke width of the line, in px. Default 2.5. */\n lineWidth?: number;\n /** Marker RADIUS in px. Overrides the per-symbol default (circle 3.5, square/\n * diamond 4.2, triangle 4.6). */\n markSize?: number;\n}\n\n/** A vertical reference line drawn across the plot at an x position, with an\n * optional label (e.g. \"Current time\"). */\nexport interface MarkLineSpec {\n /** X position — a value/time axis value, or a (possibly fractional) index on a\n * category axis. */\n value: MdChartAxisValue;\n label?: string;\n /** Resolved colour. Default: the themed axis colour. */\n color?: string;\n dash?: 'solid' | 'dashed' | 'dotted';\n}\n\n/** One value (y) axis for a multi-axis chart. Each has its own domain, scale,\n * ticks and formatter; axes stack outward from the plot on their side. */\nexport interface ValueAxisSpec {\n scale: MdChartScaleType;\n min?: number;\n max?: number;\n formatter: (v: number) => string;\n label?: string;\n /** Which side to stack on. Default: axis 0 → left, the rest → right. */\n position?: 'left' | 'right';\n hidden?: boolean;\n hideTicks?: boolean;\n /** Resolved colour for this axis' line/labels/title. Omitted → themed (matches\n * the x-axis). */\n color?: string;\n /** Shaded ranges measured on this axis. */\n bands?: AxisBandSpec[];\n /** Stroke style for this axis' line + tick marks. Default solid. */\n dash?: MdChartLineStyle;\n /** Stroke style for the gridlines this axis draws (primary axis only, since\n * one grid is shared). Default solid. */\n gridDash?: MdChartLineStyle;\n}\n\n/** A highlighted x-range band (sparkline reference areas). */\nexport interface RefBand {\n /** Start data index (category axis). */\n from: number;\n /** End data index. */\n to: number;\n /** Fill colour (already alpha-composited). */\n color: string;\n}\n\n/** A shaded value range on one axis, with an optional label inside it. */\nexport interface AxisBandSpec {\n /** Band start / end in axis values (a data index on a category axis). */\n from: MdChartAxisValue;\n to: MdChartAxisValue;\n /** Resolved fill colour. Omitted → a faint tint of the axis colour. */\n color?: string;\n label?: string;\n labelAlign?: 'start' | 'center' | 'end';\n /** Resolved label colour. Omitted → the muted text colour. */\n labelColor?: string;\n}\n\nexport interface LineChartSpec {\n series: LineSeriesSpec[];\n title?: string;\n /** Sub-title, drawn under the title in the muted text colour. */\n subtitle?: string;\n /** Horizontal alignment of the title over the plot. Default 'start'. */\n titleAlign?: MdChartTitleAlign;\n /** Vertical reference lines drawn across the plot (e.g. a \"current time\" mark). */\n markLines?: MarkLineSpec[];\n xValues: MdChartAxisValue[];\n xScale: MdChartScaleType;\n xFormatter: (v: MdChartAxisValue) => string;\n xLabel?: string;\n xHidden?: boolean;\n xHideTicks?: boolean;\n /** Stroke style for the x axis' line + tick marks. Default solid. */\n xDash?: MdChartLineStyle;\n /** Stroke style for the vertical gridlines the x ticks draw. Default solid. */\n xGridDash?: MdChartLineStyle;\n yScale: MdChartScaleType;\n yMin?: number;\n yMax?: number;\n /** Formats y VALUES — tooltip rows, data labels, and (unless\n * `yTickFormatter` overrides it) the axis ticks. */\n yFormatter: (v: number) => string;\n /** Formats the y AXIS tick labels only, so an axis can read `15` while the\n * tooltip reads `15 m/s`. Falls back to `yFormatter`. */\n yTickFormatter?: (v: number) => string;\n yLabel?: string;\n yHidden?: boolean;\n yHideTicks?: boolean;\n /** Stroke style for the y axis' line + tick marks. Default solid. */\n yDash?: MdChartLineStyle;\n /** Stroke style for the horizontal gridlines the y ticks draw. Default solid. */\n yGridDash?: MdChartLineStyle;\n yReverse?: boolean;\n /** Multiple independent value axes. When present (non-empty), each series is\n * measured against `yAxes[series.yAxisIndex ?? 0]` and the axes stack outward\n * on their side. Supersedes the single-axis `y*` fields. */\n yAxes?: ValueAxisSpec[];\n stack: MdChartStackMode;\n area: boolean;\n /** Area-fill top-stop opacity (0..1). Default 0.35. */\n fillOpacity?: number;\n /** Legend anchor, or `'none'` to hide it. */\n legend?: MdChartLegendPosition | 'none';\n /**\n * Measured legend extent in px (height for top/bottom, width for left/right).\n * The engine fills this in on a second pass so a wrapped multi-row legend\n * reserves its real size instead of the first-pass estimate.\n */\n legendExtent?: number;\n /** Sparkline mode: edge-to-edge, no axes / grid / title / legend. */\n compact?: boolean;\n /** Highlighted x-range bands (sparkline reference areas). */\n refBands?: RefBand[];\n /** Shaded ranges on the x axis (vertical bands across the plot). */\n xBands?: AxisBandSpec[];\n /** Ranges cut out of the x axis. */\n xBreaks?: MdChartAxisBreaks;\n /** Ranges cut out of the single y axis. Multi-axis charts break per axis. */\n yBreaks?: MdChartAxisBreaks;\n /** Shaded ranges on the single y axis (horizontal bands across the plot).\n * Multi-axis charts declare bands per axis on {@link ValueAxisSpec}. */\n yBands?: AxisBandSpec[];\n /** Horizontal gridlines (at y ticks). Default true. */\n gridY?: boolean;\n /** Vertical gridlines (at x ticks). Default false. */\n gridX?: boolean;\n /** Small perpendicular tick marks on the x/y axes. Default false. */\n axisTicks?: boolean;\n /** Print each point's value as a data label beside the marker. Default false. */\n showLabels?: boolean;\n /** Label each series at its last point (a marker + the series name), so the\n * name follows the end of the line — for racing / progression charts. */\n seriesLabels?: boolean;\n /** Transpose the axes: the independent axis (xValues) runs vertically and the\n * value axis horizontally — a spline that's a function of the vertical axis\n * (e.g. temperature by altitude). */\n inverted?: boolean;\n /** Entry-animation variant played on first render. Default 'expressive'. */\n animation?: MdChartAnimation;\n /** Entry-animation duration override (ms); ≤ 0 disables. */\n animationDuration?: number;\n /** Legacy on/off flag (pre-variant). `false` → no animation. */\n animate?: boolean;\n}\n\n/** Whether a hover dot has anything to sit on: a drawn line, or markers. */\nfunction hasAnchor(s: LineSeriesSpec): boolean {\n const strokes = !s.range && s.stroke !== false;\n const marks = s.showMarks || !!s.markIndices?.length || !!s.pointSymbols;\n return strokes || marks;\n}\n\n/** Length (px) of the perpendicular axis tick marks. */\nconst AXIS_TICK_LEN = 5;\n\n/** Rough text width without a canvas — good enough for gutter sizing. */\nfunction approxWidth(text: string, fontSize: number): number {\n return text.length * fontSize * 0.58;\n}\n\n/** Estimate how many rows a horizontal (top/bottom) legend wraps into, so the\n * reserved band grows with the series count instead of overflowing the plot. */\nexport function estimateLegendRows(labels: string[], fontSize: number, availW: number): number {\n let rows = 1;\n let rowW = 0;\n for (const label of labels) {\n const iw = approxWidth(label, fontSize) + 28; // swatch + gaps + chip padding\n if (rowW > 0 && rowW + iw > availW) {\n rows++;\n rowW = iw;\n } else {\n rowW += iw;\n }\n }\n return rows;\n}\n\n/** Map a line style to a px on/off dash pattern (round-capped). */\nexport function dashPattern(dash: MdChartLineStyle | undefined, width = 1): number[] | undefined {\n if (dash === 'dashed') return [width * 3.5, width * 3];\n if (dash === 'dotted') return [Math.max(1, width * 0.4), width * 2.6];\n return undefined;\n}\n\n/** The break tear's shape: a smooth sine wave, not a hard sawtooth. */\nconst BREAK_WAVE_LEN = 30; // wavelength (px) — one full undulation\nconst BREAK_WAVE_STEP = 3; // polyline sampling step (px); small → the sine reads smooth, not faceted\nconst BREAK_WAVE_AMP = 4; // half the wave's height (px), clamped to the gap\n\n/**\n * The break drawn ACROSS the whole plot, not just as a mark on the axis: a\n * smooth wave \"tear\" spanning the plot at the cut, so the discontinuity reads\n * over the bars themselves. For a y-axis break (a vertical chart) it runs\n * horizontally through the gap; for an x-axis break (a horizontal chart) it runs\n * vertically. A sine — not a sawtooth — so it reads as a soft, deliberate seam\n * (Material) rather than a jagged technical mark.\n *\n * `gapLo`/`gapHi` are the near/far pixel edges of the cut ON the value axis;\n * `spanFrom`/`spanTo` bound the OTHER axis (the plot's width for a horizontal\n * tear, its height for a vertical one). The wave undulates about the gap's centre\n * so it sits in the empty seam the split bars leave. Emitted as many short\n * segments; `renderScene` strokes each, and on a gentle curve the butt-cap joints\n * are sub-pixel, so it reads as one continuous wave.\n */\nexport function breakBandSegments(\n axis: 'x' | 'y',\n gapLo: number,\n gapHi: number,\n spanFrom: number,\n spanTo: number,\n color: string,\n): SceneSegment[] {\n const segs: SceneSegment[] = [];\n const len = spanTo - spanFrom;\n if (len <= 0) return segs;\n const mid = (gapLo + gapHi) / 2;\n const amp = Math.min(BREAK_WAVE_AMP, (gapHi - gapLo) / 2);\n const n = Math.max(4, Math.round(len / BREAK_WAVE_STEP));\n // Sample the sine at each step; `off` is the perpendicular offset from the\n // gap centre, `p` the position along the span.\n const at = (i: number) => {\n const p = spanFrom + (len * i) / n;\n return { p, off: mid + amp * Math.sin((p / BREAK_WAVE_LEN) * Math.PI * 2) };\n };\n let prev = at(0);\n for (let i = 1; i <= n; i++) {\n const cur = at(i);\n segs.push(\n axis === 'y'\n ? { x1: prev.p, y1: prev.off, x2: cur.p, y2: cur.off, color, width: 1.5 }\n : { x1: prev.off, y1: prev.p, x2: cur.off, y2: cur.p, color, width: 1.5 },\n );\n prev = cur;\n }\n return segs;\n}\n\n/**\n * An axis line split around its cuts — one segment per surviving section, so\n * the line is visibly interrupted where the scale jumps.\n */\nexport function axisLineWithBreaks(\n axis: 'x' | 'y',\n from: number,\n to: number,\n along: number,\n breaks: readonly { px: number; gap: number }[],\n color: string,\n dash?: number[],\n): SceneSegment[] {\n const segs: SceneSegment[] = [];\n let cursor = from;\n const seg = (a: number, b: number): SceneSegment =>\n axis === 'y'\n ? { x1: along, y1: a, x2: along, y2: b, color, width: 1, dash }\n : { x1: a, y1: along, x2: b, y2: along, color, width: 1, dash };\n for (const b of breaks) {\n const start = from + b.px;\n if (start > cursor) segs.push(seg(cursor, start));\n cursor = start + b.gap;\n }\n if (to > cursor) segs.push(seg(cursor, to));\n return segs;\n}\n\n/** Inset of a band's label from the band's near edge, in px. */\nconst BAND_LABEL_PAD = 8;\n\n/**\n * Band rects + their labels for one axis.\n *\n * `toPx` maps an axis value to its pixel on that axis; `plot` bounds the\n * result, so a band that runs off the visible domain is clipped to the plot\n * rather than painted outside it. Bands whose range falls entirely outside are\n * dropped. Horizontal bands (a y axis) span the plot's width and vice versa.\n */\nfunction buildAxisBands(\n bands: AxisBandSpec[] | undefined,\n axis: 'x' | 'y',\n toPx: (value: MdChartAxisValue) => number,\n plot: Rect,\n theme: EngineTheme,\n keyPrefix: string,\n): { rects: SceneBand[]; labels: TextItem[] } {\n const rects: SceneBand[] = [];\n const labels: TextItem[] = [];\n if (!bands?.length) return { rects, labels };\n const horizontal = axis === 'y';\n const lo = horizontal ? plot.y : plot.x;\n const hi = horizontal ? plot.y + plot.height : plot.x + plot.width;\n\n bands.forEach((b, i) => {\n const a = toPx(b.from);\n const z = toPx(b.to);\n if (!Number.isFinite(a) || !Number.isFinite(z)) return;\n const start = Math.max(lo, Math.min(a, z));\n const end = Math.min(hi, Math.max(a, z));\n if (end <= start) return; // entirely outside the visible domain\n const color = b.color ?? hexToRgba(theme.axisLineColor, 0.07);\n rects.push(\n horizontal\n ? { x: plot.x, y: start, w: plot.width, h: end - start, color }\n : { x: start, y: plot.y, w: end - start, h: plot.height, color },\n );\n if (!b.label) return;\n const align = b.labelAlign ?? 'start';\n // Along the band: start / centre / end of the plot's other axis.\n const along =\n align === 'center'\n ? (horizontal ? plot.x + plot.width / 2 : plot.y + plot.height / 2)\n : align === 'end'\n ? (horizontal ? plot.x + plot.width - BAND_LABEL_PAD : plot.y + plot.height - BAND_LABEL_PAD)\n : (horizontal ? plot.x + BAND_LABEL_PAD : plot.y + BAND_LABEL_PAD);\n labels.push({\n x: horizontal ? along : start + BAND_LABEL_PAD,\n y: horizontal ? start + BAND_LABEL_PAD : along,\n text: b.label,\n color: b.labelColor ?? theme.textColorMuted,\n fontSize: theme.labelSize,\n align: horizontal ? (align === 'center' ? 'center' : align) : 'start',\n baseline: horizontal ? 'top' : align === 'center' ? 'middle' : align === 'end' ? 'bottom' : 'top',\n key: `${keyPrefix}-${i}`,\n });\n });\n return { rects, labels };\n}\n\nfunction hexToRgba(color: string, alpha: number): string {\n if (color.startsWith('#')) {\n let hex = color.slice(1);\n if (hex.length === 3) hex = hex.split('').map((c) => c + c).join('');\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n if (color.startsWith('rgb(')) return color.replace(/^rgb\\(/, 'rgba(').replace(/\\)$/, `, ${alpha})`);\n return color;\n}\n\nexport function computeLayout(spec: LineChartSpec, theme: EngineTheme, width: number, height: number): RenderScene {\n if (spec.inverted) return computeInvertedLayout(spec, theme, width, height);\n if (spec.yAxes && spec.yAxes.length > 0) return computeMultiAxisLayout(spec, theme, width, height);\n const visible = spec.series.filter((s) => !s.hidden);\n const rows = spec.xValues.length || Math.max(0, ...spec.series.map((s) => s.data.length));\n\n // ── stacked bands → the value extent that drives the y domain ──\n // A range series carries its own band, so it is excluded from the stack: it\n // has no single value to add to a column, and letting its `high` land in the\n // totals would push every stacked layer above it up by the band's top edge.\n const stackKeys = spec.series.map((s) => (spec.stack !== 'none' && !s.range ? 'stacked' : '__unstacked__'));\n // Hidden series contribute empty data so they don't reserve a band — otherwise\n // a visible series above a toggled-off one keeps a gap and the domain (which\n // excludes hidden series) disagrees with the stack offsets.\n const bands = stackSeries(\n spec.series.map((s) => (s.hidden ? [] : s.data)),\n spec.stack,\n stackKeys,\n );\n // A range series' band IS its data — substitute it before the domain is taken\n // below, so the axis covers both edges rather than just the drawn top.\n spec.series.forEach((s, si) => {\n if (!s.range || s.hidden) return;\n bands[si] = s.range.map((r) => (r ? ([Math.min(r[0], r[1]), Math.max(r[0], r[1])] as [number, number]) : r));\n });\n const yVals: number[] = [];\n spec.series.forEach((s, si) => {\n if (s.hidden) return;\n bands[si].forEach((b) => {\n if (b) {\n yVals.push(b[0], b[1]);\n }\n });\n });\n\n const yDomain = computeDomain(yVals, {\n min: spec.yMin,\n max: spec.yMax,\n scale: spec.yScale,\n includeZero: spec.stack !== 'none' || spec.yScale === 'value',\n });\n\n // ── axis breaks (resolved before ticks so cut-out ticks never render) ──\n const xNums = spec.xValues.map((v) => toNumeric(v, spec.xScale));\n const xDomain = computeDomain(xNums, { scale: spec.xScale });\n // Sparklines are deliberately chrome-free — no break marks to read, so no cuts.\n const noBreaks = { ranges: [] as BreakRange[], sizing: 'equal' as const };\n const yFound = spec.compact ? noBreaks : resolveAxisBreaks(spec.yBreaks, yVals, spec.yScale);\n const xFound =\n spec.compact || spec.xScale === 'category' ? noBreaks : resolveAxisBreaks(spec.xBreaks, xNums, spec.xScale);\n // Detection runs on the DATA; the axis then rejects the cuts its domain can't\n // take (one starting at the very bottom would just shift the axis up). Settle\n // that here, once, so the ticks, the gridlines, the split runs and the scale\n // all work from the same set — a cut the scale drops used to keep sectioning\n // the ticks, which ruled one band and left the rest of the axis bare.\n const yBreaks = { ...yFound, ranges: normalizeBreaks(yFound.ranges, yDomain) };\n const xBreaks = { ...xFound, ranges: normalizeBreaks(xFound.ranges, xDomain) };\n\n // ── y ticks + gutter sizing (need widest y label to inset left) ──\n const yTickVals = sectionedTicks(yDomain, yBreaks.ranges, spec.yScale, 6).filter(\n (t) => !inBreak(yBreaks.ranges, t),\n );\n const yTickLabels = yTickVals.map((v) => (spec.yTickFormatter ?? spec.yFormatter)(v));\n const maxYLabelW = spec.yHidden || spec.yHideTicks ? 0 : Math.max(0, ...yTickLabels.map((t) => approxWidth(t, theme.labelSize)));\n\n const subtitleH = spec.subtitle ? theme.labelSize + 4 : 0;\n const titleH = spec.title ? theme.titleSize + 10 + subtitleH : 0;\n const xLabelH = spec.xHidden || spec.xHideTicks ? 0 : theme.labelSize + 8;\n const yAxisLabelW = spec.yLabel ? theme.labelSize + 6 : 0;\n const xAxisLabelH = spec.xLabel ? theme.labelSize + 6 : 0;\n\n // A top/bottom legend gets a reserved band; a left/right legend gets a\n // reserved side gutter (its column is a vertically-centred list) so it never\n // overlaps the plot or the y-axis labels.\n const legendActive = !!spec.legend && spec.legend !== 'none' && spec.series.length > 1;\n const legendSide = legendActive && (spec.legend === 'left' || spec.legend === 'right');\n const legendAtBottom = legendActive && !legendSide && spec.legend!.startsWith('bottom');\n const legendTopRow = legendActive && !legendSide && !legendAtBottom;\n // A horizontal legend wraps into as many rows as the labels need — reserve\n // that height so many-series legends don't spill onto the plot.\n const legendRows = legendTopRow || legendAtBottom ? estimateLegendRows(spec.series.map((s) => s.label), theme.labelSize, width * 0.86) : 1;\n // Second-pass measured extent wins over the first-pass estimate.\n const legendBandH = spec.legendExtent != null && (legendTopRow || legendAtBottom) ? spec.legendExtent + 8 : legendRows * (theme.labelSize + 8) + 6;\n const legendBandTop = legendTopRow ? legendBandH : 0;\n const legendBandBottom = legendAtBottom ? legendBandH : 0;\n const legendSideW = legendSide ? (spec.legendExtent != null ? spec.legendExtent + 16 : Math.max(0, ...spec.series.map((s) => approxWidth(s.label, theme.labelSize))) + 34) : 0;\n // Room on the right for end-of-line series-name labels.\n const seriesLabelW = spec.seriesLabels ? Math.max(0, ...spec.series.filter((s) => !s.hidden).map((s) => approxWidth(s.label, theme.labelSize))) + 20 : 0;\n\n // Sparkline mode fills its host edge-to-edge — no gutters for chrome. But a\n // marker at the first / last / extreme point sits ON that edge, and its radius\n // spills past it and is CLIPPED. Reserve the widest drawn marker's radius (+1px)\n // so the dots stay whole; with no markers it stays the tight 2px.\n const compact = !!spec.compact;\n const markPad = compact\n ? Math.max(\n 2,\n ...spec.series\n .filter((s) => !s.hidden && (s.showMarks || (s.markIndices?.length ?? 0) > 0 || s.pointSymbols))\n .map((s) => markerRadius(s.symbol as MdChartSymbol | undefined, s.markSize) + 2),\n )\n : 0;\n const padTop = compact ? markPad : titleH + 8 + legendBandTop;\n const padRight = compact ? markPad : 12 + approxWidth(yTickLabels[yTickLabels.length - 1] ?? '', theme.labelSize) / 2 + (spec.legend === 'right' ? legendSideW : 0) + seriesLabelW;\n const padBottom = compact ? markPad : xLabelH + xAxisLabelH + 6 + legendBandBottom;\n const padLeft = compact ? markPad : maxYLabelW + 10 + yAxisLabelW + (spec.legend === 'left' ? legendSideW : 0);\n\n const plot = {\n x: padLeft,\n y: padTop,\n width: Math.max(1, width - padLeft - padRight),\n height: Math.max(1, height - padTop - padBottom),\n };\n\n // ── scales (break-aware: a cut costs its gap in px, not its true width) ──\n const x: Scale =\n spec.xScale === 'category'\n ? makeCategoryScale(rows, plot.width, true)\n : makeBrokenScale(xDomain, plot.width, spec.xScale, xBreaks.ranges, xBreaks.sizing);\n const y: Scale = makeBrokenScale(yDomain, plot.height, spec.yScale, yBreaks.ranges, yBreaks.sizing);\n\n // Data value → pixel Y within the plot (top-origin: bigger value = higher = smaller y).\n const toPxY = (v: number) => plot.y + plot.height - y.scale(v);\n const toPxX = (i: number) =>\n plot.x + (spec.xScale === 'category' ? x.scale(i) : x.scale(toNumeric(spec.xValues[i], spec.xScale)));\n\n // ── axis bands (behind everything; their labels join the text overlay) ──\n // Named `axisBands` because `bands` below is the stacked-value bands.\n const bandLabels: TextItem[] = [];\n const axisBands: SceneBand[] = [];\n if (!compact) {\n const onY = buildAxisBands(spec.yBands, 'y', (v) => toPxY(toNumeric(v, spec.yScale)), plot, theme, 'yband');\n const onX = buildAxisBands(\n spec.xBands,\n 'x',\n (v) => plot.x + x.scale(spec.xScale === 'category' ? Number(v) : toNumeric(v, spec.xScale)),\n plot,\n theme,\n 'xband',\n );\n axisBands.push(...onY.rects, ...onX.rects);\n bandLabels.push(...onY.labels, ...onX.labels);\n }\n\n const gridlines: SceneSegment[] = [];\n const axisLines: SceneSegment[] = [];\n // Chrome stroke styles — solid unless the axis asked for dashed/dotted. The\n // break mark stays solid either way: it is a symbol, not a line.\n const yGridDash = dashPattern(spec.yGridDash, 1);\n const xGridDash = dashPattern(spec.xGridDash, 1);\n const yAxisDash = dashPattern(spec.yDash, 1);\n const xAxisDash = dashPattern(spec.xDash, 1);\n if (!spec.yHidden && !compact) {\n for (const t of yTickVals) {\n const py = toPxY(t);\n if (spec.gridY !== false) {\n gridlines.push({ x1: plot.x, y1: py, x2: plot.x + plot.width, y2: py, color: theme.gridLineColor, width: 1, dash: yGridDash });\n }\n if (spec.axisTicks) {\n axisLines.push({ x1: plot.x - AXIS_TICK_LEN, y1: py, x2: plot.x, y2: py, color: theme.axisLineColor, width: 1, dash: yAxisDash });\n }\n }\n // The y axis runs bottom-up in data space, so a cut at scale-offset `px`\n // sits `px` above the plot's bottom edge.\n const yCuts = ((y as BrokenScale).breaks ?? []).map((b) => ({ px: plot.height - b.px - b.gap, gap: b.gap }));\n axisLines.push(\n ...axisLineWithBreaks('y', plot.y, plot.y + plot.height, plot.x, yCuts, theme.axisLineColor, yAxisDash),\n );\n // The tear runs HORIZONTALLY across the whole plot width at the y cut.\n for (const c of yCuts) {\n axisLines.push(...breakBandSegments('y', plot.y + c.px, plot.y + c.px + c.gap, plot.x, plot.x + plot.width, theme.axisLineColor));\n }\n }\n if (!spec.xHidden && !compact) {\n const yb = plot.y + plot.height;\n const xCuts = ((x as BrokenScale).breaks ?? []).map((b) => ({ px: b.px, gap: b.gap }));\n axisLines.push(...axisLineWithBreaks('x', plot.x, plot.x + plot.width, yb, xCuts, theme.axisLineColor, xAxisDash));\n // The tear runs VERTICALLY up the whole plot height at the x cut.\n for (const c of xCuts) {\n axisLines.push(...breakBandSegments('x', plot.x + c.px, plot.x + c.px + c.gap, plot.y, plot.y + plot.height, theme.axisLineColor));\n }\n }\n\n // ── series → polylines / areas / markers ──\n const lines: ScenePolyline[] = [];\n const areas: SceneArea[] = [];\n const markers: SceneMarker[] = [];\n const glyphs: GlyphMarker[] = [];\n const endLabelCands: EndLabel[] = [];\n const hoverPoints: HoverSeries[] = [];\n const baselineY = toPxY(Math.max(yDomain[0], 0));\n\n /**\n * A cut has no coordinates, so nothing may be drawn across it: split a run\n * wherever consecutive points sit on opposite sides of a break (or one of\n * them lands inside it, in which case that point is dropped entirely).\n */\n const splitAtBreaks = (run: { index: number; value: number }[]) => {\n if (!yBreaks.ranges.length && !xBreaks.ranges.length) return [run];\n const out: { index: number; value: number }[][] = [];\n let current: { index: number; value: number }[] = [];\n let prevSection = '';\n for (const pt of run) {\n const xv = xNums[pt.index];\n if (inBreak(yBreaks.ranges, pt.value) || (xv !== undefined && inBreak(xBreaks.ranges, xv))) {\n if (current.length) out.push(current);\n current = [];\n prevSection = '';\n continue;\n }\n // Which section of each axis this point falls in; a change means the\n // pair straddles a cut.\n const section =\n yBreaks.ranges.filter((b) => pt.value >= b.to).length +\n ':' +\n xBreaks.ranges.filter((b) => xv !== undefined && xv >= b.to).length;\n if (prevSection && section !== prevSection && current.length) {\n out.push(current);\n current = [];\n }\n prevSection = section;\n current.push(pt);\n }\n if (current.length) out.push(current);\n return out;\n };\n\n spec.series.forEach((s, si) => {\n if (s.hidden) return;\n const runs = splitRuns(\n // A hole stays a hole (the line bridges it); a null band is a real gap.\n bands[si].map((b) => (b === undefined ? undefined : b ? b[1] : null)),\n s.connectNulls,\n ).flatMap(splitAtBreaks);\n const byIndex: Record<number, HoverPoint> = {};\n let endPt: Pt | undefined;\n for (const run of runs) {\n if (!run.length) continue;\n const raw: Pt[] = run.map((r) => ({ x: toPxX(r.index), y: toPxY(r.value) }));\n endPt = raw[raw.length - 1];\n run.forEach((r, k) => {\n // Tooltip shows the RAW datum; y follows the drawn (stacked) top. The\n // hover highlight mirrors the point's marker (per-point override, else\n // the series symbol, else a circle) instead of always a circle.\n const hoverSym = s.pointSymbols?.[r.index] ?? (s.symbol && s.symbol !== 'none' ? s.symbol : 'circle');\n const band = s.range ? (bands[si][r.index] as [number, number] | null | undefined) : undefined;\n byIndex[r.index] = {\n x: raw[k].x,\n y: raw[k].y,\n value: (s.data[r.index] as number) ?? r.value,\n symbol: hoverSym,\n // Both edges, so the tooltip reads the band rather than only its top.\n ...(band ? { low: band[0], high: band[1] } : {}),\n };\n });\n const poly = clampToRect(interpolate(decimateMinMax(raw, plot.width), s.curve), plot.x, plot.y, plot.width, plot.height);\n // `dashAfter`: draw solid up to the boundary index, dotted after it (the\n // boundary point is shared), for past-vs-forecast lines.\n const splitAt = s.dashAfter != null ? run.findIndex((r) => r.index >= s.dashAfter!) : -1;\n const lw = s.lineWidth ?? 2.5;\n // A range series is a band, not a line: stroking its top edge would read\n // as the series' value, which is exactly what a range does not have.\n if (s.range || s.stroke === false) {\n /* fill only — a range band has no single value to trace, and a\n streamgraph layer has no meaningful top edge on a free baseline */\n } else if (splitAt > 0 && splitAt < run.length) {\n lines.push({ points: clampToRect(interpolate(decimateMinMax(raw.slice(0, splitAt + 1), plot.width), s.curve), plot.x, plot.y, plot.width, plot.height), color: s.color, width: lw, dash: dashPattern(s.dash, lw), seriesIndex: si });\n lines.push({ points: clampToRect(interpolate(decimateMinMax(raw.slice(splitAt), plot.width), s.curve), plot.x, plot.y, plot.width, plot.height), color: s.color, width: lw, dash: dashPattern('dotted', lw), seriesIndex: si });\n } else if (splitAt === 0) {\n lines.push({ points: poly, color: s.color, width: lw, dash: dashPattern('dotted', lw), seriesIndex: si });\n } else {\n lines.push({ points: poly, color: s.color, width: lw, dash: dashPattern(s.dash, lw), seriesIndex: si });\n }\n if (spec.area && s.fill !== false) {\n const fo = spec.fillOpacity ?? 0.35;\n // Stacked layers and range bands fill only their own band (top → base);\n // overlapping (unstacked) areas fill down to the global zero line.\n const basePoints =\n spec.stack !== 'none' || s.range\n ? clampToRect(\n interpolate(\n run.map((r) => ({ x: toPxX(r.index), y: toPxY((bands[si][r.index] as [number, number])[0]) })),\n s.curve,\n ),\n plot.x,\n plot.y,\n plot.width,\n plot.height,\n )\n : undefined;\n areas.push({\n points: poly,\n baselineY,\n colorTop: hexToRgba(s.color, fo),\n // A BAND — a stacked layer or a range — is read as one solid extent,\n // so it keeps an even tint. The fade-to-nothing gradient belongs only\n // to a fill that runs to the baseline, where it stops the fill from\n // competing with the axis; inside a stack it just makes every layer\n // bleed into the one below and the bands stop reading as separate.\n colorBottom: basePoints ? hexToRgba(s.color, fo) : hexToRgba(s.color, Math.max(0.02, fo * 0.06)),\n basePoints,\n seriesIndex: si,\n });\n }\n // Markers: an explicit per-point override (shape or emoji) always shows;\n // otherwise the series symbol shows where marks are enabled. Emoji / text\n // symbols route to the DOM glyph overlay, which can draw a glyph.\n const markSet = s.markIndices ? new Set(s.markIndices) : null;\n run.forEach((r, k) => {\n const idx = r.index;\n const override = s.pointSymbols?.[idx];\n const showDefault = markSet ? markSet.has(idx) : s.showMarks;\n const sym = override ?? (showDefault ? s.symbol ?? 'circle' : undefined);\n if (!sym || sym === 'none') return;\n const pt = raw[k];\n if (isShapeSymbol(sym)) {\n markers.push({ x: pt.x, y: pt.y, r: markerRadius(sym, s.markSize), color: s.color, symbol: sym, seriesIndex: si, hollow: s.hollow, fill: s.hollow ? theme.surface : undefined });\n } else {\n glyphs.push({ x: pt.x, y: pt.y, text: sym, size: GLYPH_SIZE });\n }\n });\n // Data labels — each point's value just above its marker. Routed through\n // the glyph layer (not the static text overlay) so they lift / reveal /\n // fade WITH the point during the intro animation.\n if (spec.showLabels && !compact) {\n run.forEach((r, k) => {\n // Above the point by default, FLIPPED below when there is no room for\n // it there. The topmost point sits on the plot's ceiling, so a label\n // hung above it lands outside the plot and collides with the title —\n // nothing reserves headroom for these, so the label gives way.\n const above = raw[k].y - 9 - theme.labelSize >= plot.y;\n glyphs.push({\n x: raw[k].x,\n y: raw[k].y,\n text: spec.yFormatter((s.data[r.index] as number) ?? r.value),\n size: theme.labelSize,\n label: {\n color: theme.textColor,\n weight: 600,\n dx: 0,\n dy: above ? -9 : 9,\n anchorX: '-50%',\n anchorY: above ? '-100%' : '0',\n },\n });\n });\n }\n }\n // End-of-line series label — a marker (always) + the series name at the last\n // point. The name is collision-managed below so stacked ends don't overlap.\n if (spec.seriesLabels && endPt && !compact) {\n markers.push({ x: endPt.x, y: endPt.y, r: 4, color: s.color, symbol: 'circle', seriesIndex: si });\n endLabelCands.push({ key: `sl-${si}`, x: endPt.x, y: endPt.y, text: s.label, color: theme.textColor, size: theme.labelSize + 1, visible: true });\n }\n hoverPoints.push({ seriesIndex: si, color: s.color, label: s.label, byIndex, values: s.data, unanchored: !hasAnchor(s) });\n });\n\n // Hide end labels that would overlap a higher one (greedy top-down) so they\n // fade out when the line ends cluster and back in as they fan apart.\n if (endLabelCands.length > 1) {\n const minGap = theme.labelSize + 5;\n let lastY = -Infinity;\n for (const c of [...endLabelCands].sort((a, b) => a.y - b.y)) {\n c.visible = c.y - lastY >= minGap;\n if (c.visible) lastY = c.y;\n }\n }\n\n // ── reference bands (sparkline highlight windows) → translucent rects ──\n const bars: SceneBar[] = [];\n if (spec.refBands) {\n for (const b of spec.refBands) {\n const bx1 = toPxX(b.from);\n const bx2 = toPxX(b.to);\n const bx = Math.min(bx1, bx2);\n const bw = Math.abs(bx2 - bx1);\n if (bw <= 0) continue;\n bars.push({ x: bx, y: plot.y, w: bw, h: plot.height, color: b.color, radius: [0, 0, 0, 0], seriesIndex: -1, dataIndex: -1 });\n }\n }\n\n // ── overlay text items ──\n // Band labels lead, so a tick label drawn at the same spot wins the overlay.\n const texts: TextItem[] = [...bandLabels];\n if (spec.title && !compact) {\n const tt = titlePlacement(spec.titleAlign, plot.x, plot.width);\n texts.push({\n x: tt.x,\n y: legendBandTop + 6,\n text: spec.title,\n color: theme.textColor,\n fontSize: theme.titleSize,\n fontWeight: 600,\n align: tt.align,\n baseline: 'top',\n key: 'title',\n });\n if (spec.subtitle) {\n texts.push({\n x: tt.x,\n y: legendBandTop + 6 + theme.titleSize + 4,\n text: spec.subtitle,\n color: theme.textColorMuted,\n fontSize: theme.labelSize,\n align: tt.align,\n baseline: 'top',\n key: 'subtitle',\n });\n }\n }\n // ── mark lines (vertical reference lines, e.g. \"current time\") ──\n if (spec.markLines && !compact) {\n for (const ml of spec.markLines) {\n const mv = spec.xScale === 'category' ? Number(ml.value) : toNumeric(ml.value, spec.xScale);\n const px = plot.x + x.scale(mv);\n if (!Number.isFinite(px) || px < plot.x - 1 || px > plot.x + plot.width + 1) continue;\n gridlines.push({ x1: px, y1: plot.y, x2: px, y2: plot.y + plot.height, color: ml.color ?? theme.axisLineColor, width: 1.5, dash: dashPattern(ml.dash ?? 'dashed', 1.5) });\n if (ml.label) {\n texts.push({ x: px + 4, y: plot.y + 2, text: ml.label, color: theme.textColorMuted, fontSize: theme.labelSize, align: 'start', baseline: 'top', key: `markline-${Math.round(px)}` });\n }\n }\n }\n if (!spec.yHidden && !spec.yHideTicks && !compact) {\n yTickVals.forEach((t, i) => {\n texts.push({\n x: plot.x - 8,\n y: toPxY(t),\n text: yTickLabels[i],\n color: theme.textColorMuted,\n fontSize: theme.labelSize,\n align: 'end',\n baseline: 'middle',\n key: `yt-${i}`,\n });\n });\n }\n // xPositions always populate (hover/click hit-testing needs them, even in\n // compact sparkline mode); only the tick *labels* are chrome we can skip.\n const xPositions: number[] = [];\n for (let i = 0; i < rows; i++) xPositions.push(toPxX(i));\n\n // Tick anchors: a category axis labels its points (thinned to fit), while a\n // value / log / time axis labels nice round values — so a dense or irregularly\n // sampled axis prints ~one label per 90px instead of one per data point.\n const xAnchors: { px: number; text: string; key: string }[] = [];\n if (spec.xScale === 'category') {\n const step = Math.max(1, Math.ceil(rows / Math.max(1, Math.floor(plot.width / 60))));\n for (let i = 0; i < rows; i += step) {\n xAnchors.push({ px: xPositions[i], text: spec.xFormatter(spec.xValues[i] ?? i), key: `xt-${i}` });\n }\n } else if (rows) {\n const xd = computeDomain(xNums, { scale: spec.xScale });\n const target = Math.max(2, Math.floor(plot.width / 90));\n const xTicks = sectionedTicks(xd, xBreaks.ranges, spec.xScale, target).filter(\n (t) => !inBreak(xBreaks.ranges, t),\n );\n for (const tv of xTicks) {\n const px = plot.x + x.scale(tv);\n if (px < plot.x - 1 || px > plot.x + plot.width + 1) continue;\n // Format with the ORIGINAL typed value: a time axis needs a Date, not the\n // raw epoch number (a Date formatter would otherwise throw).\n xAnchors.push({ px, text: spec.xFormatter(spec.xScale === 'time' ? new Date(tv) : tv), key: `xt-${tv}` });\n }\n }\n if (!compact) {\n for (const a of xAnchors) {\n // Vertical gridline at each shown x tick (skip the y-axis edge).\n if (spec.gridX && a.px > plot.x + 0.5) {\n gridlines.push({ x1: a.px, y1: plot.y, x2: a.px, y2: plot.y + plot.height, color: theme.gridLineColor, width: 1, dash: xGridDash });\n }\n // Perpendicular tick mark below the x-axis.\n if (spec.axisTicks && !spec.xHidden) {\n const yb = plot.y + plot.height;\n axisLines.push({ x1: a.px, y1: yb, x2: a.px, y2: yb + AXIS_TICK_LEN, color: theme.axisLineColor, width: 1, dash: xAxisDash });\n }\n if (spec.xHidden || spec.xHideTicks) continue;\n texts.push({\n x: a.px,\n y: plot.y + plot.height + 6,\n text: a.text,\n color: theme.textColorMuted,\n fontSize: theme.labelSize,\n align: 'center',\n baseline: 'top',\n key: a.key,\n });\n }\n }\n\n // ── axis titles (the gutters above already reserved room for these) ──\n if (spec.xLabel && !compact) {\n texts.push({\n x: plot.x + plot.width / 2,\n // Sit above the bottom-legend band so the axis title and legend stack\n // (title, then legend) instead of overlapping.\n y: height - legendBandBottom - 2,\n text: spec.xLabel,\n color: theme.textColor,\n fontSize: theme.labelSize,\n align: 'center',\n baseline: 'bottom',\n key: 'x-axis-title',\n });\n }\n if (spec.yLabel && !compact) {\n texts.push({\n x: 4,\n y: plot.y + plot.height / 2,\n text: spec.yLabel,\n color: theme.textColor,\n fontSize: theme.labelSize,\n align: 'center',\n baseline: 'top',\n rotate: -90,\n key: 'y-axis-title',\n });\n }\n\n // ── legend (positions filled by the overlay flow-layout; we\n // provide the entries, colour, and hidden state) ──\n const legend: LegendItem[] =\n spec.legend === 'none' || compact\n ? []\n : spec.series.map((s, si) => ({\n label: s.label,\n color: s.color,\n seriesIndex: si,\n hidden: s.hidden,\n x: 0,\n y: 0,\n }));\n\n const xLabels: string[] = [];\n for (let i = 0; i < rows; i++) xLabels.push(spec.xFormatter(spec.xValues[i] ?? i));\n\n return {\n width,\n height,\n plot,\n background: theme.background === 'transparent' ? undefined : theme.background,\n bands: axisBands,\n gridlines,\n axisLines,\n areas,\n bars,\n slices: [],\n lines,\n markers,\n glyphs,\n endLabels: endLabelCands,\n texts,\n legend,\n legendPosition: spec.legend,\n xPositions,\n xValues: spec.xValues,\n xLabels,\n hoverPoints,\n };\n}\n\n/**\n * Multi-axis line layout: each series is measured against its own value axis\n * (`spec.yAxes[series.yAxisIndex]`), and the axes stack outward from the plot —\n * left axes to the left, right axes to the right — each with its own domain,\n * ticks, formatter and (when it carries a single series) a matching tint. A\n * separate path from computeLayout; lines are independent (no stacking).\n */\nexport function computeMultiAxisLayout(spec: LineChartSpec, theme: EngineTheme, width: number, height: number): RenderScene {\n const axesSpec = spec.yAxes ?? [];\n const rows = spec.xValues.length || Math.max(0, ...spec.series.map((s) => s.data.length));\n const axisIndexOf = (s: LineSeriesSpec): number => {\n const i = s.yAxisIndex ?? 0;\n return i >= 0 && i < axesSpec.length ? i : 0;\n };\n\n interface AxisInfo {\n spec: ValueAxisSpec;\n domain: readonly [number, number];\n tickVals: number[];\n tickLabels: string[];\n side: 'left' | 'right';\n gutterW: number;\n tint: string | null;\n hasData: boolean;\n scale?: Scale;\n axisX?: number;\n toPxY?: (v: number) => number;\n }\n\n // ── per-axis domain / ticks / gutter width ──\n const axes: AxisInfo[] = axesSpec.map((a, ai) => {\n const seriesOn = spec.series.filter((s) => !s.hidden && axisIndexOf(s) === ai);\n const vals: number[] = [];\n for (const s of seriesOn) for (const d of s.data) if (typeof d === 'number' && Number.isFinite(d)) vals.push(d);\n const domain = computeDomain(vals, { min: a.min, max: a.max, scale: a.scale, includeZero: a.scale === 'value' });\n const tickVals = a.scale === 'log' ? logTicks(domain[0], domain[1]) : niceLinearTicks(domain[0], domain[1], 6);\n const tickLabels = tickVals.map((v) => a.formatter(v));\n const side: 'left' | 'right' = a.position ?? (ai === 0 ? 'left' : 'right');\n const labelW = a.hidden || a.hideTicks ? 0 : Math.max(0, ...tickLabels.map((t) => approxWidth(t, theme.labelSize)));\n const titleW = a.label ? theme.labelSize + 6 : 0;\n const gutterW = a.hidden ? 4 : labelW + 12 + titleW;\n // Axes default to the themed colour (the same muted grey as the x-axis); a\n // developer can tint an axis to match its series via the axis `color`.\n const tint = a.color ?? null;\n return { spec: a, domain, tickVals, tickLabels, side, gutterW, tint, hasData: seriesOn.length > 0 };\n });\n\n const leftAxes = axes.filter((a) => a.side === 'left');\n const rightAxes = axes.filter((a) => a.side === 'right');\n const sumGut = (arr: AxisInfo[]) => arr.reduce((n, a) => n + a.gutterW, 0);\n\n // ── outer chrome gutters ──\n const titleH = spec.title ? theme.titleSize + 10 + (spec.subtitle ? theme.labelSize + 4 : 0) : 0;\n const xLabelH = spec.xHidden || spec.xHideTicks ? 0 : theme.labelSize + 8;\n const xAxisLabelH = spec.xLabel ? theme.labelSize + 6 : 0;\n const legendActive = !!spec.legend && spec.legend !== 'none' && spec.series.length > 1;\n const legendSide = legendActive && (spec.legend === 'left' || spec.legend === 'right');\n const legendAtBottom = legendActive && !legendSide && spec.legend!.startsWith('bottom');\n const legendTopRow = legendActive && !legendSide && !legendAtBottom;\n const legendRows = legendTopRow || legendAtBottom ? estimateLegendRows(spec.series.map((s) => s.label), theme.labelSize, width * 0.86) : 1;\n const legendBandH = spec.legendExtent != null && (legendTopRow || legendAtBottom) ? spec.legendExtent + 8 : legendRows * (theme.labelSize + 8) + 6;\n const legendBandTop = legendTopRow ? legendBandH : 0;\n const legendBandBottom = legendAtBottom ? legendBandH : 0;\n const legendSideW = legendSide ? (spec.legendExtent != null ? spec.legendExtent + 16 : Math.max(0, ...spec.series.map((s) => approxWidth(s.label, theme.labelSize))) + 34) : 0;\n\n // With no right-side axis, reserve the right half of the last x-tick label so\n // it isn't clipped at the canvas edge (a right axis' gutter already covers it).\n const lastXText = spec.xHidden || spec.xHideTicks ? '' : spec.xFormatter(spec.xValues[rows - 1] ?? rows - 1);\n const xOverhang = rightAxes.length === 0 ? approxWidth(lastXText, theme.labelSize) / 2 : 0;\n\n const padTop = titleH + 8 + legendBandTop;\n const padBottom = xLabelH + xAxisLabelH + 6 + legendBandBottom;\n const padLeft = sumGut(leftAxes) + 8 + (spec.legend === 'left' ? legendSideW : 0);\n const padRight = sumGut(rightAxes) + 8 + xOverhang + (spec.legend === 'right' ? legendSideW : 0);\n\n const plot = {\n x: padLeft,\n y: padTop,\n width: Math.max(1, width - padLeft - padRight),\n height: Math.max(1, height - padTop - padBottom),\n };\n\n // ── x scale + hit-test positions ──\n const x: Scale =\n spec.xScale === 'category'\n ? makeCategoryScale(rows, plot.width, true)\n : spec.xScale === 'log'\n ? makeLogScale(computeDomain(spec.xValues.map((v) => toNumeric(v, spec.xScale)), { scale: 'log' }), plot.width)\n : makeLinearScale(computeDomain(spec.xValues.map((v) => toNumeric(v, spec.xScale)), { scale: spec.xScale }), plot.width, spec.xScale);\n const toPxX = (i: number) => plot.x + (spec.xScale === 'category' ? x.scale(i) : x.scale(toNumeric(spec.xValues[i], spec.xScale)));\n\n // ── position each axis + build its scale / toPxY ──\n const makeAxisScale = (a: AxisInfo) => {\n a.scale = a.spec.scale === 'log' ? makeLogScale(a.domain, plot.height) : makeLinearScale(a.domain, plot.height, a.spec.scale);\n a.toPxY = (v: number) => plot.y + plot.height - a.scale!.scale(v);\n };\n let offL = 0;\n for (const a of leftAxes) {\n a.axisX = plot.x - offL;\n makeAxisScale(a);\n offL += a.gutterW;\n }\n let offR = 0;\n for (const a of rightAxes) {\n a.axisX = plot.x + plot.width + offR;\n makeAxisScale(a);\n offR += a.gutterW;\n }\n\n // ── axis bands (behind everything) — each value axis bands its own scale,\n // plus any declared on the x axis ──\n const bands: SceneBand[] = [];\n const bandLabels: TextItem[] = [];\n axes.forEach((a, ai) => {\n const built = buildAxisBands(a.spec.bands, 'y', (v) => a.toPxY!(toNumeric(v, a.spec.scale)), plot, theme, `yband-${ai}`);\n bands.push(...built.rects);\n bandLabels.push(...built.labels);\n });\n {\n const onX = buildAxisBands(\n spec.xBands,\n 'x',\n (v) => plot.x + x.scale(spec.xScale === 'category' ? Number(v) : toNumeric(v, spec.xScale)),\n plot,\n theme,\n 'xband',\n );\n bands.push(...onX.rects);\n bandLabels.push(...onX.labels);\n }\n\n // ── gridlines + axis lines ──\n const gridlines: SceneSegment[] = [];\n const axisLines: SceneSegment[] = [];\n // Horizontal gridlines follow the primary axis — the first non-hidden axis\n // that actually carries data, so an empty / hidden axis 0 can't anchor the\n // grid to a phantom [0,1] scale.\n const primary = axes.find((a) => !a.spec.hidden && a.hasData) ?? axes.find((a) => a.hasData);\n const xAxisDash = dashPattern(spec.xDash, 1);\n const xGridDash = dashPattern(spec.xGridDash, 1);\n if (primary && spec.gridY !== false) {\n // The shared horizontal grid follows the primary axis, so it takes that\n // axis' gridDash.\n const gridDash = dashPattern(primary.spec.gridDash, 1);\n for (const t of primary.tickVals) {\n const py = primary.toPxY!(t);\n gridlines.push({ x1: plot.x, y1: py, x2: plot.x + plot.width, y2: py, color: theme.gridLineColor, width: 1, dash: gridDash });\n if (spec.axisTicks) axisLines.push({ x1: plot.x - AXIS_TICK_LEN, y1: py, x2: plot.x, y2: py, color: theme.axisLineColor, width: 1, dash: dashPattern(primary.spec.dash, 1) });\n }\n }\n for (const a of axes) {\n if (a.spec.hidden) continue;\n const col = a.tint ?? theme.axisLineColor;\n const dash = dashPattern(a.spec.dash, 1);\n axisLines.push({ x1: a.axisX!, y1: plot.y, x2: a.axisX!, y2: plot.y + plot.height, color: col, width: 1, dash });\n // Perpendicular tick marks on this axis (opt-in via axisTicks).\n if (spec.axisTicks && !a.spec.hideTicks) {\n const dir = a.side === 'left' ? -1 : 1;\n for (const t of a.tickVals) {\n const py = a.toPxY!(t);\n axisLines.push({ x1: a.axisX!, y1: py, x2: a.axisX! + dir * AXIS_TICK_LEN, y2: py, color: col, width: 1, dash });\n }\n }\n }\n if (!spec.xHidden) {\n axisLines.push({ x1: plot.x, y1: plot.y + plot.height, x2: plot.x + plot.width, y2: plot.y + plot.height, color: theme.axisLineColor, width: 1, dash: xAxisDash });\n }\n\n // ── series → polylines / areas / markers / glyphs ──\n const lines: ScenePolyline[] = [];\n const areas: SceneArea[] = [];\n const markers: SceneMarker[] = [];\n const glyphs: GlyphMarker[] = [];\n const hoverPoints: HoverSeries[] = [];\n\n spec.series.forEach((s, si) => {\n if (s.hidden) return;\n const ax = axes[axisIndexOf(s)];\n const toPxY = ax.toPxY!;\n const zeroInDomain = ax.domain[0] <= 0 && ax.domain[1] >= 0;\n const baselineY = toPxY(zeroInDomain ? 0 : ax.domain[0]);\n const runs = splitRuns(\n s.data.map((d) => (d === undefined ? undefined : typeof d === 'number' ? d : null)),\n s.connectNulls,\n );\n const byIndex: Record<number, HoverPoint> = {};\n for (const run of runs) {\n if (!run.length) continue;\n const raw: Pt[] = run.map((r) => ({ x: toPxX(r.index), y: toPxY(r.value) }));\n run.forEach((r, k) => {\n const hoverSym = s.pointSymbols?.[r.index] ?? (s.symbol && s.symbol !== 'none' ? s.symbol : 'circle');\n byIndex[r.index] = { x: raw[k].x, y: raw[k].y, value: (s.data[r.index] as number) ?? r.value, symbol: hoverSym };\n });\n const poly = clampToRect(interpolate(decimateMinMax(raw, plot.width), s.curve), plot.x, plot.y, plot.width, plot.height);\n lines.push({ points: poly, color: s.color, width: 2.5, dash: dashPattern(s.dash, 2.5), seriesIndex: si });\n if (spec.area && s.fill !== false) {\n const fo = spec.fillOpacity ?? 0.35;\n areas.push({ points: poly, baselineY, colorTop: hexToRgba(s.color, fo), colorBottom: hexToRgba(s.color, Math.max(0.02, fo * 0.06)), seriesIndex: si });\n }\n const markSet = s.markIndices ? new Set(s.markIndices) : null;\n run.forEach((r, k) => {\n const idx = r.index;\n const override = s.pointSymbols?.[idx];\n const showDefault = markSet ? markSet.has(idx) : s.showMarks;\n const sym = override ?? (showDefault ? s.symbol ?? 'circle' : undefined);\n if (!sym || sym === 'none') return;\n const pt = raw[k];\n if (isShapeSymbol(sym)) markers.push({ x: pt.x, y: pt.y, r: markerRadius(sym, s.markSize), color: s.color, symbol: sym, seriesIndex: si });\n else glyphs.push({ x: pt.x, y: pt.y, text: sym, size: GLYPH_SIZE });\n });\n if (spec.showLabels) {\n run.forEach((r, k) => {\n // Above the point by default, but FLIPPED below when there is no room\n // for it there: the topmost point sits on the plot's ceiling, so a\n // label hung above it lands outside the plot and collides with the\n // title. Nothing reserves headroom for these, so the label has to be\n // the thing that gives way.\n const above = raw[k].y - 9 - theme.labelSize >= plot.y;\n glyphs.push({\n x: raw[k].x,\n y: raw[k].y,\n text: ax.spec.formatter((s.data[r.index] as number) ?? r.value),\n size: theme.labelSize,\n label: {\n color: theme.textColor,\n weight: 600,\n dx: 0,\n dy: above ? -9 : 9,\n anchorX: '-50%',\n anchorY: above ? '-100%' : '0',\n },\n });\n });\n }\n }\n hoverPoints.push({ seriesIndex: si, color: s.color, label: s.label, byIndex, values: s.data, valueFormat: ax.spec.formatter, unanchored: !hasAnchor(s) });\n });\n\n // ── text items ──\n const texts: TextItem[] = [...bandLabels];\n if (spec.title) {\n const tt = titlePlacement(spec.titleAlign, plot.x, plot.width);\n texts.push({ x: tt.x, y: legendBandTop + 6, text: spec.title, color: theme.textColor, fontSize: theme.titleSize, fontWeight: 600, align: tt.align, baseline: 'top', key: 'title' });\n if (spec.subtitle) {\n texts.push({\n x: tt.x,\n y: legendBandTop + 6 + theme.titleSize + 4,\n text: spec.subtitle,\n color: theme.textColorMuted,\n fontSize: theme.labelSize,\n align: tt.align,\n baseline: 'top',\n key: 'subtitle',\n });\n }\n }\n // per-axis tick labels + rotated axis titles (tinted to the single series, if any)\n axes.forEach((a, ai) => {\n if (a.spec.hidden) return;\n const labelColor = a.tint ?? theme.textColorMuted;\n if (!a.spec.hideTicks) {\n a.tickVals.forEach((t, i) => {\n texts.push({\n x: a.side === 'left' ? a.axisX! - 8 : a.axisX! + 8,\n y: a.toPxY!(t),\n text: a.tickLabels[i],\n color: labelColor,\n fontSize: theme.labelSize,\n align: a.side === 'left' ? 'end' : 'start',\n baseline: 'middle',\n key: `yt-${ai}-${i}`,\n });\n });\n }\n if (a.spec.label) {\n const outerX = a.side === 'left' ? a.axisX! - a.gutterW + theme.labelSize : a.axisX! + a.gutterW - theme.labelSize;\n texts.push({ x: outerX, y: plot.y + plot.height / 2, text: a.spec.label, color: a.tint ?? theme.textColor, fontSize: theme.labelSize, align: 'center', baseline: 'top', rotate: -90, key: `yaxis-title-${ai}` });\n }\n });\n\n // x tick anchors: category → per-point (thinned); value/log/time → nice round\n // values (e.g. decades / month boundaries) so a dense series doesn't print a\n // label per data point. Computed ONCE and reused for gridlines, tick marks and\n // labels so vertical gridlines (gridX) render even when labels are hidden.\n const xPositions: number[] = [];\n for (let i = 0; i < rows; i++) xPositions.push(toPxX(i));\n const yb = plot.y + plot.height;\n const xAnchors: { px: number; text: string; key: string }[] = [];\n if (spec.xScale === 'category') {\n const step = Math.max(1, Math.ceil(rows / Math.max(1, Math.floor(plot.width / 60))));\n for (let i = 0; i < rows; i++) {\n if (i % step !== 0) continue;\n xAnchors.push({ px: xPositions[i], text: spec.xFormatter(spec.xValues[i] ?? i), key: `xt-${i}` });\n }\n } else {\n const xd = computeDomain(spec.xValues.map((v) => toNumeric(v, spec.xScale)), { scale: spec.xScale });\n const xTicks =\n spec.xScale === 'log' ? logTicks(xd[0], xd[1]) : spec.xScale === 'time' ? timeTicks(xd[0], xd[1], Math.max(2, Math.floor(plot.width / 90))) : niceLinearTicks(xd[0], xd[1], Math.max(2, Math.floor(plot.width / 90)));\n for (const tv of xTicks) {\n const px = plot.x + x.scale(tv);\n if (px < plot.x - 1 || px > plot.x + plot.width + 1) continue;\n // Format with the ORIGINAL typed value: a time axis needs a Date, not the\n // raw epoch number (a Date formatter would otherwise throw).\n xAnchors.push({ px, text: spec.xFormatter(spec.xScale === 'time' ? new Date(tv) : tv), key: `xt-${tv}` });\n }\n }\n // Vertical gridlines — independent of x-tick label visibility.\n if (spec.gridX) for (const a of xAnchors) gridlines.push({ x1: a.px, y1: plot.y, x2: a.px, y2: yb, color: theme.gridLineColor, width: 1, dash: xGridDash });\n if (!spec.xHidden && !spec.xHideTicks) {\n for (const a of xAnchors) {\n if (spec.axisTicks) axisLines.push({ x1: a.px, y1: yb, x2: a.px, y2: yb + AXIS_TICK_LEN, color: theme.axisLineColor, width: 1, dash: xAxisDash });\n texts.push({ x: a.px, y: yb + 6, text: a.text, color: theme.textColorMuted, fontSize: theme.labelSize, align: 'center', baseline: 'top', key: a.key });\n }\n }\n if (spec.xLabel) {\n texts.push({ x: plot.x + plot.width / 2, y: height - legendBandBottom - 2, text: spec.xLabel, color: theme.textColor, fontSize: theme.labelSize, align: 'center', baseline: 'bottom', key: 'x-axis-title' });\n }\n\n const legend: LegendItem[] =\n spec.legend === 'none' ? [] : spec.series.map((s, si) => ({ label: s.label, color: s.color, seriesIndex: si, hidden: s.hidden, x: 0, y: 0 }));\n const xLabels: string[] = [];\n for (let i = 0; i < rows; i++) xLabels.push(spec.xFormatter(spec.xValues[i] ?? i));\n\n return {\n width,\n height,\n plot,\n background: theme.background === 'transparent' ? undefined : theme.background,\n bands,\n gridlines,\n axisLines,\n areas,\n bars: [],\n slices: [],\n lines,\n markers,\n glyphs,\n endLabels: [],\n texts,\n legend,\n legendPosition: spec.legend,\n xPositions,\n xValues: spec.xValues,\n xLabels,\n hoverPoints,\n };\n}\n\n/**\n * Transposed line layout: the independent axis (xValues, e.g. altitude) runs\n * VERTICALLY and the series-value axis (e.g. temperature) runs HORIZONTALLY, so\n * the line is a function of the vertical axis and can snake back and forth. A\n * separate path from computeLayout so the normal orientation is untouched.\n */\nexport function computeInvertedLayout(spec: LineChartSpec, theme: EngineTheme, width: number, height: number): RenderScene {\n const rows = spec.xValues.length || Math.max(0, ...spec.series.map((s) => s.data.length));\n const compact = !!spec.compact;\n const category = spec.xScale === 'category';\n\n // ── stacked bands → the value extent (see computeLayout; same rules, but the\n // resulting band runs horizontally once the axes are transposed) ──\n const stackKeys = spec.series.map((s) => (spec.stack !== 'none' && !s.range ? 'stacked' : '__unstacked__'));\n const bands = stackSeries(\n spec.series.map((s) => (s.hidden ? [] : s.data)),\n spec.stack,\n stackKeys,\n );\n spec.series.forEach((s, si) => {\n if (!s.range || s.hidden) return;\n bands[si] = s.range.map((r) => (r ? ([Math.min(r[0], r[1]), Math.max(r[0], r[1])] as [number, number]) : r));\n });\n\n // value axis (series values → horizontal)\n const valVals: number[] = [];\n spec.series.forEach((s, si) => {\n if (s.hidden) return;\n for (const b of bands[si]) if (b) valVals.push(b[0], b[1]);\n });\n const valDomain = computeDomain(valVals, { min: spec.yMin, max: spec.yMax, scale: spec.yScale, includeZero: false });\n const valTicks = spec.yScale === 'log' ? logTicks(valDomain[0], valDomain[1]) : niceLinearTicks(valDomain[0], valDomain[1], 8);\n const valTickLabels = valTicks.map((v) => (spec.yTickFormatter ?? spec.yFormatter)(v));\n\n // main axis (xValues → vertical)\n const mainDomain = category ? ([0, Math.max(1, rows - 1)] as [number, number]) : computeDomain(spec.xValues.map((v) => toNumeric(v, spec.xScale)), { scale: spec.xScale });\n const mainTickIdx = category ? Array.from({ length: rows }, (_, i) => i) : niceLinearTicks(mainDomain[0], mainDomain[1], 6);\n const mainTickLabels = mainTickIdx.map((v) => (category ? spec.xFormatter(spec.xValues[v] ?? v) : spec.xFormatter(v)));\n\n // ── gutters (mirror computeLayout, but altitude labels go LEFT + temperature\n // labels go BOTTOM) ──\n const legendActive = !!spec.legend && spec.legend !== 'none' && spec.series.length > 1;\n const legendSide = legendActive && (spec.legend === 'left' || spec.legend === 'right');\n const legendAtBottom = legendActive && !legendSide && spec.legend!.startsWith('bottom');\n const legendTopRow = legendActive && !legendSide && !legendAtBottom;\n // A horizontal legend wraps into as many rows as the labels need — reserve\n // that height so many-series legends don't spill onto the plot.\n const legendRows = legendTopRow || legendAtBottom ? estimateLegendRows(spec.series.map((s) => s.label), theme.labelSize, width * 0.86) : 1;\n // Second-pass measured extent wins over the first-pass estimate.\n const legendBandH = spec.legendExtent != null && (legendTopRow || legendAtBottom) ? spec.legendExtent + 8 : legendRows * (theme.labelSize + 8) + 6;\n const legendBandTop = legendTopRow ? legendBandH : 0;\n const legendBandBottom = legendAtBottom ? legendBandH : 0;\n const legendSideW = legendSide ? (spec.legendExtent != null ? spec.legendExtent + 16 : Math.max(0, ...spec.series.map((s) => approxWidth(s.label, theme.labelSize))) + 34) : 0;\n const titleH = spec.title ? theme.titleSize + 10 + (spec.subtitle ? theme.labelSize + 4 : 0) : 0;\n const maxMainLabelW = spec.xHidden || spec.xHideTicks ? 0 : Math.max(0, ...mainTickLabels.map((t) => approxWidth(t, theme.labelSize)));\n const valLabelH = spec.yHidden || spec.yHideTicks ? 0 : theme.labelSize + 8;\n const mainAxisTitleW = spec.xLabel ? theme.labelSize + 6 : 0;\n const valAxisTitleH = spec.yLabel ? theme.labelSize + 6 : 0;\n\n const padTop = compact ? 2 : titleH + 8 + legendBandTop;\n const padRight = compact ? 2 : 12 + approxWidth(valTickLabels[valTickLabels.length - 1] ?? '', theme.labelSize) / 2 + (spec.legend === 'right' ? legendSideW : 0);\n const padBottom = compact ? 2 : valLabelH + valAxisTitleH + 6 + legendBandBottom;\n const padLeft = compact ? 2 : maxMainLabelW + 10 + mainAxisTitleW + (spec.legend === 'left' ? legendSideW : 0);\n\n const plot = {\n x: padLeft,\n y: padTop,\n width: Math.max(1, width - padLeft - padRight),\n height: Math.max(1, height - padTop - padBottom),\n };\n\n const valScale: Scale = spec.yScale === 'log' ? makeLogScale(valDomain, plot.width) : makeLinearScale(valDomain, plot.width, spec.yScale);\n const mainScale: Scale = category\n ? makeCategoryScale(rows, plot.height, true)\n : spec.xScale === 'log'\n ? makeLogScale(mainDomain, plot.height)\n : makeLinearScale(mainDomain, plot.height, spec.xScale);\n\n const toPxX = (v: number) => plot.x + valScale.scale(v); // temperature → horizontal\n // Vertical pixel for a main-axis coordinate (a tick value, or a data point's\n // altitude): map through the main scale, top-origin.\n const toPxYval = (coord: number) => plot.y + plot.height - mainScale.scale(coord);\n const toPxYidx = (i: number) => toPxYval(category ? i : toNumeric(spec.xValues[i], spec.xScale));\n\n // ── gridlines + axis lines ──\n const gridlines: SceneSegment[] = [];\n const axisLines: SceneSegment[] = [];\n const yb = plot.y + plot.height;\n // Axes are transposed here: the VALUE (y) axis runs along the bottom and the\n // x-data axis up the side — the dash options follow the axis they belong to,\n // not the screen direction.\n const yAxisDash = dashPattern(spec.yDash, 1);\n const yGridDash = dashPattern(spec.yGridDash, 1);\n const xAxisDash = dashPattern(spec.xDash, 1);\n const xGridDash = dashPattern(spec.xGridDash, 1);\n if (!spec.yHidden && !compact) {\n for (const t of valTicks) {\n const px = toPxX(t);\n if (spec.gridY !== false) gridlines.push({ x1: px, y1: plot.y, x2: px, y2: yb, color: theme.gridLineColor, width: 1, dash: yGridDash });\n if (spec.axisTicks) axisLines.push({ x1: px, y1: yb, x2: px, y2: yb + AXIS_TICK_LEN, color: theme.axisLineColor, width: 1, dash: yAxisDash });\n }\n axisLines.push({ x1: plot.x, y1: yb, x2: plot.x + plot.width, y2: yb, color: theme.axisLineColor, width: 1, dash: yAxisDash });\n }\n if (!spec.xHidden && !compact) {\n for (const t of mainTickIdx) {\n const py = toPxYval(t);\n if (spec.gridX) gridlines.push({ x1: plot.x, y1: py, x2: plot.x + plot.width, y2: py, color: theme.gridLineColor, width: 1, dash: xGridDash });\n if (spec.axisTicks) axisLines.push({ x1: plot.x - AXIS_TICK_LEN, y1: py, x2: plot.x, y2: py, color: theme.axisLineColor, width: 1, dash: xAxisDash });\n }\n axisLines.push({ x1: plot.x, y1: plot.y, x2: plot.x, y2: plot.y + plot.height, color: theme.axisLineColor, width: 1, dash: xAxisDash });\n }\n\n // ── series → polylines / areas / markers / glyphs (no stacking when inverted) ──\n const lines: ScenePolyline[] = [];\n const areas: SceneArea[] = [];\n const markers: SceneMarker[] = [];\n const glyphs: GlyphMarker[] = [];\n const hoverPoints: HoverSeries[] = [];\n // The value axis runs horizontally here, so the fill closes against a\n // baseline X (clamped into the plot, as the vertical layout does for y).\n const baselineX = toPxX(Math.max(valDomain[0], Math.min(valDomain[1], 0)));\n spec.series.forEach((s, si) => {\n if (s.hidden) return;\n const byIndex: Record<number, HoverPoint> = {};\n // Walk the STACKED top edge, as the upright layout does — `r.value` is the\n // band's top, so a stacked layer sits on the one below it instead of every\n // series starting again from the baseline.\n for (const run of splitRuns(\n bands[si].map((b) => (b === undefined ? undefined : b ? b[1] : null)),\n s.connectNulls,\n )) {\n if (!run.length) continue;\n const raw: Pt[] = run.map((r) => ({ x: toPxX(r.value), y: toPxYidx(r.index) }));\n run.forEach((r, k) => {\n const hoverSym = s.pointSymbols?.[r.index] ?? (s.symbol && s.symbol !== 'none' ? s.symbol : 'circle');\n byIndex[r.index] = { x: raw[k].x, y: raw[k].y, value: (s.data[r.index] as number) ?? r.value, symbol: hoverSym };\n });\n const poly = clampToRect(interpolate(decimateMinMax(raw, plot.width), s.curve), plot.x, plot.y, plot.width, plot.height);\n // Same rule as upright: a range band and a fill-only series draw no line,\n // and a stacked layer is stroked only where its band has real width.\n if (!s.range && s.stroke !== false) {\n lines.push({ points: poly, color: s.color, width: 2.5, dash: dashPattern(s.dash, 2.5), seriesIndex: si });\n }\n if (spec.area && s.fill !== false) {\n const fo = spec.fillOpacity ?? 0.35;\n const banded = spec.stack !== 'none' || !!s.range;\n areas.push({\n points: poly,\n baselineY: baselineX,\n colorTop: hexToRgba(s.color, fo),\n // Even tint for a band, fade only for a fill that runs to the axis —\n // see the upright layout.\n colorBottom: banded ? hexToRgba(s.color, fo) : hexToRgba(s.color, Math.max(0.02, fo * 0.06)),\n // Mirror each point onto the layer's base so the polygon closes along\n // the value axis; `baselineY` alone would close it vertically, which\n // is the wrong direction once the axes are transposed. A stacked or\n // range layer bases on its own band, everything else on zero.\n basePoints:\n spec.stack !== 'none' || s.range\n ? clampToRect(\n interpolate(\n run.map((r) => ({ x: toPxX((bands[si][r.index] as [number, number])[0]), y: toPxYidx(r.index) })),\n s.curve,\n ),\n plot.x,\n plot.y,\n plot.width,\n plot.height,\n )\n : poly.map((p) => ({ x: baselineX, y: p.y })),\n horizontal: true,\n seriesIndex: si,\n });\n }\n const markSet = s.markIndices ? new Set(s.markIndices) : null;\n run.forEach((r, k) => {\n const override = s.pointSymbols?.[r.index];\n const sym = override ?? ((markSet ? markSet.has(r.index) : s.showMarks) ? s.symbol ?? 'circle' : undefined);\n if (!sym || sym === 'none') return;\n const pt = raw[k];\n if (isShapeSymbol(sym)) markers.push({ x: pt.x, y: pt.y, r: markerRadius(sym, s.markSize), color: s.color, symbol: sym, seriesIndex: si });\n else glyphs.push({ x: pt.x, y: pt.y, text: sym, size: GLYPH_SIZE });\n });\n // Data labels — to the right of each point (value axis is horizontal),\n // via the glyph layer so they animate with the point.\n if (spec.showLabels && !compact) {\n run.forEach((r, k) => {\n glyphs.push({\n x: raw[k].x,\n y: raw[k].y,\n text: spec.yFormatter((s.data[r.index] as number) ?? r.value),\n size: theme.labelSize,\n label: { color: theme.textColor, weight: 600, dx: 9, dy: 0, anchorX: '0', anchorY: '-50%' },\n });\n });\n }\n }\n hoverPoints.push({ seriesIndex: si, color: s.color, label: s.label, byIndex, values: s.data, unanchored: !hasAnchor(s) });\n });\n\n // ── overlay text (title, altitude labels LEFT, temperature labels BOTTOM, titles) ──\n const texts: TextItem[] = [];\n if (spec.title && !compact) {\n const tt = titlePlacement(spec.titleAlign, plot.x, plot.width);\n texts.push({ x: tt.x, y: legendBandTop + 6, text: spec.title, color: theme.textColor, fontSize: theme.titleSize, fontWeight: 600, align: tt.align, baseline: 'top', key: 'title' });\n if (spec.subtitle) {\n texts.push({\n x: tt.x,\n y: legendBandTop + 6 + theme.titleSize + 4,\n text: spec.subtitle,\n color: theme.textColorMuted,\n fontSize: theme.labelSize,\n align: tt.align,\n baseline: 'top',\n key: 'subtitle',\n });\n }\n }\n if (!spec.xHidden && !spec.xHideTicks && !compact) {\n mainTickIdx.forEach((t, i) => {\n texts.push({ x: plot.x - 8, y: toPxYval(t), text: mainTickLabels[i], color: theme.textColorMuted, fontSize: theme.labelSize, align: 'end', baseline: 'middle', key: `mt-${i}` });\n });\n }\n if (!spec.yHidden && !spec.yHideTicks && !compact) {\n valTicks.forEach((t, i) => {\n texts.push({ x: toPxX(t), y: yb + 6, text: valTickLabels[i], color: theme.textColorMuted, fontSize: theme.labelSize, align: 'center', baseline: 'top', key: `vt-${i}` });\n });\n }\n if (spec.xLabel && !compact) {\n texts.push({ x: 4, y: plot.y + plot.height / 2, text: spec.xLabel, color: theme.textColor, fontSize: theme.labelSize, align: 'center', baseline: 'top', rotate: -90, key: 'x-axis-title' });\n }\n if (spec.yLabel && !compact) {\n texts.push({ x: plot.x + plot.width / 2, y: height - legendBandBottom - 2, text: spec.yLabel, color: theme.textColor, fontSize: theme.labelSize, align: 'center', baseline: 'bottom', key: 'y-axis-title' });\n }\n\n const legend: LegendItem[] =\n spec.legend === 'none' || compact ? [] : spec.series.map((s, si) => ({ label: s.label, color: s.color, seriesIndex: si, hidden: s.hidden, x: 0, y: 0 }));\n\n const xPositions: number[] = [];\n const xLabels: string[] = [];\n for (let i = 0; i < rows; i++) {\n xPositions.push(toPxYidx(i));\n xLabels.push(spec.xFormatter(spec.xValues[i] ?? i));\n }\n\n return {\n width,\n height,\n plot,\n background: theme.background === 'transparent' ? undefined : theme.background,\n gridlines,\n axisLines,\n areas,\n bars: [],\n slices: [],\n lines,\n markers,\n glyphs,\n texts,\n legend,\n legendPosition: spec.legend,\n inverted: true,\n xPositions,\n xValues: spec.xValues,\n xLabels,\n hoverPoints,\n };\n}\n\n/** Default emoji / text glyph-marker size in px. */\nconst GLYPH_SIZE = 18;\n\nconst SHAPE_SYMBOLS = new Set<string>(['circle', 'square', 'diamond', 'triangle', 'triangle-down']);\n\n/** Whether a symbol is a drawable shape (canvas) vs an emoji/text glyph (DOM). */\nfunction isShapeSymbol(symbol: string): symbol is MdChartSymbol {\n return SHAPE_SYMBOLS.has(symbol);\n}\n\n/** Marker circumradius per symbol — polygons get a touch more so they read at\n * a similar visual weight to the circle (corners recede). */\nfunction markerRadius(symbol: MdChartSymbol | undefined, override?: number): number {\n if (override != null && override > 0) return override;\n if (symbol === 'square' || symbol === 'diamond') return 4.2;\n if (symbol === 'triangle' || symbol === 'triangle-down') return 4.6;\n return 3.5;\n}\n\n/**\n * Resolve a title's anchor x + text-align from the requested alignment,\n * relative to the plot box. Shared by the line/bar/pie layouts so the\n * `titleAlign` prop behaves identically across chart types.\n */\nexport function titlePlacement(\n align: MdChartTitleAlign | undefined,\n plotX: number,\n plotWidth: number,\n): { x: number; align: 'start' | 'center' | 'end' } {\n if (align === 'center') return { x: plotX + plotWidth / 2, align: 'center' };\n if (align === 'end') return { x: plotX + plotWidth, align: 'end' };\n return { x: plotX, align: 'start' };\n}\n","/*\n * Chart engine — Canvas2D renderer backend\n * ===========================================================\n * The renderer:\n * paints a RenderScene onto a 2D context. Text is NOT drawn here\n * — the DOM overlay owns it — so this only strokes/fills the plot\n * geometry (gridlines, axes, area gradients, lines, markers).\n * ===========================================================\n */\n\nimport { markerPolygon } from './geometry';\nimport type { RenderScene, SceneArea, SceneBar, SceneSlice } from './scene';\n\n/**\n * A bar as a chevron pointing along the value axis.\n *\n * The tip OVERFLOWS the bar's own rect by the notch depth, so that it lands\n * exactly in the notch cut out of the next segment along — that is what makes a\n * chain interlock rather than leaving a gap at every join. The depth is taken\n * from the bar's THICKNESS, not its length, so every segment in a stack shares\n * one figure and the tips and notches agree however short a segment is.\n */\nexport const CHEVRON_MAX_TIP = 32;\n\n/**\n * Depth a chevron's tip overflows its own rect by, from the bar's THICKNESS.\n * Exported because the hover layer has to agree with it: a marker placed at the\n * bar's rect edge sits *behind* the drawn point, which reads as pointing at\n * nothing. Shared here rather than duplicated so the two cannot drift.\n */\nexport function chevronTipDepth(thickness: number): number {\n return Math.min(thickness * 0.3, CHEVRON_MAX_TIP);\n}\n\nfunction traceChevron(ctx: CanvasRenderingContext2D, b: SceneBar): void {\n const along = b.horizontal ?? b.w > b.h;\n const t = chevronTipDepth(along ? b.h : b.w);\n const cut = b.notch === false ? 0 : t;\n if (along) {\n const my = b.y + b.h / 2;\n if (b.arrow === 1) {\n ctx.moveTo(b.x, b.y);\n ctx.lineTo(b.x + b.w, b.y);\n ctx.lineTo(b.x + b.w + t, my);\n ctx.lineTo(b.x + b.w, b.y + b.h);\n ctx.lineTo(b.x, b.y + b.h);\n if (cut) ctx.lineTo(b.x + cut, my);\n } else {\n ctx.moveTo(b.x + b.w, b.y);\n ctx.lineTo(b.x, b.y);\n ctx.lineTo(b.x - t, my);\n ctx.lineTo(b.x, b.y + b.h);\n ctx.lineTo(b.x + b.w, b.y + b.h);\n if (cut) ctx.lineTo(b.x + b.w - cut, my);\n }\n } else {\n const mx = b.x + b.w / 2;\n if (b.arrow === 1) {\n ctx.moveTo(b.x, b.y + b.h);\n ctx.lineTo(b.x, b.y);\n ctx.lineTo(mx, b.y - t);\n ctx.lineTo(b.x + b.w, b.y);\n ctx.lineTo(b.x + b.w, b.y + b.h);\n if (cut) ctx.lineTo(mx, b.y + b.h - cut);\n } else {\n ctx.moveTo(b.x, b.y);\n ctx.lineTo(b.x, b.y + b.h);\n ctx.lineTo(mx, b.y + b.h + t);\n ctx.lineTo(b.x + b.w, b.y + b.h);\n ctx.lineTo(b.x + b.w, b.y);\n if (cut) ctx.lineTo(mx, b.y + cut);\n }\n }\n ctx.closePath();\n}\n\n/**\n * Trace one slice: its gap from the neighbours cut out of its own edges, and\n * the two corners where the outer arc meets them rounded — the MD3 pie shape.\n *\n * Each corner is a circle of radius `r` tangent to BOTH the outer arc and the\n * radial edge. Its centre sits at radius `R - r`, offset from the edge by\n * `asin(r / (R - r))`: that is the angle at which the perpendicular distance\n * from the centre to the edge equals `r`. Solving it rather than approximating\n * with a curve keeps the rounding even all the way round, including on the\n * narrow slices where an approximation visibly pinches.\n *\n * Both ends round. The inner corner is the same construction mirrored: its\n * circle is tangent to the hole from OUTSIDE, so the centre sits at\n * `innerR + r` and the offset is `asin(r / (innerR + r))`. A pie has no inner\n * corner to round — its edges meet at the centre — so only a donut gets them.\n */\nfunction traceSlice(ctx: CanvasRenderingContext2D, s: SceneArc, fresh = true): void {\n const { cx, cy, innerR, outerR, startAngle: a0, endAngle: a1 } = s;\n const ccw = a1 < a0;\n const towards = ccw ? -1 : 1; // the sign that points INTO the slice from edge a0\n const sweep = Math.abs(a1 - a0);\n const at = (r: number, a: number) => ({ x: cx + Math.cos(a) * r, y: cy + Math.sin(a) * r });\n\n // Half the separation from each neighbour, taken out of this slice. Clamped\n // so a narrow slice keeps a body instead of closing up, and dropped for a\n // lone full-circle slice, which has no neighbour to stand clear of.\n const lone = sweep >= Math.PI * 2 - 0.01;\n const g = lone ? 0 : Math.min((s.gap ?? 0) / 2, outerR * Math.sin(sweep / 2) * 0.4);\n // The edge is a line offset `g` from the true radial one, so at radius R it\n // has moved `asin(g / R)` round — a constant WIDTH, which is what makes the\n // separation read the same at the hub as at the rim. It closes on itself at\n // `g / sin(sweep/2)`; the layout keeps `innerR` at or above that, so the two\n // edges never cross inside the shape being drawn.\n const insetAt = (R: number) => (g > 0 && R > g ? Math.asin(Math.min(1, g / R)) : 0);\n const b0 = a0 + towards * insetAt(outerR);\n const b1 = a1 - towards * insetAt(outerR);\n if (towards * (b1 - b0) <= 0) return;\n /** The inset edge's own angle at radius R, clamped so it cannot overshoot the\n * slice's midline (which a slice narrower than its own gap would). */\n const edgeAt = (base: number, dir: number, R: number) => {\n const mid = (a0 + a1) / 2;\n const a = base + dir * insetAt(R);\n return dir * towards > 0 ? Math.min(a * towards, mid * towards) * towards : Math.max(a * towards, mid * towards) * towards;\n };\n\n // Clamp: never wider than half the ring's thickness, and never so wide that\n // two corners of a thin slice would overlap. The INNER pair is the binding\n // one on a donut — the band is the same angle there but a smaller radius, so\n // the two corners have less room between them than the outer pair does.\n const span = Math.min(Math.abs(b1 - b0), Math.PI / 2) / 4;\n const maxByBand = (outerR - innerR) / 2;\n const maxBySweep = outerR * Math.tan(span);\n const maxBySweepInner = innerR > 0 ? innerR * Math.tan(span) : Infinity;\n const r = Math.max(0, Math.min(s.cornerRadius ?? 0, maxByBand, maxBySweep, maxBySweepInner));\n\n const n0 = edgeAt(a0, towards, Math.max(innerR, 0.01));\n const n1 = edgeAt(a1, -towards, Math.max(innerR, 0.01));\n\n if (fresh) ctx.beginPath();\n if (r < 0.5) {\n const from = at(innerR, n0);\n ctx.moveTo(from.x, from.y);\n const rim0 = at(outerR, b0);\n ctx.lineTo(rim0.x, rim0.y);\n ctx.arc(cx, cy, outerR, b0, b1, ccw);\n const back = at(innerR, n1);\n ctx.lineTo(back.x, back.y);\n if (innerR > 0 && towards * (n1 - n0) > 0) ctx.arc(cx, cy, innerR, n1, n0, !ccw);\n ctx.closePath();\n return;\n }\n\n const rhoO = outerR - r;\n const dO = Math.asin(Math.min(1, r / rhoO)) * towards;\n const footO = Math.sqrt(Math.max(0, rhoO * rhoO - r * r)); // tangent point on the radial edge\n const c0 = b0 + dO; // leading outer corner centre\n const c1 = b1 - dO; // trailing outer corner centre\n\n // The hole's corners, if there is a hole. Their circles sit OUTSIDE it, so\n // the centre is at innerR + r; and the edge's own inset differs at that\n // radius from what it is at the rim, so the angles are taken there.\n const donut = innerR > 0;\n const rhoI = innerR + r;\n const dI = Math.asin(Math.min(1, r / rhoI)) * towards;\n const footI = Math.sqrt(Math.max(0, rhoI * rhoI - r * r));\n const i0 = edgeAt(a0, towards, rhoI);\n const i1 = edgeAt(a1, -towards, rhoI);\n const e0 = i0 + dI; // leading inner corner centre\n const e1 = i1 - dI; // trailing inner corner centre\n // Perpendicular to each edge, pointing out of the slice — where a corner\n // circle touches the edge, at both ends of it.\n const off0 = b0 + (ccw ? Math.PI / 2 : -Math.PI / 2);\n const off1 = b1 + (ccw ? -Math.PI / 2 : Math.PI / 2);\n\n const from = at(donut ? footI : 0, i0);\n ctx.moveTo(from.x, from.y);\n const start = at(footO, b0);\n ctx.lineTo(start.x, start.y);\n // Leading corner: radial edge → outer arc.\n ctx.arc(at(rhoO, c0).x, at(rhoO, c0).y, r, off0, c0, ccw);\n // The outer arc between the two corners.\n ctx.arc(cx, cy, outerR, c0, c1, ccw);\n // Trailing corner: outer arc → radial edge.\n ctx.arc(at(rhoO, c1).x, at(rhoO, c1).y, r, c1, off1, ccw);\n const back = at(footO, b1);\n ctx.lineTo(back.x, back.y);\n if (donut) {\n const inner = at(footI, i1);\n ctx.lineTo(inner.x, inner.y);\n // Trailing inner corner: radial edge → the hole.\n ctx.arc(at(rhoI, e1).x, at(rhoI, e1).y, r, off1, e1 + Math.PI, ccw);\n if (towards * (e1 - e0) > 0) ctx.arc(cx, cy, innerR, e1, e0, !ccw);\n // Leading inner corner: the hole → radial edge.\n ctx.arc(at(rhoI, e0).x, at(rhoI, e0).y, r, e0 + Math.PI, off0, ccw);\n } else {\n const tip = at(0, i1);\n ctx.lineTo(tip.x, tip.y);\n }\n ctx.closePath();\n}\n\n/** The slice fields `traceSlice` needs. */\ntype SceneArc = Pick<\n SceneSlice,\n 'cx' | 'cy' | 'innerR' | 'outerR' | 'startAngle' | 'endAngle' | 'cornerRadius' | 'gap'\n>;\n\n\n/**\n * The gradient for one area fill.\n *\n * The fade runs from the series' own edge toward the baseline, so the fill\n * thins out where it meets the axis instead of competing with it. Two details\n * matter:\n *\n * • It is measured over the WHOLE painted extent, not from the line down to\n * the baseline. A series that crosses zero paints past the baseline, and a\n * gradient that stopped there left everything beyond it clamped to the\n * transparent end stop — the negative half of the chart was nearly invisible.\n * • The faint stop therefore sits AT the baseline's offset within that extent,\n * with the solid colour at both ends. A crossing series then fades toward\n * zero from above and from below; an all-positive or all-negative one puts\n * the baseline at one end, which collapses back to a plain two-stop fade.\n *\n * An inverted chart fills out from a baseline X, so the same reasoning runs\n * along x (`horizontal`). A band fill — stacked layer or range — has equal\n * stops, so the geometry here makes no difference to it.\n */\nfunction areaGradient(ctx: CanvasRenderingContext2D, a: SceneArea, hasBase: boolean): CanvasGradient {\n const horiz = !!a.horizontal;\n const at = (p: { x: number; y: number }) => (horiz ? p.x : p.y);\n const coords = a.points.map(at);\n if (hasBase) coords.push(...a.basePoints!.map(at));\n // `baselineY` carries the baseline on whichever axis the fill closes against.\n coords.push(a.baselineY);\n const lo = Math.min(...coords);\n const hi = Math.max(...coords);\n const grad = horiz ? ctx.createLinearGradient(lo, 0, hi, 0) : ctx.createLinearGradient(0, lo, 0, hi);\n const span = hi - lo;\n // Degenerate extent (a flat fill): a plain two-stop gradient is all there is.\n if (span < 1e-6) {\n grad.addColorStop(0, a.colorTop);\n grad.addColorStop(1, a.colorBottom);\n return grad;\n }\n const t = (a.baselineY - lo) / span;\n if (t <= 1e-4) {\n // Baseline at the low end: fade outward from it (an all-negative series,\n // or an upright inverted fill running left-to-right).\n grad.addColorStop(0, a.colorBottom);\n grad.addColorStop(1, a.colorTop);\n } else if (t >= 1 - 1e-4) {\n grad.addColorStop(0, a.colorTop);\n grad.addColorStop(1, a.colorBottom);\n } else {\n grad.addColorStop(0, a.colorTop);\n grad.addColorStop(t, a.colorBottom);\n grad.addColorStop(1, a.colorTop);\n }\n return grad;\n}\n\n\n/** An unlikely colour, used to detect a rejected `fillStyle` assignment. */\nconst SENTINEL = '#010203';\n\n/**\n * Draw the scene onto a 2D context already scaled to `dpr` (so\n * coordinates are in CSS pixels). Clears first.\n */\nexport function drawSceneCanvas(ctx: CanvasRenderingContext2D, scene: RenderScene, clear = true): void {\n // A transition that has two levels on screen at once draws the second one\n // OVER the first, so it must not wipe what is already there.\n if (clear) ctx.clearRect(0, 0, scene.width, scene.height);\n\n if (scene.background) {\n ctx.fillStyle = scene.background;\n ctx.fillRect(0, 0, scene.width, scene.height);\n }\n\n // ── axis bands (furthest back — the classification the data is read against) ──\n for (const b of scene.bands ?? []) {\n // A colour the context cannot parse is REJECTED, leaving fillStyle at\n // whatever was drawn last — so a bad band colour silently paints in another\n // series' colour instead of failing. Assign a sentinel first and check it\n // actually moved.\n ctx.fillStyle = SENTINEL;\n ctx.fillStyle = b.color;\n if (ctx.fillStyle === SENTINEL) continue;\n ctx.fillRect(b.x, b.y, b.w, b.h);\n }\n\n // ── gridlines (background — beneath the area fills / lines) ──\n for (const g of scene.gridlines) {\n ctx.beginPath();\n ctx.strokeStyle = g.color;\n ctx.lineWidth = g.width;\n if (g.dash) ctx.setLineDash(g.dash);\n ctx.moveTo(g.x1, g.y1);\n ctx.lineTo(g.x2, g.y2);\n ctx.stroke();\n if (g.dash) ctx.setLineDash([]);\n }\n\n // ── area fills (over the gridlines, under the lines) ──\n for (const a of scene.areas) {\n if (a.points.length < 2) continue;\n const hasBase = !!(a.basePoints && a.basePoints.length);\n ctx.beginPath();\n ctx.moveTo(a.points[0].x, a.points[0].y);\n for (let i = 1; i < a.points.length; i++) ctx.lineTo(a.points[i].x, a.points[i].y);\n if (hasBase) {\n for (let i = a.basePoints!.length - 1; i >= 0; i--) ctx.lineTo(a.basePoints![i].x, a.basePoints![i].y);\n } else {\n ctx.lineTo(a.points[a.points.length - 1].x, a.baselineY);\n ctx.lineTo(a.points[0].x, a.baselineY);\n }\n ctx.closePath();\n ctx.fillStyle = areaGradient(ctx, a, hasBase);\n ctx.fill();\n }\n\n // ── axis lines (dashable, like the gridlines above) ──\n for (const a of scene.axisLines) {\n ctx.beginPath();\n ctx.strokeStyle = a.color;\n ctx.lineWidth = a.width;\n if (a.dash) ctx.setLineDash(a.dash);\n ctx.moveTo(a.x1, a.y1);\n ctx.lineTo(a.x2, a.y2);\n ctx.stroke();\n if (a.dash) ctx.setLineDash([]);\n }\n\n // ── bars ──\n for (const b of scene.bars) {\n if (b.w <= 0 || b.h <= 0) continue;\n ctx.beginPath();\n ctx.fillStyle = b.color;\n if (b.arrow) {\n traceChevron(ctx, b);\n ctx.fill();\n continue;\n }\n const maxR = Math.min(b.w, b.h) / 2;\n const rr = b.radius.map((r) => Math.max(0, Math.min(r, maxR))) as [number, number, number, number];\n if (typeof ctx.roundRect === 'function') {\n ctx.roundRect(b.x, b.y, b.w, b.h, rr);\n } else {\n ctx.rect(b.x, b.y, b.w, b.h);\n }\n ctx.fill();\n }\n\n\n // ── pie / donut slices ──\n // What shows through the gaps, first: every wedge at full size, as ONE path\n // filled once. One path rather than a fill per slice because two abutting\n // shapes each land half-covered pixels on their shared edge, and source-over\n // does not add those back to full — separate fills would leave a faint seam\n // down the middle of every gap.\n const backed = scene.slices.filter((s) => !s.pill && s.gap && s.gapColor && s.endAngle !== s.startAngle);\n if (backed.length) {\n ctx.beginPath();\n for (const s of backed) traceSlice(ctx, { ...s, gap: 0 }, false);\n ctx.fillStyle = backed[0].gapColor!;\n ctx.fill();\n }\n for (const s of scene.slices) {\n if (s.endAngle === s.startAngle) continue;\n if (s.pill) {\n // A stroked arc: `lineWidth` is the band's thickness and the round caps\n // ARE its rounded ends, which a filled path cannot give on the inner side.\n const mid = (s.innerR + s.outerR) / 2;\n const thickness = Math.abs(s.outerR - s.innerR);\n if (thickness <= 0 || mid <= 0) continue;\n // A band with explicit per-end caps (a polar stack segment) strokes FLAT so\n // it abuts its neighbours seamlessly, then adds a round-cap disc only where\n // the ring truly starts / ends. Without them (a lone pill / a pie's thin\n // slice) it keeps round caps on both ends as before.\n const perEnd = s.capStart !== undefined || s.capEnd !== undefined;\n ctx.beginPath();\n ctx.fillStyle = s.color;\n ctx.strokeStyle = s.color;\n ctx.lineWidth = thickness;\n ctx.lineCap = perEnd ? 'butt' : 'round';\n ctx.arc(s.cx, s.cy, mid, s.startAngle, s.endAngle, s.endAngle < s.startAngle);\n ctx.stroke();\n if (perEnd) {\n const cap = (angle: number): void => {\n ctx.beginPath();\n ctx.arc(s.cx + mid * Math.cos(angle), s.cy + mid * Math.sin(angle), thickness / 2, 0, Math.PI * 2);\n ctx.fill();\n };\n if (s.capStart) cap(s.startAngle);\n if (s.capEnd) cap(s.endAngle);\n }\n ctx.lineCap = 'butt';\n continue;\n }\n // A gradient runs along the slice's OWN mid-angle, inner edge to outer, so\n // every wedge is lit from the middle of the ring outward. A single gradient\n // across the whole canvas would light the left of the pie differently from\n // the right, which reads as a shadow rather than as depth.\n if (s.gradient) {\n const mid = (s.startAngle + s.endAngle) / 2;\n const g = ctx.createLinearGradient(\n s.cx + Math.cos(mid) * s.innerR,\n s.cy + Math.sin(mid) * s.innerR,\n s.cx + Math.cos(mid) * s.outerR,\n s.cy + Math.sin(mid) * s.outerR,\n );\n g.addColorStop(0, s.gradient.from);\n g.addColorStop(1, s.gradient.to);\n ctx.fillStyle = g;\n } else {\n ctx.fillStyle = s.color;\n }\n traceSlice(ctx, s);\n ctx.fill();\n }\n\n // ── press ripple (over the slice it started on, under everything else) ──\n const rip = scene.ripple;\n if (rip && rip.alpha > 0 && rip.radius > 0) {\n const host = scene.slices.find((s) => !s.pill && s.dataIndex === rip.dataIndex);\n if (host) {\n ctx.save();\n // Clipped to the wedge, so the circle reads as the SLICE responding to\n // the press rather than as a disc drawn over the chart.\n traceSlice(ctx, host);\n ctx.clip();\n // Multiplied in, not assigned: a drill in flight is already drawing this\n // level at a partial alpha and the ripple has to fade with it.\n ctx.globalAlpha *= rip.alpha;\n ctx.fillStyle = rip.color;\n ctx.beginPath();\n ctx.arc(rip.x, rip.y, rip.radius, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n }\n }\n\n // ── series lines ──\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n for (const line of scene.lines) {\n if (line.points.length < 2) {\n // A single point still deserves a dot.\n if (line.points.length === 1) {\n ctx.beginPath();\n ctx.fillStyle = line.color;\n ctx.arc(line.points[0].x, line.points[0].y, line.width, 0, Math.PI * 2);\n ctx.fill();\n }\n continue;\n }\n ctx.beginPath();\n ctx.strokeStyle = line.color;\n ctx.lineWidth = line.width;\n // Round is right for a data line; a separator wants none, or its cap pokes\n // a half-width nub past the pie's rim.\n ctx.lineCap = line.cap ?? 'round';\n ctx.setLineDash(line.dash ?? []);\n ctx.moveTo(line.points[0].x, line.points[0].y);\n for (let i = 1; i < line.points.length; i++) ctx.lineTo(line.points[i].x, line.points[i].y);\n ctx.stroke();\n }\n ctx.setLineDash([]);\n ctx.lineCap = 'round';\n\n // ── markers ──\n for (const m of scene.markers) {\n ctx.beginPath();\n const poly = markerPolygon(m.symbol, m.x, m.y, m.r);\n if (poly) {\n ctx.moveTo(poly[0].x, poly[0].y);\n for (let i = 1; i < poly.length; i++) ctx.lineTo(poly[i].x, poly[i].y);\n ctx.closePath();\n } else {\n ctx.arc(m.x, m.y, m.r, 0, Math.PI * 2);\n }\n if (m.hollow) {\n // Open marker: fill with the surface so the line is occluded, ring in colour.\n ctx.fillStyle = m.fill ?? 'rgba(0,0,0,0)';\n ctx.fill();\n ctx.lineWidth = 2;\n ctx.strokeStyle = m.color;\n ctx.stroke();\n } else {\n ctx.fillStyle = m.color;\n ctx.fill();\n // white halo so overlapping markers stay legible\n ctx.lineWidth = 1.5;\n ctx.strokeStyle = 'rgba(255,255,255,0.9)';\n ctx.stroke();\n }\n }\n}\n","/*\n * Chart engine — render scene\n * ===========================================================\n * The backend-agnostic description of a frame. `computeLayout`\n * (layout.ts) turns a chart spec + theme + size into one of\n * these; the Canvas2D backend knows how to draw\n * it, and the DOM overlay renders `texts`. Keeping the scene\n * declarative means the two renderers can't drift — they consume\n * the identical geometry.\n * ===========================================================\n */\n\nimport type { Pt } from './geometry';\n\n/**\n * The most of a chart's width a side legend may take.\n *\n * Shared by the layout, which reserves the gutter, and the overlay, which lays\n * the chips into it: with two different numbers the chips ran past the gutter\n * and printed over the plot, which is exactly what a reserved gutter is for.\n */\nexport const LEGEND_SIDE_MAX_FRACTION = 0.3;\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A stroked polyline (the series line, tessellated). */\nexport interface ScenePolyline {\n points: Pt[];\n color: string;\n width: number;\n /** On/off dash pattern in px (round-capped). Omitted → solid. */\n dash?: number[];\n /** Owning series (for hover emphasis / dimming). */\n seriesIndex?: number;\n /**\n * Radial geometry (a pie's slice separators), not a cartesian series line.\n *\n * The intro animations are written for a plot with a baseline and a left-to-\n * right sweep: they LIFT a line from the plot's bottom edge, or TRIM it by x.\n * Both are meaningless on a line running from a ring's centre to its rim —\n * lifting slid the separators up the plot while the slices swept angularly,\n * so they arrived from somewhere else and settled at the end. Flagged lines\n * are left alone by those transforms.\n */\n radial?: boolean;\n /**\n * Stroke cap. Defaults to `round`, which is right for a data line but adds a\n * half-width nub past each end of a separator — visible poking out beyond the\n * pie's circumference.\n */\n cap?: CanvasLineCap;\n}\n\n/**\n * A shaded band across the plot (an axis value range — Beaufort force, a\n * target zone, off-hours). Painted first, under the gridlines, so it reads as\n * background the data sits on rather than as data.\n */\nexport interface SceneBand {\n x: number;\n y: number;\n w: number;\n h: number;\n color: string;\n}\n\n/**\n * A filled area between a top polyline and a baseline y, painted\n * with a vertical gradient (color at `y=top` → transparent at the\n * baseline). `points` is the top edge; the renderer closes it down\n * to `baselineY`.\n */\nexport interface SceneArea {\n points: Pt[];\n baselineY: number;\n colorTop: string;\n colorBottom: string;\n /**\n * Optional bottom edge (same x-sampling as `points`, reversed at draw time).\n * Stacked areas set this to their band base so each layer fills only its own\n * slice instead of down to the global zero line. Absent → close to baselineY.\n */\n basePoints?: Pt[];\n /**\n * Fill sideways (left→right) instead of top→bottom. An inverted chart's value\n * axis is horizontal, so its areas run out from a baseline X — the gradient\n * has to fade along that direction or it reads as a band with a stray\n * vertical wash across it.\n */\n horizontal?: boolean;\n /** Owning series (for hover emphasis / dimming). */\n seriesIndex?: number;\n}\n\n/** An end-of-line series-name label (racing charts). Rendered into a persistent,\n * keyed layer so it can fade in/out as collisions open and close. */\nexport interface EndLabel {\n /** Stable key (series id) for cross-frame reconciliation + the fade. */\n key: string;\n x: number;\n y: number;\n text: string;\n color: string;\n size: number;\n /** False when this label collides with a higher one → fades out. */\n visible: boolean;\n /**\n * Which way the text extends from the line's end point. `start` (default)\n * puts it to the right, following an LTR line that ends on the right; `end`\n * puts it to the left, which is where a mirrored (RTL) line ends.\n */\n side?: 'start' | 'end';\n}\n\n/** A data-point marker. `symbol` selects the shape (default circle). */\nexport interface SceneMarker {\n x: number;\n y: number;\n r: number;\n color: string;\n /** Shape — 'circle' (default) | 'square' | 'diamond' | 'triangle' | 'triangle-down'. */\n symbol?: import('../types').MdChartSymbol;\n /** Owning series (for hover emphasis / dimming). */\n seriesIndex?: number;\n /** Open marker: stroke in `color`, fill with `fill` (the surface) so the line\n * is occluded and the point reads as a ring. */\n hollow?: boolean;\n /** Interior fill for a hollow marker (usually the surface colour). */\n fill?: string;\n}\n\n/** An emoji / short-text point marker, or a data-value label, drawn by the DOM\n * overlay so it can animate with the point each frame. Anchored at (x, y). */\nexport interface GlyphMarker {\n x: number;\n y: number;\n text: string;\n /** Font size in px. */\n size: number;\n /**\n * Present → render as a styled data label (offset from the point, bold,\n * themed) instead of a centred emoji. dx/dy offset the anchor; anchorX/anchorY\n * are the CSS translate percentages.\n */\n label?: { color: string; weight: number; dx: number; dy: number; anchorX: string; anchorY: string };\n}\n\n/**\n * A filled bar rectangle. `radius` are the four corner radii in\n * CSS order `[topLeft, topRight, bottomRight, bottomLeft]` so the\n * renderers can round only the \"outer\" end (top for vertical bars,\n * inline-end for horizontal). Carries its category + series index\n * for hit-testing.\n */\nexport interface SceneBar {\n x: number;\n y: number;\n w: number;\n h: number;\n color: string;\n radius: [number, number, number, number];\n seriesIndex: number;\n dataIndex: number;\n /**\n * True for a horizontal-bar-chart bar (value runs along x). The intro/draw\n * animations need this because a short vertical bar can be wider than it is\n * tall, so the `w > h` aspect-ratio heuristic would misclassify it.\n */\n horizontal?: boolean;\n /**\n * Draw the bar as a CHEVRON pointing along the value axis: `1` toward the\n * high end, `-1` toward the low end, `0`/absent for an ordinary rectangle.\n *\n * The leading edge comes to a point and the trailing edge is cut with the\n * matching notch, so a chain of them interlocks — which is what a force\n * diagram is: contributions handed along in a direction, not stacked\n * quantities that happen to touch. Overrides `radius`.\n */\n arrow?: -1 | 0 | 1;\n /**\n * Cut the matching notch out of the TRAILING edge. Default true wherever\n * `arrow` is set; false for the segment sitting on the baseline, which has no\n * neighbour behind it to fill the notch — two stacks meeting at zero would\n * otherwise leave a lens-shaped hole between their two tails.\n */\n notch?: boolean;\n}\n\n/**\n * A pie / donut slice (an annular sector). Angles are in radians in\n * screen space (0 = +x / 3-o'clock, clockwise since y points down).\n * `innerR` 0 = solid pie; > 0 = donut ring.\n */\nexport interface SceneSlice {\n cx: number;\n cy: number;\n innerR: number;\n outerR: number;\n startAngle: number;\n endAngle: number;\n color: string;\n dataIndex: number;\n /** Owning series — set on a polar bar's ring segments so a hover can resolve\n * the exact segment (category + series), not just the ring. */\n seriesIndex?: number;\n /** Corner rounding in px, applied where the outer arc meets each radial edge.\n * Clamped by the renderer against the slice's own size. */\n cornerRadius?: number;\n /**\n * Separation from the neighbouring slices, in px — cut out of THIS slice's\n * own geometry rather than painted over it afterwards.\n *\n * Drawing the wedges edge to edge and stroking a line along each join is the\n * obvious way and it goes wrong in three places at once: the line keeps its\n * width while the wedge tapers, so it swallows a narrow slice's tip; every\n * join's line converges on the apex, where they pool into a blob; and a\n * stroke laid over two antialiased shapes that already meet blends with both.\n * A gap that is part of the shape has none of those failure modes — nothing\n * overlaps anything.\n *\n * Each radial edge is inset by half of this — a constant perpendicular\n * offset, so the separation reads the same width at the hub as at the rim.\n * Two such edges cross at `g / sin(sweep/2)`, which is why a solid pie's\n * slices are given a small common `innerR` to stop at rather than being run\n * to a point: past that crossing there is no wedge left to draw.\n */\n gap?: number;\n /** What shows through the gap. Painted as one shape under all the slices, so\n * a consumer can set a separator colour that isn't the chart's background. */\n gapColor?: string;\n /**\n * Fill with a gradient running outward along the slice's own mid-angle,\n * rather than flat. Decorative: it gives the ring depth without changing what\n * any slice means, so it is opt-in.\n */\n gradient?: { from: string; to: string };\n /**\n * Draw as a pill-ended band rather than a filled wedge — a stroked arc with\n * round caps. Filling gives square INNER corners (the corner rounding only\n * reaches the outer ones), and on a thin band those corners are the whole\n * shape: they poked past the slice they sit on. Stroking rounds both ends by\n * construction.\n */\n pill?: boolean;\n /**\n * Per-end round caps for a `pill` band. When EITHER is set, the arc is stroked\n * with flat (butt) ends and a round cap disc is added only where flagged — so a\n * chain of stacked segments abuts seamlessly (no rounded split at every join)\n * while the whole ring keeps a rounded head and tail. Absent (both undefined) →\n * the pill keeps round caps on both ends (a lone band / the pie's thin slice).\n */\n capStart?: boolean;\n capEnd?: boolean;\n}\n\n/**\n * A press ripple, clipped to the slice it started on.\n *\n * Declared on the scene rather than painted by the engine directly so it rides\n * along with whatever geometry that frame holds — including a drill in flight,\n * where the wedge it is clipped to is busy opening out into the next level.\n */\nexport interface SceneRipple {\n /** The slice it belongs to; it is clipped to that wedge's own path. */\n dataIndex: number;\n /** Where the press landed, in canvas px. */\n x: number;\n y: number;\n radius: number;\n color: string;\n /** 0..1, multiplied into whatever alpha the frame is already drawing at. */\n alpha: number;\n}\n\n/** A straight line — gridlines and axis lines. */\nexport interface SceneSegment {\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n color: string;\n width: number;\n /** Optional dash pattern (gridlines). */\n dash?: number[];\n}\n\n/**\n * A value label bound to a bar (by its series + data index) rather than to a\n * fixed position. The bar-label overlay recomputes its screen position from the\n * bar's CURRENT geometry every frame, so — unlike a {@link TextItem}, which is\n * synced once at the final layout — it tracks the bar as it grows in during the\n * entry animation instead of snapping to the final tip. `inside` centres it\n * within the bar (a stacked segment); otherwise it sits just past the bar's free\n * (value) end, on the low side when `atLowEnd` is set (a negative bar).\n */\nexport interface BarLabel {\n seriesIndex: number;\n dataIndex: number;\n text: string;\n color: string;\n size: number;\n fontWeight?: number;\n inside?: boolean;\n atLowEnd?: boolean;\n}\n\n/** A positioned text label rendered by the DOM overlay. */\nexport interface TextItem {\n x: number;\n y: number;\n text: string;\n color: string;\n /** CSS font shorthand or size in px (overlay resolves family). */\n fontSize: number;\n fontWeight?: number;\n align: 'start' | 'center' | 'end';\n baseline: 'top' | 'middle' | 'bottom';\n /** Rotation in degrees (rotated axis labels), default 0. */\n rotate?: number;\n /** A stable key so the overlay can diff/reuse nodes. */\n key: string;\n}\n\n/** A data point's pixel position + raw value, for hover lookup. */\nexport interface HoverPoint {\n x: number;\n y: number;\n value: number;\n /** Both edges, for a range series — the tooltip prints `low – high` rather\n * than the single `value` (which is only the band's top). */\n low?: number;\n high?: number;\n /** Effective marker at this point (shape keyword or emoji) so the hover\n * highlight matches it instead of always drawing a circle. */\n symbol?: string;\n /**\n * The point's OWN resolved colour, when it differs from the series colour — a\n * bar whose fill came from `pointColors` (a bar race, a per-category palette).\n * The hover dot and the tooltip swatch prefer it so they match the bar under\n * the cursor rather than the series default. Absent → the series colour.\n */\n color?: string;\n}\n\n/** Per-series hover index — maps an x data index to its point. */\nexport interface HoverSeries {\n seriesIndex: number;\n color: string;\n label: string;\n /**\n * The series draws neither a line nor markers, so there is no point for a\n * hover highlight to sit on — a fill-only layer or a range band. The dot\n * would land on the band's TOP EDGE, which on a stack is a cumulative total\n * and not a reading this series ever took. The crosshair and the tooltip row\n * still show; only the dot is dropped.\n */\n unanchored?: boolean;\n /** index → point (only for non-null, non-hidden points). */\n byIndex: Record<number, HoverPoint>;\n /**\n * The series' values aligned to the same indices as `byIndex`, INCLUDING the\n * ones that have no point: `null` where the series has a datum that is null\n * (or non-finite), `undefined` where it has no datum at all. Lets the tooltip\n * tell the two absences apart and offer a row for either.\n */\n values?: readonly (number | null | undefined)[];\n /** Per-series value formatter — set for multi-axis charts so each series'\n * tooltip value uses its own axis formatter. Falls back to the chart's. */\n valueFormat?: (v: number) => string;\n}\n\n/** A legend entry (rendered in the DOM overlay, clickable). */\nexport interface LegendItem {\n label: string;\n color: string;\n seriesIndex: number;\n hidden: boolean;\n x: number;\n y: number;\n}\n\n/**\n * Everything needed to paint one frame. `plot` is the inner\n * drawing rect (inside axis gutters); the backends clip series\n * geometry to it.\n */\nexport interface RenderScene {\n /**\n * Pixel position of the value axis' ZERO line, along the value axis (a y for\n * a vertical bar chart, an x for a horizontal one).\n *\n * The entry animation needs it: a bar has to grow from the line its value is\n * measured against, and for every segment of a stack but the first that line\n * is NOT its own base. Scaling each segment about its own edge collapses a\n * stack into a row of separate slivers partway up the plot instead of one\n * column rising off the axis. Absent for charts with no bars.\n */\n barBaseline?: number;\n width: number;\n height: number;\n plot: Rect;\n background?: string;\n /** Shaded axis ranges behind everything else (empty for most charts). */\n bands?: SceneBand[];\n gridlines: SceneSegment[];\n axisLines: SceneSegment[];\n areas: SceneArea[];\n /** Filled bars (bar chart / bar sparkline) — empty for line charts. */\n bars: SceneBar[];\n /** Pie / donut slices — empty for cartesian charts. */\n slices: SceneSlice[];\n lines: ScenePolyline[];\n markers: SceneMarker[];\n /** DOM-overlay emoji / text point markers (empty for most charts). */\n glyphs?: GlyphMarker[];\n /** End-of-line series-name labels (collision-managed, fade in/out). */\n endLabels?: EndLabel[];\n /** DOM-overlay text (tick labels, title, axis titles). */\n texts: TextItem[];\n /** DOM-overlay value labels bound to bars, repositioned from the bars' live\n * geometry each frame so they animate with the bars (absent for non-bar\n * charts, and for the range / stack-total labels which stay in `texts`). */\n barLabels?: BarLabel[];\n /** DOM-overlay legend (clickable) — empty when no legend. */\n legend: LegendItem[];\n /** Legend anchor: `top-start` … `bottom-end` / `left` / `right`. */\n legendPosition?: string;\n /**\n * Where a pie's centre-slot content should be anchored.\n *\n * NOT the plot rect's centre. A pie that sweeps less than a full turn is\n * fitted to the sector it actually paints, so its ring centre sits wherever\n * that sector's flat side is — the bottom edge, for a top half-donut. And the\n * hole of a half-donut is a half-disc, whose middle is above the ring centre,\n * so anchoring at the centre puts the caption across the arc rather than\n * inside it.\n */\n pieCenterSlot?: { x: number; y: number };\n /** The ring's own centre — the point every slice is measured from. Not the\n * plot centre once a partial sweep is fitted to its sector, and not\n * `pieCenterSlot`, which is the middle of the hole. */\n pieCenter?: { x: number; y: number };\n /** Width of the largest rectangle inside a donut's hole, so centre-slot\n * content can size itself against the space it actually has instead of\n * spilling over the ring. */\n pieHoleSize?: number;\n /** Height of that same rectangle. */\n pieHoleHeight?: number;\n /** Axes are transposed (independent axis vertical, value axis horizontal) —\n * the engine hit-tests hover by y and draws a horizontal crosshair. */\n inverted?: boolean;\n /** Polar (radial) BAR chart: the slices are concentric ring bands, so the\n * intro sweeps each ring along its ANGLE (drawn from nothing to its end) at a\n * fixed radius, rather than blooming a pie's wedges out from the centre. */\n polar?: boolean;\n /** Per-x pixel positions for hover hit-testing (category/value x). For an\n * inverted chart these are the vertical (main-axis) pixel positions. */\n xPositions: number[];\n /** The original x values (for tooltip headers). */\n xValues: import('../types').MdChartAxisValue[];\n /** Formatted x label per index (tooltip header). */\n xLabels: string[];\n /** Per-series data-point index for hover crosshair + tooltip. */\n hoverPoints: HoverSeries[];\n /** A press ripple in flight (pie/donut). */\n ripple?: SceneRipple;\n}\n","/*\n * Chart engine — DOM text overlay\n * ===========================================================\n * Renders the scene's text (title, tick labels, axis titles) and\n * the clickable legend as real DOM on top of the plot canvas.\n * Keeping text in the DOM (rather than baked into the canvas)\n * means it's crisp at any DPR, selectable, and — with the host's\n * a11y data table — keeps the chart accessible. Rebuilt each frame\n * (charts re-render occasionally, not per-frame) for simplicity.\n * ===========================================================\n */\n\nimport { LEGEND_SIDE_MAX_FRACTION } from './scene';\nimport type { EndLabel, GlyphMarker, LegendItem, RenderScene } from './scene';\nimport { chevronTipDepth } from './renderer-canvas';\n\nconst ALIGN_X: Record<string, string> = { start: '0', center: '-50%', end: '-100%' };\nconst ALIGN_Y: Record<string, string> = { top: '0', middle: '-50%', bottom: '-100%' };\n\nexport interface OverlayCallbacks {\n onLegendClick?: (item: LegendItem) => void;\n}\n\n/** `top-start` / `bottom-end` anchor to a corner; plain `top` / `bottom` centre. */\nfunction isCorner(pos: string): boolean {\n return pos.includes('-');\n}\n\n/**\n * Reconcile the end-of-line series-name labels into a PERSISTENT layer, keyed by\n * series, so each label element survives across frames — its `opacity` then\n * CSS-transitions, fading a name IN when its slot opens and OUT when it collides\n * with a higher one. Position tracks the line end directly (no lag).\n */\nexport function renderEndLabels(layer: HTMLElement, labels: EndLabel[] = [], fontFamily = 'sans-serif'): void {\n const seen = new Set<string>();\n for (const e of labels) {\n seen.add(e.key);\n let el = layer.querySelector<HTMLSpanElement>(`[data-k=\"${e.key}\"]`);\n if (!el) {\n el = document.createElement('span');\n el.dataset.k = e.key;\n el.style.cssText = 'position:absolute;white-space:nowrap;pointer-events:none;user-select:none;font-weight:500;opacity:0;transition:opacity 240ms ease';\n layer.appendChild(el);\n el.getBoundingClientRect(); // commit opacity:0 before the fade-in target\n }\n el.textContent = e.text;\n // The label hangs off the END of the line, so it extends away from the\n // data: right of the point for an LTR line, left of it once the scene is\n // mirrored (translate(-100%) right-aligns it onto that gap).\n const end = e.side === 'end';\n el.style.transform = end ? 'translate(-100%,-50%)' : 'translate(0,-50%)';\n el.style.left = `${end ? e.x - 12 : e.x + 12}px`;\n el.style.top = `${e.y}px`;\n el.style.fontSize = `${e.size}px`;\n el.style.color = e.color;\n el.style.fontFamily = fontFamily;\n el.style.opacity = e.visible ? '1' : '0';\n }\n // Series that vanished (e.g. toggled off) fade out, then are removed.\n for (const el of Array.from(layer.children) as HTMLElement[]) {\n if (!seen.has(el.dataset.k ?? '')) {\n el.style.opacity = '0';\n el.dataset.gone = '1';\n setTimeout(() => {\n if (el.dataset.gone === '1') el.remove();\n }, 280);\n } else {\n // `delete el.dataset.gone` is a silent no-op outside a real browser\n // (mock-doc keeps both the property and the attribute), which would leave\n // the pending timeout below free to remove a label that came back.\n el.removeAttribute('data-gone');\n }\n }\n}\n\n/**\n * (Re)draw the emoji / text point markers into their own layer. Kept out of\n * syncOverlay so the engine can re-render them each animation frame (they\n * rise / reveal / fade with the line) without rebuilding the static chrome.\n */\nexport function renderGlyphs(layer: HTMLElement, glyphs: GlyphMarker[] = [], fontFamily = 'sans-serif'): void {\n layer.textContent = '';\n for (const g of glyphs) {\n const el = document.createElement('span');\n el.textContent = g.text;\n const lbl = g.label;\n el.style.cssText = lbl\n ? [\n 'position:absolute',\n `left:${g.x + lbl.dx}px`,\n `top:${g.y + lbl.dy}px`,\n `transform:translate(${lbl.anchorX},${lbl.anchorY})`,\n `font:${lbl.weight} ${g.size}px ${fontFamily}`,\n `color:${lbl.color}`,\n 'line-height:1',\n 'white-space:nowrap',\n 'pointer-events:none',\n 'user-select:none',\n ].join(';')\n : [\n 'position:absolute',\n `left:${g.x}px`,\n `top:${g.y}px`,\n 'transform:translate(-50%,-50%)',\n `font-size:${g.size}px`,\n 'line-height:1',\n 'pointer-events:none',\n 'user-select:none',\n ].join(';');\n layer.appendChild(el);\n }\n}\n\n/**\n * (Re)draw the bar value labels into their own layer, positioning each from its\n * bar's CURRENT geometry so it tracks the bar's free end as the bar grows in\n * during the entry animation. Kept out of syncOverlay (which paints the static\n * chrome once) and re-called each frame like {@link renderGlyphs}. A label whose\n * bar isn't in the scene (a hidden series) is skipped.\n *\n * The bar the label belongs to may have been split into several pieces by a\n * broken value axis; the pieces share their cross-axis extent (only the value\n * axis is cut), so the label hangs off the OUTERMOST piece's free end — the\n * union of the pieces along the value axis.\n */\nexport function renderBarLabels(layer: HTMLElement, scene: RenderScene, fontFamily = 'sans-serif'): void {\n layer.textContent = '';\n const labels = scene.barLabels;\n if (!labels?.length) return;\n for (const bl of labels) {\n const pieces = scene.bars.filter((b) => b.seriesIndex === bl.seriesIndex && b.dataIndex === bl.dataIndex);\n if (!pieces.length) continue;\n const horizontal = !!pieces[0].horizontal;\n let loX = Infinity;\n let hiX = -Infinity;\n let loY = Infinity;\n let hiY = -Infinity;\n for (const b of pieces) {\n loX = Math.min(loX, b.x);\n hiX = Math.max(hiX, b.x + b.w);\n loY = Math.min(loY, b.y);\n hiY = Math.max(hiY, b.y + b.h);\n }\n let x: number;\n let y: number;\n let align: keyof typeof ALIGN_X;\n let baseline: keyof typeof ALIGN_Y;\n if (bl.inside) {\n // Centred within the bar (a stacked segment) — no free end to hang off.\n x = (loX + hiX) / 2;\n y = (loY + hiY) / 2;\n align = 'center';\n baseline = 'middle';\n // A chevron is not its rect: the drawn shape runs from the NOTCH APEX to\n // the TIP, both of which sit outside the rect by the tip depth. Centring\n // on the rect therefore lands the number short of the segment's visible\n // middle. Shift it along the arrow by half the two overhangs so it reads\n // as centred in the shape a reader actually sees.\n const arrow = pieces[0].arrow;\n if (arrow) {\n const tip = chevronTipDepth(horizontal ? hiY - loY : hiX - loX);\n const cut = pieces[0].notch === false ? 0 : tip;\n const shift = (arrow * (tip + cut)) / 2;\n if (horizontal) x += shift;\n else y -= shift;\n }\n } else if (horizontal) {\n // Just past the bar's free end along x; the label sits on the low side for\n // a negative bar, the high side otherwise.\n y = (loY + hiY) / 2;\n baseline = 'middle';\n x = bl.atLowEnd ? loX - 4 : hiX + 4;\n align = bl.atLowEnd ? 'end' : 'start';\n } else {\n // Vertical: past the top for a positive bar, below the bottom for a negative.\n x = (loX + hiX) / 2;\n align = 'center';\n y = bl.atLowEnd ? hiY + 4 : loY - 4;\n baseline = bl.atLowEnd ? 'top' : 'bottom';\n }\n const el = document.createElement('span');\n el.textContent = bl.text;\n el.style.cssText = [\n 'position:absolute',\n `left:${x}px`,\n `top:${y}px`,\n `transform:translate(${ALIGN_X[align]},${ALIGN_Y[baseline]})`,\n `color:${bl.color}`,\n `font:${bl.fontWeight ?? 400} ${bl.size}px ${fontFamily}`,\n 'white-space:nowrap',\n 'pointer-events:none',\n 'user-select:none',\n ].join(';');\n layer.appendChild(el);\n }\n}\n\n/**\n * The legend item a persistent chip currently stands for, and the live callbacks\n * for a persistent nav. Chips outlive a render (see `syncOverlay`), so the click\n * handler must read the CURRENT item/callback rather than close over the one that\n * happened to exist when the node was created.\n */\nconst chipItem = new WeakMap<HTMLElement, LegendItem>();\nconst navCallbacks = new WeakMap<HTMLElement, OverlayCallbacks>();\n\n/** (Re)render the overlay DOM for a scene into `layer`. */\n/**\n * @param layer clipped layer holding the text items\n * @param legendLayer where the legend goes. Defaults to `layer`, but the charts\n * pass a NON-clipping sibling: a focus ring is drawn outside the chip's box,\n * and the legend sits flush against the plot's top edge, so inside the\n * clipped layer the ring loses its outer pixels.\n */\nexport function syncOverlay(\n layer: HTMLElement,\n scene: RenderScene,\n fontFamily: string,\n cb: OverlayCallbacks = {},\n rtl = false,\n legendLayer: HTMLElement = layer,\n): void {\n // The legend is PERSISTENT: a consumer that re-feeds `series` every frame (a\n // line-race) re-renders the overlay at 60fps, and a recreated <button> loses\n // the click. A human click holds ~50-150ms, so mousedown and mouseup would\n // land on different nodes and the browser would never fire `click` on either.\n // Everything else here is stateless text and is cheaper to rebuild.\n // Direct children only. Deliberately NOT `:scope > [part=\"legend\"]` — mock-doc's\n // selector engine throws outright on `:scope` (as do older engines), which made\n // this whole function unrunnable under spec tests. Same reasoning as\n // `collectOptions` in utils/select-options.ts.\n const keptNav =\n (Array.from(legendLayer.children) as HTMLElement[]).find(\n (c) => c.getAttribute('part') === 'legend',\n ) ?? null;\n for (const child of Array.from(layer.childNodes)) {\n if (child !== keptNav) child.remove();\n }\n\n for (const t of scene.texts) {\n const span = document.createElement('span');\n span.textContent = t.text;\n if (t.key) span.dataset.key = t.key;\n span.style.cssText = [\n 'position:absolute',\n `left:${t.x}px`,\n `top:${t.y}px`,\n `transform:translate(${ALIGN_X[t.align]},${ALIGN_Y[t.baseline]})${t.rotate ? ` rotate(${t.rotate}deg)` : ''}`,\n `color:${t.color}`,\n `font:${t.fontWeight ?? 400} ${t.fontSize}px ${fontFamily}`,\n 'white-space:nowrap',\n 'pointer-events:none',\n ].join(';');\n // The legend now lives in its own layer, so there is nothing to insert\n // before — and passing a node that isn't a child of `layer` would throw.\n // It still paints above the labels, because its layer is stacked after.\n layer.insertBefore(span, keptNav?.parentNode === layer ? keptNav : null);\n }\n\n // Legend — a wrap-flow row anchored to one corner/edge inside the plot.\n const visibleLegend = scene.legend.filter((l) => scene.legend.length > 1);\n if (visibleLegend.length) {\n const pos = scene.legendPosition ?? 'top-end';\n const isSide = pos === 'left' || pos === 'right';\n const atBottom = pos.startsWith('bottom');\n // `start`/`end` are logical: they follow the reading direction, so they swap\n // sides in RTL — as `left`/`right` (physical by name) deliberately do not.\n const logicalStart = pos.endsWith('start') || pos.endsWith('end') ? pos.endsWith('start') !== rtl : pos === 'left';\n const atStart = logicalStart;\n const nav = keptNav ?? document.createElement('div');\n nav.setAttribute('part', 'legend');\n // One delegated listener, bound once to the persistent nav. It reads the\n // chip's CURRENT item and the latest callbacks, so reused nodes never fire a\n // stale closure from an earlier render.\n if (!navCallbacks.has(nav)) {\n nav.addEventListener('click', (ev) => {\n const chip = (ev.target as HTMLElement | null)?.closest?.('button[data-series-index]') as HTMLElement | null;\n const item = chip ? chipItem.get(chip) : undefined;\n if (item) navCallbacks.get(nav)?.onLegendClick?.(item);\n });\n }\n navCallbacks.set(nav, cb);\n // Side legends (left/right) are a vertically-centred column. A corner\n // top/bottom legend anchors to that corner (max 88% wide). A PLAIN top /\n // bottom legend spans the FULL chart width so a crammed legend wraps across\n // the whole width (fewer rows) instead of a narrow centred block.\n if (isSide) {\n nav.style.cssText = [\n 'position:absolute',\n 'top:50%',\n pos === 'left' ? 'left:12px' : 'right:12px',\n 'transform:translateY(-50%)',\n 'display:flex',\n 'flex-direction:column',\n 'align-items:flex-start',\n 'gap:6px',\n 'max-height:92%',\n `max-width:${LEGEND_SIDE_MAX_FRACTION * 100}%`,\n // The clip keeps a long column from spilling over the plot, but it also\n // cut the focus ring off a chip against the edge — the ring is drawn\n // OUTSIDE the button's box, so it needs room inside the clip to land in.\n 'box-sizing:border-box',\n 'padding:6px',\n 'overflow:hidden',\n 'pointer-events:auto',\n ].join(';');\n } else if (isCorner(pos)) {\n nav.style.cssText = [\n 'position:absolute',\n atBottom ? 'bottom:2px' : 'top:2px',\n atStart ? 'left:12px' : 'right:12px',\n 'display:flex',\n 'flex-wrap:wrap',\n 'gap:4px 12px',\n atStart ? 'justify-content:flex-start' : 'justify-content:flex-end',\n 'max-width:88%',\n 'pointer-events:auto',\n ].join(';');\n } else {\n nav.style.cssText = [\n 'position:absolute',\n atBottom ? 'bottom:2px' : 'top:2px',\n 'left:12px',\n 'right:12px',\n 'display:flex',\n 'flex-wrap:wrap',\n 'gap:4px 12px',\n 'justify-content:center',\n 'pointer-events:auto',\n ].join(';');\n }\n // Reconcile chips by series index so each <button> survives re-renders.\n const existing = new Map<string, HTMLElement>();\n for (const el of Array.from(nav.children) as HTMLElement[]) {\n existing.set(el.dataset.seriesIndex ?? '', el);\n }\n visibleLegend.forEach((l, i) => {\n const key = String(l.seriesIndex);\n let chip = existing.get(key);\n if (!chip) {\n chip = document.createElement('button');\n (chip as HTMLButtonElement).type = 'button';\n chip.dataset.seriesIndex = key;\n chip.append(document.createElement('span'), document.createElement('span'));\n }\n existing.delete(key);\n chipItem.set(chip, l);\n chip.style.cssText = [\n 'display:inline-flex',\n 'align-items:center',\n 'gap:6px',\n 'background:none',\n 'border:none',\n 'padding:2px 4px',\n 'cursor:pointer',\n // Keep each entry on one line + never shrink, so labels don't wrap\n // internally (which would inflate the legend's measured height).\n 'white-space:nowrap',\n // A side legend is a narrow column, so a long name has nowhere to go:\n // it was clipped mid-word by the nav's overflow and read as a typo\n // (\"Organic searc\"). Let the chip shrink there and ellipsise instead —\n // a cut is unavoidable, but it should look deliberate.\n isSide ? 'flex:0 1 auto' : 'flex:none',\n 'min-width:0',\n 'max-width:100%',\n `font:400 ${scene.texts[0]?.fontSize ?? 11}px ${fontFamily}`,\n `color:${l.hidden ? 'var(--md-sys-color-outline, #79747E)' : 'var(--md-sys-color-on-surface-variant, #49454F)'}`,\n l.hidden ? 'text-decoration:line-through' : '',\n ].join(';');\n // It toggles a series, so it is a toggle button: without aria-pressed a\n // screen reader announces \"button\" and never says whether the series is\n // currently shown or hidden. Set every render, since that is what changes.\n chip.setAttribute('aria-pressed', String(!l.hidden));\n const [dot, txt] = Array.from(chip.children) as HTMLElement[];\n dot.style.cssText = `width:10px;height:10px;border-radius:3px;background:${l.color};opacity:${l.hidden ? 0.4 : 1};flex:none`;\n txt.style.cssText = 'overflow:hidden;text-overflow:ellipsis;min-width:0';\n if (txt.textContent !== l.label) txt.textContent = l.label;\n // The clipped text is still the full name to a screen reader, but a\n // sighted user only sees \"Organic sea…\" — so carry it in the tooltip too.\n if (chip.title !== l.label) chip.title = l.label;\n // Only touch the DOM when the order actually changed — re-appending a node\n // mid-gesture is pointless churn.\n if (nav.children[i] !== chip) nav.insertBefore(chip, nav.children[i] ?? null);\n });\n for (const el of existing.values()) el.remove();\n // Already-connected nav stays exactly where it is — moving it is needless\n // churn during a click.\n if (nav.parentNode !== legendLayer) legendLayer.appendChild(nav);\n } else {\n keptNav?.remove();\n }\n}\n","/*\n * Chart engine — entry motion\n * ===========================================================\n * The intro animation played once on first render. Several\n * variants (see MdChartAnimation) all reduce to a pure\n * scene→scene transform plus an optional layer opacity, so both\n * renderer backends animate identically — the engine just draws\n * `stepAnimation(variant, scene, t)` per rAF frame. Honours\n * `prefers-reduced-motion` and a configurable duration.\n * ===========================================================\n */\n\nimport type { MdChartAnimation } from '../types';\nimport { withAlpha } from './color';\nimport type { Pt } from './geometry';\nimport type { RenderScene, SceneBar } from './scene';\n\n/**\n * Shared intro duration in ms — MD3 `--md-sys-motion-duration-extra-long1`\n * (700ms), the length for a large, expressive entering transition. Every chart\n * type (line, area, bar, pie, sparkline) runs its entrance for exactly this long\n * so their intros play in lockstep.\n */\nexport const INTRO_MS = 700;\n\nconst clamp01 = (n: number): number => (n < 0 ? 0 : n > 1 ? 1 : n);\n\n// ── easings ────────────────────────────────────────────────\n\n/**\n * Gentle critically-damped spring: 0 at t=0, settles at 1 with a\n * small (~2%) overshoot around the middle for an expressive feel.\n * May transiently exceed 1 (the overshoot) — callers that map it to\n * a bounded quantity (opacity, reveal fraction) must clamp.\n */\nexport function expressiveEase(t: number): number {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n return 1 - Math.exp(-7 * t) * Math.cos(6 * t);\n}\n\n/** MD3 decelerate — fast out, slow in, no overshoot. */\nexport function easeOutCubic(t: number): number {\n const c = clamp01(t);\n return 1 - Math.pow(1 - c, 3);\n}\n\n/** Symmetric accelerate→decelerate, for a deliberate \"draw\" sweep. */\nexport function easeInOutCubic(t: number): number {\n const c = clamp01(t);\n return c < 0.5 ? 4 * c * c * c : 1 - Math.pow(-2 * c + 2, 3) / 2;\n}\n\n/**\n * Evaluate a CSS `cubic-bezier(x1, y1, x2, y2)` timing curve as a plain easing\n * function (the endpoints are fixed at P0 = (0,0) and P3 = (1,1), as in CSS).\n * For an input progress `x ∈ [0,1]` it solves the Bézier's x(t) = x for the\n * curve parameter t (Newton–Raphson, bisection fallback) and returns y(t).\n *\n * This is the bridge from the MD3 motion-easing TOKENS — which are authored as\n * `cubic-bezier(...)` — to the numeric per-frame eases the canvas engines need.\n * See `emphasizedDecelerate`.\n */\nexport function cubicBezier(x1: number, y1: number, x2: number, y2: number): (t: number) => number {\n const cx = 3 * x1;\n const bx = 3 * (x2 - x1) - cx;\n const ax = 1 - cx - bx;\n const cy = 3 * y1;\n const by = 3 * (y2 - y1) - cy;\n const ay = 1 - cy - by;\n const sampleX = (t: number): number => ((ax * t + bx) * t + cx) * t;\n const sampleY = (t: number): number => ((ay * t + by) * t + cy) * t;\n const slopeX = (t: number): number => (3 * ax * t + 2 * bx) * t + cx;\n return (x: number): number => {\n if (x <= 0) return 0;\n if (x >= 1) return 1;\n let t = x;\n for (let i = 0; i < 8; i++) {\n const err = sampleX(t) - x;\n if (Math.abs(err) < 1e-6) return sampleY(t);\n const d = slopeX(t);\n if (Math.abs(d) < 1e-6) break;\n t -= err / d;\n }\n // Bisection fallback if Newton stalled or wandered out of the unit interval.\n let lo = 0;\n let hi = 1;\n t = x;\n for (let i = 0; i < 24; i++) {\n const err = sampleX(t) - x;\n if (Math.abs(err) < 1e-6) break;\n if (err > 0) hi = t;\n else lo = t;\n t = (lo + hi) / 2;\n }\n return sampleY(t);\n };\n}\n\n/**\n * MD3 `--md-sys-motion-easing-emphasized-decelerate`:\n * `cubic-bezier(0.05, 0.7, 0.1, 1)` — the curve for an element ENTERING the\n * frame (a fast start easing into a long, gentle settle, no overshoot). This is\n * the single shared easing behind every chart's entrance.\n */\nexport const emphasizedDecelerate = cubicBezier(0.05, 0.7, 0.1, 1);\n\n/** The eased-progress function for a variant. */\nexport function easingFor(variant: MdChartAnimation): (t: number) => number {\n switch (variant) {\n case 'draw':\n case 'stagger':\n return easeInOutCubic;\n case 'expressive':\n case 'grow':\n case 'fade':\n default:\n // The unified MD3 entering-element curve — one easing for every chart's\n // grow-and-fade intro.\n return emphasizedDecelerate;\n }\n}\n\nexport function prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && !!window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n// ── spatial transforms (scene → scene) ─────────────────────\n\n/** Whether a bar animates along the horizontal (value-on-x) axis. Prefer the\n * explicit layout flag; fall back to the aspect ratio for flagless bars (e.g.\n * line-chart reference bands) — a short vertical DATA bar can be wider than\n * tall, so the heuristic alone would misclassify it. */\nfunction isHorizontalBar(b: SceneBar): boolean {\n return b.horizontal ?? b.w > b.h;\n}\n\n/**\n * A bar grows out of the value axis' zero line.\n *\n * Both of the bar's edges are scaled about `base`, not just its length, which is\n * what makes a STACK animate as one column: every segment's boundary moves in\n * proportion, so the segments stay joined and stretch apart as the column rises.\n * Scaling each segment about its own base instead leaves a row of zero-height\n * slivers stranded partway up the plot at t=0 — they read as stray horizontal\n * lines, and the segments arrive as separate slices rather than as one bar.\n *\n * With no `base` (a bar in a chart that never computed one) it falls back to the\n * bar's own baseline edge, which is the same thing for an unstacked bar.\n */\nfunction growBar(b: SceneBar, e: number, base?: number): SceneBar {\n if (isHorizontalBar(b)) {\n const x0 = base ?? b.x;\n const a = x0 + (b.x - x0) * e;\n const z = x0 + (b.x + b.w - x0) * e;\n return { ...b, x: Math.min(a, z), w: Math.abs(z - a) };\n }\n const y0 = base ?? b.y + b.h;\n const a = y0 + (b.y - y0) * e;\n const z = y0 + (b.y + b.h - y0) * e;\n return { ...b, y: Math.min(a, z), h: Math.abs(z - a) };\n}\n\n/** The scene with its data geometry lifted from the axis baseline to\n * progress `e` (0..1). */\n/**\n * Animate the intro of the scene's slices.\n *\n * PIE: the whole ring GROWS from the centre — every wedge's radii scaled by `e`\n * with its angles already final — so the donut scales up as one and fades in\n * with the rest of the layer. This is the pie's take on the single shared\n * grow-and-fade entrance every chart type uses (no per-petal stagger or sweep).\n *\n * POLAR BAR: each concentric ring GROWS from its baseline — every segment scaled\n * in proportion about the ring's start angle by `e`, so the whole band opens as\n * one (its segments staying joined) exactly the way a stacked linear bar rises\n * from its baseline. Growing the RADIUS instead would collapse every ring to the\n * centre, which a wrapped value axis never does.\n */\nfunction animateSlices(scene: RenderScene, e: number): RenderScene['slices'] {\n if (scene.polar) {\n // The angle each ring grows FROM — its start, the value baseline.\n const base = new Map<number, number>();\n for (const s of scene.slices) {\n const cur = base.get(s.dataIndex);\n if (cur === undefined || s.startAngle < cur) base.set(s.dataIndex, s.startAngle);\n }\n return scene.slices.map((s) => {\n const s0 = base.get(s.dataIndex)!;\n // Scale both edges about the ring's baseline, so the band grows as a whole\n // and the segments stay joined — the radial twin of growBar (which scales a\n // stack's edges about the value axis' zero line).\n return { ...s, startAngle: s0 + (s.startAngle - s0) * e, endAngle: s0 + (s.endAngle - s0) * e };\n });\n }\n // Uniform grow-from-centre: radii × e, angles unchanged. The layer fade\n // (see stepAnimation) carries the opacity.\n const g = clamp01(e);\n return scene.slices.map((s) => ({ ...s, innerR: s.innerR * g, outerR: s.outerR * g }));\n}\n\nexport function easeScene(scene: RenderScene, e: number): RenderScene {\n const baseY = scene.plot.y + scene.plot.height;\n const lift = (y: number) => baseY + (y - baseY) * e;\n const liftPts = (pts: Pt[]) => pts.map((p) => ({ x: p.x, y: lift(p.y) }));\n return {\n ...scene,\n lines: scene.lines.map((l) => {\n if (!l.radial) return { ...l, points: liftPts(l.points) };\n // A radial separator must not be LIFTED (see ScenePolyline.radial), but it\n // does have to grow with the ring it divides, or it hangs at full length\n // over a pie that is still unfolding.\n const cx = scene.plot.x + scene.plot.width / 2;\n const cy = scene.plot.y + scene.plot.height / 2;\n const g = clamp01(e);\n return { ...l, points: l.points.map((pt) => ({ x: cx + (pt.x - cx) * g, y: cy + (pt.y - cy) * g })) };\n }),\n areas: scene.areas.map((a) => ({ ...a, points: liftPts(a.points), basePoints: a.basePoints ? liftPts(a.basePoints) : undefined })),\n markers: scene.markers.map((m) => ({ ...m, y: lift(m.y) })),\n glyphs: scene.glyphs?.map((g) => ({ ...g, y: lift(g.y) })),\n endLabels: scene.endLabels?.map((e) => ({ ...e, y: lift(e.y) })),\n bars: scene.bars.map((b) => growBar(b, e, scene.barBaseline)),\n slices: animateSlices(scene, e),\n };\n}\n\n/** How much of a drill is spent fading the arriving level in over the one it\n * is opening out of. */\nconst DRILL_CROSSFADE = 0.5;\n\n/** The real (non-hover-band) slices of a pie scene, in ring order. */\nfunction ringSlices(scene: RenderScene) {\n return scene.slices.filter((s) => !s.pill && s.endAngle !== s.startAngle);\n}\n\n/**\n * A drill-down as the clicked wedge SPLITTING into its contents.\n *\n * At `p = 0` this is the outer level, untouched. As `p` rises the pivot wedge's\n * angular span opens out toward the whole ring while its siblings close into\n * what is left, and the inner level — laid inside that opening span, and fading\n * up — takes its place. At `p = 1` it is the inner level, exactly.\n *\n * Nothing scales, moves or blooms: radii are each level's own and only ANGLES\n * are interpolated, so at every frame the picture is a complete ring made of\n * correctly-shaped wedges. Growing the new level from a point instead reads as\n * a second chart arriving rather than as this one opening up.\n *\n * The opening span also rotates its leading edge back to the ring's start, or\n * the inner level would arrive turned by however far round the pivot sat.\n *\n * Returns the two layers to paint, the second over the first.\n */\nexport function splitScene(\n outer: RenderScene,\n inner: RenderScene,\n pivotIndex: number,\n pRaw: number,\n): { base: RenderScene; over: RenderScene; overAlpha: number } | null {\n const p = clamp01(pRaw);\n const outs = ringSlices(outer);\n const ins = ringSlices(inner);\n if (!outs.length || !ins.length) return null;\n const pivot = outs.find((s) => s.dataIndex === pivotIndex) ?? outs[0];\n const ringStart = outs[0].startAngle;\n const total = outs.reduce((acc, s) => acc + (s.endAngle - s.startAngle), 0);\n const pivotSpan = pivot.endAngle - pivot.startAngle;\n const rest = total - pivotSpan;\n // The window the pivot has opened: its own span at p=0, the whole ring at 1.\n const w = pivotSpan + rest * p;\n const w0 = pivot.startAngle + (ringStart - pivot.startAngle) * p;\n // What the siblings have left to share.\n const k = Math.abs(rest) < 1e-9 ? 0 : (total - w) / rest;\n\n // Siblings follow the window in ring order, wrapping past the pivot.\n const order = [...outs.slice(outs.indexOf(pivot) + 1), ...outs.slice(0, outs.indexOf(pivot))];\n let cursor = w0 + w;\n const base = order.map((s) => {\n const span = (s.endAngle - s.startAngle) * k;\n const a0 = cursor;\n cursor += span;\n return { ...s, startAngle: a0, endAngle: cursor };\n });\n base.push({ ...pivot, startAngle: w0, endAngle: w0 + w });\n\n // The inner level, laid inside that window.\n const innerStart = ins[0].startAngle;\n const innerTotal = ins.reduce((acc, s) => acc + (s.endAngle - s.startAngle), 0) || 1;\n const map = (a: number) => w0 + ((a - innerStart) / innerTotal) * w;\n const over = ins.map((s) => ({ ...s, startAngle: map(s.startAngle), endAngle: map(s.endAngle) }));\n\n return {\n base: { ...outer, slices: base, lines: [], gridlines: [], texts: [] },\n over: { ...inner, slices: over, lines: [], gridlines: [], texts: [], background: undefined },\n overAlpha: clamp01(p / DRILL_CROSSFADE),\n };\n}\n\n/** Trim an x-monotonic polyline to x ≤ cutX, interpolating a boundary/** Trim an x-monotonic polyline to x ≤ cutX, interpolating a boundary\n * point on the straddling segment so the reveal edge is smooth. */\nfunction trimPolylineX(pts: Pt[], cutX: number): Pt[] {\n if (!pts.length) return pts;\n const out: Pt[] = [];\n for (let i = 0; i < pts.length; i++) {\n const p = pts[i];\n if (p.x <= cutX) {\n out.push(p);\n } else {\n if (i > 0) {\n const a = pts[i - 1];\n const span = p.x - a.x || 1;\n const f = (cutX - a.x) / span;\n out.push({ x: cutX, y: a.y + (p.y - a.y) * f });\n }\n break;\n }\n }\n return out;\n}\n\n/** The scene revealed left-to-right (draw): lines/areas trimmed at the\n * sweep, markers past the sweep hidden, bars stagger-grown as the sweep\n * crosses them, pie slices swept angularly. Chrome stays static. */\n/**\n * A drill transition for bars: the incoming level's columns RISE from the\n * baseline at their final slots — a cascade, not a slide.\n *\n * Down (`split = true`) grows the columns in a left-to-right CASCADE (each\n * category a beat after the last); up (`split = false`) grows them all together.\n * Either way a bar keeps its final position and full width and only its HEIGHT\n * grows in, so nothing ever appears as a small/compressed bar mid-transition.\n * `from`/`size` (the old pivot band) are retained in the signature but unused.\n */\n/** Fraction of the timeline the LAST category waits before it begins to part, so\n * the children CASCADE out of the parent in reading order rather than all at\n * once — the choreography that makes the split feel expressive. */\nconst DRILL_STAGGER = 0.3;\n\nexport function drillScene(scene: RenderScene, from: number, size: number, t: number, split = false): RenderScene {\n // `from`/`size` (the clicked column's band) are no longer read: the drill grows\n // in place at each bar's FINAL slot rather than unfolding out of the column,\n // which is what removed the small/thin bar it used to flash mid-transition.\n const tc = clamp01(t);\n const maxDi = split ? Math.max(0, ...scene.bars.map((b) => b.dataIndex)) : 0;\n return {\n ...scene,\n bars: scene.bars.map((b) => {\n // Grow every bar from the baseline at its final slot — no horizontal motion,\n // so a child is a full-width bar rising in place, never a thin/small bar.\n // DOWN cascades left-to-right (each category begins a beat after the last —\n // the stagger); UP rises as one block (split=false → every lag is 0). The\n // rise uses the SAME MD3 emphasized-decelerate curve as the chart intro, so\n // a drilled level rises exactly like a freshly-entering one (and, being\n // monotonic to 1, never overshoots past a bar's own gridline).\n const lag = split && maxDi > 0 ? (b.dataIndex / maxDi) * DRILL_STAGGER : 0;\n const g = emphasizedDecelerate(clamp01((tc - lag) / (1 - lag || 1)));\n return growBar(b, g, scene.barBaseline);\n }),\n };\n}\n\nexport function revealScene(scene: RenderScene, e: number): RenderScene {\n const p = scene.plot;\n const ec = clamp01(e);\n const cutX = p.x + ec * p.width;\n const cutY = p.y + ec * p.height;\n return {\n ...scene,\n lines: scene.lines.map((l) => (l.radial ? l : { ...l, points: trimPolylineX(l.points, cutX) })),\n areas: scene.areas.map((a) => ({\n ...a,\n points: trimPolylineX(a.points, cutX),\n basePoints: a.basePoints ? trimPolylineX(a.basePoints, cutX) : undefined,\n })),\n markers: scene.markers.filter((m) => m.x <= cutX),\n glyphs: scene.glyphs?.filter((g) => g.x <= cutX),\n bars: scene.bars.map((b) => {\n // Sweep along the category axis: x for vertical bars, y for horizontal.\n const localE = isHorizontalBar(b) ? clamp01((cutY - b.y) / Math.max(b.h, 1)) : clamp01((cutX - b.x) / Math.max(b.w, 1));\n return growBar(b, localE, scene.barBaseline);\n }),\n slices: scene.slices.map((s) => ({ ...s, endAngle: s.startAngle + (s.endAngle - s.startAngle) * ec })),\n };\n}\n\n/** Distinct series indices present in the scene's lines, ascending. */\nfunction seriesOrder(scene: RenderScene): number[] {\n const set = new Set<number>();\n for (const l of scene.lines) set.add(l.seriesIndex ?? 0);\n return [...set].sort((a, b) => a - b);\n}\n\n/**\n * Sequential per-series reveal: each series draws left-to-right in its own\n * 1/N slice of the timeline, so line 1 finishes before line 2 begins. `tRaw`\n * is the whole-timeline progress (0..1); each series' local progress is\n * `tRaw*N - rank`, eased. Glyphs / end-labels carry no series index, so they\n * follow the global sweep.\n */\nexport function staggerReveal(scene: RenderScene, tRaw: number): RenderScene {\n const order = seriesOrder(scene);\n const n = order.length || 1;\n const rank = new Map(order.map((si, k) => [si, k]));\n const p = scene.plot;\n const cutXFor = (si: number | undefined): number => {\n const k = rank.get(si ?? 0) ?? 0;\n return p.x + easeInOutCubic(clamp01(tRaw * n - k)) * p.width;\n };\n const globalCut = p.x + easeInOutCubic(clamp01(tRaw)) * p.width;\n return {\n ...scene,\n lines: scene.lines.map((l) => (l.radial ? l : { ...l, points: trimPolylineX(l.points, cutXFor(l.seriesIndex)) })),\n areas: scene.areas.map((a) => ({\n ...a,\n points: trimPolylineX(a.points, cutXFor(a.seriesIndex)),\n basePoints: a.basePoints ? trimPolylineX(a.basePoints, cutXFor(a.seriesIndex)) : undefined,\n })),\n markers: scene.markers.filter((m) => m.x <= cutXFor(m.seriesIndex)),\n glyphs: scene.glyphs?.filter((g) => g.x <= globalCut),\n bars: scene.bars.map((b) => growBar(b, clamp01((globalCut - b.x) / Math.max(b.w, 1)), scene.barBaseline)),\n slices: scene.slices.map((s) => ({ ...s, endAngle: s.startAngle + (s.endAngle - s.startAngle) * clamp01(tRaw) })),\n };\n}\n\n// ── per-frame driver ───────────────────────────────────────\n\nexport interface AnimationSpec {\n /** Variant; falls back to `animate === false ? 'none' : 'expressive'`. */\n animation?: MdChartAnimation;\n /** Duration override in ms; ≤ 0 disables. Default INTRO_MS. */\n animationDuration?: number;\n /** Legacy on/off flag (pre-variant). `false` → `'none'`. */\n animate?: boolean;\n}\n\n/** Resolve the effective variant + duration from a spec (with back-compat). */\nexport function resolveIntro(spec: AnimationSpec): { variant: MdChartAnimation; duration: number } {\n let variant: MdChartAnimation = spec.animation ?? (spec.animate === false ? 'none' : 'expressive');\n const requested = spec.animationDuration != null ? spec.animationDuration : INTRO_MS;\n // A finite positive duration is required; 0, negative, NaN and Infinity all\n // disable the intro (an Infinity/NaN duration would make the rAF loop's\n // `tRaw >= 1` never fire → a non-terminating animation).\n const ok = Number.isFinite(requested) && requested > 0;\n if (!ok) variant = 'none';\n return { variant, duration: ok ? requested : INTRO_MS };\n}\n\n/** One animation frame: the scene to draw + the canvas-layer opacity to\n * apply, for a raw timeline progress `tRaw` (0..1). */\n/**\n * Fade the GRIDLINES in over the first half of the intro.\n *\n * At t=0 the data has no extent yet — a bar has no height, a line no length —\n * so a grid drawn at full strength is the only thing on the canvas: a set of\n * horizontal rules that flash up before the chart arrives. Ramping them in\n * ahead of the data (full strength by the halfway point) means the plot fills\n * rather than the grid appearing first and waiting to be used.\n *\n * The axis frame is deliberately NOT ramped: it is the edge of the plot, not a\n * reading, and it holds the shape of the chart steady while the rest arrives.\n */\nfunction fadeGrid(scene: RenderScene, e: number): RenderScene['gridlines'] {\n const a = clamp01(e * 2);\n if (a >= 1) return scene.gridlines;\n return scene.gridlines.map((l) => ({ ...l, color: withAlpha(l.color, a) }));\n}\n\nexport function stepAnimation(variant: MdChartAnimation, target: RenderScene, tRaw: number): { scene: RenderScene; alpha: number } {\n const e = easingFor(variant)(clamp01(tRaw));\n switch (variant) {\n case 'fade':\n return { scene: target, alpha: clamp01(e) };\n case 'draw':\n return { scene: { ...revealScene(target, e), gridlines: fadeGrid(target, e) }, alpha: 1 };\n case 'stagger': {\n // staggerReveal applies per-series easing internally, so it takes raw t.\n const t = clamp01(tRaw);\n return { scene: { ...staggerReveal(target, t), gridlines: fadeGrid(target, t) }, alpha: 1 };\n }\n case 'grow':\n case 'expressive':\n default:\n // The single shared entrance: the geometry GROWS from the baseline\n // (easeScene — bars/areas/lines rise, pie scales from its centre) while the\n // whole layer FADES in (alpha). Same curve, same look, for every chart type.\n return { scene: easeScene(target, e), alpha: clamp01(e) };\n }\n}\n","/*\n * Chart engine — hover crosshair + tooltip\n * ===========================================================\n * Builds the DOM hover UI (a plot-height crosshair, highlighted\n * per-series dots, and an MD3-styled tooltip card) for a hovered\n * x index. Lives in its own overlay layer so it updates on\n * pointermove without re-running the plot render.\n * ===========================================================\n */\n\nimport { prefersReducedMotion } from './animate';\nimport {\n isDomNode,\n type MdChartMissingFormatter,\n type MdChartTooltipContext,\n type MdChartTooltipRenderer,\n type MdChartTooltipSeries,\n} from '../tooltip';\nimport type { RenderScene } from './scene';\n\n/** Optional hover extras — kept in one bag so the positional argument list\n * doesn't keep growing. */\nexport interface HoverOptions {\n /** Developer-supplied tooltip content. See {@link MdChartTooltipRenderer}. */\n render?: MdChartTooltipRenderer;\n /** Consulted for a series with no value at the hovered x; a non-empty return\n * opts that series into a tooltip row. See {@link MdChartMissingFormatter}. */\n missingFormatter?: MdChartMissingFormatter;\n /** Host is right-to-left: the card prefers the crosshair's LEFT side, so it\n * opens along the reading direction instead of against it. */\n rtl?: boolean;\n /**\n * `'item'` reports only the series under the cursor; `'axis'` (default) lists\n * every series at the hovered x. Item suits a chart where the pointer is\n * genuinely *on* one series — a thick stacked band, a streamgraph — where an\n * every-series list buries the one thing the user is pointing at.\n */\n trigger?: 'axis' | 'item';\n}\n\nexport function clearHover(layer: HTMLElement): void {\n layer.textContent = '';\n delete layer.dataset.hoverIndex;\n}\n\nconst SURFACE = 'var(--md-sys-color-surface, #FFFBFE)';\nconst SHAPE_KEYS = new Set(['circle', 'square', 'diamond', 'triangle', 'triangle-down']);\nconst SHAPE_CLIP: Record<string, string> = {\n diamond: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)',\n triangle: 'polygon(50% 0%, 100% 100%, 0% 100%)',\n 'triangle-down': 'polygon(0% 0%, 100% 0%, 50% 100%)',\n};\n\n/** Build the hover highlight for a point, matching its marker symbol:\n * emoji → the (enlarged) glyph itself; square/diamond/triangle → a\n * surface-outlined colour shape; otherwise the classic ringed circle.\n * Centred on (x, y) via a -50%/-50% translate the pop animation preserves. */\nfunction buildHoverMarker(symbol: string | undefined, color: string, x: number, y: number): HTMLElement {\n const el = document.createElement('div');\n const base = `position:absolute;left:${x}px;top:${y}px;transform:translate(-50%,-50%);pointer-events:none`;\n\n // Emoji / text glyph → scale the glyph up; don't cover it with a circle.\n if (symbol && !SHAPE_KEYS.has(symbol)) {\n el.textContent = symbol;\n el.style.cssText = `${base};font-size:22px;line-height:1;user-select:none`;\n return el;\n }\n\n // Squares/diamonds fill their box so they read larger than a circle of equal\n // width — size polygons down so every symbol has similar visual weight.\n const size = symbol && symbol !== 'circle' ? 11 : 13;\n el.style.cssText = `${base};width:${size}px;height:${size}px;filter:drop-shadow(0 1px 2px rgba(0,0,0,0.3))`;\n if (!symbol || symbol === 'circle') {\n el.style.cssText += `;box-sizing:border-box;border-radius:50%;background:${color};border:2px solid ${SURFACE}`;\n return el;\n }\n // Polygon shapes: a slightly larger surface shape behind the colour fill gives\n // the same \"ring\" separation the circle's border does (clip-path has no border).\n const clip = SHAPE_CLIP[symbol] ?? 'none'; // square = plain rectangle\n const outline = document.createElement('div');\n outline.style.cssText = `position:absolute;inset:-2px;background:${SURFACE};clip-path:${clip}`;\n const fill = document.createElement('div');\n fill.style.cssText = `position:absolute;inset:0;background:${color};clip-path:${clip}`;\n el.append(outline, fill);\n return el;\n}\n\n/** Expressive scale-in for a freshly-hovered point marker (base size → slight\n * overshoot → settle), centred so the -50%/-50% translate is preserved. */\nfunction popMarker(dot: HTMLElement): void {\n if (typeof dot.animate !== 'function') return; // WAAPI unavailable (older env / SSR)\n // MD3-expressive spatial spring: overshoot past full size, settle back with a\n // small counter-bounce, on the emphasized-decelerate curve.\n dot.animate(\n [\n { transform: 'translate(-50%,-50%) scale(0.4)', offset: 0 },\n { transform: 'translate(-50%,-50%) scale(1.25)', offset: 0.45 },\n { transform: 'translate(-50%,-50%) scale(0.94)', offset: 0.72 },\n { transform: 'translate(-50%,-50%) scale(1)', offset: 1 },\n ],\n { duration: 320, easing: 'cubic-bezier(0.2, 0, 0, 1)' },\n );\n}\n\n/** The MD3 card chrome shared by the built-in tooltip and a custom one, so a\n * developer who only replaces the CONTENT still gets the surface for free.\n * Opt out with `::part(tooltip) { background: none; box-shadow: none; … }`.\n * Deliberately stops short of `box-sizing` / `min-width` / `white-space`: the\n * two cards want different values, and the built-in one must keep the exact\n * box it has always had. */\nfunction tooltipCardCss(fontSize: number, fontFamily: string): string[] {\n return [\n 'position:absolute',\n 'pointer-events:none',\n 'background:var(--md-sys-color-surface-container-high, #ECE6F0)',\n 'color:var(--md-sys-color-on-surface, #1C1B1F)',\n 'border-radius:8px',\n 'padding:8px 10px',\n 'box-shadow:0 2px 6px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.2)',\n `font:400 ${fontSize}px ${fontFamily}`,\n ];\n}\n\n/**\n * Insert a renderer's return value into the tooltip card.\n *\n * A `Node` goes in as-is. A bare string is set as TEXT — markup inside it is\n * shown, not parsed — so untrusted values are safe by default. `innerHTML` is\n * only ever reached through the explicitly-named `{ unsafeHtml }` form, which\n * is NOT sanitised.\n */\nexport function appendTooltipContent(tip: HTMLElement, content: Node | string | { unsafeHtml: string }): void {\n if (isDomNode(content)) {\n tip.appendChild(content);\n return;\n }\n if (typeof content === 'object' && typeof content.unsafeHtml === 'string') {\n tip.innerHTML = content.unsafeHtml;\n return;\n }\n tip.textContent = String(content);\n}\n\nexport function renderHover(\n layer: HTMLElement,\n scene: RenderScene,\n index: number,\n yFormatter: (v: number) => string,\n fontFamily: string,\n cursor: { x: number; y: number },\n orient: 'vertical' | 'horizontal' | 'none' = 'vertical',\n focusSeries = -1,\n opts: HoverOptions = {},\n): void {\n // Only scale-in when the hovered point actually CHANGES — moving the pointer\n // within one point's region re-runs renderHover every frame, and re-animating\n // each time would jitter.\n const isNewPoint = layer.dataset.hoverIndex !== String(index);\n layer.textContent = '';\n if (index < 0) {\n delete layer.dataset.hoverIndex;\n return;\n }\n // For a vertical plot xPositions holds x-coords; for a horizontal\n // (bar) plot it holds the category y-coords along the main axis.\n const pos = scene.xPositions[index];\n if (pos == null) return;\n layer.dataset.hoverIndex = String(index);\n const animateDots = isNewPoint && !prefersReducedMotion();\n const plot = scene.plot;\n\n // ── crosshair (runs across the plot, perpendicular to the category axis) ──\n // The 1px line is centred on `pos` via a -50% translate so it can't sit half a\n // pixel off the markers.\n //\n // It reads as the pointer's position, so it has to stay legible wherever the\n // pointer goes. A muted outline at half opacity did that over an empty plot\n // and vanished completely over a filled one — on an area chart the crosshair\n // simply disappeared into the bands. So: the on-surface colour rather than\n // the outline one, and a surface-coloured halo (the box-shadow, which the\n // element's own opacity fades with it) so the line separates from a dark fill\n // and a light one alike — the same trick the point markers use.\n // 'none' skips the crosshair but keeps the tooltip: on a radial plot a\n // straight line across the chart crosses every ring at an angle that means\n // nothing, so there is no reading for it to mark.\n // Normally the crosshair is exactly the plot's span. A chevron is the\n // exception: its tip overflows the bar's rect, so the outermost segments point\n // PAST the axis extent and their markers land outside the plot. A line that\n // stopped at the plot edge would leave those end markers floating unattached,\n // so stretch it to whichever markers this index actually has.\n let lo = orient === 'horizontal' ? plot.x : plot.y;\n let hi = lo + (orient === 'horizontal' ? plot.width : plot.height);\n if (orient !== 'none') {\n for (const hp of scene.hoverPoints) {\n const pt = hp.byIndex?.[index];\n if (!pt) continue;\n const v = orient === 'horizontal' ? pt.x : pt.y;\n lo = Math.min(lo, v);\n hi = Math.max(hi, v);\n }\n }\n\n const line = document.createElement('div');\n line.style.cssText = [\n 'position:absolute',\n 'box-sizing:border-box',\n orient === 'horizontal'\n ? `left:${lo}px;top:${pos}px;width:${hi - lo}px;height:1px;transform:translateY(-50%)`\n : `left:${pos}px;top:${lo}px;height:${hi - lo}px;width:1px;transform:translateX(-50%)`,\n 'background:var(--md-sys-color-on-surface, #1C1B1F)',\n 'box-shadow:0 0 0 1px var(--md-sys-color-surface, #FFFBFE)',\n 'opacity:0.7',\n ].join(';');\n if (orient !== 'none') layer.appendChild(line);\n\n // ── per-series highlight markers + tooltip rows ──\n // `present` / `absent` mirror the two halves of the tooltip context: a series\n // with a real reading at this x, and one without (a null gap, or no datum at\n // all — partial and irregular data both land here). They are only filled in\n // for a custom renderer; renderHover runs on every hover frame, so the plain\n // path must not allocate a payload nobody reads.\n const wantContext = !!opts.render;\n const present: MdChartTooltipSeries[] = [];\n const absent: MdChartTooltipSeries[] = [];\n const rows: { color?: string; label: string; value: string }[] = [];\n const itemOnly = opts.trigger === 'item' && focusSeries >= 0;\n for (const hp of scene.hoverPoints) {\n // Item trigger: everything except the pointed-at series is dropped, rows\n // and highlight alike, so the card answers \"what am I on\" and nothing else.\n if (itemOnly && hp.seriesIndex !== focusSeries) continue;\n // Multi-axis: each series formats its value with its own axis formatter.\n const format = hp.valueFormat ?? yFormatter;\n const focused = hp.seriesIndex === focusSeries;\n const p = hp.byIndex[index];\n if (p) {\n // A fill-only series has no line and no markers, so there is nothing for a\n // dot to sit on — it would mark the band's top edge, which on a stack is a\n // cumulative total rather than this series' reading. Crosshair and row stay.\n // A bar coloured per-point (a bar race, a per-category palette) carries\n // its own colour on the point; the dot + swatch use it so they match the\n // bar under the cursor rather than the series default. Falls back to the\n // series colour for everything else (lines, ordinary bars).\n const swatch = p.color ?? hp.color;\n // A radial plot (`orient: 'none'`) has no straight reading a dot marks — a\n // ring is a band, not a point — so it shows the tooltip alone, no dots.\n if (!hp.unanchored && orient !== 'none') {\n // The highlight mirrors the point's marker (square / diamond / emoji / …)\n // rather than always a circle, so it doesn't mask the real symbol.\n const marker = buildHoverMarker(p.symbol, swatch, p.x, p.y);\n // A non-focused series is faded on the plot — fade its highlight to\n // match, and don't pop it (only the focused point gets the emphasis pop).\n const dimmed = focusSeries >= 0 && !focused;\n if (dimmed) marker.style.opacity = '0.4';\n layer.appendChild(marker);\n if (animateDots && !dimmed) popMarker(marker);\n }\n // A range series has no single value — print the band, since its `value`\n // is only the top edge and would read as a reading it never took.\n const value = p.low != null && p.high != null ? `${format(p.low)} – ${format(p.high)}` : format(p.value);\n rows.push({ color: swatch, label: hp.label, value });\n if (wantContext) present.push({ seriesIndex: hp.seriesIndex, label: hp.label, color: hp.color, value: p.value, formattedValue: value, focused, missing: false });\n continue;\n }\n // No reading here. `null` means the series HAS a datum that is null (or\n // non-finite) — \"measured, no value\"; `undefined` means it has no datum at\n // this x at all. The default is still to omit the series, but the chart's\n // valueFormatter can name the absence and opt it back in.\n if (!wantContext && !opts.missingFormatter) continue;\n const raw = hp.values?.[index];\n const value: null | undefined = typeof raw === 'number' ? null : raw;\n const text = opts.missingFormatter ? opts.missingFormatter(value) : '';\n if (wantContext) absent.push({ seriesIndex: hp.seriesIndex, label: hp.label, color: hp.color, value, formattedValue: text, focused, missing: true });\n // No highlight marker is drawn for it — there is no point on the plot to\n // highlight — and the row below carries no colour swatch either, so it\n // never reads as a data point.\n if (text) rows.push({ label: hp.label, value: text });\n }\n\n const fontSize = scene.texts[0]?.fontSize ?? 12;\n\n // ── custom tooltip content ──\n if (opts.render) {\n const context: MdChartTooltipContext = {\n dataIndex: index,\n axisValue: scene.xValues[index],\n axisLabel: scene.xLabels[index] ?? '',\n series: present,\n missing: absent,\n focusedSeriesIndex: focusSeries,\n };\n let content: ReturnType<MdChartTooltipRenderer>;\n try {\n content = opts.render(context);\n } catch (err) {\n // A throwing renderer must not take the whole hover loop down with it —\n // report it and fall back to the built-in card.\n console.error('[md-chart] tooltipRenderer threw; falling back to the default tooltip', err);\n content = undefined;\n }\n if (content === null) return; // explicit \"no tooltip at this x\"\n if (content !== undefined) {\n const custom = document.createElement('div');\n custom.setAttribute('part', 'tooltip');\n // No `min-width` / `white-space:nowrap` (they fight multi-line custom\n // layouts), and a max-width of the chart box so content far wider than the\n // default card is still narrow enough for the flip below to have somewhere\n // to put it. `border-box` so that cap includes the card's own padding.\n custom.style.cssText = [\n ...tooltipCardCss(fontSize, fontFamily),\n 'z-index:2',\n 'box-sizing:border-box',\n `max-width:${Math.max(0, scene.width - 8)}px`,\n ].join(';');\n appendTooltipContent(custom, content);\n positionTooltip(custom, layer, scene, cursor, orient, pos);\n return;\n }\n }\n\n if (!rows.length) return;\n\n // ── tooltip card ──\n const tip = document.createElement('div');\n tip.setAttribute('part', 'tooltip');\n tip.style.cssText = [...tooltipCardCss(fontSize, fontFamily), 'min-width:96px', 'z-index:2', 'white-space:nowrap'].join(';');\n\n const header = document.createElement('div');\n header.textContent = scene.xLabels[index] ?? '';\n header.style.cssText = 'font-weight:600;margin-bottom:4px';\n tip.appendChild(header);\n\n for (const r of rows) {\n const row = document.createElement('div');\n // A missing-value row is dimmed and its value is not bolded, so it reads as\n // an absence rather than as data.\n row.style.cssText = `display:flex;align-items:center;gap:8px;line-height:1.5${r.color ? '' : ';opacity:0.62'}`;\n const sw = document.createElement('span');\n // Missing rows keep the swatch's BOX (so labels stay in one column) but\n // never its colour — a swatch would imply a data point that isn't there.\n sw.style.cssText = r.color\n ? `width:10px;height:10px;border-radius:3px;background:${r.color};flex:none`\n : 'width:10px;height:10px;flex:none';\n const lbl = document.createElement('span');\n lbl.textContent = r.label;\n lbl.style.cssText = 'flex:1';\n const val = document.createElement(r.color ? 'strong' : 'span');\n val.textContent = r.value;\n row.append(sw, lbl, val);\n tip.appendChild(row);\n }\n\n positionTooltip(tip, layer, scene, cursor, orient, pos, opts.rtl);\n}\n\n/** Place a tooltip card near the crosshair, opening along the reading direction\n * and flipping away from the far / bottom edges. Measuring needs it in the DOM,\n * so it is appended first. */\nfunction positionTooltip(\n tip: HTMLElement,\n layer: HTMLElement,\n scene: RenderScene,\n cursor: { x: number; y: number },\n orient: 'vertical' | 'horizontal' | 'none',\n pos: number,\n rtl = false,\n): void {\n layer.appendChild(tip);\n const tw = tip.offsetWidth || 120;\n const th = tip.offsetHeight || 60;\n // A card taller than the host (a sparkline is only ~28px) cannot sit INSIDE it —\n // clamping it there just hides it under the layer's clip. Let it ESCAPE: stop\n // clipping the layer and float the card just ABOVE the host, centred on the\n // cursor but kept mostly over the host so it never wanders off on either side.\n if (th + 8 > scene.height) {\n layer.style.overflow = 'visible';\n const l = Math.max(24 - tw, Math.min(cursor.x - tw / 2, scene.width - 24));\n tip.style.left = `${Math.round(l)}px`;\n // Escaping ALWAYS upward is what a sparkline wants, but a short chart near\n // the top of the page then floats its card off the screen entirely — the\n // reading is unreachable, which is worse than the clipping this branch\n // exists to avoid. So pick the side that actually has room in the viewport,\n // preferring above (it covers the chart's own header rather than the next\n // section) and falling back to below when it would overflow the top.\n const box = layer.getBoundingClientRect();\n const roomAbove = box.top - th - 6 >= 0;\n // Below the PLOT, not below the scene: `scene.height` spans the legend and\n // axis gutter too, so clearing it parks the card a legend-height from the\n // data it describes. The card is transient and floats, so overlapping the\n // legend is the right trade for sitting next to the reading.\n const plotBottom = scene.plot ? scene.plot.y + scene.plot.height : scene.height;\n tip.style.top = roomAbove ? `${Math.round(-th - 6)}px` : `${Math.round(plotBottom + 6)}px`;\n return;\n }\n let left: number;\n let top: number;\n if (orient === 'none') {\n // Radial: there is no axis line to anchor to (`pos` is a ring radius, not a\n // screen position), so the card sits beside the POINTER — flipping to stay\n // on-screen — the way a plain cursor tooltip does.\n left = cursor.x + 14;\n if (left + tw > scene.width - 4) left = cursor.x - tw - 14;\n left = Math.max(4, Math.min(left, scene.width - tw - 4));\n top = cursor.y + 14;\n if (top + th > scene.height - 4) top = cursor.y - th - 14;\n top = Math.max(4, Math.min(top, scene.height - th - 4));\n } else if (orient === 'horizontal') {\n top = pos + 14;\n if (top + th > scene.height - 4) top = pos - th - 14;\n top = Math.max(4, top);\n left = rtl\n ? Math.max(4, Math.min(cursor.x - tw - 14, scene.width - tw - 4))\n : Math.max(4, Math.min(cursor.x + 14, scene.width - tw - 4));\n } else {\n // RTL opens to the left of the crosshair and flips right when it would run\n // off that edge; LTR is the mirror of the same rule.\n left = rtl ? pos - tw - 14 : pos + 14;\n if (rtl ? left < 4 : left + tw > scene.width - 4) left = rtl ? pos + 14 : pos - tw - 14;\n left = Math.max(4, Math.min(left, scene.width - tw - 4));\n top = Math.max(4, Math.min(cursor.y - th / 2, scene.height - th - 4));\n }\n tip.style.left = `${left}px`;\n tip.style.top = `${top}px`;\n}\n","/*\n * Chart engine — device-pixel-ratio watcher\n * ===========================================================\n * A canvas is drawn at a fixed `cssPx × devicePixelRatio` backing\n * store. Browser zoom changes `devicePixelRatio` WITHOUT changing\n * the element's CSS size, so a ResizeObserver never fires and the\n * canvas ends up under-resolved (upscaled → blurry) while the DOM\n * overlay stays crisp. This watches `devicePixelRatio` via a\n * `(resolution: Ndppx)` media query and re-renders when it changes.\n * ===========================================================\n */\n\nexport interface DprWatcher {\n /** Re-arm the watch for the current devicePixelRatio (call each render). */\n update(): void;\n dispose(): void;\n}\n\nexport function watchDevicePixelRatio(onChange: () => void): DprWatcher {\n let mql: MediaQueryList | null = null;\n let listener: (() => void) | null = null;\n let armed = 0;\n\n const update = (): void => {\n if (typeof window === 'undefined' || !window.matchMedia) return;\n const dpr = window.devicePixelRatio || 1;\n if (dpr === armed && mql) return; // already watching this ratio\n if (mql && listener) mql.removeEventListener?.('change', listener);\n armed = dpr;\n // Matches while the ratio equals `dpr`; stops matching (fires `change`)\n // the moment it shifts — e.g. a browser zoom step.\n mql = window.matchMedia(`(resolution: ${dpr}dppx)`);\n listener = onChange;\n mql.addEventListener?.('change', listener);\n };\n\n const dispose = (): void => {\n if (mql && listener) mql.removeEventListener?.('change', listener);\n mql = null;\n listener = null;\n armed = 0;\n };\n\n return { update, dispose };\n}\n","/*\n * Chart engine — RTL mirroring\n * ===========================================================\n * A finished frame, flipped about the canvas' vertical centre:\n * the value axis and its gutter move to the right, the category\n * axis runs right-to-left, and the title/labels anchor from the\n * other side. A pure scene→scene transform (like emphasis.ts and\n * animate.ts), so the whole geometry pipeline — scales, curves,\n * decimation, stacking — stays in one direction and cannot grow\n * an RTL branch per feature. Text is repositioned, never\n * reversed: the glyphs themselves are the browser's business.\n * ===========================================================\n */\n\nimport type { Pt } from './geometry';\nimport type { EndLabel, GlyphMarker, HoverSeries, RenderScene, SceneArea, SceneBar, SceneMarker, SceneSegment, ScenePolyline, TextItem } from './scene';\n\n/**\n * A legend anchor mirrored for a right-to-left chart.\n *\n * `start` / `end` are logical and have to resolve to the other physical side;\n * `left` / `right` are mirrored too, because everything else about the chart\n * already is — its title anchors from the right, its legend chips run\n * right-to-left — and a legend that stayed put would be the one piece of the\n * layout that did not turn round. `top` / `bottom` have no side to swap.\n *\n * Applied to the SPEC, before layout: the gutter reserved for the legend and\n * the chips placed into it both read this, and they have to agree.\n */\nexport function mirrorLegend(pos: string | undefined): string | undefined {\n switch (pos) {\n case 'left':\n return 'right';\n case 'right':\n return 'left';\n case 'top-start':\n return 'top-end';\n case 'top-end':\n return 'top-start';\n case 'bottom-start':\n return 'bottom-end';\n case 'bottom-end':\n return 'bottom-start';\n default:\n return pos;\n }\n}\n\n/** `start` and `end` swap sides; `center` is unmoved. */\nfunction flipAlign(a: TextItem['align']): TextItem['align'] {\n return a === 'start' ? 'end' : a === 'end' ? 'start' : 'center';\n}\n\n/**\n * The scene mirrored horizontally about the canvas centre.\n *\n * Mirroring about the CANVAS (not the plot) is what moves the gutters: a wide\n * y-axis gutter on the left becomes a wide gutter on the right, carrying its\n * tick labels with it, while the plot rect lands where the old right margin\n * was. Every x is `width - x`; anything with a width (rects) mirrors its far\n * edge instead, and text flips which side it anchors from.\n *\n * Point ORDER is left alone. Consumers that need monotonic input — the line\n * hit-test, the hover distance — normalise it themselves, so a mirrored scene\n * stays a plain data structure rather than a special case.\n */\nexport function mirrorScene(scene: RenderScene): RenderScene {\n const W = scene.width;\n const mx = (x: number) => W - x;\n const mPts = (pts: Pt[]): Pt[] => pts.map((p) => ({ ...p, x: mx(p.x) }));\n const mSeg = (s: SceneSegment): SceneSegment => ({ ...s, x1: mx(s.x1), x2: mx(s.x2) });\n\n return {\n ...scene,\n plot: { ...scene.plot, x: mx(scene.plot.x + scene.plot.width) },\n bands: scene.bands?.map((b) => ({ ...b, x: mx(b.x + b.w) })),\n gridlines: scene.gridlines.map(mSeg),\n axisLines: scene.axisLines.map(mSeg),\n areas: scene.areas.map(\n (a): SceneArea => ({ ...a, points: mPts(a.points), basePoints: a.basePoints ? mPts(a.basePoints) : undefined }),\n ),\n bars: scene.bars.map((b): SceneBar => ({ ...b, x: mx(b.x + b.w) })),\n // The value baseline the intro grows a bar from. For a HORIZONTAL chart it is\n // an x (the value axis) and mirrors; for a vertical one it is a y and stays.\n // (barLabels aren't mirrored here — they're re-derived from the bars above.)\n barBaseline: scene.barBaseline != null && scene.bars[0]?.horizontal ? mx(scene.barBaseline) : scene.barBaseline,\n slices: scene.slices.map((s) => ({\n ...s,\n cx: mx(s.cx),\n // A mirrored arc sweeps the other way: reflect both ends across the\n // vertical, which swaps their roles (start becomes end).\n startAngle: Math.PI - s.endAngle,\n endAngle: Math.PI - s.startAngle,\n })),\n lines: scene.lines.map((l): ScenePolyline => ({ ...l, points: mPts(l.points) })),\n markers: scene.markers.map((m): SceneMarker => ({ ...m, x: mx(m.x) })),\n glyphs: scene.glyphs?.map((g): GlyphMarker => ({ ...g, x: mx(g.x) })),\n // A mirrored line ends on the LEFT, so its label has to extend leftward —\n // mirroring the anchor x alone would leave the text lying back across the\n // plot, on top of the data it labels.\n endLabels: scene.endLabels?.map((e): EndLabel => ({ ...e, x: mx(e.x), side: e.side === 'end' ? 'start' : 'end' })),\n // Rotation mirrors with everything else: a -45° tick label tilts the other\n // way (it must lean along the reading direction, and its anchor has just\n // swapped sides), and the y-axis title reads top-to-bottom on the right\n // instead of bottom-to-top — the convention for an axis title on that side.\n texts: scene.texts.map((t): TextItem => ({ ...t, x: mx(t.x), align: flipAlign(t.align), rotate: t.rotate ? -t.rotate : t.rotate })),\n legend: scene.legend.map((l) => ({ ...l, x: mx(l.x) })),\n xPositions: scene.xPositions.map(mx),\n hoverPoints: scene.hoverPoints.map(\n (hp): HoverSeries => ({\n ...hp,\n byIndex: Object.fromEntries(Object.entries(hp.byIndex).map(([k, p]) => [k, { ...p, x: mx(p.x) }])),\n }),\n ),\n };\n}\n\n/**\n * Is this host laid out right-to-left? Reads the COMPUTED direction, so it\n * follows `dir` on any ancestor (or the document) rather than only an attribute\n * on the chart itself — the same test md-slider, md-tabs and md-tooltip use.\n */\nexport function isRtl(el: Element | null | undefined): boolean {\n if (!el || typeof getComputedStyle !== 'function') return false;\n try {\n return getComputedStyle(el).direction === 'rtl';\n } catch {\n return false; // no layout engine (mock-doc / SSR)\n }\n}\n\nexport interface DirectionWatcher {\n dispose(): void;\n}\n\n/**\n * Subscribers to a `dir` change anywhere in the document, sharing ONE observer.\n *\n * A chart resolves its direction while laying out, so unlike a CSS-driven\n * component it cannot just react to the cascade — flipping `dir` after mount\n * (the Storybook toolbar, an app-level locale switch) has to re-render it.\n * `dir` can be set on any ancestor, so the observer watches the whole document;\n * one shared instance keeps that to a single observer no matter how many charts\n * are on the page (the same shape as watchDevicePixelRatio).\n */\nconst dirListeners = new Set<() => void>();\nlet dirObserver: MutationObserver | null = null;\n\nexport function watchDirection(onChange: () => void): DirectionWatcher {\n if (typeof MutationObserver === 'undefined' || typeof document === 'undefined') {\n return { dispose: () => undefined };\n }\n dirListeners.add(onChange);\n if (!dirObserver) {\n dirObserver = new MutationObserver(() => {\n for (const fn of dirListeners) fn();\n });\n dirObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'], subtree: true });\n }\n return {\n dispose: () => {\n dirListeners.delete(onChange);\n if (!dirListeners.size) {\n dirObserver?.disconnect();\n dirObserver = null;\n }\n },\n };\n}\n\n/**\n * A polyline's samples in ascending main-axis order.\n *\n * The mirror leaves point order alone, so a mirrored series descends in x. The\n * distance-to-line search bisects on that axis and needs it ascending; reverse\n * a copy rather than making every caller aware of direction.\n */\nexport function ascending<T extends readonly [number, number]>(points: T[]): T[] {\n const n = points.length;\n if (n < 2 || points[0][0] <= points[n - 1][0]) return points;\n return [...points].reverse();\n}\n"],"mappings":"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","ignoreList":[]}