{"id":9723,"date":"2026-05-21T11:57:40","date_gmt":"2026-05-21T06:27:40","guid":{"rendered":"https:\/\/lilodhyanresort.com\/?page_id=9723"},"modified":"2026-05-21T16:45:51","modified_gmt":"2026-05-21T11:15:51","slug":"lilo-tracker-live","status":"publish","type":"page","link":"https:\/\/lilodhyanresort.com\/index.php\/lilo-tracker-live\/","title":{"rendered":"lilo-tracker-live"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"9723\" class=\"elementor elementor-9723\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6e856af e-con-full e-flex e-con e-parent\" data-id=\"6e856af\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ff20993 elementor-widget__width-inherit elementor-widget elementor-widget-html\" data-id=\"ff20993\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\"\/>\r\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"\/>\r\n<title>Lilo Tracker 2026<\/title>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/react\/18.2.0\/umd\/react.production.min.js\"><\/script>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/react-dom\/18.2.0\/umd\/react-dom.production.min.js\"><\/script>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/babel-standalone\/7.23.2\/babel.min.js\"><\/script>\r\n<style>\r\n*{box-sizing:border-box;margin:0;padding:0;}\r\nbody{background:#f1f5f9;font-family:'Segoe UI',system-ui,sans-serif;}\r\n#root{height:100vh;display:flex;flex-direction:column;overflow:hidden;}\r\n::-webkit-scrollbar{width:6px;height:6px;}\r\n::-webkit-scrollbar-track{background:#f1f5f9;}\r\n::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px;}\r\ninput::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<div id=\"root\"><\/div>\r\n<script type=\"text\/babel\">\r\nconst{useState,useEffect,useCallback,useRef}=React;\r\n\r\nconst API=\"https:\/\/script.google.com\/macros\/s\/AKfycbzSWegDRjUIFrECOHyfrIegR5OJRsiG6vHlHLf1iCUh3hb7cm7g9DmT4_QFijR9_SZy\/exec\";\r\nasync function apiLoad(){try{const r=await fetch(API);const t=await r.text();if(!t||t===\"{}\") return null;return JSON.parse(t);}catch{return null;}}\r\nasync function apiSave(d){try{await fetch(API,{method:\"POST\",mode:\"no-cors\",headers:{\"Content-Type\":\"application\/json\"},body:JSON.stringify(d)});return true;}catch{return false;}}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ TRACKER DEFAULTS\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\nconst DEFAULT_TASKS=[\r\n  {id:\"t1\", name:\"Club Tile \u2013 4 Floors\",         area:\"Club\",       status:\"Done\",    pct:100,assignee:\"\"},\r\n  {id:\"t2\", name:\"Club Plumbing \u2013 3 Floors\",      area:\"Club\",       status:\"Done\",    pct:100,assignee:\"\"},\r\n  {id:\"t3\", name:\"Lobby\",                          area:\"Club\",       status:\"Done\",    pct:100,assignee:\"\"},\r\n  {id:\"t4\", name:\"Club Pool (Con + Tile)\",         area:\"Club\",       status:\"Running\", pct:70, assignee:\"\"},\r\n  {id:\"t5\", name:\"Club Drive Ramp\",                area:\"Club\",       status:\"Running\", pct:10, assignee:\"\"},\r\n  {id:\"t6\", name:\"Club ACP \/ Glass Window\",        area:\"Club\",       status:\"Running\", pct:50, assignee:\"\"},\r\n  {id:\"t7\", name:\"Club Step Tile\",                 area:\"Club\",       status:\"Running\", pct:20, assignee:\"\"},\r\n  {id:\"t8\", name:\"Club Color\",                     area:\"Club\",       status:\"Running\", pct:20, assignee:\"\"},\r\n  {id:\"t9\", name:\"Club Electrical\",                area:\"Club\",       status:\"Pending\", pct:0,  assignee:\"\"},\r\n  {id:\"t10\",name:\"Club Entry Fabrication\",         area:\"Club\",       status:\"Pending\", pct:0,  assignee:\"\"},\r\n  {id:\"t11\",name:\"Club Fabrication\",               area:\"Club\",       status:\"Pending\", pct:0,  assignee:\"\"},\r\n  {id:\"t12\",name:\"Earth \/ Wind Plumbing\",          area:\"Earth Wind\", status:\"Running\", pct:50, assignee:\"\"},\r\n  {id:\"t13\",name:\"Jungle Pool (Con)\",              area:\"Jungle\",     status:\"Running\", pct:10, assignee:\"\"},\r\n  {id:\"t14\",name:\"Jungle Villa \u2013 10 Rooms\",        area:\"Jungle\",     status:\"Running\", pct:10, assignee:\"\"},\r\n  {id:\"t15\",name:\"Jungle Plumbing \u2013 20 Units\",     area:\"Jungle\",     status:\"Pending\", pct:0,  assignee:\"\"},\r\n  {id:\"t16\",name:\"Jungle Door \/ Window \u2013 20\",      area:\"Jungle\",     status:\"Pending\", pct:0,  assignee:\"\"},\r\n  {id:\"t17\",name:\"Jungle Color\",                   area:\"Jungle\",     status:\"Pending\", pct:0,  assignee:\"\"},\r\n  {id:\"t18\",name:\"Jungle Road\",                    area:\"Jungle\",     status:\"Pending\", pct:0,  assignee:\"\"},\r\n  {id:\"t19\",name:\"5 Staff Rooms Extended\",         area:\"Staff\",      status:\"Running\", pct:80, assignee:\"\"},\r\n  {id:\"t20\",name:\"Kid Pool (Tile Pending)\",        area:\"Pools\",      status:\"Running\", pct:85, assignee:\"\"},\r\n  {id:\"t21\",name:\"Backyard Garden\",                area:\"Site\",       status:\"Running\", pct:20, assignee:\"\"},\r\n  {id:\"t22\",name:\"Solar 10KW\",                     area:\"Site\",       status:\"Running\", pct:0,  assignee:\"\"},\r\n  {id:\"t23\",name:\"Fire Safety\",                    area:\"Site\",       status:\"Pending\", pct:0,  assignee:\"\"},\r\n];\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ STOCK DEFAULTS\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\nconst DEFAULT_MATERIALS=[\r\n  {id:\"m1\", name:\"Cement\",       category:\"\",      color:\"\",      unit:\"Bags\", openingStock:520, minStock:100, rate:0},\r\n  {id:\"m2\", name:\"Bricks\",       category:\"bricks\",color:\"\",      unit:\"Nos\",  openingStock:300, minStock:500, rate:0},\r\n  {id:\"m3\", name:\"Rati\",         category:\"\",      color:\"\",      unit:\"Tone\", openingStock:80,  minStock:10,  rate:0},\r\n  {id:\"m4\", name:\"Kapchi\",       category:\"\",      color:\"\",      unit:\"Tone\", openingStock:40,  minStock:5,   rate:0},\r\n  {id:\"m5\", name:\"TMT Sariya\",   category:\"8MM\",   color:\"\",      unit:\"Nos\",  openingStock:7,   minStock:2,   rate:0},\r\n  {id:\"m6\", name:\"TMT Sariya\",   category:\"10MM\",  color:\"\",      unit:\"Nos\",  openingStock:14,  minStock:2,   rate:0},\r\n  {id:\"m7\", name:\"TMT Sariya\",   category:\"12MM\",  color:\"\",      unit:\"Nos\",  openingStock:9,   minStock:2,   rate:0},\r\n  {id:\"m8\", name:\"TMT Sariya\",   category:\"16MM\",  color:\"\",      unit:\"Nos\",  openingStock:2,   minStock:2,   rate:0},\r\n  {id:\"m9\", name:\"Tiles 1\",      category:\"Mosaic\",color:\"\",      unit:\"Box\",  openingStock:779, minStock:50,  rate:0},\r\n  {id:\"m10\",name:\"Tile Cement\",  category:\"\",      color:\"\",      unit:\"Bag\",  openingStock:50,  minStock:10,  rate:0},\r\n  {id:\"m11\",name:\"Tiles 2\",      category:\"Tukdi\", color:\"White\", unit:\"Box\",  openingStock:30,  minStock:5,   rate:0},\r\n  {id:\"m12\",name:\"Tiles 2\",      category:\"Tukdi\", color:\"Blue\",  unit:\"Box\",  openingStock:5,   minStock:2,   rate:0},\r\n  {id:\"m13\",name:\"Tiles 2\",      category:\"Tukdi\", color:\"Brown\", unit:\"Box\",  openingStock:5,   minStock:2,   rate:0},\r\n  {id:\"m14\",name:\"Tiles 2\",      category:\"Tukdi\", color:\"Black\", unit:\"Box\",  openingStock:4,   minStock:2,   rate:0},\r\n  {id:\"m15\",name:\"POP\",          category:\"\",      color:\"\",      unit:\"Bag\",  openingStock:4,   minStock:5,   rate:0},\r\n  {id:\"m16\",name:\"COLOR\",        category:\"20L\",   color:\"Yellow\",unit:\"Tin\",  openingStock:5,   minStock:2,   rate:0},\r\n  {id:\"m17\",name:\"COLOR\",        category:\"20L\",   color:\"Blue\",  unit:\"Tin\",  openingStock:2,   minStock:2,   rate:0},\r\n  {id:\"m18\",name:\"COLOR\",        category:\"20L\",   color:\"Aster\", unit:\"Tin\",  openingStock:13,  minStock:2,   rate:0},\r\n  {id:\"m19\",name:\"Lopi\",         category:\"\",      color:\"\",      unit:\"Bag\",  openingStock:18,  minStock:5,   rate:0},\r\n  {id:\"m20\",name:\"Khilli\",       category:\"\",      color:\"\",      unit:\"KG\",   openingStock:6,   minStock:2,   rate:0},\r\n  {id:\"m21\",name:\"Banding Wire\", category:\"\",      color:\"\",      unit:\"KG\",   openingStock:6,   minStock:2,   rate:0},\r\n];\r\n\r\nconst AC={Club:\"#2563eb\",Jungle:\"#16a34a\",Pools:\"#0891b2\",Staff:\"#d97706\",\"Earth Wind\":\"#7c3aed\",Site:\"#ea580c\",New:\"#0f766e\"};\r\nconst AL={Club:\"#eff6ff\",Jungle:\"#f0fdf4\",Pools:\"#ecfeff\",Staff:\"#fffbeb\",\"Earth Wind\":\"#f5f3ff\",Site:\"#fff7ed\",New:\"#f0fdfa\"};\r\nconst AB={Club:\"#bfdbfe\",Jungle:\"#bbf7d0\",Pools:\"#a5f3fc\",Staff:\"#fde68a\",\"Earth Wind\":\"#ddd6fe\",Site:\"#fed7aa\",New:\"#99f6e4\"};\r\nconst AREA_LIST=[\"Club\",\"Jungle\",\"Pools\",\"Staff\",\"Earth Wind\",\"Site\",\"New\"];\r\nconst SC=[\"Pending\",\"Running\",\"Hold\",\"Done\"];\r\nconst SM={Done:{icon:\"\u2705\",color:\"#15803d\",bg:\"#dcfce7\",border:\"#86efac\"},Running:{icon:\"\u23f3\",color:\"#1d4ed8\",bg:\"#dbeafe\",border:\"#93c5fd\"},Pending:{icon:\"\ud83d\udd32\",color:\"#b91c1c\",bg:\"#fee2e2\",border:\"#fca5a5\"},Hold:{icon:\"\u23f8\ufe0f\",color:\"#6b21a8\",bg:\"#f3e8ff\",border:\"#d8b4fe\"}};\r\nconst DN=[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"];\r\n\r\nfunction toKey(y,m,d){return `${y}-${String(m+1).padStart(2,\"0\")}-${String(d).padStart(2,\"0\")}`;}\r\nfunction todayD(){const n=new Date();return new Date(n.getFullYear(),n.getMonth(),n.getDate());}\r\nfunction pDate(s){if(!s)return null;const[y,m,d]=s.split(\"-\").map(Number);return new Date(y,m-1,d);}\r\nfunction dDiff(a,b){return Math.round((b-a)\/864e5);}\r\nfunction fmtD(d){if(!d)return\"\";return d.toLocaleDateString(\"en-IN\",{day:\"2-digit\",month:\"short\"});}\r\nfunction uid(){return\"c\"+Math.random().toString(36).slice(2,9);}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ STOCK CRM COMPONENT\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\nfunction StockPage({year,month,setYear,setMonth,materials,setMaterials,stockEntries,setStockEntries,onSave}){\r\n  const now=new Date();\r\n  const dIM=new Date(year,month+1,0).getDate();\r\n  const days=Array.from({length:dIM},(_,i)=>i+1);\r\n  const todayKey=toKey(now.getFullYear(),now.getMonth(),now.getDate());\r\n  const mName=new Date(year,month).toLocaleString(\"en-IN\",{month:\"long\",year:\"numeric\"});\r\n  const [editCell,setEditCell]=useState(null);\r\n  const [editVal,setEditVal]=useState(\"\");\r\n  const [showAddMat,setShowAddMat]=useState(false);\r\n  const [delMat,setDelMat]=useState(null);\r\n  const [newMat,setNewMat]=useState({name:\"\",category:\"\",color:\"\",unit:\"Bag\",openingStock:0,minStock:0,rate:0});\r\n  const [filterCat,setFilterCat]=useState(\"All\");\r\n  const [editOpen,setEditOpen]=useState(null);\r\n  const [editField2,setEditField2]=useState(null);\r\n\r\n  const DN2=[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"];\r\n\r\n  const sKey=(mid,day)=>`${mid}-${toKey(year,month,day)}`;\r\n\r\n  const getEntry=(mid,day)=>stockEntries[sKey(mid,day)]||{issued:0,received:0};\r\n\r\n  const getClosing=(mid,upToDay)=>{\r\n    const mat=materials.find(m=>m.id===mid);\r\n    if(!mat)return 0;\r\n    const moKey=`${mid}-${year}-${String(month+1).padStart(2,\"0\")}-open`;\r\n    const open=stockEntries[moKey]?.opening??mat.openingStock;\r\n    let stock=open;\r\n    for(let d=1;d<=upToDay;d++){\r\n      const e=getEntry(mid,d);\r\n      stock+=((e.received||0)-(e.issued||0));\r\n    }\r\n    return stock;\r\n  };\r\n\r\n  const getTotalIssued=(mid)=>days.reduce((s,d)=>s+(getEntry(mid,d).issued||0),0);\r\n  const getTotalReceived=(mid)=>days.reduce((s,d)=>s+(getEntry(mid,d).received||0),0);\r\n\r\n  const getMonthOpen=(mid)=>{\r\n    const mat=materials.find(m=>m.id===mid);\r\n    const moKey=`${mid}-${year}-${String(month+1).padStart(2,\"0\")}-open`;\r\n    return stockEntries[moKey]?.opening??mat?.openingStock??0;\r\n  };\r\n\r\n  const setMonthOpen=(mid,val)=>{\r\n    const moKey=`${mid}-${year}-${String(month+1).padStart(2,\"0\")}-open`;\r\n    const ne={...stockEntries,[moKey]:{opening:parseInt(val)||0}};\r\n    setStockEntries(ne);onSave(ne);\r\n  };\r\n\r\n  const updateMatField=(mid,field,val)=>{\r\n    const nm=materials.map(m=>m.id===mid?{...m,[field]:val}:m);\r\n    setMaterials(nm);onSave(null,nm);setEditField2(null);\r\n  };\r\n\r\n  const updateEntry=(mid,day,type,val)=>{\r\n    const k=sKey(mid,day);\r\n    const cur=stockEntries[k]||{issued:0,received:0};\r\n    const ne={...stockEntries,[k]:{...cur,[type]:Math.max(0,parseInt(val)||0)}};\r\n    setStockEntries(ne);onSave(ne);\r\n    setEditCell(null);\r\n  };\r\n\r\n  const addMaterial=()=>{\r\n    if(!newMat.name.trim())return;\r\n    const m={id:uid(),...newMat,openingStock:parseInt(newMat.openingStock)||0,minStock:parseInt(newMat.minStock)||0,rate:parseFloat(newMat.rate)||0};\r\n    const nm=[...materials,m];setMaterials(nm);onSave(null,nm);\r\n    setNewMat({name:\"\",category:\"\",color:\"\",unit:\"Bag\",openingStock:0,minStock:0,rate:0});setShowAddMat(false);\r\n  };\r\n\r\n  const deleteMaterial=(mid)=>{const nm=materials.filter(m=>m.id!==mid);setMaterials(nm);onSave(null,nm);setDelMat(null);};\r\n\r\n  const cats=[\"All\",...[...new Set(materials.map(m=>m.name))].sort()];\r\n  const filtered=filterCat===\"All\"?materials:materials.filter(m=>m.name===filterCat);\r\n\r\n  const TH2={position:\"sticky\",top:0,zIndex:10,background:\"#fff\",borderBottom:\"2px solid #e2e8f0\",fontWeight:700,whiteSpace:\"nowrap\",fontSize:11};\r\n  const INP2={width:\"100%\",background:\"#f8fafc\",border:\"1.5px solid #e2e8f0\",color:\"#0f172a\",fontFamily:\"inherit\",fontSize:12,padding:\"5px 8px\",borderRadius:5,outline:\"none\",boxSizing:\"border-box\"};\r\n  const LBL2={display:\"block\",fontSize:11,fontWeight:700,color:\"#475569\",marginBottom:4};\r\n\r\n  return(\r\n    <div style={{flex:1,display:\"flex\",flexDirection:\"column\",overflow:\"hidden\",background:\"#f1f5f9\"}}>\r\n\r\n      {\/* Stock sub-header *\/}\r\n      <div style={{padding:\"8px 14px\",background:\"#fff\",borderBottom:\"1px solid #e2e8f0\",display:\"flex\",gap:8,flexWrap:\"wrap\",flexShrink:0,alignItems:\"center\"}}>\r\n        <div style={{display:\"flex\",gap:6,flexWrap:\"wrap\"}}>\r\n          {cats.map(c=>(\r\n            <button key={c} onClick={()=>setFilterCat(c)} style={{padding:\"3px 10px\",borderRadius:16,border:\"1px solid\",borderColor:filterCat===c?\"#0891b2\":\"#e2e8f0\",background:filterCat===c?\"#0891b2\":\"#f8fafc\",color:filterCat===c?\"#fff\":\"#475569\",cursor:\"pointer\",fontSize:10,fontWeight:700,fontFamily:\"inherit\"}}>{c}<\/button>\r\n          ))}\r\n        <\/div>\r\n        <button onClick={()=>setShowAddMat(true)} style={{marginLeft:\"auto\",background:\"#0f172a\",color:\"#fff\",border:\"none\",borderRadius:6,padding:\"5px 12px\",fontSize:11,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>\uff0b Add Material<\/button>\r\n        <div style={{display:\"flex\",gap:6,fontSize:10}}>\r\n          <span style={{background:\"#fee2e2\",color:\"#b91c1c\",padding:\"2px 7px\",borderRadius:5,fontWeight:700,border:\"1px solid #fca5a5\"}}>\ud83d\udd34 Low Stock<\/span>\r\n          <span style={{background:\"#f0fdf4\",color:\"#15803d\",padding:\"2px 7px\",borderRadius:5,fontWeight:700,border:\"1px solid #86efac\"}}>\ud83d\udfe2 OK<\/span>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      {\/* Add Material Modal *\/}\r\n      {showAddMat&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:300,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>setShowAddMat(false)}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:24,width:420,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:16,fontWeight:800,color:\"#0f172a\",marginBottom:16}}>\ud83d\udce6 Add Material<\/div>\r\n            <div style={{display:\"grid\",gridTemplateColumns:\"1fr 1fr\",gap:10,marginBottom:10}}>\r\n              <div><label style={LBL2}>Material Name *<\/label><input autoFocus value={newMat.name} onChange={e=>setNewMat(p=>({...p,name:e.target.value}))} style={INP2} placeholder=\"e.g. Cement\"\/><\/div>\r\n              <div><label style={LBL2}>Category \/ Size<\/label><input value={newMat.category} onChange={e=>setNewMat(p=>({...p,category:e.target.value}))} style={INP2} placeholder=\"e.g. 8MM, 20L\"\/><\/div>\r\n              <div><label style={LBL2}>Color<\/label><input value={newMat.color} onChange={e=>setNewMat(p=>({...p,color:e.target.value}))} style={INP2} placeholder=\"e.g. Yellow\"\/><\/div>\r\n              <div><label style={LBL2}>Unit<\/label>\r\n                <select value={newMat.unit} onChange={e=>setNewMat(p=>({...p,unit:e.target.value}))} style={INP2}>\r\n                  {[\"Bags\",\"Nos\",\"Tone\",\"Box\",\"Bag\",\"Tin\",\"KG\",\"Litre\",\"Pcs\",\"Set\",\"Roll\",\"Mtr\"].map(u=><option key={u}>{u}<\/option>)}\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL2}>Opening Stock<\/label><input type=\"number\" min={0} value={newMat.openingStock} onChange={e=>setNewMat(p=>({...p,openingStock:e.target.value}))} style={INP2}\/><\/div>\r\n              <div><label style={LBL2}>Min Stock (alert below)<\/label><input type=\"number\" min={0} value={newMat.minStock} onChange={e=>setNewMat(p=>({...p,minStock:e.target.value}))} style={INP2}\/><\/div>\r\n              <div><label style={LBL2}>Rate per Unit (\u20b9)<\/label><input type=\"number\" min={0} value={newMat.rate} onChange={e=>setNewMat(p=>({...p,rate:e.target.value}))} style={INP2}\/><\/div>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\",marginTop:14}}>\r\n              <button onClick={()=>setShowAddMat(false)} style={{background:\"#f8fafc\",border:\"1px solid #e2e8f0\",color:\"#475569\",borderRadius:6,padding:\"7px 16px\",fontSize:12,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n              <button onClick={addMaterial} disabled={!newMat.name.trim()} style={{background:newMat.name.trim()?\"#0f172a\":\"#cbd5e1\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"7px 20px\",fontSize:12,fontWeight:700,cursor:newMat.name.trim()?\"pointer\":\"not-allowed\",fontFamily:\"inherit\"}}>Add<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* Delete confirm *\/}\r\n      {delMat&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:300,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>setDelMat(null)}>\r\n          <div style={{background:\"#fff\",borderRadius:12,padding:22,width:300,boxShadow:\"0 20px 60px #00000030\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:14,fontWeight:800,color:\"#b91c1c\",marginBottom:8}}>\ud83d\uddd1\ufe0f Delete Material?<\/div>\r\n            <div style={{fontSize:12,color:\"#475569\",marginBottom:16}}><b>\"{materials.find(m=>m.id===delMat)&&(materials.find(m=>m.id===delMat).name+(materials.find(m=>m.id===delMat).category?\" - \"+materials.find(m=>m.id===delMat).category:\"\")+(materials.find(m=>m.id===delMat).color?\" \"+materials.find(m=>m.id===delMat).color:\"\"))}\"<\/b> and all its stock data will be removed.<\/div>\r\n            <div style={{display:\"flex\",gap:8,justifyContent:\"flex-end\"}}>\r\n              <button onClick={()=>setDelMat(null)} style={{background:\"#f8fafc\",border:\"1px solid #e2e8f0\",color:\"#475569\",borderRadius:6,padding:\"6px 14px\",fontSize:11,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n              <button onClick={()=>deleteMaterial(delMat)} style={{background:\"#dc2626\",color:\"#fff\",border:\"none\",borderRadius:6,padding:\"6px 16px\",fontSize:11,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>Delete<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* Stock Grid *\/}\r\n      <div style={{flex:1,overflow:\"auto\"}}>\r\n        <table style={{borderCollapse:\"collapse\",minWidth:\"100%\",background:\"#fff\"}}>\r\n          <thead>\r\n            <tr>\r\n              <th style={{...TH2,minWidth:140,maxWidth:140,position:\"sticky\",left:0,zIndex:20,background:\"#fff\",textAlign:\"left\",padding:\"8px 10px\",borderRight:\"1px solid #e2e8f0\"}}>Material<\/th>\r\n              <th style={{...TH2,minWidth:60,background:\"#f8fafc\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 4px\",textAlign:\"center\"}}>Unit<\/th>\r\n              <th style={{...TH2,minWidth:55,background:\"#fffbeb\",borderRight:\"1px solid #fde68a\",padding:\"5px 4px\",textAlign:\"center\"}}>Rate<br\/>\u20b9<\/th>\r\n              <th style={{...TH2,minWidth:65,background:\"#eff6ff\",borderRight:\"2px solid #e2e8f0\",padding:\"5px 4px\",textAlign:\"center\"}}>Closing<br\/>Stock<\/th>\r\n              {days.map(d=>{\r\n                const dk=toKey(year,month,d);const isT=dk===todayKey;const isWE=[0,6].includes(new Date(year,month,d).getDay());\r\n                return(\r\n                  <th key={d} colSpan={2} style={{...TH2,minWidth:72,padding:\"2px 1px\",background:isT?\"#eff6ff\":isWE?\"#fafafa\":\"#fff\",borderRight:`2px solid ${isT?\"#93c5fd\":\"#e2e8f0\"}`,textAlign:\"center\"}}>\r\n                    <div style={{fontSize:8,color:isT?\"#2563eb\":isWE?\"#64748b\":\"#475569\",fontWeight:isT?800:600}}>{DN2[new Date(year,month,d).getDay()]}<\/div>\r\n                    <div style={{fontSize:12,fontWeight:800,color:isT?\"#2563eb\":isWE?\"#475569\":\"#1e293b\"}}>{d}<\/div>\r\n                    <div style={{display:\"flex\",gap:0,justifyContent:\"center\"}}>\r\n                      <span style={{fontSize:7,color:\"#16a34a\",fontWeight:700,padding:\"0 2px\"}}>IN<\/span>\r\n                      <span style={{fontSize:7,color:\"#dc2626\",fontWeight:700,padding:\"0 2px\"}}>OUT<\/span>\r\n                    <\/div>\r\n                  <\/th>\r\n                );\r\n              })}\r\n              <th style={{...TH2,minWidth:70,background:\"#fffbeb\",borderRight:\"1px solid #fde68a\",padding:\"5px 4px\",textAlign:\"center\"}}>Opening<br\/>Stock<\/th>\r\n              <th style={{...TH2,minWidth:58,background:\"#f0fdf4\",borderRight:\"1px solid #86efac\",padding:\"5px 4px\",textAlign:\"center\"}}>Total<br\/>IN<\/th>\r\n              <th style={{...TH2,minWidth:58,background:\"#fef2f2\",borderRight:\"1px solid #fecaca\",padding:\"5px 4px\",textAlign:\"center\"}}>Total<br\/>OUT<\/th>\r\n              <th style={{...TH2,minWidth:60,background:\"#fef2f2\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 4px\",textAlign:\"center\"}}>Pending<br\/>Stock<\/th>\r\n              <th style={{...TH2,minWidth:30,background:\"#fff\"}}\/>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody>\r\n            {filtered.map((mat,mi)=>{\r\n              const open=getMonthOpen(mat.id);\r\n              const totIn=getTotalReceived(mat.id);\r\n              const totOut=getTotalIssued(mat.id);\r\n              const closing=open+totIn-totOut;\r\n              const pending=Math.max(0,(mat.minStock||0)-closing);\r\n              const isLow=closing<=(mat.minStock||0);\r\n              const isEditOpen=editOpen===mat.id;\r\n              const displayName=mat.name+(mat.category?\" \u2013 \"+mat.category:\"\")+(mat.color?\" (\"+mat.color+\")\":\"\");\r\n              return(\r\n                <tr key={mat.id} style={{background:mi%2===0?\"#fff\":\"#fafcff\"}}>\r\n                  {\/* Material Name \u2014 editable *\/}\r\n                  <td style={{position:\"sticky\",left:0,zIndex:5,background:isLow?\"#fef2f2\":\"#f8fafc\",borderLeft:`3px solid ${isLow?\"#dc2626\":\"#0891b2\"}`,borderRight:\"1px solid #e2e8f0\",borderBottom:\"1px solid #f1f5f9\",padding:\"5px 8px\",minWidth:140,maxWidth:140,cursor:\"pointer\"}} onClick={()=>setEditField2(editField2?.mid===mat.id&&editField2?.field===\"name\"?null:{mid:mat.id,field:\"name\"})}>\r\n                    {editField2?.mid===mat.id&&editField2?.field===\"name\"?(\r\n                      <input autoFocus type=\"text\" defaultValue={mat.name} onBlur={e=>{if(e.target.value.trim())updateMatField(mat.id,\"name\",e.target.value.trim());else setEditField2(null);}} onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){if(e.target.value.trim())updateMatField(mat.id,\"name\",e.target.value.trim());else setEditField2(null);}}} style={{width:\"100%\",background:\"#fff\",border:\"2px solid #0891b2\",color:\"#0f172a\",fontFamily:\"inherit\",fontSize:12,fontWeight:700,padding:\"2px 5px\",borderRadius:4,outline:\"none\",boxSizing:\"border-box\"}}\/>\r\n                    ):(\r\n                      <div style={{fontSize:12,fontWeight:700,color:\"#0f172a\",whiteSpace:\"nowrap\",overflow:\"hidden\",textOverflow:\"ellipsis\"}} title={displayName}>{displayName}<\/div>\r\n                    )}\r\n                    {isLow&&<div style={{fontSize:9,color:\"#dc2626\",fontWeight:700}}>\ud83d\udd34 Low stock!<\/div>}\r\n                  <\/td>\r\n                  {\/* Unit \u2014 editable *\/}\r\n                  <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:\"1px solid #f1f5f9\",textAlign:\"center\",padding:\"4px 2px\",background:\"#f8fafc\",cursor:\"pointer\"}} onClick={()=>setEditField2(editField2?.mid===mat.id&&editField2?.field===\"unit\"?null:{mid:mat.id,field:\"unit\"})}>\r\n                    {editField2?.mid===mat.id&&editField2?.field===\"unit\"?(\r\n                      <select autoFocus value={mat.unit} onChange={e=>updateMatField(mat.id,\"unit\",e.target.value)} onBlur={()=>setEditField2(null)} style={{width:\"100%\",background:\"#fff\",border:\"2px solid #0891b2\",color:\"#0f172a\",fontFamily:\"inherit\",fontSize:11,fontWeight:600,textAlign:\"center\",borderRadius:4,padding:\"2px 0\",outline:\"none\",cursor:\"pointer\"}}>\r\n                        {[\"Bags\",\"Nos\",\"Tone\",\"Box\",\"Bag\",\"Tin\",\"KG\",\"Litre\",\"Pcs\",\"Set\",\"Roll\",\"Mtr\",\"Sqft\",\"Packet\"].map(u=><option key={u} value={u}>{u}<\/option>)}\r\n                      <\/select>\r\n                    ):(\r\n                      <div style={{fontSize:11,color:\"#475569\",fontWeight:600}}>{mat.unit}<\/div>\r\n                    )}\r\n                  <\/td>\r\n                  {\/* Rate \u2014 editable *\/}\r\n                  <td style={{borderRight:\"1px solid #fde68a\",borderBottom:\"1px solid #f1f5f9\",background:\"#fffbeb55\",textAlign:\"center\",padding:\"3px 4px\",cursor:\"pointer\"}} onClick={()=>setEditField2(editField2?.mid===mat.id&&editField2?.field===\"rate\"?null:{mid:mat.id,field:\"rate\"})}>\r\n                    {editField2?.mid===mat.id&&editField2?.field===\"rate\"?(\r\n                      <input autoFocus type=\"number\" min={0} defaultValue={mat.rate} onBlur={e=>{updateMatField(mat.id,\"rate\",parseFloat(e.target.value)||0);}} onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){updateMatField(mat.id,\"rate\",parseFloat(e.target.value)||0);}}} style={{width:52,background:\"#fff\",border:\"2px solid #d97706\",color:\"#92400e\",fontFamily:\"inherit\",fontSize:11,fontWeight:700,textAlign:\"center\",borderRadius:4,padding:\"2px 0\",outline:\"none\"}}\/>\r\n                    ):(\r\n                      <div style={{fontSize:11,color:\"#92400e\",fontWeight:600}}>{mat.rate>0?\"\u20b9\"+mat.rate:\"+ add\"}<\/div>\r\n                    )}\r\n                  <\/td>\r\n                  {\/* Closing Stock *\/}\r\n                  <td style={{borderRight:\"2px solid #e2e8f0\",borderBottom:\"1px solid #f1f5f9\",background:isLow?\"#fef2f2\":\"#eff6ff\",textAlign:\"center\",padding:\"4px 4px\"}}>\r\n                    <div style={{fontSize:15,fontWeight:800,color:isLow?\"#dc2626\":\"#1d4ed8\"}}>{closing}<\/div>\r\n                  <\/td>\r\n                  {\/* Day cells \u2014 IN and OUT *\/}\r\n                  {days.map(d=>{\r\n                    const dk=toKey(year,month,d);const isT=dk===todayKey;\r\n                    const e=getEntry(mat.id,d);\r\n                    const isWE=[0,6].includes(new Date(year,month,d).getDay());\r\n                    const isEditIn=editCell&&editCell.mid===mat.id&&editCell.day===d&&editCell.type===\"received\";\r\n                    const isEditOut=editCell&&editCell.mid===mat.id&&editCell.day===d&&editCell.type===\"issued\";\r\n                    const dayBg=isT?\"#eff6ff\":isWE?\"#fafafa\":\"#fff\";\r\n                    return(\r\n                      <React.Fragment key={d}>\r\n                        <td style={{borderRight:\"1px solid #f0fdf4\",borderBottom:\"1px solid #f1f5f9\",background:e.received>0?\"#f0fdf4\":dayBg,padding:0,minWidth:36,maxWidth:36,textAlign:\"center\",verticalAlign:\"middle\",cursor:\"pointer\"}}\r\n                          onClick={()=>{setEditCell({mid:mat.id,day:d,type:\"received\"});setEditVal(e.received||\"\");}}>\r\n                          {isEditIn?(\r\n                            <input autoFocus type=\"number\" min={0} value={editVal} onChange={ex=>setEditVal(ex.target.value)}\r\n                              onBlur={()=>updateEntry(mat.id,d,\"received\",editVal)}\r\n                              onKeyDown={ex=>{if([\"Enter\",\"Tab\"].includes(ex.key))updateEntry(mat.id,d,\"received\",editVal);if(ex.key===\"Escape\")setEditCell(null);}}\r\n                              style={{width:34,background:\"#fff\",border:\"2px solid #16a34a\",color:\"#15803d\",fontFamily:\"inherit\",fontSize:11,fontWeight:700,textAlign:\"center\",borderRadius:3,padding:\"2px 0\",outline:\"none\"}}\r\n                            \/>\r\n                          ):(\r\n                            <div style={{padding:\"4px 1px\",minHeight:28,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}}>\r\n                              {e.received>0?<span style={{fontSize:11,fontWeight:800,color:\"#15803d\"}}>+{e.received}<\/span>:<span style={{fontSize:9,color:\"#d1fae5\",opacity:0.5}}>+<\/span>}\r\n                            <\/div>\r\n                          )}\r\n                        <\/td>\r\n                        <td style={{borderRight:`2px solid ${isT?\"#93c5fd\":\"#e2e8f0\"}`,borderBottom:\"1px solid #f1f5f9\",background:e.issued>0?\"#fef2f2\":dayBg,padding:0,minWidth:36,maxWidth:36,textAlign:\"center\",verticalAlign:\"middle\",cursor:\"pointer\"}}\r\n                          onClick={()=>{setEditCell({mid:mat.id,day:d,type:\"issued\"});setEditVal(e.issued||\"\");}}>\r\n                          {isEditOut?(\r\n                            <input autoFocus type=\"number\" min={0} value={editVal} onChange={ex=>setEditVal(ex.target.value)}\r\n                              onBlur={()=>updateEntry(mat.id,d,\"issued\",editVal)}\r\n                              onKeyDown={ex=>{if([\"Enter\",\"Tab\"].includes(ex.key))updateEntry(mat.id,d,\"issued\",editVal);if(ex.key===\"Escape\")setEditCell(null);}}\r\n                              style={{width:34,background:\"#fff\",border:\"2px solid #dc2626\",color:\"#dc2626\",fontFamily:\"inherit\",fontSize:11,fontWeight:700,textAlign:\"center\",borderRadius:3,padding:\"2px 0\",outline:\"none\"}}\r\n                            \/>\r\n                          ):(\r\n                            <div style={{padding:\"4px 1px\",minHeight:28,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}}>\r\n                              {e.issued>0?<span style={{fontSize:11,fontWeight:800,color:\"#dc2626\"}}>-{e.issued}<\/span>:<span style={{fontSize:9,color:\"#fecaca\",opacity:0.5}}>-<\/span>}\r\n                            <\/div>\r\n                          )}\r\n                        <\/td>\r\n                      <\/React.Fragment>\r\n                    );\r\n                  })}\r\n                  {\/* Opening Stock \u2014 editable *\/}\r\n                  <td style={{borderRight:\"1px solid #fde68a\",borderBottom:\"1px solid #f1f5f9\",background:\"#fffbeb55\",textAlign:\"center\",padding:\"3px 4px\",cursor:\"pointer\"}} onClick={()=>setEditOpen(isEditOpen?null:mat.id)}>\r\n                    {isEditOpen?(\r\n                      <input autoFocus type=\"number\" min={0} defaultValue={open}\r\n                        onBlur={e=>{setMonthOpen(mat.id,e.target.value);setEditOpen(null);}}\r\n                        onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){setMonthOpen(mat.id,e.target.value);setEditOpen(null);}}}\r\n                        style={{width:52,background:\"#fff\",border:\"2px solid #d97706\",color:\"#92400e\",fontFamily:\"inherit\",fontSize:12,fontWeight:700,textAlign:\"center\",borderRadius:4,padding:\"2px 0\",outline:\"none\"}}\r\n                      \/>\r\n                    ):(\r\n                      <div style={{fontSize:14,fontWeight:800,color:\"#92400e\"}}>{open}<\/div>\r\n                    )}\r\n                  <\/td>\r\n                  {\/* Totals *\/}\r\n                  <td style={{borderRight:\"1px solid #86efac\",borderBottom:\"1px solid #f1f5f9\",background:\"#f0fdf4\",textAlign:\"center\",padding:\"4px 4px\"}}>\r\n                    <div style={{fontSize:14,fontWeight:800,color:\"#15803d\"}}>{totIn>0?\"+\"+totIn:\"\u2014\"}<\/div>\r\n                  <\/td>\r\n                  <td style={{borderRight:\"1px solid #fecaca\",borderBottom:\"1px solid #f1f5f9\",background:\"#fef2f2\",textAlign:\"center\",padding:\"4px 4px\"}}>\r\n                    <div style={{fontSize:14,fontWeight:800,color:\"#dc2626\"}}>{totOut>0?\"-\"+totOut:\"\u2014\"}<\/div>\r\n                  <\/td>\r\n                  <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:\"1px solid #f1f5f9\",background:pending>0?\"#fef2f2\":\"#f0fdf4\",textAlign:\"center\",padding:\"4px 4px\"}}>\r\n                    <div style={{fontSize:13,fontWeight:800,color:pending>0?\"#dc2626\":\"#15803d\"}}>{pending>0?pending:\"\u2713\"}<\/div>\r\n                  <\/td>\r\n                  <td style={{borderBottom:\"1px solid #f1f5f9\",background:\"#fff\",textAlign:\"center\",padding:\"0 2px\"}}>\r\n                    <button onClick={()=>setDelMat(mat.id)} style={{background:\"none\",border:\"none\",cursor:\"pointer\",color:\"#fca5a5\",fontSize:13,padding:\"4px\",opacity:0.4}}\r\n                      onMouseEnter={e=>e.currentTarget.style.opacity=1} onMouseLeave={e=>e.currentTarget.style.opacity=0.4}>\u2715<\/button>\r\n                  <\/td>\r\n                <\/tr>\r\n              );\r\n            })}\r\n          <\/tbody>\r\n        <\/table>\r\n      <\/div>\r\n\r\n      {\/* Stock footer *\/}\r\n      <div style={{background:\"#fff\",borderTop:\"1px solid #e2e8f0\",padding:\"5px 14px\",display:\"flex\",gap:14,alignItems:\"center\",flexShrink:0}}>\r\n        <div style={{display:\"flex\",gap:12,fontSize:10,color:\"#94a3b8\"}}>\r\n          <span><b style={{color:\"#15803d\"}}>+IN<\/b> = click green cell to enter received qty<\/span>\r\n          <span><b style={{color:\"#dc2626\"}}>-OUT<\/b> = click red cell to enter issued qty<\/span>\r\n          <span><b style={{color:\"#0891b2\"}}>Name\/Unit<\/b> = click to edit<\/span>\r\n          <span><b style={{color:\"#d97706\"}}>Opening<\/b> = click to edit month opening stock<\/span>\r\n        <\/div>\r\n        <div style={{marginLeft:\"auto\",fontSize:10,color:\"#94a3b8\"}}>{materials.length} materials<\/div>\r\n      <\/div>\r\n    <\/div>\r\n  );\r\n}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ AGENCY PAGE\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\nfunction AgencyPage({contractors,setContractors,bills,setBills,customAreas,setCustomAreas,trades,setTrades,onSave,year,month}){\r\n  const now=new Date();\r\n  const mName=new Date(year,month).toLocaleString(\"en-IN\",{month:\"long\",year:\"numeric\"});\r\n  const [showAddCon,setShowAddCon]=useState(false);\r\n  const [editConId,setEditConId]=useState(null);\r\n  const [editConData,setEditConData]=useState(null);\r\n  const [newCon,setNewCon]=useState({name:\"\",phone:\"\",trade:\"\",assignedSite:\"\",status:\"New\"});\r\n  const [showBillModal,setShowBillModal]=useState(false);\r\n  const [newBill,setNewBill]=useState({contractorId:\"\",invoiceNo:\"\",amount:\"\",date:\"\",trade:\"\",assignedSite:\"\",firstPaid:\"\",firstPaidDate:\"\"});\r\n  const [editBillId,setEditBillId]=useState(null);\r\n  const [editBillData,setEditBillData]=useState(null);\r\n  const [showPayModal,setShowPayModal]=useState(false);\r\n  const [payBillId,setPayBillId]=useState(null);\r\n  const [newPay,setNewPay]=useState({paid:\"\",paidDate:\"\"});\r\n  const [editPayData,setEditPayData]=useState(null);\r\n  const [statusFilter,setStatusFilter]=useState(null);\r\n  const [agencyFilter,setAgencyFilter]=useState(null);\r\n  const [billConFilter,setBillConFilter]=useState(null);\r\n\r\n  const STATUS_OPTS=[\"New\",\"Running\",\"Hold\",\"Reject\"];\r\n  const ST_COL={New:\"#2563eb\",Running:\"#15803d\",Hold:\"#d97706\",Reject:\"#dc2626\"};\r\n  const ST_BG={New:\"#eff6ff\",Running:\"#f0fdf4\",Hold:\"#fffbeb\",Reject:\"#fef2f2\"};\r\n\r\n  const INP={width:\"100%\",background:\"#f8fafc\",border:\"1.5px solid #e2e8f0\",color:\"#0f172a\",fontFamily:\"inherit\",fontSize:14,padding:\"8px 10px\",borderRadius:6,outline:\"none\",boxSizing:\"border-box\"};\r\n  const LBL={display:\"block\",fontSize:13,fontWeight:700,color:\"#475569\",marginBottom:4};\r\n\r\n  const addCon=()=>{\r\n    if(!newCon.name.trim())return;\r\n    const c={id:uid(),...newCon};\r\n    const nc=[...contractors,c];setContractors(nc);onSave(nc,bills,trades,customAreas);\r\n    setNewCon({name:\"\",phone:\"\",trade:\"\",assignedSite:\"\",status:\"New\"});setShowAddCon(false);\r\n  };\r\n  const updateCon=(id,field,val)=>{\r\n    const nc=contractors.map(c=>c.id===id?{...c,[field]:val}:c);\r\n    setContractors(nc);onSave(nc,bills,trades,customAreas);\r\n  };\r\n  const deleteCon=(id)=>{\r\n    const nc=contractors.filter(c=>c.id!==id);\r\n    setContractors(nc);onSave(nc,bills,trades,customAreas);\r\n  };\r\n\r\n  const addBill=()=>{\r\n    if(!newBill.contractorId||!newBill.invoiceNo.trim())return;\r\n    const c=contractors.find(x=>x.id===newBill.contractorId);\r\n    const payments=[];\r\n    if(newBill.firstPaid&&parseFloat(newBill.firstPaid)>0)payments.push({id:uid(),paid:parseFloat(newBill.firstPaid),paidDate:newBill.firstPaidDate||toKey(now.getFullYear(),now.getMonth(),now.getDate())});\r\n    const b={id:uid(),contractorId:newBill.contractorId,invoiceNo:newBill.invoiceNo.trim(),amount:parseFloat(newBill.amount)||0,date:newBill.date||toKey(now.getFullYear(),now.getMonth(),now.getDate()),trade:c?c.trade:newBill.trade,assignedSite:newBill.assignedSite,payments};\r\n    const nb=[...bills,b];setBills(nb);onSave(contractors,nb,trades,customAreas);\r\n    setNewBill({contractorId:\"\",invoiceNo:\"\",amount:\"\",date:\"\",trade:\"\",assignedSite:\"\",firstPaid:\"\",firstPaidDate:\"\"});setShowBillModal(false);\r\n  };\r\n  const deleteBill=(id)=>{const nb=bills.filter(b=>b.id!==id);setBills(nb);onSave(contractors,nb,trades,customAreas);};\r\n  const addPayment=()=>{\r\n    if(!payBillId||!newPay.paid)return;\r\n    const nb=bills.map(b=>{\r\n      if(b.id!==payBillId)return b;\r\n      let payArr=b.payments||[];\r\n      if(!b.payments&&b.paid>0)payArr=[{id:uid(),paid:parseFloat(b.paid)||0,paidDate:b.date||\"\"}];\r\n      return{...b,payments:[...payArr,{id:uid(),paid:parseFloat(newPay.paid),paidDate:newPay.paidDate||toKey(now.getFullYear(),now.getMonth(),now.getDate())}]};\r\n    });\r\n    setBills(nb);onSave(contractors,nb,trades,customAreas);setPayBillId(null);setShowPayModal(false);setNewPay({paid:\"\",paidDate:\"\"});\r\n  };\r\n  const billTotalPaid=(b)=>{if(b.payments)return b.payments.reduce((s,p)=>s+(p.paid||0),0);return parseFloat(b.paid)||0;};\r\n  const billPending=(b)=>(b.amount||0)-billTotalPaid(b);\r\n  const updateBill=()=>{\r\n    if(!editBillId||!editBillData)return;\r\n    const nb=bills.map(b=>b.id===editBillId?{...b,...editBillData,amount:parseFloat(editBillData.amount)||0}:b);\r\n    setBills(nb);onSave(contractors,nb,trades,customAreas);setEditBillId(null);setEditBillData(null);\r\n  };\r\n  const updatePayment=(billId,payId,paid,paidDate)=>{\r\n    const nb=bills.map(b=>b.id===billId?{...b,payments:b.payments.map(p=>p.id===payId?{...p,paid:parseFloat(paid)||0,paidDate}:p)}:b);\r\n    setBills(nb);onSave(contractors,nb,trades,customAreas);setEditPayData(null);\r\n  };\r\n\r\n  const allSites=[...AREA_LIST,...customAreas];\r\n  const conName=(id)=>{const c=contractors.find(x=>x.id===id);return c?c.name:\"\u2014\";};\r\n  const filteredCons=contractors.filter(c=>(!statusFilter||statusFilter===\"__all__\"||c.status===statusFilter)&&(!agencyFilter||agencyFilter===\"__all__\"||c.trade===agencyFilter));\r\n  const totBills=bills.reduce((s,b)=>s+(b.amount||0),0);\r\n  const totPaid=bills.reduce((s,b)=>s+billTotalPaid(b),0);\r\n\r\n  return(\r\n    <div style={{flex:1,display:\"flex\",flexDirection:\"column\",overflow:\"hidden\",background:\"#f1f5f9\"}}>\r\n\r\n      {\/* \u2500\u2500 Compact header with totals \u2500\u2500 *\/}\r\n      <div style={{padding:\"8px 14px\",background:\"#fff\",borderBottom:\"1px solid #e2e8f0\",display:\"flex\",flexShrink:0,flexWrap:\"wrap\",gap:6,alignItems:\"center\"}}>\r\n        <span style={{fontSize:14,fontWeight:800,color:\"#1e293b\"}}>\ud83d\udc65 Agency<\/span>\r\n        <span style={{background:\"#f3e8ff\",color:\"#7c3aed\",padding:\"3px 12px\",borderRadius:10,fontSize:13,fontWeight:700}}>{contractors.length} contractors<\/span>\r\n        <span style={{background:\"#fffbeb\",color:\"#d97706\",padding:\"3px 12px\",borderRadius:10,fontSize:13,fontWeight:700}}>\u20b9{totBills} \/ \u20b9{totPaid}<\/span>\r\n      <\/div>\r\n\r\n      {\/* \u2500\u2500 Side-by-side: Contacts left, Bills right \u2500\u2500 *\/}\r\n      <div style={{flex:1,display:\"flex\",flexDirection:\"row\",gap:12,padding:\"8px 12px\",overflow:\"hidden\"}}>\r\n\r\n        {\/* \u2500\u2500 CONTACTS (left) \u2500\u2500 *\/}\r\n        <div style={{flex:1,display:\"flex\",flexDirection:\"column\",background:\"#fff\",borderRadius:10,border:\"1px solid #e2e8f0\",overflow:\"hidden\",boxShadow:\"0 1px 3px #00000008\"}}>\r\n          <div style={{padding:\"8px 12px\",borderBottom:\"1px solid #e2e8f0\",display:\"flex\",justifyContent:\"space-between\",alignItems:\"center\",flexShrink:0}}>\r\n            <span style={{fontSize:15,fontWeight:700,color:\"#7c3aed\",display:\"flex\",alignItems:\"center\",gap:6}}>\ud83d\udccb Contractors <button onClick={()=>setShowAddCon(true)} style={{background:\"#7c3aed\",color:\"#fff\",border:\"none\",borderRadius:6,padding:\"3px 12px\",fontSize:13,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\",lineHeight:1.5}}>\uff0b Add<\/button><\/span>\r\n            <span style={{fontSize:13,color:\"#94a3b8\"}}>Click phone to edit \u00b7 Click pending to filter<\/span>\r\n          <\/div>\r\n          <div style={{flex:1,overflowY:\"auto\"}}>\r\n          {contractors.length===0?(\r\n            <div style={{padding:24,textAlign:\"center\",color:\"#94a3b8\",fontSize:14}}>No contractors yet.<\/div>\r\n          ):(\r\n            <div>\r\n              {\/* Header row with select dropdowns for Status & Agency filter *\/}\r\n              <div style={{display:\"flex\",alignItems:\"center\",gap:6,padding:\"8px 12px\",fontSize:13,fontWeight:700,color:\"#94a3b8\",textTransform:\"uppercase\",letterSpacing:\"0.5px\",borderBottom:\"2px solid #e2e8f0\",background:\"#f8fafc\"}}>\r\n                <div style={{flex:2,minWidth:0}}>Name<\/div>\r\n                <div style={{flex:1.5,minWidth:0}}>Phone<\/div>\r\n                <div style={{flex:1,minWidth:0}}>\r\n                  <select value={statusFilter||\"\"} onChange={e=>{setStatusFilter(e.target.value||null);}} style={{width:\"100%\",border:\"1px solid #cbd5e1\",borderRadius:4,padding:\"2px 6px\",fontSize:13,fontWeight:600,fontFamily:\"inherit\",color:statusFilter?\"#7c3aed\":\"#94a3b8\",background:\"#fff\",outline:\"none\",cursor:\"pointer\"}}>\r\n                    <option value=\"\">Status<\/option>\r\n                    <option value=\"__all__\">All<\/option>\r\n                    {STATUS_OPTS.map(s=><option key={s} value={s}>{s}<\/option>)}\r\n                  <\/select>\r\n                <\/div>\r\n                <div style={{flex:1.2,minWidth:0}}>\r\n                  <select value={agencyFilter||\"\"} onChange={e=>{const v=e.target.value;if(v===\"__add__\"){setAgencyFilter(null);const t=prompt(\"Enter new agency:\");if(t&&t.trim()){const nt=[...trades,t.trim()];setTrades(nt);setAgencyFilter(t.trim());onSave(null,null,nt);}}else{setAgencyFilter(v||null);}}} style={{width:\"100%\",border:\"1px solid #cbd5e1\",borderRadius:4,padding:\"2px 6px\",fontSize:13,fontWeight:600,fontFamily:\"inherit\",color:agencyFilter?\"#7c3aed\":\"#94a3b8\",background:\"#fff\",outline:\"none\",cursor:\"pointer\"}}>\r\n                    <option value=\"\">Agency<\/option>\r\n                    <option value=\"__all__\">All<\/option>\r\n                    {[...new Set(contractors.map(c=>c.trade).filter(Boolean))].sort().map(a=><option key={a} value={a}>{a}<\/option>)}\r\n                    <option value=\"__add__\" style={{color:\"#7c3aed\",fontWeight:700}}>\uff0b Add new...<\/option>\r\n                  <\/select>\r\n                <\/div>\r\n                <div style={{flex:1.2,minWidth:0}}>Site<\/div>\r\n                <div style={{flex:1,minWidth:0,textAlign:\"right\",cursor:\"pointer\",color:billConFilter?\"#7c3aed\":\"#94a3b8\"}} onClick={()=>setBillConFilter(null)}>Pending<\/div>\r\n                <div style={{flex:\"none\",width:26}}\/>\r\n              <\/div>\r\n              {filteredCons.map((c,i)=>{\r\n                const cPending=bills.filter(b=>b.contractorId===c.id).reduce((s,b)=>s+billPending(b),0);\r\n                return(\r\n                <div key={c.id} style={{display:\"flex\",alignItems:\"center\",gap:6,padding:\"8px 12px\",background:i%2===0?\"#fff\":\"#fafcff\",borderBottom:\"1px solid #f1f5f9\"}}>\r\n                  <div style={{flex:2,minWidth:0,fontSize:15,fontWeight:700,color:\"#0f172a\"}}>{c.name}<\/div>\r\n                  <div style={{flex:1.5,minWidth:0,fontSize:15,color:\"#475569\",cursor:\"pointer\"}} onClick={()=>{setEditConId(c.id);setEditConData({...c});}}>{c.phone||\"\u2014\"}<\/div>\r\n                  <div style={{flex:1,minWidth:0}}>\r\n                    <span style={{background:ST_BG[c.status]||\"#f8fafc\",color:ST_COL[c.status]||\"#475569\",padding:\"3px 12px\",borderRadius:6,fontSize:13,fontWeight:700,whiteSpace:\"nowrap\"}}>{c.status||\"New\"}<\/span>\r\n                  <\/div>\r\n                  <div style={{flex:1.2,minWidth:0}}>\r\n                    {c.trade?<span style={{background:\"#f3e8ff\",color:\"#7c3aed\",padding:\"3px 12px\",borderRadius:6,fontSize:13,fontWeight:700,whiteSpace:\"nowrap\"}}>{c.trade}<\/span>:<span style={{fontSize:13,color:\"#cbd5e1\"}}>\u2014<\/span>}\r\n                  <\/div>\r\n                  <div style={{flex:1.2,minWidth:0}}>\r\n                    {c.assignedSite?<span style={{background:\"#dbeafe\",color:\"#1d4ed8\",padding:\"3px 12px\",borderRadius:6,fontSize:13,fontWeight:700,whiteSpace:\"nowrap\"}}>{c.assignedSite}<\/span>:<span style={{fontSize:13,color:\"#cbd5e1\"}}>\u2014<\/span>}\r\n                  <\/div>\r\n                  <div style={{flex:1,minWidth:0,textAlign:\"right\",fontSize:15,fontWeight:800,color:cPending>0?\"#dc2626\":\"#15803d\",cursor:\"pointer\"}} onClick={()=>setBillConFilter(billConFilter===c.id?null:c.id)}>{cPending>0?\"\u20b9\"+cPending:\"\u2713\"}<\/div>\r\n                  <div style={{flex:\"none\",width:22}}\/>\r\n                <\/div>\r\n              )})}\r\n            <\/div>\r\n          )}\r\n          <\/div>\r\n        <\/div>\r\n\r\n        {\/* \u2500\u2500 BILLS (right) \u2500\u2500 *\/}\r\n        <div style={{flex:1,display:\"flex\",flexDirection:\"column\",background:\"#fff\",borderRadius:10,border:\"1px solid #e2e8f0\",overflow:\"hidden\",boxShadow:\"0 1px 3px #00000008\"}}>\r\n          <div style={{padding:\"8px 12px\",borderBottom:\"1px solid #e2e8f0\",display:\"flex\",justifyContent:\"space-between\",alignItems:\"center\",flexShrink:0}}>\r\n            <span style={{fontSize:15,fontWeight:700,color:\"#d97706\",display:\"flex\",alignItems:\"center\",gap:6}}>\ud83e\uddfe Bills <button onClick={()=>setShowBillModal(true)} style={{background:\"#d97706\",color:\"#fff\",border:\"none\",borderRadius:6,padding:\"3px 12px\",fontSize:13,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\",lineHeight:1.5}}>\uff0b Add<\/button><\/span>\r\n            <span style={{fontSize:15,color:\"#94a3b8\"}}>Total: <b>\u20b9{totBills}<\/b> \u00b7 <span style={{color:\"#15803d\",fontWeight:700}}>Paid: \u20b9{totPaid}<\/span> \u00b7 <span style={{color:\"#dc2626\",fontWeight:700}}>Due: \u20b9{totBills-totPaid}<\/span><\/span>\r\n          <\/div>\r\n          <div style={{flex:1,overflowY:\"auto\"}}>\r\n          {bills.length===0?(\r\n            <div style={{padding:24,textAlign:\"center\",color:\"#94a3b8\",fontSize:14}}>No bills yet.<\/div>\r\n          ):(\r\n            <div>\r\n              {\/* Bills header row *\/}\r\n              <div style={{display:\"flex\",alignItems:\"center\",gap:6,padding:\"8px 12px\",fontSize:13,fontWeight:700,color:\"#94a3b8\",textTransform:\"uppercase\",letterSpacing:\"0.5px\",borderBottom:\"2px solid #e2e8f0\",background:\"#f8fafc\"}}>\r\n                <div style={{flex:1.5,minWidth:0}}>Contractor<\/div>\r\n                <div style={{flex:1,minWidth:0}}>Agency<\/div>\r\n                <div style={{flex:1,minWidth:0}}>Site<\/div>\r\n                <div style={{flex:1.5,minWidth:0}}>Work Detail<\/div>\r\n                <div style={{flex:1,minWidth:0,textAlign:\"right\"}}>Amount<\/div>\r\n                <div style={{flex:1,minWidth:0,textAlign:\"right\"}}>Date<\/div>\r\n                <div style={{flex:\"none\",width:26}}\/>\r\n              <\/div>\r\n              {[...bills].filter(b=>!billConFilter||b.contractorId===billConFilter).sort((a,b)=>new Date(b.date||0)-new Date(a.date||0)).map((b,i)=>{\r\n                const tp=billTotalPaid(b);\r\n                const pend=billPending(b);\r\n                const paidFull=pend<=0;\r\n                return(\r\n                  <div key={b.id}>\r\n                    {\/* Main bill row *\/}\r\n                    <div style={{display:\"flex\",alignItems:\"center\",gap:6,padding:\"8px 12px\",borderBottom:paidFull?\"2px solid #86efac\":\"1px solid #f1f5f9\",background:paidFull?\"#f0fdf4\":i%2===0?\"#fff\":\"#fafcff\"}}>\r\n                      <div style={{flex:1.5,minWidth:0,fontSize:15,fontWeight:600,color:\"#0f172a\"}}>{conName(b.contractorId)}<\/div>\r\n                      <div style={{flex:1,minWidth:0}}>{b.trade?<span style={{background:\"#f3e8ff\",color:\"#7c3aed\",padding:\"2px 10px\",borderRadius:6,fontSize:13,fontWeight:700,whiteSpace:\"nowrap\"}}>{b.trade}<\/span>:<span style={{fontSize:13,color:\"#cbd5e1\"}}>\u2014<\/span>}<\/div>\r\n                      <div style={{flex:1,minWidth:0,fontSize:13,color:\"#475569\"}}>{b.assignedSite||\"\u2014\"}<\/div>\r\n                      <div style={{flex:1.5,minWidth:0,fontSize:14,color:\"#475569\"}}>{b.invoiceNo}<\/div>\r\n                      <div style={{flex:1,minWidth:0,textAlign:\"right\",fontSize:14,fontWeight:700}}>\u20b9{b.amount}<\/div>\r\n                      <div style={{flex:1,minWidth:0,fontSize:13,color:\"#64748b\",textAlign:\"right\"}}>{b.date?fmtD(pDate(b.date)):\"\u2014\"}<\/div>\r\n                      <button onClick={()=>deleteBill(b.id)} style={{flex:\"none\",background:\"none\",border:\"none\",cursor:\"pointer\",color:\"#fca5a5\",fontSize:16,padding:\"2px 4px\",opacity:0.6}}>\u2715<\/button>\r\n                    <\/div>\r\n                    {\/* Payment rows *\/}\r\n                    {((b.payments&&b.payments.length>0)||(b.paid>0))&&(\r\n                      <div style={{display:\"flex\",alignItems:\"center\",gap:6,padding:\"5px 12px 5px 32px\",fontSize:13,color:\"#64748b\",background:\"#fafcff\",borderBottom:\"1px solid #f1f5f9\",cursor:\"pointer\"}} onClick={()=>{const p=b.payments?b.payments[0]:{id:\"\",paid:b.paid,paidDate:b.date};setEditPayData({billId:b.id,payId:p.id,paid:p.paid,paidDate:p.paidDate||\"\"});}}>\r\n                        <div style={{flex:1.5,minWidth:0}}\/>\r\n                        <div style={{flex:1,minWidth:0}}\/>\r\n                        <div style={{flex:1,minWidth:0}}\/>\r\n                        <div style={{flex:1.5,minWidth:0,fontWeight:600,color:\"#475569\"}}>#1 Payment<\/div>\r\n                        <div style={{flex:1,minWidth:0,textAlign:\"right\",fontWeight:700,color:\"#15803d\"}}>\u20b9{b.payments?b.payments[0].paid:b.paid}<\/div>\r\n                        <div style={{flex:1,minWidth:0,fontSize:13,color:\"#94a3b8\",textAlign:\"right\"}}>{b.payments?fmtD(pDate(b.payments[0].paidDate)):b.date?fmtD(pDate(b.date)):\"\u2014\"}<\/div>\r\n                        <div style={{flex:\"none\",width:22}}\/>\r\n                      <\/div>\r\n                    )}\r\n                    {(b.payments&&b.payments.length>1)&&b.payments.slice(1).map((p,pi)=>(\r\n                      <div key={p.id} style={{display:\"flex\",alignItems:\"center\",gap:6,padding:\"5px 12px 5px 32px\",fontSize:13,color:\"#64748b\",background:\"#fafcff\",borderBottom:pi<b.payments.length-1?\"1px solid #f1f5f9\":\"none\",cursor:\"pointer\"}} onClick={()=>setEditPayData({billId:b.id,payId:p.id,paid:p.paid,paidDate:p.paidDate||\"\"})}>\r\n                        <div style={{flex:1.5,minWidth:0}}\/>\r\n                        <div style={{flex:1,minWidth:0}}\/>\r\n                        <div style={{flex:1,minWidth:0}}\/>\r\n                        <div style={{flex:1.5,minWidth:0,fontWeight:600,color:\"#475569\"}}>#{pi+2} Payment<\/div>\r\n                        <div style={{flex:1,minWidth:0,textAlign:\"right\",fontWeight:700,color:\"#15803d\"}}>\u20b9{p.paid}<\/div>\r\n                        <div style={{flex:1,minWidth:0,fontSize:13,color:\"#94a3b8\",textAlign:\"right\"}}>{p.paidDate?fmtD(pDate(p.paidDate)):\"\u2014\"}<\/div>\r\n                        <div style={{flex:\"none\",width:22}}\/>\r\n                      <\/div>\r\n                    ))}\r\n                    {\/* Bill footer: total paid + pending + add payment button *\/}\r\n                    <div style={{display:\"flex\",alignItems:\"center\",gap:6,padding:\"5px 12px 8px 32px\",fontSize:13,borderBottom:i<bills.length-1?\"1px solid #e2e8f0\":\"none\",background:\"#f8fafc\"}}>\r\n                      <div style={{flex:1.5,minWidth:0}}\/>\r\n                      <div style={{flex:1,minWidth:0}}\/>\r\n                      <div style={{flex:1,minWidth:0}}\/>\r\n                      <div style={{flex:1.5,minWidth:0,fontWeight:700,color:\"#475569\"}}>\r\n                        <button onClick={()=>{setEditBillId(b.id);setEditBillData({contractorId:b.contractorId,invoiceNo:b.invoiceNo,amount:b.amount,date:b.date,trade:b.trade||\"\",assignedSite:b.assignedSite||\"\"});}} style={{background:\"#475569\",color:\"#fff\",border:\"none\",borderRadius:5,padding:\"4px 12px\",fontSize:13,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\",lineHeight:1.8}}>\u270f\ufe0f Edit<\/button>\r\n                        {!paidFull&&<button onClick={()=>{setPayBillId(b.id);setShowPayModal(true);}} style={{marginLeft:8,background:\"#d97706\",color:\"#fff\",border:\"none\",borderRadius:5,padding:\"4px 12px\",fontSize:13,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\",lineHeight:1.8}}>\uff0b Pay<\/button>}\r\n                      <\/div>\r\n                      <div style={{flex:1,minWidth:0,textAlign:\"right\",fontWeight:700,color:\"#15803d\",fontSize:14}}>\u20b9{tp}<\/div>\r\n                      <div style={{flex:1,minWidth:0,fontSize:15,fontWeight:800,textAlign:\"right\",color:pend>0?\"#dc2626\":\"#15803d\"}}>{pend>0?\"\u20b9\"+pend:\"\u2713\"}<\/div>\r\n                      <div style={{flex:\"none\",width:22}}\/>\r\n                    <\/div>\r\n                  <\/div>\r\n                );\r\n              })}\r\n            <\/div>\r\n          )}\r\n          <\/div>\r\n        <\/div>\r\n\r\n      <\/div>\r\n\r\n      {\/* \u2500\u2500 ADD CONTRACTOR MODAL \u2500\u2500 *\/}\r\n      {showAddCon&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>setShowAddCon(false)}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:22,width:400,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#0f172a\",marginBottom:14}}>\u2795 Add Contractor<\/div>\r\n            <div style={{display:\"grid\",gap:10}}>\r\n              <div><label style={LBL}>Name *<\/label><input autoFocus value={newCon.name} onChange={e=>setNewCon(p=>({...p,name:e.target.value}))} style={INP} placeholder=\"e.g. Ashok bhai\"\/><\/div>\r\n              <div><label style={LBL}>Phone<\/label><input value={newCon.phone} onChange={e=>setNewCon(p=>({...p,phone:e.target.value}))} style={INP} placeholder=\"e.g. 9876543210\"\/><\/div>\r\n              <div><label style={LBL}>Status<\/label>\r\n                <select value={newCon.status} onChange={e=>setNewCon(p=>({...p,status:e.target.value}))} style={INP}>\r\n                  {STATUS_OPTS.map(s=><option key={s} value={s}>{s}<\/option>)}\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL}>Agency<\/label>\r\n                <select value={newCon.trade===\"__add__\"?\"__add__\":trades.includes(newCon.trade)?newCon.trade:\"\"} onChange={e=>{const v=e.target.value;if(v===\"__add__\"){setNewCon(p=>({...p,trade:\"\"}));const t=prompt(\"Enter new agency name:\");if(t&&t.trim()){const nt=[...trades,t.trim()];setTrades(nt);setNewCon(p=>({...p,trade:t.trim()}));onSave(null,null,nt);}}else{setNewCon(p=>({...p,trade:v}));}}} style={INP}>\r\n                  <option value=\"\">Select agency...<\/option>\r\n                  {trades.map(t=><option key={t}>{t}<\/option>)}\r\n                  <option value=\"__add__\" style={{color:\"#7c3aed\",fontWeight:700}}>\uff0b Add new Agency...<\/option>\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL}>Site<\/label>\r\n                <select value={newCon.assignedSite===\"__add__\"?\"__add__\":allSites.includes(newCon.assignedSite)?newCon.assignedSite:\"\"} onChange={e=>{const v=e.target.value;if(v===\"__add__\"){setNewCon(p=>({...p,assignedSite:\"\"}));const s=prompt(\"Enter new site name:\");if(s&&s.trim()){const ns=[...customAreas,s.trim()];setCustomAreas(ns);setNewCon(p=>({...p,assignedSite:s.trim()}));}}else{setNewCon(p=>({...p,assignedSite:v}));}}} style={INP}>\r\n                  <option value=\"\">Select site...<\/option>\r\n                  {allSites.map(s=><option key={s}>{s}<\/option>)}\r\n                  <option value=\"__add__\" style={{color:\"#7c3aed\",fontWeight:700}}>\uff0b Add new Site...<\/option>\r\n                <\/select>\r\n              <\/div>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\",marginTop:14}}>\r\n              <button onClick={()=>setShowAddCon(false)} style={{border:\"1px solid #e2e8f0\",background:\"#f8fafc\",color:\"#475569\",borderRadius:6,padding:\"8px 18px\",fontSize:14,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n              <button onClick={addCon} disabled={!newCon.name.trim()} style={{background:newCon.name.trim()?\"#0f172a\":\"#cbd5e1\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"8px 22px\",fontSize:14,fontWeight:700,cursor:newCon.name.trim()?\"pointer\":\"not-allowed\",fontFamily:\"inherit\"}}>Add<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 BILL MODAL \u2500\u2500 *\/}\r\n      {showBillModal&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>setShowBillModal(false)}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:22,width:420,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#0f172a\",marginBottom:14}}>\ud83e\uddfe Add Bill<\/div>\r\n            <div style={{display:\"grid\",gap:10}}>\r\n              <div style={{gridColumn:\"1\/-1\"}}><label style={LBL}>Contractor *<\/label>\r\n                <select value={newBill.contractorId} onChange={e=>setNewBill(p=>({...p,contractorId:e.target.value,trade:contractors.find(x=>x.id===e.target.value)?.trade||\"\"}))} style={INP}>\r\n                  <option value=\"\">Select...<\/option>\r\n                  {contractors.map(c=><option key={c.id} value={c.id}>{c.name}<\/option>)}\r\n                <\/select>\r\n              <\/div>\r\n              <div style={{display:\"grid\",gridTemplateColumns:\"1fr 1fr\",gap:10}}>\r\n                <div><label style={LBL}>Agency<\/label><input value={newBill.trade} onChange={e=>setNewBill(p=>({...p,trade:e.target.value}))} style={INP} placeholder=\"Auto from contractor\"\/><\/div>\r\n                <div><label style={LBL}>Site \/ Area<\/label>\r\n                  <select value={newBill.assignedSite} onChange={e=>{const v=e.target.value;if(v===\"__add__\"){const s=prompt(\"Enter new site:\");if(s&&s.trim()){const ns=[...customAreas,s.trim()];setCustomAreas(ns);setNewBill(p=>({...p,assignedSite:s.trim()}));}}else{setNewBill(p=>({...p,assignedSite:v}));}}} style={INP}>\r\n                    <option value=\"\">Select...<\/option>\r\n                    {allSites.map(s=><option key={s} value={s}>{s}<\/option>)}\r\n                    <option value=\"__add__\" style={{color:\"#7c3aed\",fontWeight:700}}>\uff0b Add new...<\/option>\r\n                  <\/select>\r\n                <\/div>\r\n              <\/div>\r\n              <div><label style={LBL}>Work Detail *<\/label><input value={newBill.invoiceNo} onChange={e=>setNewBill(p=>({...p,invoiceNo:e.target.value}))} style={INP} placeholder=\"e.g. Kitchen tile work\"\/><\/div>\r\n              <div style={{display:\"grid\",gridTemplateColumns:\"1fr 1fr\",gap:10}}>\r\n                <div><label style={LBL}>Bill Amount<\/label><input type=\"number\" min={0} value={newBill.amount} onChange={e=>setNewBill(p=>({...p,amount:e.target.value}))} style={INP}\/><\/div>\r\n                <div><label style={LBL}>Bill Date<\/label><input type=\"date\" value={newBill.date} onChange={e=>setNewBill(p=>({...p,date:e.target.value}))} style={INP}\/><\/div>\r\n              <\/div>\r\n              <div style={{borderTop:\"1px solid #e2e8f0\",paddingTop:10}}>\r\n                <div style={{fontSize:13,fontWeight:700,color:\"#475569\",marginBottom:6}}>First Payment (optional)<\/div>\r\n                <div style={{display:\"grid\",gridTemplateColumns:\"1fr 1fr\",gap:10}}>\r\n                  <div><label style={LBL}>Paid Amount<\/label><input type=\"number\" min={0} value={newBill.firstPaid} onChange={e=>setNewBill(p=>({...p,firstPaid:e.target.value}))} style={INP}\/><\/div>\r\n                  <div><label style={LBL}>Paid Date<\/label><input type=\"date\" value={newBill.firstPaidDate} onChange={e=>setNewBill(p=>({...p,firstPaidDate:e.target.value}))} style={INP}\/><\/div>\r\n                <\/div>\r\n              <\/div>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\",marginTop:14}}>\r\n              <button onClick={()=>setShowBillModal(false)} style={{border:\"1px solid #e2e8f0\",background:\"#f8fafc\",color:\"#475569\",borderRadius:6,padding:\"8px 18px\",fontSize:14,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n              <button onClick={addBill} disabled={!newBill.contractorId||!newBill.invoiceNo.trim()} style={{background:newBill.contractorId&&newBill.invoiceNo.trim()?\"#d97706\":\"#cbd5e1\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"8px 22px\",fontSize:14,fontWeight:700,cursor:newBill.contractorId&&newBill.invoiceNo.trim()?\"pointer\":\"not-allowed\",fontFamily:\"inherit\"}}>Add Bill<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 EDIT BILL MODAL \u2500\u2500 *\/}\r\n      {editBillId&&editBillData&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>{setEditBillId(null);setEditBillData(null);}}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:22,width:420,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#0f172a\",marginBottom:14}}>\u270f\ufe0f Edit Bill<\/div>\r\n            <div style={{display:\"grid\",gap:10}}>\r\n              <div style={{gridColumn:\"1\/-1\"}}><label style={LBL}>Contractor<\/label>\r\n                <select value={editBillData.contractorId} onChange={e=>setEditBillData(p=>({...p,contractorId:e.target.value}))} style={INP}>\r\n                  {contractors.map(c=><option key={c.id} value={c.id}>{c.name}<\/option>)}\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL}>Agency<\/label><input value={editBillData.trade} onChange={e=>setEditBillData(p=>({...p,trade:e.target.value}))} style={INP}\/><\/div>\r\n              <div><label style={LBL}>Site \/ Area<\/label>\r\n                <select value={editBillData.assignedSite} onChange={e=>{const v=e.target.value;if(v===\"__add__\"){const s=prompt(\"New site:\");if(s&&s.trim()){const ns=[...customAreas,s.trim()];setCustomAreas(ns);setEditBillData(p=>({...p,assignedSite:s.trim()}));}}else{setEditBillData(p=>({...p,assignedSite:v}));}}} style={INP}>\r\n                  <option value=\"\">Select...<\/option>\r\n                  {allSites.map(s=><option key={s} value={s}>{s}<\/option>)}\r\n                  <option value=\"__add__\" style={{color:\"#7c3aed\",fontWeight:700}}>\uff0b Add new...<\/option>\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL}>Work Detail<\/label><input value={editBillData.invoiceNo} onChange={e=>setEditBillData(p=>({...p,invoiceNo:e.target.value}))} style={INP}\/><\/div>\r\n              <div style={{display:\"grid\",gridTemplateColumns:\"1fr 1fr\",gap:10}}>\r\n                <div><label style={LBL}>Bill Amount<\/label><input type=\"number\" min={0} value={editBillData.amount} onChange={e=>setEditBillData(p=>({...p,amount:e.target.value}))} style={INP}\/><\/div>\r\n                <div><label style={LBL}>Bill Date<\/label><input type=\"date\" value={editBillData.date} onChange={e=>setEditBillData(p=>({...p,date:e.target.value}))} style={INP}\/><\/div>\r\n              <\/div>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\",marginTop:14}}>\r\n              <button onClick={()=>{setEditBillId(null);setEditBillData(null);}} style={{border:\"1px solid #e2e8f0\",background:\"#f8fafc\",color:\"#475569\",borderRadius:6,padding:\"8px 18px\",fontSize:14,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n              <button onClick={updateBill} style={{background:\"#0f172a\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"8px 22px\",fontSize:14,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>Save<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 ADD PAYMENT MODAL \u2500\u2500 *\/}\r\n      {showPayModal&&payBillId&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>{setShowPayModal(false);setPayBillId(null);setNewPay({paid:\"\",paidDate:\"\"});}}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:22,width:380,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#0f172a\",marginBottom:14}}>\ud83d\udcb3 Add Payment<\/div>\r\n            <div style={{fontSize:13,color:\"#475569\",marginBottom:12}}>For: <b>{conName(bills.find(b=>b.id===payBillId)?.contractorId)}<\/b> \u00b7 Pending: <b style={{color:\"#dc2626\"}}>\u20b9{billPending(bills.find(b=>b.id===payBillId))}<\/b><\/div>\r\n            <div style={{display:\"grid\",gap:10}}>\r\n              <div><label style={LBL}>Paid Amount *<\/label><input autoFocus type=\"number\" min={0} value={newPay.paid} onChange={e=>setNewPay(p=>({...p,paid:e.target.value}))} style={INP}\/><\/div>\r\n              <div><label style={LBL}>Paid Date<\/label><input type=\"date\" value={newPay.paidDate} onChange={e=>setNewPay(p=>({...p,paidDate:e.target.value}))} style={INP}\/><\/div>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\",marginTop:14}}>\r\n              <button onClick={()=>{setShowPayModal(false);setPayBillId(null);setNewPay({paid:\"\",paidDate:\"\"});}} style={{border:\"1px solid #e2e8f0\",background:\"#f8fafc\",color:\"#475569\",borderRadius:6,padding:\"8px 18px\",fontSize:14,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n              <button onClick={addPayment} disabled={!newPay.paid} style={{background:newPay.paid?\"#15803d\":\"#cbd5e1\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"8px 22px\",fontSize:14,fontWeight:700,cursor:newPay.paid?\"pointer\":\"not-allowed\",fontFamily:\"inherit\"}}>Add Payment<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 EDIT PAYMENT MODAL \u2500\u2500 *\/}\r\n      {editPayData&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>setEditPayData(null)}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:22,width:380,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#0f172a\",marginBottom:14}}>\u270f\ufe0f Edit Payment<\/div>\r\n            <div style={{display:\"grid\",gap:10}}>\r\n              <div><label style={LBL}>Paid Amount<\/label><input autoFocus type=\"number\" min={0} value={editPayData.paid} onChange={e=>setEditPayData(p=>({...p,paid:e.target.value}))} style={INP}\/><\/div>\r\n              <div><label style={LBL}>Paid Date<\/label><input type=\"date\" value={editPayData.paidDate} onChange={e=>setEditPayData(p=>({...p,paidDate:e.target.value}))} style={INP}\/><\/div>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\",marginTop:14}}>\r\n              <button onClick={()=>setEditPayData(null)} style={{border:\"1px solid #e2e8f0\",background:\"#f8fafc\",color:\"#475569\",borderRadius:6,padding:\"8px 18px\",fontSize:14,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n              <button onClick={()=>updatePayment(editPayData.billId,editPayData.payId,editPayData.paid,editPayData.paidDate)} style={{background:\"#0f172a\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"8px 22px\",fontSize:14,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>Save<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 EDIT CONTRACTOR MODAL \u2500\u2500 *\/}\r\n      {editConId&&editConData&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>{setEditConId(null);setEditConData(null);}}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:22,width:400,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#0f172a\",marginBottom:14}}>\u270f\ufe0f Edit Contractor<\/div>\r\n            <div style={{display:\"grid\",gap:10}}>\r\n              <div><label style={LBL}>Name *<\/label><input autoFocus value={editConData.name} onChange={e=>setEditConData(p=>({...p,name:e.target.value}))} style={INP}\/><\/div>\r\n              <div><label style={LBL}>Phone<\/label><input value={editConData.phone} onChange={e=>setEditConData(p=>({...p,phone:e.target.value}))} style={INP}\/><\/div>\r\n              <div><label style={LBL}>Status<\/label>\r\n                <select value={editConData.status} onChange={e=>setEditConData(p=>({...p,status:e.target.value}))} style={INP}>\r\n                  {STATUS_OPTS.map(s=><option key={s} value={s}>{s}<\/option>)}\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL}>Agency<\/label>\r\n                <select value={editConData.trade} onChange={e=>{const v=e.target.value;if(v===\"__add__\"){const t=prompt(\"Enter new agency name:\");if(t&&t.trim()){const nt=[...trades,t.trim()];setTrades(nt);setEditConData(p=>({...p,trade:t.trim()}));onSave(null,null,nt);}}else{setEditConData(p=>({...p,trade:v}));}}} style={INP}>\r\n                  <option value=\"\">Select agency...<\/option>\r\n                  {trades.map(t=><option key={t} value={t}>{t}<\/option>)}\r\n                  <option value=\"__add__\" style={{color:\"#7c3aed\",fontWeight:700}}>\uff0b Add new...<\/option>\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL}>Site<\/label>\r\n                <select value={editConData.assignedSite} onChange={e=>{const v=e.target.value;if(v===\"__add__\"){const s=prompt(\"Enter new site name:\");if(s&&s.trim()){const ns=[...customAreas,s.trim()];setCustomAreas(ns);setEditConData(p=>({...p,assignedSite:s.trim()}));}}else{setEditConData(p=>({...p,assignedSite:v}));}}} style={INP}>\r\n                  <option value=\"\">Select site...<\/option>\r\n                  {allSites.map(s=><option key={s} value={s}>{s}<\/option>)}\r\n                  <option value=\"__add__\" style={{color:\"#7c3aed\",fontWeight:700}}>\uff0b Add new...<\/option>\r\n                <\/select>\r\n              <\/div>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"space-between\",marginTop:14}}>\r\n              <button onClick={()=>{deleteCon(editConId);setEditConId(null);setEditConData(null);}} style={{background:\"#fef2f2\",color:\"#dc2626\",border:\"1px solid #fecaca\",borderRadius:6,padding:\"8px 18px\",fontSize:14,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>\ud83d\uddd1\ufe0f Delete<\/button>\r\n              <div style={{display:\"flex\",gap:10}}>\r\n                <button onClick={()=>{setEditConId(null);setEditConData(null);}} style={{border:\"1px solid #e2e8f0\",background:\"#f8fafc\",color:\"#475569\",borderRadius:6,padding:\"8px 18px\",fontSize:14,fontWeight:600,cursor:\"pointer\",fontFamily:\"inherit\"}}>Cancel<\/button>\r\n                <button onClick={()=>{const nc=contractors.map(c=>c.id===editConId?editConData:c);setContractors(nc);onSave(nc,bills,trades,customAreas);setEditConId(null);setEditConData(null);}} disabled={!editConData.name.trim()} style={{background:editConData.name.trim()?\"#0f172a\":\"#cbd5e1\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"8px 22px\",fontSize:14,fontWeight:700,cursor:editConData.name.trim()?\"pointer\":\"not-allowed\",fontFamily:\"inherit\"}}>Save<\/button>\r\n              <\/div>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n    <\/div>\r\n  );\r\n}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ MAIN APP\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\nfunction App(){\r\n  const now=new Date();\r\n  const[page,setPage]=useState(\"tracker\");\r\n  const[year,setYear]=useState(now.getFullYear());\r\n  const[month,setMonth]=useState(now.getMonth());\r\n\r\n  \/\/ Tracker state\r\n  const[tasks,setTasks]=useState(DEFAULT_TASKS);\r\n  const[grid,setGrid]=useState({});\r\n  const[dayMeta,setDayMeta]=useState({});\r\n  const[taskMeta,setTaskMeta]=useState({});\r\n  const[customAreas,setCustomAreas]=useState([]);\r\n\r\n  \/\/ Stock state\r\n  const[materials,setMaterials]=useState(DEFAULT_MATERIALS);\r\n  const[stockEntries,setStockEntries]=useState({});\r\n\r\n  \/\/ Agency state\r\n  const[contractors,setContractors]=useState([]);\r\n  const[bills,setBills]=useState([]);\r\n  const DEFAULT_TRADES=[\"Plumber\",\"Electrician\",\"Carpenter\",\"Mason\",\"Painter\",\"Welder\",\"Tile Worker\",\"Labor\",\"Gardener\",\"Fabricator\",\"Other\"];\r\n  const[trades,setTrades]=useState(DEFAULT_TRADES);\r\n\r\n  const[loaded,setLoaded]=useState(false);\r\n  const[syncStatus,setSyncStatus]=useState(\"loading\");\r\n  const[lastSync,setLastSync]=useState(null);\r\n  const[selCell,setSelCell]=useState(null);\r\n  const[editField,setEditField]=useState(null);\r\n  const[editTask,setEditTask]=useState(null);\r\n  const[activeArea,setActiveArea]=useState(\"All\");\r\n  const[view,setView]=useState(\"grid\");\r\n  const[showAdd,setShowAdd]=useState(false);\r\n  const[newTask,setNewTask]=useState({name:\"\",area:\"Club\",status:\"Pending\",pct:0,assignee:\"\"});\r\n  const[delConfirm,setDelConfirm]=useState(null);\r\n  const[showAddArea,setShowAddArea]=useState(false);\r\n  const[newAreaName,setNewAreaName]=useState(\"\");\r\n\r\n  const saveTimer=useRef(null);\r\n  const lastTsRef=useRef(null);\r\n\r\n  useEffect(()=>{\r\n    (async()=>{\r\n      setSyncStatus(\"loading\");\r\n      const data=await apiLoad();\r\n      if(data){\r\n        if(data.tasks&&data.tasks.length)setTasks(data.tasks);\r\n        if(data.grid)setGrid(data.grid);\r\n        if(data.dayMeta)setDayMeta(data.dayMeta);\r\n        if(data.taskMeta)setTaskMeta(data.taskMeta);\r\n        if(data.customAreas)setCustomAreas(data.customAreas);\r\n        if(data.materials&&data.materials.length)setMaterials(data.materials);\r\n        if(data.stockEntries)setStockEntries(data.stockEntries);\r\n        if(data.contractors&&data.contractors.length)setContractors(data.contractors);\r\n        if(data.bills&&data.bills.length)setBills(data.bills);\r\n        if(data.trades&&data.trades.length)setTrades(data.trades);\r\n        if(data._ts)lastTsRef.current=data._ts;\r\n        setSyncStatus(\"saved\");setLastSync(new Date());\r\n      }else{setSyncStatus(\"saved\");}\r\n      setLoaded(true);\r\n    })();\r\n  },[]);\r\n\r\n  useEffect(()=>{\r\n    if(!loaded)return;\r\n    const id=setInterval(async()=>{\r\n      const data=await apiLoad();\r\n      if(data&&data._ts&&data._ts!==lastTsRef.current){\r\n        if(data.tasks&&data.tasks.length)setTasks(data.tasks);\r\n        if(data.grid)setGrid(data.grid);\r\n        if(data.dayMeta)setDayMeta(data.dayMeta);\r\n        if(data.taskMeta)setTaskMeta(data.taskMeta);\r\n        if(data.customAreas)setCustomAreas(data.customAreas);\r\n        if(data.materials&&data.materials.length)setMaterials(data.materials);\r\n        if(data.stockEntries)setStockEntries(data.stockEntries);\r\n        if(data.contractors&&data.contractors.length)setContractors(data.contractors);\r\n        if(data.bills&&data.bills.length)setBills(data.bills);\r\n        if(data.trades&&data.trades.length)setTrades(data.trades);\r\n        lastTsRef.current=data._ts;setLastSync(new Date());\r\n      }\r\n    },25000);\r\n    return()=>clearInterval(id);\r\n  },[loaded]);\r\n\r\n  const buildPayload=(ts,g,dm,tm,ca,mats,se,cons,bls,tr)=>({\r\n    tasks:ts||tasks,grid:g||grid,dayMeta:dm||dayMeta,taskMeta:tm||taskMeta,\r\n    customAreas:ca||customAreas,materials:mats||materials,stockEntries:se||stockEntries,\r\n    contractors:cons||contractors,bills:bls||bills,trades:tr||trades,_ts:Date.now()\r\n  });\r\n\r\n  const save=useCallback((ts,g,dm,tm,ca)=>{\r\n    setSyncStatus(\"saving\");\r\n    clearTimeout(saveTimer.current);\r\n    saveTimer.current=setTimeout(async()=>{\r\n      const payload=buildPayload(ts,g,dm,tm,ca,null,null);\r\n      const ts_now=payload._ts;\r\n      const ok=await apiSave(payload);\r\n      lastTsRef.current=ts_now;setSyncStatus(ok?\"saved\":\"error\");setLastSync(new Date());\r\n    },700);\r\n  },[tasks,grid,dayMeta,taskMeta,customAreas,materials,stockEntries]);\r\n\r\n  const saveStock=useCallback((newSE,newMats)=>{\r\n    setSyncStatus(\"saving\");\r\n    clearTimeout(saveTimer.current);\r\n    saveTimer.current=setTimeout(async()=>{\r\n      const payload=buildPayload(null,null,null,null,null,newMats||materials,newSE||stockEntries);\r\n      const ts_now=payload._ts;\r\n      const ok=await apiSave(payload);\r\n      lastTsRef.current=ts_now;setSyncStatus(ok?\"saved\":\"error\");setLastSync(new Date());\r\n    },700);\r\n  },[tasks,grid,dayMeta,taskMeta,customAreas,materials,stockEntries,contractors,bills]);\r\n\r\n  const saveAgency=useCallback((newCons,newBills,newTrades,newCustAreas)=>{\r\n    setSyncStatus(\"saving\");\r\n    clearTimeout(saveTimer.current);\r\n    saveTimer.current=setTimeout(async()=>{\r\n      const ca=newCustAreas||customAreas;\r\n      if(newCustAreas)setCustomAreas(newCustAreas);\r\n      const payload=buildPayload(null,null,null,null,ca,null,null,newCons||contractors,newBills||bills,newTrades||trades);\r\n      const ts_now=payload._ts;\r\n      const ok=await apiSave(payload);\r\n      lastTsRef.current=ts_now;setSyncStatus(ok?\"saved\":\"error\");setLastSync(new Date());\r\n    },700);\r\n  },[tasks,grid,dayMeta,taskMeta,customAreas,materials,stockEntries,contractors,bills,trades]);\r\n\r\n  const dIM=new Date(year,month+1,0).getDate();\r\n  const days=Array.from({length:dIM},(_,i)=>i+1);\r\n  const todayKey=toKey(now.getFullYear(),now.getMonth(),now.getDate());\r\n  const mName=new Date(year,month).toLocaleString(\"en-IN\",{month:\"long\",year:\"numeric\"});\r\n  const cKey=(tid,day)=>`${tid}-${toKey(year,month,day)}`;\r\n\r\n  const cycleStatus=(tid)=>{const nt=tasks.map(t=>t.id!==tid?t:{...t,status:SC[(SC.indexOf(t.status)+1)%4],pct:SC[(SC.indexOf(t.status)+1)%4]===\"Done\"?100:t.pct});setTasks(nt);save(nt,grid,dayMeta,taskMeta,customAreas);};\r\n  const renameTask=(tid,name)=>{const nt=tasks.map(t=>t.id===tid?{...t,name}:t);setTasks(nt);save(nt,grid,dayMeta,taskMeta,customAreas);};\r\n  const deleteTask=(tid)=>{const nt=tasks.filter(t=>t.id!==tid);setTasks(nt);save(nt,grid,dayMeta,taskMeta,customAreas);setDelConfirm(null);};\r\n  const addTask=()=>{\r\n    if(!newTask.name.trim())return;\r\n    const t={id:uid(),name:newTask.name.trim(),area:newTask.area,status:newTask.status,pct:parseInt(newTask.pct)||0,assignee:newTask.assignee||\"\"};\r\n    const nt=[...tasks,t];setTasks(nt);save(nt,grid,dayMeta,taskMeta,customAreas);\r\n    setNewTask({name:\"\",area:\"Club\",status:\"Pending\",pct:0,assignee:\"\"});setShowAdd(false);\r\n  };\r\n  const addArea=()=>{const name=newAreaName.trim();if(!name||[...AREA_LIST,...customAreas].includes(name))return;const na=[...customAreas,name];setCustomAreas(na);save(tasks,grid,dayMeta,taskMeta,na);setNewAreaName(\"\");setShowAddArea(false);};\r\n  const toggleCell=(tid,day)=>{const k=cKey(tid,day);const cur=grid[k];const t=tasks.find(x=>x.id===tid);const ng={...grid,[k]:cur&&cur.done?{...cur,done:false}:{done:true,pct:t?t.pct:0}};setGrid(ng);save(tasks,ng,dayMeta,taskMeta,customAreas);};\r\n  const updatePct=(tid,day,val)=>{const k=cKey(tid,day);const ng={...grid,[k]:{...(grid[k]||{done:true}),pct:Math.min(100,Math.max(0,parseInt(val)||0))}};setGrid(ng);save(tasks,ng,dayMeta,taskMeta,customAreas);};\r\n  const setDayStatus=(day,status)=>{const k=toKey(year,month,day);const cur=dayMeta[k]||{};const nm={...dayMeta,[k]:{...cur,status:cur.status===status?\"work\":status}};setDayMeta(nm);save(tasks,grid,nm,taskMeta,customAreas);};\r\n  const updateTM=(tid,field,val)=>{const cur=taskMeta[tid]||{};let upd={...cur,[field]:val};if(field===\"estDays\"&&val){const ed=parseInt(val)||0;if(ed>0){const fd=new Date();fd.setDate(fd.getDate()+ed);upd.finishDate=toKey(fd.getFullYear(),fd.getMonth(),fd.getDate());}}const nm={...taskMeta,[tid]:upd};setTaskMeta(nm);save(tasks,grid,dayMeta,nm,customAreas);};\r\n\r\n  const getDayCount=(day)=>tasks.filter(t=>grid[cKey(t.id,day)]&&grid[cKey(t.id,day)].done).length;\r\n  const getTaskDays=(tid)=>days.filter(d=>grid[cKey(tid,d)]&&grid[cKey(tid,d)].done).length;\r\n\r\n  const getDelay=(tid)=>{\r\n    const tm=taskMeta[tid]||{};const fd=pDate(tm.finishDate);const ed=parseInt(tm.estDays)||0;\r\n    const wd=getTaskDays(tid);const t=tasks.find(x=>x.id===tid);const td=todayD();\r\n    let label=\"\",color=\"#94a3b8\",bg=\"#f8fafc\",icon=\"\";\r\n    if(fd){const dl=dDiff(td,fd);if(t&&t.status===\"Done\"){label=\"Completed\";color=\"#15803d\";bg=\"#dcfce7\";icon=\"\u2705\";}else if(dl<0){label=Math.abs(dl)+\"d overdue\";color=\"#dc2626\";bg=\"#fee2e2\";icon=\"\ud83d\udea8\";}else if(dl===0){label=\"Due today!\";color=\"#d97706\";bg=\"#fffbeb\";icon=\"\u26a0\ufe0f\";}else if(dl<=3){label=dl+\"d left\";color=\"#d97706\";bg=\"#fffbeb\";icon=\"\u26a0\ufe0f\";}else{label=dl+\"d left\";color=\"#15803d\";bg=\"#dcfce7\";icon=\"\u2705\";}}\r\n    else if(ed>0){const rem=ed-wd;if(t&&t.status===\"Done\"){label=\"Completed\";color=\"#15803d\";bg=\"#dcfce7\";icon=\"\u2705\";}else if(rem<=0){label=Math.abs(rem)+\"d over est.\";color=\"#dc2626\";bg=\"#fee2e2\";icon=\"\ud83d\udea8\";}else if(rem<=3){label=rem+\"d left\";color=\"#d97706\";bg=\"#fffbeb\";icon=\"\u26a0\ufe0f\";}else{label=rem+\"d left\";color=\"#1d4ed8\";bg=\"#dbeafe\";icon=\"\ud83d\udcc5\";}}\r\n    return{label,color,bg,icon,wd};\r\n  };\r\n\r\n  const suggestEst=(tid)=>{const t=tasks.find(x=>x.id===tid);if(!t)return null;const wd=getTaskDays(t.id);const pct=t.pct||0;const rem=100-pct;if(rem<=0)return null;if(wd>0&&pct>0)return Math.max(1,Math.round((wd\/pct)*rem));return Math.max(1,Math.round(rem\/5));};\r\n\r\n  const sortTasks=(list)=>[...list].sort((a,b)=>{\r\n    const ad=a.status===\"Done\",bd=b.status===\"Done\";if(ad&&!bd)return 1;if(!ad&&bd)return -1;if(ad&&bd)return 0;\r\n    const af=pDate(taskMeta[a.id]&&taskMeta[a.id].finishDate);const bf=pDate(taskMeta[b.id]&&taskMeta[b.id].finishDate);\r\n    if(af&&bf)return af-bf;if(af&&!bf)return -1;if(!af&&bf)return 1;\r\n    const ah=a.status===\"Hold\",bh=b.status===\"Hold\";if(ah&&!bh)return 1;if(!ah&&bh)return -1;return 0;\r\n  });\r\n\r\n  const allAreasList=[...AREA_LIST,...customAreas];\r\n  const allAreas=[\"All\",...allAreasList].filter((a,i,ar)=>ar.indexOf(a)===i&&(a===\"All\"||tasks.some(t=>t.area===a)||allAreasList.includes(a)));\r\n  const filtered=sortTasks(activeArea===\"All\"?tasks:tasks.filter(t=>t.area===activeArea));\r\n  const totalWD=days.filter(d=>getDayCount(d)>0).length;\r\n  const filled=Object.values(grid).filter(v=>v&&v.done).length;\r\n  const doneC=tasks.filter(t=>t.status===\"Done\").length;\r\n  const runC=tasks.filter(t=>t.status===\"Running\").length;\r\n  const pendC=tasks.filter(t=>t.status===\"Pending\").length;\r\n  const holdC=tasks.filter(t=>t.status===\"Hold\").length;\r\n  const lowStockC=materials.filter(m=>{\r\n    const open=stockEntries[`${m.id}-${year}-${String(month+1).padStart(2,\"0\")}-open`]?.opening??m.openingStock;\r\n    const totIn=days.reduce((s,d)=>{const e=stockEntries[`${m.id}-${toKey(year,month,d)}`]||{};return s+(e.received||0);},0);\r\n    const totOut=days.reduce((s,d)=>{const e=stockEntries[`${m.id}-${toKey(year,month,d)}`]||{};return s+(e.issued||0);},0);\r\n    return (open+totIn-totOut)<=(m.minStock||0);\r\n  }).length;\r\n\r\n  const scMap={loading:{bg:\"#fffbeb\",border:\"#fde68a\",dot:\"#d97706\",text:\"#92400e\",lbl:\"Loading\u2026\"},saving:{bg:\"#eff6ff\",border:\"#bfdbfe\",dot:\"#2563eb\",text:\"#1d4ed8\",lbl:\"Saving\u2026\"},saved:{bg:\"#f0fdf4\",border:\"#86efac\",dot:\"#16a34a\",text:\"#15803d\",lbl:\"Live \u2713\"},error:{bg:\"#fef2f2\",border:\"#fecaca\",dot:\"#dc2626\",text:\"#b91c1c\",lbl:\"Offline \u2717\"}};\r\n  const sc=scMap[syncStatus]||scMap.saved;\r\n  const syncTime=lastSync?lastSync.toLocaleTimeString(\"en-IN\",{hour:\"2-digit\",minute:\"2-digit\"}):\"\";\r\n\r\n  const NAV={background:\"#f8fafc\",border:\"1px solid #e2e8f0\",color:\"#475569\",borderRadius:6,padding:\"4px 10px\",cursor:\"pointer\",fontFamily:\"inherit\",fontSize:14,fontWeight:600};\r\n  const LBL={display:\"block\",fontSize:11,fontWeight:700,color:\"#475569\",marginBottom:5};\r\n  const INP={width:\"100%\",background:\"#f8fafc\",border:\"1.5px solid #e2e8f0\",color:\"#0f172a\",fontFamily:\"inherit\",fontSize:13,padding:\"7px 10px\",borderRadius:6,outline:\"none\",boxSizing:\"border-box\"};\r\n  const TH={position:\"sticky\",top:0,zIndex:10,background:\"#fff\",borderBottom:\"2px solid #e2e8f0\",fontWeight:700,whiteSpace:\"nowrap\"};\r\n\r\n  if(!loaded)return(\r\n    <div style={{height:\"100vh\",display:\"flex\",alignItems:\"center\",justifyContent:\"center\",flexDirection:\"column\",gap:14,background:\"#f8fafc\"}}>\r\n      <div style={{fontSize:40}}>\ud83c\udfd7\ufe0f<\/div>\r\n      <div style={{fontSize:15,fontWeight:700,color:\"#1e293b\"}}>Lilo Tracker 2026<\/div>\r\n      <div style={{fontSize:12,color:\"#64748b\"}}>Loading from cloud\u2026<\/div>\r\n    <\/div>\r\n  );\r\n\r\n  return(\r\n    <div style={{height:\"100vh\",background:\"#f1f5f9\",fontFamily:\"'Segoe UI',system-ui,sans-serif\",color:\"#1e293b\",display:\"flex\",flexDirection:\"column\",overflow:\"hidden\"}}>\r\n\r\n      {\/* \u2500\u2500 TOP BAR \u2500\u2500 *\/}\r\n      <div style={{background:\"#fff\",borderBottom:\"1px solid #e2e8f0\",padding:\"9px 16px\",display:\"flex\",alignItems:\"center\",gap:10,flexShrink:0,boxShadow:\"0 1px 4px #0000000d\",flexWrap:\"wrap\"}}>\r\n        <div style={{display:\"flex\",alignItems:\"center\",gap:9}}>\r\n          <div style={{width:34,height:34,background:\"linear-gradient(135deg,#16a34a,#4ade80)\",borderRadius:8,display:\"flex\",alignItems:\"center\",justifyContent:\"center\",fontSize:17}}>\ud83c\udfd7\ufe0f<\/div>\r\n          <div>\r\n            <div style={{fontSize:10,color:\"#94a3b8\",letterSpacing:2,textTransform:\"uppercase\",lineHeight:1}}>Lilodhyan Resort<\/div>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#0f172a\",lineHeight:1.3}}>Lilo Tracker 2026<\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        {\/* Page tabs *\/}\r\n        <div style={{display:\"flex\",gap:5,marginLeft:8}}>\r\n          <button onClick={()=>setPage(\"tracker\")} style={{...NAV,background:page===\"tracker\"?\"#1e293b\":\"#f8fafc\",color:page===\"tracker\"?\"#fff\":\"#475569\",padding:\"5px 12px\",fontSize:11,fontWeight:700,border:\"1px solid #e2e8f0\"}}>\r\n            \ud83d\udccb Construction\r\n          <\/button>\r\n          <button onClick={()=>setPage(\"stock\")} style={{...NAV,background:page===\"stock\"?\"#0891b2\":\"#ecfeff\",color:page===\"stock\"?\"#fff\":\"#0891b2\",border:`1px solid ${page===\"stock\"?\"#0891b2\":\"#a5f3fc\"}`,padding:\"5px 12px\",fontSize:11,fontWeight:700,display:\"flex\",alignItems:\"center\",gap:5}}>\r\n            \ud83d\udce6 Stock\r\n            {lowStockC>0&&<span style={{background:\"#dc2626\",color:\"#fff\",borderRadius:10,fontSize:9,fontWeight:800,padding:\"1px 5px\"}}>{lowStockC}<\/span>}\r\n          <\/button>\r\n          <button onClick={()=>setPage(\"agency\")} style={{...NAV,background:page===\"agency\"?\"#7c3aed\":\"#f5f3ff\",color:page===\"agency\"?\"#fff\":\"#7c3aed\",border:`1px solid ${page===\"agency\"?\"#7c3aed\":\"#ddd6fe\"}`,padding:\"5px 12px\",fontSize:11,fontWeight:700,display:\"flex\",alignItems:\"center\",gap:5}}>\r\n            \ud83d\udc65 Agency\r\n            {contractors.length>0&&<span style={{background:\"#7c3aed\",color:\"#fff\",borderRadius:10,fontSize:9,fontWeight:800,padding:\"1px 5px\"}}>{contractors.length}<\/span>}\r\n          <\/button>\r\n        <\/div>\r\n\r\n        <div style={{display:\"flex\",alignItems:\"center\",gap:5}}>\r\n          <button onClick={()=>{const d=new Date(year,month-1);setYear(d.getFullYear());setMonth(d.getMonth());}} style={NAV}>\u2039<\/button>\r\n          <div style={{fontSize:13,fontWeight:700,color:\"#1e293b\",minWidth:138,textAlign:\"center\"}}>{mName}<\/div>\r\n          <button onClick={()=>{const d=new Date(year,month+1);setYear(d.getFullYear());setMonth(d.getMonth());}} style={NAV}>\u203a<\/button>\r\n        <\/div>\r\n\r\n        {page===\"tracker\"&&(\r\n          <div style={{display:\"flex\",gap:5,flexWrap:\"wrap\"}}>\r\n            {[{l:\"Done\",v:doneC,bg:\"#dcfce7\",c:\"#15803d\",b:\"#86efac\"},{l:\"Running\",v:runC,bg:\"#dbeafe\",c:\"#1d4ed8\",b:\"#93c5fd\"},{l:\"Pending\",v:pendC,bg:\"#fee2e2\",c:\"#b91c1c\",b:\"#fca5a5\"},{l:\"Hold\",v:holdC,bg:\"#f3e8ff\",c:\"#6b21a8\",b:\"#d8b4fe\"}].map(s=>(\r\n              <div key={s.l} style={{background:s.bg,border:`1px solid ${s.b}`,borderRadius:20,padding:\"3px 9px\",display:\"flex\",alignItems:\"center\",gap:3}}>\r\n                <span style={{fontSize:13,fontWeight:800,color:s.c}}>{s.v}<\/span>\r\n                <span style={{fontSize:9,color:s.c,fontWeight:700}}>{s.l}<\/span>\r\n              <\/div>\r\n            ))}\r\n          <\/div>\r\n        )}\r\n        {page===\"stock\"&&(\r\n          <div style={{display:\"flex\",gap:5,flexWrap:\"wrap\",alignItems:\"center\"}}>\r\n            <div style={{background:\"#fef2f2\",border:\"1px solid #fecaca\",borderRadius:20,padding:\"3px 9px\",display:\"flex\",alignItems:\"center\",gap:3}}>\r\n              <span style={{fontSize:13,fontWeight:800,color:\"#dc2626\"}}>{lowStockC}<\/span>\r\n              <span style={{fontSize:9,color:\"#dc2626\",fontWeight:700}}>Low Stock<\/span>\r\n            <\/div>\r\n            <div style={{background:\"#f0fdf4\",border:\"1px solid #86efac\",borderRadius:20,padding:\"3px 9px\",display:\"flex\",alignItems:\"center\",gap:3}}>\r\n              <span style={{fontSize:13,fontWeight:800,color:\"#15803d\"}}>{materials.length}<\/span>\r\n              <span style={{fontSize:9,color:\"#15803d\",fontWeight:700}}>Materials<\/span>\r\n            <\/div>\r\n          <\/div>\r\n        )}\r\n\r\n        <div style={{marginLeft:\"auto\",display:\"flex\",gap:7,alignItems:\"center\",flexWrap:\"wrap\"}}>\r\n          <div style={{background:sc.bg,border:`1px solid ${sc.border}`,borderRadius:20,padding:\"4px 10px\",display:\"flex\",alignItems:\"center\",gap:5,cursor:\"pointer\"}}\r\n            onClick={async()=>{const d=await apiLoad();if(d){if(d.tasks&&d.tasks.length)setTasks(d.tasks);if(d.grid)setGrid(d.grid);if(d.dayMeta)setDayMeta(d.dayMeta);if(d.taskMeta)setTaskMeta(d.taskMeta);if(d.customAreas)setCustomAreas(d.customAreas);if(d.materials&&d.materials.length)setMaterials(d.materials);if(d.stockEntries)setStockEntries(d.stockEntries);if(d.contractors&&d.contractors.length)setContractors(d.contractors);if(d.bills&&d.bills.length)setBills(d.bills);if(d.trades&&d.trades.length)setTrades(d.trades);setSyncStatus(\"saved\");setLastSync(new Date());}}}>\r\n            <div style={{width:7,height:7,borderRadius:\"50%\",background:sc.dot}}\/>\r\n            <span style={{fontSize:10,color:sc.text,fontWeight:700}}>{sc.lbl}<\/span>\r\n            {syncTime&&<span style={{fontSize:9,color:sc.text,opacity:0.7}}>{syncTime}<\/span>}\r\n          <\/div>\r\n\r\n          {page===\"tracker\"&&(\r\n            <>\r\n              <div style={{background:\"#dcfce7\",border:\"1px solid #86efac\",borderRadius:7,padding:\"4px 9px\"}}>\r\n                <span style={{fontSize:14,fontWeight:800,color:\"#15803d\"}}>{totalWD}<\/span>\r\n                <span style={{fontSize:9,color:\"#4ade80\",marginLeft:3}}>days<\/span>\r\n              <\/div>\r\n              <div style={{background:\"#dbeafe\",border:\"1px solid #93c5fd\",borderRadius:7,padding:\"4px 9px\"}}>\r\n                <span style={{fontSize:14,fontWeight:800,color:\"#1d4ed8\"}}>{filled}<\/span>\r\n                <span style={{fontSize:9,color:\"#60a5fa\",marginLeft:3}}>entries<\/span>\r\n              <\/div>\r\n              <button onClick={()=>setShowAdd(true)} style={{background:\"#0f172a\",color:\"#fff\",border:\"none\",borderRadius:6,padding:\"6px 12px\",fontSize:12,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>\uff0b Add Task<\/button>\r\n              <button onClick={()=>setView(v=>v===\"grid\"?\"summary\":\"grid\")} style={{...NAV,padding:\"6px 10px\",fontSize:11,fontWeight:700,background:view===\"summary\"?\"#1e293b\":\"#f8fafc\",color:view===\"summary\"?\"#fff\":\"#475569\"}}>\r\n                {view===\"grid\"?\"\ud83d\udcca\":\"\ud83d\udccb\"}\r\n              <\/button>\r\n            <\/>\r\n          )}\r\n        <\/div>\r\n      <\/div>\r\n\r\n      {\/* \u2500\u2500 ADD TASK MODAL \u2500\u2500 *\/}\r\n      {showAdd&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>setShowAdd(false)}>\r\n          <div style={{background:\"#fff\",borderRadius:14,padding:26,width:400,boxShadow:\"0 24px 64px #0000003a\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:17,fontWeight:800,color:\"#0f172a\",marginBottom:18}}>\u2795 Add New Task<\/div>\r\n            <div style={{marginBottom:12}}><label style={LBL}>Task Name *<\/label>\r\n              <input autoFocus value={newTask.name} onChange={e=>setNewTask(p=>({...p,name:e.target.value}))} placeholder=\"e.g. Jungle Pool Tiling\" onKeyDown={e=>e.key===\"Enter\"&&addTask()} style={INP}\/>\r\n            <\/div>\r\n            <div style={{display:\"grid\",gridTemplateColumns:\"1fr 1fr\",gap:12,marginBottom:12}}>\r\n              <div><label style={LBL}>Area<\/label>\r\n                <select value={newTask.area} onChange={e=>setNewTask(p=>({...p,area:e.target.value}))} style={INP}>\r\n                  {allAreasList.map(a=><option key={a}>{a}<\/option>)}<option value=\"Other\">Other<\/option>\r\n                <\/select>\r\n              <\/div>\r\n              <div><label style={LBL}>Status<\/label>\r\n                <select value={newTask.status} onChange={e=>setNewTask(p=>({...p,status:e.target.value}))} style={INP}>\r\n                  <option>Pending<\/option><option>Running<\/option><option>Hold<\/option><option>Done<\/option>\r\n                <\/select>\r\n              <\/div>\r\n            <\/div>\r\n            <div style={{marginBottom:12}}><label style={LBL}>Assigned To<\/label>\r\n              <input value={newTask.assignee||\"\"} onChange={e=>setNewTask(p=>({...p,assignee:e.target.value}))} placeholder=\"e.g. Ashok bhai\" style={INP}\/>\r\n            <\/div>\r\n            <div style={{marginBottom:20}}><label style={LBL}>Progress % (0\u2013100)<\/label>\r\n              <input type=\"number\" min={0} max={100} value={newTask.pct} onChange={e=>setNewTask(p=>({...p,pct:e.target.value}))} style={INP}\/>\r\n            <\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\"}}>\r\n              <button onClick={()=>setShowAdd(false)} style={{...NAV,padding:\"8px 18px\",fontSize:13}}>Cancel<\/button>\r\n              <button onClick={addTask} disabled={!newTask.name.trim()} style={{background:newTask.name.trim()?\"#0f172a\":\"#cbd5e1\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"8px 20px\",fontSize:13,fontWeight:700,cursor:newTask.name.trim()?\"pointer\":\"not-allowed\",fontFamily:\"inherit\"}}>Add Task<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 DELETE TASK MODAL \u2500\u2500 *\/}\r\n      {delConfirm&&(\r\n        <div style={{position:\"fixed\",inset:0,background:\"#00000060\",zIndex:200,display:\"flex\",alignItems:\"center\",justifyContent:\"center\"}} onClick={()=>setDelConfirm(null)}>\r\n          <div style={{background:\"#fff\",borderRadius:12,padding:24,width:320,boxShadow:\"0 20px 60px #00000030\"}} onClick={e=>e.stopPropagation()}>\r\n            <div style={{fontSize:15,fontWeight:800,color:\"#b91c1c\",marginBottom:8}}>\ud83d\uddd1\ufe0f Delete Task?<\/div>\r\n            <div style={{fontSize:13,color:\"#475569\",marginBottom:20}}><b>\"{tasks.find(t=>t.id===delConfirm)&&tasks.find(t=>t.id===delConfirm).name}\"<\/b> will be removed.<\/div>\r\n            <div style={{display:\"flex\",gap:10,justifyContent:\"flex-end\"}}>\r\n              <button onClick={()=>setDelConfirm(null)} style={{...NAV,padding:\"7px 16px\",fontSize:12}}>Cancel<\/button>\r\n              <button onClick={()=>deleteTask(delConfirm)} style={{background:\"#dc2626\",color:\"#fff\",border:\"none\",borderRadius:7,padding:\"7px 18px\",fontSize:12,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>Delete<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 STOCK PAGE \u2500\u2500 *\/}\r\n      {page===\"stock\"&&(\r\n        <StockPage year={year} month={month} setYear={setYear} setMonth={setMonth}\r\n          materials={materials} setMaterials={setMaterials}\r\n          stockEntries={stockEntries} setStockEntries={setStockEntries}\r\n          onSave={(se,mats)=>saveStock(se,mats)}\r\n        \/>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 AGENCY PAGE \u2500\u2500 *\/}\r\n      {page===\"agency\"&&(\r\n        <AgencyPage contractors={contractors} setContractors={setContractors}\r\n          bills={bills} setBills={setBills}\r\n          customAreas={customAreas} setCustomAreas={setCustomAreas}\r\n          trades={trades} setTrades={setTrades}\r\n          onSave={(cons,bls,tr,ca)=>saveAgency(cons,bls,tr,ca)}\r\n          year={year} month={month}\r\n        \/>\r\n      )}\r\n\r\n      {\/* \u2500\u2500 TRACKER PAGE \u2500\u2500 *\/}\r\n      {page===\"tracker\"&&view===\"summary\"&&(\r\n        <div style={{flex:1,overflowY:\"auto\",padding:20}}>\r\n          <div style={{display:\"grid\",gridTemplateColumns:\"repeat(auto-fill,minmax(260px,1fr))\",gap:14}}>\r\n            {sortTasks(tasks).map(t=>{\r\n              const wd=getTaskDays(t.id);const sm=SM[t.status]||SM[\"Pending\"];\r\n              const ac=AC[t.area]||\"#475569\";const al=AL[t.area]||\"#f8fafc\";const ab=AB[t.area]||\"#e2e8f0\";\r\n              const di=getDelay(t.id);const tm=taskMeta[t.id]||{};\r\n              const ed=parseInt(tm.estDays)||0;\r\n              const dp=ed>0?Math.min(100,Math.round(wd\/ed*100)):t.status===\"Done\"?100:t.pct;\r\n              const pp=100-dp;\r\n              return(\r\n                <div key={t.id} style={{background:\"#fff\",border:`1px solid ${ab}`,borderTop:`3px solid ${ac}`,borderRadius:10,padding:14,boxShadow:\"0 1px 4px #00000008\"}}>\r\n                  <div style={{display:\"flex\",justifyContent:\"space-between\",alignItems:\"flex-start\",marginBottom:6}}>\r\n                    <div style={{fontSize:13,fontWeight:700,color:\"#0f172a\",lineHeight:1.4,flex:1}}>{t.name}<\/div>\r\n                    <button onClick={()=>cycleStatus(t.id)} style={{background:sm.bg,color:sm.color,fontSize:10,fontWeight:800,padding:\"3px 7px\",borderRadius:10,marginLeft:6,border:`1.5px solid ${sm.border}`,cursor:\"pointer\",fontFamily:\"inherit\",whiteSpace:\"nowrap\"}}>{sm.icon} {t.status}<\/button>\r\n                  <\/div>\r\n                  {(t.assignee||tm.assignee)&&<div style={{fontSize:11,color:\"#0891b2\",marginBottom:5}}>\ud83d\udc77 {tm.assignee||t.assignee}<\/div>}\r\n                  <div style={{display:\"flex\",gap:10,marginBottom:6,flexWrap:\"wrap\"}}>\r\n                    <div style={{textAlign:\"center\"}}><div style={{fontSize:17,fontWeight:700,color:ac}}>{wd}<\/div><div style={{fontSize:9,color:\"#94a3b8\"}}>days<\/div><\/div>\r\n                    {tm.estDays&&<div style={{textAlign:\"center\"}}><div style={{fontSize:17,fontWeight:700,color:\"#475569\"}}>{tm.estDays}<\/div><div style={{fontSize:9,color:\"#94a3b8\"}}>est<\/div><\/div>}\r\n                    <div style={{textAlign:\"center\"}}><div style={{fontSize:17,fontWeight:700,color:dp>=100?\"#15803d\":dp>=50?\"#1d4ed8\":dp>0?\"#d97706\":\"#b91c1c\"}}>{dp}%<\/div><\/div>\r\n                    {di.label&&<div style={{background:di.bg,color:di.color,fontSize:10,fontWeight:700,padding:\"2px 8px\",borderRadius:8,alignSelf:\"center\"}}>{di.icon} {di.label}<\/div>}\r\n                  <\/div>\r\n                  {tm.comment&&<div style={{fontSize:11,color:\"#475569\",background:\"#f8fafc\",borderRadius:5,padding:\"4px 8px\",marginBottom:6}}>\ud83d\udcac {tm.comment}<\/div>}\r\n                  <div style={{display:\"flex\",gap:2,flexWrap:\"wrap\"}}>\r\n                    {days.map(d=>{const c=grid[cKey(t.id,d)];const isT=toKey(year,month,d)===todayKey;return <div key={d} style={{width:12,height:12,borderRadius:2,background:c&&c.done?ac:\"#f1f5f9\",border:isT?`1px solid ${ac}`:\"1px solid #e2e8f0\"}} title={\"Day \"+d+(c&&c.done?\": \"+c.pct+\"%\":\"\")}\/>;  })}\r\n                  <\/div>\r\n                <\/div>\r\n              );\r\n            })}\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n\r\n      {page===\"tracker\"&&view===\"grid\"&&(\r\n        <div style={{flex:1,display:\"flex\",flexDirection:\"column\",overflow:\"hidden\"}}>\r\n          {\/* Area tabs *\/}\r\n          <div style={{padding:\"7px 14px\",background:\"#fff\",borderBottom:\"1px solid #e2e8f0\",display:\"flex\",gap:5,flexWrap:\"wrap\",flexShrink:0,alignItems:\"center\"}}>\r\n            {allAreas.map(a=>{const ac=a===\"All\"?\"#475569\":AC[a]||\"#475569\";const al=a===\"All\"?\"#f8fafc\":AL[a]||\"#f8fafc\";const ab=a===\"All\"?\"#e2e8f0\":AB[a]||\"#e2e8f0\";const active=activeArea===a;return <button key={a} onClick={()=>setActiveArea(a)} style={{padding:\"4px 11px\",borderRadius:20,border:`1px solid ${active?ac:ab}`,background:active?ac:al,color:active?\"#fff\":ac,cursor:\"pointer\",fontSize:10,fontWeight:700,fontFamily:\"inherit\"}}>{a}<\/button>;})}\r\n            {showAddArea?(\r\n              <div style={{display:\"flex\",alignItems:\"center\",gap:4}}>\r\n                <input autoFocus value={newAreaName} onChange={e=>setNewAreaName(e.target.value)} placeholder=\"Area name\u2026\" onKeyDown={e=>{if(e.key===\"Enter\")addArea();if(e.key===\"Escape\")setShowAddArea(false);}} style={{fontSize:11,padding:\"3px 8px\",border:\"1.5px solid #2563eb\",borderRadius:6,outline:\"none\",fontFamily:\"inherit\",width:110}}\/>\r\n                <button onClick={addArea} style={{background:\"#2563eb\",color:\"#fff\",border:\"none\",borderRadius:5,padding:\"3px 8px\",fontSize:11,fontWeight:700,cursor:\"pointer\",fontFamily:\"inherit\"}}>Add<\/button>\r\n                <button onClick={()=>setShowAddArea(false)} style={{background:\"none\",border:\"none\",cursor:\"pointer\",fontSize:13,color:\"#94a3b8\",padding:\"2px\"}}>\u2715<\/button>\r\n              <\/div>\r\n            ):(\r\n              <button onClick={()=>setShowAddArea(true)} style={{padding:\"4px 10px\",borderRadius:20,border:\"1px dashed #cbd5e1\",background:\"#f8fafc\",color:\"#64748b\",cursor:\"pointer\",fontSize:10,fontWeight:700,fontFamily:\"inherit\"}}>\uff0b Area<\/button>\r\n            )}\r\n            <div style={{marginLeft:\"auto\",display:\"flex\",gap:6,fontSize:10,alignItems:\"center\"}}>\r\n              <span style={{background:\"#dcfce7\",color:\"#15803d\",padding:\"2px 7px\",borderRadius:6,fontWeight:700,border:\"1px solid #86efac\"}}>\u2705 On track<\/span>\r\n              <span style={{background:\"#fffbeb\",color:\"#d97706\",padding:\"2px 7px\",borderRadius:6,fontWeight:700,border:\"1px solid #fde68a\"}}>\u26a0\ufe0f At risk<\/span>\r\n              <span style={{background:\"#fee2e2\",color:\"#b91c1c\",padding:\"2px 7px\",borderRadius:6,fontWeight:700,border:\"1px solid #fca5a5\"}}>\ud83d\udea8 Overdue<\/span>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div style={{flex:1,overflow:\"auto\"}}>\r\n            <table style={{borderCollapse:\"collapse\",minWidth:\"100%\",background:\"#fff\"}}>\r\n              <thead>\r\n                <tr>\r\n                  <th style={{...TH,minWidth:185,maxWidth:185,position:\"sticky\",left:0,zIndex:20,background:\"#fff\",textAlign:\"left\",padding:\"8px 10px\",borderRight:\"1px solid #e2e8f0\"}}><span style={{fontSize:11,fontWeight:800,color:\"#1e293b\",textTransform:\"uppercase\"}}>Task<\/span><\/th>\r\n                  <th style={{...TH,minWidth:90,background:\"#fff\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 5px\"}}><div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Status<\/div><\/th>\r\n                  <th style={{...TH,minWidth:100,background:\"#f0f9ff\",borderRight:\"1px solid #bae6fd\",padding:\"5px 6px\"}}><div style={{fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Assigned To<\/div><\/th>\r\n                  <th style={{...TH,minWidth:58,background:\"#fffbeb\",borderRight:\"1px solid #fde68a\",padding:\"5px 4px\"}}><div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Est<br\/>Days<\/div><\/th>\r\n                  <th style={{...TH,minWidth:86,background:\"#f0fdf4\",borderRight:\"2px solid #e2e8f0\",padding:\"5px 4px\"}}><div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Finish<br\/>Date<\/div><\/th>\r\n                  <th style={{...TH,minWidth:52,background:\"#f8fafc\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 4px\"}}><div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Days<br\/>Done<\/div><\/th>\r\n                  <th style={{...TH,minWidth:155,background:\"#fafafa\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 8px\"}}><div style={{fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Comment<\/div><\/th>\r\n                  <th style={{...TH,minWidth:52,background:\"#f0fdf4\",borderRight:\"2px solid #e2e8f0\",padding:\"5px 4px\"}}><div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Overall<br\/>%<\/div><\/th>\r\n                  {days.map(d=>{\r\n                    const dk=toKey(year,month,d);const isT=dk===todayKey;const meta=dayMeta[dk];const cnt=getDayCount(d);const isWE=[0,6].includes(new Date(year,month,d).getDay());\r\n                    return(\r\n                      <th key={d} style={{...TH,minWidth:36,maxWidth:36,padding:\"2px 1px\",background:isT?\"#eff6ff\":isWE?\"#fafafa\":\"#fff\",borderRight:`1px solid ${isT?\"#93c5fd\":\"#f1f5f9\"}`}}>\r\n                        <div style={{textAlign:\"center\"}}>\r\n                          <div style={{fontSize:8,color:isT?\"#2563eb\":isWE?\"#64748b\":\"#475569\",fontWeight:isT?800:600}}>{DN[new Date(year,month,d).getDay()]}<\/div>\r\n                          <div style={{fontSize:12,fontWeight:800,color:isT?\"#2563eb\":isWE?\"#475569\":\"#1e293b\",lineHeight:1.2}}>{d}<\/div>\r\n                          <div style={{display:\"flex\",justifyContent:\"center\",gap:1}}>\r\n                            <button onClick={()=>setDayStatus(d,\"nowork\")} style={{background:\"none\",border:\"none\",cursor:\"pointer\",padding:0,fontSize:8,opacity:meta&&meta.status===\"nowork\"?1:0.2}}>\ud83d\udd34<\/button>\r\n                            <button onClick={()=>setDayStatus(d,\"holiday\")} style={{background:\"none\",border:\"none\",cursor:\"pointer\",padding:0,fontSize:8,opacity:meta&&meta.status===\"holiday\"?1:0.2}}>\ud83c\udf34<\/button>\r\n                          <\/div>\r\n                          {cnt>0&&<div style={{fontSize:9,fontWeight:800,color:\"#16a34a\",lineHeight:1}}>{cnt}<\/div>}\r\n                        <\/div>\r\n                      <\/th>\r\n                    );\r\n                  })}\r\n                  <th style={{...TH,minWidth:30,background:\"#fff\"}}\/>\r\n                <\/tr>\r\n              <\/thead>\r\n              <tbody>\r\n                {filtered.map((t,ti)=>{\r\n                  const ac=AC[t.area]||\"#475569\";const al=AL[t.area]||\"#f8fafc\";const ab=AB[t.area]||\"#e2e8f0\";\r\n                  const sm=SM[t.status]||SM[\"Pending\"];\r\n                  const wd=getTaskDays(t.id);const di=getDelay(t.id);const tm=taskMeta[t.id]||{};\r\n                  const showLbl=activeArea===\"All\"&&(ti===0||filtered[ti-1].area!==t.area);\r\n                  const isEE=editField&&editField.tid===t.id&&editField.field===\"estDays\";\r\n                  const isED=editField&&editField.tid===t.id&&editField.field===\"finishDate\";\r\n                  const isEN=editTask===t.id;\r\n                  const isEA=editField&&editField.tid===t.id&&editField.field===\"assignee\";\r\n                  const isCom=editField&&editField.tid===t.id&&editField.field===\"comment\";\r\n                  const holdBorder=t.status===\"Hold\"?(di.label&&di.label.includes(\"overdue\")?\"#dc2626\":di.label?\"#d97706\":\"#a855f7\"):ac;\r\n                  const ed=parseInt(tm.estDays)||0;\r\n                  const dp=ed>0?Math.min(100,Math.round(wd\/ed*100)):t.status===\"Done\"?100:t.pct;\r\n                  const dpc=dp>=100?\"#15803d\":dp>=50?\"#1d4ed8\":dp>0?\"#d97706\":\"#b91c1c\";\r\n                  const sug=suggestEst(t.id);\r\n                  const assigneeName=tm.assignee||t.assignee||\"\";\r\n                  return(\r\n                    <React.Fragment key={t.id}>\r\n                    {showLbl&&(<tr><td colSpan={days.length+10} style={{background:\"#f8fafc\",padding:\"5px 12px\",borderTop:\"2px solid #e2e8f0\",borderBottom:\"1px solid #e2e8f0\"}}><div style={{display:\"flex\",alignItems:\"center\",gap:6}}><div style={{width:10,height:10,background:ac,borderRadius:2}}\/><span style={{fontSize:10,fontWeight:800,color:ac,letterSpacing:1,textTransform:\"uppercase\"}}>{t.area}<\/span><\/div><\/td><\/tr>)}\r\n                    <tr style={{background:ti%2===0?\"#fff\":\"#fafcff\"}}>\r\n                      <td style={{position:\"sticky\",left:0,zIndex:5,background:al,borderLeft:`3px solid ${holdBorder}`,borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab}`,padding:\"5px 8px\",minWidth:185,maxWidth:185}}>\r\n                        {isEN?(<input autoFocus defaultValue={t.name} onBlur={e=>{renameTask(t.id,e.target.value||t.name);setEditTask(null);}} onKeyDown={e=>{if(e.key===\"Enter\"){renameTask(t.id,e.target.value||t.name);setEditTask(null);}if(e.key===\"Escape\")setEditTask(null);}} style={{width:\"100%\",background:\"#fff\",border:`2px solid ${ac}`,color:\"#0f172a\",fontFamily:\"inherit\",fontSize:13,fontWeight:700,padding:\"3px 6px\",borderRadius:5,outline:\"none\",boxSizing:\"border-box\"}}\/>):(<div style={{fontSize:13,fontWeight:700,color:\"#0f172a\",whiteSpace:\"nowrap\",overflow:\"hidden\",textOverflow:\"ellipsis\",cursor:\"text\"}} onDoubleClick={()=>setEditTask(t.id)} title={t.name}>{t.name}<\/div>)}\r\n                      <\/td>\r\n                      <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab}`,textAlign:\"center\",padding:\"5px 4px\"}}>\r\n                        <button onClick={()=>cycleStatus(t.id)} style={{background:sm.bg,color:sm.color,border:`1.5px solid ${sm.border}`,borderRadius:8,padding:\"4px 7px\",cursor:\"pointer\",fontFamily:\"inherit\",fontSize:11,fontWeight:800,display:\"inline-flex\",alignItems:\"center\",gap:3,whiteSpace:\"nowrap\"}}>{sm.icon} {t.status}<\/button>\r\n                      <\/td>\r\n                      <td style={{borderRight:\"1px solid #bae6fd\",borderBottom:`1px solid ${ab}`,background:\"#f0f9ff55\",padding:\"3px 6px\",minWidth:100,cursor:\"pointer\"}} onClick={()=>setEditField({tid:t.id,field:\"assignee\"})}>\r\n                        {isEA?(<input autoFocus defaultValue={assigneeName} placeholder=\"Name\u2026\" onBlur={e=>{updateTM(t.id,\"assignee\",e.target.value);setEditField(null);}} onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){updateTM(t.id,\"assignee\",e.target.value);setEditField(null);}}} style={{width:\"100%\",background:\"#fff\",border:\"2px solid #0891b2\",color:\"#0f172a\",fontFamily:\"inherit\",fontSize:13,padding:\"2px 5px\",borderRadius:4,outline:\"none\",boxSizing:\"border-box\"}}\/>):(<div style={{fontSize:13,color:assigneeName?\"#0f172a\":\"#cbd5e1\",whiteSpace:\"nowrap\",overflow:\"hidden\",textOverflow:\"ellipsis\"}}>{assigneeName||\"+ assign\u2026\"}<\/div>)}\r\n                      <\/td>\r\n                      <td style={{borderRight:\"1px solid #fde68a\",borderBottom:`1px solid ${ab}`,background:\"#fffbeb55\",textAlign:\"center\",padding:\"3px 4px\",cursor:\"pointer\"}} onClick={()=>setEditField({tid:t.id,field:\"estDays\"})}>\r\n                        {isEE?(<input autoFocus type=\"number\" min={1} max={999} defaultValue={tm.estDays||\"\"} onBlur={e=>{updateTM(t.id,\"estDays\",e.target.value);setEditField(null);}} onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){updateTM(t.id,\"estDays\",e.target.value);setEditField(null);}}} style={{width:44,background:\"#fff\",border:\"2px solid #d97706\",color:\"#92400e\",fontFamily:\"inherit\",fontSize:13,fontWeight:700,textAlign:\"center\",borderRadius:4,padding:\"2px 0\",outline:\"none\"}}\/>)\r\n                        :tm.estDays?(<div style={{fontSize:14,fontWeight:800,color:\"#92400e\"}}>{tm.estDays}<\/div>)\r\n                        :sug&&t.status!==\"Done\"?(<div onClick={e=>{e.stopPropagation();updateTM(t.id,\"estDays\",String(sug));}} style={{background:\"#fef3c7\",border:\"1px dashed #d97706\",borderRadius:5,padding:\"2px 3px\",cursor:\"pointer\",display:\"inline-block\"}}><div style={{fontSize:12,fontWeight:800,color:\"#92400e\"}}>~{sug}d<\/div><div style={{fontSize:8,color:\"#d97706\"}}>tap<\/div><\/div>)\r\n                        :(<div style={{color:\"#d97706\",fontSize:18,opacity:0.3}}>+<\/div>)}\r\n                      <\/td>\r\n                      <td style={{borderRight:\"2px solid #e2e8f0\",borderBottom:`1px solid ${ab}`,background:\"#f0fdf455\",textAlign:\"center\",padding:\"3px 4px\",cursor:\"pointer\"}} onClick={()=>setEditField({tid:t.id,field:\"finishDate\"})}>\r\n                        {isED?(<input autoFocus type=\"date\" defaultValue={tm.finishDate||\"\"} onBlur={e=>{updateTM(t.id,\"finishDate\",e.target.value);setEditField(null);}} onKeyDown={e=>{if([\"Enter\",\"Escape\"].includes(e.key)){updateTM(t.id,\"finishDate\",e.target.value);setEditField(null);}}} style={{width:108,background:\"#fff\",border:\"2px solid #16a34a\",color:\"#15803d\",fontFamily:\"inherit\",fontSize:11,fontWeight:600,textAlign:\"center\",borderRadius:4,padding:\"3px 3px\",outline:\"none\"}}\/>)\r\n                        :tm.finishDate?(<div><div style={{fontSize:12,fontWeight:800,color:\"#15803d\"}}>{fmtD(pDate(tm.finishDate))}<\/div>{di.label&&<div style={{background:di.bg,color:di.color,fontSize:8,fontWeight:700,padding:\"1px 5px\",borderRadius:6,marginTop:2,whiteSpace:\"nowrap\"}}>{di.icon} {di.label}<\/div>}<\/div>)\r\n                        :(<div style={{color:\"#16a34a\",fontSize:18,opacity:0.3}}>+<\/div>)}\r\n                      <\/td>\r\n                      <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab}`,background:\"#f8fafc\",textAlign:\"center\",padding:\"4px 4px\"}}>\r\n                        <div style={{fontSize:17,fontWeight:800,color:wd>0?ac:\"#cbd5e1\"}}>{wd||\"\u2014\"}<\/div>\r\n                      <\/td>\r\n                      <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab}`,background:\"#fafafa\",padding:\"3px 6px\",minWidth:155}}>\r\n                        {isCom?(<textarea autoFocus defaultValue={tm.comment||\"\"} onBlur={e=>{updateTM(t.id,\"comment\",e.target.value);setEditField(null);}} onKeyDown={e=>{if(e.key===\"Escape\")setEditField(null);}} style={{width:\"100%\",background:\"#fff\",border:\"2px solid #475569\",color:\"#1e293b\",fontFamily:\"inherit\",fontSize:13,padding:\"3px 6px\",borderRadius:4,outline:\"none\",resize:\"none\",height:42,boxSizing:\"border-box\"}}\/>)\r\n                        :(<div onClick={()=>setEditField({tid:t.id,field:\"comment\"})} style={{fontSize:13,fontWeight:400,color:tm.comment?\"#1e293b\":\"#cbd5e1\",cursor:\"text\",minHeight:28,lineHeight:1.4,padding:\"2px 0\",whiteSpace:\"pre-wrap\",wordBreak:\"break-word\"}}>{tm.comment||\"+ add comment\u2026\"}<\/div>)}\r\n                      <\/td>\r\n                      <td style={{borderRight:\"2px solid #e2e8f0\",borderBottom:`1px solid ${ab}`,background:\"#f0fdf455\",textAlign:\"center\",padding:\"4px 4px\"}}>\r\n                        <div style={{fontSize:16,fontWeight:800,color:dpc}}>{dp}%<\/div>\r\n                      <\/td>\r\n                      {days.map(d=>{\r\n                        const dk=toKey(year,month,d);const k=cKey(t.id,d);const cell=grid[k];const isDone=cell&&cell.done;const pct=cell?cell.pct:t.pct;\r\n                        const isT=dk===todayKey;const meta=dayMeta[dk];const isNW=meta&&meta.status===\"nowork\";const isHL=meta&&meta.status===\"holiday\";\r\n                        const isSel=selCell&&selCell.tid===t.id&&selCell.day===d;const isWE=[0,6].includes(new Date(year,month,d).getDay());\r\n                        let bg=isT?\"#eff6ff\":isWE?\"#fafafa\":\"#fff\";if(isDone)bg=al;if(isNW||isHL)bg=\"#fafafa\";\r\n                        return(\r\n                          <td key={d} style={{borderRight:`1px solid ${isT?\"#bfdbfe\":\"#f1f5f9\"}`,borderBottom:`1px solid ${ab}`,background:bg,padding:0,minWidth:36,maxWidth:36,textAlign:\"center\",verticalAlign:\"middle\",cursor:isNW||isHL?\"default\":\"pointer\"}}>\r\n                            {isNW||isHL?(<div style={{padding:\"7px 0\",fontSize:10,color:\"#cbd5e1\"}}>{isHL?\"\ud83c\udf34\":\"\u2014\"}<\/div>)\r\n                            :isSel?(<div style={{padding:\"3px\"}}><input autoFocus type=\"number\" min={0} max={100} defaultValue={pct} onBlur={e=>{updatePct(t.id,d,e.target.value);setSelCell(null);}} onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){updatePct(t.id,d,e.target.value);setSelCell(null);}}} style={{width:30,background:\"#fff\",border:`2px solid ${ac}`,color:ac,fontFamily:\"inherit\",fontSize:12,fontWeight:700,textAlign:\"center\",borderRadius:4,padding:\"2px 0\",outline:\"none\"}}\/><\/div>)\r\n                            :(<div onClick={()=>toggleCell(t.id,d)} onDoubleClick={()=>{if(isDone)setSelCell({tid:t.id,day:d});}} style={{padding:\"3px 2px\",display:\"flex\",flexDirection:\"column\",alignItems:\"center\",justifyContent:\"center\",minHeight:32,userSelect:\"none\"}}>\r\n                              {isDone?(<><div style={{width:20,height:20,borderRadius:4,background:ac,display:\"flex\",alignItems:\"center\",justifyContent:\"center\",boxShadow:`0 2px 5px ${ac}44`}}><span style={{fontSize:11,color:\"#fff\",fontWeight:900}}>\u2713<\/span><\/div><div style={{fontSize:8,color:ac,fontWeight:700,marginTop:1}}>{pct}%<\/div><\/>)\r\n                              :(<div style={{width:20,height:20,borderRadius:4,border:`1.5px solid ${isT?\"#bfdbfe\":\"#e2e8f0\"}`,background:isT?\"#f0f9ff\":\"transparent\"}}\/>)}\r\n                            <\/div>)}\r\n                          <\/td>\r\n                        );\r\n                      })}\r\n                      <td style={{borderBottom:`1px solid ${ab}`,background:\"#fff\",textAlign:\"center\",padding:\"0 2px\"}}>\r\n                        <button onClick={()=>setDelConfirm(t.id)} style={{background:\"none\",border:\"none\",cursor:\"pointer\",color:\"#fca5a5\",fontSize:13,padding:\"4px\",opacity:0.4}} onMouseEnter={e=>e.currentTarget.style.opacity=1} onMouseLeave={e=>e.currentTarget.style.opacity=0.4}>\u2715<\/button>\r\n                      <\/td>\r\n                    <\/tr>\r\n                    <\/React.Fragment>\r\n                  );\r\n                })}\r\n                <tr><td colSpan={days.length+10} style={{background:\"#f8fafc\",padding:\"6px 14px\",borderTop:\"2px dashed #e2e8f0\"}}><button onClick={()=>setShowAdd(true)} style={{background:\"none\",border:\"none\",color:\"#94a3b8\",cursor:\"pointer\",fontSize:12,fontWeight:700,fontFamily:\"inherit\",display:\"flex\",alignItems:\"center\",gap:6,padding:\"2px 0\"}}><span style={{fontSize:18,color:\"#cbd5e1\"}}>\uff0b<\/span> Add new task row\u2026<\/button><\/td><\/tr>\r\n                <tr style={{position:\"sticky\",bottom:0,zIndex:10}}>\r\n                  <td style={{position:\"sticky\",left:0,zIndex:11,background:\"#f8fafc\",borderTop:\"2px solid #e2e8f0\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 12px\"}}><span style={{fontSize:10,fontWeight:800,color:\"#1e293b\"}}>TASKS \/ DAY<\/span><\/td>\r\n                  <td colSpan={7} style={{background:\"#f8fafc\",borderTop:\"2px solid #e2e8f0\",borderRight:\"2px solid #e2e8f0\"}}\/>\r\n                  {days.map(d=>{const cnt=getDayCount(d);const isT=toKey(year,month,d)===todayKey;return(<td key={d} style={{background:isT?\"#eff6ff\":\"#f8fafc\",borderTop:\"2px solid #e2e8f0\",borderRight:`1px solid ${isT?\"#bfdbfe\":\"#f1f5f9\"}`,textAlign:\"center\",padding:\"4px 2px\"}}><div style={{fontSize:12,fontWeight:800,color:cnt>0?\"#16a34a\":\"#e2e8f0\"}}>{cnt||\"\"}<\/div>{cnt>0&&<div style={{height:3,background:\"#16a34a\",opacity:0.3+cnt\/tasks.length*0.7,margin:\"2px 4px\",borderRadius:2}}\/>}<\/td>);})}\r\n                  <td style={{background:\"#f8fafc\",borderTop:\"2px solid #e2e8f0\"}}\/>\r\n                <\/tr>\r\n              <\/tbody>\r\n            <\/table>\r\n          <\/div>\r\n          <div style={{background:\"#fff\",borderTop:\"1px solid #e2e8f0\",padding:\"5px 14px\",display:\"flex\",gap:14,alignItems:\"center\",flexShrink:0}}>\r\n            <div style={{display:\"flex\",gap:12,fontSize:10,color:\"#94a3b8\"}}>\r\n              <span><b style={{color:\"#1e293b\"}}>Status<\/b> = click cycle<\/span>\r\n              <span><b style={{color:\"#1e293b\"}}>Task<\/b> = dbl-click rename<\/span>\r\n              <span><b style={{color:\"#1e293b\"}}>Cell<\/b> = click mark \u00b7 dbl-click % edit<\/span>\r\n              <span style={{color:\"#16a34a\",fontWeight:700}}>\ud83d\udd04 Auto-sync 25s<\/span>\r\n            <\/div>\r\n            <div style={{marginLeft:\"auto\",fontSize:10,color:\"#94a3b8\"}}>{tasks.length} tasks \u00b7 {filled} entries \u00b7 {mName}<\/div>\r\n          <\/div>\r\n        <\/div>\r\n      )}\r\n    <\/div>\r\n  );\r\n}\r\n\r\nReactDOM.createRoot(document.getElementById(\"root\")).render(<App\/>);\r\n<\/script>\r\n<\/body>\r\n<\/html>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Lilo Tracker 2026<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-9723","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/pages\/9723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/comments?post=9723"}],"version-history":[{"count":19,"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/pages\/9723\/revisions"}],"predecessor-version":[{"id":9746,"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/pages\/9723\/revisions\/9746"}],"wp:attachment":[{"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/media?parent=9723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}