@mkbabb/glass-ui 3.10.1 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/dist/{CardAction-DrAcAV4d.js → CardAction-DuArVky-.js} +2 -2
  2. package/dist/{CommandShortcut-mV2e1aG6.js → CommandShortcut-CefCj5mt.js} +2 -2
  3. package/dist/{DataTable-C3E6jZ5B.js → DataTable-CUHMukiQ.js} +2 -2
  4. package/dist/DeckProgress-Dmk4_AKN.js +23 -0
  5. package/dist/{DialogContent-BxaaafFi.js → DialogContent-BRkT1cjP.js} +1 -1
  6. package/dist/{HoverPopover-CDA_SaCe.js → HoverPopover-2LOIW34a.js} +1 -1
  7. package/dist/InstrumentRail-CUJ05YVG.js +44 -0
  8. package/dist/{MetricBadge-idgrkqoP.js → MetricBadge-BZVWIxNy.js} +7 -5
  9. package/dist/{Notification-Cu0nN17_.js → Notification-DLMhblXR.js} +1 -1
  10. package/dist/{NumberFieldContent-CHEWghnY.js → NumberFieldContent-BbLOh8RU.js} +2 -2
  11. package/dist/{PopoverContent-DpUvdYY-.js → PopoverContent-BId6ggf_.js} +1 -1
  12. package/dist/{Progress-BW-StFw2.js → Progress-iEuD9pxG.js} +1 -1
  13. package/dist/{ScrollingText-DruYCni_.js → ScrollingText-BPP84wKo.js} +1 -1
  14. package/dist/{SelectScrollDownButton-pirzjm--.js → SelectScrollDownButton-T32cVFeM.js} +3 -3
  15. package/dist/{Switch-DeAqg6pi.js → Switch-Ch-k3Rv-.js} +1 -1
  16. package/dist/{TabsList-BAVzOZpg.js → TabsList-B8CVOQPC.js} +2 -2
  17. package/dist/{Toaster-CvuuW_y9.js → Toaster-1rYWrmAm.js} +46 -49
  18. package/dist/{ToggleGroupItem-DtD37b4G.js → ToggleGroupItem-COu_4IW4.js} +21 -17
  19. package/dist/animated-digit.js +2 -2
  20. package/dist/api/index.d.ts +5 -4
  21. package/dist/api.js +2 -2
  22. package/dist/aurora.js +70 -70
  23. package/dist/{badge-NdCQMvvB.js → badge-CaoFJzRb.js} +1 -1
  24. package/dist/badge.js +1 -1
  25. package/dist/{button-DyiWFAOE.js → button-DN39cGqL.js} +12 -12
  26. package/dist/button.js +1 -1
  27. package/dist/canvas.js +2 -2
  28. package/dist/card.js +1 -1
  29. package/dist/carousel.js +5 -5
  30. package/dist/collapsible.js +1 -1
  31. package/dist/{color-B65wWyQz.js → color-C5ls_QF7.js} +7 -9
  32. package/dist/color.js +1 -1
  33. package/dist/command.js +1 -1
  34. package/dist/components/custom/aurora/constants/presets.d.ts +62 -5
  35. package/dist/components/custom/aurora/constants/shaders/mediums.glsl.d.ts +1 -1
  36. package/dist/components/custom/aurora/index.d.ts +1 -1
  37. package/dist/components/custom/constellation/Constellation.vue.d.ts +0 -12
  38. package/dist/components/custom/constellation/constellationField.d.ts +151 -10
  39. package/dist/components/custom/constellation/index.d.ts +1 -3
  40. package/dist/components/custom/controls/DarkModeToggle.vue.d.ts +0 -11
  41. package/dist/components/custom/deck-progress/DeckProgress.vue.d.ts +27 -0
  42. package/dist/components/custom/deck-progress/index.d.ts +2 -0
  43. package/dist/components/custom/dialog-native/GlassDialogNative.vue.d.ts +57 -0
  44. package/dist/components/custom/dialog-native/index.d.ts +1 -0
  45. package/dist/components/custom/dock/DockTabButton.vue.d.ts +4 -3
  46. package/dist/components/custom/dock/GlassDock.vue.d.ts +115 -3
  47. package/dist/components/custom/dock/composables/dockMorphContext.d.ts +0 -36
  48. package/dist/components/custom/dock/composables/useLayerTransition.d.ts +0 -44
  49. package/dist/components/custom/expandable-container/ExpandableContainer.vue.d.ts +37 -5
  50. package/dist/components/custom/fourier-field/index.d.ts +1 -1
  51. package/dist/components/custom/fourier-field/math.d.ts +0 -17
  52. package/dist/components/custom/glass-panel/GlassPanel.vue.d.ts +41 -0
  53. package/dist/components/custom/glass-panel/index.d.ts +2 -0
  54. package/dist/components/custom/goo-blob/composables/useBlobPointer.d.ts +3 -4
  55. package/dist/components/custom/goo-blob/composables/useMetaballRenderer.d.ts +8 -11
  56. package/dist/components/custom/handmark/HandMark.vue.d.ts +29 -0
  57. package/dist/components/custom/handmark/brush.d.ts +242 -0
  58. package/dist/components/custom/handmark/freehand.d.ts +69 -0
  59. package/dist/components/custom/handmark/geometry.d.ts +50 -0
  60. package/dist/components/custom/handmark/index.d.ts +21 -0
  61. package/dist/components/custom/handmark/ink.d.ts +11 -0
  62. package/dist/components/custom/handmark/texture.d.ts +39 -0
  63. package/dist/components/custom/handmark/types.d.ts +53 -0
  64. package/dist/components/custom/handmark/useHandMark.d.ts +87 -0
  65. package/dist/components/custom/header-ribbon/HeaderRibbon.vue.d.ts +31 -0
  66. package/dist/components/custom/header-ribbon/index.d.ts +2 -0
  67. package/dist/components/custom/header-ribbon/types.d.ts +7 -0
  68. package/dist/components/custom/instrument-chassis/InstrumentChassis.vue.d.ts +2 -2
  69. package/dist/components/custom/instrument-rail/InstrumentRail.vue.d.ts +91 -0
  70. package/dist/components/custom/instrument-rail/index.d.ts +2 -0
  71. package/dist/components/custom/metric-badge/MetricBadge.vue.d.ts +8 -0
  72. package/dist/components/ui/drawer/Drawer.vue.d.ts +0 -1
  73. package/dist/components/ui/dropdown-menu/DropdownMenuSubContent.vue.d.ts +2 -2
  74. package/dist/components/ui/slider/index.d.ts +19 -22
  75. package/dist/components/ui/toast/use-toast.d.ts +2 -2
  76. package/dist/components/ui/toggle/Toggle.vue.d.ts +1 -1
  77. package/dist/components/ui/toggle/index.d.ts +1 -1
  78. package/dist/components/ui/toggle-group/ToggleGroup.vue.d.ts +7 -1
  79. package/dist/components/ui/toggle-group/ToggleGroupItem.vue.d.ts +3 -1
  80. package/dist/components/ui/toggle-group/toggleGroupContext.d.ts +13 -0
  81. package/dist/composables/color/index.d.ts +0 -12
  82. package/dist/composables/dark/index.d.ts +1 -1
  83. package/dist/composables/dark/useGlobalDark.d.ts +21 -1
  84. package/dist/composables/glass/useSpecularTracking.d.ts +3 -12
  85. package/dist/composables/motion/core/index.d.ts +1 -0
  86. package/dist/composables/motion/index.d.ts +0 -2
  87. package/dist/composables/motion/useRouteTransition.d.ts +42 -0
  88. package/dist/composables/motion/useSpringMount.d.ts +1 -1
  89. package/dist/configurator.js +1 -1
  90. package/dist/confirm-dialog.js +2 -2
  91. package/dist/constellation.js +225 -260
  92. package/dist/controls.js +14 -48
  93. package/dist/dark.d.ts +1 -1
  94. package/dist/dark.js +1 -1
  95. package/dist/data-table.js +1 -1
  96. package/dist/deck-progress.d.ts +1 -0
  97. package/dist/deck-progress.js +2 -0
  98. package/dist/dialog.js +2 -2
  99. package/dist/dock.js +345 -340
  100. package/dist/dockContext-BKeIMmNk.js +9 -0
  101. package/dist/{dropdown-menu-DVnQcA0E.js → dropdown-menu-D77jX6Df.js} +4 -7
  102. package/dist/dropdown-menu.js +1 -1
  103. package/dist/expandable-container.js +79 -38
  104. package/dist/forms.js +2 -2
  105. package/dist/fourier-field.js +102 -137
  106. package/dist/fourier-math.js +2 -2
  107. package/dist/glass-panel.d.ts +1 -0
  108. package/dist/glass-panel.js +44 -0
  109. package/dist/glass-ui.css +1 -1
  110. package/dist/glass-ui.js +209 -287
  111. package/dist/goo-blob.js +212 -243
  112. package/dist/handmark.d.ts +1 -0
  113. package/dist/handmark.js +662 -0
  114. package/dist/header-ribbon.d.ts +1 -0
  115. package/dist/header-ribbon.js +63 -0
  116. package/dist/hover-popover.js +1 -1
  117. package/dist/icon-tooltip.js +1 -1
  118. package/dist/index.d.ts +3 -0
  119. package/dist/instrument-rail.d.ts +1 -0
  120. package/dist/instrument-rail.js +2 -0
  121. package/dist/keyboard.js +1 -1
  122. package/dist/labeled-field.js +5 -5
  123. package/dist/{math-BUU9hHID.js → math-DTpRVC0e.js} +2 -18
  124. package/dist/metric-badge.js +1 -1
  125. package/dist/metric-stack.js +1 -1
  126. package/dist/motion-core.js +70 -69
  127. package/dist/motion.js +37 -38
  128. package/dist/notification.js +1 -1
  129. package/dist/number-field.js +1 -1
  130. package/dist/popover.js +1 -1
  131. package/dist/{presets-1OhFpaIC.js → presets-BP_ALM0m.js} +14 -1
  132. package/dist/progress.js +1 -1
  133. package/dist/pulse.js +1 -1
  134. package/dist/reactive.js +1 -1
  135. package/dist/scrolling-text.js +1 -1
  136. package/dist/search.js +6 -6
  137. package/dist/select.js +1 -1
  138. package/dist/{sheet-ChSXcJpU.js → sheet-VZEtNFvO.js} +1 -1
  139. package/dist/sheet.js +1 -1
  140. package/dist/{slider-sfl8gFDD.js → slider-ClgpP7EB.js} +4 -4
  141. package/dist/slider.js +1 -1
  142. package/dist/sortable-list.js +2 -2
  143. package/dist/stacked-icons.js +6 -6
  144. package/dist/styles/animations.css +111 -15
  145. package/dist/styles/components.css +1 -1
  146. package/dist/styles/dock/layer-group.css +0 -22
  147. package/dist/styles/dock/layers.css +1 -11
  148. package/dist/styles/dock/morph.css +19 -95
  149. package/dist/styles/dock/shell.css +0 -12
  150. package/dist/styles/dock-controls.css +31 -28
  151. package/dist/styles/drawer.css +0 -2
  152. package/dist/styles/floating-panel.css +0 -2
  153. package/dist/styles/glass-refract.css +0 -2
  154. package/dist/styles/glass.css +1188 -31
  155. package/dist/styles/hover-popover.css +0 -2
  156. package/dist/styles/index.css +6 -24
  157. package/dist/styles/instrument-chassis.css +0 -4
  158. package/dist/styles/paper.css +68 -2
  159. package/dist/styles/theme.css +20 -13
  160. package/dist/styles/tokens.css +2360 -22
  161. package/dist/styles/typography.css +6 -18
  162. package/dist/styles/utilities.css +1291 -19
  163. package/dist/styles/view-transition.css +51 -0
  164. package/dist/switch.js +1 -1
  165. package/dist/tabs.js +98 -98
  166. package/dist/timeline.js +2 -2
  167. package/dist/toast.js +1 -1
  168. package/dist/toggle-group.js +1 -1
  169. package/dist/typewriter.js +1 -1
  170. package/dist/{useAnimatedNumber-DfVgP4te.js → useAnimatedNumber-Bcpy5Etf.js} +1 -1
  171. package/dist/{useConfiguratorState-BdQXh9ie.js → useConfiguratorState-DxAqksK6.js} +1 -1
  172. package/dist/useGlassRenderer-D7YGOYiM.js +69 -0
  173. package/dist/{useGlobalDark-D7R9OypB.js → useGlobalDark-D1wgEqfW.js} +21 -2
  174. package/dist/useSpecularTracking-BVRZsRHA.js +26 -0
  175. package/dist/useSpringMount-BJSHcLl3.js +113 -0
  176. package/dist/useViewTransition-DaN5Zrox.js +21 -0
  177. package/dist/vReveal-zUIQk-rJ.js +53 -0
  178. package/dist/watercolor-dot.js +2 -2
  179. package/package.json +57 -33
  180. package/src/styles/animations.css +111 -15
  181. package/src/styles/dock/layer-group.css +0 -22
  182. package/src/styles/dock/layers.css +1 -11
  183. package/src/styles/dock/morph.css +19 -95
  184. package/src/styles/dock/shell.css +0 -12
  185. package/src/styles/dock-controls.css +31 -28
  186. package/src/styles/glass.css +1188 -31
  187. package/src/styles/index.css +6 -24
  188. package/src/styles/paper.css +68 -2
  189. package/src/styles/theme.css +20 -13
  190. package/src/styles/tokens.css +2360 -22
  191. package/src/styles/typography.css +6 -18
  192. package/src/styles/utilities.css +1291 -19
  193. package/src/styles/view-transition.css +51 -0
  194. package/dist/components/custom/aurora/constants/shaders/vangogh-medium.glsl.d.ts +0 -1
  195. package/dist/components/custom/constellation/composables/createConstellationField.d.ts +0 -35
  196. package/dist/components/custom/constellation/composables/useConstellationPointer.d.ts +0 -35
  197. package/dist/components/custom/constellation/constants.d.ts +0 -36
  198. package/dist/components/custom/constellation/constellationDraw.d.ts +0 -18
  199. package/dist/components/custom/constellation/constellationInteraction.d.ts +0 -102
  200. package/dist/components/custom/dock/composables/useDockMorphWindow.d.ts +0 -15
  201. package/dist/components/custom/dock/composables/useDockShellProps.d.ts +0 -131
  202. package/dist/components/custom/dock/constants.d.ts +0 -23
  203. package/dist/components/custom/fourier-field/presets.d.ts +0 -54
  204. package/dist/components/custom/goo-blob/composables/buildMetaballProgram.d.ts +0 -18
  205. package/dist/components/custom/goo-blob/composables/uploadBlobUniforms.d.ts +0 -41
  206. package/dist/components/custom/goo-blob/constants.d.ts +0 -52
  207. package/dist/components/custom/goo-blob/shaders/metaball-uniforms.glsl.d.ts +0 -1
  208. package/dist/components/custom/tabs/constants.d.ts +0 -12
  209. package/dist/components/custom/underline/GlassUnderline.vue.d.ts +0 -84
  210. package/dist/components/custom/underline/index.d.ts +0 -2
  211. package/dist/components/custom/underline/types.d.ts +0 -56
  212. package/dist/composables/motion/curves.d.ts +0 -48
  213. package/dist/composables/motion/springPresets.d.ts +0 -33
  214. package/dist/composables/motion/suite.d.ts +0 -2
  215. package/dist/dockContext-bho8B1A4.js +0 -17
  216. package/dist/motion-curves.d.ts +0 -1
  217. package/dist/motion-curves.js +0 -130
  218. package/dist/springPresets-aRSm-4_k.js +0 -40
  219. package/dist/styles/glass/a11y-fallback.css +0 -245
  220. package/dist/styles/glass/ladder.css +0 -304
  221. package/dist/styles/glass/material.css +0 -238
  222. package/dist/styles/glass/progress-rail.css +0 -78
  223. package/dist/styles/glass/squircle.css +0 -66
  224. package/dist/styles/glass/surfaces.css +0 -306
  225. package/dist/styles/tokens/color-radius.css +0 -250
  226. package/dist/styles/tokens/dark-arm.css +0 -194
  227. package/dist/styles/tokens/glass.css +0 -413
  228. package/dist/styles/tokens/light-dark.css +0 -158
  229. package/dist/styles/tokens/offsets-sizing.css +0 -406
  230. package/dist/styles/tokens/property-regs.css +0 -169
  231. package/dist/styles/tokens/scale-paper.css +0 -361
  232. package/dist/styles/tokens/scheme-motion.css +0 -334
  233. package/dist/styles/tokens/shadow.css +0 -132
  234. package/dist/styles/utilities/a11y-overrides.css +0 -140
  235. package/dist/styles/utilities/animate.css +0 -26
  236. package/dist/styles/utilities/base.css +0 -365
  237. package/dist/styles/utilities/btn.css +0 -399
  238. package/dist/styles/utilities/components.css +0 -317
  239. package/dist/underline.d.ts +0 -1
  240. package/dist/underline.js +0 -85
  241. package/dist/useSpecularTracking-DFK_fhpG.js +0 -32
  242. package/dist/useSpringMount-DXUzxBjV.js +0 -108
  243. package/dist/vReveal-CqaCz_mC.js +0 -44
  244. package/src/styles/glass/a11y-fallback.css +0 -245
  245. package/src/styles/glass/ladder.css +0 -304
  246. package/src/styles/glass/material.css +0 -238
  247. package/src/styles/glass/progress-rail.css +0 -78
  248. package/src/styles/glass/squircle.css +0 -66
  249. package/src/styles/glass/surfaces.css +0 -306
  250. package/src/styles/tokens/color-radius.css +0 -250
  251. package/src/styles/tokens/dark-arm.css +0 -194
  252. package/src/styles/tokens/glass.css +0 -413
  253. package/src/styles/tokens/light-dark.css +0 -158
  254. package/src/styles/tokens/offsets-sizing.css +0 -406
  255. package/src/styles/tokens/property-regs.css +0 -169
  256. package/src/styles/tokens/scale-paper.css +0 -361
  257. package/src/styles/tokens/scheme-motion.css +0 -334
  258. package/src/styles/tokens/shadow.css +0 -132
  259. package/src/styles/utilities/a11y-overrides.css +0 -140
  260. package/src/styles/utilities/animate.css +0 -26
  261. package/src/styles/utilities/base.css +0 -365
  262. package/src/styles/utilities/btn.css +0 -399
  263. package/src/styles/utilities/components.css +0 -317
  264. /package/dist/{CollapsibleContent-Drow5WkV.js → CollapsibleContent-CP9qF1v4.js} +0 -0
  265. /package/dist/{DialogFooter-DufLHi0y.js → DialogFooter-Gprw8H_A.js} +0 -0
  266. /package/dist/{IconTooltip-BrQ5p181.js → IconTooltip-Cus0fvK0.js} +0 -0
  267. /package/dist/{Input-B-F818RU.js → Input-xuDwALQR.js} +0 -0
  268. /package/dist/{_plugin-vue_export-helper-DWghtRt7.js → _plugin-vue_export-helper-ok8pgSl5.js} +0 -0
  269. /package/dist/{compile-Ce_V55zi.js → compile-BOXjLUxu.js} +0 -0
  270. /package/dist/{constants-C8NMonuo.js → constants-yKeKnE84.js} +0 -0
  271. /package/dist/{prng-CjVgzjQT.js → prng-D27-B3tK.js} +0 -0
  272. /package/dist/{resolveCanvasColor-CRvVzOvP.js → resolveCanvasColor-BBiYfp8g.js} +0 -0
  273. /package/dist/{useCanvas2D-CSeH8h16.js → useCanvas2D-ClrQuZtp.js} +0 -0
  274. /package/dist/{useIntersectionPause-DAdVPVp4.js → useIntersectionPause-Cck5Uxk8.js} +0 -0
  275. /package/dist/{useInterval-D3USn0yc.js → useInterval-Dsmqwi03.js} +0 -0
  276. /package/dist/{useKeyboardShortcuts-i8tHd5WO.js → useKeyboardShortcuts-CyIYrndH.js} +0 -0
  277. /package/dist/{useScrollProgress-CcgmgMQt.js → useScrollProgress-CffFGLa5.js} +0 -0
  278. /package/dist/{useSortable-DnyGXKKY.js → useSortable-C8ReQ50P.js} +0 -0
  279. /package/dist/{useTextHighlight-B3b10W6r.js → useTextHighlight-CWEi25hf.js} +0 -0
@@ -60,5 +60,56 @@
60
60
  @keyframes gl-vt-slide-in { from { opacity: 0; translate: 0 var(--vt-rise, 8px); } }
61
61
  @keyframes gl-vt-slide-out { to { opacity: 0; translate: 0 var(--vt-rise, 8px); } }
62
62
 
63
+ /* ── gl-shared-element — the named-pair MORPH group (D6.c M6) ──────────────────
64
+ * Distinct from `.gl-list-item` (a cross-fade of MANY members in a re-rank): a
65
+ * shared-element morph is ONE element that exists in BOTH the old and new states
66
+ * under the SAME `view-transition-name`, so the browser MORPHS it in place — the
67
+ * group interpolates its size+position (transform) while old/new cross-fade. The
68
+ * editorial case: the gallery card's title IS the dashboard masthead's title, so
69
+ * the name you clicked GROWS into the name you read (the card → masthead route
70
+ * morph). The consumer adds `view-transition-class: gl-shared-element` plus a
71
+ * MATCHED `view-transition-name: <id>` on BOTH the source and destination element
72
+ * (the MANDATORY runtime rule — ≤1 element per name per state, else the morph is
73
+ * skipped silently), and wraps the navigation in `useRouteTransition` /
74
+ * `startViewTransition`.
75
+ *
76
+ * The morph rides the SMOOTH register (the 700ms-class spring, C-ANIM-VIZ-MAP T1
77
+ * §7) — a longer, gentler curve than the list-item cross-fade, because a morph
78
+ * that travels across the viewport wants room to read. The old/new cross-fade is
79
+ * softened so the morphing GROUP is the figure and the rest recedes. */
80
+ ::view-transition-group(.gl-shared-element) {
81
+ animation-duration: var(--vt-morph-duration, var(--duration-slow, 500ms));
82
+ animation-timing-function: var(--vt-morph-ease, var(--spring-smooth, ease-in-out));
83
+ }
84
+ ::view-transition-old(.gl-shared-element),
85
+ ::view-transition-new(.gl-shared-element) {
86
+ /* The image pair cross-fades UNDER the group's size/position morph — softer
87
+ than the group curve so the morph (the size/position travel) is the figure
88
+ and the pixel cross-fade is the recessive fill. */
89
+ animation-duration: var(--vt-morph-duration, var(--duration-slow, 500ms));
90
+ animation-timing-function: var(--vt-ease, var(--spring-smooth, ease-in-out));
91
+ }
92
+
93
+ /* ── gl-expand — the plate → fullscreen MORPH recipe (D6.c M7) ─────────────────
94
+ * The expand verb (a plate growing to fullscreen) is a SHARED-ELEMENT morph, not
95
+ * an opacity jump-cut: the plate IS the fullscreen surface, growing. It is a
96
+ * specialization of `gl-shared-element` — the SAME named-pair morph, with the
97
+ * expand register (a touch snappier than a route morph, because the surface stays
98
+ * in place and only the rect grows, so it wants less travel-room). `ExpandableContainer`
99
+ * wires the `view-transition-name` plumbing on its plate↔fullscreen surfaces (an
100
+ * opt-in `viewTransitionName` prop), so a consumer opts in and the open/close
101
+ * mutation — wrapped in `startViewTransition` — morphs the plate's rect to the
102
+ * fullscreen rect and back. The named pair is the SAME element across states
103
+ * (the slot content), so the browser captures one group and grows it. */
104
+ ::view-transition-group(.gl-expand) {
105
+ animation-duration: var(--vt-expand-duration, var(--duration-normal, 240ms));
106
+ animation-timing-function: var(--vt-expand-ease, var(--spring-bouncy, ease-out));
107
+ }
108
+ ::view-transition-old(.gl-expand),
109
+ ::view-transition-new(.gl-expand) {
110
+ animation-duration: var(--vt-expand-duration, var(--duration-normal, 240ms));
111
+ animation-timing-function: var(--vt-ease, var(--spring-bouncy, ease-out));
112
+ }
113
+
63
114
  /* Keep the non-transitioned UI interactive while the snapshot animates. */
64
115
  ::view-transition { pointer-events: none; }
@@ -1 +0,0 @@
1
- export declare const AURORA_VANGOGH_MEDIUM_GLSL = "// \u2500\u2500 Van-Gogh \u2014 DEDICATED atomic-dab body (W-AUR-VANGOGH-REBUILD) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// REBUILT FROM FIRST PRINCIPLES. The prior path routed van-Gogh through the shared\n// oil paintStrokeMedium cascade \u2014 four DENSE layers of LONG-THIN tensor-oriented\n// strokes (lenMul up to 5.2, widMul 0.22) hugging a continuous coherent field. Packed\n// that tight, thin strokes that follow continuous iso-bands MERGE into smooth flowing\n// filaments \u2014 the \"marbled flow-bands\" read (a spirograph/fingerprint, not impasto),\n// AND the per-cell 8-tap structure tensor \u00D7 4 layers \u00D7 9 cells = ~324 sampleBase/pixel\n// made it run at ~4fps. Van Gogh's sky is NOT continuous flow \u2014 it is DISCRETE, SHORT,\n// LOADED comma dabs, separated by visible ground, queued into swirl ROWS.\n//\n// The rebuild is a purpose-built two-layer DAB pass, disjoint from the oil cascade:\n// \u2022 orientation from the analytic SWIRL flowField (van-Gogh skies ARE swirl rows) +\n// per-cell angular jitter \u2014 NOT the expensive per-cell tensor (the lag source, and\n// the marble source: a jittered discrete dab can NOT merge into a continuous\n// filament the way a tensor-locked thin stroke does).\n// \u2022 SHORT comma dabs (len/wid \u2248 2.6 : 1 \u2014 a loaded crescent mark, not a 10:1\n// filament), so each reads as a SEPARABLE atom.\n// \u2022 SPARSE placement with visible inter-dab ground (density \u2248 0.42), over a darkened\n// swirl underpainting (the Starry-Night visible ground the bright dabs read over).\n// \u2022 a single sampleBase per cell + OKLCh broken-color jitter (pigment shimmer);\n// full-height impasto crown per dab (each catches its own raked glint).\n// This is ~2 layers \u00D7 9 cells \u00D7 ~1 sampleBase \u2248 20/pixel (a ~16\u00D7 cost cut, ~60fps), and\n// jittered short dabs CANNOT marble.\n\n// One atomic comma dab \u2014 a CLEAN analytic crescent SDF (NOT the oil curvedStroke).\n// The oil curvedStroke's spine-projection + rounded end-caps + fwidth-AA + bristle\n// edge each leave a thin sub-pixel skirt, and a field of those skirts over open ground\n// abuts into a faint network of SEAM LINES. A van-Gogh dab needs none of that\n// machinery \u2014 it is a short oriented capsule (rounded line segment) whose half-width\n// tapers along its length (the loaded-head \u2192 dragged-tail comma). The capsule SDF is\n// derivative-free (smoothstep AA against the analytic distance), so no fwidth skirt, no\n// best-of-9 seam. Returns a StrokeHit (coverage/color/alongT/edgeN) for paintOver.\n// cellSize \u2014 dab cell pitch (UV units); lenMul/widMul \u2014 dab aspect off the cell;\n// density \u2014 placement gate (sparse \u2192 visible gaps); seed \u2014 layer decorrelation.\nStrokeHit vangoghDab(vec2 p, float cellSize, float lenMul, float widMul,\n float density, float jitterAmt, float angJitter,\n vec2 flow, float t, float seed) {\n vec2 cell = floor(p / cellSize);\n StrokeHit best = noHit();\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 cc = cell + vec2(float(dx), float(dy));\n // Sparse density gate \u2014 leaves visible canvas ground between dabs (atomicity).\n if (hash21(cc * 1.7 + seed * 0.3) > density) continue;\n vec2 jit = (hash22(cc + seed) - 0.5) * jitterAmt;\n vec2 center = (cc + 0.5 + jit) * cellSize;\n\n // Orientation: the analytic swirl flow at the cell center + per-cell angular\n // jitter (so adjacent dabs FAN \u2014 the divisionist scatter that keeps the dabs from\n // locking into perfectly-concentric rows) + a flow-noise curl wobble.\n float ang = (hash21(cc + seed + 11.0) - 0.5) * angJitter;\n float curl = (fbm(center * 3.1 + seed * 1.9) - 0.5) * (0.18 + 0.3 * uFlowCurl);\n vec2 dir = rotateDir(safeDir(flow), ang + curl);\n\n // SHORT comma \u2014 len \u2248 the cell pitch (a contained dab, not a tiling filament).\n float len = cellSize * lenMul * (0.82 + 0.30 * hash21(cc + seed + 23.0));\n float halfW = max(cellSize * widMul * (0.86 + 0.28 * hash21(cc + seed + 41.0)), 0.010);\n\n // Local dab frame: along = projection onto the dab axis (centred 0), perp = cross.\n vec2 rel = p - center;\n float along = dot(rel, dir);\n float perp = dot(rel, vec2(-dir.y, dir.x));\n // The comma TAPER: half-width peaks ~1/3 from the loaded head and drags to a fine\n // tail (the asymmetric crescent). u in [0,1] along the dab from head to tail.\n float halfLen = len * 0.5;\n float u = clamp((along + halfLen) / max(len, 1e-5), 0.0, 1.0);\n float head = smoothstep(0.0, 0.30, u); // rounded loaded head\n float tail = pow(clamp((1.0 - u) / 0.70, 0.0, 1.0), 1.3); // dragged thin tail\n float prof = clamp(min(head, tail) * 1.05, 0.0, 1.0);\n float wNow = halfW * prof;\n // A gentle comma CURVE \u2014 bow the spine sideways so the mark reads as a crescent.\n float bowAmt = (hash21(cc + seed + 53.0) - 0.5) * halfW * 1.4;\n float spine = bowAmt * sin(u * PI); // 0 at ends, max mid\n float d = abs(perp - spine);\n // Derivative-free AA: a fixed fraction of the dab width (no fwidth skirt). Coverage\n // is 1 in the dab body, smoothly 0 at the edge; outside the [head,tail] span wNow\u21920\n // so the dab self-terminates with no end-cap blob.\n float aa = max(halfW * 0.45, 0.002);\n float cov = (wNow > 1e-5) ? (1.0 - smoothstep(wNow - aa, wNow + aa, d)) : 0.0;\n if (cov < 0.004) continue;\n\n // One sampleBase per cell + OKLCh broken-color jitter (pigment patch shimmer). The\n // dab pigment is chroma-boosted (saturate3 1.22) AND value-lifted (\u00D71.14) at the\n // SOURCE \u2014 the loaded brush mark deposits BRIGHTER + more saturated pigment than the\n // base field, so the loaded-mark pixels lift BOTH the \u00A74.1 colourfulness AND the field\n // mean-luma. The higher mean raises the gap-fraction threshold (meanLum\u00B70.6) so the\n // moderate-depth inter-dab ground falls below it (the gap-fraction atomicity read is\n // DECOUPLED from the ground floor depth \u2014 the ground can stay only moderately dark, so\n // the \u00A74.3 slope is NOT over-steepened, while the bright dabs manufacture the gap). The\n // dark ground is untouched, so this lifts C + gap WITHOUT a band-conflicting deep ground.\n vec3 colMid = brokenColorJitter(\n saturate3(sampleBase(center, t), 1.22),\n hash21(cc + seed + 89.0),\n hash21(cc * 2.3 + seed + 97.0),\n 1.0\n );\n\n // edgeN: 1 at the spine, 0 at the edge (the impasto crown reads it).\n float edgeN = (wNow > 1e-5) ? clamp(1.0 - d / wNow, 0.0, 1.0) : 0.0;\n if (cov > best.coverage) {\n best = StrokeHit(cov, colMid, u, (wNow > 1e-5 ? (perp - spine) / wNow : 0.0), edgeN);\n }\n }\n }\n return best;\n}\n\nvec3 mediumVangogh(vec3 col, vec2 p, float t) {\n vec3 result = col;\n float height = 0.0;\n\n // The swirl flow basis (van-Gogh sky = swirl rows). Computed ONCE per pixel.\n vec2 flow = flowField(p, t);\n\n // Dab cell pitch in UV [0,1]. CHUNKY, SEPARABLE marks \u2014 the big layer is ~1/14 of\n // the frame so it reads as a distinct loaded brush dab (not a fine speckle, not a\n // screen-spanning filament). uStrokeScale (authored ~110) modulates the pitch\n // INVERSELY (higher = finer dabs) around the ~0.07 chunky default; clamped so the\n // dab never collapses to noise or balloons past one screen. uStrokeAnisotropy\n // stretches the comma aspect (longer, more directional marks).\n float pitch = clamp(7.0 / max(uStrokeScale, 20.0), 0.044, 0.12);\n // The dab LENGTH \u2248 the cell pitch (lenAniso ~1.2-1.7) so a dab sits WITHIN its cell\n // and leaves visible ground around it \u2014 a longer dab (lenMul > 2) spans neighbour\n // cells and tiles the field into continuous coverage (no gaps, the gap-fraction floor\n // miss + the marble). Narrow width keeps it a directional crescent, not a wide shard.\n // lenAniso/widAniso \u2014 the comma aspect. The W-AUR-VANGOGH-CONFIG reconcile lengthened\n // the comma (1.25-1.75 \u2192 1.5-2.0) and THINNED it (0.40-0.30 \u2192 0.32-0.24): the rebuilt\n // dabs measured \u00A74.2 structure-tensor anisotropy A=0.699, BELOW the reference band\n // floor 0.732 (the dabs read slightly too short-fat \u2192 locally isotropic, dragging mean\n // A down). A LONGER, THINNER comma hugs the swirl-flow tangent more strongly so the\n // rendered field reads coherent the way the tensor metric measures it (A lift), while\n // the thinner width LEAVES MORE inter-dab ground (the gap-fraction atomicity read is\n // preserved, not closed). The length stays \u2248 the cell pitch so each dab remains a\n // CONTAINED separable mark, not a tiling filament.\n float lenAniso = mix(2.1, 2.7, uStrokeAnisotropy); // comma length / cell pitch (a contained dab)\n float widAniso = mix(0.23, 0.16, uStrokeAnisotropy); // comma width / cell pitch (a thin loaded crescent)\n\n // Layer 1 \u2014 the big swirl-row dabs: the loaded gestural marks, SPARSE so the dark\n // underpainting shows BETWEEN them (the atomicity read \u2014 visible inter-dab ground).\n // hardness 0.74 \u2014 the loaded brush deposits with a SOFT shoulder, so adjacent dabs\n // feather instead of razor-clipping into hard polygon shards. jitterAmt 0.85 fully\n // scatters the cell centres so the placement GRID never reads as a periodic seam.\n // angJitter EASED 0.55 \u2192 0.38 (the reconcile A lift): a tighter angular spread keeps\n // adjacent dabs more flow-aligned (coherent) while the per-cell curl wobble still\n // breaks the perfectly-concentric-rows read (the dabs FAN gently, not lock to a grid).\n // angJitter eased 0.38 \u2192 0.26 + hardness 0.74 \u2192 0.84 (the \u00A74.2 A lift): a tighter angular\n // spread keeps adjacent dabs strongly flow-aligned (the structure-tensor coherence) and a\n // sharper edge gives each dab a STRONGER directional gradient (a soft dab's faint edge\n // reads weakly anisotropic). The per-cell curl wobble still breaks the perfectly-\n // concentric-rows read, so the dabs FAN gently rather than locking to a grid.\n StrokeHit dBig = vangoghDab(p, pitch, lenAniso, widAniso,\n 0.30, 0.50, 0.08, flow, t, 1.3);\n // streakFreq raised 14 \u2192 34 (the \u00A74.3 slope fix): a high-frequency streak runs ALONG the\n // dab spine, injecting fine-scale luma energy that flattens the too-steep \u03B2 WITHOUT\n // adding new isotropic marks (the along-spine streak stays directional, so the \u00A74.2\n // anisotropy the long-thin dab carries is preserved \u2014 the band-conflict resolution).\n paintOver(result, height, dBig, 48.0, 0.34,\n uImpasto * 0.75 * uStrokeAmount, 0.84, 1.3, 1.0 /* full crown */);\n\n // Layer 2 \u2014 two-thirds-pitch accent dabs (the divisionist sparkle between the big\n // marks \u2014 denser placement but still contained dabs, so dark canvas survives between).\n // angJitter eased 0.5 \u2192 0.34 (same A-lift reasoning \u2014 the accent dabs queue along the\n // flow rather than scattering isotropically); hardness 0.78 \u2192 0.86 sharpens the gradient.\n StrokeHit dSml = vangoghDab(p + vec2(-5.1, 8.4), pitch * 0.62, lenAniso * 0.95,\n widAniso * 0.95, 0.36, 0.60, 0.20, flow, t, 4.1);\n paintOver(result, height, dSml, 42.0, 0.22,\n uImpasto * 0.55 * uStrokeAmount, 0.86, 4.1, 1.0);\n\n // Layer 3 \u2014 the FINE divisionist flecks (W-AUR-VANGOGH-CONFIG reconcile). The two-layer\n // field read as a few BIG cobalt dabs over a smooth empty teal ground (the side-by-side\n // against starry-night-crop.png: the painting is DENSE small varied flecks, not sparse\n // large marks). The flecks are LONG\u00B7THIN directional commas hugging the swirl tangent\n // (the A-preserving fleck \u2014 short fat flecks read isotropic and drag \u00A74.2 down). Sparse\n // density 0.30 keeps the inter-fleck ground open (the gap-fraction atomicity read).\n // The flecks are FINE (\u22480.42\u00D7 pitch) directional commas, tightly flow-aligned (angJitter\n // 0.22) and SPARSE (0.30) \u2014 the divisionist sparkle between the loaded marks that keeps\n // the inter-dab ground open (atomicity) while adding the small-mark mid-band energy. Thin\n // + flow-aligned so the \u00A74.2 anisotropy the long dabs carry survives the added small marks.\n StrokeHit dFleck = vangoghDab(p + vec2(8.7, -3.2), pitch * 0.42, lenAniso * 1.0,\n widAniso * 0.68, 0.30, 0.85, 0.22, flow, t, 7.7);\n paintOver(result, height, dFleck, 30.0, 0.16,\n uImpasto * 0.40 * uStrokeAmount, 0.80, 7.7, 1.0);\n\n // \u2500\u2500 Flow-aligned GROUND swirl-GROOVING (W-AUR-VANGOGH-CONFIG reconcile) \u2500\u2500\n // The bare ground between the dabs was a SMOOTH low-frequency teal gradient \u2014 the \u00A74.3\n // power-spectrum slope ran too STEEP (\u03B2\u2248\u22122.0: too much low-frequency nuclei-field energy\n // vs the high band). Van Gogh's actual sky has the swirl BRUSHWORK everywhere, so groove\n // the OPEN GROUND with a flow-aligned ripple. It is SUBTRACTIVE-biased (it only darkens,\n // never brightens the ground), so it DEEPENS the inter-dab valleys (MORE gap-fraction \u2014\n // atomicity preserved/strengthened) while injecting the across-flow mid-band luma energy\n // that flattens \u03B2. Gated to the open ground (low height) via the (1-height) gate so it\n // never lifts/erodes the loaded dab bodies (the dab read is untouched). Across the swirl\n // FLOW axis so the grooves run WITH the sky's brushwork direction.\n // The ground swirl-combing \u2014 a FIXED-global-angle directional grain on the open ground.\n // A flow-FOLLOWING comb varies its direction with the swirl across the readback window,\n // so its blurred structure tensor averages toward isotropic (no \u00A74.2 lift). A comb at one\n // GLOBAL angle (van-Gogh's dominant diagonal stroke grain) is COHERENT over the whole\n // window \u21D2 every open-ground pixel reads the SAME direction (the \u00A74.2 mean-anisotropy lift\n // the swirl comb could not reach). Two resolved bands (\u224822 + \u224844 across the global axis \u21D2\n // ~21px + ~11px at 464px, both in the \u00A74.3 fit window) also feed the \u03B2 flatten. Gated to\n // the open ground (low height) so the loaded dabs are untouched; SUBTRACTIVE-biased so the\n // inter-dab valleys deepen (gap-fraction preserved, not filled).\n vec2 gdir = normalize(vec2(0.82, 0.57)); // the dominant global stroke grain axis\n float gacross = dot(p, vec2(-gdir.y, gdir.x));\n float groundGate = 1.0 - smoothstep(0.05, 0.28, height);\n float groove = sin(gacross * 22.0) + 0.5 * sin(gacross * 44.0 + 1.3);\n result *= 1.0 - 0.16 * groundGate * (0.5 - 0.5 * groove);\n\n // Canvas tooth (fine linen weave \u2014 base relief the raking light catches).\n float tooth1 = vnoise(p * 220.0);\n float tooth2 = vnoise(p * 220.0 * vec2(0.6, 2.4) + 37.0);\n float tooth = (0.6 * tooth1 + 0.4 * tooth2) - 0.5;\n result *= 1.0 + tooth * 0.06 * uCanvasGrain;\n\n // Relight the accumulated impasto height (raking light catches each dab's crown \u2014\n // the visible impasto ridge that makes a dab read as a RAISED loaded mark).\n float canvasBase = tooth * 0.06 * 0.5;\n result = relightImpasto(result, height, canvasBase);\n\n // The visible Starry-Night GROUND \u2014 the open canvas between dabs (low accumulated\n // height) darkens toward the deep underpainting, so the bright impasto dabs read as\n // SEPARABLE atomic marks over a darker field (the dab\u2194ground contrast the user's\n // \"reads as strokes\" bar needs, AND the painterly-statistics gap-fraction floor \u2014 the\n // dark inter-dab ground must register as a measurable fraction of the field). 0.30\n // floor over a WIDER smoothstep (0..0.40): deep enough that the open gaps read as the\n // dark Starry-Night sky between marks (clearing the 4% gap floor) while the gradual\n // ramp keeps the gaps reading as flowing underpainting, not the hard black ink LINES a\n // narrow near-black step (0.26 / 0.0..0.32) produced.\n // The smoothstep FLOOR starts at 0.10 (not 0): a dab's faint AA coverage TAIL deposits\n // a sliver of height, and where many tails align along the swirl flow those slivers\n // accumulate into a faint continuous height ridge that read as thin curved LINES in the\n // ground. Holding the ground full-dark until a real dab CORE (height > 0.10) lifts out\n // keeps the open field clean \u2014 only the loaded dab bodies emerge, the tails stay ground.\n result *= mix(0.115, 1.0, smoothstep(0.085, 0.31, height));\n\n // The van-Gogh chroma \u2014 a light OKLCh punch. EASED to 0.92 (off 1.04) in the\n // W-AUR-VANGOGH-CONFIG reconcile: the rebuilt discrete-dab register's per-dab OKLCh\n // broken-color jitter (the \u00B116\u00B0 hue + \u00B1chroma swing per cell) lifts the field's\n // colourfulness on its own, so the prior 1.04 punch on TOP overshot the \u00A74.1\n // reference band (rendered C=100.5 vs the painting's measured 70.67 \u00B1 15/+25 \u2192\n // ceiling 95.67 \u2014 neon, not Starry Night's rich-but-not-garish blue/gold). The 0.92\n // demote pulls the rendered colourfulness back IN-band while the broken-color jitter\n // keeps the per-dab pigment variation (the discrete-stroke read is untouched \u2014 this\n // is a chroma scale, not a dab-geometry change). Band-anchored on the real painting\n // (proof:aurora-arresting), NOT a widened band.\n result = saturate3(result, 1.0);\n return result;\n}\n\n";
@@ -1,35 +0,0 @@
1
- import type { ConstellationField } from "../constellationField";
2
- type WanderProp = boolean | {
3
- minIdle?: number;
4
- jitter?: number;
5
- };
6
- type GravityWellProp = boolean | {
7
- holdMs?: number;
8
- gain?: number;
9
- reach?: number;
10
- ramp?: number;
11
- maxSpeed?: number;
12
- soften?: number;
13
- };
14
- export interface ConstellationFieldState {
15
- field: ConstellationField;
16
- /** The wander prop override the render re-layers over the on-mount token read. */
17
- wanderOverride: {
18
- minIdle?: number;
19
- jitter?: number;
20
- };
21
- /** The well prop override the render re-layers over the on-mount token read. */
22
- wellOverride: Exclude<GravityWellProp, boolean>;
23
- }
24
- /**
25
- * Build the per-instance field state. The focal node (AX.W17) is engine-owned:
26
- * `focalIndex` names the pinned node, `warp` is the per-axis critically-damped
27
- * spring the engine steps inside `stepField`. `wander`/`gravityWell` absent/false
28
- * leaves `field.wander`/`field.well` undefined (byte-identical to HEAD — stepField
29
- * skips the cadence / force pass); `true` / an object seeds the cold state with the
30
- * built-in defaults + any prop override layered on (the on-mount
31
- * `readInteractionConfig` token read re-points the un-overridden members, with the
32
- * returned `*Override` winning over the token in the render closure).
33
- */
34
- export declare function createConstellationField(wander: WanderProp, gravityWell: GravityWellProp): ConstellationFieldState;
35
- export {};
@@ -1,35 +0,0 @@
1
- import type { Ref } from "vue";
2
- import type { ConstellationField, ConstellationPointer, ConstellationRipple } from "../constellationField";
3
- /** The substrate handle the wiring reads (`wake` re-arms a parked surface). */
4
- interface CanvasHandle {
5
- wake: () => void;
6
- reducedMotion: boolean;
7
- }
8
- export interface UseConstellationPointerOptions {
9
- host: HTMLElement | null;
10
- canvas: HTMLCanvasElement;
11
- field: ConstellationField;
12
- pointer: ConstellationPointer;
13
- ripples: ConstellationRipple[];
14
- handle: CanvasHandle;
15
- /** The hoisted client→canvas-local mapper ref the exposed `warpTo(clientX,clientY)` reads. */
16
- toLocalRef: Ref<((e: {
17
- clientX: number;
18
- clientY: number;
19
- }) => ConstellationPointer | null) | null>;
20
- pointerReactive: boolean;
21
- warpOnClick: boolean;
22
- gravityWell: boolean;
23
- /** The deterministic-capture predicate — a frozen capture registers NO listeners. */
24
- isFrozen: boolean;
25
- }
26
- /**
27
- * Wire the constellation pointer listeners on the host. Sets the hoisted
28
- * `toLocal` mapper (the deck-scale invariant — BOTH the ripple path AND the warp
29
- * path read this ONE mapper), then registers the three independent listener
30
- * blocks gated by their respective prop flags (each PRM-gated + capture-gated).
31
- * No teardown is returned: the listeners ride the component's lifetime (the host
32
- * element is torn down with the component), matching the prior inline behaviour.
33
- */
34
- export declare function useConstellationPointer(opts: UseConstellationPointerOptions): void;
35
- export {};
@@ -1,36 +0,0 @@
1
- import type { ConstellationPalette, ConstellationWellConfig } from "./constellationField";
2
- /**
3
- * The reference layout width (px) the field's node geometry is authored against. A
4
- * live canvas's `k = width / BASE_WIDTH` scales every base-width length (the well
5
- * reach/speed, the node spacing) so a 600px and a 1280px canvas read the same shape.
6
- */
7
- export declare const BASE_WIDTH = 1280;
8
- /**
9
- * The neutral palette FALLBACK the draw passes read when the `--constellation-*`
10
- * color/alpha tokens are absent (SSR / no-token mount). The fallbacks mirror the §5c
11
- * light-arm token defaults so a no-token mount still reads recessive-but-legible.
12
- */
13
- export declare const DEFAULT_PALETTE: ConstellationPalette;
14
- /**
15
- * Warp spring DEFAULTS — `--constellation-warp-*` tokens override these on mount.
16
- * `WARP_RESPONSE` is the keyframes.js angular PERIOD (s, NOT a settle-duration);
17
- * `WARP_ZETA = 1.0` is critically damped so a focal mark never rings/overshoots.
18
- */
19
- export declare const WARP_RESPONSE = 0.55;
20
- export declare const WARP_ZETA = 1;
21
- /**
22
- * Gravity-well tuning DEFAULTS (AY.W-CON2). The `--constellation-well-*` tokens
23
- * override these on mount via `field.well.cfg`; these stay the fallback. SET by the
24
- * §6 egg-live π readback (the field-perturbs-then-cools capture is the binding
25
- * truth) — a moderate gain over a generous reach, a brisk ramp, a tight no-slingshot
26
- * speed cap, and the singularity-soften floor.
27
- */
28
- export declare const DEFAULT_WELL_CONFIG: ConstellationWellConfig;
29
- /**
30
- * Auto-DRIFT cadence DEFAULTS (AY.W-CON1 source; tokenised in AY.W-CON2). The
31
- * `--constellation-wander-idle`/`-wander-jitter` tokens override these on mount; a
32
- * prop `{ minIdle, jitter }` still wins over the token. The 8s/8s default rhythm
33
- * re-targets the focal mark every 8–16s (the slides cadence).
34
- */
35
- export declare const DEFAULT_WANDER_IDLE = 8000;
36
- export declare const DEFAULT_WANDER_JITTER = 8000;
@@ -1,18 +0,0 @@
1
- import type { ConstellationField, ConstellationPalette, ConstellationPointer, ConstellationRipple } from "./constellationField";
2
- import { DEFAULT_PALETTE } from "./constants";
3
- export { DEFAULT_PALETTE };
4
- /**
5
- * Resolve the FULL neutral palette + legibility weights off a canvas's resolved
6
- * custom properties (AX.W17). The colors AND the alpha multipliers route through
7
- * the same `getComputedStyle` probe, so a dark-mode flip re-resolves BOTH the
8
- * `:root`/`.dark` color arms AND the per-mode alpha defaults in one read.
9
- */
10
- export declare function readPalette(canvas: HTMLCanvasElement): ConstellationPalette;
11
- /** Pass 1 — hairline edges between any two nodes within `link` px (alpha falls off with distance). */
12
- export declare function drawEdges(ctx: CanvasRenderingContext2D, field: ConstellationField, link: number, palette: ConstellationPalette, opacityCeiling?: number): void;
13
- /** Pass 2 — ambient node dots. */
14
- export declare function drawNodes(ctx: CanvasRenderingContext2D, field: ConstellationField, palette: ConstellationPalette, opacityCeiling?: number): void;
15
- /** Pass 3 — the cursor joins the web: faint links to nodes within reach + a soft cursor node. */
16
- export declare function drawPointerWeb(ctx: CanvasRenderingContext2D, field: ConstellationField, link: number, palette: ConstellationPalette, pointer: ConstellationPointer | null, opacityCeiling?: number): void;
17
- /** Pass 4 — tap ripples: expanding rings that fade over ~0.9s; consumed entries are spliced. */
18
- export declare function drawRipples(ctx: CanvasRenderingContext2D, field: ConstellationField, now: number, ripples: ConstellationRipple[], palette: ConstellationPalette, opacityCeiling?: number): void;
@@ -1,102 +0,0 @@
1
- import type { ConstellationField, ConstellationWarpConfig, ConstellationWellConfig } from "./constellationField";
2
- import { DEFAULT_WANDER_IDLE, DEFAULT_WANDER_JITTER, DEFAULT_WELL_CONFIG, WARP_RESPONSE, WARP_ZETA } from "./constants";
3
- export { DEFAULT_WANDER_IDLE, DEFAULT_WANDER_JITTER, DEFAULT_WELL_CONFIG, WARP_RESPONSE, WARP_ZETA };
4
- /**
5
- * Read the NUMERIC interaction-tuning tokens (the warp spring + the gravity-well
6
- * gains) off a canvas's resolved custom properties — ONCE on mount (AY.W-CON2),
7
- * via `parseFloat`, NOT per-frame `getComputedStyle` (the hot loop stays clean).
8
- * Returns `{ warp, well }` configs the field carries; every member falls back to
9
- * the shipped default when the token is absent (an SSR / no-token mount reads the
10
- * byte-identical spring). The tokens are PLAIN numbers (`0.55`, `12000`), immune
11
- * to the W30 `light-dark()`-into-Canvas2D leak (they never reach a `fillStyle`).
12
- */
13
- export declare function readInteractionConfig(canvas: HTMLCanvasElement): {
14
- warp: ConstellationWarpConfig;
15
- well: ConstellationWellConfig;
16
- wander: {
17
- minIdle: number;
18
- jitter: number;
19
- };
20
- };
21
- /**
22
- * Advance the gravity-well one `dt` (AY.W-CON2). A transient held-pointer force
23
- * composed inside `stepField` (NO new rAF): ease `well.strength` toward
24
- * `well.target` (1 held / 0 released) at `cfg.ramp`/s; while active, add an
25
- * inverse-square pull toward the held point onto each node within `cfg.reach`
26
- * (the `max(d, soften)` no-singularity floor + the `cfg.maxSpeed` no-slingshot
27
- * clamp); ALWAYS ease every node's |v| back toward `speed` (the field-cools
28
- * invariant — so a released well re-settles). No-ops (entirely skipped) when
29
- * `field.well` is undefined → the default render is byte-identical to HEAD.
30
- *
31
- * `dt` is clamped to {@link WARP_DT_CLAMP} (the same park-resume guard the warp
32
- * uses) so a tab-throttle gap cannot slingshot the field in one giant step.
33
- */
34
- export declare function stepWell(field: ConstellationField, k: number, speed: number, dt: number): void;
35
- /**
36
- * The nearest DRIFTING node to `(px, py)` in canvas-local px — a linear O(count)
37
- * min-d² scan (count 64 default — negligible; matches the O(count²) edge pass).
38
- * "Lattice point" = the nearest drifting NODE (the constellation has NO fixed
39
- * lattice). `excludeIdx` drops a node from the candidate set (the focal node
40
- * excludes ITSELF, so a cursor-on-focal warp no-ops). Returns `-1` if no
41
- * eligible node exists (empty field, or only the excluded node).
42
- */
43
- export declare function nearestNode(field: ConstellationField, px: number, py: number, excludeIdx?: number): number;
44
- /**
45
- * Advance the focal-node warp spring one `dt` (seconds). A per-axis 2nd-order
46
- * critically-damped integrator over `field.warp.{x,y}` toward the LIVE position
47
- * of `field.nodes[field.warp.targetIdx]` — re-read EACH frame, so the spring
48
- * CHASES a drifting target and arrives ON it (the identity-ride). No-ops when no
49
- * warp is active (`targetIdx < 0`). `dt` is clamped to {@link WARP_DT_CLAMP} so a
50
- * tab-throttle / offscreen-park-resume gap cannot teleport the mark.
51
- *
52
- * x += v·dt ; v += (−2ζω·v − ω²·(x − target))·dt
53
- *
54
- * Reads `(response, ζ)` from `field.warpCfg` (the tokenised override — AY.W-CON2),
55
- * falling back to the shipped `WARP_RESPONSE`/`WARP_ZETA` defaults. `ω = 2π/response`
56
- * is the keyframes.js `(response, dampingFraction)` convention (the SHARED house
57
- * model — `ω₀` is the angular frequency, `response` its ANGULAR PERIOD, NOT a
58
- * settle-duration; at ζ=1 the 2%-settle is `t₂ ≈ 5.83/ω₀ ≈ 0.93·response`). NO
59
- * second ω formula is minted (the ω-reconcile). NOT its rAF — the FORBID-useSpring
60
- * contract (a second rAF would defeat the parked-substrate one-path freeze).
61
- */
62
- export declare function warpStep(field: ConstellationField, dt: number): void;
63
- /**
64
- * Point the warp at a node INDEX (the live target-source seam). The focal node
65
- * re-points to `idx`; the spring chases `nodes[idx]`'s LIVE position FROM the
66
- * focal mark's CURRENT position (`warp.{x,y}`) — a continuous spring-eased path,
67
- * never a snap. The component seeds `warp.{x,y}` at field-center on first layout,
68
- * so even the first warp springs from a real start point. `idx < 0` clears the
69
- * warp (the focal mark is removed). Re-pointing does NOT zero the velocity, so a
70
- * mid-flight re-target curves smoothly toward the new node.
71
- */
72
- export declare function setWarpTarget(field: ConstellationField, idx: number): void;
73
- /**
74
- * Warp the focal node to the nearest drifting node to a canvas-LOCAL px point
75
- * (the `warpTo(point)` primitive). The DEGENERATE case — the click's UNCONSTRAINED
76
- * nearest node is already the current focal (cursor on/closest to the focal mark)
77
- * — NO-OPS (returns the current focal; a click on yourself does not re-warp). Any
78
- * OTHER click re-points to the nearest node, with the focal EXCLUDED from the
79
- * candidate set (you never re-warp to yourself; the next-nearest wins). Returns
80
- * the chosen node index, or `-1` when no eligible node exists. The component's
81
- * `warpTo(clientX, clientY)` sugar maps client→local px via `toLocal` first.
82
- */
83
- export declare function warpTo(field: ConstellationField, px: number, py: number): number;
84
- /**
85
- * Is the warp spring ARRIVED on its target (AY.W-CON1)? True when there is no
86
- * active target (`targetIdx < 0`) OR the focal's gap to its LIVE target node is
87
- * within {@link WARP_SETTLE_BAND}. A click-warp in flight (hundreds of px out)
88
- * reports NOT arrived, so a user click always PRE-EMPTS the auto-drift cadence
89
- * (the wander only re-targets a spring that has reached its current node). The
90
- * gate is POSITION-only by design — a critically-damped spring tracking a drifting
91
- * node carries a non-zero steady-state velocity forever, so a velocity term would
92
- * never clear on a live field.
93
- */
94
- export declare function warpSettled(field: ConstellationField): boolean;
95
- /**
96
- * Pick a random eligible node index for the auto-drift re-target (AY.W-CON1) —
97
- * any node EXCEPT the current `focalIndex` (so the focal actually MOVES). `rng`
98
- * is the seeded `() => number` in `[0, 1)`. A degenerate field (≤1 node, or only
99
- * the current focal) returns the current focal, which `setWarpTarget` no-ops
100
- * cleanly (no crash, no jump).
101
- */
102
- export declare function pickWanderTarget(field: ConstellationField, rng: () => number): number;
@@ -1,15 +0,0 @@
1
- import { type Ref } from "vue";
2
- /** The morph-window handlers the GlassDock SFC wires. */
3
- export interface DockMorphWindow {
4
- markTransitioning: () => void;
5
- onDockTransitionDone: (event: TransitionEvent) => void;
6
- clearTransitionTimer: () => void;
7
- }
8
- /**
9
- * Own the `isTransitioning` flag's morph-window lifecycle. `markTransitioning`
10
- * (every `visualExpanded` flip) bumps a private generation so any in-flight
11
- * morph's pending timer / `transitionend` self-cancels (the A→B→A no-skip /
12
- * no-queue invariant); `onDockTransitionDone` resolves the flag on a resize-morph
13
- * property finishing. Clears its timer on unmount.
14
- */
15
- export declare function useDockMorphWindow(dockEl: Ref<HTMLElement | null>, isTransitioning: Ref<boolean>): DockMorphWindow;
@@ -1,131 +0,0 @@
1
- import { type ComputedRef } from "vue";
2
- export type DockDensity = "compact" | "comfortable" | "spacious" | "audacious";
3
- export interface DockCommonProps {
4
- fitContent?: boolean;
5
- position?: "fixed" | "inline" | "sticky";
6
- alwaysExpanded?: boolean;
7
- /**
8
- * Corner treatment.
9
- * `"pill"` — the stadium silhouette (default).
10
- * `"rounded"` — a finite rounded radius (`--radius-xl`).
11
- * `"card"` — the AW.W3b big-dock card shell: a finite concentric
12
- * radius (`--dock-card-radius`, default `--radius-3xl`)
13
- * ABOVE 2xl, below pill — does NOT collapse to a stadium.
14
- * Collapsed it returns to a pill; the pill↔card swap
15
- * morphs on the `--dock-motion-resize` spring. AX.W56's
16
- * squircle policy applies `corner-shape:
17
- * var(--corner-shape-bigdock)` here under `@supports
18
- * (corner-shape: superellipse(2))` — the big-dock is the ONE
19
- * surface where the superellipse reads (cards/pills stay
20
- * round); the border-radius arc is the cross-engine contract.
21
- *
22
- * `"pill"`/`"rounded"` previously bound ONLY under the vertical rail
23
- * variant — on a horizontal dock the prop silently no-op'd. AW.W3b adds
24
- * the horizontal-root shape rules (closing that documented-but-dead prop),
25
- * so `shape` now paints on a horizontal dock too.
26
- */
27
- shape?: "pill" | "rounded" | "card";
28
- /**
29
- * Layout axis of the dock. `"horizontal"` (default) lays items out
30
- * left-to-right and animates `width`; `"vertical"` lays items out
31
- * top-to-bottom and animates `height`. IGNORED under `variant="rail"` /
32
- * `"instrument-strip"` (those force vertical by construction).
33
- */
34
- orientation?: "horizontal" | "vertical";
35
- /**
36
- * Density controls dock padding, gaps, layer height, and inherited
37
- * dock control sizing. Root CSS variables can override each density.
38
- */
39
- density?: DockDensity;
40
- /**
41
- * Overflow strategy when the expanded content exceeds the dock's
42
- * axis cap (`--dock-max-inline-size` horizontally,
43
- * `--dock-max-block-size` vertically). The ONE knob governing every
44
- * overflow behaviour (AT.W7-dock-a clean break — collapsed from the
45
- * prior `wrap` boolean + `overflow` pair + `containerName` clip-lift,
46
- * which all touched overflow divergently).
47
- * `"grow"` — content grows to fit then overflows visibly past
48
- * the cap (the default; nothing clips or scrolls).
49
- * `"wrap"` — expanded content wraps to multiple rows via CONTENT-DRIVEN
50
- * intrinsic flex-wrap (the `.dock-overflow-wrap` recipe). The
51
- * dock shrink-wraps to content and caps that intrinsic width
52
- * at `max-inline-size: var(--dock-max-inline-size)`, so the row
53
- * reflows to N rows EXACTLY when its intrinsic width exceeds
54
- * the cap — at ANY viewport width — and collapses to one row
55
- * when it fits (no viewport breakpoint). The wrapped multi-row silhouette lifts
56
- * onto the card/floating shadow tier as the dock expands.
57
- * HORIZONTAL-ONLY: a vertical rail grows-to-fit + clamps via
58
- * `--dock-max-block-size` (its own overflow story), so the
59
- * `.dock-overflow-wrap` class is not emitted for a vertical
60
- * orientation.
61
- * `"scroll"` — the dock becomes the scroll port. Horizontal docks
62
- * scroll the active layer on the inline axis
63
- * (`.dock-scroll-x`); vertical rails scroll on the
64
- * block axis (`.dock-scroll-y`), keeping the
65
- * `max-block-size` cap. The rounded pill masks the
66
- * scroll edge; the scrollbar is hidden. The axis is
67
- * chosen automatically from `orientation`.
68
- */
69
- overflow?: "grow" | "wrap" | "scroll";
70
- /**
71
- * When set, the dock root establishes an inline-size container query
72
- * subject (`container-type: inline-size; container-name: <value>`) so
73
- * descendants can query the named container via `@container <value>
74
- * (...)` rules. ORTHOGONAL to the `overflow` clip: opting into a
75
- * container subject does NOT silently change the dock's clip shell
76
- * (AT.W7-dock-a — the prior clip-lift was folded out; use
77
- * `overflow="wrap"` to allow multi-line content).
78
- *
79
- * T.B audit §1.3 cornerstone: the cluster's container subject must
80
- * live on the dock primitive, never on a descendant whose intrinsic
81
- * size the dock relies on.
82
- */
83
- containerName?: string;
84
- }
85
- export interface DockVariantProps extends DockCommonProps {
86
- variant?: "dock";
87
- /** Idle-collapse delay in ms (default 2000). DOCK-ONLY — a rail never collapses. */
88
- collapseDelay?: number;
89
- /** Start in the collapsed state (default true). DOCK-ONLY — a rail is always expanded. */
90
- startCollapsed?: boolean;
91
- /**
92
- * In-cap arrangement. `"linear"` (default) lays the active layer out as a
93
- * linear row/column. `"grid"` makes the active layer a self-wrapping tile
94
- * grid (Launchpad/Stage-Manager track symmetry — `auto-fill` columns of
95
- * `--dock-tile-min`). ORTHOGONAL to `overflow` (the OVER-cap strategy):
96
- * `layout` is the IN-cap arrangement.
97
- *
98
- * Hard contract: a `layout="grid"` dock is `alwaysExpanded` (a 2D panel
99
- * does not read as a collapsible pill, and no width morph means no
100
- * per-frame grid reflow). The canonical pairing is
101
- * `shape="card" layout="grid"` (the props stay independent — no
102
- * auto-implication of `shape`). DOCK-ONLY — the grid is a horizontal big-dock
103
- * arrangement, never a rail's.
104
- */
105
- layout?: "linear" | "grid";
106
- }
107
- export interface DockRailProps extends DockCommonProps {
108
- variant: "rail" | "instrument-strip";
109
- }
110
- export type DockProps = DockVariantProps | DockRailProps;
111
- export declare function dockBranch(p: DockProps): p is DockVariantProps;
112
- /** The resolved shell-prop computeds the GlassDock SFC binds. */
113
- export interface DockShellProps {
114
- containerStyle: ComputedRef<Record<string, string> | undefined>;
115
- collapseDelay: ComputedRef<number>;
116
- startCollapsed: ComputedRef<boolean>;
117
- layoutValue: ComputedRef<"linear" | "grid">;
118
- variant: ComputedRef<"dock" | "rail" | "instrument-strip">;
119
- shape: ComputedRef<"pill" | "rounded" | "card">;
120
- orientation: ComputedRef<"horizontal" | "vertical">;
121
- density: ComputedRef<DockDensity>;
122
- scrollClass: ComputedRef<string | null>;
123
- alwaysExpanded: ComputedRef<boolean>;
124
- fitContent: ComputedRef<boolean>;
125
- }
126
- /**
127
- * Derive the dock's resolved shell props off the raw `props`. The defaults the
128
- * prior `withDefaults` object held are applied at each read site via `?? default`
129
- * (every shared default has exactly one resolution point — the one-path precept).
130
- */
131
- export declare function useDockShellProps(props: DockProps): DockShellProps;
@@ -1,23 +0,0 @@
1
- /**
2
- * The ONE dock-morph spring authority — the iOS-26 interruptible-physics tuning the
3
- * dock's single `SpringProgress` orchestrator (`dockMorphContext.ts`) AND the
4
- * `useLayerTransition` engine both read. Co-located here so the `response`/`damping`
5
- * pair is defined ONCE rather than duplicated at the top of each composable (the two
6
- * prior copies were a DRY hazard — a re-tune had to touch both).
7
- */
8
- export declare const DOCK_SPRING: {
9
- readonly response: 0.32;
10
- readonly dampingFraction: 0.7;
11
- };
12
- /**
13
- * The CSS properties whose `transitionend` the dock-morph window watches to know a
14
- * resize-morph has settled (`useDockMorphWindow.ts`). A `transitionend` on any other
15
- * property is ignored.
16
- */
17
- export declare const RESIZE_MORPH_PROPS: Set<string>;
18
- /** `Symbol()` label for the `DockContext` injection key (`dockContext.ts`). */
19
- export declare const DOCK_CONTEXT_LABEL = "glass-ui:dock-context";
20
- /** `Symbol()` label for the `DockLayerGroupContext` injection key (`dockLayerContext.ts`). */
21
- export declare const DOCK_LAYER_GROUP_LABEL = "glass-ui:dock-layer-group";
22
- /** `Symbol()` label for the `DockMorphContext` injection key (`dockMorphContext.ts`). */
23
- export declare const DOCK_MORPH_LABEL = "glass-ui:dock-morph-context";
@@ -1,54 +0,0 @@
1
- export interface VariantPreset {
2
- /** Higher-order harmonics layered over the dominant counter-rotating pair. */
3
- harmonics: number;
4
- /** Peak magnitude of those harmonics relative to the dominant phasor. */
5
- harmonicScale: number;
6
- /** Draw the nested epicycle circles + arms underneath the curve. */
7
- epicycles: boolean;
8
- /** Comet-trail capacity (frames of head history). ~1/3 of the period so the
9
- * comet reads as a substantial arc, not a stub (the fourier-analysis bar). */
10
- trailLength: number;
11
- /** Hue offset (degrees) of the epicycle second hue away from the outline hue. */
12
- epicycleHueShift: number;
13
- /** Forward-clock period for one full curve traversal, in ms. */
14
- durationMs: number;
15
- /** A constant per-variant seed used under `freeze` so a capture is deterministic. */
16
- frozenSeed: string;
17
- /** The parameter `t` of the static best-frame painted under `freeze`. */
18
- frozenT: number;
19
- /** Comet-trail PEAK alpha (the head segment). The reference trail rides ~0.9
20
- * near-opaque — present, not the prior 0.45 hairline whisper. */
21
- peakAlpha: number;
22
- /** Trail stroke weight in CSS px (the reference is a BOLD 3.5px stroke, not
23
- * the prior 1.6 hairline). The single biggest faintness lever. */
24
- trailWidth: number;
25
- /** Head-glow alpha — the STRONGEST layer (head-forward: > peakAlpha). */
26
- headGlowAlpha: number;
27
- /** Head-glow `shadowBlur` bloom radius, in px. */
28
- headGlowBlur: number;
29
- /** The comet HEAD DOT radius in CSS px (the reference's glowing tip — a
30
- * saturated core + white highlight + soft halo). 0 disables it. */
31
- headDotRadius: number;
32
- /** Epicycle scaffolding alphas ÷ peak (hero only; {0,0} disables the scaffold).
33
- * The reference circles/arms are PRESENT (≈0.5/0.75), not the prior 0.18 ghost. */
34
- epicycleRatios: {
35
- circle: number;
36
- arm: number;
37
- };
38
- /** Epicycle circle / arm stroke weights in CSS px (the reference uses a bold
39
- * ≈2.5/2 chain, the joints carry filled dots). */
40
- epicycleWidths: {
41
- circle: number;
42
- arm: number;
43
- };
44
- /** Paint the epicycle chain as a rainbow across the spectrum (the
45
- * fourier-analysis signature) vs one analogous second hue. Hero only. */
46
- epicycleRainbow: boolean;
47
- /** Trail persistence exponent — SOFT (1..2), never the quadratic that kills the body. */
48
- trailFadeExp: number;
49
- /** Min trail alpha ÷ peak — the body survives, never decays to 0. The
50
- * reference body reads near-uniform; the floor sits HIGH (≈0.35) so the
51
- * comet body has real presence on cream too (the light-mode floor fork). */
52
- trailFloor: number;
53
- }
54
- export declare const PRESETS: Record<"hero" | "final", VariantPreset>;
@@ -1,18 +0,0 @@
1
- import { type MetaballUniformLocations } from "./uploadBlobUniforms";
2
- /** The compiled-program handles the renderer closes over + tears down. */
3
- export interface MetaballProgram {
4
- prog: WebGLProgram;
5
- vs: WebGLShader;
6
- fs: WebGLShader;
7
- vao: WebGLVertexArrayObject;
8
- buf: WebGLBuffer;
9
- locs: MetaballUniformLocations;
10
- }
11
- /**
12
- * Compile the metaball shader, build the full-quad VAO, and resolve the uniform
13
- * location cache on a fresh context. Leaves `BLEND` enabled with the
14
- * premultiplied-alpha `(ONE, ONE_MINUS_SRC_ALPHA)` blend func (the source's
15
- * setup), `prog` in use, and the VAO bound — the caller's `resize`/`drawFrame`
16
- * re-bind as needed.
17
- */
18
- export declare function buildMetaballProgram(gl: WebGL2RenderingContext): MetaballProgram;
@@ -1,41 +0,0 @@
1
- import type { BlobConfig, MoodParams } from "../types";
2
- import type { BlobPointer } from "./useBlobPointer";
3
- import type { BlobSatelliteSystem } from "./useBlobSatellites";
4
- import { MAX_SATS, TRAIL_N, MAX_BLOB_STOPS, POS_SCALE, UNIFORM_NAMES } from "../constants";
5
- import type { UniformName } from "../constants";
6
- export { MAX_SATS, TRAIL_N, MAX_BLOB_STOPS, POS_SCALE, UNIFORM_NAMES };
7
- export type { UniformName };
8
- /** The cached uniform-location set the GL setup builds once per context. */
9
- export interface MetaballUniformLocations {
10
- U: Record<UniformName, WebGLUniformLocation | null>;
11
- satPosLocs: (WebGLUniformLocation | null)[];
12
- satRadLocs: (WebGLUniformLocation | null)[];
13
- satOpLocs: (WebGLUniformLocation | null)[];
14
- trailPosLocs: (WebGLUniformLocation | null)[];
15
- trailRadLocs: (WebGLUniformLocation | null)[];
16
- paletteLocs: (WebGLUniformLocation | null)[];
17
- }
18
- /** The per-frame state the renderer resolves and hands to the upload leaf. */
19
- export interface BlobFrameState {
20
- /** The mood params for this frame (`mood.params.value`). */
21
- params: MoodParams;
22
- /** The resolved base-color gamma-sRGB triple. */
23
- rgb: [number, number, number];
24
- /** The tempo-integrated motion clock (ms). */
25
- simTimeMs: number;
26
- /** The substrate's seconds clock for this frame (the pulse-phase axis). */
27
- timeSec: number;
28
- /** A CONCRETE → gamma-sRGB triple resolver (the renderer's memoised `/color` leaf). */
29
- resolveColor: (css: string) => [number, number, number];
30
- /** The Fresnel rim color (CONCRETE — the SFC un-wrapped any var()-token). */
31
- rimColor: string;
32
- /** The multi-stop palette (CONCRETE strings; EMPTY → falls back to base). */
33
- paletteStops: string[];
34
- }
35
- /**
36
- * Write the resolved frame state into the metaball program's uniforms and issue
37
- * the draw call. Pure: it mutates GL state only (the bound program/VAO + the
38
- * uniform values) and never reads the renderer's closure. The body is the
39
- * byte-identical lift of the prior inline `drawFrame` uniform-upload section.
40
- */
41
- export declare function uploadBlobUniforms(gl: WebGL2RenderingContext, prog: WebGLProgram, vao: WebGLVertexArrayObject, locs: MetaballUniformLocations, canvas: HTMLCanvasElement, config: BlobConfig, pointer: BlobPointer, satellites: BlobSatelliteSystem, frame: BlobFrameState): void;