srcdev-nuxt-components 8.0.3 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -118
- package/app/assets/styles/extends-layer/srcdev-components/components/_display-prompt-core.css +94 -0
- package/app/assets/styles/extends-layer/srcdev-components/components/_display-toast.css +5 -0
- package/app/assets/styles/extends-layer/srcdev-components/components/_expanding-panel.css +37 -0
- package/app/assets/styles/extends-layer/srcdev-components/components/index.css +3 -0
- package/app/assets/styles/extends-layer/srcdev-components/index.css +1 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_form-fieldset.css +38 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-button.css +67 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-checkbox-radio-core.css +87 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-checkbox-radio-options-button.css +74 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-checkbox-radio-with-label.css +14 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-description.css +13 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-error.css +54 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-label.css +21 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-select.css +143 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-text.css +190 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-textarea.css +96 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-toggle-switch.css +68 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/index.css +12 -0
- package/app/assets/styles/extends-layer/srcdev-forms/index.css +2 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/_generic.css +21 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/index.css +3 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/sizes/_default.css +13 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/sizes/_large.css +12 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/sizes/_medium.css +12 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/sizes/_small.css +12 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/sizes/_x-small.css +11 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/sizes/index.css +23 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_default.css +62 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_error.css +63 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_ghost.css +63 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_info.css +63 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_primary.css +66 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_secondary.css +64 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_success.css +63 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_tertiary.css +63 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_warning.css +63 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/index.css +7 -0
- package/app/assets/styles/main.css +2 -0
- package/app/assets/styles/setup/01.config/_basic-resets.css +9 -0
- package/app/assets/styles/setup/01.config/_head.css +33 -0
- package/app/assets/styles/setup/01.config/_normalise.css +209 -0
- package/app/assets/styles/setup/01.config/index.css +3 -0
- package/app/assets/styles/setup/02.colours/_amber.css +12 -0
- package/app/assets/styles/setup/02.colours/_blue.css +13 -0
- package/app/assets/styles/setup/02.colours/_green.css +13 -0
- package/app/assets/styles/setup/02.colours/_orange.css +12 -0
- package/app/assets/styles/setup/02.colours/_red.css +13 -0
- package/app/assets/styles/setup/02.colours/_slate.css +13 -0
- package/app/assets/styles/setup/02.colours/_sunset.css +12 -0
- package/app/assets/styles/setup/02.colours/index.css +7 -0
- package/app/assets/styles/setup/03.theming/default/_dark.css +138 -0
- package/app/assets/styles/setup/03.theming/default/_light.css +156 -0
- package/app/assets/styles/setup/03.theming/default/index.css +2 -0
- package/app/assets/styles/setup/03.theming/error/_dark.css +56 -0
- package/app/assets/styles/setup/03.theming/error/_light.css +74 -0
- package/app/assets/styles/setup/03.theming/error/index.css +2 -0
- package/app/assets/styles/setup/03.theming/index.css +4 -0
- package/app/assets/styles/setup/03.theming/success/_dark.css +50 -0
- package/app/assets/styles/setup/03.theming/success/_light.css +65 -0
- package/app/assets/styles/setup/03.theming/success/index.css +2 -0
- package/app/assets/styles/setup/03.theming/warning/_dark.css +50 -0
- package/app/assets/styles/setup/03.theming/warning/_light.css +64 -0
- package/app/assets/styles/setup/03.theming/warning/index.css +2 -0
- package/app/assets/styles/setup/04.elements/forms/00.element-defaults.css +21 -0
- package/app/assets/styles/setup/04.elements/forms/01.field-layout-container-level.css +14 -0
- package/app/assets/styles/setup/04.elements/forms/02.typography.css +24 -0
- package/app/assets/styles/setup/04.elements/forms/03.generic-input-geometry.css +63 -0
- package/app/assets/styles/setup/04.elements/forms/04.slot-icon-system.css +14 -0
- package/app/assets/styles/setup/04.elements/forms/05.checkbox-radio-geometry.css +17 -0
- package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +17 -0
- package/app/assets/styles/setup/04.elements/forms/07.validation-error-block-layout.css +9 -0
- package/app/assets/styles/setup/04.elements/forms/09.animation-motion.css +6 -0
- package/app/assets/styles/setup/04.elements/forms/index.css +9 -0
- package/app/assets/styles/setup/04.elements/index.css +1 -0
- package/app/assets/styles/setup/05.typography/01.tokens/_font-family.css +8 -0
- package/app/assets/styles/setup/05.typography/01.tokens/_reponsive-font-sizes.css +22 -0
- package/app/assets/styles/setup/05.typography/01.tokens/_timing-functions.css +119 -0
- package/app/assets/styles/setup/05.typography/01.tokens/index.css +3 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_font-classes-article.css +30 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_font-classes-card.css +45 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_font-classes-page-body.css +146 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_font-classes-page-heading.css +35 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_font-classes-page-link.css +116 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_font-classes-section.css +7 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_generic-font-classes.css +3 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_generic-font-variation-settings.css +29 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/_generic-font-weights.css +39 -0
- package/app/assets/styles/setup/05.typography/02.utility-classes/index.css +9 -0
- package/app/assets/styles/setup/05.typography/index.css +2 -0
- package/app/assets/styles/setup/06.utility-classes/_a11y.css +280 -0
- package/app/assets/styles/setup/06.utility-classes/animations/_auto-rotate.css +13 -0
- package/app/assets/styles/setup/06.utility-classes/animations/_entry-exit-blur.css +16 -0
- package/app/assets/styles/setup/06.utility-classes/animations/_entry-slide-in.css +15 -0
- package/app/assets/styles/setup/06.utility-classes/animations/_entry-zoom-reveal.css +15 -0
- package/app/assets/styles/setup/06.utility-classes/animations/index.css +4 -0
- package/app/assets/styles/setup/06.utility-classes/index.css +4 -0
- package/app/assets/styles/setup/06.utility-classes/layout/_containers.css +96 -0
- package/app/assets/styles/setup/06.utility-classes/layout/_flexbox.css +196 -0
- package/app/assets/styles/setup/06.utility-classes/layout/_grid.css +266 -0
- package/app/assets/styles/setup/06.utility-classes/layout/_positioning.css +149 -0
- package/app/assets/styles/setup/06.utility-classes/layout/index.css +9 -0
- package/app/assets/styles/setup/06.utility-classes/spacing/_fluid-spacing.css +13 -0
- package/app/assets/styles/setup/06.utility-classes/spacing/_margin.css +334 -0
- package/app/assets/styles/setup/06.utility-classes/spacing/_padding.css +308 -0
- package/app/assets/styles/setup/06.utility-classes/spacing/index.css +3 -0
- package/app/assets/styles/setup/a11y/_variables.css +8 -0
- package/app/assets/styles/setup/a11y/index.css +1 -0
- package/app/assets/styles/setup/index.css +10 -0
- package/app/components/01.atoms/animations/entry/EntryAnimation.vue +22 -0
- package/app/components/01.atoms/animations/entry/stories/EntryAnimation.stories.ts +74 -0
- package/app/components/01.atoms/glass-panel/GlassPanel.vue +52 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/EyebrowText.vue +42 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts +67 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/default-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/default-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/default-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-large-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-large-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-large-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-medium-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-medium-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-medium-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-small-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-small-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/fontSize-small-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-div-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-div-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-div-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-p-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-p-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-p-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-span-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-span-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/playwright/eyebrow-text.playwright.ts-snapshots/tag-span-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/stories/EyebrowText.stories.ts +49 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/tests/EyebrowText.spec.ts +196 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/tests/__snapshots__/EyebrowText.spec.ts.snap +17 -0
- package/app/components/01.atoms/text-blocks/hero-text/HeroText.vue +101 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts +110 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-display-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-display-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-display-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-heading-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-heading-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-heading-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-label-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-label-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-label-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-subheading-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-subheading-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-subheading-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-title-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-title-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-fontSize-title-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-horizontal-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-display-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-display-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-display-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-heading-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-heading-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-heading-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-label-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-label-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-label-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-subheading-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-subheading-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-subheading-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-title-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-title-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-fontSize-title-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/axis-vertical-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/default-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/default-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/default-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-display-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-display-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-display-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-heading-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-heading-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-heading-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-label-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-label-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-label-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-subheading-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-subheading-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-subheading-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-title-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-title-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/fontSize-title-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/icon-with-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/icon-with-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/icon-with-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/icon-without-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/icon-without-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/icon-without-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h1-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h1-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h1-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h2-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h2-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h2-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h3-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h3-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h3-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h4-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h4-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h4-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h5-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h5-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h5-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h6-chromium-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h6-firefox-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/playwright/hero-text.playwright.ts-snapshots/tag-h6-webkit-darwin.png +0 -0
- package/app/components/01.atoms/text-blocks/hero-text/stories/HeroText.stories.ts +70 -0
- package/app/components/01.atoms/text-blocks/hero-text/tests/HeroText.spec.ts +148 -0
- package/app/components/01.atoms/text-blocks/hero-text/tests/__snapshots__/HeroText.spec.ts.snap +7 -0
- package/app/components/02.molecules/contact-section/stories/ContactSection.stories.ts +197 -0
- package/app/components/02.molecules/contact-section/tests/ContactSection.spec.ts +196 -0
- package/app/components/02.molecules/contact-section/tests/ContactSection.vue +87 -0
- package/app/components/02.molecules/contact-section/tests/__snapshots__/ContactSection.spec.ts.snap +119 -0
- package/app/components/02.molecules/price-list/PriceList.vue +119 -0
- package/app/components/02.molecules/price-list/stories/PriceList.stories.ts +103 -0
- package/app/components/02.molecules/price-list/tests/PriceList.spec.ts +192 -0
- package/app/components/02.molecules/price-list/tests/__snapshots__/PriceList.spec.ts.snap +73 -0
- package/app/components/02.molecules/profile-section/ProfileSection.vue +154 -0
- package/app/components/02.molecules/profile-section/stories/ProfileSection.stories.ts +154 -0
- package/app/components/02.molecules/profile-section/tests/ProfileSection.spec.ts +147 -0
- package/app/components/02.molecules/profile-section/tests/__snapshots__/ProfileSection.spec.ts.snap +29 -0
- package/app/components/02.molecules/stepper-list/StepperList.vue +158 -0
- package/app/components/02.molecules/stepper-list/stories/StepperList.stories.ts +392 -0
- package/app/components/02.molecules/stepper-list/tests/StepperList.spec.ts +289 -0
- package/app/components/02.molecules/stepper-list/tests/__snapshots__/StepperList.spec.ts.snap +86 -0
- package/app/components/03.organisms/colour-finder/ColourFinder.vue +1519 -0
- package/app/components/03.organisms/services/services-card/ServicesCard.vue +104 -0
- package/app/components/03.organisms/services/services-grids/ServicesCardGrid.vue +39 -0
- package/app/components/03.organisms/services/services-grids/ServicesSectionGrid.vue +52 -0
- package/app/components/03.organisms/services/services-section/ServicesSection.vue +307 -0
- package/app/components/03.organisms/treatment-consultant/TreatmentConsultant.vue +2221 -0
- package/app/components/03.organisms/treatment-consultant/stories/TreatmentConsultant.stories.ts +38 -0
- package/app/components/accordian/AccordianCore.vue +26 -21
- package/app/components/accordian/stories/AccordianCore.stories.ts +241 -0
- package/app/components/accordian/tests/AccordianCore.spec.ts +218 -0
- package/app/components/accordian/tests/__snapshots__/AccordianCore.spec.ts.snap +74 -0
- package/app/components/alert-mask/AlertMaskCore.vue +35 -33
- package/app/components/alert-mask/tests/AlertMaskCore.spec.ts +304 -0
- package/app/components/animated-svg-text/AnimatedSvgText.vue +2 -0
- package/app/components/canvas-switcher/CanvasSwitcher.vue +10 -8
- package/app/components/{carousel-basic → carousels}/CarouselBasic.vue +58 -56
- package/app/components/{carousel-basic → carousels}/CarouselFlip.vue +150 -148
- package/app/components/{carousel-basic → carousels}/CarouselInfinite.vue +2 -0
- package/app/components/carousels/stories/CarouselFlip.stories.ts +637 -0
- package/app/components/carousels/tests/CarouselFlip.spec.ts +556 -0
- package/app/components/clip-element/ClipElement.vue +2 -0
- package/app/components/clipped-panels/ClippedPanel.vue +2 -0
- package/app/components/container-glow/ContainerGlowCore.vue +119 -50
- package/app/components/container-glow/stories/ContainerGlowCore.stories.ts +337 -0
- package/app/components/content-columns/TwoColumns.vue +59 -0
- package/app/components/content-columns/stories/TwoColumns.stories.ts +561 -0
- package/app/components/content-containers/ContentContainer.vue +89 -0
- package/app/components/content-containers/stories/ContentContainer.stories.ts +465 -0
- package/app/components/content-grid/ContentGrid.vue +4 -2
- package/app/components/deep-expanding-menu/DeepExpandingMenu.vue +18 -16
- package/app/components/deep-expanding-menu/DeepExpandingMenuOld.vue +28 -26
- package/app/components/display-avatar/DisplayAvatar.vue +15 -13
- package/app/components/display-avatar/stories/DisplayAvatar.stories.ts +94 -0
- package/app/components/display-banner/DisplayBanner.vue +2 -0
- package/app/components/display-card/DisplayCard.vue +16 -14
- package/app/components/display-chip/DisplayChip.vue +2 -0
- package/app/components/display-chip/stories/DisplayChip.stories.ts +346 -0
- package/app/components/display-details/DisplayDetailsCore.vue +2 -0
- package/app/components/display-dialog/DisplayDialogCore.vue +24 -17
- package/app/components/display-dialog/variants/DisplayDialogConfirm.vue +2 -0
- package/app/components/display-dialog/variants/DisplayDialogScrollableContent.vue +2 -0
- package/app/components/display-grid/DisplayGridCore.vue +4 -4
- package/app/components/display-prompt/DisplayPromptCore.vue +20 -16
- package/app/components/display-prompt/variants/DisplayPromptError.vue +6 -4
- package/app/components/display-theme-switch/DisplayThemeSwitch.vue +182 -0
- package/app/components/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +154 -0
- package/app/components/display-toast/DisplayToast.vue +63 -61
- package/app/components/display-toast/molecules/DefaultToastContent.vue +21 -45
- package/app/components/display-toast/stories/DisplayToast.stories.ts +380 -0
- package/app/components/display-tooltip/DisplayTooltip.vue +14 -9
- package/app/components/display-tooltip/DisplayTooltipDefined.vue +2 -0
- package/app/components/expanding-panel/ExpandingPanel.vue +28 -41
- package/app/components/forms/c12/prop-validators/index.ts +48 -0
- package/app/components/forms/c12/utils.ts +14 -0
- package/app/components/forms/form-errors/InputError.vue +208 -0
- package/app/components/forms/form-errors/tests/InputError.spec.ts +66 -0
- package/app/components/forms/form-fieldset/FormFieldset.vue +75 -0
- package/app/components/forms/input-button/InputButtonCore.vue +219 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts +113 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-secondary-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-secondary-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-secondary-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-tertiary-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-tertiary-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-tertiary-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-primary-pending-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-primary-pending-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-primary-pending-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-secondary-pill-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-secondary-pill-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-secondary-pill-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-tertiary-readonly-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-tertiary-readonly-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-tertiary-readonly-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-default-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-default-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-default-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-error-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-error-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-error-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-success-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-success-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-success-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-warning-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-warning-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-warning-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-primary-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-primary-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-primary-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-secondary-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-secondary-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-secondary-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-tertiary-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-tertiary-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-tertiary-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/nuxt-icon-only-component-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/nuxt-icon-only-component-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/nuxt-icon-only-component-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pending-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pending-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pending-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pill-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pill-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pill-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-readonly-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-readonly-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-readonly-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/with-both-nuxt-icon-components-chromium-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/with-both-nuxt-icon-components-firefox-darwin.png +0 -0
- package/app/components/forms/input-button/playwright/input-button-core.playwright.ts-snapshots/with-both-nuxt-icon-components-webkit-darwin.png +0 -0
- package/app/components/forms/input-button/stories/InputButtonCore.stories.ts +304 -0
- package/app/components/forms/input-button/tests/InputButtonCore.spec.ts +269 -0
- package/app/components/forms/input-button/tests/__snapshots__/InputButtonCore.spec.ts.snap +72 -0
- package/app/components/forms/input-checkbox/MultipleCheckboxes.vue +181 -0
- package/app/components/forms/input-checkbox/SingleCheckbox.vue +144 -0
- package/app/components/forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +101 -0
- package/app/components/forms/input-checkbox/tests/data/tags.json +67 -0
- package/app/components/forms/input-checkbox-radio/InputCheckboxRadioButton.vue +174 -0
- package/app/components/forms/input-checkbox-radio/InputCheckboxRadioCore.vue +199 -0
- package/app/components/forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +104 -0
- package/app/components/forms/input-checkbox-radio/tests/InputCheckboxRadioCore.spec.ts +320 -0
- package/app/components/forms/input-description/InputDescription.vue +55 -0
- package/app/components/forms/input-description/tests/InputDescription.spec.ts +429 -0
- package/app/components/forms/input-label/InputLabel.vue +66 -0
- package/app/components/forms/input-label/tests/InputLabel.spec.ts +431 -0
- package/app/components/forms/input-number/InputNumberCore.vue +163 -0
- package/app/components/forms/input-number/variants/InputNumberDefault.vue +150 -0
- package/app/components/forms/input-radio/MultipleRadiobuttons.vue +180 -0
- package/app/components/forms/input-radio/tests/MultipleRadioButtons.spec.ts +90 -0
- package/app/components/forms/input-radio/tests/data/tags.json +67 -0
- package/app/components/forms/input-range/InputRangeCore.vue +233 -0
- package/app/components/forms/input-range/variants/InputRangeDefault.vue +166 -0
- package/app/components/forms/input-range-fancy/InputRangeFancyCore.vue +426 -0
- package/app/components/forms/input-range-fancy/InputRangeFancyWithLabel.vue +94 -0
- package/app/components/forms/input-select/InputSelectCore.vue +171 -0
- package/app/components/forms/input-select/variants/InputSelectWithLabel.vue +121 -0
- package/app/components/forms/input-text/InputTextCore.vue +222 -0
- package/app/components/forms/input-text/stories/InputPasswordWithLabel.stories.ts +339 -0
- package/app/components/forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +461 -0
- package/app/components/forms/input-text/stories/InputTextCore.stories.ts +241 -0
- package/app/components/forms/input-text/stories/InputTextWithLabel.stories.ts +293 -0
- package/app/components/forms/input-text/variants/InputPasswordWithLabel.vue +86 -0
- package/app/components/forms/input-text/variants/InputTextAsNumberWithLabel.vue +203 -0
- package/app/components/forms/input-text/variants/InputTextWithLabel.vue +149 -0
- package/app/components/forms/input-textarea/InputTextareaCore.vue +151 -0
- package/app/components/forms/input-textarea/stories/InputTextareaCore.stories.ts +247 -0
- package/app/components/forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +452 -0
- package/app/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +150 -0
- package/app/components/forms/pending-effect/PendingEffect.vue +101 -0
- package/app/components/forms/toggle-switch/ToggleSwitchCore.vue +221 -0
- package/app/components/forms/toggle-switch/stories/ToggleSwitchCore.stories.ts +236 -0
- package/app/components/forms/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +253 -0
- package/app/components/forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +280 -0
- package/app/components/forms/toggle-switch/variants/ToggleSwitchWithLabel.vue +101 -0
- package/app/components/forms/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +84 -0
- package/app/components/forms/triple-toggle-switch/TripleToggleSwitchCore.vue +290 -0
- package/app/components/forms/ui/FormField.vue +81 -0
- package/app/components/forms/ui/FormWrapper.vue +37 -0
- package/app/components/glowing-border/GlowingBorder.vue +2 -0
- package/app/components/glowing-border/stories/GlowingBorder.stories.ts +141 -0
- package/app/components/image-galleries/SliderGallery.vue +100 -100
- package/app/components/layout-grids/LayoutGridA.vue +2 -0
- package/app/components/layout-grids/LayoutGridB.vue +8 -6
- package/app/components/layout-grids/stories/LayoutGridA.stories.ts +402 -0
- package/app/components/layout-grids/stories/LayoutGridB.stories.ts +420 -0
- package/app/components/layout-grids/tests/LayoutGridA.spec.ts +352 -0
- package/app/components/layout-grids/tests/LayoutGridB.spec.ts +490 -0
- package/app/components/layout-row/LayoutRow.vue +60 -54
- package/app/components/layout-row/stories/LayoutRow.stories.ts +528 -0
- package/app/components/magnetic-navigation/MagneticNavigation.vue +2 -0
- package/app/components/marquee-scroller/MarqueeScroller.vue +35 -33
- package/app/components/masonry-grid/MasonryGrid.vue +8 -6
- package/app/components/masonry-grid-ordered/MasonryGridOrdered.vue +2 -0
- package/app/components/masonry-grid-ordered/MasonryGridOrderedGridExperiment.vue +82 -87
- package/app/components/masonry-grid-ordered/stories/MasonryGridOrdered.stories.ts +354 -0
- package/app/components/masonry-grid-sorted/MasonryGridSorted.vue +2 -0
- package/app/components/parallax/SectionParallax.vue +10 -8
- package/app/components/pop-over/PopOver.vue +2 -0
- package/app/components/qr-code/CaptureQrCode.vue +2 -0
- package/app/components/qr-code/DecodeQrCode.vue +2 -0
- package/app/components/qr-code/DisplayQrCode.vue +7 -5
- package/app/components/qr-code/stories/QrCode.stories.ts +933 -0
- package/app/components/responsive-header/NavigationItems.vue +34 -23
- package/app/components/responsive-header/ResponsiveHeader.vue +163 -157
- package/app/components/rotating-carousel/RotatingCarouselImage.vue +2 -0
- package/app/components/skip-links/SkipLinks.vue +2 -0
- package/app/components/tabs/TabsCore.vue +38 -30
- package/app/components/test-storybook/TestStorybook.vue +49 -0
- package/app/components/test-storybook/stories/TestStorybook.stories.ts +28 -0
- package/app/components/ui-block-decorated/UiBlockDecorated.vue +2 -0
- package/app/components/view-timeline/WipeAwayVertical.vue +2 -0
- package/app/composables/useApiRequest.ts +25 -0
- package/app/composables/useAriaDescribedById.ts +19 -0
- package/app/composables/useColourScheme.ts +18 -0
- package/app/composables/useErrorMessages.ts +62 -0
- package/app/composables/useFormControl.ts +264 -0
- package/app/composables/useMaxChildWidth.ts +30 -0
- package/app/composables/useTabs.ts +207 -117
- package/app/composables/useZodValidation.ts +147 -0
- package/app/layouts/default.vue +605 -0
- package/app/pages/forms/examples/buttons/index.vue +285 -0
- package/app/pages/forms/examples/material/checkbox-radio-panels.vue +244 -0
- package/app/pages/forms/examples/material/cssbattle.vue +60 -0
- package/app/pages/forms/examples/material/text-fields.vue +913 -0
- package/app/pages/index.vue +122 -0
- package/app/pages/typography/hero-text.vue +97 -0
- package/app/pages/typography/index.vue +39 -0
- package/app/pages/typography/page-body.vue +171 -0
- package/app/pages/typography/page-heading.vue +76 -0
- package/app/pages/typography/page-link.vue +103 -0
- package/app/pages/ui/accordian.vue +211 -0
- package/app/pages/ui/animated-svg-text.vue +85 -0
- package/app/pages/ui/block-decorators.vue +142 -0
- package/app/pages/ui/carousel-basic.vue +292 -0
- package/app/pages/ui/carousel-flip.vue +244 -0
- package/app/pages/ui/carousel-infinite.vue +260 -0
- package/app/pages/ui/clipped-panels.vue +101 -0
- package/app/pages/ui/contact-section.vue +323 -0
- package/app/pages/ui/container-glow.vue +107 -0
- package/app/pages/ui/content-container.vue +112 -0
- package/app/pages/ui/display-avatar.vue +253 -0
- package/app/pages/ui/display-banner.vue +78 -0
- package/app/pages/ui/display-card.vue +82 -0
- package/app/pages/ui/display-chip.vue +225 -0
- package/app/pages/ui/display-details.vue +175 -0
- package/app/pages/ui/display-dialog.vue +231 -0
- package/app/pages/ui/display-prompt.vue +81 -0
- package/app/pages/ui/display-toast.vue +332 -0
- package/app/pages/ui/expanding-panel.vue +193 -0
- package/app/pages/ui/glowing-border.vue +111 -0
- package/app/pages/ui/layout-grid-a.vue +149 -0
- package/app/pages/ui/layout-grid-b.vue +132 -0
- package/app/pages/ui/layout-row.vue +139 -0
- package/app/pages/ui/magnetic-navigation.vue +50 -0
- package/app/pages/ui/marquee-scroller.vue +99 -0
- package/app/pages/ui/mask-element.vue +82 -0
- package/app/pages/ui/masonry-columns.vue +55 -0
- package/app/pages/ui/masonry-grid-ordered-experiment.vue +79 -0
- package/app/pages/ui/masonry-grid-ordered.vue +56 -0
- package/app/pages/ui/masonry-grid-sorted.vue +55 -0
- package/app/pages/ui/masonry-grid.vue +55 -0
- package/app/pages/ui/price-list.vue +65 -0
- package/app/pages/ui/profile-section.vue +96 -0
- package/app/pages/ui/qr-code/[componentName].vue +218 -0
- package/app/pages/ui/rotating-carousel.vue +154 -0
- package/app/pages/ui/section-parallax.vue +54 -0
- package/app/pages/ui/services/colour-finder.vue +43 -0
- package/app/pages/ui/services/services-cards.vue +42 -0
- package/app/pages/ui/services/services-section/[slug].vue +59 -0
- package/app/pages/ui/services/services-sections-compact.vue +64 -0
- package/app/pages/ui/services/treatment-consultant.vue +39 -0
- package/app/pages/ui/settings.vue +80 -0
- package/app/pages/ui/simple-grid.vue +66 -0
- package/app/pages/ui/slider-gallery.vue +261 -0
- package/app/pages/ui/tabs-y.vue +108 -0
- package/app/pages/ui/tabs.vue +192 -0
- package/app/pages/ui/tooltips.vue +104 -0
- package/app/pages/ui/wipe-away-vertical.vue +129 -0
- package/app/plugins/css-anchor-positioning-polyfill.client.ts +5 -0
- package/app/stores/useServicesStore.ts +37 -0
- package/app/stores/useSettingsStore.ts +35 -0
- package/app/types/components/hero-text.ts +4 -0
- package/app/types/components/index.ts +1 -0
- package/app/types/forms/types.forms.d.ts +293 -0
- package/app/types/forms/types.zodFormControl.d.ts +29 -0
- package/app/types/types.posts.ts +21 -0
- package/app/types/types.quotes.ts +12 -0
- package/app/types/types.services.ts +20 -0
- package/app/utils/colour-scheme-init.ts +17 -0
- package/nuxt.config.ts +86 -6
- package/package.json +51 -14
- package/types/components/css-anchor-polyfill.d.ts +1 -0
|
@@ -0,0 +1,2221 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="treatment-consultant">
|
|
3
|
+
<div class="treatment-consultant__container">
|
|
4
|
+
<div class="treatment-consultant__content">
|
|
5
|
+
<!-- Header -->
|
|
6
|
+
<div
|
|
7
|
+
v-motion
|
|
8
|
+
:initial="{ opacity: 0, y: 20 }"
|
|
9
|
+
:enter="{ opacity: 1, y: 0 }"
|
|
10
|
+
class="treatment-consultant__header"
|
|
11
|
+
>
|
|
12
|
+
<EyebrowText text-content="Interactive Tool" font-size="large" />
|
|
13
|
+
<h1 class="treatment-consultant__title">
|
|
14
|
+
Find Your
|
|
15
|
+
<span class="treatment-consultant__title-highlight">Perfect Look</span>
|
|
16
|
+
</h1>
|
|
17
|
+
<p class="treatment-consultant__subtitle">
|
|
18
|
+
Select your hair type, current colour, dream shade, and any treatments to get personalised recommendations.
|
|
19
|
+
</p>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<!-- Progress Steps -->
|
|
23
|
+
<div class="treatment-consultant__progress">
|
|
24
|
+
<template v-for="(s, i) in STEPS" :key="s">
|
|
25
|
+
<div class="treatment-consultant__progress-step">
|
|
26
|
+
<button
|
|
27
|
+
:class="[
|
|
28
|
+
'treatment-consultant__progress-button',
|
|
29
|
+
{
|
|
30
|
+
'treatment-consultant__progress-button--active': i === step,
|
|
31
|
+
'treatment-consultant__progress-button--completed': i < step,
|
|
32
|
+
'treatment-consultant__progress-button--inactive': i > step,
|
|
33
|
+
},
|
|
34
|
+
]"
|
|
35
|
+
@click="
|
|
36
|
+
() => {
|
|
37
|
+
if (i < step) step = i;
|
|
38
|
+
}
|
|
39
|
+
"
|
|
40
|
+
>
|
|
41
|
+
<span
|
|
42
|
+
:class="[
|
|
43
|
+
'treatment-consultant__progress-indicator',
|
|
44
|
+
{
|
|
45
|
+
'treatment-consultant__progress-indicator--completed': i < step,
|
|
46
|
+
'treatment-consultant__progress-indicator--active': i === step,
|
|
47
|
+
'treatment-consultant__progress-indicator--inactive': i > step,
|
|
48
|
+
},
|
|
49
|
+
]"
|
|
50
|
+
>
|
|
51
|
+
{{ i < step ? "✓" : i + 1 }}
|
|
52
|
+
</span>
|
|
53
|
+
<span class="treatment-consultant__progress-label">{{ s }}</span>
|
|
54
|
+
</button>
|
|
55
|
+
<div
|
|
56
|
+
v-if="i < STEPS.length - 1"
|
|
57
|
+
:class="[
|
|
58
|
+
'treatment-consultant__progress-connector',
|
|
59
|
+
{ 'treatment-consultant__progress-connector--completed': i < step },
|
|
60
|
+
]"
|
|
61
|
+
></div>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<!-- Step Content -->
|
|
67
|
+
<Transition name="slide" mode="out-in">
|
|
68
|
+
<!-- Step 0: Hair Type -->
|
|
69
|
+
<div v-if="step === 0" key="step0" class="treatment-consultant__step">
|
|
70
|
+
<h2 class="treatment-consultant__step-title">What's your hair type?</h2>
|
|
71
|
+
<div class="treatment-consultant__options treatment-consultant__options--hair-type">
|
|
72
|
+
<button
|
|
73
|
+
v-for="(ht, index) in hairTypes"
|
|
74
|
+
:key="index"
|
|
75
|
+
:class="[
|
|
76
|
+
'treatment-consultant__option',
|
|
77
|
+
{ 'treatment-consultant__option--selected': hairType === ht.id },
|
|
78
|
+
]"
|
|
79
|
+
@click="selectHairType(ht.id)"
|
|
80
|
+
>
|
|
81
|
+
<span v-if="hairType === ht.id" class="treatment-consultant__option-check">
|
|
82
|
+
<Icon name="lucide:check" class="treatment-consultant__option-check-icon" />
|
|
83
|
+
</span>
|
|
84
|
+
<div class="treatment-consultant__option-pattern">{{ ht.pattern }}</div>
|
|
85
|
+
<span class="treatment-consultant__option-label">{{ ht.label }}</span>
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<!-- Step 1: Natural Colour -->
|
|
91
|
+
<div v-else-if="step === 1" key="step1" class="treatment-consultant__step">
|
|
92
|
+
<h2 class="treatment-consultant__step-title">What's your natural hair colour?</h2>
|
|
93
|
+
<div class="treatment-consultant__options treatment-consultant__options--natural-colour">
|
|
94
|
+
<button
|
|
95
|
+
v-for="(nc, index) in naturalColours"
|
|
96
|
+
:key="index"
|
|
97
|
+
:class="[
|
|
98
|
+
'treatment-consultant__option treatment-consultant__option--colour',
|
|
99
|
+
{ 'treatment-consultant__option--selected': naturalColour === nc.id },
|
|
100
|
+
]"
|
|
101
|
+
@click="selectNaturalColour(nc.id)"
|
|
102
|
+
>
|
|
103
|
+
<span v-if="naturalColour === nc.id" class="treatment-consultant__option-check">
|
|
104
|
+
<Icon name="lucide:check" class="treatment-consultant__option-check-icon" />
|
|
105
|
+
</span>
|
|
106
|
+
<div class="treatment-consultant__option-swatch" :style="{ backgroundColor: nc.colour }">
|
|
107
|
+
<NuxtImg
|
|
108
|
+
v-if="nc.image"
|
|
109
|
+
:src="nc.image"
|
|
110
|
+
width="128"
|
|
111
|
+
height="128"
|
|
112
|
+
alt=""
|
|
113
|
+
class="treatment-consultant__option-image"
|
|
114
|
+
:class="{ 'treatment-consultant__option-image--dark': nc.textDark }"
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
<span
|
|
118
|
+
:class="[
|
|
119
|
+
'treatment-consultant__option-label',
|
|
120
|
+
{ 'treatment-consultant__option-label--selected': naturalColour === nc.id },
|
|
121
|
+
]"
|
|
122
|
+
>
|
|
123
|
+
{{ nc.label }}
|
|
124
|
+
</span>
|
|
125
|
+
</button>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<!-- Step 2: Dream Colour -->
|
|
130
|
+
<div v-else-if="step === 2" key="step2" class="treatment-consultant__step">
|
|
131
|
+
<h2 class="treatment-consultant__step-title">What colour are you dreaming of?</h2>
|
|
132
|
+
<div class="treatment-consultant__options treatment-consultant__options--desired-colour">
|
|
133
|
+
<button
|
|
134
|
+
v-for="(dc, index) in desiredColours"
|
|
135
|
+
:key="index"
|
|
136
|
+
:class="[
|
|
137
|
+
'treatment-consultant__option',
|
|
138
|
+
dc.id === 'none' ? 'treatment-consultant__option--no-change' : 'treatment-consultant__option--colour',
|
|
139
|
+
{ 'treatment-consultant__option--selected': desiredColour === dc.id },
|
|
140
|
+
]"
|
|
141
|
+
@click="selectDesiredColour(dc.id)"
|
|
142
|
+
>
|
|
143
|
+
<span v-if="desiredColour === dc.id" class="treatment-consultant__option-check">
|
|
144
|
+
<Icon name="lucide:check" class="treatment-consultant__option-check-icon" />
|
|
145
|
+
</span>
|
|
146
|
+
<template v-if="dc.id === 'none'">
|
|
147
|
+
<div class="treatment-consultant__option-none-icon">
|
|
148
|
+
<Icon name="lucide:minus-circle" class="treatment-consultant__option-none-icon-svg" />
|
|
149
|
+
</div>
|
|
150
|
+
</template>
|
|
151
|
+
<template v-else>
|
|
152
|
+
<div class="treatment-consultant__option-swatch" :style="{ background: dc.colour }">
|
|
153
|
+
<NuxtImg
|
|
154
|
+
v-if="dc.image"
|
|
155
|
+
:src="dc.image"
|
|
156
|
+
alt=""
|
|
157
|
+
width="128"
|
|
158
|
+
height="128"
|
|
159
|
+
class="treatment-consultant__option-image"
|
|
160
|
+
/>
|
|
161
|
+
</div>
|
|
162
|
+
</template>
|
|
163
|
+
<span
|
|
164
|
+
:class="[
|
|
165
|
+
'treatment-consultant__option-label',
|
|
166
|
+
{ 'treatment-consultant__option-label--selected': desiredColour === dc.id },
|
|
167
|
+
]"
|
|
168
|
+
>
|
|
169
|
+
{{ dc.label }}
|
|
170
|
+
</span>
|
|
171
|
+
<span v-if="dc.id === 'none'" class="treatment-consultant__option-sublabel">
|
|
172
|
+
Skip to style & treatments
|
|
173
|
+
</span>
|
|
174
|
+
</button>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
|
|
178
|
+
<!-- Step 3: Style & Treatments -->
|
|
179
|
+
<div v-else-if="step === 3" key="step3" class="treatment-consultant__step">
|
|
180
|
+
<h2 class="treatment-consultant__step-title">Any style or treatments?</h2>
|
|
181
|
+
<p class="treatment-consultant__step-subtitle">
|
|
182
|
+
Select all that apply, or choose none to go straight to your results.
|
|
183
|
+
</p>
|
|
184
|
+
<div class="treatment-consultant__options treatment-consultant__options--treatments">
|
|
185
|
+
<!-- "No treatments" — full-width, outside the subgrid -->
|
|
186
|
+
<button
|
|
187
|
+
:class="[
|
|
188
|
+
'treatment-consultant__option treatment-consultant__option--treatment treatment-consultant__option--no-change',
|
|
189
|
+
{ 'treatment-consultant__option--selected': selectedTreatments.includes('none') },
|
|
190
|
+
]"
|
|
191
|
+
@click="toggleTreatment('none')"
|
|
192
|
+
>
|
|
193
|
+
<span v-if="selectedTreatments.includes('none')" class="treatment-consultant__option-check">
|
|
194
|
+
<Icon name="lucide:check" class="treatment-consultant__option-check-icon" />
|
|
195
|
+
</span>
|
|
196
|
+
<Icon name="lucide:minus-circle" class="treatment-consultant__option-treatment-icon" />
|
|
197
|
+
<span class="treatment-consultant__option-label">I don't want any treatments</span>
|
|
198
|
+
<span class="treatment-consultant__option-sublabel">Go straight to your results</span>
|
|
199
|
+
</button>
|
|
200
|
+
|
|
201
|
+
<!-- Treatment options grid -->
|
|
202
|
+
<div class="treatment-consultant__treatments-grid">
|
|
203
|
+
<button
|
|
204
|
+
v-for="(tr, index) in treatments.filter((t) => t.id !== 'none')"
|
|
205
|
+
:key="index"
|
|
206
|
+
:class="[
|
|
207
|
+
'treatment-consultant__option treatment-consultant__option--treatment',
|
|
208
|
+
{ 'treatment-consultant__option--selected': selectedTreatments.includes(tr.id) },
|
|
209
|
+
{
|
|
210
|
+
'treatment-consultant__option--excluded':
|
|
211
|
+
allowMultipleTreatments && excludedTreatmentIds.has(tr.id),
|
|
212
|
+
},
|
|
213
|
+
]"
|
|
214
|
+
@click="toggleTreatment(tr.id)"
|
|
215
|
+
>
|
|
216
|
+
<span v-if="selectedTreatments.includes(tr.id)" class="treatment-consultant__option-check">
|
|
217
|
+
<Icon name="lucide:check" class="treatment-consultant__option-check-icon" />
|
|
218
|
+
</span>
|
|
219
|
+
<Icon
|
|
220
|
+
v-if="allowMultipleTreatments && excludedTreatmentIds.has(tr.id)"
|
|
221
|
+
name="lucide:ban"
|
|
222
|
+
class="treatment-consultant__option-excluded-icon"
|
|
223
|
+
/>
|
|
224
|
+
<Icon :name="tr.icon" class="treatment-consultant__option-treatment-icon" />
|
|
225
|
+
<span class="treatment-consultant__option-label">{{ tr.label }}</span>
|
|
226
|
+
<span
|
|
227
|
+
v-if="allowMultipleTreatments && excludedTreatmentIds.has(tr.id)"
|
|
228
|
+
class="treatment-consultant__option-conflict"
|
|
229
|
+
>
|
|
230
|
+
Conflicts with {{ getConflictingLabel(tr.id) }}
|
|
231
|
+
</span>
|
|
232
|
+
<span v-else class="treatment-consultant__option-sublabel">{{ tr.description }}</span>
|
|
233
|
+
</button>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<!-- Step 4: Results -->
|
|
239
|
+
<div v-else-if="step === 4 && canShowResults" key="step4" class="treatment-consultant__results">
|
|
240
|
+
<div class="treatment-consultant__results-header">
|
|
241
|
+
<Icon name="lucide:sparkles" class="treatment-consultant__results-icon" />
|
|
242
|
+
<h2 class="treatment-consultant__results-title">Your Personalised Recommendation</h2>
|
|
243
|
+
</div>
|
|
244
|
+
|
|
245
|
+
<!-- Colour Recommendation -->
|
|
246
|
+
<h3 class="treatment-consultant__results-section-title">
|
|
247
|
+
<Icon name="lucide:palette" class="treatment-consultant__results-section-icon" />
|
|
248
|
+
Colour
|
|
249
|
+
</h3>
|
|
250
|
+
|
|
251
|
+
<template v-if="colourRecommendation">
|
|
252
|
+
<div
|
|
253
|
+
:class="[
|
|
254
|
+
'treatment-consultant__suitability',
|
|
255
|
+
`treatment-consultant__suitability--${colourRecommendation.suitability}`,
|
|
256
|
+
]"
|
|
257
|
+
>
|
|
258
|
+
<Icon
|
|
259
|
+
:name="suitabilityConfig[colourRecommendation.suitability].icon"
|
|
260
|
+
:class="[
|
|
261
|
+
'treatment-consultant__suitability-icon',
|
|
262
|
+
`treatment-consultant__suitability-icon--${colourRecommendation.suitability}`,
|
|
263
|
+
]"
|
|
264
|
+
/>
|
|
265
|
+
<div class="treatment-consultant__suitability-content">
|
|
266
|
+
<p
|
|
267
|
+
:class="[
|
|
268
|
+
'treatment-consultant__suitability-label',
|
|
269
|
+
`treatment-consultant__suitability-label--${colourRecommendation.suitability}`,
|
|
270
|
+
]"
|
|
271
|
+
>
|
|
272
|
+
{{ suitabilityConfig[colourRecommendation.suitability].label }}
|
|
273
|
+
</p>
|
|
274
|
+
<p class="treatment-consultant__suitability-notes">{{ colourRecommendation.notes }}</p>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
<div class="treatment-consultant__details-card">
|
|
278
|
+
<div class="treatment-consultant__details-header">
|
|
279
|
+
<span class="treatment-consultant__details-method-label">Processes Required</span>
|
|
280
|
+
<span class="treatment-consultant__details-method-badge">{{ colourRecommendation.method }}</span>
|
|
281
|
+
</div>
|
|
282
|
+
<div class="treatment-consultant__details-list">
|
|
283
|
+
<div
|
|
284
|
+
v-for="(detail, i) in colourRecommendation.details"
|
|
285
|
+
:key="i"
|
|
286
|
+
v-motion="`color-detail-${i}`"
|
|
287
|
+
:initial="{ opacity: 0, x: -20 }"
|
|
288
|
+
:enter="{ opacity: 1, x: 0, transition: { delay: i * 100 } }"
|
|
289
|
+
class="treatment-consultant__details-item"
|
|
290
|
+
>
|
|
291
|
+
<div class="treatment-consultant__details-bullet"></div>
|
|
292
|
+
<p class="treatment-consultant__details-text">{{ detail }}</p>
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
</template>
|
|
297
|
+
|
|
298
|
+
<!-- No colour treatment chosen -->
|
|
299
|
+
<template v-else>
|
|
300
|
+
<div class="treatment-consultant__suitability treatment-consultant__suitability--none">
|
|
301
|
+
<Icon
|
|
302
|
+
name="lucide:minus-circle"
|
|
303
|
+
class="treatment-consultant__suitability-icon treatment-consultant__suitability-icon--none"
|
|
304
|
+
/>
|
|
305
|
+
<div class="treatment-consultant__suitability-content">
|
|
306
|
+
<p class="treatment-consultant__suitability-label treatment-consultant__suitability-label--none">
|
|
307
|
+
No Colour Treatment
|
|
308
|
+
</p>
|
|
309
|
+
<p class="treatment-consultant__suitability-notes">
|
|
310
|
+
You've chosen to skip colour — a great way to maintain hair health.
|
|
311
|
+
</p>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
</template>
|
|
315
|
+
|
|
316
|
+
<!-- Style & Treatments Recommendation -->
|
|
317
|
+
<h3 class="treatment-consultant__results-section-title treatment-consultant__results-section-title--spaced">
|
|
318
|
+
<Icon name="lucide:wand-2" class="treatment-consultant__results-section-icon" />
|
|
319
|
+
Style & Treatments
|
|
320
|
+
</h3>
|
|
321
|
+
|
|
322
|
+
<template v-if="hasActiveTreatments">
|
|
323
|
+
<div
|
|
324
|
+
v-for="(tr, i) in chosenTreatments"
|
|
325
|
+
:key="i"
|
|
326
|
+
class="treatment-consultant__details-card treatment-consultant__details-card--treatment"
|
|
327
|
+
>
|
|
328
|
+
<div class="treatment-consultant__details-header">
|
|
329
|
+
<Icon :name="tr.icon" class="treatment-consultant__treatment-icon" />
|
|
330
|
+
<span class="treatment-consultant__details-method-label">{{ tr.label }}</span>
|
|
331
|
+
<span
|
|
332
|
+
v-if="tr.compatibility && desiredColour !== 'none'"
|
|
333
|
+
:class="[
|
|
334
|
+
'treatment-consultant__compat-badge',
|
|
335
|
+
`treatment-consultant__compat-badge--${getCompatibility(tr.id)}`,
|
|
336
|
+
]"
|
|
337
|
+
>
|
|
338
|
+
{{ getCompatibilityLabel(tr.id) }}
|
|
339
|
+
</span>
|
|
340
|
+
</div>
|
|
341
|
+
<div class="treatment-consultant__details-list">
|
|
342
|
+
<div
|
|
343
|
+
v-for="(note, j) in tr.notes"
|
|
344
|
+
:key="j"
|
|
345
|
+
v-motion="`treatment-note-${i}-${j}`"
|
|
346
|
+
:initial="{ opacity: 0, x: -20 }"
|
|
347
|
+
:enter="{ opacity: 1, x: 0, transition: { delay: (i + j) * 80 } }"
|
|
348
|
+
class="treatment-consultant__details-item"
|
|
349
|
+
>
|
|
350
|
+
<div class="treatment-consultant__details-bullet"></div>
|
|
351
|
+
<p class="treatment-consultant__details-text">{{ note }}</p>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
</template>
|
|
356
|
+
|
|
357
|
+
<!-- No treatments chosen -->
|
|
358
|
+
<template v-else>
|
|
359
|
+
<div class="treatment-consultant__suitability treatment-consultant__suitability--none">
|
|
360
|
+
<Icon
|
|
361
|
+
name="lucide:minus-circle"
|
|
362
|
+
class="treatment-consultant__suitability-icon treatment-consultant__suitability-icon--none"
|
|
363
|
+
/>
|
|
364
|
+
<div class="treatment-consultant__suitability-content">
|
|
365
|
+
<p class="treatment-consultant__suitability-label treatment-consultant__suitability-label--none">
|
|
366
|
+
No Treatment Selected
|
|
367
|
+
</p>
|
|
368
|
+
<p class="treatment-consultant__suitability-notes">
|
|
369
|
+
You've chosen no additional style or treatments this visit.
|
|
370
|
+
</p>
|
|
371
|
+
</div>
|
|
372
|
+
</div>
|
|
373
|
+
</template>
|
|
374
|
+
|
|
375
|
+
<!-- Selections Summary -->
|
|
376
|
+
<div class="treatment-consultant__summary">
|
|
377
|
+
<div v-for="item in summaryItems" :key="item.label" class="treatment-consultant__summary-item">
|
|
378
|
+
<p class="treatment-consultant__summary-label">{{ item.label }}</p>
|
|
379
|
+
<div class="treatment-consultant__summary-visual">
|
|
380
|
+
<div
|
|
381
|
+
v-if="item.swatch"
|
|
382
|
+
class="treatment-consultant__summary-swatch"
|
|
383
|
+
:style="{ background: item.swatch }"
|
|
384
|
+
>
|
|
385
|
+
<NuxtImg
|
|
386
|
+
v-if="item.image"
|
|
387
|
+
:src="item.image"
|
|
388
|
+
width="96"
|
|
389
|
+
height="96"
|
|
390
|
+
alt=""
|
|
391
|
+
class="treatment-consultant__summary-image"
|
|
392
|
+
:class="{ 'treatment-consultant__summary-image--dark': item.textDark }"
|
|
393
|
+
/>
|
|
394
|
+
</div>
|
|
395
|
+
<Icon v-else-if="item.icon" :name="item.icon" class="treatment-consultant__summary-none-icon" />
|
|
396
|
+
</div>
|
|
397
|
+
<p class="treatment-consultant__summary-value">{{ item.value }}</p>
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
|
|
401
|
+
<!-- CTA -->
|
|
402
|
+
<div class="treatment-consultant__cta">
|
|
403
|
+
<p class="treatment-consultant__cta-disclaimer">
|
|
404
|
+
This is a guide — every head of hair is unique. Book a consultation for tailored advice.
|
|
405
|
+
</p>
|
|
406
|
+
<div class="treatment-consultant__cta-buttons">
|
|
407
|
+
<a href="/#contact" class="treatment-consultant__button treatment-consultant__button--primary">
|
|
408
|
+
Book Consultation
|
|
409
|
+
</a>
|
|
410
|
+
<button class="treatment-consultant__button treatment-consultant__button--secondary" @click="reset">
|
|
411
|
+
Start Again
|
|
412
|
+
</button>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
</Transition>
|
|
417
|
+
|
|
418
|
+
<!-- Navigation Buttons -->
|
|
419
|
+
<div v-if="step < 4 && (step > 0 || !autoAdvance)" class="treatment-consultant__navigation">
|
|
420
|
+
<button
|
|
421
|
+
v-if="step > 0"
|
|
422
|
+
class="treatment-consultant__nav-button treatment-consultant__nav-button--back"
|
|
423
|
+
@click="back"
|
|
424
|
+
>
|
|
425
|
+
<Icon name="lucide:arrow-left" class="treatment-consultant__nav-icon" />
|
|
426
|
+
Back
|
|
427
|
+
</button>
|
|
428
|
+
<button
|
|
429
|
+
v-if="!autoAdvance || (step === 3 && allowMultipleTreatments)"
|
|
430
|
+
:disabled="!canProceed"
|
|
431
|
+
:class="[
|
|
432
|
+
'treatment-consultant__nav-button treatment-consultant__nav-button--next',
|
|
433
|
+
{ 'treatment-consultant__nav-button--disabled': !canProceed },
|
|
434
|
+
]"
|
|
435
|
+
@click="next"
|
|
436
|
+
>
|
|
437
|
+
{{ autoAdvance && step === 3 && allowMultipleTreatments ? "View Results" : "Next" }}
|
|
438
|
+
<Icon name="lucide:arrow-right" class="treatment-consultant__nav-icon" />
|
|
439
|
+
</button>
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
</div>
|
|
444
|
+
</template>
|
|
445
|
+
|
|
446
|
+
<script setup lang="ts">
|
|
447
|
+
// ─── Props ────────────────────────────────────────────────────────────────────
|
|
448
|
+
interface Props {
|
|
449
|
+
autoAdvance?: boolean;
|
|
450
|
+
allowMultipleTreatments?: boolean;
|
|
451
|
+
styleClassPassthrough?: string | string[];
|
|
452
|
+
}
|
|
453
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
454
|
+
autoAdvance: false,
|
|
455
|
+
allowMultipleTreatments: false,
|
|
456
|
+
styleClassPassthrough: () => [],
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
460
|
+
type HairType = "straight" | "wavy" | "curly" | "coily";
|
|
461
|
+
type NaturalColour = "light-blonde" | "dark-blonde" | "light-brown" | "dark-brown" | "red" | "black" | "grey-white";
|
|
462
|
+
type DesiredColour = "none" | "blonde" | "brown" | "red" | "black" | "grey-silver" | "vivid" | "balayage";
|
|
463
|
+
type TreatmentId =
|
|
464
|
+
| "none"
|
|
465
|
+
| "keratin-smoothing"
|
|
466
|
+
| "brazilian-blowout"
|
|
467
|
+
| "perm"
|
|
468
|
+
| "relaxer"
|
|
469
|
+
| "japanese-straightening"
|
|
470
|
+
| "deep-conditioning"
|
|
471
|
+
| "bond-repair"
|
|
472
|
+
| "gloss"
|
|
473
|
+
| "scalp-treatment"
|
|
474
|
+
| "blowdry";
|
|
475
|
+
type Suitability = "great" | "possible" | "difficult" | "not-recommended";
|
|
476
|
+
|
|
477
|
+
interface Recommendation {
|
|
478
|
+
suitability: Suitability;
|
|
479
|
+
method: string;
|
|
480
|
+
notes: string;
|
|
481
|
+
details: string[];
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
interface Treatment {
|
|
485
|
+
id: TreatmentId;
|
|
486
|
+
label: string;
|
|
487
|
+
icon: string;
|
|
488
|
+
description?: string;
|
|
489
|
+
notes: string[];
|
|
490
|
+
compatibility?: boolean;
|
|
491
|
+
excludes?: TreatmentId[];
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// ─── Static Data ──────────────────────────────────────────────────────────────
|
|
495
|
+
const hairTypes: { id: HairType; label: string; pattern: string }[] = [
|
|
496
|
+
{ id: "straight", label: "Straight", pattern: "|||" },
|
|
497
|
+
{ id: "wavy", label: "Wavy", pattern: "∿∿∿" },
|
|
498
|
+
{ id: "curly", label: "Curly", pattern: "⌇⌇⌇" },
|
|
499
|
+
{ id: "coily", label: "Coily", pattern: "⌀⌀⌀" },
|
|
500
|
+
];
|
|
501
|
+
|
|
502
|
+
const naturalColours: { id: NaturalColour; label: string; colour: string; image: string; textDark?: boolean }[] = [
|
|
503
|
+
{
|
|
504
|
+
id: "light-blonde",
|
|
505
|
+
label: "Light Blonde",
|
|
506
|
+
colour: "#F5DEB3",
|
|
507
|
+
image: "/images/treatment-consultant/swatch-light-blonde.jpeg",
|
|
508
|
+
textDark: true,
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
id: "dark-blonde",
|
|
512
|
+
label: "Dark Blonde",
|
|
513
|
+
colour: "#C8A951",
|
|
514
|
+
image: "/images/treatment-consultant/swatch-dark-blonde.jpeg",
|
|
515
|
+
textDark: true,
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
id: "light-brown",
|
|
519
|
+
label: "Light Brown",
|
|
520
|
+
colour: "#8B6914",
|
|
521
|
+
image: "/images/treatment-consultant/swatch-light-brown.jpeg",
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
id: "dark-brown",
|
|
525
|
+
label: "Dark Brown",
|
|
526
|
+
colour: "#4A2912",
|
|
527
|
+
image: "/images/treatment-consultant/swatch-dark-brown.jpeg",
|
|
528
|
+
},
|
|
529
|
+
{ id: "red", label: "Natural Red", colour: "#A0522D", image: "/images/treatment-consultant/swatch-red.jpeg" },
|
|
530
|
+
{ id: "black", label: "Black", colour: "#1a1a1a", image: "/images/treatment-consultant/swatch-black.jpeg" },
|
|
531
|
+
{
|
|
532
|
+
id: "grey-white",
|
|
533
|
+
label: "Grey / White",
|
|
534
|
+
colour: "#C0C0C0",
|
|
535
|
+
image: "/images/treatment-consultant/swatch-grey-white.jpeg",
|
|
536
|
+
textDark: true,
|
|
537
|
+
},
|
|
538
|
+
];
|
|
539
|
+
|
|
540
|
+
// 'none' first as requested
|
|
541
|
+
const desiredColours: { id: DesiredColour; label: string; colour?: string; image?: string; textDark?: boolean }[] = [
|
|
542
|
+
{ id: "none", label: "I don't want a colour change" },
|
|
543
|
+
{
|
|
544
|
+
id: "blonde",
|
|
545
|
+
label: "Blonde",
|
|
546
|
+
colour: "#F5DEB3",
|
|
547
|
+
image: "/images/treatment-consultant/swatch-dream-blonde.jpeg",
|
|
548
|
+
textDark: true,
|
|
549
|
+
},
|
|
550
|
+
{ id: "brown", label: "Brown", colour: "#6B3A2A", image: "/images/treatment-consultant/swatch-dream-brown.jpeg" },
|
|
551
|
+
{ id: "red", label: "Red", colour: "#B22222", image: "/images/treatment-consultant/swatch-dream-red.jpeg" },
|
|
552
|
+
{ id: "black", label: "Black", colour: "#1a1a1a", image: "/images/treatment-consultant/swatch-dream-black.jpeg" },
|
|
553
|
+
{
|
|
554
|
+
id: "grey-silver",
|
|
555
|
+
label: "Grey / Silver",
|
|
556
|
+
colour: "linear-gradient(135deg, #E8E8E8, #9E9E9E, #616161)",
|
|
557
|
+
image: "/images/treatment-consultant/swatch-dream-grey-silver.jpeg",
|
|
558
|
+
textDark: true,
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
id: "vivid",
|
|
562
|
+
label: "Vivid / Fashion",
|
|
563
|
+
colour: "linear-gradient(135deg, #FF69B4, #8A2BE2, #00CED1)",
|
|
564
|
+
image: "/images/treatment-consultant/swatch-dream-vivid.jpeg",
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: "balayage",
|
|
568
|
+
label: "Balayage",
|
|
569
|
+
colour: "linear-gradient(135deg, #8B6914, #F5DEB3)",
|
|
570
|
+
image: "/images/treatment-consultant/swatch-dream-balayage.jpeg",
|
|
571
|
+
},
|
|
572
|
+
];
|
|
573
|
+
|
|
574
|
+
const treatments: Treatment[] = [
|
|
575
|
+
{
|
|
576
|
+
id: "none",
|
|
577
|
+
label: "I don't want any treatments",
|
|
578
|
+
icon: "lucide:minus-circle",
|
|
579
|
+
description: "Go straight to your results",
|
|
580
|
+
notes: [],
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
id: "keratin-smoothing",
|
|
584
|
+
label: "Keratin Smoothing",
|
|
585
|
+
icon: "lucide:wind",
|
|
586
|
+
description: "Frizz-free smoothness for months",
|
|
587
|
+
notes: [
|
|
588
|
+
"Reduces frizz and adds mirror-like shine",
|
|
589
|
+
"Results last 3–6 months depending on hair type",
|
|
590
|
+
"Not recommended immediately after colour — wait 2 weeks",
|
|
591
|
+
],
|
|
592
|
+
compatibility: true,
|
|
593
|
+
excludes: ["perm", "japanese-straightening", "relaxer"],
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
id: "brazilian-blowout",
|
|
597
|
+
label: "Brazilian Blowout",
|
|
598
|
+
icon: "lucide:zap",
|
|
599
|
+
description: "Smoothing with colour-safe formula",
|
|
600
|
+
notes: [
|
|
601
|
+
"Can be done same-day as colour in most cases",
|
|
602
|
+
"Softens and smooths without fully straightening",
|
|
603
|
+
"Great for frizz control in humid climates",
|
|
604
|
+
],
|
|
605
|
+
compatibility: true,
|
|
606
|
+
excludes: ["perm", "japanese-straightening", "relaxer"],
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
id: "perm",
|
|
610
|
+
label: "Permanent Wave",
|
|
611
|
+
icon: "lucide:waves",
|
|
612
|
+
description: "Long-lasting curls or waves",
|
|
613
|
+
notes: [
|
|
614
|
+
"Creates curls or waves that last 3–6 months",
|
|
615
|
+
"Should not be done on the same day as colour",
|
|
616
|
+
"Particularly beautiful on straight or slightly wavy hair",
|
|
617
|
+
],
|
|
618
|
+
compatibility: true,
|
|
619
|
+
excludes: ["japanese-straightening", "relaxer", "keratin-smoothing", "brazilian-blowout"],
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
id: "relaxer",
|
|
623
|
+
label: "Relaxer",
|
|
624
|
+
icon: "lucide:arrow-right",
|
|
625
|
+
description: "Permanent chemical straightening",
|
|
626
|
+
notes: [
|
|
627
|
+
"Permanently relaxes curly or coily texture",
|
|
628
|
+
"Should not be combined with colour on the same visit",
|
|
629
|
+
"Requires regular maintenance every 6–8 weeks",
|
|
630
|
+
],
|
|
631
|
+
compatibility: true,
|
|
632
|
+
excludes: ["perm", "japanese-straightening", "keratin-smoothing", "brazilian-blowout"],
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
id: "japanese-straightening",
|
|
636
|
+
label: "Japanese Straightening",
|
|
637
|
+
icon: "lucide:minus",
|
|
638
|
+
description: "Permanently silky-straight results",
|
|
639
|
+
notes: [
|
|
640
|
+
"Most permanent straightening method available",
|
|
641
|
+
"Not compatible with colour on the same day",
|
|
642
|
+
"Results last until new growth comes through",
|
|
643
|
+
],
|
|
644
|
+
compatibility: true,
|
|
645
|
+
excludes: ["perm", "relaxer", "keratin-smoothing", "brazilian-blowout"],
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
id: "deep-conditioning",
|
|
649
|
+
label: "Deep Conditioning",
|
|
650
|
+
icon: "lucide:droplets",
|
|
651
|
+
description: "Intense hydration & moisture",
|
|
652
|
+
notes: [
|
|
653
|
+
"Ideal add-on for colour-treated or dry hair",
|
|
654
|
+
"Restores moisture, softness, and shine",
|
|
655
|
+
"Suitable for all hair types and textures",
|
|
656
|
+
],
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
id: "bond-repair",
|
|
660
|
+
label: "Protein / Bond Repair",
|
|
661
|
+
icon: "lucide:shield",
|
|
662
|
+
description: "e.g. Olaplex — rebuilds damaged hair",
|
|
663
|
+
notes: [
|
|
664
|
+
"Repairs broken bonds caused by colour or heat",
|
|
665
|
+
"Can be done alongside colour as an add-on",
|
|
666
|
+
"Recommended for frequently processed or damaged hair",
|
|
667
|
+
],
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
id: "gloss",
|
|
671
|
+
label: "Gloss / Glossing",
|
|
672
|
+
icon: "lucide:gem",
|
|
673
|
+
description: "Adds shine and enhances colour",
|
|
674
|
+
notes: [
|
|
675
|
+
"Boosts vibrancy and adds a glassy finish",
|
|
676
|
+
"Excellent follow-up to colour treatments",
|
|
677
|
+
"Semi-permanent — fades naturally over 4–6 weeks",
|
|
678
|
+
],
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
id: "scalp-treatment",
|
|
682
|
+
label: "Scalp Treatment",
|
|
683
|
+
icon: "lucide:brain",
|
|
684
|
+
description: "Head spa — scalp health & growth",
|
|
685
|
+
notes: [
|
|
686
|
+
"Detoxifies and balances the scalp",
|
|
687
|
+
"Promotes healthier hair growth over time",
|
|
688
|
+
"A relaxing, spa-like experience — highly recommended",
|
|
689
|
+
],
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
id: "blowdry",
|
|
693
|
+
label: "Blow Dry / Blowout",
|
|
694
|
+
icon: "lucide:sparkles",
|
|
695
|
+
description: "Professional finish and styling",
|
|
696
|
+
notes: [
|
|
697
|
+
"Includes tension blowdry for a smooth, voluminous finish",
|
|
698
|
+
"Can be customised — sleek, bouncy, or textured",
|
|
699
|
+
"The perfect way to finish any salon visit",
|
|
700
|
+
],
|
|
701
|
+
},
|
|
702
|
+
];
|
|
703
|
+
|
|
704
|
+
const STEPS = ["Hair Type", "Your Colour", "Dream Colour", "Style & Treatments", "Results"];
|
|
705
|
+
|
|
706
|
+
// ─── Recommendation Matrix ────────────────────────────────────────────────────
|
|
707
|
+
function getColourRecommendation(natural: NaturalColour, desired: DesiredColour, hairType: HairType): Recommendation {
|
|
708
|
+
const matrix: Record<NaturalColour, Partial<Record<DesiredColour, Recommendation>>> = {
|
|
709
|
+
"light-blonde": {
|
|
710
|
+
blonde: {
|
|
711
|
+
suitability: "great",
|
|
712
|
+
method: "Semi-Permanent",
|
|
713
|
+
notes: "Your light base is perfect for any blonde shade.",
|
|
714
|
+
details: [
|
|
715
|
+
"Ash, warm, or platinum tones all work beautifully",
|
|
716
|
+
"Semi-permanent colour recommended to maintain condition",
|
|
717
|
+
"Low maintenance — your natural base does the heavy lifting",
|
|
718
|
+
],
|
|
719
|
+
},
|
|
720
|
+
brown: {
|
|
721
|
+
suitability: "great",
|
|
722
|
+
method: "Semi-Permanent",
|
|
723
|
+
notes: "Light to medium browns will take beautifully.",
|
|
724
|
+
details: [
|
|
725
|
+
"Great for adding depth and richness",
|
|
726
|
+
"Semi-permanent gives a natural fade",
|
|
727
|
+
"Warm chocolate and caramel tones look stunning",
|
|
728
|
+
],
|
|
729
|
+
},
|
|
730
|
+
red: {
|
|
731
|
+
suitability: "possible",
|
|
732
|
+
method: "Semi-Permanent",
|
|
733
|
+
notes: "Strawberry and copper tones work, but fade quickly on light hair.",
|
|
734
|
+
details: [
|
|
735
|
+
"Strawberry blonde is the most natural-looking option",
|
|
736
|
+
"Copper tones are achievable but fade fast",
|
|
737
|
+
"Regular top-ups needed to maintain vibrancy",
|
|
738
|
+
],
|
|
739
|
+
},
|
|
740
|
+
black: {
|
|
741
|
+
suitability: "not-recommended",
|
|
742
|
+
method: "N/A",
|
|
743
|
+
notes: "Too harsh a contrast — can look unnatural and is very hard to reverse.",
|
|
744
|
+
details: [
|
|
745
|
+
"Extreme colour change can damage light hair",
|
|
746
|
+
"Very difficult to go back to blonde afterwards",
|
|
747
|
+
"Consider a dark brown instead for depth",
|
|
748
|
+
],
|
|
749
|
+
},
|
|
750
|
+
"grey-silver": {
|
|
751
|
+
suitability: "great",
|
|
752
|
+
method: "Toner / Semi-Permanent",
|
|
753
|
+
notes: "Your light base is ideal for silver and grey toning.",
|
|
754
|
+
details: [
|
|
755
|
+
"Ash or silver toners work beautifully on blonde hair",
|
|
756
|
+
"No bleaching needed — a huge advantage",
|
|
757
|
+
"A trendy, low-maintenance result",
|
|
758
|
+
],
|
|
759
|
+
},
|
|
760
|
+
vivid: {
|
|
761
|
+
suitability: "possible",
|
|
762
|
+
method: "Semi-Permanent",
|
|
763
|
+
notes: "Pastel vivid shades work well on your light base, but fade fast.",
|
|
764
|
+
details: [
|
|
765
|
+
"Pastels like lilac, rose, and mint are ideal",
|
|
766
|
+
"No bleaching needed — a rare advantage",
|
|
767
|
+
"Colours fade within 4–8 washes typically",
|
|
768
|
+
],
|
|
769
|
+
},
|
|
770
|
+
balayage: {
|
|
771
|
+
suitability: "great",
|
|
772
|
+
method: "Freehand",
|
|
773
|
+
notes: "Beautiful sun-kissed dimension with minimal effort.",
|
|
774
|
+
details: [
|
|
775
|
+
"Platinum or warm honey tones work perfectly",
|
|
776
|
+
"Natural-looking grow-out",
|
|
777
|
+
"Low maintenance colour option",
|
|
778
|
+
],
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
"dark-blonde": {
|
|
782
|
+
blonde: {
|
|
783
|
+
suitability: "great",
|
|
784
|
+
method: "Semi or Permanent",
|
|
785
|
+
notes: "Golden and honey shades are your perfect match.",
|
|
786
|
+
details: [
|
|
787
|
+
"Warm golden tones complement your base beautifully",
|
|
788
|
+
"Honey blonde gives a natural, sunkissed finish",
|
|
789
|
+
"Can be achieved with gentle lightening",
|
|
790
|
+
],
|
|
791
|
+
},
|
|
792
|
+
brown: {
|
|
793
|
+
suitability: "great",
|
|
794
|
+
method: "Semi or Permanent",
|
|
795
|
+
notes: "All brown shades work wonderfully on your base.",
|
|
796
|
+
details: [
|
|
797
|
+
"Versatile base for any brown shade",
|
|
798
|
+
"Rich chocolate and chestnut tones are gorgeous",
|
|
799
|
+
"Natural-looking results every time",
|
|
800
|
+
],
|
|
801
|
+
},
|
|
802
|
+
red: {
|
|
803
|
+
suitability: "great",
|
|
804
|
+
method: "Semi or Permanent",
|
|
805
|
+
notes: "Strawberry and copper tones look stunning.",
|
|
806
|
+
details: [
|
|
807
|
+
"Warm copper and strawberry blonde are ideal",
|
|
808
|
+
"Rich auburn is easily achievable",
|
|
809
|
+
"Beautiful warm results on your base",
|
|
810
|
+
],
|
|
811
|
+
},
|
|
812
|
+
black: {
|
|
813
|
+
suitability: "possible",
|
|
814
|
+
method: "Permanent",
|
|
815
|
+
notes: "Blue-black can look harsh. Consider a deep espresso instead.",
|
|
816
|
+
details: [
|
|
817
|
+
"Jet black may look too flat",
|
|
818
|
+
"Deep chocolate or espresso is more flattering",
|
|
819
|
+
"Permanent colour needed for lasting results",
|
|
820
|
+
],
|
|
821
|
+
},
|
|
822
|
+
"grey-silver": {
|
|
823
|
+
suitability: "possible",
|
|
824
|
+
method: "Bleach + Toner",
|
|
825
|
+
notes: "Achievable but needs careful lightening first.",
|
|
826
|
+
details: [
|
|
827
|
+
"Pre-lightening required to lift warmth",
|
|
828
|
+
"Toner applied to achieve silver or ash result",
|
|
829
|
+
"May need 2 sessions for even coverage",
|
|
830
|
+
],
|
|
831
|
+
},
|
|
832
|
+
vivid: {
|
|
833
|
+
suitability: "great",
|
|
834
|
+
method: "Semi-Permanent",
|
|
835
|
+
notes: "Pink, teal, and other vivid shades work brilliantly.",
|
|
836
|
+
details: [
|
|
837
|
+
"May need slight lightening for true vibrancy",
|
|
838
|
+
"Pink and teal are particularly stunning",
|
|
839
|
+
"Great base for fashion colours",
|
|
840
|
+
],
|
|
841
|
+
},
|
|
842
|
+
balayage: {
|
|
843
|
+
suitability: "great",
|
|
844
|
+
method: "Freehand",
|
|
845
|
+
notes: "The ideal base for beautiful balayage dimension.",
|
|
846
|
+
details: [
|
|
847
|
+
"Honey and caramel tones create gorgeous contrast",
|
|
848
|
+
"Natural-looking grow-out and low maintenance",
|
|
849
|
+
"Works beautifully with warm or cool tones",
|
|
850
|
+
],
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
"light-brown": {
|
|
854
|
+
blonde: {
|
|
855
|
+
suitability: "possible",
|
|
856
|
+
method: "Permanent + Lightening",
|
|
857
|
+
notes: "Needs careful lightening. Risk of brassiness without a toner.",
|
|
858
|
+
details: [
|
|
859
|
+
"Professional lightening recommended",
|
|
860
|
+
"Toner essential to counteract brassiness",
|
|
861
|
+
"Multiple sessions may be needed for platinum",
|
|
862
|
+
],
|
|
863
|
+
},
|
|
864
|
+
brown: {
|
|
865
|
+
suitability: "great",
|
|
866
|
+
method: "Semi or Permanent",
|
|
867
|
+
notes: "All brown shades are your sweet spot.",
|
|
868
|
+
details: [
|
|
869
|
+
"Enhance your natural colour with deeper tones",
|
|
870
|
+
"Rich mahogany and chestnut are stunning",
|
|
871
|
+
"Easy to maintain and refresh",
|
|
872
|
+
],
|
|
873
|
+
},
|
|
874
|
+
red: {
|
|
875
|
+
suitability: "great",
|
|
876
|
+
method: "Semi or Permanent",
|
|
877
|
+
notes: "Auburn and mahogany shades look incredible.",
|
|
878
|
+
details: [
|
|
879
|
+
"Your base is ideal for rich red tones",
|
|
880
|
+
"Auburn and copper create beautiful warmth",
|
|
881
|
+
"Mahogany adds luxury and depth",
|
|
882
|
+
],
|
|
883
|
+
},
|
|
884
|
+
black: {
|
|
885
|
+
suitability: "possible",
|
|
886
|
+
method: "Permanent",
|
|
887
|
+
notes: "Can result in flat tones. Consider depth-adding techniques.",
|
|
888
|
+
details: [
|
|
889
|
+
"Risk of looking too uniform and flat",
|
|
890
|
+
"Consider adding dimension with lowlights",
|
|
891
|
+
"Very dark brown may be more flattering",
|
|
892
|
+
],
|
|
893
|
+
},
|
|
894
|
+
"grey-silver": {
|
|
895
|
+
suitability: "difficult",
|
|
896
|
+
method: "Bleach + Toner",
|
|
897
|
+
notes: "Requires significant lightening — best done in stages.",
|
|
898
|
+
details: [
|
|
899
|
+
"Multiple bleaching sessions likely needed",
|
|
900
|
+
"High risk of brassiness without careful toning",
|
|
901
|
+
"Consider silver highlights as a gentler alternative",
|
|
902
|
+
],
|
|
903
|
+
},
|
|
904
|
+
vivid: {
|
|
905
|
+
suitability: "great",
|
|
906
|
+
method: "Requires Lightening",
|
|
907
|
+
notes: "Teal and purple work well but need pre-lightening.",
|
|
908
|
+
details: [
|
|
909
|
+
"Pre-lightening needed for true vibrancy",
|
|
910
|
+
"Teal and purple are particularly beautiful",
|
|
911
|
+
"Semi-permanent for easy experimentation",
|
|
912
|
+
],
|
|
913
|
+
},
|
|
914
|
+
balayage: {
|
|
915
|
+
suitability: "great",
|
|
916
|
+
method: "Freehand",
|
|
917
|
+
notes: "Perfect base for dimensional balayage.",
|
|
918
|
+
details: [
|
|
919
|
+
"Caramel and honey ends create gorgeous contrast",
|
|
920
|
+
"Natural root area means low maintenance",
|
|
921
|
+
"Sun-kissed finish looks effortlessly beautiful",
|
|
922
|
+
],
|
|
923
|
+
},
|
|
924
|
+
},
|
|
925
|
+
"dark-brown": {
|
|
926
|
+
blonde: {
|
|
927
|
+
suitability: "not-recommended",
|
|
928
|
+
method: "Bleach Required",
|
|
929
|
+
notes: "Requires heavy bleaching which can damage hair significantly.",
|
|
930
|
+
details: [
|
|
931
|
+
"Multiple bleaching sessions needed",
|
|
932
|
+
"High risk of damage and breakage",
|
|
933
|
+
"Consider highlights instead for blonde effect",
|
|
934
|
+
],
|
|
935
|
+
},
|
|
936
|
+
brown: {
|
|
937
|
+
suitability: "great",
|
|
938
|
+
method: "Semi or Permanent",
|
|
939
|
+
notes: "Enhance your natural shade — all but ash tones work.",
|
|
940
|
+
details: [
|
|
941
|
+
"Add warmth with chestnut or chocolate",
|
|
942
|
+
"Golden brown adds beautiful dimension",
|
|
943
|
+
"Easy to enrich and deepen your colour",
|
|
944
|
+
],
|
|
945
|
+
},
|
|
946
|
+
red: {
|
|
947
|
+
suitability: "great",
|
|
948
|
+
method: "Permanent",
|
|
949
|
+
notes: "Mahogany and red-violet are stunning on your dark base.",
|
|
950
|
+
details: [
|
|
951
|
+
"Mahogany and burgundy are effortlessly achievable",
|
|
952
|
+
"Red-violet adds luxurious dimension",
|
|
953
|
+
"Rich, head-turning colour with minimal lift",
|
|
954
|
+
],
|
|
955
|
+
},
|
|
956
|
+
black: {
|
|
957
|
+
suitability: "great",
|
|
958
|
+
method: "Semi-Permanent",
|
|
959
|
+
notes: "Enhancing black gloss works beautifully.",
|
|
960
|
+
details: [
|
|
961
|
+
"Blue-black gloss adds gorgeous shine",
|
|
962
|
+
"Minimal processing needed",
|
|
963
|
+
"Semi-permanent for easy maintenance",
|
|
964
|
+
],
|
|
965
|
+
},
|
|
966
|
+
"grey-silver": {
|
|
967
|
+
suitability: "not-recommended",
|
|
968
|
+
method: "Heavy Bleach Required",
|
|
969
|
+
notes: "Very challenging — extensive lifting required over multiple sessions.",
|
|
970
|
+
details: [
|
|
971
|
+
"Dark brown to silver is a multi-session journey",
|
|
972
|
+
"High risk of damage without professional guidance",
|
|
973
|
+
"Consider silver highlights or a gradual grow-out approach instead",
|
|
974
|
+
],
|
|
975
|
+
},
|
|
976
|
+
vivid: {
|
|
977
|
+
suitability: "difficult",
|
|
978
|
+
method: "Bleach Required",
|
|
979
|
+
notes: "Vivid colours need significant lightening first.",
|
|
980
|
+
details: [
|
|
981
|
+
"Heavy bleaching required — multiple sessions",
|
|
982
|
+
"High maintenance with frequent touch-ups",
|
|
983
|
+
"Consider peek-a-boo panels for less damage",
|
|
984
|
+
],
|
|
985
|
+
},
|
|
986
|
+
balayage: {
|
|
987
|
+
suitability: "great",
|
|
988
|
+
method: "Freehand + Lightening",
|
|
989
|
+
notes: "Gorgeous contrast between dark root and lighter ends.",
|
|
990
|
+
details: [
|
|
991
|
+
"Caramel and honey balayage is incredibly popular",
|
|
992
|
+
"Natural grow-out means lower maintenance",
|
|
993
|
+
"Can be subtle or dramatic — your choice",
|
|
994
|
+
],
|
|
995
|
+
},
|
|
996
|
+
},
|
|
997
|
+
red: {
|
|
998
|
+
blonde: {
|
|
999
|
+
suitability: "difficult",
|
|
1000
|
+
method: "Bleach Required",
|
|
1001
|
+
notes: "Risk of clash and unwanted orange tones. Very challenging.",
|
|
1002
|
+
details: [
|
|
1003
|
+
"Red pigment is extremely stubborn to remove",
|
|
1004
|
+
"High risk of orange and brassy tones",
|
|
1005
|
+
"Multiple sessions with colour correction needed",
|
|
1006
|
+
],
|
|
1007
|
+
},
|
|
1008
|
+
brown: {
|
|
1009
|
+
suitability: "great",
|
|
1010
|
+
method: "Semi or Permanent",
|
|
1011
|
+
notes: "Golden and chestnut browns complement red undertones.",
|
|
1012
|
+
details: [
|
|
1013
|
+
"Warm browns work harmoniously with red base",
|
|
1014
|
+
"Chestnut and golden browns are gorgeous",
|
|
1015
|
+
"Natural-looking transition from red",
|
|
1016
|
+
],
|
|
1017
|
+
},
|
|
1018
|
+
red: {
|
|
1019
|
+
suitability: "great",
|
|
1020
|
+
method: "Semi or Permanent",
|
|
1021
|
+
notes: "Deepen or brighten your natural red — stunning results.",
|
|
1022
|
+
details: [
|
|
1023
|
+
"Enhance your natural colour beautifully",
|
|
1024
|
+
"Brighten to vivid copper or deepen to auburn",
|
|
1025
|
+
"The easiest and most rewarding option",
|
|
1026
|
+
],
|
|
1027
|
+
},
|
|
1028
|
+
black: {
|
|
1029
|
+
suitability: "not-recommended",
|
|
1030
|
+
method: "Permanent",
|
|
1031
|
+
notes: "Can dull your beautiful natural vibrancy.",
|
|
1032
|
+
details: [
|
|
1033
|
+
"Black will mute your natural warmth",
|
|
1034
|
+
"Very difficult to return to red afterwards",
|
|
1035
|
+
"Consider deep burgundy as an alternative",
|
|
1036
|
+
],
|
|
1037
|
+
},
|
|
1038
|
+
"grey-silver": {
|
|
1039
|
+
suitability: "difficult",
|
|
1040
|
+
method: "Colour Correction + Bleach",
|
|
1041
|
+
notes: "Red pigment makes silver very hard to achieve.",
|
|
1042
|
+
details: [
|
|
1043
|
+
"Red is one of the hardest pigments to remove",
|
|
1044
|
+
"Colour correction required before any lightening",
|
|
1045
|
+
"Expect multiple sessions and a patient journey",
|
|
1046
|
+
],
|
|
1047
|
+
},
|
|
1048
|
+
vivid: {
|
|
1049
|
+
suitability: "possible",
|
|
1050
|
+
method: "Semi-Permanent",
|
|
1051
|
+
notes: "Some vivids may look muddy. Choose carefully.",
|
|
1052
|
+
details: [
|
|
1053
|
+
"Vivid red and orange work with your base",
|
|
1054
|
+
"Blue and green tones may go muddy",
|
|
1055
|
+
"Pink can look beautiful on lighter red hair",
|
|
1056
|
+
],
|
|
1057
|
+
},
|
|
1058
|
+
balayage: {
|
|
1059
|
+
suitability: "great",
|
|
1060
|
+
method: "Freehand",
|
|
1061
|
+
notes: "Copper and rose-gold balayage on red hair is breathtaking.",
|
|
1062
|
+
details: [
|
|
1063
|
+
"Rose gold tips on red base are stunning",
|
|
1064
|
+
"Copper highlights add gorgeous dimension",
|
|
1065
|
+
"Low maintenance with natural-looking grow-out",
|
|
1066
|
+
],
|
|
1067
|
+
},
|
|
1068
|
+
},
|
|
1069
|
+
black: {
|
|
1070
|
+
blonde: {
|
|
1071
|
+
suitability: "not-recommended",
|
|
1072
|
+
method: "Heavy Bleach Required",
|
|
1073
|
+
notes: "Requires extensive bleaching — high damage risk.",
|
|
1074
|
+
details: [
|
|
1075
|
+
"Multiple bleaching sessions over months",
|
|
1076
|
+
"Severe damage risk to hair integrity",
|
|
1077
|
+
"Consider face-framing highlights instead",
|
|
1078
|
+
],
|
|
1079
|
+
},
|
|
1080
|
+
brown: {
|
|
1081
|
+
suitability: "possible",
|
|
1082
|
+
method: "Permanent + Lightening",
|
|
1083
|
+
notes: "Needs warm undertones. Can look flat without dimension.",
|
|
1084
|
+
details: [
|
|
1085
|
+
"Warm-toned browns work better than cool",
|
|
1086
|
+
"May need multiple sessions for even coverage",
|
|
1087
|
+
"Adding highlights creates better dimension",
|
|
1088
|
+
],
|
|
1089
|
+
},
|
|
1090
|
+
red: {
|
|
1091
|
+
suitability: "possible",
|
|
1092
|
+
method: "Permanent",
|
|
1093
|
+
notes: "Red can pull burgundy on black hair. Rich results though.",
|
|
1094
|
+
details: [
|
|
1095
|
+
"Expect burgundy/wine rather than true red",
|
|
1096
|
+
"Very rich and luxurious results",
|
|
1097
|
+
"Works best as all-over colour or highlights",
|
|
1098
|
+
],
|
|
1099
|
+
},
|
|
1100
|
+
black: {
|
|
1101
|
+
suitability: "great",
|
|
1102
|
+
method: "Gloss Treatment",
|
|
1103
|
+
notes: "Glosses add incredible shine and depth to black hair.",
|
|
1104
|
+
details: [
|
|
1105
|
+
"Blue-black or violet-black glosses are stunning",
|
|
1106
|
+
"Adds mirror-like shine",
|
|
1107
|
+
"Gentle treatment with no damage",
|
|
1108
|
+
],
|
|
1109
|
+
},
|
|
1110
|
+
"grey-silver": {
|
|
1111
|
+
suitability: "not-recommended",
|
|
1112
|
+
method: "Heavy Bleach Required",
|
|
1113
|
+
notes: "Achieving silver from black is a long, high-risk journey.",
|
|
1114
|
+
details: [
|
|
1115
|
+
"Many bleaching sessions required over months",
|
|
1116
|
+
"Severe risk of damage and breakage",
|
|
1117
|
+
"A gradual grow-out or silver highlights are far safer alternatives",
|
|
1118
|
+
],
|
|
1119
|
+
},
|
|
1120
|
+
vivid: {
|
|
1121
|
+
suitability: "not-recommended",
|
|
1122
|
+
method: "Heavy Bleach Required",
|
|
1123
|
+
notes: "Needs heavy lifting for any vivid colour. Very damaging.",
|
|
1124
|
+
details: [
|
|
1125
|
+
"Extensive bleaching required",
|
|
1126
|
+
"Consider peek-a-boo panels or underlights",
|
|
1127
|
+
"Temporary colour sprays for events instead",
|
|
1128
|
+
],
|
|
1129
|
+
},
|
|
1130
|
+
balayage: {
|
|
1131
|
+
suitability: "possible",
|
|
1132
|
+
method: "Lightening + Freehand",
|
|
1133
|
+
notes: "Subtle caramel balayage on black hair is gorgeous when done right.",
|
|
1134
|
+
details: [
|
|
1135
|
+
"Caramel and toffee tones create beautiful contrast",
|
|
1136
|
+
"Requires careful lightening",
|
|
1137
|
+
"Low-maintenance once established",
|
|
1138
|
+
],
|
|
1139
|
+
},
|
|
1140
|
+
},
|
|
1141
|
+
"grey-white": {
|
|
1142
|
+
blonde: {
|
|
1143
|
+
suitability: "great",
|
|
1144
|
+
method: "Semi-Permanent",
|
|
1145
|
+
notes: "All blonde shades work beautifully — your base is ideal.",
|
|
1146
|
+
details: [
|
|
1147
|
+
"Champagne and platinum look incredibly natural",
|
|
1148
|
+
"Porous hair absorbs colour easily",
|
|
1149
|
+
"Semi-permanent for gentle, buildable colour",
|
|
1150
|
+
],
|
|
1151
|
+
},
|
|
1152
|
+
brown: {
|
|
1153
|
+
suitability: "great",
|
|
1154
|
+
method: "Semi-Permanent",
|
|
1155
|
+
notes: "Soft browns add warmth and youthfulness.",
|
|
1156
|
+
details: [
|
|
1157
|
+
"Soft brown gives a natural, youthful look",
|
|
1158
|
+
"Porous grey absorbs colour beautifully",
|
|
1159
|
+
"Demi-permanent for gradual coverage",
|
|
1160
|
+
],
|
|
1161
|
+
},
|
|
1162
|
+
red: {
|
|
1163
|
+
suitability: "great",
|
|
1164
|
+
method: "Semi-Permanent",
|
|
1165
|
+
notes: "Rose gold and peach tones are absolutely stunning on grey.",
|
|
1166
|
+
details: [
|
|
1167
|
+
"Rose gold is on-trend and gorgeous",
|
|
1168
|
+
"Peach and copper tones add warmth",
|
|
1169
|
+
"Fashionable and youthful finish",
|
|
1170
|
+
],
|
|
1171
|
+
},
|
|
1172
|
+
black: {
|
|
1173
|
+
suitability: "great",
|
|
1174
|
+
method: "Semi-Permanent",
|
|
1175
|
+
notes: "Adds depth and can look very striking.",
|
|
1176
|
+
details: [
|
|
1177
|
+
"Salt-and-pepper look is very distinguished",
|
|
1178
|
+
"Semi-permanent for gradual blending",
|
|
1179
|
+
"Adds depth while keeping natural movement",
|
|
1180
|
+
],
|
|
1181
|
+
},
|
|
1182
|
+
"grey-silver": {
|
|
1183
|
+
suitability: "great",
|
|
1184
|
+
method: "Toner / Silver Gloss",
|
|
1185
|
+
notes: "You're already there — a silver gloss will make it sing.",
|
|
1186
|
+
details: [
|
|
1187
|
+
"A purple or silver toner neutralises any yellow tones",
|
|
1188
|
+
"Adds incredible brightness and shine",
|
|
1189
|
+
"Low maintenance and beautifully on-trend",
|
|
1190
|
+
],
|
|
1191
|
+
},
|
|
1192
|
+
vivid: {
|
|
1193
|
+
suitability: "great",
|
|
1194
|
+
method: "Semi-Permanent",
|
|
1195
|
+
notes: "High vibrancy — grey is the perfect canvas for vivid colours!",
|
|
1196
|
+
details: [
|
|
1197
|
+
"Grey/white is the ultimate canvas for vivid colours",
|
|
1198
|
+
"No bleaching needed whatsoever",
|
|
1199
|
+
"Colours appear vibrant and true to tone",
|
|
1200
|
+
],
|
|
1201
|
+
},
|
|
1202
|
+
balayage: {
|
|
1203
|
+
suitability: "great",
|
|
1204
|
+
method: "Semi-Permanent",
|
|
1205
|
+
notes: "Silver-to-colour gradients look absolutely breathtaking.",
|
|
1206
|
+
details: [
|
|
1207
|
+
"Reverse balayage with colour at ends is trending",
|
|
1208
|
+
"Silver root with coloured tips is stunning",
|
|
1209
|
+
"Low maintenance and incredibly fashionable",
|
|
1210
|
+
],
|
|
1211
|
+
},
|
|
1212
|
+
},
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
const rec = matrix[natural]?.[desired];
|
|
1216
|
+
if (!rec) {
|
|
1217
|
+
return {
|
|
1218
|
+
suitability: "possible",
|
|
1219
|
+
method: "Consultation Needed",
|
|
1220
|
+
notes: "Book a consultation for personalised advice.",
|
|
1221
|
+
details: [],
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
const typeNote =
|
|
1226
|
+
hairType === "curly" || hairType === "coily"
|
|
1227
|
+
? "Textured hair may need extra conditioning treatment during the colour process."
|
|
1228
|
+
: "";
|
|
1229
|
+
|
|
1230
|
+
return { ...rec, details: typeNote ? [...rec.details, typeNote] : rec.details };
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
// ─── Treatment / Colour Compatibility ────────────────────────────────────────
|
|
1234
|
+
const clashingTreatments: TreatmentId[] = ["keratin-smoothing", "perm", "relaxer", "japanese-straightening"];
|
|
1235
|
+
|
|
1236
|
+
function getCompatibility(treatmentId: TreatmentId): "ok" | "warning" {
|
|
1237
|
+
return clashingTreatments.includes(treatmentId) ? "warning" : "ok";
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
function getCompatibilityLabel(treatmentId: TreatmentId): string {
|
|
1241
|
+
return getCompatibility(treatmentId) === "warning" ? "Not same-day as colour" : "Compatible with colour";
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// ─── State ────────────────────────────────────────────────────────────────────
|
|
1245
|
+
const step = ref(0);
|
|
1246
|
+
const hairType = ref<HairType | null>(null);
|
|
1247
|
+
const naturalColour = ref<NaturalColour | null>(null);
|
|
1248
|
+
const desiredColour = ref<DesiredColour | null>(null);
|
|
1249
|
+
const selectedTreatments = ref<TreatmentId[]>([]);
|
|
1250
|
+
|
|
1251
|
+
const excludedTreatmentIds = computed<Set<TreatmentId>>(() => {
|
|
1252
|
+
const excluded = new Set<TreatmentId>();
|
|
1253
|
+
for (const id of selectedTreatments.value) {
|
|
1254
|
+
const treatment = treatments.find((t) => t.id === id);
|
|
1255
|
+
treatment?.excludes?.forEach((e) => excluded.add(e));
|
|
1256
|
+
}
|
|
1257
|
+
return excluded;
|
|
1258
|
+
});
|
|
1259
|
+
|
|
1260
|
+
function getConflictingLabel(id: TreatmentId): string | null {
|
|
1261
|
+
for (const selectedId of selectedTreatments.value) {
|
|
1262
|
+
const t = treatments.find((tr) => tr.id === selectedId);
|
|
1263
|
+
if (t?.excludes?.includes(id)) return t.label;
|
|
1264
|
+
}
|
|
1265
|
+
return null;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
function toggleTreatment(id: TreatmentId) {
|
|
1269
|
+
if (id === "none") {
|
|
1270
|
+
selectedTreatments.value = selectedTreatments.value.includes("none") ? [] : ["none"];
|
|
1271
|
+
if (props.autoAdvance) next();
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
if (!props.allowMultipleTreatments) {
|
|
1275
|
+
selectedTreatments.value = selectedTreatments.value.includes(id) ? [] : [id];
|
|
1276
|
+
if (props.autoAdvance) next();
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
const idx = selectedTreatments.value.indexOf(id);
|
|
1280
|
+
if (idx > -1) {
|
|
1281
|
+
selectedTreatments.value.splice(idx, 1);
|
|
1282
|
+
} else {
|
|
1283
|
+
const treatment = treatments.find((t) => t.id === id);
|
|
1284
|
+
selectedTreatments.value = selectedTreatments.value
|
|
1285
|
+
.filter((t) => t !== "none")
|
|
1286
|
+
.filter((t) => !treatment?.excludes?.includes(t));
|
|
1287
|
+
selectedTreatments.value.push(id);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
// ─── Computed ─────────────────────────────────────────────────────────────────
|
|
1292
|
+
const colourRecommendation = computed<Recommendation | null>(() => {
|
|
1293
|
+
if (hairType.value && naturalColour.value && desiredColour.value && desiredColour.value !== "none") {
|
|
1294
|
+
return getColourRecommendation(naturalColour.value, desiredColour.value, hairType.value);
|
|
1295
|
+
}
|
|
1296
|
+
return null;
|
|
1297
|
+
});
|
|
1298
|
+
|
|
1299
|
+
const hasActiveTreatments = computed(
|
|
1300
|
+
() => selectedTreatments.value.length > 0 && !selectedTreatments.value.includes("none")
|
|
1301
|
+
);
|
|
1302
|
+
|
|
1303
|
+
const chosenTreatments = computed(() =>
|
|
1304
|
+
treatments.filter((t) => selectedTreatments.value.includes(t.id) && t.id !== "none")
|
|
1305
|
+
);
|
|
1306
|
+
|
|
1307
|
+
const canShowResults = computed(() => !!hairType.value && !!naturalColour.value && !!desiredColour.value);
|
|
1308
|
+
|
|
1309
|
+
const canProceed = computed(() => {
|
|
1310
|
+
if (step.value === 0) return !!hairType.value;
|
|
1311
|
+
if (step.value === 1) return !!naturalColour.value;
|
|
1312
|
+
if (step.value === 2) return !!desiredColour.value;
|
|
1313
|
+
if (step.value === 3) return true; // optional — always passable
|
|
1314
|
+
return step.value === 4;
|
|
1315
|
+
});
|
|
1316
|
+
|
|
1317
|
+
function next() {
|
|
1318
|
+
if (canProceed.value && step.value < 4) step.value++;
|
|
1319
|
+
}
|
|
1320
|
+
function back() {
|
|
1321
|
+
if (step.value > 0) step.value--;
|
|
1322
|
+
}
|
|
1323
|
+
function reset() {
|
|
1324
|
+
step.value = 0;
|
|
1325
|
+
hairType.value = null;
|
|
1326
|
+
naturalColour.value = null;
|
|
1327
|
+
desiredColour.value = null;
|
|
1328
|
+
selectedTreatments.value = [];
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
function selectHairType(id: HairType) {
|
|
1332
|
+
hairType.value = id;
|
|
1333
|
+
if (props.autoAdvance) next();
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
function selectNaturalColour(id: NaturalColour) {
|
|
1337
|
+
naturalColour.value = id;
|
|
1338
|
+
if (props.autoAdvance) next();
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
function selectDesiredColour(id: DesiredColour) {
|
|
1342
|
+
desiredColour.value = id;
|
|
1343
|
+
if (props.autoAdvance) next();
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
// ─── Summary Items ────────────────────────────────────────────────────────────
|
|
1347
|
+
const summaryItems = computed(() => {
|
|
1348
|
+
const nc = naturalColours.find((n) => n.id === naturalColour.value);
|
|
1349
|
+
const dc = desiredColours.find((d) => d.id === desiredColour.value);
|
|
1350
|
+
const treatmentLabel = hasActiveTreatments.value ? chosenTreatments.value.map((t) => t.label).join(", ") : "None";
|
|
1351
|
+
|
|
1352
|
+
return [
|
|
1353
|
+
{
|
|
1354
|
+
label: "Hair Type",
|
|
1355
|
+
value: hairTypes.find((h) => h.id === hairType.value)?.label ?? "",
|
|
1356
|
+
swatch: undefined,
|
|
1357
|
+
image: undefined,
|
|
1358
|
+
icon: "lucide:scissors",
|
|
1359
|
+
textDark: false,
|
|
1360
|
+
},
|
|
1361
|
+
{
|
|
1362
|
+
label: "Natural Colour",
|
|
1363
|
+
value: nc?.label ?? "",
|
|
1364
|
+
swatch: nc?.colour,
|
|
1365
|
+
image: nc?.image,
|
|
1366
|
+
icon: undefined,
|
|
1367
|
+
textDark: nc?.textDark ?? false,
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
label: "Dream Colour",
|
|
1371
|
+
value: dc?.label ?? "",
|
|
1372
|
+
swatch: dc?.id !== "none" ? dc?.colour : undefined,
|
|
1373
|
+
image: dc?.id !== "none" ? dc?.image : undefined,
|
|
1374
|
+
icon: dc?.id === "none" ? "lucide:minus-circle" : undefined,
|
|
1375
|
+
textDark: dc?.textDark ?? false,
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
label: "Treatments",
|
|
1379
|
+
value: treatmentLabel,
|
|
1380
|
+
swatch: undefined,
|
|
1381
|
+
image: undefined,
|
|
1382
|
+
icon: hasActiveTreatments.value ? undefined : "lucide:minus-circle",
|
|
1383
|
+
textDark: false,
|
|
1384
|
+
},
|
|
1385
|
+
];
|
|
1386
|
+
});
|
|
1387
|
+
|
|
1388
|
+
// ─── Suitability Config ───────────────────────────────────────────────────────
|
|
1389
|
+
const suitabilityConfig: Record<Suitability, { icon: string; label: string }> = {
|
|
1390
|
+
great: { icon: "lucide:check", label: "Great Match" },
|
|
1391
|
+
possible: { icon: "lucide:triangle-alert", label: "Possible with Care" },
|
|
1392
|
+
difficult: { icon: "lucide:triangle-alert", label: "Challenging" },
|
|
1393
|
+
"not-recommended": { icon: "lucide:x", label: "Not Recommended" },
|
|
1394
|
+
};
|
|
1395
|
+
</script>
|
|
1396
|
+
|
|
1397
|
+
<style lang="css">
|
|
1398
|
+
@layer components {
|
|
1399
|
+
/* ─── CSS Custom Properties ────────────────────────────────────────────────── */
|
|
1400
|
+
.treatment-consultant {
|
|
1401
|
+
--_primary-color: hsl(var(--treatment-consultant-primary-colour));
|
|
1402
|
+
--_primary-foreground: hsl(var(--primary-foreground));
|
|
1403
|
+
--_background: hsl(var(--background));
|
|
1404
|
+
--_foreground: hsl(var(--foreground));
|
|
1405
|
+
--_muted: hsl(var(--muted));
|
|
1406
|
+
--_muted-foreground: hsl(var(--muted-foreground));
|
|
1407
|
+
--_emerald: hsl(160 84% 39%);
|
|
1408
|
+
--_amber: hsl(43 96% 56%);
|
|
1409
|
+
--_orange: hsl(25 95% 53%);
|
|
1410
|
+
--_red: hsl(0 84% 60%);
|
|
1411
|
+
--_transition-duration: 300ms;
|
|
1412
|
+
--_border-radius: 0.5rem;
|
|
1413
|
+
--_spacing-xs: 0.25rem;
|
|
1414
|
+
--_spacing-sm: 0.5rem;
|
|
1415
|
+
--_spacing-md: 1rem;
|
|
1416
|
+
--_spacing-lg: 1.5rem;
|
|
1417
|
+
--_spacing-xl: 2rem;
|
|
1418
|
+
--_spacing-2xl: 3rem;
|
|
1419
|
+
--_spacing-3xl: 4rem;
|
|
1420
|
+
--_font-display: var(--font-display);
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
/* ─── Main Container ───────────────────────────────────────────────────────── */
|
|
1424
|
+
.treatment-consultant {
|
|
1425
|
+
background-color: var(--_background);
|
|
1426
|
+
color: var(--_foreground);
|
|
1427
|
+
|
|
1428
|
+
.treatment-consultant__container {
|
|
1429
|
+
padding-inline: var(--_spacing-lg);
|
|
1430
|
+
|
|
1431
|
+
@container (min-width: 1024px) {
|
|
1432
|
+
padding-inline: var(--_spacing-2xl);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
.treatment-consultant__content {
|
|
1437
|
+
margin-inline: auto;
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
/* ─── Header ───────────────────────────────────────────────────────────────── */
|
|
1442
|
+
.treatment-consultant__header {
|
|
1443
|
+
text-align: center;
|
|
1444
|
+
margin-block-end: var(--_spacing-3xl);
|
|
1445
|
+
|
|
1446
|
+
.treatment-consultant__label {
|
|
1447
|
+
letter-spacing: 0.4em;
|
|
1448
|
+
text-transform: uppercase;
|
|
1449
|
+
color: var(--_primary-color);
|
|
1450
|
+
margin-block-end: var(--_spacing-md);
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
.treatment-consultant__title {
|
|
1454
|
+
font-family: var(--_font-display);
|
|
1455
|
+
font-size: clamp(2.25rem, 5vw, 3.75rem);
|
|
1456
|
+
margin-block-end: var(--_spacing-md);
|
|
1457
|
+
|
|
1458
|
+
@media (min-width: 768px) {
|
|
1459
|
+
font-size: clamp(3.75rem, 8vw, 6rem);
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
.treatment-consultant__title-highlight {
|
|
1463
|
+
font-style: italic;
|
|
1464
|
+
background: linear-gradient(135deg, #d4af37, #ffd700, #ffed4e);
|
|
1465
|
+
background-clip: text;
|
|
1466
|
+
-webkit-background-clip: text;
|
|
1467
|
+
color: transparent;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
.treatment-consultant__subtitle {
|
|
1472
|
+
color: var(--_muted-foreground);
|
|
1473
|
+
font-weight: 300;
|
|
1474
|
+
max-inline-size: 34rem;
|
|
1475
|
+
margin-inline: auto;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
/* ─── Progress Steps ───────────────────────────────────────────────────────── */
|
|
1480
|
+
.treatment-consultant__progress {
|
|
1481
|
+
display: flex;
|
|
1482
|
+
align-items: center;
|
|
1483
|
+
justify-content: center;
|
|
1484
|
+
gap: var(--_spacing-sm);
|
|
1485
|
+
margin-block-end: var(--_spacing-3xl);
|
|
1486
|
+
|
|
1487
|
+
.treatment-consultant__progress-step {
|
|
1488
|
+
display: flex;
|
|
1489
|
+
align-items: center;
|
|
1490
|
+
gap: var(--_spacing-sm);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
.treatment-consultant__progress-button {
|
|
1494
|
+
display: flex;
|
|
1495
|
+
align-items: center;
|
|
1496
|
+
gap: var(--_spacing-sm);
|
|
1497
|
+
padding: 0.8rem 1.2rem;
|
|
1498
|
+
text-transform: uppercase;
|
|
1499
|
+
border: 1px solid var(--treatment-consultant-border-colour);
|
|
1500
|
+
background: transparent;
|
|
1501
|
+
color: var(--_muted-foreground);
|
|
1502
|
+
transition: all var(--_transition-duration) ease;
|
|
1503
|
+
cursor: pointer;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
.treatment-consultant__progress-button--active {
|
|
1507
|
+
border-color: var(--_primary-color);
|
|
1508
|
+
color: var(--_primary-color);
|
|
1509
|
+
}
|
|
1510
|
+
.treatment-consultant__progress-button--completed {
|
|
1511
|
+
border-color: color-mix(in srgb, var(--_primary-color) 30%, transparent);
|
|
1512
|
+
color: color-mix(in srgb, var(--_primary-color) 60%, transparent);
|
|
1513
|
+
}
|
|
1514
|
+
.treatment-consultant__progress-button--inactive {
|
|
1515
|
+
border-color: var(--treatment-consultant-border-colour);
|
|
1516
|
+
color: var(--_muted-foreground);
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
.treatment-consultant__progress-indicator {
|
|
1520
|
+
inline-size: 1.25rem;
|
|
1521
|
+
block-size: 1.25rem;
|
|
1522
|
+
display: flex;
|
|
1523
|
+
align-items: center;
|
|
1524
|
+
justify-content: center;
|
|
1525
|
+
font-weight: 500;
|
|
1526
|
+
border-radius: 50%;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
.treatment-consultant__progress-indicator--completed {
|
|
1530
|
+
background-color: var(--_primary-color);
|
|
1531
|
+
color: var(--_primary-foreground);
|
|
1532
|
+
}
|
|
1533
|
+
.treatment-consultant__progress-indicator--active {
|
|
1534
|
+
border: 1px solid var(--_primary-color);
|
|
1535
|
+
color: var(--_primary-color);
|
|
1536
|
+
}
|
|
1537
|
+
.treatment-consultant__progress-indicator--inactive {
|
|
1538
|
+
border: 1px solid var(--_muted-foreground);
|
|
1539
|
+
color: var(--_muted-foreground);
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
.treatment-consultant__progress-label {
|
|
1543
|
+
display: none;
|
|
1544
|
+
@media (min-width: 640px) {
|
|
1545
|
+
display: inline;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
.treatment-consultant__progress-connector {
|
|
1550
|
+
inline-size: 2rem;
|
|
1551
|
+
block-size: 1px;
|
|
1552
|
+
background-color: var(--treatment-consultant-border-colour);
|
|
1553
|
+
}
|
|
1554
|
+
.treatment-consultant__progress-connector--completed {
|
|
1555
|
+
background-color: var(--_primary-color);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
/* ─── Step ─────────────────────────────────────────────────────────────────── */
|
|
1560
|
+
.treatment-consultant__step {
|
|
1561
|
+
.treatment-consultant__step-title {
|
|
1562
|
+
font-family: var(--_font-display);
|
|
1563
|
+
text-align: center;
|
|
1564
|
+
margin-block-end: var(--_spacing-sm);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
.treatment-consultant__step-subtitle {
|
|
1568
|
+
text-align: center;
|
|
1569
|
+
color: var(--_muted-foreground);
|
|
1570
|
+
font-weight: 300;
|
|
1571
|
+
margin-block-end: var(--_spacing-xl);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
/* ─── Options Grid ─────────────────────────────────────────────────────────── */
|
|
1576
|
+
.treatment-consultant__options {
|
|
1577
|
+
display: grid;
|
|
1578
|
+
gap: var(--_spacing-md);
|
|
1579
|
+
margin-inline: auto;
|
|
1580
|
+
|
|
1581
|
+
&.treatment-consultant__options--hair-type {
|
|
1582
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1583
|
+
@media (min-width: 768px) {
|
|
1584
|
+
grid-template-columns: repeat(4, 1fr);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
&.treatment-consultant__options--natural-colour {
|
|
1589
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1590
|
+
@media (min-width: 640px) {
|
|
1591
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1592
|
+
}
|
|
1593
|
+
@media (min-width: 1024px) {
|
|
1594
|
+
grid-template-columns: repeat(4, 1fr);
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
&.treatment-consultant__options--desired-colour {
|
|
1599
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1600
|
+
@media (min-width: 640px) {
|
|
1601
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
&.treatment-consultant__options--treatments {
|
|
1606
|
+
display: flex;
|
|
1607
|
+
flex-direction: column;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
.treatment-consultant__treatments-grid {
|
|
1612
|
+
display: grid;
|
|
1613
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1614
|
+
gap: var(--_spacing-md);
|
|
1615
|
+
|
|
1616
|
+
@media (min-width: 640px) {
|
|
1617
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
@media (min-width: 1024px) {
|
|
1621
|
+
grid-template-columns: repeat(4, 1fr);
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
.treatment-consultant__option--treatment {
|
|
1625
|
+
display: grid;
|
|
1626
|
+
grid-row: span 3;
|
|
1627
|
+
grid-template-rows: subgrid;
|
|
1628
|
+
justify-items: center;
|
|
1629
|
+
align-items: center;
|
|
1630
|
+
|
|
1631
|
+
.treatment-consultant__option-treatment-icon {
|
|
1632
|
+
align-self: center;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
.treatment-consultant__option-label {
|
|
1636
|
+
align-self: end;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
.treatment-consultant__option-sublabel,
|
|
1640
|
+
.treatment-consultant__option-conflict {
|
|
1641
|
+
align-self: start;
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
.treatment-consultant__option {
|
|
1647
|
+
position: relative;
|
|
1648
|
+
padding: var(--_spacing-lg);
|
|
1649
|
+
border: 1px solid var(--treatment-consultant-border-colour);
|
|
1650
|
+
background: transparent;
|
|
1651
|
+
text-align: center;
|
|
1652
|
+
cursor: pointer;
|
|
1653
|
+
transition: all var(--_transition-duration) ease;
|
|
1654
|
+
border-radius: var(--_border-radius);
|
|
1655
|
+
display: flex;
|
|
1656
|
+
flex-direction: column;
|
|
1657
|
+
align-items: center;
|
|
1658
|
+
|
|
1659
|
+
&:hover {
|
|
1660
|
+
border-color: color-mix(in srgb, var(--_primary-color) 50%, transparent);
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
.treatment-consultant__option-pattern {
|
|
1664
|
+
/* font-size: 1.875rem; */
|
|
1665
|
+
font-weight: 300;
|
|
1666
|
+
letter-spacing: 0.1em;
|
|
1667
|
+
color: var(--_foreground);
|
|
1668
|
+
margin-block-end: 0.75rem;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
.treatment-consultant__option-swatch {
|
|
1672
|
+
aspect-ratio: 1 / 1;
|
|
1673
|
+
block-size: 8rem;
|
|
1674
|
+
inline-size: 8rem;
|
|
1675
|
+
border-radius: 50%;
|
|
1676
|
+
margin-block-end: 0.75rem;
|
|
1677
|
+
border: 1px solid color-mix(in srgb, var(--_foreground) 10%, transparent);
|
|
1678
|
+
overflow: hidden;
|
|
1679
|
+
|
|
1680
|
+
.treatment-consultant__option-image {
|
|
1681
|
+
inline-size: 100%;
|
|
1682
|
+
block-size: 100%;
|
|
1683
|
+
object-fit: cover;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
.treatment-consultant__option-none-icon {
|
|
1688
|
+
inline-size: 3.5rem;
|
|
1689
|
+
block-size: 3.5rem;
|
|
1690
|
+
border-radius: 50%;
|
|
1691
|
+
border: 1px dashed color-mix(in srgb, var(--_muted-foreground) 50%, transparent);
|
|
1692
|
+
display: flex;
|
|
1693
|
+
align-items: center;
|
|
1694
|
+
justify-content: center;
|
|
1695
|
+
flex-shrink: 0;
|
|
1696
|
+
|
|
1697
|
+
.treatment-consultant__option-none-icon-svg {
|
|
1698
|
+
inline-size: 1.25rem;
|
|
1699
|
+
block-size: 1.25rem;
|
|
1700
|
+
color: var(--_muted-foreground);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
.treatment-consultant__option-treatment-icon {
|
|
1705
|
+
inline-size: 1.5rem;
|
|
1706
|
+
block-size: 1.5rem;
|
|
1707
|
+
color: var(--_muted-foreground);
|
|
1708
|
+
margin-block-end: var(--_spacing-sm);
|
|
1709
|
+
transition: color var(--_transition-duration) ease;
|
|
1710
|
+
flex-shrink: 0;
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
.treatment-consultant__option-label {
|
|
1714
|
+
display: block;
|
|
1715
|
+
letter-spacing: 0.1em;
|
|
1716
|
+
text-transform: uppercase;
|
|
1717
|
+
color: var(--_muted-foreground);
|
|
1718
|
+
transition: color var(--_transition-duration) ease;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
.treatment-consultant__option-sublabel {
|
|
1722
|
+
display: block;
|
|
1723
|
+
/* font-size: 0.7rem; */
|
|
1724
|
+
letter-spacing: 0.05em;
|
|
1725
|
+
color: var(--_muted-foreground);
|
|
1726
|
+
font-weight: 300;
|
|
1727
|
+
margin-block-start: 0.2rem;
|
|
1728
|
+
opacity: 0.7;
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
&:hover .treatment-consultant__option-label {
|
|
1732
|
+
color: var(--_foreground);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
.treatment-consultant__option--selected {
|
|
1737
|
+
border-color: var(--treatment-consultant-checked-stroke-colour);
|
|
1738
|
+
background-color: color-mix(in srgb, var(--treatment-consultant-checked-surface-colour) 20%, transparent);
|
|
1739
|
+
box-shadow: 0 4px 20px color-mix(in srgb, var(--treatment-consultant-checked-surface-colour) 20%, transparent);
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
.treatment-consultant__option--excluded {
|
|
1743
|
+
opacity: 0.45;
|
|
1744
|
+
cursor: pointer;
|
|
1745
|
+
|
|
1746
|
+
.treatment-consultant__option-conflict {
|
|
1747
|
+
display: block;
|
|
1748
|
+
/* font-size: 0.65rem; */
|
|
1749
|
+
letter-spacing: 0.04em;
|
|
1750
|
+
color: var(--_muted-foreground);
|
|
1751
|
+
font-weight: 400;
|
|
1752
|
+
margin-block-start: 0.2rem;
|
|
1753
|
+
font-style: italic;
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
.treatment-consultant__option-excluded-icon {
|
|
1757
|
+
position: absolute;
|
|
1758
|
+
top: 0.5rem;
|
|
1759
|
+
right: 0.5rem;
|
|
1760
|
+
inline-size: 1.75rem;
|
|
1761
|
+
block-size: 1.75rem;
|
|
1762
|
+
color: var(--treatment-consultant-conflict-stroke-colour);
|
|
1763
|
+
opacity: 0.6;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
.treatment-consultant__option-check {
|
|
1768
|
+
position: absolute;
|
|
1769
|
+
top: 1rem;
|
|
1770
|
+
right: 1rem;
|
|
1771
|
+
inline-size: 2.25rem;
|
|
1772
|
+
block-size: 2.25rem;
|
|
1773
|
+
border-radius: 100vw;
|
|
1774
|
+
background-color: var(--treatment-consultant-checked-surface-colour);
|
|
1775
|
+
border: 1px solid var(--treatment-consultant-checked-stroke-colour);
|
|
1776
|
+
display: flex;
|
|
1777
|
+
align-items: center;
|
|
1778
|
+
justify-content: center;
|
|
1779
|
+
pointer-events: none;
|
|
1780
|
+
|
|
1781
|
+
.treatment-consultant__option-check-icon {
|
|
1782
|
+
inline-size: 1.55rem;
|
|
1783
|
+
block-size: 1.55rem;
|
|
1784
|
+
color: var(--treatment-consultant-checked-stroke-colour);
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
/* No-change / No-treatment — spans full width */
|
|
1789
|
+
.treatment-consultant__option--no-change {
|
|
1790
|
+
grid-column: 1 / -1;
|
|
1791
|
+
flex-direction: row;
|
|
1792
|
+
justify-content: center;
|
|
1793
|
+
gap: var(--_spacing-md);
|
|
1794
|
+
padding: var(--_spacing-md) var(--_spacing-xl);
|
|
1795
|
+
border-style: dashed;
|
|
1796
|
+
|
|
1797
|
+
.treatment-consultant__option-label,
|
|
1798
|
+
.treatment-consultant__option-sublabel {
|
|
1799
|
+
text-align: left;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
.treatment-consultant__option--selected .treatment-consultant__option-treatment-icon {
|
|
1804
|
+
color: var(--_primary-color);
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
.treatment-consultant__option-label--selected {
|
|
1808
|
+
color: var(--_primary-color);
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
/* ─── Results ──────────────────────────────────────────────────────────────── */
|
|
1812
|
+
.treatment-consultant__results {
|
|
1813
|
+
margin-inline: auto;
|
|
1814
|
+
|
|
1815
|
+
.treatment-consultant__results-header {
|
|
1816
|
+
text-align: center;
|
|
1817
|
+
margin-block-end: var(--_spacing-xl);
|
|
1818
|
+
|
|
1819
|
+
.treatment-consultant__results-icon {
|
|
1820
|
+
inline-size: 2rem;
|
|
1821
|
+
block-size: 2rem;
|
|
1822
|
+
color: var(--_primary-color);
|
|
1823
|
+
margin-inline: auto;
|
|
1824
|
+
margin-block-end: var(--_spacing-md);
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
.treatment-consultant__results-title {
|
|
1828
|
+
font-family: var(--_font-display);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
.treatment-consultant__results-section-title {
|
|
1834
|
+
display: flex;
|
|
1835
|
+
align-items: center;
|
|
1836
|
+
gap: var(--_spacing-sm);
|
|
1837
|
+
font-family: var(--_font-display);
|
|
1838
|
+
/* font-size: 0.875rem; */
|
|
1839
|
+
letter-spacing: 0.2em;
|
|
1840
|
+
text-transform: uppercase;
|
|
1841
|
+
color: var(--_muted-foreground);
|
|
1842
|
+
margin-block-end: var(--_spacing-md);
|
|
1843
|
+
|
|
1844
|
+
.treatment-consultant__results-section-icon {
|
|
1845
|
+
inline-size: 1rem;
|
|
1846
|
+
block-size: 1rem;
|
|
1847
|
+
color: var(--_primary-color);
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
.treatment-consultant__results-section-title--spaced {
|
|
1852
|
+
margin-block-start: var(--_spacing-2xl);
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
/* ─── Suitability Badge ────────────────────────────────────────────────────── */
|
|
1856
|
+
.treatment-consultant__suitability {
|
|
1857
|
+
display: flex;
|
|
1858
|
+
align-items: center;
|
|
1859
|
+
gap: 0.75rem;
|
|
1860
|
+
padding: 1.25rem;
|
|
1861
|
+
border: 1px solid;
|
|
1862
|
+
margin-block-end: var(--_spacing-xl);
|
|
1863
|
+
border-radius: var(--_border-radius);
|
|
1864
|
+
|
|
1865
|
+
.treatment-consultant__suitability-icon {
|
|
1866
|
+
inline-size: 1.5rem;
|
|
1867
|
+
block-size: 1.5rem;
|
|
1868
|
+
flex-shrink: 0;
|
|
1869
|
+
}
|
|
1870
|
+
.treatment-consultant__suitability-icon--great {
|
|
1871
|
+
color: var(--_emerald);
|
|
1872
|
+
}
|
|
1873
|
+
.treatment-consultant__suitability-icon--possible {
|
|
1874
|
+
color: var(--_amber);
|
|
1875
|
+
}
|
|
1876
|
+
.treatment-consultant__suitability-icon--difficult {
|
|
1877
|
+
color: var(--_orange);
|
|
1878
|
+
}
|
|
1879
|
+
.treatment-consultant__suitability-icon--not-recommended {
|
|
1880
|
+
color: var(--_red);
|
|
1881
|
+
}
|
|
1882
|
+
.treatment-consultant__suitability-icon--none {
|
|
1883
|
+
color: var(--_muted-foreground);
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
.treatment-consultant__suitability-label {
|
|
1887
|
+
font-family: var(--_font-display);
|
|
1888
|
+
}
|
|
1889
|
+
.treatment-consultant__suitability-label--great {
|
|
1890
|
+
color: var(--_emerald);
|
|
1891
|
+
}
|
|
1892
|
+
.treatment-consultant__suitability-label--possible {
|
|
1893
|
+
color: var(--_amber);
|
|
1894
|
+
}
|
|
1895
|
+
.treatment-consultant__suitability-label--difficult {
|
|
1896
|
+
color: var(--_orange);
|
|
1897
|
+
}
|
|
1898
|
+
.treatment-consultant__suitability-label--not-recommended {
|
|
1899
|
+
color: var(--_red);
|
|
1900
|
+
}
|
|
1901
|
+
.treatment-consultant__suitability-label--none {
|
|
1902
|
+
color: var(--_muted-foreground);
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
.treatment-consultant__suitability-notes {
|
|
1906
|
+
color: var(--_muted-foreground);
|
|
1907
|
+
font-weight: 300;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
/* Suitability colour variants — driven by modifier class from computed */
|
|
1912
|
+
.treatment-consultant__suitability--great {
|
|
1913
|
+
background-color: color-mix(in srgb, var(--_emerald) 10%, transparent);
|
|
1914
|
+
border-color: color-mix(in srgb, var(--_emerald) 30%, transparent);
|
|
1915
|
+
}
|
|
1916
|
+
.treatment-consultant__suitability--possible {
|
|
1917
|
+
background-color: color-mix(in srgb, var(--_amber) 10%, transparent);
|
|
1918
|
+
border-color: color-mix(in srgb, var(--_amber) 30%, transparent);
|
|
1919
|
+
}
|
|
1920
|
+
.treatment-consultant__suitability--difficult {
|
|
1921
|
+
background-color: color-mix(in srgb, var(--_orange) 10%, transparent);
|
|
1922
|
+
border-color: color-mix(in srgb, var(--_orange) 30%, transparent);
|
|
1923
|
+
}
|
|
1924
|
+
.treatment-consultant__suitability--not-recommended {
|
|
1925
|
+
background-color: color-mix(in srgb, var(--_red) 10%, transparent);
|
|
1926
|
+
border-color: color-mix(in srgb, var(--_red) 30%, transparent);
|
|
1927
|
+
}
|
|
1928
|
+
.treatment-consultant__suitability--none {
|
|
1929
|
+
background-color: color-mix(in srgb, var(--_muted-foreground) 8%, transparent);
|
|
1930
|
+
border-color: color-mix(in srgb, var(--_muted-foreground) 20%, transparent);
|
|
1931
|
+
border-style: dashed;
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
/* ─── Details Card ─────────────────────────────────────────────────────────── */
|
|
1935
|
+
.treatment-consultant__details-card {
|
|
1936
|
+
background: rgba(255, 255, 255, 0.05);
|
|
1937
|
+
backdrop-filter: blur(10px);
|
|
1938
|
+
border: 1px solid color-mix(in srgb, var(--_foreground) 10%, transparent);
|
|
1939
|
+
border-radius: var(--_border-radius);
|
|
1940
|
+
padding: var(--_spacing-xl);
|
|
1941
|
+
margin-block-end: var(--_spacing-md);
|
|
1942
|
+
|
|
1943
|
+
.treatment-consultant__details-header {
|
|
1944
|
+
display: flex;
|
|
1945
|
+
align-items: center;
|
|
1946
|
+
gap: 0.75rem;
|
|
1947
|
+
margin-block-end: var(--_spacing-lg);
|
|
1948
|
+
flex-wrap: wrap;
|
|
1949
|
+
|
|
1950
|
+
.treatment-consultant__details-method-label {
|
|
1951
|
+
/* font-size: 0.75rem; */
|
|
1952
|
+
letter-spacing: 0.2em;
|
|
1953
|
+
text-transform: uppercase;
|
|
1954
|
+
color: var(--_primary-color);
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
.treatment-consultant__details-method-badge {
|
|
1958
|
+
padding: var(--_spacing-xs) 0.75rem;
|
|
1959
|
+
background-color: color-mix(in srgb, var(--_primary-color) 10%, transparent);
|
|
1960
|
+
color: var(--_primary-color);
|
|
1961
|
+
border: 1px solid color-mix(in srgb, var(--_primary-color) 20%, transparent);
|
|
1962
|
+
border-radius: var(--_border-radius);
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
.treatment-consultant__treatment-icon {
|
|
1966
|
+
inline-size: 1rem;
|
|
1967
|
+
block-size: 1rem;
|
|
1968
|
+
color: var(--_primary-color);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
.treatment-consultant__details-list {
|
|
1973
|
+
display: flex;
|
|
1974
|
+
flex-direction: column;
|
|
1975
|
+
gap: 0.75rem;
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
.treatment-consultant__details-item {
|
|
1979
|
+
display: flex;
|
|
1980
|
+
align-items: flex-start;
|
|
1981
|
+
gap: 0.75rem;
|
|
1982
|
+
|
|
1983
|
+
.treatment-consultant__details-bullet {
|
|
1984
|
+
inline-size: 0.25rem;
|
|
1985
|
+
block-size: 0.25rem;
|
|
1986
|
+
border-radius: 50%;
|
|
1987
|
+
background-color: var(--_primary-color);
|
|
1988
|
+
margin-block-start: 0.5rem;
|
|
1989
|
+
flex-shrink: 0;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
.treatment-consultant__details-text {
|
|
1993
|
+
color: color-mix(in srgb, var(--_foreground) 80%, transparent);
|
|
1994
|
+
font-weight: 300;
|
|
1995
|
+
line-height: 1;
|
|
1996
|
+
margin-block: 1rem;
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
.treatment-consultant__details-card--treatment {
|
|
2002
|
+
margin-block-end: var(--_spacing-sm);
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
/* ─── Compatibility Badge ──────────────────────────────────────────────────── */
|
|
2006
|
+
.treatment-consultant__compat-badge {
|
|
2007
|
+
margin-inline-start: auto;
|
|
2008
|
+
padding: var(--_spacing-xs) var(--_spacing-sm);
|
|
2009
|
+
border-radius: var(--_border-radius);
|
|
2010
|
+
/* font-size: 0.65rem; */
|
|
2011
|
+
letter-spacing: 0.08em;
|
|
2012
|
+
text-transform: uppercase;
|
|
2013
|
+
font-weight: 500;
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
.treatment-consultant__compat-badge--ok {
|
|
2017
|
+
background-color: color-mix(in srgb, var(--_emerald) 10%, transparent);
|
|
2018
|
+
color: var(--_emerald);
|
|
2019
|
+
border: 1px solid color-mix(in srgb, var(--_emerald) 30%, transparent);
|
|
2020
|
+
}
|
|
2021
|
+
.treatment-consultant__compat-badge--warning {
|
|
2022
|
+
background-color: color-mix(in srgb, var(--_amber) 10%, transparent);
|
|
2023
|
+
color: var(--_amber);
|
|
2024
|
+
border: 1px solid color-mix(in srgb, var(--_amber) 30%, transparent);
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
/* ─── Summary ──────────────────────────────────────────────────────────────── */
|
|
2028
|
+
.treatment-consultant__summary {
|
|
2029
|
+
display: grid;
|
|
2030
|
+
grid-template-columns: repeat(2, 1fr);
|
|
2031
|
+
grid-template-rows: repeat(6, auto);
|
|
2032
|
+
gap: var(--_spacing-md);
|
|
2033
|
+
margin-block: var(--_spacing-2xl);
|
|
2034
|
+
|
|
2035
|
+
@media (min-width: 640px) {
|
|
2036
|
+
grid-template-columns: repeat(4, 1fr);
|
|
2037
|
+
grid-template-rows: repeat(3, auto);
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
.treatment-consultant__summary-item {
|
|
2041
|
+
display: grid;
|
|
2042
|
+
grid-row: span 3;
|
|
2043
|
+
grid-template-rows: subgrid;
|
|
2044
|
+
align-items: center;
|
|
2045
|
+
justify-items: center;
|
|
2046
|
+
text-align: center;
|
|
2047
|
+
padding: var(--_spacing-md);
|
|
2048
|
+
border: 1px solid var(--treatment-consultant-border-colour);
|
|
2049
|
+
border-radius: var(--_border-radius);
|
|
2050
|
+
|
|
2051
|
+
.treatment-consultant__summary-label {
|
|
2052
|
+
align-self: end;
|
|
2053
|
+
letter-spacing: 0.2em;
|
|
2054
|
+
text-transform: uppercase;
|
|
2055
|
+
color: var(--_muted-foreground);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
.treatment-consultant__summary-visual {
|
|
2059
|
+
display: flex;
|
|
2060
|
+
align-items: center;
|
|
2061
|
+
justify-content: center;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
.treatment-consultant__summary-swatch {
|
|
2065
|
+
aspect-ratio: 1 / 1;
|
|
2066
|
+
block-size: 8rem;
|
|
2067
|
+
border-radius: 100vw;
|
|
2068
|
+
border: 1px solid color-mix(in srgb, var(--_foreground) 10%, transparent);
|
|
2069
|
+
overflow: hidden;
|
|
2070
|
+
|
|
2071
|
+
.treatment-consultant__summary-image {
|
|
2072
|
+
inline-size: 100%;
|
|
2073
|
+
block-size: 100%;
|
|
2074
|
+
object-fit: cover;
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
.treatment-consultant__summary-none-icon {
|
|
2079
|
+
inline-size: 1.5rem;
|
|
2080
|
+
block-size: 1.5rem;
|
|
2081
|
+
color: var(--_muted-foreground);
|
|
2082
|
+
opacity: 0.5;
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
.treatment-consultant__summary-value {
|
|
2086
|
+
align-self: start;
|
|
2087
|
+
color: var(--_foreground);
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
.treatment-consultant__summary-image--dark {
|
|
2093
|
+
filter: brightness(0.8) contrast(1.1);
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
/* ─── CTA ──────────────────────────────────────────────────────────────────── */
|
|
2097
|
+
.treatment-consultant__cta {
|
|
2098
|
+
text-align: center;
|
|
2099
|
+
|
|
2100
|
+
.treatment-consultant__cta-disclaimer {
|
|
2101
|
+
color: var(--_muted-foreground);
|
|
2102
|
+
margin-block-end: var(--_spacing-lg);
|
|
2103
|
+
font-weight: 300;
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
.treatment-consultant__cta-buttons {
|
|
2107
|
+
display: flex;
|
|
2108
|
+
flex-direction: column;
|
|
2109
|
+
gap: var(--_spacing-md);
|
|
2110
|
+
justify-content: center;
|
|
2111
|
+
|
|
2112
|
+
@media (min-width: 640px) {
|
|
2113
|
+
flex-direction: row;
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
.treatment-consultant__button {
|
|
2119
|
+
display: inline-flex;
|
|
2120
|
+
align-items: center;
|
|
2121
|
+
justify-content: center;
|
|
2122
|
+
padding: var(--_spacing-md) var(--_spacing-xl);
|
|
2123
|
+
letter-spacing: 0.15em;
|
|
2124
|
+
text-transform: uppercase;
|
|
2125
|
+
text-decoration: none;
|
|
2126
|
+
transition: all var(--_transition-duration) ease;
|
|
2127
|
+
border-radius: var(--_border-radius);
|
|
2128
|
+
cursor: pointer;
|
|
2129
|
+
border: 1px solid transparent;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
.treatment-consultant__button--primary {
|
|
2133
|
+
background-color: var(--_primary-color);
|
|
2134
|
+
color: var(--_primary-foreground);
|
|
2135
|
+
box-shadow: 0 4px 20px color-mix(in srgb, var(--_primary-color) 20%, transparent);
|
|
2136
|
+
&:hover {
|
|
2137
|
+
background-color: color-mix(in srgb, var(--_primary-color) 90%, transparent);
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
.treatment-consultant__button--secondary {
|
|
2142
|
+
border-color: color-mix(in srgb, var(--_foreground) 20%, transparent);
|
|
2143
|
+
color: var(--_foreground);
|
|
2144
|
+
&:hover {
|
|
2145
|
+
border-color: var(--_primary-color);
|
|
2146
|
+
color: var(--_primary-color);
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
/* ─── Navigation ───────────────────────────────────────────────────────────── */
|
|
2151
|
+
.treatment-consultant__navigation {
|
|
2152
|
+
display: flex;
|
|
2153
|
+
align-items: center;
|
|
2154
|
+
justify-content: center;
|
|
2155
|
+
gap: var(--_spacing-md);
|
|
2156
|
+
margin-block-start: var(--_spacing-2xl);
|
|
2157
|
+
|
|
2158
|
+
.treatment-consultant__nav-button {
|
|
2159
|
+
display: flex;
|
|
2160
|
+
align-items: center;
|
|
2161
|
+
gap: var(--_spacing-sm);
|
|
2162
|
+
padding: 0.75rem var(--_spacing-lg);
|
|
2163
|
+
letter-spacing: 0.1em;
|
|
2164
|
+
text-transform: uppercase;
|
|
2165
|
+
background: transparent;
|
|
2166
|
+
border: 1px solid transparent;
|
|
2167
|
+
cursor: pointer;
|
|
2168
|
+
transition: all var(--_transition-duration) ease;
|
|
2169
|
+
border-radius: var(--_border-radius);
|
|
2170
|
+
|
|
2171
|
+
.treatment-consultant__nav-icon {
|
|
2172
|
+
inline-size: 1rem;
|
|
2173
|
+
block-size: 1rem;
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
.treatment-consultant__nav-button--back {
|
|
2179
|
+
color: var(--_muted-foreground);
|
|
2180
|
+
&:hover {
|
|
2181
|
+
color: var(--_foreground);
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
.treatment-consultant__nav-button--next {
|
|
2186
|
+
padding: 0.75rem var(--_spacing-xl);
|
|
2187
|
+
background-color: var(--_primary-color);
|
|
2188
|
+
color: var(--_primary-foreground);
|
|
2189
|
+
box-shadow: 0 4px 20px color-mix(in srgb, var(--_primary-color) 20%, transparent);
|
|
2190
|
+
&:hover {
|
|
2191
|
+
background-color: color-mix(in srgb, var(--_primary-color) 90%, transparent);
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
.treatment-consultant__nav-button--disabled {
|
|
2196
|
+
background-color: var(--_muted);
|
|
2197
|
+
color: var(--_muted-foreground);
|
|
2198
|
+
cursor: not-allowed;
|
|
2199
|
+
box-shadow: none;
|
|
2200
|
+
&:hover {
|
|
2201
|
+
background-color: var(--_muted);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
/* ─── Slide Transition ─────────────────────────────────────────────────────── */
|
|
2206
|
+
.slide-enter-active,
|
|
2207
|
+
.slide-leave-active {
|
|
2208
|
+
transition:
|
|
2209
|
+
opacity var(--_transition-duration) ease,
|
|
2210
|
+
transform var(--_transition-duration) ease;
|
|
2211
|
+
}
|
|
2212
|
+
.slide-enter-from {
|
|
2213
|
+
opacity: 0;
|
|
2214
|
+
transform: translateX(50px);
|
|
2215
|
+
}
|
|
2216
|
+
.slide-leave-to {
|
|
2217
|
+
opacity: 0;
|
|
2218
|
+
transform: translateX(-50px);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
</style>
|