brainforge-ai 1.2.0 → 1.2.2

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 (53) hide show
  1. package/README.md +193 -570
  2. package/dist/cli.js +47 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/defensePack.d.ts +2 -0
  5. package/dist/commands/defensePack.d.ts.map +1 -0
  6. package/dist/commands/defensePack.js +269 -0
  7. package/dist/commands/defensePack.js.map +1 -0
  8. package/dist/commands/difficulty.d.ts +2 -0
  9. package/dist/commands/difficulty.d.ts.map +1 -0
  10. package/dist/commands/difficulty.js +177 -0
  11. package/dist/commands/difficulty.js.map +1 -0
  12. package/dist/commands/doctor.d.ts.map +1 -1
  13. package/dist/commands/doctor.js +53 -1
  14. package/dist/commands/doctor.js.map +1 -1
  15. package/dist/commands/help.d.ts.map +1 -1
  16. package/dist/commands/help.js +24 -1
  17. package/dist/commands/help.js.map +1 -1
  18. package/dist/commands/init.d.ts +6 -1
  19. package/dist/commands/init.d.ts.map +1 -1
  20. package/dist/commands/init.js +64 -2
  21. package/dist/commands/init.js.map +1 -1
  22. package/dist/commands/professorCheck.d.ts +2 -0
  23. package/dist/commands/professorCheck.d.ts.map +1 -0
  24. package/dist/commands/professorCheck.js +203 -0
  25. package/dist/commands/professorCheck.js.map +1 -0
  26. package/dist/commands/simplify.d.ts +2 -0
  27. package/dist/commands/simplify.d.ts.map +1 -0
  28. package/dist/commands/simplify.js +174 -0
  29. package/dist/commands/simplify.js.map +1 -0
  30. package/dist/commands/status.d.ts +2 -0
  31. package/dist/commands/status.d.ts.map +1 -0
  32. package/dist/commands/status.js +105 -0
  33. package/dist/commands/status.js.map +1 -0
  34. package/dist/commands/study.d.ts +2 -0
  35. package/dist/commands/study.d.ts.map +1 -0
  36. package/dist/commands/study.js +193 -0
  37. package/dist/commands/study.js.map +1 -0
  38. package/dist/commands/update.js +2 -2
  39. package/dist/commands/update.js.map +1 -1
  40. package/dist/core/dashboard.d.ts +41 -0
  41. package/dist/core/dashboard.d.ts.map +1 -1
  42. package/dist/core/dashboard.js +121 -0
  43. package/dist/core/dashboard.js.map +1 -1
  44. package/dist/core/dashboardTemplate.d.ts.map +1 -1
  45. package/dist/core/dashboardTemplate.js +523 -92
  46. package/dist/core/dashboardTemplate.js.map +1 -1
  47. package/dist/core/fileSystem.d.ts.map +1 -1
  48. package/dist/core/fileSystem.js +175 -0
  49. package/dist/core/fileSystem.js.map +1 -1
  50. package/dist/core/templates.d.ts.map +1 -1
  51. package/dist/core/templates.js +652 -233
  52. package/dist/core/templates.js.map +1 -1
  53. package/package.json +5 -1
@@ -27,46 +27,162 @@ function getDashboardHtml() {
27
27
  <div class="meta-item"><span class="label">User Level</span><span id="user-level"></span></div>
28
28
  <div class="meta-item"><span class="label">Code Level</span><span id="code-level" class="badge"></span></div>
29
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>
30
32
  </div>
31
33
  </section>
32
34
 
33
- <section class="progress-section">
34
- <div class="section-header">
35
- <h2>Phases</h2>
36
- <span id="phase-counter" class="counter"></span>
37
- </div>
38
- <div class="progress-bar-wrap">
39
- <div id="progress-bar" class="progress-bar"></div>
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>
40
69
  </div>
41
- <div id="phases-list" class="phases-list"></div>
42
- </section>
43
70
 
44
- <div class="two-col">
45
71
  <section class="card">
46
- <h2>Recent Commits</h2>
47
- <ul id="commits-list" class="list"></ul>
72
+ <h2>Last Decisions</h2>
73
+ <ul id="decisions-list" class="list"></ul>
48
74
  </section>
49
75
 
50
76
  <section class="card">
51
- <h2>Known Bugs</h2>
52
- <ul id="bugs-list" class="list"></ul>
77
+ <h2>Project Depth</h2>
78
+ <div id="depth-grid" class="depth-grid"></div>
53
79
  </section>
54
80
  </div>
55
81
 
56
- <section class="card">
57
- <h2>Last Decisions</h2>
58
- <ul id="decisions-list" class="list"></ul>
59
- </section>
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>
60
166
 
61
167
  <footer class="footer">
62
- Powered by <strong>BrainForge</strong> — structured AI development
168
+ Powered by <strong>BrainForge v1.2</strong> — structured AI development
63
169
  </footer>
64
170
  </div>
65
171
 
66
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
+
67
184
  async function loadData() {
68
185
  try {
69
- // Use inlined data (file:// mode) or fetch (http:// mode via brainforge serve)
70
186
  let d = window.__BRAINFORGE_DATA__;
71
187
  if (!d) {
72
188
  const res = await fetch('data.json?t=' + Date.now());
@@ -74,42 +190,57 @@ function getDashboardHtml() {
74
190
  }
75
191
 
76
192
  document.title = 'BrainForge — ' + d.projectName;
77
- document.getElementById('project-name').textContent = d.projectName;
78
- document.getElementById('project-description').textContent = d.description || 'No description yet.';
79
- document.getElementById('project-type').textContent = d.projectType || '—';
80
- document.getElementById('project-stack').textContent = (d.stack || []).join(', ') || '—';
81
- document.getElementById('user-level').textContent = d.userLevel || '—';
82
- document.getElementById('code-level').textContent = d.codeLevel || '—';
83
- document.getElementById('git-status').textContent = d.gitStatus || '—';
84
- document.getElementById('updated-at').textContent = 'Updated: ' + new Date(d.updatedAt).toLocaleString();
85
-
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
86
207
  const done = (d.phases || []).filter(p => p.status === 'done').length;
87
208
  const total = d.totalPhases || d.phases?.length || 0;
88
- document.getElementById('phase-counter').textContent = done + ' / ' + total + ' done';
209
+ setText('phase-counter', done + ' / ' + total + ' done');
89
210
  const pct = total > 0 ? Math.round((done / total) * 100) : 0;
90
- document.getElementById('progress-bar').style.width = pct + '%';
91
- document.getElementById('progress-bar').textContent = pct + '%';
92
-
93
- const phasesList = document.getElementById('phases-list');
94
- (d.phases || []).forEach(p => {
95
- const div = document.createElement('div');
96
- div.className = 'phase-item ' + p.status;
97
- div.innerHTML = '<span class="phase-num">' + String(p.id).padStart(2,'0') + '</span>'
98
- + '<span class="phase-title">' + p.title + '</span>'
99
- + '<span class="phase-status ' + p.status + '">' + p.status + '</span>';
100
- phasesList.appendChild(div);
101
- });
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 || []);
102
217
 
103
218
  renderList('commits-list', d.recentCommits, 'No commits yet.');
104
219
  renderList('bugs-list', d.knownBugs, 'No bugs tracked.');
105
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
+
106
231
  } catch (e) {
107
- document.body.innerHTML += '<p style="color:red;padding:1rem">Error loading data.json: ' + e.message + '</p>';
232
+ document.body.innerHTML += '<p style="color:red;padding:1rem">Error loading data.json: ' + e.message + '. Run brainforge serve for live loading.</p>';
108
233
  }
109
234
  }
110
235
 
236
+ function setText(id, val) {
237
+ const el = document.getElementById(id);
238
+ if (el) el.textContent = val;
239
+ }
240
+
111
241
  function renderList(id, items, empty) {
112
242
  const el = document.getElementById(id);
243
+ if (!el) return;
113
244
  if (!items || items.length === 0) {
114
245
  el.innerHTML = '<li class="empty">' + empty + '</li>';
115
246
  return;
@@ -117,6 +248,142 @@ function getDashboardHtml() {
117
248
  el.innerHTML = items.map(i => '<li>' + i + '</li>').join('');
118
249
  }
119
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
+
120
387
  loadData();
121
388
  </script>
122
389
  </body>
@@ -149,11 +416,7 @@ body {
149
416
  min-height: 100vh;
150
417
  }
151
418
 
152
- .container {
153
- max-width: 1100px;
154
- margin: 0 auto;
155
- padding: 2rem 1.5rem;
156
- }
419
+ .container { max-width: 1100px; margin: 0 auto; padding: 2rem 1.5rem; }
157
420
 
158
421
  .header {
159
422
  display: flex;
@@ -162,13 +425,7 @@ body {
162
425
  margin-bottom: 2rem;
163
426
  }
164
427
 
165
- .logo {
166
- font-size: 1.4rem;
167
- font-weight: 700;
168
- color: var(--primary-light);
169
- letter-spacing: -0.5px;
170
- }
171
-
428
+ .logo { font-size: 1.4rem; font-weight: 700; color: var(--primary-light); letter-spacing: -0.5px; }
172
429
  .updated-at { color: var(--muted); font-size: 0.8rem; }
173
430
 
174
431
  .project-card {
@@ -181,12 +438,13 @@ body {
181
438
 
182
439
  h1 { font-size: 1.6rem; font-weight: 700; margin-bottom: 0.4rem; }
183
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; }
184
442
 
185
443
  .description { color: var(--muted); margin-bottom: 1.25rem; }
186
444
 
187
445
  .meta-grid {
188
446
  display: grid;
189
- grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
447
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
190
448
  gap: 0.75rem;
191
449
  }
192
450
 
@@ -212,7 +470,41 @@ h2 { font-size: 1.05rem; font-weight: 600; margin-bottom: 1rem; color: var(--pri
212
470
  width: fit-content;
213
471
  }
214
472
 
215
- .progress-section {
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 {
216
508
  background: var(--surface);
217
509
  border: 1px solid var(--border);
218
510
  border-radius: var(--radius);
@@ -220,13 +512,18 @@ h2 { font-size: 1.05rem; font-weight: 600; margin-bottom: 1rem; color: var(--pri
220
512
  margin-bottom: 1.5rem;
221
513
  }
222
514
 
223
- .section-header {
224
- display: flex;
225
- justify-content: space-between;
226
- align-items: center;
227
- margin-bottom: 0.75rem;
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;
228
524
  }
229
525
 
526
+ .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; }
230
527
  .counter { color: var(--muted); font-size: 0.85rem; }
231
528
 
232
529
  .progress-bar-wrap {
@@ -264,64 +561,198 @@ h2 { font-size: 1.05rem; font-weight: 600; margin-bottom: 1rem; color: var(--pri
264
561
  }
265
562
 
266
563
  .phase-item.done { border-left-color: var(--success); }
267
- .phase-item.in-progress { border-left-color: var(--primary); }
268
- .phase-item.pending { border-left-color: var(--border); }
564
+ .phase-item.in-progress { border-left-color: var(--warning); }
269
565
 
270
- .phase-num { color: var(--muted); font-size: 0.8rem; font-weight: 600; min-width: 24px; }
271
- .phase-title { flex: 1; font-size: 0.9rem; }
566
+ .phase-num { font-size: 0.8rem; color: var(--muted); min-width: 28px; }
567
+ .phase-title { flex: 1; }
272
568
 
273
569
  .phase-status {
274
570
  font-size: 0.72rem;
275
- font-weight: 600;
276
571
  padding: 2px 8px;
277
572
  border-radius: 20px;
278
- text-transform: capitalize;
573
+ font-weight: 600;
574
+ text-transform: uppercase;
575
+ background: var(--surface);
576
+ color: var(--muted);
279
577
  }
280
- .phase-status.done { background: #14532d; color: var(--success); }
281
- .phase-status.in-progress { background: #1e1b4b; color: var(--primary-light); }
282
- .phase-status.pending { background: var(--surface); color: var(--muted); }
283
578
 
284
- .two-col {
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 {
285
589
  display: grid;
286
- grid-template-columns: 1fr 1fr;
287
- gap: 1.5rem;
288
- margin-bottom: 1.5rem;
590
+ grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
591
+ gap: 0.75rem;
289
592
  }
290
593
 
291
- @media (max-width: 640px) { .two-col { grid-template-columns: 1fr; } }
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
+ }
292
603
 
293
- .card {
294
- background: var(--surface);
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);
295
649
  border: 1px solid var(--border);
296
650
  border-radius: var(--radius);
297
- padding: 1.5rem;
651
+ padding: 1rem;
298
652
  margin-bottom: 1.5rem;
299
653
  }
300
654
 
301
- .list {
302
- list-style: none;
655
+ .doc-viewer.hidden { display: none; }
656
+
657
+ .doc-viewer-header {
303
658
  display: flex;
304
- flex-direction: column;
305
- gap: 0.4rem;
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;
306
708
  }
307
709
 
308
- .list li {
309
- padding: 0.4rem 0.6rem;
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;
310
724
  background: var(--surface2);
311
- border-radius: 6px;
725
+ border-radius: 8px;
312
726
  font-size: 0.85rem;
313
- color: var(--text);
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;
314
746
  }
315
747
 
316
- .list li.empty { color: var(--muted); font-style: italic; background: none; padding: 0; }
748
+ .agent-title { font-weight: 600; font-size: 0.88rem; }
749
+ .agent-summary { font-size: 0.78rem; color: var(--muted); }
317
750
 
318
751
  .footer {
319
752
  text-align: center;
753
+ padding: 2rem 0 1rem;
320
754
  color: var(--muted);
321
- font-size: 0.8rem;
322
- padding-top: 1.5rem;
323
- border-top: 1px solid var(--border);
324
- margin-top: 1rem;
755
+ font-size: 0.82rem;
325
756
  }
326
757
  `;
327
758
  }