@striae-org/striae 3.0.4

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 (223) hide show
  1. package/.env.example +100 -0
  2. package/LICENSE +190 -0
  3. package/NOTICE +18 -0
  4. package/README.md +133 -0
  5. package/app/components/actions/case-export/core-export.ts +328 -0
  6. package/app/components/actions/case-export/data-processing.ts +167 -0
  7. package/app/components/actions/case-export/download-handlers.ts +900 -0
  8. package/app/components/actions/case-export/index.ts +41 -0
  9. package/app/components/actions/case-export/metadata-helpers.ts +107 -0
  10. package/app/components/actions/case-export/types-constants.ts +56 -0
  11. package/app/components/actions/case-export/validation-utils.ts +25 -0
  12. package/app/components/actions/case-export.ts +4 -0
  13. package/app/components/actions/case-import/annotation-import.ts +35 -0
  14. package/app/components/actions/case-import/confirmation-import.ts +363 -0
  15. package/app/components/actions/case-import/image-operations.ts +61 -0
  16. package/app/components/actions/case-import/index.ts +39 -0
  17. package/app/components/actions/case-import/orchestrator.ts +420 -0
  18. package/app/components/actions/case-import/storage-operations.ts +270 -0
  19. package/app/components/actions/case-import/validation.ts +189 -0
  20. package/app/components/actions/case-import/zip-processing.ts +413 -0
  21. package/app/components/actions/case-manage.ts +524 -0
  22. package/app/components/actions/case-review.ts +4 -0
  23. package/app/components/actions/confirm-export.ts +351 -0
  24. package/app/components/actions/generate-pdf.ts +210 -0
  25. package/app/components/actions/image-manage.ts +385 -0
  26. package/app/components/actions/notes-manage.ts +33 -0
  27. package/app/components/actions/signout.module.css +15 -0
  28. package/app/components/actions/signout.tsx +50 -0
  29. package/app/components/audit/user-audit-viewer.tsx +975 -0
  30. package/app/components/audit/user-audit.module.css +568 -0
  31. package/app/components/auth/auth-provider.tsx +78 -0
  32. package/app/components/auth/mfa-enrollment.module.css +268 -0
  33. package/app/components/auth/mfa-enrollment.tsx +398 -0
  34. package/app/components/auth/mfa-verification.module.css +251 -0
  35. package/app/components/auth/mfa-verification.tsx +295 -0
  36. package/app/components/button/button.module.css +63 -0
  37. package/app/components/button/button.tsx +46 -0
  38. package/app/components/canvas/box-annotations/box-annotations.module.css +170 -0
  39. package/app/components/canvas/box-annotations/box-annotations.tsx +634 -0
  40. package/app/components/canvas/canvas.module.css +314 -0
  41. package/app/components/canvas/canvas.tsx +449 -0
  42. package/app/components/canvas/confirmation/confirmation.module.css +187 -0
  43. package/app/components/canvas/confirmation/confirmation.tsx +214 -0
  44. package/app/components/colors/colors.module.css +59 -0
  45. package/app/components/colors/colors.tsx +68 -0
  46. package/app/components/form/base-form.tsx +21 -0
  47. package/app/components/form/form-button.tsx +28 -0
  48. package/app/components/form/form-field.tsx +53 -0
  49. package/app/components/form/form-message.tsx +17 -0
  50. package/app/components/form/form-toggle.tsx +23 -0
  51. package/app/components/form/form.module.css +427 -0
  52. package/app/components/form/index.ts +6 -0
  53. package/app/components/icon/icon.module.css +3 -0
  54. package/app/components/icon/icon.tsx +27 -0
  55. package/app/components/icon/icons.svg +102 -0
  56. package/app/components/icon/manifest.json +110 -0
  57. package/app/components/sidebar/case-export/case-export.module.css +386 -0
  58. package/app/components/sidebar/case-export/case-export.tsx +317 -0
  59. package/app/components/sidebar/case-import/case-import.module.css +626 -0
  60. package/app/components/sidebar/case-import/case-import.tsx +404 -0
  61. package/app/components/sidebar/case-import/components/CasePreviewSection.tsx +72 -0
  62. package/app/components/sidebar/case-import/components/ConfirmationDialog.tsx +72 -0
  63. package/app/components/sidebar/case-import/components/ConfirmationPreviewSection.tsx +71 -0
  64. package/app/components/sidebar/case-import/components/ExistingCaseSection.tsx +40 -0
  65. package/app/components/sidebar/case-import/components/FileSelector.tsx +161 -0
  66. package/app/components/sidebar/case-import/components/ProgressSection.tsx +46 -0
  67. package/app/components/sidebar/case-import/hooks/useFilePreview.ts +101 -0
  68. package/app/components/sidebar/case-import/hooks/useImportExecution.ts +152 -0
  69. package/app/components/sidebar/case-import/hooks/useImportState.ts +88 -0
  70. package/app/components/sidebar/case-import/index.ts +18 -0
  71. package/app/components/sidebar/case-import/utils/file-validation.ts +43 -0
  72. package/app/components/sidebar/cases/case-sidebar.tsx +827 -0
  73. package/app/components/sidebar/cases/cases-modal.module.css +166 -0
  74. package/app/components/sidebar/cases/cases-modal.tsx +201 -0
  75. package/app/components/sidebar/cases/cases.module.css +713 -0
  76. package/app/components/sidebar/files/files-modal.module.css +209 -0
  77. package/app/components/sidebar/files/files-modal.tsx +239 -0
  78. package/app/components/sidebar/hash/hash-utility.module.css +366 -0
  79. package/app/components/sidebar/hash/hash-utility.tsx +982 -0
  80. package/app/components/sidebar/notes/notes-modal.tsx +51 -0
  81. package/app/components/sidebar/notes/notes-sidebar.tsx +491 -0
  82. package/app/components/sidebar/notes/notes.module.css +360 -0
  83. package/app/components/sidebar/sidebar-container.tsx +149 -0
  84. package/app/components/sidebar/sidebar.module.css +321 -0
  85. package/app/components/sidebar/sidebar.tsx +215 -0
  86. package/app/components/sidebar/upload/image-upload-zone.module.css +123 -0
  87. package/app/components/sidebar/upload/image-upload-zone.tsx +330 -0
  88. package/app/components/theme-provider/theme-provider.tsx +131 -0
  89. package/app/components/theme-provider/theme.ts +155 -0
  90. package/app/components/toast/toast.module.css +137 -0
  91. package/app/components/toast/toast.tsx +56 -0
  92. package/app/components/toolbar/toolbar-color-selector.module.css +171 -0
  93. package/app/components/toolbar/toolbar-color-selector.tsx +129 -0
  94. package/app/components/toolbar/toolbar.module.css +42 -0
  95. package/app/components/toolbar/toolbar.tsx +167 -0
  96. package/app/components/user/delete-account.module.css +274 -0
  97. package/app/components/user/delete-account.tsx +471 -0
  98. package/app/components/user/inactivity-warning.module.css +145 -0
  99. package/app/components/user/inactivity-warning.tsx +84 -0
  100. package/app/components/user/manage-profile.module.css +190 -0
  101. package/app/components/user/manage-profile.tsx +253 -0
  102. package/app/components/user/mfa-phone-update.tsx +739 -0
  103. package/app/config-example/admin-service.json +13 -0
  104. package/app/config-example/config.json +17 -0
  105. package/app/config-example/firebase.ts +21 -0
  106. package/app/config-example/inactivity.ts +13 -0
  107. package/app/config-example/meta-config.json +6 -0
  108. package/app/contexts/auth.context.ts +12 -0
  109. package/app/entry.client.tsx +12 -0
  110. package/app/entry.server.tsx +44 -0
  111. package/app/hooks/useInactivityTimeout.ts +110 -0
  112. package/app/root.tsx +170 -0
  113. package/app/routes/_index.tsx +16 -0
  114. package/app/routes/auth/emailActionHandler.module.css +232 -0
  115. package/app/routes/auth/emailActionHandler.tsx +405 -0
  116. package/app/routes/auth/emailVerification.tsx +120 -0
  117. package/app/routes/auth/login.module.css +523 -0
  118. package/app/routes/auth/login.tsx +654 -0
  119. package/app/routes/auth/passwordReset.module.css +274 -0
  120. package/app/routes/auth/passwordReset.tsx +154 -0
  121. package/app/routes/auth/route.ts +16 -0
  122. package/app/routes/mobile-prevented/mobilePrevented.module.css +47 -0
  123. package/app/routes/mobile-prevented/mobilePrevented.tsx +26 -0
  124. package/app/routes/mobile-prevented/route.ts +14 -0
  125. package/app/routes/striae/striae.module.css +30 -0
  126. package/app/routes/striae/striae.tsx +417 -0
  127. package/app/services/audit-export.service.ts +755 -0
  128. package/app/services/audit.service.ts +1454 -0
  129. package/app/services/firebase-errors.ts +106 -0
  130. package/app/services/firebase.ts +15 -0
  131. package/app/styles/legal-pages.module.css +113 -0
  132. package/app/styles/root.module.css +146 -0
  133. package/app/tailwind.css +225 -0
  134. package/app/types/annotations.ts +45 -0
  135. package/app/types/audit.ts +301 -0
  136. package/app/types/case.ts +90 -0
  137. package/app/types/export.ts +8 -0
  138. package/app/types/file.ts +30 -0
  139. package/app/types/import.ts +107 -0
  140. package/app/types/index.ts +24 -0
  141. package/app/types/user.ts +38 -0
  142. package/app/utils/SHA256.ts +461 -0
  143. package/app/utils/annotation-timestamp.ts +25 -0
  144. package/app/utils/audit-export-signature.ts +117 -0
  145. package/app/utils/auth-action-settings.ts +48 -0
  146. package/app/utils/auth.ts +34 -0
  147. package/app/utils/batch-operations.ts +135 -0
  148. package/app/utils/confirmation-signature.ts +193 -0
  149. package/app/utils/data-operations.ts +871 -0
  150. package/app/utils/device-detection.ts +5 -0
  151. package/app/utils/html-sanitizer.ts +80 -0
  152. package/app/utils/id-generator.ts +36 -0
  153. package/app/utils/meta.ts +48 -0
  154. package/app/utils/mfa-phone.ts +97 -0
  155. package/app/utils/mfa.ts +79 -0
  156. package/app/utils/password-policy.ts +28 -0
  157. package/app/utils/permissions.ts +562 -0
  158. package/app/utils/signature-utils.ts +160 -0
  159. package/app/utils/style.ts +83 -0
  160. package/app/utils/version.ts +5 -0
  161. package/firebase.json +11 -0
  162. package/functions/[[path]].ts +10 -0
  163. package/package.json +138 -0
  164. package/postcss.config.js +6 -0
  165. package/public/.well-known/publickey.info@striae.org.asc +17 -0
  166. package/public/.well-known/security.txt +7 -0
  167. package/public/_headers +28 -0
  168. package/public/_routes.json +13 -0
  169. package/public/assets/striae.jpg +0 -0
  170. package/public/clear.jpg +0 -0
  171. package/public/favicon.ico +0 -0
  172. package/public/favicon.svg +9 -0
  173. package/public/icon-256.png +0 -0
  174. package/public/icon-512.png +0 -0
  175. package/public/logo-dark.png +0 -0
  176. package/public/manifest.json +25 -0
  177. package/public/oin-badge.png +0 -0
  178. package/public/shortcut.png +0 -0
  179. package/public/social-image.png +0 -0
  180. package/public/striae-ascii.txt +10 -0
  181. package/scripts/deploy-all.sh +100 -0
  182. package/scripts/deploy-config.sh +940 -0
  183. package/scripts/deploy-pages.sh +34 -0
  184. package/scripts/deploy-worker-secrets.sh +215 -0
  185. package/scripts/dev.cjs +23 -0
  186. package/scripts/install-workers.sh +88 -0
  187. package/scripts/run-eslint.cjs +35 -0
  188. package/scripts/update-compatibility-dates.cjs +124 -0
  189. package/scripts/update-markdown-versions.cjs +43 -0
  190. package/tailwind.config.ts +22 -0
  191. package/tsconfig.json +33 -0
  192. package/vite.config.ts +35 -0
  193. package/worker-configuration.d.ts +7490 -0
  194. package/workers/audit-worker/package.json +17 -0
  195. package/workers/audit-worker/src/audit-worker.example.ts +195 -0
  196. package/workers/audit-worker/worker-configuration.d.ts +7448 -0
  197. package/workers/audit-worker/wrangler.jsonc.example +29 -0
  198. package/workers/data-worker/package.json +17 -0
  199. package/workers/data-worker/src/data-worker.example.ts +267 -0
  200. package/workers/data-worker/src/signature-utils.ts +79 -0
  201. package/workers/data-worker/src/signing-payload-utils.ts +290 -0
  202. package/workers/data-worker/worker-configuration.d.ts +7448 -0
  203. package/workers/data-worker/wrangler.jsonc.example +30 -0
  204. package/workers/image-worker/package.json +17 -0
  205. package/workers/image-worker/src/image-worker.example.ts +180 -0
  206. package/workers/image-worker/worker-configuration.d.ts +7447 -0
  207. package/workers/image-worker/wrangler.jsonc.example +22 -0
  208. package/workers/keys-worker/package.json +17 -0
  209. package/workers/keys-worker/src/keys.example.ts +66 -0
  210. package/workers/keys-worker/src/keys.ts +66 -0
  211. package/workers/keys-worker/worker-configuration.d.ts +7447 -0
  212. package/workers/keys-worker/wrangler.jsonc.example +22 -0
  213. package/workers/pdf-worker/package.json +17 -0
  214. package/workers/pdf-worker/src/format-striae.ts +534 -0
  215. package/workers/pdf-worker/src/pdf-worker.example.ts +119 -0
  216. package/workers/pdf-worker/src/report-types.ts +69 -0
  217. package/workers/pdf-worker/worker-configuration.d.ts +7448 -0
  218. package/workers/pdf-worker/wrangler.jsonc.example +26 -0
  219. package/workers/user-worker/package.json +17 -0
  220. package/workers/user-worker/src/user-worker.example.ts +636 -0
  221. package/workers/user-worker/worker-configuration.d.ts +7448 -0
  222. package/workers/user-worker/wrangler.jsonc.example +29 -0
  223. package/wrangler.toml.example +8 -0
@@ -0,0 +1,626 @@
1
+ .overlay {
2
+ position: fixed;
3
+ inset: 0;
4
+ background-color: color-mix(in lab, var(--background) 50%, transparent);
5
+ display: flex;
6
+ justify-content: center;
7
+ align-items: center;
8
+ z-index: var(--zIndex5);
9
+ transition: background-color var(--durationM) var(--bezierFastoutSlowin);
10
+ }
11
+
12
+ .modal {
13
+ background: var(--backgroundLight);
14
+ border-radius: var(--spaceXS);
15
+ width: 90%;
16
+ max-width: 600px;
17
+ max-height: 95vh;
18
+ box-shadow: 0 var(--spaceXS) var(--spaceL) color-mix(in lab, var(--black) 10%, transparent);
19
+ transition: background-color var(--durationM) var(--bezierFastoutSlowin);
20
+ display: flex;
21
+ flex-direction: column;
22
+ }
23
+
24
+ .header {
25
+ display: flex;
26
+ font-size: var(--fontSizeBodyL);
27
+ justify-content: space-between;
28
+ align-items: center;
29
+ padding: var(--spaceL);
30
+ border-bottom: 1px solid color-mix(in lab, var(--text) 10%, transparent);
31
+ color: var(--textTitle);
32
+ flex-shrink: 0;
33
+ }
34
+
35
+ .title {
36
+ margin: 0;
37
+ font-size: var(--fontSizeBodyL);
38
+ font-weight: 600;
39
+ color: var(--textTitle);
40
+ }
41
+
42
+ .closeButton {
43
+ background: none;
44
+ border: none;
45
+ font-size: var(--fontSizeH5);
46
+ cursor: pointer;
47
+ padding: var(--spaceS);
48
+ color: var(--textLight);
49
+ transition: color var(--durationS) var(--bezierFastoutSlowin);
50
+ }
51
+
52
+ .closeButton:hover:not(:disabled) {
53
+ color: var(--text);
54
+ }
55
+
56
+ .closeButton:disabled {
57
+ opacity: 0.5;
58
+ cursor: not-allowed;
59
+ }
60
+
61
+ .content {
62
+ padding: var(--spaceL);
63
+ overflow-y: auto;
64
+ flex: 1;
65
+ min-height: 0;
66
+ }
67
+
68
+ .fieldGroup {
69
+ display: flex;
70
+ flex-direction: column;
71
+ gap: var(--spaceM);
72
+ }
73
+
74
+ /* Warning section for existing read-only cases */
75
+ .warningSection {
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: space-between;
79
+ padding: var(--spaceM);
80
+ background: color-mix(in lab, var(--warning) 10%, transparent);
81
+ border: 1px solid color-mix(in lab, var(--warning) 20%, transparent);
82
+ border-radius: var(--spaceXS);
83
+ gap: var(--spaceM);
84
+ }
85
+
86
+ .warningText {
87
+ flex: 1;
88
+ font-size: var(--fontSizeBodyS);
89
+ color: var(--warning);
90
+ font-weight: var(--fontWeightMedium);
91
+ }
92
+
93
+ .warningSubtext {
94
+ font-size: var(--fontSizeBodyXS);
95
+ color: color-mix(in lab, var(--warning) 80%, var(--black));
96
+ margin: var(--spaceXS) 0 0 0;
97
+ font-weight: normal;
98
+ }
99
+
100
+ .clearButton {
101
+ background: var(--warning);
102
+ color: white;
103
+ border: none;
104
+ border-radius: var(--spaceXS);
105
+ padding: var(--spaceS) var(--spaceM);
106
+ font-size: var(--fontSizeBodyS);
107
+ font-weight: var(--fontWeightMedium);
108
+ cursor: pointer;
109
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
110
+ white-space: nowrap;
111
+ box-shadow: 0 1px 3px color-mix(in lab, var(--warning) 30%, transparent);
112
+ }
113
+
114
+ .clearButton:hover:not(:disabled) {
115
+ background: color-mix(in lab, var(--warning) 85%, var(--black));
116
+ box-shadow: 0 2px 6px color-mix(in lab, var(--warning) 40%, transparent);
117
+ }
118
+
119
+ .clearButton:disabled {
120
+ background: color-mix(in lab, var(--background) 95%, transparent);
121
+ color: var(--textLight);
122
+ cursor: not-allowed;
123
+ box-shadow: none;
124
+ opacity: 0.6;
125
+ }
126
+
127
+ /* File selection section */
128
+ .fileSection {
129
+ display: flex;
130
+ flex-direction: column;
131
+ gap: var(--spaceS);
132
+ }
133
+
134
+ .fileInputGroup {
135
+ position: relative;
136
+ }
137
+
138
+ .clearFileButton {
139
+ position: absolute;
140
+ top: var(--spaceS);
141
+ right: var(--spaceS);
142
+ background: transparent;
143
+ color: var(--textLight);
144
+ border: none;
145
+ border-radius: 50%;
146
+ width: 24px;
147
+ height: 24px;
148
+ display: flex;
149
+ align-items: center;
150
+ justify-content: center;
151
+ cursor: pointer;
152
+ font-size: 18px;
153
+ font-weight: bold;
154
+ line-height: 1;
155
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
156
+ z-index: 1;
157
+ }
158
+
159
+ .clearFileButton:hover:not(:disabled) {
160
+ color: var(--error);
161
+ background: transparent;
162
+ }
163
+
164
+ .clearFileButton:disabled {
165
+ color: var(--textLight);
166
+ cursor: not-allowed;
167
+ opacity: 0.3;
168
+ }
169
+
170
+ .fileInput {
171
+ position: absolute;
172
+ opacity: 0;
173
+ width: 0;
174
+ height: 0;
175
+ }
176
+
177
+ .fileLabel {
178
+ display: flex;
179
+ align-items: center;
180
+ gap: var(--spaceS);
181
+ padding: var(--spaceXL);
182
+ border: 2px dashed color-mix(in lab, var(--primary) 30%, transparent);
183
+ border-radius: var(--spaceXS);
184
+ background: color-mix(in lab, var(--primary) 5%, transparent);
185
+ cursor: pointer;
186
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
187
+ min-height: 120px;
188
+ }
189
+
190
+ .fileLabel:hover {
191
+ border-color: var(--primary);
192
+ background: color-mix(in lab, var(--primary) 10%, transparent);
193
+ }
194
+
195
+ .fileLabel:focus-visible {
196
+ outline: none;
197
+ border-color: var(--primary);
198
+ box-shadow: 0 0 0 2px color-mix(in lab, var(--primary) 20%, transparent);
199
+ }
200
+
201
+ .fileLabelDragOver {
202
+ border-color: var(--accent) !important;
203
+ background: color-mix(in lab, var(--accent) 15%, transparent) !important;
204
+ transform: scale(1.02);
205
+ box-shadow: 0 0 0 2px color-mix(in lab, var(--accent) 30%, transparent);
206
+ }
207
+
208
+ .fileInput:focus + .fileLabel {
209
+ border-color: var(--primary);
210
+ box-shadow: 0 0 0 2px color-mix(in lab, var(--primary) 20%, transparent);
211
+ }
212
+
213
+ .fileInput:disabled + .fileLabel {
214
+ opacity: 0.5;
215
+ cursor: not-allowed;
216
+ border-color: color-mix(in lab, var(--text) 15%, transparent);
217
+ background: color-mix(in lab, var(--background) 95%, transparent);
218
+ }
219
+
220
+ .fileInput:disabled + .fileLabel:hover {
221
+ border-color: color-mix(in lab, var(--text) 15%, transparent);
222
+ background: color-mix(in lab, var(--background) 95%, transparent);
223
+ }
224
+
225
+ .fileLabelIcon {
226
+ font-size: var(--fontSizeBodyL);
227
+ opacity: 0.7;
228
+ }
229
+
230
+ .fileLabelText {
231
+ font-size: var(--fontSizeBodyS);
232
+ font-weight: var(--fontWeightMedium);
233
+ color: var(--textBody);
234
+ flex: 1;
235
+ }
236
+
237
+ .fileInfo {
238
+ display: flex;
239
+ justify-content: flex-start;
240
+ padding: 0 var(--spaceS);
241
+ }
242
+
243
+ .fileSize {
244
+ font-size: var(--fontSizeBodyXS);
245
+ color: var(--textLight);
246
+ font-weight: var(--fontWeightMedium);
247
+ }
248
+
249
+ /* Progress section */
250
+ .progressSection {
251
+ margin: var(--spaceM) 0;
252
+ padding: var(--spaceM);
253
+ background: var(--backgroundLight);
254
+ border-radius: var(--spaceXS);
255
+ border: 1px solid color-mix(in lab, var(--text) 10%, transparent);
256
+ }
257
+
258
+ .progressText {
259
+ font-size: var(--fontSizeBodyS);
260
+ color: var(--textTitle);
261
+ margin-bottom: var(--spaceS);
262
+ font-weight: var(--fontWeightMedium);
263
+ }
264
+
265
+ .progressDetails {
266
+ color: var(--textBody);
267
+ font-weight: normal;
268
+ }
269
+
270
+ .progressBar {
271
+ width: 100%;
272
+ height: 8px;
273
+ background: color-mix(in lab, var(--text) 10%, transparent);
274
+ border-radius: var(--spaceXS);
275
+ overflow: hidden;
276
+ margin-bottom: var(--spaceXS);
277
+ }
278
+
279
+ .progressFill {
280
+ height: 100%;
281
+ background: var(--primary);
282
+ border-radius: var(--spaceXS);
283
+ transition: width var(--durationS) var(--bezierFastoutSlowin);
284
+ }
285
+
286
+ .progressPercent {
287
+ font-size: var(--fontSizeBodyXS);
288
+ color: var(--textLight);
289
+ text-align: right;
290
+ font-weight: var(--fontWeightMedium);
291
+ }
292
+
293
+ /* Button group */
294
+ .buttonGroup {
295
+ display: flex;
296
+ gap: var(--spaceM);
297
+ margin-top: var(--spaceL);
298
+ }
299
+
300
+ .importButton {
301
+ background: var(--success);
302
+ color: white;
303
+ border: none;
304
+ border-radius: var(--spaceXS);
305
+ padding: var(--spaceM) var(--spaceL);
306
+ font-size: var(--fontSizeBodyS);
307
+ font-weight: var(--fontWeightMedium);
308
+ cursor: pointer;
309
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
310
+ flex: 1;
311
+ box-shadow: 0 1px 3px color-mix(in lab, var(--success) 30%, transparent);
312
+ }
313
+
314
+ .importButton:hover:not(:disabled) {
315
+ background: color-mix(in lab, var(--success) 85%, var(--black));
316
+ box-shadow: 0 2px 6px color-mix(in lab, var(--success) 40%, transparent);
317
+ }
318
+
319
+ .importButton:disabled {
320
+ background: color-mix(in lab, var(--background) 95%, transparent);
321
+ color: var(--textLight);
322
+ cursor: not-allowed;
323
+ box-shadow: none;
324
+ }
325
+
326
+ .cancelButton {
327
+ background: color-mix(in lab, var(--error) 70%, white);
328
+ color: white;
329
+ border: 1px solid color-mix(in lab, var(--error) 50%, transparent);
330
+ border-radius: var(--spaceXS);
331
+ padding: var(--spaceM) var(--spaceL);
332
+ font-size: var(--fontSizeBodyS);
333
+ font-weight: var(--fontWeightMedium);
334
+ cursor: pointer;
335
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
336
+ flex: 1;
337
+ box-shadow: 0 1px 3px color-mix(in lab, var(--error) 30%, transparent);
338
+ }
339
+
340
+ .cancelButton:hover:not(:disabled) {
341
+ background: color-mix(in lab, var(--error) 80%, white);
342
+ border-color: color-mix(in lab, var(--error) 60%, transparent);
343
+ box-shadow: 0 2px 6px color-mix(in lab, var(--error) 40%, transparent);
344
+ }
345
+
346
+ .cancelButton:disabled {
347
+ opacity: 0.5;
348
+ cursor: not-allowed;
349
+ }
350
+
351
+ /* Success and error messages */
352
+ .success {
353
+ margin-top: var(--spaceM);
354
+ padding: var(--spaceM);
355
+ background: color-mix(in lab, var(--success) 10%, transparent);
356
+ border: 1px solid color-mix(in lab, var(--success) 20%, transparent);
357
+ border-radius: var(--spaceXS);
358
+ color: var(--success);
359
+ font-size: var(--fontSizeBodyS);
360
+ font-weight: var(--fontWeightMedium);
361
+ white-space: pre-wrap;
362
+ }
363
+
364
+ .error {
365
+ margin-top: var(--spaceM);
366
+ padding: var(--spaceM);
367
+ background: color-mix(in lab, var(--error) 10%, transparent);
368
+ border: 1px solid color-mix(in lab, var(--error) 20%, transparent);
369
+ border-radius: var(--spaceXS);
370
+ color: var(--error);
371
+ font-size: var(--fontSizeBodyS);
372
+ font-weight: var(--fontWeightMedium);
373
+ white-space: pre-wrap;
374
+ }
375
+
376
+ /* Instructions section */
377
+ .instructions {
378
+ margin-top: var(--spaceL);
379
+ padding: var(--spaceM);
380
+ background: color-mix(in lab, var(--primary) 5%, transparent);
381
+ border: 1px solid color-mix(in lab, var(--primary) 15%, transparent);
382
+ border-radius: var(--spaceXS);
383
+ }
384
+
385
+ .instructionsTitle {
386
+ margin: 0 0 var(--spaceS) 0;
387
+ font-size: var(--fontSizeBodyS);
388
+ font-weight: var(--fontWeightMedium);
389
+ color: var(--textTitle);
390
+ }
391
+
392
+ .instructionsList {
393
+ margin: 0;
394
+ padding-left: var(--spaceM);
395
+ font-size: var(--fontSizeBodyXS);
396
+ color: var(--textBody);
397
+ line-height: 1.5;
398
+ }
399
+
400
+ .instructionsList li {
401
+ margin-bottom: var(--spaceXS);
402
+ }
403
+
404
+ .instructionsList li:last-child {
405
+ margin-bottom: 0;
406
+ }
407
+
408
+ /* Preview Section - Always Blue */
409
+ .previewSection {
410
+ background: color-mix(in lab, var(--primary) 5%, transparent);
411
+ border: 1px solid color-mix(in lab, var(--primary) 20%, transparent);
412
+ border-radius: var(--spaceXS);
413
+ padding: var(--spaceM);
414
+ margin: var(--spaceM) 0;
415
+ }
416
+
417
+ .previewTitle {
418
+ margin: 0 0 var(--spaceM) 0;
419
+ font-size: var(--fontSizeBodyM);
420
+ font-weight: var(--fontWeightMedium);
421
+ color: var(--textTitle);
422
+ }
423
+
424
+ /* Validation Section - Green/Red Based on Status */
425
+ .validationSection {
426
+ border-radius: var(--spaceXS);
427
+ padding: var(--spaceM);
428
+ margin: var(--spaceM) 0;
429
+ background: color-mix(in lab, var(--primary) 5%, transparent);
430
+ border: 1px solid color-mix(in lab, var(--primary) 15%, transparent);
431
+ }
432
+
433
+ .validationSectionValid {
434
+ background: color-mix(in lab, var(--success) 8%, transparent) !important;
435
+ border: 2px solid color-mix(in lab, var(--success) 25%, transparent) !important;
436
+ box-shadow: 0 2px 6px color-mix(in lab, var(--success) 12%, transparent) !important;
437
+ }
438
+
439
+ .validationSectionInvalid {
440
+ background: color-mix(in lab, var(--error) 8%, transparent) !important;
441
+ border: 2px solid color-mix(in lab, var(--error) 25%, transparent) !important;
442
+ box-shadow: 0 2px 6px color-mix(in lab, var(--error) 12%, transparent) !important;
443
+ }
444
+
445
+ .validationTitle {
446
+ margin: 0 0 var(--spaceM) 0;
447
+ font-size: var(--fontSizeBodyM);
448
+ font-weight: var(--fontWeightMedium);
449
+ color: var(--textTitle);
450
+ }
451
+
452
+ .validationItem {
453
+ display: flex;
454
+ justify-content: space-between;
455
+ align-items: center;
456
+ padding: var(--spaceXS) 0;
457
+ font-size: var(--fontSizeBodyS);
458
+ }
459
+
460
+ .validationLabel {
461
+ font-weight: var(--fontWeightMedium);
462
+ color: var(--textTitle);
463
+ }
464
+
465
+ .validationValue {
466
+ font-family: var(--fontMono);
467
+ font-size: var(--fontSizeBodyXS);
468
+ }
469
+
470
+ .validationSuccess {
471
+ color: var(--success);
472
+ font-weight: var(--fontWeightMedium);
473
+ }
474
+
475
+ .validationError {
476
+ color: var(--error);
477
+ font-weight: var(--fontWeightMedium);
478
+ }
479
+
480
+ .previewLoading {
481
+ text-align: center;
482
+ color: var(--textLight);
483
+ font-style: italic;
484
+ padding: var(--spaceM);
485
+ }
486
+
487
+ .previewGrid {
488
+ display: grid;
489
+ gap: var(--spaceS);
490
+ }
491
+
492
+ .previewItem {
493
+ display: flex;
494
+ justify-content: space-between;
495
+ align-items: center;
496
+ padding: var(--spaceXS) 0;
497
+ }
498
+
499
+ .previewLabel {
500
+ font-weight: var(--fontWeightMedium);
501
+ color: var(--textBody);
502
+ font-size: var(--fontSizeBodyS);
503
+ }
504
+
505
+ .previewValue {
506
+ color: var(--textTitle);
507
+ font-size: var(--fontSizeBodyS);
508
+ text-align: right;
509
+ font-weight: var(--fontWeightMedium);
510
+ }
511
+
512
+ /* Confirmation Dialog */
513
+ .confirmationOverlay {
514
+ position: fixed;
515
+ inset: 0;
516
+ background-color: color-mix(in lab, var(--black) 60%, transparent);
517
+ display: flex;
518
+ justify-content: center;
519
+ align-items: center;
520
+ z-index: 9999;
521
+ }
522
+
523
+ .confirmationModal {
524
+ background: var(--backgroundLight);
525
+ border-radius: var(--spaceXS);
526
+ width: 90%;
527
+ max-width: 400px;
528
+ box-shadow: 0 var(--spaceM) var(--spaceXL) color-mix(in lab, var(--black) 20%, transparent);
529
+ }
530
+
531
+ .confirmationContent {
532
+ padding: var(--spaceL);
533
+ }
534
+
535
+ .confirmationTitle {
536
+ margin: 0 0 var(--spaceM) 0;
537
+ font-size: var(--fontSizeBodyL);
538
+ font-weight: var(--fontWeightMedium);
539
+ color: var(--textTitle);
540
+ }
541
+
542
+ .confirmationText {
543
+ margin: 0 0 var(--spaceL) 0;
544
+ color: var(--textBody);
545
+ font-size: var(--fontSizeBodyS);
546
+ }
547
+
548
+ .confirmationDetails {
549
+ background: color-mix(in lab, var(--background) 50%, transparent);
550
+ border: 1px solid color-mix(in lab, var(--text) 10%, transparent);
551
+ border-radius: var(--spaceXS);
552
+ padding: var(--spaceM);
553
+ margin: 0 0 var(--spaceL) 0;
554
+ }
555
+
556
+ .confirmationItem {
557
+ display: flex;
558
+ justify-content: space-between;
559
+ align-items: center;
560
+ padding: var(--spaceXS) 0;
561
+ font-size: var(--fontSizeBodyS);
562
+ }
563
+
564
+ .confirmationItem:not(:last-child) {
565
+ border-bottom: 1px solid color-mix(in lab, var(--text) 5%, transparent);
566
+ }
567
+
568
+ .confirmationItemValid {
569
+ background: color-mix(in lab, var(--success) 15%, transparent);
570
+ border-radius: var(--spaceXS);
571
+ padding: var(--spaceS) var(--spaceM);
572
+ margin: var(--spaceXS) calc(-1 * var(--spaceM));
573
+ border: 2px solid color-mix(in lab, var(--success) 35%, transparent);
574
+ box-shadow: 0 2px 4px color-mix(in lab, var(--success) 10%, transparent);
575
+ }
576
+
577
+ .confirmationItemInvalid {
578
+ background: color-mix(in lab, var(--error) 8%, transparent);
579
+ border-radius: var(--spaceXS);
580
+ padding: var(--spaceS) var(--spaceM);
581
+ margin: var(--spaceXS) calc(-1 * var(--spaceM));
582
+ border: 1px solid color-mix(in lab, var(--error) 20%, transparent);
583
+ }
584
+
585
+ .confirmationSuccess {
586
+ color: var(--success);
587
+ font-weight: var(--fontWeightMedium);
588
+ }
589
+
590
+ .confirmationError {
591
+ color: var(--error);
592
+ font-weight: var(--fontWeightMedium);
593
+ }
594
+
595
+ .confirmationButtons {
596
+ display: flex;
597
+ gap: var(--spaceM);
598
+ justify-content: flex-end;
599
+ }
600
+
601
+ .confirmButton {
602
+ background: var(--primary);
603
+ color: var(--white);
604
+ border: none;
605
+ border-radius: var(--spaceXS);
606
+ padding: var(--spaceS) var(--spaceL);
607
+ font-size: var(--fontSizeBodyS);
608
+ font-weight: var(--fontWeightMedium);
609
+ cursor: pointer;
610
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
611
+ }
612
+
613
+ .confirmButton:hover {
614
+ box-shadow: 0 2px 6px color-mix(in lab, var(--primary) 30%, transparent);
615
+ }
616
+
617
+ .hashWarning {
618
+ background: color-mix(in lab, var(--error) 10%, transparent);
619
+ border: 1px solid color-mix(in lab, var(--error) 30%, transparent);
620
+ color: var(--error);
621
+ padding: var(--spaceM);
622
+ border-radius: var(--spaceXS);
623
+ margin-top: var(--spaceM);
624
+ font-size: var(--fontSizeBodyS);
625
+ font-weight: var(--fontWeightMedium);
626
+ }