@webority/theme 0.0.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -4
- package/dist/webority-theme.css +1 -1
- package/package.json +2 -1
- package/scss/_components.scss +61 -82
- package/scss/_flags.scss +270 -0
- package/scss/_tokens.scss +37 -19
- package/scss/_variables.scss +27 -24
- package/scss/_wui-aliases.scss +3 -1
- package/scss/_wui-components.scss +468 -99
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ============================================================================
|
|
2
2
|
// _wui-components.scss
|
|
3
3
|
// ----------------------------------------------------------------------------
|
|
4
|
-
// Extracted portal component layer —
|
|
5
|
-
// customer portal's `design-system.css`,
|
|
6
|
-
// `portal-helpers.css
|
|
4
|
+
// Extracted portal component layer — the shared, reusable UI-component
|
|
5
|
+
// CSS pulled from the customer portal's `design-system.css`,
|
|
6
|
+
// `components.css`, and `portal-helpers.css`.
|
|
7
7
|
//
|
|
8
8
|
// Only rules whose subject is a genuinely shared, reusable UI-component class
|
|
9
9
|
// were kept (fields, badges, modals, tables, drawers, phone/date/search
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// ============================================================================
|
|
17
17
|
|
|
18
18
|
// ── Checkbox & Radio ──
|
|
19
|
-
//
|
|
19
|
+
// Selection controls: a 20px glyph centred in a 36px circular hit area
|
|
20
20
|
// that shows a soft primary-tinted ripple on hover. Unchecked = muted
|
|
21
21
|
// grey-blue outline; checked = solid primary. Checkbox = squircle box + white
|
|
22
22
|
// tick; radio = ring + filled centre dot. Pure CSS, no JS — drives the native
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
background-color 0.15s ease;
|
|
70
70
|
}
|
|
71
71
|
.lx-check {
|
|
72
|
-
border-radius:
|
|
72
|
+
border-radius: var(--radius-sm);
|
|
73
73
|
corner-shape: squircle;
|
|
74
74
|
}
|
|
75
75
|
.lx-radio {
|
|
@@ -190,9 +190,9 @@
|
|
|
190
190
|
.textarea {
|
|
191
191
|
box-sizing: border-box;
|
|
192
192
|
width: 100%;
|
|
193
|
-
height:
|
|
193
|
+
height: var(--wui-control-height);
|
|
194
194
|
padding: 12px;
|
|
195
|
-
border-radius:
|
|
195
|
+
border-radius: var(--radius);
|
|
196
196
|
border: 1px solid var(--color-border);
|
|
197
197
|
background: var(--color-surface);
|
|
198
198
|
font-size: 14px;
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
outline: none;
|
|
223
223
|
background-color: var(--color-bg-muted);
|
|
224
224
|
color: var(--color-text);
|
|
225
|
-
border-color:
|
|
225
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
226
226
|
box-shadow: none;
|
|
227
227
|
}
|
|
228
228
|
// Textarea renders as .form-control.textarea (react-bootstrap). Match the
|
|
@@ -233,7 +233,7 @@ textarea.textarea.form-control:hover:not(:focus):not(:disabled):not([readonly])
|
|
|
233
233
|
}
|
|
234
234
|
textarea.textarea:focus {
|
|
235
235
|
outline: none;
|
|
236
|
-
border-color:
|
|
236
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
237
237
|
box-shadow: none;
|
|
238
238
|
}
|
|
239
239
|
.input::placeholder,
|
|
@@ -269,17 +269,27 @@ textarea.textarea:focus {
|
|
|
269
269
|
|
|
270
270
|
// Invalid field state (required-field validation) — soft danger-tinted
|
|
271
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.
|
|
272
275
|
.input.is-invalid,
|
|
273
276
|
.select.is-invalid,
|
|
274
277
|
.textarea.is-invalid,
|
|
275
278
|
.input.is-invalid:focus,
|
|
276
279
|
.select.is-invalid:focus,
|
|
277
|
-
.textarea.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 {
|
|
278
287
|
background: var(--color-surface);
|
|
279
288
|
border-color: color-mix(in srgb, var(--color-danger) 45%, var(--color-surface));
|
|
280
289
|
box-shadow: none;
|
|
281
290
|
}
|
|
282
|
-
.input.is-invalid
|
|
291
|
+
.input.is-invalid,
|
|
292
|
+
.input[aria-invalid="true"] {
|
|
283
293
|
padding-right: 41px;
|
|
284
294
|
}
|
|
285
295
|
.field-error {
|
|
@@ -472,7 +482,7 @@ textarea.textarea:focus {
|
|
|
472
482
|
border: none;
|
|
473
483
|
background: transparent;
|
|
474
484
|
color: var(--color-text-subtle);
|
|
475
|
-
border-radius:
|
|
485
|
+
border-radius: var(--radius);
|
|
476
486
|
cursor: pointer;
|
|
477
487
|
transition:
|
|
478
488
|
color 0.12s ease,
|
|
@@ -556,7 +566,7 @@ textarea.textarea:focus {
|
|
|
556
566
|
// red border around a non-input group (e.g. a structure-form card row)
|
|
557
567
|
.group-invalid {
|
|
558
568
|
border: 1px solid var(--color-danger);
|
|
559
|
-
border-radius:
|
|
569
|
+
border-radius: var(--radius);
|
|
560
570
|
padding: 8px;
|
|
561
571
|
}
|
|
562
572
|
|
|
@@ -566,7 +576,7 @@ textarea.textarea:focus {
|
|
|
566
576
|
display: flex;
|
|
567
577
|
align-items: stretch;
|
|
568
578
|
border: 1px solid var(--color-border);
|
|
569
|
-
border-radius:
|
|
579
|
+
border-radius: var(--radius-lg);
|
|
570
580
|
corner-shape: squircle;
|
|
571
581
|
background: var(--color-surface);
|
|
572
582
|
transition:
|
|
@@ -580,7 +590,7 @@ textarea.textarea:focus {
|
|
|
580
590
|
}
|
|
581
591
|
.input-with-unit:focus-within {
|
|
582
592
|
background: var(--color-bg-muted);
|
|
583
|
-
border-color:
|
|
593
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
584
594
|
}
|
|
585
595
|
.input-with-unit:has(.num-input.error) {
|
|
586
596
|
border-color: var(--color-danger);
|
|
@@ -657,7 +667,7 @@ textarea.textarea:focus {
|
|
|
657
667
|
background: currentColor;
|
|
658
668
|
}
|
|
659
669
|
|
|
660
|
-
//
|
|
670
|
+
// "Soft" status badge — pill, 12/600, muted tone fill.
|
|
661
671
|
.status-label {
|
|
662
672
|
display: inline-flex;
|
|
663
673
|
align-items: center;
|
|
@@ -670,24 +680,40 @@ textarea.textarea:focus {
|
|
|
670
680
|
line-height: 1;
|
|
671
681
|
white-space: nowrap;
|
|
672
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,
|
|
673
688
|
.status-label.tone-green {
|
|
674
|
-
background:
|
|
689
|
+
background: color-mix(in srgb, var(--color-success) 16%, transparent);
|
|
675
690
|
color: var(--color-success-strong);
|
|
676
691
|
}
|
|
692
|
+
.status-label.warning,
|
|
677
693
|
.status-label.tone-amber {
|
|
678
|
-
background:
|
|
694
|
+
background: color-mix(in srgb, var(--color-warning) 16%, transparent);
|
|
679
695
|
color: var(--color-warning-strong);
|
|
680
696
|
}
|
|
697
|
+
.status-label.danger,
|
|
681
698
|
.status-label.tone-red {
|
|
682
|
-
background:
|
|
699
|
+
background: color-mix(in srgb, var(--color-danger) 16%, transparent);
|
|
683
700
|
color: var(--color-danger-strong);
|
|
684
701
|
}
|
|
702
|
+
.status-label.info,
|
|
685
703
|
.status-label.tone-blue {
|
|
686
|
-
background:
|
|
704
|
+
background: color-mix(in srgb, var(--color-info) 16%, transparent);
|
|
687
705
|
color: var(--color-info-strong);
|
|
688
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,
|
|
689
715
|
.status-label.tone-grey {
|
|
690
|
-
background:
|
|
716
|
+
background: color-mix(in srgb, var(--color-text-subtle) 16%, transparent);
|
|
691
717
|
color: var(--color-text-subtle);
|
|
692
718
|
}
|
|
693
719
|
|
|
@@ -735,7 +761,7 @@ textarea.textarea:focus {
|
|
|
735
761
|
gap: 11px;
|
|
736
762
|
padding: 20px;
|
|
737
763
|
border: 1.5px solid var(--color-border);
|
|
738
|
-
border-radius:
|
|
764
|
+
border-radius: var(--radius);
|
|
739
765
|
background: var(--color-surface);
|
|
740
766
|
cursor: pointer;
|
|
741
767
|
transition:
|
|
@@ -743,10 +769,10 @@ textarea.textarea:focus {
|
|
|
743
769
|
background 0.12s ease;
|
|
744
770
|
}
|
|
745
771
|
.struct-card:hover {
|
|
746
|
-
border-color:
|
|
772
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
747
773
|
}
|
|
748
774
|
.struct-card.checked {
|
|
749
|
-
border-color:
|
|
775
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
750
776
|
background: color-mix(in srgb, var(--color-primary) 5%, transparent);
|
|
751
777
|
}
|
|
752
778
|
.struct-card.checked .struct-card-title {
|
|
@@ -893,7 +919,7 @@ textarea.textarea:focus {
|
|
|
893
919
|
}
|
|
894
920
|
.search-select-control.open {
|
|
895
921
|
background: var(--color-bg-muted);
|
|
896
|
-
border-color:
|
|
922
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
897
923
|
}
|
|
898
924
|
.search-select-caret {
|
|
899
925
|
flex-shrink: 0;
|
|
@@ -919,9 +945,9 @@ textarea.textarea:focus {
|
|
|
919
945
|
right: 0;
|
|
920
946
|
background: var(--color-surface);
|
|
921
947
|
border: 1px solid var(--color-border);
|
|
922
|
-
border-radius:
|
|
948
|
+
border-radius: var(--radius-lg);
|
|
923
949
|
corner-shape: squircle;
|
|
924
|
-
box-shadow:
|
|
950
|
+
box-shadow: var(--shadow-overlay);
|
|
925
951
|
padding: 4px;
|
|
926
952
|
overflow: hidden;
|
|
927
953
|
}
|
|
@@ -945,7 +971,7 @@ textarea.textarea:focus {
|
|
|
945
971
|
padding: 0 12px;
|
|
946
972
|
height: 40px;
|
|
947
973
|
border: 1px solid var(--color-border);
|
|
948
|
-
border-radius:
|
|
974
|
+
border-radius: var(--radius);
|
|
949
975
|
corner-shape: squircle;
|
|
950
976
|
background: var(--color-surface);
|
|
951
977
|
color: var(--color-text-subtle);
|
|
@@ -1001,7 +1027,7 @@ textarea.textarea:focus {
|
|
|
1001
1027
|
padding: 9px 14px;
|
|
1002
1028
|
line-height: 1.4;
|
|
1003
1029
|
border: none;
|
|
1004
|
-
border-radius:
|
|
1030
|
+
border-radius: var(--radius);
|
|
1005
1031
|
corner-shape: squircle;
|
|
1006
1032
|
background: transparent;
|
|
1007
1033
|
font-size: 14px;
|
|
@@ -1043,7 +1069,7 @@ textarea.textarea:focus {
|
|
|
1043
1069
|
}
|
|
1044
1070
|
.datepicker.open .datepicker-trigger {
|
|
1045
1071
|
background-color: var(--color-bg-muted);
|
|
1046
|
-
border-color:
|
|
1072
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
1047
1073
|
box-shadow: none;
|
|
1048
1074
|
}
|
|
1049
1075
|
// Portalled to <body> and fixed-positioned from JS so a modal's
|
|
@@ -1057,8 +1083,9 @@ textarea.textarea:focus {
|
|
|
1057
1083
|
padding: 18px;
|
|
1058
1084
|
background: var(--color-surface);
|
|
1059
1085
|
border: 1px solid var(--color-border);
|
|
1060
|
-
border-radius:
|
|
1086
|
+
border-radius: var(--radius-xl);
|
|
1061
1087
|
corner-shape: squircle;
|
|
1088
|
+
box-shadow: var(--shadow-overlay);
|
|
1062
1089
|
animation: datepicker-in 0.14s ease;
|
|
1063
1090
|
}
|
|
1064
1091
|
.datepicker-pop.drop-up {
|
|
@@ -1198,7 +1225,7 @@ textarea.textarea:focus {
|
|
|
1198
1225
|
border: none;
|
|
1199
1226
|
background: transparent;
|
|
1200
1227
|
padding: 6px 12px;
|
|
1201
|
-
border-radius:
|
|
1228
|
+
border-radius: var(--radius);
|
|
1202
1229
|
font-size: 13px;
|
|
1203
1230
|
font-weight: 600;
|
|
1204
1231
|
color: var(--color-primary);
|
|
@@ -1217,24 +1244,65 @@ textarea.textarea:focus {
|
|
|
1217
1244
|
.app-phone-number-input {
|
|
1218
1245
|
width: 100%;
|
|
1219
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.
|
|
1220
1251
|
.app-phone-number-input .phone-input-wrap {
|
|
1221
|
-
|
|
1252
|
+
display: flex;
|
|
1253
|
+
align-items: center;
|
|
1222
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;
|
|
1223
1263
|
}
|
|
1224
|
-
.app-phone-number-input .phone-input-wrap
|
|
1225
|
-
|
|
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);
|
|
1226
1267
|
}
|
|
1227
|
-
.app-phone-number-input .phone-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
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;
|
|
1231
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;
|
|
1232
1297
|
display: flex;
|
|
1233
1298
|
align-items: center;
|
|
1234
1299
|
padding-left: 12px;
|
|
1235
1300
|
z-index: 5;
|
|
1236
1301
|
}
|
|
1237
|
-
|
|
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 {
|
|
1238
1306
|
display: flex;
|
|
1239
1307
|
align-items: center;
|
|
1240
1308
|
gap: 6px;
|
|
@@ -1243,29 +1311,43 @@ textarea.textarea:focus {
|
|
|
1243
1311
|
background: transparent;
|
|
1244
1312
|
box-shadow: none;
|
|
1245
1313
|
color: var(--color-text);
|
|
1314
|
+
cursor: pointer;
|
|
1315
|
+
font: inherit;
|
|
1316
|
+
line-height: 1;
|
|
1246
1317
|
}
|
|
1247
|
-
.country-
|
|
1318
|
+
.country-toggle::after {
|
|
1248
1319
|
display: none;
|
|
1249
1320
|
}
|
|
1250
|
-
.country-
|
|
1251
|
-
.country-
|
|
1252
|
-
.country-
|
|
1253
|
-
background: transparent
|
|
1254
|
-
box-shadow: none
|
|
1255
|
-
color: var(--color-text)
|
|
1321
|
+
.country-toggle:hover,
|
|
1322
|
+
.country-toggle:focus,
|
|
1323
|
+
.country-toggle:active {
|
|
1324
|
+
background: transparent;
|
|
1325
|
+
box-shadow: none;
|
|
1326
|
+
color: var(--color-text);
|
|
1256
1327
|
}
|
|
1257
|
-
.
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06);
|
|
1328
|
+
.country-toggle:hover .phone-chevron {
|
|
1329
|
+
color: var(--color-text);
|
|
1330
|
+
}
|
|
1331
|
+
.country-toggle:focus {
|
|
1332
|
+
outline: none;
|
|
1263
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).
|
|
1264
1344
|
.app-phone-number-input .phone-chevron {
|
|
1265
1345
|
color: var(--color-text-muted);
|
|
1266
1346
|
transition: transform 0.2s ease;
|
|
1267
1347
|
}
|
|
1268
|
-
|
|
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 {
|
|
1269
1351
|
transform: rotate(180deg);
|
|
1270
1352
|
}
|
|
1271
1353
|
.app-phone-number-input .phone-dial {
|
|
@@ -1274,34 +1356,48 @@ textarea.textarea:focus {
|
|
|
1274
1356
|
color: var(--color-text);
|
|
1275
1357
|
}
|
|
1276
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.
|
|
1277
1364
|
.country-dropdown-menu {
|
|
1365
|
+
position: fixed;
|
|
1366
|
+
z-index: 1600;
|
|
1278
1367
|
width: 320px;
|
|
1279
|
-
|
|
1368
|
+
max-width: calc(100vw - 16px);
|
|
1369
|
+
padding: 4px;
|
|
1280
1370
|
border: 1px solid var(--color-border);
|
|
1281
|
-
border-radius:
|
|
1371
|
+
border-radius: var(--radius-lg);
|
|
1372
|
+
corner-shape: squircle;
|
|
1282
1373
|
background: var(--color-surface);
|
|
1283
|
-
box-shadow:
|
|
1374
|
+
box-shadow: var(--shadow-overlay);
|
|
1284
1375
|
overflow: hidden;
|
|
1285
1376
|
}
|
|
1286
1377
|
.dropdown-search-wrapper {
|
|
1287
1378
|
position: relative;
|
|
1288
|
-
|
|
1379
|
+
margin: 4px;
|
|
1289
1380
|
}
|
|
1290
1381
|
.dropdown-search-icon {
|
|
1291
1382
|
position: absolute;
|
|
1292
|
-
left:
|
|
1293
|
-
top:
|
|
1383
|
+
left: 12px;
|
|
1384
|
+
top: 50%;
|
|
1294
1385
|
transform: translateY(-50%);
|
|
1295
1386
|
display: flex;
|
|
1296
|
-
color: var(--color-text-
|
|
1387
|
+
color: var(--color-text-subtle);
|
|
1297
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);
|
|
1298
1393
|
}
|
|
1299
1394
|
.dropdown-search-input {
|
|
1300
1395
|
width: 100%;
|
|
1301
|
-
height:
|
|
1396
|
+
height: 40px;
|
|
1302
1397
|
padding: 0 12px 0 36px;
|
|
1303
1398
|
border: 1px solid var(--color-border);
|
|
1304
|
-
border-radius:
|
|
1399
|
+
border-radius: var(--radius);
|
|
1400
|
+
corner-shape: squircle;
|
|
1305
1401
|
font-size: 14px;
|
|
1306
1402
|
color: var(--color-text);
|
|
1307
1403
|
background: var(--color-surface);
|
|
@@ -1311,47 +1407,58 @@ textarea.textarea:focus {
|
|
|
1311
1407
|
background: var(--color-bg-muted);
|
|
1312
1408
|
border-color: var(--color-border-strong);
|
|
1313
1409
|
}
|
|
1410
|
+
// Border is the focus cue everywhere else in the system — no glow ring here.
|
|
1314
1411
|
.dropdown-search-input:focus {
|
|
1315
1412
|
background: var(--color-bg-muted);
|
|
1316
1413
|
border-color: var(--color-primary);
|
|
1317
|
-
box-shadow: 0 0 0 3px var(--color-primary-soft);
|
|
1318
1414
|
}
|
|
1319
1415
|
.country-list-scroll {
|
|
1320
1416
|
max-height: 250px;
|
|
1321
1417
|
overflow-y: auto;
|
|
1322
1418
|
overflow-x: hidden;
|
|
1419
|
+
padding: 4px;
|
|
1420
|
+
display: flex;
|
|
1421
|
+
flex-direction: column;
|
|
1422
|
+
gap: 4px;
|
|
1323
1423
|
scrollbar-width: thin;
|
|
1424
|
+
scrollbar-gutter: stable;
|
|
1324
1425
|
}
|
|
1325
1426
|
.country-list-scroll::-webkit-scrollbar {
|
|
1326
1427
|
width: 6px;
|
|
1327
1428
|
}
|
|
1328
1429
|
.country-list-scroll::-webkit-scrollbar-thumb {
|
|
1329
1430
|
background: var(--color-border);
|
|
1330
|
-
border-radius:
|
|
1431
|
+
border-radius: 999px;
|
|
1331
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.)
|
|
1332
1436
|
.country-dropdown-item {
|
|
1333
1437
|
display: flex !important;
|
|
1334
1438
|
align-items: center;
|
|
1335
1439
|
gap: 10px;
|
|
1336
|
-
padding: 9px
|
|
1440
|
+
padding: 9px 14px !important;
|
|
1441
|
+
border-radius: var(--radius) !important;
|
|
1442
|
+
corner-shape: squircle;
|
|
1337
1443
|
cursor: pointer;
|
|
1338
1444
|
color: var(--color-text) !important;
|
|
1339
1445
|
background: transparent !important;
|
|
1340
1446
|
border: 0 !important;
|
|
1447
|
+
transition:
|
|
1448
|
+
background 0.12s ease,
|
|
1449
|
+
color 0.12s ease;
|
|
1341
1450
|
}
|
|
1342
1451
|
.country-dropdown-item:hover,
|
|
1343
1452
|
.country-dropdown-item:focus {
|
|
1344
|
-
background: var(--color-
|
|
1453
|
+
background: var(--color-primary-soft) !important;
|
|
1454
|
+
color: var(--color-primary) !important;
|
|
1345
1455
|
}
|
|
1346
1456
|
.country-dropdown-item.selected {
|
|
1347
1457
|
background: var(--color-primary-soft) !important;
|
|
1458
|
+
color: var(--color-primary) !important;
|
|
1459
|
+
font-weight: 500;
|
|
1348
1460
|
}
|
|
1349
|
-
.country-dropdown-menu .
|
|
1350
|
-
width: 22px;
|
|
1351
|
-
height: 15px;
|
|
1352
|
-
border-radius: 2px;
|
|
1353
|
-
object-fit: cover;
|
|
1354
|
-
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
|
|
1461
|
+
.country-dropdown-menu .wui-flag {
|
|
1355
1462
|
flex-shrink: 0;
|
|
1356
1463
|
}
|
|
1357
1464
|
.country-name-text {
|
|
@@ -1364,6 +1471,15 @@ textarea.textarea:focus {
|
|
|
1364
1471
|
font-weight: 400;
|
|
1365
1472
|
color: var(--color-text-muted);
|
|
1366
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
|
+
}
|
|
1367
1483
|
.selected-check-icon {
|
|
1368
1484
|
margin-left: auto;
|
|
1369
1485
|
display: flex;
|
|
@@ -1423,7 +1539,7 @@ textarea.textarea:focus {
|
|
|
1423
1539
|
gap: 12px;
|
|
1424
1540
|
padding: 12px 14px;
|
|
1425
1541
|
border: 1px dashed var(--color-border);
|
|
1426
|
-
border-radius:
|
|
1542
|
+
border-radius: var(--radius-lg);
|
|
1427
1543
|
background: var(--color-surface);
|
|
1428
1544
|
cursor: pointer;
|
|
1429
1545
|
transition:
|
|
@@ -1480,7 +1596,7 @@ textarea.textarea:focus {
|
|
|
1480
1596
|
.attach-preview {
|
|
1481
1597
|
width: 100%;
|
|
1482
1598
|
border: 1px solid var(--color-border);
|
|
1483
|
-
border-radius:
|
|
1599
|
+
border-radius: var(--radius-lg);
|
|
1484
1600
|
background: var(--color-surface);
|
|
1485
1601
|
overflow: hidden;
|
|
1486
1602
|
}
|
|
@@ -1566,7 +1682,7 @@ textarea.textarea:focus {
|
|
|
1566
1682
|
display: flex;
|
|
1567
1683
|
align-items: stretch;
|
|
1568
1684
|
width: 100%;
|
|
1569
|
-
border-radius:
|
|
1685
|
+
border-radius: var(--radius-lg);
|
|
1570
1686
|
corner-shape: squircle;
|
|
1571
1687
|
border: 1px solid var(--color-border);
|
|
1572
1688
|
background: var(--color-surface);
|
|
@@ -1679,7 +1795,7 @@ textarea.textarea:focus {
|
|
|
1679
1795
|
display: block;
|
|
1680
1796
|
width: 100%;
|
|
1681
1797
|
height: 350px;
|
|
1682
|
-
border-radius:
|
|
1798
|
+
border-radius: var(--radius-lg);
|
|
1683
1799
|
corner-shape: squircle;
|
|
1684
1800
|
border: 1px solid var(--color-border);
|
|
1685
1801
|
overflow: hidden;
|
|
@@ -1746,7 +1862,7 @@ textarea.textarea:focus {
|
|
|
1746
1862
|
font-size: 14px;
|
|
1747
1863
|
font-weight: 600;
|
|
1748
1864
|
border-radius: 999px;
|
|
1749
|
-
box-shadow:
|
|
1865
|
+
box-shadow: var(--shadow-overlay);
|
|
1750
1866
|
}
|
|
1751
1867
|
.file-preview-remove {
|
|
1752
1868
|
position: absolute;
|
|
@@ -2018,7 +2134,7 @@ textarea.textarea:focus {
|
|
|
2018
2134
|
place-items: center;
|
|
2019
2135
|
width: 30px;
|
|
2020
2136
|
height: 30px;
|
|
2021
|
-
border-radius:
|
|
2137
|
+
border-radius: var(--radius);
|
|
2022
2138
|
corner-shape: squircle;
|
|
2023
2139
|
background: var(--color-primary-soft);
|
|
2024
2140
|
color: var(--color-primary);
|
|
@@ -2035,16 +2151,196 @@ textarea.textarea:focus {
|
|
|
2035
2151
|
padding: 14px 16px 20px;
|
|
2036
2152
|
}
|
|
2037
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
|
+
|
|
2038
2309
|
// ── Empty state ──
|
|
2039
2310
|
.empty-state {
|
|
2040
2311
|
text-align: center;
|
|
2041
2312
|
padding: 48px 24px;
|
|
2042
2313
|
color: var(--color-text-subtle);
|
|
2043
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
|
+
}
|
|
2044
2340
|
.empty-state-icon {
|
|
2045
2341
|
width: 48px;
|
|
2046
2342
|
height: 48px;
|
|
2047
|
-
border-radius:
|
|
2343
|
+
border-radius: var(--radius-lg);
|
|
2048
2344
|
background: var(--color-primary-soft);
|
|
2049
2345
|
color: var(--color-primary);
|
|
2050
2346
|
display: inline-flex;
|
|
@@ -2109,6 +2405,52 @@ textarea.textarea:focus {
|
|
|
2109
2405
|
background: transparent;
|
|
2110
2406
|
}
|
|
2111
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
|
+
|
|
2112
2454
|
// ── Table + pagination ──
|
|
2113
2455
|
// DataTable cell helpers
|
|
2114
2456
|
.table-ledger .lx-cell-end,
|
|
@@ -2141,11 +2483,11 @@ textarea.textarea:focus {
|
|
|
2141
2483
|
}
|
|
2142
2484
|
.table-ledger thead th:first-child {
|
|
2143
2485
|
padding-left: 20px;
|
|
2144
|
-
border-radius:
|
|
2486
|
+
border-radius: var(--radius-sm) 0 0 var(--radius-sm);
|
|
2145
2487
|
}
|
|
2146
2488
|
.table-ledger thead th:last-child {
|
|
2147
2489
|
padding-right: 20px;
|
|
2148
|
-
border-radius: 0
|
|
2490
|
+
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
2149
2491
|
}
|
|
2150
2492
|
.table-ledger tbody td {
|
|
2151
2493
|
height: 54px;
|
|
@@ -2191,7 +2533,9 @@ textarea.textarea:focus {
|
|
|
2191
2533
|
.table-ledger a.u-name:hover {
|
|
2192
2534
|
text-decoration: none;
|
|
2193
2535
|
}
|
|
2194
|
-
// Identity-cell subline.
|
|
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,
|
|
2195
2539
|
.table-ledger .u-meta > .lx-text-xs {
|
|
2196
2540
|
font-size: 12px;
|
|
2197
2541
|
font-weight: 400;
|
|
@@ -2247,7 +2591,7 @@ textarea.textarea:focus {
|
|
|
2247
2591
|
padding: 0 28px 0 12px;
|
|
2248
2592
|
font-size: 13px;
|
|
2249
2593
|
font-weight: 600;
|
|
2250
|
-
border-radius:
|
|
2594
|
+
border-radius: var(--radius);
|
|
2251
2595
|
background-position: right 8px center;
|
|
2252
2596
|
background-size: 14px;
|
|
2253
2597
|
}
|
|
@@ -2384,27 +2728,27 @@ textarea.textarea:focus {
|
|
|
2384
2728
|
}
|
|
2385
2729
|
.u-action.u-action-preview {
|
|
2386
2730
|
background: var(--color-primary-soft);
|
|
2387
|
-
color:
|
|
2731
|
+
color: var(--color-primary);
|
|
2388
2732
|
}
|
|
2389
2733
|
.u-action.u-action-download {
|
|
2390
2734
|
background: var(--color-success-soft);
|
|
2391
|
-
color:
|
|
2735
|
+
color: var(--color-success-active);
|
|
2392
2736
|
}
|
|
2393
2737
|
.u-action.u-action-share {
|
|
2394
2738
|
background: var(--color-warning-soft);
|
|
2395
|
-
color:
|
|
2739
|
+
color: var(--color-warning-active);
|
|
2396
2740
|
}
|
|
2397
2741
|
.u-action.u-action-preview:hover:not(:disabled) {
|
|
2398
2742
|
background: var(--color-primary-soft);
|
|
2399
|
-
color:
|
|
2743
|
+
color: var(--color-primary);
|
|
2400
2744
|
}
|
|
2401
2745
|
.u-action.u-action-download:hover:not(:disabled) {
|
|
2402
2746
|
background: var(--color-success-soft);
|
|
2403
|
-
color:
|
|
2747
|
+
color: var(--color-success-active);
|
|
2404
2748
|
}
|
|
2405
2749
|
.u-action.u-action-share:hover:not(:disabled) {
|
|
2406
2750
|
background: var(--color-warning-soft);
|
|
2407
|
-
color:
|
|
2751
|
+
color: var(--color-warning-active);
|
|
2408
2752
|
}
|
|
2409
2753
|
.u-action.u-action-danger:hover {
|
|
2410
2754
|
color: var(--color-danger);
|
|
@@ -2490,12 +2834,12 @@ textarea.textarea:focus {
|
|
|
2490
2834
|
// deep drop shadow.
|
|
2491
2835
|
box-shadow:
|
|
2492
2836
|
0 0 0 1px color-mix(in srgb, var(--color-text) 10%, transparent),
|
|
2493
|
-
|
|
2837
|
+
var(--shadow-overlay-lg);
|
|
2494
2838
|
background: var(--color-surface);
|
|
2495
2839
|
}
|
|
2496
2840
|
.lx-modal {
|
|
2497
2841
|
background: var(--color-surface);
|
|
2498
|
-
border-radius:
|
|
2842
|
+
border-radius: var(--radius-xl);
|
|
2499
2843
|
corner-shape: squircle;
|
|
2500
2844
|
border: none;
|
|
2501
2845
|
width: 100%;
|
|
@@ -2614,7 +2958,7 @@ textarea.textarea:focus {
|
|
|
2614
2958
|
justify-content: center;
|
|
2615
2959
|
width: 34px;
|
|
2616
2960
|
height: 34px;
|
|
2617
|
-
border-radius:
|
|
2961
|
+
border-radius: var(--radius);
|
|
2618
2962
|
corner-shape: squircle;
|
|
2619
2963
|
flex: none;
|
|
2620
2964
|
background: var(--color-primary-soft);
|
|
@@ -2760,9 +3104,9 @@ textarea.textarea:focus {
|
|
|
2760
3104
|
}
|
|
2761
3105
|
.lx-confirm-actions .btn {
|
|
2762
3106
|
flex: 1;
|
|
2763
|
-
min-height:
|
|
2764
|
-
height:
|
|
2765
|
-
border-radius:
|
|
3107
|
+
min-height: var(--wui-control-height);
|
|
3108
|
+
height: var(--wui-control-height);
|
|
3109
|
+
border-radius: var(--radius);
|
|
2766
3110
|
corner-shape: squircle;
|
|
2767
3111
|
padding-left: 16px;
|
|
2768
3112
|
padding-right: 16px;
|
|
@@ -2859,8 +3203,8 @@ textarea.textarea:focus {
|
|
|
2859
3203
|
padding: 12px 14px;
|
|
2860
3204
|
background: var(--color-surface);
|
|
2861
3205
|
border: none;
|
|
2862
|
-
border-radius:
|
|
2863
|
-
box-shadow:
|
|
3206
|
+
border-radius: var(--radius-lg);
|
|
3207
|
+
box-shadow: var(--shadow-overlay);
|
|
2864
3208
|
text-align: left;
|
|
2865
3209
|
white-space: normal;
|
|
2866
3210
|
cursor: default;
|
|
@@ -2926,6 +3270,31 @@ textarea.textarea:focus {
|
|
|
2926
3270
|
align-items: center;
|
|
2927
3271
|
}
|
|
2928
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
|
+
|
|
2929
3298
|
// ── Row-action / icon buttons ──
|
|
2930
3299
|
.btn-icon {
|
|
2931
3300
|
min-height: 0;
|
|
@@ -3002,7 +3371,7 @@ textarea.textarea:focus {
|
|
|
3002
3371
|
overflow: hidden;
|
|
3003
3372
|
display: block;
|
|
3004
3373
|
background: var(--color-bg-muted);
|
|
3005
|
-
border-radius:
|
|
3374
|
+
border-radius: var(--radius-sm);
|
|
3006
3375
|
}
|
|
3007
3376
|
.skeleton::after {
|
|
3008
3377
|
content: "";
|