srcdev-nuxt-components 9.6.18 → 9.6.19

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 (56) hide show
  1. package/.claude/rules/consumer/css-relative-colour-calc.md +15 -0
  2. package/.claude/rules/consumer/vue-dynamic-arg-no-spaces.md +16 -0
  3. package/.claude/skills/component-compliance-checklist.md +6 -1
  4. package/.claude/skills/component-dynamic-slots.md +2 -2
  5. package/.claude/skills/component-naming.md +1 -1
  6. package/.claude/skills/components/accordion-chat.md +99 -0
  7. package/.claude/skills/components/accordion-group.md +98 -0
  8. package/.claude/skills/components/action-menu.md +11 -5
  9. package/.claude/skills/components/expanding-panel-classic.md +9 -7
  10. package/.claude/skills/components/expanding-panel.md +9 -8
  11. package/.claude/skills/components/sparkle-effect.md +79 -0
  12. package/.claude/skills/index.md +4 -2
  13. package/.claude/skills/storybook-add-story.md +8 -0
  14. package/.claude/skills/using-component-skills.md +1 -1
  15. package/.vscode/srcdev-component-accordion-chat.code-snippets +42 -0
  16. package/.vscode/srcdev-component-accordion-group.code-snippets +38 -0
  17. package/.vscode/srcdev-component-action-menu.code-snippets +3 -3
  18. package/.vscode/srcdev-component-sparkle-effect.code-snippets +33 -0
  19. package/app/components/01.atoms/animations/sparkle-effect/CONSUMER-STYLING.md +75 -0
  20. package/app/components/01.atoms/animations/sparkle-effect/SparkleEffect.vue +213 -0
  21. package/app/components/01.atoms/animations/sparkle-effect/stories/SparkleEffect.stories.ts +303 -0
  22. package/app/components/01.atoms/animations/sparkle-effect/tests/SparkleEffect.spec.ts +150 -0
  23. package/app/components/01.atoms/content-wrappers/docs-pages/ContentDocs.vue +1 -1
  24. package/app/components/02.molecules/action-menu/ActionMenu.vue +6 -2
  25. package/app/components/02.molecules/action-menu/ActionMenuItem.vue +6 -3
  26. package/app/components/02.molecules/action-menu/CONSUMER-STYLING.md +11 -4
  27. package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +130 -18
  28. package/app/components/02.molecules/expandable/accordion-chat/AccordionChat.vue +227 -0
  29. package/app/components/02.molecules/expandable/accordion-chat/CONSUMER-STYLING.md +150 -0
  30. package/app/components/02.molecules/expandable/accordion-chat/stories/AccordionChat.stories.ts +347 -0
  31. package/app/components/02.molecules/expandable/accordion-chat/tests/AccordionChat.spec.ts +205 -0
  32. package/app/components/02.molecules/expandable/accordion-chat/tests/__snapshots__/AccordionChat.spec.ts.snap +40 -0
  33. package/app/components/02.molecules/expandable/{accordian/AccordianCore.vue → accordion-group/AccordionGroup.vue} +32 -20
  34. package/app/components/02.molecules/expandable/accordion-group/CONSUMER-STYLING.md +66 -0
  35. package/app/components/02.molecules/expandable/accordion-group/stories/AccordionGroup.stories.ts +238 -0
  36. package/app/components/02.molecules/expandable/accordion-group/tests/AccordionGroup.spec.ts +172 -0
  37. package/app/components/02.molecules/expandable/accordion-group/tests/__snapshots__/AccordionGroup.spec.ts.snap +45 -0
  38. package/app/components/02.molecules/expandable/expanding-panel/CONSUMER-STYLING.md +1 -0
  39. package/app/components/02.molecules/expandable/expanding-panel/ExpandingPanel.vue +11 -6
  40. package/app/components/02.molecules/expandable/expanding-panel/stories/ExpandingPanel.stories.ts +82 -1
  41. package/app/components/02.molecules/expandable/expanding-panel/tests/ExpandingPanel.spec.ts +24 -30
  42. package/app/components/02.molecules/expandable/expanding-panel/tests/__snapshots__/ExpandingPanel.spec.ts.snap +8 -8
  43. package/app/components/02.molecules/expandable/expanding-panel-classic/CONSUMER-STYLING.md +1 -0
  44. package/app/components/02.molecules/expandable/expanding-panel-classic/ExpandingPanelClassic.vue +10 -5
  45. package/app/components/02.molecules/expandable/expanding-panel-classic/stories/ExpandingPanelClassic.stories.ts +83 -1
  46. package/app/components/02.molecules/expandable/expanding-panel-classic/tests/ExpandingPanelClassic.spec.ts +24 -30
  47. package/app/components/02.molecules/expandable/expanding-panel-classic/tests/__snapshots__/ExpandingPanelClassic.spec.ts.snap +8 -8
  48. package/app/components/03.organisms/responsive-header/tests/__snapshots__/NavigationItems.spec.ts.snap +2 -2
  49. package/app/components/03.organisms/responsive-header/tests/__snapshots__/ResponsiveHeader.spec.ts.snap +2 -2
  50. package/package.json +1 -1
  51. package/.claude/skills/components/accordian-core.md +0 -180
  52. package/.vscode/srcdev-component-accordian-core.code-snippets +0 -74
  53. package/app/components/02.molecules/expandable/accordian/CONSUMER-STYLING.md +0 -100
  54. package/app/components/02.molecules/expandable/accordian/stories/AccordianCore.stories.ts +0 -272
  55. package/app/components/02.molecules/expandable/accordian/tests/AccordianCore.spec.ts +0 -257
  56. package/app/components/02.molecules/expandable/accordian/tests/__snapshots__/AccordianCore.spec.ts.snap +0 -95
@@ -0,0 +1,227 @@
1
+ <template>
2
+ <div class="accordion-chat" :class="elementClasses">
3
+ <ExpandingPanelClassic
4
+ v-for="index in panelIndexes()"
5
+ :key="index"
6
+ :name
7
+ :animation-duration="animationDuration"
8
+ :style-class-passthrough="['accordion-chat-item']"
9
+ >
10
+ <template #summary>
11
+ <slot :name="`item-${index}-summary`"></slot>
12
+ </template>
13
+ <template #icon>
14
+ <slot :name="`item-${index}-icon`">
15
+ <span class="accordion-chat-icon" aria-hidden="true">
16
+ <Icon name="lucide:plus" class="accordion-chat-icon-glyph" />
17
+ </span>
18
+ </slot>
19
+ </template>
20
+ <template #content>
21
+ <div v-if="slots[`item-${index}-content`]" class="accordion-chat-answer">
22
+ <span v-if="hasAvatar(index)" class="accordion-chat-avatar" aria-hidden="true">
23
+ <slot :name="`item-${index}-avatar`">
24
+ <slot name="avatar">{{ avatarInitials }}</slot>
25
+ </slot>
26
+ </span>
27
+ <div class="accordion-chat-bubble">
28
+ <slot :name="`item-${index}-content`"></slot>
29
+ </div>
30
+ </div>
31
+ </template>
32
+ </ExpandingPanelClassic>
33
+ </div>
34
+ </template>
35
+
36
+ <script setup lang="ts">
37
+ import ExpandingPanelClassic from "../expanding-panel-classic/ExpandingPanelClassic.vue";
38
+
39
+ interface Props {
40
+ name?: string;
41
+ animationDuration?: number;
42
+ avatarLabel?: string;
43
+ showAvatar?: boolean;
44
+ styleClassPassthrough?: string | string[];
45
+ }
46
+
47
+ const props = withDefaults(defineProps<Props>(), {
48
+ name: undefined,
49
+ animationDuration: 300,
50
+ avatarLabel: "",
51
+ showAvatar: true,
52
+ styleClassPassthrough: () => [],
53
+ });
54
+
55
+ const slots = useSlots();
56
+ const SUMMARY_SLOT = /^item-(\d+)-summary$/;
57
+
58
+ const panelIndexes = () =>
59
+ Object.keys(slots)
60
+ .map((slotName) => SUMMARY_SLOT.exec(slotName)?.[1])
61
+ .filter((index): index is string => index !== undefined)
62
+ .map(Number)
63
+ .sort((a, b) => a - b);
64
+
65
+ const toGraphemes = (text: string) =>
66
+ typeof Intl.Segmenter === "function"
67
+ ? Array.from(new Intl.Segmenter(undefined, { granularity: "grapheme" }).segment(text), ({ segment }) => segment)
68
+ : Array.from(text);
69
+
70
+ const avatarInitials = computed(() => toGraphemes(props.avatarLabel.trim()).slice(0, 2).join(""));
71
+
72
+ const hasAvatar = (index: number) =>
73
+ props.showAvatar && Boolean(slots[`item-${index}-avatar`] || slots.avatar || avatarInitials.value);
74
+
75
+ const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
76
+
77
+ watch(
78
+ () => props.styleClassPassthrough,
79
+ () => {
80
+ resetElementClasses(props.styleClassPassthrough);
81
+ }
82
+ );
83
+ </script>
84
+
85
+ <style lang="css">
86
+ @layer components {
87
+ .accordion-chat {
88
+ --_accordion-chat-radius: var(--accordion-chat-radius, 2rem);
89
+ --_accordion-chat-tail-radius: var(--accordion-chat-tail-radius, 0.6rem);
90
+ --_accordion-chat-bubble-max-width: var(--accordion-chat-bubble-max-width, 82%);
91
+ --_accordion-chat-duration: var(--accordion-chat-transition-duration, 200ms);
92
+
93
+ display: grid;
94
+ gap: var(--accordion-chat-gap, 1.4rem);
95
+
96
+ .accordion-chat-item.expanding-panel-classic {
97
+ --expanding-panel-classic-icon-size: var(--accordion-chat-icon-size, 2.2rem);
98
+ --expanding-panel-classic-summary-gap: var(--accordion-chat-question-icon-gap, 1.4rem);
99
+
100
+ .expanding-panel-classic-summary {
101
+ inline-size: fit-content;
102
+ max-inline-size: var(--_accordion-chat-bubble-max-width);
103
+ margin-inline-start: auto;
104
+ padding-block: var(--accordion-chat-question-padding-block, 1.3rem);
105
+ padding-inline: var(--accordion-chat-question-padding-inline, 2rem 1.8rem);
106
+ border: var(--accordion-chat-question-border-width, 0.1rem) solid
107
+ var(--accordion-chat-question-border, transparent);
108
+ border-radius: var(--_accordion-chat-radius);
109
+ border-end-end-radius: var(--_accordion-chat-tail-radius);
110
+ background-color: var(--accordion-chat-question-surface, var(--theme-surface-subtle));
111
+ color: var(--accordion-chat-question-colour, var(--theme-text));
112
+ font-family: var(--accordion-chat-question-font-family, inherit);
113
+ font-size: var(--accordion-chat-question-font-size, 1.6rem);
114
+ font-weight: var(--accordion-chat-question-font-weight, 600);
115
+ line-height: var(--accordion-chat-question-line-height, 1.3);
116
+ transition:
117
+ background-color var(--_accordion-chat-duration),
118
+ color var(--_accordion-chat-duration),
119
+ border-color var(--_accordion-chat-duration);
120
+
121
+ &:focus-visible {
122
+ outline: var(--accordion-chat-focus-ring-width, 0.2rem) solid
123
+ var(--accordion-chat-focus-ring-colour, var(--theme-border-focus));
124
+ outline-offset: 0.2rem;
125
+ }
126
+
127
+ .expanding-panel-classic-details[open] & {
128
+ border-color: var(--accordion-chat-question-border-open, var(--accordion-chat-question-border, transparent));
129
+ background-color: var(--accordion-chat-question-surface-open, var(--theme-surface-inverted));
130
+ color: var(--accordion-chat-question-colour-open, var(--theme-text-inverted));
131
+ }
132
+
133
+ .accordion-chat-icon {
134
+ display: grid;
135
+ place-items: center;
136
+ inline-size: 100%;
137
+ aspect-ratio: 1;
138
+ border-radius: 50%;
139
+ background-color: var(--accordion-chat-icon-surface, rgb(0 0 0 / 0.07));
140
+
141
+ .expanding-panel-classic-details[open] & {
142
+ background-color: var(--accordion-chat-icon-surface-open, rgb(255 255 255 / 0.16));
143
+ rotate: 45deg;
144
+ }
145
+
146
+ @media (prefers-reduced-motion: no-preference) {
147
+ transition:
148
+ background-color var(--_accordion-chat-duration),
149
+ rotate calc(var(--_accordion-chat-duration) * 1.25);
150
+ }
151
+
152
+ .accordion-chat-icon-glyph {
153
+ display: block;
154
+ font-size: var(--accordion-chat-icon-glyph-size, 1.4rem);
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ .accordion-chat-answer {
161
+ display: flex;
162
+ align-items: flex-end;
163
+ gap: var(--accordion-chat-avatar-gap, 1rem);
164
+ padding-block-start: var(--accordion-chat-answer-gap, 1rem);
165
+
166
+ .accordion-chat-avatar {
167
+ flex: none;
168
+ display: grid;
169
+ place-items: center;
170
+ inline-size: var(--accordion-chat-avatar-size, 3rem);
171
+ aspect-ratio: 1;
172
+ overflow: hidden;
173
+ border-radius: 50%;
174
+ background-color: var(--accordion-chat-avatar-surface, var(--theme-surface-inverted));
175
+ color: var(--accordion-chat-avatar-colour, var(--theme-text-inverted));
176
+ font-family: var(--accordion-chat-avatar-font-family, inherit);
177
+ font-size: var(--accordion-chat-avatar-font-size, 1.2rem);
178
+ font-weight: var(--accordion-chat-avatar-font-weight, 600);
179
+ line-height: 1;
180
+ white-space: nowrap;
181
+
182
+ & :where(img, svg) {
183
+ inline-size: 100%;
184
+ block-size: 100%;
185
+ object-fit: cover;
186
+ }
187
+ }
188
+
189
+ .accordion-chat-bubble {
190
+ min-inline-size: 0;
191
+ max-inline-size: var(--_accordion-chat-bubble-max-width);
192
+ padding-block: var(--accordion-chat-answer-padding-block, 1.4rem);
193
+ padding-inline: var(--accordion-chat-answer-padding-inline, 1.8rem);
194
+ border: var(--accordion-chat-answer-border-width, 0.1rem) solid
195
+ var(--accordion-chat-answer-border, var(--theme-surface-subtle));
196
+ border-radius: var(--_accordion-chat-radius);
197
+ border-end-start-radius: var(--_accordion-chat-tail-radius);
198
+ background-color: var(--accordion-chat-answer-surface, var(--theme-text-inverted));
199
+ color: var(--accordion-chat-answer-colour, var(--theme-text));
200
+ font-family: var(--accordion-chat-answer-font-family, inherit);
201
+ font-size: var(--accordion-chat-answer-font-size, 1.55rem);
202
+ font-weight: var(--accordion-chat-answer-font-weight, 400);
203
+ line-height: var(--accordion-chat-answer-line-height, 1.6);
204
+
205
+ & :where(img, video) {
206
+ max-inline-size: 100%;
207
+ block-size: auto;
208
+ }
209
+
210
+ @media (prefers-reduced-motion: no-preference) {
211
+ .expanding-panel-classic-details[open] + .expanding-panel-classic-content & {
212
+ animation: accordion-chat-answer-in var(--accordion-chat-entrance-duration, 260ms) ease-out both;
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+
219
+ @keyframes accordion-chat-answer-in {
220
+ from {
221
+ opacity: 0;
222
+ translate: 0 0.6rem;
223
+ scale: 0.98;
224
+ }
225
+ }
226
+ }
227
+ </style>
@@ -0,0 +1,150 @@
1
+ # AccordionChat — Consumer Styling Guide
2
+
3
+ Every visual property is a token. The defaults take colours from the `--theme-*` slots; the
4
+ Storybook **Default** and **Dark Theme** stories are two complete token sets for the same markup, to
5
+ copy from.
6
+
7
+ ## Public token API
8
+
9
+ ### Layout and shape (resolved on `.accordion-chat`)
10
+
11
+ | Token | Default | Controls |
12
+ |---|---|---|
13
+ | `--accordion-chat-gap` | `1.4rem` | Space between panels |
14
+ | `--accordion-chat-answer-gap` | `1rem` | Space between a question and its answer |
15
+ | `--accordion-chat-bubble-max-width` | `82%` | Maximum width of both bubbles |
16
+ | `--accordion-chat-radius` | `2rem` | Bubble corner radius |
17
+ | `--accordion-chat-tail-radius` | `0.6rem` | The "tail" corner: bottom-end of the question, bottom-start of the answer (logical, so it flips in RTL) |
18
+ | `--accordion-chat-transition-duration` | `200ms` | Question colour change; the icon rotation takes 1.25× this |
19
+ | `--accordion-chat-entrance-duration` | `260ms` | Answer bubble fade-and-settle when it opens |
20
+ | `--accordion-chat-focus-ring-width` | `0.2rem` | Question focus outline width |
21
+ | `--accordion-chat-focus-ring-colour` | `var(--theme-border-focus)` | Question focus outline colour |
22
+
23
+ ### Question bubble (the panel's `summary`)
24
+
25
+ | Token | Default | Controls |
26
+ |---|---|---|
27
+ | `--accordion-chat-question-surface` | `var(--theme-surface-subtle)` | Background, closed |
28
+ | `--accordion-chat-question-colour` | `var(--theme-text)` | Text, closed |
29
+ | `--accordion-chat-question-border` | `transparent` | Border colour, closed |
30
+ | `--accordion-chat-question-surface-open` | `var(--theme-surface-inverted)` | Background, open |
31
+ | `--accordion-chat-question-colour-open` | `var(--theme-text-inverted)` | Text, open |
32
+ | `--accordion-chat-question-border-open` | `var(--accordion-chat-question-border)` | Border colour, open |
33
+ | `--accordion-chat-question-border-width` | `0.1rem` | Border width |
34
+ | `--accordion-chat-question-font-family` | `inherit` | Font family |
35
+ | `--accordion-chat-question-font-size` | `1.6rem` | Font size |
36
+ | `--accordion-chat-question-font-weight` | `600` | Font weight |
37
+ | `--accordion-chat-question-line-height` | `1.3` | Line height |
38
+ | `--accordion-chat-question-padding-block` | `1.3rem` | Vertical padding |
39
+ | `--accordion-chat-question-padding-inline` | `2rem 1.8rem` | Start and end padding |
40
+ | `--accordion-chat-question-icon-gap` | `1.4rem` | Space between the text and the icon |
41
+
42
+ ### Icon (default `+` that turns to `×` when open)
43
+
44
+ | Token | Default | Controls |
45
+ |---|---|---|
46
+ | `--accordion-chat-icon-size` | `2.2rem` | Icon circle size |
47
+ | `--accordion-chat-icon-glyph-size` | `1.4rem` | The `+` glyph size |
48
+ | `--accordion-chat-icon-surface` | `rgb(0 0 0 / 0.07)` | Circle fill, closed |
49
+ | `--accordion-chat-icon-surface-open` | `rgb(255 255 255 / 0.16)` | Circle fill, open |
50
+
51
+ The glyph takes the question's text colour.
52
+
53
+ ### Answer bubble
54
+
55
+ | Token | Default | Controls |
56
+ |---|---|---|
57
+ | `--accordion-chat-answer-surface` | `var(--theme-text-inverted)` | Background (the lightest theme step) |
58
+ | `--accordion-chat-answer-colour` | `var(--theme-text)` | Text |
59
+ | `--accordion-chat-answer-border` | `var(--theme-surface-subtle)` | Border colour |
60
+ | `--accordion-chat-answer-border-width` | `0.1rem` | Border width |
61
+ | `--accordion-chat-answer-font-family` | `inherit` | Font family |
62
+ | `--accordion-chat-answer-font-size` | `1.55rem` | Font size |
63
+ | `--accordion-chat-answer-font-weight` | `400` | Font weight |
64
+ | `--accordion-chat-answer-line-height` | `1.6` | Line height |
65
+ | `--accordion-chat-answer-padding-block` | `1.4rem` | Vertical padding |
66
+ | `--accordion-chat-answer-padding-inline` | `1.8rem` | Horizontal padding |
67
+
68
+ ### Avatar
69
+
70
+ | Token | Default | Controls |
71
+ |---|---|---|
72
+ | `--accordion-chat-avatar-size` | `3rem` | Circle size |
73
+ | `--accordion-chat-avatar-gap` | `1rem` | Space between avatar and bubble |
74
+ | `--accordion-chat-avatar-surface` | `var(--theme-surface-inverted)` | Circle fill |
75
+ | `--accordion-chat-avatar-colour` | `var(--theme-text-inverted)` | Initials colour |
76
+ | `--accordion-chat-avatar-font-family` | `inherit` | Initials font |
77
+ | `--accordion-chat-avatar-font-size` | `1.2rem` | Initials size |
78
+ | `--accordion-chat-avatar-font-weight` | `600` | Initials weight |
79
+
80
+ Private (not public API): `--_accordion-chat-radius`, `--_accordion-chat-tail-radius`,
81
+ `--_accordion-chat-bubble-max-width` and `--_accordion-chat-duration`, each read by several rules.
82
+
83
+ ## State hooks
84
+
85
+ | Selector | Meaning |
86
+ |---|---|
87
+ | `.accordion-chat` | Root |
88
+ | `.accordion-chat-item` | Each panel (an `ExpandingPanelClassic` root) |
89
+ | `.accordion-chat-item .expanding-panel-classic-details[open]` | That panel is open |
90
+ | `.accordion-chat-item .expanding-panel-classic-summary` | Question bubble |
91
+ | `.accordion-chat-icon`, `.accordion-chat-icon-glyph` | Default icon circle and glyph |
92
+ | `.accordion-chat-answer` | Answer row (avatar + bubble), inside the panel's `.inner` |
93
+ | `.accordion-chat-avatar` | Avatar circle (`aria-hidden`) |
94
+ | `.accordion-chat-bubble` | Answer bubble |
95
+
96
+ ## Motion
97
+
98
+ Opening animates the row height (ExpandingPanelClassic, `grid-template-rows`, every browser), then
99
+ the answer bubble fades in and settles from a slight offset. Under `prefers-reduced-motion: reduce`
100
+ the entrance animation and the icon rotation's transition are off; colours still change.
101
+
102
+ ## Local overrides
103
+
104
+ Set the tokens above on an element you own (a page or section class, or a class added with
105
+ `:style-class-passthrough`): they inherit down into the component. Keep the block **unlayered** (no
106
+ `@layer` wrapper) so it beats the library's `@layer components`. If your own file uses
107
+ `<style scoped>`, tokens set on your element still work, but selectors that reach inside the component need
108
+ `:deep()`. Patterns and examples: `.claude/skills/component-local-style-override.md`.
109
+
110
+ **Caveat:** each panel re-declares `--expanding-panel-classic-icon-size` and
111
+ `--expanding-panel-classic-summary-gap` from `--accordion-chat-icon-size` and
112
+ `--accordion-chat-question-icon-gap`, so set those `--accordion-chat-*` tokens; an ancestor's
113
+ `--expanding-panel-classic-*` value for them never lands.
114
+
115
+ ## Recipe: dark, serif theme
116
+
117
+ ```css
118
+ .faq-section {
119
+ --accordion-chat-question-font-family: "Playfair Display", Georgia, serif;
120
+ --accordion-chat-question-font-size: 1.9rem;
121
+ --accordion-chat-question-font-weight: 400;
122
+ --accordion-chat-question-surface: #1a1615;
123
+ --accordion-chat-question-colour: #f2ece2;
124
+ --accordion-chat-question-border: #2b2422;
125
+ --accordion-chat-question-surface-open: #c9a961;
126
+ --accordion-chat-question-colour-open: #14100f;
127
+ --accordion-chat-question-border-open: #c9a961;
128
+ --accordion-chat-icon-surface: rgb(255 255 255 / 0.08);
129
+ --accordion-chat-icon-surface-open: rgb(0 0 0 / 0.12);
130
+ --accordion-chat-answer-surface: #1a1615;
131
+ --accordion-chat-answer-border: #2b2422;
132
+ --accordion-chat-answer-colour: #cbbfb4;
133
+ --accordion-chat-answer-font-weight: 300;
134
+ --accordion-chat-answer-line-height: 1.7;
135
+ --accordion-chat-avatar-surface: #c9a961;
136
+ --accordion-chat-avatar-colour: #14100f;
137
+ --accordion-chat-focus-ring-colour: #c9a961;
138
+ }
139
+ ```
140
+
141
+ ## Class passthrough
142
+
143
+ `style-class-passthrough` adds classes to the root `.accordion-chat` (reactive after mount). Panels
144
+ always get `.accordion-chat-item`.
145
+
146
+ ## Notes
147
+
148
+ - The answer bubble is a wrapper inside the panel's `#content` slot. Never style the panel's
149
+ `.inner` (it must keep `overflow: hidden` and no padding for the row-height animation).
150
+ - Images and videos inside an answer are capped at the bubble's width.