declarative-forms 2.0.0 → 2.1.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.
@@ -1,304 +1,616 @@
1
1
  /*!
2
- * declarative-forms — default theme
2
+ * declarative-forms — the default stylesheet
3
3
  *
4
- * Import with: @import "declarative-forms/styles.css";
4
+ * import 'declarative-forms/styles.css';
5
5
  *
6
- * This is the v1 `assets/default.css` with every hardcoded value lifted into a
7
- * `--dl-*` custom property. The selectors and the cascade are unchanged, and
8
- * each `var()` carries v1's value as its fallback, so an existing consumer
9
- * stylesheet keeps rendering identically — but you can now retheme by setting
10
- * tokens instead of overriding rules.
6
+ * This is what you get out of the box: a modern look with automatic light and
7
+ * dark mode. The v1-era look lives on as `declarative-forms/classic.css` for
8
+ * installations with overrides built against it.
11
9
  *
12
- * Tokens are declared at zero specificity via `:where(:root)`, so setting any
13
- * of them anywhere wins without `!important`.
10
+ * Both stylesheets render the same frozen DOM — every class name, id and
11
+ * structural hook is identical — so overlay CSS applies to either one, and
12
+ * three rules keep the swap between them safe:
14
13
  *
15
- * `<dl-select>` ships its own structural styles from JS; the tokens it reads
16
- * are listed under "combobox" below.
14
+ * 1. Selectors mirror the classic stylesheet's, at the same specificity.
15
+ * Overrides written against the classic look therefore still win, with
16
+ * the same amount of force they needed before.
17
+ * 2. Every visual value is a `--dl-*` custom property, declared at zero
18
+ * specificity via `:where()`, so setting a token anywhere beats it.
19
+ * 3. Nothing here changes the DOM contract. See docs/dom-contract.md.
20
+ *
21
+ * Light and dark are chosen automatically from `prefers-color-scheme`. Force
22
+ * one with `data-dl-theme="light"` or `data-dl-theme="dark"` on any ancestor
23
+ * (usually <html>), which also works per-dialog.
17
24
  */
18
25
 
19
- :where(:root) {
20
- /* typography */
21
- --dl-font-family: 'Rubik', sans-serif;
22
- --dl-font-size: 0.9em;
23
-
24
- /* palette */
25
- --dl-accent: #1ea6a3;
26
- --dl-accent-hover: #22bb8b;
27
- --dl-danger: #fe070b;
28
- --dl-surface: #fff;
29
- --dl-surface-muted: #f8f8f8;
30
- --dl-surface-sunken: #eee;
31
- --dl-overlay: rgba(0, 0, 0, 0.6);
32
- --dl-text-color: #545454;
33
- --dl-label-color: #58565c;
34
- --dl-line-color: #ddd;
35
- --dl-focused-line-color: #bbb;
36
- --dl-border-muted: #e7e6e6;
37
-
38
- /* metrics */
39
- --dl-radius: 4px;
40
- --dl-field-width: 400px;
41
- --dl-modal-width: 416px;
42
- --dl-large-modal-width: 800px;
43
-
44
- /* tooltip marker + bubble */
45
- --dl-tooltip-background: #e6e6e6;
46
- --dl-tooltip-color: #88858e;
47
- --dl-tooltip-bubble-background: #413e48;
48
- --dl-tooltip-bubble-color: #d1cfd8;
49
- --dl-tooltip-success-background: #d1e7dd;
50
- --dl-tooltip-success-color: #12b568;
51
- --dl-tooltip-warning-background: #ffecb5;
52
- --dl-tooltip-warning-color: #664d03;
53
- --dl-tooltip-error-background: #f8d7da;
54
- --dl-tooltip-error-color: #842029;
55
-
56
- /* combobox — also read by the styles <dl-select> injects itself */
57
- --dl-options-background: var(--dl-surface, #fff);
58
- --dl-options-text-color: var(--dl-text-color, #545454);
59
- --dl-options-inactive-text-color: var(--dl-text-color, #545454);
60
- --dl-options-option-hover-color: rgba(224, 240, 227, 0.4);
61
- }
62
-
63
- /* ------------------------------------------------------------------ modal */
26
+ /* ══════════════════════════════════════════════════════════ design tokens ══ */
27
+
28
+ :where(:root),
29
+ :where([data-dl-theme='light']) {
30
+ /* — type ————————————————————————————————————————————————— */
31
+ --dl-font-family:
32
+ ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
33
+ sans-serif;
34
+ --dl-font-size: 0.9375rem;
35
+ --dl-font-size-sm: 0.8125rem;
36
+ --dl-line-height: 1.5;
37
+
38
+ /* — neutrals ——————————————————————————————————————————————— */
39
+ --dl-surface: #ffffff;
40
+ --dl-surface-muted: #f6f7f9;
41
+ --dl-surface-sunken: #eef0f4;
42
+ --dl-surface-raised: #ffffff;
43
+
44
+ --dl-text-color: #1b1f27;
45
+ --dl-label-color: #39414f;
46
+ --dl-text-muted: #6b7484;
47
+
48
+ --dl-line-color: #e0e4ea;
49
+ --dl-line-strong: #cbd2dc;
50
+
51
+ /* — accent ————————————————————————————————————————————————— */
52
+ --dl-accent: #12968f;
53
+ --dl-accent-hover: #0e807a;
54
+ --dl-accent-contrast: #ffffff;
55
+ --dl-accent-soft: rgba(18, 150, 143, 0.1);
56
+ --dl-accent-ring: rgba(18, 150, 143, 0.28);
57
+
58
+ --dl-danger: #d1394b;
59
+ --dl-danger-soft: rgba(209, 57, 75, 0.1);
60
+
61
+ /* — overlay ———————————————————————————————————————————————— */
62
+ --dl-overlay: rgba(17, 22, 29, 0.42);
63
+ --dl-overlay-blur: 4px;
64
+
65
+ /* — shape —————————————————————————————————————————————————— */
66
+ --dl-radius-sm: 6px;
67
+ --dl-radius: 9px;
68
+ --dl-radius-lg: 14px;
69
+ --dl-radius-pill: 999px;
70
+
71
+ --dl-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
72
+ --dl-shadow-modal:
73
+ 0 1px 3px rgba(16, 24, 40, 0.08), 0 12px 28px -6px rgba(16, 24, 40, 0.16),
74
+ 0 32px 64px -12px rgba(16, 24, 40, 0.18);
75
+ --dl-shadow-popup:
76
+ 0 4px 10px -2px rgba(16, 24, 40, 0.1), 0 16px 32px -8px rgba(16, 24, 40, 0.18);
77
+
78
+ /* — metrics ———————————————————————————————————————————————— */
79
+ --dl-gap: 1.125rem;
80
+ --dl-field-width: 100%;
81
+ --dl-modal-width: 30rem;
82
+ --dl-large-modal-width: 52rem;
83
+ --dl-modal-padding: 1.5rem;
84
+ --dl-stack-peek: 8px;
85
+ --dl-stack-inset: 12px;
86
+ --dl-control-padding-y: 0.55rem;
87
+ --dl-control-padding-x: 0.75rem;
88
+
89
+ --dl-transition: 140ms cubic-bezier(0.4, 0, 0.2, 1);
90
+
91
+ /* — feedback ——————————————————————————————————————————————— */
92
+ --dl-tooltip-background: #eef0f4;
93
+ --dl-tooltip-color: #5b6473;
94
+ --dl-tooltip-bubble-background: #22272f;
95
+ --dl-tooltip-bubble-color: #eceef2;
96
+
97
+ --dl-tooltip-success-background: #dcf5e7;
98
+ --dl-tooltip-success-color: #11794b;
99
+ --dl-tooltip-warning-background: #fdf0cd;
100
+ --dl-tooltip-warning-color: #7a5407;
101
+ --dl-tooltip-error-background: #fbe0e3;
102
+ --dl-tooltip-error-color: #96222f;
103
+
104
+ /* — combobox (also read by the CSS <dl-select> injects itself) ——— */
105
+ --dl-options-background: var(--dl-surface-raised);
106
+ --dl-options-text-color: var(--dl-text-color);
107
+ --dl-options-inactive-text-color: var(--dl-text-muted);
108
+ --dl-options-option-hover-color: var(--dl-accent-soft);
109
+ --dl-options-padding-top: 0.5rem;
110
+ --dl-options-padding-right: 0.75rem;
111
+ --dl-options-padding-bottom: 0.5rem;
112
+ --dl-options-padding-left: 0.75rem;
113
+ --dl-focused-line-color: var(--dl-accent);
114
+ --dl-drop-down-icon-margin-top: 7px;
115
+ --dl-select-loading-col1: #eef0f4;
116
+ --dl-select-loading-col2: #e2e6ec;
117
+ }
118
+
119
+ /* Automatic dark, unless something above has pinned the theme to light. */
120
+ @media (prefers-color-scheme: dark) {
121
+ :where(:root:not([data-dl-theme='light'])) {
122
+ color-scheme: dark;
123
+
124
+ --dl-surface: #171a1f;
125
+ --dl-surface-muted: #1e222a;
126
+ --dl-surface-sunken: #262b34;
127
+ --dl-surface-raised: #1e222a;
128
+
129
+ --dl-text-color: #e7eaf0;
130
+ --dl-label-color: #c3cad5;
131
+ --dl-text-muted: #8d97a6;
132
+
133
+ --dl-line-color: #2c323c;
134
+ --dl-line-strong: #3b434f;
135
+
136
+ --dl-accent: #2fb7ae;
137
+ --dl-accent-hover: #46c9c0;
138
+ --dl-accent-contrast: #06231f;
139
+ --dl-accent-soft: rgba(47, 183, 174, 0.16);
140
+ --dl-accent-ring: rgba(47, 183, 174, 0.32);
141
+
142
+ --dl-danger: #f4707f;
143
+ --dl-danger-soft: rgba(244, 112, 127, 0.16);
144
+
145
+ --dl-overlay: rgba(6, 9, 13, 0.62);
146
+
147
+ --dl-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
148
+ --dl-shadow-modal:
149
+ 0 1px 3px rgba(0, 0, 0, 0.5), 0 12px 28px -6px rgba(0, 0, 0, 0.55),
150
+ 0 32px 64px -12px rgba(0, 0, 0, 0.6);
151
+ --dl-shadow-popup:
152
+ 0 4px 10px -2px rgba(0, 0, 0, 0.45), 0 16px 32px -8px rgba(0, 0, 0, 0.55);
153
+
154
+ --dl-tooltip-background: #2b313b;
155
+ --dl-tooltip-color: #aab3c0;
156
+ --dl-tooltip-bubble-background: #333a45;
157
+ --dl-tooltip-bubble-color: #e7eaf0;
158
+
159
+ --dl-tooltip-success-background: rgba(45, 190, 126, 0.18);
160
+ --dl-tooltip-success-color: #5fd9a0;
161
+ --dl-tooltip-warning-background: rgba(233, 176, 44, 0.18);
162
+ --dl-tooltip-warning-color: #edc65f;
163
+ --dl-tooltip-error-background: rgba(244, 112, 127, 0.18);
164
+ --dl-tooltip-error-color: #f9909b;
165
+
166
+ --dl-select-loading-col1: #1e222a;
167
+ --dl-select-loading-col2: #2a3039;
168
+ }
169
+ }
170
+
171
+ /* Explicitly pinned dark, regardless of the OS preference. */
172
+ :where([data-dl-theme='dark']) {
173
+ color-scheme: dark;
174
+
175
+ --dl-surface: #171a1f;
176
+ --dl-surface-muted: #1e222a;
177
+ --dl-surface-sunken: #262b34;
178
+ --dl-surface-raised: #1e222a;
179
+
180
+ --dl-text-color: #e7eaf0;
181
+ --dl-label-color: #c3cad5;
182
+ --dl-text-muted: #8d97a6;
183
+
184
+ --dl-line-color: #2c323c;
185
+ --dl-line-strong: #3b434f;
186
+
187
+ --dl-accent: #2fb7ae;
188
+ --dl-accent-hover: #46c9c0;
189
+ --dl-accent-contrast: #06231f;
190
+ --dl-accent-soft: rgba(47, 183, 174, 0.16);
191
+ --dl-accent-ring: rgba(47, 183, 174, 0.32);
192
+
193
+ --dl-danger: #f4707f;
194
+ --dl-danger-soft: rgba(244, 112, 127, 0.16);
195
+
196
+ --dl-overlay: rgba(6, 9, 13, 0.62);
197
+
198
+ --dl-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
199
+ --dl-shadow-modal:
200
+ 0 1px 3px rgba(0, 0, 0, 0.5), 0 12px 28px -6px rgba(0, 0, 0, 0.55),
201
+ 0 32px 64px -12px rgba(0, 0, 0, 0.6);
202
+ --dl-shadow-popup:
203
+ 0 4px 10px -2px rgba(0, 0, 0, 0.45), 0 16px 32px -8px rgba(0, 0, 0, 0.55);
204
+
205
+ --dl-tooltip-background: #2b313b;
206
+ --dl-tooltip-color: #aab3c0;
207
+ --dl-tooltip-bubble-background: #333a45;
208
+ --dl-tooltip-bubble-color: #e7eaf0;
209
+
210
+ --dl-tooltip-success-background: rgba(45, 190, 126, 0.18);
211
+ --dl-tooltip-success-color: #5fd9a0;
212
+ --dl-tooltip-warning-background: rgba(233, 176, 44, 0.18);
213
+ --dl-tooltip-warning-color: #edc65f;
214
+ --dl-tooltip-error-background: rgba(244, 112, 127, 0.18);
215
+ --dl-tooltip-error-color: #f9909b;
216
+
217
+ --dl-select-loading-col1: #1e222a;
218
+ --dl-select-loading-col2: #2a3039;
219
+ }
220
+
221
+ /* ═══════════════════════════════════════════════════════════════ modal ══ */
64
222
 
65
223
  .dl-modal {
66
224
  position: fixed;
67
- top: 0;
68
- left: 0;
225
+ inset: 0;
226
+ z-index: 1000;
69
227
  display: block;
70
228
  margin: 0;
71
229
  padding: 0;
72
230
  width: 100%;
73
231
  height: 100%;
74
- background: var(--dl-overlay, rgba(0, 0, 0, 0.6));
75
232
  overflow-y: auto;
233
+ background: var(--dl-overlay);
234
+ -webkit-backdrop-filter: blur(var(--dl-overlay-blur));
235
+ backdrop-filter: blur(var(--dl-overlay-blur));
236
+ font-family: var(--dl-font-family);
237
+ animation: dl-fade var(--dl-transition) both;
76
238
  }
77
239
 
78
240
  .dl-modal.noModalDialog {
79
241
  position: static;
242
+ inset: auto;
80
243
  width: 100%;
81
- height: 100%;
82
- margin: 0;
83
- padding: 0;
84
- background-color: var(--dl-surface, #fff);
244
+ height: auto;
245
+ overflow: visible;
246
+ background: transparent;
247
+ -webkit-backdrop-filter: none;
248
+ backdrop-filter: none;
249
+ animation: none;
85
250
  }
86
251
 
87
252
  .dl-modal-hidden {
88
253
  display: none !important;
89
254
  }
90
255
 
256
+ /* Stacked dialogs. The backdrop of a dialog opening over another one, and of
257
+ one revealed when the dialog above it closes, is continuous with the backdrop
258
+ that was already on screen — fading it in from nothing would flash the page
259
+ through the gap. A newly stacked dialog still rises; a restored one does not,
260
+ since it is not new. */
261
+ .dl-modal.dl-modal-stacked,
262
+ .dl-modal.dl-modal-restored,
263
+ .dl-modal.dl-modal-restored .modal {
264
+ animation: none;
265
+ }
266
+
267
+ /* The dialogs underneath are hidden, so the depth of the stack is drawn as two
268
+ card edges peeking out above the dialog on top. They sit entirely above the
269
+ box — never over its content — and the second one only appears once there are
270
+ two dialogs below, which `--dl-stack-depth` (set by the library) reports. */
271
+ .dl-modal.dl-modal-stacked .modal {
272
+ position: relative;
273
+ }
274
+
275
+ .dl-modal.dl-modal-stacked .modal::before,
276
+ .dl-modal.dl-modal-stacked .modal::after {
277
+ content: '';
278
+ position: absolute;
279
+ height: var(--dl-stack-peek);
280
+ border: 1px solid var(--dl-line-strong);
281
+ border-bottom: none;
282
+ border-radius: var(--dl-radius-lg) var(--dl-radius-lg) 0 0;
283
+ }
284
+
285
+ .dl-modal.dl-modal-stacked .modal::before {
286
+ right: var(--dl-stack-inset);
287
+ bottom: 100%;
288
+ left: var(--dl-stack-inset);
289
+ background: var(--dl-surface-muted);
290
+ }
291
+
292
+ .dl-modal.dl-modal-stacked .modal::after {
293
+ right: calc(var(--dl-stack-inset) * 2);
294
+ bottom: calc(100% + var(--dl-stack-peek));
295
+ left: calc(var(--dl-stack-inset) * 2);
296
+ background: var(--dl-surface-sunken);
297
+ opacity: clamp(0, calc(var(--dl-stack-depth, 1) - 1), 1);
298
+ }
299
+
91
300
  .dl-modal .modal {
92
301
  display: block;
93
- padding: 30px 10px 10px 10px;
94
- width: var(--dl-modal-width, 416px);
95
- margin: 50px auto;
96
- border-radius: var(--dl-radius, 4px);
97
- background-color: var(--dl-surface, #fff);
98
- box-shadow: 0 0 23px -2px rgba(0, 0, 0, 0.06);
302
+ box-sizing: border-box;
303
+ width: var(--dl-modal-width);
304
+ max-width: calc(100vw - 2rem);
305
+ margin: 3rem auto;
306
+ padding: var(--dl-modal-padding);
307
+ border: 1px solid var(--dl-line-color);
308
+ border-radius: var(--dl-radius-lg);
309
+ background: var(--dl-surface);
310
+ box-shadow: var(--dl-shadow-modal);
311
+ animation: dl-rise 180ms cubic-bezier(0.2, 0.8, 0.3, 1) both;
99
312
  }
100
313
 
101
314
  .dl-modal.noModalDialog .modal {
102
- box-shadow: none;
103
- border-radius: 0;
104
315
  width: auto;
105
- padding-top: 0;
316
+ max-width: none;
317
+ margin: 0;
318
+ padding: 0;
319
+ border: none;
320
+ border-radius: 0;
321
+ background: transparent;
322
+ box-shadow: none;
323
+ animation: none;
106
324
  }
107
325
 
108
326
  .dl-modal .largeModal {
109
- width: var(--dl-large-modal-width, 800px);
327
+ width: var(--dl-large-modal-width);
110
328
  }
111
329
 
112
- .dl-modal .largeModal .dl-form label {
330
+ /* The classic stylesheet pins label and control widths inside a large modal; here
331
+ everything is fluid, so these only need to stop inheriting a fixed width. */
332
+ .dl-modal .largeModal .dl-form label,
333
+ .largeModal .dl-form form .render {
113
334
  width: auto;
335
+ max-width: none;
114
336
  }
115
337
 
116
- .largeModal .dl-form form > .dl-form-field-wrapper > input,
117
- .largeModal .dl-form form > .dl-form-field-wrapper > textarea,
118
- .largeModal .dl-form form .render {
119
- width: var(--dl-large-modal-width, 800px);
120
- max-width: var(--dl-large-modal-width, 800px);
121
- min-width: var(--dl-large-modal-width, 800px);
338
+ @keyframes dl-fade {
339
+ from {
340
+ opacity: 0;
341
+ }
122
342
  }
123
343
 
124
- .dl-modal .low-bar {
125
- margin: 40px -10px -10px -10px;
126
- height: 45px;
127
- background-color: var(--dl-surface-muted, #f8f8f8);
128
- border-bottom-left-radius: var(--dl-radius, 4px);
129
- border-bottom-right-radius: var(--dl-radius, 4px);
344
+ @keyframes dl-rise {
345
+ from {
346
+ opacity: 0;
347
+ transform: translateY(8px) scale(0.985);
348
+ }
130
349
  }
131
350
 
132
- .dl-modal.dl-full-height .low-bar {
133
- bottom: 11px;
134
- width: 100%;
135
- position: absolute;
351
+ @media (prefers-reduced-motion: reduce) {
352
+ .dl-modal,
353
+ .dl-modal .modal {
354
+ animation: none;
355
+ }
136
356
  }
137
357
 
358
+ /* ── header ─────────────────────────────────────────────────────────────── */
359
+
138
360
  .dl-modal .up-bar {
139
- margin: -20px 0 -10px -50px;
361
+ display: flex;
362
+ justify-content: flex-end;
363
+ margin: 0 0 0.25rem;
364
+ min-height: 1.5rem;
365
+ }
366
+
367
+ .cancelBtn {
368
+ position: relative;
369
+ width: 1.75rem;
370
+ height: 1.75rem;
371
+ padding: 0;
372
+ border: none;
373
+ border-radius: var(--dl-radius-sm);
374
+ background: transparent;
375
+ color: var(--dl-text-muted);
376
+ cursor: pointer;
377
+ transition:
378
+ background var(--dl-transition),
379
+ color var(--dl-transition);
380
+ }
381
+
382
+ .cancelBtn:hover {
383
+ background: var(--dl-surface-sunken);
384
+ color: var(--dl-text-color);
140
385
  }
141
386
 
142
- /* -------------------------------------------------------------------- tabs */
387
+ .cancelBtn:focus-visible {
388
+ outline: 2px solid var(--dl-accent);
389
+ outline-offset: 2px;
390
+ }
391
+
392
+ /* The glyph is two bars; the element itself is not rotated, so the hit area
393
+ and the focus ring stay square. */
394
+ .cancelBtn:before,
395
+ .cancelBtn:after {
396
+ content: '';
397
+ position: absolute;
398
+ top: 50%;
399
+ left: 50%;
400
+ width: 0.875rem;
401
+ height: 1.5px;
402
+ border-radius: 1px;
403
+ background: currentColor;
404
+ }
405
+
406
+ .cancelBtn:before {
407
+ transform: translate(-50%, -50%) rotate(45deg);
408
+ }
409
+
410
+ .cancelBtn:after {
411
+ transform: translate(-50%, -50%) rotate(-45deg);
412
+ }
413
+
414
+ /* ── tabs ───────────────────────────────────────────────────────────────── */
143
415
 
144
416
  .dl-modal .tabWrapper {
145
- text-align: center;
417
+ display: flex;
418
+ flex-wrap: wrap;
419
+ gap: 0.125rem;
420
+ margin-bottom: 1.25rem;
421
+ padding: 0.25rem;
422
+ border-radius: var(--dl-radius);
423
+ background: var(--dl-surface-muted);
424
+ text-align: left;
425
+ }
426
+
427
+ .dl-modal .tabWrapper:empty {
428
+ display: none;
146
429
  }
147
430
 
148
431
  .dl-modal .dl-tab-btn {
149
- border: 1px solid var(--dl-accent, #1ea6a3);
150
- border-left: none;
151
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
152
- font-weight: lighter;
153
- font-size: var(--dl-font-size, 0.9em);
154
- padding: 6px 8px 4px 8px;
155
- display: inline-block;
156
- color: var(--dl-accent, #1ea6a3);
432
+ flex: 1 1 auto;
433
+ padding: 0.4rem 0.75rem;
434
+ border: none;
435
+ border-radius: var(--dl-radius-sm);
436
+ background: transparent;
437
+ color: var(--dl-text-muted);
438
+ font-family: var(--dl-font-family);
439
+ font-size: var(--dl-font-size-sm);
440
+ font-weight: 500;
441
+ text-align: center;
442
+ white-space: nowrap;
157
443
  cursor: pointer;
158
- margin-top: 20px;
159
- margin-bottom: 5px;
444
+ transition:
445
+ background var(--dl-transition),
446
+ color var(--dl-transition);
160
447
  }
161
448
 
162
- .dl-modal .dl-tab-btn.active {
163
- color: var(--dl-surface, #fff);
164
- background: var(--dl-accent, #1ea6a3);
165
- cursor: default;
449
+ .dl-modal .dl-tab-btn:hover {
450
+ color: var(--dl-text-color);
166
451
  }
167
452
 
168
- .dl-modal .dl-tab-btn:first-child {
169
- border-left: 1px solid var(--dl-accent, #1ea6a3);
170
- border-top-left-radius: var(--dl-radius, 4px);
171
- border-bottom-left-radius: var(--dl-radius, 4px);
453
+ .dl-modal .dl-tab-btn.active {
454
+ background: var(--dl-surface);
455
+ color: var(--dl-accent);
456
+ box-shadow: var(--dl-shadow-sm);
457
+ cursor: default;
172
458
  }
173
459
 
460
+ /* Kept so the segmented look survives the classic stylesheet's first/last rules. */
461
+ .dl-modal .dl-tab-btn:first-child,
174
462
  .dl-modal .dl-tab-btn:last-child {
175
- border-top-right-radius: var(--dl-radius, 4px);
176
- border-bottom-right-radius: var(--dl-radius, 4px);
463
+ border-radius: var(--dl-radius-sm);
177
464
  }
178
465
 
179
- /* ----------------------------------------------------------------- buttons */
466
+ /* ── footer ─────────────────────────────────────────────────────────────── */
180
467
 
181
468
  /*
182
- * v2 renders these as <button> rather than <div> so they are focusable and
183
- * keyboard-operable. The first three declarations neutralise the UA button
184
- * styles that <div> did not have, keeping the rendering identical to v1.
469
+ * `row-reverse` reproduces the classic stylesheet's `float: right`: the first button
470
+ * declared is the rightmost one. Consumers rely on that order.
185
471
  */
472
+ .dl-modal .low-bar {
473
+ display: flex;
474
+ flex-direction: row-reverse;
475
+ justify-content: flex-start;
476
+ gap: 0.5rem;
477
+ height: auto;
478
+ margin: 1.5rem calc(var(--dl-modal-padding) * -1) calc(var(--dl-modal-padding) * -1);
479
+ padding: 1rem var(--dl-modal-padding);
480
+ border-top: 1px solid var(--dl-line-color);
481
+ border-radius: 0 0 var(--dl-radius-lg) var(--dl-radius-lg);
482
+ background: var(--dl-surface-muted);
483
+ }
484
+
485
+ .dl-modal.noModalDialog .low-bar {
486
+ margin: 1.25rem 0 0;
487
+ padding: 0;
488
+ border-top: none;
489
+ background: transparent;
490
+ }
491
+
492
+ .dl-modal.dl-full-height .low-bar {
493
+ position: absolute;
494
+ bottom: 0;
495
+ width: 100%;
496
+ }
497
+
186
498
  .dl-modal .btn {
187
- font-size: inherit;
188
- line-height: normal;
499
+ flex: 0 0 auto;
500
+ padding: 0.5rem 1rem;
501
+ border: 1px solid var(--dl-accent);
502
+ border-radius: var(--dl-radius-sm);
503
+ background: var(--dl-accent);
504
+ color: var(--dl-accent-contrast);
505
+ font-family: var(--dl-font-family);
506
+ font-size: var(--dl-font-size-sm);
507
+ font-weight: 550;
508
+ line-height: 1.4;
189
509
  text-align: center;
190
- float: right;
191
- padding: 5px 10px 5px 10px;
192
- margin-top: 6px;
193
- margin-right: 10px;
194
- border: 2px solid var(--dl-accent, #1ea6a3);
195
- border-radius: var(--dl-radius, 4px);
196
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
197
- color: var(--dl-accent, #1ea6a3);
198
- background-color: transparent;
199
510
  cursor: pointer;
511
+ transition:
512
+ background var(--dl-transition),
513
+ border-color var(--dl-transition),
514
+ box-shadow var(--dl-transition),
515
+ opacity var(--dl-transition);
200
516
  }
201
517
 
202
518
  .dl-modal .btn:hover {
203
- border: 2px solid var(--dl-accent-hover, #22bb8b);
204
- box-shadow: 0 0 19px -1px rgba(34, 187, 139, 0.1);
519
+ border-color: var(--dl-accent-hover);
520
+ background: var(--dl-accent-hover);
521
+ box-shadow: none;
522
+ }
523
+
524
+ .dl-modal .btn:focus-visible {
525
+ outline: none;
526
+ box-shadow: 0 0 0 3px var(--dl-accent-ring);
527
+ }
528
+
529
+ /* A quieter companion for cancel and back. */
530
+ .dl-modal .btn.secondary {
531
+ border-color: var(--dl-line-strong);
532
+ background: transparent;
533
+ color: var(--dl-label-color);
534
+ }
535
+
536
+ .dl-modal .btn.secondary:hover {
537
+ border-color: var(--dl-line-strong);
538
+ background: var(--dl-surface-sunken);
539
+ color: var(--dl-text-color);
205
540
  }
206
541
 
207
542
  .dl-modal .btn.disabled {
208
- opacity: 0.5;
209
- cursor: default;
543
+ opacity: 0.45;
544
+ cursor: not-allowed;
210
545
  }
211
546
 
212
547
  .dl-modal .btn.disabled:hover {
213
- border: 2px solid var(--dl-accent, #1ea6a3);
548
+ border-color: var(--dl-accent);
549
+ background: var(--dl-accent);
214
550
  box-shadow: none;
215
551
  }
216
552
 
553
+ .dl-modal .btn.secondary.disabled:hover {
554
+ border-color: var(--dl-line-strong);
555
+ background: transparent;
556
+ }
557
+
217
558
  .dl-modal .btn.invisible {
218
559
  display: none;
219
560
  }
220
561
 
221
562
  .dl-modal .btn.loading-btn {
222
- cursor: default;
563
+ cursor: progress;
223
564
  }
224
565
 
225
566
  .dl-modal .btn.loading-btn::after {
226
- content: ' ';
567
+ content: '';
227
568
  display: inline-block;
228
- margin-left: 6px;
229
- margin-bottom: -4px;
230
- border: 2px solid #d1d0d8;
231
- border-top: 2px solid var(--dl-accent, #1ea6a3);
569
+ width: 0.75rem;
570
+ height: 0.75rem;
571
+ margin-left: 0.5rem;
572
+ margin-bottom: -1px;
573
+ border: 2px solid currentColor;
574
+ border-top-color: transparent;
232
575
  border-radius: 50% !important;
233
- width: 16px;
234
- height: 16px;
235
576
  padding: 0 !important;
236
- animation: loading-icon-spin 1s linear infinite;
577
+ animation: loading-icon-spin 700ms linear infinite;
237
578
  }
238
579
 
239
- /* Also a <button> in v2; reset the UA chrome so the ✕ glyph is all that shows. */
240
- .cancelBtn {
241
- float: right;
242
- width: 12px;
243
- height: 16px;
244
- padding: 0;
245
- border: none;
246
- background: transparent;
247
- position: relative;
248
- transform: rotate(45deg);
249
- opacity: 0.3;
250
- cursor: pointer;
251
- }
252
-
253
- .cancelBtn:hover {
254
- opacity: 0.6;
255
- }
256
-
257
- .cancelBtn:before,
258
- .cancelBtn:after {
259
- content: '';
260
- position: absolute;
261
- z-index: -1;
262
- background: currentColor;
263
- }
264
-
265
- .cancelBtn:before {
266
- left: 6px;
267
- width: 2px;
268
- margin-left: -1px;
269
- height: 12px;
270
- }
271
-
272
- .cancelBtn:after {
273
- top: 6px;
274
- height: 2px;
275
- margin-top: -1px;
276
- width: 12px;
580
+ @keyframes loading-icon-spin {
581
+ to {
582
+ transform: rotate(360deg);
583
+ }
277
584
  }
278
585
 
279
- /* -------------------------------------------------------------------- form */
586
+ /* ════════════════════════════════════════════════════════════════ form ══ */
280
587
 
281
588
  .dl-form {
282
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
589
+ font-family: var(--dl-font-family);
590
+ font-size: var(--dl-font-size);
591
+ line-height: var(--dl-line-height);
592
+ color: var(--dl-text-color);
283
593
  }
284
594
 
285
595
  .dl-form label {
286
596
  display: block;
287
- width: 409px;
288
- margin-bottom: 7px;
289
- margin-left: 2px;
290
- margin-top: 25px;
291
- font-size: var(--dl-font-size, 0.9em);
292
- color: var(--dl-label-color, #58565c);
293
- font-weight: 500;
597
+ width: auto;
598
+ margin: 0 0 0.375rem;
599
+ color: var(--dl-label-color);
600
+ font-size: var(--dl-font-size-sm);
601
+ font-weight: 550;
294
602
  }
295
603
 
296
- .dl-form .withoutLabel {
604
+ .dl-form form > .dl-form-field-wrapper {
297
605
  position: relative;
298
- margin-top: 9px;
606
+ margin-bottom: var(--dl-gap);
299
607
  }
300
608
 
301
- .dl-form form > .dl-form-field-wrapper {
609
+ .dl-form form > .dl-form-field-wrapper:last-child {
610
+ margin-bottom: 0;
611
+ }
612
+
613
+ .dl-form .withoutLabel {
302
614
  position: relative;
303
615
  }
304
616
 
@@ -309,432 +621,675 @@
309
621
  }
310
622
 
311
623
  .dl-form form > .dl-form-field-wrapper.dl-select-wrapper {
312
- margin-bottom: -4px;
624
+ margin-bottom: var(--dl-gap);
313
625
  }
314
626
 
627
+ /* ── text inputs ────────────────────────────────────────────────────────── */
628
+
315
629
  .dl-form form > .dl-form-field-wrapper > input,
316
- .dl-form form > .dl-form-field-wrapper > textarea {
317
- outline-width: 0;
318
- border: 2px solid var(--dl-line-color, #ddd);
319
- border-radius: var(--dl-radius, 4px);
320
- width: var(--dl-field-width, 400px);
321
- max-width: var(--dl-field-width, 400px);
322
- min-width: var(--dl-field-width, 400px);
323
- padding: 6px;
324
- font-size: var(--dl-font-size, 0.9em);
325
- font-weight: 300;
326
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
327
- box-sizing: content-box;
630
+ .dl-form form > .dl-form-field-wrapper > textarea,
631
+ .dl-form form > .dl-form-field-wrapper > div > input[type='file'] {
632
+ box-sizing: border-box;
633
+ width: var(--dl-field-width);
634
+ min-width: 0;
635
+ max-width: 100%;
636
+ padding: var(--dl-control-padding-y) var(--dl-control-padding-x);
637
+ border: 1px solid var(--dl-line-color);
638
+ border-radius: var(--dl-radius-sm);
639
+ background: var(--dl-surface-raised);
640
+ color: var(--dl-text-color);
641
+ font-family: var(--dl-font-family);
642
+ font-size: var(--dl-font-size);
643
+ font-weight: 400;
644
+ line-height: var(--dl-line-height);
645
+ outline: none;
646
+ transition:
647
+ border-color var(--dl-transition),
648
+ box-shadow var(--dl-transition);
649
+ }
650
+
651
+ .dl-form form > .dl-form-field-wrapper > input::placeholder,
652
+ .dl-form form > .dl-form-field-wrapper > textarea::placeholder {
653
+ color: var(--dl-text-muted);
654
+ }
655
+
656
+ .dl-form form > .dl-form-field-wrapper > input:hover,
657
+ .dl-form form > .dl-form-field-wrapper > textarea:hover {
658
+ border-color: var(--dl-line-strong);
328
659
  }
329
660
 
330
661
  .dl-form form > .dl-form-field-wrapper > input:focus,
331
662
  .dl-form form > .dl-form-field-wrapper > textarea:focus {
332
- border: 2px solid var(--dl-focused-line-color, #bbb);
663
+ border-color: var(--dl-accent);
664
+ box-shadow: 0 0 0 3px var(--dl-accent-ring);
333
665
  }
334
666
 
335
667
  .dl-form form > .dl-form-field-wrapper > textarea {
336
- min-height: 200px;
668
+ min-height: 7rem;
669
+ resize: vertical;
337
670
  }
338
671
 
339
672
  .dl-form form > .dl-form-field-wrapper > input.dl-tooltip-inside {
340
- width: 369px;
341
- max-width: 369px;
342
- min-width: 369px;
343
- padding-right: 37px;
344
- box-sizing: content-box;
673
+ width: var(--dl-field-width);
674
+ max-width: 100%;
675
+ min-width: 0;
676
+ padding-right: 2.5rem;
345
677
  }
346
678
 
347
679
  .dl-form form > p {
348
- border: none;
349
- max-width: 360px;
350
- min-width: 360px;
351
- padding: 6px;
352
- padding-top: 20px;
353
- line-height: 150%;
354
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
680
+ max-width: none;
681
+ min-width: 0;
682
+ margin: 0;
683
+ padding: 0;
684
+ color: var(--dl-text-muted);
685
+ font-family: var(--dl-font-family);
686
+ font-size: var(--dl-font-size-sm);
687
+ line-height: 1.6;
355
688
  }
356
689
 
357
- /* ---------------------------------------------------------------- checkbox */
690
+ /* ── checkbox ───────────────────────────────────────────────────────────── */
358
691
 
359
692
  .dl-form form .check {
360
693
  display: flex;
361
- margin-top: 8px;
694
+ align-items: flex-start;
695
+ gap: 0.625rem;
696
+ margin-top: 0;
362
697
  }
363
698
 
364
- .dl-form form .check label {
365
- display: inline;
366
- font-weight: 100;
367
- margin-top: 0;
368
- margin-left: 4px;
699
+ /*
700
+ * The classic stylesheet hides the input and paints a pseudo-element, which takes
701
+ * the control out of the tab order and out of the accessibility tree. Styling
702
+ * the input directly with `appearance: none` keeps it focusable and
703
+ * announceable. See docs/accessibility.md.
704
+ */
705
+ .dl-form form .check input,
706
+ .dl-form form input[type='checkbox'] {
707
+ flex: 0 0 auto;
708
+ appearance: none;
709
+ -webkit-appearance: none;
710
+ visibility: visible;
711
+ width: 1.125rem;
712
+ height: 1.125rem;
713
+ margin: 0.125rem 0 0;
714
+ border: 1px solid var(--dl-line-strong);
715
+ border-radius: var(--dl-radius-sm);
716
+ background: var(--dl-surface-raised);
717
+ cursor: pointer;
718
+ transition:
719
+ background var(--dl-transition),
720
+ border-color var(--dl-transition),
721
+ box-shadow var(--dl-transition);
369
722
  }
370
723
 
371
- .dl-form form .check input {
372
- visibility: hidden;
373
- margin: 0 12px 0 0;
724
+ .dl-form form input[type='checkbox']:hover {
725
+ border-color: var(--dl-accent);
374
726
  }
375
727
 
376
- .dl-form form input[type='checkbox']:before {
377
- visibility: visible;
378
- content: '';
379
- display: inline-block;
380
- top: -3px;
381
- width: 20px;
382
- height: 20px;
383
- border-radius: 5px;
384
- position: relative;
385
- border: 1px solid #828282;
386
- background-color: #f4f4f4;
387
- background-image: none;
388
- background-size: 1rem;
389
- background-position: center center;
728
+ .dl-form form input[type='checkbox']:focus-visible {
729
+ outline: none;
730
+ border-color: var(--dl-accent);
731
+ box-shadow: 0 0 0 3px var(--dl-accent-ring);
732
+ }
733
+
734
+ .dl-form form input[type='checkbox']:checked {
735
+ border-color: var(--dl-accent);
736
+ background-color: var(--dl-accent);
737
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.5 3.5L13 4.5'/%3E%3C/svg%3E");
738
+ background-size: 0.875rem;
739
+ background-position: center;
390
740
  background-repeat: no-repeat;
391
- transition:
392
- border 0.25s ease-out,
393
- background 0.25s ease-out;
394
741
  }
395
742
 
743
+ /* The pseudo-element box of the classic stylesheet must not reappear here. */
744
+ .dl-form form input[type='checkbox']:before,
396
745
  .dl-form form input[type='checkbox']:checked:before {
397
- border: 0.0625rem solid var(--dl-accent, #1ea6a3);
398
- background-color: var(--dl-accent, #1ea6a3);
399
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2096%2096%22%20fill%3D%22%23fff%22%3E%3Cpath%20d%3D%22M33.8%2081.1c-1.3%200-2.5-.5-3.3-1.4L2.1%2051.3c-1.8-1.8-1.8-4.8%200-6.7%201.8-1.8%204.8-1.8%206.7%200l25.1%2025.1%2053.5-53.5c1.8-1.8%204.8-1.8%206.7%200%201.8%201.8%201.8%204.8%200%206.7l-57%2056.8c-.8.9-2%201.4-3.3%201.4z%22%2F%3E%3C%2Fsvg%3E);
746
+ content: none;
747
+ }
748
+
749
+ .dl-form form .check label {
750
+ display: inline;
751
+ margin: 0;
752
+ color: var(--dl-text-color);
753
+ font-size: var(--dl-font-size);
754
+ font-weight: 400;
755
+ cursor: pointer;
756
+ }
757
+
758
+ .dl-form form .check label a {
759
+ color: var(--dl-accent);
760
+ text-underline-offset: 2px;
400
761
  }
401
762
 
402
- /* ------------------------------------------------------------------- cards */
763
+ /* ── cards ──────────────────────────────────────────────────────────────── */
403
764
 
404
765
  .dl-form form .detailed-options {
405
- display: flex;
406
- flex-wrap: wrap;
407
- margin-top: 20px;
766
+ display: grid;
767
+ grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
768
+ gap: 0.625rem;
769
+ margin-top: 0;
408
770
  }
409
771
 
410
772
  .dl-form form .detailed-option {
411
- background: var(--dl-surface-muted, #f8f8f8);
412
- border: 2px solid #dedddd;
773
+ width: auto;
774
+ margin: 0;
775
+ padding: 0.875rem;
776
+ border: 1px solid var(--dl-line-color);
777
+ border-radius: var(--dl-radius);
778
+ background: var(--dl-surface-raised);
779
+ color: var(--dl-text-color);
780
+ font-size: var(--dl-font-size-sm);
781
+ line-height: 1.5;
413
782
  cursor: pointer;
414
- margin: 5px;
415
- padding: 10px;
416
- border-radius: var(--dl-radius, 4px);
417
- width: 232px;
783
+ transition:
784
+ border-color var(--dl-transition),
785
+ background var(--dl-transition),
786
+ box-shadow var(--dl-transition);
787
+ }
788
+
789
+ .dl-form form .detailed-option:hover {
790
+ border-color: var(--dl-line-strong);
791
+ box-shadow: var(--dl-shadow-sm);
418
792
  }
419
793
 
420
794
  .dl-form form .detailed-option.active {
421
- border: 2px solid var(--dl-accent, #1ea6a3);
795
+ border-color: var(--dl-accent);
796
+ background: var(--dl-accent-soft);
797
+ box-shadow: 0 0 0 1px var(--dl-accent) inset;
422
798
  }
423
799
 
424
- /* -------------------------------------------------------- custom + arrays */
800
+ /* ── custom render + arrays ─────────────────────────────────────────────── */
425
801
 
426
802
  .dl-form form .render,
427
803
  .dl-form form .array-of {
428
- width: var(--dl-field-width, 400px);
429
- max-width: var(--dl-field-width, 400px);
430
- min-width: var(--dl-field-width, 400px);
431
- padding: 6px;
432
- font-size: var(--dl-font-size, 0.9em);
433
- font-weight: 300;
434
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
435
- text-align: center;
804
+ width: auto;
805
+ min-width: 0;
806
+ max-width: none;
807
+ padding: 0;
808
+ font-family: var(--dl-font-family);
809
+ font-size: var(--dl-font-size);
810
+ font-weight: 400;
811
+ text-align: left;
436
812
  }
437
813
 
438
- .largeModal .dl-form form .render,
439
- .dl-form form .array-of {
440
- width: auto;
441
- max-width: initial;
442
- min-width: auto;
814
+ .dl-form-array-suggested-container {
815
+ display: grid;
816
+ gap: 0.375rem;
817
+ margin-bottom: 0.625rem;
818
+ }
819
+
820
+ .dl-form-array-of-suggestion {
821
+ display: flex;
822
+ align-items: flex-start;
823
+ gap: 0.625rem;
824
+ min-height: 0;
825
+ margin-top: 0 !important;
826
+ padding: 0.625rem 0.75rem;
827
+ border: 1px dashed var(--dl-line-strong);
828
+ border-radius: var(--dl-radius-sm);
829
+ background: transparent;
830
+ text-align: left;
831
+ }
832
+
833
+ .dl-form-array-of-suggestion label {
834
+ margin: 0;
835
+ color: var(--dl-text-muted);
836
+ font-size: var(--dl-font-size-sm);
837
+ font-weight: 400;
838
+ text-align: left;
443
839
  }
444
840
 
445
841
  .dl-form-array-of-entry {
842
+ display: flex;
843
+ align-items: center;
844
+ gap: 0.5rem;
845
+ min-height: 0;
846
+ margin-top: 0;
847
+ margin-bottom: 0.375rem;
848
+ padding: 0.5rem 0.5rem 0.5rem 0.75rem;
849
+ border: 1px solid var(--dl-line-color);
850
+ border-radius: var(--dl-radius-sm);
851
+ background: var(--dl-surface-muted);
446
852
  text-align: left;
447
- background-color: var(--dl-surface-muted, #f8f8f8);
448
- padding: 8px;
449
- border-radius: var(--dl-radius, 4px);
450
- border: 1px solid var(--dl-border-muted, #e7e6e6);
451
- margin-top: 4px;
452
- min-height: 17px;
453
853
  }
454
854
 
455
855
  .dl-form-array-of-entry span {
456
- width: 275px;
457
- display: inline-block;
856
+ flex: 1 1 auto;
857
+ width: auto;
858
+ display: block;
458
859
  overflow: hidden;
860
+ color: var(--dl-text-color);
861
+ font-size: var(--dl-font-size-sm);
862
+ text-overflow: ellipsis;
863
+ white-space: nowrap;
459
864
  }
460
865
 
461
866
  .dl-form-array-of-entry button {
462
- float: right;
463
- margin-top: -1px;
464
- border: 1px solid color-mix(in srgb, var(--dl-danger, #fe070b) 35%, transparent);
465
- color: color-mix(in srgb, var(--dl-danger, #fe070b) 62%, transparent);
466
- border-radius: var(--dl-radius, 4px);
867
+ flex: 0 0 auto;
868
+ float: none;
869
+ margin: 0;
870
+ padding: 0.25rem 0.5rem;
871
+ border: 1px solid transparent;
872
+ border-radius: var(--dl-radius-sm);
467
873
  background: transparent;
874
+ color: var(--dl-danger);
875
+ font-family: var(--dl-font-family);
876
+ font-size: var(--dl-font-size-sm);
468
877
  cursor: pointer;
878
+ transition:
879
+ background var(--dl-transition),
880
+ border-color var(--dl-transition);
881
+ }
882
+
883
+ .dl-form-array-of-entry button:hover {
884
+ background: var(--dl-danger-soft);
469
885
  }
470
886
 
471
887
  .dl-form-array-of-entry button.edit-array-of-btn {
472
- border: 1px solid var(--dl-accent, #1ea6a3);
473
- color: var(--dl-accent, #1ea6a3);
474
- margin-left: 3px;
888
+ margin-left: 0;
889
+ border-color: transparent;
890
+ color: var(--dl-accent);
891
+ }
892
+
893
+ .dl-form-array-of-entry button.edit-array-of-btn:hover {
894
+ background: var(--dl-accent-soft);
895
+ }
896
+
897
+ .dl-form-array-of-entry button:focus-visible {
898
+ outline: none;
899
+ border-color: currentColor;
900
+ box-shadow: 0 0 0 3px var(--dl-accent-ring);
475
901
  }
476
902
 
477
903
  .dl-form-array-of-add-entry {
478
- float: right;
904
+ float: none;
479
905
  width: 100%;
480
- border: 1px solid var(--dl-border-muted, #e7e6e6);
481
- border-radius: var(--dl-radius, 4px);
482
- color: var(--dl-accent, #1ea6a3);
483
- background: var(--dl-surface-muted, #f8f8f8);
484
- cursor: pointer;
485
- padding: 8px;
486
- margin-top: 4px;
906
+ margin-top: 0.5rem;
907
+ padding: 0.625rem;
908
+ border: 1px dashed var(--dl-line-strong);
909
+ border-radius: var(--dl-radius-sm);
910
+ background: transparent;
911
+ color: var(--dl-accent);
912
+ font-family: var(--dl-font-family);
913
+ font-size: var(--dl-font-size-sm);
914
+ font-weight: 550;
487
915
  outline: none;
488
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
489
- font-size: 1.05em;
916
+ cursor: pointer;
917
+ transition:
918
+ background var(--dl-transition),
919
+ border-color var(--dl-transition);
490
920
  }
491
921
 
492
- .dl-form-array-of-suggestion {
493
- text-align: left;
494
- background-color: var(--dl-surface-muted, #f8f8f8);
495
- padding: 8px 8px 3px 8px;
496
- border-radius: var(--dl-radius, 4px);
497
- border: 1px solid var(--dl-border-muted, #e7e6e6);
498
- margin-top: 4px !important;
499
- min-height: 17px;
922
+ .dl-form-array-of-add-entry:hover {
923
+ border-color: var(--dl-accent);
924
+ background: var(--dl-accent-soft);
500
925
  }
501
926
 
502
- .dl-form-array-of-suggestion label {
503
- text-align: left;
927
+ .dl-form-array-of-add-entry:focus-visible {
928
+ border-color: var(--dl-accent);
929
+ box-shadow: 0 0 0 3px var(--dl-accent-ring);
504
930
  }
505
931
 
506
- .dl-form-array-suggested-container {
507
- margin-bottom: 15px;
932
+ /* ── file ───────────────────────────────────────────────────────────────── */
933
+
934
+ .dl-form form > .dl-form-field-wrapper .file-field {
935
+ padding: 0.75rem;
936
+ border: 1px dashed var(--dl-line-strong);
937
+ border-radius: var(--dl-radius);
938
+ background: var(--dl-surface-muted);
508
939
  }
509
940
 
510
- /* ------------------------------------------------------------- multiselect */
941
+ .dl-form form > .dl-form-field-wrapper > div > input[type='file'] {
942
+ border: none;
943
+ background: transparent;
944
+ padding: 0;
945
+ font-size: var(--dl-font-size-sm);
946
+ color: var(--dl-text-muted);
947
+ }
948
+
949
+ .dl-form form > .dl-form-field-wrapper .file-field .file-preview {
950
+ height: auto;
951
+ margin: 0 0 0.625rem;
952
+ }
953
+
954
+ .dl-form form > .dl-form-field-wrapper .file-field .file-preview.empty {
955
+ height: 0;
956
+ margin: 0;
957
+ }
958
+
959
+ .dl-form form > .dl-form-field-wrapper .file-field .file-preview.loading {
960
+ display: inline-block;
961
+ width: 1rem;
962
+ height: 1rem;
963
+ margin: 0 0 0.625rem;
964
+ padding: 0 !important;
965
+ border: 2px solid var(--dl-line-strong);
966
+ border-top-color: var(--dl-accent);
967
+ border-radius: 50% !important;
968
+ animation: loading-icon-spin 700ms linear infinite;
969
+ }
970
+
971
+ .file-selection-container {
972
+ position: relative;
973
+ display: inline-flex;
974
+ }
975
+
976
+ .file-selection-container img {
977
+ max-height: 6rem;
978
+ border-radius: var(--dl-radius-sm);
979
+ }
980
+
981
+ .file-selection-delete-btn {
982
+ position: absolute;
983
+ top: -0.4rem;
984
+ right: -0.4rem;
985
+ display: grid;
986
+ place-items: center;
987
+ width: 1.375rem;
988
+ height: 1.375rem;
989
+ padding: 0;
990
+ border: none;
991
+ border-radius: var(--dl-radius-pill);
992
+ background: var(--dl-danger);
993
+ box-shadow: var(--dl-shadow-sm);
994
+ cursor: pointer;
995
+ }
996
+
997
+ .file-selection-delete-btn-icon {
998
+ width: 0.625rem;
999
+ height: 0.625rem;
1000
+ background: #fff;
1001
+ clip-path: polygon(
1002
+ 20% 0%,
1003
+ 0% 20%,
1004
+ 30% 50%,
1005
+ 0% 80%,
1006
+ 20% 100%,
1007
+ 50% 70%,
1008
+ 80% 100%,
1009
+ 100% 80%,
1010
+ 70% 50%,
1011
+ 100% 20%,
1012
+ 80% 0%,
1013
+ 50% 30%
1014
+ );
1015
+ }
1016
+
1017
+ /* ── multi-select tags ──────────────────────────────────────────────────── */
511
1018
 
512
1019
  .multiselect-tag {
513
- display: flex;
514
- justify-content: space-between;
1020
+ display: inline-flex;
515
1021
  align-items: center;
516
- padding: 0 9px;
517
- margin: 2px;
518
- border-radius: 3px;
519
- background-color: var(--dl-surface-sunken, #eee);
1022
+ gap: 0.25rem;
1023
+ margin: 0.125rem;
1024
+ padding: 0.125rem 0.25rem 0.125rem 0.5rem;
1025
+ border-radius: var(--dl-radius-pill);
1026
+ background: var(--dl-accent-soft);
1027
+ color: var(--dl-text-color);
1028
+ font-size: var(--dl-font-size-sm);
520
1029
  }
521
1030
 
522
1031
  .multiselect-tag:last-child {
523
- margin-bottom: 6px;
1032
+ margin-bottom: 0.125rem;
524
1033
  }
525
1034
 
526
- /* The "muliselect" spelling is a v1 typo kept for compatibility. */
1035
+ /* The "muliselect" spelling is a frozen typo from v1. */
527
1036
  .dl-muliselect-selected-remove-container {
528
- margin: 9px 6px -5px 0;
1037
+ display: inline-flex;
1038
+ margin: 0;
529
1039
  }
530
1040
 
531
1041
  .dl-muliselect-selected-remove {
532
- display: inline-block;
533
- width: 12px;
534
- height: 35px;
535
1042
  position: relative;
536
- transform: rotate(45deg);
537
- opacity: 0.3;
1043
+ display: grid;
1044
+ place-items: center;
1045
+ width: 1rem;
1046
+ height: 1rem;
1047
+ margin: 0;
1048
+ border-radius: var(--dl-radius-pill);
1049
+ opacity: 0.55;
1050
+ transform: none;
538
1051
  cursor: pointer;
539
- margin-right: 3px;
1052
+ transition:
1053
+ opacity var(--dl-transition),
1054
+ background var(--dl-transition);
540
1055
  }
541
1056
 
542
1057
  .dl-muliselect-selected-remove:hover {
543
- opacity: 0.6;
1058
+ background: var(--dl-accent-soft);
1059
+ opacity: 1;
544
1060
  }
545
1061
 
546
1062
  .dl-muliselect-selected-remove:before,
547
1063
  .dl-muliselect-selected-remove:after {
548
1064
  content: '';
549
1065
  position: absolute;
550
- z-index: -1;
1066
+ top: 50%;
1067
+ left: 50%;
1068
+ width: 0.5rem;
1069
+ height: 1.5px;
1070
+ margin: 0;
1071
+ border-radius: 1px;
551
1072
  background: currentColor;
552
1073
  }
553
1074
 
554
1075
  .dl-muliselect-selected-remove:before {
555
- left: 6px;
556
- width: 2px;
557
- margin-left: -1px;
558
- height: 12px;
1076
+ transform: translate(-50%, -50%) rotate(45deg);
559
1077
  }
560
1078
 
561
1079
  .dl-muliselect-selected-remove:after {
562
- top: 6px;
563
- height: 2px;
564
- margin-top: -1px;
565
- width: 12px;
1080
+ transform: translate(-50%, -50%) rotate(-45deg);
566
1081
  }
567
1082
 
568
- /* -------------------------------------------------------------------- file */
1083
+ /* ── tooltips ───────────────────────────────────────────────────────────── */
569
1084
 
570
- .dl-form form > .dl-form-field-wrapper > div > input[type='file'] {
571
- outline-width: 0;
572
- width: var(--dl-field-width, 400px);
573
- max-width: var(--dl-field-width, 400px);
574
- min-width: var(--dl-field-width, 400px);
575
- padding: 6px;
576
- font-size: var(--dl-font-size, 0.9em);
577
- font-weight: 300;
578
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
579
- box-sizing: content-box;
1085
+ .dl-form .dl-tooltip {
1086
+ display: inline-grid;
1087
+ place-items: center;
1088
+ float: right;
1089
+ width: 1.125rem;
1090
+ height: 1.125rem;
1091
+ margin: 0;
1092
+ padding: 0;
1093
+ border-radius: var(--dl-radius-pill);
1094
+ background: var(--dl-tooltip-background);
1095
+ color: var(--dl-tooltip-color);
1096
+ font-size: 0.6875rem;
1097
+ font-weight: 600;
1098
+ line-height: 1;
1099
+ cursor: help;
580
1100
  }
581
1101
 
582
- .dl-form form > .dl-form-field-wrapper .file-field {
583
- padding: 5px;
584
- border: 2px solid var(--dl-line-color, #ddd);
585
- border-radius: var(--dl-radius, 4px);
1102
+ .dl-tooltip-in-input {
1103
+ position: absolute;
1104
+ right: 0.625rem;
1105
+ bottom: 0.625rem;
1106
+ float: none;
586
1107
  }
587
1108
 
588
- .dl-form form > .dl-form-field-wrapper .file-field .file-preview {
589
- height: 50px;
590
- margin: 5px 5px 16px 5px;
1109
+ .tooltip-success {
1110
+ padding: 0 !important;
1111
+ background-color: var(--dl-tooltip-success-background) !important;
1112
+ color: var(--dl-tooltip-success-color) !important;
591
1113
  }
592
1114
 
593
- .dl-form form > .dl-form-field-wrapper .file-field .file-preview.empty {
594
- height: 0;
595
- margin: 0;
1115
+ .tooltip-warning {
1116
+ padding: 0 !important;
1117
+ background-color: var(--dl-tooltip-warning-background) !important;
1118
+ color: var(--dl-tooltip-warning-color) !important;
596
1119
  }
597
1120
 
598
- .dl-form form > .dl-form-field-wrapper .file-field .file-preview.loading {
599
- display: inline-block;
600
- margin-left: 6px;
601
- margin-bottom: -4px;
602
- border: 2px solid #d1d0d8;
603
- border-top: 2px solid #8e8e8e;
604
- border-radius: 50% !important;
605
- width: 16px;
606
- height: 16px;
1121
+ .tooltip-error {
607
1122
  padding: 0 !important;
608
- animation: loading-icon-spin 1s linear infinite;
1123
+ background-color: var(--dl-tooltip-error-background) !important;
1124
+ color: var(--dl-tooltip-error-color) !important;
609
1125
  }
610
1126
 
611
- .file-selection-container {
612
- display: flex;
1127
+ .tooltip-loading {
1128
+ width: 1rem;
1129
+ height: 1rem;
1130
+ padding: 0 !important;
1131
+ border: 2px solid var(--dl-line-strong);
1132
+ border-top-color: var(--dl-accent);
1133
+ border-radius: 50% !important;
1134
+ background: transparent;
1135
+ animation: loading-icon-spin 700ms linear infinite;
613
1136
  }
614
1137
 
615
- .file-selection-delete-btn {
616
- width: 30px;
617
- height: 30px;
618
- padding: 0;
619
- border: none;
620
- cursor: pointer;
621
- background-color: var(--dl-danger, red);
1138
+ .dl-tooltip-bubble {
1139
+ position: absolute;
1140
+ z-index: 1100;
1141
+ max-width: min(20rem, calc(100vw - 2rem));
1142
+ padding: 0.4rem 0.625rem;
1143
+ border-radius: var(--dl-radius-sm);
1144
+ background: var(--dl-tooltip-bubble-background);
1145
+ color: var(--dl-tooltip-bubble-color);
1146
+ font-family: var(--dl-font-family);
1147
+ font-size: var(--dl-font-size-sm);
1148
+ font-weight: 400;
1149
+ line-height: 1.45;
1150
+ box-shadow: var(--dl-shadow-popup);
1151
+ pointer-events: none;
622
1152
  }
623
1153
 
624
- /* ---------------------------------------------------------------- tooltips */
1154
+ /* ══════════════════════════════════════════════════════════════ layout ══ */
625
1155
 
626
- .dl-form .dl-tooltip {
627
- padding: 1px 6px;
628
- background: var(--dl-tooltip-background, #e6e6e6);
629
- color: var(--dl-tooltip-color, #88858e);
630
- border-radius: 10px;
631
- float: right;
632
- margin-right: 3px;
1156
+ .left-side {
1157
+ float: left;
633
1158
  }
634
1159
 
635
- .dl-tooltip-in-input {
636
- position: absolute;
637
- right: 5px;
638
- bottom: 6px;
1160
+ .right-side {
1161
+ margin-left: 173px;
639
1162
  }
640
1163
 
641
- .tooltip-loading {
642
- border: 2px solid #d1d0d8;
643
- border-top: 2px solid var(--dl-tooltip-color, #88858e);
644
- border-radius: 50% !important;
645
- width: 16px;
646
- height: 16px;
647
- padding: 0 !important;
648
- animation: loading-icon-spin 1s linear infinite;
1164
+ .right-side input,
1165
+ .dl-field-two-third input {
1166
+ margin-left: 0;
1167
+ padding-top: var(--dl-control-padding-y) !important;
649
1168
  }
650
1169
 
651
- .tooltip-success {
652
- padding-left: 4px !important;
653
- padding-right: 4px !important;
654
- background-color: var(--dl-tooltip-success-background, #d1e7dd) !important;
655
- color: var(--dl-tooltip-success-color, #12b568) !important;
656
- }
1170
+ /* ════════════════════════════════════════════════════════════ combobox ══ */
657
1171
 
658
- .tooltip-warning {
659
- padding-left: 8px !important;
660
- padding-right: 8px !important;
661
- background-color: var(--dl-tooltip-warning-background, #ffecb5) !important;
662
- color: var(--dl-tooltip-warning-color, #664d03) !important;
1172
+ /*
1173
+ * `<dl-select>` injects its own structural CSS at runtime, which reads the
1174
+ * `--dl-*` tokens above — colours therefore need no rules here.
1175
+ *
1176
+ * The few geometry values it hardcodes are re-stated below. The doubled class
1177
+ * (`.a.a`) raises specificity just enough to win regardless of which
1178
+ * stylesheet the browser happens to see last, since the injected block is
1179
+ * added to <head> the first time a combobox connects.
1180
+ */
1181
+
1182
+ .dl-form dl-select,
1183
+ .dl-modal dl-select {
1184
+ --dl-select-input-width: 100%;
663
1185
  }
664
1186
 
665
- .tooltip-error {
666
- padding-left: 8px !important;
667
- padding-right: 8px !important;
668
- background-color: var(--dl-tooltip-error-background, #f8d7da) !important;
669
- color: var(--dl-tooltip-error-color, #842029) !important;
1187
+ .dl-form dl-select .input-wrapper,
1188
+ .dl-modal dl-select .input-wrapper {
1189
+ display: flex;
1190
+ align-items: center;
1191
+ box-sizing: border-box;
1192
+ width: 100%;
1193
+ border-width: 1px;
1194
+ border-radius: var(--dl-radius-sm);
1195
+ background: var(--dl-surface-raised);
1196
+ transition:
1197
+ border-color var(--dl-transition),
1198
+ box-shadow var(--dl-transition);
670
1199
  }
671
1200
 
672
- /*
673
- * The bubble drawn by NativeTooltipProvider. v1 used tippy.js and shipped its
674
- * stylesheet inline here; this replaces `.tippy-box` and `.tippy-arrow`.
675
- */
676
- .dl-tooltip-bubble {
677
- position: absolute;
678
- z-index: 1000;
679
- max-width: min(300px, calc(100vw - 20px));
680
- padding: 5px 9px;
681
- border-radius: var(--dl-radius, 4px);
682
- background: var(--dl-tooltip-bubble-background, #413e48);
683
- color: var(--dl-tooltip-bubble-color, #d1cfd8);
684
- font-family: var(--dl-font-family, 'Rubik', sans-serif);
685
- font-weight: lighter;
686
- font-size: 14px;
687
- line-height: 1.4;
688
- pointer-events: none;
1201
+ .dl-form dl-select .selected-container,
1202
+ .dl-modal dl-select .selected-container {
1203
+ display: contents;
689
1204
  }
690
1205
 
691
- /* --------------------------------------------------------------- utilities */
1206
+ .dl-form dl-select.dl-focused .input-wrapper,
1207
+ .dl-modal dl-select.dl-focused .input-wrapper {
1208
+ border-color: var(--dl-accent);
1209
+ box-shadow: 0 0 0 3px var(--dl-accent-ring);
1210
+ }
692
1211
 
693
- .dl-field-two-third input {
694
- width: 194px !important;
695
- min-width: 128px !important;
1212
+ .dl-form dl-select .input-wrapper input,
1213
+ .dl-modal dl-select .input-wrapper input {
1214
+ flex: 1 1 auto;
1215
+ float: none;
1216
+ box-sizing: border-box;
1217
+ width: auto;
1218
+ min-width: 4rem;
1219
+ margin: 0;
1220
+ padding: var(--dl-control-padding-y) var(--dl-control-padding-x);
1221
+ font-size: var(--dl-font-size);
1222
+ font-weight: 400;
696
1223
  }
697
1224
 
698
- .left-side {
699
- float: left;
1225
+ .dl-form dl-select .input-wrapper svg,
1226
+ .dl-modal dl-select .input-wrapper svg {
1227
+ flex: 0 0 auto;
1228
+ float: none;
1229
+ margin: 0 0.5rem 0 0;
1230
+ padding: 0;
1231
+ border-left: none !important;
1232
+ fill: var(--dl-text-muted);
700
1233
  }
701
1234
 
702
- .right-side {
703
- margin-left: 173px;
1235
+ .dl-form dl-select.dl-focused .input-wrapper svg,
1236
+ .dl-modal dl-select.dl-focused .input-wrapper svg {
1237
+ border-left: none !important;
1238
+ fill: var(--dl-accent);
704
1239
  }
705
1240
 
706
- .right-side input {
707
- margin-left: 3px;
708
- padding-top: 8px !important;
1241
+ .dl-form dl-select.dl-select-loading .input-wrapper,
1242
+ .dl-modal dl-select.dl-select-loading .input-wrapper {
1243
+ width: 100%;
1244
+ border-radius: var(--dl-radius-sm);
1245
+ }
1246
+
1247
+ /* The popup is portalled to <body>, so it cannot be scoped to `.dl-form`. */
1248
+ .options-wrapper.options-wrapper {
1249
+ box-sizing: border-box;
1250
+ /*
1251
+ * It is a sibling of `.dl-modal`, which this theme raises to z-index 1000 —
1252
+ * the component's own `z-index: 100` would leave the option list behind the
1253
+ * backdrop. The classic stylesheet gives the dialog no z-index at all, so it
1254
+ * never had this problem.
1255
+ */
1256
+ z-index: 1100;
1257
+ padding: 0.25rem;
1258
+ border: 1px solid var(--dl-line-color);
1259
+ border-radius: var(--dl-radius);
1260
+ box-shadow: var(--dl-shadow-popup);
1261
+ max-height: 16rem;
1262
+ }
1263
+
1264
+ .options-wrapper.options-wrapper dl-option {
1265
+ border: none;
1266
+ border-radius: var(--dl-radius-sm);
1267
+ font-size: var(--dl-font-size-sm);
709
1268
  }
710
1269
 
711
- @keyframes loading-icon-spin {
712
- 0% {
713
- transform: rotate(0deg);
714
- }
715
- 100% {
716
- transform: rotate(360deg);
717
- }
1270
+ .options-wrapper.options-wrapper dl-option:hover,
1271
+ .options-wrapper.options-wrapper dl-option.dl-focused {
1272
+ color: var(--dl-accent);
718
1273
  }
719
1274
 
720
- /* -------------------------------------------------------------- dark theme */
1275
+ .options-wrapper.options-wrapper dl-option[selected='true'] {
1276
+ opacity: 0.45;
1277
+ }
721
1278
 
722
- /*
723
- * Opt in by adding `dark-theme` to <body>, or copy these declarations under
724
- * your own `@media (prefers-color-scheme: dark)` block. v1 had a single ad-hoc
725
- * `body.dark-theme dl-select` rule; this covers the whole surface.
726
- */
727
- body.dark-theme {
728
- --dl-surface: #282727;
729
- --dl-surface-muted: #322f2f;
730
- --dl-surface-sunken: #3a3838;
731
- --dl-text-color: #d1cfd8;
732
- --dl-label-color: #b9b7c0;
733
- --dl-line-color: #4a4747;
734
- --dl-focused-line-color: #6d6a6a;
735
- --dl-border-muted: #4a4747;
736
- --dl-tooltip-background: #413e48;
737
- --dl-tooltip-color: #d1cfd8;
738
- --dl-select-loading-col1: #282727;
739
- --dl-select-loading-col2: #505656;
1279
+ .options-wrapper.options-wrapper .noMatchesHint {
1280
+ border: none;
1281
+ padding: 0.625rem 0.75rem;
1282
+ color: var(--dl-text-muted);
1283
+ font-size: var(--dl-font-size-sm);
1284
+ }
1285
+
1286
+ .dl-form dl-select .dl-option-tag,
1287
+ .options-wrapper.options-wrapper .dl-option-tag {
1288
+ padding: 0.05rem 0.35rem;
1289
+ border: 1px solid var(--dl-line-strong);
1290
+ border-radius: var(--dl-radius-pill);
1291
+ color: var(--dl-text-muted);
1292
+ font-family: var(--dl-font-family);
1293
+ font-size: 0.6875rem;
1294
+ margin-top: 0;
740
1295
  }