{"_id":"@zakkster/lite-confetti","_rev":"39-a36a68f57193e09685fbe2820b146c14","name":"@zakkster/lite-confetti","dist-tags":{"latest":"1.28.0"},"versions":{"1.0.0":{"name":"@zakkster/lite-confetti","version":"1.0.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"8bd752ee48d9ef64a193683c3a18c7cccc6490e4","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.0.tgz","fileCount":4,"integrity":"sha512-zqR5cY2tpdOJZMt4vT/CBqDszWk+2oSGu8lpLEMGw80YlLoPc+kNunXa8ej+LOvY44GVakdDxUeubhId+6lQEg==","signatures":[{"sig":"MEQCIFIhAGJ3w3+cYYlNaBbXenrL75OA+vCom+BhBBc8r7ovAiBjV6maHyIKOH1nht5qyPF9h93EVsc+H415wSKjocViXA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29849},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"lite-ticker":"^1.0.0","@zakkster/lite-color":"^1.0.0","@zakkster/lite-random":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.0_1773888650174_0.6679430918535336","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@zakkster/lite-confetti","version":"1.0.1","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.1","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"93021861fc36fa6b0878b60a1da869b4acafe1bb","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.1.tgz","fileCount":4,"integrity":"sha512-tJIN2oPdSzPtGIYF8dJLols9B/MUVuuol/XJPjmeQ6rGLOqRpLsY2Z1226MlpHF+EXV4t5BYCEKw/XLB7sjUcQ==","signatures":[{"sig":"MEQCIEqdBAAw9ikNXKCWrGYY6M7iNb2YKFW87FAAGQahQOijAiAmW9Xq+gVHu5VteQ7G2o9uqvQn8fQSyMG0jv7jCNjQNA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29859},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.1_1773891533167_0.8410957875771168","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@zakkster/lite-confetti","version":"1.0.2","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.2","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"57187299a35a93f7b6831252d04fde73a0e60e83","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.2.tgz","fileCount":4,"integrity":"sha512-g3kl0SWb4d2ZwkA3IRn6IsddSMvycJcsIB0qR6b4zo0GffUvwdGPfL2+/pyqMx26r2wn3KelZUI3czwjK/tYrQ==","signatures":[{"sig":"MEUCICf4AIuOkLuSlwXXa1UaylxQescK/RjSKfuMbMjbRob0AiEAmx9F/kLgP71lBLJ4xBWJTxh+vfiBHNxWEyw2pq7ljjE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29859},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.2_1773892214486_0.9684589530687753","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@zakkster/lite-confetti","version":"1.0.3","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.3","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"4ec85394ce823981b3d58928ee741773deab4d2c","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.3.tgz","fileCount":4,"integrity":"sha512-gJjMxfK1ZEN169vlpbgaOT6iXCq9UqTImApsUicdYn5DqK+Q+hkG2fAqKd183UAtdgCU3yvApAcVmrg3GUUJLg==","signatures":[{"sig":"MEYCIQCu7Rn6bct+fFItkQHWENfWPtaLo6P4yEorHAy1QA0/WwIhAMx+AS/uHYKKBJy7RuymHpUoUL5ggid9RyUdf+h8RNvI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29869},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.3_1773895693827_0.7993854008961634","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@zakkster/lite-confetti","version":"1.0.4","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.4","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"97a5709f9dbe764cd2eac025446c8d0d2946fa2e","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.4.tgz","fileCount":4,"integrity":"sha512-IQc6nJKpvLq9sWlZ2XpNIOVZDGS75sALoZTP2KHnQUz/08ogTt95DQ1UPBWWvOatBNHIwpC0VNxYbkFU9unQqg==","signatures":[{"sig":"MEQCIEZ5mrCL4XuuUM9juGfZDRkuE2rlCecIocwPMx1I3jeDAiAXyHIm9DULU6hZCryPtBF0uaPUMJa2kI1UtCTGhhenKQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29869},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.4_1773895814755_0.599919473549849","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@zakkster/lite-confetti","version":"1.0.5","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.5","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"1eea87c84c2e14a74b29cf54ee826d7476f2d4fd","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.5.tgz","fileCount":4,"integrity":"sha512-Z1xyUaXnLi8tKntKlncX6N/fr0h32HJH6D3OafiNasKWMtbP1SvvNkeCE1wEM1U533onbJetVSLHue5PjKGzgA==","signatures":[{"sig":"MEUCIQCcqvB8OsXBsf2BxfHV4/WAMFUsS9v9jG85b7hT4OMy9wIgDv0QATdiRk02tJBlhLfARlQYMUdEGasRtDtoYekUk1g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29869},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.5_1773899581247_0.8167602582091238","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@zakkster/lite-confetti","version":"1.0.6","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.6","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"e00be9b3fde0c31ad6cf3da4c504cbc29f02ec99","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.6.tgz","fileCount":4,"integrity":"sha512-2tUQWgsjMvprqYh3prsWGTdY2tQ7LLfO07OuLN+Uoq0ZgZ5I5iB3Nyv+TeiIsKfbkLEA847SbObcoOIW678RcQ==","signatures":[{"sig":"MEYCIQDZpcLO1zmZHzkhWL1w+LYgxaz7GSfp3A8eEmEupGaCyQIhAMOFGX/e4EWcRy6ME+sB9W3Evc3rtd5U4Tuirf14mEDn","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29779},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.6_1773900812563_0.9759866116625608","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"@zakkster/lite-confetti","version":"1.0.7","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.7","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/-zakkster-lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"614b8256e6e8018ce05f6c4970ca36e4e7f3b117","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.7.tgz","fileCount":4,"integrity":"sha512-HX+INv6oZGi6OxE5j+CfYVn6b2iK2y83LKF3Bpq5iP92GwFdyysk3cXV9g+D2iFRHwZxS9z0bxWcrsAPlOhjYQ==","signatures":[{"sig":"MEUCIC937sbsqSyunKc3ueix4vv8hcVQuKg8OyC2fOIsspiBAiEA+IwOcPiBz8fmbyZs4tZmY4PnEmqo6r4DbeLUnfWnpIg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34403},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/-zakkster-lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.7_1773984572907_0.7963767441305973","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"@zakkster/lite-confetti","version":"1.0.8","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.0.8","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"89079f6072fa7ca64d3bd25d4d3a60815fb3b58a","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.0.8.tgz","fileCount":4,"integrity":"sha512-0ABIiAuGNU4hmIxdkht8aMNk2lJ4Ujn5vKAGXmPcHvZG22FPwj0fhm6GC/2vgmqZCGICAP5A0yOY17lORC5IDw==","signatures":[{"sig":"MEUCIG18ZfwBMFVM6giyS6ZaG/7BVl9mgrOVlB8/u6TY/3LbAiEAwIOIdqwefFngiicxnY/HQF5DQXALJHF+8snozfQt0OM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34373},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.0.8_1774066590012_0.7044724337916544","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@zakkster/lite-confetti","version":"1.1.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.1.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"5e91e0e81627c459069d2e1c3ff6954dcfab67f6","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.1.0.tgz","fileCount":4,"integrity":"sha512-AQrf8Ama8tcEOy9xKI6Moh3jULATCdwQuGzIW6rcDnuXJ8+G9RPSKHE5AwVSfuAY4leQX1XNn7vBhLndbosQPA==","signatures":[{"sig":"MEYCIQCbiARQ+G/mLpDApFlVYlV3PXseyt4jzPGGr1hrmxoFFQIhAMkbNNSMfRLrMwg9uYMUCzrjKjQkt4z4Q6RTiXP6amyt","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36543},"main":"Confetti.js","type":"module","types":"Confetti.d.ts","exports":{".":{"types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.11.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, reduced-motion support, and timeline composability.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.1.0_1774590912954_0.6887885171341805","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@zakkster/lite-confetti","version":"1.2.1","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.2.1","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"1a0b23aaf0b135b98792a58c2e39a8dee41a736f","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.2.1.tgz","fileCount":5,"integrity":"sha512-/4kGGoCebQD/tFjtOtEkOUPDnpfSgsPmjCKXfSEYraupgoc833E4toEKqTOSyHwNnAqhhHzHNW7bzke6B0JjvA==","signatures":[{"sig":"MEUCIH713USfuKm6RGPVxWo/TvlIgzFJCShqZ2EkAzQcY3q8AiEAgFdRFJ3E0eB2+fnnlKGLrkL/uLiqqTfwABQuhg9TiVw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56902},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"6dcf2b1c570a27b73891573f0d0205137495f04c","scripts":{"test":"vitest run","test:watch":"vitest"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.2.1_1784152942338_0.6299939019108562","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@zakkster/lite-confetti","version":"1.2.2","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.2.2","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"6e2d565ffff379495eb5b7abf9ad06afeedac695","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.2.2.tgz","fileCount":7,"integrity":"sha512-/Uqc69GfOlmBm0wQE/v882989ozaoqxRqwjp3/a+PhUDE5IRr4yOF2eZfUYc7WeBaaGpNz+vH1D0lhqLOE1AWw==","signatures":[{"sig":"MEYCIQDfUALRlRLSCxtubyJF7gfEk7Z/aYHyaJ6ydD1QQj/z3AIhANwMFf5Hh4h8SeJ7EfuHDmU76zrKLuBimzpDR68Ciw4S","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67727},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"1fd3e7e5c0fa2b2862df358b3cb9157ba58d2f1d","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.2.2_1785456122707_0.92647640303571","host":"s3://npm-registry-packages-npm-production"}},"1.2.3":{"name":"@zakkster/lite-confetti","version":"1.2.3","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.2.3","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"4cc37d2e2ccb6b1d7cf8c8c76f75b911424b40d0","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.2.3.tgz","fileCount":7,"integrity":"sha512-wyIqKRmFljUZANDHsoVVDb9uMFcd4DcSmngaxuMAiAlfxlY8BxZBrOMEEkVZuXyeOaP1YWTxyCbOT24x2i76cQ==","signatures":[{"sig":"MEUCIQDrwu32rfnaFbyixu9FV7c7RCsmVpr5TcmDPP+MD8iWhwIgD5r2P4Xeh9FmwTJUc4fVPuuO9GKex8YDMYYvVeOqEbM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69929},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"7fa5ed0dfc8b05830e77c459eec4e1dfde9f9806","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.2.3_1785458375178_0.5247348190394567","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@zakkster/lite-confetti","version":"1.3.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.3.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"32f3f1cad54739eb1e76f6a41dcaaeaa364b47a1","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.3.0.tgz","fileCount":7,"integrity":"sha512-Be5QO2lv9hd/38oiPoSVhczmlvFVypyOK1Tp/zbp6AZunSYQWLeQwetO+U42B++8iAXAs7FFwDXOY55vjawZDg==","signatures":[{"sig":"MEQCIG8CLaIfy+N+8awpw2QxeVhQKCqPbiyNnHvWaZ9xvLEoAiAmZf994CDqle68oKxMQCxZmWHOgX+/p8K5vUlWqPkVuQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":84652},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"7eb4852d7e21100e9296d93d8bd2e790ca7a4b10","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.3.0_1785474352489_0.03369180488496015","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@zakkster/lite-confetti","version":"1.3.1","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.3.1","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"b003899c62a9975e47039ff596d4cb568e4517d8","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.3.1.tgz","fileCount":7,"integrity":"sha512-tRJy6ERkHimGaZRQj6T38qQAUcaUWJVF/iOa8gA73IR/CMEMOiRK9APAqV4K7r/Rr/53CI2WoDuamIi1RQXU4Q==","signatures":[{"sig":"MEYCIQDRO3M0kTdYkPQbLC7PMWODbm7lhtbOc1p7NdomOEm4XQIhAJEe5c+kHY4OjLoPlZOI2fE/hLs6AmHphqCmFZdx8Fmc","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":93309},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"fbddc1ca64bd3a2b1e5cf18887137fdfa9ed08ec","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.3.1_1785531706881_0.25792952862497187","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@zakkster/lite-confetti","version":"1.4.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.4.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"3059fbb61cb3d1533f1b21fcc6002fc43e7417d5","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.4.0.tgz","fileCount":7,"integrity":"sha512-+B8v1A9n1RT98gQReCDd3859A/ffaRhv73xsXnjd+rlcysNf57XiDbHnOqvg6UM1KCaEIj5G/tx7x8Y59rgEsw==","signatures":[{"sig":"MEYCIQDdA/mQmaNXTpaH1umqQEsi1kKdVckLtAVSPuhARLCt5AIhAMTzFw3JTYz7KN+8kCCogb5Bxez9eCBl23T24mI0YQp9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":102438},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"2cd4bc59b49c52c3231ebb15d7ec966d4e54ba2e","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.4.0_1785541315134_0.5895500858143583","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@zakkster/lite-confetti","version":"1.5.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.5.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"89d65b2f2cc9d7fc779e5565d483f8630d7c0699","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.5.0.tgz","fileCount":7,"integrity":"sha512-6tFyGrZCfLr4+/i+FZ0wVcfH3wvHI0Vdj+s5c4EhHCuHDCK80/ijJqX1jLbizelF76uBLAdGzgCaYISlAUaUtA==","signatures":[{"sig":"MEUCIDVh/qH2U1YTTiDe6wwu4Pufm9zzljEzj+wrUvL4NVj2AiEAjpH7M96hUGnSu/xkVJfL/KMZB8OIKswubRA2s8SL9IM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":110095},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"b656345121ca2b8f2ec3ae9da3cdf1ac8a9bd828","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.5.0_1785543004196_0.9907643285040457","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"@zakkster/lite-confetti","version":"1.6.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.6.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"74ece872a6268d2b5f59ede60c3166d09c6fb072","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.6.0.tgz","fileCount":7,"integrity":"sha512-NBzHOBcx673nnIBqv0H3PoMBDD+E+nbJJojVGc74k8M1eUiS5aeC4nwZGsYa7vzCkxDAApueS0FGEqEdDSwiIQ==","signatures":[{"sig":"MEYCIQDwD9R3mHf4BvoztEBUC/bsNmZdg8RZdDrcJLauC4gNhwIhAL9N4h/rLTcQ7+8JCAweCcp5u66LcYdEKunQSAsLxvFi","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":121562},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"b7ae136ac222c63c501e14bda3f3390117a5a4a3","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.6.0_1785555783329_0.9321951830309123","host":"s3://npm-registry-packages-npm-production"}},"1.7.0":{"name":"@zakkster/lite-confetti","version":"1.7.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.7.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"90bd59e969ea571e0877193920c37a85fce697a1","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.7.0.tgz","fileCount":7,"integrity":"sha512-TbCoGP0HjhnnE2poZT92oYmIrCvTtS+gmA4N+OzBDi2FaoHGa7K1veWPZKMpJtFj8YsEnAYRA7qfPIF3Uw9gDw==","signatures":[{"sig":"MEQCIF25ROGrVyThT18mz1an8OyzkN42+7vRVr+cBTPwlSwSAiBhrO3pOiaaHeZa/bHvi5m2xDUNhsDMBrDTp6jYjKn5sg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136754},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"88eabb153ea9a409fe6988809fe344144406a470","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"11.16.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.7.0_1785632287342_0.45659550794114945","host":"s3://npm-registry-packages-npm-production"}},"1.8.0":{"name":"@zakkster/lite-confetti","version":"1.8.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.8.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"026b970351ac2b762a64712a95cd7f308cfc325e","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.8.0.tgz","fileCount":7,"integrity":"sha512-KXc9nePBhLUZQ86q2F7jjNiRAGfj4YiUoMWQu7E879PEwbWQ8TAxEvFnVx7EO95hGESbuG7br+pnG9sh9o2yfg==","signatures":[{"sig":"MEUCIQCmj8+Dh6Lx/WtZXqlnUgeGQH6HKlwptNGWXnG7by/1EgIgavCP9XlSNzon1TsWNcoUoDqvXeVimc/DfgQgD1h+mig=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":150685},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"88eabb153ea9a409fe6988809fe344144406a470","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.8.0_1785646915677_0.7669738263715653","host":"s3://npm-registry-packages-npm-production"}},"1.9.0":{"name":"@zakkster/lite-confetti","version":"1.9.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.9.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"2bc1f5bf231834b11c8822ea530a433ec4942ad8","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.9.0.tgz","fileCount":7,"integrity":"sha512-Cjf60uRd7n7MRmVxj63eOBfskKmjSqbHQRgKFe2Cu3AW3WDjPImO/m3rWBtqFoYg3woD7MgK47L7c10HFZqkLQ==","signatures":[{"sig":"MEUCIQDPFv2pXvOCn3kIS5uA99N/Smx5aQFKrF4WWV65xrTKpAIgQd6jSGzStE2TNY1aluObzw1qpSYlE15nFH+GWtKw0N4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":173893},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"fb8f860c0f6ee34ba129adc0b5b26551c5074787","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^1.0.4","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.0","@zakkster/lite-gc-profiler":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.9.0_1785725805911_0.20202956299157848","host":"s3://npm-registry-packages-npm-production"}},"1.10.0":{"name":"@zakkster/lite-confetti","version":"1.10.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.10.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"fcd739a10e8524385fb7ff4547872fc330ae5974","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.10.0.tgz","fileCount":7,"integrity":"sha512-9nRURRZ8f0Eq3/UygL+aAzafMUFngzA27uAjn9OEiW0cGjXW+dW4BtombQd4Nz1/3gz8dMNIgUE6LZ+VYmGyow==","signatures":[{"sig":"MEUCIBT1ap8fqWYthLZ3xRFpKXWGAyN/GtkF9wOVapVsx4SdAiEAjthL3ifsw4yEokuv44ErV3Re3DdWs0OflRe0JzhS91I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":191541},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"f7cc814c0a367c8964273cbbcae3fc508cf606ea","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.10.0_1785730567854_0.9684347109181346","host":"s3://npm-registry-packages-npm-production"}},"1.11.0":{"name":"@zakkster/lite-confetti","version":"1.11.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.11.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"b93468bf2778706ec0591fd034657ac5194b06fc","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.11.0.tgz","fileCount":7,"integrity":"sha512-Y+/hiDM7gfO3x3USc+WEoEBkWvNQoyn9WnACSDdpXYw0fRF0LvcXMSYuHCfis/QtVaLfQMQSw0CWi9OdBTcsxA==","signatures":[{"sig":"MEUCIHJURlbmwMY2ir0MpfVt7wQBENaHTDm/MmHomPc1xY3bAiEA0QOChpgb9HkwOgHHbPH8X6RR/ULzLNqdMQ6L0c3H54s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":207563},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"400118bab05487f571dad5ada1f6dde8244bb977","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.11.0_1785876813534_0.06977866098502505","host":"s3://npm-registry-packages-npm-production"}},"1.12.0":{"name":"@zakkster/lite-confetti","version":"1.12.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.12.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"bfd59bb54d79cab5af5760b1abee4e811bbd0e74","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.12.0.tgz","fileCount":7,"integrity":"sha512-6SZG3EdGszy79shGAgHYM/P1LqpdqJUGgpwLpaalMmpK6t20yy/ZRMLvXZnx6aqhlBxyguWDGy8DvG7SCQ2DWg==","signatures":[{"sig":"MEUCIFVN4hnmkKbB6HOzw0j1d5/q8cLRQno4x9DZcFxM3rM3AiEA+QDuHB2hsRW97d8IcXbrbNIB7Qoh6hH2sXYSbMOVGns=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":223943},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"da561a626893d7ead8780bfd8a764b6fe1218e09","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.12.0_1785892211178_0.05773111517162688","host":"s3://npm-registry-packages-npm-production"}},"1.13.0":{"name":"@zakkster/lite-confetti","version":"1.13.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.13.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"998be0fd8224084c969c5b92b62375c4f9b4c943","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.13.0.tgz","fileCount":7,"integrity":"sha512-4m6CafTisrPn1aeisydolw7x55Y4o3ohbPcKScF9AIStrxnBcAeqbgNej0R0lDrdYV5h06gsAO67qGgYwcg1Nw==","signatures":[{"sig":"MEQCIA0cX02dKtsCE/I8unRzoBEswve2OcEov++K8/ZBbCzfAiAEwwiRFA5Ni4tsqCDD4j9vLR1G9KeAj6Eo01d6zas+gg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":243558},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"0e0d22daa56f748da49c235f6697ffca28ec9846","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.13.0_1785972029146_0.22515893738332493","host":"s3://npm-registry-packages-npm-production"}},"1.14.0":{"name":"@zakkster/lite-confetti","version":"1.14.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.14.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"72e14169ffb8147716c518a6ae32770026eda226","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.14.0.tgz","fileCount":7,"integrity":"sha512-uCKjMcuRcy5L2HtgMmBNYBszhpbnNFBc4On20g0oZxmTznePDj2pwQTXM4TRbKjO0tYJN03uqAbHP6US54v0og==","signatures":[{"sig":"MEUCIGDzl5bixLX9m2DXKt4cQ8GlfxMXr6ZWON15FyZpPl50AiEAsu7c284AqvwvABj+c2RhBdnWB5ojjcMFDYOB8olXVlQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":258501},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"427f5fb1575ae0e25c5b48d688780e5c62dc17ed","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.14.0_1785989819363_0.2034098893205214","host":"s3://npm-registry-packages-npm-production"}},"1.15.0":{"name":"@zakkster/lite-confetti","version":"1.15.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.15.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"f78b7cc88d2b42e69ba1f7e66bed1781fbbd572d","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.15.0.tgz","fileCount":7,"integrity":"sha512-c/6TC7xG+abTNKEPbpxknOnhWMUz/Gl0vIEwKHbHoM9YqbdaCsq1QsSmx4LAA92CiZLP3pNF1JfNuTMVZDY9QA==","signatures":[{"sig":"MEYCIQDiMTh/AFm7RkowoSJLnkriuJgNeFu+JbBjsfM0HAQZNQIhAIjVyh7ozGUIL3IlmYWxmAZWrkLDmkn7NcRuA3+p8+El","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":273401},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"9ec88367e97921b3063d5e6f5d0798f816e83492","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.15.0_1786137682482_0.20777258881166505","host":"s3://npm-registry-packages-npm-production"}},"1.16.0":{"name":"@zakkster/lite-confetti","version":"1.16.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.16.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"080caa16e287b313563a21833e79b9c75c51dab1","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.16.0.tgz","fileCount":7,"integrity":"sha512-3P9AnA3ce8Kjg80YM69Xj/GcreU+P0grtdW2jcy/QuUhc9cTw8UAi9hnk9Uf5h7SprunK5pWSszrtBvC+687+A==","signatures":[{"sig":"MEQCIEim7yIsQvCNLEEHwjBDItDbZsPzFyp8nuCvpE1rhP5WAiBfs7A7UMJoslQ7ahA2rEzBZ19Khd86bmoBNSCoPhhs2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":289734},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"e05b80fd7427e48e6b3546fd5fd818ac9878f2d8","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.16.0_1786235080255_0.09361392326062856","host":"s3://npm-registry-packages-npm-production"}},"1.17.0":{"name":"@zakkster/lite-confetti","version":"1.17.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.17.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"60ff828492619f67e6ebe76cd388b58c0650207a","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.17.0.tgz","fileCount":7,"integrity":"sha512-oy9l0OvElt1IUKSXZhQt28cuSw9Dwlk+S5jPhfI7R86/ZaBseXHjYYRBucq4q4WaDdw0MB3Sk6LfaztLzEc40g==","signatures":[{"sig":"MEQCIDz7pka9A1aWHppMomEX3pbYg6nhfb27pEHnCaIo/ql0AiBH3syNCbqFrtvwsPbjq3TxDBqXJuCfFo2F4JaW3Tcv+Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":307563},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"10c938f2fd819f400ea06ecb8828c10fdb67a374","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.17.0_1786242842720_0.3169429156952557","host":"s3://npm-registry-packages-npm-production"}},"1.18.0":{"name":"@zakkster/lite-confetti","version":"1.18.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.18.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"ead447cc5096d99b4553516f8452abd1153d693d","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.18.0.tgz","fileCount":7,"integrity":"sha512-iz5SR1KGgRDx1yHXqrsCLm6zbmcT6UI3K2Ml2hflotDwsMhdHjM52rpIe2k2VI+jKClniemREt3rdhxLx/0IPg==","signatures":[{"sig":"MEUCIAljOOxxqTb2jr1IgoKqZu6y5Wvv2ytLwh2S2lBCEOfrAiEAjBuwBkwaYJUvte+ssdEwhv6JWJt+XiDNnKNgRlCuEt8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":334041},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"a5e9c665a500ba68e10b37938afd06f5d9a20fb2","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.18.0_1786328075667_0.011582963164985527","host":"s3://npm-registry-packages-npm-production"}},"1.19.0":{"name":"@zakkster/lite-confetti","version":"1.19.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.19.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"9214b0c630086af1fa2cfc6ffc850843e158d114","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.19.0.tgz","fileCount":7,"integrity":"sha512-omSxdmUoosHZnrZbNJz/MXCAVXl6JVTE2Un71yZ599hgPKwmZYCAFZ/ScnB+bfGda2TGe88mGPUwHu0OHZQz/w==","signatures":[{"sig":"MEUCIQDJc3+wTyi8PBns7LEztrlfVyr4EoxlZFqihVPzFNuVSQIgcLXvpHJtN7s7c5Pw+XWDhGGRjlTTIv7hRqq5GRid9f8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":356623},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"d3490f8c6fb9fe47605ea838760a458b336199e2","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.19.0_1786429146228_0.7945193050640977","host":"s3://npm-registry-packages-npm-production"}},"1.20.0":{"name":"@zakkster/lite-confetti","version":"1.20.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.20.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"c5c5f93e8e27161d441091deb70e9ffefe8f4ed3","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.20.0.tgz","fileCount":7,"integrity":"sha512-e4t9Bh6J+V4oPLZMBJERcXS1IXtj37SsSbPx1dAz8rJSiZ3JQFYuwEWEf3qwmMWQLHzS1FQlOmA5ORJLmnTYmQ==","signatures":[{"sig":"MEYCIQDrByJpTW6Qr6FcSj/2toz/Z/bs0+awHunwKJNw6JIAogIhAPtnR2OljrL68YVo33U6YULJp4L7XSk2KgrOczYNpEhq","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":379661},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"f60d6c88d5cc6f6d8c96e56ab0c6082471576e85","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.20.0_1786488423078_0.6587067024986217","host":"s3://npm-registry-packages-npm-production"}},"1.21.0":{"name":"@zakkster/lite-confetti","version":"1.21.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.21.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"d8c30d285ef005ff51b6aa818f27a83d84deb492","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.21.0.tgz","fileCount":7,"integrity":"sha512-OtafitNXvQOCa/Fe4/fShmduVr936fZh5kQdnezdk/Io0I61FJieM0m24SnJY+v5dvcYSeB6J4O8NJ46T0A5wA==","signatures":[{"sig":"MEUCIQCdSiBA1ZFryW8rM4A4JoXRaKrPHtJBxUl9MqS6aHUYiQIgIBI4OuqBywYDf4c/R/eXg3xUJrFif0gJgdNcjBX32Ys=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":401487},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"1b3c9653ac70d5b48232e1f7c9bb7d36bc2e6771","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.21.0_1786751479214_0.6720661734317908","host":"s3://npm-registry-packages-npm-production"}},"1.22.0":{"name":"@zakkster/lite-confetti","version":"1.22.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.22.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"52d286a8e0a25425c70c4f90c323d4a5017ae9fa","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.22.0.tgz","fileCount":7,"integrity":"sha512-WguEZVpBsG9dJ0TS0B9KOE7baYYSEbsrFt2K0SGL/0sTbd8eCsPiQeV0tcSv9zGjssO4grS6nUdLxjVVKhSWbg==","signatures":[{"sig":"MEUCIHorpStUE0u3syU7XjIqHM9175cbi/USn6JEXki8Jhr2AiEAnLUoZbfr+LJ8cCbwD93TAUvGDVGUA7UmW2OOINIOjq8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":424528},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"a05693b4fe596a54608745941a0b0533852f54d7","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.22.0_1786759979568_0.628506229610734","host":"s3://npm-registry-packages-npm-production"}},"1.23.0":{"name":"@zakkster/lite-confetti","version":"1.23.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.23.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"405ad4786b8cbac12cf9960f7adc6a58434ea91b","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.23.0.tgz","fileCount":7,"integrity":"sha512-gs5qTFOi3e9eZ1fbvUKD62/FnxjZU9FjVJsySJk9Z4odbQSKGh7YOzK9321uOPbQygSf26eMv4R3fXtMprXqLg==","signatures":[{"sig":"MEQCIChwHlnAr9RTz/VtXIq8s3rX06ZkCdIa5PoRdny5TQrUAiBCMgaI9B8oVVMVq2ViaS1R4EN+C9Xn7bH8ENEr1bF6fg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":443140},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"624023ce099cb7275f7e818bdf7cf88eeced6d1c","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.23.0_1786772410653_0.7039140264757744","host":"s3://npm-registry-packages-npm-production"}},"1.25.0":{"name":"@zakkster/lite-confetti","version":"1.25.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.25.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"d9b892a869b6fc56257479f43507c3663d3ac5c6","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.25.0.tgz","fileCount":7,"integrity":"sha512-P6FmlddX3bW3iaVjv1CN/SPFUeHQ1Wt5BQnPA2sPx+T1BAIM3mjqwmmqE6hiIyeHkGm7o9ad/HMgPuzTu3ni7w==","signatures":[{"sig":"MEUCIFnjiGetk9uj7MwtKZgW0Bj5k8qtHgU4MYHAn9im7f7fAiEAxfTZKEAONWfC1tfZXz3poZu3JvpCRYk2AIoRfnN03Z8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":475999},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"c3ed7c6044c369c159263e829064670866984f5b","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.25.0_1786828172191_0.7447265554645282","host":"s3://npm-registry-packages-npm-production"}},"1.26.0":{"name":"@zakkster/lite-confetti","version":"1.26.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.26.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"aa1694931c7a7a321acf407ee4d35a32accbbe4d","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.26.0.tgz","fileCount":7,"integrity":"sha512-ZviauUYVfBI8aBklBG1gDAtMhrSc0QSIFWCdsrl81ywDwDXPiTOgGIJCSeFeO4LAkwkplNtNeXsbi1Vk1MS14Q==","signatures":[{"sig":"MEUCIQDR/v1BDd2r+h7pNFPK1BFdnlO0syl3vcBpElCyv6PxcwIgGNM4q2vKkU7l7RL+QweFq3X7LIYnnSfcETsK3hiap+A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":485174},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"c3ed7c6044c369c159263e829064670866984f5b","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.26.0_1786848111942_0.806634553800534","host":"s3://npm-registry-packages-npm-production"}},"1.27.0":{"name":"@zakkster/lite-confetti","version":"1.27.0","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","_id":"@zakkster/lite-confetti@1.27.0","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"dist":{"shasum":"cd7612d667b516e43a60a00e9a425fc319134129","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.27.0.tgz","fileCount":7,"integrity":"sha512-/FPOSKelc82NRZ/5AycTdCqm9Bvm1UwLduzRb9irIISmecPcS2+IsUV7kuUSf/gjcEH80boUgsBvbdAKTwdTZg==","signatures":[{"sig":"MEUCIEsJ4ydJ5G9IoBkBbfyWwNF5oRTZe9vKeNT/2PcWitphAiEAwWUd0ld2LC5SdXcBgTwy9j40En8Otn4Ccz8ccSyRkKw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":502321},"main":"./Confetti.js","type":"module","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"node":"./Confetti.js","types":"./Confetti.d.ts","import":"./Confetti.js","default":"./Confetti.js"}},"funding":{"url":"https://github.com/sponsors/PeshoVurtoleta","type":"github"},"gitHead":"3a5fd4cf71700b5fad05d3f0dbb1a19c5941d28e","scripts":{"test":"node --test 'test/**/*.test.mjs'","verify":"npm test && npm run torture","torture":"node --expose-gc test/torture.mjs","test:watch":"node --test --watch 'test/**/*.test.mjs'"},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"repository":{"url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git","type":"git"},"_npmVersion":"12.0.2","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.1","dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@zakkster/lite-leak":"^1.8.1","@zakkster/lite-gc-profiler":"^1.15.0"},"_npmOperationalInternal":{"tmp":"tmp/lite-confetti_1.27.0_1786852882594_0.8422611062428502","host":"s3://npm-registry-packages-npm-production"}},"1.28.0":{"name":"@zakkster/lite-confetti","author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"version":"1.28.0","description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","type":"module","main":"./Confetti.js","types":"./Confetti.d.ts","module":"Confetti.js","exports":{".":{"types":"./Confetti.d.ts","node":"./Confetti.js","import":"./Confetti.js","default":"./Confetti.js"}},"license":"MIT","homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","repository":{"type":"git","url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git"},"scripts":{"test":"node --test 'test/**/*.test.mjs'","test:watch":"node --test --watch 'test/**/*.test.mjs'","torture":"node --expose-gc test/torture.mjs","verify":"npm test && npm run torture"},"bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"funding":{"type":"github","url":"https://github.com/sponsors/PeshoVurtoleta"},"dependencies":{"@zakkster/lite-color":"^2.1.0","@zakkster/lite-random":"^1.0.0","@zakkster/lite-ticker":"^1.0.0"},"keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"sideEffects":false,"devDependencies":{"@zakkster/lite-gc-profiler":"^1.15.0","@zakkster/lite-leak":"^1.8.1"},"gitHead":"6e4606faaa52f8e0ddb3745359a0c5bcf7f1231a","_id":"@zakkster/lite-confetti@1.28.0","_nodeVersion":"26.3.1","_npmVersion":"12.0.2","dist":{"integrity":"sha512-JedhqAaRRzsv8dmON5yvSC9djYwy4vV6SUbptyjK30EhJ8vTr+KRpJkiyaGYX0E5EznK1QmQFDrRxoaHJ/Ijvg==","shasum":"828b8ff7260c6204ea65106de6348790090f2900","tarball":"https://registry.npmjs.org/@zakkster/lite-confetti/-/lite-confetti-1.28.0.tgz","fileCount":7,"unpackedSize":509870,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBuOErj7vEFwj0GwPRt9DsdfLIS+zZkT0YfDsR8Ie8dRAiA+32p4gYg2hH0muwQab+wlrc8YfRdkPxZgjDT2jBqncQ=="}]},"_npmUser":{"name":"zakkster","email":"shinikchiev@yahoo.com"},"directories":{},"maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/lite-confetti_1.28.0_1786858109254_0.1687797033017937"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-19T02:50:50.071Z","modified":"2026-08-16T05:28:29.568Z","1.0.0":"2026-03-19T02:50:50.332Z","1.0.1":"2026-03-19T03:38:53.310Z","1.0.2":"2026-03-19T03:50:14.644Z","1.0.3":"2026-03-19T04:48:13.984Z","1.0.4":"2026-03-19T04:50:14.935Z","1.0.5":"2026-03-19T05:53:01.408Z","1.0.6":"2026-03-19T06:13:32.694Z","1.0.7":"2026-03-20T05:29:33.092Z","1.0.8":"2026-03-21T04:16:30.178Z","1.1.0":"2026-03-27T05:55:13.121Z","1.2.1":"2026-07-15T22:02:22.472Z","1.2.2":"2026-07-31T00:02:02.854Z","1.2.3":"2026-07-31T00:39:35.325Z","1.3.0":"2026-07-31T05:05:52.665Z","1.3.1":"2026-07-31T21:01:47.030Z","1.4.0":"2026-07-31T23:41:55.291Z","1.5.0":"2026-08-01T00:10:04.349Z","1.6.0":"2026-08-01T03:43:03.473Z","1.7.0":"2026-08-02T00:58:07.488Z","1.8.0":"2026-08-02T05:01:55.854Z","1.9.0":"2026-08-03T02:56:46.055Z","1.10.0":"2026-08-03T04:16:07.998Z","1.11.0":"2026-08-04T20:53:33.688Z","1.12.0":"2026-08-05T01:10:11.313Z","1.13.0":"2026-08-05T23:20:29.318Z","1.14.0":"2026-08-06T04:16:59.536Z","1.15.0":"2026-08-07T21:21:22.722Z","1.16.0":"2026-08-09T00:24:40.433Z","1.17.0":"2026-08-09T02:34:02.875Z","1.18.0":"2026-08-10T02:14:35.807Z","1.19.0":"2026-08-11T06:19:06.371Z","1.20.0":"2026-08-11T22:47:03.250Z","1.21.0":"2026-08-14T23:51:19.343Z","1.22.0":"2026-08-15T02:12:59.722Z","1.23.0":"2026-08-15T05:40:10.809Z","1.25.0":"2026-08-15T21:09:32.360Z","1.26.0":"2026-08-16T02:41:52.090Z","1.27.0":"2026-08-16T04:01:22.751Z","1.28.0":"2026-08-16T05:28:29.412Z"},"bugs":{"url":"https://github.com/PeshoVurtoleta/lite-confetti/issues","email":"shinikchiev@yahoo.com"},"author":{"name":"Zahary Shinikchiev","email":"shinikchiev@yahoo.com"},"license":"MIT","homepage":"https://github.com/PeshoVurtoleta/lite-confetti#readme","keywords":["confetti","particles","celebration","oklch","deterministic","reduced-motion","canvas","presets","fireworks","pointer-follow","palette"],"repository":{"type":"git","url":"git+https://github.com/PeshoVurtoleta/lite-confetti.git"},"description":"Deterministic confetti engine with OKLCH colors, 5 shapes, named presets, palette import, pointer-follow spray, reduced-motion support, and timeline composability.","maintainers":[{"name":"zakkster","email":"shinikchiev@yahoo.com"}],"readme":"# @zakkster/lite-confetti\n\n[![npm version](https://img.shields.io/npm/v/@zakkster/lite-confetti.svg?style=for-the-badge&color=latest)](https://www.npmjs.com/package/@zakkster/lite-confetti)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@zakkster/lite-confetti?style=for-the-badge)](https://bundlephobia.com/result?p=@zakkster/lite-confetti)\n[![npm downloads](https://img.shields.io/npm/dm/@zakkster/lite-confetti?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-confetti)\n[![npm total downloads](https://img.shields.io/npm/dt/@zakkster/lite-confetti?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-confetti)\n![TypeScript](https://img.shields.io/badge/TypeScript-Types-informational)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)\n\nDeterministic confetti engine with OKLCH colors, 5 built-in shapes plus custom\n`registerShape()` shapes (vector or image sprite), per-particle multi-shape mixing,\ntunable flutter, lateral wind, turbulence + gust (living-air forces), a vortex/attractor\npoint force, a full bounding box (floor, walls, ceiling) with bounce, settle-and-pile,\nzero-GC motion trails, color-over-life ramps, spawn emitter shapes (line / ring / box),\nstaggered emission (a burst cascades in over a ms window), velocity-aligned orientation\n(pieces bank broadside to their flight, like leaves), tunable tumble speed (slow drift to\nreverse spin), size-over-life ramps (shrink-out / bloom), tunable wobble speed (lazy flutter\nto fast shimmer), birth-opacity ramps (materialize-in), and reduced-motion support.\n\n**The confetti library that canvas-confetti wishes it was.**\n\n**[→ Live Interactive Playground](https://codepen.io/Zahari-Shinikchiev/debug/dPpzGLG)**\n\n## Why lite-confetti?\n\n| Feature | lite-confetti | canvas-confetti | react-confetti | party.js |\n|---|---|---|---|---|\n| **Deterministic (seeded)** | **Yes** | No | No | No |\n| **OKLCH colors** | **Yes** | No | No | No |\n| **Reduced motion** | **Yes (auto)** | No | No | No |\n| **Shapes** | **5 built-in + custom (registerShape: vector or sprite)** | 2 | 2 | 3 |\n| **Spray mode** | **Yes** | No | No | No |\n| **Shared ticker** | **Yes** | Own RAF | Own RAF | Own RAF |\n| **SoA flat arrays** | **Yes** | No | No | No |\n| **Timeline composable** | **Yes** | No | No | No |\n| **Zero-GC hot path** | **Yes** | No | No | No |\n| **ResizeObserver** | **Yes** | window.resize | No | No |\n| **Bundle size** | **< 4KB** | ~6KB | ~5KB | ~8KB |\n\n## Installation\n\n```bash\nnpm install @zakkster/lite-confetti\n```\n\n## Quick Start\n\n### One-Liner (Fire and Forget)\n\n```javascript\nimport { confetti } from '@zakkster/lite-confetti';\n\n// Creates overlay canvas, fires burst, cleans up automatically\nconfetti();\n```\n\n### Full Control\n\n```javascript\nimport { createConfetti } from '@zakkster/lite-confetti';\n\nconst c = createConfetti(overlayCanvas, { seed: 42 });\n\nc.burst({ count: 80, spread: 1.2, shape: 'star' });\nc.burst({ x: 200, y: 100, shape: 'emoji', emoji: '🎊', count: 30 });\n\n// Later\nc.seed(42);  // reset for deterministic replay\nc.destroy();\n```\n\n---\n\n## Full Options Reference\n\n### Burst Options\n\nEvery parameter is optional. Sensible defaults produce a beautiful upward confetti burst.\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `x` | number | canvas center | Burst origin X position (CSS pixels) |\n| `y` | number | canvas height × 0.33 | Burst origin Y position (CSS pixels) |\n| `count` | number | 80 | Number of particles to spawn |\n| `spread` | number | 1.2 | Emission cone width in radians (π = half-circle) |\n| `speed` | number | 400 | Initial particle speed center (px/s) |\n| `speedVariance` | number | 200 | Speed randomness range. Actual speed: `speed ± speedVariance` |\n| `gravity` | number | 600 | Downward acceleration in px/s². Higher = falls faster. |\n| `wind` | number | 0 | Lateral acceleration in px/s² — the sideways mirror of `gravity`. Positive drifts right, negative left. Opt-in; `0` = straight down. See [Wind](#wind--lateral-drift). |\n| `floor` | number | Infinity | Settle-boundary Y in CSS px. Particles that reach it land on the line instead of falling forever. Opt-in; `Infinity` = no floor. See [Floor](#floor--settle--bounce). |\n| `bounce` | number | 0 | Restitution `0–1` on **any** boundary contact (floor and walls alike): `0` rests (pile-up), `1` is perfectly elastic. Shared by the whole [bounding box](#bounding-box). |\n| `settle` | number | 0 | Rest-speed threshold in px/s. A piece whose post-bounce speed drops below it **freezes** on the `floor` and piles up (keeps aging + fades). Opt-in; `0` = off. Needs a `floor`. See [Settle & pile](#settle--pile). |\n| `friction` | number | 0 | Tangential **floor** drag `0–1`. On each floor-contact frame, the horizontal velocity is bled by `1 - friction` (the complement to `bounce`, which reflects the vertical component): `0` = frictionless (default), `1` = full grip (horizontal stop on contact), `0.2` = a long skid. Opt-in; needs a `floor`. A physics knob (it moves the position fingerprint). See [Friction](#friction). |\n| `wallFriction` | number | 0 | Tangential drag `0–1` on the box's three **non-floor** edges — the tangential twin of `friction` (which covers the floor) and the analog to `bounce`'s one shared restitution. On a non-floor-edge contact it bleeds the *tangential* velocity (the ceiling damps horizontal `vx`, each wall damps vertical `vy` — always the component `bounce` does **not** reflect there, so it never cancels the rebound). Opt-in; needs a box. A physics knob (it moves the position fingerprint). See [Friction](#friction). |\n| `wallLeft` | number | -Infinity | Left wall X in CSS px — the X-min edge of the [bounding box](#bounding-box). Particles reaching it clamp and reflect `vx`. Opt-in; `-Infinity` = no wall. |\n| `wallRight` | number | Infinity | Right wall X in CSS px — the X-max edge. Opt-in; `Infinity` = no wall. |\n| `ceiling` | number | -Infinity | Ceiling Y in CSS px — the Y-min edge, the mirror of `floor`. Particles rising past it clamp and reflect `vy`. Opt-in; `-Infinity` = no ceiling. |\n| `drag` | number | 0.98 | Per-frame velocity retention, clamped to `0–1`. 0.98 = 2% speed loss per frame. |\n| `sizeMin` | number | 5 | Minimum particle width in CSS pixels |\n| `sizeMax` | number | 12 | Maximum particle width in CSS pixels |\n| `lifeMin` | number | 1.5 | Minimum particle lifetime in seconds |\n| `lifeMax` | number | 3.0 | Maximum particle lifetime in seconds |\n| `shape` | string | `'rect'` | `'rect'`, `'circle'`, `'star'`, `'triangle'`, `'emoji'`, or a name from `registerShape()`. Unknown names fall back to `'rect'`. |\n| `shapes` | string[] | — | Mix multiple shapes in one burst, chosen per particle. Repetition weights the mix. Overrides `shape`; unknown names are dropped. See [Mixing shapes](#mixing-shapes). |\n| `emoji` | string | party popper | Emoji character (only used when `shape` is `'emoji'`) |\n| `flutter` | number | 1 | Tumble depth, 0–1. `1` = full wobble (classic), `0` = rigid. Affects scale only, never position. |\n| `sway` | number | 0 | Horizontal drift, 0–1. `0` = straight fall; higher values sway side-to-side like real paper. |\n| `swayRate` | number | `1` | Sway **swing frequency** — the speed knob to `sway`'s depth (the mirror `sway:swayRate :: flutter:flutterRate`). `3` swings three times as fast, `0.3` a long lazy drift, `0` freezes the phase at each piece's random birth tilt (a per-particle **constant lean**, *not* inert — contrast `gustRate:0`, which collapses to `sin(0) = 0`), a **negative** reverses the swing. Coerced with `num` (signed — a frequency has a direction): non-finite → `1` (off); no upper cap. **Inert when `sway` is 0** (read only inside the `sway != 0` branch, so a sway-off burst is byte-identical for any value). A **physics** knob (it moves the position fingerprint) that reads `tilt`/`tilt0` read-only and writes nothing but `x`, so `turbulence` and `flutterRate` stay byte-identical. Honored by `burst()` **and** `spray()`; zero-rng; inert under reduced motion. |\n| `turbulence` | number | 0 | Per-particle rotating acceleration in px/s² — organic wander, so a burst fans out and mills. Opt-in; `0` = none. Draws no rng. See [Living air](#living-air). |\n| `gust` | number | 0 | Global oscillating horizontal acceleration in px/s² layered on `wind` — the whole burst swells side to side in ~3s waves. Opt-in; `0` = none. See [Living air](#living-air). |\n| `gustRate` | number | `GUST_HZ` | Gust **swell frequency** — the speed knob to `gust`'s depth (the mirror `gust:gustRate :: flutter:flutterRate`). `6` triples the swell rate (a fast breeze), `0.5` a long ocean roll, `0` freezes the phase (inert — the gust force collapses to `sin(0) = 0`), a **negative** reverses the phase (the breeze leans the other way first). Default `GUST_HZ` (= `TAU/3`, today's baked ~3s swell). Read only inside the `gust != 0` branch, so a gust-off burst is byte-identical for any value. Coerced with `num` (signed — a frequency has a direction): non-finite → the default (off); no upper cap. A **physics** knob (it moves the position fingerprint). Honored by `burst()` **and** `spray()`; zero-rng; inert under reduced motion. See [Living air](#living-air). |\n| `attract` | number | 0 | Vortex radial spring strength (1/s², scaled by distance): `+` pulls toward the center, `−` repels. Opt-in; `0` = none. See [Vortex](#vortex). |\n| `swirl` | number | 0 | Vortex tangential strength (1/s²): spins particles around the center; sign = spin direction. Opt-in; `0` = none. See [Vortex](#vortex). |\n| `attractX` | number | burst x | Vortex center X (CSS px). Defaults to the burst origin. |\n| `attractY` | number | burst y | Vortex center Y (CSS px). Defaults to the burst origin. |\n| `trail` | number | capacity | Per-particle trail length `0..capacity` — how many recent positions this burst's ribbon spans. Needs a construction `trail` budget; ignored without one. `0` opts a burst out. See [Motion trails](#motion-trails). |\n| `colors` | Array | 7 OKLCH defaults | Array of OKLCH objects `{ l, c, h }` or CSS strings |\n| `lifeColors` | Array | — | Multi-stop OKLCH life ramp (≥ 2 stops, birth-color first). The **body** sweeps it as each piece ages (sparks cooling white→red); the trail stays the flat `colors` pick. Opt-in; invalid falls back to flat. See [Color over life](#color-over-life). |\n| `emit` | string | — | Spawn-origin shape: `'line'` (horizontal curtain), `'ring'` (firework shell, velocity radial-outward), or `'box'` (square area), sized by `emitSize`. Default: a single point. Opt-in; unknown / `emitSize ≤ 0` = point spawn. See [Emitter shapes](#emitter-shapes). |\n| `emitSize` | number | — | Emitter extent in px: line half-length / ring radius / box square half-extent. Needs a shape in `emit`; `≤ 0` or non-finite = point spawn. |\n| `stagger` | number | — | Staggered-emission window in ms: spread the `count` births evenly over it (piece `i` wakes at `stagger·i/count`), so the burst cascades in instead of appearing at once. **Burst-only** (a spray already emits over time; it ignores `stagger`). Opt-in; off / `≤ 0` / non-finite = synchronous spawn, byte-identical. See [Staggered emission](#staggered-emission). |\n| `align` | number | `0` | Velocity-align blend `0..1`: rotate each piece **broadside** to its live velocity (its flat face meets the airflow, like a leaf), `0` = pure random spin, `1` = fully locked. Coerced to `[0, 1]`. A pure orientation overlay — the seeded position stream is byte-identical off or on. Honored by `burst()` **and** `spray()`. See [Velocity-aligned orientation](#velocity-aligned-orientation). |\n| `spinRate` | number | `1` | Tumble-speed multiplier on the seeded random spin: `1` = as seeded, `0` = rigid at the random birth tilt, `0.3` = slow drift, `2` = double, negative = reverse. Coerced with `num` (non-finite → `1`; `0` and negatives are valid). A pure render-orientation overlay — the seeded position stream is byte-identical off or on, **even with `turbulence` armed**. Honored by `burst()` **and** `spray()`. See [Tumble speed](#tumble-speed). |\n| `spinDrag` | number | `1` | Angular-velocity **retention** in `0–1` — the angular mirror of the linear `drag`. Each frame, before the spin advance, `spinV *= spinDrag`, so the tumble decays exactly as `drag` decays translation. `1` = off (tumble forever, today's look), `0.95` = settle to a lazy drift, `0` = freeze at the birth angle. Coerced with `clamp01` (like `drag`/`bounce`): a **negative** clamps to `0` (freeze — a retention has no direction, unlike `spinRate`'s reverse); non-finite → `1`. A contraction (`\\|spinV\\|` never grows; no accel cap). Damps `spinV` only, never `tiltV`. A **hybrid physics** knob: with `turbulence` off it moves only the render rotation (position byte-identical), with `turbulence` on the curl reads the slower spin and it moves the position fingerprint — **not** a pure render overlay. Honored by `burst()` **and** `spray()`. See [Spin drag](#spin-drag). |\n| `scaleTo` | number | `1` | Size-over-life target: lerp each piece's **rendered** size from `scaleFrom` at birth to `scaleTo` at death (isotropic, both axes). `0.2` shrinks out, `2` grows/blooms, `0` vanishes at death; `1` = constant size. Coerced with `nonneg`: a **negative** clamps to `0` (a size has no direction — not a mirror flip, not a fallback to `1`); non-finite → `1`. A pure render-scale overlay folded into flutter's `ctx.scale` — `pool.w`/`pool.h` untouched, so the seeded position stream is byte-identical off or on; the trail keeps its birth width. Honored by `burst()` **and** `spray()`. See [Size over life](#size-over-life). |\n| `scaleFrom` | number | `1` | Size-over-life **origin**: the birth endpoint of the ramp `scaleTo` targets, turning the one-endpoint `1 → scaleTo` ramp into a two-endpoint `scaleFrom → scaleTo` envelope — `s = scaleFrom + (scaleTo − scaleFrom) × (1 − lifeT)`, isotropic. `0.2` blooms up from a fifth-size, `2` starts double and settles, `1` = today's look (the ramp starts at birth size); `scaleFrom == scaleTo` is a constant size multiplier. Coerced with `nonneg`: a **negative** clamps to `0` (born invisible — a size has no direction, not a fallback to `1`); non-finite → `1`. Folded into the same single `ctx.scale` as `scaleTo` — `pool.w`/`pool.h` untouched, so the seeded position stream is byte-identical off or on; the trail keeps its birth width. Honored by `burst()` **and** `spray()`. See [Size over life](#size-over-life). |\n| `flutterRate` | number | `1` | Tumble-wobble **speed** multiplier on the seeded flutter (the speed knob to `flutter`'s depth): `1` = as seeded, `0` = frozen at the random birth tilt, `0.3` = slow lazy flutter, `2` = fast shimmer, negative = reversed. Coerced with `num` (`0` and negatives valid; non-finite → `1`). **Inert when `flutter` is 0** (a zero-depth wobble has no speed). A pure render-phase overlay about a birth pivot that never touches `pool.tilt` — the seeded position stream is byte-identical off, on, or on-with-turbulence. Honored by `burst()` **and** `spray()`. See [Wobble speed](#wobble-speed). |\n| `fadeIn` | number | `0` | Birth-**opacity** ramp: fade each piece up from transparent over the **first `fadeIn` fraction** of its life (`0.4` = ease in over the first 40%, `1` = ramp across the whole life; `0` = instant-on). The mirror of the hardcoded death fade-out, **multiplying** the same `alpha`. Coerced with `clamp01` (non-finite/negative → `0` off, `> 1` → `1`). A pure render overlay on `ctx.globalAlpha` that never touches `pool.x/y/vx/vy` — the seeded position stream is byte-identical off or on (and rotate/scale/stroke/color too). The trail materializes in with the body. Honored by `burst()` **and** `spray()`; inert under reduced motion. See [Birth opacity](#birth-opacity). |\n| `fadeOut` | number | `0.3` | Death-**opacity** window: the **fraction of life** over which each piece dissolves *out* at the END. `0.6` fades over the last 60% (a long gentle dissolve), `0.1` a quick blink-out, `0` a hard cut (full opacity then gone), `1` across the whole life; default `0.3` = today's exact look. The mirror of `fadeIn`, **multiplying** the same `alpha` to compose the full opacity envelope. Coerced with `clamp01` against a `Math.fround(0.3)` sentinel (non-finite/undefined → the `0.3` default; **negative → `0`** = hard cut, *not* a fallback to the default; `> 1` → `1`). A pure render overlay on `ctx.globalAlpha` that never touches `pool.x/y/vx/vy` — the seeded position stream is byte-identical at the default or off (and rotate/scale/stroke/color too). The trail dissolves out with the body. Honored by `burst()` **and** `spray()`; inert under reduced motion. Reuses `fadeIn`'s determinism probe with no harness change. |\n| `angle` | number | `-Math.PI / 2` | Center angle of emission cone in radians. -π/2 = upward. |\n| `onComplete` | Function | — | Called when all burst particles have died |\n\n**Inputs fail closed.** Every numeric option is sanitised before it can reach a particle: a non-finite value (`NaN`/`Infinity`, or a stray non-number) coerces to its default, `drag` clamps to `0–1`, and a `null`/empty `colors` falls back to the defaults. A call-time typo degrades gracefully — it never throws mid-animation or paints a `NaN` position — the same fail-closed stance as an unknown `shape` name falling back to `'rect'`. (`registerShape` is the one exception: a bad shape *definition* throws, because it is setup, not a per-call tunable.)\n\n### Spray Options\n\nSpray accepts all burst options plus:\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `duration` | number | 1000 | Spray duration in milliseconds |\n| `rate` | number | 5 | Particles spawned per frame |\n| `followPointer` | boolean | false | Stream follows the live pointer inside this canvas (see below) |\n\n### createConfetti Options\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `seed` | number | `Date.now()` | RNG seed for deterministic output |\n| `maxParticles` | number | 500 | Pool size (fixed ring buffer). When full a new spawn is **dropped** — existing pieces live out their life + fade — rather than overwriting a live one (v1.26.0). A full continuous spray wants `maxParticles ≥ rate × 60 × avgLife`; below that, excess spawns drop gracefully (never a pop). 500 fits typical bursts. |\n| `respectReducedMotion` | boolean | true | Honor `prefers-reduced-motion: reduce` |\n| `trail` | number | 0 | Motion-trail capacity: ring-buffer depth for the per-particle ribbon. `0` = off (no buffers). Sized once here (zero-GC); capped at 64. See [Motion trails](#motion-trails). |\n\n**Sizing the pool for sprays.** The pool is a fixed ring buffer of `maxParticles` slots. A one-shot `burst()` just needs `maxParticles ≥ count`. A **continuous** `spray()` keeps a *steady-state* population alive of roughly `rate × 60 × avgLife` (with `avgLife = (lifeMin + lifeMax) / 2`) — size the pool to that for a fully dense stream. Below it, the pool saturates and each new spawn is **dropped** (existing pieces finish their life + fade), so a long spray thins gracefully instead of cutting live pieces off mid-flight (fixed in v1.26.0). This is the zero-GC counterpart to object-per-particle engines: they never drop a piece but allocate without bound; lite-confetti stays at 0 B/frame and caps the live set, so you pick the ceiling. Example: `spray({ rate: 15, lifeMin: 1.2, lifeMax: 2.5 })` wants `≈ 15 × 60 × 1.85 ≈ 1665` slots for zero drops.\n\n---\n\n## Particle Physics Pipeline\n\nEvery frame, each alive particle runs through this pipeline:\n\n```\n--  SPAWN       origin = EMIT ? point-on(line | ring | box, emitSize) : (x, y)   (opt-in, at BIRTH; ring also fires velocity radially outward)\n0a. UNBORN?     if STAGGER delayed this piece's birth, skip steps 0b–13 entirely   (opt-in; frozen + invisible, life not yet counting, until its delay elapses)\n0b. FROZEN?     if the piece has SETTLED (landed on the floor), skip steps 1–13 entirely   (opt-in; it still ages, fades, and draws)\n1.  GRAVITY     vy += gravity × dt        (downward acceleration)\n2.  WIND        vx += wind × dt           (opt-in lateral acceleration)\n3.  TURBULENCE  vx += cos(p) × turb × dt, vy += sin(p) × turb × dt   (opt-in, p = tilt+spin phase)\n4.  GUST        vx += sin(elapsed × GUST_HZ) × gust × dt   (opt-in, global oscillating wind)\n5.  VORTEX      vx += (attract·rx − swirl·ry) × dt, vy += (attract·ry + swirl·rx) × dt   (opt-in, r = center − pos; capped)\n6.  DRAG        vx *= drag, vy *= drag    (air resistance)\n7.  POSITION    x += vx × dt, y += vy × dt\n8.  FLOOR       if y > floor:   y = floor,   vy = −vy × bounce   (opt-in, box Y-max)\n                 └─ SETTLE: if |vy| < settle, freeze the piece here (landed = true)   (opt-in; bounce-then-rest)\n9.  CEILING     if y < ceiling: y = ceiling, vy = −vy × bounce   (opt-in, box Y-min)\n10. SWAY        x += sin(tiltPhase) × sway × dt   (opt-in horizontal drift)\n11. WALLS       if x < wallLeft:  x = wallLeft,  vx = −vx × bounce   (opt-in, box X-min)\n                if x > wallRight: x = wallRight, vx = −vx × bounce   (opt-in, box X-max)\n12. SPIN        rotation += spinVelocity × dt\n13. TILT        tiltPhase += tiltSpeed × dt\n14. OPACITY     fade to 0 in last 30% of life\n15. TRAIL       record (x,y) in the ring → stroke the ribbon through recent positions   (opt-in RENDER overlay — world-space stroke, touches no physics state)\n16. RENDER      translate → rotate → flutter-scale → draw shape\n                 └─ COLOR: body fillStyle = lifeColors ? ramp[lifeFraction] : flat colors[i]   (opt-in; pure color overlay)\n```\n\nSteps 1–13 are **physics** (they mutate `x/y/vx/vy`); steps 14–16 are **rendering**. `trail` (step 15) is the first purely-render feature: it *reads* the position but draws a stroked polyline in world space (never `translate`), so it cannot move the determinism fingerprint — every committed physics hash is preserved at any trail depth. `lifeColors` (the COLOR sub-step of 16) is the second: it only chooses which pre-baked color string the body paints, touching no position, so it too preserves every physics fingerprint. Step 0 is the first **behaviour** feature: once a piece has `settle`d it is `landed`, so the whole physics block is skipped and it lies frozen — but it keeps ageing and drawing, so nothing else about the pipeline changes. The **SPAWN** line runs once at birth, before the per-frame pipeline: `emit` (the first **emission-geometry** feature) chooses the origin — a point, or a point on a line / ring / box — and for a ring also aims the launch velocity radially outward. With `emit` off it is exactly the point `(x, y)`, so the seeded stream is untouched.\n\n### Rotation & 3D Tumbling\n\nEach particle has two rotational properties:\n\n**Spin** — continuous rotation around the particle's center. Angular velocity is randomized at spawn: `(rng.next() - 0.5) * 10` radians/second. This produces particles spinning between -5 and +5 rad/s — some clockwise, some counterclockwise, all at different speeds.\n\n**Tilt** — a wobble phase that drives a cosine-based X-scale oscillation. The **`flutter`** option sets its depth: `wobbleScale = 1 − flutter × 0.5 × (1 − |cos(tiltPhase)|)`. At `flutter: 1` (the default) this is the classic `0.5 + |cos| × 0.5`, making particles \"flip\" like a thin piece of paper turning in space; at `flutter: 0` they stay rigid. Tilt speed is randomized between 1 and 5 rad/s per particle. Because flutter scales only, it never moves a particle — output stays byte-identical under a fixed seed regardless of its value.\n\n**Sway** — the opt-in **`sway`** option adds a horizontal drift driven by the same tilt phase, so pieces drift side-to-side as they fall (real confetti rarely falls straight). It defaults to `0`, which keeps the exact straight-fall positions of earlier versions.\n\nThe combination of spin rotation + flutter wobble (+ optional sway) produces the realistic confetti tumbling you see in the real world.\n\n### Wind / lateral drift\n\n**`wind`** (added in v1.5.0) is a lateral acceleration in px/s² — the sideways mirror of `gravity`. Where `sway` *oscillates* around the fall line and nets to zero, `wind` is a sustained force: the whole burst drifts. Because it shares gravity's units, `gravity` (down) and `wind` (across) read as one 2D force vector.\n\n```js\nc.burst({ wind: 300 });                    // a burst slanting to the right\nc.burst({ wind: -200, gravity: 250 });     // drifting left as it falls\nc.burst({ ...presets.snow, wind: 60 });    // snow on a gentle breeze\n```\n\nWind is applied *before* drag, so — exactly like gravity's terminal fall speed — a particle approaches a terminal lateral velocity rather than accelerating forever. It defaults to `0` and the integrator skips the term entirely at `0`, so a default burst does no extra work and its seeded positions stay byte-identical (the committed determinism fingerprint is preserved). A windy burst draws no random values, so it too replays identically under a fixed seed. Wind has no effect under reduced motion (the static render has no velocity to push).\n\n### Floor / settle & bounce\n\nWhere `gravity` and `wind` set the *force*, **`floor`** (added in v1.6.0) sets the *boundary*: a settle line, given as an absolute Y in CSS px, that a falling particle lands on instead of dropping forever. **`bounce`** is its restitution — `0` rests the piece on the line (confetti piles up), `1` reflects its vertical velocity perfectly (a lively rebound), anything between damps out.\n\n```js\nc.burst({ y: 0, floor: innerHeight - 20 });                 // confetti settles at the bottom\nc.burst({ y: 0, floor: innerHeight - 20, bounce: 0.5 });    // …and bounces on the way down\nc.spray({ floor: 400, bounce: 0.3, duration: 1500 });       // a spray that piles up on a shelf\n```\n\nOn contact the particle is clamped onto the floor and its `vy` is reflected, scaled by `bounce`. Restitution is clamped to `0–1` so a rebound can never *add* energy, and drag still damps `vy` every frame, so even `bounce: 1` loses energy and eventually rests — never a runaway. `floor` defaults to `Infinity`, and the integrator's collision branch (`if (y > floor)`) can never fire at that default, so a floor-less burst does no extra work and its seeded positions stay byte-identical (the committed determinism fingerprint is preserved). Like wind, the collision draws no random values, so a floored burst replays identically under a fixed seed. Floor has no effect under reduced motion (the static render does no integration to collide).\n\n### Bounding box\n\n**`wallLeft`**, **`wallRight`**, and **`ceiling`** (added in v1.7.0) are the three remaining edges that complete `floor` into a full axis-aligned **bounding box** — an X-min wall, an X-max wall, and a Y-min ceiling (the mirror of the `floor` Y-max). Each is an absolute CSS-px coordinate; a particle reaching an edge is clamped onto it and the perpendicular velocity component reflected. Restitution reuses the same **`bounce`**, so the whole box shares one bounciness.\n\n```js\nconst w = innerWidth, h = innerHeight;\nc.burst({ x: w / 2, y: h / 2, ceiling: 0, floor: h, wallLeft: 0, wallRight: w, bounce: 0.4 });\n// a burst that stays fully inside the viewport, bouncing off every edge\n```\n\nEach edge defaults to an infinity sentinel (`-Infinity` for `wallLeft`/`ceiling`, `Infinity` for `wallRight`), and its guard (`x < wallLeft`, `x > wallRight`, `y < ceiling`) can never fire at that default — so a box-less burst does no extra work and its seeded positions stay byte-identical. **Both** committed fingerprints — the default *and* the v1.6.0 floored — are preserved. The wall clamp runs *after* `sway` (the frame's last horizontal move), so a swaying particle is still contained. Like the floor, the box draws no random values (a boxed burst replays identically under a fixed seed), `bounce` stays clamped so no edge can add energy (an elastic particle in a tight box never escapes), a degenerate inverted box clamps deterministically without a NaN, and the box has no effect under reduced motion.\n\n### Living air\n\nEvery force so far is *constant in time* — a fixed `gravity`, a fixed `wind` — so a wide fall reads like parallel rain. **`turbulence`** and **`gust`** (added in v1.8.0) are the first **time-varying** forces, and they read as moving air:\n\n- **`turbulence`** is a per-particle *rotating* acceleration (px/s²). Each particle's push direction curls at its own rate, so a burst fans out and mills instead of falling in lockstep. Unlike `sway` (which oscillates on one axis and nets to zero), turbulence drives both axes and genuinely spreads the pool.\n- **`gust`** is a *global*, sinusoidally-oscillating horizontal acceleration (px/s²) layered on `wind`. The whole burst shares one phase, so it swells one way then the other in ~3s waves — a breeze gusting, not per-particle noise.\n\n```js\nc.burst({ turbulence: 400, gust: 250 });\n// confetti drifting on living air — each piece wandering, the whole pool breathing side to side\n```\n\nBoth draw **zero random values**: `turbulence` is a pure function of the seeded tumble phases the engine already advances, and `gust` of a shared elapsed-time clock — so a turbulent/gusty burst replays identically under a fixed seed (with its own committed fingerprints in the test suite), while the default `0` keeps every prior fingerprint (default, floored, and box) byte-for-byte unchanged. Both are accelerations applied *before* drag, exactly like `wind`, so they damp toward a terminal velocity and never run away; inside a [bounding box](#bounding-box) the edge clamps still hold, so a turbulent burst stays contained. Garbage fails closed to `0`; negatives are allowed (they flip direction). Neither has any effect under reduced motion.\n\n### Motion trails\n\nEvery feature above changes the **physics**. Trails (added in v1.9.0) are the first purely **visual** one: each particle leaves a fading ribbon through its recent positions, so a fast burst reads as motion streaks instead of hard dots. Trails are **opt-in at construction**, because the ribbon needs a *fixed* ring buffer of past positions — and a zero-GC engine can't grow one lazily, so its depth (the *capacity*) is set once when you create the instance:\n\n```js\nconst c = createConfetti(canvas, { trail: 16 });   // capacity: 16 samples of history per particle\nc.burst({ count: 120, speed: 500 });               // every particle now trails by default\nc.burst({ count: 40, trail: 6 });                  // a shorter ribbon for this burst\nc.burst({ count: 40, trail: 0 });                  // …or none for this one\n```\n\nThe per-burst `trail` sets the ribbon *length* (`0..capacity`); omit it and a trail-capable instance trails at full capacity. On an instance created without a `trail` budget the per-burst option is simply ignored (fail-closed, no throw).\n\nThe ribbon is a single **flat-alpha** stroke — one uniform-opacity line through the particle's recent positions, so the whole streak stays clearly visible. (A per-segment taper to a transparent tail was tried in 1.9.0 and reverted in 1.10.0: it read as too faint.)\n\nTrails are a **pure render overlay**. The ribbon is stroked in *world space* (`moveTo`/`lineTo`/`stroke`) — it never uses `translate` and never touches `x/y/vx/vy`, so it **cannot** perturb the determinism fingerprint: a trailed burst reproduces the exact same committed physics hash as an untrailed one, at any depth. The ribbon geometry is itself deterministic (its own committed `strokeHash` gate). Storage is a `Float32Array` ring buffer allocated **once** at construction (so `trail: 0`, the default, allocates nothing and is byte-identical to no trails), and recording + stroking are allocation-free on the hot path — verified at ~0 B/frame with a full trailed pool under the torture alloc gate. A garbage capacity fails closed to off or the 64-sample cap; on pool reuse a recycled slot's stale history can never leak (the live sample count resets at spawn). No effect under reduced motion.\n\n### Vortex\n\nEvery force so far is uniform in space (`gravity`, `wind`, `gust`) or per-particle random (`turbulence`). A **vortex** (added in v1.10.0) is the first force aimed at a *place* — a point that pulls, pushes, and spins the burst around itself, so confetti can collapse into a logo, drain into a hole, or spiral like a galaxy.\n\n```js\nc.burst({ attract: 6, swirl: 4 });                 // spiral inward around the burst origin\nc.burst({ attract: -8, x: cx, y: cy });            // blow the burst apart from its center\nc.burst({ swirl: 6, attractX: 400, attractY: 300 }); // orbit a fixed point, no net pull\n```\n\n- **`attract`** is a *linear spring*: the pull is `attract × (center − pos)`, so it grows with distance and is **zero at the center** — no `1/r` singularity, no NaN. A positive `attract` is a damped oscillator that spirals inward (`drag` bleeds the energy); a negative one repels.\n- **`swirl`** adds the perpendicular (tangential) component, turning the pull into a spiral; its sign picks the spin direction. Together `(attract, swirl)` apply the matrix `[[attract, −swirl], [swirl, attract]]` to the radius vector.\n- **`attractX` / `attractY`** set the center; they default to the **burst origin**, so a bare `attract`/`swirl` spins around where you fired.\n\nLike every force, the vortex draws **zero random values** — it's a pure function of the particle's own position and the burst center — so a vortexed burst replays identically under a fixed seed (with its own committed fingerprints for attract-only, swirl-only, and both), while the default `0` keeps every prior fingerprint byte-for-byte unchanged. It's applied *before* drag, so it damps toward the center and never runs away; inside a [bounding box](#bounding-box) the edge clamps still contain it. A negative `attract` is an unstable anti-spring, so a fail-closed acceleration cap guarantees a repeller can **never** drive a position to a non-finite value. Garbage fails closed (strengths → `0`, center → the burst origin); negatives are valid. No effect under reduced motion.\n\n### Settle & pile\n\nEvery earlier feature changed how a particle *moves* or *draws*. **Settle** (added in v1.11.0) is the first one that changes how a particle *ends*: instead of bouncing on the `floor` forever, a piece comes to **rest** and piles up — snow settling, ticker-tape drifting on the ground.\n\n```js\nc.burst({ floor: 520, bounce: 0.4, settle: 60 });   // fall, bounce a few times, then pile up\n```\n\n- **`settle`** is a *rest-speed threshold* in px/s. Each frame a piece bounces on the floor it loses energy (to `bounce` < 1 and `drag`); once the rebound is too weak to lift it — its post-bounce speed drops below `settle` — the piece **freezes**: velocity zeroed, pinned on the floor line, physics skipped. With `bounce = 0` a piece rests on first contact; a higher `bounce` just makes it bounce longer before it settles (`drag` still bleeds energy each frame), and with no `floor` nothing settles at all.\n- **It needs a `floor`.** Settle only ever fires as a piece lands on the floor, so with no floor set nothing settles (fail-closed).\n- **A settled piece keeps ageing and fades in place**, then its slot recycles — so the pile is a *transient drift* that builds and melts, and the fixed particle pool never fills up. (A permanent pile would saturate the pool and block new bursts, so it's deliberately not the default.)\n- A frozen piece is truly still: its **rotation is frozen too**, and lateral forces (`wind`, `gust`, `sway`) can't nudge it — a pile lies where it landed.\n\nLike every knob, settle draws **zero random values** (a pure function of the piece's own post-bounce velocity), so a settling burst replays identically under a fixed seed with its own committed fingerprint, and the default `0` keeps every prior fingerprint byte-for-byte unchanged. A garbage threshold fails closed to `0` (off). No effect under reduced motion — the static render never integrates, so nothing lands.\n\n### Friction\n\n`settle` freezes a piece the instant it comes to rest; **friction** (added in v1.21.0) is the softer, physical in-between — a piece that lands with sideways speed **skids** and slows along the floor instead of sliding forever. It's the first new physics knob since settle, and the tangential complement to `bounce`: on a floor contact, `bounce` reflects the *vertical* (normal) component while `friction` bleeds the *horizontal* (tangent) one.\n\n```js\nc.burst({ floor: 520, wind: 700, friction: 0.85 });   // fire sideways, land, skid to a stop\n```\n\n- **`friction`** is a coefficient `0–1`. On every floor-contact frame the horizontal velocity is multiplied by `1 - friction`: `0` is frictionless (the default — today's exact behaviour), `1` is full grip (a horizontal stop on the first contact), `0.2` a long skid, `0.8` a short one. With `bounce = 0` a piece is in contact every frame, so `vx` decays geometrically to a stop; with `bounce > 0` it bleeds a little speed on each landing.\n- **It needs a `floor`.** Friction only ever acts as a piece contacts the floor, so with no floor set nothing happens (fail-closed) — the same rule as `settle`.\n- **It's a *physics* knob, not a render overlay.** Unlike `align`/`scaleTo`/`fadeIn`/`fadeOut`, friction changes `vx` → position, so a friction burst has its **own** committed fingerprint; at `friction: 0` every prior fingerprint reproduces byte-for-byte (the guard is a plain `!= 0`, and `0` is exactly representable, so nothing drifts when off).\n- **Finite by construction.** The factor `1 - friction` is always in `[0, 1]` (a negative `friction` clamps to `0`, never an anti-friction speed-up), so it's a contraction — horizontal speed can only shrink, never grow, and no acceleration cap is needed. Zero random draws; no effect under reduced motion.\n- **`wallFriction` (v1.22.0)** extends the same idea to the box's other three edges. On a contact with a wall or the ceiling it bleeds the *tangential* component by `1 - wallFriction` — the ceiling damps horizontal `vx`, each wall damps vertical `vy`, always the component `bounce` does *not* reflect there, so it never cancels the rebound. It is **one shared coefficient** for the box's non-floor edges (the tangential analog to `bounce`'s single restitution; the ceiling rides along because `bounce` never split the box edge-by-edge). Like `friction` it is a contraction (finite, no acceleration cap), needs a box or no edge fires, and moves the position fingerprint (its own committed hash), while the floor keeps its separate `friction`. One subtlety: on a **resting** box (`bounce: 0`) `wallFriction` is *inert* — once the normal velocity is killed a piece pins to the edge and the strict guard never re-fires, so there's no tangential speed left to bleed and the committed box fingerprint is byte-identical; the grip bites only once pieces ricochet (`bounce > 0`) or are re-driven into an edge by sustained wind.\n\n```js\nc.burst({ ceiling: 40, wallLeft: 60, wallRight: 740, floor: 560, bounce: 0.6, wallFriction: 0.6, wind: 300 });\n```\n\n### Spin drag\n\n`drag` has damped a piece's **translation** every frame since day one — but its **spin** was drawn once at birth and tumbled at that rate forever. **`spinDrag`** (added in v1.23.0) is the angular mirror: each frame, immediately before the spin advance, `spinV *= spinDrag`, so the tumble decays exactly as `drag` decays motion. It's the last unmirrored asymmetry in the integrator closed.\n\n```js\nc.burst({ spinDrag: 0.9, turbulence: 300 });   // pieces tumble fast, then settle to a lazy drift\n```\n\n- **`spinDrag`** is a retention `0–1`: `1` = off (tumble forever, today's exact look), `0.95` a gentle decay to a lazy drift, `0` an instant freeze at the birth angle. Coerced with `clamp01` like `drag`/`bounce` — a **negative** clamps to `0` (freeze; a retention has no direction, unlike `spinRate`'s reverse), non-finite → `1`, `> 1` → `1` (which would otherwise *amplify* spin and diverge). It's a contraction, so `|spinV|` can only shrink and no acceleration cap is needed. It damps `spinV` only, never `tiltV` (the wobble phase feeds `sway` and the turbulence curl).\n- **It's a *hybrid physics* knob, not a pure render overlay.** `pool.spin` is read in exactly two places — the render rotation and the turbulence curl (`tilt*1.7 + spin`). So with **`turbulence` off** a slower spin moves only the render rotation and the seeded **position** stream is byte-identical (only `rotateHash` moves, its own committed fingerprint); with **`turbulence` on** the curl reads the slower spin, so it moves positions too (a second committed fingerprint on the same turbulence baseline). At `spinDrag: 1` every prior fingerprint — `rotateHash` included — reproduces byte-for-byte. Zero random draws; no effect under reduced motion (the static render never advances spin).\n\n### Color over life\n\nUntil now a piece was painted **one flat color** from birth to death. **`lifeColors`** (added in v1.12.0) lets the **body** of each piece sweep a multi-stop OKLCH ramp as it *ages* — a spark cooling white → orange → red, an ember dimming, a firework tail shifting hue.\n\n```js\nc.burst({\n    lifeColors: [\n        { l: 0.98, c: 0.02, h: 90 },  // birth: near-white\n        { l: 0.72, c: 0.22, h: 60 },  // mid: gold\n        { l: 0.40, c: 0.15, h: 30 },  // death: deep orange\n    ],\n});\n```\n\n- **`lifeColors`** is an ordered list of **≥ 2 OKLCH stops**, birth-color first, death-color last. Each piece's body color is read from the ramp by its life fraction (birth = first stop, death = last).\n- **Baked once per burst.** The ramp is interpolated in OKLCH into a small lookup table of CSS strings ([`bakeCssGradient`](../LiteColor)) when the burst fires, so the render loop is a pure array read — no per-frame color math, no allocation.\n- **The trail stays flat.** Only the body sweeps the ramp; the motion-trail ribbon keeps drawing the piece's flat `colors` pick (the trail is a simple flat overlay). The palette `colors` is still picked per particle — it's the trail color, and the body color when `lifeColors` is off.\n- **All pieces share one ramp.** Variety comes from pieces being at *different* life phases, so a stream reads as a coherent gradient of ages (perfect for sparks).\n\n`lifeColors` is a **pure color overlay**: it draws **zero random values** and moves no particle, so a `lifeColors` burst replays with the exact same positions as a plain one — every physics fingerprint is preserved byte-for-byte. An invalid or too-short ramp fails closed to the flat color. No effect under reduced motion — the static render paints the flat color.\n\n### Emitter shapes\n\nEvery burst so far spawned from the **single point** `(x, y)`. **`emit`** (added in v1.13.0) distributes the spawn **origin** over a shape, sized by the single `emitSize` scalar — so confetti can rain from a line, expand from a shell, or fill an area.\n\n```js\n// A firework shell: pieces fly radially OUTWARD from a ring.\nc.burst({ x: 400, y: 300, emit: 'ring', emitSize: 140, speed: 6, count: 160 });\n\n// A rain / snow curtain: spawn along a horizontal line across the top, fall under gravity.\nc.spray({ x: 400, y: 0, emit: 'line', emitSize: 300, angle: Math.PI / 2, gravity: 0.4 });\n```\n\n- **`emit: 'line'`** — a horizontal segment centered on `(x, y)`, half-length `emitSize` (a rain / snow curtain).\n- **`emit: 'ring'`** — the circle of radius `emitSize` around `(x, y)`. Each piece is fired **radially outward** from the centre, so `speed` becomes the shell expansion rate and `spread` the angular fuzz — a firework shell.\n- **`emit: 'box'`** — the square `[x ± emitSize, y ± emitSize]` (an area burst).\n- **Line and box move only the origin** — velocity stays governed by `angle` / `spread`. The radial-outward coupling is **ring-only**.\n\n`emit` is a **pure origin choice**: it is the first knob to draw a random value *at spawn* (the position along the shape), so it is opt-in by construction — with `emit` off, unknown, or `emitSize ≤ 0`, the burst spawns at the point and every committed fingerprint is byte-identical. Each shape has its own deterministic fingerprint when on. Fails closed to a point spawn on a bad shape or size; no effect under reduced motion.\n\n### Staggered emission\n\n`emit` chose *where* a piece is born; **`stagger`** (added in v1.14.0) chooses *when*. A burst has always spawned its whole `count` at frame 0; `stagger` (a duration in **ms**) spreads those births evenly across the window, so a burst **cascades / ripples in** instead of appearing all at once.\n\n```js\n// A 120-piece burst that pours in over 400ms instead of popping instantly.\nc.burst({ x: 400, y: 300, count: 120, stagger: 400 });\n```\n\n- Piece `i` wakes at `stagger · i / count` ms and then lives its **full life from birth** — so a late piece outlives the early ones by the width of the window.\n- **Burst-only.** This is the burst analog of a spray's `duration`; a `spray()` already emits over time, so it ignores `stagger`.\n- **How it stays deterministic.** All `count` pieces still spawn at call time, drawing the *identical* rng sequence as a synchronous burst; each is stamped with a **no-rng** per-index delay, and an unborn piece is frozen and invisible until it elapses. So with `stagger` off (or `≤ 0` / non-finite) the burst spawns synchronously and every committed fingerprint is byte-identical; on, it earns its own deterministic fingerprint purely from birth *timing*. Fails closed; no effect under reduced motion.\n\n### Velocity-aligned orientation\n\nFor fourteen releases a piece's rotation was only ever *random tumble*. **`align`** (added in v1.15.0, a `0..1` blend) rotates each piece **broadside to its live velocity** — its flat face square to the airflow, like a falling leaf — re-banking every frame as gravity, wind, or a vortex bend its path.\n\n```js\n// Leaves banking into a gentle drift — face-first to wherever the air pushes them.\nc.burst({ x: 400, y: 200, count: 80, gravity: 200, wind: 300, spread: 0.4, align: 1 });\n```\n\n- **`0`** is pure random spin (the classic look); **`1`** is fully velocity-locked; partial values blend the two along the shortest arc.\n- **Live + broadside.** The heading is recomputed from the current velocity each frame and offset by 90° so the broad face meets the direction of travel. Draws **no rng**.\n- **A pure orientation overlay.** `align` changes only *rotation*, never position — so the seeded position stream (and every committed fingerprint) is byte-identical whether `align` is off or on; only the rotation earns its own deterministic fingerprint. Honored by both `burst()` and `spray()`. Fails closed (coerced to `[0, 1]`); no effect under reduced motion.\n\n### Tumble speed\n\n`align` opened *which way* a piece faces; **`spinRate`** (added in v1.16.0) tunes *how fast* it tumbles. For fifteen releases the tumble rate was a fixed seeded random, so slow drifting petals, frozen rigid chips, and reverse tumble were all unreachable. `spinRate` is a plain multiplier on the accumulated tumble.\n\n```js\n// Slow, lazy petals drifting down — a third of the seeded tumble rate.\nc.burst({ spinRate: 0.3, gravity: 200 });\n```\n\n- **`1`** (default) is the seeded rate as-is; **`0`** is rigid — frozen at each piece's *random birth tilt* (varied, not axis-aligned); **`0.3`** is a lazy drift; **`2`** doubles the tumble; a **negative** value reverses it. Coerced with `num` (`0` and negatives are valid; non-finite → `1`), never `clamp01` — a rate multiplier is not a `0..1` blend.\n- **A pure orientation overlay, turbulence-safe.** `spinRate` is a render-time *angle scale*: it scales only the accumulated tumble about the birth orientation and **never touches the physics spin** the turbulence phase reads. So it is fully decoupled from `turbulence`, and the seeded position stream (and every committed fingerprint) is byte-identical whether off, on, or on-with-turbulence — only the rotation earns its own deterministic fingerprint. Composes with `align` (the tumble scale runs first, then `align` blends toward the velocity heading). Draws **no rng**. Honored by both `burst()` and `spray()`; inert under reduced motion.\n\n### Size over life\n\nEvery render axis had been opened *except* size: for sixteen releases a piece's size was fixed at birth (`pool.w`/`pool.h` drawn once and never changed), so a piece that **shrinks away to nothing** or an ember that **blooms as it dies** was unreachable. **`scaleTo`** (added in v1.17.0) lerps each piece's *rendered* size from `1.0` at birth to `scaleTo` at death, by the **same** age fraction the `lifeColors` ramp uses.\n\n```js\n// Sparks that shrink out as they cool — scaleTo composes with the color ramp on one life fraction.\nc.burst({ scaleTo: 0.1, gravity: 300, lifeColors: ['#fff', '#f80', '#a00'] });\n// A bloom: pieces grow as they fade.\nc.burst({ scaleTo: 2.5, gravity: 200, shape: 'circle' });\n// Pop-in: born small, settle to full size as the birth fade eases in (v1.24.0).\nc.burst({ scaleFrom: 0.2, scaleTo: 1.4, fadeIn: 0.3 });\n```\n\n- **`1`** (default) is constant size; **`0.2`** shrinks out, **`2`** grows/blooms, **`0`** vanishes at death. `s = scaleFrom + (scaleTo − scaleFrom) × (1 − lifeT)`, reusing the life fraction already computed for the opacity fade and the color ramp. Coerced with `nonneg`: a **negative** clamps to `0` (a size has no direction — *not* a mirror flip, *not* a fallback to `1`; `scaleTo: -2` renders like `scaleTo: 0`), non-finite → `1`. `scaleTo: 0` is a legitimate value (the size analog of `spinRate: 0`).\n- **`scaleFrom`** (v1.24.0) is the **birth endpoint** — the mirror `scaleFrom:scaleTo :: fadeIn:fadeOut` that closes the render-scale axis. Default `1` leaves the ramp starting at birth size (today's exact look); `scaleFrom: 0.2` blooms up from a fifth-size, `scaleFrom: 2` starts double and settles, and `scaleFrom == scaleTo` is an emergent constant multiplier. It supersedes the `0018` deferral note (which wrongly assumed `sizeMin`/`sizeMax` already covered a birth-size *override* — those set the constant birth size, they don't move the ramp's origin). Same `nonneg` coercion (a negative is born invisible, not a fallback to `1`); folded into the **same single** `ctx.scale` as `scaleTo`.\n- **Isotropic, one `ctx.scale`.** The factor is applied to **both** axes and **folded into flutter's single existing `ctx.scale` call** — the X-wobble and the size ramp multiply on one transform, never a second call. `pool.w`/`pool.h` are **never touched**.\n- **A pure render overlay.** Scale never enters `ctx.translate`, so the seeded position stream (and every committed fingerprint) is byte-identical whether off or on — a scaled burst reproduces the same-seed plain burst's position hash exactly (invisible to the rotation and color fingerprints too); only the size fold earns its own deterministic fingerprint. The **trail ribbon keeps its birth width** (the ramp scales the body, not the streak). Draws **no rng**. Honored by both `burst()` and `spray()`; inert under reduced motion.\n\n### Wobble speed\n\n`spinRate` tuned how fast a piece *tumbles*; **`flutterRate`** (added in v1.18.0) tunes how fast it *wobbles* — the speed knob to what `flutter` opened as depth. `flutter` sets the depth of the 3D-ish X-scale wobble (`wobbleScale = 1 − flutter × 0.5 × (1 − |cos(tilt)|)`), driven by the per-particle tilt phase the integrator advances every frame; but its *speed* (`tiltV`) was a fixed seeded random, so a slow lazy flutter, a wobble frozen at a chosen tilt, or a fast shimmer were all unreachable. `flutterRate` is a plain multiplier on the accumulated wobble phase about a stored birth pivot.\n\n```js\n// A wobble frozen at each piece's own birth tilt — flutter must be on for a rate to matter.\nc.burst({ flutterRate: 0, flutter: 1, gravity: 200 });\n// A fast shimmer: the wobble advances twice as quickly.\nc.burst({ flutterRate: 2, flutter: 1 });\n```\n\n- **`1`** (default) is the seeded rate as-is; **`0`** freezes the wobble at each piece's *own random birth tilt* (a varied constant per piece, not collapsed to one value); **`0.3`** is a slow lazy flutter; **`2`** is a fast shimmer; a **negative** value reverses the phase. Coerced with `num` (`0` and negatives are valid; non-finite → `1`), never `clamp01` — a rate multiplier is not a `0..1` blend.\n- **Inert when `flutter` is 0.** `flutter` (depth) multiplies the whole `(1 − |cos|)` term; at `flutter: 0` the wobble is `1` regardless of the phase, so there is no speed to scale. So a `flutterRate` demo always sets `flutter: 1`.\n- **A pure render overlay, turbulence-safe.** `flutterRate` is a render-time *phase scale* about a birth pivot `tilt0`: it scales only the accumulated wobble phase and **never touches `pool.tilt`** — the phase the `turbulence` curl and `sway` read. So it is fully decoupled from both, and the seeded position stream (and every committed fingerprint) is byte-identical whether off, on, or on-with-turbulence — only the wobble earns its own deterministic fingerprint (reusing the `scaleHash` probe, no new channel). Draws **no rng**. Honored by both `burst()` and `spray()`; inert under reduced motion.\n\n### Birth opacity\n\nFor eighteen releases a piece's *opacity* had exactly one hardcoded behaviour: a death fade-*out* over the last 30% of life. **`fadeIn`** (added in v1.19.0) opens the render-opacity axis — an opt-in scalar that **ramps a piece up from transparent over the first `fadeIn` fraction of its life**, so it *materializes in*. It is the mirror of the death fade, on the same `alpha` scalar, by the same age fraction (`1 − life/maxL`) the death-fade and `lifeColors` already use.\n\n```js\n// Materialize in over the first 40% of life, then the built-in death fade takes it out.\nc.burst({ fadeIn: 0.4, gravity: 300 });\n// Compose with size-over-life: a piece that fades in AND shrinks out.\nc.burst({ fadeIn: 0.4, scaleTo: 0.2, gravity: 200 });\n```\n\n- **`0`** (default) is today's instant-on look; **`0.4`** eases in over the first 40% of life; **`1`** ramps across the whole life. Coerced with `clamp01` (non-finite / non-numeric / undefined / negative → `0` off; `> 1` → `1`), exactly like `align` — a fraction of life, not a rate.\n- **It multiplies the existing alpha.** The birth fade-in and the hardcoded death fade-out act on the *same* `alpha`: for a normal life they fall in disjoint windows (in near birth, out near death); for a very short life they overlap and correctly multiply. The death fade-out is unchanged.\n- **The cleanest pure render overlay in the suite.** `fadeIn` changes only `ctx.globalAlpha` — it never touches `pool.x/y/vx/vy` or `ctx.translate`, draws **no rng**, and reads only the life fraction, so the seeded position stream (and the rotate/scale/stroke/color fingerprints) is byte-identical whether off or on; only the alpha earns its own deterministic fingerprint. Unlike `spinRate`/`flutterRate` it needs no birth pivot and no decoupling machinery — nothing downstream reads alpha.\n- **The trail materializes in with the body.** The ribbon already tracks the body `alpha` (the death fade dims it too); folding `fadeIn` in before the trail block makes the streak fade up with the body for free — no independent trail opacity, and the trail *geometry* fingerprint is untouched. Honored by both `burst()` and `spray()`; inert under reduced motion (the constant static opacity is untouched).\n\n### Death opacity\n\nFor nineteen releases the *other* half of the opacity envelope — the death fade — was a magic `0.3` baked into the render body (dissolve over the last 30% of life). **`fadeOut`** (added in v1.20.0) parameterizes it: the **fraction of life over which a piece dissolves out at the end**. Together with `fadeIn` it **completes the opacity envelope** — materialize in, hold, dissolve out — both multiplying one shared `alpha`.\n\n```js\n// The full envelope: fade in over the first 20%, dissolve out over the last 90%.\nc.burst({ fadeIn: 0.2, fadeOut: 0.9, gravity: 200 });\n// A hard cut — full opacity, then gone (no death fade at all).\nc.burst({ fadeOut: 0 });\n```\n\n- **`0.3`** (default) is today's exact look; **`0.6`** is a long gentle dissolve; **`0.1`** a quick blink-out; **`0`** a hard cut; **`1`** dissolves across the whole life. Coerced with `clamp01` against a `Math.fround(0.3)` sentinel — non-finite / undefined → the `0.3` default; **negative → `0`** (a hard cut, *not* a fallback to the default), `> 1` → `1`.\n- **The `Math.fround(0.3)` sentinel is the whole off-identity story.** The default `0.3` lives in a `Float32Array`, and `Math.fround(0.3) !== 0.3` (the round-trip is lossy), so the render guard compares against the *frounded* sentinel and leaves the original double-`0.3` death-fade line byte-for-byte unchanged. At the default the guard never fires, so the committed opacity fingerprint is preserved bit-for-bit. (Contrast `scaleTo`/`scaleFrom`/`spinDrag`, whose default `1` *is* Float32-exact — `Math.fround(1) === 1` — so their `!= 1` guards need no sentinel.)\n- **Always written at spawn — load-bearing here.** Unlike `fadeIn` (whose zero-init `0` happens to mean \"off\"), a zero-init `0` for `fadeOut` means \"hard cut, no death fade\" — a *wrong* default — so the unconditional spawn write is a fail-closed requirement, not just house style.\n- **Reuses `fadeIn`'s probe with no harness change.** As the second knob on the opacity axis, `fadeOut` rides the exact determinism probe v1.19.0 built — the first render feature to cost no new test-harness plumbing. The trail dissolves out with the body; inert under reduced motion.\n\n### Canvas Sizing\n\nlite-confetti uses **ResizeObserver** (not polling) to track canvas dimensions. The observer watches the canvas's parent element, RAF-deduped to prevent double-fire. `clientWidth` / `clientHeight` are never read in the hot loop — only cached `cw` / `ch` variables are used during rendering. This prevents layout thrashing at 60fps.\n\n---\n\n## Shapes\n\n| Shape | Description |\n|---|---|\n| `'rect'` | Classic confetti rectangle (default). Height varies 40–100% of width for natural variation. |\n| `'circle'` | Round confetti dots |\n| `'star'` | 5-pointed star with 40% inner radius |\n| `'triangle'` | Equilateral triangle piece |\n| `'emoji'` | Any emoji character — set via `emoji` option (e.g. `'🌟'`, `'🎊'`, `'❤️'`) |\n\nEmoji shapes are rendered through a **glyph atlas**: each unique emoji is rasterized once to a small offscreen canvas the first time it is used, then drawn per particle as a cheap `drawImage` blit. This keeps a burst of hundreds of emoji particles as cheap as any other shape. (Earlier versions set `ctx.font` and called `fillText` per particle per frame, which re-rasterized the colour glyph every time — a burst of many emoji could stall the main thread.)\n\n### Custom shapes — `registerShape(name, def)`\n\nRegister your own shape on an instance, then use it as `burst({ shape: name })`. Shapes are **per-instance**: they are invisible to other instances and released on `destroy()`, so registration never leaks across instances and determinism stays sealed to the seed.\n\n```js\nconst c = createConfetti(canvas);\n\n// 1. A VECTOR shape — a draw function. The engine sets fillStyle to the particle's\n//    colour before calling, so a plain fill() is coloured for you. Drawn centred at (0,0).\nc.registerShape('heart', (ctx, w) => {\n  const s = w / 16;\n  ctx.beginPath();\n  ctx.moveTo(0, 4 * s);\n  ctx.bezierCurveTo(-7 * s, -3 * s, -3 * s, -8 * s, 0, -3 * s);\n  ctx.bezierCurveTo(3 * s, -8 * s, 7 * s, -3 * s, 0, 4 * s);\n  ctx.fill();\n});\nc.burst({ shape: 'heart', count: 80 });\n\n// 2. An IMAGE SPRITE — prerendered once, then blitted per particle (same fast path as emoji).\nconst logo = new Image();\nlogo.src = '/logo.png';\nc.registerShape('logo', { image: logo });     // an <img>, a <canvas>, or an ImageBitmap\nc.spray({ shape: 'logo', duration: 1500 });\n```\n\n`registerShape` returns the assigned shape id (`>= 5`; built-ins keep `0–4`). Re-registering a custom name replaces it and keeps its id. It **fails closed** — an empty/non-string name, a built-in override (`'rect'`, `'emoji'`, …), or a malformed `def` throws. A typo'd `shape` name at `burst()` time does not throw; it falls back to `'rect'`.\n\n### Mixing shapes\n\nPass `shapes` (plural) to mix several shapes in **one** burst — each particle picks its own, so you get a confetti spread of stars *and* circles *and* rectangles without firing three overlapping bursts:\n\n```js\nc.burst({ shapes: ['star', 'circle', 'rect'] });\n\n// Repetition weights the mix — this is ~2:1 stars to circles:\nc.burst({ shapes: ['star', 'star', 'circle'] });\n\n// Custom registerShape() names compose for free:\nc.registerShape('logo', { image: logo });\nc.burst({ shapes: ['rect', 'logo', 'star'] });\n```\n\n`shapes` overrides the singular `shape`. It **fails closed** the same way everything else does: unknown names are dropped, and an empty / non-array / all-unknown `shapes` falls back to `shape`. Mixing is deterministic under a seed and per-instance (a `shapes` entry naming another instance's custom shape is dropped, never borrowed). Omitting `shapes` is free — the single-shape path is byte-for-byte unchanged, committed fingerprint and all.\n\nCustom shapes go through the same zero-allocation dispatch as the built-ins — the torture gate proves a live pool of a custom vector shape + an image sprite renders at ~0 bytes/frame.\n\n---\n\n## Presets\n\nFive drop-in configs for iconic effects. Spread them into `burst()` or `spray()`:\n\n```js\nimport { createConfetti, presets } from '@zakkster/lite-confetti';\n\nconst c = createConfetti(canvas, { seed: 1 });\nc.burst({ ...presets.fireworks });          // stars, explosive, upward\nc.burst({ ...presets.cannons, x: 0 });      // angled launch — override origin\nc.spray({ ...presets.snow, duration: 8000 }); // gentle falling, long life\nc.burst({ ...presets.pride });              // OKLCH rainbow palette baked in\nc.burst({ ...presets.blast, y: innerHeight }); // max-power cannon from the bottom\n```\n\nBecause a preset is just an options object, anything you add after the spread wins — `{ ...presets.snow, gravity: 200 }` keeps the snow look but drops faster. Every preset's `shape` is one of the five the engine renders, and every preset stays deterministic under a fixed seed (the test suite checks both).\n\n### Reach / power\n\nIf a burst feels weak — it barely leaves the origin instead of arcing up the screen — the lever is `speed`, not `wind`. Vertical reach is `speed^2 / (2 * gravity)`, throttled further by the per-frame `drag`, so with the default straight-up `angle` a piece rises about `speed^2 / (2 * gravity)` pixels before falling back. The gentle default `speed: 400` (with `gravity: 600`, `drag: 0.98`) rises only ~160px; to clear half a 1080-tall screen from the bottom you want `speed` around 1200-1500, and a looser `drag` (e.g. `0.99`) lengthens the arc. `wind` is a purely horizontal force (the X-mirror of `gravity`), so it drifts a burst sideways but adds **zero** vertical reach — combining `speed` with `wind` reaches exactly as high as `speed` alone. `presets.blast` is the ready-made half-screen cannon: `c.burst({ ...presets.blast, x, y: innerHeight })` peaks at ~1025px of rise on a 1080 screen.\n\n## Palette import (lite-hueforge)\n\n`colorsFromPalette()` turns a [lite-hueforge](https://github.com/PeshoVurtoleta/lite-hueforge) `toGradientStops()` result straight into a `colors` array:\n\n```js\nimport { colorsFromPalette } from '@zakkster/lite-confetti';\nimport { toGradientStops } from '@zakkster/lite-hueforge';\n\nconst stops = toGradientStops(myPalette);        // [{ color: {l,c,h}, stop }, ...]\nc.burst({ colors: colorsFromPalette(stops), count: 120 });\n```\n\nIt also accepts a `{ stops }` wrapper, a plain colors array (pass-through), or a single color. It **never returns an empty array** — an empty `colors` would make the picker paint nothing, so bad input falls back to the default palette.\n\n## Burst from an element\n\n`fromElement()` reads `getBoundingClientRect()` **once** and returns the element's centre as a burst origin:\n\n```js\nimport { fromElement, presets } from '@zakkster/lite-confetti';\n\nbutton.addEventListener('click', () => {\n  confetti(fromElement(button, { ...presets.cannons }));\n});\n```\n\n**Coordinate space matters.** The returned `x`/`y` are in *viewport* coordinates — correct as-is for a full-screen overlay canvas (what `confetti()` creates, and what most apps use). For an **inline or offset** canvas, subtract that canvas's own rect:\n\n```js\nconst o = fromElement(button);\nconst cr = canvas.getBoundingClientRect();\nc.burst({ x: o.x - cr.left, y: o.y - cr.top, count: 60 });\n```\n\n## Pointer-follow spray\n\n`spray({ followPointer: true })` makes the stream chase the pointer inside the canvas:\n\n```js\nc.spray({ ...presets.fireworks, duration: 4000, followPointer: true });\n```\n\nThe pointer is tracked by a **passive** listener that binds only while a follow-spray is running, and unbinds when it ends (or on `destroy()`). Nothing is installed at import time, so a page that never follows the pointer pays nothing. Coordinates are converted from viewport space into the canvas's own space, so it works for inline and CSS-scaled canvases, not just full-screen overlays.\n\nOne caveat, by design: **pointer-follow is not deterministic** — it injects live pointer positions the seed can't know. It consumes no RNG draw, so a *non*-following spray still replays identically from a seed; a following one won't.\n\n## Recipes\n\n<details>\n<summary><strong>Checkout Success</strong></summary>\n\n```javascript\nimport { confetti } from '@zakkster/lite-confetti';\n\nsubmitBtn.addEventListener('click', () => {\n    confetti({\n        count: 100,\n        spread: ","readmeFilename":"README.md"}