kanban-system 1.0.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 (48) hide show
  1. package/.env.example +76 -0
  2. package/CLAUDE.md +108 -0
  3. package/README.md +272 -0
  4. package/agents/_TEMPLATE.md +42 -0
  5. package/agents/backend-agent.md +81 -0
  6. package/agents/deploy-gate-agent.md +73 -0
  7. package/agents/frontend-agent.md +73 -0
  8. package/agents/monitor-agent.md +65 -0
  9. package/agents/orchestrator.md +91 -0
  10. package/agents/reviewer-codex.md +51 -0
  11. package/bin/cli.js +171 -0
  12. package/config.example.js +99 -0
  13. package/docs/adapting-to-your-project.md +155 -0
  14. package/docs/example-apex.md +86 -0
  15. package/docs/the-pattern.md +92 -0
  16. package/hooks/launchd.plist.template +66 -0
  17. package/hooks/pre-push.sample +61 -0
  18. package/lib/config.cjs +138 -0
  19. package/lib/detect/_template.cjs +63 -0
  20. package/lib/detect/rules.json +28 -0
  21. package/lib/detect/sentry.cjs +86 -0
  22. package/lib/detect/vercel.cjs +62 -0
  23. package/lib/gate/index.cjs +182 -0
  24. package/lib/runner/adapters/both.cjs +33 -0
  25. package/lib/runner/adapters/claude.cjs +119 -0
  26. package/lib/runner/adapters/codex.cjs +43 -0
  27. package/lib/runner/adapters/reviewer.cjs +91 -0
  28. package/lib/runner/budget.cjs +75 -0
  29. package/lib/runner/index.cjs +93 -0
  30. package/lib/runner/result-merger.cjs +58 -0
  31. package/lib/runner/worktree-manager.cjs +64 -0
  32. package/lib/watch/scheduler.cjs +164 -0
  33. package/package.json +59 -0
  34. package/playbooks/_TEMPLATE.html +54 -0
  35. package/playbooks/build-fail.html +57 -0
  36. package/playbooks/deploy-rollback.html +53 -0
  37. package/playbooks/e2e-regression.html +58 -0
  38. package/playbooks/playbook.css +26 -0
  39. package/playbooks/sentry-spike.html +53 -0
  40. package/server/kanban.cjs +1152 -0
  41. package/skills/archive.md +18 -0
  42. package/skills/gate.md +22 -0
  43. package/skills/standup.md +24 -0
  44. package/skills/triage.md +24 -0
  45. package/ui/kanban.html +628 -0
  46. package/ui/styles/kanban.css +436 -0
  47. package/ui/styles/progress.css +315 -0
  48. package/ui/styles/tokens.css +291 -0
@@ -0,0 +1,315 @@
1
+ /* ============================================================
2
+ kanban-system — live progress indicators, event log, and toast.
3
+ Depends on: tokens.css (import that first).
4
+ ============================================================ */
5
+
6
+ /* ── Connection Status Bar ──────────────────────────────────── */
7
+ .ws-status {
8
+ display: flex;
9
+ align-items: center;
10
+ gap: var(--token-space-2);
11
+ padding: 3px var(--token-space-3);
12
+ border-radius: var(--token-radius-full);
13
+ font-size: var(--token-size-sm);
14
+ font-weight: var(--token-weight-medium);
15
+ background: var(--s2);
16
+ border: 1px solid var(--b1);
17
+ }
18
+ .ws-dot {
19
+ width: 7px;
20
+ height: 7px;
21
+ border-radius: var(--token-radius-full);
22
+ flex-shrink: 0;
23
+ }
24
+ .ws-status[data-state="connected"] .ws-dot { background: var(--gn); }
25
+ .ws-status[data-state="connecting"] .ws-dot {
26
+ background: var(--am);
27
+ animation: ws-pulse var(--token-duration-pulse) var(--token-ease-default) infinite;
28
+ }
29
+ .ws-status[data-state="disconnected"] .ws-dot { background: var(--rd); }
30
+ .ws-status[data-state="idle"] .ws-dot { background: var(--st-idle-dot); }
31
+
32
+ @keyframes ws-pulse {
33
+ 0%, 100% { opacity: 1; }
34
+ 50% { opacity: 0.3; }
35
+ }
36
+
37
+ .ws-label {
38
+ color: var(--t2);
39
+ font-family: var(--token-font-mono);
40
+ font-size: var(--token-size-xs);
41
+ }
42
+ .ws-status[data-state="connected"] .ws-label { color: var(--gn); }
43
+ .ws-status[data-state="connecting"] .ws-label { color: var(--am); }
44
+
45
+ /* ── Run Progress Header ────────────────────────────────────── */
46
+ .run-header {
47
+ display: flex;
48
+ align-items: center;
49
+ gap: var(--token-space-4);
50
+ padding: var(--token-space-3) var(--token-space-6);
51
+ background: var(--s1);
52
+ border-bottom: 1px solid var(--b1);
53
+ }
54
+
55
+ .run-id {
56
+ font-family: var(--token-font-mono);
57
+ font-size: var(--token-size-sm);
58
+ color: var(--t3);
59
+ }
60
+
61
+ .run-progress {
62
+ flex: 1;
63
+ display: flex;
64
+ align-items: center;
65
+ gap: var(--token-space-3);
66
+ }
67
+
68
+ .progress-bar-wrap {
69
+ flex: 1;
70
+ height: 4px;
71
+ background: var(--b1);
72
+ border-radius: var(--token-radius-full);
73
+ overflow: hidden;
74
+ }
75
+
76
+ .progress-bar {
77
+ height: 100%;
78
+ width: 0%;
79
+ background: var(--ac);
80
+ border-radius: var(--token-radius-full);
81
+ transition: width var(--token-duration-normal) var(--token-ease-out);
82
+ }
83
+
84
+ .progress-pct {
85
+ font-family: var(--token-font-mono);
86
+ font-size: var(--token-size-xs);
87
+ color: var(--t3);
88
+ min-width: 32px;
89
+ text-align: right;
90
+ }
91
+
92
+ /* ── Event Log — <details> collapsible ──────────────────────── */
93
+ .event-log {
94
+ border-top: 1px solid var(--b1);
95
+ background: var(--s1);
96
+ }
97
+
98
+ .event-log > summary {
99
+ display: flex;
100
+ align-items: center;
101
+ gap: var(--token-space-2);
102
+ padding: var(--token-space-2) var(--token-space-6);
103
+ cursor: pointer;
104
+ font-size: var(--token-size-sm);
105
+ font-weight: var(--token-weight-medium);
106
+ color: var(--t3);
107
+ user-select: none;
108
+ list-style: none;
109
+ }
110
+ .event-log > summary::-webkit-details-marker { display: none; }
111
+ .event-log > summary::before {
112
+ content: '▶';
113
+ font-size: 9px;
114
+ transition: transform var(--token-duration-fast);
115
+ }
116
+ .event-log[open] > summary::before { transform: rotate(90deg); }
117
+ .event-log > summary:hover { color: var(--t1); }
118
+
119
+ .event-log-title {
120
+ font-size: var(--token-size-sm);
121
+ color: var(--t3);
122
+ }
123
+ .event-log-count {
124
+ font-family: var(--token-font-mono);
125
+ font-size: var(--token-size-xs);
126
+ background: var(--s2);
127
+ color: var(--t4);
128
+ padding: 1px 5px;
129
+ border-radius: var(--token-radius-full);
130
+ margin-left: auto;
131
+ }
132
+
133
+ /* Log lines container */
134
+ .event-log-lines {
135
+ max-height: 260px;
136
+ overflow-y: auto;
137
+ padding: var(--token-space-2) var(--token-space-6);
138
+ display: flex;
139
+ flex-direction: column;
140
+ gap: 2px;
141
+ scroll-behavior: smooth;
142
+ }
143
+
144
+ .event-log-lines::-webkit-scrollbar { width: 4px; }
145
+ .event-log-lines::-webkit-scrollbar-thumb {
146
+ background: var(--b2);
147
+ border-radius: var(--token-radius-full);
148
+ }
149
+
150
+ /* Individual log line — format: [HH:MM:SS] event_type payload_summary */
151
+ .log-line {
152
+ font-family: var(--token-font-mono);
153
+ font-size: var(--token-size-xs); /* 10px */
154
+ line-height: var(--token-lh-normal);
155
+ white-space: pre-wrap;
156
+ word-break: break-word;
157
+ padding: 1px 0;
158
+ display: flex;
159
+ gap: var(--token-space-2);
160
+ }
161
+
162
+ .log-time {
163
+ color: var(--t4);
164
+ flex-shrink: 0;
165
+ }
166
+
167
+ .log-event { flex-shrink: 0; }
168
+ .log-payload { color: var(--t3); overflow: hidden; text-overflow: ellipsis; }
169
+
170
+ /* Log line color coding per pattern spec */
171
+ .log-line[data-type="error"] .log-event,
172
+ .log-line[data-type="blueprint.error"] .log-event,
173
+ .log-line[data-type="component.error"] .log-event {
174
+ color: #f87171; /* rose-400 */
175
+ }
176
+ .log-line[data-type="run.completed"] .log-event,
177
+ .log-line[data-type="component.validated"] .log-event,
178
+ .log-line[data-type="blueprint.completed"] .log-event,
179
+ .log-line[data-type="chapter.regen_completed"] .log-event {
180
+ color: #34d399; /* emerald-400 */
181
+ }
182
+ .log-line[data-type="component.regenerating"] .log-event,
183
+ .log-line[data-type="chapter.regen_started"] .log-event,
184
+ .log-line[data-type="component.flagged"] .log-event {
185
+ color: #fbbf24; /* amber-400 */
186
+ }
187
+ /* zinc — default for all others */
188
+ .log-line .log-event { color: var(--t3); }
189
+
190
+ /* ── Reconnect Notice ───────────────────────────────────────── */
191
+ .reconnect-notice {
192
+ display: none;
193
+ align-items: center;
194
+ gap: var(--token-space-2);
195
+ padding: var(--token-space-2) var(--token-space-6);
196
+ background: color-mix(in srgb, var(--am) 12%, var(--s1));
197
+ border-bottom: 1px solid color-mix(in srgb, var(--am) 30%, transparent);
198
+ font-size: var(--token-size-sm);
199
+ color: var(--am);
200
+ }
201
+ .reconnect-notice.visible { display: flex; }
202
+ .reconnect-spinner {
203
+ width: 12px;
204
+ height: 12px;
205
+ border: 2px solid var(--am);
206
+ border-top-color: transparent;
207
+ border-radius: var(--token-radius-full);
208
+ animation: spin var(--token-duration-slow) linear infinite;
209
+ }
210
+ @keyframes spin { to { transform: rotate(360deg); } }
211
+
212
+ /* ── Toast Notifications ────────────────────────────────────── */
213
+ .toast-container {
214
+ position: fixed;
215
+ bottom: var(--token-space-6);
216
+ right: var(--token-space-6);
217
+ display: flex;
218
+ flex-direction: column;
219
+ gap: var(--token-space-2);
220
+ z-index: var(--token-z-toast);
221
+ pointer-events: none;
222
+ }
223
+
224
+ .toast {
225
+ display: flex;
226
+ align-items: center;
227
+ gap: var(--token-space-2);
228
+ padding: var(--token-space-2) var(--token-space-4);
229
+ border-radius: var(--r);
230
+ font-size: var(--token-size-md);
231
+ font-weight: var(--token-weight-medium);
232
+ box-shadow: var(--shadow-lg);
233
+ pointer-events: auto;
234
+ animation: toast-in var(--token-duration-normal) var(--token-ease-out);
235
+ }
236
+ .toast.removing {
237
+ animation: toast-out var(--token-duration-fast) var(--token-ease-in) forwards;
238
+ }
239
+
240
+ .toast-ok { background: var(--token-toast-ok-bg); color: var(--token-toast-ok-fg); }
241
+ .toast-err { background: var(--token-toast-err-bg); color: var(--token-toast-err-fg); }
242
+ .toast-info { background: var(--token-toast-info-bg); color: var(--token-toast-info-fg); }
243
+
244
+ @keyframes toast-in {
245
+ from { opacity: 0; transform: translateY(8px); }
246
+ to { opacity: 1; transform: translateY(0); }
247
+ }
248
+ @keyframes toast-out {
249
+ from { opacity: 1; transform: translateY(0); }
250
+ to { opacity: 0; transform: translateY(8px); }
251
+ }
252
+
253
+ /* ── Blueprint loading state ────────────────────────────────── */
254
+ .blueprint-loading {
255
+ display: flex;
256
+ align-items: center;
257
+ gap: var(--token-space-3);
258
+ padding: var(--token-space-4) var(--token-space-6);
259
+ color: var(--t3);
260
+ font-size: var(--token-size-md);
261
+ }
262
+ .blueprint-loading .spinner {
263
+ width: 16px;
264
+ height: 16px;
265
+ border: 2px solid var(--b2);
266
+ border-top-color: var(--ac);
267
+ border-radius: var(--token-radius-full);
268
+ animation: spin var(--token-duration-slow) linear infinite;
269
+ }
270
+
271
+ /* ── Error Banner ───────────────────────────────────────────── */
272
+ .err-banner {
273
+ display: none;
274
+ align-items: center;
275
+ gap: var(--token-space-3);
276
+ padding: var(--token-space-3) var(--token-space-6);
277
+ background: color-mix(in srgb, var(--rd) 12%, var(--s1));
278
+ border-bottom: 2px solid color-mix(in srgb, var(--rd) 40%, transparent);
279
+ color: var(--rd);
280
+ font-size: var(--token-size-md);
281
+ z-index: var(--token-z-err-banner);
282
+ }
283
+ .err-banner.visible { display: flex; }
284
+ .err-banner-close {
285
+ margin-left: auto;
286
+ background: none;
287
+ border: none;
288
+ color: var(--rd);
289
+ cursor: pointer;
290
+ font-size: var(--token-size-lg);
291
+ line-height: 1;
292
+ padding: 2px var(--token-space-1);
293
+ }
294
+
295
+ /* ── Anchor highlight (flag-anchor-system) ──────────────────── */
296
+ .anchor-highlight {
297
+ background: var(--token-anchor-bg);
298
+ border: 1px solid var(--token-anchor-border);
299
+ border-radius: var(--token-radius-sm);
300
+ padding: 0 3px;
301
+ position: relative;
302
+ }
303
+ .anchor-highlight::after {
304
+ content: '';
305
+ position: absolute;
306
+ inset: 0;
307
+ border-radius: inherit;
308
+ background: var(--token-anchor-pulse);
309
+ opacity: 0;
310
+ animation: anchor-pulse var(--token-duration-pulse) var(--token-ease-default) infinite;
311
+ }
312
+ @keyframes anchor-pulse {
313
+ 0%, 100% { opacity: 0; }
314
+ 50% { opacity: 0.4; }
315
+ }
@@ -0,0 +1,291 @@
1
+ /* ============================================================
2
+ kanban-system — design tokens (CSS custom properties)
3
+ Import this first, then kanban.css and progress.css.
4
+ Three themes ship: dark (default), navy, light. Override --token-* freely.
5
+ ============================================================ */
6
+
7
+ /* ── Raw Design Tokens ─────────────────────────────────────── */
8
+ :root {
9
+ /* Color / Neutral */
10
+ --token-neutral-50: #fafafa;
11
+ --token-neutral-100: #f4f4f5;
12
+ --token-neutral-200: #e4e4e7;
13
+ --token-neutral-300: #d4d4d8;
14
+ --token-neutral-400: #a1a1aa;
15
+ --token-neutral-500: #71717a;
16
+ --token-neutral-600: #52525b;
17
+ --token-neutral-700: #3f3f46;
18
+ --token-neutral-800: #27272a;
19
+ --token-neutral-900: #18181b;
20
+
21
+ /* Color / Brand */
22
+ --token-brand-primary: #18181b;
23
+ --token-brand-primary-hover: #27272a;
24
+ --token-brand-accent: #059669;
25
+ --token-brand-accent-hover: #047857;
26
+
27
+ /* Color / Status */
28
+ --token-status-generating-bg: #dbeafe;
29
+ --token-status-generating-fg: #1e40af;
30
+ --token-status-generating-dot: #3b82f6;
31
+
32
+ --token-status-validating-bg: #fef3c7;
33
+ --token-status-validating-fg: #92400e;
34
+ --token-status-validating-dot: #f59e0b;
35
+
36
+ --token-status-passed-bg: #d1fae5;
37
+ --token-status-passed-fg: #065f46;
38
+ --token-status-passed-dot: #10b981;
39
+
40
+ --token-status-flagged-bg: #fee2e2;
41
+ --token-status-flagged-fg: #991b1b;
42
+ --token-status-flagged-dot: #ef4444;
43
+
44
+ --token-status-regenerating-bg: #fef3c7;
45
+ --token-status-regenerating-fg: #92400e;
46
+ --token-status-regenerating-dot: #f59e0b;
47
+
48
+ --token-status-error-bg: #fecaca;
49
+ --token-status-error-fg: #7f1d1d;
50
+ --token-status-error-dot: #dc2626;
51
+
52
+ --token-status-idle-bg: #e4e4e7;
53
+ --token-status-idle-fg: #374151;
54
+ --token-status-idle-dot: #a1a1aa;
55
+
56
+ /* Color / Flag */
57
+ --token-flag-fact-bg: #fee2e2;
58
+ --token-flag-fact-fg: #991b1b;
59
+ --token-flag-schema-bg: #fef3c7;
60
+ --token-flag-schema-fg: #92400e;
61
+ --token-flag-borderline-bg: #e0e7ff;
62
+ --token-flag-borderline-fg: #3730a3;
63
+ --token-flag-sensitive-bg: #fce7f3;
64
+ --token-flag-sensitive-fg: #9d174d;
65
+ --token-flag-consistency-bg: #d1fae5;
66
+ --token-flag-consistency-fg: #065f46;
67
+
68
+ /* Color / Anchor */
69
+ --token-anchor-bg: #fef3c7;
70
+ --token-anchor-border: #f59e0b;
71
+ --token-anchor-marker: #f59e0b;
72
+ --token-anchor-pulse: #fde68a;
73
+
74
+ /* Color / Toast */
75
+ --token-toast-ok-bg: #059669;
76
+ --token-toast-ok-fg: #ffffff;
77
+ --token-toast-err-bg: #dc2626;
78
+ --token-toast-err-fg: #ffffff;
79
+ --token-toast-info-bg: #27272a;
80
+ --token-toast-info-fg: #ffffff;
81
+
82
+ /* Color / Severity */
83
+ --token-severity-high: #dc2626;
84
+ --token-severity-mid: #d97706;
85
+ --token-severity-low: #71717a;
86
+
87
+ /* Typography */
88
+ --token-font-sans: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
89
+ --token-font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
90
+
91
+ --token-size-xs: 10px;
92
+ --token-size-sm: 11px;
93
+ --token-size-base: 12px;
94
+ --token-size-md: 13px;
95
+ --token-size-lg: 14px;
96
+ --token-size-xl: 16px;
97
+ --token-size-2xl: 20px;
98
+ --token-size-3xl: 24px;
99
+
100
+ --token-lh-tight: 1.25;
101
+ --token-lh-normal: 1.5;
102
+ --token-lh-relaxed: 1.7;
103
+
104
+ --token-ls-korean: -0.01em;
105
+
106
+ --token-weight-regular: 400;
107
+ --token-weight-medium: 500;
108
+ --token-weight-semibold: 600;
109
+ --token-weight-bold: 700;
110
+
111
+ /* Spacing */
112
+ --token-space-0: 0;
113
+ --token-space-1: 4px;
114
+ --token-space-2: 8px;
115
+ --token-space-3: 12px;
116
+ --token-space-4: 16px;
117
+ --token-space-5: 20px;
118
+ --token-space-6: 24px;
119
+ --token-space-8: 32px;
120
+ --token-space-10: 40px;
121
+ --token-space-12: 48px;
122
+ --token-space-16: 64px;
123
+
124
+ /* Radius */
125
+ --token-radius-sm: 4px;
126
+ --token-radius-md: 6px;
127
+ --token-radius-lg: 8px;
128
+ --token-radius-xl: 10px;
129
+ --token-radius-full: 9999px;
130
+
131
+ /* Shadow */
132
+ --token-shadow-none: none;
133
+ --token-shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
134
+ --token-shadow-md: 0 2px 6px rgba(0,0,0,0.08);
135
+ --token-shadow-lg: 0 8px 24px rgba(0,0,0,0.12);
136
+
137
+ /* Motion */
138
+ --token-duration-instant: 0ms;
139
+ --token-duration-fast: 150ms;
140
+ --token-duration-normal: 250ms;
141
+ --token-duration-slow: 400ms;
142
+ --token-duration-pulse: 2000ms;
143
+
144
+ --token-ease-default: cubic-bezier(0.4, 0, 0.2, 1);
145
+ --token-ease-in: cubic-bezier(0.4, 0, 1, 1);
146
+ --token-ease-out: cubic-bezier(0, 0, 0.2, 1);
147
+
148
+ /* Layout */
149
+ --token-sidebar-default: 240px;
150
+ --token-sidebar-min: 200px;
151
+ --token-sidebar-max: 400px;
152
+ --token-topbar-height: 56px;
153
+ --token-content-max: 1280px;
154
+
155
+ /* Z-index */
156
+ --token-z-base: 0;
157
+ --token-z-sticky: 10;
158
+ --token-z-divider: 50;
159
+ --token-z-overlay: 100;
160
+ --token-z-modal: 200;
161
+ --token-z-toast: 300;
162
+ --token-z-err-banner: 400;
163
+ }
164
+
165
+ /* ── Semantic Aliases — Dark Theme (default) ───────────────── */
166
+ :root,
167
+ [data-theme="dark"] {
168
+ --bg: var(--token-neutral-900); /* #18181b */
169
+ --s1: #1f1f23; /* between 900 and 800 */
170
+ --s2: var(--token-neutral-800); /* #27272a */
171
+ --s3: var(--token-neutral-700); /* #3f3f46 */
172
+ --b1: var(--token-neutral-700); /* #3f3f46 */
173
+ --b2: var(--token-neutral-600); /* #52525b */
174
+ --t1: var(--token-neutral-50); /* #fafafa */
175
+ --t2: var(--token-neutral-400); /* #a1a1aa */
176
+ --t3: var(--token-neutral-500); /* #71717a */
177
+ --t4: var(--token-neutral-600); /* #52525b */
178
+ --ac: var(--token-brand-accent); /* #059669 */
179
+ --ac2: var(--token-brand-accent-hover); /* #047857 */
180
+ --gn: var(--token-status-passed-dot); /* #10b981 */
181
+ --rd: var(--token-status-flagged-dot); /* #ef4444 */
182
+ --am: var(--token-status-validating-dot); /* #f59e0b */
183
+ --vl: #8b5cf6; /* cross-val / violet */
184
+ --r: var(--token-radius-md); /* 6px */
185
+ --r-sm: var(--token-radius-sm); /* 4px */
186
+ --r-lg: var(--token-radius-lg); /* 8px */
187
+ --card-bg: var(--token-neutral-800); /* #27272a */
188
+ --card-hover: var(--token-neutral-700); /* #3f3f46 */
189
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
190
+ --shadow-md: 0 2px 6px rgba(0,0,0,0.4);
191
+ --shadow-lg: 0 8px 24px rgba(0,0,0,0.5);
192
+
193
+ /* Status — dark surface adaptations */
194
+ --st-gen-bg: #1e3a5f;
195
+ --st-gen-fg: #93c5fd;
196
+ --st-gen-dot: var(--token-status-generating-dot);
197
+ --st-val-bg: #3f2f0a;
198
+ --st-val-fg: #fbbf24;
199
+ --st-val-dot: var(--token-status-validating-dot);
200
+ --st-pass-bg: #0a3d2e;
201
+ --st-pass-fg: #6ee7b7;
202
+ --st-pass-dot: var(--token-status-passed-dot);
203
+ --st-flag-bg: #3f1212;
204
+ --st-flag-fg: #fca5a5;
205
+ --st-flag-dot: var(--token-status-flagged-dot);
206
+ --st-idle-bg: #27272a;
207
+ --st-idle-fg: #a1a1aa;
208
+ --st-idle-dot: var(--token-status-idle-dot);
209
+ }
210
+
211
+ /* ── Navy Theme ────────────────────────────────────────────── */
212
+ [data-theme="navy"] {
213
+ --bg: #050A12;
214
+ --s1: #0B1220;
215
+ --s2: #101828;
216
+ --s3: #162035;
217
+ --b1: #1E2D45;
218
+ --b2: #2A3F5F;
219
+ --t1: #DDE5F0;
220
+ --t2: #8899B0;
221
+ --t3: #607088;
222
+ --t4: #455570;
223
+ --ac: #1A6FEF;
224
+ --ac2: #1558C0;
225
+ --gn: #22C55E;
226
+ --rd: #EF4444;
227
+ --am: #C8A24A;
228
+ --vl: #8B5CF6;
229
+ --card-bg: #0F1B30;
230
+ --card-hover: #142440;
231
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
232
+ --shadow-md: 0 2px 6px rgba(0,0,0,0.5);
233
+ --shadow-lg: 0 8px 24px rgba(0,0,0,0.6);
234
+
235
+ --st-gen-bg: #0c1f3f;
236
+ --st-gen-fg: #60a5fa;
237
+ --st-gen-dot: #3b82f6;
238
+ --st-val-bg: #2a1f05;
239
+ --st-val-fg: #fbbf24;
240
+ --st-val-dot: #f59e0b;
241
+ --st-pass-bg: #062a1e;
242
+ --st-pass-fg: #34d399;
243
+ --st-pass-dot:#10b981;
244
+ --st-flag-bg: #2a0808;
245
+ --st-flag-fg: #fca5a5;
246
+ --st-flag-dot:#ef4444;
247
+ --st-idle-bg: #111828;
248
+ --st-idle-fg: #8899B0;
249
+ --st-idle-dot:#455570;
250
+ }
251
+
252
+ /* ── Light Theme ───────────────────────────────────────────── */
253
+ [data-theme="light"] {
254
+ --bg: var(--token-neutral-50); /* #fafafa */
255
+ --s1: #ffffff;
256
+ --s2: var(--token-neutral-100); /* #f4f4f5 */
257
+ --s3: var(--token-neutral-200); /* #e4e4e7 */
258
+ --b1: var(--token-neutral-200); /* #e4e4e7 */
259
+ --b2: var(--token-neutral-300); /* #d4d4d8 */
260
+ --t1: var(--token-neutral-900); /* #18181b */
261
+ --t2: var(--token-neutral-600); /* #52525b */
262
+ --t3: var(--token-neutral-500); /* #71717a */
263
+ --t4: var(--token-neutral-400); /* #a1a1aa */
264
+ --ac: var(--token-brand-accent); /* #059669 */
265
+ --ac2: var(--token-brand-accent-hover); /* #047857 */
266
+ --gn: #16A34A;
267
+ --rd: #DC2626;
268
+ --am: #D97706;
269
+ --vl: #7C3AED;
270
+ --card-bg: #FFFFFF;
271
+ --card-hover: #F0F1F3;
272
+ --shadow-sm: var(--token-shadow-sm);
273
+ --shadow-md: var(--token-shadow-md);
274
+ --shadow-lg: var(--token-shadow-lg);
275
+
276
+ --st-gen-bg: var(--token-status-generating-bg);
277
+ --st-gen-fg: var(--token-status-generating-fg);
278
+ --st-gen-dot: var(--token-status-generating-dot);
279
+ --st-val-bg: var(--token-status-validating-bg);
280
+ --st-val-fg: var(--token-status-validating-fg);
281
+ --st-val-dot: var(--token-status-validating-dot);
282
+ --st-pass-bg: var(--token-status-passed-bg);
283
+ --st-pass-fg: var(--token-status-passed-fg);
284
+ --st-pass-dot:var(--token-status-passed-dot);
285
+ --st-flag-bg: var(--token-status-flagged-bg);
286
+ --st-flag-fg: var(--token-status-flagged-fg);
287
+ --st-flag-dot:var(--token-status-flagged-dot);
288
+ --st-idle-bg: var(--token-status-idle-bg);
289
+ --st-idle-fg: var(--token-status-idle-fg);
290
+ --st-idle-dot:var(--token-status-idle-dot);
291
+ }