@24vlh/vds 0.1.0 → 0.1.1

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,1831 +1 @@
1
- /************************************************************
2
- * VLAH DESIGN SYSTEM (VDS) - Forms
3
- *
4
- * Responsibilities:
5
- * - Provide two parallel form architectures:
6
- * A) Legacy VDS form controls: input, textarea, select,
7
- * segmented controls, toggles, switches, radio/checkbox, input groups
8
- * B) UFAL (Unified Form Abstraction Layer): form-control,
9
- * wrapper elements, adaptive surfaces, loading/error states,
10
- * prefix/suffix architecture, file/drop zones, and layout primitives
11
- *
12
- * - Supply semantic/interactive states:
13
- * focus, hover, disabled, readonly, error, success, warning, info,
14
- * dirty, loading, validated, invalidated
15
- *
16
- * - Define full visual contract for:
17
- * control sizing tokens, label/caption hierarchy,
18
- * density modes, inline/stack layouts, and responsive adaptations
19
- *
20
- * System Notes:
21
- * - 100% token-driven: spacing, radii, borders, typography, motion
22
- * - No JS assumptions; all behaviours (loading shimmer, validation highlights)
23
- * are CSS-based
24
- * - Legacy and UFAL architectures MUST co-exist in v1; no cross-overwrites
25
- ************************************************************/
26
-
27
- /* ---------------------------------------------------------
28
- 1. FORM TOKEN DEFINITIONS
29
- --------------------------------------------------------- */
30
-
31
- [data-vds-form],
32
- .vds-form {
33
- --form-flow-gap-xs: var(--space-1);
34
- --form-flow-textarea-min-height: 5rem;
35
-
36
- --size-9: 2.75rem;
37
- --size-10: 3.00rem;
38
- --size-11: 3.25rem;
39
-
40
- --control-min-height: var(--size-10);
41
-
42
- --control-height-md: 40px;
43
- }
44
-
45
- [data-vds-form] .form--a .form-control,
46
- .vds-form .form--a .form-control {
47
- --control-min-height: var(--size-11);
48
- }
49
-
50
- [data-vds-form] .form--c .form-control,
51
- .vds-form .form--c .form-control {
52
- --control-min-height: var(--size-9);
53
- }
54
-
55
- /* ---------------------------------------------------------
56
- 2. BASE FORM RESET
57
- --------------------------------------------------------- */
58
-
59
- input,
60
- select,
61
- textarea,
62
- button {
63
- font-family: inherit;
64
- font-size: 100%;
65
- line-height: inherit;
66
- color: inherit;
67
- }
68
-
69
- input,
70
- select,
71
- textarea {
72
- background-clip: padding-box;
73
- }
74
-
75
- input:focus,
76
- select:focus,
77
- textarea:focus {
78
- outline: none;
79
- }
80
-
81
- /* ---------------------------------------------------------
82
- 3. DENSITY LAYERS (A/B/C)
83
- --------------------------------------------------------- */
84
-
85
- .form--a .input,
86
- .form--a .select,
87
- .form--a .textarea {
88
- padding: var(--space-4);
89
- font-size: var(--text-md);
90
- }
91
-
92
- .form--a .form-check {
93
- font-size: var(--text-md);
94
- }
95
-
96
- .form--a .segmented__option {
97
- padding: var(--space-3) var(--space-5);
98
- font-size: var(--text-md);
99
- }
100
-
101
- .form--a .file-upload__control {
102
- padding: var(--space-5);
103
- }
104
-
105
- .form--c .input,
106
- .form--c .select,
107
- .form--c .textarea {
108
- padding: var(--space-2);
109
- font-size: var(--text-xs);
110
- }
111
-
112
- .form--c .form-check {
113
- font-size: var(--text-xs);
114
- }
115
-
116
- .form--c .segmented__option {
117
- padding: var(--space-1) var(--space-3);
118
- font-size: var(--text-xs);
119
- }
120
-
121
- .form--c .file-upload__control {
122
- padding: var(--space-3);
123
- }
124
-
125
- /* ---------------------------------------------------------
126
- 4. FIELD WRAPPER
127
- --------------------------------------------------------- */
128
-
129
- .form-field {
130
- display: flex;
131
- flex-direction: column;
132
- gap: var(--form-flow-gap-xs);
133
- width: 100%;
134
- }
135
-
136
- .form-field--disabled {
137
- opacity: 0.7;
138
- pointer-events: none;
139
- }
140
-
141
- .form-label {
142
- font-weight: 500;
143
- color: var(--color-text);
144
- }
145
-
146
- .form-label--required::after {
147
- content: " *";
148
- color: var(--color-danger);
149
- font-weight: 600;
150
- }
151
-
152
- input[type="search"]::-webkit-search-decoration,
153
- input[type="search"]::-webkit-search-results-button,
154
- input[type="search"]::-webkit-search-cancel-button {
155
- -webkit-appearance: none;
156
- appearance: none;
157
- }
158
-
159
- .form-label--sr-only {
160
- position: absolute;
161
- width: 1px;
162
- height: 1px;
163
- padding: 0;
164
- margin: -1px;
165
- overflow: hidden;
166
- clip: rect(0, 0, 0, 0);
167
- border: 0;
168
- }
169
-
170
- .form-help {
171
- font-size: var(--text-xs);
172
- color: var(--color-text-muted);
173
- }
174
-
175
- .form-error {
176
- font-size: var(--text-xs);
177
- color: var(--color-danger);
178
- }
179
-
180
- .form-field--error .form-label {
181
- color: var(--color-danger);
182
- }
183
-
184
- .form-field--error .input,
185
- .form-field--error .select,
186
- .form-field--error .textarea {
187
- border-color: var(--color-danger);
188
- }
189
-
190
- .form-field--error .input-group {
191
- border-color: var(--color-danger);
192
- }
193
-
194
- .form-field--error .segmented {
195
- border-color: var(--color-danger);
196
- }
197
-
198
- .form-field--error .slider {
199
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-danger-soft);
200
- }
201
-
202
- .form-field--error .file-upload__control {
203
- border-color: var(--color-danger);
204
- background-color: var(--color-danger-soft);
205
- }
206
-
207
- /* ---------------------------------------------------------
208
- 5. BASE INPUT
209
- --------------------------------------------------------- */
210
-
211
- .input {
212
- width: 100%;
213
- padding: var(--space-3) var(--space-3);
214
-
215
- border: var(--border-width) solid var(--color-border-subtle);
216
- border-radius: var(--radius-md);
217
- background-color: var(--color-surface);
218
- color: var(--color-text);
219
-
220
- transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
221
- }
222
-
223
- .input:focus {
224
- border-color: var(--color-accent);
225
- }
226
-
227
- .input:focus-visible {
228
- border-color: var(--focus-ring-color);
229
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
230
- }
231
-
232
- .input:hover {
233
- border-color: var(--color-border-strong);
234
- }
235
-
236
- .input:disabled,
237
- .input--disabled {
238
- background-color: var(--color-muted-bg);
239
- color: var(--color-text-muted);
240
- cursor: not-allowed;
241
- }
242
-
243
- .input[readonly],
244
- .input--readonly {
245
- background-color: var(--color-surface-subtle);
246
- color: var(--color-text-muted);
247
- border-style: dashed;
248
- }
249
-
250
- .input::-moz-placeholder {
251
- color: var(--color-placeholder);
252
- opacity: 1;
253
- }
254
-
255
- .input::placeholder {
256
- color: var(--color-placeholder);
257
- opacity: 1;
258
- }
259
-
260
- /* ---------------------------------------------------------
261
- 5A. INPUT WITH ICONS
262
- Pattern:
263
- <div class="input-icon input-icon--left">
264
- <span class="input-icon__icon">...</span>
265
- <input class="input">
266
- </div>
267
- --------------------------------------------------------- */
268
-
269
- .input-icon {
270
- position: relative;
271
- display: flex;
272
- align-items: center;
273
- width: 100%;
274
- }
275
-
276
- .input-icon .input {
277
- width: 100%;
278
- }
279
-
280
- .input-icon--left .input {
281
- padding-left: var(--space-8);
282
- }
283
-
284
- .input-icon--right .input {
285
- padding-right: var(--space-8);
286
- }
287
-
288
- .input-icon--both .input {
289
- padding-left: var(--space-8);
290
- padding-right: var(--space-8);
291
- }
292
-
293
- .input-icon__icon {
294
- position: absolute;
295
- top: 50%;
296
- transform: translateY(-50%);
297
- display: inline-flex;
298
- align-items: center;
299
- justify-content: center;
300
- width: var(--icon-sm);
301
- height: var(--icon-sm);
302
- color: var(--color-text-muted);
303
- }
304
-
305
- .input-icon--left .input-icon__icon {
306
- left: var(--space-3);
307
- }
308
-
309
- .input-icon--right .input-icon__icon {
310
- right: var(--space-3);
311
- }
312
-
313
- /* ---------------------------------------------------------
314
- 6. TEXTAREA
315
- --------------------------------------------------------- */
316
-
317
- .textarea {
318
- width: 100%;
319
- resize: vertical;
320
- min-height: var(--form-flow-textarea-min-height);
321
- padding: var(--space-3);
322
-
323
- border: var(--border-width) solid var(--color-border-subtle);
324
- border-radius: var(--radius-md);
325
- background-color: var(--color-surface);
326
- color: var(--color-text);
327
-
328
- transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
329
- }
330
-
331
- .textarea:focus {
332
- border-color: var(--color-accent);
333
- }
334
-
335
- .textarea:focus-visible {
336
- border-color: var(--focus-ring-color);
337
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
338
- }
339
-
340
- .textarea:hover {
341
- border-color: var(--color-border-strong);
342
- }
343
-
344
- .textarea:disabled,
345
- .textarea--disabled {
346
- background-color: var(--color-muted-bg);
347
- color: var(--color-text-muted);
348
- cursor: not-allowed;
349
- }
350
-
351
- .textarea[readonly],
352
- .textarea--readonly {
353
- background-color: var(--color-surface-subtle);
354
- color: var(--color-text-muted);
355
- border-style: dashed;
356
- }
357
-
358
- .textarea::-moz-placeholder {
359
- color: var(--color-placeholder);
360
- opacity: 1;
361
- }
362
-
363
- .textarea::placeholder {
364
- color: var(--color-placeholder);
365
- opacity: 1;
366
- }
367
-
368
- /* ---------------------------------------------------------
369
- 7. SELECT (NATIVE + CUSTOM DROPDOWN ICON)
370
- --------------------------------------------------------- */
371
-
372
- .select {
373
- width: 100%;
374
- padding: var(--space-3) var(--space-4) var(--space-3) var(--space-3);
375
-
376
- -webkit-appearance: none;
377
-
378
- -moz-appearance: none;
379
-
380
- appearance: none;
381
- background-color: var(--color-surface);
382
- color: var(--color-text);
383
-
384
- border: var(--border-width) solid var(--color-border-subtle);
385
- border-radius: var(--radius-md);
386
-
387
- position: relative;
388
- transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
389
-
390
- background-image: linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
391
- linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
392
- background-position: calc(100% - var(--space-3)) center,
393
- calc(100% - var(--space-2)) center;
394
- background-size: 0.4rem 0.4rem;
395
- background-repeat: no-repeat;
396
- padding-right: var(--space-6);
397
- }
398
-
399
- .select:focus {
400
- border-color: var(--color-accent);
401
- }
402
-
403
- .select:focus-visible {
404
- border-color: var(--focus-ring-color);
405
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
406
- }
407
-
408
- .select:hover {
409
- border-color: var(--color-border-strong);
410
- }
411
-
412
- .select:disabled,
413
- .select--disabled {
414
- background-color: var(--color-muted-bg);
415
- color: var(--color-text-muted);
416
- cursor: not-allowed;
417
- background-image: linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
418
- linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
419
- }
420
-
421
- /* ---------------------------------------------------------
422
- 8. CHECKBOXES & RADIOS
423
- --------------------------------------------------------- */
424
-
425
- .form-check {
426
- display: flex;
427
- align-items: center;
428
- gap: var(--space-2);
429
- margin-bottom: var(--space-3);
430
- cursor: pointer;
431
- font-size: var(--text-sm);
432
- }
433
-
434
- .form-check-group .form-check:last-child {
435
- margin-bottom: 0;
436
- }
437
-
438
- .form-check--disabled {
439
- opacity: 0.7;
440
- cursor: not-allowed;
441
- }
442
-
443
- .form-check input {
444
- width: 1.15rem;
445
- height: 1.15rem;
446
- cursor: pointer;
447
- }
448
-
449
- .checkbox {
450
- -webkit-appearance: none;
451
- -moz-appearance: none;
452
- appearance: none;
453
- border: var(--border-width) solid var(--color-border-subtle);
454
- border-radius: var(--radius-sm);
455
- background-color: var(--color-surface);
456
- cursor: pointer;
457
- position: relative;
458
- transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
459
- }
460
-
461
- .checkbox:hover {
462
- border-color: var(--color-border-strong);
463
- }
464
-
465
- .checkbox:focus-visible {
466
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
467
- outline: none;
468
- }
469
-
470
- .checkbox:checked {
471
- border-color: var(--color-accent);
472
- background-color: var(--color-accent-soft);
473
- }
474
-
475
- .checkbox:checked::after {
476
- content: "";
477
- position: absolute;
478
- top: 50%;
479
- left: 50%;
480
- width: 0.55rem;
481
- height: 0.55rem;
482
- transform: translate(-50%, -50%);
483
- background-color: var(--color-accent);
484
- -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='16' height='16' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolyline points='3 8 7 12 13 4'/%3E%3C/svg%3E");
485
- mask-image: url("data:image/svg+xml,%3Csvg width='16' height='16' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolyline points='3 8 7 12 13 4'/%3E%3C/svg%3E");
486
- -webkit-mask-size: cover;
487
- mask-size: cover;
488
- }
489
-
490
- .checkbox:disabled {
491
- background-color: var(--color-muted-bg);
492
- border-color: var(--color-muted-border);
493
- cursor: not-allowed;
494
- }
495
-
496
- .checkbox--error {
497
- border-color: var(--color-danger);
498
- }
499
-
500
- .checkbox--warning {
501
- border-color: var(--color-warning);
502
- }
503
-
504
- .checkbox--success {
505
- border-color: var(--color-success);
506
- }
507
-
508
- .checkbox--info {
509
- border-color: var(--color-info);
510
- }
511
-
512
- .radio {
513
- -webkit-appearance: none;
514
- -moz-appearance: none;
515
- appearance: none;
516
- border: var(--border-width) solid var(--color-border-subtle);
517
- border-radius: 50%;
518
- background-color: var(--color-surface);
519
- cursor: pointer;
520
- position: relative;
521
- transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
522
- }
523
-
524
- .radio:hover {
525
- border-color: var(--color-border-strong);
526
- }
527
-
528
- .radio:focus-visible {
529
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
530
- outline: none;
531
- }
532
-
533
- .radio:checked {
534
- border-color: var(--color-accent);
535
- background-color: var(--color-accent-soft);
536
- }
537
-
538
- .radio:checked::after {
539
- content: "";
540
- position: absolute;
541
- top: 50%;
542
- left: 50%;
543
- width: 0.55rem;
544
- height: 0.55rem;
545
- background-color: var(--color-accent);
546
- border-radius: 50%;
547
- transform: translate(-50%, -50%);
548
- }
549
-
550
- .radio:disabled {
551
- background-color: var(--color-muted-bg);
552
- border-color: var(--color-muted-border);
553
- cursor: not-allowed;
554
- }
555
-
556
- .radio--error {
557
- border-color: var(--color-danger);
558
- }
559
-
560
- .radio--warning {
561
- border-color: var(--color-warning);
562
- }
563
-
564
- .radio--success {
565
- border-color: var(--color-success);
566
- }
567
-
568
- .radio--info {
569
- border-color: var(--color-info);
570
- }
571
-
572
- /* ---------------------------------------------------------
573
- 9. SWITCHES
574
- Pattern: <input type="checkbox" class="switch">
575
- --------------------------------------------------------- */
576
-
577
- .switch {
578
- -webkit-appearance: none;
579
- -moz-appearance: none;
580
- appearance: none;
581
- border: var(--border-width) solid var(--color-border-subtle);
582
- border-radius: 50%;
583
- background-color: var(--color-surface);
584
- cursor: pointer;
585
- position: relative;
586
- transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
587
- width: 1.15rem;
588
- height: 1.15rem;
589
- }
590
-
591
- .switch::after {
592
- content: "";
593
- position: absolute;
594
- top: 22%;
595
- left: 22%;
596
- width: 0.55rem;
597
- height: 0.55rem;
598
- background-color: var(--color-accent);
599
- border-radius: 50%;
600
- transform: translate(-50%, -50%);
601
- opacity: 0;
602
- }
603
-
604
- .switch:checked {
605
- background-color: var(--color-accent-strong);
606
- border: var(--border-width) solid var(--color-accent);
607
- }
608
-
609
- .switch:checked::after {
610
- opacity: 1;
611
- transform: scale(1);
612
- background-color: var(--color-accent);
613
- }
614
-
615
- .switch:disabled {
616
- opacity: 0.5;
617
- cursor: not-allowed;
618
- }
619
-
620
- .switch:focus-visible {
621
- outline: none;
622
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
623
- }
624
-
625
- .switch--error {
626
- background-color: var(--color-danger-soft);
627
- }
628
-
629
- .switch--warning {
630
- background-color: var(--color-warning-soft);
631
- }
632
-
633
- .switch--success {
634
- background-color: var(--color-success-soft);
635
- }
636
-
637
- .switch--info {
638
- background-color: var(--color-info-soft);
639
- }
640
-
641
- .switch--error:checked {
642
- background-color: var(--color-danger);
643
- }
644
-
645
- .switch--warning:checked {
646
- background-color: var(--color-warning);
647
- }
648
-
649
- .switch--success:checked {
650
- background-color: var(--color-success);
651
- }
652
-
653
- .switch--info:checked {
654
- background-color: var(--color-info);
655
- }
656
-
657
- /* ---------------------------------------------------------
658
- 10. INPUT GROUPS (ICONS + ADDONS)
659
- --------------------------------------------------------- */
660
-
661
- .input-group {
662
- display: flex;
663
- align-items: center;
664
- border: var(--border-width) solid var(--color-border-subtle);
665
- border-radius: var(--radius-md);
666
- background-color: var(--color-surface);
667
- overflow: hidden;
668
- }
669
-
670
- .input-group .input {
671
- border: none;
672
- flex: 1;
673
- box-shadow: none;
674
- }
675
-
676
- .input-group-addon {
677
- padding: 0 var(--space-3);
678
- display: flex;
679
- align-items: center;
680
- color: var(--color-text-muted);
681
- background-color: var(--color-surface);
682
- border-right: var(--border-width) solid var(--color-border-subtle);
683
- }
684
-
685
- .input-group-addon + .input {
686
- padding-left: var(--space-2);
687
- }
688
-
689
- .input-group-icon {
690
- display: flex;
691
- align-items: center;
692
- padding: 0 var(--space-3);
693
- color: var(--color-text-muted);
694
- }
695
-
696
- .input-group-icon .icon {
697
- width: var(--icon-sm);
698
- height: var(--icon-sm);
699
- }
700
-
701
- .input-group--error {
702
- border-color: var(--color-danger);
703
- }
704
-
705
- .input-group--warning {
706
- border-color: var(--color-warning);
707
- }
708
-
709
- .input-group--success {
710
- border-color: var(--color-success);
711
- }
712
-
713
- .input-group--info {
714
- border-color: var(--color-info);
715
- }
716
-
717
- .input-group--disabled {
718
- opacity: 0.7;
719
- pointer-events: none;
720
- }
721
-
722
- .input-group:focus-within {
723
- border-color: var(--focus-ring-color);
724
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
725
- }
726
-
727
- .input-group:hover {
728
- border-color: var(--color-border-strong);
729
- }
730
-
731
- /* ---------------------------------------------------------
732
- 11. SEGMENTED CONTROL
733
- --------------------------------------------------------- */
734
-
735
- .segmented {
736
- display: flex;
737
- width: 100%;
738
- border: var(--border-width) solid var(--color-border-subtle);
739
- border-radius: var(--radius-md);
740
- overflow: hidden;
741
- height: 2.5rem;
742
- height: var(--control-height-md, 2.5rem);
743
- background-color: var(--color-surface);
744
- }
745
-
746
- .segmented__option {
747
- flex: 1 1 0;
748
- text-align: center;
749
- -webkit-appearance: none;
750
- -moz-appearance: none;
751
- appearance: none;
752
- border: none;
753
- font: inherit;
754
- line-height: inherit;
755
- padding: var(--space-2) var(--space-4);
756
- cursor: pointer;
757
- -webkit-user-select: none;
758
- -moz-user-select: none;
759
- user-select: none;
760
- display: inline-flex;
761
- align-items: center;
762
- justify-content: center;
763
- color: var(--color-text-muted);
764
- background: var(--color-surface);
765
- height: 100%;
766
- transition: background-color 0.2s, color 0.2s;
767
- }
768
-
769
- .segmented__option:not(:last-child) {
770
- border-right: var(--border-width) solid var(--color-border-subtle);
771
- }
772
-
773
- .segmented__option:hover {
774
- background-color: var(--color-surface-subtle);
775
- color: var(--color-text);
776
- }
777
-
778
- .segmented__option:focus-visible {
779
- outline: none;
780
- box-shadow: inset 0 0 0 var(--border-width-strong) var(--focus-ring-color);
781
- }
782
-
783
- .segmented__option--active {
784
- background-color: var(--color-accent);
785
- color: var(--color-on-accent);
786
- font-weight: 600;
787
- position: relative;
788
- z-index: 1;
789
- }
790
-
791
- .segmented__option--active + .segmented__option {
792
- border-left-color: transparent;
793
- }
794
-
795
- .segmented--disabled {
796
- opacity: 0.6;
797
- pointer-events: none;
798
- }
799
-
800
- .segmented__option--disabled {
801
- cursor: not-allowed;
802
- opacity: 0.7;
803
- }
804
-
805
- .segmented__option-icon {
806
- width: var(--icon-sm);
807
- height: var(--icon-sm);
808
- margin-right: var(--space-2);
809
- }
810
-
811
- .segmented--error {
812
- border-color: var(--color-danger);
813
- }
814
-
815
- .segmented--warning {
816
- border-color: var(--color-warning);
817
- }
818
-
819
- .segmented--success {
820
- border-color: var(--color-success);
821
- }
822
-
823
- .segmented--info {
824
- border-color: var(--color-info);
825
- }
826
-
827
- .segmented--loading .segmented__option {
828
- position: relative;
829
- overflow: hidden;
830
- }
831
-
832
- .segmented--loading .segmented__option::after {
833
- content: "";
834
- position: absolute;
835
- top: 0;
836
- right: 0;
837
- bottom: 0;
838
- left: 0;
839
- background-image: linear-gradient(
840
- 90deg,
841
- var(--color-muted-bg),
842
- var(--color-surface),
843
- var(--color-muted-bg)
844
- );
845
- background-size: 200% 100%;
846
- animation: input-loading-shimmer 1.5s infinite;
847
- }
848
-
849
- /* ---------------------------------------------------------
850
- 12. SLIDER
851
- --------------------------------------------------------- */
852
-
853
- .slider {
854
- width: 100%;
855
- -webkit-appearance: none;
856
- -moz-appearance: none;
857
- appearance: none;
858
- height: var(--border-width-strong);
859
- background-color: var(--slider-track-bg);
860
- border-radius: var(--radius-sm);
861
- cursor: pointer;
862
- }
863
-
864
- .slider:focus-visible {
865
- outline: none;
866
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
867
- }
868
-
869
- .slider:disabled {
870
- cursor: not-allowed;
871
- opacity: 0.7;
872
- }
873
-
874
- .slider::-webkit-slider-thumb {
875
- -webkit-appearance: none;
876
- appearance: none;
877
- width: 1rem;
878
- height: 1rem;
879
- background: var(--slider-thumb-bg);
880
- border-radius: 50%;
881
- cursor: pointer;
882
- }
883
-
884
- .slider::-moz-range-thumb {
885
- width: 1rem;
886
- height: 1rem;
887
- background: var(--slider-thumb-bg);
888
- border-radius: 50%;
889
- cursor: pointer;
890
- }
891
-
892
- .slider--error {
893
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-danger-soft);
894
- }
895
-
896
- .slider--error:focus-visible {
897
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-danger);
898
- outline: none;
899
- }
900
-
901
- .slider--warning {
902
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-warning-soft);
903
- }
904
-
905
- .slider--warning:focus-visible {
906
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-warning);
907
- outline: none;
908
- }
909
-
910
- .slider--success {
911
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-success-soft);
912
- }
913
-
914
- .slider--success:focus-visible {
915
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-success);
916
- outline: none;
917
- }
918
-
919
- .slider--info {
920
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-info-soft);
921
- }
922
-
923
- .slider--info:focus-visible {
924
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-info);
925
- outline: none;
926
- }
927
-
928
- /* ---------------------------------------------------------
929
- 13. FILE UPLOAD (CUSTOM)
930
- --------------------------------------------------------- */
931
-
932
- .file-upload {
933
- display: flex;
934
- flex-direction: column;
935
- gap: var(--space-2);
936
- }
937
-
938
- .file-upload input {
939
- position: absolute;
940
- width: 1px;
941
- height: 1px;
942
- padding: 0;
943
- margin: -1px;
944
- overflow: hidden;
945
- clip: rect(0, 0, 0, 0);
946
- white-space: nowrap;
947
- border: 0;
948
- }
949
-
950
- .file-upload__control {
951
- border: var(--border-width) dashed var(--color-border-subtle);
952
- border-radius: var(--radius-md);
953
- padding: var(--space-4);
954
- text-align: center;
955
- color: var(--color-text-soft);
956
- cursor: pointer;
957
- background-color: var(--color-surface);
958
- transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
959
- }
960
-
961
- .file-upload__control:hover {
962
- border-color: var(--color-border-strong);
963
- background-color: var(--color-surface-subtle);
964
- }
965
-
966
- .file-upload__control:focus-visible {
967
- outline: none;
968
- box-shadow: 0 0 0 var(--border-width-strong) var(--focus-ring-color);
969
- }
970
-
971
- .file-upload__control--dragover {
972
- border-color: var(--color-accent);
973
- background-color: var(--color-accent-soft);
974
- }
975
-
976
- .file-upload__control--disabled {
977
- opacity: 0.7;
978
- cursor: not-allowed;
979
- }
980
-
981
- .file-upload__control--error {
982
- border-color: var(--color-danger);
983
- background-color: var(--color-danger-soft);
984
- color: var(--color-danger-strong);
985
- }
986
-
987
- .file-upload__control--warning {
988
- border-color: var(--color-warning);
989
- background-color: var(--color-warning-soft);
990
- color: var(--color-warning-strong);
991
- }
992
-
993
- .file-upload__control--success {
994
- border-color: var(--color-success);
995
- background-color: var(--color-success-soft);
996
- color: var(--color-success-strong);
997
- }
998
-
999
- .file-upload__control--info {
1000
- border-color: var(--color-info);
1001
- background-color: var(--color-info-soft);
1002
- color: var(--color-info-strong);
1003
- }
1004
-
1005
- .file-upload__control--loading {
1006
- background-image: linear-gradient(
1007
- 90deg,
1008
- var(--color-muted-bg),
1009
- var(--color-surface),
1010
- var(--color-muted-bg)
1011
- );
1012
- background-size: 200% 100%;
1013
- animation: input-loading-shimmer 1.5s infinite;
1014
- }
1015
-
1016
- /* ---------------------------------------------------------
1017
- 14. FORM GRID / FORM ROWS
1018
- --------------------------------------------------------- */
1019
-
1020
- .form-row {
1021
- display: flex;
1022
- flex-wrap: wrap;
1023
- gap: var(--space-4);
1024
- }
1025
-
1026
- .form-row--two {
1027
- display: grid;
1028
- grid-template-columns: repeat(2, minmax(0, 1fr));
1029
- grid-gap: var(--space-4);
1030
- gap: var(--space-4);
1031
- }
1032
-
1033
- .form-grid {
1034
- display: grid;
1035
- grid-gap: var(--space-4);
1036
- gap: var(--space-4);
1037
- }
1038
-
1039
- .form-grid--two {
1040
- grid-template-columns: repeat(2, minmax(0, 1fr));
1041
- }
1042
-
1043
- .form-grid--three {
1044
- grid-template-columns: repeat(3, minmax(0, 1fr));
1045
- }
1046
-
1047
- .form-grid--four {
1048
- grid-template-columns: repeat(4, minmax(0, 1fr));
1049
- }
1050
-
1051
- @media (max-width: 768px) {
1052
- .form-grid--two,
1053
- .form-grid--three,
1054
- .form-grid--four {
1055
- grid-template-columns: 1fr;
1056
- }
1057
- }
1058
-
1059
- /* ---------------------------------------------------------
1060
- 15. VALIDATION STATES (INPUT / SELECT / TEXTAREA)
1061
- --------------------------------------------------------- */
1062
-
1063
- .input--error,
1064
- .select--error,
1065
- .textarea--error {
1066
- border-color: var(--color-danger);
1067
- }
1068
-
1069
- .input--error:focus-visible,
1070
- .select--error:focus-visible,
1071
- .textarea--error:focus-visible {
1072
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-danger-soft);
1073
- }
1074
-
1075
- .input--success,
1076
- .select--success,
1077
- .textarea--success {
1078
- border-color: var(--color-success);
1079
- }
1080
-
1081
- .input--success:focus-visible,
1082
- .select--success:focus-visible,
1083
- .textarea--success:focus-visible {
1084
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-success-soft);
1085
- }
1086
-
1087
- .input--warning,
1088
- .select--warning,
1089
- .textarea--warning {
1090
- border-color: var(--color-warning);
1091
- }
1092
-
1093
- .input--warning:focus-visible,
1094
- .select--warning:focus-visible,
1095
- .textarea--warning:focus-visible {
1096
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-warning-soft);
1097
- }
1098
-
1099
- .input--info,
1100
- .select--info,
1101
- .textarea--info {
1102
- border-color: var(--color-info);
1103
- }
1104
-
1105
- .input--info:focus-visible,
1106
- .select--info:focus-visible,
1107
- .textarea--info:focus-visible {
1108
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-info-soft);
1109
- }
1110
-
1111
- /* ---------------------------------------------------------
1112
- 16. FIELD META (HELP, ERROR, COUNTER, ICONS, LAYOUT)
1113
- --------------------------------------------------------- */
1114
-
1115
- .form-meta {
1116
- display: flex;
1117
- align-items: flex-start;
1118
- justify-content: space-between;
1119
- gap: var(--form-flow-gap-xs);
1120
- margin-top: var(--space-1);
1121
- }
1122
-
1123
- .form-meta--stacked {
1124
- flex-direction: column;
1125
- align-items: flex-start;
1126
- }
1127
-
1128
- .form-meta--inline {
1129
- flex-direction: row;
1130
- align-items: center;
1131
- }
1132
-
1133
- .form-meta__messages {
1134
- display: flex;
1135
- flex-direction: column;
1136
- gap: var(--space-1);
1137
- min-width: 0;
1138
- }
1139
-
1140
- .form-counter {
1141
- margin-left: auto;
1142
- font-size: var(--text-xs);
1143
- font-family: var(--font-family-mono), monospace;
1144
- color: var(--color-text-muted);
1145
- white-space: nowrap;
1146
- }
1147
-
1148
- .form-counter--warning {
1149
- color: var(--color-warning);
1150
- }
1151
-
1152
- .form-counter--danger {
1153
- color: var(--color-danger);
1154
- }
1155
-
1156
- .form-field--error .form-counter {
1157
- color: var(--color-danger);
1158
- }
1159
-
1160
- .form-control-with-icon {
1161
- position: relative;
1162
- display: inline-flex;
1163
- width: 100%;
1164
- }
1165
-
1166
- .form-control-with-icon .input,
1167
- .form-control-with-icon .select,
1168
- .form-control-with-icon .textarea {
1169
- width: 100%;
1170
- padding-right: calc(var(--space-8) + var(--space-1));
1171
- }
1172
-
1173
- .form-status-icon {
1174
- position: absolute;
1175
- right: var(--space-3);
1176
- top: 50%;
1177
- transform: translateY(-50%);
1178
- display: inline-flex;
1179
- align-items: center;
1180
- justify-content: center;
1181
- width: var(--icon-sm);
1182
- height: var(--icon-sm);
1183
- color: var(--color-text-muted);
1184
- pointer-events: none;
1185
- }
1186
-
1187
- .form-field--error .form-status-icon {
1188
- color: var(--color-danger);
1189
- }
1190
-
1191
- .form-field--success .form-status-icon {
1192
- color: var(--color-success);
1193
- }
1194
-
1195
- .form-field--warning .form-status-icon {
1196
- color: var(--color-warning);
1197
- }
1198
-
1199
- .form-field--info .form-status-icon {
1200
- color: var(--color-info);
1201
- }
1202
-
1203
- .form-field--success .form-label {
1204
- color: var(--color-success);
1205
- }
1206
-
1207
- .form-field--success .input,
1208
- .form-field--success .select,
1209
- .form-field--success .textarea,
1210
- .form-field--success .input-group {
1211
- border-color: var(--color-success);
1212
- }
1213
-
1214
- .form-field--warning .form-label {
1215
- color: var(--color-warning);
1216
- }
1217
-
1218
- .form-field--warning .input,
1219
- .form-field--warning .select,
1220
- .form-field--warning .textarea,
1221
- .form-field--warning .input-group {
1222
- border-color: var(--color-warning);
1223
- }
1224
-
1225
- .form-field--info .form-label {
1226
- color: var(--color-info);
1227
- }
1228
-
1229
- .form-field--info .input,
1230
- .form-field--info .select,
1231
- .form-field--info .textarea,
1232
- .form-field--info .input-group {
1233
- border-color: var(--color-info);
1234
- }
1235
-
1236
- .form-field--horizontal {
1237
- display: grid;
1238
- grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
1239
- grid-column-gap: var(--space-4);
1240
- -moz-column-gap: var(--space-4);
1241
- column-gap: var(--space-4);
1242
- align-items: flex-start;
1243
- }
1244
-
1245
- .form-field__label {
1246
- padding-top: var(--space-1);
1247
- }
1248
-
1249
- .form-field__control {
1250
- display: flex;
1251
- flex-direction: column;
1252
- gap: var(--form-flow-gap-xs);
1253
- }
1254
-
1255
- @media (max-width: 768px) {
1256
- .form-field--horizontal {
1257
- grid-template-columns: 1fr;
1258
- }
1259
-
1260
- .form-field__label {
1261
- padding-top: 0;
1262
- }
1263
- }
1264
-
1265
- .input--loading,
1266
- .select--loading,
1267
- .textarea--loading {
1268
- background-image: linear-gradient(
1269
- 90deg,
1270
- var(--color-muted-bg),
1271
- var(--color-surface),
1272
- var(--color-muted-bg)
1273
- );
1274
- background-size: 200% 100%;
1275
- animation: input-loading-shimmer 1.5s infinite;
1276
- }
1277
-
1278
- @keyframes input-loading-shimmer {
1279
- 0% {
1280
- background-position: -150% 0;
1281
- }
1282
- 100% {
1283
- background-position: 150% 0;
1284
- }
1285
- }
1286
-
1287
- /* ---------------------------------------------------------
1288
- 17. FORMS INSIDE MODALS / PANELS
1289
- --------------------------------------------------------- */
1290
-
1291
- .modal .form-field {
1292
- margin-bottom: var(--space-3);
1293
- }
1294
-
1295
- /* ---------------------------------------------------------
1296
- 18. FORM-LEVEL MESSAGES (top of form)
1297
- --------------------------------------------------------- */
1298
-
1299
- .form-message {
1300
- width: 100%;
1301
- padding: var(--space-4) var(--space-6);
1302
- border-radius: var(--radius-md);
1303
- border: var(--border-width) solid var(--color-border-subtle);
1304
- background-color: var(--color-surface-subtle);
1305
- font-size: var(--text-sm);
1306
- display: flex;
1307
- align-items: flex-start;
1308
- gap: var(--space-3);
1309
- }
1310
-
1311
- .form-message__icon {
1312
- width: 1.25rem;
1313
- height: 1.25rem;
1314
- flex-shrink: 0;
1315
- stroke: currentColor;
1316
- fill: none;
1317
- }
1318
-
1319
- .form-message__content {
1320
- display: flex;
1321
- flex-direction: column;
1322
- gap: var(--space-1);
1323
- }
1324
-
1325
- .form-message--neutral {
1326
- border-color: var(--color-muted-border);
1327
- background-color: var(--color-muted-bg);
1328
- color: var(--color-text-muted);
1329
- }
1330
-
1331
- .form-message--error {
1332
- background-color: var(--semantic-error-bg-strong, var(--color-danger-soft));
1333
- border-color: var(--semantic-error-border-strong, var(--color-danger));
1334
- color: var(--semantic-error-text-strong, var(--color-danger-strong));
1335
- }
1336
-
1337
- .form-message--info {
1338
- background-color: var(--semantic-info-bg-strong, var(--color-info-soft));
1339
- border-color: var(--semantic-info-border-strong, var(--color-info));
1340
- color: var(--semantic-info-text-strong, var(--color-info-strong));
1341
- }
1342
-
1343
- .form-message--success {
1344
- background-color: var(--semantic-success-bg-strong, var(--color-success-soft));
1345
- border-color: var(--semantic-success-border-strong, var(--color-success));
1346
- color: var(--semantic-success-text-strong, var(--color-success-strong));
1347
- }
1348
-
1349
- .form-message--warning {
1350
- background-color: var(--semantic-warning-bg-strong, var(--color-warning-soft));
1351
- border-color: var(--semantic-warning-border-strong, var(--color-warning));
1352
- color: var(--semantic-warning-text-strong, var(--color-warning-strong));
1353
- }
1354
-
1355
- /* ---------------------------------------------------------
1356
- 19. FIELD-LEVEL STATE MESSAGES (below inputs)
1357
- --------------------------------------------------------- */
1358
-
1359
- .form-field-message {
1360
- font-size: var(--text-xs);
1361
- margin-top: var(--space-1);
1362
- display: flex;
1363
- align-items: center;
1364
- gap: var(--space-1);
1365
- }
1366
-
1367
- .form-field-message--neutral {
1368
- color: var(--color-text-muted);
1369
- }
1370
-
1371
- .form-field-message--error {
1372
- color: var(--semantic-error-text-strong, var(--color-danger-strong));
1373
- }
1374
-
1375
- .form-field-message--warning {
1376
- color: var(--semantic-warning-text-strong, var(--color-warning-strong));
1377
- }
1378
-
1379
- .form-field-message--info {
1380
- color: var(--semantic-info-text-strong, var(--color-info-strong));
1381
- }
1382
-
1383
- .form-field-message--success {
1384
- color: var(--semantic-success-text-strong, var(--color-success-strong));
1385
- }
1386
-
1387
- .form-field-message__icon {
1388
- width: 1rem;
1389
- height: 1rem;
1390
- stroke: currentColor;
1391
- fill: none;
1392
- flex-shrink: 0;
1393
- }
1394
-
1395
- /* ---------------------------------------------------------
1396
- 20. HORIZONTAL CHECKBOXES / RADIOS
1397
- --------------------------------------------------------- */
1398
-
1399
- .form-check-inline {
1400
- display: inline-flex;
1401
- align-items: center;
1402
- gap: var(--space-2);
1403
- margin-right: var(--space-6);
1404
- cursor: pointer;
1405
- }
1406
-
1407
- .form-check-group {
1408
- display: flex;
1409
- flex-direction: column;
1410
- gap: var(--space-1);
1411
- align-items: flex-start;
1412
- }
1413
-
1414
- .form-check-group--horizontal {
1415
- flex-direction: row;
1416
- flex-wrap: wrap;
1417
- gap: var(--space-6);
1418
- align-items: center;
1419
- }
1420
-
1421
- .form-check-group--horizontal .form-check {
1422
- margin-right: var(--space-6);
1423
- margin-bottom: var(--space-2);
1424
- }
1425
-
1426
- /* -----------------------------------------------
1427
- 21. FORM SECTION STATES
1428
- Add semantic state styling for entire sections.
1429
- Intended for wrapping form-row or form-grid.
1430
- ------------------------------------------------ */
1431
-
1432
- .form-section--error {
1433
- padding: var(--space-3);
1434
- border-left: var(--border-width-strong) solid var(--semantic-error-border-strong, var(--color-danger));
1435
- background-color: transparent;
1436
- background-color: var(--semantic-error-bg-strong, transparent);
1437
- }
1438
-
1439
- .form-section--warning {
1440
- padding: var(--space-3);
1441
- border-left: var(--border-width-strong) solid var(--semantic-warning-border-strong, var(--color-warning));
1442
- background-color: transparent;
1443
- background-color: var(--semantic-warning-bg-strong, transparent);
1444
- }
1445
-
1446
- .form-section--success {
1447
- padding: var(--space-3);
1448
- border-left: var(--border-width-strong) solid var(--semantic-success-border-strong, var(--color-success));
1449
- background-color: transparent;
1450
- background-color: var(--semantic-success-bg-strong, transparent);
1451
- }
1452
-
1453
- .form-section--info {
1454
- padding: var(--space-3);
1455
- border-left: var(--border-width-strong) solid var(--semantic-info-border-strong, var(--color-info));
1456
- background-color: transparent;
1457
- background-color: var(--semantic-info-bg-strong, transparent);
1458
- }
1459
-
1460
- .form-section--error:not(:last-child),
1461
- .form-section--warning:not(:last-child),
1462
- .form-section--success:not(:last-child),
1463
- .form-section--info:not(:last-child) {
1464
- margin-bottom: var(--space-4);
1465
- }
1466
-
1467
- /* -----------------------------------------------
1468
- 22. ARIA hooks for validation
1469
- ------------------------------------------------ */
1470
-
1471
- .input[aria-invalid="true"],
1472
- .select[aria-invalid="true"],
1473
- .textarea[aria-invalid="true"] {
1474
- border-color: var(--color-danger);
1475
- }
1476
-
1477
- .input[aria-invalid="true"]:focus-visible,
1478
- .select[aria-invalid="true"]:focus-visible,
1479
- .textarea[aria-invalid="true"]:focus-visible {
1480
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-danger-soft);
1481
- }
1482
-
1483
- /* ----------------------------------------------------------
1484
- 23. Base form control primitive (UFAL)
1485
- ---------------------------------------------------------- */
1486
-
1487
- .form-control {
1488
- display: block;
1489
- width: 100%;
1490
- min-height: var(--control-min-height);
1491
-
1492
- margin: 0;
1493
- box-sizing: border-box;
1494
- }
1495
-
1496
- .form-control-wrapper {
1497
- position: relative;
1498
- width: 100%;
1499
- display: flex;
1500
- align-items: center;
1501
- }
1502
-
1503
- .form-control-wrapper > .form-control {
1504
- flex: 1 1 auto;
1505
- }
1506
-
1507
- /* ----------------------------------------------------------
1508
- 23A. State modifiers
1509
- ---------------------------------------------------------- */
1510
-
1511
- .form-control--loading {
1512
- cursor: progress;
1513
- opacity: 0.55;
1514
- pointer-events: none;
1515
- }
1516
-
1517
- .form-control--disabled {
1518
- opacity: 0.45;
1519
- pointer-events: none;
1520
- }
1521
-
1522
- .form-control--readonly {
1523
- opacity: 0.75;
1524
- cursor: default;
1525
- }
1526
-
1527
- .form-control--error {
1528
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-danger);
1529
- }
1530
-
1531
- .form-control--warning {
1532
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-warning);
1533
- }
1534
-
1535
- .form-control--success {
1536
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-success);
1537
- }
1538
-
1539
- .form-control--info {
1540
- box-shadow: 0 0 0 var(--border-width-strong) var(--color-info);
1541
- }
1542
-
1543
- .form-control--password {
1544
- padding-right: calc(var(--space-8) + var(--space-2));
1545
- }
1546
-
1547
- .form-control-wrapper[data-icon="right"] .form-control--password {
1548
- padding-right: calc(var(--space-8) + var(--space-2));
1549
- }
1550
-
1551
- .form-control--password:focus {
1552
- border-color: var(--color-accent);
1553
- }
1554
-
1555
- .form-control--password::-moz-placeholder {
1556
- color: var(--color-placeholder);
1557
- }
1558
-
1559
- .form-control--password::placeholder {
1560
- color: var(--color-placeholder);
1561
- }
1562
-
1563
- /* ----------------------------------------------------------
1564
- 23B. Icon-inside-input patterns
1565
- ---------------------------------------------------------- */
1566
-
1567
- .form-control-wrapper[data-icon="left"] .form-control {
1568
- padding-left: calc(var(--space-7) + var(--space-2));
1569
- }
1570
-
1571
- .form-control-wrapper[data-icon="left"] .form-control-icon {
1572
- position: absolute;
1573
- left: var(--space-2);
1574
- display: flex;
1575
- align-items: center;
1576
- }
1577
-
1578
- .form-control-wrapper[data-icon="right"] .form-control {
1579
- padding-right: calc(var(--space-7) + var(--space-2));
1580
- }
1581
-
1582
- .form-control-wrapper[data-icon="right"] .form-control-icon {
1583
- position: absolute;
1584
- right: var(--space-2);
1585
- display: flex;
1586
- align-items: center;
1587
- }
1588
-
1589
- .form-control-icon {
1590
- font-size: var(--text-md);
1591
- color: var(--color-text-muted);
1592
- pointer-events: none;
1593
- }
1594
-
1595
- /* ----------------------------------------------------------
1596
- 23C. Loading overlay animation
1597
- ---------------------------------------------------------- */
1598
-
1599
- .form-control--loading::after {
1600
- content: "";
1601
- position: absolute;
1602
- top: 0;
1603
- right: 0;
1604
- bottom: 0;
1605
- left: 0;
1606
- border-radius: inherit;
1607
- background: var(--color-surface-subtle);
1608
- animation: formControlLoading 1.5s ease-in-out infinite;
1609
- }
1610
-
1611
- @keyframes formControlLoading {
1612
- 0% {
1613
- opacity: .35;
1614
- }
1615
- 50% {
1616
- opacity: .6;
1617
- }
1618
- 100% {
1619
- opacity: .35;
1620
- }
1621
- }
1622
-
1623
- /* ----------------------------------------------------------
1624
- 23D. File upload primitives (UFAL)
1625
- ---------------------------------------------------------- */
1626
-
1627
- /* Base dashed file control (rarely exposed directly; internal primitive) */
1628
-
1629
- .form-control--file {
1630
- position: relative;
1631
- padding: var(--space-3);
1632
- border: var(--border-width) dashed var(--color-border-subtle);
1633
- border-radius: var(--radius-md);
1634
- background-color: var(--color-surface);
1635
- color: var(--color-text-muted);
1636
- cursor: pointer;
1637
- transition: border-color .2s, background-color .2s;
1638
- }
1639
-
1640
- .form-control--file[type="file"] {
1641
- padding: 0;
1642
- border: none;
1643
- background: none;
1644
- position: static;
1645
- opacity: 1;
1646
- }
1647
-
1648
- /* ----------------------------------------------------------
1649
- 23E. UFAL Drop Surface (corrected)
1650
- ---------------------------------------------------------- */
1651
-
1652
- .form-control-file-surface {
1653
- position: relative; /* ★ FIX: contain absolute input */
1654
- display: flex;
1655
- flex-direction: column;
1656
- gap: var(--space-2);
1657
- align-items: center;
1658
- justify-content: center;
1659
- padding: var(--space-6);
1660
-
1661
- border: var(--border-width) dashed var(--color-border-subtle);
1662
- border-radius: var(--radius-md);
1663
- background-color: var(--color-surface);
1664
- cursor: pointer;
1665
-
1666
- transition: border-color .2s, background-color .2s;
1667
- }
1668
-
1669
- .form-control-file-surface input[type="file"] {
1670
- position: absolute;
1671
- top: 0;
1672
- right: 0;
1673
- bottom: 0;
1674
- left: 0;
1675
- opacity: 0;
1676
- cursor: pointer;
1677
- }
1678
-
1679
- .form-control-file-surface:hover {
1680
- border-color: var(--color-border-strong);
1681
- background-color: var(--color-surface-subtle);
1682
- }
1683
-
1684
- .form-control-file-surface--dragover {
1685
- border-color: var(--color-accent);
1686
- background-color: var(--color-accent-soft);
1687
- }
1688
-
1689
- .form-control-file-surface--disabled {
1690
- opacity: .65;
1691
- cursor: not-allowed;
1692
- }
1693
-
1694
- .form-control-file-surface--error {
1695
- border-color: var(--color-danger);
1696
- background-color: var(--color-danger-soft);
1697
- }
1698
-
1699
- .form-control-file-surface--warning {
1700
- border-color: var(--color-warning);
1701
- background-color: var(--color-warning-soft);
1702
- }
1703
-
1704
- .form-control-file-surface--success {
1705
- border-color: var(--color-success);
1706
- background-color: var(--color-success-soft);
1707
- }
1708
-
1709
- .form-control-file-surface--info {
1710
- border-color: var(--color-info);
1711
- background-color: var(--color-info-soft);
1712
- }
1713
-
1714
- /* ----------------------------------------------------------
1715
- 23F. Inline “button-as-trigger” upload
1716
- ---------------------------------------------------------- */
1717
-
1718
- .file-upload-inline {
1719
- display: inline-flex;
1720
- align-items: center;
1721
- gap: var(--space-2);
1722
- }
1723
-
1724
- .file-upload-inline__input {
1725
- position: absolute;
1726
- width: 1px;
1727
- height: 1px;
1728
- padding: 0;
1729
- margin: -1px;
1730
- overflow: hidden;
1731
- clip: rect(0, 0, 0, 0);
1732
- white-space: nowrap;
1733
- border: 0;
1734
- }
1735
-
1736
- .file-upload-inline__label {
1737
- cursor: pointer;
1738
- display: inline-flex;
1739
- align-items: center;
1740
- justify-content: center;
1741
- }
1742
-
1743
- /* ----------------------------------------------------------
1744
- 23G. Shared inner patterns
1745
- ---------------------------------------------------------- */
1746
-
1747
- .file-upload,
1748
- .file-upload * {
1749
- box-sizing: border-box;
1750
- }
1751
-
1752
- .file-upload {
1753
- display: flex;
1754
- flex-direction: column;
1755
- gap: var(--space-2);
1756
- width: 100%;
1757
- }
1758
-
1759
- /* Loading shimmer on drop surface */
1760
-
1761
- .form-control-file-surface.form-control--loading::after {
1762
- content: "";
1763
- position: absolute;
1764
- top: 0;
1765
- right: 0;
1766
- bottom: 0;
1767
- left: 0;
1768
- border-radius: inherit;
1769
- background-image: linear-gradient(
1770
- 90deg,
1771
- var(--color-muted-bg),
1772
- var(--color-surface),
1773
- var(--color-muted-bg)
1774
- );
1775
- background-size: 200% 100%;
1776
- animation: input-loading-shimmer 1.5s infinite;
1777
- }
1778
-
1779
- .form-control-file-icon {
1780
- font-size: var(--text-lg);
1781
- color: var(--color-text-muted);
1782
- }
1783
-
1784
- .form-control-file-label {
1785
- font-size: var(--text-sm);
1786
- color: var(--color-text);
1787
- }
1788
-
1789
- .form-control-file-hint {
1790
- font-size: var(--text-xs);
1791
- color: var(--color-text-muted);
1792
- }
1793
-
1794
- .slider--error:focus-visible,
1795
- .input[aria-invalid="true"]:focus-visible,
1796
- .select[aria-invalid="true"]:focus-visible,
1797
- .textarea[aria-invalid="true"]:focus-visible,
1798
- .form-control--error:focus-visible {
1799
- box-shadow: 0 0 0 var(--border-width-strong) var(--semantic-error-border-strong, var(--color-danger));
1800
- }
1801
-
1802
- .checkbox:checked,
1803
- .radio:checked,
1804
- .switch:checked {
1805
- background-color: var(--accent-soft-surface, var(--color-accent-soft));
1806
- border-color: var(--accent-soft-border, var(--color-accent));
1807
- box-shadow: 0 0 0 1px transparent;
1808
- box-shadow: 0 0 0 1px var(--accent-soft-shadow, transparent);
1809
- color: var(--accent-soft-on, var(--color-on-accent));
1810
- }
1811
-
1812
- .checkbox:checked::after,
1813
- .radio:checked::after,
1814
- .switch:checked::after {
1815
- background-color: var(--accent-soft-border, var(--color-accent));
1816
- }
1817
-
1818
- .checkbox:checked:hover,
1819
- .radio:checked:hover,
1820
- .switch:checked:hover {
1821
- background-color: var(--accent-soft-surface-strong, var(--accent-soft-surface));
1822
- border-color: var(--accent-soft-border, var(--color-accent));
1823
- }
1824
-
1825
- .checkbox:checked:disabled,
1826
- .radio:checked:disabled,
1827
- .switch:checked:disabled {
1828
- background-color: var(--color-surface-subtle);
1829
- border-color: var(--color-border-subtle);
1830
- opacity: 0.6;
1831
- }
1
+ .vds-form,[data-vds-form]{--form-flow-gap-xs:var(--space-1);--form-flow-textarea-min-height:5rem;--size-9:2.75rem;--size-10:3.00rem;--size-11:3.25rem;--control-min-height:var(--size-10);--control-height-md:40px}.vds-form .form--a .form-control,[data-vds-form] .form--a .form-control{--control-min-height:var(--size-11)}.vds-form .form--c .form-control,[data-vds-form] .form--c .form-control{--control-min-height:var(--size-9)}button,input,select,textarea{color:inherit;font-family:inherit;font-size:100%;line-height:inherit}input,select,textarea{background-clip:padding-box}input:focus,select:focus,textarea:focus{outline:none}.form--a .input,.form--a .select,.form--a .textarea{font-size:var(--text-md);padding:var(--space-4)}.form--a .form-check{font-size:var(--text-md)}.form--a .segmented__option{font-size:var(--text-md);padding:var(--space-3) var(--space-5)}.form--a .file-upload__control{padding:var(--space-5)}.form--c .input,.form--c .select,.form--c .textarea{font-size:var(--text-xs);padding:var(--space-2)}.form--c .form-check{font-size:var(--text-xs)}.form--c .segmented__option{font-size:var(--text-xs);padding:var(--space-1) var(--space-3)}.form--c .file-upload__control{padding:var(--space-3)}.form-field{display:flex;flex-direction:column;gap:var(--form-flow-gap-xs);width:100%}.form-field--disabled{opacity:.7;pointer-events:none}.form-label{color:var(--color-text);font-weight:500}.form-label--required:after{color:var(--color-danger);content:" *";font-weight:600}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button{-webkit-appearance:none;appearance:none}.form-label--sr-only{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.form-help{color:var(--color-text-muted)}.form-error,.form-help{font-size:var(--text-xs)}.form-error,.form-field--error .form-label{color:var(--color-danger)}.form-field--error .input,.form-field--error .input-group,.form-field--error .segmented,.form-field--error .select,.form-field--error .textarea{border-color:var(--color-danger)}.form-field--error .slider{box-shadow:0 0 0 var(--border-width-strong) var(--color-danger-soft)}.form-field--error .file-upload__control{background-color:var(--color-danger-soft);border-color:var(--color-danger)}.input{background-color:var(--color-surface);border:var(--border-width) solid var(--color-border-subtle);border-radius:var(--radius-md);color:var(--color-text);padding:var(--space-3) var(--space-3);transition:border-color .2s,background-color .2s,box-shadow .2s;width:100%}.input:focus{border-color:var(--color-accent)}.input:focus-visible{border-color:var(--focus-ring-color);box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color)}.input:hover{border-color:var(--color-border-strong)}.input--disabled,.input:disabled{background-color:var(--color-muted-bg);color:var(--color-text-muted);cursor:not-allowed}.input--readonly,.input[readonly]{background-color:var(--color-surface-subtle);border-style:dashed;color:var(--color-text-muted)}.input::-moz-placeholder{color:var(--color-placeholder);opacity:1}.input::placeholder{color:var(--color-placeholder);opacity:1}.input-icon{align-items:center;display:flex;position:relative;width:100%}.input-icon .input{width:100%}.input-icon--left .input{padding-left:var(--space-8)}.input-icon--both .input,.input-icon--right .input{padding-right:var(--space-8)}.input-icon--both .input{padding-left:var(--space-8)}.input-icon__icon{align-items:center;color:var(--color-text-muted);display:inline-flex;height:var(--icon-sm);justify-content:center;position:absolute;top:50%;transform:translateY(-50%);width:var(--icon-sm)}.input-icon--left .input-icon__icon{left:var(--space-3)}.input-icon--right .input-icon__icon{right:var(--space-3)}.textarea{background-color:var(--color-surface);border:var(--border-width) solid var(--color-border-subtle);border-radius:var(--radius-md);color:var(--color-text);min-height:var(--form-flow-textarea-min-height);padding:var(--space-3);resize:vertical;transition:border-color .2s,background-color .2s,box-shadow .2s;width:100%}.textarea:focus{border-color:var(--color-accent)}.textarea:focus-visible{border-color:var(--focus-ring-color);box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color)}.textarea:hover{border-color:var(--color-border-strong)}.textarea--disabled,.textarea:disabled{background-color:var(--color-muted-bg);color:var(--color-text-muted);cursor:not-allowed}.textarea--readonly,.textarea[readonly]{background-color:var(--color-surface-subtle);border-style:dashed;color:var(--color-text-muted)}.textarea::-moz-placeholder{color:var(--color-placeholder);opacity:1}.textarea::placeholder{color:var(--color-placeholder);opacity:1}.select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-surface);background-image:linear-gradient(45deg,transparent 50%,var(--color-text-muted) 50%),linear-gradient(135deg,var(--color-text-muted) 50%,transparent 50%);background-position:calc(100% - var(--space-3)),calc(100% - var(--space-2));background-repeat:no-repeat;background-size:.4rem .4rem;border:var(--border-width) solid var(--color-border-subtle);border-radius:var(--radius-md);color:var(--color-text);padding:var(--space-3) var(--space-4) var(--space-3) var(--space-3);padding-right:var(--space-6);position:relative;transition:border-color .2s,background-color .2s,box-shadow .2s;width:100%}.select:focus{border-color:var(--color-accent)}.select:focus-visible{border-color:var(--focus-ring-color);box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color)}.select:hover{border-color:var(--color-border-strong)}.select--disabled,.select:disabled{background-color:var(--color-muted-bg);background-image:linear-gradient(45deg,transparent 50%,var(--color-text-muted) 50%),linear-gradient(135deg,var(--color-text-muted) 50%,transparent 50%);color:var(--color-text-muted);cursor:not-allowed}.form-check{align-items:center;cursor:pointer;display:flex;font-size:var(--text-sm);gap:var(--space-2);margin-bottom:var(--space-3)}.form-check-group .form-check:last-child{margin-bottom:0}.form-check--disabled{cursor:not-allowed;opacity:.7}.form-check input{cursor:pointer;height:1.15rem;width:1.15rem}.checkbox{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-surface);border:var(--border-width) solid var(--color-border-subtle);border-radius:var(--radius-sm);cursor:pointer;position:relative;transition:border-color .2s,background-color .2s,box-shadow .2s}.checkbox:hover{border-color:var(--color-border-strong)}.checkbox:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color);outline:none}.checkbox:checked{background-color:var(--color-accent-soft);border-color:var(--color-accent)}.checkbox:checked:after{background-color:var(--color-accent);content:"";height:.55rem;left:50%;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m3 8 4 4 6-8'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m3 8 4 4 6-8'/%3E%3C/svg%3E");-webkit-mask-size:cover;mask-size:cover;position:absolute;top:50%;transform:translate(-50%,-50%);width:.55rem}.checkbox:disabled{background-color:var(--color-muted-bg);border-color:var(--color-muted-border);cursor:not-allowed}.checkbox--error{border-color:var(--color-danger)}.checkbox--warning{border-color:var(--color-warning)}.checkbox--success{border-color:var(--color-success)}.checkbox--info{border-color:var(--color-info)}.radio{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-surface);border:var(--border-width) solid var(--color-border-subtle);border-radius:50%;cursor:pointer;position:relative;transition:border-color .2s,background-color .2s,box-shadow .2s}.radio:hover{border-color:var(--color-border-strong)}.radio:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color);outline:none}.radio:checked{background-color:var(--color-accent-soft);border-color:var(--color-accent)}.radio:checked:after{background-color:var(--color-accent);border-radius:50%;content:"";height:.55rem;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:.55rem}.radio:disabled{background-color:var(--color-muted-bg);border-color:var(--color-muted-border);cursor:not-allowed}.radio--error{border-color:var(--color-danger)}.radio--warning{border-color:var(--color-warning)}.radio--success{border-color:var(--color-success)}.radio--info{border-color:var(--color-info)}.switch{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-surface);border:var(--border-width) solid var(--color-border-subtle);border-radius:50%;cursor:pointer;height:1.15rem;position:relative;transition:border-color .2s,background-color .2s,box-shadow .2s;width:1.15rem}.switch:after{background-color:var(--color-accent);border-radius:50%;content:"";height:.55rem;left:22%;opacity:0;position:absolute;top:22%;transform:translate(-50%,-50%);width:.55rem}.switch:checked{background-color:var(--color-accent-strong);border:var(--border-width) solid var(--color-accent)}.switch:checked:after{background-color:var(--color-accent);opacity:1;transform:scale(1)}.switch:disabled{cursor:not-allowed;opacity:.5}.switch:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color);outline:none}.switch--error{background-color:var(--color-danger-soft)}.switch--warning{background-color:var(--color-warning-soft)}.switch--success{background-color:var(--color-success-soft)}.switch--info{background-color:var(--color-info-soft)}.switch--error:checked{background-color:var(--color-danger)}.switch--warning:checked{background-color:var(--color-warning)}.switch--success:checked{background-color:var(--color-success)}.switch--info:checked{background-color:var(--color-info)}.input-group{align-items:center;background-color:var(--color-surface);border:var(--border-width) solid var(--color-border-subtle);border-radius:var(--radius-md);display:flex;overflow:hidden}.input-group .input{border:none;box-shadow:none;flex:1}.input-group-addon{align-items:center;background-color:var(--color-surface);border-right:var(--border-width) solid var(--color-border-subtle);color:var(--color-text-muted);display:flex;padding:0 var(--space-3)}.input-group-addon+.input{padding-left:var(--space-2)}.input-group-icon{align-items:center;color:var(--color-text-muted);display:flex;padding:0 var(--space-3)}.input-group-icon .icon{height:var(--icon-sm);width:var(--icon-sm)}.input-group--error{border-color:var(--color-danger)}.input-group--warning{border-color:var(--color-warning)}.input-group--success{border-color:var(--color-success)}.input-group--info{border-color:var(--color-info)}.input-group--disabled{opacity:.7;pointer-events:none}.input-group:focus-within{border-color:var(--focus-ring-color);box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color)}.input-group:hover{border-color:var(--color-border-strong)}.segmented{background-color:var(--color-surface);border:var(--border-width) solid var(--color-border-subtle);border-radius:var(--radius-md);display:flex;height:2.5rem;height:var(--control-height-md,2.5rem);overflow:hidden;width:100%}.segmented__option{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:var(--color-surface);border:none;color:var(--color-text-muted);cursor:pointer;display:inline-flex;flex:1 1 0;font:inherit;height:100%;justify-content:center;line-height:inherit;padding:var(--space-2) var(--space-4);text-align:center;transition:background-color .2s,color .2s;-webkit-user-select:none;-moz-user-select:none;user-select:none}.segmented__option:not(:last-child){border-right:var(--border-width) solid var(--color-border-subtle)}.segmented__option:hover{background-color:var(--color-surface-subtle);color:var(--color-text)}.segmented__option:focus-visible{box-shadow:inset 0 0 0 var(--border-width-strong) var(--focus-ring-color);outline:none}.segmented__option--active{background-color:var(--color-accent);color:var(--color-on-accent);font-weight:600;position:relative;z-index:1}.segmented__option--active+.segmented__option{border-left-color:transparent}.segmented--disabled{opacity:.6;pointer-events:none}.segmented__option--disabled{cursor:not-allowed;opacity:.7}.segmented__option-icon{height:var(--icon-sm);margin-right:var(--space-2);width:var(--icon-sm)}.segmented--error{border-color:var(--color-danger)}.segmented--warning{border-color:var(--color-warning)}.segmented--success{border-color:var(--color-success)}.segmented--info{border-color:var(--color-info)}.segmented--loading .segmented__option{overflow:hidden;position:relative}.segmented--loading .segmented__option:after{animation:input-loading-shimmer 1.5s infinite;background-image:linear-gradient(90deg,var(--color-muted-bg),var(--color-surface),var(--color-muted-bg));background-size:200% 100%;bottom:0;content:"";left:0;position:absolute;right:0;top:0}.slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--slider-track-bg);border-radius:var(--radius-sm);cursor:pointer;height:var(--border-width-strong);width:100%}.slider:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color);outline:none}.slider:disabled{cursor:not-allowed;opacity:.7}.slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background:var(--slider-thumb-bg);border-radius:50%;cursor:pointer;height:1rem;width:1rem}.slider::-moz-range-thumb{background:var(--slider-thumb-bg);border-radius:50%;cursor:pointer;height:1rem;width:1rem}.slider--error{box-shadow:0 0 0 var(--border-width-strong) var(--color-danger-soft)}.slider--error:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-danger);outline:none}.slider--warning{box-shadow:0 0 0 var(--border-width-strong) var(--color-warning-soft)}.slider--warning:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-warning);outline:none}.slider--success{box-shadow:0 0 0 var(--border-width-strong) var(--color-success-soft)}.slider--success:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-success);outline:none}.slider--info{box-shadow:0 0 0 var(--border-width-strong) var(--color-info-soft)}.slider--info:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-info);outline:none}.file-upload input{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.file-upload__control{background-color:var(--color-surface);border:var(--border-width) dashed var(--color-border-subtle);border-radius:var(--radius-md);color:var(--color-text-soft);cursor:pointer;padding:var(--space-4);text-align:center;transition:border-color .2s,background-color .2s,box-shadow .2s}.file-upload__control:hover{background-color:var(--color-surface-subtle);border-color:var(--color-border-strong)}.file-upload__control:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--focus-ring-color);outline:none}.file-upload__control--dragover{background-color:var(--color-accent-soft);border-color:var(--color-accent)}.file-upload__control--disabled{cursor:not-allowed;opacity:.7}.file-upload__control--error{background-color:var(--color-danger-soft);border-color:var(--color-danger);color:var(--color-danger-strong)}.file-upload__control--warning{background-color:var(--color-warning-soft);border-color:var(--color-warning);color:var(--color-warning-strong)}.file-upload__control--success{background-color:var(--color-success-soft);border-color:var(--color-success);color:var(--color-success-strong)}.file-upload__control--info{background-color:var(--color-info-soft);border-color:var(--color-info);color:var(--color-info-strong)}.file-upload__control--loading{animation:input-loading-shimmer 1.5s infinite;background-image:linear-gradient(90deg,var(--color-muted-bg),var(--color-surface),var(--color-muted-bg));background-size:200% 100%}.form-row{display:flex;flex-wrap:wrap;gap:var(--space-4)}.form-row--two{grid-template-columns:repeat(2,minmax(0,1fr))}.form-grid,.form-row--two{grid-gap:var(--space-4);display:grid;gap:var(--space-4)}.form-grid--two{grid-template-columns:repeat(2,minmax(0,1fr))}.form-grid--three{grid-template-columns:repeat(3,minmax(0,1fr))}.form-grid--four{grid-template-columns:repeat(4,minmax(0,1fr))}@media (max-width:768px){.form-grid--four,.form-grid--three,.form-grid--two{grid-template-columns:1fr}}.input--error,.select--error,.textarea--error{border-color:var(--color-danger)}.input--error:focus-visible,.select--error:focus-visible,.textarea--error:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-danger-soft)}.input--success,.select--success,.textarea--success{border-color:var(--color-success)}.input--success:focus-visible,.select--success:focus-visible,.textarea--success:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-success-soft)}.input--warning,.select--warning,.textarea--warning{border-color:var(--color-warning)}.input--warning:focus-visible,.select--warning:focus-visible,.textarea--warning:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-warning-soft)}.input--info,.select--info,.textarea--info{border-color:var(--color-info)}.input--info:focus-visible,.select--info:focus-visible,.textarea--info:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-info-soft)}.form-meta{align-items:flex-start;display:flex;gap:var(--form-flow-gap-xs);justify-content:space-between;margin-top:var(--space-1)}.form-meta--stacked{align-items:flex-start;flex-direction:column}.form-meta--inline{align-items:center;flex-direction:row}.form-meta__messages{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}.form-counter{color:var(--color-text-muted);font-family:var(--font-family-mono),monospace;font-size:var(--text-xs);margin-left:auto;white-space:nowrap}.form-counter--warning{color:var(--color-warning)}.form-counter--danger,.form-field--error .form-counter{color:var(--color-danger)}.form-control-with-icon{display:inline-flex;position:relative;width:100%}.form-control-with-icon .input,.form-control-with-icon .select,.form-control-with-icon .textarea{padding-right:calc(var(--space-8) + var(--space-1));width:100%}.form-status-icon{align-items:center;color:var(--color-text-muted);display:inline-flex;height:var(--icon-sm);justify-content:center;pointer-events:none;position:absolute;right:var(--space-3);top:50%;transform:translateY(-50%);width:var(--icon-sm)}.form-field--error .form-status-icon{color:var(--color-danger)}.form-field--success .form-status-icon{color:var(--color-success)}.form-field--warning .form-status-icon{color:var(--color-warning)}.form-field--info .form-status-icon{color:var(--color-info)}.form-field--success .form-label{color:var(--color-success)}.form-field--success .input,.form-field--success .input-group,.form-field--success .select,.form-field--success .textarea{border-color:var(--color-success)}.form-field--warning .form-label{color:var(--color-warning)}.form-field--warning .input,.form-field--warning .input-group,.form-field--warning .select,.form-field--warning .textarea{border-color:var(--color-warning)}.form-field--info .form-label{color:var(--color-info)}.form-field--info .input,.form-field--info .input-group,.form-field--info .select,.form-field--info .textarea{border-color:var(--color-info)}.form-field--horizontal{grid-column-gap:var(--space-4);align-items:flex-start;-moz-column-gap:var(--space-4);column-gap:var(--space-4);display:grid;grid-template-columns:minmax(0,12rem) minmax(0,1fr)}.form-field__label{padding-top:var(--space-1)}.form-field__control{display:flex;flex-direction:column;gap:var(--form-flow-gap-xs)}@media (max-width:768px){.form-field--horizontal{grid-template-columns:1fr}.form-field__label{padding-top:0}}.input--loading,.select--loading,.textarea--loading{animation:input-loading-shimmer 1.5s infinite;background-image:linear-gradient(90deg,var(--color-muted-bg),var(--color-surface),var(--color-muted-bg));background-size:200% 100%}@keyframes input-loading-shimmer{0%{background-position:-150% 0}to{background-position:150% 0}}.modal .form-field{margin-bottom:var(--space-3)}.form-message{align-items:flex-start;background-color:var(--color-surface-subtle);border:var(--border-width) solid var(--color-border-subtle);border-radius:var(--radius-md);display:flex;font-size:var(--text-sm);gap:var(--space-3);padding:var(--space-4) var(--space-6);width:100%}.form-message__icon{stroke:currentColor;fill:none;flex-shrink:0;height:1.25rem;width:1.25rem}.form-message__content{display:flex;flex-direction:column;gap:var(--space-1)}.form-message--neutral{background-color:var(--color-muted-bg);border-color:var(--color-muted-border);color:var(--color-text-muted)}.form-message--error{background-color:var(--semantic-error-bg-strong,var(--color-danger-soft));border-color:var(--semantic-error-border-strong,var(--color-danger));color:var(--semantic-error-text-strong,var(--color-danger-strong))}.form-message--info{background-color:var(--semantic-info-bg-strong,var(--color-info-soft));border-color:var(--semantic-info-border-strong,var(--color-info));color:var(--semantic-info-text-strong,var(--color-info-strong))}.form-message--success{background-color:var(--semantic-success-bg-strong,var(--color-success-soft));border-color:var(--semantic-success-border-strong,var(--color-success));color:var(--semantic-success-text-strong,var(--color-success-strong))}.form-message--warning{background-color:var(--semantic-warning-bg-strong,var(--color-warning-soft));border-color:var(--semantic-warning-border-strong,var(--color-warning));color:var(--semantic-warning-text-strong,var(--color-warning-strong))}.form-field-message{align-items:center;display:flex;font-size:var(--text-xs);gap:var(--space-1);margin-top:var(--space-1)}.form-field-message--neutral{color:var(--color-text-muted)}.form-field-message--error{color:var(--semantic-error-text-strong,var(--color-danger-strong))}.form-field-message--warning{color:var(--semantic-warning-text-strong,var(--color-warning-strong))}.form-field-message--info{color:var(--semantic-info-text-strong,var(--color-info-strong))}.form-field-message--success{color:var(--semantic-success-text-strong,var(--color-success-strong))}.form-field-message__icon{stroke:currentColor;fill:none;flex-shrink:0;height:1rem;width:1rem}.form-check-inline{align-items:center;cursor:pointer;display:inline-flex;gap:var(--space-2);margin-right:var(--space-6)}.form-check-group{align-items:flex-start;display:flex;flex-direction:column;gap:var(--space-1)}.form-check-group--horizontal{align-items:center;flex-direction:row;flex-wrap:wrap;gap:var(--space-6)}.form-check-group--horizontal .form-check{margin-bottom:var(--space-2);margin-right:var(--space-6)}.form-section--error{background-color:transparent;background-color:var(--semantic-error-bg-strong,transparent);border-left:var(--border-width-strong) solid var(--semantic-error-border-strong,var(--color-danger));padding:var(--space-3)}.form-section--warning{background-color:transparent;background-color:var(--semantic-warning-bg-strong,transparent);border-left:var(--border-width-strong) solid var(--semantic-warning-border-strong,var(--color-warning));padding:var(--space-3)}.form-section--success{background-color:transparent;background-color:var(--semantic-success-bg-strong,transparent);border-left:var(--border-width-strong) solid var(--semantic-success-border-strong,var(--color-success));padding:var(--space-3)}.form-section--info{background-color:transparent;background-color:var(--semantic-info-bg-strong,transparent);border-left:var(--border-width-strong) solid var(--semantic-info-border-strong,var(--color-info));padding:var(--space-3)}.form-section--error:not(:last-child),.form-section--info:not(:last-child),.form-section--success:not(:last-child),.form-section--warning:not(:last-child){margin-bottom:var(--space-4)}.input[aria-invalid=true],.select[aria-invalid=true],.textarea[aria-invalid=true]{border-color:var(--color-danger)}.input[aria-invalid=true]:focus-visible,.select[aria-invalid=true]:focus-visible,.textarea[aria-invalid=true]:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--color-danger-soft)}.form-control{box-sizing:border-box;display:block;margin:0;min-height:var(--control-min-height);width:100%}.form-control-wrapper{align-items:center;display:flex;position:relative;width:100%}.form-control-wrapper>.form-control{flex:1 1 auto}.form-control--loading{cursor:progress;opacity:.55;pointer-events:none}.form-control--disabled{opacity:.45;pointer-events:none}.form-control--readonly{cursor:default;opacity:.75}.form-control--error{box-shadow:0 0 0 var(--border-width-strong) var(--color-danger)}.form-control--warning{box-shadow:0 0 0 var(--border-width-strong) var(--color-warning)}.form-control--success{box-shadow:0 0 0 var(--border-width-strong) var(--color-success)}.form-control--info{box-shadow:0 0 0 var(--border-width-strong) var(--color-info)}.form-control--password,.form-control-wrapper[data-icon=right] .form-control--password{padding-right:calc(var(--space-8) + var(--space-2))}.form-control--password:focus{border-color:var(--color-accent)}.form-control--password::-moz-placeholder{color:var(--color-placeholder)}.form-control--password::placeholder{color:var(--color-placeholder)}.form-control-wrapper[data-icon=left] .form-control{padding-left:calc(var(--space-7) + var(--space-2))}.form-control-wrapper[data-icon=left] .form-control-icon{align-items:center;display:flex;left:var(--space-2);position:absolute}.form-control-wrapper[data-icon=right] .form-control{padding-right:calc(var(--space-7) + var(--space-2))}.form-control-wrapper[data-icon=right] .form-control-icon{align-items:center;display:flex;position:absolute;right:var(--space-2)}.form-control-icon{color:var(--color-text-muted);font-size:var(--text-md);pointer-events:none}.form-control--loading:after{animation:formControlLoading 1.5s ease-in-out infinite;background:var(--color-surface-subtle);border-radius:inherit;bottom:0;content:"";left:0;position:absolute;right:0;top:0}@keyframes formControlLoading{0%{opacity:.35}50%{opacity:.6}to{opacity:.35}}.form-control--file{background-color:var(--color-surface);border:var(--border-width) dashed var(--color-border-subtle);border-radius:var(--radius-md);color:var(--color-text-muted);cursor:pointer;padding:var(--space-3);position:relative;transition:border-color .2s,background-color .2s}.form-control--file[type=file]{background:none;border:none;opacity:1;padding:0;position:static}.form-control-file-surface{align-items:center;background-color:var(--color-surface);border:var(--border-width) dashed var(--color-border-subtle);border-radius:var(--radius-md);cursor:pointer;display:flex;flex-direction:column;gap:var(--space-2);justify-content:center;padding:var(--space-6);position:relative;transition:border-color .2s,background-color .2s}.form-control-file-surface input[type=file]{bottom:0;cursor:pointer;left:0;opacity:0;position:absolute;right:0;top:0}.form-control-file-surface:hover{background-color:var(--color-surface-subtle);border-color:var(--color-border-strong)}.form-control-file-surface--dragover{background-color:var(--color-accent-soft);border-color:var(--color-accent)}.form-control-file-surface--disabled{cursor:not-allowed;opacity:.65}.form-control-file-surface--error{background-color:var(--color-danger-soft);border-color:var(--color-danger)}.form-control-file-surface--warning{background-color:var(--color-warning-soft);border-color:var(--color-warning)}.form-control-file-surface--success{background-color:var(--color-success-soft);border-color:var(--color-success)}.form-control-file-surface--info{background-color:var(--color-info-soft);border-color:var(--color-info)}.file-upload-inline{align-items:center;display:inline-flex;gap:var(--space-2)}.file-upload-inline__input{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.file-upload-inline__label{align-items:center;cursor:pointer;display:inline-flex;justify-content:center}.file-upload,.file-upload *{box-sizing:border-box}.file-upload{display:flex;flex-direction:column;gap:var(--space-2);width:100%}.form-control-file-surface.form-control--loading:after{animation:input-loading-shimmer 1.5s infinite;background-image:linear-gradient(90deg,var(--color-muted-bg),var(--color-surface),var(--color-muted-bg));background-size:200% 100%;border-radius:inherit;bottom:0;content:"";left:0;position:absolute;right:0;top:0}.form-control-file-icon{color:var(--color-text-muted);font-size:var(--text-lg)}.form-control-file-label{color:var(--color-text);font-size:var(--text-sm)}.form-control-file-hint{color:var(--color-text-muted);font-size:var(--text-xs)}.form-control--error:focus-visible,.input[aria-invalid=true]:focus-visible,.select[aria-invalid=true]:focus-visible,.slider--error:focus-visible,.textarea[aria-invalid=true]:focus-visible{box-shadow:0 0 0 var(--border-width-strong) var(--semantic-error-border-strong,var(--color-danger))}.checkbox:checked,.radio:checked,.switch:checked{background-color:var(--accent-soft-surface,var(--color-accent-soft));border-color:var(--accent-soft-border,var(--color-accent));box-shadow:0 0 0 1px transparent;box-shadow:0 0 0 1px var(--accent-soft-shadow,transparent);color:var(--accent-soft-on,var(--color-on-accent))}.checkbox:checked:after,.radio:checked:after,.switch:checked:after{background-color:var(--accent-soft-border,var(--color-accent))}.checkbox:checked:hover,.radio:checked:hover,.switch:checked:hover{background-color:var(--accent-soft-surface-strong,var(--accent-soft-surface));border-color:var(--accent-soft-border,var(--color-accent))}.checkbox:checked:disabled,.radio:checked:disabled,.switch:checked:disabled{background-color:var(--color-surface-subtle);border-color:var(--color-border-subtle);opacity:.6}