{"_id":"srcdev-hair-treatments","_rev":"30-94aa691b4d00a9c443210a0a022f61fe","name":"srcdev-hair-treatments","dist-tags":{"alpha":"1.2.1-alpha.3","latest":"1.4.1"},"versions":{"0.1.1":{"name":"srcdev-hair-treatments","version":"0.1.1","license":"MIT","_id":"srcdev-hair-treatments@0.1.1","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"472153ab12c95bb9da1bfc4d79764d73cc3dacde","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.1.tgz","fileCount":23,"integrity":"sha512-/vhDB0j4a5FzwyB0DAmLb36bpCAmSrLu8HMOWkV5vdsTPHoJ7zfTFf58l2KeBc8TbY9pQjXs38V6tauYG2y1mg==","signatures":[{"sig":"MEQCIHo2lNjGtTbAXbm7pmmu4ph06xKLlk+av++4/nMa/dV4AiBTDVSj9mZhrwuYk2lMnN+d9Q/ytyW2H/YqolMC5e8IKA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3802142},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"}},"gitHead":"edeb20f6d1b875e1511d3f0d1e418f31f6a5c8ae","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vue-tsc --declaration --emitDeclarationOnly && vite build","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.1_1774902799882_0.03726153454110004","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"srcdev-hair-treatments","version":"0.1.2","license":"MIT","_id":"srcdev-hair-treatments@0.1.2","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"6806257e7a32afc0de4e9fd68862e3f6bb26f2d2","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.2.tgz","fileCount":30,"integrity":"sha512-OV1dobkYqy44hAFnmLrx7xl/0JxHEvMIpBe4Vfp/4LGR+tUn3pnD84dORzaFeEP/wjoyqlFh7yPlwBdM6YIDlA==","signatures":[{"sig":"MEUCIQDTGzzmKc5t1HJlJkwQztcbsC7eo03Nczv1OFOYcwy+rAIgbvTDYrP+wzm5luVxXm7S1Tj2Pt9ZSuPeNQwxdFJW/nQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3809471},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"}},"gitHead":"5f56a9534c847824ae21d3e936f38994333e1beb","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.2_1774904539493_0.22676779102984423","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"srcdev-hair-treatments","version":"0.1.3","license":"MIT","_id":"srcdev-hair-treatments@0.1.3","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"10185761019d6183a396f333a069b6fa5ca30bff","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.3.tgz","fileCount":30,"integrity":"sha512-Yh8VGqicSwkzOJBuV6RH/MESleqUwsZFy2Xr+Yuk3ek9SpTvgKJcXzDG1ANKZ/VLPruH8uSSy9y+nkDMykrH2w==","signatures":[{"sig":"MEYCIQCwJpZAOjV/91HvTxUFjG3h4Nua9CfRkPm03Bvy57RngAIhAJ4mSxtyU/FpPFgz74iPS8pwl7tcvTKTttgH8WcIB9G2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3809515},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"2b05a22b61c1f487df163c5e681505c9ec2030b9","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.3_1774904960722_0.28936490888255384","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"srcdev-hair-treatments","version":"0.1.4","license":"MIT","_id":"srcdev-hair-treatments@0.1.4","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"fadfd0298d5456320eb4876a7da65b879c9aca3d","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.4.tgz","fileCount":30,"integrity":"sha512-VqZGnGTdPMlc+YIriCuKZsOYDr7vtCQ+3pX4iHwBPxMLm29Q+QwYAPf7MckvFl9RucaDtR8wNMxolqjGUNYmbw==","signatures":[{"sig":"MEUCIH4z0Lnn6S3x+XJdu7nDe42ldEJ3vNJtX4Dzu+yM0Y4MAiEAg/ENF3uaSlS2BwoqcFbaJwr7G0OtMlbpf7YCzk7CMw0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3814665},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"0a7b673cb7a7fe2c0dd1f87b544115cf8a28f8bc","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.4_1774990604693_0.14406311811120265","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"srcdev-hair-treatments","version":"0.1.5","license":"MIT","_id":"srcdev-hair-treatments@0.1.5","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"1d3efbc005d94c9cb2b1c0a9fe85762a73aaa03f","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.5.tgz","fileCount":35,"integrity":"sha512-fGXG3O0vFhoQoUJKZywpri1XlPe8D5+uInce3wocL+N7Xryl1qFdnuKYzyVdG2NgcTk8rfUAqt3i44f13iPseQ==","signatures":[{"sig":"MEYCIQDo50MI9FM7UgJdUHTzQSj0c0Z9SOI0RK3OSowYLkXPvwIhAPCPV+aqOSerMrNWVCRAp8SHCS8vXenwGOKUKWPbnO+s","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3896108},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"d7ac79cf2fbc4e4895e467dd7296120d47c27473","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.5_1775226311915_0.7091546749439581","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"srcdev-hair-treatments","version":"0.1.6","license":"MIT","_id":"srcdev-hair-treatments@0.1.6","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"26ad25690d3659a550fe5734d4e6d53ee01e2e80","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.6.tgz","fileCount":35,"integrity":"sha512-yu4tXLqQVff4Fe87/BX/gdN2vcIDe321Zrwt27b9aFQjU12PSV/3rU4kZPmEhFhDHRr62O5uo7M2YA6x4hzzKw==","signatures":[{"sig":"MEUCICWnt2qLh/fyuRGeIAsV4pug8K4vltlEL2KVgCVWuVVgAiEAvvbN57RfTr5fuR46rG0TIUT25KygECE89Oq+lhu0/wo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3915790},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"738787547361802c9e7ebb47a7032f0f570ec4c2","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.6_1775257864286_0.6736392557198743","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"srcdev-hair-treatments","version":"0.1.7","license":"MIT","_id":"srcdev-hair-treatments@0.1.7","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"af043977735cbe8bba9c29877246b6d1787a8ac5","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.7.tgz","fileCount":35,"integrity":"sha512-PoI7cEnA30O22Ta/XZ79DtfvsB61/tC1tuXg7yhdEd8bGGQ+XLHdKcaJArrTHtBz5ku+MioU7DGLDiOy2uY8Uw==","signatures":[{"sig":"MEUCICzpjQ3l4OD2Lhgrd67kAZLqunAwjCT5ioqR5lFKXhIDAiEAqe6UYyw09x7+L0q+8NU/Umvq1kyl3KOljnNyGd2FiP0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3915745},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"67f229c426ef33b91c9e3f82de4a029a3d45612f","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.7_1775259386699_0.5516831878733846","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"srcdev-hair-treatments","version":"0.1.8","license":"MIT","_id":"srcdev-hair-treatments@0.1.8","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"866fab6378d915afcbede4c09395ff013b5aae9c","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.1.8.tgz","fileCount":35,"integrity":"sha512-+VRwTvUKPMo2aFyxX3eO7VScC/w5FUKzu5ISqk9BN5soI1mC2g3l9R+vhg8DFyWNaeSSrIcSQJmOESZjrJUZlw==","signatures":[{"sig":"MEUCIDZ/JQV8vzVWtT0Nq0ZEPBCNHlusUlrZa79pg4FR9hf6AiEAvLRRogM+w/meItTZUBT6bvqYCerdFV4WK2AmXeDzyOE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3909978},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"5802db661f859719a4b9f2cda8e781989712ce53","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.6.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.1.8_1775261639662_0.6335039505334108","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"srcdev-hair-treatments","version":"0.2.0","license":"MIT","_id":"srcdev-hair-treatments@0.2.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"f3802c1e96a033f31d9f8ab4b614ca5ccf62111b","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.2.0.tgz","fileCount":42,"integrity":"sha512-g/7/B+VYWKop36rH2kOvBWKfXCZabOYYKqULlWvmAwD4FS9yiN7oWKBfIhcjUg9T0mkOqjYFExAc0THWu0LkrA==","signatures":[{"sig":"MEYCIQCTAsReFrDKVHbb1DU+R6ONnjMnZ+IYmPH/U5fyFYQQoAIhAMqXzLk9A+yFdDiHL3ncIzTfsdGeUDdqPlC/3KMz+HOt","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3840217},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"71ddfe556dc14bd058a71c7cafbabebac9c077f4","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.2.0_1780789370668_0.4308930511462965","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"srcdev-hair-treatments","version":"0.2.1","license":"MIT","_id":"srcdev-hair-treatments@0.2.1","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"101f761d40158ba392050ca15600e904b5048902","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.2.1.tgz","fileCount":46,"integrity":"sha512-XNoCmkbyuVI/fSht0XX6H7VZxGQP39FjF/VtdWqiCZ3AExRticIbJmwMepWEpPzf/M2PsX/0GtLuqTeeRKwSng==","signatures":[{"sig":"MEQCIEE5kwfZzTaj9Eh0Dvx4syVmISR79p1mujsN5Gn5hTFSAiBOcWjB/0q4kQxMY5DVq6Cl/60IinsKXiau5mnE60XSwg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":6886535},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"npm":">=10.0.0","node":">=20.19.0 <23"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"53eb58e2d42c831b097c2f18f78d8819a8b0790e","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.2.1_1780842753205_0.1941475466118301","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"srcdev-hair-treatments","version":"0.2.2","license":"MIT","_id":"srcdev-hair-treatments@0.2.2","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"0ad5a06beda78f7e722d74720701abdb6d2c5e13","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.2.2.tgz","fileCount":64,"integrity":"sha512-Dcpea3jMZxLJDt17fMtCNUkUSaMoRhzDswKUvsr66JaqCX3vYaEeCrcoC8s9GisOdyVEdruW80QFYS7ySP+UFQ==","signatures":[{"sig":"MEUCIDGwUndXeV/HiTvhJRm9fso76nJqEImbXlutqhmUmH7/AiEAm/FARuxQCFHw4OqhR5TcySWds9Z8nfUJGLg0BkjYQ4k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13580623},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css"},"gitHead":"95929d198b95d2cad0fe4c85649c226eda8a38f6","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.2.2_1780861696229_0.01756828228533358","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"srcdev-hair-treatments","version":"0.2.3","license":"MIT","_id":"srcdev-hair-treatments@0.2.3","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"7accf8a53a5c0c8bb93c96819cffa065453d7c53","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.2.3.tgz","fileCount":67,"integrity":"sha512-Jegurn1fTQz257vfeH/fD84zOQL5ZypGpouyJdoUK/lskSC86haZu0FcjWiG7MhY/HW8mV16nSkbFA0qpycP8Q==","signatures":[{"sig":"MEUCIQDAmP8XizZ25W2nHdy4VcjTYp/hueLsxlP22jAsFbr8TQIgOCBkP+BXocksouKUe02PhZfrYd/4C/wAmC6mKFukDWU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13606309},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css"},"gitHead":"8bfd77db4856787e7d7f9f0c8998e438d369b89c","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.2.3_1783370807988_0.5282553439236828","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"srcdev-hair-treatments","version":"0.2.4","license":"MIT","_id":"srcdev-hair-treatments@0.2.4","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"788992ad937b7da4bd624155953923985df1dff3","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.2.4.tgz","fileCount":67,"integrity":"sha512-Cjw9Pb6H0cSZL5+JQ89ME9vAL2T/me25trPmz/ivCH79xdPJapbb0qozxnlAj78KLXS95DRqW6xBbqA/LIsUjQ==","signatures":[{"sig":"MEUCIQCO5DCBNQm8o7c3lhbL2iSVjAA4y6D6Ak/g1cwl3sDQQwIgcKXlSJkzbaXZVEISPWVapDw/wy8mnjN5EXwgGsqBCHc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13606997},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css"},"gitHead":"75579c3bf28015cda107efb1c433cf16ab661d93","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.2.4_1783377283651_0.9666298327228462","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"srcdev-hair-treatments","version":"0.3.0","license":"MIT","_id":"srcdev-hair-treatments@0.3.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"662b039b3b196c40d3ae94c546f911c204408308","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.3.0.tgz","fileCount":72,"integrity":"sha512-nztn0Ir+cKi0A/XB8agHj8djY74sCyG9x7+9Xrko4NwVPiY1lTIsBlJd//fS6K/aiF0RxZiu1At9SEnyKLfvnA==","signatures":[{"sig":"MEYCIQC5rWWfD82DhdYjC1dtQwSILfCbDAgU55tkvQE65K3iZgIhANytQLry1xryBbcX5wGenzFOFYSny+7VSo55GGlTxaF2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13659815},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css"},"gitHead":"c6cef5e2c2853232c28141feb2478ba3cb7c455e","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.3.0_1785706131148_0.056817355132431135","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"srcdev-hair-treatments","version":"0.3.1","license":"MIT","_id":"srcdev-hair-treatments@0.3.1","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"696a408ffe5f10a019e28452d3551f88a6d4c36f","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.3.1.tgz","fileCount":73,"integrity":"sha512-SSlBcueR59g2YCALGU/hbrs4/Zhf4Svyf4sA315/niCQRE0CtK311C9ukMIPGXtZnTyQ/THWpfggmhyx5HYjZw==","signatures":[{"sig":"MEUCIEcJjKddbT0x91Rc1w9xAJMDN5SR87EOJzDVUoz71TxZAiEA558ABcrsESAA2nbTjo4f3gz9JkfedaLZet/12puQnJc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13662297},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css"},"gitHead":"74e107b80d4caf9ec7e7a108185e0ad28d77acc4","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.3.1_1785787759370_0.8665315539797604","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"srcdev-hair-treatments","version":"0.4.0","license":"MIT","_id":"srcdev-hair-treatments@0.4.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"778c07b3c579a70df38e7ca78c87d2e08ae75274","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-0.4.0.tgz","fileCount":78,"integrity":"sha512-qhe64RPvi8hp2PKKKe3R02V3D+/lOdGbJxnRiqHMTT6dKDDXyYg09NtVeXLnhBsddkLhwfwa+DhZAxD0JWYG6w==","signatures":[{"sig":"MEQCIE/5ixPH+ysobwgV+yGBBWvdetGU/mnImjcPFxbUTctBAiAQTrlqgbjm/SBpLV0PkL81jI9/bpaSV3jXiVyB2BfkHQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13924736},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"99c618bd96201fbde5d4e6a21fdd6db8ab06d94f","scripts":{"dev":"storybook dev -p 6006","lint":"eslint .","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_0.4.0_1786482767958_0.47723355438963244","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"srcdev-hair-treatments","version":"1.0.0","license":"MIT","_id":"srcdev-hair-treatments@1.0.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"56e55add891766f0c029b04523cf4260e6d5f9ad","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.0.0.tgz","fileCount":399,"integrity":"sha512-budtYWygB5/a4TzjpRPXgNUg7mQaDxTof72Ebnj1G53MwyVW1ZeqkLG7OcIleGWdCMbtMFD+NtcQkd0QDznWrw==","signatures":[{"sig":"MEUCIDUB7mnh7kaUFNAW+6WO3gk63LwT3kOBueCtra2adsfVAiEA6hBuvZsuauvDSjqA0e16ptGJ+S4k0jRbxr/r0Khml54=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36193562},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"3498da00319ef493320837bbbf6c6d8af466ed89","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.0.0_1786922615278_0.9889910527280397","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"srcdev-hair-treatments","version":"1.0.1","license":"MIT","_id":"srcdev-hair-treatments@1.0.1","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"594b5cffa70fbc062d25ad4a57cffb149d2cb7d5","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.0.1.tgz","fileCount":399,"integrity":"sha512-ZWShmvtZEhh9n99Hb5LjxuMNlT0dKZsNla/12u+lVj0STedvA0DT0UHRi4jJvNkUALD0pI+xLqCOgZPNt8tU2g==","signatures":[{"sig":"MEUCIAMot6SgWJmkJc/ILDQZQ8yiUO9xyAXQJUrNboeXFwN+AiEA3NS72H0Kc6LECMWWwrtVIVpPgurJ9r4fh3hmFwxs6RQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36193596},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"ea3f8d2fff1488aa887ced7f84276863990e3b56","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.0.1_1787002157437_0.07212291183019248","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"srcdev-hair-treatments","version":"1.1.0","license":"MIT","_id":"srcdev-hair-treatments@1.1.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"a57f8e5c587fc55e86acda056b4634122ca97397","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.1.0.tgz","fileCount":399,"integrity":"sha512-Faan6uYAo89UGpobPrilD9KS8cj5Zj9ShldTtmC/7YEqd70n8Xfh2OWICoOLsmJNfvp4WKths828dIO7dA950g==","signatures":[{"sig":"MEQCIBE7WCEZB8/6APRRpZks9mT2DIfPAygybVe9GuaMLB/dAiAmW0XqPXBmqkuIrfwvBbXf7V3QyajfasYz1ZNdWI8yvA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36199730},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"3a67e4fa9d8e0d14e690db1d5fb54f014a262f72","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.1.0_1787090121625_0.322045119084138","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"srcdev-hair-treatments","version":"1.1.1","license":"MIT","_id":"srcdev-hair-treatments@1.1.1","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"a51aff9ff4cbf0b083751012438caf31347da00f","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.1.1.tgz","fileCount":399,"integrity":"sha512-FPA6jq/VV6Acy7Z3rrZnQp50YwexbbHvq9Ue1KxJGR/f2mmfp0rDntbK3Fkx1y10/ysoCyr5IwH8w75N1pYOjA==","signatures":[{"sig":"MEQCIC+yQInYJx4HJBQUvn3XAnCC3qnQOtab99SHqN/It73/AiBSiaRqNJZM3/MxZoj57MwbFEu+hsl2jGJcn+EMSmJ81w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36203110},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"4ef8897c6b095c0e21e4c25922ae82eb9c8ad3fe","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.1.1_1787139557112_0.6328198864255381","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"srcdev-hair-treatments","version":"1.1.2","license":"MIT","_id":"srcdev-hair-treatments@1.1.2","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"80a65e00a89a1b1aad4e7f5ff911629e877473f1","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.1.2.tgz","fileCount":400,"integrity":"sha512-f0/U03cfLI8LOEMVkoou/chG34IIKOmtXWgfGJQce1P96VzXJ/2khIiV5CJPSCpegiZg9EvY6pjqEqX+gAk0jg==","signatures":[{"sig":"MEQCIC8u6hOZgnh3Q4n3YdBVKxQsOuTBOulDoi8VJgG+2uffAiAaVOLKfv4LXZPu0QE6YeC+GCj8KumDF41vwL6ggDh0Jg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICbVOSMVfYgGllNv3KvK8Pl8vqckQn2y0UIRi+EhfhylAiEA779ma7zEZf/nqlVywVA8BVzjw7/Nc7RLPwniEJo8j+g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36207046},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"852a8f49fb09afd4f57a8ae1b3e294f94fe39dbe","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.1.2_1789042198404_0.05018379718676558","host":"s3://npm-registry-packages-npm-production"}},"1.1.3":{"name":"srcdev-hair-treatments","version":"1.1.3","license":"MIT","_id":"srcdev-hair-treatments@1.1.3","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"a3b28d35e03258aa6f4d8739d7d69691b09fc075","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.1.3.tgz","fileCount":400,"integrity":"sha512-DyiOHXphnvaoJPj8NgZSXjYAgfLNwmY/KGDB3qiuCmY70zLyh1GzppfIIOPASpFhPRfHXWBpNsClXlmspdPvpg==","signatures":[{"sig":"MEYCIQDob5LDP0DlOGMgkFZoZ3Jep+y/5H/SYNY6OeSqdnzncgIhAK63ROCmwnsNt/rN47Vfzn1BGer3APi13XEPfZumuDHg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIGcDiBUDKFW3x3nj3XMoP+Oc/wXGWao3I/kOX67OOFdtAiEA8fdmv20t4RVNFkuTIWo1Y5FiU25d5BPQjTi6VkGyOPo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36213176},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"83f7b686bb6b2a9ff7f777504930da10365612f3","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.1.3_1789044167074_0.47836188472471397","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"srcdev-hair-treatments","version":"1.2.0","license":"MIT","_id":"srcdev-hair-treatments@1.2.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"5269b1235c1493f674e76864469cac1788cec9e1","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.2.0.tgz","fileCount":400,"integrity":"sha512-7PFRQ+Is8igNnwqJakbZAUd7qtpLOtMLENwuh8UJvnisNQK6IL3LcR+saTm+J0qnaJlBxFhvdyA71GaFpqoeBQ==","signatures":[{"sig":"MEQCIB6oXPTsDG/aEyEdkkhVE/Ln27SC6lIatm6ZHMWRjAfSAiB7sqZG9tZ2IoC1Q+06bhM4kKH+jVeR3qdBksD4tsYDOw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDvFaOORHYA6NjKx91YM342sgAcC8OoTpih7G8wcWjhGAIgPZHt3Mo9U+xx622IEnoWZH6QK6EekGxEkSdvUAJ2uzk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36213909},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"dff86105d4f68fb7566a0ad47865e4eaebe09c7d","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.2.0_1789132517093_0.27919294319375365","host":"s3://npm-registry-packages-npm-production"}},"1.2.1-alpha.0":{"name":"srcdev-hair-treatments","version":"1.2.1-alpha.0","license":"MIT","_id":"srcdev-hair-treatments@1.2.1-alpha.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"9e2ffca78a7407a3079ba460709152ca05a3a9c2","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.2.1-alpha.0.tgz","fileCount":413,"integrity":"sha512-tDsKw320Mzxnhanzx+7KI35MvOweIIQwWTz7xQvmgL6YMWWQ6j3l+oL+NS7YmKtCa8ZLp6fbJvY870m0HN7OLQ==","signatures":[{"sig":"MEYCIQDtVOXFYyUBE2XyknO1IyUnZ541dNQJHPQOIHIOovB3qwIhANaeYVsCYB9Zd4z9r1En/Oqay5f95omuJjBrQ23f6sd1","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC94IlPGhlCIRgIx18mDSZuyYGUvJv04nfViyBY4EWXPQIhAM5D/coMYidphcJQ26yDYE36pd9k8C342boRq2nrLZfb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38192085},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"82244823cd61a1da72bc025e15b531d240dce8d6","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/. public/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0","@mediapipe/tasks-vision":"1.0.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.2.1-alpha.0_1789678455816_0.4985927133358081","host":"s3://npm-registry-packages-npm-production"}},"1.2.1-alpha.1":{"name":"srcdev-hair-treatments","version":"1.2.1-alpha.1","license":"MIT","_id":"srcdev-hair-treatments@1.2.1-alpha.1","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"b6370dcfb98857feff4156822ae70bbd39fe5ba9","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.2.1-alpha.1.tgz","fileCount":413,"integrity":"sha512-oaMtigZ3OfN5WO8lX26VTTpQUE89vJgaK8nTfc4+BCwEXSw/6MU4pJUMXo56UX17ehg5SKK0GV8Y7+QBPxFgIQ==","signatures":[{"sig":"MEQCIASvzaZepWmir2ngZmSfxxZNUTmjiknODDEHM5ahCrN6AiBquj4MBlSi2V+RkI8BLbkPr1HxckDjALBOjUiRwPA7cQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCqW6W2UQUciJOF0oRA2BEl89y9RiTNkgPNEcGuzttXYAIgb+m2wQxRnN7JbkWp6Ki6ehUmD3o3xZF9v3+n/1ZcxkQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38191993},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"e82b3147e28b4446b0712b0bd50ad474c53c0cfe","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/. public/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0","@mediapipe/tasks-vision":"1.0.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.2.1-alpha.1_1789679925672_0.9165112873760932","host":"s3://npm-registry-packages-npm-production"}},"1.2.1-alpha.2":{"name":"srcdev-hair-treatments","version":"1.2.1-alpha.2","license":"MIT","_id":"srcdev-hair-treatments@1.2.1-alpha.2","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"6c1a5091d8ecf0de7446d8d25564252f6f2d0897","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.2.1-alpha.2.tgz","fileCount":413,"integrity":"sha512-1NPoFCD+31uFA+FbqQvv+LQm89GQNi3HWXFwd7xMJSa0G2zFF2giSiWT35suwobQbSg5faa0g5tzR7+PVcLnAg==","signatures":[{"sig":"MEUCIQC76pZ3DhPjvKtQqwNfS6RghqoZtL7cEAFGYPlXmfhnJwIgXbU/KMkc4KiV/14ZlpyGN8usEaiC8bbJ27d6ry/t/VA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIBbbVjAAk4i6gqrYD37dj2aDpPd0wS72Hs4MHeK4BYI/AiEAksU/4/RZdoK7n8PwSx0/ww4MOGQn7C2Uik3B9eDhb1c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38211365},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"14a6a4dc64f7cff3fc107b92056cb88a3e9717ea","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/. public/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0","@mediapipe/tasks-vision":"1.0.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.2.1-alpha.2_1789821092005_0.09758643486076157","host":"s3://npm-registry-packages-npm-production"}},"1.2.1-alpha.3":{"name":"srcdev-hair-treatments","version":"1.2.1-alpha.3","license":"MIT","_id":"srcdev-hair-treatments@1.2.1-alpha.3","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"955ee5499d0335a9b21b30d46b5ca4a6f28acce7","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.2.1-alpha.3.tgz","fileCount":413,"integrity":"sha512-2VlkxHPLn2pFhkqwdjcbIMXBNB/8R+IhzCN2eO1KlKl5GUC3JAgUrHi4zh48SVbYr2P36xO0+UfypDxLRD+4kQ==","signatures":[{"sig":"MEUCIGSG0wBvAoWiYrlkHiJ282uu6xTQ4hv/1hI4ogCD9r0mAiEA5TsnuX1CyTVJ+HJVerP8uGvaAPqhpNoXxnd7du6btG4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCOe7Kh6aV3fhnamSrrcL3YxF3+lASQ41Gi/NFP9fMJrQIhAJyxuIFCPIZONJD6kcFNYJrrzyMAihFSjiUbwfo3P65y","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38210099},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"6c277540406ee1be377b7cc1092e68df03b92c51","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/. public/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0","@mediapipe/tasks-vision":"1.0.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.2.1-alpha.3_1789823562367_0.9022475780229884","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"srcdev-hair-treatments","version":"1.3.0","license":"MIT","_id":"srcdev-hair-treatments@1.3.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"3a66d4feaf3be801447488959c339c6776ebaf46","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.3.0.tgz","fileCount":404,"integrity":"sha512-ubsR+nflWD8vfipZ4lqzmzrmGuPRoRwvoROnGp1rknvLXLOh67YReJd6k157WjWeFGeS6KXSDjWgqBrr7Pr97g==","signatures":[{"sig":"MEYCIQCa7jDJW0kVb71Wtyuuqa29vNs+ZJlZlgjWsmArDAN8VwIhAIRTJjy8uxuUXKyT6FQ7QvVrKRd68UfWgv9lTJRVEr0n","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIC0Oy6RB2YM2gAFZ+jyr4sQOOqbscm1RitSMhkCr/Z9wAiBMiNszPZuWJnGyW2Of69TfkzaWbBOa6z6PHULfpST+qw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36285125},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./locales/fr":{"types":"./dist/locales/fr.d.ts","import":"./dist/locales/fr.js","require":"./dist/locales/fr.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"3ce152a38be313c258536c69e561f71816095999","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.3.0_1790716263336_0.9418947444652699","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"srcdev-hair-treatments","version":"1.4.0","license":"MIT","_id":"srcdev-hair-treatments@1.4.0","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"dist":{"shasum":"a32742c7fc56e31c6e330d8ad4300cecd10281fc","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.4.0.tgz","fileCount":417,"integrity":"sha512-Udpt4BymXNrq3GYAZJrGwznmmQt0AjDlaHRMqgfZDi+Pqodaf8+LDvQe33hDj1bTVvK1JC9PWfvCkwTyd1lwVQ==","signatures":[{"sig":"MEUCIQCVN0SIGDxxNnImLnEVE8aMqC2zKM+LwRf1SY8+VnkhEQIgRX4sFbBfoiWg2qonP7lXmXUVLtPB7bXMUhiuROQq09g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD7qrnD0lky91/rvoQSHDxjooM6VN0VHRd9K9Q/8fQYcQIgJGmMKbaQXk1grjmZ/NN+gLzdirWIgXdvOkH5iCER7yc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38305235},"main":"./dist/hair-treatments.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./locales/fr":{"types":"./dist/locales/fr.d.ts","import":"./dist/locales/fr.js","require":"./dist/locales/fr.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"0aa642cb511d394daa1fbb46af0fc2b70cbf6b0f","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/. public/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0","@mediapipe/tasks-vision":"1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"tmp":"tmp/srcdev-hair-treatments_1.4.0_1791062866621_0.11327316707314083","host":"s3://npm-registry-packages-npm-production"}},"1.4.1":{"_id":"srcdev-hair-treatments@1.4.1","dist":{"shasum":"c97d121814d65aeab38a21b3d36baa676cf4e587","tarball":"https://registry.npmjs.org/srcdev-hair-treatments/-/srcdev-hair-treatments-1.4.1.tgz","fileCount":417,"integrity":"sha512-BAAyy/1JgL91BqSrYsA09CEJZ+GJcMJdLy9yiS6SRgR4XDa7S9ZvWD9hYnGWfsvG4tkHjKEh43Wncx6LrpYWvQ==","signatures":[{"sig":"MEUCIQD0Tpew3I2mNbYy65sDsn/Mkp4yR6n7W/5Eyb+2YHYe+gIgcEKSvMBSSzhQKcQMtYyauXavIDw/+7tFreXa5VgtKWQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDzhM3UO9HnO0R2YjL0Rhoaj8PULESD8VzoybNTmumInwIgN9GAhbWMvqF3gKLq9dM2iOhEFrhplq0a5hhEf6XzPTw="}],"unpackedSize":38306307},"main":"./dist/hair-treatments.cjs","name":"srcdev-hair-treatments","type":"module","types":"./dist/index.d.ts","module":"./dist/hair-treatments.js","engines":{"node":">=24.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/hair-treatments.js","require":"./dist/hair-treatments.cjs"},"./locales/fr":{"types":"./dist/locales/fr.d.ts","import":"./dist/locales/fr.js","require":"./dist/locales/fr.cjs"},"./dist/embed.js":"./dist/embed.js","./dist/style.css":"./dist/style.css","./dist/tokens.css":"./dist/tokens.css","./dist/embed-style.css":"./dist/embed-style.css"},"gitHead":"535a19e1146f1c1bc03fb29af17fdf997c831fda","license":"MIT","scripts":{"dev":"storybook dev -p 6006","lint":"eslint . && node scripts/check-raw-rem.mjs","test":"vitest","build":"vite build && vite build --config vite.embed.config.ts && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/tokens.css dist/tokens.css","release":"release-it","test:ui":"vitest --ui","test:run":"vitest --run","storybook":"storybook dev -p 6006","typecheck":"vue-tsc --noEmit","playwright":"npx playwright test","test:update":"vitest --update","setup:assets":"cp -r node_modules/srcdev-hair-treatments/public/. public/","setup:claude":"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments","images:convert":"node scripts/convert-shade-images.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:tokens":"node scripts/generate-tokens.mjs","storybook:build":"storybook build","storybook:serve":"npm run storybook:build && npx http-server storybook-static --port 6006","playwright:update":"npx playwright test --update-snapshots","storybook:cache:clean":"rm -rf node_modules/.cache/storybook node_modules/.vite"},"version":"1.4.1","_npmUser":{"name":"srcdevnpm","email":"npm@srcdev.co.uk"},"release-it":{"git":{"commitMessage":"chore(release): release v${version}"},"github":{"release":true,"releaseName":"v${version}"},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"_npmVersion":"11.13.0","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","directories":{},"maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"_nodeVersion":"24.16.0","dependencies":{"jose":"^6.2.7","@vueuse/motion":"3.0.3","lucide-vue-next":"1.0.0","@mediapipe/tasks-vision":"1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"vue":"3.5.31","vite":"8.0.3","sharp":"^0.35.3","eslint":"10.1.0","vitest":"4.1.2","vue-tsc":"3.2.6","happy-dom":"20.8.9","storybook":"10.3.3","release-it":"19.2.4","typescript":"5.9.3","@vue/test-utils":"2.4.6","@playwright/test":"1.58.2","eslint-plugin-vue":"10.8.0","typescript-eslint":"8.57.2","@vitejs/plugin-vue":"6.0.5","@storybook/vue3-vite":"10.3.3","@storybook/addon-a11y":"10.3.3","@storybook/addon-docs":"10.3.3","eslint-plugin-storybook":"10.3.3","@vue/eslint-config-prettier":"10.2.0"},"peerDependencies":{"vue":">=3.4.0"},"optionalDependencies":{"@emnapi/core":"^1.9.1","@emnapi/runtime":"^1.9.1","@emnapi/wasi-threads":"^1.2.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/srcdev-hair-treatments_1.4.1_1791065008169_0.8308340620383747"}}},"time":{"created":"2026-03-30T20:33:19.881Z","modified":"2026-10-03T22:03:28.878Z","0.1.1":"2026-03-30T20:33:20.245Z","0.1.2":"2026-03-30T21:02:19.877Z","0.1.3":"2026-03-30T21:09:21.020Z","0.1.4":"2026-03-31T20:56:45.004Z","0.1.5":"2026-04-03T14:25:12.202Z","0.1.6":"2026-04-03T23:11:04.613Z","0.1.7":"2026-04-03T23:36:27.042Z","0.1.8":"2026-04-04T00:14:00.195Z","0.2.0":"2026-06-06T23:42:50.902Z","0.2.1":"2026-06-07T14:32:33.440Z","0.2.2":"2026-06-07T19:48:16.531Z","0.2.3":"2026-07-06T20:46:48.286Z","0.2.4":"2026-07-06T22:34:44.044Z","0.3.0":"2026-08-02T21:28:51.464Z","0.3.1":"2026-08-03T20:09:19.691Z","0.4.0":"2026-08-11T21:12:48.282Z","1.0.0":"2026-08-16T23:23:35.878Z","1.0.1":"2026-08-17T21:29:18.003Z","1.1.0":"2026-08-18T21:55:22.211Z","1.1.1":"2026-08-19T11:39:17.702Z","1.1.2":"2026-09-10T12:09:58.941Z","1.1.3":"2026-09-10T12:42:47.595Z","1.2.0":"2026-09-11T13:15:17.630Z","1.2.1-alpha.0":"2026-09-17T20:54:16.357Z","1.2.1-alpha.1":"2026-09-17T21:18:46.547Z","1.2.1-alpha.2":"2026-09-19T12:31:32.541Z","1.2.1-alpha.3":"2026-09-19T13:12:42.896Z","1.3.0":"2026-09-29T21:11:03.902Z","1.4.0":"2026-10-03T21:27:47.123Z","1.4.1":"2026-10-03T22:03:28.688Z"},"license":"MIT","description":"[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml) [![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hai","maintainers":[{"name":"srcdevnpm","email":"npm@srcdev.co.uk"}],"readme":"# SRCDEV Hair Treatments\n\n[![Tests](https://github.com/srcdev/hair-treatments/workflows/Tests/badge.svg)](https://github.com/srcdev/hair-treatments/actions/workflows/test.yml)\n[![npm version](https://badge.fury.io/js/srcdev-hair-treatments.svg)](https://badge.fury.io/js/srcdev-hair-treatments)\n\n> **Note:** Although this repo is private and developed for use with websites we develop, you are welcome to use it.\n\nA standalone Vue 3 component library providing a hair treatment consultation wizard. Distributed via npm — no Nuxt or framework dependency required.\n\n---\n\n## Post-install Setup\n\nRun these once after initial install, then add a `postinstall` script so they stay in sync automatically on every `npm install`.\n\n### Images & Models\n\nThe component uses swatch and hair-type images, plus (for the virtual try-on feature) a MediaPipe hair-segmentation model, that must be served from your app's `public/` directory. Add this script to your `package.json`:\n\n```json\n\"setup:assets\": \"cp -r node_modules/srcdev-hair-treatments/public/. public/\"\n```\n\nThen run it after install:\n\n```bash\nnpm run setup:assets\n```\n\nImages are copied into `public/images/treatment-consultant/`, and the try-on model into `public/models/treatment-consultant/hair_segmenter.tflite`. Re-running after a package update picks up any new or changed assets.\n\nIf you'd rather self-host the model elsewhere (e.g. your own CDN), override `config.behaviour.tryOnModelPath` with the URL you want to load it from instead — see [Behaviour flags](#behaviour-flags).\n\n### Claude Code Skills\n\nThis package ships consumer-facing Claude Code skills — reference docs for using the component in your app — in `.claude/skills/public/`.\n\nTo make them available in your project, add this script to your `package.json`:\n\n```json\n\"setup:claude\": \"cp -r node_modules/srcdev-hair-treatments/.claude/skills/public/. .claude/skills/srcdev-hair-treatments\"\n```\n\nThen run it after install:\n\n```bash\nnpm run setup:claude\n```\n\nSkills are copied into `.claude/skills/srcdev-hair-treatments/` so they never conflict with or overwrite skills your own project defines. Re-running the script after a package update is safe.\n\n### Automating with postinstall\n\nOnce both scripts are defined, wire them into a `postinstall` hook so they run automatically on every `npm install`. For a Nuxt app this looks like:\n\n```json\n\"postinstall\": \"NUXT_STANDALONE=true nuxt prepare && npm run setup:claude && npm run setup:assets\"\n```\n\nAdjust the leading command (`nuxt prepare`, `vite build`, etc.) to match your framework's own post-install needs, or omit it entirely if your app doesn't need one.\n\n---\n\n## Install\n\n```bash\nnpm install srcdev-hair-treatments\n```\n\n### Peer dependency\n\nVue 3.4+ must be installed in the consuming app:\n\n```bash\nnpm install vue@^3.4\n```\n\n---\n\n## Basic Usage\n\nImport the component and its bundled stylesheet:\n\n```ts\nimport { TreatmentConsultant } from \"srcdev-hair-treatments\";\nimport \"srcdev-hair-treatments/dist/style.css\";\n```\n\n```vue\n<template>\n  <TreatmentConsultant />\n</template>\n```\n\n---\n\n## App-level Configuration (Recommended)\n\nFor most projects you'll want to configure the component once — at app level — rather than repeating `:config` on every usage. Use `createHairTreatments` to register a plugin when your app starts:\n\n```ts\n// e.g. plugins/hair-treatments.ts (Nuxt) or main.ts (plain Vue)\nimport { createHairTreatments, defaultConfig } from \"srcdev-hair-treatments\";\n\nexport default defineNuxtPlugin((nuxtApp) => {\n  nuxtApp.vueApp.use(\n    createHairTreatments({\n      behaviour: {\n        currency: \"£\",\n        allowMultipleTreatments: true,\n      },\n      treatments: defaultConfig.treatments.map((t) => ({\n        ...t,\n        display: ![\"perm\", \"relaxer\", \"japanese-straightening\"].includes(t.id),\n      })),\n      text: {\n        cta: {\n          bookHref: \"/book\",\n          bookLabel: \"Book Your Appointment\",\n        },\n      },\n    })\n  );\n});\n```\n\nFor a plain Vue app (no Nuxt), register the plugin in `main.ts`:\n\n```ts\nimport { createApp } from \"vue\";\nimport { createHairTreatments } from \"srcdev-hair-treatments\";\nimport App from \"./App.vue\";\n\nconst app = createApp(App);\n\napp.use(\n  createHairTreatments({\n    behaviour: { currency: \"£\" },\n  })\n);\n\napp.mount(\"#app\");\n```\n\nEvery `<TreatmentConsultant />` in your app automatically picks up this config. The `:config` prop still works on individual instances and always wins — so you can set site-wide defaults via the plugin and fine-tune specific pages with the prop.\n\n---\n\n## Consumer Requirements\n\nThe component intentionally does not impose colour tokens on your app. You must supply them yourself — either import the defaults or provide your own:\n\n### Colour tokens\n\n```css\n@import \"srcdev-hair-treatments/dist/tokens.css\";\n```\n\nOr define the four semantic ramps yourself as CSS custom properties on `:root`:\n\n```css\n:root {\n  --brand-00: oklch(98% 0.0086 75);\n  /* ... --brand-01 through --brand-10 */\n\n  --success-00: oklch(98% 0.0086 157);\n  /* ... --success-01 through --success-10 */\n\n  --warning-00: oklch(98% 0.0099 50);\n  /* ... --warning-01 through --warning-10 */\n\n  --error-00: oklch(98% 0.0108 30);\n  /* ... --error-01 through --error-10 */\n}\n```\n\nDefault token values are generated from `ramps.config.mjs` — see [`src/tokens.css`](src/tokens.css) for the full set.\n\nNo `html { font-size: 62.5% }` rem reset is needed. The component sizes itself via a local `--_unit` custom property (default `1px`) rather than raw `rem`, so it renders at the same intended pixel sizes regardless of your app's root font-size. If you want the component to scale with your page's root font-size / browser text-zoom setting instead, opt in with:\n\n```css\n.treatment-consultant {\n  --_unit: 0.0625rem; /* 1px at a default 16px root */\n}\n```\n\n---\n\n## Per-instance Configuration\n\nYou can also pass a `:config` prop directly to any `<TreatmentConsultant />`. This merges on top of the plugin config (if registered) and always wins. Pass any subset — you don't need to repeat defaults:\n\n```vue\n<TreatmentConsultant\n  :config=\"{\n    behaviour: { autoAdvance: true },\n    text: {\n      cta: {\n        bookHref: '/book',\n        bookLabel: 'Book Your Appointment',\n      },\n    },\n  }\"\n/>\n```\n\n### Behaviour flags\n\n| Key                       | Type      | Default | Description                                                  |\n| ------------------------- | --------- | ------- | ------------------------------------------------------------ |\n| `autoAdvance`             | `boolean` | `false` | Auto-advance to the next step on selection                   |\n| `allowMultipleTreatments` | `boolean` | `false` | Allow selecting multiple treatments with conflict detection  |\n| `showTreatmentsStep`      | `boolean` | `true`  | Show or hide the Treatments step (step 5) entirely           |\n| `currency`                | `string`  | `\"£\"`   | Currency symbol used in price display                        |\n| `swatchVariant`           | `\"circle\" \\| \"square\" \\| \"portrait\" \\| \"landscape\"` | `\"circle\"` | Shape applied to every colour/image swatch (and, via modifier class, its option button) across the whole wizard |\n| `dreamColourMode`         | `\"basic\" \\| \"granular\"` | `\"basic\"` | `\"basic\"`: the 7-item desiredColours grid, as today. `\"granular\"`: a tabbed catalog of individual shades (`config.shades`), grouped by category — **requires a Premium license**, see [Granular shade catalog mode](#granular-shade-catalog-mode) |\n| `naturalColourMode`       | `\"basic\" \\| \"granular\"` | `\"basic\"` | `\"basic\"`: the 7-item naturalColours grid, as today. `\"granular\"`: a tabbed catalog of individual shades (`config.naturalShades`), grouped by category — **requires a Premium license**, see [Granular shade catalog mode](#granular-shade-catalog-mode) |\n| `theme`                   | `\"default\" \\| \"monochrome-light\" \\| \"monochrome-dark\"` | `\"default\"` | `\"default\"`: dark brand-coloured canvas, light text. `\"monochrome-light\"`: white canvas, foreground darkening from white through greys to near-black. `\"monochrome-dark\"`: same dark-canvas/light-text layout as `\"default\"`, brand hue removed. Neither monochrome theme has any hue anywhere the default theme uses brand colour. See [Themes](#themes) |\n| `sharpCorners`            | `boolean` | `false` | Squares off every rounded corner (cards, buttons, panels, the license watermark). Deliberately circular/pill shapes — the circle OptionSwatch, the checkmark badge, progress dots/bars — are unaffected |\n| `fullBleedHeader`         | `boolean` | `true`  | Header runs edge to edge of the component, flush with its top. `false`: inset by the canvas padding like the other rows |\n| `fullBleedHero`           | `boolean` | `true`  | Hero (step explainer banner) runs edge to edge of the component, flush under a full-bleed header. `false`: inset by the canvas padding like the other rows |\n| `experimentalTryOn`       | `boolean` | `false` | **Experimental.** Opts in to the virtual try-on trigger (persistent icon button, plus a prominent CTA on the Dream Colour step) — see [Virtual try-on](#virtual-try-on) |\n| `tryOnShowShadeImages`    | `boolean` | `true`  | Try-on's palette swatches show each shade's photo, same as the granular Dream Colour grid. `false`: flat colour swatches only, no photos |\n| `tryOnModelPath`          | `string`  | `\"/models/treatment-consultant/hair_segmenter.tflite\"` | HTTP(S) path to the MediaPipe hair segmenter model try-on loads at runtime — see [Images & Models](#images--models) |\n| `tryOnWasmBaseUrl`        | `string`  | a pinned jsDelivr URL | Base URL try-on's MediaPipe runtime loads its own wasm binaries from |\n\n### Themes\n\n```ts\nconst config: DeepPartial<TreatmentConsultantConfig> = {\n  behaviour: { theme: \"monochrome-light\" },\n};\n```\n\nSetting `behaviour.theme` applies a `theme-<name>` modifier class to the component's root element, which a matching stylesheet under `src/components/treatment-consultant/themes/` uses to override the colour tokens that give the component its look (canvas background/text, surfaces, borders, outlines) — everything else (fonts, spacing, the semantic \"great\"/\"possible\"/\"difficult\"/\"not-recommended\" suitability colours, and the checked/conflict/excluded state colours) stays the same across themes. These theme stylesheets ship bundled in `dist/style.css`, so no separate import is needed — just set `behaviour.theme`.\n\nCurrently available: `\"default\"`, `\"monochrome-light\"` and `\"monochrome-dark\"`. Both monochrome themes use a dedicated chroma-0 `--mono-00`…`--mono-10` grey ramp (see `ramps.config.mjs`) instead of `--brand-*`, so they stay fully desaturated even if you've customised your app's `--brand-*` tokens. `\"monochrome-dark\"` keeps the same dark-canvas/light-text layout as `\"default\"`, just with the hue removed — every token maps to the same ramp index (`--brand-NN` → `--mono-NN`), since lightness is shared across every ramp and only chroma differs.\n\n### Text\n\nAll UI copy lives under `config.text`. The full shape is exported as `TextConfig`:\n\n```ts\nimport type { TextConfig } from \"srcdev-hair-treatments\";\n```\n\nKey sections:\n\n| Path | Description |\n| ---- | ----------- |\n| `text.header.brand / title` | Built-in header text — brand/salon name (empty string hides it) and a persistent title, e.g. \"Colour Consultation\" |\n| `text.navigation.steps` | Step label array (7 items for the default 7-step flow) |\n| `text.navigation.back / next / viewResults / backToResults` | Navigation button labels |\n| `text.progress.stepFormat` | Progress counter format string — use `{step}`, `{total}`, `{label}` as placeholders. Default: `\"Step {step} of {total} — {label}\"` |\n| `text.steps.*` | Step headings and subtitles |\n| `text.explainers.*` | Title/body (and optional per-step `image`) for the `.consultant-hero` area shown above each of the 6 selection steps — hidden on Results. Keyed the same as `text.steps.*` |\n| `text.results.*` | Results section headings, no-colour / no-treatment messages, suitability labels |\n| `text.summary.*` | Summary panel column labels |\n| `text.cta.bookHref` | Booking link URL |\n| `text.cta.bookLabel / disclaimer / resetLabel` | CTA copy |\n| `text.labels.*` | Small UI strings that don't belong to any single step: the built-in \"no cut today\" skip option, the hair-type-excluded note (shared by Cut and Application Type), the treatment-conflict format string (use `{treatment}` as a placeholder), and the granular shade catalog's \"All Shades\" tab. The \"Powered by GuideMyHair\" attribution link (shown on non-Premium plans) is deliberately *not* here — its text is hardcoded, not config-overridable |\n| `text.recommendations` | Method/notes/details copy shown on the Results colour recommendation card, keyed `naturalColourId -> desiredColourId` (`Record<NaturalColourId, Partial<Record<DesiredColourId, RecommendationText>>>`). Which combinations are \"great\" vs \"not-recommended\" is internal, fixed logic — this only controls the *text* shown for each. Deep-merged, so override only the combinations you need; a full translation should supply every combination explicitly rather than relying on a partial override, or you'll get a mix of languages |\n| `text.recommendationFallback` | `{ method, notes, details }` shown for a combination with no `text.recommendations` entry (only reachable with custom `naturalColours`/`desiredColours` ids) |\n| `text.texturedHairNote` | Extra detail line appended for `hairType` \"curly\" or \"coily\" |\n| `text.options.<list>.<id>` | Per-option label/description/notes/warnings, keyed by list and option id, overriding the inline array values. Use this (not translated arrays) for localisation — see [Translating option labels](#translating-option-labels) |\n| `text.sameShadeNoteFormat` | Format string shown when the natural and dream shade selections are the literal same shade — use `{shade}` as a placeholder |\n\nText config is **deep-merged** — override only the keys you need.\n\n### i18n\n\nThe `config` prop is reactive — passing a `computed()` that reads from your i18n library means the component re-renders automatically when the locale changes. No special integration is needed.\n\n```ts\n// Nuxt + @nuxtjs/i18n\nconst { t } = useI18n();\n\nconst config = computed(() => ({\n  text: {\n    progress: { stepFormat: t(\"wizard.progress\") }, // e.g. \"Étape {step} sur {total} — {label}\"\n    steps: {\n      hairType: t(\"wizard.steps.hairType\"),\n      naturalColour: t(\"wizard.steps.naturalColour\"),\n      // ... only override the keys you need\n    },\n    cta: {\n      bookLabel: t(\"wizard.cta.bookLabel\"),\n      bookHref: \"/book\",\n    },\n  },\n}));\n```\n\n```vue\n<TreatmentConsultant :config=\"config\" />\n```\n\nThe `{step}`, `{total}`, and `{label}` placeholders in `text.progress.stepFormat` can appear in any order, which matches how most i18n libraries handle interpolation.\n\n### Translating option labels\n\nOption labels (hair types, colours, shades, grey coverage, treatments, application types, cuts) are translated under `text.options.<list>.<id>`, not by passing translated copies of the arrays. Arrays replace wholesale, so a translated `naturalColours` array passed through `:config` would silently undo any option set configured in `createHairTreatments()` (exclusions, custom options, ordering). `text` deep-merges, so `text.options` only ever changes wording:\n\n```ts\nconst config = computed(() => ({\n  text: {\n    options: {\n      hairTypes: { straight: { label: t(\"hair.straight\") } },\n      treatments: { perm: { label: t(\"treat.perm.label\"), description: t(\"treat.perm.desc\"), notes: [t(\"treat.perm.n1\")] } },\n      cuts: { fringe: { warnings: { coily: { note: t(\"cut.fringe.coily.note\"), detail: t(\"cut.fringe.coily.detail\") } } } },\n    },\n  },\n}));\n```\n\nEach entry overrides only the fields you supply (`label`, plus `description` / `notes` / `warnings` where that option type has them). Anything missing falls back to the option's inline array value. Entries for ids that aren't in the array are ignored, and `text.options` never adds or removes options. `notes` replaces the treatment's notes wholesale; `warnings` merges per hair type and per field.\n\n### Built-in locale packs\n\nThe package ships ready-made locale packs as subpath exports. Each is a pure `DeepPartial<TextConfig>` covering every string in the wizard, option labels included:\n\n```ts\nimport { fr } from \"srcdev-hair-treatments/locales/fr\";\n\nconst config = computed(() => (locale.value === \"fr\" ? { text: fr } : {}));\n```\n\nA pack deliberately leaves out per-site settings (`text.header.brand`, `text.cta.bookHref`, suitability icons), so whatever you set for those in plugin config survives a locale switch. Layer your own overrides on top with a spread, e.g. `{ text: { ...fr, cta: { ...fr.cta, bookLabel: \"Prendre rendez-vous\" } } }`. Locale packs work on every licence tier.\n\nAvailable: `fr` (French).\n\n### Treatments — showing and hiding\n\nEach treatment has an optional `display` field. Set it to `false` to hide that treatment from the wizard without removing it from the data:\n\n```ts\nimport { defaultConfig } from \"srcdev-hair-treatments\";\n\nconst config = {\n  treatments: defaultConfig.treatments.map((t) => ({\n    ...t,\n    display: ![\"perm\", \"relaxer\", \"japanese-straightening\"].includes(t.id),\n  })),\n};\n```\n\nThis is the preferred approach over `.filter()` because it keeps all the treatment data intact (notes, compatibility rules, conflict exclusions) while simply hiding specific options from the UI.\n\n### Other data arrays\n\n`hairTypes`, `naturalColours`, `naturalShades`, `greyCoverageOptions`, `desiredColours`, `shades`, `applicationTypes`, and `cuts` are replaced wholesale when provided. Always use `defaultConfig` as a base. (To translate labels, use `text.options` instead of rewriting arrays — see [Translating option labels](#translating-option-labels).)\n\n```ts\nimport { defaultConfig } from \"srcdev-hair-treatments\";\n\nconst config = {\n  naturalColours: [\n    ...defaultConfig.naturalColours,\n    { id: \"custom\", label: \"Custom Blend\", colour: \"#abc123\" },\n  ],\n};\n```\n\n### Granular shade catalog mode\n\n**Requires a Premium license.** By default (`behaviour.dreamColourMode` / `behaviour.naturalColourMode: \"basic\"`) the Dream Colour and Natural Colour steps each show their 7-item broad-category grid, unchanged. Setting either to `\"granular\"` switches that step to a tabbed catalog of individual named shades — `config.shades` for Dream Colour, `config.naturalShades` for Natural Colour — grouped into tabs by category, closer to how a real colour chart is browsed. The two modes are independent — mix and match as needed.\n\nOn a Basic or Standard license (or no/invalid license), `\"granular\"` is silently treated as `\"basic\"` — no error, no locked/upsell UI, the config value simply has no effect below Premium. The same fallback applies on a **Premium** license if the relevant catalog (`config.shades` / `config.naturalShades`) is empty — Natural Colour otherwise has no way to proceed without a selectable shade, and Dream Colour would render an empty tab bar with nothing to pick.\n\n```ts\nimport type { DesiredShadeOption, NaturalShadeOption } from \"srcdev-hair-treatments\";\n\nconst config = {\n  behaviour: { dreamColourMode: \"granular\", naturalColourMode: \"granular\" },\n  shades: [\n    { id: \"honey-blonde\", label: \"Honey Blonde\", desiredColourId: \"blonde\", colour: \"#C89A5B\" },\n    { id: \"chocolate-brown\", label: \"Chocolate Brown\", desiredColourId: \"brown\", colour: \"#3D2A1F\" },\n    // ...\n  ] satisfies DesiredShadeOption[],\n  naturalShades: [\n    { id: \"natural-auburn\", label: \"Auburn\", naturalColourId: \"red\", colour: \"#7C3B22\" },\n    // ...\n  ] satisfies NaturalShadeOption[],\n};\n```\n\n- **Tabs are derived from the data**, not hardcoded — whatever `desiredColourId` / `naturalColourId` values appear across `config.shades` / `config.naturalShades` become tabs (labelled from the matching `desiredColours` / `naturalColours` entry). Dream Colour also gets a fixed \"All Shades\" tab. Add shades with a new category id to grow another tab; there's no separate tab config to keep in sync.\n- **The broad category id drives the suitability matrix.** Selecting a shade is functionally equivalent to selecting its `desiredColourId` / `naturalColourId` in basic mode — `getColourRecommendation()` never sees individual shades, only the broad category.\n- **The specific shade is still tracked** — `ConsultationSelections.desiredShade` / `.naturalShade` holds the picked shade's `id` (`null` in basic mode, or before a shade is picked), and the Results summary card shows the shade's label (e.g. \"Chocolate Brown\") instead of just the broad category label.\n- **`image` is optional per shade** — omit it and the shade swatch falls back to `colour` only, same as `desiredColours`/`naturalColours` today.\n- **`image2x` is also optional** — a 2x-density variant of `image`, rendered via `srcset=\"<image> 1x, <image2x> 2x\"` for crisp rendering on high-DPI screens. Omit it and only `image` is used at every density (no broken-image risk from a guessed URL) — this is opt-in per entry, not automatic string-manipulation of `image`.\n- The default `config.shades` and `config.naturalShades` ship with real photography, one subfolder per category under `/images/treatment-consultant/shades/{dream,natural}/<category>/`, each shade at both a base (~480px) and `@2x` (~960px) size.\n- **Sourcing tip:** 34 of the 43 `shades` entries (everything except Vivid) are the same colour as a `naturalShades` entry of the same label — e.g. \"Honey Blonde\" is `#C89A5B` in both. If commissioning your own photography, these can be shot once and saved under both `shades/dream/blonde/honey-blonde.webp` and `shades/natural/dark-blonde/natural-honey-blonde.webp` — the two arrays stay fully independent to override later, this is purely a shortcut for sourcing the defaults. Vivid's 9 shades have no natural equivalent.\n\n### Virtual try-on\n\nLets a user preview a colour from `config.shades` on a live webcam feed or an uploaded selfie, using client-side hair segmentation ([MediaPipe](https://ai.google.dev/edge/mediapipe/solutions/vision/image_segmenter) — see [Images & Models](#images--models) for the model asset this needs, and [Third-Party Notices](#third-party-notices) for attribution). No image or video data is ever sent anywhere — segmentation and colour compositing run entirely in the browser.\n\n> **Experimental:** off by default. Opt in with `behaviour.experimentalTryOn: true`. The feature is still under research, so its behaviour, config options and this flag may change in any release, including minor and patch versions.\n\nOnce enabled, it is available on **every license tier** (a consumer opt-in, not license-gated) — opened via a persistent icon-button trigger shown on every step, plus a more prominent CTA on the Dream Colour step. Unlike the rest of the wizard, the try-on palette is **not** license-gated: it always shows the full `config.shades` catalog, even on a Basic/Standard license where the real Dream Colour step only offers the 7-item broad-category grid ([Granular shade catalog mode](#granular-shade-catalog-mode) above). This is intentional — a deliberate preview of what a Premium license unlocks.\n\nTapping a shade both previews it (recolours the live/uploaded canvas) and immediately writes it back into the same `desiredColour`/`desiredShade` state Dream Colour reads — as a specific shade if the user's license actually resolves that step to granular mode, or just the broad category otherwise. It does not navigate away or close the takeover, so the user can keep trying on different shades against the live camera; the pick is simply preselected whenever they later reach (or return to) the Dream Colour step. A try-on pick never auto-advances the wizard either, so there's a chance to change their mind (e.g. after trying on a shade just to see it, not necessarily to commit to it).\n\nWith `behaviour.experimentalTryOn` left at its default `false`, the feature (trigger buttons and takeover) is not rendered at all, and the takeover chunk (including MediaPipe) is never loaded.\n\n### Grey coverage\n\nA second, independent question shown beneath the Natural Colour swatches, set apart with its own heading, subtitle, and divider so it doesn't read as an afterthought: `config.greyCoverageOptions` (default: None / Some / Significant / Mostly Grey). It's tracked as `ConsultationSelections.greyCoverage` and shown as its own Results summary card, but — unlike hair type/natural colour/desired colour — it never feeds the suitability matrix and never triggers `autoAdvance`, since it's a secondary control rather than the step's primary selection. The heading is `text.steps.greyCoverage`, with `text.steps.greyCoverageSubtitle` beneath it explaining why it's asked. Override the options the same way as other data arrays:\n\n```ts\nimport { defaultConfig } from \"srcdev-hair-treatments\";\nimport type { GreyCoverageOption } from \"srcdev-hair-treatments\";\n\nconst config = {\n  greyCoverageOptions: defaultConfig.greyCoverageOptions satisfies GreyCoverageOption[],\n};\n```\n\n---\n\n## Events\n\nThe component emits two events, both with the same `ConsultationSelections` payload shape:\n\n| Event | When |\n| ----- | ---- |\n| `change` | Every time any selection changes (hair type, colour, cut, treatments, etc.) |\n| `complete` | Once, when the user reaches the Results step |\n\n```vue\n<script setup lang=\"ts\">\nimport { TreatmentConsultant } from \"srcdev-hair-treatments\";\nimport type { ConsultationSelections } from \"srcdev-hair-treatments\";\n\nfunction onChange(selections: ConsultationSelections) {\n  // { hairType, naturalColour, desiredColour, applicationType, cut, treatments }\n}\n\nfunction onComplete(selections: ConsultationSelections) {\n  // fires once, when the results step is first reached\n}\n</script>\n\n<template>\n  <TreatmentConsultant @change=\"onChange\" @complete=\"onComplete\" />\n</template>\n```\n\n---\n\n## Slots\n\n### `header`\n\nRenders above the step content, inside the component's root. By default this shows the built-in header — brand name + title (via `text.header.brand` / `text.header.title`) and a live progress label. Provide this slot to replace it with your own markup entirely (a custom logo/progress bar, anything). The hero (step explainer) still draws its own copy of the progress label over its image, so a custom header that also shows progress text will show it twice.\n\nIt's a scoped slot exposing the wizard's live progress, so a custom step counter stays in sync without re-deriving it yourself. **The built-in header's progress label is also the component's only screen-reader announcement of step changes** (`aria-live=\"polite\"` directly on that visible text) — replacing the slot replaces that too, so give your own progress text the same `aria-live=\"polite\" aria-atomic=\"true\"` if you want step changes announced to screen reader users.\n\n| Slot prop | Type | Description |\n| --------- | ---- | ----------- |\n| `displayStep` | `number` | Current step, 1-indexed, adjusted for any skipped/hidden steps |\n| `totalSteps` | `number` | Total step count (6 or 7, depending on `behaviour.showTreatmentsStep`) |\n| `displayStepLabel` | `string` | Current step's label from `text.navigation.steps` |\n| `progressLabel` | `string` | The same formatted string driving the built-in progress text (`text.progress.stepFormat`) |\n\n```vue\n<template>\n  <!-- Just brand it via config — no slot needed for text/copy changes -->\n  <TreatmentConsultant :config=\"{ text: { header: { brand: 'My Salon', title: 'Colour Consultation' } } }\" />\n\n  <!-- Or fully replace the header's markup via the slot -->\n  <TreatmentConsultant>\n    <template #header=\"{ displayStep, totalSteps, displayStepLabel }\">\n      <header class=\"my-consultation-header\">\n        <img class=\"my-logo\" src=\"/my-logo.svg\" alt=\"My Salon\" />\n        <span aria-live=\"polite\" aria-atomic=\"true\">Step {{ displayStep }} of {{ totalSteps }} — {{ displayStepLabel }}</span>\n      </header>\n    </template>\n  </TreatmentConsultant>\n</template>\n```\n\n---\n\n## Overriding Styles\n\nThe component root class is `.treatment-consultant`. All internal CSS custom properties are scoped to it and can be overridden in your stylesheet:\n\n```css\n.treatment-consultant {\n  /* Fonts — default to system fonts, zero setup required */\n  --treatment-consultant-font-body: \"My Font\", sans-serif; /* body, default: system-ui, sans-serif */\n  --treatment-consultant-font-heading: \"My Heading Font\", serif; /* headings, default: Georgia, serif */\n  --treatment-consultant-font-label: \"My Label Font\", sans-serif; /* small uppercase UI labels, default: same as font-body */\n\n  /* Layout */\n  --treatment-consultant-max-inline-size: 1216px; /* overall width cap, default */\n\n  /* Header banner (built-in header slot) */\n  --treatment-consultant-header-block-size: auto; /* banner depth, default: content height */\n  --treatment-consultant-header-background: var(--_surface-active); /* any `background` value, e.g. url(...) center / cover */\n\n  /* Hero (step explainer) */\n  --treatment-consultant-hero-block-size: 320px; /* tablet-up banner depth, default: calc(32 * var(--_rem)) */\n  --treatment-consultant-hero-scrim-colour: #000; /* gradient behind the text overlaid on the hero image */\n  --treatment-consultant-hero-text-colour: #fff; /* text overlaid on the hero image */\n\n  /* Check badge */\n  --treatment-consultant-checked-surface-colour: hsl(220 80% 40%);\n  --treatment-consultant-checked-stroke-colour: hsl(220 80% 80%);\n\n  /* Suitability + compatibility/warning badges on the Results step */\n  --treatment-consultant-emerald: hsl(160 84% 39%); /* \"great\" suitability, ok compatibility */\n  --treatment-consultant-amber: hsl(43 96% 56%); /* \"possible\" suitability */\n  --treatment-consultant-orange: hsl(25 95% 53%); /* \"difficult\" suitability, warning badges */\n  --treatment-consultant-red: hsl(0 84% 60%); /* \"not-recommended\" suitability */\n\n  /* Option card button (every selection step + Results summary cards) */\n  --option-gap: var(--_spacing-sm); /* space between visual/label/sublabel */\n  --option-border-width: 1px;\n  --option-border-color: var(--_border-active);\n  --option-border-radius: var(--_border-radius);\n  --option-outline-width: 2px;\n  --option-outline-color: var(--_outline-default); /* transparent — invisible until hover */\n  --option-outline-offset: 0;\n  --option-background-color: var(--_surface-active);\n  --option-padding-block: var(--_spacing-lg);\n  --option-padding-inline: var(--_spacing-lg);\n  --option-font-size: var(--_font-size-md); /* default; drops to --_font-size-sm below a 768px component width unless set */\n  --option-font-weight: 400;\n\n  /* Option label overlaid on non-circle swatches (behaviour.swatchVariant square/portrait/landscape) */\n  --option-label-scrim-colour: #000; /* gradient behind the label */\n  --option-label-overlay-colour: contrast-color(var(--option-label-scrim-colour)); /* default; #fff where contrast-color() is unsupported */\n\n  /* Option card button — hover/focus-visible state; each falls back to its resting\n     counterpart above unless overridden, except outline-color-hover, which falls back to\n     --_outline-active rather than the (transparent) resting outline colour */\n  --option-border-width-hover: 1px;\n  --option-border-color-hover: var(--_border-active);\n  --option-outline-width-hover: 2px;\n  --option-outline-color-hover: var(--_outline-active);\n  --option-outline-offset-hover: 0;\n\n  /* Colour swatch circles (hair type, colour steps, results summary) */\n  --option-swatch-size: 100px; /* default */\n  --option-swatch-border-width: 1px;\n  --option-swatch-border-color: var(--_border-active);\n  --option-swatch-outline-width: 2px;\n  --option-swatch-outline-color: var(--_outline-default); /* transparent — invisible until hover */\n  --option-swatch-outline-offset: 0px;\n  --option-swatch-img-scale: 1;\n\n  /* Colour swatch — hover/focus-visible state, triggered by the parent option button.\n     border-width-hover falls back to its resting counterpart above unless overridden.\n     outline-width-hover has its own 2px default rather than falling back to resting (so a\n     consumer who widens the resting outline doesn't also widen the hover one). The swatch's\n     outline *colour* on hover isn't driven by a swatch-level var at all — the parent option\n     button sets --option-swatch-outline-color itself, to whatever colour its own outline is\n     showing at the time (its hover colour normally, or the checked colour when selected) */\n  --option-swatch-border-width-hover: 1px;\n  --option-swatch-outline-width-hover: 2px;\n  --option-swatch-img-scale-hover: 1;\n\n  /* Granular shade catalog tab bar (Dream/Natural Colour, \"granular\" mode) — width of the\n     scroll-edge fade that hints there are more tabs off-screen */\n  --shade-tabs-fade-size: 30px; /* default */\n\n  /* Virtual try-on takeover — spacing for the sliders/tabs/palette control group above the\n     viewport edge; kept separate from the shared spacing scale so it can be overridden without\n     affecting spacing on every other step */\n  --treatment-consultant-tryon-controls-gap: 0; /* default */\n  --treatment-consultant-tryon-controls-margin-block-end: 0; /* default */\n}\n```\n\nYou can also pass additional classes to the root element:\n\n```vue\n<TreatmentConsultant style-class-passthrough=\"my-custom-theme\" />\n```\n\nThese classes are also re-applied to the virtual try-on takeover, which is teleported to `<body>`, so `.treatment-consultant.my-custom-theme { ... }` overrides reach it too. Write those overrides in a global or plain (unscoped) `<style>` block: Vue's `<style scoped>` matches on the consuming component's `data-v-*` attribute, which the teleported takeover doesn't carry, so scoped overrides apply to the main wizard but silently miss the takeover. If you need scoping, use `:global(.treatment-consultant.my-custom-theme)` inside the scoped block.\n\n---\n\n## Exported API\n\n```ts\nimport {\n  TreatmentConsultant,        // Vue component\n  createHairTreatments,       // plugin factory — register once at app level\n  HAIR_TREATMENTS_CONFIG_KEY, // advanced: the raw injection key, if you need to provide()/inject() manually\n  defaultConfig,               // full default config object\n  mergeConfig,                 // utility: mergeConfig(defaultConfig, partialOverride)\n} from \"srcdev-hair-treatments\";\n\nimport type {\n  // Config\n  TreatmentConsultantConfig,\n  TextConfig,\n  DeepPartial,\n\n  // ID types\n  HairTypeId,\n  NaturalColourId,\n  DesiredColourId,\n  TreatmentId,\n  ApplicationTypeId,\n  CutId,\n\n  // Data shape types\n  HairTypeOption,\n  ColourOption,\n  DesiredColourOption,\n  Treatment,\n  ApplicationTypeOption,\n  CutOption,\n  CutWarning,\n\n  // Result types\n  Recommendation,\n  Suitability,\n  SuitabilityEntry,\n\n  // Event payload — see \"Events\" above\n  ConsultationSelections,\n} from \"srcdev-hair-treatments\";\n```\n\n---\n\n## Development\n\n### Prerequisites\n\n- Node 20–22\n- npm 10+\n\n### Commands\n\n```bash\n# Install dependencies\nnpm install\n\n# Start Storybook dev server (http://localhost:6006)\nnpm run storybook\n\n# Type check\nnpm run typecheck\n\n# Lint\nnpm run lint\n\n# Build library output (dist/)\nnpm run build\n```\n\n---\n\n## Testing\n\n### Unit Tests (Vitest)\n\nUnit tests cover the colour recommendation matrix, config merge logic, and all composable behaviour (navigation, step skipping, treatment conflict logic, cut warnings, and computed values).\n\n```bash\n# Watch mode\nnpm run test\n\n# Single run\nnpm run test:run\n\n# Browser UI\nnpm run test:ui\n\n# Update snapshots\nnpm run test:update\n```\n\n### Visual Regression Tests (Playwright)\n\nRequires Storybook to be built and served first.\n\n```bash\n# 1. Build and serve Storybook\nnpm run storybook:serve\n\n# 2. In a separate terminal, run visual tests\nnpm run playwright\n\n# Update visual baselines after an intentional change\nnpm run playwright:update\n```\n\n> Visual tests run across Chromium, Firefox, and WebKit.\n\n### What Each Layer Catches\n\n| Change                          | Unit tests | Visual tests |\n| ------------------------------- | :--------: | :----------: |\n| Config / behaviour logic broken | ✅         | ❌           |\n| Colour recommendation wrong     | ✅         | ❌           |\n| Font / colour / spacing changed | ❌         | ✅           |\n| Layout or visual regression     | ❌         | ✅           |\n\n---\n\n## Storybook\n\n```bash\n# Dev server\nnpm run storybook\n\n# Build static output\nnpm run storybook:build\n\n# Build and serve (used before Playwright)\nnpm run storybook:serve\n\n# Clear caches (if styles appear stale)\nnpm run storybook:cache:clean\n```\n\n> After clearing the cache, restart with `npm run storybook`. Useful when `@layer` CSS changes aren't reflected in the running dev server.\n\n### Fonts\n\nFonts are served from local files in `.storybook/public/_fonts/` and declared in `.storybook/fonts.css`.\n\n| Font             | Format |\n| ---------------- | ------ |\n| Inter            | woff2  |\n| Playfair Display | woff2  |\n\n---\n\n## Architecture\n\n```text\nsrc/\n├── components/\n│   └── treatment-consultant/\n│       ├── TreatmentConsultant.vue       # Template + CSS only\n│       └── stories/\n│           └── TreatmentConsultant.stories.ts\n├── composables/\n│   └── useTreatmentConsultant.ts        # All reactive state and actions\n├── config/\n│   ├── types.ts                          # All types — IDs, data shapes, TextConfig, TreatmentConsultantConfig\n│   ├── defaults.ts                       # defaultConfig + mergeConfig\n│   └── matrix.ts                         # Colour recommendation logic (private)\n└── index.ts                              # Public API exports\n```\n\nThe recommendation matrix (natural colour × desired colour → suitability) is private to the package and not part of the public API.\n\n---\n\n## Third-Party Notices\n\nThe [Virtual try-on](#virtual-try-on) feature uses:\n\n- **[MediaPipe](https://github.com/google-ai-edge/mediapipe)** (`@mediapipe/tasks-vision`) — Apache License 2.0.\n- **The official MediaPipe Hair Segmenter model**, redistributed as `public/models/treatment-consultant/hair_segmenter.tflite` — Apache License 2.0. Source: <https://storage.googleapis.com/mediapipe-models/image_segmenter/hair_segmenter/float32/1/hair_segmenter.tflite> (SHA-256: `2628cf3ce5f695f604cbea2841e00befcaa3624bf80caf3664bef2656d59bf84`).\n- The webcam/upload segmentation-and-composite approach in `useHairSegmentation.ts` was adapted from [`Ys-sudo/hair-coloring-app`](https://github.com/Ys-sudo/hair-coloring-app) (MIT License), which itself redistributes the same MediaPipe model.\n\n---\n\n## Known Issues\n\n### Vercel deploy fails with missing `@oxc-transform` arm binding (Nuxt apps)\n\n**Symptom:** Build passes locally on macOS but fails on Vercel with an npm error about `@oxc-transform/binding-linux-arm-gnueabihf`.\n\n**Cause:** npm on macOS can write an incomplete stub entry for `@oxc-transform/binding-linux-arm-gnueabihf` (no version field) into the lock file. On Vercel's Linux x64 environment the OS name matches the arm package name, so npm tries to process the entry, hits the missing version, and errors out.\n\n**Fix:** Pin your consuming app to Node 24+ so both local and Vercel use the same npm version, which generates correct lock file stubs. Add an `engines` field to your `package.json`:\n\n```json\n\"engines\": {\n  \"node\": \">= 24\"\n}\n```\n\nIf you use `.nvmrc`, set it to `24` as well — but `engines` is what Vercel reads to select the runtime. You may also need to delete `package-lock.json` and re-run `npm install` locally to regenerate a clean lock file before redeploying.\n\n> This is a Nuxt / oxc-transform interaction and is likely to be resolved in a future Nuxt release.\n\n### SSR crash in production Nuxt builds: `Cannot read properties of null (reading 'ce')`\n\n**Symptom:** `<TreatmentConsultant />` renders fine in `npm run dev`, but a production Nuxt build (`nuxi build` + `node .output/server/index.mjs`) 500s on the very first request, with a stack trace through `renderSlot` inside `OptionButton.vue`'s compiled render function.\n\n**Cause:** This package is a plain Vue 3 library — it ships a single client-targeted `render()` per component and no compiled `ssrRender`. Nuxt's own SSR renderer (`vue-bundle-renderer`, not `@vue/server-renderer`) does not reliably support components that fall back to client-render during SSR, particularly when several sibling components (e.g. the `OptionButton` instances in a step's `v-for`) hit that fallback path together.\n\n**Fix:** Render the wizard client-only — it's a multi-step consultation form with no SEO value, so there's nothing to gain from SSR-ing it anyway. Wrap it in Nuxt's [`<ClientOnly>`](https://nuxt.com/docs/api/components/client-only):\n\n```vue\n<template>\n  <ClientOnly>\n    <TreatmentConsultant :config=\"config\" />\n  </ClientOnly>\n</template>\n```\n\nThis is the recommended pattern for any Nuxt/SSR consumer of this component; the package intentionally does not ship an SSR-compiled build.\n","readmeFilename":"README.md"}