srcdev-nuxt-components 9.4.12 → 9.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/.claude/skills/component-aria-landmark.md +1 -1
  2. package/.claude/skills/component-dynamic-slots.md +0 -1
  3. package/.claude/skills/component-export-types.md +3 -3
  4. package/.claude/skills/component-inline-action-button.md +7 -7
  5. package/.claude/skills/component-local-style-override.md +134 -50
  6. package/.claude/skills/component-naming.md +107 -0
  7. package/.claude/skills/components/action-menu.md +18 -14
  8. package/.claude/skills/components/alert-content.md +110 -0
  9. package/.claude/skills/components/alert-mask-core.md +15 -1
  10. package/.claude/skills/components/alert-masked-content.md +95 -0
  11. package/.claude/skills/components/auto-grid.md +21 -13
  12. package/.claude/skills/components/canvas-switcher.md +3 -3
  13. package/.claude/skills/components/capture-qr-code.md +19 -9
  14. package/.claude/skills/components/carousel-flip.md +3 -3
  15. package/.claude/skills/components/container-glow.md +2 -2
  16. package/.claude/skills/components/content-docs.md +9 -5
  17. package/.claude/skills/components/cookie-consent-banner.md +16 -17
  18. package/.claude/skills/components/dashboard-quad-grid.md +4 -4
  19. package/.claude/skills/components/decode-qr-code.md +15 -9
  20. package/.claude/skills/components/display-avatar.md +16 -31
  21. package/.claude/skills/components/display-chip.md +15 -10
  22. package/.claude/skills/components/display-dialog.md +3 -1
  23. package/.claude/skills/components/display-pill.md +17 -75
  24. package/.claude/skills/components/display-prompt.md +11 -19
  25. package/.claude/skills/components/display-qr-code.md +5 -0
  26. package/.claude/skills/components/display-theme-switch.md +7 -6
  27. package/.claude/skills/components/display-toast.md +5 -6
  28. package/.claude/skills/components/entry-animation.md +2 -5
  29. package/.claude/skills/components/eyebrow-text.md +6 -4
  30. package/.claude/skills/components/form-field.md +79 -0
  31. package/.claude/skills/components/form-fieldset.md +75 -0
  32. package/.claude/skills/components/form-wrapper.md +71 -0
  33. package/.claude/skills/components/glass-panel.md +60 -51
  34. package/.claude/skills/components/grid-stack.md +8 -2
  35. package/.claude/skills/components/header-block.md +1 -1
  36. package/.claude/skills/components/hero-text.md +8 -6
  37. package/.claude/skills/components/input-button.md +72 -0
  38. package/.claude/skills/components/input-checkbox-radio.md +149 -0
  39. package/.claude/skills/components/input-checkbox.md +148 -0
  40. package/.claude/skills/components/input-description.md +102 -0
  41. package/.claude/skills/components/input-error.md +105 -0
  42. package/.claude/skills/components/input-label.md +119 -0
  43. package/.claude/skills/components/{input-number-core.md → input-number.md} +41 -36
  44. package/.claude/skills/components/input-radio.md +95 -0
  45. package/.claude/skills/components/input-range-core.md +4 -4
  46. package/.claude/skills/components/input-select-core.md +1 -1
  47. package/.claude/skills/components/input-text-core.md +8 -6
  48. package/.claude/skills/components/input-textarea-core.md +4 -4
  49. package/.claude/skills/components/layout-grid-by-cols.md +31 -43
  50. package/.claude/skills/components/link-text.md +2 -2
  51. package/.claude/skills/components/opening-hours.md +116 -0
  52. package/.claude/skills/components/page-hero-highlights.md +35 -35
  53. package/.claude/skills/components/page-row.md +1 -1
  54. package/.claude/skills/components/pending-effect.md +63 -0
  55. package/.claude/skills/components/price-list.md +72 -0
  56. package/.claude/skills/components/pricing-card.md +3 -3
  57. package/.claude/skills/components/profile-section.md +6 -4
  58. package/.claude/skills/components/samaritan-prompt.md +140 -0
  59. package/.claude/skills/components/scroll-reveal-frame.md +21 -20
  60. package/.claude/skills/components/scroll-reveal-image.md +31 -21
  61. package/.claude/skills/components/service-detail.md +2 -2
  62. package/.claude/skills/components/services-card-grid.md +5 -4
  63. package/.claude/skills/components/services-card.md +12 -10
  64. package/.claude/skills/components/site-navigation.md +20 -6
  65. package/.claude/skills/components/slider-gallery.md +88 -0
  66. package/.claude/skills/components/social-icons-list.md +12 -6
  67. package/.claude/skills/components/tab-navigation.md +1 -1
  68. package/.claude/skills/components/text-block.md +68 -0
  69. package/.claude/skills/components/toggle-switch-core.md +25 -6
  70. package/.claude/skills/components/triple-toggle-switch.md +85 -0
  71. package/.claude/skills/composable-zod-validation.md +1 -1
  72. package/.claude/skills/consumer-styles-structure.md +153 -0
  73. package/.claude/skills/icon-sets.md +3 -3
  74. package/.claude/skills/icon-sizing.md +66 -0
  75. package/.claude/skills/index.md +36 -17
  76. package/.claude/skills/new-app-scaffold.md +45 -7
  77. package/.claude/skills/pull-request-description.md +1 -0
  78. package/.claude/skills/storybook-add-story.md +53 -5
  79. package/.claude/skills/testing-add-playwright.md +1 -1
  80. package/.claude/skills/theming-colour-ramps.md +25 -3
  81. package/.claude/skills/theming-component-token-pattern.md +16 -16
  82. package/.claude/skills/theming-override-default.md +7 -0
  83. package/.claude/skills/theming-partial-override.md +1 -1
  84. package/.claude/skills/theming-typography-tokens.md +1 -1
  85. package/.claude/skills/vercel-node-version.md +1 -1
  86. package/.vscode/srcdev-component-action-menu.code-snippets +42 -0
  87. package/.vscode/srcdev-component-alert-content.code-snippets +36 -0
  88. package/.vscode/srcdev-component-alert-masked-content.code-snippets +35 -0
  89. package/.vscode/srcdev-component-auto-grid.code-snippets +39 -0
  90. package/.vscode/srcdev-component-capture-decode-qr-code.code-snippets +28 -0
  91. package/.vscode/srcdev-component-content-docs.code-snippets +4 -4
  92. package/.vscode/srcdev-component-cookie-consent-banner.code-snippets +33 -0
  93. package/.vscode/srcdev-component-display-avatar.code-snippets +28 -0
  94. package/.vscode/srcdev-component-display-chip.code-snippets +27 -0
  95. package/.vscode/srcdev-component-display-pill.code-snippets +38 -0
  96. package/.vscode/srcdev-component-display-prompt.code-snippets +10 -54
  97. package/.vscode/srcdev-component-display-qr-code.code-snippets +22 -0
  98. package/.vscode/srcdev-component-eyebrow-text.code-snippets +19 -0
  99. package/.vscode/srcdev-component-form-field.code-snippets +25 -0
  100. package/.vscode/srcdev-component-form-fieldset.code-snippets +36 -0
  101. package/.vscode/srcdev-component-form-wrapper.code-snippets +30 -0
  102. package/.vscode/srcdev-component-glass-panel.code-snippets +38 -0
  103. package/.vscode/srcdev-component-grid-stack.code-snippets +49 -0
  104. package/.vscode/srcdev-component-input-button.code-snippets +27 -0
  105. package/.vscode/srcdev-component-input-checkbox-radio.code-snippets +60 -0
  106. package/.vscode/srcdev-component-input-checkbox.code-snippets +48 -0
  107. package/.vscode/srcdev-component-input-description.code-snippets +44 -0
  108. package/.vscode/srcdev-component-input-error.code-snippets +30 -0
  109. package/.vscode/srcdev-component-input-label.code-snippets +39 -0
  110. package/.vscode/srcdev-component-input-number.code-snippets +11 -11
  111. package/.vscode/srcdev-component-input-radio.code-snippets +58 -0
  112. package/.vscode/srcdev-component-layout-grid-by-cols.code-snippets +46 -0
  113. package/.vscode/srcdev-component-link-text.code-snippets +30 -0
  114. package/.vscode/srcdev-component-opening-hours.code-snippets +40 -0
  115. package/.vscode/srcdev-component-page-hero-highlights.code-snippets +37 -0
  116. package/.vscode/srcdev-component-page-row.code-snippets +47 -0
  117. package/.vscode/srcdev-component-pending-effect.code-snippets +26 -0
  118. package/.vscode/srcdev-component-price-list.code-snippets +37 -0
  119. package/.vscode/srcdev-component-pricing-card.code-snippets +2 -2
  120. package/.vscode/srcdev-component-profile-section.code-snippets +36 -0
  121. package/.vscode/srcdev-component-samaritan-prompt.code-snippets +60 -0
  122. package/.vscode/srcdev-component-scroll-reveal-frame.code-snippets +36 -0
  123. package/.vscode/srcdev-component-scroll-reveal-image.code-snippets +46 -0
  124. package/.vscode/srcdev-component-services-card.code-snippets +4 -4
  125. package/.vscode/srcdev-component-services-grids.code-snippets +36 -0
  126. package/.vscode/srcdev-component-site-navigation.code-snippets +26 -18
  127. package/.vscode/srcdev-component-slider-gallery.code-snippets +9 -0
  128. package/.vscode/srcdev-component-social-icons-list.code-snippets +24 -0
  129. package/.vscode/srcdev-component-stepper-list.code-snippets +39 -0
  130. package/.vscode/srcdev-component-text-block.code-snippets +31 -0
  131. package/.vscode/srcdev-component-toggle-switch.code-snippets +3 -1
  132. package/.vscode/srcdev-component-triple-toggle-switch.code-snippets +30 -0
  133. package/README.md +2 -2
  134. package/app/app.config.ts +10 -0
  135. package/app/assets/styles/setup/02.colours/_orange.css +11 -11
  136. package/app/assets/styles/setup/02.colours/_theme-params.css +2 -2
  137. package/app/assets/styles/setup/03.theming/_default.css +1 -22
  138. package/app/assets/styles/setup/03.theming/_theme-slots.css +1 -1
  139. package/app/assets/styles/setup/03.theming/_warning.css +8 -10
  140. package/app/assets/styles/setup/04.elements/forms/02.typography.css +0 -14
  141. package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +1 -1
  142. package/app/assets/styles/setup/index.css +1 -1
  143. package/app/components/01.atoms/alert-mask/AlertMaskCore.vue +23 -5
  144. package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +23 -5
  145. package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +45 -19
  146. package/app/components/01.atoms/alert-mask/tests/AlertMaskCore.spec.ts +35 -1
  147. package/app/components/01.atoms/animations/animated-svg-text/CONSUMER-STYLING.md +13 -0
  148. package/app/components/01.atoms/animations/clip-element/CONSUMER-STYLING.md +13 -0
  149. package/app/components/01.atoms/animations/clip-element/ClipElement.vue +2 -2
  150. package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +26 -5
  151. package/app/components/01.atoms/animations/entry/.nuxt/app.config.mjs +21 -0
  152. package/app/components/01.atoms/animations/entry/.nuxt/components.d.ts +66 -0
  153. package/app/components/01.atoms/animations/entry/.nuxt/imports.d.ts +30 -0
  154. package/app/components/01.atoms/animations/entry/.nuxt/manifest/meta/test.json +1 -0
  155. package/app/components/01.atoms/animations/entry/.nuxt/types/app.config.d.ts +35 -0
  156. package/app/components/01.atoms/animations/entry/.nuxt/types/build.d.ts +23 -0
  157. package/app/components/01.atoms/animations/entry/.nuxt/types/builder-env.d.ts +1 -0
  158. package/app/components/01.atoms/animations/entry/.nuxt/types/components.d.ts +71 -0
  159. package/app/components/01.atoms/animations/entry/.nuxt/types/imports.d.ts +386 -0
  160. package/app/components/01.atoms/animations/entry/.nuxt/types/middleware.d.ts +11 -0
  161. package/app/components/01.atoms/animations/entry/.nuxt/types/modules.d.ts +79 -0
  162. package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-layouts.d.ts +17 -0
  163. package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-nuxt.d.ts +64 -0
  164. package/app/components/01.atoms/animations/entry/.nuxt/types/plugins.d.ts +29 -0
  165. package/app/components/01.atoms/animations/entry/.nuxt/types/runtime-config.d.ts +32 -0
  166. package/app/components/01.atoms/animations/entry/.nuxt/types/shared-imports.d.ts +10 -0
  167. package/app/components/01.atoms/animations/entry/.nuxt/types/vue-shim.d.ts +0 -0
  168. package/app/components/01.atoms/animations/entry/.nuxtrc +1 -0
  169. package/app/components/01.atoms/animations/entry/CONSUMER-STYLING.md +65 -0
  170. package/app/components/01.atoms/animations/entry/EntryAnimation.vue +6 -5
  171. package/app/components/01.atoms/animations/entry/node_modules/.cache/nuxt/chrome-workspace.json +1 -0
  172. package/app/components/01.atoms/animations/entry/node_modules/.cache/vite/client/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  173. package/app/components/01.atoms/animations/entry/stories/EntryAnimation.stories.ts +1 -1
  174. package/app/components/01.atoms/animations/entry/tests/EntryAnimation.spec.ts +25 -0
  175. package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +24 -5
  176. package/app/components/01.atoms/animations/marquee-scroller/CONSUMER-STYLING.md +20 -0
  177. package/app/components/01.atoms/animations/rotating-carousel-image/CONSUMER-STYLING.md +17 -0
  178. package/app/components/01.atoms/animations/scroll-reveal-frame/CONSUMER-STYLING.md +77 -0
  179. package/app/components/01.atoms/animations/scroll-reveal-frame/ScrollRevealFrame.vue +37 -78
  180. package/app/components/01.atoms/animations/scroll-reveal-frame/stories/ScrollRevealFrame.stories.ts +48 -0
  181. package/app/components/01.atoms/animations/scroll-reveal-frame/tests/ScrollRevealFrame.spec.ts +40 -33
  182. package/app/components/01.atoms/animations/scroll-reveal-frame/tests/__snapshots__/ScrollRevealFrame.spec.ts.snap +4 -4
  183. package/app/components/01.atoms/animations/scroll-reveal-image/CONSUMER-STYLING.md +74 -0
  184. package/app/components/01.atoms/animations/scroll-reveal-image/ScrollRevealImage.vue +14 -44
  185. package/app/components/01.atoms/animations/scroll-reveal-image/stories/ScrollRevealImage.stories.ts +50 -1
  186. package/app/components/01.atoms/animations/scroll-reveal-image/tests/ScrollRevealImage.spec.ts +27 -20
  187. package/app/components/01.atoms/animations/scroll-reveal-image/tests/__snapshots__/ScrollRevealImage.spec.ts.snap +4 -4
  188. package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +21 -4
  189. package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +25 -0
  190. package/app/components/01.atoms/banner-video/CONSUMER-STYLING.md +12 -5
  191. package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +20 -7
  192. package/app/components/01.atoms/canvas-switcher/CanvasSwitcher.vue +12 -7
  193. package/app/components/01.atoms/card/CONSUMER-STYLING.md +47 -42
  194. package/app/components/01.atoms/card/CardCore.vue +7 -17
  195. package/app/components/01.atoms/clipped-panel/CONSUMER-STYLING.md +13 -0
  196. package/app/components/01.atoms/content-wrappers/docs-pages/CONSUMER-STYLING.md +127 -0
  197. package/app/components/01.atoms/content-wrappers/docs-pages/ContentDocs.vue +44 -77
  198. package/app/components/01.atoms/content-wrappers/docs-pages/stories/ContentDocs.stories.ts +3 -3
  199. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +14 -1
  200. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts +2 -0
  201. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +13 -0
  202. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts +2 -0
  203. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/CONSUMER-STYLING.md +72 -0
  204. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/LayoutGridByCols.vue +26 -25
  205. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/stories/LayoutGridByCols.stories.ts +91 -107
  206. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/LayoutGridByCols.spec.ts +50 -15
  207. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +5 -5
  208. package/app/components/01.atoms/display-banner/CONSUMER-STYLING.md +13 -0
  209. package/app/components/01.atoms/display-dialog/CONSUMER-STYLING.md +82 -54
  210. package/app/components/01.atoms/display-dialog/DisplayDialog.vue +38 -45
  211. package/app/components/01.atoms/display-dialog/stories/DisplayDialog.stories.ts +25 -0
  212. package/app/components/01.atoms/display-dialog/tests/DisplayDialog.spec.ts +21 -0
  213. package/app/components/01.atoms/display-pill/CONSUMER-STYLING.md +112 -0
  214. package/app/components/01.atoms/display-pill/DisplayPill.vue +88 -50
  215. package/app/components/01.atoms/display-pill/stories/DisplayPill.stories.ts +56 -3
  216. package/app/components/01.atoms/display-pill/tests/DisplayPill.spec.ts +104 -4
  217. package/app/components/01.atoms/display-pill/tests/__snapshots__/DisplayPill.spec.ts.snap +3 -3
  218. package/app/components/01.atoms/display-tooltip/CONSUMER-STYLING.md +22 -2
  219. package/app/components/01.atoms/display-tooltip/DisplayTooltip.vue +18 -26
  220. package/app/components/01.atoms/glass-panel/CONSUMER-STYLING.md +91 -0
  221. package/app/components/01.atoms/glass-panel/GlassPanel.vue +34 -30
  222. package/app/components/01.atoms/glass-panel/stories/GlassPanel.stories.ts +121 -0
  223. package/app/components/01.atoms/glass-panel/tests/GlassPanel.spec.ts +61 -0
  224. package/app/components/01.atoms/grids/auto-grid/AutoGrid.vue +5 -10
  225. package/app/components/01.atoms/grids/auto-grid/CONSUMER-STYLING.md +76 -0
  226. package/app/components/01.atoms/grids/auto-grid/stories/AutoGrid.stories.ts +5 -4
  227. package/app/components/01.atoms/grids/auto-grid/tests/AutoGrid.spec.ts +8 -0
  228. package/app/components/01.atoms/grids/column-flow-grid/CONSUMER-STYLING.md +11 -2
  229. package/app/components/01.atoms/grids/grid-stack/CONSUMER-STYLING.md +76 -0
  230. package/app/components/01.atoms/grids/grid-stack/GridStack.vue +6 -1
  231. package/app/components/01.atoms/grids/grid-stack/stories/GridStack.stories.ts +1 -1
  232. package/app/components/01.atoms/grids/grid-stack/tests/GridStack.spec.ts +35 -0
  233. package/app/components/01.atoms/grids/masonry-grid/CONSUMER-STYLING.md +11 -2
  234. package/app/components/01.atoms/navigation/breadcrumb/Breadcrumb.vue +5 -10
  235. package/app/components/01.atoms/navigation/breadcrumb/CONSUMER-STYLING.md +15 -0
  236. package/app/components/01.atoms/navigation/skip-links/CONSUMER-STYLING.md +13 -0
  237. package/app/components/01.atoms/navigation/tabs/CONSUMER-STYLING.md +21 -0
  238. package/app/components/01.atoms/page-row/CONSUMER-STYLING.md +46 -8
  239. package/app/components/01.atoms/page-row/PageRow.vue +17 -13
  240. package/app/components/01.atoms/page-row/stories/PageRow.stories.ts +8 -0
  241. package/app/components/01.atoms/page-row/tests/PageRow.spec.ts +7 -11
  242. package/app/components/01.atoms/pop-over/CONSUMER-STYLING.md +13 -0
  243. package/app/components/01.atoms/qr-code/CONSUMER-STYLING.md +48 -0
  244. package/app/components/01.atoms/qr-code/DisplayQrCode.vue +5 -1
  245. package/app/components/01.atoms/qr-code/stories/DisplayQrCode.stories.ts +11 -3
  246. package/app/components/01.atoms/qr-code/tests/DisplayQrCode.spec.ts +15 -0
  247. package/app/components/01.atoms/text-block/CONSUMER-STYLING.md +49 -0
  248. package/app/components/01.atoms/text-block/TextBlock.vue +13 -5
  249. package/app/components/01.atoms/text-block/stories/TextBlock.stories.ts +84 -0
  250. package/app/components/01.atoms/text-block/tests/TextBlock.spec.ts +78 -0
  251. package/app/components/01.atoms/text-block/tests/__snapshots__/TextBlock.spec.ts.snap +7 -0
  252. package/app/components/01.atoms/text-blocks/eyebrow-text/CONSUMER-STYLING.md +56 -0
  253. package/app/components/01.atoms/text-blocks/eyebrow-text/EyebrowText.vue +10 -5
  254. package/app/components/01.atoms/text-blocks/eyebrow-text/tests/EyebrowText.spec.ts +11 -0
  255. package/app/components/01.atoms/text-blocks/header-block/CONSUMER-STYLING.md +16 -1
  256. package/app/components/01.atoms/text-blocks/hero-text/CONSUMER-STYLING.md +74 -0
  257. package/app/components/01.atoms/text-blocks/hero-text/HeroText.vue +14 -9
  258. package/app/components/01.atoms/text-blocks/hero-text/tests/HeroText.spec.ts +11 -0
  259. package/app/components/01.atoms/text-blocks/link-text/CONSUMER-STYLING.md +45 -0
  260. package/app/components/01.atoms/text-blocks/link-text/LinkText.vue +15 -8
  261. package/app/components/01.atoms/text-blocks/link-text/tests/LinkText.spec.ts +11 -0
  262. package/app/components/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +13 -0
  263. package/app/components/02.molecules/action-menu/ActionMenu.vue +28 -30
  264. package/app/components/02.molecules/action-menu/{ActionMenuItemCore.vue → ActionMenuItem.vue} +12 -14
  265. package/app/components/02.molecules/action-menu/CONSUMER-STYLING.md +90 -76
  266. package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +48 -41
  267. package/app/components/02.molecules/action-menu/tests/ActionMenu.spec.ts +46 -1
  268. package/app/components/02.molecules/action-menu/tests/{ActionMenuItemCore.spec.ts → ActionMenuItem.spec.ts} +11 -5
  269. package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItem.spec.ts.snap +27 -0
  270. package/app/components/02.molecules/alert-content/AlertContent.vue +17 -8
  271. package/app/components/02.molecules/alert-content/AlertContentInner.vue +57 -30
  272. package/app/components/02.molecules/alert-content/CONSUMER-STYLING.md +84 -0
  273. package/app/components/02.molecules/alert-content/stories/AlertContent.stories.ts +39 -0
  274. package/app/components/02.molecules/alert-content/tests/AlertContent.spec.ts +32 -0
  275. package/app/components/02.molecules/alert-content/tests/AlertContentInner.spec.ts +32 -0
  276. package/app/components/02.molecules/alert-masked-content/AlertMaskedContent.vue +9 -5
  277. package/app/components/02.molecules/alert-masked-content/CONSUMER-STYLING.md +73 -0
  278. package/app/components/02.molecules/alert-masked-content/stories/AlertMaskedContent.stories.ts +91 -10
  279. package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +52 -0
  280. package/app/components/02.molecules/cookie-consent-banner/CONSUMER-STYLING.md +95 -0
  281. package/app/components/02.molecules/cookie-consent-banner/CookieConsentBanner.vue +149 -0
  282. package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/stories/CookieConsentBanner.stories.ts +22 -3
  283. package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/tests/CookieConsentBanner.spec.ts +81 -4
  284. package/app/components/02.molecules/display-avatar/CONSUMER-STYLING.md +63 -0
  285. package/app/components/02.molecules/display-avatar/DisplayAvatar.vue +120 -0
  286. package/app/components/{01.atoms → 02.molecules}/display-avatar/stories/DisplayAvatar.stories.ts +56 -14
  287. package/app/components/{01.atoms → 02.molecules}/display-avatar/tests/DisplayAvatar.spec.ts +43 -11
  288. package/app/components/02.molecules/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +11 -0
  289. package/app/components/02.molecules/display-chip/CONSUMER-STYLING.md +57 -0
  290. package/app/components/02.molecules/display-chip/DisplayChip.vue +50 -83
  291. package/app/components/02.molecules/display-chip/tests/DisplayChip.spec.ts +10 -10
  292. package/app/components/02.molecules/display-chip/tests/__snapshots__/DisplayChip.spec.ts.snap +4 -4
  293. package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +25 -4
  294. package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +9 -6
  295. package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +6 -1
  296. package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +10 -1
  297. package/app/components/02.molecules/display-tooltip-defined/CONSUMER-STYLING.md +11 -0
  298. package/app/components/02.molecules/expandable/accordian/CONSUMER-STYLING.md +11 -4
  299. package/app/components/02.molecules/expandable/expanding-panel/CONSUMER-STYLING.md +12 -5
  300. package/app/components/02.molecules/expandable/expanding-panel-classic/CONSUMER-STYLING.md +12 -5
  301. package/app/components/02.molecules/input-copy/CONSUMER-STYLING.md +12 -5
  302. package/app/components/02.molecules/input-copy/InputCopy.vue +12 -25
  303. package/app/components/02.molecules/input-copy/stories/InputCopy.stories.ts +1 -1
  304. package/app/components/02.molecules/input-copy/tests/InputCopy.spec.ts +1 -1
  305. package/app/components/02.molecules/navigation/deep-expanding-menu/CONSUMER-STYLING.md +13 -0
  306. package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md +11 -0
  307. package/app/components/02.molecules/navigation/site-navigation/CONSUMER-STYLING.md +109 -0
  308. package/app/components/02.molecules/navigation/site-navigation/SiteNavigation.vue +37 -55
  309. package/app/components/02.molecules/navigation/site-navigation/stories/SiteNavigation.stories.ts +22 -1
  310. package/app/components/02.molecules/navigation/site-navigation/tests/SiteNavigation.spec.ts +41 -6
  311. package/app/components/02.molecules/navigation/tab-navigation/CONSUMER-STYLING.md +13 -8
  312. package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +18 -36
  313. package/app/components/02.molecules/navigation/tab-navigation/stories/TabNavigation.stories.ts +1 -1
  314. package/app/components/02.molecules/navigation/tab-navigation/tests/TabNavigation.spec.ts +1 -1
  315. package/app/components/02.molecules/opening-hours/CONSUMER-STYLING.md +134 -0
  316. package/app/components/02.molecules/opening-hours/OpeningHours.vue +352 -0
  317. package/app/components/02.molecules/opening-hours/stories/OpeningHours.stories.ts +127 -0
  318. package/app/components/02.molecules/opening-hours/tests/OpeningHours.spec.ts +228 -0
  319. package/app/components/02.molecules/opening-hours/tests/OpeningHours.structuredData.spec.ts +45 -0
  320. package/app/components/02.molecules/opening-hours/tests/__snapshots__/OpeningHours.spec.ts.snap +23 -0
  321. package/app/components/02.molecules/opening-hours/tests/buildOpeningHoursSpecification.spec.ts +52 -0
  322. package/app/components/02.molecules/price-list/CONSUMER-STYLING.md +106 -0
  323. package/app/components/02.molecules/price-list/PriceList.vue +48 -40
  324. package/app/components/02.molecules/price-list/stories/PriceList.stories.ts +15 -2
  325. package/app/components/02.molecules/price-list/tests/PriceList.spec.ts +39 -2
  326. package/app/components/02.molecules/price-list/tests/__snapshots__/PriceList.spec.ts.snap +4 -16
  327. package/app/components/02.molecules/pricing-card/CONSUMER-STYLING.md +12 -5
  328. package/app/components/02.molecules/pricing-card/PricingCard.vue +28 -60
  329. package/app/components/02.molecules/pricing-card/tests/PricingCard.spec.ts +1 -1
  330. package/app/components/02.molecules/profile-section/CONSUMER-STYLING.md +53 -0
  331. package/app/components/02.molecules/profile-section/ProfileSection.vue +53 -66
  332. package/app/components/02.molecules/profile-section/tests/ProfileSection.spec.ts +4 -4
  333. package/app/components/02.molecules/profile-section/tests/__snapshots__/ProfileSection.spec.ts.snap +6 -12
  334. package/app/components/02.molecules/prompt/CONSUMER-STYLING.md +51 -0
  335. package/app/components/{01.atoms → 02.molecules}/prompt/DisplayPrompt.vue +23 -8
  336. package/app/components/{01.atoms → 02.molecules}/prompt/stories/DisplayPrompt.stories.ts +18 -1
  337. package/app/components/{01.atoms → 02.molecules}/prompt/tests/DisplayPrompt.spec.ts +37 -7
  338. package/app/components/02.molecules/qr-code/CONSUMER-STYLING.md +66 -0
  339. package/app/components/02.molecules/qr-code/CaptureQrCode.vue +31 -12
  340. package/app/components/02.molecules/qr-code/DecodeQrCode.vue +55 -19
  341. package/app/components/02.molecules/qr-code/stories/CaptureQrCode.stories.ts +56 -0
  342. package/app/components/02.molecules/qr-code/stories/DecodeQrCode.stories.ts +53 -0
  343. package/app/components/02.molecules/qr-code/tests/CaptureQrCode.spec.ts +68 -20
  344. package/app/components/02.molecules/qr-code/tests/DecodeQrCode.spec.ts +44 -8
  345. package/app/components/02.molecules/samaritan-prompt/CONSUMER-STYLING.md +118 -0
  346. package/app/components/02.molecules/samaritan-prompt/SamaritanPrompt.vue +108 -51
  347. package/app/components/02.molecules/samaritan-prompt/SamaritanPromptMixed.vue +63 -62
  348. package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPrompt.stories.ts +129 -0
  349. package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPromptMixed.stories.ts +124 -0
  350. package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPrompt.spec.ts +66 -0
  351. package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPromptMixed.spec.ts +95 -17
  352. package/app/components/02.molecules/select-menu/CONSUMER-STYLING.md +11 -2
  353. package/app/components/02.molecules/social-icons-list/CONSUMER-STYLING.md +43 -0
  354. package/app/components/02.molecules/social-icons-list/SocialIconsList.vue +15 -15
  355. package/app/components/02.molecules/social-icons-list/stories/SocialIconsList.stories.ts +6 -1
  356. package/app/components/02.molecules/social-icons-list/tests/SocialIconsList.spec.ts +22 -1
  357. package/app/components/02.molecules/social-icons-list/tests/__snapshots__/SocialIconsList.spec.ts.snap +3 -3
  358. package/app/components/02.molecules/stepper-list/CONSUMER-STYLING.md +44 -5
  359. package/app/components/02.molecules/stepper-list/StepperList.vue +23 -43
  360. package/app/components/02.molecules/stepper-list/tests/StepperList.spec.ts +9 -0
  361. package/app/components/{01.atoms → 02.molecules}/toast/CONSUMER-STYLING.md +14 -0
  362. package/app/components/{01.atoms → 02.molecules}/toast/DisplayToast.vue +1 -2
  363. package/app/components/{01.atoms → 02.molecules}/toast/DisplayToastProvider.vue +1 -2
  364. package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToast.stories.ts +1 -1
  365. package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToastProvider.stories.ts +1 -1
  366. package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +13 -0
  367. package/app/components/03.organisms/image-galleries/slider-gallery/CONSUMER-STYLING.md +137 -0
  368. package/app/components/03.organisms/image-galleries/slider-gallery/SliderGallery.vue +378 -343
  369. package/app/components/03.organisms/image-galleries/slider-gallery/stories/SliderGallery.stories.ts +26 -1
  370. package/app/components/03.organisms/image-galleries/slider-gallery/tests/SliderGallery.spec.ts +102 -23
  371. package/app/components/03.organisms/image-galleries/slider-gallery/tests/__snapshots__/SliderGallery.spec.ts.snap +44 -44
  372. package/app/components/03.organisms/responsive-header/CONSUMER-STYLING.md +12 -1
  373. package/app/components/03.organisms/responsive-header/ResponsiveHeader.vue +0 -4
  374. package/app/components/03.organisms/services/service-detail/CONSUMER-STYLING.md +24 -3
  375. package/app/components/03.organisms/services/service-detail/ServiceDetail.vue +3 -3
  376. package/app/components/03.organisms/services/service-detail/stories/ServiceDetail.stories.ts +13 -13
  377. package/app/components/03.organisms/services/service-detail/tests/__snapshots__/ServiceDetail.spec.ts.snap +1 -1
  378. package/app/components/03.organisms/services/service-summary/CONSUMER-STYLING.md +24 -7
  379. package/app/components/03.organisms/services/service-summary/ServiceSummary.vue +3 -3
  380. package/app/components/03.organisms/services/service-summary/stories/ServiceSummary.stories.ts +1 -1
  381. package/app/components/03.organisms/services/service-summary/tests/__snapshots__/ServiceSummary.spec.ts.snap +1 -1
  382. package/app/components/03.organisms/services/services-card/CONSUMER-STYLING.md +11 -2
  383. package/app/components/03.organisms/services/services-card/ServicesCard.vue +17 -26
  384. package/app/components/03.organisms/services/services-card/tests/ServicesCard.spec.ts +21 -0
  385. package/app/components/03.organisms/services/services-grids/CONSUMER-STYLING.md +50 -0
  386. package/app/components/03.organisms/services/services-grids/ServicesCardGrid.vue +9 -16
  387. package/app/components/03.organisms/services/services-grids/stories/ServicesCardGrid.stories.ts +6 -0
  388. package/app/components/03.organisms/services/services-grids/tests/ServicesCardGrid.spec.ts +18 -0
  389. package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServiceSummaryGrid.spec.ts.snap +3 -3
  390. package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServicesCardGrid.spec.ts.snap +3 -3
  391. package/app/components/03.organisms/site-header/CONSUMER-STYLING.md +12 -1
  392. package/app/components/04.templates/page-hero-highlights/CONSUMER-STYLING.md +103 -0
  393. package/app/components/04.templates/page-hero-highlights/PageHeroHighlights.vue +144 -193
  394. package/app/components/04.templates/page-hero-highlights/PageHeroHighlightsHeader.vue +27 -37
  395. package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlights.stories.ts +56 -60
  396. package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlightsHeader.stories.ts +2 -2
  397. package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlights.spec.ts +10 -10
  398. package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlightsHeader.spec.ts +7 -7
  399. package/app/components/04.templates/page-hero-highlights/tests/__snapshots__/PageHeroHighlights.spec.ts.snap +6 -6
  400. package/app/components/05.forms/form-errors/CONSUMER-STYLING.md +112 -0
  401. package/app/components/05.forms/form-errors/InputError.vue +101 -122
  402. package/app/components/05.forms/form-errors/stories/InputError.stories.ts +125 -0
  403. package/app/components/05.forms/form-errors/tests/InputError.spec.ts +82 -31
  404. package/app/components/05.forms/form-field/CONSUMER-STYLING.md +91 -0
  405. package/app/components/05.forms/form-field/FormField.vue +26 -35
  406. package/app/components/05.forms/form-field/stories/FormField.stories.ts +104 -0
  407. package/app/components/05.forms/form-field/tests/FormField.spec.ts +75 -0
  408. package/app/components/05.forms/form-fieldset/CONSUMER-STYLING.md +88 -0
  409. package/app/components/05.forms/form-fieldset/FormFieldset.vue +34 -28
  410. package/app/components/05.forms/form-fieldset/stories/FormFieldset.stories.ts +84 -0
  411. package/app/components/05.forms/form-fieldset/tests/FormFieldset.spec.ts +111 -0
  412. package/app/components/05.forms/form-wrapper/CONSUMER-STYLING.md +101 -0
  413. package/app/components/05.forms/form-wrapper/FormWrapper.vue +32 -15
  414. package/app/components/05.forms/form-wrapper/stories/FormWrapper.stories.ts +75 -0
  415. package/app/components/05.forms/form-wrapper/tests/FormWrapper.spec.ts +57 -0
  416. package/app/components/05.forms/input-button/CONSUMER-STYLING.md +52 -7
  417. package/app/components/05.forms/input-button/{InputButtonCore.vue → InputButton.vue} +60 -18
  418. package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts → input-button.playwright.ts} +5 -5
  419. package/app/components/05.forms/input-button/stories/{InputButtonCore.stories.ts → InputButton.stories.ts} +8 -10
  420. package/app/components/05.forms/input-button/tests/{InputButtonCore.spec.ts → InputButton.spec.ts} +75 -19
  421. package/app/components/05.forms/input-button/tests/__snapshots__/{InputButtonCore.spec.ts.snap → InputButton.spec.ts.snap} +18 -18
  422. package/app/components/05.forms/input-checkbox/CONSUMER-STYLING.md +93 -0
  423. package/app/components/05.forms/input-checkbox/MultipleCheckboxes.vue +19 -25
  424. package/app/components/05.forms/input-checkbox/SingleCheckbox.vue +17 -43
  425. package/app/components/05.forms/input-checkbox/stories/MultipleCheckboxes.stories.ts +104 -0
  426. package/app/components/05.forms/input-checkbox/stories/SingleCheckbox.stories.ts +75 -0
  427. package/app/components/05.forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +91 -53
  428. package/app/components/05.forms/input-checkbox/tests/SingleCheckbox.spec.ts +112 -0
  429. package/app/components/05.forms/input-checkbox-radio/CONSUMER-STYLING.md +115 -35
  430. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadio.vue +158 -0
  431. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioButton.vue +102 -101
  432. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioField.vue +100 -0
  433. package/app/components/05.forms/input-checkbox-radio/stories/{InputCheckboxRadioCore.stories.ts → InputCheckboxRadio.stories.ts} +23 -8
  434. package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioButton.stories.ts +60 -16
  435. package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioField.stories.ts +93 -0
  436. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadio.spec.ts +174 -0
  437. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioButton.spec.ts +87 -0
  438. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioField.spec.ts +87 -0
  439. package/app/components/05.forms/input-description/CONSUMER-STYLING.md +177 -0
  440. package/app/components/05.forms/input-description/InputDescription.vue +45 -24
  441. package/app/components/05.forms/input-description/stories/InputDescription.stories.ts +160 -0
  442. package/app/components/05.forms/input-description/tests/InputDescription.spec.ts +62 -386
  443. package/app/components/05.forms/input-label/CONSUMER-STYLING.md +134 -0
  444. package/app/components/05.forms/input-label/InputLabel.vue +99 -38
  445. package/app/components/05.forms/input-label/stories/InputLabel.stories.ts +236 -0
  446. package/app/components/05.forms/input-label/tests/InputLabel.spec.ts +113 -342
  447. package/app/components/05.forms/input-number/CONSUMER-STYLING.md +16 -7
  448. package/app/components/05.forms/input-number/{InputNumberCore.vue → InputNumber.vue} +6 -6
  449. package/app/components/05.forms/input-number/{variants/InputNumberDefault.vue → InputNumberField.vue} +12 -15
  450. package/app/components/05.forms/input-number/stories/{InputNumberCore.stories.ts → InputNumber.stories.ts} +6 -6
  451. package/app/components/05.forms/input-number/{variants/stories/InputNumberDefault.stories.ts → stories/InputNumberField.stories.ts} +5 -5
  452. package/app/components/05.forms/input-number/tests/{InputNumberCore.spec.ts → InputNumber.spec.ts} +2 -2
  453. package/app/components/05.forms/input-number/{variants/tests/InputNumberDefault.spec.ts → tests/InputNumberField.spec.ts} +8 -8
  454. package/app/components/05.forms/input-radio/CONSUMER-STYLING.md +70 -0
  455. package/app/components/05.forms/input-radio/MultipleRadiobuttons.vue +19 -30
  456. package/app/components/05.forms/input-radio/stories/MultipleRadiobuttons.stories.ts +116 -0
  457. package/app/components/05.forms/input-radio/tests/MultipleRadioButtons.spec.ts +125 -74
  458. package/app/components/05.forms/input-range/CONSUMER-STYLING.md +13 -0
  459. package/app/components/05.forms/input-range/InputRangeCore.vue +1 -1
  460. package/app/components/05.forms/input-range/{variants/InputRangeDefault.vue → InputRangeDefault.vue} +7 -11
  461. package/app/components/05.forms/input-range/{variants/tests → tests}/InputRangeDefault.spec.ts +1 -1
  462. package/app/components/05.forms/input-select/CONSUMER-STYLING.md +11 -2
  463. package/app/components/05.forms/input-select/{variants/InputSelectWithLabel.vue → InputSelectWithLabel.vue} +6 -9
  464. package/app/components/05.forms/input-select/stories/InputSelectWithLabel.stories.ts +1 -1
  465. package/app/components/05.forms/input-text/CONSUMER-STYLING.md +12 -3
  466. package/app/components/05.forms/input-text/{variants/InputPasswordWithLabel.vue → InputPasswordWithLabel.vue} +3 -3
  467. package/app/components/05.forms/input-text/{variants/InputTextAsNumberWithLabel.vue → InputTextAsNumberWithLabel.vue} +12 -15
  468. package/app/components/05.forms/input-text/InputTextCore.vue +8 -11
  469. package/app/components/05.forms/input-text/{variants/InputTextWithLabel.vue → InputTextWithLabel.vue} +9 -10
  470. package/app/components/05.forms/input-text/stories/InputPasswordWithLabel.stories.ts +1 -1
  471. package/app/components/05.forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +1 -1
  472. package/app/components/05.forms/input-text/stories/InputTextWithLabel.stories.ts +1 -1
  473. package/app/components/05.forms/input-text/tests/InputPasswordWithLabel.spec.ts +2 -1
  474. package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +1 -1
  475. package/app/components/05.forms/input-text/tests/InputTextWithLabel.spec.ts +2 -1
  476. package/app/components/05.forms/input-textarea/CONSUMER-STYLING.md +11 -2
  477. package/app/components/05.forms/input-textarea/{variants/InputTextareaWithLabel.vue → InputTextareaWithLabel.vue} +3 -7
  478. package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +1 -1
  479. package/app/components/05.forms/patterns/stories/ContactForm.stories.ts +9 -10
  480. package/app/components/05.forms/patterns/stories/LoginForm.stories.ts +10 -10
  481. package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +246 -101
  482. package/app/components/05.forms/pending-effect/CONSUMER-STYLING.md +92 -0
  483. package/app/components/05.forms/pending-effect/PendingEffect.vue +52 -45
  484. package/app/components/05.forms/pending-effect/stories/PendingEffect.stories.ts +132 -0
  485. package/app/components/05.forms/pending-effect/tests/PendingEffect.spec.ts +67 -0
  486. package/app/components/05.forms/toggle-switch/CONSUMER-STYLING.md +26 -2
  487. package/app/components/05.forms/toggle-switch/ToggleSwitchCore.vue +10 -29
  488. package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabel.vue → ToggleSwitchWithLabel.vue} +25 -12
  489. package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabelInline.vue → ToggleSwitchWithLabelInline.vue} +2 -4
  490. package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +2 -4
  491. package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +4 -1
  492. package/app/components/05.forms/toggle-switch/tests/ToggleSwitchWithLabel.spec.ts +133 -0
  493. package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +75 -62
  494. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitch.vue +243 -0
  495. package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitch.stories.ts +104 -0
  496. package/app/components/05.forms/triple-toggle-switch/tests/TripleToggleSwitch.spec.ts +138 -0
  497. package/app/composables/tests/useCancellableTimer.spec.ts +48 -0
  498. package/app/composables/tests/useMaxChildWidth.spec.ts +67 -0
  499. package/app/composables/useCancellableTimer.ts +27 -7
  500. package/app/composables/useMaxChildWidth.ts +4 -6
  501. package/app/types/app-config.d.ts +10 -0
  502. package/app/types/components/cookie-consent-banner.d.ts +3 -0
  503. package/app/types/components/index.ts +6 -1
  504. package/app/types/components/opening-hours.d.ts +48 -0
  505. package/app/types/components/price-list.d.ts +11 -0
  506. package/app/types/components/profile-section.d.ts +6 -0
  507. package/app/types/components/samaritan-prompt.d.ts +13 -0
  508. package/app/types/components/services-card.d.ts +9 -0
  509. package/app/types/components/slider-gallery.d.ts +2 -0
  510. package/app/types/components/social-icons-list.d.ts +2 -0
  511. package/app/types/forms/types.forms.d.ts +3 -0
  512. package/app/types/forms/types.zodFormControl.d.ts +0 -3
  513. package/app/utils/opening-hours.ts +44 -0
  514. package/nuxt.config.ts +5 -1
  515. package/package.json +2 -2
  516. package/ramps.config.mjs +1 -1
  517. package/.claude/commands/create-commit-message.md +0 -13
  518. package/.claude/commands/create-release-notes.md +0 -34
  519. package/.claude/commands/migrate-component.md +0 -169
  520. package/.claude/commands/run-commit.md +0 -13
  521. package/.claude/component-ledger/artifact-url.txt +0 -1
  522. package/.claude/component-ledger/audit.json +0 -1
  523. package/.claude/component-ledger/build.mjs +0 -164
  524. package/.claude/component-ledger/output.html +0 -569
  525. package/.claude/component-ledger/template.html +0 -569
  526. package/.claude/hooks/check-component-update.sh +0 -95
  527. package/.claude/hooks/refresh-component-ledger.sh +0 -32
  528. package/.claude/settings.json +0 -134
  529. package/.claude/settings.local.json +0 -38
  530. package/.claude/skills/components/alert-content-inner.md +0 -60
  531. package/.claude/skills/components/navigation-horizontal.md +0 -99
  532. package/.claude/skills/components/samaritan-prompt-mixed.md +0 -139
  533. package/app/components/01.atoms/content-wrappers/content-columns-2/ContentColumns2.vue +0 -51
  534. package/app/components/01.atoms/content-wrappers/content-columns-2/stories/ContentColumns2.stories.ts +0 -110
  535. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/ContentColumns2.spec.ts +0 -105
  536. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/__snapshots__/ContentColumns2.spec.ts.snap +0 -14
  537. package/app/components/01.atoms/content-wrappers/content-width/ContentWidth.vue +0 -88
  538. package/app/components/01.atoms/content-wrappers/content-width/stories/ContentWidth.stories.ts +0 -362
  539. package/app/components/01.atoms/content-wrappers/content-width/tests/ContentWidth.spec.ts +0 -132
  540. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
  541. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/LayoutGridByWidth.vue +0 -70
  542. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/stories/LayoutGridByWidth.stories.ts +0 -220
  543. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/LayoutGridByWidth.spec.ts +0 -174
  544. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
  545. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +0 -36
  546. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByWidth.spec.ts.snap +0 -36
  547. package/app/components/01.atoms/cookie-consent-banner/CookieConsentBanner.vue +0 -148
  548. package/app/components/01.atoms/display-avatar/DisplayAvatar.vue +0 -130
  549. package/app/components/01.atoms/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +0 -11
  550. package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItemCore.spec.ts.snap +0 -27
  551. package/app/components/02.molecules/navigation/navigation-horizontal/NavigationHorizontal.vue +0 -162
  552. package/app/components/02.molecules/navigation/navigation-horizontal/stories/NavigationHorizontal.stories.ts +0 -373
  553. package/app/components/02.molecules/navigation/navigation-horizontal/tests/NavigationHorizontal.spec.ts +0 -152
  554. package/app/components/02.molecules/navigation/navigation-horizontal/tests/__snapshots__/NavigationHorizontal.spec.ts.snap +0 -17
  555. package/app/components/02.molecules/qr-code/stories/QrCode.stories.ts +0 -101
  556. package/app/components/03.organisms/colour-finder/ColourFinder.vue +0 -1519
  557. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioCore.vue +0 -202
  558. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +0 -105
  559. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioCore.spec.ts +0 -320
  560. package/app/components/05.forms/toggle-switch/variants/tests/ToggleSwitchWithLabel.spec.ts +0 -77
  561. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +0 -314
  562. package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitchCore.stories.ts +0 -63
  563. package/.vscode/{srcdev-component-dialog.code-snippets → srcdev-component-display-dialog.code-snippets} +0 -0
  564. package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToast.spec.ts +1 -1
  565. /package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToastProvider.spec.ts +0 -0
  566. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-chromium-darwin.png +0 -0
  567. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-firefox-darwin.png +0 -0
  568. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-webkit-darwin.png +0 -0
  569. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-chromium-darwin.png +0 -0
  570. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-firefox-darwin.png +0 -0
  571. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-webkit-darwin.png +0 -0
  572. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-chromium-darwin.png +0 -0
  573. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-firefox-darwin.png +0 -0
  574. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-webkit-darwin.png +0 -0
  575. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-chromium-darwin.png +0 -0
  576. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-firefox-darwin.png +0 -0
  577. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-webkit-darwin.png +0 -0
  578. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-chromium-darwin.png +0 -0
  579. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-firefox-darwin.png +0 -0
  580. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-webkit-darwin.png +0 -0
  581. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-chromium-darwin.png +0 -0
  582. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-firefox-darwin.png +0 -0
  583. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-chromium-darwin.png +0 -0
  584. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-firefox-darwin.png +0 -0
  585. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-webkit-darwin.png +0 -0
  586. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-chromium-darwin.png +0 -0
  587. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-firefox-darwin.png +0 -0
  588. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-webkit-darwin.png +0 -0
  589. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-chromium-darwin.png +0 -0
  590. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-firefox-darwin.png +0 -0
  591. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-webkit-darwin.png +0 -0
  592. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-chromium-darwin.png +0 -0
  593. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-firefox-darwin.png +0 -0
  594. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-webkit-darwin.png +0 -0
  595. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-chromium-darwin.png +0 -0
  596. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-firefox-darwin.png +0 -0
  597. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-webkit-darwin.png +0 -0
  598. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-chromium-darwin.png +0 -0
  599. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-firefox-darwin.png +0 -0
  600. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-webkit-darwin.png +0 -0
  601. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-chromium-darwin.png +0 -0
  602. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-firefox-darwin.png +0 -0
  603. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-webkit-darwin.png +0 -0
  604. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-webkit-darwin.png +0 -0
  605. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-chromium-darwin.png +0 -0
  606. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-firefox-darwin.png +0 -0
  607. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-webkit-darwin.png +0 -0
  608. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-chromium-darwin.png +0 -0
  609. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-firefox-darwin.png +0 -0
  610. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-webkit-darwin.png +0 -0
  611. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-chromium-darwin.png +0 -0
  612. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-firefox-darwin.png +0 -0
  613. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-webkit-darwin.png +0 -0
  614. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-chromium-darwin.png +0 -0
  615. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-firefox-darwin.png +0 -0
  616. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-webkit-darwin.png +0 -0
  617. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-chromium-darwin.png +0 -0
  618. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-firefox-darwin.png +0 -0
  619. /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-webkit-darwin.png +0 -0
  620. /package/app/components/05.forms/input-range/{variants/stories → stories}/InputRangeDefault.stories.ts +0 -0
  621. /package/app/components/05.forms/input-select/{variants/tests → tests}/InputSelectWithLabel.spec.ts +0 -0
  622. /package/app/components/05.forms/input-textarea/{variants/tests → tests}/InputTextareaWithLabel.spec.ts +0 -0
  623. /package/app/components/05.forms/toggle-switch/{variants/tests → tests}/ToggleSwitchWithLabelInline.spec.ts +0 -0
  624. /package/app/types/components/{navigation-horizontal.d.ts → nav-item.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import ServiceDetail from "../ServiceDetail.vue";
2
- import InputButtonCore from "../../../../05.forms/input-button/InputButtonCore.vue";
2
+ import InputButton from "../../../../05.forms/input-button/InputButton.vue";
3
3
  import type { Meta, StoryObj } from "@nuxtjs/storybook";
4
4
  import type { Service } from "~/types/types.services";
5
5
 
@@ -171,7 +171,7 @@ const storyTheme = {
171
171
 
172
172
  export const Default: Story = {
173
173
  render: (args) => ({
174
- components: { ServiceDetail, InputButtonCore },
174
+ components: { ServiceDetail, InputButton },
175
175
  setup() {
176
176
  return { args, balayage, relatedServices, storyTheme };
177
177
  },
@@ -184,13 +184,13 @@ export const Default: Story = {
184
184
  :style="storyTheme"
185
185
  >
186
186
  <template #book-cta>
187
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
187
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
188
188
  </template>
189
189
  <template #sidebar-note>
190
190
  A patch test is required at least 48 hours before any colour treatment.
191
191
  </template>
192
192
  <template #final-cta>
193
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="secondary" />
193
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="secondary" />
194
194
  </template>
195
195
  </ServiceDetail>
196
196
  `,
@@ -208,17 +208,17 @@ export const Default: Story = {
208
208
  export const NoLocationOrRelated: Story = {
209
209
  name: "No Location / No Related Services",
210
210
  render: (args) => ({
211
- components: { ServiceDetail, InputButtonCore },
211
+ components: { ServiceDetail, InputButton },
212
212
  setup() {
213
213
  return { args, balayage, storyTheme };
214
214
  },
215
215
  template: `
216
216
  <ServiceDetail v-bind="args" :service-data="balayage" :style="storyTheme">
217
217
  <template #book-cta>
218
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
218
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
219
219
  </template>
220
220
  <template #final-cta>
221
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="secondary" />
221
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="secondary" />
222
222
  </template>
223
223
  </ServiceDetail>
224
224
  `,
@@ -236,7 +236,7 @@ export const NoLocationOrRelated: Story = {
236
236
  export const CustomBreadcrumbAndHeadings: Story = {
237
237
  name: "Custom Breadcrumb & Headings",
238
238
  render: (args) => ({
239
- components: { ServiceDetail, InputButtonCore },
239
+ components: { ServiceDetail, InputButton },
240
240
  setup() {
241
241
  return { args, balayage, relatedServices, storyTheme };
242
242
  },
@@ -254,10 +254,10 @@ export const CustomBreadcrumbAndHeadings: Story = {
254
254
  :style="storyTheme"
255
255
  >
256
256
  <template #book-cta>
257
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
257
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
258
258
  </template>
259
259
  <template #final-cta>
260
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="secondary" />
260
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="secondary" />
261
261
  </template>
262
262
  </ServiceDetail>
263
263
  `,
@@ -274,14 +274,14 @@ export const CustomBreadcrumbAndHeadings: Story = {
274
274
  export const CustomRelatedServiceLink: Story = {
275
275
  name: "Custom Related Service Link (slot override)",
276
276
  render: (args) => ({
277
- components: { ServiceDetail, InputButtonCore },
277
+ components: { ServiceDetail, InputButton },
278
278
  setup() {
279
279
  return { args, balayage, relatedServices, storyTheme };
280
280
  },
281
281
  template: `
282
282
  <ServiceDetail v-bind="args" :service-data="balayage" :related-services="relatedServices" :style="storyTheme">
283
283
  <template #book-cta>
284
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
284
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="primary" :style-class-passthrough="['mbs-16']" />
285
285
  </template>
286
286
  <template #related-service="{ service }">
287
287
  <a :href="'/services/' + service.slug" style="display:flex;gap:1.2rem;align-items:center;color:inherit;text-decoration:none;">
@@ -290,7 +290,7 @@ export const CustomRelatedServiceLink: Story = {
290
290
  </a>
291
291
  </template>
292
292
  <template #final-cta>
293
- <InputButtonCore tag="a" href="/contact" button-text="Book now" variant="secondary" />
293
+ <InputButton tag="a" href="/contact" button-text="Book now" variant="secondary" />
294
294
  </template>
295
295
  </ServiceDetail>
296
296
  `,
@@ -21,7 +21,7 @@ exports[`ServiceDetail > renders correct HTML structure 1`] = `
21
21
  <h1 id="v-0-0" class="hero-text mb-20 display axis-horizontal">
22
22
  <!--v-if--><span class="text-block-0 normal">Balayage</span>
23
23
  </h1>
24
- <div class="service-detail__hero-pills"><span class="display-pill md neutral"><span class="pill-label">2.5 - 3.5 hours</span></span><span class="display-pill md neutral"><span class="pill-label">From £95</span></span></div>
24
+ <div class="service-detail__hero-pills"><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">2.5 - 3.5 hours</span></span><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">From £95</span></span></div>
25
25
  </div>
26
26
  </div>
27
27
  </div>
@@ -1,3 +1,8 @@
1
+
2
+ > **Changed 2026-09-27**: the background and text-colour tokens never applied before. The pills use
3
+ > `variant="neutral"`, and `DisplayPill`'s neutral rule only read its own neutral tokens, so they rendered
4
+ > as dark slate pills with light text (only the border token worked). `DisplayPill` variants now fall
5
+ > back to the base `--display-pill-*` tokens, so these defaults (transparent, `currentColor`) take effect.
1
6
  # ServiceSummary — Consumer Styling Guide
2
7
 
3
8
  ## Public token API
@@ -39,7 +44,7 @@ where the layout is genuinely two columns side by side.
39
44
  ### Pill colours
40
45
 
41
46
  The duration/price pills are `DisplayPill` instances — `ServiceSummary` maps its own tokens onto
42
- `DisplayPill`'s `--theme-pill-*` custom properties scoped to `.service-summary__pills`:
47
+ `DisplayPill`'s `--display-pill-*` custom properties scoped to `.service-summary__pills`:
43
48
 
44
49
  | Token | Default | Controls |
45
50
  |---|---|---|
@@ -47,12 +52,12 @@ The duration/price pills are `DisplayPill` instances — `ServiceSummary` maps i
47
52
  | `--service-summary-pill-colour` | `currentColor` | Text colour of the pills |
48
53
  | `--service-summary-pill-border-colour` | `currentColor` | Border colour of the pills |
49
54
 
50
- For anything not covered by these (e.g. pill size, font weight), target `--theme-pill-*` directly
55
+ For anything not covered by these (e.g. pill size, font weight), target `--display-pill-*` directly
51
56
  under `.service-summary__pills` — see [display-pill.md](../../../../../.claude/skills/components/display-pill.md).
52
57
 
53
58
  ---
54
59
 
55
- ## Global theming — recommended approach
60
+ ## Global theming
56
61
 
57
62
  Create `assets/styles/setup/07.components/service-summary.css` in the consuming app and
58
63
  set tokens on `:root`. This applies to every `ServiceSummary` across the site.
@@ -68,7 +73,20 @@ set tokens on `:root`. This applies to every `ServiceSummary` across the site.
68
73
 
69
74
  ---
70
75
 
71
- ## Page-scoped overrides
76
+ ## Local overrides
77
+
78
+ Set the tokens above on an element you own (a page or section class, or a class added with
79
+ `:style-class-passthrough`): they inherit down into the component. Keep the block **unlayered** (no
80
+ `@layer` wrapper) so it beats the library's `@layer components`. If your own file uses
81
+ `<style scoped>`, tokens set on your element still work, but selectors that reach inside the component need
82
+ `:deep()`. Patterns and examples: `.claude/skills/component-local-style-override.md`.
83
+
84
+ **Caveat:** don't set `--display-pill-background`, `--display-pill-text-colour` or `--display-pill-border-colour` on an
85
+ ancestor to restyle the pills: `ServiceSummary` re-declares them on `.service-summary__pills`, so an
86
+ ancestor value never lands. Use the `--service-summary-pill-*` tokens, or set other
87
+ `--display-pill-*` tokens on `.service-summary__pills` itself (see **Pill colours** above).
88
+
89
+ ### Page or section
72
90
 
73
91
  Override tokens for a specific section by scoping them under the page or layout wrapper.
74
92
  No `:deep()` is required (component styles are unscoped).
@@ -82,9 +100,7 @@ No `:deep()` is required (component styles are unscoped).
82
100
  }
83
101
  ```
84
102
 
85
- ---
86
-
87
- ## Per-instance overrides via styleClassPassthrough
103
+ ### One instance
88
104
 
89
105
  Use sparingly — prefer global or page-scoped CSS. When a single instance needs a distinct
90
106
  visual style, pass a modifier class:
@@ -114,3 +130,4 @@ visual style, pass a modifier class:
114
130
  - `ServiceSummary` is summary-only — it has no "full mode". For a complete single-service page
115
131
  (process, ideal-for list, FAQs, booking CTA), use
116
132
  [ServiceDetail](../../../../../.claude/skills/components/service-detail.md) instead.
133
+
@@ -173,9 +173,9 @@ watch(
173
173
  gap: var(--service-summary-pills-gap, 0.8rem);
174
174
  margin-block-end: var(--service-summary-pills-margin-block-end, 2rem);
175
175
 
176
- --theme-pill-bg: var(--service-summary-pill-bg, transparent);
177
- --theme-pill-color: var(--service-summary-pill-colour, currentColor);
178
- --theme-pill-border-color: var(--service-summary-pill-border-colour, currentColor);
176
+ --display-pill-background: var(--service-summary-pill-bg, transparent);
177
+ --display-pill-text-colour: var(--service-summary-pill-colour, currentColor);
178
+ --display-pill-border-colour: var(--service-summary-pill-border-colour, currentColor);
179
179
  }
180
180
  }
181
181
  }
@@ -292,7 +292,7 @@ export const RealisticPageContext: Story = {
292
292
  docs: {
293
293
  description: {
294
294
  story:
295
- "Matches the real services listing page (app/pages/services/index.vue in the luxury-locs-by-natasha-nuxt3 project): a page hero (EyebrowText + HeroText inside PageRow/TextBlock) followed by a ServiceSummary. Use ServiceSummaryGrid for the full alternating listing — this story sanity-checks a single instance's layout in context.",
295
+ "Matches a typical services listing page: a page hero (EyebrowText + HeroText inside PageRow/TextBlock) followed by a ServiceSummary. Use ServiceSummaryGrid for the full alternating listing — this story sanity-checks a single instance's layout in context.",
296
296
  },
297
297
  },
298
298
  },
@@ -9,7 +9,7 @@ exports[`ServiceSummary > renders correct HTML structure 1`] = `
9
9
  <h2 id="v-0-0" class="hero-text mb-20 title axis-horizontal">
10
10
  <!--v-if--><span class="text-block-0 normal">Test Service</span>
11
11
  </h2>
12
- <div class="service-summary__pills"><span class="display-pill md neutral"><span class="pill-label">60 mins</span></span><span class="display-pill md neutral"><span class="pill-label">From £50</span></span></div>
12
+ <div class="service-summary__pills"><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">60 mins</span></span><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">From £50</span></span></div>
13
13
  <p class="page-body-normal">What this service is</p>
14
14
  </div>
15
15
  </div>
@@ -82,7 +82,15 @@ the tokens above. See the component skill doc for slot/prop usage examples.
82
82
 
83
83
  ---
84
84
 
85
- ## Per-instance overrides via styleClassPassthrough
85
+ ## Local overrides
86
+
87
+ Set the tokens above on an element you own (a page or section class, or a class added with
88
+ `:style-class-passthrough`): they inherit down into the component. Keep the block **unlayered** (no
89
+ `@layer` wrapper) so it beats the library's `@layer components`. If your own file uses
90
+ `<style scoped>`, tokens set on your element still work, but selectors that reach inside the component need
91
+ `:deep()`. Patterns and examples: `.claude/skills/component-local-style-override.md`.
92
+
93
+ ### One instance
86
94
 
87
95
  Use sparingly — prefer global or page-scoped CSS. When a single instance needs a distinct look:
88
96
 
@@ -110,7 +118,7 @@ cards regardless of each card's description length, without needing CSS subgrid.
110
118
 
111
119
  `.services-card`, `.image-wrapper`, `.details-wrapper`, and `.footer` all set
112
120
  `min-inline-size: 0`. Without it, an unbreakable child — most commonly a long `actions` slot
113
- button label, since `InputButtonCore`'s `.button-text` is `white-space: nowrap` with no
121
+ button label, since `InputButton`'s `.button-text` is `white-space: nowrap` with no
114
122
  ellipsis — forces its content's min-content width up through the flex/grid chain and widens
115
123
  that one card's grid column in `ServicesCardGrid` wider than its siblings. If a card/column
116
124
  ever looks wider than the rest with content cut off at the edge, check for a long unbreakable
@@ -127,3 +135,4 @@ on the widened column, not the cause.
127
135
  - `.meta`'s internal gap (between the duration and price text) is a fixed `1rem`, not a token.
128
136
  - Root element tag, `href`/`external` (whole-card-clickable), `eyebrowConfig`, and `heroConfig`
129
137
  are props, not CSS — see the component skill doc.
138
+
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <component
3
- :is="resolvedTag"
4
- :href="isClickable ? props.href : undefined"
3
+ :is="resolvedTag()"
4
+ :href="isClickable() ? props.href : undefined"
5
5
  class="services-card"
6
- :class="[elementClasses, { 'is-clickable': isClickable }]"
6
+ :class="[elementClasses, { 'is-clickable': isClickable() }]"
7
7
  >
8
8
  <div class="image-wrapper">
9
9
  <NuxtImg :src="serviceData.image" :alt="serviceData.title" loading="lazy" class="image" />
@@ -27,8 +27,8 @@
27
27
  <div class="description">
28
28
  {{ serviceData.shortDescription }}
29
29
  </div>
30
- <div v-if="hasFooter" class="footer">
31
- <div v-if="hasMeta" class="meta">
30
+ <div v-if="hasFooter()" class="footer">
31
+ <div v-if="hasMeta()" class="meta">
32
32
  <div class="meta-duration">
33
33
  <slot name="duration" :service-data="serviceData">{{ durationText }}</slot>
34
34
  </div>
@@ -44,16 +44,7 @@
44
44
 
45
45
  <script setup lang="ts">
46
46
  import type { Service } from "~/types/types.services";
47
-
48
- interface EyebrowConfig {
49
- tag?: "p" | "div" | "span";
50
- fontSize?: "large" | "medium" | "small";
51
- }
52
-
53
- interface HeroConfig {
54
- tag?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
55
- fontSize?: "display" | "title" | "heading" | "subheading" | "label";
56
- }
47
+ import type { ServicesCardEyebrowConfig, ServicesCardHeroConfig } from "~/types/components";
57
48
 
58
49
  interface Props {
59
50
  tag?: "div" | "section" | "article";
@@ -61,11 +52,11 @@ interface Props {
61
52
  href?: string;
62
53
  /**
63
54
  * Force a real browser navigation instead of client-side routing, even for a same-origin
64
- * href starting with "/". See InputButtonCore's `external` prop for the full rationale.
55
+ * href starting with "/". See InputButton's `external` prop for the full rationale.
65
56
  */
66
57
  external?: boolean;
67
- eyebrowConfig?: EyebrowConfig;
68
- heroConfig?: HeroConfig;
58
+ eyebrowConfig?: ServicesCardEyebrowConfig;
59
+ heroConfig?: ServicesCardHeroConfig;
69
60
  /** Overrides serviceData.duration. Ignored if the `duration` slot is used. */
70
61
  durationText?: string;
71
62
  /** Overrides serviceData.price. Ignored if the `price` slot is used. */
@@ -89,21 +80,21 @@ const NuxtLink = resolveComponent("NuxtLink");
89
80
 
90
81
  const durationText = computed(() => props.durationText ?? props.serviceData.duration);
91
82
  const priceText = computed(() => props.priceText ?? props.serviceData.price);
92
- const hasMeta = computed(() => Boolean(slots.duration || slots.price || durationText.value || priceText.value));
83
+ const hasMeta = () => Boolean(slots.duration || slots.price || durationText.value || priceText.value);
93
84
  // Groups the meta row and actions slot so they can be pushed to the bottom of the card as
94
85
  // one unit — keeps them aligned across a row of cards in ServicesCardGrid regardless of how
95
86
  // long each card's description is, without needing per-row CSS subgrid across components.
96
- const hasFooter = computed(() => Boolean(hasMeta.value || slots.actions));
87
+ const hasFooter = () => Boolean(hasMeta() || slots.actions);
97
88
 
98
89
  // Whole card is clickable only when there's no actions slot to hold its own interactive
99
90
  // content (which would otherwise end up nested inside the card's own anchor) and an href is set
100
- const isClickable = computed(() => Boolean(!slots.actions && props.href));
101
- const isInternalLink = computed(() => isClickable.value && props.href!.startsWith("/") && !props.external);
102
- const resolvedTag = computed(() => {
103
- if (!isClickable.value) return props.tag;
104
- if (isInternalLink.value) return NuxtLink;
91
+ const isClickable = () => Boolean(!slots.actions && props.href);
92
+ const isInternalLink = () => isClickable() && props.href!.startsWith("/") && !props.external;
93
+ const resolvedTag = () => {
94
+ if (!isClickable()) return props.tag;
95
+ if (isInternalLink()) return NuxtLink;
105
96
  return "a";
106
- });
97
+ };
107
98
 
108
99
  const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
109
100
 
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect } from "vitest";
2
2
  import { mountSuspended } from "@nuxt/test-utils/runtime";
3
3
  import ServicesCard from "../ServicesCard.vue";
4
+ import { defineComponent, nextTick, ref } from "vue";
4
5
  import type { Service } from "~/types/types.services";
5
6
 
6
7
  // ─── Fixtures ─────────────────────────────────────────────────────────────────
@@ -282,4 +283,24 @@ describe("ServicesCard", () => {
282
283
  expect(wrapper.classes()).not.toContain("original");
283
284
  expect(wrapper.classes()).toContain("updated");
284
285
  });
286
+
287
+ it("stops being a link when an actions slot appears after mount", async () => {
288
+ const Host = defineComponent({
289
+ components: { ServicesCard },
290
+ setup() {
291
+ return { mockService, showActions: ref(false) };
292
+ },
293
+ template: `
294
+ <ServicesCard :service-data="mockService" href="https://example.com/service">
295
+ <template v-if="showActions" #actions><button type="button">Book</button></template>
296
+ </ServicesCard>
297
+ `,
298
+ });
299
+ const wrapper = await mountSuspended(Host);
300
+ expect(wrapper.find("a.is-clickable").exists()).toBe(true);
301
+ (wrapper.vm as unknown as { showActions: boolean }).showActions = true;
302
+ await nextTick();
303
+ expect(wrapper.find("a.is-clickable").exists()).toBe(false);
304
+ expect(wrapper.find("button").exists()).toBe(true);
305
+ });
285
306
  });
@@ -0,0 +1,50 @@
1
+ # ServiceSummaryGrid / ServicesCardGrid — Consumer Styling Guide
2
+
3
+ ## Public token API
4
+
5
+ ### ServiceSummaryGrid
6
+
7
+ | Token | Default | Controls |
8
+ |---|---|---|
9
+ | `--service-summary-grid-row-gap` | `4rem` | Gap between stacked `ServiceSummary` rows |
10
+
11
+ ### ServicesCardGrid
12
+
13
+ | Token | Default | Controls |
14
+ |---|---|---|
15
+ | `--services-card-grid-column-min-width` | `250px` | Minimum card column width before wrapping (capped at the container width) |
16
+ | `--services-card-grid-gap` | `4rem` | Gap between cards |
17
+
18
+ Each item is a full `ServiceSummary` or `ServicesCard`, styled by its own tokens (see
19
+ `03.organisms/services/service-summary/CONSUMER-STYLING.md` and
20
+ `03.organisms/services/services-card/CONSUMER-STYLING.md`). ServicesCardGrid's CTA is
21
+ `InputButton` (`variant="secondary"`).
22
+
23
+ > Changed 2026-09-28: ServicesCardGrid columns use `minmax(min(<min-width>, 100%), 1fr)`, so a
24
+ > single column no longer overflows a container narrower than the minimum width.
25
+
26
+ No private `--_` tokens.
27
+
28
+ ---
29
+
30
+ ## State hooks
31
+
32
+ No state classes. The roots are `.service-summary-grid` and `.services-card-grid`; their children
33
+ are the item components' own roots.
34
+
35
+ ---
36
+
37
+ ## Local overrides
38
+
39
+ Set the tokens above on an element you own (a page or section class, or a class added with
40
+ `:style-class-passthrough`): they inherit down into the component. Keep the block **unlayered** (no
41
+ `@layer` wrapper) so it beats the library's `@layer components`. If your own file uses
42
+ `<style scoped>`, tokens set on your element still work, but selectors that reach inside the component need
43
+ `:deep()`. Patterns and examples: `.claude/skills/component-local-style-override.md`.
44
+
45
+ ---
46
+
47
+ ## Class passthrough
48
+
49
+ `style-class-passthrough` adds classes to each grid's root. Reactive after mount. It doesn't reach
50
+ the individual cards.
@@ -8,16 +8,16 @@
8
8
  :hero-config="heroConfig"
9
9
  >
10
10
  <template #actions="{ serviceData }">
11
- <InputButtonCore
11
+ <InputButton
12
12
  variant="secondary"
13
13
  :button-text="`${buttonTextPrefix} ${serviceData.title}`"
14
14
  :href="`${hrefBase}${serviceData.slug}`"
15
15
  :style-class-passthrough="['mbs-24']"
16
16
  >
17
17
  <template #right>
18
- <Icon name="mdi:arrow-right" class="icon" />
18
+ <Icon :name="buttonIcon" class="icon" aria-hidden="true" />
19
19
  </template>
20
- </InputButtonCore>
20
+ </InputButton>
21
21
  </template>
22
22
  </ServicesCard>
23
23
  </component>
@@ -25,24 +25,16 @@
25
25
 
26
26
  <script setup lang="ts">
27
27
  import type { Service } from "~/types/types.services";
28
-
29
- interface EyebrowConfig {
30
- tag?: "p" | "div" | "span";
31
- fontSize?: "large" | "medium" | "small";
32
- }
33
-
34
- interface HeroConfig {
35
- tag?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
36
- fontSize?: "display" | "title" | "heading" | "subheading" | "label";
37
- }
28
+ import type { ServicesCardEyebrowConfig, ServicesCardHeroConfig } from "~/types/components";
38
29
 
39
30
  interface Props {
40
31
  tag?: "div" | "section" | "main";
41
32
  servicesData: Service[];
42
- eyebrowConfig?: EyebrowConfig;
43
- heroConfig?: HeroConfig;
33
+ eyebrowConfig?: ServicesCardEyebrowConfig;
34
+ heroConfig?: ServicesCardHeroConfig;
44
35
  hrefBase?: string;
45
36
  buttonTextPrefix?: string;
37
+ buttonIcon?: string;
46
38
  styleClassPassthrough?: string | string[];
47
39
  }
48
40
 
@@ -52,6 +44,7 @@ const props = withDefaults(defineProps<Props>(), {
52
44
  heroConfig: () => ({}),
53
45
  hrefBase: "/services/",
54
46
  buttonTextPrefix: "Enquire about",
47
+ buttonIcon: "mdi:arrow-right",
55
48
  styleClassPassthrough: () => [],
56
49
  });
57
50
 
@@ -69,7 +62,7 @@ watch(
69
62
  @layer components {
70
63
  .services-card-grid {
71
64
  display: grid;
72
- grid-template-columns: repeat(auto-fit, minmax(var(--services-card-grid-column-min-width, 250px), 1fr));
65
+ grid-template-columns: repeat(auto-fit, minmax(min(var(--services-card-grid-column-min-width, 250px), 100%), 1fr));
73
66
  gap: var(--services-card-grid-gap, 4rem);
74
67
  }
75
68
  }
@@ -12,6 +12,7 @@ type StoryArgs = {
12
12
  };
13
13
  hrefBase?: string;
14
14
  buttonTextPrefix?: string;
15
+ buttonIcon?: string;
15
16
  styleClassPassthrough?: string | string[];
16
17
  /** Story-only — not a real ServicesCardGrid prop, see useStorySetup below. */
17
18
  lineClamp?: number;
@@ -42,6 +43,10 @@ const meta: Meta<StoryArgs> = {
42
43
  control: { type: "text" },
43
44
  description: "Prefix for each card's CTA button text — appended with the service title",
44
45
  },
46
+ buttonIcon: {
47
+ control: { type: "text" },
48
+ description: "Icon on each card's CTA button",
49
+ },
45
50
  styleClassPassthrough: {
46
51
  control: "object",
47
52
  description: "Additional CSS classes applied to the root element",
@@ -58,6 +63,7 @@ const meta: Meta<StoryArgs> = {
58
63
  heroConfig: {},
59
64
  hrefBase: "/services/",
60
65
  buttonTextPrefix: "Enquire about",
66
+ buttonIcon: "mdi:arrow-right",
61
67
  styleClassPassthrough: [],
62
68
  lineClamp: 3,
63
69
  },
@@ -179,3 +179,21 @@ describe("ServicesCardGrid", () => {
179
179
  expect(wrapper.classes()).toContain("updated");
180
180
  });
181
181
  });
182
+
183
+ describe("ServicesCardGrid button icon", () => {
184
+ const iconName = (wrapper: Awaited<ReturnType<typeof mountSuspended>>) =>
185
+ wrapper.find(".services-card-grid .iconify").classes().find((c: string) => c.includes(":")) ?? "";
186
+
187
+ it("uses the arrow icon by default, hidden from assistive tech", async () => {
188
+ const wrapper = await mountSuspended(ServicesCardGrid, { props: { servicesData: mockServices } });
189
+ expect(iconName(wrapper)).toContain("mdi:arrow-right");
190
+ expect(wrapper.find(".services-card-grid .iconify").attributes("aria-hidden")).toBe("true");
191
+ });
192
+
193
+ it("uses the buttonIcon prop when given", async () => {
194
+ const wrapper = await mountSuspended(ServicesCardGrid, {
195
+ props: { servicesData: mockServices, buttonIcon: "lucide:arrow-right" },
196
+ });
197
+ expect(iconName(wrapper)).toContain("lucide:arrow-right");
198
+ });
199
+ });
@@ -10,7 +10,7 @@ exports[`ServiceSummaryGrid > renders correct HTML structure 1`] = `
10
10
  <h2 id="v-0-0-0" class="hero-text mb-20 title axis-horizontal">
11
11
  <!--v-if--><span class="text-block-0 normal">Locs Installation</span>
12
12
  </h2>
13
- <div class="service-summary__pills"><span class="display-pill md neutral"><span class="pill-label">60 mins</span></span><span class="display-pill md neutral"><span class="pill-label">From £50</span></span></div>
13
+ <div class="service-summary__pills"><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">60 mins</span></span><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">From £50</span></span></div>
14
14
  <p class="page-body-normal">What this service is.</p>
15
15
  </div>
16
16
  </div>
@@ -23,7 +23,7 @@ exports[`ServiceSummaryGrid > renders correct HTML structure 1`] = `
23
23
  <h2 id="v-0-0-1" class="hero-text mb-20 title axis-horizontal">
24
24
  <!--v-if--><span class="text-block-0 normal">Locs Retwist</span>
25
25
  </h2>
26
- <div class="service-summary__pills"><span class="display-pill md neutral"><span class="pill-label">60 mins</span></span><span class="display-pill md neutral"><span class="pill-label">From £50</span></span></div>
26
+ <div class="service-summary__pills"><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">60 mins</span></span><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">From £50</span></span></div>
27
27
  <p class="page-body-normal">What this service is.</p>
28
28
  </div>
29
29
  </div>
@@ -36,7 +36,7 @@ exports[`ServiceSummaryGrid > renders correct HTML structure 1`] = `
36
36
  <h2 id="v-0-0-2" class="hero-text mb-20 title axis-horizontal">
37
37
  <!--v-if--><span class="text-block-0 normal">Colour Treatment</span>
38
38
  </h2>
39
- <div class="service-summary__pills"><span class="display-pill md neutral"><span class="pill-label">60 mins</span></span><span class="display-pill md neutral"><span class="pill-label">From £50</span></span></div>
39
+ <div class="service-summary__pills"><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">60 mins</span></span><span class="display-pill md neutral"><!--v-if--><span class="display-pill-label">From £50</span></span></div>
40
40
  <p class="page-body-normal">What this service is.</p>
41
41
  </div>
42
42
  </div>
@@ -14,7 +14,7 @@ exports[`ServicesCardGrid > renders correct HTML structure 1`] = `
14
14
  <div class="meta">
15
15
  <div class="meta-duration">60 mins</div>
16
16
  <div class="meta-price">£50</div>
17
- </div><a href="/services/locs-installation" data-testid="input-button-core" data-theme="default" class="input-button-core secondary mbs-24 is-link">
17
+ </div><a href="/services/locs-installation" data-testid="input-button" data-theme="default" class="input-button secondary mbs-24 is-link">
18
18
  <!--v-if-->
19
19
  <!--v-if--><span class="button-text">Enquire about Locs Installation</span><span class="btn-icon right"><span class="iconify i-mdi:arrow-right icon" aria-hidden="true"></span></span>
20
20
  <!--v-if-->
@@ -34,7 +34,7 @@ exports[`ServicesCardGrid > renders correct HTML structure 1`] = `
34
34
  <div class="meta">
35
35
  <div class="meta-duration">60 mins</div>
36
36
  <div class="meta-price">£50</div>
37
- </div><a href="/services/locs-retwist" data-testid="input-button-core" data-theme="default" class="input-button-core secondary mbs-24 is-link">
37
+ </div><a href="/services/locs-retwist" data-testid="input-button" data-theme="default" class="input-button secondary mbs-24 is-link">
38
38
  <!--v-if-->
39
39
  <!--v-if--><span class="button-text">Enquire about Locs Retwist</span><span class="btn-icon right"><span class="iconify i-mdi:arrow-right icon" aria-hidden="true"></span></span>
40
40
  <!--v-if-->
@@ -54,7 +54,7 @@ exports[`ServicesCardGrid > renders correct HTML structure 1`] = `
54
54
  <div class="meta">
55
55
  <div class="meta-duration">60 mins</div>
56
56
  <div class="meta-price">£50</div>
57
- </div><a href="/services/colour-treatment" data-testid="input-button-core" data-theme="default" class="input-button-core secondary mbs-24 is-link">
57
+ </div><a href="/services/colour-treatment" data-testid="input-button" data-theme="default" class="input-button secondary mbs-24 is-link">
58
58
  <!--v-if-->
59
59
  <!--v-if--><span class="button-text">Enquire about Colour Treatment</span><span class="btn-icon right"><span class="iconify i-mdi:arrow-right icon" aria-hidden="true"></span></span>
60
60
  <!--v-if-->
@@ -27,7 +27,7 @@ component itself.
27
27
 
28
28
  ---
29
29
 
30
- ## Global theming — recommended approach
30
+ ## Global theming
31
31
 
32
32
  Create `assets/styles/setup/07.components/site-header.css` in the consuming app and set tokens
33
33
  on a scope class matching the one passed via `styleClassPassthrough`:
@@ -52,9 +52,20 @@ on a scope class matching the one passed via `styleClassPassthrough`:
52
52
 
53
53
  ---
54
54
 
55
+ ## Local overrides
56
+
57
+ Set the tokens above on an element you own (a page or section class, or a class added with
58
+ `:style-class-passthrough`): they inherit down into the component. Keep the block **unlayered** (no
59
+ `@layer` wrapper) so it beats the library's `@layer components`. If your own file uses
60
+ `<style scoped>`, tokens set on your element still work, but selectors that reach inside the component need
61
+ `:deep()`. Patterns and examples: `.claude/skills/component-local-style-override.md`.
62
+
63
+ ---
64
+
55
65
  ## Notes
56
66
 
57
67
  - The branding markup (logo image, wordmark, etc.) is entirely consumer-authored via the
58
68
  `#branding` slot — `SiteHeader` has no opinion on brand styling.
59
69
  - `SkipLinks`' hardcoded anchors (`#main-content`, `#footer-content`) expect the consuming
60
70
  layout's main/footer regions to carry those `id`s — unchanged from using `SkipLinks` directly.
71
+