/* Al Hajar Construction — role-aware application shell */
const ROLE_NAV={
'System Administrator':'*',
'Executive Management':['dashboard','aicos','projects','leads','estimation','contracts','variations','requisitions','rfq','purchase-orders','suppliers','inventory','subcontractors','fin-dashboard','cost-control','hse-incidents','body-map','ncr','quality-audits','omanisation'],
'Project Manager':['dashboard','aicos','projects','cost-control','billing','requisitions','purchase-orders','subcontractors','hse-incidents','observations','permits','ncr','itp','equipment','job-cards','employees','attendance'],
'Site Engineer':['dashboard','projects','observations','permits','jsa','itp','ncr','requisitions','job-cards','attendance'],
'HR Manager':['dashboard','aicos','employees','attendance','leave','payroll','omanisation','training'],
'Finance Manager':['dashboard','aicos','fin-dashboard','billing','cost-control','payables','receivables','contracts'],
'Procurement Manager':['dashboard','aicos','requisitions','rfq','purchase-orders','suppliers','subcontractors','inventory'],
'Warehouse Keeper':['dashboard','inventory','purchase-orders','spares'],
'Sales & BD Manager':['dashboard','aicos','leads','estimation','contracts','variations','clients'],
'HSE Manager':['dashboard','aicos','hse-incidents','body-map','observations','permits','jsa','environment','quality-audits'],
'Quality Manager':['dashboard','aicos','ncr','itp','quality-audits','documents','calibration'],
'Maintenance Manager':['dashboard','aicos','equipment','ppm','job-cards','spares']};
const NAV_GROUPS=[
{group:'Overview',items:[['dashboard','Executive Dashboard','grid'],['aicos','AI-COS Console','sparkles'],['projects','Projects','building']]},
{group:'Sales & Contracts',items:[['leads','Leads & Tenders','trend'],['estimation','Estimation & BOQ','chart'],['contracts','Contracts','documents'],['variations','Variations','refresh'],['clients','Clients','users']]},
{group:'Supply Chain',items:[['requisitions','Purchase Requisitions','receipt'],['rfq','RFQ & Bids','chat'],['purchase-orders','Purchase Orders','box'],['suppliers','Suppliers','truck'],['inventory','Inventory & Stores','box'],['subcontractors','Subcontractors','users']]},
{group:'HSE',items:[['hse-incidents','Incidents','helmet'],['body-map','Injury Body-Map','helmet'],['observations','Observations','search'],['permits','Permit to Work','check-shield'],['jsa','JSA & Risk','shield'],['environment','Environment','thermometer']]},
{group:'Quality',items:[['ncr','NCR & CAPA','flag'],['itp','ITP & Inspections','check-shield'],['quality-audits','Audits','check-shield'],['documents','Document Control','documents'],['calibration','Calibration Register','gauge']]},
{group:'Finance',items:[['fin-dashboard','Finance Dashboard','chart'],['billing','Progress Billing / IPC','receipt'],['cost-control','Project Cost Control','chart'],['payables','Payables','receipt'],['receivables','Receivables','trend']]},
{group:'HR',items:[['employees','Employees','users'],['attendance','Attendance & Timesheets','clock'],['leave','Leave','calendar'],['payroll','Payroll & WPS','receipt'],['omanisation','Omanisation','building'],['training','Training & Competency','certificate']]},
{group:'Maintenance',items:[['equipment','Equipment Register','truck'],['ppm','Preventive Maintenance','refresh'],['job-cards','Job Cards','wrench'],['spares','Spare Parts','box']]},
{group:'Administration',items:[['audit-trail','Audit Trail','history'],['access','Users & Access','shield']]}
];
function allowedNav(role){const a=ROLE_NAV[role]||[];return NAV_GROUPS.map(g=>({...g,items:g.items.filter(x=>a==='*'||a.includes(x[0]))})).filter(g=>g.items.length);}
/* Live audit-readiness score — the sidebar's standing answer to "could we pass an audit today?".
   Weighted from the same engines the compliance strip and health matrix use, so the number in the
   sidebar and the number on the dashboard can never drift apart. */
function auditReadiness(){const c=window.complianceStrip(),h=window.domainHealth(),
  qms=DB.qmsDocuments||[],docs=qms.filter(d=>d.status==='Current'||d.status==='Approved').length,docPct=qms.length?Math.round(docs/qms.length*100):90,
  score=Math.round(c.iso9001*.26+c.iso45001*.26+c.iso14001*.14+c.trainingCompliancePct*.14+c.ppmCompliancePct*.10+docPct*.10),
  weakest=h.slice().sort((a,b)=>a.score-b.score)[0];
  return {score:Math.max(0,Math.min(100,score)),weakest};}
function AuditScoreCard({onNav}){const {score,weakest}=auditReadiness(),band=score>=80?'ok':score>=60?'warn':'bad',
  label=score>=80?'Audit ready':score>=60?'Gaps to close':'At risk';
  return <div className="readiness-card" onClick={()=>onNav('dashboard')} title="Live ISO 9001 / 45001 / 14001 readiness">
    <div className="row" style={{justifyContent:'space-between'}}><span style={{fontSize:11,color:'#9fb4d0',fontWeight:700}}>AUDIT READINESS</span><Icon name="shield" size={14}/></div>
    <div className="row" style={{gap:8,marginTop:6,alignItems:'flex-end'}}>
      <span style={{fontSize:28,fontWeight:800,color:'#fff',lineHeight:1}}>{score}</span>
      <span style={{fontSize:12,color:'#7e94b0',marginBottom:2}}>/ 100</span>
      <span className={'badge b-'+band} style={{marginLeft:'auto',marginBottom:2}}>{label}</span>
    </div>
    <div className="progress" style={{marginTop:9,height:5,background:'#0a1c30'}}><i style={{width:score+'%',background:band==='ok'?'linear-gradient(90deg,var(--primary-500),#58d6a6)':band==='warn'?'linear-gradient(90deg,#e0a12a,#f0c766)':'linear-gradient(90deg,#c0392b,#e0705f)'}}/></div>
    <div style={{marginTop:8,fontSize:10,color:'#8fa6c4',display:'flex',gap:5,alignItems:'center'}}><Icon name="alert" size={11}/>Weakest domain · {weakest.domain} {weakest.score}</div>
  </div>;}
function Sidebar({active,onNav}){const openNcr=DB.ncrs.filter(x=>x.status!=='Closed').length,delayed=DB.purchaseOrders.filter(x=>x.deliveryStatus==='Delayed').length;return <aside className="sidebar"><div className="brand"><span className="brand-mark"><Icon name="building" size={20}/></span><div><div className="brand-name">Al Hajar Construction</div><div className="brand-sub">CONSTRUCTION ERP · OMAN</div></div></div><nav className="nav">{allowedNav(window.ROLE).map(g=><div key={g.group}><div className="nav-group-label">{window.t(g.group)}</div>{g.items.map(it=><div key={it[0]} className={'nav-item'+(active===it[0]?' active':'')} onClick={()=>onNav(it[0])}><Icon name={it[2]} size={18} className="nav-ico"/><span>{window.t(it[1])}</span>{it[0]==='ncr'&&openNcr?<span className="nav-badge amber">{openNcr}</span>:it[0]==='purchase-orders'&&delayed?<span className="nav-badge">{delayed}</span>:null}</div>)}</div>)}</nav><div className="side-foot"><AuditScoreCard onNav={onNav}/><a href="mobile.html" target="_blank" rel="noopener" className="nav-item" style={{marginTop:10,color:'#b6c6dd'}}><Icon name="phone" size={18}/><span>Employee App</span><Icon name="ext" size={13}/></a><div className="aicos-powered"><span>POWERED BY</span><img src="assets/aicos-logo-white.png" alt="AI COS — QHSE Excellence"/></div></div></aside>;}
function Topbar({title,onOpenNotif,onOpenAI,onSignOut}){const role=window.ROLE,s=DB.staff.find(x=>x.role===role)||DB.staff[0],unread=DB.notifications.filter(x=>!x.read).length,toggleLang=()=>{window.LANG=window.LANG==='EN'?'AR':'EN';document.body.classList.toggle('rtl',window.LANG==='AR');window.__bump();};return <header className="topbar"><div className="breadcrumb"><span>Al Hajar</span><Icon name="chevR" size={13}/><b>{window.t(title)}</b></div><div className="spacer"/><div className="searchbox"><Icon name="search" size={16}/><input placeholder={window.t('Search')+' projects, IPCs, NCRs…'} onKeyDown={e=>e.key==='Enter'&&e.target.value.trim()&&window.__search(e.target.value.trim())}/><kbd>⌘K</kbd></div><Btn variant="ai" onClick={onOpenAI}><img src="assets/aicos-mark.png" alt="" className="aicos-mark-sm"/>{window.t('Ask AI-COS')}</Btn><Btn size="sm" onClick={toggleLang}>ع/EN</Btn><div className="field" style={{minWidth:185}}><select value={role} onChange={e=>{window.ROLE=e.target.value;sessionStorage.setItem('aicos-role',e.target.value);window.__bump();}}>{DB.roles.map(r=><option key={r}>{r}</option>)}</select></div><button className="icon-btn" onClick={onOpenNotif}><Icon name="bell" size={17}/>{unread?<span className="nav-badge">{unread}</span>:null}</button><div className="vr"/><Avatar id={s.id}/><div className="col" style={{gap:0}}><b style={{fontSize:12.5}}>{s.name}</b><span className="faint" style={{fontSize:11}}>{role}</span></div><Btn size="sm" icon="logout" onClick={onSignOut}>Sign out</Btn></header>;}
function MiniAIChart({chart}){if(!chart)return null;const data=chart.data||[],max=Math.max(...data.map(x=>x.n),1);return <div style={{display:'flex',height:120,alignItems:'flex-end',gap:8}}>{data.map(d=><div key={d.k} style={{flex:1,textAlign:'center'}}><div className="mono" style={{fontSize:9}}>{d.n}</div><div style={{height:Math.max(4,d.n/max*80),background:'var(--ai)',borderRadius:'4px 4px 0 0'}}/><span className="faint" style={{fontSize:9}}>{d.k}</span></div>)}</div>;}
function AICites({cites,onNav}){return <div className="wrap" style={{gap:5,marginTop:8}}>{(cites||[]).map((c,i)=><span key={i} className="ai-cite mono">{c}</span>)}</div>;}
function AIConversation({compact=false,prefill,onNav}){const suggested=DB.aicosSuggestions.filter(x=>!x.role||x.role===window.ROLE),[messages,setMessages]=useState([]),[q,setQ]=useState('');const ask=text=>{if(text){setMessages(s=>[...s,{q:text,a:window.aicosAnswer(text)}]);setQ('');}};useEffect(()=>{if(prefill?.q)ask(prefill.q);},[prefill]);return <div><div className="wrap" style={{gap:7,marginBottom:14}}>{suggested.slice(0,compact?5:8).map((x,i)=><Btn key={i} size="sm" variant="ai" onClick={()=>ask(x.q)}>{x.q}</Btn>)}</div>{messages.map((m,i)=><div key={i} className="card card-pad" style={{marginBottom:12}}><div className="cell-sub">You</div><b>{m.q}</b><div className="divider"/><div className="row" style={{alignItems:'flex-start'}}><span className="ai-badge-ico"><Icon name="sparkles" fill size={14}/></span><div style={{flex:1}}><div>{m.a.text}</div><MiniAIChart chart={m.a.chart}/>{m.a.table&&<div style={{overflowX:'auto',marginTop:10}}><table className="tbl"><thead><tr>{Object.keys(m.a.table[0]||{}).map(k=><th key={k}>{k}</th>)}</tr></thead><tbody>{m.a.table.slice(0,8).map((r,ri)=><tr key={ri}>{Object.keys(r).map(k=><td key={k}>{r[k]}</td>)}</tr>)}</tbody></table></div>}<AICites cites={m.a.cites} onNav={onNav}/></div></div></div>)}<form className="row" onSubmit={e=>{e.preventDefault();ask(q);}}><input className="input" value={q} onChange={e=>setQ(e.target.value)} placeholder="Ask about live construction ERP data…"/><Btn variant="primary" icon="arrowR">Ask</Btn></form></div>;}
function AICOSProactive(){return <div style={{marginBottom:16}}><div className="h-sec" style={{marginBottom:10}}>Proactive</div><div className="card card-pad"><div className="ai-label">Role digest · {window.ROLE}</div>{DB.aicosInsights.map((x,i)=><div className="lrow" key={i}><span className="kpi-ico"><Icon name={x.icon} size={14}/></span><div><b>{x.title}</b><div className="faint" style={{fontSize:11}}>{x.detail}</div></div></div>)}</div></div>;}
function AICOSPanel({open,onClose,onNav}){const [prefill,setPrefill]=useState(null);useEffect(()=>{if(open&&window.__aiPrefill){setPrefill({q:window.__aiPrefill,id:Date.now()});window.__aiPrefill='';}},[open]);return <Drawer open={open} onClose={onClose} width={720}><div className="drawer-head"><img src="assets/aicos-mark.png" alt="AI-COS" className="aicos-mark-md"/><div style={{flex:1}}><b>AI-COS · Construction Intelligence</b><div className="faint" style={{fontSize:11}}>Advisory only · cites live ERP sources · respects role permissions</div></div><button className="icon-btn" onClick={onClose}><Icon name="x"/></button></div><div className="drawer-body"><AICOSProactive/><AIConversation compact prefill={prefill} onNav={onNav}/></div></Drawer>;}
function AIStrip({module,onNav}){const [why,setWhy]=useState({});if(module==='aicos')return null;const intel=window.aicosPageIntel(module,window.ROLE),items=(intel.insights||[]).slice(0,3);return <div className="ai-strip-wrap"><div className="card ai-strip"><div className="ai-strip-head"><img src="assets/aicos-mark.png" alt="" className="aicos-mark-sm"/><b>AI-COS suggests</b><Badge kind="ai">{items.length}</Badge></div><div className="ai-strip-insights">{items.map((x,i)=><div className="ai-strip-item" key={i}><span className={`ai-tone ai-tone-${x.tone||'info'}`}/><Icon name={x.icon||'sparkles'} size={14}/><div className="ai-strip-copy"><b>{x.title}</b><span>{x.detail}</span>{why[i]&&<div className="ai-why">{x.why}</div>}</div><button className="ai-why-btn" onClick={()=>setWhy(s=>({...s,[i]:!s[i]}))}>{why[i]?'Hide':'Why?'}</button>{x.action&&<Btn size="sm" variant="ai" onClick={()=>x.action.nav?onNav(x.action.nav):window.__askAICOS(x.action.ask)}>{x.action.label}</Btn>}</div>)}</div><div className="ai-strip-prompts">{(intel.questions||[]).slice(0,3).map((q,i)=><button className="ai-chip" key={i} onClick={()=>window.__askAICOS(q)}>✦ {q}</button>)}</div><div className="ai-strip-foot">Advisory only · computed live · respects role permissions</div></div></div>;}
function NotifPanel({open,onClose,onNav}){return <Drawer open={open} onClose={onClose} width={410}><div className="drawer-head"><Icon name="bell"/><b style={{flex:1}}>Construction notifications</b><button className="icon-btn" onClick={onClose}><Icon name="x"/></button></div><div className="drawer-body">{DB.notifications.slice().sort((a,b)=>new Date(b.ts)-new Date(a.ts)).map(x=><div className="lrow" key={x.id}><span className="kpi-ico"><Icon name="bell" size={16}/></span><div style={{flex:1}}><b>{x.body}</b><div className="faint">{DB.rel(x.ts)} · {(x.to||[]).join(', ')}</div></div>{!x.read&&<Badge kind="info">New</Badge>}</div>)}</div></Drawer>;}
function StaffLogin({onEnter}){const scopes={'Executive Management':'Portfolio, finance, HSE and quality intelligence','Project Manager':'Assigned project delivery and controls','Site Engineer':'Site execution, safety and inspections','HR Manager':'People, attendance, payroll and Omanisation','Finance Manager':'IPC billing, cost and receivables','Procurement Manager':'Procurement, suppliers and inventory','Warehouse Keeper':'Stores, receipts and spare parts','Sales & BD Manager':'Tenders, estimates, contracts and clients','HSE Manager':'Incidents, observations, risk and environment','Quality Manager':'NCR, inspections, audits and documents','Maintenance Manager':'Plant, PPM, job cards and spares'},stats=[[NAV_GROUPS.reduce((a,g)=>a+g.items.length,0),'Routes'],[DB.roles.length,'Personas'],[DB.projects.length,'Projects']];return <div className="login-wrap"><section className="login-brand"><div className="login-brand-top"><img src="assets/aicos-logo-white.png" alt="AI-COS"/><div><b>{DB.company.name}</b><span>Construction ERP · Sultanate of Oman</span></div></div><div className="login-brand-copy"><Badge kind="info"><Icon name="shield" size={12}/>{DB.company.standards}</Badge><h1>Projects, people, commercial control and QHSE in one governed system.</h1><p>A role-aware multi-project construction ERP connecting delivery across Oman.</p><div className="login-stats">{stats.map(([v,l])=><div key={l}><b>{v}</b><span>{l}</span></div>)}</div></div><footer>Demo environment · no credentials collected</footer></section><main className="login-panel"><div className="login-card"><div className="eyebrow">Sign in</div><h2>Choose a staff persona</h2><p className="muted">Enter with role-scoped navigation and intelligence.</p><div className="field demo-email"><label>Email</label><input disabled value="demo.staff@alhajar.example"/></div><div className="role-grid">{DB.roles.filter(r=>r!=='System Administrator').map(role=>{const s=DB.staff.find(x=>x.role===role);return <button className="role-card" key={role} onClick={()=>onEnter(role)}><span className="avatar" style={{background:s.color}}>{s.initials}</span><span><b>{role}</b><small>{scopes[role]}</small></span><Icon name="chevR" size={15}/></button>;})}</div><Btn variant="primary" size="lg" icon="shield" style={{width:'100%',marginTop:14}} onClick={()=>onEnter('System Administrator')}>Continue as System Administrator</Btn></div></main></div>;}
Object.assign(window,{Sidebar,Topbar,NotifPanel,AICOSPanel,AICOSProactive,AIConversation,MiniAIChart,AIStrip,StaffLogin,NAV_GROUPS,ROLE_NAV,allowedNav});
