/* =====================================================================
   NOWILLS SQC ERP — Workflow definitions & module configuration data
   ===================================================================== */
(function(){
'use strict';
const D=DATA;

/* ---------------- Workflow process definitions ----------------
   Process: {n:name, cat, stages:[[name, kind(task|approval|system|decision), owner role, SLA hours]]} */
const st=(n,k,r,h)=>[n,k,r,h];
const WF={
 exec:[{n:'Board pack assembly',cat:'Reporting',stages:[st('Auto-consolidate group data','system','ERP engine',0),st('FP&A narrative & variance notes','task','Financial Controller',8),st('CFO review','approval','Chief Financial Officer',8),st('MD sign-off','approval','Managing Director',8),st('Distribute to Board portal','system','Company Secretary',0)]},
      {n:'Exception escalation',cat:'Governance',stages:[st('Rule engine raises exception','system','Rules service',0),st('Manager containment','task','Line Manager',4),st('Escalate L2 — GM','approval','General Manager',4),st('Escalate L3 — Executive','approval','Group CEO',4),st('Resolution log & learning loop','system','Audit service',0)]}],
 quarry:[{n:'Shift production capture & posting',cat:'Operations',stages:[st('Supervisor enters shift figures','task','Quarry Supervisor',1),st('Auto-validate vs weighbridge & stock','system','ERP validation',0),st('Production Manager approval','approval','Production Manager',4),st('Post to stockpile & GL','system','Posting service',0)]},
      {n:'Bench release after blasting',cat:'Operations',stages:[st('Post-blast inspection','task','Blast Engineer',2),st('Geologist clearance','task','Quarry Geologist',4),st('Quarry Manager release','approval','Quarry Manager',2),st('Bench reopened in system','system','ERP',0)]}],
 drill:[{n:'Blast authorization chain',cat:'Critical Control',stages:[st('Blast design & charge plan','task','Blast Engineer',24),st('HSE & exclusion-zone review','approval','HSE Manager',8),st('Community + police notification','task','Public Relations Officer',24),st('Minerals Commission permit check','system','Permit register',0),st('GM final authorization','approval','General Manager',4),st('Execute, record & geo-tag','system','Blast logger',0)]},
      {n:'Explosives issue & return',cat:'Explosives',stages:[st('Blaster requisition','task','Licensed Blaster',2),st('Magazine keeper issue','task','Magazine Keeper',1),st('Reconciliation & variance compute','system','ERP',0),st('HSE sign-off on variance >0.5%','approval','HSE Manager',4)]}],
 crush:[{n:'Crusher breakdown recovery',cat:'Maintenance',stages:[st('Trip event logged from telemetry','system','Plant bus',0),st('Shift fitter diagnosis','task','Shift Fitter',1),st('Auto-raise work order','system','CMMS',0),st('Parts approval','approval','Maintenance Manager',2),st('Back-in-service QC & restart','approval','Crusher Plant Manager',1)]},
      {n:'Product size change-over',cat:'Operations',stages:[st('Change-over request','task','Production Planner',4),st('Screen / mesh verification','task','Crusher Supervisor',2),st('QA lab confirmation','system','QA Lab',0),st('Output released to saleable pile','system','Stockpile ledger',0)]}],
 weigh:[{n:'Manual weight override',cat:'Control',stages:[st('Operator requests override with reason','task','Weighbridge Operator',0.5),st('Supervisor approval + CCTV check','approval','Weighbridge Supervisor',1),st('Auto e-invoice + immutable audit','system','GRA connector',0)]},
      {n:'E-invoice rejection rework',cat:'Tax',stages:[st('GRA rejection received','system','E-invoice listener',0),st('Fix TIN / amount line','task','AR Clerk',4),st('Supervisor re-check','approval','Weighbridge Supervisor',2),st('Resubmit to GRA','system','GRA connector',0)]}],
 stockpile:[{n:'Stock adjustment / write-off',cat:'Finance Control',stages:[st('Drone survey variance flagged','system','Survey service',48),st('Inventory analysis & cause codes','task','Inventory Manager',8),st('Financial Controller approval (>₵10k)','approval','Financial Controller',4),st('Post adjustment + audit anchor','system','Posting service',0)]},
      {n:'Inter-quarry stock transfer',cat:'Logistics',stages:[st('Transfer request','task','Quarry Manager',4),st('Logistics dispatch plan','task','Fleet Manager',8),st('Receiving confirmation & survey','system','Weighbridge',0),st('Both ledgers posted atomically','system','ERP',0)]}],
 sales:[{n:'Credit-limit override',cat:'Credit',stages:[st('System blocks order at 95% of limit','system','Credit engine',0),st('Sales Manager recommendation','approval','Sales Manager',2),st('CFO approval above ₵100k exposure','approval','Chief Financial Officer',4),st('Order released + full trail','system','ERP',0)]},
      {n:'Cash sale to e-invoice',cat:'Billing',stages:[st('Weighbridge ticket issued','task','Weighbridge Operator',0.25),st('Payment capture (MoMo / POS / transfer)','system','Payments hub',0),st('GRA e-invoice issued with QR','system','GRA connector',0),st('Daily cash-up reconciliation','system','Treasury',0)]}],
 projects:[{n:'Variation order',cat:'Commercial',stages:[st('Site instruction logged','task','Project Manager',4),st('QS pricing & time impact','task','Quantity Surveyor',24),st('Internal approval (director level)','approval','Construction Director',8),st('Client / RE certification','approval','Client RE (external)',72),st('Budget & BOQ reposted','system','ERP',0)]},
      {n:'Project mobilization',cat:'Start-up',stages:[st('Contract conditions-precedent check','system','Contracts register',0),st('Site establishment plan','task','Project Manager',48),st('HSE & environmental baseline approvals','approval','HSE Manager',24),st('Advance payment guarantee lodged','system','Treasury',0)]}],
 contracts:[{n:'Contract award',cat:'Commercial',stages:[st('Tender evaluation pack','task','Bid Team',120),st('Commercial Director review','approval','Construction Director',8),st('Legal & bond review','approval','Legal Counsel',24),st('MD signature & sealing','approval','Managing Director',8),st('Bond / insurance registration','system','DMS',0)]},
      {n:'BOQ re-measure',cat:'Measurement',stages:[st('Joint measurement with RE','task','Site QS',24),st('Variation impact computed','system','ERP',0),st('RE countersignature','approval','Client RE (external)',72),st('Measured ledger updated','system','BOQ ledger',0)]}],
 ipc:[{n:'Interim payment certificate',cat:'Commercial',stages:[st('Site measurement entries','task','Site Engineer',24),st('PM validation of measure','approval','Project Manager',4),st('QS arithmetic & deductions check','task','Quantity Surveyor',8),st('Client / Engineer certification','approval','Client RE (external)',72),st('AR posting + collection watch','system','Finance',0)]},
      {n:'Retention release',cat:'Commercial',stages:[st('Defects-liability expiry check','system','Contracts',0),st('Snag-free certificate attached','task','Project Manager',24),st('Client release approval','approval','Client (external)',96),st('Cash receipt matched','system','Treasury',0)]}],
 site:[{n:'Daily site report',cat:'Reporting',stages:[st('Foreman submits diary (mobile / offline)','task','Site Foreman',6),st('Auto weather / plant / labour cross-check','system','ERP',0),st('PM review & comments','approval','Project Manager',4),st('Progress posted to EVM','system','Earned value engine',0)]},
      {n:'NCR — non-conformance closure',cat:'Quality',stages:[st('QA/QC engineer raises NCR','task','QA/QC Engineer',2),st('Containment & rework plan','task','Site Agent',24),st('Root-cause analysis','task','QA/QC Engineer',48),st('Quality Manager closure approval','approval','Quality Manager',24),st('Archive + trend statistics','system','DMS',0)]}],
 equip:[{n:'Equipment inter-site transfer',cat:'Logistics',stages:[st('Transfer request with cost basis','task','Site Manager',4),st('Equipment Manager approval','approval','Equipment Manager',4),st('Movement permit & lowbed booking','task','Fleet Manager',8)]},
      {n:'Breakdown escalation',cat:'Maintenance',stages:[st('Operator fault call','task','Operator',0.25),st('Equipment Manager dispatch','task','Equipment Manager',1),st('Maintenance work order auto-link','system','CMMS',0),st('Post-repair hours verification','approval','Equipment Manager',4)]}],
 fleet:[{n:'Trip dispatch authorization',cat:'Logistics',stages:[st('Planner creates trip','task','Dispatch Planner',1),st('Auto checks: licence, load, geofence','system','Telematics',0),st('Fleet Manager approval if outside corridor','approval','Fleet Manager',1),st('Live tracking until proof-of-delivery','system','GPS feed',0)]}],
 fuel:[{n:'Fuel variance investigation',cat:'Control',stages:[st('Dip-vs-book variance flagged','system','Tank telemetry',0),st('Bulk fuel controller analysis','task','Fuel Controller',2),st('Ops Manager sign-off >500 L','approval','Operations Manager',4),st('Adjustment / loss posting','system','GL',0)]},
      {n:'Bulk fuel delivery receipt',cat:'Supply',stages:[st('Tanker arrival & seal check','task','Fuel Controller',1),st('Dip before/after + density sample','task','Fuel Controller',1),st('3-way match to PO / delivery note','system','ERP',0),st('Variance >0.5% → supplier dispute','decision','Procurement Manager',4)]}],
 maint:[{n:'Work order lifecycle',cat:'CMMS',stages:[st('Request raised (any user)','task','Requester',0.5),st('Planner triage & priority','task','Maintenance Planner',4),st('Parts reservation from store','system','Inventory',0),st('Approval if cost > ₵20k','approval','Maintenance Manager',4),st('Execution & labour booking','task','Technician',24),st('Close-out review + failure codes','approval','Maintenance Manager',4)]},
      {n:'PM schedule generation',cat:'CMMS',stages:[st('Weekly auto-generation from hours/calendar','system','CMMS',0),st('Planner capacity smoothing','task','Maintenance Planner',8),st('Publish to crews & lock plan','system','CMMS',0)]}],
 proc:[{n:'Procure-to-pay (P2P)',cat:'Core',stages:[st('Purchase requisition','task','Requester',0.5),st('HOD approval','approval','Head of Department',2),st('Sourcing — RFQ to 3+ suppliers','task','Buyer',48),st('PO approval per DoA limits','approval','DoA engine',4),st('Goods receipt (GRN)','task','Stores',4),st('3-way match PO / GRN / invoice','system','ERP',0),st('Invoice approval','approval','Financial Controller',4),st('Payment run & remittance advice','system','Treasury',0)]},
      {n:'New supplier onboarding',cat:'Vendor',stages:[st('Registration + documents upload','task','Supplier Portal',72),st('Compliance auto-check (TIN, certs, sanctions)','system','KYC service',0),st('Procurement Manager approval','approval','Procurement Manager',8),st('Vendor master created','system','ERP',0)]}],
 inventory:[{n:'Stock issue to cost centre',cat:'Stores',stages:[st('Issue request with CC / WO link','task','Requester',1),st('Stores issue & bin verification','task','Storekeeper',2),st('Cost posted — FIFO / AVCO','system','GL',0)]},
      {n:'Cycle count variance',cat:'Control',stages:[st('System count task generated','system','Inventory engine',0),st('Physical count (blind)','task','Cycle Counter',8),st('Variance computed','system','ERP',0),st('Inventory Mgr approval ≤ ₵25k','approval','Inventory Manager',4),st('FC approval > ₵25k','approval','Financial Controller',4),st('Post adjustments','system','GL',0)]}],
 crm:[{n:'Quotation to order',cat:'Sales',stages:[st('Sales rep drafts quotation','task','Sales Representative',4),st('Discount >5% → Sales Manager','approval','Sales Manager',2),st('Customer e-confirm','system','Customer Portal',48),st('Order activated + credit re-check','system','ERP',0)]}],
 suppliers:[{n:'Supplier invoice dispute',cat:'Payables',stages:[st('Match failure flagged','system','ERP',0),st('Buyer investigation','task','Buyer',8),st('Supplier engagement / credit note','task','Procurement Manager',8),st('Resolution approval','approval','Financial Controller',4),st('Repost & retain evidence','system','DMS',0)]},
      {n:'Subcontractor progress payment',cat:'Subcontracts',stages:[st('Sub submits progress claim','task','Subcontractor Portal',72),st('Site measurement verification','task','Site QS',24),st('PM certification','approval','Project Manager',8),st('Payment certificate & retention compute','system','ERP',0)]}],
 hr:[{n:'Hire to retire — onboarding',cat:'People',stages:[st('Hiring requisition','task','Head of Department',4),st('HR Manager approval','approval','HR Manager',2),st('Offer & e-contract','task','HR Officer',24),st('Payroll / SSNIT / Tier-2 setup','system','Payroll',0),st('Probation review scheduled','system','HRIS',0)]},
      {n:'Monthly payroll run',cat:'Payroll',stages:[st('Time & attendance lock','approval','HR Manager',2),st('Payroll pre-checks (Δ>5% flagged)','system','Payroll engine',0),st('Payroll Officer compute & review','task','Payroll Officer',8),st('HR Manager review','approval','HR Manager',2),st('CFO funding approval','approval','Chief Financial Officer',2),st('Bank file + payslips + statutory feeds','system','Payroll',0)]}],
 finance:[{n:'Month-end close',cat:'Close',stages:[st('Auto accruals, depreciation, FX revaluation','system','Close engine',0),st('Financial Controller review','approval','Financial Controller',8),st('CFO sign-off','approval','Chief Financial Officer',4),st('Lock posting period','system','GL',0)]},
      {n:'Journal approval',cat:'GL',stages:[st('Preparer enters journal','task','Accountant',1),st('Chief Accountant review','approval','Chief Accountant',4),st('FC approval if > ₵50k','approval','Financial Controller',4),st('Posted + immutable trail','system','GL',0)]}],
 treasury:[{n:'Payment run',cat:'Payments',stages:[st('Due items consolidated','system','AP engine',0),st('Treasurer sequencing on liquidity','task','Treasurer',4),st('FC approval','approval','Financial Controller',2),st('CFO approval for > ₵250k','approval','Chief Financial Officer',2),st('Bank release + supplier notify','system','Banking API',0)]}],
 budget:[{n:'Budget virement',cat:'Planning',stages:[st('Transfer request with justification','task','Budget Owner',2),st('Budget Officer compliance check','task','Budget Officer',4),st('FC approval (>₵100k → CFO)','approval','Financial Controller',4),st('Ledgers & forecast updated','system','Planning service',0)]}],
 tax:[{n:'Statutory filing (VAT / WHT / PAYE / SSNIT)',cat:'Compliance',stages:[st('Auto-compile from GL + subledgers','system','Tax engine',0),st('Tax Officer reconciliation','task','Tax Officer',2),st('Chief Accountant sign-off','approval','Chief Accountant',2),st('GRA portal submission','system','GRA connector',0),st('Payment & receipt filing','system','Treasury',0)]}],
 hse:[{n:'Incident investigation',cat:'Safety',stages:[st('Incident logged (mobile, geo-tagged)','task','Supervisor',1),st('HSE triage & classification','task','HSE Officer',2),st('CAPA assigned with due dates','task','HSE Manager',24),st('Effectiveness verification','approval','HSE Manager',48),st('Close + statistics update','system','HSE register',0)]},
      {n:'Permit to work',cat:'Safety',stages:[st('Permit request (hot work / height / confined)','task','Work Supervisor',2),st('Area owner approval','approval','Area Manager',2),st('HSE authorization','approval','HSE Manager',1),st('Live permit — auto-expires in 12 h','system','PTW engine',0)]}],
 env:[{n:'Environmental exceedance response',cat:'Environment',stages:[st('Monitor breach — dust / noise / vibration','system','Sensor bus',0),st('Env officer containment','task','Environmental Officer',4),st('Root-cause & corrective plan','task','Environmental Manager',24),st('EPA notification if reportable','task','Environmental Manager',24),st('Closure & trend publish','approval','Environmental Manager',48)]}],
 docs:[{n:'Controlled document approval',cat:'DMS',stages:[st('Upload with metadata','task','Document Owner',1),st('Reviewer check','approval','Reviewer',4)]},
      {n:'Expiry / renewal watch',cat:'DMS',stages:[st('Auto-flag at 60 / 30 / 7 days','system','DMS',0),st('Owner renews or archives','task','Document Owner',240),st('Evidence filed + status flipped','system','DMS',0)]}],
 reports:[{n:'Report publication & subscription',cat:'Analytics',stages:[st('Generate from certified semantic layer','system','BI engine',0),st('Analyst sanity review','approval','Data Analyst',4),st('Distribute under row-level security','system','Delivery service',0)]},
      {n:'New report request',cat:'Analytics',stages:[st('Business request form','task','Requester',2),st('Data owner approval','approval','Data Owner',8),st('Build + certify in catalogue','task','BI Developer',40),st('Publish to catalogue','system','BI engine',0)]}],
 ai:[{n:'AI recommendation actioning',cat:'AI',stages:[st('Model raises recommendation','system','AI service',0),st('Domain owner human review','approval','Domain Owner',4),st('Accept → task created / Reject → feedback','decision','Domain Owner',0),st('Outcome tracked for retraining','system','MLOps',0)]},
      {n:'Model drift response',cat:'MLOps',stages:[st('Drift / accuracy alert above threshold','system','MLOps',0),st('Data science review','task','Data Scientist',24),st('Champion / challenger promotion','approval','AI Governance Board',48),st('Registry + audit updated','system','MLOps',0)]}],
 admin:[{n:'User access provisioning',cat:'Security',stages:[st('Manager requests access','task','Line Manager',2),st('Security review (SoD check)','approval','Security Manager',2),st('SysAdmin provisions','task','System Administrator',2),st('Audit entry + user notified','system','IAM',0)]},
      {n:'Configuration change control',cat:'Change',stages:[st('Admin stages config change','task','System Administrator',2),st('Impact preview (auto diff)','system','Config service',0),st('Internal Audit / COO approval','approval','Internal Auditor',4),st('Publish + version + rollback point','system','Config service',0)]}]
};
Object.values(WF).forEach(list=>list.forEach(p=>{p.stages=p.stages.filter(s=>Array.isArray(s));}));

/* ---------------- live workflow instances ---------------- */
function wfInstances(){ const r=D.mulberry(909); const out=[]; const flat=[];
 Object.keys(WF).forEach(m=>WF[m].forEach((p,pi)=>flat.push({m,pi,p})));
 for(let i=0;i<26;i++){ const f=flat[Math.floor(r()*flat.length)]; const si=1+Math.floor(r()*(f.p.stages.length-1));
  const age=Math.round(r()*90); const sla=f.p.stages[si][3]||24; const st2=age>sla*1.5?'breached':age>sla?'at risk':'on track';
  out.push({id:'WF-'+(60210-i*7),mod:f.m,process:f.p.n,stage:si,stageName:f.p.stages[si][0],owner:f.p.stages[si][2],age:age+' h',sla:sla+' h',st:st2,
   by:['E. Osei','A. Mensah','K. Boateng','S. Adjei','R. Asante','D. Amoah'][i%6]});}
 return out;}

/* ---------------- Module configuration defaults ----------------
   Field: {k, l(label), t(text|number|currency|pct|toggle|select), v(value), h(hint)} */
const F=(k,l,t,v,h)=>({k:k,l:l,t:t,v:v,h:h});
const CFG={
 exec:{nn:'DASH',sections:[['Dashboards',[F('refresh','Live refresh cadence (seconds)','number',4,'WebSocket push interval'),F('kpiTarget','Red line — % below target renders red','pct',80),F('bpAuto','Board pack auto-generation','select','Monthly close|Weekly|Manual'),F('present','Presentation default period','select','This Month|This Quarter|FY')]]]},
 quarry:{nn:'QPR',sections:[['Production',[F('dayTarget','Daily production target (t)','number',5200),F('yieldMin','Minimum yield alert (%)','pct',92),F('wasteMax','Waste alert threshold (%)','pct',6),F('shifts','Shift pattern','select','3 × 8h|2 × 12h')]],['Posting',[F('autoPost','Auto-post after manager approval','toggle',1),F('tolerance','Weigh-vs-production tolerance (t)','number',40)]]]},
 drill:{nn:'BLST',sections:[['Blasting',[F('pf','Powder-factor target (kg/t)','number',0.5),F('ppv','PPV limit (mm/s)','number',5,'EPA / MinCom'),F('radius','Exclusion radius (m)','number',500),F('lead','Community notice lead time (days)','number',3)],['Explosives',[F('varTol','Issue variance tolerance (%)','pct',0.5),F('magRecon','Magazine reconciliation','select','Per issue|Daily')]]]]},
 crush:{nn:'CRSH',sections:[['Plant',[F('rate','Rated tph — Crusher A/B/C/D','text','280 / 260 / 220 / 180'),F('tripTemp','Bearing temperature trip (°C)','number',95),F('downAlert','Downtime alert after (min)','number',30)],['Quality',[F('flakiness','Max flakiness index (%)','pct',20),F('sampling','QA sampling frequency','select','Hourly|Per 500 t|Per shift')]]]]},
 weigh:{nn:'WB',sections:[['Bridge',[F('tolKg','Print tolerance (kg)','number',50),F('tareDays','Tare validity (days)','number',7),F('cashMax','Cash ticket cap','currency',5000)],['Compliance',[F('einvc','Auto e-invoice every ticket','toggle',1),F('override','Overrides need supervisor + CCTV','toggle',1),F('reprint','Reprint reason mandatory','toggle',1)]]]]},
 stockpile:{nn:'PILE',sections:[['Inventory',[F('daysCover','Reorder basis — days of cover','number',10),F('capAlert','Capacity alert (%)','pct',90),F('survey','Drone survey cadence','select','Weekly|Bi-weekly|Monthly')],['Adjustments',[F('adjLimit','Auto-approve adjustments below','currency',10000),F('blind','Blind physical counts','toggle',1)]]]]},
 sales:{nn:'SO',sections:[['Pricing',[F('priceList','Default price list','select','2026-Q3 List A|2026-Q3 List B (Ashanti)|Dealer'),F('disc','Rep discount floor without approval (%)','pct',5)],['Credit',[F('hold','Auto credit-hold at % of limit','pct',95),F('quoteDays','Quotation validity (days)','number',14),F('einvc','E-invoice on dispatch, not month-end','toggle',1)]]]]},
 projects:{nn:'PRJ',sections:[['EVM & Progress',[F('evm','Progress measurement','select','Physical % (EVM)|Cost-weighted|Units rate'),F('marginAlert','Margin drift alert (points)','number',4)],['Commercial',[F('retention','Default retention (%)','pct',5),F('voLimit','Variation needing MD sign-off','currency',50000)]]]]},
 contracts:{nn:'CON',sections:[['Commercial',[F('retCap','Retention cap (%)','pct',10),F('claimDays','Claim submission window (days)','number',28),F('eot','EOT notice window (days)','number',14)],['Securities',[F('bondAlert','Bond/guarantee expiry alert (days)','number',30)]]]]},
 ipc:{nn:'IPC',sections:[['Certification',[F('sla','Certification SLA (days)','number',14),F('advance','Advance recovery per IPC (%)','pct',20)],['Deductions',[F('wht','WHT on certificates (services %)','pct',7.5),F('aging','Aging buckets (days)','text','30 · 60 · 90 · 120')]]]]},
 site:{nn:'DSR',sections:[['Diaries',[F('cutoff','Diary cutoff time','text','17:00'),F('photos','Photos mandatory','toggle',1),F('weather','Weather source','select','Auto (API)|Manual entry')],['Quality',[F('ncrEsc','NCR auto-escalates after (days)','number',7)]]]]},
 equip:{nn:'EQP',sections:[['Lifecycle',[F('svcInt','Service interval (hrs)','number',250),F('util','Utilisation target (%)','pct',80),F('replaceHrs','Replacement review at hours','number',25000)],['Hire',[F('hireBasis','Hire rate basis','select','Per hour|Per day|Per tonne'),F('autoWO','Breakdown auto-creates WO','toggle',1)]]]]},
 fleet:{nn:'TRK',sections:[['Telematics',[F('speed','Speed limit (km/h)','number',80),F('geo','Geofence corridor (km)','number',5),F('idle','Idle alert (min)','number',15)],['Trips',[F('pod','e-sign / photo proof-of-delivery','toggle',1),F('night','Night driving needs approval','toggle',1)]]]]},
 fuel:{nn:'FUEL',sections:[['Reconciliation',[F('varTol','Dip-vs-book tolerance (%)','pct',1.5),F('dipTimes','Dip schedule','text','06:00 · 18:00')],['Security',[F('theftScore','AI theft-risk alert threshold','number',60),F('nightLock','Night-tap lockout 22:00–05:00','toggle',1),F('reorder','Depot reorder level (L)','number',72000)]]]]},
 maint:{nn:'WO',sections:[['Planning',[F('pmTarget','PM compliance target (%)','pct',95),F('resp','Response SLA — critical (h)','number',2)],['Costs',[F('costAppr','WO cost approval above','currency',20000),F('autoResv','Auto-reserve parts on WO','toggle',1)]]]]},
 proc:{nn:'PO',sections:[['Delegation of Authority',[F('doa1','HOD limit','currency',10000),F('doa2','Procurement Manager limit','currency',100000),F('doa3','CFO limit','currency',500000),F('doa4','Above this → MD / Board','text','> ₵500,000')],['Sourcing',[F('quotes','Minimum competitive quotes','number',3),F('match','3-way match tolerance (%)','pct',2),F('sole','Sole-source justification mandatory','toggle',1)]]]]},
 inventory:{nn:'SKU',sections:[['Control',[F('abc','ABC classification','toggle',1),F('cycle','Cycle count cadence','select','Monthly (A) / Quarterly (B,C)|Monthly for all'),F('safety','Safety stock (days)','number',7),F('neg','Block negative stock','toggle',1)],['Valuation',[F('method','Valuation method','select','AVCO|FIFO')]]]]},
 crm:{nn:'CUST',sections:[['Onboarding',[F('kyc','KYC documents required (count)','number',4),F('bureau','Credit bureau endpoint','text','https://api.bureau.gh/v2/score'),F('dormant','Dormant after (days)','number',90)],['Service',[F('caseSla','Complaint first-response SLA (h)','number',8)]]]]},
 suppliers:{nn:'VEND',sections:[['Scorecards',[F('wQ','Weight — Quality (%)','pct',40),F('wD','Weight — Delivery OTIF (%)','pct',40),F('wC','Weight — Cost (%)','pct',20)],['Control',[F('susp','Auto-review if OTIF below (%)','pct',70),F('cert','Certificate expiry alert (days)','number',30),F('terms','Default payment terms (days)','number',30)]]]]},
 hr:{nn:'EMP',sections:[['Payroll',[F('cutoff','Timesheet cutoff (day of month)','number',24),F('otCap','Overtime cap (h/month)','number',40),F('paycur','Payroll currency','select','GHS|USD (expats)')],['People',[F('leave','Annual leave accrual (days/yr)','number',15),F('prob','Probation (months)','number',6)]]]]},
 finance:{nn:'GL',sections:[['Ledger',[F('fy','Fiscal year','select','Jan–Dec|Jul–Jun'),F('closeTarget','Close target (business days)','number',5),F('jvLimit','Journal approval threshold','currency',50000)],['Compliance',[F('suspense','Suspense review (days)','number',3),F('framework','Reporting framework','text','IFRS · Ghana')]]]]},
 treasury:{nn:'TRX',sections:[['Liquidity',[F('cov','Minimum cash covenant','currency',20000000),F('runDays','Payment run days','text','Tue · Fri'),F('momo','MoMo float cap','currency',100000)],['FX',[F('fxLimit','Unhedged FX exposure cap (%)','pct',15)]]]]},
 budget:{nn:'BDG',sections:[['Control',[F('vire','Virement within cost centre auto below','currency',50000),F('ver','Freeze version on approval','toggle',1),F('fcst','Forecast cadence','select','Monthly|Quarterly')]]]},
 tax:{nn:'TAX',sections:[['Ghana Revenue Authority',[F('einvc','Auto-submit e-invoices','toggle',1),F('env','GRA API environment','select','Production|Sandbox'),F('remind','Filing reminders at D-3 / D-1','toggle',1)],['Computation',[F('levyOrder','Levy computation order','text','NHIL + GETFund + CHRL on taxable value, then VAT'),F('royalty','Quarry royalty base','select','Gross quarry revenue')]]]]},
 hse:{nn:'INC',sections:[['Permits',[F('ptw','Permit-to-work validity (h)','number',12),F('toolbox','Toolbox talk cadence','select','Weekly (Tue)|Daily')],['Metrics',[F('ltifr','LTIFR window (months)','number',12),F('capa','CAPA overdue escalation (days)','number',7),F('geotag','Incident geo-tag + photo mandatory','toggle',1)]]]]},
 env:{nn:'ENV',sections:[['EPA Limits',[F('pm10','PM10 limit (µg/m³)','number',70),F('noise','Noise limit (dB)','number',75),F('ppv','Vibration PPV limit (mm/s)','number',5)],['Community',[F('complaintSla','Complaint response SLA (h)','number',48),F('epaReport','EPA monitoring report cadence','select','Monthly|Quarterly')]]]]},
 docs:{nn:'DOC',sections:[['Governance',[F('retain','Retention (years)','number',7),F('wm','Watermark on download / print','toggle',0),F('esign','E-sign provider','select','Built-in|DocuSign')],['Lifecycle',[F('expire','Expiry alerts (days)','text','60 · 30 · 7'),F('ocr','Auto OCR + full-text index','toggle',1)]]]]},
 reports:{nn:'RPT',sections:[['Delivery',[F('refresh','Default refresh','select','Live (4 s)|15 min|Hourly'),F('rls','Row-level security on exports','toggle',1)],['Board Pack',[F('bp','Board pack template','select','Standard 9-section|Compact'),F('verify','Verification code on every export','toggle',1)]]]]},
 ai:{nn:'AI',sections:[['Models',[F('horizon','Forecast horizon (weeks)','number',13),F('conf','Minimum confidence to display (%)','pct',80),F('retrain','Auto retrain cadence','select','Monthly|Weekly')],['Governance',[F('hil','Human-in-the-loop required','toggle',1),F('explain','SHAP explanations mandatory','toggle',1),F('drift','Drift alert when PSI exceeds','number',0.2)]]]]},
 admin:{nn:'SEC',sections:[['Sessions',[F('timeout','Session timeout (min)','number',30),F('mfa','MFA for privileged roles','toggle',1),F('ips','IP allow-list (CIDR)','text','102.89.14.0/24 · HQ-VPN')],['Integrity',[F('anchor','Audit hash-anchor cadence','select','Hourly|Per block'),F('conflict','Sync conflict rule','select','Manager review|Server wins'),F('rate','API rate limit (req/min/key)','number',600)]]]]},
 wflow:{nn:'WF',sections:[['Engine',[F('escalate','Auto-escalate on SLA breach','toggle',1),F('chain','Escalation chain','text','L1 Manager → L2 GM → L3 Executive'),F('clock','SLA clock basis','select','Business hours|24 × 7')],['Designer',[F('sim','Simulation sandbox before publish','toggle',1),F('version','Workflow versioning','toggle',1)]]]]},
 setup:{nn:'CFG',sections:[['Change Control',[F('needAppr','Changes need Internal Audit / COO approval','toggle',1),F('rollback','Auto rollback point per publish','toggle',1),F('diff','Impact diff required before publish','toggle',1)],['Environments',[F('promote','Promotion path','text','Training → UAT → Production'),F('drift','Detect config drift between environments','toggle',1)]]]]}
};

/* ---------------- Notification templates ---------------- */
const TPL=[['Production below target','Production','{quarry} shift {shift}: {actual} t vs target {target} t ({pct}%). Owner: {owner}.','inapp,push,sms'],
 ['Equipment breakdown','Equipment','{asset} DOWN at {site} — {fault}. WO {wo} raised, ETA {eta}.','inapp,email,sms'],
 ['Low stock / reorder','Inventory','{sku} at {qty} — below reorder {level}. Suggested PO qty {suggest}.','inapp,email'],
 ['Project delay risk','Projects','{project} schedule variance {weeks} wks. Forecast finish {date}. EAC drift {pts} pts.','inapp,email'],
 ['Budget exceeded','Budget','{costcentre} at {pct}% of FY budget. Virement or CFO action needed.','inapp,email'],
 ['Customer payment overdue','Sales','{customer} invoice {inv} — {amount} overdue {days} d. Exposure {limit}% of limit.','inapp,email,sms'],
 ['Supplier payment due','Procurement','{supplier} invoice {inv} due {date} — {amount}. Included in {runday} payment run?','inapp'],
 ['Tax return due','Tax','{form} filing due {date} — estimated {amount}. Ledger difference {diff}.','inapp,email'],
 ['Safety incident','HSE','{type} at {site}: {desc}. Severity {sev}. CAPA {capa} assigned to {owner}.','inapp,push,sms,whatsapp'],
 ['Environmental breach','Environment','{param} {value} exceeds limit {limit} at {site}. Containment SLA {sla} h.','inapp,push,sms'],
 ['Approval pending','Workflow','{doctype} {ref} awaits your approval — {amount}. SLA {sla} h. Tap to decide.','inapp,push'],
 ['Offline sync failure','System','{node} offline {mins} min — {queue} records queued. Last sync {time}.','inapp,email'],
 ['AI high-risk alert','AI','Model {model} flagged {subject} (confidence {conf}%, impact {impact}). Review in AI Command.','inapp,push']];

window.DATA2={WF:WF,CFG:CFG,CFG_T:F,wfInstances:wfInstances,TPL:TPL};
})();
