@inchurch/matcha-theme 20.0.11 → 20.277.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 (116) hide show
  1. package/abstracts/_colors.scss +404 -404
  2. package/abstracts/_elevation.scss +102 -102
  3. package/abstracts/_functions.scss +1186 -1212
  4. package/abstracts/_media-breakpoint.scss +23 -23
  5. package/abstracts/_theme-api.scss +230 -0
  6. package/abstracts/_typography.scss +127 -127
  7. package/base/_reset.scss +438 -438
  8. package/components/app-page-header.scss +259 -0
  9. package/components/matcha-accordion.scss +293 -157
  10. package/components/matcha-audio-player.scss +1 -2
  11. package/components/matcha-autocomplete.scss +10 -11
  12. package/components/matcha-avatar.scss +173 -33
  13. package/components/matcha-badge.scss +15 -15
  14. package/components/matcha-breadcrumb.scss +231 -126
  15. package/components/matcha-button-toggle.scss +46 -2
  16. package/components/matcha-buttons.scss +908 -784
  17. package/components/matcha-calendar.scss +99 -35
  18. package/components/matcha-cards.scss +58 -33
  19. package/components/matcha-chart-card.scss +5 -12
  20. package/components/matcha-checkbox.scss +191 -490
  21. package/components/matcha-chip.scss +297 -212
  22. package/components/matcha-color-pick.scss +1 -2
  23. package/components/matcha-command-palette.scss +290 -63
  24. package/components/matcha-crop.scss +406 -172
  25. package/components/matcha-date.scss +81 -81
  26. package/components/matcha-divider.scss +86 -31
  27. package/components/matcha-draggable.scss +4 -5
  28. package/components/matcha-drawer.scss +207 -66
  29. package/components/matcha-drop-image.scss +14 -0
  30. package/components/matcha-drop-list.scss +87 -47
  31. package/components/matcha-emoji.scss +2 -2
  32. package/components/matcha-empty-state.scss +195 -83
  33. package/components/matcha-file-uploader.scss +462 -0
  34. package/components/matcha-flag.scss +93 -52
  35. package/components/matcha-footer.scss +67 -164
  36. package/components/matcha-form-field.scss +55 -3
  37. package/components/matcha-form-section.scss +100 -101
  38. package/components/matcha-header.scss +134 -325
  39. package/components/matcha-highlight.scss +65 -197
  40. package/components/matcha-hint-text.scss +25 -4
  41. package/components/matcha-horizontal-tree.scss +316 -317
  42. package/components/matcha-icon.scss +37 -45
  43. package/components/matcha-image.scss +2 -3
  44. package/components/matcha-list.scss +14 -15
  45. package/components/matcha-menu.scss +15 -2
  46. package/components/matcha-modal.scss +59 -86
  47. package/components/matcha-nav.scss +362 -231
  48. package/components/matcha-notification.scss +412 -197
  49. package/components/matcha-option.scss +98 -23
  50. package/components/matcha-page-builder.scss +16 -16
  51. package/components/matcha-paginator.scss +688 -235
  52. package/components/matcha-panel.scss +42 -27
  53. package/components/matcha-profile-card.scss +50 -50
  54. package/components/matcha-progress-bar.scss +257 -153
  55. package/components/matcha-radio.scss +244 -452
  56. package/components/matcha-scrollbar.scss +1 -2
  57. package/components/matcha-scrollbox-shadow.scss +120 -122
  58. package/components/matcha-section.scss +5 -9
  59. package/components/matcha-select-multiple.scss +56 -0
  60. package/components/matcha-select.scss +10 -10
  61. package/components/matcha-skeleton.scss +24 -7
  62. package/components/matcha-slide-toggle.scss +80 -301
  63. package/components/matcha-slider.scss +174 -77
  64. package/components/matcha-snack-bar.scss +123 -131
  65. package/components/matcha-spin.scss +12 -103
  66. package/components/matcha-spinner.scss +76 -57
  67. package/components/matcha-status-pill.scss +82 -0
  68. package/components/matcha-stepper.scss +376 -177
  69. package/components/matcha-table.scss +568 -785
  70. package/components/matcha-tabs.scss +622 -469
  71. package/components/matcha-text-editor.scss +78 -78
  72. package/components/matcha-time.scss +2 -2
  73. package/components/matcha-toolbar.scss +359 -206
  74. package/components/matcha-tooltip.scss +158 -62
  75. package/components/matcha-tree-view.scss +189 -0
  76. package/fonts/manrope/manrope-latin-ext.woff2 +0 -0
  77. package/fonts/manrope/manrope-latin.woff2 +0 -0
  78. package/layout/matcha-page-layout.scss +4 -4
  79. package/main.scss +237 -265
  80. package/package.json +1 -1
  81. package/tokens/_animations-tokens.scss +37 -37
  82. package/tokens/_breakpoints-tokens.scss +35 -26
  83. package/tokens/_color-tokens.scss +1149 -1152
  84. package/tokens/_css-custom-properties.scss +704 -568
  85. package/tokens/_primitives.scss +82 -0
  86. package/tokens/_semantic-aliases.scss +120 -0
  87. package/tokens/_spacing-tokens.scss +94 -94
  88. package/vendors/angular-editor.scss +56 -56
  89. package/vendors/angular-material-fixes.scss +297 -297
  90. package/vendors/charts.scss +92 -92
  91. package/vendors/ng5-slider.scss +56 -56
  92. package/vendors/ngx-material-timepicker.scss +50 -50
  93. package/components/matcha-uploader.scss +0 -215
  94. package/fonts/CircularStd-Black.eot +0 -0
  95. package/fonts/CircularStd-Black.svg +0 -3426
  96. package/fonts/CircularStd-Black.ttf +0 -0
  97. package/fonts/CircularStd-Black.woff +0 -0
  98. package/fonts/CircularStd-Black.woff2 +0 -0
  99. package/fonts/CircularStd-Bold.eot +0 -0
  100. package/fonts/CircularStd-Bold.otf +0 -0
  101. package/fonts/CircularStd-Bold.svg +0 -13532
  102. package/fonts/CircularStd-Bold.ttf +0 -0
  103. package/fonts/CircularStd-Bold.woff +0 -0
  104. package/fonts/CircularStd-Bold.woff2 +0 -0
  105. package/fonts/CircularStd-Medium.eot +0 -0
  106. package/fonts/CircularStd-Medium.otf +0 -0
  107. package/fonts/CircularStd-Medium.svg +0 -13511
  108. package/fonts/CircularStd-Medium.ttf +0 -0
  109. package/fonts/CircularStd-Medium.woff +0 -0
  110. package/fonts/CircularStd-Medium.woff2 +0 -0
  111. package/fonts/CircularStd-Regular.eot +0 -0
  112. package/fonts/CircularStd-Regular.otf +0 -0
  113. package/fonts/CircularStd-Regular.svg +0 -2378
  114. package/fonts/CircularStd-Regular.ttf +0 -0
  115. package/fonts/CircularStd-Regular.woff +0 -0
  116. package/fonts/CircularStd-Regular.woff2 +0 -0
@@ -1,172 +1,406 @@
1
- @use "sass:map";
2
-
3
- // =============================================================================
4
- // matcha-crop.scss — Image cropper modal
5
- // Aligned with Figma matcha/crop:
6
- // Ratio(2: 16:9, 1:1) — Crop area with overlay mask
7
- // Angular: matcha-crop (wraps cropper logic inside matcha-modal)
8
- // =============================================================================
9
-
10
- @mixin matcha-crop-theme($theme) {
11
- $is-dark: map.get($theme, is-dark);
12
-
13
- .matcha-crop {
14
- .matcha-crop__header {
15
- color: var(--matcha-color-fg, #{getForeground($theme)});
16
- }
17
-
18
- .matcha-crop__overlay {
19
- background: rgba(#212121, 0.6); // ok: structural
20
- }
21
-
22
- .matcha-crop__area {
23
- border: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent, #{getAccent($theme)});
24
- }
25
-
26
- .matcha-crop__grid-line {
27
- background: rgba(#ffffff, 0.3); // ok: structural
28
- }
29
-
30
- .matcha-crop__canvas {
31
- background: var(--matcha-color-surface-inverse, #{if($is-dark, getSurface($theme), #121212)});
32
- }
33
-
34
- .matcha-crop__handle {
35
- background: var(--matcha-color-surface, #{getSurface($theme)});
36
- border-color: var(--matcha-color-accent, #{getAccent($theme)});
37
- }
38
- }
39
- }
40
-
41
- // ── Layout ──────────────────────────────────────────────────────────────────
42
-
43
- .matcha-crop {
44
- display: flex;
45
- flex-direction: column;
46
- width: 100%;
47
- height: 100%;
48
- }
49
-
50
- .matcha-crop__header {
51
- display: flex;
52
- align-items: center;
53
- gap: var(--matcha-space-100, 8px);
54
- padding: var(--matcha-space-200, 16px) var(--matcha-space-300, 24px);
55
- font-family: var(--matcha-font-family);
56
- font-size: var(--matcha-text-title-sm, 16px);
57
- font-weight: var(--matcha-weight-semibold, 600);
58
- line-height: var(--matcha-leading-title-sm, 22px);
59
- }
60
-
61
- .matcha-crop__canvas {
62
- position: relative;
63
- flex: 1;
64
- display: flex;
65
- align-items: center;
66
- justify-content: center;
67
- overflow: hidden;
68
- min-height: 300px;
69
- }
70
-
71
- .matcha-crop__image {
72
- max-width: 100%;
73
- max-height: 100%;
74
- object-fit: contain;
75
- user-select: none;
76
- -webkit-user-drag: none;
77
- }
78
-
79
- .matcha-crop__overlay {
80
- position: absolute;
81
- inset: 0;
82
- pointer-events: none;
83
- }
84
-
85
- .matcha-crop__area {
86
- position: absolute;
87
- box-sizing: border-box;
88
- cursor: move;
89
- touch-action: none;
90
- }
91
-
92
- // ── Aspect ratios ──
93
- .matcha-crop__area--16x9 {
94
- aspect-ratio: 16 / 9;
95
- }
96
-
97
- .matcha-crop__area--1x1 {
98
- aspect-ratio: 1 / 1;
99
- border-radius: 0;
100
- }
101
-
102
- .matcha-crop__area--1x1-circle {
103
- aspect-ratio: 1 / 1;
104
- border-radius: 50%;
105
- }
106
-
107
- // ── Rule of thirds grid ──
108
- .matcha-crop__grid {
109
- position: absolute;
110
- inset: 0;
111
- display: grid;
112
- grid-template-columns: 1fr 1fr 1fr;
113
- grid-template-rows: 1fr 1fr 1fr;
114
- pointer-events: none;
115
- }
116
-
117
- .matcha-crop__grid-line {
118
- &:nth-child(1) { grid-column: 2; grid-row: 1 / 4; width: var(--matcha-border-hairline, 1px); }
119
- &:nth-child(2) { grid-column: 3; grid-row: 1 / 4; width: var(--matcha-border-hairline, 1px); }
120
- &:nth-child(3) { grid-column: 1 / 4; grid-row: 2; height: var(--matcha-border-hairline, 1px); }
121
- &:nth-child(4) { grid-column: 1 / 4; grid-row: 3; height: var(--matcha-border-hairline, 1px); }
122
- }
123
-
124
- // ── Resize handles ──
125
- .matcha-crop__handle {
126
- position: absolute;
127
- width: var(--matcha-space-150, 12px);
128
- height: var(--matcha-space-150, 12px);
129
- border: var(--matcha-border-thin, 2px) solid transparent;
130
- border-radius: 50%;
131
- pointer-events: auto;
132
-
133
- // Offset negativo = -6px = -(handle/2) pra centralizar no canto
134
- &--nw { top: calc(-1 * var(--matcha-space-075, 6px)); left: calc(-1 * var(--matcha-space-075, 6px)); cursor: nw-resize; }
135
- &--ne { top: calc(-1 * var(--matcha-space-075, 6px)); right: calc(-1 * var(--matcha-space-075, 6px)); cursor: ne-resize; }
136
- &--sw { bottom: calc(-1 * var(--matcha-space-075, 6px)); left: calc(-1 * var(--matcha-space-075, 6px)); cursor: sw-resize; }
137
- &--se { bottom: calc(-1 * var(--matcha-space-075, 6px)); right: calc(-1 * var(--matcha-space-075, 6px)); cursor: se-resize; }
138
- }
139
-
140
- // ── Footer ──
141
- .matcha-crop__footer {
142
- display: flex;
143
- align-items: center;
144
- justify-content: flex-end;
145
- gap: var(--matcha-space-100, 8px);
146
- padding: var(--matcha-space-200, 16px) var(--matcha-space-300, 24px);
147
- }
148
-
149
- // ── Responsive ──────────────────────────────────────────────────────────────
150
-
151
- @include media-breakpoint('xs') {
152
- .matcha-crop__header {
153
- padding: var(--matcha-space-150, 12px) var(--matcha-space-200, 16px);
154
- }
155
-
156
- .matcha-crop__footer {
157
- padding: var(--matcha-space-150, 12px) var(--matcha-space-200, 16px);
158
- }
159
-
160
- .matcha-crop__canvas {
161
- min-height: 240px;
162
- }
163
- }
164
-
165
- // ── Reduced motion ──────────────────────────────────────────────────────────
166
-
167
- @media (prefers-reduced-motion: reduce) {
168
- .matcha-crop__area,
169
- .matcha-crop__image {
170
- transition: none;
171
- }
172
- }
1
+ @use "sass:map";
2
+
3
+ // =============================================================================
4
+ // matcha-crop.scss — Image cropper (Tier 1 + Tier 2 gold)
5
+ //
6
+ // Estrutura:
7
+ // .matcha-crop host flex column (data-state, data-shape, data-ratio)
8
+ // .matcha-crop__header — title + toolbar (reset, lock)
9
+ // .matcha-crop__canvas — image stage + interaction surface
10
+ // .matcha-crop__image — source img (transforma via translate/scale)
11
+ // .matcha-crop__overlay — punch-out mask via clip-path
12
+ // .matcha-crop__area — crop frame draggable + 8 handles
13
+ // .matcha-crop__handle--{nw|n|ne|...} — resize handles (44×44 touch target)
14
+ // .matcha-crop__zoom-bar — slider de zoom
15
+ // .matcha-crop__state — empty / loading / error visuals
16
+ // .matcha-crop__footer — ng-content de actions
17
+ // =============================================================================
18
+
19
+ @mixin matcha-crop-theme($theme) {
20
+
21
+ .matcha-crop {
22
+ color: var(--matcha-color-text-primary);
23
+
24
+ .matcha-crop__header {
25
+ color: var(--matcha-color-text-primary);
26
+ border-bottom: var(--matcha-border-hairline, 1px) solid var(--matcha-color-surface-border);
27
+ }
28
+
29
+ .matcha-crop__canvas {
30
+ background: var(--matcha-color-surface-inverse, #121212);
31
+ }
32
+
33
+ .matcha-crop__overlay {
34
+ background: var(--matcha-color-scrim, rgba(0, 0, 0, 0.55));
35
+ }
36
+
37
+ .matcha-crop__area {
38
+ border: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent);
39
+ box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
40
+
41
+ &:focus-visible {
42
+ outline: 3px solid var(--matcha-color-focus-ring);
43
+ outline-offset: 4px;
44
+ }
45
+ }
46
+
47
+ .matcha-crop__grid-line {
48
+ background: var(--matcha-color-on-overlay, rgba(255, 255, 255, 0.3));
49
+ }
50
+
51
+ .matcha-crop__handle {
52
+ background: var(--matcha-color-surface);
53
+ border-color: var(--matcha-color-accent);
54
+ }
55
+
56
+ .matcha-crop__zoom-bar {
57
+ background: var(--matcha-color-surface-card);
58
+ border: var(--matcha-border-hairline, 1px) solid var(--matcha-color-surface-border);
59
+ color: var(--matcha-color-text-secondary);
60
+ }
61
+
62
+ .matcha-crop__icon-btn {
63
+ color: var(--matcha-color-text-secondary);
64
+
65
+ &:hover { background: var(--matcha-color-surface-hover); color: var(--matcha-color-text-primary); }
66
+ &:focus-visible { outline: 2px solid var(--matcha-color-focus-ring); outline-offset: 2px; }
67
+ &.is-active { color: var(--matcha-color-accent); background: var(--matcha-color-accent-surface-hover); }
68
+ }
69
+
70
+ .matcha-crop__state-icon { color: var(--matcha-color-text-muted); }
71
+ .matcha-crop__state-title { color: var(--matcha-color-text-primary); }
72
+ .matcha-crop__state-desc { color: var(--matcha-color-text-secondary); }
73
+
74
+ .matcha-crop__state--error .matcha-crop__state-icon { color: var(--matcha-color-danger); }
75
+ }
76
+ }
77
+
78
+ // ── Layout ──────────────────────────────────────────────────────────────────
79
+
80
+ .matcha-crop {
81
+ display: flex;
82
+ flex-direction: column;
83
+ width: 100%;
84
+ height: 100%;
85
+ min-height: 320px;
86
+ }
87
+
88
+ // ── Header ──────────────────────────────────────────────────────────────────
89
+
90
+ .matcha-crop__header {
91
+ display: flex;
92
+ align-items: center;
93
+ gap: var(--matcha-space-100, 8px);
94
+ padding: var(--matcha-space-200, 16px) var(--matcha-space-300, 24px);
95
+ font-family: var(--matcha-font-family);
96
+ font-size: var(--matcha-text-title-sm, 16px);
97
+ font-weight: var(--matcha-weight-semibold, 600);
98
+ line-height: var(--matcha-leading-title-sm, 22px);
99
+ flex-shrink: 0;
100
+ }
101
+
102
+ .matcha-crop__title {
103
+ flex: 1;
104
+ min-width: 0;
105
+ overflow: hidden;
106
+ text-overflow: ellipsis;
107
+ white-space: nowrap;
108
+ }
109
+
110
+ .matcha-crop__toolbar {
111
+ display: flex;
112
+ align-items: center;
113
+ gap: var(--matcha-space-050, 4px);
114
+ }
115
+
116
+ .matcha-crop__icon-btn {
117
+ display: inline-flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ width: 32px;
121
+ height: 32px;
122
+ padding: 0;
123
+ background: transparent;
124
+ border: 0;
125
+ border-radius: var(--matcha-radius-md, 4px);
126
+ cursor: pointer;
127
+ transition: background 150ms ease, color 150ms ease;
128
+ }
129
+
130
+ // ── Canvas (interaction area) ──────────────────────────────────────────────
131
+
132
+ .matcha-crop__canvas {
133
+ position: relative;
134
+ flex: 1;
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: center;
138
+ overflow: hidden;
139
+ min-height: 320px;
140
+ cursor: grab;
141
+ user-select: none;
142
+
143
+ &.is-interacting { cursor: grabbing; }
144
+ }
145
+
146
+ // `width/height: 100%` + `object-fit: contain` é o pareamento correto: força o
147
+ // IMG box a ocupar o canvas inteiro (mesmo pra natural < container), com o
148
+ // conteúdo escalado preservando aspect ratio. `max-width/height` causava bug
149
+ // em fotos menores que o canvas (ex: thumbnail 80×80 num modal 432×320): o
150
+ // browser não upscala via max-*, mas o JS calculava displayRatio = container/
151
+ // natural > 1 assumindo upscale, fazendo o mapeamento display→source ficar
152
+ // deslocado e o crop sair errado.
153
+ .matcha-crop__image {
154
+ width: 100%;
155
+ height: 100%;
156
+ object-fit: contain;
157
+ user-select: none;
158
+ -webkit-user-drag: none;
159
+ pointer-events: none;
160
+ transform-origin: center center;
161
+ will-change: transform;
162
+ transition: transform 80ms ease-out;
163
+ }
164
+
165
+ // ── Overlay (punch-out via clip-path) ───────────────────────────────────────
166
+
167
+ .matcha-crop__overlay {
168
+ position: absolute;
169
+ inset: 0;
170
+ pointer-events: none;
171
+ transition: clip-path 80ms ease-out;
172
+ }
173
+
174
+ // ── Crop area ───────────────────────────────────────────────────────────────
175
+
176
+ .matcha-crop__area {
177
+ position: absolute;
178
+ box-sizing: border-box;
179
+ cursor: move;
180
+ touch-action: none;
181
+
182
+ &--circle {
183
+ border-radius: 50%;
184
+ }
185
+ }
186
+
187
+ // Posicionado ACIMA da área de crop em vez do centro. Quando shape=circle,
188
+ // o texto do centro era cruzado pelo border (visualmente parecia cortado).
189
+ // Acima fica em zona de overlay escurecido, sempre legível.
190
+ .matcha-crop__hint {
191
+ position: absolute;
192
+ bottom: calc(100% + var(--matcha-space-100, 8px));
193
+ left: 50%;
194
+ transform: translateX(-50%);
195
+ padding: var(--matcha-space-050, 4px) var(--matcha-space-100, 8px);
196
+ font-size: 11px;
197
+ color: rgba(255, 255, 255, 0.85);
198
+ background: rgba(0, 0, 0, 0.7);
199
+ border-radius: var(--matcha-radius-sm, 2px);
200
+ pointer-events: none;
201
+ white-space: nowrap;
202
+ }
203
+
204
+ // ── Rule of thirds grid (mostra só durante interação) ──────────────────────
205
+
206
+ .matcha-crop__grid {
207
+ position: absolute;
208
+ inset: 0;
209
+ display: grid;
210
+ grid-template-columns: 1fr 1fr 1fr;
211
+ grid-template-rows: 1fr 1fr 1fr;
212
+ pointer-events: none;
213
+ }
214
+
215
+ .matcha-crop__grid-line {
216
+ &:nth-child(1) { grid-column: 2; grid-row: 1 / 4; width: 1px; justify-self: start; }
217
+ &:nth-child(2) { grid-column: 3; grid-row: 1 / 4; width: 1px; justify-self: start; }
218
+ &:nth-child(3) { grid-column: 1 / 4; grid-row: 2; height: 1px; align-self: start; }
219
+ &:nth-child(4) { grid-column: 1 / 4; grid-row: 3; height: 1px; align-self: start; }
220
+ }
221
+
222
+ // ── Resize handles (8 directions, 44×44 touch target) ──────────────────────
223
+
224
+ .matcha-crop__handle {
225
+ position: absolute;
226
+ width: var(--matcha-crop-handle-size, 16px);
227
+ height: var(--matcha-crop-handle-size, 16px);
228
+ margin: calc(-1 * var(--matcha-crop-handle-size, 16px) / 2);
229
+ padding: 0;
230
+ background: transparent;
231
+ border: var(--matcha-border-thin, 2px) solid transparent;
232
+ border-radius: 50%;
233
+ pointer-events: auto;
234
+ z-index: 2;
235
+ touch-action: none;
236
+
237
+ // Expand touch target via ::after (visual = 16px, hit = 44px)
238
+ &::after {
239
+ content: '';
240
+ position: absolute;
241
+ inset: -14px;
242
+ }
243
+
244
+ &:focus-visible {
245
+ outline: 2px solid var(--matcha-color-focus-ring);
246
+ outline-offset: 2px;
247
+ }
248
+ }
249
+
250
+ // ── Zoom bar ────────────────────────────────────────────────────────────────
251
+
252
+ .matcha-crop__zoom-bar {
253
+ position: absolute;
254
+ bottom: var(--matcha-space-200, 16px);
255
+ left: 50%;
256
+ transform: translateX(-50%);
257
+ display: flex;
258
+ align-items: center;
259
+ gap: var(--matcha-space-100, 8px);
260
+ padding: var(--matcha-space-075, 6px) var(--matcha-space-150, 12px);
261
+ border-radius: var(--matcha-radius-pill, 9999px);
262
+ backdrop-filter: blur(8px);
263
+ font-size: var(--matcha-text-body-sm, 12px);
264
+ z-index: 3;
265
+ }
266
+
267
+ .matcha-crop__zoom-slider {
268
+ -webkit-appearance: none;
269
+ appearance: none;
270
+ width: 160px;
271
+ height: 4px;
272
+ background: var(--matcha-color-surface-border);
273
+ border-radius: 2px;
274
+ cursor: pointer;
275
+ outline: none;
276
+
277
+ &::-webkit-slider-thumb {
278
+ -webkit-appearance: none;
279
+ width: 16px;
280
+ height: 16px;
281
+ background: var(--matcha-color-accent);
282
+ border: 2px solid var(--matcha-color-surface);
283
+ border-radius: 50%;
284
+ cursor: grab;
285
+ }
286
+ &::-moz-range-thumb {
287
+ width: 16px;
288
+ height: 16px;
289
+ background: var(--matcha-color-accent);
290
+ border: 2px solid var(--matcha-color-surface);
291
+ border-radius: 50%;
292
+ cursor: grab;
293
+ }
294
+ &:focus-visible::-webkit-slider-thumb {
295
+ box-shadow: 0 0 0 3px var(--matcha-color-focus-ring);
296
+ }
297
+ }
298
+
299
+ .matcha-crop__zoom-value {
300
+ min-width: 40px;
301
+ font-family: 'Fira Code', Consolas, monospace;
302
+ font-variant-numeric: tabular-nums;
303
+ text-align: right;
304
+ }
305
+
306
+ // ── States (empty / loading / error) ────────────────────────────────────────
307
+
308
+ .matcha-crop__state {
309
+ display: flex;
310
+ flex-direction: column;
311
+ align-items: center;
312
+ justify-content: center;
313
+ gap: var(--matcha-space-100, 8px);
314
+ padding: var(--matcha-space-300, 24px);
315
+ text-align: center;
316
+ max-width: 360px;
317
+ }
318
+
319
+ .matcha-crop__state-icon {
320
+ font-size: 48px;
321
+ width: 48px;
322
+ height: 48px;
323
+ --matcha-icon-color: currentColor;
324
+
325
+ &--spin {
326
+ animation: matcha-crop-spin 1.2s linear infinite;
327
+ }
328
+ }
329
+
330
+ .matcha-crop__state-title {
331
+ margin: 0;
332
+ font-size: var(--matcha-text-title-sm, 16px);
333
+ font-weight: var(--matcha-weight-semibold, 600);
334
+ }
335
+
336
+ .matcha-crop__state-desc {
337
+ margin: 0;
338
+ font-size: var(--matcha-text-body-sm, 12px);
339
+ line-height: 1.4;
340
+
341
+ code {
342
+ padding: 2px 6px;
343
+ background: var(--matcha-color-surface-card);
344
+ border-radius: var(--matcha-radius-sm, 2px);
345
+ font-family: 'Fira Code', Consolas, monospace;
346
+ font-size: 11px;
347
+ }
348
+ }
349
+
350
+ @keyframes matcha-crop-spin {
351
+ to { transform: rotate(360deg); }
352
+ }
353
+
354
+ // ── SR-only live region ────────────────────────────────────────────────────
355
+
356
+ .matcha-crop__sr-live {
357
+ position: absolute;
358
+ width: 1px;
359
+ height: 1px;
360
+ padding: 0;
361
+ margin: -1px;
362
+ overflow: hidden;
363
+ clip: rect(0, 0, 0, 0);
364
+ white-space: nowrap;
365
+ border: 0;
366
+ }
367
+
368
+ // ── Footer ──────────────────────────────────────────────────────────────────
369
+ // Footer só ocupa espaço quando ng-content tem children projetados.
370
+ // Truque CSS: empty footer fica height 0 via :has() — quando vazio, esconde.
371
+
372
+ .matcha-crop__footer {
373
+ display: flex;
374
+ align-items: center;
375
+ justify-content: flex-end;
376
+ gap: var(--matcha-space-100, 8px);
377
+ padding: var(--matcha-space-200, 16px) var(--matcha-space-300, 24px);
378
+ flex-shrink: 0;
379
+
380
+ &:empty {
381
+ padding: 0;
382
+ }
383
+ }
384
+
385
+ // ── Responsive ──────────────────────────────────────────────────────────────
386
+
387
+ @media (max-width: 640px) {
388
+ .matcha-crop__header,
389
+ .matcha-crop__footer {
390
+ padding: var(--matcha-space-150, 12px) var(--matcha-space-200, 16px);
391
+ }
392
+ .matcha-crop__canvas { min-height: 280px; }
393
+ .matcha-crop__zoom-slider { width: 120px; }
394
+ }
395
+
396
+ // ── Reduced motion ──────────────────────────────────────────────────────────
397
+
398
+ @media (prefers-reduced-motion: reduce) {
399
+ .matcha-crop__image,
400
+ .matcha-crop__overlay {
401
+ transition: none;
402
+ }
403
+ .matcha-crop__state-icon--spin {
404
+ animation: none;
405
+ }
406
+ }