@attrus-ds/core 0.2.0 → 0.3.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 (80) hide show
  1. package/LICENSE +27 -27
  2. package/dist/assets/flags/Brazil-rounded.svg +15 -15
  3. package/dist/assets/flags/Brazil-square.svg +16 -16
  4. package/dist/assets/flags/Chile-rounded.svg +10 -10
  5. package/dist/assets/flags/Chile-square.svg +10 -10
  6. package/dist/assets/flags/Colombia-rounded.svg +9 -9
  7. package/dist/assets/flags/Colombia-square.svg +9 -9
  8. package/dist/assets/flags/EUA-rounded.svg +10 -10
  9. package/dist/assets/flags/EUA-square.svg +10 -10
  10. package/dist/assets/flags/EUR-rounded.svg +8 -8
  11. package/dist/assets/flags/EUR-square.svg +8 -8
  12. package/dist/assets/flags/Mexico-rounded.svg +18 -18
  13. package/dist/assets/flags/Mexico-square.svg +18 -18
  14. package/dist/assets/icon-attrus-dark.svg +2 -2
  15. package/dist/assets/icon-attrus-light.svg +2 -2
  16. package/dist/assets/logo-attrus-dark.svg +7 -7
  17. package/dist/assets/logo-attrus-light.svg +7 -7
  18. package/dist/css/components/buttons.css +301 -301
  19. package/dist/css/components/callout.css +195 -195
  20. package/dist/css/components/cards.css +272 -272
  21. package/dist/css/components/combobox.css +319 -319
  22. package/dist/css/components/empty-states.css +61 -61
  23. package/dist/css/components/inputs.css +975 -975
  24. package/dist/css/components/number-input.css +138 -138
  25. package/dist/css/components/overlays.css +374 -374
  26. package/dist/css/components/primitives.css +314 -314
  27. package/dist/css/components/sidebar.css +179 -179
  28. package/dist/css/components/smart-search.css +91 -91
  29. package/dist/css/components/status-pills.css +207 -207
  30. package/dist/css/components/stepper.css +309 -309
  31. package/dist/css/components/table.css +602 -602
  32. package/dist/css/components/tabs.css +319 -319
  33. package/dist/css/components/toast.css +243 -243
  34. package/dist/css/components/tooltip.css +231 -231
  35. package/dist/css/components/topbar.css +148 -148
  36. package/dist/css/tokens.css +666 -666
  37. package/dist/react/AppSidebar/AppSidebar.d.ts +50 -50
  38. package/dist/react/AppSidebar/AppSidebar.tsx +197 -197
  39. package/dist/react/AppTopbar/AppTopbar.d.ts +58 -58
  40. package/dist/react/AppTopbar/AppTopbar.tsx +203 -203
  41. package/dist/react/Atoms/Atoms.d.ts +149 -149
  42. package/dist/react/Atoms/Atoms.tsx +407 -407
  43. package/dist/react/Button/Button.d.ts +25 -25
  44. package/dist/react/Button/Button.tsx +83 -83
  45. package/dist/react/Callout/Callout.d.ts +29 -29
  46. package/dist/react/Callout/Callout.tsx +98 -98
  47. package/dist/react/Card/Card.d.ts +38 -38
  48. package/dist/react/Card/Card.tsx +93 -93
  49. package/dist/react/Combobox/Combobox.d.ts +52 -52
  50. package/dist/react/Combobox/Combobox.tsx +254 -254
  51. package/dist/react/DataTable/DataTable.d.ts +81 -81
  52. package/dist/react/DataTable/DataTable.tsx +308 -308
  53. package/dist/react/Drawer/Drawer.d.ts +35 -35
  54. package/dist/react/Drawer/Drawer.tsx +226 -226
  55. package/dist/react/Input/Input.d.ts +155 -155
  56. package/dist/react/Input/Input.tsx +478 -478
  57. package/dist/react/Modal/Modal.d.ts +27 -27
  58. package/dist/react/Modal/Modal.tsx +173 -173
  59. package/dist/react/NumberInput/NumberInput.d.ts +25 -25
  60. package/dist/react/NumberInput/NumberInput.tsx +117 -117
  61. package/dist/react/Pill/Pill.d.ts +31 -31
  62. package/dist/react/Pill/Pill.tsx +104 -104
  63. package/dist/react/SearchPill/SearchPill.d.ts +14 -14
  64. package/dist/react/SearchPill/SearchPill.tsx +40 -40
  65. package/dist/react/SmartSearch/SmartSearch.d.ts +65 -65
  66. package/dist/react/SmartSearch/SmartSearch.tsx +271 -271
  67. package/dist/react/Stepper/Stepper.d.ts +25 -25
  68. package/dist/react/Stepper/Stepper.tsx +94 -94
  69. package/dist/react/Tabs/Tabs.d.ts +32 -32
  70. package/dist/react/Tabs/Tabs.tsx +147 -147
  71. package/dist/react/Toast/Toast.d.ts +30 -30
  72. package/dist/react/Toast/Toast.tsx +94 -94
  73. package/dist/react/Tooltip/Tooltip.d.ts +23 -23
  74. package/dist/react/Tooltip/Tooltip.tsx +80 -80
  75. package/dist/react/ZeroState/ZeroState.d.ts +17 -17
  76. package/dist/react/ZeroState/ZeroState.tsx +45 -45
  77. package/dist/react/index.ts +35 -35
  78. package/dist/tokens/attrus-tokens.flat.json +1234 -1234
  79. package/dist/tokens/attrus-tokens.json +1089 -1089
  80. package/package.json +64 -64
@@ -1,243 +1,243 @@
1
- /* ============================================================
2
- TOAST COMPONENT — ATTRUS Design System
3
- Ephemeral feedback after an action. Auto-dismiss, non-blocking.
4
- All values from tokens.
5
- ============================================================ */
6
-
7
- .toast {
8
- display: grid;
9
- grid-template-columns: auto 1fr auto;
10
- align-items: flex-start;
11
- gap: var(--space-3);
12
- min-width: 320px;
13
- max-width: 480px;
14
- padding: var(--space-4) var(--space-5);
15
- background: var(--glass-white);
16
- -webkit-backdrop-filter: var(--glass-blur);
17
- backdrop-filter: var(--glass-blur);
18
- border: var(--glass-border);
19
- border-radius: var(--radius-md);
20
- box-shadow: var(--shadow-glass), var(--shadow-lg);
21
- font-family: var(--font-sans);
22
- font-size: var(--fs-sm);
23
- line-height: var(--lh-normal);
24
- color: var(--color-foreground-default);
25
- position: relative;
26
- overflow: hidden;
27
- }
28
-
29
- /* Fallback for browsers without backdrop-filter — go back to a solid
30
- surface so text never loses contrast. */
31
- @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
32
- .toast { background: var(--color-background-surface); box-shadow: var(--shadow-lg); }
33
- }
34
-
35
- /* Leading icon container */
36
- .toast-icon {
37
- display: inline-flex;
38
- align-items: center;
39
- justify-content: center;
40
- width: var(--icon-md);
41
- height: var(--icon-md);
42
- flex-shrink: 0;
43
- margin-top: 2px;
44
- }
45
- .toast-icon i, .toast-icon svg {
46
- width: var(--icon-md);
47
- height: var(--icon-md);
48
- stroke-width: var(--icon-stroke);
49
- }
50
-
51
- /* Body — title + description */
52
- .toast-body {
53
- min-width: 0;
54
- }
55
- .toast-title {
56
- font-size: var(--fs-sm);
57
- font-weight: var(--w-semibold);
58
- color: var(--color-foreground-default);
59
- margin: 0 0 var(--space-1);
60
- letter-spacing: var(--ls-tight);
61
- }
62
- .toast-desc {
63
- font-size: var(--fs-sm);
64
- color: var(--color-foreground-secondary);
65
- line-height: var(--lh-relaxed);
66
- margin: 0;
67
- }
68
-
69
- /* Inline action link */
70
- .toast-action {
71
- display: inline-block;
72
- margin-top: var(--space-2);
73
- background: transparent;
74
- border: 0;
75
- padding: 0;
76
- font: inherit;
77
- font-weight: var(--w-semibold);
78
- color: var(--color-foreground-accent);
79
- text-decoration: underline;
80
- text-underline-offset: 3px;
81
- cursor: pointer;
82
- }
83
- .toast-action:hover { color: var(--color-brand-secondary-700); }
84
- .toast-action:focus-visible {
85
- outline: none;
86
- box-shadow: var(--shadow-focus);
87
- border-radius: var(--radius-xs);
88
- }
89
-
90
- /* Close button */
91
- .toast-close {
92
- display: inline-flex;
93
- align-items: center;
94
- justify-content: center;
95
- width: 24px; height: 24px;
96
- border-radius: var(--radius-xs);
97
- background: transparent;
98
- border: 0;
99
- color: var(--color-foreground-muted);
100
- cursor: pointer;
101
- flex-shrink: 0;
102
- margin-top: -2px;
103
- transition: var(--transition-fast);
104
- }
105
- .toast-close:hover { background: var(--color-background-hover); color: var(--color-foreground-default); }
106
- .toast-close:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
107
- .toast-close i, .toast-close svg { width: var(--icon-sm); height: var(--icon-sm); stroke-width: var(--icon-stroke); }
108
-
109
- /* Progress (auto-dismiss countdown) — bottom hairline */
110
- .toast-progress {
111
- position: absolute;
112
- bottom: 0; left: 0; right: 0;
113
- height: 2px;
114
- background: var(--color-border-subtle);
115
- overflow: hidden;
116
- }
117
- .toast-progress::after {
118
- content: "";
119
- position: block;
120
- display: block;
121
- height: 100%;
122
- width: 100%;
123
- background: var(--color-foreground-muted);
124
- transform-origin: left;
125
- animation: toast-progress var(--toast-duration, 5000ms) linear forwards;
126
- }
127
-
128
- @keyframes toast-progress {
129
- from { transform: scaleX(1); }
130
- to { transform: scaleX(0); }
131
- }
132
-
133
- /* Auto-dismiss must pause while the user inspects (doc a11y contract) */
134
- .toast:hover .toast-progress::after,
135
- .toast:focus-within .toast-progress::after { animation-play-state: paused; }
136
-
137
- /* ============================================================
138
- VARIANTS — semantic
139
- ============================================================ */
140
-
141
- /* Default (neutral, plain) — uses defaults above */
142
-
143
- /* Success */
144
- .toast-success { border-left: 3px solid var(--color-feedback-success-border); }
145
- .toast-success .toast-icon { color: var(--color-feedback-success-foreground); }
146
- .toast-success .toast-progress::after { background: var(--color-feedback-success-foreground); }
147
-
148
- /* Warning */
149
- .toast-warning { border-left: 3px solid var(--color-feedback-warning-border); }
150
- .toast-warning .toast-icon { color: var(--color-feedback-warning-foreground); }
151
- .toast-warning .toast-progress::after { background: var(--color-feedback-warning-foreground); }
152
-
153
- /* Danger */
154
- .toast-danger { border-left: 3px solid var(--color-feedback-danger-border); }
155
- .toast-danger .toast-icon { color: var(--color-feedback-danger-foreground); }
156
- .toast-danger .toast-progress::after { background: var(--color-feedback-danger-foreground); }
157
-
158
- /* Info */
159
- .toast-info { border-left: 3px solid var(--color-feedback-info-border); }
160
- .toast-info .toast-icon { color: var(--color-feedback-info-foreground); }
161
- .toast-info .toast-progress::after { background: var(--color-feedback-info-foreground); }
162
-
163
- /* Brand (announcement / non-feedback messages) */
164
- .toast-brand { border-left: 3px solid var(--color-brand-secondary-300); }
165
- .toast-brand .toast-icon { color: var(--color-foreground-accent); }
166
- .toast-brand .toast-progress::after { background: var(--color-foreground-accent); }
167
-
168
- /* Inverse (over photo, dark hero, etc.) */
169
- .toast-inverse {
170
- background: var(--glass-ink);
171
- -webkit-backdrop-filter: var(--glass-blur);
172
- backdrop-filter: var(--glass-blur);
173
- border: var(--glass-border-dark);
174
- box-shadow: var(--shadow-glass-dark), var(--shadow-2xl);
175
- }
176
- @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
177
- .toast-inverse { background: var(--color-background-inverse); box-shadow: var(--shadow-2xl); }
178
- }
179
- .toast-inverse .toast-title { color: var(--color-foreground-inverse-default); }
180
- .toast-inverse .toast-desc { color: var(--color-foreground-inverse-muted); }
181
- .toast-inverse .toast-close { color: var(--color-foreground-inverse-muted); }
182
- .toast-inverse .toast-close:hover { background: var(--color-background-inverse-hover); color: var(--color-foreground-inverse-default); }
183
- .toast-inverse .toast-action { color: var(--color-foreground-on-solid); }
184
- .toast-inverse .toast-action:hover { color: var(--color-brand-secondary-100); }
185
-
186
- /* ============================================================
187
- STACK — viewport positioning
188
- ============================================================ */
189
-
190
- .toast-stack {
191
- position: fixed;
192
- display: flex;
193
- flex-direction: column;
194
- gap: var(--space-3);
195
- z-index: 9000;
196
- pointer-events: none;
197
- }
198
- .toast-stack > .toast { pointer-events: auto; }
199
-
200
- .toast-stack-tr { top: var(--space-6); right: var(--space-6); align-items: flex-end; }
201
- .toast-stack-tl { top: var(--space-6); left: var(--space-6); align-items: flex-start; }
202
- .toast-stack-tc { top: var(--space-6); left: 50%; transform: translateX(-50%); align-items: center; }
203
- .toast-stack-br { bottom: var(--space-6); right: var(--space-6); align-items: flex-end; flex-direction: column-reverse; }
204
- .toast-stack-bl { bottom: var(--space-6); left: var(--space-6); align-items: flex-start; flex-direction: column-reverse; }
205
- .toast-stack-bc { bottom: var(--space-6); left: 50%; transform: translateX(-50%); align-items: center; flex-direction: column-reverse; }
206
-
207
- /* ============================================================
208
- ENTER / EXIT animations
209
- ============================================================ */
210
-
211
- @keyframes toast-enter-right {
212
- from { opacity: 0; transform: translateX(16px); }
213
- to { opacity: 1; transform: translateX(0); }
214
- }
215
- @keyframes toast-enter-left {
216
- from { opacity: 0; transform: translateX(-16px); }
217
- to { opacity: 1; transform: translateX(0); }
218
- }
219
- @keyframes toast-enter-down {
220
- from { opacity: 0; transform: translateY(-12px); }
221
- to { opacity: 1; transform: translateY(0); }
222
- }
223
- @keyframes toast-enter-up {
224
- from { opacity: 0; transform: translateY(12px); }
225
- to { opacity: 1; transform: translateY(0); }
226
- }
227
-
228
- .toast-stack-tr > .toast, .toast-stack-br > .toast { animation: toast-enter-right var(--duration-base) var(--ease-emphasis) both; }
229
- .toast-stack-tl > .toast, .toast-stack-bl > .toast { animation: toast-enter-left var(--duration-base) var(--ease-emphasis) both; }
230
- .toast-stack-tc > .toast { animation: toast-enter-down var(--duration-base) var(--ease-emphasis) both; }
231
- .toast-stack-bc > .toast { animation: toast-enter-up var(--duration-base) var(--ease-emphasis) both; }
232
-
233
- /* Exit — applied via .is-leaving class set by JS before removing */
234
- .toast.is-leaving { animation: toast-exit var(--duration-fast) var(--ease-standard) both; }
235
- @keyframes toast-exit {
236
- from { opacity: 1; transform: translateX(0) translateY(0) scale(1); }
237
- to { opacity: 0; transform: translateY(-4px) scale(0.96); }
238
- }
239
-
240
- @media (prefers-reduced-motion: reduce) {
241
- .toast-stack > .toast { animation: none; }
242
- .toast-progress::after { animation: none; }
243
- }
1
+ /* ============================================================
2
+ TOAST COMPONENT — ATTRUS Design System
3
+ Ephemeral feedback after an action. Auto-dismiss, non-blocking.
4
+ All values from tokens.
5
+ ============================================================ */
6
+
7
+ .toast {
8
+ display: grid;
9
+ grid-template-columns: auto 1fr auto;
10
+ align-items: flex-start;
11
+ gap: var(--space-3);
12
+ min-width: 320px;
13
+ max-width: 480px;
14
+ padding: var(--space-4) var(--space-5);
15
+ background: var(--glass-white);
16
+ -webkit-backdrop-filter: var(--glass-blur);
17
+ backdrop-filter: var(--glass-blur);
18
+ border: var(--glass-border);
19
+ border-radius: var(--radius-md);
20
+ box-shadow: var(--shadow-glass), var(--shadow-lg);
21
+ font-family: var(--font-sans);
22
+ font-size: var(--fs-sm);
23
+ line-height: var(--lh-normal);
24
+ color: var(--color-foreground-default);
25
+ position: relative;
26
+ overflow: hidden;
27
+ }
28
+
29
+ /* Fallback for browsers without backdrop-filter — go back to a solid
30
+ surface so text never loses contrast. */
31
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
32
+ .toast { background: var(--color-background-surface); box-shadow: var(--shadow-lg); }
33
+ }
34
+
35
+ /* Leading icon container */
36
+ .toast-icon {
37
+ display: inline-flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ width: var(--icon-md);
41
+ height: var(--icon-md);
42
+ flex-shrink: 0;
43
+ margin-top: 2px;
44
+ }
45
+ .toast-icon i, .toast-icon svg {
46
+ width: var(--icon-md);
47
+ height: var(--icon-md);
48
+ stroke-width: var(--icon-stroke);
49
+ }
50
+
51
+ /* Body — title + description */
52
+ .toast-body {
53
+ min-width: 0;
54
+ }
55
+ .toast-title {
56
+ font-size: var(--fs-sm);
57
+ font-weight: var(--w-semibold);
58
+ color: var(--color-foreground-default);
59
+ margin: 0 0 var(--space-1);
60
+ letter-spacing: var(--ls-tight);
61
+ }
62
+ .toast-desc {
63
+ font-size: var(--fs-sm);
64
+ color: var(--color-foreground-secondary);
65
+ line-height: var(--lh-relaxed);
66
+ margin: 0;
67
+ }
68
+
69
+ /* Inline action link */
70
+ .toast-action {
71
+ display: inline-block;
72
+ margin-top: var(--space-2);
73
+ background: transparent;
74
+ border: 0;
75
+ padding: 0;
76
+ font: inherit;
77
+ font-weight: var(--w-semibold);
78
+ color: var(--color-foreground-accent);
79
+ text-decoration: underline;
80
+ text-underline-offset: 3px;
81
+ cursor: pointer;
82
+ }
83
+ .toast-action:hover { color: var(--color-brand-secondary-700); }
84
+ .toast-action:focus-visible {
85
+ outline: none;
86
+ box-shadow: var(--shadow-focus);
87
+ border-radius: var(--radius-xs);
88
+ }
89
+
90
+ /* Close button */
91
+ .toast-close {
92
+ display: inline-flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ width: 24px; height: 24px;
96
+ border-radius: var(--radius-xs);
97
+ background: transparent;
98
+ border: 0;
99
+ color: var(--color-foreground-muted);
100
+ cursor: pointer;
101
+ flex-shrink: 0;
102
+ margin-top: -2px;
103
+ transition: var(--transition-fast);
104
+ }
105
+ .toast-close:hover { background: var(--color-background-hover); color: var(--color-foreground-default); }
106
+ .toast-close:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
107
+ .toast-close i, .toast-close svg { width: var(--icon-sm); height: var(--icon-sm); stroke-width: var(--icon-stroke); }
108
+
109
+ /* Progress (auto-dismiss countdown) — bottom hairline */
110
+ .toast-progress {
111
+ position: absolute;
112
+ bottom: 0; left: 0; right: 0;
113
+ height: 2px;
114
+ background: var(--color-border-subtle);
115
+ overflow: hidden;
116
+ }
117
+ .toast-progress::after {
118
+ content: "";
119
+ position: block;
120
+ display: block;
121
+ height: 100%;
122
+ width: 100%;
123
+ background: var(--color-foreground-muted);
124
+ transform-origin: left;
125
+ animation: toast-progress var(--toast-duration, 5000ms) linear forwards;
126
+ }
127
+
128
+ @keyframes toast-progress {
129
+ from { transform: scaleX(1); }
130
+ to { transform: scaleX(0); }
131
+ }
132
+
133
+ /* Auto-dismiss must pause while the user inspects (doc a11y contract) */
134
+ .toast:hover .toast-progress::after,
135
+ .toast:focus-within .toast-progress::after { animation-play-state: paused; }
136
+
137
+ /* ============================================================
138
+ VARIANTS — semantic
139
+ ============================================================ */
140
+
141
+ /* Default (neutral, plain) — uses defaults above */
142
+
143
+ /* Success */
144
+ .toast-success { border-left: 3px solid var(--color-feedback-success-border); }
145
+ .toast-success .toast-icon { color: var(--color-feedback-success-foreground); }
146
+ .toast-success .toast-progress::after { background: var(--color-feedback-success-foreground); }
147
+
148
+ /* Warning */
149
+ .toast-warning { border-left: 3px solid var(--color-feedback-warning-border); }
150
+ .toast-warning .toast-icon { color: var(--color-feedback-warning-foreground); }
151
+ .toast-warning .toast-progress::after { background: var(--color-feedback-warning-foreground); }
152
+
153
+ /* Danger */
154
+ .toast-danger { border-left: 3px solid var(--color-feedback-danger-border); }
155
+ .toast-danger .toast-icon { color: var(--color-feedback-danger-foreground); }
156
+ .toast-danger .toast-progress::after { background: var(--color-feedback-danger-foreground); }
157
+
158
+ /* Info */
159
+ .toast-info { border-left: 3px solid var(--color-feedback-info-border); }
160
+ .toast-info .toast-icon { color: var(--color-feedback-info-foreground); }
161
+ .toast-info .toast-progress::after { background: var(--color-feedback-info-foreground); }
162
+
163
+ /* Brand (announcement / non-feedback messages) */
164
+ .toast-brand { border-left: 3px solid var(--color-brand-secondary-300); }
165
+ .toast-brand .toast-icon { color: var(--color-foreground-accent); }
166
+ .toast-brand .toast-progress::after { background: var(--color-foreground-accent); }
167
+
168
+ /* Inverse (over photo, dark hero, etc.) */
169
+ .toast-inverse {
170
+ background: var(--glass-ink);
171
+ -webkit-backdrop-filter: var(--glass-blur);
172
+ backdrop-filter: var(--glass-blur);
173
+ border: var(--glass-border-dark);
174
+ box-shadow: var(--shadow-glass-dark), var(--shadow-2xl);
175
+ }
176
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
177
+ .toast-inverse { background: var(--color-background-inverse); box-shadow: var(--shadow-2xl); }
178
+ }
179
+ .toast-inverse .toast-title { color: var(--color-foreground-inverse-default); }
180
+ .toast-inverse .toast-desc { color: var(--color-foreground-inverse-muted); }
181
+ .toast-inverse .toast-close { color: var(--color-foreground-inverse-muted); }
182
+ .toast-inverse .toast-close:hover { background: var(--color-background-inverse-hover); color: var(--color-foreground-inverse-default); }
183
+ .toast-inverse .toast-action { color: var(--color-foreground-on-solid); }
184
+ .toast-inverse .toast-action:hover { color: var(--color-brand-secondary-100); }
185
+
186
+ /* ============================================================
187
+ STACK — viewport positioning
188
+ ============================================================ */
189
+
190
+ .toast-stack {
191
+ position: fixed;
192
+ display: flex;
193
+ flex-direction: column;
194
+ gap: var(--space-3);
195
+ z-index: 9000;
196
+ pointer-events: none;
197
+ }
198
+ .toast-stack > .toast { pointer-events: auto; }
199
+
200
+ .toast-stack-tr { top: var(--space-6); right: var(--space-6); align-items: flex-end; }
201
+ .toast-stack-tl { top: var(--space-6); left: var(--space-6); align-items: flex-start; }
202
+ .toast-stack-tc { top: var(--space-6); left: 50%; transform: translateX(-50%); align-items: center; }
203
+ .toast-stack-br { bottom: var(--space-6); right: var(--space-6); align-items: flex-end; flex-direction: column-reverse; }
204
+ .toast-stack-bl { bottom: var(--space-6); left: var(--space-6); align-items: flex-start; flex-direction: column-reverse; }
205
+ .toast-stack-bc { bottom: var(--space-6); left: 50%; transform: translateX(-50%); align-items: center; flex-direction: column-reverse; }
206
+
207
+ /* ============================================================
208
+ ENTER / EXIT animations
209
+ ============================================================ */
210
+
211
+ @keyframes toast-enter-right {
212
+ from { opacity: 0; transform: translateX(16px); }
213
+ to { opacity: 1; transform: translateX(0); }
214
+ }
215
+ @keyframes toast-enter-left {
216
+ from { opacity: 0; transform: translateX(-16px); }
217
+ to { opacity: 1; transform: translateX(0); }
218
+ }
219
+ @keyframes toast-enter-down {
220
+ from { opacity: 0; transform: translateY(-12px); }
221
+ to { opacity: 1; transform: translateY(0); }
222
+ }
223
+ @keyframes toast-enter-up {
224
+ from { opacity: 0; transform: translateY(12px); }
225
+ to { opacity: 1; transform: translateY(0); }
226
+ }
227
+
228
+ .toast-stack-tr > .toast, .toast-stack-br > .toast { animation: toast-enter-right var(--duration-base) var(--ease-emphasis) both; }
229
+ .toast-stack-tl > .toast, .toast-stack-bl > .toast { animation: toast-enter-left var(--duration-base) var(--ease-emphasis) both; }
230
+ .toast-stack-tc > .toast { animation: toast-enter-down var(--duration-base) var(--ease-emphasis) both; }
231
+ .toast-stack-bc > .toast { animation: toast-enter-up var(--duration-base) var(--ease-emphasis) both; }
232
+
233
+ /* Exit — applied via .is-leaving class set by JS before removing */
234
+ .toast.is-leaving { animation: toast-exit var(--duration-fast) var(--ease-standard) both; }
235
+ @keyframes toast-exit {
236
+ from { opacity: 1; transform: translateX(0) translateY(0) scale(1); }
237
+ to { opacity: 0; transform: translateY(-4px) scale(0.96); }
238
+ }
239
+
240
+ @media (prefers-reduced-motion: reduce) {
241
+ .toast-stack > .toast { animation: none; }
242
+ .toast-progress::after { animation: none; }
243
+ }