somtum 1.5.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +41 -22
  2. package/dist/cli/index.js +1 -0
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/cli/list.d.ts +1 -0
  5. package/dist/cli/list.d.ts.map +1 -1
  6. package/dist/cli/list.js +4 -1
  7. package/dist/cli/list.js.map +1 -1
  8. package/dist/cli/stats.d.ts +1 -0
  9. package/dist/cli/stats.d.ts.map +1 -1
  10. package/dist/cli/stats.js +11 -1
  11. package/dist/cli/stats.js.map +1 -1
  12. package/dist/config.d.ts +2 -0
  13. package/dist/config.d.ts.map +1 -1
  14. package/dist/config.js +6 -0
  15. package/dist/config.js.map +1 -1
  16. package/dist/core/dedup.d.ts +19 -0
  17. package/dist/core/dedup.d.ts.map +1 -0
  18. package/dist/core/dedup.js +56 -0
  19. package/dist/core/dedup.js.map +1 -0
  20. package/dist/core/extractor.d.ts.map +1 -1
  21. package/dist/core/extractor.js +5 -1
  22. package/dist/core/extractor.js.map +1 -1
  23. package/dist/core/retriever/bm25.d.ts.map +1 -1
  24. package/dist/core/retriever/bm25.js +1 -0
  25. package/dist/core/retriever/bm25.js.map +1 -1
  26. package/dist/core/schema.d.ts +10 -0
  27. package/dist/core/schema.d.ts.map +1 -1
  28. package/dist/core/schema.js +9 -9
  29. package/dist/core/schema.js.map +1 -1
  30. package/dist/core/store.d.ts +2 -0
  31. package/dist/core/store.d.ts.map +1 -1
  32. package/dist/core/store.js +20 -10
  33. package/dist/core/store.js.map +1 -1
  34. package/dist/dashboard/index.html +190 -225
  35. package/dist/db/migrations/005_dedup_index.sql +6 -0
  36. package/dist/hooks/post_session.d.ts +1 -0
  37. package/dist/hooks/post_session.d.ts.map +1 -1
  38. package/dist/hooks/post_session.js +8 -1
  39. package/dist/hooks/post_session.js.map +1 -1
  40. package/dist/hooks/pre_prompt.d.ts.map +1 -1
  41. package/dist/hooks/pre_prompt.js +73 -15
  42. package/dist/hooks/pre_prompt.js.map +1 -1
  43. package/dist/mcp/server.d.ts.map +1 -1
  44. package/dist/mcp/server.js +5 -3
  45. package/dist/mcp/server.js.map +1 -1
  46. package/dist/mcp/tools.d.ts +1 -0
  47. package/dist/mcp/tools.d.ts.map +1 -1
  48. package/dist/mcp/tools.js +60 -16
  49. package/dist/mcp/tools.js.map +1 -1
  50. package/package.json +1 -1
@@ -3,11 +3,11 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Somtum v1.4.0 — Memory</title>
6
+ <title>Somtum — Memory</title>
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com" />
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
9
  <link
10
- href="https://fonts.googleapis.com/css2?family=Syne:wght@400;500;600;700;800&family=Fira+Code:wght@300;400;500&display=swap"
10
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
11
11
  rel="stylesheet"
12
12
  />
13
13
  <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
@@ -16,83 +16,62 @@
16
16
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
17
17
 
18
18
  :root {
19
- --bg: #0c0a07;
20
- --surface: #111009;
21
- --surface2: #19160e;
22
- --surface3: #201d13;
23
- --border: #2d2918;
24
- --border2: #3e3920;
25
- --text: #ede8da;
26
- --muted: #6b6350;
27
- --muted2: #9e9278;
28
- --accent: #f0a030;
29
- --accent-g: #34d399;
30
- --accent-a: #f0a030;
31
- --accent-r: #e8685a;
32
- --accent-v: #a78bfa;
33
- --accent-c: #38bdf8;
34
- --radius: 7px;
35
- --sidebar: 304px;
36
- --header: 52px;
19
+ /* GitHub-inspired dark mode palette — high contrast, WCAG AA */
20
+ --bg: #0d1117;
21
+ --surface: #161b22;
22
+ --surface2: #1c2128;
23
+ --surface3: #21262d;
24
+ --border: #30363d;
25
+ --border2: #3d444d;
26
+ --text: #e6edf3;
27
+ --muted: #7d8590;
28
+ --muted2: #9198a1;
29
+ --accent: #2f81f7;
30
+ --accent-g: #3fb950;
31
+ --accent-a: #d29922;
32
+ --accent-r: #f85149;
33
+ --accent-v: #bc8cff;
34
+ --accent-c: #39c5cf;
35
+ --radius: 6px;
36
+ --sidebar: 300px;
37
+ --header: 54px;
37
38
  }
38
39
 
39
40
  html, body {
40
41
  height: 100%; overflow: hidden;
41
42
  background: var(--bg);
42
43
  color: var(--text);
43
- font-family: 'Syne', sans-serif;
44
- font-size: 13px;
44
+ font-family: 'Inter', system-ui, sans-serif;
45
+ font-size: 14px;
45
46
  line-height: 1.5;
46
47
  -webkit-font-smoothing: antialiased;
47
48
  }
48
49
 
49
- /* Grain overlay */
50
- body::after {
51
- content: '';
52
- position: fixed;
53
- inset: 0;
54
- pointer-events: none;
55
- z-index: 9999;
56
- background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
57
- opacity: 0.022;
58
- background-size: 180px 180px;
59
- }
60
-
61
50
  /* ── Scrollbars ── */
62
- ::-webkit-scrollbar { width: 3px; height: 3px; }
51
+ ::-webkit-scrollbar { width: 5px; height: 5px; }
63
52
  ::-webkit-scrollbar-track { background: transparent; }
64
53
  ::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }
65
54
  ::-webkit-scrollbar-thumb:hover { background: var(--muted); }
66
55
 
67
- .mono { font-family: 'Fira Code', monospace; }
56
+ .mono { font-family: 'JetBrains Mono', monospace; }
68
57
 
69
58
  /* ══ HEADER ══════════════════════════════════════════════════════ */
70
59
  #header {
71
60
  height: var(--header);
72
- padding: 0 18px;
61
+ padding: 0 16px;
73
62
  display: flex;
74
63
  align-items: center;
75
64
  gap: 12px;
76
65
  flex-shrink: 0;
77
66
  background: var(--surface);
78
67
  border-bottom: 1px solid var(--border);
79
- position: relative;
80
- }
81
- /* accent line under header */
82
- #header::after {
83
- content: '';
84
- position: absolute;
85
- bottom: -1px; left: 0;
86
- width: 100%; height: 1px;
87
- background: linear-gradient(90deg, var(--accent) 0%, transparent 40%);
88
- opacity: 0.35;
89
68
  }
90
69
 
91
70
  #logo {
92
- font-size: 17px;
93
- font-weight: 800;
94
- color: var(--accent);
95
- letter-spacing: -0.02em;
71
+ font-size: 15px;
72
+ font-weight: 700;
73
+ color: var(--text);
74
+ letter-spacing: -0.01em;
96
75
  line-height: 1;
97
76
  display: flex;
98
77
  align-items: center;
@@ -101,49 +80,47 @@
101
80
  }
102
81
  #logo-mark {
103
82
  width: 28px; height: 28px;
104
- border-radius: 8px;
105
- background: linear-gradient(135deg, var(--accent) 0%, #e07820 100%);
83
+ border-radius: 7px;
84
+ background: var(--accent);
106
85
  display: flex; align-items: center; justify-content: center;
107
86
  flex-shrink: 0;
108
- box-shadow: 0 0 16px rgba(240,160,48,0.3);
109
87
  }
110
- #logo-mark svg { width: 14px; height: 14px; color: #0c0a07; }
88
+ #logo-mark svg { width: 14px; height: 14px; color: #fff; }
111
89
 
112
90
  #header-sep { width: 1px; height: 18px; background: var(--border2); }
113
91
 
114
92
  #project-label {
115
- font-size: 11px;
116
- color: var(--muted);
117
- font-family: 'Fira Code', monospace;
93
+ font-size: 12px;
94
+ color: var(--muted2);
95
+ font-family: 'JetBrains Mono', monospace;
118
96
  white-space: nowrap;
119
97
  overflow: hidden;
120
98
  text-overflow: ellipsis;
121
- max-width: 200px;
99
+ max-width: 220px;
122
100
  background: var(--surface2);
123
101
  border: 1px solid var(--border);
124
102
  padding: 3px 8px;
125
- border-radius: 4px;
103
+ border-radius: var(--radius);
126
104
  }
127
105
 
128
106
  #stat-bar { display: flex; gap: 4px; margin-left: auto; }
129
107
  .stat-pill {
130
108
  display: flex; align-items: center; gap: 6px;
131
- padding: 4px 10px;
132
- border-radius: 5px;
109
+ padding: 5px 10px;
110
+ border-radius: var(--radius);
133
111
  background: var(--surface2);
134
112
  border: 1px solid var(--border);
135
113
  cursor: default;
136
- transition: border-color 0.15s;
114
+ transition: border-color 0.12s;
137
115
  }
138
116
  .stat-pill:hover { border-color: var(--border2); }
139
117
  .stat-pill .s-lbl {
140
- font-size: 9px; font-weight: 700;
141
- text-transform: uppercase; letter-spacing: 0.1em;
118
+ font-size: 11px; font-weight: 500;
142
119
  color: var(--muted);
143
120
  }
144
121
  .stat-pill .s-val {
145
- font-family: 'Fira Code', monospace;
146
- font-size: 12.5px; font-weight: 500;
122
+ font-family: 'JetBrains Mono', monospace;
123
+ font-size: 13px; font-weight: 500;
147
124
  }
148
125
 
149
126
  /* ══ LAYOUT ══════════════════════════════════════════════════════ */
@@ -174,43 +151,42 @@
174
151
  .search-box { position: relative; }
175
152
  .search-box svg {
176
153
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
177
- width: 13px; height: 13px; color: var(--muted); pointer-events: none;
154
+ width: 14px; height: 14px; color: var(--muted); pointer-events: none;
178
155
  }
179
156
  #search-input {
180
157
  width: 100%;
181
158
  background: var(--surface);
182
- border: 1px solid var(--border2);
159
+ border: 1px solid var(--border);
183
160
  border-radius: var(--radius);
184
- padding: 7px 9px 7px 28px;
185
- font-size: 12.5px;
186
- font-family: 'Fira Code', monospace;
161
+ padding: 8px 10px 8px 30px;
162
+ font-size: 13px;
163
+ font-family: 'Inter', sans-serif;
187
164
  color: var(--text);
188
165
  outline: none;
189
- transition: border-color 0.15s, box-shadow 0.15s;
166
+ transition: border-color 0.12s, box-shadow 0.12s;
190
167
  }
191
168
  #search-input::placeholder { color: var(--muted); }
192
169
  #search-input:focus {
193
170
  border-color: var(--accent);
194
- box-shadow: 0 0 0 2px rgba(240,160,48,0.1);
171
+ box-shadow: 0 0 0 3px rgba(47,129,247,0.15);
195
172
  }
196
173
  #search-meta {
197
174
  display: flex; align-items: center; justify-content: space-between;
198
175
  }
199
- .strat-row { display: flex; gap: 3px; }
176
+ .strat-row { display: flex; gap: 3px; flex-wrap: wrap; }
200
177
  .strat-btn {
201
178
  padding: 3px 8px;
202
- font-size: 10px; font-weight: 600;
203
- border: 1px solid var(--border2); border-radius: 4px;
179
+ font-size: 11px; font-weight: 500;
180
+ border: 1px solid var(--border); border-radius: 4px;
204
181
  cursor: pointer;
205
182
  background: var(--surface2); color: var(--muted2);
206
- transition: all 0.12s;
207
- font-family: 'Syne', sans-serif;
208
- letter-spacing: 0.03em;
183
+ transition: all 0.1s;
184
+ font-family: 'Inter', sans-serif;
209
185
  }
210
- .strat-btn:hover { color: var(--text); border-color: var(--muted); }
186
+ .strat-btn:hover { color: var(--text); border-color: var(--border2); }
211
187
  .strat-btn.active {
212
- background: rgba(240,160,48,0.1);
213
- border-color: rgba(240,160,48,0.4);
188
+ background: rgba(47,129,247,0.12);
189
+ border-color: rgba(47,129,247,0.4);
214
190
  color: var(--accent);
215
191
  }
216
192
  #search-spinner { display: none; }
@@ -218,34 +194,33 @@
218
194
 
219
195
  /* Kind filters */
220
196
  #kind-filters {
221
- padding: 7px 10px;
197
+ padding: 8px 10px;
222
198
  border-bottom: 1px solid var(--border);
223
- display: flex; flex-wrap: wrap; gap: 3px;
199
+ display: flex; flex-wrap: wrap; gap: 4px;
224
200
  flex-shrink: 0;
225
201
  }
226
202
  .kind-tag {
227
- padding: 2px 8px; font-size: 10px; font-weight: 700;
228
- border-radius: 4px; border: 1px solid transparent;
229
- cursor: pointer; transition: all 0.12s;
203
+ padding: 3px 9px; font-size: 11px; font-weight: 500;
204
+ border-radius: 20px; border: 1px solid transparent;
205
+ cursor: pointer; transition: all 0.1s;
230
206
  color: var(--muted2); background: var(--surface2);
231
- letter-spacing: 0.04em;
232
207
  }
233
208
  .kind-tag:hover { color: var(--text); border-color: var(--border2); }
234
209
  .kind-tag.active { color: #fff; }
235
210
 
236
211
  /* List header */
237
212
  #list-header {
238
- padding: 5px 10px 5px;
213
+ padding: 6px 12px;
239
214
  display: flex; align-items: center; justify-content: space-between;
240
215
  border-bottom: 1px solid var(--border);
241
216
  }
242
217
  #list-header .h-label {
243
- font-size: 9px; font-weight: 700;
244
- text-transform: uppercase; letter-spacing: 0.12em;
218
+ font-size: 11px; font-weight: 600;
219
+ text-transform: uppercase; letter-spacing: 0.08em;
245
220
  color: var(--muted);
246
221
  }
247
222
  #list-count {
248
- font-size: 10px; font-family: 'Fira Code', monospace; color: var(--muted);
223
+ font-size: 11px; font-family: 'JetBrains Mono', monospace; color: var(--muted);
249
224
  }
250
225
 
251
226
  /* Memory list */
@@ -257,53 +232,49 @@
257
232
 
258
233
  /* Memory card */
259
234
  .mem-card {
260
- padding: 10px 10px 8px;
261
- border-radius: 6px;
235
+ padding: 10px 12px 8px;
236
+ border-radius: var(--radius);
262
237
  background: var(--surface2);
263
238
  border: 1px solid var(--border);
264
239
  cursor: pointer;
265
- transition: border-color 0.12s, background 0.12s, transform 0.1s;
240
+ transition: border-color 0.1s, background 0.1s;
266
241
  position: relative;
267
242
  overflow: hidden;
268
243
  }
269
- /* kind color bar on left */
270
244
  .mem-card::before {
271
245
  content: '';
272
246
  position: absolute; left: 0; top: 0; bottom: 0;
273
- width: 2.5px;
274
- border-radius: 6px 0 0 6px;
275
- background: var(--card-accent, var(--muted));
276
- opacity: 0.6;
277
- transition: opacity 0.12s;
247
+ width: 3px;
248
+ border-radius: var(--radius) 0 0 var(--radius);
249
+ background: var(--card-accent, var(--border2));
278
250
  }
279
251
  .mem-card:hover {
280
252
  border-color: var(--border2);
281
253
  background: var(--surface3);
282
254
  }
283
- .mem-card:hover::before { opacity: 1; }
284
255
  .mem-card.selected {
285
256
  border-color: var(--accent);
286
- background: rgba(240,160,48,0.04);
257
+ background: rgba(47,129,247,0.05);
287
258
  }
288
- .mem-card.selected::before { background: var(--accent); opacity: 1; }
259
+ .mem-card.selected::before { background: var(--accent); }
289
260
 
290
261
  .mc-head {
291
262
  display: flex; align-items: flex-start; gap: 6px;
292
263
  margin-bottom: 4px;
293
264
  }
294
265
  .mc-title {
295
- font-size: 12.5px; font-weight: 600; color: var(--text);
296
- line-height: 1.35; flex: 1; min-width: 0;
266
+ font-size: 13px; font-weight: 600; color: var(--text);
267
+ line-height: 1.4; flex: 1; min-width: 0;
297
268
  }
298
269
  .mc-kind {
299
270
  flex-shrink: 0;
300
- font-size: 8.5px; font-weight: 700;
301
- text-transform: uppercase; letter-spacing: 0.1em;
302
- padding: 2px 6px; border-radius: 3px;
271
+ font-size: 10px; font-weight: 600;
272
+ text-transform: uppercase; letter-spacing: 0.06em;
273
+ padding: 2px 6px; border-radius: 4px;
303
274
  }
304
275
  .mc-body {
305
- font-size: 11px; color: var(--muted2);
306
- line-height: 1.45;
276
+ font-size: 12px; color: var(--muted2);
277
+ line-height: 1.5;
307
278
  overflow: hidden;
308
279
  display: -webkit-box;
309
280
  -webkit-line-clamp: 2;
@@ -313,34 +284,38 @@
313
284
  display: flex; align-items: center; gap: 5px; margin-top: 6px;
314
285
  }
315
286
  .mc-time {
316
- font-size: 9.5px; color: var(--muted);
317
- font-family: 'Fira Code', monospace;
287
+ font-size: 11px; color: var(--muted);
288
+ font-family: 'JetBrains Mono', monospace;
318
289
  }
319
290
  .mc-tags { display: flex; gap: 3px; flex-wrap: wrap; flex: 1; }
320
291
  .mc-tag {
321
- font-size: 9px; font-weight: 600;
292
+ font-size: 10px; font-weight: 500;
322
293
  padding: 1px 5px;
323
294
  background: var(--surface3);
324
- border: 1px solid var(--border2);
295
+ border: 1px solid var(--border);
325
296
  border-radius: 3px; color: var(--muted);
326
- font-family: 'Fira Code', monospace;
297
+ font-family: 'JetBrains Mono', monospace;
327
298
  }
328
299
  .mc-forget {
329
300
  display: none;
330
301
  width: 20px; height: 20px;
331
302
  align-items: center; justify-content: center;
332
303
  border-radius: 4px; cursor: pointer;
333
- background: rgba(232,104,90,0.08);
334
- border: 1px solid rgba(232,104,90,0.2);
335
- color: var(--accent-r);
336
- font-size: 13px; font-weight: 300;
337
- transition: background 0.12s;
304
+ background: transparent;
305
+ border: 1px solid transparent;
306
+ color: var(--muted2);
307
+ font-size: 14px; font-weight: 400;
308
+ transition: all 0.1s;
338
309
  flex-shrink: 0;
339
310
  position: absolute; top: 7px; right: 7px;
340
311
  line-height: 1;
341
312
  }
342
313
  .mem-card:hover .mc-forget { display: flex; }
343
- .mc-forget:hover { background: rgba(232,104,90,0.2); }
314
+ .mc-forget:hover {
315
+ background: rgba(248,81,73,0.15);
316
+ border-color: rgba(248,81,73,0.3);
317
+ color: var(--accent-r);
318
+ }
344
319
 
345
320
  /* ══ MAIN ══════════════════════════════════════════════════════════ */
346
321
  #main {
@@ -350,8 +325,8 @@
350
325
 
351
326
  /* Tab bar */
352
327
  #tab-bar {
353
- height: 40px;
354
- padding: 0 14px;
328
+ height: 42px;
329
+ padding: 0 16px;
355
330
  display: flex; align-items: center; flex-shrink: 0;
356
331
  background: var(--surface);
357
332
  border-bottom: 1px solid var(--border);
@@ -360,15 +335,14 @@
360
335
  .tab-btn {
361
336
  padding: 0 14px;
362
337
  height: 100%;
363
- font-size: 11.5px; font-weight: 600;
338
+ font-size: 13px; font-weight: 500;
364
339
  color: var(--muted2);
365
340
  border: none;
366
341
  background: none;
367
342
  cursor: pointer;
368
- transition: color 0.12s;
343
+ transition: color 0.1s;
369
344
  position: relative;
370
- font-family: 'Syne', sans-serif;
371
- letter-spacing: 0.04em;
345
+ font-family: 'Inter', sans-serif;
372
346
  }
373
347
  .tab-btn::after {
374
348
  content: '';
@@ -378,21 +352,20 @@
378
352
  background: var(--accent);
379
353
  border-radius: 2px 2px 0 0;
380
354
  opacity: 0;
381
- transition: opacity 0.15s;
355
+ transition: opacity 0.12s;
382
356
  }
383
357
  .tab-btn:hover { color: var(--text); }
384
- .tab-btn.active { color: var(--accent); }
358
+ .tab-btn.active { color: var(--text); }
385
359
  .tab-btn.active::after { opacity: 1; }
386
360
  #tab-hint {
387
361
  margin-left: auto;
388
- font-size: 10px; color: var(--muted);
389
- font-family: 'Fira Code', monospace;
390
- padding-right: 4px;
362
+ font-size: 11px; color: var(--muted);
363
+ font-family: 'JetBrains Mono', monospace;
391
364
  }
392
365
 
393
366
  /* Tab panes */
394
367
  #tab-graph { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
395
- #tab-analytics { display: none; flex: 1; overflow-y: auto; padding: 14px; }
368
+ #tab-analytics { display: none; flex: 1; overflow-y: auto; padding: 16px; }
396
369
 
397
370
  /* Graph */
398
371
  #graph-container {
@@ -400,21 +373,10 @@
400
373
  margin: 10px;
401
374
  border: 1px solid var(--border);
402
375
  border-radius: var(--radius);
403
- background: #09080500;
376
+ background: var(--surface2);
404
377
  overflow: hidden;
405
378
  position: relative;
406
379
  }
407
- /* ambient glow behind graph */
408
- #graph-container::before {
409
- content: '';
410
- position: absolute;
411
- top: 50%; left: 50%;
412
- width: 400px; height: 300px;
413
- transform: translate(-50%, -50%);
414
- background: radial-gradient(ellipse, rgba(240,160,48,0.04) 0%, transparent 70%);
415
- pointer-events: none;
416
- z-index: 0;
417
- }
418
380
 
419
381
  /* Detail panel */
420
382
  #detail-panel {
@@ -423,10 +385,10 @@
423
385
  background: var(--surface);
424
386
  overflow-y: auto; flex-shrink: 0;
425
387
  max-height: 36vh;
426
- animation: slideUp 0.18s ease forwards;
388
+ animation: slideUp 0.15s ease forwards;
427
389
  }
428
390
  @keyframes slideUp {
429
- from { opacity: 0; transform: translateY(6px); }
391
+ from { opacity: 0; transform: translateY(4px); }
430
392
  to { opacity: 1; transform: translateY(0); }
431
393
  }
432
394
  #detail-inner { padding: 16px 20px; }
@@ -434,44 +396,48 @@
434
396
  display: flex; align-items: flex-start; gap: 10px; margin-bottom: 10px;
435
397
  }
436
398
  .detail-title {
437
- font-size: 15px; font-weight: 700; color: var(--text);
438
- flex: 1; line-height: 1.3;
399
+ font-size: 15px; font-weight: 600; color: var(--text);
400
+ flex: 1; line-height: 1.4;
439
401
  }
440
402
  .detail-meta {
441
403
  display: flex; gap: 16px; margin-bottom: 12px;
442
- font-size: 10.5px; color: var(--muted);
443
- font-family: 'Fira Code', monospace;
404
+ font-size: 11px; color: var(--muted);
405
+ font-family: 'JetBrains Mono', monospace;
444
406
  }
445
407
  .detail-body {
446
- font-size: 12.5px; color: var(--muted2);
408
+ font-size: 13px; color: var(--muted2);
447
409
  line-height: 1.7; white-space: pre-wrap; word-break: break-word;
448
410
  margin-bottom: 12px;
449
411
  }
450
412
  .detail-chips { display: flex; flex-wrap: wrap; gap: 5px; }
451
413
  .detail-chip {
452
- font-size: 10px; font-weight: 500;
414
+ font-size: 11px; font-weight: 500;
453
415
  padding: 2px 8px; border-radius: 4px;
454
- background: var(--surface2); border: 1px solid var(--border2);
416
+ background: var(--surface2); border: 1px solid var(--border);
455
417
  color: var(--muted2);
456
- font-family: 'Fira Code', monospace;
418
+ font-family: 'JetBrains Mono', monospace;
457
419
  }
458
420
  .detail-chip.file {
459
- color: var(--accent-c); border-color: rgba(56,189,248,0.3);
460
- background: rgba(56,189,248,0.06);
421
+ color: var(--accent-c); border-color: rgba(57,197,207,0.3);
422
+ background: rgba(57,197,207,0.07);
461
423
  }
462
424
  .detail-close {
463
- width: 24px; height: 24px; border-radius: 5px;
425
+ width: 24px; height: 24px; border-radius: var(--radius);
464
426
  flex-shrink: 0;
465
427
  display: flex; align-items: center; justify-content: center;
466
428
  background: var(--surface2); border: 1px solid var(--border);
467
429
  cursor: pointer; color: var(--muted2);
468
- transition: color 0.12s, border-color 0.12s;
430
+ transition: color 0.1s, border-color 0.1s, background 0.1s;
431
+ }
432
+ .detail-close:hover {
433
+ color: var(--text);
434
+ border-color: var(--border2);
435
+ background: var(--surface3);
469
436
  }
470
- .detail-close:hover { color: var(--text); border-color: var(--border2); }
471
437
 
472
438
  /* Analytics */
473
439
  .a-grid {
474
- display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
440
+ display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
475
441
  }
476
442
  @media (max-width: 900px) { .a-grid { grid-template-columns: 1fr; } }
477
443
  .a-card {
@@ -481,48 +447,48 @@
481
447
  padding: 16px;
482
448
  }
483
449
  .a-title {
484
- font-size: 9px; font-weight: 700;
485
- text-transform: uppercase; letter-spacing: 0.14em;
450
+ font-size: 11px; font-weight: 600;
451
+ text-transform: uppercase; letter-spacing: 0.08em;
486
452
  color: var(--muted); margin-bottom: 14px;
487
453
  }
488
454
  .bar-row {
489
- display: flex; align-items: center; gap: 8px; margin-bottom: 9px;
455
+ display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
490
456
  }
491
457
  .bar-label {
492
- font-size: 11.5px; font-weight: 600;
493
- width: 100px; flex-shrink: 0;
458
+ font-size: 12px; font-weight: 500;
459
+ width: 100px; flex-shrink: 0; color: var(--text);
494
460
  }
495
461
  .bar-track {
496
- flex: 1; height: 3px;
462
+ flex: 1; height: 4px;
497
463
  background: var(--surface3); border-radius: 2px; overflow: hidden;
498
464
  }
499
465
  .bar-fill {
500
466
  height: 100%; border-radius: 2px;
501
- width: 0; transition: width 0.7s cubic-bezier(0.16,1,0.3,1);
467
+ width: 0; transition: width 0.6s cubic-bezier(0.16,1,0.3,1);
502
468
  }
503
469
  .bar-count {
504
- font-size: 11px; font-family: 'Fira Code', monospace;
470
+ font-size: 12px; font-family: 'JetBrains Mono', monospace;
505
471
  color: var(--muted2); width: 36px; text-align: right; flex-shrink: 0;
506
472
  }
507
473
  .cache-stat {
508
474
  display: flex; justify-content: space-between; align-items: center;
509
- padding: 8px 0; border-bottom: 1px solid var(--border);
475
+ padding: 9px 0; border-bottom: 1px solid var(--border);
510
476
  }
511
477
  .cache-stat:last-child { border-bottom: none; }
512
- .cache-stat-lbl { font-size: 12px; color: var(--muted2); }
513
- .cache-stat-val { font-family: 'Fira Code', monospace; font-size: 13px; font-weight: 500; }
478
+ .cache-stat-lbl { font-size: 13px; color: var(--muted2); }
479
+ .cache-stat-val { font-family: 'JetBrains Mono', monospace; font-size: 13px; font-weight: 500; }
514
480
  .file-row {
515
481
  display: flex; align-items: center; gap: 8px;
516
- padding: 6px 0; border-bottom: 1px solid var(--border);
482
+ padding: 7px 0; border-bottom: 1px solid var(--border);
517
483
  }
518
484
  .file-row:last-child { border-bottom: none; }
519
485
  .file-name {
520
- font-size: 11px; font-family: 'Fira Code', monospace;
486
+ font-size: 12px; font-family: 'JetBrains Mono', monospace;
521
487
  color: var(--text); flex: 1;
522
488
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
523
489
  }
524
490
  .file-count {
525
- font-size: 11px; font-family: 'Fira Code', monospace;
491
+ font-size: 12px; font-family: 'JetBrains Mono', monospace;
526
492
  color: var(--muted2); flex-shrink: 0;
527
493
  }
528
494
 
@@ -532,61 +498,61 @@
532
498
  justify-content: center; gap: 8px;
533
499
  padding: 48px 24px; color: var(--muted); text-align: center;
534
500
  }
535
- .empty-icon { opacity: 0.2; margin-bottom: 4px; }
536
- .empty-title { font-size: 13px; font-weight: 600; color: var(--muted2); }
501
+ .empty-icon { opacity: 0.25; margin-bottom: 4px; }
502
+ .empty-title { font-size: 14px; font-weight: 600; color: var(--muted2); }
537
503
  .empty-sub {
538
- font-size: 11.5px; color: var(--muted);
539
- max-width: 220px; line-height: 1.55;
504
+ font-size: 12px; color: var(--muted);
505
+ max-width: 240px; line-height: 1.6;
540
506
  }
541
507
 
542
508
  /* Skeleton */
543
509
  .skel {
544
- background: var(--surface2); border-radius: 5px;
545
- animation: shimmer 1.8s ease-in-out infinite;
510
+ background: var(--surface2); border-radius: var(--radius);
511
+ animation: shimmer 1.6s ease-in-out infinite;
546
512
  }
547
513
 
548
514
  /* ── Animations ── */
549
515
  @keyframes spin { to { transform: rotate(360deg); } }
550
516
  @keyframes shimmer {
551
- 0%, 100% { opacity: 0.35; }
552
- 50% { opacity: 0.6; }
517
+ 0%, 100% { opacity: 0.3; }
518
+ 50% { opacity: 0.55; }
553
519
  }
554
520
  @keyframes fadeIn {
555
- from { opacity: 0; transform: translateY(3px); }
521
+ from { opacity: 0; transform: translateY(2px); }
556
522
  to { opacity: 1; transform: translateY(0); }
557
523
  }
558
- .fade-in { animation: fadeIn 0.14s ease forwards; }
524
+ .fade-in { animation: fadeIn 0.12s ease forwards; }
559
525
 
560
526
  /* ── Kind colour map ── */
561
- .kind-decision { background: rgba(79,141,255,0.12); color: #6ba3ff; }
562
- .kind-learning { background: rgba(167,139,250,0.12); color: #a78bfa; }
563
- .kind-bugfix { background: rgba(232,104,90,0.12); color: #e8685a; }
564
- .kind-command { background: rgba(240,160,48,0.12); color: #f0a030; }
565
- .kind-file_summary { background: rgba(56,189,248,0.1); color: #38bdf8; }
566
- .kind-other { background: rgba(107,99,80,0.15); color: #9e9278; }
567
-
568
- .kf-decision { border-color: rgba(79,141,255,0.3); background: rgba(79,141,255,0.07); color: #6ba3ff; }
569
- .kf-learning { border-color: rgba(167,139,250,0.3); background: rgba(167,139,250,0.07); color: #a78bfa; }
570
- .kf-bugfix { border-color: rgba(232,104,90,0.3); background: rgba(232,104,90,0.07); color: #e8685a; }
571
- .kf-command { border-color: rgba(240,160,48,0.3); background: rgba(240,160,48,0.07); color: #f0a030; }
572
- .kf-file_summary { border-color: rgba(56,189,248,0.3); background: rgba(56,189,248,0.06); color: #38bdf8; }
573
- .kf-other { border-color: rgba(107,99,80,0.3); background: rgba(107,99,80,0.07); color: #9e9278; }
574
- .kf-all { border-color: rgba(240,160,48,0.35); background: rgba(240,160,48,0.08); color: #f0a030; }
527
+ .kind-decision { background: rgba(47,129,247,0.12); color: #58a6ff; }
528
+ .kind-learning { background: rgba(188,140,255,0.12); color: #bc8cff; }
529
+ .kind-bugfix { background: rgba(248,81,73,0.12); color: #f85149; }
530
+ .kind-command { background: rgba(210,153,34,0.12); color: #d29922; }
531
+ .kind-file_summary { background: rgba(57,197,207,0.10); color: #39c5cf; }
532
+ .kind-other { background: rgba(125,133,144,0.15); color: #9198a1; }
533
+
534
+ .kf-decision { border-color: rgba(47,129,247,0.35); background: rgba(47,129,247,0.08); color: #58a6ff; }
535
+ .kf-learning { border-color: rgba(188,140,255,0.35); background: rgba(188,140,255,0.08); color: #bc8cff; }
536
+ .kf-bugfix { border-color: rgba(248,81,73,0.35); background: rgba(248,81,73,0.08); color: #f85149; }
537
+ .kf-command { border-color: rgba(210,153,34,0.35); background: rgba(210,153,34,0.08); color: #d29922; }
538
+ .kf-file_summary { border-color: rgba(57,197,207,0.35); background: rgba(57,197,207,0.07); color: #39c5cf; }
539
+ .kf-other { border-color: rgba(125,133,144,0.3); background: rgba(125,133,144,0.07); color: #9198a1; }
540
+ .kf-all { border-color: rgba(47,129,247,0.35); background: rgba(47,129,247,0.08); color: #58a6ff; }
575
541
 
576
542
  /* Scope badge on memory cards */
577
543
  .mc-scope {
578
- font-size: 8px; font-weight: 700;
579
- text-transform: uppercase; letter-spacing: 0.08em;
544
+ font-size: 10px; font-weight: 500;
545
+ text-transform: uppercase; letter-spacing: 0.05em;
580
546
  padding: 1px 5px; border-radius: 3px;
581
- background: rgba(167,139,250,0.12);
582
- color: #a78bfa;
583
- border: 1px solid rgba(167,139,250,0.25);
547
+ background: rgba(188,140,255,0.1);
548
+ color: #bc8cff;
549
+ border: 1px solid rgba(188,140,255,0.25);
584
550
  flex-shrink: 0;
585
551
  }
586
552
  .mc-scope.global {
587
- background: rgba(240,160,48,0.12);
588
- color: #f0a030;
589
- border-color: rgba(240,160,48,0.25);
553
+ background: rgba(210,153,34,0.1);
554
+ color: #d29922;
555
+ border-color: rgba(210,153,34,0.3);
590
556
  }
591
557
  </style>
592
558
  </head>
@@ -610,7 +576,7 @@
610
576
  </div>
611
577
  <div class="stat-pill">
612
578
  <span class="s-lbl">Saved</span>
613
- <span id="s-saved" class="s-val" style="color:var(--accent)">—</span>
579
+ <span id="s-saved" class="s-val" style="color:var(--accent-g)">—</span>
614
580
  </div>
615
581
  <div class="stat-pill">
616
582
  <span class="s-lbl">Spent</span>
@@ -641,7 +607,7 @@
641
607
  <div id="search-meta">
642
608
  <div class="strat-row" id="strategy-btns"></div>
643
609
  <div id="search-spinner">
644
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2.5">
610
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2.5">
645
611
  <path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>
646
612
  </svg>
647
613
  </div>
@@ -656,9 +622,9 @@
656
622
  </div>
657
623
 
658
624
  <div id="memory-list">
659
- <div class="skel" style="height:66px;border-radius:6px"></div>
660
- <div class="skel" style="height:54px;border-radius:6px;margin-top:2px"></div>
661
- <div class="skel" style="height:70px;border-radius:6px;margin-top:2px"></div>
625
+ <div class="skel" style="height:68px;border-radius:6px"></div>
626
+ <div class="skel" style="height:56px;border-radius:6px;margin-top:2px"></div>
627
+ <div class="skel" style="height:72px;border-radius:6px;margin-top:2px"></div>
662
628
  </div>
663
629
  </aside>
664
630
 
@@ -701,12 +667,12 @@
701
667
 
702
668
  // ─── Kind colours (vis-network nodes) ────────────────────────────────────────
703
669
  const KIND_COLOR = {
704
- decision: { bg: '#6ba3ff', border: '#4f8dff' },
705
- learning: { bg: '#a78bfa', border: '#8b6fe8' },
706
- bugfix: { bg: '#e8685a', border: '#d04838' },
707
- command: { bg: '#f0a030', border: '#d48020' },
708
- file_summary: { bg: '#38bdf8', border: '#1aa8e8' },
709
- other: { bg: '#6b6350', border: '#504c3c' },
670
+ decision: { bg: '#58a6ff', border: '#2f81f7' },
671
+ learning: { bg: '#bc8cff', border: '#9a6fd8' },
672
+ bugfix: { bg: '#f85149', border: '#da3633' },
673
+ command: { bg: '#d29922', border: '#b08800' },
674
+ file_summary: { bg: '#39c5cf', border: '#1aafba' },
675
+ other: { bg: '#7d8590', border: '#656d76' },
710
676
  };
711
677
 
712
678
  // ─── Utilities ────────────────────────────────────────────────────────────────
@@ -853,7 +819,6 @@
853
819
 
854
820
  const kc = KIND_COLOR[m.kind] || KIND_COLOR.other;
855
821
  card.style.setProperty('--card-accent', kc.bg);
856
- if (m.id === S.selectedId) card.style.borderLeftColor = kc.bg;
857
822
 
858
823
  const forget = h('div', {
859
824
  class: 'mc-forget', title: 'Forget this memory',
@@ -1003,14 +968,14 @@
1003
968
  const kc = KIND_COLOR[n.kind] || KIND_COLOR.other;
1004
969
  return {
1005
970
  id: n.id, label: n.label, title: n.title,
1006
- color: { background: kc.bg, border: kc.border, highlight: { background: kc.bg, border: '#fff' } },
1007
- font: { color: '#ede8da', size: 11, face: 'Syne' },
971
+ color: { background: kc.bg, border: kc.border, highlight: { background: kc.bg, border: '#ffffff' } },
972
+ font: { color: '#e6edf3', size: 12, face: 'Inter' },
1008
973
  shape: 'dot', size: 10, borderWidth: 1.5,
1009
974
  };
1010
975
  }));
1011
976
  const vEdges = new vis.DataSet(edges.map((e, i) => ({
1012
977
  id: i, from: e.from, to: e.to,
1013
- color: { color: '#2d2918', highlight: '#f0a030', opacity: 0.9 },
978
+ color: { color: '#30363d', highlight: '#2f81f7', opacity: 0.9 },
1014
979
  width: 1, smooth: { type: 'dynamic' },
1015
980
  })));
1016
981
  S.network = new vis.Network(
@@ -1120,7 +1085,7 @@
1120
1085
  ['Total', mems.length, 'var(--text)'],
1121
1086
  ['Stale (>30d)', staleCount, 'var(--accent-r)'],
1122
1087
  ['Workspace', workspaceCount, 'var(--accent-v)'],
1123
- ['Global', globalCount, 'var(--accent)'],
1088
+ ['Global', globalCount, 'var(--accent-a)'],
1124
1089
  ].forEach(([lbl, val, color]) => {
1125
1090
  healthCard.append(h('div', { class: 'cache-stat' },
1126
1091
  h('span', { class: 'cache-stat-lbl' }, lbl),