@dillingerstaffing/strand-vue 0.4.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 (233) hide show
  1. package/dist/components/Alert/Alert.vue.d.ts +31 -0
  2. package/dist/components/Alert/Alert.vue.d.ts.map +1 -0
  3. package/dist/components/Alert/index.d.ts +3 -0
  4. package/dist/components/Alert/index.d.ts.map +1 -0
  5. package/dist/components/Avatar/Avatar.vue.d.ts +20 -0
  6. package/dist/components/Avatar/Avatar.vue.d.ts.map +1 -0
  7. package/dist/components/Avatar/index.d.ts +2 -0
  8. package/dist/components/Avatar/index.d.ts.map +1 -0
  9. package/dist/components/Badge/Badge.vue.d.ts +35 -0
  10. package/dist/components/Badge/Badge.vue.d.ts.map +1 -0
  11. package/dist/components/Badge/index.d.ts +2 -0
  12. package/dist/components/Badge/index.d.ts.map +1 -0
  13. package/dist/components/Breadcrumb/Breadcrumb.vue.d.ts +15 -0
  14. package/dist/components/Breadcrumb/Breadcrumb.vue.d.ts.map +1 -0
  15. package/dist/components/Breadcrumb/index.d.ts +3 -0
  16. package/dist/components/Breadcrumb/index.d.ts.map +1 -0
  17. package/dist/components/Button/Button.vue.d.ts +46 -0
  18. package/dist/components/Button/Button.vue.d.ts.map +1 -0
  19. package/dist/components/Button/index.d.ts +3 -0
  20. package/dist/components/Button/index.d.ts.map +1 -0
  21. package/dist/components/Card/Card.vue.d.ts +30 -0
  22. package/dist/components/Card/Card.vue.d.ts.map +1 -0
  23. package/dist/components/Card/index.d.ts +2 -0
  24. package/dist/components/Card/index.d.ts.map +1 -0
  25. package/dist/components/Checkbox/Checkbox.vue.d.ts +23 -0
  26. package/dist/components/Checkbox/Checkbox.vue.d.ts.map +1 -0
  27. package/dist/components/Checkbox/index.d.ts +3 -0
  28. package/dist/components/Checkbox/index.d.ts.map +1 -0
  29. package/dist/components/Container/Container.vue.d.ts +27 -0
  30. package/dist/components/Container/Container.vue.d.ts.map +1 -0
  31. package/dist/components/Container/index.d.ts +2 -0
  32. package/dist/components/Container/index.d.ts.map +1 -0
  33. package/dist/components/DataReadout/DataReadout.vue.d.ts +15 -0
  34. package/dist/components/DataReadout/DataReadout.vue.d.ts.map +1 -0
  35. package/dist/components/DataReadout/index.d.ts +2 -0
  36. package/dist/components/DataReadout/index.d.ts.map +1 -0
  37. package/dist/components/Dialog/Dialog.vue.d.ts +39 -0
  38. package/dist/components/Dialog/Dialog.vue.d.ts.map +1 -0
  39. package/dist/components/Dialog/index.d.ts +3 -0
  40. package/dist/components/Dialog/index.d.ts.map +1 -0
  41. package/dist/components/Divider/Divider.vue.d.ts +14 -0
  42. package/dist/components/Divider/Divider.vue.d.ts.map +1 -0
  43. package/dist/components/Divider/index.d.ts +2 -0
  44. package/dist/components/Divider/index.d.ts.map +1 -0
  45. package/dist/components/FormField/FormField.vue.d.ts +32 -0
  46. package/dist/components/FormField/FormField.vue.d.ts.map +1 -0
  47. package/dist/components/FormField/index.d.ts +3 -0
  48. package/dist/components/FormField/index.d.ts.map +1 -0
  49. package/dist/components/Grid/Grid.vue.d.ts +30 -0
  50. package/dist/components/Grid/Grid.vue.d.ts.map +1 -0
  51. package/dist/components/Grid/index.d.ts +2 -0
  52. package/dist/components/Grid/index.d.ts.map +1 -0
  53. package/dist/components/Input/Input.vue.d.ts +37 -0
  54. package/dist/components/Input/Input.vue.d.ts.map +1 -0
  55. package/dist/components/Input/index.d.ts +3 -0
  56. package/dist/components/Input/index.d.ts.map +1 -0
  57. package/dist/components/Link/Link.vue.d.ts +29 -0
  58. package/dist/components/Link/Link.vue.d.ts.map +1 -0
  59. package/dist/components/Link/index.d.ts +2 -0
  60. package/dist/components/Link/index.d.ts.map +1 -0
  61. package/dist/components/Nav/Nav.vue.d.ts +30 -0
  62. package/dist/components/Nav/Nav.vue.d.ts.map +1 -0
  63. package/dist/components/Nav/index.d.ts +3 -0
  64. package/dist/components/Nav/index.d.ts.map +1 -0
  65. package/dist/components/Progress/Progress.vue.d.ts +17 -0
  66. package/dist/components/Progress/Progress.vue.d.ts.map +1 -0
  67. package/dist/components/Progress/index.d.ts +2 -0
  68. package/dist/components/Progress/index.d.ts.map +1 -0
  69. package/dist/components/Radio/Radio.vue.d.ts +22 -0
  70. package/dist/components/Radio/Radio.vue.d.ts.map +1 -0
  71. package/dist/components/Radio/index.d.ts +3 -0
  72. package/dist/components/Radio/index.d.ts.map +1 -0
  73. package/dist/components/Section/Section.vue.d.ts +30 -0
  74. package/dist/components/Section/Section.vue.d.ts.map +1 -0
  75. package/dist/components/Section/index.d.ts +2 -0
  76. package/dist/components/Section/index.d.ts.map +1 -0
  77. package/dist/components/Select/Select.vue.d.ts +26 -0
  78. package/dist/components/Select/Select.vue.d.ts.map +1 -0
  79. package/dist/components/Select/index.d.ts +3 -0
  80. package/dist/components/Select/index.d.ts.map +1 -0
  81. package/dist/components/Skeleton/Skeleton.vue.d.ts +16 -0
  82. package/dist/components/Skeleton/Skeleton.vue.d.ts.map +1 -0
  83. package/dist/components/Skeleton/index.d.ts +2 -0
  84. package/dist/components/Skeleton/index.d.ts.map +1 -0
  85. package/dist/components/Slider/Slider.vue.d.ts +24 -0
  86. package/dist/components/Slider/Slider.vue.d.ts.map +1 -0
  87. package/dist/components/Slider/index.d.ts +3 -0
  88. package/dist/components/Slider/index.d.ts.map +1 -0
  89. package/dist/components/Spinner/Spinner.vue.d.ts +12 -0
  90. package/dist/components/Spinner/Spinner.vue.d.ts.map +1 -0
  91. package/dist/components/Spinner/index.d.ts +2 -0
  92. package/dist/components/Spinner/index.d.ts.map +1 -0
  93. package/dist/components/Stack/Stack.vue.d.ts +38 -0
  94. package/dist/components/Stack/Stack.vue.d.ts.map +1 -0
  95. package/dist/components/Stack/index.d.ts +2 -0
  96. package/dist/components/Stack/index.d.ts.map +1 -0
  97. package/dist/components/Switch/Switch.vue.d.ts +18 -0
  98. package/dist/components/Switch/Switch.vue.d.ts.map +1 -0
  99. package/dist/components/Switch/index.d.ts +3 -0
  100. package/dist/components/Switch/index.d.ts.map +1 -0
  101. package/dist/components/Table/Table.vue.d.ts +23 -0
  102. package/dist/components/Table/Table.vue.d.ts.map +1 -0
  103. package/dist/components/Table/index.d.ts +3 -0
  104. package/dist/components/Table/index.d.ts.map +1 -0
  105. package/dist/components/Tabs/Tabs.vue.d.ts +34 -0
  106. package/dist/components/Tabs/Tabs.vue.d.ts.map +1 -0
  107. package/dist/components/Tabs/index.d.ts +3 -0
  108. package/dist/components/Tabs/index.d.ts.map +1 -0
  109. package/dist/components/Tag/Tag.vue.d.ts +37 -0
  110. package/dist/components/Tag/Tag.vue.d.ts.map +1 -0
  111. package/dist/components/Tag/index.d.ts +2 -0
  112. package/dist/components/Tag/index.d.ts.map +1 -0
  113. package/dist/components/Textarea/Textarea.vue.d.ts +29 -0
  114. package/dist/components/Textarea/Textarea.vue.d.ts.map +1 -0
  115. package/dist/components/Textarea/index.d.ts +3 -0
  116. package/dist/components/Textarea/index.d.ts.map +1 -0
  117. package/dist/components/Toast/Toast.vue.d.ts +16 -0
  118. package/dist/components/Toast/Toast.vue.d.ts.map +1 -0
  119. package/dist/components/Toast/ToastProvider.vue.d.ts +18 -0
  120. package/dist/components/Toast/ToastProvider.vue.d.ts.map +1 -0
  121. package/dist/components/Toast/index.d.ts +6 -0
  122. package/dist/components/Toast/index.d.ts.map +1 -0
  123. package/dist/components/Toast/useToast.d.ts +13 -0
  124. package/dist/components/Toast/useToast.d.ts.map +1 -0
  125. package/dist/components/Tooltip/Tooltip.vue.d.ts +29 -0
  126. package/dist/components/Tooltip/Tooltip.vue.d.ts.map +1 -0
  127. package/dist/components/Tooltip/index.d.ts +3 -0
  128. package/dist/components/Tooltip/index.d.ts.map +1 -0
  129. package/dist/css/strand-ui.css +2534 -0
  130. package/dist/index.d.ts +35 -0
  131. package/dist/index.d.ts.map +1 -0
  132. package/dist/index.js +1413 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/test-setup.d.ts +1 -0
  135. package/dist/test-setup.d.ts.map +1 -0
  136. package/package.json +51 -0
  137. package/src/components/Alert/Alert.test.ts +100 -0
  138. package/src/components/Alert/Alert.vue +54 -0
  139. package/src/components/Alert/index.ts +2 -0
  140. package/src/components/Avatar/Avatar.test.ts +105 -0
  141. package/src/components/Avatar/Avatar.vue +56 -0
  142. package/src/components/Avatar/index.ts +1 -0
  143. package/src/components/Badge/Badge.test.ts +114 -0
  144. package/src/components/Badge/Badge.vue +66 -0
  145. package/src/components/Badge/index.ts +1 -0
  146. package/src/components/Breadcrumb/Breadcrumb.test.ts +119 -0
  147. package/src/components/Breadcrumb/Breadcrumb.vue +58 -0
  148. package/src/components/Breadcrumb/index.ts +2 -0
  149. package/src/components/Button/Button.test.ts +148 -0
  150. package/src/components/Button/Button.vue +75 -0
  151. package/src/components/Button/index.ts +2 -0
  152. package/src/components/Card/Card.test.ts +93 -0
  153. package/src/components/Card/Card.vue +36 -0
  154. package/src/components/Card/index.ts +1 -0
  155. package/src/components/Checkbox/Checkbox.test.ts +118 -0
  156. package/src/components/Checkbox/Checkbox.vue +117 -0
  157. package/src/components/Checkbox/index.ts +2 -0
  158. package/src/components/Container/Container.test.ts +70 -0
  159. package/src/components/Container/Container.vue +32 -0
  160. package/src/components/Container/index.ts +1 -0
  161. package/src/components/DataReadout/DataReadout.test.ts +99 -0
  162. package/src/components/DataReadout/DataReadout.vue +36 -0
  163. package/src/components/DataReadout/index.ts +1 -0
  164. package/src/components/Dialog/Dialog.test.ts +224 -0
  165. package/src/components/Dialog/Dialog.vue +146 -0
  166. package/src/components/Dialog/index.ts +2 -0
  167. package/src/components/Divider/Divider.test.ts +95 -0
  168. package/src/components/Divider/Divider.vue +63 -0
  169. package/src/components/Divider/index.ts +1 -0
  170. package/src/components/FormField/FormField.test.ts +98 -0
  171. package/src/components/FormField/FormField.vue +59 -0
  172. package/src/components/FormField/index.ts +2 -0
  173. package/src/components/Grid/Grid.test.ts +73 -0
  174. package/src/components/Grid/Grid.vue +34 -0
  175. package/src/components/Grid/index.ts +1 -0
  176. package/src/components/Input/Input.test.ts +102 -0
  177. package/src/components/Input/Input.vue +63 -0
  178. package/src/components/Input/index.ts +2 -0
  179. package/src/components/Link/Link.test.ts +92 -0
  180. package/src/components/Link/Link.vue +35 -0
  181. package/src/components/Link/index.ts +1 -0
  182. package/src/components/Nav/Nav.test.ts +171 -0
  183. package/src/components/Nav/Nav.vue +81 -0
  184. package/src/components/Nav/index.ts +2 -0
  185. package/src/components/Progress/Progress.test.ts +103 -0
  186. package/src/components/Progress/Progress.vue +96 -0
  187. package/src/components/Progress/index.ts +1 -0
  188. package/src/components/Radio/Radio.test.ts +92 -0
  189. package/src/components/Radio/Radio.vue +60 -0
  190. package/src/components/Radio/index.ts +2 -0
  191. package/src/components/Section/Section.test.ts +77 -0
  192. package/src/components/Section/Section.vue +36 -0
  193. package/src/components/Section/index.ts +1 -0
  194. package/src/components/Select/Select.test.ts +102 -0
  195. package/src/components/Select/Select.vue +70 -0
  196. package/src/components/Select/index.ts +2 -0
  197. package/src/components/Skeleton/Skeleton.test.ts +77 -0
  198. package/src/components/Skeleton/Skeleton.vue +48 -0
  199. package/src/components/Skeleton/index.ts +1 -0
  200. package/src/components/Slider/Slider.test.ts +73 -0
  201. package/src/components/Slider/Slider.vue +60 -0
  202. package/src/components/Slider/index.ts +2 -0
  203. package/src/components/Spinner/Spinner.test.ts +66 -0
  204. package/src/components/Spinner/Spinner.vue +33 -0
  205. package/src/components/Spinner/index.ts +1 -0
  206. package/src/components/Stack/Stack.test.ts +140 -0
  207. package/src/components/Stack/Stack.vue +50 -0
  208. package/src/components/Stack/index.ts +1 -0
  209. package/src/components/Switch/Switch.test.ts +116 -0
  210. package/src/components/Switch/Switch.vue +62 -0
  211. package/src/components/Switch/index.ts +2 -0
  212. package/src/components/Table/Table.test.ts +152 -0
  213. package/src/components/Table/Table.vue +98 -0
  214. package/src/components/Table/index.ts +2 -0
  215. package/src/components/Tabs/Tabs.test.ts +138 -0
  216. package/src/components/Tabs/Tabs.vue +96 -0
  217. package/src/components/Tabs/index.ts +2 -0
  218. package/src/components/Tag/Tag.test.ts +128 -0
  219. package/src/components/Tag/Tag.vue +65 -0
  220. package/src/components/Tag/index.ts +1 -0
  221. package/src/components/Textarea/Textarea.test.ts +107 -0
  222. package/src/components/Textarea/Textarea.vue +90 -0
  223. package/src/components/Textarea/index.ts +2 -0
  224. package/src/components/Toast/Toast.test.ts +204 -0
  225. package/src/components/Toast/Toast.vue +48 -0
  226. package/src/components/Toast/ToastProvider.vue +80 -0
  227. package/src/components/Toast/index.ts +5 -0
  228. package/src/components/Toast/useToast.ts +26 -0
  229. package/src/components/Tooltip/Tooltip.test.ts +145 -0
  230. package/src/components/Tooltip/Tooltip.vue +79 -0
  231. package/src/components/Tooltip/index.ts +2 -0
  232. package/src/index.ts +44 -0
  233. package/src/test-setup.ts +7 -0
@@ -0,0 +1,2534 @@
1
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2
+
3
+ /* Alert */
4
+ /*! Strand UI | MIT License | dillingerstaffing.com */
5
+
6
+ /*! Strand UI | MIT License | dillingerstaffing.com */
7
+
8
+ /* ── Base ── */
9
+ .strand-alert {
10
+ position: relative;
11
+ display: flex;
12
+ align-items: flex-start;
13
+ justify-content: space-between;
14
+ width: 100%;
15
+ padding: var(--strand-space-6);
16
+ padding-left: var(--strand-space-5);
17
+ border-radius: var(--strand-radius-md);
18
+ border-left: 4px solid transparent;
19
+ font-family: var(--strand-font-sans);
20
+ font-size: var(--strand-text-sm);
21
+ }
22
+
23
+ /* ── Status variants ── */
24
+ .strand-alert--info {
25
+ background: var(--strand-blue-glow);
26
+ border-left-color: var(--strand-blue-primary);
27
+ }
28
+
29
+ .strand-alert--success {
30
+ background: rgba(34, 197, 94, 0.08);
31
+ border-left-color: var(--strand-green-positive);
32
+ }
33
+
34
+ .strand-alert--warning {
35
+ background: rgba(245, 158, 11, 0.08);
36
+ border-left-color: var(--strand-amber-caution);
37
+ }
38
+
39
+ .strand-alert--error {
40
+ background: rgba(239, 68, 68, 0.08);
41
+ border-left-color: var(--strand-red-alert);
42
+ }
43
+
44
+ /* ── Content ── */
45
+ .strand-alert__content {
46
+ flex: 1;
47
+ min-width: 0;
48
+ }
49
+
50
+ /* ── Dismiss button ── */
51
+ .strand-alert__dismiss {
52
+ flex-shrink: 0;
53
+ display: inline-flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ width: 24px;
57
+ height: 24px;
58
+ margin-left: var(--strand-space-4);
59
+ padding: 0;
60
+ border: none;
61
+ border-radius: var(--strand-radius-md);
62
+ background: transparent;
63
+ color: var(--strand-gray-500);
64
+ font-size: var(--strand-text-base);
65
+ cursor: pointer;
66
+ transition: background var(--strand-duration-fast) var(--strand-ease-out-quart),
67
+ color var(--strand-duration-fast) var(--strand-ease-out-quart);
68
+ }
69
+
70
+ .strand-alert__dismiss:hover {
71
+ background: var(--strand-gray-100);
72
+ color: var(--strand-gray-600);
73
+ }
74
+
75
+ /* ── Reduced motion ── */
76
+ @media (prefers-reduced-motion: reduce) {
77
+ .strand-alert__dismiss {
78
+ transition: none;
79
+ }
80
+ }
81
+
82
+
83
+ /* Avatar */
84
+ /*! Strand UI | MIT License | dillingerstaffing.com */
85
+
86
+ /*! Strand UI | MIT License | dillingerstaffing.com */
87
+
88
+ /* ── Base ── */
89
+ .strand-avatar {
90
+ display: inline-flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ border-radius: var(--strand-radius-full);
94
+ background: var(--strand-surface-recessed);
95
+ overflow: hidden;
96
+ flex-shrink: 0;
97
+ font-family: var(--strand-font-sans);
98
+ font-weight: var(--strand-weight-medium);
99
+ color: var(--strand-gray-600);
100
+ user-select: none;
101
+ }
102
+
103
+ /* ── Image ── */
104
+ .strand-avatar__img {
105
+ width: 100%;
106
+ height: 100%;
107
+ object-fit: cover;
108
+ border-radius: var(--strand-radius-full);
109
+ }
110
+
111
+ /* ── Initials ── */
112
+ .strand-avatar__initials {
113
+ text-transform: uppercase;
114
+ line-height: 1;
115
+ }
116
+
117
+ /* ── Sizes ── */
118
+ .strand-avatar--sm {
119
+ width: 32px;
120
+ height: 32px;
121
+ font-size: var(--strand-text-xs);
122
+ }
123
+
124
+ .strand-avatar--md {
125
+ width: 40px;
126
+ height: 40px;
127
+ font-size: var(--strand-text-sm);
128
+ }
129
+
130
+ .strand-avatar--lg {
131
+ width: 48px;
132
+ height: 48px;
133
+ font-size: var(--strand-text-base);
134
+ }
135
+
136
+ .strand-avatar--xl {
137
+ width: 64px;
138
+ height: 64px;
139
+ font-size: var(--strand-text-lg);
140
+ }
141
+
142
+
143
+ /* Badge */
144
+ /*! Strand UI | MIT License | dillingerstaffing.com */
145
+
146
+ /*! Strand UI | MIT License | dillingerstaffing.com */
147
+
148
+ /* ── Wrapper ── */
149
+ .strand-badge {
150
+ position: relative;
151
+ display: inline-flex;
152
+ vertical-align: middle;
153
+ }
154
+
155
+ .strand-badge--inline {
156
+ display: inline-flex;
157
+ }
158
+
159
+ /* ── Indicator (shared) ── */
160
+ .strand-badge__indicator {
161
+ display: inline-flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ font-family: var(--strand-font-sans);
165
+ font-weight: var(--strand-weight-semibold);
166
+ color: var(--strand-on-blue-primary);
167
+ }
168
+
169
+ /* Position at top-right when wrapping children */
170
+ .strand-badge:not(.strand-badge--inline) > .strand-badge__indicator {
171
+ position: absolute;
172
+ top: 0;
173
+ right: 0;
174
+ transform: translate(50%, -50%);
175
+ z-index: 1;
176
+ }
177
+
178
+ /* ── Dot variant ── */
179
+ .strand-badge--dot {
180
+ width: 8px;
181
+ height: 8px;
182
+ border-radius: var(--strand-radius-full);
183
+ font-size: 0;
184
+ padding: 0;
185
+ }
186
+
187
+ /* ── Count variant ── */
188
+ .strand-badge--count {
189
+ min-width: 20px;
190
+ height: 20px;
191
+ padding: 0 var(--strand-space-1);
192
+ border-radius: var(--strand-radius-full);
193
+ font-size: var(--strand-text-xs);
194
+ line-height: 20px;
195
+ }
196
+
197
+ /* ── Status colors ── */
198
+ .strand-badge--default {
199
+ background: var(--strand-gray-500);
200
+ }
201
+
202
+ .strand-badge--teal {
203
+ background: var(--strand-teal-vital);
204
+ }
205
+
206
+ .strand-badge--blue {
207
+ background: var(--strand-blue-primary);
208
+ }
209
+
210
+ .strand-badge--amber {
211
+ background: var(--strand-amber-caution);
212
+ color: var(--strand-blue-midnight);
213
+ }
214
+
215
+ .strand-badge--red {
216
+ background: var(--strand-red-alert);
217
+ }
218
+
219
+
220
+ /* Breadcrumb */
221
+ /*! Strand UI | MIT License | dillingerstaffing.com */
222
+
223
+ /*! Strand UI | MIT License | dillingerstaffing.com */
224
+
225
+ .strand-breadcrumb__list {
226
+ display: flex;
227
+ align-items: center;
228
+ gap: var(--strand-space-2);
229
+ list-style: none;
230
+ margin: 0;
231
+ padding: 0;
232
+ font-family: var(--strand-font-sans);
233
+ font-size: var(--strand-text-sm);
234
+ }
235
+
236
+ .strand-breadcrumb__item {
237
+ display: inline-flex;
238
+ align-items: center;
239
+ gap: var(--strand-space-2);
240
+ }
241
+
242
+ .strand-breadcrumb__separator {
243
+ color: var(--strand-gray-400);
244
+ user-select: none;
245
+ }
246
+
247
+ .strand-breadcrumb__link {
248
+ color: var(--strand-gray-500);
249
+ text-decoration: none;
250
+ transition: color var(--strand-duration-fast) var(--strand-ease-out-quart);
251
+ }
252
+
253
+ .strand-breadcrumb__link:hover {
254
+ color: var(--strand-gray-600);
255
+ }
256
+
257
+ .strand-breadcrumb__link:focus-visible {
258
+ outline: 2px solid var(--strand-blue-primary);
259
+ outline-offset: 2px;
260
+ }
261
+
262
+ .strand-breadcrumb__current {
263
+ color: var(--strand-gray-600);
264
+ font-weight: var(--strand-weight-medium);
265
+ }
266
+
267
+ /* ── Reduced motion ── */
268
+ @media (prefers-reduced-motion: reduce) {
269
+ .strand-breadcrumb__link {
270
+ transition: none;
271
+ }
272
+ }
273
+
274
+
275
+ /* Button */
276
+ /*! Strand UI | MIT License | dillingerstaffing.com */
277
+
278
+ /*! Strand UI | MIT License | dillingerstaffing.com */
279
+
280
+ /* ── Base ── */
281
+ .strand-btn {
282
+ position: relative;
283
+ display: inline-flex;
284
+ align-items: center;
285
+ justify-content: center;
286
+ gap: var(--strand-space-2);
287
+ border: 1px solid transparent;
288
+ border-radius: var(--strand-radius-md);
289
+ font-family: var(--strand-font-sans);
290
+ font-weight: var(--strand-weight-medium);
291
+ line-height: var(--strand-leading-snug);
292
+ white-space: nowrap;
293
+ cursor: pointer;
294
+ user-select: none;
295
+ transition:
296
+ background var(--strand-duration-fast) var(--strand-ease-out-quart),
297
+ border-color var(--strand-duration-fast) var(--strand-ease-out-quart),
298
+ color var(--strand-duration-fast) var(--strand-ease-out-quart),
299
+ transform var(--strand-duration-fast) var(--strand-ease-out-expo),
300
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-quart);
301
+ }
302
+
303
+ .strand-btn:active:not(:disabled) {
304
+ transform: translateY(0);
305
+ transition-duration: 75ms;
306
+ }
307
+
308
+ .strand-btn:disabled {
309
+ opacity: 0.4;
310
+ cursor: not-allowed;
311
+ }
312
+
313
+ /* ── Sizes ── */
314
+ .strand-btn--sm {
315
+ padding: var(--strand-space-1) var(--strand-space-3);
316
+ font-size: var(--strand-text-sm);
317
+ min-height: 32px;
318
+ }
319
+
320
+ .strand-btn--md {
321
+ padding: calc(var(--strand-space-2) + var(--strand-space-1) / 2) var(--strand-space-5);
322
+ font-size: var(--strand-text-sm);
323
+ min-height: 40px;
324
+ }
325
+
326
+ .strand-btn--lg {
327
+ padding: var(--strand-space-3) var(--strand-space-6);
328
+ font-size: var(--strand-text-base);
329
+ min-height: 48px;
330
+ }
331
+
332
+ /* ── Icon-only ── */
333
+ .strand-btn--icon-only.strand-btn--sm {
334
+ padding: var(--strand-space-1);
335
+ min-width: 32px;
336
+ }
337
+
338
+ .strand-btn--icon-only.strand-btn--md {
339
+ padding: var(--strand-space-2);
340
+ min-width: 40px;
341
+ }
342
+
343
+ .strand-btn--icon-only.strand-btn--lg {
344
+ padding: var(--strand-space-3);
345
+ min-width: 48px;
346
+ }
347
+
348
+ /* ── Full width ── */
349
+ .strand-btn--full-width {
350
+ width: 100%;
351
+ }
352
+
353
+ /* ── Primary variant ── */
354
+ .strand-btn--primary {
355
+ background: var(--strand-blue-primary);
356
+ color: var(--strand-on-blue-primary);
357
+ }
358
+
359
+ .strand-btn--primary:hover:not(:disabled) {
360
+ background: var(--strand-blue-vivid);
361
+ transform: translateY(-1px);
362
+ box-shadow: var(--strand-hover-shadow-primary);
363
+ }
364
+
365
+ .strand-btn--primary:active:not(:disabled) {
366
+ background: var(--strand-blue-deep);
367
+ }
368
+
369
+ /* ── Secondary variant ── */
370
+ .strand-btn--secondary {
371
+ background: var(--strand-surface-elevated);
372
+ color: var(--strand-blue-midnight);
373
+ border-color: var(--strand-gray-200);
374
+ }
375
+
376
+ .strand-btn--secondary:hover:not(:disabled) {
377
+ background: var(--strand-blue-glow);
378
+ border-color: var(--strand-blue-indicator);
379
+ transform: translateY(-1px);
380
+ box-shadow: var(--strand-elevation-1);
381
+ }
382
+
383
+ .strand-btn--secondary:active:not(:disabled) {
384
+ background: var(--strand-blue-wash);
385
+ }
386
+
387
+ /* ── Ghost variant ── */
388
+ .strand-btn--ghost {
389
+ background: transparent;
390
+ color: var(--strand-blue-primary);
391
+ }
392
+
393
+ .strand-btn--ghost:hover:not(:disabled) {
394
+ background: var(--strand-blue-glow);
395
+ transform: translateY(-1px);
396
+ }
397
+
398
+ .strand-btn--ghost:active:not(:disabled) {
399
+ background: var(--strand-blue-wash);
400
+ }
401
+
402
+ /* ── Danger variant ── */
403
+ .strand-btn--danger {
404
+ background: var(--strand-red-alert);
405
+ color: var(--strand-on-red-alert);
406
+ }
407
+
408
+ .strand-btn--danger:hover:not(:disabled) {
409
+ background: var(--strand-red-alert-vivid);
410
+ transform: translateY(-1px);
411
+ box-shadow: var(--strand-hover-shadow-danger);
412
+ }
413
+
414
+ .strand-btn--danger:active:not(:disabled) {
415
+ background: var(--strand-red-alert-deep);
416
+ }
417
+
418
+ /* ── Loading state ── */
419
+ .strand-btn--loading {
420
+ pointer-events: none;
421
+ }
422
+
423
+ .strand-btn__spinner {
424
+ position: absolute;
425
+ width: 16px;
426
+ height: 16px;
427
+ border: 2px solid currentColor;
428
+ border-top-color: transparent;
429
+ border-radius: var(--strand-radius-full);
430
+ animation: strand-btn-spin 0.8s linear infinite;
431
+ opacity: 0.8;
432
+ }
433
+
434
+ .strand-btn--lg .strand-btn__spinner {
435
+ width: 20px;
436
+ height: 20px;
437
+ }
438
+
439
+ @keyframes strand-btn-spin {
440
+ to {
441
+ transform: rotate(360deg);
442
+ }
443
+ }
444
+
445
+ /* ── Content wrapper ── */
446
+ .strand-btn__content {
447
+ display: inline-flex;
448
+ align-items: center;
449
+ gap: var(--strand-space-2);
450
+ }
451
+
452
+ /* ── Focus ring (Part XII: Accessibility Ring) ── */
453
+ .strand-btn:focus-visible {
454
+ outline: 2px solid var(--strand-blue-primary);
455
+ outline-offset: 2px;
456
+ }
457
+
458
+ /* ── Reduced motion ── */
459
+ @media (prefers-reduced-motion: reduce) {
460
+ .strand-btn {
461
+ transition: none;
462
+ }
463
+
464
+ .strand-btn:hover:not(:disabled) {
465
+ transform: none;
466
+ }
467
+
468
+ .strand-btn__spinner {
469
+ animation: none;
470
+ border-style: dotted;
471
+ }
472
+ }
473
+
474
+
475
+ /* Card */
476
+ /*! Strand UI | MIT License | dillingerstaffing.com */
477
+
478
+ /*! Strand UI | MIT License | dillingerstaffing.com */
479
+
480
+ /* ── Base ── */
481
+ .strand-card {
482
+ border-radius: var(--strand-radius-lg);
483
+ background: var(--strand-surface-elevated);
484
+ font-family: var(--strand-font-sans);
485
+ overflow: hidden;
486
+ box-sizing: border-box;
487
+ max-width: 100%;
488
+ }
489
+
490
+ /* ── Variants ── */
491
+ .strand-card--elevated {
492
+ box-shadow: var(--strand-elevation-1);
493
+ }
494
+
495
+ .strand-card--outlined {
496
+ box-shadow: none;
497
+ border: 1px solid var(--strand-gray-200);
498
+ }
499
+
500
+ .strand-card--interactive {
501
+ box-shadow: var(--strand-elevation-1);
502
+ cursor: pointer;
503
+ transition:
504
+ transform var(--strand-duration-fast) var(--strand-ease-out-expo),
505
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-expo);
506
+ }
507
+
508
+ .strand-card--interactive:hover {
509
+ transform: translateY(-2px);
510
+ box-shadow: var(--strand-elevation-2);
511
+ }
512
+
513
+ /* ── Padding ── */
514
+ .strand-card--pad-none {
515
+ padding: 0;
516
+ }
517
+
518
+ .strand-card--pad-sm {
519
+ padding: var(--strand-space-4);
520
+ }
521
+
522
+ .strand-card--pad-md {
523
+ padding: var(--strand-space-6);
524
+ }
525
+
526
+ .strand-card--pad-lg {
527
+ padding: var(--strand-space-10);
528
+ }
529
+
530
+ /* ── Focus ring (interactive cards) ── */
531
+ .strand-card--interactive:focus-visible {
532
+ outline: 2px solid var(--strand-blue-primary);
533
+ outline-offset: 2px;
534
+ }
535
+
536
+ /* ── Reduced motion ── */
537
+ @media (prefers-reduced-motion: reduce) {
538
+ .strand-card--interactive {
539
+ transition: none;
540
+ }
541
+
542
+ .strand-card--interactive:hover {
543
+ transform: none;
544
+ }
545
+ }
546
+
547
+
548
+ /* Checkbox */
549
+ /*! Strand UI | MIT License | dillingerstaffing.com */
550
+
551
+ /*! Strand UI | MIT License | dillingerstaffing.com */
552
+
553
+ /* ── Base ── */
554
+ .strand-checkbox {
555
+ display: inline-flex;
556
+ align-items: center;
557
+ gap: var(--strand-space-2);
558
+ cursor: pointer;
559
+ user-select: none;
560
+ font-family: var(--strand-font-sans);
561
+ font-size: var(--strand-text-sm);
562
+ color: var(--strand-gray-900);
563
+ line-height: var(--strand-leading-snug);
564
+ }
565
+
566
+ /* ── Hidden native input ── */
567
+ .strand-checkbox__native {
568
+ position: absolute;
569
+ width: 1px;
570
+ height: 1px;
571
+ padding: 0;
572
+ margin: -1px;
573
+ overflow: hidden;
574
+ clip: rect(0, 0, 0, 0);
575
+ white-space: nowrap;
576
+ border: 0;
577
+ }
578
+
579
+ /* ── Custom visual ── */
580
+ .strand-checkbox__control {
581
+ display: flex;
582
+ align-items: center;
583
+ justify-content: center;
584
+ width: 18px;
585
+ height: 18px;
586
+ border: 1px solid var(--strand-gray-200);
587
+ border-radius: var(--strand-radius-sm);
588
+ background: var(--strand-surface-elevated);
589
+ color: var(--strand-on-blue-primary);
590
+ flex-shrink: 0;
591
+ transition:
592
+ background var(--strand-duration-fast) var(--strand-ease-out-quart),
593
+ border-color var(--strand-duration-fast) var(--strand-ease-out-quart),
594
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-quart);
595
+ }
596
+
597
+ .strand-checkbox__icon {
598
+ width: 14px;
599
+ height: 14px;
600
+ }
601
+
602
+ /* ── Focus ring ── */
603
+ .strand-checkbox__native:focus-visible ~ .strand-checkbox__control {
604
+ border-color: var(--strand-blue-primary);
605
+ box-shadow: var(--strand-focus-ring);
606
+ }
607
+
608
+ /* ── Checked ── */
609
+ .strand-checkbox--checked .strand-checkbox__control {
610
+ background: var(--strand-blue-primary);
611
+ border-color: var(--strand-blue-primary);
612
+ }
613
+
614
+ /* ── Indeterminate ── */
615
+ .strand-checkbox--indeterminate .strand-checkbox__control {
616
+ background: var(--strand-blue-primary);
617
+ border-color: var(--strand-blue-primary);
618
+ }
619
+
620
+ /* ── Hover ── */
621
+ .strand-checkbox:hover:not(.strand-checkbox--disabled) .strand-checkbox__control {
622
+ border-color: var(--strand-blue-indicator);
623
+ }
624
+
625
+ .strand-checkbox--checked:hover:not(.strand-checkbox--disabled) .strand-checkbox__control,
626
+ .strand-checkbox--indeterminate:hover:not(.strand-checkbox--disabled) .strand-checkbox__control {
627
+ background: var(--strand-blue-vivid);
628
+ border-color: var(--strand-blue-vivid);
629
+ }
630
+
631
+ /* ── Label ── */
632
+ .strand-checkbox__label {
633
+ color: var(--strand-gray-900);
634
+ }
635
+
636
+ /* ── Disabled ── */
637
+ .strand-checkbox--disabled {
638
+ opacity: 0.4;
639
+ cursor: not-allowed;
640
+ }
641
+
642
+ /* ── Reduced motion ── */
643
+ @media (prefers-reduced-motion: reduce) {
644
+ .strand-checkbox__control {
645
+ transition: none;
646
+ }
647
+ }
648
+
649
+
650
+ /* Container */
651
+ /*! Strand UI | MIT License | dillingerstaffing.com */
652
+
653
+ /*! Strand UI | MIT License | dillingerstaffing.com */
654
+
655
+ /* ── Base ── */
656
+ .strand-container {
657
+ width: 100%;
658
+ margin-inline: auto;
659
+ padding-inline: clamp(1.5rem, 5vw, 4rem);
660
+ }
661
+
662
+ /* ── Sizes ── */
663
+ .strand-container--narrow {
664
+ max-width: var(--strand-content-narrow);
665
+ }
666
+
667
+ .strand-container--default {
668
+ max-width: var(--strand-content-default);
669
+ }
670
+
671
+ .strand-container--wide {
672
+ max-width: var(--strand-content-wide);
673
+ }
674
+
675
+ .strand-container--full {
676
+ max-width: var(--strand-content-full);
677
+ }
678
+
679
+
680
+ /* DataReadout */
681
+ /*! Strand UI | MIT License | dillingerstaffing.com */
682
+
683
+ /*! Strand UI | MIT License | dillingerstaffing.com */
684
+
685
+ /* ── Layout ── */
686
+ .strand-data-readout {
687
+ display: flex;
688
+ flex-direction: column;
689
+ gap: var(--strand-space-1);
690
+ }
691
+
692
+ /* ── Label (overline) ── */
693
+ .strand-data-readout__label {
694
+ font-family: var(--strand-font-mono);
695
+ font-size: var(--strand-text-xs);
696
+ font-weight: var(--strand-weight-medium);
697
+ letter-spacing: var(--strand-tracking-ultra);
698
+ text-transform: uppercase;
699
+ color: var(--strand-gray-500);
700
+ line-height: var(--strand-leading-normal);
701
+ }
702
+
703
+ /* ── Value (instrument readout) ── */
704
+ .strand-data-readout__value {
705
+ font-family: var(--strand-font-mono);
706
+ font-size: var(--strand-text-3xl);
707
+ font-weight: var(--strand-weight-light);
708
+ letter-spacing: var(--strand-tracking-tighter);
709
+ color: var(--strand-blue-midnight);
710
+ line-height: var(--strand-leading-tight);
711
+ font-variant-numeric: tabular-nums;
712
+ }
713
+
714
+ /* ── Size variants ── */
715
+ .strand-data-readout--sm .strand-data-readout__value {
716
+ font-size: var(--strand-text-xl);
717
+ }
718
+
719
+ .strand-data-readout--lg .strand-data-readout__value {
720
+ font-size: var(--strand-text-4xl);
721
+ }
722
+
723
+
724
+ /* Dialog */
725
+ /*! Strand UI | MIT License | dillingerstaffing.com */
726
+
727
+ /*! Strand UI | MIT License | dillingerstaffing.com */
728
+
729
+ /* ── Backdrop ── */
730
+ .strand-dialog__backdrop {
731
+ position: fixed;
732
+ inset: 0;
733
+ z-index: 1000;
734
+ display: flex;
735
+ align-items: center;
736
+ justify-content: center;
737
+ background: var(--strand-backdrop);
738
+ }
739
+
740
+ /* ── Panel ── */
741
+ .strand-dialog__panel {
742
+ position: relative;
743
+ width: 100%;
744
+ max-width: 560px;
745
+ margin: var(--strand-space-4);
746
+ padding: var(--strand-space-8);
747
+ background: var(--strand-surface-elevated);
748
+ border-radius: var(--strand-radius-xl);
749
+ box-shadow: var(--strand-elevation-4);
750
+ font-family: var(--strand-font-sans);
751
+ outline: none;
752
+ }
753
+
754
+ /* ── Header ── */
755
+ .strand-dialog__header {
756
+ margin-bottom: var(--strand-space-4);
757
+ padding-right: var(--strand-space-8);
758
+ }
759
+
760
+ /* ── Title ── */
761
+ .strand-dialog__title {
762
+ margin: 0;
763
+ font-size: var(--strand-text-lg);
764
+ font-weight: var(--strand-weight-semibold);
765
+ color: var(--strand-blue-midnight);
766
+ line-height: var(--strand-leading-snug);
767
+ }
768
+
769
+ /* ── Close button ── */
770
+ .strand-dialog__close {
771
+ position: absolute;
772
+ top: var(--strand-space-6);
773
+ right: var(--strand-space-6);
774
+ display: inline-flex;
775
+ align-items: center;
776
+ justify-content: center;
777
+ width: 32px;
778
+ height: 32px;
779
+ padding: 0;
780
+ border: none;
781
+ border-radius: var(--strand-radius-md);
782
+ background: transparent;
783
+ color: var(--strand-gray-500);
784
+ font-size: var(--strand-text-lg);
785
+ cursor: pointer;
786
+ transition: background var(--strand-duration-fast) var(--strand-ease-out-quart),
787
+ color var(--strand-duration-fast) var(--strand-ease-out-quart);
788
+ }
789
+
790
+ .strand-dialog__close:hover {
791
+ background: var(--strand-gray-200);
792
+ color: var(--strand-gray-900);
793
+ }
794
+
795
+ /* ── Body ── */
796
+ .strand-dialog__body {
797
+ padding-top: var(--strand-space-6);
798
+ color: var(--strand-gray-600);
799
+ font-size: var(--strand-text-sm);
800
+ }
801
+
802
+ /* ── Reduced motion ── */
803
+ @media (prefers-reduced-motion: reduce) {
804
+ .strand-dialog__close {
805
+ transition: none;
806
+ }
807
+ }
808
+
809
+
810
+ /* Divider */
811
+ /*! Strand UI | MIT License | dillingerstaffing.com */
812
+
813
+ /*! Strand UI | MIT License | dillingerstaffing.com */
814
+
815
+ /* ── Base ── */
816
+ .strand-divider {
817
+ border: 0;
818
+ margin: 0;
819
+ padding: 0;
820
+ }
821
+
822
+ /* ── Horizontal (hr) ── */
823
+ .strand-divider--horizontal {
824
+ width: 100%;
825
+ border-top: 1px solid var(--strand-gray-200);
826
+ }
827
+
828
+ /* ── Vertical ── */
829
+ .strand-divider--vertical {
830
+ align-self: stretch;
831
+ border-left: 1px solid var(--strand-gray-200);
832
+ }
833
+
834
+ /* ── Labeled ── */
835
+ .strand-divider--labeled {
836
+ display: flex;
837
+ align-items: center;
838
+ gap: var(--strand-space-3);
839
+ border-top: 0;
840
+ }
841
+
842
+ .strand-divider__line {
843
+ flex: 1;
844
+ height: 0;
845
+ border-top: 1px solid var(--strand-gray-200);
846
+ }
847
+
848
+ .strand-divider__label {
849
+ font-family: var(--strand-font-mono);
850
+ font-size: var(--strand-text-xs);
851
+ font-weight: var(--strand-weight-medium);
852
+ color: var(--strand-gray-400);
853
+ letter-spacing: var(--strand-tracking-widest);
854
+ text-transform: uppercase;
855
+ white-space: nowrap;
856
+ }
857
+
858
+
859
+ /* FormField */
860
+ /*! Strand UI | MIT License | dillingerstaffing.com */
861
+
862
+ /*! Strand UI | MIT License | dillingerstaffing.com */
863
+
864
+ /* ── Base ── */
865
+ .strand-form-field {
866
+ display: flex;
867
+ flex-direction: column;
868
+ gap: var(--strand-space-2);
869
+ }
870
+
871
+ /* ── Label ── */
872
+ .strand-form-field__label {
873
+ font-family: var(--strand-font-sans);
874
+ font-size: var(--strand-text-sm);
875
+ font-weight: var(--strand-weight-medium);
876
+ color: var(--strand-gray-700);
877
+ line-height: var(--strand-leading-snug);
878
+ }
879
+
880
+ /* ── Required indicator ── */
881
+ .strand-form-field__required {
882
+ color: var(--strand-red-alert);
883
+ margin-left: var(--strand-space-1);
884
+ }
885
+
886
+ /* ── Control wrapper ── */
887
+ .strand-form-field__control {
888
+ display: flex;
889
+ flex-direction: column;
890
+ }
891
+
892
+ /* ── Hint ── */
893
+ .strand-form-field__hint {
894
+ margin: 0;
895
+ font-family: var(--strand-font-sans);
896
+ font-size: var(--strand-text-xs);
897
+ color: var(--strand-gray-500);
898
+ line-height: var(--strand-leading-normal);
899
+ }
900
+
901
+ /* ── Error message ── */
902
+ .strand-form-field__error {
903
+ margin: 0;
904
+ font-family: var(--strand-font-sans);
905
+ font-size: var(--strand-text-xs);
906
+ color: var(--strand-red-alert);
907
+ line-height: var(--strand-leading-normal);
908
+ }
909
+
910
+
911
+ /* Grid */
912
+ /*! Strand UI | MIT License | dillingerstaffing.com */
913
+
914
+ /*! Strand UI | MIT License | dillingerstaffing.com */
915
+
916
+ /* ── Base ── */
917
+ .strand-grid {
918
+ display: grid;
919
+ overflow: hidden;
920
+ max-width: 100%;
921
+ box-sizing: border-box;
922
+ }
923
+
924
+ .strand-grid > * {
925
+ min-width: 0;
926
+ }
927
+
928
+ /* ── Column utilities ── */
929
+ .strand-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
930
+ .strand-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
931
+ .strand-grid--cols-4 { grid-template-columns: repeat(4, 1fr); }
932
+
933
+ /* ── Gap utilities ── */
934
+ .strand-grid--gap-1 { gap: var(--strand-space-1); }
935
+ .strand-grid--gap-2 { gap: var(--strand-space-2); }
936
+ .strand-grid--gap-3 { gap: var(--strand-space-3); }
937
+ .strand-grid--gap-4 { gap: var(--strand-space-4); }
938
+ .strand-grid--gap-5 { gap: var(--strand-space-5); }
939
+ .strand-grid--gap-6 { gap: var(--strand-space-6); }
940
+ .strand-grid--gap-8 { gap: var(--strand-space-8); }
941
+
942
+
943
+ /* Input */
944
+ /*! Strand UI | MIT License | dillingerstaffing.com */
945
+
946
+ /*! Strand UI | MIT License | dillingerstaffing.com */
947
+
948
+ .strand-input {
949
+ position: relative;
950
+ display: flex;
951
+ align-items: center;
952
+ background: var(--strand-surface-elevated);
953
+ border: 1px solid var(--strand-gray-200);
954
+ border-radius: var(--strand-radius-md);
955
+ transition:
956
+ border-color var(--strand-duration-fast) var(--strand-ease-out-quart),
957
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-quart);
958
+ }
959
+
960
+ .strand-input:focus-within {
961
+ border-color: var(--strand-blue-primary);
962
+ box-shadow: var(--strand-focus-ring);
963
+ }
964
+
965
+ /* ── Field ── */
966
+ .strand-input__field {
967
+ flex: 1;
968
+ width: 100%;
969
+ padding: var(--strand-space-3) var(--strand-space-4);
970
+ background: transparent;
971
+ border: none;
972
+ font-family: var(--strand-font-sans);
973
+ font-size: var(--strand-text-base);
974
+ color: var(--strand-gray-900);
975
+ outline: none;
976
+ }
977
+
978
+ .strand-input__field::placeholder {
979
+ color: var(--strand-gray-400);
980
+ }
981
+
982
+ /* ── Addons ── */
983
+ .strand-input__leading,
984
+ .strand-input__trailing {
985
+ display: flex;
986
+ align-items: center;
987
+ color: var(--strand-gray-500);
988
+ font-size: var(--strand-text-sm);
989
+ }
990
+
991
+ .strand-input__leading {
992
+ padding-left: var(--strand-space-3);
993
+ }
994
+
995
+ .strand-input__trailing {
996
+ padding-right: var(--strand-space-3);
997
+ }
998
+
999
+ .strand-input--has-leading .strand-input__field {
1000
+ padding-left: var(--strand-space-2);
1001
+ }
1002
+
1003
+ .strand-input--has-trailing .strand-input__field {
1004
+ padding-right: var(--strand-space-2);
1005
+ }
1006
+
1007
+ /* ── Error ── */
1008
+ .strand-input--error {
1009
+ border-color: var(--strand-red-alert);
1010
+ }
1011
+
1012
+ .strand-input--error:focus-within {
1013
+ border-color: var(--strand-red-alert);
1014
+ box-shadow: var(--strand-focus-ring-error);
1015
+ }
1016
+
1017
+ /* ── Disabled ── */
1018
+ .strand-input--disabled {
1019
+ opacity: 0.4;
1020
+ cursor: not-allowed;
1021
+ }
1022
+
1023
+ .strand-input--disabled .strand-input__field {
1024
+ cursor: not-allowed;
1025
+ }
1026
+
1027
+ /* ── Reduced motion ── */
1028
+ @media (prefers-reduced-motion: reduce) {
1029
+ .strand-input {
1030
+ transition: none;
1031
+ }
1032
+ }
1033
+
1034
+
1035
+ /* Link */
1036
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1037
+
1038
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1039
+
1040
+ .strand-link {
1041
+ color: var(--strand-blue-primary);
1042
+ text-decoration: none;
1043
+ font-family: var(--strand-font-sans);
1044
+ background-image: linear-gradient(currentColor, currentColor);
1045
+ background-position: 0% 100%;
1046
+ background-repeat: no-repeat;
1047
+ background-size: 0% 1px;
1048
+ transition: background-size var(--strand-duration-normal) var(--strand-ease-out-expo);
1049
+ cursor: pointer;
1050
+ }
1051
+
1052
+ .strand-link:hover {
1053
+ background-size: 100% 1px;
1054
+ }
1055
+
1056
+ /* ── Focus ring ── */
1057
+ .strand-link:focus-visible {
1058
+ outline: 2px solid var(--strand-blue-primary);
1059
+ outline-offset: 2px;
1060
+ }
1061
+
1062
+ /* ── Reduced motion ── */
1063
+ @media (prefers-reduced-motion: reduce) {
1064
+ .strand-link {
1065
+ transition: none;
1066
+ }
1067
+ }
1068
+
1069
+
1070
+ /* Nav */
1071
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1072
+
1073
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1074
+
1075
+ /* ── Nav bar ── */
1076
+ .strand-nav {
1077
+ position: relative;
1078
+ width: 100%;
1079
+ height: 64px;
1080
+ background: var(--strand-surface-elevated);
1081
+ border-bottom: 1px solid var(--strand-gray-200);
1082
+ font-family: var(--strand-font-sans);
1083
+ }
1084
+
1085
+ /* ── Inner layout ── */
1086
+ .strand-nav__inner {
1087
+ display: flex;
1088
+ align-items: center;
1089
+ height: 100%;
1090
+ padding: 0 var(--strand-space-6);
1091
+ max-width: 1280px;
1092
+ margin: 0 auto;
1093
+ }
1094
+
1095
+ /* ── Logo ── */
1096
+ .strand-nav__logo {
1097
+ flex-shrink: 0;
1098
+ margin-right: var(--strand-space-8);
1099
+ }
1100
+
1101
+ /* ── Desktop items ── */
1102
+ .strand-nav__items {
1103
+ display: flex;
1104
+ align-items: center;
1105
+ gap: var(--strand-space-6);
1106
+ flex: 1;
1107
+ }
1108
+
1109
+ /* ── Links ── */
1110
+ .strand-nav__link {
1111
+ color: var(--strand-gray-600);
1112
+ text-decoration: none;
1113
+ font-size: var(--strand-text-sm);
1114
+ font-weight: var(--strand-weight-medium);
1115
+ transition: color var(--strand-duration-fast) var(--strand-ease-out-quart);
1116
+ }
1117
+
1118
+ .strand-nav__link:hover {
1119
+ color: var(--strand-gray-900);
1120
+ }
1121
+
1122
+ .strand-nav__link:focus-visible {
1123
+ outline: 2px solid var(--strand-blue-primary);
1124
+ outline-offset: 2px;
1125
+ }
1126
+
1127
+ .strand-nav__link--active {
1128
+ color: var(--strand-blue-primary);
1129
+ font-weight: var(--strand-weight-medium);
1130
+ }
1131
+
1132
+ /* ── Actions ── */
1133
+ .strand-nav__actions {
1134
+ display: flex;
1135
+ align-items: center;
1136
+ gap: var(--strand-space-3);
1137
+ margin-left: auto;
1138
+ }
1139
+
1140
+ /* ── Hamburger ── */
1141
+ .strand-nav__hamburger {
1142
+ display: none;
1143
+ align-items: center;
1144
+ justify-content: center;
1145
+ width: 40px;
1146
+ height: 40px;
1147
+ margin-left: auto;
1148
+ padding: 0;
1149
+ border: none;
1150
+ border-radius: var(--strand-radius-md);
1151
+ background: transparent;
1152
+ color: var(--strand-gray-600);
1153
+ cursor: pointer;
1154
+ transition: background var(--strand-duration-fast) var(--strand-ease-out-quart);
1155
+ }
1156
+
1157
+ .strand-nav__hamburger:hover {
1158
+ background: var(--strand-gray-200);
1159
+ }
1160
+
1161
+ .strand-nav__hamburger:focus-visible {
1162
+ outline: 2px solid var(--strand-blue-primary);
1163
+ outline-offset: 2px;
1164
+ }
1165
+
1166
+ .strand-nav__hamburger-icon {
1167
+ display: block;
1168
+ width: 20px;
1169
+ height: 2px;
1170
+ background: currentColor;
1171
+ position: relative;
1172
+ }
1173
+
1174
+ .strand-nav__hamburger-icon::before,
1175
+ .strand-nav__hamburger-icon::after {
1176
+ content: "";
1177
+ position: absolute;
1178
+ left: 0;
1179
+ width: 100%;
1180
+ height: 2px;
1181
+ background: currentColor;
1182
+ }
1183
+
1184
+ .strand-nav__hamburger-icon::before {
1185
+ top: -6px;
1186
+ }
1187
+
1188
+ .strand-nav__hamburger-icon::after {
1189
+ top: 6px;
1190
+ }
1191
+
1192
+ /* ── Mobile menu ── */
1193
+ .strand-nav__mobile-menu {
1194
+ display: none;
1195
+ flex-direction: column;
1196
+ width: 100%;
1197
+ padding: var(--strand-space-4) var(--strand-space-6);
1198
+ background: var(--strand-surface-elevated);
1199
+ border-bottom: 1px solid var(--strand-gray-200);
1200
+ }
1201
+
1202
+ .strand-nav__mobile-link {
1203
+ display: block;
1204
+ padding: var(--strand-space-3) 0;
1205
+ color: var(--strand-gray-600);
1206
+ text-decoration: none;
1207
+ font-size: var(--strand-text-sm);
1208
+ font-weight: var(--strand-weight-medium);
1209
+ transition: color var(--strand-duration-fast) var(--strand-ease-out-quart);
1210
+ }
1211
+
1212
+ .strand-nav__mobile-link:hover {
1213
+ color: var(--strand-gray-900);
1214
+ }
1215
+
1216
+ .strand-nav__mobile-link--active {
1217
+ color: var(--strand-blue-primary);
1218
+ }
1219
+
1220
+ /* ── Responsive ── */
1221
+ @media (max-width: 767px) {
1222
+ .strand-nav__items {
1223
+ display: none;
1224
+ }
1225
+
1226
+ .strand-nav__actions {
1227
+ display: none;
1228
+ }
1229
+
1230
+ .strand-nav__hamburger {
1231
+ display: inline-flex;
1232
+ }
1233
+
1234
+ .strand-nav__mobile-menu {
1235
+ display: flex;
1236
+ }
1237
+
1238
+ .strand-nav {
1239
+ height: auto;
1240
+ min-height: 64px;
1241
+ }
1242
+ }
1243
+
1244
+ /* ── Reduced motion ── */
1245
+ @media (prefers-reduced-motion: reduce) {
1246
+ .strand-nav__link,
1247
+ .strand-nav__mobile-link,
1248
+ .strand-nav__hamburger {
1249
+ transition: none;
1250
+ }
1251
+ }
1252
+
1253
+
1254
+ /* Progress */
1255
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1256
+
1257
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1258
+
1259
+ /* ── Bar base ── */
1260
+ .strand-progress--bar {
1261
+ width: 100%;
1262
+ background: var(--strand-gray-200);
1263
+ border-radius: var(--strand-radius-full);
1264
+ overflow: hidden;
1265
+ }
1266
+
1267
+ /* ── Bar sizes ── */
1268
+ .strand-progress--bar.strand-progress--sm {
1269
+ height: 4px;
1270
+ }
1271
+
1272
+ .strand-progress--bar.strand-progress--md {
1273
+ height: 8px;
1274
+ }
1275
+
1276
+ .strand-progress--bar.strand-progress--lg {
1277
+ height: 12px;
1278
+ }
1279
+
1280
+ /* ── Bar fill ── */
1281
+ .strand-progress--bar .strand-progress__fill {
1282
+ height: 100%;
1283
+ background: var(--strand-blue-primary);
1284
+ border-radius: var(--strand-radius-full);
1285
+ transition: width var(--strand-duration-normal) var(--strand-ease-out-quart);
1286
+ }
1287
+
1288
+ /* ── Bar indeterminate ── */
1289
+ .strand-progress--bar.strand-progress--indeterminate .strand-progress__fill {
1290
+ width: 40%;
1291
+ animation: strand-progress-shimmer 1.5s var(--strand-ease-in-out-sine) infinite;
1292
+ }
1293
+
1294
+ @keyframes strand-progress-shimmer {
1295
+ 0% {
1296
+ transform: translateX(-100%);
1297
+ }
1298
+ 100% {
1299
+ transform: translateX(350%);
1300
+ }
1301
+ }
1302
+
1303
+ /* ── Ring base ── */
1304
+ .strand-progress--ring {
1305
+ display: inline-flex;
1306
+ align-items: center;
1307
+ justify-content: center;
1308
+ }
1309
+
1310
+ /* ── Ring track and fill ── */
1311
+ .strand-progress__track {
1312
+ stroke: var(--strand-gray-200);
1313
+ }
1314
+
1315
+ .strand-progress__fill {
1316
+ stroke: var(--strand-blue-primary);
1317
+ }
1318
+
1319
+ .strand-progress--ring .strand-progress__ring {
1320
+ transition: stroke-dashoffset var(--strand-duration-normal) var(--strand-ease-out-quart);
1321
+ }
1322
+
1323
+ /* ── Ring indeterminate ── */
1324
+ .strand-progress--ring.strand-progress--indeterminate .strand-progress__ring {
1325
+ animation: strand-progress-rotate 1.2s linear infinite;
1326
+ }
1327
+
1328
+ @keyframes strand-progress-rotate {
1329
+ to {
1330
+ transform: rotate(360deg);
1331
+ }
1332
+ }
1333
+
1334
+ /* ── Reduced motion ── */
1335
+ @media (prefers-reduced-motion: reduce) {
1336
+ .strand-progress--bar .strand-progress__fill {
1337
+ transition: none;
1338
+ }
1339
+
1340
+ .strand-progress--bar.strand-progress--indeterminate .strand-progress__fill {
1341
+ animation: none;
1342
+ width: 100%;
1343
+ opacity: 0.4;
1344
+ }
1345
+
1346
+ .strand-progress--ring.strand-progress--indeterminate .strand-progress__ring {
1347
+ animation: none;
1348
+ }
1349
+ }
1350
+
1351
+
1352
+ /* Radio */
1353
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1354
+
1355
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1356
+
1357
+ /* ── Base ── */
1358
+ .strand-radio {
1359
+ display: inline-flex;
1360
+ align-items: center;
1361
+ gap: var(--strand-space-2);
1362
+ cursor: pointer;
1363
+ user-select: none;
1364
+ font-family: var(--strand-font-sans);
1365
+ font-size: var(--strand-text-sm);
1366
+ color: var(--strand-gray-900);
1367
+ line-height: var(--strand-leading-snug);
1368
+ }
1369
+
1370
+ /* ── Hidden native input ── */
1371
+ .strand-radio__native {
1372
+ position: absolute;
1373
+ width: 1px;
1374
+ height: 1px;
1375
+ padding: 0;
1376
+ margin: -1px;
1377
+ overflow: hidden;
1378
+ clip: rect(0, 0, 0, 0);
1379
+ white-space: nowrap;
1380
+ border: 0;
1381
+ }
1382
+
1383
+ /* ── Custom visual ── */
1384
+ .strand-radio__control {
1385
+ display: flex;
1386
+ align-items: center;
1387
+ justify-content: center;
1388
+ width: 18px;
1389
+ height: 18px;
1390
+ border: 1px solid var(--strand-gray-200);
1391
+ border-radius: var(--strand-radius-full);
1392
+ background: var(--strand-surface-elevated);
1393
+ flex-shrink: 0;
1394
+ transition:
1395
+ background var(--strand-duration-fast) var(--strand-ease-out-quart),
1396
+ border-color var(--strand-duration-fast) var(--strand-ease-out-quart),
1397
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-quart);
1398
+ }
1399
+
1400
+ .strand-radio__dot {
1401
+ width: 8px;
1402
+ height: 8px;
1403
+ border-radius: var(--strand-radius-full);
1404
+ background: var(--strand-on-blue-primary);
1405
+ transform: scale(0);
1406
+ transition: transform var(--strand-duration-fast) var(--strand-ease-out-expo);
1407
+ }
1408
+
1409
+ /* ── Focus ring ── */
1410
+ .strand-radio__native:focus-visible ~ .strand-radio__control {
1411
+ border-color: var(--strand-blue-primary);
1412
+ box-shadow: var(--strand-focus-ring);
1413
+ }
1414
+
1415
+ /* ── Checked ── */
1416
+ .strand-radio--checked .strand-radio__control {
1417
+ background: var(--strand-blue-primary);
1418
+ border-color: var(--strand-blue-primary);
1419
+ }
1420
+
1421
+ .strand-radio--checked .strand-radio__dot {
1422
+ transform: scale(1);
1423
+ }
1424
+
1425
+ /* ── Hover ── */
1426
+ .strand-radio:hover:not(.strand-radio--disabled) .strand-radio__control {
1427
+ border-color: var(--strand-blue-indicator);
1428
+ }
1429
+
1430
+ .strand-radio--checked:hover:not(.strand-radio--disabled) .strand-radio__control {
1431
+ background: var(--strand-blue-vivid);
1432
+ border-color: var(--strand-blue-vivid);
1433
+ }
1434
+
1435
+ /* ── Label ── */
1436
+ .strand-radio__label {
1437
+ color: var(--strand-gray-900);
1438
+ }
1439
+
1440
+ /* ── Disabled ── */
1441
+ .strand-radio--disabled {
1442
+ opacity: 0.4;
1443
+ cursor: not-allowed;
1444
+ }
1445
+
1446
+ /* ── Reduced motion ── */
1447
+ @media (prefers-reduced-motion: reduce) {
1448
+ .strand-radio__control,
1449
+ .strand-radio__dot {
1450
+ transition: none;
1451
+ }
1452
+ }
1453
+
1454
+
1455
+ /* Section */
1456
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1457
+
1458
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1459
+
1460
+ /* ── Base ── */
1461
+ .strand-section {
1462
+ width: 100%;
1463
+ }
1464
+
1465
+ /* ── Variants ── */
1466
+ .strand-section--standard {
1467
+ padding-block: clamp(4rem, 8vw, 8rem);
1468
+ }
1469
+
1470
+ .strand-section--hero {
1471
+ padding-block: clamp(6rem, 12vw, 12rem);
1472
+ }
1473
+
1474
+ /* ── Backgrounds ── */
1475
+ .strand-section--bg-primary {
1476
+ background-color: var(--strand-surface-primary);
1477
+ }
1478
+
1479
+ .strand-section--bg-elevated {
1480
+ background-color: var(--strand-surface-elevated);
1481
+ }
1482
+
1483
+ .strand-section--bg-recessed {
1484
+ background-color: var(--strand-surface-recessed);
1485
+ }
1486
+
1487
+
1488
+ /* Select */
1489
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1490
+
1491
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1492
+
1493
+ /* ── Base ── */
1494
+ .strand-select {
1495
+ position: relative;
1496
+ display: inline-flex;
1497
+ align-items: center;
1498
+ background: var(--strand-surface-elevated);
1499
+ border: 1px solid var(--strand-gray-200);
1500
+ border-radius: var(--strand-radius-md);
1501
+ transition:
1502
+ border-color var(--strand-duration-fast) var(--strand-ease-out-quart),
1503
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-quart);
1504
+ }
1505
+
1506
+ .strand-select:focus-within {
1507
+ border-color: var(--strand-blue-primary);
1508
+ box-shadow: var(--strand-focus-ring);
1509
+ }
1510
+
1511
+ /* ── Field ── */
1512
+ .strand-select__field {
1513
+ flex: 1;
1514
+ width: 100%;
1515
+ padding: var(--strand-space-3) var(--strand-space-8) var(--strand-space-3) var(--strand-space-4);
1516
+ background: transparent;
1517
+ border: none;
1518
+ font-family: var(--strand-font-sans);
1519
+ font-size: var(--strand-text-base);
1520
+ color: var(--strand-gray-900);
1521
+ outline: none;
1522
+ appearance: none;
1523
+ cursor: pointer;
1524
+ }
1525
+
1526
+ /* ── Arrow indicator ── */
1527
+ .strand-select__arrow {
1528
+ position: absolute;
1529
+ right: var(--strand-space-3);
1530
+ top: 50%;
1531
+ transform: translateY(-50%);
1532
+ width: 0;
1533
+ height: 0;
1534
+ border-left: 5px solid transparent;
1535
+ border-right: 5px solid transparent;
1536
+ border-top: 5px solid var(--strand-gray-500);
1537
+ pointer-events: none;
1538
+ }
1539
+
1540
+ /* ── Error ── */
1541
+ .strand-select--error {
1542
+ border-color: var(--strand-red-alert);
1543
+ }
1544
+
1545
+ .strand-select--error:focus-within {
1546
+ border-color: var(--strand-red-alert);
1547
+ box-shadow: var(--strand-focus-ring-error);
1548
+ }
1549
+
1550
+ /* ── Disabled ── */
1551
+ .strand-select--disabled {
1552
+ opacity: 0.4;
1553
+ cursor: not-allowed;
1554
+ }
1555
+
1556
+ .strand-select--disabled .strand-select__field {
1557
+ cursor: not-allowed;
1558
+ }
1559
+
1560
+ /* ── Reduced motion ── */
1561
+ @media (prefers-reduced-motion: reduce) {
1562
+ .strand-select {
1563
+ transition: none;
1564
+ }
1565
+ }
1566
+
1567
+
1568
+ /* Skeleton */
1569
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1570
+
1571
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1572
+
1573
+ /* ── Base ── */
1574
+ .strand-skeleton {
1575
+ display: block;
1576
+ background: var(--strand-gray-100);
1577
+ }
1578
+
1579
+ /* ── Shimmer ── */
1580
+ .strand-skeleton--shimmer {
1581
+ background: linear-gradient(
1582
+ 90deg,
1583
+ var(--strand-gray-100) 25%,
1584
+ var(--strand-gray-50) 50%,
1585
+ var(--strand-gray-100) 75%
1586
+ );
1587
+ background-size: 200% 100%;
1588
+ animation: strand-skeleton-shimmer 1.8s var(--strand-ease-in-out-sine) infinite;
1589
+ }
1590
+
1591
+ @keyframes strand-skeleton-shimmer {
1592
+ 0% {
1593
+ background-position: 200% 0;
1594
+ }
1595
+ 100% {
1596
+ background-position: -200% 0;
1597
+ }
1598
+ }
1599
+
1600
+ /* ── Text variant ── */
1601
+ .strand-skeleton--text {
1602
+ height: 1em;
1603
+ border-radius: var(--strand-radius-sm);
1604
+ }
1605
+
1606
+ /* ── Rectangle variant ── */
1607
+ .strand-skeleton--rectangle {
1608
+ border-radius: var(--strand-radius-md);
1609
+ }
1610
+
1611
+ /* ── Circle variant ── */
1612
+ .strand-skeleton--circle {
1613
+ border-radius: var(--strand-radius-full);
1614
+ }
1615
+
1616
+ /* ── Reduced motion ── */
1617
+ @media (prefers-reduced-motion: reduce) {
1618
+ .strand-skeleton--shimmer {
1619
+ animation: none;
1620
+ background: var(--strand-gray-100);
1621
+ }
1622
+ }
1623
+
1624
+
1625
+ /* Slider */
1626
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1627
+
1628
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1629
+
1630
+ /* ── Base ── */
1631
+ .strand-slider {
1632
+ position: relative;
1633
+ display: flex;
1634
+ align-items: center;
1635
+ width: 100%;
1636
+ }
1637
+
1638
+ /* ── Field ── */
1639
+ .strand-slider__field {
1640
+ width: 100%;
1641
+ height: 6px;
1642
+ appearance: none;
1643
+ background: var(--strand-gray-200);
1644
+ border-radius: var(--strand-radius-full);
1645
+ outline: none;
1646
+ cursor: pointer;
1647
+ transition: background var(--strand-duration-fast) var(--strand-ease-out-quart);
1648
+ }
1649
+
1650
+ /* ── Thumb: Webkit ── */
1651
+ .strand-slider__field::-webkit-slider-thumb {
1652
+ appearance: none;
1653
+ width: 20px;
1654
+ height: 20px;
1655
+ background: var(--strand-blue-primary);
1656
+ border: 2px solid var(--strand-surface-elevated);
1657
+ border-radius: var(--strand-radius-full);
1658
+ cursor: pointer;
1659
+ box-shadow: var(--strand-elevation-1);
1660
+ transition:
1661
+ background var(--strand-duration-fast) var(--strand-ease-out-quart),
1662
+ transform var(--strand-duration-fast) var(--strand-ease-out-expo);
1663
+ }
1664
+
1665
+ .strand-slider__field:hover:not(:disabled)::-webkit-slider-thumb {
1666
+ background: var(--strand-blue-vivid);
1667
+ transform: scale(1.15);
1668
+ }
1669
+
1670
+ .strand-slider__field:active:not(:disabled)::-webkit-slider-thumb {
1671
+ background: var(--strand-blue-deep);
1672
+ transform: scale(1.05);
1673
+ }
1674
+
1675
+ /* ── Thumb: Firefox ── */
1676
+ .strand-slider__field::-moz-range-thumb {
1677
+ width: 20px;
1678
+ height: 20px;
1679
+ background: var(--strand-blue-primary);
1680
+ border: 2px solid var(--strand-surface-elevated);
1681
+ border-radius: var(--strand-radius-full);
1682
+ cursor: pointer;
1683
+ box-shadow: var(--strand-elevation-1);
1684
+ transition:
1685
+ background var(--strand-duration-fast) var(--strand-ease-out-quart),
1686
+ transform var(--strand-duration-fast) var(--strand-ease-out-expo);
1687
+ }
1688
+
1689
+ .strand-slider__field:hover:not(:disabled)::-moz-range-thumb {
1690
+ background: var(--strand-blue-vivid);
1691
+ transform: scale(1.15);
1692
+ }
1693
+
1694
+ .strand-slider__field:active:not(:disabled)::-moz-range-thumb {
1695
+ background: var(--strand-blue-deep);
1696
+ transform: scale(1.05);
1697
+ }
1698
+
1699
+ /* ── Track: Firefox ── */
1700
+ .strand-slider__field::-moz-range-track {
1701
+ height: 6px;
1702
+ background: var(--strand-gray-200);
1703
+ border-radius: var(--strand-radius-full);
1704
+ }
1705
+
1706
+ /* ── Focus ── */
1707
+ .strand-slider__field:focus-visible::-webkit-slider-thumb {
1708
+ box-shadow: var(--strand-focus-ring);
1709
+ }
1710
+
1711
+ .strand-slider__field:focus-visible::-moz-range-thumb {
1712
+ box-shadow: var(--strand-focus-ring);
1713
+ }
1714
+
1715
+ /* ── Disabled ── */
1716
+ .strand-slider--disabled {
1717
+ opacity: 0.4;
1718
+ cursor: not-allowed;
1719
+ }
1720
+
1721
+ .strand-slider--disabled .strand-slider__field {
1722
+ cursor: not-allowed;
1723
+ }
1724
+
1725
+ /* ── Reduced motion ── */
1726
+ @media (prefers-reduced-motion: reduce) {
1727
+ .strand-slider__field::-webkit-slider-thumb {
1728
+ transition: none;
1729
+ }
1730
+
1731
+ .strand-slider__field::-moz-range-thumb {
1732
+ transition: none;
1733
+ }
1734
+ }
1735
+
1736
+
1737
+ /* Spinner */
1738
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1739
+
1740
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1741
+
1742
+ /* ── Base ── */
1743
+ .strand-spinner {
1744
+ display: inline-flex;
1745
+ align-items: center;
1746
+ justify-content: center;
1747
+ }
1748
+
1749
+ /* ── Ring ── */
1750
+ .strand-spinner__ring {
1751
+ display: block;
1752
+ border: 2px solid var(--strand-gray-200);
1753
+ border-top-color: var(--strand-blue-primary);
1754
+ border-radius: var(--strand-radius-full);
1755
+ animation: strand-spinner-rotate 0.8s linear infinite;
1756
+ }
1757
+
1758
+ /* ── Sizes ── */
1759
+ .strand-spinner--sm .strand-spinner__ring {
1760
+ width: 16px;
1761
+ height: 16px;
1762
+ }
1763
+
1764
+ .strand-spinner--md .strand-spinner__ring {
1765
+ width: 20px;
1766
+ height: 20px;
1767
+ }
1768
+
1769
+ .strand-spinner--lg .strand-spinner__ring {
1770
+ width: 32px;
1771
+ height: 32px;
1772
+ }
1773
+
1774
+ /* ── Animation ── */
1775
+ @keyframes strand-spinner-rotate {
1776
+ to {
1777
+ transform: rotate(360deg);
1778
+ }
1779
+ }
1780
+
1781
+ /* ── Screen reader only text ── */
1782
+ .strand-spinner__sr-only {
1783
+ position: absolute;
1784
+ width: 1px;
1785
+ height: 1px;
1786
+ padding: 0;
1787
+ margin: -1px;
1788
+ overflow: hidden;
1789
+ clip: rect(0, 0, 0, 0);
1790
+ white-space: nowrap;
1791
+ border: 0;
1792
+ }
1793
+
1794
+ /* ── Reduced motion ── */
1795
+ @media (prefers-reduced-motion: reduce) {
1796
+ .strand-spinner__ring {
1797
+ animation: none;
1798
+ border-style: dotted;
1799
+ }
1800
+ }
1801
+
1802
+
1803
+ /* Stack */
1804
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1805
+
1806
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1807
+
1808
+ /* ── Base ── */
1809
+ .strand-stack {
1810
+ display: flex;
1811
+ max-width: 100%;
1812
+ box-sizing: border-box;
1813
+ }
1814
+
1815
+ .strand-stack > * {
1816
+ min-width: 0;
1817
+ }
1818
+
1819
+ /* ── Direction ── */
1820
+ .strand-stack--vertical {
1821
+ flex-direction: column;
1822
+ }
1823
+
1824
+ .strand-stack--horizontal {
1825
+ flex-direction: row;
1826
+ }
1827
+
1828
+ /* ── Alignment ── */
1829
+ .strand-stack--align-start {
1830
+ align-items: flex-start;
1831
+ }
1832
+
1833
+ .strand-stack--align-center {
1834
+ align-items: center;
1835
+ }
1836
+
1837
+ .strand-stack--align-end {
1838
+ align-items: flex-end;
1839
+ }
1840
+
1841
+ /* Default stretch handled by flexbox default */
1842
+
1843
+ /* ── Justification ── */
1844
+ .strand-stack--justify-start {
1845
+ justify-content: flex-start;
1846
+ }
1847
+
1848
+ .strand-stack--justify-center {
1849
+ justify-content: center;
1850
+ }
1851
+
1852
+ .strand-stack--justify-end {
1853
+ justify-content: flex-end;
1854
+ }
1855
+
1856
+ .strand-stack--justify-between {
1857
+ justify-content: space-between;
1858
+ }
1859
+
1860
+ .strand-stack--justify-around {
1861
+ justify-content: space-around;
1862
+ }
1863
+
1864
+ /* ── Wrap ── */
1865
+ .strand-stack--wrap {
1866
+ flex-wrap: wrap;
1867
+ }
1868
+
1869
+ /* ── Gap utilities ── */
1870
+ .strand-stack--gap-1 { gap: var(--strand-space-1); }
1871
+ .strand-stack--gap-2 { gap: var(--strand-space-2); }
1872
+ .strand-stack--gap-3 { gap: var(--strand-space-3); }
1873
+ .strand-stack--gap-4 { gap: var(--strand-space-4); }
1874
+ .strand-stack--gap-5 { gap: var(--strand-space-5); }
1875
+ .strand-stack--gap-6 { gap: var(--strand-space-6); }
1876
+ .strand-stack--gap-8 { gap: var(--strand-space-8); }
1877
+
1878
+
1879
+ /* Switch */
1880
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1881
+
1882
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1883
+
1884
+ /* ── Base ── */
1885
+ .strand-switch {
1886
+ display: inline-flex;
1887
+ align-items: center;
1888
+ gap: var(--strand-space-2);
1889
+ cursor: pointer;
1890
+ user-select: none;
1891
+ font-family: var(--strand-font-sans);
1892
+ font-size: var(--strand-text-sm);
1893
+ color: var(--strand-gray-900);
1894
+ line-height: var(--strand-leading-snug);
1895
+ }
1896
+
1897
+ /* ── Track ── */
1898
+ .strand-switch__track {
1899
+ position: relative;
1900
+ display: inline-flex;
1901
+ align-items: center;
1902
+ width: 40px;
1903
+ height: 22px;
1904
+ padding: 0;
1905
+ border: 1px solid var(--strand-gray-200);
1906
+ border-radius: var(--strand-radius-full);
1907
+ background: var(--strand-gray-200);
1908
+ cursor: pointer;
1909
+ flex-shrink: 0;
1910
+ transition:
1911
+ background var(--strand-duration-fast) var(--strand-ease-out-quart),
1912
+ border-color var(--strand-duration-fast) var(--strand-ease-out-quart),
1913
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-quart);
1914
+ }
1915
+
1916
+ .strand-switch__track:focus-visible {
1917
+ border-color: var(--strand-blue-primary);
1918
+ box-shadow: var(--strand-focus-ring);
1919
+ outline: none;
1920
+ }
1921
+
1922
+ /* ── Thumb ── */
1923
+ .strand-switch__thumb {
1924
+ position: absolute;
1925
+ left: 2px;
1926
+ width: 16px;
1927
+ height: 16px;
1928
+ border-radius: var(--strand-radius-full);
1929
+ background: var(--strand-surface-elevated);
1930
+ box-shadow: var(--strand-elevation-1);
1931
+ transition: transform var(--strand-duration-fast) var(--strand-ease-out-expo);
1932
+ }
1933
+
1934
+ /* ── Checked ── */
1935
+ .strand-switch--checked .strand-switch__track {
1936
+ background: var(--strand-blue-primary);
1937
+ border-color: var(--strand-blue-primary);
1938
+ }
1939
+
1940
+ .strand-switch--checked .strand-switch__thumb {
1941
+ transform: translateX(18px);
1942
+ }
1943
+
1944
+ /* ── Hover ── */
1945
+ .strand-switch:hover:not(.strand-switch--disabled) .strand-switch__track {
1946
+ border-color: var(--strand-blue-indicator);
1947
+ }
1948
+
1949
+ .strand-switch--checked:hover:not(.strand-switch--disabled) .strand-switch__track {
1950
+ background: var(--strand-blue-vivid);
1951
+ border-color: var(--strand-blue-vivid);
1952
+ }
1953
+
1954
+ /* ── Label ── */
1955
+ .strand-switch__label {
1956
+ color: var(--strand-gray-900);
1957
+ }
1958
+
1959
+ /* ── Disabled ── */
1960
+ .strand-switch--disabled {
1961
+ opacity: 0.4;
1962
+ cursor: not-allowed;
1963
+ }
1964
+
1965
+ .strand-switch--disabled .strand-switch__track {
1966
+ cursor: not-allowed;
1967
+ }
1968
+
1969
+ /* ── Reduced motion ── */
1970
+ @media (prefers-reduced-motion: reduce) {
1971
+ .strand-switch__track,
1972
+ .strand-switch__thumb {
1973
+ transition: none;
1974
+ }
1975
+ }
1976
+
1977
+
1978
+ /* Table */
1979
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1980
+
1981
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1982
+
1983
+ /* ── Wrapper (responsive scroll) ── */
1984
+ .strand-table-wrapper {
1985
+ overflow-x: auto;
1986
+ -webkit-overflow-scrolling: touch;
1987
+ }
1988
+
1989
+ /* ── Table ── */
1990
+ .strand-table {
1991
+ width: 100%;
1992
+ border-collapse: collapse;
1993
+ border-spacing: 0;
1994
+ }
1995
+
1996
+ /* ── Header ── */
1997
+ .strand-table__th {
1998
+ padding: var(--strand-space-3) var(--strand-space-4);
1999
+ font-family: var(--strand-font-mono);
2000
+ font-size: var(--strand-text-xs);
2001
+ font-weight: var(--strand-weight-medium);
2002
+ letter-spacing: var(--strand-tracking-widest);
2003
+ text-transform: uppercase;
2004
+ color: var(--strand-gray-500);
2005
+ text-align: left;
2006
+ border-bottom: 1px solid var(--strand-gray-200);
2007
+ white-space: nowrap;
2008
+ }
2009
+
2010
+ /* ── Sort button ── */
2011
+ .strand-table__sort-btn {
2012
+ display: inline-flex;
2013
+ align-items: center;
2014
+ gap: var(--strand-space-1);
2015
+ padding: 0;
2016
+ border: none;
2017
+ background: none;
2018
+ font: inherit;
2019
+ color: inherit;
2020
+ letter-spacing: inherit;
2021
+ text-transform: inherit;
2022
+ cursor: pointer;
2023
+ white-space: nowrap;
2024
+ }
2025
+
2026
+ .strand-table__sort-btn:hover {
2027
+ color: var(--strand-gray-600);
2028
+ }
2029
+
2030
+ .strand-table__sort-btn:focus-visible {
2031
+ outline: 2px solid var(--strand-blue-primary);
2032
+ outline-offset: 2px;
2033
+ }
2034
+
2035
+ .strand-table__sort-indicator {
2036
+ font-size: var(--strand-text-xs);
2037
+ opacity: 0.6;
2038
+ }
2039
+
2040
+ /* ── Body ── */
2041
+ .strand-table__td {
2042
+ padding: var(--strand-space-3) var(--strand-space-4);
2043
+ font-family: var(--strand-font-sans);
2044
+ font-size: var(--strand-text-sm);
2045
+ color: var(--strand-gray-600);
2046
+ border-bottom: 1px solid var(--strand-gray-200);
2047
+ }
2048
+
2049
+ /* ── Row hover ── */
2050
+ .strand-table__row {
2051
+ transition: background var(--strand-duration-fast) var(--strand-ease-out-quart);
2052
+ }
2053
+
2054
+ .strand-table__row:hover {
2055
+ background: var(--strand-blue-glow);
2056
+ }
2057
+
2058
+ /* ── Reduced motion ── */
2059
+ @media (prefers-reduced-motion: reduce) {
2060
+ .strand-table__row {
2061
+ transition: none;
2062
+ }
2063
+ }
2064
+
2065
+
2066
+ /* Tabs */
2067
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2068
+
2069
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2070
+
2071
+ /* ── Tab list ── */
2072
+ .strand-tabs [role="tablist"] {
2073
+ display: flex;
2074
+ gap: var(--strand-space-1);
2075
+ border-bottom: 1px solid var(--strand-gray-400);
2076
+ }
2077
+
2078
+ /* ── Tab button ── */
2079
+ .strand-tabs__tab {
2080
+ position: relative;
2081
+ padding: var(--strand-space-2) var(--strand-space-4);
2082
+ border: none;
2083
+ border-bottom: 2px solid transparent;
2084
+ background: none;
2085
+ font-family: var(--strand-font-sans);
2086
+ font-size: var(--strand-text-sm);
2087
+ font-weight: var(--strand-weight-medium);
2088
+ color: var(--strand-gray-500);
2089
+ cursor: pointer;
2090
+ transition:
2091
+ color var(--strand-duration-fast) var(--strand-ease-out-quart),
2092
+ border-color var(--strand-duration-fast) var(--strand-ease-out-expo);
2093
+ }
2094
+
2095
+ .strand-tabs__tab:hover {
2096
+ color: var(--strand-gray-600);
2097
+ }
2098
+
2099
+ .strand-tabs__tab:focus-visible {
2100
+ outline: 2px solid var(--strand-blue-primary);
2101
+ outline-offset: 2px;
2102
+ }
2103
+
2104
+ .strand-tabs__tab--active {
2105
+ color: var(--strand-blue-primary);
2106
+ border-bottom-color: var(--strand-blue-primary);
2107
+ }
2108
+
2109
+ /* ── Panel ── */
2110
+ .strand-tabs [role="tabpanel"] {
2111
+ padding: var(--strand-space-4) 0;
2112
+ }
2113
+
2114
+ /* ── Reduced motion ── */
2115
+ @media (prefers-reduced-motion: reduce) {
2116
+ .strand-tabs__tab {
2117
+ transition: none;
2118
+ }
2119
+ }
2120
+
2121
+
2122
+ /* Tag */
2123
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2124
+
2125
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2126
+
2127
+ /* ── Base ── */
2128
+ .strand-tag {
2129
+ display: inline-flex;
2130
+ align-items: center;
2131
+ gap: var(--strand-space-1);
2132
+ padding: var(--strand-space-1) var(--strand-space-2);
2133
+ border-radius: var(--strand-radius-sm);
2134
+ font-family: var(--strand-font-sans);
2135
+ font-size: var(--strand-text-xs);
2136
+ font-weight: var(--strand-weight-medium);
2137
+ line-height: var(--strand-leading-snug);
2138
+ white-space: nowrap;
2139
+ border: 1px solid transparent;
2140
+ }
2141
+
2142
+ /* ── Solid variant ── */
2143
+ .strand-tag--solid.strand-tag--default {
2144
+ background: var(--strand-surface-recessed);
2145
+ color: var(--strand-gray-600);
2146
+ }
2147
+
2148
+ .strand-tag--solid.strand-tag--teal {
2149
+ background: rgba(20, 184, 166, 0.1);
2150
+ color: var(--strand-on-teal-tint);
2151
+ }
2152
+
2153
+ .strand-tag--solid.strand-tag--blue {
2154
+ background: var(--strand-blue-glow);
2155
+ color: var(--strand-blue-deep);
2156
+ }
2157
+
2158
+ .strand-tag--solid.strand-tag--amber {
2159
+ background: rgba(245, 158, 11, 0.1);
2160
+ color: var(--strand-on-amber-tint);
2161
+ }
2162
+
2163
+ .strand-tag--solid.strand-tag--red {
2164
+ background: rgba(239, 68, 68, 0.1);
2165
+ color: var(--strand-on-red-tint);
2166
+ }
2167
+
2168
+ /* ── Outlined variant ── */
2169
+ .strand-tag--outlined {
2170
+ background: transparent;
2171
+ }
2172
+
2173
+ .strand-tag--outlined.strand-tag--default {
2174
+ border-color: var(--strand-gray-200);
2175
+ color: var(--strand-gray-600);
2176
+ }
2177
+
2178
+ .strand-tag--outlined.strand-tag--teal {
2179
+ border-color: var(--strand-teal-vital);
2180
+ color: var(--strand-on-teal-tint);
2181
+ }
2182
+
2183
+ .strand-tag--outlined.strand-tag--blue {
2184
+ border-color: var(--strand-blue-primary);
2185
+ color: var(--strand-blue-deep);
2186
+ }
2187
+
2188
+ .strand-tag--outlined.strand-tag--amber {
2189
+ border-color: var(--strand-amber-caution);
2190
+ color: var(--strand-on-amber-tint);
2191
+ }
2192
+
2193
+ .strand-tag--outlined.strand-tag--red {
2194
+ border-color: var(--strand-red-alert);
2195
+ color: var(--strand-on-red-tint);
2196
+ }
2197
+
2198
+ /* ── Remove button ── */
2199
+ .strand-tag__remove {
2200
+ display: inline-flex;
2201
+ align-items: center;
2202
+ justify-content: center;
2203
+ padding: 0;
2204
+ border: none;
2205
+ background: none;
2206
+ color: currentColor;
2207
+ opacity: 0.6;
2208
+ cursor: pointer;
2209
+ border-radius: var(--strand-radius-sm);
2210
+ transition: opacity var(--strand-duration-fast) var(--strand-ease-out-quart);
2211
+ }
2212
+
2213
+ .strand-tag__remove:hover {
2214
+ opacity: 1;
2215
+ }
2216
+
2217
+ /* ── Reduced motion ── */
2218
+ @media (prefers-reduced-motion: reduce) {
2219
+ .strand-tag__remove {
2220
+ transition: none;
2221
+ }
2222
+ }
2223
+
2224
+
2225
+ /* Textarea */
2226
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2227
+
2228
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2229
+
2230
+ /* ── Base ── */
2231
+ .strand-textarea {
2232
+ position: relative;
2233
+ display: flex;
2234
+ flex-direction: column;
2235
+ background: var(--strand-surface-elevated);
2236
+ border: 1px solid var(--strand-gray-200);
2237
+ border-radius: var(--strand-radius-md);
2238
+ transition:
2239
+ border-color var(--strand-duration-fast) var(--strand-ease-out-quart),
2240
+ box-shadow var(--strand-duration-fast) var(--strand-ease-out-quart);
2241
+ }
2242
+
2243
+ .strand-textarea:focus-within {
2244
+ border-color: var(--strand-blue-primary);
2245
+ box-shadow: var(--strand-focus-ring);
2246
+ }
2247
+
2248
+ /* ── Field ── */
2249
+ .strand-textarea__field {
2250
+ width: 100%;
2251
+ min-height: 80px;
2252
+ padding: var(--strand-space-3) var(--strand-space-4);
2253
+ background: transparent;
2254
+ border: none;
2255
+ font-family: var(--strand-font-sans);
2256
+ font-size: var(--strand-text-base);
2257
+ color: var(--strand-gray-900);
2258
+ outline: none;
2259
+ resize: vertical;
2260
+ line-height: var(--strand-leading-normal);
2261
+ }
2262
+
2263
+ .strand-textarea__field::placeholder {
2264
+ color: var(--strand-gray-400);
2265
+ }
2266
+
2267
+ /* ── Auto-resize ── */
2268
+ .strand-textarea--auto-resize .strand-textarea__field {
2269
+ resize: none;
2270
+ overflow: hidden;
2271
+ }
2272
+
2273
+ /* ── Character count ── */
2274
+ .strand-textarea__count {
2275
+ align-self: flex-end;
2276
+ padding: var(--strand-space-1) var(--strand-space-3) var(--strand-space-2);
2277
+ font-family: var(--strand-font-sans);
2278
+ font-size: var(--strand-text-xs);
2279
+ color: var(--strand-gray-500);
2280
+ }
2281
+
2282
+ /* ── Error ── */
2283
+ .strand-textarea--error {
2284
+ border-color: var(--strand-red-alert);
2285
+ }
2286
+
2287
+ .strand-textarea--error:focus-within {
2288
+ border-color: var(--strand-red-alert);
2289
+ box-shadow: var(--strand-focus-ring-error);
2290
+ }
2291
+
2292
+ /* ── Disabled ── */
2293
+ .strand-textarea--disabled {
2294
+ opacity: 0.4;
2295
+ cursor: not-allowed;
2296
+ }
2297
+
2298
+ .strand-textarea--disabled .strand-textarea__field {
2299
+ cursor: not-allowed;
2300
+ }
2301
+
2302
+ /* ── Reduced motion ── */
2303
+ @media (prefers-reduced-motion: reduce) {
2304
+ .strand-textarea {
2305
+ transition: none;
2306
+ }
2307
+ }
2308
+
2309
+
2310
+ /* Toast */
2311
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2312
+
2313
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2314
+
2315
+ /* ── Container ── */
2316
+ .strand-toast__container {
2317
+ position: fixed;
2318
+ right: var(--strand-space-6);
2319
+ bottom: var(--strand-space-6);
2320
+ z-index: 1100;
2321
+ display: flex;
2322
+ flex-direction: column-reverse;
2323
+ gap: var(--strand-space-3);
2324
+ pointer-events: none;
2325
+ }
2326
+
2327
+ /* ── Toast ── */
2328
+ .strand-toast {
2329
+ display: flex;
2330
+ align-items: center;
2331
+ justify-content: space-between;
2332
+ min-width: 280px;
2333
+ max-width: 420px;
2334
+ padding: var(--strand-space-4) var(--strand-space-5);
2335
+ background: var(--strand-surface-elevated);
2336
+ border-radius: var(--strand-radius-lg);
2337
+ border-left: 4px solid transparent;
2338
+ box-shadow: var(--strand-elevation-3);
2339
+ font-family: var(--strand-font-sans);
2340
+ font-size: var(--strand-text-sm);
2341
+ pointer-events: auto;
2342
+ animation: strand-toast-in var(--strand-duration-normal) var(--strand-ease-out-expo);
2343
+ }
2344
+
2345
+ /* ── Status accents ── */
2346
+ .strand-toast--info {
2347
+ border-left-color: var(--strand-blue-primary);
2348
+ }
2349
+
2350
+ .strand-toast--success {
2351
+ border-left-color: var(--strand-green-positive);
2352
+ }
2353
+
2354
+ .strand-toast--warning {
2355
+ border-left-color: var(--strand-amber-caution);
2356
+ }
2357
+
2358
+ .strand-toast--error {
2359
+ border-left-color: var(--strand-red-alert);
2360
+ }
2361
+
2362
+ /* ── Message ── */
2363
+ .strand-toast__message {
2364
+ flex: 1;
2365
+ min-width: 0;
2366
+ color: var(--strand-gray-900);
2367
+ }
2368
+
2369
+ /* ── Dismiss button ── */
2370
+ .strand-toast__dismiss {
2371
+ flex-shrink: 0;
2372
+ display: inline-flex;
2373
+ align-items: center;
2374
+ justify-content: center;
2375
+ width: 24px;
2376
+ height: 24px;
2377
+ margin-left: var(--strand-space-3);
2378
+ padding: 0;
2379
+ border: none;
2380
+ border-radius: var(--strand-radius-md);
2381
+ background: transparent;
2382
+ color: var(--strand-gray-500);
2383
+ font-size: var(--strand-text-base);
2384
+ cursor: pointer;
2385
+ transition: background var(--strand-duration-fast) var(--strand-ease-out-quart),
2386
+ color var(--strand-duration-fast) var(--strand-ease-out-quart);
2387
+ }
2388
+
2389
+ .strand-toast__dismiss:hover {
2390
+ background: var(--strand-gray-200);
2391
+ color: var(--strand-gray-600);
2392
+ }
2393
+
2394
+ /* ── Animations ── */
2395
+ @keyframes strand-toast-in {
2396
+ from {
2397
+ opacity: 0;
2398
+ transform: translateY(8px);
2399
+ }
2400
+ to {
2401
+ opacity: 1;
2402
+ transform: translateY(0);
2403
+ }
2404
+ }
2405
+
2406
+ /* ── Reduced motion ── */
2407
+ @media (prefers-reduced-motion: reduce) {
2408
+ .strand-toast {
2409
+ animation: none;
2410
+ }
2411
+
2412
+ .strand-toast__dismiss {
2413
+ transition: none;
2414
+ }
2415
+ }
2416
+
2417
+
2418
+ /* Tooltip */
2419
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2420
+
2421
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2422
+
2423
+ /* ── Wrapper ── */
2424
+ .strand-tooltip__wrapper {
2425
+ position: relative;
2426
+ display: inline-flex;
2427
+ }
2428
+
2429
+ /* ── Tooltip ── */
2430
+ .strand-tooltip {
2431
+ position: absolute;
2432
+ z-index: 1200;
2433
+ padding: var(--strand-space-1) var(--strand-space-2);
2434
+ background: var(--strand-gray-900);
2435
+ color: var(--strand-on-blue-primary);
2436
+ font-family: var(--strand-font-sans);
2437
+ font-size: var(--strand-text-xs);
2438
+ border-radius: var(--strand-radius-md);
2439
+ white-space: nowrap;
2440
+ pointer-events: none;
2441
+ opacity: 0;
2442
+ transition: opacity var(--strand-duration-fast) var(--strand-ease-out-quart);
2443
+ }
2444
+
2445
+ .strand-tooltip--visible {
2446
+ opacity: 1;
2447
+ }
2448
+
2449
+ /* ── Positions ── */
2450
+ .strand-tooltip--top {
2451
+ bottom: 100%;
2452
+ left: 50%;
2453
+ transform: translateX(-50%);
2454
+ margin-bottom: var(--strand-space-2);
2455
+ }
2456
+
2457
+ .strand-tooltip--bottom {
2458
+ top: 100%;
2459
+ left: 50%;
2460
+ transform: translateX(-50%);
2461
+ margin-top: var(--strand-space-2);
2462
+ }
2463
+
2464
+ .strand-tooltip--left {
2465
+ right: 100%;
2466
+ top: 50%;
2467
+ transform: translateY(-50%);
2468
+ margin-right: var(--strand-space-2);
2469
+ }
2470
+
2471
+ .strand-tooltip--right {
2472
+ left: 100%;
2473
+ top: 50%;
2474
+ transform: translateY(-50%);
2475
+ margin-left: var(--strand-space-2);
2476
+ }
2477
+
2478
+ /* ── Reduced motion ── */
2479
+ @media (prefers-reduced-motion: reduce) {
2480
+ .strand-tooltip {
2481
+ transition: none;
2482
+ }
2483
+ }
2484
+
2485
+
2486
+ /* Static & Utilities */
2487
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2488
+
2489
+ /* ── Presentation mode ──
2490
+ Add .strand-static to a parent element to render components
2491
+ at full visual fidelity without interaction.
2492
+ Use for documentation, showcases, and screenshots. */
2493
+
2494
+ .strand-static {
2495
+ pointer-events: none;
2496
+ }
2497
+
2498
+ .strand-static [disabled],
2499
+ .strand-static [aria-disabled="true"] {
2500
+ opacity: 1;
2501
+ cursor: default;
2502
+ }
2503
+
2504
+ .strand-static .strand-btn:disabled {
2505
+ opacity: 1;
2506
+ cursor: default;
2507
+ }
2508
+
2509
+ .strand-static .strand-toast {
2510
+ position: static;
2511
+ }
2512
+
2513
+ .strand-static .strand-tooltip {
2514
+ position: static;
2515
+ }
2516
+
2517
+ .strand-static *,
2518
+ .strand-static *::before,
2519
+ .strand-static *::after {
2520
+ transition: none !important;
2521
+ animation: none !important;
2522
+ }
2523
+
2524
+ /* ── Recessed viewport ──
2525
+ The instrument viewport sits below the card surface.
2526
+ Use for component previews, showcases, and documentation. */
2527
+
2528
+ .strand-viewport {
2529
+ background: var(--strand-surface-recessed);
2530
+ box-shadow: inset 0 1px 3px rgba(15, 23, 42, 0.06);
2531
+ border-radius: var(--strand-radius-lg);
2532
+ padding: var(--strand-space-6);
2533
+ }
2534
+