@inchurch/matcha-theme 21.4.0 → 22.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/abstracts/_colors.scss +236 -236
  2. package/abstracts/_elevation.scss +108 -108
  3. package/abstracts/_functions.scss +321 -321
  4. package/abstracts/_media-breakpoint.scss +26 -26
  5. package/abstracts/_theme-api.scss +219 -219
  6. package/abstracts/_typography.scss +128 -128
  7. package/base/_reset.scss +446 -445
  8. package/components/app-page-header.scss +260 -260
  9. package/components/matcha-accordion.scss +293 -293
  10. package/components/matcha-audio-player.scss +31 -31
  11. package/components/matcha-autocomplete.scss +145 -145
  12. package/components/matcha-avatar.scss +440 -301
  13. package/components/matcha-badge.scss +120 -120
  14. package/components/matcha-breadcrumb.scss +231 -231
  15. package/components/matcha-button-toggle.scss +383 -384
  16. package/components/matcha-buttons.scss +913 -913
  17. package/components/matcha-calendar.scss +218 -218
  18. package/components/matcha-cards.scss +230 -230
  19. package/components/matcha-chart-card.scss +53 -53
  20. package/components/matcha-checkbox.scss +255 -255
  21. package/components/matcha-chip.scss +292 -292
  22. package/components/matcha-color-pick.scss +34 -34
  23. package/components/matcha-command-palette.scss +316 -316
  24. package/components/matcha-contact.scss +35 -0
  25. package/components/matcha-crop.scss +406 -406
  26. package/components/matcha-date.scss +81 -81
  27. package/components/matcha-divider.scss +100 -100
  28. package/components/matcha-draggable.scss +23 -23
  29. package/components/matcha-drawer.scss +376 -376
  30. package/components/matcha-drop-image.scss +14 -14
  31. package/components/matcha-drop-list.scss +430 -430
  32. package/components/matcha-emoji.scss +69 -69
  33. package/components/matcha-empty-state.scss +230 -230
  34. package/components/matcha-file-uploader.scss +471 -471
  35. package/components/matcha-flag.scss +103 -103
  36. package/components/matcha-footer.scss +91 -91
  37. package/components/matcha-form-field.scss +606 -606
  38. package/components/matcha-form-section.scss +100 -100
  39. package/components/matcha-header.scss +135 -135
  40. package/components/matcha-highlight.scss +164 -164
  41. package/components/matcha-hint-text.scss +90 -90
  42. package/components/matcha-horizontal-tree.scss +316 -316
  43. package/components/matcha-icon.scss +98 -98
  44. package/components/matcha-image.scss +61 -61
  45. package/components/matcha-list.scss +211 -211
  46. package/components/matcha-menu.scss +99 -99
  47. package/components/matcha-modal.scss +210 -210
  48. package/components/matcha-nav.scss +581 -581
  49. package/components/matcha-notification.scss +413 -413
  50. package/components/matcha-option.scss +170 -170
  51. package/components/matcha-page-builder.scss +4196 -4196
  52. package/components/matcha-paginator.scss +689 -689
  53. package/components/matcha-panel.scss +194 -194
  54. package/components/matcha-profile-card.scss +50 -50
  55. package/components/matcha-progress-bar.scss +313 -313
  56. package/components/matcha-radio.scss +320 -320
  57. package/components/matcha-ripple.scss +7 -7
  58. package/components/matcha-scrollbar.scss +33 -33
  59. package/components/matcha-scrollbox-shadow.scss +120 -120
  60. package/components/matcha-section.scss +102 -102
  61. package/components/matcha-select-multiple.scss +56 -56
  62. package/components/matcha-select.scss +667 -667
  63. package/components/matcha-skeleton.scss +155 -155
  64. package/components/matcha-slide-toggle.scss +369 -369
  65. package/components/matcha-slider.scss +285 -285
  66. package/components/matcha-snack-bar.scss +259 -259
  67. package/components/matcha-spin.scss +164 -164
  68. package/components/matcha-spinner.scss +97 -97
  69. package/components/matcha-status-pill.scss +38 -18
  70. package/components/matcha-stepper.scss +376 -376
  71. package/components/matcha-table-cell.scss +49 -41
  72. package/components/matcha-table.scss +579 -579
  73. package/components/matcha-tabs.scss +600 -600
  74. package/components/matcha-text-editor.scss +105 -105
  75. package/components/matcha-time.scss +33 -33
  76. package/components/matcha-timepicker.scss +13 -13
  77. package/components/matcha-toolbar.scss +359 -359
  78. package/components/matcha-tooltip.scss +224 -224
  79. package/components/matcha-tree-view.scss +257 -257
  80. package/layout/matcha-page-layout.scss +778 -778
  81. package/main.scss +331 -329
  82. package/package.json +1 -1
  83. package/tokens/_animations-tokens.scss +37 -37
  84. package/tokens/_breakpoints-tokens.scss +35 -35
  85. package/tokens/_color-tokens.scss +274 -274
  86. package/tokens/_elevation-tokens.scss +33 -33
  87. package/tokens/_emit-tokens.scss +324 -324
  88. package/tokens/_material-palette.scss +1149 -1149
  89. package/tokens/_primitives.scss +98 -98
  90. package/tokens/_semantic-aliases.scss +120 -120
  91. package/tokens/_spacing-tokens.scss +94 -94
  92. package/tokens/_static-tokens.scss +137 -137
  93. package/tokens/_typography-tokens.scss +65 -65
  94. package/vendors/charts.scss +90 -90
@@ -1,301 +1,440 @@
1
- // =============================================================================
2
- // matcha-avatar.scss — Avatar component (photo, initials, placeholder + status)
3
- // Aligned with Figma Avatar/Matcha: XS(24) SM(32) MD(40) LG(56) XL(80) 2XL(96)
4
- // =============================================================================
5
-
6
- // ── Structural (outside mixin) ──────────────────────────────────────────────
7
-
8
- .matcha-avatar {
9
- display: inline-flex;
10
- align-items: center;
11
- justify-content: center;
12
- position: relative;
13
- // SEM overflow:hidden — o status indicator fica no canto fora do círculo
14
- // visível e seria cortado. A <img> com border-radius inherit já se arredonda
15
- // sozinha; SVG e Initials ficam dentro dos bounds.
16
- border-radius: var(--matcha-radius-pill, 9999px);
17
-
18
- font-weight: var(--matcha-weight-medium, 500);
19
- user-select: none;
20
- flex-shrink: 0;
21
- }
22
-
23
- // =============================================================================
24
- // Ring colored (additive) — controlado pelo [ring] @Input do component.
25
- // 2px solid + halo alpha externo. Não ocupa layout (box-shadow puro).
26
- //
27
- // Aplicado no .matcha-avatar INNER (não no host) porque o inner é quem tem
28
- // width/height/border-radius:pill — box-shadow segue o radius desse elemento
29
- // e renderiza circular. No host (inline default) sairia retangular.
30
- // =============================================================================
31
- matcha-avatar[ring] .matcha-avatar {
32
- box-shadow:
33
- 0 0 0 2px transparent,
34
- 0 0 0 3px var(--matcha-avatar-ring-color, currentColor);
35
- }
36
-
37
- matcha-avatar[ring]:not([ring="neutral"]) .matcha-avatar {
38
- box-shadow:
39
- 0 0 0 2px transparent,
40
- 0 0 0 3px var(--matcha-avatar-ring-color, currentColor),
41
- 0 0 0 5px var(--matcha-avatar-ring-halo, transparent);
42
- }
43
-
44
- // ── Variants (sizes, initials, icon, disabled) — nested em .matcha-avatar pra
45
- // usar `&.matcha-avatar-*` syntax. Bloco separado do base styles (linha 8-21)
46
- // porque matcha-avatar[ring] (acima) é regra absoluta, não nested.
47
- .matcha-avatar {
48
- // ── Sizes — Canonical 5-step scale: tiny 24 · small 40 · medium 56 · large 80 · huge 96.
49
- // Abbreviations kept as @deprecated aliases, mapped BY PIXEL SIZE (old 32px `sm` dropped → tiny).
50
- // NOTE: --matcha-avatar-* tokens still carry the legacy abbreviated names; re-tier them to
51
- // tiny/small/medium/large/huge on the Figma/DSV3 side (token rename is design-driven).
52
- &.matcha-avatar-tiny,
53
- &.matcha-avatar-xs,
54
- &.matcha-avatar-sm {
55
- width: var(--matcha-avatar-xs, 24px);
56
- height: var(--matcha-avatar-xs, 24px);
57
- font-size: var(--matcha-text-2xs, 10px);
58
- line-height: 1;
59
- }
60
-
61
- &.matcha-avatar-small,
62
- &.matcha-avatar-md {
63
- width: var(--matcha-avatar-md, 40px);
64
- height: var(--matcha-avatar-md, 40px);
65
- font-size: var(--matcha-text-md, 14px);
66
- line-height: 1;
67
- }
68
-
69
- &.matcha-avatar-medium,
70
- &.matcha-avatar-lg {
71
- width: var(--matcha-avatar-lg, 56px);
72
- height: var(--matcha-avatar-lg, 56px);
73
- font-size: var(--matcha-text-2xl, 20px);
74
- line-height: 1;
75
- }
76
-
77
- &.matcha-avatar-large,
78
- &.matcha-avatar-xl {
79
- width: var(--matcha-avatar-xl, 80px);
80
- height: var(--matcha-avatar-xl, 80px);
81
- font-size: var(--matcha-text-3xl, 24px);
82
- line-height: 1;
83
- }
84
-
85
- &.matcha-avatar-huge,
86
- &.matcha-avatar-2xl {
87
- width: var(--matcha-avatar-2xl, 96px);
88
- height: var(--matcha-avatar-2xl, 96px);
89
- font-size: var(--matcha-text-4xl, 32px);
90
- line-height: 1;
91
- }
92
-
93
- // ── Image ──
94
- .matcha-avatar-image {
95
- width: 100%;
96
- height: 100%;
97
- object-fit: cover;
98
- border-radius: inherit;
99
- }
100
-
101
- // ── Initials ──
102
- .matcha-avatar-initials {
103
- font-weight: var(--matcha-weight-medium, 500);
104
- text-transform: uppercase;
105
- letter-spacing: var(--matcha-letter-spacing-wide, 0.5px);
106
- }
107
-
108
- // ── Placeholder icon ──
109
- .matcha-avatar-icon {
110
- width: 100%;
111
- height: 100%;
112
- }
113
-
114
- // ── Disabled ──
115
- &.matcha-avatar--disabled,
116
- &.color-disabled {
117
- opacity: var(--matcha-opacity-disabled, 0.38);
118
- pointer-events: none;
119
- }
120
- }
121
-
122
- // ── Placeholder — vazado canônico (Figma matcha/avatar 5668:32088) ──────────
123
- // SVG usa fill-rule=evenodd: disco preenchido com currentColor + silhueta vazada.
124
- // `currentColor` do disco precisa ser a COR DA MARCA (não o contrast da .color class
125
- // global, que é branco/preto). Override aqui força o token de palette.
126
- .matcha-avatar.matcha-avatar--placeholder {
127
- background: transparent !important;
128
-
129
- &.light-blue { color: var(--matcha-color-palette-light-blue) !important; }
130
- &.pink { color: var(--matcha-color-palette-pink) !important; }
131
- &.teal { color: var(--matcha-color-palette-teal) !important; }
132
- &.purple { color: var(--matcha-color-palette-purple) !important; }
133
- &.orange { color: var(--matcha-color-palette-orange) !important; }
134
- &.yellow { color: var(--matcha-color-palette-yellow) !important; }
135
- &.neutral { color: var(--matcha-color-icon-default) !important; }
136
- }
137
-
138
- // Neutral em Initials — cinza canônico Figma (icon-default).
139
- .matcha-avatar:not(.matcha-avatar--placeholder).neutral {
140
- background: var(--matcha-color-icon-default);
141
- }
142
-
143
- // ── Initials — bg + fg por palette canônica Figma DSV3 (6 cores) ────────────
144
- // O palette inverte por tema (light=tons saturados, dark=tons claros). text-primary
145
- // também inverte (#1a1d21 light / #e8eaed dark). Combinar os dois → contraste péssimo
146
- // em dark mode (1.2-2.9:1 FAIL). Por isso fg é fixed-per-color, não token-based.
147
- //
148
- // Light mode: pink/teal/purple bg escuros → fg branco. light-blue/orange/yellow bg
149
- // claros → fg preto (light-blue precisa #000 puro pra AA por 0.08).
150
- // Dark mode: todos os bg ficam lighter → fg preto funciona em tudo (5-12:1).
151
-
152
- .matcha-avatar:not(.matcha-avatar--placeholder) {
153
- // Backgrounds (mesmo seletor pros 2 temas — palette token já inverte sozinho).
154
- &.light-blue { background: var(--matcha-color-palette-light-blue); }
155
- &.pink { background: var(--matcha-color-palette-pink); }
156
- &.teal { background: var(--matcha-color-palette-teal); }
157
- &.purple { background: var(--matcha-color-palette-purple); }
158
- &.orange { background: var(--matcha-color-palette-orange); }
159
- &.yellow { background: var(--matcha-color-palette-yellow); }
160
- }
161
-
162
- // Light mode — bgs saturados (pink/teal/purple = escuros), fg branco passa AA.
163
- // orange/yellow/light-blue = claros, fg precisa ser dark (#000 pra light-blue por margem).
164
- .theme-default-light .matcha-avatar:not(.matcha-avatar--placeholder) {
165
- &.light-blue { color: #000; } // 5.42:1 AA
166
- &.pink { color: #fff; } // 4.95:1 AA
167
- &.teal { color: #fff; } // 5.32:1 AA
168
- &.purple { color: #fff; } // 6.30:1 AA
169
- &.orange { color: #1a1a1a; } // 4.59:1 AA
170
- &.yellow { color: #1a1a1a; } // 8.52:1 AAA
171
- &.neutral { color: #fff; } // icon-default #5f656b vs #fff = 5.18:1 AA
172
- }
173
-
174
- // Dark mode — todos os bgs ficam lighter (#54c5f7, #e46291, #4fb7ad, etc).
175
- // Texto branco falha em todos. Texto dark funciona em todos.
176
- .theme-default-dark .matcha-avatar:not(.matcha-avatar--placeholder) {
177
- &.light-blue { color: #1a1a1a; } // 8.87:1 AAA
178
- &.pink { color: #1a1a1a; } // 5.35:1 AA
179
- &.teal { color: #1a1a1a; } // 7.22:1 AAA
180
- &.purple { color: #1a1a1a; } // 4.98:1 AA
181
- &.orange { color: #1a1a1a; } // 8.58:1 AAA
182
- &.yellow { color: #1a1a1a; } // 11.94:1 AAA
183
- &.neutral { color: #1a1a1a; } // icon-default #9aa0a6 vs #1a1a1a = 5.97:1 AA
184
- }
185
-
186
- // ── Screen reader only utility (visualmente oculto, lido por AT) ────────────
187
- .matcha-avatar-sr-only {
188
- position: absolute;
189
- width: 1px;
190
- height: 1px;
191
- padding: 0;
192
- margin: -1px;
193
- overflow: hidden;
194
- clip: rect(0, 0, 0, 0);
195
- white-space: nowrap;
196
- border: 0;
197
- }
198
-
199
- // ── Status indicator ────────────────────────────────────────────────────────
200
- // Cores estruturais (online/offline/busy) ficam fora do mixin pra renderizar
201
- // independente de classe de tema (`theme-default-light`, etc.). Tokens com
202
- // fallback hardcoded resolvem o caso de tema não inicializado.
203
-
204
- .matcha-avatar-status {
205
- position: absolute;
206
- bottom: 0;
207
- right: 0;
208
- border-radius: var(--matcha-radius-pill, 9999px);
209
- border: var(--matcha-border-thin, 2px) solid var(--matcha-color-surface-card, #fff);
210
- box-sizing: border-box;
211
-
212
- // Size scales with avatar
213
- .matcha-avatar-xs &,
214
- .matcha-avatar-tiny & { width: var(--matcha-avatar-status-xs, 8px); height: var(--matcha-avatar-status-xs, 8px); }
215
-
216
- .matcha-avatar-sm &,
217
- .matcha-avatar-small & { width: var(--matcha-avatar-status-sm, 10px); height: var(--matcha-avatar-status-sm, 10px); }
218
-
219
- .matcha-avatar-md &,
220
- .matcha-avatar-medium & { width: var(--matcha-avatar-status-md, 12px); height: var(--matcha-avatar-status-md, 12px); }
221
-
222
- .matcha-avatar-lg &,
223
- .matcha-avatar-large & { width: var(--matcha-avatar-status-lg, 14px); height: var(--matcha-avatar-status-lg, 14px); }
224
-
225
- .matcha-avatar-xl & { width: var(--matcha-avatar-status-xl, 16px); height: var(--matcha-avatar-status-xl, 16px); }
226
-
227
- .matcha-avatar-2xl &,
228
- .matcha-avatar-huge & { width: var(--matcha-avatar-status-2xl, 18px); height: var(--matcha-avatar-status-2xl, 18px); }
229
-
230
- // Cores estruturais — fallback hardcoded pra funcionar mesmo sem tema.
231
- &.matcha-avatar-status--online { background-color: var(--matcha-color-success, #16a34a); }
232
- &.matcha-avatar-status--offline { background-color: var(--matcha-color-text-placeholder, #9ca3af); }
233
- &.matcha-avatar-status--busy { background-color: var(--matcha-color-danger, #dc2626); }
234
- }
235
-
236
- // ── Theme mixin ─────────────────────────────────────────────────────────────
237
-
238
- @mixin matcha-avatar-theme($theme) {
239
- .matcha-avatar {
240
- // Placeholder: SVG usa fill="currentColor" e herda do host. A classe de
241
- // cor (.blue/.orange/etc) define color=foreground + background=cor cheia,
242
- // então o icon vazado fica visível na cor escolhida pelo usuário.
243
- // Sem fallback hardcoded aqui — quando o user não passa color, o @Input
244
- // default 'blue' resolve via .blue do matcha-style.css.
245
-
246
- &.matcha-avatar--disabled,
247
- &.color-disabled {
248
- background-color: var(--matcha-color-disabled-bg);
249
- color: var(--matcha-color-disabled-fg);
250
- }
251
- }
252
-
253
- // Status border-color por tema (estrutural resolve cores de fundo via tokens).
254
- .matcha-avatar-status {
255
- border-color: var(--matcha-color-surface-card);
256
- }
257
- }
258
-
259
- // =============================================================================
260
- // A11y / modernity media queries
261
- // =============================================================================
262
-
263
- // Forced colors (Windows High Contrast) bg colors podem virar invisíveis,
264
- // usar SelectedItem/Highlight pros estados, CanvasText/Canvas pra borders.
265
- @media (forced-colors: active) {
266
- .matcha-avatar {
267
- border: 1px solid CanvasText;
268
-
269
- &.matcha-avatar--disabled,
270
- &.color-disabled {
271
- opacity: 0.5;
272
- border-color: GrayText;
273
- }
274
- }
275
-
276
- // Status dot em high-contrast as 3 cores ficam idênticas. Compensamos
277
- // com pattern visual: online=fill, offline=outline, busy=outline duplo.
278
- .matcha-avatar-status {
279
- background: SelectedItem !important;
280
- border: 2px solid Canvas !important;
281
-
282
- &.matcha-avatar-status--offline {
283
- background: Canvas !important;
284
- border: 2px solid CanvasText !important;
285
- }
286
-
287
- &.matcha-avatar-status--busy {
288
- background: SelectedItem !important;
289
- box-shadow: 0 0 0 2px Canvas, 0 0 0 4px CanvasText;
290
- }
291
- }
292
- }
293
-
294
- // Reduced motion — mata todas transitions/animations.
295
- @media (prefers-reduced-motion: reduce) {
296
- .matcha-avatar,
297
- .matcha-avatar-status {
298
- transition: none !important;
299
- animation: none !important;
300
- }
301
- }
1
+ // =============================================================================
2
+ // matcha-avatar.scss — Avatar component (photo, initials, placeholder + status)
3
+ // Aligned with Figma Avatar/Matcha: XS(24) SM(32) MD(40) LG(56) XL(80) 2XL(96)
4
+ // =============================================================================
5
+
6
+ // ── Structural (outside mixin) ──────────────────────────────────────────────
7
+
8
+ .matcha-avatar {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ position: relative;
13
+ // SEM overflow:hidden — o status indicator fica no canto fora do círculo
14
+ // visível e seria cortado. A <img> com border-radius inherit já se arredonda
15
+ // sozinha; SVG e Initials ficam dentro dos bounds.
16
+ border-radius: var(--matcha-radius-pill, 9999px);
17
+
18
+ font-weight: var(--matcha-weight-medium, 500);
19
+ user-select: none;
20
+ flex-shrink: 0;
21
+ }
22
+
23
+ // =============================================================================
24
+ // Ring colored (additive) — controlado pelo [ring] @Input do component.
25
+ // 2px solid + halo alpha externo. Não ocupa layout (box-shadow puro).
26
+ //
27
+ // Aplicado no .matcha-avatar INNER (não no host) porque o inner é quem tem
28
+ // width/height/border-radius:pill — box-shadow segue o radius desse elemento
29
+ // e renderiza circular. No host (inline default) sairia retangular.
30
+ // =============================================================================
31
+ matcha-avatar[ring] .matcha-avatar {
32
+ box-shadow:
33
+ 0 0 0 2px transparent,
34
+ 0 0 0 3px var(--matcha-avatar-ring-color, currentColor);
35
+ }
36
+
37
+ matcha-avatar[ring]:not([ring="neutral"]) .matcha-avatar {
38
+ box-shadow:
39
+ 0 0 0 2px transparent,
40
+ 0 0 0 3px var(--matcha-avatar-ring-color, currentColor),
41
+ 0 0 0 5px var(--matcha-avatar-ring-halo, transparent);
42
+ }
43
+
44
+ // ── Variants (sizes, initials, icon, disabled) — nested em .matcha-avatar pra
45
+ // usar `&.matcha-avatar-*` syntax. Bloco separado do base styles (linha 8-21)
46
+ // porque matcha-avatar[ring] (acima) é regra absoluta, não nested.
47
+ .matcha-avatar {
48
+ // ── Sizes — Canonical 5-step scale: tiny 24 · small 40 · medium 56 · large 80 · huge 96.
49
+ // Abbreviations kept as @deprecated aliases, mapped BY PIXEL SIZE (old 32px `sm` dropped → tiny).
50
+ // NOTE: --matcha-avatar-* tokens still carry the legacy abbreviated names; re-tier them to
51
+ // tiny/small/medium/large/huge on the Figma/DSV3 side (token rename is design-driven).
52
+ &.matcha-avatar-tiny,
53
+ &.matcha-avatar-xs,
54
+ &.matcha-avatar-sm {
55
+ width: var(--matcha-avatar-xs, 24px);
56
+ height: var(--matcha-avatar-xs, 24px);
57
+ font-size: var(--matcha-text-2xs, 10px);
58
+ line-height: 1;
59
+ }
60
+
61
+ &.matcha-avatar-small,
62
+ &.matcha-avatar-md {
63
+ width: var(--matcha-avatar-md, 40px);
64
+ height: var(--matcha-avatar-md, 40px);
65
+ font-size: var(--matcha-text-md, 14px);
66
+ line-height: 1;
67
+ }
68
+
69
+ &.matcha-avatar-medium,
70
+ &.matcha-avatar-lg {
71
+ width: var(--matcha-avatar-lg, 56px);
72
+ height: var(--matcha-avatar-lg, 56px);
73
+ font-size: var(--matcha-text-2xl, 20px);
74
+ line-height: 1;
75
+ }
76
+
77
+ &.matcha-avatar-large,
78
+ &.matcha-avatar-xl {
79
+ width: var(--matcha-avatar-xl, 80px);
80
+ height: var(--matcha-avatar-xl, 80px);
81
+ font-size: var(--matcha-text-3xl, 24px);
82
+ line-height: 1;
83
+ }
84
+
85
+ &.matcha-avatar-huge,
86
+ &.matcha-avatar-2xl {
87
+ width: var(--matcha-avatar-2xl, 96px);
88
+ height: var(--matcha-avatar-2xl, 96px);
89
+ font-size: var(--matcha-text-4xl, 32px);
90
+ line-height: 1;
91
+ }
92
+
93
+ // ── Image ──
94
+ .matcha-avatar-image {
95
+ width: 100%;
96
+ height: 100%;
97
+ object-fit: cover;
98
+ border-radius: inherit;
99
+ }
100
+
101
+ // ── Initials ──
102
+ .matcha-avatar-initials {
103
+ font-weight: var(--matcha-weight-medium, 500);
104
+ text-transform: uppercase;
105
+ letter-spacing: var(--matcha-letter-spacing-wide, 0.5px);
106
+ }
107
+
108
+ // ── Placeholder icon ──
109
+ .matcha-avatar-icon {
110
+ width: 100%;
111
+ height: 100%;
112
+ }
113
+
114
+ // ── Disabled ──
115
+ &.matcha-avatar--disabled,
116
+ &.color-disabled {
117
+ opacity: var(--matcha-opacity-disabled, 0.38);
118
+ pointer-events: none;
119
+ }
120
+ }
121
+
122
+ // ── Placeholder — vazado canônico (Figma matcha/avatar 5668:32088) ──────────
123
+ // SVG usa fill-rule=evenodd: disco preenchido com currentColor + silhueta vazada.
124
+ // `currentColor` do disco precisa ser a COR DA MARCA (não o contrast da .color class
125
+ // global, que é branco/preto). Override aqui força o token de palette.
126
+ .matcha-avatar.matcha-avatar--placeholder {
127
+ background: transparent !important;
128
+
129
+ &.light-blue { color: var(--matcha-color-palette-light-blue) !important; }
130
+ &.pink { color: var(--matcha-color-palette-pink) !important; }
131
+ &.teal { color: var(--matcha-color-palette-teal) !important; }
132
+ &.purple { color: var(--matcha-color-palette-purple) !important; }
133
+ &.orange { color: var(--matcha-color-palette-orange) !important; }
134
+ &.yellow { color: var(--matcha-color-palette-yellow) !important; }
135
+ &.neutral { color: var(--matcha-color-icon-default) !important; }
136
+ }
137
+
138
+ // Neutral em Initials — cinza canônico Figma (icon-default).
139
+ .matcha-avatar:not(.matcha-avatar--placeholder).neutral {
140
+ background: var(--matcha-color-icon-default);
141
+ }
142
+
143
+ // ── Initials — bg + fg por palette canônica Figma DSV3 (6 cores) ────────────
144
+ // O palette inverte por tema (light=tons saturados, dark=tons claros). text-primary
145
+ // também inverte (#1a1d21 light / #e8eaed dark). Combinar os dois → contraste péssimo
146
+ // em dark mode (1.2-2.9:1 FAIL). Por isso fg é fixed-per-color, não token-based.
147
+ //
148
+ // Light mode: pink/teal/purple bg escuros → fg branco. light-blue/orange/yellow bg
149
+ // claros → fg preto (light-blue precisa #000 puro pra AA por 0.08).
150
+ // Dark mode: todos os bg ficam lighter → fg preto funciona em tudo (5-12:1).
151
+
152
+ .matcha-avatar:not(.matcha-avatar--placeholder) {
153
+ // Backgrounds (mesmo seletor pros 2 temas — palette token já inverte sozinho).
154
+ &.light-blue { background: var(--matcha-color-palette-light-blue); }
155
+ &.pink { background: var(--matcha-color-palette-pink); }
156
+ &.teal { background: var(--matcha-color-palette-teal); }
157
+ &.purple { background: var(--matcha-color-palette-purple); }
158
+ &.orange { background: var(--matcha-color-palette-orange); }
159
+ &.yellow { background: var(--matcha-color-palette-yellow); }
160
+ }
161
+
162
+ // Light mode — bgs saturados (pink/teal/purple = escuros), fg branco passa AA.
163
+ // orange/yellow/light-blue = claros, fg precisa ser dark (#000 pra light-blue por margem).
164
+ .theme-default-light .matcha-avatar:not(.matcha-avatar--placeholder) {
165
+ &.light-blue { color: #000; } // 5.42:1 AA
166
+ &.pink { color: #fff; } // 4.95:1 AA
167
+ &.teal { color: #fff; } // 5.32:1 AA
168
+ &.purple { color: #fff; } // 6.30:1 AA
169
+ &.orange { color: #1a1a1a; } // 4.59:1 AA
170
+ &.yellow { color: #1a1a1a; } // 8.52:1 AAA
171
+ &.neutral { color: #fff; } // icon-default #5f656b vs #fff = 5.18:1 AA
172
+ }
173
+
174
+ // Dark mode — todos os bgs ficam lighter (#54c5f7, #e46291, #4fb7ad, etc).
175
+ // Texto branco falha em todos. Texto dark funciona em todos.
176
+ .theme-default-dark .matcha-avatar:not(.matcha-avatar--placeholder) {
177
+ &.light-blue { color: #1a1a1a; } // 8.87:1 AAA
178
+ &.pink { color: #1a1a1a; } // 5.35:1 AA
179
+ &.teal { color: #1a1a1a; } // 7.22:1 AAA
180
+ &.purple { color: #1a1a1a; } // 4.98:1 AA
181
+ &.orange { color: #1a1a1a; } // 8.58:1 AAA
182
+ &.yellow { color: #1a1a1a; } // 11.94:1 AAA
183
+ &.neutral { color: #1a1a1a; } // icon-default #9aa0a6 vs #1a1a1a = 5.97:1 AA
184
+ }
185
+
186
+ // ── Avatar Group empilhamento horizontal com overlap + overflow "+N" ──────
187
+ // Substitui a composição manual (SCSS local) feita nas telas. -10px de overlap
188
+ // é um offset visual bespoke (não genérico) — mantido literal de propósito.
189
+ .matcha-avatar-group {
190
+ display: inline-flex;
191
+ align-items: center;
192
+
193
+ matcha-avatar {
194
+ margin-left: -10px;
195
+ border: var(--matcha-border-thin, 2px) solid var(--matcha-color-surface-card);
196
+ border-radius: var(--matcha-radius-pill, 9999px);
197
+
198
+ &:first-child {
199
+ margin-left: 0;
200
+ }
201
+ }
202
+
203
+ &__more {
204
+ margin-left: var(--matcha-space-100, 8px);
205
+ font-size: var(--matcha-text-sm, 12px);
206
+ font-weight: var(--matcha-weight-semibold, 600);
207
+ color: var(--matcha-color-text-secondary);
208
+ }
209
+ }
210
+
211
+ // ── Screen reader only utility (visualmente oculto, lido por AT) ────────────
212
+ .matcha-avatar-sr-only {
213
+ position: absolute;
214
+ width: 1px;
215
+ height: 1px;
216
+ padding: 0;
217
+ margin: -1px;
218
+ overflow: hidden;
219
+ clip: rect(0, 0, 0, 0);
220
+ white-space: nowrap;
221
+ border: 0;
222
+ }
223
+
224
+ // ── Status indicator ────────────────────────────────────────────────────────
225
+ // Cores estruturais (online/offline/busy) ficam fora do mixin pra renderizar
226
+ // independente de classe de tema (`theme-default-light`, etc.). Tokens com
227
+ // fallback hardcoded resolvem o caso de tema não inicializado.
228
+
229
+ .matcha-avatar-status {
230
+ position: absolute;
231
+ bottom: 0;
232
+ right: 0;
233
+ border-radius: var(--matcha-radius-pill, 9999px);
234
+ border: var(--matcha-border-thin, 2px) solid var(--matcha-color-surface-card, #fff);
235
+ box-sizing: border-box;
236
+
237
+ // Size scales with avatar
238
+ .matcha-avatar-xs &,
239
+ .matcha-avatar-tiny & { width: var(--matcha-avatar-status-xs, 8px); height: var(--matcha-avatar-status-xs, 8px); }
240
+
241
+ .matcha-avatar-sm &,
242
+ .matcha-avatar-small & { width: var(--matcha-avatar-status-sm, 10px); height: var(--matcha-avatar-status-sm, 10px); }
243
+
244
+ .matcha-avatar-md &,
245
+ .matcha-avatar-medium & { width: var(--matcha-avatar-status-md, 12px); height: var(--matcha-avatar-status-md, 12px); }
246
+
247
+ .matcha-avatar-lg &,
248
+ .matcha-avatar-large & { width: var(--matcha-avatar-status-lg, 14px); height: var(--matcha-avatar-status-lg, 14px); }
249
+
250
+ .matcha-avatar-xl & { width: var(--matcha-avatar-status-xl, 16px); height: var(--matcha-avatar-status-xl, 16px); }
251
+
252
+ .matcha-avatar-2xl &,
253
+ .matcha-avatar-huge & { width: var(--matcha-avatar-status-2xl, 18px); height: var(--matcha-avatar-status-2xl, 18px); }
254
+
255
+ // Cores estruturais — fallback hardcoded pra funcionar mesmo sem tema.
256
+ &.matcha-avatar-status--online { background-color: var(--matcha-color-success, #16a34a); }
257
+ &.matcha-avatar-status--offline { background-color: var(--matcha-color-text-placeholder, #9ca3af); }
258
+ &.matcha-avatar-status--busy { background-color: var(--matcha-color-danger, #dc2626); }
259
+ }
260
+
261
+ // ── "Nome ao lado" (showName) ───────────────────────────────────────────────
262
+ // Root: `display: contents` por padrão — transparente no layout, idêntico a
263
+ // hoje ( a bolinha conta como box). Vira inline-flex (bolinha + texto lado
264
+ // a lado) quando showTextStack (showName + hasName) — ver component.
265
+ .matcha-avatar-root {
266
+ display: contents;
267
+
268
+ &--inline {
269
+ display: inline-flex;
270
+ align-items: center;
271
+ gap: var(--matcha-space-100, 8px);
272
+ min-width: 0;
273
+ }
274
+
275
+ // Stacked (hero/profile header) — bolinha + texto empilhados, centralizados.
276
+ // Substitui a composição manual <header><matcha-avatar/><h1/><p/></header>.
277
+ &--stacked {
278
+ display: inline-flex;
279
+ flex-direction: column;
280
+ align-items: center;
281
+ text-align: center;
282
+ gap: var(--matcha-space-100, 8px);
283
+ }
284
+ }
285
+
286
+ .matcha-avatar-text {
287
+ display: flex;
288
+ flex-direction: column;
289
+ min-width: 0;
290
+
291
+ &__primary {
292
+ color: var(--matcha-color-text-primary);
293
+ font-weight: var(--matcha-weight-medium, 500);
294
+ overflow: hidden;
295
+ text-overflow: ellipsis;
296
+ white-space: nowrap;
297
+ }
298
+
299
+ &__caption {
300
+ color: var(--matcha-color-text-muted);
301
+ font-weight: var(--matcha-weight-regular, 400);
302
+ font-variant-numeric: tabular-nums;
303
+ overflow: hidden;
304
+ text-overflow: ellipsis;
305
+ white-space: nowrap;
306
+ }
307
+ }
308
+
309
+ // Equilíbrio tipográfico por tamanho do avatar — seletor de irmão contra as
310
+ // classes de tamanho já existentes na bolinha (`.matcha-avatar-<size>`), sem
311
+ // duplicar a classe de tamanho no host. 5 tiers, escala proporcional ao avatar.
312
+ .matcha-avatar-tiny ~ .matcha-avatar-text,
313
+ .matcha-avatar-xs ~ .matcha-avatar-text {
314
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-sm, 12px); line-height: var(--matcha-leading-sm, 16px); }
315
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-xs, 11px); line-height: var(--matcha-leading-xs, 14px); }
316
+ }
317
+
318
+ .matcha-avatar-small ~ .matcha-avatar-text,
319
+ .matcha-avatar-md ~ .matcha-avatar-text {
320
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-md, 14px); line-height: var(--matcha-leading-md, 20px); }
321
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-sm, 12px); line-height: var(--matcha-leading-sm, 16px); }
322
+ }
323
+
324
+ .matcha-avatar-medium ~ .matcha-avatar-text,
325
+ .matcha-avatar-lg ~ .matcha-avatar-text {
326
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-lg, 16px); line-height: var(--matcha-leading-lg, 24px); }
327
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-md, 14px); line-height: var(--matcha-leading-md, 20px); }
328
+ }
329
+
330
+ .matcha-avatar-large ~ .matcha-avatar-text,
331
+ .matcha-avatar-xl ~ .matcha-avatar-text {
332
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-xl, 18px); line-height: var(--matcha-leading-xl, 24px); }
333
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-lg, 16px); line-height: var(--matcha-leading-lg, 24px); }
334
+ }
335
+
336
+ .matcha-avatar-huge ~ .matcha-avatar-text,
337
+ .matcha-avatar-2xl ~ .matcha-avatar-text {
338
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-title-lg, 20px); line-height: var(--matcha-leading-title-lg, 28px); }
339
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-xl, 18px); line-height: var(--matcha-leading-xl, 24px); }
340
+ }
341
+
342
+ // ── Stacked (hero/profile header) — tipografia maior, negrito, centralizada.
343
+ // Classe composta (.matcha-avatar-text.matcha-avatar-text--stacked) tem mais
344
+ // especificidade que a escada inline acima — sobrescreve sem depender de ordem.
345
+ .matcha-avatar-tiny ~ .matcha-avatar-text.matcha-avatar-text--stacked,
346
+ .matcha-avatar-xs ~ .matcha-avatar-text.matcha-avatar-text--stacked {
347
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-title-sm, 16px); font-weight: var(--matcha-weight-bold, 700); line-height: var(--matcha-leading-title-sm, 22px); }
348
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-sm, 12px); line-height: var(--matcha-leading-sm, 16px); }
349
+ }
350
+
351
+ .matcha-avatar-small ~ .matcha-avatar-text.matcha-avatar-text--stacked,
352
+ .matcha-avatar-md ~ .matcha-avatar-text.matcha-avatar-text--stacked {
353
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-title-sm, 16px); font-weight: var(--matcha-weight-bold, 700); line-height: var(--matcha-leading-title-sm, 22px); }
354
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-sm, 12px); line-height: var(--matcha-leading-sm, 16px); }
355
+ }
356
+
357
+ .matcha-avatar-medium ~ .matcha-avatar-text.matcha-avatar-text--stacked,
358
+ .matcha-avatar-lg ~ .matcha-avatar-text.matcha-avatar-text--stacked {
359
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-title-md, 18px); font-weight: var(--matcha-weight-bold, 700); line-height: var(--matcha-leading-title-md, 24px); }
360
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-md, 14px); line-height: var(--matcha-leading-md, 20px); }
361
+ }
362
+
363
+ .matcha-avatar-large ~ .matcha-avatar-text.matcha-avatar-text--stacked,
364
+ .matcha-avatar-xl ~ .matcha-avatar-text.matcha-avatar-text--stacked {
365
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-title-md, 18px); font-weight: var(--matcha-weight-bold, 700); line-height: var(--matcha-leading-title-md, 24px); }
366
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-md, 14px); line-height: var(--matcha-leading-md, 20px); }
367
+ }
368
+
369
+ .matcha-avatar-huge ~ .matcha-avatar-text.matcha-avatar-text--stacked,
370
+ .matcha-avatar-2xl ~ .matcha-avatar-text.matcha-avatar-text--stacked {
371
+ .matcha-avatar-text__primary { font-size: var(--matcha-text-title-lg, 20px); font-weight: var(--matcha-weight-bold, 700); line-height: var(--matcha-leading-title-lg, 28px); }
372
+ .matcha-avatar-text__caption { font-size: var(--matcha-text-lg, 16px); line-height: var(--matcha-leading-lg, 24px); }
373
+ }
374
+
375
+ // ── Theme mixin ─────────────────────────────────────────────────────────────
376
+
377
+ @mixin matcha-avatar-theme($theme) {
378
+ .matcha-avatar {
379
+ // Placeholder: SVG usa fill="currentColor" e herda do host. A classe de
380
+ // cor (.blue/.orange/etc) define color=foreground + background=cor cheia,
381
+ // então o icon vazado fica visível na cor escolhida pelo usuário.
382
+ // Sem fallback hardcoded aqui — quando o user não passa color, o @Input
383
+ // default 'blue' resolve via .blue do matcha-style.css.
384
+
385
+ &.matcha-avatar--disabled,
386
+ &.color-disabled {
387
+ background-color: var(--matcha-color-disabled-bg);
388
+ color: var(--matcha-color-disabled-fg);
389
+ }
390
+ }
391
+
392
+ // Status border-color por tema (estrutural já resolve cores de fundo via tokens).
393
+ .matcha-avatar-status {
394
+ border-color: var(--matcha-color-surface-card);
395
+ }
396
+ }
397
+
398
+ // =============================================================================
399
+ // A11y / modernity media queries
400
+ // =============================================================================
401
+
402
+ // Forced colors (Windows High Contrast) — bg colors podem virar invisíveis,
403
+ // usar SelectedItem/Highlight pros estados, CanvasText/Canvas pra borders.
404
+ @media (forced-colors: active) {
405
+ .matcha-avatar {
406
+ border: 1px solid CanvasText;
407
+
408
+ &.matcha-avatar--disabled,
409
+ &.color-disabled {
410
+ opacity: 0.5;
411
+ border-color: GrayText;
412
+ }
413
+ }
414
+
415
+ // Status dot — em high-contrast as 3 cores ficam idênticas. Compensamos
416
+ // com pattern visual: online=fill, offline=outline, busy=outline duplo.
417
+ .matcha-avatar-status {
418
+ background: SelectedItem !important;
419
+ border: 2px solid Canvas !important;
420
+
421
+ &.matcha-avatar-status--offline {
422
+ background: Canvas !important;
423
+ border: 2px solid CanvasText !important;
424
+ }
425
+
426
+ &.matcha-avatar-status--busy {
427
+ background: SelectedItem !important;
428
+ box-shadow: 0 0 0 2px Canvas, 0 0 0 4px CanvasText;
429
+ }
430
+ }
431
+ }
432
+
433
+ // Reduced motion — mata todas transitions/animations.
434
+ @media (prefers-reduced-motion: reduce) {
435
+ .matcha-avatar,
436
+ .matcha-avatar-status {
437
+ transition: none !important;
438
+ animation: none !important;
439
+ }
440
+ }