@dupecom/botcha-cloudflare 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +9 -8
  2. package/dist/agents.d.ts +68 -0
  3. package/dist/agents.d.ts.map +1 -0
  4. package/dist/agents.js +123 -0
  5. package/dist/apps.d.ts +73 -7
  6. package/dist/apps.d.ts.map +1 -1
  7. package/dist/apps.js +164 -9
  8. package/dist/challenges.d.ts.map +1 -1
  9. package/dist/challenges.js +5 -4
  10. package/dist/dashboard/api.d.ts +70 -0
  11. package/dist/dashboard/api.d.ts.map +1 -0
  12. package/dist/dashboard/api.js +553 -0
  13. package/dist/dashboard/auth.d.ts +183 -0
  14. package/dist/dashboard/auth.d.ts.map +1 -0
  15. package/dist/dashboard/auth.js +401 -0
  16. package/dist/dashboard/device-code.d.ts +43 -0
  17. package/dist/dashboard/device-code.d.ts.map +1 -0
  18. package/dist/dashboard/device-code.js +77 -0
  19. package/dist/dashboard/index.d.ts +31 -0
  20. package/dist/dashboard/index.d.ts.map +1 -0
  21. package/dist/dashboard/index.js +64 -0
  22. package/dist/dashboard/landing.d.ts +20 -0
  23. package/dist/dashboard/landing.d.ts.map +1 -0
  24. package/dist/dashboard/landing.js +45 -0
  25. package/dist/dashboard/layout.d.ts +54 -0
  26. package/dist/dashboard/layout.d.ts.map +1 -0
  27. package/dist/dashboard/layout.js +55 -0
  28. package/dist/dashboard/pages.d.ts +11 -0
  29. package/dist/dashboard/pages.d.ts.map +1 -0
  30. package/dist/dashboard/pages.js +18 -0
  31. package/dist/dashboard/styles.d.ts +11 -0
  32. package/dist/dashboard/styles.d.ts.map +1 -0
  33. package/dist/dashboard/styles.js +731 -0
  34. package/dist/email.d.ts +41 -0
  35. package/dist/email.d.ts.map +1 -0
  36. package/dist/email.js +116 -0
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +666 -189
  40. package/dist/routes/stream.js +2 -2
  41. package/dist/static.d.ts +392 -4
  42. package/dist/static.d.ts.map +1 -1
  43. package/dist/static.js +511 -14
  44. package/package.json +1 -1
@@ -0,0 +1,731 @@
1
+ /**
2
+ * BOTCHA Dashboard CSS
3
+ *
4
+ * Light terminal aesthetic — black and white with offwhite background.
5
+ * Borrows structural patterns from turbopuffer (dot shadows, hard borders,
6
+ * layered box-shadows on buttons) but with BOTCHA's own identity.
7
+ *
8
+ * JetBrains Mono · #ffffff bg · #1a1a1a text · black accent · square corners · dot shadows
9
+ */
10
+ export const DASHBOARD_CSS = `
11
+ /* ============ Reset ============ */
12
+ * { margin: 0; padding: 0; box-sizing: border-box; }
13
+
14
+ :root {
15
+ /* ---- palette (black & white) ---- */
16
+ --bg: #ffffff;
17
+ --bg-card: #ffffff;
18
+ --bg-raised: #eae8e4;
19
+ --text: #1a1a1a;
20
+ --text-muted: #6b6b6b;
21
+ --text-dim: #a0a0a0;
22
+ --accent: #1a1a1a;
23
+ --accent-dim: #333333;
24
+ --red: #cc2222;
25
+ --amber: #b87a00;
26
+ --green: #1a8a2a;
27
+ --border: #ddd9d4;
28
+ --border-bright: #c0bbb5;
29
+
30
+ /* ---- type ---- */
31
+ --font: 'JetBrains Mono', 'Courier New', monospace;
32
+
33
+ /* ---- dot shadow (turbopuffer SVG pattern, black fill) ---- */
34
+ --dot-shadow: url("data:image/svg+xml,%3Csvg width='7' height='13' viewBox='0 0 7 13' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.58984 12.2344V10.7051H6.52734V12.2344H5.58984ZM1.86328 12.2344V10.7051H2.79492V12.2344H1.86328ZM3.72656 10.0957V8.56641H4.6582V10.0957H3.72656ZM0 10.0957V8.56641H0.925781V10.0957H0ZM5.58984 7.95117V6.42188H6.52734V7.95117H5.58984ZM1.86328 7.95117V6.42188H2.79492V7.95117H1.86328ZM3.72656 5.8125V4.2832H4.6582V5.8125H3.72656ZM0 5.8125V4.2832H0.925781V5.8125H0ZM5.58984 3.66797V2.13867H6.52734V3.66797H5.58984ZM1.86328 3.66797V2.13867H2.79492V3.66797H1.86328ZM3.72656 1.5293V0H4.6582V1.5293H3.72656ZM0 1.5293V0H0.925781V1.5293H0Z' fill='%231a1a1a'/%3E%3C/svg%3E");
35
+ }
36
+
37
+ /* ============ Base ============ */
38
+ html, body {
39
+ height: 100%;
40
+ font-family: var(--font);
41
+ font-size: 16px;
42
+ line-height: 1.6;
43
+ background: var(--bg);
44
+ color: var(--text);
45
+ -webkit-font-smoothing: antialiased;
46
+ }
47
+
48
+ body { display: flex; flex-direction: column; }
49
+
50
+ ::selection { background: var(--accent); color: #fff; }
51
+
52
+ a { color: var(--accent); }
53
+ a:hover { text-decoration: none; opacity: 0.65; }
54
+
55
+ /* ============ Scanline overlay (subtle CRT feel) ============ */
56
+ body::before {
57
+ content: '';
58
+ position: fixed;
59
+ inset: 0;
60
+ background: repeating-linear-gradient(
61
+ 0deg,
62
+ transparent,
63
+ transparent 2px,
64
+ rgba(0, 0, 0, 0.012) 2px,
65
+ rgba(0, 0, 0, 0.012) 4px
66
+ );
67
+ pointer-events: none;
68
+ z-index: 9999;
69
+ }
70
+
71
+ /* ============ Dot shadow utility ============ */
72
+ .dot-shadow { position: relative; }
73
+ .dot-shadow::after {
74
+ content: '';
75
+ position: absolute;
76
+ top: 0.5rem; left: 0.5rem;
77
+ right: -0.5rem; bottom: -0.5rem;
78
+ background-image: var(--dot-shadow);
79
+ background-repeat: repeat;
80
+ z-index: -1;
81
+ pointer-events: none;
82
+ opacity: 0.6;
83
+ }
84
+
85
+ /* ============ Navigation ============ */
86
+ .dashboard-nav {
87
+ background: var(--bg);
88
+ border-bottom: 1px solid var(--border);
89
+ position: sticky; top: 0; z-index: 100;
90
+ }
91
+
92
+ .nav-container {
93
+ max-width: 1200px;
94
+ margin: 0 auto;
95
+ padding: 0.75rem 1.5rem;
96
+ display: flex;
97
+ align-items: center;
98
+ gap: 1.5rem;
99
+ }
100
+
101
+ .nav-logo {
102
+ font-weight: 700;
103
+ font-size: 0.875rem;
104
+ color: var(--text);
105
+ text-decoration: none;
106
+ letter-spacing: 0.15em;
107
+ text-transform: uppercase;
108
+ }
109
+ .nav-logo:hover { opacity: 1; }
110
+
111
+ .nav-app-id {
112
+ color: var(--text-muted);
113
+ font-size: 0.75rem;
114
+ margin-left: auto;
115
+ }
116
+
117
+ .nav-link {
118
+ color: var(--text);
119
+ text-decoration: none;
120
+ font-size: 0.75rem;
121
+ border: 1px solid var(--border-bright);
122
+ padding: 0.25rem 0.75rem;
123
+ text-transform: uppercase;
124
+ letter-spacing: 0.05em;
125
+ transition: background 0.1s, color 0.1s;
126
+ }
127
+ .nav-link:hover {
128
+ background: var(--accent);
129
+ color: var(--bg);
130
+ border-color: var(--accent);
131
+ opacity: 1;
132
+ }
133
+
134
+ /* ============ Main content ============ */
135
+ .dashboard-main {
136
+ flex: 1;
137
+ max-width: 1200px;
138
+ width: 100%;
139
+ margin: 0 auto;
140
+ padding: 2rem 1.5rem;
141
+ }
142
+
143
+ /* ============ Card — primary container (Turbopuffer-style) ============ */
144
+ .card {
145
+ display: flex;
146
+ flex-direction: column;
147
+ margin-bottom: 1.5rem;
148
+ }
149
+
150
+ .card-header {
151
+ margin-bottom: -1px; /* overlap the border */
152
+ padding: 0;
153
+ }
154
+
155
+ .card-header h3 {
156
+ position: relative;
157
+ display: inline-flex;
158
+ align-items: center;
159
+ z-index: 10;
160
+ top: 0.5rem;
161
+ left: 0.5rem;
162
+ font-size: 0.75rem;
163
+ font-weight: 700;
164
+ text-transform: uppercase;
165
+ letter-spacing: 0.1em;
166
+ line-height: 1;
167
+ color: var(--text);
168
+ background: var(--bg);
169
+ margin: 0;
170
+ padding: 0 0.5rem;
171
+ }
172
+
173
+ .card-header h3 .card-title {
174
+ }
175
+
176
+ .card-header h3 .badge-inline {
177
+ }
178
+
179
+ .card-body {
180
+ position: relative;
181
+ border: 2px solid var(--border-bright);
182
+ }
183
+
184
+ .card-body::before {
185
+ content: '';
186
+ position: absolute;
187
+ top: 0.5rem;
188
+ left: 0.5rem;
189
+ right: -0.5rem;
190
+ bottom: -0.5rem;
191
+ background-image: var(--dot-shadow);
192
+ background-repeat: repeat;
193
+ pointer-events: none;
194
+ opacity: 0.6;
195
+ }
196
+
197
+ .card-inner {
198
+ position: relative;
199
+ z-index: 1;
200
+ background: var(--bg-card);
201
+ padding: 1.5rem;
202
+ }
203
+
204
+ /* Legacy fieldset support (deprecated — use .card instead) */
205
+ fieldset {
206
+ border: 2px solid var(--border-bright);
207
+ border-radius: 0;
208
+ padding: 1.5rem;
209
+ margin-bottom: 1.5rem;
210
+ background: var(--bg-card);
211
+ position: relative;
212
+ z-index: 0;
213
+ }
214
+
215
+ legend {
216
+ padding: 0 0.5rem;
217
+ font-size: 0.75rem;
218
+ color: var(--text);
219
+ font-weight: 700;
220
+ text-transform: uppercase;
221
+ letter-spacing: 0.1em;
222
+ }
223
+
224
+ /* ============ Dashboard grid ============ */
225
+ .dashboard-grid {
226
+ display: grid;
227
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
228
+ gap: 1.5rem;
229
+ margin-bottom: 1.5rem;
230
+ }
231
+
232
+ /* ============ Stat cards ============ */
233
+ .stat-card {
234
+ display: flex; flex-direction: column; gap: 0.25rem;
235
+ padding: 1rem;
236
+ border: 1px solid var(--border);
237
+ background: var(--bg-card);
238
+ }
239
+
240
+ .stat-card .stat-value {
241
+ font-size: 2rem; font-weight: 700; line-height: 1;
242
+ color: var(--text);
243
+ font-variant-numeric: tabular-nums;
244
+ }
245
+
246
+ .stat-card .stat-label {
247
+ font-size: 0.6875rem;
248
+ color: var(--text-muted);
249
+ text-transform: uppercase;
250
+ letter-spacing: 0.1em;
251
+ }
252
+
253
+ .stat-card .stat-change { font-size: 0.75rem; font-weight: 500; }
254
+ .stat-card .stat-change.positive { color: var(--green); }
255
+ .stat-card .stat-change.negative { color: var(--red); }
256
+
257
+ /* ============ Bar chart ============ */
258
+ .bar-chart { width: 100%; }
259
+
260
+ .bar-chart .bar-item { margin-bottom: 0.75rem; }
261
+
262
+ .bar-chart .bar-label {
263
+ display: flex; justify-content: space-between; align-items: center;
264
+ margin-bottom: 0.125rem; font-size: 0.75rem;
265
+ }
266
+ .bar-chart .bar-name { color: var(--text); }
267
+ .bar-chart .bar-value {
268
+ color: var(--text-muted);
269
+ font-weight: 700; font-variant-numeric: tabular-nums;
270
+ }
271
+
272
+ .bar-chart .bar {
273
+ height: 18px;
274
+ background: var(--accent);
275
+ border-radius: 0;
276
+ transition: width 0.3s ease;
277
+ position: relative; overflow: hidden;
278
+ opacity: 0.8;
279
+ }
280
+ .bar-chart .bar:hover { opacity: 1; }
281
+
282
+ .bar-chart .bar-fill { height: 100%; background: var(--accent); }
283
+
284
+ /* ============ Form controls ============ */
285
+ input, select, textarea, button { font-family: var(--font); font-size: 0.875rem; }
286
+
287
+ input[type="text"],
288
+ input[type="email"],
289
+ input[type="password"],
290
+ input[type="number"],
291
+ select,
292
+ textarea {
293
+ width: 100%;
294
+ padding: 0.625rem 0.75rem;
295
+ background: var(--bg);
296
+ border: 1px solid var(--border-bright);
297
+ border-radius: 0;
298
+ color: var(--text);
299
+ }
300
+
301
+ input:focus, select:focus, textarea:focus {
302
+ outline: none;
303
+ border-color: var(--accent);
304
+ box-shadow: 0 0 0 1px var(--accent);
305
+ }
306
+
307
+ input::placeholder, textarea::placeholder { color: var(--text-dim); }
308
+
309
+ label {
310
+ display: block;
311
+ margin-bottom: 0.375rem;
312
+ font-size: 0.6875rem;
313
+ color: var(--text-muted);
314
+ font-weight: 700;
315
+ text-transform: uppercase;
316
+ letter-spacing: 0.08em;
317
+ }
318
+
319
+ .form-group { margin-bottom: 1.25rem; }
320
+
321
+ /* ============ Buttons ============ */
322
+ button, .button {
323
+ display: inline-block;
324
+ padding: 0.625rem 1.25rem;
325
+ background: var(--accent);
326
+ color: #fff;
327
+ border: 1px solid var(--accent);
328
+ border-radius: 0;
329
+ font-weight: 700;
330
+ cursor: pointer;
331
+ text-decoration: none;
332
+ text-align: center;
333
+ text-transform: uppercase;
334
+ letter-spacing: 0.08em;
335
+ font-size: 0.75rem;
336
+ box-shadow:
337
+ inset 1px 1px 0 rgba(255,255,255,0.15),
338
+ inset -1px -1px 0 rgba(0,0,0,0.15),
339
+ 2px 2px 0 rgba(0,0,0,0.1);
340
+ transition: box-shadow 0.1s, transform 0.1s;
341
+ }
342
+ button:hover, .button:hover {
343
+ box-shadow:
344
+ inset 1px 1px 0 rgba(255,255,255,0.1),
345
+ inset -1px -1px 0 rgba(0,0,0,0.15),
346
+ 3px 3px 0 rgba(0,0,0,0.12);
347
+ opacity: 1;
348
+ }
349
+ button:active, .button:active {
350
+ transform: translate(1px, 1px);
351
+ box-shadow: inset 1px 1px 3px rgba(0,0,0,0.25);
352
+ }
353
+ button:disabled, .button:disabled { opacity: 0.25; cursor: not-allowed; }
354
+
355
+ button.secondary, .button.secondary {
356
+ background: transparent;
357
+ color: var(--text);
358
+ border-color: var(--border-bright);
359
+ box-shadow: 2px 2px 0 rgba(0,0,0,0.05);
360
+ }
361
+ button.secondary:hover, .button.secondary:hover {
362
+ border-color: var(--accent);
363
+ color: var(--accent);
364
+ box-shadow: 2px 2px 0 rgba(0,0,0,0.1);
365
+ }
366
+
367
+ button.danger, .button.danger {
368
+ background: var(--red);
369
+ border-color: var(--red);
370
+ color: #fff;
371
+ box-shadow: 2px 2px 0 rgba(204,34,34,0.15);
372
+ }
373
+ button.danger:hover, .button.danger:hover {
374
+ background: transparent;
375
+ color: var(--red);
376
+ }
377
+
378
+ /* ============ Tables ============ */
379
+ table { width: 100%; border-collapse: collapse; }
380
+
381
+ thead { border-bottom: 1px solid var(--border-bright); }
382
+ th {
383
+ padding: 0.5rem 0.75rem; text-align: left;
384
+ font-size: 0.6875rem; color: var(--text);
385
+ font-weight: 700; text-transform: uppercase;
386
+ letter-spacing: 0.1em;
387
+ background: var(--bg-raised);
388
+ }
389
+
390
+ td {
391
+ padding: 0.5rem 0.75rem;
392
+ border-bottom: 1px solid var(--border);
393
+ font-size: 0.75rem;
394
+ font-variant-numeric: tabular-nums;
395
+ }
396
+
397
+ tbody tr:hover { background: var(--bg-raised); }
398
+
399
+ /* ============ Code ============ */
400
+ code, pre {
401
+ font-family: var(--font);
402
+ background: var(--bg-raised);
403
+ padding: 0.125rem 0.375rem;
404
+ border-radius: 0;
405
+ font-size: 0.75rem;
406
+ border: 1px solid var(--border);
407
+ color: var(--text);
408
+ }
409
+ pre { padding: 1rem; overflow-x: auto; border: 1px solid var(--border-bright); }
410
+ pre code { background: none; padding: 0; border: none; }
411
+
412
+ /* ============ Login layout ============ */
413
+ .login-container {
414
+ min-height: 100vh;
415
+ display: flex; align-items: center; justify-content: center;
416
+ padding: 2rem;
417
+ background: var(--bg);
418
+ }
419
+ .login-box { width: 100%; max-width: 420px; }
420
+
421
+ .login-header { text-align: center; margin-bottom: 2rem; }
422
+ .login-header h1 {
423
+ font-size: 1.5rem; font-weight: 700; color: var(--text);
424
+ letter-spacing: 0.15em; text-transform: uppercase;
425
+ margin-bottom: 0.25rem;
426
+ }
427
+ .login-header p { color: var(--text-muted); font-size: 0.75rem; }
428
+
429
+ /* ============ htmx loading ============ */
430
+ .htmx-indicator { opacity: 0; transition: opacity 0.15s; }
431
+ .htmx-request .htmx-indicator { opacity: 1; }
432
+ .htmx-request.htmx-swapping { opacity: 0.3; pointer-events: none; }
433
+
434
+ /* ============ Skeleton — blinking cursor ============ */
435
+ .skeleton {
436
+ background: var(--bg-raised);
437
+ border: 1px solid var(--border);
438
+ position: relative;
439
+ overflow: hidden;
440
+ }
441
+ .skeleton::after {
442
+ content: '';
443
+ position: absolute; left: 0; top: 0;
444
+ width: 2px; height: 100%;
445
+ background: var(--text);
446
+ animation: cursor-blink 0.8s step-end infinite;
447
+ }
448
+ @keyframes cursor-blink {
449
+ 0%, 100% { opacity: 1; }
450
+ 50% { opacity: 0; }
451
+ }
452
+
453
+ .skeleton-text { height: 1rem; margin-bottom: 0.5rem; }
454
+ .skeleton-heading { height: 1.5rem; width: 60%; margin-bottom: 1rem; }
455
+
456
+ /* ============ Utilities ============ */
457
+ .text-center { text-align: center; }
458
+ .text-right { text-align: right; }
459
+ .text-muted { color: var(--text-muted); }
460
+ .text-dim { color: var(--text-dim); }
461
+ .text-success { color: var(--green); }
462
+ .text-danger { color: var(--red); }
463
+ .text-warning { color: var(--amber); }
464
+
465
+ .mb-0 { margin-bottom: 0; }
466
+ .mb-1 { margin-bottom: 0.5rem; }
467
+ .mb-2 { margin-bottom: 1rem; }
468
+ .mb-3 { margin-bottom: 1.5rem; }
469
+ .mb-4 { margin-bottom: 2rem; }
470
+ .mt-0 { margin-top: 0; }
471
+ .mt-1 { margin-top: 0.5rem; }
472
+ .mt-2 { margin-top: 1rem; }
473
+ .mt-3 { margin-top: 1.5rem; }
474
+ .mt-4 { margin-top: 2rem; }
475
+
476
+ /* ============ Period selector ============ */
477
+ .period-selector button {
478
+ font-size: 0.625rem;
479
+ padding: 0.2rem 0.5rem;
480
+ }
481
+
482
+ /* ============ Responsive ============ */
483
+ @media (max-width: 768px) {
484
+ html, body { font-size: 14px; }
485
+ .dashboard-main { padding: 1rem; }
486
+ .nav-container { padding: 0.5rem 1rem; }
487
+ .dashboard-grid { grid-template-columns: 1fr; gap: 1rem; }
488
+ .card-inner { padding: 1rem; }
489
+ .card { margin-bottom: 1rem; }
490
+ fieldset { padding: 1rem; margin-bottom: 1rem; }
491
+ .stat-card .stat-value { font-size: 1.75rem; }
492
+ table { font-size: 0.625rem; }
493
+ th, td { padding: 0.375rem 0.5rem; }
494
+ }
495
+
496
+ @media (max-width: 480px) {
497
+ .nav-container { flex-wrap: wrap; }
498
+ .nav-app-id { margin-left: 0; width: 100%; order: 3; }
499
+ }
500
+
501
+ /* ============ Alerts ============ */
502
+ .alert {
503
+ padding: 0.75rem 1rem;
504
+ border-radius: 0;
505
+ margin-bottom: 1.5rem;
506
+ border: 1px solid var(--border-bright);
507
+ font-size: 0.75rem;
508
+ background: var(--bg-card);
509
+ }
510
+ .alert::before { font-weight: 700; margin-right: 0.5rem; }
511
+
512
+ .alert-info { border-color: var(--border-bright); color: var(--text); }
513
+ .alert-info::before { content: '>'; color: var(--text); }
514
+
515
+ .alert-success { border-color: var(--green); color: var(--green); }
516
+ .alert-success::before { content: '[ok]'; }
517
+
518
+ .alert-warning { border-color: var(--amber); color: var(--amber); }
519
+ .alert-warning::before { content: '[!!]'; }
520
+
521
+ .alert-danger { border-color: var(--red); color: var(--red); }
522
+ .alert-danger::before { content: '[ERR]'; }
523
+
524
+ /* ============ Badges ============ */
525
+ .badge {
526
+ display: inline-block;
527
+ padding: 0.125rem 0.375rem;
528
+ font-size: 0.625rem; font-weight: 700;
529
+ border-radius: 0;
530
+ text-transform: uppercase;
531
+ letter-spacing: 0.05em;
532
+ border: 1px solid;
533
+ }
534
+ .badge-success { color: var(--green); border-color: var(--green); background: transparent; }
535
+ .badge-danger { color: var(--red); border-color: var(--red); background: transparent; }
536
+ .badge-warning { color: var(--amber); border-color: var(--amber); background: transparent; }
537
+ .badge-info { color: #fff; border-color: var(--accent); background: var(--accent); }
538
+
539
+ /* ============ Sample data indicator ============ */
540
+ .sample-banner {
541
+ background: #fffbe6;
542
+ border: 1px solid var(--amber);
543
+ color: var(--amber);
544
+ padding: 0.5rem 0.75rem;
545
+ font-size: 0.6875rem;
546
+ font-weight: 700;
547
+ text-transform: uppercase;
548
+ letter-spacing: 0.05em;
549
+ margin-bottom: 1rem;
550
+ }
551
+ .sample-banner::before { content: '[demo]'; margin-right: 0.5rem; }
552
+ .sample-tag {
553
+ color: var(--amber);
554
+ font-size: 0.625rem;
555
+ font-weight: 700;
556
+ letter-spacing: 0.05em;
557
+ border: 1px solid var(--amber);
558
+ padding: 0.0625rem 0.3rem;
559
+ margin-left: 0.375rem;
560
+ vertical-align: middle;
561
+ background: #fffbe6;
562
+ }
563
+
564
+ /* ============ Empty state ============ */
565
+ .empty-state { text-align: center; padding: 3rem 1rem; color: var(--text-muted); }
566
+ .empty-state-icon { font-size: 1.5rem; margin-bottom: 0.75rem; color: var(--text); font-weight: 700; }
567
+ .empty-state-text { font-size: 0.8125rem; margin-bottom: 0.25rem; }
568
+ .empty-state-subtext { font-size: 0.6875rem; color: var(--text-dim); }
569
+
570
+ /* ============ Auth pages ============ */
571
+ .ascii-logo {
572
+ display: block; text-align: center; margin-bottom: 2rem;
573
+ color: var(--text); font-size: 0.55rem; line-height: 1.2;
574
+ white-space: pre; font-weight: 400;
575
+ text-decoration: none;
576
+ }
577
+
578
+ .badge-inline {
579
+ display: inline-block; font-size: 0.5625rem; font-weight: 700;
580
+ color: var(--text-muted); border: 1px solid var(--border-bright);
581
+ border-radius: 0; padding: 0.1rem 0.4rem;
582
+ margin-left: 0.5rem; vertical-align: middle;
583
+ text-transform: uppercase; letter-spacing: 0.05em;
584
+ }
585
+
586
+ .divider {
587
+ display: flex; align-items: center; gap: 0.75rem;
588
+ color: var(--text-dim); font-size: 0.6875rem;
589
+ margin: 1.5rem 0;
590
+ text-transform: uppercase; letter-spacing: 0.1em;
591
+ white-space: nowrap;
592
+ }
593
+ .divider::before, .divider::after {
594
+ content: ''; flex: 1;
595
+ height: 1px; background: var(--border-bright);
596
+ }
597
+
598
+ .credentials-box {
599
+ background: var(--bg); border: 1px solid var(--accent-dim);
600
+ padding: 1rem; margin-bottom: 1rem;
601
+ font-size: 0.75rem; line-height: 1.8; word-break: break-all;
602
+ }
603
+ .credentials-box .label { color: var(--text-muted); }
604
+ .credentials-box .value { color: var(--text); font-weight: 700; }
605
+
606
+ .warning {
607
+ background: rgba(184,122,0,0.06); border: 1px solid var(--amber);
608
+ padding: 0.75rem; margin-bottom: 1rem;
609
+ font-size: 0.7rem; color: var(--amber);
610
+ }
611
+ .warning::before { content: '[!!] '; font-weight: 700; }
612
+
613
+ .error-message {
614
+ color: var(--red); margin: 0 0 1rem 0; font-size: 0.75rem;
615
+ padding: 0.5rem 0.75rem;
616
+ border: 1px solid rgba(204,34,34,0.3);
617
+ background: var(--bg);
618
+ }
619
+ .error-message::before { content: '[ERR] '; font-weight: 700; }
620
+
621
+ .hint {
622
+ font-size: 0.6875rem; color: var(--text-muted); line-height: 1.6;
623
+ margin-top: 0.75rem;
624
+ }
625
+ .hint code {
626
+ color: var(--text); background: var(--bg-raised);
627
+ padding: 0.125rem 0.375rem; border: 1px solid var(--border);
628
+ }
629
+
630
+ .btn {
631
+ display: block; width: 100%; text-align: center; text-decoration: none;
632
+ }
633
+ .btn-secondary {
634
+ background: transparent; color: var(--text);
635
+ border-color: var(--border-bright);
636
+ box-shadow: 2px 2px 0 rgba(0,0,0,0.05);
637
+ }
638
+ .btn-secondary:hover {
639
+ border-color: var(--accent); color: var(--accent);
640
+ box-shadow: 2px 2px 0 rgba(0,0,0,0.1);
641
+ }
642
+
643
+ #create-result { display: none; }
644
+ #create-result.show { display: block; }
645
+ #create-btn.loading { opacity: 0.25; pointer-events: none; }
646
+
647
+ /* ============ Landing page ============ */
648
+ .landing-box { width: 100%; max-width: 580px; }
649
+ .landing-box .ascii-logo { font-size: 0.75rem; margin-bottom: 1rem; }
650
+
651
+ /* Landing page flows from top, not vertically centered like login */
652
+ .login-container:has(.landing-box) {
653
+ align-items: flex-start; padding-top: 4rem;
654
+ }
655
+
656
+ .landing-tagline {
657
+ text-align: center; font-size: 0.8125rem;
658
+ color: var(--text-muted); margin-bottom: 1.5rem;
659
+ }
660
+
661
+ .landing-links {
662
+ display: flex; flex-wrap: wrap; justify-content: center;
663
+ gap: 0.5rem; margin-bottom: 2rem;
664
+ }
665
+ .landing-link {
666
+ font-size: 0.6875rem; color: var(--text);
667
+ text-decoration: none; padding: 0.25rem 0.625rem;
668
+ border: 1px solid var(--border-bright);
669
+ transition: border-color 0.15s, background 0.15s;
670
+ }
671
+ .landing-link:hover {
672
+ border-color: var(--accent); background: var(--bg-raised);
673
+ }
674
+
675
+ .landing-features {
676
+ display: flex; flex-direction: column; gap: 0.75rem;
677
+ margin-top: 1rem;
678
+ }
679
+ .landing-feature {
680
+ display: flex; gap: 0.75rem; align-items: baseline;
681
+ font-size: 0.75rem;
682
+ }
683
+ .landing-feature-label {
684
+ font-weight: 700; color: var(--text);
685
+ white-space: nowrap; min-width: 10rem;
686
+ }
687
+ .landing-feature-desc { color: var(--text-muted); }
688
+
689
+ .landing-steps { display: flex; flex-direction: column; gap: 0.75rem; }
690
+ .landing-step {
691
+ display: flex; gap: 0.75rem; align-items: flex-start;
692
+ font-size: 0.75rem; line-height: 1.6;
693
+ }
694
+ .landing-step-num {
695
+ display: inline-flex; align-items: center; justify-content: center;
696
+ min-width: 1.5rem; height: 1.5rem;
697
+ border: 1px solid var(--border-bright);
698
+ font-size: 0.6875rem; font-weight: 700; color: var(--text);
699
+ flex-shrink: 0;
700
+ }
701
+ .landing-step-hint {
702
+ display: block; font-size: 0.6875rem; color: var(--text-dim);
703
+ margin-top: 0.125rem;
704
+ }
705
+
706
+ .landing-footer {
707
+ text-align: center; padding: 2rem 0 0;
708
+ font-size: 0.6875rem; color: var(--text-dim);
709
+ }
710
+ .landing-footer a {
711
+ color: var(--text-muted); text-decoration: none;
712
+ }
713
+ .landing-footer a:hover { color: var(--text); }
714
+ .landing-footer-sep { margin: 0 0.375rem; }
715
+
716
+ /* ============ Scrollbar ============ */
717
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
718
+ ::-webkit-scrollbar-track { background: var(--bg-raised); }
719
+ ::-webkit-scrollbar-thumb { background: var(--border-bright); }
720
+ ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
721
+
722
+ /* ============ Responsive (small screens) ============ */
723
+ @media (max-width: 480px) {
724
+ .ascii-logo { font-size: 0.4rem; }
725
+ .landing-box .ascii-logo { font-size: 0.5rem; }
726
+ .login-container { padding: 1rem; }
727
+ .card-inner { padding: 1rem; }
728
+ .landing-feature { flex-direction: column; gap: 0.125rem; }
729
+ .landing-feature-label { min-width: auto; }
730
+ }
731
+ `;