egregore-artifacts 0.1.0 → 0.3.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/lib/registry.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import React from 'react';
3
3
  import { defineRegistry } from '@json-render/react';
4
4
  import { catalog } from './catalog.js';
5
- import { colors, fonts } from './tokens.js';
5
+ import { fonts } from './tokens.js';
6
6
  import { renderMarkdown } from './markdown.js';
7
7
 
8
8
  const h = React.createElement;
@@ -70,12 +70,12 @@ export const { registry, handlers, executeAction } = defineRegistry(catalog, {
70
70
  h('div', {
71
71
  key: i,
72
72
  style: {
73
- background: 'white', border: `1px solid ${colors.border}`,
73
+ background: 'var(--surface)', border: '1px solid var(--border)',
74
74
  borderRadius: '12px', padding: '1.25rem', textAlign: 'center',
75
75
  },
76
76
  },
77
- h('div', { style: { fontSize: '28px', fontFamily: fonts.serif, fontWeight: 400, color: colors.black, lineHeight: 1.2 } }, m.value),
78
- h('div', { style: { fontSize: '12px', fontFamily: fonts.mono, color: colors.muted, marginTop: '4px', textTransform: 'uppercase', letterSpacing: '0.04em' } }, m.label),
77
+ h('div', { style: { fontSize: '28px', fontFamily: fonts.serif, fontWeight: 400, color: 'var(--black)', lineHeight: 1.2 } }, m.value),
78
+ h('div', { style: { fontSize: '12px', fontFamily: fonts.mono, color: 'var(--muted)', marginTop: '4px', textTransform: 'uppercase', letterSpacing: '0.04em' } }, m.label),
79
79
  )
80
80
  ),
81
81
  ),
@@ -97,7 +97,7 @@ export const { registry, handlers, executeAction } = defineRegistry(catalog, {
97
97
  h('span', { className: 'eg-artifact-date' }, a.date),
98
98
  h('span', { className: 'eg-artifact-type' }, a.type),
99
99
  h('span', { className: 'eg-artifact-title' }, a.title),
100
- a.author && h('span', { style: { color: colors.muted, fontSize: '13px', fontFamily: fonts.mono } }, `(${a.author})`),
100
+ a.author && h('span', { style: { color: 'var(--muted)', fontSize: '13px', fontFamily: fonts.mono } }, `(${a.author})`),
101
101
  )
102
102
  ),
103
103
  ),
@@ -108,7 +108,7 @@ export const { registry, handlers, executeAction } = defineRegistry(catalog, {
108
108
  h('div', { key: i, className: 'eg-contributor' },
109
109
  h('span', { className: 'eg-contributor-avatar' }, (p.name || '?')[0].toUpperCase()),
110
110
  h('span', null, p.name),
111
- p.role && h('span', { style: { color: colors.muted, fontSize: '12px' } }, p.role),
111
+ p.role && h('span', { style: { color: 'var(--muted)', fontSize: '12px' } }, p.role),
112
112
  )
113
113
  ),
114
114
  ),
@@ -121,8 +121,8 @@ export const { registry, handlers, executeAction } = defineRegistry(catalog, {
121
121
  NumberedSteps: ({ props }) =>
122
122
  h('ol', { style: { listStyle: 'none', padding: 0 } },
123
123
  ...props.steps.map((step, i) =>
124
- h('li', { key: i, style: { display: 'flex', gap: '12px', padding: '8px 0', borderBottom: i < props.steps.length - 1 ? '1px solid rgba(224, 216, 204, 0.5)' : 'none', fontSize: '15px', lineHeight: 1.5 } },
125
- h('span', { style: { flexShrink: 0, width: '24px', height: '24px', borderRadius: '50%', background: colors.terracotta, color: colors.cream, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '12px', fontFamily: fonts.mono, fontWeight: 600 } }, String(i + 1)),
124
+ h('li', { key: i, style: { display: 'flex', gap: '12px', padding: '8px 0', borderBottom: i < props.steps.length - 1 ? '1px solid var(--hairline)' : 'none', fontSize: '15px', lineHeight: 1.5 } },
125
+ h('span', { style: { flexShrink: 0, width: '24px', height: '24px', borderRadius: '50%', background: 'var(--terracotta)', color: 'var(--cream)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '12px', fontFamily: fonts.mono, fontWeight: 600 } }, String(i + 1)),
126
126
  h('span', null, step),
127
127
  )
128
128
  ),
@@ -131,11 +131,11 @@ export const { registry, handlers, executeAction } = defineRegistry(catalog, {
131
131
  SessionList: ({ props }) =>
132
132
  h('div', null,
133
133
  ...props.sessions.map((s, i) =>
134
- h('div', { key: i, style: { display: 'flex', alignItems: 'baseline', gap: '12px', padding: '6px 0', borderBottom: '1px solid rgba(224, 216, 204, 0.5)', fontSize: '14px' } },
135
- h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: colors.muted, minWidth: '72px', flexShrink: 0 } }, s.date),
136
- s.by && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: colors.blueMuted, background: 'rgba(123, 157, 183, 0.1)', padding: '1px 6px', borderRadius: '3px', flexShrink: 0 } }, s.by),
137
- h('span', { style: { color: colors.black, flex: 1 } }, s.topic),
138
- s.handedTo && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: colors.terracotta } }, `→ ${s.handedTo}`),
134
+ h('div', { key: i, style: { display: 'flex', alignItems: 'baseline', gap: '12px', padding: '6px 0', borderBottom: '1px solid var(--hairline)', fontSize: '14px' } },
135
+ h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: 'var(--muted)', minWidth: '72px', flexShrink: 0 } }, s.date),
136
+ s.by && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: 'var(--blue-muted)', background: 'var(--blue-chip)', padding: '1px 6px', borderRadius: '3px', flexShrink: 0 } }, s.by),
137
+ h('span', { style: { color: 'var(--black)', flex: 1 } }, s.topic),
138
+ s.handedTo && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: 'var(--terracotta)' } }, `→ ${s.handedTo}`),
139
139
  )
140
140
  ),
141
141
  ),
@@ -146,9 +146,9 @@ export const { registry, handlers, executeAction } = defineRegistry(catalog, {
146
146
  Callout: ({ props }) =>
147
147
  h('div', {
148
148
  style: {
149
- background: 'rgba(212, 135, 90, 0.06)', border: '1px solid rgba(212, 135, 90, 0.15)',
149
+ background: 'var(--terracotta-soft)', border: '1px solid var(--terracotta-hair)',
150
150
  borderRadius: '12px', padding: '1.25rem 1.5rem', marginBottom: '1.5rem',
151
- fontSize: '15px', lineHeight: 1.6, color: colors.dark,
151
+ fontSize: '15px', lineHeight: 1.6, color: 'var(--dark)',
152
152
  },
153
153
  }, renderMarkdown(props.text)),
154
154
 
package/lib/shell.js CHANGED
@@ -7,7 +7,7 @@ function escapeHtml(str) {
7
7
 
8
8
  export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artifact' } = {}) {
9
9
  return `<!DOCTYPE html>
10
- <html lang="en">
10
+ <html lang="en" data-theme="light">
11
11
  <head>
12
12
  <meta charset="UTF-8">
13
13
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -32,6 +32,41 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
32
32
  --font-serif: ${fonts.serif};
33
33
  --font-sans: ${fonts.sans};
34
34
  --font-mono: ${fonts.mono};
35
+ /* Semi-transparent fills used by templates (inline styles).
36
+ Defined as tokens so dark mode can override them. */
37
+ --surface: #ffffff;
38
+ --hairline: rgba(224, 216, 204, 0.5);
39
+ --subtle-fill: rgba(59, 45, 33, 0.06);
40
+ --terracotta-soft: rgba(212, 135, 90, 0.06);
41
+ --terracotta-hair: rgba(212, 135, 90, 0.15);
42
+ --terracotta-chip: rgba(212, 135, 90, 0.1);
43
+ --blue-chip: rgba(123, 157, 183, 0.1);
44
+ --neutral-chip: rgba(0, 0, 0, 0.04);
45
+ --success-bg: #e8f5e9;
46
+ --success-fg: #2e7d32;
47
+ --green-p1: #2A7B5B;
48
+ }
49
+
50
+ /* Dark mode overrides */
51
+ [data-theme="dark"] {
52
+ --cream: ${colors.darkBg};
53
+ --black: ${colors.darkText};
54
+ --dark: ${colors.darkTextSoft};
55
+ --border: ${colors.darkBorder};
56
+ --muted: ${colors.darkTextMuted};
57
+ --warm-gray: ${colors.darkTextDim};
58
+ --terminal-bg: ${colors.darkBgCode};
59
+ --surface: ${colors.darkBgCard};
60
+ --hairline: rgba(255, 255, 255, 0.08);
61
+ --subtle-fill: rgba(255, 255, 255, 0.04);
62
+ --terracotta-soft: rgba(212, 135, 90, 0.08);
63
+ --terracotta-hair: rgba(212, 135, 90, 0.22);
64
+ --terracotta-chip: rgba(212, 135, 90, 0.14);
65
+ --blue-chip: rgba(123, 157, 183, 0.16);
66
+ --neutral-chip: rgba(255, 255, 255, 0.06);
67
+ --success-bg: rgba(107, 191, 107, 0.12);
68
+ --success-fg: #9ed9a0;
69
+ --green-p1: #6BBF6B;
35
70
  }
36
71
 
37
72
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
@@ -47,6 +82,7 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
47
82
  }
48
83
 
49
84
  ::selection { background: var(--terracotta); color: var(--cream); }
85
+ [data-theme="dark"] ::selection { color: ${colors.darkBg}; }
50
86
 
51
87
  /* Layout */
52
88
  .eg-artifact {
@@ -143,12 +179,13 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
143
179
 
144
180
  /* Card */
145
181
  .eg-card {
146
- background: white;
182
+ background: var(--card-bg, white);
147
183
  border: 1px solid var(--border);
148
184
  border-radius: 12px;
149
185
  padding: 1.5rem;
150
186
  margin-bottom: 1.25rem;
151
187
  }
188
+ [data-theme="dark"] .eg-card { --card-bg: ${colors.darkBgCard}; }
152
189
  .eg-card-title {
153
190
  font-family: var(--font-mono);
154
191
  font-size: 12px;
@@ -183,7 +220,7 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
183
220
  align-items: flex-start;
184
221
  gap: 10px;
185
222
  padding: 8px 0;
186
- border-bottom: 1px solid rgba(224, 216, 204, 0.5);
223
+ border-bottom: 1px solid var(--border);
187
224
  font-size: 15px;
188
225
  line-height: 1.5;
189
226
  }
@@ -212,7 +249,7 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
212
249
  display: flex;
213
250
  gap: 12px;
214
251
  padding: 8px 0;
215
- border-bottom: 1px solid rgba(224, 216, 204, 0.5);
252
+ border-bottom: 1px solid var(--border);
216
253
  font-size: 14px;
217
254
  }
218
255
  .eg-artifact-item:last-child { border-bottom: none; }
@@ -246,10 +283,11 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
246
283
  align-items: center;
247
284
  gap: 8px;
248
285
  padding: 6px 12px;
249
- background: rgba(59, 45, 33, 0.04);
286
+ background: var(--subtle-bg, rgba(59, 45, 33, 0.04));
250
287
  border-radius: 50px;
251
288
  font-size: 14px;
252
289
  }
290
+ [data-theme="dark"] .eg-contributor { --subtle-bg: rgba(212, 135, 90, 0.06); }
253
291
  .eg-contributor-avatar {
254
292
  width: 28px;
255
293
  height: 28px;
@@ -292,10 +330,11 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
292
330
  .eg-code {
293
331
  font-family: var(--font-mono);
294
332
  font-size: 13px;
295
- background: rgba(59, 45, 33, 0.06);
333
+ background: var(--code-bg, rgba(59, 45, 33, 0.06));
296
334
  padding: 2px 6px;
297
335
  border-radius: 4px;
298
336
  }
337
+ [data-theme="dark"] .eg-code { --code-bg: rgba(212, 135, 90, 0.08); color: var(--terracotta); }
299
338
 
300
339
  /* Footer */
301
340
  .eg-footer {
@@ -316,11 +355,65 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
316
355
  }
317
356
  .eg-footer-sigil { color: var(--terracotta); }
318
357
 
319
- /* Print */
358
+ /* Theme toggle */
359
+ .eg-theme-toggle {
360
+ position: fixed;
361
+ top: 1.25rem;
362
+ right: 1.25rem;
363
+ width: 36px;
364
+ height: 36px;
365
+ border-radius: 50px;
366
+ border: 1px solid var(--border);
367
+ background: var(--card-bg, white);
368
+ cursor: pointer;
369
+ display: flex;
370
+ align-items: center;
371
+ justify-content: center;
372
+ font-size: 15px;
373
+ line-height: 1;
374
+ transition: background 0.2s, border-color 0.2s, width 0.2s;
375
+ z-index: 100;
376
+ padding: 0;
377
+ gap: 6px;
378
+ overflow: hidden;
379
+ }
380
+ .eg-theme-toggle:hover {
381
+ border-color: var(--terracotta);
382
+ width: 92px;
383
+ padding: 0 12px;
384
+ }
385
+ [data-theme="dark"] .eg-theme-toggle { --card-bg: ${colors.darkBgCard}; }
386
+ .eg-theme-toggle .eg-t-icon { flex-shrink: 0; }
387
+ .eg-theme-toggle .eg-t-label {
388
+ font-family: var(--font-mono);
389
+ font-size: 10px;
390
+ letter-spacing: 0.04em;
391
+ color: var(--muted);
392
+ white-space: nowrap;
393
+ width: 0;
394
+ overflow: hidden;
395
+ transition: width 0.2s, opacity 0.2s;
396
+ opacity: 0;
397
+ }
398
+ .eg-theme-toggle:hover .eg-t-label { width: 32px; opacity: 1; }
399
+
400
+ /* Print — force light palette regardless of active theme */
320
401
  @media print {
321
- body { background: white; }
402
+ :root, [data-theme="dark"] {
403
+ --cream: #ffffff;
404
+ --black: #16100B;
405
+ --dark: #2A2A2A;
406
+ --border: #E0D8CC;
407
+ --muted: #8a8578;
408
+ --surface: #ffffff;
409
+ --card-bg: #ffffff;
410
+ --hairline: rgba(224, 216, 204, 0.6);
411
+ --subtle-fill: rgba(59, 45, 33, 0.04);
412
+ }
413
+ body { background: white; color: #16100B; }
322
414
  .eg-artifact { padding: 1rem; max-width: none; }
323
- .eg-card { break-inside: avoid; }
415
+ .eg-card { break-inside: avoid; background: #ffffff; }
416
+ .eg-theme-toggle { display: none; }
324
417
  }
325
418
 
326
419
  /* Mobile */
@@ -329,10 +422,68 @@ export function htmlShell(bodyHtml, { title = 'Egregore Artifact', type = 'artif
329
422
  .eg-title { font-size: 28px; }
330
423
  .eg-section-title { font-size: 20px; }
331
424
  .eg-meta-row { gap: 10px; }
425
+ .eg-theme-toggle { top: 0.75rem; right: 0.75rem; width: 32px; height: 32px; font-size: 14px; }
332
426
  }
333
427
  </style>
428
+ <script>
429
+ // Theme engine: light / auto / dark
430
+ // Auto uses OS preference (prefers-color-scheme) + local clock fallback.
431
+ // No geolocation, no permissions, no API calls.
432
+ (function() {
433
+ var MODES = ['light', 'auto', 'dark'];
434
+ var ICONS = ['\\u2600', '\\u25D0', '\\u263D'];
435
+ var LABELS = ['light', 'auto', 'dark'];
436
+
437
+ function resolveAuto() {
438
+ // OS-level dark mode (follows sunset schedule if enabled)
439
+ if (window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark';
440
+ if (window.matchMedia('(prefers-color-scheme: light)').matches) return 'light';
441
+ // Fallback: local clock — dark between 19:00 and 07:00
442
+ var h = new Date().getHours();
443
+ return (h >= 19 || h < 7) ? 'dark' : 'light';
444
+ }
445
+
446
+ function applyTheme(mode) {
447
+ var resolved = mode === 'auto' ? resolveAuto() : mode;
448
+ document.documentElement.setAttribute('data-theme', resolved);
449
+ }
450
+
451
+ function updateToggle(mode) {
452
+ var idx = MODES.indexOf(mode);
453
+ var btn = document.querySelector('.eg-theme-toggle');
454
+ if (!btn) return;
455
+ btn.querySelector('.eg-t-icon').textContent = ICONS[idx];
456
+ btn.querySelector('.eg-t-label').textContent = LABELS[idx];
457
+ }
458
+
459
+ // Restore before paint
460
+ var saved = localStorage.getItem('eg-theme-mode') || 'auto';
461
+ applyTheme(saved);
462
+
463
+ // Listen for OS theme changes (e.g. sunset triggers system dark mode)
464
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
465
+ if ((localStorage.getItem('eg-theme-mode') || 'auto') === 'auto') applyTheme('auto');
466
+ });
467
+
468
+ window.__egTheme = {
469
+ cycle: function() {
470
+ var cur = localStorage.getItem('eg-theme-mode') || 'auto';
471
+ var next = MODES[(MODES.indexOf(cur) + 1) % 3];
472
+ localStorage.setItem('eg-theme-mode', next);
473
+ applyTheme(next);
474
+ updateToggle(next);
475
+ },
476
+ init: function() { updateToggle(saved); }
477
+ };
478
+ })();
479
+ </script>
334
480
  </head>
335
481
  <body>
482
+ <button class="eg-theme-toggle" aria-label="Toggle theme" onclick="__egTheme.cycle()">
483
+ <span class="eg-t-icon">&#9680;</span>
484
+ <span class="eg-t-label">auto</span>
485
+ </button>
486
+ <script>__egTheme.init();</script>
336
487
  <div class="eg-artifact" data-type="${escapeHtml(type)}">
337
488
  ${bodyHtml}
338
489
  </div>
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import {
4
4
  ArtifactHeader, SectionCard, ArtifactFooter,
5
5
  } from '../components.js';
6
- import { colors, fonts } from '../tokens.js';
6
+ import { fonts } from '../tokens.js';
7
7
 
8
8
  const h = React.createElement;
9
9
 
@@ -22,18 +22,18 @@ function MetricRow({ metrics }) {
22
22
  h('div', {
23
23
  key: i,
24
24
  style: {
25
- background: 'white',
26
- border: `1px solid ${colors.border}`,
25
+ background: 'var(--surface)',
26
+ border: '1px solid var(--border)',
27
27
  borderRadius: '12px',
28
28
  padding: '1.25rem',
29
29
  textAlign: 'center',
30
30
  },
31
31
  },
32
32
  h('div', {
33
- style: { fontSize: '28px', fontFamily: fonts.serif, fontWeight: 400, color: colors.black, lineHeight: 1.2 },
33
+ style: { fontSize: '28px', fontFamily: fonts.serif, fontWeight: 400, color: 'var(--black)', lineHeight: 1.2 },
34
34
  }, m.value),
35
35
  h('div', {
36
- style: { fontSize: '12px', fontFamily: fonts.mono, color: colors.muted, marginTop: '4px', textTransform: 'uppercase', letterSpacing: '0.04em' },
36
+ style: { fontSize: '12px', fontFamily: fonts.mono, color: 'var(--muted)', marginTop: '4px', textTransform: 'uppercase', letterSpacing: '0.04em' },
37
37
  }, m.label),
38
38
  )
39
39
  ),
@@ -62,14 +62,14 @@ function TrendsCard({ trends }) {
62
62
 
63
63
  return h('div', {
64
64
  style: {
65
- background: 'rgba(212, 135, 90, 0.06)',
66
- border: `1px solid rgba(212, 135, 90, 0.15)`,
65
+ background: 'var(--terracotta-soft)',
66
+ border: '1px solid var(--terracotta-hair)',
67
67
  borderRadius: '12px',
68
68
  padding: '1.25rem 1.5rem',
69
69
  marginBottom: '1.5rem',
70
70
  fontSize: '15px',
71
71
  lineHeight: 1.6,
72
- color: colors.dark,
72
+ color: 'var(--dark)',
73
73
  },
74
74
  },
75
75
  ...lines.map((line, i) => h('p', { key: i, style: { margin: '0 0 0.25rem' } }, line)),
@@ -83,39 +83,39 @@ function SessionRow({ date, topic, by, handedTo, muted }) {
83
83
  alignItems: 'baseline',
84
84
  gap: '12px',
85
85
  padding: '6px 0',
86
- borderBottom: '1px solid rgba(224, 216, 204, 0.5)',
86
+ borderBottom: '1px solid var(--hairline)',
87
87
  fontSize: '14px',
88
88
  },
89
89
  },
90
90
  h('span', {
91
- style: { fontFamily: fonts.mono, fontSize: '12px', color: colors.muted, minWidth: '72px', flexShrink: 0 },
91
+ style: { fontFamily: fonts.mono, fontSize: '12px', color: 'var(--muted)', minWidth: '72px', flexShrink: 0 },
92
92
  }, date),
93
93
  by && h('span', {
94
- style: { fontFamily: fonts.mono, fontSize: '11px', color: colors.blueMuted, background: 'rgba(123, 157, 183, 0.1)', padding: '1px 6px', borderRadius: '3px', flexShrink: 0 },
94
+ style: { fontFamily: fonts.mono, fontSize: '11px', color: 'var(--blue-muted)', background: 'var(--blue-chip)', padding: '1px 6px', borderRadius: '3px', flexShrink: 0 },
95
95
  }, by),
96
- h('span', { style: { color: muted ? colors.muted : colors.black, flex: 1, fontStyle: muted ? 'italic' : 'normal' } }, topic),
97
- handedTo && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: colors.terracotta } }, `→ ${handedTo}`),
96
+ h('span', { style: { color: muted ? 'var(--muted)' : 'var(--black)', flex: 1, fontStyle: muted ? 'italic' : 'normal' } }, topic),
97
+ handedTo && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: 'var(--terracotta)' } }, `→ ${handedTo}`),
98
98
  );
99
99
  }
100
100
 
101
101
  function HandoffItem({ handoff, index }) {
102
102
  const statusDot = handoff.status === 'pending'
103
- ? h('span', { style: { color: colors.terracotta, fontWeight: 700 } }, '●')
104
- : h('span', { style: { color: colors.muted } }, '○');
103
+ ? h('span', { style: { color: 'var(--terracotta)', fontWeight: 700 } }, '●')
104
+ : h('span', { style: { color: 'var(--muted)' } }, '○');
105
105
 
106
106
  return h('div', {
107
- style: { padding: '8px 0', borderBottom: '1px solid rgba(224, 216, 204, 0.5)', fontSize: '14px' },
107
+ style: { padding: '8px 0', borderBottom: '1px solid var(--hairline)', fontSize: '14px' },
108
108
  },
109
109
  h('div', { style: { display: 'flex', gap: '8px', alignItems: 'baseline' } },
110
- h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: colors.muted } }, `[${index + 1}]`),
110
+ h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: 'var(--muted)' } }, `[${index + 1}]`),
111
111
  statusDot,
112
- h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: colors.blueMuted } }, handoff.from),
112
+ h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: 'var(--blue-muted)' } }, handoff.from),
113
113
  h('span', null, '→ you:'),
114
114
  h('span', { style: { fontWeight: 500 } }, handoff.topic),
115
- h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: colors.muted } }, `(${handoff.date})`),
115
+ h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: 'var(--muted)' } }, `(${handoff.date})`),
116
116
  ),
117
117
  handoff.summary && h('p', {
118
- style: { margin: '4px 0 0 28px', fontSize: '13px', color: colors.muted, lineHeight: 1.4 },
118
+ style: { margin: '4px 0 0 28px', fontSize: '13px', color: 'var(--muted)', lineHeight: 1.4 },
119
119
  }, handoff.summary),
120
120
  );
121
121
  }
@@ -127,14 +127,14 @@ function QuestRow({ quest }) {
127
127
  alignItems: 'center',
128
128
  gap: '16px',
129
129
  padding: '8px 0',
130
- borderBottom: '1px solid rgba(224, 216, 204, 0.5)',
130
+ borderBottom: '1px solid var(--hairline)',
131
131
  fontSize: '14px',
132
132
  },
133
133
  },
134
134
  h('span', { style: { fontWeight: 500, flex: 1, minWidth: 0 } }, quest.name),
135
- h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: colors.muted, textAlign: 'right', whiteSpace: 'nowrap' } },
135
+ h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: 'var(--muted)', textAlign: 'right', whiteSpace: 'nowrap' } },
136
136
  `${quest.artifacts} artifacts`),
137
- quest.daysSince > 0 && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: colors.muted, whiteSpace: 'nowrap' } },
137
+ quest.daysSince > 0 && h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: 'var(--muted)', whiteSpace: 'nowrap' } },
138
138
  `· ${quest.daysSince}d ago`),
139
139
  );
140
140
  }
@@ -194,11 +194,11 @@ export function activityTemplate(data) {
194
194
  ...data.pendingQuestions.map((q, i) =>
195
195
  h('div', {
196
196
  key: i,
197
- style: { display: 'flex', gap: '10px', padding: '6px 0', borderBottom: '1px solid rgba(224, 216, 204, 0.5)', fontSize: '14px' },
197
+ style: { display: 'flex', gap: '10px', padding: '6px 0', borderBottom: '1px solid var(--hairline)', fontSize: '14px' },
198
198
  },
199
- h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: colors.blueMuted, flexShrink: 0 } }, q.from),
199
+ h('span', { style: { fontFamily: fonts.mono, fontSize: '12px', color: 'var(--blue-muted)', flexShrink: 0 } }, q.from),
200
200
  h('span', { style: { flex: 1 } }, q.topic),
201
- h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: colors.muted } }, q.date),
201
+ h('span', { style: { fontFamily: fonts.mono, fontSize: '11px', color: 'var(--muted)' } }, q.date),
202
202
  )
203
203
  ),
204
204
  ),
@@ -261,9 +261,9 @@ export function activityTemplate(data) {
261
261
  style: {
262
262
  fontFamily: fonts.mono,
263
263
  fontSize: '12px',
264
- color: colors.muted,
264
+ color: 'var(--muted)',
265
265
  padding: '1rem 0',
266
- borderTop: `1px solid ${colors.border}`,
266
+ borderTop: '1px solid var(--border)',
267
267
  marginTop: '1rem',
268
268
  },
269
269
  },