Marcel0123 commited on
Commit
bcd5e16
·
verified ·
1 Parent(s): a52f4f2

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +62 -10
index.html CHANGED
@@ -29,12 +29,28 @@
29
  #scanFile{display:none}.site-label{font-size:11px;color:#a6bad8}#siteSelect{background:#132947;border:1px solid #325172;border-radius:8px;color:#eaf2ff;max-width:185px;padding:9px;font:inherit;font-size:12px}
30
  #siteSelect:disabled{opacity:.55}.import-state{color:#78e0c3;font-size:11px;max-width:210px;line-height:1.4}
31
  @media(max-width:760px){.import-panel{align-items:start}.import-intro{flex-basis:100%}.import-state{flex-basis:100%;max-width:none}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  </style></head>
33
  <body>
34
  <div class="app">
35
  <main class="main">
36
  <header><div><div class="eyebrow">REAKT / AI ANALYTICS PLATFORM</div><h1>Inloop <span>Intelligence</span> <em>ORCHESTRA</em></h1><p>Een intelligente blik op ontwikkeling, kwaliteit en herstelondersteunende inloop</p></div><div class="header-actions"><span class="pill"><i></i> DEMO MODE</span><span class="clock" id="clock"></span></div></header>
37
- <div class="topbar"><div><span class="section-kicker">CONTROL CENTER</span><h2>Multi-Agent Orchestration <span class="live-dot"></span></h2></div><div class="actions"><button id="resetBtn" class="ghost">↺ Reset</button><button id="startBtn" class="primary">▶ Start demo-analyse</button></div></div>
38
  <section class="import-panel panel" aria-label="Excel-proef met fictieve gegevens">
39
  <div class="import-intro"><span class="section-kicker">VOLGENDE STAP · EXCEL-PROEF</span><strong>Lokale scandata-test</strong><small>Alleen fictieve of volledig geanonimiseerde testbestanden · geen upload naar een server</small></div>
40
  <label class="import-file-label" for="scanFile"><span>▤</span> Kies testbestand (.xlsx)</label><input type="file" id="scanFile" accept=".xlsx" />
@@ -45,11 +61,11 @@
45
  <div class="mesh"></div><div class="conductor-wrap"><div class="conductor" id="conductor"><div class="conductor-glow"></div><div class="conductor-icon" aria-hidden="true"><svg class="brain-symbol" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.55" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5c-2.7-3.2-7.4-.9-7.1 2.4C2 9 2 13.6 5 15.2c-.7 4.4 4.9 6.8 7 2.6M12 5c2.7-3.2 7.4-.9 7.1 2.4 2.9 1.6 2.9 6.2-.1 7.8.7 4.4-4.9 6.8-7 2.6M12 5v13"/><path d="M6.6 10.1 9 12v3M17.4 10.1 15 12v3"/><circle cx="9" cy="15.5" r=".9" fill="currentColor" stroke="none"/><circle cx="15" cy="15.5" r=".9" fill="currentColor" stroke="none"/></svg></div><div><small>MASTER ORCHESTRATOR</small><strong>THE CONDUCTOR</strong><span id="conductorStatus">Gereed voor analyse</span></div><div class="conductor-indicator"></div></div></div>
46
  <svg class="connections" viewBox="0 0 1000 128" preserveAspectRatio="none" aria-hidden="true"><path class="stem" d="M500 0 V30 H100 V90 M500 30 H300 V90 M500 30 V90 M500 30 H700 V90 M500 30 H900 V90"/><path class="flowline" d="M500 0 V30 H100 V90 M500 30 H300 V90 M500 30 V90 M500 30 H700 V90 M500 30 H900 V90"/><g class="signal-layer" aria-hidden="true"></g></svg>
47
  <div class="agents">
48
- <article class="agent" id="agent-data" style="--accent:#34e6b3"><div class="agent-top"><span>01 / DATA</span><span class="status">STANDBY</span></div><div class="agent-symbol">▤</div><h3>Data Agent</h3><p>Structuur & kwaliteit</p><div class="mini-visual bars"><b></b><b></b><b></b><b></b><b></b><b></b><b></b></div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
49
- <article class="agent" id="agent-analysis" style="--accent:#ffcb62"><div class="agent-top"><span>02 / ANALYSE</span><span class="status">STANDBY</span></div><div class="agent-symbol">⌁</div><h3>Analysis Agent</h3><p>Trends & vergelijkingen</p><div class="mini-visual spark">▁ ▃ ▂ ▅ ▄ ▆ ▇</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
50
- <article class="agent" id="agent-insight" style="--accent:#51b9ff"><div class="agent-top"><span>03 / INZICHT</span><span class="status">STANDBY</span></div><div class="agent-symbol">✦</div><h3>Insight Agent</h3><p>Signalen & duiding</p><div class="mini-visual rings">◎ <span>◉</span> ◎</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
51
- <article class="agent" id="agent-verify" style="--accent:#b18aff"><div class="agent-top"><span>04 / CONTROLE</span><span class="status">STANDBY</span></div><div class="agent-symbol">⬡</div><h3>Verification Agent</h3><p>Schaduwberekeningen</p><div class="mini-visual checkicons">✓ &nbsp; ✓ &nbsp; ! &nbsp; ✓</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
52
- <article class="agent" id="agent-report" style="--accent:#ff9a65"><div class="agent-top"><span>05 / RAPPORT</span><span class="status">STANDBY</span></div><div class="agent-symbol">▧</div><h3>Report Agent</h3><p>Infographic & export</p><div class="mini-visual reportlines">▰▰▰▰▰<br>▰▰▰▰<br>▰▰▰</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
53
  </div>
54
  <div class="orchestra-footer"><span><i class="dot green"></i> Systeem gereed</span><span id="flowState">Wacht op startcommando</span><span>◌ <span id="completed">0</span> / 5 agenten voltooid</span></div>
55
  </section>
@@ -99,8 +115,44 @@ function signalFor(agent){
99
  circle.appendChild(motion);layer.appendChild(circle);
100
  }
101
  }
102
- function reset(){if(running)return;clearSignal();$('conductor').classList.remove('attention');completed=0;$('completed').textContent='0';$('conductorStatus').textContent='Gereed voor analyse';$('flowState').textContent='Wacht op startcommando';$('logStatus').textContent='Stand-by';$('logs').innerHTML='<div class="logitem muted">◌ &nbsp; Klik op ‘Start demo-analyse’ om de workflow te bekijken.</div>';$('orchestra-root');document.querySelector('.orchestra').classList.remove('running');$('conductor').classList.remove('running');ids.forEach(id=>{let e=$('agent-'+id);e.classList.remove('active','done');e.querySelector('.status').textContent='STANDBY';e.querySelector('.track i').style.width='0%';e.querySelector('.percent').textContent='0%'});}
103
- async function start(){if(importedData)return startImported();if(running)return;clearSignal();$('conductor').classList.remove('attention');running=true;$('startBtn').disabled=true;$('resetBtn').disabled=true;completed=0;ids.forEach(id=>{const e=$('agent-'+id);e.classList.remove('done','active');e.querySelector('.status').textContent='STANDBY';e.querySelector('.track i').style.width='0%';e.querySelector('.percent').textContent='0%'});$('logs').innerHTML='';$('completed').textContent='0';$('conductor').classList.add('running');document.querySelector('.orchestra').classList.add('running');$('conductorStatus').textContent='Workflow wordt aangestuurd';$('logStatus').textContent='Actief';log('Dirigent start de gesimuleerde workflow');try{const response=await Promise.resolve({ok:true,json:async()=>JSON.parse(document.getElementById('orchestra-demo-data').textContent)});if(!response.ok)throw Error('API reageert niet');demoData=await response.json();renderKPIs(demoData);renderChecks(demoData);drawChart(demoData);for(let i=0;i<demoData.steps.length;i++){const step=demoData.steps[i];const e=$('agent-'+step.agent);signalFor(step.agent);e.classList.add('active');e.querySelector('.status').textContent='ACTIEF';$('flowState').textContent=step.text;log('Start: '+e.querySelector('h3').textContent);for(let p=0;p<=100;p+=5){e.querySelector('.track i').style.width=p+'%';e.querySelector('.percent').textContent=p+'%';await sleep(36);}clearSignal();e.classList.remove('active');e.classList.add('done');if(step.agent==='verify' && demoData.checks.some(c=>c.ours!==c.shadow))$('conductor').classList.add('attention');e.querySelector('.status').textContent=step.agent==='verify'?'AFWIJKING':'GEREED';completed++;$('completed').textContent=String(completed);log(step.text);await sleep(280)}$('conductorStatus').textContent='Analyse voltooid · controle vereist';$('flowState').textContent='Concept gereed · NIET GEVALIDEERD';$('logStatus').textContent='Afgerond';log('Eindstatus: concept beschikbaar, niet vrijgegeven');}catch(e){log('FOUT: '+e.message);$('flowState').textContent='Verwerking mislukt';$('conductorStatus').textContent='Fout gedetecteerd';}finally{clearSignal();running=false;$('startBtn').disabled=false;$('resetBtn').disabled=false;$('conductor').classList.remove('running');document.querySelector('.orchestra').classList.remove('running')}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  function reply(question){const q=question.toLowerCase();if(!completed)return 'Start eerst de demo-analyse. Daarna kan ik vragen beantwoorden over de fictieve cijfers.';if(/valid|wouter|controle|betrouw|verschil|akkoord/.test(q))return 'In deze fictieve demo wijken de unieke bezoekers af: monitor 386 tegenover schaduwberekening 381, een verschil van 5. De oorzaak is niet vastgesteld. Daarom blijft de infographic NIET GEVALIDEERD.';if(/groei|stijg|locatie|soeda|rietdijk|vredehof|gouda/.test(q))return 'In de fictieve reeks juli–september stijgt Soeda van 350 naar 428 bezoeken (+22,3%). Rietdijk stijgt van 285 naar 334 (+17,2%), Vredehof van 245 naar 294 (+20,0%) en Gouda van 320 naar 365 (+14,1%). Soeda heeft de grootste relatieve groei.';if(/samenvat|rapport|infographic|management/.test(q))return 'Conceptmanagementsamenvatting (fictief): alle vier getoonde locaties laten in juli–september groei in bezoeken zien. Er is een afwijking van 5 unieke bezoekers bij de schaduwcontrole. Publicatie is niet toegestaan totdat dit verschil is onderzocht en beoordeeld.';if(/bezoek|uniek|instroom|kwartaal|cijfer/.test(q))return 'De fictieve KPI-kaarten tonen 12.480 bezoeken, 1.286 unieke bezoekers en 164 nieuwe instromers. Deze totaalcijfers zijn illustratief en vormen geen optelsom van de vier voorbeeldlocaties in de grafiek.';return 'Dit is een demo-chat zonder AI-API. Ik kan alleen vooraf gedefinieerde vragen over de fictieve locatiegroei, KPI’s, verificatie en managementsamenvatting beantwoorden.'}
105
  function addMessage(role,text){const e=document.createElement('div');e.className='message '+role;if(role==='assistant'){const s=document.createElement('small');s.textContent='INLOOP AI · DEMONSTRATIE';e.appendChild(s)}const p=document.createElement('p');p.textContent=text;e.appendChild(p);$('messages').appendChild(e);$('messages').scrollTop=$('messages').scrollHeight;}
106
  function ask(q){if(!q.trim())return;addMessage('user',q);addMessage('assistant',reply(q));}
@@ -244,7 +296,7 @@ async function startImported(){
244
  running=true;$('startBtn').disabled=true;$('resetBtn').disabled=true;completed=0;clearSignal();
245
  $('logs').innerHTML='';$('completed').textContent='0';$('conductor').classList.remove('attention');
246
  $('conductor').classList.add('running');document.querySelector('.orchestra').classList.add('running');
247
- $('conductorStatus').textContent='Lokale Excel-proef actief';$('logStatus').textContent='Actief';
248
  for(const id of ids){let el=$('agent-'+id);el.classList.remove('active','done');el.querySelector('.status').textContent='STANDBY';el.querySelector('.track i').style.width='0%';el.querySelector('.percent').textContent='0%'}
249
  const result=calculateImported($('siteSelect').value);importedData.last=result;
250
  const steps=[
@@ -256,7 +308,7 @@ async function startImported(){
256
  try{
257
  renderImported(result);
258
  for(const step of steps){const el=$('agent-'+step.agent);signalFor(step.agent);el.classList.add('active');el.querySelector('.status').textContent='ACTIEF';$('flowState').textContent=step.text;log('Start: '+el.querySelector('h3').textContent);
259
- for(let p=0;p<=100;p+=5){el.querySelector('.track i').style.width=p+'%';el.querySelector('.percent').textContent=p+'%';await sleep(30)}
260
  clearSignal();el.classList.remove('active');el.classList.add('done');el.querySelector('.status').textContent=step.agent==='verify'?'NIET EXTERN':'GEREED';completed++;$('completed').textContent=String(completed);log(step.text);await sleep(200)
261
  }
262
  $('conductor').classList.add('attention');$('flowState').textContent='Concept · NIET GEVALIDEERD';$('conductorStatus').textContent='Proefberekening voltooid';$('logStatus').textContent='Afgerond';
 
29
  #scanFile{display:none}.site-label{font-size:11px;color:#a6bad8}#siteSelect{background:#132947;border:1px solid #325172;border-radius:8px;color:#eaf2ff;max-width:185px;padding:9px;font:inherit;font-size:12px}
30
  #siteSelect:disabled{opacity:.55}.import-state{color:#78e0c3;font-size:11px;max-width:210px;line-height:1.4}
31
  @media(max-width:760px){.import-panel{align-items:start}.import-intro{flex-basis:100%}.import-state{flex-basis:100%;max-width:none}}
32
+
33
+ /* v0.5: agent-workflow-inzicht, zonder de goedgekeurde basisvormgeving te wijzigen */
34
+ .pace-label{display:flex;gap:7px;align-items:center;color:#a3b8d5;font-size:11px}
35
+ #paceSelect{max-width:175px;color:#e2f2ff;background:#102641;border:1px solid #36577d;border-radius:7px;padding:8px;font-size:11px}
36
+ .agent-steps{display:none;margin:11px 0 10px;min-height:116px;flex-direction:column;gap:5px}
37
+ .agent.has-steps .agent-steps{display:flex}
38
+ .agent.has-steps .mini-visual{display:none}
39
+ .agent-step{display:flex;gap:6px;align-items:flex-start;font-size:10px;line-height:1.35;color:#7288a7;min-height:17px}
40
+ .agent-step .step-mark{flex:none;display:inline-flex;align-items:center;justify-content:center;width:13px;height:13px;border:1px solid #526782;border-radius:50%;font-size:9px;color:#718cac;margin-top:1px}
41
+ .agent-step.complete{color:#d6efe8}.agent-step.complete .step-mark{border-color:#34e6b3;background:#0c624b;color:#fff}
42
+ .agent-step.current{color:#f1f7ff;font-weight:650}.agent-step.current .step-mark{border-color:var(--accent);color:var(--accent);box-shadow:0 0 7px var(--accent);animation:stepBlink 1s ease-in-out infinite}
43
+ .agent-step.skipped{color:#b6a9c9}.agent-step.skipped .step-mark{border-color:#b18aff;color:#b18aff}
44
+ @keyframes stepBlink{50%{opacity:.45}}
45
+ @media(max-width:1250px){.agent-step{font-size:9px}.pace-label{font-size:10px}}
46
+ @media(max-width:680px){.pace-label{flex-direction:column;align-items:start}.agent-steps{min-height:110px}}
47
+ @media(prefers-reduced-motion:reduce){.agent-step.current .step-mark{animation:none}}
48
  </style></head>
49
  <body>
50
  <div class="app">
51
  <main class="main">
52
  <header><div><div class="eyebrow">REAKT / AI ANALYTICS PLATFORM</div><h1>Inloop <span>Intelligence</span> <em>ORCHESTRA</em></h1><p>Een intelligente blik op ontwikkeling, kwaliteit en herstelondersteunende inloop</p></div><div class="header-actions"><span class="pill"><i></i> DEMO MODE</span><span class="clock" id="clock"></span></div></header>
53
+ <div class="topbar"><div><span class="section-kicker">CONTROL CENTER</span><h2>Multi-Agent Orchestration <span class="live-dot"></span></h2></div><div class="actions"><label class="pace-label" for="paceSelect">Weergave <select id="paceSelect" aria-label="Animatiesnelheid"><option value="presentation">Presentatie ± 30 sec</option><option value="fast">Snel ± 6 sec</option></select></label><button id="resetBtn" class="ghost">↺ Reset</button><button id="startBtn" class="primary">▶ Start demo-analyse</button></div></div>
54
  <section class="import-panel panel" aria-label="Excel-proef met fictieve gegevens">
55
  <div class="import-intro"><span class="section-kicker">VOLGENDE STAP · EXCEL-PROEF</span><strong>Lokale scandata-test</strong><small>Alleen fictieve of volledig geanonimiseerde testbestanden · geen upload naar een server</small></div>
56
  <label class="import-file-label" for="scanFile"><span>▤</span> Kies testbestand (.xlsx)</label><input type="file" id="scanFile" accept=".xlsx" />
 
61
  <div class="mesh"></div><div class="conductor-wrap"><div class="conductor" id="conductor"><div class="conductor-glow"></div><div class="conductor-icon" aria-hidden="true"><svg class="brain-symbol" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.55" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5c-2.7-3.2-7.4-.9-7.1 2.4C2 9 2 13.6 5 15.2c-.7 4.4 4.9 6.8 7 2.6M12 5c2.7-3.2 7.4-.9 7.1 2.4 2.9 1.6 2.9 6.2-.1 7.8.7 4.4-4.9 6.8-7 2.6M12 5v13"/><path d="M6.6 10.1 9 12v3M17.4 10.1 15 12v3"/><circle cx="9" cy="15.5" r=".9" fill="currentColor" stroke="none"/><circle cx="15" cy="15.5" r=".9" fill="currentColor" stroke="none"/></svg></div><div><small>MASTER ORCHESTRATOR</small><strong>THE CONDUCTOR</strong><span id="conductorStatus">Gereed voor analyse</span></div><div class="conductor-indicator"></div></div></div>
62
  <svg class="connections" viewBox="0 0 1000 128" preserveAspectRatio="none" aria-hidden="true"><path class="stem" d="M500 0 V30 H100 V90 M500 30 H300 V90 M500 30 V90 M500 30 H700 V90 M500 30 H900 V90"/><path class="flowline" d="M500 0 V30 H100 V90 M500 30 H300 V90 M500 30 V90 M500 30 H700 V90 M500 30 H900 V90"/><g class="signal-layer" aria-hidden="true"></g></svg>
63
  <div class="agents">
64
+ <article class="agent" id="agent-data" style="--accent:#34e6b3"><div class="agent-top"><span>01 / DATA</span><span class="status">STANDBY</span></div><div class="agent-symbol">▤</div><h3>Data Agent</h3><p>Structuur & kwaliteit</p><div class="agent-steps" aria-live="polite" aria-label="Werkstappen"></div><div class="mini-visual bars"><b></b><b></b><b></b><b></b><b></b><b></b><b></b></div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
65
+ <article class="agent" id="agent-analysis" style="--accent:#ffcb62"><div class="agent-top"><span>02 / ANALYSE</span><span class="status">STANDBY</span></div><div class="agent-symbol">⌁</div><h3>Analysis Agent</h3><p>Trends & vergelijkingen</p><div class="agent-steps" aria-live="polite" aria-label="Werkstappen"></div><div class="mini-visual spark">▁ ▃ ▂ ▅ ▄ ▆ ▇</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
66
+ <article class="agent" id="agent-insight" style="--accent:#51b9ff"><div class="agent-top"><span>03 / INZICHT</span><span class="status">STANDBY</span></div><div class="agent-symbol">✦</div><h3>Insight Agent</h3><p>Signalen & duiding</p><div class="agent-steps" aria-live="polite" aria-label="Werkstappen"></div><div class="mini-visual rings">◎ <span>◉</span> ◎</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
67
+ <article class="agent" id="agent-verify" style="--accent:#b18aff"><div class="agent-top"><span>04 / CONTROLE</span><span class="status">STANDBY</span></div><div class="agent-symbol">⬡</div><h3>Verification Agent</h3><p>Schaduwberekeningen</p><div class="agent-steps" aria-live="polite" aria-label="Werkstappen"></div><div class="mini-visual checkicons">✓ &nbsp; ✓ &nbsp; ! &nbsp; ✓</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
68
+ <article class="agent" id="agent-report" style="--accent:#ff9a65"><div class="agent-top"><span>05 / RAPPORT</span><span class="status">STANDBY</span></div><div class="agent-symbol">▧</div><h3>Report Agent</h3><p>Infographic & export</p><div class="agent-steps" aria-live="polite" aria-label="Werkstappen"></div><div class="mini-visual reportlines">▰▰▰▰▰<br>▰▰▰▰<br>▰▰▰</div><div class="agent-bottom"><div class="track"><i></i></div><span class="percent">0%</span></div></article>
69
  </div>
70
  <div class="orchestra-footer"><span><i class="dot green"></i> Systeem gereed</span><span id="flowState">Wacht op startcommando</span><span>◌ <span id="completed">0</span> / 5 agenten voltooid</span></div>
71
  </section>
 
115
  circle.appendChild(motion);layer.appendChild(circle);
116
  }
117
  }
118
+ function reset(){if(running)return;clearStages();clearSignal();$('conductor').classList.remove('attention');completed=0;$('completed').textContent='0';$('conductorStatus').textContent='Gereed voor analyse';$('flowState').textContent='Wacht op startcommando';$('logStatus').textContent='Stand-by';$('logs').innerHTML='<div class="logitem muted">◌ &nbsp; Klik op ‘Start demo-analyse’ om de workflow te bekijken.</div>';$('orchestra-root');document.querySelector('.orchestra').classList.remove('running');$('conductor').classList.remove('running');ids.forEach(id=>{let e=$('agent-'+id);e.classList.remove('active','done');e.querySelector('.status').textContent='STANDBY';e.querySelector('.track i').style.width='0%';e.querySelector('.percent').textContent='0%'});}
119
+
120
+ // v0.5: voortgang is een presentatielaag, geen indicatie van de rekentijd.
121
+ function paceDelay(){return $('paceSelect').value==='fast'?170:1050;}
122
+ function stepDescriptions(agent, result, fake){
123
+ const n=v=>Number(v).toLocaleString('nl-NL');
124
+ const sites=result?.sites??0, rows=result?.rows??0, repeat=result?.duplicates??0;
125
+ const provisional=result?.visits??0, unique=result?.unique??0;
126
+ if(agent==='data')return fake?['Demobron geladen','4 voorbeeldlocaties','Fictieve scanregels','Democontrole afgerond','Overdracht aan analyse']:[
127
+ 'Excel-bestand ingelezen',`${sites} locaties herkend`,`${n(rows)} scanregels bekeken`,`${n(repeat)} herhaalde scans gevonden`,'Overdracht aan Analysis Agent'];
128
+ if(agent==='analysis')return fake?['Voorbeeld-KPI’s geladen','Locaties vergeleken','Trends weergegeven','Groei samengevat','Overdracht aan inzicht']:[
129
+ 'Dubbele scans uitgesloten',`${n(provisional)} bezoeken voorlopig`,`${n(unique)} unieke cliëntnummers`,'Maandtrends weergegeven','Overdracht aan Insight Agent'];
130
+ if(agent==='insight')return fake?['Voorbeeldtrend gelezen','Locatieverschillen bekeken','Fictieve inzichten verzameld','Conceptduiding opgesteld','Overdracht aan verificatie']:[
131
+ 'Maandgegevens beschikbaar','Locaties in grafiek gezet','Signalen zonder causaliteit','AI-duiding niet aangesloten','Overdracht aan controle'];
132
+ if(agent==='verify')return fake?['Demovergelijking geopend','5 indicatoren bekeken','1 fictieve afwijking','Rapport niet gevalideerd','Overdracht met waarschuwing']:[
133
+ 'Interne telling beschikbaar','Dubbeltellingen gemarkeerd','Businesscontroller: geen bestand','Externe controle overgeslagen','Status: niet gevalideerd'];
134
+ return fake?['Concept gestart','Voorbeeldcijfers verwerkt','Illustratie bijgewerkt','Niet gevalideerd gemarkeerd','Concept gereed']:[
135
+ 'Concept gestart','KPI-preview bijgewerkt','Instroom nog niet bepaald','Niet gevalideerd gemarkeerd','Concept gereed'];
136
+ }
137
+ function showStages(agent,steps){
138
+ const box=$('agent-'+agent);box.classList.add('has-steps');const wrap=box.querySelector('.agent-steps');wrap.replaceChildren();
139
+ steps.forEach((str,i)=>{const d=document.createElement('div');d.className='agent-step';d.innerHTML='<span class="step-mark">○</span><span class="step-label"></span>';d.querySelector('.step-label').textContent=str;wrap.appendChild(d)});
140
+ }
141
+ async function animateStages(agent,steps){
142
+ const el=$('agent-'+agent),items=[...el.querySelectorAll('.agent-step')];
143
+ const delay=paceDelay();
144
+ for(let i=0;i<items.length;i++){
145
+ items[i].classList.add('current');items[i].querySelector('.step-mark').textContent='◌';
146
+ $('flowState').textContent=steps[i];
147
+ await sleep(delay);
148
+ items[i].classList.remove('current');items[i].classList.add('complete');items[i].querySelector('.step-mark').textContent='✓';
149
+ el.querySelector('.track i').style.width=Math.round((i+1)*100/items.length)+'%';
150
+ el.querySelector('.percent').textContent=Math.round((i+1)*100/items.length)+'%';
151
+ }
152
+ }
153
+ function clearStages(){ids.forEach(id=>{const el=$('agent-'+id);el.classList.remove('has-steps');el.querySelector('.agent-steps').replaceChildren()})}
154
+
155
+ async function start(){if(importedData)return startImported();if(running)return;clearStages();clearSignal();$('conductor').classList.remove('attention');running=true;$('startBtn').disabled=true;$('resetBtn').disabled=true;completed=0;ids.forEach(id=>{const e=$('agent-'+id);e.classList.remove('done','active');e.querySelector('.status').textContent='STANDBY';e.querySelector('.track i').style.width='0%';e.querySelector('.percent').textContent='0%'});$('logs').innerHTML='';$('completed').textContent='0';$('conductor').classList.add('running');document.querySelector('.orchestra').classList.add('running');$('conductorStatus').textContent='Workflow wordt aangestuurd';$('logStatus').textContent='Actief';log('Dirigent toont de gesimuleerde workflow stap voor stap');try{const response=await Promise.resolve({ok:true,json:async()=>JSON.parse(document.getElementById('orchestra-demo-data').textContent)});if(!response.ok)throw Error('API reageert niet');demoData=await response.json();renderKPIs(demoData);renderChecks(demoData);drawChart(demoData);for(let i=0;i<demoData.steps.length;i++){const step=demoData.steps[i];const e=$('agent-'+step.agent);signalFor(step.agent);e.classList.add('active');e.querySelector('.status').textContent='ACTIEF';$('flowState').textContent=step.text;log('Start: '+e.querySelector('h3').textContent);const stageLabels=stepDescriptions(step.agent,null,true);showStages(step.agent,stageLabels);await animateStages(step.agent,stageLabels);clearSignal();e.classList.remove('active');e.classList.add('done');if(step.agent==='verify' && demoData.checks.some(c=>c.ours!==c.shadow))$('conductor').classList.add('attention');e.querySelector('.status').textContent=step.agent==='verify'?'AFWIJKING':'GEREED';completed++;$('completed').textContent=String(completed);log(step.text);await sleep(280)}$('conductorStatus').textContent='Analyse voltooid · controle vereist';$('flowState').textContent='Concept gereed · NIET GEVALIDEERD';$('logStatus').textContent='Afgerond';log('Eindstatus: concept beschikbaar, niet vrijgegeven');}catch(e){log('FOUT: '+e.message);$('flowState').textContent='Verwerking mislukt';$('conductorStatus').textContent='Fout gedetecteerd';}finally{clearSignal();running=false;$('startBtn').disabled=false;$('resetBtn').disabled=false;$('conductor').classList.remove('running');document.querySelector('.orchestra').classList.remove('running')}}
156
  function reply(question){const q=question.toLowerCase();if(!completed)return 'Start eerst de demo-analyse. Daarna kan ik vragen beantwoorden over de fictieve cijfers.';if(/valid|wouter|controle|betrouw|verschil|akkoord/.test(q))return 'In deze fictieve demo wijken de unieke bezoekers af: monitor 386 tegenover schaduwberekening 381, een verschil van 5. De oorzaak is niet vastgesteld. Daarom blijft de infographic NIET GEVALIDEERD.';if(/groei|stijg|locatie|soeda|rietdijk|vredehof|gouda/.test(q))return 'In de fictieve reeks juli–september stijgt Soeda van 350 naar 428 bezoeken (+22,3%). Rietdijk stijgt van 285 naar 334 (+17,2%), Vredehof van 245 naar 294 (+20,0%) en Gouda van 320 naar 365 (+14,1%). Soeda heeft de grootste relatieve groei.';if(/samenvat|rapport|infographic|management/.test(q))return 'Conceptmanagementsamenvatting (fictief): alle vier getoonde locaties laten in juli–september groei in bezoeken zien. Er is een afwijking van 5 unieke bezoekers bij de schaduwcontrole. Publicatie is niet toegestaan totdat dit verschil is onderzocht en beoordeeld.';if(/bezoek|uniek|instroom|kwartaal|cijfer/.test(q))return 'De fictieve KPI-kaarten tonen 12.480 bezoeken, 1.286 unieke bezoekers en 164 nieuwe instromers. Deze totaalcijfers zijn illustratief en vormen geen optelsom van de vier voorbeeldlocaties in de grafiek.';return 'Dit is een demo-chat zonder AI-API. Ik kan alleen vooraf gedefinieerde vragen over de fictieve locatiegroei, KPI’s, verificatie en managementsamenvatting beantwoorden.'}
157
  function addMessage(role,text){const e=document.createElement('div');e.className='message '+role;if(role==='assistant'){const s=document.createElement('small');s.textContent='INLOOP AI · DEMONSTRATIE';e.appendChild(s)}const p=document.createElement('p');p.textContent=text;e.appendChild(p);$('messages').appendChild(e);$('messages').scrollTop=$('messages').scrollHeight;}
158
  function ask(q){if(!q.trim())return;addMessage('user',q);addMessage('assistant',reply(q));}
 
296
  running=true;$('startBtn').disabled=true;$('resetBtn').disabled=true;completed=0;clearSignal();
297
  $('logs').innerHTML='';$('completed').textContent='0';$('conductor').classList.remove('attention');
298
  $('conductor').classList.add('running');document.querySelector('.orchestra').classList.add('running');
299
+ $('conductorStatus').textContent='Excel-berekeningen worden gepresenteerd';$('logStatus').textContent='Actief';
300
  for(const id of ids){let el=$('agent-'+id);el.classList.remove('active','done');el.querySelector('.status').textContent='STANDBY';el.querySelector('.track i').style.width='0%';el.querySelector('.percent').textContent='0%'}
301
  const result=calculateImported($('siteSelect').value);importedData.last=result;
302
  const steps=[
 
308
  try{
309
  renderImported(result);
310
  for(const step of steps){const el=$('agent-'+step.agent);signalFor(step.agent);el.classList.add('active');el.querySelector('.status').textContent='ACTIEF';$('flowState').textContent=step.text;log('Start: '+el.querySelector('h3').textContent);
311
+ const stageLabels=stepDescriptions(step.agent,{...result,sites:importedData.sites.length},false);showStages(step.agent,stageLabels);await animateStages(step.agent,stageLabels);
312
  clearSignal();el.classList.remove('active');el.classList.add('done');el.querySelector('.status').textContent=step.agent==='verify'?'NIET EXTERN':'GEREED';completed++;$('completed').textContent=String(completed);log(step.text);await sleep(200)
313
  }
314
  $('conductor').classList.add('attention');$('flowState').textContent='Concept · NIET GEVALIDEERD';$('conductorStatus').textContent='Proefberekening voltooid';$('logStatus').textContent='Afgerond';