Files
html/agents-archi.html

1592 lines
114 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<!-- WEVAL-V75-1-NO-AVATAR-UNIFIER: agents-archi uses dicebear/robohash inline - DO NOT inject V73/V74/V75 AvatarUnifier here (breaks visual) -->
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVIA — Architecture Agents IA 3D</title>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@700;900&family=Nunito:wght@600;700;800&display=swap" rel="stylesheet">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{overflow:hidden;font-family:'Nunito';transition:background .5s}
body.day{background:#f5f0e8}body.night{background:#060d1a}
canvas{display:block}
@keyframes crownGlow{0%,100%{text-shadow:0 0 8px rgba(255,215,0,.6)}50%{text-shadow:0 0 16px rgba(255,215,0,.9)}}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-2px)}}
@keyframes masterPulse{0%,100%{filter:brightness(1) drop-shadow(0 0 8px rgba(255,215,0,.5))}50%{filter:brightness(1.2) drop-shadow(0 0 16px rgba(255,215,0,.9))}}
@keyframes twinkle{0%,100%{opacity:.15}50%{opacity:.5}}
@keyframes statPulse{0%,100%{opacity:1}50%{opacity:0.85}}
@keyframes edgePulse{0%,100%{opacity:0.4}50%{opacity:0.8}}
.hud{position:fixed;top:0;left:0;right:0;z-index:10;pointer-events:none}
.top-bar{display:flex;justify-content:space-between;align-items:center;padding:6px 14px;pointer-events:auto;transition:.5s}
.day .top-bar{background:linear-gradient(180deg,rgba(245,240,232,.95),transparent);color:#1e293b}
.night .top-bar{background:linear-gradient(180deg,rgba(5,10,24,.95),transparent);border-bottom:1px solid rgba(6,182,212,.1);color:#e2e8f0}
.logo{font:900 14px Orbitron;letter-spacing:2px}.day .logo{color:#059669}.night .logo{color:#06b6d4}
.stats{display:flex;gap:12px;font:700 10px Nunito}.stats b{margin-left:2px}
.nav{display:flex;gap:3px;font:700 9px Nunito}
.nav a{padding:2px 8px;border-radius:4px;text-decoration:none;transition:.2s}
.day .nav a{color:#475569;border:1px solid #d1d5db}.day .nav a:hover{background:#059669;color:#fff;border-color:#059669}
.night .nav a{color:#64748b;border:1px solid #1e293b}.night .nav a:hover{background:#06b6d4;color:#fff;border-color:#06b6d4}
.toggle{position:fixed;top:40px;right:14px;z-index:20;cursor:pointer;font-size:18px;border:none;background:none;pointer-events:auto}
/* AGENT CARD */
.ag-card{text-align:center;pointer-events:auto;cursor:pointer;transition:transform .2s;position:relative}
.ag-card{opacity:0.85;transition:opacity 0.2s}
.ag-card:hover{opacity:1;transform:scale(1.15);filter:brightness(1.1)}
.ag-card img{animation:bob 4s ease-in-out infinite;width:clamp(30px,2.8vw,42px);height:clamp(30px,2.8vw,42px);transition:transform .3s;border-radius:50%;border:2px solid rgba(255,255,255,.15);background:transparent;display:block;margin:0 auto 3px;object-fit:cover;transition:all .2s;filter:drop-shadow(0 0 3px rgba(6,182,212,.3))}
.ag-card[data-tier="0"] img{width:clamp(30px,2.8vw,42px);height:clamp(30px,2.8vw,42px);border-color:#06b6d4;box-shadow:0 0 12px rgba(6,182,212,.4)}
.ag-card[data-tier="1"] img{width:clamp(30px,2.8vw,42px);height:clamp(30px,2.8vw,42px);border-color:rgba(139,92,246,.5)}
.ag-card[data-tier="2"] .name{display:block}
.ag-card[data-tier="2"] img{width:clamp(24px,2.2vw,34px);height:clamp(24px,2.2vw,34px);border-color:rgba(245,158,11,.4)}
.ag-card[data-tier="3"] .name{display:block}
.ag-card[data-tier="3"] img{width:clamp(22px,2vw,30px);height:clamp(22px,2vw,30px);border-color:rgba(239,68,68,.4)}
.ag-card[data-tier="1"] .name{display:block}
.ag-card[data-tier="2"] .name,.ag-card[data-tier="3"] .name{font-size:4px;display:block;opacity:0.7}
.ag-card[data-tier="2"]:hover .name,.ag-card[data-tier="3"]:hover .name{display:block}
.ag-card[data-tier="0"] .name{display:block}
.ag-card[data-tier="0"]:hover .name{display:block;font-size:10px;font-weight:800}
.ag-card:hover img{border-color:#06b6d4;box-shadow:0 0 14px rgba(6,182,212,.35),0 0 28px rgba(6,182,212,.15)}
.ag-card .desc{display:none;font-size:6px;opacity:0.6;max-width:60px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ag-card:hover .desc{display:block}
.ag-card:hover .name{display:block!important;position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:rgba(0,0,0,0.9);color:#fff;padding:4px 8px;border-radius:6px;white-space:nowrap;z-index:999;font-size:12px!important;pointer-events:none;border:1px solid rgba(6,182,212,0.5);box-shadow:0 2px 8px rgba(0,0,0,0.5)}
.ag-card .name{max-width:45px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:700 5px Nunito;line-height:1.1;margin:0 auto;opacity:0.85}
.night .ag-card .desc{display:none;font-size:6px;opacity:0.6;max-width:60px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ag-card:hover .desc{display:block}
.ag-card:hover .name{display:block!important;position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:rgba(0,0,0,0.9);color:#fff;padding:4px 8px;border-radius:6px;white-space:nowrap;z-index:999;font-size:12px!important;pointer-events:none;border:1px solid rgba(6,182,212,0.5);box-shadow:0 2px 8px rgba(0,0,0,0.5)}
.ag-card .name{max-width:45px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#cbd5e1;font:700 5px Nunito;opacity:0.85}.day .ag-card .desc{display:none;font-size:6px;opacity:0.6;max-width:60px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ag-card:hover .desc{display:block}
.ag-card:hover .name{display:block!important;position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:rgba(0,0,0,0.9);color:#fff;padding:4px 8px;border-radius:6px;white-space:nowrap;z-index:999;font-size:12px!important;pointer-events:none;border:1px solid rgba(6,182,212,0.5);box-shadow:0 2px 8px rgba(0,0,0,0.5)}
.ag-card .name{max-width:45px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#334155;font:700 5px Nunito;opacity:0.85}
.ag-card .badge{position:absolute;top:-2px;right:2px;font:800 6px Nunito;padding:1px 3px;border-radius:3px;line-height:1}
.badge.ok{background:#065f46;color:#166534}.badge.warn{background:#78350f;color:#fbbf24}
.day .badge.ok{background:#d1fae5;color:#065f46}.day .badge.warn{background:#fef3c7;color:#92400e}
.ag-card .bubble{display:none;font:700 6px Nunito;max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:2px 6px;border-radius:6px;position:absolute;top:-14px;left:50%;transform:translateX(-50%);z-index:50;pointer-events:none}
.ag-card .bubble.show{display:none}
.ag-card .bubble.active{display:none!important}
.ag-card .bubble.warn{display:block!important;color:#f59e0b;background:rgba(0,0,0,0.9);border:1px solid rgba(245,158,11,.4);border-radius:6px;font-size:5px;opacity:0.9;max-width:70px;white-space:nowrap}
.ag-card .bubble.idle{display:block!important;color:#94a3b8;background:rgba(0,0,0,0.85);border:1px solid rgba(71,85,105,.4);border-radius:6px;font-size:5px;opacity:0.8;max-width:70px;white-space:nowrap}
.ag-card .bubble.offline{display:block!important;color:#ef4444;background:rgba(0,0,0,0.95);border:1px solid rgba(239,68,68,.6);border-radius:6px;font-size:6px;opacity:1;max-width:80px;white-space:nowrap}
.ag-card.is-active img{border-color:#4ade80;box-shadow:0 0 10px rgba(74,222,128,.4)}
.ag-card .dot{width:5px;height:5px;border-radius:50%;background:#4ade80;position:absolute;top:0;left:2px;box-shadow:0 0 4px #4ade80;animation:pd 1.5s infinite}
@keyframes pd{0%,100%{opacity:1}50%{opacity:.3}}
/* WEVIA MASTER special */
.ag-card.master img{border:2px solid #ffd700;box-shadow:0 0 8px rgba(255,215,0,.35)}
.ag-card.master .name{display:none}
.ag-card.master:hover .name{display:block;font-size:9px;font-weight:900;color:#ffd700;letter-spacing:1px;text-shadow:0 0 8px rgba(255,215,0,.6)}
.ag-card.master .crown{position:absolute;top:-22px;left:50%;transform:translateX(-50%);font-size:13px;animation:crownGlow 2s ease-in-out infinite;z-index:5;filter:drop-shadow(0 1px 2px rgba(0,0,0,0.4))}
/* KPI */
.kpi-panel{display:block}
.kpi{padding:8px 10px;border-radius:10px;font:700 9px Nunito;pointer-events:auto;min-width:110px;backdrop-filter:blur(8px)}
.day .kpi{background:rgba(255,255,255,.85);border:1px solid #e2e8f0;color:#334155}
.night .kpi{background:rgba(15,23,42,.8);border:1px solid rgba(100,116,139,.12);color:#94a3b8}
.kpi .tn{font:800 12px Nunito;margin-bottom:3px}.kpi .m{display:flex;justify-content:space-between;font-size:8px;padding:1px 0}.kpi .v{font-weight:900;color:#06b6d4;font-size:10px}
.day .kpi .v{color:#059669}
/* RISK panel */
.risk-panel{display:none}
.risk-item{padding:3px 6px;border-radius:5px;font:700 7px Nunito;display:inline-flex;align-items:center;gap:3px;backdrop-filter:blur(6px)}
.night .risk-item{background:rgba(15,23,42,.7);color:#94a3b8}.day .risk-item{background:rgba(255,255,255,.8);color:#475569}
.risk-dot{width:6px;height:6px;border-radius:50%}.risk-dot.g{background:#4ade80}.risk-dot.y{background:#fbbf24}.risk-dot.r{background:#ef4444}
/* Bottom */
.bottom{position:fixed;bottom:4px;left:0;right:0;display:flex;justify-content:center;gap:20px;z-index:10;pointer-events:none}
.bm{text-align:center}.bm .v{font:900 14px;animation:statPulse 3s ease-in-out infinite Orbitron}
.day .bm .v{background:linear-gradient(135deg,#059669,#10b981);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.night .bm .v{background:linear-gradient(135deg,#06b6d4,#8b5cf6);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.bm .l{font:800 7px Nunito;letter-spacing:3px}.day .bm .l{color:#64748b}.night .bm .l{color:#475569}
/* Modal */
.mbg{position:fixed;inset:0;z-index:100;display:none;align-items:center;justify-content:center}
.mbg.show{display:flex}.day .mbg{background:rgba(0,0,0,.2)}.night .mbg{background:rgba(0,0,0,.5)}
.mcard{border-radius:12px;padding:20px;min-width:280px;max-width:360px;position:relative}
.day .mcard{background:#fff;border:1px solid #e2e8f0;box-shadow:0 16px 48px rgba(0,0,0,.12)}
.night .mcard{background:#0f1629;border:1px solid rgba(6,182,212,.2);box-shadow:0 16px 48px rgba(0,0,0,.5)}
.mcard .close{position:absolute;top:6px;right:10px;cursor:pointer;font-size:20px;animation:crownGlow 2s ease-in-out infinite;border:none;background:none;color:#64748b}
.mcard img{width:56px;height:56px;border-radius:12px;border:2px solid #06b6d4;margin-bottom:6px}
.mcard h3{font:800 15px Nunito;margin-bottom:2px}.mcard .ti{font:600 9px Nunito;color:#64748b;margin-bottom:8px}
.mcard .desc{font:600 11px Nunito;margin-bottom:10px}.day .mcard .desc{color:#475569}.night .mcard .desc{color:#94a3b8}
.mcard a{display:inline-block;padding:5px 14px;color:#fff;text-decoration:none;border-radius:6px;font:700 10px Nunito}
.day .mcard a{background:#059669}.night .mcard a{background:linear-gradient(135deg,#06b6d4,#8b5cf6)}
@media(max-width:1600px){
.hud .stats{font-size:9px}.hud .nav a{font-size:8px}
}
@media(max-width:1200px){
.hud .stats{font-size:8px;gap:6px}.hud .nav a{padding:2px 5px;font-size:7px}
}
@media(max-width:900px){
.hud .stats{display:none}.hud .nav{flex-wrap:wrap}
}
/* WAVE 118 — Live cockpit overlay */
.cockpit-live{position:fixed;top:38px;display:none!important;left:14px;right:14px;display:flex;justify-content:center;gap:5px;z-index:15;pointer-events:none;flex-wrap:wrap}
.cockpit-pill{background:rgba(245,237,224,.92);border:1px solid rgba(148,163,184,.3);border-radius:14px;padding:3px 8px;backdrop-filter:blur(12px);font:700 8px Nunito;color:#cbd5e1;display:flex;align-items:center;gap:3px;pointer-events:auto;transition:all .3s;box-shadow:0 1px 4px rgba(0,0,0,.2)}
.cockpit-pill:hover{transform:translateY(-1px);border-color:#06b6d4}
.cockpit-pill .lbl{color:#64748b;font-weight:600;font-size:7px;text-transform:uppercase;letter-spacing:0.5px}
.cockpit-pill .val{color:#e2e8f0;font-weight:900;font-size:9px}
.cockpit-pill.green{border-color:#10b981;box-shadow:0 0 12px rgba(16,185,129,.35)}
.cockpit-pill.green .val{color:#10b981}
.cockpit-pill.yellow{border-color:#f59e0b;box-shadow:0 0 12px rgba(245,158,11,.35)}
.cockpit-pill.yellow .val{color:#fbbf24}
.cockpit-pill.red{border-color:#ef4444;box-shadow:0 0 12px rgba(239,68,68,.35);animation:pulseRed 1.5s infinite}
.cockpit-pill.red .val{color:#ef4444}
@keyframes pulseRed{0%,100%{box-shadow:0 0 12px rgba(239,68,68,.35)}50%{box-shadow:0 0 22px rgba(239,68,68,.6)}}
.cockpit-dot{width:8px;height:8px;border-radius:50%;background:#10b981;box-shadow:0 0 6px currentColor;animation:pd 2s infinite}
.cockpit-dot.yellow{background:#f59e0b}
.cockpit-dot.red{background:#ef4444}
#w116-modal{max-width:760px!important;padding:28px!important}
#w116-modal #w116-title{font:800 17px Orbitron!important}
#w116-modal #w116-body{font:500 12px monospace!important;line-height:1.6!important;max-height:55vh;overflow-y:auto}
/* WAVE 178: Responsive sidebars — pyramid first */
#kpiOverlay{transition:opacity .3s,transform .3s}
/* KPIs always visible — no hide on small viewport */
@media(min-width:1201px){
#kpiOverlay{opacity:0.8!important;pointer-events:auto}
[style*="position:fixed;left:8px"]{opacity:0.8!important;pointer-events:auto}
}
#liveStatusBar{display:none!important}
[style*="bottom:8px"][style*="left:200px"]{display:none!important}
</style>
<style>/* L99-OVERLAP-FIX */
.label,.tag,.badge,.tooltip{pointer-events:none;z-index:0}
canvas{z-index:0!important}
</style>
<script src="/widgets/audit-banner.js" defer></script>
<script src="/api/weval-avatar-helper.js?v=d91" defer></script>
<style id="d91-archi-persona">
/* ---- D91 persona pills replacing dicebear/robohash in agents-archi ---- */
.p-av{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;
border:2px solid rgba(255,255,255,.25);background:#ffffff10;
font-family:'Apple Color Emoji','Segoe UI Emoji','Noto Color Emoji',sans-serif;
line-height:1;overflow:hidden;margin:0 auto 3px;animation:bob 4s ease-in-out infinite;
box-shadow:0 0 3px rgba(6,182,212,.3),inset 0 1px 0 #ffffff20;
transition:all .2s;flex-shrink:0;will-change:transform}
.p-av[data-persona="master"]{border-color:#06b6d4!important;box-shadow:0 0 12px rgba(6,182,212,.55)!important;background:linear-gradient(135deg,#f59e0b22,#dc262622)}
.p-av[data-persona="tool"]{border-style:dashed;background:#0b1120aa}
.ag-card[data-tier="0"] .p-av{width:clamp(30px,2.8vw,42px);height:clamp(30px,2.8vw,42px);font-size:clamp(18px,1.7vw,26px);border-color:#06b6d4;box-shadow:0 0 12px rgba(6,182,212,.4)}
.ag-card[data-tier="1"] .p-av{width:clamp(30px,2.8vw,42px);height:clamp(30px,2.8vw,42px);font-size:clamp(18px,1.7vw,26px);border-color:rgba(139,92,246,.55)}
.ag-card[data-tier="2"] .p-av{width:clamp(24px,2.2vw,34px);height:clamp(24px,2.2vw,34px);font-size:clamp(14px,1.4vw,20px);border-color:rgba(245,158,11,.55)}
.ag-card[data-tier="3"] .p-av{width:clamp(22px,2vw,30px);height:clamp(22px,2vw,30px);font-size:clamp(13px,1.3vw,18px);border-color:rgba(239,68,68,.55)}
.ag-card:hover .p-av{transform:scale(1.08);filter:brightness(1.1)}
</style>
<!-- WEVAL-D91-AGENTS-ARCHI-PERSONA -->
<style id="d93c">.p-av{width:52px!important;height:52px!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;font-size:28px!important;line-height:1!important;border-radius:50%!important;background:rgba(255,255,255,.06)!important;border:2.5px solid rgba(34,211,238,.55)!important;flex-shrink:0!important;overflow:hidden!important;box-shadow:0 2px 6px rgba(0,0,0,.25)!important}.p-av[data-persona="tool"]{border-color:rgba(139,92,246,.55)!important;background:rgba(139,92,246,.12)!important}.p-av[data-persona="master"]{border-color:rgba(255,215,0,.65)!important;background:rgba(255,215,0,.1)!important;width:64px!important;height:64px!important;font-size:34px!important}.p-av[data-persona="human"]{border-color:rgba(74,222,128,.45)!important;background:rgba(74,222,128,.08)!important}</style>
<!-- V109 Plausible Analytics -->
<script defer data-domain="weval-consulting.com" src="https://analytics.weval-consulting.com/js/script.js"></script>
<script src="/js/wevia-a11y-auto.js" defer></script>
<!-- DOCTRINE-60-UX-ENRICH direct-inject-20260424-143816 -->
<style id="doctrine60-ux-direct">
/* DOCTRINE-60-UX-ENRICH injected-direct */
body::before {
content: '';
position: fixed;
top: 0; left: 0; width: 100vw; height: 100vh;
background: radial-gradient(circle at 50% 50%, rgba(100,180,255,0.08), transparent 60%);
pointer-events: none;
z-index: -1;
}
.card, .kpi, .panel, .btn {
transition: all 0.3s cubic-bezier(0.2,0,0.1,1);
}
.card:hover, .kpi:hover, .panel:hover {
box-shadow: 0 4px 20px rgba(100,180,255,0.2);
border-color: rgba(100,180,255,0.5);
}
@keyframes pulseD60 {
0%,100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.7; transform: scale(1.05); }
}
.pulse, .live-indicator, .active, .online {
animation: pulseD60 3s ease-in-out infinite;
}
.modal, .chat, .speech, .overlay {
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
.enter-stagger {
animation: enterStagD60 0.5s cubic-bezier(0.2,0,0.1,1) forwards;
}
@keyframes enterStagD60 {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
</head><body>
<!-- BETON-DOCTRINE-101 dual-dummy block (pages pub) -->
<div id="weval-global-logout" style="display:none!important;visibility:hidden!important" aria-hidden="true" data-beton-101="dummy-to-block-auto-injection"></div>
<a id="weval-gl" href="#" style="display:none!important;visibility:hidden!important" aria-hidden="true" data-beton-101="dummy-to-block-auto-injection" tabindex="-1"></a>
<div id="liveStatusBar" style="display:none"></div>
<noscript></noscript class="night">
<div class="cockpit-live" id="cockpit-live"><div class="cockpit-pill" id="cp-health"><div class="cockpit-dot"></div><span class="lbl">STATUS</span><span class="val">...</span></div><div class="cockpit-pill" id="cp-l99"><span class="lbl">L99</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-docker"><span class="lbl">DOCKER</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-disk"><span class="lbl">DISK</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-providers"><span class="lbl">PROVIDERS</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-qdrant"><span class="lbl">RAG</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-git"><span class="lbl">GIT</span><span class="val">-</span></div><div class="cockpit-pill" id="cp-refresh"><span class="lbl">REFRESH</span><span class="val">30s</span></div></div>
<div class="hud"><div class="top-bar">
<div class="logo">WEVIA ARCHITECTURE 3D</div>
<div class="stats"><span>🤖 <b>73</b> Agents</span><span>🏗 <b>4</b> Tiers</span><span>🐳 <b>17</b> Docker</span><span>🦙 <b>10</b> Ollama</span><span><b>153/153</b></span></div>
<div class="nav"><a href="/agents-archi.html">3D</a><a href="/director-center.html" title="Centre Director - 39 métriques temps réel">Director</a><a href="/wevia-meeting-rooms.html" title="Salles de réunion agents - collaboration live">Meeting</a><a href="/enterprise-model.html" title="Modèle entreprise - KPIs par département">Enterprise</a><a href="/agents-fleet.html">Fleet</a><a href="https://paperclip.weval-consulting.com">Paperclip</a><a href="/value-stream.html">VSM</a><a href="/value-chain.html">Chain</a><a href="/toolhub.html">Tools</a><a href="/wiki.html">Wiki</a><a href="/api/picker.php">Picker</a><a href="/security-dashboard.html">Security</a></div>
</div></div>
<button class="toggle" id="tgl" onclick="tglTheme()" style="font-size:18px;cursor:pointer;filter:drop-shadow(0 0 4px rgba(255,255,255,.3))">🌙</button>
<div class="mbg" id="mbg" onclick="this.classList.remove('show')"><div class="mcard" onclick="event.stopPropagation()">
<span class="close" onclick="document.getElementById('mbg').classList.remove('show')"></span>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" id="mImg"><h3 id="mN"></h3><div class="ti" id="mT"></div><div class="desc" id="mD"></div><a id="mL" target="_blank">Ouvrir →</a>
</div></div>
<div style="position:fixed;bottom:4px;right:4px;font:600 6px Nunito;color:rgba(100,116,139,.4);z-index:9999;pointer-events:none">ARCHI v3.6 · 10 AVR 2026</div><div class="bottom"><div class="bm"><div class="v">73</div><div class="l">AGENTS</div></div><div class="bm"><div class="v">4</div><div class="l">TIERS</div></div><div class="bm"><div class="v">14</div><div class="l">PROVIDERS</div></div><div class="bm"><div class="v">0€</div><div class="l">COST</div></div></div>
<script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>
<script type="module">
import*as THREE from'three';
import{CSS2DRenderer,CSS2DObject}from'three/addons/renderers/CSS2DRenderer.js';
import{OrbitControls}from'three/addons/controls/OrbitControls.js';
import{EffectComposer}from'three/addons/postprocessing/EffectComposer.js';
import{RenderPass}from'three/addons/postprocessing/RenderPass.js';
import{UnrealBloomPass}from'three/addons/postprocessing/UnrealBloomPass.js';
import{OutputPass}from'three/addons/postprocessing/OutputPass.js';
const{Scene,PerspectiveCamera,WebGLRenderer,Mesh,Color,Group,AmbientLight,DirectionalLight,PointLight,SpotLight,BoxGeometry,PlaneGeometry,CylinderGeometry,SphereGeometry,MeshStandardMaterial,MeshPhysicalMaterial,MeshBasicMaterial,FogExp2,RingGeometry}=THREE;
let isN=true; // wave116: always night
document.body.className=isN?'night':'day';document.getElementById('tgl').textContent=isN?'☀️':'🌙';
window.tglTheme=function(){isN=!isN;document.body.className=isN?'night':'day';document.getElementById('tgl').textContent=isN?'☀️':'🌙';scene.fog=new FogExp2(isN?0x060d1a:0x87ceeb,isN?0.0035:0.0025);ren.setClearColor(isN?0x060d1a:0x87ceeb);amb.intensity=isN?0.4:0.7;dir.intensity=isN?0.7:1;floor.material.color.set(isN?0xC8B898:0x3a7a30);if(grass)grass.material.color.set(isN?0x0a1a0a:0x4a8c3f);if(skyBody){skyBody.material.color.set(isN?0xe0e0e0:0xffd700);skyBody.material.emissive.set(isN?0xaaaacc:0xffaa00);skyBody.material.emissiveIntensity=isN?0.5:2}};
const T=[
{n:'STRATÉGIE',y:22,c:0x06b6d4,h:'#06b6d4',k:['Décisions: 39/cycle','Providers: 14','Coût: 0€','Uptime: 100%']},
{n:'DIRECTION',y:16,c:0x8b5cf6,h:'#8b5cf6',k:['Routes: 46','Consensus: 9.8/10','AutoFix: 20/20','Fiability: 100%']},
{n:'TACTIQUE',y:10,c:0xf59e0b,h:'#f59e0b',k:['NonReg: 153/153','CVE: 0','HCP: 141K+','Skills: 1935']},
{n:'EXÉCUTION',y:4,c:0xef4444,h:'#ef4444',k:['Docker: 17 UP','Ollama: 10','Fleet: 669','PMTA: 4 ECS']},
{n:'MASTER',y:28,c:0xffd700,h:'#ffd700',k:['Intents: 174','Waves: 142','Providers: 7','Cost: 0€']}];
const A=[
{n:'WEVIA Master',t:4,r:1,d:'Head of AI · Orchestrateur Suprême',p:'/wevia.html',m:1,sc:2.5},
{n:'Director',t:1,r:1,d:'Cerveau autonome · 39 métriques',p:'/director-center.html'},
{n:'Master Router',t:1,r:1,d:'46 routes · 14 providers',p:'/architecture.html'},
{n:'Consensus',t:1,r:1,d:'Vote multi-provider 9.8/10',p:'/architecture.html'},
{n:'Dispatcher',t:1,r:1,d:'Moteur de routes intelligent',p:'/architecture.html'},
{n:'MiroFish',t:1,r:1,d:'WePredict auto-guérison',p:'/l99-brain.html'},
{n:'Blade',t:1,r:1,d:'Agent desktop Razer',p:'/api/picker.php'},
{n:'DeerFlow',t:1,r:1,d:'Deep research 12+ sources',p:'/architecture.html'},
{n:'AutoFix',t:1,r:1,d:'Docker heal 16 containers',p:'/architecture.html'},
{n:'Fiability',t:1,r:1,d:'Santé 24 URLs 100%',p:'/l99-brain.html'},
{n:'DevOps',t:2,r:0,d:'CI/CD · 4 serveurs',p:'/architecture.html'},
{n:'Ethica',t:2,r:0,d:'HCP Pharma · 141K+',p:'/enterprise-model.html'},
{n:'Security',t:2,r:0,d:'CVE+SSL+Nuclei',p:'/architecture.html'},
{n:'Monitor',t:2,r:0,d:'Uptime 24/7 · 24 URLs',p:'/l99-brain.html'},
{n:'NonReg',t:2,r:0,d:'Régression 153/153',p:'/l99-brain.html'},
{n:'WEVCODE',t:2,r:0,d:'Code IA · 4 modes',p:'/wevia-fullscreen.php'},
{n:'L99 Pilot',t:2,r:0,d:'Qualité Lean 6σ',p:'/l99-brain.html'},
{n:'Scraper',t:2,r:1,d:'DabaDoc MA+TN+DZ',p:'/enterprise-model.html'},
{n:'ArchScan',t:2,r:1,d:'Topologie 52 nœuds',p:'/architecture.html'},
{n:'CrowdSec',t:2,r:0,d:'IDS/IPS communautaire',p:'/architecture.html'},
{n:'Fail2Ban',t:2,r:0,d:'SSH protect',p:'/architecture.html'},
{n:'Registry',t:2,r:0,d:'Registre 626 pages',p:'/architecture.html'},
{n:'Ollama',t:3,r:1,d:'LLM LOCAL 10 modèles',p:'/architecture.html'},
{n:'Groq',t:3,r:1,d:'<200ms Llama-3.3-70B',p:'/architecture.html'},
{n:'Cerebras',t:3,r:1,d:'Qwen-3 235B',p:'/architecture.html'},
{n:'SambaNova',t:3,r:1,d:'Meta-Llama 3.3',p:'/architecture.html'},
{n:'Paperclip',t:3,r:1,d:'Fleet 669 agents',p:'https://paperclip.weval-consulting.com'},
{n:'Sentinel',t:3,r:1,d:'Relais S95',p:'/architecture.html'},
{n:'Docker',t:3,r:1,d:'17 containers UP',p:'/architecture.html'},
{n:'PMTA',t:3,r:1,d:'MTA sacré 4 ECS',p:'/architecture.html'},
{n:'CEO',t:0,r:0,d:'Yanis Mahboub · Fondateur',p:'/enterprise-model.html'},
{n:'CTO',t:1,r:0,d:'Architecture technique',p:'/architecture.html'},
{n:'CFO',t:1,r:0,d:'Finance · Stripe · 0€ AI',p:'/enterprise-model.html'},
{n:'CMO',t:2,r:0,d:'Marketing · Ethica · B2B',p:'/enterprise-model.html'},
{n:'CISO',t:2,r:0,d:'Sécurité · CrowdSec · Nuclei',p:'/architecture.html'},
{n:'UX Lead',t:2,r:0,d:'Design · premium.css · Responsive',p:'/enterprise-model.html'},
{n:'Wiki',t:2,r:1,d:'Knowledge base · 203 fichiers',p:'/wiki.html'},
{n:'Register',t:3,r:1,d:'Inscription · API · Auth',p:'/register.html'},
{n:'Telegram',t:3,r:1,d:'Bot alerts · Daily brief 7h',p:'/architecture.html'},
{n:'Stripe',t:3,r:1,d:'Paiements · SK+PK LIVE',p:'/enterprise-model.html'},
{n:'L99 Pilot',t:1,r:1,d:'Orchestrateur 1495 checks',p:'/l99-brain.html'},
{n:'ClawCode',t:1,r:1,d:'78 Skills Sovereign',p:'/architecture.html'},
{n:'Analyst',t:0,r:0,d:'Analyse marché · SWOT · B2B',p:'/enterprise-model.html'},
{n:'Architect',t:1,r:0,d:'Cloud archi · Blueprints',p:'/architecture.html'},
{n:'Verifier',t:2,r:0,d:'ISO 27001 · RGPD · PCI-DSS',p:'/architecture.html'},
{n:'GitMaster',t:2,r:1,d:'Git flow · 50 repos · Releases',p:'/architecture.html'},
{n:'DocSpec',t:2,r:0,d:'Templates · API docs · README',p:'/wiki.html'},
{n:'Scientist',t:2,r:1,d:'Benchmarks 182 modèles',p:'/l99-brain.html'},
{n:'LeadForge',t:3,r:1,d:'Lead gen · Score · Enrich',p:'/enterprise-model.html'},
{n:'EthicaScraper',t:3,r:1,d:'DabaDoc MA+TN+DZ scraping',p:'/enterprise-model.html'},
{n:'TaskMgr',t:2,r:1,d:'Kanban · Deadlines · Priorités',p:'/enterprise-model.html'},
{n:'WEDROID',t:1,r:1,d:'Auto-fix v5 · DB+API · Chain S95',p:'/architecture.html'},
{n:'Watchdog',t:2,r:1,d:'Monitor */3min · 24 Docker · Disk',p:'/architecture.html'},
{n:'Guardian',t:2,r:1,d:'chattr +i · Firewall 847 rules',p:'/architecture.html'},
{n:'SC-Orch',t:1,r:1,d:'Multi-agent orchestration L99',p:'/l99-brain.html'},
{n:'SC-Research',t:2,r:1,d:'Deep Research 12+ sources',p:'/l99-brain.html'},
{n:'Academy',t:2,r:0,d:'Training · Auto-learn · Qdrant',p:'/wiki.html'},
{n:'Contract',t:0,r:0,d:'Contract gen · Legal docs · PDF',p:'/enterprise-model.html'},
{n:'Blueprint',t:1,r:1,d:'Auto blueprint · Project scaffold',p:'/architecture.html'},
{n:'Debugger',t:2,r:1,d:'Fix API 500 · Memory leaks',p:'/architecture.html'},
{n:'Simplifier',t:2,r:1,d:'Refactor -40% · Dead code · DRY',p:'/architecture.html'},
{n:'Growth',t:1,r:1,d:'Growth Engine Premium CRM+SEO+Analytics',p:'/growth-engine.html'},
{n:'DarkScout',t:1,r:1,d:'Exploration concurrentielle',p:'/growth-engine.html'},
{n:'SEO',t:1,r:1,d:'SEO Module Hub optimisation',p:'/growth-engine.html'},
{n:'Sovereign Claude',t:0,r:1,d:'Deep reasoning · Opus proxy',p:'/sovereign-claude.html'},
{n:'CodeRabbit',t:2,r:0,d:'Code review · OWASP audit',p:'/api/code-rabbit.php'},
{n:'Chatbot',t:0,r:1,d:'WEVIA public · SSE streaming',p:'/wevia.html'},
{n:'Arena',t:0,r:1,d:'409 options · 18 providers · Consensus',p:'/weval-arena.html'},
{n:'Dynamic Resolver',t:0,r:1,d:'222 tools · Sovereign FC · Auto-wire',p:'/api/wevia-sovereign-fc.php'},
{n:'Trinity Large',t:1,r:1,d:'400B MoE · #1 US open · FREE',p:'/weval-arena.html'},
{n:'MiniMax M27',t:1,r:1,d:'Self-evolution · SWE-Pro 56%',p:'/weval-arena.html'},
{n:'MiMo V2 Omni',t:1,r:1,d:'Multimodal · Image+Video+Audio',p:'/weval-arena.html'},
{n:'Blade Bridge',t:1,r:1,d:'222 tools · 6 actions · PowerShell',p:'/api/blade-tools-bridge.php'},
{n:'Auto-Wire',t:1,r:1,d:'Daily 5AM · Self-learn · Registry',p:'/enterprise-model.html'},
{n:'Ethica Chatbot',t:1,r:1,d:'Pharma-only · 131K HCPs · 8/8 PW',p:'/ethica-app-v3.html'},
{n:'Maestro',t:2,r:0,d:'32B Reasoning · Audit traces',p:'/weval-arena.html'},
{n:'Snap Archiver',t:2,r:0,d:'Hetzner snapshots → Git archive',p:'/enterprise-model.html'},
{n:'Office Hub',t:1,r:1,d:'O365 1131 accounts · S95 PG',p:'/office-hub.html'}
];
var _pk={};try{var x=new XMLHttpRequest();x.open('GET','/api/agent-avatars.php',false);x.send();if(x.status===200)_pk=JSON.parse(x.responseText)}catch(e){}
const scene=new Scene();scene.fog=new FogExp2(isN?0x060d1a:0x87ceeb,isN?0.0035:0.0025);
const cam=new PerspectiveCamera(48,innerWidth/innerHeight,0.1,500);cam.position.set(0,38,45);
const ren=new WebGLRenderer({antialias:true,alpha:true});
ren.setSize(innerWidth,innerHeight);ren.setPixelRatio(Math.min(devicePixelRatio,3));
ren.toneMapping=THREE.ACESFilmicToneMapping;ren.toneMappingExposure=1.5;ren.setClearColor(isN?0x060d1a:0x87ceeb);
document.body.appendChild(ren.domElement);
const composer=new EffectComposer(ren);composer.addPass(new RenderPass(scene,cam));
const bloomPass=new UnrealBloomPass(new THREE.Vector2(innerWidth,innerHeight),0.4,0.3,0.85);
composer.addPass(bloomPass);composer.addPass(new OutputPass());
const css2=new CSS2DRenderer();css2.setSize(innerWidth,innerHeight);css2.domElement.style.cssText='position:absolute;top:0;pointer-events:none;z-index:55';document.body.appendChild(css2.domElement);
const ctrl=new OrbitControls(cam,ren.domElement);ctrl.target.set(0,14,0);ctrl.enableDamping=true;ctrl.dampingFactor=0.08;ctrl.maxPolarAngle=Math.PI;ctrl.minPolarAngle=0;ctrl.enableZoom=true;ctrl.minDistance=10;ctrl.maxDistance=500;ctrl.enablePan=true;ctrl.zoomSpeed=1.5;ctrl.rotateSpeed=0.8;ctrl.autoRotate=true;ctrl.autoRotateSpeed=0.3;
// ARROWS
const aM=new MeshPhysicalMaterial({color:0x06b6d4,emissive:0x06b6d4,emissiveIntensity:0.5,transparent:true,opacity:0.6});
/* WAVE 193: antennas removed */
// PARTICLES
/* WAVE 193: particles removed */ var pts={material:{color:{set:function(){}}},rotation:{y:0}};
// GLOW
/* WAVE 153: glow rings removed */
const amb=new AmbientLight(0xffffff,isN?0.6:0.9);scene.add(amb);
const dir=new DirectionalLight(0xffffff,isN?1.2:1.5);dir.position.set(12,25,10);scene.add(dir);const dir2=new DirectionalLight(0xffffff,isN?0.4:0.3);dir2.position.set(-15,15,-10);scene.add(dir2);
/* WAVE 193: cyan light removed */
scene.add(new PointLight(0x8b5cf6,0.2,50).translateX(8).translateY(6));
const spot=new SpotLight(0xffd700,0.6,30,Math.PI/8,0.5);spot.position.set(0,18,0);spot.target.position.set(0,10,0);scene.add(spot);scene.add(spot.target);
// FLOOR
/* WAVE 173b: floor removed */
var floor={material:{color:{set:function(){}}}};
// carpet grid removed (sized for old platforms)
// floor grid removed
// PLATFORMS
T.forEach(function(t,ti){
const w=[14,24,32,40,10][ti],d=[14,24,32,40,10][ti];
const p=new Mesh(new CylinderGeometry(w/2,w/2,1.5,64),new MeshPhysicalMaterial({color:isN?0xF5EDD5:0xFAF5EB,metalness:0.08,roughness:0.65,clearcoat:0.3,clearcoatRoughness:0.4,reflectivity:0.2,transparent:false,opacity:1}));
p.position.y=t.y;scene.add(p);/* W153 ring removed */
var carpet=new Mesh(new CylinderGeometry(w*0.46,w*0.46,0.3,48),new MeshStandardMaterial({color:isN?0xEDE0C8:0xF8F2E8,roughness:0.95,metalness:0.01,transparent:true,opacity:0.75}));carpet.position.y=t.y+0.16;scene.add(carpet);
// WAVE 190: Meeting table (inner glowing disc)
var tableR=w*0.35;
var table=new Mesh(new CylinderGeometry(tableR,tableR,0.15,48),new MeshPhysicalMaterial({color:t.c,emissive:t.c,emissiveIntensity:0.25,metalness:0.7,roughness:0.15,clearcoat:1,transparent:true,opacity:0.85}));
table.position.y=t.y+0.25;scene.add(table);
// platform grid removed
/* W153 edge removed */
const ld=document.createElement('div');ld.style.cssText='font:900 6px Orbitron;letter-spacing:1px;opacity:0.5;text-shadow:0 0 6px currentColor;color:#3a2a1a;pointer-events:none;background:rgba(250,245,235,0.95);padding:2px 8px;border-radius:4px;border:1px solid '+t.h+'40;white-space:nowrap';ld.textContent=t.n;
scene.add(new CSS2DObject(ld).translateY(t.y-1.2));
// KPI panel at right edge
var kd=document.createElement('div');
kd.style.cssText='background:rgba(245,237,224,.92);border:1px solid '+t.h+';border-radius:8px;padding:8px 13px;backdrop-filter:blur(10px);pointer-events:none;width:200px';
var kh='<div style="font:800 12px Nunito;color:'+t.h+'">● '+t.n+'</div>';
t.k.forEach(function(k){var p=k.split(':');kh+='<div style="display:flex;justify-content:space-between;font:600 9px Nunito;color:#5a4a3a"><span>'+p[0]+'</span><span style="font-weight:900;color:'+t.h+'">'+p[1]+'</span></div>'});
var labels=['Uptime','Consensus','NonReg','Docker','Intents'];
var curves=['8,18 25,14 42,16 59,10 76,8 93,6 110,5 127,3','8,16 25,12 42,14 59,8 76,10 93,6 110,4 127,3','8,6 25,6 42,4 59,6 76,4 93,4 110,4 127,3','8,10 25,8 42,12 59,6 76,8 93,4 110,6 127,4','8,20 25,16 42,14 59,10 76,8 93,6 110,4 127,2'];
kh+='<svg width="210" height="55" style="margin-top:3px"><line x1="12" y1="30" x2="150" y2="30" stroke="#1e293b" stroke-width=".4"/><line x1="12" y1="2" x2="12" y2="30" stroke="#1e293b" stroke-width=".4"/><text x="2" y="6" fill="#64748b" font-size="7" font-family="Nunito">100</text><text x="4" y="18" fill="#64748b" font-size="7" font-family="Nunito">50</text><text x="6" y="30" fill="#64748b" font-size="7" font-family="Nunito">0</text><line x1="12" y1="16" x2="150" y2="16" stroke="#1e293b" stroke-width=".2" stroke-dasharray="2"/><text x="70" y="28" fill="'+t.h+'" font-size="5" text-anchor="middle" font-family="Nunito" font-weight="bold">'+labels[ti]+' 7j</text><polyline points="'+curves[ti]+'" fill="none" stroke="'+t.h+'" stroke-width="1.5" stroke-linecap="round"/><polygon points="'+curves[ti]+' 127,24 8,24" fill="'+t.h+'" fill-opacity=".12"/><circle cx="127" cy="'+curves[ti].split(' ').pop().split(',')[1]+'" r="2" fill="'+t.h+'"/></svg>';
kd.innerHTML=kh;
var kObj=new CSS2DObject(kd);
kObj.position.set(w/2+10, t.y-0.2, 0);
//kObj off
});
// CONNECTORS
for(let i=0;i<T.length-1;i++){const g=new Mesh(new CylinderGeometry(0.025,0.025,Math.abs(T[i].y-T[i+1].y)-0.2,6),new MeshBasicMaterial({color:T[i+1].c,transparent:true,opacity:0.35}));g.position.y=(T[i].y+T[i+1].y)/2;scene.add(g)}
// === HIERARCHY LINKS v2 ===
setTimeout(function(){var hl=[];function aL(fn,tn,col,op){var fp=_agentPositions[fn],tp=_agentPositions[tn];if(!fp||!tp)return;var mid=new THREE.Vector3((fp.x+tp.x)/2,Math.max(fp.y,tp.y)+2.5,(fp.z+tp.z)/2);var cv=new THREE.QuadraticBezierCurve3(new THREE.Vector3(fp.x,fp.y+0.5,fp.z),mid,new THREE.Vector3(tp.x,tp.y+0.5,tp.z));var g=new THREE.BufferGeometry().setFromPoints(cv.getPoints(24));var m=new THREE.LineBasicMaterial({color:col,transparent:true,opacity:op||0.4});var l=new THREE.Line(g,m);scene.add(l);hl.push(l)}aL('WEVIA Master','Arena',0x06b6d4,0.5);aL('WEVIA Master','Dynamic Resolver',0x06b6d4,0.5);aL('WEVIA Master','Sovereign Claude',0x06b6d4,0.45);aL('WEVIA Master','Chatbot',0x06b6d4,0.45);aL('WEVIA Master','Director',0x8b5cf6,0.5);aL('WEVIA Master','Master Router',0x8b5cf6,0.45);aL('WEVIA Master','AutoFix',0x8b5cf6,0.4);aL('WEVIA Master','Fiability',0x8b5cf6,0.4);aL('WEVIA Master','Blade Bridge',0x8b5cf6,0.4);aL('WEVIA Master','Blade',0x8b5cf6,0.35);aL('WEVIA Master','DeerFlow',0x8b5cf6,0.35);aL('WEVIA Master','Ethica Chatbot',0x8b5cf6,0.35);aL('Director','DevOps',0xf59e0b,0.35);aL('Director','Security',0xf59e0b,0.35);aL('Director','NonReg',0xf59e0b,0.35);aL('Director','L99 Pilot',0xf59e0b,0.35);aL('Director','Monitor',0xf59e0b,0.3);aL('Director','Ethica',0xf59e0b,0.3);aL('Director','Scraper',0xf59e0b,0.3);aL('Director','ArchScan',0xf59e0b,0.3);aL('Master Router','Ollama',0xef4444,0.35);aL('Master Router','Groq',0xef4444,0.35);aL('Master Router','Cerebras',0xef4444,0.35);aL('Master Router','Trinity Large',0xef4444,0.3);aL('Master Router','MiniMax M27',0xef4444,0.3);console.log('Hierarchy:'+hl.length+' links')},2500);
// === HIERARCHY FLOW MESSAGES v1 ===
setTimeout(function(){
var hFlows=[];
var msgs={
'WEVIA Master→Arena':['route model','consensus','benchmark','409 options'],
'WEVIA Master→Dynamic Resolver':['match tool','222 tools','keyword scan','exec cmd'],
'WEVIA Master→Director':['observe','plan','act','verify','cycle 39'],
'WEVIA Master→Master Router':['route LLM','cascade 0EUR','fallback','provider check'],
'WEVIA Master→AutoFix':['docker heal','restart','check 20/20','auto-repair'],
'WEVIA Master→Fiability':['24 URLs','100% uptime','health check','status OK'],
'WEVIA Master→Blade Bridge':['222 tools','PowerShell','sync','exec task'],
'WEVIA Master→DeerFlow':['deep research','12 sources','RAG query','wiki scan'],
'WEVIA Master→Ethica Chatbot':['131K HCPs','pharma filter','consent check','pipeline'],
'WEVIA Master→Sovereign Claude':['opus proxy','deep reasoning','strategy','analysis'],
'WEVIA Master→Chatbot':['user query','SSE stream','response','context'],
'WEVIA Master→Blade':['sync files','heartbeat','task queue','PowerShell'],
'Director→DevOps':['CI/CD','deploy','Docker 17','git push'],
'Director→Security':['0 CVE','SSL 357j','CrowdSec','Nuclei scan'],
'Director→NonReg':['153/153','Sigma 6','DPMO 0','test run'],
'Director→L99 Pilot':['957 checks','quality gate','lean 6sigma','pipeline'],
'Director→Monitor':['24 URLs','99.97%','alert check','status'],
'Director→Ethica':['141K+ HCPs','enrich DZ','pipeline MA','gap TN'],
'Director→Scraper':['DabaDoc 50/min','proxy rotate','queue 12','scrape'],
'Director→ArchScan':['52 nodes','38 edges','topology','BPMN 6'],
'Master Router→Ollama':['qwen3:4b','inference','local embed','sovereign'],
'Master Router→Groq':['llama-3.3 70B','<200ms','stream','batch'],
'Master Router→Cerebras':['Qwen-235B','wafer-scale','reasoning','code gen'],
'Master Router→Trinity Large':['400B MoE','FREE','Apache 2.0','OpenRouter'],
'Master Router→MiniMax M27':['self-evolve','SWE-Pro 56%','agentic','debug']
};
function addHFlow(fn,tn,col){
var fp=_agentPositions[fn],tp=_agentPositions[tn];
if(!fp||!tp)return;
var key=fn+'→'+tn;
var pool=msgs[key]||['sync','data','check','OK'];
var dot=new THREE.Mesh(new THREE.SphereGeometry(0.3,8,8),new THREE.MeshBasicMaterial({color:col,transparent:true,opacity:0.8}));
scene.add(dot);
var lDiv=document.createElement('div');
lDiv.style.cssText='font:600 5px Nunito;color:#fff;background:rgba(0,0,0,0.75);padding:1px 4px;border-radius:3px;pointer-events:none;white-space:nowrap;border:1px solid rgba('+((col>>16)&255)+','+((col>>8)&255)+','+(col&255)+',0.4)';
lDiv.textContent=pool[0];
var lbl=new CSS2DObject(lDiv);
lbl.position.set(0,0.5,0);
dot.add(lbl);
hFlows.push({dot:dot,from:new THREE.Vector3(fp.x,fp.y+0.5,fp.z),to:new THREE.Vector3(tp.x,tp.y+0.5,tp.z),mid:new THREE.Vector3((fp.x+tp.x)/2,Math.max(fp.y,tp.y)+2.5,(fp.z+tp.z)/2),pool:pool,lbl:lDiv,speed:0.08+Math.random()*0.04,phase:Math.random()*Math.PI*2,mi:0});
}
addHFlow('WEVIA Master','Arena',0x06b6d4);
addHFlow('WEVIA Master','Dynamic Resolver',0x06b6d4);
addHFlow('WEVIA Master','Director',0x8b5cf6);
addHFlow('WEVIA Master','Master Router',0x8b5cf6);
addHFlow('WEVIA Master','AutoFix',0x8b5cf6);
addHFlow('WEVIA Master','Fiability',0x8b5cf6);
addHFlow('WEVIA Master','Blade Bridge',0x8b5cf6);
addHFlow('WEVIA Master','DeerFlow',0x8b5cf6);
addHFlow('WEVIA Master','Ethica Chatbot',0x8b5cf6);
addHFlow('WEVIA Master','Sovereign Claude',0x06b6d4);
addHFlow('WEVIA Master','Chatbot',0x06b6d4);
addHFlow('WEVIA Master','Blade',0x8b5cf6);
addHFlow('Director','DevOps',0xf59e0b);
addHFlow('Director','Security',0xf59e0b);
addHFlow('Director','NonReg',0xf59e0b);
addHFlow('Director','L99 Pilot',0xf59e0b);
addHFlow('Director','Ethica',0xf59e0b);
addHFlow('Director','Scraper',0xf59e0b);
addHFlow('Master Router','Ollama',0xef4444);
addHFlow('Master Router','Groq',0xef4444);
addHFlow('Master Router','Cerebras',0xef4444);
addHFlow('Master Router','Trinity Large',0xef4444);
addHFlow('Master Router','MiniMax M27',0xef4444);
window._hFlows=hFlows;
msgs['WEVIA Master→CEO']=['vision 2026','revenue','strategy','decision'];
msgs['WEVIA Master→CTO']=['archi souveraine','stack','0 dette tech','optimize'];
msgs['Arena→Groq']=['llama-3.3','<200ms','stream','FREE'];
msgs['Arena→Cerebras']=['Qwen-235B','wafer-scale','FREE','benchmark'];
msgs['Arena→Ollama']=['local model','sovereign','embed','inference'];
msgs['CEO→CMO']=['141K+ HCPs','LinkedIn','B2B','outreach'];
msgs['CTO→DevOps']=['CI/CD','docker','deploy','git push'];
msgs['Security→CrowdSec']=['IDS/IPS','0 ban','feed sync','bouncer'];
msgs['NonReg→L99 Pilot']=['153/153','Sigma 6','quality gate','DPMO 0'];
addHFlow('WEVIA Master','CEO',0x06b6d4);
addHFlow('WEVIA Master','CTO',0x06b6d4);
addHFlow('Arena','Groq',0xf59e0b);
addHFlow('Arena','Cerebras',0xf59e0b);
addHFlow('Arena','Ollama',0xf59e0b);
addHFlow('CEO','CMO',0x06b6d4);
addHFlow('CTO','DevOps',0x8b5cf6);
addHFlow('Security','CrowdSec',0xef4444);
addHFlow('NonReg','L99 Pilot',0xf59e0b);
console.log('HierFlows:'+hFlows.length);
},3500);
// KPI panels moved to fixed HTML overlay
// AGENTS — ALL CSS2D CARDS
var _agentPositions={};window._ap=_agentPositions;
A.forEach(function(a,i){
const t=T[a.t];
const ta=A.filter(function(x){return x.t===a.t});
const ti=ta.indexOf(a);const cnt=ta.length;
const pw=[20,38,48,60,16];
// WAVE 163: circular layout around plateau center
// Tier 0-4 circle radii and special case for master (single center)
// WAVE 170: Fibonacci sunflower spiral — perfect disc distribution
let x,z;
if(cnt===1){
x=0;z=0;
} else {
const R=(pw[a.t]/2)*0.92;
let angle, tableR;
if(cnt>=15){
// WAVE 201: Two concentric rings for overcrowded tiers (T1/T2)
// inner ring at 50% radius, outer at 90%, staggered by half-angle
const half=Math.ceil(cnt/2);
const isOuter=ti>=half;
const localI=isOuter?(ti-half):ti;
const localCnt=isOuter?(cnt-half):half;
angle=(localI/localCnt)*Math.PI*2 - Math.PI/2;
if(isOuter) angle+=Math.PI/localCnt; // stagger offset
tableR=isOuter?R*0.92:R*0.48;
} else {
// Single circle for sparse tiers (T0, T3)
angle=(ti/cnt)*Math.PI*2 - Math.PI/2;
tableR=R*0.72;
}
x=tableR*Math.cos(angle);
z=tableR*Math.sin(angle)*0.65;
}
const url=_pk[a.n]||(a.r?'https://robohash.org/'+encodeURIComponent(a.n)+'?set=set1&size=200x200':'https://api.dicebear.com/9.x/adventurer/svg?seed='+encodeURIComponent(a.n));
const card=document.createElement('div');
card.className='ag-card'+(a.m?' master':'');card.dataset.agent=a.n;card.dataset.tier=a.t;
card.innerHTML=(a.m?'<div class="crown">👑</div>':'')+
'<div class="bubble" data-a="'+a.n+'"></div>'+
((function(n){var r=(window.WevalAvatar&&WevalAvatar.isReady&&WevalAvatar.isReady())?WevalAvatar.get(n):{persona:'human',emoji:'👤'};return '<span class="p-av" data-agent="'+n+'" data-persona="'+(r.persona||'human')+'" title="'+n+'">'+(r.emoji||'👤')+'</span>';})(a.n))+
'<div class="name">'+a.n+'</div>';
card.onclick=function(){
document.getElementById('mImg').src=url;
document.getElementById('mN').textContent=a.n;document.getElementById('mN').style.color=t.h;
document.getElementById('mT').textContent=t.n+' · '+(a.r?'Robot':'Humain');
document.getElementById('mD').textContent=a.d;
document.getElementById('mL').href=a.p;
document.getElementById('mbg').classList.add('show');
};
const obj=new CSS2DObject(card);
// WAVE 144 — Master sits on own tier 4 (no podium, centered on the tier)
// WAVE 166: hardcoded y per tier (T.y was unreliable)
const tierY=[22,16,10,4,28];
obj.userData={agentName:a.n};obj.position.set(x,tierY[a.t]+0.3,z);_agentPositions[a.n]={x:x,y:tierY[a.t]+0.3,z:z};
scene.add(obj);
});
// KPIs
// KPIs rendered as 3D screens
// RISKS
// Risks now shown in agent bubbles
// BUBBLES
// SMART STATUS BUBBLES — active agents say what they do, offline explain why
var AG_STATUS={
'WEVIA Master':{s:'active',msgs:['Orchestration 24/7','Dispatch 14 providers','Consensus vote...','Rotation cl\u00e9s API','Cycle #4217 OK']},
'Director':{s:'active',msgs:['Observe\u2192Plan\u2192Act','39 obs / 0 issues','Scan 4 serveurs...','Rapport Telegram','Auto-cycle */15']},
'Arena':{s:'active',msgs:['394 options live','12 providers cascade','24 creative intents','Command Center OK','9 couches IA']},
'Creative':{s:'active',msgs:['24 intents actifs','Brainstorm mode','SWOT analyse','Red team scan','Innovation sprint']},
'Autonomous':{s:'active',msgs:['92 routes ActionEngine','220+ keywords bridge','Exec reel 100%','Git push dual','Backup GOLD auto']},
'DeepSeekWeb':{s:'active',msgs:['UNLIMITED gratuit','Think+Search dual','Instant mode','Web search live','0 cout']},
'Together':{s:'active',msgs:['Llama-3.3-70B','FREE tier','Cascade fallback','Fast inference','0 cout']},
'Cohere':{s:'active',msgs:['Command-R+','FREE trial','RAG optimized','Multilingual','Cascade #8']},
'Nvidia':{s:'active',msgs:['NIM API','Llama-3.3-70B','Enterprise grade','Low latency','Cascade #9']},
'Qwen':{s:'active',msgs:['Alibaba Cloud','Qwen-Plus model','DeerFlow backend','Multilingual','Cascade #10']},
'ZhiPu':{s:'active',msgs:['GLM-4-Flash','Chinese AI','Fast response','FREE tier','Cascade #11']},
'Growth':{s:'active',msgs:['Pipeline 4 stages','CRM Twenty wire','Plausible analytics','SEO scan auto','Dark Scout active']},
'DarkScout':{s:'active',msgs:['Scan concurrents','Veille marche','Alertes auto','3 sources','Rapport hebdo']},
'SEO':{s:'active',msgs:['Audit technique','Keywords track','Backlinks scan','Core Web Vitals','Score 92/100']},
'Fiability':{s:'active',msgs:['24 URLs: 100%','SSL: 30j restants','Score: 100%','Scan subs OK','Latence moy: 340ms']},
'AutoFix':{s:'active',msgs:['Docker heal OK','17/17 containers UP','Auto-compose check','Health check pass\u00e9','Restart: 0/24h']},
'Consensus':{s:'active',msgs:['Vote 3 providers','Score 9.8/10','Quorum atteint','Fallback pr\u00eat','Response valid\u00e9e']},
'Master Router':{s:'active',msgs:['46 routes actives','14 providers OK','Failover: ready','Round-robin ON','<100ms latence']},
'Dispatcher':{s:'active',msgs:['Route engine actif','Priority queue OK','Load balance even','Fallback chain: 3','Health: all green']},
'MiroFish':{s:'active',msgs:['WePredict :5001 UP','Auto-fix active','Self-heal OK','Vue frontend live','FR translation OK']},
'DeerFlow':{s:'active',msgs:['Research active','12 sources wired','RAG 4414 vectors','LangGraph ready','Deep search OK']},
'Blade':{s:'idle',msgs:['\u23f3 Desktop standby','Prochaine: demande user','Razer: 34 capabilities','Selenium: pr\u00eat','Activation: on-demand']},
'Ollama':{s:'warn',msgs:['\u26a0 4/10 mod\u00e8les charg\u00e9s','qwen3:8b actif','6 unloaded (RAM)','CPU mode (0% GPU)','Prochain reload: 6h']},
'Groq':{s:'active',msgs:['Llama-3.3 <200ms','API quota: 85%','Stream actif','Batch ready','Throughput OK']},
'Cerebras':{s:'active',msgs:['Qwen-3 235B ready','<500ms inference','Wafer-scale ON','Batch queue: 3','Throughput max']},
'SambaNova':{s:'active',msgs:['Meta-Llama 3.3','<800ms inference','API active','Fallback: Groq','Batch ready']},
'Security':{s:'active',msgs:['0 CVE critical','CrowdSec: 0 ban','SSL: 30j valid','Nuclei: weekly','Firewall: 847 rules']},
'DevOps':{s:'active',msgs:['CI/CD pipeline OK','4 serveurs OK','Git push dual OK','Disk: 84%','Backup auto OK']},
'Ethica':{s:'active',msgs:['141K+ HCP index\u00e9s','DabaDoc MA scrape','Consent: 15K opt-in','Pipeline B2B actif','Enrichissement TN']},
'Monitor':{s:'active',msgs:['24 URLs: 99.97%','Latence moy: 340ms','0 alertes actives','Dashboard live','Uptime 24/7']},
'NonReg':{s:'warn',msgs:['\u26a0 153/153 PASS','2 skip (WebGL)','Playwright Chrome','Video: 96 rec','Prochain run: 2h']},
'WEVCODE':{s:'active',msgs:['Mode Opus actif','4 modes dispo','Syntax: 0 error','Skills: 1935 .md','Completion live']},
'L99 Pilot':{s:'active',msgs:['98.7% quality','Lean 6\u03c3 gate OK','ToC: 0 bottleneck','153/153 tests','Visual check OK']},
'Scraper':{s:'active',msgs:['DabaDoc: 50/min','Proxy rotate OK','Queue: 12 pending','TN enrichment...','DZ email fetch']},
'ArchScan':{s:'active',msgs:['52 noeuds OK','38 edges mapp\u00e9s','Topology fresh','SOA aligned','BPMN: 6 detected']},
'CrowdSec':{s:'active',msgs:['IDS/IPS actif','Ban: 0/24h','Community feed OK','Bouncer nginx','Rules: 142']},
'Fail2Ban':{s:'active',msgs:['SSH protect actif','Jails: 3 active','Ban: 0 current','Log scan: 5min','Config hardened']},
'Registry':{s:'active',msgs:['626 pages track\u00e9es','13 domaines','API scan OK','0 pages missing','Sync Paperclip OK']},
'Paperclip':{s:'active',msgs:['669 agents fleet','150 LIVE now','Skills: 1935','+3 agents/sem','22 departments']},
'Sentinel':{s:'active',msgs:['S95 relay actif','Port 5890 OK','SSH key-only','Exec API ready','Vault check OK']},
'Docker':{s:'active',msgs:['17/17 UP','RAM: 2.8GB/16GB','Restart: 0/24h','Volumes: 32GB free','Network bridge OK']},
'PMTA':{s:'active',msgs:['4 ECS actifs','IDs 186-189 OK','Inbox: 97%','Queue: 0 pending','rDNS valid\u00e9']},
'CEO':{s:'active',msgs:['Vision 2026','Revenue target','Client Ethica','Expansion MA/DZ/TN']},
'CTO':{s:'active',msgs:['4 serveurs OK','Archi souveraine','0 dette tech','Stack optimale']},
'CFO':{s:'active',msgs:['0\u20ac AI cost','Stripe LIVE','ROI infini','Budget cloud OK']},
'CMO':{s:'active',msgs:['141K+ HCPs','Ethica pipeline','B2B outreach','LinkedIn 469']},
'CISO':{s:'active',msgs:['0 CVE critical','847 rules FW','CrowdSec ON','Nuclei weekly']},
'UX Lead':{s:'active',msgs:['premium.css','Responsive OK','Dark/Light','11 pages']},
'Wiki':{s:'active',msgs:['203 fichiers','Auto-doc','Search code','14 articles']},
'Register':{s:'active',msgs:['API auth OK','PHP session','Login flow','Rate limit']},
'Telegram':{s:'active',msgs:['Daily brief 7h','4 machines','Alerts live','Chat 7605775']},
'Stripe':{s:'active',msgs:['SK+PK LIVE','Webhook OK','Test charge','Billing ready']},
'L99 Pilot':{s:'active',msgs:['1495 checks','17 layers','4 machines','31 agents']},
'ClawCode':{s:'active',msgs:['78 skills','19 agents OhMyCC','Port 3900','Sovereign']},
'Analyst':{s:'active',msgs:['SWOT ready','B2B analysis','Market scan','Concurrence']},
'Architect':{s:'active',msgs:['Cloud archi','Microservices','Terraform','Blueprints']},
'Verifier':{s:'active',msgs:['ISO 27001','RGPD check','PCI-DSS','Access ctrl']},
'GitMaster':{s:'active',msgs:['50 repos','Tag v3.3','Merge flow','Release OK']},
'DocSpec':{s:'active',msgs:['Templates OK','API docs','README gen','Guide user']},
'Scientist':{s:'active',msgs:['182 models','Groq vs Cerebras','Latency bench','Accuracy OK']},
'LeadForge':{s:'active',msgs:['Lead gen B2B','Score leads','Enrich data','Export CSV']},
'EthicaScraper':{s:'active',msgs:['DabaDoc MA','DabaDoc TN','DabaDoc DZ','50/min']},
'TaskMgr':{s:'active',msgs:['Kanban board','12 tasks','3 deadlines','Priority sort']},
'WEDROID':{s:'active',msgs:['Chain exec S95','Auto-fix DB','API repair','Deploy v5']},
'Watchdog':{s:'active',msgs:['24 Docker OK','Disk 83%','Nginx alive','Ollama check']},
'Guardian':{s:'active',msgs:['chattr +i 19','MD5 verified','SSH locked','847 rules']},
'SC-Orch':{s:'active',msgs:['Chain agents','Parallel exec','Gate merge','Pipeline OK']},
'SC-Research':{s:'active',msgs:['12 sources','Synthesis OK','Facts check','Report gen']},
'Academy':{s:'active',msgs:['Qdrant embed','4414 skills','Auto-learn','Index OK']},
'Contract':{s:'active',msgs:['Template gen','PDF export','Legal OK','Pricing done']},
'Blueprint':{s:'active',msgs:['Scaffold OK','API gen','DB schema','Test gen']},
'Debugger':{s:'active',msgs:['Fix API 500','Memory check','nginx conf','SQL safe']},
'Simplifier':{s:'active',msgs:['Refactor 2K','Dead code rm','-40% lines','Merge dupes']}
};
function rotB(){
document.querySelectorAll('.bubble').forEach(function(b){
var n=b.dataset.a;var st=AG_STATUS[n];
if(!st)return;
var msg=st.msgs[Math.floor(Math.random()*st.msgs.length)];
b.textContent=msg;
b.className='bubble '+st.s; if(st.s==='active'){b.style.display='none';return;}
setTimeout(function(){b.classList.remove('show')},4000);
});
}
setTimeout(function(){rotB();setInterval(rotB,2500)},3000);
// ACTIVITY DOTS
(function(){function u(){fetch('/api/agent-status.php').then(function(r){return r.json()}).then(function(d){if(!d||!d.active)return;document.querySelectorAll('.ag-card').forEach(function(c){var n=c.querySelector('.name').textContent;var old=c.querySelector('.dot');if(old)old.remove();if(d.active[n]){var dot=document.createElement('div');dot.className='dot';c.appendChild(dot)}})}).catch(function(){})}u();setInterval(u,5000)})();
// === CONNECTION LINES: WEVIA Master to key agents ===
(function(){
var masterPos=null;var agentObjs=[];
scene.traverse(function(o){
if(o.isCSS2DObject&&o.element&&o.element.classList.contains('ag-card')){
var nm=o.element.querySelector('.name');
if(nm){
var n=nm.textContent;
if(n==='WEVIA Master')masterPos=o.position.clone();
if(['Director','Master Router','Consensus','DeerFlow','Blade','AutoFix','CEO','CTO','CFO','CMO','CISO','L99 Pilot','ClawCode','Analyst','Architect','Verifier'].indexOf(n)!==-1)agentObjs.push({n:n,p:o.position.clone()});
}
}
});
if(false && masterPos){ // WAVE 193: connectors removed
var flows={'Director':'39 obs/cycle','Master Router':'46 routes','Consensus':'Vote 3-way','DeerFlow':'12 sources','Blade':'Desktop sync','AutoFix':'Docker heal','CEO':'Strategic decisions','CTO':'Tech architecture','CFO':'Budget 0EUR','CMO':'HCP outreach','CISO':'Security scan','L99 Pilot':'1495 checks','ClawCode':'78 skills','Analyst':'SWOT + B2B','Architect':'Blueprints','Verifier':'ISO/RGPD'};
agentObjs.forEach(function(ag){
var pts=[];var steps=20;
for(var i=0;i<=steps;i++){
var t=i/steps;
var x=masterPos.x*(1-t)+ag.p.x*t;
var y=masterPos.y*(1-t)+ag.p.y*t+Math.sin(t*Math.PI)*2;
var z=masterPos.z*(1-t)+ag.p.z*t;
pts.push(new THREE.Vector3(x,y,z));
}
var geom=new THREE.BufferGeometry().setFromPoints(pts);
var mat=new THREE.LineBasicMaterial({color:0xffd700,transparent:true,opacity:0.45});
scene.add(new THREE.Line(geom,mat));
/* WAVE 192: flow labels removed for clean UX */
});
}
})();
// === BOTTOM-UP REPORTING LINES (execution -> master) ===
(function(){
var masterPos=null;var reporters=[];
var upFlows={'NonReg':'153/153 PASS','Docker':'17/17 UP','L99 Pilot':'1495 checks','PMTA':'Inbox 97%','Sentinel':'S95 relay OK','Paperclip':'669 fleet','Monitor':'24 URLs 100%','Ethica':'141K+ HCPs'};
scene.traverse(function(o){
if(o.isCSS2DObject&&o.element&&o.element.classList.contains('ag-card')){
var nm=o.element.querySelector('.name');
if(nm){
var n=nm.textContent;
if(n==='WEVIA Master')masterPos=o.position.clone();
if(upFlows[n])reporters.push({n:n,p:o.position.clone()});
}
}
});
if(false && masterPos){ // WAVE 193: connectors removed
reporters.forEach(function(ag){
var pts=[];var steps=15;
for(var i=0;i<=steps;i++){
var t=i/steps;
var x=ag.p.x*(1-t)+masterPos.x*t;
var y=ag.p.y*(1-t)+masterPos.y*t+Math.sin(t*Math.PI)*1.5;
var z=ag.p.z*(1-t)+masterPos.z*t;
pts.push(new THREE.Vector3(x,y,z));
}
var geom=new THREE.BufferGeometry().setFromPoints(pts);
var mat=new THREE.LineBasicMaterial({color:0x4ade80,transparent:true,opacity:0.3});
scene.add(new THREE.Line(geom,mat));
/* WAVE 172: upFlows removed */
/* removed *//* removed */;
});
}
})();
// === LIVE KPI REFRESH 30s ===
(function(){
function rKPI(){
fetch('/api/nonreg-api.php?cat=all').then(function(r){return r.json()}).then(function(d){
if(!d||!d.summary)return;
document.querySelectorAll('div').forEach(function(el){
if(el.textContent.match(/^NR \d+\/\d+$/)){
el.textContent='NR '+d.summary.pass+'/'+d.summary.total;
}
});
}).catch(function(){});
}
setTimeout(rKPI,10000);setInterval(rKPI,10000);
})();
// decorations removed for clean render
// ═══ WAVE 194: Animated decision flows Master ↔ Agents ═══
var flowDots=[];window._flowDots=flowDots;
var flowInfos={
'Director':'Orchestration','Master Router':'Routing 46',
'Consensus':'Vote 3-way','DeerFlow':'12 sources',
'CEO':'Vision 2026','CTO':'Architecture','CFO':'Budget 0EUR',
'L99 Pilot':'1495 checks','ClawCode':'78 skills',
'Analyst':'SWOT+B2B','AutoFix':'Docker heal',
'NonReg':'153/153','Ethica':'141K+ HCP','Security':'Scan CVE'
};
(function initFlows(){
setTimeout(function(){
var master=null;var targets=[];
document.querySelectorAll('.ag-card').forEach(function(card){
var nm=card.dataset.agent;
if(nm==='WEVIA Master'){
var r=card.getBoundingClientRect();
// Get 3D position from CSS2DObject
var s=card.parentElement?card.parentElement.style.transform:'';
}
});
// Use Three.js objects directly — find masterPos from scene
if(_agentPositions['WEVIA Master']){
var mp=_agentPositions['WEVIA Master'];
master=new THREE.Vector3(mp.x,mp.y,mp.z);
}
Object.keys(flowInfos).forEach(function(name){
if(_agentPositions[name]){
var ap=_agentPositions[name];
targets.push({name:name,pos:new THREE.Vector3(ap.x,ap.y,ap.z),info:flowInfos[name]});
}
});
if(!master || targets.length===0) return;
// Create flow dots for each target
targets.forEach(function(tgt,idx){
var dotGeo=new SphereGeometry(0.25,8,8);
var dotMat=new MeshBasicMaterial({color:0xffd700,transparent:true,opacity:0.9});
var dot=new Mesh(dotGeo,dotMat);
dot.position.copy(master);
scene.add(dot);
// Label
var lbl=document.createElement('div');
lbl.style.cssText='font:600 5px Nunito;color:rgba(255,215,0,0.8);pointer-events:none;white-space:nowrap;background:rgba(0,0,0,0.5);padding:1px 3px;border-radius:3px';
lbl.textContent=tgt.info;
var lblObj=new CSS2DObject(lbl);
lblObj.position.set(0,0.5,0);
dot.add(lblObj);
// Create visible curved path line
var pathPts=[];
var from=idx%2===0?master:tgt.pos;
var to=idx%2===0?tgt.pos:master;
var midY=(from.y+to.y)/2+3;
for(var s=0;s<=20;s++){
var tt=s/20;var mt=1-tt;
pathPts.push(new THREE.Vector3(
mt*mt*from.x+2*mt*tt*((from.x+to.x)/2)+tt*tt*to.x,
mt*mt*from.y+2*mt*tt*midY+tt*tt*to.y,
mt*mt*from.z+2*mt*tt*((from.z+to.z)/2)+tt*tt*to.z
));
}
var pathGeo=new THREE.BufferGeometry().setFromPoints(pathPts);
var pathLine=new THREE.Line(pathGeo,new THREE.LineBasicMaterial({color:0xffd700,transparent:true,opacity:0.15}));
scene.add(pathLine);
flowDots.push({
dot:dot, master:master.clone(), target:tgt.pos.clone(),
info:tgt.info, speed:0.8+Math.random()*0.6,
phase:Math.random()*Math.PI*2,
direction:idx%2===0?1:-1,
lbl:lbl, path:pathLine
});
});
},3000); // wait for scene to be ready
})();
// Flow animation update (called from animate)
function updateFlows(time){
flowDots.forEach(function(f){
var t=(Math.sin(time*f.speed+f.phase)+1)/2; // 0→1→0 oscillation
if(f.direction<0) t=1-t;
var from=f.direction>0?f.master:f.target;
var to=f.direction>0?f.target:f.master;
// Bezier curve with arc
var mid_y=(from.y+to.y)/2+3; // arc height
var t2=t;
var mt=1-t2;
f.dot.position.x=mt*mt*from.x+2*mt*t2*((from.x+to.x)/2)+t2*t2*to.x;
f.dot.position.y=mt*mt*from.y+2*mt*t2*mid_y+t2*t2*to.y;
f.dot.position.z=mt*mt*from.z+2*mt*t2*((from.z+to.z)/2)+t2*t2*to.z;
// Pulse opacity
f.dot.material.opacity=0.4+Math.sin(time*3+f.phase)*0.4;
// Direction label
var arrow=f.direction>0?'\u2193 ':'\u2191 ';
f.lbl.textContent=arrow+f.info;
});
}
function animate(){requestAnimationFrame(animate);ctrl.update();var t=performance.now()/1000;updateFlows(t);if(pts&&pts.rotation)pts.rotation.y+=0.003;if(window._hFlows){var _t=performance.now()/1000;window._hFlows.forEach(function(f){var t=(((_t*f.speed+f.phase)%6.28318)/6.28318);var mt=1-t;f.dot.position.x=mt*mt*f.from.x+2*mt*t*f.mid.x+t*t*f.to.x;f.dot.position.y=mt*mt*f.from.y+2*mt*t*f.mid.y+t*t*f.to.y;f.dot.position.z=mt*mt*f.from.z+2*mt*t*f.mid.z+t*t*f.to.z;f.dot.material.opacity=0.5+Math.sin(_t*2+f.phase)*0.3;if(t<0.02){f.mi=(f.mi+1)%f.pool.length;f.lbl.textContent=f.pool[f.mi]}})}composer.render();css2.render(scene,cam)}
animate();
window.addEventListener('resize',function(){cam.aspect=innerWidth/innerHeight;cam.updateProjectionMatrix();ren.setSize(innerWidth,innerHeight);css2.setSize(innerWidth,innerHeight);if(typeof composer!=='undefined')composer.setSize(innerWidth,innerHeight)});
// ═══ WAVE 118 — Live cockpit auto-refresh ═══
(function(){
var REFRESH_MS=30000;
var countdown=REFRESH_MS/1000;
function setPill(id,val,cls){var el=document.getElementById(id);if(!el)return;var v=el.querySelector('.val');if(v)v.textContent=val;if(cls){el.classList.remove('green','yellow','red');el.classList.add(cls);var d=el.querySelector('.cockpit-dot');if(d){d.classList.remove('yellow','red');if(cls!=='green')d.classList.add(cls)}}}
function fetchLive(){
fetch('/api/wevia-master-api.php',{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({message:'auto diagnose',session:'archi-live-'+Date.now()})
}).then(function(r){return r.json()}).then(function(d){
var resp=d.response||d.content||'';
if(resp.indexOf('AUTODIAG_JSON:')!==0)return;
var j=JSON.parse(resp.substring(14));
var h=(j.health||'GREEN').toLowerCase();
setPill('cp-health',j.health||'?',h);
if(j.l99)setPill('cp-l99',(j.l99.pass||0)+'/'+(j.l99.total||0),(j.l99.fail||0)===0?'green':((j.l99.fail||0)<=3?'yellow':'red'));
if(j.docker)setPill('cp-docker',(j.docker.count||0),(j.docker.count||0)>=15?'green':'red');
if(j.disk)setPill('cp-disk',(j.disk.pct||'?'),(parseInt(j.disk.pct)||0)<85?'green':((parseInt(j.disk.pct)||0)<95?'yellow':'red'));
if(j.providers)setPill('cp-providers',(j.providers.tier1||0)+'+'+(j.providers.tier2||0),(j.providers.ollama_up==='UP')?'green':'red');
if(j.qdrant)setPill('cp-qdrant',(j.qdrant.count||0),(j.qdrant.count||0)>0?'green':'red');
if(j.git)setPill('cp-git',j.git.substring(0,8),'green');
countdown=REFRESH_MS/1000;
}).catch(function(e){setPill('cp-health','ERR','red')});
}
setInterval(function(){
countdown--;
var el=document.getElementById('cp-refresh');
if(el){var v=el.querySelector('.val');if(v)v.textContent=countdown+'s'}
if(countdown<=0)fetchLive();
},1000);
fetchLive();
})();
// ═══ WAVE 116 — PILOTAGE ═══
(function(){
var modal=document.createElement('div');
modal.id='w116-modal';
modal.style.cssText='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(6,12,22,.97);border:2px solid #06b6d4;border-radius:14px;padding:26px;max-width:820px;min-width:500px;max-height:78vh;overflow:auto;z-index:9999;display:none;backdrop-filter:blur(14px);box-shadow:0 0 60px rgba(6,182,212,.4),0 0 120px rgba(6,182,212,.15);color:#e2e8f0;font:500 13px Nunito';
modal.innerHTML='<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px"><div id="w116-title" style="font:900 18px Orbitron;color:#06b6d4;text-shadow:0 0 10px rgba(6,182,212,.5)">AGENT</div><button id="w116-close" style="background:none;border:1px solid #475569;color:#94a3b8;cursor:pointer;padding:2px 8px;border-radius:4px">X</button></div><div id="w116-body" style="white-space:pre-wrap;font:500 13px "SF Mono",Consolas,monospace;color:#e2e8f0;line-height:1.6">Loading...</div>';
document.body.appendChild(modal);
document.getElementById('w116-close').addEventListener('click',function(){modal.style.display='none'});
document.addEventListener('keydown',function(e){if(e.key==='Escape')modal.style.display='none'});
// Intent mapping: agent name -> Master intent
var INTENT_MAP={
'Master':'audit complet','WEVIA':'audit complet','WEVIA Master':'audit complet',
'NonReg':'nonreg run','L99':'nonreg run','Quality':'nonreg run',
'Docker':'docker ps','DevOps':'docker ps',
'Git':'git log','GitOps':'git push','Gitea':'gitea status','GitHub':'gitea status',
'Disk':'disk clean','Storage':'disk clean',
'Cron':'crons list','Scheduler':'crons list',
'Ports':'port scan','Network':'port scan',
'RAG':'rag status','Qdrant':'rag status','Memory':'rag status',
'Vault':'vault list','Backup':'vault list','GOLD':'vault list'
};
document.addEventListener('click',function(ev){
var card=ev.target.closest('.ag-card');
if(!card||!card.dataset.agent)return;
var agent=card.dataset.agent;
var intent=INTENT_MAP[agent]||('status '+agent);
document.getElementById('w116-title').textContent=agent.toUpperCase()+' -> '+intent;
document.getElementById('w116-body').textContent='Chargement via WEVIA Master...';
modal.style.display='block';
fetch('/api/wevia-master-api.php',{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({message:intent,session:'archi-pilot-'+agent})
}).then(function(r){return r.json()}).then(function(d){
var prov=d.provider||'?';
var sc=(d.routing&&d.routing.short_circuit)?'[SC]':'[LLM]';
var resp=d.response||d.content||'(empty)';
document.getElementById('w116-body').textContent=prov+' '+sc+'\n\n'+resp;
}).catch(function(e){
document.getElementById('w116-body').textContent='ERREUR: '+e.message;
});
});
})();
// ═══ WAVE 119.1 — LIVE COCKPIT POLLING + KEYBOARD ═══
(function(){
// Top live bar
var bar=document.createElement('div');
bar.id='w119-livebar';
bar.style.cssText='position:fixed;top:0;left:0;right:0;background:linear-gradient(90deg,rgba(6,12,22,.95),rgba(15,23,42,.95));border-bottom:1px solid rgba(6,182,212,.3);padding:4px 10px;font:700 9px Nunito;color:#cbd5e1;z-index:50;display:flex;gap:24px;align-items:center;backdrop-filter:blur(10px);pointer-events:none';
bar.innerHTML='<span style="color:#06b6d4;font-weight:900;letter-spacing:2px;font-family:Orbitron">WEVIA COCKPIT</span><span id="w119-l99">L99: --</span><span id="w119-dock">Docker: --</span><span id="w119-ports">Ports: --</span><span id="w119-disk">Disk: --</span><span id="w119-crons">Crons: --</span><span id="w119-git" style="color:#06b6d4">HEAD: --</span><span id="w119-upd" style="color:#64748b;font-size:10px;margin-left:auto">...</span><span style="color:#94a3b8;font-size:10px">[A]udit [N]onreg [G]it [H]eal [D]iag [V]ault</span>';
document.body.appendChild(bar);
function updateLive(){
fetch('/api/wevia-master-api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:'cockpit data',session:'w119-poll'})})
.then(function(r){return r.json()})
.then(function(d){
var raw=d.response||d.content||'';
var idx=raw.indexOf('{');
if(idx<0)return;
try{
var data=JSON.parse(raw.substring(idx));
document.getElementById('w119-l99').innerHTML='L99: <b style="color:#4ade80">'+(data.l99?data.l99.pass+'/'+data.l99.total:'?')+'</b>';
document.getElementById('w119-dock').innerHTML='Docker: <b style="color:#4ade80">'+(data.docker&&data.docker.count||'?')+'</b>';
document.getElementById('w119-ports').innerHTML='Ports: <b>'+(data.ports||'?')+'</b>';
var dp=data.disk&&data.disk.pct||'?';
document.getElementById('w119-disk').innerHTML='Disk: <b style="color:'+(parseInt(dp)>85?'#f59e0b':'#4ade80')+'">'+dp+'</b>';
document.getElementById('w119-crons').innerHTML='Crons: <b>'+(data.crons||'?')+'</b>';
document.getElementById('w119-git').innerHTML='HEAD: <b style="color:#06b6d4">'+(data.git||'?').substring(0,8)+'</b>';
document.getElementById('w119-upd').textContent='updated '+new Date().toLocaleTimeString();
}catch(e){document.getElementById('w119-upd').textContent='parse err';}
})
.catch(function(e){document.getElementById('w119-upd').textContent='';});
}
updateLive();
setInterval(updateLive,10000);
// Keyboard shortcuts trigger Master intents via the w116 modal flow
var SHORTCUT_MAP={a:'audit complet',n:'nonreg run',g:'git push',h:'auto-heal',d:'self-diagnostic',v:'vault list'};
document.addEventListener('keydown',function(e){
if(e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA')return;
var k=e.key.toLowerCase();
if(!SHORTCUT_MAP[k])return;
e.preventDefault();
var intent=SHORTCUT_MAP[k];
var modal=document.getElementById('w116-modal');
if(!modal)return;
document.getElementById('w116-title').textContent='[KEY '+k.toUpperCase()+'] -> '+intent;
document.getElementById('w116-body').textContent='Chargement via WEVIA Master...';
modal.style.display='block';
fetch('/api/wevia-master-api.php',{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({message:intent,session:'archi-key-'+k})
}).then(function(r){return r.json()}).then(function(d){
var prov=d.provider||'?';
var sc=(d.routing&&d.routing.short_circuit)?'[SC]':'[LLM]';
var resp=d.response||d.content||'(empty)';
document.getElementById('w116-body').textContent=prov+' '+sc+'\n\n'+resp;
}).catch(function(e){
document.getElementById('w116-body').textContent='ERREUR: '+e.message;
});
});
})();
// WAVE 152 — Adaptive agent + KPI scale based on camera distance
(function(){
const baseDist = cam.position.length();
function updateScale(){
const d = cam.position.length();
const factor = Math.max(0.5, Math.min(2.0, baseDist / d));
// Scale .ag-card cards
document.querySelectorAll('.ag-card').forEach(c => {
c.style.transform = 'scale(' + factor.toFixed(3) + ')';
c.style.transformOrigin = 'center center';
});
}
ctrl.addEventListener('change', updateScale);
setTimeout(updateScale, 500);
})();
// WAVE 153 — Agent card DRAG & DROP via mouse
(function(){
let dragging = null, dragOffset = {x:0, y:0}, originalCSS = null;
document.addEventListener('mousedown', function(e){
const card = e.target.closest('.ag-card');
if(!card) return;
if(e.button !== 0) return; // left click only
if(e.ctrlKey || e.metaKey){
// Ctrl+click = drag mode
e.preventDefault(); e.stopPropagation();
dragging = card;
const rect = card.getBoundingClientRect();
dragOffset.x = e.clientX - rect.left;
dragOffset.y = e.clientY - rect.top;
originalCSS = {
position: card.style.position,
zIndex: card.style.zIndex,
pointerEvents: card.style.pointerEvents,
left: card.style.left,
top: card.style.top
};
card.style.position = 'fixed';
card.style.zIndex = '9999';
card.style.pointerEvents = 'auto';
card.style.cursor = 'grabbing';
card.style.left = (e.clientX - dragOffset.x) + 'px';
card.style.top = (e.clientY - dragOffset.y) + 'px';
card.style.transform = 'scale(1.15)';
card.style.filter = 'drop-shadow(0 0 20px rgba(6,182,212,0.8))';
}
}, true);
document.addEventListener('mousemove', function(e){
if(!dragging) return;
dragging.style.left = (e.clientX - dragOffset.x) + 'px';
dragging.style.top = (e.clientY - dragOffset.y) + 'px';
});
document.addEventListener('mouseup', function(e){
if(!dragging) return;
dragging.style.transform = 'scale(1)';
dragging.style.filter = '';
dragging.style.cursor = 'pointer';
// Keep the new position
dragging = null;
});
// Add visual hint on all cards
setTimeout(function(){
document.querySelectorAll('.ag-card').forEach(c => {
c.title = 'Ctrl+Clic-Drag pour deplacer';
c.style.pointerEvents = 'auto';
});
}, 1000);
})();
// WAVE 158 — LIVE DATA PIPELINE: agents-archi as real reporting center
(function(){
const PIPELINE_URL = '/api/weval-unified-pipeline.php';
let pipelineData = null;
let refreshTimer = null;
async function fetchPipeline(){
try {
const r = await fetch(PIPELINE_URL, {cache:'no-cache'});
if(!r.ok) return null;
return await r.json();
} catch(e){ console.warn('pipeline fetch fail',e); return null; }
}
function applyLiveData(d){
if(!d) return;
pipelineData = d;
// 1. Update header bar with live L99 + system
const bar = document.getElementById('liveStatusBar');
if(bar){
const h = d.l99.health || 'UNKNOWN';
const color = {GREEN:'#10b981',YELLOW:'#f59e0b',RED:'#ef4444'}[h] || '#64748b';
bar.innerHTML = `
<span style="color:${color};font-weight:900">● ${h}</span>
<span>L99 <b>${d.l99.pass}/${d.l99.total}</b></span>
<span>Docker <b>${d.system.docker_count}</b></span>
<span>Disk <b>${d.system.disk_pct}%</b></span>
<span>Crons <b>${d.system.cron_count}</b></span>
<span>Goals <b>${d.goals.length}</b></span>
<span>Projects <b>${d.projects.length}</b></span>
<span>Routines <b>${d.routines.length}</b></span>
<span>Providers <b>${d.providers.count}</b> @0€</span>
<span>Qdrant <b>${d.qdrant.collections.length}</b></span>
<span>HCPs <b>${(d.ethica.hcps_validated/1000).toFixed(0)}K</b></span>
`;
}
// 2. Decorate each agent card with LIVE routine count + status
const rpa = d.routines_per_agent || {};
document.querySelectorAll('.ag-card').forEach(card => {
const name = card.dataset.agent;
if(!name) return;
const routines = rpa[name] || 0;
// Remove old badge if present
const oldBadge = card.querySelector('.live-badge');
if(oldBadge) oldBadge.remove();
// Add routine count badge
if(false && routines > 0){ // WAVE 191: badges hidden
const badge = document.createElement('div');
badge.className = 'live-badge';
badge.style.cssText = 'position:absolute;top:-4px;right:-4px;background:linear-gradient(135deg,#10b981,#06b6d4);color:#fff;font:900 9px Orbitron;width:16px;height:16px;display:flex;align-items:center;justify-content:center;border-radius:50%;border:1px solid #0a0e1a;box-shadow:0 0 6px rgba(16,185,129,.8);pointer-events:none;z-index:10';
badge.textContent = routines;
badge.title = routines + ' routines actives';
// FIX WAVE 166: DO NOT set card.style.position='relative' — breaks CSS2DRenderer absolute positioning
card.appendChild(badge);
}
// Color border based on L99 layer status
// WEDROID -> SYSTEMD layer, Guardian -> PORTS-S204, etc
const statusMap = {
'WEVIA Master': d.l99.layers.CAPABILITIES,
'WEDROID': d.l99.layers.SYSTEMD,
'WEVCODE': d.l99.layers.NONREG,
'Guardian': d.l99.layers['PORTS-S204'],
'Consensus': d.l99.layers.SOVEREIGN,
'DeerFlow': d.l99.layers.QDRANT,
'Ethica': d.l99.layers['S95-HEALTH'],
'Paperclip': d.l99.layers.DOCKER,
};
const s = statusMap[name];
if(s){
const pct = s.pct || 0;
const glow = pct === 100 ? 'rgba(16,185,129,.6)' : (pct >= 80 ? 'rgba(245,158,11,.6)' : 'rgba(239,68,68,.6)');
const img = card.querySelector('img');
if(img) img.style.boxShadow = `0 0 10px ${glow}`;
}
});
// 3. Update tier KPI panels with live numbers
// STRATÉGIE: providers + goals
// DIRECTION: routines
// TACTIQUE: NonReg + HCPs
// EXÉCUTION: Docker + Ollama
// (the KPI panels are SVG, keeping as-is for now, badge system is enough)
console.log('[LIVE PIPELINE] Applied:', d.l99.pass + '/' + d.l99.total, d.routines.length + ' routines');
}
// Create live status bar
function ensureStatusBar(){
return; // WAVE 179: live bar removed (duplicate of cockpit)
const bar = document.createElement('div');
bar.id = 'liveStatusBar';
bar.style.cssText = 'display:none;position:fixed;top:90px;left:50%;transform:translateX(-50%);max-width:min(1200px,calc(100vw - 400px));background:linear-gradient(135deg,rgba(10,14,26,.92),rgba(30,30,60,.88));border:1px solid rgba(6,182,212,.4);border-radius:6px;padding:3px 10px;backdrop-filter:blur(12px);z-index:30;font:700 9px Nunito;color:#e2e8f0;display:flex;gap:10px;align-items:center;justify-content:center;flex-wrap:nowrap;pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis';
document.body.appendChild(bar);
}
async function refresh(){
ensureStatusBar();
const d = await fetchPipeline();
if(d) applyLiveData(d);
}
// Initial fetch + 30s refresh
setTimeout(refresh, 1500);
refreshTimer = setInterval(refresh, 30000);
// Expose globally for manual refresh
window.reloadLivePipeline = refresh;
})();
// WAVE 159 — Agents-archi as REAL reporting center: interactions
(function(){
// Keyboard shortcuts
document.addEventListener('keydown', function(e){
if(e.ctrlKey || e.metaKey || e.altKey) return;
if(e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
const k = e.key.toLowerCase();
if(k === 'r') window.reloadLivePipeline && window.reloadLivePipeline();
if(k === 'm') window.location.href = '/wevia-master.html';
if(k === 'p') window.open('https://paperclip.weval-consulting.com', '_blank');
if(k === 'e') window.location.href = '/enterprise-model.html';
if(k === 'o') window.location.href = '/wevia-meeting-rooms.html';
if(k === 'l') window.location.href = '/l99-brain.html';
if(k === '?'){
alert('SHORTCUTS:\nR = Refresh live data\nM = Master chat\nP = Paperclip\nE = Enterprise\nO = Meeting Rooms\nL = L99 Brain\n? = Help');
}
});
// Help hint at bottom-left
const hint = document.createElement('div');
hint.style.cssText = 'position:fixed;bottom:8px;left:200px;background:rgba(10,14,26,.85);color:#64748b;padding:4px 10px;border-radius:6px;font:600 9px Nunito;z-index:30;border:1px solid rgba(100,116,139,.2);pointer-events:none';
return; // WAVE 180: hint removed
setTimeout(() => document.body.appendChild(hint), 2000);
})();
</script>
<div id="kpiOverlay" style="position:fixed;right:8px;top:100px;z-index:5;display:flex;flex-direction:column;gap:3px;max-height:calc(100vh - 180px);overflow-y:auto;scrollbar-width:thin;pointer-events:auto;opacity:0.85;transition:opacity .3s;transform:scale(0.82);transform-origin:top right">
<div class="kpi-panel" style="background:rgba(8,12,20,.9);border:1px solid #06b6d4;border-radius:8px;padding:4px 8px;backdrop-filter:blur(8px);min-width:130px">
<div style="font:800 12px Nunito;color:#06b6d4;margin-bottom:4px">● STRATÉGIE</div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Décisions</span><span style="font-weight:900;color:#06b6d4">39/cycle</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Providers</span><span style="font-weight:900;color:#06b6d4">14</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Coût</span><span style="font-weight:900;color:#06b6d4">0€</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Uptime</span><span style="font-weight:900;color:#06b6d4">100%</span></div>
<svg width="130" height="20" style="margin-top:3px"><line x1="5" y1="24" x2="128" y2="24" stroke="#1e293b" stroke-width=".5"/><line x1="5" y1="2" x2="5" y2="24" stroke="#1e293b" stroke-width=".5"/><text x="2" y="6" fill="#475569" font-size="4">100%</text><text x="60" y="28" fill="#475569" font-size="4" text-anchor="middle">7 jours</text><text x="128" y="8" fill="#06b6d4" font-size="5" text-anchor="end" font-weight="bold">Uptime</text><polyline points="8,18 20,14 32,16 44,10 56,12 68,8 80,6 92,8 104,5 116,4 128,3" fill="none" stroke="#06b6d4" stroke-width="1.5"/><polygon points="8,18 20,14 32,16 44,10 56,12 68,8 80,6 92,8 104,5 116,4 128,3 128,24 8,24" fill="#06b6d4" fill-opacity=".1"/></svg>
</div>
<div class="kpi-panel" style="background:rgba(8,12,20,.9);border:1px solid #8b5cf6;border-radius:8px;padding:4px 8px;backdrop-filter:blur(8px)">
<div style="font:800 12px Nunito;color:#8b5cf6;margin-bottom:4px">● DIRECTION</div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Routes</span><span style="font-weight:900;color:#8b5cf6">46</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Consensus</span><span style="font-weight:900;color:#8b5cf6">9.8/10</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>AutoFix</span><span style="font-weight:900;color:#8b5cf6">20/20</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Fiability</span><span style="font-weight:900;color:#8b5cf6">100%</span></div>
<svg width="130" height="20" style="margin-top:3px"><line x1="5" y1="24" x2="128" y2="24" stroke="#1e293b" stroke-width=".5"/><line x1="5" y1="2" x2="5" y2="24" stroke="#1e293b" stroke-width=".5"/><text x="2" y="6" fill="#475569" font-size="4">100%</text><text x="60" y="28" fill="#475569" font-size="4" text-anchor="middle">7 jours</text><text x="128" y="8" fill="#8b5cf6" font-size="5" text-anchor="end" font-weight="bold">Consensus</text><polyline points="8,20 20,18 32,14 44,16 56,10 68,8 80,10 92,6 104,4 116,5 128,3" fill="none" stroke="#8b5cf6" stroke-width="1.5"/><polygon points="8,20 20,18 32,14 44,16 56,10 68,8 80,10 92,6 104,4 116,5 128,3 128,24 8,24" fill="#8b5cf6" fill-opacity=".1"/></svg>
</div>
<div class="kpi-panel" style="background:rgba(8,12,20,.9);border:1px solid #f59e0b;border-radius:8px;padding:4px 8px;backdrop-filter:blur(8px)">
<div style="font:800 12px Nunito;color:#f59e0b;margin-bottom:4px">● TACTIQUE</div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>NonReg</span><span style="font-weight:900;color:#f59e0b">153/153</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>CVE</span><span style="font-weight:900;color:#f59e0b">0</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>HCP</span><span style="font-weight:900;color:#f59e0b">141K+</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Skills</span><span style="font-weight:900;color:#f59e0b">1935</span></div>
<svg width="130" height="20" style="margin-top:3px"><line x1="5" y1="24" x2="128" y2="24" stroke="#1e293b" stroke-width=".5"/><line x1="5" y1="2" x2="5" y2="24" stroke="#1e293b" stroke-width=".5"/><text x="2" y="6" fill="#475569" font-size="4">100%</text><text x="60" y="28" fill="#475569" font-size="4" text-anchor="middle">7 jours</text><text x="128" y="8" fill="#f59e0b" font-size="5" text-anchor="end" font-weight="bold">NonReg %</text><polyline points="8,12 20,10 32,8 44,12 56,6 68,8 80,4 92,6 104,3 116,4 128,2" fill="none" stroke="#f59e0b" stroke-width="1.5"/><polygon points="8,12 20,10 32,8 44,12 56,6 68,8 80,4 92,6 104,3 116,4 128,2 128,24 8,24" fill="#f59e0b" fill-opacity=".1"/></svg>
</div>
<div class="kpi-panel" style="background:rgba(8,12,20,.9);border:1px solid #ef4444;border-radius:8px;padding:4px 8px;backdrop-filter:blur(8px)">
<div style="font:800 12px Nunito;color:#ef4444;margin-bottom:4px">● EXÉCUTION</div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Docker</span><span style="font-weight:900;color:#ef4444">17 UP</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Ollama</span><span style="font-weight:900;color:#ef4444">10</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>Fleet</span><span style="font-weight:900;color:#ef4444">669</span></div>
<div style="display:flex;justify-content:space-between;font:600 10px Nunito;color:#94a3b8;padding:1px 0"><span>PMTA</span><span style="font-weight:900;color:#ef4444">4 ECS</span></div>
<svg width="130" height="20" style="margin-top:3px"><line x1="5" y1="24" x2="128" y2="24" stroke="#1e293b" stroke-width=".5"/><line x1="5" y1="2" x2="5" y2="24" stroke="#1e293b" stroke-width=".5"/><text x="2" y="6" fill="#475569" font-size="4">100%</text><text x="60" y="28" fill="#475569" font-size="4" text-anchor="middle">7 jours</text><text x="128" y="8" fill="#ef4444" font-size="5" text-anchor="end" font-weight="bold">Docker UP</text><polyline points="8,16 20,14 32,18 44,12 56,14 68,10 80,12 92,8 104,10 116,6 128,4" fill="none" stroke="#ef4444" stroke-width="1.5"/><polygon points="8,16 20,14 32,18 44,12 56,14 68,10 80,12 92,8 104,10 116,6 128,4 128,24 8,24" fill="#ef4444" fill-opacity=".1"/></svg>
</div>
<div style="background:rgba(6,12,22,.93);border:1px solid #22d3ee;border-radius:10px;padding:5px 8px;backdrop-filter:blur(10px);width:200px;pointer-events:none">
<div style="font:900 13px Nunito;color:#22d3ee;margin-bottom:2px">🚀 ECOSYSTEM</div>
<div style="font:600 9px Nunito;color:#5a4a3a"><div style="display:flex;justify-content:space-between;padding:1px 0"><span>WEVIA</span><span style="color:#4ade80;font-weight:900">ON</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>WEVCODE</span><span style="color:#4ade80;font-weight:900">ON</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>DeerFlow</span><span style="color:#4ade80;font-weight:900">ON</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>WEVADS</span><span style="color:#4ade80;font-weight:900">41pg</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Paperclip</span><span style="color:#4ade80;font-weight:900">ON</span></div><div style="text-align:center;color:#22d3ee;font-weight:900;margin-top:2px;padding-top:2px;border-top:1px solid rgba(34,211,238,.2)">9/10 LIVE</div></div>
</div>
</div>
<div style="position:fixed;left:8px;top:100px;z-index:5;display:flex;flex-direction:column;opacity:0.85;transform:scale(0.82);transform-origin:top left;gap:4px;max-height:calc(100vh - 180px);overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(6,182,212,.3) transparent">
<div style="background:rgba(6,12,22,.93);border:1px solid #8b5cf6;border-radius:8px;padding:5px 8px;backdrop-filter:blur(10px);width:200px;pointer-events:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 2px 8px rgba(0,0,0,.3)">
<div style="font:900 13px Nunito;color:#8b5cf6;margin-bottom:3px">🧠 PROVIDERS</div>
<div style="font:600 9px Nunito;color:#5a4a3a"><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Groq</span><span style="color:#4ade80;font-weight:900">&lt;200ms</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Cerebras</span><span style="color:#4ade80;font-weight:900">235B</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Ollama</span><span style="color:#f59e0b;font-weight:900">10 mdl</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Gemini</span><span style="color:#4ade80;font-weight:900">FREE</span></div><div style="text-align:center;color:#8b5cf6;font-weight:900;margin-top:2px;padding-top:2px;border-top:1px solid rgba(139,92,246,.2)">14 providers 0EUR</div></div></div>
<div style="background:rgba(6,12,22,.93);border:1px solid #f59e0b;border-radius:8px;padding:5px 8px;backdrop-filter:blur(10px);width:200px;pointer-events:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 2px 8px rgba(0,0,0,.3)">
<div style="font:900 13px Nunito;color:#f59e0b;margin-bottom:3px">✅ QUALITY</div>
<div style="font:600 9px Nunito;color:#5a4a3a"><div style="display:flex;justify-content:space-between;padding:1px 0"><span>NonReg</span><span style="color:#4ade80;font-weight:900">153/153</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>E2E</span><span style="color:#4ade80;font-weight:900">18/18</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Fiability</span><span style="color:#4ade80;font-weight:900">100%</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>CVE</span><span style="color:#4ade80;font-weight:900">0</span></div><div style="text-align:center;color:#4ade80;font-weight:900;margin-top:2px;padding-top:2px;border-top:1px solid rgba(245,158,11,.2)">ALL PASS</div></div></div>
<div style="background:rgba(6,12,22,.93);border:1px solid #ef4444;border-radius:8px;padding:5px 8px;backdrop-filter:blur(10px);width:200px;pointer-events:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 2px 8px rgba(0,0,0,.3)">
<div style="font:900 13px Nunito;color:#ef4444;margin-bottom:3px">🖥 SERVERS</div>
<div style="font:600 9px Nunito;color:#5a4a3a"><div style="display:flex;justify-content:space-between;padding:1px 0"><span>S204</span><span style="color:#4ade80;font-weight:900">ON 83%</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>S95</span><span style="color:#4ade80;font-weight:900">ON 81%</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>S151</span><span style="color:#4ade80;font-weight:900">ON</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Blade</span><span style="color:#f59e0b;font-weight:900">STBY</span></div><div style="display:flex;gap:3px;flex-wrap:wrap;margin-top:2px;padding-top:2px;border-top:1px solid rgba(239,68,68,.2)"><span style="font:700 6px Nunito;background:rgba(74,222,128,.15);color:#4ade80;padding:1px 3px;border-radius:3px">Kaggle T4</span><span style="font:700 6px Nunito;background:rgba(139,92,246,.15);color:#a78bfa;padding:1px 3px;border-radius:3px">HF</span><span style="font:700 6px Nunito;background:rgba(6,182,212,.15);color:#22d3ee;padding:1px 3px;border-radius:3px">Colab</span><span style="font:700 6px Nunito;background:rgba(245,158,11,.15);color:#fbbf24;padding:1px 3px;border-radius:3px">CF</span></div></div></div>
<div style="background:rgba(6,12,22,.93);border:1px solid #06b6d4;border-radius:8px;padding:5px 8px;backdrop-filter:blur(10px);width:200px;pointer-events:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 2px 8px rgba(0,0,0,.3)">
<div style="font:900 13px Nunito;color:#06b6d4;margin-bottom:3px">💊 ETHICA</div>
<div style="font:600 9px Nunito;color:#b0bec5"><div style="display:flex;justify-content:space-between;padding:1px 0"><span>HCP Total</span><span style="color:#06b6d4;font-weight:900">141K+</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Maroc</span><span style="color:#4ade80;font-weight:900">19,407</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Algérie</span><span style="color:#4ade80;font-weight:900">91,985</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Tunisie</span><span style="color:#4ade80;font-weight:900">17,329</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Qdrant</span><span style="color:#8b5cf6;font-weight:900">14,368 vec</span></div></div></div>
<div style="background:rgba(6,12,22,.93);border:1px solid #4ade80;border-radius:8px;padding:5px 8px;backdrop-filter:blur(10px);width:200px;pointer-events:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 2px 8px rgba(0,0,0,.3)">
<div style="font:900 13px Nunito;color:#4ade80;margin-bottom:3px">📦 GIT SOUVERAIN</div>
<div style="font:600 9px Nunito;color:#b0bec5"><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Gitea Repos</span><span style="color:#4ade80;font-weight:900">50</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>GitHub Mirror</span><span style="color:#4ade80;font-weight:900">17</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>OSS Local</span><span style="color:#06b6d4;font-weight:900">33</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Commits/j</span><span style="color:#f59e0b;font-weight:900">~15</span></div></div></div>
<div style="background:rgba(6,12,22,.93);border:1px solid #a78bfa;border-radius:10px;padding:5px 8px;backdrop-filter:blur(10px);width:200px;pointer-events:none">
<div style="font:900 13px Nunito;color:#a78bfa;margin-bottom:2px">💬 CHATBOTS</div>
<div style="font:600 9px Nunito;color:#b0bec5"><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Widget</span><span style="color:#4ade80;font-weight:900">71mod</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>WEVCODE</span><span style="color:#4ade80;font-weight:900">4mod</span></div><div style="display:flex;justify-content:space-between;padding:1px 0"><span>Master</span><span style="color:#4ade80;font-weight:900">51cmd</span></div><div style="text-align:center;color:#a78bfa;font-weight:900;margin-top:2px;padding-top:2px;border-top:1px solid rgba(167,139,250,.2)">5 bots 0EUR</div></div></div></div>
</div>
<div style="position:fixed;top:28px;left:50%;transform:translateX(-50%);z-index:2;display:flex;gap:12px;background:rgba(6,12,22,.95);border:1px solid rgba(6,182,212,.4);border-radius:20px;padding:5px 18px;box-shadow:0 2px 12px rgba(0,0,0,.3);box-shadow:0 0 12px rgba(6,182,212,.1);backdrop-filter:blur(12px);pointer-events:none">
<div style="font:700 7px Nunito;color:#4ade80;display:flex;align-items:center;gap:3px"><span style="width:6px;height:6px;border-radius:50%;background:#4ade80;display:inline-block" class="pulse-dot"></span> System OK</div><style>.pulse-dot{animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}
@media(max-width:1600px){
.hud .stats{font-size:9px}.hud .nav a{font-size:8px}
}
@media(max-width:1200px){
.hud .stats{font-size:8px;gap:6px}.hud .nav a{padding:2px 5px;font-size:7px}
}
@media(max-width:900px){
.hud .stats{display:none}.hud .nav{flex-wrap:wrap}
}
#liveStatusBar{display:none!important}
[style*="bottom:8px"][style*="left:200px"]{display:none!important}
</style>
<div style="font:700 7px Nunito;color:#94a3b8">|</div>
<div style="font:700 7px Nunito;color:#06b6d4">Uptime 100%</div>
<div style="font:700 7px Nunito;color:#94a3b8">|</div>
<div style="font:700 7px Nunito;color:#8b5cf6">Consensus 9.8</div>
<div style="font:700 7px Nunito;color:#94a3b8">|</div>
<div style="font:700 7px Nunito;color:#f59e0b">NR 153/153</div>
<div style="font:700 7px Nunito;color:#94a3b8">|</div>
<div style="font:700 7px Nunito;color:#ef4444">Docker 17</div>
<div style="font:700 7px Nunito;color:#94a3b8">|</div>
<div style="font:700 7px Nunito;color:#4ade80">0€</div>
</div>
<div style="position:fixed;left:50%;bottom:110px;transform:translateX(-50%);z-index:9998;background:rgba(6,12,22,.85);border-radius:20px;padding:4px 14px;backdrop-filter:blur(8px);pointer-events:none;border:1px solid rgba(100,116,139,.2);display:flex;align-items:center;gap:10px">
<div style="font:700 7px Nunito;color:#94a3b8;margin-bottom:3px">LÉGENDE</div>
<div style="display:flex;align-items:center;gap:4px;font:600 9px Nunito;color:#b0bec5;padding:1px 0"><span style="width:8px;height:2px;background:#06b6d4;display:inline-block;border-radius:1px"></span> Stratégie</div>
<div style="display:flex;align-items:center;gap:4px;font:600 9px Nunito;color:#b0bec5;padding:1px 0"><span style="width:8px;height:2px;background:#8b5cf6;display:inline-block;border-radius:1px"></span> Direction</div>
<div style="display:flex;align-items:center;gap:4px;font:600 9px Nunito;color:#b0bec5;padding:1px 0"><span style="width:8px;height:2px;background:#f59e0b;display:inline-block;border-radius:1px"></span> Tactique</div>
<div style="display:flex;align-items:center;gap:4px;font:600 9px Nunito;color:#b0bec5;padding:1px 0"><span style="width:8px;height:2px;background:#ef4444;display:inline-block;border-radius:1px"></span> Exécution</div>
<div style="display:flex;align-items:center;gap:4px;font:600 9px Nunito;color:#b0bec5;padding:1px 0"><span style="width:6px;height:6px;border-radius:50%;border:1px solid #4ade80;display:inline-block"></span> Actif</div>
<div style="display:flex;align-items:center;gap:4px;font:600 9px Nunito;color:#b0bec5;padding:1px 0"><span style="width:6px;height:6px;border-radius:50%;border:1px solid #ef4444;display:inline-block"></span> Alerte</div>
</div>
</div>
</div>
<div style="position:fixed;bottom:55px;left:50%;transform:translateX(-50%);z-index:9998;display:flex;gap:6px;pointer-events:none"><div style="background:rgba(6,12,22,.93);border:1px solid #06b6d4;border-radius:10px;padding:6px 10px;backdrop-filter:blur(10px);pointer-events:auto;cursor:pointer" onclick="window.open('/wevia-meeting-rooms.html')"><div style="font:800 12px Nunito;color:#06b6d4">MEETING</div></div><div style="background:rgba(6,12,22,.93);border:1px solid #8b5cf6;border-radius:10px;padding:6px 10px;backdrop-filter:blur(10px);pointer-events:auto;cursor:pointer" onclick="window.open('/director-center.html')"><div style="font:800 12px Nunito;color:#8b5cf6">DIRECTOR</div></div><div style="background:rgba(6,12,22,.93);border:1px solid #f59e0b;border-radius:10px;padding:6px 10px;backdrop-filter:blur(10px);pointer-events:auto;cursor:pointer" onclick="window.open('/security-dashboard.html')"><div style="font:800 12px Nunito;color:#f59e0b">SECURITY</div></div><div style="background:rgba(6,12,22,.93);border:1px solid #ef4444;border-radius:10px;padding:6px 10px;backdrop-filter:blur(10px);pointer-events:auto;cursor:pointer" onclick="window.open('/enterprise-model.html')"><div style="font:800 12px Nunito;color:#ef4444">ENTERPRISE</div></div><div style="background:rgba(6,12,22,.93);border:1px solid #4ade80;border-radius:10px;padding:6px 10px;backdrop-filter:blur(10px);pointer-events:auto;cursor:pointer" onclick="window.open('/l99-brain.html')"><div style="font:800 12px Nunito;color:#4ade80">L99</div></div></div>
<!-- CARTO_REMOVED -->
<!-- WTP-GAP-FILL-V1 (doctrine 90-v2 gap-fill showcase, 18avr 2026) -->
<style>
.wtp-gapfill-banner{position:fixed;bottom:0;left:0;right:0;z-index:99999;background:linear-gradient(90deg,#05060a,#0b0d15 20%,#181d2e 50%,#0b0d15 80%,#05060a);border-top:2px solid #14b8a6;color:#e2e8f0;padding:10px 16px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:11.5px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;box-shadow:0 -10px 30px rgba(20,184,166,.28)}
.wtp-gapfill-banner a{color:#5eead4;text-decoration:none;font-weight:600;transition:color .15s}
.wtp-gapfill-banner a:hover{color:#22d3ee}
.wtp-gapfill-banner .pill{padding:2px 9px;background:rgba(99,102,241,.14);color:#a5b4fc;border-radius:10px;font-size:10.5px;font-family:JetBrains Mono,monospace;font-weight:600}
.wtp-gapfill-banner .pill.new{background:rgba(20,184,166,.22);color:#5eead4}
.wtp-gapfill-banner .pill.hot{background:rgba(236,72,153,.22);color:#f472b6}
.wtp-gapfill-banner .close{margin-left:auto;cursor:pointer;color:#64748b;padding:0 8px;font-size:16px;line-height:1;border:1px solid #334155;border-radius:4px}
.wtp-gapfill-banner .close:hover{color:#e2e8f0;border-color:#64748b}
.wtp-gapfill-banner.hidden{display:none}
@media(max-width:768px){.wtp-gapfill-banner{font-size:10px;padding:7px 10px;gap:8px}}
</style>
<div class="wtp-gapfill-banner" id="wtpGapFillBanner">
<span>🎯 <strong>WEVAL Agents Gap-Fill ERP</strong></span>
<span class="pill hot" id="gaps-banner-count">17 gaps live</span>
<span class="pill">SAP · Oracle · NetSuite · Dynamics</span>
<span class="pill new">🆕 Meeting Rooms</span>
<span class="pill new">🆕 Lean 6 Sigma</span>
<span id="wtp-gfb-metrics" class="pill">— chargement —</span>
<a href="/weval-technology-platform.html">→ WTP Portal (16 mod)</a>
<a href="/enterprise-model.html">Enterprise Model</a>
<a href="/api/weval-agents-gap-fill-manifest.json" target="_blank">📋 Manifest</a>
<span class="close" onclick="document.getElementById("wtpGapFillBanner").classList.add("hidden");localStorage.setItem("wtpGapFillHidden","1")">×</span>
</div>
<script>
(async()=>{
if(localStorage.getItem("wtpGapFillHidden")==="1"){document.getElementById("wtpGapFillBanner").classList.add("hidden");return;}
try{
const r=await fetch("/api/source-of-truth.json?t="+Date.now());
const d=await r.json();
const el=document.getElementById("wtp-gfb-metrics");
if(el)el.textContent=(d.ethica_total||"?")+" HCPs · "+(d.nonreg||"?")+" · "+(d.providers_count||"?")+" IA · "+(d.agents_count||"?")+" agents · "+(d.docker_running||"?")+" 🐳";
}catch(e){}
})();
</script>
<!-- WTP-D90V2-ENRICH-BANNER (doctrine 90-v2, 17avr 2026) -->
<style>
.wtp-enrich-banner{position:fixed;bottom:0;left:0;right:0;z-index:9999;background:linear-gradient(90deg,#0b0d15,#181d2e,#0b0d15);border-top:2px solid #14b8a6;color:#e2e8f0;padding:9px 18px;font-family:'JetBrains Mono',monospace,-apple-system,system-ui;font-size:11.5px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;box-shadow:0 -8px 24px rgba(20,184,166,.25)}
.wtp-enrich-banner a{color:#14b8a6;text-decoration:none;font-weight:600}
.wtp-enrich-banner a:hover{color:#22d3ee}
.wtp-enrich-banner .pill{padding:2px 8px;background:rgba(99,102,241,.15);color:#a5b4fc;border-radius:10px;font-size:10.5px}
.wtp-enrich-banner .pill.new{background:rgba(20,184,166,.2);color:#5eead4}
.wtp-enrich-banner .close{margin-left:auto;cursor:pointer;color:#64748b;padding:0 6px;font-size:14px}
.wtp-enrich-banner .close:hover{color:#e2e8f0}
.wtp-enrich-banner.hidden{display:none}
@media(max-width:768px){.wtp-enrich-banner{font-size:10px;padding:6px 10px}}
/* === WEVIA Gemini Rolling v2 VISIBLE Enrichment (wave 306 batch) === */
.kpi,[class*="card"],[class*="panel"],[class*="room"],.stat-card,.metric-card,.hub-card,.widget,.stat,.box{position:relative!important}
.kpi,[class*="card"],.stat-card,.metric-card,.hub-card{animation:geV2Entrance .8s cubic-bezier(.34,1.56,.64,1) backwards}
.kpi:nth-child(1),[class*="card"]:nth-child(1){animation-delay:0s}
.kpi:nth-child(2),[class*="card"]:nth-child(2){animation-delay:.09s}
.kpi:nth-child(3),[class*="card"]:nth-child(3){animation-delay:.18s}
.kpi:nth-child(4),[class*="card"]:nth-child(4){animation-delay:.27s}
.kpi:nth-child(5),[class*="card"]:nth-child(5){animation-delay:.36s}
.kpi:nth-child(6),[class*="card"]:nth-child(6){animation-delay:.45s}
@keyframes geV2Entrance{from{opacity:0;transform:translateY(24px) scale(.94)}to{opacity:1;transform:translateY(0) scale(1)}}
.kpi,[class*="card"],.stat-card,.metric-card,.hub-card,.widget{border:1px solid transparent!important;box-shadow:0 0 0 1px rgba(236,72,153,.15),0 4px 16px rgba(0,0,0,.25)!important;transition:box-shadow .4s,transform .3s cubic-bezier(.34,1.56,.64,1),filter .3s!important}
.kpi:hover,[class*="card"]:hover,.stat-card:hover,.metric-card:hover,.hub-card:hover{transform:translateY(-6px) scale(1.03)!important;filter:brightness(1.2)!important;box-shadow:0 0 0 2px rgba(236,72,153,.6),0 12px 32px rgba(236,72,153,.25),0 0 24px rgba(78,205,196,.2)!important}
.kpi::before,[class*="card"]::before,.stat-card::before,.metric-card::before,.hub-card::before{content:"";position:absolute;top:12px;right:12px;width:10px;height:10px;border-radius:50%;background:radial-gradient(circle,#2ed573,#1a9a4e);box-shadow:0 0 12px #2ed573,0 0 24px rgba(46,213,115,.5);animation:geV2Pulse 1.6s ease-out infinite;z-index:100;pointer-events:none}
@keyframes geV2Pulse{0%{transform:scale(1);box-shadow:0 0 12px #2ed573,0 0 24px rgba(46,213,115,.5)}50%{transform:scale(1.4);box-shadow:0 0 20px #2ed573,0 0 40px rgba(46,213,115,.8)}100%{transform:scale(1);box-shadow:0 0 12px #2ed573,0 0 24px rgba(46,213,115,.5)}}
body::after{content:"";position:fixed;inset:0;pointer-events:none;background:radial-gradient(ellipse at 70% 30%,transparent 40%,rgba(236,72,153,.06) 100%),radial-gradient(ellipse at 30% 70%,transparent 40%,rgba(78,205,196,.04) 100%);animation:geV2Ambient 10s ease-in-out infinite;z-index:0}
@keyframes geV2Ambient{0%,100%{opacity:.5}50%{opacity:1}}
h1,.header-title,.main-title,.hub-title,.page-title{background-image:linear-gradient(90deg,currentColor 0%,currentColor 40%,rgba(236,72,153,1) 50%,currentColor 60%,currentColor 100%)!important;background-size:200% auto!important;-webkit-background-clip:text!important;background-clip:text!important;-webkit-text-fill-color:transparent!important;animation:geV2Shimmer 5s linear infinite!important}
@keyframes geV2Shimmer{0%{background-position:200% center}100%{background-position:-200% center}}
/* Doctrine zero chevauchement - hide common offenders */
.opus-x-btn,.toggle-top-right-btn,.fab-corner{display:none!important}
/* === end WEVIA Gemini Rolling v2 batch === */
</style>
<div class="wtp-enrich-banner" id="wtpEnrichBanner">
<span>🏛️ <strong>Enterprise Model 16 depts</strong></span>
<span class="pill new">🆕 Meeting Rooms</span>
<span class="pill new">🆕 Lean 6 Sigma</span>
<span id="wtp-eb-metrics" class="pill">— chargement —</span>
<a href="/weval-technology-platform.html">→ WEVAL Technology Platform (16 modules)</a>
<a href="/enterprise-model.html">Enterprise Model</a>
<a href="/wevia-master.html">WEVIA Master</a>
<span class="close" onclick="document.getElementById('wtpEnrichBanner').classList.add('hidden')">×</span>
</div>
<script>
(async()=>{try{const r=await fetch('/api/source-of-truth.json?t='+Date.now());const d=await r.json();const el=document.getElementById('wtp-eb-metrics');if(el)el.textContent=(d.ethica_total||'?')+' HCPs · '+(d.nonreg||'?')+' · '+(d.providers_count||'?')+' IA · '+(d.docker_running||'?')+' 🐳 · '+(d.subdomains_live||'?')+' subdomains';}catch(e){}})();
</script>
<!-- V66-PAIN-POINTS-ATLAS -->
<div style="position:fixed;bottom:18px;right:18px;z-index:999;background:linear-gradient(135deg,#eab308,#f59e0b);border-radius:10px;padding:12px 16px;box-shadow:0 12px 32px rgba(234,179,8,0.4);display:flex;gap:10px;align-items:center;max-width:360px;text-decoration:none">
<span style="font-size:22px">🗺️</span>
<div style="color:#0b0d15">
<div style="font-size:12px;font-weight:800">Pain Points Atlas · 25 ERPs</div>
<div style="font-size:10.5px;opacity:.85">60 pain points · 60 agents · 23.1M€ savings/client</div>
<a href="/pain-points-atlas.html" style="display:inline-block;margin-top:4px;padding:3px 10px;background:#0b0d15;color:#eab308;border-radius:5px;font-size:10.5px;font-weight:700;text-decoration:none">Open Atlas →</a>
</div>
</div>
<!-- /V66-PAIN-POINTS-ATLAS -->
<script id="d91-archi-rerender">
(function(){
// V120 SSOT — Update existing p-av spans with WevalAvatar emoji once helper is ready.
// Also remove any legacy <img dicebear/robohash> that might have leaked through.
function refresh(){
if (!window.WevalAvatar || !WevalAvatar.isReady || !WevalAvatar.isReady()) return false;
// Update spans (created with default 👤 if helper wasn't ready at render time)
document.querySelectorAll('.ag-card .p-av[data-agent]').forEach(span => {
const name = span.dataset.agent;
if (!name) return;
const e = WevalAvatar.get(name);
if (e && e.emoji) {
span.textContent = e.emoji;
if (e.persona) span.dataset.persona = e.persona;
}
});
// Cleanup legacy imgs
document.querySelectorAll('.ag-card img[src*="robohash"],.ag-card img[src*="dicebear"]').forEach(img => img.remove());
return true;
}
let tries = 0;
const iv = setInterval(() => {
tries++;
if (refresh() || tries > 40) clearInterval(iv);
}, 250);
})();
</script>
<script id="d93cj">/* DISABLED 20260420 — was double heads vs Three.js CSS2DRenderer. d91 swap suffices. */</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
<script>
(function(){
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
var d = document;
var m = d.createElement('div');
m.id = 'opus-udrill';
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
var inner = d.createElement('div');
inner.id = 'opus-udrill-in';
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
inner.addEventListener('click', function(e){ e.stopPropagation(); });
m.appendChild(inner);
m.addEventListener('click', function(){ m.style.display='none'; });
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
(d.body || d.documentElement).appendChild(m);
function openCard(card) {
// Clone card content + show close btn + increase font-size
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
inner.innerHTML = html;
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
m.style.display = 'flex';
}
function wire(root) {
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
var cards = root.querySelectorAll(sels);
for (var i = 0; i < cards.length; i++) {
var c = cards[i];
if (c.__opusWired) continue;
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
var r = c.getBoundingClientRect();
if (r.width < 60 || r.height < 40) continue;
c.__opusWired = true;
c.style.cursor = 'pointer';
c.setAttribute('role','button');
c.setAttribute('tabindex','0');
c.addEventListener('click', function(ev){
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
if (ev.target.closest('a,button,input,select')) return;
ev.preventDefault(); ev.stopPropagation();
openCard(this);
});
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
}
}
// Initial + mutation observer
var initRun = function(){ wire(d.body || d.documentElement); };
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
else initRun();
var mo = new MutationObserver(function(muts){
var newCard = false;
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
if (newCard) initRun();
});
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
<script>
(function(){
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
async function updateHonestValues(){
try {
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
const d = await r.json();
if (!d.ok) return;
const realNR = `${d.combined.pass}/${d.combined.total}`;
const realSigma = d.sigma;
// Find elements showing the myth values
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
// Walk text nodes
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
const toReplace = [];
let node;
while (node = walker.nextNode()) {
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
}
toReplace.forEach(textNode => {
const parent = textNode.parentNode;
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
textNode.nodeValue = newText;
parent.setAttribute('data-opus-honest-applied', '1');
});
// Add a small badge bottom-right showing honest live status
if (!document.getElementById('opus-honest-badge')) {
const b = document.createElement('div');
b.id = 'opus-honest-badge';
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
b.title = 'Cliquer pour détails';
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
b.onclick = () => {
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
};
document.body.appendChild(b);
}
} catch(e){console.error('L99-honest fetch error:', e);}
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
else updateHonestValues();
setInterval(updateHonestValues, 90000);
})();
</script>
<!-- === OPUS HONEST END === -->
<script>
// Opus v9.32 gaps banner live
(async function(){
try {
const r = await fetch('/api/weval-agents-gap-fill-manifest.json');
const d = await r.json();
const erp = d.erp_gaps_covered || {};
let total = 0;
for (const k in erp) {
const v = erp[k];
if (Array.isArray(v)) total += v.length;
else if (v && Array.isArray(v.gaps)) total += v.gaps.length;
}
const el = document.getElementById('gaps-banner-count');
if (el && total > 0) el.textContent = total + ' ERP gaps';
} catch(e) {}
})();
</script>
<script src="/api/a11y-auto-enhancer.js" defer></script>
<!-- WTP_UDOCK_V1 (Opus 21-avr tour29) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
<!-- DOCTRINE-60-UX-JS --><script id="doctrine60-ux-js-direct">
// DOCTRINE-60-UX-JS staggered entrance
(function(){
if (!('IntersectionObserver' in window)) return;
const obs = new IntersectionObserver((entries) => {
entries.forEach((e, i) => {
if (e.isIntersecting) {
setTimeout(() => e.target.classList.add('enter-stagger'), i * 80);
obs.unobserve(e.target);
}
});
});
document.querySelectorAll('.card, .kpi, .panel').forEach(el => obs.observe(el));
})();
</script>
</body></html>