fraim 2.0.280 → 2.0.283

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 (31) hide show
  1. package/README.md +467 -467
  2. package/bin/fraim.js +12 -12
  3. package/dist/src/cli/mcp/fraim-mcp-latest-launcher.js +266 -182
  4. package/dist/src/cli/mcp/mcp-server-registry.js +11 -3
  5. package/dist/src/cli/setup/ide-invocation-surfaces.js +64 -64
  6. package/dist/src/cli/utils/agent-adapters.js +61 -61
  7. package/dist/src/core/ai-mentor.js +35 -0
  8. package/dist/src/core/handoff-contracts.js +73 -46
  9. package/dist/src/core/resolve-phase-edge.js +33 -0
  10. package/dist/src/core/utils/stub-generator.js +53 -53
  11. package/dist/src/first-run/server.js +5 -1
  12. package/dist/src/first-run/session-service.js +48 -12
  13. package/dist/src/fraim/issues.js +4 -4
  14. package/dist/src/local-mcp-server/stdio-server.js +43 -4
  15. package/dist/src/mcp/tool-schemas.js +40 -40
  16. package/dist/src/middleware/telemetry.js +21 -21
  17. package/dist/src/services/email-service.js +623 -623
  18. package/dist/src/services/installer-service.js +22 -22
  19. package/index.js +83 -83
  20. package/package.json +59 -59
  21. package/public/first-run/error-frame.js +100 -100
  22. package/public/first-run/index.html +35 -35
  23. package/public/first-run/script.js +747 -742
  24. package/public/first-run/styles.css +929 -929
  25. package/dist/src/cli/commands/learning-usage.js +0 -412
  26. package/dist/src/cli/commands/test-mcp.js +0 -171
  27. package/dist/src/cli/setup/first-run.js +0 -242
  28. package/dist/src/core/config-writer.js +0 -75
  29. package/dist/src/core/utils/job-aliases.js +0 -47
  30. package/dist/src/core/utils/workflow-parser.js +0 -174
  31. package/dist/src/services/email-service-clean.js +0 -782
@@ -1,929 +1,929 @@
1
- /*
2
- * FRAIM first-run — Setup checklist surface.
3
- *
4
- * The :root variable set below is a STRICT SUBSET of public/ai-hub/styles.css
5
- * — see R5.1 acceptance and tests/test-installer-service.ts'
6
- * `testBootstrapCssVarsAreSubsetOfHub`. Adding a token here that does not
7
- * exist on the Hub side fails CI.
8
- */
9
- :root {
10
- --bg: #f4f6f2;
11
- --surface: #ffffff;
12
- --soft: #f7faf6;
13
- --line: #e3e8df;
14
- --text: #1f2a24;
15
- --muted: #6b7a72;
16
- --accent: #3d8a6e;
17
- --accent-strong: #2f7359;
18
- --accent-soft: #eaf3ee;
19
- --warn: #b08442;
20
- --warn-soft: #fffaf0;
21
- --danger: #a24747;
22
- --shadow: 0 1px 2px rgba(20, 40, 30, 0.04);
23
- --shadow-lg: 0 12px 36px rgba(20, 40, 30, 0.18);
24
- }
25
-
26
- * { box-sizing: border-box; }
27
- html, body { margin: 0; padding: 0; }
28
- body {
29
- font-family: -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
30
- color: var(--text);
31
- background: var(--bg);
32
- line-height: 1.5;
33
- font-size: 15px;
34
- }
35
-
36
- .page {
37
- max-width: 720px;
38
- margin: 0 auto;
39
- padding: 48px 24px 32px;
40
- }
41
-
42
- .page-header h1 {
43
- margin: 0 0 8px;
44
- font-size: 26px;
45
- font-weight: 600;
46
- }
47
- .page-header .lede {
48
- margin: 0 0 24px;
49
- color: var(--muted);
50
- font-size: 16px;
51
- line-height: 1.5;
52
- }
53
-
54
- .card {
55
- background: var(--surface);
56
- border: 1px solid var(--line);
57
- border-radius: 14px;
58
- box-shadow: var(--shadow);
59
- padding: 24px;
60
- }
61
-
62
- .checklist {
63
- list-style: none;
64
- margin: 0;
65
- padding: 0;
66
- display: flex;
67
- flex-direction: column;
68
- border: 1px solid var(--line);
69
- border-radius: 12px;
70
- overflow: hidden;
71
- }
72
-
73
- .checklist .row {
74
- display: flex;
75
- flex-wrap: wrap;
76
- align-items: center;
77
- gap: 12px;
78
- padding: 14px 16px;
79
- border-bottom: 1px solid var(--line);
80
- background: var(--surface);
81
- }
82
- .checklist .row:last-child { border-bottom: 0; }
83
-
84
- .row .icon {
85
- width: 22px;
86
- height: 22px;
87
- border-radius: 50%;
88
- display: inline-flex;
89
- align-items: center;
90
- justify-content: center;
91
- font-size: 13px;
92
- font-weight: 700;
93
- flex-shrink: 0;
94
- }
95
- .row[data-row-status="ok"] .icon { background: var(--accent); color: #fff; }
96
- .row[data-row-status="pending"] .icon { background: var(--line); color: var(--muted); }
97
- .row[data-row-status="in-progress"] .icon { background: var(--accent-soft); color: var(--accent-strong); }
98
- .row[data-row-status="manual-required"] .icon { background: var(--warn-soft); color: var(--warn); border: 1px solid var(--warn); }
99
- .row[data-row-status="error"] .icon { background: #fbf1f1; color: var(--danger); border: 1px solid var(--danger); }
100
-
101
- .row .label { font-weight: 600; min-width: 124px; }
102
- .row .verb { color: var(--muted); font-size: 14px; flex: 1; }
103
- .row[data-row-status="ok"] .verb { color: var(--accent-strong); }
104
- .row[data-row-status="error"] .verb { color: var(--danger); }
105
- .row[data-row-status="manual-required"] .verb { color: var(--warn); }
106
-
107
- .row .detail {
108
- color: var(--muted);
109
- font-size: 13px;
110
- flex-basis: 100%;
111
- padding-left: 34px;
112
- }
113
-
114
- .setup-result {
115
- display: flex;
116
- flex-direction: column;
117
- gap: 8px;
118
- padding: 16px;
119
- border-top: 1px solid var(--line);
120
- background: var(--soft);
121
- }
122
- .setup-result strong {
123
- font-size: 15px;
124
- font-weight: 600;
125
- }
126
- .setup-result p {
127
- margin: 0;
128
- color: var(--muted);
129
- font-size: 14px;
130
- }
131
- .surface-list {
132
- margin: 0;
133
- padding-left: 18px;
134
- color: var(--muted);
135
- font-size: 14px;
136
- }
137
-
138
- .row .change-link {
139
- font-size: 13px;
140
- color: var(--accent-strong);
141
- text-decoration: none;
142
- cursor: pointer;
143
- border: 0;
144
- background: transparent;
145
- padding: 4px 6px;
146
- }
147
- .row .change-link:hover { text-decoration: underline; }
148
- .row .change-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
149
-
150
- .row .row-stream {
151
- flex-basis: 100%;
152
- margin: 8px 0 0;
153
- background: #0d1410;
154
- color: #c8d3cd;
155
- font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
156
- font-size: 12px;
157
- padding: 10px 12px;
158
- border-radius: 8px;
159
- max-height: 80px;
160
- overflow: auto;
161
- white-space: pre;
162
- }
163
- .row .manual-message {
164
- flex-basis: 100%;
165
- margin: 8px 0 0;
166
- background: var(--warn-soft);
167
- border: 1px solid var(--warn);
168
- color: var(--text);
169
- border-radius: 8px;
170
- padding: 10px 12px;
171
- font-size: 13px;
172
- }
173
- .row .manual-message code {
174
- background: var(--surface);
175
- padding: 2px 4px;
176
- border-radius: 4px;
177
- }
178
-
179
- /* Inline agent picker. No popups; no separate page. */
180
- .agent-picker {
181
- flex-basis: 100%;
182
- margin-top: 10px;
183
- background: var(--soft);
184
- border: 1px solid var(--line);
185
- border-radius: 10px;
186
- padding: 12px;
187
- display: flex;
188
- flex-direction: column;
189
- gap: 10px;
190
- }
191
- .agent-picker[hidden] { display: none; }
192
- .agent-picker .options { display: flex; gap: 8px; flex-wrap: wrap; }
193
- .agent-picker .option {
194
- background: var(--surface);
195
- border: 1px solid var(--line);
196
- border-radius: 8px;
197
- padding: 8px 12px;
198
- cursor: pointer;
199
- font-size: 14px;
200
- }
201
- .agent-picker .option:hover { background: var(--soft); border-color: var(--accent); }
202
- .agent-picker .option:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
203
- .agent-picker .option[aria-pressed="true"] {
204
- border-color: var(--accent);
205
- background: var(--accent-soft);
206
- color: var(--accent-strong);
207
- font-weight: 600;
208
- }
209
- .agent-picker details { margin-top: 4px; }
210
- .agent-picker summary {
211
- cursor: pointer;
212
- color: var(--muted);
213
- font-size: 13px;
214
- }
215
- .agent-picker .custom-warning {
216
- background: var(--warn-soft);
217
- border: 1px solid var(--warn);
218
- color: var(--text);
219
- border-radius: 8px;
220
- padding: 10px 12px;
221
- font-size: 13px;
222
- margin-top: 8px;
223
- }
224
- .agent-picker .custom-form {
225
- display: grid;
226
- grid-template-columns: 1fr 1fr auto;
227
- gap: 8px;
228
- margin-top: 8px;
229
- }
230
- .agent-picker .custom-form input {
231
- border: 1px solid var(--line);
232
- border-radius: 8px;
233
- padding: 8px 10px;
234
- font: inherit;
235
- }
236
- .agent-picker .custom-form button {
237
- background: var(--accent);
238
- color: #fff;
239
- border: 0;
240
- border-radius: 8px;
241
- padding: 8px 14px;
242
- cursor: pointer;
243
- font: inherit;
244
- }
245
-
246
- /* Project row picker affordances */
247
- .row .project-picker {
248
- display: flex;
249
- gap: 8px;
250
- align-items: center;
251
- flex-basis: 100%;
252
- margin-top: 8px;
253
- }
254
- .row .project-picker input {
255
- flex: 1;
256
- border: 1px solid var(--line);
257
- border-radius: 8px;
258
- padding: 8px 12px;
259
- font: inherit;
260
- }
261
- .row .project-picker .browse {
262
- background: var(--surface);
263
- border: 1px solid var(--line);
264
- border-radius: 8px;
265
- padding: 8px 12px;
266
- cursor: pointer;
267
- font: inherit;
268
- }
269
- .row .project-picker .browse:hover { background: var(--soft); border-color: var(--accent); }
270
-
271
- /* Preflight summary — shown above the Continue button on the project row.
272
- Tells the user exactly which side effects FRAIM will perform when they
273
- click Continue. The "no surprises" half of the non-tech-user invariant. */
274
- .row .preflight-summary {
275
- flex-basis: 100%;
276
- margin-top: 12px;
277
- padding: 12px 14px;
278
- border: 1px solid var(--line);
279
- background: var(--soft);
280
- border-radius: 8px;
281
- font-size: 13px;
282
- color: var(--muted);
283
- }
284
- .row .preflight-heading {
285
- color: var(--text);
286
- font-weight: 600;
287
- margin-bottom: 6px;
288
- }
289
- .row .preflight-list {
290
- margin: 0;
291
- padding-left: 18px;
292
- }
293
- .row .preflight-list li { margin: 2px 0; }
294
-
295
- .actions {
296
- display: flex;
297
- justify-content: flex-end;
298
- gap: 8px;
299
- margin-top: 20px;
300
- }
301
-
302
- /* Primary button — same geometry as Hub's send-button (R5.2). */
303
- .primary-button {
304
- background: var(--accent);
305
- color: #fff;
306
- border: 0;
307
- border-radius: 10px;
308
- padding: 10px 18px;
309
- font: inherit;
310
- font-weight: 600;
311
- cursor: pointer;
312
- }
313
- .primary-button:hover { background: var(--accent-strong); }
314
- .primary-button:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
315
- .primary-button:disabled { background: #c5d2cb; cursor: not-allowed; }
316
-
317
- .status {
318
- margin: 16px 0 0;
319
- padding: 12px 14px;
320
- border-radius: 10px;
321
- background: var(--soft);
322
- border: 1px solid var(--line);
323
- color: var(--muted);
324
- font-size: 14px;
325
- min-height: 1em;
326
- }
327
- .status:empty { display: none; }
328
- .status[data-tone="error"] {
329
- background: #fbf1f1;
330
- border-color: var(--danger);
331
- color: var(--danger);
332
- }
333
-
334
- /* Error frame — R6.1 single visual contract. */
335
- .error-frame {
336
- flex-basis: 100%;
337
- margin-top: 10px;
338
- background: #fbf1f1;
339
- border: 1px solid var(--danger);
340
- border-radius: 10px;
341
- padding: 12px 14px;
342
- display: flex;
343
- flex-direction: column;
344
- gap: 8px;
345
- }
346
- .error-frame .what-tried {
347
- color: var(--danger);
348
- font-weight: 600;
349
- }
350
- .error-frame .error-hint {
351
- color: var(--text);
352
- font-size: 14px;
353
- line-height: 1.45;
354
- background: var(--warn-soft);
355
- border: 1px solid #f0d8b3;
356
- border-radius: 8px;
357
- padding: 10px 12px;
358
- }
359
- .error-frame .what-happened {
360
- background: #0d1410;
361
- color: #f1c0c0;
362
- font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
363
- font-size: 12px;
364
- padding: 10px 12px;
365
- border-radius: 8px;
366
- max-height: 88px;
367
- overflow: auto;
368
- white-space: pre;
369
- margin: 0;
370
- }
371
- .error-frame .show-full {
372
- align-self: flex-start;
373
- font-size: 12px;
374
- color: var(--muted);
375
- cursor: pointer;
376
- background: 0;
377
- border: 0;
378
- padding: 0;
379
- text-decoration: underline;
380
- }
381
- .error-frame .actions {
382
- display: flex;
383
- gap: 8px;
384
- margin-top: 4px;
385
- justify-content: flex-start;
386
- }
387
- .error-frame .action {
388
- border-radius: 8px;
389
- padding: 8px 14px;
390
- cursor: pointer;
391
- font: inherit;
392
- font-weight: 500;
393
- border: 1px solid var(--line);
394
- background: var(--surface);
395
- color: var(--text);
396
- }
397
- .error-frame .action[data-variant="primary"] {
398
- background: var(--accent);
399
- color: #fff;
400
- border-color: var(--accent);
401
- }
402
- .error-frame .action[data-variant="primary"]:hover { background: var(--accent-strong); }
403
- .error-frame .action[data-variant="secondary"]:hover {
404
- border-color: var(--accent);
405
- color: var(--accent-strong);
406
- }
407
- .error-frame .action[data-variant="ghost"] {
408
- background: transparent;
409
- border-color: transparent;
410
- color: var(--accent-strong);
411
- }
412
-
413
- /* User-type selection screen — shown after all 4 setup rows complete.
414
- .checklist switches to .selection-container so card borders don't
415
- nest inside the outer bordered list container. */
416
- .selection-container {
417
- list-style: none;
418
- margin: 0;
419
- padding: 0;
420
- display: flex;
421
- flex-direction: column;
422
- }
423
-
424
- .setup-shell {
425
- list-style: none;
426
- margin: 0;
427
- padding: 0;
428
- display: grid;
429
- grid-template-columns: minmax(190px, 0.85fr) minmax(0, 2fr);
430
- gap: 20px;
431
- }
432
- .setup-steps {
433
- display: flex;
434
- flex-direction: column;
435
- gap: 8px;
436
- border-right: 1px solid var(--line);
437
- padding-right: 16px;
438
- }
439
- .setup-step {
440
- width: 100%;
441
- min-height: 44px;
442
- display: flex;
443
- align-items: center;
444
- gap: 10px;
445
- border: 1px solid var(--line);
446
- border-radius: 8px;
447
- background: var(--surface);
448
- color: var(--text);
449
- padding: 9px 10px;
450
- font: inherit;
451
- font-weight: 600;
452
- text-align: left;
453
- cursor: pointer;
454
- }
455
- .setup-step[aria-current="step"] {
456
- border-color: var(--accent);
457
- background: var(--accent-soft);
458
- }
459
- .setup-step:disabled {
460
- opacity: 0.55;
461
- cursor: not-allowed;
462
- }
463
- .step-dot {
464
- width: 24px;
465
- height: 24px;
466
- border-radius: 50%;
467
- display: inline-flex;
468
- align-items: center;
469
- justify-content: center;
470
- background: var(--line);
471
- color: var(--muted);
472
- font-size: 12px;
473
- flex: 0 0 auto;
474
- }
475
- .setup-step[data-status="done"] .step-dot {
476
- background: var(--accent);
477
- color: #fff;
478
- }
479
- .setup-pane {
480
- min-width: 0;
481
- display: flex;
482
- flex-direction: column;
483
- gap: 14px;
484
- }
485
- .setup-pane h2 {
486
- margin: 0;
487
- font-size: 18px;
488
- font-weight: 650;
489
- }
490
- .pane-copy,
491
- .locked-note {
492
- margin: 0;
493
- color: var(--muted);
494
- font-size: 14px;
495
- }
496
- .locked-note { color: var(--warn); }
497
-
498
- /* Issue #646: paste-your-key step (no-terminal macOS installer path). */
499
- .key-input {
500
- width: 100%;
501
- margin: 10px 0 4px;
502
- padding: 10px 12px;
503
- font-family: ui-monospace, 'SFMono-Regular', Menlo, monospace;
504
- font-size: 14px;
505
- border: 1px solid var(--border, #2c3343);
506
- border-radius: 8px;
507
- background: var(--panel, #12151c);
508
- color: var(--text, #e6e9ef);
509
- }
510
- .key-input:focus-visible { outline: 2px solid var(--accent-strong, #6366f1); outline-offset: 1px; }
511
- .row-list {
512
- list-style: none;
513
- margin: 0;
514
- padding: 0;
515
- border: 1px solid var(--line);
516
- border-radius: 10px;
517
- overflow: hidden;
518
- }
519
- .row-list .row {
520
- display: flex;
521
- gap: 10px;
522
- align-items: center;
523
- padding: 12px;
524
- border-bottom: 1px solid var(--line);
525
- }
526
- .row-list .row:last-child { border-bottom: 0; }
527
- .agent-grid,
528
- .choice-grid {
529
- display: grid;
530
- grid-template-columns: repeat(2, minmax(0, 1fr));
531
- gap: 12px;
532
- }
533
-
534
- .agent-section-heading {
535
- margin: 8px 0 -6px;
536
- font-size: 13px;
537
- font-weight: 700;
538
- color: var(--text);
539
- }
540
-
541
- .agent-list {
542
- list-style: none;
543
- margin: 0;
544
- padding: 0;
545
- border: 1px solid var(--line);
546
- border-radius: 10px;
547
- overflow: hidden;
548
- }
549
-
550
- .agent-row {
551
- display: flex;
552
- align-items: center;
553
- justify-content: space-between;
554
- padding: 12px 16px;
555
- border-bottom: 1px solid var(--line);
556
- background: var(--surface);
557
- gap: 12px;
558
- }
559
-
560
- .agent-row:last-child { border-bottom: 0; }
561
- .agent-row--detected { background: var(--accent-soft); }
562
-
563
- .agent-row__name {
564
- min-width: 0;
565
- flex: 1;
566
- font-size: 14px;
567
- font-weight: 500;
568
- color: var(--text);
569
- }
570
-
571
- .agent-row--detected .agent-row__name { color: var(--accent-strong); }
572
-
573
- .agent-row__action {
574
- flex: 0 0 auto;
575
- }
576
-
577
- .agent-row__muted {
578
- font-size: 12px;
579
- color: var(--muted);
580
- }
581
-
582
- .agent-badge {
583
- display: inline-flex;
584
- align-items: center;
585
- min-height: 24px;
586
- padding: 3px 10px;
587
- border-radius: 999px;
588
- font-size: 12px;
589
- font-weight: 700;
590
- }
591
-
592
- .agent-badge--installed {
593
- background: var(--accent);
594
- color: #fff;
595
- }
596
-
597
- .agent-download-link {
598
- font-size: 13px;
599
- font-weight: 600;
600
- color: var(--accent-strong);
601
- text-decoration: none;
602
- }
603
-
604
- .agent-download-link:hover { text-decoration: underline; }
605
-
606
- .ready-strip {
607
- background: var(--accent-soft);
608
- border: 1px solid var(--accent);
609
- color: var(--accent-strong);
610
- border-radius: 8px;
611
- padding: 10px 12px;
612
- font-size: 13px;
613
- font-weight: 600;
614
- }
615
- .ready-strip--muted {
616
- background: var(--soft);
617
- border-color: var(--line);
618
- color: var(--muted);
619
- }
620
- .ready-strip--error {
621
- background: #fff1f2;
622
- border-color: #fb7185;
623
- color: #9f1239;
624
- }
625
- .btn {
626
- border-radius: 8px;
627
- padding: 9px 14px;
628
- font: inherit;
629
- font-weight: 600;
630
- cursor: pointer;
631
- border: 1px solid var(--line);
632
- align-self: flex-start;
633
- }
634
- .btn:disabled {
635
- opacity: 0.55;
636
- cursor: not-allowed;
637
- }
638
- .btn-primary {
639
- background: var(--accent);
640
- border-color: var(--accent);
641
- color: #fff;
642
- }
643
- .btn-primary:hover { background: var(--accent-strong); }
644
- .btn-secondary {
645
- background: var(--surface);
646
- color: var(--accent-strong);
647
- }
648
- .btn-secondary:hover {
649
- border-color: var(--accent);
650
- background: var(--soft);
651
- }
652
- .btn-ghost {
653
- background: transparent;
654
- color: var(--muted);
655
- }
656
- .modal-backdrop {
657
- position: fixed;
658
- inset: 0;
659
- z-index: 1000;
660
- display: flex;
661
- align-items: center;
662
- justify-content: center;
663
- padding: 18px;
664
- background: rgba(31, 42, 36, 0.36);
665
- }
666
- .modal {
667
- width: min(520px, 100%);
668
- background: var(--surface);
669
- border: 1px solid var(--line);
670
- border-radius: 12px;
671
- box-shadow: var(--shadow-lg);
672
- padding: 22px;
673
- display: flex;
674
- flex-direction: column;
675
- gap: 14px;
676
- }
677
- .modal h2 {
678
- margin: 0;
679
- font-size: 19px;
680
- }
681
- .install-status {
682
- margin: 0;
683
- border: 1px solid var(--line);
684
- background: var(--soft);
685
- border-radius: 8px;
686
- padding: 10px 12px;
687
- color: var(--muted);
688
- }
689
- .install-status[data-tone="error"] {
690
- color: var(--danger);
691
- background: #fbf1f1;
692
- border-color: var(--danger);
693
- }
694
- .modal-help {
695
- margin: -4px 0 0;
696
- color: var(--muted);
697
- font-size: 13px;
698
- line-height: 1.45;
699
- }
700
- .install-actions {
701
- display: flex;
702
- flex-wrap: wrap;
703
- gap: 8px;
704
- }
705
-
706
- .recruit-container,
707
- .start-container {
708
- gap: 12px;
709
- }
710
-
711
- .start-container {
712
- gap: 14px;
713
- }
714
-
715
- .user-type-card {
716
- background: var(--surface);
717
- border: 1.5px solid var(--line);
718
- border-radius: 12px;
719
- padding: 20px;
720
- display: flex;
721
- flex-direction: column;
722
- gap: 16px;
723
- transition: box-shadow 0.15s ease, border-color 0.15s ease;
724
- }
725
- .user-type-card:hover {
726
- box-shadow: 0 4px 16px rgba(20, 40, 30, 0.10);
727
- border-color: var(--accent);
728
- }
729
- .user-type-card--featured {
730
- border-color: var(--accent);
731
- background: var(--accent-soft);
732
- }
733
- .user-type-card--featured:hover {
734
- box-shadow: 0 4px 20px rgba(61, 138, 110, 0.18);
735
- }
736
-
737
- .user-type-card--ide-default {
738
- padding: 24px;
739
- gap: 18px;
740
- }
741
-
742
- .user-type-card--compact {
743
- padding: 16px 18px;
744
- gap: 12px;
745
- }
746
-
747
- .user-type-card--alpha {
748
- background: linear-gradient(180deg, #fbfcfa 0%, #f4f7f2 100%);
749
- }
750
-
751
- .card-header {
752
- display: flex;
753
- gap: 14px;
754
- align-items: flex-start;
755
- }
756
- .card-icon {
757
- width: 38px;
758
- height: 38px;
759
- flex-shrink: 0;
760
- display: flex;
761
- align-items: center;
762
- justify-content: center;
763
- background: var(--soft);
764
- border: 1px solid var(--line);
765
- border-radius: 9px;
766
- font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
767
- font-size: 10px;
768
- font-weight: 700;
769
- color: var(--accent-strong);
770
- letter-spacing: -0.5px;
771
- }
772
- .user-type-card--featured .card-icon {
773
- background: #fff;
774
- border-color: var(--accent);
775
- }
776
-
777
- .card-title {
778
- display: block;
779
- font-size: 15px;
780
- font-weight: 600;
781
- color: var(--text);
782
- margin-bottom: 3px;
783
- }
784
- .card-desc { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.45; }
785
-
786
- .card-eyebrow {
787
- display: inline-flex;
788
- align-self: flex-start;
789
- padding: 4px 10px;
790
- border-radius: 999px;
791
- background: var(--accent-soft);
792
- color: var(--accent-strong);
793
- font-size: 11px;
794
- font-weight: 700;
795
- letter-spacing: 0.06em;
796
- text-transform: uppercase;
797
- }
798
-
799
- .route-note {
800
- margin: 0;
801
- color: var(--muted);
802
- font-size: 13px;
803
- line-height: 1.5;
804
- }
805
-
806
- .route-note--compact {
807
- font-size: 12px;
808
- }
809
-
810
- .btn {
811
- display: inline-flex;
812
- align-items: center;
813
- justify-content: center;
814
- border-radius: 8px;
815
- padding: 10px 18px;
816
- font: inherit;
817
- font-weight: 600;
818
- font-size: 14px;
819
- cursor: pointer;
820
- transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;
821
- align-self: flex-start;
822
- }
823
- .btn-block { align-self: stretch; width: 100%; }
824
- .btn-primary {
825
- background: var(--accent);
826
- color: #fff;
827
- border: 1.5px solid var(--accent);
828
- }
829
- .btn-primary:hover {
830
- background: var(--accent-strong);
831
- border-color: var(--accent-strong);
832
- box-shadow: 0 2px 8px rgba(61, 138, 110, 0.25);
833
- }
834
- .btn-primary:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
835
- .btn-primary:disabled { background: #c5d2cb; border-color: #c5d2cb; cursor: not-allowed; box-shadow: none; }
836
- .btn-secondary {
837
- background: var(--surface);
838
- color: var(--accent-strong);
839
- border: 1.5px solid var(--line);
840
- }
841
- .btn-secondary:hover {
842
- border-color: var(--accent);
843
- background: var(--accent-soft);
844
- box-shadow: 0 2px 8px rgba(61, 138, 110, 0.10);
845
- }
846
- .btn-secondary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
847
-
848
- /* Recruit cards are informational — no pointer/hover highlight. */
849
- .recruit-card {
850
- cursor: default;
851
- }
852
-
853
- .byoa-card {
854
- grid-column: 1 / -1;
855
- }
856
-
857
- .byoa-card .cmd-block {
858
- align-self: flex-start;
859
- display: inline-block;
860
- white-space: nowrap;
861
- word-break: normal;
862
- }
863
- .recruit-card:hover {
864
- box-shadow: none;
865
- border-color: var(--line);
866
- }
867
-
868
- /* IDE command display — shown after choosing "In my IDE". */
869
- .cmd-block {
870
- background: #0d1410;
871
- color: #c8d3cd;
872
- font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
873
- font-size: 14px;
874
- padding: 12px 16px;
875
- border-radius: 8px;
876
- word-break: break-all;
877
- }
878
-
879
- .command-row {
880
- display: flex;
881
- gap: 8px;
882
- align-items: center;
883
- margin-bottom: 8px;
884
- }
885
- .command-row .cmd-block { flex: 1; }
886
- .command-row .btn {
887
- flex-shrink: 0;
888
- font-size: 12px;
889
- padding: 6px 10px;
890
- }
891
- .text-button {
892
- align-self: flex-start;
893
- border: 0;
894
- background: transparent;
895
- color: var(--accent-strong);
896
- padding: 6px 0;
897
- font: inherit;
898
- font-size: 13px;
899
- cursor: pointer;
900
- text-decoration: underline;
901
- }
902
-
903
- /* Below ~600px the row's flex layout starts compressing the verb text and
904
- * clipping the project-picker. First-run is desktop-by-spec but we still
905
- * want the surface to degrade gracefully for users who happen to open it
906
- * in a narrow window. Stack the label / verb / change link vertically and
907
- * let the row breathe. */
908
- @media (max-width: 600px) {
909
- .page { padding: 24px 16px 24px; }
910
- .setup-shell { grid-template-columns: 1fr; }
911
- .setup-steps {
912
- border-right: 0;
913
- border-bottom: 1px solid var(--line);
914
- padding-right: 0;
915
- padding-bottom: 12px;
916
- }
917
- .agent-grid,
918
- .choice-grid { grid-template-columns: 1fr; }
919
- .checklist .row { gap: 8px; padding: 12px 14px; }
920
- .row .label { min-width: 0; }
921
- .row .verb { flex: 1 1 100%; }
922
- .row .change-link { margin-left: auto; }
923
- .row .project-picker { gap: 8px; }
924
- .row .project-picker input { width: 100%; min-width: 0; }
925
- .user-type-card--ide-default,
926
- .user-type-card--compact {
927
- padding: 18px 16px;
928
- }
929
- }
1
+ /*
2
+ * FRAIM first-run — Setup checklist surface.
3
+ *
4
+ * The :root variable set below is a STRICT SUBSET of public/ai-hub/styles.css
5
+ * — see R5.1 acceptance and tests/test-installer-service.ts'
6
+ * `testBootstrapCssVarsAreSubsetOfHub`. Adding a token here that does not
7
+ * exist on the Hub side fails CI.
8
+ */
9
+ :root {
10
+ --bg: #f4f6f2;
11
+ --surface: #ffffff;
12
+ --soft: #f7faf6;
13
+ --line: #e3e8df;
14
+ --text: #1f2a24;
15
+ --muted: #627168;
16
+ --accent: #2f7359;
17
+ --accent-strong: #245c46;
18
+ --accent-soft: #eaf3ee;
19
+ --warn: #b08442;
20
+ --warn-soft: #fffaf0;
21
+ --danger: #a24747;
22
+ --shadow: 0 1px 2px rgba(20, 40, 30, 0.04);
23
+ --shadow-lg: 0 12px 36px rgba(20, 40, 30, 0.18);
24
+ }
25
+
26
+ * { box-sizing: border-box; }
27
+ html, body { margin: 0; padding: 0; }
28
+ body {
29
+ font-family: -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
30
+ color: var(--text);
31
+ background: var(--bg);
32
+ line-height: 1.5;
33
+ font-size: 15px;
34
+ }
35
+
36
+ .page {
37
+ max-width: 720px;
38
+ margin: 0 auto;
39
+ padding: 48px 24px 32px;
40
+ }
41
+
42
+ .page-header h1 {
43
+ margin: 0 0 8px;
44
+ font-size: 26px;
45
+ font-weight: 600;
46
+ }
47
+ .page-header .lede {
48
+ margin: 0 0 24px;
49
+ color: var(--muted);
50
+ font-size: 16px;
51
+ line-height: 1.5;
52
+ }
53
+
54
+ .card {
55
+ background: var(--surface);
56
+ border: 1px solid var(--line);
57
+ border-radius: 14px;
58
+ box-shadow: var(--shadow);
59
+ padding: 24px;
60
+ }
61
+
62
+ .checklist {
63
+ list-style: none;
64
+ margin: 0;
65
+ padding: 0;
66
+ display: flex;
67
+ flex-direction: column;
68
+ border: 1px solid var(--line);
69
+ border-radius: 12px;
70
+ overflow: hidden;
71
+ }
72
+
73
+ .checklist .row {
74
+ display: flex;
75
+ flex-wrap: wrap;
76
+ align-items: center;
77
+ gap: 12px;
78
+ padding: 14px 16px;
79
+ border-bottom: 1px solid var(--line);
80
+ background: var(--surface);
81
+ }
82
+ .checklist .row:last-child { border-bottom: 0; }
83
+
84
+ .row .icon {
85
+ width: 22px;
86
+ height: 22px;
87
+ border-radius: 50%;
88
+ display: inline-flex;
89
+ align-items: center;
90
+ justify-content: center;
91
+ font-size: 13px;
92
+ font-weight: 700;
93
+ flex-shrink: 0;
94
+ }
95
+ .row[data-row-status="ok"] .icon { background: var(--accent); color: #fff; }
96
+ .row[data-row-status="pending"] .icon { background: var(--line); color: var(--muted); }
97
+ .row[data-row-status="in-progress"] .icon { background: var(--accent-soft); color: var(--accent-strong); }
98
+ .row[data-row-status="manual-required"] .icon { background: var(--warn-soft); color: var(--warn); border: 1px solid var(--warn); }
99
+ .row[data-row-status="error"] .icon { background: #fbf1f1; color: var(--danger); border: 1px solid var(--danger); }
100
+
101
+ .row .label { font-weight: 600; min-width: 124px; }
102
+ .row .verb { color: var(--muted); font-size: 14px; flex: 1; }
103
+ .row[data-row-status="ok"] .verb { color: var(--accent-strong); }
104
+ .row[data-row-status="error"] .verb { color: var(--danger); }
105
+ .row[data-row-status="manual-required"] .verb { color: var(--warn); }
106
+
107
+ .row .detail {
108
+ color: var(--muted);
109
+ font-size: 13px;
110
+ flex-basis: 100%;
111
+ padding-left: 34px;
112
+ }
113
+
114
+ .setup-result {
115
+ display: flex;
116
+ flex-direction: column;
117
+ gap: 8px;
118
+ padding: 16px;
119
+ border-top: 1px solid var(--line);
120
+ background: var(--soft);
121
+ }
122
+ .setup-result strong {
123
+ font-size: 15px;
124
+ font-weight: 600;
125
+ }
126
+ .setup-result p {
127
+ margin: 0;
128
+ color: var(--muted);
129
+ font-size: 14px;
130
+ }
131
+ .surface-list {
132
+ margin: 0;
133
+ padding-left: 18px;
134
+ color: var(--muted);
135
+ font-size: 14px;
136
+ }
137
+
138
+ .row .change-link {
139
+ font-size: 13px;
140
+ color: var(--accent-strong);
141
+ text-decoration: none;
142
+ cursor: pointer;
143
+ border: 0;
144
+ background: transparent;
145
+ padding: 4px 6px;
146
+ }
147
+ .row .change-link:hover { text-decoration: underline; }
148
+ .row .change-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
149
+
150
+ .row .row-stream {
151
+ flex-basis: 100%;
152
+ margin: 8px 0 0;
153
+ background: #0d1410;
154
+ color: #c8d3cd;
155
+ font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
156
+ font-size: 12px;
157
+ padding: 10px 12px;
158
+ border-radius: 8px;
159
+ max-height: 80px;
160
+ overflow: auto;
161
+ white-space: pre;
162
+ }
163
+ .row .manual-message {
164
+ flex-basis: 100%;
165
+ margin: 8px 0 0;
166
+ background: var(--warn-soft);
167
+ border: 1px solid var(--warn);
168
+ color: var(--text);
169
+ border-radius: 8px;
170
+ padding: 10px 12px;
171
+ font-size: 13px;
172
+ }
173
+ .row .manual-message code {
174
+ background: var(--surface);
175
+ padding: 2px 4px;
176
+ border-radius: 4px;
177
+ }
178
+
179
+ /* Inline agent picker. No popups; no separate page. */
180
+ .agent-picker {
181
+ flex-basis: 100%;
182
+ margin-top: 10px;
183
+ background: var(--soft);
184
+ border: 1px solid var(--line);
185
+ border-radius: 10px;
186
+ padding: 12px;
187
+ display: flex;
188
+ flex-direction: column;
189
+ gap: 10px;
190
+ }
191
+ .agent-picker[hidden] { display: none; }
192
+ .agent-picker .options { display: flex; gap: 8px; flex-wrap: wrap; }
193
+ .agent-picker .option {
194
+ background: var(--surface);
195
+ border: 1px solid var(--line);
196
+ border-radius: 8px;
197
+ padding: 8px 12px;
198
+ cursor: pointer;
199
+ font-size: 14px;
200
+ }
201
+ .agent-picker .option:hover { background: var(--soft); border-color: var(--accent); }
202
+ .agent-picker .option:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
203
+ .agent-picker .option[aria-pressed="true"] {
204
+ border-color: var(--accent);
205
+ background: var(--accent-soft);
206
+ color: var(--accent-strong);
207
+ font-weight: 600;
208
+ }
209
+ .agent-picker details { margin-top: 4px; }
210
+ .agent-picker summary {
211
+ cursor: pointer;
212
+ color: var(--muted);
213
+ font-size: 13px;
214
+ }
215
+ .agent-picker .custom-warning {
216
+ background: var(--warn-soft);
217
+ border: 1px solid var(--warn);
218
+ color: var(--text);
219
+ border-radius: 8px;
220
+ padding: 10px 12px;
221
+ font-size: 13px;
222
+ margin-top: 8px;
223
+ }
224
+ .agent-picker .custom-form {
225
+ display: grid;
226
+ grid-template-columns: 1fr 1fr auto;
227
+ gap: 8px;
228
+ margin-top: 8px;
229
+ }
230
+ .agent-picker .custom-form input {
231
+ border: 1px solid var(--line);
232
+ border-radius: 8px;
233
+ padding: 8px 10px;
234
+ font: inherit;
235
+ }
236
+ .agent-picker .custom-form button {
237
+ background: var(--accent);
238
+ color: #fff;
239
+ border: 0;
240
+ border-radius: 8px;
241
+ padding: 8px 14px;
242
+ cursor: pointer;
243
+ font: inherit;
244
+ }
245
+
246
+ /* Project row picker affordances */
247
+ .row .project-picker {
248
+ display: flex;
249
+ gap: 8px;
250
+ align-items: center;
251
+ flex-basis: 100%;
252
+ margin-top: 8px;
253
+ }
254
+ .row .project-picker input {
255
+ flex: 1;
256
+ border: 1px solid var(--line);
257
+ border-radius: 8px;
258
+ padding: 8px 12px;
259
+ font: inherit;
260
+ }
261
+ .row .project-picker .browse {
262
+ background: var(--surface);
263
+ border: 1px solid var(--line);
264
+ border-radius: 8px;
265
+ padding: 8px 12px;
266
+ cursor: pointer;
267
+ font: inherit;
268
+ }
269
+ .row .project-picker .browse:hover { background: var(--soft); border-color: var(--accent); }
270
+
271
+ /* Preflight summary — shown above the Continue button on the project row.
272
+ Tells the user exactly which side effects FRAIM will perform when they
273
+ click Continue. The "no surprises" half of the non-tech-user invariant. */
274
+ .row .preflight-summary {
275
+ flex-basis: 100%;
276
+ margin-top: 12px;
277
+ padding: 12px 14px;
278
+ border: 1px solid var(--line);
279
+ background: var(--soft);
280
+ border-radius: 8px;
281
+ font-size: 13px;
282
+ color: var(--muted);
283
+ }
284
+ .row .preflight-heading {
285
+ color: var(--text);
286
+ font-weight: 600;
287
+ margin-bottom: 6px;
288
+ }
289
+ .row .preflight-list {
290
+ margin: 0;
291
+ padding-left: 18px;
292
+ }
293
+ .row .preflight-list li { margin: 2px 0; }
294
+
295
+ .actions {
296
+ display: flex;
297
+ justify-content: flex-end;
298
+ gap: 8px;
299
+ margin-top: 20px;
300
+ }
301
+
302
+ /* Primary button — same geometry as Hub's send-button (R5.2). */
303
+ .primary-button {
304
+ background: var(--accent);
305
+ color: #fff;
306
+ border: 0;
307
+ border-radius: 10px;
308
+ padding: 10px 18px;
309
+ font: inherit;
310
+ font-weight: 600;
311
+ cursor: pointer;
312
+ }
313
+ .primary-button:hover { background: var(--accent-strong); }
314
+ .primary-button:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
315
+ .primary-button:disabled { background: #c5d2cb; cursor: not-allowed; }
316
+
317
+ .status {
318
+ margin: 16px 0 0;
319
+ padding: 12px 14px;
320
+ border-radius: 10px;
321
+ background: var(--soft);
322
+ border: 1px solid var(--line);
323
+ color: var(--muted);
324
+ font-size: 14px;
325
+ min-height: 1em;
326
+ }
327
+ .status:empty { display: none; }
328
+ .status[data-tone="error"] {
329
+ background: #fbf1f1;
330
+ border-color: var(--danger);
331
+ color: var(--danger);
332
+ }
333
+
334
+ /* Error frame — R6.1 single visual contract. */
335
+ .error-frame {
336
+ flex-basis: 100%;
337
+ margin-top: 10px;
338
+ background: #fbf1f1;
339
+ border: 1px solid var(--danger);
340
+ border-radius: 10px;
341
+ padding: 12px 14px;
342
+ display: flex;
343
+ flex-direction: column;
344
+ gap: 8px;
345
+ }
346
+ .error-frame .what-tried {
347
+ color: var(--danger);
348
+ font-weight: 600;
349
+ }
350
+ .error-frame .error-hint {
351
+ color: var(--text);
352
+ font-size: 14px;
353
+ line-height: 1.45;
354
+ background: var(--warn-soft);
355
+ border: 1px solid #f0d8b3;
356
+ border-radius: 8px;
357
+ padding: 10px 12px;
358
+ }
359
+ .error-frame .what-happened {
360
+ background: #0d1410;
361
+ color: #f1c0c0;
362
+ font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
363
+ font-size: 12px;
364
+ padding: 10px 12px;
365
+ border-radius: 8px;
366
+ max-height: 88px;
367
+ overflow: auto;
368
+ white-space: pre;
369
+ margin: 0;
370
+ }
371
+ .error-frame .show-full {
372
+ align-self: flex-start;
373
+ font-size: 12px;
374
+ color: var(--muted);
375
+ cursor: pointer;
376
+ background: 0;
377
+ border: 0;
378
+ padding: 0;
379
+ text-decoration: underline;
380
+ }
381
+ .error-frame .actions {
382
+ display: flex;
383
+ gap: 8px;
384
+ margin-top: 4px;
385
+ justify-content: flex-start;
386
+ }
387
+ .error-frame .action {
388
+ border-radius: 8px;
389
+ padding: 8px 14px;
390
+ cursor: pointer;
391
+ font: inherit;
392
+ font-weight: 500;
393
+ border: 1px solid var(--line);
394
+ background: var(--surface);
395
+ color: var(--text);
396
+ }
397
+ .error-frame .action[data-variant="primary"] {
398
+ background: var(--accent);
399
+ color: #fff;
400
+ border-color: var(--accent);
401
+ }
402
+ .error-frame .action[data-variant="primary"]:hover { background: var(--accent-strong); }
403
+ .error-frame .action[data-variant="secondary"]:hover {
404
+ border-color: var(--accent);
405
+ color: var(--accent-strong);
406
+ }
407
+ .error-frame .action[data-variant="ghost"] {
408
+ background: transparent;
409
+ border-color: transparent;
410
+ color: var(--accent-strong);
411
+ }
412
+
413
+ /* User-type selection screen — shown after all 4 setup rows complete.
414
+ .checklist switches to .selection-container so card borders don't
415
+ nest inside the outer bordered list container. */
416
+ .selection-container {
417
+ list-style: none;
418
+ margin: 0;
419
+ padding: 0;
420
+ display: flex;
421
+ flex-direction: column;
422
+ }
423
+
424
+ .setup-shell {
425
+ list-style: none;
426
+ margin: 0;
427
+ padding: 0;
428
+ display: grid;
429
+ grid-template-columns: minmax(190px, 0.85fr) minmax(0, 2fr);
430
+ gap: 20px;
431
+ }
432
+ .setup-steps {
433
+ display: flex;
434
+ flex-direction: column;
435
+ gap: 8px;
436
+ border-right: 1px solid var(--line);
437
+ padding-right: 16px;
438
+ }
439
+ .setup-step {
440
+ width: 100%;
441
+ min-height: 44px;
442
+ display: flex;
443
+ align-items: center;
444
+ gap: 10px;
445
+ border: 1px solid var(--line);
446
+ border-radius: 8px;
447
+ background: var(--surface);
448
+ color: var(--text);
449
+ padding: 9px 10px;
450
+ font: inherit;
451
+ font-weight: 600;
452
+ text-align: left;
453
+ cursor: pointer;
454
+ }
455
+ .setup-step[aria-current="step"] {
456
+ border-color: var(--accent);
457
+ background: var(--accent-soft);
458
+ }
459
+ .setup-step:disabled {
460
+ opacity: 0.55;
461
+ cursor: not-allowed;
462
+ }
463
+ .step-dot {
464
+ width: 24px;
465
+ height: 24px;
466
+ border-radius: 50%;
467
+ display: inline-flex;
468
+ align-items: center;
469
+ justify-content: center;
470
+ background: var(--line);
471
+ color: var(--muted);
472
+ font-size: 12px;
473
+ flex: 0 0 auto;
474
+ }
475
+ .setup-step[data-status="done"] .step-dot {
476
+ background: var(--accent);
477
+ color: #fff;
478
+ }
479
+ .setup-pane {
480
+ min-width: 0;
481
+ display: flex;
482
+ flex-direction: column;
483
+ gap: 14px;
484
+ }
485
+ .setup-pane h2 {
486
+ margin: 0;
487
+ font-size: 18px;
488
+ font-weight: 650;
489
+ }
490
+ .pane-copy,
491
+ .locked-note {
492
+ margin: 0;
493
+ color: var(--muted);
494
+ font-size: 14px;
495
+ }
496
+ .locked-note { color: var(--warn); }
497
+
498
+ /* Issue #646: paste-your-key step (no-terminal macOS installer path). */
499
+ .key-input {
500
+ width: 100%;
501
+ margin: 10px 0 4px;
502
+ padding: 10px 12px;
503
+ font-family: ui-monospace, 'SFMono-Regular', Menlo, monospace;
504
+ font-size: 14px;
505
+ border: 1px solid var(--border, #2c3343);
506
+ border-radius: 8px;
507
+ background: var(--panel, #12151c);
508
+ color: #e6e9ef;
509
+ }
510
+ .key-input:focus-visible { outline: 2px solid var(--accent-strong, #6366f1); outline-offset: 1px; }
511
+ .row-list {
512
+ list-style: none;
513
+ margin: 0;
514
+ padding: 0;
515
+ border: 1px solid var(--line);
516
+ border-radius: 10px;
517
+ overflow: hidden;
518
+ }
519
+ .row-list .row {
520
+ display: flex;
521
+ gap: 10px;
522
+ align-items: center;
523
+ padding: 12px;
524
+ border-bottom: 1px solid var(--line);
525
+ }
526
+ .row-list .row:last-child { border-bottom: 0; }
527
+ .agent-grid,
528
+ .choice-grid {
529
+ display: grid;
530
+ grid-template-columns: repeat(2, minmax(0, 1fr));
531
+ gap: 12px;
532
+ }
533
+
534
+ .agent-section-heading {
535
+ margin: 8px 0 -6px;
536
+ font-size: 13px;
537
+ font-weight: 700;
538
+ color: var(--text);
539
+ }
540
+
541
+ .agent-list {
542
+ list-style: none;
543
+ margin: 0;
544
+ padding: 0;
545
+ border: 1px solid var(--line);
546
+ border-radius: 10px;
547
+ overflow: hidden;
548
+ }
549
+
550
+ .agent-row {
551
+ display: flex;
552
+ align-items: center;
553
+ justify-content: space-between;
554
+ padding: 12px 16px;
555
+ border-bottom: 1px solid var(--line);
556
+ background: var(--surface);
557
+ gap: 12px;
558
+ }
559
+
560
+ .agent-row:last-child { border-bottom: 0; }
561
+ .agent-row--detected { background: var(--accent-soft); }
562
+
563
+ .agent-row__name {
564
+ min-width: 0;
565
+ flex: 1;
566
+ font-size: 14px;
567
+ font-weight: 500;
568
+ color: var(--text);
569
+ }
570
+
571
+ .agent-row--detected .agent-row__name { color: var(--accent-strong); }
572
+
573
+ .agent-row__action {
574
+ flex: 0 0 auto;
575
+ }
576
+
577
+ .agent-row__muted {
578
+ font-size: 12px;
579
+ color: var(--muted);
580
+ }
581
+
582
+ .agent-badge {
583
+ display: inline-flex;
584
+ align-items: center;
585
+ min-height: 24px;
586
+ padding: 3px 10px;
587
+ border-radius: 999px;
588
+ font-size: 12px;
589
+ font-weight: 700;
590
+ }
591
+
592
+ .agent-badge--installed {
593
+ background: var(--accent);
594
+ color: #fff;
595
+ }
596
+
597
+ .agent-download-link {
598
+ font-size: 13px;
599
+ font-weight: 600;
600
+ color: var(--accent-strong);
601
+ text-decoration: none;
602
+ }
603
+
604
+ .agent-download-link:hover { text-decoration: underline; }
605
+
606
+ .ready-strip {
607
+ background: var(--accent-soft);
608
+ border: 1px solid var(--accent);
609
+ color: var(--accent-strong);
610
+ border-radius: 8px;
611
+ padding: 10px 12px;
612
+ font-size: 13px;
613
+ font-weight: 600;
614
+ }
615
+ .ready-strip--muted {
616
+ background: var(--soft);
617
+ border-color: var(--line);
618
+ color: var(--muted);
619
+ }
620
+ .ready-strip--error {
621
+ background: #fff1f2;
622
+ border-color: #fb7185;
623
+ color: #9f1239;
624
+ }
625
+ .btn {
626
+ border-radius: 8px;
627
+ padding: 9px 14px;
628
+ font: inherit;
629
+ font-weight: 600;
630
+ cursor: pointer;
631
+ border: 1px solid var(--line);
632
+ align-self: flex-start;
633
+ }
634
+ .btn:disabled {
635
+ opacity: 0.55;
636
+ cursor: not-allowed;
637
+ }
638
+ .btn-primary {
639
+ background: var(--accent);
640
+ border-color: var(--accent);
641
+ color: #fff;
642
+ }
643
+ .btn-primary:hover { background: var(--accent-strong); }
644
+ .btn-secondary {
645
+ background: var(--surface);
646
+ color: var(--accent-strong);
647
+ }
648
+ .btn-secondary:hover {
649
+ border-color: var(--accent);
650
+ background: var(--soft);
651
+ }
652
+ .btn-ghost {
653
+ background: transparent;
654
+ color: var(--muted);
655
+ }
656
+ .modal-backdrop {
657
+ position: fixed;
658
+ inset: 0;
659
+ z-index: 1000;
660
+ display: flex;
661
+ align-items: center;
662
+ justify-content: center;
663
+ padding: 18px;
664
+ background: rgba(31, 42, 36, 0.36);
665
+ }
666
+ .modal {
667
+ width: min(520px, 100%);
668
+ background: var(--surface);
669
+ border: 1px solid var(--line);
670
+ border-radius: 12px;
671
+ box-shadow: var(--shadow-lg);
672
+ padding: 22px;
673
+ display: flex;
674
+ flex-direction: column;
675
+ gap: 14px;
676
+ }
677
+ .modal h2 {
678
+ margin: 0;
679
+ font-size: 19px;
680
+ }
681
+ .install-status {
682
+ margin: 0;
683
+ border: 1px solid var(--line);
684
+ background: var(--soft);
685
+ border-radius: 8px;
686
+ padding: 10px 12px;
687
+ color: var(--muted);
688
+ }
689
+ .install-status[data-tone="error"] {
690
+ color: var(--danger);
691
+ background: #fbf1f1;
692
+ border-color: var(--danger);
693
+ }
694
+ .modal-help {
695
+ margin: -4px 0 0;
696
+ color: var(--muted);
697
+ font-size: 13px;
698
+ line-height: 1.45;
699
+ }
700
+ .install-actions {
701
+ display: flex;
702
+ flex-wrap: wrap;
703
+ gap: 8px;
704
+ }
705
+
706
+ .recruit-container,
707
+ .start-container {
708
+ gap: 12px;
709
+ }
710
+
711
+ .start-container {
712
+ gap: 14px;
713
+ }
714
+
715
+ .user-type-card {
716
+ background: var(--surface);
717
+ border: 1.5px solid var(--line);
718
+ border-radius: 12px;
719
+ padding: 20px;
720
+ display: flex;
721
+ flex-direction: column;
722
+ gap: 16px;
723
+ transition: box-shadow 0.15s ease, border-color 0.15s ease;
724
+ }
725
+ .user-type-card:hover {
726
+ box-shadow: 0 4px 16px rgba(20, 40, 30, 0.10);
727
+ border-color: var(--accent);
728
+ }
729
+ .user-type-card--featured {
730
+ border-color: var(--accent);
731
+ background: var(--accent-soft);
732
+ }
733
+ .user-type-card--featured:hover {
734
+ box-shadow: 0 4px 20px rgba(61, 138, 110, 0.18);
735
+ }
736
+
737
+ .user-type-card--ide-default {
738
+ padding: 24px;
739
+ gap: 18px;
740
+ }
741
+
742
+ .user-type-card--compact {
743
+ padding: 16px 18px;
744
+ gap: 12px;
745
+ }
746
+
747
+ .user-type-card--alpha {
748
+ background: linear-gradient(180deg, #fbfcfa 0%, #f4f7f2 100%);
749
+ }
750
+
751
+ .card-header {
752
+ display: flex;
753
+ gap: 14px;
754
+ align-items: flex-start;
755
+ }
756
+ .card-icon {
757
+ width: 38px;
758
+ height: 38px;
759
+ flex-shrink: 0;
760
+ display: flex;
761
+ align-items: center;
762
+ justify-content: center;
763
+ background: var(--soft);
764
+ border: 1px solid var(--line);
765
+ border-radius: 9px;
766
+ font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
767
+ font-size: 10px;
768
+ font-weight: 700;
769
+ color: var(--accent-strong);
770
+ letter-spacing: -0.5px;
771
+ }
772
+ .user-type-card--featured .card-icon {
773
+ background: #fff;
774
+ border-color: var(--accent);
775
+ }
776
+
777
+ .card-title {
778
+ display: block;
779
+ font-size: 15px;
780
+ font-weight: 600;
781
+ color: var(--text);
782
+ margin-bottom: 3px;
783
+ }
784
+ .card-desc { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.45; }
785
+
786
+ .card-eyebrow {
787
+ display: inline-flex;
788
+ align-self: flex-start;
789
+ padding: 4px 10px;
790
+ border-radius: 999px;
791
+ background: var(--accent-soft);
792
+ color: var(--accent-strong);
793
+ font-size: 11px;
794
+ font-weight: 700;
795
+ letter-spacing: 0.06em;
796
+ text-transform: uppercase;
797
+ }
798
+
799
+ .route-note {
800
+ margin: 0;
801
+ color: var(--muted);
802
+ font-size: 13px;
803
+ line-height: 1.5;
804
+ }
805
+
806
+ .route-note--compact {
807
+ font-size: 12px;
808
+ }
809
+
810
+ .btn {
811
+ display: inline-flex;
812
+ align-items: center;
813
+ justify-content: center;
814
+ border-radius: 8px;
815
+ padding: 10px 18px;
816
+ font: inherit;
817
+ font-weight: 600;
818
+ font-size: 14px;
819
+ cursor: pointer;
820
+ transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;
821
+ align-self: flex-start;
822
+ }
823
+ .btn-block { align-self: stretch; width: 100%; }
824
+ .btn-primary {
825
+ background: var(--accent);
826
+ color: #fff;
827
+ border: 1.5px solid var(--accent);
828
+ }
829
+ .btn-primary:hover {
830
+ background: var(--accent-strong);
831
+ border-color: var(--accent-strong);
832
+ box-shadow: 0 2px 8px rgba(61, 138, 110, 0.25);
833
+ }
834
+ .btn-primary:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
835
+ .btn-primary:disabled { background: #c5d2cb; border-color: #c5d2cb; cursor: not-allowed; box-shadow: none; }
836
+ .btn-secondary {
837
+ background: var(--surface);
838
+ color: var(--accent-strong);
839
+ border: 1.5px solid var(--line);
840
+ }
841
+ .btn-secondary:hover {
842
+ border-color: var(--accent);
843
+ background: var(--accent-soft);
844
+ box-shadow: 0 2px 8px rgba(61, 138, 110, 0.10);
845
+ }
846
+ .btn-secondary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
847
+
848
+ /* Recruit cards are informational — no pointer/hover highlight. */
849
+ .recruit-card {
850
+ cursor: default;
851
+ }
852
+
853
+ .byoa-card {
854
+ grid-column: 1 / -1;
855
+ }
856
+
857
+ .byoa-card .cmd-block {
858
+ align-self: flex-start;
859
+ display: inline-block;
860
+ white-space: nowrap;
861
+ word-break: normal;
862
+ }
863
+ .recruit-card:hover {
864
+ box-shadow: none;
865
+ border-color: var(--line);
866
+ }
867
+
868
+ /* IDE command display — shown after choosing "In my IDE". */
869
+ .cmd-block {
870
+ background: #0d1410;
871
+ color: #c8d3cd;
872
+ font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
873
+ font-size: 14px;
874
+ padding: 12px 16px;
875
+ border-radius: 8px;
876
+ word-break: break-all;
877
+ }
878
+
879
+ .command-row {
880
+ display: flex;
881
+ gap: 8px;
882
+ align-items: center;
883
+ margin-bottom: 8px;
884
+ }
885
+ .command-row .cmd-block { flex: 1; }
886
+ .command-row .btn {
887
+ flex-shrink: 0;
888
+ font-size: 12px;
889
+ padding: 6px 10px;
890
+ }
891
+ .text-button {
892
+ align-self: flex-start;
893
+ border: 0;
894
+ background: transparent;
895
+ color: var(--accent-strong);
896
+ padding: 6px 0;
897
+ font: inherit;
898
+ font-size: 13px;
899
+ cursor: pointer;
900
+ text-decoration: underline;
901
+ }
902
+
903
+ /* Below ~600px the row's flex layout starts compressing the verb text and
904
+ * clipping the project-picker. First-run is desktop-by-spec but we still
905
+ * want the surface to degrade gracefully for users who happen to open it
906
+ * in a narrow window. Stack the label / verb / change link vertically and
907
+ * let the row breathe. */
908
+ @media (max-width: 600px) {
909
+ .page { padding: 24px 16px 24px; }
910
+ .setup-shell { grid-template-columns: 1fr; }
911
+ .setup-steps {
912
+ border-right: 0;
913
+ border-bottom: 1px solid var(--line);
914
+ padding-right: 0;
915
+ padding-bottom: 12px;
916
+ }
917
+ .agent-grid,
918
+ .choice-grid { grid-template-columns: 1fr; }
919
+ .checklist .row { gap: 8px; padding: 12px 14px; }
920
+ .row .label { min-width: 0; }
921
+ .row .verb { flex: 1 1 100%; }
922
+ .row .change-link { margin-left: auto; }
923
+ .row .project-picker { gap: 8px; }
924
+ .row .project-picker input { width: 100%; min-width: 0; }
925
+ .user-type-card--ide-default,
926
+ .user-type-card--compact {
927
+ padding: 18px 16px;
928
+ }
929
+ }