brainforge-ai 1.2.1 → 1.2.3
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/README.md +344 -863
- package/dist/commands/defensePack.js +194 -194
- package/dist/commands/difficulty.js +116 -116
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +0 -1
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/study.js +119 -119
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +18 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/core/dashboardTemplate.js +748 -748
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +208 -84
- package/dist/core/templates.js.map +1 -1
- package/package.json +2 -2
|
@@ -3,757 +3,757 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getDashboardHtml = getDashboardHtml;
|
|
4
4
|
exports.getDashboardCss = getDashboardCss;
|
|
5
5
|
function getDashboardHtml() {
|
|
6
|
-
return `<!DOCTYPE html>
|
|
7
|
-
<html lang="en">
|
|
8
|
-
<head>
|
|
9
|
-
<meta charset="UTF-8" />
|
|
10
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
11
|
-
<title>BrainForge Dashboard</title>
|
|
12
|
-
<link rel="stylesheet" href="style.css" />
|
|
13
|
-
</head>
|
|
14
|
-
<body>
|
|
15
|
-
<div class="container">
|
|
16
|
-
<header class="header">
|
|
17
|
-
<div class="logo">⚡ BrainForge</div>
|
|
18
|
-
<div id="updated-at" class="updated-at"></div>
|
|
19
|
-
</header>
|
|
20
|
-
|
|
21
|
-
<section class="project-card">
|
|
22
|
-
<h1 id="project-name"></h1>
|
|
23
|
-
<p id="project-description" class="description"></p>
|
|
24
|
-
<div class="meta-grid">
|
|
25
|
-
<div class="meta-item"><span class="label">Type</span><span id="project-type"></span></div>
|
|
26
|
-
<div class="meta-item"><span class="label">Stack</span><span id="project-stack"></span></div>
|
|
27
|
-
<div class="meta-item"><span class="label">User Level</span><span id="user-level"></span></div>
|
|
28
|
-
<div class="meta-item"><span class="label">Code Level</span><span id="code-level" class="badge"></span></div>
|
|
29
|
-
<div class="meta-item"><span class="label">Git</span><span id="git-status"></span></div>
|
|
30
|
-
<div class="meta-item"><span class="label">Complexity</span><span id="complexity"></span></div>
|
|
31
|
-
<div class="meta-item"><span class="label">Academic Readiness</span><span id="academic-readiness"></span></div>
|
|
32
|
-
</div>
|
|
33
|
-
</section>
|
|
34
|
-
|
|
35
|
-
<!-- Tab Navigation -->
|
|
36
|
-
<nav class="tab-nav">
|
|
37
|
-
<button class="tab-btn active" data-tab="overview">Overview</button>
|
|
38
|
-
<button class="tab-btn" data-tab="phases">Phases</button>
|
|
39
|
-
<button class="tab-btn" data-tab="memory">Memory</button>
|
|
40
|
-
<button class="tab-btn" data-tab="study">Study</button>
|
|
41
|
-
<button class="tab-btn" data-tab="defense">Defense</button>
|
|
42
|
-
<button class="tab-btn" data-tab="docs">Docs Hub</button>
|
|
43
|
-
<button class="tab-btn" data-tab="agents">Agents</button>
|
|
44
|
-
<button class="tab-btn" data-tab="reports">Reports</button>
|
|
45
|
-
</nav>
|
|
46
|
-
|
|
47
|
-
<!-- Overview Tab -->
|
|
48
|
-
<div class="tab-content active" id="tab-overview">
|
|
49
|
-
<section class="progress-section card">
|
|
50
|
-
<div class="section-header">
|
|
51
|
-
<h2>Progress</h2>
|
|
52
|
-
<span id="phase-counter" class="counter"></span>
|
|
53
|
-
</div>
|
|
54
|
-
<div class="progress-bar-wrap">
|
|
55
|
-
<div id="progress-bar" class="progress-bar"></div>
|
|
56
|
-
</div>
|
|
57
|
-
<div id="phases-list-overview" class="phases-list"></div>
|
|
58
|
-
</section>
|
|
59
|
-
|
|
60
|
-
<div class="two-col">
|
|
61
|
-
<section class="card">
|
|
62
|
-
<h2>Recent Commits</h2>
|
|
63
|
-
<ul id="commits-list" class="list"></ul>
|
|
64
|
-
</section>
|
|
65
|
-
<section class="card">
|
|
66
|
-
<h2>Known Bugs</h2>
|
|
67
|
-
<ul id="bugs-list" class="list"></ul>
|
|
68
|
-
</section>
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
<section class="card">
|
|
72
|
-
<h2>Last Decisions</h2>
|
|
73
|
-
<ul id="decisions-list" class="list"></ul>
|
|
74
|
-
</section>
|
|
75
|
-
|
|
76
|
-
<section class="card">
|
|
77
|
-
<h2>Project Depth</h2>
|
|
78
|
-
<div id="depth-grid" class="depth-grid"></div>
|
|
79
|
-
</section>
|
|
80
|
-
</div>
|
|
81
|
-
|
|
82
|
-
<!-- Phases Tab -->
|
|
83
|
-
<div class="tab-content" id="tab-phases">
|
|
84
|
-
<section class="card">
|
|
85
|
-
<h2>All Phases</h2>
|
|
86
|
-
<div id="phases-list-full" class="phases-list"></div>
|
|
87
|
-
</section>
|
|
88
|
-
</div>
|
|
89
|
-
|
|
90
|
-
<!-- Memory Tab -->
|
|
91
|
-
<div class="tab-content" id="tab-memory">
|
|
92
|
-
<section class="card">
|
|
93
|
-
<h2>Memory Files</h2>
|
|
94
|
-
<p class="tab-hint">These files keep your project context. Run <code>brainforge serve</code> to read them.</p>
|
|
95
|
-
<div id="memory-docs-grid" class="docs-grid"></div>
|
|
96
|
-
</section>
|
|
97
|
-
</div>
|
|
98
|
-
|
|
99
|
-
<!-- Study Tab -->
|
|
100
|
-
<div class="tab-content" id="tab-study">
|
|
101
|
-
<section class="card">
|
|
102
|
-
<h2>Study Mode</h2>
|
|
103
|
-
<div id="study-status" class="status-banner"></div>
|
|
104
|
-
<div id="study-docs-grid" class="docs-grid"></div>
|
|
105
|
-
<div class="cmd-hint">
|
|
106
|
-
<span class="cmd-label">Run to enable:</span>
|
|
107
|
-
<code>brainforge study</code>
|
|
108
|
-
<span class="cmd-label">then:</span>
|
|
109
|
-
<code>/study-phase 1</code>
|
|
110
|
-
</div>
|
|
111
|
-
</section>
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
<!-- Defense Tab -->
|
|
115
|
-
<div class="tab-content" id="tab-defense">
|
|
116
|
-
<section class="card">
|
|
117
|
-
<h2>Defense Pack</h2>
|
|
118
|
-
<div id="defense-checklist" class="checklist"></div>
|
|
119
|
-
<div class="cmd-hint">
|
|
120
|
-
<span class="cmd-label">Run:</span>
|
|
121
|
-
<code>brainforge defense-pack</code>
|
|
122
|
-
<span class="cmd-label">then:</span>
|
|
123
|
-
<code>/defense-pack</code>
|
|
124
|
-
</div>
|
|
125
|
-
</section>
|
|
126
|
-
</div>
|
|
127
|
-
|
|
128
|
-
<!-- Docs Hub Tab -->
|
|
129
|
-
<div class="tab-content" id="tab-docs">
|
|
130
|
-
<section class="card">
|
|
131
|
-
<h2>Docs Hub</h2>
|
|
132
|
-
<p class="tab-hint">Click a card to preview the file. Run <code>brainforge serve</code> for full file reading.</p>
|
|
133
|
-
<div id="doc-viewer" class="doc-viewer hidden">
|
|
134
|
-
<div class="doc-viewer-header">
|
|
135
|
-
<span id="doc-viewer-title"></span>
|
|
136
|
-
<button id="doc-viewer-close" class="close-btn">✕</button>
|
|
137
|
-
</div>
|
|
138
|
-
<pre id="doc-viewer-content" class="doc-viewer-content"></pre>
|
|
139
|
-
</div>
|
|
140
|
-
<div id="docs-by-category"></div>
|
|
141
|
-
</section>
|
|
142
|
-
</div>
|
|
143
|
-
|
|
144
|
-
<!-- Agents Tab -->
|
|
145
|
-
<div class="tab-content" id="tab-agents">
|
|
146
|
-
<section class="card">
|
|
147
|
-
<h2>Agent Families</h2>
|
|
148
|
-
<p class="tab-hint">Use <code>/router</code> to find the right agent for your task.</p>
|
|
149
|
-
<div id="agents-grid" class="agents-grid"></div>
|
|
150
|
-
</section>
|
|
151
|
-
</div>
|
|
152
|
-
|
|
153
|
-
<!-- Reports Tab -->
|
|
154
|
-
<div class="tab-content" id="tab-reports">
|
|
155
|
-
<section class="card">
|
|
156
|
-
<h2>Reports</h2>
|
|
157
|
-
<div id="reports-docs-grid" class="docs-grid"></div>
|
|
158
|
-
<div class="cmd-hint">
|
|
159
|
-
<span class="cmd-label">Generate:</span>
|
|
160
|
-
<code>brainforge professor-check</code>
|
|
161
|
-
<code>brainforge difficulty</code>
|
|
162
|
-
<code>brainforge defense-pack</code>
|
|
163
|
-
</div>
|
|
164
|
-
</section>
|
|
165
|
-
</div>
|
|
166
|
-
|
|
167
|
-
<footer class="footer">
|
|
168
|
-
Powered by <strong>BrainForge v1.2</strong> — structured AI development
|
|
169
|
-
</footer>
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<script>
|
|
173
|
-
// Tab navigation
|
|
174
|
-
document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
175
|
-
btn.addEventListener('click', () => {
|
|
176
|
-
const tab = btn.dataset.tab;
|
|
177
|
-
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
178
|
-
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
|
179
|
-
btn.classList.add('active');
|
|
180
|
-
document.getElementById('tab-' + tab).classList.add('active');
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
async function loadData() {
|
|
185
|
-
try {
|
|
186
|
-
let d = window.__BRAINFORGE_DATA__;
|
|
187
|
-
if (!d) {
|
|
188
|
-
const res = await fetch('data.json?t=' + Date.now());
|
|
189
|
-
d = await res.json();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
document.title = 'BrainForge — ' + d.projectName;
|
|
193
|
-
setText('project-name', d.projectName);
|
|
194
|
-
setText('project-description', d.description || 'No description yet.');
|
|
195
|
-
setText('project-type', d.projectType || '—');
|
|
196
|
-
setText('project-stack', (d.stack || []).join(', ') || '—');
|
|
197
|
-
setText('user-level', d.userLevel || '—');
|
|
198
|
-
setText('code-level', d.codeLevel || '—');
|
|
199
|
-
setText('git-status', d.gitStatus || '—');
|
|
200
|
-
setText('updated-at', 'Updated: ' + new Date(d.updatedAt).toLocaleString());
|
|
201
|
-
|
|
202
|
-
const pd = d.projectDepth || {};
|
|
203
|
-
setText('complexity', pd.estimatedComplexity || '—');
|
|
204
|
-
setText('academic-readiness', pd.academicReadiness || '—');
|
|
205
|
-
|
|
206
|
-
// Progress
|
|
207
|
-
const done = (d.phases || []).filter(p => p.status === 'done').length;
|
|
208
|
-
const total = d.totalPhases || d.phases?.length || 0;
|
|
209
|
-
setText('phase-counter', done + ' / ' + total + ' done');
|
|
210
|
-
const pct = total > 0 ? Math.round((done / total) * 100) : 0;
|
|
211
|
-
const pb = document.getElementById('progress-bar');
|
|
212
|
-
pb.style.width = pct + '%';
|
|
213
|
-
pb.textContent = pct + '%';
|
|
214
|
-
|
|
215
|
-
renderPhases('phases-list-overview', d.phases || []);
|
|
216
|
-
renderPhases('phases-list-full', d.phases || []);
|
|
217
|
-
|
|
218
|
-
renderList('commits-list', d.recentCommits, 'No commits yet.');
|
|
219
|
-
renderList('bugs-list', d.knownBugs, 'No bugs tracked.');
|
|
220
|
-
renderList('decisions-list', d.decisions, 'No decisions recorded.');
|
|
221
|
-
|
|
222
|
-
renderDepthGrid(pd);
|
|
223
|
-
renderDocsByCategory('docs-by-category', d.docs || []);
|
|
224
|
-
renderDocsByCategory('memory-docs-grid', (d.docs || []).filter(dc => dc.category === 'Memory'), true);
|
|
225
|
-
renderDocsByCategory('study-docs-grid', (d.docs || []).filter(dc => dc.category === 'Study'), true);
|
|
226
|
-
renderDocsByCategory('reports-docs-grid', (d.docs || []).filter(dc => dc.category === 'Reports'), true);
|
|
227
|
-
renderStudyStatus(d.study || {});
|
|
228
|
-
renderDefenseChecklist(d.defense || {});
|
|
229
|
-
renderAgentsGrid(d.agents || []);
|
|
230
|
-
|
|
231
|
-
} catch (e) {
|
|
232
|
-
document.body.innerHTML += '<p style="color:red;padding:1rem">Error loading data.json: ' + e.message + '. Run brainforge serve for live loading.</p>';
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function setText(id, val) {
|
|
237
|
-
const el = document.getElementById(id);
|
|
238
|
-
if (el) el.textContent = val;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function renderList(id, items, empty) {
|
|
242
|
-
const el = document.getElementById(id);
|
|
243
|
-
if (!el) return;
|
|
244
|
-
if (!items || items.length === 0) {
|
|
245
|
-
el.innerHTML = '<li class="empty">' + empty + '</li>';
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
el.innerHTML = items.map(i => '<li>' + i + '</li>').join('');
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function renderPhases(id, phases) {
|
|
252
|
-
const el = document.getElementById(id);
|
|
253
|
-
if (!el) return;
|
|
254
|
-
if (!phases.length) { el.innerHTML = '<p class="empty">No phases yet.</p>'; return; }
|
|
255
|
-
el.innerHTML = phases.map(p =>
|
|
256
|
-
'<div class="phase-item ' + p.status + '">'
|
|
257
|
-
+ '<span class="phase-num">' + String(p.id).padStart(2,'0') + '</span>'
|
|
258
|
-
+ '<span class="phase-title">' + p.title + '</span>'
|
|
259
|
-
+ '<span class="phase-status ' + p.status + '">' + p.status + '</span>'
|
|
260
|
-
+ '</div>'
|
|
261
|
-
).join('');
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function renderDepthGrid(pd) {
|
|
265
|
-
const el = document.getElementById('depth-grid');
|
|
266
|
-
if (!el) return;
|
|
267
|
-
const items = [
|
|
268
|
-
{ label: 'Agents', value: pd.totalAgents || 0 },
|
|
269
|
-
{ label: 'Commands', value: pd.totalCommands || 0 },
|
|
270
|
-
{ label: 'Phases', value: pd.totalPhases || 0 },
|
|
271
|
-
{ label: 'Memory Files', value: pd.totalMemoryFiles || 0 },
|
|
272
|
-
{ label: 'Reports', value: pd.totalReports || 0 },
|
|
273
|
-
{ label: 'Total MD Files', value: pd.totalMarkdownFiles || 0 },
|
|
274
|
-
];
|
|
275
|
-
el.innerHTML = items.map(i =>
|
|
276
|
-
'<div class="depth-item"><span class="depth-value">' + i.value + '</span><span class="label">' + i.label + '</span></div>'
|
|
277
|
-
).join('');
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function renderDocsByCategory(id, docs, flat) {
|
|
281
|
-
const el = document.getElementById(id);
|
|
282
|
-
if (!el) return;
|
|
283
|
-
if (!docs.length) { el.innerHTML = '<p class="empty">No docs found.</p>'; return; }
|
|
284
|
-
|
|
285
|
-
if (flat) {
|
|
286
|
-
el.innerHTML = docs.map(doc => docCard(doc)).join('');
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const cats = {};
|
|
291
|
-
docs.forEach(doc => {
|
|
292
|
-
if (!cats[doc.category]) cats[doc.category] = [];
|
|
293
|
-
cats[doc.category].push(doc);
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
el.innerHTML = Object.entries(cats).map(([cat, catDocs]) =>
|
|
297
|
-
'<div class="doc-category">'
|
|
298
|
-
+ '<h3 class="doc-cat-title">' + cat + '</h3>'
|
|
299
|
-
+ '<div class="doc-cat-grid">' + catDocs.map(doc => docCard(doc)).join('') + '</div>'
|
|
300
|
-
+ '</div>'
|
|
301
|
-
).join('');
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
function docCard(doc) {
|
|
305
|
-
const cls = doc.exists ? 'doc-card' : 'doc-card missing';
|
|
306
|
-
const badge = doc.exists ? '<span class="doc-badge exists">exists</span>' : '<span class="doc-badge missing">missing</span>';
|
|
307
|
-
return '<div class="' + cls + '" data-path="' + doc.path + '" onclick="openDoc(this)">'
|
|
308
|
-
+ '<div class="doc-card-title">' + doc.title + '</div>'
|
|
309
|
-
+ '<div class="doc-card-path">' + doc.path + '</div>'
|
|
310
|
-
+ badge
|
|
311
|
-
+ '</div>';
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
async function openDoc(el) {
|
|
315
|
-
const p = el.dataset.path;
|
|
316
|
-
const viewer = document.getElementById('doc-viewer');
|
|
317
|
-
const title = document.getElementById('doc-viewer-title');
|
|
318
|
-
const content = document.getElementById('doc-viewer-content');
|
|
319
|
-
title.textContent = p;
|
|
320
|
-
content.textContent = 'Loading...';
|
|
321
|
-
viewer.classList.remove('hidden');
|
|
322
|
-
try {
|
|
323
|
-
const res = await fetch('../' + p.replace('.brainforge/', '') + '?t=' + Date.now());
|
|
324
|
-
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
325
|
-
content.textContent = await res.text();
|
|
326
|
-
} catch {
|
|
327
|
-
content.textContent = 'Cannot read file in file:// mode.\\nRun: brainforge serve';
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
document.getElementById('doc-viewer-close').addEventListener('click', () => {
|
|
332
|
-
document.getElementById('doc-viewer').classList.add('hidden');
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
function renderStudyStatus(study) {
|
|
336
|
-
const el = document.getElementById('study-status');
|
|
337
|
-
if (!el) return;
|
|
338
|
-
if (study.enabled) {
|
|
339
|
-
el.className = 'status-banner success';
|
|
340
|
-
el.textContent = 'Study Mode enabled — ' + (study.files || []).length + ' file(s)';
|
|
341
|
-
} else {
|
|
342
|
-
el.className = 'status-banner warn';
|
|
343
|
-
el.textContent = 'Study Mode not initialized. Run: brainforge study';
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function renderDefenseChecklist(defense) {
|
|
348
|
-
const el = document.getElementById('defense-checklist');
|
|
349
|
-
if (!el) return;
|
|
350
|
-
const items = [
|
|
351
|
-
{ label: 'Defense Pack report', ok: defense.reportExists },
|
|
352
|
-
{ label: 'Professor Check report', ok: defense.professorCheckExists },
|
|
353
|
-
{ label: 'Difficulty Report', ok: defense.difficultyReportExists },
|
|
354
|
-
];
|
|
355
|
-
el.innerHTML = items.map(item =>
|
|
356
|
-
'<div class="check-item ' + (item.ok ? 'ok' : 'missing') + '">'
|
|
357
|
-
+ '<span class="check-icon">' + (item.ok ? '✔' : '✖') + '</span>'
|
|
358
|
-
+ '<span>' + item.label + '</span>'
|
|
359
|
-
+ '</div>'
|
|
360
|
-
).join('');
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
function renderAgentsGrid(agents) {
|
|
364
|
-
const el = document.getElementById('agents-grid');
|
|
365
|
-
if (!el) return;
|
|
366
|
-
if (!agents.length) { el.innerHTML = '<p class="empty">No agents found. Run brainforge update.</p>'; return; }
|
|
367
|
-
|
|
368
|
-
const families = {};
|
|
369
|
-
agents.forEach(a => {
|
|
370
|
-
if (!families[a.family]) families[a.family] = [];
|
|
371
|
-
families[a.family].push(a);
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
el.innerHTML = Object.entries(families).map(([fam, agts]) =>
|
|
375
|
-
'<div class="agent-family">'
|
|
376
|
-
+ '<h3 class="agent-family-title">' + fam + '</h3>'
|
|
377
|
-
+ agts.map(a =>
|
|
378
|
-
'<div class="agent-card">'
|
|
379
|
-
+ '<div class="agent-title">' + a.title + '</div>'
|
|
380
|
-
+ '<div class="agent-summary">' + a.summary + '</div>'
|
|
381
|
-
+ '</div>'
|
|
382
|
-
).join('')
|
|
383
|
-
+ '</div>'
|
|
384
|
-
).join('');
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
loadData();
|
|
388
|
-
</script>
|
|
389
|
-
</body>
|
|
6
|
+
return `<!DOCTYPE html>
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="UTF-8" />
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
11
|
+
<title>BrainForge Dashboard</title>
|
|
12
|
+
<link rel="stylesheet" href="style.css" />
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<div class="container">
|
|
16
|
+
<header class="header">
|
|
17
|
+
<div class="logo">⚡ BrainForge</div>
|
|
18
|
+
<div id="updated-at" class="updated-at"></div>
|
|
19
|
+
</header>
|
|
20
|
+
|
|
21
|
+
<section class="project-card">
|
|
22
|
+
<h1 id="project-name"></h1>
|
|
23
|
+
<p id="project-description" class="description"></p>
|
|
24
|
+
<div class="meta-grid">
|
|
25
|
+
<div class="meta-item"><span class="label">Type</span><span id="project-type"></span></div>
|
|
26
|
+
<div class="meta-item"><span class="label">Stack</span><span id="project-stack"></span></div>
|
|
27
|
+
<div class="meta-item"><span class="label">User Level</span><span id="user-level"></span></div>
|
|
28
|
+
<div class="meta-item"><span class="label">Code Level</span><span id="code-level" class="badge"></span></div>
|
|
29
|
+
<div class="meta-item"><span class="label">Git</span><span id="git-status"></span></div>
|
|
30
|
+
<div class="meta-item"><span class="label">Complexity</span><span id="complexity"></span></div>
|
|
31
|
+
<div class="meta-item"><span class="label">Academic Readiness</span><span id="academic-readiness"></span></div>
|
|
32
|
+
</div>
|
|
33
|
+
</section>
|
|
34
|
+
|
|
35
|
+
<!-- Tab Navigation -->
|
|
36
|
+
<nav class="tab-nav">
|
|
37
|
+
<button class="tab-btn active" data-tab="overview">Overview</button>
|
|
38
|
+
<button class="tab-btn" data-tab="phases">Phases</button>
|
|
39
|
+
<button class="tab-btn" data-tab="memory">Memory</button>
|
|
40
|
+
<button class="tab-btn" data-tab="study">Study</button>
|
|
41
|
+
<button class="tab-btn" data-tab="defense">Defense</button>
|
|
42
|
+
<button class="tab-btn" data-tab="docs">Docs Hub</button>
|
|
43
|
+
<button class="tab-btn" data-tab="agents">Agents</button>
|
|
44
|
+
<button class="tab-btn" data-tab="reports">Reports</button>
|
|
45
|
+
</nav>
|
|
46
|
+
|
|
47
|
+
<!-- Overview Tab -->
|
|
48
|
+
<div class="tab-content active" id="tab-overview">
|
|
49
|
+
<section class="progress-section card">
|
|
50
|
+
<div class="section-header">
|
|
51
|
+
<h2>Progress</h2>
|
|
52
|
+
<span id="phase-counter" class="counter"></span>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="progress-bar-wrap">
|
|
55
|
+
<div id="progress-bar" class="progress-bar"></div>
|
|
56
|
+
</div>
|
|
57
|
+
<div id="phases-list-overview" class="phases-list"></div>
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
<div class="two-col">
|
|
61
|
+
<section class="card">
|
|
62
|
+
<h2>Recent Commits</h2>
|
|
63
|
+
<ul id="commits-list" class="list"></ul>
|
|
64
|
+
</section>
|
|
65
|
+
<section class="card">
|
|
66
|
+
<h2>Known Bugs</h2>
|
|
67
|
+
<ul id="bugs-list" class="list"></ul>
|
|
68
|
+
</section>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<section class="card">
|
|
72
|
+
<h2>Last Decisions</h2>
|
|
73
|
+
<ul id="decisions-list" class="list"></ul>
|
|
74
|
+
</section>
|
|
75
|
+
|
|
76
|
+
<section class="card">
|
|
77
|
+
<h2>Project Depth</h2>
|
|
78
|
+
<div id="depth-grid" class="depth-grid"></div>
|
|
79
|
+
</section>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<!-- Phases Tab -->
|
|
83
|
+
<div class="tab-content" id="tab-phases">
|
|
84
|
+
<section class="card">
|
|
85
|
+
<h2>All Phases</h2>
|
|
86
|
+
<div id="phases-list-full" class="phases-list"></div>
|
|
87
|
+
</section>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<!-- Memory Tab -->
|
|
91
|
+
<div class="tab-content" id="tab-memory">
|
|
92
|
+
<section class="card">
|
|
93
|
+
<h2>Memory Files</h2>
|
|
94
|
+
<p class="tab-hint">These files keep your project context. Run <code>brainforge serve</code> to read them.</p>
|
|
95
|
+
<div id="memory-docs-grid" class="docs-grid"></div>
|
|
96
|
+
</section>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<!-- Study Tab -->
|
|
100
|
+
<div class="tab-content" id="tab-study">
|
|
101
|
+
<section class="card">
|
|
102
|
+
<h2>Study Mode</h2>
|
|
103
|
+
<div id="study-status" class="status-banner"></div>
|
|
104
|
+
<div id="study-docs-grid" class="docs-grid"></div>
|
|
105
|
+
<div class="cmd-hint">
|
|
106
|
+
<span class="cmd-label">Run to enable:</span>
|
|
107
|
+
<code>brainforge study</code>
|
|
108
|
+
<span class="cmd-label">then:</span>
|
|
109
|
+
<code>/study-phase 1</code>
|
|
110
|
+
</div>
|
|
111
|
+
</section>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<!-- Defense Tab -->
|
|
115
|
+
<div class="tab-content" id="tab-defense">
|
|
116
|
+
<section class="card">
|
|
117
|
+
<h2>Defense Pack</h2>
|
|
118
|
+
<div id="defense-checklist" class="checklist"></div>
|
|
119
|
+
<div class="cmd-hint">
|
|
120
|
+
<span class="cmd-label">Run:</span>
|
|
121
|
+
<code>brainforge defense-pack</code>
|
|
122
|
+
<span class="cmd-label">then:</span>
|
|
123
|
+
<code>/defense-pack</code>
|
|
124
|
+
</div>
|
|
125
|
+
</section>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<!-- Docs Hub Tab -->
|
|
129
|
+
<div class="tab-content" id="tab-docs">
|
|
130
|
+
<section class="card">
|
|
131
|
+
<h2>Docs Hub</h2>
|
|
132
|
+
<p class="tab-hint">Click a card to preview the file. Run <code>brainforge serve</code> for full file reading.</p>
|
|
133
|
+
<div id="doc-viewer" class="doc-viewer hidden">
|
|
134
|
+
<div class="doc-viewer-header">
|
|
135
|
+
<span id="doc-viewer-title"></span>
|
|
136
|
+
<button id="doc-viewer-close" class="close-btn">✕</button>
|
|
137
|
+
</div>
|
|
138
|
+
<pre id="doc-viewer-content" class="doc-viewer-content"></pre>
|
|
139
|
+
</div>
|
|
140
|
+
<div id="docs-by-category"></div>
|
|
141
|
+
</section>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<!-- Agents Tab -->
|
|
145
|
+
<div class="tab-content" id="tab-agents">
|
|
146
|
+
<section class="card">
|
|
147
|
+
<h2>Agent Families</h2>
|
|
148
|
+
<p class="tab-hint">Use <code>/router</code> to find the right agent for your task.</p>
|
|
149
|
+
<div id="agents-grid" class="agents-grid"></div>
|
|
150
|
+
</section>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<!-- Reports Tab -->
|
|
154
|
+
<div class="tab-content" id="tab-reports">
|
|
155
|
+
<section class="card">
|
|
156
|
+
<h2>Reports</h2>
|
|
157
|
+
<div id="reports-docs-grid" class="docs-grid"></div>
|
|
158
|
+
<div class="cmd-hint">
|
|
159
|
+
<span class="cmd-label">Generate:</span>
|
|
160
|
+
<code>brainforge professor-check</code>
|
|
161
|
+
<code>brainforge difficulty</code>
|
|
162
|
+
<code>brainforge defense-pack</code>
|
|
163
|
+
</div>
|
|
164
|
+
</section>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<footer class="footer">
|
|
168
|
+
Powered by <strong>BrainForge v1.2</strong> — structured AI development
|
|
169
|
+
</footer>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<script>
|
|
173
|
+
// Tab navigation
|
|
174
|
+
document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
175
|
+
btn.addEventListener('click', () => {
|
|
176
|
+
const tab = btn.dataset.tab;
|
|
177
|
+
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
178
|
+
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
|
179
|
+
btn.classList.add('active');
|
|
180
|
+
document.getElementById('tab-' + tab).classList.add('active');
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
async function loadData() {
|
|
185
|
+
try {
|
|
186
|
+
let d = window.__BRAINFORGE_DATA__;
|
|
187
|
+
if (!d) {
|
|
188
|
+
const res = await fetch('data.json?t=' + Date.now());
|
|
189
|
+
d = await res.json();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
document.title = 'BrainForge — ' + d.projectName;
|
|
193
|
+
setText('project-name', d.projectName);
|
|
194
|
+
setText('project-description', d.description || 'No description yet.');
|
|
195
|
+
setText('project-type', d.projectType || '—');
|
|
196
|
+
setText('project-stack', (d.stack || []).join(', ') || '—');
|
|
197
|
+
setText('user-level', d.userLevel || '—');
|
|
198
|
+
setText('code-level', d.codeLevel || '—');
|
|
199
|
+
setText('git-status', d.gitStatus || '—');
|
|
200
|
+
setText('updated-at', 'Updated: ' + new Date(d.updatedAt).toLocaleString());
|
|
201
|
+
|
|
202
|
+
const pd = d.projectDepth || {};
|
|
203
|
+
setText('complexity', pd.estimatedComplexity || '—');
|
|
204
|
+
setText('academic-readiness', pd.academicReadiness || '—');
|
|
205
|
+
|
|
206
|
+
// Progress
|
|
207
|
+
const done = (d.phases || []).filter(p => p.status === 'done').length;
|
|
208
|
+
const total = d.totalPhases || d.phases?.length || 0;
|
|
209
|
+
setText('phase-counter', done + ' / ' + total + ' done');
|
|
210
|
+
const pct = total > 0 ? Math.round((done / total) * 100) : 0;
|
|
211
|
+
const pb = document.getElementById('progress-bar');
|
|
212
|
+
pb.style.width = pct + '%';
|
|
213
|
+
pb.textContent = pct + '%';
|
|
214
|
+
|
|
215
|
+
renderPhases('phases-list-overview', d.phases || []);
|
|
216
|
+
renderPhases('phases-list-full', d.phases || []);
|
|
217
|
+
|
|
218
|
+
renderList('commits-list', d.recentCommits, 'No commits yet.');
|
|
219
|
+
renderList('bugs-list', d.knownBugs, 'No bugs tracked.');
|
|
220
|
+
renderList('decisions-list', d.decisions, 'No decisions recorded.');
|
|
221
|
+
|
|
222
|
+
renderDepthGrid(pd);
|
|
223
|
+
renderDocsByCategory('docs-by-category', d.docs || []);
|
|
224
|
+
renderDocsByCategory('memory-docs-grid', (d.docs || []).filter(dc => dc.category === 'Memory'), true);
|
|
225
|
+
renderDocsByCategory('study-docs-grid', (d.docs || []).filter(dc => dc.category === 'Study'), true);
|
|
226
|
+
renderDocsByCategory('reports-docs-grid', (d.docs || []).filter(dc => dc.category === 'Reports'), true);
|
|
227
|
+
renderStudyStatus(d.study || {});
|
|
228
|
+
renderDefenseChecklist(d.defense || {});
|
|
229
|
+
renderAgentsGrid(d.agents || []);
|
|
230
|
+
|
|
231
|
+
} catch (e) {
|
|
232
|
+
document.body.innerHTML += '<p style="color:red;padding:1rem">Error loading data.json: ' + e.message + '. Run brainforge serve for live loading.</p>';
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function setText(id, val) {
|
|
237
|
+
const el = document.getElementById(id);
|
|
238
|
+
if (el) el.textContent = val;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function renderList(id, items, empty) {
|
|
242
|
+
const el = document.getElementById(id);
|
|
243
|
+
if (!el) return;
|
|
244
|
+
if (!items || items.length === 0) {
|
|
245
|
+
el.innerHTML = '<li class="empty">' + empty + '</li>';
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
el.innerHTML = items.map(i => '<li>' + i + '</li>').join('');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function renderPhases(id, phases) {
|
|
252
|
+
const el = document.getElementById(id);
|
|
253
|
+
if (!el) return;
|
|
254
|
+
if (!phases.length) { el.innerHTML = '<p class="empty">No phases yet.</p>'; return; }
|
|
255
|
+
el.innerHTML = phases.map(p =>
|
|
256
|
+
'<div class="phase-item ' + p.status + '">'
|
|
257
|
+
+ '<span class="phase-num">' + String(p.id).padStart(2,'0') + '</span>'
|
|
258
|
+
+ '<span class="phase-title">' + p.title + '</span>'
|
|
259
|
+
+ '<span class="phase-status ' + p.status + '">' + p.status + '</span>'
|
|
260
|
+
+ '</div>'
|
|
261
|
+
).join('');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function renderDepthGrid(pd) {
|
|
265
|
+
const el = document.getElementById('depth-grid');
|
|
266
|
+
if (!el) return;
|
|
267
|
+
const items = [
|
|
268
|
+
{ label: 'Agents', value: pd.totalAgents || 0 },
|
|
269
|
+
{ label: 'Commands', value: pd.totalCommands || 0 },
|
|
270
|
+
{ label: 'Phases', value: pd.totalPhases || 0 },
|
|
271
|
+
{ label: 'Memory Files', value: pd.totalMemoryFiles || 0 },
|
|
272
|
+
{ label: 'Reports', value: pd.totalReports || 0 },
|
|
273
|
+
{ label: 'Total MD Files', value: pd.totalMarkdownFiles || 0 },
|
|
274
|
+
];
|
|
275
|
+
el.innerHTML = items.map(i =>
|
|
276
|
+
'<div class="depth-item"><span class="depth-value">' + i.value + '</span><span class="label">' + i.label + '</span></div>'
|
|
277
|
+
).join('');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function renderDocsByCategory(id, docs, flat) {
|
|
281
|
+
const el = document.getElementById(id);
|
|
282
|
+
if (!el) return;
|
|
283
|
+
if (!docs.length) { el.innerHTML = '<p class="empty">No docs found.</p>'; return; }
|
|
284
|
+
|
|
285
|
+
if (flat) {
|
|
286
|
+
el.innerHTML = docs.map(doc => docCard(doc)).join('');
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const cats = {};
|
|
291
|
+
docs.forEach(doc => {
|
|
292
|
+
if (!cats[doc.category]) cats[doc.category] = [];
|
|
293
|
+
cats[doc.category].push(doc);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
el.innerHTML = Object.entries(cats).map(([cat, catDocs]) =>
|
|
297
|
+
'<div class="doc-category">'
|
|
298
|
+
+ '<h3 class="doc-cat-title">' + cat + '</h3>'
|
|
299
|
+
+ '<div class="doc-cat-grid">' + catDocs.map(doc => docCard(doc)).join('') + '</div>'
|
|
300
|
+
+ '</div>'
|
|
301
|
+
).join('');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function docCard(doc) {
|
|
305
|
+
const cls = doc.exists ? 'doc-card' : 'doc-card missing';
|
|
306
|
+
const badge = doc.exists ? '<span class="doc-badge exists">exists</span>' : '<span class="doc-badge missing">missing</span>';
|
|
307
|
+
return '<div class="' + cls + '" data-path="' + doc.path + '" onclick="openDoc(this)">'
|
|
308
|
+
+ '<div class="doc-card-title">' + doc.title + '</div>'
|
|
309
|
+
+ '<div class="doc-card-path">' + doc.path + '</div>'
|
|
310
|
+
+ badge
|
|
311
|
+
+ '</div>';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async function openDoc(el) {
|
|
315
|
+
const p = el.dataset.path;
|
|
316
|
+
const viewer = document.getElementById('doc-viewer');
|
|
317
|
+
const title = document.getElementById('doc-viewer-title');
|
|
318
|
+
const content = document.getElementById('doc-viewer-content');
|
|
319
|
+
title.textContent = p;
|
|
320
|
+
content.textContent = 'Loading...';
|
|
321
|
+
viewer.classList.remove('hidden');
|
|
322
|
+
try {
|
|
323
|
+
const res = await fetch('../' + p.replace('.brainforge/', '') + '?t=' + Date.now());
|
|
324
|
+
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
325
|
+
content.textContent = await res.text();
|
|
326
|
+
} catch {
|
|
327
|
+
content.textContent = 'Cannot read file in file:// mode.\\nRun: brainforge serve';
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
document.getElementById('doc-viewer-close').addEventListener('click', () => {
|
|
332
|
+
document.getElementById('doc-viewer').classList.add('hidden');
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
function renderStudyStatus(study) {
|
|
336
|
+
const el = document.getElementById('study-status');
|
|
337
|
+
if (!el) return;
|
|
338
|
+
if (study.enabled) {
|
|
339
|
+
el.className = 'status-banner success';
|
|
340
|
+
el.textContent = 'Study Mode enabled — ' + (study.files || []).length + ' file(s)';
|
|
341
|
+
} else {
|
|
342
|
+
el.className = 'status-banner warn';
|
|
343
|
+
el.textContent = 'Study Mode not initialized. Run: brainforge study';
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function renderDefenseChecklist(defense) {
|
|
348
|
+
const el = document.getElementById('defense-checklist');
|
|
349
|
+
if (!el) return;
|
|
350
|
+
const items = [
|
|
351
|
+
{ label: 'Defense Pack report', ok: defense.reportExists },
|
|
352
|
+
{ label: 'Professor Check report', ok: defense.professorCheckExists },
|
|
353
|
+
{ label: 'Difficulty Report', ok: defense.difficultyReportExists },
|
|
354
|
+
];
|
|
355
|
+
el.innerHTML = items.map(item =>
|
|
356
|
+
'<div class="check-item ' + (item.ok ? 'ok' : 'missing') + '">'
|
|
357
|
+
+ '<span class="check-icon">' + (item.ok ? '✔' : '✖') + '</span>'
|
|
358
|
+
+ '<span>' + item.label + '</span>'
|
|
359
|
+
+ '</div>'
|
|
360
|
+
).join('');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function renderAgentsGrid(agents) {
|
|
364
|
+
const el = document.getElementById('agents-grid');
|
|
365
|
+
if (!el) return;
|
|
366
|
+
if (!agents.length) { el.innerHTML = '<p class="empty">No agents found. Run brainforge update.</p>'; return; }
|
|
367
|
+
|
|
368
|
+
const families = {};
|
|
369
|
+
agents.forEach(a => {
|
|
370
|
+
if (!families[a.family]) families[a.family] = [];
|
|
371
|
+
families[a.family].push(a);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
el.innerHTML = Object.entries(families).map(([fam, agts]) =>
|
|
375
|
+
'<div class="agent-family">'
|
|
376
|
+
+ '<h3 class="agent-family-title">' + fam + '</h3>'
|
|
377
|
+
+ agts.map(a =>
|
|
378
|
+
'<div class="agent-card">'
|
|
379
|
+
+ '<div class="agent-title">' + a.title + '</div>'
|
|
380
|
+
+ '<div class="agent-summary">' + a.summary + '</div>'
|
|
381
|
+
+ '</div>'
|
|
382
|
+
).join('')
|
|
383
|
+
+ '</div>'
|
|
384
|
+
).join('');
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
loadData();
|
|
388
|
+
</script>
|
|
389
|
+
</body>
|
|
390
390
|
</html>`;
|
|
391
391
|
}
|
|
392
392
|
function getDashboardCss() {
|
|
393
|
-
return `*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
394
|
-
|
|
395
|
-
:root {
|
|
396
|
-
--bg: #0f172a;
|
|
397
|
-
--surface: #1e293b;
|
|
398
|
-
--surface2: #273549;
|
|
399
|
-
--primary: #6366f1;
|
|
400
|
-
--primary-light: #818cf8;
|
|
401
|
-
--success: #22c55e;
|
|
402
|
-
--warning: #f59e0b;
|
|
403
|
-
--error: #ef4444;
|
|
404
|
-
--text: #f1f5f9;
|
|
405
|
-
--muted: #94a3b8;
|
|
406
|
-
--border: #334155;
|
|
407
|
-
--radius: 10px;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
body {
|
|
411
|
-
background: var(--bg);
|
|
412
|
-
color: var(--text);
|
|
413
|
-
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
414
|
-
font-size: 15px;
|
|
415
|
-
line-height: 1.6;
|
|
416
|
-
min-height: 100vh;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
.container { max-width: 1100px; margin: 0 auto; padding: 2rem 1.5rem; }
|
|
420
|
-
|
|
421
|
-
.header {
|
|
422
|
-
display: flex;
|
|
423
|
-
justify-content: space-between;
|
|
424
|
-
align-items: center;
|
|
425
|
-
margin-bottom: 2rem;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
.logo { font-size: 1.4rem; font-weight: 700; color: var(--primary-light); letter-spacing: -0.5px; }
|
|
429
|
-
.updated-at { color: var(--muted); font-size: 0.8rem; }
|
|
430
|
-
|
|
431
|
-
.project-card {
|
|
432
|
-
background: var(--surface);
|
|
433
|
-
border: 1px solid var(--border);
|
|
434
|
-
border-radius: var(--radius);
|
|
435
|
-
padding: 1.75rem;
|
|
436
|
-
margin-bottom: 1.5rem;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
h1 { font-size: 1.6rem; font-weight: 700; margin-bottom: 0.4rem; }
|
|
440
|
-
h2 { font-size: 1.05rem; font-weight: 600; margin-bottom: 1rem; color: var(--primary-light); }
|
|
441
|
-
h3 { font-size: 0.95rem; font-weight: 600; margin-bottom: 0.75rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
|
|
442
|
-
|
|
443
|
-
.description { color: var(--muted); margin-bottom: 1.25rem; }
|
|
444
|
-
|
|
445
|
-
.meta-grid {
|
|
446
|
-
display: grid;
|
|
447
|
-
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
448
|
-
gap: 0.75rem;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
.meta-item {
|
|
452
|
-
background: var(--surface2);
|
|
453
|
-
border-radius: 8px;
|
|
454
|
-
padding: 0.6rem 0.9rem;
|
|
455
|
-
display: flex;
|
|
456
|
-
flex-direction: column;
|
|
457
|
-
gap: 2px;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
.label { font-size: 0.72rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
|
|
461
|
-
|
|
462
|
-
.badge {
|
|
463
|
-
display: inline-block;
|
|
464
|
-
background: var(--primary);
|
|
465
|
-
color: #fff;
|
|
466
|
-
border-radius: 20px;
|
|
467
|
-
padding: 1px 10px;
|
|
468
|
-
font-size: 0.8rem;
|
|
469
|
-
font-weight: 600;
|
|
470
|
-
width: fit-content;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/* Tab Navigation */
|
|
474
|
-
.tab-nav {
|
|
475
|
-
display: flex;
|
|
476
|
-
gap: 0.25rem;
|
|
477
|
-
margin-bottom: 1.5rem;
|
|
478
|
-
background: var(--surface);
|
|
479
|
-
border: 1px solid var(--border);
|
|
480
|
-
border-radius: var(--radius);
|
|
481
|
-
padding: 0.4rem;
|
|
482
|
-
flex-wrap: wrap;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
.tab-btn {
|
|
486
|
-
background: none;
|
|
487
|
-
border: none;
|
|
488
|
-
color: var(--muted);
|
|
489
|
-
cursor: pointer;
|
|
490
|
-
padding: 0.45rem 0.9rem;
|
|
491
|
-
border-radius: 7px;
|
|
492
|
-
font-size: 0.85rem;
|
|
493
|
-
font-weight: 500;
|
|
494
|
-
transition: all 0.15s;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
.tab-btn:hover { background: var(--surface2); color: var(--text); }
|
|
498
|
-
.tab-btn.active { background: var(--primary); color: #fff; }
|
|
499
|
-
|
|
500
|
-
.tab-content { display: none; }
|
|
501
|
-
.tab-content.active { display: block; }
|
|
502
|
-
|
|
503
|
-
.tab-hint { color: var(--muted); font-size: 0.85rem; margin-bottom: 1rem; }
|
|
504
|
-
.tab-hint code { background: var(--surface2); padding: 1px 6px; border-radius: 4px; font-size: 0.8rem; }
|
|
505
|
-
|
|
506
|
-
/* Cards */
|
|
507
|
-
.card {
|
|
508
|
-
background: var(--surface);
|
|
509
|
-
border: 1px solid var(--border);
|
|
510
|
-
border-radius: var(--radius);
|
|
511
|
-
padding: 1.5rem;
|
|
512
|
-
margin-bottom: 1.5rem;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 1.5rem; }
|
|
516
|
-
@media (max-width: 640px) { .two-col { grid-template-columns: 1fr; } }
|
|
517
|
-
|
|
518
|
-
.progress-section {
|
|
519
|
-
background: var(--surface);
|
|
520
|
-
border: 1px solid var(--border);
|
|
521
|
-
border-radius: var(--radius);
|
|
522
|
-
padding: 1.5rem;
|
|
523
|
-
margin-bottom: 1.5rem;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; }
|
|
527
|
-
.counter { color: var(--muted); font-size: 0.85rem; }
|
|
528
|
-
|
|
529
|
-
.progress-bar-wrap {
|
|
530
|
-
background: var(--surface2);
|
|
531
|
-
border-radius: 20px;
|
|
532
|
-
height: 22px;
|
|
533
|
-
overflow: hidden;
|
|
534
|
-
margin-bottom: 1.25rem;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
.progress-bar {
|
|
538
|
-
background: linear-gradient(90deg, var(--primary), var(--primary-light));
|
|
539
|
-
height: 100%;
|
|
540
|
-
border-radius: 20px;
|
|
541
|
-
display: flex;
|
|
542
|
-
align-items: center;
|
|
543
|
-
justify-content: center;
|
|
544
|
-
font-size: 0.75rem;
|
|
545
|
-
font-weight: 600;
|
|
546
|
-
color: #fff;
|
|
547
|
-
min-width: 2rem;
|
|
548
|
-
transition: width 0.5s ease;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
.phases-list { display: flex; flex-direction: column; gap: 0.5rem; }
|
|
552
|
-
|
|
553
|
-
.phase-item {
|
|
554
|
-
display: flex;
|
|
555
|
-
align-items: center;
|
|
556
|
-
gap: 0.75rem;
|
|
557
|
-
padding: 0.6rem 0.9rem;
|
|
558
|
-
background: var(--surface2);
|
|
559
|
-
border-radius: 8px;
|
|
560
|
-
border-left: 3px solid var(--border);
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
.phase-item.done { border-left-color: var(--success); }
|
|
564
|
-
.phase-item.in-progress { border-left-color: var(--warning); }
|
|
565
|
-
|
|
566
|
-
.phase-num { font-size: 0.8rem; color: var(--muted); min-width: 28px; }
|
|
567
|
-
.phase-title { flex: 1; }
|
|
568
|
-
|
|
569
|
-
.phase-status {
|
|
570
|
-
font-size: 0.72rem;
|
|
571
|
-
padding: 2px 8px;
|
|
572
|
-
border-radius: 20px;
|
|
573
|
-
font-weight: 600;
|
|
574
|
-
text-transform: uppercase;
|
|
575
|
-
background: var(--surface);
|
|
576
|
-
color: var(--muted);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
.phase-status.done { background: rgba(34,197,94,0.15); color: var(--success); }
|
|
580
|
-
.phase-status.in-progress { background: rgba(245,158,11,0.15); color: var(--warning); }
|
|
581
|
-
|
|
582
|
-
.list { list-style: none; display: flex; flex-direction: column; gap: 0.4rem; }
|
|
583
|
-
.list li { padding: 0.4rem 0; border-bottom: 1px solid var(--border); font-size: 0.88rem; }
|
|
584
|
-
.list li:last-child { border-bottom: none; }
|
|
585
|
-
.list .empty { color: var(--muted); font-style: italic; }
|
|
586
|
-
|
|
587
|
-
/* Depth grid */
|
|
588
|
-
.depth-grid {
|
|
589
|
-
display: grid;
|
|
590
|
-
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
|
|
591
|
-
gap: 0.75rem;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
.depth-item {
|
|
595
|
-
background: var(--surface2);
|
|
596
|
-
border-radius: 8px;
|
|
597
|
-
padding: 0.75rem;
|
|
598
|
-
display: flex;
|
|
599
|
-
flex-direction: column;
|
|
600
|
-
align-items: center;
|
|
601
|
-
gap: 4px;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
.depth-value { font-size: 1.6rem; font-weight: 700; color: var(--primary-light); }
|
|
605
|
-
|
|
606
|
-
/* Docs grid */
|
|
607
|
-
.docs-grid {
|
|
608
|
-
display: grid;
|
|
609
|
-
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
610
|
-
gap: 0.75rem;
|
|
611
|
-
margin-bottom: 1rem;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
.doc-category { margin-bottom: 1.5rem; }
|
|
615
|
-
.doc-cat-title { font-size: 0.85rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 0.75rem; }
|
|
616
|
-
.doc-cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.75rem; }
|
|
617
|
-
|
|
618
|
-
.doc-card {
|
|
619
|
-
background: var(--surface2);
|
|
620
|
-
border: 1px solid var(--border);
|
|
621
|
-
border-radius: 8px;
|
|
622
|
-
padding: 0.75rem;
|
|
623
|
-
cursor: pointer;
|
|
624
|
-
transition: border-color 0.15s;
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
.doc-card:hover { border-color: var(--primary); }
|
|
628
|
-
.doc-card.missing { opacity: 0.5; cursor: default; }
|
|
629
|
-
.doc-card.missing:hover { border-color: var(--border); }
|
|
630
|
-
|
|
631
|
-
.doc-card-title { font-weight: 600; font-size: 0.9rem; margin-bottom: 0.25rem; }
|
|
632
|
-
.doc-card-path { font-size: 0.7rem; color: var(--muted); margin-bottom: 0.4rem; word-break: break-all; }
|
|
633
|
-
|
|
634
|
-
.doc-badge {
|
|
635
|
-
display: inline-block;
|
|
636
|
-
font-size: 0.68rem;
|
|
637
|
-
padding: 1px 6px;
|
|
638
|
-
border-radius: 10px;
|
|
639
|
-
font-weight: 600;
|
|
640
|
-
text-transform: uppercase;
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
.doc-badge.exists { background: rgba(34,197,94,0.15); color: var(--success); }
|
|
644
|
-
.doc-badge.missing { background: rgba(239,68,68,0.15); color: var(--error); }
|
|
645
|
-
|
|
646
|
-
/* Doc viewer */
|
|
647
|
-
.doc-viewer {
|
|
648
|
-
background: var(--surface2);
|
|
649
|
-
border: 1px solid var(--border);
|
|
650
|
-
border-radius: var(--radius);
|
|
651
|
-
padding: 1rem;
|
|
652
|
-
margin-bottom: 1.5rem;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
.doc-viewer.hidden { display: none; }
|
|
656
|
-
|
|
657
|
-
.doc-viewer-header {
|
|
658
|
-
display: flex;
|
|
659
|
-
justify-content: space-between;
|
|
660
|
-
align-items: center;
|
|
661
|
-
margin-bottom: 0.75rem;
|
|
662
|
-
font-size: 0.85rem;
|
|
663
|
-
color: var(--muted);
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
.doc-viewer-content {
|
|
667
|
-
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
|
668
|
-
font-size: 0.8rem;
|
|
669
|
-
white-space: pre-wrap;
|
|
670
|
-
max-height: 400px;
|
|
671
|
-
overflow-y: auto;
|
|
672
|
-
color: var(--text);
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
.close-btn {
|
|
676
|
-
background: none;
|
|
677
|
-
border: none;
|
|
678
|
-
color: var(--muted);
|
|
679
|
-
cursor: pointer;
|
|
680
|
-
font-size: 1rem;
|
|
681
|
-
padding: 2px 6px;
|
|
682
|
-
border-radius: 4px;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
.close-btn:hover { background: var(--surface); }
|
|
686
|
-
|
|
687
|
-
/* Status banners */
|
|
688
|
-
.status-banner {
|
|
689
|
-
padding: 0.75rem 1rem;
|
|
690
|
-
border-radius: 8px;
|
|
691
|
-
margin-bottom: 1rem;
|
|
692
|
-
font-weight: 500;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
.status-banner.success { background: rgba(34,197,94,0.12); color: var(--success); border: 1px solid rgba(34,197,94,0.2); }
|
|
696
|
-
.status-banner.warn { background: rgba(245,158,11,0.12); color: var(--warning); border: 1px solid rgba(245,158,11,0.2); }
|
|
697
|
-
|
|
698
|
-
/* Defense checklist */
|
|
699
|
-
.checklist { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; }
|
|
700
|
-
|
|
701
|
-
.check-item {
|
|
702
|
-
display: flex;
|
|
703
|
-
align-items: center;
|
|
704
|
-
gap: 0.75rem;
|
|
705
|
-
padding: 0.5rem 0.75rem;
|
|
706
|
-
border-radius: 8px;
|
|
707
|
-
font-size: 0.9rem;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
.check-item.ok { background: rgba(34,197,94,0.08); }
|
|
711
|
-
.check-item.missing { background: rgba(239,68,68,0.08); }
|
|
712
|
-
|
|
713
|
-
.check-icon { font-size: 1rem; }
|
|
714
|
-
.check-item.ok .check-icon { color: var(--success); }
|
|
715
|
-
.check-item.missing .check-icon { color: var(--error); }
|
|
716
|
-
|
|
717
|
-
/* Command hints */
|
|
718
|
-
.cmd-hint {
|
|
719
|
-
display: flex;
|
|
720
|
-
align-items: center;
|
|
721
|
-
gap: 0.5rem;
|
|
722
|
-
flex-wrap: wrap;
|
|
723
|
-
padding: 0.75rem;
|
|
724
|
-
background: var(--surface2);
|
|
725
|
-
border-radius: 8px;
|
|
726
|
-
font-size: 0.85rem;
|
|
727
|
-
margin-top: 1rem;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
.cmd-label { color: var(--muted); }
|
|
731
|
-
.cmd-hint code { background: var(--bg); padding: 2px 8px; border-radius: 4px; font-family: monospace; font-size: 0.82rem; }
|
|
732
|
-
|
|
733
|
-
/* Agents grid */
|
|
734
|
-
.agents-grid { display: flex; flex-direction: column; gap: 1.5rem; }
|
|
735
|
-
|
|
736
|
-
.agent-family { }
|
|
737
|
-
.agent-family-title { font-size: 0.85rem; font-weight: 600; color: var(--primary-light); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 0.75rem; }
|
|
738
|
-
|
|
739
|
-
.agent-card {
|
|
740
|
-
display: inline-block;
|
|
741
|
-
background: var(--surface2);
|
|
742
|
-
border: 1px solid var(--border);
|
|
743
|
-
border-radius: 8px;
|
|
744
|
-
padding: 0.6rem 0.9rem;
|
|
745
|
-
margin: 0 0.4rem 0.4rem 0;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
.agent-title { font-weight: 600; font-size: 0.88rem; }
|
|
749
|
-
.agent-summary { font-size: 0.78rem; color: var(--muted); }
|
|
750
|
-
|
|
751
|
-
.footer {
|
|
752
|
-
text-align: center;
|
|
753
|
-
padding: 2rem 0 1rem;
|
|
754
|
-
color: var(--muted);
|
|
755
|
-
font-size: 0.82rem;
|
|
756
|
-
}
|
|
393
|
+
return `*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
394
|
+
|
|
395
|
+
:root {
|
|
396
|
+
--bg: #0f172a;
|
|
397
|
+
--surface: #1e293b;
|
|
398
|
+
--surface2: #273549;
|
|
399
|
+
--primary: #6366f1;
|
|
400
|
+
--primary-light: #818cf8;
|
|
401
|
+
--success: #22c55e;
|
|
402
|
+
--warning: #f59e0b;
|
|
403
|
+
--error: #ef4444;
|
|
404
|
+
--text: #f1f5f9;
|
|
405
|
+
--muted: #94a3b8;
|
|
406
|
+
--border: #334155;
|
|
407
|
+
--radius: 10px;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
body {
|
|
411
|
+
background: var(--bg);
|
|
412
|
+
color: var(--text);
|
|
413
|
+
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
414
|
+
font-size: 15px;
|
|
415
|
+
line-height: 1.6;
|
|
416
|
+
min-height: 100vh;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.container { max-width: 1100px; margin: 0 auto; padding: 2rem 1.5rem; }
|
|
420
|
+
|
|
421
|
+
.header {
|
|
422
|
+
display: flex;
|
|
423
|
+
justify-content: space-between;
|
|
424
|
+
align-items: center;
|
|
425
|
+
margin-bottom: 2rem;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.logo { font-size: 1.4rem; font-weight: 700; color: var(--primary-light); letter-spacing: -0.5px; }
|
|
429
|
+
.updated-at { color: var(--muted); font-size: 0.8rem; }
|
|
430
|
+
|
|
431
|
+
.project-card {
|
|
432
|
+
background: var(--surface);
|
|
433
|
+
border: 1px solid var(--border);
|
|
434
|
+
border-radius: var(--radius);
|
|
435
|
+
padding: 1.75rem;
|
|
436
|
+
margin-bottom: 1.5rem;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
h1 { font-size: 1.6rem; font-weight: 700; margin-bottom: 0.4rem; }
|
|
440
|
+
h2 { font-size: 1.05rem; font-weight: 600; margin-bottom: 1rem; color: var(--primary-light); }
|
|
441
|
+
h3 { font-size: 0.95rem; font-weight: 600; margin-bottom: 0.75rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
|
|
442
|
+
|
|
443
|
+
.description { color: var(--muted); margin-bottom: 1.25rem; }
|
|
444
|
+
|
|
445
|
+
.meta-grid {
|
|
446
|
+
display: grid;
|
|
447
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
448
|
+
gap: 0.75rem;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.meta-item {
|
|
452
|
+
background: var(--surface2);
|
|
453
|
+
border-radius: 8px;
|
|
454
|
+
padding: 0.6rem 0.9rem;
|
|
455
|
+
display: flex;
|
|
456
|
+
flex-direction: column;
|
|
457
|
+
gap: 2px;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.label { font-size: 0.72rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
|
|
461
|
+
|
|
462
|
+
.badge {
|
|
463
|
+
display: inline-block;
|
|
464
|
+
background: var(--primary);
|
|
465
|
+
color: #fff;
|
|
466
|
+
border-radius: 20px;
|
|
467
|
+
padding: 1px 10px;
|
|
468
|
+
font-size: 0.8rem;
|
|
469
|
+
font-weight: 600;
|
|
470
|
+
width: fit-content;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/* Tab Navigation */
|
|
474
|
+
.tab-nav {
|
|
475
|
+
display: flex;
|
|
476
|
+
gap: 0.25rem;
|
|
477
|
+
margin-bottom: 1.5rem;
|
|
478
|
+
background: var(--surface);
|
|
479
|
+
border: 1px solid var(--border);
|
|
480
|
+
border-radius: var(--radius);
|
|
481
|
+
padding: 0.4rem;
|
|
482
|
+
flex-wrap: wrap;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.tab-btn {
|
|
486
|
+
background: none;
|
|
487
|
+
border: none;
|
|
488
|
+
color: var(--muted);
|
|
489
|
+
cursor: pointer;
|
|
490
|
+
padding: 0.45rem 0.9rem;
|
|
491
|
+
border-radius: 7px;
|
|
492
|
+
font-size: 0.85rem;
|
|
493
|
+
font-weight: 500;
|
|
494
|
+
transition: all 0.15s;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.tab-btn:hover { background: var(--surface2); color: var(--text); }
|
|
498
|
+
.tab-btn.active { background: var(--primary); color: #fff; }
|
|
499
|
+
|
|
500
|
+
.tab-content { display: none; }
|
|
501
|
+
.tab-content.active { display: block; }
|
|
502
|
+
|
|
503
|
+
.tab-hint { color: var(--muted); font-size: 0.85rem; margin-bottom: 1rem; }
|
|
504
|
+
.tab-hint code { background: var(--surface2); padding: 1px 6px; border-radius: 4px; font-size: 0.8rem; }
|
|
505
|
+
|
|
506
|
+
/* Cards */
|
|
507
|
+
.card {
|
|
508
|
+
background: var(--surface);
|
|
509
|
+
border: 1px solid var(--border);
|
|
510
|
+
border-radius: var(--radius);
|
|
511
|
+
padding: 1.5rem;
|
|
512
|
+
margin-bottom: 1.5rem;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 1.5rem; }
|
|
516
|
+
@media (max-width: 640px) { .two-col { grid-template-columns: 1fr; } }
|
|
517
|
+
|
|
518
|
+
.progress-section {
|
|
519
|
+
background: var(--surface);
|
|
520
|
+
border: 1px solid var(--border);
|
|
521
|
+
border-radius: var(--radius);
|
|
522
|
+
padding: 1.5rem;
|
|
523
|
+
margin-bottom: 1.5rem;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; }
|
|
527
|
+
.counter { color: var(--muted); font-size: 0.85rem; }
|
|
528
|
+
|
|
529
|
+
.progress-bar-wrap {
|
|
530
|
+
background: var(--surface2);
|
|
531
|
+
border-radius: 20px;
|
|
532
|
+
height: 22px;
|
|
533
|
+
overflow: hidden;
|
|
534
|
+
margin-bottom: 1.25rem;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
.progress-bar {
|
|
538
|
+
background: linear-gradient(90deg, var(--primary), var(--primary-light));
|
|
539
|
+
height: 100%;
|
|
540
|
+
border-radius: 20px;
|
|
541
|
+
display: flex;
|
|
542
|
+
align-items: center;
|
|
543
|
+
justify-content: center;
|
|
544
|
+
font-size: 0.75rem;
|
|
545
|
+
font-weight: 600;
|
|
546
|
+
color: #fff;
|
|
547
|
+
min-width: 2rem;
|
|
548
|
+
transition: width 0.5s ease;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.phases-list { display: flex; flex-direction: column; gap: 0.5rem; }
|
|
552
|
+
|
|
553
|
+
.phase-item {
|
|
554
|
+
display: flex;
|
|
555
|
+
align-items: center;
|
|
556
|
+
gap: 0.75rem;
|
|
557
|
+
padding: 0.6rem 0.9rem;
|
|
558
|
+
background: var(--surface2);
|
|
559
|
+
border-radius: 8px;
|
|
560
|
+
border-left: 3px solid var(--border);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.phase-item.done { border-left-color: var(--success); }
|
|
564
|
+
.phase-item.in-progress { border-left-color: var(--warning); }
|
|
565
|
+
|
|
566
|
+
.phase-num { font-size: 0.8rem; color: var(--muted); min-width: 28px; }
|
|
567
|
+
.phase-title { flex: 1; }
|
|
568
|
+
|
|
569
|
+
.phase-status {
|
|
570
|
+
font-size: 0.72rem;
|
|
571
|
+
padding: 2px 8px;
|
|
572
|
+
border-radius: 20px;
|
|
573
|
+
font-weight: 600;
|
|
574
|
+
text-transform: uppercase;
|
|
575
|
+
background: var(--surface);
|
|
576
|
+
color: var(--muted);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.phase-status.done { background: rgba(34,197,94,0.15); color: var(--success); }
|
|
580
|
+
.phase-status.in-progress { background: rgba(245,158,11,0.15); color: var(--warning); }
|
|
581
|
+
|
|
582
|
+
.list { list-style: none; display: flex; flex-direction: column; gap: 0.4rem; }
|
|
583
|
+
.list li { padding: 0.4rem 0; border-bottom: 1px solid var(--border); font-size: 0.88rem; }
|
|
584
|
+
.list li:last-child { border-bottom: none; }
|
|
585
|
+
.list .empty { color: var(--muted); font-style: italic; }
|
|
586
|
+
|
|
587
|
+
/* Depth grid */
|
|
588
|
+
.depth-grid {
|
|
589
|
+
display: grid;
|
|
590
|
+
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
|
|
591
|
+
gap: 0.75rem;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.depth-item {
|
|
595
|
+
background: var(--surface2);
|
|
596
|
+
border-radius: 8px;
|
|
597
|
+
padding: 0.75rem;
|
|
598
|
+
display: flex;
|
|
599
|
+
flex-direction: column;
|
|
600
|
+
align-items: center;
|
|
601
|
+
gap: 4px;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.depth-value { font-size: 1.6rem; font-weight: 700; color: var(--primary-light); }
|
|
605
|
+
|
|
606
|
+
/* Docs grid */
|
|
607
|
+
.docs-grid {
|
|
608
|
+
display: grid;
|
|
609
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
610
|
+
gap: 0.75rem;
|
|
611
|
+
margin-bottom: 1rem;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
.doc-category { margin-bottom: 1.5rem; }
|
|
615
|
+
.doc-cat-title { font-size: 0.85rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 0.75rem; }
|
|
616
|
+
.doc-cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.75rem; }
|
|
617
|
+
|
|
618
|
+
.doc-card {
|
|
619
|
+
background: var(--surface2);
|
|
620
|
+
border: 1px solid var(--border);
|
|
621
|
+
border-radius: 8px;
|
|
622
|
+
padding: 0.75rem;
|
|
623
|
+
cursor: pointer;
|
|
624
|
+
transition: border-color 0.15s;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.doc-card:hover { border-color: var(--primary); }
|
|
628
|
+
.doc-card.missing { opacity: 0.5; cursor: default; }
|
|
629
|
+
.doc-card.missing:hover { border-color: var(--border); }
|
|
630
|
+
|
|
631
|
+
.doc-card-title { font-weight: 600; font-size: 0.9rem; margin-bottom: 0.25rem; }
|
|
632
|
+
.doc-card-path { font-size: 0.7rem; color: var(--muted); margin-bottom: 0.4rem; word-break: break-all; }
|
|
633
|
+
|
|
634
|
+
.doc-badge {
|
|
635
|
+
display: inline-block;
|
|
636
|
+
font-size: 0.68rem;
|
|
637
|
+
padding: 1px 6px;
|
|
638
|
+
border-radius: 10px;
|
|
639
|
+
font-weight: 600;
|
|
640
|
+
text-transform: uppercase;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.doc-badge.exists { background: rgba(34,197,94,0.15); color: var(--success); }
|
|
644
|
+
.doc-badge.missing { background: rgba(239,68,68,0.15); color: var(--error); }
|
|
645
|
+
|
|
646
|
+
/* Doc viewer */
|
|
647
|
+
.doc-viewer {
|
|
648
|
+
background: var(--surface2);
|
|
649
|
+
border: 1px solid var(--border);
|
|
650
|
+
border-radius: var(--radius);
|
|
651
|
+
padding: 1rem;
|
|
652
|
+
margin-bottom: 1.5rem;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.doc-viewer.hidden { display: none; }
|
|
656
|
+
|
|
657
|
+
.doc-viewer-header {
|
|
658
|
+
display: flex;
|
|
659
|
+
justify-content: space-between;
|
|
660
|
+
align-items: center;
|
|
661
|
+
margin-bottom: 0.75rem;
|
|
662
|
+
font-size: 0.85rem;
|
|
663
|
+
color: var(--muted);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
.doc-viewer-content {
|
|
667
|
+
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
|
668
|
+
font-size: 0.8rem;
|
|
669
|
+
white-space: pre-wrap;
|
|
670
|
+
max-height: 400px;
|
|
671
|
+
overflow-y: auto;
|
|
672
|
+
color: var(--text);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
.close-btn {
|
|
676
|
+
background: none;
|
|
677
|
+
border: none;
|
|
678
|
+
color: var(--muted);
|
|
679
|
+
cursor: pointer;
|
|
680
|
+
font-size: 1rem;
|
|
681
|
+
padding: 2px 6px;
|
|
682
|
+
border-radius: 4px;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.close-btn:hover { background: var(--surface); }
|
|
686
|
+
|
|
687
|
+
/* Status banners */
|
|
688
|
+
.status-banner {
|
|
689
|
+
padding: 0.75rem 1rem;
|
|
690
|
+
border-radius: 8px;
|
|
691
|
+
margin-bottom: 1rem;
|
|
692
|
+
font-weight: 500;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.status-banner.success { background: rgba(34,197,94,0.12); color: var(--success); border: 1px solid rgba(34,197,94,0.2); }
|
|
696
|
+
.status-banner.warn { background: rgba(245,158,11,0.12); color: var(--warning); border: 1px solid rgba(245,158,11,0.2); }
|
|
697
|
+
|
|
698
|
+
/* Defense checklist */
|
|
699
|
+
.checklist { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; }
|
|
700
|
+
|
|
701
|
+
.check-item {
|
|
702
|
+
display: flex;
|
|
703
|
+
align-items: center;
|
|
704
|
+
gap: 0.75rem;
|
|
705
|
+
padding: 0.5rem 0.75rem;
|
|
706
|
+
border-radius: 8px;
|
|
707
|
+
font-size: 0.9rem;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.check-item.ok { background: rgba(34,197,94,0.08); }
|
|
711
|
+
.check-item.missing { background: rgba(239,68,68,0.08); }
|
|
712
|
+
|
|
713
|
+
.check-icon { font-size: 1rem; }
|
|
714
|
+
.check-item.ok .check-icon { color: var(--success); }
|
|
715
|
+
.check-item.missing .check-icon { color: var(--error); }
|
|
716
|
+
|
|
717
|
+
/* Command hints */
|
|
718
|
+
.cmd-hint {
|
|
719
|
+
display: flex;
|
|
720
|
+
align-items: center;
|
|
721
|
+
gap: 0.5rem;
|
|
722
|
+
flex-wrap: wrap;
|
|
723
|
+
padding: 0.75rem;
|
|
724
|
+
background: var(--surface2);
|
|
725
|
+
border-radius: 8px;
|
|
726
|
+
font-size: 0.85rem;
|
|
727
|
+
margin-top: 1rem;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.cmd-label { color: var(--muted); }
|
|
731
|
+
.cmd-hint code { background: var(--bg); padding: 2px 8px; border-radius: 4px; font-family: monospace; font-size: 0.82rem; }
|
|
732
|
+
|
|
733
|
+
/* Agents grid */
|
|
734
|
+
.agents-grid { display: flex; flex-direction: column; gap: 1.5rem; }
|
|
735
|
+
|
|
736
|
+
.agent-family { }
|
|
737
|
+
.agent-family-title { font-size: 0.85rem; font-weight: 600; color: var(--primary-light); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 0.75rem; }
|
|
738
|
+
|
|
739
|
+
.agent-card {
|
|
740
|
+
display: inline-block;
|
|
741
|
+
background: var(--surface2);
|
|
742
|
+
border: 1px solid var(--border);
|
|
743
|
+
border-radius: 8px;
|
|
744
|
+
padding: 0.6rem 0.9rem;
|
|
745
|
+
margin: 0 0.4rem 0.4rem 0;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
.agent-title { font-weight: 600; font-size: 0.88rem; }
|
|
749
|
+
.agent-summary { font-size: 0.78rem; color: var(--muted); }
|
|
750
|
+
|
|
751
|
+
.footer {
|
|
752
|
+
text-align: center;
|
|
753
|
+
padding: 2rem 0 1rem;
|
|
754
|
+
color: var(--muted);
|
|
755
|
+
font-size: 0.82rem;
|
|
756
|
+
}
|
|
757
757
|
`;
|
|
758
758
|
}
|
|
759
759
|
//# sourceMappingURL=dashboardTemplate.js.map
|