@authrim/setup 0.1.62 → 0.1.64

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 (60) hide show
  1. package/dist/__tests__/migrate.test.d.ts +5 -0
  2. package/dist/__tests__/migrate.test.d.ts.map +1 -0
  3. package/dist/__tests__/migrate.test.js +273 -0
  4. package/dist/__tests__/migrate.test.js.map +1 -0
  5. package/dist/__tests__/paths.test.d.ts +2 -0
  6. package/dist/__tests__/paths.test.d.ts.map +1 -0
  7. package/dist/__tests__/paths.test.js +257 -0
  8. package/dist/__tests__/paths.test.js.map +1 -0
  9. package/dist/cli/commands/config.d.ts +1 -0
  10. package/dist/cli/commands/config.d.ts.map +1 -1
  11. package/dist/cli/commands/config.js +41 -7
  12. package/dist/cli/commands/config.js.map +1 -1
  13. package/dist/cli/commands/deploy.d.ts +1 -0
  14. package/dist/cli/commands/deploy.d.ts.map +1 -1
  15. package/dist/cli/commands/deploy.js +181 -19
  16. package/dist/cli/commands/deploy.js.map +1 -1
  17. package/dist/cli/commands/init.d.ts.map +1 -1
  18. package/dist/cli/commands/init.js +267 -82
  19. package/dist/cli/commands/init.js.map +1 -1
  20. package/dist/cli/commands/migrate.d.ts +21 -0
  21. package/dist/cli/commands/migrate.d.ts.map +1 -0
  22. package/dist/cli/commands/migrate.js +166 -0
  23. package/dist/cli/commands/migrate.js.map +1 -0
  24. package/dist/core/admin.d.ts +18 -1
  25. package/dist/core/admin.d.ts.map +1 -1
  26. package/dist/core/admin.js +36 -7
  27. package/dist/core/admin.js.map +1 -1
  28. package/dist/core/config.d.ts +10 -2
  29. package/dist/core/config.d.ts.map +1 -1
  30. package/dist/core/config.js +6 -2
  31. package/dist/core/config.js.map +1 -1
  32. package/dist/core/keys.d.ts +55 -4
  33. package/dist/core/keys.d.ts.map +1 -1
  34. package/dist/core/keys.js +104 -12
  35. package/dist/core/keys.js.map +1 -1
  36. package/dist/core/lock.d.ts +60 -3
  37. package/dist/core/lock.d.ts.map +1 -1
  38. package/dist/core/lock.js +108 -4
  39. package/dist/core/lock.js.map +1 -1
  40. package/dist/core/migrate.d.ts +95 -0
  41. package/dist/core/migrate.d.ts.map +1 -0
  42. package/dist/core/migrate.js +549 -0
  43. package/dist/core/migrate.js.map +1 -0
  44. package/dist/core/paths.d.ts +171 -0
  45. package/dist/core/paths.d.ts.map +1 -0
  46. package/dist/core/paths.js +319 -0
  47. package/dist/core/paths.js.map +1 -0
  48. package/dist/core/wrangler-sync.d.ts +88 -0
  49. package/dist/core/wrangler-sync.d.ts.map +1 -0
  50. package/dist/core/wrangler-sync.js +242 -0
  51. package/dist/core/wrangler-sync.js.map +1 -0
  52. package/dist/index.js +16 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/web/api.d.ts.map +1 -1
  55. package/dist/web/api.js +102 -28
  56. package/dist/web/api.js.map +1 -1
  57. package/dist/web/ui.d.ts.map +1 -1
  58. package/dist/web/ui.js +1140 -286
  59. package/dist/web/ui.js.map +1 -1
  60. package/package.json +1 -1
package/dist/web/ui.js CHANGED
@@ -14,18 +14,74 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
14
14
  <meta charset="UTF-8">
15
15
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
16
16
  <title>Authrim Setup</title>
17
+ <link rel="preconnect" href="https://fonts.googleapis.com">
18
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
19
+ <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;0,700;1,400&family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&display=swap" rel="stylesheet">
17
20
  <style>
18
21
  :root {
22
+ /* Typography */
23
+ --font-serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
24
+ --font-sans: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
25
+ --font-mono: 'SF Mono', Monaco, 'Cascadia Code', 'Consolas', monospace;
26
+
27
+ /* Light theme colors */
19
28
  --primary: #2563eb;
20
29
  --primary-dark: #1d4ed8;
21
- --success: #10b981;
22
- --error: #ef4444;
23
- --warning: #f59e0b;
24
- --bg: #f8fafc;
25
- --card-bg: #ffffff;
26
- --text: #1e293b;
27
- --text-muted: #64748b;
28
- --border: #e2e8f0;
30
+ --primary-light: #3b82f6;
31
+ --accent: #c2410c;
32
+ --success: #059669;
33
+ --error: #dc2626;
34
+ --warning: #d97706;
35
+ --bg: #f8f5e3;
36
+ --bg-secondary: #f3eed6;
37
+ --card-bg: #fffefa;
38
+ --card-bg-hover: #fdfcf4;
39
+ --text: #1c1917;
40
+ --text-muted: #57534e;
41
+ --text-subtle: #78716c;
42
+ --border: #d6d3d1;
43
+ --border-light: #e7e5e4;
44
+
45
+ /* Splash */
46
+ --splash-bg: #1c1917;
47
+ --splash-text: #f8f5e3;
48
+
49
+ /* Shadows & Effects */
50
+ --shadow-sm: 0 1px 2px rgba(28, 25, 23, 0.04);
51
+ --shadow-md: 0 4px 12px rgba(28, 25, 23, 0.06);
52
+ --shadow-lg: 0 12px 32px rgba(28, 25, 23, 0.08);
53
+ --shadow-card: 0 1px 3px rgba(28, 25, 23, 0.04), 0 4px 12px rgba(28, 25, 23, 0.02);
54
+
55
+ /* Transitions */
56
+ --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
57
+ --transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
58
+ --transition-slow: 400ms cubic-bezier(0.4, 0, 0.2, 1);
59
+ }
60
+
61
+ /* Dark theme */
62
+ [data-theme="dark"] {
63
+ --primary: #60a5fa;
64
+ --primary-dark: #3b82f6;
65
+ --primary-light: #93c5fd;
66
+ --accent: #fb923c;
67
+ --success: #34d399;
68
+ --error: #f87171;
69
+ --warning: #fbbf24;
70
+ --bg: #0c0a09;
71
+ --bg-secondary: #1c1917;
72
+ --card-bg: #1c1917;
73
+ --card-bg-hover: #292524;
74
+ --text: #fafaf9;
75
+ --text-muted: #a8a29e;
76
+ --text-subtle: #78716c;
77
+ --border: #44403c;
78
+ --border-light: #292524;
79
+ --splash-bg: #0c0a09;
80
+ --splash-text: #f8f5e3;
81
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
82
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
83
+ --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.4);
84
+ --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.2), 0 4px 12px rgba(0, 0, 0, 0.15);
29
85
  }
30
86
 
31
87
  * {
@@ -35,155 +91,409 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
35
91
  }
36
92
 
37
93
  body {
38
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
94
+ font-family: var(--font-sans);
39
95
  background: var(--bg);
40
96
  color: var(--text);
41
97
  line-height: 1.6;
42
98
  min-height: 100vh;
99
+ transition: background-color var(--transition-slow), color var(--transition-slow);
100
+ }
101
+
102
+ /* Subtle grain texture */
103
+ body::before {
104
+ content: '';
105
+ position: fixed;
106
+ top: 0;
107
+ left: 0;
108
+ width: 100%;
109
+ height: 100%;
110
+ pointer-events: none;
111
+ opacity: 0.015;
112
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
113
+ z-index: 9998;
114
+ }
115
+
116
+ [data-theme="dark"] body::before {
117
+ opacity: 0.03;
118
+ }
119
+
120
+ /* ========================================
121
+ SPLASH SCREEN
122
+ ======================================== */
123
+ .splash {
124
+ position: fixed;
125
+ inset: 0;
126
+ z-index: 10000;
127
+ background: var(--splash-bg);
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ opacity: 1;
132
+ visibility: visible;
133
+ transition: opacity 600ms ease, visibility 600ms ease;
134
+ }
135
+
136
+ .splash.fade-out {
137
+ opacity: 0;
138
+ visibility: hidden;
139
+ }
140
+
141
+ .splash-content {
142
+ text-align: center;
143
+ opacity: 0;
144
+ transform: translateY(16px);
145
+ animation: splash-reveal 800ms ease forwards;
146
+ animation-delay: 200ms;
147
+ }
148
+
149
+ .splash-logo {
150
+ display: flex;
151
+ align-items: center;
152
+ justify-content: center;
153
+ gap: 1rem;
154
+ margin-bottom: 1.5rem;
155
+ }
156
+
157
+ .splash-icon {
158
+ width: 56px;
159
+ height: 56px;
160
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
161
+ border-radius: 14px;
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: center;
165
+ font-size: 1.75rem;
166
+ box-shadow: 0 8px 24px rgba(37, 99, 235, 0.3);
167
+ }
168
+
169
+ .splash-title {
170
+ font-family: var(--font-serif);
171
+ font-size: clamp(3rem, 8vw, 4.5rem);
172
+ font-weight: 600;
173
+ color: var(--splash-text);
174
+ letter-spacing: -0.03em;
175
+ line-height: 1;
176
+ }
177
+
178
+ .splash-tagline {
179
+ font-family: var(--font-sans);
180
+ font-size: 0.9rem;
181
+ font-weight: 500;
182
+ color: var(--text-subtle);
183
+ letter-spacing: 0.15em;
184
+ text-transform: uppercase;
185
+ margin-bottom: 3rem;
186
+ }
187
+
188
+ .splash-loader {
189
+ width: 40px;
190
+ height: 40px;
191
+ margin: 0 auto;
192
+ border: 2px solid var(--border);
193
+ border-top-color: var(--primary);
194
+ border-radius: 50%;
195
+ animation: spin 1s linear infinite;
196
+ }
197
+
198
+ @keyframes splash-reveal {
199
+ to {
200
+ opacity: 1;
201
+ transform: translateY(0);
202
+ }
203
+ }
204
+
205
+ /* ========================================
206
+ THEME TOGGLE
207
+ ======================================== */
208
+ .theme-toggle {
209
+ position: fixed;
210
+ top: 1.25rem;
211
+ right: 1.5rem;
212
+ z-index: 100;
213
+ width: 44px;
214
+ height: 44px;
215
+ background: var(--card-bg);
216
+ border: 1px solid var(--border);
217
+ border-radius: 12px;
218
+ display: flex;
219
+ align-items: center;
220
+ justify-content: center;
221
+ cursor: pointer;
222
+ font-size: 1.25rem;
223
+ transition: all var(--transition-fast);
224
+ box-shadow: var(--shadow-sm);
43
225
  }
44
226
 
227
+ .theme-toggle:hover {
228
+ background: var(--card-bg-hover);
229
+ border-color: var(--primary);
230
+ transform: scale(1.05);
231
+ }
232
+
233
+ .theme-toggle:active {
234
+ transform: scale(0.95);
235
+ }
236
+
237
+ /* ========================================
238
+ LAYOUT
239
+ ======================================== */
45
240
  .container {
46
- max-width: 800px;
241
+ max-width: 820px;
47
242
  margin: 0 auto;
48
- padding: 2rem;
243
+ padding: 2.5rem 2rem;
49
244
  }
50
245
 
51
246
  header {
52
247
  text-align: center;
53
- margin-bottom: 2rem;
248
+ margin-bottom: 2.5rem;
249
+ padding-top: 0.5rem;
250
+ }
251
+
252
+ .header-brand {
253
+ display: flex;
254
+ align-items: center;
255
+ justify-content: center;
256
+ gap: 0.75rem;
257
+ margin-bottom: 0.75rem;
258
+ }
259
+
260
+ .header-icon {
261
+ width: 48px;
262
+ height: 48px;
263
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
264
+ border-radius: 12px;
265
+ display: flex;
266
+ align-items: center;
267
+ justify-content: center;
268
+ font-size: 1.5rem;
269
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.25);
54
270
  }
55
271
 
56
272
  h1 {
57
- font-size: 2rem;
273
+ font-family: var(--font-serif);
274
+ font-size: clamp(2rem, 5vw, 2.75rem);
275
+ font-weight: 600;
276
+ color: var(--text);
277
+ letter-spacing: -0.02em;
278
+ line-height: 1.1;
279
+ }
280
+
281
+ .header-wizard {
282
+ font-family: var(--font-serif);
283
+ font-size: 1.25rem;
284
+ font-weight: 400;
285
+ font-style: italic;
58
286
  color: var(--primary);
59
- margin-bottom: 0.5rem;
287
+ margin-bottom: 0.25rem;
60
288
  }
61
289
 
62
290
  .subtitle {
291
+ font-family: var(--font-sans);
292
+ font-size: 0.9rem;
63
293
  color: var(--text-muted);
294
+ letter-spacing: 0.02em;
64
295
  }
65
296
 
297
+ /* ========================================
298
+ CARDS
299
+ ======================================== */
66
300
  .card {
67
301
  background: var(--card-bg);
68
- border-radius: 12px;
69
- padding: 1.5rem;
70
- margin-bottom: 1.5rem;
71
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
302
+ border-radius: 16px;
303
+ border: 1px solid var(--border-light);
304
+ padding: 2rem;
305
+ margin-bottom: 1.75rem;
306
+ box-shadow: var(--shadow-card);
307
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
308
+ }
309
+
310
+ .card:hover {
311
+ border-color: var(--border);
72
312
  }
73
313
 
74
314
  .card-title {
75
- font-size: 1.25rem;
315
+ font-family: var(--font-sans);
316
+ font-size: 1.35rem;
76
317
  font-weight: 600;
77
- margin-bottom: 1rem;
318
+ margin-bottom: 1.25rem;
78
319
  display: flex;
79
320
  align-items: center;
80
- gap: 0.5rem;
321
+ gap: 0.625rem;
322
+ color: var(--text);
81
323
  }
82
324
 
325
+ /* ========================================
326
+ STATUS BADGES
327
+ ======================================== */
83
328
  .status-badge {
84
- font-size: 0.75rem;
85
- padding: 0.25rem 0.5rem;
86
- border-radius: 9999px;
87
- font-weight: 500;
329
+ font-family: var(--font-sans);
330
+ font-size: 0.7rem;
331
+ font-weight: 600;
332
+ padding: 0.3rem 0.625rem;
333
+ border-radius: 6px;
334
+ letter-spacing: 0.02em;
335
+ text-transform: uppercase;
336
+ }
337
+
338
+ .status-pending {
339
+ background: var(--bg-secondary);
340
+ color: var(--text-muted);
341
+ }
342
+ .status-running {
343
+ background: rgba(37, 99, 235, 0.1);
344
+ color: var(--primary);
345
+ }
346
+ .status-success {
347
+ background: rgba(5, 150, 105, 0.1);
348
+ color: var(--success);
349
+ }
350
+ .status-error {
351
+ background: rgba(220, 38, 38, 0.1);
352
+ color: var(--error);
353
+ }
354
+ .status-warning {
355
+ background: rgba(217, 119, 6, 0.1);
356
+ color: var(--warning);
88
357
  }
89
358
 
90
- .status-pending { background: var(--border); color: var(--text-muted); }
91
- .status-running { background: #dbeafe; color: var(--primary); }
92
- .status-success { background: #d1fae5; color: var(--success); }
93
- .status-error { background: #fee2e2; color: var(--error); }
94
- .status-warning { background: #fef3c7; color: #b45309; }
359
+ [data-theme="dark"] .status-running { background: rgba(96, 165, 250, 0.15); }
360
+ [data-theme="dark"] .status-success { background: rgba(52, 211, 153, 0.15); }
361
+ [data-theme="dark"] .status-error { background: rgba(248, 113, 113, 0.15); }
362
+ [data-theme="dark"] .status-warning { background: rgba(251, 191, 36, 0.15); }
95
363
 
96
- /* Mode selection cards */
364
+ /* ========================================
365
+ MODE SELECTION CARDS
366
+ ======================================== */
97
367
  .mode-cards {
98
368
  display: grid;
99
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
100
- gap: 1rem;
101
- margin-bottom: 1rem;
369
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
370
+ gap: 1.25rem;
371
+ margin-bottom: 1.25rem;
102
372
  }
103
373
 
104
374
  .mode-card {
105
- border: 2px solid var(--border);
106
- border-radius: 12px;
107
- padding: 1.5rem;
375
+ background: var(--card-bg);
376
+ border: 2px solid var(--border-light);
377
+ border-radius: 14px;
378
+ padding: 1.75rem;
108
379
  cursor: pointer;
109
- transition: all 0.2s;
380
+ transition: all var(--transition-base);
110
381
  position: relative;
111
382
  }
112
383
 
113
384
  .mode-card:hover {
114
385
  border-color: var(--primary);
115
- background: #f8fafc;
386
+ background: var(--card-bg-hover);
387
+ transform: translateY(-2px);
388
+ box-shadow: var(--shadow-md);
116
389
  }
117
390
 
118
391
  .mode-card.selected {
119
392
  border-color: var(--primary);
120
- background: #eff6ff;
393
+ background: rgba(37, 99, 235, 0.04);
394
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
395
+ }
396
+
397
+ [data-theme="dark"] .mode-card.selected {
398
+ background: rgba(96, 165, 250, 0.08);
399
+ box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.15);
121
400
  }
122
401
 
123
402
  .mode-card .mode-icon {
124
- font-size: 2rem;
125
- margin-bottom: 0.5rem;
403
+ font-size: 2.25rem;
404
+ margin-bottom: 0.75rem;
405
+ display: block;
126
406
  }
127
407
 
128
408
  .mode-card h3 {
409
+ font-family: var(--font-sans);
129
410
  font-size: 1.1rem;
411
+ font-weight: 600;
130
412
  margin-bottom: 0.5rem;
413
+ color: var(--text);
131
414
  }
132
415
 
133
416
  .mode-card p {
134
- font-size: 0.875rem;
417
+ font-size: 0.9rem;
135
418
  color: var(--text-muted);
136
- margin-bottom: 0.75rem;
419
+ margin-bottom: 0.875rem;
420
+ line-height: 1.5;
137
421
  }
138
422
 
139
423
  .mode-card ul {
140
424
  font-size: 0.8rem;
141
- color: var(--text-muted);
425
+ color: var(--text-subtle);
142
426
  margin-left: 1rem;
427
+ line-height: 1.6;
143
428
  }
144
429
 
145
430
  .mode-card ul li {
146
- margin-bottom: 0.25rem;
431
+ margin-bottom: 0.3rem;
147
432
  }
148
433
 
149
434
  .mode-badge {
150
435
  position: absolute;
151
- top: -8px;
152
- right: 10px;
153
- background: var(--primary);
436
+ top: -10px;
437
+ right: 12px;
438
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
154
439
  color: white;
155
- font-size: 0.7rem;
156
- padding: 0.2rem 0.5rem;
157
- border-radius: 4px;
158
- font-weight: 500;
440
+ font-family: var(--font-sans);
441
+ font-size: 0.65rem;
442
+ font-weight: 600;
443
+ padding: 0.35rem 0.625rem;
444
+ border-radius: 6px;
445
+ letter-spacing: 0.03em;
446
+ text-transform: uppercase;
447
+ box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3);
159
448
  }
160
449
 
450
+ /* ========================================
451
+ FORMS
452
+ ======================================== */
161
453
  .form-group {
162
- margin-bottom: 1rem;
454
+ margin-bottom: 1.25rem;
163
455
  }
164
456
 
165
457
  label {
166
458
  display: block;
459
+ font-family: var(--font-sans);
167
460
  font-weight: 500;
461
+ font-size: 0.9rem;
168
462
  margin-bottom: 0.5rem;
463
+ color: var(--text);
169
464
  }
170
465
 
171
466
  input[type="text"],
172
467
  input[type="password"],
468
+ input[type="email"],
173
469
  input[type="file"],
174
470
  select {
175
471
  width: 100%;
176
- padding: 0.75rem;
472
+ padding: 0.875rem 1rem;
177
473
  border: 1px solid var(--border);
178
- border-radius: 8px;
179
- font-size: 1rem;
180
- transition: border-color 0.2s;
474
+ border-radius: 10px;
475
+ font-family: var(--font-sans);
476
+ font-size: 0.95rem;
477
+ background: var(--card-bg);
478
+ color: var(--text);
479
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
480
+ }
481
+
482
+ input::placeholder,
483
+ select::placeholder {
484
+ color: var(--text-subtle);
181
485
  }
182
486
 
183
487
  input:focus,
184
488
  select:focus {
185
489
  outline: none;
186
490
  border-color: var(--primary);
491
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
492
+ }
493
+
494
+ [data-theme="dark"] input:focus,
495
+ [data-theme="dark"] select:focus {
496
+ box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.15);
187
497
  }
188
498
 
189
499
  /* Fix browser autofill/autocomplete styling */
@@ -191,9 +501,17 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
191
501
  input:-webkit-autofill:hover,
192
502
  input:-webkit-autofill:focus,
193
503
  input:-webkit-autofill:active {
194
- -webkit-box-shadow: 0 0 0 30px white inset !important;
195
- -webkit-text-fill-color: #1e293b !important;
196
- caret-color: #1e293b !important;
504
+ -webkit-box-shadow: 0 0 0 30px var(--card-bg) inset !important;
505
+ -webkit-text-fill-color: var(--text) !important;
506
+ caret-color: var(--text) !important;
507
+ }
508
+
509
+ small {
510
+ display: block;
511
+ font-size: 0.8rem;
512
+ color: var(--text-muted);
513
+ margin-top: 0.375rem;
514
+ line-height: 1.4;
197
515
  }
198
516
 
199
517
  .checkbox-group {
@@ -206,28 +524,42 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
206
524
  display: flex;
207
525
  align-items: center;
208
526
  gap: 0.5rem;
527
+ cursor: pointer;
209
528
  }
210
529
 
211
- /* Infrastructure info section */
530
+ .checkbox-item input[type="checkbox"] {
531
+ width: 18px;
532
+ height: 18px;
533
+ accent-color: var(--primary);
534
+ cursor: pointer;
535
+ }
536
+
537
+ /* ========================================
538
+ INFRASTRUCTURE INFO SECTION
539
+ ======================================== */
212
540
  .infra-section {
213
- background: #f8fafc;
214
- border: 1px solid var(--border);
215
- border-radius: 8px;
216
- padding: 1rem;
217
- margin-bottom: 1rem;
541
+ background: var(--bg-secondary);
542
+ border: 1px solid var(--border-light);
543
+ border-radius: 12px;
544
+ padding: 1.25rem;
545
+ margin-bottom: 1.25rem;
218
546
  }
219
547
 
220
548
  .infra-section h4 {
221
- margin: 0 0 0.75rem 0;
222
- font-size: 0.9rem;
549
+ margin: 0 0 0.875rem 0;
550
+ font-family: var(--font-sans);
551
+ font-size: 0.85rem;
552
+ font-weight: 600;
223
553
  color: var(--text-muted);
554
+ text-transform: uppercase;
555
+ letter-spacing: 0.04em;
224
556
  }
225
557
 
226
558
  .infra-item {
227
559
  display: flex;
228
560
  justify-content: space-between;
229
- padding: 0.25rem 0;
230
- font-size: 0.85rem;
561
+ padding: 0.375rem 0;
562
+ font-size: 0.875rem;
231
563
  }
232
564
 
233
565
  .infra-label {
@@ -235,22 +567,27 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
235
567
  }
236
568
 
237
569
  .infra-value {
238
- font-family: monospace;
570
+ font-family: var(--font-mono);
571
+ font-size: 0.8rem;
239
572
  color: var(--primary);
240
573
  }
241
574
 
242
- /* Domain configuration section */
575
+ /* ========================================
576
+ DOMAIN CONFIGURATION SECTION
577
+ ======================================== */
243
578
  .domain-section {
244
- background: var(--bg);
245
- border: 1px solid var(--border);
246
- border-radius: 8px;
247
- padding: 1rem;
248
- margin-bottom: 1rem;
579
+ background: var(--bg-secondary);
580
+ border: 1px solid var(--border-light);
581
+ border-radius: 12px;
582
+ padding: 1.25rem;
583
+ margin-bottom: 1.25rem;
249
584
  }
250
585
 
251
586
  .domain-section h4 {
252
- margin: 0 0 0.5rem 0;
253
- font-size: 0.95rem;
587
+ margin: 0 0 0.625rem 0;
588
+ font-family: var(--font-sans);
589
+ font-size: 1rem;
590
+ font-weight: 600;
254
591
  color: var(--text);
255
592
  display: flex;
256
593
  align-items: center;
@@ -261,9 +598,14 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
261
598
  font-size: 0.8rem;
262
599
  color: var(--text-muted);
263
600
  margin-bottom: 1rem;
264
- padding: 0.5rem;
265
- background: #f0f9ff;
266
- border-radius: 4px;
601
+ padding: 0.625rem 0.75rem;
602
+ background: rgba(37, 99, 235, 0.06);
603
+ border-radius: 8px;
604
+ line-height: 1.5;
605
+ }
606
+
607
+ [data-theme="dark"] .domain-section .section-hint {
608
+ background: rgba(96, 165, 250, 0.1);
267
609
  }
268
610
 
269
611
  .domain-row {
@@ -294,14 +636,15 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
294
636
 
295
637
  .domain-default {
296
638
  position: absolute;
297
- right: 10px;
639
+ right: 12px;
298
640
  top: 50%;
299
641
  transform: translateY(-50%);
300
- font-size: 0.7rem;
301
- color: var(--text-muted);
302
- background: #f1f5f9;
303
- padding: 2px 6px;
304
- border-radius: 4px;
642
+ font-family: var(--font-mono);
643
+ font-size: 0.65rem;
644
+ color: var(--text-subtle);
645
+ background: var(--bg);
646
+ padding: 3px 8px;
647
+ border-radius: 5px;
305
648
  max-width: 160px;
306
649
  overflow: hidden;
307
650
  text-overflow: ellipsis;
@@ -309,11 +652,15 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
309
652
  }
310
653
 
311
654
  .issuer-preview {
312
- margin-top: 0.75rem;
313
- padding: 0.5rem;
314
- background: #f0fdf4;
315
- border-radius: 4px;
316
- font-size: 0.85rem;
655
+ margin-top: 0.875rem;
656
+ padding: 0.625rem 0.75rem;
657
+ background: rgba(5, 150, 105, 0.08);
658
+ border-radius: 8px;
659
+ font-size: 0.875rem;
660
+ }
661
+
662
+ [data-theme="dark"] .issuer-preview {
663
+ background: rgba(52, 211, 153, 0.1);
317
664
  }
318
665
 
319
666
  .issuer-preview .label {
@@ -322,87 +669,187 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
322
669
  }
323
670
 
324
671
  .issuer-preview .value {
325
- color: #16a34a;
326
- font-family: monospace;
672
+ color: var(--success);
673
+ font-family: var(--font-mono);
674
+ font-size: 0.8rem;
327
675
  word-break: break-all;
328
676
  }
329
677
 
678
+ /* ========================================
679
+ BUTTONS
680
+ ======================================== */
330
681
  button {
331
- padding: 0.75rem 1.5rem;
332
- border-radius: 8px;
333
- font-size: 1rem;
334
- font-weight: 500;
682
+ padding: 0.875rem 1.75rem;
683
+ border-radius: 10px;
684
+ font-family: var(--font-sans);
685
+ font-size: 0.95rem;
686
+ font-weight: 600;
335
687
  cursor: pointer;
336
- transition: all 0.2s;
688
+ transition: all var(--transition-fast);
337
689
  border: none;
338
690
  }
339
691
 
340
692
  .btn-primary {
341
- background: var(--primary);
693
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
342
694
  color: white;
695
+ box-shadow: 0 2px 8px rgba(37, 99, 235, 0.25);
343
696
  }
344
697
 
345
698
  .btn-primary:hover:not(:disabled) {
346
- background: var(--primary-dark);
699
+ transform: translateY(-1px);
700
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.35);
701
+ }
702
+
703
+ .btn-primary:active:not(:disabled) {
704
+ transform: translateY(0);
347
705
  }
348
706
 
349
707
  .btn-primary:disabled {
350
- opacity: 0.6;
708
+ opacity: 0.5;
351
709
  cursor: not-allowed;
710
+ box-shadow: none;
352
711
  }
353
712
 
354
713
  .btn-secondary {
355
- background: var(--border);
714
+ background: var(--bg-secondary);
356
715
  color: var(--text);
716
+ border: 1px solid var(--border);
357
717
  }
358
718
 
359
719
  .btn-secondary:hover {
360
- background: #cbd5e1;
720
+ background: var(--border-light);
721
+ border-color: var(--border);
361
722
  }
362
723
 
363
724
  .button-group {
364
725
  display: flex;
365
726
  gap: 1rem;
366
- margin-top: 1.5rem;
727
+ margin-top: 2rem;
367
728
  }
368
729
 
730
+ /* ========================================
731
+ PROGRESS LOG
732
+ ======================================== */
369
733
  .progress-log {
370
- background: #1e293b;
371
- border-radius: 8px;
372
- padding: 1rem;
373
- max-height: 300px;
734
+ background: #0f172a;
735
+ border-radius: 12px;
736
+ padding: 1.25rem;
737
+ max-height: 320px;
374
738
  overflow-y: auto;
375
- font-family: 'Monaco', 'Menlo', monospace;
376
- font-size: 0.875rem;
739
+ font-family: var(--font-mono);
740
+ font-size: 0.8rem;
741
+ border: 1px solid #1e293b;
377
742
  }
378
743
 
379
744
  .progress-log pre {
380
745
  color: #e2e8f0;
381
746
  white-space: pre-wrap;
382
747
  word-break: break-word;
748
+ line-height: 1.6;
749
+ }
750
+
751
+ /* Progress UI Components */
752
+ .progress-container {
753
+ margin: 1.25rem 0;
754
+ }
755
+
756
+ .progress-status {
757
+ display: flex;
758
+ align-items: center;
759
+ gap: 0.875rem;
760
+ margin-bottom: 1rem;
761
+ }
762
+
763
+ .progress-status .spinner {
764
+ width: 22px;
765
+ height: 22px;
766
+ border: 2px solid var(--border);
767
+ border-top-color: var(--primary);
768
+ border-radius: 50%;
769
+ animation: spin 0.8s linear infinite;
770
+ }
771
+
772
+ @keyframes spin {
773
+ to { transform: rotate(360deg); }
774
+ }
775
+
776
+ .progress-bar-wrapper {
777
+ background: var(--bg-secondary);
778
+ border-radius: 6px;
779
+ height: 10px;
780
+ overflow: hidden;
781
+ margin-bottom: 0.625rem;
782
+ }
783
+
784
+ .progress-bar {
785
+ height: 100%;
786
+ background: linear-gradient(90deg, var(--primary) 0%, var(--primary-light) 100%);
787
+ border-radius: 6px;
788
+ transition: width 0.4s ease;
383
789
  }
384
790
 
791
+ .progress-text {
792
+ font-family: var(--font-sans);
793
+ font-size: 0.85rem;
794
+ color: var(--text-muted);
795
+ }
796
+
797
+ .log-toggle {
798
+ display: inline-flex;
799
+ align-items: center;
800
+ gap: 0.5rem;
801
+ padding: 0.625rem 1rem;
802
+ background: var(--bg-secondary);
803
+ border: 1px solid var(--border-light);
804
+ border-radius: 8px;
805
+ cursor: pointer;
806
+ font-family: var(--font-sans);
807
+ font-size: 0.85rem;
808
+ color: var(--text-muted);
809
+ margin-top: 1rem;
810
+ transition: all var(--transition-fast);
811
+ }
812
+
813
+ .log-toggle:hover {
814
+ background: var(--border-light);
815
+ color: var(--text);
816
+ }
817
+
818
+ .log-toggle .arrow {
819
+ transition: transform var(--transition-fast);
820
+ }
821
+
822
+ .log-toggle.open .arrow {
823
+ transform: rotate(90deg);
824
+ }
825
+
826
+ /* ========================================
827
+ STEP INDICATOR
828
+ ======================================== */
385
829
  .step-indicator {
386
830
  display: flex;
387
831
  justify-content: center;
388
- gap: 0.5rem;
389
- margin-bottom: 2rem;
832
+ gap: 0.375rem;
833
+ margin-bottom: 2.5rem;
390
834
  }
391
835
 
392
836
  .step {
393
- width: 40px;
394
- height: 40px;
837
+ width: 38px;
838
+ height: 38px;
395
839
  border-radius: 50%;
396
840
  display: flex;
397
841
  align-items: center;
398
842
  justify-content: center;
843
+ font-family: var(--font-sans);
399
844
  font-weight: 600;
400
- font-size: 0.875rem;
845
+ font-size: 0.85rem;
846
+ transition: all var(--transition-base);
401
847
  }
402
848
 
403
849
  .step-active {
404
- background: var(--primary);
850
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
405
851
  color: white;
852
+ box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3);
406
853
  }
407
854
 
408
855
  .step-complete {
@@ -411,52 +858,104 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
411
858
  }
412
859
 
413
860
  .step-pending {
414
- background: var(--border);
415
- color: var(--text-muted);
861
+ background: var(--bg-secondary);
862
+ color: var(--text-subtle);
863
+ border: 1px solid var(--border-light);
416
864
  }
417
865
 
418
866
  .step-connector {
419
- width: 40px;
867
+ width: 32px;
420
868
  height: 2px;
421
- background: var(--border);
869
+ background: var(--border-light);
422
870
  align-self: center;
423
871
  }
424
872
 
873
+ /* ========================================
874
+ ALERTS
875
+ ======================================== */
425
876
  .alert {
426
- padding: 1rem;
427
- border-radius: 8px;
428
- margin-bottom: 1rem;
877
+ padding: 1rem 1.25rem;
878
+ border-radius: 10px;
879
+ margin-bottom: 1.25rem;
880
+ font-size: 0.9rem;
881
+ line-height: 1.5;
882
+ }
883
+
884
+ .alert-success {
885
+ background: rgba(5, 150, 105, 0.08);
886
+ color: var(--success);
887
+ border: 1px solid rgba(5, 150, 105, 0.2);
888
+ }
889
+ .alert-error {
890
+ background: rgba(220, 38, 38, 0.08);
891
+ color: var(--error);
892
+ border: 1px solid rgba(220, 38, 38, 0.2);
893
+ }
894
+ .alert-warning {
895
+ background: rgba(217, 119, 6, 0.08);
896
+ color: var(--warning);
897
+ border: 1px solid rgba(217, 119, 6, 0.2);
898
+ }
899
+ .alert-info {
900
+ background: rgba(37, 99, 235, 0.06);
901
+ color: var(--primary);
902
+ border: 1px solid rgba(37, 99, 235, 0.15);
903
+ }
904
+
905
+ [data-theme="dark"] .alert-success {
906
+ background: rgba(52, 211, 153, 0.1);
907
+ border-color: rgba(52, 211, 153, 0.25);
908
+ }
909
+ [data-theme="dark"] .alert-error {
910
+ background: rgba(248, 113, 113, 0.1);
911
+ border-color: rgba(248, 113, 113, 0.25);
912
+ }
913
+ [data-theme="dark"] .alert-warning {
914
+ background: rgba(251, 191, 36, 0.1);
915
+ border-color: rgba(251, 191, 36, 0.25);
916
+ }
917
+ [data-theme="dark"] .alert-info {
918
+ background: rgba(96, 165, 250, 0.1);
919
+ border-color: rgba(96, 165, 250, 0.2);
429
920
  }
430
921
 
431
- .alert-success { background: #d1fae5; color: #065f46; }
432
- .alert-error { background: #fee2e2; color: #991b1b; }
433
- .alert-warning { background: #fef3c7; color: #92400e; }
434
- .alert-info { background: #dbeafe; color: #1e40af; }
435
-
922
+ /* ========================================
923
+ URL DISPLAY
924
+ ======================================== */
436
925
  .url-display {
437
- background: var(--bg);
438
- padding: 1rem;
439
- border-radius: 8px;
440
- margin-top: 1rem;
926
+ background: var(--bg-secondary);
927
+ padding: 1.25rem;
928
+ border-radius: 12px;
929
+ margin-top: 1.25rem;
930
+ border: 1px solid var(--border-light);
441
931
  }
442
932
 
443
933
  .url-item {
444
934
  display: flex;
445
- gap: 0.5rem;
446
- margin-bottom: 0.5rem;
935
+ gap: 0.75rem;
936
+ margin-bottom: 0.625rem;
937
+ align-items: baseline;
447
938
  }
448
939
 
449
940
  .url-label {
450
- font-weight: 500;
451
- min-width: 100px;
941
+ font-family: var(--font-sans);
942
+ font-weight: 600;
943
+ font-size: 0.85rem;
944
+ min-width: 110px;
945
+ color: var(--text-muted);
452
946
  }
453
947
 
454
948
  .url-value {
949
+ font-family: var(--font-mono);
950
+ font-size: 0.8rem;
455
951
  color: var(--primary);
456
952
  word-break: break-all;
457
953
  overflow-wrap: break-word;
458
954
  }
459
955
 
956
+ /* ========================================
957
+ FILE INPUT
958
+ ======================================== */
460
959
  .file-input-wrapper {
461
960
  position: relative;
462
961
  overflow: hidden;
@@ -474,74 +973,92 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
474
973
  }
475
974
 
476
975
  .file-input-btn {
477
- display: inline-block;
478
- padding: 0.75rem 1.5rem;
479
- background: var(--border);
976
+ display: inline-flex;
977
+ align-items: center;
978
+ gap: 0.5rem;
979
+ padding: 0.875rem 1.5rem;
980
+ background: var(--bg-secondary);
480
981
  color: var(--text);
481
- border-radius: 8px;
982
+ border: 1px solid var(--border);
983
+ border-radius: 10px;
482
984
  cursor: pointer;
985
+ font-family: var(--font-sans);
986
+ font-weight: 500;
987
+ transition: all var(--transition-fast);
483
988
  }
484
989
 
485
990
  .file-input-btn:hover {
486
- background: #cbd5e1;
991
+ background: var(--border-light);
992
+ border-color: var(--primary);
487
993
  }
488
994
 
489
995
  .config-preview {
490
- background: var(--bg);
491
- border-radius: 8px;
996
+ background: var(--bg-secondary);
997
+ border: 1px solid var(--border-light);
998
+ border-radius: 10px;
492
999
  padding: 1rem;
493
1000
  margin-top: 1rem;
494
- font-family: 'Monaco', 'Menlo', monospace;
495
- font-size: 0.8rem;
1001
+ font-family: var(--font-mono);
1002
+ font-size: 0.75rem;
496
1003
  max-height: 200px;
497
1004
  overflow-y: auto;
1005
+ line-height: 1.5;
498
1006
  }
499
1007
 
500
1008
  .hidden { display: none; }
501
1009
 
502
- /* Modal styles */
1010
+ /* ========================================
1011
+ MODAL
1012
+ ======================================== */
503
1013
  .modal {
504
1014
  position: fixed;
505
- top: 0;
506
- left: 0;
507
- right: 0;
508
- bottom: 0;
1015
+ inset: 0;
509
1016
  z-index: 1000;
510
1017
  display: flex;
511
1018
  align-items: center;
512
1019
  justify-content: center;
513
1020
  }
514
1021
  .modal.hidden { display: none; }
1022
+
515
1023
  .modal-backdrop {
516
1024
  position: absolute;
517
- top: 0;
518
- left: 0;
519
- right: 0;
520
- bottom: 0;
521
- background: rgba(0, 0, 0, 0.5);
1025
+ inset: 0;
1026
+ background: rgba(0, 0, 0, 0.6);
1027
+ backdrop-filter: blur(4px);
522
1028
  }
1029
+
523
1030
  .modal-content {
524
1031
  position: relative;
525
1032
  background: var(--card-bg);
526
- border-radius: 12px;
527
- padding: 1.5rem;
528
- max-width: 450px;
1033
+ border-radius: 16px;
1034
+ padding: 2rem;
1035
+ max-width: 460px;
529
1036
  width: 90%;
530
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
1037
+ box-shadow: var(--shadow-lg);
1038
+ border: 1px solid var(--border-light);
531
1039
  }
532
1040
 
533
- /* Resource preview styles */
534
- .resource-preview {
535
- background: var(--bg);
536
- border: 1px solid var(--border);
537
- border-radius: 8px;
538
- padding: 1rem;
1041
+ .modal-content h3 {
1042
+ font-family: var(--font-sans);
1043
+ font-size: 1.25rem;
1044
+ font-weight: 600;
539
1045
  margin-bottom: 1rem;
540
1046
  }
541
1047
 
1048
+ /* ========================================
1049
+ RESOURCE PREVIEW
1050
+ ======================================== */
1051
+ .resource-preview {
1052
+ background: var(--bg-secondary);
1053
+ border: 1px solid var(--border-light);
1054
+ border-radius: 12px;
1055
+ padding: 1.25rem;
1056
+ margin-bottom: 1.25rem;
1057
+ }
1058
+
542
1059
  .resource-list {
543
1060
  display: grid;
544
- gap: 1rem;
1061
+ gap: 1.25rem;
545
1062
  }
546
1063
 
547
1064
  .resource-category {
@@ -550,6 +1067,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
550
1067
 
551
1068
  .resource-category strong {
552
1069
  display: block;
1070
+ font-family: var(--font-sans);
1071
+ font-weight: 600;
553
1072
  margin-bottom: 0.5rem;
554
1073
  color: var(--text);
555
1074
  }
@@ -561,9 +1080,9 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
561
1080
  }
562
1081
 
563
1082
  .resource-category li {
564
- font-family: 'Monaco', 'Menlo', monospace;
565
- font-size: 0.8rem;
566
- margin-bottom: 0.25rem;
1083
+ font-family: var(--font-mono);
1084
+ font-size: 0.75rem;
1085
+ margin-bottom: 0.3rem;
567
1086
  }
568
1087
 
569
1088
  /* Progress spinner */
@@ -587,6 +1106,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
587
1106
  align-items: center;
588
1107
  margin-bottom: 0.5rem;
589
1108
  color: #e2e8f0;
1109
+ font-family: var(--font-mono);
1110
+ font-size: 0.8rem;
590
1111
  }
591
1112
 
592
1113
  .progress-item.complete {
@@ -597,28 +1118,32 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
597
1118
  color: var(--error);
598
1119
  }
599
1120
 
600
- /* Environment cards */
1121
+ /* ========================================
1122
+ ENVIRONMENT CARDS
1123
+ ======================================== */
601
1124
  .env-cards {
602
1125
  display: grid;
603
1126
  gap: 1rem;
604
- margin-bottom: 1rem;
1127
+ margin-bottom: 1.25rem;
605
1128
  }
606
1129
 
607
1130
  .env-card {
608
- border: 1px solid var(--border);
609
- border-radius: 8px;
610
- padding: 1rem;
1131
+ background: var(--card-bg);
1132
+ border: 1px solid var(--border-light);
1133
+ border-radius: 12px;
1134
+ padding: 1.25rem;
611
1135
  display: flex;
612
1136
  justify-content: space-between;
613
1137
  align-items: center;
614
1138
  cursor: pointer;
615
- transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
1139
+ transition: all var(--transition-fast);
616
1140
  }
617
1141
 
618
1142
  .env-card:hover {
619
1143
  border-color: var(--primary);
620
- background: #f8fafc;
621
- box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);
1144
+ background: var(--card-bg-hover);
1145
+ box-shadow: var(--shadow-md);
1146
+ transform: translateY(-1px);
622
1147
  }
623
1148
 
624
1149
  .env-card-info {
@@ -626,14 +1151,16 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
626
1151
  }
627
1152
 
628
1153
  .env-card-name {
1154
+ font-family: var(--font-sans);
629
1155
  font-size: 1.1rem;
630
1156
  font-weight: 600;
631
1157
  margin-bottom: 0.5rem;
1158
+ color: var(--text);
632
1159
  }
633
1160
 
634
1161
  .env-card-stats {
635
1162
  display: flex;
636
- gap: 1rem;
1163
+ gap: 1.25rem;
637
1164
  font-size: 0.8rem;
638
1165
  color: var(--text-muted);
639
1166
  }
@@ -641,70 +1168,79 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
641
1168
  .env-card-stat {
642
1169
  display: flex;
643
1170
  align-items: center;
644
- gap: 0.25rem;
1171
+ gap: 0.375rem;
645
1172
  }
646
1173
 
647
1174
  .env-card-actions {
648
1175
  display: flex;
649
- gap: 0.5rem;
1176
+ gap: 0.625rem;
650
1177
  }
651
1178
 
652
1179
  .btn-danger {
653
1180
  background: var(--error);
654
1181
  color: white;
655
- padding: 0.5rem 1rem;
656
- font-size: 0.875rem;
1182
+ padding: 0.625rem 1rem;
1183
+ font-size: 0.85rem;
1184
+ border-radius: 8px;
657
1185
  }
658
1186
 
659
1187
  .btn-danger:hover {
660
- background: #dc2626;
1188
+ background: #b91c1c;
1189
+ transform: translateY(-1px);
661
1190
  }
662
1191
 
663
1192
  .btn-info {
664
1193
  background: var(--primary);
665
1194
  color: white;
666
- padding: 0.5rem 1rem;
667
- font-size: 0.875rem;
1195
+ padding: 0.625rem 1rem;
1196
+ font-size: 0.85rem;
1197
+ border-radius: 8px;
668
1198
  }
669
1199
 
670
1200
  .btn-info:hover {
671
1201
  background: var(--primary-dark);
1202
+ transform: translateY(-1px);
672
1203
  }
673
1204
 
674
- /* Resource list in details view */
1205
+ /* ========================================
1206
+ RESOURCE LIST (Details view)
1207
+ ======================================== */
675
1208
  .resource-section {
676
- margin-bottom: 1.5rem;
1209
+ margin-bottom: 1.75rem;
677
1210
  }
678
1211
 
679
1212
  .resource-section-title {
1213
+ font-family: var(--font-sans);
680
1214
  font-size: 1rem;
681
1215
  font-weight: 600;
682
- margin-bottom: 0.75rem;
1216
+ margin-bottom: 0.875rem;
683
1217
  display: flex;
684
1218
  align-items: center;
685
1219
  gap: 0.5rem;
1220
+ color: var(--text);
686
1221
  }
687
1222
 
688
1223
  .resource-section-title .count {
689
1224
  font-size: 0.8rem;
690
1225
  color: var(--text-muted);
691
- font-weight: normal;
1226
+ font-weight: 500;
692
1227
  }
693
1228
 
694
1229
  .resource-list {
695
- background: var(--bg);
696
- border-radius: 8px;
697
- padding: 0.75rem;
1230
+ background: var(--bg-secondary);
1231
+ border-radius: 10px;
1232
+ padding: 0.875rem;
1233
+ border: 1px solid var(--border-light);
698
1234
  }
699
1235
 
700
1236
  .resource-item {
701
- font-family: 'Monaco', 'Menlo', monospace;
702
- font-size: 0.8rem;
703
- padding: 0.25rem 0.5rem;
704
- margin-bottom: 0.25rem;
1237
+ font-family: var(--font-mono);
1238
+ font-size: 0.75rem;
1239
+ padding: 0.5rem 0.75rem;
1240
+ margin-bottom: 0.375rem;
705
1241
  background: var(--card-bg);
706
- border-radius: 4px;
707
- border: 1px solid var(--border);
1242
+ border-radius: 6px;
1243
+ border: 1px solid var(--border-light);
708
1244
  }
709
1245
 
710
1246
  .resource-item:last-child {
@@ -712,14 +1248,14 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
712
1248
  }
713
1249
 
714
1250
  .resource-item-name {
715
- font-weight: 500;
1251
+ font-weight: 600;
716
1252
  }
717
1253
 
718
1254
  .resource-item-details {
719
- font-size: 0.75rem;
1255
+ font-size: 0.7rem;
720
1256
  color: var(--text-muted);
721
1257
  margin-top: 0.25rem;
722
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1258
+ font-family: var(--font-sans);
723
1259
  }
724
1260
 
725
1261
  .resource-item-details span {
@@ -746,29 +1282,35 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
746
1282
  font-size: 0.875rem;
747
1283
  }
748
1284
 
749
- /* Delete options */
1285
+ /* ========================================
1286
+ DELETE OPTIONS
1287
+ ======================================== */
750
1288
  .delete-options {
751
1289
  display: grid;
752
- gap: 0.75rem;
1290
+ gap: 0.875rem;
753
1291
  }
754
1292
 
755
1293
  .delete-option {
756
1294
  display: flex;
757
1295
  align-items: center;
758
- gap: 0.75rem;
759
- padding: 0.75rem;
760
- border: 1px solid var(--border);
761
- border-radius: 8px;
1296
+ gap: 0.875rem;
1297
+ padding: 1rem;
1298
+ border: 1px solid var(--border-light);
1299
+ border-radius: 10px;
762
1300
  cursor: pointer;
1301
+ background: var(--card-bg);
1302
+ transition: all var(--transition-fast);
763
1303
  }
764
1304
 
765
1305
  .delete-option:hover {
766
- background: var(--bg);
1306
+ background: var(--bg-secondary);
1307
+ border-color: var(--border);
767
1308
  }
768
1309
 
769
1310
  .delete-option input[type="checkbox"] {
770
1311
  width: 18px;
771
1312
  height: 18px;
1313
+ accent-color: var(--error);
772
1314
  }
773
1315
 
774
1316
  .delete-option span {
@@ -781,37 +1323,43 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
781
1323
  font-size: 0.8rem;
782
1324
  }
783
1325
 
784
- /* Database configuration styles */
1326
+ /* ========================================
1327
+ DATABASE CONFIGURATION
1328
+ ======================================== */
785
1329
  .database-config-grid {
786
1330
  display: grid;
787
1331
  grid-template-columns: 1fr 1fr;
788
1332
  gap: 1.5rem;
789
- margin-bottom: 1.5rem;
1333
+ margin-bottom: 1.75rem;
790
1334
  }
791
1335
 
792
1336
  .database-config-stack {
793
1337
  display: flex;
794
1338
  flex-direction: column;
795
1339
  gap: 1.5rem;
796
- margin-bottom: 1.5rem;
1340
+ margin-bottom: 1.75rem;
797
1341
  }
798
1342
 
799
1343
  .database-card {
800
- background: var(--bg);
801
- border: 1px solid var(--border);
802
- border-radius: 0.5rem;
803
- padding: 1.25rem;
1344
+ background: var(--bg-secondary);
1345
+ border: 1px solid var(--border-light);
1346
+ border-radius: 12px;
1347
+ padding: 1.5rem;
804
1348
  }
805
1349
 
806
1350
  .database-card h3 {
807
- margin: 0 0 1rem 0;
1351
+ margin: 0 0 1.125rem 0;
1352
+ font-family: var(--font-sans);
808
1353
  font-size: 1.1rem;
1354
+ font-weight: 600;
1355
+ color: var(--text);
809
1356
  }
810
1357
 
811
1358
  .db-description {
812
1359
  font-size: 0.875rem;
813
1360
  color: var(--text-muted);
814
- margin-bottom: 1rem;
1361
+ margin-bottom: 1.25rem;
1362
+ line-height: 1.6;
815
1363
  }
816
1364
 
817
1365
  .db-description p {
@@ -824,21 +1372,28 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
824
1372
  }
825
1373
 
826
1374
  .db-description li {
827
- margin-bottom: 0.25rem;
1375
+ margin-bottom: 0.3rem;
828
1376
  }
829
1377
 
830
1378
  .db-hint {
831
1379
  font-style: italic;
832
- margin-top: 0.75rem;
833
- padding: 0.5rem;
834
- background: #f0f9ff;
835
- border-radius: 4px;
1380
+ margin-top: 0.875rem;
1381
+ padding: 0.625rem 0.75rem;
1382
+ background: rgba(37, 99, 235, 0.06);
1383
+ border-radius: 8px;
1384
+ font-size: 0.85rem;
1385
+ }
1386
+
1387
+ [data-theme="dark"] .db-hint {
1388
+ background: rgba(96, 165, 250, 0.1);
836
1389
  }
837
1390
 
838
1391
  .region-selection h4 {
839
- margin: 0 0 0.75rem 0;
1392
+ margin: 0 0 0.875rem 0;
1393
+ font-family: var(--font-sans);
840
1394
  font-size: 0.95rem;
841
1395
  font-weight: 600;
1396
+ color: var(--text);
842
1397
  }
843
1398
 
844
1399
  .radio-group {
@@ -850,24 +1405,27 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
850
1405
  .radio-item {
851
1406
  display: flex;
852
1407
  align-items: center;
853
- gap: 0.5rem;
1408
+ gap: 0.625rem;
854
1409
  cursor: pointer;
855
- padding: 0.25rem 0;
1410
+ padding: 0.375rem 0;
1411
+ font-size: 0.9rem;
856
1412
  }
857
1413
 
858
1414
  .radio-item input[type="radio"] {
859
1415
  margin: 0;
860
- width: 16px;
861
- height: 16px;
1416
+ width: 18px;
1417
+ height: 18px;
1418
+ accent-color: var(--primary);
862
1419
  }
863
1420
 
864
1421
  .radio-separator {
865
- font-size: 0.75rem;
866
- color: var(--text-muted);
867
- margin: 0.5rem 0 0.25rem 0;
868
- font-weight: 500;
1422
+ font-family: var(--font-sans);
1423
+ font-size: 0.7rem;
1424
+ color: var(--text-subtle);
1425
+ margin: 0.75rem 0 0.375rem 0;
1426
+ font-weight: 600;
869
1427
  text-transform: uppercase;
870
- letter-spacing: 0.05em;
1428
+ letter-spacing: 0.08em;
871
1429
  }
872
1430
 
873
1431
  @media (max-width: 768px) {
@@ -878,21 +1436,31 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
878
1436
  </style>
879
1437
  </head>
880
1438
  <body>
1439
+ <!-- Splash Screen -->
1440
+ <div id="splash" class="splash">
1441
+ <div class="splash-content">
1442
+ <div class="splash-logo">
1443
+ <div class="splash-icon">🔐</div>
1444
+ <span class="splash-title">Authrim</span>
1445
+ </div>
1446
+ <p class="splash-tagline">Identity & Access Platform</p>
1447
+ <div class="splash-loader"></div>
1448
+ </div>
1449
+ </div>
1450
+
1451
+ <!-- Theme Toggle -->
1452
+ <button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">🌙</button>
1453
+
881
1454
  <div class="container">
882
1455
  <header>
883
- <h1>🔐 Authrim Setup</h1>
1456
+ <div class="header-brand">
1457
+ <div class="header-icon">🔐</div>
1458
+ <h1>Authrim</h1>
1459
+ </div>
1460
+ <p class="header-wizard">Setup Wizard</p>
884
1461
  <p class="subtitle">OIDC Provider on Cloudflare Workers</p>
885
1462
  </header>
886
1463
 
887
- <!-- Development Warning Banner -->
888
- <div style="background: #fef3c7; border: 2px solid #f59e0b; border-radius: 0.5rem; padding: 1rem; margin-bottom: 1.5rem; text-align: center;">
889
- <strong style="color: #92400e;">⚠️ WARNING: Under Development!</strong>
890
- <p style="color: #78350f; margin: 0.5rem 0 0 0; font-size: 0.875rem;">
891
- This project is still under active development and does not work correctly yet.<br>
892
- Admin UI is incomplete and does not support login functionality.
893
- </p>
894
- </div>
895
-
896
1464
  <div class="step-indicator" id="step-indicator">
897
1465
  <div class="step step-active" id="step-1">1</div>
898
1466
  <div class="step-connector"></div>
@@ -1415,6 +1983,23 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1415
1983
  </div>
1416
1984
  </div>
1417
1985
 
1986
+ <!-- Progress UI (shown during provisioning) -->
1987
+ <div id="provision-progress-ui" class="progress-container hidden">
1988
+ <div class="progress-status">
1989
+ <div class="spinner" id="provision-spinner"></div>
1990
+ <span id="provision-current-task">Initializing...</span>
1991
+ </div>
1992
+ <div class="progress-bar-wrapper">
1993
+ <div class="progress-bar" id="provision-progress-bar" style="width: 0%"></div>
1994
+ </div>
1995
+ <div class="progress-text" id="provision-progress-text">0 / 0 resources</div>
1996
+
1997
+ <div class="log-toggle" id="provision-log-toggle">
1998
+ <span class="arrow">▶</span>
1999
+ <span>Show detailed log</span>
2000
+ </div>
2001
+ </div>
2002
+
1418
2003
  <div class="progress-log hidden" id="provision-log">
1419
2004
  <pre id="provision-output"></pre>
1420
2005
  </div>
@@ -1443,7 +2028,24 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1443
2028
  <span class="status-badge status-pending" id="deploy-status">Ready</span>
1444
2029
  </h2>
1445
2030
 
1446
- <p style="margin-bottom: 1rem;">Ready to deploy Authrim workers to Cloudflare.</p>
2031
+ <p id="deploy-ready-text" style="margin-bottom: 1rem;">Ready to deploy Authrim workers to Cloudflare.</p>
2032
+
2033
+ <!-- Progress UI (shown during deployment) -->
2034
+ <div id="deploy-progress-ui" class="progress-container hidden">
2035
+ <div class="progress-status">
2036
+ <div class="spinner" id="deploy-spinner"></div>
2037
+ <span id="deploy-current-task">Initializing...</span>
2038
+ </div>
2039
+ <div class="progress-bar-wrapper">
2040
+ <div class="progress-bar" id="deploy-progress-bar" style="width: 0%"></div>
2041
+ </div>
2042
+ <div class="progress-text" id="deploy-progress-text">0 / 0 components</div>
2043
+
2044
+ <div class="log-toggle" id="deploy-log-toggle">
2045
+ <span class="arrow">▶</span>
2046
+ <span>Show detailed log</span>
2047
+ </div>
2048
+ </div>
1447
2049
 
1448
2050
  <div class="progress-log hidden" id="deploy-log">
1449
2051
  <pre id="deploy-output"></pre>
@@ -1519,6 +2121,31 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1519
2121
  <code id="detail-env-name" style="background: var(--bg); padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 1rem;"></code>
1520
2122
  </h2>
1521
2123
 
2124
+ <!-- Admin Setup Section -->
2125
+ <div id="admin-setup-section" class="hidden" style="margin-bottom: 1.5rem; padding: 1rem; background: #fef3c7; border-radius: 8px; border: 1px solid #fcd34d;">
2126
+ <div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem;">
2127
+ <span style="font-size: 1.5rem;">⚠️</span>
2128
+ <div>
2129
+ <div style="font-weight: 600; color: #92400e;">Admin Account Not Configured</div>
2130
+ <div style="font-size: 0.875rem; color: #a16207;">Initial administrator has not been set up for this environment.</div>
2131
+ </div>
2132
+ </div>
2133
+ <button class="btn-primary" id="btn-start-admin-setup" style="margin-top: 0.5rem;">
2134
+ 🔐 Start Admin Account Setup with Passkey
2135
+ </button>
2136
+ <div id="admin-setup-result" class="hidden" style="margin-top: 1rem; padding: 0.75rem; background: white; border-radius: 6px;">
2137
+ <div style="font-weight: 500; margin-bottom: 0.5rem;">Setup URL Generated:</div>
2138
+ <div style="display: flex; gap: 0.5rem; align-items: center;">
2139
+ <input type="text" id="admin-setup-url" readonly style="flex: 1; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px; font-family: monospace; font-size: 0.875rem;">
2140
+ <button class="btn-secondary" id="btn-copy-setup-url" style="white-space: nowrap;">📋 Copy</button>
2141
+ <a id="btn-open-setup-url" href="#" target="_blank" class="btn-primary" style="text-decoration: none; white-space: nowrap;">🔗 Open</a>
2142
+ </div>
2143
+ <div style="font-size: 0.75rem; color: #6b7280; margin-top: 0.5rem;">
2144
+ This URL is valid for 1 hour. Open it in a browser to register the first admin account.
2145
+ </div>
2146
+ </div>
2147
+ </div>
2148
+
1522
2149
  <div id="detail-resources">
1523
2150
  <!-- Workers -->
1524
2151
  <div class="resource-section">
@@ -1569,31 +2196,6 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1569
2196
  </div>
1570
2197
  </div>
1571
2198
 
1572
- <!-- Admin Setup Section -->
1573
- <div id="admin-setup-section" class="resource-section hidden" style="margin-top: 1.5rem; padding: 1rem; background: #fef3c7; border-radius: 8px; border: 1px solid #fcd34d;">
1574
- <div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem;">
1575
- <span style="font-size: 1.5rem;">⚠️</span>
1576
- <div>
1577
- <div style="font-weight: 600; color: #92400e;">Admin Account Not Configured</div>
1578
- <div style="font-size: 0.875rem; color: #a16207;">Initial administrator has not been set up for this environment.</div>
1579
- </div>
1580
- </div>
1581
- <button class="btn-primary" id="btn-start-admin-setup" style="margin-top: 0.5rem;">
1582
- 🔐 Start Admin Account Setup with Passkey
1583
- </button>
1584
- <div id="admin-setup-result" class="hidden" style="margin-top: 1rem; padding: 0.75rem; background: white; border-radius: 6px;">
1585
- <div style="font-weight: 500; margin-bottom: 0.5rem;">Setup URL Generated:</div>
1586
- <div style="display: flex; gap: 0.5rem; align-items: center;">
1587
- <input type="text" id="admin-setup-url" readonly style="flex: 1; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px; font-family: monospace; font-size: 0.875rem;">
1588
- <button class="btn-secondary" id="btn-copy-setup-url" style="white-space: nowrap;">📋 Copy</button>
1589
- <a id="btn-open-setup-url" href="#" target="_blank" class="btn-primary" style="text-decoration: none; white-space: nowrap;">🔗 Open</a>
1590
- </div>
1591
- <div style="font-size: 0.75rem; color: #6b7280; margin-top: 0.5rem;">
1592
- This URL is valid for 1 hour. Open it in a browser to register the first admin account.
1593
- </div>
1594
- </div>
1595
- </div>
1596
-
1597
2199
  <div class="button-group">
1598
2200
  <button class="btn-secondary" id="btn-back-env-detail">← Back to List</button>
1599
2201
  <button class="btn-danger" id="btn-delete-from-detail">🗑️ Delete Environment...</button>
@@ -1615,6 +2217,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1615
2217
  Environment: <code id="delete-env-name" style="background: var(--bg); padding: 0.25rem 0.5rem; border-radius: 4px;"></code>
1616
2218
  </h3>
1617
2219
 
2220
+ <div id="delete-options-section">
1618
2221
  <p style="margin-bottom: 1rem; color: var(--text-muted);">Select resources to delete:</p>
1619
2222
 
1620
2223
  <div class="delete-options">
@@ -1666,6 +2269,24 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1666
2269
  </span>
1667
2270
  </label>
1668
2271
  </div>
2272
+ </div>
2273
+ </div>
2274
+
2275
+ <!-- Progress UI (shown during deletion) -->
2276
+ <div id="delete-progress-ui" class="progress-container hidden">
2277
+ <div class="progress-status">
2278
+ <div class="spinner" id="delete-spinner"></div>
2279
+ <span id="delete-current-task">Initializing...</span>
2280
+ </div>
2281
+ <div class="progress-bar-wrapper">
2282
+ <div class="progress-bar" id="delete-progress-bar" style="width: 0%"></div>
2283
+ </div>
2284
+ <div class="progress-text" id="delete-progress-text">0 / 0 resources</div>
2285
+
2286
+ <div class="log-toggle" id="delete-log-toggle">
2287
+ <span class="arrow">▶</span>
2288
+ <span>Show detailed log</span>
2289
+ </div>
1669
2290
  </div>
1670
2291
 
1671
2292
  <div class="progress-log hidden" id="delete-log">
@@ -1698,6 +2319,67 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1698
2319
  </div>
1699
2320
 
1700
2321
  <script>
2322
+ // ========================================
2323
+ // THEME MANAGEMENT
2324
+ // ========================================
2325
+ function initTheme() {
2326
+ const savedTheme = localStorage.getItem('authrim-theme');
2327
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
2328
+ const theme = savedTheme || (prefersDark ? 'dark' : 'light');
2329
+ document.documentElement.setAttribute('data-theme', theme);
2330
+ updateThemeToggle(theme);
2331
+ }
2332
+
2333
+ function toggleTheme() {
2334
+ const current = document.documentElement.getAttribute('data-theme') || 'light';
2335
+ const newTheme = current === 'dark' ? 'light' : 'dark';
2336
+ document.documentElement.setAttribute('data-theme', newTheme);
2337
+ localStorage.setItem('authrim-theme', newTheme);
2338
+ updateThemeToggle(newTheme);
2339
+ }
2340
+
2341
+ function updateThemeToggle(theme) {
2342
+ const toggle = document.getElementById('theme-toggle');
2343
+ if (toggle) {
2344
+ toggle.textContent = theme === 'dark' ? '☀️' : '🌙';
2345
+ toggle.setAttribute('aria-label', theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode');
2346
+ }
2347
+ }
2348
+
2349
+ // Listen for system preference changes
2350
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
2351
+ if (!localStorage.getItem('authrim-theme')) {
2352
+ const theme = e.matches ? 'dark' : 'light';
2353
+ document.documentElement.setAttribute('data-theme', theme);
2354
+ updateThemeToggle(theme);
2355
+ }
2356
+ });
2357
+
2358
+ // Initialize theme immediately
2359
+ initTheme();
2360
+
2361
+ // Theme toggle event
2362
+ document.getElementById('theme-toggle').addEventListener('click', toggleTheme);
2363
+
2364
+ // ========================================
2365
+ // SPLASH SCREEN
2366
+ // ========================================
2367
+ function hideSplash() {
2368
+ const splash = document.getElementById('splash');
2369
+ if (splash) {
2370
+ splash.classList.add('fade-out');
2371
+ setTimeout(() => {
2372
+ splash.style.display = 'none';
2373
+ }, 600);
2374
+ }
2375
+ }
2376
+
2377
+ // Hide splash after 2500ms
2378
+ setTimeout(hideSplash, 2500);
2379
+
2380
+ // ========================================
2381
+ // MAIN APPLICATION
2382
+ // ========================================
1701
2383
  // Session token for API authentication (embedded by server)
1702
2384
  const SESSION_TOKEN = '${safeToken}';
1703
2385
  const MANAGE_ONLY = ${manageOnlyFlag};
@@ -1770,6 +2452,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1770
2452
  function showSection(name) {
1771
2453
  Object.values(sections).forEach(s => s.classList.add('hidden'));
1772
2454
  sections[name].classList.remove('hidden');
2455
+ window.scrollTo(0, 0);
1773
2456
  }
1774
2457
 
1775
2458
  // Auto-scroll helper for progress logs
@@ -1779,6 +2462,106 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
1779
2462
  }
1780
2463
  }
1781
2464
 
2465
+ // Log toggle functionality
2466
+ function setupLogToggle(toggleId, logId) {
2467
+ const toggle = document.getElementById(toggleId);
2468
+ const log = document.getElementById(logId);
2469
+ if (toggle && log) {
2470
+ toggle.addEventListener('click', () => {
2471
+ const isHidden = log.classList.contains('hidden');
2472
+ if (isHidden) {
2473
+ log.classList.remove('hidden');
2474
+ toggle.classList.add('open');
2475
+ toggle.querySelector('span:last-child').textContent = 'Hide detailed log';
2476
+ } else {
2477
+ log.classList.add('hidden');
2478
+ toggle.classList.remove('open');
2479
+ toggle.querySelector('span:last-child').textContent = 'Show detailed log';
2480
+ }
2481
+ });
2482
+ }
2483
+ }
2484
+
2485
+ // Setup all log toggles
2486
+ setupLogToggle('deploy-log-toggle', 'deploy-log');
2487
+ setupLogToggle('provision-log-toggle', 'provision-log');
2488
+ setupLogToggle('delete-log-toggle', 'delete-log');
2489
+
2490
+ // Progress UI update helper
2491
+ function updateProgressUI(prefix, current, total, currentTask) {
2492
+ const progressBar = document.getElementById(prefix + '-progress-bar');
2493
+ const progressText = document.getElementById(prefix + '-progress-text');
2494
+ const currentTaskEl = document.getElementById(prefix + '-current-task');
2495
+
2496
+ if (progressBar && total > 0) {
2497
+ const percent = Math.round((current / total) * 100);
2498
+ progressBar.style.width = percent + '%';
2499
+ }
2500
+ if (progressText) {
2501
+ progressText.textContent = current + ' / ' + total + ' ' + (prefix === 'deploy' ? 'components' : 'resources');
2502
+ }
2503
+ if (currentTaskEl && currentTask) {
2504
+ currentTaskEl.textContent = currentTask;
2505
+ }
2506
+ }
2507
+
2508
+ // Parse progress message to extract current task
2509
+ function parseProgressMessage(message) {
2510
+ // Match patterns like "Deploying xxx...", "Creating xxx...", "Deleting xxx..."
2511
+ if (message.includes('Deploying ')) {
2512
+ const parts = message.split('Deploying ')[1];
2513
+ if (parts) {
2514
+ const name = parts.split('.')[0].split(' ')[0];
2515
+ if (name) return 'Deploying ' + name + '...';
2516
+ }
2517
+ }
2518
+
2519
+ if (message.includes('Creating ')) {
2520
+ const parts = message.split('Creating ')[1];
2521
+ if (parts) {
2522
+ const name = parts.split(' ')[0].split('.')[0];
2523
+ if (name) return 'Creating ' + name + '...';
2524
+ }
2525
+ }
2526
+
2527
+ if (message.includes('Deleting')) {
2528
+ const parts = message.split('Deleting')[1];
2529
+ if (parts) {
2530
+ const name = parts.trim().split(' ')[0].replace(':', '');
2531
+ if (name) return 'Deleting ' + name + '...';
2532
+ }
2533
+ }
2534
+
2535
+ if (message.includes('✓')) {
2536
+ const parts = message.split('✓')[1];
2537
+ if (parts) {
2538
+ const text = parts.trim().substring(0, 40);
2539
+ return '✓ ' + text;
2540
+ }
2541
+ }
2542
+
2543
+ if (message.includes('Level ')) {
2544
+ const parts = message.split('Level ')[1];
2545
+ if (parts) {
2546
+ const num = parts.trim().split(' ')[0];
2547
+ if (num) return 'Deployment Level ' + num;
2548
+ }
2549
+ }
2550
+
2551
+ if (message.includes('Generating')) {
2552
+ const parts = message.split('Generating')[1];
2553
+ if (parts) {
2554
+ const text = parts.trim().substring(0, 30);
2555
+ return 'Generating ' + text + '...';
2556
+ }
2557
+ }
2558
+
2559
+ if (message.includes('Uploading')) return 'Uploading secrets...';
2560
+ if (message.toLowerCase().includes('building')) return 'Building packages...';
2561
+
2562
+ return null;
2563
+ }
2564
+
1782
2565
  // Safe DOM element creation helpers
1783
2566
  function createAlert(type, content) {
1784
2567
  const div = document.createElement('div');
@@ -2578,16 +3361,23 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2578
3361
  const resourcePreview = document.getElementById('resource-preview');
2579
3362
  const keysSavedInfo = document.getElementById('keys-saved-info');
2580
3363
  const keysPath = document.getElementById('keys-path');
3364
+ const progressUI = document.getElementById('provision-progress-ui');
2581
3365
 
2582
3366
  btn.disabled = true;
3367
+ btn.classList.add('hidden');
2583
3368
  btnGotoDeploy.classList.add('hidden');
2584
3369
  status.textContent = 'Running...';
2585
3370
  status.className = 'status-badge status-running';
2586
- log.classList.remove('hidden');
3371
+ progressUI.classList.remove('hidden');
3372
+ log.classList.add('hidden'); // Log is hidden by default, toggled via button
2587
3373
  resourcePreview.classList.add('hidden');
2588
3374
  keysSavedInfo.classList.add('hidden');
2589
3375
  output.textContent = '';
2590
3376
 
3377
+ let provisionCompleted = 0;
3378
+ const totalResources = 8; // D1 Core, D1 PII, KV Settings, KV Cache, KV Tokens, R2 (optional), Queues (optional), Keys
3379
+ updateProgressUI('provision', 0, totalResources, 'Initializing...');
3380
+
2591
3381
  // Start polling for progress
2592
3382
  let lastProgressLength = 0;
2593
3383
  provisionPollInterval = setInterval(async () => {
@@ -2598,6 +3388,16 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2598
3388
  const newMessages = statusResult.progress.slice(lastProgressLength);
2599
3389
  newMessages.forEach(msg => {
2600
3390
  output.textContent += msg + '\\n';
3391
+ // Update progress UI based on message content
3392
+ const taskInfo = parseProgressMessage(msg);
3393
+ if (taskInfo) {
3394
+ updateProgressUI('provision', provisionCompleted, totalResources, taskInfo);
3395
+ }
3396
+ // Count completed items (lines with checkmark)
3397
+ if (msg.includes('✓') || msg.includes('✅')) {
3398
+ provisionCompleted++;
3399
+ updateProgressUI('provision', provisionCompleted, totalResources, taskInfo || ('Completed ' + provisionCompleted + ' items'));
3400
+ }
2601
3401
  });
2602
3402
  lastProgressLength = statusResult.progress.length;
2603
3403
  scrollToBottom(log);
@@ -2630,8 +3430,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2630
3430
  output.textContent += '\\n';
2631
3431
  scrollToBottom(log);
2632
3432
 
2633
- // Show keys saved location (full path with environment)
2634
- keysPath.textContent = workingDirectory ? workingDirectory + '/.keys/' + config.env + '/' : './.keys/' + config.env + '/';
3433
+ // Show keys saved location (new structure: .authrim/{env}/keys/)
3434
+ keysPath.textContent = workingDirectory ? workingDirectory + '/.authrim/' + config.env + '/keys/' : './.authrim/' + config.env + '/keys/';
2635
3435
 
2636
3436
  // Provision resources
2637
3437
  output.textContent += '☁️ Provisioning Cloudflare resources...\\n';
@@ -2649,6 +3449,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2649
3449
  }
2650
3450
 
2651
3451
  if (result.success) {
3452
+ // Final progress update
3453
+ updateProgressUI('provision', totalResources, totalResources, '✅ Provisioning complete!');
2652
3454
  output.textContent += '\\n✅ Provisioning complete!\\n';
2653
3455
  scrollToBottom(log);
2654
3456
  status.textContent = 'Complete';
@@ -2662,6 +3464,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2662
3464
 
2663
3465
  // Update buttons
2664
3466
  btn.textContent = 'Re-provision (Delete & Create)';
3467
+ btn.classList.remove('hidden');
2665
3468
  btn.disabled = false;
2666
3469
  btnGotoDeploy.classList.remove('hidden');
2667
3470
  } else {
@@ -2678,6 +3481,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2678
3481
  scrollToBottom(log);
2679
3482
  status.textContent = 'Error';
2680
3483
  status.className = 'status-badge status-error';
3484
+ btn.classList.remove('hidden');
2681
3485
  btn.disabled = false;
2682
3486
  resourcePreview.classList.remove('hidden');
2683
3487
  }
@@ -2706,13 +3510,21 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2706
3510
  const status = document.getElementById('deploy-status');
2707
3511
  const log = document.getElementById('deploy-log');
2708
3512
  const output = document.getElementById('deploy-output');
3513
+ const progressUI = document.getElementById('deploy-progress-ui');
3514
+ const readyText = document.getElementById('deploy-ready-text');
2709
3515
 
2710
3516
  btn.disabled = true;
3517
+ btn.classList.add('hidden');
2711
3518
  status.textContent = 'Deploying...';
2712
3519
  status.className = 'status-badge status-running';
2713
- log.classList.remove('hidden');
3520
+ readyText.classList.add('hidden');
3521
+ progressUI.classList.remove('hidden');
3522
+ log.classList.add('hidden'); // Log is hidden by default, toggled via button
2714
3523
  output.textContent = 'Starting deployment...\\n\\n';
2715
- scrollToBottom(log);
3524
+
3525
+ let completedCount = 0;
3526
+ const totalComponents = 10; // Approximate total components
3527
+ updateProgressUI('deploy', 0, totalComponents, 'Initializing...');
2716
3528
 
2717
3529
  try {
2718
3530
  // Generate wrangler configs first
@@ -2730,10 +3542,25 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2730
3542
  scrollToBottom(log);
2731
3543
 
2732
3544
  // Poll for status updates
3545
+ let lastProgressLength = 0;
2733
3546
  const pollInterval = setInterval(async () => {
2734
3547
  const statusResult = await api('/deploy/status');
2735
- if (statusResult.progress && statusResult.progress.length > 0) {
2736
- output.textContent = statusResult.progress.join('\\n') + '\\n';
3548
+ if (statusResult.progress && statusResult.progress.length > lastProgressLength) {
3549
+ const newMessages = statusResult.progress.slice(lastProgressLength);
3550
+ newMessages.forEach(msg => {
3551
+ output.textContent += msg + '\\n';
3552
+ // Update progress UI based on message content
3553
+ const taskInfo = parseProgressMessage(msg);
3554
+ if (taskInfo) {
3555
+ updateProgressUI('deploy', completedCount, totalComponents, taskInfo);
3556
+ }
3557
+ // Count completed items (lines with checkmark)
3558
+ if (msg.includes('✓') || msg.includes('✅')) {
3559
+ completedCount++;
3560
+ updateProgressUI('deploy', completedCount, totalComponents, taskInfo || ('Completed ' + completedCount + ' items'));
3561
+ }
3562
+ });
3563
+ lastProgressLength = statusResult.progress.length;
2737
3564
  scrollToBottom(log);
2738
3565
  }
2739
3566
  }, 1000);
@@ -2749,6 +3576,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2749
3576
  clearInterval(pollInterval);
2750
3577
 
2751
3578
  if (result.success) {
3579
+ // Final progress update
3580
+ updateProgressUI('deploy', totalComponents, totalComponents, '✓ Deployment complete!');
2752
3581
  output.textContent += '\\n✓ Deployment complete!\\n';
2753
3582
  scrollToBottom(log);
2754
3583
 
@@ -2778,7 +3607,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2778
3607
 
2779
3608
  output.textContent += ' API URL: ' + apiUrl + '\\n';
2780
3609
  output.textContent += ' Login UI URL: ' + loginUiUrl + '\\n';
2781
- output.textContent += ' Keys Dir: .keys/' + config.env + '\\n';
3610
+ output.textContent += ' Keys Dir: .authrim/' + config.env + '/keys/\\n';
2782
3611
  scrollToBottom(log);
2783
3612
 
2784
3613
  let adminSetupResult;
@@ -2788,7 +3617,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2788
3617
  body: {
2789
3618
  env: config.env,
2790
3619
  baseUrl: apiUrl, // Setup page is served by ar-auth worker (API)
2791
- keysDir: '.keys',
3620
+ // keysDir is auto-detected by API using paths.ts
2792
3621
  },
2793
3622
  });
2794
3623
  output.textContent += ' API Response: ' + JSON.stringify(adminSetupResult) + '\\n';
@@ -2909,8 +3738,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
2909
3738
 
2910
3739
  // Resource naming functions
2911
3740
  function getResourceNames(env) {
2912
- // Keys are stored in environment-specific subdirectory: .keys/{env}/
2913
- const keysDir = workingDirectory ? workingDirectory + '/.keys/' + env : '.keys/' + env;
3741
+ // Keys are stored in environment-specific subdirectory: .authrim/{env}/keys/
3742
+ const keysDir = workingDirectory ? workingDirectory + '/.authrim/' + env + '/keys' : '.authrim/' + env + '/keys';
2914
3743
  return {
2915
3744
  d1: [
2916
3745
  env + '-authrim-core-db',
@@ -3077,7 +3906,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3077
3906
  policy: true,
3078
3907
  },
3079
3908
  keys: {
3080
- secretsPath: './.keys/',
3909
+ secretsPath: './keys/', // Relative path within .authrim/{env}/ structure
3081
3910
  },
3082
3911
  database: config.database || {
3083
3912
  core: { location: 'auto', jurisdiction: 'none' },
@@ -3510,9 +4339,11 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3510
4339
  document.getElementById('delete-pages').checked = true;
3511
4340
 
3512
4341
  // Reset UI state
4342
+ document.getElementById('delete-options-section').classList.remove('hidden');
3513
4343
  document.getElementById('delete-log').classList.add('hidden');
3514
4344
  document.getElementById('delete-result').classList.add('hidden');
3515
- document.getElementById('delete-result').innerHTML = '';
4345
+ document.getElementById('delete-result').textContent = '';
4346
+ document.getElementById('btn-confirm-delete').classList.remove('hidden');
3516
4347
  document.getElementById('btn-confirm-delete').disabled = false;
3517
4348
 
3518
4349
  showSection('envDelete');
@@ -3636,9 +4467,13 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3636
4467
  const log = document.getElementById('delete-log');
3637
4468
  const output = document.getElementById('delete-output');
3638
4469
  const result = document.getElementById('delete-result');
4470
+ const progressUI = document.getElementById('delete-progress-ui');
3639
4471
 
3640
4472
  btn.disabled = true;
3641
- log.classList.remove('hidden');
4473
+ btn.classList.add('hidden');
4474
+ document.getElementById('delete-options-section').classList.add('hidden');
4475
+ progressUI.classList.remove('hidden');
4476
+ log.classList.add('hidden'); // Log is hidden by default, toggled via button
3642
4477
  result.classList.add('hidden');
3643
4478
  output.textContent = '';
3644
4479
 
@@ -3651,6 +4486,11 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3651
4486
  deletePages: document.getElementById('delete-pages').checked,
3652
4487
  };
3653
4488
 
4489
+ // Count selected options for progress tracking
4490
+ let deleteCompleted = 0;
4491
+ const totalToDelete = Object.values(deleteOptions).filter(v => v).length;
4492
+ updateProgressUI('delete', 0, totalToDelete, 'Starting deletion...');
4493
+
3654
4494
  // Poll for progress
3655
4495
  let lastProgressLength = 0;
3656
4496
  const pollInterval = setInterval(async () => {
@@ -3660,9 +4500,19 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3660
4500
  const newMessages = statusResult.progress.slice(lastProgressLength);
3661
4501
  newMessages.forEach(msg => {
3662
4502
  output.textContent += msg + '\\n';
4503
+ // Update progress UI based on message content
4504
+ const taskInfo = parseProgressMessage(msg);
4505
+ if (taskInfo) {
4506
+ updateProgressUI('delete', deleteCompleted, totalToDelete, taskInfo);
4507
+ }
4508
+ // Count completed items (lines with checkmark)
4509
+ if (msg.includes('✓') || msg.includes('✅') || msg.includes('Deleted')) {
4510
+ deleteCompleted++;
4511
+ updateProgressUI('delete', deleteCompleted, totalToDelete, taskInfo || ('Deleted ' + deleteCompleted + ' items'));
4512
+ }
3663
4513
  });
3664
4514
  lastProgressLength = statusResult.progress.length;
3665
- log.scrollTop = log.scrollHeight;
4515
+ scrollToBottom(log);
3666
4516
  }
3667
4517
  } catch (e) {}
3668
4518
  }, 500);
@@ -3683,6 +4533,8 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3683
4533
  result.classList.remove('hidden');
3684
4534
 
3685
4535
  if (deleteResult.success) {
4536
+ // Final progress update
4537
+ updateProgressUI('delete', totalToDelete, totalToDelete, '✅ Deletion complete!');
3686
4538
  result.textContent = '';
3687
4539
  result.appendChild(createAlert('success', '✅ Environment deleted successfully!'));
3688
4540
 
@@ -3694,6 +4546,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3694
4546
  } else {
3695
4547
  result.textContent = '';
3696
4548
  result.appendChild(createAlert('error', '❌ Some errors occurred: ' + (deleteResult.errors || []).join(', ')));
4549
+ btn.classList.remove('hidden');
3697
4550
  btn.disabled = false;
3698
4551
  }
3699
4552
  } catch (error) {
@@ -3701,6 +4554,7 @@ export function getHtmlTemplate(sessionToken, manageOnly) {
3701
4554
  result.classList.remove('hidden');
3702
4555
  result.textContent = '';
3703
4556
  result.appendChild(createAlert('error', '❌ Error: ' + error.message));
4557
+ btn.classList.remove('hidden');
3704
4558
  btn.disabled = false;
3705
4559
  }
3706
4560
  });