@webority/theme 0.2.0 → 0.4.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 -29
- package/dist/webority-theme.css +1 -1
- package/package.json +2 -2
- package/scss/_components.scss +42 -0
- package/scss/_variables.scss +17 -0
- package/scss/_wui-components.scss +20 -3648
- package/scss/wui/_card.scss +37 -0
- package/scss/wui/_choice.scss +746 -0
- package/scss/wui/_controls.scss +808 -0
- package/scss/wui/_data.scss +614 -0
- package/scss/wui/_disclosure.scss +113 -0
- package/scss/wui/_display.scss +508 -0
- package/scss/wui/_flow.scss +410 -0
- package/scss/wui/_media.scss +569 -0
- package/scss/wui/_navigation.scss +284 -0
- package/scss/wui/_overlays.scss +350 -0
- package/scss/wui/_shell.scss +474 -0
- package/scss/wui/_typography.scss +275 -0
- package/scss/wui/_utilities.scss +340 -0
|
@@ -14,3652 +14,24 @@
|
|
|
14
14
|
//
|
|
15
15
|
// Plain CSS is valid SCSS; nothing here has been re-nested or renamed.
|
|
16
16
|
// ============================================================================
|
|
17
|
-
|
|
18
|
-
// ── Checkbox & Radio ──
|
|
19
|
-
// Selection controls: a 20px glyph centred in a 36px circular hit area
|
|
20
|
-
// that shows a soft primary-tinted ripple on hover. Unchecked = muted
|
|
21
|
-
// grey-blue outline; checked = solid primary. Checkbox = squircle box + white
|
|
22
|
-
// tick; radio = ring + filled centre dot. Pure CSS, no JS — drives the native
|
|
23
|
-
// input via `appearance: none`, so it stays keyboard- and screen-reader-
|
|
24
|
-
// accessible.
|
|
25
17
|
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
gap: 8px 20px;
|
|
47
|
-
}
|
|
48
|
-
.lx-control-label {
|
|
49
|
-
padding-right: 2px;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// The control glyph: 20px box inside a 36px circular tap target (8px ring).
|
|
53
|
-
.lx-check,
|
|
54
|
-
.lx-radio {
|
|
55
|
-
appearance: none;
|
|
56
|
-
-webkit-appearance: none;
|
|
57
|
-
flex: none;
|
|
58
|
-
box-sizing: border-box;
|
|
59
|
-
width: 20px;
|
|
60
|
-
height: 20px;
|
|
61
|
-
// 8px transparent ring → 36px hit area + room for the hover ripple
|
|
62
|
-
margin: 8px;
|
|
63
|
-
position: relative;
|
|
64
|
-
border: 1.6px solid var(--color-border-strong);
|
|
65
|
-
background: transparent;
|
|
66
|
-
cursor: pointer;
|
|
67
|
-
transition:
|
|
68
|
-
border-color 0.15s ease,
|
|
69
|
-
background-color 0.15s ease;
|
|
70
|
-
}
|
|
71
|
-
.lx-check {
|
|
72
|
-
border-radius: var(--radius-sm);
|
|
73
|
-
corner-shape: squircle;
|
|
74
|
-
}
|
|
75
|
-
.lx-radio {
|
|
76
|
-
border-radius: 50%;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Soft primary circular ripple behind the glyph on hover (the Minimals halo).
|
|
80
|
-
.lx-check::after,
|
|
81
|
-
.lx-radio::after {
|
|
82
|
-
content: "";
|
|
83
|
-
position: absolute;
|
|
84
|
-
left: 50%;
|
|
85
|
-
top: 50%;
|
|
86
|
-
width: 36px;
|
|
87
|
-
height: 36px;
|
|
88
|
-
border-radius: 50%;
|
|
89
|
-
transform: translate(-50%, -50%) scale(0.5);
|
|
90
|
-
background: var(--color-primary-soft);
|
|
91
|
-
opacity: 0;
|
|
92
|
-
z-index: -1;
|
|
93
|
-
pointer-events: none;
|
|
94
|
-
transition:
|
|
95
|
-
opacity 0.15s ease,
|
|
96
|
-
transform 0.15s ease;
|
|
97
|
-
}
|
|
98
|
-
.lx-control:hover .lx-check::after,
|
|
99
|
-
.lx-control:hover .lx-radio::after,
|
|
100
|
-
.lx-check:hover::after,
|
|
101
|
-
.lx-radio:hover::after {
|
|
102
|
-
opacity: 1;
|
|
103
|
-
transform: translate(-50%, -50%) scale(1);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Checked — primary fill (checkbox) / primary ring + dot (radio)
|
|
107
|
-
.lx-check:checked {
|
|
108
|
-
border-color: var(--color-primary);
|
|
109
|
-
background: var(--color-primary);
|
|
110
|
-
// white tick drawn with a rotated box-shadow-free pseudo
|
|
111
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E");
|
|
112
|
-
background-size: 15px 15px;
|
|
113
|
-
background-position: center;
|
|
114
|
-
background-repeat: no-repeat;
|
|
115
|
-
}
|
|
116
|
-
.lx-radio:checked {
|
|
117
|
-
border-color: var(--color-primary);
|
|
118
|
-
}
|
|
119
|
-
.lx-radio:checked::before {
|
|
120
|
-
content: "";
|
|
121
|
-
position: absolute;
|
|
122
|
-
left: 50%;
|
|
123
|
-
top: 50%;
|
|
124
|
-
width: 10px;
|
|
125
|
-
height: 10px;
|
|
126
|
-
border-radius: 50%;
|
|
127
|
-
background: var(--color-primary);
|
|
128
|
-
transform: translate(-50%, -50%);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Keyboard focus ring (only on focus-visible, not mouse)
|
|
132
|
-
.lx-check:focus-visible,
|
|
133
|
-
.lx-radio:focus-visible {
|
|
134
|
-
outline: none;
|
|
135
|
-
box-shadow: 0 0 0 3px var(--color-primary-soft);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Disabled
|
|
139
|
-
.lx-check:disabled,
|
|
140
|
-
.lx-radio:disabled,
|
|
141
|
-
.lx-control:has(:disabled) {
|
|
142
|
-
cursor: not-allowed;
|
|
143
|
-
}
|
|
144
|
-
.lx-check:disabled,
|
|
145
|
-
.lx-radio:disabled {
|
|
146
|
-
border-color: var(--color-border);
|
|
147
|
-
background-color: var(--color-bg-muted);
|
|
148
|
-
}
|
|
149
|
-
.lx-check:disabled:checked,
|
|
150
|
-
.lx-radio:disabled:checked {
|
|
151
|
-
border-color: var(--color-border-strong);
|
|
152
|
-
}
|
|
153
|
-
.lx-check:disabled:checked {
|
|
154
|
-
background-color: var(--color-border-strong);
|
|
155
|
-
}
|
|
156
|
-
.lx-radio:disabled:checked::before {
|
|
157
|
-
background: var(--color-border-strong);
|
|
158
|
-
}
|
|
159
|
-
.lx-control:has(:disabled) {
|
|
160
|
-
color: var(--color-text-subtle);
|
|
161
|
-
}
|
|
162
|
-
.lx-check:disabled::after,
|
|
163
|
-
.lx-radio:disabled::after {
|
|
164
|
-
display: none;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
@media (prefers-reduced-motion: reduce) {
|
|
168
|
-
.lx-check,
|
|
169
|
-
.lx-radio,
|
|
170
|
-
.lx-check::after,
|
|
171
|
-
.lx-radio::after {
|
|
172
|
-
transition: none;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Row-selection checkbox variant used inside a .table-ledger select column.
|
|
177
|
-
.lx-check {
|
|
178
|
-
width: 16px;
|
|
179
|
-
height: 16px;
|
|
180
|
-
accent-color: var(--color-primary);
|
|
181
|
-
cursor: pointer;
|
|
182
|
-
vertical-align: middle;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// ── Field / Input ──
|
|
186
|
-
// Inputs — always-white fill, 16px squircle, soft brand border tint on focus
|
|
187
|
-
// (no glow).
|
|
188
|
-
.input,
|
|
189
|
-
.select,
|
|
190
|
-
.textarea {
|
|
191
|
-
box-sizing: border-box;
|
|
192
|
-
width: 100%;
|
|
193
|
-
height: var(--wui-control-height);
|
|
194
|
-
padding: 12px;
|
|
195
|
-
border-radius: var(--radius);
|
|
196
|
-
border: 1px solid var(--color-border);
|
|
197
|
-
background: var(--color-surface);
|
|
198
|
-
font-size: 14px;
|
|
199
|
-
line-height: 1.5;
|
|
200
|
-
color: var(--color-text);
|
|
201
|
-
transition:
|
|
202
|
-
border-color 0.12s,
|
|
203
|
-
box-shadow 0.12s;
|
|
204
|
-
font-family: inherit;
|
|
205
|
-
}
|
|
206
|
-
.textarea {
|
|
207
|
-
height: auto;
|
|
208
|
-
min-height: 120px;
|
|
209
|
-
padding: 12px 15px 16px;
|
|
210
|
-
line-height: 1.5;
|
|
211
|
-
resize: vertical;
|
|
212
|
-
}
|
|
213
|
-
.input:hover:not(:focus):not(:disabled),
|
|
214
|
-
.select:hover:not(:focus):not(:disabled),
|
|
215
|
-
.textarea:hover:not(:focus):not(:disabled) {
|
|
216
|
-
background-color: var(--color-bg-muted);
|
|
217
|
-
border-color: var(--color-border-strong);
|
|
218
|
-
}
|
|
219
|
-
.input:focus,
|
|
220
|
-
.select:focus,
|
|
221
|
-
.textarea:focus {
|
|
222
|
-
outline: none;
|
|
223
|
-
background-color: var(--color-bg-muted);
|
|
224
|
-
color: var(--color-text);
|
|
225
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
226
|
-
box-shadow: none;
|
|
227
|
-
}
|
|
228
|
-
// Textarea renders as .form-control.textarea (react-bootstrap). Match the
|
|
229
|
-
// shared theme's .form-control:hover specificity so it hovers to
|
|
230
|
-
// --color-border-strong too.
|
|
231
|
-
textarea.textarea.form-control:hover:not(:focus):not(:disabled):not([readonly]) {
|
|
232
|
-
border-color: var(--color-border-strong);
|
|
233
|
-
}
|
|
234
|
-
textarea.textarea:focus {
|
|
235
|
-
outline: none;
|
|
236
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
237
|
-
box-shadow: none;
|
|
238
|
-
}
|
|
239
|
-
.input::placeholder,
|
|
240
|
-
.textarea::placeholder {
|
|
241
|
-
color: var(--color-text-subtle);
|
|
242
|
-
}
|
|
243
|
-
// Edge/IE add a native password reveal (and clear) button — hide them so only
|
|
244
|
-
// the app's own eye toggle shows.
|
|
245
|
-
.input::-ms-reveal,
|
|
246
|
-
.input::-ms-clear {
|
|
247
|
-
display: none;
|
|
248
|
-
}
|
|
249
|
-
.input:disabled,
|
|
250
|
-
.select:disabled,
|
|
251
|
-
.textarea:disabled {
|
|
252
|
-
background: var(--color-bg-muted);
|
|
253
|
-
border-color: var(--color-border);
|
|
254
|
-
color: var(--color-text-subtle);
|
|
255
|
-
cursor: not-allowed;
|
|
256
|
-
}
|
|
257
|
-
.field:has(.input:disabled) .label {
|
|
258
|
-
color: var(--color-text-subtle);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Read-only inputs: darker muted fill to signal non-editable.
|
|
262
|
-
.input[readonly],
|
|
263
|
-
.select[readonly],
|
|
264
|
-
.textarea[readonly] {
|
|
265
|
-
background: var(--color-bg-muted);
|
|
266
|
-
color: var(--color-text-muted);
|
|
267
|
-
cursor: not-allowed;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Invalid field state (required-field validation) — soft danger-tinted
|
|
271
|
-
// border on the surface.
|
|
272
|
-
// `[aria-invalid="true"]` is styled alongside `.is-invalid`: React sets the ARIA
|
|
273
|
-
// attribute (it is the accessible source of truth) and does not always add the
|
|
274
|
-
// Bootstrap class, so keying on the class alone left React error states unstyled.
|
|
275
|
-
.input.is-invalid,
|
|
276
|
-
.select.is-invalid,
|
|
277
|
-
.textarea.is-invalid,
|
|
278
|
-
.input.is-invalid:focus,
|
|
279
|
-
.select.is-invalid:focus,
|
|
280
|
-
.textarea.is-invalid:focus,
|
|
281
|
-
.input[aria-invalid="true"],
|
|
282
|
-
.select[aria-invalid="true"],
|
|
283
|
-
.textarea[aria-invalid="true"],
|
|
284
|
-
.input[aria-invalid="true"]:focus,
|
|
285
|
-
.select[aria-invalid="true"]:focus,
|
|
286
|
-
.textarea[aria-invalid="true"]:focus {
|
|
287
|
-
background: var(--color-surface);
|
|
288
|
-
border-color: color-mix(in srgb, var(--color-danger) 45%, var(--color-surface));
|
|
289
|
-
box-shadow: none;
|
|
290
|
-
}
|
|
291
|
-
.input.is-invalid,
|
|
292
|
-
.input[aria-invalid="true"] {
|
|
293
|
-
padding-right: 41px;
|
|
294
|
-
}
|
|
295
|
-
.field-error {
|
|
296
|
-
font-size: 12px;
|
|
297
|
-
line-height: normal;
|
|
298
|
-
color: var(--color-danger);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Native select with a rounded squircle, custom chevron, off-surface fill.
|
|
302
|
-
.select {
|
|
303
|
-
appearance: none;
|
|
304
|
-
-webkit-appearance: none;
|
|
305
|
-
padding-right: 40px;
|
|
306
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19.92 8.95l-6.52 6.52c-.77.77-2.03.77-2.8 0L4.08 8.95' fill='none' stroke='%234B5675' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10'/%3E%3C/svg%3E");
|
|
307
|
-
background-repeat: no-repeat;
|
|
308
|
-
background-position: right 14px center;
|
|
309
|
-
background-size: 16px;
|
|
310
|
-
cursor: pointer;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Date inputs — a brand calendar glyph that fills the field so a click
|
|
314
|
-
// anywhere opens the native picker; muted text until a value is chosen.
|
|
315
|
-
.input[type="date"] {
|
|
316
|
-
position: relative;
|
|
317
|
-
cursor: pointer;
|
|
318
|
-
}
|
|
319
|
-
.input[type="date"]:not(.has-value):not(:focus) {
|
|
320
|
-
color: var(--color-text-subtle);
|
|
321
|
-
}
|
|
322
|
-
.input[type="date"]::-webkit-calendar-picker-indicator {
|
|
323
|
-
position: absolute;
|
|
324
|
-
inset: 0;
|
|
325
|
-
width: auto;
|
|
326
|
-
height: auto;
|
|
327
|
-
margin: 0;
|
|
328
|
-
padding: 0;
|
|
329
|
-
cursor: pointer;
|
|
330
|
-
opacity: 0;
|
|
331
|
-
}
|
|
332
|
-
.input[type="date"]::-webkit-datetime-edit {
|
|
333
|
-
padding-right: 28px;
|
|
334
|
-
}
|
|
335
|
-
.input-date-wrap {
|
|
336
|
-
position: relative;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Number input: hide the native spinner so a custom stepper can be rendered.
|
|
340
|
-
.input[type="number"]::-webkit-inner-spin-button,
|
|
341
|
-
.input[type="number"]::-webkit-outer-spin-button {
|
|
342
|
-
-webkit-appearance: none;
|
|
343
|
-
margin: 0;
|
|
344
|
-
}
|
|
345
|
-
.input[type="number"] {
|
|
346
|
-
-moz-appearance: textfield;
|
|
347
|
-
appearance: textfield;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// Custom number stepper — up/down arrows, no background.
|
|
351
|
-
.num-stepper {
|
|
352
|
-
position: relative;
|
|
353
|
-
width: 100%;
|
|
354
|
-
}
|
|
355
|
-
.field > .num-stepper {
|
|
356
|
-
align-self: stretch;
|
|
357
|
-
}
|
|
358
|
-
.num-stepper .input {
|
|
359
|
-
width: 100%;
|
|
360
|
-
padding-right: 36px;
|
|
361
|
-
}
|
|
362
|
-
.num-stepper-btns {
|
|
363
|
-
position: absolute;
|
|
364
|
-
top: 50%;
|
|
365
|
-
right: 8px;
|
|
366
|
-
transform: translateY(-50%);
|
|
367
|
-
display: flex;
|
|
368
|
-
flex-direction: column;
|
|
369
|
-
gap: 0;
|
|
370
|
-
}
|
|
371
|
-
.num-stepper-btns button {
|
|
372
|
-
display: grid;
|
|
373
|
-
place-items: center;
|
|
374
|
-
width: 20px;
|
|
375
|
-
height: 15px;
|
|
376
|
-
border: none;
|
|
377
|
-
background: transparent;
|
|
378
|
-
padding: 0;
|
|
379
|
-
cursor: pointer;
|
|
380
|
-
color: var(--color-text-muted);
|
|
381
|
-
}
|
|
382
|
-
.num-stepper-btns button:hover {
|
|
383
|
-
color: var(--color-text);
|
|
384
|
-
}
|
|
385
|
-
.num-stepper-btns button:active {
|
|
386
|
-
color: var(--color-primary);
|
|
387
|
-
}
|
|
388
|
-
.input-date-wrap > .input {
|
|
389
|
-
padding-right: 38px;
|
|
390
|
-
}
|
|
391
|
-
.input-date-icon {
|
|
392
|
-
position: absolute;
|
|
393
|
-
right: 12px;
|
|
394
|
-
top: 50%;
|
|
395
|
-
transform: translateY(-50%);
|
|
396
|
-
color: var(--color-text-muted);
|
|
397
|
-
pointer-events: none;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// Error state — danger-tinted border + room for a trailing affix.
|
|
401
|
-
.input.error,
|
|
402
|
-
.input.error:focus,
|
|
403
|
-
.textarea.error,
|
|
404
|
-
.textarea.error:focus {
|
|
405
|
-
background: var(--color-surface);
|
|
406
|
-
border-color: color-mix(in srgb, var(--color-danger) 45%, var(--color-surface));
|
|
407
|
-
box-shadow: none;
|
|
408
|
-
}
|
|
409
|
-
.input.error {
|
|
410
|
-
padding-right: 41px;
|
|
411
|
-
}
|
|
412
|
-
// Dark mode: keep the value in an errored field legible.
|
|
413
|
-
:root[data-theme="dark"] .input.error,
|
|
414
|
-
:root[data-theme="dark"] .input.error:focus,
|
|
415
|
-
:root[data-theme="dark"] .input.error:-webkit-autofill,
|
|
416
|
-
:root[data-theme="dark"] .input.error:focus:-webkit-autofill {
|
|
417
|
-
color: var(--color-text);
|
|
418
|
-
-webkit-text-fill-color: var(--color-text);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// Field-relative wrap for trailing affixes (error icon, password toggle).
|
|
422
|
-
.input-wrap {
|
|
423
|
-
position: relative;
|
|
424
|
-
width: 100%;
|
|
425
|
-
align-self: stretch;
|
|
426
|
-
}
|
|
427
|
-
.input-wrap .input {
|
|
428
|
-
width: 100%;
|
|
429
|
-
}
|
|
430
|
-
.input-affix {
|
|
431
|
-
position: absolute;
|
|
432
|
-
right: 14px;
|
|
433
|
-
top: 22.5px;
|
|
434
|
-
transform: translateY(-50%);
|
|
435
|
-
display: grid;
|
|
436
|
-
place-items: center;
|
|
437
|
-
pointer-events: none;
|
|
438
|
-
color: var(--color-danger);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// Leading-icon input — icon turns brand on focus.
|
|
442
|
-
.input-icon {
|
|
443
|
-
position: relative;
|
|
444
|
-
display: flex;
|
|
445
|
-
align-items: center;
|
|
446
|
-
width: 100%;
|
|
447
|
-
}
|
|
448
|
-
.input-icon > .ic {
|
|
449
|
-
position: absolute;
|
|
450
|
-
left: 13px;
|
|
451
|
-
top: 50%;
|
|
452
|
-
transform: translateY(-50%);
|
|
453
|
-
display: grid;
|
|
454
|
-
place-items: center;
|
|
455
|
-
color: var(--color-text-subtle);
|
|
456
|
-
pointer-events: none;
|
|
457
|
-
}
|
|
458
|
-
.input-icon .input {
|
|
459
|
-
padding-left: 40px;
|
|
460
|
-
}
|
|
461
|
-
.input-icon:focus-within > .ic {
|
|
462
|
-
color: var(--color-primary);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// Password reveal toggle (place inside .input-wrap).
|
|
466
|
-
.input.pw {
|
|
467
|
-
padding-right: 44px;
|
|
468
|
-
}
|
|
469
|
-
.input.pw[type="password"]::placeholder {
|
|
470
|
-
letter-spacing: normal;
|
|
471
|
-
color: var(--color-text-subtle);
|
|
472
|
-
}
|
|
473
|
-
.pw-toggle {
|
|
474
|
-
position: absolute;
|
|
475
|
-
right: 7px;
|
|
476
|
-
top: 22px;
|
|
477
|
-
transform: translateY(-50%);
|
|
478
|
-
display: grid;
|
|
479
|
-
place-items: center;
|
|
480
|
-
width: 32px;
|
|
481
|
-
height: 32px;
|
|
482
|
-
border: none;
|
|
483
|
-
background: transparent;
|
|
484
|
-
color: var(--color-text-subtle);
|
|
485
|
-
border-radius: var(--radius);
|
|
486
|
-
cursor: pointer;
|
|
487
|
-
transition:
|
|
488
|
-
color 0.12s ease,
|
|
489
|
-
background 0.12s ease;
|
|
490
|
-
}
|
|
491
|
-
.pw-toggle:hover {
|
|
492
|
-
color: var(--color-primary);
|
|
493
|
-
background: transparent;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
.hint,
|
|
497
|
-
.field-hint {
|
|
498
|
-
margin-top: 2px;
|
|
499
|
-
font-size: 12px;
|
|
500
|
-
color: var(--color-text-subtle);
|
|
501
|
-
}
|
|
502
|
-
.label {
|
|
503
|
-
display: block;
|
|
504
|
-
font-size: 14px;
|
|
505
|
-
line-height: normal;
|
|
506
|
-
font-weight: 500;
|
|
507
|
-
color: var(--color-text);
|
|
508
|
-
margin-bottom: 6px;
|
|
509
|
-
}
|
|
510
|
-
.label-hint {
|
|
511
|
-
color: var(--color-text-subtle);
|
|
512
|
-
font-weight: 400;
|
|
513
|
-
margin-left: 6px;
|
|
514
|
-
font-size: 12px;
|
|
515
|
-
}
|
|
516
|
-
.label-optional {
|
|
517
|
-
font-weight: 400;
|
|
518
|
-
font-size: 14px;
|
|
519
|
-
color: var(--color-text-subtle);
|
|
520
|
-
}
|
|
521
|
-
.required {
|
|
522
|
-
color: var(--color-danger);
|
|
523
|
-
}
|
|
524
|
-
.field {
|
|
525
|
-
display: flex;
|
|
526
|
-
flex-direction: column;
|
|
527
|
-
align-items: flex-start;
|
|
528
|
-
gap: 6px;
|
|
529
|
-
margin-bottom: 16px;
|
|
530
|
-
}
|
|
531
|
-
.field > .label,
|
|
532
|
-
.field label {
|
|
533
|
-
margin-bottom: 0;
|
|
534
|
-
}
|
|
535
|
-
.field-row {
|
|
536
|
-
display: grid;
|
|
537
|
-
grid-template-columns: 1fr 1fr;
|
|
538
|
-
gap: 16px;
|
|
539
|
-
margin-bottom: 16px;
|
|
540
|
-
}
|
|
541
|
-
.field-row-3 {
|
|
542
|
-
grid-template-columns: 1fr 1fr 1fr;
|
|
543
|
-
}
|
|
544
|
-
// min-width:0 — grid/flex items default to min-width:auto, which lets a long
|
|
545
|
-
// control (e.g. a search-select label) push its track past 1fr and defeat
|
|
546
|
-
// text truncation. Reset to 0 so the ellipsis engages instead of overflowing.
|
|
547
|
-
.field-row .field {
|
|
548
|
-
margin-bottom: 0;
|
|
549
|
-
min-width: 0;
|
|
550
|
-
}
|
|
551
|
-
// Controls fill their field even though .field aligns children flex-start.
|
|
552
|
-
.field > .search-select,
|
|
553
|
-
.field > .input-with-unit,
|
|
554
|
-
.field > .input,
|
|
555
|
-
.field > .datepicker,
|
|
556
|
-
.field > .field-error {
|
|
557
|
-
align-self: stretch;
|
|
558
|
-
}
|
|
559
|
-
@media (max-width: 575.98px) {
|
|
560
|
-
.field-row,
|
|
561
|
-
.field-row-3 {
|
|
562
|
-
grid-template-columns: 1fr;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// red border around a non-input group (e.g. a structure-form card row)
|
|
567
|
-
.group-invalid {
|
|
568
|
-
border: 1px solid var(--color-danger);
|
|
569
|
-
border-radius: var(--radius);
|
|
570
|
-
padding: 8px;
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
// One field, one border: the WRAPPER owns the border + hover/focus/error ring
|
|
574
|
-
// so the numeric input and its trailing unit pill light up together.
|
|
575
|
-
.input-with-unit {
|
|
576
|
-
display: flex;
|
|
577
|
-
align-items: stretch;
|
|
578
|
-
border: 1px solid var(--color-border);
|
|
579
|
-
border-radius: var(--radius-lg);
|
|
580
|
-
corner-shape: squircle;
|
|
581
|
-
background: var(--color-surface);
|
|
582
|
-
transition:
|
|
583
|
-
border-color 0.12s,
|
|
584
|
-
background-color 0.12s;
|
|
585
|
-
overflow: hidden;
|
|
586
|
-
}
|
|
587
|
-
.input-with-unit:hover:not(:focus-within) {
|
|
588
|
-
background: var(--color-bg-muted);
|
|
589
|
-
border-color: var(--color-border-strong);
|
|
590
|
-
}
|
|
591
|
-
.input-with-unit:focus-within {
|
|
592
|
-
background: var(--color-bg-muted);
|
|
593
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
594
|
-
}
|
|
595
|
-
.input-with-unit:has(.num-input.error) {
|
|
596
|
-
border-color: var(--color-danger);
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// Numeric inputs are plain text fields — no native spinner, no stepper. The
|
|
600
|
-
// field flows seamlessly into the trailing unit pill; the wrapper carries the
|
|
601
|
-
// border.
|
|
602
|
-
.input-with-unit .num-input {
|
|
603
|
-
border: none;
|
|
604
|
-
border-radius: 0;
|
|
605
|
-
background: transparent;
|
|
606
|
-
}
|
|
607
|
-
.input-with-unit .num-input:focus {
|
|
608
|
-
box-shadow: none;
|
|
609
|
-
}
|
|
610
|
-
.input-with-unit .unit {
|
|
611
|
-
background: var(--color-bg-muted);
|
|
612
|
-
border: none;
|
|
613
|
-
border-left: 1px solid var(--color-border);
|
|
614
|
-
padding: 9px 14px;
|
|
615
|
-
font-size: 14px;
|
|
616
|
-
font-weight: 500;
|
|
617
|
-
color: var(--color-text-muted);
|
|
618
|
-
font-family: "Inter", sans-serif;
|
|
619
|
-
display: inline-flex;
|
|
620
|
-
align-items: center;
|
|
621
|
-
white-space: nowrap;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// ── Status badge ──
|
|
625
|
-
.badge {
|
|
626
|
-
display: inline-flex;
|
|
627
|
-
align-items: center;
|
|
628
|
-
gap: 4px;
|
|
629
|
-
padding: 3px 9px;
|
|
630
|
-
border-radius: 999px;
|
|
631
|
-
font-size: 12px;
|
|
632
|
-
font-weight: 500;
|
|
633
|
-
background: var(--color-bg-muted);
|
|
634
|
-
color: var(--color-text-muted);
|
|
635
|
-
border: 1px solid var(--color-border);
|
|
636
|
-
}
|
|
637
|
-
.badge-primary {
|
|
638
|
-
background: var(--color-primary-soft);
|
|
639
|
-
color: var(--color-primary);
|
|
640
|
-
border-color: color-mix(in srgb, var(--color-primary) 25%, transparent);
|
|
641
|
-
}
|
|
642
|
-
.badge-success {
|
|
643
|
-
background: var(--color-success-soft);
|
|
644
|
-
color: var(--color-success-strong);
|
|
645
|
-
border-color: transparent;
|
|
646
|
-
}
|
|
647
|
-
.badge-warn {
|
|
648
|
-
background: var(--color-warning-soft);
|
|
649
|
-
color: var(--color-warning-strong);
|
|
650
|
-
border-color: transparent;
|
|
651
|
-
}
|
|
652
|
-
.badge-danger {
|
|
653
|
-
background: var(--color-danger-soft);
|
|
654
|
-
color: var(--color-danger-strong);
|
|
655
|
-
border-color: transparent;
|
|
656
|
-
}
|
|
657
|
-
.badge-info {
|
|
658
|
-
background: var(--color-info-soft);
|
|
659
|
-
color: var(--color-info-strong);
|
|
660
|
-
border-color: transparent;
|
|
661
|
-
}
|
|
662
|
-
.badge-dot::before {
|
|
663
|
-
content: "";
|
|
664
|
-
width: 6px;
|
|
665
|
-
height: 6px;
|
|
666
|
-
border-radius: 999px;
|
|
667
|
-
background: currentColor;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// "Soft" status badge — pill, 12/600, muted tone fill.
|
|
671
|
-
.status-label {
|
|
672
|
-
display: inline-flex;
|
|
673
|
-
align-items: center;
|
|
674
|
-
gap: 5px;
|
|
675
|
-
padding: 0 10px;
|
|
676
|
-
height: 24px;
|
|
677
|
-
border-radius: 999px;
|
|
678
|
-
font-size: 12px;
|
|
679
|
-
font-weight: 600;
|
|
680
|
-
line-height: 1;
|
|
681
|
-
white-space: nowrap;
|
|
682
|
-
}
|
|
683
|
-
// Tones are SEMANTIC (success/warning/danger/info/neutral) — the same
|
|
684
|
-
// vocabulary .chip and .badge use — and derive from the same semantic ramp.
|
|
685
|
-
// The colour-named `.tone-*` classes are kept as deprecated aliases so older
|
|
686
|
-
// Razor call sites keep working; author new markup with the semantic names.
|
|
687
|
-
.status-label.success,
|
|
688
|
-
.status-label.tone-green {
|
|
689
|
-
background: color-mix(in srgb, var(--color-success) 16%, transparent);
|
|
690
|
-
color: var(--color-success-strong);
|
|
691
|
-
}
|
|
692
|
-
.status-label.warning,
|
|
693
|
-
.status-label.tone-amber {
|
|
694
|
-
background: color-mix(in srgb, var(--color-warning) 16%, transparent);
|
|
695
|
-
color: var(--color-warning-strong);
|
|
696
|
-
}
|
|
697
|
-
.status-label.danger,
|
|
698
|
-
.status-label.tone-red {
|
|
699
|
-
background: color-mix(in srgb, var(--color-danger) 16%, transparent);
|
|
700
|
-
color: var(--color-danger-strong);
|
|
701
|
-
}
|
|
702
|
-
.status-label.info,
|
|
703
|
-
.status-label.tone-blue {
|
|
704
|
-
background: color-mix(in srgb, var(--color-info) 16%, transparent);
|
|
705
|
-
color: var(--color-info-strong);
|
|
706
|
-
}
|
|
707
|
-
.status-label.primary {
|
|
708
|
-
background: var(--color-primary-soft);
|
|
709
|
-
color: var(--color-primary);
|
|
710
|
-
}
|
|
711
|
-
// Default/neutral — also the bare `.status-label` look, so an unknown or
|
|
712
|
-
// omitted tone still renders as a proper pill instead of transparent text.
|
|
713
|
-
.status-label,
|
|
714
|
-
.status-label.neutral,
|
|
715
|
-
.status-label.tone-grey {
|
|
716
|
-
background: color-mix(in srgb, var(--color-text-subtle) 16%, transparent);
|
|
717
|
-
color: var(--color-text-subtle);
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// ── Choice chip ──
|
|
721
|
-
// Inline selectable chip — native control hidden, pill adopts the primary
|
|
722
|
-
// accent when checked.
|
|
723
|
-
.choice-chip {
|
|
724
|
-
display: inline-flex;
|
|
725
|
-
align-items: center;
|
|
726
|
-
gap: 8px;
|
|
727
|
-
padding: 9px 14px;
|
|
728
|
-
border: 1.5px solid var(--color-border);
|
|
729
|
-
border-radius: 999px;
|
|
730
|
-
font-size: 14px;
|
|
731
|
-
font-weight: 500;
|
|
732
|
-
color: var(--color-text);
|
|
733
|
-
background: var(--color-surface);
|
|
734
|
-
cursor: pointer;
|
|
735
|
-
user-select: none;
|
|
736
|
-
transition:
|
|
737
|
-
border-color 0.12s ease,
|
|
738
|
-
background 0.12s ease,
|
|
739
|
-
color 0.12s ease;
|
|
740
|
-
}
|
|
741
|
-
.choice-chip:hover {
|
|
742
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
743
|
-
}
|
|
744
|
-
.choice-chip input {
|
|
745
|
-
position: absolute;
|
|
746
|
-
opacity: 0;
|
|
747
|
-
pointer-events: none;
|
|
748
|
-
}
|
|
749
|
-
.choice-chip.checked {
|
|
750
|
-
border-color: var(--color-primary);
|
|
751
|
-
background: var(--color-primary-soft);
|
|
752
|
-
color: var(--color-primary);
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
// ── Structure card (struct-card*) ──
|
|
756
|
-
// Single-select radio-card control (e.g. "type of structure" picker).
|
|
757
|
-
.struct-card {
|
|
758
|
-
position: relative;
|
|
759
|
-
display: flex;
|
|
760
|
-
align-items: center;
|
|
761
|
-
gap: 11px;
|
|
762
|
-
padding: 20px;
|
|
763
|
-
border: 1.5px solid var(--color-border);
|
|
764
|
-
border-radius: var(--radius);
|
|
765
|
-
background: var(--color-surface);
|
|
766
|
-
cursor: pointer;
|
|
767
|
-
transition:
|
|
768
|
-
border-color 0.12s ease,
|
|
769
|
-
background 0.12s ease;
|
|
770
|
-
}
|
|
771
|
-
.struct-card:hover {
|
|
772
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
773
|
-
}
|
|
774
|
-
.struct-card.checked {
|
|
775
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
776
|
-
background: color-mix(in srgb, var(--color-primary) 5%, transparent);
|
|
777
|
-
}
|
|
778
|
-
.struct-card.checked .struct-card-title {
|
|
779
|
-
color: var(--color-primary);
|
|
780
|
-
}
|
|
781
|
-
.struct-card-input {
|
|
782
|
-
position: absolute;
|
|
783
|
-
opacity: 0;
|
|
784
|
-
pointer-events: none;
|
|
785
|
-
}
|
|
786
|
-
.struct-card-ic {
|
|
787
|
-
width: 44px;
|
|
788
|
-
height: 44px;
|
|
789
|
-
border-radius: 99px;
|
|
790
|
-
flex-shrink: 0;
|
|
791
|
-
display: inline-flex;
|
|
792
|
-
align-items: center;
|
|
793
|
-
justify-content: center;
|
|
794
|
-
background: var(--color-bg-muted);
|
|
795
|
-
color: var(--color-text-subtle);
|
|
796
|
-
transition:
|
|
797
|
-
background 0.12s,
|
|
798
|
-
color 0.12s;
|
|
799
|
-
}
|
|
800
|
-
.struct-card.checked .struct-card-ic {
|
|
801
|
-
background: var(--color-surface);
|
|
802
|
-
color: var(--color-primary);
|
|
803
|
-
}
|
|
804
|
-
// Icon illustrations are coloured PNGs: greyscale them until the card is
|
|
805
|
-
// selected, then show the full-colour (blue) art.
|
|
806
|
-
.struct-card-ic img {
|
|
807
|
-
filter: grayscale(1);
|
|
808
|
-
opacity: 0.6;
|
|
809
|
-
transition:
|
|
810
|
-
filter 0.12s,
|
|
811
|
-
opacity 0.12s;
|
|
812
|
-
}
|
|
813
|
-
.struct-card.checked .struct-card-ic img {
|
|
814
|
-
filter: none;
|
|
815
|
-
opacity: 1;
|
|
816
|
-
}
|
|
817
|
-
.struct-card-body {
|
|
818
|
-
display: flex;
|
|
819
|
-
flex-direction: column;
|
|
820
|
-
min-width: 0;
|
|
821
|
-
}
|
|
822
|
-
.struct-card-title {
|
|
823
|
-
font-weight: 600;
|
|
824
|
-
font-size: 16px;
|
|
825
|
-
color: var(--color-text);
|
|
826
|
-
}
|
|
827
|
-
.struct-card-desc {
|
|
828
|
-
font-size: 14px;
|
|
829
|
-
font-weight: 400;
|
|
830
|
-
color: var(--color-text-muted);
|
|
831
|
-
line-height: 1.35;
|
|
832
|
-
margin-top: 2px;
|
|
833
|
-
}
|
|
834
|
-
.struct-card-check {
|
|
835
|
-
position: absolute;
|
|
836
|
-
top: 10px;
|
|
837
|
-
right: 10px;
|
|
838
|
-
display: inline-flex;
|
|
839
|
-
align-items: center;
|
|
840
|
-
justify-content: center;
|
|
841
|
-
background: transparent;
|
|
842
|
-
color: var(--color-primary);
|
|
843
|
-
opacity: 0;
|
|
844
|
-
transform: scale(0.5);
|
|
845
|
-
transition:
|
|
846
|
-
opacity 0.12s ease,
|
|
847
|
-
transform 0.12s ease;
|
|
848
|
-
}
|
|
849
|
-
.struct-card.checked .struct-card-check {
|
|
850
|
-
opacity: 1;
|
|
851
|
-
transform: scale(1);
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
// Tile variant: big centered illustration + label. Opt in with
|
|
855
|
-
// className="struct-card-tile".
|
|
856
|
-
.struct-card-tile {
|
|
857
|
-
flex-direction: column;
|
|
858
|
-
align-items: center;
|
|
859
|
-
text-align: center;
|
|
860
|
-
gap: 16px;
|
|
861
|
-
padding: 26px 18px 20px;
|
|
862
|
-
}
|
|
863
|
-
// Drop the icon disc — the illustration stands on its own, sized large.
|
|
864
|
-
.struct-card-tile .struct-card-ic,
|
|
865
|
-
.struct-card-tile.checked .struct-card-ic {
|
|
866
|
-
width: auto;
|
|
867
|
-
height: auto;
|
|
868
|
-
border-radius: 0;
|
|
869
|
-
background: transparent;
|
|
870
|
-
}
|
|
871
|
-
// Full-colour at all times (override the greyscale-until-selected treatment).
|
|
872
|
-
.struct-card-tile .struct-card-ic img,
|
|
873
|
-
.struct-card-tile.checked .struct-card-ic img {
|
|
874
|
-
width: 100px;
|
|
875
|
-
height: 100px;
|
|
876
|
-
filter: none;
|
|
877
|
-
opacity: 1;
|
|
878
|
-
}
|
|
879
|
-
.struct-card-tile .struct-card-body {
|
|
880
|
-
align-items: center;
|
|
881
|
-
}
|
|
882
|
-
.struct-card-tile .struct-card-title {
|
|
883
|
-
font-size: 17px;
|
|
884
|
-
}
|
|
885
|
-
.struct-card-tile .struct-card-desc {
|
|
886
|
-
margin-top: 4px;
|
|
887
|
-
}
|
|
888
|
-
.struct-card-tile .struct-card-check {
|
|
889
|
-
display: none;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
// ── Search select ──
|
|
893
|
-
.search-select {
|
|
894
|
-
position: relative;
|
|
895
|
-
min-width: 0;
|
|
896
|
-
}
|
|
897
|
-
.search-select-control {
|
|
898
|
-
display: flex;
|
|
899
|
-
align-items: center;
|
|
900
|
-
justify-content: space-between;
|
|
901
|
-
gap: 8px;
|
|
902
|
-
text-align: left;
|
|
903
|
-
cursor: pointer;
|
|
904
|
-
width: 100%;
|
|
905
|
-
min-width: 0;
|
|
906
|
-
}
|
|
907
|
-
.search-select-control > span {
|
|
908
|
-
min-width: 0;
|
|
909
|
-
overflow: hidden;
|
|
910
|
-
text-overflow: ellipsis;
|
|
911
|
-
white-space: nowrap;
|
|
912
|
-
}
|
|
913
|
-
.search-select-control:disabled {
|
|
914
|
-
cursor: not-allowed;
|
|
915
|
-
opacity: 0.6;
|
|
916
|
-
}
|
|
917
|
-
.search-select-control:hover:not(:disabled) {
|
|
918
|
-
border-color: var(--color-border-strong);
|
|
919
|
-
}
|
|
920
|
-
.search-select-control.open {
|
|
921
|
-
background: var(--color-bg-muted);
|
|
922
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
923
|
-
}
|
|
924
|
-
.search-select-caret {
|
|
925
|
-
flex-shrink: 0;
|
|
926
|
-
color: var(--color-text-muted);
|
|
927
|
-
transition: transform 0.15s ease;
|
|
928
|
-
}
|
|
929
|
-
.search-select-caret path {
|
|
930
|
-
stroke-width: 2px;
|
|
931
|
-
}
|
|
932
|
-
.search-select-control.open .search-select-caret {
|
|
933
|
-
transform: rotate(180deg);
|
|
934
|
-
}
|
|
935
|
-
.search-select-placeholder {
|
|
936
|
-
color: var(--color-text-subtle);
|
|
937
|
-
}
|
|
938
|
-
// Menu matches the themed-select dropdown: 16px squircle, 4px padding, soft
|
|
939
|
-
// shadow.
|
|
940
|
-
.search-select-menu {
|
|
941
|
-
position: absolute;
|
|
942
|
-
z-index: 40;
|
|
943
|
-
top: calc(100% + 6px);
|
|
944
|
-
left: 0;
|
|
945
|
-
right: 0;
|
|
946
|
-
background: var(--color-surface);
|
|
947
|
-
border: 1px solid var(--color-border);
|
|
948
|
-
border-radius: var(--radius-lg);
|
|
949
|
-
corner-shape: squircle;
|
|
950
|
-
box-shadow: var(--shadow-overlay);
|
|
951
|
-
padding: 4px;
|
|
952
|
-
overflow: hidden;
|
|
953
|
-
}
|
|
954
|
-
// Portalled to <body>: fixed-positioned (top/left set inline from the
|
|
955
|
-
// trigger rect) so the menu overlays instead of being clipped by a
|
|
956
|
-
// scrollable modal / table card. Sits above the modal layer.
|
|
957
|
-
.search-select-menu-fixed {
|
|
958
|
-
position: fixed;
|
|
959
|
-
z-index: 1600;
|
|
960
|
-
right: auto;
|
|
961
|
-
top: auto;
|
|
962
|
-
left: auto;
|
|
963
|
-
}
|
|
964
|
-
// Search box matches the search bar: rounded field, leading icon turns
|
|
965
|
-
// primary.
|
|
966
|
-
.search-select-search {
|
|
967
|
-
display: flex;
|
|
968
|
-
align-items: center;
|
|
969
|
-
gap: 8px;
|
|
970
|
-
margin: 4px;
|
|
971
|
-
padding: 0 12px;
|
|
972
|
-
height: 40px;
|
|
973
|
-
border: 1px solid var(--color-border);
|
|
974
|
-
border-radius: var(--radius);
|
|
975
|
-
corner-shape: squircle;
|
|
976
|
-
background: var(--color-surface);
|
|
977
|
-
color: var(--color-text-subtle);
|
|
978
|
-
}
|
|
979
|
-
.search-select-search {
|
|
980
|
-
position: relative;
|
|
981
|
-
}
|
|
982
|
-
.search-select-search:focus-within {
|
|
983
|
-
background: var(--color-bg-muted);
|
|
984
|
-
}
|
|
985
|
-
.search-select-search:focus-within svg {
|
|
986
|
-
color: var(--color-primary);
|
|
987
|
-
}
|
|
988
|
-
.search-select-clear {
|
|
989
|
-
display: grid;
|
|
990
|
-
place-items: center;
|
|
991
|
-
width: 24px;
|
|
992
|
-
height: 24px;
|
|
993
|
-
border: none;
|
|
994
|
-
background: transparent;
|
|
995
|
-
padding: 0;
|
|
996
|
-
cursor: pointer;
|
|
997
|
-
color: var(--color-text-subtle);
|
|
998
|
-
}
|
|
999
|
-
.search-select-clear:hover {
|
|
1000
|
-
color: var(--color-text);
|
|
1001
|
-
}
|
|
1002
|
-
.search-select-input {
|
|
1003
|
-
flex: 1;
|
|
1004
|
-
border: none;
|
|
1005
|
-
outline: none;
|
|
1006
|
-
font-size: 14px;
|
|
1007
|
-
font-family: inherit;
|
|
1008
|
-
color: var(--color-text);
|
|
1009
|
-
background: transparent;
|
|
1010
|
-
}
|
|
1011
|
-
.search-select-options {
|
|
1012
|
-
max-height: 300px;
|
|
1013
|
-
overflow-y: auto;
|
|
1014
|
-
padding: 4px 4px 4px;
|
|
1015
|
-
display: flex;
|
|
1016
|
-
flex-direction: column;
|
|
1017
|
-
gap: 4px;
|
|
1018
|
-
scrollbar-gutter: stable;
|
|
1019
|
-
}
|
|
1020
|
-
.search-select-option {
|
|
1021
|
-
display: flex;
|
|
1022
|
-
align-items: center;
|
|
1023
|
-
justify-content: space-between;
|
|
1024
|
-
gap: 8px;
|
|
1025
|
-
width: 100%;
|
|
1026
|
-
text-align: left;
|
|
1027
|
-
padding: 9px 14px;
|
|
1028
|
-
line-height: 1.4;
|
|
1029
|
-
border: none;
|
|
1030
|
-
border-radius: var(--radius);
|
|
1031
|
-
corner-shape: squircle;
|
|
1032
|
-
background: transparent;
|
|
1033
|
-
font-size: 14px;
|
|
1034
|
-
color: var(--color-text);
|
|
1035
|
-
cursor: pointer;
|
|
1036
|
-
transition:
|
|
1037
|
-
background 0.12s ease,
|
|
1038
|
-
color 0.12s ease;
|
|
1039
|
-
}
|
|
1040
|
-
.search-select-option:hover,
|
|
1041
|
-
.search-select-option.is-active {
|
|
1042
|
-
background: var(--color-primary-soft);
|
|
1043
|
-
color: var(--color-primary);
|
|
1044
|
-
}
|
|
1045
|
-
.search-select-option.selected {
|
|
1046
|
-
background: var(--color-primary-soft);
|
|
1047
|
-
color: var(--color-primary);
|
|
1048
|
-
font-weight: 500;
|
|
1049
|
-
}
|
|
1050
|
-
.search-select-empty {
|
|
1051
|
-
padding: 12px 10px;
|
|
1052
|
-
font-size: 13px;
|
|
1053
|
-
color: var(--color-text-subtle);
|
|
1054
|
-
text-align: center;
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
// ── Date picker ──
|
|
1058
|
-
// Custom DatePicker — themed popover calendar (the native popup can't be
|
|
1059
|
-
// styled).
|
|
1060
|
-
.datepicker {
|
|
1061
|
-
position: relative;
|
|
1062
|
-
}
|
|
1063
|
-
.datepicker-trigger {
|
|
1064
|
-
text-align: left;
|
|
1065
|
-
cursor: pointer;
|
|
1066
|
-
}
|
|
1067
|
-
.datepicker-trigger:not(.has-value) {
|
|
1068
|
-
color: var(--color-text-subtle);
|
|
1069
|
-
}
|
|
1070
|
-
.datepicker.open .datepicker-trigger {
|
|
1071
|
-
background-color: var(--color-bg-muted);
|
|
1072
|
-
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
1073
|
-
box-shadow: none;
|
|
1074
|
-
}
|
|
1075
|
-
// Portalled to <body> and fixed-positioned from JS so a modal's
|
|
1076
|
-
// overflow:hidden can't clip it; top/left come from inline styles. z-index
|
|
1077
|
-
// sits above the modal layer.
|
|
1078
|
-
.datepicker-pop {
|
|
1079
|
-
position: fixed;
|
|
1080
|
-
z-index: 1600;
|
|
1081
|
-
width: 312px;
|
|
1082
|
-
max-width: calc(100vw - 16px);
|
|
1083
|
-
padding: 18px;
|
|
1084
|
-
background: var(--color-surface);
|
|
1085
|
-
border: 1px solid var(--color-border);
|
|
1086
|
-
border-radius: var(--radius-xl);
|
|
1087
|
-
corner-shape: squircle;
|
|
1088
|
-
box-shadow: var(--shadow-overlay);
|
|
1089
|
-
animation: datepicker-in 0.14s ease;
|
|
1090
|
-
}
|
|
1091
|
-
.datepicker-pop.drop-up {
|
|
1092
|
-
animation: datepicker-in-up 0.14s ease;
|
|
1093
|
-
}
|
|
1094
|
-
@keyframes datepicker-in {
|
|
1095
|
-
from {
|
|
1096
|
-
opacity: 0;
|
|
1097
|
-
transform: translateY(-4px);
|
|
1098
|
-
}
|
|
1099
|
-
to {
|
|
1100
|
-
opacity: 1;
|
|
1101
|
-
transform: translateY(0);
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
@keyframes datepicker-in-up {
|
|
1105
|
-
from {
|
|
1106
|
-
opacity: 0;
|
|
1107
|
-
transform: translateY(4px);
|
|
1108
|
-
}
|
|
1109
|
-
to {
|
|
1110
|
-
opacity: 1;
|
|
1111
|
-
transform: translateY(0);
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
.datepicker-head {
|
|
1115
|
-
display: flex;
|
|
1116
|
-
align-items: center;
|
|
1117
|
-
justify-content: space-between;
|
|
1118
|
-
margin-bottom: 14px;
|
|
1119
|
-
}
|
|
1120
|
-
.datepicker-month {
|
|
1121
|
-
font-size: 15px;
|
|
1122
|
-
font-weight: 600;
|
|
1123
|
-
color: var(--color-text);
|
|
1124
|
-
letter-spacing: -0.01em;
|
|
1125
|
-
}
|
|
1126
|
-
.datepicker-nav {
|
|
1127
|
-
display: inline-flex;
|
|
1128
|
-
gap: 6px;
|
|
1129
|
-
}
|
|
1130
|
-
.datepicker-nav-btn {
|
|
1131
|
-
display: inline-flex;
|
|
1132
|
-
align-items: center;
|
|
1133
|
-
justify-content: center;
|
|
1134
|
-
width: 30px;
|
|
1135
|
-
height: 30px;
|
|
1136
|
-
border: 1px solid var(--color-border);
|
|
1137
|
-
border-radius: 999px;
|
|
1138
|
-
background: transparent;
|
|
1139
|
-
color: var(--color-text-muted);
|
|
1140
|
-
cursor: pointer;
|
|
1141
|
-
transition:
|
|
1142
|
-
background 0.12s,
|
|
1143
|
-
color 0.12s,
|
|
1144
|
-
border-color 0.12s;
|
|
1145
|
-
}
|
|
1146
|
-
.datepicker-nav-btn:hover {
|
|
1147
|
-
background: var(--color-primary-soft, color-mix(in srgb, var(--color-primary) 8%, transparent));
|
|
1148
|
-
border-color: var(--color-primary);
|
|
1149
|
-
color: var(--color-primary);
|
|
1150
|
-
}
|
|
1151
|
-
.datepicker-weekdays {
|
|
1152
|
-
display: grid;
|
|
1153
|
-
grid-template-columns: repeat(7, 1fr);
|
|
1154
|
-
gap: 4px;
|
|
1155
|
-
margin-bottom: 6px;
|
|
1156
|
-
}
|
|
1157
|
-
.datepicker-grid {
|
|
1158
|
-
display: flex;
|
|
1159
|
-
flex-direction: column;
|
|
1160
|
-
gap: 4px;
|
|
1161
|
-
}
|
|
1162
|
-
.datepicker-row {
|
|
1163
|
-
display: grid;
|
|
1164
|
-
grid-template-columns: repeat(7, 1fr);
|
|
1165
|
-
gap: 4px;
|
|
1166
|
-
}
|
|
1167
|
-
.datepicker-weekdays span {
|
|
1168
|
-
text-align: center;
|
|
1169
|
-
font-size: 11px;
|
|
1170
|
-
font-weight: 600;
|
|
1171
|
-
text-transform: uppercase;
|
|
1172
|
-
letter-spacing: 0.04em;
|
|
1173
|
-
color: var(--color-text-subtle);
|
|
1174
|
-
padding: 4px 0;
|
|
1175
|
-
}
|
|
1176
|
-
.datepicker-day {
|
|
1177
|
-
display: inline-flex;
|
|
1178
|
-
align-items: center;
|
|
1179
|
-
justify-content: center;
|
|
1180
|
-
aspect-ratio: 1;
|
|
1181
|
-
width: 100%;
|
|
1182
|
-
border: none;
|
|
1183
|
-
border-radius: 50%;
|
|
1184
|
-
background: transparent;
|
|
1185
|
-
font-size: 13px;
|
|
1186
|
-
font-weight: 500;
|
|
1187
|
-
color: var(--color-text);
|
|
1188
|
-
cursor: pointer;
|
|
1189
|
-
transition:
|
|
1190
|
-
background 0.12s,
|
|
1191
|
-
color 0.12s,
|
|
1192
|
-
box-shadow 0.12s;
|
|
1193
|
-
}
|
|
1194
|
-
.datepicker-day:hover:not(:disabled):not(.is-selected) {
|
|
1195
|
-
background: var(--color-primary-soft, color-mix(in srgb, var(--color-primary) 8%, transparent));
|
|
1196
|
-
color: var(--color-primary);
|
|
1197
|
-
}
|
|
1198
|
-
.datepicker-day.is-outside {
|
|
1199
|
-
color: var(--color-text-subtle);
|
|
1200
|
-
font-weight: 400;
|
|
1201
|
-
}
|
|
1202
|
-
.datepicker-day.is-today {
|
|
1203
|
-
font-weight: 700;
|
|
1204
|
-
color: var(--color-primary);
|
|
1205
|
-
box-shadow: inset 0 0 0 1.5px var(--color-primary);
|
|
1206
|
-
}
|
|
1207
|
-
.datepicker-day.is-selected {
|
|
1208
|
-
background: var(--color-primary);
|
|
1209
|
-
color: #fff;
|
|
1210
|
-
font-weight: 600;
|
|
1211
|
-
}
|
|
1212
|
-
.datepicker-day:disabled {
|
|
1213
|
-
color: var(--color-border-strong);
|
|
1214
|
-
cursor: not-allowed;
|
|
1215
|
-
}
|
|
1216
|
-
.datepicker-foot {
|
|
1217
|
-
display: flex;
|
|
1218
|
-
align-items: center;
|
|
1219
|
-
justify-content: space-between;
|
|
1220
|
-
margin-top: 14px;
|
|
1221
|
-
padding-top: 14px;
|
|
1222
|
-
border-top: 1px solid var(--color-border);
|
|
1223
|
-
}
|
|
1224
|
-
.datepicker-link {
|
|
1225
|
-
border: none;
|
|
1226
|
-
background: transparent;
|
|
1227
|
-
padding: 6px 12px;
|
|
1228
|
-
border-radius: var(--radius);
|
|
1229
|
-
font-size: 13px;
|
|
1230
|
-
font-weight: 600;
|
|
1231
|
-
color: var(--color-primary);
|
|
1232
|
-
cursor: pointer;
|
|
1233
|
-
transition: background 0.12s;
|
|
1234
|
-
}
|
|
1235
|
-
.datepicker-link:hover:not(:disabled) {
|
|
1236
|
-
background: var(--color-primary-soft, color-mix(in srgb, var(--color-primary) 8%, transparent));
|
|
1237
|
-
}
|
|
1238
|
-
.datepicker-link:disabled {
|
|
1239
|
-
color: var(--color-text-subtle);
|
|
1240
|
-
cursor: not-allowed;
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
// ── Phone input ──
|
|
1244
|
-
.app-phone-number-input {
|
|
1245
|
-
width: 100%;
|
|
1246
|
-
}
|
|
1247
|
-
// One field, one border: the WRAPPER owns the chrome (same pattern as
|
|
1248
|
-
// .input-with-unit) so the dial-code picker and the number light up together.
|
|
1249
|
-
// The adornment used to be absolutely positioned over the input, which let the
|
|
1250
|
-
// placeholder run underneath it — masked only by the UA button's grey fill.
|
|
1251
|
-
.app-phone-number-input .phone-input-wrap {
|
|
1252
|
-
display: flex;
|
|
1253
|
-
align-items: center;
|
|
1254
|
-
width: 100%;
|
|
1255
|
-
height: var(--wui-control-height);
|
|
1256
|
-
border: 1px solid var(--color-border);
|
|
1257
|
-
border-radius: var(--radius);
|
|
1258
|
-
corner-shape: squircle;
|
|
1259
|
-
background: var(--color-surface);
|
|
1260
|
-
transition:
|
|
1261
|
-
border-color 0.12s,
|
|
1262
|
-
background-color 0.12s;
|
|
1263
|
-
}
|
|
1264
|
-
.app-phone-number-input .phone-input-wrap:hover:not(:focus-within) {
|
|
1265
|
-
background: var(--color-bg-muted);
|
|
1266
|
-
border-color: var(--color-border-strong);
|
|
1267
|
-
}
|
|
1268
|
-
.app-phone-number-input .phone-input-wrap:focus-within {
|
|
1269
|
-
background: var(--color-bg-muted);
|
|
1270
|
-
border-color: var(--color-primary);
|
|
1271
|
-
}
|
|
1272
|
-
.app-phone-number-input .phone-input-wrap:has(> .input:disabled) {
|
|
1273
|
-
background: var(--color-bg-muted);
|
|
1274
|
-
cursor: not-allowed;
|
|
1275
|
-
}
|
|
1276
|
-
.app-phone-number-input .phone-input-wrap:has(.input.error),
|
|
1277
|
-
.app-phone-number-input .phone-input-wrap:has(.input.is-invalid) {
|
|
1278
|
-
border-color: color-mix(in srgb, var(--color-danger) 45%, var(--color-surface));
|
|
1279
|
-
}
|
|
1280
|
-
// The inner control drops its own chrome — the shell carries it.
|
|
1281
|
-
.app-phone-number-input .phone-input-wrap > .input,
|
|
1282
|
-
.app-phone-number-input .phone-input-wrap > .input:hover,
|
|
1283
|
-
.app-phone-number-input .phone-input-wrap > .input:focus {
|
|
1284
|
-
flex: 1 1 auto;
|
|
1285
|
-
min-width: 0;
|
|
1286
|
-
width: auto;
|
|
1287
|
-
height: 100%;
|
|
1288
|
-
border: 0;
|
|
1289
|
-
background: transparent;
|
|
1290
|
-
box-shadow: none;
|
|
1291
|
-
}
|
|
1292
|
-
// `relative` so the menu anchors here (it is NOT positioned by JS — it used to
|
|
1293
|
-
// rely on the adornment being absolute, which is why it appeared to float).
|
|
1294
|
-
.app-phone-number-input .phone-country-adornment {
|
|
1295
|
-
position: relative;
|
|
1296
|
-
flex: none;
|
|
1297
|
-
display: flex;
|
|
1298
|
-
align-items: center;
|
|
1299
|
-
padding-left: 12px;
|
|
1300
|
-
z-index: 5;
|
|
1301
|
-
}
|
|
1302
|
-
// NOT scoped under `.country-dropdown` — <wui-phone> renders the toggle inside
|
|
1303
|
-
// `.phone-country-adornment`, with no such wrapper. Scoping it there left the
|
|
1304
|
-
// button on raw UA styling (2px outset border + grey fill) inside the field.
|
|
1305
|
-
.country-toggle {
|
|
1306
|
-
display: flex;
|
|
1307
|
-
align-items: center;
|
|
1308
|
-
gap: 6px;
|
|
1309
|
-
padding: 0;
|
|
1310
|
-
border: 0;
|
|
1311
|
-
background: transparent;
|
|
1312
|
-
box-shadow: none;
|
|
1313
|
-
color: var(--color-text);
|
|
1314
|
-
cursor: pointer;
|
|
1315
|
-
font: inherit;
|
|
1316
|
-
line-height: 1;
|
|
1317
|
-
}
|
|
1318
|
-
.country-toggle::after {
|
|
1319
|
-
display: none;
|
|
1320
|
-
}
|
|
1321
|
-
.country-toggle:hover,
|
|
1322
|
-
.country-toggle:focus,
|
|
1323
|
-
.country-toggle:active {
|
|
1324
|
-
background: transparent;
|
|
1325
|
-
box-shadow: none;
|
|
1326
|
-
color: var(--color-text);
|
|
1327
|
-
}
|
|
1328
|
-
.country-toggle:hover .phone-chevron {
|
|
1329
|
-
color: var(--color-text);
|
|
1330
|
-
}
|
|
1331
|
-
.country-toggle:focus {
|
|
1332
|
-
outline: none;
|
|
1333
|
-
}
|
|
1334
|
-
.country-toggle:focus-visible {
|
|
1335
|
-
outline: 2px solid var(--color-primary);
|
|
1336
|
-
outline-offset: 2px;
|
|
1337
|
-
border-radius: var(--radius-sm);
|
|
1338
|
-
}
|
|
1339
|
-
.country-toggle:disabled {
|
|
1340
|
-
cursor: not-allowed;
|
|
1341
|
-
opacity: 0.6;
|
|
1342
|
-
}
|
|
1343
|
-
// Flag glyphs come from the generated .wui-flag-* classes (_flags.scss).
|
|
1344
|
-
.app-phone-number-input .phone-chevron {
|
|
1345
|
-
color: var(--color-text-muted);
|
|
1346
|
-
transition: transform 0.2s ease;
|
|
1347
|
-
}
|
|
1348
|
-
// Keyed off the element's own ARIA state — <wui-phone> toggles aria-expanded,
|
|
1349
|
-
// it never adds react-bootstrap's `.show`.
|
|
1350
|
-
.country-toggle[aria-expanded="true"] .phone-chevron {
|
|
1351
|
-
transform: rotate(180deg);
|
|
1352
|
-
}
|
|
1353
|
-
.app-phone-number-input .phone-dial {
|
|
1354
|
-
font-size: 13px;
|
|
1355
|
-
font-weight: 500;
|
|
1356
|
-
color: var(--color-text);
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
// Menu, search field and rows all share the .search-select language so the
|
|
1360
|
-
// country picker reads as the same component family as every other picker.
|
|
1361
|
-
// Fixed, with top/left set from the trigger rect by <wui-phone>, so an
|
|
1362
|
-
// overflow-hidden card/modal/table wrapper can't clip the list. Sits above the
|
|
1363
|
-
// modal layer, matching .search-select-menu-fixed and .datepicker-pop.
|
|
1364
|
-
.country-dropdown-menu {
|
|
1365
|
-
position: fixed;
|
|
1366
|
-
z-index: 1600;
|
|
1367
|
-
width: 320px;
|
|
1368
|
-
max-width: calc(100vw - 16px);
|
|
1369
|
-
padding: 4px;
|
|
1370
|
-
border: 1px solid var(--color-border);
|
|
1371
|
-
border-radius: var(--radius-lg);
|
|
1372
|
-
corner-shape: squircle;
|
|
1373
|
-
background: var(--color-surface);
|
|
1374
|
-
box-shadow: var(--shadow-overlay);
|
|
1375
|
-
overflow: hidden;
|
|
1376
|
-
}
|
|
1377
|
-
.dropdown-search-wrapper {
|
|
1378
|
-
position: relative;
|
|
1379
|
-
margin: 4px;
|
|
1380
|
-
}
|
|
1381
|
-
.dropdown-search-icon {
|
|
1382
|
-
position: absolute;
|
|
1383
|
-
left: 12px;
|
|
1384
|
-
top: 50%;
|
|
1385
|
-
transform: translateY(-50%);
|
|
1386
|
-
display: flex;
|
|
1387
|
-
color: var(--color-text-subtle);
|
|
1388
|
-
pointer-events: none;
|
|
1389
|
-
transition: color 0.12s ease;
|
|
1390
|
-
}
|
|
1391
|
-
.dropdown-search-wrapper:focus-within .dropdown-search-icon {
|
|
1392
|
-
color: var(--color-primary);
|
|
1393
|
-
}
|
|
1394
|
-
.dropdown-search-input {
|
|
1395
|
-
width: 100%;
|
|
1396
|
-
height: 40px;
|
|
1397
|
-
padding: 0 12px 0 36px;
|
|
1398
|
-
border: 1px solid var(--color-border);
|
|
1399
|
-
border-radius: var(--radius);
|
|
1400
|
-
corner-shape: squircle;
|
|
1401
|
-
font-size: 14px;
|
|
1402
|
-
color: var(--color-text);
|
|
1403
|
-
background: var(--color-surface);
|
|
1404
|
-
outline: none;
|
|
1405
|
-
}
|
|
1406
|
-
.dropdown-search-input:hover:not(:focus) {
|
|
1407
|
-
background: var(--color-bg-muted);
|
|
1408
|
-
border-color: var(--color-border-strong);
|
|
1409
|
-
}
|
|
1410
|
-
// Border is the focus cue everywhere else in the system — no glow ring here.
|
|
1411
|
-
.dropdown-search-input:focus {
|
|
1412
|
-
background: var(--color-bg-muted);
|
|
1413
|
-
border-color: var(--color-primary);
|
|
1414
|
-
}
|
|
1415
|
-
.country-list-scroll {
|
|
1416
|
-
max-height: 250px;
|
|
1417
|
-
overflow-y: auto;
|
|
1418
|
-
overflow-x: hidden;
|
|
1419
|
-
padding: 4px;
|
|
1420
|
-
display: flex;
|
|
1421
|
-
flex-direction: column;
|
|
1422
|
-
gap: 4px;
|
|
1423
|
-
scrollbar-width: thin;
|
|
1424
|
-
scrollbar-gutter: stable;
|
|
1425
|
-
}
|
|
1426
|
-
.country-list-scroll::-webkit-scrollbar {
|
|
1427
|
-
width: 6px;
|
|
1428
|
-
}
|
|
1429
|
-
.country-list-scroll::-webkit-scrollbar-thumb {
|
|
1430
|
-
background: var(--color-border);
|
|
1431
|
-
border-radius: 999px;
|
|
1432
|
-
}
|
|
1433
|
-
// Rounded, inset rows with a primary-tinted hover — identical to
|
|
1434
|
-
// .search-select-option. (!important is required: react-bootstrap's
|
|
1435
|
-
// .dropdown-item ships its own colour/padding at equal specificity.)
|
|
1436
|
-
.country-dropdown-item {
|
|
1437
|
-
display: flex !important;
|
|
1438
|
-
align-items: center;
|
|
1439
|
-
gap: 10px;
|
|
1440
|
-
padding: 9px 14px !important;
|
|
1441
|
-
border-radius: var(--radius) !important;
|
|
1442
|
-
corner-shape: squircle;
|
|
1443
|
-
cursor: pointer;
|
|
1444
|
-
color: var(--color-text) !important;
|
|
1445
|
-
background: transparent !important;
|
|
1446
|
-
border: 0 !important;
|
|
1447
|
-
transition:
|
|
1448
|
-
background 0.12s ease,
|
|
1449
|
-
color 0.12s ease;
|
|
1450
|
-
}
|
|
1451
|
-
.country-dropdown-item:hover,
|
|
1452
|
-
.country-dropdown-item:focus {
|
|
1453
|
-
background: var(--color-primary-soft) !important;
|
|
1454
|
-
color: var(--color-primary) !important;
|
|
1455
|
-
}
|
|
1456
|
-
.country-dropdown-item.selected {
|
|
1457
|
-
background: var(--color-primary-soft) !important;
|
|
1458
|
-
color: var(--color-primary) !important;
|
|
1459
|
-
font-weight: 500;
|
|
1460
|
-
}
|
|
1461
|
-
.country-dropdown-menu .wui-flag {
|
|
1462
|
-
flex-shrink: 0;
|
|
1463
|
-
}
|
|
1464
|
-
.country-name-text {
|
|
1465
|
-
font-size: 14px;
|
|
1466
|
-
font-weight: 500;
|
|
1467
|
-
color: var(--color-text);
|
|
1468
|
-
}
|
|
1469
|
-
.country-code-text {
|
|
1470
|
-
margin-left: 6px;
|
|
1471
|
-
font-weight: 400;
|
|
1472
|
-
color: var(--color-text-muted);
|
|
1473
|
-
}
|
|
1474
|
-
// On a tinted row the label must ride the row colour, not stay grey.
|
|
1475
|
-
.country-dropdown-item:hover .country-name-text,
|
|
1476
|
-
.country-dropdown-item:focus .country-name-text,
|
|
1477
|
-
.country-dropdown-item.selected .country-name-text,
|
|
1478
|
-
.country-dropdown-item:hover .country-code-text,
|
|
1479
|
-
.country-dropdown-item:focus .country-code-text,
|
|
1480
|
-
.country-dropdown-item.selected .country-code-text {
|
|
1481
|
-
color: currentColor;
|
|
1482
|
-
}
|
|
1483
|
-
.selected-check-icon {
|
|
1484
|
-
margin-left: auto;
|
|
1485
|
-
display: flex;
|
|
1486
|
-
color: var(--color-primary);
|
|
1487
|
-
}
|
|
1488
|
-
.country-empty {
|
|
1489
|
-
padding: 10px 16px;
|
|
1490
|
-
text-align: center;
|
|
1491
|
-
color: var(--color-text-subtle);
|
|
1492
|
-
font-size: 14px;
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
// ── Avatar ──
|
|
1496
|
-
// A photo fills the avatar disc edge to edge; the circle is the frame, so
|
|
1497
|
-
// the image is cropped to it rather than letterboxed.
|
|
1498
|
-
.avatar > .avatar-img {
|
|
1499
|
-
width: 100%;
|
|
1500
|
-
height: 100%;
|
|
1501
|
-
border-radius: inherit;
|
|
1502
|
-
object-fit: cover;
|
|
1503
|
-
display: block;
|
|
1504
|
-
}
|
|
1505
|
-
.avatar {
|
|
1506
|
-
width: 32px;
|
|
1507
|
-
height: 32px;
|
|
1508
|
-
border-radius: 999px;
|
|
1509
|
-
background: color-mix(in srgb, var(--color-primary) 15%, var(--color-surface));
|
|
1510
|
-
color: var(--color-primary);
|
|
1511
|
-
font-size: 12px;
|
|
1512
|
-
font-weight: 600;
|
|
1513
|
-
display: inline-flex;
|
|
1514
|
-
align-items: center;
|
|
1515
|
-
justify-content: center;
|
|
1516
|
-
}
|
|
1517
|
-
.avatar-lg {
|
|
1518
|
-
width: 48px;
|
|
1519
|
-
height: 48px;
|
|
1520
|
-
font-size: 16px;
|
|
1521
|
-
}
|
|
1522
|
-
.avatar-xl {
|
|
1523
|
-
width: 64px;
|
|
1524
|
-
height: 64px;
|
|
1525
|
-
font-size: 22px;
|
|
1526
|
-
}
|
|
1527
|
-
.avatar-sm {
|
|
1528
|
-
width: 24px;
|
|
1529
|
-
height: 24px;
|
|
1530
|
-
font-size: 10px;
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
// ── File attach ──
|
|
1534
|
-
// Support-form attachment strip: drop zone → attached-image preview.
|
|
1535
|
-
.attach-drop {
|
|
1536
|
-
display: flex;
|
|
1537
|
-
width: 100%;
|
|
1538
|
-
align-items: center;
|
|
1539
|
-
gap: 12px;
|
|
1540
|
-
padding: 12px 14px;
|
|
1541
|
-
border: 1px dashed var(--color-border);
|
|
1542
|
-
border-radius: var(--radius-lg);
|
|
1543
|
-
background: var(--color-surface);
|
|
1544
|
-
cursor: pointer;
|
|
1545
|
-
transition:
|
|
1546
|
-
border-color 0.3s cubic-bezier(0.22, 1, 0.36, 1),
|
|
1547
|
-
background 0.3s cubic-bezier(0.22, 1, 0.36, 1);
|
|
1548
|
-
}
|
|
1549
|
-
.attach-drop:hover {
|
|
1550
|
-
border-color: var(--color-primary);
|
|
1551
|
-
background: var(--color-primary-soft);
|
|
1552
|
-
}
|
|
1553
|
-
.attach-drop-icon {
|
|
1554
|
-
flex: 0 0 auto;
|
|
1555
|
-
width: 36px;
|
|
1556
|
-
height: 36px;
|
|
1557
|
-
display: inline-flex;
|
|
1558
|
-
align-items: center;
|
|
1559
|
-
justify-content: center;
|
|
1560
|
-
border-radius: 999px;
|
|
1561
|
-
background: var(--color-primary-soft);
|
|
1562
|
-
color: var(--color-primary);
|
|
1563
|
-
}
|
|
1564
|
-
.attach-drop:hover .attach-drop-icon {
|
|
1565
|
-
background: var(--color-surface);
|
|
1566
|
-
}
|
|
1567
|
-
.attach-drop-copy {
|
|
1568
|
-
display: flex;
|
|
1569
|
-
flex-direction: column;
|
|
1570
|
-
gap: 2px;
|
|
1571
|
-
flex: 1;
|
|
1572
|
-
min-width: 0;
|
|
1573
|
-
}
|
|
1574
|
-
.attach-drop-title {
|
|
1575
|
-
font-weight: 600;
|
|
1576
|
-
font-size: 14px;
|
|
1577
|
-
line-height: 1.4;
|
|
1578
|
-
color: var(--color-text);
|
|
1579
|
-
}
|
|
1580
|
-
.attach-drop-hint {
|
|
1581
|
-
font-size: 12px;
|
|
1582
|
-
color: var(--color-text-subtle);
|
|
1583
|
-
}
|
|
1584
|
-
.attach-drop-cta {
|
|
1585
|
-
flex: 0 0 auto;
|
|
1586
|
-
font-size: 12px;
|
|
1587
|
-
font-weight: 600;
|
|
1588
|
-
color: var(--color-primary);
|
|
1589
|
-
border: 1px solid var(--color-border);
|
|
1590
|
-
border-radius: 999px;
|
|
1591
|
-
padding: 5px 14px;
|
|
1592
|
-
background: var(--color-surface);
|
|
1593
|
-
}
|
|
1594
|
-
// Attached image renders full width so the user can actually check what
|
|
1595
|
-
// they're sending.
|
|
1596
|
-
.attach-preview {
|
|
1597
|
-
width: 100%;
|
|
1598
|
-
border: 1px solid var(--color-border);
|
|
1599
|
-
border-radius: var(--radius-lg);
|
|
1600
|
-
background: var(--color-surface);
|
|
1601
|
-
overflow: hidden;
|
|
1602
|
-
}
|
|
1603
|
-
.attach-figure {
|
|
1604
|
-
position: relative;
|
|
1605
|
-
// A lighter elevated surface behind the (contained) image so the
|
|
1606
|
-
// letterbox reads as a surface, not near-black — dark mode uses the
|
|
1607
|
-
// muted/elevated step instead.
|
|
1608
|
-
background: var(--color-bg-muted);
|
|
1609
|
-
}
|
|
1610
|
-
.attach-figure img {
|
|
1611
|
-
display: block;
|
|
1612
|
-
width: 100%;
|
|
1613
|
-
max-height: 260px;
|
|
1614
|
-
object-fit: contain;
|
|
1615
|
-
}
|
|
1616
|
-
.attach-meta {
|
|
1617
|
-
display: flex;
|
|
1618
|
-
align-items: baseline;
|
|
1619
|
-
justify-content: space-between;
|
|
1620
|
-
gap: 12px;
|
|
1621
|
-
padding: 10px 14px;
|
|
1622
|
-
border-top: 1px solid var(--color-border);
|
|
1623
|
-
min-width: 0;
|
|
1624
|
-
}
|
|
1625
|
-
.attach-name {
|
|
1626
|
-
font-size: 13px;
|
|
1627
|
-
font-weight: 500;
|
|
1628
|
-
color: var(--color-text);
|
|
1629
|
-
overflow: hidden;
|
|
1630
|
-
text-overflow: ellipsis;
|
|
1631
|
-
white-space: nowrap;
|
|
1632
|
-
}
|
|
1633
|
-
.attach-size {
|
|
1634
|
-
font-size: 12px;
|
|
1635
|
-
color: var(--color-text-subtle);
|
|
1636
|
-
flex: 0 0 auto;
|
|
1637
|
-
}
|
|
1638
|
-
.attach-remove {
|
|
1639
|
-
position: absolute;
|
|
1640
|
-
top: 8px;
|
|
1641
|
-
right: 8px;
|
|
1642
|
-
display: inline-flex;
|
|
1643
|
-
align-items: center;
|
|
1644
|
-
justify-content: center;
|
|
1645
|
-
width: 28px;
|
|
1646
|
-
height: 28px;
|
|
1647
|
-
border: 0;
|
|
1648
|
-
background: rgba(0, 0, 0, 0.62);
|
|
1649
|
-
backdrop-filter: blur(10px);
|
|
1650
|
-
-webkit-backdrop-filter: blur(10px);
|
|
1651
|
-
color: #fff;
|
|
1652
|
-
border-radius: 999px;
|
|
1653
|
-
cursor: pointer;
|
|
1654
|
-
transition: background 0.2s;
|
|
1655
|
-
}
|
|
1656
|
-
.attach-remove:hover {
|
|
1657
|
-
background: var(--color-danger);
|
|
1658
|
-
}
|
|
1659
|
-
// Iconsax hardcodes both stroke colour and width on its paths, so force
|
|
1660
|
-
// white here — otherwise the glyph vanishes into the button in dark mode.
|
|
1661
|
-
.attach-remove svg {
|
|
1662
|
-
width: 18px;
|
|
1663
|
-
height: 18px;
|
|
1664
|
-
display: block;
|
|
1665
|
-
}
|
|
1666
|
-
.attach-remove svg path {
|
|
1667
|
-
stroke: #fff;
|
|
1668
|
-
stroke-width: 2px;
|
|
1669
|
-
}
|
|
1670
|
-
@media (prefers-reduced-motion: reduce) {
|
|
1671
|
-
.attach-drop,
|
|
1672
|
-
.attach-remove {
|
|
1673
|
-
transition: none;
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
|
|
1677
|
-
// ── File picker ──
|
|
1678
|
-
// File input — segmented "Upload" button + placeholder, matches the .input
|
|
1679
|
-
// shell.
|
|
1680
|
-
.file-input {
|
|
1681
|
-
box-sizing: border-box;
|
|
1682
|
-
display: flex;
|
|
1683
|
-
align-items: stretch;
|
|
1684
|
-
width: 100%;
|
|
1685
|
-
border-radius: var(--radius-lg);
|
|
1686
|
-
corner-shape: squircle;
|
|
1687
|
-
border: 1px solid var(--color-border);
|
|
1688
|
-
background: var(--color-surface);
|
|
1689
|
-
overflow: hidden;
|
|
1690
|
-
cursor: pointer;
|
|
1691
|
-
transition:
|
|
1692
|
-
border-color 0.12s,
|
|
1693
|
-
box-shadow 0.12s;
|
|
1694
|
-
}
|
|
1695
|
-
.file-input:hover {
|
|
1696
|
-
border-color: var(--color-border-strong);
|
|
1697
|
-
}
|
|
1698
|
-
.file-input-btn {
|
|
1699
|
-
display: inline-flex;
|
|
1700
|
-
align-items: center;
|
|
1701
|
-
flex-shrink: 0;
|
|
1702
|
-
padding: 12px 20px;
|
|
1703
|
-
font-size: 14px;
|
|
1704
|
-
font-weight: 600;
|
|
1705
|
-
color: var(--color-text);
|
|
1706
|
-
background: var(--color-bg-muted);
|
|
1707
|
-
border-right: 1px solid var(--color-border);
|
|
1708
|
-
}
|
|
1709
|
-
.file-input-text {
|
|
1710
|
-
display: inline-flex;
|
|
1711
|
-
align-items: center;
|
|
1712
|
-
min-width: 0;
|
|
1713
|
-
padding: 12px 16px;
|
|
1714
|
-
font-size: 14px;
|
|
1715
|
-
color: var(--color-text-subtle);
|
|
1716
|
-
white-space: nowrap;
|
|
1717
|
-
overflow: hidden;
|
|
1718
|
-
text-overflow: ellipsis;
|
|
1719
|
-
}
|
|
1720
|
-
.file-input-text.has-file {
|
|
1721
|
-
color: var(--color-text);
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
// Tall empty state (AppFilePicker): a drag-and-drop dropzone — dashed
|
|
1725
|
-
// border, circular icon badge, click-or-drop copy. Highlights on hover and
|
|
1726
|
-
// while a file is dragged over.
|
|
1727
|
-
.file-input.file-input-tall {
|
|
1728
|
-
position: relative;
|
|
1729
|
-
flex-direction: column;
|
|
1730
|
-
align-items: center;
|
|
1731
|
-
justify-content: center;
|
|
1732
|
-
gap: 10px;
|
|
1733
|
-
height: 350px;
|
|
1734
|
-
padding: 20px;
|
|
1735
|
-
text-align: center;
|
|
1736
|
-
background: var(--color-bg-subtle);
|
|
1737
|
-
border: 1px dashed var(--color-border-strong);
|
|
1738
|
-
transition:
|
|
1739
|
-
border-color 0.15s ease,
|
|
1740
|
-
background-color 0.15s ease;
|
|
1741
|
-
}
|
|
1742
|
-
.file-input.file-input-tall:hover,
|
|
1743
|
-
.file-input.file-input-tall.dragging {
|
|
1744
|
-
border-color: var(--color-primary);
|
|
1745
|
-
background: var(--color-bg-muted);
|
|
1746
|
-
}
|
|
1747
|
-
// Fill-label associates click with the hidden file input; children don't
|
|
1748
|
-
// steal drag hits.
|
|
1749
|
-
.file-input.file-input-tall > .file-input-zone-label {
|
|
1750
|
-
position: absolute;
|
|
1751
|
-
inset: 0;
|
|
1752
|
-
display: flex;
|
|
1753
|
-
flex-direction: column;
|
|
1754
|
-
align-items: center;
|
|
1755
|
-
justify-content: center;
|
|
1756
|
-
gap: 10px;
|
|
1757
|
-
margin: 0;
|
|
1758
|
-
cursor: pointer;
|
|
1759
|
-
}
|
|
1760
|
-
.file-input.file-input-tall > .file-input-zone-label > * {
|
|
1761
|
-
pointer-events: none;
|
|
1762
|
-
}
|
|
1763
|
-
.file-input.file-input-tall .file-input-icon {
|
|
1764
|
-
display: inline-flex;
|
|
1765
|
-
align-items: center;
|
|
1766
|
-
justify-content: center;
|
|
1767
|
-
width: 54px;
|
|
1768
|
-
height: 54px;
|
|
1769
|
-
border-radius: 50%;
|
|
1770
|
-
background: var(--color-primary-soft);
|
|
1771
|
-
color: var(--color-primary);
|
|
1772
|
-
transition: transform 0.15s ease;
|
|
1773
|
-
}
|
|
1774
|
-
.file-input.file-input-tall.dragging .file-input-icon {
|
|
1775
|
-
transform: translateY(-2px) scale(1.06);
|
|
1776
|
-
}
|
|
1777
|
-
.file-input-title {
|
|
1778
|
-
font-size: 14px;
|
|
1779
|
-
font-weight: 600;
|
|
1780
|
-
color: var(--color-text);
|
|
1781
|
-
}
|
|
1782
|
-
.file-input-title .browse {
|
|
1783
|
-
color: var(--color-primary);
|
|
1784
|
-
}
|
|
1785
|
-
.file-input.file-input-tall .file-input-text {
|
|
1786
|
-
padding: 0;
|
|
1787
|
-
font-size: 12px;
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
// Large preview shown once an image exists; hover reveals a "Change image"
|
|
1791
|
-
// overlay.
|
|
1792
|
-
.file-preview {
|
|
1793
|
-
position: relative;
|
|
1794
|
-
box-sizing: border-box;
|
|
1795
|
-
display: block;
|
|
1796
|
-
width: 100%;
|
|
1797
|
-
height: 350px;
|
|
1798
|
-
border-radius: var(--radius-lg);
|
|
1799
|
-
corner-shape: squircle;
|
|
1800
|
-
border: 1px solid var(--color-border);
|
|
1801
|
-
overflow: hidden;
|
|
1802
|
-
cursor: pointer;
|
|
1803
|
-
background: var(--color-bg-subtle);
|
|
1804
|
-
transition: border-color 0.12s;
|
|
1805
|
-
}
|
|
1806
|
-
.file-preview:hover {
|
|
1807
|
-
border-color: var(--color-border-strong);
|
|
1808
|
-
}
|
|
1809
|
-
.file-preview.error {
|
|
1810
|
-
border-color: var(--color-danger);
|
|
1811
|
-
}
|
|
1812
|
-
// Open-picker control fills the shell (remove button is a sibling, not
|
|
1813
|
-
// nested).
|
|
1814
|
-
.file-preview-open {
|
|
1815
|
-
display: block;
|
|
1816
|
-
box-sizing: border-box;
|
|
1817
|
-
width: 100%;
|
|
1818
|
-
height: 100%;
|
|
1819
|
-
padding: 0;
|
|
1820
|
-
border: none;
|
|
1821
|
-
background: transparent;
|
|
1822
|
-
cursor: pointer;
|
|
1823
|
-
position: relative;
|
|
1824
|
-
font: inherit;
|
|
1825
|
-
color: inherit;
|
|
1826
|
-
text-align: left;
|
|
1827
|
-
}
|
|
1828
|
-
.file-preview-img {
|
|
1829
|
-
display: block;
|
|
1830
|
-
width: 100%;
|
|
1831
|
-
height: 100%;
|
|
1832
|
-
object-fit: cover;
|
|
1833
|
-
transition: transform 0.25s ease;
|
|
1834
|
-
}
|
|
1835
|
-
// Gentle zoom on hover so the field feels interactive.
|
|
1836
|
-
.file-preview:hover .file-preview-img {
|
|
1837
|
-
transform: scale(1.03);
|
|
1838
|
-
}
|
|
1839
|
-
.file-preview-overlay {
|
|
1840
|
-
position: absolute;
|
|
1841
|
-
inset: 0;
|
|
1842
|
-
display: flex;
|
|
1843
|
-
align-items: center;
|
|
1844
|
-
justify-content: center;
|
|
1845
|
-
// Subtle dim so the glassy CTA reads on any image, without hiding it.
|
|
1846
|
-
background: rgba(16, 24, 40, 0.22);
|
|
1847
|
-
opacity: 0;
|
|
1848
|
-
transition: opacity 0.15s ease;
|
|
1849
|
-
}
|
|
1850
|
-
.file-preview:hover .file-preview-overlay,
|
|
1851
|
-
.file-preview:focus-within .file-preview-overlay {
|
|
1852
|
-
opacity: 1;
|
|
1853
|
-
}
|
|
1854
|
-
// The "Change image" call-to-action as a glassy pill button.
|
|
1855
|
-
.file-preview-cta {
|
|
1856
|
-
display: inline-flex;
|
|
1857
|
-
align-items: center;
|
|
1858
|
-
gap: 8px;
|
|
1859
|
-
padding: 9px 18px;
|
|
1860
|
-
background: rgba(255, 255, 255, 0.96);
|
|
1861
|
-
color: var(--color-text);
|
|
1862
|
-
font-size: 14px;
|
|
1863
|
-
font-weight: 600;
|
|
1864
|
-
border-radius: 999px;
|
|
1865
|
-
box-shadow: var(--shadow-overlay);
|
|
1866
|
-
}
|
|
1867
|
-
.file-preview-remove {
|
|
1868
|
-
position: absolute;
|
|
1869
|
-
top: 8px;
|
|
1870
|
-
right: 8px;
|
|
1871
|
-
z-index: 2;
|
|
1872
|
-
box-sizing: border-box;
|
|
1873
|
-
display: inline-flex;
|
|
1874
|
-
align-items: center;
|
|
1875
|
-
justify-content: center;
|
|
1876
|
-
width: 30px;
|
|
1877
|
-
height: 30px;
|
|
1878
|
-
padding: 0;
|
|
1879
|
-
border: 2px solid transparent;
|
|
1880
|
-
border-radius: 50%;
|
|
1881
|
-
background: rgba(16, 24, 40, 0.55);
|
|
1882
|
-
color: #fff;
|
|
1883
|
-
cursor: pointer;
|
|
1884
|
-
opacity: 0;
|
|
1885
|
-
transition:
|
|
1886
|
-
border-color 0.12s,
|
|
1887
|
-
opacity 0.15s ease;
|
|
1888
|
-
}
|
|
1889
|
-
.file-preview:hover .file-preview-remove,
|
|
1890
|
-
.file-preview:focus-within .file-preview-remove {
|
|
1891
|
-
opacity: 1;
|
|
1892
|
-
}
|
|
1893
|
-
// Hovering the cross: keep it plain — just a slightly deeper disc, no
|
|
1894
|
-
// coloured ring.
|
|
1895
|
-
.file-preview-remove:hover {
|
|
1896
|
-
background: rgba(16, 24, 40, 0.78);
|
|
1897
|
-
color: #fff;
|
|
1898
|
-
}
|
|
1899
|
-
|
|
1900
|
-
// ── Logo picker ──
|
|
1901
|
-
// Round dropzone uploader (workspace/brand logo) and the settings-page photo
|
|
1902
|
-
// ring share this same interactive-uploader pattern.
|
|
1903
|
-
.set-uploader {
|
|
1904
|
-
display: inline-flex;
|
|
1905
|
-
padding: 0;
|
|
1906
|
-
border: none;
|
|
1907
|
-
background: transparent;
|
|
1908
|
-
font: inherit;
|
|
1909
|
-
color: inherit;
|
|
1910
|
-
cursor: pointer;
|
|
1911
|
-
}
|
|
1912
|
-
.set-uploader:disabled {
|
|
1913
|
-
cursor: progress;
|
|
1914
|
-
}
|
|
1915
|
-
.set-uploader-img {
|
|
1916
|
-
width: 100%;
|
|
1917
|
-
height: 100%;
|
|
1918
|
-
border-radius: 50%;
|
|
1919
|
-
object-fit: cover;
|
|
1920
|
-
}
|
|
1921
|
-
.set-uploader-ring {
|
|
1922
|
-
position: relative;
|
|
1923
|
-
width: 120px;
|
|
1924
|
-
height: 120px;
|
|
1925
|
-
border-radius: 50%;
|
|
1926
|
-
padding: 8px;
|
|
1927
|
-
border: 1px dashed color-mix(in srgb, var(--color-border-strong) 75%, transparent);
|
|
1928
|
-
cursor: pointer;
|
|
1929
|
-
transition: border-color 0.18s;
|
|
1930
|
-
}
|
|
1931
|
-
.set-uploader-ring:hover,
|
|
1932
|
-
.set-uploader:hover .set-uploader-ring,
|
|
1933
|
-
.set-uploader:focus-visible .set-uploader-ring {
|
|
1934
|
-
border-color: var(--color-primary);
|
|
1935
|
-
}
|
|
1936
|
-
.set-uploader-logo {
|
|
1937
|
-
width: 100%;
|
|
1938
|
-
height: 100%;
|
|
1939
|
-
border-radius: 50%;
|
|
1940
|
-
display: grid;
|
|
1941
|
-
place-items: center;
|
|
1942
|
-
font-size: 38px;
|
|
1943
|
-
font-weight: 700;
|
|
1944
|
-
letter-spacing: -0.02em;
|
|
1945
|
-
color: var(--color-primary);
|
|
1946
|
-
background: var(--color-primary-soft);
|
|
1947
|
-
}
|
|
1948
|
-
.set-uploader-overlay {
|
|
1949
|
-
position: absolute;
|
|
1950
|
-
inset: 8px;
|
|
1951
|
-
border-radius: 50%;
|
|
1952
|
-
display: flex;
|
|
1953
|
-
flex-direction: column;
|
|
1954
|
-
align-items: center;
|
|
1955
|
-
justify-content: center;
|
|
1956
|
-
gap: 4px;
|
|
1957
|
-
background: rgba(20, 26, 33, 0.62);
|
|
1958
|
-
color: #fff;
|
|
1959
|
-
font-size: 11px;
|
|
1960
|
-
font-weight: 600;
|
|
1961
|
-
opacity: 0;
|
|
1962
|
-
transition: opacity 0.18s;
|
|
1963
|
-
}
|
|
1964
|
-
.set-uploader-ring:hover .set-uploader-overlay,
|
|
1965
|
-
.set-uploader:hover .set-uploader-overlay,
|
|
1966
|
-
.set-uploader:focus-visible .set-uploader-overlay {
|
|
1967
|
-
opacity: 1;
|
|
1968
|
-
}
|
|
1969
|
-
// While uploading: keep the overlay (spinner) visible and signal it's not
|
|
1970
|
-
// clickable.
|
|
1971
|
-
.set-uploader-overlay.is-loading {
|
|
1972
|
-
opacity: 1;
|
|
1973
|
-
}
|
|
1974
|
-
.set-uploader[aria-busy="true"] {
|
|
1975
|
-
cursor: progress;
|
|
1976
|
-
}
|
|
1977
|
-
.set-uploader-hint {
|
|
1978
|
-
margin: 18px auto 0;
|
|
1979
|
-
max-width: 240px;
|
|
1980
|
-
font-size: 12px;
|
|
1981
|
-
line-height: 1.5;
|
|
1982
|
-
color: var(--color-text-subtle);
|
|
1983
|
-
}
|
|
1984
|
-
|
|
1985
|
-
// Minimals-style rounded logo dropzone (workspace branding form).
|
|
1986
|
-
.logo-upload {
|
|
1987
|
-
display: flex;
|
|
1988
|
-
align-items: center;
|
|
1989
|
-
gap: 20px;
|
|
1990
|
-
flex-wrap: wrap;
|
|
1991
|
-
}
|
|
1992
|
-
.logo-dropzone {
|
|
1993
|
-
position: relative;
|
|
1994
|
-
width: 104px;
|
|
1995
|
-
height: 104px;
|
|
1996
|
-
flex: none;
|
|
1997
|
-
border-radius: var(--radius-lg);
|
|
1998
|
-
border: 1.5px dashed var(--color-border-strong);
|
|
1999
|
-
background: var(--color-bg-subtle);
|
|
2000
|
-
display: grid;
|
|
2001
|
-
place-items: center;
|
|
2002
|
-
overflow: hidden;
|
|
2003
|
-
cursor: pointer;
|
|
2004
|
-
padding: 6px;
|
|
2005
|
-
transition:
|
|
2006
|
-
border-color 0.15s ease,
|
|
2007
|
-
background 0.15s ease;
|
|
2008
|
-
}
|
|
2009
|
-
.logo-dropzone:hover,
|
|
2010
|
-
.logo-dropzone:focus-visible {
|
|
2011
|
-
border-color: var(--color-primary);
|
|
2012
|
-
background: var(--color-primary-soft);
|
|
2013
|
-
outline: none;
|
|
2014
|
-
}
|
|
2015
|
-
.logo-dropzone.has-image {
|
|
2016
|
-
border-style: solid;
|
|
2017
|
-
background: var(--color-surface);
|
|
2018
|
-
}
|
|
2019
|
-
.logo-dropzone-empty {
|
|
2020
|
-
display: grid;
|
|
2021
|
-
place-items: center;
|
|
2022
|
-
color: var(--color-text-subtle);
|
|
2023
|
-
}
|
|
2024
|
-
.logo-dropzone-img {
|
|
2025
|
-
max-width: 100%;
|
|
2026
|
-
max-height: 100%;
|
|
2027
|
-
object-fit: contain;
|
|
2028
|
-
border-radius: var(--radius);
|
|
2029
|
-
}
|
|
2030
|
-
// hover overlay (camera + label), like the Minimals avatar uploader
|
|
2031
|
-
.logo-dropzone-overlay {
|
|
2032
|
-
position: absolute;
|
|
2033
|
-
inset: 0;
|
|
2034
|
-
display: flex;
|
|
2035
|
-
flex-direction: column;
|
|
2036
|
-
align-items: center;
|
|
2037
|
-
justify-content: center;
|
|
2038
|
-
gap: 4px;
|
|
2039
|
-
background: var(--color-scrim);
|
|
2040
|
-
color: var(--color-on-scrim);
|
|
2041
|
-
font-size: 12px;
|
|
2042
|
-
font-weight: 600;
|
|
2043
|
-
opacity: 0;
|
|
2044
|
-
transition: opacity 0.15s ease;
|
|
2045
|
-
}
|
|
2046
|
-
.logo-dropzone:hover .logo-dropzone-overlay,
|
|
2047
|
-
.logo-dropzone:focus-visible .logo-dropzone-overlay {
|
|
2048
|
-
opacity: 1;
|
|
2049
|
-
}
|
|
2050
|
-
.logo-upload-body {
|
|
2051
|
-
flex: 1;
|
|
2052
|
-
min-width: 200px;
|
|
2053
|
-
}
|
|
2054
|
-
|
|
2055
|
-
// ── Drawer / Sidebar menu ──
|
|
2056
|
-
// AppSidebarMenu — react-bootstrap Offcanvas mapped onto the app tokens plus
|
|
2057
|
-
// a flex column layout for the header / scrolling body / sticky footer.
|
|
2058
|
-
.app-sidebar-menu.offcanvas {
|
|
2059
|
-
--bs-offcanvas-width: var(--asm-width, 420px);
|
|
2060
|
-
--bs-offcanvas-bg: var(--color-surface);
|
|
2061
|
-
--bs-offcanvas-color: var(--color-text);
|
|
2062
|
-
--bs-offcanvas-border-color: var(--color-border);
|
|
2063
|
-
--bs-offcanvas-border-width: 1px;
|
|
2064
|
-
--bs-offcanvas-padding-x: 0;
|
|
2065
|
-
--bs-offcanvas-padding-y: 0;
|
|
2066
|
-
max-width: 100vw;
|
|
2067
|
-
display: flex;
|
|
2068
|
-
flex-direction: column;
|
|
2069
|
-
}
|
|
2070
|
-
.app-sidebar-menu .offcanvas-body {
|
|
2071
|
-
padding: 0;
|
|
2072
|
-
display: flex;
|
|
2073
|
-
flex-direction: column;
|
|
2074
|
-
flex: 1;
|
|
2075
|
-
min-height: 0;
|
|
2076
|
-
}
|
|
2077
|
-
.app-sidebar-menu .asm-footer {
|
|
2078
|
-
padding: 16px 20px;
|
|
2079
|
-
border-top: 1px solid var(--color-border);
|
|
2080
|
-
background: var(--color-surface);
|
|
2081
|
-
}
|
|
2082
|
-
|
|
2083
|
-
.drawer {
|
|
2084
|
-
position: fixed;
|
|
2085
|
-
top: 0;
|
|
2086
|
-
right: 0;
|
|
2087
|
-
width: 420px;
|
|
2088
|
-
max-width: 100vw;
|
|
2089
|
-
height: 100vh;
|
|
2090
|
-
background: var(--color-surface);
|
|
2091
|
-
border-left: 1px solid var(--color-border);
|
|
2092
|
-
z-index: 200;
|
|
2093
|
-
transform: translateX(100%);
|
|
2094
|
-
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
2095
|
-
display: flex;
|
|
2096
|
-
flex-direction: column;
|
|
2097
|
-
}
|
|
2098
|
-
.drawer.open {
|
|
2099
|
-
transform: translateX(0);
|
|
2100
|
-
}
|
|
2101
|
-
.drawer-backdrop {
|
|
2102
|
-
position: fixed;
|
|
2103
|
-
inset: 0;
|
|
2104
|
-
background: rgba(15, 23, 42, 0.4);
|
|
2105
|
-
opacity: 0;
|
|
2106
|
-
pointer-events: none;
|
|
2107
|
-
transition: opacity 0.2s;
|
|
2108
|
-
z-index: 150;
|
|
2109
|
-
}
|
|
2110
|
-
.drawer-backdrop.open {
|
|
2111
|
-
opacity: 1;
|
|
2112
|
-
pointer-events: auto;
|
|
2113
|
-
}
|
|
2114
|
-
.drawer-header {
|
|
2115
|
-
padding: 18px 20px;
|
|
2116
|
-
border-bottom: 1px solid var(--color-border);
|
|
2117
|
-
display: flex;
|
|
2118
|
-
align-items: center;
|
|
2119
|
-
justify-content: space-between;
|
|
2120
|
-
background: var(--color-surface);
|
|
2121
|
-
}
|
|
2122
|
-
.drawer-title {
|
|
2123
|
-
font-weight: 600;
|
|
2124
|
-
font-size: 16px;
|
|
2125
|
-
letter-spacing: -0.01em;
|
|
2126
|
-
display: flex;
|
|
2127
|
-
align-items: center;
|
|
2128
|
-
gap: 10px;
|
|
2129
|
-
color: var(--color-text);
|
|
2130
|
-
}
|
|
2131
|
-
.drawer-title-ic {
|
|
2132
|
-
flex: none;
|
|
2133
|
-
display: grid;
|
|
2134
|
-
place-items: center;
|
|
2135
|
-
width: 30px;
|
|
2136
|
-
height: 30px;
|
|
2137
|
-
border-radius: var(--radius);
|
|
2138
|
-
corner-shape: squircle;
|
|
2139
|
-
background: var(--color-primary-soft);
|
|
2140
|
-
color: var(--color-primary);
|
|
2141
|
-
}
|
|
2142
|
-
// Sticky tools zone: search + section meta stay put while the list scrolls.
|
|
2143
|
-
.drawer-tools {
|
|
2144
|
-
padding: 16px 20px 12px;
|
|
2145
|
-
border-bottom: 1px solid var(--color-border);
|
|
2146
|
-
background: var(--color-surface);
|
|
2147
|
-
}
|
|
2148
|
-
.drawer-body {
|
|
2149
|
-
flex: 1;
|
|
2150
|
-
overflow-y: auto;
|
|
2151
|
-
padding: 14px 16px 20px;
|
|
2152
|
-
}
|
|
2153
|
-
|
|
2154
|
-
// ── Tabs ──
|
|
2155
|
-
// The tab strip both surfaces render. React drives it as a controlled strip and
|
|
2156
|
-
// Razor additionally renders Bootstrap panels beneath it, but the strip markup —
|
|
2157
|
-
// and therefore the look — is identical.
|
|
2158
|
-
.app-tabs {
|
|
2159
|
-
display: flex;
|
|
2160
|
-
align-items: center;
|
|
2161
|
-
gap: 2px;
|
|
2162
|
-
border-bottom: 1px solid var(--color-border);
|
|
2163
|
-
overflow-x: auto;
|
|
2164
|
-
scrollbar-width: none;
|
|
2165
|
-
}
|
|
2166
|
-
.app-tabs::-webkit-scrollbar {
|
|
2167
|
-
display: none;
|
|
2168
|
-
}
|
|
2169
|
-
.app-tab {
|
|
2170
|
-
display: inline-flex;
|
|
2171
|
-
align-items: center;
|
|
2172
|
-
gap: 8px;
|
|
2173
|
-
padding: 10px 14px;
|
|
2174
|
-
border: 0;
|
|
2175
|
-
// Sits on the strip's own hairline rather than adding a second one.
|
|
2176
|
-
border-bottom: 2px solid transparent;
|
|
2177
|
-
margin-bottom: -1px;
|
|
2178
|
-
background: transparent;
|
|
2179
|
-
font-family: inherit;
|
|
2180
|
-
font-size: 14px;
|
|
2181
|
-
font-weight: 500;
|
|
2182
|
-
line-height: 1.4;
|
|
2183
|
-
color: var(--color-text-muted);
|
|
2184
|
-
white-space: nowrap;
|
|
2185
|
-
cursor: pointer;
|
|
2186
|
-
transition:
|
|
2187
|
-
color 0.12s ease,
|
|
2188
|
-
border-color 0.12s ease;
|
|
2189
|
-
}
|
|
2190
|
-
.app-tab:hover:not(:disabled):not(.active) {
|
|
2191
|
-
color: var(--color-text);
|
|
2192
|
-
}
|
|
2193
|
-
.app-tab.active {
|
|
2194
|
-
color: var(--color-primary);
|
|
2195
|
-
border-bottom-color: var(--color-primary);
|
|
2196
|
-
}
|
|
2197
|
-
.app-tab:disabled {
|
|
2198
|
-
color: var(--color-text-subtle);
|
|
2199
|
-
cursor: not-allowed;
|
|
2200
|
-
}
|
|
2201
|
-
.app-tab:focus-visible {
|
|
2202
|
-
outline: 2px solid var(--color-primary);
|
|
2203
|
-
outline-offset: -2px;
|
|
2204
|
-
border-radius: var(--radius-sm);
|
|
2205
|
-
}
|
|
2206
|
-
.app-tab.danger.active {
|
|
2207
|
-
color: var(--color-danger);
|
|
2208
|
-
border-bottom-color: var(--color-danger);
|
|
2209
|
-
}
|
|
2210
|
-
// Trailing count pill.
|
|
2211
|
-
.app-tab-count {
|
|
2212
|
-
display: inline-flex;
|
|
2213
|
-
align-items: center;
|
|
2214
|
-
justify-content: center;
|
|
2215
|
-
min-width: 20px;
|
|
2216
|
-
padding: 0 6px;
|
|
2217
|
-
height: 20px;
|
|
2218
|
-
border-radius: 999px;
|
|
2219
|
-
background: var(--color-bg-muted);
|
|
2220
|
-
color: var(--color-text-subtle);
|
|
2221
|
-
font-size: 12px;
|
|
2222
|
-
font-weight: 600;
|
|
2223
|
-
}
|
|
2224
|
-
.app-tab.active .app-tab-count {
|
|
2225
|
-
background: var(--color-primary-soft);
|
|
2226
|
-
color: var(--color-primary);
|
|
2227
|
-
}
|
|
2228
|
-
|
|
2229
|
-
// Wrapper for a self-contained tabs widget (strip + panels), as <app-tabs>
|
|
2230
|
-
// renders server-side. React composes the strip and its panels itself.
|
|
2231
|
-
.app-tabs-group > .tab-content {
|
|
2232
|
-
padding-top: 16px;
|
|
2233
|
-
}
|
|
2234
|
-
|
|
2235
|
-
// Pills variant — a segmented control rather than an underline.
|
|
2236
|
-
.app-tabs-pills {
|
|
2237
|
-
gap: 4px;
|
|
2238
|
-
border-bottom: 0;
|
|
2239
|
-
}
|
|
2240
|
-
.app-tabs-pills .app-tab {
|
|
2241
|
-
border-bottom: 0;
|
|
2242
|
-
margin-bottom: 0;
|
|
2243
|
-
border-radius: var(--radius);
|
|
2244
|
-
}
|
|
2245
|
-
.app-tabs-pills .app-tab.active {
|
|
2246
|
-
background: var(--color-primary-soft);
|
|
2247
|
-
}
|
|
2248
|
-
|
|
2249
|
-
// ── Search field ──
|
|
2250
|
-
// The search control both surfaces render: a rounded field with a leading
|
|
2251
|
-
// magnifier that takes the brand colour on focus, plus a clear button that
|
|
2252
|
-
// appears once there's a value.
|
|
2253
|
-
.search-wrap {
|
|
2254
|
-
position: relative;
|
|
2255
|
-
display: flex;
|
|
2256
|
-
align-items: center;
|
|
2257
|
-
width: 100%;
|
|
2258
|
-
}
|
|
2259
|
-
.search-wrap > .search-icon {
|
|
2260
|
-
position: absolute;
|
|
2261
|
-
left: 13px;
|
|
2262
|
-
top: 50%;
|
|
2263
|
-
transform: translateY(-50%);
|
|
2264
|
-
display: grid;
|
|
2265
|
-
place-items: center;
|
|
2266
|
-
color: var(--color-text-subtle);
|
|
2267
|
-
pointer-events: none;
|
|
2268
|
-
transition: color 0.12s ease;
|
|
2269
|
-
}
|
|
2270
|
-
.search-wrap:focus-within > .search-icon {
|
|
2271
|
-
color: var(--color-primary);
|
|
2272
|
-
}
|
|
2273
|
-
.search-field,
|
|
2274
|
-
.search-input {
|
|
2275
|
-
width: 100%;
|
|
2276
|
-
padding-left: 40px;
|
|
2277
|
-
padding-right: 36px;
|
|
2278
|
-
}
|
|
2279
|
-
.search-clear {
|
|
2280
|
-
position: absolute;
|
|
2281
|
-
right: 8px;
|
|
2282
|
-
top: 50%;
|
|
2283
|
-
transform: translateY(-50%);
|
|
2284
|
-
display: grid;
|
|
2285
|
-
place-items: center;
|
|
2286
|
-
width: 26px;
|
|
2287
|
-
height: 26px;
|
|
2288
|
-
padding: 0;
|
|
2289
|
-
border: 0;
|
|
2290
|
-
border-radius: 999px;
|
|
2291
|
-
background: transparent;
|
|
2292
|
-
color: var(--color-text-subtle);
|
|
2293
|
-
cursor: pointer;
|
|
2294
|
-
opacity: 0;
|
|
2295
|
-
pointer-events: none;
|
|
2296
|
-
transition:
|
|
2297
|
-
opacity 0.12s ease,
|
|
2298
|
-
color 0.12s ease;
|
|
2299
|
-
}
|
|
2300
|
-
.search-wrap.has-value .search-clear,
|
|
2301
|
-
.search-wrap:focus-within .search-clear {
|
|
2302
|
-
opacity: 1;
|
|
2303
|
-
pointer-events: auto;
|
|
2304
|
-
}
|
|
2305
|
-
.search-clear:hover {
|
|
2306
|
-
color: var(--color-text);
|
|
2307
|
-
}
|
|
2308
|
-
|
|
2309
|
-
// ── Empty state ──
|
|
2310
|
-
.empty-state {
|
|
2311
|
-
text-align: center;
|
|
2312
|
-
padding: 48px 24px;
|
|
2313
|
-
color: var(--color-text-subtle);
|
|
2314
|
-
}
|
|
2315
|
-
.empty-state-title {
|
|
2316
|
-
font-size: 16px;
|
|
2317
|
-
font-weight: 600;
|
|
2318
|
-
line-height: 1.35;
|
|
2319
|
-
color: var(--color-text);
|
|
2320
|
-
}
|
|
2321
|
-
.empty-state-message {
|
|
2322
|
-
margin: 6px 0 0;
|
|
2323
|
-
font-size: 14px;
|
|
2324
|
-
line-height: 1.5;
|
|
2325
|
-
color: var(--color-text-muted);
|
|
2326
|
-
}
|
|
2327
|
-
.empty-state-action {
|
|
2328
|
-
margin-top: 16px;
|
|
2329
|
-
}
|
|
2330
|
-
// Tighter scale for a widget/tile, as opposed to a full card or page.
|
|
2331
|
-
.empty-state-sm {
|
|
2332
|
-
padding: 28px 16px;
|
|
2333
|
-
}
|
|
2334
|
-
.empty-state-sm .empty-state-title {
|
|
2335
|
-
font-size: 14px;
|
|
2336
|
-
}
|
|
2337
|
-
.empty-state-sm .empty-state-message {
|
|
2338
|
-
font-size: 12px;
|
|
2339
|
-
}
|
|
2340
|
-
.empty-state-icon {
|
|
2341
|
-
width: 48px;
|
|
2342
|
-
height: 48px;
|
|
2343
|
-
border-radius: var(--radius-lg);
|
|
2344
|
-
background: var(--color-primary-soft);
|
|
2345
|
-
color: var(--color-primary);
|
|
2346
|
-
display: inline-flex;
|
|
2347
|
-
align-items: center;
|
|
2348
|
-
justify-content: center;
|
|
2349
|
-
margin-bottom: 14px;
|
|
2350
|
-
}
|
|
2351
|
-
|
|
2352
|
-
// The empty state a DataTable renders in place of its rows. Distinct from
|
|
2353
|
-
// the card-level .empty-state above: a 50px primary-tinted disc, then a 32px
|
|
2354
|
-
// gap to the title and 12px to the subtitle.
|
|
2355
|
-
.tbl-empty {
|
|
2356
|
-
display: flex;
|
|
2357
|
-
flex-direction: column;
|
|
2358
|
-
align-items: center;
|
|
2359
|
-
text-align: center;
|
|
2360
|
-
padding: 40px 24px;
|
|
2361
|
-
}
|
|
2362
|
-
.tbl-empty-icon {
|
|
2363
|
-
display: inline-grid;
|
|
2364
|
-
place-items: center;
|
|
2365
|
-
flex: none;
|
|
2366
|
-
width: 50px;
|
|
2367
|
-
height: 50px;
|
|
2368
|
-
border-radius: 50%;
|
|
2369
|
-
background: color-mix(in srgb, var(--color-primary) 10%, transparent);
|
|
2370
|
-
color: var(--color-primary);
|
|
2371
|
-
margin-bottom: 16px;
|
|
2372
|
-
}
|
|
2373
|
-
.tbl-empty-title {
|
|
2374
|
-
font-size: 18px;
|
|
2375
|
-
font-weight: 600;
|
|
2376
|
-
line-height: 1.35;
|
|
2377
|
-
color: var(--color-text);
|
|
2378
|
-
}
|
|
2379
|
-
.tbl-empty-text {
|
|
2380
|
-
margin-top: 8px;
|
|
2381
|
-
font-size: 16px;
|
|
2382
|
-
font-weight: 400;
|
|
2383
|
-
line-height: 1.5;
|
|
2384
|
-
color: var(--color-text-muted);
|
|
2385
|
-
}
|
|
2386
|
-
// An action (e.g. "New assessment") sits under the subtitle when the caller
|
|
2387
|
-
// supplies one.
|
|
2388
|
-
.tbl-empty-action {
|
|
2389
|
-
margin-top: 20px;
|
|
2390
|
-
}
|
|
2391
|
-
|
|
2392
|
-
.lx-table-empty {
|
|
2393
|
-
padding: 36px 24px;
|
|
2394
|
-
text-align: center;
|
|
2395
|
-
color: var(--color-text-muted);
|
|
2396
|
-
}
|
|
2397
|
-
// The empty state owns its own padding and is not a row you can act on — no
|
|
2398
|
-
// cell padding, no border, and no hover fill from .table / .table-ledger.
|
|
2399
|
-
.table td.lx-table-empty:has(> .tbl-empty) {
|
|
2400
|
-
padding: 0;
|
|
2401
|
-
border-bottom: 0;
|
|
2402
|
-
}
|
|
2403
|
-
.table tbody tr:hover td.lx-table-empty:has(> .tbl-empty),
|
|
2404
|
-
.table-ledger tbody tr:hover td.lx-table-empty:has(> .tbl-empty) {
|
|
2405
|
-
background: transparent;
|
|
2406
|
-
}
|
|
2407
|
-
|
|
2408
|
-
// ── Table (base) ──
|
|
2409
|
-
// The shared data-table look, on the plain `.table` class Bootstrap already
|
|
2410
|
-
// gives every table. Without this a product's tables fall back to stock
|
|
2411
|
-
// Bootstrap and drift from the design system; `.table-ledger` below is the
|
|
2412
|
-
// denser, card-inset variant, not a replacement for having a base.
|
|
2413
|
-
.table {
|
|
2414
|
-
--bs-table-bg: transparent;
|
|
2415
|
-
--bs-table-color: var(--color-text);
|
|
2416
|
-
width: 100%;
|
|
2417
|
-
margin-bottom: 0;
|
|
2418
|
-
color: var(--color-text);
|
|
2419
|
-
vertical-align: middle;
|
|
2420
|
-
border-color: var(--color-border);
|
|
2421
|
-
}
|
|
2422
|
-
.table > thead > tr > th {
|
|
2423
|
-
height: 42px;
|
|
2424
|
-
padding: 0 12px;
|
|
2425
|
-
background: var(--color-bg-muted);
|
|
2426
|
-
border-bottom: 1px solid var(--color-border);
|
|
2427
|
-
font-size: 12px;
|
|
2428
|
-
font-weight: 500;
|
|
2429
|
-
letter-spacing: 0.04em;
|
|
2430
|
-
text-transform: uppercase;
|
|
2431
|
-
color: var(--color-text-subtle);
|
|
2432
|
-
white-space: nowrap;
|
|
2433
|
-
vertical-align: middle;
|
|
2434
|
-
}
|
|
2435
|
-
.table > tbody > tr > td {
|
|
2436
|
-
padding: 12px;
|
|
2437
|
-
border-bottom: 1px solid var(--color-border);
|
|
2438
|
-
font-size: 14px;
|
|
2439
|
-
color: var(--color-text-muted);
|
|
2440
|
-
vertical-align: middle;
|
|
2441
|
-
}
|
|
2442
|
-
.table > tbody > tr:last-child > td {
|
|
2443
|
-
border-bottom: 0;
|
|
2444
|
-
}
|
|
2445
|
-
.table > tbody > tr:hover > td {
|
|
2446
|
-
background: var(--color-bg-subtle);
|
|
2447
|
-
}
|
|
2448
|
-
// Numeric / action columns align to the trailing edge.
|
|
2449
|
-
.table .cell-end,
|
|
2450
|
-
.table thead th.cell-end {
|
|
2451
|
-
text-align: right;
|
|
2452
|
-
}
|
|
2453
|
-
|
|
2454
|
-
// ── Table + pagination ──
|
|
2455
|
-
// DataTable cell helpers
|
|
2456
|
-
.table-ledger .lx-cell-end,
|
|
2457
|
-
.table-ledger thead th.lx-cell-end {
|
|
2458
|
-
text-align: right;
|
|
2459
|
-
}
|
|
2460
|
-
|
|
2461
|
-
// Ledger chrome — the shared table look. Applies to every .table-ledger: a
|
|
2462
|
-
// floating 42px header band, airy rows on a hairline rule, and an inset from
|
|
2463
|
-
// the card edge. Column geometry is NOT set here.
|
|
2464
|
-
.table-wrap:has(> .table-ledger) {
|
|
2465
|
-
padding: 20px 20px 0;
|
|
2466
|
-
}
|
|
2467
|
-
.table-ledger {
|
|
2468
|
-
border-spacing: 0;
|
|
2469
|
-
}
|
|
2470
|
-
.table-ledger thead th {
|
|
2471
|
-
height: 42px;
|
|
2472
|
-
padding: 0 12px;
|
|
2473
|
-
background: var(--color-bg-muted);
|
|
2474
|
-
border-bottom: none;
|
|
2475
|
-
font-family: "Inter", var(--font-sans, sans-serif);
|
|
2476
|
-
font-size: 12px;
|
|
2477
|
-
font-weight: 500;
|
|
2478
|
-
line-height: 17px;
|
|
2479
|
-
letter-spacing: 0.04em;
|
|
2480
|
-
text-transform: uppercase;
|
|
2481
|
-
color: var(--color-text-subtle);
|
|
2482
|
-
vertical-align: middle;
|
|
2483
|
-
}
|
|
2484
|
-
.table-ledger thead th:first-child {
|
|
2485
|
-
padding-left: 20px;
|
|
2486
|
-
border-radius: var(--radius-sm) 0 0 var(--radius-sm);
|
|
2487
|
-
}
|
|
2488
|
-
.table-ledger thead th:last-child {
|
|
2489
|
-
padding-right: 20px;
|
|
2490
|
-
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
2491
|
-
}
|
|
2492
|
-
.table-ledger tbody td {
|
|
2493
|
-
height: 54px;
|
|
2494
|
-
padding: 12px;
|
|
2495
|
-
border-bottom: 0.5px solid var(--color-border);
|
|
2496
|
-
font-family: "Inter", var(--font-sans, sans-serif);
|
|
2497
|
-
font-size: 12px;
|
|
2498
|
-
font-weight: 500;
|
|
2499
|
-
line-height: 15px;
|
|
2500
|
-
color: var(--color-text-muted);
|
|
2501
|
-
}
|
|
2502
|
-
.table-ledger tbody td:first-child {
|
|
2503
|
-
padding-left: 20px;
|
|
2504
|
-
}
|
|
2505
|
-
.table-ledger tbody td:last-child {
|
|
2506
|
-
padding-right: 20px;
|
|
2507
|
-
}
|
|
2508
|
-
.table-ledger tbody tr:last-child td {
|
|
2509
|
-
border-bottom: none;
|
|
2510
|
-
}
|
|
2511
|
-
.table-ledger tbody tr:hover td {
|
|
2512
|
-
background: var(--color-bg-subtle);
|
|
2513
|
-
}
|
|
2514
|
-
.table-ledger .u-meta {
|
|
2515
|
-
gap: 2px;
|
|
2516
|
-
}
|
|
2517
|
-
.table-ledger .u-name {
|
|
2518
|
-
font-size: 14px;
|
|
2519
|
-
font-weight: 500;
|
|
2520
|
-
line-height: 19px;
|
|
2521
|
-
color: var(--color-text);
|
|
2522
|
-
}
|
|
2523
|
-
@media (max-width: 575.98px) {
|
|
2524
|
-
.table-ledger .u-name {
|
|
2525
|
-
font-size: 12px;
|
|
2526
|
-
line-height: normal;
|
|
2527
|
-
margin-bottom: 2px;
|
|
2528
|
-
}
|
|
2529
|
-
}
|
|
2530
|
-
// An identity-cell name is often a link, so it inherits Bootstrap's
|
|
2531
|
-
// underline-on-hover. The colour shift is the affordance here.
|
|
2532
|
-
.table-ledger a.u-name,
|
|
2533
|
-
.table-ledger a.u-name:hover {
|
|
2534
|
-
text-decoration: none;
|
|
2535
|
-
}
|
|
2536
|
-
// Identity-cell subline. `.u-email` is in the group because an identity cell
|
|
2537
|
-
// renders the secondary line as either a generic .lx-text-xs or a .u-email.
|
|
2538
|
-
.table-ledger .u-meta > .u-email,
|
|
2539
|
-
.table-ledger .u-meta > .lx-text-xs {
|
|
2540
|
-
font-size: 12px;
|
|
2541
|
-
font-weight: 400;
|
|
2542
|
-
line-height: 15px;
|
|
2543
|
-
color: var(--color-text-subtle);
|
|
2544
|
-
}
|
|
2545
|
-
.table-ledger .u-row-actions {
|
|
2546
|
-
gap: 6px;
|
|
2547
|
-
}
|
|
2548
|
-
|
|
2549
|
-
// Ledger tables: 20px edge padding so header labels + first/last cells align
|
|
2550
|
-
// with the card edge — shared across every .table-ledger surface.
|
|
2551
|
-
.table-ledger thead th:first-child,
|
|
2552
|
-
.table-ledger tbody td:first-child {
|
|
2553
|
-
padding-left: 20px;
|
|
2554
|
-
}
|
|
2555
|
-
.table-ledger thead th:last-child,
|
|
2556
|
-
.table-ledger tbody td:last-child {
|
|
2557
|
-
padding-right: 20px;
|
|
2558
|
-
}
|
|
2559
|
-
|
|
2560
|
-
// Pagination footer — rows-per-page + range + prev/next, sits flush under a
|
|
2561
|
-
// table.
|
|
2562
|
-
.table-pagination {
|
|
2563
|
-
display: flex;
|
|
2564
|
-
align-items: center;
|
|
2565
|
-
justify-content: flex-end;
|
|
2566
|
-
gap: 22px;
|
|
2567
|
-
padding: 12px 16px;
|
|
2568
|
-
border-top: 1px solid var(--color-border);
|
|
2569
|
-
font-size: 13px;
|
|
2570
|
-
color: var(--color-text-muted);
|
|
2571
|
-
flex-wrap: wrap;
|
|
2572
|
-
}
|
|
2573
|
-
// Rows-per-page sits at the leading edge; range + nav stay grouped on the
|
|
2574
|
-
// right.
|
|
2575
|
-
.tpg-rows {
|
|
2576
|
-
display: inline-flex;
|
|
2577
|
-
align-items: center;
|
|
2578
|
-
gap: 8px;
|
|
2579
|
-
white-space: nowrap;
|
|
2580
|
-
margin-right: auto;
|
|
2581
|
-
font-size: 12px;
|
|
2582
|
-
font-weight: 500;
|
|
2583
|
-
text-transform: uppercase;
|
|
2584
|
-
color: var(--color-text-subtle);
|
|
2585
|
-
}
|
|
2586
|
-
.select.tpg-select {
|
|
2587
|
-
width: auto;
|
|
2588
|
-
min-width: 64px;
|
|
2589
|
-
height: 32px;
|
|
2590
|
-
min-height: 32px;
|
|
2591
|
-
padding: 0 28px 0 12px;
|
|
2592
|
-
font-size: 13px;
|
|
2593
|
-
font-weight: 600;
|
|
2594
|
-
border-radius: var(--radius);
|
|
2595
|
-
background-position: right 8px center;
|
|
2596
|
-
background-size: 14px;
|
|
2597
|
-
}
|
|
2598
|
-
.tpg-range {
|
|
2599
|
-
font-variant-numeric: tabular-nums;
|
|
2600
|
-
white-space: nowrap;
|
|
2601
|
-
font-size: 14px;
|
|
2602
|
-
font-weight: 500;
|
|
2603
|
-
color: var(--color-text-muted);
|
|
2604
|
-
}
|
|
2605
|
-
.tpg-nav {
|
|
2606
|
-
display: inline-flex;
|
|
2607
|
-
align-items: center;
|
|
2608
|
-
gap: 4px;
|
|
2609
|
-
}
|
|
2610
|
-
.tpg-arrow {
|
|
2611
|
-
display: grid;
|
|
2612
|
-
place-items: center;
|
|
2613
|
-
width: 32px;
|
|
2614
|
-
height: 32px;
|
|
2615
|
-
border: none;
|
|
2616
|
-
background: transparent;
|
|
2617
|
-
color: var(--color-text-muted);
|
|
2618
|
-
border-radius: 50%;
|
|
2619
|
-
cursor: pointer;
|
|
2620
|
-
transition:
|
|
2621
|
-
background 0.14s ease,
|
|
2622
|
-
color 0.14s ease;
|
|
2623
|
-
}
|
|
2624
|
-
.tpg-arrow:hover:not(:disabled) {
|
|
2625
|
-
background: color-mix(in srgb, var(--color-primary) 10%, transparent);
|
|
2626
|
-
color: var(--color-primary);
|
|
2627
|
-
}
|
|
2628
|
-
// Text-5 already reads as "unavailable" — no opacity dimming on top of it.
|
|
2629
|
-
.tpg-arrow:disabled {
|
|
2630
|
-
color: var(--color-border-strong);
|
|
2631
|
-
cursor: not-allowed;
|
|
2632
|
-
}
|
|
2633
|
-
|
|
2634
|
-
// Horizontal scroll guard + flush-fit inside a card. Wrapping the table here
|
|
2635
|
-
// also stops `.card > .table` header-corner rounding from applying mid-card.
|
|
2636
|
-
.table-wrap {
|
|
2637
|
-
overflow-x: auto;
|
|
2638
|
-
max-width: 100%;
|
|
2639
|
-
// Keep the horizontal swipe inside the table — don't let it drag the
|
|
2640
|
-
// page — and give touch devices momentum scrolling. Scrollbar is
|
|
2641
|
-
// thinned/hidden so the scroll feels native.
|
|
2642
|
-
overscroll-behavior-x: contain;
|
|
2643
|
-
-webkit-overflow-scrolling: touch;
|
|
2644
|
-
scrollbar-width: thin;
|
|
2645
|
-
scrollbar-color: var(--color-border-strong) transparent;
|
|
2646
|
-
}
|
|
2647
|
-
.table-wrap::-webkit-scrollbar {
|
|
2648
|
-
height: 6px;
|
|
2649
|
-
}
|
|
2650
|
-
.table-wrap::-webkit-scrollbar-track {
|
|
2651
|
-
background: transparent;
|
|
2652
|
-
}
|
|
2653
|
-
.table-wrap::-webkit-scrollbar-thumb {
|
|
2654
|
-
background: var(--color-border-strong);
|
|
2655
|
-
border-radius: 999px;
|
|
2656
|
-
}
|
|
2657
|
-
|
|
2658
|
-
// Row-selection checkbox column.
|
|
2659
|
-
.table-ledger th.lx-select-cell,
|
|
2660
|
-
.table-ledger td.lx-select-cell {
|
|
2661
|
-
width: 44px;
|
|
2662
|
-
min-width: 44px;
|
|
2663
|
-
max-width: 44px;
|
|
2664
|
-
text-align: center;
|
|
2665
|
-
padding-left: 12px;
|
|
2666
|
-
padding-right: 0;
|
|
2667
|
-
}
|
|
2668
|
-
.table-ledger tbody tr.is-selected {
|
|
2669
|
-
background: var(--color-bg-muted);
|
|
2670
|
-
}
|
|
2671
|
-
|
|
2672
|
-
// Row actions — icon-only buttons replacing a kebab dropdown.
|
|
2673
|
-
.u-row-actions {
|
|
2674
|
-
display: flex;
|
|
2675
|
-
align-items: center;
|
|
2676
|
-
justify-content: flex-end;
|
|
2677
|
-
gap: 6px;
|
|
2678
|
-
// Action cells never wrap — a status hint stays on one line.
|
|
2679
|
-
white-space: nowrap;
|
|
2680
|
-
}
|
|
2681
|
-
.u-action {
|
|
2682
|
-
display: inline-grid;
|
|
2683
|
-
place-items: center;
|
|
2684
|
-
flex: none;
|
|
2685
|
-
width: 36px;
|
|
2686
|
-
height: 36px;
|
|
2687
|
-
padding: 0;
|
|
2688
|
-
border: none;
|
|
2689
|
-
background: var(--color-bg-subtle);
|
|
2690
|
-
border-radius: 999px;
|
|
2691
|
-
color: var(--color-text-subtle);
|
|
2692
|
-
cursor: pointer;
|
|
2693
|
-
transition:
|
|
2694
|
-
background 0.12s ease,
|
|
2695
|
-
color 0.12s ease;
|
|
2696
|
-
position: relative;
|
|
2697
|
-
}
|
|
2698
|
-
// Touch pointers need a 44px minimum target. Grow the hit area, not the
|
|
2699
|
-
// ink, so row density and alignment are untouched.
|
|
2700
|
-
@media (pointer: coarse) {
|
|
2701
|
-
.u-action::after {
|
|
2702
|
-
content: "";
|
|
2703
|
-
position: absolute;
|
|
2704
|
-
top: 50%;
|
|
2705
|
-
left: 50%;
|
|
2706
|
-
transform: translate(-50%, -50%);
|
|
2707
|
-
width: 44px;
|
|
2708
|
-
height: 44px;
|
|
2709
|
-
}
|
|
2710
|
-
}
|
|
2711
|
-
.u-action svg {
|
|
2712
|
-
flex: none;
|
|
2713
|
-
}
|
|
2714
|
-
.u-action:hover:not(:disabled) {
|
|
2715
|
-
background: color-mix(in srgb, var(--color-primary) 10%, transparent);
|
|
2716
|
-
color: var(--color-primary);
|
|
2717
|
-
}
|
|
2718
|
-
.u-action:disabled {
|
|
2719
|
-
opacity: 0.4;
|
|
2720
|
-
cursor: not-allowed;
|
|
2721
|
-
}
|
|
2722
|
-
.u-action.danger {
|
|
2723
|
-
color: var(--color-danger);
|
|
2724
|
-
}
|
|
2725
|
-
.u-action.danger:hover:not(:disabled) {
|
|
2726
|
-
background: color-mix(in srgb, var(--color-danger) 10%, transparent);
|
|
2727
|
-
color: var(--color-danger);
|
|
2728
|
-
}
|
|
2729
|
-
.u-action.u-action-preview {
|
|
2730
|
-
background: var(--color-primary-soft);
|
|
2731
|
-
color: var(--color-primary);
|
|
2732
|
-
}
|
|
2733
|
-
.u-action.u-action-download {
|
|
2734
|
-
background: var(--color-success-soft);
|
|
2735
|
-
color: var(--color-success-active);
|
|
2736
|
-
}
|
|
2737
|
-
.u-action.u-action-share {
|
|
2738
|
-
background: var(--color-warning-soft);
|
|
2739
|
-
color: var(--color-warning-active);
|
|
2740
|
-
}
|
|
2741
|
-
.u-action.u-action-preview:hover:not(:disabled) {
|
|
2742
|
-
background: var(--color-primary-soft);
|
|
2743
|
-
color: var(--color-primary);
|
|
2744
|
-
}
|
|
2745
|
-
.u-action.u-action-download:hover:not(:disabled) {
|
|
2746
|
-
background: var(--color-success-soft);
|
|
2747
|
-
color: var(--color-success-active);
|
|
2748
|
-
}
|
|
2749
|
-
.u-action.u-action-share:hover:not(:disabled) {
|
|
2750
|
-
background: var(--color-warning-soft);
|
|
2751
|
-
color: var(--color-warning-active);
|
|
2752
|
-
}
|
|
2753
|
-
.u-action.u-action-danger:hover {
|
|
2754
|
-
color: var(--color-danger);
|
|
2755
|
-
background: color-mix(in srgb, var(--color-danger) 10%, transparent);
|
|
2756
|
-
}
|
|
2757
|
-
|
|
2758
|
-
// Identity cell — avatar + stacked name/email.
|
|
2759
|
-
.u-cell {
|
|
2760
|
-
display: flex;
|
|
2761
|
-
align-items: center;
|
|
2762
|
-
gap: 14px;
|
|
2763
|
-
}
|
|
2764
|
-
.u-avatar {
|
|
2765
|
-
width: 40px;
|
|
2766
|
-
height: 40px;
|
|
2767
|
-
border-radius: 50%;
|
|
2768
|
-
flex: none;
|
|
2769
|
-
display: grid;
|
|
2770
|
-
place-items: center;
|
|
2771
|
-
font-size: 16px;
|
|
2772
|
-
font-weight: 600;
|
|
2773
|
-
color: var(--color-primary);
|
|
2774
|
-
background: color-mix(in srgb, var(--color-primary) 20%, transparent);
|
|
2775
|
-
}
|
|
2776
|
-
.u-meta {
|
|
2777
|
-
display: flex;
|
|
2778
|
-
flex-direction: column;
|
|
2779
|
-
min-width: 0;
|
|
2780
|
-
}
|
|
2781
|
-
.u-name {
|
|
2782
|
-
display: inline-flex;
|
|
2783
|
-
align-items: center;
|
|
2784
|
-
gap: 8px;
|
|
2785
|
-
font-size: 14px;
|
|
2786
|
-
font-weight: 600;
|
|
2787
|
-
color: var(--color-text);
|
|
2788
|
-
}
|
|
2789
|
-
.u-email {
|
|
2790
|
-
font-size: 14px;
|
|
2791
|
-
font-weight: 400;
|
|
2792
|
-
color: var(--color-text-muted);
|
|
2793
|
-
}
|
|
2794
|
-
.u-you {
|
|
2795
|
-
padding: 1px 7px;
|
|
2796
|
-
font-size: 10.5px;
|
|
2797
|
-
}
|
|
2798
|
-
|
|
2799
|
-
// ── Modal ──
|
|
2800
|
-
// Chrome stays on `.lx-modal-*`. The shell is react-bootstrap <Modal>:
|
|
2801
|
-
// .modal.lx-modal-shell ← className (layout container)
|
|
2802
|
-
// .modal-backdrop.lx-modal-dim ← backdropClassName (dim only)
|
|
2803
|
-
// .modal-dialog.lx-rb-dialog ← dialogClassName
|
|
2804
|
-
// .modal-content.lx-modal ← contentClassName (the card)
|
|
2805
|
-
// Do NOT put layout on backdropClassName — that targets a sibling, not
|
|
2806
|
-
// .modal.
|
|
2807
|
-
.modal-backdrop.lx-modal-dim {
|
|
2808
|
-
background: rgba(15, 23, 42, 0.45);
|
|
2809
|
-
z-index: 1500;
|
|
2810
|
-
}
|
|
2811
|
-
.modal.lx-modal-shell {
|
|
2812
|
-
--bs-modal-bg: transparent;
|
|
2813
|
-
display: flex !important;
|
|
2814
|
-
align-items: center;
|
|
2815
|
-
justify-content: center;
|
|
2816
|
-
z-index: 1505;
|
|
2817
|
-
padding: 20px;
|
|
2818
|
-
}
|
|
2819
|
-
// RB dialog shell: no Bootstrap max-width/margin so `.lx-modal` owns sizing.
|
|
2820
|
-
.modal.lx-modal-shell .modal-dialog.lx-rb-dialog {
|
|
2821
|
-
margin: 0;
|
|
2822
|
-
max-width: none;
|
|
2823
|
-
width: auto;
|
|
2824
|
-
pointer-events: none;
|
|
2825
|
-
display: flex;
|
|
2826
|
-
align-items: center;
|
|
2827
|
-
justify-content: center;
|
|
2828
|
-
}
|
|
2829
|
-
.modal.lx-modal-shell .modal-dialog.lx-rb-dialog .modal-content {
|
|
2830
|
-
pointer-events: auto;
|
|
2831
|
-
border: none;
|
|
2832
|
-
// Lift off the dim backdrop: a hairline ring defines the edge (carries
|
|
2833
|
-
// elevation in dark mode where a drop shadow barely reads) + a soft,
|
|
2834
|
-
// deep drop shadow.
|
|
2835
|
-
box-shadow:
|
|
2836
|
-
0 0 0 1px color-mix(in srgb, var(--color-text) 10%, transparent),
|
|
2837
|
-
var(--shadow-overlay-lg);
|
|
2838
|
-
background: var(--color-surface);
|
|
2839
|
-
}
|
|
2840
|
-
.lx-modal {
|
|
2841
|
-
background: var(--color-surface);
|
|
2842
|
-
border-radius: var(--radius-xl);
|
|
2843
|
-
corner-shape: squircle;
|
|
2844
|
-
border: none;
|
|
2845
|
-
width: 100%;
|
|
2846
|
-
max-width: 440px;
|
|
2847
|
-
max-height: calc(100vh - 40px);
|
|
2848
|
-
display: flex;
|
|
2849
|
-
flex-direction: column;
|
|
2850
|
-
overflow: hidden;
|
|
2851
|
-
}
|
|
2852
|
-
.lx-modal-wide {
|
|
2853
|
-
max-width: 1240px;
|
|
2854
|
-
}
|
|
2855
|
-
|
|
2856
|
-
// Side drawer — the dialog docks to the right edge at 30% of the viewport
|
|
2857
|
-
// and slides in, instead of sitting centred. Same chrome, different
|
|
2858
|
-
// geometry.
|
|
2859
|
-
.modal.lx-modal-shell.is-side {
|
|
2860
|
-
align-items: stretch;
|
|
2861
|
-
justify-content: flex-end;
|
|
2862
|
-
padding: 0;
|
|
2863
|
-
}
|
|
2864
|
-
.modal.lx-modal-shell.is-side .modal-dialog.lx-rb-dialog {
|
|
2865
|
-
height: 100%;
|
|
2866
|
-
width: auto;
|
|
2867
|
-
max-width: none;
|
|
2868
|
-
align-items: stretch;
|
|
2869
|
-
justify-content: flex-end;
|
|
2870
|
-
}
|
|
2871
|
-
.lx-modal-side {
|
|
2872
|
-
width: 30vw;
|
|
2873
|
-
min-width: 420px;
|
|
2874
|
-
max-width: none;
|
|
2875
|
-
max-height: 100vh;
|
|
2876
|
-
height: 100vh;
|
|
2877
|
-
border-radius: 0;
|
|
2878
|
-
corner-shape: normal;
|
|
2879
|
-
animation: lx-drawer-in 0.32s cubic-bezier(0.22, 1, 0.36, 1);
|
|
2880
|
-
}
|
|
2881
|
-
@media (max-width: 991.98px) {
|
|
2882
|
-
.lx-modal-side {
|
|
2883
|
-
width: 70vw;
|
|
2884
|
-
}
|
|
2885
|
-
}
|
|
2886
|
-
@media (max-width: 575.98px) {
|
|
2887
|
-
.lx-modal-side {
|
|
2888
|
-
width: 100vw;
|
|
2889
|
-
}
|
|
2890
|
-
}
|
|
2891
|
-
@keyframes lx-drawer-in {
|
|
2892
|
-
from {
|
|
2893
|
-
transform: translateX(100%);
|
|
2894
|
-
}
|
|
2895
|
-
to {
|
|
2896
|
-
transform: translateX(0);
|
|
2897
|
-
}
|
|
2898
|
-
}
|
|
2899
|
-
@media (prefers-reduced-motion: reduce) {
|
|
2900
|
-
.lx-modal-side {
|
|
2901
|
-
animation: none;
|
|
2902
|
-
}
|
|
2903
|
-
}
|
|
2904
|
-
.lx-modal-header {
|
|
2905
|
-
flex: 0 0 auto;
|
|
2906
|
-
display: flex;
|
|
2907
|
-
align-items: center;
|
|
2908
|
-
justify-content: space-between;
|
|
2909
|
-
gap: 12px;
|
|
2910
|
-
padding: 16px 20px;
|
|
2911
|
-
border-bottom: 1px solid var(--color-border);
|
|
2912
|
-
}
|
|
2913
|
-
.lx-modal-body {
|
|
2914
|
-
flex: 1 1 auto;
|
|
2915
|
-
min-height: 0;
|
|
2916
|
-
overflow-y: auto;
|
|
2917
|
-
overscroll-behavior: contain;
|
|
2918
|
-
scroll-behavior: smooth;
|
|
2919
|
-
-webkit-overflow-scrolling: touch;
|
|
2920
|
-
scrollbar-width: thin;
|
|
2921
|
-
scrollbar-color: var(--color-border-strong) transparent;
|
|
2922
|
-
padding: 20px 22px 24px;
|
|
2923
|
-
}
|
|
2924
|
-
.lx-modal-body::-webkit-scrollbar {
|
|
2925
|
-
width: 8px;
|
|
2926
|
-
}
|
|
2927
|
-
.lx-modal-body::-webkit-scrollbar-track {
|
|
2928
|
-
background: transparent;
|
|
2929
|
-
}
|
|
2930
|
-
.lx-modal-body::-webkit-scrollbar-thumb {
|
|
2931
|
-
background: transparent;
|
|
2932
|
-
border-radius: 999px;
|
|
2933
|
-
border: 2px solid transparent;
|
|
2934
|
-
background-clip: padding-box;
|
|
2935
|
-
}
|
|
2936
|
-
.lx-modal-body:hover::-webkit-scrollbar-thumb {
|
|
2937
|
-
background: var(--color-border-strong);
|
|
2938
|
-
background-clip: padding-box;
|
|
2939
|
-
}
|
|
2940
|
-
@media (prefers-reduced-motion: reduce) {
|
|
2941
|
-
.lx-modal-body {
|
|
2942
|
-
scroll-behavior: auto;
|
|
2943
|
-
}
|
|
2944
|
-
}
|
|
2945
|
-
// Modal heading group: optional contextual (Bulk) icon tile + title/subtitle.
|
|
2946
|
-
.lx-modal-heading {
|
|
2947
|
-
display: flex;
|
|
2948
|
-
align-items: center;
|
|
2949
|
-
gap: 10px;
|
|
2950
|
-
min-width: 0;
|
|
2951
|
-
}
|
|
2952
|
-
.lx-modal-headtext {
|
|
2953
|
-
min-width: 0;
|
|
2954
|
-
}
|
|
2955
|
-
.lx-modal-headicon {
|
|
2956
|
-
display: inline-flex;
|
|
2957
|
-
align-items: center;
|
|
2958
|
-
justify-content: center;
|
|
2959
|
-
width: 34px;
|
|
2960
|
-
height: 34px;
|
|
2961
|
-
border-radius: var(--radius);
|
|
2962
|
-
corner-shape: squircle;
|
|
2963
|
-
flex: none;
|
|
2964
|
-
background: var(--color-primary-soft);
|
|
2965
|
-
color: var(--color-primary);
|
|
2966
|
-
}
|
|
2967
|
-
|
|
2968
|
-
// Break long unbroken names so they wrap within the heading instead of
|
|
2969
|
-
// running under the close button.
|
|
2970
|
-
.lx-modal-title {
|
|
2971
|
-
font-size: 20px;
|
|
2972
|
-
font-weight: 600;
|
|
2973
|
-
color: var(--color-text);
|
|
2974
|
-
overflow-wrap: anywhere;
|
|
2975
|
-
}
|
|
2976
|
-
.lx-modal-subtitle {
|
|
2977
|
-
margin-top: 1px;
|
|
2978
|
-
font-size: 12px;
|
|
2979
|
-
font-weight: 400;
|
|
2980
|
-
color: var(--color-text-muted);
|
|
2981
|
-
overflow-wrap: anywhere;
|
|
2982
|
-
}
|
|
2983
|
-
.lx-form-section {
|
|
2984
|
-
margin-top: 24px;
|
|
2985
|
-
}
|
|
2986
|
-
.lx-form-section:first-child {
|
|
2987
|
-
margin-top: 0;
|
|
2988
|
-
}
|
|
2989
|
-
// Stretch controls to fill the column even though .field aligns to
|
|
2990
|
-
// flex-start.
|
|
2991
|
-
.lx-modal-body .field > .input,
|
|
2992
|
-
.lx-modal-body .field > .search-select,
|
|
2993
|
-
.lx-modal-body .field > .input-date-wrap,
|
|
2994
|
-
.lx-modal-body .field > .datepicker,
|
|
2995
|
-
.lx-modal-body .field > .phone-input-wrap,
|
|
2996
|
-
.lx-modal-body .field > .field-error {
|
|
2997
|
-
align-self: stretch;
|
|
2998
|
-
}
|
|
2999
|
-
.lx-form-section-head {
|
|
3000
|
-
margin-bottom: 16px;
|
|
3001
|
-
}
|
|
3002
|
-
.lx-form-section-title {
|
|
3003
|
-
font-size: 16px;
|
|
3004
|
-
font-weight: 600;
|
|
3005
|
-
text-transform: uppercase;
|
|
3006
|
-
letter-spacing: 0.04em;
|
|
3007
|
-
color: var(--color-text-subtle);
|
|
3008
|
-
}
|
|
3009
|
-
.lx-modal-footer {
|
|
3010
|
-
flex: 0 0 auto;
|
|
3011
|
-
display: flex;
|
|
3012
|
-
align-items: center;
|
|
3013
|
-
justify-content: flex-end;
|
|
3014
|
-
gap: 10px;
|
|
3015
|
-
padding: 16px 22px;
|
|
3016
|
-
border-top: 1px solid var(--color-border);
|
|
3017
|
-
}
|
|
3018
|
-
|
|
3019
|
-
// Modal close — a squircle at rest that morphs into a circle on hover while
|
|
3020
|
-
// taking a danger tint, so dismissing reads as the destructive-ish gesture
|
|
3021
|
-
// it is. Slower on the way in than the way out.
|
|
3022
|
-
.lx-modal-close {
|
|
3023
|
-
margin-left: auto;
|
|
3024
|
-
display: grid;
|
|
3025
|
-
place-items: center;
|
|
3026
|
-
flex: none;
|
|
3027
|
-
width: 36px;
|
|
3028
|
-
height: 36px;
|
|
3029
|
-
padding: 0;
|
|
3030
|
-
border: none;
|
|
3031
|
-
cursor: pointer;
|
|
3032
|
-
line-height: 1;
|
|
3033
|
-
background: var(--color-bg-subtle);
|
|
3034
|
-
color: var(--color-text-muted);
|
|
3035
|
-
border-radius: 999px;
|
|
3036
|
-
corner-shape: squircle;
|
|
3037
|
-
transition:
|
|
3038
|
-
background 180ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
3039
|
-
color 180ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
3040
|
-
corner-shape 180ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
3041
|
-
}
|
|
3042
|
-
.lx-modal-close:hover {
|
|
3043
|
-
background: var(--color-danger-soft);
|
|
3044
|
-
color: var(--color-danger);
|
|
3045
|
-
corner-shape: round;
|
|
3046
|
-
transition:
|
|
3047
|
-
background 280ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
3048
|
-
color 280ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
3049
|
-
corner-shape 280ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
3050
|
-
}
|
|
3051
|
-
.lx-modal-close:focus-visible {
|
|
3052
|
-
outline: 2px solid var(--color-primary);
|
|
3053
|
-
outline-offset: 2px;
|
|
3054
|
-
}
|
|
3055
|
-
// The shape morph is decorative; hold the colour cue for reduced-motion
|
|
3056
|
-
// users.
|
|
3057
|
-
@media (prefers-reduced-motion: reduce) {
|
|
3058
|
-
.lx-modal-close,
|
|
3059
|
-
.lx-modal-close:hover {
|
|
3060
|
-
corner-shape: squircle;
|
|
3061
|
-
transition:
|
|
3062
|
-
background 1ms linear,
|
|
3063
|
-
color 1ms linear;
|
|
3064
|
-
}
|
|
3065
|
-
}
|
|
3066
|
-
|
|
3067
|
-
// ── Confirm dialog ──
|
|
3068
|
-
// Confirmation dialog — centred status icon + title + message, two equal
|
|
3069
|
-
// side-by-side CTAs. Runs headerless (Modal hideHeader), so the body
|
|
3070
|
-
// carries the spacing and the footer drops its divider.
|
|
3071
|
-
.lx-confirm-content {
|
|
3072
|
-
display: flex;
|
|
3073
|
-
flex-direction: column;
|
|
3074
|
-
align-items: center;
|
|
3075
|
-
text-align: center;
|
|
3076
|
-
padding: 16px 12px 6px;
|
|
3077
|
-
}
|
|
3078
|
-
.lx-confirm-icon {
|
|
3079
|
-
line-height: 0;
|
|
3080
|
-
margin-bottom: 22px;
|
|
3081
|
-
}
|
|
3082
|
-
.lx-confirm-title {
|
|
3083
|
-
margin: 0 0 10px;
|
|
3084
|
-
font-size: 22px;
|
|
3085
|
-
font-weight: 700;
|
|
3086
|
-
letter-spacing: -0.01em;
|
|
3087
|
-
color: var(--color-text);
|
|
3088
|
-
}
|
|
3089
|
-
.lx-confirm-msg {
|
|
3090
|
-
margin: 0;
|
|
3091
|
-
font-size: 15px;
|
|
3092
|
-
line-height: 1.55;
|
|
3093
|
-
color: var(--color-text-muted);
|
|
3094
|
-
max-width: 40ch;
|
|
3095
|
-
}
|
|
3096
|
-
.lx-confirm-actions {
|
|
3097
|
-
display: flex;
|
|
3098
|
-
gap: 12px;
|
|
3099
|
-
width: 100%;
|
|
3100
|
-
}
|
|
3101
|
-
.lx-modal-footer:has(.lx-confirm-actions) {
|
|
3102
|
-
border-top: none;
|
|
3103
|
-
padding-top: 0;
|
|
3104
|
-
}
|
|
3105
|
-
.lx-confirm-actions .btn {
|
|
3106
|
-
flex: 1;
|
|
3107
|
-
min-height: var(--wui-control-height);
|
|
3108
|
-
height: var(--wui-control-height);
|
|
3109
|
-
border-radius: var(--radius);
|
|
3110
|
-
corner-shape: squircle;
|
|
3111
|
-
padding-left: 16px;
|
|
3112
|
-
padding-right: 16px;
|
|
3113
|
-
font-size: 14px;
|
|
3114
|
-
font-weight: 500;
|
|
3115
|
-
}
|
|
3116
|
-
|
|
3117
|
-
// ── Grid / layout utils ──
|
|
3118
|
-
// Responsive card grids (Bootstrap has no grid-template utility).
|
|
3119
|
-
.lx-grid {
|
|
3120
|
-
display: grid;
|
|
3121
|
-
grid-template-columns: 1fr;
|
|
3122
|
-
}
|
|
3123
|
-
.lx-cols-2 {
|
|
3124
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
3125
|
-
}
|
|
3126
|
-
.lx-cols-3 {
|
|
3127
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
3128
|
-
}
|
|
3129
|
-
.lx-cols-4 {
|
|
3130
|
-
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
3131
|
-
}
|
|
3132
|
-
@media (min-width: 768px) {
|
|
3133
|
-
.lx-grid-md-2 {
|
|
3134
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
3135
|
-
}
|
|
3136
|
-
.lx-grid-md-3 {
|
|
3137
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
3138
|
-
}
|
|
3139
|
-
.lx-grid-md-4 {
|
|
3140
|
-
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
3141
|
-
}
|
|
3142
|
-
}
|
|
3143
|
-
@media (min-width: 992px) {
|
|
3144
|
-
.lx-grid-lg-2 {
|
|
3145
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
3146
|
-
}
|
|
3147
|
-
.lx-grid-lg-3 {
|
|
3148
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
3149
|
-
}
|
|
3150
|
-
.lx-grid-lg-4 {
|
|
3151
|
-
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
3152
|
-
}
|
|
3153
|
-
}
|
|
3154
|
-
.lx-col-span-2 {
|
|
3155
|
-
grid-column: span 2 / span 2;
|
|
3156
|
-
}
|
|
3157
|
-
.lx-col-span-3 {
|
|
3158
|
-
grid-column: span 3 / span 3;
|
|
3159
|
-
}
|
|
3160
|
-
.lx-col-span-full {
|
|
3161
|
-
grid-column: 1 / -1;
|
|
3162
|
-
}
|
|
3163
|
-
|
|
3164
|
-
// ── Info tip ──
|
|
3165
|
-
// Inline term help (InfoTip).
|
|
3166
|
-
.infotip {
|
|
3167
|
-
position: relative;
|
|
3168
|
-
display: inline-flex;
|
|
3169
|
-
vertical-align: middle;
|
|
3170
|
-
margin-left: 5px;
|
|
3171
|
-
}
|
|
3172
|
-
.infotip-btn {
|
|
3173
|
-
display: inline-flex;
|
|
3174
|
-
align-items: center;
|
|
3175
|
-
justify-content: center;
|
|
3176
|
-
width: 16px;
|
|
3177
|
-
height: 16px;
|
|
3178
|
-
padding: 0;
|
|
3179
|
-
border: none;
|
|
3180
|
-
border-radius: 999px;
|
|
3181
|
-
background: transparent;
|
|
3182
|
-
color: var(--color-text-subtle);
|
|
3183
|
-
cursor: help;
|
|
3184
|
-
transform: scaleY(-1);
|
|
3185
|
-
transition: color 0.15s;
|
|
3186
|
-
}
|
|
3187
|
-
.infotip-btn:hover,
|
|
3188
|
-
.infotip-btn:focus-visible {
|
|
3189
|
-
color: var(--color-primary);
|
|
3190
|
-
outline: none;
|
|
3191
|
-
}
|
|
3192
|
-
.infotip-pop {
|
|
3193
|
-
position: absolute;
|
|
3194
|
-
bottom: calc(100% + 8px);
|
|
3195
|
-
left: 50%;
|
|
3196
|
-
transform: translateX(-50%);
|
|
3197
|
-
z-index: 220;
|
|
3198
|
-
display: flex;
|
|
3199
|
-
flex-direction: column;
|
|
3200
|
-
gap: 4px;
|
|
3201
|
-
width: 280px;
|
|
3202
|
-
max-width: 78vw;
|
|
3203
|
-
padding: 12px 14px;
|
|
3204
|
-
background: var(--color-surface);
|
|
3205
|
-
border: none;
|
|
3206
|
-
border-radius: var(--radius-lg);
|
|
3207
|
-
box-shadow: var(--shadow-overlay);
|
|
3208
|
-
text-align: left;
|
|
3209
|
-
white-space: normal;
|
|
3210
|
-
cursor: default;
|
|
3211
|
-
}
|
|
3212
|
-
.infotip-pop::after {
|
|
3213
|
-
content: "";
|
|
3214
|
-
position: absolute;
|
|
3215
|
-
top: 100%;
|
|
3216
|
-
left: 50%;
|
|
3217
|
-
transform: translateX(-50%);
|
|
3218
|
-
border: 6px solid transparent;
|
|
3219
|
-
border-top-color: var(--color-surface);
|
|
3220
|
-
}
|
|
3221
|
-
// Portalled to <body>: position is set inline (fixed top/left), so drop the
|
|
3222
|
-
// anchored offsets and the centering transform, and hide the arrow. z-index
|
|
3223
|
-
// sits above the modal backdrop so it shows over the modal, not behind it.
|
|
3224
|
-
.infotip-pop.is-portal {
|
|
3225
|
-
bottom: auto;
|
|
3226
|
-
transform: none;
|
|
3227
|
-
z-index: 1600;
|
|
3228
|
-
}
|
|
3229
|
-
.infotip-pop.is-portal::after {
|
|
3230
|
-
display: none;
|
|
3231
|
-
}
|
|
3232
|
-
.infotip-term {
|
|
3233
|
-
display: flex;
|
|
3234
|
-
align-items: center;
|
|
3235
|
-
gap: 8px;
|
|
3236
|
-
font-size: 13px;
|
|
3237
|
-
font-weight: 600;
|
|
3238
|
-
color: var(--color-text);
|
|
3239
|
-
}
|
|
3240
|
-
.infotip-full {
|
|
3241
|
-
font-size: 12px;
|
|
3242
|
-
font-weight: 500;
|
|
3243
|
-
color: var(--color-text);
|
|
3244
|
-
}
|
|
3245
|
-
.infotip-def {
|
|
3246
|
-
font-size: 12px;
|
|
3247
|
-
color: var(--color-text-muted);
|
|
3248
|
-
line-height: 1.5;
|
|
3249
|
-
}
|
|
3250
|
-
|
|
3251
|
-
// ── Page header ──
|
|
3252
|
-
.page-header {
|
|
3253
|
-
margin-bottom: 24px;
|
|
3254
|
-
}
|
|
3255
|
-
.page-title {
|
|
3256
|
-
font-size: 24px;
|
|
3257
|
-
font-weight: 600;
|
|
3258
|
-
letter-spacing: -0.02em;
|
|
3259
|
-
color: var(--color-text);
|
|
3260
|
-
}
|
|
3261
|
-
.page-subtitle {
|
|
3262
|
-
font-size: 14px;
|
|
3263
|
-
font-weight: 400;
|
|
3264
|
-
color: var(--color-text-muted);
|
|
3265
|
-
margin-top: 2px;
|
|
3266
|
-
}
|
|
3267
|
-
.page-actions {
|
|
3268
|
-
display: flex;
|
|
3269
|
-
gap: 8px;
|
|
3270
|
-
align-items: center;
|
|
3271
|
-
}
|
|
3272
|
-
|
|
3273
|
-
// Tablet and below: the masthead stops being a single row — the title block and
|
|
3274
|
-
// its actions stack, and the actions stretch to the full width rather than
|
|
3275
|
-
// crowding the title. Bootstrap's lg tier (991.98px), not an invented breakpoint.
|
|
3276
|
-
@media (max-width: 991.98px) {
|
|
3277
|
-
.page-header {
|
|
3278
|
-
flex-direction: column;
|
|
3279
|
-
align-items: stretch;
|
|
3280
|
-
gap: 12px;
|
|
3281
|
-
}
|
|
3282
|
-
.page-actions {
|
|
3283
|
-
flex-wrap: wrap;
|
|
3284
|
-
width: 100%;
|
|
3285
|
-
}
|
|
3286
|
-
// A two-up field row is too tight for a tablet column.
|
|
3287
|
-
.field-row,
|
|
3288
|
-
.field-row-3 {
|
|
3289
|
-
grid-template-columns: 1fr;
|
|
3290
|
-
}
|
|
3291
|
-
// A fixed 420px drawer leaves too little of the page visible on a tablet.
|
|
3292
|
-
.drawer {
|
|
3293
|
-
width: 100vw;
|
|
3294
|
-
max-width: 420px;
|
|
3295
|
-
}
|
|
3296
|
-
}
|
|
3297
|
-
|
|
3298
|
-
// ── Row-action / icon buttons ──
|
|
3299
|
-
.btn-icon {
|
|
3300
|
-
min-height: 0;
|
|
3301
|
-
padding: 8px;
|
|
3302
|
-
border-radius: 999px;
|
|
3303
|
-
corner-shape: round;
|
|
3304
|
-
}
|
|
3305
|
-
|
|
3306
|
-
// Circular icon buttons in the top bar (minimal dashboard chrome).
|
|
3307
|
-
.topbar-icon-btn {
|
|
3308
|
-
position: relative;
|
|
3309
|
-
display: inline-flex;
|
|
3310
|
-
align-items: center;
|
|
3311
|
-
justify-content: center;
|
|
3312
|
-
width: 36px;
|
|
3313
|
-
height: 36px;
|
|
3314
|
-
flex: 0 0 auto;
|
|
3315
|
-
border: none;
|
|
3316
|
-
border-radius: 999px;
|
|
3317
|
-
background: transparent;
|
|
3318
|
-
color: var(--color-text-muted);
|
|
3319
|
-
cursor: pointer;
|
|
3320
|
-
transition:
|
|
3321
|
-
background 0.15s ease,
|
|
3322
|
-
color 0.15s ease;
|
|
3323
|
-
}
|
|
3324
|
-
.topbar-icon-btn:hover {
|
|
3325
|
-
background: var(--color-primary-soft);
|
|
3326
|
-
color: var(--color-primary);
|
|
3327
|
-
}
|
|
3328
|
-
.topbar-icon-btn.has-badge::after {
|
|
3329
|
-
content: "";
|
|
3330
|
-
position: absolute;
|
|
3331
|
-
top: 9px;
|
|
3332
|
-
right: 9px;
|
|
3333
|
-
width: 8px;
|
|
3334
|
-
height: 8px;
|
|
3335
|
-
border-radius: 999px;
|
|
3336
|
-
background: var(--color-danger);
|
|
3337
|
-
border: 2px solid var(--color-bg);
|
|
3338
|
-
}
|
|
3339
|
-
|
|
3340
|
-
// ── Spinner / shimmer ──
|
|
3341
|
-
.lx-spinner {
|
|
3342
|
-
width: 18px;
|
|
3343
|
-
height: 18px;
|
|
3344
|
-
border: 2.5px solid var(--color-border);
|
|
3345
|
-
border-top-color: var(--color-primary);
|
|
3346
|
-
border-radius: 999px;
|
|
3347
|
-
animation: lx-spin 0.7s linear infinite;
|
|
3348
|
-
display: inline-block;
|
|
3349
|
-
flex-shrink: 0;
|
|
3350
|
-
}
|
|
3351
|
-
@keyframes lx-spin {
|
|
3352
|
-
to {
|
|
3353
|
-
transform: rotate(360deg);
|
|
3354
|
-
}
|
|
3355
|
-
}
|
|
3356
|
-
// Small (14px) spinner variant.
|
|
3357
|
-
.lx-spinner-sm {
|
|
3358
|
-
width: 14px;
|
|
3359
|
-
height: 14px;
|
|
3360
|
-
border-width: 2px;
|
|
3361
|
-
}
|
|
3362
|
-
// Spinner for the Button loading state.
|
|
3363
|
-
.lx-spin {
|
|
3364
|
-
animation: lx-spin 0.8s linear infinite;
|
|
3365
|
-
}
|
|
3366
|
-
|
|
3367
|
-
// Skeleton shimmer — used ONLY while loading the first data (loading &&
|
|
3368
|
-
// empty), to tell "loading first data" apart from "loaded but empty".
|
|
3369
|
-
.skeleton {
|
|
3370
|
-
position: relative;
|
|
3371
|
-
overflow: hidden;
|
|
3372
|
-
display: block;
|
|
3373
|
-
background: var(--color-bg-muted);
|
|
3374
|
-
border-radius: var(--radius-sm);
|
|
3375
|
-
}
|
|
3376
|
-
.skeleton::after {
|
|
3377
|
-
content: "";
|
|
3378
|
-
position: absolute;
|
|
3379
|
-
inset: 0;
|
|
3380
|
-
transform: translateX(-100%);
|
|
3381
|
-
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
|
|
3382
|
-
animation: skeleton-shimmer 1.4s ease-in-out infinite;
|
|
3383
|
-
}
|
|
3384
|
-
@keyframes skeleton-shimmer {
|
|
3385
|
-
100% {
|
|
3386
|
-
transform: translateX(100%);
|
|
3387
|
-
}
|
|
3388
|
-
}
|
|
3389
|
-
:root[data-theme="dark"] .skeleton::after {
|
|
3390
|
-
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent);
|
|
3391
|
-
}
|
|
3392
|
-
@media (prefers-reduced-motion: reduce) {
|
|
3393
|
-
.skeleton::after {
|
|
3394
|
-
animation: none;
|
|
3395
|
-
}
|
|
3396
|
-
}
|
|
3397
|
-
|
|
3398
|
-
// ── Text-scale utilities (lx-text-*) ──
|
|
3399
|
-
.lx-text-xs {
|
|
3400
|
-
font-size: 12px;
|
|
3401
|
-
line-height: 1.4;
|
|
3402
|
-
}
|
|
3403
|
-
.lx-text-sm {
|
|
3404
|
-
font-size: 13.5px;
|
|
3405
|
-
line-height: 1.5;
|
|
3406
|
-
}
|
|
3407
|
-
.lx-text-base {
|
|
3408
|
-
font-size: 15px;
|
|
3409
|
-
line-height: 1.5;
|
|
3410
|
-
}
|
|
3411
|
-
.lx-text-lg {
|
|
3412
|
-
font-size: 17px;
|
|
3413
|
-
line-height: 1.4;
|
|
3414
|
-
}
|
|
3415
|
-
.lx-text-xl {
|
|
3416
|
-
font-size: 20px;
|
|
3417
|
-
line-height: 1.4;
|
|
3418
|
-
}
|
|
3419
|
-
.lx-text-2xl {
|
|
3420
|
-
font-size: 24px;
|
|
3421
|
-
line-height: 1.3;
|
|
3422
|
-
}
|
|
3423
|
-
.lx-text-3xl {
|
|
3424
|
-
font-size: 30px;
|
|
3425
|
-
line-height: 1.2;
|
|
3426
|
-
}
|
|
3427
|
-
.lx-text-4xl {
|
|
3428
|
-
font-size: 36px;
|
|
3429
|
-
line-height: 1.15;
|
|
3430
|
-
}
|
|
3431
|
-
|
|
3432
|
-
/* ── Chip (token / tag) ── */
|
|
3433
|
-
.chip {
|
|
3434
|
-
display: inline-flex;
|
|
3435
|
-
align-items: center;
|
|
3436
|
-
gap: 6px;
|
|
3437
|
-
max-width: 100%;
|
|
3438
|
-
padding: 4px 10px;
|
|
3439
|
-
border: 1px solid var(--color-border);
|
|
3440
|
-
border-radius: 999px;
|
|
3441
|
-
background: var(--color-bg-muted);
|
|
3442
|
-
color: var(--color-text);
|
|
3443
|
-
font-size: 0.8125rem;
|
|
3444
|
-
font-weight: 500;
|
|
3445
|
-
line-height: 1.2;
|
|
3446
|
-
vertical-align: middle;
|
|
3447
|
-
}
|
|
3448
|
-
.chip-sm {
|
|
3449
|
-
gap: 4px;
|
|
3450
|
-
padding: 2px 8px;
|
|
3451
|
-
font-size: 0.75rem;
|
|
3452
|
-
}
|
|
3453
|
-
.chip-label {
|
|
3454
|
-
overflow: hidden;
|
|
3455
|
-
text-overflow: ellipsis;
|
|
3456
|
-
white-space: nowrap;
|
|
3457
|
-
}
|
|
3458
|
-
.chip-ic {
|
|
3459
|
-
display: inline-flex;
|
|
3460
|
-
color: var(--color-text-subtle);
|
|
3461
|
-
}
|
|
3462
|
-
.chip-avatar {
|
|
3463
|
-
display: inline-flex;
|
|
3464
|
-
width: 18px;
|
|
3465
|
-
height: 18px;
|
|
3466
|
-
margin-left: -2px;
|
|
3467
|
-
border-radius: 999px;
|
|
3468
|
-
overflow: hidden;
|
|
3469
|
-
flex: none;
|
|
3470
|
-
}
|
|
3471
|
-
.chip-avatar img {
|
|
3472
|
-
width: 100%;
|
|
3473
|
-
height: 100%;
|
|
3474
|
-
object-fit: cover;
|
|
3475
|
-
}
|
|
3476
|
-
.chip-body {
|
|
3477
|
-
display: inline-flex;
|
|
3478
|
-
align-items: center;
|
|
3479
|
-
gap: inherit;
|
|
3480
|
-
padding: 0;
|
|
3481
|
-
border: 0;
|
|
3482
|
-
background: none;
|
|
3483
|
-
font: inherit;
|
|
3484
|
-
color: inherit;
|
|
3485
|
-
cursor: pointer;
|
|
3486
|
-
}
|
|
3487
|
-
.chip-clickable {
|
|
3488
|
-
cursor: pointer;
|
|
3489
|
-
}
|
|
3490
|
-
.chip-clickable:hover {
|
|
3491
|
-
border-color: var(--color-border-strong);
|
|
3492
|
-
}
|
|
3493
|
-
.chip-remove {
|
|
3494
|
-
display: inline-flex;
|
|
3495
|
-
align-items: center;
|
|
3496
|
-
justify-content: center;
|
|
3497
|
-
margin: 0 -4px 0 2px;
|
|
3498
|
-
padding: 2px;
|
|
3499
|
-
border: 0;
|
|
3500
|
-
border-radius: 999px;
|
|
3501
|
-
background: none;
|
|
3502
|
-
color: var(--color-text-subtle);
|
|
3503
|
-
line-height: 0;
|
|
3504
|
-
cursor: pointer;
|
|
3505
|
-
}
|
|
3506
|
-
.chip-remove:hover {
|
|
3507
|
-
background: color-mix(in srgb, var(--color-text) 8%, transparent);
|
|
3508
|
-
color: var(--color-text);
|
|
3509
|
-
}
|
|
3510
|
-
.chip.is-disabled {
|
|
3511
|
-
opacity: 0.55;
|
|
3512
|
-
pointer-events: none;
|
|
3513
|
-
}
|
|
3514
|
-
|
|
3515
|
-
/* Tones — tinted surface + on-tint text; icon/remove inherit the tone colour. */
|
|
3516
|
-
.chip.primary {
|
|
3517
|
-
border-color: transparent;
|
|
3518
|
-
background: var(--color-primary-soft);
|
|
3519
|
-
color: var(--color-primary);
|
|
3520
|
-
}
|
|
3521
|
-
.chip.success {
|
|
3522
|
-
border-color: transparent;
|
|
3523
|
-
background: var(--color-success-soft);
|
|
3524
|
-
color: var(--color-success-active);
|
|
3525
|
-
}
|
|
3526
|
-
.chip.warning {
|
|
3527
|
-
border-color: transparent;
|
|
3528
|
-
background: var(--color-warning-soft);
|
|
3529
|
-
color: var(--color-warning-active);
|
|
3530
|
-
}
|
|
3531
|
-
.chip.danger {
|
|
3532
|
-
border-color: transparent;
|
|
3533
|
-
background: var(--color-danger-soft);
|
|
3534
|
-
color: var(--color-danger-active);
|
|
3535
|
-
}
|
|
3536
|
-
.chip.info {
|
|
3537
|
-
border-color: transparent;
|
|
3538
|
-
background: var(--color-info-soft);
|
|
3539
|
-
color: var(--color-info-active);
|
|
3540
|
-
}
|
|
3541
|
-
.chip.primary .chip-ic,
|
|
3542
|
-
.chip.success .chip-ic,
|
|
3543
|
-
.chip.warning .chip-ic,
|
|
3544
|
-
.chip.danger .chip-ic,
|
|
3545
|
-
.chip.info .chip-ic,
|
|
3546
|
-
.chip.primary .chip-remove,
|
|
3547
|
-
.chip.success .chip-remove,
|
|
3548
|
-
.chip.warning .chip-remove,
|
|
3549
|
-
.chip.danger .chip-remove,
|
|
3550
|
-
.chip.info .chip-remove {
|
|
3551
|
-
color: currentColor;
|
|
3552
|
-
}
|
|
3553
|
-
.chip.primary .chip-remove:hover,
|
|
3554
|
-
.chip.success .chip-remove:hover,
|
|
3555
|
-
.chip.warning .chip-remove:hover,
|
|
3556
|
-
.chip.danger .chip-remove:hover,
|
|
3557
|
-
.chip.info .chip-remove:hover {
|
|
3558
|
-
background: color-mix(in srgb, currentColor 16%, transparent);
|
|
3559
|
-
color: currentColor;
|
|
3560
|
-
}
|
|
3561
|
-
|
|
3562
|
-
/* ── Autocomplete (input-first combobox; extends .search-select) ── */
|
|
3563
|
-
.search-select-ac {
|
|
3564
|
-
justify-content: flex-start;
|
|
3565
|
-
cursor: text;
|
|
3566
|
-
padding-right: 8px;
|
|
3567
|
-
}
|
|
3568
|
-
.search-select-ac-input {
|
|
3569
|
-
flex: 1 1 auto;
|
|
3570
|
-
min-width: 0;
|
|
3571
|
-
padding: 0;
|
|
3572
|
-
border: 0;
|
|
3573
|
-
background: none;
|
|
3574
|
-
color: inherit;
|
|
3575
|
-
font: inherit;
|
|
3576
|
-
outline: none;
|
|
3577
|
-
}
|
|
3578
|
-
.search-select-ac-input::placeholder {
|
|
3579
|
-
color: var(--color-text-subtle);
|
|
3580
|
-
}
|
|
3581
|
-
.search-select-spinner {
|
|
3582
|
-
flex: none;
|
|
3583
|
-
width: 1rem;
|
|
3584
|
-
height: 1rem;
|
|
3585
|
-
color: var(--color-text-subtle);
|
|
3586
|
-
border-width: 2px;
|
|
3587
|
-
}
|
|
3588
|
-
.search-select-hint {
|
|
3589
|
-
padding: 10px 12px;
|
|
3590
|
-
color: var(--color-text-subtle);
|
|
3591
|
-
font-size: 0.8125rem;
|
|
3592
|
-
}
|
|
3593
|
-
|
|
3594
|
-
/* ── Multi-select (chips in the control; check-list dropdown; extends .search-select) ── */
|
|
3595
|
-
.search-select-multi {
|
|
3596
|
-
align-items: flex-start;
|
|
3597
|
-
gap: 6px;
|
|
3598
|
-
min-height: 40px;
|
|
3599
|
-
height: auto;
|
|
3600
|
-
padding-top: 5px;
|
|
3601
|
-
padding-bottom: 5px;
|
|
3602
|
-
flex-wrap: nowrap;
|
|
3603
|
-
}
|
|
3604
|
-
.ms-chips {
|
|
3605
|
-
display: flex;
|
|
3606
|
-
flex-wrap: wrap;
|
|
3607
|
-
gap: 6px;
|
|
3608
|
-
flex: 1 1 auto;
|
|
3609
|
-
min-width: 0;
|
|
3610
|
-
align-items: center;
|
|
3611
|
-
}
|
|
3612
|
-
.search-select-multi .search-select-caret {
|
|
3613
|
-
align-self: center;
|
|
3614
|
-
}
|
|
3615
|
-
.ms-check {
|
|
3616
|
-
display: inline-flex;
|
|
3617
|
-
align-items: center;
|
|
3618
|
-
justify-content: center;
|
|
3619
|
-
width: 16px;
|
|
3620
|
-
flex: none;
|
|
3621
|
-
color: var(--color-primary);
|
|
3622
|
-
opacity: 0;
|
|
3623
|
-
}
|
|
3624
|
-
.search-select-option[aria-selected='true'] .ms-check {
|
|
3625
|
-
opacity: 1;
|
|
3626
|
-
}
|
|
3627
|
-
.ms-opt-label {
|
|
3628
|
-
min-width: 0;
|
|
3629
|
-
overflow: hidden;
|
|
3630
|
-
text-overflow: ellipsis;
|
|
3631
|
-
}
|
|
3632
|
-
.search-select-multi .search-select-option {
|
|
3633
|
-
display: flex;
|
|
3634
|
-
align-items: center;
|
|
3635
|
-
gap: 8px;
|
|
3636
|
-
}
|
|
3637
|
-
|
|
3638
|
-
/* ── Choice card: image / custom-template variant ── */
|
|
3639
|
-
.struct-card-img-card {
|
|
3640
|
-
flex-direction: column;
|
|
3641
|
-
align-items: stretch;
|
|
3642
|
-
padding: 0;
|
|
3643
|
-
overflow: hidden;
|
|
3644
|
-
}
|
|
3645
|
-
.struct-card-media {
|
|
3646
|
-
display: block;
|
|
3647
|
-
width: 100%;
|
|
3648
|
-
aspect-ratio: 16 / 9;
|
|
3649
|
-
background: var(--color-bg-muted);
|
|
3650
|
-
overflow: hidden;
|
|
3651
|
-
}
|
|
3652
|
-
.struct-card-img {
|
|
3653
|
-
width: 100%;
|
|
3654
|
-
height: 100%;
|
|
3655
|
-
object-fit: cover;
|
|
3656
|
-
display: block;
|
|
3657
|
-
}
|
|
3658
|
-
.struct-card-img-card .struct-card-body {
|
|
3659
|
-
padding: 12px 14px;
|
|
3660
|
-
}
|
|
3661
|
-
.struct-card-img-card .struct-card-check {
|
|
3662
|
-
position: absolute;
|
|
3663
|
-
top: 8px;
|
|
3664
|
-
right: 8px;
|
|
3665
|
-
}
|
|
18
|
+
// This file is now an INDEX. The rules live in ./wui/*.scss, split by domain
|
|
19
|
+
// because one 5,000-line stylesheet made finding a component a grep.
|
|
20
|
+
//
|
|
21
|
+
// The order below is LOAD-BEARING. A later partial may deliberately override an
|
|
22
|
+
// earlier one, so reordering these imports silently changes the cascade — and
|
|
23
|
+
// nothing in the build will complain. `pnpm check:theme` measures the rules that
|
|
24
|
+
// have to win against Bootstrap; the rest is guarded by review.
|
|
25
|
+
@import "wui/controls";
|
|
26
|
+
@import "wui/choice";
|
|
27
|
+
@import "wui/media";
|
|
28
|
+
@import "wui/navigation";
|
|
29
|
+
@import "wui/card";
|
|
30
|
+
@import "wui/data";
|
|
31
|
+
@import "wui/overlays";
|
|
32
|
+
@import "wui/utilities";
|
|
33
|
+
@import "wui/typography";
|
|
34
|
+
@import "wui/disclosure";
|
|
35
|
+
@import "wui/display";
|
|
36
|
+
@import "wui/flow";
|
|
37
|
+
@import "wui/shell";
|