altitude-design 0.1.0 → 0.2.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.
- package/README.md +18 -3
- package/dist/altitude.css +28 -1
- package/dist/altitude.iife.js +5 -3
- package/dist/altitude.no-fonts.css +1659 -0
- package/dist/fonts.css +1 -0
- package/dist/index.cjs +205 -70
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +205 -70
- package/dist/index.js.map +4 -4
- package/dist/types/command.d.ts +5 -1
- package/dist/types/core.d.ts +23 -2
- package/dist/types/empty.d.ts +24 -0
- package/dist/types/index.d.ts +9 -1
- package/package.json +11 -1
|
@@ -0,0 +1,1659 @@
|
|
|
1
|
+
:root, [data-theme="daylight"] {
|
|
2
|
+
--surface-trench: #e1e4ea;
|
|
3
|
+
--surface-well: #eaedf1;
|
|
4
|
+
--surface-ground: #f3f4f7;
|
|
5
|
+
--surface-raised: #ffffff;
|
|
6
|
+
--surface-lifted: #ffffff;
|
|
7
|
+
--surface-floating: #ffffff;
|
|
8
|
+
--surface-overlay: #ffffff;
|
|
9
|
+
--surface-modal: #ffffff;
|
|
10
|
+
--ink: #12161f;
|
|
11
|
+
--ink-muted: #4f5767;
|
|
12
|
+
--ink-faint: #8a92a0;
|
|
13
|
+
--line: #e0e3e9;
|
|
14
|
+
--line-control: #737b89;
|
|
15
|
+
--accent: #2b56d6;
|
|
16
|
+
--on-accent: #ffffff;
|
|
17
|
+
--accent-ink: #2a52c8;
|
|
18
|
+
--accent-soft: #e3eafc;
|
|
19
|
+
--positive: #13734f;
|
|
20
|
+
--positive-soft: #dcf2e8;
|
|
21
|
+
--caution: #875400;
|
|
22
|
+
--caution-soft: #fbefd3;
|
|
23
|
+
--critical: #b52e16;
|
|
24
|
+
--critical-soft: #fbe4de;
|
|
25
|
+
--on-critical: #ffffff;
|
|
26
|
+
--presence-1: #b0256f;
|
|
27
|
+
--presence-2: #0b7285;
|
|
28
|
+
--presence-3: #7046c9;
|
|
29
|
+
--on-presence: #ffffff;
|
|
30
|
+
--scrim: #12161f52;
|
|
31
|
+
--trench: inset 0 1px 3px #0f17292e, 0 0 0 0 #0f172900, 0 0 0 0 #0f172900, 0 0 0 0 #0f172900;
|
|
32
|
+
--well: inset 0 1px 2px #0f17291a, 0 0 0 0 #0f172900, 0 0 0 0 #0f172900, 0 0 0 0 #0f172900;
|
|
33
|
+
--elev-0: inset 0 1px 0 #ffffff00, 0 0 0 0 #0f172900, 0 0 0 0 #0f172900, 0 0 0 0 #0f172900;
|
|
34
|
+
--elev-1: inset 0 1px 0 #ffffffb3, 0 0 0 1px #0f172917, 0 1px 2px #0f172912, 0 2px 4px -1px #0f17290f;
|
|
35
|
+
--elev-2: inset 0 1px 0 #ffffffcc, 0 0 0 1px #0f172912, 0 2px 4px -1px #0f172914, 0 8px 16px -6px #0f172924;
|
|
36
|
+
--elev-3: inset 0 1px 0 #ffffffe6, 0 0 0 1px #0f17290f, 0 4px 8px -2px #0f172914, 0 16px 32px -10px #0f172933;
|
|
37
|
+
--elev-4: inset 0 1px 0 #ffffff, 0 0 0 1px #0f17290d, 0 8px 16px -4px #0f172917, 0 28px 56px -16px #0f17293d;
|
|
38
|
+
--elev-5: inset 0 1px 0 #ffffff, 0 0 0 1px #0f17290a, 0 12px 24px -6px #0f17291a, 0 48px 96px -24px #0f17294d;
|
|
39
|
+
--lip-top: inset 0 18px 18px -18px #0f17293d;
|
|
40
|
+
--lip-bottom: inset 0 -18px 18px -18px #0f17293d;
|
|
41
|
+
}
|
|
42
|
+
[data-theme="nightfall"] {
|
|
43
|
+
--surface-trench: #08090c;
|
|
44
|
+
--surface-well: #0c0e12;
|
|
45
|
+
--surface-ground: #121419;
|
|
46
|
+
--surface-raised: #191c23;
|
|
47
|
+
--surface-lifted: #1f232b;
|
|
48
|
+
--surface-floating: #252a33;
|
|
49
|
+
--surface-overlay: #2a303a;
|
|
50
|
+
--surface-modal: #2f3541;
|
|
51
|
+
--ink: #eef1f6;
|
|
52
|
+
--ink-muted: #a3abb9;
|
|
53
|
+
--ink-faint: #5f6775;
|
|
54
|
+
--line: #262a33;
|
|
55
|
+
--line-control: #6a7280;
|
|
56
|
+
--accent: #86a2ff;
|
|
57
|
+
--on-accent: #0b1022;
|
|
58
|
+
--accent-ink: #93acff;
|
|
59
|
+
--accent-soft: #1c2440;
|
|
60
|
+
--positive: #56cf9f;
|
|
61
|
+
--positive-soft: #10291f;
|
|
62
|
+
--caution: #ebb550;
|
|
63
|
+
--caution-soft: #2e2411;
|
|
64
|
+
--critical: #ff8064;
|
|
65
|
+
--critical-soft: #3a1913;
|
|
66
|
+
--on-critical: #1a0905;
|
|
67
|
+
--presence-1: #f07ab8;
|
|
68
|
+
--presence-2: #3fc1d0;
|
|
69
|
+
--presence-3: #b39dff;
|
|
70
|
+
--on-presence: #0b0d12;
|
|
71
|
+
--scrim: #00000080;
|
|
72
|
+
--trench: inset 0 2px 4px #000000b3, 0 0 0 0 #00000000, 0 0 0 0 #00000000, 0 0 0 0 #00000000;
|
|
73
|
+
--well: inset 0 1px 2px #00000099, 0 0 0 0 #00000000, 0 0 0 0 #00000000, 0 0 0 0 #00000000;
|
|
74
|
+
--elev-0: inset 0 1px 0 #ffffff00, 0 0 0 0 #00000000, 0 0 0 0 #00000000, 0 0 0 0 #00000000;
|
|
75
|
+
--elev-1: inset 0 1px 0 #ffffff12, 0 0 0 1px #ffffff0a, 0 1px 2px #00000080, 0 2px 6px -1px #00000052;
|
|
76
|
+
--elev-2: inset 0 1px 0 #ffffff17, 0 0 0 1px #ffffff0d, 0 2px 4px -1px #00000073, 0 10px 20px -6px #00000066;
|
|
77
|
+
--elev-3: inset 0 1px 0 #ffffff1c, 0 0 0 1px #ffffff0f, 0 4px 8px -2px #00000073, 0 18px 36px -10px #00000080;
|
|
78
|
+
--elev-4: inset 0 1px 0 #ffffff21, 0 0 0 1px #ffffff12, 0 8px 16px -4px #00000080, 0 30px 60px -16px #0000008c;
|
|
79
|
+
--elev-5: inset 0 1px 0 #ffffff26, 0 0 0 1px #ffffff14, 0 12px 24px -6px #0000008c, 0 48px 96px -24px #00000099;
|
|
80
|
+
--lip-top: inset 0 18px 18px -18px #000000cc;
|
|
81
|
+
--lip-bottom: inset 0 -18px 18px -18px #000000cc;
|
|
82
|
+
}
|
|
83
|
+
[data-theme="mesa"] {
|
|
84
|
+
--surface-trench: #e5ddd2;
|
|
85
|
+
--surface-well: #eee7dd;
|
|
86
|
+
--surface-ground: #f6f1ea;
|
|
87
|
+
--surface-raised: #fffcf8;
|
|
88
|
+
--surface-lifted: #fffdfa;
|
|
89
|
+
--surface-floating: #ffffff;
|
|
90
|
+
--surface-overlay: #ffffff;
|
|
91
|
+
--surface-modal: #ffffff;
|
|
92
|
+
--ink: #221b14;
|
|
93
|
+
--ink-muted: #62564a;
|
|
94
|
+
--ink-faint: #a09484;
|
|
95
|
+
--line: #e6ded3;
|
|
96
|
+
--line-control: #807467;
|
|
97
|
+
--accent: #b4441b;
|
|
98
|
+
--on-accent: #ffffff;
|
|
99
|
+
--accent-ink: #a63e17;
|
|
100
|
+
--accent-soft: #f8e4d9;
|
|
101
|
+
--positive: #2c6e3f;
|
|
102
|
+
--positive-soft: #e3efdc;
|
|
103
|
+
--caution: #8a5000;
|
|
104
|
+
--caution-soft: #fbeccf;
|
|
105
|
+
--critical: #b3261e;
|
|
106
|
+
--critical-soft: #f9e1dc;
|
|
107
|
+
--on-critical: #ffffff;
|
|
108
|
+
--presence-1: #a8256a;
|
|
109
|
+
--presence-2: #0b7285;
|
|
110
|
+
--presence-3: #6e44c2;
|
|
111
|
+
--on-presence: #ffffff;
|
|
112
|
+
--scrim: #221b144d;
|
|
113
|
+
--trench: inset 0 1px 3px #2a1a0c2e, 0 0 0 0 #2a1a0c00, 0 0 0 0 #2a1a0c00, 0 0 0 0 #2a1a0c00;
|
|
114
|
+
--well: inset 0 1px 2px #2a1a0c1a, 0 0 0 0 #2a1a0c00, 0 0 0 0 #2a1a0c00, 0 0 0 0 #2a1a0c00;
|
|
115
|
+
--elev-0: inset 0 1px 0 #ffffff00, 0 0 0 0 #2a1a0c00, 0 0 0 0 #2a1a0c00, 0 0 0 0 #2a1a0c00;
|
|
116
|
+
--elev-1: inset 0 1px 0 #ffffffb3, 0 0 0 1px #2a1a0c17, 0 1px 2px #2a1a0c12, 0 2px 4px -1px #2a1a0c0f;
|
|
117
|
+
--elev-2: inset 0 1px 0 #ffffffcc, 0 0 0 1px #2a1a0c12, 0 2px 4px -1px #2a1a0c14, 0 8px 16px -6px #2a1a0c24;
|
|
118
|
+
--elev-3: inset 0 1px 0 #ffffffe6, 0 0 0 1px #2a1a0c0f, 0 4px 8px -2px #2a1a0c14, 0 16px 32px -10px #2a1a0c33;
|
|
119
|
+
--elev-4: inset 0 1px 0 #ffffff, 0 0 0 1px #2a1a0c0d, 0 8px 16px -4px #2a1a0c17, 0 28px 56px -16px #2a1a0c3d;
|
|
120
|
+
--elev-5: inset 0 1px 0 #ffffff, 0 0 0 1px #2a1a0c0a, 0 12px 24px -6px #2a1a0c1a, 0 48px 96px -24px #2a1a0c4d;
|
|
121
|
+
--lip-top: inset 0 18px 18px -18px #2a1a0c3d;
|
|
122
|
+
--lip-bottom: inset 0 -18px 18px -18px #2a1a0c3d;
|
|
123
|
+
}
|
|
124
|
+
[data-theme="alpine"] {
|
|
125
|
+
--surface-trench: #060a09;
|
|
126
|
+
--surface-well: #0a0f0e;
|
|
127
|
+
--surface-ground: #0f1513;
|
|
128
|
+
--surface-raised: #151e1b;
|
|
129
|
+
--surface-lifted: #1a2522;
|
|
130
|
+
--surface-floating: #202c28;
|
|
131
|
+
--surface-overlay: #25332f;
|
|
132
|
+
--surface-modal: #2a3935;
|
|
133
|
+
--ink: #eaf3ef;
|
|
134
|
+
--ink-muted: #9db0a9;
|
|
135
|
+
--ink-faint: #5d6c67;
|
|
136
|
+
--line: #222c29;
|
|
137
|
+
--line-control: #62736d;
|
|
138
|
+
--accent: #5fd6b2;
|
|
139
|
+
--on-accent: #04140f;
|
|
140
|
+
--accent-ink: #6fdcbc;
|
|
141
|
+
--accent-soft: #13302a;
|
|
142
|
+
--positive: #8ed67a;
|
|
143
|
+
--positive-soft: #1a2e17;
|
|
144
|
+
--caution: #efbd5b;
|
|
145
|
+
--caution-soft: #2f2712;
|
|
146
|
+
--critical: #ff8a70;
|
|
147
|
+
--critical-soft: #3a1a14;
|
|
148
|
+
--on-critical: #1a0905;
|
|
149
|
+
--presence-1: #f07ab8;
|
|
150
|
+
--presence-2: #5cc8e0;
|
|
151
|
+
--presence-3: #b9a3ff;
|
|
152
|
+
--on-presence: #06100d;
|
|
153
|
+
--scrim: #00000080;
|
|
154
|
+
--trench: inset 0 2px 4px #000000b3, 0 0 0 0 #00000000, 0 0 0 0 #00000000, 0 0 0 0 #00000000;
|
|
155
|
+
--well: inset 0 1px 2px #00000099, 0 0 0 0 #00000000, 0 0 0 0 #00000000, 0 0 0 0 #00000000;
|
|
156
|
+
--elev-0: inset 0 1px 0 #ffffff00, 0 0 0 0 #00000000, 0 0 0 0 #00000000, 0 0 0 0 #00000000;
|
|
157
|
+
--elev-1: inset 0 1px 0 #ffffff12, 0 0 0 1px #ffffff0a, 0 1px 2px #00000080, 0 2px 6px -1px #00000052;
|
|
158
|
+
--elev-2: inset 0 1px 0 #ffffff17, 0 0 0 1px #ffffff0d, 0 2px 4px -1px #00000073, 0 10px 20px -6px #00000066;
|
|
159
|
+
--elev-3: inset 0 1px 0 #ffffff1c, 0 0 0 1px #ffffff0f, 0 4px 8px -2px #00000073, 0 18px 36px -10px #00000080;
|
|
160
|
+
--elev-4: inset 0 1px 0 #ffffff21, 0 0 0 1px #ffffff12, 0 8px 16px -4px #00000080, 0 30px 60px -16px #0000008c;
|
|
161
|
+
--elev-5: inset 0 1px 0 #ffffff26, 0 0 0 1px #ffffff14, 0 12px 24px -6px #0000008c, 0 48px 96px -24px #00000099;
|
|
162
|
+
--lip-top: inset 0 18px 18px -18px #000000cc;
|
|
163
|
+
--lip-bottom: inset 0 -18px 18px -18px #000000cc;
|
|
164
|
+
}
|
|
165
|
+
:root {
|
|
166
|
+
--space-1: 4px;
|
|
167
|
+
--space-2: 8px;
|
|
168
|
+
--space-3: 12px;
|
|
169
|
+
--space-4: 16px;
|
|
170
|
+
--space-5: 20px;
|
|
171
|
+
--space-6: 24px;
|
|
172
|
+
--space-8: 32px;
|
|
173
|
+
--space-12: 48px;
|
|
174
|
+
--radius-xs: 4px;
|
|
175
|
+
--radius-sm: 7px;
|
|
176
|
+
--radius-md: 10px;
|
|
177
|
+
--radius-lg: 14px;
|
|
178
|
+
--radius-xl: 20px;
|
|
179
|
+
--radius-full: 9999px;
|
|
180
|
+
--dur-press: 90ms;
|
|
181
|
+
--dur-travel-1: 140ms;
|
|
182
|
+
--dur-travel-2: 180ms;
|
|
183
|
+
--dur-travel-3: 220ms;
|
|
184
|
+
--dur-travel-4: 260ms;
|
|
185
|
+
--dur-travel-5: 300ms;
|
|
186
|
+
--dur-sweep: 1600ms;
|
|
187
|
+
--dur-grace: 300ms;
|
|
188
|
+
--dur-onset: 500ms;
|
|
189
|
+
--dur-hold: 1000ms;
|
|
190
|
+
--dur-hover: 1800ms;
|
|
191
|
+
--dur-settle: 8000ms;
|
|
192
|
+
--ease-rise: cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
193
|
+
--ease-sink: cubic-bezier(0.45, 0, 0.8, 0.35);
|
|
194
|
+
--ease-settle: cubic-bezier(0.3, 1.3, 0.45, 1);
|
|
195
|
+
--ease-glide: cubic-bezier(0.65, 0, 0.35, 1);
|
|
196
|
+
--ease-decay: cubic-bezier(0.25, 0.4, 0.35, 1);
|
|
197
|
+
--wall-1: 2px;
|
|
198
|
+
--wall-2: 4px;
|
|
199
|
+
--z-floating: 30;
|
|
200
|
+
--z-overlay: 40;
|
|
201
|
+
--z-modal: 50;
|
|
202
|
+
--z-toast: 60;
|
|
203
|
+
--font-sans: "Instrument Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
204
|
+
--font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
/* Altitude — component styles. Every value comes from tokens.css; the only
|
|
209
|
+
local knob is --alt-travel (1 = full motion, 0 = reduced: altitude still
|
|
210
|
+
changes, nothing moves). */
|
|
211
|
+
|
|
212
|
+
:root {
|
|
213
|
+
--alt-travel: 1;
|
|
214
|
+
/* Convexity cue: a 2–5 L* light-to-dark face gradient on things you press (measured; see Research). Pressing flattens it. */
|
|
215
|
+
--alt-sheen: linear-gradient(to bottom, rgb(255 255 255 / 0.06), rgb(0 0 0 / 0.03));
|
|
216
|
+
}
|
|
217
|
+
:root, [data-theme] {
|
|
218
|
+
/* The hairline that outlines a slab, face and wall together, so its edges read on light grounds. */
|
|
219
|
+
--alt-ring: color-mix(in oklab, var(--ink) 12%, transparent);
|
|
220
|
+
/* A contact or cast shadow on the ground (avatars, crumbs, sheets). */
|
|
221
|
+
--alt-cast: rgb(15 23 41 / 0.22);
|
|
222
|
+
/* A cast shadow seen with a clear gap under its object (avatars) needs a denser core to read. */
|
|
223
|
+
--alt-cast-deep: rgb(15 23 41 / 0.36);
|
|
224
|
+
/* The inside wall of an opening, seen past its top edge. */
|
|
225
|
+
--alt-wall-in: color-mix(in oklab, var(--surface-trench), var(--ink) 10%);
|
|
226
|
+
/* Light catching the far edge of a cut in the page. */
|
|
227
|
+
--alt-lip: rgb(255 255 255 / 0.7);
|
|
228
|
+
/* The rim of an opening you're filling (a focused field, an open select): a neutral, never the accent, so a form
|
|
229
|
+
in use stays calm. 80% ink keeps a 3:1 change from line-control in every scheme. */
|
|
230
|
+
--alt-rim-held: color-mix(in oklab, var(--ink) 80%, var(--line-control));
|
|
231
|
+
}
|
|
232
|
+
[data-theme="mesa"] { --alt-cast: rgb(42 26 12 / 0.22); --alt-cast-deep: rgb(42 26 12 / 0.36); }
|
|
233
|
+
[data-theme="nightfall"], [data-theme="alpine"] {
|
|
234
|
+
--alt-ring: color-mix(in oklab, var(--ink) 9%, transparent); --alt-cast: rgb(0 0 0 / 0.8); --alt-cast-deep: rgb(0 0 0 / 1);
|
|
235
|
+
--alt-wall-in: color-mix(in oklab, var(--surface-trench), #000 55%); --alt-lip: rgb(255 255 255 / 0.035);
|
|
236
|
+
}
|
|
237
|
+
/* Approach: [data-approach] elements receive --near (0 far … 1 touching) from the pointer tracker, and --mx/--my
|
|
238
|
+
(−1…1, where the pointer is on them) while hovered. --n is --near with reduced motion folded in. Approach belongs
|
|
239
|
+
to openings only (inputs, selects, the sheet's finger pull): an opening may deepen as a hand comes near, but
|
|
240
|
+
nothing raised ever moves until the pointer is actually on it. */
|
|
241
|
+
.alt-input, [data-approach] { --near: 0; --mx: 0; --my: 0; --n: calc(var(--near) * var(--alt-travel)); }
|
|
242
|
+
.alt-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
243
|
+
@media (prefers-reduced-motion: reduce) { :root { --alt-travel: 0; } }
|
|
244
|
+
[data-motion="reduced"] { --alt-travel: 0; }
|
|
245
|
+
[data-motion="full"] { --alt-travel: 1; }
|
|
246
|
+
|
|
247
|
+
body { margin: 0; background: var(--surface-ground); color: var(--ink); font-family: var(--font-sans); -webkit-font-smoothing: antialiased; }
|
|
248
|
+
.alt-root { font-family: var(--font-sans); color: var(--ink); -webkit-font-smoothing: antialiased; }
|
|
249
|
+
.alt-root[data-theme] { background: var(--surface-ground); }
|
|
250
|
+
.alt-root *, .alt-root *::before, .alt-root *::after { box-sizing: border-box; }
|
|
251
|
+
.alt-stage { transform-origin: 50% 35%; transition: transform var(--dur-travel-5) var(--ease-rise), filter var(--dur-travel-5) var(--ease-rise); }
|
|
252
|
+
.alt-stage[data-receded] { transform: scale(calc(1 - 0.015 * var(--alt-travel))); filter: saturate(0.85); }
|
|
253
|
+
|
|
254
|
+
@keyframes alt-emerge { from { opacity: 0; transform: translateY(calc(var(--alt-from-y, 6px) * var(--alt-travel))); } }
|
|
255
|
+
@keyframes alt-spin { to { transform: rotate(360deg); } }
|
|
256
|
+
@keyframes alt-sweep { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
|
|
257
|
+
@keyframes alt-travel { from { transform: translateX(-110%); } to { transform: translateX(310%); } }
|
|
258
|
+
.alt-spinner { animation: alt-spin 800ms linear infinite; }
|
|
259
|
+
|
|
260
|
+
/* ── Surface: the primitive. data-level sets the tint and shadow; .alt-lift climbs one level on hover and presses to ground. ── */
|
|
261
|
+
.alt-surface { background: var(--alt-bg); box-shadow: var(--alt-sh); color: var(--ink); border-radius: var(--radius-lg); }
|
|
262
|
+
[data-level="-2"] { --alt-bg: var(--surface-trench); --alt-sh: var(--trench); --alt-bg-up: var(--surface-well); --alt-sh-up: var(--well); }
|
|
263
|
+
[data-level="-1"] { --alt-bg: var(--surface-well); --alt-sh: var(--well); --alt-bg-up: var(--surface-ground); --alt-sh-up: var(--elev-0); }
|
|
264
|
+
[data-level="0"] { --alt-bg: var(--surface-ground); --alt-sh: var(--elev-0); --alt-bg-up: var(--surface-raised); --alt-sh-up: var(--elev-1); }
|
|
265
|
+
[data-level="1"] { --alt-bg: var(--surface-raised); --alt-sh: var(--elev-1); --alt-bg-up: var(--surface-lifted); --alt-sh-up: var(--elev-2); }
|
|
266
|
+
[data-level="2"] { --alt-bg: var(--surface-lifted); --alt-sh: var(--elev-2); --alt-bg-up: var(--surface-floating); --alt-sh-up: var(--elev-3); }
|
|
267
|
+
[data-level="3"] { --alt-bg: var(--surface-floating); --alt-sh: var(--elev-3); --alt-bg-up: var(--surface-overlay); --alt-sh-up: var(--elev-4); }
|
|
268
|
+
[data-level="4"] { --alt-bg: var(--surface-overlay); --alt-sh: var(--elev-4); --alt-bg-up: var(--surface-modal); --alt-sh-up: var(--elev-5); }
|
|
269
|
+
[data-level="5"] { --alt-bg: var(--surface-modal); --alt-sh: var(--elev-5); --alt-bg-up: var(--surface-modal); --alt-sh-up: var(--elev-5); }
|
|
270
|
+
|
|
271
|
+
.alt-lift {
|
|
272
|
+
cursor: pointer;
|
|
273
|
+
transition: box-shadow var(--dur-travel-1) var(--ease-rise), background-color var(--dur-travel-1) var(--ease-rise), transform var(--dur-travel-2) var(--ease-settle);
|
|
274
|
+
}
|
|
275
|
+
.alt-lift:hover, .alt-lift:focus-visible { background: var(--alt-bg-up); box-shadow: var(--alt-sh-up); transform: translateY(calc(-1px * var(--alt-travel))); }
|
|
276
|
+
.alt-lift:active { box-shadow: var(--elev-0); transform: translateY(calc(1px * var(--alt-travel))); transition-duration: var(--dur-press); transition-timing-function: ease-out; }
|
|
277
|
+
.alt-lift:focus-visible, .alt-tabs-trigger:focus-visible, .alt-acc-trigger:focus-visible,
|
|
278
|
+
.alt-slider-thumb:focus-visible, .alt-switch:focus-visible, .alt-tabs-content:focus-visible, .alt-toast-close:focus-visible {
|
|
279
|
+
outline: 2px solid var(--accent-ink); outline-offset: 2px;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* ── Button: importance is altitude, and altitude is visible as thickness.
|
|
283
|
+
A button is a slab standing on the ground: its face sits `--wall` above it, and the wall under the
|
|
284
|
+
face is that height made visible (wall-2 for primary and danger, wall-1 for secondary, none for ghost).
|
|
285
|
+
Hover raises the face 1px (the wall grows to stay on the ground). Pressing pushes the face all the
|
|
286
|
+
way down: the wall disappears and the sheen flattens. The shadow list is always five layers —
|
|
287
|
+
[wall, rim, ring, key, ambient] — so every state interpolates. ── */
|
|
288
|
+
.alt-btn {
|
|
289
|
+
--wall: var(--wall-1); --wall-c: var(--surface-trench);
|
|
290
|
+
--alt-bg: var(--surface-raised); --alt-bg-up: var(--surface-lifted); --alt-fg: var(--ink); --alt-sh: var(--elev-1); --alt-sh-up: var(--elev-2);
|
|
291
|
+
position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none;
|
|
292
|
+
height: 36px; padding: 0 var(--space-4); border: 0; border-radius: var(--radius-md);
|
|
293
|
+
font: 500 14px/20px var(--font-sans); letter-spacing: -0.003em; white-space: nowrap; user-select: none; cursor: pointer;
|
|
294
|
+
background: var(--alt-bg); background-image: var(--alt-sheen); color: var(--alt-fg);
|
|
295
|
+
/* A button stays exactly where it is until the pointer is on it: no approach, no lean. */
|
|
296
|
+
box-shadow: 0 var(--wall) 0 0 var(--wall-c), var(--alt-sh);
|
|
297
|
+
-webkit-tap-highlight-color: transparent;
|
|
298
|
+
transition: box-shadow var(--dur-travel-1) var(--ease-rise), background-color var(--dur-travel-1) var(--ease-rise),
|
|
299
|
+
color var(--dur-travel-1) var(--ease-rise), transform var(--dur-travel-2) var(--ease-settle);
|
|
300
|
+
}
|
|
301
|
+
/* Focus ring: wraps the whole slab, face and wall, so it follows the button's real shape at every height. */
|
|
302
|
+
.alt-btn:focus-visible, .alt-crumbs button:focus-visible { outline: none; }
|
|
303
|
+
.alt-btn::after, .alt-crumbs button::after {
|
|
304
|
+
content: ""; position: absolute; pointer-events: none; opacity: 0;
|
|
305
|
+
inset: -4px -4px calc(-4px - var(--wall, 0px) - 1px) -4px; border: 2px solid var(--accent-ink); border-radius: calc(var(--radius-md) + 4px);
|
|
306
|
+
transition: opacity var(--dur-travel-1) var(--ease-rise), inset var(--dur-press) ease-out;
|
|
307
|
+
}
|
|
308
|
+
.alt-btn[data-size="sm"]::after, .alt-crumbs button::after { border-radius: calc(var(--radius-sm) + 4px); }
|
|
309
|
+
.alt-btn:focus-visible::after, .alt-crumbs button:focus-visible::after { opacity: 1; }
|
|
310
|
+
.alt-btn:active::after, .alt-btn[data-loading]::after { inset: -4px; }
|
|
311
|
+
.alt-btn-label { display: inline-flex; align-items: center; gap: var(--space-2); transition: opacity var(--dur-travel-1) var(--ease-rise); }
|
|
312
|
+
.alt-btn-label > svg { flex: none; margin-inline: -2px; }
|
|
313
|
+
.alt-btn[data-variant="primary"] {
|
|
314
|
+
--wall: var(--wall-2); --wall-c: color-mix(in oklab, var(--accent), #000 34%);
|
|
315
|
+
--alt-bg: var(--accent); --alt-bg-up: var(--accent); --alt-fg: var(--on-accent); --alt-sh: var(--elev-2); --alt-sh-up: var(--elev-3);
|
|
316
|
+
}
|
|
317
|
+
.alt-btn[data-variant="danger"] {
|
|
318
|
+
--wall: var(--wall-2); --wall-c: color-mix(in oklab, var(--critical), #000 34%);
|
|
319
|
+
--alt-bg: var(--critical); --alt-bg-up: var(--critical); --alt-fg: var(--on-critical); --alt-sh: var(--elev-2); --alt-sh-up: var(--elev-3);
|
|
320
|
+
}
|
|
321
|
+
.alt-btn[data-variant="ghost"] { --wall: 0px; --alt-bg: transparent; --alt-bg-up: var(--surface-raised); --alt-sh: var(--elev-0); --alt-sh-up: var(--elev-1); background-image: none; }
|
|
322
|
+
.alt-btn[data-variant="ghost"]:hover:not(:disabled), .alt-btn[data-variant="ghost"]:focus-visible { --wall: var(--wall-1); background-image: var(--alt-sheen); }
|
|
323
|
+
.alt-btn[data-size="sm"] { height: 30px; padding: 0 var(--space-3); font-size: 13px; border-radius: var(--radius-sm); }
|
|
324
|
+
.alt-btn[data-size="lg"] { height: 44px; padding: 0 var(--space-5); font-size: 15px; }
|
|
325
|
+
.alt-btn[data-square] { width: 36px; padding: 0; }
|
|
326
|
+
.alt-btn[data-square][data-size="sm"] { width: 30px; }
|
|
327
|
+
.alt-btn[data-square][data-size="lg"] { width: 44px; }
|
|
328
|
+
.alt-btn:hover:not(:disabled):not([data-loading]), .alt-btn:focus-visible {
|
|
329
|
+
background: var(--alt-bg-up); background-image: var(--alt-sheen);
|
|
330
|
+
box-shadow: 0 calc(var(--wall) + 1px) 0 0 var(--wall-c), var(--alt-sh-up); transform: translateY(calc(-1px * var(--alt-travel)));
|
|
331
|
+
}
|
|
332
|
+
.alt-btn:active:not(:disabled):not([data-loading]) {
|
|
333
|
+
box-shadow: 0 0 0 0 var(--wall-c), var(--elev-0); background-image: none; transform: translateY(var(--wall));
|
|
334
|
+
transition-duration: var(--dur-press); transition-timing-function: ease-out;
|
|
335
|
+
}
|
|
336
|
+
.alt-btn[data-loading] { box-shadow: 0 0 0 0 var(--wall-c), var(--elev-0); background-image: none; transform: translateY(var(--wall)); cursor: progress; }
|
|
337
|
+
.alt-btn[data-loading] .alt-btn-label { opacity: 0; }
|
|
338
|
+
.alt-btn-spinner { position: absolute; inset: 0; display: grid; place-items: center; animation: alt-emerge var(--dur-travel-1) var(--ease-rise); --alt-from-y: 0px; }
|
|
339
|
+
.alt-btn:disabled { background: var(--surface-well); background-image: none; color: var(--ink-faint); box-shadow: 0 0 0 0 var(--wall-c), var(--elev-0); cursor: not-allowed; }
|
|
340
|
+
.alt-btn[data-variant="ghost"]:disabled { background: transparent; }
|
|
341
|
+
|
|
342
|
+
/* ── Card ── */
|
|
343
|
+
.alt-card {
|
|
344
|
+
--alt-bg: var(--surface-raised); --alt-bg-up: var(--surface-lifted); --alt-sh: var(--elev-1); --alt-sh-up: var(--elev-2);
|
|
345
|
+
background: var(--alt-bg); box-shadow: var(--alt-sh); border-radius: var(--radius-lg); color: var(--ink);
|
|
346
|
+
display: flex; flex-direction: column;
|
|
347
|
+
}
|
|
348
|
+
.alt-card.alt-lift:hover, .alt-card.alt-lift:focus-visible { transform: translateY(calc(-2px * var(--alt-travel))); }
|
|
349
|
+
.alt-card-header { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-5) var(--space-5) 0; }
|
|
350
|
+
.alt-card-title { margin: 0; font: 600 17px/24px var(--font-sans); letter-spacing: -0.01em; }
|
|
351
|
+
.alt-card-desc { margin: 0; font: 400 14px/20px var(--font-sans); color: var(--ink-muted); }
|
|
352
|
+
.alt-card-content { padding: var(--space-4) var(--space-5) var(--space-5); font: 400 15px/23px var(--font-sans); }
|
|
353
|
+
.alt-card-header + .alt-card-footer { padding-top: var(--space-5); }
|
|
354
|
+
.alt-card-footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); padding: 0 var(--space-5) var(--space-5); }
|
|
355
|
+
|
|
356
|
+
/* ── Input / Textarea: a field is an opening cut into the page, and its depth says whether it still needs filling.
|
|
357
|
+
One camera for everything: under a raised face you see its front wall; inside an opening you see its back wall,
|
|
358
|
+
just below the top edge. An empty field shows that inside wall (wall-in); a pointer approaching deepens it, the
|
|
359
|
+
way a receptacle opens for something about to be put in; once it holds a value the floor rises flush with the
|
|
360
|
+
page and the wall is gone, so a form shows which fields are still holes. Focus is the hand at work: the floor
|
|
361
|
+
lights and an empty field holds the depth that approach previewed until something is put in it. Only focus that
|
|
362
|
+
arrived from the keyboard also darkens the rim to a 2px neutral (--alt-rim-held, never the accent: a form in use
|
|
363
|
+
shouldn't glow); a field you clicked into needs no outline, since you know where you clicked and the caret is there.
|
|
364
|
+
data-key-focus comes from useKeyFocus(). Invalid drops it to trench depth and keyboard focus keeps its rim critical.
|
|
365
|
+
Shadow list is always [wall, occlusion, lip, halo]. ── */
|
|
366
|
+
.alt-input {
|
|
367
|
+
--w: 4px; --wc: var(--alt-wall-in); --halo: 0px; --halo-c: transparent;
|
|
368
|
+
--wd: calc(var(--w) + var(--n) * 2px);
|
|
369
|
+
position: relative; isolation: isolate; display: flex; align-items: center; gap: var(--space-2); height: 40px; padding: 0 var(--space-3);
|
|
370
|
+
border: 1px solid var(--line-control); border-radius: var(--radius-md);
|
|
371
|
+
background: var(--surface-well); color: var(--ink); cursor: text;
|
|
372
|
+
box-shadow: inset 0 var(--wd) 0 0 var(--wc), inset 0 calc(var(--wd) + 3px) 3px -2px var(--alt-cast), 0 1px 0 0 var(--alt-lip), 0 0 0 var(--halo) var(--halo-c);
|
|
373
|
+
transition: background-color var(--dur-travel-2) var(--ease-rise), box-shadow var(--dur-travel-2) var(--ease-settle), border-color var(--dur-travel-1) var(--ease-rise), outline-color var(--dur-travel-1) var(--ease-rise);
|
|
374
|
+
outline: 1px solid transparent; outline-offset: 0;
|
|
375
|
+
}
|
|
376
|
+
.alt-input[data-size="sm"] { --w: 3px; height: 34px; border-radius: var(--radius-sm); }
|
|
377
|
+
.alt-input:hover { border-color: var(--ink-muted); }
|
|
378
|
+
/* Filled: the floor rises flush with the page. Nothing left to receive, so approach no longer deepens it. */
|
|
379
|
+
.alt-input:has(input:not(:placeholder-shown)), .alt-input:has(textarea:not(:placeholder-shown)) { --w: 0px; --n: 0; background: var(--surface-raised); }
|
|
380
|
+
/* Focused: the floor lights up, and an empty field stays open (at the depth approach previewed) until something is put
|
|
381
|
+
in it. Keyboard focus adds the 2px neutral rim, so you can find the field you tabbed to; the command palette's field
|
|
382
|
+
never needs it, since focus never leaves it. */
|
|
383
|
+
.alt-input:focus-within { background: var(--surface-raised); --n: var(--alt-travel); }
|
|
384
|
+
.alt-input[data-key-focus]:focus-within:not(.alt-cmd-field) { border-color: var(--alt-rim-held); outline-color: var(--alt-rim-held); }
|
|
385
|
+
.alt-input input, .alt-input textarea {
|
|
386
|
+
flex: 1; min-width: 0; height: 100%; margin: 0; padding: 0; border: 0; outline: 0; background: none;
|
|
387
|
+
font: 400 14px/20px var(--font-sans); color: inherit;
|
|
388
|
+
/* Content sits on the floor: it moves down with the wall and back up when the floor rises. */
|
|
389
|
+
transform: translateY(calc(var(--wd) * 0.5)); transition: transform var(--dur-travel-2) var(--ease-settle);
|
|
390
|
+
}
|
|
391
|
+
.alt-input input::placeholder, .alt-input textarea::placeholder { color: var(--ink-muted); opacity: 1; }
|
|
392
|
+
.alt-input[data-multiline] { height: auto; padding: var(--space-2) var(--space-3); align-items: stretch; flex-direction: column; overflow: hidden; }
|
|
393
|
+
.alt-input textarea { min-height: 84px; resize: vertical; line-height: 21px; }
|
|
394
|
+
.alt-input-adorn { display: inline-flex; color: var(--ink-muted); flex: none; transform: translateY(calc(var(--wd) * 0.5)); transition: transform var(--dur-travel-2) var(--ease-settle); }
|
|
395
|
+
/* Fill line: with a maxLength, the well fills from the floor as the text approaches the limit. */
|
|
396
|
+
.alt-input-gauge {
|
|
397
|
+
--g: var(--accent-ink);
|
|
398
|
+
position: absolute; left: 0; right: 0; bottom: 0; z-index: -1; height: calc(var(--alt-fill, 0) * 100%);
|
|
399
|
+
background: color-mix(in oklab, var(--g) 7%, transparent); box-shadow: inset 0 1.5px 0 0 color-mix(in oklab, var(--g) 45%, transparent);
|
|
400
|
+
transition: height var(--dur-travel-2) var(--ease-glide), background-color var(--dur-travel-2), box-shadow var(--dur-travel-2);
|
|
401
|
+
}
|
|
402
|
+
.alt-input[data-fill="near"] .alt-input-gauge { --g: var(--caution); }
|
|
403
|
+
.alt-input[data-fill="full"] .alt-input-gauge { --g: var(--critical); }
|
|
404
|
+
.alt-input-count { align-self: flex-end; font: 500 12px/16px var(--font-mono); color: var(--ink-muted); }
|
|
405
|
+
.alt-input[data-fill="near"] .alt-input-count { color: var(--caution); }
|
|
406
|
+
.alt-input[data-fill="full"] .alt-input-count { color: var(--critical); }
|
|
407
|
+
/* Invalid: a problem to fill in. It drops to trench depth, tinted, whether or not it holds a value. */
|
|
408
|
+
.alt-input[data-invalid], .alt-input[data-invalid]:has(input:not(:placeholder-shown)), .alt-input[data-invalid]:has(textarea:not(:placeholder-shown)) {
|
|
409
|
+
--w: 6px; --n: 0; --wc: color-mix(in oklab, var(--critical-soft), var(--critical) 34%);
|
|
410
|
+
background: var(--critical-soft); border-color: var(--critical);
|
|
411
|
+
transition-timing-function: var(--ease-rise), var(--ease-sink), var(--ease-rise), var(--ease-rise);
|
|
412
|
+
}
|
|
413
|
+
.alt-input[data-invalid]:focus-within { background: var(--surface-raised); }
|
|
414
|
+
.alt-input[data-invalid][data-key-focus]:focus-within { border-color: var(--critical); outline-color: var(--critical); }
|
|
415
|
+
.alt-input[data-disabled], .alt-input[data-disabled]:has(input:not(:placeholder-shown)) { --w: 0px; --n: 0; background: var(--surface-ground); border-color: var(--line); color: var(--ink-faint); cursor: not-allowed; }
|
|
416
|
+
.alt-input[data-disabled] input { cursor: not-allowed; }
|
|
417
|
+
|
|
418
|
+
.alt-field { display: flex; flex-direction: column; gap: 6px; }
|
|
419
|
+
.alt-field-label { font: 500 14px/20px var(--font-sans); color: var(--ink); }
|
|
420
|
+
.alt-field-req { color: var(--critical); }
|
|
421
|
+
.alt-field-hint, .alt-field-error { margin: 0; font: 500 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
422
|
+
.alt-field-error { display: flex; gap: 6px; align-items: flex-start; color: var(--critical); --alt-from-y: -4px; animation: alt-emerge var(--dur-travel-2) var(--ease-rise); }
|
|
423
|
+
.alt-field-error svg { flex: none; margin-top: 1.5px; }
|
|
424
|
+
|
|
425
|
+
/* ── Checkbox & Radio: built like the Switch. Off is an empty trench with a line-control rim. On, the accent pours
|
|
426
|
+
into the trench and a raised white mark sits on it: the check for a checkbox, the thumb for a radio. A radio group
|
|
427
|
+
is one switch with several positions, so it has a single thumb that slides to the chosen option. ── */
|
|
428
|
+
.alt-check { position: relative; display: inline-flex; align-items: flex-start; gap: 10px; cursor: pointer; color: var(--ink); -webkit-tap-highlight-color: transparent; }
|
|
429
|
+
.alt-check input { position: absolute; opacity: 0; width: 22px; height: 22px; margin: 0; pointer-events: none; }
|
|
430
|
+
.alt-check-track {
|
|
431
|
+
position: relative; flex: none; box-sizing: border-box; width: 22px; height: 22px;
|
|
432
|
+
border: 1px solid var(--line-control); border-radius: 6px; background: var(--surface-trench); box-shadow: var(--trench);
|
|
433
|
+
transition: border-color var(--dur-travel-2) var(--ease-rise);
|
|
434
|
+
}
|
|
435
|
+
.alt-check-track[data-round] { border-radius: var(--radius-full); }
|
|
436
|
+
.alt-check-fill {
|
|
437
|
+
/* inset −1px: the poured accent covers the rim too, so the fill and the outline are one shape. */
|
|
438
|
+
position: absolute; inset: -1px; border-radius: inherit; background: var(--accent); opacity: 0; clip-path: circle(0% at 50% 50%);
|
|
439
|
+
transition: clip-path var(--dur-travel-2) var(--ease-settle), opacity var(--dur-travel-1) var(--ease-rise);
|
|
440
|
+
}
|
|
441
|
+
.alt-check-mark {
|
|
442
|
+
position: absolute; inset: 0; margin: auto; color: var(--on-accent); pointer-events: none;
|
|
443
|
+
filter: drop-shadow(0 1px 0.5px rgb(0 0 0 / 0.28));
|
|
444
|
+
transition: transform var(--dur-travel-2) var(--ease-settle), filter var(--dur-travel-1) var(--ease-rise), color var(--dur-travel-1);
|
|
445
|
+
}
|
|
446
|
+
/* Hover is feedforward: an unchecked box shows a ghost of the check it would get; a checked one lifts its mark. */
|
|
447
|
+
.alt-check:not(.alt-radio):hover:not([data-disabled]) input:not(:checked):not(:indeterminate) + .alt-check-track .alt-check-mark { color: var(--ink-faint); filter: none; }
|
|
448
|
+
.alt-check:not(.alt-radio):hover:not([data-disabled]) input:not(:checked):not(:indeterminate) + .alt-check-track .alt-check-tick { stroke-dashoffset: 0; opacity: 0.55; transition: stroke-dashoffset var(--dur-travel-2) var(--ease-rise); }
|
|
449
|
+
.alt-check:not(.alt-radio):hover:not([data-disabled]) input:checked + .alt-check-track .alt-check-mark { transform: translateY(calc(-0.5px * var(--alt-travel))); filter: drop-shadow(0 1.5px 1px rgb(0 0 0 / 0.32)); }
|
|
450
|
+
.alt-check input:checked + .alt-check-track, .alt-check input:indeterminate + .alt-check-track { border-color: var(--accent); }
|
|
451
|
+
.alt-check input:checked + .alt-check-track .alt-check-fill, .alt-check input:indeterminate + .alt-check-track .alt-check-fill { opacity: 1; clip-path: circle(75% at 50% 50%); }
|
|
452
|
+
.alt-check:hover:not([data-disabled]) input:not(:checked):not(:indeterminate) + .alt-check-track { border-color: var(--ink-muted); }
|
|
453
|
+
.alt-check:not(.alt-radio):active:not([data-disabled]) .alt-check-track { box-shadow: var(--trench); }
|
|
454
|
+
.alt-check:not(.alt-radio):active:not([data-disabled]) .alt-check-mark { transform: scale(calc(1 - 0.12 * var(--alt-travel))); transition-duration: var(--dur-press); }
|
|
455
|
+
.alt-check input:focus-visible + .alt-check-track { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
456
|
+
.alt-check-mark path { stroke-dasharray: 16; stroke-dashoffset: 16; transition: stroke-dashoffset var(--dur-travel-1) var(--ease-sink); }
|
|
457
|
+
.alt-check input:checked:not(:indeterminate) + .alt-check-track .alt-check-tick,
|
|
458
|
+
.alt-check input:indeterminate + .alt-check-track .alt-check-dash { stroke-dashoffset: 0; transition: stroke-dashoffset var(--dur-travel-2) var(--ease-rise) 60ms; }
|
|
459
|
+
.alt-check-text { display: flex; flex-direction: column; gap: 2px; padding-top: 1px; }
|
|
460
|
+
.alt-check-label { font: 500 14px/20px var(--font-sans); }
|
|
461
|
+
.alt-check-desc { font: 400 13px/18px var(--font-sans); color: var(--ink-muted); }
|
|
462
|
+
.alt-check[data-disabled] { cursor: not-allowed; color: var(--ink-faint); }
|
|
463
|
+
.alt-check[data-disabled] .alt-check-track { border-color: var(--line); background: var(--surface-ground); box-shadow: var(--elev-0); }
|
|
464
|
+
.alt-check[data-disabled] .alt-check-mark { color: var(--ink-faint); filter: none; }
|
|
465
|
+
.alt-check[data-disabled] .alt-check-fill { background: var(--line); }
|
|
466
|
+
.alt-check[data-disabled] .alt-check-desc { color: var(--ink-faint); }
|
|
467
|
+
.alt-radio-group { position: relative; display: flex; flex-direction: column; gap: var(--space-3); }
|
|
468
|
+
.alt-radio-group[data-orientation="horizontal"] { flex-direction: row; flex-wrap: wrap; gap: var(--space-5); }
|
|
469
|
+
.alt-radio .alt-check-fill { transition: clip-path var(--dur-travel-1) var(--ease-sink), opacity var(--dur-travel-1) var(--ease-sink); }
|
|
470
|
+
.alt-radio input:checked + .alt-check-track .alt-check-fill {
|
|
471
|
+
transition: clip-path var(--dur-travel-2) var(--ease-settle) calc(var(--dur-travel-3) * 0.4), opacity var(--dur-travel-1) var(--ease-rise) calc(var(--dur-travel-3) * 0.4);
|
|
472
|
+
}
|
|
473
|
+
.alt-radio-thumb {
|
|
474
|
+
position: absolute; left: 0; top: 0; z-index: 1; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: var(--radius-full); pointer-events: none;
|
|
475
|
+
background: var(--surface-raised); background-image: var(--alt-sheen); box-shadow: var(--elev-1);
|
|
476
|
+
transition: box-shadow var(--dur-travel-1) var(--ease-rise), scale var(--dur-travel-2) var(--ease-settle);
|
|
477
|
+
}
|
|
478
|
+
.alt-radio-thumb[data-ready] { transition: transform var(--dur-travel-3) var(--ease-settle), box-shadow var(--dur-travel-1) var(--ease-rise), scale var(--dur-travel-2) var(--ease-settle); }
|
|
479
|
+
.alt-radio-group:has(.alt-radio:hover input:checked) .alt-radio-thumb { box-shadow: var(--elev-2); }
|
|
480
|
+
.alt-radio-group:has(.alt-radio:active input:checked) .alt-radio-thumb { scale: calc(1 + 0.25 * var(--alt-travel)) calc(1 - 0.08 * var(--alt-travel)); }
|
|
481
|
+
/* Feedforward: hovering an unchosen option shows a ghost of the thumb where it would land. */
|
|
482
|
+
.alt-radio .alt-check-track::after {
|
|
483
|
+
content: ""; position: absolute; left: 50%; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: var(--radius-full);
|
|
484
|
+
background: var(--surface-raised); box-shadow: var(--elev-1); opacity: 0; scale: 0.5; pointer-events: none;
|
|
485
|
+
transition: opacity var(--dur-travel-1) var(--ease-sink), scale var(--dur-travel-2) var(--ease-settle);
|
|
486
|
+
}
|
|
487
|
+
.alt-radio:hover:not([data-disabled]) input:not(:checked) + .alt-check-track::after { opacity: 0.5; scale: 0.85; transition-timing-function: var(--ease-rise), var(--ease-settle); }
|
|
488
|
+
.alt-radio-group[data-disabled] .alt-radio-thumb { background: var(--surface-well); background-image: none; box-shadow: var(--elev-0); }
|
|
489
|
+
|
|
490
|
+
/* ── Switch: a trench with a raised thumb; the accent pours in behind the thumb. ── */
|
|
491
|
+
.alt-switch {
|
|
492
|
+
--track: 36px; --tw: 18px;
|
|
493
|
+
position: relative; flex: none; width: 42px; height: 24px; padding: 0; border: 1px solid var(--line-control); border-radius: var(--radius-full);
|
|
494
|
+
background: var(--surface-trench); box-shadow: var(--trench); cursor: pointer; -webkit-tap-highlight-color: transparent;
|
|
495
|
+
transition: border-color var(--dur-travel-2) var(--ease-rise);
|
|
496
|
+
}
|
|
497
|
+
.alt-switch-fill {
|
|
498
|
+
position: absolute; inset: 0; border-radius: inherit; background: var(--accent); opacity: 0;
|
|
499
|
+
clip-path: inset(0 calc(100% - 22px) 0 0 round 999px);
|
|
500
|
+
transition: clip-path var(--dur-travel-2) var(--ease-settle), opacity var(--dur-travel-1) var(--ease-rise);
|
|
501
|
+
}
|
|
502
|
+
.alt-switch-thumb {
|
|
503
|
+
position: absolute; top: 2px; left: 2px; width: var(--tw); height: 18px; border-radius: var(--radius-full);
|
|
504
|
+
background: var(--surface-raised); background-image: var(--alt-sheen); box-shadow: var(--elev-1);
|
|
505
|
+
transition: transform var(--dur-travel-2) var(--ease-settle), width var(--dur-travel-2) var(--ease-settle), box-shadow var(--dur-travel-1) var(--ease-rise);
|
|
506
|
+
}
|
|
507
|
+
.alt-switch[aria-checked="true"] { border-color: var(--accent); }
|
|
508
|
+
.alt-switch[aria-checked="true"] .alt-switch-fill { opacity: 1; clip-path: inset(0 0 0 0 round 999px); }
|
|
509
|
+
.alt-switch[aria-checked="true"] .alt-switch-thumb { transform: translateX(calc(var(--track) - var(--tw))); }
|
|
510
|
+
.alt-switch:hover:not(:disabled) .alt-switch-thumb { box-shadow: var(--elev-2); }
|
|
511
|
+
.alt-switch:active:not(:disabled) { --tw: calc(18px + 5px * var(--alt-travel)); }
|
|
512
|
+
.alt-switch:disabled { cursor: not-allowed; border-color: var(--line); background: var(--surface-ground); box-shadow: var(--elev-0); }
|
|
513
|
+
.alt-switch:disabled .alt-switch-thumb { box-shadow: var(--elev-0); background: var(--surface-well); }
|
|
514
|
+
.alt-switch:disabled .alt-switch-fill { background: var(--line); }
|
|
515
|
+
.alt-switch-row { display: inline-flex; align-items: center; gap: 10px; font: 500 14px/20px var(--font-sans); color: var(--ink); cursor: pointer; }
|
|
516
|
+
.alt-switch-row[data-disabled] { color: var(--ink-faint); cursor: not-allowed; }
|
|
517
|
+
|
|
518
|
+
/* ── Tabs. Default, "folder": every tab is the top edge of its own sheet, and the sheet on top is the one you're
|
|
519
|
+
reading. The chosen tab and its panel are one raised piece (with concave fillets where they meet); the other tabs
|
|
520
|
+
lie flush behind it. Choosing a tab brings its sheet up from behind (its tab rises into place, the panel's shadow
|
|
521
|
+
swells as it surfaces) while the old tab drops back. Hovering a tab peeks its sheet up a little.
|
|
522
|
+
variant="segmented": the options sit in a well and one raised pill glides between them. ── */
|
|
523
|
+
.alt-tabs { display: flex; flex-direction: column; gap: var(--space-4); }
|
|
524
|
+
.alt-tabs-list {
|
|
525
|
+
position: relative; display: inline-flex; align-self: flex-start; gap: 2px; padding: var(--space-1);
|
|
526
|
+
border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-well); box-shadow: var(--well);
|
|
527
|
+
}
|
|
528
|
+
.alt-tabs-indicator {
|
|
529
|
+
position: absolute; top: var(--space-1); bottom: var(--space-1); left: 0; border-radius: calc(var(--radius-md) - var(--space-1));
|
|
530
|
+
background: var(--surface-raised); background-image: var(--alt-sheen); box-shadow: var(--elev-1); pointer-events: none;
|
|
531
|
+
}
|
|
532
|
+
.alt-tabs-indicator[data-ready] { transition: transform var(--dur-travel-3) var(--ease-settle), width var(--dur-travel-3) var(--ease-settle), opacity var(--dur-travel-1); }
|
|
533
|
+
.alt-tabs-trigger {
|
|
534
|
+
position: relative; z-index: 1; height: 30px; padding: 0 var(--space-3); border: 0; border-radius: calc(var(--radius-md) - var(--space-1));
|
|
535
|
+
background: none; color: var(--ink-muted); font: 500 14px/20px var(--font-sans); cursor: pointer; white-space: nowrap;
|
|
536
|
+
transition: color var(--dur-travel-1) var(--ease-rise), background-color var(--dur-travel-1) var(--ease-rise);
|
|
537
|
+
}
|
|
538
|
+
.alt-tabs-trigger:hover, .alt-tabs-trigger[aria-selected="true"] { color: var(--ink); }
|
|
539
|
+
.alt-tabs[data-variant="segmented"] .alt-tabs-trigger:hover:not([aria-selected="true"]) { background: color-mix(in oklab, var(--surface-raised) 40%, transparent); }
|
|
540
|
+
.alt-tabs-content { animation: alt-emerge var(--dur-travel-2) var(--ease-rise); border-radius: var(--radius-sm); }
|
|
541
|
+
|
|
542
|
+
.alt-tabs[data-variant="folder"] { gap: 0; }
|
|
543
|
+
.alt-tabs[data-variant="folder"] > .alt-tabs-list {
|
|
544
|
+
--r: 10px; align-self: stretch; z-index: 2; gap: var(--space-1); margin-bottom: -1px; padding: 0 var(--space-5);
|
|
545
|
+
border: 0; border-radius: 0; background: none; box-shadow: none;
|
|
546
|
+
}
|
|
547
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-indicator { display: none; }
|
|
548
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger { isolation: isolate; height: 38px; padding: 0 var(--space-4); border-radius: var(--r) var(--r) 0 0; }
|
|
549
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger:focus-visible { outline-offset: -5px; }
|
|
550
|
+
/* The tab: the top edge of its sheet. It reaches 1px into the panel to cover the panel's top hairline. */
|
|
551
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger::before {
|
|
552
|
+
content: ""; position: absolute; inset: 0 0 -1px; z-index: -1; border-radius: inherit; pointer-events: none;
|
|
553
|
+
background: var(--surface-raised); box-shadow: 0 0 0 1px var(--alt-ring), 0 -2px 5px -2px var(--alt-cast); clip-path: inset(-8px -8px 0 -8px);
|
|
554
|
+
opacity: 0; transform: translateY(calc(10px * var(--alt-travel)));
|
|
555
|
+
transition: opacity var(--dur-travel-1) var(--ease-sink), transform var(--dur-travel-2) var(--ease-sink), background-color var(--dur-travel-1);
|
|
556
|
+
}
|
|
557
|
+
/* Fillets: the concave corners where the tab flows into the panel, hairline included. */
|
|
558
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger::after {
|
|
559
|
+
content: ""; position: absolute; bottom: -1px; left: calc(-1 * var(--r)); right: calc(-1 * var(--r)); height: var(--r); z-index: -1; pointer-events: none;
|
|
560
|
+
background:
|
|
561
|
+
radial-gradient(circle at 0 0, transparent calc(var(--r) - 0.75px), var(--alt-ring) calc(var(--r) - 0.5px), var(--alt-ring) calc(var(--r) + 0.25px), var(--surface-raised) calc(var(--r) + 0.75px)) left / var(--r) var(--r) no-repeat,
|
|
562
|
+
radial-gradient(circle at 100% 0, transparent calc(var(--r) - 0.75px), var(--alt-ring) calc(var(--r) - 0.5px), var(--alt-ring) calc(var(--r) + 0.25px), var(--surface-raised) calc(var(--r) + 0.75px)) right / var(--r) var(--r) no-repeat;
|
|
563
|
+
opacity: 0; transition: opacity var(--dur-travel-1) var(--ease-sink);
|
|
564
|
+
}
|
|
565
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger[aria-selected="true"]::before {
|
|
566
|
+
opacity: 1; transform: none; transition: opacity var(--dur-travel-1) var(--ease-rise), transform var(--dur-travel-3) var(--ease-settle);
|
|
567
|
+
}
|
|
568
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger[aria-selected="true"]::after { opacity: 1; transition: opacity var(--dur-travel-2) var(--ease-rise) 60ms; }
|
|
569
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger:hover:not([aria-selected="true"])::before {
|
|
570
|
+
opacity: 1; transform: translateY(calc(5px * var(--alt-travel))); clip-path: inset(-8px -8px calc(1px + 5px * var(--alt-travel)) -8px);
|
|
571
|
+
background: color-mix(in oklab, var(--surface-raised) 50%, var(--surface-ground)); box-shadow: 0 0 0 1px color-mix(in oklab, var(--ink) 6%, transparent);
|
|
572
|
+
transition: opacity var(--dur-travel-1) var(--ease-rise), transform var(--dur-travel-2) var(--ease-settle);
|
|
573
|
+
}
|
|
574
|
+
.alt-tabs[data-variant="folder"] > .alt-tabs-content {
|
|
575
|
+
position: relative; z-index: 1; padding: var(--space-5); border-radius: var(--radius-lg);
|
|
576
|
+
background: var(--surface-raised); box-shadow: var(--elev-2); color: var(--ink);
|
|
577
|
+
animation: alt-sheet-surface var(--dur-travel-3) var(--ease-rise);
|
|
578
|
+
}
|
|
579
|
+
.alt-tabs[data-variant="folder"] > .alt-tabs-content > * { --alt-from-y: 3px; animation: alt-emerge var(--dur-travel-2) var(--ease-rise) 40ms backwards; }
|
|
580
|
+
@keyframes alt-sheet-surface { from { box-shadow: var(--elev-1); } }
|
|
581
|
+
|
|
582
|
+
/* ── Slider: trench track, accent fill, raised thumb that floats to level 3 while held. ── */
|
|
583
|
+
.alt-slider { position: relative; display: flex; align-items: center; height: 28px; touch-action: none; user-select: none; cursor: pointer; }
|
|
584
|
+
.alt-slider-track { position: relative; flex: 1; height: 8px; border-radius: var(--radius-full); background: var(--surface-trench); box-shadow: var(--trench); overflow: hidden; }
|
|
585
|
+
.alt-slider-fill { height: 100%; border-radius: inherit; background: var(--accent); box-shadow: var(--elev-1); transition: width var(--dur-travel-1) var(--ease-glide); }
|
|
586
|
+
.alt-slider-thumb {
|
|
587
|
+
position: absolute; top: 50%; width: 20px; height: 20px; translate: -50% -50%;
|
|
588
|
+
border: 2px solid var(--accent); border-radius: var(--radius-full); background: var(--surface-raised); background-image: var(--alt-sheen); box-shadow: var(--elev-1);
|
|
589
|
+
transition: left var(--dur-travel-1) var(--ease-glide), box-shadow var(--dur-travel-1) var(--ease-rise), transform var(--dur-travel-2) var(--ease-settle);
|
|
590
|
+
}
|
|
591
|
+
.alt-slider:hover .alt-slider-thumb { box-shadow: var(--elev-2); }
|
|
592
|
+
.alt-slider[data-dragging] .alt-slider-fill, .alt-slider[data-dragging] .alt-slider-thumb { transition-property: box-shadow, transform; }
|
|
593
|
+
.alt-slider[data-dragging] .alt-slider-thumb { box-shadow: var(--elev-3); transform: scale(calc(1 + 0.12 * var(--alt-travel))); cursor: grabbing; }
|
|
594
|
+
.alt-slider-bubble {
|
|
595
|
+
position: absolute; left: 50%; bottom: calc(100% + 10px); translate: -50% 0; min-width: 32px; padding: 3px 8px; text-align: center;
|
|
596
|
+
border-radius: var(--radius-sm); background: var(--surface-floating); box-shadow: var(--elev-1); color: var(--ink);
|
|
597
|
+
font: 500 12px/16px var(--font-mono); white-space: nowrap; pointer-events: none;
|
|
598
|
+
opacity: 0; transform: translateY(calc(4px * var(--alt-travel))) scale(calc(1 - 0.1 * var(--alt-travel))); transform-origin: 50% 100%;
|
|
599
|
+
transition: opacity var(--dur-travel-1) var(--ease-sink), transform var(--dur-travel-1) var(--ease-sink), box-shadow var(--dur-travel-1) var(--ease-sink);
|
|
600
|
+
}
|
|
601
|
+
.alt-slider[data-dragging] .alt-slider-bubble, .alt-slider-thumb:focus-visible .alt-slider-bubble {
|
|
602
|
+
opacity: 1; transform: none; box-shadow: var(--elev-3);
|
|
603
|
+
transition: opacity var(--dur-travel-3) var(--ease-rise), transform var(--dur-travel-3) var(--ease-rise), box-shadow var(--dur-travel-3) var(--ease-rise);
|
|
604
|
+
}
|
|
605
|
+
.alt-slider[data-disabled] { cursor: not-allowed; }
|
|
606
|
+
.alt-slider[data-disabled] .alt-slider-fill { background: var(--line-control); box-shadow: none; }
|
|
607
|
+
.alt-slider[data-disabled] .alt-slider-thumb { border-color: var(--line-control); box-shadow: var(--elev-0); }
|
|
608
|
+
|
|
609
|
+
/* ── Progress ── */
|
|
610
|
+
.alt-progress { position: relative; height: 8px; border-radius: var(--radius-full); background: var(--surface-trench); box-shadow: var(--trench); overflow: hidden; }
|
|
611
|
+
.alt-progress-fill { height: 100%; border-radius: inherit; background: var(--accent); box-shadow: var(--elev-1); transition: width var(--dur-travel-3) var(--ease-glide); }
|
|
612
|
+
.alt-progress[data-indeterminate] .alt-progress-fill { width: 32%; animation: alt-travel var(--dur-sweep) var(--ease-glide) infinite; }
|
|
613
|
+
|
|
614
|
+
/* ── Badge: an indicator plate. A label is part of the record, so a badge is a plate set flush into the page — a
|
|
615
|
+
shallow stamp with a dark top edge and a light lip below — and it never lifts. Status carries an indicator lamp:
|
|
616
|
+
a flat dot in its tone's own colour (the colour its text takes), with no gloss, socket or glow, so it reads as part
|
|
617
|
+
of the plate's printing rather than a bead sitting on it. A neutral lamp is unlit: an empty ring. When the status
|
|
618
|
+
changes the lamp relights; when the label changes the plate is re-stamped. A count is the exception: a number that
|
|
619
|
+
wants your attention floats above the page, and pops up when it changes. ── */
|
|
620
|
+
.alt-badge {
|
|
621
|
+
--b-bg: color-mix(in oklab, var(--surface-ground), var(--surface-well) 70%); --b-fg: var(--ink); --b-edge: var(--ink);
|
|
622
|
+
--b-lamp: var(--ink-muted); --b-tint: var(--surface-well); --b-ink: var(--ink-muted);
|
|
623
|
+
display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px; border-radius: var(--radius-sm);
|
|
624
|
+
background: var(--b-bg); color: var(--b-fg); font: 550 12px/1 var(--font-sans); letter-spacing: 0.005em; white-space: nowrap; vertical-align: middle;
|
|
625
|
+
box-shadow: inset 0 1px 1.5px color-mix(in oklab, var(--b-edge) 16%, transparent), inset 0 0 0 1px color-mix(in oklab, var(--b-edge) 9%, transparent), 0 1px 0 0 var(--alt-lip);
|
|
626
|
+
}
|
|
627
|
+
.alt-badge:has(> .alt-badge-lamp) { padding-left: 6px; }
|
|
628
|
+
.alt-badge[data-tone="accent"] { --b-lamp: var(--accent); --b-tint: var(--accent-soft); --b-ink: var(--accent-ink); }
|
|
629
|
+
.alt-badge[data-tone="positive"] { --b-lamp: var(--positive); --b-tint: var(--positive-soft); --b-ink: var(--positive); }
|
|
630
|
+
.alt-badge[data-tone="caution"] { --b-lamp: var(--caution); --b-tint: var(--caution-soft); --b-ink: var(--caution); }
|
|
631
|
+
.alt-badge[data-tone="critical"] { --b-lamp: var(--critical); --b-tint: var(--critical-soft); --b-ink: var(--critical); }
|
|
632
|
+
/* Without a lamp, a toned plate says its tone in its lettering. */
|
|
633
|
+
.alt-badge[data-variant="plate"]:not(:has(> .alt-badge-lamp)) { --b-fg: var(--b-ink); }
|
|
634
|
+
.alt-badge[data-variant="tinted"] { --b-bg: var(--b-tint); --b-fg: var(--b-ink); --b-edge: var(--b-ink); }
|
|
635
|
+
.alt-badge[data-variant="outline"] { --b-fg: var(--b-ink); background: transparent; box-shadow: inset 0 0 0 1px var(--line-control); }
|
|
636
|
+
.alt-badge-lamp { position: relative; flex: none; width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--b-lamp); }
|
|
637
|
+
.alt-badge[data-tone="neutral"] .alt-badge-lamp { background: transparent; box-shadow: inset 0 0 0 1.5px var(--b-lamp); }
|
|
638
|
+
.alt-badge-lamp[data-lit] { animation: alt-lamp-on var(--dur-travel-3) var(--ease-rise); }
|
|
639
|
+
.alt-badge-lamp[data-pulse] { animation: alt-lamp-pulse var(--dur-hover) ease-in-out infinite alternate; }
|
|
640
|
+
@keyframes alt-lamp-on { from { background-color: transparent; box-shadow: inset 0 0 0 1.5px var(--b-lamp); } }
|
|
641
|
+
@keyframes alt-lamp-pulse { to { opacity: 0.35; } }
|
|
642
|
+
.alt-badge[data-stamp="a"] { animation: alt-stamp-a var(--dur-travel-3) var(--ease-settle); }
|
|
643
|
+
.alt-badge[data-stamp="b"] { animation: alt-stamp-b var(--dur-travel-3) var(--ease-settle); }
|
|
644
|
+
@keyframes alt-stamp-a { from { transform: translateY(calc(-3px * var(--alt-travel))) scale(calc(1 + 0.05 * var(--alt-travel))); filter: drop-shadow(0 3px 3px rgb(0 0 0 / 0.16)); } }
|
|
645
|
+
@keyframes alt-stamp-b { from { transform: translateY(calc(-3px * var(--alt-travel))) scale(calc(1 + 0.05 * var(--alt-travel))); filter: drop-shadow(0 3px 3px rgb(0 0 0 / 0.16)); } }
|
|
646
|
+
.alt-badge[data-variant="count"] {
|
|
647
|
+
--b-bg: var(--surface-floating); --b-fg: var(--ink);
|
|
648
|
+
justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--radius-full);
|
|
649
|
+
font: 650 11.5px/1 var(--font-sans); font-variant-numeric: tabular-nums; box-shadow: var(--elev-2);
|
|
650
|
+
}
|
|
651
|
+
.alt-badge[data-variant="count"][data-tone="accent"] { --b-bg: var(--accent); --b-fg: var(--on-accent); }
|
|
652
|
+
.alt-badge[data-variant="count"][data-tone="critical"] { --b-bg: var(--critical); --b-fg: var(--on-critical); }
|
|
653
|
+
.alt-badge[data-variant="count"][data-tone="positive"], .alt-badge[data-variant="count"][data-tone="caution"] { --b-bg: var(--b-tint); --b-fg: var(--b-ink); }
|
|
654
|
+
.alt-badge[data-variant="count"][data-stamp="a"] { animation-name: alt-count-a; }
|
|
655
|
+
.alt-badge[data-variant="count"][data-stamp="b"] { animation-name: alt-count-b; }
|
|
656
|
+
@keyframes alt-count-a { from { transform: translateY(calc(3px * var(--alt-travel))) scale(calc(1 - 0.2 * var(--alt-travel))); box-shadow: var(--elev-0); } }
|
|
657
|
+
@keyframes alt-count-b { from { transform: translateY(calc(3px * var(--alt-travel))) scale(calc(1 - 0.2 * var(--alt-travel))); box-shadow: var(--elev-0); } }
|
|
658
|
+
@media (prefers-reduced-motion: reduce) { .alt-badge-lamp[data-pulse] { animation: none; } }
|
|
659
|
+
[data-motion="reduced"] .alt-badge-lamp[data-pulse] { animation: none; }
|
|
660
|
+
|
|
661
|
+
/* ── Avatar: presence as height, drawn the way the eye judges height above a floor: by the gap between a thing and
|
|
662
|
+
its shadow (Kersten, Mamassian & Knill 1997). Every face is a disc with a cast shadow on the ground beneath it.
|
|
663
|
+
Active people hover: the face lifts off and its shadow shrinks and fades. Idle people rest: a tight contact
|
|
664
|
+
shadow right under them. Offline people lie flat in the page, grey, with no shadow at all. Someone live
|
|
665
|
+
(speaking, typing, presenting) drifts gently up and down. --hr is the height as a fraction of the face. ── */
|
|
666
|
+
@property --hr { syntax: "<number>"; inherits: true; initial-value: 0; }
|
|
667
|
+
.alt-avatar {
|
|
668
|
+
--size: 36px; --hr: 0; --lift: calc(var(--size) * var(--hr) * var(--alt-travel));
|
|
669
|
+
position: relative; isolation: isolate; display: inline-grid; flex: none; width: var(--size); height: var(--size); vertical-align: middle;
|
|
670
|
+
transition: --hr var(--dur-travel-3) var(--ease-settle);
|
|
671
|
+
}
|
|
672
|
+
.alt-avatar-face {
|
|
673
|
+
position: relative; z-index: 1; display: grid; place-items: center; width: 100%; height: 100%; overflow: hidden; border-radius: var(--radius-full);
|
|
674
|
+
background-color: var(--surface-raised); background-image: radial-gradient(120% 90% at 50% 0%, rgb(255 255 255 / 0.2), transparent 60%);
|
|
675
|
+
box-shadow: inset 0 0 0 1px var(--alt-ring); color: var(--ink);
|
|
676
|
+
font: 600 calc(var(--size) * 0.36) / 1 var(--font-sans); letter-spacing: 0.01em; user-select: none;
|
|
677
|
+
transform: translateY(calc(-1 * var(--lift)));
|
|
678
|
+
transition: background-color var(--dur-travel-2), color var(--dur-travel-2), filter var(--dur-travel-2), box-shadow var(--dur-travel-2);
|
|
679
|
+
}
|
|
680
|
+
.alt-avatar-face img { width: 100%; height: 100%; object-fit: cover; }
|
|
681
|
+
/* The cast shadow. The higher the face, the smaller and fainter it gets — that gap is what reads as height. */
|
|
682
|
+
.alt-avatar-shadow {
|
|
683
|
+
position: absolute; left: 7%; right: 7%; top: 100%; height: calc(var(--size) * 0.2); margin-top: calc(var(--size) * -0.1);
|
|
684
|
+
border-radius: 50%; background: radial-gradient(closest-side, var(--alt-cast-deep), var(--alt-cast-deep) 25%, transparent); pointer-events: none;
|
|
685
|
+
scale: calc(1 - var(--hr) * 1.15); opacity: calc(1 - var(--hr) * 1.7);
|
|
686
|
+
}
|
|
687
|
+
.alt-avatar[data-tint="accent"] .alt-avatar-face { background-color: var(--accent-soft); }
|
|
688
|
+
.alt-avatar[data-tint="positive"] .alt-avatar-face { background-color: var(--positive-soft); }
|
|
689
|
+
.alt-avatar[data-tint="caution"] .alt-avatar-face { background-color: var(--caution-soft); }
|
|
690
|
+
.alt-avatar[data-tint="critical"] .alt-avatar-face { background-color: var(--critical-soft); }
|
|
691
|
+
.alt-avatar[data-status="active"] { --hr: 0.15; }
|
|
692
|
+
.alt-avatar[data-status="offline"] .alt-avatar-face, .alt-avatar[data-tint="more"] .alt-avatar-face {
|
|
693
|
+
background-color: var(--surface-well); background-image: none; color: var(--ink-muted); box-shadow: inset 0 0 0 1px var(--alt-ring), inset 0 1px 2px var(--alt-cast);
|
|
694
|
+
}
|
|
695
|
+
.alt-avatar[data-status="offline"] .alt-avatar-face { filter: grayscale(1); }
|
|
696
|
+
.alt-avatar[data-status="offline"] .alt-avatar-face img { opacity: 0.6; }
|
|
697
|
+
.alt-avatar[data-status="offline"] .alt-avatar-shadow, .alt-avatar[data-tint="more"] .alt-avatar-shadow { opacity: 0; }
|
|
698
|
+
.alt-avatar[data-tint="more"] .alt-avatar-face { font-size: calc(var(--size) * 0.32); }
|
|
699
|
+
.alt-avatar[data-live] { animation: alt-drift var(--dur-hover) ease-in-out infinite alternate; }
|
|
700
|
+
@keyframes alt-drift { from { --hr: 0.15; } to { --hr: 0.24; } }
|
|
701
|
+
@media (prefers-reduced-motion: reduce) { .alt-avatar[data-live] { animation: none; --hr: 0.2; } }
|
|
702
|
+
[data-motion="reduced"] .alt-avatar[data-live] { animation: none; --hr: 0.2; }
|
|
703
|
+
.alt-avatar[data-presence] .alt-avatar-face { outline: 2px solid var(--alt-presence); outline-offset: 1px; }
|
|
704
|
+
.alt-avatar-lamp {
|
|
705
|
+
--b-lamp: var(--positive);
|
|
706
|
+
position: absolute; z-index: 2; right: -1px; bottom: -1px; width: max(8px, calc(var(--size) * 0.24)); height: max(8px, calc(var(--size) * 0.24)); border-radius: var(--radius-full);
|
|
707
|
+
background: var(--b-lamp); box-shadow: 0 0 0 2px var(--surface-ground); transform: translateY(calc(-1 * var(--lift)));
|
|
708
|
+
}
|
|
709
|
+
.alt-avatar[data-status="idle"] .alt-avatar-lamp { --b-lamp: var(--caution); }
|
|
710
|
+
.alt-avatar[data-interactive]:hover, .alt-avatar[data-interactive]:focus-visible { --hr: 0.3; }
|
|
711
|
+
.alt-avatar[data-interactive] { cursor: pointer; outline: none; }
|
|
712
|
+
.alt-avatar[data-interactive]:focus-visible .alt-avatar-face { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
713
|
+
.alt-avatar-group { isolation: isolate; display: inline-flex; align-items: flex-end; padding: calc(var(--size, 36px) * 0.32) 0 calc(var(--size, 36px) * 0.1); }
|
|
714
|
+
.alt-avatar-group > .alt-avatar { isolation: auto; margin-left: calc(var(--size) * -0.22); }
|
|
715
|
+
.alt-avatar-group > .alt-avatar:first-child { margin-left: 0; }
|
|
716
|
+
/* Overlapping faces are cut out of each other with a ring of ground; higher faces sit in front. */
|
|
717
|
+
.alt-avatar-group > .alt-avatar .alt-avatar-face { box-shadow: 0 0 0 2px var(--surface-ground), inset 0 0 0 1px var(--alt-ring); }
|
|
718
|
+
.alt-avatar-group > .alt-avatar[data-status="offline"] .alt-avatar-face { box-shadow: 0 0 0 2px var(--surface-ground), inset 0 0 0 1px var(--alt-ring), inset 0 1px 2px var(--alt-cast); }
|
|
719
|
+
.alt-avatar-group > .alt-avatar[data-status="active"] .alt-avatar-face { z-index: 3; }
|
|
720
|
+
.alt-avatar-group > .alt-avatar[data-status="idle"] .alt-avatar-face { z-index: 2; }
|
|
721
|
+
.alt-avatar-group > .alt-avatar:not([data-tint="more"]):hover { --hr: 0.32; }
|
|
722
|
+
.alt-avatar-group > .alt-avatar:not([data-tint="more"]):hover .alt-avatar-face { z-index: 5; }
|
|
723
|
+
.alt-avatar-group .alt-avatar-lamp { display: none; }
|
|
724
|
+
|
|
725
|
+
/* ── Skeleton: an imprint of the content to come, pressed into the page. Light passes over it while it waits; when the
|
|
726
|
+
content lands it rises out of its imprint and the imprint fills in behind it. ── */
|
|
727
|
+
.alt-skeleton { position: relative; overflow: hidden; border-radius: var(--radius-sm); background: var(--surface-well); box-shadow: var(--well); }
|
|
728
|
+
.alt-skeleton[data-shape="circle"] { border-radius: var(--radius-full); }
|
|
729
|
+
.alt-skeleton[data-shape="text"] { border-radius: var(--radius-xs); }
|
|
730
|
+
.alt-skeleton::after {
|
|
731
|
+
content: ""; position: absolute; inset: 0; transform: translateX(-100%);
|
|
732
|
+
background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--surface-raised) 60%, transparent), transparent);
|
|
733
|
+
animation: alt-sweep var(--dur-sweep) var(--ease-glide) calc(var(--i, 0) * 90ms) infinite;
|
|
734
|
+
}
|
|
735
|
+
.alt-skeleton-lines { display: flex; flex-direction: column; gap: 9px; }
|
|
736
|
+
@media (prefers-reduced-motion: reduce) { .alt-skeleton::after { animation: none; opacity: 0; } }
|
|
737
|
+
[data-motion="reduced"] .alt-skeleton::after { animation: none; opacity: 0; }
|
|
738
|
+
.alt-reveal[data-reveal] { border-radius: var(--radius-sm); animation: alt-imprint var(--dur-travel-3) linear var(--alt-rise-delay, 0ms) backwards; }
|
|
739
|
+
.alt-reveal[data-reveal] > .alt-reveal-inner { animation: alt-rise-out var(--dur-travel-3) var(--ease-rise) var(--alt-rise-delay, 0ms) backwards; }
|
|
740
|
+
@keyframes alt-imprint {
|
|
741
|
+
from { clip-path: inset(0 round var(--radius-sm)); background-color: var(--surface-well); box-shadow: var(--well); }
|
|
742
|
+
to { clip-path: inset(0 round var(--radius-sm)); background-color: transparent; box-shadow: var(--elev-0); }
|
|
743
|
+
}
|
|
744
|
+
@keyframes alt-rise-out { from { transform: translateY(calc(100% * var(--alt-travel))); opacity: 0.25; } }
|
|
745
|
+
|
|
746
|
+
/* ── Alert: a sheet laid on the page. Status that informs is a thin tinted sheet resting on the ground — you can see
|
|
747
|
+
its paper edge and the contact shadow under it — and it never floats. Status that asks you to act is a raised
|
|
748
|
+
card. Dismissing lifts the sheet off the page and the gap closes behind it. Several alerts make an AlertStack:
|
|
749
|
+
one sheet on top and the rest peeking out beneath it, each tinted by its own tone, with a count; open the stack
|
|
750
|
+
and they fan out. Shadow list: [ring, paper edge, contact, lift]. ── */
|
|
751
|
+
.alt-alert, .alt-alert-sheet { --a-bg: var(--surface-raised); --a-fg: var(--ink-muted); }
|
|
752
|
+
.alt-alert[data-tone="accent"], .alt-alert-sheet[data-tone="accent"] { --a-bg: var(--accent-soft); --a-fg: var(--accent-ink); }
|
|
753
|
+
.alt-alert[data-tone="positive"], .alt-alert-sheet[data-tone="positive"] { --a-bg: var(--positive-soft); --a-fg: var(--positive); }
|
|
754
|
+
.alt-alert[data-tone="caution"], .alt-alert-sheet[data-tone="caution"] { --a-bg: var(--caution-soft); --a-fg: var(--caution); }
|
|
755
|
+
.alt-alert[data-tone="critical"], .alt-alert-sheet[data-tone="critical"] { --a-bg: var(--critical-soft); --a-fg: var(--critical); }
|
|
756
|
+
.alt-alert {
|
|
757
|
+
--a-sheet: 0 0 0 1px color-mix(in oklab, var(--a-fg) 18%, transparent), 0 1px 0 0 color-mix(in oklab, var(--a-bg), #000 10%), 0 1.5px 3px -0.5px var(--alt-cast);
|
|
758
|
+
display: grid; grid-template-rows: 1fr; border-radius: var(--radius-md); background: var(--a-bg); color: var(--ink);
|
|
759
|
+
box-shadow: var(--a-sheet), 0 0 0 0 transparent;
|
|
760
|
+
transition: grid-template-rows var(--dur-travel-3) var(--ease-glide) var(--dur-travel-1), opacity var(--dur-travel-2) var(--ease-sink) var(--dur-travel-1),
|
|
761
|
+
box-shadow var(--dur-travel-2) var(--ease-rise), transform var(--dur-travel-2) var(--ease-rise);
|
|
762
|
+
}
|
|
763
|
+
.alt-alert[data-variant="raised"] { --a-bg: var(--surface-raised); background-image: var(--alt-sheen); box-shadow: var(--elev-2); }
|
|
764
|
+
/* Lifted off: the sheet rises and its shadow spreads, then it fades and the space closes. */
|
|
765
|
+
.alt-alert[data-closing] {
|
|
766
|
+
grid-template-rows: 0fr; opacity: 0; transform: translateY(calc(-8px * var(--alt-travel))) scale(calc(1 + 0.01 * var(--alt-travel)));
|
|
767
|
+
box-shadow: var(--a-sheet), 0 14px 22px -10px var(--alt-cast);
|
|
768
|
+
}
|
|
769
|
+
.alt-alert[data-variant="raised"][data-closing] { box-shadow: var(--elev-4); }
|
|
770
|
+
.alt-alert-inner { min-height: 0; overflow: hidden; display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-3) var(--space-4); }
|
|
771
|
+
.alt-alert-icon { display: inline-flex; flex: none; margin-top: 1px; color: var(--a-fg); }
|
|
772
|
+
.alt-alert[data-variant="raised"][data-tone="accent"] .alt-alert-icon { color: var(--accent-ink); }
|
|
773
|
+
.alt-alert[data-variant="raised"][data-tone="positive"] .alt-alert-icon { color: var(--positive); }
|
|
774
|
+
.alt-alert[data-variant="raised"][data-tone="caution"] .alt-alert-icon { color: var(--caution); }
|
|
775
|
+
.alt-alert[data-variant="raised"][data-tone="critical"] .alt-alert-icon { color: var(--critical); }
|
|
776
|
+
.alt-alert-body { flex: 1; min-width: 0; }
|
|
777
|
+
.alt-alert-title { margin: 0; font: 600 14px/20px var(--font-sans); }
|
|
778
|
+
.alt-alert-text { font: 400 14px/20px var(--font-sans); color: var(--ink); }
|
|
779
|
+
.alt-alert-title + .alt-alert-text { margin-top: 2px; }
|
|
780
|
+
.alt-alert-action { flex: none; align-self: center; }
|
|
781
|
+
.alt-alert-close {
|
|
782
|
+
flex: none; width: 24px; height: 24px; margin: -2px -6px 0 0; display: grid; place-items: center; padding: 0; border: 0; border-radius: var(--radius-xs);
|
|
783
|
+
background: none; color: var(--ink-muted); cursor: pointer; transition: background-color var(--dur-travel-1), color var(--dur-travel-1);
|
|
784
|
+
}
|
|
785
|
+
.alt-alert-close:hover { background: color-mix(in oklab, var(--ink) 8%, transparent); color: var(--ink); }
|
|
786
|
+
.alt-alert-close:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
787
|
+
|
|
788
|
+
.alt-alert-stack { position: relative; display: grid; gap: var(--space-2); }
|
|
789
|
+
.alt-alert-stack[data-sheets="1"] { --sheets: 1; } .alt-alert-stack[data-sheets="2"] { --sheets: 2; }
|
|
790
|
+
.alt-alert-stack:not([data-expanded]) { padding-bottom: calc(var(--sheets, 0) * 6px); margin-bottom: 12px; }
|
|
791
|
+
.alt-alert-stack-top { position: relative; z-index: 3; }
|
|
792
|
+
.alt-alert-stack-top[data-risen] { animation: alt-from-under var(--dur-travel-3) var(--ease-rise); }
|
|
793
|
+
/* In a stack the top sheet lifts off without closing its space: the next one comes up from under it. */
|
|
794
|
+
.alt-alert-stack-top > .alt-alert[data-closing] { grid-template-rows: 1fr; }
|
|
795
|
+
.alt-alert-sheet {
|
|
796
|
+
position: absolute; z-index: calc(3 - var(--i)); top: calc(var(--i) * 6px); bottom: calc(var(--sheets) * 6px - var(--i) * 6px); left: calc(var(--i) * 10px); right: calc(var(--i) * 10px);
|
|
797
|
+
border-radius: var(--radius-md); background: var(--a-bg); pointer-events: none;
|
|
798
|
+
box-shadow: 0 0 0 1px color-mix(in oklab, var(--a-fg) 16%, transparent), 0 1px 0 0 color-mix(in oklab, var(--a-bg), #000 10%), 0 1.5px 3px -0.5px var(--alt-cast);
|
|
799
|
+
filter: brightness(calc(1 - var(--i) * 0.025));
|
|
800
|
+
animation: alt-tuck var(--dur-travel-3) var(--ease-settle) backwards;
|
|
801
|
+
}
|
|
802
|
+
@keyframes alt-tuck { from { transform: translateY(calc(var(--i) * -6px)); } }
|
|
803
|
+
.alt-alert-more {
|
|
804
|
+
position: absolute; z-index: 4; right: var(--space-4); bottom: -11px; height: 22px; padding: 0 10px; border: 0; border-radius: var(--radius-full);
|
|
805
|
+
background: var(--surface-floating); color: var(--ink); box-shadow: var(--elev-2); font: 600 12px/1 var(--font-sans); cursor: pointer;
|
|
806
|
+
transition: box-shadow var(--dur-travel-1) var(--ease-rise), transform var(--dur-travel-2) var(--ease-settle);
|
|
807
|
+
}
|
|
808
|
+
.alt-alert-more:hover { box-shadow: var(--elev-3); transform: translateY(calc(-1px * var(--alt-travel))); }
|
|
809
|
+
.alt-alert-more:active { box-shadow: var(--elev-1); transform: none; transition-duration: var(--dur-press); }
|
|
810
|
+
.alt-alert-more:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
811
|
+
.alt-alert-stack[data-expanded] .alt-alert-more { position: static; justify-self: end; height: 26px; background: none; color: var(--ink-muted); box-shadow: none; transform: none; }
|
|
812
|
+
.alt-alert-stack[data-expanded] .alt-alert-more:hover { color: var(--ink); background: color-mix(in oklab, var(--ink) 6%, transparent); }
|
|
813
|
+
.alt-alert-stack-item { animation: alt-fan var(--dur-travel-3) var(--ease-settle) calc(var(--i) * 30ms) backwards; }
|
|
814
|
+
.alt-alert-stack-item:first-child { animation: none; }
|
|
815
|
+
@keyframes alt-fan { from { opacity: 0; transform: translateY(calc(var(--i) * -12px * var(--alt-travel))) scale(calc(1 - 0.02 * var(--alt-travel))); } }
|
|
816
|
+
|
|
817
|
+
/* ── Accordion: closed items are lids lying flush on the page. Opening one lifts its lid into a raised card and
|
|
818
|
+
opens the compartment underneath, an opening sunk into the lid (with its back wall showing) where the content
|
|
819
|
+
sits. Hovering a closed row raises a ghost of its lid. ── */
|
|
820
|
+
.alt-acc { display: flex; flex-direction: column; }
|
|
821
|
+
.alt-acc-item {
|
|
822
|
+
position: relative; border-radius: var(--radius-lg); background: transparent; box-shadow: var(--elev-0);
|
|
823
|
+
transition: background-color var(--dur-travel-3) var(--ease-rise), box-shadow var(--dur-travel-3) var(--ease-rise), margin var(--dur-travel-3) var(--ease-glide);
|
|
824
|
+
}
|
|
825
|
+
.alt-acc-item + .alt-acc-item::before {
|
|
826
|
+
content: ""; position: absolute; top: 0; left: var(--space-4); right: var(--space-4); height: 1px; background: var(--line);
|
|
827
|
+
transition: opacity var(--dur-travel-1) var(--ease-rise);
|
|
828
|
+
}
|
|
829
|
+
.alt-acc-item[data-state="open"] { background: var(--surface-raised); box-shadow: var(--elev-2); margin: var(--space-2) 0; }
|
|
830
|
+
.alt-acc-item[data-state="open"]:first-child { margin-top: 0; }
|
|
831
|
+
.alt-acc-item[data-state="open"]:last-child { margin-bottom: 0; }
|
|
832
|
+
.alt-acc-item[data-state="open"]::before, .alt-acc-item[data-state="open"] + .alt-acc-item::before,
|
|
833
|
+
.alt-acc-item:has(> .alt-acc-heading .alt-acc-trigger:hover)::before, .alt-acc-item:has(> .alt-acc-heading .alt-acc-trigger:hover) + .alt-acc-item::before { opacity: 0; }
|
|
834
|
+
.alt-acc-heading { margin: 0; }
|
|
835
|
+
.alt-acc-trigger {
|
|
836
|
+
display: flex; width: 100%; align-items: center; justify-content: space-between; gap: var(--space-3);
|
|
837
|
+
padding: var(--space-4); border: 0; border-radius: inherit; background: none; color: var(--ink);
|
|
838
|
+
font: 500 15px/22px var(--font-sans); text-align: left; cursor: pointer;
|
|
839
|
+
transition: background-color var(--dur-travel-1) var(--ease-rise), box-shadow var(--dur-travel-1) var(--ease-rise);
|
|
840
|
+
}
|
|
841
|
+
.alt-acc-item[data-state="closed"] .alt-acc-trigger:hover {
|
|
842
|
+
background: color-mix(in oklab, var(--surface-raised) 55%, transparent); box-shadow: 0 0 0 1px color-mix(in oklab, var(--ink) 5%, transparent), 0 1px 2px var(--alt-cast);
|
|
843
|
+
}
|
|
844
|
+
.alt-acc-chevron { flex: none; color: var(--ink-muted); transition: transform var(--dur-travel-3) var(--ease-settle); }
|
|
845
|
+
.alt-acc-trigger:hover .alt-acc-chevron { transform: translateY(calc(2px * var(--alt-travel))); }
|
|
846
|
+
.alt-acc-item[data-state="open"] .alt-acc-chevron { transform: rotate(180deg); }
|
|
847
|
+
.alt-acc-panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--dur-travel-3) var(--ease-glide); }
|
|
848
|
+
.alt-acc-item[data-state="open"] .alt-acc-panel { grid-template-rows: 1fr; }
|
|
849
|
+
.alt-acc-panel > div { overflow: hidden; }
|
|
850
|
+
/* The compartment: content sits in an opening under the lid, its back wall just visible below the rim. */
|
|
851
|
+
.alt-acc-content {
|
|
852
|
+
margin: 0 var(--space-1) var(--space-1); padding: calc(var(--space-3) + 2px) var(--space-4) var(--space-3);
|
|
853
|
+
border-radius: calc(var(--radius-lg) - var(--space-1)); background: var(--surface-well);
|
|
854
|
+
box-shadow: inset 0 0 0 1px var(--line), inset 0 2px 0 0 var(--alt-wall-in), inset 0 4px 3px -2px var(--alt-cast);
|
|
855
|
+
font: 400 14px/21px var(--font-sans); color: var(--ink-muted);
|
|
856
|
+
opacity: 0; transform: translateY(calc(-4px * var(--alt-travel))); transition: opacity var(--dur-travel-1) var(--ease-sink), transform var(--dur-travel-1) var(--ease-sink);
|
|
857
|
+
}
|
|
858
|
+
.alt-acc-item[data-state="open"] .alt-acc-content { opacity: 1; transform: none; transition: opacity var(--dur-travel-3) var(--ease-rise) 60ms, transform var(--dur-travel-3) var(--ease-rise) 60ms; }
|
|
859
|
+
|
|
860
|
+
/* ── Kbd: a tiny raised key that presses when its key is held. ── */
|
|
861
|
+
.alt-kbd {
|
|
862
|
+
display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 6px; margin: 0 1px 2px;
|
|
863
|
+
border-radius: var(--radius-xs); background: var(--surface-raised); background-image: var(--alt-sheen); color: var(--ink-muted);
|
|
864
|
+
box-shadow: 0 var(--wall-1) 0 0 var(--surface-trench), var(--elev-1);
|
|
865
|
+
font: 500 12px/1 var(--font-mono); vertical-align: middle;
|
|
866
|
+
transition: box-shadow var(--dur-travel-1) var(--ease-settle), transform var(--dur-travel-1) var(--ease-settle), background-color var(--dur-travel-1);
|
|
867
|
+
}
|
|
868
|
+
.alt-kbd[data-pressed] { background: var(--surface-well); background-image: none; box-shadow: 0 0 0 0 var(--surface-trench), var(--elev-0); transform: translateY(var(--wall-1)); transition-duration: var(--dur-press); color: var(--ink); }
|
|
869
|
+
|
|
870
|
+
/* ── Floating layer: tooltip, popover, menu. Closed pose = one level up and near the anchor; open = level 3. ── */
|
|
871
|
+
.alt-tip-anchor, .alt-pop-anchor { position: relative; display: inline-flex; }
|
|
872
|
+
.alt-tip, .alt-pop {
|
|
873
|
+
position: absolute; z-index: var(--z-floating); color: var(--ink);
|
|
874
|
+
transition: opacity var(--dur-travel-3) var(--ease-rise), transform var(--dur-travel-3) var(--ease-rise), box-shadow var(--dur-travel-3) var(--ease-rise);
|
|
875
|
+
}
|
|
876
|
+
.alt-tip[data-state="closed"], .alt-pop[data-state="closed"] {
|
|
877
|
+
opacity: 0; box-shadow: var(--elev-1);
|
|
878
|
+
transition-timing-function: var(--ease-sink); transition-duration: calc(var(--dur-travel-3) * 0.7);
|
|
879
|
+
}
|
|
880
|
+
.alt-tip {
|
|
881
|
+
left: 50%; bottom: calc(100% + 8px); translate: -50% 0; transform-origin: 50% 100%;
|
|
882
|
+
padding: 5px 10px; border-radius: var(--radius-sm); background: var(--surface-floating); box-shadow: var(--elev-3);
|
|
883
|
+
font: 500 12.5px/17px var(--font-sans); white-space: nowrap; pointer-events: none;
|
|
884
|
+
}
|
|
885
|
+
.alt-tip[data-side="bottom"] { bottom: auto; top: calc(100% + 8px); transform-origin: 50% 0; }
|
|
886
|
+
.alt-tip[data-state="closed"] { transform: translateY(calc(4px * var(--alt-travel))) scale(calc(1 - 0.04 * var(--alt-travel))); }
|
|
887
|
+
.alt-tip[data-side="bottom"][data-state="closed"] { transform: translateY(calc(-4px * var(--alt-travel))) scale(calc(1 - 0.04 * var(--alt-travel))); }
|
|
888
|
+
.alt-tip[data-warm] { transition-duration: var(--dur-travel-1); }
|
|
889
|
+
|
|
890
|
+
.alt-pop {
|
|
891
|
+
top: calc(100% + 8px); left: 0; transform-origin: 0 0; min-width: 220px; padding: var(--space-4);
|
|
892
|
+
border-radius: var(--radius-lg); background: var(--surface-floating); box-shadow: var(--elev-3); outline: none;
|
|
893
|
+
}
|
|
894
|
+
.alt-pop[data-align="end"] { left: auto; right: 0; transform-origin: 100% 0; }
|
|
895
|
+
.alt-pop[data-align="center"] { left: 50%; translate: -50% 0; transform-origin: 50% 0; }
|
|
896
|
+
.alt-pop[data-side="top"] { top: auto; bottom: calc(100% + 8px); transform-origin: 0 100%; }
|
|
897
|
+
.alt-pop[data-side="top"][data-align="end"] { transform-origin: 100% 100%; }
|
|
898
|
+
.alt-pop[data-state="closed"] { transform: translateY(calc(-6px * var(--alt-travel))) scale(calc(1 - 0.04 * var(--alt-travel))); }
|
|
899
|
+
.alt-pop[data-side="top"][data-state="closed"] { transform: translateY(calc(6px * var(--alt-travel))) scale(calc(1 - 0.04 * var(--alt-travel))); }
|
|
900
|
+
|
|
901
|
+
.alt-menu { padding: var(--space-1); min-width: 228px; }
|
|
902
|
+
.alt-menu-hl {
|
|
903
|
+
position: absolute; top: 0; left: var(--space-1); right: var(--space-1); border-radius: var(--radius-sm); background: var(--accent-soft);
|
|
904
|
+
pointer-events: none; transition: transform var(--dur-travel-2) var(--ease-settle), height var(--dur-travel-2) var(--ease-settle), opacity var(--dur-travel-1), background-color var(--dur-travel-1);
|
|
905
|
+
}
|
|
906
|
+
.alt-menu-hl[data-tone="critical"] { background: var(--critical-soft); }
|
|
907
|
+
.alt-menu-item, .alt-menu-label {
|
|
908
|
+
position: relative; display: flex; align-items: center; gap: 10px; min-height: 34px; padding: 0 10px; border-radius: var(--radius-sm);
|
|
909
|
+
font: 500 14px/20px var(--font-sans); color: var(--ink); cursor: pointer; user-select: none;
|
|
910
|
+
opacity: 0; transform: translateY(calc(-3px * var(--alt-travel)));
|
|
911
|
+
transition: opacity var(--dur-travel-2) var(--ease-rise), transform var(--dur-travel-2) var(--ease-rise);
|
|
912
|
+
}
|
|
913
|
+
.alt-menu[data-state="open"] .alt-menu-item, .alt-menu[data-state="open"] .alt-menu-label { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * 16ms); }
|
|
914
|
+
.alt-menu-label { min-height: 28px; font-size: 12.5px; color: var(--ink-muted); cursor: default; }
|
|
915
|
+
.alt-menu-item[data-tone="critical"] { color: var(--critical); }
|
|
916
|
+
.alt-menu-item[aria-disabled] { color: var(--ink-faint); cursor: not-allowed; }
|
|
917
|
+
.alt-menu-icon { display: inline-flex; color: var(--ink-muted); }
|
|
918
|
+
.alt-menu-item[data-tone="critical"] .alt-menu-icon { color: inherit; }
|
|
919
|
+
.alt-menu-text { flex: 1; }
|
|
920
|
+
.alt-menu-shortcut { font: 400 12px/1 var(--font-mono); color: var(--ink-muted); }
|
|
921
|
+
.alt-menu-sep { height: 1px; margin: var(--space-1) 6px; background: var(--line); }
|
|
922
|
+
|
|
923
|
+
/* ── Dialog: level 5. The page recedes, the scrim veils it, the dialog rises with its shadow growing. ── */
|
|
924
|
+
.alt-dialog-root { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center; padding: var(--space-6); }
|
|
925
|
+
.alt-scrim {
|
|
926
|
+
position: absolute; inset: 0; background: var(--scrim); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
|
|
927
|
+
transition: opacity var(--dur-travel-5) var(--ease-rise);
|
|
928
|
+
}
|
|
929
|
+
.alt-dialog {
|
|
930
|
+
position: relative; width: min(100%, 460px); max-height: calc(100vh - 48px); overflow: auto; outline: none;
|
|
931
|
+
padding: var(--space-6); border-radius: var(--radius-xl); background: var(--surface-modal); box-shadow: var(--elev-5); color: var(--ink);
|
|
932
|
+
transition: opacity var(--dur-travel-5) var(--ease-rise), transform var(--dur-travel-5) var(--ease-rise), box-shadow var(--dur-travel-5) var(--ease-rise);
|
|
933
|
+
}
|
|
934
|
+
.alt-dialog[data-size="sm"] { width: min(100%, 380px); }
|
|
935
|
+
.alt-dialog[data-size="lg"] { width: min(100%, 620px); }
|
|
936
|
+
.alt-dialog-root[data-state="closed"] .alt-scrim { opacity: 0; transition-duration: calc(var(--dur-travel-5) * 0.7); transition-timing-function: var(--ease-sink); }
|
|
937
|
+
.alt-dialog-root[data-state="closed"] .alt-dialog {
|
|
938
|
+
opacity: 0; box-shadow: var(--elev-1); transform: translateY(calc(16px * var(--alt-travel))) scale(calc(1 - 0.04 * var(--alt-travel)));
|
|
939
|
+
transition-duration: calc(var(--dur-travel-5) * 0.7); transition-timing-function: var(--ease-sink);
|
|
940
|
+
}
|
|
941
|
+
.alt-dialog-head { display: flex; flex-direction: column; gap: 6px; padding-right: var(--space-8); }
|
|
942
|
+
.alt-dialog-title { margin: 0; font: 600 19px/26px var(--font-sans); letter-spacing: -0.01em; }
|
|
943
|
+
.alt-dialog-desc { margin: 0; font: 400 14px/21px var(--font-sans); color: var(--ink-muted); }
|
|
944
|
+
.alt-dialog-body { margin-top: var(--space-5); font: 400 15px/23px var(--font-sans); }
|
|
945
|
+
.alt-dialog-footer { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-6); }
|
|
946
|
+
.alt-dialog-close { position: absolute; top: var(--space-4); right: var(--space-4); color: var(--ink-muted); }
|
|
947
|
+
|
|
948
|
+
/* ── Toast: the stack is a depth stack. Newest in front at level 4; older ones sink behind it. ── */
|
|
949
|
+
.alt-toaster {
|
|
950
|
+
position: fixed; z-index: var(--z-toast); right: var(--space-6); bottom: var(--space-6); width: min(360px, calc(100vw - 32px));
|
|
951
|
+
transition: height var(--dur-travel-4) var(--ease-rise);
|
|
952
|
+
}
|
|
953
|
+
.alt-toast {
|
|
954
|
+
position: absolute; right: 0; bottom: 0; width: 100%; display: flex; align-items: flex-start; gap: var(--space-3);
|
|
955
|
+
padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4); border-radius: var(--radius-lg);
|
|
956
|
+
background: var(--surface-overlay); color: var(--ink); transform-origin: 50% 100%; overflow: hidden;
|
|
957
|
+
transition: transform var(--dur-travel-4) var(--ease-rise), opacity var(--dur-travel-4) var(--ease-rise), box-shadow var(--dur-travel-4) var(--ease-rise), height var(--dur-travel-4) var(--ease-rise);
|
|
958
|
+
}
|
|
959
|
+
.alt-toast[data-behind] > * { opacity: 0; transition: opacity var(--dur-travel-1); }
|
|
960
|
+
.alt-toast > * { transition: opacity var(--dur-travel-2) var(--ease-rise); }
|
|
961
|
+
.alt-toast-icon { display: inline-flex; margin-top: 1px; color: var(--ink-muted); flex: none; }
|
|
962
|
+
.alt-toast[data-tone="positive"] .alt-toast-icon { color: var(--positive); }
|
|
963
|
+
.alt-toast[data-tone="caution"] .alt-toast-icon { color: var(--caution); }
|
|
964
|
+
.alt-toast[data-tone="critical"] .alt-toast-icon { color: var(--critical); }
|
|
965
|
+
.alt-toast-body { flex: 1; min-width: 0; }
|
|
966
|
+
.alt-toast-title { margin: 0; font: 600 14px/20px var(--font-sans); }
|
|
967
|
+
.alt-toast-desc { margin: 2px 0 0; font: 400 13px/18px var(--font-sans); color: var(--ink-muted); }
|
|
968
|
+
.alt-toast-action { align-self: center; }
|
|
969
|
+
.alt-toast-close {
|
|
970
|
+
display: grid; place-items: center; width: 24px; height: 24px; margin: -2px -2px 0 0; padding: 0; flex: none; border: 0; border-radius: var(--radius-xs);
|
|
971
|
+
background: none; color: var(--ink-muted); cursor: pointer; transition: background-color var(--dur-travel-1), color var(--dur-travel-1);
|
|
972
|
+
}
|
|
973
|
+
.alt-toast-close:hover { background: var(--surface-well); color: var(--ink); }
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
/* ════════════════════ Depth signals: what height can tell you ════════════════════ */
|
|
977
|
+
|
|
978
|
+
/* Afterglow (recency). New or changed content lifts, tints and settles over dur-settle.
|
|
979
|
+
Drawn on ::before behind the content so the surface's own hover and press stay free. */
|
|
980
|
+
[data-settle] { position: relative; isolation: isolate; }
|
|
981
|
+
[data-settle]::before {
|
|
982
|
+
content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
|
|
983
|
+
animation: alt-afterglow-a var(--dur-settle) linear var(--alt-rise-delay, 0ms) both;
|
|
984
|
+
}
|
|
985
|
+
[data-settle="b"]::before { animation-name: alt-afterglow-b; }
|
|
986
|
+
@keyframes alt-afterglow-a { 0%, 12% { background-color: var(--accent-soft); box-shadow: var(--elev-2); animation-timing-function: var(--ease-decay); } 100% { background-color: transparent; box-shadow: var(--elev-0); } }
|
|
987
|
+
@keyframes alt-afterglow-b { 0%, 12% { background-color: var(--accent-soft); box-shadow: var(--elev-2); animation-timing-function: var(--ease-decay); } 100% { background-color: transparent; box-shadow: var(--elev-0); } }
|
|
988
|
+
|
|
989
|
+
/* Commitment. Pending writes hover above the ground (only after dur-grace, so fast saves never flicker);
|
|
990
|
+
committed ones land; failed ones drop into a trench. */
|
|
991
|
+
[data-status="pending"] { cursor: progress; animation: alt-hover var(--dur-hover) ease-in-out var(--dur-grace) infinite alternate both; }
|
|
992
|
+
@keyframes alt-hover {
|
|
993
|
+
from { box-shadow: var(--elev-2); transform: translateY(calc(-2px * var(--alt-travel))); }
|
|
994
|
+
to { box-shadow: var(--elev-3); transform: translateY(calc(-4px * var(--alt-travel))); }
|
|
995
|
+
}
|
|
996
|
+
@media (prefers-reduced-motion: reduce) { [data-status="pending"] { animation: none; box-shadow: var(--elev-2); transition: box-shadow var(--dur-travel-1) var(--ease-rise) var(--dur-grace); } }
|
|
997
|
+
[data-motion="reduced"] [data-status="pending"] { animation: none; box-shadow: var(--elev-2); transition: box-shadow var(--dur-travel-1) var(--ease-rise) var(--dur-grace); }
|
|
998
|
+
[data-land="a"] { animation: alt-land-a calc(var(--dur-travel-3) * 1.6) var(--ease-settle); }
|
|
999
|
+
[data-land="b"] { animation: alt-land-b calc(var(--dur-travel-3) * 1.6) var(--ease-settle); }
|
|
1000
|
+
@keyframes alt-land-a { from { box-shadow: var(--elev-3); transform: translateY(calc(-4px * var(--alt-travel))); } }
|
|
1001
|
+
@keyframes alt-land-b { from { box-shadow: var(--elev-3); transform: translateY(calc(-4px * var(--alt-travel))); } }
|
|
1002
|
+
.alt-surface[data-status="failed"], .alt-card[data-status="failed"], [data-status="failed"] {
|
|
1003
|
+
background: var(--critical-soft); box-shadow: var(--trench); outline: 1px solid var(--critical); outline-offset: -1px;
|
|
1004
|
+
animation: alt-drop var(--dur-travel-2) var(--ease-sink);
|
|
1005
|
+
}
|
|
1006
|
+
@keyframes alt-drop { from { box-shadow: var(--elev-1); transform: translateY(calc(-2px * var(--alt-travel))); } }
|
|
1007
|
+
|
|
1008
|
+
/* Possession. Something being held (by you or a collaborator) is in a hand: level 3, slightly tilted. */
|
|
1009
|
+
[data-presence="1"] { --alt-presence: var(--presence-1); }
|
|
1010
|
+
[data-presence="2"] { --alt-presence: var(--presence-2); }
|
|
1011
|
+
[data-presence="3"] { --alt-presence: var(--presence-3); }
|
|
1012
|
+
[data-held] {
|
|
1013
|
+
position: relative; z-index: 2; box-shadow: var(--elev-3);
|
|
1014
|
+
transform: translateY(calc(-2px * var(--alt-travel))) rotate(calc(-0.5deg * var(--alt-travel)));
|
|
1015
|
+
transition: box-shadow var(--dur-travel-3) var(--ease-rise), transform var(--dur-travel-3) var(--ease-rise);
|
|
1016
|
+
}
|
|
1017
|
+
[data-held-by] { outline: 2px solid var(--alt-presence); outline-offset: 2px; }
|
|
1018
|
+
[data-held-by]::after {
|
|
1019
|
+
content: attr(data-held-by); position: absolute; top: -12px; left: 14px; padding: 1px 7px; border-radius: var(--radius-xs);
|
|
1020
|
+
background: var(--alt-presence); color: var(--on-presence); box-shadow: var(--elev-1);
|
|
1021
|
+
font: 600 11.5px/16px var(--font-sans); white-space: nowrap; pointer-events: none;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/* Relevance (focus+context). Matches rise one level, misses sink into a well. Nothing is removed,
|
|
1025
|
+
so positions — and the person's spatial memory of them — survive the filter. No blur: small blur
|
|
1026
|
+
isn't detected pre-attentively and blurred text is unpleasant to read; shading polarity is. */
|
|
1027
|
+
[data-relevance] {
|
|
1028
|
+
transition: background-color var(--dur-travel-2) var(--ease-rise), box-shadow var(--dur-travel-2) var(--ease-rise),
|
|
1029
|
+
transform var(--dur-travel-2) var(--ease-settle), color var(--dur-travel-2) var(--ease-rise), filter var(--dur-travel-2);
|
|
1030
|
+
}
|
|
1031
|
+
[data-relevance="match"] { background: var(--alt-bg-up, var(--surface-lifted)); box-shadow: var(--alt-sh-up, var(--elev-2)); transform: translateY(calc(-1px * var(--alt-travel))); }
|
|
1032
|
+
[data-relevance="miss"] { background: var(--surface-well); box-shadow: var(--well); color: var(--ink-muted); filter: saturate(0.5); }
|
|
1033
|
+
|
|
1034
|
+
/* ── HoldButton: holding pushes it through the ground; the fuse along the bottom shows how far. ── */
|
|
1035
|
+
.alt-hold { overflow: visible; }
|
|
1036
|
+
.alt-hold .alt-btn-label { position: static; }
|
|
1037
|
+
.alt-hold-text { position: relative; }
|
|
1038
|
+
.alt-hold-fill {
|
|
1039
|
+
position: absolute; left: 8px; right: 8px; bottom: 3px; height: 2px; border-radius: var(--radius-full); background: currentColor; opacity: 0.9;
|
|
1040
|
+
transform: scaleX(0); transform-origin: left; transition: transform var(--dur-travel-2) var(--ease-sink);
|
|
1041
|
+
}
|
|
1042
|
+
.alt-btn.alt-hold[data-hold="holding"]:not(:disabled):not([data-loading]) {
|
|
1043
|
+
box-shadow: 0 0 0 0 var(--wall-c), var(--trench); background-image: none; transform: translateY(calc(var(--wall) + 2px));
|
|
1044
|
+
transition: box-shadow var(--alt-hold-dur) linear, transform var(--alt-hold-dur) linear;
|
|
1045
|
+
}
|
|
1046
|
+
.alt-hold[data-hold="holding"] .alt-hold-fill { transform: scaleX(1); transition: transform var(--alt-hold-dur) linear; }
|
|
1047
|
+
.alt-hold[data-hold="done"]:not([data-final]) { animation: alt-land-a calc(var(--dur-travel-3) * 1.6) var(--ease-settle); }
|
|
1048
|
+
/* A completed hold is final by default: the action is now part of the record, so the button lies flat and can't be pressed again. */
|
|
1049
|
+
.alt-btn.alt-hold[data-final], .alt-btn.alt-hold[data-final]:hover, .alt-btn.alt-hold[data-final]:active, .alt-btn.alt-hold[data-final]:focus-visible {
|
|
1050
|
+
background: var(--surface-well); background-image: none; color: var(--ink-muted); box-shadow: 0 0 0 0 var(--wall-c), var(--elev-0); transform: none; cursor: default;
|
|
1051
|
+
transition: box-shadow var(--dur-travel-2) var(--ease-settle), transform var(--dur-travel-2) var(--ease-settle), background-color var(--dur-travel-2), color var(--dur-travel-2);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
.alt-hold[data-final] .alt-hold-fill { opacity: 0; }
|
|
1055
|
+
|
|
1056
|
+
/* ── Pile: thickness says roughly how many (ordinal), the badge says exactly. Click a pile that has items and they
|
|
1057
|
+
slide out from under the top card, floating over the page below (level 3) without moving anything. Click the top,
|
|
1058
|
+
press Escape or click away and they slide back under. ── */
|
|
1059
|
+
.alt-pile { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); padding-bottom: calc(var(--sheets, 0) * 4px); transition: padding-bottom var(--dur-travel-3) var(--ease-glide); }
|
|
1060
|
+
.alt-pile[data-sheets="1"] { --sheets: 1; } .alt-pile[data-sheets="2"] { --sheets: 2; } .alt-pile[data-sheets="3"] { --sheets: 3; }
|
|
1061
|
+
.alt-pile-top, .alt-pile-sheet { grid-area: 1 / 1; border-radius: var(--radius-lg); background: var(--surface-raised); }
|
|
1062
|
+
.alt-pile-top { position: relative; z-index: 4; box-shadow: var(--elev-1); outline: none; transition: box-shadow var(--dur-travel-2) var(--ease-rise), transform var(--dur-travel-2) var(--ease-settle); }
|
|
1063
|
+
.alt-pile-sheet {
|
|
1064
|
+
position: relative; z-index: calc(4 - var(--i)); box-shadow: var(--elev-1); filter: brightness(calc(1 - var(--i) * 0.025));
|
|
1065
|
+
transform: translateY(calc(var(--i) * 4px)) scaleX(calc(1 - var(--i) * 0.035));
|
|
1066
|
+
translate: 0 calc(var(--i) * 3px * var(--fan, 0)); rotate: calc((var(--i) - 2) * 1.2deg * var(--fan, 0));
|
|
1067
|
+
transition: transform var(--dur-travel-3) var(--ease-settle), translate var(--dur-travel-3) var(--ease-settle), rotate var(--dur-travel-3) var(--ease-settle), opacity var(--dur-travel-2);
|
|
1068
|
+
}
|
|
1069
|
+
.alt-pile-live .alt-pile-top { cursor: pointer; }
|
|
1070
|
+
/* Hover: the top lifts and the sheets beneath fan a little, a preview of what's underneath. */
|
|
1071
|
+
.alt-pile-live .alt-pile-top:hover, .alt-pile-live .alt-pile-top:focus-visible { box-shadow: var(--elev-2); transform: translateY(calc(-3px * var(--alt-travel))); }
|
|
1072
|
+
.alt-pile-live:has(.alt-pile-top:hover) .alt-pile-sheet, .alt-pile-live:has(.alt-pile-top:focus-visible) .alt-pile-sheet { --fan: var(--alt-travel); }
|
|
1073
|
+
.alt-pile-live .alt-pile-top:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1074
|
+
.alt-pile-count {
|
|
1075
|
+
position: absolute; z-index: 5; top: -8px; right: -8px; min-width: 22px; height: 22px; padding: 0 6px; display: grid; place-items: center;
|
|
1076
|
+
border-radius: var(--radius-full); background: var(--surface-floating); box-shadow: var(--elev-2); color: var(--ink);
|
|
1077
|
+
font: 600 12px/1 var(--font-sans); pointer-events: none;
|
|
1078
|
+
}
|
|
1079
|
+
.alt-pile[data-open] { z-index: var(--z-floating); }
|
|
1080
|
+
.alt-pile[data-open] .alt-pile-sheet { opacity: 0; transform: none; --fan: 0; }
|
|
1081
|
+
.alt-pile[data-open] .alt-pile-top { box-shadow: var(--elev-2); }
|
|
1082
|
+
.alt-pile-list { position: absolute; z-index: 3; top: calc(100% - var(--sheets, 0) * 4px); left: -18px; right: -18px; pointer-events: none; }
|
|
1083
|
+
.alt-pile-list[data-state="open"] { pointer-events: auto; }
|
|
1084
|
+
/* Each card casts its own shadow; the scroll area has none. Its padding holds the shadows, and the top and bottom
|
|
1085
|
+
edges fade out instead of cutting them off. */
|
|
1086
|
+
.alt-pile-list-inner {
|
|
1087
|
+
margin: 0; padding: var(--space-2) 18px 24px; list-style: none; display: flex; flex-direction: column; gap: 10px; overflow: hidden;
|
|
1088
|
+
-webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--space-2), #000 calc(100% - 22px), transparent);
|
|
1089
|
+
mask-image: linear-gradient(to bottom, transparent, #000 var(--space-2), #000 calc(100% - 22px), transparent);
|
|
1090
|
+
}
|
|
1091
|
+
.alt-pile-list[data-state="open"] .alt-pile-list-inner { overflow-y: auto; }
|
|
1092
|
+
.alt-pile-item {
|
|
1093
|
+
display: block; width: 100%; padding: var(--space-3); border: 0; border-radius: var(--radius-md); background: var(--surface-lifted); box-shadow: var(--elev-2);
|
|
1094
|
+
color: inherit; font: inherit; text-align: left; cursor: pointer;
|
|
1095
|
+
opacity: 0; transform: translateY(calc((var(--i) + 1) * -20px * var(--alt-travel))) scale(calc(1 - 0.03 * var(--alt-travel)));
|
|
1096
|
+
transition: transform var(--dur-travel-2) var(--ease-sink), opacity var(--dur-travel-1) var(--ease-sink), box-shadow var(--dur-travel-1) var(--ease-rise);
|
|
1097
|
+
}
|
|
1098
|
+
.alt-pile-list[data-state="open"] .alt-pile-item {
|
|
1099
|
+
opacity: 1; transform: none;
|
|
1100
|
+
transition: transform var(--dur-travel-3) var(--ease-settle) calc(var(--i) * 22ms), opacity var(--dur-travel-2) var(--ease-rise) calc(var(--i) * 22ms), box-shadow var(--dur-travel-1) var(--ease-rise);
|
|
1101
|
+
}
|
|
1102
|
+
.alt-pile-list[data-state="open"] .alt-pile-item:hover, .alt-pile-list[data-state="open"] .alt-pile-item:focus-visible {
|
|
1103
|
+
box-shadow: var(--elev-3); transform: translateY(calc(-2px * var(--alt-travel))); transition-delay: 0ms;
|
|
1104
|
+
}
|
|
1105
|
+
.alt-pile-list[data-state="open"] .alt-pile-item:active { box-shadow: var(--elev-0); transform: translateY(calc(1px * var(--alt-travel))); transition-duration: var(--dur-press); transition-delay: 0ms; }
|
|
1106
|
+
.alt-pile-item:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1107
|
+
|
|
1108
|
+
/* ── ScrollArea: edges curve away where content continues; content under the header lifts it. ── */
|
|
1109
|
+
.alt-scroll { position: relative; display: flex; flex-direction: column; overflow: hidden; border-radius: var(--radius-lg); background: var(--surface-raised); box-shadow: var(--elev-1); }
|
|
1110
|
+
.alt-scroll-header {
|
|
1111
|
+
position: relative; z-index: 2; padding: var(--space-3) var(--space-4); background: var(--surface-raised); box-shadow: var(--elev-0);
|
|
1112
|
+
transition: box-shadow var(--dur-travel-2) var(--ease-rise);
|
|
1113
|
+
}
|
|
1114
|
+
.alt-scroll[data-top] .alt-scroll-header { box-shadow: var(--elev-2); }
|
|
1115
|
+
.alt-scroll-body { overflow: auto; overscroll-behavior: contain; outline: none; scrollbar-width: thin; }
|
|
1116
|
+
.alt-scroll-body:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: -2px; }
|
|
1117
|
+
.alt-scroll-lip { position: absolute; left: 0; right: 0; height: 24px; pointer-events: none; opacity: 0; transition: opacity var(--dur-travel-2) var(--ease-rise); z-index: 1; }
|
|
1118
|
+
.alt-scroll-lip[data-edge="top"] { top: 0; box-shadow: var(--lip-top); }
|
|
1119
|
+
.alt-scroll-header ~ .alt-scroll-lip[data-edge="top"] { display: none; }
|
|
1120
|
+
.alt-scroll-lip[data-edge="bottom"] { bottom: 0; box-shadow: var(--lip-bottom); }
|
|
1121
|
+
.alt-scroll[data-top] .alt-scroll-lip[data-edge="top"], .alt-scroll[data-bottom] .alt-scroll-lip[data-edge="bottom"] { opacity: 1; }
|
|
1122
|
+
|
|
1123
|
+
/* ── DropZone: flush until a file is in flight anywhere, then it opens; over it, it deepens. ── */
|
|
1124
|
+
.alt-drop {
|
|
1125
|
+
display: grid; place-items: center; gap: var(--space-2); min-height: 132px; padding: var(--space-5); text-align: center;
|
|
1126
|
+
border: 1.5px dashed var(--line-control); border-radius: var(--radius-lg); background: var(--surface-ground); box-shadow: var(--elev-0);
|
|
1127
|
+
color: var(--ink-muted); font: 500 14px/20px var(--font-sans); cursor: pointer;
|
|
1128
|
+
transition: background-color var(--dur-travel-2) var(--ease-rise), box-shadow var(--dur-travel-2) var(--ease-rise), border-color var(--dur-travel-2), transform var(--dur-travel-2) var(--ease-settle);
|
|
1129
|
+
}
|
|
1130
|
+
.alt-drop:hover { border-color: var(--ink-muted); }
|
|
1131
|
+
.alt-drop:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1132
|
+
.alt-drop[data-drop="armed"] { background: var(--surface-well); box-shadow: var(--well); border-color: var(--ink-muted); }
|
|
1133
|
+
.alt-drop[data-drop="over"] { background: var(--accent-soft); box-shadow: var(--trench); border-style: solid; border-color: var(--accent-ink); color: var(--ink); transform: scale(calc(1 - 0.01 * var(--alt-travel))); }
|
|
1134
|
+
|
|
1135
|
+
/* ── EmptyState: an opening the first record will fill. Nothing here yet isn't a problem (Alert) or a settled
|
|
1136
|
+
container (Card): it's a space waiting to receive, so it's sunk, a well cut into the page with a dashed rim, the
|
|
1137
|
+
same below-ground signal as an empty field. Its actions are ordinary raised buttons standing in it. Pointing at
|
|
1138
|
+
the primary action deepens the well to a trench and darkens the rim: feedforward for where the record will land.
|
|
1139
|
+
It sinks in when it appears (flush to well, dur-travel-1, ease-sink), the inverse of content arriving lifted,
|
|
1140
|
+
and it never pulses. ── */
|
|
1141
|
+
.alt-empty {
|
|
1142
|
+
display: flex; flex-direction: column; align-items: center; gap: var(--space-2); padding: var(--space-8) var(--space-6); text-align: center;
|
|
1143
|
+
border: 1.5px dashed var(--line-control); border-radius: var(--radius-lg); background: var(--surface-well); box-shadow: var(--well);
|
|
1144
|
+
color: var(--ink-muted); font: 400 15px/23px var(--font-sans);
|
|
1145
|
+
animation: alt-empty-sink var(--dur-travel-1) var(--ease-sink);
|
|
1146
|
+
transition: box-shadow var(--dur-travel-1) var(--ease-sink), border-color var(--dur-travel-1);
|
|
1147
|
+
}
|
|
1148
|
+
@keyframes alt-empty-sink { from { background-color: var(--surface-ground); box-shadow: var(--elev-0); } }
|
|
1149
|
+
.alt-empty-icon { display: inline-flex; margin-bottom: var(--space-1); color: var(--ink-muted); }
|
|
1150
|
+
.alt-empty-icon > svg { width: 24px; height: 24px; }
|
|
1151
|
+
.alt-empty-title { margin: 0; font: 600 19px/26px var(--font-sans); letter-spacing: -0.01em; color: var(--ink); text-wrap: balance; }
|
|
1152
|
+
.alt-empty-desc { margin: 0; max-width: 46ch; color: var(--ink-muted); text-wrap: pretty; }
|
|
1153
|
+
.alt-empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); margin-top: var(--space-3); }
|
|
1154
|
+
.alt-empty:has(.alt-empty-actions > :first-child:is(:hover, :focus-visible):not(:disabled)) { box-shadow: var(--trench); border-color: var(--ink-muted); }
|
|
1155
|
+
.alt-empty[data-size="sm"] { gap: var(--space-1); padding: var(--space-5) var(--space-4); border-radius: var(--radius-md); font: 400 14px/20px var(--font-sans); }
|
|
1156
|
+
.alt-empty[data-size="sm"] .alt-empty-icon > svg { width: 18px; height: 18px; }
|
|
1157
|
+
.alt-empty[data-size="sm"] .alt-empty-title { font: 500 14px/20px var(--font-sans); letter-spacing: 0; }
|
|
1158
|
+
.alt-empty[data-size="sm"] .alt-empty-actions { margin-top: var(--space-2); }
|
|
1159
|
+
|
|
1160
|
+
/* ── SortableList: pick up → level 3 in your hand; the landing slot opens as a well; release → it lands. ── */
|
|
1161
|
+
.alt-sort { position: relative; display: flex; flex-direction: column; }
|
|
1162
|
+
.alt-sort-item {
|
|
1163
|
+
position: relative; z-index: 1; display: flex; align-items: center; gap: var(--space-3); padding: 10px var(--space-4) 10px var(--space-3);
|
|
1164
|
+
border-radius: var(--radius-md); background: var(--surface-raised); box-shadow: var(--elev-1); color: var(--ink);
|
|
1165
|
+
font: 500 14px/20px var(--font-sans); user-select: none; touch-action: none; cursor: grab; outline: none;
|
|
1166
|
+
transition: transform var(--dur-travel-2) var(--ease-settle), box-shadow var(--dur-travel-2) var(--ease-rise), background-color var(--dur-travel-1);
|
|
1167
|
+
}
|
|
1168
|
+
.alt-sort-item:hover { box-shadow: var(--elev-2); }
|
|
1169
|
+
.alt-sort-item:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1170
|
+
.alt-sort-item[data-held] { z-index: 3; cursor: grabbing; background: var(--surface-floating); box-shadow: var(--elev-3); }
|
|
1171
|
+
.alt-sort-item[data-held]:not([data-following]) { transform: translateY(calc(-2px * var(--alt-travel))) rotate(calc(-0.5deg * var(--alt-travel))); }
|
|
1172
|
+
.alt-sort-item[data-following] { transition: box-shadow var(--dur-travel-2) var(--ease-rise), background-color var(--dur-travel-1); rotate: calc(-0.6deg * var(--alt-travel)); scale: calc(1 + 0.015 * var(--alt-travel)); }
|
|
1173
|
+
.alt-sort-grip { display: inline-flex; color: var(--ink-muted); flex: none; }
|
|
1174
|
+
.alt-sort-body { flex: 1; min-width: 0; }
|
|
1175
|
+
.alt-sort-slot {
|
|
1176
|
+
position: absolute; left: 0; right: 0; z-index: 0; border-radius: var(--radius-md); background: var(--surface-well); box-shadow: var(--well);
|
|
1177
|
+
border: 1.5px dashed var(--line-control); transition: top var(--dur-travel-2) var(--ease-settle);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
/* ── Drilldown: hierarchy as a stack. Each place you go into is laid on top of the last: the crumbs climb a
|
|
1181
|
+
staircase (each one step higher, its wall one pixel thicker), and the view sits on a pile as thick as you are deep. ── */
|
|
1182
|
+
.alt-drill { display: flex; flex-direction: column; gap: var(--space-4); }
|
|
1183
|
+
.alt-crumbs ol { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 6px; margin: 0; padding: 18px 0 8px; list-style: none; }
|
|
1184
|
+
/* Every step stands on the same ground line: a deeper step is a taller slab (its wall is longer), not one floating
|
|
1185
|
+
higher, so all the contact shadows line up. Face and wall share one hairline so the top edge always reads.
|
|
1186
|
+
Shadow list: [face ring, wall, wall ring, contact, ambient]. */
|
|
1187
|
+
.alt-crumbs li { position: relative; display: flex; --rise: calc(var(--d) * 3px); }
|
|
1188
|
+
.alt-crumbs button {
|
|
1189
|
+
--wd: calc(2px + var(--rise)); --wall: var(--wd); --wall-c: color-mix(in oklab, var(--surface-trench), var(--ink) 6%);
|
|
1190
|
+
position: relative; height: 30px; padding: 0 12px; border: 0; border-radius: var(--radius-sm);
|
|
1191
|
+
font: 500 13px/18px var(--font-sans); color: var(--ink-muted); white-space: nowrap; cursor: pointer;
|
|
1192
|
+
background: var(--surface-raised); background-image: var(--alt-sheen);
|
|
1193
|
+
box-shadow: 0 0 0 1px var(--alt-ring), 0 var(--wd) 0 0 var(--wall-c), 0 var(--wd) 0 1px var(--alt-ring),
|
|
1194
|
+
0 calc(var(--wd) + 1px) 2px 0 var(--alt-cast), 0 calc(var(--wd) + 3px) 8px -3px var(--alt-cast);
|
|
1195
|
+
transform: translateY(calc(-1 * var(--wd)));
|
|
1196
|
+
transition: transform var(--dur-travel-2) var(--ease-settle), box-shadow var(--dur-travel-2) var(--ease-settle),
|
|
1197
|
+
color var(--dur-travel-1), background-color var(--dur-travel-1);
|
|
1198
|
+
}
|
|
1199
|
+
.alt-crumbs li:not([data-current]) button:hover, .alt-crumbs li:not([data-current]) button:focus-visible {
|
|
1200
|
+
--wd: calc(3px + var(--rise)); color: var(--ink); background-color: var(--surface-lifted);
|
|
1201
|
+
}
|
|
1202
|
+
.alt-crumbs li:not([data-current]) button:active { --wd: 0px; background-image: none; transition-duration: var(--dur-press); transition-timing-function: ease-out; }
|
|
1203
|
+
.alt-crumbs li[data-current] button { color: var(--ink); font-weight: 600; cursor: default; }
|
|
1204
|
+
.alt-crumbs li[data-new] button { animation: alt-crumb-rise var(--dur-travel-3) var(--ease-settle); }
|
|
1205
|
+
/* A new step is built: it rises out of the ground to its height. */
|
|
1206
|
+
@keyframes alt-crumb-rise {
|
|
1207
|
+
from { transform: none; box-shadow: 0 0 0 1px var(--alt-ring), 0 0 0 0 var(--wall-c), 0 0 0 1px var(--alt-ring), 0 1px 2px 0 var(--alt-cast), 0 3px 8px -3px var(--alt-cast); }
|
|
1208
|
+
}
|
|
1209
|
+
.alt-drill-pile .alt-pile-sheet { animation: alt-sheet-in var(--dur-travel-3) var(--ease-settle); }
|
|
1210
|
+
@keyframes alt-sheet-in { from { transform: none; } }
|
|
1211
|
+
.alt-drill-stage { display: grid; overflow: hidden; }
|
|
1212
|
+
.alt-drill-view { grid-area: 1 / 1; padding: var(--space-2); outline: none; }
|
|
1213
|
+
.alt-drill-view[data-phase="out"] { pointer-events: none; }
|
|
1214
|
+
.alt-drill[data-dir="down"] .alt-drill-view[data-phase="in"] { animation: alt-laid-on var(--dur-travel-3) var(--ease-rise) both; }
|
|
1215
|
+
.alt-drill[data-dir="down"] .alt-drill-view[data-phase="out"] { animation: alt-pressed-under calc(var(--dur-travel-3) * 0.7) var(--ease-sink) both; }
|
|
1216
|
+
.alt-drill[data-dir="up"] .alt-drill-view[data-phase="in"] { animation: alt-from-under var(--dur-travel-3) var(--ease-rise) both; }
|
|
1217
|
+
.alt-drill[data-dir="up"] .alt-drill-view[data-phase="out"] { animation: alt-lifted-off calc(var(--dur-travel-3) * 0.7) var(--ease-sink) both; }
|
|
1218
|
+
@keyframes alt-laid-on { from { opacity: 0; transform: translateY(calc(-8px * var(--alt-travel))) scale(calc(1 + 0.02 * var(--alt-travel))); } }
|
|
1219
|
+
@keyframes alt-pressed-under { to { opacity: 0; transform: translateY(calc(6px * var(--alt-travel))) scale(calc(1 - 0.03 * var(--alt-travel))); } }
|
|
1220
|
+
@keyframes alt-from-under { from { opacity: 0; transform: translateY(calc(6px * var(--alt-travel))) scale(calc(1 - 0.03 * var(--alt-travel))); } }
|
|
1221
|
+
@keyframes alt-lifted-off { to { opacity: 0; transform: translateY(calc(-8px * var(--alt-travel))) scale(calc(1 + 0.02 * var(--alt-travel))); } }
|
|
1222
|
+
.alt-drill-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 2px; }
|
|
1223
|
+
.alt-drill-row {
|
|
1224
|
+
display: flex; width: 100%; align-items: center; gap: var(--space-3); padding: 10px var(--space-3); border: 0; border-radius: var(--radius-md);
|
|
1225
|
+
background: transparent; color: var(--ink); text-align: left; cursor: pointer; box-shadow: var(--elev-0);
|
|
1226
|
+
transition: background-color var(--dur-travel-1) var(--ease-rise), box-shadow var(--dur-travel-1) var(--ease-rise), transform var(--dur-travel-2) var(--ease-settle);
|
|
1227
|
+
}
|
|
1228
|
+
.alt-drill-row:hover, .alt-drill-row:focus-visible { background: var(--surface-lifted); box-shadow: var(--elev-2); transform: translateY(calc(-1px * var(--alt-travel))); }
|
|
1229
|
+
.alt-drill-row:active { box-shadow: var(--elev-0); transform: translateY(calc(1px * var(--alt-travel))); transition-duration: var(--dur-press); }
|
|
1230
|
+
.alt-drill-row:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1231
|
+
.alt-drill-row-text { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
|
|
1232
|
+
.alt-drill-row-title { font: 500 14px/20px var(--font-sans); }
|
|
1233
|
+
.alt-drill-row-desc { font: 400 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1234
|
+
.alt-drill-count { font: 500 12px/1 var(--font-mono); color: var(--ink-muted); }
|
|
1235
|
+
.alt-drill-chev { color: var(--ink-muted); transform: rotate(-90deg); flex: none; }
|
|
1236
|
+
.alt-drill-leaf { padding: var(--space-3); font: 400 14px/21px var(--font-sans); color: var(--ink); }
|
|
1237
|
+
|
|
1238
|
+
/* ── CommandPalette: the summit. Level 5 like Dialog — the page recedes, the scrim veils it, the palette rises 16px
|
|
1239
|
+
as its shadow grows from elev-1 — but anchored near the top, so the results can grow downward without the field
|
|
1240
|
+
moving. The query field is an opening built exactly like Input: its back wall shows while it's empty, and once it
|
|
1241
|
+
holds a query its floor rises flush with the palette (surface-modal, the page it sits on here; surface-raised
|
|
1242
|
+
would sit below level 5 in dark schemes). One accent-soft highlight is carried between results. When the results
|
|
1243
|
+
change, rows that survive travel to their new places (FLIP, ease-glide) and new ones rise 4px in, at most four at a
|
|
1244
|
+
time (riseDelay) and only near the top; the rest cross-fade. On opening, predicted items are there at once and the
|
|
1245
|
+
rest fade in over dur-onset. ── */
|
|
1246
|
+
.alt-cmd-root { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; justify-items: center; align-items: start; padding: max(var(--space-6), 12vh) var(--space-4) var(--space-6); }
|
|
1247
|
+
.alt-cmd-root[data-state="closed"] .alt-scrim { opacity: 0; transition-duration: calc(var(--dur-travel-5) * 0.7); transition-timing-function: var(--ease-sink); }
|
|
1248
|
+
.alt-cmd {
|
|
1249
|
+
position: relative; display: flex; flex-direction: column; width: min(100%, 600px); max-height: 100%; overflow: hidden; outline: none;
|
|
1250
|
+
border-radius: var(--radius-xl); background: var(--surface-modal); box-shadow: var(--elev-5); color: var(--ink); transform-origin: 50% 0;
|
|
1251
|
+
transition: opacity var(--dur-travel-5) var(--ease-rise), transform var(--dur-travel-5) var(--ease-rise), box-shadow var(--dur-travel-5) var(--ease-rise);
|
|
1252
|
+
}
|
|
1253
|
+
.alt-cmd-root[data-state="closed"] .alt-cmd {
|
|
1254
|
+
opacity: 0; box-shadow: var(--elev-1); transform: translateY(calc(16px * var(--alt-travel))) scale(calc(1 - 0.04 * var(--alt-travel)));
|
|
1255
|
+
transition-duration: calc(var(--dur-travel-5) * 0.7); transition-timing-function: var(--ease-sink);
|
|
1256
|
+
}
|
|
1257
|
+
.alt-cmd-head { flex: none; padding: var(--space-3); }
|
|
1258
|
+
.alt-cmd .alt-cmd-field { height: 48px; padding: 0 var(--space-3) 0 var(--space-4); gap: var(--space-3); border-radius: calc(var(--radius-xl) - var(--space-3)); }
|
|
1259
|
+
.alt-cmd .alt-cmd-field input { font-size: 16px; }
|
|
1260
|
+
.alt-cmd .alt-cmd-field:focus-within, .alt-cmd .alt-cmd-field:has(input:not(:placeholder-shown)) { background: var(--surface-modal); }
|
|
1261
|
+
.alt-cmd-viewport { position: relative; flex: 0 1 auto; min-height: 0; max-height: min(380px, 52vh); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
|
|
1262
|
+
.alt-cmd-viewport[data-ready] { transition: height var(--dur-travel-2) var(--ease-glide); }
|
|
1263
|
+
.alt-cmd-list { position: relative; padding: 0 var(--space-2) var(--space-2); outline: none; }
|
|
1264
|
+
.alt-cmd-group + .alt-cmd-group { margin-top: var(--space-1); }
|
|
1265
|
+
.alt-cmd-label { padding: 8px 10px 4px; font: 500 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1266
|
+
.alt-cmd-hl {
|
|
1267
|
+
position: absolute; top: 0; left: var(--space-2); right: var(--space-2); border-radius: var(--radius-sm); background: var(--accent-soft); pointer-events: none;
|
|
1268
|
+
transition: transform var(--dur-travel-2) var(--ease-settle), height var(--dur-travel-2) var(--ease-settle), opacity var(--dur-travel-1), background-color var(--dur-travel-1);
|
|
1269
|
+
}
|
|
1270
|
+
.alt-cmd-hl[data-tone="critical"] { background: var(--critical-soft); }
|
|
1271
|
+
.alt-cmd-item {
|
|
1272
|
+
position: relative; display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 0 10px; border-radius: var(--radius-sm);
|
|
1273
|
+
font: 500 14px/20px var(--font-sans); color: var(--ink); cursor: pointer; user-select: none;
|
|
1274
|
+
}
|
|
1275
|
+
.alt-cmd-item[data-tone="critical"] { color: var(--critical); }
|
|
1276
|
+
.alt-cmd-item[aria-disabled] { color: var(--ink-faint); cursor: not-allowed; }
|
|
1277
|
+
.alt-cmd-icon { display: inline-flex; flex: none; color: var(--ink-muted); }
|
|
1278
|
+
.alt-cmd-item[data-tone="critical"] .alt-cmd-icon, .alt-cmd-item[aria-disabled] .alt-cmd-icon { color: inherit; }
|
|
1279
|
+
.alt-cmd-text { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: var(--space-2); white-space: nowrap; overflow: hidden; }
|
|
1280
|
+
.alt-cmd-title { flex: none; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
|
|
1281
|
+
.alt-cmd-desc { min-width: 0; overflow: hidden; text-overflow: ellipsis; font: 400 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1282
|
+
.alt-cmd-match { background: none; color: var(--accent-ink); }
|
|
1283
|
+
.alt-cmd-item[data-tone="critical"] .alt-cmd-match { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
|
|
1284
|
+
.alt-cmd-keys { display: inline-flex; flex: none; gap: 2px; }
|
|
1285
|
+
.alt-cmd-empty { padding: var(--space-5) var(--space-6) var(--space-8); text-align: center; font: 400 14px/21px var(--font-sans); color: var(--ink-muted); }
|
|
1286
|
+
.alt-cmd-empty b { display: block; margin-bottom: 2px; font-weight: 500; color: var(--ink); }
|
|
1287
|
+
.alt-cmd-foot { flex: none; display: flex; align-items: center; gap: var(--space-4); padding: var(--space-2) var(--space-4); border-top: 1px solid var(--line); font: 500 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1288
|
+
.alt-cmd-foot span { display: inline-flex; align-items: center; gap: 6px; }
|
|
1289
|
+
.alt-cmd-foot .alt-kbd { margin: 0 0 2px; }
|
|
1290
|
+
.alt-cmd-foot .alt-kbd + .alt-kbd { margin-left: -4px; }
|
|
1291
|
+
.alt-cmd[data-ephemeral] .alt-cmd-item:not([data-predicted]), .alt-cmd[data-ephemeral] .alt-cmd-label:not([data-predicted]) { animation: alt-onset var(--dur-onset) linear backwards; }
|
|
1292
|
+
@keyframes alt-onset { from { opacity: 0; } }
|
|
1293
|
+
|
|
1294
|
+
/* ── Sheet: a large sheet laid over the page at level 4, anchored to an edge. It isn't slid in: it rises at its edge —
|
|
1295
|
+
16px of travel from that edge at most, a fade, its shadow growing from elev-1 to elev-4 — while the page recedes
|
|
1296
|
+
behind it (modal). Closing lifts it off: up and toward you as its shadow spreads, faster than it came. It stands
|
|
1297
|
+
8px clear of its edge so its own edges, and the shadow it casts below them, read as height. While content scrolls
|
|
1298
|
+
under its header the header rises; where content continues below, the footer's top edge curves away. A bottom
|
|
1299
|
+
sheet has a finger pull: a small recess (an opening, like every place you put something into) to drag it down by. ── */
|
|
1300
|
+
.alt-sheet-root { position: fixed; inset: 0; z-index: var(--z-overlay); pointer-events: none; }
|
|
1301
|
+
.alt-sheet-root > .alt-scrim { pointer-events: auto; }
|
|
1302
|
+
.alt-sheet-root[data-state="closed"] > .alt-scrim { opacity: 0; transition-duration: calc(var(--dur-travel-4) * 0.7); transition-timing-function: var(--ease-sink); }
|
|
1303
|
+
.alt-sheet {
|
|
1304
|
+
--edge: var(--space-2); --w: 440px;
|
|
1305
|
+
position: absolute; display: flex; flex-direction: column; overflow: hidden; outline: none; pointer-events: auto;
|
|
1306
|
+
border-radius: var(--radius-xl); background: var(--surface-overlay); box-shadow: var(--elev-4); color: var(--ink);
|
|
1307
|
+
transition: opacity var(--dur-travel-4) var(--ease-rise), transform var(--dur-travel-4) var(--ease-rise), box-shadow var(--dur-travel-4) var(--ease-rise);
|
|
1308
|
+
}
|
|
1309
|
+
.alt-sheet[data-size="sm"] { --w: 360px; }
|
|
1310
|
+
.alt-sheet[data-size="lg"] { --w: 560px; }
|
|
1311
|
+
.alt-sheet[data-side="right"], .alt-sheet[data-side="left"] { top: var(--edge); bottom: var(--edge); width: min(calc(100% - 2 * var(--edge)), var(--w)); }
|
|
1312
|
+
.alt-sheet[data-side="right"] { right: var(--edge); transform-origin: 100% 50%; }
|
|
1313
|
+
.alt-sheet[data-side="left"] { left: var(--edge); transform-origin: 0 50%; }
|
|
1314
|
+
.alt-sheet[data-side="bottom"] { --w: 720px; left: 0; right: 0; bottom: var(--edge); width: min(calc(100% - 2 * var(--edge)), var(--w)); max-height: calc(100% - 2 * var(--space-8)); margin: 0 auto; transform-origin: 50% 100%; }
|
|
1315
|
+
.alt-sheet[data-side="bottom"][data-size="sm"] { --w: 480px; }
|
|
1316
|
+
.alt-sheet[data-side="bottom"][data-size="lg"] { --w: 960px; }
|
|
1317
|
+
.alt-sheet-root[data-state="closed"] .alt-sheet { opacity: 0; box-shadow: var(--elev-1); }
|
|
1318
|
+
.alt-sheet-root[data-state="closed"] .alt-sheet[data-side="right"] { transform: translateX(calc(16px * var(--alt-travel))); }
|
|
1319
|
+
.alt-sheet-root[data-state="closed"] .alt-sheet[data-side="left"] { transform: translateX(calc(-16px * var(--alt-travel))); }
|
|
1320
|
+
.alt-sheet-root[data-state="closed"] .alt-sheet[data-side="bottom"] { transform: translateY(calc(16px * var(--alt-travel))); }
|
|
1321
|
+
.alt-sheet-root[data-state="closed"][data-exit] .alt-sheet {
|
|
1322
|
+
box-shadow: var(--elev-5); transform: translateY(calc(-8px * var(--alt-travel))) scale(calc(1 + 0.01 * var(--alt-travel)));
|
|
1323
|
+
transition-duration: calc(var(--dur-travel-4) * 0.7); transition-timing-function: var(--ease-sink);
|
|
1324
|
+
}
|
|
1325
|
+
.alt-sheet-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
|
|
1326
|
+
.alt-sheet-inner { display: flex; flex-direction: column; gap: var(--space-4); min-height: 100%; padding: 0 var(--space-6); }
|
|
1327
|
+
.alt-sheet-header {
|
|
1328
|
+
position: sticky; top: 0; z-index: 2; display: flex; flex-direction: column; gap: 6px; margin: 0 calc(-1 * var(--space-6));
|
|
1329
|
+
padding: var(--space-6) calc(var(--space-6) + 36px) var(--space-2) var(--space-6); background: var(--surface-overlay); box-shadow: var(--elev-0);
|
|
1330
|
+
transition: box-shadow var(--dur-travel-2) var(--ease-rise);
|
|
1331
|
+
}
|
|
1332
|
+
.alt-sheet[data-top] .alt-sheet-header { box-shadow: var(--elev-2); }
|
|
1333
|
+
.alt-sheet-title { margin: 0; font: 600 19px/26px var(--font-sans); letter-spacing: -0.01em; }
|
|
1334
|
+
.alt-sheet-desc { margin: 0; font: 400 14px/21px var(--font-sans); color: var(--ink-muted); }
|
|
1335
|
+
.alt-sheet-inner > :last-child:not(.alt-sheet-footer) { margin-bottom: var(--space-6); }
|
|
1336
|
+
.alt-sheet-footer {
|
|
1337
|
+
position: sticky; bottom: 0; z-index: 2; display: flex; justify-content: flex-end; gap: var(--space-2); margin: auto calc(-1 * var(--space-6)) 0;
|
|
1338
|
+
padding: var(--space-4) var(--space-6) var(--space-6); background: var(--surface-overlay);
|
|
1339
|
+
}
|
|
1340
|
+
.alt-sheet-footer::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 24px; pointer-events: none; box-shadow: var(--lip-bottom); opacity: 0; transition: opacity var(--dur-travel-2) var(--ease-rise); }
|
|
1341
|
+
.alt-sheet[data-bottom] .alt-sheet-footer::before { opacity: 1; }
|
|
1342
|
+
.alt-sheet-close { position: absolute; z-index: 3; top: var(--space-4); right: var(--space-4); color: var(--ink-muted); }
|
|
1343
|
+
.alt-sheet-pull {
|
|
1344
|
+
position: relative; z-index: 3; flex: none; align-self: center; width: 44px; height: 8px; margin: 10px 0 -8px; border-radius: var(--radius-full);
|
|
1345
|
+
background: var(--surface-well); cursor: grab; touch-action: none;
|
|
1346
|
+
box-shadow: inset 0 calc(2px + var(--n) * 1px) 0 0 var(--alt-wall-in), inset 0 calc(3px + var(--n) * 1px) 2px -1px var(--alt-cast), 0 1px 0 0 var(--alt-lip);
|
|
1347
|
+
transition: box-shadow var(--dur-travel-2) var(--ease-settle);
|
|
1348
|
+
}
|
|
1349
|
+
.alt-sheet-pull::after { content: ""; position: absolute; inset: -12px -28px; }
|
|
1350
|
+
.alt-sheet[data-dragging] { transition: none; cursor: grabbing; }
|
|
1351
|
+
.alt-sheet[data-dragging] .alt-sheet-pull { cursor: grabbing; --n: 1; }
|
|
1352
|
+
.alt-sheet[data-side="bottom"] .alt-sheet-close { top: var(--space-3); }
|
|
1353
|
+
|
|
1354
|
+
/* ── Select & Combobox: choosing a value is filling a field, so the trigger is an opening built like Input — its back
|
|
1355
|
+
wall shows while it's empty (or on its placeholder), its floor rises flush once a value is chosen, and it drops to
|
|
1356
|
+
trench depth when invalid. The list rises from the field's edge at level 3, like Popover and DropdownMenu, with the
|
|
1357
|
+
one gliding highlight; the chosen option wears the Checkbox family's tick, drawn in as the list opens. On choosing,
|
|
1358
|
+
the list sinks back, the floor rises and the new value settles in with a brief afterglow. In a Combobox what you
|
|
1359
|
+
type is a query, not a value: the field stays an opening (its wall showing under the text) until you choose. ── */
|
|
1360
|
+
.alt-select { position: relative; display: block; min-width: 0; }
|
|
1361
|
+
.alt-select > .alt-input { padding: 0; cursor: pointer; }
|
|
1362
|
+
.alt-combobox > .alt-input { cursor: text; }
|
|
1363
|
+
.alt-input[data-filled]:not([data-invalid]):not([data-disabled]) { --w: 0px; --n: 0; background: var(--surface-raised); }
|
|
1364
|
+
.alt-combobox > .alt-input:not([data-filled]):not([data-invalid]):not([data-disabled]) { --w: 4px; --n: calc(var(--near) * var(--alt-travel)); }
|
|
1365
|
+
.alt-combobox > .alt-input[data-size="sm"]:not([data-filled]):not([data-invalid]):not([data-disabled]) { --w: 3px; }
|
|
1366
|
+
/* Open, or focused: held like a focused Input, and like it the 2px neutral rim only when you got there by keyboard
|
|
1367
|
+
(data-key-focus sits on the whole .alt-select, so it survives focus moving into the list). While nothing is chosen
|
|
1368
|
+
it holds the depth approach previewed; what you type into a Combobox doesn't fill it. */
|
|
1369
|
+
.alt-select[data-open] > .alt-input:not([data-invalid]) { background: var(--surface-raised); }
|
|
1370
|
+
.alt-select[data-key-focus] > .alt-input:focus-within, .alt-select[data-key-focus][data-open] > .alt-input:not([data-invalid]) { border-color: var(--alt-rim-held); outline-color: var(--alt-rim-held); }
|
|
1371
|
+
.alt-select[data-key-focus] > .alt-input[data-invalid]:focus-within { border-color: var(--critical); outline-color: var(--critical); }
|
|
1372
|
+
.alt-select[data-open] > .alt-input:not([data-invalid]):not([data-filled]),
|
|
1373
|
+
.alt-combobox > .alt-input:not([data-filled]):not([data-invalid]):not([data-disabled]):focus-within { --n: var(--alt-travel); }
|
|
1374
|
+
.alt-select-trigger {
|
|
1375
|
+
display: flex; align-items: center; gap: var(--space-2); flex: 1; min-width: 0; height: 100%; margin: 0; padding: 0 10px 0 var(--space-3);
|
|
1376
|
+
border: 0; border-radius: inherit; background: none; color: inherit; font: 400 14px/20px var(--font-sans); text-align: left; cursor: inherit; outline: none;
|
|
1377
|
+
}
|
|
1378
|
+
.alt-select-trigger:disabled { cursor: not-allowed; }
|
|
1379
|
+
.alt-select-value {
|
|
1380
|
+
flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; border-radius: var(--radius-xs);
|
|
1381
|
+
transform: translateY(calc(var(--wd) * 0.5)); transition: transform var(--dur-travel-2) var(--ease-settle);
|
|
1382
|
+
}
|
|
1383
|
+
.alt-select-value[data-placeholder] { color: var(--ink-muted); }
|
|
1384
|
+
.alt-select-icon { display: inline-flex; margin-right: var(--space-2); vertical-align: -3px; color: var(--ink-muted); }
|
|
1385
|
+
.alt-select-chevron { flex: none; color: var(--ink-muted); transform: translateY(calc(var(--wd) * 0.5)); transition: transform var(--dur-travel-3) var(--ease-settle); }
|
|
1386
|
+
.alt-select[data-open] .alt-select-chevron { transform: translateY(calc(var(--wd) * 0.5)) rotate(180deg); }
|
|
1387
|
+
.alt-combobox input { padding-left: var(--space-3); border-radius: var(--radius-xs); }
|
|
1388
|
+
.alt-select-toggle { display: inline-grid; place-items: center; align-self: stretch; margin: 0; padding: 0 10px 0 4px; border: 0; background: none; color: inherit; cursor: pointer; }
|
|
1389
|
+
.alt-select-toggle:disabled { cursor: not-allowed; }
|
|
1390
|
+
.alt-select-list { left: 0; right: auto; min-width: 100%; width: max-content; max-width: max(100%, 360px); max-height: 280px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; transform-origin: 50% 0; }
|
|
1391
|
+
.alt-select-list[data-side="top"] { transform-origin: 50% 100%; }
|
|
1392
|
+
.alt-select-list:focus { outline: none; }
|
|
1393
|
+
.alt-select-option { padding-right: 10px; }
|
|
1394
|
+
.alt-select-option .alt-menu-text { min-width: 0; }
|
|
1395
|
+
.alt-select-option:has(.alt-select-desc) { padding-block: 6px; }
|
|
1396
|
+
.alt-select-desc { display: block; font: 400 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1397
|
+
.alt-select-tick { flex: none; color: var(--accent-ink); }
|
|
1398
|
+
.alt-select-tick path { stroke-dasharray: 16; }
|
|
1399
|
+
.alt-select-list[data-state="open"] .alt-select-tick path { animation: alt-tick-draw var(--dur-travel-2) var(--ease-rise) var(--dur-travel-1) backwards; }
|
|
1400
|
+
@keyframes alt-tick-draw { from { stroke-dashoffset: 16; } }
|
|
1401
|
+
.alt-select-empty { padding: 8px 10px; font: 400 13.5px/20px var(--font-sans); color: var(--ink-muted); }
|
|
1402
|
+
.alt-select-value[data-glow="a"], .alt-combobox input[data-glow="a"] { animation: alt-value-a calc(var(--dur-settle) / 5) var(--ease-decay); }
|
|
1403
|
+
.alt-select-value[data-glow="b"], .alt-combobox input[data-glow="b"] { animation: alt-value-b calc(var(--dur-settle) / 5) var(--ease-decay); }
|
|
1404
|
+
@keyframes alt-value-a { from { background-color: var(--accent-soft); box-shadow: 0 0 0 3px var(--accent-soft); } to { background-color: transparent; box-shadow: 0 0 0 3px transparent; } }
|
|
1405
|
+
@keyframes alt-value-b { from { background-color: var(--accent-soft); box-shadow: 0 0 0 3px var(--accent-soft); } to { background-color: transparent; box-shadow: 0 0 0 3px transparent; } }
|
|
1406
|
+
|
|
1407
|
+
/* ── Stepper: a process as a staircase of plates standing on one ground line, in the breadcrumb's vocabulary. Done
|
|
1408
|
+
steps are settled into the record: plates flush with the ground, their edges stamped, wearing the Checkbox family's
|
|
1409
|
+
raised check on the accent. The current step is a raised slab with a wall (wall-2), as tall as the primary action; it
|
|
1410
|
+
carries no sheen, because it isn't pressed. Steps to come are imprints pressed into the page, like Skeleton's.
|
|
1411
|
+
Advancing presses the current step down into the record (ease-sink), stamps its check in (as a Badge re-stamps), then
|
|
1412
|
+
raises the next out of its imprint (ease-rise, within the attention budget). Every state uses the same six-layer
|
|
1413
|
+
shadow list — [stamp or well edge, ring, wall, wall ring, contact, ambient] — so each animates into the others. ── */
|
|
1414
|
+
.alt-stepper { display: flex; align-items: center; flex-wrap: wrap; row-gap: var(--space-3); margin: 0; padding: 8px 0 4px; list-style: none; }
|
|
1415
|
+
.alt-step-item { display: flex; align-items: center; flex: 1 1 auto; min-width: 0; }
|
|
1416
|
+
.alt-step-item:last-child { flex: none; }
|
|
1417
|
+
.alt-step-line { flex: 1 1 16px; min-width: 16px; height: 2px; margin: 0 var(--space-2); border-radius: var(--radius-full); background: var(--line-control); transition: background-color var(--dur-travel-2) var(--ease-rise); }
|
|
1418
|
+
.alt-step-line[data-done] { background: var(--accent); }
|
|
1419
|
+
.alt-step {
|
|
1420
|
+
--wall: 0px; --wall-c: color-mix(in oklab, var(--surface-trench), var(--ink) 6%);
|
|
1421
|
+
--st-in: inset 0 0 0 0 transparent; --st-ring: transparent; --st-cast: transparent;
|
|
1422
|
+
position: relative; display: inline-flex; align-items: center; gap: var(--space-2); min-height: 36px; margin: 0; padding: 6px var(--space-3) 6px 7px;
|
|
1423
|
+
border: 0; border-radius: var(--radius-md); background: transparent; color: var(--ink-muted); font: 500 13.5px/18px var(--font-sans); text-align: left; white-space: nowrap;
|
|
1424
|
+
box-shadow: var(--st-in), 0 0 0 1px var(--st-ring), 0 var(--wall) 0 0 var(--wall-c), 0 var(--wall) 0 1px var(--st-ring),
|
|
1425
|
+
0 calc(var(--wall) + 1px) 2px 0 var(--st-cast), 0 calc(var(--wall) + 3px) 8px -3px var(--st-cast);
|
|
1426
|
+
transform: translateY(calc(-1 * var(--wall)));
|
|
1427
|
+
transition: box-shadow var(--dur-travel-2) var(--ease-settle), transform var(--dur-travel-2) var(--ease-settle), background-color var(--dur-travel-2) var(--ease-rise), color var(--dur-travel-1);
|
|
1428
|
+
}
|
|
1429
|
+
.alt-step[data-state="done"] { color: var(--ink); --st-in: inset 0 1px 1.5px color-mix(in oklab, var(--alt-cast) 70%, transparent); --st-ring: color-mix(in oklab, var(--ink) 10%, transparent); }
|
|
1430
|
+
.alt-step[data-state="current"] { --wall: var(--wall-2); --st-ring: var(--alt-ring); --st-cast: var(--alt-cast); background: var(--surface-raised); color: var(--ink); font-weight: 600; }
|
|
1431
|
+
.alt-step[data-state="upcoming"] { --st-in: inset 0 1px 2px var(--alt-cast); background: var(--surface-well); }
|
|
1432
|
+
.alt-step-mark {
|
|
1433
|
+
flex: none; display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: var(--radius-full);
|
|
1434
|
+
font: 600 12px/1 var(--font-sans); font-variant-numeric: tabular-nums;
|
|
1435
|
+
transition: background-color var(--dur-travel-2) var(--ease-rise), color var(--dur-travel-1), box-shadow var(--dur-travel-2) var(--ease-rise);
|
|
1436
|
+
}
|
|
1437
|
+
.alt-step[data-state="done"] .alt-step-mark { background: var(--accent); color: var(--on-accent); }
|
|
1438
|
+
.alt-step[data-state="done"] .alt-step-mark svg { filter: drop-shadow(0 1px 0.5px rgb(0 0 0 / 0.28)); }
|
|
1439
|
+
.alt-step[data-state="done"] .alt-step-mark path { stroke-dasharray: 16; }
|
|
1440
|
+
.alt-step[data-state="current"] .alt-step-mark { background: var(--accent-soft); color: var(--accent-ink); box-shadow: inset 0 0 0 1.5px var(--accent-ink); }
|
|
1441
|
+
.alt-step[data-state="upcoming"] .alt-step-mark { box-shadow: inset 0 0 0 1px var(--line-control); }
|
|
1442
|
+
.alt-step-mark[data-stamp="a"] { animation: alt-stamp-a var(--dur-travel-3) var(--ease-settle) 110ms backwards; }
|
|
1443
|
+
.alt-step-mark[data-stamp="b"] { animation: alt-stamp-b var(--dur-travel-3) var(--ease-settle) 110ms backwards; }
|
|
1444
|
+
.alt-step-mark[data-stamp] path { animation: alt-tick-draw var(--dur-travel-2) var(--ease-rise) 160ms backwards; }
|
|
1445
|
+
.alt-step[data-motion="press"] { transition-timing-function: var(--ease-sink); }
|
|
1446
|
+
.alt-step[data-motion="rise"] { transition-duration: var(--dur-travel-3); transition-timing-function: var(--ease-rise); transition-delay: var(--alt-rise-delay, 0ms); }
|
|
1447
|
+
.alt-step[data-motion="rise"] > * { animation: alt-step-rise var(--dur-travel-3) var(--ease-rise) var(--alt-rise-delay, 0ms) backwards; }
|
|
1448
|
+
@keyframes alt-step-rise { from { opacity: 0.3; transform: translateY(calc(5px * var(--alt-travel))); } }
|
|
1449
|
+
.alt-step-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
|
|
1450
|
+
.alt-step-desc { font: 400 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1451
|
+
.alt-step[role="button"] { cursor: pointer; }
|
|
1452
|
+
.alt-step[role="button"][data-state="done"] { --wall: 0px; }
|
|
1453
|
+
.alt-step[role="button"][data-state="done"]:hover, .alt-step[role="button"][data-state="done"]:focus-visible {
|
|
1454
|
+
--wall: var(--wall-1); --st-ring: var(--alt-ring); --st-cast: var(--alt-cast); background: color-mix(in oklab, var(--surface-raised) 60%, transparent);
|
|
1455
|
+
}
|
|
1456
|
+
.alt-step[role="button"][data-state="done"]:active { --wall: 0px; transition-duration: var(--dur-press); transition-timing-function: ease-out; }
|
|
1457
|
+
.alt-step[role="button"]:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1458
|
+
.alt-stepper[data-orientation="vertical"] { flex-direction: column; align-items: stretch; flex-wrap: nowrap; padding: 4px 0 0; }
|
|
1459
|
+
.alt-stepper[data-orientation="vertical"] .alt-step-item { flex-direction: column; align-items: stretch; flex: none; }
|
|
1460
|
+
.alt-stepper[data-orientation="vertical"] .alt-step { display: flex; align-items: flex-start; white-space: normal; padding: 9px var(--space-3) 9px 9px; }
|
|
1461
|
+
.alt-stepper[data-orientation="vertical"] .alt-step-mark { margin-top: -2px; }
|
|
1462
|
+
.alt-stepper[data-orientation="vertical"] .alt-step-line { flex: none; width: 2px; min-width: 0; height: 12px; margin: 2px 0 2px 19px; }
|
|
1463
|
+
|
|
1464
|
+
/* ── Table: rows are the record. They sit on the ground with `line` dividers, and only rows that do something react:
|
|
1465
|
+
an interactive row lifts one level on hover (a ghost lift), dropping back to
|
|
1466
|
+
the ground when pressed. A selected row is tinted accent-soft and raised one level; the toolbar counts the selection
|
|
1467
|
+
with a floating count Badge. Filtering in place raises matches and sinks misses into a well. The header stays flush
|
|
1468
|
+
until rows scroll under it, then rises (elev-2), as in ScrollArea; where rows continue below, the bottom edge curves
|
|
1469
|
+
away. Re-sorting carries rows to their new places (FLIP) instead of reshuffling. A row picked up to reorder floats at
|
|
1470
|
+
level 3, tilted, over a slot that opens as a well. Cells can't share one shadow, so each row's height is drawn as a
|
|
1471
|
+
single slab by its first cell, as wide as the table (--alt-row-w, measured). ── */
|
|
1472
|
+
.alt-data-table { min-width: 0; }
|
|
1473
|
+
.alt-table-tools { display: flex; align-items: center; gap: var(--space-3); min-height: 36px; margin-bottom: var(--space-2); font: 500 14px/20px var(--font-sans); color: var(--ink); }
|
|
1474
|
+
.alt-table-selection { display: inline-flex; align-items: center; gap: var(--space-2); --alt-from-y: 4px; animation: alt-emerge var(--dur-travel-1) var(--ease-rise); }
|
|
1475
|
+
.alt-table-selection .alt-badge[data-variant="count"] { position: static; }
|
|
1476
|
+
.alt-table-tools-end { display: inline-flex; align-items: center; gap: var(--space-2); margin-left: auto; }
|
|
1477
|
+
.alt-table-wrap { position: relative; isolation: isolate; overflow: auto; overscroll-behavior: contain; scrollbar-width: thin; outline: none; }
|
|
1478
|
+
.alt-table-wrap:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; border-radius: var(--radius-md); }
|
|
1479
|
+
.alt-table-wrap::after { content: ""; position: sticky; z-index: 4; bottom: 0; display: block; height: 24px; margin-top: -24px; pointer-events: none; box-shadow: var(--lip-bottom); opacity: 0; transition: opacity var(--dur-travel-2) var(--ease-rise); }
|
|
1480
|
+
.alt-table-wrap[data-bottom]::after { opacity: 1; }
|
|
1481
|
+
.alt-table { --alt-row-w: 100%; width: 100%; border-collapse: separate; border-spacing: 0; font: 400 14px/20px var(--font-sans); color: var(--ink); font-variant-numeric: tabular-nums; }
|
|
1482
|
+
.alt-th, .alt-td { padding: 10px 12px; text-align: left; vertical-align: middle; border-bottom: 1px solid var(--line); transition: border-color var(--dur-travel-1); }
|
|
1483
|
+
.alt-th[data-align="end"], .alt-td[data-align="end"] { text-align: right; }
|
|
1484
|
+
.alt-th { position: sticky; top: 0; z-index: 3; padding-block: 9px; font: 500 12.5px/17px var(--font-sans); color: var(--ink-muted); white-space: nowrap; }
|
|
1485
|
+
.alt-td:first-child { position: relative; }
|
|
1486
|
+
.alt-tr { --row-bg: transparent; --row-sh: var(--elev-0); transition: transform var(--dur-travel-1) var(--ease-rise), color var(--dur-travel-2) var(--ease-rise); }
|
|
1487
|
+
.alt-tr > .alt-td:first-child::before, .alt-tr > .alt-th:first-child::before {
|
|
1488
|
+
content: ""; position: absolute; z-index: -1; top: 0; bottom: -1px; left: 0; width: var(--alt-row-w); pointer-events: none;
|
|
1489
|
+
border-radius: var(--radius-md); background: var(--row-bg); box-shadow: var(--row-sh);
|
|
1490
|
+
transition: background-color var(--dur-travel-1) var(--ease-rise), box-shadow var(--dur-travel-1) var(--ease-rise);
|
|
1491
|
+
}
|
|
1492
|
+
.alt-table-wrap[data-top] .alt-table-head .alt-tr { --row-bg: var(--surface-raised); --row-sh: var(--elev-2); }
|
|
1493
|
+
.alt-table-wrap[data-top] .alt-th { border-bottom-color: transparent; }
|
|
1494
|
+
.alt-tr[data-interactive] { cursor: pointer; }
|
|
1495
|
+
.alt-tr[data-interactive]:not([data-row-held]):hover, .alt-tr[data-interactive]:not([data-row-held]):has(.alt-table-rowbtn:focus-visible) { --row-bg: var(--surface-raised); --row-sh: var(--elev-1); transform: translateY(calc(-1px * var(--alt-travel))); }
|
|
1496
|
+
.alt-tr[data-interactive]:not([data-row-held]):active { --row-sh: var(--elev-0); transform: none; transition-duration: var(--dur-press); }
|
|
1497
|
+
.alt-tr[data-row-relevance="match"] { --row-bg: var(--surface-raised); --row-sh: var(--elev-1); }
|
|
1498
|
+
.alt-tr[data-row-relevance="miss"] { --row-bg: var(--surface-well); --row-sh: var(--well); color: var(--ink-muted); }
|
|
1499
|
+
.alt-tr[data-selected] { --row-bg: var(--accent-soft); --row-sh: var(--elev-1); }
|
|
1500
|
+
.alt-tr[data-selected][data-interactive]:not([data-row-held]):hover { --row-bg: var(--accent-soft); --row-sh: var(--elev-2); }
|
|
1501
|
+
.alt-tr[data-row-held] { position: relative; z-index: 5; --row-bg: var(--surface-floating); --row-sh: var(--elev-3); rotate: calc(-0.35deg * var(--alt-travel)); transition: none; }
|
|
1502
|
+
.alt-tr[data-row-held][data-selected] { --row-bg: color-mix(in oklab, var(--accent-soft) 70%, var(--surface-floating)); }
|
|
1503
|
+
.alt-tr[data-row-held]:not([data-following]) { transform: translateY(calc(-3px * var(--alt-travel))); }
|
|
1504
|
+
.alt-tr:is([data-interactive]:hover, [data-selected], [data-row-relevance], [data-row-held]) > .alt-td,
|
|
1505
|
+
.alt-tr:has(+ .alt-tr:is([data-selected], [data-row-relevance], [data-row-held])) > .alt-td { border-bottom-color: transparent; }
|
|
1506
|
+
.alt-tr[data-row-settle="a"] > .alt-td:first-child::before { animation: alt-afterglow-a var(--dur-settle) linear var(--alt-rise-delay, 0ms) backwards; }
|
|
1507
|
+
.alt-tr[data-row-settle="b"] > .alt-td:first-child::before { animation: alt-afterglow-b var(--dur-settle) linear var(--alt-rise-delay, 0ms) backwards; }
|
|
1508
|
+
.alt-table[data-dragging] .alt-tr:not([data-following]) { transition: transform var(--dur-travel-2) var(--ease-settle); }
|
|
1509
|
+
.alt-table-sort {
|
|
1510
|
+
display: inline-flex; align-items: center; gap: 4px; margin: -4px -6px; padding: 4px 6px; border: 0; border-radius: var(--radius-xs);
|
|
1511
|
+
background: none; color: inherit; font: inherit; cursor: pointer; box-shadow: var(--elev-0);
|
|
1512
|
+
transition: background-color var(--dur-travel-1), color var(--dur-travel-1), box-shadow var(--dur-travel-1) var(--ease-rise);
|
|
1513
|
+
}
|
|
1514
|
+
.alt-table-sort:hover { color: var(--ink); background: var(--surface-raised); box-shadow: var(--elev-1); }
|
|
1515
|
+
.alt-table-sort:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1516
|
+
.alt-table-sort:not([data-sort="none"]) { color: var(--ink); }
|
|
1517
|
+
.alt-table-sort-icon { opacity: 0; transition: transform var(--dur-travel-2) var(--ease-settle), opacity var(--dur-travel-1); }
|
|
1518
|
+
.alt-table-sort:hover .alt-table-sort-icon { opacity: 0.45; }
|
|
1519
|
+
.alt-table-sort:not([data-sort="none"]) .alt-table-sort-icon { opacity: 1; }
|
|
1520
|
+
.alt-table-sort[data-sort="descending"] .alt-table-sort-icon { transform: rotate(180deg); }
|
|
1521
|
+
.alt-th[data-align="end"] .alt-table-sort { flex-direction: row-reverse; }
|
|
1522
|
+
.alt-th-check, .alt-td-check { width: 22px; padding-right: 2px; }
|
|
1523
|
+
.alt-th-check .alt-check, .alt-td-check .alt-check { display: inline-flex; vertical-align: middle; }
|
|
1524
|
+
.alt-th-grip, .alt-td-grip { width: 24px; padding-right: 0; }
|
|
1525
|
+
.alt-table-grip { display: inline-grid; place-items: center; width: 24px; height: 28px; margin: -4px 0 -4px -6px; padding: 0; border: 0; border-radius: var(--radius-xs); background: none; color: var(--ink-muted); cursor: grab; touch-action: none; }
|
|
1526
|
+
.alt-table-grip:hover { color: var(--ink); background: color-mix(in oklab, var(--ink) 7%, transparent); }
|
|
1527
|
+
.alt-table-grip:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 1px; }
|
|
1528
|
+
.alt-tr[data-row-held] .alt-table-grip { cursor: grabbing; color: var(--ink); }
|
|
1529
|
+
.alt-table-slot { position: absolute; z-index: -2; left: 0; width: var(--alt-row-w); border-radius: var(--radius-md); background: var(--surface-well); box-shadow: var(--well); outline: 1.5px dashed var(--line-control); outline-offset: -3px; pointer-events: none; transition: top var(--dur-travel-2) var(--ease-settle); }
|
|
1530
|
+
.alt-table-rowbtn { margin: -2px -4px; padding: 2px 4px; border: 0; border-radius: var(--radius-xs); background: none; color: inherit; font: inherit; font-weight: 500; text-align: inherit; cursor: pointer; }
|
|
1531
|
+
.alt-table-rowbtn:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1532
|
+
.alt-table-empty { padding: var(--space-8) var(--space-4); text-align: center; color: var(--ink-muted); }
|
|
1533
|
+
.alt-table-caption { caption-side: bottom; padding-top: var(--space-3); text-align: left; font: 500 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1534
|
+
|
|
1535
|
+
/* ── Board: columns of cards. Columns are receptacles: flush on the ground at rest, so the board reads as its cards;
|
|
1536
|
+
while a card is being carried every column opens into a well (ease-sink), and the one under the card deepens to a
|
|
1537
|
+
trench with an accent rim, as DropZone shows it's ready to receive. Cards are raised (level 1) and lift to level 2
|
|
1538
|
+
on hover. A picked-up card floats at level 3, tilted 1.2° and 1.5% larger,
|
|
1539
|
+
and follows the pointer; the others glide aside and the slot it will land in opens as a trench; dropped, it is carried
|
|
1540
|
+
into place with a settle (ease-settle) while its shadow sinks back to elev-1. A collapsed column is a Pile whose
|
|
1541
|
+
thickness and count say how many cards it holds; it still takes drops, fanning its sheets as a card comes over it.
|
|
1542
|
+
A collaborator's card is held: lifted, outlined in their presence colour, wearing their name. ── */
|
|
1543
|
+
.alt-board { position: relative; display: flex; gap: var(--space-3); align-items: flex-start; overflow-x: auto; padding: var(--space-3) var(--space-1) var(--space-4); scrollbar-width: thin; }
|
|
1544
|
+
.alt-board-col {
|
|
1545
|
+
position: relative; flex: none; width: 264px; display: flex; flex-direction: column; padding: var(--space-2); border-radius: var(--radius-lg);
|
|
1546
|
+
background: transparent; box-shadow: var(--elev-0); outline: 1.5px solid transparent; outline-offset: -1.5px;
|
|
1547
|
+
transition: background-color var(--dur-travel-2) var(--ease-rise), box-shadow var(--dur-travel-2) var(--ease-rise), outline-color var(--dur-travel-1), width var(--dur-travel-3) var(--ease-glide);
|
|
1548
|
+
}
|
|
1549
|
+
.alt-board[data-carrying] .alt-board-col { background: var(--surface-well); box-shadow: var(--well); transition-timing-function: var(--ease-sink); }
|
|
1550
|
+
.alt-board[data-carrying] .alt-board-col[data-over] { background: color-mix(in oklab, var(--accent-soft) 70%, var(--surface-well)); box-shadow: var(--trench); outline-color: var(--accent-ink); }
|
|
1551
|
+
.alt-board-col[data-collapsed] { width: 196px; }
|
|
1552
|
+
.alt-board-head { display: flex; align-items: center; gap: var(--space-2); min-height: 32px; padding: 0 0 var(--space-2) 6px; }
|
|
1553
|
+
.alt-board-title { margin: 0; font: 600 14px/20px var(--font-sans); color: var(--ink); }
|
|
1554
|
+
.alt-board-count { font: 500 12px/1 var(--font-mono); color: var(--ink-muted); }
|
|
1555
|
+
.alt-board-fold { margin-left: auto; color: var(--ink-muted); }
|
|
1556
|
+
.alt-board-fold svg { transition: transform var(--dur-travel-2) var(--ease-settle); }
|
|
1557
|
+
.alt-board-fold[data-collapsed] svg { transform: rotate(-90deg); }
|
|
1558
|
+
.alt-board-list { position: relative; display: flex; flex-direction: column; gap: var(--space-2); min-height: 72px; transition: padding-bottom var(--dur-travel-2) var(--ease-settle); }
|
|
1559
|
+
.alt-board-empty { display: grid; place-items: center; min-height: 72px; border-radius: var(--radius-md); font: 400 13px/18px var(--font-sans); color: var(--ink-muted); }
|
|
1560
|
+
.alt-board-card {
|
|
1561
|
+
position: relative; padding: 10px 12px; border-radius: var(--radius-md); background: var(--surface-raised); box-shadow: var(--elev-1);
|
|
1562
|
+
color: var(--ink); font: 500 14px/20px var(--font-sans); cursor: grab; user-select: none; outline: none;
|
|
1563
|
+
transition: box-shadow var(--dur-travel-1) var(--ease-rise), background-color var(--dur-travel-1), transform var(--dur-travel-2) var(--ease-settle),
|
|
1564
|
+
rotate var(--dur-travel-2) var(--ease-settle), scale var(--dur-travel-2) var(--ease-settle);
|
|
1565
|
+
}
|
|
1566
|
+
.alt-board-card:hover:not([data-carried]):not([data-held]) { box-shadow: var(--elev-2); }
|
|
1567
|
+
.alt-board-card:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
|
|
1568
|
+
.alt-board-card[data-carried] { z-index: 10; cursor: grabbing; background: var(--surface-floating); box-shadow: var(--elev-3); rotate: calc(-1.2deg * var(--alt-travel)); scale: calc(1 + 0.015 * var(--alt-travel)); }
|
|
1569
|
+
.alt-board-card[data-carried]:not([data-following]) { transform: translateY(calc(-3px * var(--alt-travel))); }
|
|
1570
|
+
.alt-board-card[data-following] { transition: box-shadow var(--dur-travel-1), background-color var(--dur-travel-1), rotate var(--dur-travel-2) var(--ease-settle), scale var(--dur-travel-2) var(--ease-settle); }
|
|
1571
|
+
.alt-board-card[data-landing] { transition-duration: var(--dur-travel-2); transition-timing-function: var(--ease-settle); }
|
|
1572
|
+
.alt-board-card[data-held] { cursor: not-allowed; box-shadow: var(--elev-3); transform: translateY(calc(-2px * var(--alt-travel))) rotate(calc(-0.5deg * var(--alt-travel))); }
|
|
1573
|
+
.alt-board-card[data-held-by] { outline: 2px solid var(--alt-presence); outline-offset: 2px; }
|
|
1574
|
+
.alt-board-card small { display: block; margin-top: 4px; font: 400 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1575
|
+
.alt-board-slot { position: absolute; left: 0; right: 0; border-radius: var(--radius-md); background: var(--surface-trench); box-shadow: var(--trench); outline: 1.5px dashed var(--line-control); outline-offset: -3px; pointer-events: none; transition: top var(--dur-travel-2) var(--ease-settle); }
|
|
1576
|
+
.alt-board-pile { margin: 2px 2px 0; }
|
|
1577
|
+
.alt-board-pile-face { display: flex; flex-direction: column; gap: 2px; padding: 12px; font: 600 14px/20px var(--font-sans); color: var(--ink); }
|
|
1578
|
+
.alt-board-pile-face span { font: 400 12.5px/17px var(--font-sans); color: var(--ink-muted); }
|
|
1579
|
+
.alt-board[data-carrying] .alt-board-col[data-over] .alt-pile-sheet { --fan: var(--alt-travel); }
|
|
1580
|
+
|
|
1581
|
+
/* ── HoverCard: a richer preview than a Tooltip, rising from its trigger at level 3 like Popover (6px from 96%, its
|
|
1582
|
+
shadow growing to elev-3). It opens after the pointer rests 400ms (hover intent) or on keyboard focus, and waits
|
|
1583
|
+
250ms after the pointer leaves; an invisible bridge spans the gap so the pointer can travel into it. It shares
|
|
1584
|
+
Tooltip's warm-up between neighbours. ── */
|
|
1585
|
+
.alt-hovercard { width: 300px; min-width: 0; padding: var(--space-4); }
|
|
1586
|
+
.alt-hovercard::before { content: ""; position: absolute; left: 0; right: 0; height: 12px; }
|
|
1587
|
+
.alt-hovercard:not([data-side="top"])::before { bottom: 100%; }
|
|
1588
|
+
.alt-hovercard[data-side="top"]::before { top: 100%; }
|
|
1589
|
+
|
|
1590
|
+
/* ── Ephemeral adaptation in menus: predicted items arrive at once; the rest fade in over dur-onset. ── */
|
|
1591
|
+
.alt-menu[data-ephemeral][data-state="open"] .alt-menu-item:not([data-predicted]) { transition: opacity var(--dur-onset) linear, transform var(--dur-onset) var(--ease-rise); transition-delay: 0ms; }
|
|
1592
|
+
.alt-menu[data-ephemeral][data-state="open"] .alt-menu-item[data-predicted], .alt-menu[data-ephemeral][data-state="open"] .alt-menu-label { transition-duration: var(--dur-travel-1); transition-delay: 0ms; }
|
|
1593
|
+
|
|
1594
|
+
/* ════════════════════ Accessible elevation ════════════════════ */
|
|
1595
|
+
|
|
1596
|
+
/* High contrast: elevation becomes a hard slab whose thickness is the height (1 level = 1px more),
|
|
1597
|
+
with a solid ink edge. Same four-layer structure, so it still animates. */
|
|
1598
|
+
@media (prefers-contrast: more) {
|
|
1599
|
+
:root, [data-theme] {
|
|
1600
|
+
--elev-0: inset 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000;
|
|
1601
|
+
--elev-1: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 2px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1602
|
+
--elev-2: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 3px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1603
|
+
--elev-3: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 4px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1604
|
+
--elev-4: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 5px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1605
|
+
--elev-5: inset 0 0 0 0 #0000, 0 0 0 2px var(--ink), 0 7px 0 2px var(--ink), 0 0 0 0 #0000;
|
|
1606
|
+
--well: inset 0 2px 0 0 var(--ink-muted), 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000;
|
|
1607
|
+
--trench: inset 0 4px 0 0 var(--ink-muted), 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000;
|
|
1608
|
+
--line: var(--line-control); --alt-sheen: none;
|
|
1609
|
+
--alt-ring: var(--ink); --alt-cast: transparent; --alt-cast-deep: transparent; --alt-wall-in: var(--ink-muted); --alt-lip: transparent; --alt-rim-held: var(--ink);
|
|
1610
|
+
}
|
|
1611
|
+
.alt-btn, .alt-kbd, .alt-crumbs button { --wall-c: var(--ink); }
|
|
1612
|
+
.alt-empty { border-style: solid; }
|
|
1613
|
+
}
|
|
1614
|
+
[data-contrast="more"], [data-contrast="more"] [data-theme] {
|
|
1615
|
+
--elev-0: inset 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000;
|
|
1616
|
+
--elev-1: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 2px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1617
|
+
--elev-2: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 3px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1618
|
+
--elev-3: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 4px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1619
|
+
--elev-4: inset 0 0 0 0 #0000, 0 0 0 1px var(--ink), 0 5px 0 1px var(--ink), 0 0 0 0 #0000;
|
|
1620
|
+
--elev-5: inset 0 0 0 0 #0000, 0 0 0 2px var(--ink), 0 7px 0 2px var(--ink), 0 0 0 0 #0000;
|
|
1621
|
+
--well: inset 0 2px 0 0 var(--ink-muted), 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000;
|
|
1622
|
+
--trench: inset 0 4px 0 0 var(--ink-muted), 0 0 0 0 #0000, 0 0 0 0 #0000, 0 0 0 0 #0000;
|
|
1623
|
+
--line: var(--line-control); --alt-sheen: none;
|
|
1624
|
+
--alt-ring: var(--ink); --alt-cast: transparent; --alt-cast-deep: transparent; --alt-wall-in: var(--ink-muted); --alt-lip: transparent; --alt-rim-held: var(--ink);
|
|
1625
|
+
}
|
|
1626
|
+
[data-contrast="more"] .alt-btn, [data-contrast="more"] .alt-kbd, [data-contrast="more"] .alt-crumbs button { --wall-c: var(--ink); }
|
|
1627
|
+
[data-contrast="more"] .alt-empty { border-style: solid; }
|
|
1628
|
+
|
|
1629
|
+
/* Forced colours (Windows High Contrast) drop every box-shadow, which erases elevation entirely
|
|
1630
|
+
(measured: the ladder renders as blank). Height falls back to border weight and style. */
|
|
1631
|
+
@media (forced-colors: active) {
|
|
1632
|
+
.alt-surface[data-level="1"], .alt-surface[data-level="2"], .alt-card, .alt-btn:not([data-variant="ghost"]), .alt-tabs-indicator,
|
|
1633
|
+
.alt-switch-thumb, .alt-slider-thumb, .alt-kbd, .alt-avatar-face, .alt-sort-item, .alt-pile-top, .alt-pile-sheet, .alt-scroll { border: 1px solid CanvasText; }
|
|
1634
|
+
.alt-surface[data-level="3"], .alt-surface[data-level="4"], .alt-pop, .alt-tip, .alt-toast, .alt-sort-item[data-held], [data-held] { border: 2px solid CanvasText; }
|
|
1635
|
+
.alt-surface[data-level="5"], .alt-dialog { border: 4px double CanvasText; }
|
|
1636
|
+
.alt-input:has(input:not(:placeholder-shown)), .alt-input:has(textarea:not(:placeholder-shown)) { border-style: solid !important; }
|
|
1637
|
+
.alt-input[data-invalid] { border: 2px dashed CanvasText !important; }
|
|
1638
|
+
.alt-surface[data-level="-1"], .alt-input, .alt-tabs-list, .alt-sort-slot, .alt-drop[data-drop="armed"], .alt-empty { border: 1px dashed CanvasText; }
|
|
1639
|
+
.alt-surface[data-level="-2"], .alt-switch, .alt-slider-track, .alt-progress, [data-status="failed"], .alt-drop[data-drop="over"] { border: 2px dashed CanvasText; }
|
|
1640
|
+
[data-status="pending"] { border: 2px dotted CanvasText; }
|
|
1641
|
+
.alt-progress-fill, .alt-slider-fill, .alt-switch-fill, .alt-check-fill { background: Highlight; }
|
|
1642
|
+
.alt-check-track { border: 2px dashed CanvasText; } .alt-radio-thumb { border: 1px solid CanvasText; } .alt-check-mark { color: Canvas; filter: none; }
|
|
1643
|
+
.alt-pile-item { border: 1px solid CanvasText; }
|
|
1644
|
+
.alt-alert, .alt-alert-sheet, .alt-badge { border: 1px solid CanvasText; } .alt-alert[data-variant="raised"], .alt-badge[data-variant="count"] { border: 2px solid CanvasText; }
|
|
1645
|
+
.alt-badge-lamp, .alt-avatar-lamp { border: 1px solid CanvasText; }
|
|
1646
|
+
.alt-tabs[data-variant="folder"] .alt-tabs-trigger[aria-selected="true"] { border: 2px solid CanvasText; border-bottom: 0; }
|
|
1647
|
+
.alt-tabs[data-variant="folder"] > .alt-tabs-content { border: 1px solid CanvasText; }
|
|
1648
|
+
.alt-acc-item[data-state="open"] { border: 1px solid CanvasText; } .alt-acc-content { border: 1px dashed CanvasText; }
|
|
1649
|
+
.alt-crumbs button { border: 1px solid CanvasText; } .alt-crumbs li[data-current] button { border-width: 2px; }
|
|
1650
|
+
.alt-cmd { border: 4px double CanvasText; } .alt-cmd-hl { display: none; } .alt-cmd-item[aria-selected="true"] { outline: 2px solid Highlight; outline-offset: -2px; }
|
|
1651
|
+
.alt-sheet { border: 2px solid CanvasText; } .alt-sheet-pull { border: 1px dashed CanvasText; }
|
|
1652
|
+
.alt-input[data-filled]:not([data-invalid]) { border-style: solid !important; }
|
|
1653
|
+
.alt-select-option[data-active] { outline: 2px solid Highlight; outline-offset: -2px; } .alt-select-tick { color: CanvasText; }
|
|
1654
|
+
.alt-tr:is([data-selected], [data-row-relevance="match"], [data-interactive]:hover) > .alt-td { border-block: 1px solid CanvasText; } .alt-tr[data-row-relevance="miss"] > .alt-td { border-bottom: 1px dashed CanvasText; }
|
|
1655
|
+
.alt-board-card { border: 1px solid CanvasText; } .alt-board-card[data-carried] { border-width: 2px; } .alt-board[data-carrying] .alt-board-col { border: 1px dashed CanvasText; } .alt-board[data-carrying] .alt-board-col[data-over] { border: 2px dashed Highlight; } .alt-board-slot { outline-color: CanvasText; }
|
|
1656
|
+
.alt-tr[data-row-held] > .alt-td { border-block: 2px solid CanvasText; } .alt-table-slot { outline-color: CanvasText; } .alt-table-wrap[data-top] .alt-th { border-bottom: 1px solid CanvasText; }
|
|
1657
|
+
.alt-step[data-state="current"] { border: 1px solid CanvasText; } .alt-step[data-state="upcoming"] { border: 1px dashed CanvasText; } .alt-step-mark { border: 1px solid CanvasText; } .alt-step-line[data-done] { background: Highlight; }
|
|
1658
|
+
.alt-avatar[data-status="offline"] .alt-avatar-face { border: 1px dashed CanvasText; } .alt-avatar[data-status="active"] .alt-avatar-face { border: 2px solid CanvasText; }
|
|
1659
|
+
}
|