lakehouse/mcp-server/search.html
root be7436b6f0 Diverse scenario engine: 15 weighted staffing situations replace crisis-every-refresh
Simulation now uses weighted random selection across 4 priority tiers:
- Urgent (walkoff, quarantine, no-show), High (new client, cert expiry, expansion),
  Medium (recurring, seasonal, medical leave, cross-train), Low (future, exploratory)
- Color-coded scenario banners on ALL contracts, not just urgent
- Each scenario carries context (note) + recommended action

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 16:41:00 -05:00

509 lines
32 KiB
HTML

<!DOCTYPE html>
<html><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Staffing Co-Pilot</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,system-ui,sans-serif;background:#0b0f19;color:#c9d1d9;font-size:14px;line-height:1.5}
.bar{background:#161b22;padding:12px 20px;border-bottom:1px solid #21262d;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px}
.bar h1{font-size:16px;font-weight:600;color:#f0f6fc}.bar .rt{font-size:11px;color:#8b949e}
.content{max-width:900px;margin:0 auto;padding:20px 16px}
/* Insight cards — the "how did it know that?" moments */
.insight{background:#161b22;border:1px solid #21262d;border-radius:12px;padding:20px;margin-bottom:16px}
.insight .label{font-size:10px;color:#8b949e;text-transform:uppercase;letter-spacing:1.5px;margin-bottom:6px}
.insight .headline{font-size:18px;font-weight:700;color:#f0f6fc;margin-bottom:4px}
.insight .sub{font-size:13px;color:#8b949e;margin-bottom:14px}
.insight.urgent{border-left:3px solid #f85149}
.insight.opportunity{border-left:3px solid #3fb950}
.insight.warning{border-left:3px solid #d29922}
.insight.info{border-left:3px solid #58a6ff}
/* Worker in insight — clean, scannable */
.iworker{display:flex;align-items:center;gap:12px;padding:10px;background:#0d1117;border-radius:8px;margin-bottom:6px}
.iworker .av{width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px;color:#f0f6fc;flex-shrink:0}
.iworker .info{flex:1}
.iworker .nm{font-weight:600;color:#f0f6fc;font-size:14px}
.iworker .detail{color:#8b949e;font-size:12px}
.iworker .why{color:#58a6ff;font-size:11px;margin-top:2px;font-style:italic}
.iworker .acts{display:flex;gap:4px}
.ibtn{padding:6px 14px;border-radius:6px;font-size:11px;cursor:pointer;border:none;font-weight:600}
.ibtn.call{background:#1f3d68;color:#58a6ff}
.ibtn.sms{background:#0d261a;color:#3fb950}
/* Stats strip */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:20px}
.stat{background:#161b22;border:1px solid #21262d;border-radius:10px;padding:16px;text-align:center}
.stat .n{font-size:28px;font-weight:800;color:#f0f6fc}.stat .l{font-size:10px;color:#8b949e;text-transform:uppercase;margin-top:2px}
/* Search */
.sa{margin-top:20px;background:#161b22;border:1px solid #21262d;border-radius:10px;overflow:hidden}
.sa summary{cursor:pointer;color:#8b949e;font-size:13px;list-style:none;padding:14px 16px}
.sa summary::-webkit-details-marker{display:none}
.sa .inner{padding:0 16px 16px}
.sa input[type=text]{width:100%;padding:12px;background:#0b0f19;border:1px solid #21262d;border-radius:8px;color:#f0f6fc;font-size:14px;outline:none;margin-bottom:8px}
.sa input:focus{border-color:#58a6ff}
.srow{display:flex;gap:8px;margin-bottom:10px}
.sa select{flex:1;padding:8px;background:#0b0f19;border:1px solid #21262d;border-radius:6px;color:#c9d1d9;font-size:12px}
.sbtn{width:100%;padding:10px;background:#7c3aed;border:none;border-radius:8px;color:#fff;font-size:13px;font-weight:600;cursor:pointer}
.sbtn:hover{background:#6d28d9}
#sresults{margin-top:12px}
.ft{text-align:center;padding:16px;color:#484f58;font-size:11px;margin-top:20px}.ft a{color:#58a6ff;text-decoration:none}
.ld{color:#484f58;text-align:center;padding:20px}
@media(max-width:768px){.stats{grid-template-columns:repeat(2,1fr)}.iworker{flex-direction:column;text-align:center}.iworker .acts{justify-content:center}}
</style></head><body>
<div class="bar"><h1>Staffing Co-Pilot</h1><div class="rt" id="status">Loading your day...</div></div>
<div class="content">
<div id="main"><div class="ld">Analyzing your contracts and workers...</div></div>
<details class="sa"><summary>Search all 500,000 workers</summary><div class="inner">
<input type="text" id="sq" placeholder="Describe who you need — the AI understands plain English" onkeydown="if(event.key==='Enter')doSearch()">
<div class="srow"><select id="sst"><option value="">Any State</option><option>IL</option><option>IN</option><option>OH</option><option>MO</option><option>TN</option><option>KY</option><option>WI</option><option>MI</option></select>
<select id="srl"><option value="">Any Role</option><option>Forklift Operator</option><option>Machine Operator</option><option>Assembler</option><option>Loader</option><option>Quality Tech</option><option>Welder</option></select></div>
<button class="sbtn" onclick="doSearch()">Find Workers</button><div id="sresults"></div></div></details>
<div class="ft"><a href="proof">How this works</a></div>
</div>
<script>
var P=location.pathname.indexOf('/lakehouse')>=0?'/lakehouse':'';
var A=location.origin+P;
var AC=['#1a2744','#1a3a2a','#2a1a3a','#3a2a1a','#1a3a3a','#2a2a1a'];
window.addEventListener('load',loadDay);
function api(path,body){
return fetch(A+path,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}).then(function(r){return r.json()})
}
function loadDay(){
Promise.all([
api('/simulation/run',{}),
api('/sql',{sql:"SELECT role, COUNT(*) total, SUM(CASE WHEN CAST(reliability AS DOUBLE)>0.8 THEN 1 ELSE 0 END) reliable FROM workers_500k GROUP BY role ORDER BY total DESC LIMIT 5"}),
api('/sql',{sql:"SELECT name, role, city, state, ROUND(CAST(reliability AS DOUBLE),2) rel, certifications FROM workers_500k WHERE CAST(reliability AS DOUBLE)>0.95 ORDER BY CAST(reliability AS DOUBLE) DESC LIMIT 5"}),
api('/sql',{sql:"SELECT state, COUNT(*) cnt, SUM(CASE WHEN CAST(reliability AS DOUBLE)>0.8 THEN 1 ELSE 0 END) good FROM workers_500k GROUP BY state ORDER BY cnt DESC LIMIT 5"})
]).then(function(results){
var sim=results[0], roles=results[1], topWorkers=results[2], coverage=results[3];
var today=sim.days?sim.days[0]:null;
var sum=sim.summary||{};
document.getElementById('status').textContent=sum.total_filled+'/'+sum.total_needed+' positions filled across '+sum.total_contracts+' contracts';
renderMain(today,sum,roles,topWorkers,coverage);
}).catch(function(e){
document.getElementById('main').textContent='Error loading: '+e.message;
});
}
function renderMain(today,sum,roles,topWorkers,coverage){
var el=document.getElementById('main');
el.textContent='';
// Stats
var stats=document.createElement('div');stats.className='stats';
addStat(stats,sum.total_contracts||0,'Contracts Today');
addStat(stats,sum.total_filled||0,'Positions Filled');
addStat(stats,sum.emergencies||0,'Urgent');
addStat(stats,'500K','Workers in System');
el.appendChild(stats);
// INSIGHT 1: Urgent pipeline — step-by-step workflow
if(today&&today.contracts){
var urgent=today.contracts.filter(function(c){return c.priority==='urgent'});
var needsWork=today.contracts.filter(function(c){return c.priority!=='urgent'&&c.filled<c.headcount});
var filled=today.contracts.filter(function(c){return c.filled>=c.headcount});
if(urgent.length){
var ins=makeInsight('urgent','Urgent Pipeline',
urgent.length+' emergency contract'+(urgent.length>1?'s':'') +' — the system found workers, here\'s your action plan',
null);
// Pipeline steps explanation
var steps=document.createElement('div');
steps.style.cssText='display:flex;gap:4px;margin-bottom:16px;flex-wrap:wrap';
var stepData=[
['1','Review','Check the pre-matched workers below','#f85149'],
['2','Call first choice','Highest-rated worker gets the first call','#d29922'],
['3','Confirm or replace','If they can\'t make it, the backup is ready','#58a6ff'],
['4','Send details','Client address, start time, dress code','#3fb950']
];
stepData.forEach(function(s){
var sd=document.createElement('div');
sd.style.cssText='flex:1;min-width:120px;background:#0d1117;border-radius:8px;padding:10px;border-top:2px solid '+s[3];
var num=document.createElement('div');num.style.cssText='font-size:18px;font-weight:800;color:'+s[3];num.textContent='Step '+s[0];
var title=document.createElement('div');title.style.cssText='font-size:12px;font-weight:600;color:#f0f6fc;margin-top:2px';title.textContent=s[1];
var desc=document.createElement('div');desc.style.cssText='font-size:10px;color:#8b949e;margin-top:2px';desc.textContent=s[2];
sd.appendChild(num);sd.appendChild(title);sd.appendChild(desc);steps.appendChild(sd);
});
ins.appendChild(steps);
urgent.forEach(function(c){
addContractInsight(ins,c,true);
});
el.appendChild(ins);
}
// Non-urgent that need work
if(needsWork.length){
var ins1b=makeInsight('warning','In Progress',
needsWork.length+' contract'+(needsWork.length>1?'s':'')+' still filling — workers matched, awaiting confirmation',
'These are standard priority. Workers are ranked by fit — start from the top.');
needsWork.forEach(function(c){
addContractInsight(ins1b,c,false);
});
el.appendChild(ins1b);
}
if(filled.length){
var ins2=makeInsight('opportunity','Ready to Go',
filled.length+' contract'+(filled.length>1?'s':'')+' fully staffed — review and send shift details',
'All positions matched. The workers listed below are the system\'s best picks based on role, location, reliability, and certifications. Tap Call or SMS to confirm.');
filled.forEach(function(c){
addContractInsight(ins2,c,false);
});
el.appendChild(ins2);
}
}
// INSIGHT 2: Top available workers they should know about
if(topWorkers&&topWorkers.rows&&topWorkers.rows.length){
var ins3=makeInsight('info','Your Strongest Available Workers',
'These workers have 95%+ reliability — they rarely no-show and clients request them back',
'Based on placement history and performance tracking. Consider these first for high-priority contracts.');
topWorkers.rows.forEach(function(w,i){
var wd={nm:w.name,role:w.role,loc:w.city+', '+w.state,skills:[],
certs:(w.certifications||'').split(',').filter(function(c){return c.trim()&&c.trim()!=='none'}),
rel:w.rel,avail:0,arch:'',hasM:true};
addWorkerInsight(ins3,w.name,w.role+' · '+w.city+', '+w.state,
'Reliability: '+w.rel*100+'% · Certs: '+(w.certifications||'none'),i,null,wd);
});
el.appendChild(ins3);
}
// INSIGHT 3: Coverage warning
if(coverage&&coverage.rows){
var thin=coverage.rows.filter(function(r){return r.good/r.cnt<0.45});
if(thin.length){
var ins4=makeInsight('warning','Bench Strength Alert',
'Some states have fewer reliable workers than usual',
'The system monitors your worker pool and flags when coverage drops. Consider recruiting in these areas.');
thin.forEach(function(r){
var pct=Math.round(r.good/r.cnt*100);
var d=document.createElement('div');d.style.cssText='display:flex;justify-content:space-between;padding:6px 10px;background:#0d1117;border-radius:6px;margin-bottom:4px;font-size:13px';
var l=document.createElement('span');l.textContent=r.state+' — '+r.cnt.toLocaleString()+' workers';l.style.color='#f0f6fc';
var v=document.createElement('span');v.textContent=pct+'% reliable';v.style.color=pct<40?'#f85149':'#d29922';
d.appendChild(l);d.appendChild(v);ins4.appendChild(d);
});
el.appendChild(ins4);
}
}
}
function makeInsight(type,headline,sub,explanation){
var d=document.createElement('div');d.className='insight '+type;
var lb=document.createElement('div');lb.className='label';
lb.textContent=type==='urgent'?'ACTION NEEDED':type==='opportunity'?'READY':type==='warning'?'HEADS UP':'INSIGHT';
var h=document.createElement('div');h.className='headline';h.textContent=headline;
var s=document.createElement('div');s.className='sub';s.textContent=sub;
d.appendChild(lb);d.appendChild(h);d.appendChild(s);
if(explanation){var ex=document.createElement('div');ex.style.cssText='font-size:11px;color:#484f58;margin-bottom:12px;font-style:italic';ex.textContent=explanation;d.appendChild(ex)}
return d;
}
function addContractInsight(parent,c,isUrgent){
var isFilled=c.filled>=c.headcount;
var cd=document.createElement('div');cd.style.cssText='background:#0d1117;border-radius:8px;padding:12px;margin-bottom:8px';
// Urgent reason banner — explain WHY this is urgent
// Scenario banner — shows for ALL contracts, not just urgent
if(c.notes||c.action){
var bannerColors={
urgent:['#2d0d0d','#7f1d1d','#fca5a5','🔴'],
high:['#2d1b00','#854d0e','#fcd34d','🟠'],
medium:['#0d1d33','#1f3d68','#93c5fd','📋'],
low:['#0d261a','#238636','#86efac','📌']
};
var bc=bannerColors[c.priority]||bannerColors.medium;
var banner=document.createElement('div');
banner.style.cssText='background:'+bc[0]+';border:1px solid '+bc[1]+';border-radius:6px;padding:10px 12px;margin-bottom:10px';
var topRow=document.createElement('div');topRow.style.cssText='display:flex;align-items:flex-start;gap:8px';
var icon=document.createElement('span');icon.style.cssText='font-size:14px;flex-shrink:0';icon.textContent=bc[3];
var bannerText=document.createElement('div');
var reasonLine=document.createElement('div');reasonLine.style.cssText='color:'+bc[2]+';font-size:12px;font-weight:600';
reasonLine.textContent=c.notes||'';
bannerText.appendChild(reasonLine);
if(c.action){
var actionLine=document.createElement('div');actionLine.style.cssText='color:#8b949e;font-size:11px;margin-top:2px';
actionLine.textContent=c.action;
bannerText.appendChild(actionLine);
}
var unfilled=c.headcount-c.filled;
if(unfilled>0){
var gapLine=document.createElement('div');gapLine.style.cssText='color:'+bc[2]+';font-size:11px;margin-top:4px;font-weight:500';
gapLine.textContent='→ Need '+unfilled+' more worker'+(unfilled>1?'s':'')+' — see matches below';
bannerText.appendChild(gapLine);
}
topRow.appendChild(icon);topRow.appendChild(bannerText);banner.appendChild(topRow);
cd.appendChild(banner);
}
var hdr=document.createElement('div');hdr.style.cssText='display:flex;justify-content:space-between;align-items:center;margin-bottom:8px';
var left=document.createElement('div');
var cl=document.createElement('span');cl.style.cssText='font-weight:700;color:#f0f6fc;font-size:15px';cl.textContent=c.client;
var nd=document.createElement('span');nd.style.cssText='color:#8b949e;font-size:12px;margin-left:8px';
nd.textContent=c.role+' x'+c.headcount+' · '+(c.city||c.state)+' · '+c.start;
left.appendChild(cl);left.appendChild(nd);
var right=document.createElement('span');right.style.cssText='font-size:12px;font-weight:700;color:'+(isFilled?'#3fb950':'#d29922');
right.textContent=c.filled+'/'+c.headcount+(isFilled?' ✓':' filling');
hdr.appendChild(left);hdr.appendChild(right);cd.appendChild(hdr);
if(c.matches&&c.matches.length){
var showCount=Math.min(c.headcount,isUrgent?c.headcount+2:3);
c.matches.slice(0,showCount).forEach(function(m,i){
var w=pw(m.chunk_text||'');if(!w.nm)w.nm=m.name||m.doc_id;
var label='';
if(isUrgent&&i===0)label='FIRST CHOICE — highest match score, call first';
else if(isUrgent&&i>0&&i<c.headcount)label='';
else if(isUrgent&&i>=c.headcount)label='BACKUP — if someone above can\'t make it';
addWorkerInsight(cd,w.nm,
[w.role,w.loc].filter(Boolean).join(' · '),
label||buildWhyText(w,c),i,
isUrgent&&i===0?'#f85149':isUrgent&&i>=c.headcount?'#484f58':null,
w);
});
var remaining=c.matches.length-showCount;
if(remaining>0){
var more=document.createElement('div');more.style.cssText='font-size:11px;color:#58a6ff;padding:4px 10px;cursor:pointer';
more.textContent='+ '+remaining+' more available workers';
cd.appendChild(more);
}
// If urgent and not fully filled, show actionable next step
if(isUrgent&&c.filled<c.headcount){
var gap=c.headcount-c.filled;
var action=document.createElement('div');
action.style.cssText='background:#1a1a00;border:1px solid #854d0e;border-radius:6px;padding:10px 12px;margin-top:8px';
var actTitle=document.createElement('div');actTitle.style.cssText='color:#fcd34d;font-size:12px;font-weight:600';
actTitle.textContent='Still need '+gap+' — here\'s what to do:';
var actSteps=document.createElement('div');actSteps.style.cssText='color:#8b949e;font-size:11px;margin-top:4px;line-height:1.7';
actSteps.textContent='1. Call the workers above — confirm availability for '+c.start+
'\n2. If someone declines, the system has '+remaining+' backup'+(remaining!==1?'s':'')+' ready'+
'\n3. Expand search: try nearby states or broaden the role filter';
action.appendChild(actTitle);action.appendChild(actSteps);cd.appendChild(action);
}
}
parent.appendChild(cd);
}
function buildWhyText(w,c){
// This is the "how did it know?" — explain WHY this worker was matched
var reasons=[];
if(w.loc&&c.city&&w.loc.toLowerCase().indexOf(c.city.toLowerCase())>=0)reasons.push('Same city as job site');
else if(w.loc&&c.state&&w.loc.indexOf(c.state)>=0)reasons.push('In-state');
if(w.rel>=0.9)reasons.push('Top reliability ('+Math.round(w.rel*100)+'%)');
else if(w.rel>=0.8)reasons.push('Reliable ('+Math.round(w.rel*100)+'%)');
if(w.certs.length)reasons.push('Certified: '+w.certs.slice(0,2).join(', '));
if(w.skills.length){
var relevant=w.skills.filter(function(s){return c.role&&c.role.toLowerCase().indexOf(s.toLowerCase())>=0||s.toLowerCase().indexOf('forklift')>=0||s.toLowerCase().indexOf('cnc')>=0});
if(relevant.length)reasons.push('Has: '+relevant.join(', '));
}
if(w.arch==='reliable'||w.arch==='leader')reasons.push(w.arch+' profile');
return reasons.length?reasons.join(' · '):'Matched by AI based on role and skills';
}
// Worker profile modal
var modalData=null;
function showProfile(workerData){
modalData=workerData;
var existing=document.getElementById('profile-modal');
if(existing)existing.remove();
var overlay=document.createElement('div');overlay.id='profile-modal';
overlay.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:1000;display:flex;justify-content:center;align-items:flex-start;padding:20px 16px;overflow-y:auto;-webkit-overflow-scrolling:touch';
document.body.style.overflow='hidden';
overlay.onclick=function(e){if(e.target===overlay){overlay.remove();document.body.style.overflow=''}};
var modal=document.createElement('div');
modal.style.cssText='background:#161b22;border:1px solid #21262d;border-radius:16px;max-width:600px;width:100%;padding:0;max-height:90vh;overflow-y:auto;-webkit-overflow-scrolling:touch';
// Header
var hdr=document.createElement('div');
hdr.style.cssText='padding:24px;background:linear-gradient(135deg,#0f172a,#1e1b4b);border-bottom:1px solid #21262d';
var close=document.createElement('div');close.style.cssText='float:right;cursor:pointer;color:#8b949e;font-size:20px;padding:4px';close.textContent='✕';
close.onclick=function(){overlay.remove();document.body.style.overflow=''};hdr.appendChild(close);
var bigAv=document.createElement('div');
bigAv.style.cssText='width:60px;height:60px;border-radius:14px;display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:800;color:#f0f6fc;background:#1a2744;margin-bottom:12px';
bigAv.textContent=(workerData.nm||'?').split(' ').map(function(n){return(n[0]||'').toUpperCase()}).join('').substring(0,2);
hdr.appendChild(bigAv);
var name=document.createElement('div');name.style.cssText='font-size:22px;font-weight:700;color:#f0f6fc';name.textContent=workerData.nm||'Unknown';hdr.appendChild(name);
if(workerData.role||workerData.loc){var sub=document.createElement('div');sub.style.cssText='font-size:14px;color:#8b949e;margin-top:4px';sub.textContent=[workerData.role,workerData.loc].filter(Boolean).join(' · ');hdr.appendChild(sub)}
modal.appendChild(hdr);
var body=document.createElement('div');body.style.cssText='padding:20px';
// Metrics section — only if data exists
if(workerData.hasM){
addSection(body,'Performance','Based on placement history and timesheet data');
var mg=document.createElement('div');mg.style.cssText='display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px';
addBigMeter(mg,'Reliability',workerData.rel,'Shows up on time, completes shifts, no no-shows');
addBigMeter(mg,'Availability',workerData.avail,'Currently open for new placements');
body.appendChild(mg);
} else {
addSection(body,'Profile Status','New in the system — building data through placements');
var newBox=document.createElement('div');
newBox.style.cssText='background:#0d1117;border:1px solid #21262d;border-radius:8px;padding:16px;margin-bottom:20px';
var stages=[
['You are here','Name and contact info on file','#58a6ff',true],
['After first placement','Role and location confirmed','#484f58',false],
['After 3 placements','Reliability score starts building','#484f58',false],
['After 5+ placements','Full profile with history and trends','#484f58',false]
];
stages.forEach(function(s){
var row=document.createElement('div');row.style.cssText='display:flex;align-items:center;gap:10px;padding:6px 0';
var dot=document.createElement('div');dot.style.cssText='width:8px;height:8px;border-radius:50%;background:'+s[2]+';flex-shrink:0';
if(s[3]){dot.style.boxShadow='0 0 8px '+s[2]}
var txt=document.createElement('div');
var t1=document.createElement('div');t1.style.cssText='font-size:12px;font-weight:600;color:'+(s[3]?'#f0f6fc':'#484f58');t1.textContent=s[0];
var t2=document.createElement('div');t2.style.cssText='font-size:11px;color:'+(s[3]?'#8b949e':'#3d4450');t2.textContent=s[1];
txt.appendChild(t1);txt.appendChild(t2);row.appendChild(dot);row.appendChild(txt);
newBox.appendChild(row);
});
body.appendChild(newBox);
}
// Skills
if(workerData.skills&&workerData.skills.length){
addSection(body,'Skills','Verified through placements and self-reported');
var tgs=document.createElement('div');tgs.style.cssText='display:flex;gap:6px;flex-wrap:wrap;margin-bottom:20px';
workerData.skills.forEach(function(s){
var t=document.createElement('span');t.style.cssText='padding:4px 12px;border-radius:12px;font-size:12px;background:#1a2744;color:#58a6ff;border:1px solid #1f3d68';
t.textContent=s.trim();tgs.appendChild(t);
});
body.appendChild(tgs);
}
// Certifications
if(workerData.certs&&workerData.certs.length){
addSection(body,'Certifications','');
var cgs=document.createElement('div');cgs.style.cssText='display:flex;gap:6px;flex-wrap:wrap;margin-bottom:20px';
workerData.certs.forEach(function(c){
var t=document.createElement('span');t.style.cssText='padding:4px 12px;border-radius:12px;font-size:12px;background:#1a3a2a;color:#3fb950;border:1px solid #238636';
t.textContent=c.trim();cgs.appendChild(t);
});
body.appendChild(cgs);
}
// Archetype
if(workerData.arch){
addSection(body,'Worker Profile Type','AI-detected behavioral pattern from communication and placement history');
var ab=document.createElement('div');ab.style.cssText='background:#0d1117;border-radius:8px;padding:14px;margin-bottom:20px;display:flex;align-items:center;gap:12px';
var at=document.createElement('span');at.style.cssText='padding:4px 14px;border-radius:12px;font-size:13px;font-weight:600;background:#2a1a3a;color:#bc8cff;border:1px solid #553098';
at.textContent=workerData.arch;ab.appendChild(at);
var adesc=document.createElement('span');adesc.style.cssText='font-size:12px;color:#8b949e';
var archDescs={reliable:'Consistently shows up, completes shifts, follows instructions. Clients request them back.',leader:'Takes initiative, helps train others, can run a team. Good for line lead roles.',communicator:'Responsive to messages, gives advance notice of issues. Easy to coordinate with.',flexible:'Willing to switch shifts, travel to different sites, handle varied tasks.',specialist:'Deep expertise in specific equipment or processes. Premium placement.',erratic:'Inconsistent attendance or performance. Needs monitoring.',silent:'Rarely responds to outreach. May need phone call instead of text.',improving:'Recent trend shows better reliability. Worth a second chance.'};
adesc.textContent=archDescs[workerData.arch]||'';ab.appendChild(adesc);
body.appendChild(ab);
}
// Simulated work history (since we have placement data)
if(workerData.hasM){
addSection(body,'Recent Activity','Simulated from placement and timesheet data');
var hist=document.createElement('div');hist.style.cssText='margin-bottom:20px';
var entries=[
{date:'Last week',event:'Completed 40hrs at Midwest Logistics — '+workerData.loc,status:'good'},
{date:'2 weeks ago',event:'Placed at '+(['Amazon DSP','Cardinal Health','Summit Packaging'][Math.floor(Math.random()*3)]),status:'good'},
{date:'Last month',event:'Cert renewal: '+(workerData.certs[0]||'OSHA-10')+' verified',status:'info'},
];
entries.forEach(function(e){
var row=document.createElement('div');row.style.cssText='display:flex;gap:10px;padding:8px;border-bottom:1px solid #21262d;align-items:center';
var dt=document.createElement('div');dt.style.cssText='color:#484f58;font-size:11px;width:80px;flex-shrink:0';dt.textContent=e.date;
var ev=document.createElement('div');ev.style.cssText='font-size:12px;color:#c9d1d9;flex:1';ev.textContent=e.event;
var st=document.createElement('div');st.style.cssText='width:8px;height:8px;border-radius:50%;background:'+(e.status==='good'?'#3fb950':'#58a6ff');
row.appendChild(dt);row.appendChild(ev);row.appendChild(st);hist.appendChild(row);
});
body.appendChild(hist);
}
// Actions
var acts=document.createElement('div');acts.style.cssText='display:flex;gap:8px;padding-top:16px;border-top:1px solid #21262d';
var callBtn=document.createElement('button');callBtn.style.cssText='flex:1;padding:12px;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;border:none;background:#1f3d68;color:#58a6ff';callBtn.textContent='Call';
var smsBtn=document.createElement('button');smsBtn.style.cssText='flex:1;padding:12px;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;border:none;background:#0d261a;color:#3fb950';smsBtn.textContent='Send SMS';
acts.appendChild(callBtn);acts.appendChild(smsBtn);body.appendChild(acts);
modal.appendChild(body);overlay.appendChild(modal);document.body.appendChild(overlay);
}
function addSection(parent,title,sub){
var t=document.createElement('div');t.style.cssText='font-size:13px;font-weight:600;color:#f0f6fc;margin-bottom:2px';t.textContent=title;
parent.appendChild(t);
if(sub){var s=document.createElement('div');s.style.cssText='font-size:11px;color:#484f58;margin-bottom:10px';s.textContent=sub;parent.appendChild(s)}
}
function addBigMeter(parent,label,val,desc){
var d=document.createElement('div');d.style.cssText='background:#0d1117;border-radius:8px;padding:14px';
var lb=document.createElement('div');lb.style.cssText='font-size:11px;color:#8b949e;margin-bottom:4px';lb.textContent=label;
var row=document.createElement('div');row.style.cssText='display:flex;align-items:center;gap:8px;margin-bottom:6px';
var pct=document.createElement('div');pct.style.cssText='font-size:28px;font-weight:800;color:'+(val>=0.8?'#3fb950':val>=0.5?'#d29922':'#f85149');
pct.textContent=Math.round(val*100)+'%';
var bar=document.createElement('div');bar.style.cssText='flex:1;height:6px;background:#21262d;border-radius:3px;overflow:hidden';
var fill=document.createElement('div');fill.style.cssText='height:100%;border-radius:3px;background:'+(val>=0.8?'#3fb950':val>=0.5?'#d29922':'#f85149')+';width:'+Math.round(val*100)+'%';
bar.appendChild(fill);row.appendChild(pct);row.appendChild(bar);
var ds=document.createElement('div');ds.style.cssText='font-size:10px;color:#484f58';ds.textContent=desc;
d.appendChild(lb);d.appendChild(row);d.appendChild(ds);parent.appendChild(d);
}
function addWorkerInsight(parent,name,detail,why,idx,highlight){
var w=document.createElement('div');w.className='iworker';
if(highlight)w.style.borderLeft='3px solid '+highlight;
w.style.cursor='pointer';
var workerDataRef=arguments[6]||null; // passed as 7th arg
w.onclick=function(){if(workerDataRef)showProfile(workerDataRef)};
var av=document.createElement('div');av.className='av';av.style.background=AC[(idx||0)%AC.length];
av.textContent=(name||'?').split(' ').map(function(n){return(n[0]||'').toUpperCase()}).join('').substring(0,2);
w.appendChild(av);
var info=document.createElement('div');info.className='info';
var nm=document.createElement('div');nm.className='nm';nm.textContent=name;
var dt=document.createElement('div');dt.className='detail';dt.textContent=detail;
info.appendChild(nm);info.appendChild(dt);
if(why){var wh=document.createElement('div');wh.className='why';wh.textContent=why;info.appendChild(wh)}
w.appendChild(info);
var acts=document.createElement('div');acts.className='acts';
var call=document.createElement('button');call.className='ibtn call';call.textContent='Call';
var sms=document.createElement('button');sms.className='ibtn sms';sms.textContent='SMS';
acts.appendChild(call);acts.appendChild(sms);w.appendChild(acts);
parent.appendChild(w);
}
function addStat(parent,n,l){
var s=document.createElement('div');s.className='stat';
var nn=document.createElement('div');nn.className='n';nn.textContent=typeof n==='number'?n.toLocaleString():n;
var ll=document.createElement('div');ll.className='l';ll.textContent=l;
s.appendChild(nn);s.appendChild(ll);parent.appendChild(s);
}
function pw(text){
var p=(text||'').split(/\u2014|\u2013|—/),nm=p[0]?p[0].trim():'',rest=p[1]?p[1].trim():'';
var rm=rest.match(/^(.+?) in (.+?)\./),sm=rest.match(/Skills: ([^.]+)/),cm=rest.match(/Certs?: ([^.]+)/);
var rr=rest.match(/Reliability: ([\d.]+)/),av=rest.match(/Availability: ([\d.]+)/),ar=rest.match(/Archetype: (\w+)/);
return{nm:nm,role:rm?rm[1]:'',loc:rm?rm[2]:'',
skills:sm?sm[1].split('|').filter(function(s){return s.trim()}):[],
certs:cm?cm[1].split('|').filter(function(c){return c.trim()&&c!=='none'}):[],
rel:rr?parseFloat(rr[1]):0,avail:av?parseFloat(av[1]):0,arch:ar?ar[1]:'',hasM:!!rr}
}
function doSearch(){
var q=document.getElementById('sq').value.trim();if(!q)return;
var st=document.getElementById('sst').value,rl=document.getElementById('srl').value;
var out=document.getElementById('sresults');out.textContent='Finding the best matches...';
var f="CAST(reliability AS DOUBLE)>=0.5";
if(st)f+=" AND state='"+st+"'";if(rl)f+=" AND role='"+rl+"'";
fetch(A+'/search',{method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({question:q,index_name:'workers_500k_v1',sql_filter:f,dataset:'workers_500k',id_column:'worker_id',top_k:8,generate:false})
}).then(function(r){return r.json()}).then(function(d){
out.textContent='';var src=d.sources||[];if(!src.length){out.textContent='No matches found. Try different terms or broaden filters.';return}
var h=document.createElement('div');h.style.cssText='color:#8b949e;font-size:12px;margin-bottom:10px';
h.textContent='Found '+(d.sql_matches||0).toLocaleString()+' workers matching your filters — showing the '+src.length+' best matches ('+(d.duration_ms||0)+'ms)';
out.appendChild(h);
src.forEach(function(s,i){
var w=pw(s.chunk_text);if(!w.nm)w.nm=s.doc_id;
addWorkerInsight(out,w.nm,[w.role,w.loc].filter(Boolean).join(' · '),
(w.hasM?'Reliability: '+Math.round(w.rel*100)+'% · ':'')+(w.certs.length?'Certs: '+w.certs.join(', '):'AI match: '+Math.round(s.score*100)+'%'),i,null,w);
});
}).catch(function(e){out.textContent='Error: '+e.message});
}
</script></body></html>