claude-mission-control 1.18.0 → 1.19.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 (2) hide show
  1. package/package.json +1 -1
  2. package/public/index.html +261 -239
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mission-control",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "Local dashboard for Claude Code: live sessions, transcripts, costs, git status — all your projects in one place.",
5
5
  "main": "server.js",
6
6
  "bin": {
package/public/index.html CHANGED
@@ -31,23 +31,25 @@
31
31
  src: url('/fonts/Oswald-Variable.woff2') format('woff2');
32
32
  font-weight: 200 700; font-style: normal; font-display: swap;
33
33
  }
34
- /* Departures board: blue-black enamel, ivory flap letters, amber is the
35
- loudest color (needs you), green is a small "boarding" lamp, red means
36
- broken. Oswald condensed caps carry names; JetBrains Mono carries data.
37
- Light theme is the same timetable, printed on paper. */
34
+ /* Departures board: blue-black enamel, amber is the loudest color (needs
35
+ you), green is a small "boarding" lamp, red means broken. Prose is the
36
+ system sans, data is JetBrains Mono, and the split-flap status lamp is
37
+ the one place Oswald caps survive. Light theme is the same board on paper. */
38
38
  :root {
39
39
  --disp-font: 'Oswald', 'Arial Narrow', sans-serif;
40
- --bg: #f5f4f0;
41
- --surface: #ecebe5;
42
- --surface2: #e0dfd8;
40
+ --ui-font: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif;
41
+ --mono-font: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
42
+ --bg: #f1f0eb;
43
+ --surface: #fbfbf8;
44
+ --surface2: #e6e5df;
43
45
  --ink: #1b2022;
44
46
  --muted: #596264;
45
- --faint: #8d9496;
46
- --line: #d5d4cc;
47
+ --faint: #8a9193;
48
+ --line: #dddcd4;
47
49
  --accent: #1d7a44;
48
50
  --warn: #a66a00;
49
51
  --bad: #bd3524;
50
- --chip-bg: #e0dfd8;
52
+ --chip-bg: #ecebe5;
51
53
  --warn-bg: rgba(166, 106, 0, 0.10);
52
54
  --accent-bg: rgba(29, 122, 68, 0.08);
53
55
  --glow: none;
@@ -82,6 +84,7 @@
82
84
  so it overrides both light and dark palettes. */
83
85
  :root[data-theme="phosphor"] {
84
86
  --disp-font: 'JetBrains Mono', ui-monospace, monospace;
87
+ --ui-font: 'JetBrains Mono', ui-monospace, monospace;
85
88
  --bg: #050a06;
86
89
  --surface: #0a120c;
87
90
  --surface2: #122015;
@@ -106,6 +109,7 @@
106
109
  and "needs you" is the white-hot bright intensity. Red still means broken. */
107
110
  :root[data-theme="amber"] {
108
111
  --disp-font: 'JetBrains Mono', ui-monospace, monospace;
112
+ --ui-font: 'JetBrains Mono', ui-monospace, monospace;
109
113
  --bg: #0a0602;
110
114
  --surface: #140d04;
111
115
  --surface2: #1f1508;
@@ -179,10 +183,12 @@
179
183
  body {
180
184
  background: var(--bg);
181
185
  color: var(--ink);
182
- font: 12.5px/1.5 'JetBrains Mono', ui-monospace, "SF Mono", Menlo, monospace;
186
+ font: 13.5px/1.5 var(--ui-font);
183
187
  padding-bottom: 48px;
188
+ -webkit-font-smoothing: antialiased;
184
189
  }
185
- .mono { font-family: inherit; }
190
+ /* Numbers, costs, branches and commands stay monospaced; prose does not. */
191
+ .mono, code, pre, kbd, .badge, .num { font-family: var(--mono-font); font-variant-numeric: tabular-nums; }
186
192
  ::selection { background: var(--warn); color: var(--amber-ink); }
187
193
 
188
194
  /* Display face: condensed caps, the board's letter-painted voice. */
@@ -206,99 +212,100 @@
206
212
  .flap.flip { animation: flapflip 0.3s ease-out; transform-origin: 50% 50%; }
207
213
  @media (prefers-reduced-motion: reduce) { .flap.flip { animation: none; } }
208
214
 
209
- /* ---------- header: the station sign ---------- */
215
+ /* ---------- header ---------- */
210
216
  header {
211
- display: flex; align-items: center; gap: 16px;
217
+ display: flex; align-items: center; gap: 14px;
212
218
  flex-wrap: wrap; row-gap: 10px;
213
- padding: 12px 20px;
214
- border-bottom: 2px solid var(--line);
219
+ padding: 10px 24px;
220
+ border-bottom: 1px solid var(--line);
215
221
  background: var(--surface);
216
222
  }
217
223
  header h1 {
218
- font-family: var(--disp-font);
219
- font-size: 19px; font-weight: 600; letter-spacing: 0.10em;
220
- text-transform: uppercase; white-space: nowrap;
221
- }
222
- header h1 .tilde { color: var(--warn); }
223
- #clock {
224
- font-size: 14px; font-weight: 700; color: var(--ink);
225
- letter-spacing: 0.08em; font-variant-numeric: tabular-nums;
224
+ font-size: 15px; font-weight: 650; letter-spacing: -0.01em; white-space: nowrap;
226
225
  }
226
+ #clock { display: none; }
227
227
  #conn {
228
- width: 7px; height: 7px; border-radius: 50%;
228
+ width: 8px; height: 8px; border-radius: 50%;
229
229
  background: var(--faint); flex: none;
230
230
  }
231
231
  #conn.on { background: var(--accent); box-shadow: var(--glow) var(--accent); }
232
232
  #conn.retry { background: var(--warn); }
233
233
  .spacer { flex: 1; }
234
234
 
235
- #quota { display: flex; gap: 18px; align-items: center; font-size: 12px; color: var(--muted); }
235
+ #quota { display: flex; gap: 20px; align-items: center; font-size: 12.5px; color: var(--muted); }
236
236
  #quota.stale { opacity: 0.45; }
237
- .meter { display: flex; align-items: center; gap: 7px; }
237
+ #quota .q-spend { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
238
+ #quota .q-spend .num { color: var(--ink); }
239
+ .meter { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
240
+ .meter .m-pct { color: var(--ink); font-family: var(--mono-font); font-size: 12px; min-width: 3ch; }
238
241
  .meter .bar {
239
- width: 72px; height: 5px; border-radius: 3px;
242
+ width: 64px; height: 6px; border-radius: 3px;
240
243
  background: var(--surface2); overflow: hidden;
241
244
  }
242
245
  .meter .fill { height: 100%; border-radius: 3px; background: var(--accent); }
243
246
  .meter .fill.hot { background: var(--warn); }
244
247
  .meter .fill.crit { background: var(--bad); }
245
- .meter .eta { color: var(--warn); white-space: nowrap; }
248
+ .meter .eta { color: var(--warn); white-space: nowrap; font-family: var(--mono-font); font-size: 12px; }
249
+
250
+ /* Section headings: plain sentence case, the count as a quiet number. */
251
+ .sec-head {
252
+ display: flex; align-items: baseline; gap: 8px;
253
+ font-size: 14px; font-weight: 600; color: var(--ink);
254
+ margin-bottom: 10px;
255
+ }
256
+ .sec-head .n { color: var(--faint); font-weight: 500; font-family: var(--mono-font); font-size: 12.5px; }
246
257
 
247
- /* ---------- live rail: the departures rows ---------- */
258
+ /* ---------- live rail ---------- */
248
259
  #live {
249
260
  position: sticky; top: 0; z-index: 5;
250
261
  background: var(--bg);
251
- padding: 14px 20px 14px;
252
- border-bottom: 2px solid var(--line);
253
- }
254
- #live .rail-label {
255
- font-family: var(--disp-font);
256
- font-size: 12px; text-transform: uppercase; letter-spacing: 0.22em;
257
- color: var(--faint); margin-bottom: 10px;
262
+ padding: 18px 24px 16px;
263
+ border-bottom: 1px solid var(--line);
258
264
  }
259
- #live .rows { display: flex; flex-direction: column; gap: 5px; }
265
+ #live .rows { display: flex; flex-direction: column; gap: 6px; }
260
266
  .dep-row {
261
267
  display: grid;
262
- grid-template-columns: 52px minmax(150px, 230px) 1fr max-content;
263
- gap: 2px 16px; align-items: center;
268
+ grid-template-columns: minmax(140px, 220px) 1fr max-content;
269
+ gap: 2px 18px; align-items: center;
264
270
  background: var(--surface);
265
- border-radius: 2px;
266
- padding: 8px 14px;
271
+ border: 1px solid var(--line);
272
+ border-radius: 8px;
273
+ padding: 10px 14px 10px 16px;
267
274
  }
268
- .dep-row.waiting { background: var(--warn-bg); box-shadow: inset 2px 0 0 var(--warn); }
269
- .dep-time { color: var(--faint); font-size: 12px; font-variant-numeric: tabular-nums; }
275
+ .dep-row.waiting { background: var(--warn-bg); border-color: var(--warn); }
276
+ .dep-time { display: none; }
270
277
  .dep-proj {
271
- font-size: 19px; line-height: 1.15; color: var(--ink);
278
+ font-size: 15px; font-weight: 600; line-height: 1.25; color: var(--ink);
272
279
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
273
280
  min-width: 0;
274
281
  }
275
- .dep-proj .badge { vertical-align: 3px; }
282
+ .dep-proj .badge { vertical-align: 1px; font-weight: 400; }
276
283
  .dep-mid { min-width: 0; }
277
284
  .dep-title {
278
- font-size: 12.5px; color: var(--muted); cursor: pointer;
285
+ font-size: 13.5px; color: var(--ink); cursor: pointer;
279
286
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
280
287
  }
281
- .dep-title:hover { color: var(--ink); }
288
+ .dep-title:hover { color: var(--accent); }
282
289
  .dep-task {
283
- margin-top: 2px; font-size: 11.5px; color: var(--ink);
290
+ margin-top: 2px; font-size: 12px; color: var(--muted);
284
291
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
285
292
  }
286
293
  .dep-task .prompt-ch { color: var(--accent); margin-right: 6px; }
287
294
  .dep-task .count { color: var(--faint); margin-left: 6px; }
288
295
  .dep-reason {
289
- margin-top: 2px; font-size: 11.5px; color: var(--muted);
296
+ margin-top: 2px; font-size: 12.5px; color: var(--ink);
290
297
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
291
298
  }
292
299
  .dep-reason .glyph { color: var(--warn); margin-right: 6px; font-weight: 600; }
293
- .dep-right { display: flex; align-items: center; gap: 10px; justify-self: end; }
294
- .dep-elapsed { color: var(--faint); font-size: 12px; }
300
+ .dep-right { display: flex; align-items: center; gap: 14px; justify-self: end; }
301
+ .dep-elapsed { color: var(--faint); font-size: 12px; font-family: var(--mono-font); }
295
302
  .dep-elapsed.overdue { color: var(--warn); font-weight: 600; }
296
303
  .unpriced { color: var(--warn); font-weight: 700; margin-left: 2px; cursor: help; }
297
- .dep-cost { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.15; min-width: 52px; }
304
+ .dep-cost { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.2; min-width: 52px; font-family: var(--mono-font); }
298
305
  .dep-cost-main { color: var(--muted); font-size: 12px; }
299
306
  .dep-burn { color: var(--faint); font-size: 10.5px; }
300
- .ctx { display: inline-flex; flex-direction: column; gap: 2px; min-width: 64px; }
301
- .ctx-label { font-size: 10.5px; color: var(--faint); text-align: right; white-space: nowrap; }
307
+ .ctx { display: inline-flex; flex-direction: column; gap: 3px; min-width: 64px; }
308
+ .ctx-label { font-size: 10.5px; color: var(--faint); text-align: right; white-space: nowrap; font-family: var(--mono-font); }
302
309
  .ctx-bar { height: 3px; background: var(--surface2); border-radius: 2px; overflow: hidden; }
303
310
  .ctx-fill { height: 100%; background: var(--accent); }
304
311
  .ctx.warn .ctx-fill { background: var(--warn); }
@@ -307,7 +314,11 @@
307
314
  .ctx.bad .ctx-label { color: var(--bad); }
308
315
  .mc-meta .failed { color: var(--warn); }
309
316
  .mc-meta.overdue { color: var(--warn); font-weight: 600; }
310
- .st { font-size: 11.5px; letter-spacing: 0.14em; padding: 3px 10px 2px; }
317
+ /* The status lamp is the one split-flap left: the loudest thing on screen. */
318
+ .st {
319
+ font-family: var(--disp-font); text-transform: uppercase; font-weight: 500;
320
+ font-size: 11.5px; letter-spacing: 0.12em; padding: 3px 10px 2px;
321
+ }
311
322
  .st.st-busy { color: var(--accent); }
312
323
  .st.st-waiting {
313
324
  background: var(--warn); color: var(--amber-ink); font-weight: 600;
@@ -315,105 +326,130 @@
315
326
  }
316
327
  .st.st-waiting::after { background: rgba(0, 0, 0, 0.22); }
317
328
  .st.st-quiet { color: var(--warn); }
318
- @media (max-width: 700px) {
319
- .dep-row { grid-template-columns: 44px 1fr max-content; }
320
- .dep-mid { grid-column: 1 / -1; }
329
+ .live-none { color: var(--muted); font-size: 13px; }
330
+ .live-none code { color: var(--ink); }
331
+
332
+ /* Row actions (rename / open / copy) wait for hover so titles get the room. */
333
+ .acts { display: inline-flex; align-items: center; gap: 2px; flex: none; }
334
+ @media (hover: hover) {
335
+ .acts { opacity: 0; transition: opacity 0.12s; }
336
+ li:hover > .acts, li:focus-within > .acts,
337
+ .dep-row:hover .acts, .dep-row:focus-within .acts,
338
+ .pin-row:hover .acts, .pin-row:focus-within .acts,
339
+ .digest-item:hover .acts, .digest-item:focus-within .acts { opacity: 1; }
340
+ }
341
+
342
+ /* In the narrow project cards the actions float over the row's right end. */
343
+ @media (hover: hover) {
344
+ .sessions li { position: relative; }
345
+ .sessions li > .acts {
346
+ position: absolute; right: 0; top: 50%; transform: translateY(-50%);
347
+ padding-left: 28px;
348
+ background: linear-gradient(to right, transparent, var(--surface) 24px);
349
+ pointer-events: none;
350
+ }
351
+ .sessions li:hover > .acts, .sessions li:focus-within > .acts { pointer-events: auto; }
321
352
  }
322
- .live-none { color: var(--faint); font-size: 13px; }
323
- .live-none code { color: var(--muted); }
353
+ .card .new-btn { font-size: 16px; line-height: 1; padding: 2px 7px; color: var(--faint); }
354
+ .card .new-btn:hover { color: var(--accent); }
324
355
 
325
356
  /* ---------- project grid ---------- */
326
- main { padding: 18px 20px; }
357
+ main { padding: 22px 24px; }
327
358
  #grid {
328
359
  display: grid; gap: 14px;
329
- grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
360
+ grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
330
361
  }
331
362
  .card {
332
363
  background: var(--surface);
333
- border-radius: 2px;
334
- border-top: 2px solid var(--line);
335
- padding: 12px 16px 10px;
364
+ border: 1px solid var(--line);
365
+ border-radius: 10px;
366
+ padding: 14px 16px 8px;
336
367
  display: flex; flex-direction: column;
368
+ min-width: 0;
337
369
  }
338
370
  .card .head { display: flex; align-items: center; gap: 8px; }
339
371
  .card .name {
340
- font-family: var(--disp-font);
341
- text-transform: uppercase; letter-spacing: 0.05em;
342
- font-weight: 500; font-size: 15px;
372
+ font-weight: 600; font-size: 15px; line-height: 1.3;
373
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
343
374
  }
344
- .card .live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex: none; box-shadow: var(--glow) var(--accent); }
345
- .card .spark { margin-left: auto; }
346
- .card .meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 7px; font-size: 11px; }
375
+ .card .name:hover { color: var(--accent); }
376
+ .card .live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: none; box-shadow: var(--glow) var(--accent); }
377
+ .card .spark { margin-left: auto; opacity: 0.8; flex: none; }
378
+ .card .meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 6px; font-size: 11.5px; }
347
379
  .badge {
348
- padding: 0 6px; border-radius: 2px; background: var(--chip-bg); color: var(--muted);
349
- font-family: inherit; font-size: 11px;
380
+ padding: 1px 6px; border-radius: 4px; background: var(--chip-bg); color: var(--muted);
381
+ font-size: 11px; white-space: nowrap;
350
382
  }
351
383
  .badge.dirty { color: var(--warn); }
352
384
  .badge.ahead { color: var(--accent); }
353
385
  .badge.err { color: var(--bad); }
354
386
  .badge.bg { color: var(--accent); letter-spacing: 0.06em; }
355
387
  .badge.missing { color: var(--bad); }
388
+ .badge.changes { cursor: pointer; }
356
389
  .note-mark { color: var(--warn); cursor: default; font-size: 12px; flex: none; }
357
390
  #note-editor { margin: 10px 0 4px; display: flex; flex-direction: column; gap: 6px; }
358
391
  #note-editor textarea {
359
392
  width: 100%; min-height: 72px; resize: vertical; box-sizing: border-box;
360
- font: 12.5px 'JetBrains Mono', ui-monospace, monospace; color: var(--ink);
361
- background: var(--surface); border: 1px solid var(--line); border-radius: 3px; padding: 8px 10px;
393
+ font: 12.5px var(--mono-font); color: var(--ink);
394
+ background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px;
362
395
  }
363
396
  #note-editor .hint { color: var(--faint); font-size: 11px; }
364
- .card .when { color: var(--faint); font-size: 11px; margin-left: auto; }
397
+ .card .when { color: var(--faint); font-size: 11.5px; margin-left: auto; }
365
398
  .sessions { list-style: none; padding: 0; margin: 10px 0 0; border-top: 1px solid var(--line); }
366
399
  .sessions li {
367
400
  display: flex; align-items: center; gap: 8px;
368
401
  padding: 7px 0; border-bottom: 1px solid var(--line);
369
- font-size: 12.5px;
402
+ font-size: 13px; min-height: 34px;
370
403
  }
371
404
  .sessions li:last-child { border-bottom: none; }
372
- .sessions .s-title {
405
+ .sessions .s-title, #pinned .s-title {
373
406
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
374
- color: var(--ink); flex: 1;
407
+ color: var(--ink); flex: 1; min-width: 0;
375
408
  }
376
- .sessions .s-title .wt { color: var(--accent); font-size: 11px; margin-right: 5px; }
377
- .sessions .s-when { color: var(--faint); font-size: 11px; flex: none; }
409
+ .sessions .s-title .wt { color: var(--accent); font-size: 11.5px; margin-right: 5px; }
410
+ .s-when { color: var(--faint); font-size: 11.5px; flex: none; white-space: nowrap; }
378
411
  .copy {
379
- flex: none; border: none; background: none; color: var(--faint);
380
- font-size: 11px; cursor: pointer; padding: 2px 6px; border-radius: 5px;
412
+ flex: none; border: none; background: none; color: var(--muted);
413
+ font-size: 12px; cursor: pointer; padding: 3px 7px; border-radius: 5px;
381
414
  font-family: inherit;
382
415
  }
383
416
  .copy:hover { background: var(--surface2); color: var(--ink); }
384
417
  .copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
385
418
  .open-btn { color: var(--accent); }
386
- #open-pref-wrap { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 6px; white-space: nowrap; }
419
+ #open-pref-wrap { font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 6px; white-space: nowrap; }
420
+ #open-pref-wrap[hidden] { display: none; }
387
421
  #open-pref {
388
422
  font: inherit; color: var(--ink);
389
423
  background: var(--surface2); border: 1px solid var(--line);
390
- border-radius: 2px; padding: 2px 6px;
424
+ border-radius: 6px; padding: 3px 6px;
391
425
  }
392
426
  #search {
393
427
  font: inherit; color: var(--ink);
394
- background: var(--surface2); border: 1px solid var(--line);
395
- border-radius: 2px; padding: 4px 10px; width: 190px; margin-left: 14px;
428
+ background: var(--bg); border: 1px solid var(--line);
429
+ border-radius: 8px; padding: 6px 12px; width: 260px; margin-left: 10px;
396
430
  }
397
- #search:focus { outline: 2px solid var(--accent); outline-offset: 0; }
431
+ #search:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
398
432
  #search::placeholder { color: var(--faint); }
399
- /* A full set of meters needs ~1600px; tighten before the header wraps. */
400
- @media (max-width: 1600px) {
433
+ /* A full set of meters needs room; tighten before the header wraps. */
434
+ @media (max-width: 1500px) {
401
435
  header { gap: 12px; }
402
- #search { width: 120px; }
436
+ #search { width: 180px; }
403
437
  #open-pref-wrap .open-label { display: none; }
404
- #quota { gap: 12px; }
438
+ #quota { gap: 14px; }
405
439
  .meter .bar { width: 44px; }
440
+ #wk-chart { display: none; }
406
441
  }
407
- #gear, #mc-btn, #bell-btn {
442
+ .hd-btn {
408
443
  border: none; background: none; color: var(--muted); cursor: pointer;
409
- font-size: 15px; padding: 2px 6px; border-radius: 2px; margin-left: 4px;
444
+ font-size: 15px; line-height: 1; padding: 6px 8px; border-radius: 6px;
410
445
  }
411
- #gear:hover, #mc-btn:hover, #bell-btn:hover { background: var(--surface2); color: var(--ink); }
446
+ .hd-btn:hover { background: var(--surface2); color: var(--ink); }
447
+ .hd-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
412
448
  #bell-btn { position: relative; }
413
449
  #bell-badge {
414
- position: absolute; top: -3px; right: -3px;
450
+ position: absolute; top: -2px; right: -2px;
415
451
  background: var(--warn); color: var(--amber-ink);
416
- font: 700 9.5px 'JetBrains Mono', monospace;
452
+ font: 700 9.5px var(--mono-font);
417
453
  border-radius: 8px; padding: 1px 4px; min-width: 10px; text-align: center;
418
454
  }
419
455
 
@@ -429,11 +465,11 @@
429
465
  .set-row input[type="text"] {
430
466
  font: inherit; color: var(--ink);
431
467
  background: var(--surface2); border: 1px solid var(--line);
432
- border-radius: 2px; padding: 4px 8px; width: 170px;
468
+ border-radius: 6px; padding: 4px 8px; width: 170px;
433
469
  }
434
470
  .set-row select {
435
471
  font: inherit; color: var(--ink); background: var(--surface2);
436
- border: 1px solid var(--line); border-radius: 2px; padding: 3px 6px;
472
+ border: 1px solid var(--line); border-radius: 6px; padding: 3px 6px;
437
473
  }
438
474
  .set-row input[type="checkbox"] { accent-color: var(--accent); width: 15px; height: 15px; }
439
475
 
@@ -445,7 +481,7 @@
445
481
  .rename-input {
446
482
  font: inherit; font-size: 12.5px; color: var(--ink);
447
483
  background: var(--surface2); border: 1px solid var(--accent);
448
- border-radius: 2px; padding: 2px 6px; flex: 1; min-width: 0; width: 100%;
484
+ border-radius: 6px; padding: 2px 6px; flex: 1; min-width: 0; width: 100%;
449
485
  box-sizing: border-box;
450
486
  }
451
487
  .rename-input:focus { outline: none; }
@@ -457,8 +493,7 @@
457
493
  border-radius: 3px; padding: 8px 12px; font-size: 13px;
458
494
  white-space: pre-wrap; overflow-wrap: break-word;
459
495
  }
460
- .t-user .t-who { color: var(--accent); font-size: 10px; text-transform: uppercase;
461
- letter-spacing: 0.08em; display: block; margin-bottom: 3px; }
496
+ .t-user .t-who { color: var(--accent); font-size: 11.5px; font-weight: 600; display: block; margin-bottom: 3px; }
462
497
  .t-tool {
463
498
  font-family: inherit; font-size: 11.5px;
464
499
  color: var(--muted); padding: 1px 0 1px 10px;
@@ -476,16 +511,11 @@
476
511
  .none-yet { color: var(--faint); font-size: 12px; padding: 10px 0 4px; }
477
512
 
478
513
  /* ---------- pinned strip ---------- */
479
- #pinned { margin-bottom: 16px; }
480
- #pinned .pin-label {
481
- font-family: var(--disp-font);
482
- font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.22em;
483
- color: var(--faint); margin-bottom: 6px;
484
- }
514
+ #pinned { margin-bottom: 22px; }
485
515
  #pinned .pin-row {
486
- display: flex; align-items: baseline; gap: 10px;
487
- background: var(--surface); border-radius: 2px;
488
- padding: 7px 14px; margin-bottom: 4px;
516
+ display: flex; align-items: center; gap: 10px;
517
+ background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
518
+ padding: 8px 14px; margin-bottom: 6px; min-height: 38px;
489
519
  }
490
520
  #pinned .pin-row .star { color: var(--warn); flex: none; }
491
521
 
@@ -509,78 +539,71 @@
509
539
 
510
540
  /* ---------- git attention strip ---------- */
511
541
  #git-attn {
512
- display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px 14px;
513
- background: var(--warn-bg);
514
- border: 1px solid var(--line); border-radius: 3px;
515
- padding: 8px 14px; margin-bottom: 16px;
516
- font-size: 12.5px;
542
+ display: flex; align-items: center; flex-wrap: wrap; gap: 8px 16px;
543
+ border: 1px solid var(--line); border-left: 3px solid var(--warn); border-radius: 8px;
544
+ background: var(--surface);
545
+ padding: 10px 16px; margin-bottom: 22px;
546
+ font-size: 13px;
517
547
  }
518
- #git-attn .ga-label { color: var(--warn); font-weight: 600; white-space: nowrap; }
519
- #git-attn .ga-item { color: var(--ink); white-space: nowrap; }
520
- #git-attn .ga-item .badge { margin-left: 4px; }
548
+ #git-attn .ga-label { color: var(--ink); font-weight: 600; white-space: nowrap; }
549
+ #git-attn .ga-item { color: var(--muted); white-space: nowrap; }
550
+ #git-attn .ga-item .badge { margin-left: 5px; }
521
551
 
522
552
  /* ---------- digest ---------- */
523
- #digest { margin-bottom: 20px; }
524
- #digest summary {
553
+ #digest { margin-bottom: 28px; }
554
+ #digest summary, #dormant summary {
525
555
  cursor: pointer; user-select: none; list-style: none;
526
556
  display: flex; align-items: center; gap: 12px;
527
557
  }
528
- #digest summary::-webkit-details-marker { display: none; }
529
- #digest-label {
530
- font-family: var(--disp-font);
531
- font-size: 12px; text-transform: uppercase; letter-spacing: 0.22em;
532
- color: var(--faint);
558
+ #digest summary::-webkit-details-marker, #dormant summary::-webkit-details-marker { display: none; }
559
+ #digest summary .sec-head, #dormant summary .sec-head { margin-bottom: 0; }
560
+ .sec-head .caret {
561
+ display: inline-block; width: 10px; color: var(--faint); font-size: 10px;
562
+ transition: transform 0.12s;
533
563
  }
534
- #digest-label::before { content: '▸ '; }
535
- #digest[open] #digest-label::before { content: '▾ '; }
536
- #digest-range { display: none; gap: 2px; }
564
+ details[open] > summary .caret { transform: rotate(90deg); }
565
+ #digest-range { display: none; padding: 2px; gap: 2px; background: var(--surface); border: 1px solid var(--line); border-radius: 7px; }
537
566
  #digest[open] #digest-range { display: inline-flex; }
538
567
  #digest-range button {
539
- font: 11px 'JetBrains Mono', ui-monospace, monospace; color: var(--muted);
540
- background: none; border: 1px solid var(--line); cursor: pointer;
541
- padding: 2px 9px;
568
+ font: 12px var(--ui-font); color: var(--muted);
569
+ background: none; border: none; border-radius: 5px; cursor: pointer;
570
+ padding: 3px 10px;
542
571
  }
543
- #digest-range button:first-child { border-radius: 6px 0 0 6px; }
544
- #digest-range button:last-child { border-radius: 0 2px 2px 0; }
572
+ #digest-range button:hover { color: var(--ink); }
545
573
  #digest-range button.sel { background: var(--surface2); color: var(--ink); }
546
- #digest-body { margin-top: 10px; }
574
+ #digest-body { margin-top: 12px; }
547
575
  .digest-day {
548
- font-family: var(--disp-font);
549
- color: var(--faint); font-size: 11.5px; text-transform: uppercase;
550
- letter-spacing: 0.22em; margin: 16px 0 6px;
576
+ color: var(--muted); font-size: 12.5px; font-weight: 500;
577
+ margin: 16px 0 8px;
551
578
  }
579
+ .digest-day:first-child { margin-top: 0; }
552
580
  .digest-item {
553
- background: var(--surface); border-radius: 2px;
554
- padding: 9px 14px; margin-bottom: 5px;
581
+ background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
582
+ padding: 10px 14px; margin-bottom: 6px;
555
583
  }
556
- .digest-item .di-top { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
584
+ .digest-item .di-top { display: flex; align-items: center; gap: 10px; min-width: 0; }
557
585
  .digest-item .di-proj {
558
- font-family: var(--disp-font);
559
- text-transform: uppercase; letter-spacing: 0.05em;
560
- font-weight: 500; font-size: 14.5px;
586
+ font-weight: 600; font-size: 13.5px; flex: none;
587
+ max-width: 30%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
561
588
  }
562
- .digest-item .di-title { color: var(--muted); font-size: 13px;
563
- overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 140px; }
564
- .digest-item .di-when { color: var(--faint); font-size: 11px; }
589
+ .digest-item .di-title { color: var(--muted); font-size: 13.5px;
590
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
591
+ .digest-item .di-when { color: var(--faint); font-size: 11.5px; font-family: var(--mono-font); white-space: nowrap; flex: none; }
565
592
  .digest-item .di-summary {
566
- margin-top: 6px; font-size: 12.5px; color: var(--ink); line-height: 1.5;
593
+ margin-top: 6px; font-size: 13px; color: var(--ink); line-height: 1.55; max-width: 110ch;
567
594
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
568
595
  cursor: pointer;
569
596
  }
570
597
  .digest-item .di-summary.expanded { display: block; }
571
- .digest-item .di-tasks { margin-top: 5px; font-size: 11px; color: var(--faint); }
598
+ .digest-item .di-tasks { margin-top: 5px; font-size: 12px; color: var(--faint); }
572
599
  .digest-item .di-tasks .done { color: var(--accent); }
573
- .digest-empty { color: var(--faint); font-size: 12.5px; padding: 6px 0; }
600
+ .digest-empty { color: var(--faint); font-size: 13px; padding: 6px 0; }
574
601
 
575
602
  /* ---------- dormant ---------- */
576
- #dormant { margin-top: 26px; }
577
- #dormant summary {
578
- font-family: var(--disp-font);
579
- cursor: pointer; color: var(--faint); font-size: 12px;
580
- text-transform: uppercase; letter-spacing: 0.22em; user-select: none;
581
- }
603
+ #dormant { margin-top: 32px; }
604
+ #grid + #dormant summary .sec-head { color: var(--muted); }
582
605
  #dormant .cards { margin-top: 12px; display: grid; gap: 14px;
583
- grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
606
+ grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); }
584
607
  #dormant .card { opacity: 0.75; }
585
608
 
586
609
  /* ---------- mission control ---------- */
@@ -592,13 +615,10 @@
592
615
  #mc[hidden] { display: none !important; }
593
616
  .mc-head {
594
617
  display: flex; align-items: center; gap: 14px;
595
- padding: 12px 20px; border-bottom: 2px solid var(--line);
618
+ padding: 12px 24px; border-bottom: 1px solid var(--line);
596
619
  background: var(--surface); flex: none;
597
620
  }
598
- .mc-title {
599
- font-family: var(--disp-font);
600
- font-size: 16px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase;
601
- }
621
+ .mc-title { font-size: 15px; font-weight: 650; }
602
622
  .mc-sub { color: var(--faint); font-size: 12px; }
603
623
  #mc-grid {
604
624
  flex: 1; overflow-y: auto;
@@ -609,7 +629,7 @@
609
629
  #mc-grid .mc-empty { color: var(--faint); font-size: 13px; padding: 24px 0; }
610
630
  .mc-pane {
611
631
  display: flex; flex-direction: column;
612
- background: var(--surface); border-radius: 2px;
632
+ background: var(--surface); border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
613
633
  height: min(46vh, 480px); min-width: 0;
614
634
  }
615
635
  .mc-pane.waiting { box-shadow: inset 0 2px 0 var(--warn); }
@@ -621,9 +641,7 @@
621
641
  .mc-pane-head .mc-proj { min-width: 0; flex: 0 1 auto; }
622
642
  .mc-stats { flex: 1 0 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; min-width: 0; }
623
643
  .mc-pane-head .mc-proj {
624
- font-family: var(--disp-font);
625
- text-transform: uppercase; letter-spacing: 0.05em;
626
- font-weight: 500; font-size: 15px; cursor: pointer;
644
+ font-weight: 600; font-size: 14.5px; cursor: pointer;
627
645
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
628
646
  }
629
647
  .mc-pane-head .mc-proj:hover { color: var(--warn); }
@@ -649,8 +667,8 @@
649
667
  display: grid; gap: 10px; padding: 14px 20px 0;
650
668
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
651
669
  }
652
- .hv-tile { background: var(--surface); border-radius: 2px; padding: 9px 12px; min-width: 0; }
653
- .hv-tile .k { color: var(--faint); font-size: 10.5px; letter-spacing: 0.14em; text-transform: uppercase; }
670
+ .hv-tile { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 9px 12px; min-width: 0; }
671
+ .hv-tile .k { color: var(--muted); font-size: 12px; font-weight: 500; }
654
672
  .hv-tile .v { font-family: var(--disp-font); font-size: 26px; font-weight: 500; line-height: 1.15; }
655
673
  .hv-tile .s { color: var(--faint); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
656
674
  .hv-tile.warn .v, .hv-tile .eta { color: var(--warn); }
@@ -661,7 +679,7 @@
661
679
  }
662
680
  .hv-empty { color: var(--faint); font-size: 13px; padding: 24px 20px; }
663
681
  .hv-card {
664
- background: var(--surface); border-radius: 2px; min-width: 0;
682
+ background: var(--surface); border: 1px solid var(--line); border-radius: 10px; min-width: 0;
665
683
  border-top: 3px solid var(--hue); display: flex; flex-direction: column;
666
684
  }
667
685
  .hv-card.waiting { border-top-color: var(--warn); box-shadow: inset 0 0 0 1px var(--warn-bg); }
@@ -683,14 +701,14 @@
683
701
  .hv-money .big { font-family: var(--disp-font); font-size: 38px; font-weight: 500; line-height: 1; }
684
702
  .hv-money .rate { color: var(--muted); font-size: 12px; }
685
703
  .hv-state {
686
- margin: 0 14px; padding: 7px 10px; border-radius: 2px; background: var(--surface2);
704
+ margin: 0 14px; padding: 7px 10px; border-radius: 6px; background: var(--surface2);
687
705
  display: flex; gap: 10px; align-items: center; min-width: 0; font-size: 12px;
688
706
  }
689
707
  .hv-state .txt { color: var(--muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
690
708
  .hv-card.waiting .hv-state { background: var(--warn-bg); }
691
709
  .hv-card.waiting .hv-state .txt { color: var(--ink); }
692
710
  .hv-sec { padding: 12px 14px 0; }
693
- .hv-label { color: var(--faint); font-size: 10.5px; letter-spacing: 0.14em; text-transform: uppercase; display: flex; justify-content: space-between; gap: 8px; }
711
+ .hv-label { color: var(--muted); font-size: 12px; font-weight: 500; display: flex; justify-content: space-between; gap: 8px; }
694
712
  .hv-call { margin-top: 5px; font-size: 13px; display: flex; gap: 6px; min-width: 0; }
695
713
  .hv-call .verb { color: var(--muted); flex: none; }
696
714
  .hv-call .tgt { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
@@ -702,7 +720,7 @@
702
720
  .hv-task { margin-top: 6px; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
703
721
  .hv-task .prompt-ch { color: var(--accent); margin-right: 6px; }
704
722
  .hv-bars { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 14px 14px 0; }
705
- .hv-bar .row { display: flex; justify-content: space-between; color: var(--faint); font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; }
723
+ .hv-bar .row { display: flex; justify-content: space-between; color: var(--muted); font-size: 12px; }
706
724
  .hv-bar .row b { color: var(--muted); font-weight: 500; letter-spacing: 0; }
707
725
  .hv-bar .track { height: 4px; background: var(--surface2); margin-top: 5px; border-radius: 2px; overflow: hidden; }
708
726
  .hv-bar .fill { display: block; height: 100%; background: var(--hue); }
@@ -712,14 +730,14 @@
712
730
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
713
731
  padding: 12px 14px 12px; margin-top: 12px; border-top: 1px solid var(--line);
714
732
  }
715
- .hv-foot .k { color: var(--faint); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; }
733
+ .hv-foot .k { color: var(--muted); font-size: 12px; }
716
734
  .hv-foot .v { font-size: 13px; margin-top: 2px; }
717
735
  .hv-foot .v.bad { color: var(--bad); }
718
736
  .hv-note { color: var(--faint); font-size: 11px; padding: 0 20px 24px; }
719
737
  .fm-sum { color: var(--muted); font-size: 12px; margin: 4px 0 14px; }
720
- .fm-award { margin: 0 0 18px; padding: 12px 14px; background: var(--surface); border-radius: 2px; }
738
+ .fm-award { margin: 0 0 18px; padding: 12px 14px; background: var(--surface); border: 1px solid var(--line); border-radius: 10px; }
721
739
  .fm-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
722
- .fm-title { font-family: var(--disp-font); font-size: 18px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; }
740
+ .fm-title { font-size: 16px; font-weight: 650; }
723
741
  .fm-blurb { color: var(--faint); font-size: 11.5px; flex: 1; min-width: 0; }
724
742
  .fm-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-top: 1px solid var(--line); min-width: 0; }
725
743
  .fm-head + .fm-row { border-top: none; margin-top: 6px; }
@@ -742,7 +760,7 @@
742
760
 
743
761
  .mc-agents .agents { max-height: 160px; overflow-y: auto; }
744
762
  .agents { padding: 4px 12px 6px; border-bottom: 1px solid var(--line); font-size: 11.5px; flex: none; }
745
- .agents .team { color: var(--faint); text-transform: uppercase; letter-spacing: 0.08em; font-size: 10.5px; margin-bottom: 2px; }
763
+ .agents .team { color: var(--muted); font-size: 12px; font-weight: 500; margin-bottom: 2px; }
746
764
  .agents .agent { display: flex; align-items: center; gap: 7px; line-height: 1.6; }
747
765
  .agents .swatch { width: 7px; height: 7px; border-radius: 50%; flex: none; }
748
766
  .agents .aname { color: var(--ink); }
@@ -771,10 +789,7 @@
771
789
  display: flex; align-items: baseline; gap: 10px;
772
790
  padding: 16px 22px 12px; border-bottom: 1px solid var(--line);
773
791
  }
774
- #drawer .d-head h2 {
775
- font-family: var(--disp-font);
776
- font-size: 17px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
777
- }
792
+ #drawer .d-head h2 { font-size: 17px; font-weight: 650; }
778
793
  #drawer .d-head .d-path {
779
794
  color: var(--faint); font-size: 11px;
780
795
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1;
@@ -782,15 +797,15 @@
782
797
  #drawer .d-actions { display: flex; gap: 2px; align-items: center; flex: none; }
783
798
  #drawer .d-close {
784
799
  border: none; background: none; color: var(--muted); cursor: pointer;
785
- font-size: 18px; padding: 2px 8px; border-radius: 2px;
800
+ font-size: 18px; padding: 2px 8px; border-radius: 6px;
786
801
  }
787
802
  #drawer .d-close:hover { background: var(--surface2); color: var(--ink); }
788
803
  #drawer .d-body { overflow-y: auto; padding: 6px 22px 40px; }
789
804
  .d-section { margin-top: 18px; }
790
805
  .d-section > summary {
791
806
  cursor: pointer; user-select: none; list-style: none;
792
- font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
793
- color: var(--faint); padding: 4px 0;
807
+ font-size: 13px; font-weight: 600;
808
+ color: var(--muted); padding: 4px 0;
794
809
  }
795
810
  .d-section > summary::before { content: '▸ '; }
796
811
  .d-section[open] > summary::before { content: '▾ '; }
@@ -804,7 +819,11 @@
804
819
  font-size: 12px; color: var(--accent); margin-bottom: 6px;
805
820
  }
806
821
  .d-sessions li { display: flex; align-items: center; gap: 8px;
807
- padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 12.5px; }
822
+ padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 13px; min-height: 36px; }
823
+ .d-sessions .s-title {
824
+ flex: 1; min-width: 0; overflow: hidden;
825
+ display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
826
+ }
808
827
  .d-sessions li:last-child { border-bottom: none; }
809
828
  .d-sessions { list-style: none; padding: 0; margin: 6px 0 0; }
810
829
 
@@ -820,7 +839,7 @@
820
839
  background: var(--surface2); padding: 1px 4px; border-radius: 4px;
821
840
  }
822
841
  .md pre {
823
- background: var(--surface2); border-radius: 2px; padding: 10px 12px;
842
+ background: var(--surface2); border-radius: 6px; padding: 10px 12px;
824
843
  overflow-x: auto; margin: 8px 0;
825
844
  }
826
845
  .md pre code { background: none; padding: 0; }
@@ -833,7 +852,7 @@
833
852
  /* ---------- session changes panel ---------- */
834
853
  .badge.changes { color: var(--accent); cursor: pointer; }
835
854
  #changes-panel { margin-top: 10px; }
836
- .d-section-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--faint); padding: 4px 0; }
855
+ .d-section-title { font-size: 13px; font-weight: 600; color: var(--muted); padding: 4px 0; }
837
856
  .chg-file { border: 1px solid var(--line); border-radius: 3px; margin-top: 8px; background: var(--surface); }
838
857
  .chg-head { display: flex; align-items: center; gap: 10px; padding: 8px 12px; cursor: pointer; font-size: 12.5px; }
839
858
  .chg-head .chg-path { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
@@ -927,13 +946,13 @@
927
946
  }
928
947
  #welcome h2 { font-size: 14px; margin-bottom: 8px; }
929
948
  #welcome h2 .tilde { color: var(--accent); }
930
- #welcome code { background: var(--surface2); padding: 1px 5px; border-radius: 2px; }
949
+ #welcome code { background: var(--surface2); padding: 1px 5px; border-radius: 6px; }
931
950
  #welcome p { color: var(--muted); font-size: 12.5px; }
932
951
 
933
952
  #toast {
934
953
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
935
954
  background: var(--ink); color: var(--bg);
936
- padding: 7px 14px; border-radius: 2px; font-size: 12.5px;
955
+ padding: 7px 14px; border-radius: 6px; font-size: 12.5px;
937
956
  opacity: 0; transition: opacity 0.18s; pointer-events: none;
938
957
  }
939
958
  #toast.show { opacity: 1; }
@@ -941,19 +960,22 @@
941
960
  /* ---------- phones: everything in one column, nothing scrolls sideways ---------- */
942
961
  @media (max-width: 700px) {
943
962
  header { padding: 10px 16px; gap: 8px 10px; }
944
- header h1 { font-size: 16px; }
945
- #search { flex: 1 1 90px; width: auto; min-width: 0; margin-left: 0; }
963
+ header h1 { font-size: 15px; margin-right: auto; }
964
+ #search { order: 9; flex: 1 1 100%; width: auto; min-width: 0; margin-left: 0; }
946
965
  header .spacer, #open-pref-wrap { display: none; } /* opening terminals is a desk thing; still in settings */
947
966
  #quota { order: 10; flex: 1 1 100%; flex-wrap: wrap; gap: 8px 14px; }
948
967
  .meter .bar { width: 52px; }
949
968
  #live { padding: 12px 16px; }
950
969
  main { padding: 14px 16px; }
951
- .dep-row { grid-template-columns: 44px 1fr; padding: 8px 12px; }
952
- .dep-proj { font-size: 17px; }
970
+ .dep-row { grid-template-columns: 1fr; padding: 10px 12px; }
971
+ .dep-proj { font-size: 15px; }
953
972
  .dep-mid, .dep-right { grid-column: 1 / -1; }
954
973
  .dep-right { justify-self: stretch; flex-wrap: wrap; gap: 6px 10px; }
955
974
  .dep-title, .dep-reason { white-space: normal; overflow-wrap: anywhere; }
956
975
  #pinned .pin-row { flex-wrap: wrap; padding: 7px 12px; }
976
+ .digest-item .di-top { flex-wrap: wrap; row-gap: 2px; }
977
+ .digest-item .di-proj { max-width: none; flex: 1 1 auto; }
978
+ .digest-item .di-title { order: 9; flex: 1 1 100%; }
957
979
  #git-attn .ga-item { white-space: normal; }
958
980
  #drawer { width: 100vw; border-left: none; }
959
981
  #drawer .d-head { flex-wrap: wrap; padding: 12px 16px 10px; }
@@ -980,8 +1002,8 @@
980
1002
  <body>
981
1003
  <header>
982
1004
  <div id="conn" title="connection"></div>
983
- <h1>Claude<span class="tilde"> · </span>Mission Control</h1>
984
- <input id="search" type="search" placeholder="Search… ⏎" autocomplete="off">
1005
+ <h1>Claude Mission Control</h1>
1006
+ <input id="search" type="search" placeholder="Search sessions" aria-label="Search sessions" autocomplete="off">
985
1007
  <div class="spacer"></div>
986
1008
  <label id="open-pref-wrap"><span class="open-label">Open in</span>
987
1009
  <select id="open-pref" aria-label="Open sessions in">
@@ -990,10 +1012,10 @@
990
1012
  </label>
991
1013
  <div id="quota"></div>
992
1014
  <span id="clock" class="flap" title="board time"></span>
993
- <button id="mc-btn" title="Mission Control — every live session at once">▦</button>
994
- <button id="hive-btn" title="Hive: every live session as a character card">⬢</button>
995
- <button id="bell-btn" title="Catch-up — what happened while you were away">🔔<span id="bell-badge" hidden></span></button>
996
- <button id="gear" title="Settings">⚙</button>
1015
+ <button id="mc-btn" class="hd-btn" title="Mission Control: every live session side by side" aria-label="Mission Control"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="2.5" width="5" height="5" rx="1"/><rect x="9" y="2.5" width="5" height="5" rx="1"/><rect x="2" y="9.5" width="5" height="5" rx="1"/><rect x="9" y="9.5" width="5" height="5" rx="1"/></svg></button>
1016
+ <button id="hive-btn" class="hd-btn" title="Hive: every live session as a character card" aria-label="Hive"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 1.8 13.4 4.9v6.2L8 14.2 2.6 11.1V4.9Z"/></svg></button>
1017
+ <button id="bell-btn" class="hd-btn" title="Catch up on what happened while you were away" aria-label="Catch up"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 11V7a4 4 0 0 1 8 0v4l1.2 1.5H2.8Z"/><path d="M6.5 14a1.6 1.6 0 0 0 3 0"/></svg><span id="bell-badge" hidden></span></button>
1018
+ <button id="gear" class="hd-btn" title="Settings" aria-label="Settings"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="8" cy="8" r="2.2"/><path d="M8 1.5v2M8 12.5v2M1.5 8h2M12.5 8h2M3.4 3.4l1.4 1.4M11.2 11.2l1.4 1.4M3.4 12.6l1.4-1.4M11.2 4.8l1.4-1.4"/></svg></button>
997
1019
  </header>
998
1020
 
999
1021
  <section id="live"></section>
@@ -1002,13 +1024,14 @@
1002
1024
  <div id="git-attn" hidden></div>
1003
1025
  <details id="digest" open>
1004
1026
  <summary>
1005
- <span id="digest-label">Digest</span>
1006
- <span id="digest-range" role="group" aria-label="digest window">
1007
- <button data-days="1">day</button><button data-days="3">3 days</button><button data-days="7">week</button>
1027
+ <span class="sec-head"><span class="caret">▶</span><span id="digest-label">Recent sessions</span><span class="n" id="digest-n"></span></span>
1028
+ <span id="digest-range" role="group" aria-label="How far back">
1029
+ <button data-days="1">Today</button><button data-days="3">3 days</button><button data-days="7">Week</button>
1008
1030
  </span>
1009
1031
  </summary>
1010
1032
  <div id="digest-body"></div>
1011
1033
  </details>
1034
+ <div class="sec-head" id="grid-head" hidden>Projects <span class="n"></span></div>
1012
1035
  <div id="grid"></div>
1013
1036
  <details id="dormant" hidden>
1014
1037
  <summary></summary>
@@ -1155,7 +1178,7 @@ function meter(label, pct, title, extra = '') {
1155
1178
  return `<div class="meter" title="${esc(title || '')}">
1156
1179
  <span>${esc(label)}</span>
1157
1180
  <span class="bar"><span class="fill ${cls}" style="width:${Math.min(100, pct)}%"></span></span>
1158
- <span>${Math.round(pct)}%</span>${extra}
1181
+ <span class="m-pct">${Math.round(pct)}%</span>${extra}
1159
1182
  </div>`;
1160
1183
  }
1161
1184
 
@@ -1218,6 +1241,11 @@ function modelShort(m) {
1218
1241
  return m.replace(/^claude-/, '').replace(/-\d{8}$/, '');
1219
1242
  }
1220
1243
 
1244
+ // Tooltip for a clickable session title; the model rides along instead of a chip.
1245
+ function titleTip(m, action = 'Click to read the transcript') {
1246
+ return m ? `${modelShort(m)}. ${action}` : action;
1247
+ }
1248
+
1221
1249
  function modelChip(m) {
1222
1250
  return m ? `<span class="badge" title="${esc(m)}">${esc(modelShort(m))}</span>` : '';
1223
1251
  }
@@ -1265,7 +1293,7 @@ function noteMark(sess) {
1265
1293
 
1266
1294
  function openBtn(sessionId) {
1267
1295
  if (liveIds.has(sessionId)) return '';
1268
- return `<button class="copy open-btn" data-open="${esc(sessionId)}" title="Open this session">open ⬈</button>`;
1296
+ return `<button class="copy open-btn" data-open="${esc(sessionId)}" title="Open this session">open</button>`;
1269
1297
  }
1270
1298
 
1271
1299
  // "Δ n" — how many files Claude edited in this session. Opens the changes panel.
@@ -1325,16 +1353,14 @@ function liveCard(s) {
1325
1353
  ? ` <span class="badge bg" title="${BG_TIP}">BG</span>`
1326
1354
  : s.isWorktree ? ' <span class="badge">worktree</span>' : '';
1327
1355
  return `<div class="dep-row ${s.status === 'waiting' ? 'waiting' : ''}">
1328
- <span class="dep-time" title="session started">${esc(dep)}</span>
1329
- <span class="dep-proj disp">${esc(s.projectName)}${kindBadge}</span>
1356
+ <span class="dep-proj" title="Started at ${esc(dep)}">${esc(s.projectName)}${kindBadge}</span>
1330
1357
  <div class="dep-mid">
1331
- <div class="dep-title" data-session="${esc(s.sessionId)}" title="Click to watch the transcript live">${esc(s.title || '')}</div>
1358
+ <div class="dep-title" data-session="${esc(s.sessionId)}" title="${esc(titleTip(s.model, 'Click to watch the transcript live'))}">${esc(s.title || '')}</div>
1332
1359
  ${task}
1333
1360
  ${reason}
1334
1361
  ${bgDetail}
1335
1362
  </div>
1336
1363
  <div class="dep-right">
1337
- ${modelChip(s.model)}
1338
1364
  ${s.estCost != null ? `<span class="dep-cost">${costChip(s.estCost, { cls: 'dep-cost-main', assumed: s.assumed })}${
1339
1365
  s.burnRate ? `<span class="dep-burn" title="Spend per hour over the last 30 minutes">$${s.burnRate}/h</span>` : ''}</span>` : ''}
1340
1366
  ${contextMeter(s.context)}
@@ -1342,8 +1368,7 @@ function liveCard(s) {
1342
1368
  ? `<span class="dep-elapsed overdue" title="No reply for ${s.waitingMin} minutes — session started ${elapsed(s.startedAt)} ago">${waitLabel(s.waitingMin)}</span>`
1343
1369
  : `<span class="dep-elapsed">${elapsed(s.startedAt)}</span>`}
1344
1370
  ${statusFlap(s)}
1345
- ${renameBtn(s.sessionId, s.title)}
1346
- ${copyBtn(s.resumeCommand)}
1371
+ <span class="acts">${renameBtn(s.sessionId, s.title)}${copyBtn(s.resumeCommand)}</span>
1347
1372
  </div>
1348
1373
  </div>`;
1349
1374
  }
@@ -1352,26 +1377,23 @@ function projectCard(p) {
1352
1377
  const sessions = p.sessions.length
1353
1378
  ? `<ul class="sessions">${p.sessions.map((sess) => `
1354
1379
  <li>
1355
- <span class="s-title" data-session="${esc(sess.sessionId)}" title="Click to read the transcript">${
1380
+ <span class="s-title" data-session="${esc(sess.sessionId)}" title="${esc(titleTip(sess.model))}">${
1356
1381
  sess.worktree ? `<span class="wt mono">⎇ ${esc(sess.worktree)}</span>` : ''}${esc(sess.title)}</span>${noteMark(sess)}
1357
- ${modelChip(sess.model)}
1358
1382
  ${changesChip(sess)}
1359
1383
  <span class="s-when">${relTime(sess.lastActivityAt)}</span>
1360
- ${renameBtn(sess.sessionId, sess.title)}
1361
- ${openBtn(sess.sessionId)}
1362
- ${copyBtn(sess.resumeCommand)}
1384
+ <span class="acts">${renameBtn(sess.sessionId, sess.title)}${openBtn(sess.sessionId)}${copyBtn(sess.resumeCommand)}</span>
1363
1385
  </li>`).join('')}</ul>`
1364
1386
  : '<div class="none-yet">No sessions recorded.</div>';
1365
1387
  return `<div class="card">
1366
1388
  <div class="head">
1367
1389
  ${p.isLive ? '<span class="live-dot" title="session running"></span>' : ''}
1368
1390
  <span class="name" data-detail="${esc(p.path)}" style="cursor:pointer" title="Click for project details">${esc(p.name)}</span>
1369
- <button class="copy" data-new="${esc(p.path)}" title="Start a new Claude session here (Ghostty)">⊕</button>
1391
+ <button class="copy new-btn" data-new="${esc(p.path)}" title="Start a new Claude session here" aria-label="New session in ${esc(p.name)}">+</button>
1370
1392
  ${sparkSVG(p.activity.counts)}
1371
1393
  </div>
1372
1394
  <div class="meta">
1373
1395
  ${gitBadges(p.git, p.missing)}
1374
- ${costChip(p.spend7d, { cls: 'badge', after: '/7d' })}
1396
+ ${costChip(p.spend7d, { cls: 'badge', after: ' in 7d' })}
1375
1397
  <span class="when" title="${esc(p.path)}">${relTime(p.lastActivityAt)}</span>
1376
1398
  </div>
1377
1399
  ${sessions}
@@ -1383,16 +1405,14 @@ function renderPinned(state) {
1383
1405
  const pins = state.pinned || [];
1384
1406
  el.hidden = !pins.length;
1385
1407
  if (!pins.length) { patch(el, ''); return; }
1386
- patch(el, `<div class="pin-label">Pinned</div>` + pins.map((p) => `
1408
+ patch(el, `<div class="sec-head">Pinned <span class="n">${pins.length}</span></div>` + pins.map((p) => `
1387
1409
  <div class="pin-row">
1388
1410
  <span class="star">★</span>
1389
- <span class="s-title" data-session="${esc(p.sessionId)}" title="Click to read the transcript">${esc(p.title)}</span>${noteMark(p)}
1390
- ${modelChip(p.model)}
1411
+ <span class="s-title" data-session="${esc(p.sessionId)}" title="${esc(titleTip(p.model))}">${esc(p.title)}</span>${noteMark(p)}
1391
1412
  ${changesChip(p)}
1392
1413
  <span class="s-when">${esc(p.projectName)}</span>
1393
1414
  <span class="s-when">${relTime(p.lastActivityAt)}</span>
1394
- ${renameBtn(p.sessionId, p.title)}
1395
- <button class="copy" data-pin="${esc(p.sessionId)}" title="Unpin">unpin</button>
1415
+ <span class="acts">${renameBtn(p.sessionId, p.title)}<button class="copy" data-pin="${esc(p.sessionId)}" title="Unpin">unpin</button></span>
1396
1416
  </div>`).join(''));
1397
1417
  }
1398
1418
 
@@ -1420,7 +1440,7 @@ function renderGitAttention(state) {
1420
1440
  const plural = (n, w) => `${n} ${w}${n === 1 ? '' : 's'}`;
1421
1441
  el.hidden = false;
1422
1442
  patch(el,
1423
- `<span class="ga-label">Unpushed work — ${[items.length && plural(items.length, 'repo'), atRisk.length && plural(atRisk.length, 'worktree')].filter(Boolean).join(', ')}</span>` +
1443
+ `<span class="ga-label">Unpushed work in ${[items.length && plural(items.length, 'repo'), atRisk.length && plural(atRisk.length, 'worktree')].filter(Boolean).join(', ')}</span>` +
1424
1444
  items.map((it) => `<span class="ga-item">${esc(it.name)}${
1425
1445
  it.changes ? `<span class="badge dirty" title="${it.changes} uncommitted/untracked files">●${it.changes}</span>` : ''}${
1426
1446
  it.ahead ? `<span class="badge ahead" title="${it.ahead} commits not pushed">↑${it.ahead}</span>` : ''}</span>`).join('') +
@@ -1469,14 +1489,13 @@ function digestItem(it) {
1469
1489
  return `<div class="digest-item">
1470
1490
  <div class="di-top">
1471
1491
  <span class="di-proj">${esc(it.project)}</span>
1472
- <span class="di-title" data-session="${esc(it.sessionId)}" title="Click to read the transcript">${it.worktree ? `<span class="wt mono">⎇</span> ` : ''}${esc(it.title)}</span>${noteMark(it)}
1492
+ <span class="di-title" data-session="${esc(it.sessionId)}" title="${esc(titleTip(it.model))}">${it.worktree ? `<span class="wt mono">⎇</span> ` : ''}${esc(it.title)}</span>${noteMark(it)}
1473
1493
  ${job ? `<span class="badge bg" title="${BG_TIP}">BG</span>` : ''}
1474
1494
  ${running ? '<span class="flap disp st st-busy">running</span>' : ''}
1475
- ${modelChip(it.model)}
1476
1495
  ${changesChip(it)}
1477
1496
  ${costChip(it.estCost, { cls: 'di-when', assumed: it.assumed })}
1478
1497
  <span class="di-when">${time}</span>
1479
- ${openBtn(it.sessionId)}
1498
+ <span class="acts">${openBtn(it.sessionId)}</span>
1480
1499
  </div>
1481
1500
  ${summary ? `<div class="di-summary" title="Click to expand">${esc(summary)}</div>` : ''}
1482
1501
  ${total ? `<div class="di-tasks"><span class="done">${t.completed}</span>/${total} tasks done${
@@ -1488,12 +1507,13 @@ function digestItem(it) {
1488
1507
  function renderDigest(state) {
1489
1508
  const items = digestEntries(state);
1490
1509
  const label = $('#digest-label');
1491
- label.textContent = `Digest — ${items.length} session${items.length === 1 ? '' : 's'}`;
1510
+ label.textContent = 'Recent sessions';
1511
+ $('#digest-n').textContent = items.length || '';
1492
1512
  for (const b of document.querySelectorAll('#digest-range button')) {
1493
1513
  b.classList.toggle('sel', Number(b.dataset.days) === digestDays);
1494
1514
  }
1495
1515
  if (!items.length) {
1496
- patch($('#digest-body'), `<div class="digest-empty">Quiet — no sessions in the last ${
1516
+ patch($('#digest-body'), `<div class="digest-empty">No sessions in the last ${
1497
1517
  digestDays === 1 ? 'day' : digestDays + ' days'}.</div>`);
1498
1518
  return;
1499
1519
  }
@@ -1536,17 +1556,17 @@ function render(state) {
1536
1556
  : '';
1537
1557
  const b = state.budget;
1538
1558
  const budgetMeter = b
1539
- ? meter('budget', (b.spent / b.limit) * 100, `≈$${b.spent.toFixed(0)} of your $${b.limit} weekly budget (7-day estimate)`)
1559
+ ? meter('Budget', (b.spent / b.limit) * 100, `≈$${b.spent.toFixed(0)} of your $${b.limit} weekly budget (7-day estimate)`)
1540
1560
  : '';
1541
1561
  const spendChip = planChip + (fmtCost(spend)
1542
- ? `${weeklyChart(state.weeklyCost)}${costChip(spend, { cls: '', before: '7d ' })}`
1562
+ ? `<span class="q-spend">${weeklyChart(state.weeklyCost)}${costChip(spend, { cls: 'num' })}<span>in 7 days</span></span>`
1543
1563
  : '') + budgetMeter;
1544
1564
  if (q) {
1545
1565
  qEl.className = q.stale ? 'stale' : '';
1546
1566
  patch(qEl, spendChip +
1547
- (q.utilization != null ? forecastMeter('session', q.utilization, q.resetsAt, state.forecast && state.forecast.session) : '') +
1548
- (q.weeklyUtilization != null ? forecastMeter('week', q.weeklyUtilization, q.weeklyResetsAt, state.forecast && state.forecast.week) : '') +
1549
- (q.costUsed != null && q.costLimit ? `<span title="extra usage">$${q.costUsed.toFixed(0)}/$${q.costLimit.toFixed(0)}</span>` : ''));
1567
+ (q.utilization != null ? forecastMeter('Session', q.utilization, q.resetsAt, state.forecast && state.forecast.session) : '') +
1568
+ (q.weeklyUtilization != null ? forecastMeter('Week', q.weeklyUtilization, q.weeklyResetsAt, state.forecast && state.forecast.week) : '') +
1569
+ (q.costUsed != null && q.costLimit ? `<span title="Extra usage spent this month, of your limit">Extra <span class="num" style="color:var(--ink)">$${q.costUsed.toFixed(0)}</span> of $${q.costLimit.toFixed(0)}</span>` : ''));
1550
1570
  } else {
1551
1571
  qEl.className = '';
1552
1572
  patch(qEl, spendChip);
@@ -1555,7 +1575,7 @@ function render(state) {
1555
1575
  // live rail
1556
1576
  const live = state.liveSessions || [];
1557
1577
  patch($('#live'),
1558
- `<div class="rail-label">Departures — ${live.length || 'none'} running</div>` +
1578
+ `<div class="sec-head">Running now${live.length ? ` <span class="n">${live.length}</span>` : ''}</div>` +
1559
1579
  (live.length
1560
1580
  ? `<div class="rows">${live.map(liveCard).join('')}</div>`
1561
1581
  : `<div class="live-none">No sessions running. Start one with <code class="mono">claude</code> in any project.</div>`));
@@ -1583,7 +1603,10 @@ function render(state) {
1583
1603
  </div>`);
1584
1604
  const d = $('#dormant');
1585
1605
  d.hidden = dormant.length === 0;
1586
- $('summary', d).textContent = `Dormant — ${dormant.length} project${dormant.length === 1 ? '' : 's'}`;
1606
+ patch($('summary', d), `<span class="sec-head"><span class="caret">▶</span>Dormant projects <span class="n">${dormant.length}</span></span>`);
1607
+ const gh = $('#grid-head');
1608
+ gh.hidden = !active.length;
1609
+ $('.n', gh).textContent = active.length;
1587
1610
  patch($('.cards', d), dormant.map(projectCard).join(''));
1588
1611
 
1589
1612
  // tab title = attention signal
@@ -1618,6 +1641,7 @@ async function loadOpenPref() {
1618
1641
  const opts = [`<option value="terminal">${esc(c.resolvedTerminal.label)}</option>`];
1619
1642
  if (c.claudeApp) opts.push('<option value="app">Claude app</option>');
1620
1643
  prefEl.innerHTML = opts.join('');
1644
+ $('#open-pref-wrap').hidden = opts.length < 2;
1621
1645
  const stored = localStorage.getItem('openTarget') || 'terminal';
1622
1646
  prefEl.value = stored === 'app' && !c.claudeApp ? 'terminal' : stored;
1623
1647
  } catch {
@@ -1830,14 +1854,12 @@ function renderDetail(d, name) {
1830
1854
  const sessions = d.sessions.length
1831
1855
  ? `<ul class="d-sessions">${d.sessions.map((s) => `
1832
1856
  <li>
1833
- <span class="s-title" data-session="${esc(s.sessionId)}" title="Click to read the transcript">${
1857
+ <span class="s-title" data-session="${esc(s.sessionId)}" title="${esc(titleTip(s.model))}">${
1834
1858
  s.worktree ? `<span class="wt mono">⎇ ${esc(s.worktree)}</span> ` : ''}${esc(s.title)}</span>${noteMark(s)}
1835
1859
  ${changesChip(s)}
1836
1860
  ${costChip(s.estCost, { assumed: s.assumed })}
1837
1861
  <span class="s-when">${relTime(s.lastActivityAt)}</span>
1838
- ${renameBtn(s.sessionId, s.title)}
1839
- ${openBtn(s.sessionId)}
1840
- ${copyBtn(s.resumeCommand)}
1862
+ <span class="acts">${renameBtn(s.sessionId, s.title)}${openBtn(s.sessionId)}${copyBtn(s.resumeCommand)}</span>
1841
1863
  </li>`).join('')}</ul>`
1842
1864
  : null;
1843
1865
  const caps = [...d.skills, ...d.agents.map((a) => ({ ...a, name: `agent: ${a.name}` })),