@codemem/server 0.33.0-alpha.3 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/static/index.html CHANGED
@@ -21,252 +21,20 @@
21
21
  } catch (_e) {}
22
22
  })();
23
23
  </script>
24
+ <link rel="stylesheet" href="/assets/tokens.css" />
25
+ <link rel="stylesheet" href="/assets/themes.css" />
24
26
  <style>
25
- /* ── Design Tokens ─────────────────────────────────────── */
26
- /* Dark-first: :root carries the dark palette. [data-theme="light"]
27
- overrides for the light variant. Values come from the codemem
28
- design handoff (tokens/colors_and_type.css). */
29
-
30
- :root {
31
- /* Surface — deep ink */
32
- --surface-0: #0b1016;
33
- --surface-1: #0f1720;
34
- --surface-2: #111c27;
35
- --surface-3: #172332;
36
-
37
- /* Text — cool blue-white, never pure */
38
- --text-primary: #e7f0f7;
39
- --text-secondary: #b7c5d3;
40
- --text-tertiary: #8493a3;
41
- --text-inverse: #0b1016;
42
-
43
- /* Accents */
44
- --accent: #7ef0c2;
45
- --accent-hover: #9eff87;
46
- --accent-subtle: rgba(126, 240, 194, 0.10);
47
- --accent-strong: rgba(126, 240, 194, 0.28);
48
- --accent-warm: #ffb454;
49
- --accent-warm-subtle: rgba(255, 180, 84, 0.14);
50
- --accent-cool: #86a9ff;
51
- --accent-cool-subtle: rgba(134, 169, 255, 0.14);
52
- --accent-violet: #c79bff;
53
- --accent-violet-subtle: rgba(199, 155, 255, 0.14);
54
- --accent-steel: #4dd4b4;
55
- --accent-steel-subtle: rgba(77, 212, 180, 0.14);
56
- --accent-ochre: #e2c07e;
57
- --accent-ochre-subtle: rgba(226, 192, 126, 0.14);
58
- --accent-neutral: #9ea7b7;
59
- --accent-neutral-subtle: rgba(158, 167, 183, 0.14);
60
-
61
- /* Status */
62
- --status-healthy: #7ef0c2;
63
- --status-degraded: #ffb454;
64
- --status-attention: #ff7a50;
65
-
66
- /* Chrome */
67
- --border: rgba(126, 240, 194, 0.12);
68
- --border-strong: rgba(126, 240, 194, 0.28);
69
- --border-hover: rgba(126, 240, 194, 0.22);
70
- --focus-ring: rgba(126, 240, 194, 0.35);
71
- --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
72
- --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.35);
73
- --shadow-lg: 0 24px 80px rgba(0, 0, 0, 0.45);
74
-
75
- /* Body background */
76
- --grad-1: rgba(126, 240, 194, 0.08);
77
- --grad-2: rgba(86, 145, 255, 0.08);
78
- --grad-3: rgba(126, 240, 194, 0.04);
79
- --body-start: #0b1016;
80
- --body-mid: #0d131c;
81
- --body-end: #091018;
82
- --dot-color: rgba(126, 240, 194, 0.045);
83
- --grid-color: rgba(126, 240, 194, 0.045);
84
-
85
- /* Inputs & controls */
86
- --input-bg: rgba(9, 15, 22, 0.55);
87
- --control-bg: rgba(126, 240, 194, 0.06);
88
- --control-border: rgba(126, 240, 194, 0.22);
89
- --control-hover-bg: rgba(126, 240, 194, 0.12);
90
- --control-hover-border: rgba(126, 240, 194, 0.4);
91
- --control-text: var(--accent);
92
-
93
- /* Toggles */
94
- --toggle-active-bg: var(--accent-subtle);
95
- --toggle-active-text: var(--accent);
96
- --toggle-hover-bg: rgba(255, 255, 255, 0.04);
97
-
98
- /* Spacing scale (4px base) */
99
- --sp-1: 4px;
100
- --sp-2: 8px;
101
- --sp-3: 12px;
102
- --sp-4: 16px;
103
- --sp-5: 20px;
104
- --sp-6: 24px;
105
- --sp-8: 32px;
106
- --sp-10: 40px;
107
- --sp-12: 48px;
108
-
109
- /* Radii */
110
- --radius-sm: 10px;
111
- --radius-md: 12px;
112
- --radius-lg: 16px;
113
- --radius-xl: 20px;
114
- --radius-2xl: 24px;
115
- --radius-pill: 999px;
116
-
117
- /* Typography */
118
- --font-sans: "Geist", system-ui, -apple-system, sans-serif;
119
- --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
120
- }
121
-
122
- /* ── Light variant ─────────────────────────────────────── */
123
- /* Applied two ways:
124
- 1. Explicit [data-theme="light"] (set by the theme switcher or
125
- the inline boot script when localStorage says "light").
126
- 2. @media (prefers-color-scheme: light) whenever the user has not
127
- explicitly chosen dark — this gives us live OS-theme-switch
128
- behavior and is resilient to JS failures.
129
- Keep the two rule bodies identical. */
130
-
131
- /* The light palette applies two ways — they stay in lockstep:
132
- 1. Explicitly: [data-theme="light"], set by the theme switcher or
133
- the inline boot script from localStorage.
134
- 2. Automatically: @media (prefers-color-scheme: light) whenever
135
- the user has not opted into dark. This keeps live OS-theme
136
- switching working and gives us a CSS-only fallback if the
137
- inline script is blocked. */
138
-
139
- [data-theme="light"] {
140
- /* Surface */
141
- --surface-0: #f7faf8;
142
- --surface-1: #ffffff;
143
- --surface-2: #eef5f1;
144
- --surface-3: #e3ede7;
145
-
146
- /* Text — warm-tinted near-black, never pure */
147
- --text-primary: #0b1016;
148
- --text-secondary: #3f4d5c;
149
- --text-tertiary: #6b7985;
150
- --text-inverse: #ffffff;
151
-
152
- /* Accents — AA-safe evergreen on white */
153
- --accent: #0f8a68;
154
- --accent-hover: #0a6f53;
155
- --accent-subtle: rgba(15, 138, 104, 0.10);
156
- --accent-strong: rgba(15, 138, 104, 0.28);
157
- --accent-warm: #c97a1f;
158
- --accent-warm-subtle: rgba(201, 122, 31, 0.12);
159
- --accent-cool: #3e5fa8;
160
- --accent-cool-subtle: rgba(62, 95, 168, 0.10);
161
- --accent-violet: #7f52c2;
162
- --accent-violet-subtle: rgba(127, 82, 194, 0.12);
163
- --accent-steel: #1a8a70;
164
- --accent-steel-subtle: rgba(26, 138, 112, 0.12);
165
- --accent-ochre: #b5832a;
166
- --accent-ochre-subtle: rgba(181, 131, 42, 0.12);
167
- --accent-neutral: #5d6a7c;
168
- --accent-neutral-subtle: rgba(93, 106, 124, 0.10);
169
-
170
- /* Status */
171
- --status-healthy: #0f8a68;
172
- --status-degraded: #c97a1f;
173
- --status-attention: #b4411e;
174
-
175
- /* Chrome */
176
- --border: rgba(15, 138, 104, 0.16);
177
- --border-strong: rgba(15, 138, 104, 0.30);
178
- --border-hover: rgba(15, 138, 104, 0.24);
179
- --focus-ring: rgba(15, 138, 104, 0.20);
180
- --shadow-sm: 0 1px 3px rgba(11, 16, 22, 0.05);
181
- --shadow-md: 0 8px 24px rgba(11, 16, 22, 0.08);
182
- --shadow-lg: 0 18px 40px rgba(11, 16, 22, 0.12);
183
-
184
- /* Body background */
185
- --grad-1: rgba(15, 138, 104, 0.08);
186
- --grad-2: rgba(62, 95, 168, 0.06);
187
- --grad-3: rgba(15, 138, 104, 0.04);
188
- --body-start: #f7faf8;
189
- --body-mid: #eef5f1;
190
- --body-end: #e6efe9;
191
- --dot-color: rgba(11, 16, 22, 0.035);
192
- --grid-color: rgba(11, 16, 22, 0.035);
193
-
194
- /* Inputs & controls */
195
- --input-bg: rgba(255, 255, 255, 0.9);
196
- --control-bg: rgba(15, 138, 104, 0.08);
197
- --control-border: rgba(15, 138, 104, 0.22);
198
- --control-hover-bg: rgba(15, 138, 104, 0.14);
199
- --control-hover-border: rgba(15, 138, 104, 0.4);
200
- --control-text: var(--accent);
201
-
202
- /* Toggles */
203
- --toggle-active-bg: var(--accent-subtle);
204
- --toggle-active-text: var(--accent);
205
- --toggle-hover-bg: rgba(11, 16, 22, 0.04);
206
- }
207
-
208
- @media (prefers-color-scheme: light) {
209
- :root:not([data-theme="dark"]) {
210
- --surface-0: #f7faf8;
211
- --surface-1: #ffffff;
212
- --surface-2: #eef5f1;
213
- --surface-3: #e3ede7;
214
-
215
- --text-primary: #0b1016;
216
- --text-secondary: #3f4d5c;
217
- --text-tertiary: #6b7985;
218
- --text-inverse: #ffffff;
219
-
220
- --accent: #0f8a68;
221
- --accent-hover: #0a6f53;
222
- --accent-subtle: rgba(15, 138, 104, 0.10);
223
- --accent-strong: rgba(15, 138, 104, 0.28);
224
- --accent-warm: #c97a1f;
225
- --accent-warm-subtle: rgba(201, 122, 31, 0.12);
226
- --accent-cool: #3e5fa8;
227
- --accent-cool-subtle: rgba(62, 95, 168, 0.10);
228
- --accent-violet: #7f52c2;
229
- --accent-violet-subtle: rgba(127, 82, 194, 0.12);
230
- --accent-steel: #1a8a70;
231
- --accent-steel-subtle: rgba(26, 138, 112, 0.12);
232
- --accent-ochre: #b5832a;
233
- --accent-ochre-subtle: rgba(181, 131, 42, 0.12);
234
- --accent-neutral: #5d6a7c;
235
- --accent-neutral-subtle: rgba(93, 106, 124, 0.10);
236
-
237
- --status-healthy: #0f8a68;
238
- --status-degraded: #c97a1f;
239
- --status-attention: #b4411e;
240
-
241
- --border: rgba(15, 138, 104, 0.16);
242
- --border-strong: rgba(15, 138, 104, 0.30);
243
- --border-hover: rgba(15, 138, 104, 0.24);
244
- --focus-ring: rgba(15, 138, 104, 0.20);
245
- --shadow-sm: 0 1px 3px rgba(11, 16, 22, 0.05);
246
- --shadow-md: 0 8px 24px rgba(11, 16, 22, 0.08);
247
- --shadow-lg: 0 18px 40px rgba(11, 16, 22, 0.12);
248
-
249
- --grad-1: rgba(15, 138, 104, 0.08);
250
- --grad-2: rgba(62, 95, 168, 0.06);
251
- --grad-3: rgba(15, 138, 104, 0.04);
252
- --body-start: #f7faf8;
253
- --body-mid: #eef5f1;
254
- --body-end: #e6efe9;
255
- --dot-color: rgba(11, 16, 22, 0.035);
256
- --grid-color: rgba(11, 16, 22, 0.035);
257
-
258
- --input-bg: rgba(255, 255, 255, 0.9);
259
- --control-bg: rgba(15, 138, 104, 0.08);
260
- --control-border: rgba(15, 138, 104, 0.22);
261
- --control-hover-bg: rgba(15, 138, 104, 0.14);
262
- --control-hover-border: rgba(15, 138, 104, 0.4);
263
- --control-text: var(--accent);
264
-
265
- --toggle-active-bg: var(--accent-subtle);
266
- --toggle-active-text: var(--accent);
267
- --toggle-hover-bg: rgba(11, 16, 22, 0.04);
268
- }
269
- }
27
+ /* Design tokens (color, surface, accent, status, chrome, body bg,
28
+ inputs, toggles, spacing, radii, typography, motion) and the light
29
+ theme overrides live in /assets/tokens.css and /assets/themes.css
30
+ and load above this block. The cascade order is:
31
+ 1. Dark defaults from tokens.css (:root).
32
+ 2. Light overrides from themes.css ([data-theme="light"] +
33
+ @media (prefers-color-scheme: light)).
34
+ 3. The component-level rules below, which reference the tokens
35
+ via var(--...).
36
+ Edit packages/ui/static/tokens.css and themes.css to change the
37
+ token surface. Edit this <style> block for per-component styling. */
270
38
 
271
39
  /* ── Reset & base ──────────────────────────────────────── */
272
40
 
@@ -274,7 +42,7 @@
274
42
 
275
43
  body {
276
44
  font-family: var(--font-sans);
277
- font-size: 14px;
45
+ font-size: var(--font-size-base);
278
46
  line-height: 1.55;
279
47
  color: var(--text-primary);
280
48
  background:
@@ -354,8 +122,8 @@
354
122
  .logo svg { display: block; }
355
123
 
356
124
  .header-title {
357
- font-size: 18px;
358
- font-weight: 600;
125
+ font-size: var(--font-size-2xl);
126
+ font-weight: var(--font-weight-semibold);
359
127
  letter-spacing: -0.01em;
360
128
  white-space: nowrap;
361
129
  }
@@ -368,7 +136,7 @@
368
136
  }
369
137
  .health-dot.status-healthy { background: var(--status-healthy); box-shadow: 0 0 0 3px var(--accent-subtle); }
370
138
  .health-dot.status-degraded { background: var(--status-degraded); box-shadow: 0 0 0 3px var(--accent-warm-subtle); }
371
- .health-dot.status-attention { background: var(--status-attention); box-shadow: 0 0 0 3px rgba(255, 122, 80, 0.18); animation: pulse 2.4s ease infinite; }
139
+ .health-dot.status-attention { background: var(--status-attention); box-shadow: 0 0 0 3px rgba(255, 122, 80, 0.18); animation: pulse var(--duration-pulse) var(--ease-standard) infinite; }
372
140
 
373
141
  .header-right {
374
142
  display: flex;
@@ -376,17 +144,28 @@
376
144
  gap: var(--sp-2);
377
145
  }
378
146
 
147
+ /* Diagnostic metadata cluster: runtime version + database path. Grouped
148
+ under one container so the responsive treatment can hide both together
149
+ on narrow viewports without disturbing the surrounding primary
150
+ controls (project filter, theme toggle, settings). */
151
+ .header-tertiary {
152
+ display: flex;
153
+ align-items: center;
154
+ gap: var(--sp-2);
155
+ min-width: 0;
156
+ }
157
+
379
158
  .refresh-status {
380
159
  display: inline-flex;
381
160
  align-items: center;
382
161
  gap: 6px;
383
- font-size: 12px;
162
+ font-size: var(--font-size-sm);
384
163
  color: var(--text-tertiary);
385
164
  }
386
165
 
387
166
  .meta-line {
388
167
  font-family: var(--font-mono);
389
- font-size: 12px;
168
+ font-size: var(--font-size-sm);
390
169
  letter-spacing: 0.02em;
391
170
  color: var(--text-tertiary);
392
171
  white-space: nowrap;
@@ -396,7 +175,7 @@
396
175
  }
397
176
 
398
177
  .runtime-label {
399
- font-size: 11px;
178
+ font-size: var(--font-size-xs);
400
179
  color: var(--text-tertiary);
401
180
  opacity: 0.8;
402
181
  white-space: nowrap;
@@ -424,10 +203,10 @@
424
203
  background: transparent;
425
204
  color: var(--text-tertiary);
426
205
  font-family: var(--font-sans);
427
- font-size: 13px;
428
- font-weight: 500;
206
+ font-size: var(--font-size-md);
207
+ font-weight: var(--font-weight-medium);
429
208
  cursor: pointer;
430
- transition: color 140ms ease;
209
+ transition: color var(--duration-fast) var(--ease-standard);
431
210
  }
432
211
 
433
212
  .tab-btn:hover {
@@ -436,7 +215,7 @@
436
215
 
437
216
  .tab-btn.active {
438
217
  color: var(--accent);
439
- font-weight: 600;
218
+ font-weight: var(--font-weight-semibold);
440
219
  }
441
220
 
442
221
  .tab-btn.active::after {
@@ -501,12 +280,12 @@
501
280
  border-radius: var(--radius-xl);
502
281
  padding: var(--sp-5);
503
282
  box-shadow: var(--shadow-md);
504
- animation: fadeUp 0.4s ease both;
283
+ animation: fadeUp var(--duration-fade-up) var(--ease-standard) both;
505
284
  }
506
285
 
507
286
  .card h2 {
508
- font-size: 16px;
509
- font-weight: 600;
287
+ font-size: var(--font-size-xl);
288
+ font-weight: var(--font-weight-semibold);
510
289
  letter-spacing: -0.01em;
511
290
  margin-bottom: var(--sp-3);
512
291
  }
@@ -538,7 +317,7 @@
538
317
  }
539
318
 
540
319
  .coordinator-admin-summary-card strong {
541
- font-size: 16px;
320
+ font-size: var(--font-size-xl);
542
321
  line-height: 1.3;
543
322
  }
544
323
 
@@ -572,7 +351,7 @@
572
351
  }
573
352
 
574
353
  .coordinator-admin-context-pair strong {
575
- font-size: 16px;
354
+ font-size: var(--font-size-xl);
576
355
  line-height: 1.2;
577
356
  }
578
357
 
@@ -614,7 +393,7 @@
614
393
  }
615
394
 
616
395
  .coordinator-admin-panel h3 {
617
- font-size: 18px;
396
+ font-size: var(--font-size-2xl);
618
397
  line-height: 1.25;
619
398
  margin: 0;
620
399
  }
@@ -631,9 +410,9 @@
631
410
  }
632
411
 
633
412
  .coordinator-admin-field > span {
634
- font-size: 12px;
413
+ font-size: var(--font-size-sm);
635
414
  color: var(--text-secondary);
636
- font-weight: 600;
415
+ font-weight: var(--font-weight-semibold);
637
416
  }
638
417
 
639
418
  .coordinator-admin-output {
@@ -678,7 +457,7 @@
678
457
  cursor: pointer;
679
458
  flex-shrink: 0;
680
459
  padding: 1px;
681
- transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
460
+ transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
682
461
  }
683
462
 
684
463
  .coordinator-admin-switch:hover {
@@ -709,7 +488,7 @@
709
488
  background: color-mix(in srgb, var(--surface-0) 88%, white);
710
489
  border: 1px solid color-mix(in srgb, var(--text-tertiary) 24%, transparent);
711
490
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
712
- transition: transform 140ms ease, background 140ms ease;
491
+ transition: transform var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);
713
492
  transform: translateX(0);
714
493
  }
715
494
 
@@ -746,7 +525,7 @@
746
525
  display: inline-flex;
747
526
  width: 14px;
748
527
  height: 14px;
749
- transition: transform 140ms ease;
528
+ transition: transform var(--duration-fast) var(--ease-standard);
750
529
  }
751
530
  .coordinator-admin-scope-trigger .device-row-chevron svg {
752
531
  width: 100%;
@@ -759,8 +538,8 @@
759
538
  }
760
539
 
761
540
  .coordinator-admin-drawer-title {
762
- font-size: 13px;
763
- font-weight: 600;
541
+ font-size: var(--font-size-md);
542
+ font-weight: var(--font-weight-semibold);
764
543
  color: var(--text-primary);
765
544
  margin: 0;
766
545
  letter-spacing: 0.01em;
@@ -838,12 +617,12 @@
838
617
  }
839
618
 
840
619
  .coordinator-admin-scope-member-copy strong {
841
- font-size: 13px;
620
+ font-size: var(--font-size-md);
842
621
  }
843
622
 
844
623
  .coordinator-admin-scope-member-copy span {
845
624
  color: var(--text-tertiary);
846
- font-size: 12px;
625
+ font-size: var(--font-size-sm);
847
626
  line-height: 1.35;
848
627
  }
849
628
 
@@ -896,13 +675,13 @@
896
675
  display: inline-flex;
897
676
  align-items: center;
898
677
  gap: 4px;
899
- font-size: 13px;
900
- font-weight: 500;
678
+ font-size: var(--font-size-md);
679
+ font-weight: var(--font-weight-medium);
901
680
  color: var(--text-secondary);
902
681
  text-decoration: none;
903
682
  padding: 4px 6px;
904
683
  border-radius: var(--radius-sm);
905
- transition: color 140ms ease;
684
+ transition: color var(--duration-fast) var(--ease-standard);
906
685
  }
907
686
  .sync-subview-link:hover {
908
687
  color: var(--accent);
@@ -915,7 +694,7 @@
915
694
 
916
695
  .section-meta {
917
696
  color: var(--text-tertiary);
918
- font-size: 12px;
697
+ font-size: var(--font-size-sm);
919
698
  margin-bottom: var(--sp-3);
920
699
  }
921
700
 
@@ -961,8 +740,8 @@
961
740
 
962
741
  .stat .value {
963
742
  font-family: var(--font-sans);
964
- font-weight: 600;
965
- font-size: 20px;
743
+ font-weight: var(--font-weight-semibold);
744
+ font-size: var(--font-size-3xl);
966
745
  color: var(--text-primary);
967
746
  line-height: 1.15;
968
747
  letter-spacing: -0.01em;
@@ -971,8 +750,8 @@
971
750
 
972
751
  .stat .label {
973
752
  color: var(--text-tertiary);
974
- font-size: 12px;
975
- font-weight: 500;
753
+ font-size: var(--font-size-sm);
754
+ font-weight: var(--font-weight-medium);
976
755
  line-height: 1.3;
977
756
  letter-spacing: 0.08em;
978
757
  text-transform: uppercase;
@@ -981,7 +760,7 @@
981
760
  .health-primary {
982
761
  border-width: 2px;
983
762
  }
984
- .health-primary .value { font-size: 20px; letter-spacing: 0.2px; }
763
+ .health-primary .value { font-size: var(--font-size-3xl); letter-spacing: 0.2px; }
985
764
  .health-primary.status-healthy .value { color: var(--status-healthy); }
986
765
  .health-primary.status-degraded .value { color: var(--status-degraded); }
987
766
  .health-primary.status-attention .value { color: var(--status-attention); }
@@ -1014,8 +793,8 @@
1014
793
  padding: 5px 12px;
1015
794
  min-width: 28px;
1016
795
  min-height: 28px;
1017
- font-size: 12px;
1018
- transition: background 140ms ease, border-color 140ms ease;
796
+ font-size: var(--font-size-sm);
797
+ transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
1019
798
  }
1020
799
  .settings-button:hover {
1021
800
  background: var(--control-hover-bg);
@@ -1073,7 +852,7 @@
1073
852
  .device-row-chevron svg {
1074
853
  width: 18px;
1075
854
  height: 18px;
1076
- transition: transform 140ms ease;
855
+ transition: transform var(--duration-fast) var(--ease-standard);
1077
856
  }
1078
857
  button.device-row-head--trigger[data-state="open"] .device-row-chevron svg {
1079
858
  transform: rotate(90deg);
@@ -1081,8 +860,8 @@
1081
860
  .device-row-head .device-row-name {
1082
861
  flex: 1 1 auto;
1083
862
  min-width: 0;
1084
- font-size: 14px;
1085
- font-weight: 600;
863
+ font-size: var(--font-size-base);
864
+ font-weight: var(--font-weight-semibold);
1086
865
  color: var(--text-primary);
1087
866
  overflow: hidden;
1088
867
  text-overflow: ellipsis;
@@ -1095,7 +874,7 @@
1095
874
  flex-wrap: wrap;
1096
875
  }
1097
876
  .device-row-head .device-row-meta {
1098
- font-size: 12px;
877
+ font-size: var(--font-size-sm);
1099
878
  color: var(--text-tertiary);
1100
879
  font-feature-settings: 'tnum' 1;
1101
880
  white-space: nowrap;
@@ -1138,7 +917,7 @@
1138
917
  color-mix(in srgb, var(--surface-2) 60%, var(--surface-1)) 50%,
1139
918
  color-mix(in srgb, var(--surface-2) 82%, var(--surface-1)) 75%);
1140
919
  background-size: 200% 100%;
1141
- animation: device-skel-shimmer 1.5s ease-in-out infinite;
920
+ animation: device-skel-shimmer var(--duration-shimmer) var(--ease-in-out) infinite;
1142
921
  }
1143
922
  .device-row-skeleton .skel-pip {
1144
923
  width: 8px;
@@ -1181,7 +960,7 @@
1181
960
  cursor: pointer;
1182
961
  flex-shrink: 0;
1183
962
  padding: 1px;
1184
- transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
963
+ transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
1185
964
  }
1186
965
 
1187
966
  .sync-redact-switch:hover {
@@ -1207,7 +986,7 @@
1207
986
  background: color-mix(in srgb, var(--surface-0) 88%, white);
1208
987
  border: 1px solid color-mix(in srgb, var(--text-tertiary) 24%, transparent);
1209
988
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
1210
- transition: transform 140ms ease, background 140ms ease;
989
+ transition: transform var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);
1211
990
  transform: translateX(0);
1212
991
  }
1213
992
 
@@ -1226,9 +1005,9 @@
1226
1005
  background: var(--input-bg);
1227
1006
  color: var(--text-primary);
1228
1007
  font-family: var(--font-sans);
1229
- font-size: 12px;
1008
+ font-size: var(--font-size-sm);
1230
1009
  cursor: pointer;
1231
- transition: border-color 140ms ease;
1010
+ transition: border-color var(--duration-fast) var(--ease-standard);
1232
1011
  }
1233
1012
  .project-filter:hover { border-color: var(--border-hover); }
1234
1013
  .project-filter:focus {
@@ -1252,13 +1031,35 @@
1252
1031
  background: var(--input-bg);
1253
1032
  color: var(--text-primary);
1254
1033
  font-family: var(--font-sans);
1255
- font-size: 13px;
1034
+ font-size: var(--font-size-md);
1256
1035
  }
1257
1036
  .project-inventory-list {
1258
1037
  display: grid;
1259
1038
  gap: var(--sp-3);
1260
1039
  margin-top: var(--sp-4);
1261
1040
  }
1041
+ .project-inventory-skeleton {
1042
+ display: grid;
1043
+ gap: var(--sp-3);
1044
+ margin-top: var(--sp-4);
1045
+ }
1046
+ .project-inventory-skeleton-row {
1047
+ padding: var(--sp-4);
1048
+ border: 1px solid var(--border);
1049
+ border-radius: var(--radius-md);
1050
+ background: var(--surface-1);
1051
+ }
1052
+ .project-inventory-skeleton-line {
1053
+ height: 12px;
1054
+ border-radius: var(--radius-pill);
1055
+ background: linear-gradient(90deg, var(--border) 25%, var(--surface-2) 50%, var(--border) 75%);
1056
+ background-size: 400px 100%;
1057
+ animation: sync-shimmer var(--duration-shimmer) var(--ease-in-out) infinite;
1058
+ margin: var(--sp-2) 0;
1059
+ }
1060
+ .project-inventory-skeleton-line.title { width: 42%; height: 16px; }
1061
+ .project-inventory-skeleton-line.meta { width: 68%; }
1062
+ .project-inventory-skeleton-line.signal { width: 86%; }
1262
1063
  .project-inventory-row {
1263
1064
  padding: var(--sp-4);
1264
1065
  border: 1px solid var(--border);
@@ -1271,12 +1072,12 @@
1271
1072
  gap: var(--sp-3);
1272
1073
  align-items: flex-start;
1273
1074
  }
1274
- .project-inventory-title { font-size: 15px; font-weight: 650; color: var(--text-primary); }
1275
- .project-inventory-domain { font-family: var(--font-mono); font-size: 12px; color: var(--accent); }
1075
+ .project-inventory-title { font-size: var(--font-size-lg); font-weight: 650; color: var(--text-primary); }
1076
+ .project-inventory-domain { font-family: var(--font-mono); font-size: var(--font-size-sm); color: var(--accent); }
1276
1077
  .project-inventory-meta, .project-inventory-signal {
1277
1078
  margin-top: var(--sp-2);
1278
1079
  color: var(--text-secondary);
1279
- font-size: 12px;
1080
+ font-size: var(--font-size-sm);
1280
1081
  }
1281
1082
  .project-inventory-signal { overflow-wrap: anywhere; }
1282
1083
  .project-inventory-badges {
@@ -1290,20 +1091,20 @@
1290
1091
  border-radius: var(--radius-pill);
1291
1092
  background: var(--surface-2);
1292
1093
  color: var(--text-secondary);
1293
- font-size: 11px;
1094
+ font-size: var(--font-size-xs);
1294
1095
  border: 1px solid var(--border);
1295
1096
  }
1296
1097
  .project-status-badge.needs_attention,
1297
1098
  .project-status-badge.legacy_review { color: var(--accent-warm); background: var(--accent-warm-subtle); }
1298
1099
  .project-status-badge.suggested { color: var(--accent); background: var(--accent-subtle); }
1299
1100
  .project-inventory-details { margin-top: var(--sp-3); }
1300
- .project-inventory-details summary { cursor: pointer; color: var(--text-secondary); font-size: 12px; }
1101
+ .project-inventory-details summary { cursor: pointer; color: var(--text-secondary); font-size: var(--font-size-sm); }
1301
1102
  .project-detail-grid {
1302
1103
  display: grid;
1303
1104
  grid-template-columns: minmax(130px, max-content) 1fr;
1304
1105
  gap: var(--sp-2) var(--sp-3);
1305
1106
  margin-top: var(--sp-3);
1306
- font-size: 12px;
1107
+ font-size: var(--font-size-sm);
1307
1108
  }
1308
1109
  .project-detail-grid dt { color: var(--text-tertiary); }
1309
1110
  .project-detail-grid dd { margin: 0; overflow-wrap: anywhere; color: var(--text-primary); }
@@ -1322,7 +1123,7 @@
1322
1123
  background: var(--input-bg);
1323
1124
  color: var(--text-primary);
1324
1125
  font-family: var(--font-sans);
1325
- font-size: 13px;
1126
+ font-size: var(--font-size-md);
1326
1127
  }
1327
1128
  .project-guardrail-confirmation {
1328
1129
  flex-basis: 100%;
@@ -1344,7 +1145,7 @@
1344
1145
  color: var(--control-text);
1345
1146
  cursor: pointer;
1346
1147
  flex-shrink: 0;
1347
- transition: background-color 140ms ease, border-color 140ms ease, transform 140ms ease;
1148
+ transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard);
1348
1149
  }
1349
1150
  .icon-button:hover {
1350
1151
  background: var(--control-hover-bg);
@@ -1415,9 +1216,9 @@
1415
1216
  background: var(--input-bg);
1416
1217
  color: var(--text-primary);
1417
1218
  font-family: var(--font-sans);
1418
- font-size: 13px;
1219
+ font-size: var(--font-size-md);
1419
1220
  outline: none;
1420
- transition: border-color 140ms ease, box-shadow 140ms ease;
1221
+ transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
1421
1222
  }
1422
1223
  .feed-search::placeholder { color: var(--text-tertiary); }
1423
1224
  .feed-search:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus-ring); }
@@ -1432,11 +1233,11 @@
1432
1233
  background: var(--input-bg);
1433
1234
  color: var(--text-primary);
1434
1235
  font-family: var(--font-mono);
1435
- font-size: 12px;
1236
+ font-size: var(--font-size-sm);
1436
1237
  line-height: 1.45;
1437
1238
  resize: vertical;
1438
1239
  outline: none;
1439
- transition: border-color 140ms ease, box-shadow 140ms ease;
1240
+ transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
1440
1241
  }
1441
1242
  .feed-inspector-files::placeholder { color: var(--text-tertiary); }
1442
1243
  .feed-inspector-files:focus {
@@ -1458,14 +1259,14 @@
1458
1259
  background: transparent;
1459
1260
  color: var(--text-tertiary);
1460
1261
  font-family: var(--font-sans);
1461
- font-size: 12px;
1262
+ font-size: var(--font-size-sm);
1462
1263
  padding: 4px 12px;
1463
1264
  border-radius: var(--radius-pill);
1464
1265
  cursor: pointer;
1465
1266
  display: inline-flex;
1466
1267
  align-items: center;
1467
1268
  gap: 5px;
1468
- transition: background-color 140ms ease, color 140ms ease, box-shadow 140ms ease;
1269
+ transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
1469
1270
  }
1470
1271
  .toggle-button:hover { background: var(--toggle-hover-bg); color: var(--text-primary); }
1471
1272
  .toggle-button.active {
@@ -1507,7 +1308,7 @@
1507
1308
  height: 28px;
1508
1309
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
1509
1310
  background-size: 400px 100%;
1510
- animation: sync-shimmer 1.5s ease-in-out infinite;
1311
+ animation: sync-shimmer var(--duration-shimmer) var(--ease-in-out) infinite;
1511
1312
  border-bottom: 1px solid var(--border);
1512
1313
  }
1513
1314
  .feed-skeleton-body {
@@ -1521,7 +1322,7 @@
1521
1322
  border-radius: 6px;
1522
1323
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
1523
1324
  background-size: 400px 100%;
1524
- animation: sync-shimmer 1.5s ease-in-out infinite;
1325
+ animation: sync-shimmer var(--duration-shimmer) var(--ease-in-out) infinite;
1525
1326
  }
1526
1327
  .feed-skeleton-line.w-85 { width: 85%; }
1527
1328
  .feed-skeleton-line.w-65 { width: 65%; }
@@ -1537,7 +1338,7 @@
1537
1338
  border-radius: var(--radius-pill);
1538
1339
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
1539
1340
  background-size: 400px 100%;
1540
- animation: sync-shimmer 1.5s ease-in-out infinite;
1341
+ animation: sync-shimmer var(--duration-shimmer) var(--ease-in-out) infinite;
1541
1342
  }
1542
1343
  .feed-skeleton-chip.w-36 { width: 36px; }
1543
1344
  .feed-skeleton-chip.w-56 { width: 56px; }
@@ -1556,7 +1357,7 @@
1556
1357
  display: flex;
1557
1358
  flex-direction: column;
1558
1359
  box-shadow: var(--shadow-sm);
1559
- transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
1360
+ transition: transform var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
1560
1361
  }
1561
1362
  .feed-item:hover {
1562
1363
  transform: translateY(-1px);
@@ -1627,9 +1428,9 @@
1627
1428
  border: 1px solid var(--border);
1628
1429
  background: transparent;
1629
1430
  color: var(--text-tertiary);
1630
- font-size: 18px;
1431
+ font-size: var(--font-size-2xl);
1631
1432
  line-height: 1;
1632
- transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
1433
+ transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
1633
1434
  }
1634
1435
  .feed-menu-trigger:hover,
1635
1436
  .feed-menu-trigger[data-state="open"] {
@@ -1650,7 +1451,7 @@
1650
1451
  padding: 8px 10px;
1651
1452
  border-radius: var(--radius-md);
1652
1453
  color: var(--text-primary);
1653
- font-size: 13px;
1454
+ font-size: var(--font-size-md);
1654
1455
  cursor: pointer;
1655
1456
  user-select: none;
1656
1457
  outline: none;
@@ -1670,8 +1471,8 @@
1670
1471
  }
1671
1472
 
1672
1473
  .feed-title {
1673
- font-weight: 600;
1674
- font-size: 15px;
1474
+ font-weight: var(--font-weight-semibold);
1475
+ font-size: var(--font-size-lg);
1675
1476
  flex: 1;
1676
1477
  min-width: 0;
1677
1478
  display: -webkit-box;
@@ -1687,7 +1488,7 @@
1687
1488
  }
1688
1489
  .feed-meta {
1689
1490
  color: var(--text-tertiary);
1690
- font-size: 12px;
1491
+ font-size: var(--font-size-sm);
1691
1492
  }
1692
1493
  /* Empty state renders as a terminal-output block — mono surface,
1693
1494
  blinking mint cursor — to match the codemem "warm local journal"
@@ -1702,24 +1503,24 @@
1702
1503
  background: var(--surface-2);
1703
1504
  color: var(--text-secondary);
1704
1505
  font-family: var(--font-mono);
1705
- font-size: 13px;
1506
+ font-size: var(--font-size-md);
1706
1507
  }
1707
1508
  .feed-empty-state strong {
1708
1509
  color: var(--text-primary);
1709
- font-weight: 600;
1510
+ font-weight: var(--font-weight-semibold);
1710
1511
  }
1711
1512
  .feed-empty-state::before {
1712
1513
  content: "$ codemem feed";
1713
1514
  display: block;
1714
1515
  color: var(--accent);
1715
- font-weight: 500;
1516
+ font-weight: var(--font-weight-medium);
1716
1517
  margin-bottom: 4px;
1717
1518
  }
1718
1519
  .feed-empty-state::after {
1719
1520
  content: "_";
1720
1521
  display: inline-block;
1721
1522
  color: var(--accent);
1722
- animation: cursorBlink 1.1s steps(2, end) infinite;
1523
+ animation: cursorBlink var(--duration-blink) steps(2, end) infinite;
1723
1524
  }
1724
1525
  @keyframes cursorBlink {
1725
1526
  0%, 100% { opacity: 1; }
@@ -1751,7 +1552,7 @@
1751
1552
  border: 1px solid transparent;
1752
1553
  line-height: 1.2;
1753
1554
  white-space: nowrap;
1754
- font-size: 11px;
1555
+ font-size: var(--font-size-xs);
1755
1556
  }
1756
1557
 
1757
1558
  .provenance-chip {
@@ -1769,9 +1570,15 @@
1769
1570
  .provenance-chip.source { background: rgba(94, 129, 172, 0.12); color: #5e81ac; }
1770
1571
  .provenance-chip.device { background: rgba(128, 110, 74, 0.12); color: #806e4a; }
1771
1572
  .provenance-chip.trust { background: rgba(202, 138, 4, 0.12); color: #a16207; }
1573
+ .provenance-chip.memory-id {
1574
+ background: transparent;
1575
+ border-color: color-mix(in srgb, var(--border) 55%, transparent);
1576
+ color: var(--text-tertiary);
1577
+ font-family: var(--font-mono);
1578
+ }
1772
1579
 
1773
1580
  .feed-body {
1774
- font-size: 13px;
1581
+ font-size: var(--font-size-md);
1775
1582
  line-height: 1.55;
1776
1583
  color: var(--text-secondary);
1777
1584
  }
@@ -1787,10 +1594,10 @@
1787
1594
  .feed-body code { background: var(--surface-2); padding: 0.15em 0.35em; border-radius: 4px; font-family: var(--font-mono); font-size: 0.9em; }
1788
1595
  .feed-body pre { background: var(--surface-2); padding: 0.6em 0.8em; border-radius: var(--radius-sm); overflow-x: auto; margin: 0.5em 0; }
1789
1596
  .feed-body pre code { background: none; padding: 0; }
1790
- .feed-body strong { font-weight: 600; }
1597
+ .feed-body strong { font-weight: var(--font-weight-semibold); }
1791
1598
  .feed-body em { font-style: italic; }
1792
1599
  .feed-body a { color: var(--accent); text-decoration: underline; }
1793
- .feed-body h1, .feed-body h2, .feed-body h3, .feed-body h4 { font-size: 1em; font-weight: 600; margin: 0.6em 0 0.3em; }
1600
+ .feed-body h1, .feed-body h2, .feed-body h3, .feed-body h4 { font-size: 1em; font-weight: var(--font-weight-semibold); margin: 0.6em 0 0.3em; }
1794
1601
  .feed-body blockquote { border-left: 3px solid var(--border); margin: 0.5em 0; padding-left: 0.8em; color: var(--text-tertiary); }
1795
1602
 
1796
1603
  .summary-section {
@@ -1801,8 +1608,8 @@
1801
1608
  border-bottom: 1px solid var(--border);
1802
1609
  }
1803
1610
  .summary-section:last-child { border-bottom: none; }
1804
- .summary-section-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-tertiary); }
1805
- .summary-section-content { font-size: 13px; line-height: 1.5; color: var(--text-primary); }
1611
+ .summary-section-label { font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-tertiary); }
1612
+ .summary-section-content { font-size: var(--font-size-md); line-height: 1.5; color: var(--text-primary); }
1806
1613
 
1807
1614
  .feed-footer {
1808
1615
  display: flex;
@@ -1822,17 +1629,17 @@
1822
1629
  background: var(--input-bg);
1823
1630
  color: var(--text-primary);
1824
1631
  font-family: var(--font-sans);
1825
- font-size: 12px;
1632
+ font-size: var(--font-size-sm);
1826
1633
  }
1827
- .feed-visibility-note { width: 100%; max-width: 60ch; font-size: 12px; color: var(--text-tertiary); }
1634
+ .feed-visibility-note { width: 100%; max-width: 60ch; font-size: var(--font-size-sm); color: var(--text-tertiary); }
1828
1635
 
1829
1636
  .feed-expand {
1830
1637
  border: 1px solid var(--border);
1831
1638
  background: transparent;
1832
1639
  color: var(--text-tertiary);
1833
1640
  padding: 3px 10px;
1834
- font-size: 11px;
1835
- transition: background 140ms ease, color 140ms ease;
1641
+ font-size: var(--font-size-xs);
1642
+ transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
1836
1643
  }
1837
1644
  .feed-expand:hover { background: var(--accent-subtle); color: var(--accent); }
1838
1645
  .feed-expand:focus-visible {
@@ -1851,11 +1658,11 @@
1851
1658
  background: var(--surface-2);
1852
1659
  border: 1px solid var(--border);
1853
1660
  font-family: var(--font-mono);
1854
- font-size: 11px;
1661
+ font-size: var(--font-size-xs);
1855
1662
  color: var(--text-tertiary);
1856
1663
  white-space: nowrap;
1857
1664
  }
1858
- .feed-age { white-space: nowrap; font-family: var(--font-mono); font-size: 11px; color: var(--text-tertiary); letter-spacing: 0.02em; }
1665
+ .feed-age { white-space: nowrap; font-family: var(--font-mono); font-size: var(--font-size-xs); color: var(--text-tertiary); letter-spacing: 0.02em; }
1859
1666
 
1860
1667
  /* ── Pills & badges ────────────────────────────────────── */
1861
1668
 
@@ -1864,8 +1671,8 @@
1864
1671
  .kind-chip {
1865
1672
  padding: 2px 10px;
1866
1673
  font-family: var(--font-mono);
1867
- font-size: 10px;
1868
- font-weight: 600;
1674
+ font-size: var(--font-size-2xs);
1675
+ font-weight: var(--font-weight-semibold);
1869
1676
  letter-spacing: 0.08em;
1870
1677
  text-transform: uppercase;
1871
1678
  background: var(--accent-subtle);
@@ -1886,12 +1693,12 @@
1886
1693
  padding: 2px 10px;
1887
1694
  background: var(--accent-cool-subtle);
1888
1695
  color: var(--accent-cool);
1889
- font-weight: 500;
1696
+ font-weight: var(--font-weight-medium);
1890
1697
  }
1891
1698
 
1892
1699
  .badge {
1893
- font-size: 12px;
1894
- font-weight: 600;
1700
+ font-size: var(--font-size-sm);
1701
+ font-weight: var(--font-weight-semibold);
1895
1702
  background: var(--accent-cool-subtle);
1896
1703
  color: var(--accent-cool);
1897
1704
  }
@@ -1904,9 +1711,9 @@
1904
1711
  border-radius: var(--radius-pill);
1905
1712
  background: var(--accent-subtle);
1906
1713
  color: var(--accent);
1907
- font-size: 12px;
1908
- font-weight: 600;
1909
- transition: background 140ms ease, color 140ms ease;
1714
+ font-size: var(--font-size-sm);
1715
+ font-weight: var(--font-weight-semibold);
1716
+ transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
1910
1717
  }
1911
1718
  .pill.alt { background: var(--accent-warm-subtle); color: var(--accent-warm); }
1912
1719
  .pill-success { background: var(--green-bg, #16a34a22); color: var(--green-text, #16a34a); }
@@ -1926,10 +1733,10 @@
1926
1733
  border-radius: var(--radius-pill);
1927
1734
  background: var(--accent-subtle);
1928
1735
  color: var(--accent);
1929
- font-size: 12px;
1930
- font-weight: 600;
1736
+ font-size: var(--font-size-sm);
1737
+ font-weight: var(--font-weight-semibold);
1931
1738
  letter-spacing: 0.02em;
1932
- transition: background 140ms ease, color 140ms ease;
1739
+ transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
1933
1740
  }
1934
1741
  .sync-online-badge::before {
1935
1742
  content: "";
@@ -1977,13 +1784,13 @@
1977
1784
  portal <div>s between action rows and the `+` selector would miss. */
1978
1785
  .sync-action ~ .sync-action { margin-top: var(--sp-2); }
1979
1786
 
1980
- .health-action-text, .sync-action-text { font-size: 13px; color: var(--text-primary); flex: 1; min-width: 0; }
1787
+ .health-action-text, .sync-action-text { font-size: var(--font-size-md); color: var(--text-primary); flex: 1; min-width: 0; }
1981
1788
  .settings-link,
1982
1789
  .sync-subview-link {
1983
1790
  color: var(--accent);
1984
1791
  text-decoration-color: color-mix(in srgb, var(--accent) 52%, transparent);
1985
1792
  text-underline-offset: 3px;
1986
- transition: color 140ms ease, text-decoration-color 140ms ease;
1793
+ transition: color var(--duration-fast) var(--ease-standard), text-decoration-color var(--duration-fast) var(--ease-standard);
1987
1794
  }
1988
1795
  .settings-link:hover,
1989
1796
  .sync-subview-link:hover {
@@ -1999,14 +1806,14 @@
1999
1806
  }
2000
1807
  .sync-section-label {
2001
1808
  margin-top: 0;
2002
- font-size: 12px;
2003
- font-weight: 700;
1809
+ font-size: var(--font-size-sm);
1810
+ font-weight: var(--font-weight-bold);
2004
1811
  letter-spacing: 0.04em;
2005
1812
  text-transform: uppercase;
2006
1813
  color: var(--text-tertiary);
2007
1814
  }
2008
1815
  .sync-section-count {
2009
- font-size: 11px;
1816
+ font-size: var(--font-size-xs);
2010
1817
  padding: 2px 8px;
2011
1818
  }
2012
1819
  .sync-section-note {
@@ -2014,7 +1821,7 @@
2014
1821
  margin-bottom: var(--sp-1);
2015
1822
  max-width: 72ch;
2016
1823
  }
2017
- .health-action-command, .sync-action-command { display: block; margin-top: 2px; font-family: var(--font-mono); font-size: 12px; color: var(--text-tertiary); }
1824
+ .health-action-command, .sync-action-command { display: block; margin-top: 2px; font-family: var(--font-mono); font-size: var(--font-size-sm); color: var(--text-tertiary); }
2018
1825
  .health-action-buttons { display: flex; gap: 6px; flex-shrink: 0; flex-wrap: wrap; }
2019
1826
 
2020
1827
  /* ── Diagnostics ───────────────────────────────────────── */
@@ -2038,11 +1845,11 @@
2038
1845
  .diag-line .right { color: var(--text-tertiary); white-space: nowrap; }
2039
1846
  @media (max-width: 600px) {
2040
1847
  .diag-line { grid-template-columns: 1fr; }
2041
- .diag-line .right { font-size: 11px; }
1848
+ .diag-line .right { font-size: var(--font-size-xs); }
2042
1849
  }
2043
1850
 
2044
1851
  .diag-group { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); margin-top: var(--sp-3); background: var(--surface-2); }
2045
- .diag-group summary { cursor: pointer; color: var(--text-tertiary); font-size: 13px; }
1852
+ .diag-group summary { cursor: pointer; color: var(--text-tertiary); font-size: var(--font-size-md); }
2046
1853
 
2047
1854
  /* ── Peers ─────────────────────────────────────────────── */
2048
1855
 
@@ -2067,7 +1874,7 @@
2067
1874
  gap: var(--sp-2);
2068
1875
  }
2069
1876
  .peer-title { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); flex-wrap: wrap; }
2070
- .peer-title strong { font-size: 14px; font-weight: 600; }
1877
+ .peer-title strong { font-size: var(--font-size-base); font-weight: var(--font-weight-semibold); }
2071
1878
  /* Direction glyph rendered when a peer is in mutual-trust state.
2072
1879
  Handoff §E asked for ↕/↓/↑ but the full 3-way split requires a
2073
1880
  peer-role field that doesn't exist in core yet — ship the
@@ -2076,7 +1883,7 @@
2076
1883
  .peer-direction {
2077
1884
  margin-left: 6px;
2078
1885
  font-family: var(--font-mono);
2079
- font-size: 13px;
1886
+ font-size: var(--font-size-md);
2080
1887
  color: var(--text-tertiary);
2081
1888
  vertical-align: baseline;
2082
1889
  }
@@ -2144,18 +1951,18 @@
2144
1951
  align-items: start;
2145
1952
  }
2146
1953
  .legacy-review-title-wrap { display: flex; align-items: flex-start; gap: var(--sp-2); min-width: 0; }
2147
- .legacy-review-group-title { color: var(--text-primary); font-weight: 700; overflow-wrap: anywhere; }
1954
+ .legacy-review-group-title { color: var(--text-primary); font-weight: var(--font-weight-bold); overflow-wrap: anywhere; }
2148
1955
  .legacy-review-group-meta,
2149
1956
  .legacy-review-reason {
2150
1957
  margin-top: 2px;
2151
1958
  color: var(--text-tertiary);
2152
- font-size: 12px;
1959
+ font-size: var(--font-size-sm);
2153
1960
  line-height: 1.45;
2154
1961
  }
2155
1962
  .legacy-review-cleanup-note {
2156
1963
  margin-top: 6px;
2157
1964
  color: var(--accent-warm);
2158
- font-size: 12px;
1965
+ font-size: var(--font-size-sm);
2159
1966
  line-height: 1.45;
2160
1967
  }
2161
1968
  .legacy-review-count {
@@ -2166,7 +1973,7 @@
2166
1973
  background: var(--accent-neutral-subtle);
2167
1974
  color: var(--text-secondary);
2168
1975
  font-family: var(--font-mono);
2169
- font-size: 12px;
1976
+ font-size: var(--font-size-sm);
2170
1977
  }
2171
1978
  .legacy-review-confirmation {
2172
1979
  padding: var(--sp-2) var(--sp-3);
@@ -2174,15 +1981,43 @@
2174
1981
  border-radius: var(--radius-md);
2175
1982
  background: var(--accent-warm-subtle);
2176
1983
  color: var(--text-secondary);
2177
- font-size: 13px;
1984
+ font-size: var(--font-size-md);
2178
1985
  line-height: 1.45;
2179
1986
  }
1987
+ .legacy-review-samples {
1988
+ padding: var(--sp-2) var(--sp-3);
1989
+ border: 1px solid var(--border);
1990
+ border-radius: var(--radius-md);
1991
+ background: color-mix(in srgb, var(--surface-1) 72%, transparent);
1992
+ }
1993
+ .legacy-review-samples summary {
1994
+ cursor: pointer;
1995
+ color: var(--text-primary);
1996
+ font-weight: var(--font-weight-semibold);
1997
+ }
1998
+ .legacy-review-sample-list {
1999
+ display: grid;
2000
+ gap: var(--sp-2);
2001
+ margin: var(--sp-2) 0 0;
2002
+ padding: 0;
2003
+ list-style: none;
2004
+ }
2005
+ .legacy-review-sample {
2006
+ display: grid;
2007
+ gap: 3px;
2008
+ padding: var(--sp-2);
2009
+ border: 1px solid var(--border);
2010
+ border-radius: var(--radius-sm);
2011
+ background: var(--surface-1);
2012
+ }
2013
+ .legacy-review-sample-title { color: var(--text-primary); font-weight: var(--font-weight-semibold); }
2014
+ .legacy-review-sample-body { color: var(--text-secondary); font-size: var(--font-size-sm); line-height: 1.45; }
2180
2015
  .legacy-review-target {
2181
2016
  display: grid;
2182
2017
  gap: 5px;
2183
2018
  color: var(--text-tertiary);
2184
- font-size: 11px;
2185
- font-weight: 600;
2019
+ font-size: var(--font-size-xs);
2020
+ font-weight: var(--font-weight-semibold);
2186
2021
  letter-spacing: 0.04em;
2187
2022
  text-transform: uppercase;
2188
2023
  }
@@ -2195,12 +2030,12 @@
2195
2030
  .actor-create-row input { flex: 1 1 260px; max-height: 40px; }
2196
2031
  .actor-badge.local { background: rgba(31, 111, 92, 0.12); color: var(--accent); }
2197
2032
  .peer-scope { display: grid; gap: var(--sp-2); padding-top: var(--sp-2); border-top: 1px solid var(--border); }
2198
- .peer-scope-summary, .peer-scope-effective { font-size: 12px; color: var(--text-secondary); }
2033
+ .peer-scope-summary, .peer-scope-effective { font-size: var(--font-size-sm); color: var(--text-secondary); }
2199
2034
  .peer-actor-row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
2200
2035
  .peer-scope-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
2201
2036
  .peer-scope-editor { display: grid; gap: 8px; }
2202
2037
  .peer-scope-chips { display: flex; flex-wrap: wrap; gap: 6px; min-height: 32px; align-items: flex-start; padding: 8px 10px; margin: 0; list-style: none; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); }
2203
- .peer-scope-chip { padding: 4px 8px; background: rgba(43, 122, 176, 0.12); color: var(--accent); font-size: 12px; }
2038
+ .peer-scope-chip { padding: 4px 8px; background: rgba(43, 122, 176, 0.12); color: var(--accent); font-size: var(--font-size-sm); }
2204
2039
  .peer-scope-chip.empty { background: transparent; color: var(--text-tertiary); border-style: dashed; border-color: var(--border); }
2205
2040
 
2206
2041
  /* ProjectScopePicker — selected chips on top, an "Add project"
@@ -2228,7 +2063,7 @@
2228
2063
  align-items: center;
2229
2064
  }
2230
2065
  .project-scope-picker-selected-empty {
2231
- font-size: 12px;
2066
+ font-size: var(--font-size-sm);
2232
2067
  color: var(--text-tertiary);
2233
2068
  }
2234
2069
  .project-scope-picker-selected-chip {
@@ -2240,7 +2075,7 @@
2240
2075
  border: 1px solid color-mix(in srgb, var(--accent) 48%, var(--border));
2241
2076
  border-radius: var(--radius-pill);
2242
2077
  color: var(--accent);
2243
- font-size: 12px;
2078
+ font-size: var(--font-size-sm);
2244
2079
  }
2245
2080
  .project-scope-picker-selected-remove {
2246
2081
  appearance: none;
@@ -2250,7 +2085,7 @@
2250
2085
  cursor: pointer;
2251
2086
  padding: 0 4px;
2252
2087
  font: inherit;
2253
- font-size: 14px;
2088
+ font-size: var(--font-size-base);
2254
2089
  line-height: 1;
2255
2090
  opacity: 0.7;
2256
2091
  }
@@ -2261,7 +2096,7 @@
2261
2096
  align-items: center;
2262
2097
  gap: 6px;
2263
2098
  padding: 6px 12px;
2264
- font-size: 12px;
2099
+ font-size: var(--font-size-sm);
2265
2100
  }
2266
2101
  .project-scope-picker-popover {
2267
2102
  width: min(360px, 100%);
@@ -2295,7 +2130,7 @@
2295
2130
  color: var(--text-primary);
2296
2131
  padding: 6px 10px;
2297
2132
  font: inherit;
2298
- font-size: 13px;
2133
+ font-size: var(--font-size-md);
2299
2134
  }
2300
2135
  .project-scope-picker-search:focus {
2301
2136
  outline: 2px solid var(--accent);
@@ -2312,7 +2147,7 @@
2312
2147
  }
2313
2148
  .project-scope-picker-empty-row {
2314
2149
  padding: 8px 10px;
2315
- font-size: 12px;
2150
+ font-size: var(--font-size-sm);
2316
2151
  color: var(--text-tertiary);
2317
2152
  }
2318
2153
  .project-scope-picker-row {
@@ -2330,7 +2165,7 @@
2330
2165
  border-radius: var(--radius-sm);
2331
2166
  cursor: pointer;
2332
2167
  color: var(--text-secondary);
2333
- font-size: 13px;
2168
+ font-size: var(--font-size-md);
2334
2169
  }
2335
2170
  .project-scope-picker-row:focus-visible {
2336
2171
  outline: 2px solid var(--accent);
@@ -2347,7 +2182,7 @@
2347
2182
  display: inline-block;
2348
2183
  width: 16px;
2349
2184
  text-align: center;
2350
- font-size: 12px;
2185
+ font-size: var(--font-size-sm);
2351
2186
  color: var(--accent);
2352
2187
  }
2353
2188
  .project-scope-picker-row--create .project-scope-picker-row-check {
@@ -2366,8 +2201,8 @@
2366
2201
  .presence-pip--online { background: var(--accent); }
2367
2202
  .presence-pip--offline { background: var(--accent-warm, var(--accent)); }
2368
2203
  .presence-pip--degraded { background: var(--accent-warm, var(--accent)); }
2369
- .presence-pip--attention { background: var(--accent-warm-strong, var(--accent-warm, var(--accent))); animation: pip-attention 2.4s ease-in-out infinite; }
2370
- .presence-pip--syncing { background: var(--accent); animation: pip-syncing 1.2s ease-in-out infinite; }
2204
+ .presence-pip--attention { background: var(--accent-warm-strong, var(--accent-warm, var(--accent))); animation: pip-attention var(--duration-pulse) var(--ease-in-out) infinite; }
2205
+ .presence-pip--syncing { background: var(--accent); animation: pip-syncing var(--duration-pip) var(--ease-in-out) infinite; }
2371
2206
  .presence-pip--unknown { background: var(--text-tertiary); opacity: 0.6; }
2372
2207
 
2373
2208
  @keyframes pip-attention {
@@ -2393,8 +2228,8 @@
2393
2228
  were glaring once the deep-ink palette raised contrast. */
2394
2229
  .sync-labeled-field { display: flex; flex-direction: column; gap: 4px; min-width: 180px; flex: 1 1 220px; }
2395
2230
  .sync-labeled-field-caption {
2396
- font-size: 11px;
2397
- font-weight: 500;
2231
+ font-size: var(--font-size-xs);
2232
+ font-weight: var(--font-weight-medium);
2398
2233
  letter-spacing: 0.06em;
2399
2234
  text-transform: uppercase;
2400
2235
  color: var(--text-tertiary);
@@ -2411,7 +2246,7 @@
2411
2246
  display: grid;
2412
2247
  gap: var(--sp-2);
2413
2248
  overflow: hidden;
2414
- transition: max-height 0.25s ease, opacity 0.2s ease;
2249
+ transition: max-height var(--duration-medium) var(--ease-standard), opacity var(--duration-base) var(--ease-standard);
2415
2250
  max-height: 400px;
2416
2251
  opacity: 1;
2417
2252
  }
@@ -2430,7 +2265,7 @@
2430
2265
  border-radius: 6px;
2431
2266
  background: linear-gradient(90deg, var(--border) 25%, var(--surface-2) 50%, var(--border) 75%);
2432
2267
  background-size: 400px 100%;
2433
- animation: sync-shimmer 1.5s ease-in-out infinite;
2268
+ animation: sync-shimmer var(--duration-shimmer) var(--ease-in-out) infinite;
2434
2269
  margin: 8px 0;
2435
2270
  }
2436
2271
  .sync-skeleton-line.short { width: 40%; }
@@ -2441,7 +2276,7 @@
2441
2276
  border-radius: 8px;
2442
2277
  background: linear-gradient(90deg, var(--border) 25%, var(--surface-2) 50%, var(--border) 75%);
2443
2278
  background-size: 400px 100%;
2444
- animation: sync-shimmer 1.5s ease-in-out infinite;
2279
+ animation: sync-shimmer var(--duration-shimmer) var(--ease-in-out) infinite;
2445
2280
  margin: 8px 0;
2446
2281
  }
2447
2282
  .sync-empty-state {
@@ -2467,7 +2302,7 @@
2467
2302
  }
2468
2303
  .sync-inline-feedback {
2469
2304
  margin-top: 8px;
2470
- font-size: 12px;
2305
+ font-size: var(--font-size-sm);
2471
2306
  color: var(--text-secondary);
2472
2307
  }
2473
2308
  .sync-inline-feedback.success { color: var(--accent); }
@@ -2486,7 +2321,7 @@
2486
2321
  20%, 60% { transform: translateX(-4px); }
2487
2322
  40%, 80% { transform: translateX(4px); }
2488
2323
  }
2489
- .sync-shake { animation: sync-shake 0.3s ease-in-out; }
2324
+ .sync-shake { animation: sync-shake var(--duration-shake) var(--ease-in-out); }
2490
2325
  @keyframes sync-attention-target {
2491
2326
  0% {
2492
2327
  transform: translateY(0);
@@ -2502,14 +2337,14 @@
2502
2337
  }
2503
2338
  }
2504
2339
  .sync-attention-target {
2505
- animation: sync-attention-target 900ms ease-out;
2340
+ animation: sync-attention-target var(--duration-attention) var(--ease-out);
2506
2341
  }
2507
2342
  .settings-button:disabled {
2508
2343
  opacity: 0.55;
2509
2344
  cursor: not-allowed;
2510
2345
  }
2511
2346
  .settings-button {
2512
- transition: opacity 140ms ease, background 140ms ease, color 140ms ease;
2347
+ transition: opacity var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
2513
2348
  }
2514
2349
  .sync-toggle-admin {
2515
2350
  background: none;
@@ -2552,19 +2387,19 @@
2552
2387
  flex-wrap: wrap;
2553
2388
  }
2554
2389
  .sync-team-status-label {
2555
- font-size: 12px;
2556
- font-weight: 600;
2390
+ font-size: var(--font-size-sm);
2391
+ font-weight: var(--font-weight-semibold);
2557
2392
  letter-spacing: 0.04em;
2558
2393
  text-transform: uppercase;
2559
2394
  color: var(--text-tertiary);
2560
2395
  }
2561
2396
  .sync-team-headline {
2562
- font-size: 15px;
2563
- font-weight: 700;
2397
+ font-size: var(--font-size-lg);
2398
+ font-weight: var(--font-weight-bold);
2564
2399
  color: var(--text-primary);
2565
2400
  }
2566
2401
  .sync-team-metrics {
2567
- font-size: 13px;
2402
+ font-size: var(--font-size-md);
2568
2403
  color: var(--text-secondary);
2569
2404
  font-feature-settings: 'tnum' 1;
2570
2405
  }
@@ -2627,7 +2462,7 @@
2627
2462
  border-radius: var(--radius-sm);
2628
2463
  color: var(--text-primary);
2629
2464
  font-family: var(--font-sans);
2630
- font-size: 13px;
2465
+ font-size: var(--font-size-md);
2631
2466
  cursor: pointer;
2632
2467
  user-select: none;
2633
2468
  }
@@ -2652,9 +2487,9 @@
2652
2487
  background: var(--input-bg);
2653
2488
  color: var(--text-primary);
2654
2489
  font-family: var(--font-sans);
2655
- font-size: 13px;
2490
+ font-size: var(--font-size-md);
2656
2491
  cursor: pointer;
2657
- transition: border-color 140ms ease, box-shadow 140ms ease;
2492
+ transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
2658
2493
  }
2659
2494
  .sync-legacy-select:hover { border-color: var(--border-hover); }
2660
2495
  .sync-legacy-select:focus {
@@ -2667,9 +2502,9 @@
2667
2502
  background: var(--control-bg);
2668
2503
  color: var(--control-text);
2669
2504
  padding: 8px 14px;
2670
- font-size: 13px;
2671
- font-weight: 600;
2672
- transition: background 140ms ease, border-color 140ms ease, transform 140ms ease;
2505
+ font-size: var(--font-size-md);
2506
+ font-weight: var(--font-weight-semibold);
2507
+ transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard);
2673
2508
  }
2674
2509
  .sync-legacy-button:hover {
2675
2510
  background: var(--control-hover-bg);
@@ -2691,9 +2526,9 @@
2691
2526
  background: var(--input-bg);
2692
2527
  color: var(--text-primary);
2693
2528
  font-family: var(--font-sans);
2694
- font-size: 13px;
2529
+ font-size: var(--font-size-md);
2695
2530
  cursor: pointer;
2696
- transition: border-color 140ms ease, box-shadow 140ms ease;
2531
+ transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
2697
2532
  }
2698
2533
  .sync-actor-select:hover { border-color: var(--border-hover); }
2699
2534
  .sync-actor-select:focus {
@@ -2701,15 +2536,15 @@
2701
2536
  border-color: var(--accent);
2702
2537
  box-shadow: 0 0 0 3px var(--focus-ring);
2703
2538
  }
2704
- .peer-meta { font-size: 13px; color: var(--text-tertiary); font-feature-settings: 'tnum' 1; }
2705
- .peer-addresses { font-family: var(--font-mono); font-size: 12px; color: var(--text-tertiary); letter-spacing: 0.02em; }
2706
- .attempts-list { margin-top: var(--sp-3); display: grid; gap: 6px; font-size: 13px; color: var(--text-tertiary); }
2539
+ .peer-meta { font-size: var(--font-size-md); color: var(--text-tertiary); font-feature-settings: 'tnum' 1; }
2540
+ .peer-addresses { font-family: var(--font-mono); font-size: var(--font-size-sm); color: var(--text-tertiary); letter-spacing: 0.02em; }
2541
+ .attempts-list { margin-top: var(--sp-3); display: grid; gap: 6px; font-size: var(--font-size-md); color: var(--text-tertiary); }
2707
2542
 
2708
2543
  /* ── Pairing ───────────────────────────────────────────── */
2709
2544
 
2710
2545
  .pairing-card { margin-top: var(--sp-4); border: 1px dashed var(--border); border-radius: var(--radius-lg); padding: var(--sp-4); display: grid; gap: var(--sp-3); background: var(--surface-2); }
2711
2546
  .pairing-body { display: grid; gap: var(--sp-3); grid-template-columns: 1.4fr 1fr; align-items: start; }
2712
- .pairing-body pre { margin: 0; font-size: 12px; background: var(--surface-0); padding: var(--sp-3); border-radius: var(--radius-md); white-space: pre-wrap; word-break: break-all; }
2547
+ .pairing-body pre { margin: 0; font-size: var(--font-size-sm); background: var(--surface-0); padding: var(--sp-3); border-radius: var(--radius-md); white-space: pre-wrap; word-break: break-all; }
2713
2548
  @media (max-width: 900px) { .pairing-body { grid-template-columns: 1fr; } }
2714
2549
 
2715
2550
  /* ── Modal ──────────────────────────────────────────────── */
@@ -2770,13 +2605,13 @@
2770
2605
  color: var(--text-primary);
2771
2606
  padding: 6px 10px;
2772
2607
  font-family: var(--font-mono);
2773
- font-size: 11px;
2608
+ font-size: var(--font-size-xs);
2774
2609
  line-height: 1.4;
2775
2610
  letter-spacing: 0.01em;
2776
2611
  max-width: 320px;
2777
2612
  z-index: 60;
2778
2613
  user-select: none;
2779
- animation: tooltipFade 140ms ease;
2614
+ animation: tooltipFade var(--duration-fast) var(--ease-standard);
2780
2615
  }
2781
2616
  .tooltip-content[data-state="closed"] { animation: none; }
2782
2617
  .tooltip-arrow { fill: var(--surface-1); filter: drop-shadow(0 1px 0 var(--border)); }
@@ -2785,7 +2620,7 @@
2785
2620
  to { opacity: 1; transform: translateY(0); }
2786
2621
  }
2787
2622
  .modal-header { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
2788
- .modal-header h2 { margin: 0; font-size: 18px; }
2623
+ .modal-header h2 { margin: 0; font-size: var(--font-size-2xl); }
2789
2624
  .modal-close-button {
2790
2625
  border: 1px solid color-mix(in srgb, var(--border) 88%, transparent);
2791
2626
  background: color-mix(in srgb, var(--surface-0) 78%, transparent);
@@ -2798,8 +2633,8 @@
2798
2633
  gap: 7px;
2799
2634
  cursor: pointer;
2800
2635
  font-family: var(--font-sans);
2801
- font-size: 12px;
2802
- transition: border-color 140ms ease, background 140ms ease, color 140ms ease;
2636
+ font-size: var(--font-size-sm);
2637
+ transition: border-color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
2803
2638
  }
2804
2639
  .modal-close-button:hover {
2805
2640
  border-color: var(--border-hover);
@@ -2824,7 +2659,7 @@
2824
2659
  height: 100%;
2825
2660
  }
2826
2661
  .modal-close-button-label {
2827
- font-weight: 600;
2662
+ font-weight: var(--font-weight-semibold);
2828
2663
  letter-spacing: 0.01em;
2829
2664
  }
2830
2665
  .modal-body { display: flex; flex-direction: column; gap: var(--sp-3); flex: 1; min-height: 0; overflow-y: auto; padding-right: 6px; }
@@ -2859,14 +2694,14 @@
2859
2694
  gap: var(--sp-3);
2860
2695
  align-items: start;
2861
2696
  color: var(--text-primary);
2862
- font-size: 13px;
2697
+ font-size: var(--font-size-md);
2863
2698
  line-height: 1.5;
2864
2699
  }
2865
- .toast-root[data-state="open"] { animation: toastSlideIn 160ms ease; }
2866
- .toast-root[data-state="closed"] { animation: toastFadeOut 140ms ease forwards; }
2700
+ .toast-root[data-state="open"] { animation: toastSlideIn var(--duration-toast) var(--ease-standard); }
2701
+ .toast-root[data-state="closed"] { animation: toastFadeOut var(--duration-fast) var(--ease-standard) forwards; }
2867
2702
  .toast-root[data-swipe="move"] { transform: translateX(var(--radix-toast-swipe-move-x)); }
2868
- .toast-root[data-swipe="cancel"] { transform: translateX(0); transition: transform 140ms ease; }
2869
- .toast-root[data-swipe="end"] { animation: toastSwipeOut 140ms ease forwards; }
2703
+ .toast-root[data-swipe="cancel"] { transform: translateX(0); transition: transform var(--duration-fast) var(--ease-standard); }
2704
+ .toast-root[data-swipe="end"] { animation: toastSwipeOut var(--duration-fast) var(--ease-standard) forwards; }
2870
2705
 
2871
2706
  .toast-success { border-left-color: var(--accent); }
2872
2707
  .toast-info { border-left-color: var(--accent-cool); }
@@ -2885,10 +2720,10 @@
2885
2720
  display: inline-flex;
2886
2721
  align-items: center;
2887
2722
  justify-content: center;
2888
- font-size: 14px;
2723
+ font-size: var(--font-size-base);
2889
2724
  line-height: 1;
2890
2725
  cursor: pointer;
2891
- transition: background-color 140ms ease, color 140ms ease;
2726
+ transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
2892
2727
  padding: 0;
2893
2728
  flex-shrink: 0;
2894
2729
  }
@@ -2934,19 +2769,19 @@
2934
2769
  box-shadow: var(--shadow-md);
2935
2770
  }
2936
2771
  .viewer-reconnect-eyebrow {
2937
- font-size: 12px;
2938
- font-weight: 700;
2772
+ font-size: var(--font-size-sm);
2773
+ font-weight: var(--font-weight-bold);
2939
2774
  letter-spacing: 0.06em;
2940
2775
  text-transform: uppercase;
2941
2776
  color: var(--text-tertiary);
2942
2777
  }
2943
2778
  .viewer-reconnect-title {
2944
- font-size: 18px;
2945
- font-weight: 700;
2779
+ font-size: var(--font-size-2xl);
2780
+ font-weight: var(--font-weight-bold);
2946
2781
  color: var(--text-primary);
2947
2782
  }
2948
2783
  .viewer-reconnect-detail {
2949
- font-size: 13px;
2784
+ font-size: var(--font-size-md);
2950
2785
  line-height: 1.5;
2951
2786
  color: var(--text-secondary);
2952
2787
  }
@@ -2955,7 +2790,7 @@
2955
2790
  align-items: center;
2956
2791
  gap: 10px;
2957
2792
  color: var(--text-secondary);
2958
- font-size: 12px;
2793
+ font-size: var(--font-size-sm);
2959
2794
  }
2960
2795
  .viewer-reconnect-spinner {
2961
2796
  width: 14px;
@@ -2963,14 +2798,14 @@
2963
2798
  border-radius: 50%;
2964
2799
  border: 2px solid color-mix(in srgb, var(--accent) 22%, transparent);
2965
2800
  border-top-color: var(--accent);
2966
- animation: reconnectSpin 0.9s linear infinite;
2801
+ animation: reconnectSpin var(--duration-attention) linear infinite;
2967
2802
  }
2968
2803
  @keyframes reconnectSpin {
2969
2804
  from { transform: rotate(0deg); }
2970
2805
  to { transform: rotate(360deg); }
2971
2806
  }
2972
2807
 
2973
- .settings-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
2808
+ .settings-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin-bottom: var(--sp-2); }
2974
2809
  .settings-tab {
2975
2810
  border: 1px solid var(--border);
2976
2811
  background: var(--surface-0);
@@ -2978,7 +2813,7 @@
2978
2813
  border-radius: var(--radius-sm);
2979
2814
  padding: 7px 10px;
2980
2815
  font-family: var(--font-sans);
2981
- font-size: 12px;
2816
+ font-size: var(--font-size-sm);
2982
2817
  cursor: pointer;
2983
2818
  }
2984
2819
  .settings-tab:hover { border-color: var(--border-hover); }
@@ -3002,8 +2837,8 @@
3002
2837
  }
3003
2838
  .settings-section-intro-title {
3004
2839
  color: var(--text-primary);
3005
- font-size: 13px;
3006
- font-weight: 600;
2840
+ font-size: var(--font-size-md);
2841
+ font-weight: var(--font-weight-semibold);
3007
2842
  }
3008
2843
  .settings-section-intro-detail {
3009
2844
  margin: 0;
@@ -3017,17 +2852,17 @@
3017
2852
  border: 1px solid var(--border);
3018
2853
  border-radius: var(--radius-md);
3019
2854
  background: var(--surface-0);
3020
- font-size: 12px;
2855
+ font-size: var(--font-size-sm);
3021
2856
  color: var(--text-secondary);
3022
2857
  line-height: 1.5;
3023
2858
  }
3024
2859
  .observer-status-banner .status-active {
3025
2860
  color: var(--text-primary);
3026
- font-weight: 500;
2861
+ font-weight: var(--font-weight-medium);
3027
2862
  }
3028
2863
  .observer-status-banner .status-label {
3029
2864
  color: var(--text-tertiary);
3030
- font-size: 11px;
2865
+ font-size: var(--font-size-xs);
3031
2866
  text-transform: uppercase;
3032
2867
  letter-spacing: 0.06em;
3033
2868
  }
@@ -3047,7 +2882,7 @@
3047
2882
  }
3048
2883
  .observer-status-banner .status-issue-message {
3049
2884
  color: var(--text-primary);
3050
- font-weight: 500;
2885
+ font-weight: var(--font-weight-medium);
3051
2886
  }
3052
2887
  .observer-status-banner .status-issue-meta {
3053
2888
  color: var(--text-secondary);
@@ -3068,7 +2903,7 @@
3068
2903
  }
3069
2904
  .settings-group-title {
3070
2905
  margin: 0;
3071
- font-size: 12px;
2906
+ font-size: var(--font-size-sm);
3072
2907
  letter-spacing: 0.06em;
3073
2908
  text-transform: uppercase;
3074
2909
  color: var(--text-tertiary);
@@ -3111,13 +2946,13 @@
3111
2946
  border-radius: var(--radius-sm);
3112
2947
  background: var(--surface-1);
3113
2948
  color: var(--text-secondary);
3114
- font-size: 12px;
2949
+ font-size: var(--font-size-sm);
3115
2950
  line-height: 1.4;
3116
2951
  box-shadow: var(--shadow-sm);
3117
2952
  pointer-events: none;
3118
2953
  opacity: 0;
3119
2954
  transform: translateY(-2px);
3120
- transition: opacity 0.08s ease, transform 0.08s ease;
2955
+ transition: opacity var(--duration-instant) var(--ease-standard), transform var(--duration-instant) var(--ease-standard);
3121
2956
  z-index: 1000;
3122
2957
  }
3123
2958
 
@@ -3146,8 +2981,8 @@
3146
2981
  display: none !important;
3147
2982
  }
3148
2983
 
3149
- .field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
3150
- .field input:not([type="checkbox"]), .field select, .field textarea { padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--input-bg); font-family: var(--font-sans); font-size: 13px; color: var(--text-primary); }
2984
+ .field { display: flex; flex-direction: column; gap: 6px; font-size: var(--font-size-md); }
2985
+ .field input:not([type="checkbox"]), .field select, .field textarea { padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--input-bg); font-family: var(--font-sans); font-size: var(--font-size-md); color: var(--text-primary); }
3151
2986
  .settings-select-trigger {
3152
2987
  display: inline-flex;
3153
2988
  align-items: center;
@@ -3160,7 +2995,7 @@
3160
2995
  background: var(--input-bg);
3161
2996
  color: var(--text-primary);
3162
2997
  font-family: var(--font-sans);
3163
- font-size: 13px;
2998
+ font-size: var(--font-size-md);
3164
2999
  text-align: left;
3165
3000
  }
3166
3001
  .settings-select-trigger:hover { border-color: var(--border-hover); }
@@ -3189,7 +3024,7 @@
3189
3024
  border-radius: var(--radius-sm);
3190
3025
  color: var(--text-primary);
3191
3026
  font-family: var(--font-sans);
3192
- font-size: 13px;
3027
+ font-size: var(--font-size-md);
3193
3028
  cursor: pointer;
3194
3029
  user-select: none;
3195
3030
  }
@@ -3223,7 +3058,7 @@
3223
3058
  cursor: pointer;
3224
3059
  flex-shrink: 0;
3225
3060
  padding: 1px;
3226
- transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
3061
+ transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
3227
3062
  }
3228
3063
  .settings-switch:hover {
3229
3064
  border-color: color-mix(in srgb, var(--accent) 38%, var(--control-hover-border));
@@ -3249,7 +3084,7 @@
3249
3084
  background: color-mix(in srgb, var(--surface-0) 88%, white);
3250
3085
  border: 1px solid color-mix(in srgb, var(--text-tertiary) 24%, transparent);
3251
3086
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
3252
- transition: transform 140ms ease, background 140ms ease;
3087
+ transition: transform var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);
3253
3088
  transform: translateX(0);
3254
3089
  }
3255
3090
  .settings-switch[data-state="checked"] .settings-switch-thumb {
@@ -3294,9 +3129,9 @@
3294
3129
  padding: var(--sp-2) var(--sp-4);
3295
3130
  border-radius: var(--radius-md);
3296
3131
  font-family: var(--font-sans);
3297
- font-size: 12px;
3132
+ font-size: var(--font-size-sm);
3298
3133
  cursor: pointer;
3299
- transition: background 140ms ease;
3134
+ transition: background var(--duration-fast) var(--ease-standard);
3300
3135
  }
3301
3136
  .settings-save:hover { background: var(--control-hover-bg); }
3302
3137
  .sync-dialog-card {
@@ -3316,7 +3151,7 @@
3316
3151
  background: var(--input-bg);
3317
3152
  color: var(--text-primary);
3318
3153
  font-family: var(--font-sans);
3319
- font-size: 13px;
3154
+ font-size: var(--font-size-md);
3320
3155
  box-sizing: border-box;
3321
3156
  }
3322
3157
  .sync-dialog-input:focus {
@@ -3346,7 +3181,7 @@
3346
3181
  border-radius: var(--radius-sm);
3347
3182
  color: var(--text-primary);
3348
3183
  font-family: var(--font-sans);
3349
- font-size: 13px;
3184
+ font-size: var(--font-size-md);
3350
3185
  cursor: pointer;
3351
3186
  user-select: none;
3352
3187
  }
@@ -3386,7 +3221,7 @@
3386
3221
  border-radius: var(--radius-md);
3387
3222
  background: color-mix(in srgb, var(--surface-1) 86%, var(--surface-0));
3388
3223
  cursor: pointer;
3389
- transition: border-color 140ms ease, background 140ms ease;
3224
+ transition: border-color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);
3390
3225
  }
3391
3226
  .sync-dialog-radio-option:hover {
3392
3227
  border-color: var(--border-hover);
@@ -3424,15 +3259,15 @@
3424
3259
  }
3425
3260
  .sync-dialog-radio-label {
3426
3261
  color: var(--text-primary);
3427
- font-size: 13px;
3262
+ font-size: var(--font-size-md);
3428
3263
  }
3429
3264
  .settings-save:disabled { opacity: 0.6; cursor: not-allowed; }
3430
- .settings-note { color: var(--text-tertiary); font-size: 12px; }
3265
+ .settings-note { color: var(--text-tertiary); font-size: var(--font-size-sm); }
3431
3266
 
3432
3267
  /* ── Utilities ─────────────────────────────────────────── */
3433
3268
 
3434
- .small { color: var(--text-tertiary); font-size: 12px; }
3435
- .mono { font-family: var(--font-mono); font-size: 12px; }
3269
+ .small { color: var(--text-tertiary); font-size: var(--font-size-sm); }
3270
+ .mono { font-family: var(--font-mono); font-size: var(--font-size-sm); }
3436
3271
 
3437
3272
  /* ── Animations ────────────────────────────────────────── */
3438
3273
 
@@ -3458,7 +3293,7 @@
3458
3293
  30% { box-shadow: 0 0 0 6px var(--accent-subtle); }
3459
3294
  100% { box-shadow: 0 0 0 0 transparent; }
3460
3295
  }
3461
- .feed-item.new-item { animation: newPulse 420ms ease-out 1; }
3296
+ .feed-item.new-item { animation: newPulse var(--duration-new-pulse) var(--ease-out) 1; }
3462
3297
  }
3463
3298
 
3464
3299
  /* ── Responsive ────────────────────────────────────────── */
@@ -3480,6 +3315,22 @@
3480
3315
  .legacy-review-bulk-row .settings-save { width: 100%; }
3481
3316
  }
3482
3317
 
3318
+ @media (max-width: 720px) {
3319
+ /* Hide diagnostic metadata (runtime version + database path) when the
3320
+ header would otherwise wrap. Keeps brand + project filter + theme
3321
+ + settings on a single row at common split-window widths. */
3322
+ .header-tertiary { display: none; }
3323
+ /* Allow the tab bar to scroll horizontally rather than wrap into two
3324
+ rows. Scrollbar is hidden to keep the sticky chrome compact. */
3325
+ .tab-bar {
3326
+ overflow-x: auto;
3327
+ -webkit-overflow-scrolling: touch;
3328
+ scrollbar-width: none;
3329
+ }
3330
+ .tab-bar::-webkit-scrollbar { display: none; }
3331
+ .tab-btn { flex-shrink: 0; }
3332
+ }
3333
+
3483
3334
  @media (max-width: 520px) {
3484
3335
  header { padding: var(--sp-3) var(--sp-4); }
3485
3336
  .tab-bar { padding: 0 var(--sp-4); }
@@ -3487,6 +3338,34 @@
3487
3338
  .modal-card { padding: var(--sp-4); border-radius: var(--radius-lg); }
3488
3339
  }
3489
3340
 
3341
+ /* ──────────────────────────────────────────────────────────────────
3342
+ Token-aligned focus rings.
3343
+
3344
+ The interactive surfaces below previously relied on the browser's
3345
+ default focus outline. They now share the same focus language as
3346
+ the rest of the system:
3347
+ - Buttons get a 2px var(--accent) outline with a 2px offset.
3348
+ - Inputs and selects get an accent border + 3px var(--focus-ring)
3349
+ halo, matching .feed-search / .project-filter / .sync-actor-select.
3350
+ Radix-managed items (with [data-highlighted]) are intentionally not
3351
+ touched here because their highlight state already serves as a
3352
+ keyboard-focus indicator. */
3353
+ .coordinator-admin-tab-trigger:focus-visible,
3354
+ .feed-inspector-button:focus-visible {
3355
+ outline: 2px solid var(--accent);
3356
+ outline-offset: 2px;
3357
+ }
3358
+ .actor-merge-select:focus,
3359
+ .actor-name-input:focus,
3360
+ .feed-visibility-select:focus,
3361
+ .legacy-review-search:focus,
3362
+ .peer-scope-input:focus,
3363
+ .project-domain-select:focus {
3364
+ outline: none;
3365
+ border-color: var(--accent);
3366
+ box-shadow: 0 0 0 3px var(--focus-ring);
3367
+ }
3368
+
3490
3369
  @media (prefers-reduced-motion: reduce) {
3491
3370
  *, *::before, *::after {
3492
3371
  animation-duration: 0.01ms !important;
@@ -3516,8 +3395,10 @@
3516
3395
  <span class="sr-only" id="refreshAnnouncer" aria-live="polite"></span>
3517
3396
  </div>
3518
3397
  <div class="header-right">
3519
- <span class="runtime-label" id="runtimeLabel" hidden></span>
3520
- <span class="meta-line" id="metaLine"></span>
3398
+ <div class="header-tertiary">
3399
+ <span class="runtime-label" id="runtimeLabel" hidden></span>
3400
+ <span class="meta-line" id="metaLine"></span>
3401
+ </div>
3521
3402
  <select class="project-filter" id="projectFilter" aria-label="Project filter">
3522
3403
  <option value="">All Projects</option>
3523
3404
  </select>
@@ -3845,6 +3726,18 @@
3845
3726
  <select id="projectsStatusFilter" aria-label="Project status filter"></select>
3846
3727
  </div>
3847
3728
  <div class="section-meta" id="projectsInventoryMeta">Loading project inventory…</div>
3729
+ <div class="project-inventory-skeleton" id="projectsInventorySkeleton" role="status" aria-label="Loading project inventory" aria-busy="true">
3730
+ <div class="project-inventory-skeleton-row">
3731
+ <div class="project-inventory-skeleton-line title"></div>
3732
+ <div class="project-inventory-skeleton-line meta"></div>
3733
+ <div class="project-inventory-skeleton-line signal"></div>
3734
+ </div>
3735
+ <div class="project-inventory-skeleton-row">
3736
+ <div class="project-inventory-skeleton-line title"></div>
3737
+ <div class="project-inventory-skeleton-line meta"></div>
3738
+ <div class="project-inventory-skeleton-line signal"></div>
3739
+ </div>
3740
+ </div>
3848
3741
  <div class="project-inventory-list" id="projectsInventoryList" aria-live="polite"></div>
3849
3742
  <div class="section-actions projects-pagination">
3850
3743
  <button class="settings-button" id="projectsPrevPage" type="button">Previous</button>