diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c2658d7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/README.md b/README.md
index 346f012..cd1f243 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,24 @@
Open `index.html` in a browser.
+Production uses the committed `dist/game.js` bundle. Edit source files under
+`src/`, then run `npm install` once and `npm run build` after JavaScript
+changes to regenerate the bundle.
+
+## Static server cache setup
+
+Serve `index.html`, the bundled JavaScript, and CSS with cache validation
+instead of import query strings. This prevents stale files while keeping reloads
+fast.
+
+Use the example in `deploy/` for your HTTP server:
+
+- nginx: include `deploy/nginx-cache.conf` inside the server block.
+- Apache: copy or include `deploy/apache-cache.htaccess` from the site root.
+- Caddy: adapt `deploy/Caddyfile-cache`.
+
+After deploying, purge any CDN or reverse-proxy cache once.
+
## Current baseline
- Build, move, box-select, sell, and repair factory equipment during Build phase.
diff --git a/deploy/Caddyfile-cache b/deploy/Caddyfile-cache
new file mode 100644
index 0000000..1b430f3
--- /dev/null
+++ b/deploy/Caddyfile-cache
@@ -0,0 +1,9 @@
+# Adapt these directives inside the Caddy site block that serves this static app.
+
+encode gzip zstd
+
+@html path /index.html
+header @html Cache-Control "no-cache"
+
+@assets path *.js *.css
+header @assets Cache-Control "no-cache"
diff --git a/deploy/apache-cache.htaccess b/deploy/apache-cache.htaccess
new file mode 100644
index 0000000..69d3f75
--- /dev/null
+++ b/deploy/apache-cache.htaccess
@@ -0,0 +1,17 @@
+# Use this from the static site root when served by Apache with .htaccess enabled.
+
+FileETag MTime Size
+
+
+
+ Header set Cache-Control "no-cache"
+
+
+
+ Header set Cache-Control "no-cache"
+
+
+
+
+ AddOutputFilterByType DEFLATE text/css application/javascript text/javascript
+
diff --git a/deploy/nginx-cache.conf b/deploy/nginx-cache.conf
new file mode 100644
index 0000000..82b8614
--- /dev/null
+++ b/deploy/nginx-cache.conf
@@ -0,0 +1,20 @@
+# Include this in the nginx server block that serves this static app.
+#
+# Example:
+# server {
+# root /var/www/zunda-shiwake;
+# include /var/www/zunda-shiwake/deploy/nginx-cache.conf;
+# }
+
+etag on;
+gzip on;
+gzip_types text/css application/javascript text/javascript;
+
+location = /index.html {
+ add_header Cache-Control "no-cache";
+}
+
+location ~* \.(js|css)$ {
+ add_header Cache-Control "no-cache";
+ gzip_static on;
+}
diff --git a/dist/game.js b/dist/game.js
new file mode 100644
index 0000000..73d86dc
--- /dev/null
+++ b/dist/game.js
@@ -0,0 +1,55 @@
+var H={version:"v27.6 direct conveyor chick movement",time:{daySeconds:60,farmShutdownGraceSeconds:10},cash:{starting:250},grid:{x:170,y:78,cols:20,rows:10,cell:46,expansion:{colsPerPurchase:10,rowsPerPurchase:10,costBase:1e3,costMultiplier:1.3333333333333333,truncateUnit:100}},map:{blockedRatio:.075},economy:{income:{mixer:5,truck:10},poopFine:10,zundaTax:{exemption:500,legalWorkExemptionBonus:250,maxRateCash:1e4,stepAmount:500,stepRate:.05,maxRate:.95},fairiesTribute:{perDay:10},incomeUpgradeRate:1.05,explosionDamageDivisor:30,maleTruckFinePerHalfDay:30,shredderBonus:{maxCards:30,probabilityPercentDivisor:2}},production:{poopRate:.08,autoScannerCooldown:2.25,autoScannerUpgradeRate:.95,autoScannerMinCooldown:.5,eggSpawnRanges:[[1.95,4.35],[1.55,3.45],[1.25,2.8],[1.05,2.35]]},conveyor:{baseSpeed:52,maxSpeed:300,bearingSpeedMultiplier:1.075},cards:{definitions:[{id:"upgradeEgg",title:"EGG Improvement",rarity:"common",type:"equipmentUpgrade",target:"eggFarm",description:"Choose one EGG FARM on the map and raise it by 1 level.",tags:["EGG","ACTIVE"]},{id:"upgradeAutoScanner",title:"AUTO SCANNER Improvement",rarity:"common",type:"equipmentUpgrade",target:"autoScanner",description:"Choose one AUTO SCANNER on the map and raise it by 1 level.",tags:["SCANNER","ACTIVE"]},{id:"upgradeMixer",title:"MIXER Improvement",rarity:"common",type:"equipmentUpgrade",target:"mixer",description:"Choose MIXER on the map and raise it by 1 level.",tags:["ECONOMY","ACTIVE"]},{id:"upgradeTruck",title:"TRUCK Improvement",rarity:"common",type:"equipmentUpgrade",target:"truck",description:"Choose TRUCK on the map and raise it by 1 level.",tags:["ECONOMY","ACTIVE"]},{id:"upgradeTrash",title:"SHREDDER Improvement",rarity:"common",type:"equipmentUpgrade",target:"trash",description:"Shred poops for a little money. Max 30 upgrades.",tags:["POOP","ACTIVE"]},{id:"crowdedFarming",title:"Crowded Farming Contract",rarity:"common",type:"instant",description:"EGG production interval -5%. Equipment deterioration +4%. Max 10 cards.",tags:["EGG","RISK","PASSIVE"]},{id:"hatchingFeed",title:"Hatching Feed",rarity:"common",type:"instant",description:"EGG production interval -4%. Poop rate +3%. No card limit.",tags:["EGG","POOP","PASSIVE"]},{id:"safetyCover",title:"Safety Cover",rarity:"common",type:"instant",description:"Explosion damage -5%. No card limit.",tags:["RISK","PASSIVE"]},{id:"preventiveMaintenance",title:"Preventive Maintenance Manual",rarity:"common",type:"instant",description:"All equipment deterioration speed -5%. No card limit.",tags:["MAINTENANCE","PASSIVE"]},{id:"dudFilter",title:"DUD Filter",rarity:"common",type:"instant",description:"DUD chance -5 percentage points. Stacks until DUD chance reaches 0%.",tags:["CARD","PASSIVE"]},{id:"durabilityCoating",title:"Durability Coating",rarity:"common",type:"instant",description:"All equipment maximum durability +3%. No card limit.",tags:["MAINTENANCE","PASSIVE"]},{id:"bearing",title:"High-Quality Bearing",rarity:"common",type:"instant",description:"Conveyor speed +7.5%.",tags:["CONVEYOR","PASSIVE"]},{id:"extraEggOutlet",title:"Extra Egg Outlet",rarity:"rare",type:"equipmentUpgrade",target:"eggOutlet",description:"Choose one EGG FARM and add +1 output port to that EGG. Max +3 per EGG.",tags:["EGG","RARE","ACTIVE"]},{id:"recyclingSubsidy",title:"Recycling Subsidy",rarity:"rare",type:"instant",description:"SELL refund rate +10 points. Max 3 cards; normal SELL can reach 80%.",tags:["ECONOMY","RARE","PASSIVE"]},{id:"dynamite",title:"Dynamite",rarity:"rare",type:"cellAction",target:"blockedCell",description:"Remove any 3 blocked cells with a burst effect.",tags:["RISK","RARE","ONE-SHOT"]},{id:"usedMachine",title:"Used Machines",rarity:"rare",type:"instant",description:"Future equipment costs half. New purchases have no refund and 60% durability. New Machines cancels it.",tags:["ECONOMY","RISK","RARE"]},{id:"newMachine",title:"New Machines",rarity:"common",type:"instant",description:"Cancel Used Machines and restore normal prices, refunds, and durability.",tags:["ECONOMY","ONE-SHOT"]},{id:"flattery",title:"Flattery",rarity:"rare",type:"instant",description:"Next Fairies tribute -50%.",tags:["ECONOMY","RARE","ONE-SHOT"]},{id:"loan",title:"Loan",rarity:"rare",type:"instant",description:"Gain JPY 300 per elapsed day now. Pay JPY 400 per day for that many days starting tomorrow.",tags:["ECONOMY","RISK","RARE"]},{id:"extraCards",title:"Extra Cards",rarity:"rare",type:"instant",description:"Draw 2 cards now and choose both.",tags:["RARE","ACTIVE"]},{id:"legalWork",title:"Legal Work",rarity:"rare",type:"instant",description:"ZUNDA TAX exemption +\uFFE5250. The 95% cap point also moves up by \uFFE5250.",tags:["ECONOMY","RARE","PASSIVE"]},{id:"chemicalWeaponSubsidy",title:"Chemical Weapons Subsidy",rarity:"ultraRare",type:"instant",description:"Each day, gain JPY 2000 per 100 poop shipped by truck. No card limit.",tags:["POOP","ULTRA RARE","PASSIVE"]},{id:"laborExploitation",title:"Motivational Exploitation",rarity:"ultraRare",type:"instant",description:"Repairman labor cost -30%. The repairman smiles with bloodshot eyes. One time only.",tags:["MAINTENANCE","ULTRA RARE","PASSIVE"]},{id:"rescueLoan",title:"Emergency Loan",rarity:"ultraRare",type:"instant",description:"If cash is below JPY 0 at day-end settlement, gain JPY 500. Consumed on use.",tags:["ECONOMY","ULTRA RARE","ONE-SHOT"]}],defaultEffects:{bearing:0,legalWork:0,fairiesFlatteryNext:0,crowdedFarming:0,extraEggOutlet:0,hatchingFeed:0,safetyCover:0,recyclingSubsidy:0,chemicalWeaponSubsidy:0,preventiveMaintenance:0,dudFilter:0,durabilityCoating:0,laborExploitation:0,usedMachineActive:!1,rescueLoanCharges:0,loans:[]},commonWeight:8,rareWeight:2,ultraRareWeight:.45,baseDraftSize:3,maxDudsPerDraft:2,dudChancePerCard:.3,dudChanceReductionPerFilter:.05,extraCardsAddedPicks:2,rerollCost:{dayDivisor:2,multiplier:100}},contracts:{eventChance:.7,firstTurn:8},maintenance:{fullPerformanceUntilWear:.5,minimumPerformance:.5,durability:{conveyor:1300,eggFarm:475,autoScanner:850,mixer:775,trash:950},processingDelayMaxSeconds:{mixer:1.2,trash:1},repairman:{dailyCost:100,secondsPerOnePercent:.5,walkSpeed:90}},facilities:{conveyor:{id:"conveyor",type:"conveyor",name:"Conveyor",shortName:"Belt",price:30,buildable:!0,upgradeable:!1},eggFarm:{id:"eggFarm",type:"eggFarm",name:"Egg Farm",shortName:"EGG",price:250,buildable:!0,upgradeable:!0,maxLevel:4,upgradeCosts:[null,300,720,1600]},manualScanner:{id:"manualScanner",type:"scanner",kind:"manual",name:"Manual Scanner",shortName:"Manual Scanner",price:260,buildable:!0,upgradeable:!1},autoScanner:{id:"autoScanner",type:"scanner",kind:"auto",name:"Auto Scanner",shortName:"Auto Scanner",price:360,buildable:!0,upgradeable:!1},mixer:{id:"mixer",type:"facility",name:"Mixer",shortName:"MIXER",price:450,buildable:!0,upgradeable:!0,incomeKey:"mixer",body:{w:164,h:126}},trash:{id:"trash",type:"facility",name:"Waste Shredder",shortName:"SHREDDER",price:240,buildable:!0,upgradeable:!0,body:{w:180,h:100}},truck:{id:"truck",type:"facility",name:"Truck",shortName:"TRUCK",price:450,buildable:!0,upgradeable:!0,incomeKey:"truck",body:{w:176,h:138}}}};var ln=H.version,At=H.time.daySeconds,zt=H.cash.starting,fe=H.economy,Go=H.time.farmShutdownGraceSeconds,an=H.production.autoScannerCooldown,Uo=H.production.autoScannerUpgradeRate,Nn=H.production.autoScannerMinCooldown,Wo=H.contracts.eventChance,bt=H.contracts.firstTurn,_o=H.production.poopRate,cn=H.conveyor.baseSpeed,Dt=H.conveyor.maxSpeed,un=H.conveyor.bearingSpeedMultiplier,ke=H.cards,Ko=H.cards.definitions,Gn=H.cards.defaultEffects,nt=H.production.eggSpawnRanges,y=H.grid,pe=H.facilities,Un=["conveyor","eggFarm","autoScanner","manualScanner","mixer","trash","truck"],ot=["mixer","trash","truck"],Ho=["mixer","truck"],kt=Object.fromEntries(Object.entries(pe).map(([e,t])=>[e,t.price])),ge=[{name:"right",dc:1,dr:0,angle:0,opposite:"left"},{name:"left",dc:-1,dr:0,angle:Math.PI,opposite:"right"},{name:"down",dc:0,dr:1,angle:Math.PI/2,opposite:"up"},{name:"up",dc:0,dr:-1,angle:-Math.PI/2,opposite:"down"}],d={bg:"#eefbea",ink:"#102015",muted:"#526456",green:"#22b94f",greenSoft:"#b7f5c6",mixerBlue:"#2477ff",truckPink:"#ff6aa8",wasteGreen:"#22b94f",danger:"#c42424",warn:"#f0a020",white:"#ffffff",poop:"#7b4a23",male:"#62a9ff",female:"#ff8bc6"},we={ambient:0,important:1,critical:2};function S(e){let t=Number(e)||0;return`${t<0?"-":""}\uFFE5${Math.ceil(Math.abs(t)).toLocaleString("ja-JP")}`}function F(e,t){return`${e},${t}`}function ee(e){let[t,n]=String(e).split(",").map(Number);return{col:t,row:n}}function Vt(e,t,n){return Math.max(t,Math.min(n,e))}function O(e,t){return e+Math.random()*(t-e)}function Ee(e,t){return e>=0&&e=0&&tMath.round(Vt(r,0,255)).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`}function _n(e,t,n){let o=qo(e),r=qo(t);return is(Wn(o.r,r.r,n),Wn(o.g,r.g,n),Wn(o.b,r.b,n))}var te={appTitle:"Chick Sorter",versionTitle:`Chick Sorter ${ln}`,currency:"\uFFE5",phases:{title:"Title",build:"Build",running:"Sorting",clearing:"Clearing",loanDecision:"Emergency Loan",gameover:"Game Over"},actions:{startGame:"Start Game",nextDay:"Next Day",buildPhase:"Build Phase",restart:"Restart",close:"Close",remove:"Remove",refund:"Refund",autoMenu:"Auto Menu"},status:{build:e=>`BUILD: ${(e==="erase"?"SELL":e||"SELECT").toUpperCase()} | Right-drag pan | Hover equipment for info`,sorting:"Sorting: use scanner keys. Build after clearing the day.",allPortsConnected:"Start condition met: one EGG route reaches an exit.",equipmentPanelEmpty:"Hover equipment in Build phase.",eventPanelRunning:"Forced events appear in Build phase."},routeLabels:{mixer:"MIXER",truck:"TRUCK",trash:"WASTE",scanner:"NEXT","scanner-role-1":"NEXT",input:"IN"},fail:{outOfGrid:"Out of grid",cellOccupied:"Cell occupied",notEnoughCash:"Not enough cash",facilityExists:"Facility already exists",facilityOverlap:"Facility overlap",nothingToErase:"Nothing to sell",noUpgrade:"No upgrade available"}};function Ft(e){return pe[e]?.name||String(e||"").replace(/^[a-z]/,t=>t.toUpperCase())}function ss(e){let t=pe[e];return t?e==="conveyor"?`${S(t.price)} / tile`:e==="autoScanner"?`${S(t.price)} / ${an.toFixed(1)}s cooldown`:e==="trash"?S(t.price):S(t.price):""}function ls(e){return{conveyor:"A narrow green belt. Routes decide whether chicks live, ship, or become invoices.",eggFarm:"A tiny gatehouse producing questionable eggs on schedule.",autoScanner:"An automated judge. Faster than hands, still very sure of itself.",manualScanner:"A manual checkpoint. The operator is the algorithm.",mixer:"Male chicks become revenue here. Do not feed it poop.",trash:"A polite shredder for poop and other regrets.",truck:"Ships the target cargo. Wrong cargo still leaves a paper trail."}[e]||""}function zo(e){let t=ls(e);return`${Ft(e)}${ss(e)}${t?`${t}`:""}`}function Vo(e){return te.routeLabels[e]||String(e).toUpperCase()}function Xo(e){let t=2166136261;for(let n=0;n>>0}function Jo(e){let t=e>>>0;return()=>{t+=1831565813;let n=Math.imul(t^t>>>15,1|t);return n^=n+Math.imul(n^n>>>7,61|n),((n^n>>>14)>>>0)/4294967296}}function fn(){return`RUN-${Date.now().toString(36)}-${Math.floor(Math.random()*1e6).toString(36)}`.toUpperCase()}function Qo({seed:e,targetRatio:t=.2,reserved:n=[]}={}){let o=Jo(Xo(e||fn())),r=new Set(n.map(f=>typeof f=="string"?f:F(f.col,f.row))),i=[];for(let f=0;f0;f-=1){let w=Math.floor(o()*(f+1));[i[f],i[w]]=[i[w],i[f]]}let l=Math.round(y.cols*y.rows*t);return new Set(i.slice(0,Math.min(l,i.length)).map(f=>f.k))}function Zo({seed:e,colStart:t=0,colEnd:n=y.cols,rowStart:o=0,rowEnd:r=y.rows,targetRatio:i=.2,reserved:l=[]}={}){let f=Jo(Xo(e||fn())),w=new Set(l.map(z=>typeof z=="string"?z:F(z.col,z.row))),M=[],R=Math.max(0,Math.floor(t)),D=Math.max(R,Math.floor(n)),I=Math.max(0,Math.floor(o)),j=Math.max(I,Math.floor(r));for(let z=I;z0;z-=1){let X=Math.floor(f()*(z+1));[M[z],M[X]]=[M[X],M[z]]}let se=Math.round((D-R)*(j-I)*i);return new Set(M.slice(0,Math.min(se,M.length)).map(z=>z.k))}var It=10,jo=2,er=1;function Lt(e,t){return`${e},${t}`}function as(e){let[t,n]=String(e).split(",").map(Number);return{chunkX:t,chunkY:n}}function pn(e){let t=H.grid.expansion||{},n=Math.max(1,(e.gridExpansionPurchases||0)+1),o=(t.costBase||1e3)*n*(t.costMultiplier||4/3),r=Math.max(1,t.truncateUnit||100);return Math.floor(o/r)*r}function tr(e){e.ownedCells=new Set,e.ownedChunks=new Set,e.gridChunkOriginY=0,e.gridExpansionPurchases=0,e.gridExpansionPurchasesByDirection={right:0,up:0};for(let t=0;t=0&&t=0&&n0)continue;let M=Lt(w.chunkX,w.chunkY);t.has(M)||n.has(M)||n.set(M,Kn(e,w.chunkX,w.chunkY,w.direction))}}return[...n.values()].sort((o,r)=>{let i=o.direction===r.direction?0:o.direction==="right"?-1:1;return i||(o.chunkY!==r.chunkY?o.chunkY-r.chunkY:o.chunkX-r.chunkX)})}function rr(e,t="right"){let n=vt(e);return n.find(o=>o.direction===t)||n[0]||null}function Ct(e){return{x:y.x+e.colStart*y.cell,y:y.y+e.rowStart*y.cell,w:e.cols*y.cell,h:e.rows*y.cell}}function Hn(e){let t=Ct(e);return{x:t.x+t.w/2-116,y:t.y+t.h/2-36,w:232,h:72,cx:t.x+t.w/2,cy:t.y+t.h/2}}function ir(e,t){let n=Hn(e);return t.x>=n.x&&t.x<=n.x+n.w&&t.y>=n.y&&t.y<=n.y+n.h}function sr(e){let t=[];for(let n=e.rowStart;nEe(t.col,t.row))}function ms(e){return[{col:e.col,row:e.row+1},{col:e.col-1,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row-1}].filter(t=>Ee(t.col,t.row))}function fr(e){let t=new Set([...e.conveyorTiles]),n=o=>{o&&Ee(o.col,o.row)&&t.add(F(o.col,o.row))};for(let o of e.scanners){n(o);for(let r of hs(o))n(r)}for(let o of e.eggFarms){n(o);for(let r of ms(o))n(r)}for(let o of Object.values(e.facilities))n(o.entry);return t}function ur(e){let t=ds.map(([n,o])=>({col:n,row:o}));for(let{col:n,row:o}of t)dr(e,n,o);for(let n=0;n({...n,keys:n.keys?{left:{...n.keys.left},right:{...n.keys.right}}:null,queue:[]})),e.eggFarms=ps.map(n=>{let o=St(n);return{...n,nextSpawn:o,lastInterval:o}});let t=fr(e);e.blockedCells=Qo({seed:e.runSeed,targetRatio:H.map.blockedRatio,reserved:[...t]}),xs(e),ur(e),e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function le(e){return P(e.col,e.row)}function Ot(e,t,n){return e.eggFarms.find(o=>o.col===t&&o.row===n)||null}function Nt(e,t,n){return e.scanners.find(o=>o.col===t&&o.row===n)||null}function it(e,t){return e.scanners.find(n=>n.id===t)||null}function Xn(e,t){return e.scanners.find(n=>n.kind==="manual"&&n.slot===t)||null}function ve(e,t){return{inputA:{col:e.col,row:e.row-1},inputB:null,left:{col:e.col-1,row:e.row},right:{col:e.col+1,row:e.row}}[t]}function hr(e){return e?ge.map(t=>({col:e.col+t.dc,row:e.row+t.dr})).filter(t=>Ee(t.col,t.row)):[]}function Jn(e,t,n=[],o=[]){if(!t||!Ee(t.col,t.row))return[];let r=[],i=l=>{!l||!Ee(l.col,l.row)||!e.conveyorTiles.has(F(l.col,l.row))||n.some(f=>f&&dn(l,f))||r.some(f=>dn(f,l))||r.push({...l,viaTolerance:!dn(l,t)})};i(t);for(let l of o)i(l);for(let l of hr(t))i(l);return r}function pr(e,t,n=[],o=[]){let r=Jn(e,t,n,o),i=r.filter(l=>!l.viaTolerance);return i.length?i:r}function ws(e,t){let n=ve(t,"inputA");return Jn(e,n,[{col:t.col,row:t.row}])}function bs(e,t,n){let o=ve(t,n);return Jn(e,o,[{col:t.col,row:t.row}])}function ks(e,t){let n=e.facilities[t];return n?n.entry?P(n.entry.col,n.entry.row):t==="mixer"?{x:n.x+n.w,y:n.y+n.h*.52}:t==="truck"?{x:n.x,y:n.y+n.h*.52}:t==="trash"?{x:n.x+n.w/2,y:n.y+8}:{x:n.x+n.w/2,y:n.y+n.h/2}:null}function mr(e,t,n){return n==="inputA"?ws(e,t).length>0:bs(e,t,n).length>0}function he(e){e.branchCounters?.clear?.(),e.routeCache=null,e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function Pe(e,t){return F(e,t)}function Bt(e){return ee(e)}function vs(e,t){let n=e.conveyorMeta?.get?.(t)||{},o=[];return Array.isArray(n.outDirs)&&o.push(...n.outDirs),n.dir&&o.push(n.dir),[...new Set(o)].filter(r=>ge.some(i=>i.name===r))}function Cs(e){return{version:e.routingVersion||0,cells:new Set,adjacency:new Map,components:new Map,cellToComponent:new Map,scannerInputs:new Map,scannerPorts:new Map,facilityPorts:new Map,farmOutputs:new Map,pathCache:new Map,metrics:{conveyorCells:0,edges:0,components:0,deadEnds:0,crosses:0,scannerPorts:0,connectedScannerPorts:0,facilityPorts:0,connectedFacilityPorts:0,farmOutputs:0},issues:[]}}function Ss(e){let t=Cs(e);for(let o of e.conveyorTiles)t.cells.add(o),t.adjacency.set(o,[]);for(let o of t.cells){let r=Bt(o),i=vs(e,o),l=i.length?ge.filter(f=>i.includes(f.name)):ge;for(let f of l){let w=Pe(r.col+f.dc,r.row+f.dr);t.cells.has(w)&&t.adjacency.get(o).push({key:w,dir:f.name})}}let n=0;for(let[o,r]of t.adjacency.entries()){n+=r.length;let i=new Set(r.map(l=>l.dir));r.length===1&&(t.metrics.deadEnds+=1),r.length===4&&i.has("left")&&i.has("right")&&i.has("up")&&i.has("down")&&(t.metrics.crosses+=1)}return t.metrics.conveyorCells=t.cells.size,t.metrics.edges=Math.floor(n/2),Ms(t),Ts(e,t),t.issues=Ns(e,t,{includeRoutes:!1}),t}function Ms(e){let t=1;for(let n of e.cells){if(e.cellToComponent.has(n))continue;let o=t++,r=[n],i=[];for(e.cellToComponent.set(n,o);r.length;){let l=r.shift();i.push(l);for(let f of e.adjacency.get(l)||[])e.cellToComponent.has(f.key)||(e.cellToComponent.set(f.key,o),r.push(f.key))}e.components.set(o,{id:o,cells:i,capacity:Math.max(1,i.length),count:0,ratio:0})}e.metrics.components=e.components.size}function Ts(e,t){for(let n of e.scanners){let o={};for(let r of["inputA","left","right"]){let i=ve(n,r),l=pr(e,i,[{col:n.col,row:n.row}]).filter(M=>t.cells.has(Pe(M.col,M.row))),f=l.map(M=>Pe(M.col,M.row)),w=f.length>0;if(o[r]={type:r,cell:i,cells:l,keys:f,key:f[0]||null,connected:w},t.metrics.scannerPorts+=1,w&&(t.metrics.connectedScannerPorts+=1),r==="inputA")for(let M of f)t.scannerInputs.set(M,n.id)}t.scannerPorts.set(n.id,o)}for(let[n,o]of Object.entries(e.facilities)){if(!o.entry)continue;let r=pr(e,o.entry).filter(f=>t.cells.has(Pe(f.col,f.row))),i=r.map(f=>Pe(f.col,f.row)),l=i.length>0;t.facilityPorts.set(n,{id:n,cell:{...o.entry},cells:r,keys:i,key:i[0]||null,connected:l}),t.metrics.facilityPorts+=1,l&&(t.metrics.connectedFacilityPorts+=1)}for(let n of e.eggFarms){let o=hr({col:n.col,row:n.row}).map(r=>Pe(r.col,r.row)).filter(r=>t.cells.has(r));t.farmOutputs.set(n.id,o),t.metrics.farmOutputs+=o.length}}function Ce(e){let t=e.routingVersion||0;return(!e.factoryGraph||e.factoryGraph.version!==t)&&(e.factoryGraph=Ss(e)),e.factoryGraph}function xr(e){let t=Ce(e);return e.factoryGraphCommittedVersion=t.version,e.factoryGraphSnapshot=gs(t),t}function gs(e){return e?{version:e.version,conveyorCells:e.metrics.conveyorCells,edges:e.metrics.edges,components:e.metrics.components,deadEnds:e.metrics.deadEnds,crosses:e.metrics.crosses,scannerPorts:`${e.metrics.connectedScannerPorts}/${e.metrics.scannerPorts}`,facilityPorts:`${e.metrics.connectedFacilityPorts}/${e.metrics.facilityPorts}`,farmOutputs:e.metrics.farmOutputs,issues:[...e.issues||[]]}:null}function wr(e,t,n){let o=Ce(e),r=Pe(t,n);return(o.adjacency.get(r)||[]).map(i=>({...Bt(i.key),dir:ge.find(l=>l.name===i.dir)||{name:i.dir,dc:0,dr:0}}))}function Es(e,t){let n=t.col-e.col,o=t.row-e.row;return ge.find(r=>r.dc===n&&r.dr===o)?.name||null}function Ps(e,t){let n=e.adjacency.get(t)||[],o=new Set(n.map(r=>r.dir));return n.length===4&&o.has("left")&&o.has("right")&&o.has("up")&&o.has("down")}function Qn(e,t,n){let o=Ce(e),r=Pe(t.col,t.row);if(!o.cells.has(r))return[];let i=`${r}|${n.cacheKey||"dynamic"}`;if(n.cacheKey&&o.pathCache.has(i))return o.pathCache.get(i).map(g=>g.map(W=>({...W})));let l=`${r}|none`,f=[{key:r,col:t.col,row:t.row,incoming:"none",depth:0}],w=new Map([[l,0]]),M=new Map,R=[],D=1/0,I=8,j=24,se=80;for(;f.length;){let g=f.shift();if(g.depth>D)break;let W=`${g.key}|${g.incoming}`;if(n(g)){if(R.push(W),D=g.depth,R.length>=j)break;continue}for(let _ of o.adjacency.get(g.key)||[]){let ae=Bt(_.key),Z=Es(g,ae);if(g.incoming!=="none"&&Ps(o,g.key)&&Z!==g.incoming)continue;let me=g.depth+1;if(me>D)continue;let E=`${_.key}|${Z}`,A=w.get(E);if(A==null)w.set(E,me),M.set(E,[W]),f.push({key:_.key,col:ae.col,row:ae.row,incoming:Z,depth:me});else if(A===me){let x=M.get(E)||[];x.length{if(z.length>=se)return;let[_]=g.split("|"),ae=[Bt(_),...W];if(g===l||_===r){z.push(ae);return}for(let Z of M.get(g)||[])X(Z,ae)};for(let g of R)X(g,[]);let ue=[],ie=new Set;for(let g of z){let W=g.map(_=>Pe(_.col,_.row)).join(">");ie.has(W)||(ie.add(W),ue.push(g))}return n.cacheKey&&o.pathCache.set(i,ue.map(g=>g.map(W=>({...W})))),ue}function br(e){let t=Ce(e),n=new Map;for(let[o,r]of t.components.entries())n.set(o,{id:o,cells:[...r.cells],capacity:r.capacity,count:0,ratio:0});return{components:n,cellToComponent:new Map(t.cellToComponent)}}function kr(e,t,n){let o=Ce(e),r=null,i=1/0;for(let l of o.cells){let f=ee(l),w=P(f.col,f.row),M=Math.hypot(w.x-t,w.y-n);MP(o.col,o.row));return t&&n.push(t),n}function rt(e,t){t&&(!e.length||Yo(e[e.length-1],t)>1)&&e.push(t)}function Rs(e,t,n,o=null){let r=[{x:e.x,y:e.y}];rt(r,P(t.col,t.row));for(let i of xn(n,o))rt(r,i);return r}function $s(e,t){let n=xn(e),o=ve(t,"inputA");return o&&rt(n,P(o.col,o.row)),rt(n,le(t)),n}function As(e,t,n,o){let r=[{x:e.x,y:e.y}];rt(r,P(t.col,t.row));for(let l of xn(n))rt(r,l);let i=ve(o,"inputA");return i&&rt(r,P(i.col,i.row)),rt(r,le(o)),r}function Ds(e,t,n=0){let o=P(t.col,t.row),r=0;for(let i of e.chicks||[]){if(i.stage==="flying"||i.stage==="queued")continue;Math.hypot(i.x-o.x,i.y-o.y){let D=M.roleBias??0,I=R.roleBias??0;if(D!==I)return D-I;let j=M.cells?.length??M.route?.length??Number.POSITIVE_INFINITY,se=R.cells?.length??R.route?.length??Number.POSITIVE_INFINITY;if(j!==se)return j-se;let z=M.key||JSON.stringify(M.route||M.cells||M),X=R.key||JSON.stringify(R.route||R.cells||R);return z.localeCompare(X)});if(!o||r.length===1)return r[0];let i=r[0].roleBias??0,l=r.filter(M=>(M.roleBias??0)===i),f=Math.min(...l.map(M=>yr(e,M)));l=l.filter(M=>yr(e,M)===f);let w=e.branchCounters.get(t)||0;return e.branchCounters.set(t,w+1),l[Math.floor(Math.random()*l.length)]}function vr(e){return e.role===0?{left:{match:"male",destination:"mixer"},right:{match:"default",destination:"scanner-role-1"}}:{left:{match:"poop",destination:"trash"},right:{match:"default",destination:"truck"}}}function Zn(e){let t=vr(e);return{left:t.left.destination,right:t.right.destination}}function jn(e,t){return vr(e).left.match===t.sex?"left":"right"}function eo(e){return Vo(e)}function to(e){return{mixer:"#2477ff",truck:"#ff6aa8",trash:"#22b94f","scanner-role-1":"#526456",scanner:"#526456",input:"#526456"}[e]||"#102015"}function Ye(e,t,n=!1){let o=Ce(e),r=(o.farmOutputs.get(t.id)||[]).map(Bt),i=[];for(let w of r){let M=D=>o.scannerInputs.has(Pe(D.col,D.row));M.cacheKey=`farmInput:${w.col},${w.row}:v${o.version}`;let R=Qn(e,w,M);for(let D of R){let I=D[D.length-1],j=o.scannerInputs.get(Pe(I.col,I.row)),se=it(e,j);se&&i.push({key:`${se.id}:${I.col},${I.row}:${D.length}`,scanner:se,cells:D})}}let l=mn(e,`farm:${t.id}`,i,n);if(l)return{scannerId:l.scanner.id,route:$s(l.cells,l.scanner)};let f=mn(e,`farm:${t.id}:output`,r.map(w=>({key:F(w.col,w.row),cells:[w]})),n);return f?{scannerId:null,route:xn(f.cells)}:null}function Qt(e,t,n,o,r=!1){let i=it(e,o);if(!i)return null;let f=Ce(e).scannerPorts.get(i.id)?.[t],w=ve(i,t),M=f?.connected?(f.keys||[f.key]).filter(Boolean).map(Bt):[];if(!w||!M.length)return null;let R=Zn(i)[t];return R==="scanner-role-1"?Fs(e,i,t,n,w,M,r):Is(e,i,t,n,w,M,R,r)}function Fs(e,t,n,o,r,i,l){let f=Ce(e),w=e.scanners.filter(D=>D.id!==t.id&&f.scannerPorts.get(D.id)?.inputA?.connected),M=[];for(let D of i)for(let I of w){let j=f.scannerPorts.get(I.id)?.inputA?.key;if(!j)continue;let se=(f.scannerPorts.get(I.id)?.inputA?.keys||[j]).filter(Boolean),z=ie=>se.includes(Pe(ie.col,ie.row));z.cacheKey=`toScanner:${D.col},${D.row}:${I.id}:v${f.version}`;let X=Qn(e,D,z),ue=I.role===1?0:1;for(let ie of X)M.push({key:`${ue}:start${F(D.col,D.row)}:s${I.id}:${ie.length}:${F(ie[ie.length-1].col,ie[ie.length-1].row)}`,target:I,cells:ie,roleBias:ue})}let R=mn(e,`scanner:${t.id}:${n}:toRole1`,M,l);return R?{destination:"scanner",nextScannerId:R.target.id,route:As(o,r,R.cells,R.target)}:null}function Is(e,t,n,o,r,i,l,f){let w=Ce(e),M=w.facilityPorts.get(l);if(!M?.connected)return null;let R=[];for(let I of i){let j=(M.keys||[M.key]).filter(Boolean);if(!j.length)continue;let se=X=>j.includes(Pe(X.col,X.row));se.cacheKey=`toFacility:${I.col},${I.row}:${l}:v${w.version}`;let z=Qn(e,I,se);for(let X of z)R.push({key:`start${F(I.col,I.row)}:${l}:${X.length}:${F(X[X.length-1].col,X[X.length-1].row)}`,cells:X})}let D=mn(e,`scanner:${t.id}:${n}:${l}`,R,f);return D?{destination:l,route:Rs(o,r,D.cells,ks(e,l))}:null}function Cr(e,t,n=new Set){if(!t||n.has(t.id))return!1;n.add(t.id);for(let o of["left","right"]){let r=Qt(e,o,le(t),t.id,!1);if(r){if(["mixer","trash","truck"].includes(r.destination))return!0;if(r.destination==="scanner"){let i=it(e,r.nextScannerId);if(Cr(e,i,n))return!0}}}return!1}function Sr(e,t,n,o=new Set){if(!t||o.has(t.id))return!1;o.add(t.id);for(let r of["left","right"]){let i=Qt(e,r,le(t),t.id,!1);if(i){if(i.destination===n)return!0;if(i.destination==="scanner"){let l=it(e,i.nextScannerId);if(Sr(e,l,n,o))return!0}}}return!1}function Ls(e,t){return!!Ye(e,t,!1)?.scannerId}function Bs(e,t){return Ce(e).facilityPorts.get(t)?.connected?e.scanners.some(o=>Sr(e,o,t)):!1}function wn(e){if(e.phase!=="build")return[];let t=[];for(let n of e.eggFarms||[])Ls(e,n)||t.push({type:"eggFarm",id:n.id,ref:n,message:"This Egg will not produce chicks"});for(let n of ot){let o=e.facilities?.[n];o&&!Bs(e,n)&&t.push({type:"facility",id:n,ref:o,message:"This facility cannot receive items"})}return t}function Os(e){let t=Ce(e);for(let r of e.eggFarms||[]){let i=Ye(e,r,!1);if(!i?.scannerId)continue;let l=it(e,i.scannerId);if(Cr(e,l))return[]}let n=e.eggFarms?.length||0,o=["mixer","trash","truck"].filter(r=>t.facilityPorts.get(r)?.connected).length;return n?t.metrics.farmOutputs?e.scanners?.length?o?["Connect at least one EGG through a scanner to any valid exit."]:["Connect at least one receiver exit: Mixer, Shredder, or Truck."]:["Build at least one scanner and connect it to an EGG route."]:["Connect at least one EGG to a conveyor."]:["Build at least one EGG before starting the next day."]}function hn(e){return e.kind==="manual"?`S${(e.slot??0)+1}`:`Auto Scanner #${e.id}`}function Ns(e,t=Ce(e),n={}){let o=n.includeRoutes!==!1,r=[],i={mixer:"Mixer",trash:"Shredder",truck:"Truck"};for(let l of ot){if(!e.facilities[l]){r.push(`${i[l]||l} is missing`);continue}t.facilityPorts.get(l)?.connected||r.push(`${i[l]||l} receiver has no conveyor`)}for(let l of e.scanners){let f=t.scannerPorts.get(l.id)||{};if(f.inputA?.connected||r.push(`${hn(l)} input has no conveyor`),f.left?.connected||r.push(`${hn(l)} left output has no conveyor`),f.right?.connected||r.push(`${hn(l)} right output has no conveyor`),!!o)for(let w of["left","right"])f[w]?.connected&&!Qt(e,w,le(l),l.id)&&r.push(`${hn(l)} ${w} route is incomplete`)}if(o)for(let l of e.eggFarms)Ye(e,l)?.scannerId||r.push(`Egg Farm #${l.id} has no scanner route`);else for(let l of e.eggFarms)(t.farmOutputs.get(l.id)||[]).length||r.push(`Egg Farm #${l.id} has no output conveyor`);return[...new Set(r)]}function Zt(e){return Os(e)}function Mr(e){return Zt(e).length===0}var Tr=[{target:"female",title:"Premium Female Shipment",route:"Female -> Truck",note:"Only female chicks are valid truck cargo this turn."},{target:"male",title:"Male Export Trial",route:"Male -> Truck",note:"Male chicks are temporarily valid truck cargo. Male truck fines are suspended for valid male cargo."},{target:"poop",title:"Contaminant Sample Export",route:"Poop -> Truck",note:"Poop is temporarily valid truck cargo. Shipped poop does not soil this contract shipment."}];function no(e){return[...e.eggFarms.map(t=>t.price||0),...e.scanners.map(t=>t.price||0),...Object.values(e.facilities).map(t=>t.price||0),...[...e.conveyorMeta.values()].map(t=>t.price||0)].reduce((t,n)=>t+n,0)}function Gs(e,t=1){return e.eggFarms.reduce((n,o)=>{let[r,i]=Jt(o),l=Math.max(.1,(r+i)/2);return n+At/l*t},0)}function gr(e){if(e.turn+1Wo)return null;let n=Tr[Math.floor(Math.random()*Tr.length)],o=2,r=3,i=Gs(e,o),l=Math.max(1,Math.ceil(i*.9)),f=Math.round((.08+Math.random()*.08)*100)/100,w=Math.floor(no(e)*f),M=Math.floor(Math.max(0,e.cash)*.25),R=Math.max(w,M);return{id:`contract-${e.turn}-${Date.now()}-${Math.floor(Math.random()*9999)}`,...n,forced:!0,productionMultiplier:o,poopMultiplier:r,targetAmount:l,estimatedOutput:Math.round(i),rewardRate:f,reward:R,rewardByFactory:w,rewardByCash:M,createdTurn:e.turn,oneTurnOnly:!0}}function Er(e){e.contractActive=e.contractOffer?{...e.contractOffer}:null,e.contractOffer=null}function Pr(e){e.contractActive=null}function Rr(e){return e.contractActive?.productionMultiplier||1}function $r(e){let t=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),n=Math.pow(1.03,t);return Math.min(.95,_o*(e.contractActive?.poopMultiplier||1)*n)}function ze(e){return e.contractActive?.target||"female"}function oo(e,t){return t==="male"?e.truckMale||0:t==="poop"?e.poopTruck||0:e.truckFemale||0}function Ar(e,t){return ze(e)===t}function Dr(e){return ze(e)!=="male"}function Fr(e){let t=e.contractActive;if(!t)return null;let n=oo(e.stats,t.target),o=n>=t.targetAmount,r=o?t.reward:0;r>0?(Ae(e,r),e.stats.contractBonus=r,e.totals.contractBonus+=r,e.totals.contractSuccess+=1):(e.stats.contractBonus=0,e.totals.contractFailed+=1);let i={title:t.title,target:t.target,route:t.route,targetAmount:t.targetAmount,count:n,success:o,bonus:r,reward:t.reward,productionMultiplier:t.productionMultiplier,poopMultiplier:t.poopMultiplier};return e.stats.contractResult=i,i}function ro(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Us(e){return!!e?.cardEffects?.usedMachineActive}function Ws(e,t){return t?1:Math.min(.8,.5+.1*Math.min(3,ro(e,"recyclingSubsidy")))}function _s(e){return Math.pow(.95,ro(e,"safetyCover"))}function io(e){let t=e?.ref||e||{},n=e?.type||t.type;return n==="conveyor"?pe.conveyor.price:n==="eggFarm"?t.price||pe.eggFarm.price:n==="scanner"?t.price||(t.kind==="auto"?pe.autoScanner.price:pe.manualScanner.price):n==="facility"?t.price||pe[t.id]?.price||0:pe[t.id]?.price||0}function Re(e,t=null){let n=pe[e]?.price||0;return Us(t)?Math.ceil(n*.5):n}function Ks(e,t){return Math.max(0,(e.facilities?.[t]?.level||1)-1)}function st(e,t){return Ho.includes(t)?Math.pow(fe.incomeUpgradeRate,Ks(e,t)):1}function lt(e){return Math.ceil(fe.income.mixer*st(e,"mixer"))}function Ie(e){return Math.ceil(fe.income.truck*st(e,"truck"))}function jt(e){return Math.ceil(fe.poopFine*st(e,"mixer"))}function en(e){return Math.ceil(fe.poopFine*st(e,"truck"))}function so(e){let t=fe.maleTruckFinePerHalfDay*(e.turn/2);return Math.ceil(t*st(e,"truck"))}function Mt(e){let t=Math.max(0,(e.facilities?.trash?.level||1)-1);return Math.min(fe.shredderBonus.maxCards,t)}function Ir(e){return Math.max(0,(e.facilities?.trash?.level||1)-1)}function Gt(){return fe.shredderBonus.maxCards}function at(e){let t=typeof e=="number"?e:Mt(e),n=Math.min(fe.shredderBonus.maxCards,Math.max(0,t)),o=Math.sqrt(n)/fe.shredderBonus.probabilityPercentDivisor*n;return Math.min(1,o/100)}function Hs(e){let t=Mt(e),n=at(t),o=t>0&&Math.random()0&&(e.stats.shredderBonus=(e.stats.shredderBonus||0)+t.amount,e.totals.shredderBonus=(e.totals.shredderBonus||0)+t.amount,Ae(e,t.amount)),t}function bn(e,t=null){let n=fe.zundaTax,o=Math.max(0,t?.cardEffects?.legalWork||0),r=n.exemption+o*n.legalWorkExemptionBonus,i=n.maxRateCash+o*n.legalWorkExemptionBonus,l=Math.max(0,Math.floor(Number(e)||0)),f=Math.max(0,l-r);if(f<=0)return{profit:l,exemption:r,maxRateCash:i,taxable:0,rate:0,ratePercent:0,tax:0,step:0,legalWork:o};let w=Math.max(1,Math.ceil(f/n.stepAmount)),M=Math.min(n.maxRate,w*n.stepRate),R=Math.ceil(f*M);return{profit:l,exemption:r,maxRateCash:i,taxable:f,rate:M,ratePercent:Math.round(M*100),tax:R,step:w,legalWork:o}}function lo(e,t=e.turn){let n=Math.max(1,Math.floor(Number(t)||1)),o=Math.ceil(n*fe.fairiesTribute.perDay),r=Math.max(0,e?.cardEffects?.fairiesFlatteryNext||e?.cardEffects?.flattery||0),i=r>0?Math.pow(.5,r):1,l=Math.max(0,Math.ceil(o*i)),f=Math.max(0,o-l);return{day:n,base:o,flatteryCount:r,perCardReduction:Math.ceil(o*.5),reduction:f,amount:l}}function Tt(e,t){let n=e?.ref||e||{},o=e?.type==="conveyor"?t?.conveyorMeta?.get(e.oldKey||n.id):n,r=o?.price||io(e||n),i=o?.builtSession===t?.buildSession;if(o?.noRefund||n?.noRefund)return{amount:0,sameBuild:i,price:r,rate:0,noRefund:!0};let l=Ws(t,i);return{amount:Math.max(0,Math.ceil(r*l)),sameBuild:i,price:r,rate:l,noRefund:!1}}function qs(e,t=null){let n=Math.max(1,Math.ceil((Number(e)||0)/fe.explosionDamageDivisor));return Math.max(1,Math.ceil(n*_s(t)))}function Ys(e,t){return Math.max(0,Math.ceil(t))}function Br(e,t){let n=e.cash;e.cash+=t,e.stats.profit+=t,e.totals.profit+=t,t>=0?(e.stats.revenue+=t,e.totals.revenue+=t):(e.stats.penalty+=Math.abs(t),e.totals.penalty+=Math.abs(t)),e.totals.maxCash=Math.max(e.totals.maxCash,e.cash)}function Ae(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Br(e,n),n}function Ve(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Br(e,-n),n}function ct(e,t){Ve(e,t)}function Or(e,t){if(t<=0)return;let n=e.cash;e.cash+=t,e.stats.profit+=t,e.totals.profit+=t,e.totals.maxCash=Math.max(e.totals.maxCash,e.cash)}function Nr(e){let t=lt(e);return e.stats.mixerRevenue+=t,Ae(e,t),t}function Gr(e){let t=jt(e);return e.stats.mixerPoopFine+=t,e.totals.mixerPoopFine+=t,Ve(e,t),t}function Ur(e){let t=en(e);return e.stats.truckPoopFine+=t,e.totals.truckPoopFine+=t,Ve(e,t),t}function Wr(e){let t=so(e);return e.stats.maleTruckFine+=t,e.totals.maleTruckFine+=t,Ve(e,t),t}function _r(e,t){let n=qs(t,e);return e.stats.explosionDamage+=n,e.totals.explosionDamage+=n,Ve(e,n),n}function Kr(e){let t=ze(e),n=oo(e.stats,t),o=Ie(e),r=n*o,i=Ys(e,r);return e.stats.pendingTruckRevenue=i,e.stats.truckRevenue=i,t==="poop"?e.stats.poopShipmentIncome=i:e.stats.chickShipmentIncome=i,i>0&&Ae(e,i),{base:r,adjusted:i,target:t,targetCount:n,unitPrice:o}}function Hr(e,t=0){let n=bn(t,e);return n.tax<=0||(e.totals.zundaTax=(e.totals.zundaTax||0)+n.tax,e.totals.penalty=(e.totals.penalty||0)+n.tax,e.totals.profit=(e.totals.profit||0)-n.tax,e.cash-=n.tax),n}function qr(e,t=e.turn){let n=lo(e,t);return e.cardEffects&&(e.cardEffects.fairiesFlatteryNext=0,e.cardEffects.flattery!=null&&delete e.cardEffects.flattery),n.amount<=0||(e.stats.fairiesTribute=(e.stats.fairiesTribute||0)+n.amount,e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+n.amount,Ve(e,n.amount)),n}function Yr(e){let t=ro(e,"chemicalWeaponSubsidy"),n=Math.max(0,e?.stats?.poopTruck||0),o=Math.floor(n/100),r=t>0&&o>0?o*2e3*t:0;return r>0&&(e.stats.chemicalWeaponSubsidy=(e.stats.chemicalWeaponSubsidy||0)+r,e.totals.chemicalWeaponSubsidy=(e.totals.chemicalWeaponSubsidy||0)+r,Ae(e,r)),{cards:t,poopTruck:n,blocks:o,amount:r}}function zr(e){let t=e?.cardEffects;if(!t||!Array.isArray(t.loans)||!t.loans.length)return{amount:0,paidLoans:0,remainingLoans:0};let n=0,o=0,r=[];for(let i of t.loans){if((i.daysRemaining||0)<=0)continue;let l=Math.max(0,Math.ceil(i.dailyPayment||400));n+=l,o+=1;let f=Math.max(0,(i.daysRemaining||0)-1);f>0&&r.push({...i,daysRemaining:f})}return t.loans=r,n>0&&(e.stats.loanRepayment=(e.stats.loanRepayment||0)+n,e.totals.loanRepayment=(e.totals.loanRepayment||0)+n,Ve(e,n)),{amount:n,paidLoans:o,remainingLoans:r.length}}function Vr(e){let t=no(e),n=Math.max(1,e.totals.turnsCompleted||e.turn||1),o=Math.max(0,e.cash+e.totals.revenue+t*.5+e.totals.contractBonus*.5),r=Math.ceil(o/n),i=Math.floor(n*35+Math.max(0,n-5)*15),l=e.totals.correct*5,f=e.totals.explosionDamage;return{score:Math.max(0,Math.floor(o+r+l-e.totals.penalty-i)),factoryValue:t,base:o,dailyEarned:r,dayPenalty:i,correctBonus:l,explosionPenalty:f,days:n}}function zs(e){return{...e,keys:e.keys?{left:{...e.keys.left},right:{...e.keys.right}}:null,queue:[],cooldown:e.cooldown||0}}function tn(e){return JSON.stringify({cash:e.cash,stats:e.stats,totals:e.totals,nextId:e.nextId,gridX:y.x,gridY:y.y,gridCols:e.gridCols||y.cols,gridRows:e.gridRows||y.rows,gridExpansionPurchases:e.gridExpansionPurchases||0,gridExpansionPurchasesByDirection:e.gridExpansionPurchasesByDirection||{right:0,up:0},gridChunkOriginY:e.gridChunkOriginY||0,ownedCells:[...e.ownedCells||[]],ownedChunks:[...e.ownedChunks||[]],blockedCells:[...e.blockedCells||[]],selected:e.selected,multiSelected:e.multiSelected||[],buildTool:e.buildTool,view:e.view,facilities:e.facilities,eggFarms:e.eggFarms,scanners:e.scanners.map(zs),conveyorTiles:[...e.conveyorTiles],conveyorMeta:[...e.conveyorMeta.entries()],branchCounters:[...e.branchCounters.entries()],cardEffects:e.cardEffects,cardDraft:e.cardDraft,cardTargetPick:e.cardTargetPick})}function Xr(e,t){let n=JSON.parse(t);e.cash=n.cash,e.stats=n.stats,e.totals=n.totals,e.nextId=n.nextId,y.x=n.gridX??H.grid.x,y.y=n.gridY??H.grid.y,y.cols=n.gridCols||H.grid.cols,y.rows=n.gridRows||H.grid.rows,e.gridCols=y.cols,e.gridRows=y.rows,e.gridExpansionPurchases=n.gridExpansionPurchases||0,e.gridExpansionPurchasesByDirection=n.gridExpansionPurchasesByDirection||{right:0,up:0},e.gridChunkOriginY=n.gridChunkOriginY||0,e.ownedCells=new Set(n.ownedCells||[]),e.ownedChunks=new Set(n.ownedChunks||[]),e.gridOwnedCells=e.ownedCells.size||y.cols*y.rows,e.blockedCells=new Set(n.blockedCells||[]),e.selected=n.selected,e.multiSelected=n.multiSelected||[],e.buildTool=n.buildTool,e.view=n.view||{x:0,y:0,scale:1},e.view.scale==null&&(e.view.scale=1),e.facilities=n.facilities||{},e.eggFarms=n.eggFarms||[],e.scanners=(n.scanners||[]).map(o=>({...o,queue:[],cooldown:o.cooldown||0})),e.conveyorTiles=new Set(n.conveyorTiles||[]),e.conveyorMeta=new Map(n.conveyorMeta||[]),e.branchCounters=new Map(n.branchCounters||[]),e.cardEffects=n.cardEffects||{bearing:0,legalWork:0,flattery:0},e.cardEffects.drawBonus!=null&&delete e.cardEffects.drawBonus,e.cardDraft=n.cardDraft||{pending:!1,choices:[],rerolls:0,picksRemaining:0},e.cardDraft.picksRemaining==null&&(e.cardDraft.picksRemaining=e.cardDraft.pending?1:0),e.cardTargetPick=n.cardTargetPick||null,e.groupDrag=null,e.selectionBox=null,e.pan=null,e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function Le(e){e.phase==="build"&&(e.undoStack.push(tn(e)),e.undoStack.length>80&&e.undoStack.shift(),e.redoStack=[])}function ao(e){return e.phase!=="build"||!e.undoStack.length?!1:(e.redoStack.push(tn(e)),Xr(e,e.undoStack.pop()),!0)}function co(e){return e.phase!=="build"||!e.redoStack.length?!1:(e.undoStack.push(tn(e)),Xr(e,e.redoStack.pop()),!0)}function G(e,t,n,o,r=d.ink){e.floatingTexts.push({x:t,y:n,text:o,color:r,life:1,maxLife:1})}function gt(e,t,n){e.shake.strength=Math.max(e.shake.strength,t),e.shake.time=Math.max(e.shake.time,n)}function Jr(e,t,n){e.effects.push({type:"spawn",priority:we.ambient,x:t,y:n,life:.42,maxLife:.42,size:12})}function Qr(e,t,n,o=d.green){e.effects.push({type:"scannerPulse",priority:we.important,x:t,y:n,color:o,life:.42,maxLife:.42,size:24})}function Zr(e,t,n){for(let o=0;o<12;o+=1)e.effects.push({type:"meat",priority:we.important,x:t+O(-18,18),y:n+O(-12,16),vx:O(-60,60),vy:O(-90,-25),life:O(.45,.85),maxLife:.85,size:O(4,8)})}function jr(e,t,n){for(let o=0;o<16;o+=1)e.effects.push({type:"sludge",priority:we.important,x:t+O(-18,18),y:n+O(-12,16),vx:O(-46,46),vy:O(-70,-20),life:O(.45,.9),maxLife:.9,size:O(4,8)})}function ei(e,t,n,o){let r=o==="poop"?d.poop:o==="male"?d.male:d.female;for(let i=0;i<22;i+=1)e.effects.push({type:"shred",priority:we.important,x:t+O(-16,16),y:n+O(-8,8),vx:O(-70,70),vy:O(40,160),color:i%3===0?d.white:r,life:O(.45,.95),maxLife:.95,w:O(3,7),h:O(10,24),rot:O(-Math.PI,Math.PI)});Xe(e,t,n,d.green,34,we.important)}function ti(e,t,n,o){let r=o==="poop"?d.poop:o==="male"?d.danger:d.green;for(let i=0;i<8;i+=1)e.effects.push({type:"load",priority:we.important,x:t+O(-18,18),y:n+O(-18,18),vx:O(-42,42),vy:O(-90,-25),color:r,life:O(.35,.65),maxLife:.65,size:8})}function Xe(e,t,n,o=d.danger,r=52,i=we.critical){e.effects.push({type:"shockwave",priority:i,x:t,y:n,color:o,life:.55,maxLife:.55,size:8,maxSize:r})}function ut(e,t,n,o=12,r=d.danger,i=we.critical){for(let l=0;l0&&(e.shake.time=Math.max(0,e.shake.time-t),e.shake.time<=0&&(e.shake.strength=0));for(let r of e.effects)if(r.life-=t,["meat","sludge","spark","smoke","shred","load","rage"].includes(r.type))r.x+=(r.vx||0)*t,r.y+=(r.vy||0)*t,r.vy=(r.vy||0)+150*t;else if(r.type==="flyingChick"){r.x+=r.vx*t,r.y+=r.vy*t,r.vy+=360*t,r.noDamage||Vs(e,r,o);let i=r.x+e.view.x,l=r.y+e.view.y;(i<-100||l<-100||i>n.width+100||l>n.height+100)&&(r.life=0)}e.effects=e.effects.filter(r=>r.life>0);for(let r of e.floatingTexts)r.life-=t,r.y-=34*t;e.floatingTexts=e.floatingTexts.filter(r=>r.life>0)}function Vs(e,t,n){t.hit||(t.hit=new Set);for(let o of n()){if(t.hit.has(o.id)||t.xo.x+o.w||t.yo.y+o.h)continue;t.hit.add(o.id);let r=_r(e,o.price);G(e,t.x,t.y-10,`-${S(r)}`,d.danger),Xe(e,t.x,t.y,d.danger,30),ut(e,t.x,t.y,5,d.danger),gt(e,5,.18)}}var Se=H.maintenance;function fo(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Cn(e){let t=Math.min(1.4,1+.04*Math.min(10,fo(e,"crowdedFarming"))),n=Math.pow(.95,fo(e,"preventiveMaintenance"));return t*n}function Xs(e){return Math.pow(1.03,fo(e,"durabilityCoating"))}function Sn(e,t,n=1){let o=Se.durability[t]||1e3;return Math.max(1,Math.ceil(o*Math.max(.1,n||1)*Xs(e)))}function mo(e){let t=Se.repairman.dailyCost;return e?.cardEffects?.laborExploitation?Math.ceil(t*.7):t}function ii(e){return Math.max(.1,Number(e?.durabilityBaseMultiplier)||1)}function de(e){e.repairman||(e.repairman={hiredForNextDay:!1,active:!1,x:y.x+y.cell*.5,y:y.y+y.rows*y.cell+84,target:null,repairedToday:0});for(let[t,n]of e.conveyorMeta||[]){n.uses==null&&(n.uses=0),n.maintenanceType==null&&(n.maintenanceType="conveyor");let o=Sn(e,"conveyor",ii(n));(n.durability==null||n.durability0&&(o.processingCooldown=Math.max(0,o.processingCooldown-t))}}function So(e){de(e);let t=[];for(let[n,o]of e.conveyorMeta||[])t.push({type:"conveyor",key:n,meta:o,label:`Belt ${n}`,center:P(ee(n).col,ee(n).row)});for(let n of e.eggFarms||[])t.push({type:"eggFarm",ref:n,label:`EGG #${n.id}`,center:P(n.col,n.row)});for(let n of(e.scanners||[]).filter(o=>o.kind==="auto"))t.push({type:"autoScanner",ref:n,label:`AUTO #${n.id}`,center:P(n.col,n.row)});for(let n of["mixer","trash"]){let o=e.facilities?.[n];o&&t.push({type:n,ref:o,label:o.shortName||o.name||n,center:{x:o.x+o.w/2,y:o.y+o.h/2}})}return t}function vn(e){return e.meta?Ut(e):Ut(e.ref)}function ho(e){return e.meta?po(e):po(e.ref)}function ri(e){return e.meta?yo(e):yo(e.ref)}function Zs(e,t){Js(e.meta?e:e.ref,Math.max(0,ho(e)-t))}function ui(e){return e.type==="conveyor"?`conveyor:${e.key}`:`${e.type}:${e.ref?.id||e.ref?.type||e.type}`}function di(e){if(de(e),e.repairman.hiredForNextDay)return{ok:!1,reason:"Repairman already hired."};let t=mo(e);return e.cashui(o)===t.key)||null}function el(e){let t=null;for(let n of So(e)){let o=vn(n);o<=.001||(!t||o>vn(t))&&(t=n)}return t}function yi(e,t){de(e);let n=e.repairman;if(!n.active||e.phase!=="running")return;let o=js(e,n.target)||el(e);if(!o){n.target=null;return}n.target={key:ui(o),label:o.label};let r=Se.repairman.walkSpeed,i=o.center.x-n.x,l=o.center.y-n.y,f=Math.hypot(i,l);if(f>8){let I=Math.min(f,r*t);n.x+=i/f*I,n.y+=l/f*I;return}let w=t/(Se.repairman.secondsPerOnePercent*100),M=ho(o),R=w*ri(o);Zs(o,R);let D=Math.max(0,(M-ho(o))/ri(o)*100);n.repairedToday=(n.repairedToday||0)+D,D>0&&Math.random()<.02&&G(e,n.x,n.y-28,"REPAIR",d.green),vn(o)<=.001&&(n.target=null)}function tl(e){let t=0,n="none";for(let o of So(e)){let r=vn(o);r>t&&(t=r,n=o.label)}return{ratio:t,percent:Math.round(t*100),label:n}}function Mo(e){let t=tl(e),n=wo(e);return{worst:t,avgBeltPerformance:n,repairman:e.repairman||null}}var nl=ke.commonWeight,ol=ke.rareWeight,rl=ke.ultraRareWeight||.45,Wt=ke.baseDraftSize,_t=Ko;function hi(e,t){let n=Me(e);return Math.max(0,Number(n[t])||0)}function Me(e){e.cardEffects||(e.cardEffects={...Gn,loans:[]});for(let[t,n]of Object.entries(Gn))e.cardEffects[t]==null&&(e.cardEffects[t]=Array.isArray(n)?[]:n);return e.cardEffects.flattery!=null&&(e.cardEffects.fairiesFlatteryNext=Math.max(0,e.cardEffects.fairiesFlatteryNext||0)+Math.max(0,e.cardEffects.flattery||0),delete e.cardEffects.flattery),Array.isArray(e.cardEffects.loans)||(e.cardEffects.loans=[]),e.cardEffects.drawBonus!=null&&delete e.cardEffects.drawBonus,e.cardDraft||(e.cardDraft={pending:!1,choices:[],rerolls:0,picksRemaining:0}),e.cardDraft.picksRemaining==null&&(e.cardDraft.picksRemaining=e.cardDraft.pending?1:0),e.cardEffects}function ki(e){let t=Math.max(.5,1-.05*Math.min(10,hi(e,"crowdedFarming"))),n=Math.pow(.96,hi(e,"hatchingFeed"));return t*n}function vi(e,t=null){return Math.min(3,Math.max(0,Number(t?.extraEggOutlet)||0))}function $n(e,t=null){let n=Me(e),o=cn*Math.pow(un,Math.max(0,n.bearing||0)),r=t?1:wo(e);return Math.min(Dt,o*r)}function Je(e,t=null){let n=Math.max(0,(e?.level||1)-1),o=Math.max(Nn,an*Math.pow(Uo,n));return t?Math.max(Nn,o*Tn(e)):o}function mi(e){let t=e.cardDraft||{rerolls:0},n=Math.max(1,(t.rerolls||0)+1);return Math.ceil(Math.max(1,e.turn||1)/ke.rerollCost.dayDivisor*n*ke.rerollCost.multiplier)}function go(e){return _t.find(t=>t.id===e)||null}function Eo(e,t){let n=typeof t=="string"?go(t):t;if(Me(e),!n||n.type==="dud")return{ok:!1,reason:"Card not found."};if(n.id==="extraCards")return e.cardDraft=e.cardDraft||{pending:!1,choices:[],rerolls:0,picksRemaining:0},e.cardDraft.choices.push(...Pn(e,2)),{ok:!0,reason:`${n.title} added draft cards.`};if(n.type==="instant")return Si(e,n),{ok:!0,reason:`${n.title} granted.`};if(n.type==="equipmentUpgrade"){let o=Ue(e,n)[0];return o?(Ci(e,o),{ok:!0,reason:`${n.title} applied.`}):{ok:!1,reason:`No valid target for ${n.title}.`}}if(n.type==="cellAction"&&n.target==="blockedCell"){let o=Ue(e,n).slice(0,3);if(!o.length)return{ok:!1,reason:"No blocked cells to remove."};for(let r of o){e.blockedCells.delete(F(r.col,r.row));let i=P(r.col,r.row);dt(e,i.x,i.y)}return he(e),{ok:!0,reason:`${n.title} removed ${o.length} blocked cells.`}}return{ok:!1,reason:`${n.title} cannot be debug-granted.`}}function il(e,t){if(t.type==="blockedCell")return`Blocked cell ${t.col},${t.row}`;if(t.type==="eggFarm")return`EGG #${t.id} L${t.level} -> L${t.level+1}`;if(t.type==="eggOutlet"){let n=Math.max(0,Number(t.farm?.extraEggOutlet)||0);return`EGG #${t.id} OUTLET ${1+n} -> ${2+n}`}if(t.type==="scanner")return`AUTO #${t.id} L${t.level} -> L${t.level+1} | CD ${Je(t,e).toFixed(1)}s -> ${Je({...t,level:t.level+1},e).toFixed(1)}s`;if(t.type==="facility"&&t.id==="mixer"){let n=t.level,o=lt(e);t.level=n+1;let r=lt(e);return t.level=n,`MIXER L${t.level} -> L${t.level+1} | ${S(o)} -> ${S(r)}`}if(t.type==="facility"&&t.id==="truck"){let n=t.level,o=Ie(e);t.level=n+1;let r=Ie(e);return t.level=n,`TRUCK L${t.level} -> L${t.level+1} | ${S(o)} -> ${S(r)}`}if(t.type==="facility"&&t.id==="trash"){let n=Mt(e),o=Math.min(Gt(),n+1),r=(at(n)*100).toFixed(2),i=(at(o)*100).toFixed(2);return`SHREDDER L${t.level||1} -> L${(t.level||1)+1} | ${r}% -> ${i}% per item`}return`${t.name||t.id} L${t.level||1} -> L${(t.level||1)+1}`}function sl(e){return[...e.blockedCells||[]].map(t=>{let[n,o]=String(t).split(",").map(Number);return{type:"blockedCell",id:t,col:n,row:o}}).filter(t=>Number.isFinite(t.col)&&Number.isFinite(t.row))}function Ue(e,t){let n=typeof t=="string"?go(t):t;return Me(e),n?n.target==="blockedCell"?sl(e):n.target==="eggFarm"?e.eggFarms.filter(o=>(o.level||1)<4):n.target==="eggOutlet"?e.eggFarms.filter(o=>Math.max(0,Number(o.extraEggOutlet)||0)<3).map(o=>({type:"eggOutlet",id:o.id,col:o.col,row:o.row,farm:o})):n.target==="autoScanner"?e.scanners.filter(o=>o.kind==="auto"):n.target==="mixer"?e.facilities.mixer?[e.facilities.mixer]:[]:n.target==="truck"?e.facilities.truck?[e.facilities.truck]:[]:n.target==="trash"?e.facilities.trash&&Ir(e)=10;if(t.id==="recyclingSubsidy")return(n.recyclingSubsidy||0)>=3;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,ke.dudChancePerCard||0)),r=Math.max(1e-4,Math.min(1,ke.dudChanceReductionPerFilter||.05));return(n.dudFilter||0)>=Math.ceil(o/r)}return t.id==="laborExploitation"?!!n.laborExploitation:t.id==="usedMachine"?!!n.usedMachineActive:t.id==="newMachine"?!n.usedMachineActive:!1}function al(e){let t=e.repairman||{};return!!(t.active||t.hiredForNextDay||e.pendingRepairWorkerWages>0)}function cl(e){return _t.filter(t=>!(t.id==="laborExploitation"&&!al(e)||ll(e,t)||(t.type==="equipmentUpgrade"||t.type==="cellAction")&&Ue(e,t).length<=0))}function xi(e){return e.rarity==="ultraRare"?rl:e.rarity==="rare"?ol:nl}function ul(e){let t=e.reduce((o,r)=>o+xi(r),0),n=Math.random()*t;for(let o of e)if(n-=xi(o),n<=0)return o;return e[e.length-1]}var wi=0;function dl(){return wi+=1,{id:`dud:${Date.now()}:${wi}`,title:"Dud",rarity:"dud",type:"dud",description:"Click to flick this dud away. It does not consume a pick."}}function fl(e){let t=Me(e),n=Math.max(0,Math.min(1,ke.dudChancePerCard||0)),o=Math.max(0,Math.min(1,ke.dudChanceReductionPerFilter||0));return Math.max(0,n-o*Math.max(0,t.dudFilter||0))}function pl(e,t){let n=[...t],o=0,r=Math.max(0,ke.maxDudsPerDraft||0),i=fl(e);for(let l=0;lf.id===i.id);l>=0&&r.splice(l,1)}return pl(e,o)}function Rn(e){return e?e.type==="blockedCell"?`blockedCell:${e.id}`:e.type==="eggFarm"?`eggFarm:${e.id}`:e.type==="eggOutlet"?`eggOutlet:${e.id}`:e.type==="scanner"?`scanner:${e.id}`:e.type==="facility"?`facility:${e.id}`:`${e.type}:${e.id}`:""}function yl(e){if(!e)return null;if(e.type==="blockedCell"){let t=P(e.col,e.row);return{x:t.x-y.cell*.48,y:t.y-y.cell*.48,w:y.cell*.96,h:y.cell*.96,cx:t.x,cy:t.y}}if(e.type==="eggFarm"||e.type==="eggOutlet"){let t=P(e.col,e.row);return{x:t.x-34,y:t.y-34,w:68,h:68,cx:t.x,cy:t.y}}if(e.type==="scanner"){let t=le(e);return{x:t.x-58,y:t.y-42,w:116,h:84,cx:t.x,cy:t.y}}return e.type==="facility"?{x:e.x,y:e.y,w:e.w,h:e.h,cx:e.x+e.w/2,cy:e.y+e.h/2}:null}function Po(e){if(!e.cardTargetPick?.pending)return[];let t=new Set(e.cardTargetPick.targetKeys||[]);return Ue(e,e.cardTargetPick.cardId).filter(n=>t.has(Rn(n))).map(n=>({key:Rn(n),label:il(e,n),target:n,bounds:yl(n)})).filter(n=>n.bounds)}function hl(e,t){let n=Po(e);for(let o of n){let r=o.bounds;if(t.x>=r.x&&t.x<=r.x+r.w&&t.y>=r.y&&t.y<=r.y+r.h)return o.target}return null}function Ci(e,t){if(t.type==="eggOutlet"){let n=t.farm||e.eggFarms.find(r=>r.id===t.id);if(!n)return;n.extraEggOutlet=Math.min(3,Math.max(0,Number(n.extraEggOutlet)||0)+1);let o=P(n.col,n.row);G(e,o.x,o.y-30,`OUTLET ${1+n.extraEggOutlet}`,d.green),he(e);return}if(t.level=(t.level||1)+1,t.type==="eggFarm"){t.nextSpawn=St(t),t.lastInterval=t.nextSpawn;let n=P(t.col,t.row);G(e,n.x,n.y-30,`LV ${t.level}`,d.green);return}if(t.type==="scanner"){let n=le(t);G(e,n.x,n.y-34,`LV ${t.level}`,d.green);return}t.type==="facility"&&G(e,t.x+t.w/2,t.y+18,`LV ${t.level}`,d.green)}function Si(e,t){let n=Me(e),o=r=>{n[r]=Math.max(0,n[r]||0)+1};if(t.id==="bearing"&&o("bearing"),t.id==="legalWork"&&o("legalWork"),t.id==="crowdedFarming"&&(n.crowdedFarming=Math.min(10,(n.crowdedFarming||0)+1)),t.id==="hatchingFeed"&&o("hatchingFeed"),t.id==="safetyCover"&&o("safetyCover"),t.id==="recyclingSubsidy"&&(n.recyclingSubsidy=Math.min(3,(n.recyclingSubsidy||0)+1)),t.id==="chemicalWeaponSubsidy"&&o("chemicalWeaponSubsidy"),t.id==="preventiveMaintenance"&&o("preventiveMaintenance"),t.id==="dudFilter"&&o("dudFilter"),t.id==="durabilityCoating"&&(o("durabilityCoating"),de(e)),t.id==="flattery"&&o("fairiesFlatteryNext"),t.id==="usedMachine"&&(n.usedMachineActive=!0),t.id==="newMachine"&&(n.usedMachineActive=!1),t.id==="laborExploitation"&&(n.laborExploitation=1),t.id==="rescueLoan"&&(o("rescueLoanCharges"),G(e,y.x+y.cols*y.cell/2,y.y-30,"RESCUE HELD",d.green)),t.id==="loan"){let r=Math.max(1,Math.floor(Number(e.turn)||1)),i=300*r;Ae(e,i),n.loans.push({daysRemaining:r,dailyPayment:400,borrowedOnTurn:e.turn||1}),G(e,y.x+y.cols*y.cell/2,y.y-30,`LOAN +${S(i)}`,d.green)}}function Be(e){return`${Math.round(Number(e||0)*100)}%`}function bi(e){let t=nt[Math.max(0,Math.min(nt.length-1,e-1))]||nt[0]||[0,0];return`${t[0].toFixed(2)}-${t[1].toFixed(2)}s`}function En(e,t){return Math.ceil(e*Math.pow(fe.incomeUpgradeRate,Math.max(0,t-1)))}function ml(e,t){let n=Me(e);if(t.id==="upgradeEgg"){let o=Ue(e,t),r=Math.min(3,Math.max(1,o[0]?.level||1));return`Choose one EGG. Level +1. Production interval ${bi(r)} -> ${bi(r+1)}.`}if(t.id==="upgradeAutoScanner"){let o=Ue(e,t)[0]||{level:1},r=Je(o,e),i=Je({...o,level:(o.level||1)+1},e);return`Choose one AUTO SCANNER. Level +1. Cooldown ${r.toFixed(2)}s -> ${i.toFixed(2)}s.`}if(t.id==="upgradeMixer"){let o=e.facilities?.mixer?.level||1;return`MIXER level +1. Male-chick income ${S(En(fe.income.mixer,o))} -> ${S(En(fe.income.mixer,o+1))}.`}if(t.id==="upgradeTruck"){let o=e.facilities?.truck?.level||1;return`TRUCK level +1. Correct shipment income ${S(En(fe.income.truck,o))} -> ${S(En(fe.income.truck,o+1))}.`}if(t.id==="upgradeTrash"){let o=Mt(e),r=Math.min(Gt(),o+1);return`SHREDDER level +1. Bonus chance per item ${Be(at(o))} -> ${Be(at(r))}.`}if(t.id==="bearing"){let o=Math.min(Dt,cn*Math.pow(un,Math.max(0,n.bearing||0))),r=Math.min(Dt,cn*Math.pow(un,Math.max(0,(n.bearing||0)+1)));return`Conveyor speed +7.5%. After pick: ${o.toFixed(1)} -> ${r.toFixed(1)} px/s.`}if(t.id==="legalWork"){let o=Math.max(0,n.legalWork||0);return`ZUNDA TAX exemption +${S(250)}. After pick: exemption bonus ${S(250*(o+1))}.`}if(t.id==="crowdedFarming"){let o=Math.min(10,(n.crowdedFarming||0)+1);return`Held ${n.crowdedFarming||0}/10. After pick: EGG interval ${Be(Math.max(.5,1-.05*o))}, deterioration ${Be(Math.min(1.4,1+.04*o))}.`}if(t.id==="extraEggOutlet"){let o=Ue(e,t),r=Math.max(0,Number(o[0]?.farm?.extraEggOutlet)||0);return`Choose one EGG. Output ports ${1+r} -> ${2+r}. Max 4 ports per EGG.`}if(t.id==="hatchingFeed")return`Held ${n.hatchingFeed||0}. After pick: EGG interval ${Be(Math.pow(.96,(n.hatchingFeed||0)+1))}, poop rate ${Be(Math.pow(1.03,(n.hatchingFeed||0)+1))}.`;if(t.id==="safetyCover")return`Held ${n.safetyCover||0}. After pick: explosion damage ${Be(Math.pow(.95,(n.safetyCover||0)+1))}.`;if(t.id==="recyclingSubsidy")return`Held ${n.recyclingSubsidy||0}/3. After pick: normal SELL refund ${Math.round(Math.min(.8,.5+.1*((n.recyclingSubsidy||0)+1))*100)}%.`;if(t.id==="chemicalWeaponSubsidy")return`Held ${n.chemicalWeaponSubsidy||0}. After pick: ${S(2e3*((n.chemicalWeaponSubsidy||0)+1))} per 100 truck-shipped poop each day.`;if(t.id==="preventiveMaintenance")return`Held ${n.preventiveMaintenance||0}. After pick: deterioration speed ${Be(Math.pow(.95,(n.preventiveMaintenance||0)+1))}.`;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,ke.dudChancePerCard||0)),r=Math.max(0,Math.min(1,ke.dudChanceReductionPerFilter||.05)),i=Math.max(0,n.dudFilter||0),l=Math.max(0,o-r*i),f=Math.max(0,o-r*(i+1));return`Held ${i}. DUD chance per card ${Be(l)} -> ${Be(f)}.`}if(t.id==="durabilityCoating")return`Held ${n.durabilityCoating||0}. After pick: maximum durability ${Be(Math.pow(1.03,(n.durabilityCoating||0)+1))}.`;if(t.id==="flattery")return`Next Fairies tribute -50%. Held for next tribute: ${n.fairiesFlatteryNext||0}.`;if(t.id==="usedMachine")return"Enable Used Machines: future equipment costs 50%, has no SELL refund, and starts with 60% durability.";if(t.id==="newMachine")return"Cancel Used Machines. Future equipment returns to normal price, refund, and durability.";if(t.id==="laborExploitation")return"Repairman labor cost -30% permanently. One time only.";if(t.id==="rescueLoan")return`At day-end bankruptcy check, gain ${S(500)} if cash is below ${S(0)}. Held: ${n.rescueLoanCharges||0}.`;if(t.id==="loan"){let o=Math.max(1,Math.floor(Number(e.turn)||1));return`Gain ${S(300*o)} now. Starting tomorrow, pay ${S(400)} per day for ${o} days.`}return t.description}function To(e,t){let n=e.cardDraft?.choices||[],o=n.findIndex(r=>r.id===t.id);o>=0&&n.splice(o,1)}function Mi({game:e,ui:t,onUpdatePanels:n}){function o(){n&&n()}function r(){Me(e),e.cardTargetPick=null,e.cardDraft={pending:!0,choices:Pn(e,Wt),rerolls:0,picksRemaining:1}}function i(){Me(e),e.cardDraft.pending=!1,e.cardDraft.choices=[],e.cardDraft.picksRemaining=0,e.cardTargetPick=null,t.modal.classList.remove("visible","equipment-popover"),o()}function l(g=Wt){Me(e),e.cardDraft.choices=Pn(e,g)}function f(){Me(e),!e.cardDraft.choices.length&&e.cardDraft.picksRemaining>0&&l(Wt)}function w(g){To(e,g),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1),e.cardTargetPick=null,f(),e.cardDraft.picksRemaining<=0?i():ie()}function M(g){To(e,g),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1)+ke.extraCardsAddedPicks,e.cardDraft.choices.push(...Pn(e,2)),ie()}function R(g,W){gt(e,34,.62),document.body?.animate&&document.body.animate([{transform:"translate(0, 0)"},{transform:"translate(-10px, 7px)"},{transform:"translate(12px, -8px)"},{transform:"translate(-8px, -5px)"},{transform:"translate(9px, 6px)"},{transform:"translate(0, 0)"}],{duration:260,easing:"steps(5, end)"}),W&&(W.style.setProperty("--fling-x",`${260+Math.random()*260}px`),W.style.setProperty("--fling-y",`${-260-Math.random()*170}px`),W.style.setProperty("--fling-r",`${(Math.random()<.5?-1:1)*(52+Math.random()*38)}deg`),W.classList.add("flung")),window.setTimeout(()=>{To(e,g),f(),ie()},340)}function D(g,W=null){if(g.type==="dud")return R(g,W);if(g.id==="extraCards")return M(g);if(g.type==="equipmentUpgrade"||g.type==="cellAction")return I(g);Si(e,g),w(g)}function I(g){let W=Ue(e,g);W.length&&(e.cardTargetPick={pending:!0,cardId:g.id,mode:g.target==="blockedCell"?"blockedCell":"equipment",targetKeys:W.map(Rn),remaining:g.id==="dynamite"?Math.min(3,W.length):1},t.modal.classList.remove("visible","equipment-popover"),o())}function j(g){if(!g||g.type!=="blockedCell")return!1;let W=F(g.col,g.row);if(!e.blockedCells?.has(W))return!1;e.blockedCells.delete(W);let _=P(g.col,g.row);return dt(e,_.x,_.y),Xe(e,_.x,_.y,d.danger,62),ut(e,_.x,_.y,18,d.warn),kn(e,_.x,_.y,8),gt(e,16,.35),G(e,_.x,_.y-18,"BOOM",d.danger),he(e),e.cardTargetPick.remaining=Math.max(0,(e.cardTargetPick.remaining||1)-1),e.cardTargetPick.targetKeys=Ue(e,"dynamite").map(Rn),o(),!0}function se(g){if(!e.cardTargetPick?.pending)return!1;let W=go(e.cardTargetPick.cardId),_=hl(e,g);if(!W||!_){let ae=e.cardTargetPick.mode==="blockedCell"?"SELECT BLOCKED CELL":"SELECT UPGRADE TARGET";return G(e,g.x,g.y-18,ae,d.danger),!0}return W.id==="dynamite"?(j(_)&&((e.cardTargetPick.remaining||0)<=0||!Ue(e,"dynamite").length)&&w(W),!0):(Ci(e,_),w(W),!0)}function z(){e.cardTargetPick?.pending&&(e.cardTargetPick=null,ie())}function X(){let g=mi(e);e.cashE!==Z)].slice(0,5);return _.innerHTML=`${g.title}
Choose ${_} card${_===1?"":"s"} before Build phase. Dud cards can be flicked away without consuming a pick. Equipment cards target machines; Dynamite targets blocked cells.
`;let ae=t.modalBody.querySelector("#cardChoices");g.forEach((me,E)=>ae.appendChild(ue(me,E))),t.modalActions.innerHTML="";let Z=document.createElement("button");Z.type="button",Z.className="facility-action warn reroll-button",Z.textContent=`Reroll ${S(W)}`,Z.disabled=e.cash{n.loaded=!1},(xl||e==="poop")&&t&&(n.onload=()=>{n.loaded=!0},n.src=t),We[e]=n}function Ri(e,t,n,o){e.clearRect(0,0,t.width,t.height),vl(e,t),e.save();let r=n.shake.time>0?O(-n.shake.strength,n.shake.strength):0,i=n.shake.time>0?O(-n.shake.strength,n.shake.strength):0,l=n.view?.scale||1;e.translate((n.view?.x||0)+r,(n.view?.y||0)+i),e.scale(l,l),Sl(e,n),Ml(e,n),Tl(e,n),$l(e,n),Bl(e,n),Al(e,n),Fl(e,n),kl(e,n),Ul(e,n,o.activeQueuedChick),Xl(e,n),ql(e,t,n),Hl(e,n,o.selectedObject,o.selectedTitle),Yl(e,n),zl(e,n),Vl(e,n),e.restore(),Jl(e,n,t)}function bl(e){if(e.type==="eggFarm"){let n=P(e.ref.col,e.ref.row);return{x:n.x-34,y:n.y-34,w:68,h:68,cx:n.x,cy:n.y}}let t=e.ref;return{x:t.x,y:t.y,w:t.w,h:t.h,cx:t.x+t.w/2,cy:t.y+t.h/2}}function kl(e,t){if(t.phase!=="build")return;let n=wn(t);for(let o of n){let r=bl(o);e.save(),e.fillStyle="rgba(196,36,36,.22)",e.strokeStyle=d.danger,e.lineWidth=5,e.setLineDash([10,6]),Q(e,r.x,r.y,r.w,r.h,!0,!0),e.setLineDash([]),e.fillStyle=d.danger,e.strokeStyle=d.white,e.lineWidth=4,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.strokeText("!",r.cx,r.y+24),e.fillText("!",r.cx,r.y+24),e.font="900 11px ui-monospace, monospace",e.strokeText("NO ROUTE",r.cx,r.y+r.h-8),e.fillText("NO ROUTE",r.cx,r.y+r.h-8),e.restore()}}function Q(e,t,n,o,r,i=!0,l=!0){e.beginPath(),e.rect(t,n,o,r),i&&e.fill(),l&&e.stroke()}function Ao(e,t,n,o,r=d.ink){e.save(),e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.lineWidth=4,e.strokeStyle=d.white,e.fillStyle=r,e.strokeText(o,t,n),e.fillText(o,t,n),e.restore()}function Et(e,t,n,o,r,i){return t?.loaded?(e.drawImage(t,n,o,r,i),!0):!1}function vl(e,t){e.fillStyle=d.bg,e.fillRect(0,0,t.width,t.height),e.save(),e.strokeStyle="rgba(16, 32, 21, 0.035)",e.lineWidth=1;for(let n=0;n=n;for(let r of vt(t)){let i=Ct(r);e.save(),e.fillStyle=o?"rgba(183,245,198,.34)":"rgba(255,255,255,.22)",e.strokeStyle=o?d.green:d.muted,e.lineWidth=5,e.setLineDash([16,10]),Q(e,i.x,i.y,i.w,i.h,!0,!0),e.setLineDash([]);let l=Hn(r),f=l.cx,w=l.cy;e.fillStyle="rgba(255,255,255,.94)",e.strokeStyle=d.ink,e.lineWidth=4,Q(e,l.x,l.y,l.w,l.h,!0,!0),e.fillStyle=o?d.green:d.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText(r.direction==="right"?"BUY RIGHT LOT":"BUY UPPER LOT",f,w-12),e.fillStyle=d.ink,e.font="900 16px ui-monospace, monospace",e.fillText(`${S(n)} / 10\xD710`,f,w+15),e.fillStyle=d.muted,e.font="900 11px ui-monospace, monospace",e.fillText("blocked tiles included",f,w+30),e.restore()}}function Qe(e,t,n,o,r,i,l=0){let f=Ut(i);f<.5||(e.save(),e.globalAlpha=Math.min(.62,.12+f*.54),e.fillStyle="#6b4a23",l>0?(e.beginPath(),e.roundRect?.(t,n,o,r,l),e.roundRect?e.fill():Q(e,t,n,o,r,!0,!1)):Q(e,t,n,o,r,!0,!1),e.globalAlpha=Math.min(.9,.25+f*.6),e.strokeStyle="#3a2a16",e.lineWidth=Math.max(2,Math.floor(2+f*5)),e.setLineDash([5,6]),Q(e,t+3,n+3,o-6,r-6,!1,!0),e.restore())}function Ro(e,t){let n=e.componentLookup?.get(t);return(n?e.congestion.get(n):null)?.ratio||0}function Tl(e,t){let n=[],o=new Set;for(let i of t.conveyorTiles){let{col:l,row:f}=ee(i);for(let w of wr(t,l,f)){let M=F(w.col,w.row),R=[i,M].sort().join("|");if(o.has(R))continue;o.add(R);let D=Math.max(Ro(t,i),Ro(t,M));n.push({a:P(l,f),b:P(w.col,w.row),ratio:D})}}e.save(),e.lineCap="round",e.lineJoin="round";for(let i of[{width:33,color:d.ink,alpha:1},{width:25,color:d.white,alpha:1},{width:17,color:d.greenSoft,alpha:1}]){e.globalAlpha=i.alpha,e.strokeStyle=i.color,e.lineWidth=i.width;for(let l of n)e.beginPath(),e.moveTo(l.a.x,l.a.y),e.lineTo(l.b.x,l.b.y),e.stroke()}for(let i of n){let l=Math.max(0,(i.ratio-.5)/.5);e.strokeStyle=_n(d.green,d.danger,l),e.globalAlpha=i.ratio>.5?.35+l*.55:.8,e.lineWidth=6,e.beginPath(),e.moveTo(i.a.x,i.a.y),e.lineTo(i.b.x,i.b.y),e.stroke()}let r=El(t);for(let i of t.conveyorTiles){let l=P(...Object.values(ee(i))),f=Ro(t,i);e.fillStyle=f>.5?_n(d.white,"#ffd6d6",Math.max(0,(f-.5)/.5)):d.white,e.strokeStyle=d.ink,e.lineWidth=2,Q(e,l.x-8,l.y-8,16,16,!0,!0),Qe(e,l.x-14,l.y-14,28,28,{meta:t.conveyorMeta.get(i)}),Oe(e,t,"conveyor",i,l.x,l.y,38,38),Pl(e,l,r.get(i)||[]),f>.5&&Ao(e,l.x,l.y-15,`${Math.floor(f*100)}%`,d.danger)}e.restore()}function Ti(e,t){let n=$e(t.x,t.y);if(!n)return null;let o=P(n.col,n.row);if(Math.hypot(o.x-t.x,o.y-t.y)>y.cell*.38)return null;let r=F(n.col,n.row);return e.conveyorTiles.has(r)?r:null}function gi(e,t,n){if(!(!n||n.length<2))for(let o=0;oMath.abs(Math.sin((se-I)/2))<.01)||j.push(I)}}function gl(e){if(!e)return[];let t=[];return Array.isArray(e.outDirs)&&t.push(...e.outDirs),e.dir&&t.push(e.dir),[...new Set(t)].map(n=>ge.find(o=>o.name===n)?.angle).filter(n=>Number.isFinite(n))}function El(e){let t=new Map;for(let[n,o]of e.conveyorMeta||[]){let r=gl(o);r.length&&t.set(n,r)}for(let n of e.eggFarms)gi(e,t,Ye(e,n)?.route);for(let n of e.scanners)for(let o of["left","right"])gi(e,t,Qt(e,o,le(n),n.id)?.route);return t}function Pl(e,t,n){let o=n.slice(0,3);o.length&&(e.save(),e.fillStyle=d.ink,e.globalAlpha=.86,o.forEach((r,i)=>{let l=(i-(o.length-1)/2)*4,f=Math.cos(r+Math.PI/2),w=Math.sin(r+Math.PI/2);Rl(e,t.x+f*l,t.y+w*l,r,6,5)}),e.restore())}function Rl(e,t,n,o,r=11,i=8){e.save(),e.translate(t,n),e.rotate(o),e.beginPath(),e.moveTo(r,0),e.lineTo(-r*.72,-i),e.lineTo(-r*.72,i),e.closePath(),e.fill(),e.restore()}function $l(e,t){e.save(),e.lineWidth=2,e.font="900 12px ui-monospace, monospace",e.textAlign="center";for(let n of t.scanners){let o=Zn(n),r=[{type:"inputA",p:ve(n,"inputA"),label:"IN",color:d.green},{type:"left",p:ve(n,"left"),label:eo(o.left),color:to(o.left)},{type:"right",p:ve(n,"right"),label:eo(o.right),color:to(o.right)}];for(let i of r){if(!i.p)continue;let l=P(i.p.col,i.p.row),f=mr(t,n,i.type||(i.label==="IN"?"inputA":null))||t.conveyorTiles.has(F(i.p.col,i.p.row));e.fillStyle=f?i.color:"#f4c2c2",e.strokeStyle=d.ink,Q(e,l.x-18,l.y-12,36,24,!0,!0),e.fillStyle=f&&i.color===d.white?d.ink:d.white,e.fillText(i.label,l.x,l.y+4)}}e.restore()}function Al(e,t){for(let n of t.eggFarms)Dl(e,n,t)}function Dl(e,t,n){let o=P(t.col,t.row);if(e.save(),Et(e,We.eggFarm,o.x-29,o.y-29,58,58)){Qe(e,o.x-29,o.y-29,58,58,t);let l=1+Math.max(0,Number(t.extraEggOutlet)||0);e.fillStyle="rgba(255,255,255,.92)",e.strokeStyle=d.ink,e.lineWidth=2,Q(e,o.x+9,o.y+12,30,18,!0,!0),e.fillStyle=d.ink,e.font="900 10px ui-monospace, monospace",e.textAlign="center",e.fillText(`O${l}`,o.x+24,o.y+24),Oe(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore();return}e.fillStyle=d.white,e.strokeStyle=d.ink,e.lineWidth=4,Q(e,o.x-28,o.y-28,56,56,!0,!0),e.fillStyle=d.green,e.font="900 19px ui-monospace, monospace",e.textAlign="center",e.fillText("EGG",o.x,o.y-4);let r=1+Math.max(0,Number(t.extraEggOutlet)||0);e.font="900 11px ui-monospace, monospace",e.fillStyle=d.ink,e.fillText(`L${t.level} O${r}`,o.x,o.y+13),e.fillText(`${t.nextSpawn.toFixed(1)}s`,o.x,o.y+26);let i=Math.max(0,Math.min(1,t.shutterProgress||0));if(i>0){let l=56*i;e.fillStyle=d.ink,Q(e,o.x-28,o.y-28,56,l,!0,!1),e.strokeStyle=d.white,e.lineWidth=2;for(let f=o.y-24;f=1&&(e.fillStyle=d.white,e.font="900 12px ui-monospace, monospace",e.fillText("SHUT",o.x,o.y+4))}Qe(e,o.x-28,o.y-28,56,56,t),Oe(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore()}function Fl(e,t){for(let n of t.scanners)Il(e,n,t)}function Il(e,t,n){let o=le(t);if(e.save(),t.kind==="manual"&&(n.manualCombo?.count||0)>=10){let w=n.manualCombo.count;e.save(),e.globalAlpha=Math.min(.55,.16+w/120),e.strokeStyle=w>=30?d.warn:d.green,e.lineWidth=Math.min(14,5+Math.floor(w/10)),e.shadowColor=e.strokeStyle,e.shadowBlur=Math.min(28,8+w),Q(e,o.x-60,o.y-44,120,88,!1,!0),e.restore()}let r=t.kind==="auto"?We.scannerAuto:We.scannerManual;if(Et(e,r,o.x-54,o.y-38,108,76)){t.kind==="auto"?Qe(e,o.x-54,o.y-38,108,76,t):Ei(e,t,o),Oe(e,n,"scanner",t.id,o.x,o.y,116,84),e.restore();return}e.fillStyle=t.kind==="auto"?"#d8ffe2":d.white,e.strokeStyle=d.ink,e.lineWidth=4,Q(e,o.x-52,o.y-36,104,72,!0,!0),e.fillStyle=t.kind==="auto"?d.green:d.ink,e.font="900 19px ui-monospace, monospace",e.textAlign="center",e.fillText(`${t.kind==="auto"?"AUTO":`S${(t.slot??0)+1}`}`,o.x,o.y-14),e.font="900 11px ui-monospace, monospace";let i=t.keys?.left?.label||(t.slot===0?"A":"Left"),l=t.keys?.right?.label||(t.slot===0?"D":"Right");e.fillText(t.role===0?`${i}:M ${l}:NEXT`:`${i}:WASTE ${l}:TRUCK`,o.x,o.y+3);let f=t.queue.length;t.kind==="manual"?(Ei(e,t,o),e.fillStyle=f>0?d.green:d.muted,e.font="900 10px ui-monospace, monospace",e.fillText(`Q:${f}`,o.x,o.y+32)):(e.fillStyle=f>0?d.green:d.muted,e.font="900 12px ui-monospace, monospace",e.fillText(`Q:${f} CD:${t.cooldown.toFixed(1)}`,o.x,o.y+25),Qe(e,o.x-52,o.y-36,104,72,t)),Oe(e,n,"scanner",t.id,o.x,o.y,116,84),e.restore()}function Ei(e,t,n){if(t.kind!=="manual")return;let r=(t.slot??0)===0?[{side:"left",text:"A"},{side:"right",text:"D"}]:[{side:"left",text:"\u2190"},{side:"right",text:"\u2192"}];r[0].text=t.keys?.left?.label||r[0].text,r[1].text=t.keys?.right?.label||r[1].text;let i=t.keyPressTime>0?t.keyPressSide:null,l=n.x-30,f=n.y+8;e.save(),e.lineWidth=3,e.fillStyle="#f7fff5",e.strokeStyle=d.ink,Q(e,l-4,f-4,68,25,!0,!0),e.font="900 19px ui-monospace, monospace",e.textAlign="center";for(let w=0;w.8,i=t.y+Math.sin(t.bob)*(r?5:1.5);if(e.save(),n&&(e.strokeStyle=d.green,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius+8,0,Math.PI*2),e.stroke()),r&&(e.strokeStyle=d.danger,e.lineWidth=3,e.beginPath(),e.arc(t.x,i,t.radius+12+Math.sin(t.bob*2)*4,0,Math.PI*2),e.stroke()),t.sex==="poop")Lo(e,t.x,i,t.radius);else{let l=t.sex==="male"?We.chickMale:We.chickFemale;Et(e,l,t.x-t.radius,i-t.radius,t.radius*2,t.radius*2)||(e.fillStyle=t.sex==="male"?d.male:d.female,e.strokeStyle=d.ink,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle=d.ink,e.beginPath(),e.arc(t.x-6,i-5,2.5,0,Math.PI*2),e.arc(t.x+6,i-5,2.5,0,Math.PI*2),e.fill(),e.fillStyle="#ffaa2e",e.beginPath(),e.moveTo(t.x,i+2),e.lineTo(t.x+9,i+6),e.lineTo(t.x,i+10),e.closePath(),e.fill())}e.restore()}function _l(e,t){let n=null,o=1/0;for(let[r,i]of e.componentLookup.entries()){let l=ee(r),f=P(l.col,l.row),w=Math.hypot(t.x-f.x,t.y-f.y);wPi(o.type,o.id)===Pi(t,n))}function Oe(e,t,n,o,r,i,l,f){Kl(t,n,o)&&(e.save(),e.fillStyle="rgba(34,185,79,.18)",e.strokeStyle=d.green,e.lineWidth=(t.multiSelected||[]).length>1?6:4,e.setLineDash((t.multiSelected||[]).length>1?[]:[8,5]),Q(e,r-l/2,i-f/2,l,f,!0,!0),e.restore())}function Hl(e,t,n,o){if(t.phase==="build"&&(t.multiSelected||[]).length>1){e.save(),e.fillStyle="rgba(255,255,255,.96)",e.strokeStyle=d.ink,e.lineWidth=3,Q(e,54-t.view.x,66-t.view.y,214,42,!0,!0),e.fillStyle=d.ink,e.font="900 11px ui-monospace, monospace",e.fillText(`${t.multiSelected.length} ITEMS SELECTED`,65-t.view.x,83-t.view.y),e.fillStyle=d.muted,e.font="900 11px ui-monospace, monospace",e.fillText("drag any selected item to move group",65-t.view.x,99-t.view.y),e.restore();return}}function ql(e,t,n){if(!n.cardTargetPick?.pending)return;let o=Po(n);e.save(),e.fillStyle="rgba(0,0,0,.66)",e.beginPath();let r=n.view?.scale||1;e.rect(-(n.view?.x||0)/r,-(n.view?.y||0)/r,t.width/r,t.height/r);for(let w of o){let M=w.bounds,R=8;e.rect(M.x-R,M.y-R,M.w+R*2,M.h+R*2)}e.fill("evenodd");let i=n.cardTargetPick?.mode==="blockedCell";if(!o.length){e.fillStyle="rgba(255,255,255,.95)",e.strokeStyle=d.ink,e.lineWidth=3,Q(e,(260-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,420/r,42/r,!0,!0),e.fillStyle=d.danger,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(i?"NO BLOCKED CELL. PRESS ESC.":"NO VALID UPGRADE TARGET. PRESS ESC.",(470-(n.view?.x||0))/r,(122-(n.view?.y||0))/r),e.restore();return}e.fillStyle="rgba(255,255,255,.95)",e.strokeStyle=d.ink,e.lineWidth=3;let l=Math.max(1,n.cardTargetPick?.remaining||1),f=i?`CLICK BLOCKED CELL: ${l} LEFT. PRESS ESC TO CANCEL.`:"CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.";Q(e,(216-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,560/r,42/r,!0,!0),e.fillStyle=d.ink,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(f,(496-(n.view?.x||0))/r,(122-(n.view?.y||0))/r),e.restore()}function Yl(e,t){if(t.phase!=="build"||!t.selectionBox)return;let n=t.selectionBox,o=Math.min(n.x1,n.x2),r=Math.min(n.y1,n.y2),i=Math.abs(n.x2-n.x1),l=Math.abs(n.y2-n.y1);e.save(),e.fillStyle="rgba(34,185,79,.12)",e.strokeStyle=d.green,e.lineWidth=2,e.setLineDash([7,4]),Q(e,o,r,i,l,!0,!0),e.restore()}function zl(e,t){let n=[...t.effects].sort((o,r)=>(o.priority??we.ambient)-(r.priority??we.ambient));for(let o of n){let r=Math.max(0,o.life/o.maxLife);e.save(),e.globalAlpha=r,o.type==="meat"?(e.fillStyle=d.green,Q(e,o.x-o.size/2,o.y-o.size/2,o.size*1.5,o.size,!0,!1)):o.type==="sludge"?(e.fillStyle=d.poop,Q(e,o.x-o.size/2,o.y-o.size/2,o.size*1.4,o.size,!0,!1)):o.type==="spawn"?(e.strokeStyle=d.green,e.lineWidth=3,e.beginPath(),e.arc(o.x,o.y,o.size+(1-r)*20,0,Math.PI*2),e.stroke()):o.type==="spark"?(e.fillStyle=o.color||d.danger,Q(e,o.x-o.size/2,o.y-o.size/2,o.size,o.size,!0,!1)):o.type==="smoke"?(e.fillStyle="rgba(16,32,21,.24)",e.beginPath(),e.arc(o.x,o.y,o.size*(1.2-r*.2),0,Math.PI*2),e.fill()):o.type==="shockwave"?(e.strokeStyle=o.color||d.danger,e.lineWidth=4,e.beginPath(),e.arc(o.x,o.y,o.size+(1-r)*(o.maxSize||44),0,Math.PI*2),e.stroke()):o.type==="scannerPulse"?(e.strokeStyle=o.color||d.green,e.lineWidth=5,e.setLineDash([8,6]),e.beginPath(),e.arc(o.x,o.y,o.size+(1-r)*38,0,Math.PI*2),e.stroke()):o.type==="shred"?(e.fillStyle=o.color||d.ink,e.save(),e.translate(o.x,o.y),e.rotate(o.rot||0),Q(e,-o.w/2,-o.h/2,o.w,o.h,!0,!1),e.restore()):o.type==="load"?(e.strokeStyle=o.color||d.green,e.lineWidth=3,e.beginPath(),e.moveTo(o.x-14,o.y),e.lineTo(o.x+14,o.y),e.moveTo(o.x,o.y-14),e.lineTo(o.x,o.y+14),e.stroke()):o.type==="erase"?(e.strokeStyle=d.ink,e.lineWidth=3,e.setLineDash([4,4]),Q(e,o.x-o.size/2,o.y-o.size/2,o.size,o.size,!1,!0)):o.type==="rage"?(e.fillStyle=o.color||d.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText("!",o.x,o.y)):o.type==="flyingChick"&&(o.sex==="poop"?Lo(e,o.x,o.y,o.radius||11):Bo(e,o.x,o.y,o.sex,o.sex==="male")),e.restore()}}function Vl(e,t){e.save(),e.font="900 19px ui-monospace, monospace",e.textAlign="center";for(let n of t.floatingTexts){let o=Math.max(0,n.life/n.maxLife);e.globalAlpha=o,e.lineWidth=5,e.strokeStyle=d.white,e.fillStyle=n.color,e.strokeText(n.text,n.x,n.y),e.fillText(n.text,n.x,n.y)}e.restore()}function Xl(e,t){let n=t.repairman;if(!(!!n?.active||t.phase==="build"&&!!n?.hiredForNextDay))return;e.save(),e.lineWidth=3,e.fillStyle="#fff0d1",e.strokeStyle=d.ink,e.beginPath(),e.arc(n.x,n.y,17,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle="#ffd6e7",e.beginPath(),e.arc(n.x-6,n.y-2,3.2,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(n.x+6,n.y-2,3.2,0,Math.PI*2),e.fill();let r=!!t.cardEffects?.laborExploitation;e.fillStyle=r?d.danger:d.ink,e.beginPath(),e.arc(n.x-5,n.y-5,r?2.8:2.2,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(n.x+5,n.y-5,r?2.8:2.2,0,Math.PI*2),e.fill(),e.strokeStyle=d.ink,e.lineWidth=r?3:2,e.beginPath(),e.arc(n.x,n.y+(r?0:1),r?8:7,.1*Math.PI,.9*Math.PI),e.stroke(),e.fillStyle=d.green,Q(e,n.x-9,n.y+14,18,8,!0,!0),e.strokeStyle=d.ink,e.lineWidth=3,e.beginPath(),e.moveTo(n.x-11,n.y+18),e.lineTo(n.x-20,n.y+24),e.stroke(),e.beginPath(),e.moveTo(n.x+11,n.y+18),e.lineTo(n.x+20,n.y+24),e.stroke(),e.fillStyle=d.ink,e.font="900 11px ui-monospace, monospace",e.textAlign="center",e.fillText(n.active?"FIX":"HIRED",n.x,n.y+33),n.target?.label?Ao(e,n.x,n.y-24,n.target.label,d.green):!n.active&&n.hiredForNextDay&&Ao(e,n.x,n.y-24,"NEXT DAY",d.green),e.restore()}function Jl(e,t,n){e.save(),e.font="900 19px ui-monospace, monospace",e.textAlign="left",e.fillStyle=d.ink,e.fillStyle="rgba(255,255,255,.92)",e.strokeStyle=d.ink,e.lineWidth=3,Q(e,n.width-284,18,260,34,!0,!0),e.fillStyle=d.green,e.font="900 12px ui-monospace, monospace",e.fillText(ln,n.width-270,40),e.font="900 19px ui-monospace, monospace",e.fillStyle=d.ink;let o=[];t.phase==="running"&&o.push(t.timeLeft<=0?"TIME UP: FARMS SHUT. CLEAR LINE.":"A/D: S1 \u2190/\u2192: S2"),t.phase==="build"&&o.push(`BUILD: ${t.buildTool||"SELECT"} | connect 1 EGG route to any exit`);let r=76;for(let i of o)e.strokeStyle=d.white,e.lineWidth=4,e.strokeText(i,24,r),e.fillText(i,24,r),r+=20;e.restore()}var Di=[[{key:"a",code:"KeyA",label:"A"},{key:"d",code:"KeyD",label:"D"}],[{key:"arrowleft",code:"ArrowLeft",label:"Left"},{key:"arrowright",code:"ArrowRight",label:"Right"}],[{key:"j",code:"KeyJ",label:"J"},{key:"l",code:"KeyL",label:"L"}],[{key:"f",code:"KeyF",label:"F"},{key:"h",code:"KeyH",label:"H"}],[{key:"q",code:"KeyQ",label:"Q"},{key:"e",code:"KeyE",label:"E"}],[{key:"z",code:"KeyZ",label:"Z"},{key:"x",code:"KeyX",label:"X"}],[{key:"u",code:"KeyU",label:"U"},{key:"o",code:"KeyO",label:"O"}],[{key:"n",code:"KeyN",label:"N"},{key:"m",code:"KeyM",label:"M"}]];function Ql(e){let t=Di[e]||Di[0];return{left:{...t[0]},right:{...t[1]}}}function Fi(e,t,n){let o={type:"eggFarm",id:e.nextId++,col:t,row:n,level:1,nextSpawn:2,lastInterval:2,extraEggOutlet:0,price:kt.eggFarm,builtSession:e.buildSession};return o.nextSpawn=St(o),o.lastInterval=o.nextSpawn,o}function Ii(e,t,n,o){let r=o==="auto"?pe.autoScanner.price:pe.manualScanner.price,i=e.scanners.filter(l=>l.kind==="manual").length;return{type:"scanner",id:e.nextId++,kind:o,slot:o==="manual"?i:null,role:i%2,col:t,row:n,level:1,queue:[],cooldown:0,price:r,builtSession:e.buildSession,autoMode:"standard",keys:o==="manual"?Ql(i):null}}function An(e){let t=(e.x-y.x)/y.cell,n=(e.y-y.y)/y.cell,o=Math.max(0,Math.min(y.cols-1,Math.round(t-.5))),r=Math.max(0,Math.min(y.rows-1,Math.round(n-.5))),i=Math.abs(e.x-y.x),l=Math.abs(e.x-(y.x+y.cols*y.cell)),f=Math.abs(e.y-y.y),w=Math.abs(e.y-(y.y+y.rows*y.cell)),M=[["left",i],["right",l],["top",f],["bottom",w]].sort((R,D)=>R[1]-D[1])[0][0];return M==="left"?{side:M,entry:{col:0,row:r}}:M==="right"?{side:M,entry:{col:y.cols-1,row:r}}:M==="top"?{side:M,entry:{col:o,row:0}}:{side:M,entry:{col:o,row:y.rows-1}}}function Dn(e,t,n){let o={x:y.x+t.col*y.cell+y.cell/2,y:y.y+t.row*y.cell+y.cell/2},r={left:y.x,right:y.x+y.cols*y.cell,top:y.y,bottom:y.y+y.rows*y.cell};return e.entry={...t},e.side=n,n==="left"?(e.x=r.left-e.w-18,e.y=o.y-e.h/2):n==="right"?(e.x=r.right+18,e.y=o.y-e.h/2):n==="top"?(e.x=o.x-e.w/2,e.y=r.top-e.h-18):(e.x=o.x-e.w/2,e.y=r.bottom+18),e}function Li(e,t,n,o){let{entry:r,side:i}=An(n),l=pe[t],f=l?{name:l.name,w:l.body?.w||168,h:l.body?.h||110,price:l.price}:{name:t[0].toUpperCase()+t.slice(1),w:168,h:110,price:o},w={type:"facility",id:t,name:f.name,x:0,y:0,w:f.w,h:f.h,level:1,price:o||f.price,builtSession:e.buildSession};return Dn(w,r,i)}function Zl(e){return Math.random()<$r(e)?"poop":Math.random()<.5?"male":"female"}function Bi(e,t){let n=Zl(e),o=(t.route||[]).map(i=>({x:i.x,y:i.y})),r=o[0];return{id:e.nextId++,sex:n,x:r.x,y:r.y,route:o,targetIndex:o.length>1?1:o.length,stage:t.stage||"belt",scannerId:t.scannerId??null,nextScannerId:null,pendingScannerId:null,radius:n==="poop"?15:17,bob:Math.random()*Math.PI*2,queueIndex:-1,queueRoute:null}}function Oi({game:e,canvasPoint:t,updatePanels:n,equipmentAtPoint:o,fail:r,pointInGrid:i,rectOfFacility:l,rectsOverlap:f}){function w(x){return x?x.type==="conveyor"?`conveyor:${x.id||x.oldKey}`:x.type==="facility"?`facility:${x.id||x.ref?.id}`:`${x.type}:${x.id||x.ref?.id}`:""}function M(x){return x?x.type==="conveyor"?{type:"conveyor",id:x.oldKey}:{type:x.type,id:x.ref.id}:null}function R(x){let m=w(M(x));return(e.multiSelected||[]).some(U=>w(U)===m)}function D(x){return x?x.type==="eggFarm"?e.eggFarms.find(m=>m.id===x.id)||null:x.type==="scanner"?e.scanners.find(m=>m.id===x.id)||null:x.type==="facility"?e.facilities[x.id]||null:x.type==="conveyor"&&e.conveyorTiles.has(x.id)?{type:"conveyor",id:x.id}:null:null}function I(){let x=[];for(let m of e.conveyorTiles){let U=ee(m),K=P(U.col,U.row);x.push({type:"conveyor",id:m,center:K,cell:U})}for(let m of e.eggFarms)x.push({type:"eggFarm",id:m.id,ref:m,center:P(m.col,m.row),cell:{col:m.col,row:m.row}});for(let m of e.scanners)x.push({type:"scanner",id:m.id,ref:m,center:le(m),cell:{col:m.col,row:m.row}});for(let m of Object.values(e.facilities)){let U={x:m.x+m.w/2,y:m.y+m.h/2},K=m.entry?P(m.entry.col,m.entry.row):U;x.push({type:"facility",id:m.id,ref:m,center:U,portCenter:K})}return x}function j(x,m){let U=Math.min(m.x1,m.x2),K=Math.max(m.x1,m.x2),J=Math.min(m.y1,m.y2),oe=Math.max(m.y1,m.y2);return x.x>=U&&x.x<=K&&x.y>=J&&x.y<=oe}function se(x){let m=[];for(let U of I())(j(U.center,x)||U.portCenter&&j(U.portCenter,x))&&m.push({type:U.type,id:U.id});return e.multiSelected=m,e.selected=m[0]||null,n(),m.length}function z(){e.multiSelected=[],e.selected=null,n()}function X(x){let m=t(x);return e.selectionBox={x1:m.x,y1:m.y,x2:m.x,y2:m.y},e.multiSelected=[],e.selected=null,n(),!0}function ue(x){if(!e.selectionBox)return;let m=t(x);e.selectionBox.x2=m.x,e.selectionBox.y2=m.y}function ie(){if(!e.selectionBox)return 0;let x=e.selectionBox,m=Math.abs(x.x2-x.x1),U=Math.abs(x.y2-x.y1);return e.selectionBox=null,m<6&&U<6?(z(),0):se(x)}function g(x){let m=M(x);return m?(e.multiSelected||[]).length&&R(x)?[...e.multiSelected]:[m]:[]}function W(x){let m=D(x);if(!m)return null;if(x.type==="conveyor"){let U=ee(x.id);return{...x,obj:m,oldKey:x.id,currentKey:x.id,meta:e.conveyorMeta.get(x.id)||{price:Re("conveyor"),builtSession:null},col:U.col,row:U.row}}return x.type==="eggFarm"||x.type==="scanner"?{...x,obj:m,col:m.col,row:m.row}:x.type==="facility"?{...x,obj:m,x:m.x,y:m.y,w:m.w,h:m.h,entry:m.entry?{...m.entry}:null,side:m.side,center:{x:m.x+m.w/2,y:m.y+m.h/2}}:null}function _(x){let m=t(x),U=o(m);if(!U)return!1;let K=g(U),J=K.map(W).filter(Boolean);return J.length?(e.groupDrag={start:m,selections:K,origins:J,historySnapshot:tn(e),committed:!1,lastDCol:0,lastDRow:0},e.multiSelected=K,e.selected=K[0]||null,n(),!0):!1}function ae(){!e.groupDrag||e.groupDrag.committed||(e.undoStack.push(e.groupDrag.historySnapshot),e.redoStack=[],e.groupDrag.committed=!0)}function Z(x,m,U){let K=F(x,m),J=Ot(e,x,m);if(J&&!U.has(`eggFarm:${J.id}`))return!0;let oe=Nt(e,x,m);return!!(oe&&!U.has(`scanner:${oe.id}`)||e.conveyorTiles.has(K)&&!U.has(`conveyor:${K}`))}function me(x,m,U){let K=[];for(let J of e.groupDrag.origins){if(J.type!=="facility")continue;let oe={x:J.center.x+x,y:J.center.y+m},{entry:ye,side:Ne}=An(oe);if(!i(ye.col,ye.row)||e.blockedCells?.has?.(F(ye.col,ye.row)))return!0;let _e={...J.obj,entry:{...ye},side:Ne};Dn(_e,ye,Ne),K.push({id:J.id,rect:l(_e)})}for(let J of K)for(let oe of Object.values(e.facilities))if(!U.has(`facility:${oe.id}`)&&f(J.rect,l(oe),12))return!0;for(let J=0;JV.type==="conveyor");for(let V of _e){let xe=V.currentKey||V.oldKey;e.conveyorTiles.delete(xe),e.conveyorMeta.delete(xe)}for(let V of _e){let xe=F(V.col+J,V.row+oe);e.conveyorTiles.add(xe),e.conveyorMeta.set(xe,V.meta||{price:Re("conveyor"),builtSession:null,uses:0}),V.currentKey=xe}for(let V of e.groupDrag.origins)if(V.type==="eggFarm")V.obj.col=V.col+J,V.obj.row=V.row+oe;else if(V.type==="scanner")V.obj.col=V.col+J,V.obj.row=V.row+oe;else if(V.type==="facility"){let xe={x:V.center.x+U,y:V.center.y+K},{entry:De,side:je}=An(xe);Dn(V.obj,De,je)}e.groupDrag.selections=e.groupDrag.origins.map(V=>V.type==="conveyor"?{type:"conveyor",id:V.currentKey||V.oldKey}:{type:V.type,id:V.id}),e.multiSelected=[...e.groupDrag.selections],e.selected=e.multiSelected[0]||null,he(e),n()}function A(){e.groupDrag&&(he(e),e.groupDrag=null,n())}return{selectionFromHit:M,startSelectionBox:X,updateSelectionBox:ue,finishSelectionBox:ie,startGroupDrag:_,updateGroupDrag:E,finishGroupDrag:A}}function Ni({game:e,ui:t,canvas:n,canvasPoint:o,onUpdatePanels:r}){function i(){r&&r()}let l=null,f=!1;function w(){return pn(e)}function M(){e.gridCols=y.cols,e.gridRows=y.rows,e.gridOwnedCells=or(e)}function R(s){if(s){y.y-=s*y.cell,y.rows+=s,e.gridChunkOriginY=(e.gridChunkOriginY||0)-Math.floor(s/10),e.ownedCells=yn(e.ownedCells,s),e.blockedCells=yn(e.blockedCells,s),e.conveyorTiles=yn(e.conveyorTiles,s),e.conveyorMeta=lr(e.conveyorMeta,s);for(let u of e.eggFarms||[])u.row+=s;for(let u of e.scanners||[])u.row+=s;for(let u of Object.values(e.facilities||{}))u.entry&&(u.entry.row+=s)}}function D(s){e.ownedCells=e.ownedCells||new Set;for(let u of sr(s))e.ownedCells.add(F(u.col,u.row))}function I(s){return e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending?null:vt(e).find(u=>u&&ir(u,s))||null}function j(s="right"){if(s&&typeof s=="object"&&Number.isFinite(s.chunkX)&&Number.isFinite(s.chunkY))return s;let u=["right","up"].includes(s)?s:"right";return rr(e,u)}function se(s="right"){let u=j(s);if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return{ok:!1,reason:"Cannot expand now."};if(!u)return{ok:!1,reason:"Invalid expansion lot."};let b=u.direction||"right",k=w();if(e.cashy.cols&&(y.cols=B.colStart+B.cols),B.rowStart+B.rows>y.rows&&(y.rows=B.rowStart+B.rows),D(B),ar(e,B.chunkX,B.chunkY),e.gridExpansionPurchases=(e.gridExpansionPurchases||0)+1,e.gridExpansionPurchasesByDirection[b]=(e.gridExpansionPurchasesByDirection[b]||0)+1,M();let ce=Zo({seed:`${e.runSeed}:grid-expansion:${B.chunkX},${B.chunkY}:${e.gridExpansionPurchases}`,colStart:B.colStart,colEnd:B.colStart+B.cols,rowStart:B.rowStart,rowEnd:B.rowStart+B.rows,targetRatio:H.map.blockedRatio});for(let $t of ce)e.blockedCells.add($t);he(e);let Ke=B.cols*B.rows,He=Ct(B);return G(e,He.x+He.w/2,He.y+He.h/2,`${b.toUpperCase()} +${Ke} CELLS -${S(k)}`,d.green),i(),{ok:!0,direction:b,cost:k,addedCells:Ke,blocked:ce.size,chunkX:B.chunkX,chunkY:B.chunkY}}function z(s,u){return s>=0&&s=0&&u!u.has(k.id)&&ie(b,ue(k),12))}function W(s,u,b=null){if(!z(s,u))return!1;if(X(s,u))return!0;let k=F(s,u),$=Ot(e,s,u);if($&&!(b?.type==="eggFarm"&&b.ref?.id===$.id))return!0;let B=Nt(e,s,u);return!!(B&&!(b?.type==="scanner"&&b.ref?.id===B.id)||e.conveyorTiles.has(k)&&!(b?.type==="conveyor"&&b.oldKey===k))}function _(){return e.selected?e.selected.type==="eggFarm"?e.eggFarms.find(s=>s.id===e.selected.id)||null:e.selected.type==="scanner"?e.scanners.find(s=>s.id===e.selected.id)||null:e.selected.type==="conveyor"?e.conveyorTiles.has(e.selected.id)?{type:"conveyor",id:e.selected.id}:null:e.selected.type==="facility"&&e.facilities[e.selected.id]||null:null}function ae(s){return s?s.type==="eggFarm"?`${Ft("eggFarm")} #${s.id}`:s.type==="scanner"?`${s.kind==="auto"?Ft("autoScanner"):Ft("manualScanner")} #${s.id}`:s.type==="conveyor"?Ft("conveyor"):s.type==="facility"?s.name:"Equipment":"Equipment"}function Z(s){return io(s)}function me(){return!!e.cardEffects?.usedMachineActive}function E(){return me()?{usedMachine:!0,noRefund:!0,durabilityBaseMultiplier:.6}:{usedMachine:!1,noRefund:!1,durabilityBaseMultiplier:1}}function A(s){let u=E();return Object.assign(s,u),s}function x(s){let u=s?.ref||s||{};return s?.type==="eggFarm"||u.type==="eggFarm"?e.eggFarms.length<=1?"Cannot sell the last EGG FARM.":"":(s?.type==="facility"||u.type==="facility")&&["mixer","trash","truck"].includes(u.id)&&Object.values(e.facilities).filter(k=>k.id===u.id).length<=1?`Cannot sell the last ${u.shortName||u.name||u.id}.`:""}function m(s){t.buildStatus.textContent=s,G(e,n.width/2-e.view.x,86-e.view.y,s.toUpperCase(),d.danger)}function U(s){if(!s)return null;let u=F(s.col,s.row);return e.conveyorMeta.get(u)||null}function K(s){return s?(Array.isArray(s.outDirs)||(s.outDirs=[]),s.outDirs=[...new Set(s.outDirs.filter(u=>["right","left","down","up"].includes(u)))],s.outDirs):[]}function J(s,u){let b=Xt(s,u);if(!b)return!1;let k=F(s.col,s.row),$=F(u.col,u.row),B=e.conveyorMeta.get(k),ce=e.conveyorMeta.get($);if(!B||!ce)return!1;let Ke=K(B),He=!Ke.includes(b)||B.dir!==b||!ce.dir;return Ke.includes(b)||Ke.push(b),B.dir=b,ce.dir||(ce.dir=b),He}function oe(s,u=null){if(!s)return{ok:!1,reason:te.fail.outOfGrid};let{col:b,row:k}=s,$=F(b,k);if(e.conveyorTiles.has($))return{ok:!1,exists:!0};if(X(b,k))return{ok:!1,reason:"Cannot build on blocked ground."};if(Ot(e,b,k)||Nt(e,b,k))return{ok:!1,reason:te.fail.cellOccupied};let B=Re("conveyor",e);if(e.cash=Math.abs(k)?{col:s.col+Math.sign(b),row:s.row}:{col:s.col,row:s.row+Math.sign(k)}}function _e(s){f=!1,l=null,ye(s)}function V(s){if(!s)return;if(!l)return ye(s);let u=l,b=0;for(;(u.col!==s.col||u.row!==s.row)&&b<64;){let k=Ne(u,s);if(ye(k),u=l||k,b+=1,!l)break}}function xe(){l=null,f=!1}function De(s){if(!s)return m(te.fail.outOfGrid);let{col:u,row:b}=s;if(e.buildTool==="conveyor"){let k=oe(s,null);if(!k.ok)return m(k.reason||te.fail.cellOccupied);he(e);return}if(X(u,b))return m("Cannot build on blocked ground.");if(W(u,b))return m(te.fail.cellOccupied);e.buildTool==="eggFarm"?rn(u,b):e.buildTool==="manualScanner"?ht(u,b,"manual"):e.buildTool==="autoScanner"&&ht(u,b,"auto")}function je(s){let u=$e(s.x,s.y);if(["conveyor","eggFarm","manualScanner","autoScanner"].includes(e.buildTool))return De(u);if(ot.includes(e.buildTool))return On(s,e.buildTool)}function rn(s,u){let b=Re("eggFarm",e);if(e.cashB.kind==="manual").length>=8)return m("Manual Scanner limit reached (8 max).");let k=b==="auto"?Re("autoScanner",e):Re("manualScanner",e);if(e.cash$.id!==u.ref.id),dt(e,k.x,k.y),he(e)}if(u.type==="scanner"){let k=le(u.ref);Pt(u,k.x,k.y),e.scanners=e.scanners.filter($=>$.id!==u.ref.id),dt(e,k.x,k.y),he(e)}if(u.type==="facility"){let k=u.ref;Pt(u,k.x+k.w/2,k.y+k.h/2),delete e.facilities[k.id],dt(e,k.x+k.w/2,k.y+k.h/2),he(e)}e.selected=null,e.multiSelected=[],i()}function et(s){let u=Object.values(e.facilities).find(ce=>{if(s.x>=ce.x&&s.x<=ce.x+ce.w&&s.y>=ce.y&&s.y<=ce.y+ce.h)return!0;if(!ce.entry)return!1;let He=P(ce.entry.col,ce.entry.row);return Math.abs(s.x-He.x)<=y.cell*.46&&Math.abs(s.y-He.y)<=y.cell*.46});if(u)return{type:"facility",ref:u};let b=$e(s.x,s.y);if(!b)return null;let k=Ot(e,b.col,b.row);if(k)return{type:"eggFarm",ref:k};let $=Nt(e,b.col,b.row);if($)return{type:"scanner",ref:$};let B=F(b.col,b.row);return e.conveyorTiles.has(B)?{type:"conveyor",oldKey:B,ref:{type:"conveyor",id:B}}:null}let tt=Oi({game:e,canvasPoint:o,updatePanels:i,equipmentAtPoint:et,fail:m,pointInGrid:z,rectOfFacility:ue,rectsOverlap:ie});function sn(s){return null}function Rt(){let s=_();s&&(s.type==="conveyor"?mt(P(...Object.values(ee(s.id)))):s.type==="eggFarm"?mt(P(s.col,s.row)):s.type==="scanner"?mt(le(s)):s.type==="facility"&&mt({x:s.x+s.w/2,y:s.y+s.h/2}))}function Fe(s,u,b="primary-button"){let k=document.createElement("button");return k.type="button",k.className=b,k.textContent=s,k.addEventListener("click",u),k}function xt(){t.modal.classList.remove("visible","equipment-popover"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function Yt(s){t.modalTitle.textContent="Auto Scanner",t.modalBody.innerHTML=`
Standard auto scanner.
Role 0: male left, others right.
Role 1: poop left, others right.
Cooldown: ${Je(s).toFixed(1)}s.
`,t.modalActions.innerHTML="";let u=Fe("Set Role 0",()=>{Le(e),s.role=0,xt(),i()}),b=Fe("Set Role 1",()=>{Le(e),s.role=1,xt(),i()});t.modalActions.append(u,b),Te(s),t.modal.classList.add("visible","equipment-popover")}function c(s){return s?.label||s?.key||"?"}function p(s){let u=s.key===" "?"Space":s.key.length===1?s.key.toUpperCase():s.key.replace(/^Arrow/,"");return{key:s.key.toLowerCase(),code:s.code,label:u}}function h(s,u,b){for(let k of e.scanners.filter($=>$.kind==="manual"))for(let $ of["left","right"]){if(k.id===s.id&&$===u)continue;let B=k.keys?.[$];if(B&&(B.code===b.code||B.key===b.key))return!0}return!1}function v(s,u=""){if(!s||s.kind!=="manual")return;t.modalTitle.textContent=`Manual Scanner #${s.id}`;let b=c(s.keys?.left),k=c(s.keys?.right),$=C(s);t.modalBody.innerHTML=`
+
+
Left route key: ${b}
+
Right route key: ${k}
+
Role: ${s.role===0?"Male left / others right":"Poop left / others right"}
+ ${u?`
${u}
`:""}
+ ${$?`
${$}
`:""}
+
`,t.modalActions.innerHTML="",t.modalActions.appendChild(Fe("Set Left Key",()=>T(s,"left"),"facility-action warn")),t.modalActions.appendChild(Fe("Set Right Key",()=>T(s,"right"),"facility-action warn")),t.modalActions.appendChild(Fe("Close",xt,"facility-action")),Te(s),t.modal.classList.add("visible","equipment-popover")}function C(s){let u=[{side:"left",binding:s.keys?.left},{side:"right",binding:s.keys?.right}];if(u[0].binding&&u[1].binding&&(u[0].binding.code===u[1].binding.code||u[0].binding.key===u[1].binding.key))return"Left and right keys conflict.";for(let b of u)if(b.binding)for(let k of e.scanners.filter($=>$.kind==="manual"&&$.id!==s.id)){if(k.keys?.left&&(k.keys.left.code===b.binding.code||k.keys.left.key===b.binding.key))return`Key conflicts with Manual Scanner #${k.id} left.`;if(k.keys?.right&&(k.keys.right.code===b.binding.code||k.keys.right.key===b.binding.key))return`Key conflicts with Manual Scanner #${k.id} right.`}return""}function T(s,u){t.modalBody.innerHTML=`
Press a key for ${u.toUpperCase()} route.
Esc cancels.
`,t.modalActions.innerHTML="";let b=k=>{if(k.preventDefault(),k.stopPropagation(),window.removeEventListener("keydown",b,!0),k.key==="Escape")return v(s);let $=p(k),B=h(s,u,$);Le(e),s.keys=s.keys||{left:null,right:null},s.keys[u]=$,i(),v(s,B?`${$.label} assigned, but another scanner already uses it.`:`${u.toUpperCase()} set to ${$.label}.`)};window.addEventListener("keydown",b,!0)}function L(){let s=_();if(!(!s||s.type!=="scanner"))return s.kind==="auto"?Yt(s):v(s)}function ne(s){if(!s)return{x:80,y:80};if(s.type==="conveyor"){let u=ee(s.id);return P(u.col,u.row)}return s.type==="eggFarm"?P(s.col,s.row):s.type==="scanner"?le(s):s.type==="facility"?{x:s.x+s.w/2,y:s.y+10}:{x:80,y:80}}function Te(s){let u=n.getBoundingClientRect(),b=ne(s),k=e.view?.scale||1,$=u.left+(b.x*k+(e.view?.x||0))/n.width*u.width+18,B=u.top+(b.y*k+(e.view?.y||0))/n.height*u.height-12,ce=Math.max(12,window.innerWidth-274),Ke=Math.max(12,window.innerHeight-220);t.modal.style.setProperty("--popover-x",`${Math.max(12,Math.min(ce,$))}px`),t.modal.style.setProperty("--popover-y",`${Math.max(12,Math.min(Ke,B))}px`)}function wt(){let s=_();if(!s)return;let u=No(s);t.modalTitle.textContent=ae(s),t.modalBody.innerHTML=`
+
${u.map($=>`
${$}
`).join("")}
+ ${["mixer","truck"].includes(s.id)?'
Income/Fine = ceil(base \xD7 1.05^upgrades)
':""}`,t.modalActions.innerHTML="",s.type==="scanner"&&s.kind==="auto"&&t.modalActions.appendChild(Fe("Auto Menu",()=>Yt(s),"facility-action warn")),s.type==="scanner"&&s.kind==="manual"&&t.modalActions.appendChild(Fe("Set Keys",()=>v(s),"facility-action warn"));let b=s.type==="conveyor"?{type:"conveyor",oldKey:s.id,ref:s}:{type:s.type,ref:s},k=x(b);if(k){let $=Fe(k,()=>{},"facility-action danger disabled");$.disabled=!0,t.modalActions.appendChild($)}else{let $=Tt(b,e),B=$.sameBuild?`Remove / Refund ${S($.amount)}`:`Sell ${S($.amount)}`;t.modalActions.appendChild(Fe(B,()=>{Rt(),xt()},"facility-action danger"))}Te(s),t.modal.classList.add("visible","equipment-popover")}function ts(s){e.phase==="build"&&(xe(),e.buildTool=e.buildTool===s?null:s,e.selected=null,e.multiSelected=[],e.selectionBox=null,i())}function ns(){let s=[];for(let[u,b]of Object.entries(e.facilities))if(s.push({id:`facility:${u}`,price:Z({type:"facility",ref:b}),x:b.x,y:b.y,w:b.w,h:b.h}),b.entry){let k=P(b.entry.col,b.entry.row);s.push({id:`facilityPort:${u}`,price:Z({type:"facility",ref:b}),x:k.x-18,y:k.y-18,w:36,h:36})}for(let u of e.eggFarms){let b=P(u.col,u.row);s.push({id:`eggFarm:${u.id}`,price:Z({type:"eggFarm",ref:u}),x:b.x-24,y:b.y-24,w:48,h:48})}for(let u of e.scanners){let b=le(u);s.push({id:`scanner:${u.id}`,price:Z({type:"scanner",ref:u}),x:b.x-52,y:b.y-36,w:104,h:72})}for(let u of e.conveyorTiles){let b=ee(u),k=P(b.col,b.row);s.push({id:`conveyor:${u}`,price:Re("conveyor",e),x:k.x-22,y:k.y-22,w:44,h:44})}return s}function No(s){de(e);let u=[];if(s.type==="eggFarm"){let[b,k]=Jt(s);u.push(`Price: ${S(Z(s))}`);{let $=x({type:s.type,ref:s});u.push($?`Sale: blocked (${$})`:`Sale value: ${S(Tt({type:s.type,ref:s},e).amount)}`)}u.push(`Level: ${s.level}/4`),u.push(`Random interval: ${b.toFixed(2)}-${k.toFixed(2)}s`),u.push(`Durability: ${nn(s)}% | Spawn delay x${gn(s).toFixed(2)}`)}else if(s.type==="scanner")u.push(`Price: ${S(Z(s))}`),u.push(`Sale value: ${S(Tt({type:s.type,ref:s},e).amount)}`),u.push(`Type: ${s.kind.toUpperCase()} / Standard`),u.push(`Role: ${s.role===0?"Male left / Others right":"Poop left / Others right"}`),u.push(`Queue: ${s.queue.length}`),s.kind==="auto"&&u.push(`Cooldown: ${s.cooldown.toFixed(1)}s / ${Je(s,e).toFixed(1)}s`),s.kind==="auto"&&u.push(`Durability: ${nn(s)}% | Delay x${Tn(s).toFixed(2)}`),s.kind==="manual"&&u.push("Durability: none | Always normal");else if(s.type==="conveyor"){let b=e.conveyorMeta.get(s.id),k=e.componentLookup?.get(s.id),$=k?e.congestion.get(k):null;u.push(`Price: ${S(Z({type:"conveyor",oldKey:s.id,ref:s}))}`),u.push(`Cell: ${s.id}`),u.push(`Congestion: ${$?Math.floor($.ratio*100):0}%`),u.push(`Durability: ${nn({meta:b})}% | Speed x${Mn({meta:b}).toFixed(2)}`),u.push("Flow follows drawn directions. Branches choose randomly; full branches are avoided when possible."),u.push(`Sale value: ${S(Tt({type:"conveyor",oldKey:s.id,ref:s},e).amount)}`)}else if(s.type==="facility"){u.push(`Price: ${S(Z(s))}`);{let b=x({type:s.type,ref:s});u.push(b?`Sale: blocked (${b})`:`Sale value: ${S(Tt({type:s.type,ref:s},e).amount)}`)}if(u.push(["mixer","truck","trash"].includes(s.id)?`Level: ${s.level} / no cap`:`Level: ${s.level}`),s.id==="truck"&&u.push("Durability: none | Always normal"),["mixer","trash"].includes(s.id)&&u.push(`Durability: ${nn(s)}% | Extra delay ${ko(e,s.id).toFixed(2)}s`),s.id==="mixer"&&(u.push(`Income: ${S(lt(e))} per chick | upgrade x${st(e,"mixer").toFixed(3)}`),u.push(`Poop fine: -${S(jt(e))}`)),s.id==="truck"&&(u.push(`Income: ${S(Ie(e))} per target cargo | upgrade x${st(e,"truck").toFixed(3)}`),u.push(`Poop shipment fine: -${S(en(e))}`)),s.id==="trash"){let b=Mt(e),k=at(b);u.push(`Bonus cards: ${b}/${Gt()}`),u.push(`Bonus chance: ${(k*100).toFixed(2)}% for ${S(1)} per processed item.`),u.push(`Expected value: ${k.toFixed(3)} JPY per item.`)}s.entry&&u.push(`Receiver: edge cell ${s.entry.col},${s.entry.row} (${s.side})`)}return u}function os(s){if(!s||e.phase!=="build")return"";let u=wn(e).find(b=>b.type===s.type&&b.id===s.id);return u?u.message||"Not connected to conveyor route":""}function rs(s){return s?s.type==="conveyor"?"A stubborn belt tile. It only cares about the next cell.":s.type==="eggFarm"?"A tiny gatehouse producing questionable eggs on schedule.":s.type==="scanner"&&s.kind==="auto"?"An automated judge. Faster than hands, still very sure of itself.":s.type==="scanner"?"A manual checkpoint. The operator is the algorithm.":s.type==="facility"&&s.id==="mixer"?"Male chicks become revenue here. Do not feed it poop.":s.type==="facility"&&s.id==="trash"?"Poop goes in. Sometimes coins come out, for reasons best left unaudited.":s.type==="facility"&&s.id==="truck"?"The shipping endpoint. Correct cargo pays; wrong cargo complains.":"Factory equipment.":""}return{buildAtCell:De,buildAtPoint:je,eraseAtPoint:mt,equipmentAtPoint:et,startSelectionBox:tt.startSelectionBox,updateSelectionBox:tt.updateSelectionBox,finishSelectionBox:tt.finishSelectionBox,startGroupDrag:tt.startGroupDrag,updateGroupDrag:tt.updateGroupDrag,finishGroupDrag:tt.finishGroupDrag,selectedObject:_,selectedTitle:ae,equipmentPrice:Z,selectedUpgradeCost:sn,selectedInfoLines:No,flavorText:rs,disconnectedWarningFor:os,gridExpansionCost:w,buyGridExpansion:se,expansionOfferAtPoint:I,beginConveyorDrag:_e,continueConveyorDrag:V,endConveyorDrag:xe,removeSelected:Rt,switchScannerRole:L,showManualScannerMenu:v,showAutoScannerMenu:Yt,showSelectedMenu:wt,setBuildTool:ts,fail:m,isEquipmentCell:W,equipmentHitBoxes:ns,routeFromFarmToScanner:Ye}}function Gi({game:e,ui:t,build:n,startGame:o,beginCardDraft:r,activeQueuedChick:i}){function l(E){return String(E).replace(/[&<>"']/g,A=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[A])}function f(){return Math.round($n(e))}function w(){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return!1;let E=!1;for(let A of Un)if(!(ot.includes(A)&&e.facilities[A])&&(E=!0,e.cash>=Re(A,e)))return!1;return n?.gridExpansionCost&&e.cash>=n.gridExpansionCost()?!1:E}function M(){R(),D(),se(),j(),I()}function R(){for(let[A,x]of Object.entries(t.buttons))x?.classList?.contains("tool-button")&&x.classList.toggle("active",e.buildTool===A);for(let A of Un){let x=t.buttons[A];if(!x)continue;let m=Re(A,e),U=x.querySelector("span");U&&(U.textContent=A==="conveyor"?`${S(m)} / tile`:S(m));let K=ot.includes(A)&&!!e.facilities[A],J=A==="manualScanner"&&e.scanners.filter(ye=>ye.kind==="manual").length>=8,oe=e.cashYe(e,ye)?.scannerId).length,A=Zt(e),x=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),m=bn(x,e),U=e.phase==="running"?Math.max(1,(e.totals.turnsCompleted||0)+1):Math.max(1,Number(e.turn)||1),K=lo(e,U),J=e.lastBuildFees?.turn===U?e.lastBuildFees.fairiesTribute||0:null,oe=e.lastBuildFees?.turn===U&&e.lastBuildFees.reduction||0;t.turnSummary.innerHTML=[`Seed: ${l(e.runSeed||"none")} | Grid box: ${e.gridRows||10}\xD7${e.gridCols||20} | Owned: ${e.gridOwnedCells||e.ownedCells?.size||(e.gridRows||10)*(e.gridCols||20)} cells | Blocked: ${e.blockedCells?.size||0} cells`,`Truck target: ${ze(e).toUpperCase()} | Male fine: -${S(so(e))}`,`Poop fine: Mixer -${S(jt(e))} / Shipment -${S(en(e))}`,`ZUNDA TAX on Next Day: -${S(m.tax)} | basis net ${S(x)} | taxable ${S(m.taxable)} \xD7 ${m.ratePercent}% | exemption ${S(m.exemption)} | 95% at ${S(m.maxRateCash)}`,J!=null?`Fairies tribute paid before Build: -${S(J)}${oe?` | Flattery -${S(oe)}`:""}`:`Fairies tribute before Build: -${S(K.amount)}${K.reduction?` | Flattery -${S(K.reduction)}`:""}`,`Maintenance: worst ${Mo(e).worst.percent}% dirty (${Mo(e).worst.label}) | Repairman: ${e.repairman?.hiredForNextDay?"hired next day":e.repairman?.active?"working":"none"}`,`Manual combo: ${e.manualCombo?.count||0} | Next expansion: ${S(n?.gridExpansionCost?n.gridExpansionCost():0)} | Card draft: ${e.cardDraft?.pending?Math.max(1,e.cardDraft.picksRemaining||1)+" pick(s) left":"ready after each day"} | Belt: ${f()}px/s | Farms with scanner route: ${E}/${e.eggFarms.length}`,e.cardEffects?.usedMachineActive?'Procurement: USED MACHINE MODE / no refunds / 60% durability':"",A.length?`Blocked: ${A[0]}`:`${te.status.allPortsConnected}`].join(" ")}function se(){if(!t.contractPanel)return;let E=e.contractOffer;if(e.phase!=="build"){t.contractPanel.innerHTML=te.status.eventPanelRunning;return}if(!E){t.contractPanel.className="contract-card empty",e.turn+1Event lock active.No irregular events during Days 1-7. First possible forced event: Day ${bt}.`:t.contractPanel.innerHTML="No event.Random forced events can appear later.";return}t.contractPanel.className="contract-card accepted",t.contractPanel.innerHTML=`
+