@mkbabb/glass-ui 4.0.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (606) hide show
  1. package/dist/{CardAction-CW7a0m8M.js → CardAction-DlVP2evz.js} +72 -53
  2. package/dist/{CommandShortcut-DvZNQ_HF.js → CommandShortcut-By-VQcLO.js} +25 -14
  3. package/dist/{ConfiguratorRow-BR4l-ixA.js → ConfiguratorRow-YMXdINHx.js} +14 -14
  4. package/dist/ContextMenuContent-CMWn6huB.js +90 -0
  5. package/dist/{ContextMenuSubContent-xol4sD2q.js → ContextMenuSubContent-DvwWCUc0.js} +16 -16
  6. package/dist/{DataTable-CuKwF7wr.js → DataTable-C4tG3eIJ.js} +4 -4
  7. package/dist/DialogContent-D8U9ZfWS.js +121 -0
  8. package/dist/DialogFooter-DoLy0ewI.js +80 -0
  9. package/dist/DialogScrollContent-BMekN7gq.js +93 -0
  10. package/dist/{FadingScroll-DI6hQhT9.js → FadingScroll-P8B30rAD.js} +1 -1
  11. package/dist/HoverCardContent-DAmGYglo.js +88 -0
  12. package/dist/{HoverPopover-CbqbNwgU.js → HoverPopover-DYpBOzzF.js} +1 -1
  13. package/dist/{IconChip-BTD-nay5.js → IconChip-CQa7XZYc.js} +7 -5
  14. package/dist/{IconTooltip-Bl8gFZ8d.js → IconTooltip-_df8M3xm.js} +1 -1
  15. package/dist/Input-CyU4_hIC.js +57 -0
  16. package/dist/{MetricBadge-RHdBP72w.js → MetricBadge-DQt_dGah.js} +1 -1
  17. package/dist/{Notification-VUwexFUf.js → Notification-BlSPJhtZ.js} +4 -4
  18. package/dist/NumberFieldContent-Z3VxGu_6.js +140 -0
  19. package/dist/PagerDots-CYlqVFd4.js +196 -0
  20. package/dist/PaperBackdrop-DYWgrnh8.js +42 -0
  21. package/dist/{PopoverContent-DL7E6vJP.js → PopoverContent-BuKyHZSz.js} +2 -2
  22. package/dist/{Progress-DctG61iZ.js → Progress-C9SsdwIZ.js} +1 -1
  23. package/dist/{ScrollingText-yOpBzFYq.js → ScrollingText-DY3W1Jfh.js} +2 -2
  24. package/dist/SelectScrollDownButton-3mFHX_R-.js +260 -0
  25. package/dist/{SelectSeparator-DXswVdRz.js → SelectSeparator-CNRGG7Ew.js} +1 -1
  26. package/dist/Separator-Cf9-JFgi.js +44 -0
  27. package/dist/Switch-uf-UKPA2.js +49 -0
  28. package/dist/{Toaster-Bw4xR8xV.js → Toaster-ozrsR4mP.js} +2 -2
  29. package/dist/{ToggleGroupItem-pEM9vIhs.js → ToggleGroupItem-BpzaVzNm.js} +6 -6
  30. package/dist/TooltipProvider-QQVM_80r.js +109 -0
  31. package/dist/animated-digit.js +2 -2
  32. package/dist/api/index.d.ts +16 -32
  33. package/dist/api/types-extra.d.ts +33 -0
  34. package/dist/api.js +2 -2
  35. package/dist/aurora.js +629 -269
  36. package/dist/badge-Bt14yURi.js +72 -0
  37. package/dist/badge.js +1 -1
  38. package/dist/border-progress.js +49 -57
  39. package/dist/button-D1W9PrzI.js +130 -0
  40. package/dist/button.js +1 -1
  41. package/dist/canvas.js +2 -3
  42. package/dist/card.js +1 -1
  43. package/dist/carousel.js +235 -106
  44. package/dist/chipVariants-BJQ0I2kB.js +18 -0
  45. package/dist/collapsible.js +1 -1
  46. package/dist/color-B9jZdhJX.js +116 -0
  47. package/dist/color.js +2 -2
  48. package/dist/command.js +1 -1
  49. package/dist/completion-seal.d.ts +1 -0
  50. package/dist/completion-seal.js +89 -0
  51. package/dist/components/custom/aurora/Aurora.vue.d.ts +10 -5
  52. package/dist/components/custom/aurora/composables/color.d.ts +13 -0
  53. package/dist/components/custom/aurora/composables/frameLoop.d.ts +9 -0
  54. package/dist/components/custom/aurora/composables/glSetup.d.ts +1 -1
  55. package/dist/components/custom/aurora/composables/runtime.d.ts +12 -0
  56. package/dist/components/custom/aurora/composables/uniformBridgeWGPU.d.ts +12 -3
  57. package/dist/components/custom/aurora/composables/wgpuSetup.d.ts +8 -0
  58. package/dist/components/custom/aurora/constants/presets.d.ts +47 -0
  59. package/dist/components/custom/aurora/constants/renderMode.d.ts +16 -8
  60. package/dist/components/custom/aurora/constants/shaders/aurora-mediums.wgsl.d.ts +1 -0
  61. package/dist/components/custom/aurora/constants/shaders/aurora.wgsl.d.ts +1 -1
  62. package/dist/components/custom/aurora/index.d.ts +1 -1
  63. package/dist/components/custom/border-progress/composables/spectrum-walk.d.ts +25 -0
  64. package/dist/components/custom/border-progress/composables/useBorderSpectrum.d.ts +14 -18
  65. package/dist/components/custom/border-progress/index.d.ts +1 -1
  66. package/dist/components/custom/completion-seal/CompletionSeal.vue.d.ts +21 -0
  67. package/dist/components/custom/completion-seal/composables/useCompletionSeal.d.ts +37 -0
  68. package/dist/components/custom/completion-seal/constants.d.ts +46 -0
  69. package/dist/components/custom/completion-seal/index.d.ts +4 -0
  70. package/dist/components/custom/concentric/Concentric.vue.d.ts +15 -12
  71. package/dist/components/custom/concentric/composables/concentricGLSetup.d.ts +12 -0
  72. package/dist/components/custom/concentric/composables/concentricWGPUSetup.d.ts +13 -0
  73. package/dist/components/custom/concentric/composables/levelField.d.ts +50 -0
  74. package/dist/components/custom/concentric/composables/uniformBridgeWGPU.d.ts +7 -3
  75. package/dist/components/custom/concentric/composables/useConcentric.d.ts +3 -3
  76. package/dist/components/custom/concentric/constants.d.ts +69 -24
  77. package/dist/components/custom/concentric/index.d.ts +2 -2
  78. package/dist/components/custom/concentric/shaders/concentric.glsl.d.ts +2 -2
  79. package/dist/components/custom/concentric/shaders/concentric.wgsl.d.ts +1 -1
  80. package/dist/components/custom/configurator/Configurator.vue.d.ts +23 -2
  81. package/dist/components/custom/configurator/index.d.ts +1 -1
  82. package/dist/components/custom/confirm-dialog/ConfirmDialog.vue.d.ts +3 -3
  83. package/dist/components/custom/constellation/Constellation.vue.d.ts +5 -4
  84. package/dist/components/custom/constellation/composables/constellationGLSetup.d.ts +10 -0
  85. package/dist/components/custom/constellation/composables/constellationWGPUSetup.d.ts +19 -0
  86. package/dist/components/custom/constellation/composables/uniformBridgeWGPU.d.ts +66 -0
  87. package/dist/components/custom/constellation/composables/useConstellation.d.ts +3 -10
  88. package/dist/components/custom/constellation/constants.d.ts +33 -0
  89. package/dist/components/custom/constellation/constellationField.d.ts +31 -1
  90. package/dist/components/custom/constellation/constellationInteraction.d.ts +23 -14
  91. package/dist/components/custom/constellation/constellationRender.d.ts +25 -0
  92. package/dist/components/custom/constellation/constellationTypes.d.ts +38 -0
  93. package/dist/components/custom/constellation/constellationWell.d.ts +15 -0
  94. package/dist/components/custom/constellation/index.d.ts +5 -5
  95. package/dist/components/custom/constellation/shaders/constellation-lines.glsl.d.ts +2 -0
  96. package/dist/components/custom/constellation/shaders/constellation-lines.wgsl.d.ts +1 -0
  97. package/dist/components/custom/constellation/shaders/constellation-points.glsl.d.ts +2 -0
  98. package/dist/components/custom/constellation/shaders/constellation-points.wgsl.d.ts +1 -0
  99. package/dist/components/custom/deck/DeckPager.vue.d.ts +29 -0
  100. package/dist/components/custom/deck/composables/useDeck.d.ts +27 -0
  101. package/dist/components/custom/deck/composables/useDeckKeyboard.d.ts +25 -0
  102. package/dist/components/custom/deck/composables/useDeckSpring.d.ts +22 -0
  103. package/dist/components/custom/deck/constants.d.ts +14 -0
  104. package/dist/components/custom/deck/index.d.ts +8 -0
  105. package/dist/components/custom/dock/DockDropdownTrigger.vue.d.ts +4 -3
  106. package/dist/components/custom/dock/DockIconButton.vue.d.ts +22 -0
  107. package/dist/components/custom/dock/DockPopoverTrigger.vue.d.ts +19 -0
  108. package/dist/components/custom/dock/DockStack.vue.d.ts +78 -0
  109. package/dist/components/custom/dock/GlassDock.vue.d.ts +21 -3
  110. package/dist/components/custom/dock/composables/dockMorphContext.d.ts +18 -32
  111. package/dist/components/custom/dock/composables/dockMorphMeasure.d.ts +78 -67
  112. package/dist/components/custom/dock/composables/index.d.ts +3 -0
  113. package/dist/components/custom/dock/composables/railProjection.d.ts +45 -0
  114. package/dist/components/custom/dock/composables/useDockContextSilhouette.d.ts +192 -0
  115. package/dist/components/custom/dock/composables/useDockFission.d.ts +158 -0
  116. package/dist/components/custom/dock/composables/useDockItemDrag.d.ts +18 -0
  117. package/dist/components/custom/dock/composables/useDockSearch.d.ts +85 -0
  118. package/dist/components/custom/dock/composables/useDockShellProps.d.ts +49 -0
  119. package/dist/components/custom/dock/constants.d.ts +32 -17
  120. package/dist/components/custom/dock/index.d.ts +8 -2
  121. package/dist/components/custom/dot-flow-field/DotFlowField.vue.d.ts +15 -11
  122. package/dist/components/custom/dot-flow-field/composables/flowField.d.ts +69 -6
  123. package/dist/components/custom/dot-flow-field/composables/flowGLProgram.d.ts +8 -0
  124. package/dist/components/custom/dot-flow-field/composables/flowSetupGL.d.ts +9 -0
  125. package/dist/components/custom/dot-flow-field/composables/flowSetupGLFlow.d.ts +12 -0
  126. package/dist/components/custom/dot-flow-field/composables/flowSetupWGPU.d.ts +7 -0
  127. package/dist/components/custom/dot-flow-field/composables/uniformBridgeWGPU.d.ts +50 -9
  128. package/dist/components/custom/dot-flow-field/composables/useDotFlowField.d.ts +6 -5
  129. package/dist/components/custom/dot-flow-field/composables/useFlowParticles.d.ts +23 -9
  130. package/dist/components/custom/dot-flow-field/constants.d.ts +92 -20
  131. package/dist/components/custom/dot-flow-field/index.d.ts +2 -2
  132. package/dist/components/custom/dot-flow-field/shaders/flow-field.compute.wgsl.d.ts +1 -1
  133. package/dist/components/custom/dot-flow-field/shaders/flow-field.glsl.d.ts +31 -18
  134. package/dist/components/custom/dot-flow-field/shaders/flow-field.render.wgsl.d.ts +2 -1
  135. package/dist/components/custom/dot-matrix/DotMatrix.vue.d.ts +43 -0
  136. package/dist/components/custom/dot-matrix/composables/dotMatrixField.d.ts +89 -0
  137. package/dist/components/custom/dot-matrix/composables/uniformBridgeWGPU.d.ts +61 -0
  138. package/dist/components/custom/dot-matrix/composables/useDotMatrix.d.ts +34 -0
  139. package/dist/components/custom/dot-matrix/composables/useDotSphere.d.ts +34 -0
  140. package/dist/components/custom/dot-matrix/constants.d.ts +72 -0
  141. package/dist/components/custom/dot-matrix/index.d.ts +5 -0
  142. package/dist/components/custom/dot-matrix/shaders/dot-matrix.glsl.d.ts +4 -0
  143. package/dist/components/custom/dot-matrix/shaders/dot-matrix.wgsl.d.ts +1 -0
  144. package/dist/components/custom/easing/EasingPicker.vue.d.ts +2 -2
  145. package/dist/components/custom/easing/composables/useEasingPicker.d.ts +5 -0
  146. package/dist/components/custom/expandable-container/ExpandableContainer.vue.d.ts +11 -0
  147. package/dist/components/custom/fourier-field/FourierField.vue.d.ts +44 -47
  148. package/dist/components/custom/fourier-field/composables/fourierFieldGLSetup.d.ts +24 -0
  149. package/dist/components/custom/fourier-field/composables/fourierFieldWGPUSetup.d.ts +31 -0
  150. package/dist/components/custom/fourier-field/composables/uniformBridgeWGPU.d.ts +56 -0
  151. package/dist/components/custom/fourier-field/composables/useFourierField.d.ts +61 -37
  152. package/dist/components/custom/fourier-field/constants.d.ts +114 -4
  153. package/dist/components/custom/fourier-field/index.d.ts +23 -18
  154. package/dist/components/custom/fourier-field/shaders/fourier-field.compute.wgsl.d.ts +1 -0
  155. package/dist/components/custom/fourier-field/shaders/fourier-field.glsl.d.ts +4 -0
  156. package/dist/components/custom/fourier-field/shaders/fourier-field.render.wgsl.d.ts +1 -0
  157. package/dist/components/custom/goo-blob/GooBlob.vue.d.ts +9 -1
  158. package/dist/components/custom/goo-blob/composables/easing.d.ts +1 -0
  159. package/dist/components/custom/goo-blob/composables/useBlobSatellites.d.ts +1 -0
  160. package/dist/components/custom/goo-blob/constants.d.ts +26 -1
  161. package/dist/components/custom/goo-blob/index.d.ts +1 -1
  162. package/dist/components/custom/goo-blob/shaders/metaball-noise.wgsl.d.ts +1 -0
  163. package/dist/components/custom/goo-blob/shaders/metaball-palette.wgsl.d.ts +1 -0
  164. package/dist/components/custom/goo-blob/shaders/metaball-uniforms.glsl.d.ts +1 -1
  165. package/dist/components/custom/goo-blob/shaders/metaball.wgsl.d.ts +1 -1
  166. package/dist/components/custom/goo-blob/types.d.ts +86 -1
  167. package/dist/components/custom/goo-dot-matrix/GooDotMatrix.vue.d.ts +49 -0
  168. package/dist/components/custom/goo-dot-matrix/composables/gooDotLattice.d.ts +24 -0
  169. package/dist/components/custom/goo-dot-matrix/composables/gooDotSetup.d.ts +79 -0
  170. package/dist/components/custom/goo-dot-matrix/composables/uniformBridgeWGPU.d.ts +45 -0
  171. package/dist/components/custom/goo-dot-matrix/composables/useGooDotMatrix.d.ts +31 -0
  172. package/dist/components/custom/goo-dot-matrix/constants.d.ts +115 -0
  173. package/dist/components/custom/goo-dot-matrix/index.d.ts +5 -0
  174. package/dist/components/custom/goo-dot-matrix/shaders/goo-dot.frag.d.ts +13 -0
  175. package/dist/components/custom/goo-dot-matrix/shaders/goo-dot.wgsl.d.ts +4 -0
  176. package/dist/components/custom/goo-filter/GooFilter.vue.d.ts +22 -0
  177. package/dist/components/custom/goo-filter/index.d.ts +1 -0
  178. package/dist/components/custom/handmark/brush.d.ts +17 -17
  179. package/dist/components/custom/handmark/constants.d.ts +28 -8
  180. package/dist/components/custom/handmark/geometry.d.ts +34 -1
  181. package/dist/components/custom/handmark/index.d.ts +1 -1
  182. package/dist/components/custom/icon-chip/types.d.ts +10 -0
  183. package/dist/components/custom/labeled-field/LabeledField.vue.d.ts +21 -2
  184. package/dist/components/custom/metric-stack/MetricRow.vue.d.ts +15 -0
  185. package/dist/components/custom/pager-dots/PagerDots.vue.d.ts +9 -0
  186. package/dist/components/custom/pager-dots/index.d.ts +2 -0
  187. package/dist/components/custom/pager-dots/pagerWindow.d.ts +9 -0
  188. package/dist/components/custom/paper-backdrop/PaperBackdrop.vue.d.ts +18 -0
  189. package/dist/components/custom/paper-grid/PaperGrid.vue.d.ts +42 -0
  190. package/dist/components/custom/paper-grid/composables/paperGrid.d.ts +105 -0
  191. package/dist/components/custom/paper-grid/composables/paperGridGLSetup.d.ts +18 -0
  192. package/dist/components/custom/paper-grid/composables/paperGridWGPUSetup.d.ts +21 -0
  193. package/dist/components/custom/paper-grid/composables/uniformBridgeWGPU.d.ts +16 -0
  194. package/dist/components/custom/paper-grid/composables/usePaperGrid.d.ts +31 -0
  195. package/dist/components/custom/paper-grid/constants.d.ts +95 -0
  196. package/dist/components/custom/paper-grid/index.d.ts +5 -0
  197. package/dist/components/custom/paper-grid/shaders/paper-grid.glsl.d.ts +4 -0
  198. package/dist/components/custom/paper-grid/shaders/paper-grid.wgsl.d.ts +1 -0
  199. package/dist/components/custom/search/FuzzySearch.vue.d.ts +8 -2
  200. package/dist/components/custom/search/SearchBar.vue.d.ts +8 -0
  201. package/dist/components/custom/search/index.d.ts +2 -0
  202. package/dist/components/custom/search/searchVariants.d.ts +19 -0
  203. package/dist/components/custom/selectable-chip/SelectableChip.vue.d.ts +50 -0
  204. package/dist/components/custom/selectable-chip/chipVariants.d.ts +39 -0
  205. package/dist/components/custom/selectable-chip/index.d.ts +2 -0
  206. package/dist/components/custom/selectable-chip/selectableChipVariants.d.ts +15 -0
  207. package/dist/components/custom/split-chars/SplitChars.vue.d.ts +39 -0
  208. package/dist/components/custom/split-chars/index.d.ts +1 -0
  209. package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +8 -6
  210. package/dist/components/custom/tabs/constants.d.ts +28 -2
  211. package/dist/components/custom/timeline/ScrubberTimeline.vue.d.ts +16 -0
  212. package/dist/components/custom/timeline/geometry.d.ts +0 -8
  213. package/dist/components/custom/toggle-chip/index.d.ts +15 -4
  214. package/dist/components/custom/watercolor-dot/WatercolorDot.vue.d.ts +32 -17
  215. package/dist/components/custom/watercolor-dot/useWatercolorBlob.d.ts +10 -5
  216. package/dist/components/ui/_shared/index.d.ts +2 -0
  217. package/dist/components/ui/_shared/useControlSize.d.ts +46 -0
  218. package/dist/components/ui/_shared/useSurfaceAxis.d.ts +17 -3
  219. package/dist/components/ui/badge/Badge.vue.d.ts +14 -0
  220. package/dist/components/ui/badge/index.d.ts +1 -0
  221. package/dist/components/ui/button/Button.vue.d.ts +1 -0
  222. package/dist/components/ui/button/index.d.ts +1 -1
  223. package/dist/components/ui/card/Card.vue.d.ts +46 -1
  224. package/dist/components/ui/card/ScrollCard.vue.d.ts +1 -1
  225. package/dist/components/ui/card/index.d.ts +1 -1
  226. package/dist/components/ui/carousel/CarouselContent.vue.d.ts +2 -4
  227. package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
  228. package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
  229. package/dist/components/ui/command/CommandDialog.vue.d.ts +9 -3
  230. package/dist/components/ui/command/CommandList.vue.d.ts +3 -0
  231. package/dist/components/ui/context-menu/ContextMenuContent.vue.d.ts +5 -1
  232. package/dist/components/ui/dialog/DialogContent.vue.d.ts +9 -0
  233. package/dist/components/ui/drawer/Drawer.vue.d.ts +33 -14
  234. package/dist/components/ui/drawer/constants.d.ts +8 -6
  235. package/dist/components/ui/drawer/index.d.ts +12 -2
  236. package/dist/components/ui/dropdown-menu/DropdownMenuContent.vue.d.ts +4 -0
  237. package/dist/components/ui/hover-card/HoverCardContent.vue.d.ts +3 -0
  238. package/dist/components/ui/input/Input.vue.d.ts +3 -0
  239. package/dist/components/ui/number-field/NumberFieldInput.vue.d.ts +6 -1
  240. package/dist/components/ui/select/SelectContent.vue.d.ts +12 -0
  241. package/dist/components/ui/slider/Slider.vue.d.ts +9 -0
  242. package/dist/components/ui/switch/Switch.vue.d.ts +2 -0
  243. package/dist/components/ui/textarea/Textarea.vue.d.ts +3 -0
  244. package/dist/components/ui/tooltip/TooltipContent.vue.d.ts +3 -0
  245. package/dist/composables/color/index.d.ts +2 -0
  246. package/dist/composables/color/useAccentTone.d.ts +34 -0
  247. package/dist/composables/dom/index.d.ts +1 -0
  248. package/dist/composables/dom/useDragVelocity.d.ts +46 -0
  249. package/dist/composables/glass/useVizChoreography.d.ts +123 -0
  250. package/dist/composables/glass/wave/index.d.ts +4 -0
  251. package/dist/composables/glass/wave/waveField.d.ts +115 -0
  252. package/dist/composables/glass/wave/waveField.glsl.d.ts +1 -0
  253. package/dist/composables/glass/wave/waveField.wgsl.d.ts +1 -0
  254. package/dist/composables/glass/webgl/createCanvasLifecycle.d.ts +105 -2
  255. package/dist/composables/glass/webgl/shaders/flow.wgsl.d.ts +1 -0
  256. package/dist/composables/glass/webgl/useWebGLCanvas.d.ts +40 -2
  257. package/dist/composables/glass/webgpu/index.d.ts +2 -1
  258. package/dist/composables/glass/webgpu/useGpuSubstrate.d.ts +65 -7
  259. package/dist/composables/glass/webgpu/useWebGPUCanvas.d.ts +50 -2
  260. package/dist/composables/glass/webgpu/webgpuDevice.d.ts +42 -0
  261. package/dist/composables/motion/core/index.d.ts +7 -0
  262. package/dist/composables/motion/core/useHaptic.d.ts +48 -0
  263. package/dist/composables/motion/core/writeVelocityWeight.d.ts +31 -0
  264. package/dist/composables/motion/index.d.ts +2 -0
  265. package/dist/composables/motion/scrollReader.d.ts +25 -0
  266. package/dist/composables/motion/springPresets.d.ts +19 -1
  267. package/dist/composables/motion/suite.d.ts +2 -2
  268. package/dist/composables/motion/useBloomUp.d.ts +97 -0
  269. package/dist/composables/motion/useCelebrationBurst.d.ts +50 -0
  270. package/dist/composables/motion/useCharStagger.d.ts +44 -0
  271. package/dist/composables/motion/useDockCtaReceive.d.ts +29 -22
  272. package/dist/composables/motion/useGooMorph.d.ts +72 -0
  273. package/dist/composables/motion/useLiquidFlex.d.ts +18 -0
  274. package/dist/composables/motion/useLiquidMorph.d.ts +108 -0
  275. package/dist/composables/motion/useLiquidPress.d.ts +12 -0
  276. package/dist/composables/motion/useLiquidReveal.d.ts +7 -4
  277. package/dist/composables/motion/useMorphField.d.ts +157 -0
  278. package/dist/composables/motion/useScrollChrome.d.ts +58 -0
  279. package/dist/composables/motion/useScrollPin.d.ts +49 -0
  280. package/dist/composables/motion/useScrollScene.d.ts +67 -0
  281. package/dist/composables/motion/useScrollTrigger.d.ts +67 -0
  282. package/dist/composables/motion/useSpringPress.d.ts +5 -5
  283. package/dist/composables/motion/useStaggerReveal.d.ts +24 -0
  284. package/dist/composables/sidebar/index.d.ts +4 -1
  285. package/dist/composables/sidebar/types.d.ts +68 -3
  286. package/dist/composables/sidebar/useClickDelegate.d.ts +4 -0
  287. package/dist/composables/sidebar/useLazyLoader.d.ts +5 -0
  288. package/dist/composables/sidebar/useScrollTo.d.ts +5 -0
  289. package/dist/composables/virtual/index.d.ts +4 -0
  290. package/dist/composables/virtual/useVirtualSectionWindow.d.ts +72 -0
  291. package/dist/composables/virtual/useWindowedStore.d.ts +43 -0
  292. package/dist/composables/virtual/virtualSectionLayout.d.ts +103 -0
  293. package/dist/concentric.js +552 -309
  294. package/dist/configurator.js +2 -2
  295. package/dist/confirm-dialog.js +62 -47
  296. package/dist/constellation.js +635 -235
  297. package/dist/context-menu.js +2 -2
  298. package/dist/controls.js +2 -2
  299. package/dist/createCanvasLifecycle-CuCrGRfq.js +173 -0
  300. package/dist/dark.js +1 -1
  301. package/dist/data-table.js +1 -1
  302. package/dist/deck.d.ts +1 -0
  303. package/dist/deck.js +105 -0
  304. package/dist/dialog.js +4 -3
  305. package/dist/dock.js +1320 -631
  306. package/dist/dockContext-gFVS2gMg.js +18 -0
  307. package/dist/dom.js +7 -6
  308. package/dist/dot-flow-field.js +1268 -387
  309. package/dist/dot-matrix.d.ts +1 -0
  310. package/dist/dot-matrix.js +774 -0
  311. package/dist/dotMatrixField-CRO0ZFk4.js +48 -0
  312. package/dist/drawer.js +106 -96
  313. package/dist/{dropdown-menu-CofSZuk8.js → dropdown-menu-CCfcCQ68.js} +83 -79
  314. package/dist/dropdown-menu.js +1 -1
  315. package/dist/easing.js +188 -176
  316. package/dist/expandable-container.js +43 -21
  317. package/dist/fading-scroll.js +1 -1
  318. package/dist/flow.glsl-DqEGRpl4.js +4 -0
  319. package/dist/forms.js +64 -62
  320. package/dist/fourier-field.js +1069 -178
  321. package/dist/fourier-math.js +1 -1
  322. package/dist/glass-panel.js +2 -2
  323. package/dist/glass-ui.css +1 -1
  324. package/dist/glass-ui.js +164 -119
  325. package/dist/goo-blob.js +175 -1230
  326. package/dist/goo-dot-matrix.d.ts +1 -0
  327. package/dist/goo-dot-matrix.js +811 -0
  328. package/dist/handmark.js +137 -94
  329. package/dist/header-ribbon.js +1 -1
  330. package/dist/hover-card.js +1 -1
  331. package/dist/hover-popover.js +1 -1
  332. package/dist/icon-chip.js +1 -1
  333. package/dist/icon-tooltip.js +1 -1
  334. package/dist/index.d.ts +5 -0
  335. package/dist/instrument-chassis.js +1 -1
  336. package/dist/keyboard.js +1 -1
  337. package/dist/label.js +1 -1
  338. package/dist/labeled-field.js +70 -60
  339. package/dist/metric-badge.js +1 -1
  340. package/dist/metric-cell.js +1 -1
  341. package/dist/metric-stack.js +12 -3
  342. package/dist/motion-core.js +59 -34
  343. package/dist/motion-curves.js +30 -14
  344. package/dist/motion.js +231 -96
  345. package/dist/notification.js +1 -1
  346. package/dist/number-field.js +1 -1
  347. package/dist/pager-dots.js +2 -91
  348. package/dist/paper-backdrop.js +1 -1
  349. package/dist/paper-grid.d.ts +1 -0
  350. package/dist/paper-grid.js +761 -0
  351. package/dist/paperGrid-CXCSMbZ1.js +191 -0
  352. package/dist/popover.js +1 -1
  353. package/dist/{presets-BW2b-fr1.js → presets-QvYgnFIZ.js} +14 -13
  354. package/dist/{procedural-color.glsl-CIFsJhwI.js → procedural-color.wgsl-C1Y5PkM6.js} +2 -2
  355. package/dist/progress.js +1 -1
  356. package/dist/pulse.js +2 -2
  357. package/dist/reactive.js +2 -2
  358. package/dist/{useCanvas2D-B8w_E3Rr.js → resolveCanvasColor-DsSJk06I.js} +16 -6
  359. package/dist/scrollReader-rc3Ns_NM.js +42 -0
  360. package/dist/scrolling-text.js +1 -1
  361. package/dist/search.js +162 -306
  362. package/dist/select.js +3 -3
  363. package/dist/selectable-chip.d.ts +1 -0
  364. package/dist/selectable-chip.js +48 -0
  365. package/dist/separator.js +1 -1
  366. package/dist/{sheet-tZMg0E0w.js → sheet-DUCIoOe0.js} +4 -4
  367. package/dist/sheet.js +1 -1
  368. package/dist/sidebar.js +216 -114
  369. package/dist/slider-CcICPe3u.js +149 -0
  370. package/dist/slider.js +1 -1
  371. package/dist/sortable-list.js +3 -3
  372. package/dist/spectrum-walk-cBNSx_zm.js +33 -0
  373. package/dist/springPresets-DfoQ6XRY.js +64 -0
  374. package/dist/stacked-icons.js +54 -39
  375. package/dist/styles/animations.css +13 -3
  376. package/dist/styles/cards.css +271 -2
  377. package/dist/styles/completion-seal.css +131 -0
  378. package/dist/styles/components.css +1 -4
  379. package/dist/styles/configurator.css +221 -1
  380. package/dist/styles/critical-partition.mjs +66 -11
  381. package/dist/styles/deferred.css +4 -0
  382. package/dist/styles/dock/adaptive-legibility.css +119 -0
  383. package/dist/styles/dock/cta-seat.css +87 -0
  384. package/dist/styles/dock/density.css +167 -6
  385. package/dist/styles/dock/fission-bridge.css +552 -0
  386. package/dist/styles/dock/layers.css +90 -78
  387. package/dist/styles/dock/morph-bridge.css +67 -18
  388. package/dist/styles/dock/morph.css +57 -118
  389. package/dist/styles/dock/overflow.css +12 -0
  390. package/dist/styles/dock/search.css +68 -0
  391. package/dist/styles/dock/shape.css +250 -0
  392. package/dist/styles/dock/shell.css +24 -8
  393. package/dist/styles/dock/stack-rail.css +352 -0
  394. package/dist/styles/dock-controls/dark-mode-toggle.css +17 -4
  395. package/dist/styles/dock-controls/icon-button.css +46 -0
  396. package/dist/styles/dock-controls/triggers.css +23 -1
  397. package/dist/styles/dock-controls.css +18 -0
  398. package/dist/styles/dock.css +27 -2
  399. package/dist/styles/drawer.css +166 -0
  400. package/dist/styles/glass/accent-tone.css +66 -0
  401. package/dist/styles/glass/control-surfaces.css +167 -0
  402. package/dist/styles/glass/glass-atom.css +244 -0
  403. package/dist/styles/glass/glass-capsule.css +143 -0
  404. package/dist/styles/glass/glass-chip.css +215 -0
  405. package/dist/styles/glass/ladder.css +67 -17
  406. package/dist/styles/glass/liquid-enter.css +252 -0
  407. package/dist/styles/glass/liquid-morph.css +850 -0
  408. package/dist/styles/glass/material.css +70 -1
  409. package/dist/styles/glass/reveal.css +22 -2
  410. package/dist/styles/glass/rim.css +31 -9
  411. package/dist/styles/glass/surfaces.css +81 -150
  412. package/dist/styles/glass.css +21 -0
  413. package/dist/styles/icon-chip.css +45 -0
  414. package/dist/styles/index.css +26 -0
  415. package/dist/styles/jubilance.css +65 -0
  416. package/dist/styles/motion/morph-field.css +229 -0
  417. package/dist/styles/paper.css +230 -14
  418. package/dist/styles/scroll-choreography.css +135 -78
  419. package/dist/styles/scroll-chrome.css +123 -0
  420. package/dist/styles/scroll-driven.css +38 -0
  421. package/dist/styles/segmented-tabs.css +110 -40
  422. package/dist/styles/select.css +151 -0
  423. package/dist/styles/theme/bridges.css +22 -0
  424. package/dist/styles/theme/radius.css +18 -1
  425. package/dist/styles/tokens/color-radius.css +14 -4
  426. package/dist/styles/tokens/dark-arm.css +94 -12
  427. package/dist/styles/tokens/glass-deep.css +33 -4
  428. package/dist/styles/tokens/glass-fx.css +122 -1
  429. package/dist/styles/tokens/glass.css +226 -34
  430. package/dist/styles/tokens/light-dark.css +3 -3
  431. package/dist/styles/tokens/offsets.css +27 -0
  432. package/dist/styles/tokens/property-regs.css +277 -0
  433. package/dist/styles/tokens/scale-paper.css +86 -30
  434. package/dist/styles/tokens/scheme-motion.css +106 -133
  435. package/dist/styles/tokens/scheme-spring.css +239 -0
  436. package/dist/styles/tokens/scroll-tokens.css +15 -15
  437. package/dist/styles/tokens/shadow.css +73 -13
  438. package/dist/styles/tokens/sizing-config.css +110 -0
  439. package/dist/styles/tokens/sizing.css +55 -104
  440. package/dist/styles/tokens.css +14 -2
  441. package/dist/styles/typography/semantic.css +18 -5
  442. package/dist/styles/utilities/a11y-overrides.css +20 -5
  443. package/dist/styles/utilities/base-misc.css +52 -0
  444. package/dist/styles/utilities/btn.css +84 -3
  445. package/dist/styles/utilities/components.css +31 -6
  446. package/dist/styles/utilities/metal.css +26 -0
  447. package/dist/switch.js +1 -1
  448. package/dist/tabs.js +199 -182
  449. package/dist/timeline.js +241 -206
  450. package/dist/toast.js +1 -1
  451. package/dist/toggle-chip.js +14 -41
  452. package/dist/toggle-group.js +1 -1
  453. package/dist/tooltip.js +1 -1
  454. package/dist/typewriter.js +2 -2
  455. package/dist/uniformBridgeWGPU-BCse1SHU.js +1268 -0
  456. package/dist/{useAnimatedNumber-BfUq2bUM.js → useAnimatedNumber-BntskVdQ.js} +1 -1
  457. package/dist/{useConfiguratorState-DNlOh6c8.js → useConfiguratorState-22BcULzF.js} +41 -38
  458. package/dist/useControlSize-DAZ062x7.js +9 -0
  459. package/dist/useDockCtaReceive-DX7RDb6_.js +88 -0
  460. package/dist/{useDragMorph-DgxnsVJz.js → useDragMorph-DGLSewwB.js} +4 -4
  461. package/dist/useDragVelocity-CjcfX3dA.js +57 -0
  462. package/dist/useFuzzySearch-0fTYOhS4.js +177 -0
  463. package/dist/useGooMorph-Cs13NgYL.js +104 -0
  464. package/dist/useGpuSubstrate-Ceet70xq.js +347 -0
  465. package/dist/useHaptic-CPz5BT9I.js +134 -0
  466. package/dist/{useLiquidFlex-mZPMiNXh.js → useLiquidFlex-Cc6PjVJD.js} +8 -3
  467. package/dist/useLiquidPress-CtOQ8Z0_.js +43 -0
  468. package/dist/useMorphField-ogBM7ubT.js +141 -0
  469. package/dist/usePointerVelocityField-BrkqZFhj.js +91 -0
  470. package/dist/useScrollChrome-JuImi1DM.js +258 -0
  471. package/dist/{useSpringMount-q1amq1SJ.js → useSpringMount-DFxtzmkR.js} +1 -1
  472. package/dist/useSpringPress-VM9RgVq3.js +36 -0
  473. package/dist/{useSurfaceAxis-g0NloYEF.js → useSurfaceAxis-Ci7Dnaw2.js} +1 -1
  474. package/dist/{useTouchGate-CBZTD4SD.js → useTouchGate-B1Lf9XqN.js} +1 -1
  475. package/dist/{vendor-CKmzio-i.js → vendor-B2qOlYY3.js} +24 -11
  476. package/dist/virtual.d.ts +1 -0
  477. package/dist/virtual.js +225 -0
  478. package/dist/watercolor-dot.js +107 -74
  479. package/dist/writeVelocityWeight-Bh83xZfs.js +19 -0
  480. package/package.json +140 -9
  481. package/src/styles/animations.css +13 -3
  482. package/src/styles/cards.css +271 -2
  483. package/src/styles/completion-seal.css +131 -0
  484. package/src/styles/configurator.css +221 -1
  485. package/src/styles/critical-partition.mjs +66 -11
  486. package/src/styles/dock/adaptive-legibility.css +119 -0
  487. package/src/styles/dock/cta-seat.css +87 -0
  488. package/src/styles/dock/density.css +167 -6
  489. package/src/styles/dock/fission-bridge.css +552 -0
  490. package/src/styles/dock/layers.css +90 -78
  491. package/src/styles/dock/morph-bridge.css +67 -18
  492. package/src/styles/dock/morph.css +57 -118
  493. package/src/styles/dock/overflow.css +12 -0
  494. package/src/styles/dock/search.css +68 -0
  495. package/src/styles/dock/shape.css +250 -0
  496. package/src/styles/dock/shell.css +24 -8
  497. package/src/styles/dock/stack-rail.css +352 -0
  498. package/src/styles/dock-controls/dark-mode-toggle.css +17 -4
  499. package/src/styles/dock-controls/icon-button.css +46 -0
  500. package/src/styles/dock-controls/triggers.css +23 -1
  501. package/src/styles/dock-controls.css +18 -0
  502. package/src/styles/dock.css +27 -2
  503. package/src/styles/drawer.css +164 -0
  504. package/src/styles/glass/accent-tone.css +66 -0
  505. package/src/styles/glass/control-surfaces.css +167 -0
  506. package/src/styles/glass/glass-atom.css +244 -0
  507. package/src/styles/glass/glass-capsule.css +143 -0
  508. package/src/styles/glass/glass-chip.css +215 -0
  509. package/src/styles/glass/ladder.css +67 -17
  510. package/src/styles/glass/liquid-enter.css +252 -0
  511. package/src/styles/glass/liquid-morph.css +850 -0
  512. package/src/styles/glass/material.css +70 -1
  513. package/src/styles/glass/reveal.css +22 -2
  514. package/src/styles/glass/rim.css +31 -9
  515. package/src/styles/glass/surfaces.css +81 -150
  516. package/src/styles/glass.css +21 -0
  517. package/src/styles/icon-chip.css +45 -0
  518. package/src/styles/index.css +26 -0
  519. package/src/styles/jubilance.css +65 -0
  520. package/src/styles/motion/morph-field.css +229 -0
  521. package/src/styles/paper.css +230 -14
  522. package/src/styles/scroll-choreography.css +135 -78
  523. package/src/styles/scroll-chrome.css +123 -0
  524. package/src/styles/scroll-driven.css +38 -0
  525. package/src/styles/segmented-tabs.css +110 -36
  526. package/src/styles/select.css +151 -0
  527. package/src/styles/theme/bridges.css +22 -0
  528. package/src/styles/theme/radius.css +18 -1
  529. package/src/styles/tokens/color-radius.css +14 -4
  530. package/src/styles/tokens/dark-arm.css +94 -12
  531. package/src/styles/tokens/glass-deep.css +33 -4
  532. package/src/styles/tokens/glass-fx.css +122 -1
  533. package/src/styles/tokens/glass.css +226 -34
  534. package/src/styles/tokens/light-dark.css +3 -3
  535. package/src/styles/tokens/offsets.css +27 -0
  536. package/src/styles/tokens/property-regs.css +277 -0
  537. package/src/styles/tokens/scale-paper.css +86 -30
  538. package/src/styles/tokens/scheme-motion.css +106 -133
  539. package/src/styles/tokens/scheme-spring.css +239 -0
  540. package/src/styles/tokens/scroll-tokens.css +15 -15
  541. package/src/styles/tokens/shadow.css +73 -13
  542. package/src/styles/tokens/sizing-config.css +110 -0
  543. package/src/styles/tokens/sizing.css +55 -104
  544. package/src/styles/tokens.css +14 -2
  545. package/src/styles/typography/semantic.css +18 -5
  546. package/src/styles/utilities/a11y-overrides.css +20 -5
  547. package/src/styles/utilities/base-misc.css +52 -0
  548. package/src/styles/utilities/btn.css +84 -3
  549. package/src/styles/utilities/components.css +31 -6
  550. package/src/styles/utilities/metal.css +26 -0
  551. package/dist/ContextMenuContent-uWnVxDab.js +0 -85
  552. package/dist/DialogContent-DcKK8k9i.js +0 -103
  553. package/dist/DialogFooter-BZNX5aVr.js +0 -165
  554. package/dist/HoverCardContent-b2uaAMRR.js +0 -83
  555. package/dist/Input-h9v5LeXf.js +0 -55
  556. package/dist/NumberFieldContent-Cq7EzX-U.js +0 -138
  557. package/dist/PaperBackdrop-Vf3tlpvd.js +0 -31
  558. package/dist/SelectScrollDownButton-CrA8F0iV.js +0 -252
  559. package/dist/Separator-pKF0oA4M.js +0 -37
  560. package/dist/Switch-CwYNf8bo.js +0 -47
  561. package/dist/TooltipProvider-rzvnXz60.js +0 -104
  562. package/dist/badge-D9XWW4GT.js +0 -53
  563. package/dist/button-DYCUa-tH.js +0 -126
  564. package/dist/color-DweYl7pE.js +0 -86
  565. package/dist/components/custom/concentric/composables/ringField.d.ts +0 -44
  566. package/dist/components/custom/constellation/composables/useConstellationPointer.d.ts +0 -35
  567. package/dist/components/custom/constellation/constellationDraw.d.ts +0 -30
  568. package/dist/components/custom/dock/DockRail.vue.d.ts +0 -89
  569. package/dist/createCanvasLifecycle-CHD5XrDW.js +0 -82
  570. package/dist/dockContext-BNfyPLe9.js +0 -17
  571. package/dist/procedural-color.wgsl-CToRHugY.js +0 -224
  572. package/dist/resolveCanvasColor-CUyHr5Uu.js +0 -11
  573. package/dist/slider-DVb4HXU-.js +0 -142
  574. package/dist/springPresets-CFQGQfdl.js +0 -40
  575. package/dist/styles/dock/rail-extend.css +0 -397
  576. package/dist/useLiquidPress-kfb4KX79.js +0 -39
  577. package/dist/usePointerVelocityField-JbRd5CrM.js +0 -137
  578. package/dist/useRAFLoop-UYa4zoiN.js +0 -109
  579. package/dist/useSpringPress-BsqPr7FJ.js +0 -34
  580. package/src/styles/dock/rail-extend.css +0 -397
  581. /package/dist/{CollapsibleContent-68dEXIAl.js → CollapsibleContent-D7UNsXQr.js} +0 -0
  582. /package/dist/{InstrumentChassis-Bx0F_q5g.js → InstrumentChassis-UUJX0-mW.js} +0 -0
  583. /package/dist/{Label-C2ejNWeC.js → Label-B_HPqi_q.js} +0 -0
  584. /package/dist/{ModalOverlay-D1VrWyoi.js → ModalOverlay-DfAf7o15.js} +0 -0
  585. /package/dist/{SelectGroup-DwwjicPY.js → SelectGroup-Dcczq44n.js} +0 -0
  586. /package/dist/{_plugin-vue_export-helper-C1je1s0u.js → _plugin-vue_export-helper-gLzyemvl.js} +0 -0
  587. /package/dist/{compile-CQEFRTmx.js → compile-INR_tPk_.js} +0 -0
  588. /package/dist/{constants-BPOqYJAm.js → constants-BWj7DkMn.js} +0 -0
  589. /package/dist/{createContext-CpBNTRMI.js → createContext-Cd23P9j0.js} +0 -0
  590. /package/dist/{math-BINYmg5z.js → math-5RcIgCB4.js} +0 -0
  591. /package/dist/{menuItemVariants-D8VNHq22.js → menuItemVariants-DAXquKja.js} +0 -0
  592. /package/dist/{prng-Za0Rmgag.js → prng-B5tIXTtj.js} +0 -0
  593. /package/dist/{useGlobalDark-C28t0VWJ.js → useGlobalDark-B4HO9LXG.js} +0 -0
  594. /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-DO8Vl4gs.js} +0 -0
  595. /package/dist/{useInterval-CvK1mL92.js → useInterval-BVUI-sez.js} +0 -0
  596. /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-BEut54Tk.js} +0 -0
  597. /package/dist/{useResizeObserver-Bpoi7tRE.js → useResizeObserver-DdEn3v2f.js} +0 -0
  598. /package/dist/{useResolveTokenColor-vAylyR0x.js → useResolveTokenColor-ChOnCckA.js} +0 -0
  599. /package/dist/{useScrollProgress-D7bYU2RK.js → useScrollProgress-A0M6qRl7.js} +0 -0
  600. /package/dist/{useSortable-DHjtZSEd.js → useSortable-DQV_UNDw.js} +0 -0
  601. /package/dist/{useTextHighlight-CWEi25hf.js → useTextHighlight-Bma3UlKA.js} +0 -0
  602. /package/dist/{useTimer-BHJOKr35.js → useTimer-BBLGPXR8.js} +0 -0
  603. /package/dist/{useUserInvalidAria-y5namzeE.js → useUserInvalidAria-EmmwWPOl.js} +0 -0
  604. /package/dist/{useViewportReady-anbac3m6.js → useViewportReady-C9pYnn7K.js} +0 -0
  605. /package/dist/{vReveal-Czsb7zQC.js → vReveal-CT1KtwZA.js} +0 -0
  606. /package/dist/{vSpecular-CQFmLNzA.js → vSpecular-EX7loENl.js} +0 -0
@@ -0,0 +1,89 @@
1
+ import { t as e } from "./cn-DJXf4yaB.js";
2
+ import { computed as t, createCommentVNode as n, createElementBlock as r, defineComponent as i, normalizeClass as a, onMounted as o, openBlock as s, readonly as c, ref as l, toDisplayString as u, toRef as d, unref as f, watch as p } from "vue";
3
+ //#region src/components/custom/completion-seal/composables/useCompletionSeal.ts
4
+ function m() {
5
+ return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
6
+ }
7
+ function h(e) {
8
+ if (e != null) return typeof e == "function" ? e() : e.value;
9
+ }
10
+ function g(e = {}) {
11
+ let { play: n, respectReducedMotion: r = !0 } = e, i = l(!1), a = l(!1), s = t(() => r && m());
12
+ function u() {
13
+ if (s.value) {
14
+ i.value = !1, a.value = !0;
15
+ return;
16
+ }
17
+ i.value = !1, typeof requestAnimationFrame == "function" ? requestAnimationFrame(() => {
18
+ i.value = !0, a.value = !0;
19
+ }) : (i.value = !0, a.value = !0);
20
+ }
21
+ return n == null ? o(u) : (o(() => {
22
+ h(n) && u();
23
+ }), p(() => h(n), (e, t) => {
24
+ e && !t && u();
25
+ })), {
26
+ playing: c(i),
27
+ drawn: c(a),
28
+ reduced: c(s),
29
+ draw: u
30
+ };
31
+ }
32
+ var _ = "0 0 64 64", v = {
33
+ check: "M16 33 L28 45 L48 19",
34
+ wordmark: "M14 30 L26 42 L50 16 M14 50 L50 50"
35
+ }, y = {
36
+ cx: 32,
37
+ cy: 32,
38
+ r: 24
39
+ }, b = [
40
+ "data-shape",
41
+ "data-play",
42
+ "data-drawn"
43
+ ], x = ["viewBox"], S = [
44
+ "cx",
45
+ "cy",
46
+ "r"
47
+ ], C = ["d"], w = {
48
+ key: 0,
49
+ class: "sr-only"
50
+ }, T = /* @__PURE__ */ i({
51
+ name: "CompletionSeal",
52
+ __name: "CompletionSeal",
53
+ props: {
54
+ shape: {},
55
+ label: {},
56
+ play: { type: Boolean },
57
+ class: {}
58
+ },
59
+ setup(i) {
60
+ let o = i, c = t(() => o.shape ?? "check"), l = t(() => c.value === "wordmark" ? v.wordmark : v.check), { playing: p, drawn: m } = g({ play: o.play === void 0 ? void 0 : d(o, "play") });
61
+ return (t, i) => (s(), r("div", {
62
+ class: a(["completion-seal", f(e)(o.class)]),
63
+ "data-shape": c.value,
64
+ "data-play": f(p) ? "" : void 0,
65
+ "data-drawn": f(m) ? "" : void 0,
66
+ role: "status",
67
+ "aria-live": "polite"
68
+ }, [(s(), r("svg", {
69
+ class: "completion-seal__svg",
70
+ viewBox: f(_),
71
+ "aria-hidden": "true",
72
+ focusable: "false"
73
+ }, [c.value === "ring" ? (s(), r("circle", {
74
+ key: 0,
75
+ class: "completion-seal__mark",
76
+ cx: f(y).cx,
77
+ cy: f(y).cy,
78
+ r: f(y).r,
79
+ pathLength: "100"
80
+ }, null, 8, S)) : (s(), r("path", {
81
+ key: 1,
82
+ class: "completion-seal__mark",
83
+ d: l.value,
84
+ pathLength: "100"
85
+ }, null, 8, C))], 8, x)), o.label ? (s(), r("span", w, u(o.label), 1)) : n("", !0)], 10, b));
86
+ }
87
+ });
88
+ //#endregion
89
+ export { T as CompletionSeal, g as useCompletionSeal };
@@ -52,11 +52,16 @@ type __VLS_Props = {
52
52
  * - `"css"` — never arm WebGL; the `paletteToCssGradient` placeholder
53
53
  * stays the permanent surface (the warm wash composites, it just
54
54
  * does not animate).
55
- * - `"auto"` (default) — resolve to `"css"` on low-power /
56
- * reduced-motion / save-data devices (`hardwareConcurrency <= 4` OR
57
- * `prefers-reduced-motion: reduce` OR `connection.saveData`), else
58
- * `"webgl"`. Resolved once at setup; SSR / missing-API safe (assumes
59
- * capable → `"webgl"` when the probes are unavailable).
55
+ * - `"auto"` (default) — resolves to `"webgl"` on every device EXCEPT a
56
+ * detected SOFTWARE renderer (SwiftShader / llvmpipe / MS Basic Render),
57
+ * which falls to `"css"` (the page-wedging-software-raster guard, the only
58
+ * surviving `"css"` signal). BC.W-VIZ-AURORA (T1) RETIRED the dead-static
59
+ * `hardwareConcurrency <= 4` / `saveData` / `reduced-motion` falls: a
60
+ * 2026-capable low-core / throttled tab no longer gets a frozen gradient
61
+ * (the "renders SLOW" defect root), and reduced-motion is handled SOLELY by
62
+ * the substrate's live `matchMedia` freeze (one static frame then park,
63
+ * re-arms on un-reduce). Resolved once at setup; SSR / missing-API safe
64
+ * (assumes capable → `"webgl"` when the probes are unavailable).
60
65
  */
61
66
  renderMode?: AuroraRenderMode;
62
67
  /**
@@ -60,6 +60,19 @@ export interface DeriveAuroraOptions {
60
60
  * fold that makes the oil/oil-pastel mediums read as mixed paint. Default 0.
61
61
  */
62
62
  temperatureShift?: number;
63
+ /**
64
+ * BC.W-VIZ-AURORA (A7) — the additive DERIVE-path hue-EXCLUSION axis (the
65
+ * speedtest-AX cross-repo fold). Named OKLCh hue bands (each `[startDeg, endDeg]`,
66
+ * wrap-around supported via `start > end`) that EVERY derived stop's hue must fall
67
+ * OUTSIDE. The mechanism that makes "teal-on-navy is GONE" enforceable in the DERIVE
68
+ * path, not just the static default — a consumer deriving a palette FROM any seed
69
+ * can never re-introduce a purged band (e.g. `avoidHues: [[170, 200]]` excludes the
70
+ * teal arc by construction). The exclusion RE-ROUTES the walked hue to the nearest
71
+ * band EDGE (preserving L/C — no chroma flatten); it is NOT a post-hoc desaturate.
72
+ * Additive + default-unset → byte-identical derive (the `WarpMode`-additive-widen
73
+ * precedent: `proof:aurora-atoms-roundtrip` stays GREEN by construction).
74
+ */
75
+ avoidHues?: readonly (readonly [number, number])[];
63
76
  }
64
77
  /**
65
78
  * Seed ONE color into a harmonious, gamut-safe N-stop aurora palette.
@@ -11,6 +11,7 @@
11
11
  import type { UniformLocations } from "./glSetup";
12
12
  import { type CursorState } from "./cursorModel";
13
13
  import type { AuroraConfig } from "../constants/presets";
14
+ import type { UsePointerVelocityField } from "../../../../composables/motion/usePointerVelocityField";
14
15
  export interface FrameLoopDeps {
15
16
  gl: WebGL2RenderingContext;
16
17
  prog: WebGLProgram;
@@ -20,6 +21,14 @@ export interface FrameLoopDeps {
20
21
  getConfig: () => AuroraConfig;
21
22
  /** Reduced-motion intent — parks the loop after one static frame. */
22
23
  getReducedMotion: () => boolean;
24
+ /**
25
+ * BC.W-VIZ-AURORA (T5) — the shared viz-pointer-physics field (BB.B4). FED
26
+ * `tick(deltaMs)` from THIS frame callback (the one-loop discipline — the field owns
27
+ * NO own rAF); the renderer reads `acceleration` for the iOS-27 gel snap-back. The
28
+ * existing cursorModel velocity/burst stays the byte-faithful baseline; the accel
29
+ * term is the additive fold.
30
+ */
31
+ pointerField: UsePointerVelocityField;
23
32
  }
24
33
  export interface FrameLoop {
25
34
  /** Advance the cursor easing THEN draw — the per-frame step. */
@@ -9,7 +9,7 @@
9
9
  * shader-uniform boundary: a NEW uniform name must be added here, and the cache is
10
10
  * keyed off it, so a fresh uniform always gets a location slot.
11
11
  */
12
- export declare const UNIFORM_NAMES: readonly ["uTime", "uPalette", "uStopCount", "uNucleiCount", "uNucleiPos", "uNucleiRadius", "uNucleiPaletteBias", "uNucleiValueBias", "uNucleiDriftRadius", "uNucleiDriftPhase", "uNucleiElong", "uNucleiAngle", "uSoftmaxBeta", "uValueVariance", "uWarpAmount", "uWarpScale", "uWarpDrift", "uWarpMode", "uNoiseOctaves", "uMedium", "uHuePath", "uFlowPattern", "uFlowFocal", "uFlowAngle", "uFlowCurl", "uCursor", "uCursorStrength", "uCursorRadius", "uCursorVelocity", "uCursorBurst", "uStrokeAmount", "uStrokeScale", "uStrokeAnisotropy", "uStrokeLayers", "uStrokeMode", "uStrokeOrient", "uLightDir", "uLightColor", "uWetEdge", "uGranulation", "uImpasto", "uBrokenColor", "uCanvasGrain", "uNucleiDrift", "uPaletteDrift", "uBreathDepth", "uBreathPeriod", "uSaturation", "uPaperGrain", "uAlpha"];
12
+ export declare const UNIFORM_NAMES: readonly ["uTime", "uPalette", "uStopCount", "uNucleiCount", "uNucleiPos", "uNucleiRadius", "uNucleiPaletteBias", "uNucleiValueBias", "uNucleiDriftRadius", "uNucleiDriftPhase", "uNucleiElong", "uNucleiAngle", "uSoftmaxBeta", "uValueVariance", "uWarpAmount", "uWarpScale", "uWarpDrift", "uWarpMode", "uNoiseOctaves", "uMedium", "uHuePath", "uFlowPattern", "uFlowFocal", "uFlowAngle", "uFlowCurl", "uCursor", "uCursorStrength", "uCursorRadius", "uCursorVelocity", "uCursorBurst", "uStrokeAmount", "uStrokeScale", "uStrokeAnisotropy", "uStrokeLayers", "uStrokeMode", "uStrokeOrient", "uLightDir", "uLightColor", "uWetEdge", "uGranulation", "uImpasto", "uBrokenColor", "uCanvasGrain", "uNucleiDrift", "uPaletteDrift", "uBreathDepth", "uBreathPeriod", "uSaturation", "uPaperGrain", "uAlpha", "uVividness"];
13
13
  export type UniformName = (typeof UNIFORM_NAMES)[number];
14
14
  export type UniformLocations = Record<UniformName, WebGLUniformLocation | null>;
15
15
  export interface GlProgram {
@@ -102,6 +102,18 @@ export interface AuroraRuntimeOptions {
102
102
  export interface AuroraRuntime extends Omit<AuroraInstance, "pause" | "resume"> {
103
103
  pause(reason?: SuspendReason): void;
104
104
  resume(reason?: SuspendReason): void;
105
+ /**
106
+ * BC.W-VIZ-AURORA (T2) — the device-resolved arm PROMISE. On the WebGPU
107
+ * backend `renderAt`/`arm` are NO-OPS until `armAsync()` resolves the async
108
+ * adapter→device→configure→setup prelude (`useGpuSubstrate.armAsync` tries
109
+ * WebGPU then falls to the WebGL2 net). A CAPTURE consumer (`renderAt(t)` +
110
+ * `toDataURL`) MUST `await armAsync()` before the first `renderAt` — the
111
+ * synchronous `arm()` cannot guarantee the WebGPU device is present, so a
112
+ * synchronous `renderAt` right after `createAurora(…,{mode:"capture"})` paints
113
+ * a BLANK frame (the dead-preview defect). Resolves once the backend is armed;
114
+ * the WebGL2 fallback resolves immediately. Idempotent + safe post-dispose.
115
+ */
116
+ armAsync(): Promise<void>;
105
117
  /**
106
118
  * AW.W8.1 — feed a pointer delta into the velocity-reactive flow (a fast flick →
107
119
  * a transient swirl-burst). The PRM early-out lives here: the injection is
@@ -13,7 +13,7 @@
13
13
  * scalars0 : vec4<f32> off 0 (uTime, uSoftmaxBeta, uValueVariance, uWarpAmount)
14
14
  * scalars1 : vec4<f32> off 16 (uWarpScale, uWarpDrift, uSaturation, uPaperGrain)
15
15
  * scalars2 : vec4<f32> off 32 (uAlpha, uNucleiDrift, uPaletteDrift, uBreathDepth)
16
- * scalars3 : vec4<f32> off 48 (uBreathPeriod, uCursorStrength, uCursorRadius, _)
16
+ * scalars3 : vec4<f32> off 48 (uBreathPeriod, uCursorStrength, uCursorRadius, uVividness)
17
17
  * cursor : vec4<f32> off 64 (uCursor.x, uCursor.y, _, _)
18
18
  * ints0 : vec4<i32> off 80 (uStopCount, uNucleiCount, uWarpMode, uNoiseOctaves)
19
19
  * ints1 : vec4<i32> off 96 (uMedium, uHuePath, _, _)
@@ -21,7 +21,16 @@
21
21
  * nuc0 : array<vec4<f32>, 6> off 240 (pos.x, pos.y, radius, paletteBias)
22
22
  * nuc1 : array<vec4<f32>, 6> off 336 (valueBias, driftRadius, driftPhase, elong)
23
23
  * nuc2 : array<vec4<f32>, 6> off 432 (angle, _, _, _)
24
- * total : 528 bytes (16-aligned)
24
+ * scalars4 : vec4<f32> off 528 (uStrokeAmount, uStrokeScale, uStrokeAnisotropy, uCanvasGrain)
25
+ * scalars5 : vec4<f32> off 544 (uWetEdge, uGranulation, uBrokenColor, uKuwaharaQ)
26
+ * kuwahara : vec4<f32> off 560 (uKuwaharaRadius, uKuwaharaSectors, _, _)
27
+ * total : 576 bytes (16-aligned)
28
+ *
29
+ * BC.W-VIZ-AURORA (T4) — the painterly-medium scalar lanes (scalars4/scalars5/kuwahara)
30
+ * are APPENDED after the arrays, so EVERY pre-existing offset is byte-identical and the
31
+ * smooth-default parity capture is byte-equivalent (these lanes pack 0 on a smooth config).
32
+ * The WGSL `Uniforms` struct (`aurora.wgsl.ts`) carries the SAME three trailing lanes —
33
+ * the typed-struct lockstep: a one-sided add reds the parity-ΔE.
25
34
  *
26
35
  * Y-origin: config authoring is CSS-top-origin (0 = top); the bridge flips Y at the
27
36
  * uniform boundary (`flipY`), exactly as the GLSL `uniformBridge` does.
@@ -29,7 +38,7 @@
29
38
  import { type AuroraConfig } from "../constants/presets";
30
39
  import type { CursorState } from "./cursorModel";
31
40
  /** The total uniform-buffer byte size (16-aligned). */
32
- export declare const AURORA_WGPU_UNIFORM_BYTES = 528;
41
+ export declare const AURORA_WGPU_UNIFORM_BYTES = 576;
33
42
  /**
34
43
  * The packed scratch buffer + the dual ArrayBuffer views. A slider drag refills this
35
44
  * in place (no per-frame allocation) — mirroring the GLSL bridge's pre-allocated
@@ -15,11 +15,19 @@
15
15
  import type { WebGPUCanvasFrame } from "../../../../composables/glass/webgpu/useWebGPUCanvas";
16
16
  import { type CursorState } from "./cursorModel";
17
17
  import type { AuroraConfig } from "../constants/presets";
18
+ import type { UsePointerVelocityField } from "../../../../composables/motion/usePointerVelocityField";
18
19
  export interface AuroraWGPUSetupDeps {
19
20
  canvas: HTMLCanvasElement;
20
21
  cursor: CursorState;
21
22
  getConfig: () => AuroraConfig;
22
23
  getReducedMotion: () => boolean;
24
+ /**
25
+ * BC.W-VIZ-AURORA (T5) — the shared viz-pointer-physics field (BB.B4). FED
26
+ * `tick(deltaMs)` from the WGPU frame callback (the SAME field instance the WebGL2
27
+ * loop feeds — one source, no own rAF); the renderer reads `acceleration` for the
28
+ * iOS-27 gel snap-back.
29
+ */
30
+ pointerField: UsePointerVelocityField;
23
31
  }
24
32
  /**
25
33
  * Build the aurora `setupWGPU(device, context, format)` callback. Closes over the
@@ -115,6 +115,16 @@ export interface AuroraConfig {
115
115
  impasto: number;
116
116
  brokenColor: number;
117
117
  canvasGrain: number;
118
+ /**
119
+ * BC.W-VIZ-AURORA (T4) — the anisotropic-Kuwahara painterly-finish knobs (the
120
+ * `medium:"kuwahara"` register; the WGSL primary's keystone). Optional; omitted =
121
+ * the recipe defaults (radius 0.010 procedural-patch units, q 4.0 the SOFT
122
+ * variance-weight exponent). Sectors are fixed at 8 (the soft-blend overlap floor —
123
+ * not an authoring axis). These ride the appended WGSL `kuwahara`/`scalars5` struct
124
+ * lanes; a smooth/non-kuwahara config leaves them at the default (a no-op).
125
+ */
126
+ kuwaharaRadius?: number;
127
+ kuwaharaQ?: number;
118
128
  /**
119
129
  * AW.W4.2 — the impasto relight direction (the movable directional source the
120
130
  * accumulated paint-height field catches). Optional; omitted = upper-left
@@ -139,6 +149,20 @@ export interface AuroraConfig {
139
149
  saturation: number;
140
150
  paperGrain: number;
141
151
  alpha: number;
152
+ /**
153
+ * BD.W-AUR-VIVIDNESS — the §3 chroma FLOOR (the warm-field vividness contract).
154
+ * Optional; omitted = `DEFAULT_VIVIDNESS` (1 — high, the library's vivid identity).
155
+ * A shader-resident OKLab chroma-floor lifts any pale zone toward `VIVID_TARGET`
156
+ * (mode-scaled in the shader) so the field never resolves toward gray BEHIND glass
157
+ * — the literal fix for the "missing colorful field → gray glass" defect. The lift
158
+ * is HUE-PRESERVING (scales chroma along the zone's existing OKLab direction); below
159
+ * `VIVID_EPS` the hue is precision noise, so the floor synthesizes along the WARM
160
+ * anchor (`VIVID_WARM_ANCHOR`) — NEVER teal/navy, the warm-floor guarantee. A
161
+ * deliberately-pale hero surface opts OUT with `vividness: 0` (the new lanes write 0,
162
+ * so a `vividness:0` config is byte-identical to the pre-floor render — the gated
163
+ * identity move). Range 0..1.
164
+ */
165
+ vividness?: number;
142
166
  /**
143
167
  * AW.W6/W8 — the pointer/scroll interactivity opt-in (default OFF — the wispy-sky
144
168
  * default stays static). W6 declares the SHAPE; W8 wires the cursor-as-light /
@@ -166,6 +190,14 @@ export interface AuroraInstance extends AuroraCursorApi {
166
190
  * 24). A no-op once armed or once `dispose()` has run.
167
191
  */
168
192
  arm(): void;
193
+ /**
194
+ * BC.W-VIZ-AURORA (T2) — the device-resolved arm PROMISE. On the WebGPU
195
+ * backend `renderAt`/`arm` are no-ops until this resolves the async
196
+ * adapter→device→configure→setup prelude. A CAPTURE consumer (thumbnail bake)
197
+ * MUST `await armAsync()` before the first `renderAt` or the frame is BLANK
198
+ * (the dead-preview defect). The WebGL2 fallback resolves immediately.
199
+ */
200
+ armAsync(): Promise<void>;
169
201
  update(cfg: AuroraConfig): void;
170
202
  /** Render a single deterministic frame at time `t` (seconds). Used for thumbnail bakes. */
171
203
  renderAt(timeSec: number): void;
@@ -176,6 +208,21 @@ export interface AuroraInstance extends AuroraCursorApi {
176
208
  }
177
209
  export declare const MAX_NUCLEI = 6;
178
210
  export declare const MAX_STOPS = 8;
211
+ /**
212
+ * The default `vividness` for a bare `<Aurora>` — HIGH (the library's vivid identity).
213
+ * This INVERTS the pre-floor status quo: vivid is the default, pale is the explicit
214
+ * `vividness: 0` opt-out. The literal §3 fix — a warm glass plate over the default field
215
+ * now reads transmissive-not-gray because the field carries chroma.
216
+ */
217
+ export declare const DEFAULT_VIVIDNESS = 1;
218
+ /**
219
+ * The per-fragment OKLab chroma the floor lifts a pale zone TOWARD at `vividness:1`
220
+ * (the shader scales this by a mode factor — a dim/dark field needs more chroma to read
221
+ * vivid through glass). Tuned so the lifted DEFAULT field clears the §3 transmissive
222
+ * floor (mean OKLab chroma ≥ 0.045) with headroom; a vivid zone above this is untouched.
223
+ * Mirrored as `VIVID_TARGET` in the GLSL + WGSL twins.
224
+ */
225
+ export declare const VIVID_TARGET = 0.115;
179
226
  /**
180
227
  * A neutral starting point for consumers that build their own config from scratch.
181
228
  * Not a themed preset — the demo's 11 authored presets override every field.
@@ -59,12 +59,22 @@ export interface ResolveRenderModeOptions {
59
59
  * would arm WebGL. The single ESCAPE is `options.forceWebGLUnderSoftwareRaster`
60
60
  * (default `false` — the guard is the safe default).
61
61
  *
62
- * `"auto"` then resolves to `"css"` when ANY low-power signal is present:
63
- * - a SOFTWARE WebGL renderer (already handled by the universal guard above),
64
- * - `navigator.hardwareConcurrency <= 4` (few logical cores),
65
- * - `prefers-reduced-motion: reduce`,
66
- * - `navigator.connection.saveData === true` (Data Saver on).
67
- * Otherwise `"webgl"`.
62
+ * BC.W-VIZ-AURORA (T1) — the DEAD-STATIC `"auto"` fall is RETIRED. The
63
+ * `lowConcurrency` (`hardwareConcurrency <= 4`) and `saveData` heuristics are
64
+ * GONE: they predate the offscreen-park + the `AV_AURORA_DPR_MAX` sub-2× cap +
65
+ * the demand-gate that make a full-viewport aurora cheap, and `<= 4` is
66
+ * false-positive-prone in 2026 (a capable base-M-series laptop / a throttled VM
67
+ * tab reports 4 logical cores → it got a FROZEN static gradient that reads as
68
+ * "the aurora is broken", USER-DEFECTS §E "renders SLOW"). So `"auto"` arms the
69
+ * GPU on every Chrome-113/Safari-26/Firefox-141 device.
70
+ *
71
+ * Reduced-motion is handled SOLELY by the substrate's live `matchMedia` freeze
72
+ * (`createCanvasLifecycle` paints ONE static frame then parks, and re-arms on
73
+ * un-reduce) — NOT a render-mode fall (the old `"css"` fall never armed WebGL,
74
+ * so an un-reduce mid-session could never wake it; the substrate freeze does).
75
+ * The ONLY `"css"` signal that remains is the genuine software-raster GUARD
76
+ * (the universal first leg above) — and even that is subsumed by
77
+ * `BC.W-WEBGPU-EVERYWHERE`'s try-WebGPU-then-rebuild-WebGL2 picker.
68
78
  *
69
79
  * THE CAPABLE PATH IS BYTE-UNTOUCHED: `isSoftwareWebGLRenderer()` returns `false`
70
80
  * on a real GPU (or a null probe — never a false downgrade), so a forced
@@ -73,8 +83,6 @@ export interface ResolveRenderModeOptions {
73
83
  * SSR / missing-API safe: if `navigator` / `window` / the probes are
74
84
  * unavailable we ASSUME a capable device and resolve `"webgl"` (the warm wash
75
85
  * still composites either way — the only question is whether it animates).
76
- * `navigator.connection` is non-standard, so it is feature-probed via an
77
- * optional-chained cast rather than a typed accessor.
78
86
  *
79
87
  * Called ONCE at component setup — the device tier is a mount-time decision,
80
88
  * not a reactive one (a connection-type flip mid-session does not re-resolve;
@@ -0,0 +1 @@
1
+ export declare const AURORA_MEDIUMS_WGSL = "\n// \u2500\u2500 Painterly luma + medium scalar accessors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst W_LUMA: vec3<f32> = vec3<f32>(0.2126, 0.7152, 0.0722);\n\nfn mStrokeAmount() -> f32 { return u.scalars4.x; }\nfn mStrokeScale() -> f32 { return u.scalars4.y; }\nfn mStrokeAnisotropy() -> f32 { return u.scalars4.z; }\nfn mCanvasGrain() -> f32 { return u.scalars4.w; }\nfn mWetEdge() -> f32 { return u.scalars5.x; }\nfn mGranulation() -> f32 { return u.scalars5.y; }\nfn mBrokenColor() -> f32 { return u.scalars5.z; }\nfn mKuwaharaQ() -> f32 { return u.scalars5.w; }\nfn mKuwaharaRadius() -> f32 { return u.kuwahara.x; }\n\n// \u2500\u2500 Base color re-sample (the edge-mask operator the mediums Sobel/sector-sample) \u2500\u2500\n// The WGSL twin of mediums.glsl.ts sampleBase: warp -> nuclei field -> palette -> value.\nfn sampleBase(p: vec2<f32>, t: f32) -> vec3<f32> {\n let pw = domainWarp(p, t);\n let nf = nucleiField(pw, t);\n var c = samplePalette(nf.paletteId);\n c = c * (1.0 + u.scalars0.z * nf.valueMod);\n return c;\n}\n\n// \u2500\u2500 Broken color (hue + chroma jitter at constant OKLCh L) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn brokenColorJitter(c: vec3<f32>, hueSeed: f32, valueSeed: f32, strength: f32) -> vec3<f32> {\n let amt = clamp(mBrokenColor() * strength, 0.0, 1.0);\n if (amt <= 0.001) { return c; }\n var lch = oklabToOklch(linOklab(c));\n lch.z = lch.z + (hueSeed - 0.5) * (32.0 * PI / 180.0) * amt;\n lch.y = max(lch.y * (1.0 + (valueSeed - 0.5) * 0.28 * amt), 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 Structure-tensor / edge-tangent-flow (AW.W4.1; the WGSL twin) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Returns vec3(tangent.x, tangent.y, A) \u2014 the minor-eigenvector edge-tangent + coherence.\nfn structureTensorField(p: vec2<f32>, t: f32, fallbackDir: vec2<f32>) -> vec3<f32> {\n let e = 0.0035;\n let l00 = dot(sampleBase(p + vec2<f32>(-e, -e), t), W_LUMA);\n let l10 = dot(sampleBase(p + vec2<f32>(0.0, -e), t), W_LUMA);\n let l20 = dot(sampleBase(p + vec2<f32>( e, -e), t), W_LUMA);\n let l01 = dot(sampleBase(p + vec2<f32>(-e, 0.0), t), W_LUMA);\n let l21 = dot(sampleBase(p + vec2<f32>( e, 0.0), t), W_LUMA);\n let l02 = dot(sampleBase(p + vec2<f32>(-e, e), t), W_LUMA);\n let l12 = dot(sampleBase(p + vec2<f32>(0.0, e), t), W_LUMA);\n let l22 = dot(sampleBase(p + vec2<f32>( e, e), t), W_LUMA);\n let Gx = (l20 + 2.0 * l21 + l22) - (l00 + 2.0 * l01 + l02);\n let Gy = (l02 + 2.0 * l12 + l22) - (l00 + 2.0 * l10 + l20);\n let Jxx = Gx * Gx;\n let Jyy = Gy * Gy;\n let Jxy = Gx * Gy;\n let tr = Jxx + Jyy;\n let disc = sqrt(max((Jxx - Jyy) * (Jxx - Jyy) + 4.0 * Jxy * Jxy, 0.0));\n let lambdaMaj = 0.5 * (tr + disc);\n let lambdaMin = 0.5 * (tr - disc);\n var tangent: vec2<f32>;\n if (disc < 1e-7) {\n tangent = fallbackDir;\n } else {\n let theta = 0.5 * atan2(2.0 * Jxy, Jxx - Jyy);\n tangent = vec2<f32>(-sin(theta), cos(theta));\n }\n var A = (lambdaMaj - lambdaMin) / (lambdaMaj + lambdaMin + 1e-6);\n A = clamp(A, 0.0, 1.0);\n if (dot(tangent, fallbackDir) < 0.0) { tangent = -tangent; }\n let blendW = pow(A, 0.28);\n let dir = normalize(mix(fallbackDir, tangent, blendW) + vec2<f32>(1e-6, 1e-6));\n return vec3<f32>(dir, A);\n}\n\n// \u2500\u2500 Flow field (the WGSL twin \u2014 the simple flow seed the medium fallback dirs use) \u2500\u2500\nfn flowField(p: vec2<f32>, t: f32) -> vec2<f32> {\n // Curl-noise-driven swirl (the medium-default dir; the full radial/swirl/diagonal\n // dispatch rides uniforms the WGSL struct does not carry \u2014 the procedural mediums\n // use this multi/curl seed as the fallback the structure tensor relaxes toward).\n let n = fbm(p * 2.0 + vec2<f32>(t * 0.02, t * 0.02));\n let a = n * 6.2831853;\n var dir = vec2<f32>(cos(a), sin(a));\n // Cursor swirl bias (matches the GLSL flow cursor term \u2014 the steady attraction).\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n if (cursorStrength > 0.001) {\n let toCur = cursor - p;\n let d = length(toCur);\n let r = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (r * r * 0.5));\n let tangent = vec2<f32>(-toCur.y, toCur.x) / max(d, 1e-4);\n let a0 = atan2(dir.y, dir.x);\n let a1 = atan2(tangent.y, tangent.x);\n var da = a1 - a0;\n da = atan2(sin(da), cos(da));\n let aa = a0 + da * w * cursorStrength;\n dir = vec2<f32>(cos(aa), sin(aa));\n }\n return dir;\n}\n\n// \u2500\u2500 Watercolor \u2014 wet-edge cauliflowers + granulation + wash banding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumWatercolor(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let eps = 0.004;\n let cx1 = sampleBase(p + vec2<f32>(eps, 0.0), t);\n let cx2 = sampleBase(p - vec2<f32>(eps, 0.0), t);\n let cy1 = sampleBase(p + vec2<f32>(0.0, eps), t);\n let cy2 = sampleBase(p - vec2<f32>(0.0, eps), t);\n let gx = dot(cx1 - cx2, W_LUMA);\n let gy = dot(cy1 - cy2, W_LUMA);\n let edge = sqrt(gx * gx + gy * gy) / (2.0 * eps);\n let mask = smoothstep(0.0, 2.5, edge);\n col = col * mix(1.0, 0.78, mask * mWetEdge());\n\n let paper = 0.5 * vnoise(p * 160.0) + 0.5 * vnoise(p * 360.0);\n let pigLoad = 1.0 - dot(col, W_LUMA);\n col = col * (1.0 - mGranulation() * pigLoad * (paper - 0.5));\n\n let band = fbm(vec2<f32>(p.x * 1.5, p.y * 0.4));\n col = col * (1.0 + 0.04 * (band - 0.5));\n return col;\n}\n\n// \u2500\u2500 Pastel \u2014 anisotropic stroke noise along the flow + tooth grain \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumPastel(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let flow = flowField(p, t);\n let perp = vec2<f32>(-flow.y, flow.x);\n let strokeScale = mStrokeScale();\n let along = dot(p, flow) * strokeScale;\n var across = dot(p, perp) * strokeScale;\n across = across + 0.03 * (vnoise(p * 260.0) - 0.5);\n\n let aniso = mix(1.0, 0.18, mStrokeAnisotropy());\n let stroke = fbm(vec2<f32>(along * aniso, across));\n col = col * mix(1.0, 0.82 + 0.32 * stroke, mStrokeAmount());\n\n let tooth = vnoise(p * 800.0);\n col = col * (1.0 - 0.08 * mStrokeAmount() * (tooth - 0.5));\n return col;\n}\n\n// \u2500\u2500 Crayon \u2014 DRY wax pigment on paper tooth (the tooth-multiply + scumble) \u2500\u2500\nfn mediumCrayon(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let flow = structureTensorField(p, t, flowField(p, t)).xy;\n let ang = atan2(flow.y, flow.x);\n let ca = cos(-ang);\n let sa = sin(-ang);\n let pr = vec2<f32>(p.x * ca - p.y * sa, p.x * sa + p.y * ca);\n\n let aniso = mix(0.45, 0.95, mStrokeAnisotropy());\n let scale = max(mStrokeScale() * 1.6, 180.0);\n\n let t1 = vnoise(vec2<f32>(pr.x * scale * aniso, pr.y * scale));\n let t2 = vnoise(vec2<f32>(pr.x * scale * aniso * 0.4, pr.y * scale * 0.4) + vec2<f32>(11.0, 11.0));\n let t3 = vnoise(vec2<f32>(pr.x * scale * aniso * 2.1, pr.y * scale * 2.1) + vec2<f32>(23.0, 23.0));\n let tooth = 0.55 * t1 + 0.30 * t2 + 0.15 * t3;\n\n let pressure = clamp(mStrokeAmount(), 0.0, 1.0);\n let bite = mix(0.18, 0.46, pressure);\n var result = col0 * (1.0 - bite * (0.5 - tooth));\n\n let scumbleMask = smoothstep(0.42, 0.78, vnoise(vec2<f32>(pr.x * scale * 0.55, pr.y * scale * 0.22) + vec2<f32>(7.0, 7.0)));\n let scumbleCoverage = scumbleMask * pressure * 0.7;\n let paper = col0 * mix(0.80, 0.94, pressure);\n result = mix(paper, result, scumbleCoverage);\n\n let pigmentCell = floor(pr * max(scale * 0.18, 32.0));\n let pigmentMask = smoothstep(0.28, 0.82, vnoise(pr * scale * 0.21 + vec2<f32>(19.0, 19.0)));\n result = brokenColorJitter(\n result,\n hash21(pigmentCell + vec2<f32>(17.0, 17.0)),\n hash21(pigmentCell * 2.1 + vec2<f32>(31.0, 31.0)),\n 0.45 + 0.55 * pigmentMask\n );\n\n result = saturate3(result, 1.08);\n return result;\n}\n\n// \u2500\u2500 Kuwahara \u2014 the SOFT anisotropic generalized Kuwahara painterly finish \u2500\u2500\u2500\u2500\n// THE KEYSTONE (Kyprianidis 2010). Aurora is a PROCEDURAL field (no input texture) so the\n// operator runs over sampleBase directly: an elliptical kernel oriented along the structure\n// tensor (elongated along the edge-tangent, narrowed across by the anisotropy), 8 OVERLAPPING\n// sectors via SMOOTH gaussian-angular weights, blended by 1/(1+var^q) (the SOFT criterion \u2192\n// no 8-spoke pinwheel by construction). 4 rings \u00D7 8 angular taps = 32 procedural samples.\nfn mediumKuwahara(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let stf = structureTensorField(p, t, flowField(p, t));\n let tangent = stf.xy;\n let A = stf.z;\n // The studio knob drives the patch radius; clamp into the procedural patch band.\n let radius = clamp(mKuwaharaRadius() + mStrokeScale() * 0.00018, 0.006, 0.024);\n let aniso = mix(1.0, 0.34, clamp(A, 0.0, 1.0));\n let ax = tangent;\n let ay = vec2<f32>(-tangent.y, tangent.x);\n\n // Per-sector weighted sums (8 sectors). WGSL has no runtime-indexed local arrays of\n // vectors as cleanly as GLSL, so unroll the sector accumulators explicitly.\n var mSum: array<vec3<f32>, 8>;\n var sSum: array<vec3<f32>, 8>;\n var wSum: array<f32, 8>;\n for (var i = 0; i < 8; i = i + 1) {\n mSum[i] = vec3<f32>(0.0);\n sSum[i] = vec3<f32>(0.0);\n wSum[i] = 0.0;\n }\n\n let RINGS = 4;\n let TAPS = 8;\n for (var r = 1; r <= RINGS; r = r + 1) {\n let rr = f32(r) / f32(RINGS);\n let radial = 1.0 - 0.6 * rr;\n for (var a = 0; a < TAPS; a = a + 1) {\n let ang = 6.2831853 * f32(a) / f32(TAPS);\n let dirE = ax * cos(ang) + ay * (sin(ang) * aniso);\n let off = dirE * (radius * rr);\n let c = sampleBase(p + off, t);\n for (var k = 0; k < 8; k = k + 1) {\n let sectorAng = 6.2831853 * f32(k) / 8.0;\n var d = ang - sectorAng;\n d = atan2(sin(d), cos(d));\n let sw = exp(-d * d * 2.2) * radial;\n mSum[k] = mSum[k] + c * sw;\n sSum[k] = sSum[k] + c * c * sw;\n wSum[k] = wSum[k] + sw;\n }\n }\n }\n\n let q = max(mKuwaharaQ(), 1.0);\n var accum = vec3<f32>(0.0);\n var accumW = 0.0;\n for (var k = 0; k < 8; k = k + 1) {\n let wk = max(wSum[k], 1e-4);\n let mean = mSum[k] / wk;\n let var3 = max(sSum[k] / wk - mean * mean, vec3<f32>(0.0));\n let variance = dot(var3, W_LUMA);\n let sectorW = 1.0 / (1.0 + pow(variance * 320.0, q));\n accum = accum + mean * sectorW;\n accumW = accumW + sectorW;\n }\n var result = accum / max(accumW, 1e-4);\n\n // Anchor in near-flat zones so the smoothing only bites at edges.\n let center = sampleBase(p, t);\n result = mix(center, result, clamp(0.35 + 0.65 * A, 0.0, 1.0));\n\n // Faint canvas tooth + pigment-saturation so the flattened patches read as oil paint.\n let tooth = vnoise(p * 300.0) - 0.5;\n result = result * (1.0 + tooth * 0.06 * mCanvasGrain());\n result = saturate3(result, 1.04);\n\n return mix(col0, result, clamp(mStrokeAmount(), 0.0, 1.0));\n}\n\n// \u2500\u2500 Medium dispatch (the WGSL twin of the GLSL main() if-ladder) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// uMedium: 0 smooth \u00B7 1 pastel \u00B7 2 watercolor \u00B7 3 oil \u00B7 4 crayon \u00B7 5 vangogh \u00B7\n// 6 oil-pastel \u00B7 7 kuwahara. The cheap peer mediums (pastel/watercolor/crayon) +\n// kuwahara port their own bodies; the oil/vangogh/oil-pastel STROKE cascade renders\n// the anisotropic-Kuwahara PAINTERLY finish here (a real oil-paint read, never the\n// smooth core \u2014 the \"NO FALLBACKS on Safari\" mandate; the full per-dab Starry-Night\n// stroke WGSL is the booked W-AURORA-WGPU-MEDIUMS-STROKES tail).\nfn applyMedium(col: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let medium = u.ints1.x;\n if (medium == 1) { return mediumPastel(col, p, t); }\n if (medium == 2) { return mediumWatercolor(col, p, t); }\n if (medium == 4) { return mediumCrayon(col, p, t); }\n // oil(3) / vangogh(5) / oil-pastel(6) / kuwahara(7) all render the painterly\n // anisotropic-Kuwahara finish on the WGSL primary (the WebGL2 fallback carries the\n // full per-dab stroke cascade for oil/vangogh/oil-pastel).\n if (medium == 3 || medium == 5 || medium == 6 || medium == 7) {\n return mediumKuwahara(col, p, t);\n }\n return col;\n}\n";
@@ -1 +1 @@
1
- export declare const AURORA_WGSL = "\nconst MAX_NUCLEI: i32 = 6;\nconst MAX_STOPS: i32 = 8;\nconst PI: f32 = 3.141592653589793;\n\n// \u2500\u2500 Uniforms (the typed-struct source-of-truth \u2014 see aurora.wgsl.uniforms.ts) \u2500\u2500\n// Scalars are packed into vec4 lanes to keep the std140/WGSL 16-byte struct alignment\n// trivial. nuc0[i] = (pos.x, pos.y, radius, paletteBias); nuc1[i] = (valueBias,\n// driftRadius, driftPhase, elong); nuc2[i] = (angle, _, _, _). palette[i].rgb is the\n// CPU-baked linear-sRGB stop.\nstruct Uniforms {\n // scalars0: (uTime, uSoftmaxBeta, uValueVariance, uWarpAmount)\n scalars0: vec4<f32>,\n // scalars1: (uWarpScale, uWarpDrift, uSaturation, uPaperGrain)\n scalars1: vec4<f32>,\n // scalars2: (uAlpha, uNucleiDrift, uPaletteDrift, uBreathDepth)\n scalars2: vec4<f32>,\n // scalars3: (uBreathPeriod, uCursorStrength, uCursorRadius, _pad)\n scalars3: vec4<f32>,\n // cursor: (uCursor.x, uCursor.y, _pad, _pad)\n cursor: vec4<f32>,\n // ints: (uStopCount, uNucleiCount, uWarpMode, uNoiseOctaves)\n ints0: vec4<i32>,\n // ints1: (uMedium, uHuePath, _, _)\n ints1: vec4<i32>,\n palette: array<vec4<f32>, 8>,\n nuc0: array<vec4<f32>, 6>,\n nuc1: array<vec4<f32>, 6>,\n nuc2: array<vec4<f32>, 6>,\n};\n\n@group(0) @binding(0) var<uniform> u: Uniforms;\n\n// \u2500\u2500 Authoring-scale \u2192 rad/sec lifts (byte-identical to aurora.frag.ts) \u2500\u2500\nconst K_NUCLEI: f32 = 14.0;\nconst K_PAL: f32 = 24.0;\nconst K_WARP: f32 = 5.0;\n\n// \u2500\u2500 Noise (aurora-local hash21/vnoise/fbm \u2014 legitimately divergent per AV.W2 \u00A73a) \u2500\u2500\nfn hash21(p0: vec2<f32>) -> f32 {\n var p = fract(p0 * vec2<f32>(123.34, 456.21));\n p = p + dot(p, p + 45.32);\n return fract(p.x * p.y);\n}\n\nfn hash22(p0: vec2<f32>) -> vec2<f32> {\n let p = vec2<f32>(dot(p0, vec2<f32>(127.1, 311.7)),\n dot(p0, vec2<f32>(269.5, 183.3)));\n return fract(sin(p) * 43758.5453);\n}\n\nfn vnoise(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n let uu = f * f * (3.0 - 2.0 * f);\n let a = hash21(i);\n let b = hash21(i + vec2<f32>(1.0, 0.0));\n let c = hash21(i + vec2<f32>(0.0, 1.0));\n let d = hash21(i + vec2<f32>(1.0, 1.0));\n return mix(mix(a, b, uu.x), mix(c, d, uu.x), uu.y);\n}\n\nconst FBM_ROT: mat2x2<f32> = mat2x2<f32>(0.8, 0.6, -0.6, 0.8);\n\nfn fbm(p0: vec2<f32>) -> f32 {\n var v = 0.0;\n var a = 0.5;\n var p = p0;\n let octaves = u.ints0.w;\n for (var i = 0; i < 5; i = i + 1) {\n if (i >= octaves) { break; }\n v = v + a * vnoise(p);\n p = FBM_ROT * p * 2.02;\n a = a * 0.5;\n }\n return v;\n}\n\n\nfn srgbToLinearCh(c: f32) -> f32 {\n if (c <= 0.04045) { return c / 12.92; }\n return pow((c + 0.055) / 1.055, 2.4);\n}\nfn srgbToLinear(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfn linearToSrgbCh(c: f32) -> f32 {\n if (c <= 0.0031308) { return c * 12.92; }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nfn linearToSrgb(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS, row-major \u2192 WGSL columns (= the transpose).\nconst LINEAR_SRGB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients, row-major \u2192 WGSL columns.\nconst LMS_TO_OKLAB: mat3x3<f32> = mat3x3<f32>(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF, row-major \u2192 WGSL columns.\nconst OKLAB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB, row-major \u2192 WGSL columns.\nconst LMS_TO_LINEAR_SRGB: mat3x3<f32> = mat3x3<f32>(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\nfn cbrt3(v: vec3<f32>) -> vec3<f32> {\n return sign(v) * pow(abs(v), vec3<f32>(1.0 / 3.0));\n}\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nfn srgbToOklab(c: vec3<f32>) -> vec3<f32> {\n let lin = srgbToLinear(c);\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nfn oklabToLinearSrgb(lab: vec3<f32>) -> vec3<f32> {\n let lms_ = OKLAB_TO_LMS * lab;\n let lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS, folded to [0, 2pi). Mirrors value.js rawOklabToOklch.\nfn oklabToOklch(lab: vec3<f32>) -> vec3<f32> {\n let C = length(lab.yz);\n var H = atan2(lab.z, lab.y);\n if (H < 0.0) { H = H + 2.0 * PI; }\n return vec3<f32>(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nfn oklchToOklab(lch: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// value.js interpolateHue in the NORMALIZED-TURNS domain. methods: 0 shorter,\n// 1 longer, 2 increasing, 3 decreasing.\nfn interpolateHueTurns(h0: f32, h1: f32, t: f32, method: i32) -> f32 {\n let TAU = 2.0 * PI;\n var a = h0 / TAU;\n var b = h1 / TAU;\n let i = b - a;\n if (method == 0) { // shorter\n if (i > 0.5) { a = a + 1.0; } else if (i < -0.5) { b = b + 1.0; }\n } else if (method == 1) { // longer\n if (i > 0.0 && i < 0.5) { a = a + 1.0; } else if (i > -0.5 && i <= 0.0) { b = b + 1.0; }\n } else if (method == 2) { // increasing\n if (i < 0.0) { b = b + 1.0; }\n } else { // decreasing\n if (i > 0.0) { a = a + 1.0; }\n }\n var r = a + t * (b - a);\n r = fract(r); // fract is non-negative in WGSL\n return r * TAU; // back to radians\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLab-rectangular interpolation \u2192 linear sRGB.\nfn mixPaletteOklab(linA: vec3<f32>, linB: vec3<f32>, t: f32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lab = mix(labA, labB, t);\n return oklabToLinearSrgb(lab);\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLCh hue-arc interpolation \u2192 linear sRGB.\nfn mixPaletteOklchArc(linA: vec3<f32>, linB: vec3<f32>, t: f32, method: i32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lchA = oklabToOklch(labA);\n let lchB = oklabToOklch(labB);\n let L = mix(lchA.x, lchB.x, t);\n let C = mix(lchA.y, lchB.y, t);\n let H = interpolateHueTurns(lchA.z, lchB.z, t, method);\n return oklabToLinearSrgb(oklchToOklab(vec3<f32>(L, C, H)));\n}\n\n// The ramp dispatcher (the samplePalette splices it). tRaw is the raw inter-stop\n// parameter [0,1]; the smoothstep ease + the huePath branch live here so the ramp is\n// one source. increasing(2)/decreasing(3) take the OKLCh hue-arc; every other method\n// takes the OKLab-rectangular straight line.\nfn samplePaletteRamp(a: vec3<f32>, b: vec3<f32>, tRaw: f32, huePath: i32) -> vec3<f32> {\n let t = smoothstep(0.0, 1.0, tRaw);\n if (huePath == 2 || huePath == 3) {\n return mixPaletteOklchArc(a, b, t, huePath);\n }\n return mixPaletteOklab(a, b, t);\n}\n\n// Interleaved Gradient Noise (Jimenez) \u2014 display-space 1-LSB dither.\nfn ign(p: vec2<f32>) -> f32 {\n return fract(52.9829189 * fract(dot(p, vec2<f32>(0.06711056, 0.00583715))));\n}\n\n// Cellular / Worley f1.\nfn cellular(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n var m = 1e9;\n for (var y = -1; y <= 1; y = y + 1) {\n for (var x = -1; x <= 1; x = x + 1) {\n let g = vec2<f32>(f32(x), f32(y));\n let o = hash22(i + g);\n let r = g + o - f;\n m = min(m, dot(r, r));\n }\n }\n return sqrt(m);\n}\n\n// \u2500\u2500 Warp (Quilez double warp + the three warp modes + the cursor swirl) \u2500\u2500\nfn domainWarp(p: vec2<f32>, t: f32) -> vec2<f32> {\n let warpScale = u.scalars1.x;\n let warpDrift = u.scalars1.y;\n let warpAmount = u.scalars0.w;\n let warpMode = u.ints0.z;\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n\n let q = vec2<f32>(fbm(p * warpScale + vec2<f32>(0.0, 0.0) + t * warpDrift * K_WARP),\n fbm(p * warpScale + vec2<f32>(5.2, 1.3) + t * warpDrift * K_WARP));\n let r = vec2<f32>(fbm(p * warpScale + 4.0 * q + vec2<f32>(1.7, 9.2)),\n fbm(p * warpScale + 4.0 * q + vec2<f32>(8.3, 2.8)));\n\n var warp = r;\n if (warpMode == 1) {\n // cellular \u2014 chunky territories\n let c1 = cellular(p * warpScale * 1.5 + vec2<f32>(t * warpDrift * K_WARP * 2.0, 0.0));\n let c2 = cellular(p * warpScale * 1.5 + vec2<f32>(11.0, 7.0 + t * warpDrift * K_WARP * 2.0));\n warp = vec2<f32>(c1, c2);\n } else if (warpMode == 2) {\n // hybrid \u2014 fbm + cellular averaged\n let c1 = cellular(p * warpScale * 1.2);\n let c2 = cellular(p * warpScale * 1.2 + vec2<f32>(11.0, 7.0));\n warp = mix(r, vec2<f32>(c1, c2), 0.5);\n }\n var warped = p + warpAmount * warp;\n\n // Cursor swirl \u2014 rotate p around the cursor with radial falloff.\n if (cursorStrength > 0.001) {\n let toP = p - cursor;\n let d = length(toP);\n let rr = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (rr * rr * 0.45));\n let ang = w * cursorStrength * 2.1;\n let ca = cos(ang);\n let sa = sin(ang);\n var rotated = vec2<f32>(ca * toP.x - sa * toP.y, sa * toP.x + ca * toP.y) + cursor;\n let pinch = w * cursorStrength * 0.08;\n rotated = mix(rotated, cursor, pinch);\n warped = mix(warped, rotated + warpAmount * warp * 0.7, w * cursorStrength);\n }\n return warped;\n}\n\n// \u2500\u2500 Palette LUT \u2500\u2500\nfn samplePalette(id0: f32) -> vec3<f32> {\n let id = clamp(id0, 0.0, 1.0);\n let stopCount = u.ints0.x;\n let scaled = id * f32(stopCount - 1);\n let i0 = i32(floor(scaled));\n let i1 = min(i0 + 1, stopCount - 1);\n let t = fract(scaled);\n return samplePaletteRamp(u.palette[i0].rgb, u.palette[i1].rgb, t, u.ints1.y);\n}\n\n// \u2500\u2500 Nuclei field (anisotropic Gaussian softmax + drift + palette drift) \u2500\u2500\nstruct NucleiResult { paletteId: f32, valueMod: f32 };\n\nfn nucleiField(p: vec2<f32>, t: f32) -> NucleiResult {\n let nucleiCount = u.ints0.y;\n let nucleiDrift = u.scalars2.y;\n let paletteDrift = u.scalars2.z;\n let softmaxBeta = u.scalars0.y;\n\n var accumBias = 0.0;\n var accumValue = 0.0;\n var accumW = 0.0;\n for (var i = 0; i < MAX_NUCLEI; i = i + 1) {\n if (i >= nucleiCount) { break; }\n let n0 = u.nuc0[i]; // pos.x, pos.y, radius, paletteBias\n let n1 = u.nuc1[i]; // valueBias, driftRadius, driftPhase, elong\n let angle = u.nuc2[i].x;\n let driftRadius = n1.y;\n let driftPhase = n1.z;\n let posI = n0.xy + driftRadius * vec2<f32>(\n cos(t * nucleiDrift * K_NUCLEI + driftPhase),\n sin(t * nucleiDrift * K_NUCLEI + driftPhase * 1.13)\n );\n let diff = p - posI;\n let ca = cos(angle);\n let sa = sin(angle);\n let local = vec2<f32>(ca * diff.x + sa * diff.y, -sa * diff.x + ca * diff.y);\n let along = local.x / max(n1.w, 0.01);\n let across = local.y;\n let d2 = along * along + across * across;\n let r = max(n0.z, 0.01);\n let w = exp(-softmaxBeta * d2 / (r * r));\n accumBias = accumBias + w * n0.w;\n accumValue = accumValue + w * n1.x;\n accumW = accumW + w;\n }\n var paletteId = accumBias / max(accumW, 1e-4);\n let valueMod = accumValue / max(accumW, 1e-4);\n\n let palAmp = clamp(paletteDrift * 6.0, 0.0, 0.06);\n paletteId = paletteId + palAmp * sin(t * paletteDrift * K_PAL);\n paletteId = clamp(paletteId, 0.0, 1.0);\n return NucleiResult(paletteId, valueMod);\n}\n\n// \u2500\u2500 Color utils (OKLCh saturation) \u2500\u2500\nfn linOklab(lin: vec3<f32>) -> vec3<f32> {\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\nfn saturate3(c: vec3<f32>, amt: f32) -> vec3<f32> {\n var lch = oklabToOklch(linOklab(c));\n lch.y = max(lch.y * amt, 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 PBR-Neutral tonemap (named aces() in the GLSL \u2014 the tonemap slot) \u2500\u2500\nfn aces(color0: vec3<f32>) -> vec3<f32> {\n let startCompression = 0.8 - 0.04;\n let desaturation = 0.15;\n var color = color0;\n let x = min(color.r, min(color.g, color.b));\n var offset = 0.04;\n if (x < 0.08) { offset = x - 6.25 * x * x; }\n color = color - offset;\n let peak = max(color.r, max(color.g, color.b));\n if (peak < startCompression) { return clamp(color, vec3<f32>(0.0), vec3<f32>(1.0)); }\n let d = 1.0 - startCompression;\n let newPeak = 1.0 - d * d / (peak + d - startCompression);\n color = color * (newPeak / peak);\n let g = 1.0 - 1.0 / (desaturation * (peak - newPeak) + 1.0);\n return clamp(mix(color, newPeak * vec3<f32>(1.0), g), vec3<f32>(0.0), vec3<f32>(1.0));\n}\n\n// \u2500\u2500 Full-screen triangle vertex stage (the pilot idiom \u2014 no vertex buffer) \u2500\u2500\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) uv: vec2<f32>,\n};\n\n@vertex\nfn vs_main(@builtin(vertex_index) vi: u32) -> VSOut {\n // NDC corners of the covering triangle (-1,-1), (3,-1), (-1,3).\n var p = vec2<f32>(-1.0, -1.0);\n if (vi == 1u) { p = vec2<f32>(3.0, -1.0); }\n else if (vi == 2u) { p = vec2<f32>(-1.0, 3.0); }\n var out: VSOut;\n out.pos = vec4<f32>(p, 0.0, 1.0);\n // vUv = aPos * 0.5 + 0.5 (the aurora.vert convention).\n out.uv = p * 0.5 + 0.5;\n return out;\n}\n\n// \u2500\u2500 Fragment stage (the main() transcription) \u2500\u2500\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n let t = u.scalars0.x;\n let valueVariance = u.scalars0.z;\n let breathDepth = u.scalars2.w;\n let breathPeriod = u.scalars3.x;\n let saturation = u.scalars1.z;\n let paperGrain = u.scalars1.w;\n let alpha = u.scalars2.x;\n\n let uv = in.uv;\n let pN = uv;\n\n let p_warp = domainWarp(pN, t);\n\n let nf = nucleiField(p_warp, t);\n var col = samplePalette(nf.paletteId);\n col = col * (1.0 + valueVariance * nf.valueMod);\n\n // Breath \u2014 slow global luminance wobble.\n let breath = sin(t * 6.2831 / max(breathPeriod, 1.0));\n col = col * (1.0 + breathDepth * breath * 0.5);\n\n // The painterly mediums (uMedium 1-6) are the WebGL2 fallback's register; the WGSL\n // primary renders the smooth core for the default parity capture (the booked\n // W-AURORA-WGPU-MEDIUMS successor ports the painterly bodies).\n\n // Saturation trim.\n col = saturate3(col, saturation);\n\n // Tonemap + film grain.\n col = aces(col);\n // gl_FragCoord.xy \u2192 the device-pixel position (the WGSL @builtin(position)).\n let fragCoord = in.pos.xy;\n let grain = hash21(fragCoord + t * 17.0);\n col = col + (grain - 0.5) * paperGrain;\n\n col = clamp(col * 0.985 + 0.008, vec3<f32>(0.0), vec3<f32>(1.0));\n\n // MANDATORY OETF \u2014 closes the seam (the whole pipeline above runs in LINEAR).\n col = linearToSrgb(col);\n\n // 1-LSB triangular IGN dither in DISPLAY space, AFTER the OETF.\n col = col + (1.0 / 255.0) * (ign(fragCoord) - 0.5);\n\n // Premultiply on DISPLAY-space color (matches the WebGL2 path: OETF, then premul).\n return vec4<f32>(col * alpha, alpha);\n}\n";
1
+ export declare const AURORA_WGSL = "\nconst MAX_NUCLEI: i32 = 6;\nconst MAX_STOPS: i32 = 8;\nconst PI: f32 = 3.141592653589793;\n\n// \u2500\u2500 Uniforms (the typed-struct source-of-truth \u2014 see aurora.wgsl.uniforms.ts) \u2500\u2500\n// Scalars are packed into vec4 lanes to keep the std140/WGSL 16-byte struct alignment\n// trivial. nuc0[i] = (pos.x, pos.y, radius, paletteBias); nuc1[i] = (valueBias,\n// driftRadius, driftPhase, elong); nuc2[i] = (angle, _, _, _). palette[i].rgb is the\n// CPU-baked linear-sRGB stop.\nstruct Uniforms {\n // scalars0: (uTime, uSoftmaxBeta, uValueVariance, uWarpAmount)\n scalars0: vec4<f32>,\n // scalars1: (uWarpScale, uWarpDrift, uSaturation, uPaperGrain)\n scalars1: vec4<f32>,\n // scalars2: (uAlpha, uNucleiDrift, uPaletteDrift, uBreathDepth)\n scalars2: vec4<f32>,\n // scalars3: (uBreathPeriod, uCursorStrength, uCursorRadius, uVividness)\n // BD.W-AUR-VIVIDNESS \u2014 the .w pad lane now carries the \u00A73 chroma-floor strength.\n scalars3: vec4<f32>,\n // cursor: (uCursor.x, uCursor.y, _pad, _pad)\n cursor: vec4<f32>,\n // ints: (uStopCount, uNucleiCount, uWarpMode, uNoiseOctaves)\n ints0: vec4<i32>,\n // ints1: (uMedium, uHuePath, _, _)\n ints1: vec4<i32>,\n palette: array<vec4<f32>, 8>,\n nuc0: array<vec4<f32>, 6>,\n nuc1: array<vec4<f32>, 6>,\n nuc2: array<vec4<f32>, 6>,\n // BC.W-VIZ-AURORA (T4) \u2014 the painterly-medium scalar lanes. APPENDED after the\n // arrays so EVERY existing offset (and the smooth-default parity capture) is\n // byte-identical (these lanes are written 0 on a smooth config). scalars4:\n // (uStrokeAmount, uStrokeScale, uStrokeAnisotropy, uCanvasGrain). scalars5:\n // (uWetEdge, uGranulation, uBrokenColor, uKuwaharaQ). kuwahara: (uKuwaharaRadius,\n // uKuwaharaSectors, _, _) \u2014 the Kuwahara radius/sectors/q in lockstep with\n // packAuroraWGPUUniforms (the typed-struct discipline).\n scalars4: vec4<f32>,\n scalars5: vec4<f32>,\n kuwahara: vec4<f32>,\n};\n\n@group(0) @binding(0) var<uniform> u: Uniforms;\n\n// \u2500\u2500 Authoring-scale \u2192 rad/sec lifts (byte-identical to aurora.frag.ts) \u2500\u2500\nconst K_NUCLEI: f32 = 14.0;\nconst K_PAL: f32 = 24.0;\nconst K_WARP: f32 = 5.0;\n\n// \u2500\u2500 Noise (aurora-local hash21/vnoise/fbm \u2014 legitimately divergent per AV.W2 \u00A73a) \u2500\u2500\nfn hash21(p0: vec2<f32>) -> f32 {\n var p = fract(p0 * vec2<f32>(123.34, 456.21));\n p = p + dot(p, p + 45.32);\n return fract(p.x * p.y);\n}\n\nfn hash22(p0: vec2<f32>) -> vec2<f32> {\n let p = vec2<f32>(dot(p0, vec2<f32>(127.1, 311.7)),\n dot(p0, vec2<f32>(269.5, 183.3)));\n return fract(sin(p) * 43758.5453);\n}\n\nfn vnoise(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n let uu = f * f * (3.0 - 2.0 * f);\n let a = hash21(i);\n let b = hash21(i + vec2<f32>(1.0, 0.0));\n let c = hash21(i + vec2<f32>(0.0, 1.0));\n let d = hash21(i + vec2<f32>(1.0, 1.0));\n return mix(mix(a, b, uu.x), mix(c, d, uu.x), uu.y);\n}\n\nconst FBM_ROT: mat2x2<f32> = mat2x2<f32>(0.8, 0.6, -0.6, 0.8);\n\nfn fbm(p0: vec2<f32>) -> f32 {\n var v = 0.0;\n var a = 0.5;\n var p = p0;\n let octaves = u.ints0.w;\n for (var i = 0; i < 5; i = i + 1) {\n if (i >= octaves) { break; }\n v = v + a * vnoise(p);\n p = FBM_ROT * p * 2.02;\n a = a * 0.5;\n }\n return v;\n}\n\n\nfn srgbToLinearCh(c: f32) -> f32 {\n if (c <= 0.04045) { return c / 12.92; }\n return pow((c + 0.055) / 1.055, 2.4);\n}\nfn srgbToLinear(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfn linearToSrgbCh(c: f32) -> f32 {\n if (c <= 0.0031308) { return c * 12.92; }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nfn linearToSrgb(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS, row-major \u2192 WGSL columns (= the transpose).\nconst LINEAR_SRGB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients, row-major \u2192 WGSL columns.\nconst LMS_TO_OKLAB: mat3x3<f32> = mat3x3<f32>(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF, row-major \u2192 WGSL columns.\nconst OKLAB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB, row-major \u2192 WGSL columns.\nconst LMS_TO_LINEAR_SRGB: mat3x3<f32> = mat3x3<f32>(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\nfn cbrt3(v: vec3<f32>) -> vec3<f32> {\n return sign(v) * pow(abs(v), vec3<f32>(1.0 / 3.0));\n}\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nfn srgbToOklab(c: vec3<f32>) -> vec3<f32> {\n let lin = srgbToLinear(c);\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nfn oklabToLinearSrgb(lab: vec3<f32>) -> vec3<f32> {\n let lms_ = OKLAB_TO_LMS * lab;\n let lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS, folded to [0, 2pi). Mirrors value.js rawOklabToOklch.\nfn oklabToOklch(lab: vec3<f32>) -> vec3<f32> {\n let C = length(lab.yz);\n var H = atan2(lab.z, lab.y);\n if (H < 0.0) { H = H + 2.0 * PI; }\n return vec3<f32>(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nfn oklchToOklab(lch: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// value.js interpolateHue in the NORMALIZED-TURNS domain. methods: 0 shorter,\n// 1 longer, 2 increasing, 3 decreasing.\nfn interpolateHueTurns(h0: f32, h1: f32, t: f32, method: i32) -> f32 {\n let TAU = 2.0 * PI;\n var a = h0 / TAU;\n var b = h1 / TAU;\n let i = b - a;\n if (method == 0) { // shorter\n if (i > 0.5) { a = a + 1.0; } else if (i < -0.5) { b = b + 1.0; }\n } else if (method == 1) { // longer\n if (i > 0.0 && i < 0.5) { a = a + 1.0; } else if (i > -0.5 && i <= 0.0) { b = b + 1.0; }\n } else if (method == 2) { // increasing\n if (i < 0.0) { b = b + 1.0; }\n } else { // decreasing\n if (i > 0.0) { a = a + 1.0; }\n }\n var r = a + t * (b - a);\n r = fract(r); // fract is non-negative in WGSL\n return r * TAU; // back to radians\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLab-rectangular interpolation \u2192 linear sRGB.\nfn mixPaletteOklab(linA: vec3<f32>, linB: vec3<f32>, t: f32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lab = mix(labA, labB, t);\n return oklabToLinearSrgb(lab);\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLCh hue-arc interpolation \u2192 linear sRGB.\nfn mixPaletteOklchArc(linA: vec3<f32>, linB: vec3<f32>, t: f32, method: i32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lchA = oklabToOklch(labA);\n let lchB = oklabToOklch(labB);\n let L = mix(lchA.x, lchB.x, t);\n let C = mix(lchA.y, lchB.y, t);\n let H = interpolateHueTurns(lchA.z, lchB.z, t, method);\n return oklabToLinearSrgb(oklchToOklab(vec3<f32>(L, C, H)));\n}\n\n// The ramp dispatcher (the samplePalette splices it). tRaw is the raw inter-stop\n// parameter [0,1]; the smoothstep ease + the huePath branch live here so the ramp is\n// one source. increasing(2)/decreasing(3) take the OKLCh hue-arc; every other method\n// takes the OKLab-rectangular straight line.\nfn samplePaletteRamp(a: vec3<f32>, b: vec3<f32>, tRaw: f32, huePath: i32) -> vec3<f32> {\n let t = smoothstep(0.0, 1.0, tRaw);\n if (huePath == 2 || huePath == 3) {\n return mixPaletteOklchArc(a, b, t, huePath);\n }\n return mixPaletteOklab(a, b, t);\n}\n\n// Interleaved Gradient Noise (Jimenez) \u2014 display-space 1-LSB dither.\nfn ign(p: vec2<f32>) -> f32 {\n return fract(52.9829189 * fract(dot(p, vec2<f32>(0.06711056, 0.00583715))));\n}\n\n// Cellular / Worley f1.\nfn cellular(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n var m = 1e9;\n for (var y = -1; y <= 1; y = y + 1) {\n for (var x = -1; x <= 1; x = x + 1) {\n let g = vec2<f32>(f32(x), f32(y));\n let o = hash22(i + g);\n let r = g + o - f;\n m = min(m, dot(r, r));\n }\n }\n return sqrt(m);\n}\n\n// \u2500\u2500 Warp (Quilez double warp + the three warp modes + the cursor swirl) \u2500\u2500\nfn domainWarp(p: vec2<f32>, t: f32) -> vec2<f32> {\n let warpScale = u.scalars1.x;\n let warpDrift = u.scalars1.y;\n let warpAmount = u.scalars0.w;\n let warpMode = u.ints0.z;\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n\n let q = vec2<f32>(fbm(p * warpScale + vec2<f32>(0.0, 0.0) + t * warpDrift * K_WARP),\n fbm(p * warpScale + vec2<f32>(5.2, 1.3) + t * warpDrift * K_WARP));\n let r = vec2<f32>(fbm(p * warpScale + 4.0 * q + vec2<f32>(1.7, 9.2)),\n fbm(p * warpScale + 4.0 * q + vec2<f32>(8.3, 2.8)));\n\n var warp = r;\n if (warpMode == 1) {\n // cellular \u2014 chunky territories\n let c1 = cellular(p * warpScale * 1.5 + vec2<f32>(t * warpDrift * K_WARP * 2.0, 0.0));\n let c2 = cellular(p * warpScale * 1.5 + vec2<f32>(11.0, 7.0 + t * warpDrift * K_WARP * 2.0));\n warp = vec2<f32>(c1, c2);\n } else if (warpMode == 2) {\n // hybrid \u2014 fbm + cellular averaged\n let c1 = cellular(p * warpScale * 1.2);\n let c2 = cellular(p * warpScale * 1.2 + vec2<f32>(11.0, 7.0));\n warp = mix(r, vec2<f32>(c1, c2), 0.5);\n }\n var warped = p + warpAmount * warp;\n\n // Cursor swirl \u2014 rotate p around the cursor with radial falloff.\n if (cursorStrength > 0.001) {\n let toP = p - cursor;\n let d = length(toP);\n let rr = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (rr * rr * 0.45));\n let ang = w * cursorStrength * 2.1;\n let ca = cos(ang);\n let sa = sin(ang);\n var rotated = vec2<f32>(ca * toP.x - sa * toP.y, sa * toP.x + ca * toP.y) + cursor;\n let pinch = w * cursorStrength * 0.08;\n rotated = mix(rotated, cursor, pinch);\n warped = mix(warped, rotated + warpAmount * warp * 0.7, w * cursorStrength);\n }\n return warped;\n}\n\n// \u2500\u2500 Palette LUT \u2500\u2500\nfn samplePalette(id0: f32) -> vec3<f32> {\n let id = clamp(id0, 0.0, 1.0);\n let stopCount = u.ints0.x;\n let scaled = id * f32(stopCount - 1);\n let i0 = i32(floor(scaled));\n let i1 = min(i0 + 1, stopCount - 1);\n let t = fract(scaled);\n return samplePaletteRamp(u.palette[i0].rgb, u.palette[i1].rgb, t, u.ints1.y);\n}\n\n// \u2500\u2500 Nuclei field (anisotropic Gaussian softmax + drift + palette drift) \u2500\u2500\nstruct NucleiResult { paletteId: f32, valueMod: f32 };\n\nfn nucleiField(p: vec2<f32>, t: f32) -> NucleiResult {\n let nucleiCount = u.ints0.y;\n let nucleiDrift = u.scalars2.y;\n let paletteDrift = u.scalars2.z;\n let softmaxBeta = u.scalars0.y;\n\n var accumBias = 0.0;\n var accumValue = 0.0;\n var accumW = 0.0;\n for (var i = 0; i < MAX_NUCLEI; i = i + 1) {\n if (i >= nucleiCount) { break; }\n let n0 = u.nuc0[i]; // pos.x, pos.y, radius, paletteBias\n let n1 = u.nuc1[i]; // valueBias, driftRadius, driftPhase, elong\n let angle = u.nuc2[i].x;\n let driftRadius = n1.y;\n let driftPhase = n1.z;\n let posI = n0.xy + driftRadius * vec2<f32>(\n cos(t * nucleiDrift * K_NUCLEI + driftPhase),\n sin(t * nucleiDrift * K_NUCLEI + driftPhase * 1.13)\n );\n let diff = p - posI;\n let ca = cos(angle);\n let sa = sin(angle);\n let local = vec2<f32>(ca * diff.x + sa * diff.y, -sa * diff.x + ca * diff.y);\n let along = local.x / max(n1.w, 0.01);\n let across = local.y;\n let d2 = along * along + across * across;\n let r = max(n0.z, 0.01);\n let w = exp(-softmaxBeta * d2 / (r * r));\n accumBias = accumBias + w * n0.w;\n accumValue = accumValue + w * n1.x;\n accumW = accumW + w;\n }\n var paletteId = accumBias / max(accumW, 1e-4);\n let valueMod = accumValue / max(accumW, 1e-4);\n\n let palAmp = clamp(paletteDrift * 6.0, 0.0, 0.06);\n paletteId = paletteId + palAmp * sin(t * paletteDrift * K_PAL);\n paletteId = clamp(paletteId, 0.0, 1.0);\n return NucleiResult(paletteId, valueMod);\n}\n\n// \u2500\u2500 Color utils (OKLCh saturation) \u2500\u2500\nfn linOklab(lin: vec3<f32>) -> vec3<f32> {\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\nfn saturate3(c: vec3<f32>, amt: f32) -> vec3<f32> {\n var lch = oklabToOklch(linOklab(c));\n lch.y = max(lch.y * amt, 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// BD.W-AUR-VIVIDNESS \u2014 the \u00A73 chroma FLOOR, the WGSL twin of the GLSL vividnessFloor.\n// OKLab chroma lifted toward the floor, hue + L preserved; below VIVID_EPS the (a,b)\n// direction is precision noise so the lift synthesizes along the WARM anchor (amber,\n// both components positive) \u2014 never teal/navy. vividness (scalars3.w) == 0 is a no-op\n// (the byte-identity opt-out). Mode factor lifts a dim field a touch (read through glass).\nconst VIVID_TARGET: f32 = 0.115;\nconst VIVID_EPS: f32 = 0.012;\nconst VIVID_WARM_ANCHOR: vec2<f32> = vec2<f32>(0.34202, 0.93969);\nfn vividnessFloor(c: vec3<f32>, vividness: f32) -> vec3<f32> {\n if (vividness <= 0.0001) { return c; }\n var lab = linOklab(c);\n let C = length(lab.yz);\n let modeLift = mix(1.18, 1.0, clamp(lab.x * 1.4, 0.0, 1.0));\n let Cmin = vividness * VIVID_TARGET * modeLift;\n var hueDir = VIVID_WARM_ANCHOR;\n if (C > VIVID_EPS) { hueDir = lab.yz / C; }\n let yz = hueDir * max(C, Cmin);\n lab = vec3<f32>(lab.x, yz.x, yz.y);\n return max(oklabToLinearSrgb(lab), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 PBR-Neutral tonemap (named aces() in the GLSL \u2014 the tonemap slot) \u2500\u2500\nfn aces(color0: vec3<f32>) -> vec3<f32> {\n let startCompression = 0.8 - 0.04;\n let desaturation = 0.15;\n var color = color0;\n let x = min(color.r, min(color.g, color.b));\n var offset = 0.04;\n if (x < 0.08) { offset = x - 6.25 * x * x; }\n color = color - offset;\n let peak = max(color.r, max(color.g, color.b));\n if (peak < startCompression) { return clamp(color, vec3<f32>(0.0), vec3<f32>(1.0)); }\n let d = 1.0 - startCompression;\n let newPeak = 1.0 - d * d / (peak + d - startCompression);\n color = color * (newPeak / peak);\n let g = 1.0 - 1.0 / (desaturation * (peak - newPeak) + 1.0);\n return clamp(mix(color, newPeak * vec3<f32>(1.0), g), vec3<f32>(0.0), vec3<f32>(1.0));\n}\n\n// \u2500\u2500 BC.W-VIZ-AURORA (T4) \u2014 the painterly-medium bodies (the keystone WGSL port) \u2500\u2500\n// Spliced HERE, after every helper the mediums consume is defined (domainWarp,\n// nucleiField, samplePalette, linOklab, saturate3, oklabToOklch/oklchToOklab,\n// hash21/vnoise/fbm) and before the vertex/fragment stages. applyMedium(col,p,t)\n// is the dispatch the fragment stage calls.\n\n// \u2500\u2500 Painterly luma + medium scalar accessors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst W_LUMA: vec3<f32> = vec3<f32>(0.2126, 0.7152, 0.0722);\n\nfn mStrokeAmount() -> f32 { return u.scalars4.x; }\nfn mStrokeScale() -> f32 { return u.scalars4.y; }\nfn mStrokeAnisotropy() -> f32 { return u.scalars4.z; }\nfn mCanvasGrain() -> f32 { return u.scalars4.w; }\nfn mWetEdge() -> f32 { return u.scalars5.x; }\nfn mGranulation() -> f32 { return u.scalars5.y; }\nfn mBrokenColor() -> f32 { return u.scalars5.z; }\nfn mKuwaharaQ() -> f32 { return u.scalars5.w; }\nfn mKuwaharaRadius() -> f32 { return u.kuwahara.x; }\n\n// \u2500\u2500 Base color re-sample (the edge-mask operator the mediums Sobel/sector-sample) \u2500\u2500\n// The WGSL twin of mediums.glsl.ts sampleBase: warp -> nuclei field -> palette -> value.\nfn sampleBase(p: vec2<f32>, t: f32) -> vec3<f32> {\n let pw = domainWarp(p, t);\n let nf = nucleiField(pw, t);\n var c = samplePalette(nf.paletteId);\n c = c * (1.0 + u.scalars0.z * nf.valueMod);\n return c;\n}\n\n// \u2500\u2500 Broken color (hue + chroma jitter at constant OKLCh L) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn brokenColorJitter(c: vec3<f32>, hueSeed: f32, valueSeed: f32, strength: f32) -> vec3<f32> {\n let amt = clamp(mBrokenColor() * strength, 0.0, 1.0);\n if (amt <= 0.001) { return c; }\n var lch = oklabToOklch(linOklab(c));\n lch.z = lch.z + (hueSeed - 0.5) * (32.0 * PI / 180.0) * amt;\n lch.y = max(lch.y * (1.0 + (valueSeed - 0.5) * 0.28 * amt), 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 Structure-tensor / edge-tangent-flow (AW.W4.1; the WGSL twin) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Returns vec3(tangent.x, tangent.y, A) \u2014 the minor-eigenvector edge-tangent + coherence.\nfn structureTensorField(p: vec2<f32>, t: f32, fallbackDir: vec2<f32>) -> vec3<f32> {\n let e = 0.0035;\n let l00 = dot(sampleBase(p + vec2<f32>(-e, -e), t), W_LUMA);\n let l10 = dot(sampleBase(p + vec2<f32>(0.0, -e), t), W_LUMA);\n let l20 = dot(sampleBase(p + vec2<f32>( e, -e), t), W_LUMA);\n let l01 = dot(sampleBase(p + vec2<f32>(-e, 0.0), t), W_LUMA);\n let l21 = dot(sampleBase(p + vec2<f32>( e, 0.0), t), W_LUMA);\n let l02 = dot(sampleBase(p + vec2<f32>(-e, e), t), W_LUMA);\n let l12 = dot(sampleBase(p + vec2<f32>(0.0, e), t), W_LUMA);\n let l22 = dot(sampleBase(p + vec2<f32>( e, e), t), W_LUMA);\n let Gx = (l20 + 2.0 * l21 + l22) - (l00 + 2.0 * l01 + l02);\n let Gy = (l02 + 2.0 * l12 + l22) - (l00 + 2.0 * l10 + l20);\n let Jxx = Gx * Gx;\n let Jyy = Gy * Gy;\n let Jxy = Gx * Gy;\n let tr = Jxx + Jyy;\n let disc = sqrt(max((Jxx - Jyy) * (Jxx - Jyy) + 4.0 * Jxy * Jxy, 0.0));\n let lambdaMaj = 0.5 * (tr + disc);\n let lambdaMin = 0.5 * (tr - disc);\n var tangent: vec2<f32>;\n if (disc < 1e-7) {\n tangent = fallbackDir;\n } else {\n let theta = 0.5 * atan2(2.0 * Jxy, Jxx - Jyy);\n tangent = vec2<f32>(-sin(theta), cos(theta));\n }\n var A = (lambdaMaj - lambdaMin) / (lambdaMaj + lambdaMin + 1e-6);\n A = clamp(A, 0.0, 1.0);\n if (dot(tangent, fallbackDir) < 0.0) { tangent = -tangent; }\n let blendW = pow(A, 0.28);\n let dir = normalize(mix(fallbackDir, tangent, blendW) + vec2<f32>(1e-6, 1e-6));\n return vec3<f32>(dir, A);\n}\n\n// \u2500\u2500 Flow field (the WGSL twin \u2014 the simple flow seed the medium fallback dirs use) \u2500\u2500\nfn flowField(p: vec2<f32>, t: f32) -> vec2<f32> {\n // Curl-noise-driven swirl (the medium-default dir; the full radial/swirl/diagonal\n // dispatch rides uniforms the WGSL struct does not carry \u2014 the procedural mediums\n // use this multi/curl seed as the fallback the structure tensor relaxes toward).\n let n = fbm(p * 2.0 + vec2<f32>(t * 0.02, t * 0.02));\n let a = n * 6.2831853;\n var dir = vec2<f32>(cos(a), sin(a));\n // Cursor swirl bias (matches the GLSL flow cursor term \u2014 the steady attraction).\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n if (cursorStrength > 0.001) {\n let toCur = cursor - p;\n let d = length(toCur);\n let r = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (r * r * 0.5));\n let tangent = vec2<f32>(-toCur.y, toCur.x) / max(d, 1e-4);\n let a0 = atan2(dir.y, dir.x);\n let a1 = atan2(tangent.y, tangent.x);\n var da = a1 - a0;\n da = atan2(sin(da), cos(da));\n let aa = a0 + da * w * cursorStrength;\n dir = vec2<f32>(cos(aa), sin(aa));\n }\n return dir;\n}\n\n// \u2500\u2500 Watercolor \u2014 wet-edge cauliflowers + granulation + wash banding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumWatercolor(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let eps = 0.004;\n let cx1 = sampleBase(p + vec2<f32>(eps, 0.0), t);\n let cx2 = sampleBase(p - vec2<f32>(eps, 0.0), t);\n let cy1 = sampleBase(p + vec2<f32>(0.0, eps), t);\n let cy2 = sampleBase(p - vec2<f32>(0.0, eps), t);\n let gx = dot(cx1 - cx2, W_LUMA);\n let gy = dot(cy1 - cy2, W_LUMA);\n let edge = sqrt(gx * gx + gy * gy) / (2.0 * eps);\n let mask = smoothstep(0.0, 2.5, edge);\n col = col * mix(1.0, 0.78, mask * mWetEdge());\n\n let paper = 0.5 * vnoise(p * 160.0) + 0.5 * vnoise(p * 360.0);\n let pigLoad = 1.0 - dot(col, W_LUMA);\n col = col * (1.0 - mGranulation() * pigLoad * (paper - 0.5));\n\n let band = fbm(vec2<f32>(p.x * 1.5, p.y * 0.4));\n col = col * (1.0 + 0.04 * (band - 0.5));\n return col;\n}\n\n// \u2500\u2500 Pastel \u2014 anisotropic stroke noise along the flow + tooth grain \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumPastel(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let flow = flowField(p, t);\n let perp = vec2<f32>(-flow.y, flow.x);\n let strokeScale = mStrokeScale();\n let along = dot(p, flow) * strokeScale;\n var across = dot(p, perp) * strokeScale;\n across = across + 0.03 * (vnoise(p * 260.0) - 0.5);\n\n let aniso = mix(1.0, 0.18, mStrokeAnisotropy());\n let stroke = fbm(vec2<f32>(along * aniso, across));\n col = col * mix(1.0, 0.82 + 0.32 * stroke, mStrokeAmount());\n\n let tooth = vnoise(p * 800.0);\n col = col * (1.0 - 0.08 * mStrokeAmount() * (tooth - 0.5));\n return col;\n}\n\n// \u2500\u2500 Crayon \u2014 DRY wax pigment on paper tooth (the tooth-multiply + scumble) \u2500\u2500\nfn mediumCrayon(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let flow = structureTensorField(p, t, flowField(p, t)).xy;\n let ang = atan2(flow.y, flow.x);\n let ca = cos(-ang);\n let sa = sin(-ang);\n let pr = vec2<f32>(p.x * ca - p.y * sa, p.x * sa + p.y * ca);\n\n let aniso = mix(0.45, 0.95, mStrokeAnisotropy());\n let scale = max(mStrokeScale() * 1.6, 180.0);\n\n let t1 = vnoise(vec2<f32>(pr.x * scale * aniso, pr.y * scale));\n let t2 = vnoise(vec2<f32>(pr.x * scale * aniso * 0.4, pr.y * scale * 0.4) + vec2<f32>(11.0, 11.0));\n let t3 = vnoise(vec2<f32>(pr.x * scale * aniso * 2.1, pr.y * scale * 2.1) + vec2<f32>(23.0, 23.0));\n let tooth = 0.55 * t1 + 0.30 * t2 + 0.15 * t3;\n\n let pressure = clamp(mStrokeAmount(), 0.0, 1.0);\n let bite = mix(0.18, 0.46, pressure);\n var result = col0 * (1.0 - bite * (0.5 - tooth));\n\n let scumbleMask = smoothstep(0.42, 0.78, vnoise(vec2<f32>(pr.x * scale * 0.55, pr.y * scale * 0.22) + vec2<f32>(7.0, 7.0)));\n let scumbleCoverage = scumbleMask * pressure * 0.7;\n let paper = col0 * mix(0.80, 0.94, pressure);\n result = mix(paper, result, scumbleCoverage);\n\n let pigmentCell = floor(pr * max(scale * 0.18, 32.0));\n let pigmentMask = smoothstep(0.28, 0.82, vnoise(pr * scale * 0.21 + vec2<f32>(19.0, 19.0)));\n result = brokenColorJitter(\n result,\n hash21(pigmentCell + vec2<f32>(17.0, 17.0)),\n hash21(pigmentCell * 2.1 + vec2<f32>(31.0, 31.0)),\n 0.45 + 0.55 * pigmentMask\n );\n\n result = saturate3(result, 1.08);\n return result;\n}\n\n// \u2500\u2500 Kuwahara \u2014 the SOFT anisotropic generalized Kuwahara painterly finish \u2500\u2500\u2500\u2500\n// THE KEYSTONE (Kyprianidis 2010). Aurora is a PROCEDURAL field (no input texture) so the\n// operator runs over sampleBase directly: an elliptical kernel oriented along the structure\n// tensor (elongated along the edge-tangent, narrowed across by the anisotropy), 8 OVERLAPPING\n// sectors via SMOOTH gaussian-angular weights, blended by 1/(1+var^q) (the SOFT criterion \u2192\n// no 8-spoke pinwheel by construction). 4 rings \u00D7 8 angular taps = 32 procedural samples.\nfn mediumKuwahara(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let stf = structureTensorField(p, t, flowField(p, t));\n let tangent = stf.xy;\n let A = stf.z;\n // The studio knob drives the patch radius; clamp into the procedural patch band.\n let radius = clamp(mKuwaharaRadius() + mStrokeScale() * 0.00018, 0.006, 0.024);\n let aniso = mix(1.0, 0.34, clamp(A, 0.0, 1.0));\n let ax = tangent;\n let ay = vec2<f32>(-tangent.y, tangent.x);\n\n // Per-sector weighted sums (8 sectors). WGSL has no runtime-indexed local arrays of\n // vectors as cleanly as GLSL, so unroll the sector accumulators explicitly.\n var mSum: array<vec3<f32>, 8>;\n var sSum: array<vec3<f32>, 8>;\n var wSum: array<f32, 8>;\n for (var i = 0; i < 8; i = i + 1) {\n mSum[i] = vec3<f32>(0.0);\n sSum[i] = vec3<f32>(0.0);\n wSum[i] = 0.0;\n }\n\n let RINGS = 4;\n let TAPS = 8;\n for (var r = 1; r <= RINGS; r = r + 1) {\n let rr = f32(r) / f32(RINGS);\n let radial = 1.0 - 0.6 * rr;\n for (var a = 0; a < TAPS; a = a + 1) {\n let ang = 6.2831853 * f32(a) / f32(TAPS);\n let dirE = ax * cos(ang) + ay * (sin(ang) * aniso);\n let off = dirE * (radius * rr);\n let c = sampleBase(p + off, t);\n for (var k = 0; k < 8; k = k + 1) {\n let sectorAng = 6.2831853 * f32(k) / 8.0;\n var d = ang - sectorAng;\n d = atan2(sin(d), cos(d));\n let sw = exp(-d * d * 2.2) * radial;\n mSum[k] = mSum[k] + c * sw;\n sSum[k] = sSum[k] + c * c * sw;\n wSum[k] = wSum[k] + sw;\n }\n }\n }\n\n let q = max(mKuwaharaQ(), 1.0);\n var accum = vec3<f32>(0.0);\n var accumW = 0.0;\n for (var k = 0; k < 8; k = k + 1) {\n let wk = max(wSum[k], 1e-4);\n let mean = mSum[k] / wk;\n let var3 = max(sSum[k] / wk - mean * mean, vec3<f32>(0.0));\n let variance = dot(var3, W_LUMA);\n let sectorW = 1.0 / (1.0 + pow(variance * 320.0, q));\n accum = accum + mean * sectorW;\n accumW = accumW + sectorW;\n }\n var result = accum / max(accumW, 1e-4);\n\n // Anchor in near-flat zones so the smoothing only bites at edges.\n let center = sampleBase(p, t);\n result = mix(center, result, clamp(0.35 + 0.65 * A, 0.0, 1.0));\n\n // Faint canvas tooth + pigment-saturation so the flattened patches read as oil paint.\n let tooth = vnoise(p * 300.0) - 0.5;\n result = result * (1.0 + tooth * 0.06 * mCanvasGrain());\n result = saturate3(result, 1.04);\n\n return mix(col0, result, clamp(mStrokeAmount(), 0.0, 1.0));\n}\n\n// \u2500\u2500 Medium dispatch (the WGSL twin of the GLSL main() if-ladder) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// uMedium: 0 smooth \u00B7 1 pastel \u00B7 2 watercolor \u00B7 3 oil \u00B7 4 crayon \u00B7 5 vangogh \u00B7\n// 6 oil-pastel \u00B7 7 kuwahara. The cheap peer mediums (pastel/watercolor/crayon) +\n// kuwahara port their own bodies; the oil/vangogh/oil-pastel STROKE cascade renders\n// the anisotropic-Kuwahara PAINTERLY finish here (a real oil-paint read, never the\n// smooth core \u2014 the \"NO FALLBACKS on Safari\" mandate; the full per-dab Starry-Night\n// stroke WGSL is the booked W-AURORA-WGPU-MEDIUMS-STROKES tail).\nfn applyMedium(col: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let medium = u.ints1.x;\n if (medium == 1) { return mediumPastel(col, p, t); }\n if (medium == 2) { return mediumWatercolor(col, p, t); }\n if (medium == 4) { return mediumCrayon(col, p, t); }\n // oil(3) / vangogh(5) / oil-pastel(6) / kuwahara(7) all render the painterly\n // anisotropic-Kuwahara finish on the WGSL primary (the WebGL2 fallback carries the\n // full per-dab stroke cascade for oil/vangogh/oil-pastel).\n if (medium == 3 || medium == 5 || medium == 6 || medium == 7) {\n return mediumKuwahara(col, p, t);\n }\n return col;\n}\n\n\n// \u2500\u2500 Full-screen triangle vertex stage (the pilot idiom \u2014 no vertex buffer) \u2500\u2500\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) uv: vec2<f32>,\n};\n\n@vertex\nfn vs_main(@builtin(vertex_index) vi: u32) -> VSOut {\n // NDC corners of the covering triangle (-1,-1), (3,-1), (-1,3).\n var p = vec2<f32>(-1.0, -1.0);\n if (vi == 1u) { p = vec2<f32>(3.0, -1.0); }\n else if (vi == 2u) { p = vec2<f32>(-1.0, 3.0); }\n var out: VSOut;\n out.pos = vec4<f32>(p, 0.0, 1.0);\n // vUv = aPos * 0.5 + 0.5 (the aurora.vert convention).\n out.uv = p * 0.5 + 0.5;\n return out;\n}\n\n// \u2500\u2500 Fragment stage (the main() transcription) \u2500\u2500\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n let t = u.scalars0.x;\n let valueVariance = u.scalars0.z;\n let breathDepth = u.scalars2.w;\n let breathPeriod = u.scalars3.x;\n let saturation = u.scalars1.z;\n let paperGrain = u.scalars1.w;\n let alpha = u.scalars2.x;\n let vividness = u.scalars3.w;\n\n let uv = in.uv;\n let pN = uv;\n\n let p_warp = domainWarp(pN, t);\n\n let nf = nucleiField(p_warp, t);\n var col = samplePalette(nf.paletteId);\n col = col * (1.0 + valueVariance * nf.valueMod);\n\n // Breath \u2014 slow global luminance wobble.\n let breath = sin(t * 6.2831 / max(breathPeriod, 1.0));\n col = col * (1.0 + breathDepth * breath * 0.5);\n\n // BC.W-VIZ-AURORA (T4) \u2014 the painterly-medium dispatch. uMedium 0 (smooth) is a\n // no-op pass-through so the DEFAULT smooth config is byte-identical to the prior\n // WGSL primary (the parity capture); uMedium 1-7 render the ported painterly\n // bodies (pastel/watercolor/crayon/kuwahara) or the anisotropic-Kuwahara finish\n // (oil/vangogh/oil-pastel) \u2014 never a silent smooth degrade on Safari 26.\n col = applyMedium(col, pN, t);\n\n // Saturation trim.\n col = saturate3(col, saturation);\n\n // BD.W-AUR-VIVIDNESS \u2014 the \u00A73 chroma floor (warm-anchored, hue-preserving). The WGSL\n // twin of the GLSL call; vividness:0 is a no-op so the smooth/pale default stays gated.\n col = vividnessFloor(col, vividness);\n\n // Tonemap + film grain.\n col = aces(col);\n // gl_FragCoord.xy \u2192 the device-pixel position (the WGSL @builtin(position)).\n let fragCoord = in.pos.xy;\n let grain = hash21(fragCoord + t * 17.0);\n col = col + (grain - 0.5) * paperGrain;\n\n col = clamp(col * 0.985 + 0.008, vec3<f32>(0.0), vec3<f32>(1.0));\n\n // MANDATORY OETF \u2014 closes the seam (the whole pipeline above runs in LINEAR).\n col = linearToSrgb(col);\n\n // 1-LSB triangular IGN dither in DISPLAY space, AFTER the OETF.\n col = col + (1.0 / 255.0) * (ign(fragCoord) - 0.5);\n\n // Premultiply on DISPLAY-space color (matches the WebGL2 path: OETF, then premul).\n return vec4<f32>(col * alpha, alpha);\n}\n";
@@ -5,7 +5,7 @@ export type { UseAuroraReturn } from "./composables/useAurora";
5
5
  export { useCursorInteraction } from "./composables/useCursorInteraction";
6
6
  export { createAurora } from "./composables/runtime";
7
7
  export type { AuroraRuntimeMode, AuroraRuntimeOptions } from "./composables/runtime";
8
- export { DEFAULT_AURORA_CONFIG, PAPER_WASH_GROUND, MAX_NUCLEI, MAX_STOPS, type AuroraConfig, type AuroraCursorApi, type AuroraFlow, type AuroraInstance, type AuroraInteractivity, type AuroraMedium, type AuroraNucleus, type FlowPattern, type OklchStop, type StrokeMode, type StrokeOrient, type WarpMode, } from "./constants/presets";
8
+ export { DEFAULT_AURORA_CONFIG, PAPER_WASH_GROUND, DEFAULT_VIVIDNESS, VIVID_TARGET, MAX_NUCLEI, MAX_STOPS, type AuroraConfig, type AuroraCursorApi, type AuroraFlow, type AuroraInstance, type AuroraInteractivity, type AuroraMedium, type AuroraNucleus, type FlowPattern, type OklchStop, type StrokeMode, type StrokeOrient, type WarpMode, } from "./constants/presets";
9
9
  export { resolveAtoms, configToAtoms, nucleiPrior, DEFAULT_ATOMS, type AuroraAtoms, type AuroraMotionAtom, type AuroraZones, type AuroraZoneArrangement, type AuroraMediumAtom, type AuroraInteractivityAtom, } from "./composables/atoms";
10
10
  export { cssToOklch, deriveAurora, flattenPalette, hexToOklchStop, oklchStopToHex, oklchToLinear, paletteToCssGradient, } from "./composables/color";
11
11
  export { auroraFallbackGround, sampleAuroraField, nucleiFieldStatic, relativeLuminance, type AuroraFallbackGround, type AuroraFallbackGroundOptions, type AuroraGroundMetrics, } from "./composables/auroraFallbackGround";
@@ -0,0 +1,25 @@
1
+ import { type OklchStop } from "../../../../composables/color";
2
+ /**
3
+ * Walk the anchor ramp to the single OKLCh stop at parameter `t` (0..1) via the
4
+ * shorter-hue arc — the segment is located, then value.js's `mixColors` runs the
5
+ * OKLCh/shorter-hue perceptual mix at the in-segment fraction (the single-point
6
+ * twin of `sampleColorRamp`; ONE color source — value.js). L/C lerp in OKLCh and
7
+ * the hue walks the SHORTER arc, so the warm→cool midpoint keeps its chroma.
8
+ *
9
+ * Deterministic + DOM-free (SSR-safe; mirrors `deriveBlobPalette`).
10
+ */
11
+ export declare function spectrumAt(stops: readonly OklchStop[], t: number): OklchStop;
12
+ /**
13
+ * Walk a CONCRETE-anchor ramp to `count` evenly-spaced HEX stops — the perceptual
14
+ * (OKLCH/shorter-hue) cold path. The caller (`spectrumStops` in the sync shell) has
15
+ * already screened out `var(--…)` ramps, so every stop here is a CONCRETE CSS color
16
+ * the leaf's `cssToOklch` parses to OKLCh; the walk carries no chroma trough.
17
+ *
18
+ * Each adjacent anchor pair is one `sampleColorRamp` segment (the value.js grid
19
+ * sampler walked SHORTER-hue in OKLCh); the per-segment grids concatenate (shared
20
+ * boundary deduped) into one continuous `count`-stop ramp. The endpoints anchor the
21
+ * input exactly; the hue walks the shorter arc end-to-end, so no segment greys out.
22
+ *
23
+ * @returns one HEX (`#rrggbb`) per stop.
24
+ */
25
+ export declare function walkConcreteSpectrum(stops: readonly string[], count: number): string[];
@@ -1,22 +1,18 @@
1
- import { type OklchStop } from "../../../../composables/color";
1
+ /** A consumer-supplied callback the COLD path calls once the perceptual walk resolves. */
2
+ export type SpectrumUpgrade = (stops: string[]) => void;
2
3
  /**
3
- * Walk the anchor ramp to the single OKLCh stop at parameter `t` (0..1) via the
4
- * shorter-hue arc. The segment is located, then L/C lerp linearly and the hue
5
- * walks value.js's `interpolateHue` in the normalized-turns domain (`/360` in,
6
- * `*360` out — value.js takes turns, the `.5` short-arc threshold is a half-turn;
7
- * the `deriveHue` leaf convention).
4
+ * Produce `samples` evenly-spaced HEX/CSS stops across the anchor ramp — the conic
5
+ * gradient's color stops. CSS `var(--…)` tokens (the LIBRARY-default brand ramp) are
6
+ * passed through UNTOUCHED (they resolve in the cascade at paint — the value.js-free
7
+ * fast path). CONCRETE color anchors return the synchronous interim immediately AND,
8
+ * when `onUpgrade` is supplied, load `./spectrum-walk` and upgrade to the OKLCH/
9
+ * shorter-hue perceptual walk once the dynamic chunk resolves.
8
10
  *
9
- * Deterministic + DOM-free (SSR-safe; mirrors `deriveBlobPalette`).
10
- */
11
- export declare function spectrumAt(stops: readonly OklchStop[], t: number): OklchStop;
12
- /**
13
- * Produce `samples` evenly-spaced HEX stops across the anchor ramp — the conic
14
- * gradient's color stops, carrying no chroma trough across the sweep. The anchor
15
- * stops are CSS color strings parsed via the leaf's `cssToOklch`; CSS `var(--…)`
16
- * tokens (the LIBRARY-default brand ramp) are passed through UNTOUCHED (they
17
- * resolve in the cascade at paint — the helper only walks CONCRETE color anchors).
11
+ * `spectrumStops` is SYNCHRONOUS (the SFC's `computed` cannot await). The dynamic
12
+ * boundary lives INSIDE it (the value.js branch fires `import()` and returns the
13
+ * synchronous interim), never on the export signature.
18
14
  *
19
- * @returns one HEX (`#rrggbb`) per sample, or the raw `var()` strings when the
20
- * anchors are CSS custom-property references (the token-cascade default).
15
+ * @returns one stop per sample — `var()` strings for a token ramp, the raw anchors
16
+ * for the concrete-anchor synchronous interim (upgraded to HEX via `onUpgrade`).
21
17
  */
22
- export declare function spectrumStops(stops: readonly string[], samples?: number): string[];
18
+ export declare function spectrumStops(stops: readonly string[], samples?: number, onUpgrade?: SpectrumUpgrade): string[];
@@ -1,4 +1,4 @@
1
1
  export { default as BorderProgress } from "./BorderProgress.vue";
2
2
  export type { BorderProgressProps } from "./BorderProgress.vue";
3
3
  export type { BorderProgressCoverage, BorderProgressMilestone, BorderProgressMilestoneEvent, } from "./constants";
4
- export { spectrumAt, spectrumStops } from "./composables/useBorderSpectrum";
4
+ export { spectrumStops, type SpectrumUpgrade } from "./composables/useBorderSpectrum";