@ux-builder/ui 0.0.0-stage → 0.6.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/dist/ui.css ADDED
@@ -0,0 +1,997 @@
1
+ /* @ux-builder/ui: the shared widgets, as prefixed CSS on @ux-builder/tokens.
2
+
3
+ Every rule reads a token, never a literal colour, so the theme on the page
4
+ decides how each widget looks: Praxis's warm hairlines, Material's tonal
5
+ fields, Fluent's 4px controls, Carbon's square layers.
6
+
7
+ Token names are CONTRACT-001 role names (--piq-color-text,
8
+ --piq-button-radius). The widget tokens (--piq-field-*, --piq-check-*,
9
+ --piq-switch-*, --piq-menu-*, --piq-choice-picker-*, --piq-card-*,
10
+ --piq-notice-*, --piq-toast-*, --piq-progress-*, --piq-spinner-*,
11
+ --piq-skeleton-*, --piq-table-*, and the --piq-button-*
12
+ variants) are optional. A theme that
13
+ does not set one gets the fallback written here, which is the treatment
14
+ the platform's ui.css gave that widget, drawn from the base tokens every
15
+ theme has. So praxis and plain render as they always did, and a
16
+ theme opts into a different anatomy by setting the token.
17
+
18
+ Load it once, after the theme CSS:
19
+ import "@ux-builder/tokens/themes.css";
20
+ import "@ux-builder/ui/ui.css"; */
21
+
22
+ [class^="piq-"],
23
+ [class*=" piq-"] { box-sizing: border-box; }
24
+
25
+ /* ----------------------------------------------------------------- buttons */
26
+
27
+ /* Hover and press are a state layer: the label's own colour mixed over the
28
+ container, as M3, Fluent and Carbon all do it. Praxis sets no mix, so its
29
+ lift and shift tokens carry the state instead. */
30
+ .piq-btn {
31
+ --_state: 0%;
32
+ display: inline-flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ gap: var(--piq-space-2);
36
+ min-height: var(--piq-button-height);
37
+ padding: 0 var(--piq-button-padding-x);
38
+ border: 1px solid var(--piq-color-structure);
39
+ border-radius: var(--piq-button-radius);
40
+ background-color: var(--piq-color-structure);
41
+ background-image: linear-gradient(color-mix(in srgb, currentColor var(--_state), transparent) 0 0);
42
+ color: var(--piq-color-surface);
43
+ font: var(--piq-button-font-weight) var(--piq-button-font-size) / 1 var(--piq-font-body);
44
+ box-shadow: var(--piq-button-shadow);
45
+ cursor: pointer;
46
+ transition: box-shadow 90ms ease, transform 90ms ease, background-color 120ms ease;
47
+ }
48
+ .piq-btn:hover:not(:disabled) {
49
+ --_state: var(--piq-state-layer-hover, 0%);
50
+ box-shadow: var(--piq-button-shadow-hover);
51
+ transform: translateY(var(--piq-button-offset-hover));
52
+ }
53
+ .piq-btn:active:not(:disabled) {
54
+ --_state: var(--piq-state-layer-press, 0%);
55
+ box-shadow: var(--piq-button-shadow-press);
56
+ transform: translateY(var(--piq-button-offset-press));
57
+ }
58
+ .piq-btn:focus-visible { outline: var(--piq-focus-ring); outline-offset: var(--piq-focus-offset); }
59
+ .piq-btn:disabled { opacity: 0.45; box-shadow: var(--piq-button-shadow-flat); cursor: not-allowed; transform: none; }
60
+
61
+ .piq-btn--secondary {
62
+ border: var(--piq-button-secondary-border, 1px solid var(--piq-color-structure));
63
+ background-color: var(--piq-button-secondary-bg, transparent);
64
+ color: var(--piq-button-secondary-fg, var(--piq-color-structure));
65
+ box-shadow: var(--piq-button-shadow-flat);
66
+ }
67
+ .piq-btn--text {
68
+ border-color: transparent;
69
+ background-color: transparent;
70
+ color: var(--piq-button-ghost-fg, var(--piq-color-structure));
71
+ box-shadow: none;
72
+ }
73
+ .piq-btn--text:hover:not(:disabled) { box-shadow: none; }
74
+ .piq-btn--sm { min-height: 26px; padding: 0 var(--piq-space-3); font-size: var(--piq-font-size-label); }
75
+
76
+ /* A count on a button: part of the control, never the pill's dot or the
77
+ button's shadow, so all three stay distinct. */
78
+ .piq-btn__badge {
79
+ display: inline-flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ min-width: 1.35em;
83
+ padding: 0 0.35em;
84
+ margin-left: var(--piq-space-1);
85
+ border-radius: var(--piq-badge-radius);
86
+ background: var(--piq-badge-bg);
87
+ color: var(--piq-badge-fg);
88
+ font-size: var(--piq-badge-font-size);
89
+ font-weight: var(--piq-font-weight-strong);
90
+ font-variant-numeric: tabular-nums;
91
+ line-height: 1.6;
92
+ }
93
+
94
+ /* ------------------------------------------------------------ status pill */
95
+
96
+ /* A pill is a STATUS, never a target: no full border unless the theme's own
97
+ pill border says so, and never the button's radius. Availability never
98
+ relies on colour alone; the label always says it. */
99
+ .piq-pill {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ gap: var(--piq-pill-gap);
103
+ padding: var(--piq-pill-padding);
104
+ border: var(--piq-pill-border);
105
+ border-radius: var(--piq-pill-radius);
106
+ background: var(--piq-pill-bg);
107
+ font: var(--piq-pill-font-weight) var(--piq-pill-font-size) / 1.5 var(--piq-font-body);
108
+ text-transform: var(--piq-pill-text-transform);
109
+ letter-spacing: var(--piq-pill-letter-spacing);
110
+ white-space: nowrap;
111
+ }
112
+ .piq-pill::before {
113
+ content: "";
114
+ flex: none;
115
+ width: var(--piq-pill-dot-size);
116
+ height: var(--piq-pill-dot-size);
117
+ border-radius: 50%;
118
+ background: currentColor;
119
+ }
120
+ .piq-pill--live { color: var(--piq-state-live); }
121
+ .piq-pill--limited { color: var(--piq-state-limited); }
122
+ .piq-pill--purchasing { color: var(--piq-state-purchasing); }
123
+ .piq-pill--evaluation { color: var(--piq-state-evaluation); }
124
+ .piq-pill--closed { color: var(--piq-state-closed); }
125
+ /* Closed is an outcome, not a status: a hollow dot says "finished". */
126
+ .piq-pill--closed::before { background: transparent; box-shadow: inset 0 0 0 2px currentColor; }
127
+
128
+ /* ------------------------------------------------------------------ fields */
129
+
130
+ .piq-field { display: grid; gap: var(--piq-space-2); min-width: 0; }
131
+ .piq-field__label {
132
+ color: var(--piq-field-label-fg, var(--piq-color-structure));
133
+ font-size: var(--piq-field-label-font-size, var(--piq-font-size-label));
134
+ font-weight: var(--piq-field-label-font-weight, var(--piq-font-weight-strong));
135
+ letter-spacing: var(--piq-field-label-letter-spacing, var(--piq-letter-spacing-label));
136
+ text-transform: var(--piq-field-label-text-transform, uppercase);
137
+ }
138
+ .piq-field__input {
139
+ width: 100%;
140
+ min-height: var(--piq-field-height, var(--piq-button-height));
141
+ padding: 0 var(--piq-field-padding-x, var(--piq-space-3));
142
+ border: var(--piq-field-border, var(--piq-border-default));
143
+ border-bottom: var(--piq-field-border-bottom, var(--piq-field-border, var(--piq-border-default)));
144
+ border-radius: var(--piq-field-radius, var(--piq-radius-control));
145
+ background: var(--piq-field-bg, var(--piq-color-surface));
146
+ color: var(--piq-color-text-strong);
147
+ font: var(--piq-font-weight-regular) var(--piq-font-size-body) / var(--piq-line-height-body) var(--piq-font-body);
148
+ }
149
+ .piq-field__input::placeholder { color: var(--piq-color-text-muted); opacity: 1; }
150
+ .piq-field__input:hover:not(:disabled) { border-bottom-color: var(--piq-field-border-hover, var(--piq-color-border)); }
151
+ .piq-field__input:focus-visible {
152
+ outline: var(--piq-field-focus-outline, var(--piq-focus-ring));
153
+ outline-offset: var(--piq-field-focus-offset, var(--piq-focus-offset));
154
+ box-shadow: var(--piq-field-focus-shadow, none);
155
+ }
156
+ .piq-field__input:disabled { opacity: 0.45; cursor: not-allowed; }
157
+ .piq-field__input[aria-invalid="true"] {
158
+ border-color: var(--piq-state-closed);
159
+ box-shadow: var(--piq-field-invalid-shadow, none);
160
+ }
161
+ .piq-field__hint { color: var(--piq-color-text-muted); font-size: var(--piq-font-size-label); }
162
+ .piq-field__error { color: var(--piq-state-closed); font-size: var(--piq-font-size-label); }
163
+
164
+ /* ---------------------------------------------------------------- checkbox */
165
+
166
+ .piq-check {
167
+ display: inline-flex;
168
+ align-items: center;
169
+ gap: var(--piq-space-2);
170
+ color: var(--piq-color-text);
171
+ font: var(--piq-font-weight-regular) var(--piq-font-size-body) / var(--piq-line-height-body) var(--piq-font-body);
172
+ cursor: pointer;
173
+ }
174
+ .piq-check__box {
175
+ appearance: none;
176
+ flex: none;
177
+ display: inline-grid;
178
+ place-items: center;
179
+ width: var(--piq-check-size, 16px);
180
+ height: var(--piq-check-size, 16px);
181
+ margin: 0;
182
+ border: var(--piq-check-border, 1.5px solid var(--piq-color-text-muted));
183
+ border-radius: var(--piq-check-radius, 4px);
184
+ background: var(--piq-field-bg, var(--piq-color-surface));
185
+ cursor: pointer;
186
+ }
187
+ .piq-check__box::after {
188
+ content: "";
189
+ width: 30%;
190
+ height: 55%;
191
+ margin-top: -12%;
192
+ border: solid var(--piq-check-checked-fg, var(--piq-color-surface));
193
+ border-width: 0 2px 2px 0;
194
+ transform: rotate(45deg) scale(0);
195
+ transition: transform 90ms ease;
196
+ }
197
+ .piq-check__box:checked {
198
+ border-color: var(--piq-check-checked-bg, var(--piq-color-structure));
199
+ background: var(--piq-check-checked-bg, var(--piq-color-structure));
200
+ }
201
+ .piq-check__box:checked::after { transform: rotate(45deg) scale(1); }
202
+ .piq-check__box:focus-visible { outline: var(--piq-focus-ring); outline-offset: var(--piq-check-focus-offset, 2px); }
203
+ .piq-check__box:disabled,
204
+ .piq-check__box:disabled + span { opacity: 0.45; cursor: not-allowed; }
205
+
206
+ /* ------------------------------------------------------- textarea, select */
207
+
208
+ .piq-field__input--multi {
209
+ min-height: calc(var(--piq-field-height, var(--piq-button-height)) * 2);
210
+ padding-block: var(--piq-space-2);
211
+ resize: vertical;
212
+ }
213
+
214
+ /* The closed dropdown is a field with a chevron drawn in currentColor, so it
215
+ takes the theme's ink. The chevron sits on the wrapper because a select
216
+ cannot hold generated content. */
217
+ .piq-select { position: relative; display: block; color: var(--piq-color-text-muted); }
218
+ .piq-select::after {
219
+ content: "";
220
+ position: absolute;
221
+ top: 50%;
222
+ right: calc(var(--piq-field-padding-x, var(--piq-space-3)) + 2px);
223
+ width: 0.45em;
224
+ height: 0.45em;
225
+ border: solid currentColor;
226
+ border-width: 0 1.5px 1.5px 0;
227
+ transform: translateY(-70%) rotate(45deg);
228
+ pointer-events: none;
229
+ }
230
+ .piq-select__input {
231
+ appearance: none;
232
+ appearance: base-select;
233
+ display: flex;
234
+ align-items: center;
235
+ padding-right: calc(var(--piq-field-padding-x, var(--piq-space-3)) + 1.5em);
236
+ cursor: pointer;
237
+ }
238
+ .piq-select__input::picker-icon { display: none; }
239
+ .piq-select__input:has(option[value=""]:checked) { color: var(--piq-color-text-muted); }
240
+
241
+ /* The open list, where the browser lets the page style it, and .piq-menu for
242
+ the same list drawn anywhere else. */
243
+ .piq-select__input::picker(select),
244
+ .piq-menu {
245
+ appearance: base-select;
246
+ margin: var(--piq-menu-offset, 4px) 0 0;
247
+ padding: var(--piq-menu-padding-y, var(--piq-space-1)) 0;
248
+ border: var(--piq-menu-border, var(--piq-border-default));
249
+ border-radius: var(--piq-menu-radius, var(--piq-radius-control));
250
+ background: var(--piq-menu-bg, var(--piq-color-surface));
251
+ box-shadow: var(--piq-menu-shadow, var(--piq-shadow-overlay));
252
+ color: var(--piq-color-text);
253
+ }
254
+ .piq-menu { display: grid; list-style: none; font: var(--piq-font-weight-regular) var(--piq-font-size-body) / var(--piq-line-height-body) var(--piq-font-body); }
255
+ .piq-select__input option,
256
+ .piq-menu__item {
257
+ display: flex;
258
+ align-items: center;
259
+ gap: var(--piq-space-2);
260
+ min-height: var(--piq-menu-item-height, 36px);
261
+ padding: 0 var(--piq-field-padding-x, var(--piq-space-3));
262
+ color: var(--piq-color-text);
263
+ }
264
+ .piq-select__input option::checkmark { display: none; }
265
+ .piq-select__input option:hover,
266
+ .piq-select__input option:focus-visible,
267
+ .piq-menu__item.is-hover { background: var(--piq-menu-item-hover-bg, var(--piq-color-surface-sunken)); outline: none; }
268
+ .piq-select__input option:checked,
269
+ .piq-menu__item[aria-selected="true"] {
270
+ background: var(--piq-menu-item-selected-bg, var(--piq-color-surface-sunken));
271
+ color: var(--piq-menu-item-selected-fg, var(--piq-color-text-strong));
272
+ font-weight: var(--piq-menu-item-selected-font-weight, var(--piq-font-weight-strong));
273
+ box-shadow: var(--piq-menu-item-selected-indicator, none);
274
+ }
275
+ .piq-select__input option:disabled { color: var(--piq-color-text-muted); }
276
+
277
+ /* ------------------------------------------------------------ radio, switch */
278
+
279
+ .piq-radios { display: grid; gap: var(--piq-space-2); margin: 0; padding: 0; border: 0; min-width: 0; }
280
+ .piq-radios > legend { padding: 0; margin-bottom: var(--piq-space-1); }
281
+ .piq-radio {
282
+ appearance: none;
283
+ flex: none;
284
+ display: inline-grid;
285
+ place-items: center;
286
+ width: var(--piq-check-size, 16px);
287
+ height: var(--piq-check-size, 16px);
288
+ margin: 0;
289
+ border: var(--piq-check-border, 1.5px solid var(--piq-color-text-muted));
290
+ border-radius: 50%;
291
+ background: var(--piq-field-bg, var(--piq-color-surface));
292
+ cursor: pointer;
293
+ }
294
+ .piq-radio::after {
295
+ content: "";
296
+ width: 50%;
297
+ height: 50%;
298
+ border-radius: 50%;
299
+ background: var(--piq-check-checked-bg, var(--piq-color-structure));
300
+ transform: scale(0);
301
+ transition: transform 90ms ease;
302
+ }
303
+ .piq-radio:checked { border-color: var(--piq-check-checked-bg, var(--piq-color-structure)); }
304
+ .piq-radio:checked::after { transform: scale(1); }
305
+ .piq-radio:focus-visible { outline: var(--piq-focus-ring); outline-offset: var(--piq-check-focus-offset, 2px); }
306
+ .piq-radio:disabled,
307
+ .piq-radio:disabled + span { opacity: 0.45; cursor: not-allowed; }
308
+
309
+ /* A switch: the track is the input, the thumb its ::before. M3 grows the
310
+ thumb when on, so the thumb has a size per state. */
311
+ .piq-switch__track {
312
+ appearance: none;
313
+ position: relative;
314
+ flex: none;
315
+ width: var(--piq-switch-width, 36px);
316
+ height: var(--piq-switch-height, 20px);
317
+ margin: 0;
318
+ border: var(--piq-switch-track-border, 1.5px solid var(--piq-color-text-muted));
319
+ border-radius: var(--piq-switch-radius, 999px);
320
+ background: var(--piq-switch-track-bg, var(--piq-color-surface-sunken));
321
+ cursor: pointer;
322
+ transition: background-color 120ms ease, border-color 120ms ease;
323
+ }
324
+ .piq-switch__track::before {
325
+ content: "";
326
+ position: absolute;
327
+ top: 50%;
328
+ left: var(--piq-switch-thumb-inset, 3px);
329
+ width: var(--piq-switch-thumb-size, 12px);
330
+ height: var(--piq-switch-thumb-size, 12px);
331
+ border-radius: 50%;
332
+ background: var(--piq-switch-thumb-bg, var(--piq-color-text-muted));
333
+ transform: translateY(-50%);
334
+ transition: left 120ms ease, width 120ms ease, height 120ms ease;
335
+ }
336
+ .piq-switch__track:checked {
337
+ border-color: var(--piq-switch-checked-border-color, var(--piq-switch-checked-track-bg, var(--piq-color-structure)));
338
+ background: var(--piq-switch-checked-track-bg, var(--piq-color-structure));
339
+ }
340
+ .piq-switch__track:checked::before {
341
+ left: calc(100% - var(--piq-switch-checked-thumb-size, var(--piq-switch-thumb-size, 12px)) - var(--piq-switch-thumb-inset, 3px));
342
+ width: var(--piq-switch-checked-thumb-size, var(--piq-switch-thumb-size, 12px));
343
+ height: var(--piq-switch-checked-thumb-size, var(--piq-switch-thumb-size, 12px));
344
+ background: var(--piq-switch-checked-thumb-bg, var(--piq-color-surface));
345
+ }
346
+ .piq-switch__track:focus-visible { outline: var(--piq-focus-ring); outline-offset: 2px; }
347
+ .piq-switch__track:disabled,
348
+ .piq-switch__track:disabled + span { opacity: 0.45; cursor: not-allowed; }
349
+
350
+ /* ----------------------------------------------------------- choice picker */
351
+
352
+ /* One choice from a few, every option visible: a radio group drawn as
353
+ segments. Connected segments (--seg-gap 0) share one outline; separated
354
+ ones each carry their own. The selected segment's label is --seg-on-fg on
355
+ --seg-on-bg, a pairing the contrast gate checks, never a literal white. */
356
+ /* AppearanceSwitch: three icons in a pill, the chosen one on a raised disc. */
357
+ .piq-appearance {
358
+ display: inline-flex;
359
+ gap: var(--piq-space-1);
360
+ padding: var(--piq-space-1);
361
+ border: var(--piq-border-default);
362
+ border-radius: var(--piq-pill-radius, 999em);
363
+ background: var(--piq-color-surface);
364
+ }
365
+ .piq-appearance__opt {
366
+ display: inline-grid;
367
+ place-items: center;
368
+ inline-size: max(var(--piq-button-height, 36px), var(--piq-size-target-minimum, 24px));
369
+ block-size: max(var(--piq-button-height, 36px), var(--piq-size-target-minimum, 24px));
370
+ padding: 0;
371
+ border: 0;
372
+ border-radius: 50%;
373
+ background: transparent;
374
+ color: var(--piq-color-text-muted);
375
+ font-size: 1.25em;
376
+ cursor: pointer;
377
+ }
378
+ .piq-appearance__opt:hover:not(:disabled) { color: var(--piq-color-text-strong); }
379
+ .piq-appearance__opt[aria-checked="true"] { background: var(--piq-color-surface-sunken); color: var(--piq-color-text-strong); outline: var(--piq-border-default); outline-offset: -1px; }
380
+ .piq-appearance__opt:focus-visible { outline: var(--piq-focus-ring); outline-offset: var(--piq-focus-offset); }
381
+ .piq-appearance__opt:disabled { opacity: 0.4; cursor: not-allowed; }
382
+ @media (pointer: coarse) { .piq-appearance__opt { inline-size: var(--piq-size-target-touch, 44px); block-size: var(--piq-size-target-touch, 44px); } }
383
+ @media (forced-colors: active) { .piq-appearance__opt[aria-checked="true"] { outline: 2px solid CanvasText; } }
384
+
385
+ .piq-seg {
386
+ display: inline-flex;
387
+ flex-wrap: wrap;
388
+ width: fit-content;
389
+ max-width: 100%;
390
+ justify-self: start;
391
+ gap: var(--piq-choice-picker-gap, 0);
392
+ border: var(--piq-choice-picker-border, var(--piq-border-default));
393
+ border-radius: var(--piq-choice-picker-radius, var(--piq-button-radius));
394
+ overflow: hidden;
395
+ }
396
+ .piq-seg__opt {
397
+ --_state: 0%;
398
+ appearance: none;
399
+ display: inline-flex;
400
+ align-items: center;
401
+ justify-content: center;
402
+ gap: var(--piq-space-1);
403
+ min-height: var(--piq-choice-picker-height, var(--piq-button-height));
404
+ padding: 0 var(--piq-choice-picker-padding-x, var(--piq-space-4));
405
+ border: var(--piq-choice-picker-option-border, 0);
406
+ border-radius: var(--piq-choice-picker-option-radius, 0);
407
+ background-color: var(--piq-choice-picker-option-bg, var(--piq-color-surface));
408
+ background-image: linear-gradient(color-mix(in srgb, currentColor var(--_state), transparent) 0 0);
409
+ color: var(--piq-choice-picker-option-fg, var(--piq-color-text));
410
+ font: var(--piq-choice-picker-font-weight, var(--piq-font-weight-regular)) var(--piq-choice-picker-font-size, var(--piq-font-size-small)) / 1 var(--piq-font-body);
411
+ cursor: pointer;
412
+ }
413
+ .piq-seg__opt + .piq-seg__opt { border-left: var(--piq-choice-picker-divider, var(--piq-border-default)); }
414
+ .piq-seg__opt:hover:not([aria-checked="true"]) { --_state: var(--piq-state-layer-hover, 0%); background-color: var(--piq-choice-picker-option-hover-bg, var(--piq-color-surface-sunken)); }
415
+ .piq-seg__opt:focus-visible { outline: var(--piq-focus-ring); outline-offset: -2px; position: relative; }
416
+ .piq-seg__opt[aria-checked="true"] {
417
+ background-color: var(--piq-choice-picker-option-selected-bg, var(--piq-color-structure));
418
+ color: var(--piq-choice-picker-option-selected-fg, var(--piq-color-surface));
419
+ font-weight: var(--piq-choice-picker-option-selected-font-weight, var(--piq-choice-picker-font-weight, var(--piq-font-weight-regular)));
420
+ }
421
+ .piq-seg__tick { display: none; }
422
+ .piq-seg__opt[aria-checked="true"] .piq-seg__tick { display: var(--piq-choice-picker-option-selected-check, none); }
423
+
424
+ /* -------------------------------------------------------------------- card */
425
+
426
+ .piq-card {
427
+ display: grid;
428
+ gap: var(--piq-space-3);
429
+ padding: var(--piq-card-padding, var(--piq-space-4));
430
+ border: var(--piq-card-border, var(--piq-border-default));
431
+ border-radius: var(--piq-radius-card);
432
+ background: var(--piq-card-bg, var(--piq-color-surface));
433
+ box-shadow: var(--piq-shadow-card);
434
+ color: var(--piq-color-text);
435
+ }
436
+ .piq-card__title { margin: 0; color: var(--piq-color-text-strong); font: var(--piq-font-weight-strong) var(--piq-font-size-heading) / var(--piq-line-height-tight) var(--piq-font-heading); }
437
+ .piq-card__body { margin: 0; }
438
+ .piq-card__actions { display: flex; flex-wrap: wrap; gap: var(--piq-space-2); }
439
+
440
+ /* ------------------------------------------------------------------ notice */
441
+
442
+ /* A message in the flow of the page. --_tone is the message's colour:
443
+ the stripe, the tint and the tinted edge all come from it, so a theme
444
+ chooses the anatomy and the tone chooses the hue. */
445
+ .piq-notice {
446
+ --_tone: var(--piq-color-structure);
447
+ display: grid;
448
+ grid-template-columns: auto 1fr;
449
+ gap: var(--piq-space-1) var(--piq-space-3);
450
+ align-items: start;
451
+ padding: var(--piq-space-3) var(--piq-space-4);
452
+ border: var(--piq-notice-border-width, 1px) solid color-mix(in srgb, var(--_tone) var(--piq-notice-border-tone-mix, 0%), var(--piq-color-border));
453
+ border-left: var(--piq-notice-stripe-width, 3px) solid var(--_tone);
454
+ border-radius: var(--piq-notice-radius, var(--piq-radius-control));
455
+ background: color-mix(in srgb, var(--_tone) var(--piq-notice-tone-mix, 0%), var(--piq-notice-bg, var(--piq-color-surface)));
456
+ color: var(--piq-color-text);
457
+ }
458
+ .piq-notice--accent { --_tone: var(--piq-color-accent); }
459
+ .piq-notice--success { --_tone: var(--piq-state-live); }
460
+ .piq-notice--warning { --_tone: var(--piq-state-limited); }
461
+ .piq-notice--error { --_tone: var(--piq-state-closed); }
462
+ .piq-notice__mark {
463
+ display: grid;
464
+ place-items: center;
465
+ width: 1.25em;
466
+ height: 1.25em;
467
+ margin-top: 0.15em;
468
+ border-radius: 50%;
469
+ background: var(--_tone);
470
+ color: var(--piq-color-surface);
471
+ font: var(--piq-font-weight-strong) var(--piq-font-size-label) / 1 var(--piq-font-body);
472
+ }
473
+ .piq-notice__title { margin: 0; color: var(--piq-color-text-strong); font-weight: var(--piq-font-weight-strong); }
474
+ .piq-notice__body { grid-column: 2; margin: 0; }
475
+
476
+ /* ------------------------------------------------------------------- toast */
477
+
478
+ .piq-toasts {
479
+ position: fixed;
480
+ inset: auto var(--piq-space-4) var(--piq-space-4) auto;
481
+ z-index: 1000;
482
+ display: grid;
483
+ gap: var(--piq-space-2);
484
+ width: min(420px, calc(100vw - 2 * var(--piq-space-4)));
485
+ }
486
+ .piq-toast {
487
+ display: flex;
488
+ align-items: center;
489
+ gap: var(--piq-space-3);
490
+ min-height: 48px;
491
+ padding: var(--piq-space-2) var(--piq-space-2) var(--piq-space-2) var(--piq-space-4);
492
+ border-left: var(--piq-toast-stripe-width, 0) solid var(--piq-color-accent);
493
+ border-radius: var(--piq-toast-radius, var(--piq-radius-control));
494
+ background: var(--piq-toast-bg, var(--piq-color-surface));
495
+ box-shadow: var(--piq-toast-shadow, var(--piq-shadow-overlay));
496
+ color: var(--piq-toast-fg, var(--piq-color-text));
497
+ font: var(--piq-font-weight-regular) var(--piq-font-size-body) / var(--piq-line-height-body) var(--piq-font-body);
498
+ }
499
+ .piq-toast__text { flex: 1; margin: 0; }
500
+ .piq-toast__action {
501
+ --_state: 0%;
502
+ appearance: none;
503
+ min-height: 36px;
504
+ padding: 0 var(--piq-space-3);
505
+ border: 0;
506
+ border-radius: var(--piq-button-radius);
507
+ background: linear-gradient(color-mix(in srgb, currentColor var(--_state), transparent) 0 0) transparent;
508
+ color: var(--piq-toast-action-fg, var(--piq-color-accent));
509
+ font: var(--piq-font-weight-strong) var(--piq-font-size-small) / 1 var(--piq-font-body);
510
+ cursor: pointer;
511
+ }
512
+ .piq-toast__action:hover { --_state: 12%; }
513
+ .piq-toast__action:focus-visible { outline: var(--piq-focus-ring); outline-offset: 0; }
514
+
515
+ /* ------------------------------------------------------ loading and progress */
516
+
517
+ /* The bar, the spinner and the skeleton read --piq-progress-*,
518
+ --piq-spinner-* and --piq-skeleton-*, which the shared design systems set
519
+ (Material's 4px rounded bar, Carbon's square 8px bar and shimmer, Fluent's
520
+ 2px bar and wave, Databricks's 8px pill and pulse). A theme with its own
521
+ anatomy gets the fallbacks here. */
522
+ .piq-progress { display: grid; gap: var(--piq-space-2); min-width: 0; }
523
+ .piq-progress__head {
524
+ display: flex;
525
+ align-items: baseline;
526
+ justify-content: space-between;
527
+ gap: var(--piq-space-3);
528
+ color: var(--piq-color-text);
529
+ font: var(--piq-font-weight-strong) var(--piq-font-size-small) / 1.3 var(--piq-font-body);
530
+ }
531
+ .piq-progress__value { color: var(--piq-color-text-muted); font-weight: var(--piq-font-weight-regular); font-variant-numeric: tabular-nums; }
532
+ .piq-progress__track {
533
+ position: relative;
534
+ overflow: hidden;
535
+ height: var(--piq-progress-height, 6px);
536
+ border-radius: var(--piq-progress-radius, var(--piq-radius-control));
537
+ background: var(--piq-progress-track-bg, var(--piq-color-border));
538
+ }
539
+ .piq-progress__fill {
540
+ height: 100%;
541
+ border-radius: inherit;
542
+ background: var(--piq-progress-fill-bg, var(--piq-color-structure));
543
+ transition: width 200ms ease;
544
+ }
545
+ .piq-progress--indeterminate .piq-progress__fill {
546
+ position: absolute;
547
+ inset: 0 auto 0 0;
548
+ width: 40%;
549
+ animation: piq-progress-sweep 1.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
550
+ }
551
+ @keyframes piq-progress-sweep {
552
+ from { transform: translateX(-100%); }
553
+ to { transform: translateX(250%); }
554
+ }
555
+
556
+ .piq-spinner {
557
+ display: inline-flex;
558
+ align-items: center;
559
+ gap: var(--piq-space-2);
560
+ vertical-align: middle;
561
+ color: var(--piq-progress-fill-bg, var(--piq-color-structure));
562
+ }
563
+ .piq-spinner--sm { --_size: 16px; }
564
+ .piq-spinner--md { --_size: 24px; }
565
+ .piq-spinner--lg { --_size: 48px; }
566
+ .piq-spinner .piq-spinner__glyph { width: var(--_size); height: var(--_size); }
567
+ .piq-spinner__label { color: var(--piq-color-text); font: var(--piq-font-weight-regular) var(--piq-font-size-small) / 1.3 var(--piq-font-body); }
568
+ .piq-spinner__glyph {
569
+ flex: none;
570
+ display: block;
571
+ animation: piq-spin 0.9s linear infinite;
572
+ }
573
+ .piq-spinner__track,
574
+ .piq-spinner__arc { stroke-width: var(--piq-spinner-stroke-width, 2.5); }
575
+ .piq-spinner__track { stroke: var(--piq-spinner-track-color, transparent); }
576
+ .piq-spinner__arc {
577
+ stroke: currentColor;
578
+ stroke-dasharray: 40 100;
579
+ stroke-linecap: var(--piq-spinner-line-cap, round);
580
+ }
581
+ @keyframes piq-spin { to { transform: rotate(360deg); } }
582
+
583
+ /* A busy button keeps its label (and its name) under the spinner, so it
584
+ keeps its width. */
585
+ .piq-btn--busy { position: relative; cursor: progress; }
586
+ .piq-btn--busy .piq-btn__label { display: inline-flex; align-items: center; gap: inherit; opacity: 0; }
587
+ .piq-btn__spinner { position: absolute; inset: 0; display: grid; place-items: center; }
588
+ .piq-btn__spinner .piq-spinner__glyph { width: 1.25em; height: 1.25em; }
589
+ /* On a filled button the arc is the label's colour; a track would fight it. */
590
+ .piq-btn__spinner .piq-spinner__track { stroke: transparent; }
591
+
592
+ .piq-skeleton {
593
+ --_skeleton: var(--piq-skeleton-bg, var(--piq-color-border));
594
+ display: block;
595
+ max-width: 100%;
596
+ border-radius: var(--piq-skeleton-radius, var(--piq-radius-control));
597
+ }
598
+ .piq-skeleton:not(.piq-skeleton--text),
599
+ .piq-skeleton__line {
600
+ /* The highlight sits off the visible half until piq-shimmer sweeps it. */
601
+ background: linear-gradient(90deg, transparent 0 15%, color-mix(in srgb, var(--piq-color-surface) 60%, transparent) 25%, transparent 35% 100%) var(--_skeleton);
602
+ background-position: 100% 0;
603
+ background-size: 200% 100%;
604
+ animation: var(--piq-skeleton-effect, piq-pulse) 1.6s ease-in-out infinite;
605
+ }
606
+ .piq-skeleton--text { display: grid; gap: 0.6em; background: none; }
607
+ .piq-skeleton__line { display: block; height: 0.8em; border-radius: inherit; }
608
+ .piq-skeleton__line:last-child:not(:first-child) { width: 60%; }
609
+ .piq-skeleton--rect { width: 100%; height: 6rem; }
610
+ .piq-skeleton--circle { flex: none; border-radius: 50%; }
611
+ @keyframes piq-pulse { 50% { opacity: 0.5; } }
612
+ @keyframes piq-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
613
+
614
+ /* -------------------------------------------------------------- data table */
615
+
616
+ .piq-table-wrap { overflow-x: auto; }
617
+ .piq-table {
618
+ width: 100%;
619
+ border-collapse: collapse;
620
+ color: var(--piq-color-text);
621
+ font-size: var(--piq-table-font-size, var(--piq-font-size-small));
622
+ font-variant-numeric: tabular-nums;
623
+ }
624
+ .piq-table th {
625
+ height: var(--piq-table-header-height, auto);
626
+ padding: var(--piq-space-2) var(--piq-table-cell-padding-x, var(--piq-space-3));
627
+ border-bottom: var(--piq-table-header-border, 2px solid var(--piq-color-border));
628
+ background: var(--piq-table-header-bg, transparent);
629
+ color: var(--piq-table-header-fg, var(--piq-color-structure));
630
+ font-size: var(--piq-table-header-font-size, var(--piq-font-size-label));
631
+ font-weight: var(--piq-table-header-font-weight, var(--piq-font-weight-strong));
632
+ letter-spacing: var(--piq-table-header-letter-spacing, var(--piq-letter-spacing-label));
633
+ text-align: left;
634
+ text-transform: var(--piq-table-header-text-transform, uppercase);
635
+ white-space: nowrap;
636
+ }
637
+ .piq-table td {
638
+ height: var(--piq-table-row-height, auto);
639
+ padding: var(--piq-table-cell-padding-y, var(--piq-space-3)) var(--piq-table-cell-padding-x, var(--piq-space-3));
640
+ border-bottom: var(--piq-table-row-border, var(--piq-border-default));
641
+ vertical-align: middle;
642
+ }
643
+ /* Ruled or banded rows: the design system's table variant (ADR-022). */
644
+ .piq-table tbody tr:nth-child(even) { background: var(--piq-table-row-stripe-bg, transparent); }
645
+ .piq-table tbody tr:hover { background: var(--piq-table-row-hover-bg, var(--piq-color-surface-sunken)); }
646
+ .piq-table .piq-num { text-align: right; }
647
+ .piq-table__sort {
648
+ all: unset;
649
+ display: inline-flex;
650
+ align-items: center;
651
+ gap: var(--piq-space-1);
652
+ cursor: pointer;
653
+ }
654
+ .piq-table__sort:focus-visible { outline: var(--piq-focus-ring); outline-offset: 2px; }
655
+ .piq-table__arrow { opacity: 0.35; font-size: 0.9em; }
656
+ th[aria-sort="ascending"] .piq-table__arrow,
657
+ th[aria-sort="descending"] .piq-table__arrow { opacity: 1; }
658
+ .piq-table__pager {
659
+ display: flex;
660
+ align-items: center;
661
+ justify-content: flex-end;
662
+ gap: var(--piq-space-2);
663
+ padding-top: var(--piq-space-2);
664
+ color: var(--piq-color-text-muted);
665
+ font-size: var(--piq-font-size-label);
666
+ }
667
+
668
+ @media (prefers-reduced-motion: reduce) {
669
+ .piq-btn, .piq-check__box::after, .piq-radio::after, .piq-switch__track, .piq-switch__track::before, .piq-progress__fill { transition: none; }
670
+ /* Still, not gone: an unknown amount fills the track faintly, a skeleton
671
+ stands as it is, and a spinner turns slowly so the wait still shows. */
672
+ .piq-progress--indeterminate .piq-progress__fill { width: 100%; opacity: 0.35; animation: none; }
673
+ .piq-skeleton:not(.piq-skeleton--text), .piq-skeleton__line { animation: none; }
674
+ .piq-spinner__glyph { animation-duration: 3s; }
675
+ }
676
+
677
+ /* For text that is for assistive technology only, such as a table caption. */
678
+ .piq-visually-hidden {
679
+ position: absolute;
680
+ width: 1px;
681
+ height: 1px;
682
+ overflow: hidden;
683
+ clip-path: inset(50%);
684
+ white-space: nowrap;
685
+ }
686
+
687
+ /* ------------------------------------------------------------------- icons */
688
+
689
+ /* <Icon>: an inline SVG in the text colour, sized by its font (1em) unless
690
+ told otherwise, sitting on the text's baseline like a glyph. */
691
+ .piq-icon {
692
+ display: inline-block;
693
+ flex-shrink: 0;
694
+ vertical-align: -0.125em;
695
+ }
696
+
697
+ /* -------------------------------------------------------------------- logo */
698
+
699
+ /* <Logo>: the brand's artwork from its brand tokens, so it follows the theme
700
+ and the appearance. Artwork is drawn as supplied (--piq-brand-logo-image)
701
+ or, for single-colour artwork, as a mask painted in --piq-brand-logo-bg
702
+ (the brand sets it to its logo paint). Height and aspect come from the
703
+ brand; 28px and 3:1 when it gives none. A brand without artwork gets its
704
+ title in --piq-brand-logo-paint (.piq-logo--text). */
705
+ .piq-logo {
706
+ --piq-logo-height: var(--piq-brand-logo-height, 28px);
707
+ display: inline-block;
708
+ flex-shrink: 0;
709
+ vertical-align: middle;
710
+ height: var(--piq-logo-height);
711
+ aspect-ratio: var(--piq-brand-logo-aspect, 3);
712
+ background-color: var(--piq-brand-logo-bg, transparent);
713
+ background-image: var(--piq-brand-logo-image, none);
714
+ background-position: left center;
715
+ background-repeat: no-repeat;
716
+ background-size: contain;
717
+ mask-image: var(--piq-brand-logo-mask, none);
718
+ mask-position: left center;
719
+ mask-repeat: no-repeat;
720
+ mask-size: contain;
721
+ }
722
+ .piq-logo--sm { --piq-logo-height: var(--piq-brand-logo-height-sm, 22px); }
723
+ .piq-logo--mark {
724
+ aspect-ratio: 1;
725
+ background-color: var(--piq-brand-mark-bg, transparent);
726
+ background-image: var(--piq-brand-mark-image, none);
727
+ background-position: center;
728
+ mask-image: var(--piq-brand-mark-mask, none);
729
+ mask-position: center;
730
+ }
731
+ .piq-logo--text {
732
+ display: inline-flex;
733
+ align-items: center;
734
+ aspect-ratio: auto;
735
+ background: none;
736
+ mask-image: none;
737
+ color: var(--piq-brand-logo-paint, var(--piq-color-text-strong));
738
+ font-family: var(--piq-font-heading);
739
+ font-size: calc(var(--piq-logo-height) * 0.72);
740
+ font-weight: var(--piq-font-weight-strong);
741
+ line-height: 1;
742
+ white-space: nowrap;
743
+ }
744
+ .piq-logo--mark.piq-logo--text { justify-content: center; width: var(--piq-logo-height); }
745
+
746
+ /* ------------------------------------------------------------- menu button */
747
+
748
+ /* A menu of actions under its button (MenuButton): the same list as .piq-menu,
749
+ positioned under the button, start-aligned or end-aligned. */
750
+ .piq-menubutton { position: relative; display: inline-block; }
751
+ .piq-menubutton__menu {
752
+ position: absolute;
753
+ inset-block-start: 100%;
754
+ inset-inline-start: 0;
755
+ z-index: 10;
756
+ min-inline-size: 100%;
757
+ inline-size: max-content;
758
+ max-inline-size: var(--piq-size-measure);
759
+ }
760
+ .piq-menubutton[data-align="end"] > .piq-menubutton__menu { inset-inline-start: auto; inset-inline-end: 0; }
761
+ .piq-menubutton__menu .piq-menu__item {
762
+ box-sizing: border-box;
763
+ inline-size: 100%;
764
+ min-block-size: max(var(--piq-menu-item-height, 36px), var(--piq-size-target-minimum, 24px));
765
+ border: 0;
766
+ background: none;
767
+ font: inherit;
768
+ text-align: start;
769
+ text-decoration: none;
770
+ cursor: pointer;
771
+ }
772
+ .piq-menu__item:focus-visible { outline: var(--piq-focus-ring); outline-offset: calc(var(--piq-focus-offset, 2px) * -1); }
773
+ .piq-menu__item[aria-disabled="true"] { color: var(--piq-color-text-muted); cursor: default; }
774
+ .piq-menu__item[aria-checked="true"] { font-weight: var(--piq-font-weight-strong); }
775
+ .piq-menu__item[aria-checked="true"]::after { content: "✓" / ""; margin-inline-start: auto; }
776
+
777
+ /* ------------------------------------------------------------- breadcrumbs */
778
+
779
+ /* The full trail where there is room; below the medium size class only the
780
+ link back to the parent (the breadcrumbs measure their own width). */
781
+ .piq-breadcrumbs { container-type: inline-size; font-size: var(--piq-font-size-small); }
782
+ .piq-breadcrumbs__list { display: none; flex-wrap: wrap; align-items: center; gap: var(--piq-space-1); margin: 0; padding: 0; list-style: none; }
783
+ .piq-breadcrumbs:not(:has(.piq-breadcrumbs__back)) .piq-breadcrumbs__list { display: flex; }
784
+ .piq-breadcrumbs__item { display: inline-flex; align-items: center; gap: var(--piq-space-1); }
785
+ .piq-breadcrumbs__item + .piq-breadcrumbs__item::before { content: "/" / ""; color: var(--piq-color-text-subtle); }
786
+ .piq-breadcrumbs a {
787
+ display: inline-flex;
788
+ align-items: center;
789
+ gap: var(--piq-space-1);
790
+ min-block-size: var(--piq-size-target-minimum, 24px);
791
+ color: var(--piq-color-text-muted);
792
+ text-underline-offset: 0.2em;
793
+ }
794
+ .piq-breadcrumbs a:hover { color: var(--piq-color-text); }
795
+ .piq-breadcrumbs a:focus-visible { outline: var(--piq-focus-ring); outline-offset: var(--piq-focus-offset, 2px); }
796
+ .piq-breadcrumbs [aria-current="page"] { color: var(--piq-color-text); font-weight: var(--piq-font-weight-strong); text-decoration: none; }
797
+ @container (min-width: 600px) {
798
+ .piq-breadcrumbs .piq-breadcrumbs__list { display: flex; }
799
+ .piq-breadcrumbs .piq-breadcrumbs__back { display: none; }
800
+ }
801
+
802
+ /* -------------------------------------------------------------------- tabs */
803
+
804
+ /* The selected tab is marked by the design system's tabs variant: an
805
+ underline (indicator height) or an enclosed fill (tab background). */
806
+ .piq-tabs__list {
807
+ display: flex;
808
+ overflow-x: auto;
809
+ border-block-end: var(--piq-tabs-list-border, var(--piq-border-default));
810
+ scrollbar-width: thin;
811
+ }
812
+ .piq-tabs__tab {
813
+ all: unset;
814
+ box-sizing: border-box;
815
+ display: inline-flex;
816
+ align-items: center;
817
+ gap: var(--piq-space-2);
818
+ min-block-size: max(var(--piq-button-height, 36px), var(--piq-size-target-minimum, 24px));
819
+ padding-inline: var(--piq-tabs-tab-padding-x, var(--piq-space-4));
820
+ border-start-start-radius: var(--piq-tabs-tab-radius, 0);
821
+ border-start-end-radius: var(--piq-tabs-tab-radius, 0);
822
+ color: var(--piq-color-text-muted);
823
+ font: var(--piq-font-weight-strong) var(--piq-font-size-body) / var(--piq-line-height-tight) var(--piq-font-body);
824
+ white-space: nowrap;
825
+ cursor: pointer;
826
+ }
827
+ .piq-tabs__tab:hover { color: var(--piq-color-text); }
828
+ .piq-tabs__tab[aria-selected="true"] {
829
+ background: var(--piq-tabs-tab-bg-selected, transparent);
830
+ box-shadow: inset 0 calc(var(--piq-tabs-indicator-height, 2px) * -1) 0 var(--piq-color-structure);
831
+ color: var(--piq-color-text-strong);
832
+ }
833
+ .piq-tabs__tab:focus-visible { outline: var(--piq-focus-ring); outline-offset: calc(var(--piq-focus-offset, 2px) * -1); }
834
+ .piq-tabs__count {
835
+ padding-inline: var(--piq-space-2);
836
+ border-radius: var(--piq-pill-radius, var(--piq-radius-control));
837
+ background: var(--piq-color-surface-sunken);
838
+ font-size: var(--piq-font-size-small);
839
+ font-variant-numeric: tabular-nums;
840
+ }
841
+ .piq-tabs__panel { padding-block: var(--piq-space-4); }
842
+ .piq-tabs__panel:focus-visible { outline: var(--piq-focus-ring); outline-offset: var(--piq-focus-offset, 2px); }
843
+
844
+ /* ------------------------------------------------------------------- sheet */
845
+
846
+ /* A modal <dialog> from an edge. It leaves a strip of the page showing at the
847
+ side, so a tap outside can close it. */
848
+ .piq-sheet {
849
+ box-sizing: border-box;
850
+ margin: 0;
851
+ padding: 0;
852
+ border: 0;
853
+ max-inline-size: none;
854
+ max-block-size: none;
855
+ background: var(--piq-color-surface);
856
+ box-shadow: var(--piq-shadow-overlay);
857
+ color: var(--piq-color-text);
858
+ }
859
+ .piq-sheet::backdrop { background: color-mix(in srgb, var(--piq-color-text-strong) 40%, transparent); }
860
+ .piq-sheet[data-side="start"],
861
+ .piq-sheet[data-side="end"] { inset-block: 0; block-size: 100dvh; inline-size: min(var(--piq-size-measure), calc(100vw - var(--piq-size-target-touch, 44px))); }
862
+ .piq-sheet[data-side="start"] { inset-inline: 0 auto; }
863
+ .piq-sheet[data-side="end"] { inset-inline: auto 0; }
864
+ .piq-sheet[data-side="bottom"] {
865
+ inset-inline: 0;
866
+ inset-block: auto 0;
867
+ inline-size: 100%;
868
+ max-block-size: calc(100dvh - var(--piq-size-target-touch, 44px));
869
+ border-start-start-radius: var(--piq-radius-card);
870
+ border-start-end-radius: var(--piq-radius-card);
871
+ }
872
+ .piq-sheet[data-side="full"] { inset: 0; inline-size: 100%; block-size: 100dvh; }
873
+ .piq-sheet__body {
874
+ display: grid;
875
+ align-content: start;
876
+ gap: var(--piq-space-4);
877
+ padding: var(--piq-space-4);
878
+ padding-block-end: max(var(--piq-space-4), env(safe-area-inset-bottom));
879
+ }
880
+ .piq-sheet__head { display: flex; align-items: center; gap: var(--piq-space-3); }
881
+ .piq-sheet__title { margin: 0; color: var(--piq-color-text-strong); font: var(--piq-font-weight-strong) var(--piq-font-size-heading) / var(--piq-line-height-tight) var(--piq-font-heading); }
882
+ .piq-sheet__close { margin-inline-start: auto; }
883
+
884
+ /* ------------------------------------------------------------------ dialog */
885
+
886
+ /* A modal <dialog> centred by the browser, no wider than a reading measure
887
+ and never wider than the screen less a margin. */
888
+ .piq-dialog {
889
+ box-sizing: border-box;
890
+ inline-size: min(var(--piq-size-measure), calc(100vw - var(--piq-space-4) * 2));
891
+ max-block-size: calc(100dvh - var(--piq-space-4) * 2);
892
+ padding: var(--piq-space-5);
893
+ border: var(--piq-card-border, var(--piq-border-default));
894
+ border-radius: var(--piq-radius-card);
895
+ background: var(--piq-color-surface);
896
+ box-shadow: var(--piq-shadow-overlay);
897
+ color: var(--piq-color-text);
898
+ }
899
+ .piq-dialog[open] { display: grid; gap: var(--piq-space-4); }
900
+ .piq-dialog::backdrop { background: color-mix(in srgb, var(--piq-color-text-strong) 40%, transparent); }
901
+ .piq-dialog__head { display: flex; align-items: center; gap: var(--piq-space-3); }
902
+ .piq-dialog__title { margin: 0; color: var(--piq-color-text-strong); font: var(--piq-font-weight-strong) var(--piq-font-size-heading) / var(--piq-line-height-tight) var(--piq-font-heading); }
903
+ .piq-dialog__close { margin-inline-start: auto; }
904
+ .piq-dialog__description { margin: 0; color: var(--piq-color-text-muted); }
905
+ .piq-dialog__body { display: grid; gap: var(--piq-space-3); }
906
+ .piq-dialog__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--piq-space-2); }
907
+
908
+ /* -------------------------------------------------------------- date range */
909
+
910
+ .piq-date-range { display: grid; gap: var(--piq-space-2); margin: 0; padding: 0; border: 0; min-inline-size: 0; }
911
+ .piq-date-range__fields { display: flex; flex-wrap: wrap; gap: var(--piq-space-3); }
912
+ .piq-date-range__fields > .piq-field { flex: 1 1 10rem; }
913
+
914
+ /* ---------------------------------------------------------------- combobox */
915
+
916
+ .piq-combobox__field { position: relative; display: block; }
917
+ .piq-combobox__field > .piq-field__input { inline-size: 100%; }
918
+ .piq-combobox__list { position: absolute; inset-inline: 0; inset-block-start: 100%; z-index: 10; max-block-size: calc(var(--piq-size-target-touch, 44px) * 7); margin: var(--piq-menu-offset, 4px) 0 0; overflow-y: auto; }
919
+ .piq-combobox__list[hidden] { display: none; }
920
+ .piq-combobox__list .piq-menu__item { cursor: pointer; }
921
+ .piq-combobox__empty { position: absolute; inset-inline: 0; inset-block-start: 100%; z-index: 10; margin-block-start: var(--piq-menu-offset, 4px); padding: var(--piq-space-2) var(--piq-space-3); border: var(--piq-menu-border, var(--piq-border-default)); border-radius: var(--piq-menu-radius, var(--piq-radius-control)); background: var(--piq-menu-bg, var(--piq-color-surface)); color: var(--piq-color-text-muted); }
922
+
923
+ /* ----------------------------------------------------------------- tooltip */
924
+
925
+ /* Above the control by default (placement bottom puts it below); it can be
926
+ hovered, so the pointer may move onto it. */
927
+ .piq-tooltip-anchor { position: relative; display: inline-flex; }
928
+ .piq-tooltip {
929
+ position: absolute;
930
+ inset-block-end: 100%;
931
+ inset-inline-start: 50%;
932
+ z-index: 20;
933
+ translate: -50% calc(var(--piq-space-1) * -1);
934
+ inline-size: max-content;
935
+ max-inline-size: calc(var(--piq-size-measure) / 2);
936
+ padding: var(--piq-space-1) var(--piq-space-2);
937
+ border-radius: var(--piq-radius-control);
938
+ background: var(--piq-color-text-strong);
939
+ color: var(--piq-color-ground);
940
+ font-size: var(--piq-font-size-small);
941
+ line-height: var(--piq-line-height-tight);
942
+ }
943
+ .piq-tooltip[data-placement="bottom"] { inset-block: 100% auto; translate: -50% var(--piq-space-1); }
944
+ .piq-tooltip[hidden] { display: none; }
945
+
946
+ /* -------------------------------------------------------------- pagination */
947
+
948
+ .piq-pagination { display: flex; flex-wrap: wrap; align-items: end; justify-content: flex-end; gap: var(--piq-space-3); }
949
+ .piq-pagination__size { flex-direction: row; align-items: center; }
950
+ .piq-pagination__position { margin: 0; align-self: center; color: var(--piq-color-text-muted); font-size: var(--piq-font-size-small); font-variant-numeric: tabular-nums; }
951
+ .piq-pagination__steps { display: flex; gap: var(--piq-space-1); }
952
+ /* Mirrored in a right-to-left page. An attribute selector, not :dir(), which
953
+ bundlers rewrite into a :lang() list the audit cannot recognise as the SDK's. */
954
+ [dir="rtl"] .piq-pagination__steps svg { transform: scaleX(-1); }
955
+
956
+ /* -------------------------------------------------------------------- chip */
957
+
958
+ /* An applied filter: its label and a button that removes it. */
959
+ .piq-chip {
960
+ display: inline-flex;
961
+ align-items: center;
962
+ gap: var(--piq-space-1);
963
+ min-block-size: var(--piq-size-target-minimum, 24px);
964
+ padding-inline: var(--piq-space-3) var(--piq-space-1);
965
+ border: var(--piq-pill-border, var(--piq-border-default));
966
+ border-radius: var(--piq-pill-radius, var(--piq-radius-control));
967
+ background: var(--piq-color-surface-sunken);
968
+ color: var(--piq-color-text);
969
+ font-size: var(--piq-font-size-small);
970
+ }
971
+ .piq-chip__remove {
972
+ all: unset;
973
+ box-sizing: border-box;
974
+ display: inline-grid;
975
+ place-items: center;
976
+ min-inline-size: var(--piq-size-target-minimum, 24px);
977
+ min-block-size: var(--piq-size-target-minimum, 24px);
978
+ border-radius: var(--piq-pill-radius, var(--piq-radius-control));
979
+ color: var(--piq-color-text-muted);
980
+ cursor: pointer;
981
+ }
982
+ .piq-chip__remove:hover { color: var(--piq-color-text-strong); }
983
+ .piq-chip__remove:focus-visible { outline: var(--piq-focus-ring); outline-offset: var(--piq-focus-offset, 2px); }
984
+
985
+ /* ------------------------------------------------------------ touch input */
986
+
987
+ /* On a touch screen every control is at least the touch-target size
988
+ (WCAG 2.5.8; Apple HIG 44pt), whatever the window's width. */
989
+ @media (pointer: coarse) {
990
+ .piq-btn,
991
+ .piq-menu__item,
992
+ .piq-tabs__tab,
993
+ .piq-breadcrumbs a,
994
+ .piq-chip__remove { min-block-size: var(--piq-size-target-touch, 44px); }
995
+ .piq-chip__remove { min-inline-size: var(--piq-size-target-touch, 44px); }
996
+ .piq-btn { min-inline-size: var(--piq-size-target-touch, 44px); }
997
+ }