@dsrc-cm/core 0.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.
Files changed (51) hide show
  1. package/dist/dsrc.css +10743 -0
  2. package/dist/dsrc.min.css +1 -0
  3. package/package.json +44 -0
  4. package/src/base/print.css +404 -0
  5. package/src/base/reset.css +106 -0
  6. package/src/components/accordion/accordion.css +216 -0
  7. package/src/components/alert/alert.css +187 -0
  8. package/src/components/badge/badge.css +178 -0
  9. package/src/components/breadcrumb/breadcrumb.css +235 -0
  10. package/src/components/button/button.css +805 -0
  11. package/src/components/callout/callout.css +95 -0
  12. package/src/components/card/card.css +551 -0
  13. package/src/components/checkbox/checkbox.css +257 -0
  14. package/src/components/consent/consent.css +297 -0
  15. package/src/components/download/download.css +66 -0
  16. package/src/components/dropdown/dropdown.css +295 -0
  17. package/src/components/highlight/highlight.css +74 -0
  18. package/src/components/input/input.css +337 -0
  19. package/src/components/label/label.css +29 -0
  20. package/src/components/link/link.css +208 -0
  21. package/src/components/logo/logo.css +86 -0
  22. package/src/components/modal/modal.css +271 -0
  23. package/src/components/notice/notice.css +211 -0
  24. package/src/components/pagination/pagination.css +132 -0
  25. package/src/components/password/password.css +195 -0
  26. package/src/components/quote/quote.css +156 -0
  27. package/src/components/radio/radio.css +270 -0
  28. package/src/components/range/range.css +362 -0
  29. package/src/components/search/search.css +129 -0
  30. package/src/components/select/select.css +130 -0
  31. package/src/components/sidemenu/sidemenu.css +268 -0
  32. package/src/components/spinner/spinner.css +73 -0
  33. package/src/components/stepper/stepper.css +140 -0
  34. package/src/components/summary/summary.css +142 -0
  35. package/src/components/tab/tab.css +184 -0
  36. package/src/components/table/table.css +556 -0
  37. package/src/components/tag/tag.css +201 -0
  38. package/src/components/tile/tile.css +389 -0
  39. package/src/components/toggle/toggle.css +229 -0
  40. package/src/components/tooltip/tooltip.css +158 -0
  41. package/src/components/translate/translate.css +356 -0
  42. package/src/components/upload/upload.css +185 -0
  43. package/src/index.css +77 -0
  44. package/src/layout/bandeau/bandeau.css +44 -0
  45. package/src/layout/entete/entete.css +130 -0
  46. package/src/layout/footer/footer.css +107 -0
  47. package/src/layout/grid/grid.css +197 -0
  48. package/src/layout/hero/hero.css +86 -0
  49. package/src/layout/main/main.css +123 -0
  50. package/src/layout/navigation/navigation.css +206 -0
  51. package/src/utilities/utilities.css +430 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * DSRC Dropdown Component
3
+ *
4
+ * A dropdown menu triggered by a button. Visibility is controlled
5
+ * via the [aria-expanded] attribute on the trigger element.
6
+ *
7
+ * Usage:
8
+ * <div class="dsrc-dropdown">
9
+ * <button class="dsrc-dropdown__trigger" aria-expanded="false" aria-haspopup="true">
10
+ * Menu
11
+ * </button>
12
+ * <ul class="dsrc-dropdown__menu" role="menu">
13
+ * <li><a class="dsrc-dropdown__item" role="menuitem" href="#">Option 1</a></li>
14
+ * <li><a class="dsrc-dropdown__item" role="menuitem" href="#">Option 2</a></li>
15
+ * <li class="dsrc-dropdown__divider" role="separator"></li>
16
+ * <li><a class="dsrc-dropdown__item" role="menuitem" href="#">Option 3</a></li>
17
+ * </ul>
18
+ * </div>
19
+ *
20
+ * Variants:
21
+ * .dsrc-dropdown--up (opens upward)
22
+ * .dsrc-dropdown--right (aligns menu to right edge)
23
+ */
24
+
25
+ /* ============================================
26
+ * Container
27
+ * ============================================ */
28
+ .dsrc-dropdown {
29
+ position: relative;
30
+ display: inline-block;
31
+ }
32
+
33
+ /* ============================================
34
+ * Trigger button
35
+ * ============================================ */
36
+ .dsrc-dropdown__trigger {
37
+ display: inline-flex;
38
+ align-items: center;
39
+ gap: var(--dsrc-spacing-2);
40
+ font-family: var(--dsrc-font-family-sans);
41
+ font-size: var(--dsrc-font-size-small);
42
+ font-weight: var(--dsrc-font-weight-medium);
43
+ line-height: 1;
44
+ padding: var(--dsrc-spacing-2) var(--dsrc-spacing-4);
45
+ border-radius: var(--dsrc-radius-default);
46
+ border: var(--dsrc-border-width-default) solid var(--dsrc-color-gris-200);
47
+ background-color: var(--dsrc-color-blanc);
48
+ color: var(--dsrc-color-noir);
49
+ cursor: pointer;
50
+ white-space: nowrap;
51
+ transition: border-color var(--dsrc-transition-duration-fast) ease,
52
+ background-color var(--dsrc-transition-duration-fast) ease;
53
+ }
54
+
55
+ /* Chevron indicator */
56
+ .dsrc-dropdown__trigger::after {
57
+ content: '';
58
+ display: inline-block;
59
+ width: 8px;
60
+ height: 8px;
61
+ border-right: var(--dsrc-border-width-default) solid var(--dsrc-color-gris-600);
62
+ border-bottom: var(--dsrc-border-width-default) solid var(--dsrc-color-gris-600);
63
+ transform: rotate(45deg);
64
+ transition: transform var(--dsrc-transition-duration-normal) ease;
65
+ margin-top: -2px;
66
+ flex-shrink: 0;
67
+ }
68
+
69
+ .dsrc-dropdown__trigger:hover {
70
+ border-color: var(--dsrc-color-gris-400);
71
+ background-color: var(--dsrc-color-gris-50);
72
+ }
73
+
74
+ .dsrc-dropdown__trigger:focus-visible {
75
+ outline: var(--dsrc-outline-width) solid var(--dsrc-color-primaire-focus);
76
+ outline-offset: var(--dsrc-outline-offset);
77
+ }
78
+
79
+ .dsrc-dropdown__trigger:active {
80
+ background-color: var(--dsrc-color-gris-100);
81
+ }
82
+
83
+ /* Rotate chevron when expanded */
84
+ .dsrc-dropdown__trigger[aria-expanded="true"]::after {
85
+ transform: rotate(-135deg);
86
+ margin-top: 2px;
87
+ }
88
+
89
+ .dsrc-dropdown__trigger[aria-expanded="true"] {
90
+ border-color: var(--dsrc-color-primaire);
91
+ background-color: var(--dsrc-color-blanc);
92
+ }
93
+
94
+ /* ============================================
95
+ * Menu panel
96
+ * ============================================ */
97
+ .dsrc-dropdown__menu {
98
+ position: absolute;
99
+ top: calc(100% + var(--dsrc-spacing-1));
100
+ left: 0;
101
+ min-width: 200px;
102
+ max-height: 320px;
103
+ overflow-y: auto;
104
+ padding: var(--dsrc-spacing-1) 0;
105
+ margin: 0;
106
+ list-style: none;
107
+ background-color: var(--dsrc-color-blanc);
108
+ border: var(--dsrc-border-width-thin) solid var(--dsrc-color-gris-200);
109
+ border-radius: var(--dsrc-radius-default);
110
+ box-shadow: var(--dsrc-shadow-lg);
111
+ z-index: var(--dsrc-z-index-tooltip);
112
+ font-family: var(--dsrc-font-family-sans);
113
+
114
+ /* Hidden by default */
115
+ opacity: 0;
116
+ visibility: hidden;
117
+ transform: translateY(-4px);
118
+ transition: opacity var(--dsrc-transition-duration-normal) ease,
119
+ transform var(--dsrc-transition-duration-normal) ease,
120
+ visibility 0s linear var(--dsrc-transition-duration-normal);
121
+ }
122
+
123
+ /* Shown when trigger is expanded */
124
+ .dsrc-dropdown__trigger[aria-expanded="true"] + .dsrc-dropdown__menu,
125
+ .dsrc-dropdown__trigger[aria-expanded="true"] ~ .dsrc-dropdown__menu {
126
+ opacity: 1;
127
+ visibility: visible;
128
+ transform: translateY(0);
129
+ transition: opacity var(--dsrc-transition-duration-normal) ease,
130
+ transform var(--dsrc-transition-duration-normal) ease,
131
+ visibility 0s linear 0s;
132
+ }
133
+
134
+ /* ============================================
135
+ * Menu items
136
+ * ============================================ */
137
+ .dsrc-dropdown__item {
138
+ display: flex;
139
+ align-items: center;
140
+ gap: var(--dsrc-spacing-2);
141
+ padding: var(--dsrc-spacing-2) var(--dsrc-spacing-4);
142
+ font-size: var(--dsrc-font-size-small);
143
+ font-weight: var(--dsrc-font-weight-regular);
144
+ color: var(--dsrc-color-noir);
145
+ text-decoration: none;
146
+ cursor: pointer;
147
+ white-space: nowrap;
148
+ transition: background-color var(--dsrc-transition-duration-fast) ease,
149
+ color var(--dsrc-transition-duration-fast) ease;
150
+ }
151
+
152
+ .dsrc-dropdown__item:hover {
153
+ background-color: var(--dsrc-color-gris-50);
154
+ color: var(--dsrc-color-noir);
155
+ }
156
+
157
+ .dsrc-dropdown__item:focus-visible {
158
+ outline: var(--dsrc-outline-width) solid var(--dsrc-color-primaire-focus);
159
+ outline-offset: calc(-1 * var(--dsrc-outline-offset));
160
+ background-color: var(--dsrc-color-gris-50);
161
+ }
162
+
163
+ .dsrc-dropdown__item:active {
164
+ background-color: var(--dsrc-color-gris-100);
165
+ }
166
+
167
+ /* Active / current item */
168
+ .dsrc-dropdown__item[aria-current="true"] {
169
+ background-color: var(--dsrc-color-primaire-clair);
170
+ color: var(--dsrc-color-primaire);
171
+ font-weight: var(--dsrc-font-weight-medium);
172
+ }
173
+
174
+ .dsrc-dropdown__item[aria-current="true"]:hover {
175
+ background-color: var(--dsrc-color-primaire-clair);
176
+ color: var(--dsrc-color-primaire-fonce);
177
+ }
178
+
179
+ /* Disabled item */
180
+ .dsrc-dropdown__item[aria-disabled="true"] {
181
+ color: var(--dsrc-color-gris-400);
182
+ cursor: not-allowed;
183
+ pointer-events: none;
184
+ }
185
+
186
+ /* ============================================
187
+ * Divider
188
+ * ============================================ */
189
+ .dsrc-dropdown__divider {
190
+ height: 0;
191
+ margin: var(--dsrc-spacing-1) 0;
192
+ border: none;
193
+ border-top: var(--dsrc-border-width-thin) solid var(--dsrc-color-gris-200);
194
+ }
195
+
196
+ /* ============================================
197
+ * Variant: opens upward
198
+ * ============================================ */
199
+ .dsrc-dropdown--up .dsrc-dropdown__menu {
200
+ top: auto;
201
+ bottom: calc(100% + var(--dsrc-spacing-1));
202
+ transform: translateY(4px);
203
+ }
204
+
205
+ .dsrc-dropdown--up .dsrc-dropdown__trigger[aria-expanded="true"] + .dsrc-dropdown__menu,
206
+ .dsrc-dropdown--up .dsrc-dropdown__trigger[aria-expanded="true"] ~ .dsrc-dropdown__menu {
207
+ transform: translateY(0);
208
+ }
209
+
210
+ /* Flip chevron for upward variant */
211
+ .dsrc-dropdown--up .dsrc-dropdown__trigger::after {
212
+ transform: rotate(-135deg);
213
+ margin-top: 2px;
214
+ }
215
+
216
+ .dsrc-dropdown--up .dsrc-dropdown__trigger[aria-expanded="true"]::after {
217
+ transform: rotate(45deg);
218
+ margin-top: -2px;
219
+ }
220
+
221
+ /* ============================================
222
+ * Variant: align menu to right edge
223
+ * ============================================ */
224
+ .dsrc-dropdown--right .dsrc-dropdown__menu {
225
+ left: auto;
226
+ right: 0;
227
+ }
228
+
229
+ /* ============================================
230
+ * Variant: full-width menu (matches trigger)
231
+ * ============================================ */
232
+ .dsrc-dropdown--full .dsrc-dropdown__menu {
233
+ min-width: 100%;
234
+ }
235
+
236
+
237
+ /* ============================================
238
+ * High contrast (forced-colors)
239
+ * ============================================ */
240
+
241
+ @media (forced-colors: active) {
242
+ .dsrc-dropdown__trigger {
243
+ border: 1px solid ButtonText;
244
+ }
245
+
246
+ .dsrc-dropdown__trigger::after {
247
+ border-right-color: ButtonText;
248
+ border-bottom-color: ButtonText;
249
+ }
250
+
251
+ .dsrc-dropdown__menu {
252
+ border: 1px solid ButtonText;
253
+ box-shadow: none;
254
+ }
255
+
256
+ .dsrc-dropdown__item[aria-current="true"] {
257
+ border: 1px solid Highlight;
258
+ }
259
+
260
+ .dsrc-dropdown__item[aria-disabled="true"] {
261
+ color: GrayText;
262
+ }
263
+
264
+ .dsrc-dropdown__item:focus-visible {
265
+ outline: 2px solid Highlight;
266
+ }
267
+ }
268
+
269
+
270
+ /* ============================================
271
+ * Reduced motion
272
+ * ============================================ */
273
+
274
+ @media (prefers-reduced-motion: reduce) {
275
+ .dsrc-dropdown__trigger {
276
+ transition: none;
277
+ }
278
+
279
+ .dsrc-dropdown__trigger::after {
280
+ transition: none;
281
+ }
282
+
283
+ .dsrc-dropdown__menu {
284
+ transition: none;
285
+ }
286
+
287
+ .dsrc-dropdown__trigger[aria-expanded="true"] + .dsrc-dropdown__menu,
288
+ .dsrc-dropdown__trigger[aria-expanded="true"] ~ .dsrc-dropdown__menu {
289
+ transition: none;
290
+ }
291
+
292
+ .dsrc-dropdown__item {
293
+ transition: none;
294
+ }
295
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * DSRC Highlight Component
3
+ *
4
+ * Emphasized text block with a colored left accent line.
5
+ * Simpler than callout — used for inline content emphasis.
6
+ *
7
+ * Variants:
8
+ * --info / --success / --warning / --error (semantic colors)
9
+ *
10
+ * Usage:
11
+ * <div class="dsrc-highlight">
12
+ * <p>Texte mis en exergue pour attirer l'attention.</p>
13
+ * </div>
14
+ */
15
+
16
+
17
+ /* ============================================
18
+ * 1. Base highlight
19
+ * ============================================ */
20
+
21
+ .dsrc-highlight {
22
+ padding-left: var(--dsrc-spacing-5);
23
+ border-left: 4px solid var(--dsrc-color-primaire);
24
+ font-family: var(--dsrc-font-family-sans);
25
+ font-size: var(--dsrc-font-size-body);
26
+ line-height: 1.5;
27
+ }
28
+
29
+ .dsrc-highlight p {
30
+ margin: 0;
31
+ }
32
+
33
+
34
+ /* ============================================
35
+ * 2. Semantic variants
36
+ * ============================================ */
37
+
38
+ .dsrc-highlight--info {
39
+ border-left-color: var(--dsrc-color-info-bordure);
40
+ }
41
+
42
+ .dsrc-highlight--success {
43
+ border-left-color: var(--dsrc-color-succes-bordure);
44
+ }
45
+
46
+ .dsrc-highlight--warning {
47
+ border-left-color: var(--dsrc-color-avertissement-bordure);
48
+ }
49
+
50
+ .dsrc-highlight--error {
51
+ border-left-color: var(--dsrc-color-erreur-bordure);
52
+ }
53
+
54
+
55
+ /* ============================================
56
+ * 3. High contrast (forced-colors)
57
+ * ============================================ */
58
+
59
+ @media (forced-colors: active) {
60
+ .dsrc-highlight {
61
+ border-left: 4px solid ButtonText;
62
+ }
63
+ }
64
+
65
+
66
+ /* ============================================
67
+ * 4. Print
68
+ * ============================================ */
69
+
70
+ @media print {
71
+ .dsrc-highlight {
72
+ border-left: 2px solid var(--dsrc-color-gris-600);
73
+ }
74
+ }
@@ -0,0 +1,337 @@
1
+ /**
2
+ * DSRC Input Component
3
+ * Aligned with DSFR input-group architecture
4
+ *
5
+ * The input system uses a group wrapper (.dsrc-input-group) that manages
6
+ * layout, validation states (error/valid left bar), and messages.
7
+ *
8
+ * HTML patterns:
9
+ *
10
+ * Basic input:
11
+ * <div class="dsrc-input-group">
12
+ * <label class="dsrc-label" for="input-1">
13
+ * Libelle du champ
14
+ * <span class="dsrc-hint">Texte d'aide optionnel</span>
15
+ * </label>
16
+ * <input class="dsrc-input" id="input-1" type="text">
17
+ * <div class="dsrc-messages-group" aria-live="polite"></div>
18
+ * </div>
19
+ *
20
+ * Error state:
21
+ * <div class="dsrc-input-group dsrc-input-group--error">
22
+ * <label class="dsrc-label" for="input-2">Libelle</label>
23
+ * <input class="dsrc-input" id="input-2" type="text" aria-describedby="input-2-msg">
24
+ * <div class="dsrc-messages-group" id="input-2-msg" aria-live="polite">
25
+ * <p class="dsrc-message dsrc-message--error">Ce champ est obligatoire</p>
26
+ * </div>
27
+ * </div>
28
+ *
29
+ * Valid state:
30
+ * <div class="dsrc-input-group dsrc-input-group--valid">
31
+ * <label class="dsrc-label" for="input-3">Libelle</label>
32
+ * <input class="dsrc-input" id="input-3" type="text">
33
+ * <div class="dsrc-messages-group" aria-live="polite">
34
+ * <p class="dsrc-message dsrc-message--valid">Champ valide</p>
35
+ * </div>
36
+ * </div>
37
+ *
38
+ * Disabled:
39
+ * <div class="dsrc-input-group dsrc-input-group--disabled">
40
+ * <label class="dsrc-label" for="input-4">Libelle</label>
41
+ * <input class="dsrc-input" id="input-4" type="text" disabled>
42
+ * </div>
43
+ *
44
+ * With addon button:
45
+ * <div class="dsrc-input-group">
46
+ * <label class="dsrc-label" for="input-5">Libelle</label>
47
+ * <div class="dsrc-input-wrap dsrc-input-wrap--addon">
48
+ * <input class="dsrc-input" id="input-5" type="text">
49
+ * <button type="submit" class="dsrc-btn dsrc-btn--primary">Envoyer</button>
50
+ * </div>
51
+ * </div>
52
+ *
53
+ * Textarea:
54
+ * <div class="dsrc-input-group">
55
+ * <label class="dsrc-label" for="textarea-1">Libelle</label>
56
+ * <textarea class="dsrc-input" id="textarea-1"></textarea>
57
+ * </div>
58
+ */
59
+
60
+
61
+ /* ============================================
62
+ * 1. Input-group wrapper
63
+ * Manages vertical layout, left-bar states
64
+ * ============================================ */
65
+
66
+ .dsrc-input-group {
67
+ display: flex;
68
+ flex-direction: column;
69
+ gap: var(--dsrc-spacing-1);
70
+ margin-bottom: var(--dsrc-spacing-4);
71
+ }
72
+
73
+
74
+ /* ============================================
75
+ * 2. Hint text (below label, lighter)
76
+ * ============================================ */
77
+
78
+ .dsrc-hint {
79
+ display: block;
80
+ font-weight: 400;
81
+ font-size: var(--dsrc-font-size-caption);
82
+ line-height: var(--dsrc-font-line-height-relaxed);
83
+ color: var(--dsrc-color-gris-600);
84
+ margin-top: var(--dsrc-spacing-1);
85
+ }
86
+
87
+
88
+ /* ============================================
89
+ * 3. Input base
90
+ * DSFR-style: top-only border-radius,
91
+ * bottom border thicker for affordance
92
+ * ============================================ */
93
+
94
+ .dsrc-input {
95
+ display: block;
96
+ width: 100%;
97
+ font-family: var(--dsrc-font-family-sans);
98
+ font-size: var(--dsrc-font-size-body);
99
+ line-height: var(--dsrc-font-line-height-normal);
100
+ padding: var(--dsrc-spacing-2) var(--dsrc-spacing-3);
101
+ border: var(--dsrc-border-width-thin) solid var(--dsrc-color-gris-200);
102
+ border-bottom-width: var(--dsrc-border-width-default);
103
+ border-radius: 0.25rem 0.25rem 0 0;
104
+ background-color: var(--dsrc-color-gris-50);
105
+ color: var(--dsrc-color-noir);
106
+ outline: none;
107
+ transition:
108
+ border-color var(--dsrc-transition-duration-fast) ease,
109
+ box-shadow var(--dsrc-transition-duration-fast) ease;
110
+ }
111
+
112
+ .dsrc-input::placeholder {
113
+ color: var(--dsrc-color-gris-400);
114
+ }
115
+
116
+
117
+ /* ============================================
118
+ * 4. Input hover
119
+ * ============================================ */
120
+
121
+ .dsrc-input:hover {
122
+ border-color: var(--dsrc-color-gris-400);
123
+ }
124
+
125
+
126
+ /* ============================================
127
+ * 5. Input focus
128
+ * ============================================ */
129
+
130
+ .dsrc-input:focus-visible {
131
+ border-color: var(--dsrc-color-primaire);
132
+ box-shadow: 0 0 0 var(--dsrc-outline-width) var(--dsrc-color-primaire-focus);
133
+ }
134
+
135
+
136
+ /* ============================================
137
+ * 6. Textarea
138
+ * Inherits .dsrc-input styling, adds resize
139
+ * ============================================ */
140
+
141
+ textarea.dsrc-input {
142
+ min-height: 100px;
143
+ resize: vertical;
144
+ border-radius: 0.25rem 0.25rem 0 0;
145
+ }
146
+
147
+
148
+ /* ============================================
149
+ * 7. Disabled state
150
+ * Applied on group wrapper AND native disabled
151
+ * ============================================ */
152
+
153
+ .dsrc-input:disabled,
154
+ .dsrc-input-group--disabled .dsrc-input {
155
+ background-color: var(--dsrc-color-gris-100);
156
+ color: var(--dsrc-color-gris-600);
157
+ border-color: var(--dsrc-color-gris-200);
158
+ cursor: not-allowed;
159
+ }
160
+
161
+ .dsrc-input-group--disabled .dsrc-label {
162
+ color: var(--dsrc-color-gris-400);
163
+ }
164
+
165
+
166
+ /* ============================================
167
+ * 8. Error state (DSFR left-bar pattern)
168
+ * Red left border on wrapper, red bottom
169
+ * border on input, red messages
170
+ * ============================================ */
171
+
172
+ .dsrc-input-group--error {
173
+ border-left: var(--dsrc-border-width-thick) solid var(--dsrc-color-erreur-bordure);
174
+ padding-left: var(--dsrc-spacing-4);
175
+ }
176
+
177
+ .dsrc-input-group--error .dsrc-input {
178
+ border-color: var(--dsrc-color-erreur-bordure);
179
+ }
180
+
181
+ .dsrc-input-group--error .dsrc-input:focus-visible {
182
+ border-color: var(--dsrc-color-erreur-bordure);
183
+ box-shadow: 0 0 0 var(--dsrc-outline-width) rgba(197, 48, 48, 0.12);
184
+ }
185
+
186
+ .dsrc-input-group--error .dsrc-label {
187
+ color: var(--dsrc-color-erreur-texte);
188
+ }
189
+
190
+
191
+ /* ============================================
192
+ * 9. Valid state (DSFR left-bar pattern)
193
+ * Green left border on wrapper, green bottom
194
+ * border on input, green messages
195
+ * ============================================ */
196
+
197
+ .dsrc-input-group--valid {
198
+ border-left: var(--dsrc-border-width-thick) solid var(--dsrc-color-succes-bordure);
199
+ padding-left: var(--dsrc-spacing-4);
200
+ }
201
+
202
+ .dsrc-input-group--valid .dsrc-input {
203
+ border-color: var(--dsrc-color-succes-bordure);
204
+ }
205
+
206
+ .dsrc-input-group--valid .dsrc-input:focus-visible {
207
+ border-color: var(--dsrc-color-succes-bordure);
208
+ box-shadow: 0 0 0 var(--dsrc-outline-width) rgba(24, 128, 56, 0.12);
209
+ }
210
+
211
+ .dsrc-input-group--valid .dsrc-label {
212
+ color: var(--dsrc-color-succes-texte);
213
+ }
214
+
215
+
216
+ /* ============================================
217
+ * 10. Messages group
218
+ * Container for validation messages,
219
+ * uses aria-live="polite" in HTML
220
+ * ============================================ */
221
+
222
+ .dsrc-messages-group {
223
+ display: flex;
224
+ flex-direction: column;
225
+ gap: var(--dsrc-spacing-1);
226
+ }
227
+
228
+
229
+ /* ============================================
230
+ * 11. Individual message
231
+ * ============================================ */
232
+
233
+ .dsrc-message {
234
+ font-family: var(--dsrc-font-family-sans);
235
+ font-size: var(--dsrc-font-size-caption);
236
+ font-weight: var(--dsrc-font-weight-medium);
237
+ line-height: var(--dsrc-font-line-height-relaxed);
238
+ margin: 0;
239
+ padding: 0;
240
+ }
241
+
242
+ .dsrc-message--error {
243
+ color: var(--dsrc-color-erreur-texte);
244
+ }
245
+
246
+ .dsrc-message--valid {
247
+ color: var(--dsrc-color-succes-texte);
248
+ }
249
+
250
+ .dsrc-message--info {
251
+ color: var(--dsrc-color-gris-600);
252
+ }
253
+
254
+
255
+ /* ============================================
256
+ * 12. Input wrap (for addon buttons)
257
+ * Flex row: input + button side by side
258
+ * ============================================ */
259
+
260
+ .dsrc-input-wrap {
261
+ display: flex;
262
+ width: 100%;
263
+ }
264
+
265
+ .dsrc-input-wrap--addon {
266
+ align-items: stretch;
267
+ }
268
+
269
+ .dsrc-input-wrap--addon .dsrc-input {
270
+ flex: 1 1 auto;
271
+ min-width: 0;
272
+ border-right: none;
273
+ border-top-right-radius: 0;
274
+ }
275
+
276
+ .dsrc-input-wrap--addon .dsrc-btn {
277
+ flex: 0 0 auto;
278
+ border-top-left-radius: 0;
279
+ border-bottom-left-radius: 0;
280
+ white-space: nowrap;
281
+ }
282
+
283
+
284
+ /* ============================================
285
+ * 13. Select (native dropdown)
286
+ * DSFR-style: same field treatment as input,
287
+ * custom chevron via background SVG
288
+ * ============================================ */
289
+
290
+ .dsrc-select {
291
+ appearance: none;
292
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' fill='none'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23555' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
293
+ background-repeat: no-repeat;
294
+ background-position: right var(--dsrc-spacing-3) center;
295
+ padding-right: 34px;
296
+ cursor: pointer;
297
+ }
298
+
299
+ .dsrc-select:hover {
300
+ border-color: var(--dsrc-color-gris-400);
301
+ }
302
+
303
+
304
+ /* ============================================
305
+ * 14. High contrast (forced-colors)
306
+ * ============================================ */
307
+
308
+ @media (forced-colors: active) {
309
+ .dsrc-input {
310
+ border: 1px solid ButtonText;
311
+ }
312
+
313
+ .dsrc-input:disabled,
314
+ .dsrc-input-group--disabled .dsrc-input {
315
+ border-color: GrayText;
316
+ color: GrayText;
317
+ }
318
+
319
+ .dsrc-input-group--error .dsrc-input {
320
+ border-color: LinkText;
321
+ border-bottom-width: 3px;
322
+ }
323
+
324
+ .dsrc-input-group--valid .dsrc-input {
325
+ border-color: ButtonText;
326
+ border-bottom-width: 3px;
327
+ }
328
+
329
+ .dsrc-input-group--error,
330
+ .dsrc-input-group--valid {
331
+ border-left-color: LinkText;
332
+ }
333
+
334
+ .dsrc-select {
335
+ border: 1px solid ButtonText;
336
+ }
337
+ }