astralkit 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.
@@ -0,0 +1,410 @@
1
+
2
+
3
+ /* Avatar primitives -- base, sizes, colors, shapes, groups, progress, rings, faces */
4
+
5
+
6
+
7
+ /* Avatar base */
8
+ .ak-avatar {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ border-radius: var(--radius-ak-full);
13
+ overflow: hidden;
14
+ position: relative;
15
+ flex-shrink: 0;
16
+ background: var(--color-ak-surface-2);
17
+ color: var(--color-ak-text-secondary);
18
+ font-weight: 600;
19
+ line-height: 1;
20
+ letter-spacing: 0.01em;
21
+ user-select: none;
22
+ -webkit-font-smoothing: antialiased;
23
+ border: none;
24
+ /* Fix jagged circle edge from overflow:hidden + border-radius.
25
+ Inset shadow acts as an AA layer at the clip boundary. */
26
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.04);
27
+ }
28
+ .ak-avatar img {
29
+ width: 100%;
30
+ height: 100%;
31
+ object-fit: cover;
32
+ display: block;
33
+ filter: grayscale(100%);
34
+ }
35
+
36
+ /* Size modifiers */
37
+ .ak-avatar--md { width: var(--size-ak-avatar-md); height: var(--size-ak-avatar-md); font-size: var(--text-ak-avatar-md); font-weight: 600; }
38
+ .ak-avatar--md i { font-size: var(--size-ak-icon-md); }
39
+ .ak-avatar--lg { width: var(--size-ak-avatar-lg); height: var(--size-ak-avatar-lg); font-size: var(--text-ak-avatar-lg); font-weight: 600; }
40
+ .ak-avatar--lg i { font-size: var(--size-ak-icon-lg); }
41
+ .ak-avatar--xl { width: var(--size-ak-avatar-xl); height: var(--size-ak-avatar-xl); font-size: var(--text-ak-avatar-xl); font-weight: 500; }
42
+ .ak-avatar--xl i { font-size: var(--size-ak-icon-xl); }
43
+ .ak-avatar--2xl { width: var(--size-ak-avatar-2xl); height: var(--size-ak-avatar-2xl); font-size: var(--text-ak-avatar-2xl); font-weight: 500; }
44
+ .ak-avatar--2xl i { font-size: var(--size-ak-icon-2xl); }
45
+ .ak-avatar--3xl { width: var(--size-ak-avatar-3xl); height: var(--size-ak-avatar-3xl); font-size: var(--text-ak-avatar-3xl); font-weight: 500; }
46
+ .ak-avatar--3xl i { font-size: var(--size-ak-icon-3xl); }
47
+
48
+ /* Color variants */
49
+ .ak-avatar--primary { background: var(--color-ak-primary); color: var(--color-ak-on-primary); }
50
+ .ak-avatar--success { background: var(--color-ak-success-subtle); color: var(--color-ak-success-text); }
51
+ .ak-avatar--warning { background: var(--color-ak-warning-subtle); color: var(--color-ak-warning-text); }
52
+ .ak-avatar--danger { background: var(--color-ak-danger-subtle); color: var(--color-ak-danger-text); }
53
+ .ak-avatar--info { background: var(--color-ak-info-subtle); color: var(--color-ak-info-text); }
54
+ .ak-avatar--surface { background: var(--color-ak-surface-2); color: var(--color-ak-text-secondary); }
55
+
56
+ /* Shape variants */
57
+ .ak-avatar--rounded { border-radius: var(--radius-ak-lg); }
58
+ .ak-avatar--square { border-radius: var(--radius-ak-sm); }
59
+
60
+ /* Interactive avatar */
61
+ .ak-avatar--interactive {
62
+ cursor: pointer;
63
+ transition: transform var(--duration-ak-fast) var(--ease-ak-default),
64
+ box-shadow var(--duration-ak-fast) var(--ease-ak-default);
65
+ }
66
+ .ak-avatar--interactive:hover { transform: scale(1.08); }
67
+ .ak-avatar--interactive:active { transform: scale(0.96); }
68
+ .ak-avatar--interactive:focus-visible {
69
+ outline: 2px solid var(--color-ak-border-focus);
70
+ outline-offset: 2px;
71
+ }
72
+
73
+ /* Ring variants — outline + box-shadow approach eliminates the subpixel
74
+ bleed artifact that occurs with multi-layer box-shadows.
75
+ - box-shadow: white gap (covers the element edge cleanly)
76
+ - outline: colored ring (separate compositing layer, no bleed) */
77
+ .ak-avatar--ring-primary { box-shadow: 0 0 0 var(--ak-ring-gap, 3px) var(--color-ak-bg); outline: var(--ak-ring-width, 3px) solid var(--color-ak-primary); outline-offset: var(--ak-ring-gap, 3px); }
78
+ .ak-avatar--ring-success { box-shadow: 0 0 0 var(--ak-ring-gap, 3px) var(--color-ak-bg); outline: var(--ak-ring-width, 3px) solid var(--color-ak-success); outline-offset: var(--ak-ring-gap, 3px); }
79
+ .ak-avatar--ring-warning { box-shadow: 0 0 0 var(--ak-ring-gap, 3px) var(--color-ak-bg); outline: var(--ak-ring-width, 3px) solid var(--color-ak-warning); outline-offset: var(--ak-ring-gap, 3px); }
80
+ .ak-avatar--ring-info { box-shadow: 0 0 0 var(--ak-ring-gap, 3px) var(--color-ak-bg); outline: var(--ak-ring-width, 3px) solid var(--color-ak-info); outline-offset: var(--ak-ring-gap, 3px); }
81
+ .ak-avatar--ring-border { box-shadow: 0 0 0 1px var(--color-ak-border); }
82
+
83
+ /* Scale ring per avatar size */
84
+ .ak-avatar--md[class*="ak-avatar--ring-"] { --ak-ring-gap: 2px; --ak-ring-width: 2px; }
85
+ .ak-avatar--lg[class*="ak-avatar--ring-"] { --ak-ring-gap: 2px; --ak-ring-width: 2px; }
86
+ .ak-avatar--xl[class*="ak-avatar--ring-"] { --ak-ring-gap: 2px; --ak-ring-width: 3px; }
87
+ .ak-avatar--2xl[class*="ak-avatar--ring-"] { --ak-ring-gap: 3px; --ak-ring-width: 3px; }
88
+ .ak-avatar--3xl[class*="ak-avatar--ring-"] { --ak-ring-gap: 3px; --ak-ring-width: 4px; }
89
+
90
+ /* Fallback (initials/icon shown when image fails) */
91
+ .ak-avatar__fallback { display: none; }
92
+ .ak-avatar--fallback img { display: none; }
93
+ .ak-avatar--fallback .ak-avatar__fallback {
94
+ display: flex;
95
+ align-items: center;
96
+ justify-content: center;
97
+ width: 100%;
98
+ height: 100%;
99
+ }
100
+
101
+ /* Avatar wrap (positions badges/status relative to avatar) */
102
+ .ak-avatar-wrap { position: relative; display: inline-flex; flex-shrink: 0; }
103
+
104
+ /* Wrap size modifiers for badge/status positioning */
105
+ .ak-avatar-wrap--md .ak-status-dot { width: var(--size-ak-status-md); height: var(--size-ak-status-md); border: var(--size-ak-badge-border-md) solid var(--color-ak-bg); bottom: var(--offset-ak-status-md); right: var(--offset-ak-status-md); }
106
+ .ak-avatar-wrap--md .ak-status-dot--dnd::after { width: 7px; height: 1.5px; }
107
+ .ak-avatar-wrap--md .ak-badge { min-width: var(--size-ak-status-md); height: var(--size-ak-status-md); border: var(--size-ak-badge-border-md) solid var(--color-ak-bg); top: var(--offset-ak-status-md); right: var(--offset-ak-status-md); }
108
+ .ak-avatar-wrap--md .ak-badge--count { min-width: var(--size-ak-badge-md); height: var(--size-ak-badge-md); font-size: var(--text-ak-badge-md); top: var(--offset-ak-badge-md-top, var(--offset-ak-badge-md)); right: var(--offset-ak-badge-md-right, var(--offset-ak-badge-md)); --ak-badge-pad: 2px; }
109
+ .ak-avatar-wrap--md .ak-notif-badge { min-width: var(--size-ak-badge-md); height: var(--size-ak-badge-md); font-size: var(--text-ak-badge-md); top: var(--offset-ak-badge-md); right: var(--offset-ak-badge-md); }
110
+ .ak-avatar-wrap--md .ak-rank-badge { width: var(--size-ak-icon-badge-md); height: var(--size-ak-icon-badge-md); font-size: 0.625rem; border: var(--size-ak-badge-border-md) solid var(--color-ak-bg); top: var(--offset-ak-icon-badge-md); right: var(--offset-ak-icon-badge-md); }
111
+ .ak-avatar-wrap--md .ak-status-icon { width: var(--size-ak-icon-badge-md); height: var(--size-ak-icon-badge-md); border: var(--size-ak-badge-border-md) solid var(--color-ak-bg); bottom: var(--offset-ak-icon-badge-md); right: var(--offset-ak-icon-badge-md); }
112
+ .ak-avatar-wrap--md .ak-status-icon i { font-size: 12px; }
113
+ .ak-avatar-wrap--md .ak-verified-badge { width: var(--size-ak-badge-md); height: var(--size-ak-badge-md); border: var(--size-ak-badge-border-md) solid var(--color-ak-bg); bottom: var(--offset-ak-badge-md-top, var(--offset-ak-badge-md)); right: var(--offset-ak-badge-md-right, var(--offset-ak-badge-md)); }
114
+ .ak-avatar-wrap--md .ak-verified-badge i { font-size: 10px; }
115
+
116
+ .ak-avatar-wrap--lg .ak-status-dot { width: var(--size-ak-status-lg); height: var(--size-ak-status-lg); border: var(--size-ak-badge-border-lg) solid var(--color-ak-bg); bottom: var(--offset-ak-status-lg); right: var(--offset-ak-status-lg); }
117
+ .ak-avatar-wrap--lg .ak-status-dot--dnd::after { width: 8px; height: 1.5px; }
118
+ .ak-avatar-wrap--lg .ak-badge { min-width: var(--size-ak-status-lg); height: var(--size-ak-status-lg); border: var(--size-ak-badge-border-lg) solid var(--color-ak-bg); top: var(--offset-ak-status-lg); right: var(--offset-ak-status-lg); }
119
+ .ak-avatar-wrap--lg .ak-badge--count { min-width: var(--size-ak-badge-lg); height: var(--size-ak-badge-lg); font-size: var(--text-ak-badge-lg); top: var(--offset-ak-badge-lg-top, var(--offset-ak-badge-lg)); right: var(--offset-ak-badge-lg-right, var(--offset-ak-badge-lg)); --ak-badge-pad: 2px; }
120
+ .ak-avatar-wrap--lg .ak-notif-badge { min-width: var(--size-ak-badge-lg); height: var(--size-ak-badge-lg); font-size: var(--text-ak-badge-lg); top: var(--offset-ak-badge-lg); right: var(--offset-ak-badge-lg); }
121
+ .ak-avatar-wrap--lg .ak-rank-badge { width: var(--size-ak-icon-badge-lg); height: var(--size-ak-icon-badge-lg); font-size: 0.6875rem; border: var(--size-ak-badge-border-lg) solid var(--color-ak-bg); top: var(--offset-ak-icon-badge-lg); right: var(--offset-ak-icon-badge-lg); }
122
+ .ak-avatar-wrap--lg .ak-status-icon { width: var(--size-ak-icon-badge-lg); height: var(--size-ak-icon-badge-lg); border: var(--size-ak-badge-border-lg) solid var(--color-ak-bg); bottom: var(--offset-ak-icon-badge-lg); right: var(--offset-ak-icon-badge-lg); }
123
+ .ak-avatar-wrap--lg .ak-status-icon i { font-size: 13px; }
124
+ .ak-avatar-wrap--lg .ak-verified-badge { width: var(--size-ak-badge-lg); height: var(--size-ak-badge-lg); border: var(--size-ak-badge-border-lg) solid var(--color-ak-bg); bottom: var(--offset-ak-badge-lg-top, var(--offset-ak-badge-lg)); right: var(--offset-ak-badge-lg-right, var(--offset-ak-badge-lg)); }
125
+ .ak-avatar-wrap--lg .ak-verified-badge i { font-size: 12px; }
126
+
127
+ .ak-avatar-wrap--xl .ak-status-dot { width: var(--size-ak-status-xl); height: var(--size-ak-status-xl); border: var(--size-ak-badge-border-xl) solid var(--color-ak-bg); bottom: var(--offset-ak-status-xl); right: var(--offset-ak-status-xl); }
128
+ .ak-avatar-wrap--xl .ak-status-dot--dnd::after { width: 9px; height: 2px; }
129
+ .ak-avatar-wrap--xl .ak-badge { min-width: var(--size-ak-status-xl); height: var(--size-ak-status-xl); border: var(--size-ak-badge-border-xl) solid var(--color-ak-bg); top: var(--offset-ak-status-xl); right: var(--offset-ak-status-xl); }
130
+ .ak-avatar-wrap--xl .ak-badge--count { min-width: var(--size-ak-badge-xl); height: var(--size-ak-badge-xl); font-size: var(--text-ak-badge-xl); top: var(--offset-ak-badge-xl-top, var(--offset-ak-badge-xl)); right: var(--offset-ak-badge-xl-right, var(--offset-ak-badge-xl)); --ak-badge-pad: 3px; }
131
+ .ak-avatar-wrap--xl .ak-notif-badge { min-width: var(--size-ak-badge-xl); height: var(--size-ak-badge-xl); font-size: var(--text-ak-badge-xl); top: var(--offset-ak-badge-xl); right: var(--offset-ak-badge-xl); }
132
+ .ak-avatar-wrap--xl .ak-rank-badge { width: var(--size-ak-icon-badge-xl); height: var(--size-ak-icon-badge-xl); font-size: 0.75rem; border: var(--size-ak-badge-border-xl) solid var(--color-ak-bg); top: var(--offset-ak-icon-badge-xl); right: var(--offset-ak-icon-badge-xl); }
133
+ .ak-avatar-wrap--xl .ak-status-icon { width: var(--size-ak-icon-badge-xl); height: var(--size-ak-icon-badge-xl); border: var(--size-ak-badge-border-xl) solid var(--color-ak-bg); bottom: var(--offset-ak-icon-badge-xl); right: var(--offset-ak-icon-badge-xl); }
134
+ .ak-avatar-wrap--xl .ak-status-icon i { font-size: 14px; }
135
+ .ak-avatar-wrap--xl .ak-verified-badge { width: var(--size-ak-badge-xl); height: var(--size-ak-badge-xl); border: var(--size-ak-badge-border-xl) solid var(--color-ak-bg); bottom: var(--offset-ak-badge-xl-top, var(--offset-ak-badge-xl)); right: var(--offset-ak-badge-xl-right, var(--offset-ak-badge-xl)); }
136
+ .ak-avatar-wrap--xl .ak-verified-badge i { font-size: 14px; }
137
+
138
+ .ak-avatar-wrap--2xl .ak-status-dot { width: var(--size-ak-status-2xl); height: var(--size-ak-status-2xl); border: var(--size-ak-badge-border-2xl) solid var(--color-ak-bg); bottom: var(--offset-ak-status-2xl); right: var(--offset-ak-status-2xl); }
139
+ .ak-avatar-wrap--2xl .ak-status-dot--dnd::after { width: 11px; height: 2px; }
140
+ .ak-avatar-wrap--2xl .ak-badge { min-width: var(--size-ak-status-2xl); height: var(--size-ak-status-2xl); border: var(--size-ak-badge-border-2xl) solid var(--color-ak-bg); top: var(--offset-ak-status-2xl); right: var(--offset-ak-status-2xl); }
141
+ .ak-avatar-wrap--2xl .ak-badge--count { min-width: var(--size-ak-badge-2xl); height: var(--size-ak-badge-2xl); font-size: var(--text-ak-badge-2xl); top: var(--offset-ak-badge-2xl-top, var(--offset-ak-badge-2xl)); right: var(--offset-ak-badge-2xl-right, var(--offset-ak-badge-2xl)); }
142
+ .ak-avatar-wrap--2xl .ak-rank-badge { width: var(--size-ak-icon-badge-2xl); height: var(--size-ak-icon-badge-2xl); font-size: 0.875rem; border: var(--size-ak-badge-border-2xl) solid var(--color-ak-bg); top: var(--offset-ak-icon-badge-2xl); right: var(--offset-ak-icon-badge-2xl); }
143
+ .ak-avatar-wrap--2xl .ak-status-icon { width: var(--size-ak-icon-badge-2xl); height: var(--size-ak-icon-badge-2xl); border: var(--size-ak-badge-border-2xl) solid var(--color-ak-bg); bottom: var(--offset-ak-icon-badge-2xl); right: var(--offset-ak-icon-badge-2xl); }
144
+ .ak-avatar-wrap--2xl .ak-status-icon i { font-size: 16px; }
145
+ .ak-avatar-wrap--2xl .ak-verified-badge { width: var(--size-ak-badge-2xl); height: var(--size-ak-badge-2xl); border: var(--size-ak-badge-border-2xl) solid var(--color-ak-bg); bottom: var(--offset-ak-badge-2xl-top, var(--offset-ak-badge-2xl)); right: var(--offset-ak-badge-2xl-right, var(--offset-ak-badge-2xl)); }
146
+ .ak-avatar-wrap--2xl .ak-verified-badge i { font-size: 18px; }
147
+
148
+ .ak-avatar-wrap--3xl .ak-status-dot { width: var(--size-ak-status-3xl); height: var(--size-ak-status-3xl); border: var(--size-ak-badge-border-3xl) solid var(--color-ak-bg); bottom: var(--offset-ak-status-3xl); right: var(--offset-ak-status-3xl); }
149
+ .ak-avatar-wrap--3xl .ak-status-dot--dnd::after { width: 13px; height: 2.5px; }
150
+ .ak-avatar-wrap--3xl .ak-badge { min-width: var(--size-ak-status-3xl); height: var(--size-ak-status-3xl); border: var(--size-ak-badge-border-3xl) solid var(--color-ak-bg); top: var(--offset-ak-status-3xl); right: var(--offset-ak-status-3xl); }
151
+ .ak-avatar-wrap--3xl .ak-badge--count { min-width: var(--size-ak-badge-3xl); height: var(--size-ak-badge-3xl); font-size: var(--text-ak-badge-3xl); top: var(--offset-ak-badge-3xl-top, var(--offset-ak-badge-3xl)); right: var(--offset-ak-badge-3xl-right, var(--offset-ak-badge-3xl)); }
152
+ .ak-avatar-wrap--3xl .ak-rank-badge { width: var(--size-ak-icon-badge-3xl); height: var(--size-ak-icon-badge-3xl); font-size: 1rem; border: var(--size-ak-badge-border-3xl) solid var(--color-ak-bg); top: var(--offset-ak-icon-badge-3xl); right: var(--offset-ak-icon-badge-3xl); }
153
+ .ak-avatar-wrap--3xl .ak-status-icon { width: var(--size-ak-icon-badge-3xl); height: var(--size-ak-icon-badge-3xl); border: var(--size-ak-badge-border-3xl) solid var(--color-ak-bg); bottom: var(--offset-ak-icon-badge-3xl); right: var(--offset-ak-icon-badge-3xl); }
154
+ .ak-avatar-wrap--3xl .ak-status-icon i { font-size: 20px; }
155
+ .ak-avatar-wrap--3xl .ak-verified-badge { width: var(--size-ak-badge-3xl); height: var(--size-ak-badge-3xl); border: var(--size-ak-badge-border-3xl) solid var(--color-ak-bg); bottom: var(--offset-ak-badge-3xl-top, var(--offset-ak-badge-3xl)); right: var(--offset-ak-badge-3xl-right, var(--offset-ak-badge-3xl)); }
156
+ .ak-avatar-wrap--3xl .ak-verified-badge i { font-size: 22px; }
157
+
158
+ /* Social badge per-size — sized to match count-badge ratio for visual
159
+ parity with other avatar badges (~30-45% of avatar size). Border
160
+ width scales with avatar so the "cutout" ring reads at every size. */
161
+ .ak-avatar-wrap--md .ak-social-badge { width: var(--size-ak-badge-md); height: var(--size-ak-badge-md); font-size: 10px; border-width: var(--size-ak-badge-border-md); }
162
+ .ak-avatar-wrap--lg .ak-social-badge { width: var(--size-ak-badge-lg); height: var(--size-ak-badge-lg); font-size: 12px; border-width: var(--size-ak-badge-border-lg); }
163
+ .ak-avatar-wrap--xl .ak-social-badge { width: var(--size-ak-badge-xl); height: var(--size-ak-badge-xl); font-size: 14px; border-width: var(--size-ak-badge-border-xl); }
164
+ .ak-avatar-wrap--2xl .ak-social-badge { width: var(--size-ak-badge-2xl); height: var(--size-ak-badge-2xl); font-size: 18px; border-width: var(--size-ak-badge-border-2xl); }
165
+ .ak-avatar-wrap--3xl .ak-social-badge { width: var(--size-ak-badge-3xl); height: var(--size-ak-badge-3xl); font-size: 22px; border-width: var(--size-ak-badge-border-3xl); }
166
+
167
+ /* Status dot offset adjustments for ring avatars — ring (box-shadow) extends
168
+ beyond the layout box, so the dot needs to shift outward to sit at the ring edge */
169
+ .ak-avatar-wrap--md:has([class*="ak-avatar--ring-"]) .ak-status-dot { bottom: -2px; right: -2px; }
170
+ .ak-avatar-wrap--lg:has([class*="ak-avatar--ring-"]) .ak-status-dot { bottom: -2px; right: -2px; }
171
+ .ak-avatar-wrap--xl:has([class*="ak-avatar--ring-"]) .ak-status-dot { bottom: 0px; right: 0px; }
172
+ .ak-avatar-wrap--2xl:has([class*="ak-avatar--ring-"]) .ak-status-dot { bottom: 2px; right: 2px; }
173
+ .ak-avatar-wrap--3xl:has([class*="ak-avatar--ring-"]) .ak-status-dot { bottom: 4px; right: 4px; }
174
+
175
+ /* Avatar group (stacked/overlapping) */
176
+ .ak-avatar-group { display: flex; align-items: center; }
177
+ .ak-avatar-group .ak-avatar { position: relative; }
178
+ /* White ring only on filled avatars and overflow counter so they
179
+ read as separated chips. The "+" add button uses a dashed border
180
+ instead — no white ring so the dashes are the only visible edge.
181
+ Integer pixel widths to avoid subpixel anti-aliasing. */
182
+ .ak-avatar-group .ak-avatar,
183
+ .ak-avatar-group .ak-avatar-overflow { box-shadow: 0 0 0 3px var(--color-ak-bg); }
184
+ .ak-avatar-group--xl .ak-avatar,
185
+ .ak-avatar-group--xl .ak-avatar-overflow { box-shadow: 0 0 0 4px var(--color-ak-bg); }
186
+ .ak-avatar-group--2xl .ak-avatar,
187
+ .ak-avatar-group--2xl .ak-avatar-overflow { box-shadow: 0 0 0 6px var(--color-ak-bg); }
188
+ .ak-avatar-group--3xl .ak-avatar,
189
+ .ak-avatar-group--3xl .ak-avatar-overflow { box-shadow: 0 0 0 7px var(--color-ak-bg); }
190
+ .ak-avatar-group .ak-avatar:first-child,
191
+ .ak-avatar-group .ak-avatar-add:first-child,
192
+ .ak-avatar-group .ak-avatar-overflow:first-child { margin-left: 0; }
193
+
194
+ /* Hover micro-interaction: diagonal shimmer sweep across the face.
195
+ The ::after pseudo is hidden (opacity: 0) at rest so it can never
196
+ leak a visible band on dark backgrounds. Hovering triggers a
197
+ keyframe animation that slides a soft white gradient across the
198
+ circle once, then resets. `overflow: hidden` on .ak-avatar clips
199
+ it to the circle so it reads as a sheen, not a square flash.
200
+ Skipped under prefers-reduced-motion. */
201
+ /* Shimmer is scoped to avatars that contain an <img> (photo avatars) so
202
+ static initials/icon avatars don't flash on hover. Works in group
203
+ contexts and standalone showcases. */
204
+ .ak-avatar:has(img)::after,
205
+ .ak-avatar-group .ak-avatar::after,
206
+ .ak-avatar-group .ak-avatar-overflow::after {
207
+ content: '';
208
+ position: absolute;
209
+ inset: 0;
210
+ border-radius: inherit;
211
+ background: linear-gradient(
212
+ 110deg,
213
+ transparent 30%,
214
+ rgba(255, 255, 255, 0.35) 50%,
215
+ transparent 70%
216
+ );
217
+ opacity: 0;
218
+ pointer-events: none;
219
+ }
220
+ .ak-avatar:has(img):hover::after,
221
+ .ak-avatar-group .ak-avatar:hover::after,
222
+ .ak-avatar-group .ak-avatar-overflow:hover::after {
223
+ animation: ak-avatar-shimmer 700ms cubic-bezier(0.4, 0, 0.2, 1);
224
+ }
225
+ @keyframes ak-avatar-shimmer {
226
+ 0% { transform: translateX(-120%); opacity: 1; }
227
+ 100% { transform: translateX(120%); opacity: 1; }
228
+ }
229
+ @media (prefers-reduced-motion: reduce) {
230
+ .ak-avatar:has(img):hover::after,
231
+ .ak-avatar-group .ak-avatar:hover::after,
232
+ .ak-avatar-group .ak-avatar-overflow:hover::after {
233
+ animation: none;
234
+ }
235
+ }
236
+
237
+ /* Group size modifiers */
238
+ .ak-avatar-group--md .ak-avatar,
239
+ .ak-avatar-group--md .ak-avatar-add,
240
+ .ak-avatar-group--md .ak-avatar-overflow { margin-left: -8px; }
241
+ .ak-avatar-group--md .ak-avatar-overflow { width: var(--size-ak-avatar-md); height: var(--size-ak-avatar-md); font-size: var(--text-ak-avatar-md); font-weight: 600; }
242
+ .ak-avatar-group--md .ak-avatar-add { width: var(--size-ak-avatar-md); height: var(--size-ak-avatar-md); }
243
+ .ak-avatar-group--md .ak-avatar-add i { font-size: var(--size-ak-icon-md); }
244
+
245
+ .ak-avatar-group--lg .ak-avatar,
246
+ .ak-avatar-group--lg .ak-avatar-add,
247
+ .ak-avatar-group--lg .ak-avatar-overflow { margin-left: -10px; }
248
+ .ak-avatar-group--lg .ak-avatar-overflow { width: var(--size-ak-avatar-lg); height: var(--size-ak-avatar-lg); font-size: var(--text-ak-avatar-lg); font-weight: 600; }
249
+ .ak-avatar-group--lg .ak-avatar-add { width: var(--size-ak-avatar-lg); height: var(--size-ak-avatar-lg); }
250
+ .ak-avatar-group--lg .ak-avatar-add i { font-size: var(--size-ak-icon-lg); }
251
+
252
+ .ak-avatar-group--xl .ak-avatar,
253
+ .ak-avatar-group--xl .ak-avatar-add,
254
+ .ak-avatar-group--xl .ak-avatar-overflow { margin-left: -12px; }
255
+ .ak-avatar-group--xl .ak-avatar-overflow { width: var(--size-ak-avatar-xl); height: var(--size-ak-avatar-xl); font-size: var(--text-ak-avatar-xl); font-weight: 500; }
256
+ .ak-avatar-group--xl .ak-avatar-add { width: var(--size-ak-avatar-xl); height: var(--size-ak-avatar-xl); }
257
+ .ak-avatar-group--xl .ak-avatar-add i { font-size: 1.75rem; }
258
+
259
+ .ak-avatar-group--2xl .ak-avatar,
260
+ .ak-avatar-group--2xl .ak-avatar-add,
261
+ .ak-avatar-group--2xl .ak-avatar-overflow { margin-left: -16px; }
262
+ .ak-avatar-group--2xl .ak-avatar-overflow { width: var(--size-ak-avatar-2xl); height: var(--size-ak-avatar-2xl); font-size: var(--text-ak-avatar-2xl); font-weight: 400; }
263
+ .ak-avatar-group--2xl .ak-avatar-add { width: var(--size-ak-avatar-2xl); height: var(--size-ak-avatar-2xl); }
264
+ .ak-avatar-group--2xl .ak-avatar-add i { font-size: var(--size-ak-icon-2xl); }
265
+
266
+ .ak-avatar-group--3xl .ak-avatar,
267
+ .ak-avatar-group--3xl .ak-avatar-add,
268
+ .ak-avatar-group--3xl .ak-avatar-overflow { margin-left: -20px; }
269
+ .ak-avatar-group--3xl .ak-avatar-overflow { width: var(--size-ak-avatar-3xl); height: var(--size-ak-avatar-3xl); font-size: var(--text-ak-avatar-3xl); font-weight: 400; }
270
+ .ak-avatar-group--3xl .ak-avatar-add { width: var(--size-ak-avatar-3xl); height: var(--size-ak-avatar-3xl); }
271
+ .ak-avatar-group--3xl .ak-avatar-add i { font-size: var(--size-ak-icon-3xl); }
272
+
273
+ /* Avatar overflow ("+3" counter) */
274
+ .ak-avatar-overflow {
275
+ display: flex;
276
+ align-items: center;
277
+ justify-content: center;
278
+ border-radius: var(--radius-ak-full);
279
+ background: var(--color-ak-surface-2);
280
+ color: var(--color-ak-text-secondary);
281
+ font-weight: 600;
282
+ cursor: pointer;
283
+ transition: background-color var(--duration-ak-fast) var(--ease-ak-default);
284
+ /* Clip the shimmer ::after to the circle shape (same reason
285
+ .ak-avatar needs overflow:hidden to clip its <img>). */
286
+ overflow: hidden;
287
+ position: relative;
288
+ }
289
+ .ak-avatar-overflow:hover { background: var(--color-ak-active); z-index: 5; }
290
+ .ak-avatar-overflow:focus-visible {
291
+ outline: 2px solid var(--color-ak-border-focus);
292
+ outline-offset: 2px;
293
+ }
294
+
295
+ /* Avatar add button */
296
+ .ak-avatar-add {
297
+ display: flex;
298
+ align-items: center;
299
+ justify-content: center;
300
+ border-radius: var(--radius-ak-full);
301
+ border: 2px dashed var(--color-ak-border);
302
+ background: none;
303
+ color: var(--color-ak-text-muted);
304
+ cursor: pointer;
305
+ transition: border-color var(--duration-ak-fast) var(--ease-ak-default),
306
+ color var(--duration-ak-fast) var(--ease-ak-default),
307
+ background-color var(--duration-ak-fast) var(--ease-ak-default);
308
+ }
309
+ .ak-avatar-add:hover {
310
+ border-color: var(--color-ak-border-strong);
311
+ color: var(--color-ak-text);
312
+ background: var(--color-ak-hover);
313
+ }
314
+ .ak-avatar-add:focus-visible {
315
+ outline: 2px solid var(--color-ak-border-focus);
316
+ outline-offset: 2px;
317
+ }
318
+
319
+ /* Avatar progress ring */
320
+ .ak-avatar-progress { position: relative; display: inline-flex; align-items: center; justify-content: center; }
321
+ .ak-avatar-progress--md { width: 56px; height: 56px; }
322
+ .ak-avatar-progress--lg { width: 66px; height: 66px; }
323
+ .ak-avatar-progress--xl { width: 86px; height: 86px; }
324
+ .ak-avatar-progress--2xl { width: 126px; height: 126px; }
325
+ .ak-avatar-progress--3xl { width: 166px; height: 166px; }
326
+ .ak-avatar-progress--md .ak-progress-ring__track,
327
+ .ak-avatar-progress--md .ak-progress-ring__fill { stroke-width: 14; }
328
+ .ak-avatar-progress--lg .ak-progress-ring__track,
329
+ .ak-avatar-progress--lg .ak-progress-ring__fill { stroke-width: 12; }
330
+ .ak-avatar-progress--xl .ak-progress-ring__track,
331
+ .ak-avatar-progress--xl .ak-progress-ring__fill { stroke-width: 12; }
332
+ .ak-avatar-progress--2xl .ak-progress-ring__track,
333
+ .ak-avatar-progress--2xl .ak-progress-ring__fill { stroke-width: 10; }
334
+ .ak-avatar-progress--3xl .ak-progress-ring__track,
335
+ .ak-avatar-progress--3xl .ak-progress-ring__fill { stroke-width: 8; }
336
+
337
+ /* Progress ring SVG */
338
+ .ak-progress-ring {
339
+ position: absolute;
340
+ inset: 0;
341
+ width: 100%;
342
+ height: 100%;
343
+ transform: rotate(-90deg);
344
+ }
345
+ .ak-progress-ring__track {
346
+ fill: none;
347
+ stroke: var(--color-ak-border-subtle);
348
+ shape-rendering: geometricPrecision;
349
+ }
350
+ .ak-progress-ring__fill {
351
+ fill: none;
352
+ stroke: var(--color-ak-primary);
353
+ stroke-linecap: round;
354
+ shape-rendering: geometricPrecision;
355
+ stroke-dasharray: 552.92;
356
+ stroke-dashoffset: calc(552.92 - (552.92 * var(--progress, 0) / 100));
357
+ transition: stroke-dashoffset 800ms cubic-bezier(0.4, 0, 0.2, 1),
358
+ stroke 400ms ease;
359
+ }
360
+ .ak-progress-ring__fill--primary { stroke: var(--color-ak-primary); }
361
+ .ak-progress-ring__fill--success { stroke: var(--color-ak-success); }
362
+ .ak-progress-ring__fill--warning { stroke: var(--color-ak-warning); }
363
+ .ak-progress-ring__fill--danger { stroke: var(--color-ak-danger); }
364
+ .ak-progress-ring__fill--info { stroke: var(--color-ak-info); }
365
+
366
+ /* Progress ring shape variants */
367
+ .ak-progress-ring--rounded .ak-progress-ring__track,
368
+ .ak-progress-ring--rounded .ak-progress-ring__fill { stroke-linecap: round; }
369
+ .ak-progress-ring--square .ak-progress-ring__track,
370
+ .ak-progress-ring--square .ak-progress-ring__fill { stroke-linecap: square; }
371
+ .ak-progress-ring--circle .ak-progress-ring__track,
372
+ .ak-progress-ring--circle .ak-progress-ring__fill { stroke-linecap: round; }
373
+
374
+ /* Avatar ring (decorative border ring) */
375
+ .ak-avatar-ring {
376
+ position: absolute;
377
+ inset: -3px;
378
+ border-radius: var(--radius-ak-full);
379
+ border: 2px solid var(--color-ak-primary);
380
+ pointer-events: none;
381
+ }
382
+
383
+ /* Face stack (simpler avatar group variant) */
384
+ .ak-faces { display: flex; align-items: center; isolation: isolate; }
385
+ .ak-face {
386
+ width: 40px;
387
+ height: 40px;
388
+ margin-left: -10px;
389
+ border-radius: var(--radius-ak-full);
390
+ overflow: hidden;
391
+ outline: 3px solid var(--color-ak-bg);
392
+ outline-offset: -0.5px;
393
+ flex-shrink: 0;
394
+ }
395
+ .ak-face:first-child { margin-left: 0; }
396
+ .ak-face:nth-child(1) { z-index: 5; }
397
+ .ak-face:nth-child(2) { z-index: 4; }
398
+ .ak-face:nth-child(3) { z-index: 3; }
399
+ .ak-face:nth-child(4) { z-index: 2; }
400
+ .ak-face:nth-child(5) { z-index: 1; }
401
+ .ak-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
402
+ .ak-face--lg { width: 48px; height: 48px; margin-left: -12px; }
403
+ .ak-face--lg:first-child { margin-left: 0; }
404
+ .ak-face--xl { width: 56px; height: 56px; margin-left: -14px; }
405
+ .ak-face--xl:first-child { margin-left: 0; }
406
+
407
+
408
+ /* Note: The unlayered override block that was here has been removed.
409
+ With @layer gone, the border declarations above now compete with
410
+ Tailwind preflight via specificity (.class > *) and win. */
@@ -0,0 +1,231 @@
1
+
2
+
3
+ /* Badge primitives -- notification badges, status dots, rank, social, verified, count badges */
4
+
5
+
6
+
7
+ /* Badge (notification counts) */
8
+ /* Base badge — background + color only.
9
+ Position is set by context (absolute on avatars, static in nav links). */
10
+ /* Exact match of HTML badge CSS — nothing extra */
11
+ .ak-badge {
12
+ position: absolute;
13
+ border-radius: var(--radius-ak-full);
14
+ background: var(--color-ak-primary);
15
+ /* Monochrome by default — use .ak-badge--danger/success/warning/info
16
+ to override when a semantic color is needed.
17
+ No outer shadow: the white border (set per-size in avatar.css)
18
+ matches the page background and creates a "cutout" illusion —
19
+ the badge appears to be carved into the avatar rather than
20
+ floating on top. An outer shadow would contradict that. */
21
+ }
22
+ .ak-badge--count {
23
+ /* Horizontal padding is overridable via --ak-badge-pad so tighter
24
+ sizes (MD/LG/XL on avatars) can keep a perfect circle for
25
+ 2-digit counts without stretching into a pill. */
26
+ padding: 0 var(--ak-badge-pad, 4px);
27
+ font-weight: 700;
28
+ color: var(--color-ak-on-primary);
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ /* Tabular digits so "11" / "24" / "99+" share column widths and
33
+ read centered regardless of digit mix. Tight letter-spacing
34
+ makes multi-digit counts feel like a single token. */
35
+ font-variant-numeric: tabular-nums;
36
+ letter-spacing: -0.01em;
37
+ }
38
+ .ak-badge--success { background: var(--color-ak-success); }
39
+ .ak-badge--warning { background: var(--color-ak-warning); }
40
+ .ak-badge--danger { background: var(--color-ak-danger); }
41
+ .ak-badge--info { background: var(--color-ak-info); }
42
+
43
+ /* Dark panel/rail badge overrides */
44
+ [data-ak-dark-panel] .ak-badge,
45
+ [data-ak-dark-rail] .ak-badge,
46
+ [data-ak-mobile-sheet] .ak-badge {
47
+ background: #ffffff;
48
+ color: #171717;
49
+ }
50
+ [data-ak-dark-panel] .ak-on-elevated .ak-badge,
51
+ [data-ak-dark-rail] .ak-on-elevated .ak-badge,
52
+ [data-ak-mobile-sheet] .ak-on-elevated .ak-badge {
53
+ background: #171717;
54
+ color: #ffffff;
55
+ }
56
+
57
+ /* Badge variants */
58
+ .ak-badge-dot {
59
+ width: 8px;
60
+ height: 8px;
61
+ border-radius: var(--radius-ak-full);
62
+ background: var(--color-ak-primary);
63
+ }
64
+ .ak-badge-inline {
65
+ display: inline-flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ padding: 0.125rem 0.5rem;
69
+ border-radius: var(--radius-ak-full);
70
+ font-size: var(--text-ak-xs);
71
+ font-weight: 600;
72
+ }
73
+ .ak-badge-subtle {
74
+ background: var(--color-ak-primary-subtle);
75
+ color: var(--color-ak-primary);
76
+ }
77
+
78
+ /* Count badge (standalone) */
79
+ .ak-count-badge {
80
+ display: inline-flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ min-width: 1.25rem;
84
+ height: 1.25rem;
85
+ padding: 0 0.375rem;
86
+ border-radius: var(--radius-ak-full);
87
+ font-size: var(--text-ak-xs);
88
+ font-weight: 600;
89
+ background: var(--color-ak-surface-2);
90
+ color: var(--color-ak-text-secondary);
91
+ }
92
+
93
+ /* Notification badge — monochrome by default.
94
+ Add .ak-notif-badge.ak-badge--danger etc. to override when needed. */
95
+ .ak-notif-badge {
96
+ position: absolute;
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ border-radius: var(--radius-ak-full);
101
+ background: var(--color-ak-primary);
102
+ color: var(--color-ak-on-primary);
103
+ font-weight: 700;
104
+ padding: 0 0.25rem;
105
+ }
106
+
107
+ /* Pro/plan badges */
108
+ .ak-pro-badge {
109
+ display: inline-flex;
110
+ align-items: center;
111
+ padding: 0.125rem 0.5rem;
112
+ border-radius: var(--radius-ak-full);
113
+ font-size: var(--text-ak-xs);
114
+ font-weight: 600;
115
+ background: var(--color-ak-primary);
116
+ color: var(--color-ak-on-primary);
117
+ }
118
+ .ak-plan-badge {
119
+ display: inline-flex;
120
+ align-items: center;
121
+ padding: 0.125rem 0.5rem;
122
+ border-radius: var(--radius-ak-full);
123
+ font-size: var(--text-ak-xs);
124
+ font-weight: 600;
125
+ }
126
+
127
+ /* Verified badge — monochrome by default. Add .ak-badge--info
128
+ to override with the traditional blue checkmark. */
129
+ .ak-verified-badge {
130
+ position: absolute;
131
+ display: flex;
132
+ align-items: center;
133
+ justify-content: center;
134
+ border-radius: var(--radius-ak-full);
135
+ background: var(--color-ak-primary);
136
+ }
137
+ .ak-verified-badge i {
138
+ color: var(--color-ak-on-primary);
139
+ }
140
+
141
+ /* Rank badge — tonal monochrome hierarchy.
142
+ 1st = primary (black), 2nd = secondary neutral, 3rd = surface. */
143
+ .ak-rank-badge {
144
+ position: absolute;
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ border-radius: var(--radius-ak-full);
149
+ font-weight: 700;
150
+ }
151
+ .ak-rank-badge--1 { background: var(--color-ak-primary); color: var(--color-ak-on-primary); }
152
+ .ak-rank-badge--2 { background: var(--color-ak-text-secondary); color: var(--color-ak-bg); }
153
+ .ak-rank-badge--3 { background: var(--color-ak-surface-2); color: var(--color-ak-text); }
154
+
155
+ /* Social badge — per-size border width set in avatar.css to scale with avatar */
156
+ .ak-social-badge {
157
+ position: absolute;
158
+ bottom: -6px;
159
+ right: -6px;
160
+ display: flex;
161
+ align-items: center;
162
+ justify-content: center;
163
+ border-radius: var(--radius-ak-full);
164
+ border-style: solid;
165
+ border-color: var(--color-ak-bg);
166
+ font-weight: 700;
167
+ line-height: 1;
168
+ flex-shrink: 0;
169
+ }
170
+ .ak-social-badge--google { background: #ffffff; color: #4285F4; }
171
+ .ak-social-badge--linkedin { background: #0A66C2; color: #ffffff; }
172
+ .ak-social-badge--meta { background: #0081FB; color: #ffffff; }
173
+ .ak-social-badge--x { background: #000000; color: #ffffff; }
174
+
175
+ /* Status dot */
176
+ .ak-status-dot {
177
+ position: absolute;
178
+ border-radius: var(--radius-ak-full);
179
+ }
180
+ .ak-status-dot--online { background: var(--color-ak-success); }
181
+ .ak-status-dot--away { background: var(--color-ak-warning); }
182
+ .ak-status-dot--busy { background: var(--color-ak-danger); }
183
+ .ak-status-dot--offline { background: var(--color-ak-text-muted); }
184
+ .ak-status-dot--dnd { background: var(--color-ak-danger); }
185
+ .ak-status-dot--dnd::after {
186
+ content: '';
187
+ position: absolute;
188
+ top: 50%;
189
+ left: 50%;
190
+ transform: translate(-50%, -50%);
191
+ background: var(--color-ak-text-inverse);
192
+ border-radius: var(--radius-ak-full);
193
+ }
194
+
195
+ /* Activity / status badges */
196
+ .ak-activity-badge {
197
+ display: inline-flex;
198
+ align-items: center;
199
+ padding: 0.125rem 0.5rem;
200
+ border-radius: var(--radius-ak-full);
201
+ font-size: var(--text-ak-xs);
202
+ font-weight: 600;
203
+ }
204
+ .ak-status-badge {
205
+ display: inline-flex;
206
+ align-items: center;
207
+ gap: 0.375rem;
208
+ padding: 0.25rem 0.625rem;
209
+ border-radius: var(--radius-ak-full);
210
+ font-size: var(--text-ak-xs);
211
+ font-weight: 500;
212
+ }
213
+ .ak-notification-dot {
214
+ width: 6px;
215
+ height: 6px;
216
+ border-radius: var(--radius-ak-full);
217
+ background: var(--color-ak-danger);
218
+ }
219
+ .ak-status-indicator {
220
+ width: 8px;
221
+ height: 8px;
222
+ border-radius: var(--radius-ak-full);
223
+ }
224
+
225
+ /* Presence indicators */
226
+ .ak-presence-online { background-color: var(--color-ak-success); }
227
+ .ak-presence-away { background-color: var(--color-ak-warning); }
228
+
229
+
230
+
231
+ /* Note: Unlayered override block removed — no longer needed without @layer. */