daily-focus 1.2.0-dev.9 → 2.0.0-dev.15

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 +18 -4
  2. package/SETUP.md +156 -105
  3. package/dist/{audit-DNTFZOHH.js → audit-AQUBVWPA.js} +4 -3
  4. package/dist/{chunk-KZNY45XW.js → chunk-72NUDSOV.js} +126 -119
  5. package/dist/{chunk-GQ3NCWRT.js → chunk-ITUK7XKS.js} +6 -19
  6. package/dist/{chunk-KL6RU4XT.js → chunk-JTMBBUMD.js} +316 -10
  7. package/dist/chunk-QG4XXKBP.js +18 -0
  8. package/dist/chunk-U6EPOXEW.js +570 -0
  9. package/dist/{chunk-P3E2B2SD.js → chunk-WPXIQPYX.js} +1 -1
  10. package/dist/{chunk-6SMUSPZG.js → chunk-YPGKXTBX.js} +2 -2
  11. package/dist/cli.js +19 -12
  12. package/dist/{demo-TIIXODJG.js → demo-KE6WDWMA.js} +159 -37
  13. package/dist/{init-XDMAXU2S.js → init-5KJVHWJU.js} +41 -6
  14. package/dist/{seed-TWT7EDXJ.js → seed-T4VEY6DT.js} +4 -3
  15. package/dist/{server-WT4CQ3VX.js → server-FFRNYEAO.js} +2000 -743
  16. package/dist/{service-ZUHI3VKH.js → service-LQ46YRCZ.js} +7 -6
  17. package/package.json +6 -2
  18. package/prompts/README.md +20 -4
  19. package/prompts/assistant.md +7 -1
  20. package/prompts/morning-brief-personal.md +37 -0
  21. package/prompts/morning-brief-work.md +37 -0
  22. package/prompts/onboarding.md +41 -0
  23. package/public/app.js +806 -287
  24. package/public/fonts/IBMPlexSans-Variable.woff2 +0 -0
  25. package/public/fonts/IBMPlexSerif-Italic.woff2 +0 -0
  26. package/public/fonts/IBMPlexSerif-Medium.woff2 +0 -0
  27. package/public/fonts/IBMPlexSerif-Regular.woff2 +0 -0
  28. package/public/fonts/IBMPlexSerif-SemiBold.woff2 +0 -0
  29. package/public/fonts/OFL.txt +93 -0
  30. package/public/style.css +1686 -481
  31. package/dist/chunk-V2UN3JYL.js +0 -140
package/public/style.css CHANGED
@@ -1,18 +1,75 @@
1
1
  /*
2
- * Tokens come from the validated reference palette: the eight categorical hues
3
- * carry source identity, the four status colours are reserved for state only.
4
- * Both modes are selected, not flipped — dark has its own steps.
2
+ * The page is a day-book: one page for one day. The date is its masthead, the
3
+ * objective its headline, the agenda a ruled timeline in the margin. Prose —
4
+ * the objective, the agent's headline, a court's hint — is written straight on
5
+ * the paper. Anything tabular — a list of rows, the day's numbers, the
6
+ * timeline, a settings group — sits on a white sheet with an edge, and the
7
+ * rows on a sheet are ruled apart. That edge is what tells one block from the
8
+ * next; the first cut of this design ruled everything on the paper alone, and
9
+ * where a row ended was anyone's guess.
10
+ *
11
+ * Two faces, each with a job. The words the brief is made of — the date, the
12
+ * objective, the agent's headline, its reports and the assistant's answers,
13
+ * setup's questions — are set in Plex Serif, the face for reading. Everything
14
+ * operational — rows, meta, pills, controls, times — is Plex Sans. Both are
15
+ * served from `fonts/`, since this dashboard is private and may be offline, and
16
+ * nothing it shows should fetch from a third party on every open.
17
+ *
18
+ * The masthead is a band of navy across the top of every page: the date, the
19
+ * readout and the tabs, and on Today the objective, the day's numbers and the
20
+ * agent's note too, since those are the morning's masthead as much as the date
21
+ * is. Amber is the one accent, for what can be pressed: the selected tab, the
22
+ * primary button, the pressed gear, the rank of a row. The eight source hues
23
+ * carry source identity and the four status colours are reserved for state, so
24
+ * a coloured thing on the paper is a fact about the content or a thing to press.
25
+ * A blue accent used to compete with GitHub's blue for the same job.
26
+ *
27
+ * Both modes are selected, not flipped — dark has its own steps. Each token
28
+ * names both and `light-dark()` picks one, so the dark palette lives here and
29
+ * nowhere else; a second hand-kept copy inside a `prefers-color-scheme` block
30
+ * used to drift from this one with nothing to notice.
5
31
  *
6
32
  * Source colour is never the only cue: every dot sits beside its source name in
7
33
  * text, which is what lets the lighter light-mode hues (aqua, yellow, magenta)
8
34
  * sit below 3:1 contrast without losing meaning.
9
- *
10
- * Each token names both its steps and `light-dark()` picks one, so the dark
11
- * palette lives here and nowhere else. It used to be a second, hand-kept copy of
12
- * this list inside a `prefers-color-scheme` block — twenty-two values one edit
13
- * away from disagreeing with the ones above them, with nothing to notice.
14
35
  */
15
36
 
37
+ @font-face {
38
+ font-family: 'Plex Sans';
39
+ src: url('/fonts/IBMPlexSans-Variable.woff2') format('woff2');
40
+ font-weight: 100 700;
41
+ font-style: normal;
42
+ font-display: swap;
43
+ }
44
+ @font-face {
45
+ font-family: 'Plex Serif';
46
+ src: url('/fonts/IBMPlexSerif-Regular.woff2') format('woff2');
47
+ font-weight: 400;
48
+ font-style: normal;
49
+ font-display: swap;
50
+ }
51
+ @font-face {
52
+ font-family: 'Plex Serif';
53
+ src: url('/fonts/IBMPlexSerif-Medium.woff2') format('woff2');
54
+ font-weight: 500;
55
+ font-style: normal;
56
+ font-display: swap;
57
+ }
58
+ @font-face {
59
+ font-family: 'Plex Serif';
60
+ src: url('/fonts/IBMPlexSerif-SemiBold.woff2') format('woff2');
61
+ font-weight: 600;
62
+ font-style: normal;
63
+ font-display: swap;
64
+ }
65
+ @font-face {
66
+ font-family: 'Plex Serif';
67
+ src: url('/fonts/IBMPlexSerif-Italic.woff2') format('woff2');
68
+ font-weight: 400;
69
+ font-style: italic;
70
+ font-display: swap;
71
+ }
72
+
16
73
  :root {
17
74
  /*
18
75
  * Both keywords, which is the state the toggle calls "system": `light-dark()`
@@ -21,22 +78,41 @@
21
78
  */
22
79
  color-scheme: light dark;
23
80
 
24
- --page: light-dark(#f9f9f7, #0d0d0d);
25
- --surface: light-dark(#fcfcfb, #1a1a19);
26
- --surface-sunken: light-dark(#f2f1ed, #131312);
27
- --ink-1: light-dark(#0b0b0b, #ffffff);
28
- --ink-2: light-dark(#52514e, #c3c2b7);
29
- --ink-3: #898781; /* Shared deliberately: the muted step clears both pages. */
30
- --hairline: light-dark(#e1e0d9, #2c2c2a);
31
- --border: light-dark(rgba(11, 11, 11, 0.1), rgba(255, 255, 255, 0.1));
81
+ --page: light-dark(#f2f1ec, #0f1012);
82
+ --surface: light-dark(#ffffff, #1e2025);
83
+ --surface-sunken: light-dark(#eceae4, #2a2c32);
84
+ --ink-1: light-dark(#1b1f2a, #e9ebef);
85
+ --ink-2: light-dark(#4d5362, #aeb4c0);
86
+ --ink-3: light-dark(#6e7484, #868c9a);
87
+ /* A rule between rows on a sheet, and a rule on the paper: the paper's is darker, to show at all. */
88
+ --rule: light-dark(#e6e5df, #2e3037);
89
+ --hairline: light-dark(#d7d6ce, #33353c);
90
+ --border: light-dark(rgba(27, 31, 42, 0.2), rgba(233, 235, 239, 0.16));
91
+
92
+ /*
93
+ * The band. Navy in both modes: in light it is the dark thing on a light
94
+ * page, in dark the blue thing on a near-black one, so hue carries it where
95
+ * lightness can't. Its own steps for text and rules, since nothing on it is
96
+ * the paper's ink.
97
+ */
98
+ --band: light-dark(#1c2541, #1a2140);
99
+ --band-ink: #ffffff;
100
+ --band-muted: light-dark(#a9b3cc, #9aa4c3);
101
+ --band-rule: rgba(255, 255, 255, 0.18);
102
+ --band-sheet: rgba(255, 255, 255, 0.07);
103
+ --band-critical: #ffb3b3;
104
+ --band-good: #7ee2a8;
32
105
  /*
33
106
  * Dark wants no shadow at all. Written as transparent steps rather than as a
34
107
  * `none` somewhere else, because anywhere else means a selector that knows
35
108
  * which mode it is in — and that is the duplicate copy coming back for one
36
109
  * property.
37
110
  */
38
- --shadow: 0 1px 2px light-dark(rgba(11, 11, 11, 0.05), transparent),
39
- 0 4px 16px light-dark(rgba(11, 11, 11, 0.04), transparent);
111
+ --shadow: 0 1px 2px light-dark(rgba(27, 31, 42, 0.05), transparent),
112
+ 0 6px 20px light-dark(rgba(27, 31, 42, 0.06), transparent);
113
+ /* The panel and the menus float, so they cast more. */
114
+ --shadow-float: 0 1px 2px light-dark(rgba(27, 31, 42, 0.06), transparent),
115
+ 0 14px 40px light-dark(rgba(27, 31, 42, 0.14), rgba(0, 0, 0, 0.5));
40
116
 
41
117
  --good: #0ca30c;
42
118
  --warning: #fab219;
@@ -55,15 +131,24 @@
55
131
  --src-reminders: light-dark(#8a5a2b, #c89058);
56
132
  --src-messages: light-dark(#9b3fc0, #c07ae8);
57
133
  --src-eboks: light-dark(#c42b3a, #e5535f);
58
- --src-other: #898781;
134
+ --src-other: #7d8392;
59
135
 
60
- --accent: light-dark(#2a78d6, #3987e5);
61
- --accent-wash: light-dark(#e8f1fd, #14263a);
62
- --focus-ring: light-dark(#2a78d6, #3987e5);
136
+ /*
137
+ * Amber, for what can be pressed. As a fill it carries dark text; as text on
138
+ * the paper it is darkened until it clears the page, which `--accent-ink` is.
139
+ */
140
+ --accent: #e0962a;
141
+ --accent-ink: light-dark(#a86a14, #e8a743);
142
+ --on-accent: #1b1f2a;
143
+ --accent-wash: light-dark(#fbefd9, #3a3220);
144
+ --focus-ring: var(--ink-1);
63
145
 
64
146
  --radius: 10px;
65
147
  --radius-sm: 6px;
66
- --font: system-ui, -apple-system, 'Segoe UI', sans-serif;
148
+ --page-width: 1180px;
149
+ --font: 'Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
150
+ --font-serif: 'Plex Serif', 'Iowan Old Style', Georgia, serif;
151
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
67
152
  }
68
153
 
69
154
  /*
@@ -86,22 +171,23 @@
86
171
 
87
172
  /*
88
173
  * The UA stylesheet's `[hidden] { display: none }` loses to any class that sets
89
- * display, so `.toast` rendered as an empty box
90
- * while "hidden". Assert it once here rather than remembering per component.
174
+ * display, so `.toast` rendered as an empty box while "hidden". Assert it once
175
+ * here rather than remembering per component.
91
176
  */
92
177
  [hidden] {
93
178
  display: none !important;
94
179
  }
95
180
 
96
181
  body {
182
+ --gutter: clamp(16px, 4vw, 48px);
97
183
  margin: 0;
98
- padding: 0 clamp(16px, 4vw, 40px) 64px;
99
184
  background: var(--page);
100
185
  color: var(--ink-1);
101
186
  font-family: var(--font);
102
- font-size: 15px;
187
+ font-size: 14.5px;
103
188
  line-height: 1.5;
104
189
  -webkit-font-smoothing: antialiased;
190
+ text-rendering: optimizeLegibility;
105
191
  }
106
192
 
107
193
  :focus-visible {
@@ -110,10 +196,15 @@ body {
110
196
  border-radius: 3px;
111
197
  }
112
198
 
199
+ /* Links are ink, told apart by the underline alone; it darkens under the pointer. */
113
200
  a {
114
- color: var(--accent);
201
+ color: var(--ink-1);
202
+ text-decoration-color: var(--ink-3);
115
203
  text-underline-offset: 2px;
116
204
  }
205
+ a:hover {
206
+ text-decoration-color: currentColor;
207
+ }
117
208
 
118
209
  .skip-link {
119
210
  position: absolute;
@@ -129,50 +220,104 @@ a {
129
220
  border-radius: var(--radius-sm);
130
221
  }
131
222
 
223
+ /*
224
+ * The page's margins are the root's padding, not the body's, so that the root
225
+ * spans the viewport: the band paints a viewport past each edge of the page,
226
+ * and the root clips it at the viewport's. Not on `body`, whose overflow would
227
+ * be handed to the viewport and clip nothing itself; and `clip` rather than
228
+ * `hidden`, which would make this a scroll container and unstick the agenda.
229
+ */
230
+ #app {
231
+ padding: 0 var(--gutter) 72px;
232
+ overflow-x: clip;
233
+ }
234
+
235
+ /* ---------- the band ---------- */
236
+
237
+ /*
238
+ * The band behind the masthead, painted by a pseudo-element that runs a
239
+ * viewport past each edge, since the page's own margins keep the content in.
240
+ * Behind the content at `z-index: -1`, which in the root stacking context is
241
+ * above the page colour and below everything in flow — so a sheet that sits on
242
+ * it, like the agenda's, is simply drawn on top. On Today the morning's
243
+ * masthead paints its own band all the way up to the top of the page, so the
244
+ * banners between the tabs and the objective sit on navy however many there
245
+ * are, and there is no seam for them to fall through.
246
+ */
247
+ .band {
248
+ position: relative;
249
+ color: var(--band-ink);
250
+ }
251
+ .band::before,
252
+ .today__masthead::before {
253
+ content: '';
254
+ position: absolute;
255
+ top: 0;
256
+ bottom: 0;
257
+ left: -100vw;
258
+ right: -100vw;
259
+ background: var(--band);
260
+ z-index: -1;
261
+ }
262
+ .band :focus-visible,
263
+ .today__masthead :focus-visible {
264
+ outline-color: var(--band-ink);
265
+ }
266
+
132
267
  /* ---------- header ---------- */
133
268
 
269
+ /*
270
+ * The masthead. The date is the biggest thing on the page, because the day is
271
+ * the subject; the name above it is a small wordmark, since whoever is reading
272
+ * already knows which tab this is.
273
+ */
134
274
  .page-header {
135
275
  display: flex;
136
276
  align-items: flex-end;
137
277
  justify-content: space-between;
138
278
  gap: 16px;
139
279
  flex-wrap: wrap;
140
- max-width: 1280px;
280
+ max-width: var(--page-width);
141
281
  margin: 0 auto;
142
- padding: 28px 0 20px;
282
+ padding: 30px 0 18px;
143
283
  }
144
284
 
145
285
  .page-header h1 {
146
286
  margin: 0;
147
- font-size: 22px;
287
+ font-size: 13px;
148
288
  font-weight: 600;
149
- letter-spacing: -0.01em;
289
+ color: var(--band-muted);
150
290
  }
151
291
 
152
292
  .page-header__date {
153
293
  margin: 2px 0 0;
154
- color: var(--ink-2);
155
- font-size: 14px;
294
+ font-family: var(--font-serif);
295
+ font-size: 32px;
296
+ font-weight: 400;
297
+ line-height: 1.1;
298
+ letter-spacing: -0.01em;
299
+ color: var(--band-ink);
156
300
  }
157
301
 
158
302
  .page-header__meta {
159
303
  display: flex;
160
304
  align-items: center;
161
305
  gap: 8px;
306
+ padding-bottom: 4px;
162
307
  }
163
308
 
164
309
  .page-header__zone {
165
- margin: 3px 0 0;
166
- color: var(--ink-2);
167
- font-size: 12px;
310
+ margin: 8px 0 0;
311
+ color: var(--band-muted);
312
+ font-size: 12.5px;
168
313
  }
169
314
 
170
315
  .freshness {
171
- color: var(--ink-3);
316
+ color: var(--band-muted);
172
317
  font-size: 13px;
173
318
  }
174
319
  .freshness[data-stale='true'] {
175
- color: var(--critical);
320
+ color: var(--band-critical);
176
321
  font-weight: 500;
177
322
  }
178
323
  /*
@@ -189,7 +334,7 @@ a {
189
334
  }
190
335
  .freshness__link:hover {
191
336
  text-decoration: underline;
192
- text-decoration-color: var(--accent);
337
+ text-underline-offset: 2px;
193
338
  }
194
339
 
195
340
  .icon-button {
@@ -199,7 +344,7 @@ a {
199
344
  place-items: center;
200
345
  border: 1px solid var(--border);
201
346
  border-radius: var(--radius-sm);
202
- background: var(--surface);
347
+ background: transparent;
203
348
  color: var(--ink-2);
204
349
  font-size: 14px;
205
350
  cursor: pointer;
@@ -207,16 +352,28 @@ a {
207
352
  .icon-button:hover {
208
353
  color: var(--ink-1);
209
354
  border-color: var(--ink-3);
355
+ background: var(--surface-sunken);
356
+ }
357
+ /* On the band, drawn in its light. */
358
+ .band .icon-button {
359
+ border-color: rgba(255, 255, 255, 0.28);
360
+ color: #e5e7eb;
361
+ }
362
+ .band .icon-button:hover {
363
+ color: var(--band-ink);
364
+ border-color: rgba(255, 255, 255, 0.5);
365
+ background: rgba(255, 255, 255, 0.1);
210
366
  }
211
367
  .icon-button__icon {
212
368
  width: 15px;
213
369
  height: 15px;
214
370
  }
215
- /* A toggle that is on, such as the gear while Settings is open: drawn as the selected tab is, in the accent. */
216
- .icon-button[aria-pressed='true'] {
217
- color: var(--accent);
371
+ /* A toggle that is on, such as the gear while Settings is open: filled in amber, as the selected tab is underlined in it. */
372
+ .icon-button[aria-pressed='true'],
373
+ .band .icon-button[aria-pressed='true'] {
374
+ color: var(--on-accent);
218
375
  border-color: var(--accent);
219
- background: var(--accent-wash);
376
+ background: var(--accent);
220
377
  }
221
378
 
222
379
  /*
@@ -231,10 +388,10 @@ a {
231
388
  gap: 6px;
232
389
  height: 30px;
233
390
  padding: 0 10px;
234
- border: 1px solid var(--border);
391
+ border: 1px solid rgba(255, 255, 255, 0.28);
235
392
  border-radius: 999px;
236
- background: var(--surface);
237
- color: var(--ink-2);
393
+ background: rgba(255, 255, 255, 0.1);
394
+ color: var(--band-ink);
238
395
  font-size: 13px;
239
396
  white-space: nowrap;
240
397
  cursor: help;
@@ -306,12 +463,12 @@ body[data-view='tickets'] #brief-refresh {
306
463
  }
307
464
  /* Reads as the Today tab's "updated … ago" does, so the three tabs match. */
308
465
  .refresh-label {
309
- color: var(--ink-3);
466
+ color: var(--band-muted);
310
467
  font-size: 13px;
311
468
  font-variant-numeric: tabular-nums;
312
469
  }
313
470
  .refresh-label[data-stale='true'] {
314
- color: var(--critical);
471
+ color: var(--band-critical);
315
472
  font-weight: 500;
316
473
  }
317
474
  /*
@@ -334,9 +491,10 @@ body[data-view='tickets'] #brief-refresh {
334
491
  .refresh-button[data-fetching='true'] .refresh-button__icon {
335
492
  animation: refresh-spin 0.9s linear infinite;
336
493
  }
337
- .refresh-button[data-stale='true'] {
338
- color: var(--critical);
339
- border-color: var(--critical);
494
+ .refresh-button[data-stale='true'],
495
+ .band .refresh-button[data-stale='true'] {
496
+ color: var(--band-critical);
497
+ border-color: var(--band-critical);
340
498
  }
341
499
  @keyframes refresh-spin {
342
500
  to {
@@ -354,34 +512,47 @@ body[data-view='tickets'] #brief-refresh {
354
512
  /* ---------- banners ---------- */
355
513
 
356
514
  .banners {
357
- max-width: 1280px;
515
+ max-width: var(--page-width);
358
516
  margin: 0 auto;
359
517
  }
360
518
 
519
+ /*
520
+ * A sheet of its own, one line tall, with a bar in the tone's colour. Its
521
+ * button is taller than its line, so the line is centred on the button rather
522
+ * than left at the top with the button's extra height beneath it.
523
+ */
361
524
  .banner {
362
525
  display: flex;
363
526
  gap: 10px;
364
- align-items: flex-start;
365
- padding: 10px 14px;
527
+ align-items: center;
528
+ padding: 10px 14px 10px 12px;
366
529
  margin-bottom: 10px;
367
- border-radius: var(--radius-sm);
368
530
  border: 1px solid var(--border);
531
+ border-left: 3px solid var(--ink-3);
532
+ border-radius: var(--radius-sm);
369
533
  background: var(--surface);
370
- font-size: 14px;
534
+ font-size: 13.5px;
371
535
  color: var(--ink-2);
372
536
  }
373
537
  .banner__icon {
374
538
  flex: none;
539
+ width: 14px;
540
+ text-align: center;
541
+ font-weight: 600;
375
542
  line-height: 1.5;
376
543
  }
544
+ /* The fold's own line keeps the icon on its first line, since the facts open beneath it. */
545
+ .failure__summary .banner__icon {
546
+ align-self: flex-start;
547
+ }
377
548
  .banner--critical {
378
- border-left: 3px solid var(--critical);
549
+ border-left-color: var(--critical);
379
550
  }
380
551
  .banner--critical .banner__icon {
381
552
  color: var(--critical);
382
553
  }
383
554
  .banner--warning {
384
- border-left: 3px solid var(--warning);
555
+ border-left-color: var(--warning);
385
556
  }
386
557
  .banner--warning .banner__icon {
387
558
  color: var(--serious);
@@ -430,7 +601,7 @@ body[data-view='tickets'] #brief-refresh {
430
601
  }
431
602
  /* Under the message, not under the icon. */
432
603
  .banner .failure__body {
433
- margin-left: 20px;
604
+ margin-left: 24px;
434
605
  }
435
606
  .failure__facts {
436
607
  display: flex;
@@ -453,9 +624,9 @@ body[data-view='tickets'] #brief-refresh {
453
624
  padding: 8px 10px;
454
625
  max-height: 16em;
455
626
  overflow: auto;
456
- border-radius: 6px;
627
+ border-radius: var(--radius-sm);
457
628
  background: var(--surface-sunken);
458
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
629
+ font-family: var(--font-mono);
459
630
  font-size: 12px;
460
631
  line-height: 1.45;
461
632
  color: var(--ink-2);
@@ -479,15 +650,15 @@ body[data-view='tickets'] #brief-refresh {
479
650
  white-space: nowrap;
480
651
  }
481
652
 
482
- /* A banner that is a way in, as a card is: the whole strip is the target. */
653
+ /* A banner that is a way in, as a row is: the whole strip is the target. */
483
654
  .banner--link {
484
655
  cursor: pointer;
485
656
  }
486
657
  .banner--link:hover {
487
- border-color: var(--ink-3);
658
+ background: var(--accent-wash);
488
659
  }
489
660
  .banner--link:focus-visible {
490
- outline: 2px solid var(--accent);
661
+ outline: 2px solid var(--focus-ring);
491
662
  outline-offset: 1px;
492
663
  }
493
664
 
@@ -505,6 +676,9 @@ body[data-view='tickets'] #brief-refresh {
505
676
  font-size: 13px;
506
677
  color: var(--ink-3);
507
678
  }
679
+ .agent-run__list summary:hover {
680
+ color: var(--ink-1);
681
+ }
508
682
  /* What the agent said along the way, one fold per message, under its first line. */
509
683
  .agent-run__messages {
510
684
  display: flex;
@@ -517,7 +691,7 @@ body[data-view='tickets'] #brief-refresh {
517
691
  .agent-run__message {
518
692
  border: 1px solid var(--hairline);
519
693
  border-radius: var(--radius-sm);
520
- background: var(--surface-sunken);
694
+ background: var(--page);
521
695
  }
522
696
  .agent-run__message summary {
523
697
  padding: 6px 10px;
@@ -539,7 +713,68 @@ body[data-view='tickets'] #brief-refresh {
539
713
  display: inline;
540
714
  }
541
715
  .agent-run__message .assistant__reply {
716
+ margin: 0;
542
717
  padding: 0 10px 8px;
718
+ border-left: 0;
719
+ }
720
+ /*
721
+ * A run's steps, the assistant's look: what it said in its own words between
722
+ * the calls, and each subagent as a fold under the step that handed it work.
723
+ */
724
+ .agent-run__list > .agent-run__steps {
725
+ margin-top: 8px;
726
+ }
727
+ .agent-run__said {
728
+ margin: 6px 0;
729
+ font-family: var(--font-serif);
730
+ font-size: 13.5px;
731
+ line-height: 1.5;
732
+ color: var(--ink-1);
733
+ overflow-wrap: anywhere;
734
+ }
735
+ .agent-run__said:first-child {
736
+ margin-top: 0;
737
+ }
738
+ .agent-run__said > * {
739
+ margin: 0;
740
+ }
741
+ .agent-run__said > * + * {
742
+ margin-top: 5px;
743
+ }
744
+ .agent-run__said ul,
745
+ .agent-run__said ol {
746
+ padding-left: 18px;
747
+ }
748
+ .agent-run__said pre {
749
+ white-space: pre-wrap;
750
+ }
751
+ .agent-run__handoff > details {
752
+ flex: 1 1 auto;
753
+ min-width: 0;
754
+ }
755
+ /* The spinner stays on the subagent's own line, not in the middle of its open steps. */
756
+ .agent-run__steps > .agent-run__handoff[data-state='running']::before {
757
+ align-self: flex-start;
758
+ margin-top: 4px;
759
+ }
760
+ .agent-run__handoff summary {
761
+ cursor: pointer;
762
+ overflow: hidden;
763
+ text-overflow: ellipsis;
764
+ white-space: nowrap;
765
+ }
766
+ .agent-run__handoff summary:hover {
767
+ color: var(--ink-1);
768
+ }
769
+ .agent-run__handoff summary .assistant__step-text {
770
+ font-weight: 600;
771
+ }
772
+ .agent-run__handoff summary .assistant__step-detail {
773
+ margin-left: 6px;
774
+ font-size: 12px;
775
+ }
776
+ .agent-run__handoff .agent-run__steps {
777
+ margin-top: 4px;
543
778
  }
544
779
  .agent-run__runs {
545
780
  margin: 8px 0 0;
@@ -555,7 +790,7 @@ body[data-view='tickets'] #brief-refresh {
555
790
  padding: 7px 10px;
556
791
  border: 1px solid var(--hairline);
557
792
  border-radius: var(--radius-sm);
558
- background: var(--surface-sunken);
793
+ background: var(--page);
559
794
  text-align: left;
560
795
  font: inherit;
561
796
  color: var(--ink-2);
@@ -581,7 +816,7 @@ body[data-view='tickets'] #brief-refresh {
581
816
 
582
817
  /* Explanation, not status — so it borrows the accent, not one of the four state hues. */
583
818
  .banner--info {
584
- border-left: 3px solid var(--accent);
819
+ border-left-color: var(--accent);
585
820
  }
586
821
  .banner--info .banner__icon {
587
822
  color: var(--accent);
@@ -591,147 +826,275 @@ body[data-view='tickets'] #brief-refresh {
591
826
 
592
827
  .layout {
593
828
  display: grid;
594
- grid-template-columns: minmax(0, 1fr) 320px;
595
- gap: 24px;
829
+ grid-template-columns: minmax(0, 1fr) 300px;
830
+ gap: 48px;
596
831
  align-items: start;
597
- max-width: 1280px;
832
+ max-width: var(--page-width);
598
833
  margin: 0 auto;
599
834
  }
600
835
 
601
836
  @media (max-width: 900px) {
602
837
  .layout {
603
838
  grid-template-columns: minmax(0, 1fr);
839
+ gap: 32px;
604
840
  }
605
841
  .layout__side {
606
842
  order: -1;
607
843
  }
608
844
  }
609
845
 
610
- /* ---------- standing objective ---------- */
846
+ /* ---------- Today's masthead: the objective, the numbers, the note ---------- */
847
+
848
+ /*
849
+ * The rest of the morning's masthead, on the band with the date. Its band is
850
+ * its own pseudo-element (see `.band`), run up past the top of the page so it
851
+ * and the tabs' are one navy whatever sits between them, and it keeps a clear
852
+ * margin under the agent's note so the last line never sits on the edge.
853
+ */
854
+ .today__masthead {
855
+ position: relative;
856
+ padding: 2px 0 40px;
857
+ color: var(--band-ink);
858
+ }
859
+ .today__masthead::before {
860
+ top: -9999px;
861
+ }
862
+
863
+ /*
864
+ * A notice about the morning — the agent at work, a brief gone stale, a run
865
+ * that failed — is part of its masthead, so on Today it is drawn in the band's
866
+ * materials: the stats sheet's translucent white, the band's rule, its light
867
+ * ink. A sheet of paper laid on the band read as something from another page.
868
+ * The tone keeps its bar; the icons take the band's steps of red and amber.
869
+ */
870
+ body[data-view='today']:has(.today__masthead) .banner {
871
+ background: var(--band-sheet);
872
+ border-color: var(--band-rule);
873
+ color: #d9deea;
874
+ }
875
+ body[data-view='today']:has(.today__masthead) .banner--critical {
876
+ border-left-color: var(--band-critical);
877
+ }
878
+ body[data-view='today']:has(.today__masthead) .banner--critical .banner__icon {
879
+ color: var(--band-critical);
880
+ }
881
+ body[data-view='today']:has(.today__masthead) .banner--warning {
882
+ border-left-color: var(--warning);
883
+ }
884
+ body[data-view='today']:has(.today__masthead) .banner--info {
885
+ border-left-color: var(--accent);
886
+ }
887
+ body[data-view='today']:has(.today__masthead) .banner--link:hover {
888
+ background: rgba(255, 255, 255, 0.12);
889
+ }
890
+ body[data-view='today']:has(.today__masthead) .banner .button {
891
+ border-color: rgba(255, 255, 255, 0.28);
892
+ background: transparent;
893
+ color: var(--band-ink);
894
+ }
895
+ body[data-view='today']:has(.today__masthead) .banner .button:hover {
896
+ border-color: rgba(255, 255, 255, 0.5);
897
+ background: rgba(255, 255, 255, 0.1);
898
+ }
899
+ body[data-view='today']:has(.today__masthead) .banner a {
900
+ color: var(--band-ink);
901
+ }
902
+ body[data-view='today']:has(.today__masthead) .failure__facts {
903
+ color: var(--band-muted);
904
+ }
905
+ body[data-view='today']:has(.today__masthead) .failure__detail {
906
+ background: rgba(0, 0, 0, 0.28);
907
+ color: #d9deea;
908
+ }
909
+ .today__masthead + #sections {
910
+ margin-top: 30px;
911
+ }
611
912
 
612
913
  /*
613
- * Deliberately heavier than the agent's headline below it. The headline changes
614
- * daily; this doesn't, and it should be the first thing read on the page.
914
+ * The headline of the day-book: set in the serif, large, and without a box.
915
+ * Deliberately heavier than the agent's note below it. That one changes daily;
916
+ * this doesn't, and it should be the first thing read on the page.
615
917
  */
616
918
  .objective {
617
- margin-bottom: 20px;
618
- padding: 14px 16px;
619
- background: var(--surface);
620
- border: 1px solid var(--border);
621
- border-left: 3px solid var(--accent);
622
- border-radius: var(--radius);
623
- box-shadow: var(--shadow);
919
+ margin: 4px 0 26px;
624
920
  }
625
921
 
626
922
  .objective__label {
627
- margin: 0 0 4px;
628
- font-size: 11px;
629
- font-weight: 600;
630
- letter-spacing: 0.07em;
631
- text-transform: uppercase;
632
- color: var(--ink-3);
923
+ display: flex;
924
+ align-items: baseline;
925
+ gap: 10px;
926
+ margin: 0 0 6px;
927
+ font-size: 12.5px;
928
+ font-weight: 500;
929
+ color: var(--accent);
633
930
  }
634
931
 
635
932
  .objective__text {
636
933
  margin: 0;
637
- font-size: 17px;
638
- font-weight: 600;
639
- line-height: 1.35;
640
- letter-spacing: -0.01em;
641
- color: var(--ink-1);
934
+ max-width: 38ch;
935
+ font-family: var(--font-serif);
936
+ font-size: 24px;
937
+ font-weight: 500;
938
+ line-height: 1.25;
939
+ letter-spacing: -0.005em;
940
+ color: var(--band-ink);
941
+ text-wrap: pretty;
642
942
  }
643
943
 
644
944
  .objective__blocker {
645
- margin: 6px 0 0;
945
+ margin: 8px 0 0;
946
+ max-width: 70ch;
646
947
  font-size: 13.5px;
647
- color: var(--ink-2);
948
+ color: var(--band-muted);
648
949
  }
649
950
  .objective__blocker-label {
650
- color: var(--critical);
651
- font-weight: 500;
951
+ color: var(--band-critical);
952
+ font-weight: 600;
652
953
  }
653
954
 
654
955
  .objective__note {
655
956
  margin: 8px 0 0;
656
- font-size: 13px;
657
- color: var(--ink-3);
957
+ max-width: 70ch;
958
+ font-size: 13.5px;
959
+ color: var(--band-muted);
658
960
  }
659
961
 
660
- /* A reminder, not a headline: no accent, no shadow, nothing competing with the brief. */
962
+ /* A reminder, not a headline: nothing competing with the brief. */
661
963
  .objective--empty {
662
- padding: 10px 16px;
663
- background: transparent;
664
- border-style: dashed;
665
- border-left-width: 1px;
666
- box-shadow: none;
964
+ padding: 6px 0 6px 14px;
965
+ border-left: 2px dashed var(--band-rule);
966
+ }
967
+ .objective--empty .objective__label {
968
+ margin: 0;
969
+ font-size: 14px;
970
+ color: var(--band-ink);
667
971
  }
668
972
  .objective--empty .objective__note {
669
973
  margin-top: 2px;
670
974
  }
975
+ .objective--empty .link-button {
976
+ color: var(--band-ink);
977
+ }
978
+ .objective--empty code {
979
+ color: var(--band-ink);
980
+ }
671
981
 
672
982
  /* ---------- stat row ---------- */
673
983
 
984
+ /*
985
+ * The day's numbers on one sheet, each a figure with its name beneath and a
986
+ * rule between them, the way a planner's margin keeps its counts. One sheet
987
+ * rather than five tiles: the figures are read as a line, not compared as boxes.
988
+ */
674
989
  .stats {
675
- display: grid;
676
- grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
677
- gap: 12px;
678
- margin-bottom: 20px;
990
+ display: flex;
991
+ flex-wrap: wrap;
992
+ gap: 12px 0;
993
+ margin: 0;
994
+ padding: 14px 20px;
995
+ background: var(--band-sheet);
996
+ border: 1px solid var(--band-rule);
997
+ border-radius: var(--radius);
679
998
  }
680
999
 
681
1000
  .stat {
682
- padding: 12px 14px;
683
- background: var(--surface);
684
- border: 1px solid var(--border);
685
- border-radius: var(--radius);
686
- box-shadow: var(--shadow);
1001
+ display: flex;
1002
+ flex-direction: column;
1003
+ flex: 1 1 120px;
1004
+ min-width: 0;
1005
+ padding: 0 20px;
1006
+ border-left: 1px solid var(--band-rule);
1007
+ }
1008
+ .stat:first-child {
1009
+ padding-left: 0;
1010
+ border-left: 0;
687
1011
  }
688
1012
  .stat__label {
689
- margin: 0;
690
- color: var(--ink-2);
691
- font-size: 12px;
1013
+ order: 2;
1014
+ margin: 2px 0 0;
1015
+ color: var(--band-muted);
1016
+ font-size: 12.5px;
1017
+ line-height: 1.35;
692
1018
  }
693
1019
  .stat__value {
694
- margin: 2px 0 0;
695
- font-size: 26px;
1020
+ order: 1;
1021
+ margin: 0;
1022
+ font-size: 22px;
696
1023
  font-weight: 600;
697
1024
  line-height: 1.15;
698
- letter-spacing: -0.02em;
1025
+ letter-spacing: -0.01em;
1026
+ font-variant-numeric: tabular-nums;
1027
+ white-space: nowrap; /* "5 h 15 min" is one figure, however narrow the column. */
1028
+ color: var(--band-ink);
699
1029
  }
700
1030
  .stat__value[data-tone='critical'] {
701
- color: var(--critical);
1031
+ color: var(--band-critical);
702
1032
  }
703
1033
  .stat__value[data-tone='good'] {
704
- color: var(--good-ink);
1034
+ color: var(--band-good);
705
1035
  }
706
1036
  .stat__footnote {
707
- margin: 3px 0 0;
708
- color: var(--ink-3);
709
- font-size: 11.5px;
1037
+ order: 3;
1038
+ margin: 4px 0 0;
1039
+ color: var(--band-muted);
1040
+ font-size: 12px;
710
1041
  line-height: 1.35;
711
- /* The last thing completed can be a full title; keep the tile from growing. */
1042
+ /* The last thing completed can be a full title; keep the line from growing. */
712
1043
  display: -webkit-box;
713
1044
  -webkit-line-clamp: 2;
714
1045
  -webkit-box-orient: vertical;
715
1046
  overflow: hidden;
716
1047
  }
717
1048
 
1049
+ /* Two to a line on a phone, the pairs ruled apart, rather than a ragged wrap. */
1050
+ @media (max-width: 600px) {
1051
+ .stats {
1052
+ display: grid;
1053
+ grid-template-columns: 1fr 1fr;
1054
+ gap: 14px 0;
1055
+ }
1056
+ .stat:nth-child(odd) {
1057
+ padding-left: 0;
1058
+ border-left: 0;
1059
+ }
1060
+ }
1061
+
1062
+ /*
1063
+ * The agent's one-line reading of the day, set as a note in the margin: the
1064
+ * serif's italic, against a rule. Yours above it is roman and heavy; this is
1065
+ * what it made of it. Anything bold in it steps back to roman, which is how
1066
+ * emphasis inside italic is made.
1067
+ */
718
1068
  .headline {
719
- margin: 0 0 20px;
720
- padding: 12px 14px;
721
- background: var(--surface);
722
- border: 1px solid var(--border);
723
- border-left: 3px solid var(--accent);
724
- border-radius: var(--radius);
725
- color: var(--ink-2);
726
- font-size: 14px;
1069
+ margin: 28px 0 0;
1070
+ padding: 2px 0 2px 16px;
1071
+ max-width: 64ch;
1072
+ border-left: 2px solid var(--accent);
1073
+ font-family: var(--font-serif);
1074
+ font-style: italic;
1075
+ font-size: 16px;
1076
+ line-height: 1.5;
1077
+ color: #c9d0e2;
1078
+ }
1079
+ .headline strong {
1080
+ font-style: normal;
1081
+ font-weight: 500;
1082
+ color: var(--band-ink);
1083
+ }
1084
+ .headline code {
1085
+ font-family: var(--font-mono);
1086
+ font-style: normal;
1087
+ font-size: 0.9em;
1088
+ color: var(--band-ink);
727
1089
  }
728
1090
 
729
1091
  /* ---------- sections ---------- */
730
1092
 
731
1093
  .section {
732
- margin-bottom: 22px;
1094
+ margin-bottom: 30px;
733
1095
  }
734
1096
 
1097
+ /* The heading stands on the paper above its sheet, naming what the sheet holds. */
735
1098
  .section__header {
736
1099
  display: flex;
737
1100
  align-items: baseline;
@@ -741,15 +1104,13 @@ body[data-view='tickets'] #brief-refresh {
741
1104
  }
742
1105
  .section__title {
743
1106
  margin: 0;
744
- font-size: 12px;
1107
+ font-size: 14px;
745
1108
  font-weight: 600;
746
- letter-spacing: 0.06em;
747
- text-transform: uppercase;
748
- color: var(--ink-2);
1109
+ color: var(--ink-1);
749
1110
  }
750
1111
  .section__count {
751
1112
  color: var(--ink-3);
752
- font-size: 12px;
1113
+ font-size: 12.5px;
753
1114
  font-variant-numeric: tabular-nums;
754
1115
  }
755
1116
  .section__dot {
@@ -760,40 +1121,52 @@ body[data-view='tickets'] #brief-refresh {
760
1121
  align-self: center;
761
1122
  }
762
1123
 
1124
+ /* A stack of cards with air between them; the heading stands on the paper above. */
763
1125
  .list {
764
1126
  list-style: none;
765
1127
  margin: 0;
766
1128
  padding: 0;
767
1129
  display: flex;
768
1130
  flex-direction: column;
769
- gap: 2px; /* the surface gap doing the separating, not a border */
1131
+ gap: 8px;
770
1132
  }
771
1133
 
772
1134
  /* ---------- item ---------- */
773
1135
 
1136
+ /*
1137
+ * A row is a card: its own sheet, with an edge, so where one ends and the next
1138
+ * begins is never in doubt. The one under the pointer darkens its edge, the
1139
+ * keyboard's cursor wears a ring, and the one the panel is open on carries a
1140
+ * bar on the edge the panel sits past.
1141
+ */
774
1142
  .item {
775
1143
  position: relative;
776
1144
  display: grid;
777
- grid-template-columns: auto minmax(0, 1fr);
778
- gap: 10px;
779
- padding: 11px 13px;
1145
+ grid-template-columns: 30px minmax(0, 1fr);
1146
+ gap: 0 8px;
1147
+ padding: 12px 14px 12px 8px;
780
1148
  background: var(--surface);
781
1149
  border: 1px solid var(--border);
782
1150
  border-radius: var(--radius);
783
1151
  box-shadow: var(--shadow);
1152
+ cursor: pointer; /* A click anywhere on the row opens the panel, and the cursor says so. */
784
1153
  scroll-margin: 90px;
785
1154
  }
1155
+ .item:hover {
1156
+ border-color: var(--ink-3);
1157
+ }
786
1158
  /*
787
1159
  * Two states used to share one look: selected and priority were both "accent
788
1160
  * border", so the ranked rows were indistinguishable from a keyboard cursor.
789
- * Selected is the quieter of the two.
1161
+ * The cursor is a ring; a rank is the numeral in the margin.
790
1162
  */
791
1163
  .item[data-selected='true'] {
792
- border-color: var(--ink-3);
793
- box-shadow: 0 0 0 1px var(--ink-3);
1164
+ border-color: var(--ink-2);
1165
+ box-shadow: 0 0 0 1px var(--ink-2);
794
1166
  }
795
- .item[data-priority='true'] {
796
- border-left: 3px solid var(--accent);
1167
+ .item[data-detail='true'] {
1168
+ border-color: var(--accent);
1169
+ box-shadow: inset -3px 0 0 var(--accent);
797
1170
  }
798
1171
  .item[data-status='done'] .item__title,
799
1172
  .item[data-status='dismissed'] .item__title {
@@ -805,18 +1178,44 @@ body[data-view='tickets'] #brief-refresh {
805
1178
  }
806
1179
 
807
1180
  .item__mark {
808
- padding-top: 4px;
1181
+ display: flex;
1182
+ justify-content: center;
1183
+ align-items: flex-start;
1184
+ padding-top: 6px;
809
1185
  }
810
1186
 
811
1187
  .item__dot {
812
- width: 9px;
813
- height: 9px;
1188
+ width: 8px;
1189
+ height: 8px;
814
1190
  border-radius: 50%;
815
1191
  display: block;
816
1192
  }
817
1193
 
1194
+ /*
1195
+ * A ranked row's number, in the margin where the dot would be. Drawn in the
1196
+ * serif at the title's cap height, so the three ranks read as a column down
1197
+ * the top of the page. The dot gives way: the source is named in text on the
1198
+ * line beneath, and the rank is what this row is for.
1199
+ */
1200
+ .item__mark[data-rank] {
1201
+ padding-top: 0;
1202
+ }
1203
+ .item__mark[data-rank]::before {
1204
+ content: attr(data-rank);
1205
+ font-family: var(--font-serif);
1206
+ font-size: 18px;
1207
+ font-weight: 500;
1208
+ line-height: 1.15;
1209
+ color: var(--accent-ink);
1210
+ font-variant-numeric: tabular-nums;
1211
+ }
1212
+ .item__mark[data-rank] .item__dot {
1213
+ display: none;
1214
+ }
1215
+
818
1216
  .item__body {
819
1217
  min-width: 0;
1218
+ max-width: 72ch;
820
1219
  }
821
1220
 
822
1221
  .item__title {
@@ -833,7 +1232,7 @@ body[data-view='tickets'] #brief-refresh {
833
1232
  }
834
1233
  .item__title a:hover {
835
1234
  text-decoration: underline;
836
- text-decoration-color: var(--accent);
1235
+ text-decoration-color: var(--ink-3);
837
1236
  }
838
1237
 
839
1238
  /*
@@ -851,9 +1250,9 @@ body[data-view='tickets'] #brief-refresh {
851
1250
  display: flex;
852
1251
  flex-wrap: wrap;
853
1252
  align-items: center;
854
- gap: 6px;
1253
+ gap: 4px 6px;
855
1254
  margin-top: 5px;
856
- font-size: 12px;
1255
+ font-size: 12.5px;
857
1256
  color: var(--ink-3);
858
1257
  }
859
1258
 
@@ -864,24 +1263,58 @@ body[data-view='tickets'] #brief-refresh {
864
1263
 
865
1264
  .item__detail {
866
1265
  margin: 6px 0 0;
867
- font-size: 13px;
1266
+ font-size: 13.5px;
1267
+ line-height: 1.5;
868
1268
  color: var(--ink-2);
869
1269
  overflow-wrap: anywhere;
870
1270
  }
1271
+ /*
1272
+ * The assistant's answer, asked ahead, in a line: the verdict on the row, so
1273
+ * the row says what to do about the pull request before it is opened.
1274
+ */
1275
+ .item__ahead {
1276
+ display: -webkit-box;
1277
+ margin: 7px 0 0;
1278
+ padding: 4px 8px;
1279
+ border-radius: var(--radius-sm);
1280
+ background: var(--accent-wash);
1281
+ font-size: 13px;
1282
+ color: var(--ink-1);
1283
+ overflow: hidden;
1284
+ overflow-wrap: anywhere;
1285
+ -webkit-box-orient: vertical;
1286
+ -webkit-line-clamp: 2;
1287
+ }
1288
+ .item__ahead--quiet {
1289
+ background: none;
1290
+ padding: 0;
1291
+ color: var(--ink-3);
1292
+ }
1293
+ .item__ahead-mark {
1294
+ margin-right: 6px;
1295
+ color: var(--accent-ink);
1296
+ font-weight: 600;
1297
+ }
1298
+ .item__ahead[data-status='running'] .item__ahead-mark {
1299
+ animation: ahead-pulse 1.4s ease-in-out infinite;
1300
+ }
1301
+ @keyframes ahead-pulse {
1302
+ 50% {
1303
+ opacity: 0.3;
1304
+ }
1305
+ }
1306
+ @media (prefers-reduced-motion: reduce) {
1307
+ .item__ahead[data-status='running'] .item__ahead-mark {
1308
+ animation: none;
1309
+ }
1310
+ }
1311
+
871
1312
  .item__detail code {
872
1313
  padding: 1px 4px;
873
1314
  background: var(--surface-sunken);
874
1315
  border-radius: 3px;
875
- font-size: 0.92em;
876
- }
877
-
878
- /* A click anywhere on the card opens the panel, and the cursor says so. */
879
- .item {
880
- cursor: pointer;
881
- }
882
- /* The row the panel is open on: a bar on the edge the panel sits past. */
883
- .item[data-detail='true'] {
884
- border-right: 3px solid var(--accent);
1316
+ font-family: var(--font-mono);
1317
+ font-size: 0.9em;
885
1318
  }
886
1319
 
887
1320
  /* pills */
@@ -898,16 +1331,9 @@ body[data-view='tickets'] #brief-refresh {
898
1331
  color: var(--ink-2);
899
1332
  white-space: nowrap;
900
1333
  }
901
- .pill--priority {
902
- border-color: transparent;
903
- background: var(--accent);
904
- color: #fff;
905
- font-weight: 600;
906
- font-variant-numeric: tabular-nums;
907
- }
908
1334
  .pill--objective {
909
- border-color: var(--accent);
910
- color: var(--accent);
1335
+ border-color: var(--accent-ink);
1336
+ color: var(--accent-ink);
911
1337
  font-weight: 500;
912
1338
  }
913
1339
  .pill--overdue {
@@ -935,10 +1361,14 @@ body[data-view='tickets'] #brief-refresh {
935
1361
 
936
1362
  /* actions */
937
1363
 
1364
+ /*
1365
+ * The strip sits over the card's top right on the card's own white, so the
1366
+ * tail of a long title is covered rather than shown through it.
1367
+ */
938
1368
  .item__actions {
939
1369
  position: absolute;
940
- top: 8px;
941
- right: 10px;
1370
+ top: 9px;
1371
+ right: 12px;
942
1372
  display: flex;
943
1373
  gap: 4px;
944
1374
  opacity: 0;
@@ -954,43 +1384,69 @@ body[data-view='tickets'] #brief-refresh {
954
1384
  @media (hover: none) {
955
1385
  .item__actions {
956
1386
  opacity: 1;
1387
+ background: transparent;
1388
+ }
1389
+ }
1390
+ /*
1391
+ * On a phone the title runs the whole width, so a strip laid over its end
1392
+ * covers the words. There it takes a line of its own under the row instead.
1393
+ */
1394
+ @media (max-width: 600px) {
1395
+ .item__actions,
1396
+ .item:hover .item__actions,
1397
+ .item[data-selected='true'] .item__actions,
1398
+ .item[data-detail='true'] .item__actions {
1399
+ position: static;
1400
+ grid-column: 2;
1401
+ margin-top: 8px;
1402
+ padding-left: 0;
1403
+ opacity: 1;
1404
+ background: transparent;
957
1405
  }
958
1406
  }
959
1407
 
960
1408
  .button {
961
- padding: 3px 9px;
1409
+ padding: 4px 10px;
962
1410
  border: 1px solid var(--border);
963
1411
  border-radius: var(--radius-sm);
964
1412
  background: var(--surface);
965
- color: var(--ink-2);
1413
+ color: var(--ink-1);
966
1414
  font: inherit;
967
- font-size: 12px;
1415
+ font-size: 12.5px;
1416
+ font-weight: 500;
1417
+ line-height: 1.5;
968
1418
  cursor: pointer;
969
1419
  white-space: nowrap;
970
1420
  }
971
1421
  .button:hover {
972
- color: var(--ink-1);
973
- border-color: var(--ink-3);
1422
+ border-color: var(--ink-2);
1423
+ background: var(--surface-sunken);
974
1424
  }
975
1425
  .button--primary {
976
- border-color: transparent;
1426
+ border-color: var(--accent);
977
1427
  background: var(--accent);
978
- color: #fff;
1428
+ color: var(--on-accent);
979
1429
  }
980
1430
  .button--primary:hover {
981
- color: #fff;
982
- filter: brightness(1.08);
1431
+ border-color: #c9841f;
1432
+ background: #c9841f;
1433
+ color: var(--on-accent);
983
1434
  }
984
1435
  /* Not yet: it reads as waiting, not as the next thing to press. */
985
1436
  .button:disabled,
986
1437
  .button:disabled:hover {
987
1438
  opacity: 0.45;
988
1439
  cursor: not-allowed;
989
- filter: none;
1440
+ background: var(--surface);
990
1441
  border-color: var(--border);
1442
+ color: var(--ink-1);
1443
+ }
1444
+ .button--primary:disabled,
1445
+ .button--primary:disabled:hover {
1446
+ background: var(--accent);
1447
+ border-color: var(--accent);
1448
+ color: var(--on-accent);
991
1449
  }
992
-
993
- /* note composer */
994
1450
 
995
1451
  /* snooze menu */
996
1452
 
@@ -1020,12 +1476,12 @@ body[data-view='tickets'] #brief-refresh {
1020
1476
  background: var(--surface);
1021
1477
  border: 1px solid var(--border);
1022
1478
  border-radius: var(--radius-sm);
1023
- box-shadow: 0 6px 24px rgba(11, 11, 11, 0.14);
1479
+ box-shadow: var(--shadow-float);
1024
1480
  }
1025
1481
  .menu button {
1026
1482
  display: block;
1027
1483
  width: 100%;
1028
- padding: 5px 9px;
1484
+ padding: 6px 9px;
1029
1485
  border: 0;
1030
1486
  border-radius: 4px;
1031
1487
  background: none;
@@ -1078,23 +1534,27 @@ body[data-view='tickets'] #brief-refresh {
1078
1534
 
1079
1535
  /* ---------- agenda ---------- */
1080
1536
 
1537
+ /*
1538
+ * The day's timeline, in the margin: a column of times, a rule running down
1539
+ * the day, a mark on it per event, and the red line of now crossing it. The
1540
+ * list is a sheet like the brief's, under a heading on the paper like theirs,
1541
+ * and sticky so the morning's meetings stay beside the afternoon's rows.
1542
+ */
1081
1543
  .agenda {
1082
- padding: 14px;
1083
- background: var(--surface);
1084
- border: 1px solid var(--border);
1085
- border-radius: var(--radius);
1086
- box-shadow: var(--shadow);
1087
1544
  position: sticky;
1088
1545
  top: 16px;
1089
1546
  }
1090
1547
 
1091
1548
  .agenda__title {
1092
- margin: 0 0 10px;
1093
- font-size: 12px;
1549
+ margin: 0 0 8px;
1550
+ padding: 0 2px;
1551
+ font-size: 14px;
1094
1552
  font-weight: 600;
1095
- letter-spacing: 0.06em;
1096
- text-transform: uppercase;
1097
- color: var(--ink-2);
1553
+ color: var(--ink-1);
1554
+ }
1555
+ /* Level with the masthead, the agenda's heading stands on the band. */
1556
+ body:has(.today__masthead) .agenda__title {
1557
+ color: var(--band-ink);
1098
1558
  }
1099
1559
 
1100
1560
  /*
@@ -1104,12 +1564,13 @@ body[data-view='tickets'] #brief-refresh {
1104
1564
  .agenda__note {
1105
1565
  margin: 0 0 10px;
1106
1566
  padding: 6px 8px;
1107
- border-radius: 6px;
1108
- font-size: 11px;
1567
+ border: 1px solid var(--border);
1568
+ border-left: 2px solid var(--ink-3);
1569
+ border-radius: var(--radius-sm);
1570
+ font-size: 11.5px;
1109
1571
  line-height: 1.4;
1110
1572
  color: var(--ink-2);
1111
- background: var(--surface-sunken);
1112
- border-left: 2px solid var(--ink-3);
1573
+ background: var(--surface);
1113
1574
  }
1114
1575
 
1115
1576
  /* Falling back to the brief is a louder thing than a merely stale read. */
@@ -1118,22 +1579,46 @@ body[data-view='tickets'] #brief-refresh {
1118
1579
  }
1119
1580
 
1120
1581
  .agenda__list {
1582
+ position: relative;
1121
1583
  list-style: none;
1122
1584
  margin: 0;
1123
- padding: 0;
1585
+ padding: 8px 14px;
1586
+ background: var(--surface);
1587
+ border: 1px solid var(--border);
1588
+ border-radius: var(--radius);
1589
+ box-shadow: var(--shadow);
1590
+ }
1591
+ /* The rule the day runs down, between the times and the names. */
1592
+ .agenda__list::before {
1593
+ content: '';
1594
+ position: absolute;
1595
+ top: 14px;
1596
+ bottom: 14px;
1597
+ left: 77px;
1598
+ width: 1px;
1599
+ background: var(--hairline);
1124
1600
  }
1125
1601
 
1126
1602
  .agenda__row {
1603
+ position: relative;
1127
1604
  display: grid;
1128
1605
  /* Wide enough for a 12-hour "09:30 AM" without wrapping. */
1129
- grid-template-columns: 64px minmax(0, 1fr);
1130
- gap: 10px;
1131
- padding: 6px 0;
1132
- border-top: 1px solid var(--hairline);
1606
+ grid-template-columns: 56px minmax(0, 1fr);
1607
+ gap: 16px;
1608
+ padding: 7px 0;
1133
1609
  font-size: 13px;
1134
1610
  }
1135
- .agenda__row:first-child {
1136
- border-top: 0;
1611
+ /* The event's mark on the rule, ringed in the sheet so the rule doesn't run through it. */
1612
+ .agenda__row::before {
1613
+ content: '';
1614
+ position: absolute;
1615
+ left: 60px;
1616
+ top: 13px;
1617
+ width: 7px;
1618
+ height: 7px;
1619
+ border-radius: 50%;
1620
+ background: var(--ink-2);
1621
+ box-shadow: 0 0 0 2px var(--surface);
1137
1622
  }
1138
1623
 
1139
1624
  .agenda__time {
@@ -1141,11 +1626,13 @@ body[data-view='tickets'] #brief-refresh {
1141
1626
  font-size: 12px;
1142
1627
  font-variant-numeric: tabular-nums; /* a column of times, so tabular is right here */
1143
1628
  white-space: nowrap;
1629
+ text-align: right;
1144
1630
  padding-top: 1px;
1145
1631
  }
1146
1632
 
1147
1633
  .agenda__name {
1148
1634
  color: var(--ink-1);
1635
+ line-height: 1.4;
1149
1636
  overflow-wrap: anywhere;
1150
1637
  }
1151
1638
  /* Event links take the row's ink so past events actually read as past. */
@@ -1155,12 +1642,15 @@ body[data-view='tickets'] #brief-refresh {
1155
1642
  }
1156
1643
  .agenda__name a:hover {
1157
1644
  text-decoration: underline;
1158
- text-decoration-color: var(--accent);
1645
+ text-decoration-color: var(--ink-3);
1159
1646
  }
1160
1647
  .agenda__row[data-past='true'] .agenda__name,
1161
1648
  .agenda__row[data-past='true'] .agenda__time {
1162
1649
  color: var(--ink-3);
1163
1650
  }
1651
+ .agenda__row[data-past='true']::before {
1652
+ background: var(--rule);
1653
+ }
1164
1654
 
1165
1655
  /*
1166
1656
  * An event that sits on the day without taking any of it: a delivery window, a
@@ -1168,11 +1658,15 @@ body[data-view='tickets'] #brief-refresh {
1168
1658
  * dimming, because being home for the delivery is the entire point of it being
1169
1659
  * on the agenda — a 14:30 slot that reads as already over is a worse mistake
1170
1660
  * than one that reads as a meeting. The row also says "marked free" in text,
1171
- * since ink is never the only cue here.
1661
+ * since ink is never the only cue here; its mark is hollow for the same reason.
1172
1662
  */
1173
1663
  .agenda__row[data-blocking='false'] .agenda__name {
1174
1664
  color: var(--ink-2);
1175
1665
  }
1666
+ .agenda__row[data-blocking='false']::before {
1667
+ background: var(--surface);
1668
+ box-shadow: 0 0 0 2px var(--surface), inset 0 0 0 1.5px var(--ink-3);
1669
+ }
1176
1670
  .agenda__sub {
1177
1671
  display: block;
1178
1672
  color: var(--ink-3);
@@ -1183,10 +1677,16 @@ body[data-view='tickets'] #brief-refresh {
1183
1677
  color: var(--good-ink);
1184
1678
  font-weight: 500;
1185
1679
  }
1680
+ .agenda__row--free::before {
1681
+ background: var(--surface);
1682
+ box-shadow: 0 0 0 2px var(--surface), inset 0 0 0 1.5px var(--good-ink);
1683
+ }
1186
1684
  .agenda__row--now {
1187
1685
  align-items: center;
1188
1686
  padding: 2px 0;
1189
- border-top: 0;
1687
+ }
1688
+ .agenda__row--now::before {
1689
+ display: none;
1190
1690
  }
1191
1691
  .agenda__now-label {
1192
1692
  color: var(--critical);
@@ -1194,36 +1694,40 @@ body[data-view='tickets'] #brief-refresh {
1194
1694
  font-weight: 600;
1195
1695
  font-variant-numeric: tabular-nums;
1196
1696
  white-space: nowrap;
1697
+ text-align: right;
1197
1698
  }
1699
+ /* Starts back across the rule, so now is seen to cut the day. */
1198
1700
  .agenda__now-line {
1199
1701
  height: 2px;
1702
+ margin-left: -14px;
1200
1703
  background: var(--critical);
1201
1704
  border-radius: 1px;
1202
1705
  }
1203
1706
 
1204
1707
  .empty {
1205
1708
  margin: 0;
1206
- padding: 18px 4px;
1709
+ padding: 16px 0;
1207
1710
  color: var(--ink-3);
1208
- font-size: 13.5px;
1209
- text-align: center;
1711
+ font-family: var(--font-serif);
1712
+ font-style: italic;
1713
+ font-size: 14.5px;
1210
1714
  }
1211
1715
 
1212
1716
  /* ---------- done drawer ---------- */
1213
1717
 
1214
1718
  .drawer {
1215
- margin-top: 8px;
1216
- border: 1px solid var(--border);
1217
- border-radius: var(--radius);
1218
- background: var(--surface);
1719
+ margin-top: 12px;
1219
1720
  }
1220
1721
  .drawer > summary {
1221
- padding: 9px 13px;
1722
+ padding: 10px 8px;
1222
1723
  cursor: pointer;
1223
1724
  color: var(--ink-2);
1224
1725
  font-size: 13px;
1225
1726
  list-style: none;
1226
1727
  }
1728
+ .drawer > summary:hover {
1729
+ color: var(--ink-1);
1730
+ }
1227
1731
  .drawer > summary::-webkit-details-marker {
1228
1732
  display: none;
1229
1733
  }
@@ -1235,10 +1739,7 @@ body[data-view='tickets'] #brief-refresh {
1235
1739
  content: '▾ ';
1236
1740
  }
1237
1741
  .drawer .list {
1238
- padding: 0 8px 8px;
1239
- }
1240
- .drawer .item {
1241
- box-shadow: none;
1742
+ padding: 0 0 8px;
1242
1743
  }
1243
1744
 
1244
1745
  /* ---------- toast ---------- */
@@ -1252,12 +1753,12 @@ body[data-view='tickets'] #brief-refresh {
1252
1753
  display: flex;
1253
1754
  align-items: center;
1254
1755
  gap: 12px;
1255
- padding: 9px 14px;
1756
+ padding: 9px 16px;
1256
1757
  background: var(--ink-1);
1257
1758
  color: var(--page);
1258
1759
  border-radius: 999px;
1259
1760
  font-size: 13px;
1260
- box-shadow: 0 6px 24px rgba(11, 11, 11, 0.25);
1761
+ box-shadow: 0 8px 28px rgba(0, 0, 0, 0.25);
1261
1762
  }
1262
1763
  .toast button {
1263
1764
  border: 0;
@@ -1266,6 +1767,7 @@ body[data-view='tickets'] #brief-refresh {
1266
1767
  font: inherit;
1267
1768
  font-weight: 600;
1268
1769
  text-decoration: underline;
1770
+ text-underline-offset: 2px;
1269
1771
  cursor: pointer;
1270
1772
  padding: 0;
1271
1773
  }
@@ -1273,24 +1775,27 @@ body[data-view='tickets'] #brief-refresh {
1273
1775
  /* ---------- help dialog ---------- */
1274
1776
 
1275
1777
  .help {
1276
- max-width: 420px;
1277
- padding: 22px;
1778
+ max-width: 440px;
1779
+ padding: 24px 26px;
1278
1780
  border: 1px solid var(--border);
1279
- border-radius: var(--radius);
1781
+ border-radius: 12px;
1280
1782
  background: var(--surface);
1281
1783
  color: var(--ink-1);
1784
+ box-shadow: var(--shadow-float);
1282
1785
  }
1283
1786
  .help::backdrop {
1284
- background: rgba(11, 11, 11, 0.4);
1787
+ background: rgba(10, 12, 20, 0.55);
1285
1788
  }
1286
1789
  .help h2 {
1287
- margin: 0 0 14px;
1288
- font-size: 16px;
1790
+ margin: 0 0 16px;
1791
+ font-family: var(--font-serif);
1792
+ font-size: 20px;
1793
+ font-weight: 500;
1289
1794
  }
1290
1795
  .help dl {
1291
- margin: 0 0 14px;
1796
+ margin: 0 0 16px;
1292
1797
  display: grid;
1293
- gap: 6px;
1798
+ gap: 7px;
1294
1799
  }
1295
1800
  .help dl > div {
1296
1801
  display: grid;
@@ -1306,8 +1811,9 @@ body[data-view='tickets'] #brief-refresh {
1306
1811
  color: var(--ink-2);
1307
1812
  }
1308
1813
  .help__note {
1309
- margin: 0 0 16px;
1814
+ margin: 0 0 18px;
1310
1815
  font-size: 13px;
1816
+ line-height: 1.5;
1311
1817
  color: var(--ink-3);
1312
1818
  }
1313
1819
  kbd {
@@ -1316,7 +1822,7 @@ kbd {
1316
1822
  border-bottom-width: 2px;
1317
1823
  border-radius: 4px;
1318
1824
  background: var(--surface-sunken);
1319
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
1825
+ font-family: var(--font-mono);
1320
1826
  font-size: 11.5px;
1321
1827
  color: var(--ink-1);
1322
1828
  }
@@ -1330,38 +1836,38 @@ kbd {
1330
1836
  /* ---------- tabs ---------- */
1331
1837
 
1332
1838
  /*
1333
- * Two views, one page. Today is the brief; the board is the live list of pull
1334
- * requests. They're tabs rather than one long page because the brief is edited
1335
- * down to a short list on purpose, and a wall of PRs beneath it would undo that.
1839
+ * Three views, one page. Today is the brief; the boards are the live lists.
1840
+ * They're tabs rather than one long page because the brief is edited down to
1841
+ * a short list on purpose, and a wall of PRs beneath it would undo that.
1336
1842
  */
1337
1843
  .tabs {
1338
1844
  display: flex;
1339
- gap: 4px;
1340
- max-width: 1280px;
1341
- margin: -6px auto 14px;
1342
- border-bottom: 1px solid var(--hairline);
1845
+ gap: 2px;
1846
+ max-width: var(--page-width);
1847
+ margin: 0 auto 24px;
1848
+ border-bottom: 1px solid var(--band-rule);
1343
1849
  }
1344
1850
 
1345
1851
  .tab {
1346
1852
  display: inline-flex;
1347
1853
  align-items: center;
1348
1854
  gap: 7px;
1349
- padding: 7px 12px 9px;
1855
+ padding: 8px 12px 10px;
1350
1856
  margin-bottom: -1px;
1351
1857
  border: 0;
1352
1858
  border-bottom: 2px solid transparent;
1353
1859
  background: none;
1354
- color: var(--ink-2);
1860
+ color: var(--band-muted);
1355
1861
  font: inherit;
1356
- font-size: 13.5px;
1862
+ font-size: 14px;
1357
1863
  font-weight: 500;
1358
1864
  cursor: pointer;
1359
1865
  }
1360
1866
  .tab:hover {
1361
- color: var(--ink-1);
1867
+ color: var(--band-ink);
1362
1868
  }
1363
1869
  .tab[aria-selected='true'] {
1364
- color: var(--ink-1);
1870
+ color: var(--band-ink);
1365
1871
  border-bottom-color: var(--accent);
1366
1872
  }
1367
1873
 
@@ -1435,7 +1941,6 @@ body[data-view='settings'] .layout {
1435
1941
 
1436
1942
  /* ---------- the pull request board ---------- */
1437
1943
 
1438
-
1439
1944
  /* The line under a waiting-on-you row that says why. Reads as the row's detail. */
1440
1945
  .item__reason {
1441
1946
  margin: 6px 0 0;
@@ -1475,29 +1980,27 @@ body[data-view='settings'] .layout {
1475
1980
  /*
1476
1981
  * Two columns, by measurement rather than by taste: the rows were
1477
1982
  * 1200px wide for a summary that runs 520px at the median and 683px at the
1478
- * longest, so half of every card was empty and thirty of them came to 2527px of
1983
+ * longest, so half of every row was empty and thirty of them came to 2527px of
1479
1984
  * scrolling. At 460px a column the same thirty fit in half that.
1480
1985
  *
1481
1986
  * Multicol rather than a grid, which is what this was and which was wrong for a
1482
- * board whose cards disagree about height. A grid lays out in *rows*, so a
1483
- * one-line card beside a card carrying a note gets the note's height reserved
1987
+ * board whose rows disagree about height. A grid lays out in *rows*, so a
1988
+ * one-line row beside a row carrying a note gets the note's height reserved
1484
1989
  * next to it and left empty — `align-items: start` stops it stretching but
1485
- * cannot reclaim the row, and one noted card on a real board cost about a
1990
+ * cannot reclaim the row, and one noted row on a real board cost about a
1486
1991
  * hundred pixels of nothing. A column flow has no rows to align against: each
1487
- * card starts where the one above it ended.
1992
+ * row starts where the one above it ended.
1488
1993
  *
1489
- * `break-inside: avoid` so a card is never split down the middle of a column,
1490
- * and the vertical rhythm is a margin rather than `gap`, which a multicol
1491
- * container does not have.
1994
+ * `break-inside: avoid` so a row is never split down the middle of a column.
1492
1995
  *
1493
1996
  * Never more than two, so the board keeps the shared page width and its edges
1494
1997
  * line up with the other tabs' however wide the display is. The 460px floor is
1495
1998
  * what drops it to one column on a narrow window rather than squeezing two.
1496
1999
  *
1497
2000
  * An absolutely positioned child is still fragmented by the columns, and counts
1498
- * toward balancing them. `.item__actions` stays inside its card, so it travels
1499
- * with the card into its column and nothing notices. Anything that hangs below a
1500
- * card must not be in here at all: the row menus once were, and were split
2001
+ * toward balancing them. `.item__actions` stays inside its row, so it travels
2002
+ * with the row into its column and nothing notices. Anything that hangs below a
2003
+ * row must not be in here at all: the row menus once were, and were split
1501
2004
  * across both columns and pushed the next section down. They are popovers now.
1502
2005
  */
1503
2006
  #tickets .list {
@@ -1507,7 +2010,7 @@ body[data-view='settings'] .layout {
1507
2010
  }
1508
2011
  #tickets .list > .item {
1509
2012
  break-inside: avoid;
1510
- margin-bottom: 4px;
2013
+ margin-bottom: 8px;
1511
2014
  }
1512
2015
 
1513
2016
  /*
@@ -1518,13 +2021,14 @@ body[data-view='settings'] .layout {
1518
2021
  * column.
1519
2022
  */
1520
2023
  #tickets .item--ticket {
1521
- padding: 8px 11px;
2024
+ padding: 9px 14px 9px 8px;
1522
2025
  }
1523
2026
  #tickets .item__body {
1524
2027
  display: grid;
1525
2028
  grid-template-columns: 6rem minmax(0, 1fr);
1526
2029
  align-items: baseline;
1527
2030
  gap: 4px 9px;
2031
+ max-width: none;
1528
2032
  }
1529
2033
  #tickets .item__meta--status {
1530
2034
  grid-column: 1;
@@ -1534,7 +2038,7 @@ body[data-view='settings'] .layout {
1534
2038
  }
1535
2039
  /*
1536
2040
  * The reserve on the right is the action strip's width. `.item__actions` is
1537
- * absolutely positioned over the card's top right and opaque, so without this it
2041
+ * absolutely positioned over the row's top right and opaque, so without this it
1538
2042
  * covers the tail of any summary long enough to reach it — on hover, and
1539
2043
  * permanently on the selected row, which is the row being read. Measured rather
1540
2044
  * than guessed: reserving the pull request board's three buttons cost 142px of
@@ -1563,10 +2067,8 @@ body[data-view='settings'] .layout {
1563
2067
  * The switch between the ticket tab's two views: what is out of sync, and what
1564
2068
  * you are working on. A segmented control rather than a second row of tabs, so it
1565
2069
  * reads as a way of looking at this tab and not as more places to go — the tabs
1566
- * above are underlined words, the status line below is a bordered bar, and this
1567
- * is neither.
1568
- */
1569
- /*
2070
+ * above are underlined words, and this is a pair of pills with one filled in.
2071
+ *
1570
2072
  * The switch and the key to the dots share a line: both describe the view
1571
2073
  * below rather than being part of it, and stacked they made a third tier under
1572
2074
  * the tabs, with the key hanging off the switch like a caption. The key goes
@@ -1578,7 +2080,7 @@ body[data-view='settings'] .layout {
1578
2080
  align-items: center;
1579
2081
  justify-content: space-between;
1580
2082
  gap: 8px 24px;
1581
- margin: 0 0 18px;
2083
+ margin: 0 0 22px;
1582
2084
  }
1583
2085
  .mode-switch {
1584
2086
  display: inline-flex;
@@ -1606,15 +2108,18 @@ body[data-view='settings'] .layout {
1606
2108
  color: var(--ink-1);
1607
2109
  }
1608
2110
  .mode-switch__option[aria-selected='true'] {
1609
- background: var(--surface);
1610
- color: var(--ink-1);
1611
- box-shadow: var(--shadow);
2111
+ background: var(--band);
2112
+ color: var(--band-ink);
1612
2113
  }
1613
2114
  .mode-switch__count {
1614
2115
  color: var(--ink-3);
1615
2116
  font-size: 12px;
1616
2117
  font-variant-numeric: tabular-nums;
1617
2118
  }
2119
+ .mode-switch__option[aria-selected='true'] .mode-switch__count {
2120
+ color: inherit;
2121
+ opacity: 0.7;
2122
+ }
1618
2123
 
1619
2124
  /*
1620
2125
  * On a Working on row whose ticket is also out of sync. The border is the due
@@ -1638,7 +2143,7 @@ body[data-view='settings'] .layout {
1638
2143
  gap: 4px 14px;
1639
2144
  /* A <p>, and its default margins made the switch's line taller whenever the key was on it. */
1640
2145
  margin: 0;
1641
- font-size: 12px;
2146
+ font-size: 12.5px;
1642
2147
  color: var(--ink-3);
1643
2148
  }
1644
2149
  .legend__entry {
@@ -1647,8 +2152,8 @@ body[data-view='settings'] .layout {
1647
2152
  gap: 6px;
1648
2153
  }
1649
2154
  .legend__dot {
1650
- width: 9px;
1651
- height: 9px;
2155
+ width: 8px;
2156
+ height: 8px;
1652
2157
  border-radius: 50%;
1653
2158
  display: block;
1654
2159
  }
@@ -1659,10 +2164,8 @@ body[data-view='settings'] .layout {
1659
2164
  * every single morning is one you stop reading by the end of the week.
1660
2165
  */
1661
2166
  .tab__badge--quiet {
1662
- background: var(--surface-sunken);
1663
- /* A shadow, not a border, so it adds nothing to the padding that centres the digits. */
1664
- box-shadow: inset 0 0 0 1px var(--hairline);
1665
- color: var(--ink-2);
2167
+ background: rgba(255, 255, 255, 0.14);
2168
+ color: var(--band-ink);
1666
2169
  }
1667
2170
 
1668
2171
  /*
@@ -1674,8 +2177,8 @@ body[data-view='settings'] .layout {
1674
2177
  * here" is actually worth knowing.
1675
2178
  */
1676
2179
  .court-hint {
1677
- margin: -6px 0 18px;
1678
- padding-left: 26px;
2180
+ margin: -10px 0 26px;
2181
+ padding: 0 8px;
1679
2182
  font-size: 12.5px;
1680
2183
  line-height: 1.5;
1681
2184
  color: var(--ink-3);
@@ -1701,8 +2204,8 @@ body[data-view='settings'] .layout {
1701
2204
 
1702
2205
  /*
1703
2206
  * Hung from the pill's left edge, where the park menu hangs from its button's
1704
- * right: the pill sits in the card's left gutter, so each menu opens toward the
1705
- * middle of its own card.
2207
+ * right: the pill sits in the row's left gutter, so each menu opens toward the
2208
+ * middle of its own row.
1706
2209
  */
1707
2210
  .menu--status {
1708
2211
  right: auto;
@@ -1712,7 +2215,7 @@ body[data-view='settings'] .layout {
1712
2215
 
1713
2216
  /* The status the ticket claims — the row's own subject, so it carries weight. */
1714
2217
  .pill--status {
1715
- border-color: var(--hairline);
2218
+ border-color: var(--border);
1716
2219
  background: var(--surface-sunken);
1717
2220
  color: var(--ink-1);
1718
2221
  font-weight: 500;
@@ -1728,43 +2231,45 @@ a.button {
1728
2231
  /* ---------- the assistant ---------- */
1729
2232
 
1730
2233
  .pill--assistant {
1731
- color: var(--accent);
2234
+ color: var(--ink-1);
1732
2235
  background: var(--accent-wash);
2236
+ border-color: transparent;
1733
2237
  }
1734
2238
 
1735
2239
  /*
1736
- * ---------- the assistant ----------
1737
- *
1738
2240
  * A section of the item panel, so the transcript scrolls with the panel's body;
1739
- * the field is pinned in the panel's foot. It used to be a box under the card
1740
- * with its own scroll region; now the panel is the box.
2241
+ * the field is pinned in the panel's foot. What was asked is set in the sans,
2242
+ * as a row is; what came back is set in the serif, as the brief is — it is the
2243
+ * part written to be read.
1741
2244
  */
1742
2245
 
1743
2246
  .assistant__turns {
1744
2247
  display: flex;
1745
2248
  flex-direction: column;
1746
- gap: 12px;
2249
+ gap: 14px;
1747
2250
  margin-bottom: 14px;
1748
2251
  }
1749
2252
 
1750
2253
  .assistant__request {
1751
2254
  margin: 0;
1752
- font-size: 12.5px;
2255
+ font-size: 13px;
1753
2256
  color: var(--ink-2);
1754
2257
  }
1755
2258
  .assistant__request strong {
1756
2259
  color: var(--ink-1);
1757
2260
  font-weight: 600;
1758
2261
  }
2262
+ .assistant__auto {
2263
+ color: var(--ink-3);
2264
+ }
1759
2265
 
1760
2266
  .assistant__reply {
1761
- margin-top: 5px;
1762
- padding: 7px 10px;
1763
- border-left: 2px solid var(--accent);
1764
- background: var(--surface);
1765
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
1766
- font-size: 13px;
1767
- line-height: 1.45;
2267
+ margin-top: 6px;
2268
+ padding: 2px 0 2px 12px;
2269
+ border-left: 2px solid var(--hairline);
2270
+ font-family: var(--font-serif);
2271
+ font-size: 14px;
2272
+ line-height: 1.55;
1768
2273
  color: var(--ink-1);
1769
2274
  overflow-wrap: anywhere;
1770
2275
  }
@@ -1772,7 +2277,7 @@ a.button {
1772
2277
  margin: 0;
1773
2278
  }
1774
2279
  .assistant__reply > * + * {
1775
- margin-top: 7px;
2280
+ margin-top: 8px;
1776
2281
  }
1777
2282
  .assistant__reply ul,
1778
2283
  .assistant__reply ol {
@@ -1782,14 +2287,17 @@ a.button {
1782
2287
  margin-top: 3px;
1783
2288
  }
1784
2289
  .assistant__reply pre {
1785
- padding: 7px 9px;
2290
+ padding: 8px 10px;
1786
2291
  border-radius: var(--radius-sm);
1787
2292
  background: var(--surface-sunken);
2293
+ font-family: var(--font-mono);
1788
2294
  font-size: 12px;
2295
+ line-height: 1.5;
1789
2296
  overflow-x: auto;
1790
2297
  white-space: pre-wrap;
1791
2298
  }
1792
2299
  .assistant__reply code {
2300
+ font-family: var(--font-mono);
1793
2301
  font-size: 12px;
1794
2302
  }
1795
2303
  .assistant__reply blockquote {
@@ -1818,6 +2326,7 @@ a.button {
1818
2326
  background: var(--surface);
1819
2327
  color: var(--ink-3);
1820
2328
  font: inherit;
2329
+ font-family: var(--font);
1821
2330
  font-size: 11px;
1822
2331
  cursor: pointer;
1823
2332
  }
@@ -1828,7 +2337,7 @@ a.button {
1828
2337
 
1829
2338
  .assistant__status {
1830
2339
  margin: 4px 0 0;
1831
- font-size: 12px;
2340
+ font-size: 12.5px;
1832
2341
  color: var(--ink-3);
1833
2342
  }
1834
2343
  .assistant__status--bad {
@@ -1847,7 +2356,7 @@ a.button {
1847
2356
  width: 9px;
1848
2357
  height: 9px;
1849
2358
  border-radius: 50%;
1850
- border: 1.5px solid var(--accent);
2359
+ border: 1.5px solid var(--ink-1);
1851
2360
  border-top-color: transparent;
1852
2361
  animation: assistant-spin 0.9s linear infinite;
1853
2362
  }
@@ -1875,24 +2384,24 @@ a.button {
1875
2384
  margin-top: 4px;
1876
2385
  }
1877
2386
  .assistant__work > summary {
1878
- font-size: 12px;
2387
+ font-size: 12.5px;
1879
2388
  color: var(--ink-3);
1880
2389
  cursor: pointer;
1881
2390
  }
1882
2391
  .assistant__work > summary:hover {
1883
- color: var(--ink-2);
2392
+ color: var(--ink-1);
1884
2393
  }
1885
2394
  .assistant__took {
1886
2395
  margin: 4px 0 0;
1887
- font-size: 12px;
2396
+ font-size: 12.5px;
1888
2397
  color: var(--ink-3);
1889
2398
  }
1890
2399
  .assistant__steps {
1891
- margin: 5px 0 0;
2400
+ margin: 6px 0 0;
1892
2401
  padding: 0 0 0 10px;
1893
2402
  border-left: 2px solid var(--hairline);
1894
2403
  list-style: none;
1895
- font-size: 12px;
2404
+ font-size: 12.5px;
1896
2405
  line-height: 1.45;
1897
2406
  color: var(--ink-2);
1898
2407
  }
@@ -1934,14 +2443,17 @@ a.button {
1934
2443
  overflow: hidden;
1935
2444
  text-overflow: ellipsis;
1936
2445
  white-space: nowrap;
2446
+ font-family: var(--font-mono);
1937
2447
  font-size: 11.5px;
1938
2448
  color: var(--ink-3);
1939
2449
  }
1940
- /* What it said on the way: its own words, set apart from the calls by having no mark. */
2450
+ /* What it said on the way: its own words, in the reading face, set apart from the calls by having no mark. */
1941
2451
  .assistant__step--message {
1942
2452
  display: block;
1943
2453
  padding-left: 15px;
2454
+ font-family: var(--font-serif);
1944
2455
  font-style: italic;
2456
+ font-size: 13px;
1945
2457
  color: var(--ink-3);
1946
2458
  white-space: pre-line;
1947
2459
  overflow-wrap: anywhere;
@@ -1952,7 +2464,7 @@ a.button {
1952
2464
  display: flex;
1953
2465
  flex-wrap: wrap;
1954
2466
  gap: 6px;
1955
- margin-top: 6px;
2467
+ margin-top: 8px;
1956
2468
  }
1957
2469
 
1958
2470
  .assistant__quick {
@@ -1973,10 +2485,10 @@ a.button {
1973
2485
  padding: 8px 10px;
1974
2486
  border: 1px solid var(--border);
1975
2487
  border-radius: var(--radius-sm);
1976
- background: var(--page);
2488
+ background: var(--surface);
1977
2489
  color: var(--ink-1);
1978
2490
  font: inherit;
1979
- font-size: 13px;
2491
+ font-size: 13.5px;
1980
2492
  line-height: 1.4;
1981
2493
  resize: vertical;
1982
2494
  }
@@ -1990,12 +2502,15 @@ a.button {
1990
2502
  * The panel takes the side column: on Today it stands in for the agenda while it
1991
2503
  * is open, and on the boards it brings the column back. In the grid rather than
1992
2504
  * over it, so the list is never covered, and sticky like the agenda so a long
1993
- * list scrolls past a panel that stays put. Placed after the view rules above
1994
- * on purpose: they and these share a specificity, and the panel being open has
2505
+ * list scrolls past a panel that stays put. It is the one surface on the page
2506
+ * with an edge of its own, because it is the one thing that floats over the
2507
+ * sheet rather than being written on it. Placed after the view rules above on
2508
+ * purpose: they and these share a specificity, and the panel being open has
1995
2509
  * to win.
1996
2510
  */
1997
2511
  body[data-flyout='open'] .layout {
1998
2512
  grid-template-columns: minmax(0, 1fr) 420px;
2513
+ gap: 40px;
1999
2514
  }
2000
2515
  body[data-flyout='open'] .layout__side {
2001
2516
  display: none;
@@ -2010,8 +2525,8 @@ body[data-flyout='open'] .layout__side {
2010
2525
  max-height: calc(100vh - 32px);
2011
2526
  background: var(--surface);
2012
2527
  border: 1px solid var(--border);
2013
- border-radius: var(--radius);
2014
- box-shadow: var(--shadow);
2528
+ border-radius: 12px;
2529
+ box-shadow: var(--shadow-float);
2015
2530
  }
2016
2531
  .flyout[hidden] {
2017
2532
  display: none;
@@ -2021,7 +2536,7 @@ body[data-flyout='open'] .layout__side {
2021
2536
  display: grid;
2022
2537
  grid-template-columns: minmax(0, 1fr) auto;
2023
2538
  gap: 5px 10px;
2024
- padding: 14px 16px 13px;
2539
+ padding: 16px 18px 14px;
2025
2540
  border-bottom: 1px solid var(--hairline);
2026
2541
  }
2027
2542
  .flyout__where {
@@ -2029,7 +2544,7 @@ body[data-flyout='open'] .layout__side {
2029
2544
  flex-wrap: wrap;
2030
2545
  align-items: center;
2031
2546
  gap: 6px;
2032
- font-size: 12px;
2547
+ font-size: 12.5px;
2033
2548
  color: var(--ink-3);
2034
2549
  }
2035
2550
  .flyout__close {
@@ -2040,7 +2555,7 @@ body[data-flyout='open'] .layout__side {
2040
2555
  .flyout__title {
2041
2556
  grid-column: 1;
2042
2557
  margin: 0;
2043
- font-size: 15px;
2558
+ font-size: 15.5px;
2044
2559
  font-weight: 500;
2045
2560
  line-height: 1.4;
2046
2561
  color: var(--ink-1);
@@ -2052,11 +2567,11 @@ body[data-flyout='open'] .layout__side {
2052
2567
  }
2053
2568
  .flyout__title a:hover {
2054
2569
  text-decoration: underline;
2055
- text-decoration-color: var(--accent);
2570
+ text-decoration-color: var(--ink-3);
2056
2571
  }
2057
2572
 
2058
2573
  /*
2059
- * A ticket's status and park, laid out as on its card: the status at the left,
2574
+ * A ticket's status and park, laid out as on its row: the status at the left,
2060
2575
  * the park at the right, so each menu opens into the panel rather than out over
2061
2576
  * the list. Under the close button too, so the park lines up with it. A child
2062
2577
  * combinator, because the park menu's own Set button is a `.button` in here.
@@ -2076,17 +2591,20 @@ body[data-flyout='open'] .layout__side {
2076
2591
  flex: 1;
2077
2592
  min-height: 0;
2078
2593
  overflow-y: auto;
2079
- padding: 16px 16px 20px;
2594
+ padding: 18px 18px 22px;
2080
2595
  }
2081
2596
  /* The assistant's field and its canned asks, pinned under the body that scrolls. */
2082
2597
  .flyout__footer {
2083
2598
  flex: none;
2084
- padding: 12px 16px 14px;
2599
+ padding: 12px 18px 16px;
2085
2600
  border-top: 1px solid var(--hairline);
2086
2601
  }
2602
+ /* What the agent wrote under the row: the brief's own words, so the reading face. */
2087
2603
  .flyout__detail {
2088
- margin: 0 0 22px;
2089
- font-size: 13px;
2604
+ margin: 0 0 24px;
2605
+ font-family: var(--font-serif);
2606
+ font-size: 14px;
2607
+ line-height: 1.55;
2090
2608
  color: var(--ink-2);
2091
2609
  overflow-wrap: anywhere;
2092
2610
  }
@@ -2094,28 +2612,29 @@ body[data-flyout='open'] .layout__side {
2094
2612
  padding: 1px 4px;
2095
2613
  background: var(--surface-sunken);
2096
2614
  border-radius: 3px;
2097
- font-size: 0.92em;
2615
+ font-family: var(--font-mono);
2616
+ font-size: 0.9em;
2098
2617
  }
2099
2618
 
2100
2619
  .flyout__section + .flyout__section {
2101
- margin-top: 26px;
2620
+ margin-top: 28px;
2102
2621
  }
2103
2622
  .flyout__label {
2104
2623
  margin: 0 0 10px;
2105
- font-size: 11.5px;
2624
+ padding: 0 0 6px;
2625
+ border-bottom: 1px solid var(--hairline);
2626
+ font-size: 12.5px;
2106
2627
  font-weight: 600;
2107
- letter-spacing: 0.04em;
2108
- text-transform: uppercase;
2109
- color: var(--ink-3);
2628
+ color: var(--ink-2);
2110
2629
  }
2111
2630
 
2112
2631
  .flyout__notes {
2113
2632
  margin: 0 0 12px;
2114
- padding: 7px 10px;
2633
+ padding: 2px 0 2px 12px;
2115
2634
  border-left: 2px solid var(--hairline);
2116
- background: var(--surface-sunken);
2117
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
2118
- font-size: 12.5px;
2635
+ font-family: var(--font-serif);
2636
+ font-size: 13.5px;
2637
+ line-height: 1.5;
2119
2638
  color: var(--ink-2);
2120
2639
  }
2121
2640
  .flyout__note {
@@ -2126,12 +2645,13 @@ body[data-flyout='open'] .layout__side {
2126
2645
  }
2127
2646
  .flyout__when {
2128
2647
  color: var(--ink-3);
2648
+ font-family: var(--font);
2129
2649
  font-size: 11.5px;
2130
2650
  white-space: nowrap;
2131
2651
  }
2132
2652
  .flyout__empty {
2133
2653
  margin: 0 0 10px;
2134
- font-size: 12.5px;
2654
+ font-size: 13px;
2135
2655
  color: var(--ink-3);
2136
2656
  }
2137
2657
 
@@ -2153,10 +2673,10 @@ body[data-flyout='open'] .layout__side {
2153
2673
  padding: 0 10px;
2154
2674
  border: 1px solid var(--border);
2155
2675
  border-radius: var(--radius-sm);
2156
- background: var(--page);
2676
+ background: var(--surface);
2157
2677
  color: var(--ink-1);
2158
2678
  font: inherit;
2159
- font-size: 13px;
2679
+ font-size: 13.5px;
2160
2680
  }
2161
2681
  .flyout__submit {
2162
2682
  flex: none;
@@ -2175,7 +2695,7 @@ body[data-flyout='open'] .layout__side {
2175
2695
  z-index: 15;
2176
2696
  max-height: 80vh;
2177
2697
  border-bottom: 0;
2178
- border-radius: var(--radius) var(--radius) 0 0;
2698
+ border-radius: 12px 12px 0 0;
2179
2699
  }
2180
2700
  /* The sheet has the bottom, so a toast goes to the top rather than over its field. */
2181
2701
  body[data-flyout='open'] .toast {
@@ -2190,178 +2710,750 @@ body[data-flyout='open'] .layout__side {
2190
2710
  padding: 0;
2191
2711
  border: 0;
2192
2712
  background: none;
2193
- color: var(--accent);
2713
+ color: var(--ink-1);
2194
2714
  font: inherit;
2715
+ text-decoration: underline;
2716
+ text-decoration-color: var(--ink-3);
2717
+ text-underline-offset: 2px;
2195
2718
  cursor: pointer;
2196
2719
  }
2197
2720
  .link-button:hover {
2198
- text-decoration: underline;
2721
+ text-decoration-color: currentColor;
2199
2722
  }
2200
2723
  .objective__edit {
2201
- margin-left: 8px;
2202
- font-size: 11px;
2724
+ font-size: 12.5px;
2725
+ font-weight: 500;
2726
+ color: var(--ink-3);
2727
+ text-decoration: none;
2728
+ }
2729
+ .objective__edit:hover {
2730
+ color: var(--ink-1);
2731
+ text-decoration: underline;
2732
+ }
2733
+
2734
+ /* ---------- the first brief, after setup ---------- */
2735
+
2736
+ /*
2737
+ * Today between the setup screen and the first brief. Set as the objective is,
2738
+ * since it does the same job in its place: the first thing read, before
2739
+ * anything else exists. On the paper, not the band: the band holds a morning's
2740
+ * masthead, and there is no morning yet.
2741
+ */
2742
+ .first-brief {
2743
+ max-width: 60ch;
2744
+ padding: 10px 0 0;
2745
+ }
2746
+ .first-brief__title {
2747
+ margin: 0 0 8px;
2748
+ font-family: var(--font-serif);
2749
+ font-size: 26px;
2750
+ font-weight: 500;
2751
+ line-height: 1.2;
2752
+ letter-spacing: -0.005em;
2753
+ }
2754
+ .first-brief__text {
2755
+ margin: 0;
2756
+ color: var(--ink-2);
2757
+ font-size: 14.5px;
2758
+ line-height: 1.55;
2759
+ }
2760
+ .first-brief__actions {
2761
+ display: flex;
2762
+ flex-wrap: wrap;
2763
+ gap: 8px;
2764
+ margin-top: 18px;
2765
+ }
2766
+ .first-brief .button {
2767
+ padding: 7px 14px;
2768
+ font-size: 13.5px;
2769
+ }
2770
+
2771
+ /* ---------- the setup screen ---------- */
2772
+
2773
+ /*
2774
+ * The whole page while a new store is set up: one column, one question open at
2775
+ * a time, on a thread whose dots are the questions. Answered ones fold into a
2776
+ * sentence; the open one is the only card. The questions are set in the serif,
2777
+ * since they are read once and slowly, and the buttons here are larger than the
2778
+ * dashboard's: each one is a decision.
2779
+ */
2780
+ /* The page's own margins are the dashboard's; this one runs edge to edge. */
2781
+ body[data-onboarding='true'] #app {
2782
+ padding: 0;
2783
+ }
2784
+ .onboarding {
2785
+ min-height: 100vh;
2786
+ background: var(--page);
2787
+ }
2788
+ .onboarding__bar {
2789
+ position: sticky;
2790
+ top: 0;
2791
+ z-index: 2;
2792
+ display: flex;
2793
+ align-items: center;
2794
+ gap: 18px;
2795
+ padding: 14px 28px;
2796
+ background: var(--band);
2797
+ font-size: 13px;
2798
+ color: var(--band-muted);
2799
+ }
2800
+ .onboarding__name {
2801
+ color: var(--band-ink);
2802
+ font-weight: 600;
2803
+ font-size: 14px;
2804
+ }
2805
+ .onboarding__progress {
2806
+ flex: 1;
2807
+ display: flex;
2808
+ align-items: center;
2809
+ gap: 10px;
2810
+ }
2811
+ .onboarding__track {
2812
+ flex: 1;
2813
+ max-width: 220px;
2814
+ height: 4px;
2815
+ border-radius: 2px;
2816
+ background: rgba(255, 255, 255, 0.2);
2817
+ overflow: hidden;
2818
+ }
2819
+ .onboarding__track i {
2820
+ display: block;
2821
+ height: 100%;
2822
+ background: var(--accent);
2823
+ border-radius: 2px;
2824
+ transition: width 0.3s ease;
2825
+ }
2826
+ .onboarding__column {
2827
+ max-width: 640px;
2828
+ margin: 0 auto;
2829
+ padding: 40px 24px 30vh;
2830
+ }
2831
+ .onboarding__lede {
2832
+ margin: 0 0 28px;
2833
+ padding-left: 30px;
2834
+ font-family: var(--font-serif);
2835
+ color: var(--ink-2);
2836
+ font-size: 17px;
2837
+ line-height: 1.55;
2838
+ }
2839
+ .onboarding__thread {
2840
+ position: relative;
2841
+ margin: 0;
2842
+ padding: 0 0 0 30px;
2843
+ list-style: none;
2844
+ }
2845
+ /* The thread: one hairline the dots sit on. */
2846
+ .onboarding__thread::before {
2847
+ content: '';
2848
+ position: absolute;
2849
+ left: 6px;
2850
+ top: 10px;
2851
+ bottom: 10px;
2852
+ width: 1px;
2853
+ background: var(--hairline);
2854
+ }
2855
+ .onboarding__thread > li {
2856
+ position: relative;
2857
+ }
2858
+ .onboarding__dot {
2859
+ position: absolute;
2860
+ left: -28px;
2861
+ top: 10px;
2862
+ width: 9px;
2863
+ height: 9px;
2864
+ border-radius: 50%;
2865
+ background: var(--ink-3);
2866
+ box-shadow: 0 0 0 3px var(--page);
2867
+ }
2868
+ .onboarding__dot--open {
2869
+ left: -30px;
2870
+ top: 13px;
2871
+ width: 13px;
2872
+ height: 13px;
2873
+ background: var(--accent);
2874
+ }
2875
+ .onboarding__dot--looking,
2876
+ .onboarding__dot--later {
2877
+ left: -29px;
2878
+ top: 6px;
2879
+ width: 8px;
2880
+ height: 8px;
2881
+ background: var(--page);
2882
+ border: 1.5px solid var(--ink-1);
2883
+ }
2884
+ .onboarding__dot--later {
2885
+ border-color: var(--hairline);
2886
+ background: var(--hairline);
2887
+ }
2888
+ .onboarding__done {
2889
+ display: flex;
2890
+ align-items: baseline;
2891
+ gap: 12px;
2892
+ padding: 5px 0;
2893
+ color: var(--ink-2);
2894
+ font-size: 14.5px;
2895
+ line-height: 1.5;
2896
+ }
2897
+ .onboarding__done[data-status='later'] {
2898
+ color: var(--ink-3);
2899
+ }
2900
+ .onboarding__done[data-status='later'] .onboarding__dot {
2901
+ background: var(--page);
2902
+ border: 1.5px solid var(--ink-3);
2903
+ width: 6px;
2904
+ height: 6px;
2905
+ }
2906
+ .onboarding__summary {
2907
+ flex: 1;
2908
+ min-width: 0;
2909
+ }
2910
+ .onboarding__change {
2911
+ padding: 0;
2912
+ border: 0;
2913
+ background: none;
2914
+ color: var(--ink-3);
2915
+ font: inherit;
2916
+ font-size: 13px;
2917
+ cursor: pointer;
2918
+ }
2919
+ .onboarding__change:hover {
2920
+ color: var(--ink-1);
2921
+ text-decoration: underline;
2922
+ }
2923
+ .onboarding__change:disabled {
2924
+ visibility: hidden;
2925
+ }
2926
+
2927
+ .onboarding__card {
2928
+ margin: 24px 0 30px;
2929
+ scroll-margin: 90px 0 120px;
2930
+ }
2931
+ .onboarding__card h2 {
2932
+ margin: 0 0 12px;
2933
+ font-family: var(--font-serif);
2934
+ font-size: 27px;
2935
+ line-height: 1.2;
2936
+ font-weight: 500;
2937
+ letter-spacing: -0.005em;
2938
+ text-wrap: balance;
2939
+ }
2940
+ .onboarding__card h2:focus {
2941
+ outline: none;
2942
+ }
2943
+ .onboarding__why {
2944
+ display: flex;
2945
+ gap: 10px;
2946
+ margin: 0 0 18px;
2947
+ color: var(--ink-2);
2948
+ font-size: 14.5px;
2949
+ line-height: 1.5;
2950
+ }
2951
+ /*
2952
+ * What it said and what the user told it, in order, under the question: its
2953
+ * lines as the reason always reads, the user's set off to the right.
2954
+ */
2955
+ .onboarding__talk {
2956
+ display: grid;
2957
+ gap: 10px;
2958
+ margin: 0 0 16px;
2959
+ padding: 0;
2960
+ list-style: none;
2961
+ }
2962
+ .onboarding__talk .onboarding__why {
2963
+ margin: 0;
2964
+ }
2965
+ .onboarding__said {
2966
+ justify-self: end;
2967
+ max-width: 85%;
2968
+ padding: 7px 12px;
2969
+ border-radius: 12px 12px 4px 12px;
2970
+ background: var(--accent-wash);
2971
+ color: var(--ink-1);
2972
+ font-size: 14.5px;
2973
+ line-height: 1.45;
2974
+ }
2975
+ .onboarding__sparkle {
2976
+ flex: none;
2977
+ margin-top: 3px;
2978
+ color: var(--accent-ink);
2979
+ }
2980
+ .onboarding__looking {
2981
+ margin: 0 0 16px;
2982
+ font-size: 14px;
2983
+ color: var(--ink-2);
2984
+ }
2985
+ .onboarding__looking p,
2986
+ .onboarding__next p {
2987
+ margin: 0 0 4px;
2988
+ }
2989
+ .onboarding__steps {
2990
+ margin: 0;
2991
+ padding: 0;
2992
+ list-style: none;
2993
+ font-size: 13px;
2994
+ color: var(--ink-3);
2995
+ }
2996
+ .onboarding__steps li {
2997
+ padding: 2px 0;
2998
+ overflow: hidden;
2999
+ text-overflow: ellipsis;
3000
+ white-space: nowrap;
3001
+ }
3002
+ .onboarding__steps li::before {
3003
+ content: '✓';
3004
+ display: inline-block;
3005
+ width: 17px;
3006
+ color: var(--good-ink);
3007
+ }
3008
+ .onboarding__steps li[data-state='failed']::before {
3009
+ content: '!';
3010
+ color: var(--serious);
3011
+ }
3012
+ .onboarding__steps li[data-state='running']::before {
3013
+ content: '';
3014
+ width: 8px;
3015
+ height: 8px;
3016
+ margin-right: 9px;
3017
+ border-radius: 50%;
3018
+ border: 1.5px solid var(--ink-3);
3019
+ border-top-color: transparent;
3020
+ animation: onboarding-spin 0.9s linear infinite;
3021
+ }
3022
+ @keyframes onboarding-spin {
3023
+ to {
3024
+ transform: rotate(360deg);
3025
+ }
3026
+ }
3027
+ @media (prefers-reduced-motion: reduce) {
3028
+ .onboarding__steps li[data-state='running']::before {
3029
+ animation: none;
3030
+ }
3031
+ .onboarding__track i {
3032
+ transition: none;
3033
+ }
3034
+ }
3035
+ .onboarding__note {
3036
+ margin: 0 0 14px;
3037
+ color: var(--ink-2);
3038
+ font-size: 13.5px;
3039
+ }
3040
+ .onboarding__problem {
3041
+ margin: 0 0 16px;
3042
+ padding: 2px 0 2px 12px;
3043
+ border-left: 3px solid var(--serious);
3044
+ color: var(--ink-2);
3045
+ font-size: 14px;
3046
+ line-height: 1.5;
3047
+ }
3048
+ .onboarding__problem p {
3049
+ margin: 0 0 8px;
3050
+ }
3051
+ .onboarding__links {
3052
+ display: flex;
3053
+ flex-wrap: wrap;
3054
+ gap: 16px;
3055
+ }
3056
+ .onboarding__problem[data-blocking='false'] {
3057
+ margin: 0;
3058
+ border-left-color: var(--hairline);
3059
+ font-size: 13.5px;
3060
+ }
3061
+ .onboarding__problem pre {
3062
+ margin: 0 0 10px;
3063
+ padding: 8px 10px;
3064
+ background: var(--surface-sunken);
3065
+ border-radius: var(--radius-sm);
3066
+ font-family: var(--font-mono);
3067
+ font-size: 13px;
3068
+ overflow-x: auto;
3069
+ }
3070
+ .onboarding__form {
3071
+ display: grid;
3072
+ gap: 16px;
3073
+ }
3074
+ .onboarding__choice {
3075
+ margin: 0;
3076
+ padding: 0;
3077
+ border: 0;
3078
+ min-width: 0;
3079
+ }
3080
+ .onboarding__legend {
3081
+ margin-bottom: 8px;
3082
+ padding: 0;
3083
+ color: var(--ink-2);
3084
+ font-size: 13px;
3085
+ font-weight: 600;
3086
+ }
3087
+ .onboarding__pills {
3088
+ display: flex;
3089
+ flex-wrap: wrap;
3090
+ gap: 8px;
3091
+ }
3092
+ .onboarding__pill {
3093
+ padding: 6px 13px;
3094
+ border: 1px solid var(--border);
3095
+ border-radius: 999px;
3096
+ background: transparent;
3097
+ color: var(--ink-1);
3098
+ font: inherit;
3099
+ font-size: 14px;
3100
+ cursor: pointer;
3101
+ }
3102
+ .onboarding__pill:hover {
3103
+ border-color: var(--ink-3);
3104
+ background: var(--surface-sunken);
3105
+ }
3106
+ .onboarding__pill[aria-checked='true'] {
3107
+ border-color: var(--band);
3108
+ background: var(--band);
3109
+ color: var(--band-ink);
2203
3110
  font-weight: 500;
2204
- letter-spacing: normal;
2205
- text-transform: none;
2206
3111
  }
2207
-
2208
- /* ---------- setup, before the first brief ---------- */
2209
-
2210
- /*
2211
- * The page a new store opens on. Built from the objective's card, since it does
2212
- * the same job in its place: the first thing read, before anything else exists.
2213
- */
2214
- .setup {
2215
- padding: 18px 20px;
2216
- background: var(--surface);
2217
- border: 1px solid var(--border);
2218
- border-left: 3px solid var(--accent);
2219
- border-radius: var(--radius);
2220
- box-shadow: var(--shadow);
3112
+ .onboarding__list {
3113
+ background: var(--surface);
3114
+ border: 1px solid var(--border);
3115
+ border-radius: var(--radius);
3116
+ overflow: hidden;
3117
+ }
3118
+ .onboarding__group + .onboarding__group,
3119
+ .onboarding__adder {
3120
+ border-top: 1px solid var(--hairline);
3121
+ }
3122
+ .onboarding__group-name {
3123
+ margin: 0;
3124
+ padding: 12px 16px 4px;
3125
+ color: var(--ink-3);
3126
+ font-size: 12.5px;
3127
+ font-weight: 600;
3128
+ }
3129
+ .onboarding__option {
3130
+ position: relative;
3131
+ display: flex;
3132
+ align-items: flex-start;
3133
+ gap: 12px;
3134
+ padding: 8px 16px;
3135
+ cursor: pointer;
3136
+ }
3137
+ .onboarding__group > .onboarding__option:first-child {
3138
+ padding-top: 12px;
3139
+ }
3140
+ .onboarding__group > .onboarding__option:last-child {
3141
+ padding-bottom: 12px;
3142
+ }
3143
+ .onboarding__option:hover {
3144
+ background: var(--surface-sunken);
3145
+ }
3146
+ .onboarding__option input {
3147
+ position: absolute;
3148
+ opacity: 0;
3149
+ pointer-events: none;
3150
+ }
3151
+ .onboarding__box {
3152
+ flex: none;
3153
+ display: grid;
3154
+ place-items: center;
3155
+ width: 18px;
3156
+ height: 18px;
3157
+ margin-top: 1px;
3158
+ border: 1.5px solid var(--ink-3);
3159
+ border-radius: 5px;
3160
+ }
3161
+ .onboarding__box[data-kind='radio'] {
3162
+ border-radius: 50%;
3163
+ }
3164
+ .onboarding__option input:checked + .onboarding__box {
3165
+ border-color: var(--band);
3166
+ background: var(--band);
3167
+ }
3168
+ .onboarding__option input:checked + .onboarding__box[data-kind='check']::after {
3169
+ content: '';
3170
+ width: 9px;
3171
+ height: 5px;
3172
+ border-left: 2px solid var(--band-ink);
3173
+ border-bottom: 2px solid var(--band-ink);
3174
+ transform: translateY(-1px) rotate(-45deg);
3175
+ }
3176
+ .onboarding__option input:checked + .onboarding__box[data-kind='radio']::after {
3177
+ content: '';
3178
+ width: 6px;
3179
+ height: 6px;
3180
+ border-radius: 50%;
3181
+ background: var(--band-ink);
3182
+ }
3183
+ .onboarding__option input:focus-visible + .onboarding__box {
3184
+ outline: 2px solid var(--focus-ring);
3185
+ outline-offset: 2px;
3186
+ }
3187
+ .onboarding__option-text {
3188
+ display: flex;
3189
+ flex-direction: column;
3190
+ font-size: 15px;
3191
+ }
3192
+ .onboarding__option-text small,
3193
+ .onboarding__field small {
3194
+ color: var(--ink-3);
3195
+ font-size: 13px;
3196
+ }
3197
+ .onboarding__none {
3198
+ margin: 0;
3199
+ padding: 12px 16px;
3200
+ color: var(--ink-3);
3201
+ font-size: 14px;
3202
+ }
3203
+ .onboarding__adder {
3204
+ padding: 4px 16px;
3205
+ }
3206
+ .onboarding__add-button {
3207
+ padding: 8px 0;
3208
+ border: 0;
3209
+ background: none;
3210
+ color: var(--ink-1);
3211
+ font: inherit;
3212
+ font-size: 14px;
3213
+ text-decoration: underline;
3214
+ text-decoration-color: var(--ink-3);
3215
+ text-underline-offset: 2px;
3216
+ cursor: pointer;
3217
+ }
3218
+ .onboarding__add-button:hover {
3219
+ text-decoration-color: currentColor;
3220
+ }
3221
+ .onboarding__pills .onboarding__add-button {
3222
+ padding: 6px 4px;
3223
+ }
3224
+ .onboarding__add {
3225
+ display: flex;
3226
+ gap: 8px;
3227
+ padding: 6px 0;
2221
3228
  }
2222
- .setup__title {
2223
- margin: 0 0 6px;
2224
- font-size: 18px;
2225
- letter-spacing: -0.01em;
3229
+ .onboarding__add input,
3230
+ .onboarding__field input,
3231
+ .onboarding__tell input {
3232
+ flex: 1;
3233
+ min-width: 0;
3234
+ height: 36px;
3235
+ padding: 0 10px;
3236
+ border: 1px solid var(--border);
3237
+ border-radius: var(--radius-sm);
3238
+ background: var(--surface);
3239
+ color: var(--ink-1);
3240
+ font: inherit;
3241
+ font-size: 14.5px;
2226
3242
  }
2227
- .setup__lede {
2228
- margin: 0 0 16px;
2229
- color: var(--ink-2);
2230
- font-size: 13.5px;
2231
- line-height: 1.5;
3243
+ .onboarding__fields {
3244
+ display: grid;
3245
+ gap: 14px;
2232
3246
  }
2233
- .setup__steps {
3247
+ .onboarding__field,
3248
+ .onboarding__field > label {
2234
3249
  display: grid;
2235
3250
  gap: 4px;
2236
- margin: 0;
3251
+ }
3252
+ .onboarding__suggestions {
3253
+ display: grid;
3254
+ gap: 6px;
3255
+ margin: 4px 0 0;
2237
3256
  padding: 0;
2238
3257
  list-style: none;
2239
3258
  }
2240
- .setup__step {
3259
+ .onboarding__suggestions button {
2241
3260
  display: grid;
2242
- grid-template-columns: 22px minmax(0, 1fr);
2243
- gap: 10px;
2244
- padding: 12px 0;
2245
- border-top: 1px solid var(--hairline);
3261
+ gap: 1px;
3262
+ width: 100%;
3263
+ padding: 8px 12px;
3264
+ border: 1px dashed var(--border);
3265
+ border-radius: var(--radius-sm);
3266
+ background: none;
3267
+ color: var(--ink-1);
3268
+ font: inherit;
3269
+ font-size: 14px;
3270
+ text-align: left;
3271
+ cursor: pointer;
2246
3272
  }
2247
- .setup__mark {
2248
- font-size: 15px;
2249
- line-height: 1.3;
2250
- color: var(--ink-3);
2251
- text-align: center;
3273
+ .onboarding__suggestions button:hover,
3274
+ .onboarding__suggestions button[aria-pressed='true'] {
3275
+ border-style: solid;
3276
+ border-color: var(--accent);
3277
+ background: var(--accent-wash);
2252
3278
  }
2253
- .setup__step[data-done='true'] .setup__mark {
2254
- color: var(--good-ink);
3279
+ .onboarding__suggestions small {
3280
+ color: var(--ink-3);
3281
+ font-size: 12.5px;
2255
3282
  }
2256
- .setup__step[data-done='false'] .setup__mark {
2257
- color: var(--accent);
3283
+ /* Asked in place of the buttons, where the eye already is. */
3284
+ .onboarding__confirm {
3285
+ padding: 12px 14px;
3286
+ border-radius: var(--radius);
3287
+ background: var(--surface-sunken);
2258
3288
  }
2259
- .setup__step-title {
3289
+ .onboarding__confirm p {
3290
+ flex-basis: 100%;
2260
3291
  margin: 0 0 4px;
3292
+ color: var(--ink-2);
2261
3293
  font-size: 14px;
2262
- font-weight: 600;
2263
3294
  }
2264
- .setup__body p {
2265
- margin: 0 0 8px;
3295
+ .onboarding__field-label {
3296
+ font-size: 13.5px;
3297
+ font-weight: 500;
2266
3298
  color: var(--ink-2);
2267
- font-size: 13px;
2268
- line-height: 1.5;
2269
3299
  }
2270
- .setup__step[data-done='true'] .setup__body p {
2271
- color: var(--ink-3);
3300
+ .onboarding__error {
3301
+ margin: 0;
3302
+ color: var(--critical);
3303
+ font-size: 13.5px;
2272
3304
  }
2273
- .setup__choices {
3305
+ .onboarding__actions {
2274
3306
  display: flex;
2275
3307
  flex-wrap: wrap;
2276
- gap: 8px;
2277
- }
2278
- .setup__boards {
2279
- display: grid;
2280
- gap: 8px;
2281
- margin: 0;
2282
- padding: 0;
2283
- list-style: none;
2284
- }
2285
- .setup__board {
2286
- display: grid;
2287
- grid-template-columns: 16px 104px minmax(0, 1fr) auto;
3308
+ align-items: center;
2288
3309
  gap: 10px;
2289
- align-items: baseline;
2290
- font-size: 13px;
2291
3310
  }
2292
- .setup__board-name {
2293
- font-weight: 500;
3311
+ .onboarding .button {
3312
+ padding: 9px 16px;
3313
+ border-radius: var(--radius);
3314
+ font-size: 14.5px;
3315
+ font-weight: 550;
2294
3316
  }
2295
- .setup__board-text {
3317
+ .onboarding .onboarding__quiet {
3318
+ border-color: transparent;
3319
+ background: none;
2296
3320
  color: var(--ink-2);
2297
3321
  }
2298
- /*
2299
- * The mark says how a board is doing; the words beside it say it again, so the
2300
- * colour is never the only cue, and the words stay one colour for every state.
2301
- */
2302
- .setup__board-mark {
2303
- font-weight: 600;
2304
- text-align: center;
2305
- color: var(--ink-3);
2306
- }
2307
- .setup__board[data-health='ok'] .setup__board-mark {
2308
- color: var(--good-ink);
3322
+ .onboarding .onboarding__quiet:hover {
3323
+ color: var(--ink-1);
3324
+ background: var(--surface-sunken);
2309
3325
  }
2310
- .setup__board[data-health='problem'] .setup__board-mark {
2311
- color: var(--serious);
3326
+ .onboarding__tell {
3327
+ display: flex;
3328
+ gap: 8px;
3329
+ margin: 0 0 18px;
2312
3330
  }
2313
- .setup__board[data-health='todo'] .setup__board-mark {
2314
- color: var(--accent);
3331
+ .onboarding .onboarding__tell .button {
3332
+ padding: 6px 12px;
3333
+ font-weight: 500;
2315
3334
  }
2316
- .setup__body .setup__note {
3335
+ .onboarding__ahead {
2317
3336
  color: var(--ink-3);
3337
+ font-size: 14px;
2318
3338
  }
2319
- .setup__body .setup__note--todo {
2320
- color: var(--serious);
2321
- }
2322
- .setup__editor {
2323
- margin-top: 12px;
3339
+ .onboarding__next {
3340
+ position: relative;
3341
+ margin-bottom: 14px;
3342
+ color: var(--ink-2);
2324
3343
  }
2325
- /* The settings page's own fold and fields, inside a step. */
2326
- .setup__body .setup__advanced p {
3344
+ .onboarding__then {
3345
+ position: relative;
2327
3346
  margin: 0;
2328
- font-size: 12px;
2329
- line-height: 1.45;
2330
3347
  }
2331
- .setup__advanced .field {
2332
- max-width: 480px;
3348
+ .onboarding__preview {
3349
+ margin: 0 0 18px;
3350
+ }
3351
+ .onboarding__preview > summary {
3352
+ cursor: pointer;
3353
+ color: var(--ink-2);
3354
+ font-size: 14px;
3355
+ }
3356
+ .onboarding__preview > summary:hover {
3357
+ color: var(--ink-1);
2333
3358
  }
2334
- .setup__advanced-actions {
2335
- display: flex;
2336
- justify-content: flex-start;
3359
+ .onboarding__preview pre {
3360
+ max-height: 360px;
3361
+ margin: 10px 0 0;
3362
+ padding: 12px 14px;
3363
+ overflow: auto;
3364
+ background: var(--surface);
3365
+ border: 1px solid var(--border);
3366
+ border-radius: var(--radius-sm);
3367
+ font-family: var(--font-mono);
3368
+ font-size: 12.5px;
3369
+ line-height: 1.5;
3370
+ white-space: pre-wrap;
3371
+ }
3372
+ .onboarding__preview p {
3373
+ margin: 8px 0 0;
3374
+ color: var(--ink-2);
3375
+ font-size: 13.5px;
2337
3376
  }
2338
3377
 
2339
3378
  /* ---------- settings ---------- */
2340
3379
 
3380
+ /*
3381
+ * A column of groups, each a sheet titled in the serif, with an index beside
3382
+ * them that stays put as the page scrolls and says where on it you are. In a
3383
+ * group, each setting is a row: its name and what it does on the left, the
3384
+ * control on the right, a rule between rows.
3385
+ */
2341
3386
  .settings {
2342
3387
  display: grid;
2343
- gap: 16px;
2344
- max-width: 760px;
2345
- padding-bottom: 72px;
3388
+ grid-template-columns: minmax(0, 740px) 200px;
3389
+ column-gap: 44px;
3390
+ row-gap: 16px;
3391
+ max-width: 1000px;
3392
+ padding-bottom: 80px;
3393
+ }
3394
+ .settings > * {
3395
+ grid-column: 1;
2346
3396
  }
2347
3397
  .settings__head {
2348
3398
  display: flex;
2349
- align-items: center;
3399
+ align-items: baseline;
2350
3400
  justify-content: space-between;
3401
+ padding: 4px 2px 0;
3402
+ }
3403
+ .settings__nav {
3404
+ grid-column: 2;
3405
+ grid-row: 2 / span 40;
3406
+ position: sticky;
3407
+ top: 24px;
3408
+ align-self: start;
3409
+ display: grid;
3410
+ gap: 2px;
3411
+ padding-top: 4px;
3412
+ }
3413
+ .settings__nav a {
3414
+ display: block;
3415
+ padding: 5px 10px;
3416
+ border-left: 2px solid transparent;
3417
+ border-radius: 0 6px 6px 0;
3418
+ color: var(--ink-2);
3419
+ font-size: 13.5px;
3420
+ text-decoration: none;
3421
+ }
3422
+ .settings__nav a:hover {
3423
+ color: var(--ink-1);
3424
+ background: var(--surface-sunken);
3425
+ }
3426
+ .settings__nav a[aria-current='true'] {
3427
+ border-left-color: var(--accent);
3428
+ color: var(--ink-1);
3429
+ font-weight: 600;
3430
+ }
3431
+ @media (max-width: 1000px) {
3432
+ .settings {
3433
+ grid-template-columns: minmax(0, 1fr);
3434
+ }
3435
+ .settings__nav {
3436
+ display: none;
3437
+ }
2351
3438
  }
2352
3439
  .settings__title {
2353
3440
  margin: 0;
2354
- font-size: 18px;
3441
+ font-family: var(--font-serif);
3442
+ font-size: 26px;
3443
+ font-weight: 500;
3444
+ letter-spacing: -0.005em;
2355
3445
  }
2356
3446
  .settings__problem {
2357
3447
  margin: 0;
2358
3448
  padding: 10px 14px;
2359
- border: 1px solid var(--warning);
3449
+ border: 1px solid var(--border);
3450
+ border-left: 3px solid var(--warning);
2360
3451
  border-radius: var(--radius-sm);
2361
- font-size: 13px;
3452
+ background: var(--surface);
3453
+ font-size: 13.5px;
2362
3454
  }
2363
3455
  .settings-card {
2364
- padding: 16px 18px;
3456
+ padding: 18px 24px 6px;
2365
3457
  background: var(--surface);
2366
3458
  border: 1px solid var(--border);
2367
3459
  border-radius: var(--radius);
@@ -2369,58 +3461,148 @@ body[data-flyout='open'] .layout__side {
2369
3461
  scroll-margin-top: 16px;
2370
3462
  }
2371
3463
  .settings-card__title {
2372
- margin: 0 0 10px;
2373
- font-size: 15px;
3464
+ margin: 0 0 4px;
3465
+ font-family: var(--font-serif);
3466
+ font-size: 19px;
3467
+ font-weight: 500;
2374
3468
  }
2375
3469
  .settings-card__help {
2376
- margin: 0 0 12px;
3470
+ margin: 0 0 10px;
3471
+ max-width: 70ch;
2377
3472
  color: var(--ink-2);
2378
- font-size: 13px;
3473
+ font-size: 13.5px;
2379
3474
  line-height: 1.5;
2380
3475
  }
2381
3476
  .settings-card__warning {
2382
3477
  margin: 0 0 10px;
2383
3478
  color: var(--serious);
2384
- font-size: 13px;
3479
+ font-size: 13.5px;
2385
3480
  }
2386
- .settings-card__more,
2387
- .setup__advanced {
2388
- margin-top: 6px;
3481
+ .settings-card__more {
3482
+ margin: 0;
2389
3483
  }
2390
- .settings-card__more > summary,
2391
- .setup__advanced > summary {
3484
+ .settings-card__more > summary {
3485
+ padding: 12px 0;
3486
+ border-top: 1px solid var(--rule);
2392
3487
  cursor: pointer;
2393
3488
  color: var(--ink-2);
2394
- font-size: 13px;
2395
- padding: 4px 0;
3489
+ font-size: 13.5px;
2396
3490
  }
2397
- .settings-card__more[open] > summary,
2398
- .setup__advanced[open] > summary {
2399
- margin-bottom: 10px;
3491
+ .settings-card__more > summary:hover {
3492
+ color: var(--ink-1);
2400
3493
  }
2401
3494
 
3495
+ /* One setting: name and help on the left, the control on the right. */
2402
3496
  .field {
2403
3497
  display: grid;
2404
- gap: 4px;
2405
- margin-bottom: 14px;
3498
+ grid-template-columns: minmax(0, 1fr) 300px;
3499
+ grid-template-areas:
3500
+ 'label control'
3501
+ 'help control'
3502
+ 'note control';
3503
+ column-gap: 28px;
3504
+ row-gap: 3px;
3505
+ align-items: start;
3506
+ margin: 0;
3507
+ padding: 14px 0;
3508
+ border-top: 1px solid var(--rule);
2406
3509
  }
2407
- .settings-card > .field:last-child,
2408
- .settings-card__more > .field:last-child {
2409
- margin-bottom: 0;
3510
+ .settings-card__title + .field,
3511
+ .settings-card__help + .field,
3512
+ .settings-card__warning + .field,
3513
+ .settings-card__more > .field:first-of-type {
3514
+ border-top: 0;
2410
3515
  }
2411
3516
  .field__label {
2412
- font-size: 13px;
2413
- font-weight: 500;
3517
+ grid-area: label;
3518
+ font-size: 14px;
3519
+ font-weight: 600;
2414
3520
  }
2415
3521
  .field__input {
2416
- height: 32px;
3522
+ grid-area: control;
3523
+ width: 100%;
3524
+ height: 34px;
2417
3525
  padding: 0 10px;
2418
3526
  border: 1px solid var(--border);
2419
3527
  border-radius: var(--radius-sm);
2420
3528
  background: var(--page);
2421
3529
  color: var(--ink-1);
2422
3530
  font: inherit;
3531
+ font-size: 13.5px;
3532
+ }
3533
+ select.field__input {
3534
+ appearance: none;
3535
+ padding-right: 30px;
3536
+ background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e7484' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
3537
+ background-repeat: no-repeat;
3538
+ background-position: right 10px center;
3539
+ background-size: 14px;
3540
+ }
3541
+ @media (max-width: 600px) {
3542
+ .field {
3543
+ grid-template-columns: minmax(0, 1fr);
3544
+ grid-template-areas:
3545
+ 'label'
3546
+ 'help'
3547
+ 'note'
3548
+ 'control';
3549
+ }
3550
+ }
3551
+
3552
+ /*
3553
+ * A yes/no, or a short list: a segmented control of the real answers. The one
3554
+ * in force by default says "default" beside its name, so a setting never
3555
+ * touched never looks like a choice that was made.
3556
+ */
3557
+ .segmented {
3558
+ grid-area: control;
3559
+ display: inline-flex;
3560
+ justify-self: end;
3561
+ max-width: 100%;
3562
+ padding: 3px;
3563
+ background: var(--surface-sunken);
3564
+ border: 1px solid var(--hairline);
3565
+ border-radius: 999px;
3566
+ }
3567
+ .segmented__option {
3568
+ display: inline-flex;
3569
+ align-items: baseline;
3570
+ gap: 5px;
3571
+ padding: 4px 12px;
3572
+ border: 0;
3573
+ border-radius: 999px;
3574
+ background: none;
3575
+ color: var(--ink-2);
3576
+ font: inherit;
2423
3577
  font-size: 13px;
3578
+ font-weight: 500;
3579
+ white-space: nowrap;
3580
+ cursor: pointer;
3581
+ }
3582
+ .segmented__option small {
3583
+ font-size: 11.5px;
3584
+ color: var(--ink-3);
3585
+ }
3586
+ .segmented__option:hover {
3587
+ color: var(--ink-1);
3588
+ }
3589
+ .segmented__option[aria-checked='true'] {
3590
+ background: var(--band);
3591
+ color: var(--band-ink);
3592
+ }
3593
+ .segmented__option[aria-checked='true'] small {
3594
+ color: rgba(255, 255, 255, 0.7);
3595
+ }
3596
+ .segmented[aria-disabled='true'] {
3597
+ opacity: 0.55;
3598
+ }
3599
+ .segmented[aria-disabled='true'] .segmented__option {
3600
+ cursor: not-allowed;
3601
+ }
3602
+ @media (max-width: 600px) {
3603
+ .segmented {
3604
+ justify-self: start;
3605
+ }
2424
3606
  }
2425
3607
  .field__input:disabled {
2426
3608
  color: var(--ink-3);
@@ -2429,29 +3611,48 @@ body[data-flyout='open'] .layout__side {
2429
3611
  .field[data-changed='true'] .field__input {
2430
3612
  border-color: var(--accent);
2431
3613
  }
3614
+ .field[data-changed='true'] .segmented {
3615
+ border-color: var(--accent);
3616
+ }
2432
3617
  .field__help,
2433
3618
  .field__note {
2434
3619
  margin: 0;
3620
+ max-width: 70ch;
2435
3621
  color: var(--ink-3);
2436
- font-size: 12px;
3622
+ font-size: 12.5px;
2437
3623
  line-height: 1.45;
2438
3624
  }
3625
+ .field__help {
3626
+ grid-area: help;
3627
+ }
2439
3628
  .field__note {
3629
+ grid-area: note;
2440
3630
  color: var(--ink-2);
2441
3631
  }
2442
3632
 
3633
+ /* The objective's two fields read top to bottom: a sentence wants the width. */
2443
3634
  .objective-form {
2444
3635
  display: grid;
2445
3636
  gap: 2px;
3637
+ padding-top: 4px;
3638
+ }
3639
+ .objective-form .field {
3640
+ grid-template-columns: minmax(0, 1fr);
3641
+ grid-template-areas:
3642
+ 'label'
3643
+ 'control';
3644
+ padding: 8px 0 10px;
2446
3645
  }
2447
3646
  .objective-form__actions {
2448
3647
  display: flex;
2449
3648
  justify-content: flex-end;
3649
+ padding: 6px 0 12px;
2450
3650
  }
2451
3651
 
2452
3652
  .text-editor {
2453
3653
  display: grid;
2454
3654
  gap: 8px;
3655
+ padding-bottom: 14px;
2455
3656
  }
2456
3657
  .text-editor__area {
2457
3658
  width: 100%;
@@ -2461,7 +3662,7 @@ body[data-flyout='open'] .layout__side {
2461
3662
  border-radius: var(--radius-sm);
2462
3663
  background: var(--page);
2463
3664
  color: var(--ink-1);
2464
- font: 12.5px/1.5 ui-monospace, 'SF Mono', Menlo, monospace;
3665
+ font: 12.5px/1.5 var(--font-mono);
2465
3666
  resize: vertical;
2466
3667
  }
2467
3668
  .text-editor__bar {
@@ -2472,7 +3673,7 @@ body[data-flyout='open'] .layout__side {
2472
3673
  }
2473
3674
  .text-editor__status {
2474
3675
  color: var(--ink-3);
2475
- font-size: 12px;
3676
+ font-size: 12.5px;
2476
3677
  }
2477
3678
  .text-editor__conflict {
2478
3679
  display: flex;
@@ -2480,17 +3681,21 @@ body[data-flyout='open'] .layout__side {
2480
3681
  align-items: center;
2481
3682
  gap: 8px;
2482
3683
  padding: 8px 12px;
2483
- border: 1px solid var(--warning);
3684
+ border: 1px solid var(--border);
3685
+ border-left: 3px solid var(--warning);
2484
3686
  border-radius: var(--radius-sm);
3687
+ background: var(--page);
2485
3688
  }
2486
3689
  .text-editor__conflict p {
2487
3690
  flex: 1 1 100%;
2488
3691
  margin: 0;
2489
- font-size: 13px;
3692
+ font-size: 13.5px;
2490
3693
  }
2491
3694
 
2492
3695
  .calendar-picker {
2493
- margin: -4px 0 14px;
3696
+ margin: 0;
3697
+ padding: 12px 0;
3698
+ border-top: 1px solid var(--rule);
2494
3699
  }
2495
3700
  .calendar-picker__list {
2496
3701
  display: grid;
@@ -2499,7 +3704,7 @@ body[data-flyout='open'] .layout__side {
2499
3704
  margin: 10px 0 0;
2500
3705
  padding: 0;
2501
3706
  list-style: none;
2502
- font-size: 13px;
3707
+ font-size: 13.5px;
2503
3708
  }
2504
3709
  .calendar-picker__source {
2505
3710
  color: var(--ink-3);
@@ -2520,7 +3725,7 @@ body[data-flyout='open'] .layout__side {
2520
3725
  background: var(--surface);
2521
3726
  border: 1px solid var(--border);
2522
3727
  border-radius: var(--radius);
2523
- box-shadow: 0 6px 24px rgba(11, 11, 11, 0.14);
3728
+ box-shadow: var(--shadow-float);
2524
3729
  }
2525
3730
  .settings__bar[hidden] {
2526
3731
  display: none;
@@ -2528,7 +3733,7 @@ body[data-flyout='open'] .layout__side {
2528
3733
  .settings__bar-text {
2529
3734
  flex: 1;
2530
3735
  margin: 0;
2531
- font-size: 13px;
3736
+ font-size: 13.5px;
2532
3737
  color: var(--ink-2);
2533
3738
  }
2534
3739
  .settings__bar-text--error {