Files
html/agents-valuechain.html
opus c42b0ec0fb
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
auto-sync via WEVIA git_sync_all intent 2026-04-21T12:08:27+02:00
2026-04-21 12:08:27 +02:00

490 lines
24 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>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WEVAL Value Chain — Agents</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Outfit:wght@300;500;700;900&display=swap" rel="stylesheet">
<style>@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;700;800;900&display=swap');
:root{--bg:#06080f;--card:#0c1020;--border:#1a2040;--text:#c8d0e0;--dim:#5a6580;--green:#22c55e;--red:#ef4444;--blue:#3b82f6;--purple:#a855f7;--amber:#f59e0b;--cyan:#06b6d4;--pink:#ec4899;--lime:#84cc16;}
*{margin:0;padding:0;box-sizing:border-box;}
body{background:var(--bg);color:var(--text);font-family:'Outfit',sans-serif;overflow-x:hidden;}
.noise{position:fixed;inset:0;opacity:.025;pointer-events:none;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");}
header{padding:32px 40px 16px;border-bottom:1px solid var(--border);}
h1{font-size:2.4rem;font-weight:900;letter-spacing:-2px;}
h1 span{background:linear-gradient(135deg,var(--cyan),var(--purple));-webkit-background-clip:text;-webkit-text-fill-color:transparent;}
.sub{color:var(--dim);font-size:.85rem;margin-top:4px;}
.chain{padding:30px 24px 60px;position:relative;}
/* ═══ STAGE ═══ */
.stage{
position:relative;margin-bottom:12px;
border:1px solid var(--border);border-radius:16px;
background:var(--card);overflow:hidden;
animation:fadeIn .5s ease both;
}
.stage:nth-child(2){animation-delay:.1s}
.stage:nth-child(3){animation-delay:.2s}
.stage:nth-child(4){animation-delay:.3s}
.stage:nth-child(5){animation-delay:.4s}
.stage:nth-child(6){animation-delay:.5s}
.stage:nth-child(7){animation-delay:.6s}
.stage:nth-child(8){animation-delay:.7s}
@keyframes fadeIn{from{opacity:0;transform:translateX(-20px)}to{opacity:1;transform:none}}
.stage-header{
display:flex;align-items:center;gap:16px;
padding:16px 20px;cursor:pointer;
border-bottom:1px solid transparent;
transition:.2s;
}
.stage.open .stage-header{border-bottom:1px solid var(--border);}
.stage-header:hover{background:#0e1428;}
.stage-icon{
width:48px;height:48px;border-radius:12px;
display:flex;align-items:center;justify-content:center;
font-size:1.5rem;flex-shrink:0;
}
.stage-title{font-weight:700;font-size:1.1rem;color:#fff;}
.stage-sub{font-size:.78rem;color:var(--dim);margin-top:2px;}
.stage-right{margin-left:auto;display:flex;align-items:center;gap:12px;}
.stage-count{
font-family:'JetBrains Mono',monospace;font-size:.75rem;
background:#111830;padding:4px 10px;border-radius:8px;color:var(--cyan);
}
.stage-arrow{color:var(--dim);font-size:1.2rem;transition:transform .2s;}
.stage.open .stage-arrow{transform:rotate(90deg);}
.stage-body{display:none;padding:16px 20px;}
.stage.open .stage-body{display:block;}
/* ═══ FLOW CONNECTOR ═══ */
.flow-connector{
display:flex;justify-content:center;padding:4px 0;
}
.flow-line{
width:2px;height:24px;
background:linear-gradient(180deg,var(--cyan),var(--purple));
border-radius:2px;position:relative;
}
.flow-line::after{
content:'▼';position:absolute;bottom:-10px;left:50%;transform:translateX(-50%);
font-size:.6rem;color:var(--purple);
}
/* ═══ AGENTS ROW ═══ */
.agents-row{display:flex;flex-wrap:wrap;gap:10px;}
.agent-chip{
display:flex;align-items:center;gap:8px;
background:#111830;border:1px solid #1a2540;
border-radius:12px;padding:8px 14px;
transition:.2s;cursor:default;position:relative;
}
.agent-chip:hover{border-color:var(--cyan);transform:translateY(-2px);box-shadow:0 4px 16px rgba(6,182,212,.1);}
.agent-chip .av{
width:32px;height:32px;border-radius:8px;
display:flex;align-items:center;justify-content:center;
font-size:1rem;background:#1a2550;position:relative;
}
.agent-chip .av::after{
content:'';position:absolute;bottom:-1px;right:-1px;
width:8px;height:8px;border-radius:50%;background:var(--green);
border:1.5px solid #111830;
}
.agent-chip .info{display:flex;flex-direction:column;}
.agent-chip .name{font-weight:600;font-size:.82rem;color:#fff;}
.agent-chip .prod{font-family:'JetBrains Mono',monospace;font-size:.62rem;color:var(--cyan);opacity:.7;}
/* ═══ OUTPUTS ═══ */
.outputs{margin-top:12px;display:flex;flex-wrap:wrap;gap:6px;}
.output-tag{
font-family:'JetBrains Mono',monospace;font-size:.65rem;
background:#0a1225;border:1px solid #1a2040;
padding:3px 10px;border-radius:6px;color:var(--amber);
}
/* ═══ RISK BAR ═══ */
.risk-bar{
margin-top:12px;padding:8px 12px;
background:#1a0a0a;border:1px solid #3a1515;border-radius:8px;
display:flex;align-items:center;gap:8px;font-size:.75rem;
}
.risk-bar .icon{font-size:1rem;}
.risk-bar .text{color:#f87171;}
/* ═══ COLORS ═══ */
.bg-prospect{background:linear-gradient(135deg,#0a1a30,#081528);}
.bg-consulting{background:linear-gradient(135deg,#1a0a30,#120828);}
.bg-dev{background:linear-gradient(135deg,#0a2a1a,#081a12);}
.bg-infra{background:linear-gradient(135deg,#2a1a0a,#1a1208);}
.bg-security{background:linear-gradient(135deg,#2a0a0a,#1a0808);}
.bg-delivery{background:linear-gradient(135deg,#0a2a2a,#081a1a);}
.bg-pharma{background:linear-gradient(135deg,#1a0a2a,#120820);}
.bg-monitor{background:linear-gradient(135deg,#1a1a0a,#121208);}
@media(max-width:768px){
.agents-row{flex-direction:column;}
header{padding:20px;}
.chain{padding:16px 12px;}
}
</style>
</head>
<body style="padding-top:60px"><div style="position:fixed;top:0;left:0;right:0;height:28px;background:#ffffffee;z-index:100;display:flex;align-items:center;padding:0 14px;font-family:Nunito,sans-serif;font-size:.65rem;gap:12px;border-bottom:1px solid #e2e8f0;backdrop-filter:blur(8px)"><b style="color:#059669">WEVIA</b></div>
<div style="position:fixed;top:30px;left:0;right:0;display:flex;justify-content:center;gap:5px;padding:4px;z-index:100;background:#f8fafcee;backdrop-filter:blur(8px);font-family:Nunito,sans-serif">
<a href="/agents-archi.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Architecture</a>
<a href="/director-center.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Director</a>
<a href="/wevia-meeting-rooms.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Rooms</a>
<a href="/enterprise-model.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Enterprise</a>
<a href="/agents-ia.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Pyramid</a>
<a href="/director-chat.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Chat</a>
<a href="/l99-brain.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">L99</a>
</div><div id="live-stats" ondblclick="this.remove()" style="position:fixed;top:0;left:0;right:0;z-index:9999;display:flex;justify-content:center;gap:12px;padding:4px 8px;background:linear-gradient(135deg,#1e293b,#0f172a);font-family:sans-serif"><div style="color:#4ade80;font:700 10px sans-serif"><body>#9889; <span id="ls-ag">669</span> Agents</div><div style="color:#60a5fa;font:700 10px sans-serif"><body>#127970; <span id="ls-dp">22</span> Depts</div><div style="color:#fbbf24;font:700 10px sans-serif"><body>#128051; 20 Docker</div><div style="color:#a78bfa;font:700 10px sans-serif"><body>#129302; 10 Ollama</div><div style="color:#f87171;font:700 10px sans-serif"><body>#128200; <span id="ls-nr">153/153</span></div><div style="color:#34d399;font:700 10px sans-serif"><body>#128274; SSO OK</div><div style="width:6px;height:6px;border-radius:50%;background:#4ade80;animation:lp 2s infinite;align-self:center"></div></div><style>@keyframes lp{0%,100%{opacity:1}50%{opacity:.3}}</style>
<div class="noise"></div>
<header>
<h1><span>WEVAL</span> Value Chain</h1>
<div class="sub">Où chaque agent agit — de la prospection à la livraison · Cliquez pour ouvrir</div>
</header>
<div class="chain" id="chain"></div>
<script>
const CHAIN = [
{
id:'prospect', icon:'🎯', title:'Prospection & Leads', color:'bg-prospect',
desc:'Acquisition clients, scraping B2B, enrichissement contacts',
agents:[
{n:'Ethica Scraper',e:'💊',p:'131K+ HCPs DZ/MA/TN'},
{n:'analyst',e:'🔍',p:'Analyse besoins client'},
{n:'writer',e:'✍️',p:'Cold emails, proposals'},
{n:'/sc:business_panel',e:'📊',p:'Analyse marché, KPIs'},
],
outputs:['weval_leads (166 contacts)','ethica_medecins (131K+)','linkedin_profiles (469)','Email campaigns B2B'],
risk:'Taux de réponse cold email < 5% — enrichissement emails en cours (gap: DZ 15K, MA 4.9K)',
},
{
id:'consulting', icon:'💼', title:'Consulting & Stratégie', color:'bg-consulting',
desc:'SWOT, audits, propositions commerciales, transformation digitale',
agents:[
{n:'CEO',e:'👔',p:'Décisions stratégiques autonomes'},
{n:'architect',e:'🏗️',p:'Architecture technique'},
{n:'planner',e:'📋',p:'Roadmaps, planning'},
{n:'critic',e:'⚖️',p:'Validation plans, risques'},
{n:'/sc:deep_research',e:'🔬',p:'Recherche approfondie'},
{n:'DeerFlow',e:'🦌',p:'Research multi-sources'},
],
outputs:['Propositions commerciales','Architecture technique','SWOT / PESTEL','Roadmaps migration','Audits conformité'],
risk:'12 providers cascade (0€): Groq→Cerebras→Gemini→Mistral→OpenRouter→SambaNova→Together→DeepSeek→Cohere→Nvidia→Qwen→ZhiPu — Ollama local en fallback',
},
{
id:'dev', icon:'⚡', title:'Développement & Code', color:'bg-dev',
desc:'Code, APIs, intégrations, 396 APIs PHP actives, 38 outils',
agents:[
{n:'executor',e:'⚡',p:'Exécution scripts, deploy'},
{n:'debugger',e:'🐛',p:'Trace bugs, root cause'},
{n:'code-reviewer',e:'👁️',p:'Reviews, severity rating'},
{n:'code-simplifier',e:'✂️',p:'Refactoring, clean code'},
{n:'designer',e:'🎨',p:'UI/UX, mockups'},
{n:'WEDROID',e:'🤖',p:'Backend auto-fix v5.0'},
{n:'/sc:token_efficiency',e:'⚡',p:'Code optimisé'},
],
outputs:['396 APIs PHP','WEVADS IA (36 pages)','WEVIA Chatbot (2842 lignes)','NonReg 153 tests','React SPA'],
risk:'Chatbot 24KB (refactoris — dette technique élevée, refonte par modules recommandée',
},
{
id:'infra', icon:'🏗️', title:'Infrastructure & DevOps', color:'bg-infra',
desc:'3 serveurs, 17 Docker, Ollama 5 modèles, Qdrant RAG',
agents:[
{n:'Watchdog',e:'🐕',p:'Auto-restart */3min'},
{n:'Guardian',e:'🛡️',p:'chattr +i, protection'},
{n:'Blade Sentinel',e:'💻',p:'Desktop agent PowerShell'},
{n:'git-master',e:'🌿',p:'Releases, branches'},
{n:'/sc:orchestration',e:'🎯',p:'Coordination multi-agent'},
],
outputs:['S204 (17 Docker)','S95 (192 Arsenal endpoints)','S151 (Ollama + tracking)','Blade (Razer laptop)','52 repos /opt/'],
risk:'Disk S204 82% — nettoyage régulier requis. S88 = DEAD (annulé, 0€)',
},
{
id:'security', icon:'🛡️', title:'Sécurité & Conformité', color:'bg-security',
desc:'OWASP, ISO 27001, RGPD, audit, chiffrement',
agents:[
{n:'security-reviewer',e:'🛡️',p:'Audit OWASP, vulns'},
{n:'verifier',e:'✅',p:'Conformité, checks'},
{n:'Guardian',e:'🛡️',p:'Protection fichiers'},
{n:'/sc:introspection',e:'🧠',p:'Méta-analyse sécurité'},
],
outputs:['Audit CLAUDE.md (secrets=clean)','Auth PHP session HMAC (simplifié, 0 dépendance)','AgentShield scan','chattr +i (8 fichiers protégés)'],
risk:'Auth PHP session + HMAC 30j — Authentik supprimé 8-avr (plus léger, plus stable)',
},
{
id:'delivery', icon:'🚀', title:'Livraison & QA', color:'bg-delivery',
desc:'Tests, NonReg, Playwright, L99, déploiement continu',
agents:[
{n:'qa-tester',e:'🧪',p:'Tests E2E, couverture'},
{n:'test-engineer',e:'🧰',p:'Suites CI/CD'},
{n:'tracer',e:'🔦',p:'Logs, debug chain'},
{n:'scientist',e:'🔬',p:'Benchmarks, métriques'},
],
outputs:['NonReg 153/153 PASS','L99 957/957 = 100% + NonReg 153/153 + PW 20/20','Playwright 20/20 + Visual 15/15','11 baselines visuelles','AI Benchmark (182 modèles)'],
risk:'L99 957/957 = 100% — 6σ DPMO 0',
},
{
id:'pharma', icon:'💊', title:'Pharma & Ethica', color:'bg-pharma',
desc:'HCP outreach Maghreb, campagnes email, consent RGPD',
agents:[
{n:'Ethica Scraper',e:'💊',p:'DabaDoc + LinkedIn'},
{n:'explore',e:'🧭',p:'Exploration nouvelles sources'},
{n:'document-specialist',e:'📝',p:'Templates campagnes'},
{n:'/sc:brainstorming',e:'💡',p:'Idées campagnes'},
{n:'MiroFish',e:'🐟',p:'Contenu créatif'},
],
outputs:['131K+ HCPs (DZ 95K, MA 19K, TN 17K)','Email drip */5min (DZ+MA+TN)','PhantomBuster LinkedIn','Consent RGPD (wevup.app)','16 scripts + 12 crons'],
risk:'Taux emails manquants: DZ 15K, MA 4.9K, TN 2.9K — enrichissement en cours',
},
{
id:'monitor', icon:'📡', title:'Monitoring & Intelligence', color:'bg-monitor',
desc:'Realtime monitor, KPIs, alertes, training data',
agents:[
{n:'Watchdog',e:'🐕',p:'Alerte Telegram restart'},
{n:'/sc:task_management',e:'📋',p:'Suivi tâches, deadlines'},
{n:'CEO',e:'👔',p:'Décisions autonomes'},
{n:'DeerFlow',e:'🦌',p:'Veille technologique'},
],
outputs:['Realtime Monitor v2','L99 Command Center','Uptime Kuma (99.9%)','Plausible Analytics','5,731+ training samples (GPU-ready, HuggingFace yace222/)'],
risk:'Fine-tune Phase 5 planifié — 5,731+ samples prêts, attente Colab/Kaggle',
},
];
function render(){
const el = document.getElementById('chain');
let html = '';
CHAIN.forEach((s,i) => {
html += `
<div class="stage" id="s-${s.id}" onclick="toggle('s-${s.id}')">
<div class="stage-header">
<div class="stage-icon ${s.color}">${s.icon}</div>
<div>
<div class="stage-title">${s.title}</div>
<div class="stage-sub">${s.desc}</div>
</div>
<div class="stage-right">
<div class="stage-count">${s.agents.length} agents · ${s.outputs.length} outputs</div>
<div class="stage-arrow"></div>
</div>
</div>
<div class="stage-body">
<div class="agents-row">
${s.agents.map(a => `
<div class="agent-chip">
<div class="av">${a.e}</div>
<div class="info">
<div class="name">${a.n}</div>
<div class="prod">${a.p}</div>
</div>
</div>
`).join('')}
</div>
<div class="outputs">
${s.outputs.map(o => `<span class="output-tag">${o}</span>`).join('')}
</div>
<div class="risk-bar">
<span class="icon">⚠️</span>
<span class="text">${s.risk}</span>
</div>
</div>
</div>
`;
if(i < CHAIN.length - 1){
html += `<div class="flow-connector"><div class="flow-line"></div></div>`;
}
});
el.innerHTML = html;
// Auto-open first
document.getElementById('s-prospect').classList.add('open');
}
function toggle(id){
document.getElementById(id).classList.toggle('open');
}
render();
</script>
<!-- CARTO_REMOVED -->
<script>
/* V75 AVATAR UNIFIER — Meeting-rooms emoji style (Opus 19avr) */
(function() {
if (window.__WEVAL_AVATAR_V75) return;
window.__WEVAL_AVATAR_V75 = true;
const REG_URL = '/api/agent-avatars-v75.json';
const SVG_EP = '/api/agent-avatar-svg.php';
function emojiSVGUrl(name, emoji) {
return SVG_EP + '?n=' + encodeURIComponent(name) + '&e=' + encodeURIComponent(emoji);
}
fetch(REG_URL + '?t=' + Date.now()).then(r => r.json()).then(REG => {
function getAvatarUrl(name) {
const rec = REG[name];
if (!rec) return null;
if (typeof rec === 'object' && rec.svg) return rec.svg;
if (typeof rec === 'object' && rec.emoji) return emojiSVGUrl(name, rec.emoji);
return typeof rec === 'string' ? rec : null;
}
function findCI(key) {
const lower = key.toLowerCase();
for (const k of Object.keys(REG)) if (k.toLowerCase() === lower) return k;
return null;
}
function apply() {
document.querySelectorAll('img').forEach(img => {
const key = img.alt || img.dataset.agent || img.dataset.name || img.title || '';
if (!key) return;
let url = getAvatarUrl(key);
if (!url) { const alt = findCI(key); if (alt) url = getAvatarUrl(alt); }
if (url && img.src !== url && !img.src.endsWith(url)) {
img.src = url;
img.setAttribute('data-weval-v75', '1');
}
});
document.querySelectorAll('[data-agent]:not([data-weval-v75-applied])').forEach(el => {
const name = el.dataset.agent;
const url = getAvatarUrl(name);
if (!url) return;
const img = document.createElement('img');
img.src = url; img.alt = name; img.title = name;
img.className = 'v75-avatar';
img.style.cssText = 'width:32px;height:32px;border-radius:50%;object-fit:cover;vertical-align:middle;background:transparent';
el.setAttribute('data-weval-v75-applied', '1');
el.prepend(img);
});
}
apply();
setTimeout(apply, 400); setTimeout(apply, 1200); setTimeout(apply, 3000);
const mo = new MutationObserver(() => apply());
mo.observe(document.body, {childList: true, subtree: true});
setTimeout(() => mo.disconnect(), 20000);
console.log('[V75 AvatarUnifier] applied from', Object.keys(REG).length, 'agents');
}).catch(e => console.warn('[V75] fetch failed', e));
})();
</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 src="/api/a11y-auto-enhancer.js" defer></script>
</body>
</html>