@pure-ds/storybook 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 (129) hide show
  1. package/.storybook/addons/description/preview.js +15 -0
  2. package/.storybook/addons/description/register.js +60 -0
  3. package/.storybook/addons/html-preview/Panel.jsx +327 -0
  4. package/.storybook/addons/html-preview/constants.js +6 -0
  5. package/.storybook/addons/html-preview/preview.js +178 -0
  6. package/.storybook/addons/html-preview/register.js +16 -0
  7. package/.storybook/addons/pds-configurator/SearchTool.js +44 -0
  8. package/.storybook/addons/pds-configurator/Tool.js +30 -0
  9. package/.storybook/addons/pds-configurator/constants.js +9 -0
  10. package/.storybook/addons/pds-configurator/preview.js +159 -0
  11. package/.storybook/addons/pds-configurator/register.js +24 -0
  12. package/.storybook/docs.css +35 -0
  13. package/.storybook/htmlPreview.css +103 -0
  14. package/.storybook/htmlPreview.js +271 -0
  15. package/.storybook/main.js +160 -0
  16. package/.storybook/preview-body.html +48 -0
  17. package/.storybook/preview-head.html +11 -0
  18. package/.storybook/preview.js +1563 -0
  19. package/README.md +266 -0
  20. package/bin/index.js +40 -0
  21. package/dist/pds-reference.json +2101 -0
  22. package/package.json +45 -0
  23. package/pds.config.js +6 -0
  24. package/public/assets/css/app.css +1216 -0
  25. package/public/assets/data/auto-design-advanced.json +704 -0
  26. package/public/assets/data/auto-design-simple.json +123 -0
  27. package/public/assets/img/icon-512x512.png +0 -0
  28. package/public/assets/img/logo-trans.png +0 -0
  29. package/public/assets/img/logo.png +0 -0
  30. package/public/assets/js/app.js +15088 -0
  31. package/public/assets/js/app.js.map +7 -0
  32. package/public/assets/js/lit.js +1176 -0
  33. package/public/assets/js/lit.js.map +7 -0
  34. package/public/assets/js/pds.js +9801 -0
  35. package/public/assets/js/pds.js.map +7 -0
  36. package/public/assets/pds/components/pds-calendar.js +837 -0
  37. package/public/assets/pds/components/pds-drawer.js +857 -0
  38. package/public/assets/pds/components/pds-icon.js +338 -0
  39. package/public/assets/pds/components/pds-jsonform.js +1775 -0
  40. package/public/assets/pds/components/pds-richtext.js +1035 -0
  41. package/public/assets/pds/components/pds-scrollrow.js +331 -0
  42. package/public/assets/pds/components/pds-splitpanel.js +401 -0
  43. package/public/assets/pds/components/pds-tabstrip.js +251 -0
  44. package/public/assets/pds/components/pds-toaster.js +446 -0
  45. package/public/assets/pds/components/pds-upload.js +657 -0
  46. package/public/assets/pds/custom-elements.json +2003 -0
  47. package/public/assets/pds/icons/pds-icons.svg +498 -0
  48. package/public/assets/pds/pds-css-complete.json +1861 -0
  49. package/public/assets/pds/pds-runtime-config.json +11 -0
  50. package/public/assets/pds/pds.css-data.json +2152 -0
  51. package/public/assets/pds/styles/pds-components.css +1944 -0
  52. package/public/assets/pds/styles/pds-components.css.js +3895 -0
  53. package/public/assets/pds/styles/pds-primitives.css +352 -0
  54. package/public/assets/pds/styles/pds-primitives.css.js +711 -0
  55. package/public/assets/pds/styles/pds-styles.css +3761 -0
  56. package/public/assets/pds/styles/pds-styles.css.js +7529 -0
  57. package/public/assets/pds/styles/pds-tokens.css +699 -0
  58. package/public/assets/pds/styles/pds-tokens.css.js +1405 -0
  59. package/public/assets/pds/styles/pds-utilities.css +763 -0
  60. package/public/assets/pds/styles/pds-utilities.css.js +1533 -0
  61. package/public/assets/pds/vscode-custom-data.json +824 -0
  62. package/scripts/build-pds-reference.mjs +807 -0
  63. package/scripts/generate-stories.js +542 -0
  64. package/scripts/package-build.js +86 -0
  65. package/src/js/app.js +17 -0
  66. package/src/js/common/ask.js +208 -0
  67. package/src/js/common/common.js +20 -0
  68. package/src/js/common/font-loader.js +200 -0
  69. package/src/js/common/msg.js +90 -0
  70. package/src/js/lit.js +40 -0
  71. package/src/js/pds-core/pds-config.js +1162 -0
  72. package/src/js/pds-core/pds-enhancer-metadata.js +75 -0
  73. package/src/js/pds-core/pds-enhancers.js +357 -0
  74. package/src/js/pds-core/pds-enums.js +86 -0
  75. package/src/js/pds-core/pds-generator.js +5317 -0
  76. package/src/js/pds-core/pds-ontology.js +256 -0
  77. package/src/js/pds-core/pds-paths.js +109 -0
  78. package/src/js/pds-core/pds-query.js +571 -0
  79. package/src/js/pds-core/pds-registry.js +129 -0
  80. package/src/js/pds-core/pds.d.ts +129 -0
  81. package/src/js/pds.d.ts +408 -0
  82. package/src/js/pds.js +1579 -0
  83. package/src/pds-core/pds-api.js +105 -0
  84. package/stories/GettingStarted.md +96 -0
  85. package/stories/GettingStarted.stories.js +144 -0
  86. package/stories/WhatIsPDS.md +194 -0
  87. package/stories/WhatIsPDS.stories.js +144 -0
  88. package/stories/components/PdsCalendar.stories.js +263 -0
  89. package/stories/components/PdsDrawer.stories.js +623 -0
  90. package/stories/components/PdsIcon.stories.js +78 -0
  91. package/stories/components/PdsJsonform.stories.js +1444 -0
  92. package/stories/components/PdsRichtext.stories.js +367 -0
  93. package/stories/components/PdsScrollrow.stories.js +140 -0
  94. package/stories/components/PdsSplitpanel.stories.js +502 -0
  95. package/stories/components/PdsTabstrip.stories.js +442 -0
  96. package/stories/components/PdsToaster.stories.js +186 -0
  97. package/stories/components/PdsUpload.stories.js +66 -0
  98. package/stories/enhancements/Dropdowns.stories.js +185 -0
  99. package/stories/enhancements/InteractiveStates.stories.js +625 -0
  100. package/stories/enhancements/MeshGradients.stories.js +320 -0
  101. package/stories/enhancements/OpenGroups.stories.js +227 -0
  102. package/stories/enhancements/RangeSliders.stories.js +232 -0
  103. package/stories/enhancements/RequiredFields.stories.js +189 -0
  104. package/stories/enhancements/Toggles.stories.js +167 -0
  105. package/stories/foundations/Colors.stories.js +283 -0
  106. package/stories/foundations/Icons.stories.js +305 -0
  107. package/stories/foundations/SmartSurfaces.stories.js +367 -0
  108. package/stories/foundations/Spacing.stories.js +175 -0
  109. package/stories/foundations/Typography.stories.js +960 -0
  110. package/stories/foundations/ZIndex.stories.js +325 -0
  111. package/stories/patterns/BorderEffects.stories.js +72 -0
  112. package/stories/patterns/Layout.stories.js +99 -0
  113. package/stories/patterns/Utilities.stories.js +107 -0
  114. package/stories/primitives/Accordion.stories.js +359 -0
  115. package/stories/primitives/Alerts.stories.js +64 -0
  116. package/stories/primitives/Badges.stories.js +183 -0
  117. package/stories/primitives/Buttons.stories.js +229 -0
  118. package/stories/primitives/Cards.stories.js +353 -0
  119. package/stories/primitives/FormGroups.stories.js +569 -0
  120. package/stories/primitives/Forms.stories.js +131 -0
  121. package/stories/primitives/Media.stories.js +203 -0
  122. package/stories/primitives/Tables.stories.js +232 -0
  123. package/stories/reference/ReferenceCatalog.stories.js +28 -0
  124. package/stories/reference/reference-catalog.js +413 -0
  125. package/stories/reference/reference-docs.js +302 -0
  126. package/stories/reference/reference-helpers.js +310 -0
  127. package/stories/utilities/GridSystem.stories.js +208 -0
  128. package/stories/utils/PdsAsk.stories.js +420 -0
  129. package/stories/utils/toast-utils.js +148 -0
@@ -0,0 +1,711 @@
1
+ // Pure Design System - primitives
2
+ // Auto-generated - do not edit directly
3
+
4
+ export const primitives = new CSSStyleSheet();
5
+ primitives.replaceSync(`@layer primitives {
6
+ /* Base HTML reset */
7
+ *, *::before, *::after {
8
+ box-sizing: border-box;
9
+ }
10
+
11
+ :where(html) {
12
+ interpolate-size: allow-keywords;
13
+ font-family: var(--font-family-body);
14
+ font-size: var(--font-size-base);
15
+ line-height: var(--font-line-height-normal);
16
+ color: var(--color-text-primary);
17
+ background-color: var(--color-surface-base);
18
+ -webkit-text-size-adjust: 100%;
19
+ -webkit-font-smoothing: antialiased;
20
+ -moz-osx-font-smoothing: grayscale;
21
+ tab-size: 4;
22
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0.1);
23
+ }
24
+
25
+ :where(dialog){
26
+ background-color: transparent;
27
+ min-width: 320px;
28
+ border: none;
29
+ }
30
+
31
+ :where(body) {
32
+ margin: 0;
33
+ padding: 0;
34
+ scroll-behavior: smooth;
35
+ min-height: 100vh;
36
+ min-height: var(--layout-min-height, 100vh);
37
+ overflow-x: hidden;
38
+ -webkit-overflow-scrolling: touch;
39
+ }
40
+
41
+ :where(body.drawer-open) {
42
+ /* overflow: hidden; */
43
+ /* scrollbar-gutter: stable; */
44
+ }
45
+
46
+ /* Button primitives */
47
+ :where(button) {
48
+ all: unset;
49
+ box-sizing: border-box;
50
+ font: inherit;
51
+ color: var(--color-primary-contrast, white);
52
+ background: var(--color-primary-600);
53
+ padding: var(--spacing-2) var(--spacing-4);
54
+ border: 0;
55
+ border-radius: var(--radius-md);
56
+ cursor: pointer;
57
+ transition: opacity var(--transition-fast), background-color var(--transition-fast);
58
+ display: inline-flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ gap: var(--spacing-2);
62
+ font-weight: var(--font-weight-medium);
63
+ line-height: 1.5;
64
+ min-height: 44px;
65
+ touch-action: manipulation;
66
+ user-select: none;
67
+ }
68
+
69
+ :where(button):hover:not(:disabled) {
70
+ opacity: 0.9;
71
+ background-color: var(--color-primary-700);
72
+ }
73
+
74
+ :where(button):focus-visible {
75
+ outline: 2px solid var(--color-primary-500);
76
+ outline-offset: 2px;
77
+ }
78
+
79
+ :where(button):disabled {
80
+ opacity: 0.5;
81
+ cursor: not-allowed;
82
+ }
83
+
84
+ :where(button):active:not(:disabled) {
85
+ transform: scale(0.98);
86
+ }
87
+
88
+ /* Input primitives */
89
+ :where(input:not([type="radio"]):not([type="checkbox"]):not([type="range"]):not([type="color"])),
90
+ :where(select),
91
+ :where(textarea) {
92
+ font: inherit;
93
+ color: var(--color-text-primary);
94
+ background: var(--color-input-bg);
95
+ border: 1px solid var(--color-border);
96
+ border-radius: var(--radius-md);
97
+ padding: var(--spacing-2) var(--spacing-3);
98
+ min-height: 40px;
99
+ width: 100%;
100
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
101
+ appearance: none;
102
+ }
103
+
104
+ :where(input):focus-visible,
105
+ :where(select):focus-visible,
106
+ :where(textarea):focus-visible {
107
+ outline: none;
108
+ border-color: var(--color-primary-500);
109
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary-500) 30%, transparent);
110
+ }
111
+
112
+ :where(input):disabled,
113
+ :where(select):disabled,
114
+ :where(textarea):disabled {
115
+ opacity: 0.6;
116
+ cursor: not-allowed;
117
+ background-color: var(--color-input-disabled-bg);
118
+ }
119
+
120
+ /* Harmonized placeholder styling */
121
+ :where(input)::placeholder,
122
+ :where(textarea)::placeholder,
123
+ :where(pds-richtext)::placeholder {
124
+ color: var(--color-text-muted);
125
+ opacity: 1;
126
+ font-weight: var(--font-weight-normal);
127
+ }
128
+
129
+ :where(textarea) {
130
+ min-height: 80px;
131
+ resize: vertical;
132
+ }
133
+
134
+ /* Link primitives */
135
+ :where(a) {
136
+ color: var(--color-primary-600);
137
+ text-decoration: underline;
138
+ text-underline-offset: 0.2em;
139
+ transition: opacity var(--transition-fast);
140
+ }
141
+
142
+ :where(a):hover {
143
+ opacity: 0.8;
144
+ }
145
+
146
+ :where(a):focus-visible {
147
+ outline: 2px solid var(--color-primary-500);
148
+ outline-offset: 2px;
149
+ border-radius: var(--radius-sm);
150
+ }
151
+
152
+ /* Form primitives */
153
+ :where(label) {
154
+ display: block;
155
+ font-weight: var(--font-weight-medium);
156
+ margin-bottom: var(--spacing-2);
157
+ color: var(--color-text-primary);
158
+ font-size: var(--font-size-sm);
159
+ }
160
+
161
+ /* Checkbox enhancement - visually hide native input but keep accessible
162
+ Excludes button-style checkboxes in fieldsets and special containers */
163
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]) input[type="checkbox"]) {
164
+ position: absolute;
165
+ opacity: 0;
166
+ width: 1px;
167
+ height: 1px;
168
+ }
169
+
170
+ /* Style label container for checkbox */
171
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"])) {
172
+ display: inline-flex;
173
+ align-items: center;
174
+ gap: var(--spacing-2);
175
+ cursor: pointer;
176
+ user-select: none;
177
+ position: relative;
178
+ padding-left: calc(var(--spacing-5) + var(--spacing-3));
179
+ }
180
+
181
+ /* Custom checkbox box using PDS tokens - works with or without span wrapper */
182
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"])::before) {
183
+ content: "";
184
+ position: absolute;
185
+ left: 0;
186
+ top: 50%;
187
+ transform: translateY(-50%);
188
+ width: var(--spacing-5);
189
+ height: var(--spacing-5);
190
+ border: var(--border-width-md) solid var(--color-border);
191
+ border-radius: var(--radius-sm);
192
+ background: var(--color-surface-base);
193
+ transition: all var(--transition-fast);
194
+ flex-shrink: 0;
195
+ }
196
+
197
+ /* Checkmark */
198
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:checked)::after) {
199
+ content: "";
200
+ position: absolute;
201
+ left: var(--spacing-2);
202
+ top: 50%;
203
+ transform: translateY(-60%) rotate(45deg);
204
+ width: var(--spacing-1-5);
205
+ height: var(--spacing-3);
206
+ border: solid var(--color-primary-contrast, white);
207
+ border-width: 0 2px 2px 0;
208
+ }
209
+
210
+ /* Checked state */
211
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:checked)::before) {
212
+ background: var(--color-primary-600);
213
+ border-color: var(--color-primary-600);
214
+ }
215
+
216
+ /* Focus styles for accessibility */
217
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:focus)::before) {
218
+ outline: 2px solid var(--color-primary-500);
219
+ outline-offset: 2px;
220
+ }
221
+
222
+ /* Hover effects */
223
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:not(:disabled)):hover::before) {
224
+ border-color: var(--color-primary-600);
225
+ background: var(--color-surface-subtle);
226
+ }
227
+
228
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:checked:not(:disabled)):hover::before) {
229
+ background: var(--color-primary-700);
230
+ border-color: var(--color-primary-700);
231
+ }
232
+
233
+ /* Disabled state */
234
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:disabled)) {
235
+ opacity: 0.5;
236
+ cursor: not-allowed;
237
+ }
238
+
239
+ :where(fieldset) {
240
+ border: none;
241
+ padding: var(--spacing-4);
242
+ margin: 0 0 var(--spacing-4) 0;
243
+ background-color: var(--color-surface-subtle);
244
+ }
245
+
246
+ :where(legend) {
247
+ display: block;
248
+ font-weight: var(--font-weight-semibold);
249
+ padding: 0;
250
+ color: var(--color-text-primary);
251
+ font-weight: var(--font-weight-semibold);
252
+ color: var(--color-text-primary);
253
+ margin: 0 0 var(--spacing-3) 0;
254
+ border: none;
255
+ line-height: var(--font-line-height-tight);
256
+ font-size: var(--font-size-lg);
257
+ background: transparent; /* avoid browser default notch behavior */
258
+ width: auto;
259
+ box-sizing: border-box;
260
+ }
261
+
262
+
263
+ /* List primitives */
264
+ :where(ul, ol) {
265
+ padding-left: var(--spacing-6);
266
+ margin: var(--spacing-3) 0;
267
+ }
268
+
269
+ :where(li) {
270
+ margin: var(--spacing-1) 0;
271
+ }
272
+
273
+ /* Typography primitives */
274
+ :where(h1, h2, h3, h4, h5, h6) {
275
+ font-family: var(--font-family-headings);
276
+ font-weight: var(--font-weight-bold);
277
+ line-height: var(--font-line-height-tight);
278
+ margin: var(--spacing-4) 0 var(--spacing-3) 0;
279
+ color: var(--color-text-primary);
280
+ word-wrap: break-word;
281
+ hyphens: auto;
282
+ overflow-wrap: break-word;
283
+ }
284
+
285
+ /* Mobile-first heading sizes */
286
+ :where(h1) { font-size: var(--font-size-2xl); }
287
+ :where(h2) { font-size: var(--font-size-xl); }
288
+ :where(h3) { font-size: var(--font-size-lg); }
289
+ :where(h4) { font-size: var(--font-size-base); }
290
+ :where(h5) { font-size: var(--font-size-sm); }
291
+ :where(h6) { font-size: var(--font-size-xs); }
292
+
293
+ /* Scale up on larger screens */
294
+ @media (min-width: 640px) {
295
+ :where(h1) { font-size: var(--font-size-3xl); }
296
+ :where(h2) { font-size: var(--font-size-2xl); }
297
+ :where(h3) { font-size: var(--font-size-xl); }
298
+ :where(h4) { font-size: var(--font-size-lg); }
299
+ :where(h5) { font-size: var(--font-size-base); }
300
+ :where(h6) { font-size: var(--font-size-sm); }
301
+ }
302
+
303
+ :where(p) {
304
+ margin: var(--spacing-3) 0;
305
+ line-height: var(--font-line-height-relaxed);
306
+ color: var(--color-text-primary);
307
+ }
308
+
309
+ /* Code primitives */
310
+ :where(code) {
311
+ font-family: var(--font-family-mono, monospace);
312
+ font-size: 0.9em;
313
+ background: var(--color-surface-muted);
314
+ padding: 0.2em 0.4em;
315
+ border-radius: var(--radius-sm);
316
+ color: var(--color-text-primary);
317
+ }
318
+
319
+ :where(pre) {
320
+ font-family: var(--font-family-mono, monospace);
321
+ background: var(--color-surface-muted);
322
+ padding: var(--spacing-4);
323
+ border-radius: var(--radius-md);
324
+ overflow-x: auto;
325
+ margin: var(--spacing-4) 0;
326
+ }
327
+
328
+ :where(pre code) {
329
+ background: none;
330
+ padding: 0;
331
+ }
332
+
333
+ /* Media primitives */
334
+ :where(img, video) {
335
+ max-width: 100%;
336
+ height: auto;
337
+ border-radius: var(--radius-sm);
338
+ }
339
+
340
+ :where(figure) {
341
+ margin: 0 0 var(--spacing-6) 0;
342
+ }
343
+
344
+ :where(figcaption) {
345
+ margin-top: var(--spacing-3);
346
+ font-size: var(--font-size-sm);
347
+ color: var(--color-text-secondary);
348
+ line-height: var(--font-line-height-relaxed);
349
+ }
350
+
351
+
352
+ :where([hidden]) {
353
+ display: none !important;
354
+ }
355
+ }
356
+
357
+ `);
358
+
359
+ export const primitivesCSS = `@layer primitives {
360
+ /* Base HTML reset */
361
+ *, *::before, *::after {
362
+ box-sizing: border-box;
363
+ }
364
+
365
+ :where(html) {
366
+ interpolate-size: allow-keywords;
367
+ font-family: var(--font-family-body);
368
+ font-size: var(--font-size-base);
369
+ line-height: var(--font-line-height-normal);
370
+ color: var(--color-text-primary);
371
+ background-color: var(--color-surface-base);
372
+ -webkit-text-size-adjust: 100%;
373
+ -webkit-font-smoothing: antialiased;
374
+ -moz-osx-font-smoothing: grayscale;
375
+ tab-size: 4;
376
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0.1);
377
+ }
378
+
379
+ :where(dialog){
380
+ background-color: transparent;
381
+ min-width: 320px;
382
+ border: none;
383
+ }
384
+
385
+ :where(body) {
386
+ margin: 0;
387
+ padding: 0;
388
+ scroll-behavior: smooth;
389
+ min-height: 100vh;
390
+ min-height: var(--layout-min-height, 100vh);
391
+ overflow-x: hidden;
392
+ -webkit-overflow-scrolling: touch;
393
+ }
394
+
395
+ :where(body.drawer-open) {
396
+ /* overflow: hidden; */
397
+ /* scrollbar-gutter: stable; */
398
+ }
399
+
400
+ /* Button primitives */
401
+ :where(button) {
402
+ all: unset;
403
+ box-sizing: border-box;
404
+ font: inherit;
405
+ color: var(--color-primary-contrast, white);
406
+ background: var(--color-primary-600);
407
+ padding: var(--spacing-2) var(--spacing-4);
408
+ border: 0;
409
+ border-radius: var(--radius-md);
410
+ cursor: pointer;
411
+ transition: opacity var(--transition-fast), background-color var(--transition-fast);
412
+ display: inline-flex;
413
+ align-items: center;
414
+ justify-content: center;
415
+ gap: var(--spacing-2);
416
+ font-weight: var(--font-weight-medium);
417
+ line-height: 1.5;
418
+ min-height: 44px;
419
+ touch-action: manipulation;
420
+ user-select: none;
421
+ }
422
+
423
+ :where(button):hover:not(:disabled) {
424
+ opacity: 0.9;
425
+ background-color: var(--color-primary-700);
426
+ }
427
+
428
+ :where(button):focus-visible {
429
+ outline: 2px solid var(--color-primary-500);
430
+ outline-offset: 2px;
431
+ }
432
+
433
+ :where(button):disabled {
434
+ opacity: 0.5;
435
+ cursor: not-allowed;
436
+ }
437
+
438
+ :where(button):active:not(:disabled) {
439
+ transform: scale(0.98);
440
+ }
441
+
442
+ /* Input primitives */
443
+ :where(input:not([type="radio"]):not([type="checkbox"]):not([type="range"]):not([type="color"])),
444
+ :where(select),
445
+ :where(textarea) {
446
+ font: inherit;
447
+ color: var(--color-text-primary);
448
+ background: var(--color-input-bg);
449
+ border: 1px solid var(--color-border);
450
+ border-radius: var(--radius-md);
451
+ padding: var(--spacing-2) var(--spacing-3);
452
+ min-height: 40px;
453
+ width: 100%;
454
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
455
+ appearance: none;
456
+ }
457
+
458
+ :where(input):focus-visible,
459
+ :where(select):focus-visible,
460
+ :where(textarea):focus-visible {
461
+ outline: none;
462
+ border-color: var(--color-primary-500);
463
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary-500) 30%, transparent);
464
+ }
465
+
466
+ :where(input):disabled,
467
+ :where(select):disabled,
468
+ :where(textarea):disabled {
469
+ opacity: 0.6;
470
+ cursor: not-allowed;
471
+ background-color: var(--color-input-disabled-bg);
472
+ }
473
+
474
+ /* Harmonized placeholder styling */
475
+ :where(input)::placeholder,
476
+ :where(textarea)::placeholder,
477
+ :where(pds-richtext)::placeholder {
478
+ color: var(--color-text-muted);
479
+ opacity: 1;
480
+ font-weight: var(--font-weight-normal);
481
+ }
482
+
483
+ :where(textarea) {
484
+ min-height: 80px;
485
+ resize: vertical;
486
+ }
487
+
488
+ /* Link primitives */
489
+ :where(a) {
490
+ color: var(--color-primary-600);
491
+ text-decoration: underline;
492
+ text-underline-offset: 0.2em;
493
+ transition: opacity var(--transition-fast);
494
+ }
495
+
496
+ :where(a):hover {
497
+ opacity: 0.8;
498
+ }
499
+
500
+ :where(a):focus-visible {
501
+ outline: 2px solid var(--color-primary-500);
502
+ outline-offset: 2px;
503
+ border-radius: var(--radius-sm);
504
+ }
505
+
506
+ /* Form primitives */
507
+ :where(label) {
508
+ display: block;
509
+ font-weight: var(--font-weight-medium);
510
+ margin-bottom: var(--spacing-2);
511
+ color: var(--color-text-primary);
512
+ font-size: var(--font-size-sm);
513
+ }
514
+
515
+ /* Checkbox enhancement - visually hide native input but keep accessible
516
+ Excludes button-style checkboxes in fieldsets and special containers */
517
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]) input[type="checkbox"]) {
518
+ position: absolute;
519
+ opacity: 0;
520
+ width: 1px;
521
+ height: 1px;
522
+ }
523
+
524
+ /* Style label container for checkbox */
525
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"])) {
526
+ display: inline-flex;
527
+ align-items: center;
528
+ gap: var(--spacing-2);
529
+ cursor: pointer;
530
+ user-select: none;
531
+ position: relative;
532
+ padding-left: calc(var(--spacing-5) + var(--spacing-3));
533
+ }
534
+
535
+ /* Custom checkbox box using PDS tokens - works with or without span wrapper */
536
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"])::before) {
537
+ content: "";
538
+ position: absolute;
539
+ left: 0;
540
+ top: 50%;
541
+ transform: translateY(-50%);
542
+ width: var(--spacing-5);
543
+ height: var(--spacing-5);
544
+ border: var(--border-width-md) solid var(--color-border);
545
+ border-radius: var(--radius-sm);
546
+ background: var(--color-surface-base);
547
+ transition: all var(--transition-fast);
548
+ flex-shrink: 0;
549
+ }
550
+
551
+ /* Checkmark */
552
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:checked)::after) {
553
+ content: "";
554
+ position: absolute;
555
+ left: var(--spacing-2);
556
+ top: 50%;
557
+ transform: translateY(-60%) rotate(45deg);
558
+ width: var(--spacing-1-5);
559
+ height: var(--spacing-3);
560
+ border: solid var(--color-primary-contrast, white);
561
+ border-width: 0 2px 2px 0;
562
+ }
563
+
564
+ /* Checked state */
565
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:checked)::before) {
566
+ background: var(--color-primary-600);
567
+ border-color: var(--color-primary-600);
568
+ }
569
+
570
+ /* Focus styles for accessibility */
571
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:focus)::before) {
572
+ outline: 2px solid var(--color-primary-500);
573
+ outline-offset: 2px;
574
+ }
575
+
576
+ /* Hover effects */
577
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:not(:disabled)):hover::before) {
578
+ border-color: var(--color-primary-600);
579
+ background: var(--color-surface-subtle);
580
+ }
581
+
582
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:checked:not(:disabled)):hover::before) {
583
+ background: var(--color-primary-700);
584
+ border-color: var(--color-primary-700);
585
+ }
586
+
587
+ /* Disabled state */
588
+ :where(label:not(fieldset label, .checkbox-container label, [data-toggle]):has(input[type="checkbox"]:disabled)) {
589
+ opacity: 0.5;
590
+ cursor: not-allowed;
591
+ }
592
+
593
+ :where(fieldset) {
594
+ border: none;
595
+ padding: var(--spacing-4);
596
+ margin: 0 0 var(--spacing-4) 0;
597
+ background-color: var(--color-surface-subtle);
598
+ }
599
+
600
+ :where(legend) {
601
+ display: block;
602
+ font-weight: var(--font-weight-semibold);
603
+ padding: 0;
604
+ color: var(--color-text-primary);
605
+ font-weight: var(--font-weight-semibold);
606
+ color: var(--color-text-primary);
607
+ margin: 0 0 var(--spacing-3) 0;
608
+ border: none;
609
+ line-height: var(--font-line-height-tight);
610
+ font-size: var(--font-size-lg);
611
+ background: transparent; /* avoid browser default notch behavior */
612
+ width: auto;
613
+ box-sizing: border-box;
614
+ }
615
+
616
+
617
+ /* List primitives */
618
+ :where(ul, ol) {
619
+ padding-left: var(--spacing-6);
620
+ margin: var(--spacing-3) 0;
621
+ }
622
+
623
+ :where(li) {
624
+ margin: var(--spacing-1) 0;
625
+ }
626
+
627
+ /* Typography primitives */
628
+ :where(h1, h2, h3, h4, h5, h6) {
629
+ font-family: var(--font-family-headings);
630
+ font-weight: var(--font-weight-bold);
631
+ line-height: var(--font-line-height-tight);
632
+ margin: var(--spacing-4) 0 var(--spacing-3) 0;
633
+ color: var(--color-text-primary);
634
+ word-wrap: break-word;
635
+ hyphens: auto;
636
+ overflow-wrap: break-word;
637
+ }
638
+
639
+ /* Mobile-first heading sizes */
640
+ :where(h1) { font-size: var(--font-size-2xl); }
641
+ :where(h2) { font-size: var(--font-size-xl); }
642
+ :where(h3) { font-size: var(--font-size-lg); }
643
+ :where(h4) { font-size: var(--font-size-base); }
644
+ :where(h5) { font-size: var(--font-size-sm); }
645
+ :where(h6) { font-size: var(--font-size-xs); }
646
+
647
+ /* Scale up on larger screens */
648
+ @media (min-width: 640px) {
649
+ :where(h1) { font-size: var(--font-size-3xl); }
650
+ :where(h2) { font-size: var(--font-size-2xl); }
651
+ :where(h3) { font-size: var(--font-size-xl); }
652
+ :where(h4) { font-size: var(--font-size-lg); }
653
+ :where(h5) { font-size: var(--font-size-base); }
654
+ :where(h6) { font-size: var(--font-size-sm); }
655
+ }
656
+
657
+ :where(p) {
658
+ margin: var(--spacing-3) 0;
659
+ line-height: var(--font-line-height-relaxed);
660
+ color: var(--color-text-primary);
661
+ }
662
+
663
+ /* Code primitives */
664
+ :where(code) {
665
+ font-family: var(--font-family-mono, monospace);
666
+ font-size: 0.9em;
667
+ background: var(--color-surface-muted);
668
+ padding: 0.2em 0.4em;
669
+ border-radius: var(--radius-sm);
670
+ color: var(--color-text-primary);
671
+ }
672
+
673
+ :where(pre) {
674
+ font-family: var(--font-family-mono, monospace);
675
+ background: var(--color-surface-muted);
676
+ padding: var(--spacing-4);
677
+ border-radius: var(--radius-md);
678
+ overflow-x: auto;
679
+ margin: var(--spacing-4) 0;
680
+ }
681
+
682
+ :where(pre code) {
683
+ background: none;
684
+ padding: 0;
685
+ }
686
+
687
+ /* Media primitives */
688
+ :where(img, video) {
689
+ max-width: 100%;
690
+ height: auto;
691
+ border-radius: var(--radius-sm);
692
+ }
693
+
694
+ :where(figure) {
695
+ margin: 0 0 var(--spacing-6) 0;
696
+ }
697
+
698
+ :where(figcaption) {
699
+ margin-top: var(--spacing-3);
700
+ font-size: var(--font-size-sm);
701
+ color: var(--color-text-secondary);
702
+ line-height: var(--font-line-height-relaxed);
703
+ }
704
+
705
+
706
+ :where([hidden]) {
707
+ display: none !important;
708
+ }
709
+ }
710
+
711
+ `;