@timmeck/brain-core 2.36.22 → 2.36.24

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.
@@ -202,6 +202,8 @@ canvas{display:block;width:100%;height:100%}
202
202
  .btn{padding:6px 16px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--bg-card);color:var(--text);cursor:pointer;font-size:12px;transition:all .2s}
203
203
  .btn:hover{border-color:var(--cyan);color:var(--cyan)}
204
204
  .btn.btn-active{border-color:var(--green);color:var(--green);background:rgba(0,255,136,0.08)}
205
+ .lang-btn{padding:3px 10px;border-radius:20px;font-size:11px;font-weight:600;border:1px solid var(--border);background:rgba(100,140,255,0.04);color:var(--text-dim);cursor:pointer;transition:all .2s;letter-spacing:1px}
206
+ .lang-btn:hover{border-color:var(--cyan);color:var(--cyan)}
205
207
 
206
208
  /* ── Scrollbar ─────────────────────────────────────────── */
207
209
  ::-webkit-scrollbar{width:6px}
@@ -229,14 +231,14 @@ canvas{display:block;width:100%;height:100%}
229
231
  <div class="sidebar-brand">COMMAND CENTER<span>Brain Ecosystem</span></div>
230
232
  <div class="nav-section">Views</div>
231
233
  <div class="nav-item active" data-page="overview"><span class="nav-icon">&#x1F30D;</span><span class="nav-label">Ecosystem</span></div>
232
- <div class="nav-item" data-page="learning"><span class="nav-icon">&#x1F9E0;</span><span class="nav-label">Lern-Kreislauf</span></div>
234
+ <div class="nav-item" data-page="learning"><span class="nav-icon">&#x1F9E0;</span><span class="nav-label" data-t="Lern-Kreislauf">Lern-Kreislauf</span></div>
233
235
  <div class="nav-item" data-page="trading"><span class="nav-icon">&#x1F4C8;</span><span class="nav-label">Trading Flow</span></div>
234
236
  <div class="nav-item" data-page="marketing"><span class="nav-icon">&#x1F4E3;</span><span class="nav-label">Marketing Flow</span></div>
235
237
  <div class="nav-section">System</div>
236
238
  <div class="nav-item" data-page="crossbrain"><span class="nav-icon">&#x1F517;</span><span class="nav-label">Cross-Brain</span></div>
237
239
  <div class="nav-item" data-page="debates"><span class="nav-icon">&#x2696;</span><span class="nav-label">Debates</span></div>
238
- <div class="nav-item" data-page="activity"><span class="nav-icon">&#x26A1;</span><span class="nav-label">Aktivität</span></div>
239
- <div class="nav-item" data-page="infra"><span class="nav-icon">&#x2699;</span><span class="nav-label">Infrastruktur</span></div>
240
+ <div class="nav-item" data-page="activity"><span class="nav-icon">&#x26A1;</span><span class="nav-label" data-t="Aktivität">Aktivität</span></div>
241
+ <div class="nav-item" data-page="infra"><span class="nav-icon">&#x2699;</span><span class="nav-label" data-t="Infrastruktur">Infrastruktur</span></div>
240
242
  </div>
241
243
 
242
244
  <!-- ── Main ──────────────────────────────────────────── -->
@@ -250,6 +252,7 @@ canvas{display:block;width:100%;height:100%}
250
252
  </div>
251
253
  <span class="badge badge-off" id="healthBadge">--</span>
252
254
  <span class="badge badge-off" id="connectionBadge">Connecting...</span>
255
+ <button class="lang-btn" id="langToggle" onclick="setLang(currentLang==='en'?'de':'en')">EN</button>
253
256
  </div>
254
257
  </div>
255
258
 
@@ -258,11 +261,11 @@ canvas{display:block;width:100%;height:100%}
258
261
  <div class="page active" id="page-overview">
259
262
  <!-- Quick Actions -->
260
263
  <div class="section">
261
- <div class="section-title"><span class="icon">&#x1F3AE;</span> Schnellaktionen</div>
264
+ <div class="section-title"><span class="icon">&#x1F3AE;</span> <span data-t="Schnellaktionen">Schnellaktionen</span></div>
262
265
  <div class="quick-actions" id="quickActions">
263
- <button class="action-btn" data-action="learning-cycle"><span class="action-icon">&#x1F504;</span> Lernzyklus starten</button>
266
+ <button class="action-btn" data-action="learning-cycle"><span class="action-icon">&#x1F504;</span> <span data-t="Lernzyklus starten">Lernzyklus starten</span></button>
264
267
  <button class="action-btn" data-action="borg-sync"><span class="action-icon">&#x1F47E;</span> Borg Sync</button>
265
- <button class="action-btn" data-action="tech-scan"><span class="action-icon">&#x1F4E1;</span> Tech-Radar Scan</button>
268
+ <button class="action-btn" data-action="tech-scan"><span class="action-icon">&#x1F4E1;</span> <span data-t="Tech-Radar Scan">Tech-Radar Scan</span></button>
266
269
  <button class="action-btn" data-action="health-check"><span class="action-icon">&#x1F3E5;</span> Health Check</button>
267
270
  </div>
268
271
  </div>
@@ -288,13 +291,13 @@ canvas{display:block;width:100%;height:100%}
288
291
  </div>
289
292
  </div>
290
293
  <div class="section">
291
- <div class="section-title"><span class="icon">&#x1F4CA;</span> KI-Nutzung</div>
294
+ <div class="section-title"><span class="icon">&#x1F4CA;</span> <span data-t="KI-Nutzung">KI-Nutzung</span></div>
292
295
  <div class="card" id="llmCard"><div class="empty">Warte auf KI-Daten...</div></div>
293
296
  </div>
294
297
  </div>
295
298
 
296
299
  <div class="section">
297
- <div class="section-title"><span class="icon">&#x1F4AD;</span> Brain denkt gerade... <span id="thoughtCount" style="color:var(--text-dim);font-weight:400;font-size:12px"></span></div>
300
+ <div class="section-title"><span class="icon">&#x1F4AD;</span> <span data-t="Brain denkt gerade...">Brain denkt gerade...</span> <span id="thoughtCount" style="color:var(--text-dim);font-weight:400;font-size:12px"></span></div>
298
301
  <div class="card" style="padding:0">
299
302
  <div class="thought-stream" id="thoughtStream"><div class="empty">Warte auf Gedanken...</div></div>
300
303
  </div>
@@ -303,14 +306,14 @@ canvas{display:block;width:100%;height:100%}
303
306
 
304
307
  <!-- Error Log -->
305
308
  <div class="section">
306
- <div class="section-title"><span class="icon">&#x26A0;</span> Letzte Fehler & Warnungen <span id="errorCount" style="color:var(--text-dim);font-weight:400;font-size:12px"></span></div>
309
+ <div class="section-title"><span class="icon">&#x26A0;</span> <span data-t="Letzte Fehler & Warnungen">Letzte Fehler & Warnungen</span> <span id="errorCount" style="color:var(--text-dim);font-weight:400;font-size:12px"></span></div>
307
310
  <div class="card" style="padding:0">
308
311
  <div class="error-feed" id="errorFeed"><div class="empty">Keine Fehler — alles läuft!</div></div>
309
312
  </div>
310
313
  </div>
311
314
 
312
315
  <div class="section">
313
- <div class="section-title"><span class="icon">&#x1F310;</span> Peer Verbindungen</div>
316
+ <div class="section-title"><span class="icon">&#x1F310;</span> <span data-t="Peer Verbindungen">Peer Verbindungen</span></div>
314
317
  <div class="card canvas-wrap" style="height:180px">
315
318
  <canvas id="peerCanvas"></canvas>
316
319
  </div>
@@ -320,30 +323,30 @@ canvas{display:block;width:100%;height:100%}
320
323
  <!-- ════ Page 2: Lern-Kreislauf ═════════════════════ -->
321
324
  <div class="page" id="page-learning">
322
325
  <div class="section">
323
- <div class="section-title"><span class="icon">&#x1F504;</span> So lernt Brain — Der Kreislauf</div>
324
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Daten kommen rein, Brain analysiert sie, bildet Hypothesen, testet sie als Experimente und macht daraus Wissen. Dieser Kreislauf läuft ständig.</p>
326
+ <div class="section-title"><span class="icon">&#x1F504;</span> <span data-t="So lernt Brain — Der Kreislauf">So lernt Brain — Der Kreislauf</span></div>
327
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Daten kommen rein, Brain analysiert sie, bildet Hypothesen, testet sie als Experimente und macht daraus Wissen. Dieser Kreislauf läuft ständig.">Daten kommen rein, Brain analysiert sie, bildet Hypothesen, testet sie als Experimente und macht daraus Wissen. Dieser Kreislauf läuft ständig.</p>
325
328
  <div class="pipeline" id="learnPipeline">
326
- <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F4E5;</div><div class="pipe-label">Daten rein</div><div class="pipe-value" id="lp-data">0</div></div></div>
329
+ <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F4E5;</div><div class="pipe-label" data-t="Daten rein">Daten rein</div><div class="pipe-value" id="lp-data">0</div></div></div>
327
330
  <div class="pipe-arrow">&#x27A1;</div>
328
- <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F50D;</div><div class="pipe-label">Analysieren</div><div class="pipe-value" id="lp-analysis">0</div></div></div>
331
+ <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F50D;</div><div class="pipe-label" data-t="Analysieren">Analysieren</div><div class="pipe-value" id="lp-analysis">0</div></div></div>
329
332
  <div class="pipe-arrow">&#x27A1;</div>
330
- <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F4A1;</div><div class="pipe-label">Ideen bilden</div><div class="pipe-value" id="lp-hypotheses">0</div></div></div>
333
+ <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F4A1;</div><div class="pipe-label" data-t="Ideen bilden">Ideen bilden</div><div class="pipe-value" id="lp-hypotheses">0</div></div></div>
331
334
  <div class="pipe-arrow">&#x27A1;</div>
332
- <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F9EA;</div><div class="pipe-label">Ausprobieren</div><div class="pipe-value" id="lp-experiments">0</div></div></div>
335
+ <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F9EA;</div><div class="pipe-label" data-t="Ausprobieren">Ausprobieren</div><div class="pipe-value" id="lp-experiments">0</div></div></div>
333
336
  <div class="pipe-arrow">&#x27A1;</div>
334
- <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F4DC;</div><div class="pipe-label">Wissen merken</div><div class="pipe-value" id="lp-principles">0</div></div></div>
337
+ <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x1F4DC;</div><div class="pipe-label" data-t="Wissen merken">Wissen merken</div><div class="pipe-value" id="lp-principles">0</div></div></div>
335
338
  <div class="pipe-arrow">&#x27A1;</div>
336
- <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x26A1;</div><div class="pipe-label">Umsetzen</div><div class="pipe-value" id="lp-actions">0</div></div></div>
339
+ <div class="pipe-stage"><div class="pipe-box"><div class="pipe-icon">&#x26A1;</div><div class="pipe-label" data-t="Umsetzen">Umsetzen</div><div class="pipe-value" id="lp-actions">0</div></div></div>
337
340
  </div>
338
341
  </div>
339
342
 
340
343
  <!-- Engine Dependency Flow -->
341
344
  <div class="section">
342
- <div class="section-title"><span class="icon">&#x1F500;</span> Wie die Engines zusammenarbeiten</div>
343
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Jede Engine hat eine Aufgabe. Zusammen bilden sie eine Kette — von der Beobachtung bis zur Aktion.</p>
345
+ <div class="section-title"><span class="icon">&#x1F500;</span> <span data-t="Wie die Engines zusammenarbeiten">Wie die Engines zusammenarbeiten</span></div>
346
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Jede Engine hat eine Aufgabe. Zusammen bilden sie eine Kette — von der Beobachtung bis zur Aktion.">Jede Engine hat eine Aufgabe. Zusammen bilden sie eine Kette — von der Beobachtung bis zur Aktion.</p>
344
347
  <div class="dep-flow" id="engineDependencyFlow">
345
348
  <div class="dep-group">
346
- <div class="dep-group-title">&#x1F441; Beobachten</div>
349
+ <div class="dep-group-title">&#x1F441; <span data-t="Beobachten">Beobachten</span></div>
347
350
  <div class="dep-engine">DataScout</div>
348
351
  <div class="dep-engine">TechRadar</div>
349
352
  <div class="dep-engine">SignalScanner</div>
@@ -351,7 +354,7 @@ canvas{display:block;width:100%;height:100%}
351
354
  </div>
352
355
  <div class="dep-arrow">&#x27A1;</div>
353
356
  <div class="dep-group">
354
- <div class="dep-group-title">&#x1F9E0; Verstehen</div>
357
+ <div class="dep-group-title">&#x1F9E0; <span data-t="Verstehen">Verstehen</span></div>
355
358
  <div class="dep-engine">CausalEngine</div>
356
359
  <div class="dep-engine">PatternEngine</div>
357
360
  <div class="dep-engine">Curiosity</div>
@@ -359,28 +362,28 @@ canvas{display:block;width:100%;height:100%}
359
362
  </div>
360
363
  <div class="dep-arrow">&#x27A1;</div>
361
364
  <div class="dep-group">
362
- <div class="dep-group-title">&#x1F4A1; Ideen</div>
365
+ <div class="dep-group-title">&#x1F4A1; <span data-t="Ideen">Ideen</span></div>
363
366
  <div class="dep-engine">HypothesisEngine</div>
364
367
  <div class="dep-engine">DreamEngine</div>
365
368
  <div class="dep-engine">DebateEngine</div>
366
369
  </div>
367
370
  <div class="dep-arrow">&#x27A1;</div>
368
371
  <div class="dep-group">
369
- <div class="dep-group-title">&#x1F9EA; Testen</div>
372
+ <div class="dep-group-title">&#x1F9EA; <span data-t="Testen">Testen</span></div>
370
373
  <div class="dep-engine">ExperimentEngine</div>
371
374
  <div class="dep-engine">SimulationEngine</div>
372
375
  <div class="dep-engine">Prediction</div>
373
376
  </div>
374
377
  <div class="dep-arrow">&#x27A1;</div>
375
378
  <div class="dep-group">
376
- <div class="dep-group-title">&#x1F4DA; Wissen</div>
379
+ <div class="dep-group-title">&#x1F4DA; <span data-t="Wissen">Wissen</span></div>
377
380
  <div class="dep-engine">KnowledgeDistiller</div>
378
381
  <div class="dep-engine">MemoryPalace</div>
379
382
  <div class="dep-engine">ResearchJournal</div>
380
383
  </div>
381
384
  <div class="dep-arrow">&#x27A1;</div>
382
385
  <div class="dep-group">
383
- <div class="dep-group-title">&#x26A1; Handeln</div>
386
+ <div class="dep-group-title">&#x26A1; <span data-t="Handeln">Handeln</span></div>
384
387
  <div class="dep-engine">SelfMod</div>
385
388
  <div class="dep-engine">GoalEngine</div>
386
389
  <div class="dep-engine">Strategy</div>
@@ -391,27 +394,27 @@ canvas{display:block;width:100%;height:100%}
391
394
 
392
395
  <!-- Knowledge Growth -->
393
396
  <div class="section">
394
- <div class="section-title"><span class="icon">&#x1F4C8;</span> Wissens-Wachstum — Wird Brain schlauer?</div>
397
+ <div class="section-title"><span class="icon">&#x1F4C8;</span> <span data-t="Wissens-Wachstum — Wird Brain schlauer?">Wissens-Wachstum — Wird Brain schlauer?</span></div>
395
398
  <div class="card">
396
399
  <div class="grid grid-4" id="knowledgeTotals">
397
- <div style="text-align:center"><div class="card-value" id="kn-principles" style="color:var(--cyan)">0</div><div class="card-sub">Regeln gelernt</div></div>
398
- <div style="text-align:center"><div class="card-value" id="kn-hypotheses" style="color:var(--yellow)">0</div><div class="card-sub">Hypothesen getestet</div></div>
399
- <div style="text-align:center"><div class="card-value" id="kn-experiments" style="color:var(--green)">0</div><div class="card-sub">Experimente gemacht</div></div>
400
- <div style="text-align:center"><div class="card-value" id="kn-errors" style="color:var(--red)">0</div><div class="card-sub">Fehler gelöst</div></div>
400
+ <div style="text-align:center"><div class="card-value" id="kn-principles" style="color:var(--cyan)">0</div><div class="card-sub" data-t="Regeln gelernt">Regeln gelernt</div></div>
401
+ <div style="text-align:center"><div class="card-value" id="kn-hypotheses" style="color:var(--yellow)">0</div><div class="card-sub" data-t="Hypothesen getestet">Hypothesen getestet</div></div>
402
+ <div style="text-align:center"><div class="card-value" id="kn-experiments" style="color:var(--green)">0</div><div class="card-sub" data-t="Experimente gemacht">Experimente gemacht</div></div>
403
+ <div style="text-align:center"><div class="card-value" id="kn-errors" style="color:var(--red)">0</div><div class="card-sub" data-t="Fehler gelöst">Fehler gelöst</div></div>
401
404
  </div>
402
405
  <div class="chart-wrap" id="knowledgeChart">
403
406
  <svg id="knowledgeSvg" viewBox="0 0 600 180" preserveAspectRatio="none"></svg>
404
407
  </div>
405
408
  <div style="display:flex;gap:16px;justify-content:center;font-size:10px;color:var(--text-dim)">
406
- <span><span style="color:var(--cyan)">&#x2B24;</span> Regeln</span>
407
- <span><span style="color:var(--green)">&#x2B24;</span> Lösungen</span>
408
- <span><span style="color:var(--red)">&#x2B24;</span> Fehler</span>
409
+ <span><span style="color:var(--cyan)">&#x2B24;</span> <span data-t="Regeln">Regeln</span></span>
410
+ <span><span style="color:var(--green)">&#x2B24;</span> <span data-t="Lösungen">Lösungen</span></span>
411
+ <span><span style="color:var(--red)">&#x2B24;</span> <span data-t="Fehler">Fehler</span></span>
409
412
  </div>
410
413
  </div>
411
414
  </div>
412
415
 
413
416
  <div class="section">
414
- <div class="section-title"><span class="icon">&#x1F3ED;</span> Engine Stationen</div>
417
+ <div class="section-title"><span class="icon">&#x1F3ED;</span> <span data-t="Engine Stationen">Engine Stationen</span></div>
415
418
  <div class="engine-grid" id="brainEngineGrid"><div class="empty">Loading...</div></div>
416
419
  </div>
417
420
  </div>
@@ -419,24 +422,24 @@ canvas{display:block;width:100%;height:100%}
419
422
  <!-- ════ Page 3: Trading Flow ═══════════════════════ -->
420
423
  <div class="page" id="page-trading">
421
424
  <div class="section">
422
- <div class="section-title"><span class="icon">&#x1F4C8;</span> So tradet Trading-Brain</div>
423
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Signale kommen rein, werden analysiert, als Paper Trade getestet und das Ergebnis fließt zurück ins Lernen.</p>
425
+ <div class="section-title"><span class="icon">&#x1F4C8;</span> <span data-t="So tradet Trading-Brain">So tradet Trading-Brain</span></div>
426
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Signale kommen rein, werden analysiert, als Paper Trade getestet und das Ergebnis fließt zurück ins Lernen.">Signale kommen rein, werden analysiert, als Paper Trade getestet und das Ergebnis fließt zurück ins Lernen.</p>
424
427
  <div class="pipeline">
425
- <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F4E1;</div><div class="pipe-label">Signale</div><div class="pipe-value" id="tp-signals" style="color:var(--green)">0</div></div></div>
428
+ <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F4E1;</div><div class="pipe-label" data-t="Signale">Signale</div><div class="pipe-value" id="tp-signals" style="color:var(--green)">0</div></div></div>
426
429
  <div class="pipe-arrow" style="color:var(--green)">&#x27A1;</div>
427
- <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F50E;</div><div class="pipe-label">Analyse</div><div class="pipe-value" id="tp-analysis" style="color:var(--green)">0</div></div></div>
430
+ <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F50E;</div><div class="pipe-label" data-t="Analyse">Analyse</div><div class="pipe-value" id="tp-analysis" style="color:var(--green)">0</div></div></div>
428
431
  <div class="pipe-arrow" style="color:var(--green)">&#x27A1;</div>
429
432
  <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F4B5;</div><div class="pipe-label">Paper Trade</div><div class="pipe-value" id="tp-trades" style="color:var(--green)">0</div></div></div>
430
433
  <div class="pipe-arrow" style="color:var(--green)">&#x27A1;</div>
431
- <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F4CA;</div><div class="pipe-label">Ergebnis</div><div class="pipe-value" id="tp-pnl" style="color:var(--green)">$0</div></div></div>
434
+ <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F4CA;</div><div class="pipe-label" data-t="Ergebnis">Ergebnis</div><div class="pipe-value" id="tp-pnl" style="color:var(--green)">$0</div></div></div>
432
435
  <div class="pipe-arrow" style="color:var(--green)">&#x27A1;</div>
433
- <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F393;</div><div class="pipe-label">Lernen</div><div class="pipe-value" id="tp-learned" style="color:var(--green)">0</div></div></div>
436
+ <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(0,255,136,0.2)"><div class="pipe-icon">&#x1F393;</div><div class="pipe-label" data-t="Lernen">Lernen</div><div class="pipe-value" id="tp-learned" style="color:var(--green)">0</div></div></div>
434
437
  </div>
435
438
  </div>
436
439
  <div class="grid grid-3">
437
- <div class="card"><div class="card-title">Equity</div><div class="card-value" id="tradingEquity" style="color:var(--green)">--</div><div class="card-sub">Paper Trading Guthaben</div></div>
438
- <div class="card"><div class="card-title">Win Rate</div><div class="card-value" id="tradingWinRate" style="color:var(--green)">--</div><div class="card-sub">Gewinnrate aller Trades</div></div>
439
- <div class="card"><div class="card-title">Offene Positionen</div><div class="card-value" id="tradingPositions" style="color:var(--green)">--</div><div class="card-sub">Aktive Trades gerade</div></div>
440
+ <div class="card"><div class="card-title">Equity</div><div class="card-value" id="tradingEquity" style="color:var(--green)">--</div><div class="card-sub" data-t="Paper Trading Guthaben">Paper Trading Guthaben</div></div>
441
+ <div class="card"><div class="card-title">Win Rate</div><div class="card-value" id="tradingWinRate" style="color:var(--green)">--</div><div class="card-sub" data-t="Gewinnrate aller Trades">Gewinnrate aller Trades</div></div>
442
+ <div class="card"><div class="card-title" data-t="Offene Positionen">Offene Positionen</div><div class="card-value" id="tradingPositions" style="color:var(--green)">--</div><div class="card-sub" data-t="Aktive Trades gerade">Aktive Trades gerade</div></div>
440
443
  </div>
441
444
  <div class="section" style="margin-top:16px">
442
445
  <div class="section-title"><span class="icon">&#x1F3ED;</span> Trading Engines</div>
@@ -447,22 +450,22 @@ canvas{display:block;width:100%;height:100%}
447
450
  <!-- ════ Page 4: Marketing Flow ═════════════════════ -->
448
451
  <div class="page" id="page-marketing">
449
452
  <div class="section">
450
- <div class="section-title"><span class="icon">&#x1F4E3;</span> So lernt Marketing-Brain</div>
451
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Posts werden veröffentlicht, das Engagement wird gemessen, Muster erkannt und die Strategie angepasst.</p>
453
+ <div class="section-title"><span class="icon">&#x1F4E3;</span> <span data-t="So lernt Marketing-Brain">So lernt Marketing-Brain</span></div>
454
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Posts werden veröffentlicht, das Engagement wird gemessen, Muster erkannt und die Strategie angepasst.">Posts werden veröffentlicht, das Engagement wird gemessen, Muster erkannt und die Strategie angepasst.</p>
452
455
  <div class="pipeline">
453
456
  <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(255,68,204,0.2)"><div class="pipe-icon">&#x270D;</div><div class="pipe-label">Posts</div><div class="pipe-value" id="mp-posts" style="color:var(--magenta)">0</div></div></div>
454
457
  <div class="pipe-arrow" style="color:var(--magenta)">&#x27A1;</div>
455
458
  <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(255,68,204,0.2)"><div class="pipe-icon">&#x1F4CA;</div><div class="pipe-label">Engagement</div><div class="pipe-value" id="mp-engagement" style="color:var(--magenta)">0</div></div></div>
456
459
  <div class="pipe-arrow" style="color:var(--magenta)">&#x27A1;</div>
457
- <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(255,68,204,0.2)"><div class="pipe-icon">&#x1F50D;</div><div class="pipe-label">Muster</div><div class="pipe-value" id="mp-patterns" style="color:var(--magenta)">0</div></div></div>
460
+ <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(255,68,204,0.2)"><div class="pipe-icon">&#x1F50D;</div><div class="pipe-label" data-t="Muster">Muster</div><div class="pipe-value" id="mp-patterns" style="color:var(--magenta)">0</div></div></div>
458
461
  <div class="pipe-arrow" style="color:var(--magenta)">&#x27A1;</div>
459
- <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(255,68,204,0.2)"><div class="pipe-icon">&#x1F3AF;</div><div class="pipe-label">Strategie</div><div class="pipe-value" id="mp-campaigns" style="color:var(--magenta)">0</div></div></div>
462
+ <div class="pipe-stage"><div class="pipe-box" style="border-color:rgba(255,68,204,0.2)"><div class="pipe-icon">&#x1F3AF;</div><div class="pipe-label" data-t="Strategie">Strategie</div><div class="pipe-value" id="mp-campaigns" style="color:var(--magenta)">0</div></div></div>
460
463
  </div>
461
464
  </div>
462
465
  <div class="grid grid-3">
463
- <div class="card"><div class="card-title">Top Content</div><div class="card-value" id="marketingTopContent" style="color:var(--magenta)">--</div><div class="card-sub">Bester Post</div></div>
464
- <div class="card"><div class="card-title">Kampagnen</div><div class="card-value" id="marketingCampaigns" style="color:var(--magenta)">--</div><div class="card-sub">Aktive Kampagnen</div></div>
465
- <div class="card"><div class="card-title">Audience</div><div class="card-value" id="marketingAudience" style="color:var(--magenta)">--</div><div class="card-sub">Zielgruppe</div></div>
466
+ <div class="card"><div class="card-title">Top Content</div><div class="card-value" id="marketingTopContent" style="color:var(--magenta)">--</div><div class="card-sub" data-t="Bester Post">Bester Post</div></div>
467
+ <div class="card"><div class="card-title" data-t="Kampagnen">Kampagnen</div><div class="card-value" id="marketingCampaigns" style="color:var(--magenta)">--</div><div class="card-sub" data-t="Aktive Kampagnen">Aktive Kampagnen</div></div>
468
+ <div class="card"><div class="card-title">Audience</div><div class="card-value" id="marketingAudience" style="color:var(--magenta)">--</div><div class="card-sub" data-t="Zielgruppe">Zielgruppe</div></div>
466
469
  </div>
467
470
  <div class="section" style="margin-top:16px">
468
471
  <div class="section-title"><span class="icon">&#x1F3ED;</span> Marketing Engines</div>
@@ -473,17 +476,17 @@ canvas{display:block;width:100%;height:100%}
473
476
  <!-- ════ Page 5: Cross-Brain & Borg ═════════════════ -->
474
477
  <div class="page" id="page-crossbrain">
475
478
  <div class="section">
476
- <div class="section-title"><span class="icon">&#x1F517;</span> So kommunizieren die Brains</div>
477
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Die drei Brains tauschen ständig Nachrichten aus. Jeder fliegende Punkt ist eine Nachricht. Lila = Borg-Wissens-Sync.</p>
479
+ <div class="section-title"><span class="icon">&#x1F517;</span> <span data-t="So kommunizieren die Brains">So kommunizieren die Brains</span></div>
480
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Die drei Brains tauschen ständig Nachrichten aus. Jeder fliegende Punkt ist eine Nachricht. Lila = Borg-Wissens-Sync.">Die drei Brains tauschen ständig Nachrichten aus. Jeder fliegende Punkt ist eine Nachricht. Lila = Borg-Wissens-Sync.</p>
478
481
  <div class="card canvas-wrap" style="height:280px">
479
482
  <canvas id="crossBrainCanvas"></canvas>
480
483
  </div>
481
484
  </div>
482
485
  <div class="grid grid-2">
483
486
  <div class="section">
484
- <div class="section-title"><span class="icon">&#x1F47E;</span> Borg Sync — Geteiltes Wissen</div>
487
+ <div class="section-title"><span class="icon">&#x1F47E;</span> <span data-t="Borg Sync — Geteiltes Wissen">Borg Sync — Geteiltes Wissen</span></div>
485
488
  <div class="card" id="borgCard">
486
- <p style="font-size:11px;color:var(--text-dim);margin-bottom:10px">Borg synchronisiert Wissen zwischen allen Brains. Was einer lernt, wissen alle.</p>
489
+ <p style="font-size:11px;color:var(--text-dim);margin-bottom:10px" data-t="Borg synchronisiert Wissen zwischen allen Brains. Was einer lernt, wissen alle.">Borg synchronisiert Wissen zwischen allen Brains. Was einer lernt, wissen alle.</p>
487
490
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">
488
491
  <div>
489
492
  <div class="card-title" style="margin-bottom:4px">Collective Sync</div>
@@ -495,12 +498,12 @@ canvas{display:block;width:100%;height:100%}
495
498
  </div>
496
499
  </div>
497
500
  <div class="section">
498
- <div class="section-title"><span class="icon">&#x1F4DC;</span> Korrelationen — Was hängt zusammen?</div>
501
+ <div class="section-title"><span class="icon">&#x1F4DC;</span> <span data-t="Korrelationen — Was hängt zusammen?">Korrelationen — Was hängt zusammen?</span></div>
499
502
  <div class="card"><div id="correlationList"><div class="empty">Noch keine Korrelationen gefunden</div></div></div>
500
503
  </div>
501
504
  </div>
502
505
  <div class="section">
503
- <div class="section-title"><span class="icon">&#x1F4C3;</span> Sync Verlauf</div>
506
+ <div class="section-title"><span class="icon">&#x1F4C3;</span> <span data-t="Sync Verlauf">Sync Verlauf</span></div>
504
507
  <div class="card"><div id="borgHistory"><div class="empty">Noch kein Sync passiert</div></div></div>
505
508
  </div>
506
509
  </div>
@@ -509,13 +512,13 @@ canvas{display:block;width:100%;height:100%}
509
512
  <div class="page" id="page-activity">
510
513
  <!-- Self-Modification -->
511
514
  <div class="section">
512
- <div class="section-title"><span class="icon">&#x1F527;</span> Brain verbessert sich selbst</div>
513
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Brain erkennt Probleme im eigenen Code und schlägt Verbesserungen vor. Jede Änderung wird erst getestet, bevor sie angewendet wird.</p>
515
+ <div class="section-title"><span class="icon">&#x1F527;</span> <span data-t="Brain verbessert sich selbst">Brain verbessert sich selbst</span></div>
516
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Brain erkennt Probleme im eigenen Code und schlägt Verbesserungen vor. Jede Änderung wird erst getestet, bevor sie angewendet wird.">Brain erkennt Probleme im eigenen Code und schlägt Verbesserungen vor. Jede Änderung wird erst getestet, bevor sie angewendet wird.</p>
514
517
  <div class="grid grid-4" id="selfModStats">
515
- <div class="card" style="text-align:center"><div class="card-value" id="sm-total" style="color:var(--cyan)">0</div><div class="card-sub">Vorschläge insgesamt</div></div>
516
- <div class="card" style="text-align:center"><div class="card-value" id="sm-applied" style="color:var(--green)">0</div><div class="card-sub">Erfolgreich angewendet</div></div>
517
- <div class="card" style="text-align:center"><div class="card-value" id="sm-testing" style="color:var(--yellow)">0</div><div class="card-sub">Wird gerade getestet</div></div>
518
- <div class="card" style="text-align:center"><div class="card-value" id="sm-failed" style="color:var(--red)">0</div><div class="card-sub">Fehlgeschlagen</div></div>
518
+ <div class="card" style="text-align:center"><div class="card-value" id="sm-total" style="color:var(--cyan)">0</div><div class="card-sub" data-t="Vorschläge insgesamt">Vorschläge insgesamt</div></div>
519
+ <div class="card" style="text-align:center"><div class="card-value" id="sm-applied" style="color:var(--green)">0</div><div class="card-sub" data-t="Erfolgreich angewendet">Erfolgreich angewendet</div></div>
520
+ <div class="card" style="text-align:center"><div class="card-value" id="sm-testing" style="color:var(--yellow)">0</div><div class="card-sub" data-t="Wird gerade getestet">Wird gerade getestet</div></div>
521
+ <div class="card" style="text-align:center"><div class="card-value" id="sm-failed" style="color:var(--red)">0</div><div class="card-sub" data-t="Fehlgeschlagen">Fehlgeschlagen</div></div>
519
522
  </div>
520
523
  <div class="card" style="padding:0;margin-top:12px">
521
524
  <div style="max-height:300px;overflow-y:auto" id="selfModFeed"><div class="empty">Brain hat sich noch nicht selbst verbessert</div></div>
@@ -524,12 +527,12 @@ canvas{display:block;width:100%;height:100%}
524
527
 
525
528
  <!-- Mission Tracker -->
526
529
  <div class="section">
527
- <div class="section-title"><span class="icon">&#x1F680;</span> Aktive Recherche-Missionen</div>
528
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Brain forscht eigenständig zu Themen. Jede Mission durchläuft 5 Phasen: Aufteilen, Sammeln, Hypothesen bilden, Analysieren, Zusammenfassen.</p>
530
+ <div class="section-title"><span class="icon">&#x1F680;</span> <span data-t="Aktive Recherche-Missionen">Aktive Recherche-Missionen</span></div>
531
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Brain forscht eigenständig zu Themen. Jede Mission durchläuft 5 Phasen: Aufteilen, Sammeln, Hypothesen bilden, Analysieren, Zusammenfassen.">Brain forscht eigenständig zu Themen. Jede Mission durchläuft 5 Phasen: Aufteilen, Sammeln, Hypothesen bilden, Analysieren, Zusammenfassen.</p>
529
532
  <div class="grid grid-3" id="missionStats">
530
- <div class="card" style="text-align:center"><div class="card-value" id="ms-active" style="color:var(--cyan)">0</div><div class="card-sub">Aktive Missionen</div></div>
531
- <div class="card" style="text-align:center"><div class="card-value" id="ms-completed" style="color:var(--green)">0</div><div class="card-sub">Abgeschlossen</div></div>
532
- <div class="card" style="text-align:center"><div class="card-value" id="ms-sources" style="color:var(--purple)">0</div><div class="card-sub">Quellen gesammelt</div></div>
533
+ <div class="card" style="text-align:center"><div class="card-value" id="ms-active" style="color:var(--cyan)">0</div><div class="card-sub" data-t="Aktive Missionen">Aktive Missionen</div></div>
534
+ <div class="card" style="text-align:center"><div class="card-value" id="ms-completed" style="color:var(--green)">0</div><div class="card-sub" data-t="Abgeschlossen">Abgeschlossen</div></div>
535
+ <div class="card" style="text-align:center"><div class="card-value" id="ms-sources" style="color:var(--purple)">0</div><div class="card-sub" data-t="Quellen gesammelt">Quellen gesammelt</div></div>
533
536
  </div>
534
537
  <div id="missionList" style="margin-top:12px"><div class="empty">Keine aktiven Missionen</div></div>
535
538
  </div>
@@ -540,32 +543,32 @@ canvas{display:block;width:100%;height:100%}
540
543
  <!-- Debate Engine Status -->
541
544
  <div class="section">
542
545
  <div class="section-title"><span class="icon">&#x2696;</span> Debate Engine</div>
543
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Multi-Perspektiven-Debatten zu Schlüsselfragen. Jeder Brain liefert seine Sichtweise basierend auf Prinzipien, Hypothesen und Vorhersagen.</p>
546
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Multi-Perspektiven-Debatten zu Schlüsselfragen. Jeder Brain liefert seine Sichtweise basierend auf Prinzipien, Hypothesen und Vorhersagen.">Multi-Perspektiven-Debatten zu Schlüsselfragen. Jeder Brain liefert seine Sichtweise basierend auf Prinzipien, Hypothesen und Vorhersagen.</p>
544
547
  <div class="grid grid-4" id="debateStats">
545
- <div class="card" style="text-align:center"><div class="card-value" id="db-total" style="color:var(--cyan)">0</div><div class="card-sub">Debatten gesamt</div></div>
546
- <div class="card" style="text-align:center"><div class="card-value" id="db-open" style="color:var(--yellow)">0</div><div class="card-sub">Offen</div></div>
547
- <div class="card" style="text-align:center"><div class="card-value" id="db-synthesized" style="color:var(--green)">0</div><div class="card-sub">Synthesiert</div></div>
548
+ <div class="card" style="text-align:center"><div class="card-value" id="db-total" style="color:var(--cyan)">0</div><div class="card-sub" data-t="Debatten gesamt">Debatten gesamt</div></div>
549
+ <div class="card" style="text-align:center"><div class="card-value" id="db-open" style="color:var(--yellow)">0</div><div class="card-sub" data-t="Offen">Offen</div></div>
550
+ <div class="card" style="text-align:center"><div class="card-value" id="db-synthesized" style="color:var(--green)">0</div><div class="card-sub" data-t="Synthesiert">Synthesiert</div></div>
548
551
  <div class="card" style="text-align:center"><div class="card-value" id="db-challenges" style="color:var(--red)">0</div><div class="card-sub">Challenges</div></div>
549
552
  </div>
550
553
  </div>
551
554
 
552
555
  <!-- Recent Debates -->
553
556
  <div class="section">
554
- <div class="section-title"><span class="icon">&#x1F4AC;</span> Letzte Debatten</div>
557
+ <div class="section-title"><span class="icon">&#x1F4AC;</span> <span data-t="Letzte Debatten">Letzte Debatten</span></div>
555
558
  <div id="debateList" style="margin-top:8px"><div class="empty">Noch keine Debatten gestartet</div></div>
556
559
  </div>
557
560
 
558
561
  <!-- Advocatus Diaboli: Principle Challenges -->
559
562
  <div class="section">
560
- <div class="section-title"><span class="icon">&#x1F525;</span> Advocatus Diaboli — Prinzip-Challenges</div>
561
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Jedes Prinzip wird aktiv hinterfragt. Überlebt es die Gegenargumente, oder wird es geschwächt/widerlegt?</p>
563
+ <div class="section-title"><span class="icon">&#x1F525;</span> <span data-t="Advocatus Diaboli — Prinzip-Challenges">Advocatus Diaboli — Prinzip-Challenges</span></div>
564
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Jedes Prinzip wird aktiv hinterfragt. Überlebt es die Gegenargumente, oder wird es geschwächt/widerlegt?">Jedes Prinzip wird aktiv hinterfragt. Überlebt es die Gegenargumente, oder wird es geschwächt/widerlegt?</p>
562
565
  <div id="challengeList" style="margin-top:8px"><div class="empty">Noch keine Challenges durchgeführt</div></div>
563
566
  </div>
564
567
 
565
568
  <!-- Most Vulnerable Principles -->
566
569
  <div class="section">
567
- <div class="section-title"><span class="icon">&#x26A0;</span> Verwundbarste Prinzipien</div>
568
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Prinzipien mit den niedrigsten Resilienz-Scores — die schwächsten Überzeugungen, die überprüft werden sollten.</p>
570
+ <div class="section-title"><span class="icon">&#x26A0;</span> <span data-t="Verwundbarste Prinzipien">Verwundbarste Prinzipien</span></div>
571
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Prinzipien mit den niedrigsten Resilienz-Scores — die schwächsten Überzeugungen, die überprüft werden sollten.">Prinzipien mit den niedrigsten Resilienz-Scores — die schwächsten Überzeugungen, die überprüft werden sollten.</p>
569
572
  <div id="vulnerableList" style="margin-top:8px"><div class="empty">Keine verwundbaren Prinzipien</div></div>
570
573
  </div>
571
574
  </div>
@@ -573,8 +576,8 @@ canvas{display:block;width:100%;height:100%}
573
576
  <!-- ════ Page 8: Infrastruktur ══════════════════════ -->
574
577
  <div class="page" id="page-infra">
575
578
  <div class="section">
576
- <div class="section-title"><span class="icon">&#x1F6E1;</span> Watchdog — Daemon-Überwachung</div>
577
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px">Überwacht alle Brain-Daemons. Grün = gesund, Gelb = läuft aber Healthcheck fehlgeschlagen, Rot = gestoppt. Auto-Update alle 30s.</p>
579
+ <div class="section-title"><span class="icon">&#x1F6E1;</span> <span data-t="Watchdog — Daemon-Überwachung">Watchdog — Daemon-Überwachung</span></div>
580
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:12px" data-t="Überwacht alle Brain-Daemons. Grün = gesund, Gelb = läuft aber Healthcheck fehlgeschlagen, Rot = gestoppt. Auto-Update alle 30s.">Überwacht alle Brain-Daemons. Grün = gesund, Gelb = läuft aber Healthcheck fehlgeschlagen, Rot = gestoppt. Auto-Update alle 30s.</p>
578
581
  <div class="grid grid-3" id="watchdogCards"><div class="empty">Loading...</div></div>
579
582
  </div>
580
583
  <div class="section">
@@ -583,17 +586,17 @@ canvas{display:block;width:100%;height:100%}
583
586
  </div>
584
587
  <div class="grid grid-2">
585
588
  <div class="section">
586
- <div class="section-title"><span class="icon">&#x1F9E9;</span> Plugins — Erweiterungen</div>
589
+ <div class="section-title"><span class="icon">&#x1F9E9;</span> <span data-t="Plugins — Erweiterungen">Plugins — Erweiterungen</span></div>
587
590
  <div class="card" id="pluginCard"><div class="empty">Loading...</div></div>
588
591
  </div>
589
592
  <div class="section" style="min-height:100px">
590
- <div class="section-title"><span class="icon">&#x1F4CA;</span> Dienst-Statistik</div>
593
+ <div class="section-title"><span class="icon">&#x1F4CA;</span> <span data-t="Dienst-Statistik">Dienst-Statistik</span></div>
591
594
  <div class="card" id="watchdogStatsCard"><div class="empty">Loading...</div></div>
592
595
  </div>
593
596
  </div>
594
597
  <div class="section">
595
- <div class="section-title"><span class="icon">&#x1F3ED;</span> Alle Engines auf einen Blick</div>
596
- <p style="font-size:12px;color:var(--text-dim);margin-bottom:8px">Grün = aktiv, Gelb = bereit, Grau = aus. Die Zahl zeigt wie viele Gedanken die Engine produziert hat.</p>
598
+ <div class="section-title"><span class="icon">&#x1F3ED;</span> <span data-t="Alle Engines auf einen Blick">Alle Engines auf einen Blick</span></div>
599
+ <p style="font-size:12px;color:var(--text-dim);margin-bottom:8px" data-t="Grün = aktiv, Gelb = bereit, Grau = aus. Die Zahl zeigt wie viele Gedanken die Engine produziert hat.">Grün = aktiv, Gelb = bereit, Grau = aus. Die Zahl zeigt wie viele Gedanken die Engine produziert hat.</p>
597
600
  <div class="engine-grid" id="allEngineGrid"><div class="empty">Loading...</div></div>
598
601
  </div>
599
602
  </div>
@@ -609,7 +612,108 @@ const state = {
609
612
  errors:null, selfmod:null, missions:null, knowledge:null, debates:null
610
613
  };
611
614
 
615
+ // ── i18n ──────────────────────────────────────────────────
616
+ const translations = { en: {
617
+ 'Lern-Kreislauf':'Learning Cycle','Aktivität':'Activity','Infrastruktur':'Infrastructure',
618
+ 'Schnellaktionen':'Quick Actions','Lernzyklus starten':'Start Learning Cycle','Tech-Radar Scan':'Tech Radar Scan',
619
+ 'KI-Nutzung':'AI Usage','Brain denkt gerade...':'Brain is thinking...','Letzte Fehler & Warnungen':'Recent Errors & Warnings',
620
+ 'Peer Verbindungen':'Peer Connections','So lernt Brain — Der Kreislauf':'How Brain Learns — The Cycle',
621
+ 'Daten kommen rein, Brain analysiert sie, bildet Hypothesen, testet sie als Experimente und macht daraus Wissen. Dieser Kreislauf läuft ständig.':'Data comes in, Brain analyzes it, forms hypotheses, tests them as experiments, and turns them into knowledge. This cycle runs continuously.',
622
+ 'Daten rein':'Data In','Analysieren':'Analyze','Ideen bilden':'Form Ideas','Ausprobieren':'Experiment','Wissen merken':'Store Knowledge','Umsetzen':'Execute',
623
+ 'Wie die Engines zusammenarbeiten':'How Engines Work Together',
624
+ 'Jede Engine hat eine Aufgabe. Zusammen bilden sie eine Kette — von der Beobachtung bis zur Aktion.':'Each engine has a job. Together they form a chain — from observation to action.',
625
+ 'Beobachten':'Observe','Verstehen':'Understand','Ideen':'Ideas','Testen':'Test','Wissen':'Knowledge','Handeln':'Act',
626
+ 'Wissens-Wachstum — Wird Brain schlauer?':'Knowledge Growth — Is Brain Getting Smarter?',
627
+ 'Regeln gelernt':'Rules Learned','Hypothesen getestet':'Hypotheses Tested','Experimente gemacht':'Experiments Run','Fehler gelöst':'Errors Solved',
628
+ 'Regeln':'Rules','Lösungen':'Solutions','Fehler':'Errors','Engine Stationen':'Engine Stations',
629
+ 'So tradet Trading-Brain':'How Trading Brain Trades',
630
+ 'Signale kommen rein, werden analysiert, als Paper Trade getestet und das Ergebnis fließt zurück ins Lernen.':'Signals come in, get analyzed, tested as paper trades, and results feed back into learning.',
631
+ 'Signale':'Signals','Analyse':'Analysis','Ergebnis':'Result','Lernen':'Learn',
632
+ 'Paper Trading Guthaben':'Paper Trading Balance','Gewinnrate aller Trades':'Win Rate All Trades','Offene Positionen':'Open Positions','Aktive Trades gerade':'Active Trades Now',
633
+ 'So lernt Marketing-Brain':'How Marketing Brain Learns',
634
+ 'Posts werden veröffentlicht, das Engagement wird gemessen, Muster erkannt und die Strategie angepasst.':'Posts are published, engagement is measured, patterns detected, and strategy adjusted.',
635
+ 'Muster':'Patterns','Strategie':'Strategy','Bester Post':'Best Post','Kampagnen':'Campaigns','Aktive Kampagnen':'Active Campaigns','Zielgruppe':'Audience',
636
+ 'So kommunizieren die Brains':'How the Brains Communicate',
637
+ 'Die drei Brains tauschen ständig Nachrichten aus. Jeder fliegende Punkt ist eine Nachricht. Lila = Borg-Wissens-Sync.':'The three brains constantly exchange messages. Each flying dot is a message. Purple = Borg knowledge sync.',
638
+ 'Borg Sync — Geteiltes Wissen':'Borg Sync — Shared Knowledge',
639
+ 'Borg synchronisiert Wissen zwischen allen Brains. Was einer lernt, wissen alle.':'Borg synchronizes knowledge between all brains. What one learns, all know.',
640
+ 'Korrelationen — Was hängt zusammen?':'Correlations — What\'s Connected?','Sync Verlauf':'Sync History',
641
+ 'Brain verbessert sich selbst':'Brain Improves Itself',
642
+ 'Brain erkennt Probleme im eigenen Code und schlägt Verbesserungen vor. Jede Änderung wird erst getestet, bevor sie angewendet wird.':'Brain detects issues in its own code and suggests improvements. Each change is tested before being applied.',
643
+ 'Vorschläge insgesamt':'Total Proposals','Erfolgreich angewendet':'Successfully Applied','Wird gerade getestet':'Currently Testing','Fehlgeschlagen':'Failed',
644
+ 'Aktive Recherche-Missionen':'Active Research Missions',
645
+ 'Brain forscht eigenständig zu Themen. Jede Mission durchläuft 5 Phasen: Aufteilen, Sammeln, Hypothesen bilden, Analysieren, Zusammenfassen.':'Brain researches topics autonomously. Each mission goes through 5 phases: decompose, gather, hypothesize, analyze, synthesize.',
646
+ 'Aktive Missionen':'Active Missions','Abgeschlossen':'Completed','Quellen gesammelt':'Sources Gathered',
647
+ 'Multi-Perspektiven-Debatten zu Schlüsselfragen. Jeder Brain liefert seine Sichtweise basierend auf Prinzipien, Hypothesen und Vorhersagen.':'Multi-perspective debates on key questions. Each brain provides its viewpoint based on principles, hypotheses, and predictions.',
648
+ 'Debatten gesamt':'Total Debates','Offen':'Open','Synthesiert':'Synthesized','Letzte Debatten':'Recent Debates',
649
+ 'Advocatus Diaboli — Prinzip-Challenges':'Advocatus Diaboli — Principle Challenges',
650
+ 'Jedes Prinzip wird aktiv hinterfragt. Überlebt es die Gegenargumente, oder wird es geschwächt/widerlegt?':'Every principle is actively challenged. Does it survive the counter-arguments, or is it weakened/disproved?',
651
+ 'Verwundbarste Prinzipien':'Most Vulnerable Principles',
652
+ 'Prinzipien mit den niedrigsten Resilienz-Scores — die schwächsten Überzeugungen, die überprüft werden sollten.':'Principles with the lowest resilience scores — the weakest beliefs that should be reviewed.',
653
+ 'Watchdog — Daemon-Überwachung':'Watchdog — Daemon Monitoring',
654
+ 'Überwacht alle Brain-Daemons. Grün = gesund, Gelb = läuft aber Healthcheck fehlgeschlagen, Rot = gestoppt. Auto-Update alle 30s.':'Monitors all brain daemons. Green = healthy, Yellow = running but healthcheck failed, Red = stopped. Auto-update every 30s.',
655
+ 'Plugins — Erweiterungen':'Plugins — Extensions','Dienst-Statistik':'Service Statistics',
656
+ 'Alle Engines auf einen Blick':'All Engines at a Glance',
657
+ 'Grün = aktiv, Gelb = bereit, Grau = aus. Die Zahl zeigt wie viele Gedanken die Engine produziert hat.':'Green = active, Yellow = ready, Gray = off. The number shows how many thoughts the engine has produced.',
658
+ 'Verbunden':'Connected','Getrennt':'Disconnected','Warte...':'Waiting...','Brain arbeitet':'Brain active','Ruhig':'Idle',
659
+ 'Gesund':'Healthy','Eingeschränkt':'Degraded','Kritisch':'Critical',
660
+ 'Warte auf Gedanken...':'Waiting for thoughts...','Durchbruch!':'Breakthrough!','Bemerkenswert':'Notable',
661
+ 'Warte auf KI-Daten...':'Waiting for AI data...','Kein KI-Service aktiv':'No AI service active',
662
+ 'KI-Anfragen':'AI Requests','Tokens verbraucht':'Tokens Used','Cache Treffer':'Cache Hits',
663
+ 'Anfragen/Stunde':'Requests/Hour','Antwortzeit':'Response Time','KI-Fehler':'AI Errors',
664
+ 'Budget pro Stunde':'Hourly Budget','Budget pro Tag':'Daily Budget','KI-Modell:':'AI Model:','Anbieter:':'Providers:',
665
+ 'Keine Fehler — alles läuft!':'No errors — all systems running!','Gelöst':'Resolved','Unbekannter Fehler':'Unknown error',
666
+ 'Lernt aus Fehlern, verbessert Code':'Learns from errors, improves code','Paper Trading, Signal-Analyse':'Paper trading, signal analysis','Content-Strategie, Engagement':'Content strategy, engagement',
667
+ 'Online':'Online','Offline':'Offline',
668
+ 'Noch keine Zusammenhänge gefunden':'No correlations found yet','Noch keine Korrelationen gefunden':'No correlations found yet',
669
+ 'Nicht verfügbar':'Not available','Aktiv':'Active','Deaktiviert':'Disabled','Deaktivieren':'Disable','Aktivieren':'Enable','Standard':'Standard',
670
+ 'Gesendet':'Sent','Empfangen':'Received','Noch kein Sync passiert':'No sync yet',
671
+ 'Zeit':'Time','Richtung':'Direction','Partner':'Peer','Elemente':'Items','Akzeptiert':'Accepted',
672
+ 'Brain hat sich noch nicht selbst verbessert':'Brain hasn\'t improved itself yet','Noch keine Verbesserungen':'No improvements yet',
673
+ 'Angewendet':'Applied','Wird getestet':'Testing','Bereit':'Ready','Vorgeschlagen':'Proposed','Generiert':'Generated','Abgelehnt':'Rejected','Zurückgesetzt':'Rolled Back',
674
+ 'Verbesserung':'Improvement','Dateien:':'Files:',
675
+ 'Keine aktiven Missionen':'No active missions','Aufteilen':'Decompose','Sammeln':'Gather','Zusammenfassen':'Synthesize',
676
+ 'Fertig':'Complete','Tiefgehend':'Deep','Schnell':'Quick','Quellen':'Sources','Gestartet:':'Started:','Fertig:':'Completed:',
677
+ 'Noch keine Debatten gestartet':'No debates started yet','Perspektiven':'Perspectives','Konsens:':'Consensus:',
678
+ 'Noch keine Challenges durchgeführt':'No challenges performed yet','Keine verwundbaren Prinzipien':'No vulnerable principles',
679
+ 'Kein Watchdog konfiguriert — starte Brain mit <code>brain start</code>':'No watchdog configured — start Brain with <code>brain start</code>',
680
+ 'Gestoppt':'Stopped','Problem':'Problem','Laufzeit':'Uptime','Neustarts':'Restarts','Letzter Crash':'Last Crash',
681
+ 'Alle Systeme laufen':'All Systems Running','Dienste offline':'services offline','Dienste mit Problemen':'services with problems',
682
+ 'Dienste überwacht':'services monitored','laufen':'running','gesund':'healthy',
683
+ 'Gesamt-Neustarts':'Total Restarts','Längste Laufzeit':'Longest Uptime','Dienste':'Services',
684
+ 'Keine Plugins installiert':'No plugins installed','Geladen':'Loaded','Keine Engines':'No engines',
685
+ 'Strategien':'Strategies','BORG AKTIV':'BORG ACTIVE','gesendet':'sent','empfangen':'received',
686
+ 'Der Lern-Kreislauf':'The Learning Cycle','Aktivität & Missionen':'Activity & Missions',
687
+ }};
688
+ let currentLang = localStorage.getItem('brain-lang') || 'en';
689
+ function t(text) { if (currentLang === 'en' && translations.en[text]) return translations.en[text]; return text; }
690
+ function setLang(lang) {
691
+ currentLang = lang; localStorage.setItem('brain-lang', lang);
692
+ document.getElementById('langToggle').textContent = lang.toUpperCase();
693
+ updateStaticTexts(); renderAll();
694
+ }
695
+ function updateStaticTexts() {
696
+ document.querySelectorAll('[data-t]').forEach(el => { el.textContent = t(el.dataset.t); });
697
+ }
698
+ function renderAll() {
699
+ const active = document.querySelector('.nav-item.active');
700
+ if (active) document.getElementById('pageTitle').textContent = getTitle(active.dataset.page);
701
+ updateConnection(); updatePulse();
702
+ renderEcosystem(); renderEngines(); renderWatchdog(); renderPlugins();
703
+ renderBorg(); renderAnalytics(); renderLLM(); renderErrors();
704
+ renderSelfMod(); renderMissions(); renderKnowledge(); renderDebates();
705
+ if (state.thoughts.length) renderThoughts();
706
+ }
707
+ function getLocale() { return currentLang === 'de' ? 'de-DE' : 'en-US'; }
708
+
612
709
  // ── Navigation ────────────────────────────────────────────
710
+ function getTitle(page) {
711
+ const titles = {
712
+ overview:'Ecosystem Overview', learning:t('Der Lern-Kreislauf'), trading:'Trading Flow',
713
+ marketing:'Marketing Flow', crossbrain:'Cross-Brain & Borg', activity:t('Aktivität & Missionen'),
714
+ debates:'Debates & Challenges', infra:t('Infrastruktur')
715
+ }; return titles[page] || '';
716
+ }
613
717
  const titles = {
614
718
  overview:'Ecosystem Overview',
615
719
  learning:'Der Lern-Kreislauf',
@@ -626,7 +730,7 @@ document.querySelectorAll('.nav-item').forEach(item => {
626
730
  document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
627
731
  item.classList.add('active');
628
732
  document.getElementById('page-' + item.dataset.page).classList.add('active');
629
- document.getElementById('pageTitle').textContent = titles[item.dataset.page] || '';
733
+ document.getElementById('pageTitle').textContent = getTitle(item.dataset.page);
630
734
  });
631
735
  });
632
736
 
@@ -651,7 +755,7 @@ function connectSSE() {
651
755
 
652
756
  function updateConnection() {
653
757
  const b = document.getElementById('connectionBadge');
654
- b.textContent = state.connected ? 'Verbunden' : 'Getrennt';
758
+ b.textContent = state.connected ? t('Verbunden') : t('Getrennt');
655
759
  b.className = 'badge ' + (state.connected ? 'badge-ok' : 'badge-err');
656
760
  }
657
761
 
@@ -684,12 +788,12 @@ function addThought(t) {
684
788
  function renderThoughts() {
685
789
  const el = document.getElementById('thoughtStream');
686
790
  const cnt = document.getElementById('thoughtCount');
687
- if (!state.thoughts.length) { el.innerHTML = '<div class="empty">Warte auf Gedanken...</div>'; cnt.textContent = ''; return; }
791
+ if (!state.thoughts.length) { el.innerHTML = `<div class="empty">${t('Warte auf Gedanken...')}</div>`; cnt.textContent = ''; return; }
688
792
  cnt.textContent = `(${state.thoughts.length})`;
689
793
  el.innerHTML = state.thoughts.slice(0, 50).map(t => {
690
- const time = new Date(t.timestamp).toLocaleTimeString('de-DE', { hour:'2-digit', minute:'2-digit', second:'2-digit' });
794
+ const time = new Date(t.timestamp).toLocaleTimeString(getLocale(), { hour:'2-digit', minute:'2-digit', second:'2-digit' });
691
795
  const sigClass = t.significance === 'breakthrough' ? 'sig-breakthrough' : t.significance === 'notable' ? 'sig-notable' : 'sig-routine';
692
- const sigLabel = t.significance === 'breakthrough' ? 'Durchbruch!' : t.significance === 'notable' ? 'Bemerkenswert' : '';
796
+ const sigLabel = t.significance === 'breakthrough' ? window.t('Durchbruch!') : t.significance === 'notable' ? window.t('Bemerkenswert') : '';
693
797
  return `<div class="thought-item">
694
798
  <span class="thought-time">${time}</span>
695
799
  <span class="thought-engine" style="color:var(--cyan)">${t.engine}</span>
@@ -704,10 +808,10 @@ function updatePulse() {
704
808
  const dot = document.getElementById('pulseDot');
705
809
  const label = document.getElementById('pulseLabel');
706
810
  const age = Date.now() - state.lastThoughtTime;
707
- if (state.lastThoughtTime === 0) { dot.className = 'pulse-dot off'; label.textContent = 'Warte...'; return; }
708
- if (age < 30000) { dot.className = 'pulse-dot'; label.textContent = 'Brain arbeitet'; }
811
+ if (state.lastThoughtTime === 0) { dot.className = 'pulse-dot off'; label.textContent = t('Warte...'); return; }
812
+ if (age < 30000) { dot.className = 'pulse-dot'; label.textContent = t('Brain arbeitet'); }
709
813
  else if (age < 120000) { dot.className = 'pulse-dot idle'; label.textContent = 'Idle'; }
710
- else { dot.className = 'pulse-dot off'; label.textContent = 'Ruhig'; }
814
+ else { dot.className = 'pulse-dot off'; label.textContent = t('Ruhig'); }
711
815
  }
712
816
  setInterval(updatePulse, 5000);
713
817
 
@@ -715,28 +819,28 @@ setInterval(updatePulse, 5000);
715
819
  function renderLLM() {
716
820
  const el = document.getElementById('llmCard');
717
821
  const s = state.llm;
718
- if (!s) { el.innerHTML = '<div class="empty">Kein KI-Service aktiv</div>'; return; }
822
+ if (!s) { el.innerHTML = `<div class="empty">${t('Kein KI-Service aktiv')}</div>`; return; }
719
823
 
720
824
  const hourPct = s.tokensThisHour && s.budgetRemainingHour != null ? Math.min(100, (s.tokensThisHour / (s.tokensThisHour + s.budgetRemainingHour)) * 100) : 0;
721
825
  const dayPct = s.tokensToday && s.budgetRemainingDay != null ? Math.min(100, (s.tokensToday / (s.tokensToday + s.budgetRemainingDay)) * 100) : 0;
722
826
 
723
827
  el.innerHTML = `
724
828
  <div class="llm-grid">
725
- <div class="llm-stat"><div class="llm-stat-value">${s.totalCalls ?? 0}</div><div class="llm-stat-label">KI-Anfragen</div></div>
726
- <div class="llm-stat"><div class="llm-stat-value">${formatK(s.totalTokens ?? 0)}</div><div class="llm-stat-label">Tokens verbraucht</div></div>
727
- <div class="llm-stat"><div class="llm-stat-value">${s.cacheHitRate != null ? (s.cacheHitRate * 100).toFixed(0) + '%' : '--'}</div><div class="llm-stat-label">Cache Treffer</div></div>
728
- <div class="llm-stat"><div class="llm-stat-value">${s.callsThisHour ?? 0}</div><div class="llm-stat-label">Anfragen/Stunde</div></div>
729
- <div class="llm-stat"><div class="llm-stat-value">${s.averageLatencyMs ? Math.round(s.averageLatencyMs) + 'ms' : '--'}</div><div class="llm-stat-label">Antwortzeit</div></div>
730
- <div class="llm-stat"><div class="llm-stat-value">${s.errors ?? 0}</div><div class="llm-stat-label">KI-Fehler</div></div>
829
+ <div class="llm-stat"><div class="llm-stat-value">${s.totalCalls ?? 0}</div><div class="llm-stat-label">${t('KI-Anfragen')}</div></div>
830
+ <div class="llm-stat"><div class="llm-stat-value">${formatK(s.totalTokens ?? 0)}</div><div class="llm-stat-label">${t('Tokens verbraucht')}</div></div>
831
+ <div class="llm-stat"><div class="llm-stat-value">${s.cacheHitRate != null ? (s.cacheHitRate * 100).toFixed(0) + '%' : '--'}</div><div class="llm-stat-label">${t('Cache Treffer')}</div></div>
832
+ <div class="llm-stat"><div class="llm-stat-value">${s.callsThisHour ?? 0}</div><div class="llm-stat-label">${t('Anfragen/Stunde')}</div></div>
833
+ <div class="llm-stat"><div class="llm-stat-value">${s.averageLatencyMs ? Math.round(s.averageLatencyMs) + 'ms' : '--'}</div><div class="llm-stat-label">${t('Antwortzeit')}</div></div>
834
+ <div class="llm-stat"><div class="llm-stat-value">${s.errors ?? 0}</div><div class="llm-stat-label">${t('KI-Fehler')}</div></div>
731
835
  </div>
732
836
  <div style="margin-top:12px">
733
- <div style="display:flex;justify-content:space-between;font-size:10px;color:var(--text-dim);margin-bottom:2px"><span>Budget pro Stunde</span><span>${formatK(s.tokensThisHour ?? 0)} / ${formatK((s.tokensThisHour ?? 0) + (s.budgetRemainingHour ?? 0))}</span></div>
837
+ <div style="display:flex;justify-content:space-between;font-size:10px;color:var(--text-dim);margin-bottom:2px"><span>${t('Budget pro Stunde')}</span><span>${formatK(s.tokensThisHour ?? 0)} / ${formatK((s.tokensThisHour ?? 0) + (s.budgetRemainingHour ?? 0))}</span></div>
734
838
  <div class="llm-bar"><div class="llm-bar-fill" style="width:${hourPct}%;background:${hourPct > 80 ? 'var(--red)' : hourPct > 50 ? 'var(--orange)' : 'var(--cyan)'}"></div></div>
735
- <div style="display:flex;justify-content:space-between;font-size:10px;color:var(--text-dim);margin:8px 0 2px"><span>Budget pro Tag</span><span>${formatK(s.tokensToday ?? 0)} / ${formatK((s.tokensToday ?? 0) + (s.budgetRemainingDay ?? 0))}</span></div>
839
+ <div style="display:flex;justify-content:space-between;font-size:10px;color:var(--text-dim);margin:8px 0 2px"><span>${t('Budget pro Tag')}</span><span>${formatK(s.tokensToday ?? 0)} / ${formatK((s.tokensToday ?? 0) + (s.budgetRemainingDay ?? 0))}</span></div>
736
840
  <div class="llm-bar"><div class="llm-bar-fill" style="width:${dayPct}%;background:${dayPct > 80 ? 'var(--red)' : dayPct > 50 ? 'var(--orange)' : 'var(--green)'}"></div></div>
737
841
  </div>
738
- ${s.model ? `<div style="margin-top:10px;font-size:10px;color:var(--text-dim)">KI-Modell: ${s.model}</div>` : ''}
739
- ${s.providers ? `<div style="margin-top:4px;font-size:10px;color:var(--text-dim)">Anbieter: ${s.providers.map(p => `<span style="color:${p.available ? 'var(--green)' : 'var(--red)'}">${p.name}</span>`).join(', ')}</div>` : ''}
842
+ ${s.model ? `<div style="margin-top:10px;font-size:10px;color:var(--text-dim)">${t('KI-Modell:')} ${s.model}</div>` : ''}
843
+ ${s.providers ? `<div style="margin-top:4px;font-size:10px;color:var(--text-dim)">${t('Anbieter:')} ${s.providers.map(p => `<span style="color:${p.available ? 'var(--green)' : 'var(--red)'}">${p.name}</span>`).join(', ')}</div>` : ''}
740
844
  `;
741
845
  }
742
846
 
@@ -745,18 +849,18 @@ function renderErrors() {
745
849
  const el = document.getElementById('errorFeed');
746
850
  const cnt = document.getElementById('errorCount');
747
851
  const d = state.errors;
748
- if (!d) { el.innerHTML = '<div class="empty">Keine Fehler — alles läuft!</div>'; cnt.textContent = ''; return; }
852
+ if (!d) { el.innerHTML = `<div class="empty">${t('Keine Fehler — alles läuft!')}</div>`; cnt.textContent = ''; return; }
749
853
  const errors = d.errors || d;
750
- if (!Array.isArray(errors) || !errors.length) { el.innerHTML = '<div class="empty">Keine Fehler — alles läuft!</div>'; cnt.textContent = ''; return; }
854
+ if (!Array.isArray(errors) || !errors.length) { el.innerHTML = `<div class="empty">${t('Keine Fehler — alles läuft!')}</div>`; cnt.textContent = ''; return; }
751
855
  cnt.textContent = `(${errors.length})`;
752
856
  el.innerHTML = errors.slice(0, 20).map(e => {
753
- const time = e.timestamp ? new Date(e.timestamp).toLocaleTimeString('de-DE', { hour:'2-digit', minute:'2-digit' }) : '';
857
+ const time = e.timestamp ? new Date(e.timestamp).toLocaleTimeString(getLocale(), { hour:'2-digit', minute:'2-digit' }) : '';
754
858
  const level = e.resolved ? 'warn' : 'err';
755
- const msg = e.message || e.error_message || e.title || 'Unbekannter Fehler';
859
+ const msg = e.message || e.error_message || e.title || t('Unbekannter Fehler');
756
860
  const source = e.source || e.project || '';
757
861
  return `<div class="error-item">
758
862
  <span class="thought-time">${time}</span>
759
- <span class="error-level ${level}">${e.resolved ? 'Gelöst' : 'Fehler'}</span>
863
+ <span class="error-level ${level}">${e.resolved ? t('Gelöst') : t('Fehler')}</span>
760
864
  ${source ? `<span style="font-size:11px;color:var(--cyan);min-width:60px">${escHtml(source)}</span>` : ''}
761
865
  <span class="error-msg">${escHtml(msg)}</span>
762
866
  </div>`;
@@ -768,7 +872,7 @@ function renderSelfMod() {
768
872
  const d = state.selfmod;
769
873
  if (!d || !d.status) {
770
874
  setText('sm-total', 0); setText('sm-applied', 0); setText('sm-testing', 0); setText('sm-failed', 0);
771
- document.getElementById('selfModFeed').innerHTML = '<div class="empty">Brain hat sich noch nicht selbst verbessert</div>';
875
+ document.getElementById('selfModFeed').innerHTML = `<div class="empty">${t('Brain hat sich noch nicht selbst verbessert')}</div>`;
772
876
  return;
773
877
  }
774
878
  const s = d.status;
@@ -780,28 +884,45 @@ function renderSelfMod() {
780
884
 
781
885
  const hist = d.history || [];
782
886
  const el = document.getElementById('selfModFeed');
783
- if (!hist.length) { el.innerHTML = '<div class="empty">Noch keine Verbesserungen</div>'; return; }
887
+ if (!hist.length) { el.innerHTML = `<div class="empty">${t('Noch keine Verbesserungen')}</div>`; return; }
784
888
  el.innerHTML = hist.map(m => {
785
- const statusMap = { applied:'Angewendet', testing:'Wird getestet', ready:'Bereit', proposed:'Vorgeschlagen', generating:'Generiert', failed:'Fehlgeschlagen', rejected:'Abgelehnt', rolled_back:'Zurückgesetzt' };
889
+ const statusMap = { applied:t('Angewendet'), testing:t('Wird getestet'), ready:t('Bereit'), proposed:t('Vorgeschlagen'), generating:t('Generiert'), failed:t('Fehlgeschlagen'), rejected:t('Abgelehnt'), rolled_back:t('Zurückgesetzt') };
786
890
  const statusClass = m.status === 'applied' ? 'mod-applied' : m.status === 'testing' || m.status === 'generating' ? 'mod-testing' : m.status === 'failed' || m.status === 'rejected' ? 'mod-failed' : 'mod-proposed';
787
- const time = m.created_at ? new Date(m.created_at).toLocaleString('de-DE', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' }) : '';
891
+ const time = m.created_at ? new Date(m.created_at).toLocaleString(getLocale(), { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' }) : '';
892
+ const actions = (m.status === 'ready' || m.status === 'proposed') ?
893
+ `<div style="margin-top:4px;display:flex;gap:6px">
894
+ <button onclick="selfmodAction(${m.id},'approve')" style="background:var(--green);color:#fff;border:none;border-radius:4px;padding:2px 10px;cursor:pointer;font-size:11px">Approve</button>
895
+ <button onclick="selfmodAction(${m.id},'reject')" style="background:var(--red);color:#fff;border:none;border-radius:4px;padding:2px 10px;cursor:pointer;font-size:11px">Reject</button>
896
+ </div>` : '';
897
+ const riskBadge = m.risk_level ? `<span style="font-size:10px;padding:1px 5px;border-radius:3px;background:${m.risk_level==='high'?'var(--red)':m.risk_level==='medium'?'var(--yellow)':'var(--green)'};color:#fff;margin-left:6px">${m.risk_level}</span>` : '';
788
898
  return `<div class="mod-item">
789
899
  <span class="mod-status ${statusClass}">${statusMap[m.status] || m.status}</span>
790
900
  <div style="flex:1">
791
- <div class="mod-title">${escHtml(m.title || 'Verbesserung')}</div>
901
+ <div class="mod-title">${escHtml(m.title || t('Verbesserung'))}${riskBadge}</div>
792
902
  <div class="mod-detail">${escHtml(m.problem_description || '')} ${time ? `<span style="float:right">${time}</span>` : ''}</div>
793
- ${m.target_files?.length ? `<div style="font-size:10px;color:var(--text-dim);margin-top:2px">Dateien: ${m.target_files.map(f => f.split('/').pop()).join(', ')}</div>` : ''}
903
+ ${m.target_files?.length ? `<div style="font-size:10px;color:var(--text-dim);margin-top:2px">${t('Dateien:')} ${m.target_files.map(f => f.split('/').pop()).join(', ')}</div>` : ''}
904
+ ${actions}
794
905
  </div>
795
906
  </div>`;
796
907
  }).join('');
797
908
  }
798
909
 
910
+ async function selfmodAction(id, action) {
911
+ try {
912
+ const res = await fetch(`/api/selfmod/${action}`, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({id}) });
913
+ const data = await res.json();
914
+ if (!res.ok) { alert(`${t('Fehler')}: ${data.error || 'Unknown'}`); return; }
915
+ // Refresh selfmod data
916
+ fetch('/api/selfmod').then(r => r.json()).then(d => { state.selfmod = d; renderSelfMod(); });
917
+ } catch(e) { alert(`${t('Fehler')}: ${e.message}`); }
918
+ }
919
+
799
920
  // ── Mission Tracker ───────────────────────────────────────
800
921
  function renderMissions() {
801
922
  const d = state.missions;
802
923
  if (!d || !d.status) {
803
924
  setText('ms-active', 0); setText('ms-completed', 0); setText('ms-sources', 0);
804
- document.getElementById('missionList').innerHTML = '<div class="empty">Keine aktiven Missionen</div>';
925
+ document.getElementById('missionList').innerHTML = `<div class="empty">${t('Keine aktiven Missionen')}</div>`;
805
926
  return;
806
927
  }
807
928
  const s = d.status;
@@ -811,24 +932,24 @@ function renderMissions() {
811
932
 
812
933
  const list = d.list || [];
813
934
  const el = document.getElementById('missionList');
814
- if (!list.length) { el.innerHTML = '<div class="empty">Keine aktiven Missionen</div>'; return; }
935
+ if (!list.length) { el.innerHTML = `<div class="empty">${t('Keine aktiven Missionen')}</div>`; return; }
815
936
  const phases = ['decomposing','gathering','hypothesizing','analyzing','synthesizing'];
816
- const phaseLabels = { decomposing:'Aufteilen', gathering:'Sammeln', hypothesizing:'Ideen bilden', analyzing:'Analysieren', synthesizing:'Zusammenfassen' };
937
+ const phaseLabels = { decomposing:t('Aufteilen'), gathering:t('Sammeln'), hypothesizing:t('Ideen bilden'), analyzing:t('Analysieren'), synthesizing:t('Zusammenfassen') };
817
938
  el.innerHTML = list.slice(0, 10).map(m => {
818
939
  const statusIdx = phases.indexOf(m.status);
819
940
  const phaseHtml = phases.map((p, i) => {
820
941
  const cls = m.status === 'complete' ? 'done' : m.status === 'failed' ? (i <= statusIdx ? 'fail' : '') : (i < statusIdx ? 'done' : i === statusIdx ? 'running' : '');
821
942
  return `<div class="mission-phase ${cls}" title="${phaseLabels[p] || p}"></div>`;
822
943
  }).join('');
823
- const statusText = m.status === 'complete' ? 'Fertig' : m.status === 'failed' ? 'Fehlgeschlagen' : phaseLabels[m.status] || m.status;
824
- const depth = m.depth === 'deep' ? 'Tiefgehend' : m.depth === 'quick' ? 'Schnell' : 'Standard';
944
+ const statusText = m.status === 'complete' ? t('Fertig') : m.status === 'failed' ? t('Fehlgeschlagen') : phaseLabels[m.status] || m.status;
945
+ const depth = m.depth === 'deep' ? t('Tiefgehend') : m.depth === 'quick' ? t('Schnell') : t('Standard');
825
946
  return `<div class="mission-card">
826
947
  <div class="mission-topic">${escHtml(m.topic || 'Mission')}</div>
827
- <div style="font-size:11px;color:var(--text-dim)">${statusText} — ${depth} — ${m.sourceCount || 0} Quellen</div>
948
+ <div style="font-size:11px;color:var(--text-dim)">${statusText} — ${depth} — ${m.sourceCount || 0} ${t('Quellen')}</div>
828
949
  <div class="mission-phases">${phaseHtml}</div>
829
950
  <div class="mission-meta">
830
- <span>Gestartet: ${m.createdAt ? new Date(m.createdAt).toLocaleString('de-DE', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' }) : '?'}</span>
831
- ${m.completedAt ? `<span>Fertig: ${new Date(m.completedAt).toLocaleString('de-DE', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' })}</span>` : ''}
951
+ <span>${t('Gestartet:')} ${m.createdAt ? new Date(m.createdAt).toLocaleString(getLocale(), { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' }) : '?'}</span>
952
+ ${m.completedAt ? `<span>${t('Fertig:')} ${new Date(m.completedAt).toLocaleString(getLocale(), { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' })}</span>` : ''}
832
953
  </div>
833
954
  </div>`;
834
955
  }).join('');
@@ -891,7 +1012,7 @@ function renderEcosystem() {
891
1012
  const hb = document.getElementById('healthBadge');
892
1013
  const h = eco.health;
893
1014
  if (h) {
894
- hb.textContent = h.status === 'healthy' ? 'Gesund' : h.status === 'degraded' ? 'Eingeschränkt' : 'Kritisch';
1015
+ hb.textContent = h.status === 'healthy' ? t('Gesund') : h.status === 'degraded' ? t('Eingeschränkt') : t('Kritisch');
895
1016
  hb.className = 'badge ' + (h.status === 'healthy' ? 'badge-ok' : h.status === 'degraded' ? 'badge-warn' : 'badge-err');
896
1017
  const score = h.score || 0;
897
1018
  document.getElementById('gaugeArc').setAttribute('stroke-dasharray', `${(score / 100) * 172} 172`);
@@ -901,7 +1022,7 @@ function renderEcosystem() {
901
1022
  const container = document.getElementById('brainCards');
902
1023
  const brainNames = ['brain', 'trading-brain', 'marketing-brain'];
903
1024
  const labels = { brain:'Brain', 'trading-brain':'Trading-Brain', 'marketing-brain':'Marketing-Brain' };
904
- const descs = { brain:'Lernt aus Fehlern, verbessert Code', 'trading-brain':'Paper Trading, Signal-Analyse', 'marketing-brain':'Content-Strategie, Engagement' };
1025
+ const descs = { brain:t('Lernt aus Fehlern, verbessert Code'), 'trading-brain':t('Paper Trading, Signal-Analyse'), 'marketing-brain':t('Content-Strategie, Engagement') };
905
1026
  const classes = { brain:'brain-brain', 'trading-brain':'brain-trading', 'marketing-brain':'brain-marketing' };
906
1027
  container.innerHTML = brainNames.map(name => {
907
1028
  const b = (eco.brains || []).find(x => x.name === name) || { name, available:false };
@@ -909,7 +1030,7 @@ function renderEcosystem() {
909
1030
  <div class="brain-status"><span class="dot ${b.available ? 'dot-on' : 'dot-off'}"></span><span class="brain-name">${labels[name]}</span></div>
910
1031
  <div style="font-size:11px;color:var(--text-dim);margin-bottom:6px">${descs[name]}</div>
911
1032
  <div class="brain-meta">
912
- <span>${b.available ? 'Online' : 'Offline'}</span>
1033
+ <span>${b.available ? t('Online') : t('Offline')}</span>
913
1034
  ${b.version ? `<span>v${b.version}</span>` : ''}${b.pid ? `<span>PID ${b.pid}</span>` : ''}
914
1035
  ${b.uptime ? `<span>${fmtUp(b.uptime)}</span>` : ''}${b.methods ? `<span>${b.methods} Tools</span>` : ''}
915
1036
  </div></div>`;
@@ -920,7 +1041,7 @@ function renderEcosystem() {
920
1041
 
921
1042
  function renderCorrelations(c) {
922
1043
  const el = document.getElementById('correlationList');
923
- if (!c.length) { el.innerHTML = '<div class="empty">Noch keine Zusammenhänge gefunden</div>'; return; }
1044
+ if (!c.length) { el.innerHTML = `<div class="empty">${t('Noch keine Zusammenhänge gefunden')}</div>`; return; }
924
1045
  el.innerHTML = c.slice(0, 10).map(x => `<div style="padding:6px 0;border-bottom:1px solid var(--border);font-size:12px">
925
1046
  <span style="color:var(--cyan)">${x.sourceA}/${x.eventA}</span> <span style="color:var(--text-dim)">&#x2194;</span>
926
1047
  <span style="color:var(--magenta)">${x.sourceB}/${x.eventB}</span>
@@ -942,7 +1063,7 @@ function renderEngines() {
942
1063
 
943
1064
  function renderGrid(id, engines, showBrain = false) {
944
1065
  const el = document.getElementById(id); if (!el) return;
945
- if (!engines.length) { el.innerHTML = '<div class="empty">Keine Engines</div>'; return; }
1066
+ if (!engines.length) { el.innerHTML = `<div class="empty">${t('Keine Engines')}</div>`; return; }
946
1067
  el.innerHTML = engines.map(e => {
947
1068
  const lastTs = e.lastActive || e.lastActivity || 0;
948
1069
  const count = e.metrics?.totalThoughts ?? e.thoughtCount ?? 0;
@@ -989,7 +1110,7 @@ function renderAnalytics() {
989
1110
  setText('mp-campaigns', num(m.campaigns));
990
1111
  setText('marketingCampaigns', num(m.campaigns));
991
1112
  setText('marketingTopContent', num(m.templates) > 0 ? num(m.templates) + ' Templates' : '--');
992
- setText('marketingAudience', num(m.strategies) > 0 ? num(m.strategies) + ' Strategien' : '--');
1113
+ setText('marketingAudience', num(m.strategies) > 0 ? num(m.strategies) + ' ' + t('Strategien') : '--');
993
1114
  }
994
1115
  }
995
1116
  function num(v) { if (v == null) return 0; if (typeof v === 'object') return v.total || v.count || v.length || Object.keys(v).length || 0; return Number(v) || 0; }
@@ -998,13 +1119,13 @@ function num(v) { if (v == null) return 0; if (typeof v === 'object') return v.t
998
1119
  function renderWatchdog() {
999
1120
  const el = document.getElementById('watchdogCards');
1000
1121
  const d = state.watchdog || [];
1001
- if (!d.length) { el.innerHTML = '<div class="empty">Kein Watchdog konfiguriert — starte Brain mit <code>brain start</code></div>'; return; }
1122
+ if (!d.length) { el.innerHTML = `<div class="empty">${t('Kein Watchdog konfiguriert — starte Brain mit <code>brain start</code>')}</div>`; return; }
1002
1123
 
1003
1124
  // Daemon cards — color-coded
1004
1125
  el.innerHTML = d.map(x => {
1005
1126
  const borderColor = !x.running ? 'var(--red)' : x.healthy ? 'var(--green)' : 'var(--orange)';
1006
1127
  const bgColor = !x.running ? 'rgba(239,68,68,0.08)' : x.healthy ? 'rgba(34,197,94,0.08)' : 'rgba(234,179,8,0.08)';
1007
- const statusText = !x.running ? 'Gestoppt' : x.healthy ? 'Gesund' : 'Problem';
1128
+ const statusText = !x.running ? t('Gestoppt') : x.healthy ? t('Gesund') : t('Problem');
1008
1129
  const statusIcon = !x.running ? '&#x1F534;' : x.healthy ? '&#x1F7E2;' : '&#x1F7E1;';
1009
1130
  const uptime = x.uptime ? fmtUp(x.uptime / 1000) : '-';
1010
1131
  return `<div class="card" style="border-left:3px solid ${borderColor};background:${bgColor};padding:16px">
@@ -1014,9 +1135,9 @@ function renderWatchdog() {
1014
1135
  </div>
1015
1136
  <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;font-size:12px">
1016
1137
  <div><span style="color:var(--text-dim)">PID</span><br><span style="font-weight:600;font-size:14px">${x.pid || '-'}</span></div>
1017
- <div><span style="color:var(--text-dim)">Laufzeit</span><br><span style="font-weight:600;font-size:14px">${uptime}</span></div>
1018
- <div><span style="color:var(--text-dim)">Neustarts</span><br><span style="font-weight:600;font-size:14px;color:${x.restarts > 0 ? 'var(--orange)' : 'inherit'}">${x.restarts || 0}</span></div>
1019
- <div><span style="color:var(--text-dim)">Letzter Crash</span><br><span style="font-weight:600;font-size:11px">${x.lastCrash ? new Date(x.lastCrash).toLocaleString('de') : '-'}</span></div>
1138
+ <div><span style="color:var(--text-dim)">${t('Laufzeit')}</span><br><span style="font-weight:600;font-size:14px">${uptime}</span></div>
1139
+ <div><span style="color:var(--text-dim)">${t('Neustarts')}</span><br><span style="font-weight:600;font-size:14px;color:${x.restarts > 0 ? 'var(--orange)' : 'inherit'}">${x.restarts || 0}</span></div>
1140
+ <div><span style="color:var(--text-dim)">${t('Letzter Crash')}</span><br><span style="font-weight:600;font-size:11px">${x.lastCrash ? new Date(x.lastCrash).toLocaleString(getLocale()) : '-'}</span></div>
1020
1141
  </div>
1021
1142
  </div>`;
1022
1143
  }).join('');
@@ -1025,7 +1146,7 @@ function renderWatchdog() {
1025
1146
  const hc = document.getElementById('healthCheckCard');
1026
1147
  const ok = d.every(x => x.running && x.healthy), off = d.filter(x => !x.running).length;
1027
1148
  const unhealthy = d.filter(x => x.running && !x.healthy).length;
1028
- hc.innerHTML = `<div style="display:flex;gap:20px;align-items:center"><span style="font-size:32px">${ok?'&#x2705;':off?'&#x1F6A8;':'&#x26A0;'}</span><div><div style="font-size:15px;font-weight:600;color:${ok?'var(--green)':off?'var(--red)':'var(--orange)'}">${ok?'Alle Systeme laufen':off?`${off} Dienste offline`:`${unhealthy} Dienste mit Problemen`}</div><div style="font-size:12px;color:var(--text-dim);margin-top:4px">${d.length} Dienste überwacht &bull; ${d.filter(x=>x.running).length} laufen &bull; ${d.filter(x=>x.running&&x.healthy).length} gesund</div></div></div>`;
1149
+ hc.innerHTML = `<div style="display:flex;gap:20px;align-items:center"><span style="font-size:32px">${ok?'&#x2705;':off?'&#x1F6A8;':'&#x26A0;'}</span><div><div style="font-size:15px;font-weight:600;color:${ok?'var(--green)':off?'var(--red)':'var(--orange)'}">${ok?t('Alle Systeme laufen'):off?`${off} ${t('Dienste offline')}`:`${unhealthy} ${t('Dienste mit Problemen')}`}</div><div style="font-size:12px;color:var(--text-dim);margin-top:4px">${d.length} ${t('Dienste überwacht')} &bull; ${d.filter(x=>x.running).length} ${t('laufen')} &bull; ${d.filter(x=>x.running&&x.healthy).length} ${t('gesund')}</div></div></div>`;
1029
1150
 
1030
1151
  // Stats card
1031
1152
  const sc = document.getElementById('watchdogStatsCard');
@@ -1033,32 +1154,32 @@ function renderWatchdog() {
1033
1154
  const avgUptime = d.filter(x => x.uptime).map(x => x.uptime);
1034
1155
  const maxUp = avgUptime.length ? fmtUp(Math.max(...avgUptime) / 1000) : '-';
1035
1156
  sc.innerHTML = `<div style="display:flex;gap:24px;font-size:13px">
1036
- <div><span style="color:var(--text-dim)">Gesamt-Neustarts</span><br><span style="font-size:20px;font-weight:700;color:${totalRestarts>0?'var(--orange)':'var(--green)'}">${totalRestarts}</span></div>
1037
- <div><span style="color:var(--text-dim)">Längste Laufzeit</span><br><span style="font-size:20px;font-weight:700">${maxUp}</span></div>
1038
- <div><span style="color:var(--text-dim)">Dienste</span><br><span style="font-size:20px;font-weight:700">${d.length}</span></div>
1157
+ <div><span style="color:var(--text-dim)">${t('Gesamt-Neustarts')}</span><br><span style="font-size:20px;font-weight:700;color:${totalRestarts>0?'var(--orange)':'var(--green)'}">${totalRestarts}</span></div>
1158
+ <div><span style="color:var(--text-dim)">${t('Längste Laufzeit')}</span><br><span style="font-size:20px;font-weight:700">${maxUp}</span></div>
1159
+ <div><span style="color:var(--text-dim)">${t('Dienste')}</span><br><span style="font-size:20px;font-weight:700">${d.length}</span></div>
1039
1160
  </div>`;
1040
1161
  }
1041
1162
 
1042
1163
  function renderPlugins() {
1043
1164
  const el = document.getElementById('pluginCard');
1044
1165
  const p = state.plugins || [];
1045
- if (!p.length) { el.innerHTML = '<div class="empty">Keine Plugins installiert</div>'; return; }
1046
- el.innerHTML = p.map(x => `<div style="padding:8px 0;border-bottom:1px solid var(--border);display:flex;justify-content:space-between"><div><div style="font-weight:600;font-size:13px">${x.name}</div><div style="font-size:11px;color:var(--text-dim)">${x.description||''} v${x.version}</div></div><span class="tag tag-green">${x.status||'Geladen'}</span></div>`).join('');
1166
+ if (!p.length) { el.innerHTML = `<div class="empty">${t('Keine Plugins installiert')}</div>`; return; }
1167
+ el.innerHTML = p.map(x => `<div style="padding:8px 0;border-bottom:1px solid var(--border);display:flex;justify-content:space-between"><div><div style="font-weight:600;font-size:13px">${x.name}</div><div style="font-size:11px;color:var(--text-dim)">${x.description||''} v${x.version}</div></div><span class="tag tag-green">${x.status||t('Geladen')}</span></div>`).join('');
1047
1168
  }
1048
1169
 
1049
1170
  // ── Render: Borg ──────────────────────────────────────────
1050
1171
  function renderBorg() {
1051
1172
  const b = state.borg;
1052
1173
  const sEl = document.getElementById('borgStatus'), btn = document.getElementById('borgToggle'), det = document.getElementById('borgDetails'), hist = document.getElementById('borgHistory');
1053
- if (!b || !b.status) { sEl.textContent = 'Nicht verfügbar'; btn.disabled = true; return; }
1174
+ if (!b || !b.status) { sEl.textContent = t('Nicht verfügbar'); btn.disabled = true; return; }
1054
1175
  const s = b.status;
1055
- sEl.innerHTML = `<span class="dot ${s.enabled?'dot-on':'dot-off'}" style="margin-right:6px"></span>${s.enabled?'Aktiv':'Deaktiviert'} &mdash; ${s.mode || 'Standard'}`;
1056
- btn.disabled = false; btn.className = s.enabled ? 'btn btn-active' : 'btn'; btn.textContent = s.enabled ? 'Deaktivieren' : 'Aktivieren';
1057
- det.innerHTML = `<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;font-size:12px;margin-top:8px"><div><span style="color:var(--text-dim)">Syncs</span><br><strong>${s.totalSyncs||0}</strong></div><div><span style="color:var(--text-dim)">Gesendet</span><br><strong>${s.totalSent||0}</strong></div><div><span style="color:var(--text-dim)">Empfangen</span><br><strong>${s.totalReceived||0}</strong></div></div>`;
1176
+ sEl.innerHTML = `<span class="dot ${s.enabled?'dot-on':'dot-off'}" style="margin-right:6px"></span>${s.enabled?t('Aktiv'):t('Deaktiviert')} &mdash; ${s.mode || t('Standard')}`;
1177
+ btn.disabled = false; btn.className = s.enabled ? 'btn btn-active' : 'btn'; btn.textContent = s.enabled ? t('Deaktivieren') : t('Aktivieren');
1178
+ det.innerHTML = `<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;font-size:12px;margin-top:8px"><div><span style="color:var(--text-dim)">Syncs</span><br><strong>${s.totalSyncs||0}</strong></div><div><span style="color:var(--text-dim)">${t('Gesendet')}</span><br><strong>${s.totalSent||0}</strong></div><div><span style="color:var(--text-dim)">${t('Empfangen')}</span><br><strong>${s.totalReceived||0}</strong></div></div>`;
1058
1179
  const h = b.history || [];
1059
- if (!h.length) { hist.innerHTML = '<div class="empty">Noch kein Sync passiert</div>'; return; }
1060
- hist.innerHTML = `<table class="tbl"><thead><tr><th>Zeit</th><th>Richtung</th><th>Partner</th><th>Elemente</th><th>Akzeptiert</th></tr></thead><tbody>` +
1061
- h.slice(-15).reverse().map(x => `<tr><td>${new Date(x.timestamp).toLocaleTimeString('de-DE')}</td><td>${x.direction==='sent'?'&#x2B06;':'&#x2B07;'} ${x.direction==='sent'?'Gesendet':'Empfangen'}</td><td>${x.peer}</td><td>${x.itemCount}</td><td>${x.accepted}</td></tr>`).join('') + '</tbody></table>';
1180
+ if (!h.length) { hist.innerHTML = `<div class="empty">${t('Noch kein Sync passiert')}</div>`; return; }
1181
+ hist.innerHTML = `<table class="tbl"><thead><tr><th>${t('Zeit')}</th><th>${t('Richtung')}</th><th>${t('Partner')}</th><th>${t('Elemente')}</th><th>${t('Akzeptiert')}</th></tr></thead><tbody>` +
1182
+ h.slice(-15).reverse().map(x => `<tr><td>${new Date(x.timestamp).toLocaleTimeString(getLocale())}</td><td>${x.direction==='sent'?'&#x2B06;':'&#x2B07;'} ${x.direction==='sent'?t('Gesendet'):t('Empfangen')}</td><td>${x.peer}</td><td>${x.itemCount}</td><td>${x.accepted}</td></tr>`).join('') + '</tbody></table>';
1062
1183
  }
1063
1184
  document.getElementById('borgToggle').addEventListener('click', async () => {
1064
1185
  if (!state.borg?.status) return;
@@ -1079,7 +1200,7 @@ function renderDebates() {
1079
1200
  // Recent debates
1080
1201
  const list = d.recent || [];
1081
1202
  const listEl = document.getElementById('debateList');
1082
- if (!list.length) { listEl.innerHTML = '<div class="empty">Noch keine Debatten gestartet</div>'; }
1203
+ if (!list.length) { listEl.innerHTML = `<div class="empty">${t('Noch keine Debatten gestartet')}</div>`; }
1083
1204
  else {
1084
1205
  listEl.innerHTML = list.map(db => {
1085
1206
  const statusCol = db.status === 'synthesized' ? 'var(--green)' : db.status === 'open' ? 'var(--yellow)' : 'var(--cyan)';
@@ -1089,15 +1210,15 @@ function renderDebates() {
1089
1210
  <strong style="color:var(--cyan)">#${db.id}: ${db.question?.substring(0,80)||'?'}</strong>
1090
1211
  <span style="color:${statusCol};font-size:11px;text-transform:uppercase">${db.status}</span>
1091
1212
  </div>
1092
- <div style="font-size:11px;color:var(--text-dim);margin-top:4px">${persp} Perspektiven | ${db.created_at ? new Date(db.created_at).toLocaleString('de-DE') : ''}</div>
1093
- ${db.synthesis ? `<div style="font-size:11px;margin-top:4px;color:var(--green)">Konsens: ${(db.synthesis.consensus||'').substring(0,120)}...</div>` : ''}
1213
+ <div style="font-size:11px;color:var(--text-dim);margin-top:4px">${persp} ${t('Perspektiven')} | ${db.created_at ? new Date(db.created_at).toLocaleString(getLocale()) : ''}</div>
1214
+ ${db.synthesis ? `<div style="font-size:11px;margin-top:4px;color:var(--green)">${t('Konsens:')} ${(db.synthesis.consensus||'').substring(0,120)}...</div>` : ''}
1094
1215
  </div>`;
1095
1216
  }).join('');
1096
1217
  }
1097
1218
  // Challenges
1098
1219
  const chList = d.challenges || [];
1099
1220
  const chEl = document.getElementById('challengeList');
1100
- if (!chList.length) { chEl.innerHTML = '<div class="empty">Noch keine Challenges durchgeführt</div>'; }
1221
+ if (!chList.length) { chEl.innerHTML = `<div class="empty">${t('Noch keine Challenges durchgeführt')}</div>`; }
1101
1222
  else {
1102
1223
  chEl.innerHTML = chList.map(c => {
1103
1224
  const icon = c.outcome === 'survived' ? '\u2705' : c.outcome === 'weakened' ? '\u26A0\uFE0F' : '\u274C';
@@ -1114,7 +1235,7 @@ function renderDebates() {
1114
1235
  // Vulnerable
1115
1236
  const vulList = d.vulnerable || [];
1116
1237
  const vulEl = document.getElementById('vulnerableList');
1117
- if (!vulList.length) { vulEl.innerHTML = '<div class="empty">Keine verwundbaren Prinzipien</div>'; }
1238
+ if (!vulList.length) { vulEl.innerHTML = `<div class="empty">${t('Keine verwundbaren Prinzipien')}</div>`; }
1118
1239
  else {
1119
1240
  vulEl.innerHTML = vulList.map(v => {
1120
1241
  const pct = ((v.resilienceScore || 0) * 100).toFixed(0);
@@ -1265,7 +1386,7 @@ function initCrossBrainCanvas() {
1265
1386
  }
1266
1387
  if(borgEnabled) {
1267
1388
  ctx.fillStyle='rgba(170,136,255,0.7)'; ctx.font='10px Segoe UI,sans-serif'; ctx.textAlign='center';
1268
- ctx.fillText(`BORG AKTIV \u2022 ${borgSent} gesendet \u2022 ${borgRecv} empfangen`, w/2, h-8);
1389
+ ctx.fillText(`${t('BORG AKTIV')} \u2022 ${borgSent} ${t('gesendet')} \u2022 ${borgRecv} ${t('empfangen')}`, w/2, h-8);
1269
1390
  }
1270
1391
  ctx.restore(); requestAnimationFrame(draw);
1271
1392
  }
@@ -1279,6 +1400,8 @@ function formatK(n) { if(n>=1e6) return (n/1e6).toFixed(1)+'M'; if(n>=1e3) retur
1279
1400
  function escHtml(s) { const d=document.createElement('div'); d.textContent=s; return d.innerHTML; }
1280
1401
 
1281
1402
  // ── Init ──────────────────────────────────────────────────
1403
+ document.getElementById('langToggle').textContent = currentLang.toUpperCase();
1404
+ updateStaticTexts();
1282
1405
  connectSSE(); loadInitial(); initCrossBrainCanvas();
1283
1406
  window.addEventListener('resize', () => { if(state.ecosystem?.brains) drawPeerGraph(state.ecosystem.brains); });
1284
1407
  </script>