impact-ui 5.0.2-alpha.1 → 5.0.2-beta.2

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 (710) hide show
  1. package/dist/_virtual/index13.js +2 -2
  2. package/dist/_virtual/index14.js +2 -2
  3. package/dist/_virtual/index15.js +2 -2
  4. package/dist/assets/animated-bar.lottie.js +4 -0
  5. package/dist/assets/animated-bulb.lottie.js +4 -0
  6. package/dist/assets/animated-chip.lottie.js +4 -0
  7. package/dist/assets/confetti-cone.lottie.js +4 -0
  8. package/dist/assets/halloween_devil_morning_final.html.js +1304 -0
  9. package/dist/assets/halloween_devil_night_Final.html.js +1299 -0
  10. package/dist/components/Accordion/index.js +1 -1
  11. package/dist/components/AccordionModern/SortableAccordionComp.d.ts +2 -2
  12. package/dist/components/AccordionModern/SortableAccordionComp.d.ts.map +1 -1
  13. package/dist/components/AccordionModern/SortableAccordionComp.js +2 -2
  14. package/dist/components/AccordionModern/index.d.ts +1 -1
  15. package/dist/components/AccordionModern/index.d.ts.map +1 -1
  16. package/dist/components/AccordionModern/index.js +34 -41
  17. package/dist/components/Alert/index.js +1 -1
  18. package/dist/components/Avatar/index.js +1 -1
  19. package/dist/components/Badge/filled/filledIconLabelBadges/index.d.ts +1 -1
  20. package/dist/components/Badge/filled/filledIconLabelBadges/index.d.ts.map +1 -1
  21. package/dist/components/Badge/filled/filledIconLabelBadges/index.js +1 -1
  22. package/dist/components/Badge/filled/filledOnlyIconBadges/index.d.ts +1 -1
  23. package/dist/components/Badge/filled/filledOnlyIconBadges/index.d.ts.map +1 -1
  24. package/dist/components/Badge/filled/filledOnlyIconBadges/index.js +1 -1
  25. package/dist/components/Badge/filled/filledOnlyLabelBadges/index.d.ts +1 -1
  26. package/dist/components/Badge/filled/filledOnlyLabelBadges/index.d.ts.map +1 -1
  27. package/dist/components/Badge/filled/filledOnlyLabelBadges/index.js +1 -1
  28. package/dist/components/Badge/filled/index.d.ts +1 -1
  29. package/dist/components/Badge/filled/index.d.ts.map +1 -1
  30. package/dist/components/Badge/index.d.ts +1 -1
  31. package/dist/components/Badge/index.js +1 -1
  32. package/dist/components/Badge/stroke/index.d.ts +1 -1
  33. package/dist/components/Badge/stroke/index.d.ts.map +1 -1
  34. package/dist/components/Badge/stroke/strokeIconLabelBadges/index.d.ts +1 -1
  35. package/dist/components/Badge/stroke/strokeIconLabelBadges/index.d.ts.map +1 -1
  36. package/dist/components/Badge/stroke/strokeIconLabelBadges/index.js +1 -1
  37. package/dist/components/Badge/stroke/strokeOnlyIconBadges/index.d.ts +1 -1
  38. package/dist/components/Badge/stroke/strokeOnlyIconBadges/index.d.ts.map +1 -1
  39. package/dist/components/Badge/stroke/strokeOnlyIconBadges/index.js +1 -1
  40. package/dist/components/Badge/stroke/strokeOnlyLabelBadges/index.d.ts +1 -1
  41. package/dist/components/Badge/stroke/strokeOnlyLabelBadges/index.d.ts.map +1 -1
  42. package/dist/components/Badge/stroke/strokeOnlyLabelBadges/index.js +1 -1
  43. package/dist/components/Badge/subtle/index.d.ts +1 -1
  44. package/dist/components/Badge/subtle/index.d.ts.map +1 -1
  45. package/dist/components/Badge/subtle/subtleIOnlyIconBadges/index.d.ts +1 -1
  46. package/dist/components/Badge/subtle/subtleIOnlyIconBadges/index.d.ts.map +1 -1
  47. package/dist/components/Badge/subtle/subtleIOnlyIconBadges/index.js +1 -1
  48. package/dist/components/Badge/subtle/subtleIconLabelBadges/index.d.ts +1 -1
  49. package/dist/components/Badge/subtle/subtleIconLabelBadges/index.d.ts.map +1 -1
  50. package/dist/components/Badge/subtle/subtleIconLabelBadges/index.js +1 -1
  51. package/dist/components/Badge/subtle/subtleOnlyLabelBadges/index.d.ts +1 -1
  52. package/dist/components/Badge/subtle/subtleOnlyLabelBadges/index.d.ts.map +1 -1
  53. package/dist/components/Badge/subtle/subtleOnlyLabelBadges/index.js +1 -1
  54. package/dist/components/BottomSheet/index.d.ts +1 -1
  55. package/dist/components/BottomSheet/index.d.ts.map +1 -1
  56. package/dist/components/BottomSheet/index.js +1 -1
  57. package/dist/components/Breadcrumbs/HomeIcon.d.ts +1 -1
  58. package/dist/components/Breadcrumbs/HomeIcon.d.ts.map +1 -1
  59. package/dist/components/Breadcrumbs/HomeIcon.js +1 -1
  60. package/dist/components/Breadcrumbs/index.d.ts +1 -1
  61. package/dist/components/Breadcrumbs/index.d.ts.map +1 -1
  62. package/dist/components/Breadcrumbs/index.js +8 -2
  63. package/dist/components/Button/index.d.ts.map +1 -1
  64. package/dist/components/Button/index.js +5 -1
  65. package/dist/components/ButtonGroup/index.d.ts +1 -1
  66. package/dist/components/ButtonGroup/index.d.ts.map +1 -1
  67. package/dist/components/ButtonGroup/index.js +1 -1
  68. package/dist/components/Card/index.js +1 -1
  69. package/dist/components/Chart/ChartSkeleton.d.ts +1 -1
  70. package/dist/components/Chart/ChartSkeleton.d.ts.map +1 -1
  71. package/dist/components/Chart/ChartSkeleton.js +24 -17
  72. package/dist/components/Chart/index.d.ts +2 -1
  73. package/dist/components/Chart/index.d.ts.map +1 -1
  74. package/dist/components/Chart/index.js +84 -28
  75. package/dist/components/Chatbot/bookMarkPanel.d.ts +1 -1
  76. package/dist/components/Chatbot/bookMarkPanel.d.ts.map +1 -1
  77. package/dist/components/Chatbot/bookMarkPanel.js +12 -5
  78. package/dist/components/Chatbot/chatBotFooter.d.ts +1 -1
  79. package/dist/components/Chatbot/chatBotFooter.d.ts.map +1 -1
  80. package/dist/components/Chatbot/chatBotLandingScreen.d.ts +1 -1
  81. package/dist/components/Chatbot/chatBotLandingScreen.d.ts.map +1 -1
  82. package/dist/components/Chatbot/chatInput.d.ts +1 -1
  83. package/dist/components/Chatbot/chatInput.d.ts.map +1 -1
  84. package/dist/components/Chatbot/chatInput.js +7 -9
  85. package/dist/components/Chatbot/chatbotModuleMenu.d.ts +1 -1
  86. package/dist/components/Chatbot/chatbotModuleMenu.d.ts.map +1 -1
  87. package/dist/components/Chatbot/chatbotModuleMenu.js +69 -62
  88. package/dist/components/Chatbot/constant.d.ts.map +1 -1
  89. package/dist/components/Chatbot/constant.js +12 -12
  90. package/dist/components/Chatbot/conversationScreen.d.ts +1 -1
  91. package/dist/components/Chatbot/conversationScreen.d.ts.map +1 -1
  92. package/dist/components/Chatbot/customScreen.d.ts +1 -1
  93. package/dist/components/Chatbot/customScreen.d.ts.map +1 -1
  94. package/dist/components/Chatbot/historyPanel.d.ts +1 -1
  95. package/dist/components/Chatbot/historyPanel.d.ts.map +1 -1
  96. package/dist/components/Chatbot/historyPanel.js +11 -3
  97. package/dist/components/Chatbot/index.d.ts +1 -1
  98. package/dist/components/Chatbot/index.d.ts.map +1 -1
  99. package/dist/components/Chatbot/index.js +8 -7
  100. package/dist/components/Chatbot/newChatComponent.d.ts +1 -1
  101. package/dist/components/Chatbot/newChatComponent.d.ts.map +1 -1
  102. package/dist/components/Checkbox/WithDropDown.d.ts +1 -1
  103. package/dist/components/Checkbox/WithDropDown.d.ts.map +1 -1
  104. package/dist/components/Checkbox/WithoutFormLabel.d.ts +1 -1
  105. package/dist/components/Checkbox/WithoutFormLabel.d.ts.map +1 -1
  106. package/dist/components/Checkbox/index.js +1 -1
  107. package/dist/components/Chips/chipLeadingIcon.d.ts +6 -0
  108. package/dist/components/Chips/chipLeadingIcon.d.ts.map +1 -0
  109. package/dist/components/Chips/chipLeadingIcon.js +46 -0
  110. package/dist/components/Chips/index.d.ts.map +1 -1
  111. package/dist/components/Chips/index.js +9 -3
  112. package/dist/components/CommentsPanel/CommentsContext.d.ts +1 -1
  113. package/dist/components/CommentsPanel/CommentsContext.d.ts.map +1 -1
  114. package/dist/components/CommentsPanel/CommentsContext.js +5 -4
  115. package/dist/components/CommentsPanel/CommentsPanel.impl.d.ts +1 -1
  116. package/dist/components/CommentsPanel/CommentsPanel.impl.d.ts.map +1 -1
  117. package/dist/components/CommentsPanel/CommentsPanel.impl.js +11 -8
  118. package/dist/components/CommentsPanel/CommentsPanel.types.d.ts +1 -1
  119. package/dist/components/CommentsPanel/CommentsPanel.types.d.ts.map +1 -1
  120. package/dist/components/CreateItemFlow/index.js +1 -1
  121. package/dist/components/DatePicker/datePickerDropdown.d.ts +1 -1
  122. package/dist/components/DatePicker/datePickerDropdown.d.ts.map +1 -1
  123. package/dist/components/DatePicker/datePickerFooter.d.ts +1 -1
  124. package/dist/components/DatePicker/datePickerFooter.d.ts.map +1 -1
  125. package/dist/components/DatePicker/datePickerInput.d.ts.map +1 -1
  126. package/dist/components/DatePicker/datePickerInput.js +5 -2
  127. package/dist/components/DatePicker/index.js +2 -2
  128. package/dist/components/DatePicker/showMonthYearSelect.d.ts +1 -1
  129. package/dist/components/DatePicker/showMonthYearSelect.d.ts.map +1 -1
  130. package/dist/components/DateRangePicker/dateRangePickerCustom.d.ts +1 -1
  131. package/dist/components/DateRangePicker/dateRangePickerCustom.d.ts.map +1 -1
  132. package/dist/components/DateRangePicker/dateRangePickerDropdown.d.ts +3 -1
  133. package/dist/components/DateRangePicker/dateRangePickerDropdown.d.ts.map +1 -1
  134. package/dist/components/DateRangePicker/dateRangePickerFooter.d.ts +1 -1
  135. package/dist/components/DateRangePicker/dateRangePickerFooter.d.ts.map +1 -1
  136. package/dist/components/DateRangePicker/dateRangePickerInput.d.ts +1 -1
  137. package/dist/components/DateRangePicker/dateRangePickerInput.d.ts.map +1 -1
  138. package/dist/components/DateRangePicker/dateRangePickerInput.js +6 -7
  139. package/dist/components/DateRangePicker/index.js +2 -2
  140. package/dist/components/DateRangePicker/showMonthYearSelect.d.ts +1 -1
  141. package/dist/components/DateRangePicker/showMonthYearSelect.d.ts.map +1 -1
  142. package/dist/components/DynamicLayout/index.d.ts +2 -1
  143. package/dist/components/DynamicLayout/index.d.ts.map +1 -1
  144. package/dist/components/DynamicLayout/index.js +1 -1
  145. package/dist/components/EmptyState/EmptyStateImage.d.ts +2 -2
  146. package/dist/components/EmptyState/EmptyStateImage.d.ts.map +1 -1
  147. package/dist/components/EmptyState/EmptyStateImage.js +26 -13
  148. package/dist/components/EmptyState/index.d.ts +1 -1
  149. package/dist/components/EmptyState/index.d.ts.map +1 -1
  150. package/dist/components/EmptyState/index.js +29 -1
  151. package/dist/components/FileUpload/TemplatePreview.d.ts +1 -1
  152. package/dist/components/FileUpload/TemplatePreview.d.ts.map +1 -1
  153. package/dist/components/FileUpload/fileUploadAssets.loader.d.ts +0 -1
  154. package/dist/components/FileUpload/fileUploadAssets.loader.d.ts.map +1 -1
  155. package/dist/components/FileUpload/fileUploadAssets.loader.js +0 -1
  156. package/dist/components/FileUpload/index.d.ts +1 -1
  157. package/dist/components/FileUpload/index.d.ts.map +1 -1
  158. package/dist/components/FileUpload/index.js +27 -11
  159. package/dist/components/FilterPanel/FilterPanelHeader.d.ts +1 -1
  160. package/dist/components/FilterPanel/FilterPanelHeader.d.ts.map +1 -1
  161. package/dist/components/FilterPanel/PanelFooter.d.ts +1 -1
  162. package/dist/components/FilterPanel/PanelFooter.d.ts.map +1 -1
  163. package/dist/components/FilterPanel/PanelSidebar.d.ts +1 -1
  164. package/dist/components/FilterPanel/PanelSidebar.d.ts.map +1 -1
  165. package/dist/components/FilterPanel/index.d.ts +1 -1
  166. package/dist/components/FilterPanel/index.d.ts.map +1 -1
  167. package/dist/components/FilterPanel/index.js +67 -43
  168. package/dist/components/FiltersStrip/AppliedFilters.d.ts +1 -1
  169. package/dist/components/FiltersStrip/AppliedFilters.d.ts.map +1 -1
  170. package/dist/components/FiltersStrip/FilterDropDown.d.ts +1 -1
  171. package/dist/components/FiltersStrip/FilterDropDown.d.ts.map +1 -1
  172. package/dist/components/FiltersStrip/FilterSlider.d.ts +1 -1
  173. package/dist/components/FiltersStrip/FilterSlider.d.ts.map +1 -1
  174. package/dist/components/FiltersStrip/FilterSlider.js +1 -1
  175. package/dist/components/FiltersStrip/FilterSliderPortal.d.ts +1 -1
  176. package/dist/components/FiltersStrip/FilterSliderPortal.d.ts.map +1 -1
  177. package/dist/components/FiltersStrip/index.d.ts +1 -1
  178. package/dist/components/FiltersStrip/index.d.ts.map +1 -1
  179. package/dist/components/FiltersStrip/index.js +1 -1
  180. package/dist/components/HalloweenStyleIntro/HalloweenStyleIntroProvider.d.ts +14 -0
  181. package/dist/components/HalloweenStyleIntro/HalloweenStyleIntroProvider.d.ts.map +1 -0
  182. package/dist/components/HalloweenStyleIntro/HalloweenStyleIntroProvider.js +131 -0
  183. package/dist/components/HalloweenStyleIntro/halloweenIntro.constants.d.ts +13 -0
  184. package/dist/components/HalloweenStyleIntro/halloweenIntro.constants.d.ts.map +1 -0
  185. package/dist/components/HalloweenStyleIntro/halloweenIntro.constants.js +9 -0
  186. package/dist/components/HalloweenStyleIntro/halloweenIntroHtml.d.ts +15 -0
  187. package/dist/components/HalloweenStyleIntro/halloweenIntroHtml.d.ts.map +1 -0
  188. package/dist/components/HalloweenStyleIntro/halloweenIntroHtml.js +141 -0
  189. package/dist/components/HalloweenStyleIntro/halloweenIntroHtml.test.d.ts +2 -0
  190. package/dist/components/HalloweenStyleIntro/halloweenIntroHtml.test.d.ts.map +1 -0
  191. package/dist/components/HalloweenStyleIntro/index.d.ts +4 -0
  192. package/dist/components/HalloweenStyleIntro/index.d.ts.map +1 -0
  193. package/dist/components/Header/Header.types.d.ts +22 -5
  194. package/dist/components/Header/Header.types.d.ts.map +1 -1
  195. package/dist/components/Header/index.d.ts +1 -1
  196. package/dist/components/Header/index.d.ts.map +1 -1
  197. package/dist/components/Header/index.js +88 -57
  198. package/dist/components/HomePage/HomePage.types.d.ts +3 -2
  199. package/dist/components/HomePage/HomePage.types.d.ts.map +1 -1
  200. package/dist/components/HomePage/constants.d.ts.map +1 -1
  201. package/dist/components/HomePage/constants.js +23 -44
  202. package/dist/components/HomePage/index.d.ts +1 -1
  203. package/dist/components/HomePage/index.d.ts.map +1 -1
  204. package/dist/components/HomePage/index.js +48 -53
  205. package/dist/components/ImpactIcon/index.d.ts +19 -0
  206. package/dist/components/ImpactIcon/index.d.ts.map +1 -0
  207. package/dist/components/ImpactIcon/index.js +52 -0
  208. package/dist/components/Input/HelperText.d.ts +1 -1
  209. package/dist/components/Input/HelperText.d.ts.map +1 -1
  210. package/dist/components/Input/HelperText.js +3 -1
  211. package/dist/components/Input/InputWithIcon.d.ts +1 -1
  212. package/dist/components/Input/InputWithIcon.d.ts.map +1 -1
  213. package/dist/components/Input/InputWithIcon.js +1 -1
  214. package/dist/components/Input/VanillaInput.d.ts +1 -1
  215. package/dist/components/Input/VanillaInput.d.ts.map +1 -1
  216. package/dist/components/Input/VanillaInput.js +1 -1
  217. package/dist/components/Input/index.js +3 -3
  218. package/dist/components/KeyboardShortCuts/Keycombo.d.ts +2 -2
  219. package/dist/components/KeyboardShortCuts/Keycombo.d.ts.map +1 -1
  220. package/dist/components/KeyboardShortCuts/ShortcutLandingPage.d.ts +1 -1
  221. package/dist/components/KeyboardShortCuts/ShortcutLandingPage.d.ts.map +1 -1
  222. package/dist/components/KeyboardShortCuts/ShortcutLandingPage.js +5 -4
  223. package/dist/components/KeyboardShortCuts/ShortcutModal.d.ts +1 -1
  224. package/dist/components/KeyboardShortCuts/ShortcutModal.d.ts.map +1 -1
  225. package/dist/components/KeyboardShortCuts/ShortcutModal.js +2 -2
  226. package/dist/components/KeyboardShortCuts/StarOutlineIcon.d.ts +1 -1
  227. package/dist/components/KeyboardShortCuts/StarOutlineIcon.d.ts.map +1 -1
  228. package/dist/components/KeyboardShortCuts/allSetBox.d.ts +4 -3
  229. package/dist/components/KeyboardShortCuts/allSetBox.d.ts.map +1 -1
  230. package/dist/components/KeyboardShortCuts/allSetBox.js +12 -16
  231. package/dist/components/KeyboardShortCuts/index.d.ts +1 -1
  232. package/dist/components/KeyboardShortCuts/index.d.ts.map +1 -1
  233. package/dist/components/KeyboardShortCuts/index.js +1 -1
  234. package/dist/components/KeyboardShortCuts/screen2.d.ts +1 -1
  235. package/dist/components/KeyboardShortCuts/screen2.d.ts.map +1 -1
  236. package/dist/components/KeyboardShortCuts/screen3.d.ts +1 -1
  237. package/dist/components/KeyboardShortCuts/screen3.d.ts.map +1 -1
  238. package/dist/components/KeyboardShortCuts/tutorial.d.ts +2 -1
  239. package/dist/components/KeyboardShortCuts/tutorial.d.ts.map +1 -1
  240. package/dist/components/KeyboardShortCuts/tutorial.js +3 -2
  241. package/dist/components/Loader/HalloweenLoaderSlides.d.ts +13 -0
  242. package/dist/components/Loader/HalloweenLoaderSlides.d.ts.map +1 -0
  243. package/dist/components/Loader/HalloweenLoaderSlides.js +109 -0
  244. package/dist/components/Loader/index.d.ts +1 -1
  245. package/dist/components/Loader/index.d.ts.map +1 -1
  246. package/dist/components/Loader/index.js +3 -1
  247. package/dist/components/Menu/IconMenuItem.js +1 -1
  248. package/dist/components/Menu/MenuHeaderInfo.d.ts +2 -2
  249. package/dist/components/Menu/MenuHeaderInfo.d.ts.map +1 -1
  250. package/dist/components/Menu/MenuHeaderInfo.js +10 -2
  251. package/dist/components/Menu/NestedMenuItem.js +1 -1
  252. package/dist/components/Menu/index.js +5 -14
  253. package/dist/components/Menu/nestedMenuItemsFromObject.js +1 -1
  254. package/dist/components/Modal/index.d.ts +1 -1
  255. package/dist/components/Modal/index.d.ts.map +1 -1
  256. package/dist/components/Modal/index.js +1 -1
  257. package/dist/components/MonthPicker/index.d.ts +1 -1
  258. package/dist/components/MonthPicker/index.d.ts.map +1 -1
  259. package/dist/components/MonthPicker/index.js +10 -4
  260. package/dist/components/MonthRangePicker/constants.d.ts +4 -0
  261. package/dist/components/MonthRangePicker/constants.d.ts.map +1 -1
  262. package/dist/components/MonthRangePicker/constants.js +15 -1
  263. package/dist/components/MonthRangePicker/index.d.ts +1 -1
  264. package/dist/components/MonthRangePicker/index.d.ts.map +1 -1
  265. package/dist/components/MonthRangePicker/index.js +68 -30
  266. package/dist/components/NewCreateItemFlow/index.d.ts +1 -1
  267. package/dist/components/NewCreateItemFlow/index.d.ts.map +1 -1
  268. package/dist/components/NewCreateItemFlow/index.js +1 -1
  269. package/dist/components/NewDynamicLayout/index.d.ts +1 -1
  270. package/dist/components/NewDynamicLayout/index.d.ts.map +1 -1
  271. package/dist/components/NewDynamicLayout/index.js +13 -15
  272. package/dist/components/Notification/NotificationBody/NotificationList/NotificationChipsList.d.ts +1 -1
  273. package/dist/components/Notification/NotificationBody/NotificationList/NotificationChipsList.d.ts.map +1 -1
  274. package/dist/components/Notification/NotificationBody/NotificationList/NotificationChipsList.js +3 -1
  275. package/dist/components/Notification/NotificationBody/NotificationList/NotificationList.d.ts +1 -1
  276. package/dist/components/Notification/NotificationBody/NotificationList/NotificationList.d.ts.map +1 -1
  277. package/dist/components/Notification/NotificationBody/NotificationList/NotificationList.js +1 -1
  278. package/dist/components/Notification/NotificationBody/NotificationList/NotificationListItem.d.ts +1 -1
  279. package/dist/components/Notification/NotificationBody/NotificationList/NotificationListItem.d.ts.map +1 -1
  280. package/dist/components/Notification/NotificationBody/NotificationList/NotificationListItem.js +12 -16
  281. package/dist/components/Notification/NotificationBody/NotificationPanelContent.d.ts +1 -1
  282. package/dist/components/Notification/NotificationBody/NotificationPanelContent.d.ts.map +1 -1
  283. package/dist/components/Notification/NotificationBody/NotificationTaskList.d.ts +1 -1
  284. package/dist/components/Notification/NotificationBody/NotificationTaskList.d.ts.map +1 -1
  285. package/dist/components/Notification/NotificationBody/NotificationTaskList.js +4 -2
  286. package/dist/components/Notification/NotificationBody/index.d.ts +1 -1
  287. package/dist/components/Notification/NotificationBody/index.d.ts.map +1 -1
  288. package/dist/components/Notification/NotificationHeader.d.ts.map +1 -1
  289. package/dist/components/Notification/NotificationHeader.js +13 -3
  290. package/dist/components/Notification/index.d.ts +1 -1
  291. package/dist/components/Notification/index.d.ts.map +1 -1
  292. package/dist/components/Notification/index.js +1 -1
  293. package/dist/components/OnboardingTour/index.d.ts +1 -1
  294. package/dist/components/OnboardingTour/index.d.ts.map +1 -1
  295. package/dist/components/OnboardingTour/index.js +10 -4
  296. package/dist/components/OnboardingTour/productTourList.d.ts +1 -1
  297. package/dist/components/OnboardingTour/productTourList.d.ts.map +1 -1
  298. package/dist/components/OnboardingTour/productTourList.js +4 -4
  299. package/dist/components/OnboardingTour/tooltipCard.d.ts +1 -1
  300. package/dist/components/OnboardingTour/tooltipCard.d.ts.map +1 -1
  301. package/dist/components/OnboardingTour/tooltipCard.js +2 -2
  302. package/dist/components/Panel/Panel.types.d.ts +0 -7
  303. package/dist/components/Panel/Panel.types.d.ts.map +1 -1
  304. package/dist/components/Panel/index.d.ts +1 -1
  305. package/dist/components/Panel/index.d.ts.map +1 -1
  306. package/dist/components/Panel/index.js +15 -12
  307. package/dist/components/Popover/Popover.types.d.ts +5 -0
  308. package/dist/components/Popover/Popover.types.d.ts.map +1 -1
  309. package/dist/components/Popover/index.d.ts +1 -1
  310. package/dist/components/Popover/index.d.ts.map +1 -1
  311. package/dist/components/Popover/index.js +12 -4
  312. package/dist/components/ProfileMenu/ProfileMenu.types.d.ts +55 -0
  313. package/dist/components/ProfileMenu/ProfileMenu.types.d.ts.map +1 -0
  314. package/dist/components/ProfileMenu/ProfileMenuListItem.d.ts +12 -0
  315. package/dist/components/ProfileMenu/ProfileMenuListItem.d.ts.map +1 -0
  316. package/dist/components/ProfileMenu/ProfileMenuListItem.js +42 -0
  317. package/dist/components/ProfileMenu/index.d.ts +11 -0
  318. package/dist/components/ProfileMenu/index.d.ts.map +1 -0
  319. package/dist/components/ProfileMenu/index.js +164 -0
  320. package/dist/components/ProgressBar/index.d.ts +1 -1
  321. package/dist/components/ProgressBar/index.d.ts.map +1 -1
  322. package/dist/components/ProgressBar/index.js +1 -1
  323. package/dist/components/Prompt/index.d.ts +1 -1
  324. package/dist/components/Prompt/index.d.ts.map +1 -1
  325. package/dist/components/Prompt/index.js +10 -2
  326. package/dist/components/RadioButtonGroup/index.d.ts +1 -1
  327. package/dist/components/RadioButtonGroup/index.d.ts.map +1 -1
  328. package/dist/components/RadioButtonGroup/index.js +1 -1
  329. package/dist/components/Select/customGroupHeading.d.ts +1 -1
  330. package/dist/components/Select/customGroupHeading.d.ts.map +1 -1
  331. package/dist/components/Select/dropdown.d.ts +1 -1
  332. package/dist/components/Select/dropdown.d.ts.map +1 -1
  333. package/dist/components/Select/index.js +2 -2
  334. package/dist/components/Select/menuList.d.ts +2 -1
  335. package/dist/components/Select/menuList.d.ts.map +1 -1
  336. package/dist/components/Select/menuList.js +2 -1
  337. package/dist/components/Select/optionList.d.ts +2 -1
  338. package/dist/components/Select/optionList.d.ts.map +1 -1
  339. package/dist/components/Select/selected-option-tags.d.ts +1 -1
  340. package/dist/components/Select/selected-option-tags.d.ts.map +1 -1
  341. package/dist/components/Shortcuts/ShortcutHint.d.ts +1 -1
  342. package/dist/components/Shortcuts/ShortcutHint.d.ts.map +1 -1
  343. package/dist/components/Shortcuts/ShortcutHint.js +4 -18
  344. package/dist/components/Shortcuts/ShortcutScope.d.ts +1 -1
  345. package/dist/components/Shortcuts/ShortcutScope.d.ts.map +1 -1
  346. package/dist/components/Shortcuts/ShortcutsProvider.d.ts +1 -1
  347. package/dist/components/Shortcuts/ShortcutsProvider.d.ts.map +1 -1
  348. package/dist/components/Sidebar/ChildMenu.d.ts +1 -1
  349. package/dist/components/Sidebar/ChildMenu.d.ts.map +1 -1
  350. package/dist/components/Sidebar/ParentMenu.d.ts +1 -1
  351. package/dist/components/Sidebar/ParentMenu.d.ts.map +1 -1
  352. package/dist/components/Sidebar/SidebarActions.d.ts +1 -1
  353. package/dist/components/Sidebar/SidebarActions.d.ts.map +1 -1
  354. package/dist/components/Sidebar/SidebarActions.js +3 -3
  355. package/dist/components/Sidebar/SidebarMenus.d.ts +1 -1
  356. package/dist/components/Sidebar/SidebarMenus.d.ts.map +1 -1
  357. package/dist/components/Sidebar/index.d.ts +1 -1
  358. package/dist/components/Sidebar/index.d.ts.map +1 -1
  359. package/dist/components/Sidebar/index.js +1 -1
  360. package/dist/components/Skeleton/index.d.ts +1 -1
  361. package/dist/components/Skeleton/index.d.ts.map +1 -1
  362. package/dist/components/Skeleton/index.js +1 -1
  363. package/dist/components/Slider/index.d.ts +1 -1
  364. package/dist/components/Slider/index.d.ts.map +1 -1
  365. package/dist/components/Slider/index.js +8 -6
  366. package/dist/components/Slider/sliderValueLabel.d.ts +7 -0
  367. package/dist/components/Slider/sliderValueLabel.d.ts.map +1 -0
  368. package/dist/components/Slider/sliderValueLabel.js +31 -0
  369. package/dist/components/Stepper/index.d.ts +1 -1
  370. package/dist/components/Stepper/index.d.ts.map +1 -1
  371. package/dist/components/Stepper/index.js +2 -2
  372. package/dist/components/Switch/index.d.ts.map +1 -1
  373. package/dist/components/Switch/index.js +11 -10
  374. package/dist/components/TableChat/EmptyContainer.d.ts +2 -1
  375. package/dist/components/TableChat/EmptyContainer.d.ts.map +1 -1
  376. package/dist/components/TableChat/EmptyContainer.js +3 -3
  377. package/dist/components/TableChat/TableChatSidePanel.d.ts +2 -3
  378. package/dist/components/TableChat/TableChatSidePanel.d.ts.map +1 -1
  379. package/dist/components/TableChat/TableChatSidePanel.js +23 -214
  380. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatFooterSkeleton.d.ts +2 -1
  381. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatFooterSkeleton.d.ts.map +1 -1
  382. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatFooterSkeleton.js +1 -1
  383. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatHeaderSkeleton.d.ts +2 -1
  384. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatHeaderSkeleton.d.ts.map +1 -1
  385. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatHeaderSkeleton.js +1 -1
  386. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatMessageListSkeleton.d.ts +2 -1
  387. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatMessageListSkeleton.d.ts.map +1 -1
  388. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatMessageListSkeleton.js +1 -1
  389. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatSkeleton.d.ts +2 -1
  390. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatSkeleton.d.ts.map +1 -1
  391. package/dist/components/TableChat/components/ChatMessageSkeleton/ChatSkeleton.js +1 -1
  392. package/dist/components/TableChat/components/SkeletonList.d.ts +1 -1
  393. package/dist/components/TableChat/components/SkeletonList.d.ts.map +1 -1
  394. package/dist/components/TableChat/components/TableChatLeftSection/AddChatContainer/AddChatContainer.d.ts +1 -1
  395. package/dist/components/TableChat/components/TableChatLeftSection/AddChatContainer/AddChatContainer.d.ts.map +1 -1
  396. package/dist/components/TableChat/components/TableChatLeftSection/AddChatContainer/AddChatContainer.js +1 -1
  397. package/dist/components/TableChat/components/TableChatLeftSection/ChannelCheckbox/ChannelCheckbox.d.ts +3 -1
  398. package/dist/components/TableChat/components/TableChatLeftSection/ChannelCheckbox/ChannelCheckbox.d.ts.map +1 -1
  399. package/dist/components/TableChat/components/TableChatLeftSection/ChatChannelItem.d.ts +3 -5
  400. package/dist/components/TableChat/components/TableChatLeftSection/ChatChannelItem.d.ts.map +1 -1
  401. package/dist/components/TableChat/components/TableChatLeftSection/ChatChannelItem.js +30 -60
  402. package/dist/components/TableChat/components/TableChatLeftSection/ChatChannelList.d.ts +1 -1
  403. package/dist/components/TableChat/components/TableChatLeftSection/ChatChannelList.d.ts.map +1 -1
  404. package/dist/components/TableChat/components/TableChatLeftSection/ChatChannelList.js +2 -3
  405. package/dist/components/TableChat/components/TableChatLeftSection/ChatHeaderButton/ChatHeaderButton.d.ts +2 -2
  406. package/dist/components/TableChat/components/TableChatLeftSection/ChatHeaderButton/ChatHeaderButton.d.ts.map +1 -1
  407. package/dist/components/TableChat/components/TableChatLeftSection/ChatHeaderNavigation.d.ts.map +1 -1
  408. package/dist/components/TableChat/components/TableChatLeftSection/ChatHeaderNavigation.js +43 -20
  409. package/dist/components/TableChat/components/TableChatLeftSection/ChatIconButton/ChatIconButton.d.ts +3 -1
  410. package/dist/components/TableChat/components/TableChatLeftSection/ChatIconButton/ChatIconButton.d.ts.map +1 -1
  411. package/dist/components/TableChat/components/TableChatLeftSection/TableChatChannelHeader.d.ts +1 -1
  412. package/dist/components/TableChat/components/TableChatLeftSection/TableChatChannelHeader.d.ts.map +1 -1
  413. package/dist/components/TableChat/components/TableChatLeftSection/TableChatChannelHeader.js +2 -37
  414. package/dist/components/TableChat/components/TableChatLeftSection/UnreadBadge/UnreadBadge.d.ts +3 -1
  415. package/dist/components/TableChat/components/TableChatLeftSection/UnreadBadge/UnreadBadge.d.ts.map +1 -1
  416. package/dist/components/TableChat/components/TableChatRightSection/AvatarGroup/AvatarGroup.d.ts +2 -2
  417. package/dist/components/TableChat/components/TableChatRightSection/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  418. package/dist/components/TableChat/components/TableChatRightSection/AvatarGroup/AvatarGroup.js +36 -90
  419. package/dist/components/TableChat/components/TableChatRightSection/ChatDefaultMessageType/ChatDefaultMessageType.d.ts +2 -5
  420. package/dist/components/TableChat/components/TableChatRightSection/ChatDefaultMessageType/ChatDefaultMessageType.d.ts.map +1 -1
  421. package/dist/components/TableChat/components/TableChatRightSection/ChatDefaultMessageType/ChatDefaultMessageType.js +91 -108
  422. package/dist/components/TableChat/components/TableChatRightSection/ChatDeleteMessageType/ChatDeletedMessageType.d.ts +1 -1
  423. package/dist/components/TableChat/components/TableChatRightSection/ChatDeleteMessageType/ChatDeletedMessageType.d.ts.map +1 -1
  424. package/dist/components/TableChat/components/TableChatRightSection/ChatDeleteMessageType/ChatDeletedMessageType.js +2 -2
  425. package/dist/components/TableChat/components/TableChatRightSection/ChatEditedMessageType/ChatEditedMessageType.d.ts +1 -1
  426. package/dist/components/TableChat/components/TableChatRightSection/ChatEditedMessageType/ChatEditedMessageType.d.ts.map +1 -1
  427. package/dist/components/TableChat/components/TableChatRightSection/ChatEditedMessageType/ChatEditedMessageType.js +76 -0
  428. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeader.d.ts +1 -1
  429. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeader.d.ts.map +1 -1
  430. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeader.js +7 -14
  431. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeaderAction.d.ts +1 -1
  432. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeaderAction.d.ts.map +1 -1
  433. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeaderAction.js +75 -74
  434. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeaderInfo.d.ts +2 -9
  435. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeaderInfo.d.ts.map +1 -1
  436. package/dist/components/TableChat/components/TableChatRightSection/ChatHeader/ChatHeaderInfo.js +4 -170
  437. package/dist/components/TableChat/components/TableChatRightSection/ChatInput/ChatInput.d.ts +3 -6
  438. package/dist/components/TableChat/components/TableChatRightSection/ChatInput/ChatInput.d.ts.map +1 -1
  439. package/dist/components/TableChat/components/TableChatRightSection/ChatInput/ChatInput.js +142 -159
  440. package/dist/components/TableChat/components/TableChatRightSection/ChatMessageActions/ChatMessageActions.d.ts +1 -1
  441. package/dist/components/TableChat/components/TableChatRightSection/ChatMessageActions/ChatMessageActions.d.ts.map +1 -1
  442. package/dist/components/TableChat/components/TableChatRightSection/ChatMessageAvatar/ChatMessageAvatar.d.ts +2 -1
  443. package/dist/components/TableChat/components/TableChatRightSection/ChatMessageAvatar/ChatMessageAvatar.d.ts.map +1 -1
  444. package/dist/components/TableChat/components/TableChatRightSection/ChatMessages/ChatMessage.d.ts +10 -12
  445. package/dist/components/TableChat/components/TableChatRightSection/ChatMessages/ChatMessage.d.ts.map +1 -1
  446. package/dist/components/TableChat/components/TableChatRightSection/ChatMessages/ChatMessage.js +108 -105
  447. package/dist/components/TableChat/components/TableChatRightSection/ChatNotificationSettings/ChatNotificationSettings.d.ts +1 -1
  448. package/dist/components/TableChat/components/TableChatRightSection/ChatNotificationSettings/ChatNotificationSettings.d.ts.map +1 -1
  449. package/dist/components/TableChat/components/TableChatRightSection/ChatNotificationSettings/ChatNotificationSettings.js +18 -1
  450. package/dist/components/TableChat/components/TableChatRightSection/DateSeparator/DateSeparator.d.ts +1 -1
  451. package/dist/components/TableChat/components/TableChatRightSection/DateSeparator/DateSeparator.d.ts.map +1 -1
  452. package/dist/components/TableChat/components/TableChatRightSection/DateSeparator/DateSeparator.js +1 -4
  453. package/dist/components/TableChat/components/TableChatRightSection/EmojiPicker/EmojiPicker.d.ts +3 -1
  454. package/dist/components/TableChat/components/TableChatRightSection/EmojiPicker/EmojiPicker.d.ts.map +1 -1
  455. package/dist/components/TableChat/components/TableChatRightSection/FileUploader/FileUploader.d.ts +3 -1
  456. package/dist/components/TableChat/components/TableChatRightSection/FileUploader/FileUploader.d.ts.map +1 -1
  457. package/dist/components/TableChat/components/TableChatRightSection/FileUploader/FileUploader.js +6 -6
  458. package/dist/components/TableChat/components/TableChatRightSection/ImageUploader/ImageUploader.d.ts +1 -1
  459. package/dist/components/TableChat/components/TableChatRightSection/ImageUploader/ImageUploader.d.ts.map +1 -1
  460. package/dist/components/TableChat/components/TableChatRightSection/ImageUploader/ImageUploader.js +5 -5
  461. package/dist/components/TableChat/components/TableChatRightSection/PinedChatPanel/PinedChatPanel.d.ts +1 -1
  462. package/dist/components/TableChat/components/TableChatRightSection/PinedChatPanel/PinedChatPanel.d.ts.map +1 -1
  463. package/dist/components/TableChat/components/TableChatRightSection/PinedChatPanel/PinedChatPanel.js +1 -1
  464. package/dist/components/TableChat/components/TableChatRightSection/ReplyBadge/ReplyBadge.d.ts +2 -3
  465. package/dist/components/TableChat/components/TableChatRightSection/ReplyBadge/ReplyBadge.d.ts.map +1 -1
  466. package/dist/components/TableChat/components/TableChatRightSection/TableChatRightSection.d.ts +2 -1
  467. package/dist/components/TableChat/components/TableChatRightSection/TableChatRightSection.d.ts.map +1 -1
  468. package/dist/components/TableChat/components/TableChatRightSection/TableChatRightSection.js +223 -328
  469. package/dist/components/TableChat/components/TextEditor/EditorToolbar.js +1 -1
  470. package/dist/components/TableChat/components/TextEditor/Mention.d.ts.map +1 -1
  471. package/dist/components/TableChat/components/TextEditor/Mention.js +2 -7
  472. package/dist/components/TableChat/components/TextEditor/MentionList.js +1 -1
  473. package/dist/components/TableChat/components/chatConfig.js +1 -0
  474. package/dist/components/TableV36/AdvanceSearchModalItem.d.ts +3 -1
  475. package/dist/components/TableV36/AdvanceSearchModalItem.d.ts.map +1 -1
  476. package/dist/components/TableV36/AdvanceSortModal.d.ts +3 -1
  477. package/dist/components/TableV36/AdvanceSortModal.d.ts.map +1 -1
  478. package/dist/components/TableV36/AdvanceSortModal.js +42 -42
  479. package/dist/components/TableV36/AgGridHeader.d.ts +1 -1
  480. package/dist/components/TableV36/AgGridHeader.d.ts.map +1 -1
  481. package/dist/components/TableV36/AgGridHeader.js +21 -11
  482. package/dist/components/TableV36/CellTooltip.d.ts +1 -1
  483. package/dist/components/TableV36/CellTooltip.d.ts.map +1 -1
  484. package/dist/components/TableV36/CommentsPortal.d.ts.map +1 -1
  485. package/dist/components/TableV36/CommentsPortal.js +7 -4
  486. package/dist/components/TableV36/NewAdvanceSearchModal/NewAdvanceSearchModal.d.ts +3 -1
  487. package/dist/components/TableV36/NewAdvanceSearchModal/NewAdvanceSearchModal.d.ts.map +1 -1
  488. package/dist/components/TableV36/NewAdvanceSearchModal/NewAdvanceSearchModalItem.d.ts +3 -1
  489. package/dist/components/TableV36/NewAdvanceSearchModal/NewAdvanceSearchModalItem.d.ts.map +1 -1
  490. package/dist/components/TableV36/NewAdvanceSearchModal/NewAdvanceSearchModalItem.js +5 -0
  491. package/dist/components/TableV36/NoComments.d.ts +3 -1
  492. package/dist/components/TableV36/NoComments.d.ts.map +1 -1
  493. package/dist/components/TableV36/NoComments.js +1 -1
  494. package/dist/components/TableV36/Table.types.d.ts +2 -2
  495. package/dist/components/TableV36/Table.types.d.ts.map +1 -1
  496. package/dist/components/TableV36/TableSkeletonCell.d.ts +1 -1
  497. package/dist/components/TableV36/TableSkeletonCell.d.ts.map +1 -1
  498. package/dist/components/TableV36/TableSkeletonCell.js +3 -15
  499. package/dist/components/TableV36/actionBar.d.ts +3 -1
  500. package/dist/components/TableV36/actionBar.d.ts.map +1 -1
  501. package/dist/components/TableV36/advanceSearchModal.d.ts +3 -1
  502. package/dist/components/TableV36/advanceSearchModal.d.ts.map +1 -1
  503. package/dist/components/TableV36/index.d.ts.map +1 -1
  504. package/dist/components/TableV36/index.js +28 -138
  505. package/dist/components/TableV36/tableFunctions.d.ts.map +1 -1
  506. package/dist/components/TableV36/tableFunctions.js +44 -30
  507. package/dist/components/TableV36/tableHeader.d.ts +2 -6
  508. package/dist/components/TableV36/tableHeader.d.ts.map +1 -1
  509. package/dist/components/TableV36/tableHeader.js +16 -40
  510. package/dist/components/TableV36/tableIcons.d.ts +4 -2
  511. package/dist/components/TableV36/tableIcons.d.ts.map +1 -1
  512. package/dist/components/TableV36/tableMoreOptions.d.ts +3 -1
  513. package/dist/components/TableV36/tableMoreOptions.d.ts.map +1 -1
  514. package/dist/components/TableV36/tableMoreOptions.js +36 -18
  515. package/dist/components/TableV36/tablePagination.d.ts +3 -1
  516. package/dist/components/TableV36/tablePagination.d.ts.map +1 -1
  517. package/dist/components/TableV36/tableSettings.d.ts +3 -1
  518. package/dist/components/TableV36/tableSettings.d.ts.map +1 -1
  519. package/dist/components/TableV36/tableSettings.js +8 -9
  520. package/dist/components/TableV36/withCommentIcon.d.ts.map +1 -1
  521. package/dist/components/TableV36/withCommentIcon.js +13 -5
  522. package/dist/components/Tabs/TabPanel.d.ts +1 -1
  523. package/dist/components/Tabs/TabPanel.d.ts.map +1 -1
  524. package/dist/components/Tabs/index.d.ts +1 -1
  525. package/dist/components/Tabs/index.d.ts.map +1 -1
  526. package/dist/components/Tabs/index.js +1 -1
  527. package/dist/components/Tag/filled.d.ts +1 -1
  528. package/dist/components/Tag/filled.d.ts.map +1 -1
  529. package/dist/components/Tag/index.js +1 -1
  530. package/dist/components/Tag/solid.d.ts +1 -1
  531. package/dist/components/Tag/solid.d.ts.map +1 -1
  532. package/dist/components/Tag/stroke.d.ts +1 -1
  533. package/dist/components/Tag/stroke.d.ts.map +1 -1
  534. package/dist/components/TagGroup/index.d.ts +1 -1
  535. package/dist/components/TagGroup/index.d.ts.map +1 -1
  536. package/dist/components/TextArea/index.d.ts +1 -1
  537. package/dist/components/TextArea/index.d.ts.map +1 -1
  538. package/dist/components/TextArea/index.js +3 -3
  539. package/dist/components/ThemingPanel/AccentColorSection.d.ts +11 -0
  540. package/dist/components/ThemingPanel/AccentColorSection.d.ts.map +1 -0
  541. package/dist/components/ThemingPanel/AccentColorSection.js +45 -0
  542. package/dist/components/ThemingPanel/EnhanceContrastSection.d.ts +11 -0
  543. package/dist/components/ThemingPanel/EnhanceContrastSection.d.ts.map +1 -0
  544. package/dist/components/ThemingPanel/EnhanceContrastSection.js +42 -0
  545. package/dist/components/ThemingPanel/InterfaceThemeSection.d.ts +13 -0
  546. package/dist/components/ThemingPanel/InterfaceThemeSection.d.ts.map +1 -0
  547. package/dist/components/ThemingPanel/InterfaceThemeSection.js +118 -0
  548. package/dist/components/ThemingPanel/StylesSection.d.ts +11 -0
  549. package/dist/components/ThemingPanel/StylesSection.d.ts.map +1 -0
  550. package/dist/components/ThemingPanel/StylesSection.js +44 -0
  551. package/dist/components/ThemingPanel/ThemesTab.d.ts +23 -0
  552. package/dist/components/ThemingPanel/ThemesTab.d.ts.map +1 -0
  553. package/dist/components/ThemingPanel/ThemesTab.js +49 -0
  554. package/dist/components/ThemingPanel/ThemingPanel.d.ts +10 -0
  555. package/dist/components/ThemingPanel/ThemingPanel.d.ts.map +1 -0
  556. package/dist/components/ThemingPanel/ThemingPanel.js +233 -0
  557. package/dist/components/ThemingPanel/ThemingPanel.types.d.ts +33 -0
  558. package/dist/components/ThemingPanel/ThemingPanel.types.d.ts.map +1 -0
  559. package/dist/components/ThemingPanel/ThemingPanel.types.js +8 -0
  560. package/dist/components/ThemingPanel/index.d.ts +10 -0
  561. package/dist/components/ThemingPanel/index.d.ts.map +1 -0
  562. package/dist/components/ThemingPanel/themingPanel.constants.d.ts +24 -0
  563. package/dist/components/ThemingPanel/themingPanel.constants.d.ts.map +1 -0
  564. package/dist/components/ThemingPanel/themingPanel.constants.js +49 -0
  565. package/dist/components/Toast/index.d.ts +1 -1
  566. package/dist/components/Toast/index.d.ts.map +1 -1
  567. package/dist/components/Toast/index.js +1 -1
  568. package/dist/components/Tooltip/index.js +1 -1
  569. package/dist/components/common/DotLottiePlayer/index.d.ts +5 -0
  570. package/dist/components/common/DotLottiePlayer/index.d.ts.map +1 -0
  571. package/dist/components/common/DotLottiePlayer/index.js +9 -0
  572. package/dist/components/common/HelperText/index.d.ts +1 -1
  573. package/dist/components/common/HelperText/index.d.ts.map +1 -1
  574. package/dist/components/common/HelperText/index.js +1 -1
  575. package/dist/components/common/MentionEditor/MentionList/index.js +1 -1
  576. package/dist/components/common/MentionEditor/index.js +1 -1
  577. package/dist/components/index.d.ts +9 -0
  578. package/dist/components/index.d.ts.map +1 -1
  579. package/dist/components/index.js +48 -0
  580. package/dist/components/shared/tableColumnSettings/columnsSettingsVirtualList.d.ts +1 -1
  581. package/dist/components/shared/tableColumnSettings/columnsSettingsVirtualList.d.ts.map +1 -1
  582. package/dist/components/shared/tableColumnSettings/columnsTabV36.d.ts.map +1 -1
  583. package/dist/components/shared/tableColumnSettings/tableSettingsV36.d.ts +3 -1
  584. package/dist/components/shared/tableColumnSettings/tableSettingsV36.d.ts.map +1 -1
  585. package/dist/i18n/I18nContext.d.ts +1 -1
  586. package/dist/i18n/I18nContext.d.ts.map +1 -1
  587. package/dist/locales/de-DE.json.d.ts +45 -16
  588. package/dist/locales/de-DE.json.js +45 -15
  589. package/dist/locales/en-US.json.d.ts +45 -16
  590. package/dist/locales/en-US.json.js +45 -15
  591. package/dist/locales/es-ES.json.d.ts +45 -16
  592. package/dist/locales/es-ES.json.js +45 -15
  593. package/dist/mcp-component-registry.json +185 -128
  594. package/dist/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js +4 -4
  595. package/dist/node_modules/@impactsmartsuite/impact-icons/dist/index.js +637 -367
  596. package/dist/node_modules/@lottiefiles/dotlottie-react/dist/index.js +87 -0
  597. package/dist/node_modules/@lottiefiles/dotlottie-web/dist/index.js +1871 -0
  598. package/dist/node_modules/@mui/icons-material/utils/createSvgIcon.js +3 -3
  599. package/dist/node_modules/@mui/material/styles/ThemeProvider.js +43 -0
  600. package/dist/node_modules/@mui/private-theming/ThemeProvider/ThemeProvider.js +59 -0
  601. package/dist/node_modules/@mui/private-theming/ThemeProvider/nested.js +5 -0
  602. package/dist/node_modules/@mui/private-theming/node_modules/@mui/utils/esm/exactProp/exactProp.js +19 -0
  603. package/dist/node_modules/@mui/private-theming/useTheme/ThemeContext.js +8 -0
  604. package/dist/node_modules/@mui/private-theming/useTheme/useTheme.js +12 -0
  605. package/dist/node_modules/@mui/system/esm/DefaultPropsProvider/DefaultPropsProvider.js +12 -2
  606. package/dist/node_modules/@mui/system/esm/RtlProvider/index.js +14 -4
  607. package/dist/node_modules/@mui/system/esm/ThemeProvider/ThemeProvider.js +86 -0
  608. package/dist/node_modules/@mui/system/esm/ThemeProvider/useLayerOrder.js +50 -0
  609. package/dist/node_modules/@mui/system/esm/createStyled.js +1 -1
  610. package/dist/node_modules/@mui/system/node_modules/@mui/utils/esm/exactProp/exactProp.js +19 -0
  611. package/dist/node_modules/@mui/system/node_modules/@mui/utils/esm/useEnhancedEffect/useEnhancedEffect.js +5 -0
  612. package/dist/node_modules/@mui/system/node_modules/@mui/utils/esm/useId/useId.js +24 -0
  613. package/dist/node_modules/call-bind/index.js +3 -3
  614. package/dist/node_modules/es-abstract/2025/ToString.js +21 -0
  615. package/dist/node_modules/es-abstract-get/GetMethod.js +33 -0
  616. package/dist/node_modules/es-abstract-get/GetV.js +25 -0
  617. package/dist/node_modules/es-abstract-get/isPropertyKey.js +13 -0
  618. package/dist/node_modules/es-to-primitive/es2015.js +28 -28
  619. package/dist/node_modules/hoist-non-react-statics/node_modules/react-is/cjs/react-is.development.js +1 -1
  620. package/dist/node_modules/hoist-non-react-statics/node_modules/react-is/cjs/react-is.production.min.js +1 -1
  621. package/dist/node_modules/hoist-non-react-statics/node_modules/react-is/index.js +1 -1
  622. package/dist/node_modules/moment/dist/locale/de.js +21 -1
  623. package/dist/node_modules/moment/dist/moment.js +792 -624
  624. package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.development.js +1 -1
  625. package/dist/node_modules/react-dates/lib/theme/DefaultTheme.js +4 -4
  626. package/dist/node_modules/react-dates/lib/utils/registerCSSInterfaceWithDefaultTheme.js +3 -3
  627. package/dist/node_modules/react-dates/lib/utils/registerInterfaceWithDefaultTheme.js +3 -3
  628. package/dist/node_modules/react-is/cjs/react-is.development.js +1 -1
  629. package/dist/node_modules/react-is/cjs/react-is.production.js +1 -1
  630. package/dist/node_modules/react-with-styles/lib/ThemedStyleSheet.js +6 -6
  631. package/dist/node_modules/react-with-styles-interface-css/dist/index.js +5 -5
  632. package/dist/node_modules/react-with-styles-interface-css/dist/utils/getClassName.js +3 -3
  633. package/dist/node_modules/react-with-styles-interface-css/dist/utils/separateStyles.js +4 -4
  634. package/dist/node_modules/string.prototype.trim/implementation.js +12 -4
  635. package/dist/node_modules/stylis/src/Parser.js +1 -1
  636. package/dist/node_modules/stylis/src/Tokenizer.js +1 -1
  637. package/dist/stories/LocaleDictionaryCollapse.d.ts +1 -1
  638. package/dist/stories/LocaleDictionaryCollapse.d.ts.map +1 -1
  639. package/dist/stories/designTokensStoryHelpers.d.ts +2 -0
  640. package/dist/stories/designTokensStoryHelpers.d.ts.map +1 -0
  641. package/dist/stories/i18nDemo.d.ts +1 -1
  642. package/dist/stories/i18nDemo.d.ts.map +1 -1
  643. package/dist/stories/tableV36ChatApiMock.d.ts +79 -246
  644. package/dist/stories/tableV36ChatApiMock.d.ts.map +1 -1
  645. package/dist/styles/style.css +1 -1
  646. package/dist/styles/tokens/accent-palettes.generated.d.ts +13 -0
  647. package/dist/styles/tokens/accent-palettes.generated.d.ts.map +1 -0
  648. package/dist/styles/tokens/accent-palettes.generated.js +8 -0
  649. package/dist/styles/tokens/effects.generated.d.ts +60 -0
  650. package/dist/styles/tokens/effects.generated.d.ts.map +1 -0
  651. package/dist/styles/tokens/effects.generated.js +80 -0
  652. package/dist/styles/tokens/tokens.generated.d.ts +438 -0
  653. package/dist/styles/tokens/tokens.generated.d.ts.map +1 -0
  654. package/dist/styles/tokens/tokens.generated.js +431 -0
  655. package/dist/tokens/ImpactUiAppProviders.d.ts +18 -0
  656. package/dist/tokens/ImpactUiAppProviders.d.ts.map +1 -0
  657. package/dist/tokens/ImpactUiAppProviders.js +23 -0
  658. package/dist/tokens/ImpactUiThemeProvider.d.ts +17 -0
  659. package/dist/tokens/ImpactUiThemeProvider.d.ts.map +1 -0
  660. package/dist/tokens/ImpactUiThemeProvider.js +86 -0
  661. package/dist/tokens/accentDom.d.ts +17 -0
  662. package/dist/tokens/accentDom.d.ts.map +1 -0
  663. package/dist/tokens/accentDom.js +44 -0
  664. package/dist/tokens/accentDom.test.d.ts +2 -0
  665. package/dist/tokens/accentDom.test.d.ts.map +1 -0
  666. package/dist/tokens/contrastDom.d.ts +18 -0
  667. package/dist/tokens/contrastDom.d.ts.map +1 -0
  668. package/dist/tokens/contrastDom.js +34 -0
  669. package/dist/tokens/contrastDom.test.d.ts +2 -0
  670. package/dist/tokens/contrastDom.test.d.ts.map +1 -0
  671. package/dist/tokens/createImpactUiMuiTheme.d.ts +13 -0
  672. package/dist/tokens/createImpactUiMuiTheme.d.ts.map +1 -0
  673. package/dist/tokens/createImpactUiMuiTheme.js +122 -0
  674. package/dist/tokens/impactUiPreferences.d.ts +25 -0
  675. package/dist/tokens/impactUiPreferences.d.ts.map +1 -0
  676. package/dist/tokens/impactUiPreferences.js +109 -0
  677. package/dist/tokens/impactUiPreferences.test.d.ts +2 -0
  678. package/dist/tokens/impactUiPreferences.test.d.ts.map +1 -0
  679. package/dist/tokens/index.d.ts +22 -0
  680. package/dist/tokens/index.d.ts.map +1 -0
  681. package/dist/tokens/interfaceStyleDom.d.ts +26 -0
  682. package/dist/tokens/interfaceStyleDom.d.ts.map +1 -0
  683. package/dist/tokens/interfaceStyleDom.js +58 -0
  684. package/dist/tokens/theme.types.d.ts +19 -0
  685. package/dist/tokens/theme.types.d.ts.map +1 -0
  686. package/dist/tokens/themeDom.d.ts +34 -0
  687. package/dist/tokens/themeDom.d.ts.map +1 -0
  688. package/dist/tokens/themeDom.js +97 -0
  689. package/dist/tokens/useImpactUiInterfaceStyle.d.ts +7 -0
  690. package/dist/tokens/useImpactUiInterfaceStyle.d.ts.map +1 -0
  691. package/dist/tokens/useImpactUiInterfaceStyle.js +19 -0
  692. package/dist/tokens/useImpactUiTheme.d.ts +9 -0
  693. package/dist/tokens/useImpactUiTheme.d.ts.map +1 -0
  694. package/dist/tokens/useImpactUiTheme.js +46 -0
  695. package/package.json +12 -3
  696. package/dist/_virtual/Check.js +0 -4
  697. package/dist/components/TableChat/components/TableChatLeftSection/ChatFilterChips/ChatFilterChips.d.ts +0 -11
  698. package/dist/components/TableChat/components/TableChatLeftSection/ChatFilterChips/ChatFilterChips.d.ts.map +0 -1
  699. package/dist/components/TableChat/components/TableChatLeftSection/ChatFilterChips/ChatFilterChips.js +0 -57
  700. package/dist/components/TableChat/components/TableChatRightSection/ChatInlineEdit/ChatInlineEdit.d.ts +0 -12
  701. package/dist/components/TableChat/components/TableChatRightSection/ChatInlineEdit/ChatInlineEdit.d.ts.map +0 -1
  702. package/dist/components/TableChat/components/TableChatRightSection/ChatInlineEdit/ChatInlineEdit.js +0 -132
  703. package/dist/components/TableChat/components/TableChatRightSection/ReplyBadge/ReplyBadge.js +0 -29
  704. package/dist/components/TableV36/withChatIndicator.d.ts +0 -3
  705. package/dist/components/TableV36/withChatIndicator.d.ts.map +0 -1
  706. package/dist/components/TableV36/withChatIndicator.js +0 -89
  707. package/dist/node_modules/@mui/icons-material/Check.js +0 -17
  708. /package/dist/_virtual/{react-is.development2.js → react-is2.development.js} +0 -0
  709. /package/dist/_virtual/{react-is.production.min2.js → react-is2.production.min.js} +0 -0
  710. /package/dist/_virtual/{react-is.development3.js → react-is3.development.js} +0 -0
@@ -0,0 +1,1304 @@
1
+ const halloweenDevilLightHtml = `<!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6
+ <title>The Last Candle: Morning</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Creepster&display=swap">
10
+ <style>
11
+ html, body { margin: 0; height: 100%; background: #fff; overflow: hidden; }
12
+ canvas { display: block; }
13
+ #hint { position: fixed; inset: 0; display: grid; place-items: center; margin: 0; pointer-events: none; user-select: none;
14
+ font: 400 15px/1.5 "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif; letter-spacing: 0.05em;
15
+ color: #7f766a; transition: opacity 1.4s ease; }
16
+ #hint.gone { opacity: 0; }
17
+ </style>
18
+ <script type="importmap">
19
+ { "imports": {
20
+ "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
21
+ "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
22
+ } }
23
+ <\/script>
24
+ </head>
25
+ <body>
26
+ <p id="hint">Click anywhere to begin. Best with sound.</p>
27
+ <script type="module">
28
+ import * as THREE from 'three';
29
+ import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
30
+ import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
31
+ import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
32
+ import { BokehPass } from 'three/addons/postprocessing/BokehPass.js';
33
+ import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
34
+ import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
35
+ import { mergeGeometries, mergeVertices } from 'three/addons/utils/BufferGeometryUtils.js';
36
+
37
+ /* ==========================================================================
38
+ THE LAST CANDLE
39
+ Climax shot (designed first): camera at z 2.9, eye 1.62, 32mm-ish lens,
40
+ looking slightly up at the hooded devil dead centre, candle raised to its
41
+ face. A low morning sun back-lights the scene from the upper right; the candle
42
+ is the warm key on the hood and horns from below.
43
+
44
+ Timeline (seconds)
45
+ (story clock: the 20 s piece below plays in 18 s of video)
46
+ 0.0 - 0.6 pure white
47
+ 0.6 - 3.6 the white fades away, revealing the sunlit graveyard
48
+ 2.4 - 10.6 bats come out of the fog and take their time flying past the lens, squeaking
49
+ 0.8 - 6.5 morning sun, sky, haze and environment fade up; pumpkins kindle
50
+ 1.5 - 3.5 a lone flame appears deep in the fog beyond the gate
51
+ 2.2 - 14.4 the devil floats the length of the aisle (physical glide)
52
+ 15.0 - 16.1 it lifts the candle to its face and draws breath
53
+ 16.25- 16.9 it blows; the flame bends and gutters
54
+ 1.0 - 16.9 a small "Applying Style...." status line at the bottom centre, dots loading
55
+ 9.8 - 16.9 "Happy Halloween" burns in at the top-left corner: fire-lit letters,
56
+ a hot igniting edge, heat shimmer and rising embers
57
+ 16.9 every light hits exactly 0
58
+ 16.9 - 20.0 pure white
59
+ ========================================================================== */
60
+
61
+ const QS = new URLSearchParams(location.search), EXPORT = QS.has('export'), RENDER = QS.has('render') || EXPORT; // ?render: frame-by-frame capture; ?export: save an MP4 in the browser
62
+ const T = { revealIn: 0.8, revealFull: 6.5, devilGo: 2.2, devilArrive: 14.4,
63
+ lift0: 15.0, lift1: 16.1, blow0: 16.25, out: 16.9, end: 20.0, loop: 22.0 };
64
+ const Z_START = -31.0, Z_END = 0.4; // devil path
65
+ const CAM_Z0 = 9.0, CAM_Z1 = 2.9; // dolly path
66
+ const CAM_Y0 = 1.74, CAM_Y1 = 1.62;
67
+ const FOG_DENSITY = 0.026; // light morning haze
68
+ // light levels at full reveal (physical units: lux for the sun, candela for point lights)
69
+ const K = { sun: 3.8, hemi: 1.05, env: 0.4, candle: 1.1, pump: 0.42, ap0: 0.00025, ap1: 0.0013 };
70
+
71
+ /* ---------- deterministic randomness ---------- */
72
+ function mulberry32(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
73
+ const rng = mulberry32(31102026);
74
+ const rand = (a = 0, b = 1) => a + (b - a) * rng();
75
+ function hash1(n) { const x = Math.sin(n * 127.1 + 311.7) * 43758.5453; return x - Math.floor(x); }
76
+ function noise1(x) { const i = Math.floor(x), f = x - i, u = f * f * (3 - 2 * f); return hash1(i) * (1 - u) + hash1(i + 1) * u; }
77
+ function fbm1(x) { return 0.5 * noise1(x) + 0.3 * noise1(x * 2.03 + 7.1) + 0.2 * noise1(x * 4.11 + 3.3); }
78
+
79
+ /* ---------- easing ---------- */
80
+ const clamp = (x, a = 0, b = 1) => Math.min(b, Math.max(a, x));
81
+ const lerp = (a, b, t) => a + (b - a) * t;
82
+ const smooth = (e0, e1, x) => { const t = clamp((x - e0) / (e1 - e0)); return t * t * (3 - 2 * t); };
83
+ const smoother = (e0, e1, x) => { const t = clamp((x - e0) / (e1 - e0)); return t * t * t * (t * (t * 6 - 15) + 10); };
84
+ // long-tailed ease: very gentle start and an extremely soft landing
85
+ function easeLong(u) { u = clamp(u); const p = 2.3, a = Math.pow(u, p), b = Math.pow(1 - u, p); return a / (a + b); }
86
+ // glide profile: speed ~ u^1.6 (1-u)^2.6, integrated once (a drifting body that bleeds speed slowly)
87
+ const TRAVEL = (() => { const N = 2048, arr = new Float32Array(N + 1); let s = 0;
88
+ for (let i = 1; i <= N; i++) { const u = (i - 0.5) / N; s += Math.pow(u, 1.6) * Math.pow(1 - u, 2.6); arr[i] = s; }
89
+ for (let i = 0; i <= N; i++) arr[i] /= s; return arr; })();
90
+ function travel(u) { u = clamp(u); const f = u * 2048, i = Math.min(2047, Math.floor(f)); return lerp(TRAVEL[i], TRAVEL[i + 1], f - i); }
91
+ function devilZ(t) { return lerp(Z_START, Z_END, travel((t - T.devilGo) / (T.devilArrive - T.devilGo))); }
92
+
93
+ /* ---------- bats: a small colony bursts out of the fog and flies past the lens ----------
94
+ Shared by the picture and the sound so every squeak follows its own bat. Story-clock times. */
95
+ const BATS = (() => {
96
+ const r = mulberry32(4242), out = [];
97
+ for (let i = 0; i < 14; i++) {
98
+ const side = i % 2 ? 1 : -1, hero = i === 0; // bat 0 skims right past the lens
99
+ out.push({ t0: hero ? 6.2 : 2.4 + r() * 3.0, dur: hero ? 4.4 : 4.2 + r() * 1.6, // long, unhurried flights
100
+ a: [(r() - 0.5) * 9, 1.8 + r() * 2.8, -34 + r() * 10],
101
+ b: hero ? [0.5, 0.35] : [side * (1.3 + r() * 2.4), 0.7 + r() * 1.9],
102
+ ph: r() * 6.28, rate: 4.5 + r() * 1.5, wob: 0.3 + r() * 0.4, span: 0.52 + r() * 0.18 });
103
+ }
104
+ return out;
105
+ })();
106
+ function camAt(t) { const cu = easeLong(t / T.out); return [0, lerp(CAM_Y0, CAM_Y1, cu), lerp(CAM_Z0, CAM_Z1, cu)]; }
107
+ function batPos(bt, t) {
108
+ const u = (t - bt.t0) / bt.dur; if (u < 0 || u > 1) return null;
109
+ const c = camAt(bt.t0 + bt.dur), e = u * u * (3 - 2 * u) * 0.35 + u * 0.65;
110
+ return [lerp(bt.a[0], c[0] + bt.b[0], e) + bt.wob * Math.sin(u * 11 + bt.ph),
111
+ lerp(bt.a[1], c[1] + bt.b[1], e) + 0.6 * bt.wob * Math.sin(u * 14 + bt.ph * 2),
112
+ lerp(bt.a[2], c[2] + 2.5, e)];
113
+ }
114
+
115
+ /* ---------- sound: fully procedural, scheduled on the same timeline ----------
116
+ 0.4 - 5.5 wind rises with the reveal; a whistle threads through the trees
117
+ 2.6 a distant bell as the flame appears beyond the gate
118
+ 2.0 - 16.9 the candle hisses and crackles, louder as it nears the camera
119
+ 6.5 - 16.3 a dissonant drone gathers; the wind drains away
120
+ 8.7 the bell again
121
+ 10.6 - 15.0 a heartbeat, quickening, then stopping dead
122
+ 15.3 - 16.2 it draws breath
123
+ 16.22- 18.8 it blows the candle out: a breathy gust, the flame flutters and dies at
124
+ 16.9, and the breath carries on into the dark, trailing off
125
+ 1.5, 8.0 a ghostly, theremin-like wail drifts across the speakers
126
+ 16.9 everything else stops with the light; only the breath lingers, then silence
127
+ ------------------------------------------------------------------------- */
128
+ const sndCache = new WeakMap();
129
+ function noiseBuf(ctx, seconds, kind, seed) {
130
+ const sr = ctx.sampleRate, fade = Math.floor(0.05 * sr), n = Math.floor(seconds * sr) + fade, b = ctx.createBuffer(2, n, sr);
131
+ for (let ch = 0; ch < 2; ch++) {
132
+ const r = mulberry32(seed + ch * 7919), d = b.getChannelData(ch);
133
+ let b0 = 0, b1 = 0, b2 = 0, last = 0;
134
+ for (let i = 0; i < n; i++) {
135
+ const w = r() * 2 - 1;
136
+ if (kind === 'white') d[i] = w * 0.7;
137
+ else if (kind === 'pink') { b0 = 0.99765 * b0 + w * 0.099046; b1 = 0.963 * b1 + w * 0.2965164; b2 = 0.57 * b2 + w * 1.0526913; d[i] = (b0 + b1 + b2 + w * 0.1848) * 0.2; }
138
+ else { last = (last + 0.02 * w) / 1.02; d[i] = last * 3.2; }
139
+ }
140
+ // seamless loop: the head fades in from the tail that will precede it
141
+ for (let i = 0; i < fade; i++) { const k = i / fade; d[i] = d[i] * k + d[n - fade + i] * (1 - k); }
142
+ }
143
+ b.__loopEnd = (n - fade) / sr;
144
+ return b;
145
+ }
146
+ function impulseBuf(ctx, seconds, seed) {
147
+ const sr = ctx.sampleRate, n = Math.floor(seconds * sr), b = ctx.createBuffer(2, n, sr), pre = Math.floor(0.018 * sr);
148
+ for (let ch = 0; ch < 2; ch++) {
149
+ const r = mulberry32(seed + ch * 31), d = b.getChannelData(ch); let lp = 0;
150
+ for (let i = 0; i < n; i++) {
151
+ const x = i / n, w = r() * 2 - 1; lp += (w - lp) * (0.6 - 0.5 * x);
152
+ d[i] = i < pre ? 0 : lp * Math.pow(1 - x, 1.6) * Math.exp(-3.0 * x);
153
+ }
154
+ }
155
+ return b;
156
+ }
157
+ // The picture is authored on a 20 s story clock and plays in 18 s of video. The soundtrack keeps
158
+ // natural speed: each sound STARTS at its story moment mapped into video time (V), but plays out
159
+ // at its own real-time pace: bell decay, heartbeat tempo, wail, crackles, squeaks, the breath.
160
+ const STORY_SCALE = 20 / 18, V = s => s / STORY_SCALE;
161
+ const WHITE_BLANK = true; // morning: open on white, fade into the scene, cut to white at the end
162
+
163
+ const BAT_SQUEAK = 0.16, BAT_WINGS = 0.8;
164
+ function buildSound(ctx, t0, dest) {
165
+ const S = sndCache.get(ctx) || (() => { const c = { white: noiseBuf(ctx, 6, 'white', 101), pink: noiseBuf(ctx, 7, 'pink', 202), brown: noiseBuf(ctx, 8, 'brown', 303), ir: impulseBuf(ctx, 4.5, 404) }; sndCache.set(ctx, c); return c; })();
166
+ const R = mulberry32(1666);
167
+ const END = T.out + 0.2, END_V = V(END); // story / video
168
+ const automate = (param, a, b, fn, rate = 30) => { // a, b and fn in story time; scheduled in video time
169
+ const va = V(a), vb = V(b), n = Math.max(2, Math.ceil((vb - va) * rate)), v = new Float32Array(n);
170
+ for (let i = 0; i < n; i++) v[i] = fn((va + (vb - va) * i / (n - 1)) * STORY_SCALE);
171
+ param.value = v[0]; param.setValueCurveAtTime(v, t0 + va, vb - va);
172
+ };
173
+ const filter = (type, f, q) => { const x = ctx.createBiquadFilter(); x.type = type; x.frequency.value = f; if (q !== undefined) x.Q.value = q; return x; };
174
+
175
+ // master: everything dies on the frame the lights do
176
+ const master = ctx.createGain(); master.gain.value = 0;
177
+ master.gain.setValueAtTime(0.9, t0); master.gain.setValueAtTime(0.9, t0 + V(T.out) - 0.004); master.gain.linearRampToValueAtTime(0, t0 + V(T.out) + 0.025);
178
+ const comp = ctx.createDynamicsCompressor(); comp.threshold.value = -18; comp.knee.value = 12; comp.ratio.value = 3; comp.attack.value = 0.008; comp.release.value = 0.3;
179
+ master.connect(comp); comp.connect(dest);
180
+ const verb = ctx.createConvolver(); verb.buffer = S.ir;
181
+ const verbOut = ctx.createGain(); verbOut.gain.value = 0.5; verb.connect(filter('lowpass', 3000, 0.5)).connect(verbOut).connect(master);
182
+ const dry = ctx.createGain(); dry.connect(master);
183
+ const voice = (fn, send, rate) => { const g = ctx.createGain(); automate(g.gain, 0, T.out + 0.05, fn, rate); g.connect(dry); if (send) { const s = ctx.createGain(); s.gain.value = send; g.connect(s).connect(verb); } return g; };
184
+ const loop = (buf, offset) => { const s = ctx.createBufferSource(); s.buffer = buf; s.loop = true; s.loopEnd = buf.__loopEnd; s.start(t0, offset % (buf.__loopEnd - 0.1)); s.stop(t0 + END_V); return s; };
185
+ const osc = (type, f) => { const o = ctx.createOscillator(); o.type = type; o.frequency.value = f; o.start(t0); o.stop(t0 + END_V); return o; };
186
+
187
+ // shared curves, same functions the picture uses
188
+ const camZ = t => lerp(CAM_Z0, CAM_Z1, easeLong(t / T.out));
189
+ const near = t => { const d = Math.max(0.5, camZ(t) - devilZ(t) - 0.4); return 1 / (1 + (d / 2.6) ** 2); };
190
+ const flameLvl = t => smoother(1.5, 3.5, t) * near(t);
191
+ const windLvl = t => smoother(0.4, 5.5, t) * (0.65 + 0.7 * (fbm1(t * 0.45 + 3.1) - 0.3)) * (1 - 0.72 * smoother(10.5, 15.2, t));
192
+
193
+ // wind: low body + a thin whistle wandering left to right
194
+ { const lp = filter('lowpass', 400, 0.5); automate(lp.frequency, 0, END, t => 240 + 460 * fbm1(t * 0.45 + 3.1), 20);
195
+ loop(S.brown, 1.3).connect(lp).connect(voice(t => 0.5 * windLvl(t), 0.25, 30)); }
196
+ { const bp = filter('bandpass', 700, 7); automate(bp.frequency, 0, END, t => 420 + 900 * (fbm1(t * 0.35 + 11) - 0.2) + 160 * Math.sin(t * 0.7), 30);
197
+ const pan = ctx.createStereoPanner(); automate(pan.pan, 0, END, t => 0.65 * Math.sin(t * 0.21 + 1.0), 10);
198
+ loop(S.white, 2.2).connect(bp).connect(pan).connect(voice(t => 0.2 * windLvl(t) * smooth(0.5, 0.78, fbm1(t * 0.55 + 5)) * (1 - smoother(9.5, 13.5, t)), 0.7, 30)); }
199
+
200
+ // sub drone, then a dissonant cluster (A, B flat, E flat) that opens up as it nears
201
+ { const lp = filter('lowpass', 170, 0.7); lp.connect(voice(t => 0.2 * smoother(2.0, 9, t) + 0.14 * smoother(9, 16.2, t), 0.3, 20));
202
+ [[43.65, 'sine', 1], [43.95, 'sine', 0.8], [65.41, 'triangle', 0.4], [87.31, 'triangle', 0.25]].forEach(([f, ty, a]) => { const g = ctx.createGain(); g.gain.value = a; osc(ty, f).connect(g).connect(lp); }); }
203
+ { const lp = filter('lowpass', 300, 1.8); automate(lp.frequency, 0, END, t => 240 + 950 * smoother(7, 16.2, t) + 600 * smoother(16.25, 16.7, t), 20);
204
+ lp.connect(voice(t => 0.07 * smoother(6.5, 14.5, t) + 0.07 * smoother(15.0, 16.3, t), 0.9, 20));
205
+ const lfo = osc('sine', 4.7), depth = ctx.createGain(); depth.gain.value = 7; lfo.connect(depth);
206
+ [[110, -4, 0.5], [116.54, 3, 0.5], [155.56, -2, 0.45], [220, 5, 0.22], [233.08, -6, 0.22]].forEach(([f, det, a]) => {
207
+ const o = osc('sawtooth', f); o.detune.value = det; depth.connect(o.detune); const g = ctx.createGain(); g.gain.value = a; o.connect(g).connect(lp); }); }
208
+
209
+ // a far-off bell, mostly heard as its reverb
210
+ const bell = (tb, f, amp) => {
211
+ const lp = filter('lowpass', 2200), g = ctx.createGain(); g.gain.value = amp; lp.connect(g); g.connect(dry);
212
+ const s = ctx.createGain(); s.gain.value = 2.0; g.connect(s).connect(verb);
213
+ [[0.5, 0.35, 7], [1, 1, 5], [1.183, 0.55, 3.8], [1.506, 0.4, 3], [2.0, 0.45, 2.6], [2.514, 0.28, 2], [2.662, 0.22, 1.7], [3.011, 0.16, 1.4], [4.166, 0.08, 0.9]].forEach(([r, a, d]) => {
214
+ const o = ctx.createOscillator(); o.frequency.value = f * r; const e = ctx.createGain(); e.gain.value = 0;
215
+ e.gain.setValueAtTime(0, t0 + tb); e.gain.linearRampToValueAtTime(a, t0 + tb + 0.005); e.gain.exponentialRampToValueAtTime(0.0001, t0 + tb + d);
216
+ o.connect(e).connect(lp); o.start(t0 + tb); o.stop(t0 + Math.min(tb + d + 0.05, END_V)); });
217
+ };
218
+ bell(V(2.6), 146.83, 0.07); bell(V(8.7), 146.83, 0.055);
219
+
220
+ // heartbeat: lub-dub, quickening, stopping before the breath
221
+ { const lp = filter('lowpass', 260, 0.8); lp.connect(dry);
222
+ for (let tb = V(10.6); tb < V(15.0);) {
223
+ const k = smoother(10.6, 15.0, tb * STORY_SCALE), amp = 0.55 * (0.3 + 0.7 * k);
224
+ for (const [off, a] of [[0, 1], [0.27, 0.6]]) {
225
+ const ts = t0 + tb + off;
226
+ for (const [mul, ty, w] of [[1, 'sine', 1], [2, 'triangle', 0.35]]) {
227
+ const o = ctx.createOscillator(); o.type = ty; o.frequency.setValueAtTime(72 * mul, ts); o.frequency.exponentialRampToValueAtTime(44 * mul, ts + 0.15);
228
+ const e = ctx.createGain(); e.gain.value = 0; e.gain.setValueAtTime(0, ts); e.gain.linearRampToValueAtTime(amp * a * w, ts + 0.012); e.gain.exponentialRampToValueAtTime(0.0001, ts + 0.24);
229
+ o.connect(e).connect(lp); o.start(ts); o.stop(ts + 0.26);
230
+ }
231
+ }
232
+ tb += lerp(1.05, 0.68, k);
233
+ }
234
+ }
235
+
236
+ // candle: soft hiss with flicker, and sparse crackles
237
+ { const bp = filter('bandpass', 1100, 0.7);
238
+ loop(S.pink, 3.7).connect(bp).connect(voice(t => 0.22 * flameLvl(t) * (0.75 + 0.25 * noise1(V(t) * 14)), 0.15, 60)); }
239
+ { let tp = V(2.0);
240
+ while (tp < V(T.out) - 0.03) {
241
+ const blow = smooth(16.3, 16.6, tp * STORY_SCALE), lvl = flameLvl(tp * STORY_SCALE) * (1 + 1.5 * blow);
242
+ const dur = 0.004 + R() * 0.016, src = ctx.createBufferSource(); src.buffer = S.white;
243
+ const bp = filter('bandpass', 1800 + R() * 3200, 1.2), e = ctx.createGain(), pan = ctx.createStereoPanner(); pan.pan.value = (R() - 0.5) * 0.3;
244
+ const a = 0.9 * lvl * (0.25 + 0.75 * R() * R());
245
+ e.gain.value = 0; e.gain.setValueAtTime(0, t0 + tp); e.gain.linearRampToValueAtTime(a, t0 + tp + 0.001); e.gain.exponentialRampToValueAtTime(0.0001, t0 + tp + dur);
246
+ src.connect(bp).connect(e).connect(pan).connect(dry); src.start(t0 + tp, R() * 5); src.stop(t0 + tp + dur + 0.01);
247
+ tp += (0.08 + R() * 0.32) / (1 + 2.5 * blow);
248
+ }
249
+ }
250
+
251
+ // breath in: rising, hoarse
252
+ { const bp = filter('bandpass', 500, 1.4); automate(bp.frequency, 0, END, t => 420 + 950 * smooth(15.3, 16.15, t), 40);
253
+ const hs = filter('highshelf', 2500); hs.gain.value = 5;
254
+ loop(S.pink, 0.7).connect(bp).connect(hs).connect(voice(t => 1.1 * smooth(15.3, 16.05, t) * (1 - smooth(16.05, 16.24, t)) * (0.85 + 0.15 * noise1(V(t) * 30)), 0.35, 60)); }
255
+ // breath out: blowing the candle out. The gust is routed past the master cut, so while the
256
+ // flame's flutter and everything else stop with the light, the breath itself carries on into
257
+ // the dark and trails off, with its own bit of room.
258
+ {
259
+ const B0 = T.blow0 - 0.03, PEAK_END = 16.6, TAIL_END = T.out + 2.3;
260
+ const tail = ctx.createGain(); tail.connect(comp);
261
+ const tailVerb = ctx.createConvolver(); tailVerb.buffer = S.ir;
262
+ const tailVerbOut = ctx.createGain(); tailVerbOut.gain.value = 0.45; tailVerb.connect(filter('lowpass', 3000, 0.5)).connect(tailVerbOut).connect(comp);
263
+ tailVerbOut.gain.setValueAtTime(0.45, t0 + V(TAIL_END) - 0.15); tailVerbOut.gain.linearRampToValueAtTime(0, t0 + V(TAIL_END) + 0.45); // echo gone before the video ends
264
+ const gust = t => t < B0 ? 0 : smooth(B0, B0 + 0.1, t) * (t < PEAK_END ? 1 : Math.exp(-(t - PEAK_END) / (0.55 * STORY_SCALE)))
265
+ * (1 - smooth(TAIL_END - 0.6, TAIL_END - 0.2, t)) * (0.85 + 0.15 * noise1(V(t) * 40)); // trails ~1.7 s past the blow-out
266
+ // the breath: airy "fffhhh", losing pressure (and pitch) as it fades
267
+ const air = ctx.createBufferSource(); air.buffer = S.white; air.loop = true; air.loopEnd = S.white.__loopEnd;
268
+ const bp = filter('bandpass', 2300, 0.6); automate(bp.frequency, 0, TAIL_END, t => 2300 - 900 * smooth(16.5, 18.2, t), 30);
269
+ const g = ctx.createGain(); automate(g.gain, 0, TAIL_END, t => 0.44 * gust(t), 120); // about 4 dB softer
270
+ const send = ctx.createGain(); send.gain.value = 0.35;
271
+ air.connect(filter('highpass', 350)).connect(bp).connect(filter('lowpass', 6500)).connect(g).connect(tail); g.connect(send).connect(tailVerb);
272
+ air.start(t0, 1.7); air.stop(t0 + V(TAIL_END) + 0.05);
273
+ // a low puff as the breath leaves
274
+ const puff = ctx.createBufferSource(); puff.buffer = S.brown; puff.loop = true; puff.loopEnd = S.brown.__loopEnd;
275
+ const pg = ctx.createGain(); automate(pg.gain, 0, 17.4, t => 0.57 * smooth(B0, B0 + 0.06, t) * Math.exp(-Math.max(0, t - B0 - 0.06) / (0.25 * STORY_SCALE)), 120);
276
+ puff.connect(filter('lowpass', 260)).connect(pg).connect(tail); puff.start(t0, 4.1); puff.stop(t0 + V(17.45));
277
+ }
278
+ // the flame flutters in the gust and dies with the light (inside the master, so it stops at 16.9)
279
+ { const env = t => smooth(16.28, 16.4, t);
280
+ loop(S.pink, 2.9).connect(filter('bandpass', 750, 1.2)).connect(voice(t => 0.35 * env(t) * (0.6 + 0.4 * Math.sin(V(t) * Math.PI * 2 * 18)), 0.2, 220)); }
281
+ // bats: squeaks and wingbeats that follow each bat's flight past the lens
282
+ for (const bt of BATS) {
283
+ const R = mulberry32(Math.floor(bt.ph * 1000) + 17);
284
+ const rel = t => { const p = batPos(bt, t), c = camAt(t); return p ? [p[0] - c[0], p[1] - c[1], p[2] - c[2]] : null; };
285
+ const loud = t => { const q = rel(t); return q ? 1 / (1 + (Math.hypot(q[0], q[1], q[2]) / 3.5) ** 2) : 0; };
286
+ const panAt = t => { const q = rel(t); return q ? clamp(q[0] / (Math.abs(q[2]) * 0.6 + Math.abs(q[0]) + 0.3), -1, 1) : 0; };
287
+ for (let t = V(bt.t0) + 0.05; t < V(bt.t0 + bt.dur) - 0.05;) {
288
+ const ts = t * STORY_SCALE, f0 = 7000 + R() * 2800, d = 0.018 + R() * 0.02, a = BAT_SQUEAK * loud(ts) * (0.5 + 0.5 * R());
289
+ if (a > 0.002) {
290
+ const o = ctx.createOscillator(); o.frequency.setValueAtTime(f0, t0 + t); o.frequency.exponentialRampToValueAtTime(f0 * 0.45, t0 + t + d);
291
+ const g = ctx.createGain(); g.gain.value = 0; g.gain.setValueAtTime(0, t0 + t); g.gain.linearRampToValueAtTime(a, t0 + t + 0.002); g.gain.exponentialRampToValueAtTime(0.0001, t0 + t + d);
292
+ const p = ctx.createStereoPanner(); p.pan.value = panAt(ts);
293
+ o.connect(g).connect(p).connect(dry); o.start(t0 + t); o.stop(t0 + t + d + 0.01);
294
+ }
295
+ t += R() < 0.35 ? 0.03 + R() * 0.03 : 0.1 + R() * 0.2;
296
+ }
297
+ const n = ctx.createBufferSource(); n.buffer = S.white; n.loop = true; n.loopEnd = S.white.__loopEnd;
298
+ const g = ctx.createGain(), p = ctx.createStereoPanner();
299
+ automate(g.gain, bt.t0, bt.t0 + bt.dur, t => BAT_WINGS * loud(t) ** 1.5 * Math.pow(0.5 + 0.5 * Math.sin(2 * Math.PI * bt.rate * t + bt.ph), 3), 240);
300
+ automate(p.pan, bt.t0, bt.t0 + bt.dur, panAt, 60);
301
+ n.connect(filter('bandpass', 750, 0.9)).connect(g).connect(p).connect(dry); n.start(t0 + V(bt.t0), R() * 2); n.stop(t0 + V(bt.t0 + bt.dur) + 0.02);
302
+ }
303
+
304
+ // ghostly wail: a theremin-like voice that rises and falls with vibrato, drifting across the speakers
305
+ const voiceCurve = (t, dur, freqFn, ampFn, type, pan, lpf) => {
306
+ const n = Math.max(8, Math.ceil(dur * 120)), fq = new Float32Array(n), am = new Float32Array(n);
307
+ for (let i = 0; i < n; i++) { const u = i / (n - 1); fq[i] = freqFn(u); am[i] = ampFn(u); }
308
+ am[n - 1] = 0;
309
+ const o = ctx.createOscillator(); o.type = type; o.frequency.value = fq[0]; o.frequency.setValueCurveAtTime(fq, t0 + t, dur);
310
+ const g = ctx.createGain(); g.gain.value = 0; g.gain.setValueCurveAtTime(am, t0 + t, dur);
311
+ const p = ctx.createStereoPanner(); p.pan.setValueAtTime(pan[0], t0 + t); p.pan.linearRampToValueAtTime(pan[1], t0 + t + dur);
312
+ const send = ctx.createGain(); send.gain.value = 0.35;
313
+ o.connect(filter('lowpass', lpf)).connect(g).connect(p); p.connect(dry); p.connect(send).connect(verb);
314
+ o.start(t0 + t); o.stop(t0 + t + dur + 0.02);
315
+ };
316
+ const wail = (t, pan, k = 1) => {
317
+ const vib = u => 1 + 0.03 * Math.sin(u * 2.3 * 2 * Math.PI * 5.5), shape = u => Math.sin(Math.PI * Math.min(1, u * 1.3));
318
+ voiceCurve(t, 2.3, u => (520 + 380 * shape(u)) * vib(u), u => k * WAIL * Math.sin(Math.PI * u), 'sine', pan, 3000);
319
+ voiceCurve(t, 2.3, u => (260 + 190 * shape(u)) * vib(u), u => k * WAIL * 0.4 * Math.sin(Math.PI * u), 'triangle', pan, 1500);
320
+ };
321
+ const WAIL = 0.09;
322
+ wail(V(1.5), [0.7, -0.7]); // as the graveyard fades up, right to left
323
+ wail(V(8.0), [-0.7, 0.7], 1.7); // again in the middle, left to right (louder: the drone is up by then)
324
+ }
325
+ function wavBase64(buf) {
326
+ const ch = buf.numberOfChannels, n = buf.length, sr = buf.sampleRate, bytes = new Uint8Array(44 + n * ch * 2), v = new DataView(bytes.buffer);
327
+ const str = (o, s) => { for (let i = 0; i < s.length; i++) v.setUint8(o + i, s.charCodeAt(i)); };
328
+ str(0, 'RIFF'); v.setUint32(4, 36 + n * ch * 2, true); str(8, 'WAVE'); str(12, 'fmt '); v.setUint32(16, 16, true); v.setUint16(20, 1, true); v.setUint16(22, ch, true);
329
+ v.setUint32(24, sr, true); v.setUint32(28, sr * ch * 2, true); v.setUint16(32, ch * 2, true); v.setUint16(34, 16, true); str(36, 'data'); v.setUint32(40, n * ch * 2, true);
330
+ const data = []; for (let c = 0; c < ch; c++) data.push(buf.getChannelData(c));
331
+ let o = 44; for (let i = 0; i < n; i++) for (let c = 0; c < ch; c++) { const s = Math.max(-1, Math.min(1, data[c][i])); v.setInt16(o, s < 0 ? s * 0x8000 : s * 0x7fff, true); o += 2; }
332
+ let bin = ''; for (let i = 0; i < bytes.length; i += 0x8000) bin += String.fromCharCode.apply(null, bytes.subarray(i, i + 0x8000));
333
+ return btoa(bin);
334
+ }
335
+ async function renderSoundtrack() {
336
+ const ctx = new OfflineAudioContext(2, Math.ceil(T.end / STORY_SCALE * 48000), 48000);
337
+ buildSound(ctx, 0, ctx.destination);
338
+ return wavBase64(await ctx.startRendering());
339
+ }
340
+ /* ---------- end sound ---------- */
341
+
342
+ /* ---------- renderer ---------- */
343
+ let W = RENDER ? 1920 : innerWidth, H = RENDER ? 1080 : innerHeight;
344
+ const renderer = new THREE.WebGLRenderer({ antialias: true, powerPreference: 'high-performance', preserveDrawingBuffer: RENDER });
345
+ let pixelRatio = RENDER ? 1 : Math.min(devicePixelRatio, 1.5);
346
+ renderer.setPixelRatio(pixelRatio);
347
+ renderer.setSize(W, H);
348
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
349
+ renderer.toneMappingExposure = 1.0;
350
+ renderer.shadowMap.enabled = true;
351
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
352
+ renderer.setClearColor(0x000000, 1);
353
+ document.body.appendChild(renderer.domElement);
354
+ const maxAniso = renderer.capabilities.getMaxAnisotropy();
355
+
356
+ const scene = new THREE.Scene();
357
+ const FOG_BASE = new THREE.Color(0xb3c2d2); // pale blue morning haze
358
+ scene.fog = new THREE.FogExp2(0x000000, FOG_DENSITY);
359
+ scene.background = new THREE.Color(0x000000);
360
+ const pmrem = new THREE.PMREMGenerator(renderer);
361
+ scene.environment = pmrem.fromScene(new RoomEnvironment(), 0.04).texture;
362
+ scene.environmentIntensity = 0;
363
+
364
+ const camera = new THREE.PerspectiveCamera(32, W / H, 0.1, 100);
365
+ camera.position.set(0, CAM_Y0, CAM_Z0);
366
+
367
+ /* ---------- procedural textures (seeded, tileable) ---------- */
368
+ function tileNoise(size, cells, seed) {
369
+ const r = mulberry32(seed), g = new Float32Array(cells * cells);
370
+ for (let i = 0; i < g.length; i++) g[i] = r();
371
+ const out = new Float32Array(size * size);
372
+ for (let y = 0; y < size; y++) {
373
+ const fy = y / size * cells, iy = Math.floor(fy), ty = fy - iy, sy = ty * ty * (3 - 2 * ty), y0 = iy % cells, y1 = (iy + 1) % cells;
374
+ for (let x = 0; x < size; x++) {
375
+ const fx = x / size * cells, ix = Math.floor(fx), tx = fx - ix, sx = tx * tx * (3 - 2 * tx), x0 = ix % cells, x1 = (ix + 1) % cells;
376
+ const a = g[y0 * cells + x0], b = g[y0 * cells + x1], c = g[y1 * cells + x0], d = g[y1 * cells + x1];
377
+ out[y * size + x] = (a * (1 - sx) + b * sx) * (1 - sy) + (c * (1 - sx) + d * sx) * sy;
378
+ }
379
+ }
380
+ return out;
381
+ }
382
+ function fbmField(size, base, oct, seed) {
383
+ const acc = new Float32Array(size * size); let amp = 0.5, tot = 0;
384
+ for (let o = 0; o < oct; o++) { const n = tileNoise(size, base << o, seed + o * 101); for (let i = 0; i < acc.length; i++) acc[i] += n[i] * amp; tot += amp; amp *= 0.5; }
385
+ for (let i = 0; i < acc.length; i++) acc[i] = clamp((acc[i] / tot - 0.5) * 2.3 + 0.5);
386
+ return acc;
387
+ }
388
+ function canvasTex(size, fill, srgb, repeat = 1) {
389
+ const c = document.createElement('canvas'); c.width = c.height = size;
390
+ const ctx = c.getContext('2d'), img = ctx.createImageData(size, size);
391
+ for (let i = 0; i < size * size; i++) { const p = fill(i); img.data[i * 4] = p[0] * 255; img.data[i * 4 + 1] = p[1] * 255; img.data[i * 4 + 2] = p[2] * 255; img.data[i * 4 + 3] = 255; }
392
+ ctx.putImageData(img, 0, 0);
393
+ const t = new THREE.CanvasTexture(c);
394
+ t.wrapS = t.wrapT = THREE.RepeatWrapping; t.repeat.set(repeat, repeat);
395
+ t.colorSpace = srgb ? THREE.SRGBColorSpace : THREE.NoColorSpace; t.anisotropy = maxAniso;
396
+ return t;
397
+ }
398
+ const TS = 512;
399
+ const nA = fbmField(TS, 4, 6, 11), nB = fbmField(TS, 8, 4, 23), nC = fbmField(TS, 32, 3, 37), nD = fbmField(TS, 4, 5, 53);
400
+
401
+ const stoneMap = canvasTex(TS, i => {
402
+ const base = 0.34 + 0.2 * nA[i] + 0.07 * (nC[i] - 0.5);
403
+ let r = base, g = base * 0.985, b = base * 0.95;
404
+ const lichen = smooth(0.62, 0.85, nB[i]) * 0.38;
405
+ r = lerp(r, 0.24, lichen); g = lerp(g, 0.27, lichen); b = lerp(b, 0.15, lichen);
406
+ const pit = smooth(0.68, 0.88, nC[i]) * 0.22; return [r * (1 - pit), g * (1 - pit), b * (1 - pit)];
407
+ }, true, 1.7);
408
+ const stoneRough = canvasTex(TS, i => { const v = 0.7 + 0.28 * nB[i]; return [v, v, v]; }, false, 1.7);
409
+ const stoneBump = canvasTex(TS, i => { const v = 0.6 * nC[i] + 0.4 * nA[i]; return [v, v, v]; }, false, 1.7);
410
+ const soilMap = canvasTex(TS, i => {
411
+ const a = nD[i], c = nC[i]; let r = 0.13 + 0.07 * a, g = 0.105 + 0.055 * a, b = 0.085 + 0.04 * a;
412
+ const leaf = smooth(0.62, 0.8, nB[i]) * 0.6; r = lerp(r, 0.24, leaf); g = lerp(g, 0.17, leaf); b = lerp(b, 0.09, leaf);
413
+ const k = 0.85 + 0.3 * c; return [r * k, g * k, b * k];
414
+ }, true, 1);
415
+ soilMap.repeat.set(22, 34);
416
+ const soilBump = canvasTex(TS, i => { const v = 0.55 * nC[i] + 0.45 * nB[i]; return [v, v, v]; }, false, 1);
417
+ soilBump.repeat.set(22, 34);
418
+ const fabricBump = canvasTex(TS, i => {
419
+ const x = (i % TS) / TS; const v = 0.5 + 0.38 * Math.sin(Math.PI * 2 * (x * 11) + 3.2 * nA[i]) + 0.12 * (nC[i] - 0.5); return [v, v, v];
420
+ }, false, 1);
421
+ const waxGlow = (() => { const c = document.createElement('canvas'); c.width = 4; c.height = 128; const g = c.getContext('2d');
422
+ const gr = g.createLinearGradient(0, 128, 0, 0); gr.addColorStop(0, '#000'); gr.addColorStop(0.55, '#140802'); gr.addColorStop(0.85, '#7a3a14'); gr.addColorStop(1, '#ffd2a0');
423
+ g.fillStyle = gr; g.fillRect(0, 0, 4, 128); const t = new THREE.CanvasTexture(c); t.colorSpace = THREE.SRGBColorSpace; return t; })();
424
+ const haloTex = (() => { const c = document.createElement('canvas'); c.width = c.height = 128; const g = c.getContext('2d');
425
+ const gr = g.createRadialGradient(64, 64, 0, 64, 64, 64); gr.addColorStop(0, 'rgba(255,255,255,1)'); gr.addColorStop(0.15, 'rgba(255,255,255,0.45)');
426
+ gr.addColorStop(0.45, 'rgba(255,255,255,0.08)'); gr.addColorStop(1, 'rgba(255,255,255,0)');
427
+ g.fillStyle = gr; g.fillRect(0, 0, 128, 128); const t = new THREE.CanvasTexture(c); t.colorSpace = THREE.SRGBColorSpace; return t; })();
428
+
429
+ /* ---------- materials ---------- */
430
+ const P = o => new THREE.MeshPhysicalMaterial(o);
431
+ const stoneMats = [0xbdb8ae, 0xa8a49c, 0xc9c2b4, 0x9a9890].map((c, k) => P({
432
+ color: c, map: stoneMap, roughnessMap: stoneRough, roughness: 1.0, bumpMap: stoneBump, bumpScale: 0.5 + k * 0.1,
433
+ metalness: 0, specularIntensity: 0.35, envMapIntensity: 0.6 }));
434
+ const groundMat = P({ color: 0xffffff, vertexColors: true, map: soilMap, roughness: 0.97, bumpMap: soilBump, bumpScale: 3.0, specularIntensity: 0.25 });
435
+ const barkMat = P({ color: 0x3a322b, roughness: 0.93, bumpMap: stoneBump, bumpScale: 4.0, specularIntensity: 0.2 });
436
+ const ironMat = P({ color: 0x1d1c1b, metalness: 0.85, roughness: 0.58, envMapIntensity: 0.8 });
437
+ const grassMat = P({ color: 0xffffff, roughness: 0.85, specularIntensity: 0.3, sheen: 0.4, sheenColor: 0x8a8460, sheenRoughness: 0.6 });
438
+
439
+ /* ---------- terrain ---------- */
440
+ function groundH(x, z) {
441
+ const m = smooth(0.9, 2.4, Math.abs(x));
442
+ const h = 0.10 * Math.sin(0.33 * x + 0.21 * z) * Math.sin(0.27 * z - 0.13 * x + 1.0)
443
+ + 0.05 * Math.sin(1.13 * x + 0.6) * Math.cos(0.87 * z + 0.3) + 0.025 * Math.sin(2.7 * x + 1.9 * z);
444
+ const hill = 1.4 * smooth(-26, -70, z) * (0.6 + 0.4 * Math.sin(0.13 * x + 0.8));
445
+ return h * m - 0.015 * (1 - m) + hill;
446
+ }
447
+ {
448
+ const g = new THREE.PlaneGeometry(76, 110, 152, 220); g.rotateX(-Math.PI / 2); g.translate(0, 0, -35);
449
+ const pos = g.attributes.position, col = new Float32Array(pos.count * 3);
450
+ for (let i = 0; i < pos.count; i++) {
451
+ const x = pos.getX(i), z = pos.getZ(i); pos.setY(i, groundH(x, z));
452
+ const path = 1 - smooth(0.5, 1.6, Math.abs(x)); const damp = 0.5 + 0.5 * Math.sin(x * 0.7 + z * 0.4) * Math.sin(z * 0.23);
453
+ col[i * 3] = lerp(0.82 + 0.1 * damp, 1.18, path); col[i * 3 + 1] = lerp(0.86 + 0.08 * damp, 1.1, path); col[i * 3 + 2] = lerp(0.8, 1.02, path);
454
+ }
455
+ g.setAttribute('color', new THREE.BufferAttribute(col, 3)); g.computeVertexNormals();
456
+ const ground = new THREE.Mesh(g, groundMat); ground.receiveShadow = true; scene.add(ground);
457
+ }
458
+
459
+ /* ---------- sky dome: morning blue overhead, hazy at the horizon, warm around a low sun ---------- */
460
+ const SUN_POS = new THREE.Vector3(14, 9, -40); // low, upper right of frame, behind the monument
461
+ const sunDir = SUN_POS.clone().normalize();
462
+ const ZENITH = new THREE.Color(0x6f9ccf), SUN_TINT = new THREE.Color(0xffc283);
463
+ const skyMat = new THREE.ShaderMaterial({
464
+ side: THREE.BackSide, depthWrite: false, fog: false,
465
+ uniforms: { uFog: { value: new THREE.Color(0) }, uZenith: { value: new THREE.Color(0) }, uSunCol: { value: new THREE.Color(0) }, uSun: { value: sunDir } },
466
+ vertexShader: \`varying vec3 vDir; void main(){ vec4 w = modelMatrix*vec4(position,1.0); vDir = w.xyz - cameraPosition; gl_Position = projectionMatrix*viewMatrix*w; }\`,
467
+ fragmentShader: \`uniform vec3 uFog, uZenith, uSunCol, uSun; varying vec3 vDir;
468
+ void main(){ vec3 d = normalize(vDir); float h = d.y;
469
+ vec3 col = mix(uFog, uZenith, smoothstep(0.0, 0.55, h));
470
+ float m = max(dot(d, normalize(uSun)), 0.0);
471
+ col += uSunCol * (0.35*pow(m, 6.0) + 0.6*pow(m, 60.0)) * smoothstep(-0.1, 0.15, h); // warm glow around the sun
472
+ col += uSunCol * 4.0 * smoothstep(0.99955, 0.9998, m); // the sun's disc
473
+ gl_FragColor = vec4(col, 1.0); }\`
474
+ });
475
+ const sky = new THREE.Mesh(new THREE.SphereGeometry(85, 32, 16), skyMat); sky.renderOrder = -1; scene.add(sky);
476
+
477
+ /* ---------- tombstones ---------- */
478
+ function stoneShape(w, h, type) {
479
+ const s = new THREE.Shape(), hw = w / 2;
480
+ if (type === 0) { s.moveTo(-hw, 0); s.lineTo(hw, 0); s.lineTo(hw, h - hw); s.absarc(0, h - hw, hw, 0, Math.PI, false); s.lineTo(-hw, 0); }
481
+ else if (type === 1) { s.moveTo(-hw, 0); s.lineTo(hw, 0); s.lineTo(hw, h * 0.62); s.quadraticCurveTo(hw, h * 0.9, 0, h); s.quadraticCurveTo(-hw, h * 0.9, -hw, h * 0.62); s.lineTo(-hw, 0); }
482
+ else if (type === 2) { s.moveTo(-hw, 0); s.lineTo(hw, 0); s.lineTo(hw, h * 0.8); s.quadraticCurveTo(hw * 0.95, h * 0.88, hw * 0.58, h * 0.88);
483
+ s.quadraticCurveTo(hw * 0.25, h * 0.88, 0, h); s.quadraticCurveTo(-hw * 0.25, h * 0.88, -hw * 0.58, h * 0.88); s.quadraticCurveTo(-hw * 0.95, h * 0.88, -hw, h * 0.8); s.lineTo(-hw, 0); }
484
+ else { const a = w * 0.15, y0 = h * 0.6, y1 = y0 + 2 * a;
485
+ s.moveTo(-a, 0); s.lineTo(a, 0); s.lineTo(a, y0); s.lineTo(hw, y0); s.lineTo(hw, y1); s.lineTo(a, y1); s.lineTo(a, h); s.lineTo(-a, h); s.lineTo(-a, y1); s.lineTo(-hw, y1); s.lineTo(-hw, y0); s.lineTo(-a, y0); s.lineTo(-a, 0); }
486
+ return s;
487
+ }
488
+ const stoneGroup = new THREE.Group(); scene.add(stoneGroup);
489
+ function addTomb(x, z, scale) {
490
+ const type = rng() < 0.12 ? 3 : Math.floor(rand(0, 3)), r = rng();
491
+ const w = (type === 3 ? rand(0.55, 0.75) : rand(0.5, 0.78)) * scale, h = (type === 3 ? rand(1.0, 1.35) : rand(0.7, 1.15)) * scale, d = rand(0.1, 0.17) * scale;
492
+ const geo = new THREE.ExtrudeGeometry(stoneShape(w, h, type), { depth: d, bevelEnabled: true, bevelThickness: 0.014, bevelSize: 0.014, bevelSegments: 2, curveSegments: 18 });
493
+ geo.translate(0, 0, -d / 2);
494
+ const m = new THREE.Mesh(geo, stoneMats[Math.floor(r * 4)]);
495
+ const grp = new THREE.Group(); grp.add(m);
496
+ if (type !== 3 && rng() < 0.45) { const pl = new THREE.Mesh(new THREE.BoxGeometry(w * 1.18, 0.12 * scale, d * 2.2), m.material); pl.position.y = 0.0; m.position.y = 0.05 * scale; grp.add(pl); pl.castShadow = pl.receiveShadow = true; }
497
+ grp.position.set(x, groundH(x, z) - rand(0.03, 0.1), z);
498
+ grp.rotation.set(rand(-0.11, 0.07), rand(-0.3, 0.3) + (x > 0 ? -0.08 : 0.08), rand(-0.09, 0.09));
499
+ m.castShadow = m.receiveShadow = true; stoneGroup.add(grp);
500
+ if (rng() < 0.5) { const mound = new THREE.Mesh(new THREE.SphereGeometry(1, 20, 12, 0, Math.PI * 2, 0, Math.PI / 2), groundMat);
501
+ mound.scale.set(w * 0.62, 0.11, 0.85); mound.position.set(x + rand(-0.05, 0.05), groundH(x, z + 0.95) - 0.05, z + 0.95); mound.receiveShadow = true; scene.add(mound); }
502
+ }
503
+ function addObelisk(x, z) {
504
+ const h = rand(1.5, 2.1), w = rand(0.32, 0.4), grp = new THREE.Group(), mat = stoneMats[Math.floor(rand(0, 4))];
505
+ const base = new THREE.Mesh(new THREE.BoxGeometry(w * 1.7, 0.28, w * 1.7), mat); base.position.y = 0.1;
506
+ const shaft = new THREE.Mesh(new THREE.CylinderGeometry(w * 0.48, w * 0.68, h, 4, 1), mat); shaft.rotation.y = Math.PI / 4; shaft.position.y = 0.24 + h / 2;
507
+ const tip = new THREE.Mesh(new THREE.ConeGeometry(w * 0.48, w * 0.7, 4), mat); tip.rotation.y = Math.PI / 4; tip.position.y = 0.24 + h + w * 0.35;
508
+ [base, shaft, tip].forEach(o => { o.castShadow = o.receiveShadow = true; grp.add(o); });
509
+ grp.position.set(x, groundH(x, z) - 0.05, z); grp.rotation.set(rand(-0.04, 0.04), rand(0, 1), rand(-0.05, 0.05)); stoneGroup.add(grp);
510
+ }
511
+ for (const side of [-1, 1]) {
512
+ for (let z = 6.2; z > -40; z -= rand(2.2, 3.0)) addTomb(side * rand(1.55, 2.05), z + rand(-0.4, 0.4), rand(0.9, 1.1));
513
+ for (let z = 5.0; z > -42; z -= rand(2.4, 3.4)) addTomb(side * rand(3.0, 4.2), z + rand(-0.5, 0.5), rand(0.85, 1.15));
514
+ for (let z = 3.0; z > -44; z -= rand(2.6, 4.0)) { const x = side * rand(5.2, 8.5); if (rng() < 0.18) addObelisk(x, z); else addTomb(x, z, rand(0.9, 1.25)); }
515
+ }
516
+
517
+ /* ---------- dead trees ---------- */
518
+ function makeTree(seed, scale) {
519
+ const r = mulberry32(seed), geos = [], Y = new THREE.Vector3(0, 1, 0);
520
+ function seg(a, b, r0, r1, joint) {
521
+ const d = new THREE.Vector3().subVectors(b, a), L = d.length();
522
+ const g = new THREE.CylinderGeometry(r1, r0, L, 7, 1); g.translate(0, L / 2, 0);
523
+ g.applyQuaternion(new THREE.Quaternion().setFromUnitVectors(Y, d.normalize())); g.translate(a.x, a.y, a.z); geos.push(g);
524
+ if (joint) { const s = new THREE.SphereGeometry(r1 * 1.02, 8, 6); s.translate(b.x, b.y, b.z); geos.push(s); }
525
+ }
526
+ function branch(p, dir, len, rad, depth) {
527
+ let cur = p.clone(), d = dir.clone(), r0 = rad * (depth === 0 ? 1.7 : 1);
528
+ for (let i = 0; i < 3; i++) {
529
+ d.add(new THREE.Vector3((r() - 0.5) * 0.7, (r() - 0.45) * 0.35, (r() - 0.5) * 0.7)).normalize();
530
+ const nxt = cur.clone().addScaledVector(d, len / 3), r1 = rad * (1 - 0.5 * (i + 1) / 3);
531
+ seg(cur, nxt, r0, r1, depth < 3); cur = nxt; r0 = r1;
532
+ }
533
+ if (depth >= 5 || rad < 0.012) return;
534
+ const kids = depth < 1 ? 3 : 2 + (r() < 0.4 ? 1 : 0);
535
+ for (let k = 0; k < kids; k++) {
536
+ const nd = d.clone().add(new THREE.Vector3((r() - 0.5) * 1.7, r() * 0.7 - 0.15, (r() - 0.5) * 1.7)).normalize();
537
+ branch(cur, nd, len * (0.6 + r() * 0.16), r0 * 0.74, depth + 1);
538
+ }
539
+ }
540
+ branch(new THREE.Vector3(0, -0.3, 0), new THREE.Vector3(0, 1, 0), 3.4 * scale, 0.2 * scale, 0);
541
+ return mergeGeometries(geos);
542
+ }
543
+ [[-5.6, -13, 1.25, 7], [6.8, -19, 1.1, 19], [-8.5, -27, 1.3, 33], [4.6, -35, 1.0, 41], [9.5, -8, 0.9, 57], [-11, -6, 1.0, 71], [12, -30, 1.2, 83]]
544
+ .forEach(([x, z, s, seed]) => { const t = new THREE.Mesh(makeTree(seed, s), barkMat); t.position.set(x, groundH(x, z), z); t.rotation.y = seed; t.castShadow = true; t.receiveShadow = true; scene.add(t); });
545
+
546
+ /* ---------- gate and iron fence (where the devil comes from) ---------- */
547
+ const GATE_Z = -27;
548
+ {
549
+ const pillarMat = stoneMats[1];
550
+ for (const side of [-1, 1]) {
551
+ const pg = new THREE.Group();
552
+ const p = new THREE.Mesh(new THREE.BoxGeometry(0.5, 2.5, 0.5), pillarMat); p.position.y = 1.25;
553
+ const cap = new THREE.Mesh(new THREE.BoxGeometry(0.64, 0.14, 0.64), pillarMat); cap.position.y = 2.57;
554
+ const fin = new THREE.Mesh(new THREE.SphereGeometry(0.17, 20, 14), pillarMat); fin.position.y = 2.82;
555
+ [p, cap, fin].forEach(o => { o.castShadow = o.receiveShadow = true; pg.add(o); });
556
+ pg.position.set(side * 1.65, groundH(side * 1.65, GATE_Z), GATE_Z); scene.add(pg);
557
+ // open gate leaf, hinged at the pillar, swung toward the camera
558
+ const bars = [];
559
+ for (let i = 0; i < 8; i++) { const b = new THREE.CylinderGeometry(0.013, 0.013, 1.9, 6); b.translate(0.08 + i * 0.16, 0.98, 0); bars.push(b);
560
+ const tip = new THREE.ConeGeometry(0.03, 0.12, 6); tip.translate(0.08 + i * 0.16, 1.98, 0); bars.push(tip); }
561
+ for (const y of [0.18, 1.55, 1.8]) { const r = new THREE.BoxGeometry(1.24, 0.035, 0.035); r.translate(0.64, y, 0); bars.push(r); }
562
+ const leaf = new THREE.Mesh(mergeGeometries(bars.map(g => g.toNonIndexed())), ironMat); leaf.castShadow = true;
563
+ const hinge = new THREE.Group(); hinge.position.set(side * 1.38, groundH(side * 1.38, GATE_Z), GATE_Z + 0.02);
564
+ hinge.rotation.y = side < 0 ? -1.15 : Math.PI + 1.15; hinge.add(leaf); scene.add(hinge);
565
+ }
566
+ // arch
567
+ const arch = new THREE.Mesh(new THREE.TorusGeometry(1.4, 0.022, 8, 48, Math.PI), ironMat);
568
+ arch.position.set(0, 2.45, GATE_Z); arch.castShadow = true; scene.add(arch);
569
+ // fence
570
+ const barGeo = mergeGeometries([new THREE.CylinderGeometry(0.011, 0.011, 1.5, 5).translate(0, 0.75, 0).toNonIndexed(), new THREE.ConeGeometry(0.026, 0.1, 5).translate(0, 1.55, 0).toNonIndexed()]);
571
+ const xs = []; for (const side of [-1, 1]) for (let x = 2.0; x < 16; x += 0.15) xs.push(side * x);
572
+ const fence = new THREE.InstancedMesh(barGeo, ironMat, xs.length); const m4 = new THREE.Matrix4();
573
+ xs.forEach((x, i) => { m4.makeRotationZ((hash1(i * 3.1) - 0.5) * 0.06); m4.setPosition(x, groundH(x, GATE_Z) - 0.05, GATE_Z); fence.setMatrixAt(i, m4); });
574
+ fence.castShadow = true; scene.add(fence);
575
+ for (const side of [-1, 1]) for (const y of [0.25, 1.32]) { const r = new THREE.Mesh(new THREE.BoxGeometry(14, 0.03, 0.03), ironMat); r.position.set(side * 9, y + 0.1, GATE_Z); r.castShadow = true; scene.add(r); }
576
+ }
577
+
578
+ /* ---------- dead grass ---------- */
579
+ {
580
+ const N = 5200, blade = new THREE.ConeGeometry(0.008, 0.18, 3, 1); blade.translate(0, 0.09, 0);
581
+ const grass = new THREE.InstancedMesh(blade, grassMat, N), m4 = new THREE.Matrix4(), q = new THREE.Quaternion(), e = new THREE.Euler(), s = new THREE.Vector3(), p = new THREE.Vector3(), c = new THREE.Color();
582
+ let n = 0;
583
+ while (n < N) {
584
+ const x = rand(-13, 13), z = rand(-40, 8.5);
585
+ if (Math.abs(x) < 0.75 + rng() * 0.6) continue;
586
+ e.set(rand(-0.45, 0.45), rand(0, 6.28), rand(-0.45, 0.45)); q.setFromEuler(e);
587
+ s.set(rand(0.7, 1.3), rand(0.45, 1.5), rand(0.7, 1.3)); p.set(x, groundH(x, z) - 0.02, z);
588
+ m4.compose(p, q, s); grass.setMatrixAt(n, m4);
589
+ c.setRGB(lerp(0.14, 0.27, rng()), lerp(0.13, 0.23, rng()), lerp(0.08, 0.12, rng())); grass.setColorAt(n, c); n++;
590
+ }
591
+ grass.receiveShadow = true; scene.add(grass);
592
+ }
593
+
594
+ /* ---------- pumpkins ---------- */
595
+ const pumpkinColorDark = new THREE.Color(0x5a1e06), pumpkinColorLight = new THREE.Color(0xd9661c);
596
+ function pumpkinDeform(v) {
597
+ const th = Math.atan2(v.z, v.x), lobe = Math.pow(Math.abs(Math.cos(th * 4)), 0.5);
598
+ const rf = (1 - 0.075 * (1 - lobe)) * (1 - 0.06 * v.y * v.y);
599
+ let y = v.y * 0.72 - 0.2 * smooth(0.72, 1.0, v.y) + 0.08 * smooth(-0.8, -1.0, v.y);
600
+ return { p: new THREE.Vector3(v.x * rf, y, v.z * rf), lobe };
601
+ }
602
+ const pumpkinGeo = (() => {
603
+ let g = new THREE.SphereGeometry(1, 64, 40); g.deleteAttribute('uv'); g.deleteAttribute('normal'); g = mergeVertices(g);
604
+ const pos = g.attributes.position, col = new Float32Array(pos.count * 3), v = new THREE.Vector3(), c = new THREE.Color();
605
+ for (let i = 0; i < pos.count; i++) {
606
+ v.fromBufferAttribute(pos, i).normalize(); const d = pumpkinDeform(v); pos.setXYZ(i, d.p.x, d.p.y, d.p.z);
607
+ c.copy(pumpkinColorDark).lerp(pumpkinColorLight, Math.pow(d.lobe, 1.6) * (0.75 + 0.25 * (1 - Math.abs(v.y))));
608
+ col[i * 3] = c.r; col[i * 3 + 1] = c.g; col[i * 3 + 2] = c.b;
609
+ }
610
+ g.setAttribute('color', new THREE.BufferAttribute(col, 3)); g.computeVertexNormals(); return g;
611
+ })();
612
+ const pumpkinMat = P({ color: 0xffffff, vertexColors: true, roughness: 0.52, clearcoat: 0.35, clearcoatRoughness: 0.45, sheen: 0.3, sheenColor: 0xffa060, specularIntensity: 0.6 });
613
+ const stemMat = P({ color: 0x4a4426, roughness: 0.82, bumpMap: stoneBump, bumpScale: 3 });
614
+ function subdivide(geo, times) {
615
+ let g = geo.index ? geo.toNonIndexed() : geo;
616
+ for (let k = 0; k < times; k++) {
617
+ const a = g.attributes.position.array, out = [];
618
+ for (let i = 0; i < a.length; i += 9) {
619
+ const A = [a[i], a[i + 1], a[i + 2]], B = [a[i + 3], a[i + 4], a[i + 5]], C = [a[i + 6], a[i + 7], a[i + 8]];
620
+ const mid = (p, q) => [(p[0] + q[0]) / 2, (p[1] + q[1]) / 2, (p[2] + q[2]) / 2];
621
+ const ab = mid(A, B), bc = mid(B, C), ca = mid(C, A);
622
+ out.push(...A, ...ab, ...ca, ...ab, ...B, ...bc, ...ca, ...bc, ...C, ...ab, ...bc, ...ca);
623
+ }
624
+ g = new THREE.BufferGeometry(); g.setAttribute('position', new THREE.Float32BufferAttribute(out, 3));
625
+ }
626
+ return g;
627
+ }
628
+ const faceGeo = (() => {
629
+ const shapes = [];
630
+ const tri = pts => { const s = new THREE.Shape(); s.moveTo(...pts[0]); pts.slice(1).forEach(p => s.lineTo(...p)); s.closePath(); return s; };
631
+ shapes.push(tri([[0.12, 0.08], [0.42, 0.17], [0.25, 0.38]]), tri([[-0.12, 0.08], [-0.25, 0.38], [-0.42, 0.17]]), tri([[-0.06, -0.03], [0.06, -0.03], [0, 0.07]]));
632
+ const yu = x => -0.1 - 0.1 * (1 - (x / 0.5) ** 2), yl = x => -0.14 - 0.26 * (1 - (x / 0.5) ** 2);
633
+ const m = new THREE.Shape(); m.moveTo(-0.5, yu(-0.5));
634
+ for (let x = -0.45; x <= 0.451; x += 0.05) { const xr = Math.round(x * 100) / 100;
635
+ if (xr === -0.05) { m.lineTo(-0.05, yl(-0.05)); m.lineTo(-0.05, yl(-0.05) + 0.08); m.lineTo(0.05, yl(0.05) + 0.08); m.lineTo(0.05, yl(0.05)); continue; }
636
+ if (xr === 0 || xr === 0.05) continue; m.lineTo(xr, yl(xr)); }
637
+ m.lineTo(0.5, yu(0.5));
638
+ for (let x = 0.45; x >= -0.451; x -= 0.05) { const xr = Math.round(x * 100) / 100;
639
+ if (xr === 0.22) { m.lineTo(0.22, yu(0.22)); m.lineTo(0.22, yu(0.22) - 0.08); m.lineTo(0.12, yu(0.12) - 0.08); m.lineTo(0.12, yu(0.12)); continue; }
640
+ if (xr === -0.12) { m.lineTo(-0.12, yu(-0.12)); m.lineTo(-0.12, yu(-0.12) - 0.08); m.lineTo(-0.22, yu(-0.22) - 0.08); m.lineTo(-0.22, yu(-0.22)); continue; }
641
+ if ((xr > 0.12 && xr < 0.22) || (xr > -0.22 && xr < -0.12)) continue; m.lineTo(xr, yu(xr)); }
642
+ m.closePath(); shapes.push(m);
643
+ const flat = subdivide(new THREE.ShapeGeometry(shapes, 1), 3), pos = flat.attributes.position;
644
+ const col = new Float32Array(pos.count * 3), v = new THREE.Vector3();
645
+ for (let i = 0; i < pos.count; i++) {
646
+ const x = pos.getX(i), y = pos.getY(i); v.set(x, y, Math.sqrt(Math.max(0, 1 - x * x - y * y))).normalize();
647
+ const d = pumpkinDeform(v); d.p.addScaledVector(v, 0.014); pos.setXYZ(i, d.p.x, d.p.y, d.p.z);
648
+ const k = 0.55 + 0.45 * smooth(0.55, 0.0, Math.hypot(x * 0.8, y + 0.05)); col[i * 3] = k; col[i * 3 + 1] = k * k; col[i * 3 + 2] = k * k * k;
649
+ }
650
+ flat.setAttribute('color', new THREE.BufferAttribute(col, 3)); return flat;
651
+ })();
652
+ const pumpkins = [];
653
+ function addPumpkin(x, z, r, carved, withLight) {
654
+ const g = new THREE.Group(), body = new THREE.Mesh(pumpkinGeo, pumpkinMat); body.castShadow = body.receiveShadow = true; g.add(body);
655
+ const st = new THREE.CylinderGeometry(0.045, 0.08, 0.26, 7, 5); const sp = st.attributes.position;
656
+ for (let i = 0; i < sp.count; i++) { const yy = sp.getY(i) + 0.13; sp.setX(i, sp.getX(i) + 0.1 * yy * yy); } st.computeVertexNormals();
657
+ const stem = new THREE.Mesh(st, stemMat); stem.position.y = 0.58; stem.rotation.y = rand(0, 6); stem.castShadow = true; g.add(stem);
658
+ let face = null, faceMat = null, light = null;
659
+ if (carved) {
660
+ faceMat = new THREE.MeshBasicMaterial({ color: 0x000000, vertexColors: true, polygonOffset: true, polygonOffsetFactor: -2, polygonOffsetUnits: -2 });
661
+ face = new THREE.Mesh(faceGeo, faceMat); g.add(face);
662
+ if (withLight) { light = new THREE.PointLight(0xff7a2a, 0, 5, 2); light.position.set(0, 0.25, 0.55); g.add(light); }
663
+ }
664
+ g.scale.setScalar(r); g.position.set(x, groundH(x, z) + r * 0.62, z);
665
+ g.rotation.y = Math.atan2(0 - x, 3.0 - z) + rand(-0.18, 0.18); g.rotation.z = rand(-0.08, 0.08);
666
+ scene.add(g); pumpkins.push({ g, faceMat, light, seed: pumpkins.length * 13.7 + 2.1 });
667
+ }
668
+ addPumpkin(-0.98, -1.35, 0.3, true, true);
669
+ addPumpkin(1.18, -2.75, 0.34, true, true);
670
+ addPumpkin(1.42, -2.25, 0.2, false);
671
+ addPumpkin(-1.38, 4.6, 0.26, true, true);
672
+ addPumpkin(-2.4, 2.1, 0.22, false);
673
+ addPumpkin(1.55, -6.6, 0.27, true, false);
674
+ addPumpkin(-1.75, -11.2, 0.3, true, false);
675
+ addPumpkin(2.6, -8.4, 0.24, false);
676
+ addPumpkin(1.6, -17.5, 0.28, true, false);
677
+ addPumpkin(-2.9, -3.8, 0.2, false);
678
+
679
+ /* ---------- ground mist (soft sheets, never in the dolly path) ---------- */
680
+ const mistUniforms = { uTime: { value: 0 }, uColor: { value: new THREE.Color(0) }, uCandlePos: { value: new THREE.Vector3() },
681
+ uCandleCol: { value: new THREE.Color(1.0, 0.5, 0.18) }, uCandleI: { value: 0 }, uCam: { value: new THREE.Vector3() }, uFogDensity: { value: FOG_DENSITY } };
682
+ function mistMaterial(vertical, opacity) {
683
+ return new THREE.ShaderMaterial({
684
+ transparent: true, depthWrite: false, fog: false, side: THREE.DoubleSide,
685
+ uniforms: { ...mistUniforms, uVertical: { value: vertical ? 1 : 0 }, uOpacity: { value: opacity } },
686
+ vertexShader: \`varying vec3 vW; void main(){ vec4 w = modelMatrix*vec4(position,1.0); vW = w.xyz; gl_Position = projectionMatrix*viewMatrix*w; }\`,
687
+ fragmentShader: \`
688
+ uniform float uTime, uOpacity, uFogDensity, uVertical, uCandleI; uniform vec3 uColor, uCandlePos, uCandleCol, uCam; varying vec3 vW;
689
+ float hash(vec2 p){ p = fract(p*vec2(123.34,456.21)); p += dot(p, p+45.32); return fract(p.x*p.y); }
690
+ float vn(vec2 p){ vec2 i = floor(p), f = fract(p), u = f*f*(3.0-2.0*f);
691
+ return mix(mix(hash(i), hash(i+vec2(1,0)), u.x), mix(hash(i+vec2(0,1)), hash(i+vec2(1,1)), u.x), u.y); }
692
+ float fbm(vec2 p){ float a = 0.5, s = 0.0; for(int i=0;i<4;i++){ s += a*vn(p); p = p*2.03 + vec2(1.7,9.2); a *= 0.5; } return s; }
693
+ void main(){
694
+ vec2 q = uVertical > 0.5 ? vec2(vW.x*0.32 + uTime*0.05, vW.y*0.75 - uTime*0.012) : vec2(vW.x*0.22 + uTime*0.04, vW.z*0.2 + uTime*0.025);
695
+ float n = fbm(q + 1.3*fbm(q*1.6 - uTime*0.03));
696
+ float a = smoothstep(0.38, 0.86, n) * uOpacity;
697
+ if (uVertical > 0.5) { a *= smoothstep(0.0, 0.6, vW.y) * smoothstep(3.0, 1.1, vW.y) * smoothstep(13.0, 5.0, abs(vW.x)); }
698
+ else { a *= smoothstep(15.0, 4.0, abs(vW.x)); }
699
+ float dc = distance(uCam, vW); a *= smoothstep(0.9, 3.5, dc);
700
+ float fogF = 1.0 - exp(-pow(uFogDensity*dc, 2.0));
701
+ float dl = distance(vW, uCandlePos); float w = uCandleI / (0.3 + dl*dl);
702
+ vec3 col = uColor + uCandleCol * w * 0.22;
703
+ a = a * (1.0 - 0.75*fogF) * (1.0 + min(w, 3.0)*0.35);
704
+ gl_FragColor = vec4(col, clamp(a, 0.0, 1.0));
705
+ }\`
706
+ });
707
+ }
708
+ const mistGroup = new THREE.Group(); scene.add(mistGroup);
709
+ {
710
+ const h1 = new THREE.Mesh(new THREE.PlaneGeometry(36, 66), mistMaterial(false, 0.55)); h1.rotation.x = -Math.PI / 2; h1.position.set(0, 0.2, -24); mistGroup.add(h1);
711
+ const h2 = new THREE.Mesh(new THREE.PlaneGeometry(36, 60), mistMaterial(false, 0.3)); h2.rotation.x = -Math.PI / 2; h2.position.set(0, 0.55, -27); mistGroup.add(h2);
712
+ for (const z of [-3.5, -9, -15.5, -22.5]) { const v = new THREE.Mesh(new THREE.PlaneGeometry(26, 3.2), mistMaterial(true, 0.5)); v.position.set(0, 1.5, z); mistGroup.add(v); }
713
+ }
714
+
715
+ /* ==========================================================================
716
+ THE DEVIL
717
+ ========================================================================== */
718
+ const U = { time: { value: 0 }, drag: { value: 0 }, flutter: { value: 1 } };
719
+ const devil = new THREE.Group(); devil.scale.setScalar(0.9); scene.add(devil);
720
+ const body = new THREE.Group(); body.position.y = 1.1; devil.add(body);
721
+ const parts = new THREE.Group(); parts.position.y = -1.1; body.add(parts);
722
+
723
+ const clothMat = P({ color: 0x1a0a0b, roughness: 0.88, sheen: 0.55, sheenColor: 0x5e2a22, sheenRoughness: 0.55,
724
+ bumpMap: fabricBump, bumpScale: 1.6, specularIntensity: 0.4, envMapIntensity: 0.7 });
725
+ const robeMat = clothMat.clone(); robeMat.transparent = true;
726
+ robeMat.onBeforeCompile = sh => {
727
+ sh.uniforms.uTime = U.time; sh.uniforms.uDrag = U.drag; sh.uniforms.uFlutter = U.flutter;
728
+ sh.vertexShader = 'attribute float aW; attribute float aPhi; attribute float aFade; uniform float uTime, uDrag, uFlutter; varying float vFade;\\n' +
729
+ sh.vertexShader.replace('#include <begin_vertex>', \`#include <begin_vertex>
730
+ float w2 = aW*aW;
731
+ float wave = sin(position.y*7.0 - uTime*2.2 + aPhi*3.0) + 0.6*sin(position.y*13.0 - uTime*3.6 + aPhi*5.0 + 1.3);
732
+ transformed.xz += normalize(position.xz + 1e-4) * wave * 0.035 * w2 * uFlutter;
733
+ transformed.x += sin(uTime*1.7 + aPhi*2.0 + position.y*4.0) * 0.02 * w2;
734
+ transformed.z -= uDrag * (aW*0.22 + w2*0.3);
735
+ transformed.y += uDrag * w2 * 0.12;
736
+ vFade = aFade;\`);
737
+ sh.fragmentShader = 'varying float vFade;\\n' + sh.fragmentShader.replace('#include <alphamap_fragment>', '#include <alphamap_fragment>\\n diffuseColor.a *= vFade;');
738
+ };
739
+ robeMat.customProgramCacheKey = () => 'ghost-robe';
740
+
741
+ // robe: lathe from a smooth profile, then tattered hem
742
+ {
743
+ const prof = [[0.44, 0.0], [0.4, 0.14], [0.36, 0.32], [0.32, 0.56], [0.29, 0.8], [0.28, 1.0], [0.295, 1.18], [0.315, 1.32], [0.3, 1.42], [0.25, 1.5], [0.17, 1.58], [0.1, 1.64], [0.02, 1.67]];
744
+ const curve = new THREE.CatmullRomCurve3(prof.map(([r, y]) => new THREE.Vector3(r, y, 0)));
745
+ const pts = curve.getPoints(64).map(p => new THREE.Vector2(Math.max(0.01, p.x), p.y));
746
+ const g = new THREE.LatheGeometry(pts, 112, Math.PI, Math.PI * 2);
747
+ const pos = g.attributes.position, n = pos.count, aW = new Float32Array(n), aPhi = new Float32Array(n), aFade = new Float32Array(n);
748
+ for (let i = 0; i < n; i++) {
749
+ let x = pos.getX(i), y = pos.getY(i), z = pos.getZ(i); const phi = Math.atan2(x, z);
750
+ const w = smooth(0.6, 0.0, y);
751
+ const nn = 0.5 * (0.5 + 0.5 * Math.sin(phi * 7 + 0.4)) + 0.3 * (0.5 + 0.5 * Math.sin(phi * 13 + 2.1)) + 0.2 * (0.5 + 0.5 * Math.sin(phi * 23 + 0.7));
752
+ y -= w * w * 0.34 * Math.pow(nn, 2.4); const shrink = 1 - 0.16 * w * w * nn; x *= shrink; z *= shrink;
753
+ x *= 1 + 0.12 * smooth(1.0, 1.4, y) * smooth(1.62, 1.45, y); z *= 0.84;
754
+ pos.setXYZ(i, x, y, z); aW[i] = w; aPhi[i] = phi; aFade[i] = smooth(-0.3, 0.55, y);
755
+ }
756
+ g.setAttribute('aW', new THREE.BufferAttribute(aW, 1)); g.setAttribute('aPhi', new THREE.BufferAttribute(aPhi, 1)); g.setAttribute('aFade', new THREE.BufferAttribute(aFade, 1));
757
+ g.computeVertexNormals();
758
+ var robe = new THREE.Mesh(g, robeMat); robe.castShadow = true; robe.receiveShadow = true; parts.add(robe);
759
+ }
760
+
761
+ // hood, void, eyes, horns
762
+ const head = new THREE.Group(); head.position.set(0, 1.76, 0); parts.add(head);
763
+ {
764
+ const g = new THREE.SphereGeometry(0.2, 56, 40); g.rotateY(-Math.PI / 2);
765
+ const pos = g.attributes.position, v = new THREE.Vector3();
766
+ for (let i = 0; i < pos.count; i++) {
767
+ v.fromBufferAttribute(pos, i); const ny = v.y / 0.2, nz = v.z / 0.2;
768
+ const peak = Math.pow(Math.max(0, ny * 0.75 - nz * 0.25), 3.5);
769
+ v.z *= 1.12; v.y += 0.085 * peak; v.z -= 0.06 * peak; v.x *= 1 - 0.1 * peak;
770
+ pos.setXYZ(i, v.x, v.y, v.z);
771
+ }
772
+ g.computeVertexNormals();
773
+ const hood = new THREE.Mesh(g, clothMat); hood.castShadow = hood.receiveShadow = true; head.add(hood);
774
+ const voidMat = new THREE.MeshBasicMaterial({ color: 0x000000 });
775
+ const face = new THREE.Mesh(new THREE.SphereGeometry(1, 40, 28), voidMat); face.scale.set(0.108, 0.138, 0.075); face.position.set(0, -0.015, 0.165); head.add(face);
776
+ }
777
+ const eyeMat = new THREE.MeshBasicMaterial({ color: 0x000000 });
778
+ for (const s of [-1, 1]) {
779
+ const e = new THREE.Mesh(new THREE.SphereGeometry(1, 16, 10), eyeMat); e.scale.set(0.017, 0.0075, 0.006);
780
+ e.position.set(s * 0.04, -0.0, 0.237); e.rotation.z = s * -0.38; head.add(e);
781
+ }
782
+ const hornMat = P({ color: 0xffffff, vertexColors: true, roughness: 0.36, clearcoat: 0.6, clearcoatRoughness: 0.28, specularIntensity: 0.7, bumpMap: stoneBump, bumpScale: 0.8 });
783
+ for (const s of [-1, 1]) {
784
+ const path = new THREE.CatmullRomCurve3([[0.1, 0.08, 0.03], [0.19, 0.14, 0.01], [0.245, 0.25, -0.03], [0.225, 0.37, -0.055], [0.165, 0.445, -0.03]].map(p => new THREE.Vector3(s * p[0], p[1], p[2])));
785
+ const segs = 48, rad = 14, g = new THREE.TubeGeometry(path, segs, 1, rad, false);
786
+ const pos = g.attributes.position, col = new Float32Array(pos.count * 3), P0 = new THREE.Vector3(), v = new THREE.Vector3();
787
+ for (let i = 0; i <= segs; i++) {
788
+ const t = i / segs; path.getPointAt(t, P0);
789
+ const r = (0.036 * Math.pow(1 - t, 0.85) + 0.0015) * (1 + 0.07 * Math.sin(t * 46) * (1 - t));
790
+ const c0 = [0.46, 0.37, 0.27], c1 = [0.03, 0.02, 0.02], k = Math.pow(t, 0.8);
791
+ for (let j = 0; j <= rad; j++) { const idx = i * (rad + 1) + j; v.fromBufferAttribute(pos, idx).sub(P0).multiplyScalar(r).add(P0); pos.setXYZ(idx, v.x, v.y, v.z);
792
+ col[idx * 3] = lerp(c0[0], c1[0], k); col[idx * 3 + 1] = lerp(c0[1], c1[1], k); col[idx * 3 + 2] = lerp(c0[2], c1[2], k); }
793
+ }
794
+ g.setAttribute('color', new THREE.BufferAttribute(col, 3)); g.computeVertexNormals();
795
+ const horn = new THREE.Mesh(g, hornMat); horn.castShadow = true; head.add(horn);
796
+ }
797
+
798
+ // sleeves and hands
799
+ function sleeveGeometry(r0, r1, billow) { const g = new THREE.CylinderGeometry(r1, r0, 1, 24, 8, true); g.translate(0, 0.5, 0);
800
+ const pos = g.attributes.position;
801
+ for (let i = 0; i < pos.count; i++) { const y = pos.getY(i), k = 1 + billow * Math.sin(Math.PI * y) * (1 - smooth(0.85, 1.0, y)); pos.setX(i, pos.getX(i) * k); pos.setZ(i, pos.getZ(i) * k); }
802
+ g.computeVertexNormals(); return g; }
803
+ const upperGeo = sleeveGeometry(0.085, 0.08, 0.12), foreGeo = sleeveGeometry(0.072, 0.098, 0.1);
804
+ const sleeveMat = clothMat.clone(); sleeveMat.side = THREE.DoubleSide;
805
+ const skinMat = P({ color: 0x5f6b67, roughness: 0.55, sheen: 0.4, sheenColor: 0x9fb0aa, sheenRoughness: 0.5, specularIntensity: 0.5, clearcoat: 0.15 });
806
+ const clawMat = P({ color: 0x120c0a, roughness: 0.3, clearcoat: 0.8 });
807
+ const SHOULDERS = [new THREE.Vector3(-0.25, 1.43, 0.03), new THREE.Vector3(0.25, 1.43, 0.03)];
808
+ const sleeves = [], hands = [], elbows = [];
809
+ const elbowGeo = new THREE.SphereGeometry(0.084, 20, 14);
810
+ for (const s of [-1, 1]) {
811
+ const up = new THREE.Mesh(upperGeo, sleeveMat), fo = new THREE.Mesh(foreGeo, sleeveMat), el = new THREE.Mesh(elbowGeo, clothMat);
812
+ [up, fo, el].forEach(o => { o.castShadow = o.receiveShadow = true; parts.add(o); }); sleeves.push([up, fo]); elbows.push(el);
813
+ const hand = new THREE.Group();
814
+ const palm = new THREE.Mesh(new THREE.SphereGeometry(1, 20, 14), skinMat); palm.scale.set(0.034, 0.02, 0.048); palm.position.set(0, 0, 0.03); hand.add(palm);
815
+ for (let f = 0; f < 4; f++) {
816
+ const fx = (f - 1.5) * 0.015, len = 0.032 - Math.abs(f - 1.5) * 0.004;
817
+ const prox = new THREE.Mesh(new THREE.CapsuleGeometry(0.0075, len, 4, 8), skinMat); prox.rotation.x = Math.PI / 2 - 0.25; prox.position.set(fx, 0.004, 0.07 + len * 0.3); hand.add(prox);
818
+ const dist = new THREE.Mesh(new THREE.CapsuleGeometry(0.0065, len * 0.9, 4, 8), skinMat); dist.rotation.x = Math.PI / 2 - 1.3; dist.position.set(fx, 0.02, 0.093 + len * 0.45); hand.add(dist);
819
+ const claw = new THREE.Mesh(new THREE.ConeGeometry(0.0055, 0.018, 6), clawMat); claw.rotation.x = -0.35; claw.position.set(fx, 0.04, 0.099 + len * 0.5); hand.add(claw);
820
+ }
821
+ hand.traverse(o => { if (o.isMesh) o.castShadow = true; });
822
+ hand.rotation.set(0.15, -s * 1.15, s * 0.25); parts.add(hand); hands.push(hand);
823
+ }
824
+
825
+ // candle rig
826
+ const candleRig = new THREE.Group(); parts.add(candleRig);
827
+ const brassMat = P({ color: 0x7a5a36, metalness: 1.0, roughness: 0.4, clearcoat: 0.2, envMapIntensity: 1.0, bumpMap: stoneBump, bumpScale: 0.5 });
828
+ const waxMat = P({ color: 0xe9dcc2, roughness: 0.48, sheen: 0.5, sheenColor: 0xffd6a0, emissive: 0xff8a3a, emissiveMap: waxGlow, emissiveIntensity: 0, specularIntensity: 0.5 });
829
+ {
830
+ const dish = new THREE.Mesh(new THREE.LatheGeometry([[0.0, 0.0], [0.06, 0.0], [0.074, 0.008], [0.08, 0.019], [0.077, 0.021], [0.07, 0.012], [0.03, 0.009], [0.028, 0.03], [0.024, 0.031], [0.022, 0.012], [0.0, 0.012]].map(p => new THREE.Vector2(...p)), 48), brassMat);
831
+ dish.castShadow = dish.receiveShadow = true; candleRig.add(dish);
832
+ const ring = new THREE.Mesh(new THREE.TorusGeometry(0.022, 0.0045, 8, 24), brassMat); ring.position.set(0.09, 0.012, 0); ring.rotation.y = Math.PI / 2; candleRig.add(ring);
833
+ const cg = new THREE.CylinderGeometry(0.021, 0.023, 0.12, 28, 6); const cp = cg.attributes.position;
834
+ for (let i = 0; i < cp.count; i++) { const y = cp.getY(i), r = Math.hypot(cp.getX(i), cp.getZ(i)); if (y > 0.059 && r < 0.012) cp.setY(i, y - 0.008); }
835
+ cg.computeVertexNormals();
836
+ const candle = new THREE.Mesh(cg, waxMat); candle.position.y = 0.012 + 0.06; candle.castShadow = true; candle.receiveShadow = true; candleRig.add(candle);
837
+ for (let k = 0; k < 5; k++) { const a = k * 1.3 + 0.4, l = 0.012 + hash1(k) * 0.03;
838
+ const d = new THREE.Mesh(new THREE.CapsuleGeometry(0.0042, l, 4, 8), waxMat); d.position.set(Math.cos(a) * 0.022, 0.13 - l / 2 - 0.004, Math.sin(a) * 0.022); candleRig.add(d); }
839
+ const pool = new THREE.Mesh(new THREE.SphereGeometry(1, 20, 10), waxMat); pool.scale.set(0.034, 0.006, 0.032); pool.position.y = 0.012; candleRig.add(pool);
840
+ const wick = new THREE.Mesh(new THREE.CylinderGeometry(0.0016, 0.0018, 0.014, 6), new THREE.MeshPhysicalMaterial({ color: 0x0b0806, roughness: 0.9 }));
841
+ wick.position.set(0, 0.131, 0); wick.rotation.z = 0.12; candleRig.add(wick);
842
+ }
843
+ const FLAME_BASE = new THREE.Vector3(0, 0.137, 0);
844
+ const flameMat = new THREE.ShaderMaterial({
845
+ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, fog: false,
846
+ uniforms: { uTime: { value: 0 }, uBend: { value: new THREE.Vector3() }, uLife: { value: 0 }, uStretch: { value: 1 }, uFogDensity: { value: FOG_DENSITY } },
847
+ vertexShader: \`uniform float uTime, uStretch; uniform vec3 uBend; varying float vH; varying vec3 vN; varying vec3 vV; varying float vD;
848
+ void main(){ vec3 p = position; float h = p.y; vH = h;
849
+ float fl = sin(uTime*17.0 + h*5.0)*0.5 + sin(uTime*23.0 + 1.7)*0.3 + sin(uTime*9.0 + h*2.0)*0.4;
850
+ p.x += fl*0.07*h*h; p.z += cos(uTime*13.0 + h*4.0)*0.05*h*h;
851
+ p.y *= uStretch*(1.0 + 0.06*sin(uTime*21.0));
852
+ p += uBend*h*h;
853
+ vec4 mv = modelViewMatrix*vec4(p,1.0); vN = normalize(normalMatrix*normal); vV = normalize(-mv.xyz); vD = -mv.z;
854
+ gl_Position = projectionMatrix*mv; }\`,
855
+ fragmentShader: \`uniform float uLife, uFogDensity; varying float vH; varying vec3 vN; varying vec3 vV; varying float vD;
856
+ void main(){ float f = abs(dot(normalize(vN), normalize(vV))); float core = pow(f, 2.6);
857
+ vec3 blue = vec3(0.12, 0.22, 1.1), orange = vec3(2.4, 0.8, 0.14), white = vec3(4.2, 3.1, 1.7);
858
+ vec3 col = mix(orange, white, core*smoothstep(0.95, 0.2, vH));
859
+ col = mix(col, blue, smoothstep(0.22, 0.0, vH)*0.75*(1.0 - core));
860
+ float a = pow(f, 1.2)*smoothstep(1.0, 0.55, vH)*smoothstep(0.0, 0.06, vH);
861
+ float fogF = exp(-pow(uFogDensity*0.5*vD, 2.0));
862
+ gl_FragColor = vec4(col*a*uLife*fogF, 1.0); }\`
863
+ });
864
+ const flame = (() => { const pts = []; for (let i = 0; i <= 28; i++) { const y = i / 28; pts.push(new THREE.Vector2(0.4 * Math.sin(Math.PI * Math.pow(y, 0.55)) * Math.pow(1 - y, 0.35) + 0.0005, y)); }
865
+ const m = new THREE.Mesh(new THREE.LatheGeometry(pts, 28), flameMat); m.scale.set(0.042, 0.064, 0.042); m.position.copy(FLAME_BASE); m.frustumCulled = false; return m; })();
866
+ candleRig.add(flame);
867
+ const halo = new THREE.Sprite(new THREE.SpriteMaterial({ map: haloTex, color: 0xff9a50, blending: THREE.AdditiveBlending, transparent: true, depthWrite: false, fog: false, opacity: 0 }));
868
+ halo.position.copy(FLAME_BASE).add(new THREE.Vector3(0, 0.03, 0)); halo.scale.setScalar(0.85); candleRig.add(halo);
869
+ const candleLight = new THREE.PointLight(0xff9548, 0, 0, 2);
870
+ candleLight.position.copy(FLAME_BASE).add(new THREE.Vector3(0, 0.028, 0));
871
+ candleLight.castShadow = true; candleLight.shadow.mapSize.set(512, 512);
872
+ candleLight.shadow.camera.near = 0.03; candleLight.shadow.camera.far = 14; candleLight.shadow.bias = -0.0025; candleLight.shadow.normalBias = 0.018;
873
+ candleRig.add(candleLight);
874
+ const flameAnchor = new THREE.Object3D(); flameAnchor.position.copy(FLAME_BASE).add(new THREE.Vector3(0, 0.03, 0)); candleRig.add(flameAnchor);
875
+
876
+ /* ---------- the bats themselves: dark body, ears, scalloped membrane wings that flap ---------- */
877
+ const batMat = P({ color: 0x15100f, roughness: 0.75, sheen: 0.4, sheenColor: 0x4a3a36, side: THREE.DoubleSide });
878
+ const batWingGeo = (() => {
879
+ const s = new THREE.Shape(), pts = [[0, 0.06], [0.35, 0.16], [0.7, 0.14], [1.0, 0.05], [0.82, -0.04], [0.75, 0.02], [0.62, -0.1], [0.52, -0.02], [0.38, -0.16], [0.27, -0.06], [0.12, -0.14], [0, -0.08]];
880
+ pts.forEach(([x, y], i) => i ? s.lineTo(x, y) : s.moveTo(x, y)); s.closePath();
881
+ const g = new THREE.ShapeGeometry(s); g.rotateX(Math.PI / 2); return g; // span along +x, leading edge forward (+z)
882
+ })();
883
+ const batBodyGeo = new THREE.SphereGeometry(1, 12, 8), batEarGeo = new THREE.ConeGeometry(1, 2.2, 5);
884
+ const batRigs = BATS.map(bt => {
885
+ const g = new THREE.Group(), k = bt.span;
886
+ const bodyM = new THREE.Mesh(batBodyGeo, batMat); bodyM.scale.set(0.045 * k, 0.04 * k, 0.11 * k); g.add(bodyM);
887
+ const headM = new THREE.Mesh(batBodyGeo, batMat); headM.scale.setScalar(0.035 * k); headM.position.set(0, 0.012 * k, 0.1 * k); g.add(headM);
888
+ for (const s of [-1, 1]) { const e = new THREE.Mesh(batEarGeo, batMat); e.scale.setScalar(0.012 * k); e.position.set(s * 0.016 * k, 0.045 * k, 0.1 * k); e.rotation.z = -s * 0.3; g.add(e); }
889
+ const wings = [-1, 1].map(s => { const piv = new THREE.Group(); piv.position.x = s * 0.03 * k; const w = new THREE.Mesh(batWingGeo, batMat); w.scale.set(s * k * 0.5, 1, k * 0.95); piv.add(w); g.add(piv); return piv; });
890
+ g.visible = false; scene.add(g); return { g, wings };
891
+ });
892
+
893
+ /* ---------- lights ---------- */
894
+ const sun = new THREE.DirectionalLight(0xffcf9a, 0); // low warm morning sun, backlighting the scene
895
+ sun.position.copy(SUN_POS); sun.target.position.set(0, 0, -12);
896
+ sun.castShadow = true; sun.shadow.mapSize.set(2048, 2048);
897
+ Object.assign(sun.shadow.camera, { left: -27, right: 27, top: 27, bottom: -27, near: 1, far: 90 });
898
+ sun.shadow.bias = -0.0005; sun.shadow.normalBias = 0.03;
899
+ scene.add(sun, sun.target);
900
+ const hemi = new THREE.HemisphereLight(0xbcd0e8, 0x5e5040, 0); scene.add(hemi);
901
+
902
+ /* ---------- "Happy Halloween": a burning title in the top-left corner ----------
903
+ Screen-space pass after tone mapping, placed in the lower part of the frame so it frames
904
+ the monument instead of covering it. The letters ignite left to right behind a hot edge,
905
+ then burn: fire flowing upward inside, a charred rim, an orange halo, heat shimmer and
906
+ embers rising off the words. */
907
+ // <fire-title>
908
+ const TITLE_T0 = 9.8, TITLE_W = 0.42, TITLE_CY = 0.867, TITLE_LEFT = 0.05; // start, rect width, rect centre (from bottom), left margin
909
+ const TITLE_FRAG = \`
910
+ uniform sampler2D tDiffuse, tMask; uniform float uT, uAspect, uOn; uniform vec4 uRect; varying vec2 vUv;
911
+ float hh(vec2 p){ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
912
+ float vn(vec2 p){ vec2 i = floor(p), f = fract(p); f = f*f*(3.0-2.0*f);
913
+ return mix(mix(hh(i), hh(i+vec2(1.0,0.0)), f.x), mix(hh(i+vec2(0.0,1.0)), hh(i+vec2(1.0,1.0)), f.x), f.y); }
914
+ float fbm(vec2 p){ float s = 0.0, a = 0.5; for (int i = 0; i < 4; i++){ s += a*vn(p); p = p*2.03 + vec2(1.7, 9.2); a *= 0.5; } return s; }
915
+ void main(){
916
+ vec3 col = texture2D(tDiffuse, vUv).rgb;
917
+ vec2 q = (vUv - uRect.xy)/uRect.zw + 0.5;
918
+ if (uT <= 0.0 || uOn <= 0.0 || q.x < -0.12 || q.x > 1.12 || q.y < -0.5 || q.y > 2.2) { gl_FragColor = vec4(col, 1.0); return; }
919
+ float R = uRect.z*uAspect/uRect.w;
920
+ vec2 hq = q + vec2((vn(vec2(q.x*14.0, q.y*6.0 - uT*3.0)) - 0.5)*0.003, (vn(vec2(q.x*10.0 + 3.0, q.y*5.0 - uT*2.5)) - 0.5)*0.012); // heat shimmer
921
+ vec4 M = texture2D(tMask, hq); // r sharp, g soft, b wide halo
922
+ float n = fbm(q*vec2(R*2.5, 2.5) + 3.1);
923
+ float front = uT*0.75 - q.x*0.9 + (n - 0.5)*0.5; // ignition sweeps left to right
924
+ float lit = smoothstep(0.0, 0.08, front);
925
+ float edge = smoothstep(0.0, 0.05, front)*(1.0 - smoothstep(0.05, 0.28, front));
926
+ col *= 1.0 - 0.5*M.b*smoothstep(-0.2, 0.3, front); // the night darkens behind the words
927
+ float flick = 0.86 + 0.14*vn(vec2(uT*7.0, 1.0));
928
+ float fire = fbm(vec2(q.x*R*3.0, q.y*3.0 - uT*1.6));
929
+ vec3 deep = vec3(0.78, 0.17, 0.02), hot = vec3(1.0, 0.6, 0.1), core = vec3(1.0, 0.92, 0.66);
930
+ vec3 fillc = mix(deep, hot, smoothstep(0.3, 0.75, fire + 0.3*(1.0 - clamp(q.y, 0.0, 1.0))));
931
+ fillc = mix(fillc, core, smoothstep(0.72, 0.95, fire)*0.6);
932
+ float inside = smoothstep(0.38, 0.62, M.g);
933
+ float rim = smoothstep(0.38, 0.5, M.g)*(1.0 - smoothstep(0.55, 0.85, M.g));
934
+ vec3 letters = fillc*flick*(1.0 - 0.45*rim); // charred rim, burning heart
935
+ col += vec3(1.0, 0.4, 0.07)*(M.g*0.55 + M.b*0.55)*flick*lit*0.6; // halo
936
+ col = mix(col, letters, inside*lit);
937
+ col += vec3(1.0, 0.82, 0.5)*edge*smoothstep(0.15, 0.6, M.g)*1.3; // the igniting edge flares
938
+ vec2 sp = vec2(q.x*R*6.0, q.y*6.0 - uT*1.3); // embers drifting up off the words
939
+ vec2 cid = floor(sp), cf = fract(sp) - 0.5; float hs = hh(cid);
940
+ vec2 off = vec2(hh(cid + 7.1) - 0.5, hh(cid + 3.3) - 0.5)*0.6 + vec2(sin(uT*3.0 + hs*20.0)*0.15, 0.0);
941
+ float spark = step(0.86, hs)*smoothstep(0.09, 0.0, length(cf - off))*smoothstep(2.0, 0.7, q.y)*smoothstep(0.1, 0.6, q.y)
942
+ * smoothstep(0.05, 0.3, max(texture2D(tMask, vec2(q.x, 0.34)).b, texture2D(tMask, vec2(q.x, 0.66)).b))*lit;
943
+ col += vec3(1.0, 0.55, 0.15)*spark*(0.55 + 0.45*sin(uT*9.0 + hs*40.0));
944
+ gl_FragColor = vec4(min(col, vec3(1.0)), 1.0);
945
+ }\`;
946
+ function blurInto(src, CW, CH, RB, passes) {
947
+ const b = src.slice(), tmp = new Float32Array(src.length), cl = (v, n) => Math.min(n - 1, Math.max(0, v)), k = 1 / (2 * RB + 1);
948
+ for (let pass = 0; pass < passes; pass++) {
949
+ for (let y = 0; y < CH; y++) { const row = y * CW; let s = 0;
950
+ for (let x = -RB; x <= RB; x++) s += b[row + cl(x, CW)];
951
+ for (let x = 0; x < CW; x++) { tmp[row + x] = s * k; s += b[row + cl(x + RB + 1, CW)] - b[row + cl(x - RB, CW)]; } }
952
+ for (let x = 0; x < CW; x++) { let s = 0;
953
+ for (let y = -RB; y <= RB; y++) s += tmp[cl(y, CH) * CW + x];
954
+ for (let y = 0; y < CH; y++) { b[y * CW + x] = s * k; s += tmp[cl(y + RB + 1, CH) * CW + x] - tmp[cl(y - RB, CH) * CW + x]; } }
955
+ }
956
+ return b;
957
+ }
958
+ function buildTitleMask(text) {
959
+ const CW = 2048, CH = 512, c = document.createElement('canvas'); c.width = CW; c.height = CH;
960
+ const g = c.getContext('2d'), font = s => \`400 \${s}px "Creepster", "Chiller", "Papyrus", Georgia, serif\`;
961
+ const lines = text.split('\\n');
962
+ g.font = font(260); const widest = Math.max(...lines.map(l => g.measureText(l).width));
963
+ const fs = Math.floor(Math.min(260 * 1820 / widest, 400 / (lines.length * 1.12))); g.font = font(fs);
964
+ g.textAlign = 'left'; g.textBaseline = 'middle'; g.fillStyle = g.strokeStyle = '#fff'; g.lineJoin = 'round'; g.lineWidth = fs * 0.02;
965
+ lines.forEach((l, i) => { const y = CH / 2 + (i - (lines.length - 1) / 2) * fs * 1.12; g.fillText(l, 40, y); g.strokeText(l, 40, y); }); // left-aligned
966
+ const px = g.getImageData(0, 0, CW, CH).data, a = new Float32Array(CW * CH);
967
+ for (let i = 0; i < a.length; i++) a[i] = px[i * 4 + 3] / 255;
968
+ const soft = blurInto(a, CW, CH, 3, 2), wide = blurInto(a, CW, CH, 22, 3);
969
+ const data = new Uint8Array(CW * CH * 4);
970
+ for (let y = 0; y < CH; y++) for (let x = 0; x < CW; x++) {
971
+ const i = y * CW + x, o = ((CH - 1 - y) * CW + x) * 4; // flip: texture rows run bottom-up
972
+ data[o] = a[i] * 255; data[o + 1] = soft[i] * 255; data[o + 2] = Math.min(1, wide[i] * 1.8) * 255; data[o + 3] = 255;
973
+ }
974
+ return { data, CW, CH };
975
+ }
976
+ // </fire-title>
977
+ await Promise.race([document.fonts ? document.fonts.load('400 200px "Creepster"') : Promise.resolve(), new Promise(res => setTimeout(res, 3000))]);
978
+ const titleMask = buildTitleMask('Happy\\nHalloween');
979
+ const titleTex = new THREE.DataTexture(titleMask.data, titleMask.CW, titleMask.CH, THREE.RGBAFormat);
980
+ titleTex.minFilter = titleTex.magFilter = THREE.LinearFilter; titleTex.generateMipmaps = false; titleTex.needsUpdate = true;
981
+ const titlePass = new ShaderPass({
982
+ uniforms: { tDiffuse: { value: null }, tMask: { value: titleTex }, uT: { value: 0 }, uOn: { value: 0 }, uAspect: { value: W / H },
983
+ uRect: { value: new THREE.Vector4(TITLE_LEFT + TITLE_W / 2 - 40 / 2048 * TITLE_W, TITLE_CY, TITLE_W, TITLE_W * (W / H) / 4) } },
984
+ vertexShader: \`varying vec2 vUv; void main(){ vUv = uv; gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0); }\`,
985
+ fragmentShader: TITLE_FRAG
986
+ });
987
+
988
+ /* ---------- "Applying Style....": a small loading line at the bottom centre ----------
989
+ Text and dots are drawn once into a mipmapped mask (red = words, green = dots) so they stay
990
+ crisp at a small size; the dots fill in one by one and reset, and a soft shimmer sweeps the words. */
991
+ // <status-line>
992
+ const STATUS_CY = 0.045, STATUS_H = 0.031; // centre (from bottom) and rect height, as fractions of the screen
993
+ const STATUS_FRAG = \`
994
+ uniform sampler2D tDiffuse, tStatus; uniform float uT, uOn, uDot0, uDotStep; uniform vec4 uRect; varying vec2 vUv;
995
+ void main(){
996
+ vec3 col = texture2D(tDiffuse, vUv).rgb;
997
+ vec2 q = (vUv - uRect.xy)/uRect.zw + 0.5;
998
+ if (uOn <= 0.0 || q.x < 0.0 || q.x > 1.0 || q.y < -0.2 || q.y > 1.0) { gl_FragColor = vec4(col, 1.0); return; }
999
+ float appear = smoothstep(1.0, 1.8, uT);
1000
+ vec4 m = texture2D(tStatus, q);
1001
+ float phase = fract(uT/1.6)*5.0, i = floor((q.x - uDot0)/uDotStep);
1002
+ float dotA = smoothstep(i + 0.6, i + 1.0, phase)*(1.0 - smoothstep(4.55, 4.95, phase)); // dots fill in, then reset
1003
+ float sweep = exp(-pow((q.x - (fract(uT/2.4)*1.6 - 0.3))*7.0, 2.0)); // soft shimmer
1004
+ float a = (m.r*(0.6 + 0.4*sweep) + m.g*dotA*0.85)*appear;
1005
+ gl_FragColor = vec4(mix(col, vec3(0.93, 0.94, 0.97), a), 1.0);
1006
+ }\`;
1007
+ function buildStatusMask(words, dots) {
1008
+ const CW = 1024, CH = 128, c = document.createElement('canvas'); c.width = CW; c.height = CH;
1009
+ const g = c.getContext('2d'); g.fillStyle = '#000'; g.fillRect(0, 0, CW, CH);
1010
+ g.font = '300 64px "Helvetica Neue", Helvetica, Arial, sans-serif'; if ('letterSpacing' in g) g.letterSpacing = '2px';
1011
+ g.textBaseline = 'middle';
1012
+ const ww = g.measureText(words).width, dw = g.measureText('.').width + 4, x0 = (CW - (ww + dw * dots)) / 2;
1013
+ g.fillStyle = '#f00'; g.fillText(words, x0, CH / 2);
1014
+ g.fillStyle = '#0f0'; for (let i = 0; i < dots; i++) g.fillText('.', x0 + ww + i * dw, CH / 2);
1015
+ const tex = new THREE.CanvasTexture(c); tex.colorSpace = THREE.NoColorSpace;
1016
+ tex.generateMipmaps = true; tex.minFilter = THREE.LinearMipmapLinearFilter; tex.magFilter = THREE.LinearFilter; tex.anisotropy = 4;
1017
+ return { tex, dot0: (x0 + ww) / CW, dotStep: dw / CW, aspect: CW / CH };
1018
+ }
1019
+ // </status-line>
1020
+ const status = buildStatusMask('Applying Style', 4);
1021
+ const statusPass = new ShaderPass({
1022
+ uniforms: { tDiffuse: { value: null }, tStatus: { value: status.tex }, uT: { value: 0 }, uOn: { value: 0 },
1023
+ uDot0: { value: status.dot0 }, uDotStep: { value: status.dotStep },
1024
+ uRect: { value: new THREE.Vector4(0.5, STATUS_CY, STATUS_H * status.aspect / (W / H), STATUS_H) } },
1025
+ vertexShader: \`varying vec2 vUv; void main(){ vUv = uv; gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0); }\`,
1026
+ fragmentShader: STATUS_FRAG
1027
+ });
1028
+
1029
+ /* ---------- post: MSAA HDR -> depth of field -> ACES -> film ---------- */
1030
+ const rt = new THREE.WebGLRenderTarget(W * pixelRatio, H * pixelRatio, { type: THREE.HalfFloatType, samples: 4 });
1031
+ const composer = new EffectComposer(renderer, rt);
1032
+ composer.addPass(new RenderPass(scene, camera));
1033
+ const bokeh = new BokehPass(scene, camera, { focus: 10, aperture: 0.0004, maxblur: 0.009 });
1034
+ const bokehRender = bokeh.render.bind(bokeh);
1035
+ bokeh.render = (...a) => { mistGroup.visible = false; halo.visible = false; sky.visible = false; bokehRender(...a); mistGroup.visible = true; halo.visible = true; sky.visible = true; };
1036
+ composer.addPass(bokeh);
1037
+ composer.addPass(new OutputPass());
1038
+ const filmPass = new ShaderPass({
1039
+ uniforms: { tDiffuse: { value: null }, uTime: { value: 0 }, uFade: { value: 0 }, uWhite: { value: 0 }, uRes: { value: new THREE.Vector2(W, H) } },
1040
+ vertexShader: \`varying vec2 vUv; void main(){ vUv = uv; gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0); }\`,
1041
+ fragmentShader: \`uniform sampler2D tDiffuse; uniform float uTime, uFade, uWhite; uniform vec2 uRes; varying vec2 vUv;
1042
+ float h(vec2 p){ return fract(sin(dot(p, vec2(12.9898, 78.233)))*43758.5453); }
1043
+ void main(){ vec2 c = vUv - 0.5; vec2 ca = c*vec2(uRes.x/uRes.y, 1.0); float r2 = dot(ca, ca);
1044
+ vec2 off = c*r2*0.006;
1045
+ vec3 col = vec3(texture2D(tDiffuse, vUv - off).r, texture2D(tDiffuse, vUv).g, texture2D(tDiffuse, vUv + off).b);
1046
+ col *= 1.0 - 0.58*smoothstep(0.12, 0.95, sqrt(r2));
1047
+ float g = h(floor(vUv*uRes) + fract(uTime*7.31)*vec2(91.7, 37.3)) - 0.5;
1048
+ col *= 1.0 + g*0.11;
1049
+ gl_FragColor = vec4(mix(max(col, 0.0)*uFade, vec3(1.0), uWhite), 1.0); }\` // uWhite = 1 gives pure white
1050
+ });
1051
+ composer.addPass(titlePass);
1052
+ composer.addPass(statusPass);
1053
+ composer.addPass(filmPass);
1054
+
1055
+ /* ==========================================================================
1056
+ SEQUENCE — every value is a pure function of t
1057
+ ========================================================================== */
1058
+ const tmpV = new THREE.Vector3(), flameW = new THREE.Vector3(), lookFar = new THREE.Vector3(0, 1.15, -30), lookDev = new THREE.Vector3(), Yup = new THREE.Vector3(0, 1, 0);
1059
+ const fogCol = new THREE.Color();
1060
+ const CANDLE_REST = new THREE.Vector3(0, 1.18, 0.42);
1061
+
1062
+ function update(t) {
1063
+ const out = t >= T.out;
1064
+ const on = out ? 0 : 1;
1065
+
1066
+ // world light: the morning fades up from absolute zero; thin drifting cloud barely varies the sun
1067
+ const reveal = (WHITE_BLANK ? 1 : smoother(T.revealIn, T.revealFull, t)) * on; // morning: full daylight under the white
1068
+ const cloud = 1 + 0.05 * (fbm1(t * 0.35) - 0.5);
1069
+ sun.intensity = K.sun * reveal * cloud;
1070
+ hemi.intensity = K.hemi * reveal;
1071
+ scene.environmentIntensity = K.env * reveal;
1072
+ fogCol.copy(FOG_BASE).multiplyScalar(reveal);
1073
+ scene.fog.color.copy(fogCol); scene.background.copy(fogCol); skyMat.uniforms.uFog.value.copy(fogCol);
1074
+ skyMat.uniforms.uZenith.value.copy(ZENITH).multiplyScalar(reveal); skyMat.uniforms.uSunCol.value.copy(SUN_TINT).multiplyScalar(reveal * cloud);
1075
+
1076
+ // devil glide (integrated speed profile) + floating oscillators
1077
+ const u = clamp((t - T.devilGo) / (T.devilArrive - T.devilGo));
1078
+ const s = travel(u), zD = devilZ(t);
1079
+ const vel = (devilZ(t + 0.05) - devilZ(t - 0.05)) / 0.1;
1080
+ const acc = (devilZ(t + 0.1) - 2 * zD + devilZ(t - 0.1)) / 0.01;
1081
+ const settle = Math.pow(1 - s, 2);
1082
+ const swayX = 0.16 * Math.sin(t * 0.55 + 0.4) * settle;
1083
+ const swayV = 0.16 * 0.55 * Math.cos(t * 0.55 + 0.4) * settle;
1084
+ const bob = 0.055 * Math.sin(t * 2.05) + 0.022 * Math.sin(t * 3.7 + 1.3) + 0.012 * Math.sin(t * 0.9 + 2.0);
1085
+ const lift = smoother(T.lift0, T.lift1, t), blow = smoother(T.blow0, T.out - 0.1, t);
1086
+ devil.position.set(swayX, 0.36 + bob, zD);
1087
+ devil.rotation.y = 0.13 * Math.sin(t * 0.38 + 1.1) * settle;
1088
+ body.rotation.x = 0.016 * vel - 0.012 * acc + 0.035 * lift - 0.02 * blow;
1089
+ body.rotation.z = -0.9 * swayV + 0.015 * Math.sin(t * 1.3);
1090
+ U.time.value = t; U.drag.value = clamp(vel / 6, 0, 1); U.flutter.value = 0.7 + 0.5 * clamp(vel / 4, 0, 1);
1091
+
1092
+ // breath: lift candle to the face, inhale, blow
1093
+ const inhale = smooth(T.lift0 + 0.3, T.blow0, t) * (1 - blow);
1094
+ candleRig.position.set(0, CANDLE_REST.y + 0.2 * lift + 0.01 * Math.sin(t * 2.6), CANDLE_REST.z - 0.03 * lift + 0.015 * blow);
1095
+ head.rotation.x = 0.06 + 0.2 * lift + 0.08 * blow + 0.012 * Math.sin(t * 1.1);
1096
+ head.position.z = 0.035 * blow; head.position.y = 1.76 + 0.012 * inhale;
1097
+ robe.scale.set(1 + 0.035 * inhale, 1, 1 + 0.05 * inhale);
1098
+ for (let k = 0; k < 2; k++) {
1099
+ const sgn = k === 0 ? -1 : 1, S = SHOULDERS[k];
1100
+ const Wp = tmpV.copy(candleRig.position).add(new THREE.Vector3(sgn * 0.09, -0.03, -0.05));
1101
+ hands[k].position.copy(Wp);
1102
+ const Sp = S.clone().add(new THREE.Vector3(0, 0.012 * inhale, 0));
1103
+ const E = new THREE.Vector3(sgn * 0.3, 1.12 + 0.12 * lift, 0.17);
1104
+ elbows[k].position.copy(E);
1105
+ const [up, fo] = sleeves[k];
1106
+ let dir = E.clone().sub(Sp); up.position.copy(Sp); up.scale.set(1, dir.length(), 1); up.quaternion.setFromUnitVectors(Yup, dir.normalize());
1107
+ dir = Wp.clone().sub(E); fo.position.copy(E); fo.scale.set(1, dir.length(), 1); fo.quaternion.setFromUnitVectors(Yup, dir.normalize());
1108
+ }
1109
+
1110
+ // candle: kindles deep in the fog, flickers, bends and gutters, then dies
1111
+ const kindle = smoother(1.5, 3.5, t) * on;
1112
+ const flick = 0.8 + 0.14 * fbm1(t * 2.3) + 0.06 * noise1(t * 14.0);
1113
+ const gutter = 1 - 0.65 * blow;
1114
+ const candleLevel = kindle * flick * gutter;
1115
+ candleLight.intensity = K.candle * candleLevel;
1116
+ flameMat.uniforms.uTime.value = t; flameMat.uniforms.uLife.value = kindle * (0.85 + 0.15 * flick) * (1 - 0.5 * blow);
1117
+ flameMat.uniforms.uBend.value.set(0.25 * Math.sin(t * 9) * blow, -0.25 * blow, 1.4 * blow + 0.25 * inhale * Math.sin(t * 7));
1118
+ flameMat.uniforms.uStretch.value = 1 + 0.25 * blow;
1119
+ flame.visible = !out;
1120
+ waxMat.emissiveIntensity = 0.9 * candleLevel;
1121
+ candleLight.position.x = 0.002 * Math.sin(t * 13) + 0.012 * blow;
1122
+
1123
+ // eyes wake once it is close
1124
+ const eyeK = smoother(6.5, 10.0, t) * on * (0.85 + 0.15 * noise1(t * 4.0)) * (1 + 0.6 * inhale);
1125
+ eyeMat.color.setRGB(2.1 * eyeK, 0.2 * eyeK, 0.025 * eyeK);
1126
+
1127
+ // pumpkins kindle with the reveal and cower as it passes
1128
+ const fear = smoother(10, 15.5, t);
1129
+ for (const p of pumpkins) {
1130
+ if (!p.faceMat) continue;
1131
+ const f = (0.78 + 0.22 * fbm1(t * 3.1 + p.seed) + 0.07 * noise1(t * 11 + p.seed)) * (1 - 0.45 * fear);
1132
+ const k = smoother(1.6, 6.0, t) * on * f;
1133
+ p.faceMat.color.setRGB(2.6 * k, 0.95 * k, 0.22 * k);
1134
+ if (p.light) p.light.intensity = K.pump * k;
1135
+ }
1136
+
1137
+ // bats: fly their paths, flapping, banking into each weave
1138
+ BATS.forEach((bt, i) => {
1139
+ const rig = batRigs[i], p = batPos(bt, t);
1140
+ if (!p || on === 0) { rig.g.visible = false; return; }
1141
+ const q = batPos(bt, Math.min(t + 0.03, bt.t0 + bt.dur)) || p;
1142
+ rig.g.visible = true; rig.g.position.set(p[0], p[1], p[2]); rig.g.lookAt(q[0], q[1], q[2] + (q === p ? 0.01 : 0));
1143
+ rig.g.rotateZ(0.5 * Math.cos(((t - bt.t0) / bt.dur) * 11 + bt.ph));
1144
+ rig.g.rotateX(-0.75); // nose up a little, so the camera sees the wings' undersides rather than their edges
1145
+ const flap = 0.2 + 0.95 * Math.sin(2 * Math.PI * bt.rate * t + bt.ph);
1146
+ rig.wings[0].rotation.z = flap; rig.wings[1].rotation.z = -flap;
1147
+ });
1148
+
1149
+ // camera: one continuous dolly, eased to an almost imperceptible landing
1150
+ const cu = easeLong(t / T.out);
1151
+ camera.position.set(0, lerp(CAM_Y0, CAM_Y1, cu), lerp(CAM_Z0, CAM_Z1, cu));
1152
+ const wLook = smoother(3.5, 13.8, t);
1153
+ lookDev.set(0, 1.735, Math.max(zD, -30));
1154
+ camera.lookAt(tmpV.copy(lookFar).lerp(lookDev, wLook));
1155
+ camera.updateMatrixWorld();
1156
+
1157
+ // derived: candle world position feeds DOF, mist scattering, halo
1158
+ devil.updateMatrixWorld(true);
1159
+ flameAnchor.getWorldPosition(flameW);
1160
+ const camDist = camera.position.distanceTo(flameW);
1161
+ halo.material.opacity = 0.2 * candleLevel * Math.exp(-Math.pow(FOG_DENSITY * 0.55 * camDist, 2));
1162
+ mistUniforms.uTime.value = t; mistUniforms.uColor.value.copy(fogCol).multiplyScalar(1.1);
1163
+ mistUniforms.uCandlePos.value.copy(flameW); mistUniforms.uCandleI.value = candleLevel; mistUniforms.uCam.value.copy(camera.position);
1164
+ sky.position.copy(camera.position);
1165
+ const focus = -flameW.clone().applyMatrix4(camera.matrixWorldInverse).z;
1166
+ bokeh.uniforms.focus.value = focus;
1167
+ bokeh.uniforms.aperture.value = lerp(K.ap0, K.ap1, smoother(5, 15.5, t));
1168
+
1169
+ filmPass.uniforms.uTime.value = t;
1170
+ filmPass.uniforms.uFade.value = WHITE_BLANK ? 1 : on;
1171
+ filmPass.uniforms.uWhite.value = WHITE_BLANK ? Math.max(1 - smoother(0.6, 3.6, t), on ? 0 : 1) : 0; // fade from white; cut to white
1172
+ titlePass.uniforms.uT.value = t - TITLE_T0; titlePass.uniforms.uOn.value = on;
1173
+ statusPass.uniforms.uT.value = t; statusPass.uniforms.uOn.value = on;
1174
+ }
1175
+
1176
+ /* ---------- ?export: render every frame from the timeline and save an MP4 with sound ----------
1177
+ Runs entirely in the browser (Chrome or Edge): WebCodecs encodes H.264 video and AAC audio
1178
+ (Opus where AAC isn't available) and mp4-muxer packs them into a file that downloads. */
1179
+ async function exportVideo() {
1180
+ const FPS = 30, VW = 1920, VH = 1080, total = Math.round(T.end / STORY_SCALE * FPS), file = 'halloween_devil_morning.mp4';
1181
+ const ui = document.createElement('p');
1182
+ ui.style.cssText = 'position:fixed;left:18px;bottom:14px;margin:0;font:13px/1.4 system-ui,sans-serif;color:#a7adb5;z-index:10';
1183
+ document.body.appendChild(ui);
1184
+ renderer.domElement.style.width = '100vw'; renderer.domElement.style.height = 'auto';
1185
+ const say = s => { ui.textContent = s; };
1186
+ const breathe = () => new Promise(r => { const c = new MessageChannel(); c.port1.onmessage = r; c.port2.postMessage(0); });
1187
+ try {
1188
+ if (!('VideoEncoder' in window) || !('AudioEncoder' in window)) throw new Error('this browser cannot encode video. Open the page in a recent Chrome or Edge.');
1189
+ const { Muxer, ArrayBufferTarget } = await import('https://cdn.jsdelivr.net/npm/mp4-muxer@5.1.3/build/mp4-muxer.mjs');
1190
+ const aac = (await AudioEncoder.isConfigSupported({ codec: 'mp4a.40.2', sampleRate: 48000, numberOfChannels: 2, bitrate: 192000 })).supported;
1191
+ const muxer = new Muxer({ target: new ArrayBufferTarget(), fastStart: 'in-memory',
1192
+ video: { codec: 'avc', width: VW, height: VH, frameRate: FPS }, audio: { codec: aac ? 'aac' : 'opus', numberOfChannels: 2, sampleRate: 48000 } });
1193
+ let failure = null;
1194
+ const ve = new VideoEncoder({ output: (c, m) => muxer.addVideoChunk(c, m), error: e => { failure = e; } });
1195
+ ve.configure({ codec: 'avc1.640028', width: VW, height: VH, bitrate: 16e6, framerate: FPS });
1196
+ for (let i = 0; i < total; i++) {
1197
+ if (failure) throw failure;
1198
+ window.__renderAt(i / FPS);
1199
+ const frame = new VideoFrame(renderer.domElement, { timestamp: Math.round(i * 1e6 / FPS), duration: Math.round(1e6 / FPS) });
1200
+ ve.encode(frame, { keyFrame: i % (FPS * 2) === 0 }); frame.close();
1201
+ while (ve.encodeQueueSize > 4) await new Promise(r => ve.addEventListener('dequeue', r, { once: true }));
1202
+ if (i % 5 === 0) { say(\`Rendering video \${Math.round(100 * i / total)}%. Keep this tab open and visible.\`); await breathe(); }
1203
+ }
1204
+ await ve.flush();
1205
+ say('Rendering sound…');
1206
+ const actx = new OfflineAudioContext(2, Math.ceil(T.end / STORY_SCALE * 48000), 48000);
1207
+ buildSound(actx, 0, actx.destination);
1208
+ const sound = await actx.startRendering();
1209
+ const ae = new AudioEncoder({ output: (c, m) => muxer.addAudioChunk(c, m), error: e => { failure = e; } });
1210
+ ae.configure({ codec: aac ? 'mp4a.40.2' : 'opus', sampleRate: 48000, numberOfChannels: 2, bitrate: 192000 });
1211
+ for (let s = 0; s < sound.length; s += 4800) {
1212
+ const n = Math.min(4800, sound.length - s), planar = new Float32Array(n * 2);
1213
+ planar.set(sound.getChannelData(0).subarray(s, s + n), 0); planar.set(sound.getChannelData(1).subarray(s, s + n), n);
1214
+ const data = new AudioData({ format: 'f32-planar', sampleRate: 48000, numberOfFrames: n, numberOfChannels: 2, timestamp: Math.round(s * 1e6 / 48000), data: planar });
1215
+ ae.encode(data); data.close();
1216
+ }
1217
+ await ae.flush();
1218
+ if (failure) throw failure;
1219
+ muxer.finalize();
1220
+ const blob = new Blob([muxer.target.buffer], { type: 'video/mp4' }), url = URL.createObjectURL(blob);
1221
+ const a = document.createElement('a'); a.href = url; a.download = file; document.body.appendChild(a); a.click();
1222
+ ui.textContent = ''; const link = document.createElement('a'); link.href = url; link.download = file; link.style.color = '#d8dde3';
1223
+ link.textContent = \`Download \${file} (\${(blob.size / 1e6).toFixed(1)} MB)\`; ui.append('Saved. If the download didn\\'t start: ', link);
1224
+ } catch (e) {
1225
+ say(\`Export stopped: \${e.message || e}\`); console.error(e);
1226
+ }
1227
+ }
1228
+
1229
+ /* ---------- drive ---------- */
1230
+ function resize() {
1231
+ if (RENDER) return;
1232
+ W = innerWidth; H = innerHeight;
1233
+ camera.aspect = W / H; camera.updateProjectionMatrix();
1234
+ renderer.setPixelRatio(pixelRatio); renderer.setSize(W, H);
1235
+ composer.setPixelRatio(pixelRatio); composer.setSize(W, H);
1236
+ bokeh.uniforms.aspect.value = camera.aspect; filmPass.uniforms.uRes.value.set(W * pixelRatio, H * pixelRatio);
1237
+ titlePass.uniforms.uAspect.value = W / H; titlePass.uniforms.uRect.value.w = TITLE_W * (W / H) / 4;
1238
+ statusPass.uniforms.uRect.value.z = STATUS_H * status.aspect / (W / H);
1239
+ }
1240
+ filmPass.uniforms.uRes.value.set(W * pixelRatio, H * pixelRatio);
1241
+ addEventListener('resize', resize);
1242
+
1243
+ update(0);
1244
+ renderer.compile(scene, camera);
1245
+
1246
+ if (RENDER) {
1247
+ window.__renderAt = t => { update(t * STORY_SCALE); composer.render(); return true; }; // t in video seconds
1248
+ window.__duration = T.end / STORY_SCALE; // 18 s
1249
+ window.__renderAudio = renderSoundtrack; // base64 WAV, 48 kHz stereo, same timeline
1250
+ document.getElementById('hint').remove();
1251
+ window.__ready = true;
1252
+ if (EXPORT) exportVideo();
1253
+ } else {
1254
+ // Live: the timeline runs on the audio clock so picture and sound stay locked.
1255
+ // Browsers only allow sound after a gesture, so it waits on black for a click or key.
1256
+ const hint = document.getElementById('hint');
1257
+ let actx = null, outGain = null, cycleOut = null, cycleStart = 0, nextQueued = false, started = false, clockStart = 0, muted = false;
1258
+ let frames = 0, acc = 0, tuned = false, last = 0;
1259
+ const schedule = at => { const g = actx.createGain(); g.connect(outGain); buildSound(actx, at, g); return g; };
1260
+ function begin() {
1261
+ hint.classList.add('gone');
1262
+ try {
1263
+ if (!actx) { actx = new (window.AudioContext || window.webkitAudioContext)(); outGain = actx.createGain(); outGain.connect(actx.destination); }
1264
+ actx.resume();
1265
+ } catch (e) { actx = null; }
1266
+ if (actx) {
1267
+ if (cycleOut) { const old = cycleOut; old.gain.setTargetAtTime(0, actx.currentTime, 0.04); setTimeout(() => old.disconnect(), 800); }
1268
+ cycleStart = actx.currentTime + 0.15; cycleOut = schedule(cycleStart); nextQueued = false;
1269
+ } else clockStart = performance.now();
1270
+ started = true;
1271
+ }
1272
+ function clock() {
1273
+ if (!actx) return (performance.now() - clockStart) / 1000;
1274
+ return actx.currentTime - cycleStart - (actx.outputLatency || actx.baseLatency || 0);
1275
+ }
1276
+ const LOOP = T.loop / STORY_SCALE; // video seconds
1277
+ function frame(now) {
1278
+ let t = 0;
1279
+ if (started) {
1280
+ t = clock();
1281
+ if (actx && !nextQueued && t > LOOP - 0.6) { cycleOut = schedule(cycleStart + LOOP); nextQueued = true; }
1282
+ if (t >= LOOP) { if (actx) { cycleStart += LOOP; nextQueued = false; } else clockStart += LOOP * 1000; t -= LOOP; }
1283
+ t = Math.max(0, t);
1284
+ }
1285
+ update(t * STORY_SCALE); composer.render();
1286
+ if (started && !tuned && t > 2) { acc += now - last; frames++;
1287
+ if (frames === 90) { tuned = true; if (acc / frames > 19 && pixelRatio > 1) { pixelRatio = 1; resize(); } } }
1288
+ last = now;
1289
+ requestAnimationFrame(frame);
1290
+ }
1291
+ requestAnimationFrame(frame);
1292
+ addEventListener('pointerdown', begin);
1293
+ addEventListener('keydown', e => {
1294
+ if (e.key === 'm' || e.key === 'M') { muted = !muted; if (outGain) outGain.gain.setTargetAtTime(muted ? 0 : 1, actx.currentTime, 0.05); }
1295
+ else if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); begin(); }
1296
+ });
1297
+ }
1298
+ <\/script>
1299
+ </body>
1300
+ </html>
1301
+ `;
1302
+ export {
1303
+ halloweenDevilLightHtml as default
1304
+ };