@dillingerstaffing/strand-ui 0.1.0 → 0.1.1

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