{"id":9652,"date":"2026-05-16T13:42:29","date_gmt":"2026-05-16T08:12:29","guid":{"rendered":"https:\/\/lilodhyanresort.com\/?page_id=9652"},"modified":"2026-05-16T14:00:32","modified_gmt":"2026-05-16T08:30:32","slug":"site-tracker","status":"publish","type":"page","link":"https:\/\/lilodhyanresort.com\/index.php\/site-tracker\/","title":{"rendered":"Site Tracker"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"9652\" class=\"elementor elementor-9652\">\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\n  body{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\n  input::-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}=React;\r\n\r\nconst DEFAULT_TASKS=[\r\n  {id:\"t1\", name:\"Club Tile \u2013 4 Floors\",         area:\"Club\",       status:\"Done\",    pct:100},\r\n  {id:\"t2\", name:\"Club Plumbing \u2013 3 Floors\",      area:\"Club\",       status:\"Done\",    pct:100},\r\n  {id:\"t3\", name:\"Lobby\",                          area:\"Club\",       status:\"Done\",    pct:100},\r\n  {id:\"t4\", name:\"Club Pool (Con + Tile)\",         area:\"Club\",       status:\"Running\", pct:70},\r\n  {id:\"t5\", name:\"Club Drive Ramp\",                area:\"Club\",       status:\"Running\", pct:10},\r\n  {id:\"t6\", name:\"Club ACP \/ Glass Window\",        area:\"Club\",       status:\"Running\", pct:50},\r\n  {id:\"t7\", name:\"Club Step Tile\",                 area:\"Club\",       status:\"Running\", pct:20},\r\n  {id:\"t8\", name:\"Club Color\",                     area:\"Club\",       status:\"Running\", pct:20},\r\n  {id:\"t9\", name:\"Club Electrical\",                area:\"Club\",       status:\"Pending\", pct:0},\r\n  {id:\"t10\",name:\"Club Entry Fabrication\",         area:\"Club\",       status:\"Pending\", pct:0},\r\n  {id:\"t11\",name:\"Club Fabrication\",               area:\"Club\",       status:\"Pending\", pct:0},\r\n  {id:\"t12\",name:\"Earth \/ Wind Plumbing\",          area:\"Earth Wind\", status:\"Running\", pct:50},\r\n  {id:\"t13\",name:\"Jungle Pool (Con)\",              area:\"Jungle\",     status:\"Running\", pct:10},\r\n  {id:\"t14\",name:\"Jungle Villa \u2013 10 Rooms\",        area:\"Jungle\",     status:\"Running\", pct:10},\r\n  {id:\"t15\",name:\"Jungle Plumbing \u2013 20 Units\",     area:\"Jungle\",     status:\"Pending\", pct:0},\r\n  {id:\"t16\",name:\"Jungle Door \/ Window \u2013 20\",      area:\"Jungle\",     status:\"Pending\", pct:0},\r\n  {id:\"t17\",name:\"Jungle Color\",                   area:\"Jungle\",     status:\"Pending\", pct:0},\r\n  {id:\"t18\",name:\"Jungle Road\",                    area:\"Jungle\",     status:\"Pending\", pct:0},\r\n  {id:\"t19\",name:\"5 Staff Rooms Extended\",         area:\"Staff\",      status:\"Running\", pct:80},\r\n  {id:\"t20\",name:\"Kid Pool (Tile Pending)\",        area:\"Pools\",      status:\"Running\", pct:85},\r\n  {id:\"t21\",name:\"Backyard Garden\",                area:\"Site\",       status:\"Running\", pct:20},\r\n  {id:\"t22\",name:\"Solar 10KW\",                     area:\"Site\",       status:\"Running\", pct:0},\r\n  {id:\"t23\",name:\"Fire Safety\",                    area:\"Site\",       status:\"Pending\", pct:0},\r\n];\r\n\r\nconst AC={Club:\"#2563eb\",Jungle:\"#16a34a\",Pools:\"#0891b2\",Staff:\"#d97706\",\"Earth Wind\":\"#7c3aed\",Site:\"#ea580c\"};\r\nconst AL={Club:\"#eff6ff\",Jungle:\"#f0fdf4\",Pools:\"#ecfeff\",Staff:\"#fffbeb\",\"Earth Wind\":\"#f5f3ff\",Site:\"#fff7ed\"};\r\nconst AB={Club:\"#bfdbfe\",Jungle:\"#bbf7d0\",Pools:\"#a5f3fc\",Staff:\"#fde68a\",\"Earth Wind\":\"#ddd6fe\",Site:\"#fed7aa\"};\r\nconst AREA_LIST=[\"Club\",\"Jungle\",\"Pools\",\"Staff\",\"Earth Wind\",\"Site\"];\r\nconst SC=[\"Pending\",\"Running\",\"Hold\",\"Done\"];\r\nconst SM={\r\n  Done:{icon:\"\u2705\",color:\"#15803d\",bg:\"#dcfce7\",border:\"#86efac\"},\r\n  Running:{icon:\"\u23f3\",color:\"#1d4ed8\",bg:\"#dbeafe\",border:\"#93c5fd\"},\r\n  Pending:{icon:\"\ud83d\udd32\",color:\"#b91c1c\",bg:\"#fee2e2\",border:\"#fca5a5\"},\r\n  Hold:{icon:\"\u23f8\ufe0f\",color:\"#6b21a8\",bg:\"#f3e8ff\",border:\"#d8b4fe\"},\r\n};\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\/\/ localStorage storage API (replaces window.storage)\r\nconst LS={\r\n  get:(k)=>{try{const v=localStorage.getItem(k);return v?{value:v}:null;}catch{return null;}},\r\n  set:(k,v)=>{try{localStorage.setItem(k,v);return true;}catch{return null;}},\r\n};\r\n\r\nfunction App(){\r\n  const now=new Date();\r\n  const[year,setYear]=useState(now.getFullYear());\r\n  const[month,setMonth]=useState(now.getMonth());\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[loaded,setLoaded]=useState(false);\r\n  const[saving,setSaving]=useState(false);\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});\r\n  const[delConfirm,setDelConfirm]=useState(null);\r\n\r\n  useEffect(()=>{\r\n    try{\r\n      const t=LS.get(\"lilo-tasks-v3\");if(t)setTasks(JSON.parse(t.value));\r\n      const g=LS.get(\"lilo-grid-v3\");if(g)setGrid(JSON.parse(g.value));\r\n      const dm=LS.get(\"lilo-dm-v3\");if(dm)setDayMeta(JSON.parse(dm.value));\r\n      const tm=LS.get(\"lilo-tm-v3\");if(tm)setTaskMeta(JSON.parse(tm.value));\r\n    }catch{}\r\n    setLoaded(true);\r\n  },[]);\r\n\r\n  const save=useCallback((ts,g,dm,tm)=>{\r\n    setSaving(true);\r\n    try{\r\n      LS.set(\"lilo-tasks-v3\",JSON.stringify(ts));\r\n      LS.set(\"lilo-grid-v3\",JSON.stringify(g));\r\n      LS.set(\"lilo-dm-v3\",JSON.stringify(dm));\r\n      LS.set(\"lilo-tm-v3\",JSON.stringify(tm));\r\n    }catch{}\r\n    setTimeout(()=>setSaving(false),400);\r\n  },[]);\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);};\r\n  const renameTask=(tid,name)=>{const nt=tasks.map(t=>t.id===tid?{...t,name}:t);setTasks(nt);save(nt,grid,dayMeta,taskMeta);};\r\n  const deleteTask=(tid)=>{const nt=tasks.filter(t=>t.id!==tid);setTasks(nt);save(nt,grid,dayMeta,taskMeta);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};\r\n    const nt=[...tasks,t];setTasks(nt);save(nt,grid,dayMeta,taskMeta);\r\n    setNewTask({name:\"\",area:\"Club\",status:\"Pending\",pct:0});setShowAdd(false);\r\n  };\r\n  const toggleCell=(tid,day)=>{\r\n    const k=cKey(tid,day);const cur=grid[k];const t=tasks.find(x=>x.id===tid);\r\n    const ng={...grid,[k]:cur&&cur.done?{...cur,done:false}:{done:true,pct:t?t.pct:0}};\r\n    setGrid(ng);save(tasks,ng,dayMeta,taskMeta);\r\n  };\r\n  const updatePct=(tid,day,val)=>{\r\n    const k=cKey(tid,day);\r\n    const ng={...grid,[k]:{...(grid[k]||{done:true}),pct:Math.min(100,Math.max(0,parseInt(val)||0))}};\r\n    setGrid(ng);save(tasks,ng,dayMeta,taskMeta);\r\n  };\r\n  const setDayStatus=(day,status)=>{\r\n    const k=toKey(year,month,day);const cur=dayMeta[k]||{};\r\n    const nm={...dayMeta,[k]:{...cur,status:cur.status===status?\"work\":status}};\r\n    setDayMeta(nm);save(tasks,grid,nm,taskMeta);\r\n  };\r\n  const updateTM=(tid,field,val)=>{\r\n    const cur=taskMeta[tid]||{};\r\n    let upd={...cur,[field]:val};\r\n    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());}}\r\n    const nm={...taskMeta,[tid]:upd};setTaskMeta(nm);save(tasks,grid,dayMeta,nm);\r\n  };\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);\r\n      if(t&&t.status===\"Done\"){label=\"Completed\";color=\"#15803d\";bg=\"#dcfce7\";icon=\"\u2705\";}\r\n      else if(dl<0){label=Math.abs(dl)+\"d overdue\";color=\"#dc2626\";bg=\"#fee2e2\";icon=\"\ud83d\udea8\";}\r\n      else if(dl===0){label=\"Due today!\";color=\"#d97706\";bg=\"#fffbeb\";icon=\"\u26a0\ufe0f\";}\r\n      else if(dl<=3){label=dl+\"d left\";color=\"#d97706\";bg=\"#fffbeb\";icon=\"\u26a0\ufe0f\";}\r\n      else{label=dl+\"d left\";color=\"#15803d\";bg=\"#dcfce7\";icon=\"\u2705\";}\r\n    }else if(ed>0){const rem=ed-wd;\r\n      if(t&&t.status===\"Done\"){label=\"Completed\";color=\"#15803d\";bg=\"#dcfce7\";icon=\"\u2705\";}\r\n      else if(rem<=0){label=Math.abs(rem)+\"d over est.\";color=\"#dc2626\";bg=\"#fee2e2\";icon=\"\ud83d\udea8\";}\r\n      else if(rem<=3){label=rem+\"d left\";color=\"#d97706\";bg=\"#fffbeb\";icon=\"\u26a0\ufe0f\";}\r\n      else{label=rem+\"d left\";color=\"#1d4ed8\";bg=\"#dbeafe\";icon=\"\ud83d\udcc5\";}\r\n    }\r\n    return{label,color,bg,icon,wd};\r\n  };\r\n\r\n  const suggestEst=(tid)=>{\r\n    const t=tasks.find(x=>x.id===tid);if(!t)return null;\r\n    const wd=getTaskDays(tid);const pct=t.pct||0;const rem=100-pct;\r\n    if(rem<=0)return null;\r\n    if(wd>0&&pct>0)return Math.max(1,Math.round((wd\/pct)*rem));\r\n    return Math.max(1,Math.round(rem\/5));\r\n  };\r\n\r\n  const sortTasks=(list)=>[...list].sort((a,b)=>{\r\n    const ad=a.status===\"Done\",bd=b.status===\"Done\";\r\n    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);\r\n    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\";\r\n    if(ah&&!bh)return 1;if(!ah&&bh)return -1;return 0;\r\n  });\r\n\r\n  const allAreas=[\"All\",...AREA_LIST].filter((a,i,ar)=>ar.indexOf(a)===i&&(a===\"All\"||tasks.some(t=>t.area===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\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(<div style={{height:\"100vh\",display:\"flex\",alignItems:\"center\",justifyContent:\"center\",color:\"#64748b\",fontSize:14}}>Loading\u2026<\/div>);\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      {\/* TOP BAR *\/}\r\n      <div style={{background:\"#fff\",borderBottom:\"1px solid #e2e8f0\",padding:\"9px 18px\",display:\"flex\",alignItems:\"center\",gap:12,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        <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:140,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        <div style={{display:\"flex\",gap:6,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 10px\",display:\"flex\",alignItems:\"center\",gap:4}}>\r\n              <span style={{fontSize:13,fontWeight:800,color:s.c}}>{s.v}<\/span>\r\n              <span style={{fontSize:10,color:s.c,fontWeight:700}}>{s.l}<\/span>\r\n            <\/div>\r\n          ))}\r\n        <\/div>\r\n        <div style={{marginLeft:\"auto\",display:\"flex\",gap:7,alignItems:\"center\"}}>\r\n          {saving&&<span style={{fontSize:10,color:\"#94a3b8\"}}>Saving\u2026<\/span>}\r\n          <div style={{background:\"#dcfce7\",border:\"1px solid #86efac\",borderRadius:7,padding:\"4px 10px\"}}>\r\n            <span style={{fontSize:15,fontWeight:800,color:\"#15803d\"}}>{totalWD}<\/span>\r\n            <span style={{fontSize:9,color:\"#4ade80\",marginLeft:3}}>work days<\/span>\r\n          <\/div>\r\n          <div style={{background:\"#dbeafe\",border:\"1px solid #93c5fd\",borderRadius:7,padding:\"4px 10px\"}}>\r\n            <span style={{fontSize:15,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 12px\",fontSize:11,fontWeight:700,background:view===\"summary\"?\"#1e293b\":\"#f8fafc\",color:view===\"summary\"?\"#fff\":\"#475569\"}}>\r\n            {view===\"grid\"?\"\ud83d\udcca Summary\":\"\ud83d\udccb Grid\"}\r\n          <\/button>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      {\/* ADD MODAL *\/}\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:360,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}}>\r\n              <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                  {AREA_LIST.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:20}}>\r\n              <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      {\/* DELETE CONFIRM *\/}\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 permanently 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      {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:8}}>\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                  <div style={{display:\"flex\",gap:10,marginBottom:8,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\"}}>\r\n                      <div style={{fontSize:17,fontWeight:700,color:dp>=100?\"#15803d\":dp>=50?\"#1d4ed8\":dp>0?\"#d97706\":\"#b91c1c\"}}>{dp}%<\/div>\r\n                      {pp>0&&<div style={{fontSize:9,color:\"#b91c1c\",fontWeight:700}}>{pp}% left<\/div>}\r\n                    <\/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:10,color:\"#475569\",background:\"#f8fafc\",borderRadius:5,padding:\"4px 8px\",marginBottom:6,fontStyle:\"italic\"}}>\ud83d\udcac {tm.comment}<\/div>}\r\n                  <div style={{background:\"#f1f5f9\",borderRadius:4,height:5,marginBottom:6}}><div style={{background:dp>=100?\"#15803d\":dp>=50?\"#1d4ed8\":\"#d97706\",width:dp+\"%\",height:\"100%\",borderRadius:4}}\/><\/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        <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=>{\r\n              const ac=a===\"All\"?\"#475569\":AC[a]||\"#475569\";\r\n              const al=a===\"All\"?\"#f8fafc\":AL[a]||\"#f8fafc\";\r\n              const ab2=a===\"All\"?\"#e2e8f0\":AB[a]||\"#e2e8f0\";\r\n              const active=activeArea===a;\r\n              return <button key={a} onClick={()=>setActiveArea(a)} style={{padding:\"4px 11px\",borderRadius:20,border:`1px solid ${active?ac:ab2}`,background:active?ac:al,color:active?\"#fff\":ac,cursor:\"pointer\",fontSize:10,fontWeight:700,fontFamily:\"inherit\"}}>{a}<\/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\"}}>\r\n                    <span style={{fontSize:11,fontWeight:800,color:\"#1e293b\",textTransform:\"uppercase\"}}>Task<\/span>\r\n                  <\/th>\r\n                  <th style={{...TH,minWidth:90,background:\"#fff\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 5px\"}}>\r\n                    <div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Status<\/div>\r\n                  <\/th>\r\n                  <th style={{...TH,minWidth:60,background:\"#fffbeb\",borderRight:\"1px solid #fde68a\",padding:\"5px 4px\"}}>\r\n                    <div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Est<br\/>Days<\/div>\r\n                  <\/th>\r\n                  <th style={{...TH,minWidth:86,background:\"#f0fdf4\",borderRight:\"2px solid #e2e8f0\",padding:\"5px 4px\"}}>\r\n                    <div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Finish<br\/>Date<\/div>\r\n                  <\/th>\r\n                  <th style={{...TH,minWidth:55,background:\"#f8fafc\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 4px\"}}>\r\n                    <div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Days<br\/>Done<\/div>\r\n                  <\/th>\r\n                  <th style={{...TH,minWidth:155,background:\"#fafafa\",borderRight:\"1px solid #e2e8f0\",padding:\"5px 8px\"}}>\r\n                    <div style={{fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Comment<\/div>\r\n                  <\/th>\r\n                  <th style={{...TH,minWidth:55,background:\"#f0fdf4\",borderRight:\"2px solid #e2e8f0\",padding:\"5px 4px\"}}>\r\n                    <div style={{textAlign:\"center\",fontSize:11,fontWeight:800,color:\"#1e293b\"}}>Overall<br\/>%<\/div>\r\n                  <\/th>\r\n                  {days.map(d=>{\r\n                    const dk=toKey(year,month,d);const isT=dk===todayKey;\r\n                    const meta=dayMeta[dk];const cnt=getDayCount(d);\r\n                    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 ab2=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 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 pp=100-dp;\r\n                  const dpc=dp>=100?\"#15803d\":dp>=50?\"#1d4ed8\":dp>0?\"#d97706\":\"#b91c1c\";\r\n                  const sug=suggestEst(t.id);\r\n\r\n                  return(\r\n                    <React.Fragment key={t.id}>\r\n                    {showLbl&&(\r\n                      <tr>\r\n                        <td colSpan={days.length+9} style={{background:\"#f8fafc\",padding:\"5px 12px\",borderTop:\"2px solid #e2e8f0\",borderBottom:\"1px solid #e2e8f0\"}}>\r\n                          <div style={{display:\"flex\",alignItems:\"center\",gap:6}}>\r\n                            <div style={{width:10,height:10,background:ac,borderRadius:2}}\/>\r\n                            <span style={{fontSize:10,fontWeight:800,color:ac,letterSpacing:1,textTransform:\"uppercase\"}}>{t.area}<\/span>\r\n                          <\/div>\r\n                        <\/td>\r\n                      <\/tr>\r\n                    )}\r\n                    <tr style={{background:ti%2===0?\"#fff\":\"#fafcff\"}}>\r\n                      {\/* Task name *\/}\r\n                      <td style={{position:\"sticky\",left:0,zIndex:5,background:al,borderLeft:`3px solid ${holdBorder}`,borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab2}`,padding:\"5px 8px\",minWidth:185,maxWidth:185}}>\r\n                        {isEN?(\r\n                          <input autoFocus defaultValue={t.name}\r\n                            onBlur={e=>{renameTask(t.id,e.target.value||t.name);setEditTask(null);}}\r\n                            onKeyDown={e=>{if(e.key===\"Enter\"){renameTask(t.id,e.target.value||t.name);setEditTask(null);}if(e.key===\"Escape\")setEditTask(null);}}\r\n                            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\"}}\r\n                          \/>\r\n                        ):(\r\n                          <div style={{fontSize:13,fontWeight:700,color:\"#0f172a\",whiteSpace:\"nowrap\",overflow:\"hidden\",textOverflow:\"ellipsis\",cursor:\"text\"}} onDoubleClick={()=>setEditTask(t.id)} title={t.name+\" (dbl-click to rename)\"}>\r\n                            {t.name}\r\n                          <\/div>\r\n                        )}\r\n                      <\/td>\r\n                      {\/* Status *\/}\r\n                      <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab2}`,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\"}}>\r\n                          {sm.icon} {t.status}\r\n                        <\/button>\r\n                      <\/td>\r\n                      {\/* Est Days *\/}\r\n                      <td style={{borderRight:\"1px solid #fde68a\",borderBottom:`1px solid ${ab2}`,background:\"#fffbeb55\",textAlign:\"center\",padding:\"3px 4px\",cursor:\"pointer\"}} onClick={()=>setEditField({tid:t.id,field:\"estDays\"})}>\r\n                        {isEE?(\r\n                          <input autoFocus type=\"number\" min={1} max={999} defaultValue={tm.estDays||\"\"}\r\n                            onBlur={e=>{updateTM(t.id,\"estDays\",e.target.value);setEditField(null);}}\r\n                            onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){updateTM(t.id,\"estDays\",e.target.value);setEditField(null);}}}\r\n                            style={{width:46,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                          \/>\r\n                        ):tm.estDays?(\r\n                          <div>\r\n                            <div style={{fontSize:14,fontWeight:800,color:\"#92400e\"}}>{tm.estDays}<\/div>\r\n                            {wd>0&&<div style={{height:3,background:\"#e2e8f0\",borderRadius:2,margin:\"2px 4px\",overflow:\"hidden\"}}><div style={{background:wd>=tm.estDays?\"#dc2626\":\"#d97706\",width:Math.min(100,Math.round(wd\/tm.estDays*100))+\"%\",height:\"100%\",borderRadius:2}}\/><\/div>}\r\n                          <\/div>\r\n                        ):sug&&t.status!==\"Done\"?(\r\n                          <div onClick={e=>{e.stopPropagation();updateTM(t.id,\"estDays\",String(sug));}} style={{background:\"#fef3c7\",border:\"1px dashed #d97706\",borderRadius:5,padding:\"2px 4px\",cursor:\"pointer\",display:\"inline-block\"}}>\r\n                            <div style={{fontSize:12,fontWeight:800,color:\"#92400e\"}}>~{sug}d<\/div>\r\n                            <div style={{fontSize:8,color:\"#d97706\"}}>tap<\/div>\r\n                          <\/div>\r\n                        ):(\r\n                          <div style={{color:\"#d97706\",fontSize:18,opacity:0.3}}>+<\/div>\r\n                        )}\r\n                      <\/td>\r\n                      {\/* Finish Date *\/}\r\n                      <td style={{borderRight:\"2px solid #e2e8f0\",borderBottom:`1px solid ${ab2}`,background:\"#f0fdf455\",textAlign:\"center\",padding:\"3px 4px\",cursor:\"pointer\"}} onClick={()=>setEditField({tid:t.id,field:\"finishDate\"})}>\r\n                        {isED?(\r\n                          <input autoFocus type=\"date\" defaultValue={tm.finishDate||\"\"}\r\n                            onBlur={e=>{updateTM(t.id,\"finishDate\",e.target.value);setEditField(null);}}\r\n                            onKeyDown={e=>{if([\"Enter\",\"Escape\"].includes(e.key)){updateTM(t.id,\"finishDate\",e.target.value);setEditField(null);}}}\r\n                            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                          \/>\r\n                        ):tm.finishDate?(\r\n                          <div>\r\n                            <div style={{fontSize:12,fontWeight:800,color:\"#15803d\"}}>{fmtD(pDate(tm.finishDate))}<\/div>\r\n                            {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>}\r\n                          <\/div>\r\n                        ):(\r\n                          <div style={{color:\"#16a34a\",fontSize:18,opacity:0.3}}>+<\/div>\r\n                        )}\r\n                      <\/td>\r\n                      {\/* Days worked *\/}\r\n                      <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab2}`,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                      {\/* Comment *\/}\r\n                      <td style={{borderRight:\"1px solid #e2e8f0\",borderBottom:`1px solid ${ab2}`,background:\"#fafafa\",padding:\"3px 6px\",minWidth:155}}>\r\n                        {isCom?(\r\n                          <textarea autoFocus defaultValue={tm.comment||\"\"}\r\n                            onBlur={e=>{updateTM(t.id,\"comment\",e.target.value);setEditField(null);}}\r\n                            onKeyDown={e=>{if(e.key===\"Escape\")setEditField(null);}}\r\n                            style={{width:\"100%\",background:\"#fff\",border:\"2px solid #475569\",color:\"#1e293b\",fontFamily:\"inherit\",fontSize:11,padding:\"3px 6px\",borderRadius:4,outline:\"none\",resize:\"none\",height:42,boxSizing:\"border-box\"}}\r\n                          \/>\r\n                        ):(\r\n                          <div onClick={()=>setEditField({tid:t.id,field:\"comment\"})} style={{fontSize:11,color:tm.comment?\"#1e293b\":\"#cbd5e1\",cursor:\"text\",minHeight:34,lineHeight:1.4,padding:\"2px 0\",whiteSpace:\"pre-wrap\",wordBreak:\"break-word\"}}>\r\n                            {tm.comment||\"+ comment\u2026\"}\r\n                          <\/div>\r\n                        )}\r\n                      <\/td>\r\n                      {\/* Overall % *\/}\r\n                      <td style={{borderRight:\"2px solid #e2e8f0\",borderBottom:`1px solid ${ab2}`,background:\"#f0fdf455\",textAlign:\"center\",padding:\"4px 4px\"}}>\r\n                        <div style={{fontSize:16,fontWeight:800,color:dpc}}>{dp}%<\/div>\r\n                        {pp>0&&pp<100&&<div style={{fontSize:9,fontWeight:700,color:\"#b91c1c\"}}>{pp}% left<\/div>}\r\n                        {pp===100&&<div style={{fontSize:9,fontWeight:700,color:\"#b91c1c\"}}>100% left<\/div>}\r\n                        {pp===0&&<div style={{fontSize:9,fontWeight:700,color:\"#15803d\"}}>Done \u2713<\/div>}\r\n                        {ed>0&&<div style={{height:3,background:\"#e2e8f0\",borderRadius:2,margin:\"2px 3px\",overflow:\"hidden\"}}><div style={{background:dpc,width:dp+\"%\",height:\"100%\",borderRadius:2}}\/><\/div>}\r\n                      <\/td>\r\n                      {\/* Day cells *\/}\r\n                      {days.map(d=>{\r\n                        const dk=toKey(year,month,d);const k=cKey(t.id,d);\r\n                        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];\r\n                        const isNW=meta&&meta.status===\"nowork\";const isHL=meta&&meta.status===\"holiday\";\r\n                        const isSel=selCell&&selCell.tid===t.id&&selCell.day===d;\r\n                        const isWE=[0,6].includes(new Date(year,month,d).getDay());\r\n                        let bg=isT?\"#eff6ff\":isWE?\"#fafafa\":\"#fff\";\r\n                        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 ${ab2}`,background:bg,padding:0,minWidth:36,maxWidth:36,textAlign:\"center\",verticalAlign:\"middle\",cursor:isNW||isHL?\"default\":\"pointer\"}}>\r\n                            {isNW||isHL?(\r\n                              <div style={{padding:\"7px 0\",fontSize:10,color:\"#cbd5e1\"}}>{isHL?\"\ud83c\udf34\":\"\u2014\"}<\/div>\r\n                            ):isSel?(\r\n                              <div style={{padding:\"3px\"}}>\r\n                                <input autoFocus type=\"number\" min={0} max={100} defaultValue={pct}\r\n                                  onBlur={e=>{updatePct(t.id,d,e.target.value);setSelCell(null);}}\r\n                                  onKeyDown={e=>{if([\"Enter\",\"Escape\",\"Tab\"].includes(e.key)){updatePct(t.id,d,e.target.value);setSelCell(null);}}}\r\n                                  style={{width:32,background:\"#fff\",border:`2px solid ${ac}`,color:ac,fontFamily:\"inherit\",fontSize:12,fontWeight:700,textAlign:\"center\",borderRadius:4,padding:\"2px 0\",outline:\"none\"}}\r\n                                \/>\r\n                              <\/div>\r\n                            ):(\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:34,userSelect:\"none\"}}>\r\n                                {isDone?(\r\n                                  <>\r\n                                    <div style={{width:20,height:20,borderRadius:4,background:ac,display:\"flex\",alignItems:\"center\",justifyContent:\"center\",boxShadow:`0 2px 5px ${ac}44`}}>\r\n                                      <span style={{fontSize:11,color:\"#fff\",fontWeight:900}}>\u2713<\/span>\r\n                                    <\/div>\r\n                                    <div style={{fontSize:8,color:ac,fontWeight:700,marginTop:1}}>{pct}%<\/div>\r\n                                  <\/>\r\n                                ):(\r\n                                  <div style={{width:20,height:20,borderRadius:4,border:`1.5px solid ${isT?\"#bfdbfe\":\"#e2e8f0\"}`,background:isT?\"#f0f9ff\":\"transparent\"}}\/>\r\n                                )}\r\n                              <\/div>\r\n                            )}\r\n                          <\/td>\r\n                        );\r\n                      })}\r\n                      {\/* Delete *\/}\r\n                      <td style={{borderBottom:`1px solid ${ab2}`,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\",borderRadius:4,opacity:0.4}}\r\n                          onMouseEnter={e=>e.currentTarget.style.opacity=1}\r\n                          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                {\/* Add row *\/}\r\n                <tr>\r\n                  <td colSpan={days.length+9} style={{background:\"#f8fafc\",padding:\"6px 14px\",borderTop:\"2px dashed #e2e8f0\"}}>\r\n                    <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\"}}>\r\n                      <span style={{fontSize:18,color:\"#cbd5e1\"}}>\uff0b<\/span> Add new task row\u2026\r\n                    <\/button>\r\n                  <\/td>\r\n                <\/tr>\r\n                {\/* Footer *\/}\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\"}}>\r\n                    <span style={{fontSize:10,fontWeight:800,color:\"#1e293b\"}}>TASKS \/ DAY<\/span>\r\n                  <\/td>\r\n                  <td colSpan={6} style={{background:\"#f8fafc\",borderTop:\"2px solid #e2e8f0\",borderRight:\"2px solid #e2e8f0\"}}\/>\r\n                  {days.map(d=>{\r\n                    const cnt=getDayCount(d);const isT=toKey(year,month,d)===todayKey;\r\n                    return(\r\n                      <td key={d} style={{background:isT?\"#eff6ff\":\"#f8fafc\",borderTop:\"2px solid #e2e8f0\",borderRight:`1px solid ${isT?\"#bfdbfe\":\"#f1f5f9\"}`,textAlign:\"center\",padding:\"4px 2px\"}}>\r\n                        <div style={{fontSize:12,fontWeight:800,color:cnt>0?\"#16a34a\":\"#e2e8f0\"}}>{cnt||\"\"}<\/div>\r\n                        {cnt>0&&<div style={{height:3,background:\"#16a34a\",opacity:0.3+cnt\/tasks.length*0.7,margin:\"2px 4px\",borderRadius:2}}\/>}\r\n                      <\/td>\r\n                    );\r\n                  })}\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:14,fontSize:10,color:\"#94a3b8\"}}>\r\n              <span><b style={{color:\"#1e293b\"}}>Status<\/b> = click to 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            <\/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-9652","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/pages\/9652","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=9652"}],"version-history":[{"count":6,"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/pages\/9652\/revisions"}],"predecessor-version":[{"id":9659,"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/pages\/9652\/revisions\/9659"}],"wp:attachment":[{"href":"https:\/\/lilodhyanresort.com\/index.php\/wp-json\/wp\/v2\/media?parent=9652"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}