shadok-ai 0.15.35 → 0.15.36

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 (2) hide show
  1. package/package.json +1 -1
  2. package/public/index.html +110 -88
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.15.35",
3
+ "version": "0.15.36",
4
4
  "main": "dist/session.js",
5
5
  "scripts": {
6
6
  "test": "node --import tsx --test --test-timeout=120000 test/*.ts context/*/test/*.test.mjs",
package/public/index.html CHANGED
@@ -14,6 +14,10 @@
14
14
  <link rel="icon" id="favicon" href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20rx%3D%227%22%20fill%3D%22%2314161d%22%2F%3E%3Cline%20x1%3D%2210.8%22%20y1%3D%2223%22%20x2%3D%2210.4%22%20y2%3D%2230.6%22%20stroke%3D%22%23f0a848%22%20stroke-width%3D%221.3%22%20stroke-linecap%3D%22round%22%2F%3E%3Cline%20x1%3D%2216.400000000000002%22%20y1%3D%2223%22%20x2%3D%2216.8%22%20y2%3D%2230.6%22%20stroke%3D%22%23f0a848%22%20stroke-width%3D%221.3%22%20stroke-linecap%3D%22round%22%2F%3E%3Cline%20x1%3D%228.8%22%20y1%3D%2230.7%22%20x2%3D%2211.9%22%20y2%3D%2230.7%22%20stroke%3D%22%23f0a848%22%20stroke-width%3D%221.3%22%20stroke-linecap%3D%22round%22%2F%3E%3Cline%20x1%3D%2215.4%22%20y1%3D%2230.7%22%20x2%3D%2218.5%22%20y2%3D%2230.7%22%20stroke%3D%22%23f0a848%22%20stroke-width%3D%221.3%22%20stroke-linecap%3D%22round%22%2F%3E%3Cline%20x1%3D%2219.6%22%20y1%3D%2217.2%22%20x2%3D%2224.000000000000004%22%20y2%3D%2220.4%22%20stroke%3D%22%23f0a848%22%20stroke-width%3D%221.3%22%20stroke-linecap%3D%22round%22%2F%3E%3Cg%3E%3Cline%20x1%3D%2211.600000000000001%22%20y1%3D%225.399999999999999%22%20x2%3D%229.600000000000001%22%20y2%3D%222.8%22%20stroke%3D%22%23f0a848%22%20stroke-width%3D%220.9%22%20stroke-linecap%3D%22round%22%2F%3E%3Ccircle%20cx%3D%229.600000000000001%22%20cy%3D%222.8%22%20r%3D%221%22%20fill%3D%22%23f0a848%22%2F%3E%3Cline%20x1%3D%2216%22%20y1%3D%225.399999999999999%22%20x2%3D%2218%22%20y2%3D%222.8%22%20stroke%3D%22%23f0a848%22%20stroke-width%3D%220.9%22%20stroke-linecap%3D%22round%22%2F%3E%3Ccircle%20cx%3D%2218%22%20cy%3D%222.8%22%20r%3D%221%22%20fill%3D%22%23f0a848%22%2F%3E%3Ccircle%20cx%3D%2213.8%22%20cy%3D%2216.2%22%20r%3D%228.4%22%20fill%3D%22%23f0a848%22%2F%3E%3Cpath%20d%3D%22M12.200000000000001%2018.2%20L15.4%2018.2%20L13.8%2021.6%20Z%22%20fill%3D%22%23f0a848%22%2F%3E%3Ccircle%20cx%3D%2210.9%22%20cy%3D%227.799999999999999%22%20r%3D%222.6%22%20fill%3D%22%23fff%22%2F%3E%3Ccircle%20cx%3D%2216.7%22%20cy%3D%227.799999999999999%22%20r%3D%222.6%22%20fill%3D%22%23fff%22%2F%3E%3Ccircle%20cx%3D%2211.200000000000001%22%20cy%3D%228.1%22%20r%3D%221.3%22%20fill%3D%22%2314161d%22%2F%3E%3Ccircle%20cx%3D%2217%22%20cy%3D%228.1%22%20r%3D%221.3%22%20fill%3D%22%2314161d%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E">
15
15
  <style>
16
16
  :root {
17
+ /* The page the panels sit on: a shade darker than --bg, so the nav and the
18
+ conversation read as cards (the "sober" pass, 2026-10-28). */
19
+ --page: #0d0f14;
20
+ --radius: 12px;
17
21
  --bg: #14161d;
18
22
  --bg-raised: #1b1e27;
19
23
  --bg-inset: #0e1015;
@@ -32,7 +36,9 @@
32
36
  --menu-bg: #14140f;
33
37
  --menu-hover: #26261c;
34
38
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
35
- --sans: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
39
+ /* One sans for the whole interface; the mono is kept for what IS code —
40
+ code blocks, session ids, the terminal. */
41
+ --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
36
42
  }
37
43
  /* Light mode. An ORTHOGONAL axis to the accent palette: only the base surfaces
38
44
  and text flip; the instance's accent (--amber/--phosphor) stays its identity.
@@ -42,7 +48,8 @@
42
48
  a pale amber on white. Accent-tinted surfaces (--amber-soft) derive from
43
49
  --amber and follow on their own. */
44
50
  :root[data-mode="light"] {
45
- --bg: #eef0f4;
51
+ --page: #eef0f4;
52
+ --bg: #f7f8fa;
46
53
  --bg-raised: #ffffff;
47
54
  --bg-inset: #e5e8ee;
48
55
  --line: #d2d7e0;
@@ -69,10 +76,11 @@
69
76
  html, body { height: 100%; }
70
77
  html { overflow: hidden; }
71
78
  body {
72
- background: var(--bg);
79
+ background: var(--page);
73
80
  color: var(--text);
74
81
  font-family: var(--sans);
75
- font-size: 15px;
82
+ font-size: 14px;
83
+ -webkit-font-smoothing: antialiased;
76
84
  display: flex;
77
85
  flex-direction: column;
78
86
  /* Fixed chassis: the page never scrolls — only the inner panels (channel
@@ -101,17 +109,16 @@
101
109
  reports. Set from `visualViewport` (see `syncViewport`), touch only. */
102
110
  body { height: 100dvh; }
103
111
  body.vv-sized { height: var(--app-h); }
112
+ /* Labels read as quiet sentence-case captions, not stamped capitals. */
104
113
  .label {
105
- font-family: var(--mono);
106
- font-size: 10px;
107
- letter-spacing: 0.18em;
108
- text-transform: uppercase;
114
+ font-size: 12px;
115
+ font-weight: 500;
109
116
  color: var(--text-dim);
110
117
  }
111
118
  /* Message time, hooked onto the speaker's label. Paler and less spaced out
112
119
  than the label: there for whoever looks for it, quiet otherwise. */
113
120
  .label .time {
114
- letter-spacing: 0.06em;
121
+ font-weight: 400;
115
122
  opacity: 0.6;
116
123
  }
117
124
  .label .time::before {
@@ -126,8 +133,7 @@
126
133
  align-items: center;
127
134
  gap: 12px;
128
135
  padding: 10px 16px;
129
- border-bottom: 1px solid var(--line);
130
- background: var(--bg-raised);
136
+ background: var(--page);
131
137
  flex-wrap: wrap;
132
138
  }
133
139
  /* Keep the toolbar buttons together so they never split across lines. */
@@ -156,11 +162,11 @@
156
162
  #starBtn:hover { border-color: var(--amber); color: var(--amber); }
157
163
  #starBtn:hover .star-count { color: var(--amber); }
158
164
  header .brand {
159
- font-family: var(--mono);
160
- font-size: 14px;
161
- color: var(--amber);
162
- letter-spacing: 0.06em;
165
+ font-size: 15px;
166
+ font-weight: 700;
167
+ color: var(--text);
163
168
  }
169
+ header .brand::before { color: var(--amber); }
164
170
  header .brand::before { content: "◆ "; }
165
171
  /* The brand name doubles as the cockpit's editable title: click to rename,
166
172
  Enter/blur commits, Escape cancels. A dashed outline + pencil on hover make
@@ -225,7 +231,7 @@
225
231
  #verMenu {
226
232
  position: fixed; top: 42px; left: 12px; z-index: 1001;
227
233
  background: var(--menu-bg); border: 1px solid var(--line); border-radius: 6px;
228
- padding: 10px 12px; font-family: var(--mono); font-size: 12px;
234
+ padding: 10px 12px; font-family: var(--sans); font-size: 12px;
229
235
  min-width: 210px; box-shadow: 0 6px 20px rgba(0,0,0,0.5);
230
236
  }
231
237
  #verMenu .vm-row { display: flex; justify-content: space-between; gap: 16px; margin-bottom: 4px; }
@@ -241,7 +247,7 @@
241
247
  #tabMenu {
242
248
  position: fixed; z-index: 1002;
243
249
  background: var(--menu-bg); border: 1px solid var(--line); border-radius: 6px;
244
- padding: 4px; font-family: var(--mono); font-size: 12px;
250
+ padding: 4px; font-family: var(--sans); font-size: 12px;
245
251
  min-width: 170px; box-shadow: 0 6px 20px rgba(0,0,0,0.5);
246
252
  }
247
253
  #tabMenu .tm-item {
@@ -298,7 +304,7 @@
298
304
  #updateBanner {
299
305
  position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
300
306
  background: var(--amber); color: #1a1200;
301
- font-family: var(--mono); font-size: 12px; text-align: center;
307
+ font-family: var(--sans); font-size: 12px; text-align: center;
302
308
  padding: 6px 12px;
303
309
  }
304
310
  /* The re-login reminder (sign-in within 48h / expired). Same top strip as the
@@ -306,7 +312,7 @@
306
312
  #expiryBanner {
307
313
  position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
308
314
  background: var(--amber); color: #1a1200;
309
- font-family: var(--mono); font-size: 12px;
315
+ font-family: var(--sans); font-size: 12px;
310
316
  padding: 6px 12px;
311
317
  display: flex; gap: 10px; align-items: center; justify-content: center; flex-wrap: wrap;
312
318
  }
@@ -317,7 +323,7 @@
317
323
  }
318
324
  .gauge { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
319
325
  .gauge .value {
320
- font-family: var(--mono);
326
+ font-family: var(--sans);
321
327
  font-size: 12px;
322
328
  color: var(--text);
323
329
  white-space: nowrap;
@@ -385,23 +391,25 @@
385
391
  .dial .needle, .dial .pct { transition: none; }
386
392
  }
387
393
  button {
388
- font-family: var(--mono);
389
- font-size: 12px;
390
- letter-spacing: 0.06em;
394
+ font-family: var(--sans);
395
+ font-size: 13px;
396
+ font-weight: 500;
391
397
  background: transparent;
392
398
  color: var(--text);
393
399
  border: 1px solid var(--line);
394
- border-radius: 4px;
400
+ border-radius: 8px;
395
401
  padding: 6px 12px;
396
402
  cursor: pointer;
403
+ transition: background 0.12s, color 0.12s, border-color 0.12s;
397
404
  }
398
- /* Compact icon buttons in the header (emoji + tooltip). */
405
+ /* Icon buttons carry no frame: a soft fill on hover is the whole affordance. */
399
406
  header button.icon {
400
- padding: 5px 8px;
407
+ padding: 7px 9px;
401
408
  font-size: 14px;
402
409
  line-height: 1;
403
- letter-spacing: 0;
410
+ border-color: transparent;
404
411
  }
412
+ header button.icon:hover { background: var(--bg-raised); border-color: transparent; color: var(--text); }
405
413
  header button.icon.stop:hover { border-color: var(--err); color: var(--err); }
406
414
  /* The bell's diagonal slash shows only when notifications are muted. */
407
415
  #muteNotif:not(.muted) .mute-slash { display: none; }
@@ -431,7 +439,7 @@
431
439
  .mm-tools:empty { display: none; }
432
440
  #moreMenu .mm-tools button { width: auto; } /* override #moreMenu button width:100% */
433
441
  #moreMenu .mm-sep { height: 1px; background: var(--line); margin: 4px 2px; }
434
- #moreMenu .mm-label { padding: 2px 4px; font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); }
442
+ #moreMenu .mm-label { padding: 2px 4px; font-size: 12px; font-weight: 500; color: var(--text-dim); }
435
443
  .mm-themes { display: flex; gap: 6px; padding: 2px 4px 4px; }
436
444
  /* Swatch buttons must override `#moreMenu button { width:100% }` — hence the
437
445
  id-scoped selector so specificity wins. */
@@ -450,9 +458,10 @@
450
458
  }
451
459
  #moreMenu .mm-mode button:hover { border-color: var(--text-dim); color: var(--text); }
452
460
  #moreMenu .mm-mode button.active { border-color: var(--amber); color: var(--amber); background: color-mix(in srgb, var(--amber) 12%, transparent); }
453
- button:hover { border-color: var(--amber); color: var(--amber); }
461
+ button:hover { background: var(--bg-inset); border-color: var(--line); color: var(--text); }
454
462
  button:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
455
463
  button.primary { background: var(--amber); border-color: var(--amber); color: #1a1205; font-weight: 600; }
464
+ button.primary:hover { background: var(--amber); border-color: var(--amber); color: #1a1205; }
456
465
  button.primary:hover { filter: brightness(1.1); }
457
466
  button:disabled { opacity: 0.4; cursor: default; }
458
467
 
@@ -464,22 +473,22 @@
464
473
  flex-direction: column;
465
474
  gap: 2px;
466
475
  background: var(--bg-raised);
467
- border-right: 1px solid var(--line);
476
+ border: 1px solid var(--line);
477
+ border-radius: var(--radius);
468
478
  padding: 12px 8px;
469
479
  overflow-y: auto;
470
480
  }
471
- #tabbar .side-label { padding: 0 8px 8px; }
481
+ #tabbar .side-label { padding: 0 8px 8px; font-size: 13px; font-weight: 600; color: var(--text); }
472
482
  .tab {
473
483
  position: relative;
474
484
  display: flex;
475
485
  flex-direction: column; /* row 1 (led+name+icons) then row 2 (info) */
476
486
  gap: 1px;
477
- font-family: var(--mono);
478
- font-size: 12px;
487
+ font-size: 14px;
479
488
  color: var(--text-dim);
480
489
  border-left: 2px solid transparent;
481
- border-radius: 4px;
482
- padding: 9px 10px 11px;
490
+ border-radius: 8px;
491
+ padding: 8px 10px 10px;
483
492
  cursor: pointer;
484
493
  user-select: none;
485
494
  }
@@ -497,7 +506,7 @@
497
506
  right: 10px;
498
507
  bottom: 3px;
499
508
  height: 2px;
500
- background: var(--line);
509
+ background: transparent;
501
510
  border-radius: 1px;
502
511
  overflow: hidden;
503
512
  }
@@ -521,7 +530,7 @@
521
530
  color: var(--text);
522
531
  font-weight: 600;
523
532
  border-left-color: var(--phosphor);
524
- border-radius: 0 4px 4px 0;
533
+ border-radius: 0 8px 8px 0;
525
534
  box-shadow: inset 3px 0 0 var(--phosphor);
526
535
  }
527
536
  /* Full-width row 2: "xxx ago" on the left, context % hard right. */
@@ -541,8 +550,7 @@
541
550
  .tab input.rename {
542
551
  flex: 1;
543
552
  min-width: 0;
544
- font-family: var(--mono);
545
- font-size: 12px;
553
+ font-size: 13px;
546
554
  background: var(--bg-inset);
547
555
  border: 1px solid var(--amber);
548
556
  border-radius: 3px;
@@ -591,13 +599,14 @@
591
599
  }
592
600
  @media (prefers-reduced-motion: reduce) { .tab.working, .tab.has-bg { animation: none; } }
593
601
  #newTab, #newGroup, #newGroupBare {
594
- margin-top: 8px;
595
- border: 1px dashed var(--line);
596
- font-size: 12px;
602
+ margin-top: 6px;
603
+ border-color: transparent;
604
+ font-size: 13px;
597
605
  color: var(--text-dim);
598
- padding: 8px;
606
+ padding: 8px 10px;
607
+ text-align: left;
599
608
  }
600
- #newTab:hover, #newGroup:hover, #newGroupBare:hover { color: var(--amber); border-color: var(--amber); }
609
+ #newTab:hover, #newGroup:hover, #newGroupBare:hover { color: var(--amber); background: var(--amber-soft); border-color: transparent; }
601
610
  #newGroup { margin-top: 4px; }
602
611
  /* The fallback "new group" entry: only on desktop, only while the rail (which
603
612
  has its own) is hidden for want of a group. */
@@ -618,7 +627,7 @@
618
627
  padding-top: 8px;
619
628
  background: var(--bg-raised);
620
629
  /* Separates it from the list scrolling underneath, with no extra rule. */
621
- box-shadow: 0 -8px 10px -8px rgba(0, 0, 0, 0.6);
630
+ box-shadow: 0 -8px 10px -10px rgba(0, 0, 0, 0.35);
622
631
  }
623
632
  /* The tweak channel's tab keeps its slot's tint, so it is recognisable in the
624
633
  same place as before it was started. */
@@ -633,18 +642,18 @@
633
642
  gap: 2px;
634
643
  text-align: left;
635
644
  padding: 8px;
636
- border: 1px solid var(--amber);
637
- border-radius: 6px;
645
+ border: 1px solid color-mix(in srgb, var(--amber) 45%, transparent);
646
+ border-radius: 10px;
638
647
  width: 100%;
639
648
  background: linear-gradient(var(--amber-soft), var(--amber-soft)), var(--bg-raised);
640
649
  }
641
650
  #tweakCta .tweak-title {
642
- font-family: var(--mono);
643
- font-size: 12px;
651
+ font-family: var(--sans);
652
+ font-size: 13px;
644
653
  font-weight: 600;
645
654
  color: var(--amber);
646
655
  }
647
- #tweakCta .tweak-sub { font-size: 10px; color: var(--text-dim); }
656
+ #tweakCta .tweak-sub { font-size: 11px; color: var(--text-dim); }
648
657
  #tweakCta .tweak-arrow { display: inline-block; transition: transform 0.15s ease; }
649
658
  /* No permanent animation: an element blinking here would compete with the
650
659
  real signals (a waiting tab, the gauges) and would turn into noise. */
@@ -662,12 +671,11 @@
662
671
  display: flex;
663
672
  align-items: center;
664
673
  gap: 6px;
665
- font-family: var(--mono);
666
- font-size: 10px;
667
- letter-spacing: 0.14em;
668
- text-transform: uppercase;
674
+ font-family: var(--sans);
675
+ font-size: 12px;
676
+ font-weight: 600;
669
677
  color: var(--text-dim);
670
- border-radius: 4px;
678
+ border-radius: 6px;
671
679
  padding: 5px 8px;
672
680
  cursor: pointer;
673
681
  user-select: none;
@@ -683,7 +691,7 @@
683
691
  .group-head input.rename {
684
692
  flex: 1;
685
693
  min-width: 0;
686
- font-family: var(--mono);
694
+ font-family: var(--sans);
687
695
  font-size: 11px;
688
696
  text-transform: none;
689
697
  letter-spacing: normal;
@@ -719,13 +727,19 @@
719
727
  /* The column only earns its space once a group exists: with none, the
720
728
  cockpit is the single agents list it always was (body.has-groups is set
721
729
  from groups.length in applyView). */
730
+ /* The rail and the agents column are ONE card: the rail is its tinted
731
+ left half, the agents column its right half. */
722
732
  body.has-groups #groupRail {
723
733
  width: 190px; flex: none;
724
734
  display: flex; flex-direction: column; gap: 2px;
725
735
  background: var(--bg-inset);
726
- border-right: 1px solid var(--line);
736
+ border: 1px solid var(--line); border-right: none;
737
+ border-radius: var(--radius) 0 0 var(--radius);
727
738
  padding: 12px 8px; overflow-y: auto;
728
739
  }
740
+ body.has-groups #tabbar { border-radius: 0 var(--radius) var(--radius) 0; }
741
+ /* Cancel <main>'s gap between the two halves of the card. */
742
+ body.has-groups #groupRail { margin-right: -12px; }
729
743
  .rail-head { display: flex; align-items: center; justify-content: space-between; padding: 0 4px 8px 8px; }
730
744
  #railMini { border: none; background: none; padding: 2px 6px; color: var(--text-dim); font-size: 13px; }
731
745
  #railMini:hover { color: var(--amber); }
@@ -752,7 +766,7 @@
752
766
  background: var(--bg-inset); border: 1px solid var(--amber); border-radius: 3px;
753
767
  color: var(--text); padding: 2px 5px;
754
768
  }
755
- .rail-count { flex: none; font-family: var(--mono); font-size: 10px; color: var(--text-dim); }
769
+ .rail-count { flex: none; font-family: var(--sans); font-size: 10px; color: var(--text-dim); }
756
770
  /* What a group that is not on screen asks of you — the single place it shows. */
757
771
  .rail-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; display: none; }
758
772
  .rail-item.needs-answer .rail-dot { display: block; background: var(--amber); animation: breathe 1.2s ease-in-out infinite; }
@@ -777,8 +791,8 @@
777
791
  .rail-add:hover { color: var(--amber); }
778
792
  .rail-del:hover { color: var(--err); }
779
793
  #groupRail #newGroup {
780
- margin-top: 8px; border: 1px dashed var(--line);
781
- font-size: 12px; color: var(--text-dim); padding: 8px;
794
+ margin-top: 6px; border-color: transparent; text-align: left;
795
+ font-size: 13px; color: var(--text-dim); padding: 8px 10px;
782
796
  }
783
797
  #groupRail #newGroup:hover { color: var(--amber); border-color: var(--amber); }
784
798
  /* Collapsed to icons, like a dock: the names live in the tooltips. */
@@ -827,11 +841,16 @@
827
841
  .icon-picker input { width: 100%; font-size: 13px; box-sizing: border-box; }
828
842
 
829
843
  /* ── Body ────────────────────────────────────────────── */
830
- main { flex: 1; display: flex; min-height: 0; }
844
+ /* The panels are cards on the page: a gap around them, rounded corners.
845
+ A phone keeps edge-to-edge panels (see the mobile query). */
846
+ main { flex: 1; display: flex; min-height: 0; padding: 0 12px 12px; gap: 12px; }
831
847
  /* min-height:0 so the transcript (flex:1) bounds the height instead of pushing
832
848
  the chassis; overflow-y:auto keeps the setup screen reachable when it
833
849
  overflows (with a session running the transcript fits exactly → inert). */
834
- .chat-pane { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow-y: auto; position: relative; }
850
+ .chat-pane {
851
+ flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow-y: auto; position: relative;
852
+ background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius);
853
+ }
835
854
  /* File drag-and-drop target: a dashed accent overlay while a file hovers.
836
855
  pointer-events:none so the drop still lands on the pane underneath. */
837
856
  .chat-pane.dropping::after {
@@ -846,7 +865,7 @@
846
865
 
847
866
  .field { display: flex; flex-direction: column; gap: 6px; }
848
867
  input[type="text"] {
849
- font-family: var(--mono);
868
+ font-family: var(--sans);
850
869
  font-size: 13px;
851
870
  background: var(--bg-inset);
852
871
  border: 1px solid var(--line);
@@ -909,7 +928,7 @@
909
928
  .profile-card.selected { border-color: var(--amber); box-shadow: inset 0 0 0 1px var(--amber); }
910
929
  .profile-card.selected .pc-name { color: var(--amber); }
911
930
  .profile-card:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }
912
- .pc-name { font-family: var(--mono); font-size: 13px; }
931
+ .pc-name { font-size: 14px; font-weight: 600; }
913
932
  .pc-blurb {
914
933
  color: var(--text-dim); font-size: 11.5px; line-height: 1.35;
915
934
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
@@ -1081,8 +1100,8 @@
1081
1100
  .turn.user { align-self: flex-end; align-items: flex-end; }
1082
1101
  .turn.claude { align-self: flex-start; }
1083
1102
  .bubble {
1084
- padding: 7px 12px;
1085
- border-radius: 6px;
1103
+ padding: 9px 14px;
1104
+ border-radius: 14px;
1086
1105
  font-size: 14px;
1087
1106
  line-height: 1.4;
1088
1107
  white-space: pre-wrap;
@@ -1134,10 +1153,11 @@
1134
1153
  color: #fff; border-radius: 50%; width: 16px; height: 16px; font-size: 9px; line-height: 1; cursor: pointer; padding: 0; }
1135
1154
  .cmp-att .cmp-x:hover { background: var(--err); }
1136
1155
  .turn.claude .bubble {
1137
- background: var(--bg-inset);
1156
+ background: var(--bg-raised);
1138
1157
  border: 1px solid var(--line);
1139
- font-family: var(--mono);
1140
- font-size: 13px;
1158
+ font-family: var(--sans);
1159
+ font-size: 14px;
1160
+ line-height: 1.55;
1141
1161
  /* Wrap long prose lines so nothing is clipped; still preserves the
1142
1162
  TUI's own newlines. (Wide tables come through history as real HTML.) */
1143
1163
  white-space: pre-wrap;
@@ -1152,7 +1172,7 @@
1152
1172
  .turn.claude.live-preview .bubble {
1153
1173
  opacity: 0.55;
1154
1174
  white-space: pre-wrap;
1155
- font-family: var(--mono);
1175
+ font-family: var(--sans);
1156
1176
  }
1157
1177
  .turn.claude.live-preview .bubble::after {
1158
1178
  content: "▍";
@@ -1433,7 +1453,7 @@
1433
1453
  .validate { align-self: flex-end; margin-top: 2px; }
1434
1454
  .freetext-row { display: flex; gap: 8px; width: 100%; }
1435
1455
  .freetext-row input { flex: 1; }
1436
- #thinking { display: none; align-self: flex-start; color: var(--text-dim); font-family: var(--mono); font-size: 12.5px; padding: 0 22px 6px; }
1456
+ #thinking { display: none; align-self: flex-start; color: var(--text-dim); font-family: var(--sans); font-size: 12.5px; padding: 0 22px 6px; }
1437
1457
  #thinking.visible { display: flex; align-items: center; gap: 6px; }
1438
1458
  /* Shimmering text (an amber sweep) + a little Shadok pumping alongside. */
1439
1459
  #thinking .tw-text {
@@ -1460,9 +1480,8 @@
1460
1480
  gap: 10px;
1461
1481
  /* The bottom padding absorbs the home indicator (viewport-fit=cover): without
1462
1482
  it the field slides under it and half the text becomes unreadable. */
1463
- padding: 14px 22px calc(18px + env(safe-area-inset-bottom, 0px));
1464
- border-top: 1px solid var(--line);
1465
- background: var(--bg-raised);
1483
+ padding: 12px 16px calc(14px + env(safe-area-inset-bottom, 0px));
1484
+ background: var(--bg);
1466
1485
  }
1467
1486
  #composer textarea {
1468
1487
  flex: 1;
@@ -1471,17 +1490,17 @@
1471
1490
  min-width: 0;
1472
1491
  font-family: var(--sans);
1473
1492
  font-size: 14px;
1474
- background: var(--bg-inset);
1493
+ background: var(--bg-raised);
1475
1494
  color: var(--text);
1476
1495
  border: 1px solid var(--line);
1477
- border-radius: 6px;
1478
- padding: 10px 12px;
1496
+ border-radius: var(--radius);
1497
+ padding: 11px 14px;
1479
1498
  resize: none;
1480
1499
  min-height: 42px;
1481
1500
  max-height: 160px;
1482
1501
  line-height: 1.45;
1483
1502
  }
1484
- #composer textarea:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }
1503
+ #composer textarea:focus-visible { outline: none; border-color: var(--amber); box-shadow: 0 0 0 3px var(--amber-soft); }
1485
1504
 
1486
1505
  /* ── Engine room (live terminal) ─────────────────────── */
1487
1506
  #machine {
@@ -1523,13 +1542,13 @@
1523
1542
  channel's actions only existed in terminal mode; it now sits above both
1524
1543
  views, and `hidden` only removes it while the "New agent" form is up (no
1525
1544
  channel to act on yet). */
1526
- #chanBar { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--line); background: var(--bg-raised); font-family: var(--mono); font-size: 12px; }
1545
+ #chanBar { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--line); background: var(--bg-raised); font-size: 13px; }
1527
1546
  #chanBar[hidden] { display: none; }
1528
1547
  #chanBar .label { color: var(--text-dim); }
1529
- #chanBar #chanBarName { color: var(--amber); }
1548
+ #chanBar #chanBarName { color: var(--text); font-size: 14px; font-weight: 600; }
1530
1549
  /* Channel actions on the right of the bar (icons like the header). */
1531
1550
  .chan-actions { margin-left: auto; display: flex; align-items: center; gap: 6px; }
1532
- #chanBar button.icon { padding: 4px 8px; font-size: 14px; line-height: 1; letter-spacing: 0; }
1551
+ #chanBar button.icon { padding: 6px 8px; font-size: 14px; line-height: 1; border-color: transparent; }
1533
1552
  #chanBar button.icon.stop:hover { border-color: var(--err); color: var(--err); }
1534
1553
  #chanBar button.icon.on { border-color: var(--amber); color: var(--amber); background: color-mix(in srgb, var(--amber) 15%, transparent); }
1535
1554
  /* Reload-to-apply: a green, pulsing text pill (not a bare icon) so an available
@@ -1549,7 +1568,7 @@
1549
1568
  shown as a compact "● name ▾" pill on a phone. */
1550
1569
  #chanPicker {
1551
1570
  display: none; align-items: center; gap: 6px;
1552
- font-family: var(--mono); font-size: 13px; cursor: pointer;
1571
+ font-family: var(--sans); font-size: 13px; cursor: pointer;
1553
1572
  background: var(--bg-inset); color: var(--text);
1554
1573
  border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px;
1555
1574
  max-width: 55vw;
@@ -1559,6 +1578,12 @@
1559
1578
  body.picker-open #chanPicker { border-color: var(--amber); }
1560
1579
  body.picker-open #chanPicker .pk-caret { transform: rotate(180deg); }
1561
1580
  /* ── Mobile: sidebar hidden, navigation via the channel header's selector ── */
1581
+ /* A phone has no room for cards: panels go edge to edge, as before. */
1582
+ @media (max-width: 640px) {
1583
+ main { padding: 0; gap: 0; }
1584
+ .chat-pane { border: none; border-radius: 0; }
1585
+ #tabbar { border-radius: 0; }
1586
+ }
1562
1587
  @media (max-width: 640px) {
1563
1588
  #tabbar { display: none; }
1564
1589
  #chanPicker { display: inline-flex; min-width: 0; }
@@ -1649,8 +1674,7 @@
1649
1674
  }
1650
1675
  #emptyState.visible, #startingState.visible { display: flex; }
1651
1676
  #emptyState .es-title, #startingState .es-title {
1652
- font-family: var(--mono); font-size: 12px;
1653
- letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-dim);
1677
+ font-family: var(--sans); font-size: 15px; font-weight: 600; color: var(--text);
1654
1678
  }
1655
1679
  #emptyState .es-hint, #startingState .es-hint { color: var(--text-dim); font-size: 13px; line-height: 1.5; max-width: 44ch; }
1656
1680
  .keys {
@@ -1783,7 +1807,7 @@
1783
1807
  .preprompt { margin: 0 0 14px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-raised); }
1784
1808
  .preprompt > summary {
1785
1809
  cursor: pointer; padding: 8px 12px; color: var(--text-dim);
1786
- font-size: 12px; font-family: var(--mono); list-style: none;
1810
+ font-size: 12px; font-family: var(--sans); list-style: none;
1787
1811
  }
1788
1812
  .preprompt > summary::-webkit-details-marker { display: none; }
1789
1813
  .preprompt > summary::before { content: "▸ "; }
@@ -1878,10 +1902,8 @@
1878
1902
  /* Same treatment as the cockpit's labels (.label, channel bar): the popin
1879
1903
  visibly belongs to the same family. */
1880
1904
  .modal > .sec-head strong {
1881
- font-family: var(--mono); font-size: 11px; font-weight: normal;
1882
- letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-dim);
1905
+ font-family: var(--sans); font-size: 16px; font-weight: 600; color: var(--text);
1883
1906
  }
1884
- .modal > .sec-head strong .obj { color: var(--amber); }
1885
1907
  .modal-body { flex: 1 1 auto; overflow: auto; padding: 14px 16px; }
1886
1908
  .modal-foot {
1887
1909
  flex: 0 0 auto; display: flex; align-items: center; justify-content: flex-end;