From 368de90c6c2c07693249b17465af389aa9316173 Mon Sep 17 00:00:00 2001 From: 33333-33333 Date: Thu, 11 Jun 2026 14:34:37 +0900 Subject: [PATCH] visual --- BALANCE_PATCH_NOTES.md | 36 + PATCH_VERIFICATION.md | 20 + README.md | 55 +- assets/README_ASSETS_DARK_FACTORY.md | 19 + assets/_legacy/images/README.md | 3 + assets/_legacy/images/poop.png | Bin 0 -> 1211 bytes assets/chicks/README.md | 1 + assets/dark_factory/facilities/README.md | 1 + .../conveyor/boost_conveyor_straight_h_16.png | Bin 0 -> 423 bytes .../conveyor/boost_conveyor_straight_v_16.png | Bin 0 -> 473 bytes .../conveyor/boost_conveyor_turn_ne_16.png | Bin 0 -> 575 bytes .../conveyor/boost_conveyor_turn_nw_16.png | Bin 0 -> 563 bytes .../conveyor/boost_conveyor_turn_se_16.png | Bin 0 -> 548 bytes .../conveyor/boost_conveyor_turn_sw_16.png | Bin 0 -> 534 bytes .../conveyor/conveyor_straight_h_16.png | Bin 0 -> 426 bytes .../conveyor/conveyor_straight_v_16.png | Bin 0 -> 480 bytes .../conveyor/conveyor_turn_ne_16.png | Bin 0 -> 581 bytes .../conveyor/conveyor_turn_nw_16.png | Bin 0 -> 565 bytes .../conveyor/conveyor_turn_se_16.png | Bin 0 -> 558 bytes .../conveyor/conveyor_turn_sw_16.png | Bin 0 -> 539 bytes .../machines/auto_scanner_32x48.png | Bin 0 -> 850 bytes .../facilities/machines/egg_farm_16.png | Bin 0 -> 314 bytes .../machines/manual_scanner_32x48.png | Bin 0 -> 714 bytes .../facilities/machines/mixer_32.png | Bin 0 -> 557 bytes .../facilities/machines/mixer_compact_16.png | Bin 0 -> 475 bytes .../facilities/machines/shredder_32.png | Bin 0 -> 410 bytes .../machines/shredder_compact_16.png | Bin 0 -> 326 bytes .../utility/maintenance_room_32.png | Bin 0 -> 843 bytes .../facilities/utility/obstacle_crate_16.png | Bin 0 -> 387 bytes .../facilities/utility/repairman_16.png | Bin 0 -> 222 bytes .../facilities/vehicles/truck_32.png | Bin 0 -> 496 bytes .../facilities/vehicles/truck_compact_16.png | Bin 0 -> 401 bytes assets/dark_factory/manifest.json | 103 ++ assets/dark_factory/previews/README.md | 1 + .../facilities_overview_dark_factory.png | Bin 0 -> 2448 bytes assets/images/chick_female.png | Bin 0 -> 430 bytes assets/images/chick_male.png | Bin 0 -> 385 bytes assets/images/poop.png | Bin 1211 -> 378 bytes assets/poop/README.md | 1 + assets/poop/poop.png | Bin 0 -> 378 bytes assets/ui/README.md | 1 + dist/game-v27.17.js | 59 + dist/game-v27.18.js | 59 + dist/game-v27.19.js | 51 + dist/game.js | 74 +- index.html | 30 +- package-lock.json | 58 +- package.json | 4 +- src/core/balance.js | 15 +- src/core/config.js | 28 +- src/core/entities.js | 20 + src/core/mapGen.js | 10 +- src/core/state.js | 12 +- src/core/text.js | 4 +- src/game.js | 35 +- src/render/draw.js | 552 +++++-- src/systems/buildSystem.js | 110 +- src/systems/cards.js | 59 +- src/systems/chickSystem.js | 16 +- src/systems/economy.js | 1 + src/systems/maintenance.js | 107 +- src/systems/routing.js | 17 +- src/systems/selectionSystem.js | 17 +- src/systems/uiSystem.js | 60 +- styles-v27.17.css | 1130 +++++++++++++++ styles-v27.18.css | 1253 ++++++++++++++++ styles-v27.19.css | 1279 +++++++++++++++++ styles.css | 518 +++++++ 68 files changed, 5418 insertions(+), 401 deletions(-) create mode 100644 PATCH_VERIFICATION.md create mode 100644 assets/README_ASSETS_DARK_FACTORY.md create mode 100644 assets/_legacy/images/README.md create mode 100644 assets/_legacy/images/poop.png create mode 100644 assets/chicks/README.md create mode 100644 assets/dark_factory/facilities/README.md create mode 100644 assets/dark_factory/facilities/conveyor/boost_conveyor_straight_h_16.png create mode 100644 assets/dark_factory/facilities/conveyor/boost_conveyor_straight_v_16.png create mode 100644 assets/dark_factory/facilities/conveyor/boost_conveyor_turn_ne_16.png create mode 100644 assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png create mode 100644 assets/dark_factory/facilities/conveyor/boost_conveyor_turn_se_16.png create mode 100644 assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png create mode 100644 assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png create mode 100644 assets/dark_factory/facilities/conveyor/conveyor_straight_v_16.png create mode 100644 assets/dark_factory/facilities/conveyor/conveyor_turn_ne_16.png create mode 100644 assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png create mode 100644 assets/dark_factory/facilities/conveyor/conveyor_turn_se_16.png create mode 100644 assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png create mode 100644 assets/dark_factory/facilities/machines/auto_scanner_32x48.png create mode 100644 assets/dark_factory/facilities/machines/egg_farm_16.png create mode 100644 assets/dark_factory/facilities/machines/manual_scanner_32x48.png create mode 100644 assets/dark_factory/facilities/machines/mixer_32.png create mode 100644 assets/dark_factory/facilities/machines/mixer_compact_16.png create mode 100644 assets/dark_factory/facilities/machines/shredder_32.png create mode 100644 assets/dark_factory/facilities/machines/shredder_compact_16.png create mode 100644 assets/dark_factory/facilities/utility/maintenance_room_32.png create mode 100644 assets/dark_factory/facilities/utility/obstacle_crate_16.png create mode 100644 assets/dark_factory/facilities/utility/repairman_16.png create mode 100644 assets/dark_factory/facilities/vehicles/truck_32.png create mode 100644 assets/dark_factory/facilities/vehicles/truck_compact_16.png create mode 100644 assets/dark_factory/manifest.json create mode 100644 assets/dark_factory/previews/README.md create mode 100644 assets/dark_factory/previews/facilities_overview_dark_factory.png create mode 100644 assets/images/chick_female.png create mode 100644 assets/images/chick_male.png create mode 100644 assets/poop/README.md create mode 100644 assets/poop/poop.png create mode 100644 assets/ui/README.md create mode 100644 dist/game-v27.17.js create mode 100644 dist/game-v27.18.js create mode 100644 dist/game-v27.19.js create mode 100644 styles-v27.17.css create mode 100644 styles-v27.18.css create mode 100644 styles-v27.19.css diff --git a/BALANCE_PATCH_NOTES.md b/BALANCE_PATCH_NOTES.md index 58b64b1..b00bc7f 100644 --- a/BALANCE_PATCH_NOTES.md +++ b/BALANCE_PATCH_NOTES.md @@ -76,3 +76,39 @@ Implemented events: - Fixed duplicate Emergency Loan button in the bankruptcy decision modal. - Fixed stale debug-removal CSS fragments left from the previous audit pass. - Fixed corrupted score-breakdown formula text. + +## v27.15 dark factory visual patch + +- Wired `assets/dark_factory/facilities/` sprites into canvas rendering. +- Added pixelated rendering for facility sprites and dark factory grid/floor colors. +- Changed CSS theme from green/white panels to dark industrial panels with amber/red/blue accents. +- Moved UI emphasis: status HUD across the top, event/status strip down the left, build/equipment panel on the right, sorting controls at the bottom. +- Kept user-supplied chick/poop slots unmodified. Chick art is not auto-requested; existing poop compatibility path remains. +- Debug UI remains intentionally present for balancing builds. + + +## v27.17 verified visual patch + +- Versioned CSS and JavaScript launch filenames prevent the old visual bundle from being reused from cache. +- Removed all player-facing remnants of wage-based Repairman hiring. +- Maintenance Room remains a 2×2 buildable object and dispatches one Repairman per room. +- Conveyor slats now animate perpendicular to travel, with blue-green rubber on Boost Conveyors. +- DEBUG collapsed width reduced to 58 px. +- Facility sprite scale aligned to grid-object pixel density. +- Scanner ducts, blocked-cell coverage, chick sex colors/symbols, metal/grime decoration, and card texture icons verified in browser. + +## v27.18 UI and routing patch + +- Moved event, belt speed, combo, and truck target indicators to a non-overlapping lower-left group. +- Reworked T-junction branch mode as explicit output selection: random or a valid fixed exit. +- Lightened floor tiles, added deterministic green-fluid stains, increased conveyor arrow contrast, and centered blocked-cell X marks. +- Converted card icons into translucent background watermarks and normalized modal button styling. +- Replaced Maintenance Room art with storage/break-room pixel art. + + +## v27.19 land/UI/dynamite patch + +- Starting blocked ratio: 3%. +- Purchased-lot blocked ratio: base 3% + 0.5 percentage points per purchase, max 10%. +- Dynamite target selection is map-driven and consumes the card correctly after any blast. +- Duplicate event/status information removed. diff --git a/PATCH_VERIFICATION.md b/PATCH_VERIFICATION.md new file mode 100644 index 0000000..180730f --- /dev/null +++ b/PATCH_VERIFICATION.md @@ -0,0 +1,20 @@ +# v27.19 verification + +## Automated checks + +- All source JavaScript files pass `node --check`. +- Production bundle `dist/game-v27.19.js` builds successfully. +- Initial blocked-cell generation: 6 / 200 cells = 3%. +- Purchased-lot ratios: purchase 1 = 3.5%, purchase 2 = 4.0%, purchase 14+ = 10% cap. +- A 10x10 lot at the cap generates 10 blocked cells. +- Dynamite empty-space click leaves target mode active. +- Clicking a chosen blocked cell removes that exact cell and consumes one charge. +- Escape after at least one blast finishes and consumes the card, preventing reuse. +- Browser check: no console/page errors, duplicate right-side event panel absent, Status contains no event/belt/combo/truck-target duplicates. +- Browser check: NEXT DAY Fairies fee remains inside the button. + +## Visual checks + +- Green floor residue is sparse and splattered. +- Blocked cells use subdued black/yellow hazard striping. +- Initial Status reports 6 blocked cells. diff --git a/README.md b/README.md index e4a0cca..5ffb72b 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,25 @@ -# Chick Sorter v27.14 Balancing Build +# Chick Sorter v27.19 — Land and UI Patch -Open `index.html` in a browser. +Serve this folder with a static HTTP server and open `index.html`. -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. +The launch page uses cache-busted files: -## Static server cache setup +- `styles-v27.19.css?build=2719` +- `dist/game-v27.19.js?build=2719` -Serve `index.html`, the bundled JavaScript, and CSS with cache validation -instead of import query strings. This prevents stale files while keeping reloads -fast. +A `v27.19 VERIFIED` badge appears near the upper-right when the current build is loaded. -Use the example in `deploy/` for your HTTP server: +## Build -- 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`. +Run `npm install` once, then `npm run build` after editing JavaScript or `styles.css`. -After deploying, purge any CDN or reverse-proxy cache once. +## v27.19 changes -## Current baseline - -- Build, move, box-select, sell, and repair factory equipment during Build phase. -- Start the next day only when at least one EGG route reaches a scanner and then any valid exit. -- Fairies tribute is paid when pressing Next Day, using the previous day's net profit as part of the calculation. -- Bankruptcy is checked at day-end settlement after shipment/event/subsidy revenue. Temporary negative cash during production does not immediately end the game. -- Cards use English names and descriptions with numeric effect summaries. -- `poop.png` is the only bundled image asset currently used by default; other art falls back to canvas drawing. - -## Controls - -- S1 manual scanner: `A` = left / `D` = right. -- S2 manual scanner: `←` = left / `→` = right. -- Build phase: left-drag empty map for box selection; drag selected equipment to move it. -- Right-drag: pan. -- `Ctrl+Z` / `Ctrl+Y`: undo / redo. -- `Esc`: cancel upgrade-card target selection. - -## Cleanup in this build - -- Removed duplicate `src/index.html` and `src/styles.css`; root `index.html` and `styles.css` are the single launch surface. -- Debug panel is intentionally present for balancing builds. Do not remove it during cleanup unless explicitly requested. Its card menu is grouped and target-consuming cards can be applied to selected targets. -- Removed the obsolete right-side selected-facility panel code left behind after the UI removal. -- Removed stale historical README files and old changelog text that no longer matched the current specification. +- Initial no-build tiles are 3% of the starting 20x10 land. +- Each purchased 10x10 lot increases its own no-build ratio by 0.5 percentage points, capped at 10%. +- Floor slime is sparse, deterministic splatter instead of frequent puddles. +- No-build tiles use subdued black/yellow hazard striping. +- The duplicate right-side event panel was removed. +- The Status panel no longer repeats event, belt speed, combo, or truck target data. +- NEXT DAY displays the Fairies fee on a contained second line. +- Dynamite lets the player select any highlighted no-build tiles, up to three. Empty clicks do not cancel selection. diff --git a/assets/README_ASSETS_DARK_FACTORY.md b/assets/README_ASSETS_DARK_FACTORY.md new file mode 100644 index 0000000..1e49cb5 --- /dev/null +++ b/assets/README_ASSETS_DARK_FACTORY.md @@ -0,0 +1,19 @@ +# Assets organization (prepared, not yet wired into the game) + +This patch adds a **dark factory** art set without changing runtime references yet. + +## Folder guide +- `assets/dark_factory/facilities/` : new factory equipment sprites +- `assets/dark_factory/previews/` : visual overview sheet +- `assets/ui/` : future UI asset buckets (buttons / panels / icons / debug) +- `assets/chicks/` : reserved for user-supplied chick sprites +- `assets/poop/` : reserved for user-supplied poop sprites +- `assets/_legacy/` : copied backup of older loose files +- `assets/images/` : left untouched for compatibility with the current build + +## Notes +- Grid base unit: **16x16** +- Non-grid UI object base unit: **32x32** +- Color count intentionally limited for a coarse pixel-art look +- Sprites are supplied as individual PNG files with transparency +- This patch **does not yet hook the new art into the live game** diff --git a/assets/_legacy/images/README.md b/assets/_legacy/images/README.md new file mode 100644 index 0000000..0e29b23 --- /dev/null +++ b/assets/_legacy/images/README.md @@ -0,0 +1,3 @@ +# Image assets + +`poop.png` is bundled and loaded by default. Other equipment/chick art is optional and currently falls back to canvas drawing unless external art loading is enabled in `src/render/draw.js`. diff --git a/assets/_legacy/images/poop.png b/assets/_legacy/images/poop.png new file mode 100644 index 0000000000000000000000000000000000000000..75fde9d97f6e0e8e3cec842c7b2d3c52709ed5f9 GIT binary patch literal 1211 zcmV;s1VsCZP) zO>Wdc5Jn5c8ihr&P9#=bg`;oH5A%qY@2qAR;mVN1n^Eu6$wg| zvfgBT`tbJb&%S>D({=3Z!$Ioc7g_|^OZqulWXLW+`XRt7`K_PJJ`|)Dz%uzgpU*5o zY5^`Wntbhc5J@Y*rK?UmX_wl|S_RSyu!q$ZTd@+96o9moQUKI)iyGG+DFxWWx=dFa z2FeLQ`k(-lLjfj-0!$7Cm>dc)IpqZC{XQS9eQ#0Z#$X36iOq&(UUqV!O_oWkpR9_X`M)`RlzMF z4+*e=iP&95n)?D;L6rb9D3SijUc?N&_qd1>K+XY<%=En%Y8*K(;=BOPNRhGi{vMTJ z;Qwy#VV;*yH`fi=RE-KMYR-t=o^L)NP>1|4GW$zBkaffxWY5niPS{^jZL5Ev;R|Q^vPNR^ErUlj^7OT|7*1RWIZPce-hY} z*enuc>XT`Cv0UtdI3!s1$7(1D6Tox3w>2Jpu@WHtqR{op_mm;JbZcQIK*aNHYZ)Sw zesz2OWKjjoh5)ob_%QPD#uM*hApH=~N|lnWP55mfiG>184h5K;5CIVG-4Tg6FJ=ND zEP1Yk)%oNQFgalYa2R+=)cG(K;8NM51pkQKJsds+%q~H6|IGzxu{Zi8L@~vRAQ4J% z3WVf~fUgR!$h5117ouMM8V%~(#Zv4H$}9rBLKv`B)3IVc3W=xKPqi>bUGbl`A4?m54E&V_4Yf=Kv}FhL|DvWH_SA|ksH)oPg_ zl8Ff-h0YTkc=_?Fd*PmQj{9dP0hj?GSt?@RHIHPeII^h}k8=OCXI+QK0H6Y>)5XQx z3jmqU@UT`bgF0O`kQ6s%o}Nik+$1S(a^`b1n6oe|IrBMkD6>>qSs)9u z^0P7Bh5Mv^a0CEYeEfTidI|=*PRZ zPj;&fF>J%=P)6wEFNic3-G(58@pFmX4 z%t9i8&+BQ2imHi-I3uy7h=?;+D2n4`za?^oqKJsIHCItJu_>x1GY{gX;mdEI*?GHU zIaxOhjtq?uIOR6^fV&TyqH1zFILVDOXL<4U69A>`N}Kr7;6+P2*|l|iUJtzh_lJj= zUQ7e9cXg2cBY*o0^9z8ZjuR%^-r6+tdorte?xfxzjXKh(15nk&L}edUJxo;(H}7iU zDF7e)H2`+sXE=1sNsrI#K^hG+T6=C?d-@ar=f3=Gd z!1b<4*|l}-4i~Om7Q4fR-QhATZ5q@YJRS>hJMp|tSgVw&Rm%SyD%~)e22YGJrsfk! zqfW^`Y6?@!Y19J;sa48d#Q?Tkp(vAc^Xz(d#>2-6E zj$gh)@VtlkMjn9ZM3C^axWyzo5#-vipSv>;iErfjv9gF|ln2~>gkrN6aV&I;P;8c) z7rZ9BHyvz#CSW`gOG>U#6kxnFI(a0P6q75eCW@*_u27Ue`_}j${|)v02K>pX4~YN( N002ovPDHLkV1gXS2EG6Q literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png b/assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png new file mode 100644 index 0000000000000000000000000000000000000000..e1e1fc79db72baeacb1735e09b35c329c4e9da3f GIT binary patch literal 563 zcmV-30?hr1P)W5R8Z)vq=X7; zu#`5n5o}+`kaox}2#QOw(4ozcfS4{X$0773d5L)7z`Y;m{Oi;+b-Cik6EwMC%)~1^n0(!-ks~xtMtj$ zSV9z4lb(OQwv!)C%>r=a`)>fGUI%Dca7H)LgZBencX0ask#WaUsJ_B$z`=P6iaySCO@>-VoVj6&7s~;PK)PL_j(VGEMJ9z-+ zr=!fgNp*N?eJnDE?stOGxo2 z7}Q1*Q9IJbY@D@%ptuniF0?`d)^sy-U4$7-GQDu%ao#!aoeTG(sG5wzwCpi%D;`DF zL`0&MYC}XMYFf64NOTnc^PW~wH3=!ICRcAfz^lh!Kl$emH?L*W7cRFeCy#OIGVjqhow$b&YIhiV07&_^buM=IQAnVTr#0 z?9uo8+|M81e0{k6_8k|S&k@%_TnB)SVu^dQjg4Z7jbaG^W%(`u?~@t;zhAf6wJ%CI zo0&pf*9X9Iy-v|EhLUU+7XUc?`OgqP0U(YuM2?!h*g+Kr{P?%>xj<28b&ZG~BW8Ap z=rJOC%uhOaz;U@fm*;%_;gGT4>(cLa0~2{|h5_yvb1c;Ai0iOEGwU0hD=pORJLvbi zfo6b^Y1vXhBJ~InIbEQRjsRqFJ7f(S^HA&o68Ot&Kqd0000%=lmc literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png b/assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png new file mode 100644 index 0000000000000000000000000000000000000000..06444d762a33e47a5cf28aa2e28603dd5144cccc GIT binary patch literal 534 zcmV+x0_pvUP)yWk+ki&A|mOy_w!JzsG6h{Rg;I0pA*{4A76=E<<@mp-+cgJ-podPDmzI^Q8hWc zRO0Tri@f;$WhnU3?VH?~xjMvKTWw}@(;Nv!_lH!{-CN0l)#x7%{sI4{4hU6N5{OfD>!MNu^wS+uO7_SWll;{0H71%S)n z{s17p4-kwHx1^+dyE_AK@jL)V;+2!Ewbf=^pJ2jnVH7Nkf`#}V?>~J$Opw%euiK&5 z?F?}7e8ls4vM|qVZaPTNAG|+Thyph@o2W;R(d%{&6Zjratp!$ULANQ}aiz3YE@BVLOF;)fu~Kb_?YIIIlPc>*Mu1|d1&X%g2G;XQZ|5k#e6kwZg6P(cJCQA8yq1ri8iON|Y-2~CcXqeCr);3651c>S?N zB#@w@cqBMFIRp|x^Scf99#--a`oZD;IGp?4b1oc*BrAgdNRkyHgz)U8GC~O9=_Jfr zNmhhIk`~JR4uGcS2(B!nsW~(?2S7Ly1)w~l z08p*y^trt_Z3k{qCVdRRboJv~-qk7KwO(tR?+DQE83G^>T(d?pWjn(ATZ8wvhAsS8 z2brTo0M^%5>FVyWK&JmGha@Xva@x5Bc4dodWWxVjP9i}0*H1JX05eMfA(#oPfG5z UPQAq%$N&HU07*qoM6N<$f1unheT2&1WK)@8qH8>5Ya^(lwz$FDPp06fe@ipaMnq1%4p+O1!Ex+xE-Vg zky!jg>L48&i4w6}tx01Egb*xsyQf2PPrN^M@xbAn@4Mgop67g*W3xM)0>il9&}2*j z@cY+KQ|=DH)!$3c+rB&(K!1n&vjFmxuPnQQkt98`g&DiV?rwB)uWYL$M&!mqJ zEeZT>9rQjOl=1A;M44c3E5VazL+ouOEQJ@@A9CH^_y|DX^O5QmRH3rFxeh?9&xg0Q zMQ5=5F2cPB%`(pC&QOI~H4v(*6C~C?nJ5Cm5K4T7gGWw$xvHj2U@%yEzpRU24D_MI zR{-e#{)g+DGJ((=OuT+$BFN{?bg>XO5Ew^&qZfdo;g_7Aq|F5XGbj}c0MxnMGH0wc zHBpI0&EO70mN5jlWhEoZa5sO*(p zl@mj8t_H7h! z>^lH1`~9xq%=;P6UFdM$hX?!g^hNn>t7ReB0yv#Y=Su*L#oqy3*N6)QmJt;rFkfE(h&i9{{HSL{x+2RwFz-*mrRN zZ2(Fslv0d5f7UW+ZDW&muaEfCVcNYur~3S2=2&3##R$_=uNx9;)gx-vqkk?{Vkll0 z7<)O&RB9SgitN&YlbFjdbNb9#YSp8b$p9Y9E=g))lFH6k00tjFY1u}0X#s#-ewoz7 zBmiHwY}(9l2vLf$)GUEuH@oF+qGp8M@^%9P!ESQ-Wd`o|V?KE3jNG-#T>&4-@ubT^ zaw17`JW2mR%;8=QC+eRGh^6PUV%a4DV$Epg({ovIcuhA%(+#oglKj1&#Q*p|QlbrO T;>EVz00000NkvXXu0mjfIB5{G literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png b/assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png new file mode 100644 index 0000000000000000000000000000000000000000..66b24af7423485746aa0f375105663dfe2e49dc2 GIT binary patch literal 565 zcmV-50?Pe~P)F|9LGPqbeMsGh#)BTptOfzW5tenNULo(qgkwjV8jNRmySYMkqoYN5j_NXPy-_v z@G^@oOFEm>T--ypsI0L^PaXsjq4WE7SRLJ&jUN2q{XV?k_xI<$7twS>2(0CmGQ)#I zLCox@dCW|z8EU#AA`+XNu|-5;u2+$^cp_x3R}m43ojt4RhD0>oko?rFFX(;yN^QFu z$~-(c#P#G2Zr#1_^NvJ25luJbb~;PXy$5`EO91??Z8ilzOy3E$Q(Rrc%%mCu%PVE3 zr#}F2H69Ngp8q(-r7LZ|zrVLjPddvFw@CD4VD+7C>O0#2l$IQ_W-p~BhtiS*z`)ZS z0PEKb07NMOqW_w9klSBA18}qc2LN>}a4r-LEw6BYZ@0-8Ij$g>xz#GJu5mfm&d`ey zy1LVJb*E8EvAj|~6=+rV(cu9{hX+kuDTPvs(N`}qGpUBa*&= z3k4z2O-fp$cC^TBItvj*D!9{yCeopawg@GgE$m(I3qrwcm> z$FJ!kB1SG>6cI5j+Yu2lI=dBba{ZbvKEI|*cA-GC?2qr<^PAG^Q+x@!)?U! z=34-c91XhIzdyfRe$VFn4=lWRi716A1wf@-B9$DbQZ7*`mjD$NKNTGi80VRePfSh_Lb@sla$vh#>i6xWtr z;d*I9*Bkx%sl;Unyc4M7kfIMX*dAPT)rrl?Fe9c wy&Mcj1u&ajz_e_qv5lRp>Lm__qn@k%AILQ+_j^|oKmY&$07*qoM6N<$g6~TE1ONa4 literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png b/assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png new file mode 100644 index 0000000000000000000000000000000000000000..5f55830d4b989d9e4ca76128db37b271c136a169 GIT binary patch literal 539 zcmV+$0_6RPP)1unhdVfsQV^9431$#7bhiN;wWd)_aS{r0LSqIMs}!VKl+sj}V8IR<(iSSh zL6?-IMBA%HZs`poNU@NylY+#`aoQS3y zaxF7K`sQuE*^Pkt+4Cpd$y^Wct(`q`<6{i;L`zG{09;BWP6=!E&j6ge81vYl-$$PQ zOnrNo!c?B-;Q`IV0{|MeDigU|G-_2EwJHFU_e}uyFB<@eQr!WCseB+_Wo;Edw?2IY z;7ao^0P1+aK)?+Fb1!y(i5w^JpBz?OJ9}J+#>qdPVPrJJ$Y=(o6!q=hlL29|JM9*o zcIy;ZN}-fu_T>w5<73?c{bp-@#WQYHH#s{vM5o<4iLMl{=4N?YdgTEMg&x4Vu0RSh%8 d63Nij{s&n*COctAE~o$i002ovPDHLkV1m!%@Q(lh literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/machines/auto_scanner_32x48.png b/assets/dark_factory/facilities/machines/auto_scanner_32x48.png new file mode 100644 index 0000000000000000000000000000000000000000..4a6d6dbbea2752406f4c96acf5a0187af3847455 GIT binary patch literal 850 zcmV-Y1FigtP)74P3uan1fw7kZ{wlerR~n_qn(y7nPfWu%zWSe^Z);JR}dwc zU=`s4faSk`Jb}B9)ZR14J;fl^xTG~}RY8#>84`+QIB%=LHl z=>5wVIw6RXOtv;P;8aHs267;`gU_K)hOwIF9r*HYGI<0b1Otz66og#EhKg#vKNpVz zBpG@x+T_FcD!7sdlnI=CR)@j%X^eVh)W%nAQ~>~Rd(RkG5rgg10DzXrQpUIo00=33 zCeFp98NZ3y5ol;RaEJ@}=!+-l9`RwgYt~@XgOIh5D=0k4BVf$u=>Zmxi)le2Jirpb zP{7**G#=9+yE~ zZ7s^1Y%XdR44sZ~CugCgXiN+g?KWh=)C1F@@n)+Hjt*4kCBXDHtZUj8VpgeiiCT5!rpMJ-ai)H0ssgouT0l?cGoflFrHz38T~!Q|J=(I6>N)8ZSx70 z%HucUpHZUr%BDW{P$g%3T zA(u4FgWtRm@mIhh3wXn}06S@xZnp~73;~1?L(4^k6*-MV5G9$EH*7Xcj!#4#S3)!L z`Gks!#_Ei*?~`9sM_{)SS&&$|ox)+7hROO(M?gv1dc&=jmypg+8Dkcr^6gc&Hgz=D z>5GYdp#C}b;)^Eb1x{yWUwpwcnJNx~Zn$^+}xYU0grIl{IQEzAmEq$-j zN;ekO1-+f??9;=>@TvCJ{VRDrxfRZL_33^6Q|-UyCI8hs4}%xap70lxJq3+Rl;ohW c+MnzH13IgQL2fa!ga7~l07*qoM6N<$f?Yw55C8xG literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/machines/egg_farm_16.png b/assets/dark_factory/facilities/machines/egg_farm_16.png new file mode 100644 index 0000000000000000000000000000000000000000..dd9dd9f5fe5fd5f56a4b8e7ead496445eef21917 GIT binary patch literal 314 zcmV-A0mc4_P)eF~FB2q6h(z{9<36wT6`J6k#?PhT|VXNJB z>+z^hptOc% zyxCJAiGpmVL2c>wvqL8b2B@3}{7PoQ0E61nQ{)rayn>=p0kBfOml6w4D#%(0RmAMj z@y>2NVp4^?g)GT6Fo0|2@u>fp_B4{;*qg>{0eVG7de?oXa;Z=856f1Hn}&Qdi~s-t M07*qoM6N<$g6B|%eErQmaT)_72Pe;eT~j-Tu!tBG%c%)2ojQOarf25B zaQXBhNEH14|DR#y^2Ic<90tUs6yWSv&mJ)R{|`xeEZ7vEuD(ZA%Q*rV7#>ag%OID< z%y3MDhe72TLJl4R=s+;$6IC4{m&MG$z`(#@b>j;IvYl8%fEM7@vjJl|;vOZlsC>;C5mWW5F#&-4MWK4+|dqsU8B@?14wY z`D42r4XxbvBTG^{1aL>e|NjhzmahBJ6C?FQ09O>?0Mt(dm;f3D*b@Qua{-Bokm>+e zA{$-LbPa(^r}n#}i_tX% zbWI(0qT4k%(g3#9dF%3Ns#~U}Yl__gq{M)T1f=is=EY-@aMgy?x1WpLBkcf>%;$mRlu1MuZT zYUTnhL+cCZb`6e_kY05GHhTzmPN|v;uz*353vk2$uGCB}AgL};RM(@b<+$vjZ(V=| zkX0AFdioGUOiWsydNklz zPe_zO7{-4q9@O+8is*`H_ymSP1eO5?&3$gVG;Jy{sZ` ztAa-0!9x@TB8njkma=N-)j!+mTMyfOGQ;d*Bz^-ur*GbQ-g#!8@12?Nb7f>^$8iv8 zPKpDhi-*|RaS6ciSTG7O(Eq69DuvW>GqZA{V1NTIQ3FFS-)IS;>B)Z*c-ZaJ#-Bgy z159$@c0&^YT|JKhn4Ox?CWJoBTx#H(#f94Vox9BdtbO|o7~p`t3#_;Wz)bMHmKYAt z0^s#_0g&JKNz2<9tO20FT_(kk4t69R0dpLPTlxcWZaxHne=!G0zH))u7n@T1b+8eD ziUYllK@KSIW_}?IK<5K500sTaQvcCdtJL0D{R%+q+fylif9phQt2!n*psxXS<%gp! zDFKjt#iGDTT90#l~pJS>g#t1W#c94{zz?A^`244yoU92kh^Gs#|pcM0b8j zgw04|W#TUQTfFNy2Efzik>Zi>>wrlPR94plu($j3T7+X~i95n^2kZ&>`~iIafO8XY v3U&?rj-B)ZpI1!&00000NkvXXu0mjfoO}I= literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/machines/mixer_compact_16.png b/assets/dark_factory/facilities/machines/mixer_compact_16.png new file mode 100644 index 0000000000000000000000000000000000000000..980ab2e9eed9c330e277f6d5bdac90d686b1fdfa GIT binary patch literal 475 zcmV<10VMv3P)LW%{!T0*cC8w({NV6=#e zxIT~-0u~lxVIztn7kn&H!EIe)sxv9pd)DP*@bSZe;h*{cGc%lHn3gR(2c~6eaLZZP0JR;v}_p}`=$+J^E3awu(P{Y$HPMd7^Y=QL+CACJs(+|o6Z<5EqKHg zFN<~D*wn)A&K9`A zJU>eeQ2*rsfUmP}@Ly&$IRGLG5yi@CjE)asElN(dlALU1qd!k`%||I*%^d?lB<)!A zX#;?(iFaANYvOj|^0y->&%*9r7YK%Q{&tDpx1>Z!96JEKs;cqiTx9J4V0*9x z0AF;IvPwT?m3|V(4!-Cn02kve#Mjq!yC_+YzB_fk0L6U;_I;qCu^E8W$OHf%@sd})U)N^(9)R1MD?oq&I|J6vS2MF; zjf_vki1Sss0XqZl#n)i~t-F3L2=L?C6ClZes#0#?6W>61G$msr!vFvP07*qoM6N<$ Ef)PEjApigX literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/machines/shredder_compact_16.png b/assets/dark_factory/facilities/machines/shredder_compact_16.png new file mode 100644 index 0000000000000000000000000000000000000000..573e8d79dd46bd75a92d8d85bc5a1b4d49b94fec GIT binary patch literal 326 zcmV-M0lEH(P)dH$N3Qo zqxF8f00|Ns?X;xGM30hGABc<6H Y0J&0;{a?*IS*07*qoM6N<$f_A5p+W-In literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/utility/maintenance_room_32.png b/assets/dark_factory/facilities/utility/maintenance_room_32.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4e45b30e1d03a335d9fe68979bdc1bb886b6c0 GIT binary patch literal 843 zcmV-R1GM~!P)`$&Z(vJ;UvH_FEK#t;WZ3l6sTIlq&Z;XI4MgIfSi@V^eYeaC&M-r&2 zt|tryAxexH#dq0A%mk51YMQ8b9w^Kx=Ql%I-tJPxV(Wl6nU2o;xhb z!Q7*g?0dq)W-mv0W=bN_+MBOQqW(e)cy1J|y8!^;ANHzjh+Cjc84ZFEg}Km%@XQn# z#w4YcVN4K&sPs$ZUz+y^!7-njKq?SP06@o}1rI%6(wc|51O-asm!lohrcW0y|wjhZ*FfcNoVEyWV08m!xjt3f#_k_+< z9t%YayV-m zB$?;@;OAC|Ezl*9N{dxi=_aFmb)in}hv5nd+y)J>Rz&`@= VBmlBX*d_n~002ovPDHLkV1hG9g;W3l literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/utility/obstacle_crate_16.png b/assets/dark_factory/facilities/utility/obstacle_crate_16.png new file mode 100644 index 0000000000000000000000000000000000000000..8dfba88f524e534c2595504d07f046c69572afcd GIT binary patch literal 387 zcmV-}0et?6P)Nkl zt6#MpQ|D)S@(djS6cIN%rVd3ES$^@^)dv80232Rp&2A$R5_cO3?pK`^6p_zBeO1}^ zOnO$5@t&1rylk%+2LMe-gH8{20y%Fkwj%SFF5d(9+s79#g1?H*Wk_6XE<-$E{TY?| zdllk1krNE;RERjRQ;`#_4ZIq*1d9sR0tIWq_hCx}xSoL`C`A}Ko;Yv1jOR_4@sT4K z4@4NZC6jXXd1%~Rea`)HTmFnd$kt{6fNX6RyNTZ%0JytO16c3D!hNemzT%ie_j`Tq hcv2D4=xdw)&YuHy{V?jTG;ja_002ovPDHLkV1oZ|pp^gs literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/utility/repairman_16.png b/assets/dark_factory/facilities/utility/repairman_16.png new file mode 100644 index 0000000000000000000000000000000000000000..1fb17b04102c4d077aba978c13a07c92b2226e88 GIT binary patch literal 222 zcmV<403rX0P)pD8_+!<~g3qAh^Uf&z01sCTH8^8|SU|A>@K8igVZ;Dj8H^+V Y0Fwbw^1=;l{r~^~07*qoM6N<$f}n?A(*OVf literal 0 HcmV?d00001 diff --git a/assets/dark_factory/facilities/vehicles/truck_32.png b/assets/dark_factory/facilities/vehicles/truck_32.png new file mode 100644 index 0000000000000000000000000000000000000000..c8c3360d64c3385a49ae99f836f79cbdf897bc3e GIT binary patch literal 496 zcmVEP~@MWd@YzFMM?QsVTF~CvZ1653!ky_ABe>$6tb`p zH4Bl2X@C-o&$;J3=f2N-&g~d3x7Wf!q&Zm}AYD8}!mkAYbIV%~ z0HggK1*t3)&+GPNK7a-a7@`NJ=2w&f2Rj={6=-hjQu-%H`T(62sIF}UprySVfc@?D zKM|b=j%>x%)HMNcae54Bpg?pAOv?mdZ)+_n!o2(2o8HfN`L*t zJ@DQAiRx&ifNA~~XB*<=0-`qrt}jj{TOS2XE47P}zcowg_wBw&wmu5P&u60UPBk=A zAi)&Wjo(RjV5Z0xare%%WUsenE8`qjAi5EimRA9Advgi=?1>+VhWgw8n&-Fz(H`jP z9h6>74EO$;SW;H0^a}+OL2TdpZN+bqkPl#XY10odHqhw<$Z&c5u?g>QVV@o1_`K!#{aq~Eabue#pN~QF~0Duz3?bTW6 z=8@5HQ`c)gN)!MQ08tW}0M(Nr0G<;r8Ur*Hh$!C5#Xq-ORs<*Y0>Cn3XiR{h$u>MO z(*=Im{x82ogS8rf_e!ZvprpUIbe*KV$<8qIt>5Tn vb9n*0s2!829TULoOx@G7<}>v)+-Lj%$Qrti8HC?l00000NkvXXu0mjfUn;bi literal 0 HcmV?d00001 diff --git a/assets/dark_factory/manifest.json b/assets/dark_factory/manifest.json new file mode 100644 index 0000000..98ccc56 --- /dev/null +++ b/assets/dark_factory/manifest.json @@ -0,0 +1,103 @@ +{ + "theme": "dark_factory", + "grid_unit_px": 16, + "ui_unit_px": 32, + "palette_note": "restricted palette / coarse pixel art", + "facilities": [ + { + "id": "conveyor", + "files": [ + "conveyor_straight_h_16.png", + "conveyor_straight_v_16.png", + "conveyor_turn_ne_16.png", + "conveyor_turn_nw_16.png", + "conveyor_turn_se_16.png", + "conveyor_turn_sw_16.png" + ], + "size": "16x16", + "folder": "facilities/conveyor" + }, + { + "id": "boost_conveyor", + "files": [ + "boost_conveyor_straight_h_16.png", + "boost_conveyor_straight_v_16.png", + "boost_conveyor_turn_ne_16.png", + "boost_conveyor_turn_nw_16.png", + "boost_conveyor_turn_se_16.png", + "boost_conveyor_turn_sw_16.png" + ], + "size": "16x16", + "folder": "facilities/conveyor" + }, + { + "id": "egg_farm", + "files": [ + "egg_farm_16.png" + ], + "size": "16x16", + "folder": "facilities/machines" + }, + { + "id": "manual_scanner", + "files": [ + "manual_scanner_32x48.png" + ], + "size": "32x48", + "footprint": "2x3 tiles", + "folder": "facilities/machines" + }, + { + "id": "auto_scanner", + "files": [ + "auto_scanner_32x48.png" + ], + "size": "32x48", + "footprint": "2x3 tiles", + "folder": "facilities/machines" + }, + { + "id": "mixer", + "files": [ + "mixer_32.png", + "mixer_compact_16.png" + ], + "size": "32x32 + 16x16 compact", + "folder": "facilities/machines" + }, + { + "id": "shredder", + "files": [ + "shredder_32.png", + "shredder_compact_16.png" + ], + "size": "32x32 + 16x16 compact", + "folder": "facilities/machines" + }, + { + "id": "truck", + "files": [ + "truck_32.png", + "truck_compact_16.png" + ], + "size": "32x32 + 16x16 compact", + "folder": "facilities/vehicles" + }, + { + "id": "repairman", + "files": [ + "repairman_16.png" + ], + "size": "16x16", + "folder": "facilities/utility" + }, + { + "id": "obstacle_crate", + "files": [ + "obstacle_crate_16.png" + ], + "size": "16x16", + "folder": "facilities/utility" + } + ] +} \ No newline at end of file diff --git a/assets/dark_factory/previews/README.md b/assets/dark_factory/previews/README.md new file mode 100644 index 0000000..b1790a8 --- /dev/null +++ b/assets/dark_factory/previews/README.md @@ -0,0 +1 @@ +Preview sheet(s) for quick inspection. These are reference only, not runtime assets.\n \ No newline at end of file diff --git a/assets/dark_factory/previews/facilities_overview_dark_factory.png b/assets/dark_factory/previews/facilities_overview_dark_factory.png new file mode 100644 index 0000000000000000000000000000000000000000..b387a8d20efd2f4034e8530c98ba612523318b60 GIT binary patch literal 2448 zcmc(heLT}^AIB$_A?#MEROZ$>IY>?qEXAgsn&Yw1OjvZXkQSAxC6A|4x+8g5(x^l? zi-~5Ar#02VNK!0ptelCh%{*;pPxsuXbHD1`-GAJFoqw*^_4-}k@Ar3I*XR5Dynk2r z`?wkEo9P1p07Lg5_xJ$-TCSQo7qnC}o|4nW0DvCaeb4R#XKxER`!3&(Sg$LNz#FZ! z_ka7;W^dgMguU-&&vxtMdATl|K)$#1wdTMet?ZvpMeYs+oBci85&`<{4&q7Ko0RJG z=l3q%_E>GOkqErnefaKaPy3(jYs}-IwY8HiligkNh+$bG416|Xj3gyAkd&gC$;6{~ zhcIk!fEM1*BWmIz?~48RZzmoQ>2+JDf?y$A5Vp z!7_4AnvJzhoE?A43O{vK{>XXMDXO6trie-CRMhaSu% zfOmh3;g;GfW7ZuLcUa8SA0zPKm3I}MQXg{=qhW&II(48Is2UhB*3Tl(7T3ZzJ6E+% z)JDtg*v;UFLxZxba&=9SZc+I+faC>n$h(tyFtwO?u?-(-sY4TuaMVOUk2Av@XR)*R zAMV#P9R8N3RJBp_b#bVU)m&~4BfBk>P@Z9u6`B-O)uQmlX8||c7oQD~2n5u8LtIUd zaI+|%YC?~^^oYNvy{z+PknYXW41CJL(FA1{O>+pl;Qx zQf=k1K9PpBEq%{%&R9{YZF^4BQWy~8DZEQDQc5Ue{<%Uqf{akuzz;Iy!4hzhG z&R#Y&q*rdY%Yr976Euhze+6D|)VB56W1GzT)BAb5#7r!*)m){F#4 zVMLTED#_}{*R&e%=tDtp^`X$U0)_qY6Q~2r2e}mb{QK0lk@*g~S%o|Gc>41$8!|Nj zPd;Ui1r8sI2`dUpqXN10g_d1GohR8-j|ovuj<`vpkO6_d=92}>*FO*zvw|m_(0$eI zJo4I$ELgYG=yxsvC{d+GCq!8*V}GMIG1?E8)b_&XIZ$a9tx9?17T+7&yRf`%du2(T zm(2m5S! zT%3eyn_d+>CqigC*h{l6QCbyH=y+AQCfJigK?kHWeh!X`nq#U?dQ9|;Zp|}Kv2A9k zraI6qAxwwlnP&JT^)HcKhR${nyS=XqKRIl3d zD(d1@?^TcBJ-kT#s`>9~9m%_@9J~2riEi%wJ1LGTXg4{Xrt(WD*n1>_I81Ia@+6~; zfSgo|kGR~RBKPZn%*G25vrPv<&)%7Sj5Roadvs`Je~h`1dQ2MhxFn10SO2V(wng3< zcFAE5cLH1RpirGo6tC;cgLgZjI)fF?9cg14IoAi?@{?RoIT1t1oKcsp>%xXiMtj0ZBPqmTN_t1Js{NDVHS_uW)@$2;zm`j2<=oR8<73NdP-~6`oqyt3#+-s zCtxnq)EG=6>~z|O=#c91ohWM?X!O75 z;~bhhRMuo{Z_ad+G0`p4R;32Z{(#nJz81YmzZZp_#LX7I+6uX@=cwg!yB zAaahM3c+Cb(90?Sx%QJtV@%lRJp8QmV#a?TW|4vtZJk#BqRHfI%yzJARf%>uSo8Q3 z9KW9P#xFRafOpOlz@FOxr^`^%fEgGi5&m$?p1OLp}E zmwpcGzh*xf$KfKL$SN?r`n5(qjn+se>;K=^Tqur3Ie85u4%hr?0o?cc?5RS8rTq)A CxMX<% literal 0 HcmV?d00001 diff --git a/assets/images/chick_female.png b/assets/images/chick_female.png new file mode 100644 index 0000000000000000000000000000000000000000..2280bb985ad07512c77291cc45fa2a66f7d26d18 GIT binary patch literal 430 zcmV;f0a5;mP)v&WzQyXWS8Vjai)fn@w2kgKuHE&YfL3B)2#U6N=AZ8p;2 zmc9^xHsJE}L;YrTdoRA%AWR8_j6)#F3HT7cdHeLH_T}}w0}-o(D8Q6&jtR8;ue(m; zVpAg^-|bHIfw$qnoQUZ4VffDV52OSGxY>*51_(bz7~p6Q&LkDW^d~%rM1Zko?-WV_ zOTepk&hnbGyq4OC{;J>K0WslAu-J5rIm>IwTzVb{;7l?B_%$KbN331awFN*NxTuJ> zmDxBMKvZ!8@L>?C|7dtC`sRHdU|c~;XTmrMXga{P#f-RY#4c(PI$Fz~9%x$;mkn{* zs3#(P9IH#wUjnZNLeV?HOTg>74j~jCnjCy9?p#d38&PQHW`I6KOo+J|00BXbFS^L- Y7dzRk%U6%d{Qv*}07*qoM6N<$g333*k^lez literal 0 HcmV?d00001 diff --git a/assets/images/chick_male.png b/assets/images/chick_male.png new file mode 100644 index 0000000000000000000000000000000000000000..b6d8eab0db379887ca31c90c49caab046be4ca6e GIT binary patch literal 385 zcmV-{0e=38P)b;@5Ji8YNX}Z>mIH7Ae226yxIiR2dQOs_E)o}@*p@rs18@LZ5DryRL=z3pjCU4{ zoWj4dyz7~_Gk?7c4C+}A)`_F(`&Vl4{dy6N|Ck!IYxNFbZUF#1yBBjCKI@|?wi$pY ze_bBbd7HUUf{0GwiR;s0!pF)Ls#`(K9%v>9fbfPt??`P`G6T@+rQ|6PZQfA<=p*Y& zu7&7*8;Ss3t)A3Y1ycpM+g@7;;R89g{=5}<}eni|7h!0N7&4@ECfwD8AuABF0`+$`U0#ePW&P#$00000NkvXXu0mjf?D(lO literal 0 HcmV?d00001 diff --git a/assets/images/poop.png b/assets/images/poop.png index 75fde9d97f6e0e8e3cec842c7b2d3c52709ed5f9..13517e795f1f26ac264d6801f59ba005e4256064 100644 GIT binary patch literal 378 zcmV-=0fqjFP)VnmIUm{=?WmzJDRhEGBALj*U+&Aj{P-%O)jh!^QIEU1eZkAUz~V4go?w zB{d|-jsj%gW8>4@0n`FR%K^m3FDdDOXa}Gh3QP64_{2JbCz*;Z%z( zPmCjo%Cj(o&@EPyk;1SXU7k?6KrjSgmNy3~;8ll9o=_+d3;}cpL{C1(z`(%3ur${S zt9oSl+Vu|@7#Q%Ejx2;6fDUk3OsqUQ7~JIma{R%9lURVP9$z}Z=>Tk+h;;-ub+{aX zHE|#-E_M`WU|?Wi=-vMkMGdx8k8UwGz32%NuLEEPzyP`<@Bv(U(H%fiF2EHU_$(#_ zh>ikE0KO=|nh22viN8j@5Qkpl=-MkKe2iE#|MeT0z- Y0JdI?It5RF8~^|S07*qoM6N<$f>6DX4FCWD literal 1211 zcmV;s1VsCZP) zO>Wdc5Jn5c8ihr&P9#=bg`;oH5A%qY@2qAR;mVN1n^Eu6$wg| zvfgBT`tbJb&%S>D({=3Z!$Ioc7g_|^OZqulWXLW+`XRt7`K_PJJ`|)Dz%uzgpU*5o zY5^`Wntbhc5J@Y*rK?UmX_wl|S_RSyu!q$ZTd@+96o9moQUKI)iyGG+DFxWWx=dFa z2FeLQ`k(-lLjfj-0!$7Cm>dc)IpqZC{XQS9eQ#0Z#$X36iOq&(UUqV!O_oWkpR9_X`M)`RlzMF z4+*e=iP&95n)?D;L6rb9D3SijUc?N&_qd1>K+XY<%=En%Y8*K(;=BOPNRhGi{vMTJ z;Qwy#VV;*yH`fi=RE-KMYR-t=o^L)NP>1|4GW$zBkaffxWY5niPS{^jZL5Ev;R|Q^vPNR^ErUlj^7OT|7*1RWIZPce-hY} z*enuc>XT`Cv0UtdI3!s1$7(1D6Tox3w>2Jpu@WHtqR{op_mm;JbZcQIK*aNHYZ)Sw zesz2OWKjjoh5)ob_%QPD#uM*hApH=~N|lnWP55mfiG>184h5K;5CIVG-4Tg6FJ=ND zEP1Yk)%oNQFgalYa2R+=)cG(K;8NM51pkQKJsds+%q~H6|IGzxu{Zi8L@~vRAQ4J% z3WVf~fUgR!$h5117ouMM8V%~(#Zv4H$}9rVnmIUm{=?WmzJDRhEGBALj*U+&Aj{P-%O)jh!^QIEU1eZkAUz~V4go?w zB{d|-jsj%gW8>4@0n`FR%K^m3FDdDOXa}Gh3QP64_{2JbCz*;Z%z( zPmCjo%Cj(o&@EPyk;1SXU7k?6KrjSgmNy3~;8ll9o=_+d3;}cpL{C1(z`(%3ur${S zt9oSl+Vu|@7#Q%Ejx2;6fDUk3OsqUQ7~JIma{R%9lURVP9$z}Z=>Tk+h;;-ub+{aX zHE|#-E_M`WU|?Wi=-vMkMGdx8k8UwGz32%NuLEEPzyP`<@Bv(U(H%fiF2EHU_$(#_ zh>ikE0KO=|nh22viN8j@5Qkpl=-MkKe2iE#|MeT0z- Y0JdI?It5RF8~^|S07*qoM6N<$f>6DX4FCWD literal 0 HcmV?d00001 diff --git a/assets/ui/README.md b/assets/ui/README.md new file mode 100644 index 0000000..94d658a --- /dev/null +++ b/assets/ui/README.md @@ -0,0 +1 @@ +Future UI asset buckets. Nothing is wired yet. Use 32x32 as the base size for non-grid UI objects.\n \ No newline at end of file diff --git a/dist/game-v27.17.js b/dist/game-v27.17.js new file mode 100644 index 0000000..1863d48 --- /dev/null +++ b/dist/game-v27.17.js @@ -0,0 +1,59 @@ +var Y={version:"v27.17 VERIFIED VISUAL PATCH",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,fairiesTribute:{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},incomeUpgradeRate:1.1,explosionDamageDivisor:30,maleTruckFinePerHalfDay:30,shredderBonus:{maxCards:30,incomePerUpgrade:1.25},chemicalWeaponSubsidy:{poopPerBlock:70,yenPerBlock:1200}},production:{poopRate:.08,autoScannerCooldown:3.5,autoScannerUpgradeRate:.95,autoScannerCardUpgradeRate:.95,autoScannerMinCooldown:.5,poopRateCardBonus:.04,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:"autoScannerTuning",title:"AUTO SCANNER Tuning",rarity:"common",type:"instant",description:"All AUTO SCANNER cooldowns use default cooldown x0.95 per copy.",tags:["SCANNER","PASSIVE"]},{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",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:"poopRateBooster",title:"Poop Culture",rarity:"common",type:"instant",description:"Base poop rate +4 percentage points. No card limit.",tags:["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:"sparePartsBin",title:"SPARE PARTS BIN",rarity:"common",type:"instant",description:"Restores 2% durability to every machine. A box of almost-compatible parts.",tags:["MAINTENANCE","ACTIVE"]},{id:"dudRefund",title:"DUD REFUND",rarity:"common",type:"instant",description:"DUDs now come with paperwork. Gain JPY 50 per copy when you pick a DUD.",tags:["CARD","ECONOMY","PASSIVE"]},{id:"freeReroll",title:"FREE REROLL",rarity:"common",type:"instant",description:"The first bad ideas are free.",tags:["CARD","PASSIVE"]},{id:"composter",title:"COMPOSTER",rarity:"common",type:"instant",description:"Turns shredder waste into suspicious fertilizer. Gain JPY 3 per copy when SHREDDER processes poop.",tags:["POOP","ECONOMY","PASSIVE"]},{id:"scannerQueueSpacing",title:"Scanner Queue Spacing",rarity:"common",type:"instant",description:"Manual and Auto Scanner queue spacing -15%. No card limit.",tags:["SCANNER","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 unbuildable cells",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:"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:"Fairies tribute profit exemption +JPY 250.",tags:["ECONOMY","RARE","PASSIVE"]},{id:"chemicalWeaponSubsidy",title:"Chemical Weapons Subsidy",rarity:"ultraRare",type:"instant",description:"Each day, gain JPY 1200 per 70 poop shipped by truck. No card limit.",tags:["POOP","ULTRA RARE","PASSIVE"]},{id:"laborExploitation",title:"Motivational Exploitation",rarity:"ultraRare",type:"instant",description:"Repair room work time -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,autoScannerTuning:0,poopRateBooster:0,crowdedFarming:0,hatchingFeed:0,safetyCover:0,recyclingSubsidy:0,chemicalWeaponSubsidy:0,preventiveMaintenance:0,dudFilter:0,durabilityCoating:0,sparePartsBin:0,dudRefund:0,freeReroll:0,composter:0,scannerQueueSpacing:0,laborExploitation:0,usedMachineActive:!1,rescueLoanCharges:0},commonWeight:8,rareWeight:2,ultraRareWeight:.45,baseDraftSize:3,maxDudsPerDraft:2,dudChancePerCard:.3,dudChanceReductionPerFilter:.05,extraCardsAddedPicks:2,rerollCost:{dayDivisor:2,multiplier:100}},events:{eventChance:.1,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:{secondsPerOnePercent:.5,walkSpeed:90}},facilities:{conveyor:{id:"conveyor",type:"conveyor",name:"Conveyor",shortName:"Belt",price:30,buildable:!0,upgradeable:!1},boostConveyor:{id:"boostConveyor",type:"conveyor",name:"Boost Conveyor",shortName:"BOOST BELT",price:75,buildable:!0,upgradeable:!1,speedMultiplier:2},eggFarm:{id:"eggFarm",type:"eggFarm",name:"Egg Farm",shortName:"EGG",price:250,buildable:!0,upgradeable:!0,maxLevel:4},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:180,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}},maintenanceRoom:{id:"maintenanceRoom",type:"maintenanceRoom",name:"Maintenance Room",shortName:"REPAIR ROOM",price:220,buildable:!0,upgradeable:!1,footprint:{cols:2,rows:2}}}};var Er=Y.version,Mt=Y.time.daySeconds,an=Y.cash.starting,Ce=Y.economy,Rr=Y.time.farmShutdownGraceSeconds,xn=Y.production.autoScannerCooldown,Pr=Y.production.autoScannerUpgradeRate,po=Y.production.autoScannerCardUpgradeRate||Y.production.autoScannerUpgradeRate,yo=Y.production.autoScannerMinCooldown,Ar=Y.events.eventChance,gt=Y.events.firstTurn,ho=Y.production.poopRate,mo=Y.production.poopRateCardBonus||0,Mn=Y.conveyor.baseSpeed,Wt=Y.conveyor.maxSpeed,gn=Y.conveyor.bearingSpeedMultiplier,$e=Y.cards,Ir=Y.cards.definitions,bo=Y.cards.defaultEffects,st=Y.production.eggSpawnRanges,f=Y.grid,ve=Y.facilities,vo=["conveyor","boostConveyor","eggFarm","autoScanner","manualScanner","mixer","trash","truck","maintenanceRoom"],cn=["mixer","trash","truck"],$r=["mixer","truck"],lt=Object.fromEntries(Object.entries(ve).map(([e,t])=>[e,t.price])),de=[{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"}],p={bg:"#111318",ink:"#090a0d",muted:"#8f9bab",green:"#7bd84f",greenSoft:"#273c24",mixerBlue:"#4aa3ff",truckPink:"#ffb33e",wasteGreen:"#88d35a",danger:"#e34a36",warn:"#ffb827",white:"#e6edf2",poop:"#7b4a23",male:"#4aa3ff",female:"#ff6fae"},xe={ambient:0,important:1,critical:2};function g(e){let t=Number(e)||0;return`${t<0?"-":""}\uFFE5${Math.ceil(Math.abs(t)).toLocaleString("ja-JP")}`}function I(e,t){return`${e},${t}`}function Z(e){let[t,n]=String(e).split(",").map(Number);return{col:t,row:n}}function un(e,t,n){return Math.max(t,Math.min(n,e))}function W(e,t){return e+Math.random()*(t-e)}function Ee(e,t){return e>=0&&e=0&&tMath.round(un(r,0,255)).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`}function Kt(e,t,n){let o=Dr(e),r=Dr(t);return cl(wo(o.r,r.r,n),wo(o.g,r.g,n),wo(o.b,r.b,n))}var oe={appTitle:"Chick Sorter",versionTitle:`Chick Sorter ${Er}`,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 ct(e){return ve[e]?.name||String(e||"").replace(/^[a-z]/,t=>t.toUpperCase())}function ul(e){let t=ve[e];return t?e==="conveyor"||e==="boostConveyor"?`${g(t.price)} / tile`:e==="autoScanner"?`${g(t.price)} / ${xn.toFixed(1)}s cooldown`:e==="trash"?g(t.price):g(t.price):""}function dl(e){return{conveyor:"A narrow green belt. Routes decide whether chicks live, ship, or become invoices.",boostConveyor:"Moves chicks twice as fast. Wears down like a normal belt.",eggFarm:"A tiny gatehouse producing questionable eggs on schedule.",autoScanner:"Slower than hands without upgrades.",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.",maintenanceRoom:"2\xD72 repair bay. Each room dispatches one repairman during the day."}[e]||""}function Br(e){let t=dl(e);return`${ct(e)}${ul(e)}${t?`${t}`:""}`}function Lr(e){return oe.routeLabels[e]||String(e).toUpperCase()}function Or(e){let t=2166136261;for(let n=0;n>>0}function Nr(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 En(){return`RUN-${Date.now().toString(36)}-${Math.floor(Math.random()*1e6).toString(36)}`.toUpperCase()}function _r({seed:e,targetRatio:t=.2,reserved:n=[]}={}){let o=Nr(Or(e||En())),r=new Set(n.map(c=>typeof c=="string"?c:I(c.col,c.row))),i=[];for(let c=0;c0;c-=1){let v=Math.floor(o()*(c+1));[i[c],i[v]]=[i[v],i[c]]}let l=Math.round(f.cols*f.rows*t);return new Set(i.slice(0,Math.min(l,i.length)).map(c=>c.k))}function Gr({seed:e,colStart:t=0,colEnd:n=f.cols,rowStart:o=0,rowEnd:r=f.rows,targetRatio:i=.2,reserved:l=[]}={}){let c=Nr(Or(e||En())),v=new Set(l.map(X=>typeof X=="string"?X:I(X.col,X.row))),x=[],E=Math.max(0,Math.floor(t)),R=Math.max(E,Math.floor(n)),B=Math.max(0,Math.floor(o)),O=Math.max(B,Math.floor(r));for(let X=B;X0;X-=1){let ae=Math.floor(c()*(X+1));[x[X],x[ae]]=[x[ae],x[X]]}let ee=Math.round((R-E)*(O-B)*i);return new Set(x.slice(0,Math.min(ee,x.length)).map(X=>X.k))}var Ht=10,Ur=2,Wr=1;function qt(e,t){return`${e},${t}`}function fl(e){let[t,n]=String(e).split(",").map(Number);return{chunkX:t,chunkY:n}}function Rn(e){let t=Y.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 Kr(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 x=qt(v.chunkX,v.chunkY);t.has(x)||n.has(x)||n.set(x,So(e,v.chunkX,v.chunkY,v.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 Yr(e,t="right"){let n=Tt(e);return n.find(o=>o.direction===t)||n[0]||null}function Et(e){return{x:f.x+e.colStart*f.cell,y:f.y+e.rowStart*f.cell,w:e.cols*f.cell,h:e.rows*f.cell}}function ko(e){let t=Et(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 Vr(e,t){let n=ko(e);return t.x>=n.x&&t.x<=n.x+n.w&&t.y>=n.y&&t.y<=n.y+n.h}function zr(e){let t=[];for(let n=e.rowStart;nEe(t.col,t.row))}function Sl(e){return[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}].filter(t=>Ee(t.col,t.row))}function kl(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 ei(e){let t=new Set([...e.conveyorTiles]),n=o=>{o&&Ee(o.col,o.row)&&t.add(I(o.col,o.row))};for(let o of e.scanners){for(let r of Sl(o))n(r);for(let r of wl(o))n(r)}for(let o of e.eggFarms){n(o);for(let r of kl(o))n(r)}for(let o of Object.values(e.facilities))n(o.entry);return t}function jr(e){let t=hl.map(([n,o])=>({col:n,row:o}));for(let{col:n,row:o}of t)Zr(e,n,o);for(let n=0;n({...n,keys:n.keys?{left:{...n.keys.left},right:{...n.keys.right}}:null,queue:[]})),e.eggFarms=bl.map(n=>{let o=Rt(n);return{...n,nextSpawn:o,lastInterval:o}});let t=ei(e);e.blockedCells=_r({seed:e.runSeed,targetRatio:Y.map.blockedRatio,reserved:[...t]}),Cl(e),jr(e),e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function Pt(e){return e?[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function ye(e){let t=F(e.col,e.row);return{x:t.x+f.cell/2,y:t.y}}function dt(e,t,n){return e.eggFarms.find(o=>o.col===t&&o.row===n)||null}function ft(e,t,n){return e.scanners.find(o=>Pt(o).some(r=>r.col===t&&r.row===n))||null}function At(e,t){return e.scanners.find(n=>n.id===t)||null}function To(e,t){return e.scanners.find(n=>n.kind==="manual"&&n.slot===t)||null}function $n(e){return e?.baseId||e?.id||""}function Eo(e,t){return Object.entries(e.facilities||{}).filter(([,n])=>$n(n)===t)}function Re(e,t){return{inputA:{col:e.col,row:e.row-2},inputB:null,left:{col:e.col-1,row:e.row},right:{col:e.col+2,row:e.row}}[t]}function oi(e){return e?de.map(t=>({col:e.col+t.dc,row:e.row+t.dr})).filter(t=>Ee(t.col,t.row)):[]}function ri(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(I(l.col,l.row))||n.some(c=>c&&Tn(l,c))||r.some(c=>Tn(c,l))||r.push({...l,viaTolerance:!Tn(l,t)})};i(t);for(let l of o)i(l);for(let l of oi(t))i(l);return r}function ti(e,t,n=[],o=[]){let r=ri(e,t,n,o),i=r.filter(l=>!l.viaTolerance);return i.length?i:r}function xl(e,t){let n=Re(t,"inputA");return!n||!Ee(n.col,n.row)?[]:e.conveyorTiles.has(I(n.col,n.row))?[{...n,viaTolerance:!1}]:[]}function Ml(e,t,n){let o=Re(t,n);return ri(e,o,Pt(t))}function gl(e,t){let n=e.facilities[t]||Eo(e,t)[0]?.[1];if(!n)return null;if(n.entry)return F(n.entry.col,n.entry.row);let o=$n(n)||t;return o==="mixer"?{x:n.x+n.w,y:n.y+n.h*.52}:o==="truck"?{x:n.x,y:n.y+n.h*.52}:o==="trash"?{x:n.x+n.w/2,y:n.y+8}:{x:n.x+n.w/2,y:n.y+n.h/2}}function ii(e,t,n){return n==="inputA"?xl(e,t).length>0:Ml(e,t,n).length>0}function be(e){e.branchCounters?.clear?.(),e.routeCache=null,e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function De(e,t){return I(e,t)}function Yt(e){return Z(e)}function Tl(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=>de.some(i=>i.name===r))}function El(e,t,n){let o=de.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.(De(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Rl(e,t){let n=Yt(t),o=e.conveyorMeta?.get?.(t)||{},r=de.filter(R=>e.conveyorTiles.has(De(n.col+R.dc,n.row+R.dr))).map(R=>R.name),i=Tl(e,t).filter(R=>r.includes(R)),l=r,c=i.length?i:l;if(r.length<3)return c;let v=new Set(r.filter(R=>El(e,n,R)));if(o.branchMode&&o.branchMode!=="random"&&r.includes(o.branchMode)){let R=new Set(v);R.add(o.branchMode),r.filter(B=>!R.has(B)).length>=2&&v.add(o.branchMode)}let x=r.filter(R=>!v.has(R));if(x.length)return x;let E=c.filter(R=>!v.has(R));return E.length?E:c}function Pl(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 Al(e){let t=Pl(e);for(let o of e.conveyorTiles)t.cells.add(o),t.adjacency.set(o,[]);for(let o of t.cells){let r=Yt(o),i=Rl(e,o),l=de.filter(c=>i.includes(c.name));for(let c of l){let v=De(r.col+c.dc,r.row+c.dr);t.cells.has(v)&&t.adjacency.get(o).push({key:v,dir:c.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),Il(t),$l(e,t),t.issues=Kl(e,t,{includeRoutes:!1}),t}function Il(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 c of e.adjacency.get(l)||[])e.cellToComponent.has(c.key)||(e.cellToComponent.set(c.key,o),r.push(c.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 $l(e,t){for(let n of e.scanners){let o={};for(let r of["inputA","left","right"]){let i=Re(n,r),l=r==="inputA"?i&&t.cells.has(De(i.col,i.row))?[{...i}]:[]:ti(e,i,Pt(n)).filter(x=>t.cells.has(De(x.col,x.row))),c=l.map(x=>De(x.col,x.row)),v=c.length>0;if(o[r]={type:r,cell:i,cells:l,keys:c,key:c[0]||null,connected:v},t.metrics.scannerPorts+=1,v&&(t.metrics.connectedScannerPorts+=1),r==="inputA")for(let x of c)t.scannerInputs.set(x,n.id)}t.scannerPorts.set(n.id,o)}for(let[n,o]of Object.entries(e.facilities)){if(!o.entry)continue;let r=ti(e,o.entry).filter(c=>t.cells.has(De(c.col,c.row))),i=r.map(c=>De(c.col,c.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=oi({col:n.col,row:n.row}).map(r=>De(r.col,r.row)).filter(r=>t.cells.has(r));t.farmOutputs.set(n.id,o),t.metrics.farmOutputs+=o.length}}function _e(e){let t=e.routingVersion||0;return(!e.factoryGraph||e.factoryGraph.version!==t)&&(e.factoryGraph=Al(e)),e.factoryGraph}function si(e){let t=_e(e);return e.factoryGraphCommittedVersion=t.version,e.factoryGraphSnapshot=Dl(t),t}function Dl(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 Fl(e,t){let n=t.col-e.col,o=t.row-e.row;return de.find(r=>r.dc===n&&r.dr===o)?.name||null}function Ro(e,t,n){let o=_e(e),r=De(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(le=>le.map(se=>({...se})));let l=`${r}|none`,c=[{key:r,col:t.col,row:t.row,incoming:"none",depth:0}],v=new Map([[l,0]]),x=new Map,E=[],R=1/0,B=8,O=24,ee=80;for(;c.length;){let le=c.shift();if(le.depth>R)break;let se=`${le.key}|${le.incoming}`;if(n(le)){if(E.push(se),R=le.depth,E.length>=O)break;continue}for(let A of o.adjacency.get(le.key)||[]){let G=Yt(A.key),q=Fl(le,G),me=le.depth+1;if(me>R)continue;let D=`${A.key}|${q}`,U=v.get(D);if(U==null)v.set(D,me),x.set(D,[se]),c.push({key:A.key,col:G.col,row:G.row,incoming:q,depth:me});else if(U===me){let S=x.get(D)||[];S.length{if(X.length>=ee)return;let[A]=le.split("|"),G=[Yt(A),...se];if(le===l||A===r){X.push(G);return}for(let q of x.get(le)||[])ae(q,G)};for(let le of E)ae(le,[]);let he=[],ie=new Set;for(let le of X){let se=le.map(A=>De(A.col,A.row)).join(">");ie.has(se)||(ie.add(se),he.push(le))}return n.cacheKey&&o.pathCache.set(i,he.map(le=>le.map(se=>({...se})))),he}function li(e){let t=_e(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 ai(e,t,n){let o=_e(e),r=null,i=1/0;for(let l of o.cells){let c=Z(l),v=F(c.col,c.row),x=Math.hypot(v.x-t,v.y-n);xF(o.col,o.row));return t&&n.push(t),n}function ut(e,t){t&&(!e.length||Fr(e[e.length-1],t)>1)&&e.push(t)}function Bl(e,t,n,o=null){let r=[{x:e.x,y:e.y}];ut(r,F(t.col,t.row));for(let i of Dn(n,o))ut(r,i);return r}function Ll(e,t){let n=Dn(e),o=Re(t,"inputA");return o&&ut(n,F(o.col,o.row)),ut(n,ye(t)),n}function Ol(e,t,n,o){let r=[{x:e.x,y:e.y}];ut(r,F(t.col,t.row));for(let l of Dn(n))ut(r,l);let i=Re(o,"inputA");return i&&ut(r,F(i.col,i.row)),ut(r,ye(o)),r}function Nl(e,t,n=0){let o=F(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 R=x.roleBias??0,B=E.roleBias??0;if(R!==B)return R-B;let O=x.cells?.length??x.route?.length??Number.POSITIVE_INFINITY,ee=E.cells?.length??E.route?.length??Number.POSITIVE_INFINITY;if(O!==ee)return O-ee;let X=x.key||JSON.stringify(x.route||x.cells||x),ae=E.key||JSON.stringify(E.route||E.cells||E);return X.localeCompare(ae)});if(!o||r.length===1)return r[0];let i=r[0].roleBias??0,l=r.filter(x=>(x.roleBias??0)===i),c=Math.min(...l.map(x=>ni(e,x)));l=l.filter(x=>ni(e,x)===c);let v=e.branchCounters.get(t)||0;return e.branchCounters.set(t,v+1),l[Math.floor(Math.random()*l.length)]}function ci(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 Po(e){let t=ci(e);return{left:t.left.destination,right:t.right.destination}}function Ao(e,t){return ci(e).left.match===t.sex?"left":"right"}function Io(e){return Lr(e)}function $o(e){return{mixer:"#2477ff",truck:"#ff6aa8",trash:"#22b94f","scanner-role-1":"#526456",scanner:"#526456",input:"#526456"}[e]||"#102015"}function It(e,t,n=!1){let o=_e(e),r=(o.farmOutputs.get(t.id)||[]).map(Yt),i=[];for(let v of r){let x=R=>o.scannerInputs.has(De(R.col,R.row));x.cacheKey=`farmInput:${v.col},${v.row}:v${o.version}`;let E=Ro(e,v,x);for(let R of E){let B=R[R.length-1],O=o.scannerInputs.get(De(B.col,B.row)),ee=At(e,O);ee&&i.push({key:`${ee.id}:${B.col},${B.row}:${R.length}`,scanner:ee,cells:R})}}let l=In(e,`farm:${t.id}`,i,n);if(l)return{scannerId:l.scanner.id,route:Ll(l.cells,l.scanner)};let c=In(e,`farm:${t.id}:output`,r.map(v=>({key:I(v.col,v.row),cells:[v]})),n);return c?{scannerId:null,route:Dn(c.cells)}:null}function ui(e,t,n,o,r=!1){let i=At(e,o);if(!i)return null;let c=_e(e).scannerPorts.get(i.id)?.[t],v=Re(i,t),x=c?.connected?(c.keys||[c.key]).filter(Boolean).map(Yt):[];if(!v||!x.length)return null;let E=Po(i)[t];return E==="scanner-role-1"?_l(e,i,t,n,v,x,r):Gl(e,i,t,n,v,x,E,r)}function _l(e,t,n,o,r,i,l){let c=_e(e),v=e.scanners.filter(R=>R.id!==t.id&&c.scannerPorts.get(R.id)?.inputA?.connected),x=[];for(let R of i)for(let B of v){let O=c.scannerPorts.get(B.id)?.inputA?.key;if(!O)continue;let ee=(c.scannerPorts.get(B.id)?.inputA?.keys||[O]).filter(Boolean),X=ie=>ee.includes(De(ie.col,ie.row));X.cacheKey=`toScanner:${R.col},${R.row}:${B.id}:v${c.version}`;let ae=Ro(e,R,X),he=B.role===1?0:1;for(let ie of ae)x.push({key:`${he}:start${I(R.col,R.row)}:s${B.id}:${ie.length}:${I(ie[ie.length-1].col,ie[ie.length-1].row)}`,target:B,cells:ie,roleBias:he})}let E=In(e,`scanner:${t.id}:${n}:toRole1`,x,l);return E?{destination:"scanner",nextScannerId:E.target.id,route:Ol(o,r,E.cells,E.target)}:null}function Gl(e,t,n,o,r,i,l,c){let v=_e(e),x=[...v.facilityPorts.entries()].filter(([B,O])=>O?.connected&&$n(e.facilities?.[B])===l);if(!x.length)return null;let E=[];for(let B of i)for(let[O,ee]of x){let X=(ee.keys||[ee.key]).filter(Boolean);if(!X.length)continue;let ae=ie=>X.includes(De(ie.col,ie.row));ae.cacheKey=`toFacility:${B.col},${B.row}:${O}:v${v.version}`;let he=Ro(e,B,ae);for(let ie of he)E.push({key:`start${I(B.col,B.row)}:${O}:${ie.length}:${I(ie[ie.length-1].col,ie[ie.length-1].row)}`,cells:ie,facilityId:O})}let R=In(e,`scanner:${t.id}:${n}:${l}`,E,c);return R?{destination:l,facilityId:R.facilityId,route:Bl(o,r,R.cells,gl(e,R.facilityId))}:null}function di(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=ui(e,o,ye(t),t.id,!1);if(r){if(["mixer","trash","truck"].includes(r.destination))return!0;if(r.destination==="scanner"){let i=At(e,r.nextScannerId);if(di(e,i,n))return!0}}}return!1}function Ul(e,t){return!!It(e,t,!1)?.scannerId}function Fn(e){if(e.phase!=="build")return[];let t=[];for(let n of e.eggFarms||[])Ul(e,n)||t.push({type:"eggFarm",id:n.id,ref:n,message:"This Egg will not produce chicks"});for(let n of cn)for(let[o,r]of Eo(e,n))_e(e).facilityPorts.get(o)?.connected||t.push({type:"facility",id:o,ref:r,message:"This facility cannot receive items"});return t}function Wl(e){let t=_e(e);for(let r of e.eggFarms||[]){let i=It(e,r,!1);if(!i?.scannerId)continue;let l=At(e,i.scannerId);if(di(e,l))return[]}let n=e.eggFarms?.length||0,o=[...t.facilityPorts.entries()].filter(([r,i])=>i?.connected&&["mixer","trash","truck"].includes($n(e.facilities?.[r]))).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 An(e){return e.kind==="manual"?`S${(e.slot??0)+1}`:`Auto Scanner #${e.id}`}function Kl(e,t=_e(e),n={}){let o=n.includeRoutes!==!1,r=[],i={mixer:"Mixer",trash:"Shredder",truck:"Truck"};for(let l of cn){let c=Eo(e,l);if(!c.length){r.push(`${i[l]||l} is missing`);continue}for(let[v]of c)t.facilityPorts.get(v)?.connected||r.push(`${i[l]||l} receiver has no conveyor`)}for(let l of e.scanners){let c=t.scannerPorts.get(l.id)||{};if(c.inputA?.connected||r.push(`${An(l)} input has no conveyor`),c.left?.connected||r.push(`${An(l)} left output has no conveyor`),c.right?.connected||r.push(`${An(l)} right output has no conveyor`),!!o)for(let v of["left","right"])c[v]?.connected&&!ui(e,v,ye(l),l.id)&&r.push(`${An(l)} ${v} route is incomplete`)}if(o)for(let l of e.eggFarms)It(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 fn(e){return Wl(e)}function fi(e){return fn(e).length===0}var pi=[{key:"premiumFemaleShipment",target:"female",truckTarget:"female",title:"Premium Female Shipment",route:"Female -> Truck",note:"Today only: ship female chicks to Truck. Meet the export target for a bonus.",objective:"truckTarget"},{key:"contaminantSampleExport",target:"poop",truckTarget:"poop",title:"Contaminant Sample Export",route:"Poop value x2",note:"Today only: poop is valid Truck cargo and all poop income is doubled.",objective:"truckTarget",poopValueMultiplier:2},{key:"healthInspection",title:"Health Inspection",route:"Poop -> Shredder",note:"Today only: poop mistakes are fined double. Shred enough poop for an inspection bonus.",objective:"poopTrash",poopFineMultiplier:2},{key:"conveyorJamWarning",title:"Conveyor Jam Warning",route:"No explosions",note:"Today only: jam explosions trigger at 85% congestion. Finish with zero explosions for a bonus.",objective:"noExplosion",congestionExplosionThreshold:.85,congestionWarningThreshold:.68},{key:"powerSavingOrder",title:"Power Saving Order",route:"Slow factory subsidy",note:"Today only: conveyors -20% speed and Auto Scanners +20% cooldown. A subsidy is paid at settlement.",objective:"flatBonus",conveyorSpeedMultiplier:.8,autoScannerCooldownMultiplier:1.2},{key:"overtimeDay",title:"Overtime Day",route:"80 second day",note:"Today only: the work day is longer. No extra reward or penalty.",objective:"none",daySeconds:80},{key:"shortShift",title:"Short Shift",route:"40 second day",note:"Today only: the work day is shorter. The next Fairies tribute is reduced by 10%.",objective:"none",daySeconds:40,fairiesTributeMultiplier:.9},{key:"chickBoom",title:"Chick Boom",route:"EGG interval x0.65",note:"Today only: eggs hatch faster and poop rate rises by 5 percentage points.",objective:"none",productionMultiplier:1/.65,poopRateAdd:.05},{key:"rottenFeed",title:"Rotten Feed",route:"Poop surge",note:"Today only: poop rate rises by 20 percentage points and Shredder poop income is multiplied by 1.5.",objective:"none",poopRateAdd:.2,shredderIncomeMultiplier:1.5},{key:"maintenanceAudit",title:"Maintenance Audit",route:"Durability check",note:"Today only: machines below 50% remaining durability fail the audit. Passing with none below 50% pays a bonus.",objective:"maintenanceAudit"}];function we(e,t=0){let n=Number(e);return Number.isFinite(n)?n:t}function Hl(e,t=0,n=1){let o=Math.max(1,Number(e?.turn||1)+1),r=Math.floor(Do(e)*(.08+Math.random()*.08)),i=Math.floor(Math.max(0,e.cash||0)*.25),l=Math.floor(Math.max(0,t)*Math.max(1,o)*.75);return Math.max(120,Math.ceil(Math.max(r,i,l)*n))}function yi(e){return Math.max(0,Math.ceil(500+Math.max(1,e?.turn||1)*25))}function Do(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 ql(e,t=1,n=Mt){return e.eggFarms.reduce((o,r)=>{let[i,l]=dn(r),c=Math.max(.1,(i+l)/2);return o+Math.max(1,n)/c*Math.max(.01,t||1)},0)}function Yl(e,t){let n=we(t.productionMultiplier,1),o=we(t.daySeconds,Mt),r=ql(e,n,o),i=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),l=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),c=Math.pow(1.03,i),v=ho+mo*l,x=Math.min(.95,Math.max(0,(v+we(t.poopRateAdd,0))*we(t.poopMultiplier,1)*c));return{estimate:r,poopRate:x}}function hi(e){if(e.turn+1Ar)return null;let n=pi[Math.floor(Math.random()*pi.length)],{estimate:o,poopRate:r}=Yl(e,n),i=0;n.objective==="truckTarget"?i=Math.max(1,Math.ceil(o*.3)):n.objective==="poopTrash"&&(i=Math.max(1,Math.ceil(o*r*.8)));let l=0;return["truckTarget","poopTrash","noExplosion"].includes(n.objective)&&(l=Hl(e,o)),n.objective==="flatBonus"&&(l=yi(e)),n.objective==="maintenanceAudit"&&(l=yi(e)),{id:`event-${e.turn}-${Date.now()}-${Math.floor(Math.random()*9999)}`,...n,target:n.target||null,truckTarget:n.truckTarget||null,forced:!0,productionMultiplier:we(n.productionMultiplier,1),poopMultiplier:we(n.poopMultiplier,1),poopRateAdd:we(n.poopRateAdd,0),daySeconds:we(n.daySeconds,Mt),targetAmount:i,estimatedOutput:Math.round(o),reward:l,createdTurn:e.turn,oneTurnOnly:!0}}function mi(e){e.eventActive=e.eventOffer?{...e.eventOffer}:null,e.eventOffer=null}function bi(e){e.eventActive=null}function vi(e){return Math.max(1,we(e.eventActive?.daySeconds,Mt))}function wi(e){return we(e.eventActive?.productionMultiplier,1)}function Si(e){let t=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),n=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),o=Math.pow(1.03,t),r=ho+mo*n,i=we(e.eventActive?.poopRateAdd,0);return Math.min(.95,Math.max(0,(r+i)*we(e.eventActive?.poopMultiplier,1)*o))}function je(e){return e.eventActive?.truckTarget||e.eventActive?.target||"female"}function Fo(e,t){return t==="male"?e.truckMale||0:t==="poop"?e.poopTruck||0:e.truckFemale||0}function ki(e,t){return je(e)===t}function Ci(e){return je(e)!=="male"}function Bo(e){return Math.max(.01,we(e.eventActive?.poopValueMultiplier,1))}function Bn(e){return Math.max(.01,Bo(e)*we(e.eventActive?.shredderIncomeMultiplier,1))}function Lo(e){return Math.max(.01,we(e.eventActive?.poopFineMultiplier,1))}function Oo(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionExplosionThreshold,1)))}function xi(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionWarningThreshold,.8)))}function Mi(e){return Math.max(.01,we(e?.fairiesTributeMultiplier,1))}function Vl(e){let t=0,n=(o,r)=>{let i=Math.max(1,we(r,1)),l=Math.max(0,we(o,0));1-Math.min(1,l/i)<.5&&(t+=1)};for(let o of e.conveyorMeta?.values?.()||[])n(o.uses,o.durability);for(let o of e.eggFarms||[])n(o.maintenance?.uses,o.maintenance?.durability);for(let o of e.scanners||[])o.kind==="auto"&&n(o.maintenance?.uses,o.maintenance?.durability);for(let o of Object.values(e.facilities||{})){let r=o?.baseId||o?.id;(r==="mixer"||r==="trash")&&n(o.maintenance?.uses,o.maintenance?.durability)}return t}function gi(e){let t=e.eventActive;if(!t)return null;let n=0,o=!0,r=0,i="";t.objective==="truckTarget"?(n=Fo(e.stats,t.target),o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="poopTrash"?(n=e.stats.poopTrash||0,o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="noExplosion"?(n=e.stats.explosions||0,o=n===0,r=o?t.reward:0,i=`${n} explosion(s)`):t.objective==="flatBonus"?(o=!0,r=t.reward):t.objective==="maintenanceAudit"?(n=Vl(e),o=n===0,o&&(r=t.reward),i=`${n} machine(s) below 50%`):o=!0,r>0?(Ge(e,r),e.stats.eventBonus=(e.stats.eventBonus||0)+r,e.totals.eventBonus+=r,e.totals.eventSuccess+=1):t.objective&&t.objective!=="none"&&(e.stats.eventBonus=e.stats.eventBonus||0,e.totals.eventFailed+=o?0:1,o&&(e.totals.eventSuccess+=1));let l={title:t.title,key:t.key,target:t.target,route:t.route,objective:t.objective,targetAmount:t.targetAmount||0,count:n,success:o,bonus:r,reward:t.reward||0,productionMultiplier:t.productionMultiplier,poopMultiplier:t.poopMultiplier,daySeconds:t.daySeconds,detail:i};return e.stats.eventResult=l,l}function No(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function zl(e){return!!e?.cardEffects?.usedMachineActive}function Xl(e,t){return t?1:Math.min(.8,.5+.1*Math.min(3,No(e,"recyclingSubsidy")))}function Ql(e){return Math.pow(.95,No(e,"safetyCover"))}function Ln(e){let t=e?.ref||e||{},n=e?.type||t.type;return n==="conveyor"?t.price||ve[t.kind]?.price||ve.conveyor.price:n==="eggFarm"?t.price||ve.eggFarm.price:n==="scanner"?t.price||(t.kind==="auto"?ve.autoScanner.price:ve.manualScanner.price):n==="facility"?t.price||ve[t.id]?.price||0:n==="maintenanceRoom"?t.price||ve.maintenanceRoom.price:ve[t.id]?.price||0}function Oe(e,t=null){let n=ve[e]?.price||0;return zl(t)?Math.ceil(n*.5):n}function Jl(e,t){return e?.facilities?Object.values(e.facilities).filter(n=>(n?.baseId||n?.id)===t).reduce((n,o)=>n+Math.max(0,(o.level||1)-1),0):0}function pt(e,t){return $r.includes(t)?Math.pow(Ce.incomeUpgradeRate,Jl(e,t)):1}function ze(e){return Math.ceil(Ce.income.mixer*pt(e,"mixer"))}function Fe(e){return Math.ceil(Ce.income.truck*pt(e,"truck"))}function pn(e){return Math.ceil(Ce.poopFine*pt(e,"mixer")*Lo(e))}function yn(e){return Math.ceil(Ce.poopFine*pt(e,"truck")*Lo(e))}function _o(e){let t=Ce.maleTruckFinePerHalfDay*(e.turn/2);return Math.ceil(t*pt(e,"truck"))}function Go(e){return e?.facilities?Object.values(e.facilities).filter(t=>(t?.baseId||t?.id)==="trash").reduce((t,n)=>t+Math.max(0,(n.level||1)-1),0):0}function $t(e){return Math.min(Ce.shredderBonus.maxCards,Go(e))}function Vt(){return Ce.shredderBonus.maxCards}function yt(e){let t=typeof e=="number"?e:$t(e),n=Math.min(Ce.shredderBonus.maxCards,Math.max(0,t));return n>0?Math.ceil(n*(Ce.shredderBonus.incomePerUpgrade||1)):0}function jl(e){let t=$t(e),n=yt(t),o=Math.ceil(n*Bn(e));return{cards:t,chance:o>0?1:0,amount:o,expected:o,baseAmount:n}}function Ti(e){let t=jl(e);return t.amount>0&&(e.stats.shredderBonus=(e.stats.shredderBonus||0)+t.amount,e.totals.shredderBonus=(e.totals.shredderBonus||0)+t.amount,Ge(e,t.amount)),t}function On(e,t=e.turn,n=null){let o=Math.max(1,Math.floor(Number(t)||1)),r=Ce.fairiesTribute||{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},i=Math.ceil(o*(r.perDay||10)),l=Math.max(0,Math.floor(Number(n??e?.lastResult?.profit??e?.stats?.profit??0)||0)),c=Math.max(0,e?.cardEffects?.legalWork||0),v=Math.max(0,(r.profitExemption||0)+c*(r.legalWorkExemptionBonus||0)),x=Math.max(0,l-v),E=Math.ceil(x*Math.max(0,Number(r.profitRate)||0)),R=i+E,B=Math.max(0,e?.cardEffects?.fairiesFlatteryNext||e?.cardEffects?.flattery||0),O=B>0?Math.pow(.5,B):1,ee=Math.max(.01,Number(e?.pendingFairiesTributeMultiplier)||1),X=O*ee,ae=Math.max(0,Math.ceil(R*X)),he=Math.max(0,R-ae);return{day:o,base:i,profit:l,legalWork:c,profitExemption:v,taxableProfit:x,profitTribute:E,gross:R,flatteryCount:B,eventMultiplier:ee,perCardReduction:Math.ceil(R*.5),reduction:he,amount:ae}}function ht(e,t){let n=e?.ref||e||{},o=e?.type==="conveyor"?t?.conveyorMeta?.get(e.oldKey||n.id):n,r=o?.price||Ln(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=Xl(t,i);return{amount:Math.max(0,Math.ceil(r*l)),sameBuild:i,price:r,rate:l,noRefund:!1}}function Zl(e,t=null){let n=Math.max(1,Math.ceil((Number(e)||0)/Ce.explosionDamageDivisor));return Math.max(1,Math.ceil(n*Ql(t)))}function ea(e,t){return Math.max(0,Math.ceil(t))}function Ei(e,t){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 Ge(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Ei(e,n),n}function mt(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Ei(e,-n),n}function Dt(e,t){mt(e,t)}function Ri(e,t){t<=0||(e.cash+=t,e.stats.profit+=t,e.totals.profit+=t,e.totals.maxCash=Math.max(e.totals.maxCash,e.cash))}function Pi(e){let t=ze(e);return e.stats.mixerRevenue+=t,Ge(e,t),t}function Ai(e){let t=pn(e);return e.stats.mixerPoopFine+=t,e.totals.mixerPoopFine+=t,mt(e,t),t}function Ii(e){let t=yn(e);return e.stats.truckPoopFine+=t,e.totals.truckPoopFine+=t,mt(e,t),t}function $i(e){let t=_o(e);return e.stats.maleTruckFine+=t,e.totals.maleTruckFine+=t,mt(e,t),t}function Di(e,t){let n=Zl(t,e);return e.stats.explosionDamage+=n,e.totals.explosionDamage+=n,mt(e,n),n}function Fi(e){let t=je(e),n=Fo(e.stats,t),o=t==="poop"?Math.ceil(Fe(e)*Bo(e)):Fe(e),r=n*o,i=ea(e,r);return e.stats.pendingTruckRevenue=i,e.stats.truckRevenue=i,t==="poop"?e.stats.poopShipmentIncome=i:e.stats.chickShipmentIncome=i,i>0&&Ge(e,i),{base:r,adjusted:i,target:t,targetCount:n,unitPrice:o}}function Bi(e,t=e.turn,n=null,o={}){let r=On(e,t,n);return e.cardEffects&&(e.cardEffects.fairiesFlatteryNext=0,e.cardEffects.flattery!=null&&delete e.cardEffects.flattery),e.pendingFairiesTributeMultiplier!=null&&(e.pendingFairiesTributeMultiplier=1),r.amount<=0||(o.recordStats?(e.stats.fairiesTribute=(e.stats.fairiesTribute||0)+r.amount,e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,mt(e,r.amount)):(e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,e.totals.penalty=(e.totals.penalty||0)+r.amount,e.totals.profit=(e.totals.profit||0)-r.amount,e.cash-=r.amount)),r}function Li(e){let t=No(e,"chemicalWeaponSubsidy"),n=Math.max(0,e?.stats?.poopTruck||0),o=Ce.chemicalWeaponSubsidy||{poopPerBlock:70,yenPerBlock:1200},r=Math.floor(n/Math.max(1,o.poopPerBlock||70)),i=t>0&&r>0?r*Math.max(0,o.yenPerBlock||1200)*t:0;return i>0&&(e.stats.chemicalWeaponSubsidy=(e.stats.chemicalWeaponSubsidy||0)+i,e.totals.chemicalWeaponSubsidy=(e.totals.chemicalWeaponSubsidy||0)+i,Ge(e,i)),{cards:t,poopTruck:n,blocks:r,amount:i}}function Oi(e){let t=Do(e),n=Math.max(1,e.totals.turnsCompleted||e.turn||1),o=Math.max(0,e.cash+e.totals.revenue+t*.5+e.totals.eventBonus*.5),r=Math.ceil(o/n),i=Math.floor(n*35+Math.max(0,n-5)*15),l=e.totals.correct*5,c=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:c,days:n}}function ta(e){return{...e,keys:e.keys?{left:{...e.keys.left},right:{...e.keys.right}}:null,queue:[],cooldown:e.cooldown||0}}function hn(e){return JSON.stringify({cash:e.cash,stats:e.stats,totals:e.totals,nextId:e.nextId,gridX:f.x,gridY:f.y,gridCols:e.gridCols||f.cols,gridRows:e.gridRows||f.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(ta),conveyorTiles:[...e.conveyorTiles],conveyorMeta:[...e.conveyorMeta.entries()],branchCounters:[...e.branchCounters.entries()],cardEffects:e.cardEffects,cardDraft:e.cardDraft,cardTargetPick:e.cardTargetPick})}function Ni(e,t){let n=JSON.parse(t);e.cash=n.cash,e.stats=n.stats,e.totals=n.totals,e.nextId=n.nextId,f.x=n.gridX??Y.grid.x,f.y=n.gridY??Y.grid.y,f.cols=n.gridCols||Y.grid.cols,f.rows=n.gridRows||Y.grid.rows,e.gridCols=f.cols,e.gridRows=f.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||f.cols*f.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,fairiesFlatteryNext:0,scannerQueueSpacing: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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=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 Be(e){e.phase==="build"&&(e.undoStack.push(hn(e)),e.undoStack.length>80&&e.undoStack.shift(),e.redoStack=[])}function Uo(e){return e.phase!=="build"||!e.undoStack.length?!1:(e.redoStack.push(hn(e)),Ni(e,e.undoStack.pop()),!0)}function Wo(e){return e.phase!=="build"||!e.redoStack.length?!1:(e.undoStack.push(hn(e)),Ni(e,e.redoStack.pop()),!0)}function H(e,t,n,o,r=p.ink){e.floatingTexts.push({x:t,y:n,text:o,color:r,life:1,maxLife:1})}function Ft(e,t,n){e.shake.strength=Math.max(e.shake.strength,t),e.shake.time=Math.max(e.shake.time,n)}function _i(e,t,n){e.effects.push({type:"spawn",priority:xe.ambient,x:t,y:n,life:.42,maxLife:.42,size:12})}function Gi(e,t,n,o=p.green){e.effects.push({type:"scannerPulse",priority:xe.important,x:t,y:n,color:o,life:.42,maxLife:.42,size:24})}function Ui(e,t,n){for(let o=0;o<12;o+=1)e.effects.push({type:"meat",priority:xe.important,x:t+W(-18,18),y:n+W(-12,16),vx:W(-60,60),vy:W(-90,-25),life:W(.45,.85),maxLife:.85,size:W(4,8)})}function Wi(e,t,n){for(let o=0;o<16;o+=1)e.effects.push({type:"sludge",priority:xe.important,x:t+W(-18,18),y:n+W(-12,16),vx:W(-46,46),vy:W(-70,-20),life:W(.45,.9),maxLife:.9,size:W(4,8)})}function Ki(e,t,n,o){let r=o==="poop"?p.poop:o==="male"?p.male:p.female;for(let i=0;i<22;i+=1)e.effects.push({type:"shred",priority:xe.important,x:t+W(-16,16),y:n+W(-8,8),vx:W(-70,70),vy:W(40,160),color:i%3===0?p.white:r,life:W(.45,.95),maxLife:.95,w:W(3,7),h:W(10,24),rot:W(-Math.PI,Math.PI)});Xe(e,t,n,p.green,34,xe.important)}function Hi(e,t,n,o){let r=o==="poop"?p.poop:o==="male"?p.danger:p.green;for(let i=0;i<8;i+=1)e.effects.push({type:"load",priority:xe.important,x:t+W(-18,18),y:n+W(-18,18),vx:W(-42,42),vy:W(-90,-25),color:r,life:W(.35,.65),maxLife:.65,size:8})}function Xe(e,t,n,o=p.danger,r=52,i=xe.critical){e.effects.push({type:"shockwave",priority:i,x:t,y:n,color:o,life:.55,maxLife:.55,size:8,maxSize:r})}function Ze(e,t,n,o=12,r=p.danger,i=xe.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||na(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 na(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=Di(e,o.price);H(e,t.x,t.y-10,`-${g(r)}`,p.danger),Xe(e,t.x,t.y,p.danger,30),Ze(e,t.x,t.y,5,p.danger),Ft(e,5,.18)}}var Ue=Y.maintenance;function Ho(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Gn(e){let t=Math.min(1.4,1+.04*Math.min(10,Ho(e,"crowdedFarming"))),n=Math.pow(.95,Ho(e,"preventiveMaintenance"));return t*n}function oa(e){return Math.pow(1.03,Ho(e,"durabilityCoating"))}function Un(e,t,n=1){let o=Ue.durability[t]||1e3;return Math.max(1,Math.ceil(o*Math.max(.1,n||1)*oa(e)))}function Vi(e){return Math.max(.1,Number(e?.durabilityBaseMultiplier)||1)}function ra(e,t=0){if(!e)return{x:f.x+f.cell*(.5+t*.55),y:f.y+f.rows*f.cell+84};let n=f.x+e.col*f.cell+f.cell,o=f.y+e.row*f.cell+f.cell;return{x:n,y:o}}function ia(e,t=0){let n=(e.maintenanceRooms||[])[t];return ra(n,t)}function Se(e){e.repairman||(e.repairman={active:!1,x:f.x+f.cell*.5,y:f.y+f.rows*f.cell+84,target:null,repairedToday:0}),Array.isArray(e.maintenanceRooms)||(e.maintenanceRooms=[]),Array.isArray(e.repairmen)||(e.repairmen=[]);for(let[t,n]of e.conveyorMeta||[]){n.uses==null&&(n.uses=0),n.maintenanceType==null&&(n.maintenanceType="conveyor"),n.kind||(n.kind="conveyor"),n.speedMultiplier||(n.speedMultiplier=n.kind==="boostConveyor"?2:1),n.branchMode||(n.branchMode="random");let o=Un(e,"conveyor",Vi(n));(n.durability==null||n.durability0&&(n.processingCooldown=Math.max(0,n.processingCooldown-t))}function vn(e){Se(e);let t=[];for(let[n,o]of e.conveyorMeta||[])t.push({type:"conveyor",key:n,meta:o,label:`${o.kind==="boostConveyor"?"Boost Belt":"Belt"} ${n}`,center:F(Z(n).col,Z(n).row)});for(let n of e.eggFarms||[])t.push({type:"eggFarm",ref:n,label:`EGG #${n.id}`,center:F(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:F(n.col,n.row)});for(let n of Object.values(e.facilities||{})){let o=qn(n);["mixer","trash"].includes(o)&&t.push({type:o,ref:n,label:`${n.shortName||n.name||o} #${n.id}`,center:{x:n.x+n.w/2,y:n.y+n.h/2}})}return t}function Bt(e){return e.meta?zt(e):zt(e.ref)}function mn(e){return e.meta?qo(e):qo(e.ref)}function _n(e){return e.meta?Yo(e):Yo(e.ref)}function ji(e,t){sa(e.meta?e:e.ref,Math.max(0,mn(e)-t))}function er(e){return e.type==="conveyor"?`conveyor:${e.key}`:`${e.type}:${e.ref?.id||e.ref?.type||e.type}`}function Zi(e,t=.02){Se(e);let n=Math.max(0,Number(t)||0),o=0;for(let r of vn(e)){let i=mn(r);ji(r,_n(r)*n),o+=Math.max(0,i-mn(r))/_n(r)*100}return o}function es(e){Se(e);let t=e.maintenanceRooms||[];e.repairmen=t.map((o,r)=>{let i=ia(e,r);return{id:`room-${o.id}`,roomId:o.id,active:!0,x:i.x,y:i.y,target:null,repairedToday:0}});let n=e.repairmen[0];e.repairman.active=!!n,e.repairman.target=n?.target||null,e.repairman.repairedToday=0,n&&(e.repairman.x=n.x,e.repairman.y=n.y)}function ts(e){Se(e);for(let t of e.repairmen||[])t.active=!1,t.target=null;e.repairmen=[],e.repairman.active=!1,e.repairman.target=null}function aa(e,t){return t&&vn(e).find(o=>er(o)===t.key)||null}function ca(e){let t=null;for(let n of vn(e)){let o=Bt(n);o<=.001||(!t||o>Bt(t))&&(t=n)}return t}function ns(e,t){Se(e);let n=e.repairmen?.length?e.repairmen:e.repairman?.active?[e.repairman]:[];if(!n.length||e.phase!=="running")return;let o=new Set(n.map(i=>i.target?.key).filter(Boolean));for(let i of n)ua(e,i,t,o);let r=n[0];r&&e.repairman!==r&&(e.repairman.active=!0,e.repairman.x=r.x,e.repairman.y=r.y,e.repairman.target=r.target,e.repairman.repairedToday=r.repairedToday||0)}function ua(e,t,n,o){if(!t.active)return;let r=aa(e,t.target);if((!r||Bt(r)<=.001)&&(t.target?.key&&o.delete(t.target.key),r=da(e,o)),!r){t.target=null;return}let i=er(r);o.add(i),t.target={key:i,label:r.label};let l=Ue.repairman.walkSpeed,c=r.center.x-t.x,v=r.center.y-t.y,x=Math.hypot(c,v);if(x>8){let X=Math.min(x,l*n);t.x+=c/x*X,t.y+=v/x*X;return}let E=e?.cardEffects?.laborExploitation?.7:1,R=n/(Ue.repairman.secondsPerOnePercent*E*100),B=mn(r),O=R*_n(r);ji(r,O);let ee=Math.max(0,(B-mn(r))/_n(r)*100);t.repairedToday=(t.repairedToday||0)+ee,ee>0&&Math.random()<.02&&H(e,t.x,t.y-28,"REPAIR",p.green),Bt(r)<=.001&&(o.delete(i),t.target=null)}function da(e,t=new Set){let n=null;for(let o of vn(e)){if(t.has(er(o)))continue;let r=Bt(o);r<=.001||(!n||r>Bt(n))&&(n=o)}return n||ca(e)}function fa(e){let t=0,n="none";for(let o of vn(e)){let r=Bt(o);r>t&&(t=r,n=o.label)}return{ratio:t,percent:Math.round(t*100),label:n}}function tr(e){let t=fa(e),n=zo(e);return{worst:t,avgBeltPerformance:n,repairman:e.repairman||null,repairmen:e.repairmen||[],rooms:e.maintenanceRooms||[]}}var pa=$e.commonWeight,ya=$e.rareWeight,ha=$e.ultraRareWeight||.45,Lt=$e.baseDraftSize,Qt=Ir;function Xt(e,t){let n=Le(e);return Math.max(0,Number(n[t])||0)}function Le(e){e.cardEffects||(e.cardEffects={...bo});for(let[t,n]of Object.entries(bo))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),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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=0),e.cardEffects}function us(e){let t=Math.max(.5,1-.05*Math.min(10,Xt(e,"crowdedFarming"))),n=Math.pow(.96,Xt(e,"hatchingFeed"));return t*n}function ds(e,t=null){return Math.min(3,Math.max(0,Number(t?.extraEggOutlet)||0))}function fs(e){return Math.pow(.85,Xt(e,"scannerQueueSpacing"))}function Vn(e,t=null){let n=Le(e),o=Mn*Math.pow(gn,Math.max(0,n.bearing||0)),r=t?Math.max(.1,Number(e?.conveyorMeta?.get?.(t)?.speedMultiplier)||1):1,i=t?1:zo(e),l=Math.max(.01,Number(e?.eventActive?.conveyorSpeedMultiplier)||1);return Math.min(Wt,o*i)*r*l}function nt(e,t=null){let n=Math.max(0,(e?.level||1)-1),o=t?Xt(t,"autoScannerTuning"):0,r=xn*Math.pow(Pr,n)*Math.pow(po,o),i=Math.max(yo,r),l=t?Math.max(.01,Number(t?.eventActive?.autoScannerCooldownMultiplier)||1):1;return t?Math.max(yo,i*Kn(e)*l):i}function os(e){let t=e.cardDraft||{rerolls:0},n=Math.max(1,(t.rerolls||0)+1);return Math.ceil(Math.max(1,e.turn||1)/$e.rerollCost.dayDivisor*n*$e.rerollCost.multiplier)}function Jt(e){return Qt.find(t=>t.id===e)||null}function ps(e,t){let n=typeof t=="string"?Jt(t):t;return Le(e),!n||!(n.type==="equipmentUpgrade"||n.type==="cellAction")?[]:We(e,n).map(o=>({key:tt(o),label:rr(e,o),type:o.type}))}function or(e,t,n={}){let o=typeof t=="string"?Jt(t):t;if(Le(e),!o||o.type==="dud")return{ok:!1,reason:"Card not found."};if(o.id==="extraCards")return e.cardDraft=e.cardDraft||{pending:!1,choices:[],rerolls:0,picksRemaining:0},e.cardDraft.choices.push(...Yn(e,2)),{ok:!0,reason:`${o.title} added 2 draft cards.`};if(o.type==="instant")return hs(e,o),{ok:!0,reason:`${o.title} granted.`};if(o.type==="equipmentUpgrade"){let r=We(e,o);if(!r.length)return{ok:!1,reason:`No valid target for ${o.title}.`};let i=n.targetKey&&n.targetKey!=="__auto__"?String(n.targetKey):"",l=i?r.find(c=>tt(c)===i):r[0];return l?(ys(e,l),{ok:!0,reason:`${o.title} applied to ${rr(e,l)}.`}):{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`}}if(o.type==="cellAction"&&o.target==="blockedCell"){let r=We(e,o);if(!r.length)return{ok:!1,reason:"No blocked cells to remove."};let i=new Set((Array.isArray(n.targetKeys)?n.targetKeys:[n.targetKey]).filter(c=>c&&c!=="__auto__").map(String)),l=i.size?r.filter(c=>i.has(tt(c))):r.slice(0,3);if(!l.length)return{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`};for(let c of l.slice(0,3)){e.blockedCells.delete(I(c.col,c.row));let v=F(c.col,c.row);et(e,v.x,v.y),Xe(e,v.x,v.y,p.danger,42),Ze(e,v.x,v.y,8,p.warn)}return be(e),{ok:!0,reason:`${o.title} removed ${Math.min(3,l.length)} blocked cell(s).`}}return{ok:!1,reason:`${o.title} cannot be debug-granted.`}}function rr(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 ${nt(t,e).toFixed(1)}s -> ${nt({...t,level:t.level+1},e).toFixed(1)}s`;if(t.type==="facility"&&(t.baseId||t.id)==="mixer"){let n=t.level,o=ze(e);t.level=n+1;let r=ze(e);return t.level=n,`MIXER L${t.level} -> L${t.level+1} | ${g(o)} -> ${g(r)}`}if(t.type==="facility"&&(t.baseId||t.id)==="truck"){let n=t.level,o=Fe(e);t.level=n+1;let r=Fe(e);return t.level=n,`TRUCK L${t.level} -> L${t.level+1} | ${g(o)} -> ${g(r)}`}if(t.type==="facility"&&t.id==="trash"){let n=$t(e),o=Math.min(Vt(),n+1),r=yt(n),i=yt(o);return`SHREDDER L${t.level||1} -> L${(t.level||1)+1} | poop income ${g(r)} -> ${g(i)} per item`}return`${t.name||t.id} L${t.level||1} -> L${(t.level||1)+1}`}function ma(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 We(e,t){let n=typeof t=="string"?Jt(t):t;return Le(e),n?n.target==="blockedCell"?ma(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"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="mixer"):n.target==="truck"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="truck"):n.target==="trash"?Go(e)(o.baseId||o.id)==="trash"):[]:[]:[]}function ba(e,t){let n=Le(e);if(t.id==="crowdedFarming")return(n.crowdedFarming||0)>=10;if(t.id==="recyclingSubsidy")return(n.recyclingSubsidy||0)>=3;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,$e.dudChancePerCard||0)),r=Math.max(1e-4,Math.min(1,$e.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 va(e){return!!((e.maintenanceRooms||[]).length||(e.repairmen||[]).length||e.repairman?.active)}function wa(e){return Qt.filter(t=>!(t.id==="laborExploitation"&&!va(e)||ba(e,t)||(t.type==="equipmentUpgrade"||t.type==="cellAction")&&We(e,t).length<=0))}function rs(e,t){return t.rarity==="ultraRare"?ha:t.rarity==="rare"?ya:pa}function Sa(e,t){let n=t.reduce((r,i)=>r+rs(e,i),0);if(n<=0)return t[Math.floor(Math.random()*t.length)];let o=Math.random()*n;for(let r of t)if(o-=rs(e,r),o<=0)return r;return t[t.length-1]}var is=0;function ka(){return is+=1,{id:`dud:${Date.now()}:${is}`,title:"Dud",rarity:"dud",type:"dud",description:"Click to flick this dud away. It does not consume a pick."}}function Ca(e){let t=Le(e),n=Math.max(0,Math.min(1,$e.dudChancePerCard||0)),o=Math.max(0,Math.min(1,$e.dudChanceReductionPerFilter||0));return Math.max(0,n-o*Math.max(0,t.dudFilter||0))}function xa(e,t){let n=[...t],o=0,r=Math.max(0,$e.maxDudsPerDraft||0),i=Ca(e);for(let l=0;lc.id===i.id);l>=0&&r.splice(l,1)}return xa(e,o)}function tt(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 ss(e){if(!e)return null;if(e.type==="blockedCell"){let t=F(e.col,e.row);return{x:t.x-f.cell*.48,y:t.y-f.cell*.48,w:f.cell*.96,h:f.cell*.96,cx:t.x,cy:t.y}}if(e.type==="eggFarm"||e.type==="eggOutlet"){let t=F(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=ye(e);return{x:t.x-54,y:t.y-77,w:108,h:154,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 ir(e){if(!e.cardTargetPick?.pending)return[];if(e.cardTargetPick.mode==="autoScannerMenu"){let n=new Set(e.cardTargetPick.targetKeys||[]);return e.scanners.filter(o=>o.kind==="auto"&&n.has(tt(o))).map(o=>({key:tt(o),label:"AUTO ROUTE SETTINGS",target:o,bounds:ss(o)})).filter(o=>o.bounds)}let t=new Set(e.cardTargetPick.targetKeys||[]);return We(e,e.cardTargetPick.cardId).filter(n=>t.has(tt(n))).map(n=>({key:tt(n),label:rr(e,n),target:n,bounds:ss(n)})).filter(n=>n.bounds)}function Ma(e,t){let n=ir(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 ys(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=F(n.col,n.row);H(e,o.x,o.y-30,`OUTLET ${1+n.extraEggOutlet}`,p.green),be(e);return}if(t.level=(t.level||1)+1,t.type==="eggFarm"){t.nextSpawn=Rt(t),t.lastInterval=t.nextSpawn;let n=F(t.col,t.row);H(e,n.x,n.y-30,`LV ${t.level}`,p.green);return}if(t.type==="scanner"){let n=ye(t);H(e,n.x,n.y-34,`LV ${t.level}`,p.green);return}t.type==="facility"&&H(e,t.x+t.w/2,t.y+18,`LV ${t.level}`,p.green)}function hs(e,t){let n=Le(e),o=r=>{n[r]=Math.max(0,n[r]||0)+1};if(t.id==="bearing"&&o("bearing"),t.id==="autoScannerTuning"&&o("autoScannerTuning"),t.id==="legalWork"&&o("legalWork"),t.id==="crowdedFarming"&&(n.crowdedFarming=Math.min(10,(n.crowdedFarming||0)+1)),t.id==="hatchingFeed"&&o("hatchingFeed"),t.id==="poopRateBooster"&&o("poopRateBooster"),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"),Se(e)),t.id==="sparePartsBin"){o("sparePartsBin");let r=Zi(e,.02);e.stats.sparePartsRepair=(e.stats.sparePartsRepair||0)+r,e.totals.sparePartsRepair=(e.totals.sparePartsRepair||0)+r,H(e,f.x+f.cols*f.cell/2,f.y-30,"REPAIR +2%",p.green)}t.id==="dudRefund"&&o("dudRefund"),t.id==="freeReroll"&&o("freeReroll"),t.id==="composter"&&o("composter"),t.id==="scannerQueueSpacing"&&o("scannerQueueSpacing"),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"),H(e,f.x+f.cols*f.cell/2,f.y-30,"RESCUE HELD",p.green))}function He(e){return`${Math.round(Number(e||0)*100)}%`}function ls(e){let t=st[Math.max(0,Math.min(st.length-1,e-1))]||st[0]||[0,0];return`${t[0].toFixed(2)}-${t[1].toFixed(2)}s`}function as(e,t){return Math.ceil(e*Math.pow(Ce.incomeUpgradeRate,Math.max(0,t-1)))}function cs(e,t,n){let r=We(e,t==="mixer"?"upgradeMixer":"upgradeTruck")[0];if(!r)return{before:as(n,1),after:as(n,2)};let i=t==="mixer"?ze(e):Fe(e),l=r.level||1;r.level=l+1;let c=t==="mixer"?ze(e):Fe(e);return r.level=l,{before:i,after:c}}function ga(e,t){let n=Le(e);if(t.id==="upgradeEgg"){let o=We(e,t),r=Math.min(3,Math.max(1,o[0]?.level||1));return`Choose one EGG. Level +1. Production interval ${ls(r)} -> ${ls(r+1)}.`}if(t.id==="upgradeAutoScanner"){let o=We(e,t)[0]||{level:1},r=nt(o,e),i=nt({...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=cs(e,"mixer",Ce.income.mixer);return`Choose one MIXER. Earning +10%. Male-chick income ${g(o.before)} -> ${g(o.after)}.`}if(t.id==="upgradeTruck"){let o=cs(e,"truck",Ce.income.truck);return`Choose one TRUCK. Earning +10%. Correct shipment income ${g(o.before)} -> ${g(o.after)}.`}if(t.id==="upgradeTrash"){let o=$t(e),r=Math.min(Vt(),o+1),i=yt(o),l=yt(r);return`SHREDDER level +1. Poop income ${g(i)} -> ${g(l)} per item.`}if(t.id==="bearing"){let o=Math.min(Wt,Mn*Math.pow(gn,Math.max(0,n.bearing||0))),r=Math.min(Wt,Mn*Math.pow(gn,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`Fairies tribute profit exemption +${g(250)}. After pick: exemption bonus ${g(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 ${He(Math.max(.5,1-.05*o))}, deterioration ${He(Math.min(1.4,1+.04*o))}.`}if(t.id==="extraEggOutlet"){let o=We(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 ${He(Math.pow(.96,(n.hatchingFeed||0)+1))}, poop rate multiplier ${He(Math.pow(1.03,(n.hatchingFeed||0)+1))}.`;if(t.id==="poopRateBooster")return`Held ${n.poopRateBooster||0}. After pick: base poop rate +${Math.round((n.poopRateBooster||0)+1)*4} percentage points.`;if(t.id==="autoScannerTuning")return`Held ${n.autoScannerTuning||0}. After pick: all AUTO SCANNER default cooldown ${He(Math.pow(po,(n.autoScannerTuning||0)+1))}.`;if(t.id==="safetyCover")return`Held ${n.safetyCover||0}. After pick: explosion damage ${He(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: ${g(1200*((n.chemicalWeaponSubsidy||0)+1))} per 70 truck-shipped poop each day.`;if(t.id==="preventiveMaintenance")return`Held ${n.preventiveMaintenance||0}. After pick: deterioration speed ${He(Math.pow(.95,(n.preventiveMaintenance||0)+1))}.`;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,$e.dudChancePerCard||0)),r=Math.max(0,Math.min(1,$e.dudChanceReductionPerFilter||.05)),i=Math.max(0,n.dudFilter||0),l=Math.max(0,o-r*i),c=Math.max(0,o-r*(i+1));return`Held ${i}. DUD chance per card ${He(l)} -> ${He(c)}.`}return t.id==="durabilityCoating"?`Held ${n.durabilityCoating||0}. After pick: maximum durability ${He(Math.pow(1.03,(n.durabilityCoating||0)+1))}.`:t.id==="sparePartsBin"?`Held ${n.sparePartsBin||0}. Immediately restores 2% durability to every maintained machine. Common card weight.`:t.id==="dudRefund"?`Held ${n.dudRefund||0}. After pick: DUD clicks award ${g(50*((n.dudRefund||0)+1))}.`:t.id==="freeReroll"?`Held ${n.freeReroll||0}. After pick: each card screen starts with ${(n.freeReroll||0)+1} free reroll${(n.freeReroll||0)+1===1?"":"s"}.`:t.id==="composter"?`Held ${n.composter||0}. After pick: SHREDDER poop grants ${g(3*((n.composter||0)+1))}.`:t.id==="scannerQueueSpacing"?`Held ${n.scannerQueueSpacing||0}. After pick: Manual/Auto Scanner queue spacing ${He(Math.pow(.85,(n.scannerQueueSpacing||0)+1))}.`:t.id==="flattery"?`Next Fairies tribute -50%. Held for next tribute: ${n.fairiesFlatteryNext||0}.`:t.id==="usedMachine"?"Enable Used Machines: future equipment costs 50%, has no SELL refund, and starts with 60% durability.":t.id==="newMachine"?"Cancel Used Machines. Future equipment returns to normal price, refund, and durability.":t.id==="laborExploitation"?"Repairman dispatch paperwork is streamlined. Repair rooms keep operating; one time only.":t.id==="rescueLoan"?`At day-end bankruptcy check, gain ${g(500)} if cash is below ${g(0)}. Held: ${n.rescueLoanCharges||0}.`:t.description}function nr(e,t){let n=e.cardDraft?.choices||[],o=n.findIndex(r=>r.id===t.id);o>=0&&n.splice(o,1)}function ms({game:e,ui:t,onUpdatePanels:n}){function o(){n&&n()}function r(){Le(e),e.cardTargetPick=null,e.cardDraft={pending:!0,choices:Yn(e,Lt),rerolls:0,freeRerolls:Xt(e,"freeReroll"),picksRemaining:1}}function i(){Le(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(A=Lt){Le(e),e.cardDraft.choices=Yn(e,A)}function c(){Le(e),!e.cardDraft.choices.length&&e.cardDraft.picksRemaining>0&&l(Lt)}function v(A){nr(e,A),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1),e.cardTargetPick=null,c(),e.cardDraft.picksRemaining<=0?i():se()}function x(A){nr(e,A),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1)+$e.extraCardsAddedPicks,e.cardDraft.choices.push(...Yn(e,2)),se()}function E(A,G){let q=Xt(e,"dudRefund")*50;if(q>0){let me=Ge(e,q);e.stats.dudRefundIncome=(e.stats.dudRefundIncome||0)+me,e.totals.dudRefundIncome=(e.totals.dudRefundIncome||0)+me,H(e,f.x+f.cols*f.cell/2,f.y-30,`DUD REFUND +${g(me)}`,p.green)}Ft(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)"}),G&&(G.style.setProperty("--fling-x",`${260+Math.random()*260}px`),G.style.setProperty("--fling-y",`${-260-Math.random()*170}px`),G.style.setProperty("--fling-r",`${(Math.random()<.5?-1:1)*(52+Math.random()*38)}deg`),G.classList.add("flung")),window.setTimeout(()=>{nr(e,A),c(),se()},340)}function R(A,G=null){if(A.type==="dud")return E(A,G);if(A.id==="extraCards")return x(A);if(A.type==="equipmentUpgrade"||A.type==="cellAction")return B(A);hs(e,A),v(A)}function B(A){let G=We(e,A);G.length&&(e.cardTargetPick={pending:!0,cardId:A.id,mode:A.target==="blockedCell"?"blockedCell":"equipment",targetKeys:G.map(tt),remaining:A.id==="dynamite"?Math.min(3,G.length):1},t.modal.classList.remove("visible","equipment-popover"),o())}function O(A){if(!A||A.type!=="blockedCell")return!1;let G=I(A.col,A.row);if(!e.blockedCells?.has(G))return!1;e.blockedCells.delete(G);let q=F(A.col,A.row);return et(e,q.x,q.y),Xe(e,q.x,q.y,p.danger,62),Ze(e,q.x,q.y,18,p.warn),Nn(e,q.x,q.y,8),Ft(e,16,.35),H(e,q.x,q.y-18,"BOOM",p.danger),be(e),e.cardTargetPick.remaining=Math.max(0,(e.cardTargetPick.remaining||1)-1),e.cardTargetPick.targetKeys=We(e,"dynamite").map(tt),o(),!0}function ee(A){if(!e.cardTargetPick?.pending)return!1;let G=Jt(e.cardTargetPick.cardId),q=Ma(e,A);return!G||!q?(X(),!0):G.id==="dynamite"?(O(q)&&((e.cardTargetPick.remaining||0)<=0||!We(e,"dynamite").length)&&v(G),!0):(ys(e,q),v(G),!0)}function X(){e.cardTargetPick?.pending&&(e.cardTargetPick=null,se())}function ae(){let A=Math.max(0,e.cardDraft?.freeRerolls||0);if(A>0){e.cardDraft.freeRerolls=A-1,e.cardDraft.rerolls+=1,l(Lt),se();return}let G=os(e);e.cash${G.alt||`:``}function le(A,G){let q=document.createElement("button");q.type="button";let me=A.type==="dud"?"dud":A.rarity==="ultraRare"?"ultra-rare":A.rarity==="rare"?"rare":"common";q.className=`card-choice ${me}`;let D=A.type==="dud"?"MISS":A.rarity==="ultraRare"?"ULTRA RARE":A.rarity==="rare"?"RARE":"COMMON",U=[D,...(A.tags||[]).filter(S=>S!==D)].slice(0,5);return q.innerHTML=`${ie(A)}
${A.title}
${U.map(S=>`${S}`).join("")}
${ga(e,A)}
`,q.addEventListener("click",()=>R(A,q)),q.dataset.index=String(G),q}function se(){Le(e),e.cardTargetPick=null,e.cardDraft?.pending||r(),e.cardDraft.choices?.length||l(Lt);let A=e.cardDraft.choices||[],G=os(e),q=Math.max(0,e.cardDraft?.freeRerolls||0),me=Math.max(1,e.cardDraft.picksRemaining||1);t.modalTitle.textContent="Choose Upgrade Card",t.modalBody.innerHTML=`

Choose ${me} card${me===1?"":"s"} before Build phase. Dud cards can be flicked away without consuming a pick. Equipment cards target machines; Dynamite targets blocked cells.

`;let D=t.modalBody.querySelector("#cardChoices");A.forEach((M,N)=>D.appendChild(le(M,N))),t.modalActions.innerHTML="";let U=document.createElement("button");U.type="button",U.className="facility-action warn reroll-button",U.textContent=q>0?`Reroll (FREE x${q})`:`Reroll ${g(G)}`,U.disabled=q<=0&&e.cash0?`${q} free reroll${q===1?"":"s"} remaining.`:U.disabled?"Not enough cash":"",U.addEventListener("click",ae),t.modalActions.appendChild(U);let S=document.createElement("button");S.type="button",S.className="facility-action",S.textContent="No Card",S.title="Skip this upgrade pick and enter Build phase.",S.addEventListener("click",i),t.modalActions.appendChild(S),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible")}return{prepareDraft:r,showDraft:se,finishDraft:i,chooseTargetAtPoint:ee,cancelTargetPick:X}}var Ta=!0,Ea={chickMale:"./assets/images/chick_male.png",chickFemale:"./assets/images/chick_female.png",poop:"./assets/images/poop.png",conveyorStraightH:"./assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png",conveyorStraightV:"./assets/dark_factory/facilities/conveyor/conveyor_straight_v_16.png",conveyorTurnNe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_ne_16.png",conveyorTurnNw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png",conveyorTurnSe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_se_16.png",conveyorTurnSw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png",boostConveyorStraightH:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_h_16.png",boostConveyorStraightV:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_v_16.png",boostConveyorTurnNe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_ne_16.png",boostConveyorTurnNw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png",boostConveyorTurnSe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_se_16.png",boostConveyorTurnSw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png",scannerManual:"./assets/dark_factory/facilities/machines/manual_scanner_32x48.png",scannerAuto:"./assets/dark_factory/facilities/machines/auto_scanner_32x48.png",eggFarm:"./assets/dark_factory/facilities/machines/egg_farm_16.png",mixer:"./assets/dark_factory/facilities/machines/mixer_32.png",shredder:"./assets/dark_factory/facilities/machines/shredder_32.png",truck:"./assets/dark_factory/facilities/vehicles/truck_32.png",mixerCompact:"./assets/dark_factory/facilities/machines/mixer_compact_16.png",shredderCompact:"./assets/dark_factory/facilities/machines/shredder_compact_16.png",truckCompact:"./assets/dark_factory/facilities/vehicles/truck_compact_16.png",maintenanceRoom:"./assets/dark_factory/facilities/utility/maintenance_room_32.png",repairman:"./assets/dark_factory/facilities/utility/repairman_16.png",obstacleCrate:"./assets/dark_factory/facilities/utility/obstacle_crate_16.png"},ce={};for(let[e,t]of Object.entries(Ea)){let n=new Image;n.loaded=!1,n.onerror=()=>{n.loaded=!1},Ta&&t&&(n.onload=()=>{n.loaded=!0},n.src=t),ce[e]=n}function Ss(e,t,n,o){e.imageSmoothingEnabled=!1,e.clearRect(0,0,t.width,t.height),Aa(e,t),e.save();let r=n.shake.time>0?W(-n.shake.strength,n.shake.strength):0,i=n.shake.time>0?W(-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),$a(e,n),Da(e,n),Ba(e,n),qa(e,n),Za(e,n),ec(e,n),Ya(e,n),za(e,n),Pa(e,n),rc(e,n,o.activeQueuedChick),pc(e,n),cc(e,t,n),ac(e,n,o.selectedObject,o.selectedTitle),uc(e,n),dc(e,n),fc(e,n),e.restore(),hc(e,n,t)}function Ra(e){if(e.type==="eggFarm"){let n=F(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 Pa(e,t){if(t.phase!=="build")return;let n=Fn(t);for(let o of n){let r=Ra(o);e.save(),e.fillStyle="rgba(196,36,36,.22)",e.strokeStyle=p.danger,e.lineWidth=5,e.setLineDash([10,6]),ne(e,r.x,r.y,r.w,r.h,!0,!0),e.setLineDash([]),e.fillStyle=p.danger,e.strokeStyle=p.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 ne(e,t,n,o,r,i=!0,l=!0){e.beginPath(),e.rect(t,n,o,r),i&&e.fill(),l&&e.stroke()}function lr(e,t,n,o,r=p.ink){e.save(),e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.lineWidth=4,e.strokeStyle=p.white,e.fillStyle=r,e.strokeText(o,t,n),e.fillText(o,t,n),e.restore()}function rt(e,t,n,o,r,i){if(!t?.loaded)return!1;let l=e.imageSmoothingEnabled;return e.imageSmoothingEnabled=!1,e.drawImage(t,Math.round(n),Math.round(o),Math.round(r),Math.round(i)),e.imageSmoothingEnabled=l,!0}function bs(e,t,n,o,r,i,l=null,c=1){e.fillStyle=i,e.fillRect(Math.round(t),Math.round(n),Math.round(o),Math.round(r)),l&&(e.strokeStyle=l,e.lineWidth=c,e.strokeRect(Math.round(t)+.5,Math.round(n)+.5,Math.round(o)-1,Math.round(r)-1))}function Aa(e,t){e.fillStyle=p.bg,e.fillRect(0,0,t.width,t.height),e.save(),e.globalAlpha=.85;for(let n=0;n=n;for(let r of Tt(t)){let i=Et(r);e.save(),e.fillStyle=o?"rgba(183,245,198,.34)":"rgba(255,255,255,.22)",e.strokeStyle=o?p.green:p.muted,e.lineWidth=5,e.setLineDash([16,10]),ne(e,i.x,i.y,i.w,i.h,!0,!0),e.setLineDash([]);let l=ko(r),c=l.cx,v=l.cy;e.fillStyle="rgba(255,255,255,.94)",e.strokeStyle=p.ink,e.lineWidth=4,ne(e,l.x,l.y,l.w,l.h,!0,!0),e.fillStyle=o?p.green:p.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText(r.direction==="right"?"BUY RIGHT LOT":"BUY UPPER LOT",c,v-12),e.fillStyle=p.ink,e.font="900 16px ui-monospace, monospace",e.fillText(`${g(n)} / 10\xD710`,c,v+15),e.fillStyle=p.muted,e.font="900 11px ui-monospace, monospace",e.fillText("blocked tiles included",c,v+30),e.restore()}}function bt(e,t,n,o,r,i,l=0){let c=zt(i);c<.5||(e.save(),e.globalAlpha=Math.min(.62,.12+c*.54),e.fillStyle="#6b4a23",l>0?(e.beginPath(),e.roundRect?.(t,n,o,r,l),e.roundRect?e.fill():ne(e,t,n,o,r,!0,!1)):ne(e,t,n,o,r,!0,!1),e.globalAlpha=Math.min(.9,.25+c*.6),e.strokeStyle="#3a2a16",e.lineWidth=Math.max(2,Math.floor(2+c*5)),e.setLineDash([5,6]),ne(e,t+3,n+3,o-6,r-6,!1,!0),e.restore())}function sr(e,t){let n=e.componentLookup?.get(t);return(n?e.congestion.get(n):null)?.ratio||0}function Fa(e,t,n={}){let o=Xn(e,t).sort(),i=n.kind==="boostConveyor"?"boostConveyor":"conveyor",l=c=>o.includes(c);if(o.length===2){if(l("left")&&l("right"))return ce[`${i}StraightH`];if(l("up")&&l("down"))return ce[`${i}StraightV`];if(l("up")&&l("right"))return ce[`${i}TurnNe`];if(l("up")&&l("left"))return ce[`${i}TurnNw`];if(l("down")&&l("right"))return ce[`${i}TurnSe`];if(l("down")&&l("left"))return ce[`${i}TurnSw`]}return o.length===1?l("up")||l("down")?ce[`${i}StraightV`]:ce[`${i}StraightH`]:l("up")||l("down")?ce[`${i}StraightV`]:ce[`${i}StraightH`]}function Ba(e,t){let n=[],o=new Set;for(let i of t.conveyorTiles){let{col:l,row:c}=Z(i);for(let v of de){let x={col:l+v.dc,row:c+v.dr},E=I(x.col,x.row);if(!t.conveyorTiles.has(E))continue;let R=[i,E].sort().join("|");if(o.has(R))continue;o.add(R);let B=Math.max(sr(t,i),sr(t,E));n.push({a:F(l,c),b:F(x.col,x.row),ratio:B})}}e.save(),e.lineCap="round",e.lineJoin="round";for(let i of[{width:31,color:"#0b0c0f",alpha:1},{width:23,color:"#444b56",alpha:1},{width:15,color:"#171a1f",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=Kt(p.green,p.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=Wa(t);for(let i of t.conveyorTiles){let l=F(...Object.values(Z(i))),c=t.conveyorMeta.get(i)||{},v=sr(t,i),x=Fa(t,i,c),E=v>.5;if(e.fillStyle=E?"rgba(196,36,36,.28)":"rgba(0,0,0,.35)",e.strokeStyle=E?p.danger:"rgba(255,184,39,.34)",e.lineWidth=E?3:1,ne(e,l.x-20,l.y-20,40,40,!0,!0),!rt(e,x,l.x-19,l.y-19,38,38)){let B=c.kind==="boostConveyor"?"#315e92":"#454b55";e.fillStyle=v>.5?Kt(B,"#a12c2c",Math.max(0,(v-.5)/.5)):B,e.strokeStyle=p.ink,e.lineWidth=2,ne(e,l.x-18,l.y-18,36,36,!0,!0)}La(e,l,i,c,v),bt(e,l.x-18,l.y-18,36,36,{meta:c}),ot(e,t,"conveyor",i,l.x,l.y,38,38),Ka(e,l,r.get(i)||[]);let R=Xn(t,i);Ga(e,l,c,Na(t,i,R),R),v>.5&&lr(e,l.x,l.y-15,`${Math.floor(v*100)}%`,p.danger)}e.restore()}function La(e,t,n,o={},r=0){let l=[...new Set([...Array.isArray(o.outDirs)?o.outDirs:[],o.dir].filter(Boolean))][0]||"right",c=l==="up"||l==="down",v=l==="left"||l==="up",x=o.kind==="boostConveyor",E=typeof performance<"u"?performance.now()/(x?70:105):0,R=((v?-E:E)%10+10)%10;e.save(),e.beginPath(),e.rect(t.x-18,t.y-18,36,36),e.clip();let B=x?"rgba(20,126,124,.62)":"rgba(42,47,54,.72)";if(e.fillStyle=B,e.fillRect(t.x-18,t.y-18,36,36),e.strokeStyle=r>.5?"rgba(238,83,61,.90)":"rgba(184,190,198,.92)",e.lineWidth=4,c)for(let O=t.y-28+R;Oe.conveyorTiles.has(I(n.col+o.dc,n.row+o.dr))).map(o=>o.name)}function ks(e,t,n){let o=de.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.(I(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Oa(e,t,n,o=Xn(e,t),r="random"){if(o.length<3)return n;let i=Z(t),l=new Set(o.filter(x=>ks(e,i,x)));if(r&&r!=="random"&&o.includes(r)){let x=new Set(l);x.add(r),o.filter(E=>!x.has(E)).length>=2&&l.add(r)}let c=o.filter(x=>!l.has(x));if(c.length)return c;let v=n.filter(x=>!l.has(x));return v.length?v:n}function Na(e,t,n=Xn(e,t)){if(n.length<3)return[];let o=Z(t),r=new Set(n.filter(i=>ks(e,o,i)));return n.filter(i=>{let l=new Set(r);return l.add(i),n.filter(c=>!l.has(c)).length>=2})}function _a(e,t,n){let o=Z(t),r=de.filter(c=>e.conveyorTiles.has(I(o.col+c.dc,o.row+c.dr))).map(c=>c.name),i=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(c=>r.includes(c)),l=r;return i.length?i:l}function Ga(e,t,n,o,r=o){if(r.length<3||o.length<2)return;e.save();let i=o.includes(n.branchMode)?n.branchMode:"random",l=i!=="random";if(e.lineJoin="round",e.lineCap="round",e.lineWidth=2,e.fillStyle="rgba(255,255,255,.9)",e.strokeStyle=l?p.warn:p.green,ne(e,t.x-17,t.y-17,34,34,!0,!0),e.strokeStyle=p.ink,e.lineWidth=2,e.fillStyle=p.ink,i!=="random"){let c=de.find(v=>v.name===i);zn(e,t.x,t.y,c?.angle||0,9,6)}else e.beginPath(),e.moveTo(t.x-10,t.y),e.lineTo(t.x-2,t.y),e.lineTo(t.x+8,t.y-8),e.moveTo(t.x-2,t.y),e.lineTo(t.x+8,t.y+8),e.stroke(),zn(e,t.x+9,t.y-9,-Math.PI/4,4,3),zn(e,t.x+9,t.y+9,Math.PI/4,4,3);e.restore()}function Ua(e,t,n){if(!n)return[];let o=Z(t),r=de.filter(c=>e.conveyorTiles.has(I(o.col+c.dc,o.row+c.dr))).map(c=>c.name),i=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(c=>r.includes(c));return Oa(e,t,i.length?i:_a(e,t,n),r,n.branchMode||"random").map(c=>de.find(v=>v.name===c)).filter(Boolean)}function Wa(e){let t=new Map;for(let[n,o]of e.conveyorMeta||[]){let r=Ua(e,n,o);r.length&&t.set(n,r)}return t}function Ka(e,t,n){let o=n.slice(0,4);o.length&&(e.save(),e.fillStyle=p.ink,e.globalAlpha=.86,o.forEach(r=>{zn(e,t.x+r.dc*12,t.y+r.dr*12,r.angle,6,5)}),e.restore())}function zn(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 Ha(e,t,n,o,r){let i=ye(t),l=null;if(n==="inputA"&&(l={x:i.x,y:i.y-67}),n==="left"&&(l={x:i.x-49,y:i.y+14}),n==="right"&&(l={x:i.x+49,y:i.y+14}),!l)return;let c=n==="inputA"?{x:o.x,y:l.y}:{x:l.x,y:o.y};e.save(),e.lineCap="square",e.lineJoin="bevel",e.strokeStyle="#050609",e.lineWidth=15,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.strokeStyle="#596473",e.lineWidth=9,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.strokeStyle=r||"#7b8795",e.lineWidth=3,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.fillStyle=r||"#7b8795",e.strokeStyle="#050609",e.lineWidth=3,ne(e,l.x-9,l.y-7,18,14,!0,!0),e.restore()}function qa(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=Po(n),r=[{type:"inputA",p:Re(n,"inputA"),label:"IN",color:p.green},{type:"left",p:Re(n,"left"),label:Io(o.left),color:$o(o.left)},{type:"right",p:Re(n,"right"),label:Io(o.right),color:$o(o.right)}];for(let i of r){if(!i.p)continue;let l=F(i.p.col,i.p.row);Ha(e,n,i.type,l,i.color);let c=ii(t,n,i.type||(i.label==="IN"?"inputA":null))||t.conveyorTiles.has(I(i.p.col,i.p.row));e.fillStyle=c?Kt("#1a1d23",i.color,.24):"#3a1e22",e.strokeStyle=c?i.color:p.danger,ne(e,l.x-18,l.y-12,36,24,!0,!0),e.fillStyle=p.white,e.fillText(i.label,l.x,l.y+4)}}e.restore()}function Ya(e,t){for(let n of t.eggFarms)Va(e,n,t)}function Va(e,t,n){let o=F(t.col,t.row);if(e.save(),rt(e,ce.eggFarm,o.x-29,o.y-29,58,58)){bt(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=p.ink,e.lineWidth=2,ne(e,o.x+9,o.y+12,30,18,!0,!0),e.fillStyle=p.ink,e.font="900 10px ui-monospace, monospace",e.textAlign="center",e.fillText(`O${l}`,o.x+24,o.y+24),ot(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore();return}e.fillStyle=p.white,e.strokeStyle=p.ink,e.lineWidth=4,ne(e,o.x-28,o.y-28,56,56,!0,!0),e.fillStyle=p.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=p.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=p.ink,ne(e,o.x-28,o.y-28,56,l,!0,!1),e.strokeStyle=p.white,e.lineWidth=2;for(let c=o.y-24;c=1&&(e.fillStyle=p.white,e.font="900 12px ui-monospace, monospace",e.fillText("SHUT",o.x,o.y+4))}bt(e,o.x-28,o.y-28,56,56,t),ot(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore()}function za(e,t){for(let n of t.scanners)Xa(e,n,t)}function Xa(e,t,n){let o=ye(t);if(e.save(),t.kind==="manual"&&(n.manualCombo?.count||0)>=10){let v=n.manualCombo.count;e.save(),e.globalAlpha=Math.min(.55,.16+v/120),e.strokeStyle=v>=30?p.warn:p.green,e.lineWidth=Math.min(14,5+Math.floor(v/10)),e.shadowColor=e.strokeStyle,e.shadowBlur=Math.min(28,8+v),ne(e,o.x-54,o.y-76,108,152,!1,!0),e.restore()}let r=t.kind==="auto"?ce.scannerAuto:ce.scannerManual;if(rt(e,r,o.x-50,o.y-73,100,146)){t.kind==="auto"?bt(e,o.x-50,o.y-73,100,146,t):vs(e,t,o),ot(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore();return}e.fillStyle=t.kind==="auto"?"#d8ffe2":p.white,e.strokeStyle=p.ink,e.lineWidth=4,ne(e,o.x-50,o.y-73,100,146,!0,!0),e.fillStyle=t.kind==="auto"?p.green:p.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-48),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-28);let c=t.queue.length;t.kind==="manual"?(vs(e,t,o),e.fillStyle=c>0?p.green:p.muted,e.font="900 10px ui-monospace, monospace",e.fillText(`Q:${c}`,o.x,o.y+54)):(e.fillStyle=c>0?p.green:p.muted,e.font="900 12px ui-monospace, monospace",e.fillText(`Q:${c} CD:${t.cooldown.toFixed(1)}`,o.x,o.y+54),bt(e,o.x-50,o.y-73,100,146,t)),ot(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore()}function vs(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,c=n.y+18;e.save(),e.lineWidth=3,e.fillStyle="#f7fff5",e.strokeStyle=p.ink,ne(e,l-4,c-4,68,25,!0,!0),e.font="900 19px ui-monospace, monospace",e.textAlign="center";for(let v=0;v.8,i=t.y+Math.sin(t.bob)*(r?5:1.5);if(e.save(),n&&(e.strokeStyle=p.green,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius+8,0,Math.PI*2),e.stroke()),r&&(e.strokeStyle=p.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")pr(e,t.x,i,t.radius);else{let l=t.sex==="male"?ce.chickMale:ce.chickFemale;if(!rt(e,l,t.x-t.radius,i-t.radius,t.radius*2,t.radius*2)){let x=t.sex==="male"?p.male:p.female,E=t.sex==="male"?"#164f8f":"#8b2252";e.fillStyle=x,e.strokeStyle=p.ink,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle="rgba(255,255,255,.24)",e.beginPath(),e.arc(t.x-5,i-7,t.radius*.36,0,Math.PI*2),e.fill(),e.fillStyle=p.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.strokeStyle=E,e.lineWidth=3,t.sex==="male"?(e.beginPath(),e.moveTo(t.x-8,i-t.radius-2),e.lineTo(t.x+8,i-t.radius-2),e.stroke()):(e.beginPath(),e.moveTo(t.x-9,i-t.radius+2),e.lineTo(t.x,i-t.radius-6),e.lineTo(t.x+9,i-t.radius+2),e.stroke())}e.fillStyle=t.sex==="male"?"#dff1ff":"#fff0f7",e.strokeStyle="#050609",e.lineWidth=3,e.font=`900 ${Math.max(10,Math.round(t.radius*.72))}px ui-monospace, monospace`,e.textAlign="center";let v=t.sex==="male"?"\u2642":"\u2640";e.strokeText(v,t.x+t.radius*.54,i+t.radius*.7),e.fillText(v,t.x+t.radius*.54,i+t.radius*.7)}e.restore()}function sc(e,t){let n=null,o=1/0;for(let[r,i]of e.componentLookup.entries()){let l=Z(r),c=F(l.col,l.row),v=Math.hypot(t.x-c.x,t.y-c.y);vws(o.type,o.id)===ws(t,n))}function ot(e,t,n,o,r,i,l,c){lc(t,n,o)&&(e.save(),e.fillStyle="rgba(34,185,79,.18)",e.strokeStyle=p.green,e.lineWidth=(t.multiSelected||[]).length>1?6:4,e.setLineDash((t.multiSelected||[]).length>1?[]:[8,5]),ne(e,r-l/2,i-c/2,l,c,!0,!0),e.restore())}function ac(e,t,n,o){if(t.phase==="build"&&(t.multiSelected||[]).length>1){e.save(),e.fillStyle="rgba(255,255,255,.96)",e.strokeStyle=p.ink,e.lineWidth=3,ne(e,54-t.view.x,66-t.view.y,214,42,!0,!0),e.fillStyle=p.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=p.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 cc(e,t,n){if(!n.cardTargetPick?.pending)return;let o=ir(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 v of o){let x=v.bounds,E=8;e.rect(x.x-E,x.y-E,x.w+E*2,x.h+E*2)}e.fill("evenodd");let i=n.cardTargetPick?.mode==="blockedCell";if(!o.length){e.fillStyle="rgba(255,255,255,.95)",e.strokeStyle=p.ink,e.lineWidth=3,ne(e,(260-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,420/r,42/r,!0,!0),e.fillStyle=p.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=p.ink,e.lineWidth=3;let l=Math.max(1,n.cardTargetPick?.remaining||1),c=n.cardTargetPick?.mode==="autoScannerMenu"?"AUTO SCANNER ROUTE SETTINGS. CLICK EMPTY AREA TO CLOSE.":i?`CLICK BLOCKED CELL: ${l} LEFT. PRESS ESC TO CANCEL.`:"CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.";ne(e,(216-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,560/r,42/r,!0,!0),e.fillStyle=p.ink,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(c,(496-(n.view?.x||0))/r,(122-(n.view?.y||0))/r),e.restore()}function uc(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=p.green,e.lineWidth=2,e.setLineDash([7,4]),ne(e,o,r,i,l,!0,!0),e.restore()}function dc(e,t){let n=[...t.effects].sort((o,r)=>(o.priority??xe.ambient)-(r.priority??xe.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=p.green,ne(e,o.x-o.size/2,o.y-o.size/2,o.size*1.5,o.size,!0,!1)):o.type==="sludge"?(e.fillStyle=p.poop,ne(e,o.x-o.size/2,o.y-o.size/2,o.size*1.4,o.size,!0,!1)):o.type==="spawn"?(e.strokeStyle=p.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||p.danger,ne(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||p.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||p.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||p.ink,e.save(),e.translate(o.x,o.y),e.rotate(o.rot||0),ne(e,-o.w/2,-o.h/2,o.w,o.h,!0,!1),e.restore()):o.type==="load"?(e.strokeStyle=o.color||p.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=p.ink,e.lineWidth=3,e.setLineDash([4,4]),ne(e,o.x-o.size/2,o.y-o.size/2,o.size,o.size,!1,!0)):o.type==="rage"?(e.fillStyle=o.color||p.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText("!",o.x,o.y)):o.type==="flyingChick"&&(o.sex==="poop"?pr(e,o.x,o.y,o.radius||11):yr(e,o.x,o.y,o.sex,o.sex==="male")),e.restore()}}function fc(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=p.white,e.fillStyle=n.color,e.strokeText(n.text,n.x,n.y),e.fillText(n.text,n.x,n.y)}e.restore()}function pc(e,t){let n=t.repairmen&&t.repairmen.length?t.repairmen:t.repairman?[t.repairman]:[];for(let o of n)yc(e,t,o)}function yc(e,t,n){if(!!!n?.active)return;if(e.save(),rt(e,ce.repairman,n.x-18,n.y-18,36,36)){n.target?.label&&lr(e,n.x,n.y-24,n.target.label,p.green),e.restore();return}e.lineWidth=3,e.fillStyle="#fff0d1",e.strokeStyle=p.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?p.danger:p.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=p.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=p.green,ne(e,n.x-9,n.y+14,18,8,!0,!0),e.strokeStyle=p.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=p.ink,e.font="900 11px ui-monospace, monospace",e.textAlign="center",e.fillText("FIX",n.x,n.y+33),n.target?.label&&lr(e,n.x,n.y-24,n.target.label,p.green),e.restore()}function hc(e,t,n){e.save(),e.font="900 19px ui-monospace, monospace",e.textAlign="left",e.fillStyle=p.ink,e.font="900 19px ui-monospace, monospace",e.fillStyle=p.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=p.white,e.lineWidth=4,e.strokeText(i,24,r),e.fillText(i,24,r),r+=20;e.restore()}var gs=[[{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 mc(e){let t=gs[e]||gs[0];return{left:{...t[0]},right:{...t[1]}}}function Ts(e,t,n){let o={type:"eggFarm",id:e.nextId++,col:t,row:n,level:1,nextSpawn:2,lastInterval:2,extraEggOutlet:0,price:lt.eggFarm,builtSession:e.buildSession};return o.nextSpawn=Rt(o),o.lastInterval=o.nextSpawn,o}function Es(e,t,n,o){let r=o==="auto"?ve.autoScanner.price:ve.manualScanner.price,i=new Set(e.scanners.filter(c=>c.kind==="manual").map(c=>c.slot)),l=0;for(;i.has(l);)l+=1;return{type:"scanner",id:e.nextId++,kind:o,slot:o==="manual"?l:null,role:o==="manual"?l%2:0,col:t,row:n,level:1,queue:[],cooldown:0,price:r,builtSession:e.buildSession,autoMode:"standard",keys:o==="manual"?mc(l):null}}function Jn(e){let t=(e.x-f.x)/f.cell,n=(e.y-f.y)/f.cell,o=Math.max(0,Math.min(f.cols-1,Math.round(t-.5))),r=Math.max(0,Math.min(f.rows-1,Math.round(n-.5))),i=Math.abs(e.x-f.x),l=Math.abs(e.x-(f.x+f.cols*f.cell)),c=Math.abs(e.y-f.y),v=Math.abs(e.y-(f.y+f.rows*f.cell)),x=[["left",i],["right",l],["top",c],["bottom",v]].sort((E,R)=>E[1]-R[1])[0][0];return x==="left"?{side:x,entry:{col:0,row:r}}:x==="right"?{side:x,entry:{col:f.cols-1,row:r}}:x==="top"?{side:x,entry:{col:o,row:0}}:{side:x,entry:{col:o,row:f.rows-1}}}function jn(e,t,n){let o={x:f.x+t.col*f.cell+f.cell/2,y:f.y+t.row*f.cell+f.cell/2},r={left:f.x,right:f.x+f.cols*f.cell,top:f.y,bottom:f.y+f.rows*f.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 Rs(e,t,n,o){let{entry:r,side:i}=Jn(n),l=ve[t],c=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},v={type:"facility",id:t,name:c.name,x:0,y:0,w:c.w,h:c.h,level:1,price:o||c.price,builtSession:e.buildSession};return jn(v,r,i)}function jt(e){return e?[{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function Ps(e,t,n){return{type:"maintenanceRoom",id:e.nextId++,col:t,row:n,price:lt.maintenanceRoom,builtSession:e.buildSession,wCells:2,hCells:2}}function bc(e){return Math.random()({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 Is({game:e,canvasPoint:t,updatePanels:n,equipmentAtPoint:o,fail:r,pointInGrid:i,rectOfFacility:l,rectsOverlap:c}){function v(S){return S?S.type==="conveyor"?`conveyor:${S.id||S.oldKey}`:S.type==="facility"?`facility:${S.id||S.ref?.id}`:S.type==="maintenanceRoom"?`maintenanceRoom:${S.id||S.ref?.id}`:`${S.type}:${S.id||S.ref?.id}`:""}function x(S){return S?S.type==="conveyor"?{type:"conveyor",id:S.oldKey}:{type:S.type,id:S.ref.id}:null}function E(S){let M=v(x(S));return(e.multiSelected||[]).some(N=>v(N)===M)}function R(S){return S?S.type==="eggFarm"?e.eggFarms.find(M=>M.id===S.id)||null:S.type==="scanner"?e.scanners.find(M=>M.id===S.id)||null:S.type==="facility"?e.facilities[S.id]||null:S.type==="maintenanceRoom"?(e.maintenanceRooms||[]).find(M=>M.id===S.id)||null:S.type==="conveyor"&&e.conveyorTiles.has(S.id)?{type:"conveyor",id:S.id}:null:null}function B(){let S=[];for(let M of e.conveyorTiles){let N=Z(M),J=F(N.col,N.row);S.push({type:"conveyor",id:M,center:J,cell:N})}for(let M of e.eggFarms)S.push({type:"eggFarm",id:M.id,ref:M,center:F(M.col,M.row),cell:{col:M.col,row:M.row}});for(let M of e.scanners)S.push({type:"scanner",id:M.id,ref:M,center:ye(M),cell:{col:M.col,row:M.row}});for(let M of e.maintenanceRooms||[]){let N=F(M.col,M.row);S.push({type:"maintenanceRoom",id:M.id,ref:M,center:{x:N.x+f.cell/2,y:N.y+f.cell/2},cell:{col:M.col,row:M.row}})}for(let M of Object.values(e.facilities)){let N={x:M.x+M.w/2,y:M.y+M.h/2},J=M.entry?F(M.entry.col,M.entry.row):N;S.push({type:"facility",id:M.id,ref:M,center:N,portCenter:J})}return S}function O(S,M){let N=Math.min(M.x1,M.x2),J=Math.max(M.x1,M.x2),Q=Math.min(M.y1,M.y2),pe=Math.max(M.y1,M.y2);return S.x>=N&&S.x<=J&&S.y>=Q&&S.y<=pe}function ee(S){let M=[];for(let N of B())(O(N.center,S)||N.portCenter&&O(N.portCenter,S))&&M.push({type:N.type,id:N.id});return e.multiSelected=M,e.selected=M[0]||null,n(),M.length}function X(){e.multiSelected=[],e.selected=null,n()}function ae(S){let M=t(S);return e.selectionBox={x1:M.x,y1:M.y,x2:M.x,y2:M.y},e.multiSelected=[],e.selected=null,n(),!0}function he(S){if(!e.selectionBox)return;let M=t(S);e.selectionBox.x2=M.x,e.selectionBox.y2=M.y}function ie(){if(!e.selectionBox)return 0;let S=e.selectionBox,M=Math.abs(S.x2-S.x1),N=Math.abs(S.y2-S.y1);return e.selectionBox=null,M<6&&N<6?(X(),0):ee(S)}function le(S){let M=x(S);return M?(e.multiSelected||[]).length&&E(S)?[...e.multiSelected]:[M]:[]}function se(S){let M=R(S);if(!M)return null;if(S.type==="conveyor"){let N=Z(S.id);return{...S,obj:M,oldKey:S.id,currentKey:S.id,meta:e.conveyorMeta.get(S.id)||{price:Oe("conveyor"),builtSession:null},col:N.col,row:N.row}}return S.type==="eggFarm"||S.type==="scanner"||S.type==="maintenanceRoom"?{...S,obj:M,col:M.col,row:M.row}:S.type==="facility"?{...S,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 A(S){let M=t(S),N=o(M);if(!N)return!1;let J=le(N),Q=J.map(se).filter(Boolean);return Q.length?(e.groupDrag={start:M,selections:J,origins:Q,historySnapshot:hn(e),committed:!1,lastDCol:0,lastDRow:0},e.multiSelected=J,e.selected=J[0]||null,n(),!0):!1}function G(){!e.groupDrag||e.groupDrag.committed||(e.undoStack.push(e.groupDrag.historySnapshot),e.redoStack=[],e.groupDrag.committed=!0)}function q(S,M,N){let J=I(S,M),Q=dt(e,S,M);if(Q&&!N.has(`eggFarm:${Q.id}`))return!0;let pe=ft(e,S,M);if(pe&&!N.has(`scanner:${pe.id}`))return!0;let ge=(e.maintenanceRooms||[]).find(Pe=>jt(Pe).some(Ae=>Ae.col===S&&Ae.row===M));return!!(ge&&!N.has(`maintenanceRoom:${ge.id}`)||e.conveyorTiles.has(J)&&!N.has(`conveyor:${J}`))}function me(S,M,N){let J=[];for(let Q of e.groupDrag.origins){if(Q.type!=="facility")continue;let pe={x:Q.center.x+S,y:Q.center.y+M},{entry:ge,side:Pe}=Jn(pe);if(!i(ge.col,ge.row)||e.blockedCells?.has?.(I(ge.col,ge.row)))return!0;let Ae={...Q.obj,entry:{...ge},side:Pe};jn(Ae,ge,Pe),J.push({id:Q.id,rect:l(Ae)})}for(let Q of J)for(let pe of Object.values(e.facilities))if(!N.has(`facility:${pe.id}`)&&c(Q.rect,l(pe),12))return!0;for(let Q=0;Q_.type==="conveyor");for(let _ of Ae){let Ie=_.currentKey||_.oldKey;e.conveyorTiles.delete(Ie),e.conveyorMeta.delete(Ie)}for(let _ of Ae){let Ie=I(_.col+Q,_.row+pe);e.conveyorTiles.add(Ie),e.conveyorMeta.set(Ie,_.meta||{price:Oe("conveyor"),builtSession:null,uses:0}),_.currentKey=Ie}for(let _ of e.groupDrag.origins)if(_.type==="eggFarm")_.obj.col=_.col+Q,_.obj.row=_.row+pe;else if(_.type==="scanner")_.obj.col=_.col+Q,_.obj.row=_.row+pe;else if(_.type==="maintenanceRoom")_.obj.col=_.col+Q,_.obj.row=_.row+pe;else if(_.type==="facility"){let Ie={x:_.center.x+N,y:_.center.y+J},{entry:qe,side:Ye}=Jn(Ie);jn(_.obj,qe,Ye)}e.groupDrag.selections=e.groupDrag.origins.map(_=>_.type==="conveyor"?{type:"conveyor",id:_.currentKey||_.oldKey}:{type:_.type,id:_.id}),e.multiSelected=[...e.groupDrag.selections],e.selected=e.multiSelected[0]||null,be(e),n()}function U(){e.groupDrag&&(be(e),e.groupDrag=null,n())}return{selectionFromHit:x,startSelectionBox:ae,updateSelectionBox:he,finishSelectionBox:ie,startGroupDrag:A,updateGroupDrag:D,finishGroupDrag:U}}function $s({game:e,ui:t,canvas:n,canvasPoint:o,onUpdatePanels:r}){function i(){r&&r()}let l=null,c=!1,v=null,x=!1,E=["random","up","right","down","left"],R={random:"RND",up:"UP",right:"RT",down:"DN",left:"LF"},B={w:40,h:40,y:0};function O(){return Rn(e)}function ee(){e.gridCols=f.cols,e.gridRows=f.rows,e.gridOwnedCells=qr(e)}function X(s){if(s){f.y-=s*f.cell,f.rows+=s,e.gridChunkOriginY=(e.gridChunkOriginY||0)-Math.floor(s/10),e.ownedCells=Pn(e.ownedCells,s),e.blockedCells=Pn(e.blockedCells,s),e.conveyorTiles=Pn(e.conveyorTiles,s),e.conveyorMeta=Xr(e.conveyorMeta,s);for(let a of e.eggFarms||[])a.row+=s;for(let a of e.scanners||[])a.row+=s;for(let a of Object.values(e.facilities||{}))a.entry&&(a.entry.row+=s)}}function ae(s){e.ownedCells=e.ownedCells||new Set;for(let a of zr(s))e.ownedCells.add(I(a.col,a.row))}function he(s){return e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending?null:Tt(e).find(a=>a&&Vr(a,s))||null}function ie(s="right"){if(s&&typeof s=="object"&&Number.isFinite(s.chunkX)&&Number.isFinite(s.chunkY))return s;let a=["right","up"].includes(s)?s:"right";return Yr(e,a)}function le(s="right"){let a=ie(s);if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return{ok:!1,reason:"Cannot expand now."};if(!a)return{ok:!1,reason:"Invalid expansion lot."};let h=a.direction||"right",m=O();if(e.cashf.cols&&(f.cols=T.colStart+T.cols),T.rowStart+T.rows>f.rows&&(f.rows=T.rowStart+T.rows),ae(T),Qr(e,T.chunkX,T.chunkY),e.gridExpansionPurchases=(e.gridExpansionPurchases||0)+1,e.gridExpansionPurchasesByDirection[h]=(e.gridExpansionPurchasesByDirection[h]||0)+1,ee();let te=Gr({seed:`${e.runSeed}:grid-expansion:${T.chunkX},${T.chunkY}:${e.gridExpansionPurchases}`,colStart:T.colStart,colEnd:T.colStart+T.cols,rowStart:T.rowStart,rowEnd:T.rowStart+T.rows,targetRatio:Y.map.blockedRatio});for(let ke of te)e.blockedCells.add(ke);be(e);let j=T.cols*T.rows,ue=Et(T);return H(e,ue.x+ue.w/2,ue.y+ue.h/2,`${h.toUpperCase()} +${j} CELLS -${g(m)}`,p.green),i(),{ok:!0,direction:h,cost:m,addedCells:j,blocked:te.size,chunkX:T.chunkX,chunkY:T.chunkY}}function se(s,a){return s>=0&&s=0&&a!a.has(m.id)&&q(h,G(m),12))}function D(s,a,h=null){if(!se(s,a))return!1;if(A(s,a))return!0;let m=I(s,a),w=dt(e,s,a);if(w&&!(h?.type==="eggFarm"&&h.ref?.id===w.id))return!0;let T=ft(e,s,a);if(T&&!(h?.type==="scanner"&&h.ref?.id===T.id))return!0;let te=U(e,s,a);return!!(te&&!(h?.type==="maintenanceRoom"&&h.ref?.id===te.id)||e.conveyorTiles.has(m)&&!(h?.type==="conveyor"&&h.oldKey===m))}function U(s,a,h){return(s.maintenanceRooms||[]).find(m=>jt(m).some(w=>w.col===a&&w.row===h))||null}function S(s,a,h=null){let m={col:s,row:a};for(let w of jt(m)){if(!se(w.col,w.row)||A(w.col,w.row))return!0;let T=I(w.col,w.row);if(dt(e,w.col,w.row)||ft(e,w.col,w.row))return!0;let ue=U(e,w.col,w.row);if(ue&&!(h?.type==="maintenanceRoom"&&h.ref?.id===ue.id)||e.conveyorTiles.has(T))return!0}return!1}function M(s,a,h=null){let m={col:s,row:a};for(let w of Pt(m)){if(!se(w.col,w.row)||A(w.col,w.row))return!0;let T=I(w.col,w.row);if(dt(e,w.col,w.row))return!0;let j=ft(e,w.col,w.row);if(j&&!(h?.type==="scanner"&&h.ref?.id===j.id)||e.conveyorTiles.has(T))return!0}return!1}function N(){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:e.selected.type==="maintenanceRoom"&&(e.maintenanceRooms||[]).find(s=>s.id===e.selected.id)||null:null}function J(s){return s?s.type==="eggFarm"?`${ct("eggFarm")} #${s.id}`:s.type==="scanner"?`${s.kind==="auto"?ct("autoScanner"):ct("manualScanner")} #${s.id}`:s.type==="conveyor"?e.conveyorMeta.get(s.id)?.kind==="boostConveyor"?ct("boostConveyor"):ct("conveyor"):s.type==="facility"?s.name:s.type==="maintenanceRoom"?`${ct("maintenanceRoom")} #${s.id}`:"Equipment":"Equipment"}function Q(s){return s?.type==="conveyor"?e.conveyorMeta?.get(s.oldKey||s.ref?.id)?.price||Ln(s):Ln(s)}function pe(){return!!e.cardEffects?.usedMachineActive}function ge(){return pe()?{usedMachine:!0,noRefund:!0,durabilityBaseMultiplier:.6}:{usedMachine:!1,noRefund:!1,durabilityBaseMultiplier:1}}function Pe(s){let a=ge();return Object.assign(s,a),s}function Ae(s){let a=s?.ref||s||{};if(s?.type==="eggFarm"||a.type==="eggFarm")return e.eggFarms.length<=1?"Cannot sell the last EGG FARM.":"";if((s?.type==="facility"||a.type==="facility")&&["mixer","trash","truck"].includes(a.baseId||a.id)){let h=a.baseId||a.id;if(Object.values(e.facilities).filter(w=>(w.baseId||w.id)===h).length<=1)return`Cannot sell the last ${a.shortName||a.name||a.id}.`}return""}function _(s){t.buildStatus.textContent=s,H(e,n.width/2-e.view.x,86-e.view.y,s.toUpperCase(),p.danger)}function Ie(s){if(!s)return null;let a=I(s.col,s.row);return e.conveyorMeta.get(a)||null}function qe(s){return s?(Array.isArray(s.outDirs)||(s.outDirs=[]),s.outDirs=[...new Set(s.outDirs.filter(a=>["right","left","down","up"].includes(a)))],E.includes(s.branchMode)||(s.branchMode="random"),s.kind||(s.kind="conveyor"),s.speedMultiplier||(s.speedMultiplier=s.kind==="boostConveyor"?2:1),s.outDirs):[]}function Ye(s){return s?de.filter(a=>e.conveyorTiles.has(I(s.col+a.dc,s.row+a.dr))).map(a=>a.name):[]}function Te(s){return Ye(s).length>=3}function kt(s,a){let h=de.find(j=>j.name===a);if(!s||!h)return!1;let m=I(s.col+h.dc,s.row+h.dr),w=e.conveyorMeta.get(m);if(!w)return!1;let T=h.opposite;return[...new Set([...Array.isArray(w.outDirs)?w.outDirs:[],w.dir].filter(Boolean))].includes(T)}function oo(s){if(!e.conveyorTiles.has(s))return[];let a=Z(s),h=e.conveyorMeta.get(s),m=qe(h),w=Ye(a),T=[...new Set([...m,h?.dir].filter(Boolean))].filter(ue=>w.includes(ue)),te=w,j=T.length?T:te;return h&&(h.outDirs=m.filter(ue=>w.includes(ue)),h.dir&&!w.includes(h.dir)&&(h.dir=h.outDirs[0]||null),h.branchMode!=="random"&&!w.includes(h.branchMode)&&(h.branchMode="random")),j}function Sn(s){if(!e.conveyorTiles.has(s))return[];let a=Z(s),h=Ye(a);return Te(a)||h.length?h:oo(s)}function ro(s){let a=Z(s),h=Sn(s);if(h.length<3)return[];let m=new Set(h.filter(w=>kt(a,w)));return h.filter(w=>{let T=new Set(m);return T.add(w),h.filter(te=>!T.has(te)).length>=2})}function nn(s,a){let h=at(s,a);if(!h)return!1;let m=I(s.col,s.row),w=I(a.col,a.row),T=e.conveyorMeta.get(m),te=e.conveyorMeta.get(w);if(!T||!te)return!1;let j=qe(T),ue=!j.includes(h)||T.dir!==h||!te.dir;return j.includes(h)||j.push(h),T.dir=h,te.dir||(te.dir=h),ue}function Ct(s){let a=so(s);return a.length<2?io(s):(Be(e),lo(a),be(e),i(),!0)}function io(s){if(!s)return!1;let a=I(s.col,s.row),h=e.conveyorMeta.get(a);if(!h||Te(s))return!1;let m=de.map(te=>te.name),w=h.dir&&m.includes(h.dir)?h.dir:null,T=m[(Math.max(-1,m.indexOf(w))+1)%m.length];return Be(e),h.dir=T,h.outDirs=[T],h.branchMode="random",be(e),i(),!0}function kn(s){return s?de.map(a=>({col:s.col+a.dc,row:s.row+a.dr})).filter(a=>e.conveyorTiles.has(I(a.col,a.row))):[]}function so(s){if(!s||!e.conveyorTiles.has(I(s.col,s.row))||Te(s))return[];let a=kn(s);if(!a.length||a.length>2)return[];let h=T=>{let te=[],j=new Set([I(s.col,s.row)]),ue=s,ke=T,xr=0;for(;ke&&xr<200;){xr+=1;let Mr=I(ke.col,ke.row);if(j.has(Mr)||(j.add(Mr),te.push(ke),Te(ke)))break;let gr=kn(ke).filter(Tr=>!(Tr.col===ue.col&&Tr.row===ue.row));if(gr.length!==1)break;ue=ke,ke=gr[0]}return te},m=a[0]?h(a[0]).reverse():[],w=a[1]?h(a[1]):[];return[...m,s,...w]}function xt(s,a){return!!s&&[...new Set([...Array.isArray(s.outDirs)?s.outDirs:[],s.dir].filter(Boolean))].includes(a)}function lo(s){let a=0,h=0;for(let w=0;wh?[...s].reverse():s;for(let w=0;w=Math.abs(m)?{col:s.col+Math.sign(h),row:s.row}:{col:s.col,row:s.row+Math.sign(m)}}function ao(s){c=!1,v=s?{col:s.col,row:s.row}:null,x=!1,l=null,on(s)}function d(s){if(!s)return;if(!l)return on(s);let a=l,h=0;for(;(a.col!==s.col||a.row!==s.row)&&h<64;){let m=rn(a,s);if(on(m),a=l||m,h+=1,!l)break}}function y(){!x&&v&&e.conveyorTiles.has(I(v.col,v.row))&&Ct(v),v=null,x=!1,l=null,c=!1}function b(s){if(!s)return _(oe.fail.outOfGrid);let{col:a,row:h}=s;if(e.buildTool==="conveyor"||e.buildTool==="boostConveyor"){let m=_t(s,null);if(!m.ok)return _(m.reason||oe.fail.cellOccupied);be(e);return}if(A(a,h))return _("Cannot build on blocked ground.");if(e.buildTool==="maintenanceRoom")return S(a,h)?_(oe.fail.cellOccupied):$(a,h);if(e.buildTool==="manualScanner"||e.buildTool==="autoScanner"?M(a,h):D(a,h))return _(oe.fail.cellOccupied);e.buildTool==="eggFarm"?k(a,h):e.buildTool==="manualScanner"?P(a,h,"manual"):e.buildTool==="autoScanner"&&P(a,h,"auto")}function C(s){let a=Ke(s.x,s.y);if(["conveyor","boostConveyor","eggFarm","manualScanner","autoScanner","maintenanceRoom"].includes(e.buildTool))return b(a);if(cn.includes(e.buildTool))return re(s,e.buildTool)}function k(s,a){let h=Oe("eggFarm",e);if(e.cashT.kind==="manual").length>=8)return _("Manual Scanner limit reached (8 max).");let m=h==="auto"?Oe("autoScanner",e):Oe("manualScanner",e);if(e.cashw.id!==a.ref.id),et(e,m.x,m.y),be(e)}if(a.type==="scanner"){let m=ye(a.ref);Ne(a,m.x,m.y),e.scanners=e.scanners.filter(w=>w.id!==a.ref.id),et(e,m.x,m.y),be(e)}if(a.type==="facility"){let m=a.ref;Ne(a,m.x+m.w/2,m.y+m.h/2),delete e.facilities[m.id],et(e,m.x+m.w/2,m.y+m.h/2),be(e)}if(a.type==="maintenanceRoom"){let m=a.ref,w=K(m);Ne(a,w.x,w.y),e.maintenanceRooms=(e.maintenanceRooms||[]).filter(T=>T.id!==m.id),et(e,w.x,w.y)}e.selected=null,e.multiSelected=[],i()}function co(s){let a=Object.values(e.facilities).find(j=>{if(s.x>=j.x&&s.x<=j.x+j.w&&s.y>=j.y&&s.y<=j.y+j.h)return!0;if(!j.entry)return!1;let ke=F(j.entry.col,j.entry.row);return Math.abs(s.x-ke.x)<=f.cell*.46&&Math.abs(s.y-ke.y)<=f.cell*.46});if(a)return{type:"facility",ref:a};let h=Ke(s.x,s.y);if(!h)return null;let m=dt(e,h.col,h.row);if(m)return{type:"eggFarm",ref:m};let w=ft(e,h.col,h.row);if(w)return{type:"scanner",ref:w};let T=U(e,h.col,h.row);if(T)return{type:"maintenanceRoom",ref:T};let te=I(h.col,h.row);return e.conveyorTiles.has(te)?{type:"conveyor",oldKey:te,ref:{type:"conveyor",id:te}}:null}let Ut=Is({game:e,canvasPoint:o,updatePanels:i,equipmentAtPoint:co,fail:_,pointInGrid:se,rectOfFacility:G,rectsOverlap:q});function Qs(s){return null}function mr(){let s=N();s&&(s.type==="conveyor"?Gt(F(...Object.values(Z(s.id)))):s.type==="eggFarm"?Gt(F(s.col,s.row)):s.type==="scanner"?Gt(ye(s)):s.type==="facility"?Gt({x:s.x+s.w/2,y:s.y+s.h/2}):s.type==="maintenanceRoom"&&Gt(K(s)))}function Ve(s,a,h="primary-button"){let m=document.createElement("button");return m.type="button",m.className=h,m.textContent=s,m.addEventListener("click",a),m}function sn(){e.cardTargetPick?.mode==="autoScannerMenu"&&(e.cardTargetPick=null),t.modal.classList.remove("visible","equipment-popover"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function uo(s){t.modalTitle.textContent="Auto Scanner",e.cardTargetPick={pending:!0,mode:"autoScannerMenu",cardId:null,targetKeys:[`scanner:${s.id}`],remaining:1},t.modalBody.innerHTML=` +
+

Left / right output routing for this AUTO scanner.

+

Current: ${s.role===0?"Male left / others right":"Poop left / others right"}

+

Cooldown: ${nt(s).toFixed(1)}s.

+
`,t.modalActions.innerHTML="";let a=Ve("Male Left / Others Right",()=>{Be(e),s.role=0,sn(),i()},s.role===0?"facility-action warn":"facility-action"),h=Ve("Poop Left / Others Right",()=>{Be(e),s.role=1,sn(),i()},s.role===1?"facility-action warn":"facility-action");t.modalActions.append(a,h,Ve("Close",sn,"facility-action")),fo(s),t.modal.classList.add("visible","equipment-popover"),i()}function br(s){return s?.label||s?.key||"?"}function Js(s){let a=s.key===" "?"Space":s.key.length===1?s.key.toUpperCase():s.key.replace(/^Arrow/,"");return{key:s.key.toLowerCase(),code:s.code,label:a}}function js(s,a,h){for(let m of e.scanners.filter(w=>w.kind==="manual"))for(let w of["left","right"]){if(m.id===s.id&&w===a)continue;let T=m.keys?.[w];if(T&&(T.code===h.code||T.key===h.key))return!0}return!1}function ln(s,a=""){if(!s||s.kind!=="manual")return;t.modalTitle.textContent=`Manual Scanner #${s.id}`;let h=br(s.keys?.left),m=br(s.keys?.right),w=Zs(s);t.modalBody.innerHTML=` +
+

Left route key: ${h}

+

Right route key: ${m}

+ ${a?`

${a}

`:""} + ${w?`

${w}

`:""} +
`,t.modalActions.innerHTML="",t.modalActions.appendChild(Ve("Set Left Key",()=>vr(s,"left"),"facility-action warn")),t.modalActions.appendChild(Ve("Set Right Key",()=>vr(s,"right"),"facility-action warn")),t.modalActions.appendChild(Ve("Close",sn,"facility-action")),fo(s),t.modal.classList.add("visible","equipment-popover")}function Zs(s){let a=[{side:"left",binding:s.keys?.left},{side:"right",binding:s.keys?.right}];if(a[0].binding&&a[1].binding&&(a[0].binding.code===a[1].binding.code||a[0].binding.key===a[1].binding.key))return"Left and right keys conflict.";for(let h of a)if(h.binding)for(let m of e.scanners.filter(w=>w.kind==="manual"&&w.id!==s.id)){if(m.keys?.left&&(m.keys.left.code===h.binding.code||m.keys.left.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} left.`;if(m.keys?.right&&(m.keys.right.code===h.binding.code||m.keys.right.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} right.`}return""}function vr(s,a){t.modalBody.innerHTML=`

Press a key for ${a.toUpperCase()} route.

Esc cancels.

`,t.modalActions.innerHTML="";let h=m=>{if(m.preventDefault(),m.stopPropagation(),window.removeEventListener("keydown",h,!0),m.key==="Escape")return ln(s);let w=Js(m),T=js(s,a,w);Be(e),s.keys=s.keys||{left:null,right:null},s.keys[a]=w,i(),ln(s,T?`${w.label} assigned, but another scanner already uses it.`:`${a.toUpperCase()} set to ${w.label}.`)};window.addEventListener("keydown",h,!0)}function el(){let s=N();if(!(!s||s.type!=="scanner"))return s.kind==="auto"?uo(s):ln(s)}function tl(s){if(!s)return{x:80,y:80};if(s.type==="conveyor"){let a=Z(s.id);return F(a.col,a.row)}return s.type==="eggFarm"?F(s.col,s.row):s.type==="scanner"?ye(s):s.type==="facility"?{x:s.x+s.w/2,y:s.y+10}:{x:80,y:80}}function fo(s){let a=n.getBoundingClientRect(),h=tl(s),m=e.view?.scale||1,w=a.left+(h.x*m+(e.view?.x||0))/n.width*a.width+18,T=a.top+(h.y*m+(e.view?.y||0))/n.height*a.height-12,te=Math.max(12,window.innerWidth-274),j=Math.max(12,window.innerHeight-220);t.modal.style.setProperty("--popover-x",`${Math.max(12,Math.min(te,w))}px`),t.modal.style.setProperty("--popover-y",`${Math.max(12,Math.min(j,T))}px`)}function nl(){let s=N();if(!s)return;let a=Cr(s);t.modalTitle.textContent=J(s),t.modalBody.innerHTML=` +
${a.map(w=>`

${w}

`).join("")}
+ ${["mixer","truck"].includes(s.baseId||s.id)?'

Income/Fine = ceil(base x 1.10^upgrades)

':""}`,t.modalActions.innerHTML="",s.type==="scanner"&&s.kind==="auto"&&t.modalActions.appendChild(Ve("Auto Menu",()=>uo(s),"facility-action warn")),s.type==="scanner"&&s.kind==="manual"&&t.modalActions.appendChild(Ve("Set Keys",()=>ln(s),"facility-action warn"));let h=s.type==="conveyor"?{type:"conveyor",oldKey:s.id,ref:s}:{type:s.type,ref:s},m=Ae(h);if(m){let w=Ve(m,()=>{},"facility-action danger disabled");w.disabled=!0,t.modalActions.appendChild(w)}else{let w=ht(h,e),T=w.sameBuild?`Remove / Refund ${g(w.amount)}`:`Sell ${g(w.amount)}`;t.modalActions.appendChild(Ve(T,()=>{mr(),sn()},"facility-action danger"))}fo(s),t.modal.classList.add("visible","equipment-popover")}function ol(s){e.phase==="build"&&(y(),e.buildTool=e.buildTool===s?null:s,e.selected=null,e.multiSelected=[],e.selectionBox=null,i())}function rl(){let s=[];for(let[a,h]of Object.entries(e.facilities))if(s.push({id:`facility:${a}`,price:Q({type:"facility",ref:h}),x:h.x,y:h.y,w:h.w,h:h.h}),h.entry){let m=F(h.entry.col,h.entry.row);s.push({id:`facilityPort:${a}`,price:Q({type:"facility",ref:h}),x:m.x-18,y:m.y-18,w:36,h:36})}for(let a of e.maintenanceRooms||[]){let h=K(a);s.push({id:`maintenanceRoom:${a.id}`,price:Q({type:"maintenanceRoom",ref:a}),x:h.x-f.cell,y:h.y-f.cell,w:f.cell*2,h:f.cell*2})}for(let a of e.eggFarms){let h=F(a.col,a.row);s.push({id:`eggFarm:${a.id}`,price:Q({type:"eggFarm",ref:a}),x:h.x-24,y:h.y-24,w:48,h:48})}for(let a of e.scanners){let h=ye(a);s.push({id:`scanner:${a.id}`,price:Q({type:"scanner",ref:a}),x:h.x-50,y:h.y-73,w:100,h:146})}for(let a of e.conveyorTiles){let h=Z(a),m=F(h.col,h.row),w=e.conveyorMeta.get(a)||{};s.push({id:`conveyor:${a}`,price:w.price||Oe(w.kind==="boostConveyor"?"boostConveyor":"conveyor",e),x:m.x-22,y:m.y-22,w:44,h:44})}return s}function il(s){return R[s]||R.random}function Hc(s){return Sn(s)}function wr(s){return e.conveyorTiles.has(s)?Te(Z(s)):!1}function Sr(s){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return null;for(let a of e.conveyorTiles){if(!wr(a))continue;let h=Z(a),m=F(h.col,h.row),w=m.x-B.w/2,T=m.y+B.y-B.h/2;if(s.x>=w&&s.x<=w+B.w&&s.y>=T&&s.y<=T+B.h)return a}return null}function sl(s){let a=Sr(s);return a?(kr(a),!0):!1}function kr(s){let a=e.conveyorMeta.get(s);if(!a)return!1;let h=ro(s);if(h.length<2)return!1;Be(e);let m=E.includes(a.branchMode)?a.branchMode:"random",w=["random",...de.map(T=>T.name).filter(T=>h.includes(T))];return a.branchMode=w[(Math.max(0,w.indexOf(m))+1)%w.length],e.selected=null,e.multiSelected=[],i(),!0}function Cr(s){Se(e);let a=[],h=s?.type==="facility"?s.baseId||s.id:"";if(s.type==="eggFarm"){let[m,w]=dn(s);a.push(`Price: ${g(Q(s))}`);{let T=Ae({type:s.type,ref:s});a.push(T?`Sale: blocked (${T})`:`Sale value: ${g(ht({type:s.type,ref:s},e).amount)}`)}a.push(`Level: ${s.level}/4`),a.push(`Random interval: ${m.toFixed(2)}-${w.toFixed(2)}s`),a.push(`Durability: ${bn(s)}% | Spawn delay x${Hn(s).toFixed(2)}`)}else if(s.type==="scanner")a.push(`Price: ${g(Q(s))}`),a.push(`Sale value: ${g(ht({type:s.type,ref:s},e).amount)}`),a.push(`Type: ${s.kind.toUpperCase()} / Standard`),s.kind==="auto"&&a.push(`Role: ${s.role===0?"Male left / Others right":"Poop left / Others right"}`),a.push(`Queue: ${s.queue.length}`),s.kind==="auto"&&a.push(`Cooldown: ${s.cooldown.toFixed(1)}s / ${nt(s,e).toFixed(1)}s`),s.kind==="auto"&&a.push(`Durability: ${bn(s)}% | Delay x${Kn(s).toFixed(2)}`),s.kind==="manual"&&a.push("Durability: none | Always normal");else if(s.type==="conveyor"){let m=e.conveyorMeta.get(s.id),w=e.componentLookup?.get(s.id),T=w?e.congestion.get(w):null;a.push(`Price: ${g(Q({type:"conveyor",oldKey:s.id,ref:s}))}`),a.push(`Cell: ${s.id}`),a.push(`Type: ${m?.kind==="boostConveyor"?"BOOST BELT":"Normal Belt"} | Speed x${Number(m?.speedMultiplier||1).toFixed(1)}`),a.push(`Congestion: ${T?Math.floor(T.ratio*100):0}%`),a.push(`Durability: ${bn({meta:m})}% | Speed x${Wn({meta:m}).toFixed(2)}`),wr(s.id)?(a.push(`Branch mode: ${il(m?.branchMode||"random")}`),a.push("Use the Branch button below or the on-belt branch badge.")):a.push("Branch mode: needs 3+ conveyor connections."),a.push(`Sale value: ${g(ht({type:"conveyor",oldKey:s.id,ref:s},e).amount)}`)}else if(s.type==="maintenanceRoom")a.push(`Price: ${g(Q({type:"maintenanceRoom",ref:s}))}`),a.push(`Sale value: ${g(ht({type:"maintenanceRoom",ref:s},e).amount)}`),a.push("Size: 2\xD72 grid cells"),a.push("Dispatch: 1 repairman during each production day");else if(s.type==="facility"){a.push(`Price: ${g(Q(s))}`);{let m=Ae({type:s.type,ref:s});a.push(m?`Sale: blocked (${m})`:`Sale value: ${g(ht({type:s.type,ref:s},e).amount)}`)}if(a.push(["mixer","truck","trash"].includes(s.id)?`Level: ${s.level} / no cap`:`Level: ${s.level}`),h==="truck"&&a.push("Durability: none | Always normal"),["mixer","trash"].includes(h)&&a.push(`Durability: ${bn(s)}% | Extra delay ${Jo(e,s).toFixed(2)}s`),h==="mixer"&&(a.push(`Income: ${g(ze(e))} per chick | upgrade x${pt(e,"mixer").toFixed(3)}`),a.push(`Poop fine: -${g(pn(e))}`)),h==="truck"&&(a.push(`Income: ${g(Fe(e))} per target cargo | upgrade x${pt(e,"truck").toFixed(3)}`),a.push(`Poop shipment fine: -${g(yn(e))}`)),h==="trash"){let m=$t(e),w=yt(m);a.push(`Bonus cards: ${m}/${Vt()}`),a.push(`Poop income bonus: ${g(w)} per processed poop.`),a.push("With enough upgrades, poop can out-earn male/female routes.")}s.entry&&a.push(`Receiver: edge cell ${s.entry.col},${s.entry.row} (${s.side})`)}return a}function ll(s){if(!s||e.phase!=="build")return"";let a=Fn(e).find(h=>h.type===s.type&&h.id===s.id);return a?a.message||"Not connected to conveyor route":""}function al(s){return s?s.type==="conveyor"&&e.conveyorMeta.get(s.id)?.kind==="boostConveyor"?"Moves chicks twice as fast. Wears down like a normal belt.":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"?"Slower than hands without upgrades.":s.type==="scanner"?"A manual checkpoint. The operator is the algorithm.":s.type==="facility"&&(s.baseId||s.id)==="mixer"?"Male chicks become revenue here. Do not feed it poop.":s.type==="facility"&&(s.baseId||s.id)==="trash"?"Poop goes in. Sometimes coins come out, for reasons best left unaudited.":s.type==="facility"&&(s.baseId||s.id)==="truck"?"The shipping endpoint. Correct cargo pays; wrong cargo complains.":s.type==="maintenanceRoom"?"A 2\xD72 repair bay. One room dispatches one repairman per day.":"Factory equipment.":""}return{buildAtCell:b,buildAtPoint:C,eraseAtPoint:Gt,equipmentAtPoint:co,startSelectionBox:Ut.startSelectionBox,updateSelectionBox:Ut.updateSelectionBox,finishSelectionBox:Ut.finishSelectionBox,startGroupDrag:Ut.startGroupDrag,updateGroupDrag:Ut.updateGroupDrag,finishGroupDrag:Ut.finishGroupDrag,selectedObject:N,selectedTitle:J,equipmentPrice:Q,selectedUpgradeCost:Qs,selectedInfoLines:Cr,flavorText:al,disconnectedWarningFor:ll,gridExpansionCost:O,buyGridExpansion:le,expansionOfferAtPoint:he,beginConveyorDrag:ao,continueConveyorDrag:d,endConveyorDrag:y,cycleSingleConveyorDirection:Ct,branchSwitcherAtPoint:Sr,cycleBranchModeAtPoint:sl,cycleBranchModeForKey:kr,removeSelected:mr,switchScannerRole:el,showManualScannerMenu:ln,showAutoScannerMenu:uo,showSelectedMenu:nl,setBuildTool:ol,fail:_,isEquipmentCell:D,equipmentHitBoxes:rl,routeFromFarmToScanner:It}}function Ds({game:e,ui:t,build:n,startGame:o,beginCardDraft:r,activeQueuedChick:i}){function l(D){return String(D).replace(/[&<>"']/g,U=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[U])}function c(){return Math.round(Vn(e))}function v(){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return!1;let D=!1;for(let U of vo)if(D=!0,e.cash>=Oe(U,e))return!1;return D}function x(){E(),R(),ee(),O(),B()}function E(){for(let[U,S]of Object.entries(t.buttons))S?.classList?.contains("tool-button")&&S.classList.toggle("active",e.buildTool===U);for(let U of vo){let S=t.buttons[U];if(!S)continue;let M=Oe(U,e),N=S.querySelector("span");N&&(N.textContent=U==="conveyor"||U==="boostConveyor"?`${g(M)} / tile`:g(M));let J=U==="manualScanner"&&e.scanners.filter(pe=>pe.kind==="manual").length>=8,Q=e.cashIt(e,J)?.scannerId).length,U=fn(e),S=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),M=Math.max(1,Number(e.turn)||1),N=On(e,M,S);t.turnSummary.innerHTML=[`Seed: ${l(e.runSeed||"none")} | Grid box: ${e.gridRows||10}x${e.gridCols||20} | Owned: ${e.gridOwnedCells||e.ownedCells?.size||(e.gridRows||10)*(e.gridCols||20)} cells | Blocked: ${e.blockedCells?.size||0} cells`,`Truck target: ${je(e).toUpperCase()} | Male fine: -${g(_o(e))}`,`Poop fine: Mixer -${g(pn(e))} / Shipment -${g(yn(e))}`,`Fairies tribute on Next Day: -${g(N.amount)} | base ${g(N.base)} + profit share ${g(N.profitTribute)} | basis net ${g(S)} | exemption ${g(N.profitExemption)}${N.reduction?` | reduction -${g(N.reduction)}`:""}`,`Maintenance: worst ${tr(e).worst.percent}% dirty (${tr(e).worst.label}) | Repair rooms: ${(e.maintenanceRooms||[]).length} | Repairmen: ${(e.repairmen||[]).length}`,`Manual combo: ${e.manualCombo?.count||0} | Card draft: ${e.cardDraft?.pending?Math.max(1,e.cardDraft.picksRemaining||1)+" pick(s) left":"ready after each day"} | Belt: ${c()}px/s | Farms with scanner route: ${D}/${e.eggFarms.length}`,e.cardEffects?.usedMachineActive?'Procurement: USED MACHINE MODE / no refunds / 60% durability':"",U.length?`Blocked: ${U[0]}`:`${oe.status.allPortsConnected}`].join("
")}function ee(){if(!t.eventPanel)return;let D=e.eventOffer;if(e.phase!=="build"){t.eventPanel.innerHTML=oe.status.eventPanelRunning;return}if(!D){t.eventPanel.className="event-card empty",e.turn+1Event lock active.No irregular events during Days 1-7. First possible forced event: Day ${gt}.`:t.eventPanel.innerHTML="No event.Random forced events can appear later.";return}t.eventPanel.className="event-card accepted",t.eventPanel.innerHTML=` +
FORCED NEXT DAY
+

${D.title}

+
+ Effect: ${D.route} + ${D.targetAmount?`Target: ${D.targetAmount}`:"Target: none"} + ${D.reward?`Reward: ${g(D.reward)}`:"Reward: none"} + Time ${D.daySeconds||60}s / Output x${Number(D.productionMultiplier||1).toFixed(2)} / Poop +${Math.round((D.poopRateAdd||0)*100)}pt +
`}function X(){E(),t.shell.classList.toggle("phase-running",e.phase==="running"),t.shell.classList.toggle("phase-build",e.phase==="build"),t.shell.classList.toggle("phase-gameover",e.phase==="gameover"),t.shell.classList.toggle("phase-title",e.phase==="title"),t.shell.classList.toggle("phase-loanDecision",e.phase==="loanDecision"),t.money.textContent=g(e.cash),t.money.classList.toggle("cash-negative",e.cash<0),t.money.classList.toggle("cash-positive",e.cash>an),t.turn.textContent=e.turn,t.timeLeft.textContent=e.phase==="running"&&e.timeLeft<=0&&e.shutdownTimeLeft>0?`+${e.shutdownTimeLeft.toFixed(1)}s`:`${Math.max(0,e.timeLeft).toFixed(1)}s`,t.timeLeft.closest?.(".hud-card")?.classList.toggle("time-critical",e.phase==="running"&&(e.timeLeft<=10||e.timeLeft<=0&&e.shutdownTimeLeft>0)),t.phase.textContent=he(),t.comboCount&&(t.comboCount.textContent=e.manualCombo?.count||0),ae(),t.turnProfit.textContent=g(e.stats.profit),t.turnProfit.classList.toggle("cash-negative",e.stats.profit<0),t.turnProfit.classList.toggle("cash-positive",e.stats.profit>0),t.mixerCount.textContent=e.stats.mixerCount,t.truckFemaleCount.textContent=e.stats.truckFemale,t.truckMaleCount.textContent=e.stats.truckMale,t.poopCount.textContent=e.stats.poopSpawned,t.buttons.s1Left.disabled=e.phase!=="running"||!i(0),t.buttons.s1Right.disabled=e.phase!=="running"||!i(0),t.buttons.s2Left.disabled=e.phase!=="running"||!i(1),t.buttons.s2Right.disabled=e.phase!=="running"||!i(1);let D=e.scanners.find(N=>N.kind==="manual"&&N.slot===0),U=e.scanners.find(N=>N.kind==="manual"&&N.slot===1);D&&(t.buttons.s1Left.textContent=`S1 ${D.keys?.left?.label||"A"} -> Mixer`,t.buttons.s1Right.textContent=`S1 ${D.keys?.right?.label||"D"} -> S2`),U&&(t.buttons.s2Left.textContent=`S2 ${U.keys?.left?.label||"Left"} -> Waste`,t.buttons.s2Right.textContent=`S2 ${U.keys?.right?.label||"Right"} -> Truck`);let S=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),M=On(e,Math.max(1,Number(e.turn)||1),S).amount;t.buttons.nextTurn.textContent=e.phase==="build"&&M>0?`Next Day - Fairies ${g(M)}`:oe.actions.nextDay,t.buttons.nextTurn.disabled=e.phase!=="build"||!!e.cardDraft?.pending||!!e.cardTargetPick?.pending||!fi(e)}function ae(){if(!t.eventBrief||!t.targetBrief||!t.speedBrief)return;let D=je(e).toUpperCase();t.targetBrief.textContent=`TRUCK TARGET: ${D}`,t.speedBrief.textContent=`BELT: ${c()} px/s | COMBO: ${e.manualCombo?.count||0}`,t.speedBrief.title=`Conveyor speed does not increase by day. Degraded belts reduce speed. Cap: ${Wt}px/s.`;let U=e.eventActive,S=e.eventOffer;U?(t.eventBrief.textContent=`ACTIVE EVENT: ${U.title} | ${U.route}`,t.eventBrief.className="event-brief active"):e.phase==="build"&&S?(t.eventBrief.textContent=`NEXT DAY EVENT: ${S.title} | ${S.route}${S.targetAmount?` | Target ${S.targetAmount}`:""}${S.reward?` | Reward ${g(S.reward)}`:""}`,t.eventBrief.className="event-brief next"):e.phase==="build"&&e.turn+1
\u2642Male->MixerS1: A
\u2640Female->TruckS1: D, then S2: right
\u{1F4A9}Poop->ShredderS1: D, then S2: left

Build phase: connect at least one EGG through a scanner to Mixer, Shredder, or Truck before Next Day. One day is one run.

',t.modalActions.innerHTML="",t.modalActions.appendChild(G(oe.actions.startGame,o,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function le(D){let U=J=>`${J>0?"+":""}${g(J)}`,S=J=>`${J>0?"-":""}${g(J)}`,M=D.profit>=0?"cash-positive":"cash-negative",N=(D.mixerPoopFine||0)+(D.truckPoopFine||0)+(D.maleTruckFine||0)+(D.explosionDamage||0)+(D.cardRerollCost||0);t.modalTitle.textContent=`Day ${D.turn} Settlement`,t.modalBody.innerHTML=` +
Net result${g(D.profit)}
+
+
Chick shipment income${U(D.chickShipmentIncome||0)}
+
Poop shipment income${U(D.poopShipmentIncome||0)}
+
Mixer income${U(D.mixerRevenue||0)}
+
Composter income${U(D.composterIncome||0)}
+
DUD refund income${U(D.dudRefundIncome||0)}
+
Manual combo bonus${U(D.manualComboBonus||0)}
+
Chemical subsidy${U(D.chemicalWeaponSubsidy||0)}
+
Event bonus${U(D.eventBonus||0)}
+
Penalties${S(N)}
+
Fairies fee${S(D.fairiesTribute?.amount||D.fairiesTribute||0)}
+
+

Income ${g(D.revenue)} - losses ${g(D.penalty)} = ${g(D.profit)}

`,t.modalActions.innerHTML="",t.modalActions.appendChild(G("Choose Upgrade Card",r||q,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function se(D,U){let S=Math.max(0,e.cardEffects?.rescueLoanCharges||0);t.modalTitle.textContent="Emergency Loan Available",t.modalBody.innerHTML=` +

End-of-day cash is below ${g(0)}.

+
+
Current money${g(e.cash)}
+
Emergency Loan+${g(500)}
+
Cards remaining${S}
+
+

Use one Emergency Loan to gain ${g(500)} immediately. If cash is still negative, another decision will be shown if another card remains.

`,t.modalActions.innerHTML="",t.modalActions.appendChild(G("Accept Game Over",U,"facility-action danger")),t.modalActions.appendChild(G("Use Emergency Loan",D,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function A(){let D=e.totals.processed,U=D?Math.round(e.totals.correct/D*100):0,S=Oi(e);t.modalTitle.textContent=oe.phases.gameover,t.modalBody.innerHTML=`

Your cash went negative.

+
Final Score${S.score}
Survival${e.totals.turnsCompleted} days
Final Cash${g(e.cash)}
Accuracy${U}%
+
Score breakdown +
Formula
Base = Cash + Total revenue + Factory value \xD70.5 + Event bonus \xD70.5 = ${g(S.base)}
Daily earned = ceil(Base \xF7 Days) = ${g(S.dailyEarned)}
Score = max(0, floor(Base + Daily earned + Correct bonus - Total outflow - Day penalty)) = ${S.score}
+
Factory Value${g(S.factoryValue)}
Total Revenue${g(e.totals.revenue)}
Daily Earned${g(S.dailyEarned)} / day
Total Outflow${g(e.totals.penalty)}
Fairies Tribute${g(e.totals.fairiesTribute||0)}
Correct Sorts${e.totals.correct}
Auto Sorted${e.totals.autoSorted}
Poop Control${e.totals.poopTrash} trashed / ${e.totals.poopTruck} shipped / ${e.totals.poopMixer} mixer
Explosion Penalty${g(e.totals.explosionDamage)}
Event Bonus${g(e.totals.eventBonus)}
Day Penalty-${S.dayPenalty}
Events${e.totals.eventSuccess} success / ${e.totals.eventFailed} failed
+
`,t.modalActions.innerHTML="",t.modalActions.appendChild(G(oe.actions.restart||"Restart",o,"primary-button restart-button")),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible","gameover-modal")}function G(D,U,S="primary-button"){let M=document.createElement("button");return M.type="button",M.className=S,M.textContent=D,M.addEventListener("click",U),M}function q(){t.modal.classList.remove("visible","equipment-popover","gameover-modal"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function me(){}return{updatePanels:x,updateUI:X,showTitle:ie,showTurnResult:le,showEmergencyLoanDecision:se,showGameOver:A,hideModal:q,checkGameOver:me}}function hr(e){e.totals.processed+=1}function Zt(e){e.stats.correct+=1,e.totals.correct+=1}function vt(e){e.stats.mistakes+=1,e.totals.mistakes+=1}function Fs(e){e.stats.autoSorted+=1,e.totals.autoSorted+=1}function Bs(e){e.stats.poopSpawned+=1}function Ls(e){e.stats.mixerCount+=1,hr(e)}function Os(e){e.stats.trashCount+=1,hr(e)}function Ns(e,t){t==="female"?e.stats.truckFemale+=1:t==="male"&&(e.stats.truckMale+=1),hr(e)}function Zn(e,t){let n=t==="truck"?"poopTruck":t==="trash"?"poopTrash":t==="mixer"?"poopMixer":null;n&&(e.stats[n]+=1,e.totals[n]+=1)}function _s({game:e,currentConveyorSpeed:t,onGameOverCheck:n}){function o(d){return Rt(d)*Hn(d)*us(e)/wi(e)}function r(d){let y=F(d.col,d.row),b=1+ds(e,d),C=l(d,b);if(!C.length)return i(d,y),!0;let k=0,P=0;for(let $ of C){let K=F($.col,$.row),re=c(K);if(re){re.stoppedTimer=.85,P+=1;continue}let Ne=As(e,{stage:"belt",scannerId:null,route:[K]});Ne.sex==="poop"&&Bs(e),e.chicks.push(Ne),Xi(e,d),k+=1}return k>0?(_i(e,y.x,y.y),k>1&&H(e,y.x,y.y-28,`x${k}`,p.green),!0):P===0}function i(d,y){(d.noRouteNoticeCooldown||0)<=0&&(H(e,y.x,y.y-24,"NO BELT: PAUSED",p.warn),d.noRouteNoticeCooldown=2.5)}function l(d,y){let C=de.map(k=>({col:d.col+k.dc,row:d.row+k.dr})).filter(k=>Ee(k.col,k.row)&&e.conveyorTiles.has(I(k.col,k.row))).map(k=>({p:k,blocked:B(null,F(k.col,k.row))?1:0,roll:Math.random()}));return C.sort((k,P)=>k.blocked-P.blocked||k.roll-P.roll),C.slice(0,Math.max(1,y||1)).map(k=>k.p)}function c(d){return e.chicks.find(y=>y.stage!=="flying"&&Math.hypot(y.x-d.x,y.y-d.y)0;if(e.timeLeft=Math.max(0,e.timeLeft-d),C&&e.timeLeft<=0&&y(),e.timeLeft<=0){e.shutdownTimeLeft>0&&(e.shutdownTimeLeft=Math.max(0,e.shutdownTimeLeft-d));for(let k of e.eggFarms)k.shutterProgress=Math.min(1,(k.shutterProgress||0)+d*2.8)}if(C&&e.timeLeft>0){for(let k of e.eggFarms)if(k.noRouteNoticeCooldown>0&&(k.noRouteNoticeCooldown=Math.max(0,k.noRouteNoticeCooldown-d)),k.nextSpawn-=d,k.nextSpawn<=0){let P=r(k);k.nextSpawn=P?o(k):.15,k.lastInterval=k.nextSpawn}}for(let k=e.chicks.length-1;k>=0;k-=1){let P=e.chicks[k];P.bob+=d*7,P.stoppedTimer>0&&(P.stoppedTimer=Math.max(0,P.stoppedTimer-d)),P.stage!=="queued"&&E(P,k,d)}_(d),_t(),on(),e.timeLeft<=0&&(e.chicks.length===0?b():e.shutdownTimeLeft<=0&&x())}function x(){if(e.cleanupBlown)return;e.cleanupBlown=!0,e.cleanupTimer=1;let d=[...e.chicks];for(let y of d)Ko(e,y.sex,y.x,y.y,-Math.PI/2,!0);e.chicks=[];for(let y of e.scanners)y.queue=[];if(_t(),d.length){let y=d.reduce((C,k)=>C+k.x,0)/d.length,b=d.reduce((C,k)=>C+k.y,0)/d.length;Xe(e,y,b,p.warn,58),H(e,y,b-24,"CLEANUP",p.warn)}}function E(d,y,b){if(R(d)){d.stoppedTimer=.35;return}if(pe(d,b),!(d.route&&d.targetIndex=d.route.length)return!1;let y=d.route[d.targetIndex];return B(d,y)}function B(d,y){if(!y)return!1;for(let b of e.chicks)if(!(d&&b.id===d.id)&&b.stage!=="flying"&&Math.hypot(b.x-y.x,b.y-y.y)1)&&d.push({x:y.x,y:y.y})}function ee(d){let y=e.conveyorMeta?.get?.(d)||{},b=[];Array.isArray(y.outDirs)&&b.push(...y.outDirs),y.dir&&b.push(y.dir);let C=[...new Set(b)].filter(re=>de.some(Ne=>Ne.name===re)),k=Z(d),P=de.filter(re=>A(k,re.name)).map(re=>re.name),$=C.filter(re=>P.includes(re)),K=P;return $.length?$:K}function X(d){return de.find(y=>y.name===d)||null}function ae(d,y){return e.scanners.find(b=>b.col<=d&&d<=b.col+1&&b.row-1<=y&&y<=b.row+1)||null}function he(d,y){let b=X(y);if(!b)return null;let C=ae(d.col+b.dc,d.row+b.dr);if(!C)return null;let k=Re(C,"inputA");return k&&k.col===d.col&&k.row===d.row?C:null}function ie(d){return Object.entries(e.facilities||{}).find(([,y])=>y?.entry&&y.entry.col===d.col&&y.entry.row===d.row)||null}function le(d){return d?.baseId||d?.id||""}function se(d,y){return d.side==="left"&&y==="left"||d.side==="right"&&y==="right"||d.side==="top"&&y==="up"||d.side==="bottom"&&y==="down"}function A(d,y){let b=X(y);if(!b)return null;let C={col:d.col+b.dc,row:d.row+b.dr};if(Ee(C.col,C.row)&&e.conveyorTiles.has(I(C.col,C.row)))return{type:"conveyor",dirName:y,target:F(C.col,C.row),nextCell:C};let k=he(d,y);if(k)return{type:"scanner",dirName:y,target:ye(k),scanner:k};let P=ie(d);return P&&se(P[1],y)?{type:"facility",dirName:y,facilityId:P[0],facility:P[1],target:F(d.col,d.row)}:null}function G(d,y){let b=X(y);if(!b)return!1;let C=e.conveyorMeta?.get?.(I(d.col+b.dc,d.row+b.dr));return C?[...new Set([...Array.isArray(C.outDirs)?C.outDirs:[],C.dir].filter(Boolean))].includes(b.opposite):!1}function q(d){return de.filter(y=>Ee(d.col+y.dc,d.row+y.dr)&&e.conveyorTiles.has(I(d.col+y.dc,d.row+y.dr))).map(y=>y.name)}function me(d,y,b="random"){let C=q(d);if(C.length<3)return y;let k=new Set(C.filter(K=>G(d,K)));if(b&&b!=="random"&&b!=="pass"&&C.includes(b)){let K=new Set(k);K.add(b),C.filter(re=>!K.has(re)).length>=2&&k.add(b)}let P=C.filter(K=>!k.has(K));if(P.length)return P;let $=y.filter(K=>!k.has(K));return $.length?$:y}function D(d,y){return y&&(y.type==="facility"||!B(d,y.target))}function U(d,y,b,C="random"){let k=b.map(re=>A(y,re)).filter(Boolean);if(!k.length)return null;let $=k.filter(re=>re.type!=="facility").filter(re=>!B(d,re.target)),K=$.length?$:k.filter(re=>re.type==="facility");return K.length?K[Math.floor(Math.random()*K.length)]:null}function S(d,y){let b=[];O(b,{x:d.x,y:d.y}),O(b,y),d.route=b.length?b:[{x:d.x,y:d.y}],d.targetIndex=d.route.length>1?1:d.route.length}function M(d,y){let b=Ke(d.x,d.y);if(!b)return xt(y,"OFF GRID");let C=I(b.col,b.row);if(!e.conveyorTiles.has(C))return xt(y,"OFF BELT");let k=e.conveyorMeta?.get(C)||{},P=me(b,ee(C),k.branchMode||"random");if(!P.length){d.stoppedTimer=.25;return}let $=U(d,b,P,k.branchMode||"random");if(!$){d.stoppedTimer=.25;return}if($.type==="facility"){let K=le($.facility);K==="mixer"?io(y,$.facility):K==="truck"?kn(y,$.facility):K==="trash"?so(y,$.facility):xt(y,"DONE");return}$.type==="scanner"&&(d.pendingScannerId=$.scanner.id),d.prevConveyorCell=C,S(d,$.target)}function N(d){let y=Ke(d.x,d.y);if(!y)return null;let b=I(y.col,y.row);return e.conveyorTiles.has(b)?b:null}function J(d){let y=N(d)||N(d.route?.[d.targetIndex]||d);return t(y)}function Q(d,y){let b=N(y);!b||d.lastWearKey===b||(d.lastWearKey=b,zi(e,b))}function pe(d,y){let b=J(d)*y;for(;b>0&&d.targetIndex=$?(d.x=C.x,d.y=C.y,Q(d,C),d.targetIndex+=1,b-=$):(d.x+=k/$*b,d.y+=P/$*b,b=0)}}function ge(d,y,b){d.stage="queued",d.route=null,d.queueRoute=b?b.map(C=>({x:C.x,y:C.y})):[ye(y)],d.scannerId=y.id,y.queue.includes(d.id)||y.queue.push(d.id),Pe(y)}function Pe(d){d.queue=d.queue.filter(b=>e.chicks.some(C=>C.id===b&&C.stage==="queued"));let y=f.cell*.86*fs(e);d.queue.forEach((b,C)=>{let k=e.chicks.find(P=>P.id===b);k&&(Ae(k,k.queueRoute||[ye(d)],C*y),k.queueIndex=C)})}function Ae(d,y,b){if(!y||!y.length)return;if(y.length===1||b<=0){let P=y[y.length-1];d.x=P.x,d.y=P.y;return}let C=b;for(let P=y.length-1;P>0;P-=1){let $=y[P-1],K=y[P],re=Math.hypot(K.x-$.x,K.y-$.y);if(C<=re){let Ne=1-C/re;d.x=$.x+(K.x-$.x)*Ne,d.y=$.y+(K.y-$.y)*Ne;return}C-=re}let k=y[0];d.x=k.x,d.y=k.y}function _(d){for(let y of e.scanners){if(y.cooldown>0&&(y.cooldown=Math.max(0,y.cooldown-d)),y.keyPressTime>0&&(y.keyPressTime=Math.max(0,y.keyPressTime-d)),Pe(y),y.kind!=="auto"||y.cooldown>0||!y.queue.length)continue;let b=y.queue[0],C=e.chicks.findIndex(k=>k.id===b);if(C<0){y.queue.shift();continue}nn(C,Ao(y,e.chicks[C]),!0)&&(Qi(e,y),y.cooldown=nt(y,e),Fs(e))}}function Ie(d){let y=To(e,d);return!y||!y.queue.length?null:e.chicks.find(b=>b.id===y.queue[0])||null}function qe(d,y){if(e.phase!=="running")return;let b=To(e,d);Ye(b,y)}function Ye(d,y){if(e.phase!=="running"||!d||d.kind!=="manual"||(d.keyPressTime=.18,d.keyPressSide=y,!d.queue.length))return;let b=e.chicks.findIndex(C=>C.id===d.queue[0]);b>=0&&nn(b,y,!1)}function Te(d,y,b){return d.kind==="manual"&&Ao(d,y)===b}function kt(d){let y=e.manualCombo?.count||0;if(e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=0,e.manualCombo.lastBonus=0,e.stats.manualComboFailure=(e.stats.manualComboFailure||0)+1,e.totals.manualComboFailure=(e.totals.manualComboFailure||0)+1,y>=10){let b=ye(d);Ft(e,10,.25),H(e,b.x,b.y-36,"COMBO RESET",p.danger)}}function oo(d){e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=Math.max(0,e.manualCombo.count||0)+1,e.stats.manualComboSuccess=(e.stats.manualComboSuccess||0)+1,e.totals.manualComboSuccess=(e.totals.manualComboSuccess||0)+1;let y=e.manualCombo.count;if(e.manualCombo.lastBonus=0,y<10)return 0;let b=Math.max(1,Math.floor(y/10)),C=e.scanners.filter(K=>K.kind==="manual").length,k=Math.min(1,(20+C*10)/100),P=0;for(let K=0;K0){Ge(e,$),e.stats.manualComboBonus=(e.stats.manualComboBonus||0)+$,e.totals.manualComboBonus=(e.totals.manualComboBonus||0)+$,e.manualCombo.lastBonus=$;let K=ye(d);H(e,K.x,K.y-42,`COMBO +${g($)}`,p.green)}return $}function Sn(d,y){let b=Re(d,y);if(!b)return null;let C=I(b.col,b.row);if(e.conveyorTiles.has(C))return{...b};let P=(_e(e).scannerPorts.get(d.id)?.[y]?.keys||[]).filter(Boolean);if(!P.length)return null;let $=P.map(Z);return $.find(re=>re.col===b.col&&re.row===b.row)||$[0]||null}function ro(d,y,b,C){let k=[];O(k,{x:d.x,y:d.y});let P=Re(y,b);return P&&O(k,F(P.col,P.row)),O(k,F(C.col,C.row)),k}function nn(d,y,b){let C=e.chicks[d];if(!C||C.stage!=="queued")return!1;let k=At(e,C.scannerId);if(!k)return!1;let P=Sn(k,y);if(!P)return!b&&k.kind==="manual"&&kt(k),H(e,C.x,C.y-16,y==="left"?"NO LEFT BELT":"NO RIGHT BELT",p.danger),!1;!b&&k.kind==="manual"&&(Te(k,C,y)?oo(k):kt(k)),k.queue=k.queue.filter(K=>K!==C.id),C.stage="belt",C.route=ro(C,k,y,P),C.targetIndex=C.route.length>1?1:C.route.length,C.scannerId=null,C.nextScannerId=null,C.pendingScannerId=null,C.queueRoute=null,C.queueIndex=-1;let $=b?p.green:y==="left"?p.mixerBlue:p.truckPink;return Gi(e,ye(k).x,ye(k).y,$),H(e,C.x,C.y-20,b?"AUTO":y.toUpperCase(),$),!0}function Ct(d){let y=e.chicks[d];return y?(e.chicks.splice(d,1),y):null}function io(d,y=e.facilities.mixer){if(y?.processingCooldown>0){let $=e.chicks[d];$&&($.stoppedTimer=.25);return}let b=Ct(d);if(!b)return;let{x:C,y:k}=b;if(Ls(e),jo(e,y),Zo(e,y),b.sex==="poop"){let $=Ai(e);Zn(e,"mixer"),vt(e),Wi(e,C,k),H(e,C,k-18,`-${g($)}`,p.danger);return}let P=Pi(e);b.sex==="male"?Zt(e):vt(e),Ui(e,C,k),H(e,C,k-18,`+${g(P)}`,p.green)}function kn(d,y=e.facilities.truck){let b=Ct(d);if(!b)return;let{x:C,y:k}=b;lo(b.sex,y),Hi(e,C,k,b.sex),Ns(e,b.sex);let P=je(e),$=ki(e,b.sex);if(b.sex==="poop"){if(Zn(e,"truck"),$)Zt(e),H(e,C,k-18,`+${g(Fe(e))}`,p.green);else{let K=Ii(e);vt(e),H(e,C,k-18,`-${g(K)}`,p.danger)}return}if(b.sex==="female"){$?(Zt(e),H(e,C,k-18,`+${g(Fe(e))}`,p.green)):(vt(e),H(e,C,k-18,P==="male"?"REJECT":"NO SALE",p.warn));return}if($){Zt(e),H(e,C,k-18,`+${g(Fe(e))}`,p.green);return}if(Ci(e)){let K=$i(e);vt(e),H(e,C,k-18,`-${g(K)}`,p.danger)}else vt(e),H(e,C,k-18,"REJECT",p.warn)}function so(d,y=e.facilities.trash){if(y?.processingCooldown>0){let K=e.chicks[d];K&&(K.stoppedTimer=.25);return}let b=Ct(d);if(!b)return;let{x:C,y:k}=b;Ki(e,C,k,b.sex),Os(e),jo(e,y),Zo(e,y);let P={amount:0},$="";if(b.sex==="poop"){P=Ti(e),$=P.amount>0?` +${g(P.amount)}`:"",Zn(e,"trash"),Zt(e);let K=Math.ceil(Math.max(0,Number(e.cardEffects?.composter)||0)*3*Bn(e));if(K>0){let re=Ge(e,K);e.stats.composterIncome=(e.stats.composterIncome||0)+re,e.totals.composterIncome=(e.totals.composterIncome||0)+re,H(e,C,k-36,`COMPOST +${g(re)}`,p.green)}H(e,C,k-18,`CLEAN${$}`,P.amount>0?p.green:p.green)}else vt(e),H(e,C,k-18,P.amount>0?`WASTE${$}`:"WASTE",P.amount>0?p.green:p.ink)}function xt(d,y){let b=Ct(d);b&&H(e,b.x,b.y-12,y,p.muted)}function lo(d,y=e.facilities.truck){let b=y||e.facilities.truck;b&&(e.truckCargo.push({sex:d,x:W(22,b.w-22),y:W(66,b.h-24)}),e.truckCargo.length>45&&e.truckCargo.shift())}function Cn(d){let y=Ke(d.x,d.y);if(y){let P=I(y.col,y.row);if(e.conveyorTiles.has(P))return P}let b=ai(e,d.x,d.y);if(!b)return null;let C=Z(b),k=F(C.col,C.row);return Math.hypot(d.x-k.x,d.y-k.y)<=f.cell*.55?b:null}function _t(){let{components:d,cellToComponent:y}=li(e);for(let b of e.chicks){if(b.stage==="flying")continue;let C=Cn(b);if(!C)continue;let k=y.get(C),P=d.get(k);P&&(P.count+=1)}for(let b of d.values())b.ratio=b.count/b.capacity;e.congestion=d,e.componentLookup=y}function on(){for(let d of e.congestion.values()){let y=Oo(e),b=xi(e);if(d.ratio>b&&d.ratio=y){let C=rn(d.id);if(!C.length||C.some($=>$.stage!=="queued"&&$.stoppedTimer<=.2))continue;let k=e.lastExplodedComponent.get(d.id)||0,P=performance.now();P-k>900&&(e.lastExplodedComponent.set(d.id,P),ao(d))}}}function rn(d){return e.chicks.filter(y=>{let b=Cn(y);return b&&e.componentLookup?.get(b)===d})}function ao(d){let y=rn(d.id);if(!y.length)return;for(let k of y)Ko(e,k.sex,k.x,k.y);e.chicks=e.chicks.filter(k=>!y.some(P=>P.id===k.id));for(let k of e.scanners)k.queue=k.queue.filter(P=>e.chicks.some($=>$.id===P));for(let k of d.cells){let P=Z(k),$=F(P.col,P.row);Xe(e,$.x,$.y,p.danger),Ze(e,$.x,$.y,6),Nn(e,$.x,$.y,4)}Ft(e,18,.75);let b=Z(d.cells[0]),C=F(b.col,b.row);e.stats.explosions=(e.stats.explosions||0)+1,e.totals.explosions=(e.totals.explosions||0)+1,H(e,C.x,C.y-22,`${Math.round(Oo(e)*100)}% JAM EXPLOSION`,p.danger)}return{activeQueuedChick:Ie,currentSpawnDelay:o,sortSlot:qe,updateCongestion:_t,sortScanner:Ye,updateRunning:v}}var fe=document.getElementById("gameCanvas"),vc=fe.getContext("2d"),L={shell:document.getElementById("gameShell"),money:document.getElementById("money"),turn:document.getElementById("turn"),timeLeft:document.getElementById("timeLeft"),phase:document.getElementById("phaseLabel"),comboCount:document.getElementById("comboCount"),eventBrief:document.getElementById("eventBrief"),targetBrief:document.getElementById("targetBrief"),speedBrief:document.getElementById("speedBrief"),turnProfit:document.getElementById("turnProfit"),mixerCount:document.getElementById("mixerCount"),truckFemaleCount:document.getElementById("truckFemaleCount"),truckMaleCount:document.getElementById("truckMaleCount"),poopCount:document.getElementById("poopCount"),buildStatus:document.getElementById("buildStatus"),turnSummary:document.getElementById("turnSummary"),eventPanel:document.getElementById("eventPanel"),modal:document.getElementById("modal"),modalTitle:document.getElementById("modalTitle"),modalBody:document.getElementById("modalBody"),modalActions:document.getElementById("modalActions"),hoverTooltip:document.getElementById("hoverTooltip"),manualScannerMonitor:document.getElementById("manualScannerMonitor"),debug:{panel:document.getElementById("debugPanel"),infiniteCash:document.getElementById("debugInfiniteCash"),dayInput:document.getElementById("debugDayInput"),setDay:document.getElementById("debugSetDayButton"),zeroTimer:document.getElementById("debugZeroTimerButton"),cardSelect:document.getElementById("debugCardSelect"),targetSelect:document.getElementById("debugTargetSelect"),grantCard:document.getElementById("debugGrantCardButton"),grantAllCards:document.getElementById("debugGrantAllCardsButton"),readout:document.getElementById("debugReadout")},buttons:{s1Left:document.getElementById("scanner1MixerButton"),s1Right:document.getElementById("scanner1TruckButton"),s2Left:document.getElementById("scanner2MixerButton"),s2Right:document.getElementById("scanner2TruckButton"),nextTurn:document.getElementById("nextTurnButton"),conveyor:document.getElementById("buildConveyorButton"),boostConveyor:document.getElementById("buildBoostConveyorButton"),eggFarm:document.getElementById("buildEggFarmButton"),autoScanner:document.getElementById("buildAutoScannerButton"),manualScanner:document.getElementById("buildManualScannerButton"),mixer:document.getElementById("buildMixerButton"),trash:document.getElementById("buildTrashButton"),truck:document.getElementById("buildTruckButton"),maintenanceRoom:document.getElementById("buildMaintenanceRoomButton"),erase:document.getElementById("eraseButton"),undo:document.getElementById("undoButton"),redo:document.getElementById("redoButton")}};function wc(){let e={conveyor:"conveyor",boostConveyor:"boostConveyor",eggFarm:"eggFarm",autoScanner:"autoScanner",manualScanner:"manualScanner",mixer:"mixer",trash:"trash",truck:"truck",maintenanceRoom:"maintenanceRoom"};for(let[t,n]of Object.entries(e))L.buttons[t]&&(L.buttons[t].innerHTML=Br(n))}function Sc(e){let t=new Set(e.tags||[]);return["upgradeEgg","crowdedFarming","hatchingFeed","extraEggOutlet"].includes(e.id)||t.has("EGG")?"Production / EGG":["upgradeTrash","poopRateBooster","composter","chemicalWeaponSubsidy"].includes(e.id)||t.has("POOP")?"Poop / Shredder":["upgradeAutoScanner","autoScannerTuning","scannerQueueSpacing"].includes(e.id)||t.has("SCANNER")?"Scanner":["bearing","dynamite"].includes(e.id)||t.has("CONVEYOR")?"Conveyor / Map":["safetyCover","preventiveMaintenance","durabilityCoating","sparePartsBin","laborExploitation"].includes(e.id)||t.has("MAINTENANCE")?"Maintenance / Risk":["dudFilter","dudRefund","freeReroll","extraCards"].includes(e.id)||t.has("CARD")?"Card Engine":t.has("ULTRA RARE")?"Ultra Rare":t.has("ECONOMY")||["upgradeMixer","upgradeTruck","recyclingSubsidy","usedMachine","newMachine","flattery","legalWork","rescueLoan"].includes(e.id)?"Economy / Shipment":"Other"}function kc(){if(!L.debug?.panel||!L.debug.cardSelect)return;let e=["Production / EGG","Poop / Shredder","Scanner","Conveyor / Map","Maintenance / Risk","Card Engine","Economy / Shipment","Ultra Rare","Other"],t=new Map(e.map(n=>[n,[]]));for(let n of Qt){let o=Sc(n);t.has(o)||t.set(o,[]),t.get(o).push(n)}L.debug.cardSelect.innerHTML="";for(let n of e){let o=t.get(n)||[];if(!o.length)continue;let r=document.createElement("optgroup");r.label=n;for(let i of o){let l=document.createElement("option");l.value=i.id;let c=i.rarity==="ultraRare"?"UR":i.rarity==="rare"?"R":"C";l.textContent=`[${c}] ${i.title}`,r.appendChild(l)}L.debug.cardSelect.appendChild(r)}L.debug.cardSelect.addEventListener("change",Ot),Ot()}function Ot(){if(!L.debug?.targetSelect)return;let e=L.debug.cardSelect?.value,t=Jt(e),n=t?ps(u,t):[];if(L.debug.targetSelect.innerHTML="",!n.length){let r=document.createElement("option");r.value="__none__",r.textContent=t?"No target required":"No card selected",L.debug.targetSelect.appendChild(r),L.debug.targetSelect.disabled=!0;return}let o=document.createElement("option");o.value="__auto__",o.textContent=t?.id==="dynamite"?"Auto: first 3 blocked cells":"Auto: first valid target",L.debug.targetSelect.appendChild(o);for(let r of n){let i=document.createElement("option");i.value=r.key,i.textContent=r.label,L.debug.targetSelect.appendChild(i)}L.debug.targetSelect.disabled=!1}function Cc(){let e=Math.max(1,Math.floor(Number(L.debug.dayInput?.value)||1));u.turn=e,L.debug.dayInput&&(L.debug.dayInput.value=String(e)),H(u,fe.width/2-u.view.x,86-u.view.y,`DAY ${e}`,p.green),z.updatePanels(),z.updateUI(),Ot(),Nt(`Day set to ${e}.`)}function xc(){u.timeLeft=0,u.phase==="running"&&qs(),H(u,fe.width/2-u.view.x,86-u.view.y,"TIMER 0",p.warn),z.updatePanels(),z.updateUI(),Nt("Timer set to 0.")}function Mc(){let e=L.debug.cardSelect?.value,t=L.debug.targetSelect?.disabled?void 0:L.debug.targetSelect?.value,n=or(u,e,{targetKey:t});L.debug.grantCard&&(L.debug.grantCard.textContent=n.ok?"Granted":"Failed",window.setTimeout(()=>{L.debug.grantCard&&(L.debug.grantCard.textContent="Grant Selected")},900)),Me?.updateCongestion?.(),z.updatePanels(),z.updateUI(),Ot(),Nt(n.reason)}function gc(){let t=Qt.map(n=>or(u,n,{targetKey:"__auto__"})).filter(n=>n.ok).length;Me?.updateCongestion?.(),z.updatePanels(),z.updateUI(),Ot(),Nt(`Granted ${t}/${Qt.length} cards.`)}function Tc(){L.debug?.infiniteCash?.checked&&u.cash<999999&&(u.cash=999999,u.totals.maxCash=Math.max(u.totals.maxCash,u.cash))}function Nt(e=""){L.debug?.readout&&(L.debug.readout.textContent=[e,`D${u.turn}`,g(u.cash),`Combo ${u.manualCombo?.count||0}`,`Event ${u.eventActive?.title||u.eventOffer?.title||"none"}`,`Rescue ${u.cardEffects?.rescueLoanCharges||0}`,`Chem ${u.cardEffects?.chemicalWeaponSubsidy||0}`].filter(Boolean).join(" | "))}var u=Mo(),V,z,Me,tn;function Ec(e=null){let t=Vn(u,e);return e?t*Vo(u,e):t}function Rc(){Object.assign(u,Mo()),u.phase="running",u.view={x:0,y:0,scale:1},go(u),Vs(),Se(u),z.hideModal(),Me.updateCongestion(),z.updatePanels(),z.updateUI(),Nt()}function Pc(){if(u.phase!=="build")return;if(u.cardDraft?.pending||u.cardTargetPick?.pending){V.fail(u.cardTargetPick?.pending?"Choose upgrade target first.":"Choose an upgrade card first."),z.updatePanels();return}let e=fn(u);if(e.length){V.fail(`Cannot start: ${e[0]}`),z.updatePanels();return}Se(u),si(u),es(u);let t=Math.max(0,Math.floor(u.lastResult?.profit??u.stats?.profit??0)),n=Bi(u,Math.max(1,u.turn||1),t);u.lastStartFees={fairiesTribute:n.amount||0,tribute:n},n.amount>0&&H(u,fe.width/2-u.view.x,116-u.view.y,`FAIRIES -${g(n.amount)}`,p.danger),mi(u),u.phase="running",u.turn+=1,u.timeLeft=vi(u),u.shutdownTimeLeft=0,u.cleanupTimer=null,u.cleanupBlown=!1,u.chicks=[],u.effects=[],u.floatingTexts=[],u.shake={time:0,strength:0},u.truckCargo=[],Vs(),u.stats=xo(),u.stats.fairiesTribute=u.lastStartFees?.fairiesTribute||0,u.stats.fairiesTribute>0&&(u.stats.penalty+=u.stats.fairiesTribute,u.stats.profit-=u.stats.fairiesTribute);for(let o of u.scanners)o.queue=[],o.cooldown=0;for(let o of u.eggFarms)o.nextSpawn=Me.currentSpawnDelay(o),o.lastInterval=o.nextSpawn,o.shutterProgress=0,o.shutterSparked=!1;u.buildTool=null,u.selected=null,u.groupDrag=null,u.selectionBox=null,u.pan=null,Me.updateCongestion(),z.updatePanels(),z.updateUI()}function Ac(){if(u.phase!=="running")return;let e=Fi(u),t=u.eventActive?{...u.eventActive}:null,n=gi(u),o=Li(u);if(e.adjusted>0){let i=u.facilities.truck,l=i?i.x+i.w/2:fe.width/2-u.view.x,c=i?i.y+26:96-u.view.y;H(u,l,c,`${e.target==="poop"?"POOP SHIP":"SHIP"} +${g(e.adjusted)}`,p.green)}n?.bonus>0&&H(u,fe.width/2-u.view.x,96-u.view.y,`EVENT +${g(n.bonus)}`,p.green),o.amount>0&&H(u,fe.width/2-u.view.x,116-u.view.y,`CHEM SUBSIDY +${g(o.amount)}`,p.green),bi(u),u.totals.turnsCompleted+=1;let r=Mi(t);if(r!==1&&(u.pendingFairiesTributeMultiplier=r),u.lastResult={...u.stats,ship:e,event:n,chemical:o,rescue:{amount:0,used:0,remaining:u.cardEffects?.rescueLoanCharges||0},fairiesTribute:{amount:u.stats.fairiesTribute||0},tributeMultiplier:r,turn:u.turn,cash:u.cash},u.cash<0){if((u.cardEffects?.rescueLoanCharges||0)>0){u.phase="loanDecision",z.showEmergencyLoanDecision(Hs,eo);return}u.phase="gameover",z.showGameOver();return}Ks()}function Ks(){u.phase="build",u.truckCargo=[],u.chicks=[],u.shutdownTimeLeft=0,u.cleanupTimer=null,u.cleanupBlown=!1,u.buildSession+=1,u.undoStack=[],u.redoStack=[],u.timeLeft=0;for(let e of u.scanners)e.queue=[];for(let e of u.eggFarms)e.shutterProgress=0,e.shutterSparked=!1;ts(u),u.eventOffer=hi(u),tn&&tn.prepareDraft(),u.cardTargetPick=null,u.buildTool=null,u.groupDrag=null,u.selectionBox=null,u.pan=null,z.updatePanels(),z.showTurnResult(u.lastResult)}function Hs(){if((u.cardEffects?.rescueLoanCharges||0)<=0)return eo();u.cardEffects.rescueLoanCharges-=1,u.stats.rescueLoan=(u.stats.rescueLoan||0)+500,u.totals.rescueLoan=(u.totals.rescueLoan||0)+500;let e=Ge(u,500);u.lastResult={...u.lastResult||{},...u.stats,rescue:{amount:(u.lastResult?.rescue?.amount||0)+e,used:(u.lastResult?.rescue?.used||0)+1,remaining:u.cardEffects.rescueLoanCharges},cash:u.cash},H(u,fe.width/2-u.view.x,176-u.view.y,`RESCUE +${g(e)}`,p.green),u.cash>=0?Ks():(u.cardEffects?.rescueLoanCharges||0)>0?(u.phase="loanDecision",z.showEmergencyLoanDecision(Hs,eo)):eo()}function eo(){u.phase="gameover",z.showGameOver()}function qs(){u.shutdownTimeLeft<=0&&(u.shutdownTimeLeft=u.shutdownGraceSeconds||10);for(let e of u.eggFarms){if(e.shutterSparked)continue;e.shutterProgress=.02,e.shutterSparked=!0;let t=F(e.col,e.row);Xe(u,t.x,t.y,p.ink),Ze(u,t.x,t.y+10,10),H(u,t.x,t.y-34,"SHUT +10s",p.ink)}}function Ys(e){u.lastTimestamp||(u.lastTimestamp=e);let t=Math.min((e-u.lastTimestamp)/1e3,.05);u.lastTimestamp=e,u.phase==="running"&&Me.updateRunning(t,{closeFarmShutters:qs,completeTurn:Ac}),Yi(u,t,fe,V.equipmentHitBoxes),Me.updateCongestion(),Ss(vc,fe,u,{activeQueuedChick:Me.activeQueuedChick,selectedObject:V.selectedObject,selectedTitle:V.selectedTitle}),Tc(),z.updateUI(),Xs(),Nt(),requestAnimationFrame(Ys)}function to(){return u.view?.scale||1}function wn(){u.view||(u.view={x:0,y:0,scale:1}),u.view.scale==null&&(u.view.scale=1)}function no(e){let t=fe.getBoundingClientRect();return{x:(e.clientX-t.left)*fe.width/t.width,y:(e.clientY-t.top)*fe.height/t.height}}function wt(e){let t=no(e),n=to();return{x:(t.x-(u.view?.x||0))/n,y:(t.y-(u.view?.y||0))/n}}function Ic(e){let t=to();return{x:e.x*t+(u.view?.x||0),y:e.y*t+(u.view?.y||0)}}function $c(){let e={left:f.x-90,top:f.y-130,right:f.x+f.cols*f.cell+260,bottom:f.y+f.rows*f.cell+220};if(u.phase==="build")for(let t of Tt(u)){let n=Et(t);e.left=Math.min(e.left,n.x-60),e.top=Math.min(e.top,n.y-80),e.right=Math.max(e.right,n.x+n.w+80),e.bottom=Math.max(e.bottom,n.y+n.h+80)}return e}function Gs(e,t){if(e<=t)return[e,t];let n=(e+t)/2;return[n,n]}function St(){wn();let e=to(),t=$c(),[n,o]=Gs(fe.width-160-t.right*e,110-t.left*e),[r,i]=Gs(fe.height-150-t.bottom*e,150-t.top*e);u.view.x=un(u.view.x,n,o),u.view.y=un(u.view.y,r,i)}function Vs(){wn(),u.view.scale=1;let e=u.eggFarms?.[0],t=e?F(e.col,e.row):{x:f.x,y:f.y};u.view.x=280-t.x,u.view.y=190-t.y,St()}function Dc(e){let t=no(e);wn(),u.pan={start:t,viewX:u.view.x,viewY:u.view.y,moved:!1}}function Fc(e){if(!u.pan)return;let t=no(e);Math.hypot(t.x-u.pan.start.x,t.y-u.pan.start.y)>5&&(u.pan.moved=!0),wn(),u.view.x=u.pan.viewX+t.x-u.pan.start.x,u.view.y=u.pan.viewY+t.y-u.pan.start.y,St()}function Bc(e){e.preventDefault(),wn();let t=no(e),n=wt(e),o=Math.exp(-e.deltaY*.0012),r=un(to()*o,.55,1.8);u.view.scale=r,u.view.x=t.x-n.x*r,u.view.y=t.y-n.y*r,St(),it()}function Lc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:{type:e.type,id:e.ref.id}:null}function Oc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:e.ref||null:null}function it(){L.hoverTooltip&&(L.hoverTooltip.classList.remove("visible"),L.hoverTooltip.setAttribute("aria-hidden","true"),u.hover=null)}function Nc(e,t){if(!L.hoverTooltip||u.phase!=="build"||u.cardTargetPick?.pending||u.groupDrag||u.selectionBox||u.pan)return it();let n=Oc(t);if(!n)return it();let o=V.selectedTitle(n),r=V.flavorText?V.flavorText(n):"",i=V.disconnectedWarningFor?V.disconnectedWarningFor(n):"",l=V.selectedInfoLines(n).slice(0,7);L.hoverTooltip.innerHTML=`${o}${i?`${i}`:r?`${r}`:""}${l.map(x=>`${x}`).join("")}`;let c=Math.min(window.innerWidth-330,e.clientX+18),v=Math.min(window.innerHeight-220,e.clientY+18);L.hoverTooltip.style.left=`${Math.max(8,c)}px`,L.hoverTooltip.style.top=`${Math.max(8,v)}px`,L.hoverTooltip.classList.add("visible"),L.hoverTooltip.setAttribute("aria-hidden","false"),u.hover={type:t.type,id:t.oldKey||t.ref?.id||null}}function _c(e){if(u.phase!=="build")return it();Nc(e,V.equipmentAtPoint(wt(e)))}function zs(e){it();let t=wt(e),n=V.equipmentAtPoint(t),o=Lc(n);if(!o){u.selected=null,u.multiSelected=[],z.updatePanels();return}u.selected=o,u.multiSelected=[o],z.updatePanels();let r=V.selectedObject();r?.type==="scanner"&&r.kind==="manual"&&V.showManualScannerMenu(r),r?.type==="scanner"&&r.kind==="auto"&&V.showAutoScannerMenu(r)}function en(){u.buildTool=null,u.selected=null,u.multiSelected=[],u.selectionBox=null,u.cardTargetPick?.mode==="autoScannerMenu"&&(u.cardTargetPick=null),z.hideModal(),it(),z.updatePanels(),z.updateUI()}function Us(e){return String(e).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function Gc(e){let t=e?.queue?.[0];return t==null?null:u.chicks.find(n=>n.id===t)||null}function Uc(e){if(!e)return'WAIT';let t=e.sex==="poop"?"\u{1F4A9} POOP":e.sex==="male"?"\u2642 MALE":"\u2640 FEMALE";return`${t}`}function Wc(e,t){let n=new Set(u.eggFarms.map(E=>I(E.col,E.row))),o=new Map(u.scanners.map(E=>[I(E.col,E.row),E])),r=Re(e,"inputA"),i=r?I(r.col,r.row):null,l=new Set(Object.values(u.facilities||{}).map(E=>E.entry?I(E.entry.col,E.entry.row):null).filter(Boolean)),c=t?.sex||"",v=c==="poop"?"\u{1F4A9}":c==="male"?"\u2642":c==="female"?"\u2640":"",x=[];for(let E=e.row-2;E<=e.row+2;E+=1)for(let R=e.col-2;R<=e.col+2;R+=1){let B=I(R,E),O=["mini-cell"],ee="";R===e.col&&E===e.row?(O.push("scanner"),c&&O.push(c),ee=v||"S"):B===i?(O.push("input"),ee="IN"):n.has(B)?(O.push("egg"),ee="E"):o.has(B)?(O.push("scanner-other"),ee="S"):l.has(B)?(O.push("port"),ee="P"):u.conveyorTiles.has(B)?(O.push("belt"),ee="\u2022"):u.blockedCells?.has?.(B)&&(O.push("blocked"),ee="\xD7"),x.push(`${ee}`)}return`
${x.join("")}
`}function Kc(e){let t=Ic(F(e.col,e.row)),n=76;return t.x<-n||t.y<-n||t.x>fe.width+n||t.y>fe.height+n}function Xs(){if(!L.manualScannerMonitor)return;if(u.phase!=="running"){L.manualScannerMonitor.classList.remove("visible"),L.manualScannerMonitor.innerHTML="";return}let e=u.scanners.filter(t=>t.kind==="manual"&&Kc(t));if(!e.length){L.manualScannerMonitor.classList.remove("visible"),L.manualScannerMonitor.innerHTML="";return}L.manualScannerMonitor.innerHTML=e.map(t=>{let n=Gc(t),o=t.keys?.left?.label||(t.slot===0?"A":"Left"),r=t.keys?.right?.label||(t.slot===0?"D":"Right"),i=t.role===0?"MIXER":"WASTE",l=t.role===0?"S2":"TRUCK",c=n?"":" disabled";return` +
+
S${(t.slot??0)+1}OFFSCREEN / Q:${t.queue.length}
+
+ IN${Uc(n)}SCANNER +
+ ${Wc(t,n)} +
+ + +
+
`}).join(""),L.manualScannerMonitor.classList.add("visible")}L.manualScannerMonitor?.addEventListener("click",e=>{let t=e.target.closest("button[data-scanner-id]");if(!t||t.disabled)return;let n=u.scanners.find(o=>o.id===Number(t.dataset.scannerId));n&&(Me.sortScanner(n,t.dataset.side),Xs())});fe.addEventListener("contextmenu",e=>e.preventDefault());fe.addEventListener("wheel",Bc,{passive:!1});fe.addEventListener("pointerdown",e=>{if(u.phase!=="build")return;fe.setPointerCapture(e.pointerId);let t=wt(e);if(e.button===2){Dc(e);return}if(e.button!==0)return;if(u.cardTargetPick?.mode==="autoScannerMenu"){en();return}if(u.cardTargetPick?.pending){tn.chooseTargetAtPoint(t);return}let n=V.expansionOfferAtPoint?.(t);if(n){V.buyGridExpansion(n),St(),z.updatePanels(),z.updateUI();return}if(V.cycleBranchModeAtPoint?.(t)){z.updatePanels(),z.updateUI();return}let o=Ke(t.x,t.y),r=V.equipmentAtPoint(t);if(!u.buildTool&&r?.type==="conveyor"&&o&&V.cycleSingleConveyorDirection?.(o)){z.updatePanels(),z.updateUI();return}if(u.buildTool==="erase"){if(!V.equipmentAtPoint(t)){en();return}V.eraseAtPoint(t);return}if(u.buildTool){let i=Ke(t.x,t.y);if(!i&&!["mixer","trash","truck"].includes(u.buildTool)){en();return}if(u.buildTool==="conveyor"||u.buildTool==="boostConveyor"){V.beginConveyorDrag(i);return}if(V.equipmentAtPoint(t)){u.buildTool=null,zs(e);return}V.buildAtPoint(t);return}V.startGroupDrag(e)||V.startSelectionBox(e)});fe.addEventListener("pointermove",e=>{if(u.phase!=="build"){it();return}_c(e),u.pan&&e.buttons&2&&Fc(e),u.groupDrag&&e.buttons&1&&V.updateGroupDrag(e),u.selectionBox&&e.buttons&1&&V.updateSelectionBox(e),(u.buildTool==="conveyor"||u.buildTool==="boostConveyor")&&e.buttons&1&&V.continueConveyorDrag(Ke(wt(e).x,wt(e).y)),u.buildTool==="erase"&&e.buttons&1&&V.eraseAtPoint(wt(e))});fe.addEventListener("pointerup",e=>{u.selectionBox?V.finishSelectionBox():u.groupDrag&&(u.groupDrag.committed||zs(e),V.finishGroupDrag()),e.button===2&&u.pan&&!u.pan.moved&&u.buildTool&&en(),(u.buildTool==="conveyor"||u.buildTool==="boostConveyor")&&V.endConveyorDrag?.(),u.groupDrag=null,u.pan=null;try{fe.releasePointerCapture(e.pointerId)}catch{}});fe.addEventListener("pointerleave",it);fe.addEventListener("pointercancel",()=>{V?.endConveyorDrag?.(),u.groupDrag=null,u.selectionBox=null,u.pan=null,it()});document.addEventListener("pointerdown",e=>{!L.modal.classList.contains("visible")||!L.modal.classList.contains("equipment-popover")||e.target.closest("#modal .modal-card")||en()},!0);L.buttons.s1Left.addEventListener("click",()=>Me.sortSlot(0,"left"));L.buttons.s1Right.addEventListener("click",()=>Me.sortSlot(0,"right"));L.buttons.s2Left.addEventListener("click",()=>Me.sortSlot(1,"left"));L.buttons.s2Right.addEventListener("click",()=>Me.sortSlot(1,"right"));L.buttons.nextTurn.addEventListener("click",Pc);L.buttons.conveyor.addEventListener("click",()=>V.setBuildTool("conveyor"));L.buttons.boostConveyor.addEventListener("click",()=>V.setBuildTool("boostConveyor"));L.buttons.eggFarm.addEventListener("click",()=>V.setBuildTool("eggFarm"));L.buttons.autoScanner.addEventListener("click",()=>V.setBuildTool("autoScanner"));L.buttons.manualScanner.addEventListener("click",()=>V.setBuildTool("manualScanner"));L.buttons.mixer.addEventListener("click",()=>V.setBuildTool("mixer"));L.buttons.trash.addEventListener("click",()=>V.setBuildTool("trash"));L.buttons.truck.addEventListener("click",()=>V.setBuildTool("truck"));L.buttons.maintenanceRoom.addEventListener("click",()=>V.setBuildTool("maintenanceRoom"));L.buttons.erase.addEventListener("click",()=>V.setBuildTool("erase"));L.debug.setDay?.addEventListener("click",Cc);L.debug.zeroTimer?.addEventListener("click",xc);L.debug.grantCard?.addEventListener("click",Mc);L.debug.grantAllCards?.addEventListener("click",gc);L.buttons.undo.addEventListener("click",()=>{Uo(u)&&(St(),z.updatePanels(),z.updateUI(),Ot())});L.buttons.redo.addEventListener("click",()=>{Wo(u)&&(St(),z.updatePanels(),z.updateUI(),Ot())});function Ws(e,t,n){let o=e.keys?.[t];return o?o.code&&n.code===o.code||o.key&&n.key.toLowerCase()===o.key:!1}window.addEventListener("keydown",e=>{if(e.repeat)return;let t=e.key.toLowerCase();if(u.phase==="running")for(let n of u.scanners.filter(o=>o.kind==="manual")){if(Ws(n,"left",e)){e.preventDefault(),Me.sortScanner(n,"left");return}if(Ws(n,"right",e)){e.preventDefault(),Me.sortScanner(n,"right");return}}u.phase==="build"&&(e.ctrlKey||e.metaKey)&&t==="z"&&(e.preventDefault(),Uo(u)&&(St(),z.updatePanels(),z.updateUI())),u.phase==="build"&&(e.ctrlKey||e.metaKey)&&(t==="y"||e.shiftKey&&t==="z")&&(e.preventDefault(),Wo(u)&&(St(),z.updatePanels(),z.updateUI())),e.key==="Escape"&&u.cardTargetPick?.pending&&(e.preventDefault(),u.cardTargetPick.mode==="autoScannerMenu"?en():tn.cancelTargetPick())});V=$s({game:u,ui:L,canvas:fe,canvasPoint:wt,onUpdatePanels:()=>z?.updatePanels()});Me=_s({game:u,currentConveyorSpeed:Ec,onGameOverCheck:()=>z?.checkGameOver()});tn=ms({game:u,ui:L,onUpdatePanels:()=>z?.updatePanels()});z=Ds({game:u,ui:L,build:V,startGame:Rc,beginCardDraft:()=>tn.showDraft(),activeQueuedChick:Me.activeQueuedChick});wc();kc();go(u);Se(u);Me.updateCongestion();z.updatePanels();z.updateUI();z.showTitle();Nt();requestAnimationFrame(Ys); diff --git a/dist/game-v27.18.js b/dist/game-v27.18.js new file mode 100644 index 0000000..b796070 --- /dev/null +++ b/dist/game-v27.18.js @@ -0,0 +1,59 @@ +var Y={version:"v27.18 UI + ROUTING PATCH",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,fairiesTribute:{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},incomeUpgradeRate:1.1,explosionDamageDivisor:30,maleTruckFinePerHalfDay:30,shredderBonus:{maxCards:30,incomePerUpgrade:1.25},chemicalWeaponSubsidy:{poopPerBlock:70,yenPerBlock:1200}},production:{poopRate:.08,autoScannerCooldown:3.5,autoScannerUpgradeRate:.95,autoScannerCardUpgradeRate:.95,autoScannerMinCooldown:.5,poopRateCardBonus:.04,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:"autoScannerTuning",title:"AUTO SCANNER Tuning",rarity:"common",type:"instant",description:"All AUTO SCANNER cooldowns use default cooldown x0.95 per copy.",tags:["SCANNER","PASSIVE"]},{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",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:"poopRateBooster",title:"Poop Culture",rarity:"common",type:"instant",description:"Base poop rate +4 percentage points. No card limit.",tags:["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:"sparePartsBin",title:"SPARE PARTS BIN",rarity:"common",type:"instant",description:"Restores 2% durability to every machine. A box of almost-compatible parts.",tags:["MAINTENANCE","ACTIVE"]},{id:"dudRefund",title:"DUD REFUND",rarity:"common",type:"instant",description:"DUDs now come with paperwork. Gain JPY 50 per copy when you pick a DUD.",tags:["CARD","ECONOMY","PASSIVE"]},{id:"freeReroll",title:"FREE REROLL",rarity:"common",type:"instant",description:"The first bad ideas are free.",tags:["CARD","PASSIVE"]},{id:"composter",title:"COMPOSTER",rarity:"common",type:"instant",description:"Turns shredder waste into suspicious fertilizer. Gain JPY 3 per copy when SHREDDER processes poop.",tags:["POOP","ECONOMY","PASSIVE"]},{id:"scannerQueueSpacing",title:"Scanner Queue Spacing",rarity:"common",type:"instant",description:"Manual and Auto Scanner queue spacing -15%. No card limit.",tags:["SCANNER","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 unbuildable cells",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:"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:"Fairies tribute profit exemption +JPY 250.",tags:["ECONOMY","RARE","PASSIVE"]},{id:"chemicalWeaponSubsidy",title:"Chemical Weapons Subsidy",rarity:"ultraRare",type:"instant",description:"Each day, gain JPY 1200 per 70 poop shipped by truck. No card limit.",tags:["POOP","ULTRA RARE","PASSIVE"]},{id:"laborExploitation",title:"Motivational Exploitation",rarity:"ultraRare",type:"instant",description:"Repair room work time -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,autoScannerTuning:0,poopRateBooster:0,crowdedFarming:0,hatchingFeed:0,safetyCover:0,recyclingSubsidy:0,chemicalWeaponSubsidy:0,preventiveMaintenance:0,dudFilter:0,durabilityCoating:0,sparePartsBin:0,dudRefund:0,freeReroll:0,composter:0,scannerQueueSpacing:0,laborExploitation:0,usedMachineActive:!1,rescueLoanCharges:0},commonWeight:8,rareWeight:2,ultraRareWeight:.45,baseDraftSize:3,maxDudsPerDraft:2,dudChancePerCard:.3,dudChanceReductionPerFilter:.05,extraCardsAddedPicks:2,rerollCost:{dayDivisor:2,multiplier:100}},events:{eventChance:.1,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:{secondsPerOnePercent:.5,walkSpeed:90}},facilities:{conveyor:{id:"conveyor",type:"conveyor",name:"Conveyor",shortName:"Belt",price:30,buildable:!0,upgradeable:!1},boostConveyor:{id:"boostConveyor",type:"conveyor",name:"Boost Conveyor",shortName:"BOOST BELT",price:75,buildable:!0,upgradeable:!1,speedMultiplier:2},eggFarm:{id:"eggFarm",type:"eggFarm",name:"Egg Farm",shortName:"EGG",price:250,buildable:!0,upgradeable:!0,maxLevel:4},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:180,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}},maintenanceRoom:{id:"maintenanceRoom",type:"maintenanceRoom",name:"Maintenance Room",shortName:"REPAIR ROOM",price:220,buildable:!0,upgradeable:!1,footprint:{cols:2,rows:2}}}};var Pr=Y.version,gt=Y.time.daySeconds,an=Y.cash.starting,Ce=Y.economy,Ar=Y.time.farmShutdownGraceSeconds,xn=Y.production.autoScannerCooldown,Dr=Y.production.autoScannerUpgradeRate,ho=Y.production.autoScannerCardUpgradeRate||Y.production.autoScannerUpgradeRate,mo=Y.production.autoScannerMinCooldown,Ir=Y.events.eventChance,xt=Y.events.firstTurn,bo=Y.production.poopRate,vo=Y.production.poopRateCardBonus||0,Tn=Y.conveyor.baseSpeed,Wt=Y.conveyor.maxSpeed,En=Y.conveyor.bearingSpeedMultiplier,Ie=Y.cards,$r=Y.cards.definitions,wo=Y.cards.defaultEffects,lt=Y.production.eggSpawnRanges,f=Y.grid,ve=Y.facilities,So=["conveyor","boostConveyor","eggFarm","autoScanner","manualScanner","mixer","trash","truck","maintenanceRoom"],cn=["mixer","trash","truck"],Fr=["mixer","truck"],at=Object.fromEntries(Object.entries(ve).map(([e,t])=>[e,t.price])),de=[{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"}],y={bg:"#111318",ink:"#090a0d",muted:"#8f9bab",green:"#7bd84f",greenSoft:"#273c24",mixerBlue:"#4aa3ff",truckPink:"#ffb33e",wasteGreen:"#88d35a",danger:"#e34a36",warn:"#ffb827",white:"#e6edf2",poop:"#7b4a23",male:"#4aa3ff",female:"#ff6fae"},Me={ambient:0,important:1,critical:2};function x(e){let t=Number(e)||0;return`${t<0?"-":""}\uFFE5${Math.ceil(Math.abs(t)).toLocaleString("ja-JP")}`}function A(e,t){return`${e},${t}`}function te(e){let[t,n]=String(e).split(",").map(Number);return{col:t,row:n}}function un(e,t,n){return Math.max(t,Math.min(n,e))}function W(e,t){return e+Math.random()*(t-e)}function Ee(e,t){return e>=0&&e=0&&tMath.round(un(r,0,255)).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`}function Kt(e,t,n){let o=Br(e),r=Br(t);return cl(ko(o.r,r.r,n),ko(o.g,r.g,n),ko(o.b,r.b,n))}var oe={appTitle:"Chick Sorter",versionTitle:`Chick Sorter ${Pr}`,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 ut(e){return ve[e]?.name||String(e||"").replace(/^[a-z]/,t=>t.toUpperCase())}function ul(e){let t=ve[e];return t?e==="conveyor"||e==="boostConveyor"?`${x(t.price)} / tile`:e==="autoScanner"?`${x(t.price)} / ${xn.toFixed(1)}s cooldown`:e==="trash"?x(t.price):x(t.price):""}function dl(e){return{conveyor:"A narrow green belt. Routes decide whether chicks live, ship, or become invoices.",boostConveyor:"Moves chicks twice as fast. Wears down like a normal belt.",eggFarm:"A tiny gatehouse producing questionable eggs on schedule.",autoScanner:"Slower than hands without upgrades.",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.",maintenanceRoom:"2\xD72 repair bay. Each room dispatches one repairman during the day."}[e]||""}function Or(e){let t=dl(e);return`${ut(e)}${ul(e)}${t?`${t}`:""}`}function Nr(e){return oe.routeLabels[e]||String(e).toUpperCase()}function _r(e){let t=2166136261;for(let n=0;n>>0}function Gr(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 Pn(){return`RUN-${Date.now().toString(36)}-${Math.floor(Math.random()*1e6).toString(36)}`.toUpperCase()}function Ur({seed:e,targetRatio:t=.2,reserved:n=[]}={}){let o=Gr(_r(e||Pn())),r=new Set(n.map(c=>typeof c=="string"?c:A(c.col,c.row))),i=[];for(let c=0;c0;c-=1){let b=Math.floor(o()*(c+1));[i[c],i[b]]=[i[b],i[c]]}let l=Math.round(f.cols*f.rows*t);return new Set(i.slice(0,Math.min(l,i.length)).map(c=>c.k))}function Wr({seed:e,colStart:t=0,colEnd:n=f.cols,rowStart:o=0,rowEnd:r=f.rows,targetRatio:i=.2,reserved:l=[]}={}){let c=Gr(_r(e||Pn())),b=new Set(l.map(X=>typeof X=="string"?X:A(X.col,X.row))),C=[],T=Math.max(0,Math.floor(t)),I=Math.max(T,Math.floor(n)),$=Math.max(0,Math.floor(o)),O=Math.max($,Math.floor(r));for(let X=$;X0;X-=1){let ae=Math.floor(c()*(X+1));[C[X],C[ae]]=[C[ae],C[X]]}let ee=Math.round((I-T)*(O-$)*i);return new Set(C.slice(0,Math.min(ee,C.length)).map(X=>X.k))}var Ht=10,Kr=2,Hr=1;function qt(e,t){return`${e},${t}`}function fl(e){let[t,n]=String(e).split(",").map(Number);return{chunkX:t,chunkY:n}}function An(e){let t=Y.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 qr(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 C=qt(b.chunkX,b.chunkY);t.has(C)||n.has(C)||n.set(C,Co(e,b.chunkX,b.chunkY,b.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 zr(e,t="right"){let n=Tt(e);return n.find(o=>o.direction===t)||n[0]||null}function Et(e){return{x:f.x+e.colStart*f.cell,y:f.y+e.rowStart*f.cell,w:e.cols*f.cell,h:e.rows*f.cell}}function Mo(e){let t=Et(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 Xr(e,t){let n=Mo(e);return t.x>=n.x&&t.x<=n.x+n.w&&t.y>=n.y&&t.y<=n.y+n.h}function Qr(e){let t=[];for(let n=e.rowStart;nEe(t.col,t.row))}function Sl(e){return[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}].filter(t=>Ee(t.col,t.row))}function kl(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 ni(e){let t=new Set([...e.conveyorTiles]),n=o=>{o&&Ee(o.col,o.row)&&t.add(A(o.col,o.row))};for(let o of e.scanners){for(let r of Sl(o))n(r);for(let r of wl(o))n(r)}for(let o of e.eggFarms){n(o);for(let r of kl(o))n(r)}for(let o of Object.values(e.facilities))n(o.entry);return t}function ei(e){let t=hl.map(([n,o])=>({col:n,row:o}));for(let{col:n,row:o}of t)ti(e,n,o);for(let n=0;n({...n,keys:n.keys?{left:{...n.keys.left},right:{...n.keys.right}}:null,queue:[]})),e.eggFarms=bl.map(n=>{let o=Rt(n);return{...n,nextSpawn:o,lastInterval:o}});let t=ni(e);e.blockedCells=Ur({seed:e.runSeed,targetRatio:Y.map.blockedRatio,reserved:[...t]}),Cl(e),ei(e),e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function Pt(e){return e?[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function ye(e){let t=B(e.col,e.row);return{x:t.x+f.cell/2,y:t.y}}function ft(e,t,n){return e.eggFarms.find(o=>o.col===t&&o.row===n)||null}function pt(e,t,n){return e.scanners.find(o=>Pt(o).some(r=>r.col===t&&r.row===n))||null}function At(e,t){return e.scanners.find(n=>n.id===t)||null}function Ro(e,t){return e.scanners.find(n=>n.kind==="manual"&&n.slot===t)||null}function Fn(e){return e?.baseId||e?.id||""}function Po(e,t){return Object.entries(e.facilities||{}).filter(([,n])=>Fn(n)===t)}function Re(e,t){return{inputA:{col:e.col,row:e.row-2},inputB:null,left:{col:e.col-1,row:e.row},right:{col:e.col+2,row:e.row}}[t]}function ii(e){return e?de.map(t=>({col:e.col+t.dc,row:e.row+t.dr})).filter(t=>Ee(t.col,t.row)):[]}function si(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(A(l.col,l.row))||n.some(c=>c&&Rn(l,c))||r.some(c=>Rn(c,l))||r.push({...l,viaTolerance:!Rn(l,t)})};i(t);for(let l of o)i(l);for(let l of ii(t))i(l);return r}function oi(e,t,n=[],o=[]){let r=si(e,t,n,o),i=r.filter(l=>!l.viaTolerance);return i.length?i:r}function Ml(e,t){let n=Re(t,"inputA");return!n||!Ee(n.col,n.row)?[]:e.conveyorTiles.has(A(n.col,n.row))?[{...n,viaTolerance:!1}]:[]}function gl(e,t,n){let o=Re(t,n);return si(e,o,Pt(t))}function xl(e,t){let n=e.facilities[t]||Po(e,t)[0]?.[1];if(!n)return null;if(n.entry)return B(n.entry.col,n.entry.row);let o=Fn(n)||t;return o==="mixer"?{x:n.x+n.w,y:n.y+n.h*.52}:o==="truck"?{x:n.x,y:n.y+n.h*.52}:o==="trash"?{x:n.x+n.w/2,y:n.y+8}:{x:n.x+n.w/2,y:n.y+n.h/2}}function li(e,t,n){return n==="inputA"?Ml(e,t).length>0:gl(e,t,n).length>0}function me(e){e.branchCounters?.clear?.(),e.routeCache=null,e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function $e(e,t){return A(e,t)}function Yt(e){return te(e)}function Tl(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=>de.some(i=>i.name===r))}function El(e,t,n){let o=de.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.($e(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Rl(e,t){let n=Yt(t),o=e.conveyorMeta?.get?.(t)||{},r=de.filter(T=>e.conveyorTiles.has($e(n.col+T.dc,n.row+T.dr))).map(T=>T.name),i=Tl(e,t).filter(T=>r.includes(T)),l=i.length?i:r;if(r.length<3)return l;let c=new Set(r.filter(T=>El(e,n,T))),b=r.filter(T=>!c.has(T)),C=c.size&&b.length>=2?b:[...new Set(l)];return C.length<2&&(C=r),o.branchMode&&o.branchMode!=="random"&&C.includes(o.branchMode)?[o.branchMode]:C}function Pl(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 Al(e){let t=Pl(e);for(let o of e.conveyorTiles)t.cells.add(o),t.adjacency.set(o,[]);for(let o of t.cells){let r=Yt(o),i=Rl(e,o),l=de.filter(c=>i.includes(c.name));for(let c of l){let b=$e(r.col+c.dc,r.row+c.dr);t.cells.has(b)&&t.adjacency.get(o).push({key:b,dir:c.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),Dl(t),Il(e,t),t.issues=Kl(e,t,{includeRoutes:!1}),t}function Dl(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 c of e.adjacency.get(l)||[])e.cellToComponent.has(c.key)||(e.cellToComponent.set(c.key,o),r.push(c.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 Il(e,t){for(let n of e.scanners){let o={};for(let r of["inputA","left","right"]){let i=Re(n,r),l=r==="inputA"?i&&t.cells.has($e(i.col,i.row))?[{...i}]:[]:oi(e,i,Pt(n)).filter(C=>t.cells.has($e(C.col,C.row))),c=l.map(C=>$e(C.col,C.row)),b=c.length>0;if(o[r]={type:r,cell:i,cells:l,keys:c,key:c[0]||null,connected:b},t.metrics.scannerPorts+=1,b&&(t.metrics.connectedScannerPorts+=1),r==="inputA")for(let C of c)t.scannerInputs.set(C,n.id)}t.scannerPorts.set(n.id,o)}for(let[n,o]of Object.entries(e.facilities)){if(!o.entry)continue;let r=oi(e,o.entry).filter(c=>t.cells.has($e(c.col,c.row))),i=r.map(c=>$e(c.col,c.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=ii({col:n.col,row:n.row}).map(r=>$e(r.col,r.row)).filter(r=>t.cells.has(r));t.farmOutputs.set(n.id,o),t.metrics.farmOutputs+=o.length}}function _e(e){let t=e.routingVersion||0;return(!e.factoryGraph||e.factoryGraph.version!==t)&&(e.factoryGraph=Al(e)),e.factoryGraph}function ai(e){let t=_e(e);return e.factoryGraphCommittedVersion=t.version,e.factoryGraphSnapshot=$l(t),t}function $l(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 Fl(e,t){let n=t.col-e.col,o=t.row-e.row;return de.find(r=>r.dc===n&&r.dr===o)?.name||null}function Ao(e,t,n){let o=_e(e),r=$e(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(se=>se.map(ie=>({...ie})));let l=`${r}|none`,c=[{key:r,col:t.col,row:t.row,incoming:"none",depth:0}],b=new Map([[l,0]]),C=new Map,T=[],I=1/0,$=8,O=24,ee=80;for(;c.length;){let se=c.shift();if(se.depth>I)break;let ie=`${se.key}|${se.incoming}`;if(n(se)){if(T.push(ie),I=se.depth,T.length>=O)break;continue}for(let P of o.adjacency.get(se.key)||[]){let G=Yt(P.key),H=Fl(se,G),be=se.depth+1;if(be>I)continue;let F=`${P.key}|${H}`,U=b.get(F);if(U==null)b.set(F,be),C.set(F,[ie]),c.push({key:P.key,col:G.col,row:G.row,incoming:H,depth:be});else if(U===be){let S=C.get(F)||[];S.length<$&&!S.includes(ie)&&S.push(ie),C.set(F,S)}}}let X=[],ae=(se,ie)=>{if(X.length>=ee)return;let[P]=se.split("|"),G=[Yt(P),...ie];if(se===l||P===r){X.push(G);return}for(let H of C.get(se)||[])ae(H,G)};for(let se of T)ae(se,[]);let he=[],re=new Set;for(let se of X){let ie=se.map(P=>$e(P.col,P.row)).join(">");re.has(ie)||(re.add(ie),he.push(se))}return n.cacheKey&&o.pathCache.set(i,he.map(se=>se.map(ie=>({...ie})))),he}function ci(e){let t=_e(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 ui(e,t,n){let o=_e(e),r=null,i=1/0;for(let l of o.cells){let c=te(l),b=B(c.col,c.row),C=Math.hypot(b.x-t,b.y-n);CB(o.col,o.row));return t&&n.push(t),n}function dt(e,t){t&&(!e.length||Lr(e[e.length-1],t)>1)&&e.push(t)}function Bl(e,t,n,o=null){let r=[{x:e.x,y:e.y}];dt(r,B(t.col,t.row));for(let i of Bn(n,o))dt(r,i);return r}function Ll(e,t){let n=Bn(e),o=Re(t,"inputA");return o&&dt(n,B(o.col,o.row)),dt(n,ye(t)),n}function Ol(e,t,n,o){let r=[{x:e.x,y:e.y}];dt(r,B(t.col,t.row));for(let l of Bn(n))dt(r,l);let i=Re(o,"inputA");return i&&dt(r,B(i.col,i.row)),dt(r,ye(o)),r}function Nl(e,t,n=0){let o=B(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 I=C.roleBias??0,$=T.roleBias??0;if(I!==$)return I-$;let O=C.cells?.length??C.route?.length??Number.POSITIVE_INFINITY,ee=T.cells?.length??T.route?.length??Number.POSITIVE_INFINITY;if(O!==ee)return O-ee;let X=C.key||JSON.stringify(C.route||C.cells||C),ae=T.key||JSON.stringify(T.route||T.cells||T);return X.localeCompare(ae)});if(!o||r.length===1)return r[0];let i=r[0].roleBias??0,l=r.filter(C=>(C.roleBias??0)===i),c=Math.min(...l.map(C=>ri(e,C)));l=l.filter(C=>ri(e,C)===c);let b=e.branchCounters.get(t)||0;return e.branchCounters.set(t,b+1),l[Math.floor(Math.random()*l.length)]}function di(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 Do(e){let t=di(e);return{left:t.left.destination,right:t.right.destination}}function Io(e,t){return di(e).left.match===t.sex?"left":"right"}function $o(e){return Nr(e)}function Fo(e){return{mixer:"#2477ff",truck:"#ff6aa8",trash:"#22b94f","scanner-role-1":"#526456",scanner:"#526456",input:"#526456"}[e]||"#102015"}function Dt(e,t,n=!1){let o=_e(e),r=(o.farmOutputs.get(t.id)||[]).map(Yt),i=[];for(let b of r){let C=I=>o.scannerInputs.has($e(I.col,I.row));C.cacheKey=`farmInput:${b.col},${b.row}:v${o.version}`;let T=Ao(e,b,C);for(let I of T){let $=I[I.length-1],O=o.scannerInputs.get($e($.col,$.row)),ee=At(e,O);ee&&i.push({key:`${ee.id}:${$.col},${$.row}:${I.length}`,scanner:ee,cells:I})}}let l=$n(e,`farm:${t.id}`,i,n);if(l)return{scannerId:l.scanner.id,route:Ll(l.cells,l.scanner)};let c=$n(e,`farm:${t.id}:output`,r.map(b=>({key:A(b.col,b.row),cells:[b]})),n);return c?{scannerId:null,route:Bn(c.cells)}:null}function fi(e,t,n,o,r=!1){let i=At(e,o);if(!i)return null;let c=_e(e).scannerPorts.get(i.id)?.[t],b=Re(i,t),C=c?.connected?(c.keys||[c.key]).filter(Boolean).map(Yt):[];if(!b||!C.length)return null;let T=Do(i)[t];return T==="scanner-role-1"?_l(e,i,t,n,b,C,r):Gl(e,i,t,n,b,C,T,r)}function _l(e,t,n,o,r,i,l){let c=_e(e),b=e.scanners.filter(I=>I.id!==t.id&&c.scannerPorts.get(I.id)?.inputA?.connected),C=[];for(let I of i)for(let $ of b){let O=c.scannerPorts.get($.id)?.inputA?.key;if(!O)continue;let ee=(c.scannerPorts.get($.id)?.inputA?.keys||[O]).filter(Boolean),X=re=>ee.includes($e(re.col,re.row));X.cacheKey=`toScanner:${I.col},${I.row}:${$.id}:v${c.version}`;let ae=Ao(e,I,X),he=$.role===1?0:1;for(let re of ae)C.push({key:`${he}:start${A(I.col,I.row)}:s${$.id}:${re.length}:${A(re[re.length-1].col,re[re.length-1].row)}`,target:$,cells:re,roleBias:he})}let T=$n(e,`scanner:${t.id}:${n}:toRole1`,C,l);return T?{destination:"scanner",nextScannerId:T.target.id,route:Ol(o,r,T.cells,T.target)}:null}function Gl(e,t,n,o,r,i,l,c){let b=_e(e),C=[...b.facilityPorts.entries()].filter(([$,O])=>O?.connected&&Fn(e.facilities?.[$])===l);if(!C.length)return null;let T=[];for(let $ of i)for(let[O,ee]of C){let X=(ee.keys||[ee.key]).filter(Boolean);if(!X.length)continue;let ae=re=>X.includes($e(re.col,re.row));ae.cacheKey=`toFacility:${$.col},${$.row}:${O}:v${b.version}`;let he=Ao(e,$,ae);for(let re of he)T.push({key:`start${A($.col,$.row)}:${O}:${re.length}:${A(re[re.length-1].col,re[re.length-1].row)}`,cells:re,facilityId:O})}let I=$n(e,`scanner:${t.id}:${n}:${l}`,T,c);return I?{destination:l,facilityId:I.facilityId,route:Bl(o,r,I.cells,xl(e,I.facilityId))}:null}function pi(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=fi(e,o,ye(t),t.id,!1);if(r){if(["mixer","trash","truck"].includes(r.destination))return!0;if(r.destination==="scanner"){let i=At(e,r.nextScannerId);if(pi(e,i,n))return!0}}}return!1}function Ul(e,t){return!!Dt(e,t,!1)?.scannerId}function Ln(e){if(e.phase!=="build")return[];let t=[];for(let n of e.eggFarms||[])Ul(e,n)||t.push({type:"eggFarm",id:n.id,ref:n,message:"This Egg will not produce chicks"});for(let n of cn)for(let[o,r]of Po(e,n))_e(e).facilityPorts.get(o)?.connected||t.push({type:"facility",id:o,ref:r,message:"This facility cannot receive items"});return t}function Wl(e){let t=_e(e);for(let r of e.eggFarms||[]){let i=Dt(e,r,!1);if(!i?.scannerId)continue;let l=At(e,i.scannerId);if(pi(e,l))return[]}let n=e.eggFarms?.length||0,o=[...t.facilityPorts.entries()].filter(([r,i])=>i?.connected&&["mixer","trash","truck"].includes(Fn(e.facilities?.[r]))).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 In(e){return e.kind==="manual"?`S${(e.slot??0)+1}`:`Auto Scanner #${e.id}`}function Kl(e,t=_e(e),n={}){let o=n.includeRoutes!==!1,r=[],i={mixer:"Mixer",trash:"Shredder",truck:"Truck"};for(let l of cn){let c=Po(e,l);if(!c.length){r.push(`${i[l]||l} is missing`);continue}for(let[b]of c)t.facilityPorts.get(b)?.connected||r.push(`${i[l]||l} receiver has no conveyor`)}for(let l of e.scanners){let c=t.scannerPorts.get(l.id)||{};if(c.inputA?.connected||r.push(`${In(l)} input has no conveyor`),c.left?.connected||r.push(`${In(l)} left output has no conveyor`),c.right?.connected||r.push(`${In(l)} right output has no conveyor`),!!o)for(let b of["left","right"])c[b]?.connected&&!fi(e,b,ye(l),l.id)&&r.push(`${In(l)} ${b} route is incomplete`)}if(o)for(let l of e.eggFarms)Dt(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 fn(e){return Wl(e)}function yi(e){return fn(e).length===0}var hi=[{key:"premiumFemaleShipment",target:"female",truckTarget:"female",title:"Premium Female Shipment",route:"Female -> Truck",note:"Today only: ship female chicks to Truck. Meet the export target for a bonus.",objective:"truckTarget"},{key:"contaminantSampleExport",target:"poop",truckTarget:"poop",title:"Contaminant Sample Export",route:"Poop value x2",note:"Today only: poop is valid Truck cargo and all poop income is doubled.",objective:"truckTarget",poopValueMultiplier:2},{key:"healthInspection",title:"Health Inspection",route:"Poop -> Shredder",note:"Today only: poop mistakes are fined double. Shred enough poop for an inspection bonus.",objective:"poopTrash",poopFineMultiplier:2},{key:"conveyorJamWarning",title:"Conveyor Jam Warning",route:"No explosions",note:"Today only: jam explosions trigger at 85% congestion. Finish with zero explosions for a bonus.",objective:"noExplosion",congestionExplosionThreshold:.85,congestionWarningThreshold:.68},{key:"powerSavingOrder",title:"Power Saving Order",route:"Slow factory subsidy",note:"Today only: conveyors -20% speed and Auto Scanners +20% cooldown. A subsidy is paid at settlement.",objective:"flatBonus",conveyorSpeedMultiplier:.8,autoScannerCooldownMultiplier:1.2},{key:"overtimeDay",title:"Overtime Day",route:"80 second day",note:"Today only: the work day is longer. No extra reward or penalty.",objective:"none",daySeconds:80},{key:"shortShift",title:"Short Shift",route:"40 second day",note:"Today only: the work day is shorter. The next Fairies tribute is reduced by 10%.",objective:"none",daySeconds:40,fairiesTributeMultiplier:.9},{key:"chickBoom",title:"Chick Boom",route:"EGG interval x0.65",note:"Today only: eggs hatch faster and poop rate rises by 5 percentage points.",objective:"none",productionMultiplier:1/.65,poopRateAdd:.05},{key:"rottenFeed",title:"Rotten Feed",route:"Poop surge",note:"Today only: poop rate rises by 20 percentage points and Shredder poop income is multiplied by 1.5.",objective:"none",poopRateAdd:.2,shredderIncomeMultiplier:1.5},{key:"maintenanceAudit",title:"Maintenance Audit",route:"Durability check",note:"Today only: machines below 50% remaining durability fail the audit. Passing with none below 50% pays a bonus.",objective:"maintenanceAudit"}];function we(e,t=0){let n=Number(e);return Number.isFinite(n)?n:t}function Hl(e,t=0,n=1){let o=Math.max(1,Number(e?.turn||1)+1),r=Math.floor(Bo(e)*(.08+Math.random()*.08)),i=Math.floor(Math.max(0,e.cash||0)*.25),l=Math.floor(Math.max(0,t)*Math.max(1,o)*.75);return Math.max(120,Math.ceil(Math.max(r,i,l)*n))}function mi(e){return Math.max(0,Math.ceil(500+Math.max(1,e?.turn||1)*25))}function Bo(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 ql(e,t=1,n=gt){return e.eggFarms.reduce((o,r)=>{let[i,l]=dn(r),c=Math.max(.1,(i+l)/2);return o+Math.max(1,n)/c*Math.max(.01,t||1)},0)}function Yl(e,t){let n=we(t.productionMultiplier,1),o=we(t.daySeconds,gt),r=ql(e,n,o),i=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),l=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),c=Math.pow(1.03,i),b=bo+vo*l,C=Math.min(.95,Math.max(0,(b+we(t.poopRateAdd,0))*we(t.poopMultiplier,1)*c));return{estimate:r,poopRate:C}}function bi(e){if(e.turn+1Ir)return null;let n=hi[Math.floor(Math.random()*hi.length)],{estimate:o,poopRate:r}=Yl(e,n),i=0;n.objective==="truckTarget"?i=Math.max(1,Math.ceil(o*.3)):n.objective==="poopTrash"&&(i=Math.max(1,Math.ceil(o*r*.8)));let l=0;return["truckTarget","poopTrash","noExplosion"].includes(n.objective)&&(l=Hl(e,o)),n.objective==="flatBonus"&&(l=mi(e)),n.objective==="maintenanceAudit"&&(l=mi(e)),{id:`event-${e.turn}-${Date.now()}-${Math.floor(Math.random()*9999)}`,...n,target:n.target||null,truckTarget:n.truckTarget||null,forced:!0,productionMultiplier:we(n.productionMultiplier,1),poopMultiplier:we(n.poopMultiplier,1),poopRateAdd:we(n.poopRateAdd,0),daySeconds:we(n.daySeconds,gt),targetAmount:i,estimatedOutput:Math.round(o),reward:l,createdTurn:e.turn,oneTurnOnly:!0}}function vi(e){e.eventActive=e.eventOffer?{...e.eventOffer}:null,e.eventOffer=null}function wi(e){e.eventActive=null}function Si(e){return Math.max(1,we(e.eventActive?.daySeconds,gt))}function ki(e){return we(e.eventActive?.productionMultiplier,1)}function Ci(e){let t=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),n=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),o=Math.pow(1.03,t),r=bo+vo*n,i=we(e.eventActive?.poopRateAdd,0);return Math.min(.95,Math.max(0,(r+i)*we(e.eventActive?.poopMultiplier,1)*o))}function je(e){return e.eventActive?.truckTarget||e.eventActive?.target||"female"}function Lo(e,t){return t==="male"?e.truckMale||0:t==="poop"?e.poopTruck||0:e.truckFemale||0}function Mi(e,t){return je(e)===t}function gi(e){return je(e)!=="male"}function Oo(e){return Math.max(.01,we(e.eventActive?.poopValueMultiplier,1))}function On(e){return Math.max(.01,Oo(e)*we(e.eventActive?.shredderIncomeMultiplier,1))}function No(e){return Math.max(.01,we(e.eventActive?.poopFineMultiplier,1))}function _o(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionExplosionThreshold,1)))}function xi(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionWarningThreshold,.8)))}function Ti(e){return Math.max(.01,we(e?.fairiesTributeMultiplier,1))}function Vl(e){let t=0,n=(o,r)=>{let i=Math.max(1,we(r,1)),l=Math.max(0,we(o,0));1-Math.min(1,l/i)<.5&&(t+=1)};for(let o of e.conveyorMeta?.values?.()||[])n(o.uses,o.durability);for(let o of e.eggFarms||[])n(o.maintenance?.uses,o.maintenance?.durability);for(let o of e.scanners||[])o.kind==="auto"&&n(o.maintenance?.uses,o.maintenance?.durability);for(let o of Object.values(e.facilities||{})){let r=o?.baseId||o?.id;(r==="mixer"||r==="trash")&&n(o.maintenance?.uses,o.maintenance?.durability)}return t}function Ei(e){let t=e.eventActive;if(!t)return null;let n=0,o=!0,r=0,i="";t.objective==="truckTarget"?(n=Lo(e.stats,t.target),o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="poopTrash"?(n=e.stats.poopTrash||0,o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="noExplosion"?(n=e.stats.explosions||0,o=n===0,r=o?t.reward:0,i=`${n} explosion(s)`):t.objective==="flatBonus"?(o=!0,r=t.reward):t.objective==="maintenanceAudit"?(n=Vl(e),o=n===0,o&&(r=t.reward),i=`${n} machine(s) below 50%`):o=!0,r>0?(Ge(e,r),e.stats.eventBonus=(e.stats.eventBonus||0)+r,e.totals.eventBonus+=r,e.totals.eventSuccess+=1):t.objective&&t.objective!=="none"&&(e.stats.eventBonus=e.stats.eventBonus||0,e.totals.eventFailed+=o?0:1,o&&(e.totals.eventSuccess+=1));let l={title:t.title,key:t.key,target:t.target,route:t.route,objective:t.objective,targetAmount:t.targetAmount||0,count:n,success:o,bonus:r,reward:t.reward||0,productionMultiplier:t.productionMultiplier,poopMultiplier:t.poopMultiplier,daySeconds:t.daySeconds,detail:i};return e.stats.eventResult=l,l}function Go(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function zl(e){return!!e?.cardEffects?.usedMachineActive}function Xl(e,t){return t?1:Math.min(.8,.5+.1*Math.min(3,Go(e,"recyclingSubsidy")))}function Ql(e){return Math.pow(.95,Go(e,"safetyCover"))}function Nn(e){let t=e?.ref||e||{},n=e?.type||t.type;return n==="conveyor"?t.price||ve[t.kind]?.price||ve.conveyor.price:n==="eggFarm"?t.price||ve.eggFarm.price:n==="scanner"?t.price||(t.kind==="auto"?ve.autoScanner.price:ve.manualScanner.price):n==="facility"?t.price||ve[t.id]?.price||0:n==="maintenanceRoom"?t.price||ve.maintenanceRoom.price:ve[t.id]?.price||0}function Oe(e,t=null){let n=ve[e]?.price||0;return zl(t)?Math.ceil(n*.5):n}function Jl(e,t){return e?.facilities?Object.values(e.facilities).filter(n=>(n?.baseId||n?.id)===t).reduce((n,o)=>n+Math.max(0,(o.level||1)-1),0):0}function yt(e,t){return Fr.includes(t)?Math.pow(Ce.incomeUpgradeRate,Jl(e,t)):1}function ze(e){return Math.ceil(Ce.income.mixer*yt(e,"mixer"))}function Fe(e){return Math.ceil(Ce.income.truck*yt(e,"truck"))}function pn(e){return Math.ceil(Ce.poopFine*yt(e,"mixer")*No(e))}function yn(e){return Math.ceil(Ce.poopFine*yt(e,"truck")*No(e))}function Uo(e){let t=Ce.maleTruckFinePerHalfDay*(e.turn/2);return Math.ceil(t*yt(e,"truck"))}function Wo(e){return e?.facilities?Object.values(e.facilities).filter(t=>(t?.baseId||t?.id)==="trash").reduce((t,n)=>t+Math.max(0,(n.level||1)-1),0):0}function It(e){return Math.min(Ce.shredderBonus.maxCards,Wo(e))}function Vt(){return Ce.shredderBonus.maxCards}function ht(e){let t=typeof e=="number"?e:It(e),n=Math.min(Ce.shredderBonus.maxCards,Math.max(0,t));return n>0?Math.ceil(n*(Ce.shredderBonus.incomePerUpgrade||1)):0}function jl(e){let t=It(e),n=ht(t),o=Math.ceil(n*On(e));return{cards:t,chance:o>0?1:0,amount:o,expected:o,baseAmount:n}}function Ri(e){let t=jl(e);return t.amount>0&&(e.stats.shredderBonus=(e.stats.shredderBonus||0)+t.amount,e.totals.shredderBonus=(e.totals.shredderBonus||0)+t.amount,Ge(e,t.amount)),t}function _n(e,t=e.turn,n=null){let o=Math.max(1,Math.floor(Number(t)||1)),r=Ce.fairiesTribute||{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},i=Math.ceil(o*(r.perDay||10)),l=Math.max(0,Math.floor(Number(n??e?.lastResult?.profit??e?.stats?.profit??0)||0)),c=Math.max(0,e?.cardEffects?.legalWork||0),b=Math.max(0,(r.profitExemption||0)+c*(r.legalWorkExemptionBonus||0)),C=Math.max(0,l-b),T=Math.ceil(C*Math.max(0,Number(r.profitRate)||0)),I=i+T,$=Math.max(0,e?.cardEffects?.fairiesFlatteryNext||e?.cardEffects?.flattery||0),O=$>0?Math.pow(.5,$):1,ee=Math.max(.01,Number(e?.pendingFairiesTributeMultiplier)||1),X=O*ee,ae=Math.max(0,Math.ceil(I*X)),he=Math.max(0,I-ae);return{day:o,base:i,profit:l,legalWork:c,profitExemption:b,taxableProfit:C,profitTribute:T,gross:I,flatteryCount:$,eventMultiplier:ee,perCardReduction:Math.ceil(I*.5),reduction:he,amount:ae}}function mt(e,t){let n=e?.ref||e||{},o=e?.type==="conveyor"?t?.conveyorMeta?.get(e.oldKey||n.id):n,r=o?.price||Nn(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=Xl(t,i);return{amount:Math.max(0,Math.ceil(r*l)),sameBuild:i,price:r,rate:l,noRefund:!1}}function Zl(e,t=null){let n=Math.max(1,Math.ceil((Number(e)||0)/Ce.explosionDamageDivisor));return Math.max(1,Math.ceil(n*Ql(t)))}function ea(e,t){return Math.max(0,Math.ceil(t))}function Pi(e,t){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 Ge(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Pi(e,n),n}function bt(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Pi(e,-n),n}function $t(e,t){bt(e,t)}function Ai(e,t){t<=0||(e.cash+=t,e.stats.profit+=t,e.totals.profit+=t,e.totals.maxCash=Math.max(e.totals.maxCash,e.cash))}function Di(e){let t=ze(e);return e.stats.mixerRevenue+=t,Ge(e,t),t}function Ii(e){let t=pn(e);return e.stats.mixerPoopFine+=t,e.totals.mixerPoopFine+=t,bt(e,t),t}function $i(e){let t=yn(e);return e.stats.truckPoopFine+=t,e.totals.truckPoopFine+=t,bt(e,t),t}function Fi(e){let t=Uo(e);return e.stats.maleTruckFine+=t,e.totals.maleTruckFine+=t,bt(e,t),t}function Bi(e,t){let n=Zl(t,e);return e.stats.explosionDamage+=n,e.totals.explosionDamage+=n,bt(e,n),n}function Li(e){let t=je(e),n=Lo(e.stats,t),o=t==="poop"?Math.ceil(Fe(e)*Oo(e)):Fe(e),r=n*o,i=ea(e,r);return e.stats.pendingTruckRevenue=i,e.stats.truckRevenue=i,t==="poop"?e.stats.poopShipmentIncome=i:e.stats.chickShipmentIncome=i,i>0&&Ge(e,i),{base:r,adjusted:i,target:t,targetCount:n,unitPrice:o}}function Oi(e,t=e.turn,n=null,o={}){let r=_n(e,t,n);return e.cardEffects&&(e.cardEffects.fairiesFlatteryNext=0,e.cardEffects.flattery!=null&&delete e.cardEffects.flattery),e.pendingFairiesTributeMultiplier!=null&&(e.pendingFairiesTributeMultiplier=1),r.amount<=0||(o.recordStats?(e.stats.fairiesTribute=(e.stats.fairiesTribute||0)+r.amount,e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,bt(e,r.amount)):(e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,e.totals.penalty=(e.totals.penalty||0)+r.amount,e.totals.profit=(e.totals.profit||0)-r.amount,e.cash-=r.amount)),r}function Ni(e){let t=Go(e,"chemicalWeaponSubsidy"),n=Math.max(0,e?.stats?.poopTruck||0),o=Ce.chemicalWeaponSubsidy||{poopPerBlock:70,yenPerBlock:1200},r=Math.floor(n/Math.max(1,o.poopPerBlock||70)),i=t>0&&r>0?r*Math.max(0,o.yenPerBlock||1200)*t:0;return i>0&&(e.stats.chemicalWeaponSubsidy=(e.stats.chemicalWeaponSubsidy||0)+i,e.totals.chemicalWeaponSubsidy=(e.totals.chemicalWeaponSubsidy||0)+i,Ge(e,i)),{cards:t,poopTruck:n,blocks:r,amount:i}}function _i(e){let t=Bo(e),n=Math.max(1,e.totals.turnsCompleted||e.turn||1),o=Math.max(0,e.cash+e.totals.revenue+t*.5+e.totals.eventBonus*.5),r=Math.ceil(o/n),i=Math.floor(n*35+Math.max(0,n-5)*15),l=e.totals.correct*5,c=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:c,days:n}}function ta(e){return{...e,keys:e.keys?{left:{...e.keys.left},right:{...e.keys.right}}:null,queue:[],cooldown:e.cooldown||0}}function hn(e){return JSON.stringify({cash:e.cash,stats:e.stats,totals:e.totals,nextId:e.nextId,gridX:f.x,gridY:f.y,gridCols:e.gridCols||f.cols,gridRows:e.gridRows||f.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(ta),conveyorTiles:[...e.conveyorTiles],conveyorMeta:[...e.conveyorMeta.entries()],branchCounters:[...e.branchCounters.entries()],cardEffects:e.cardEffects,cardDraft:e.cardDraft,cardTargetPick:e.cardTargetPick})}function Gi(e,t){let n=JSON.parse(t);e.cash=n.cash,e.stats=n.stats,e.totals=n.totals,e.nextId=n.nextId,f.x=n.gridX??Y.grid.x,f.y=n.gridY??Y.grid.y,f.cols=n.gridCols||Y.grid.cols,f.rows=n.gridRows||Y.grid.rows,e.gridCols=f.cols,e.gridRows=f.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||f.cols*f.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,fairiesFlatteryNext:0,scannerQueueSpacing: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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=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 Be(e){e.phase==="build"&&(e.undoStack.push(hn(e)),e.undoStack.length>80&&e.undoStack.shift(),e.redoStack=[])}function Ko(e){return e.phase!=="build"||!e.undoStack.length?!1:(e.redoStack.push(hn(e)),Gi(e,e.undoStack.pop()),!0)}function Ho(e){return e.phase!=="build"||!e.redoStack.length?!1:(e.undoStack.push(hn(e)),Gi(e,e.redoStack.pop()),!0)}function K(e,t,n,o,r=y.ink){e.floatingTexts.push({x:t,y:n,text:o,color:r,life:1,maxLife:1})}function Ft(e,t,n){e.shake.strength=Math.max(e.shake.strength,t),e.shake.time=Math.max(e.shake.time,n)}function Ui(e,t,n){e.effects.push({type:"spawn",priority:Me.ambient,x:t,y:n,life:.42,maxLife:.42,size:12})}function Wi(e,t,n,o=y.green){e.effects.push({type:"scannerPulse",priority:Me.important,x:t,y:n,color:o,life:.42,maxLife:.42,size:24})}function Ki(e,t,n){for(let o=0;o<12;o+=1)e.effects.push({type:"meat",priority:Me.important,x:t+W(-18,18),y:n+W(-12,16),vx:W(-60,60),vy:W(-90,-25),life:W(.45,.85),maxLife:.85,size:W(4,8)})}function Hi(e,t,n){for(let o=0;o<16;o+=1)e.effects.push({type:"sludge",priority:Me.important,x:t+W(-18,18),y:n+W(-12,16),vx:W(-46,46),vy:W(-70,-20),life:W(.45,.9),maxLife:.9,size:W(4,8)})}function qi(e,t,n,o){let r=o==="poop"?y.poop:o==="male"?y.male:y.female;for(let i=0;i<22;i+=1)e.effects.push({type:"shred",priority:Me.important,x:t+W(-16,16),y:n+W(-8,8),vx:W(-70,70),vy:W(40,160),color:i%3===0?y.white:r,life:W(.45,.95),maxLife:.95,w:W(3,7),h:W(10,24),rot:W(-Math.PI,Math.PI)});Xe(e,t,n,y.green,34,Me.important)}function Yi(e,t,n,o){let r=o==="poop"?y.poop:o==="male"?y.danger:y.green;for(let i=0;i<8;i+=1)e.effects.push({type:"load",priority:Me.important,x:t+W(-18,18),y:n+W(-18,18),vx:W(-42,42),vy:W(-90,-25),color:r,life:W(.35,.65),maxLife:.65,size:8})}function Xe(e,t,n,o=y.danger,r=52,i=Me.critical){e.effects.push({type:"shockwave",priority:i,x:t,y:n,color:o,life:.55,maxLife:.55,size:8,maxSize:r})}function Ze(e,t,n,o=12,r=y.danger,i=Me.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||na(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 na(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=Bi(e,o.price);K(e,t.x,t.y-10,`-${x(r)}`,y.danger),Xe(e,t.x,t.y,y.danger,30),Ze(e,t.x,t.y,5,y.danger),Ft(e,5,.18)}}var Ue=Y.maintenance;function Yo(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Wn(e){let t=Math.min(1.4,1+.04*Math.min(10,Yo(e,"crowdedFarming"))),n=Math.pow(.95,Yo(e,"preventiveMaintenance"));return t*n}function oa(e){return Math.pow(1.03,Yo(e,"durabilityCoating"))}function Kn(e,t,n=1){let o=Ue.durability[t]||1e3;return Math.max(1,Math.ceil(o*Math.max(.1,n||1)*oa(e)))}function Xi(e){return Math.max(.1,Number(e?.durabilityBaseMultiplier)||1)}function ra(e,t=0){if(!e)return{x:f.x+f.cell*(.5+t*.55),y:f.y+f.rows*f.cell+84};let n=f.x+e.col*f.cell+f.cell,o=f.y+e.row*f.cell+f.cell;return{x:n,y:o}}function ia(e,t=0){let n=(e.maintenanceRooms||[])[t];return ra(n,t)}function Se(e){e.repairman||(e.repairman={active:!1,x:f.x+f.cell*.5,y:f.y+f.rows*f.cell+84,target:null,repairedToday:0}),Array.isArray(e.maintenanceRooms)||(e.maintenanceRooms=[]),Array.isArray(e.repairmen)||(e.repairmen=[]);for(let[t,n]of e.conveyorMeta||[]){n.uses==null&&(n.uses=0),n.maintenanceType==null&&(n.maintenanceType="conveyor"),n.kind||(n.kind="conveyor"),n.speedMultiplier||(n.speedMultiplier=n.kind==="boostConveyor"?2:1),n.branchMode||(n.branchMode="random");let o=Kn(e,"conveyor",Xi(n));(n.durability==null||n.durability0&&(n.processingCooldown=Math.max(0,n.processingCooldown-t))}function vn(e){Se(e);let t=[];for(let[n,o]of e.conveyorMeta||[])t.push({type:"conveyor",key:n,meta:o,label:`${o.kind==="boostConveyor"?"Boost Belt":"Belt"} ${n}`,center:B(te(n).col,te(n).row)});for(let n of e.eggFarms||[])t.push({type:"eggFarm",ref:n,label:`EGG #${n.id}`,center:B(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:B(n.col,n.row)});for(let n of Object.values(e.facilities||{})){let o=Vn(n);["mixer","trash"].includes(o)&&t.push({type:o,ref:n,label:`${n.shortName||n.name||o} #${n.id}`,center:{x:n.x+n.w/2,y:n.y+n.h/2}})}return t}function Bt(e){return e.meta?zt(e):zt(e.ref)}function mn(e){return e.meta?Vo(e):Vo(e.ref)}function Un(e){return e.meta?zo(e):zo(e.ref)}function es(e,t){sa(e.meta?e:e.ref,Math.max(0,mn(e)-t))}function nr(e){return e.type==="conveyor"?`conveyor:${e.key}`:`${e.type}:${e.ref?.id||e.ref?.type||e.type}`}function ts(e,t=.02){Se(e);let n=Math.max(0,Number(t)||0),o=0;for(let r of vn(e)){let i=mn(r);es(r,Un(r)*n),o+=Math.max(0,i-mn(r))/Un(r)*100}return o}function ns(e){Se(e);let t=e.maintenanceRooms||[];e.repairmen=t.map((o,r)=>{let i=ia(e,r);return{id:`room-${o.id}`,roomId:o.id,active:!0,x:i.x,y:i.y,target:null,repairedToday:0}});let n=e.repairmen[0];e.repairman.active=!!n,e.repairman.target=n?.target||null,e.repairman.repairedToday=0,n&&(e.repairman.x=n.x,e.repairman.y=n.y)}function os(e){Se(e);for(let t of e.repairmen||[])t.active=!1,t.target=null;e.repairmen=[],e.repairman.active=!1,e.repairman.target=null}function aa(e,t){return t&&vn(e).find(o=>nr(o)===t.key)||null}function ca(e){let t=null;for(let n of vn(e)){let o=Bt(n);o<=.001||(!t||o>Bt(t))&&(t=n)}return t}function rs(e,t){Se(e);let n=e.repairmen?.length?e.repairmen:e.repairman?.active?[e.repairman]:[];if(!n.length||e.phase!=="running")return;let o=new Set(n.map(i=>i.target?.key).filter(Boolean));for(let i of n)ua(e,i,t,o);let r=n[0];r&&e.repairman!==r&&(e.repairman.active=!0,e.repairman.x=r.x,e.repairman.y=r.y,e.repairman.target=r.target,e.repairman.repairedToday=r.repairedToday||0)}function ua(e,t,n,o){if(!t.active)return;let r=aa(e,t.target);if((!r||Bt(r)<=.001)&&(t.target?.key&&o.delete(t.target.key),r=da(e,o)),!r){t.target=null;return}let i=nr(r);o.add(i),t.target={key:i,label:r.label};let l=Ue.repairman.walkSpeed,c=r.center.x-t.x,b=r.center.y-t.y,C=Math.hypot(c,b);if(C>8){let X=Math.min(C,l*n);t.x+=c/C*X,t.y+=b/C*X;return}let T=e?.cardEffects?.laborExploitation?.7:1,I=n/(Ue.repairman.secondsPerOnePercent*T*100),$=mn(r),O=I*Un(r);es(r,O);let ee=Math.max(0,($-mn(r))/Un(r)*100);t.repairedToday=(t.repairedToday||0)+ee,ee>0&&Math.random()<.02&&K(e,t.x,t.y-28,"REPAIR",y.green),Bt(r)<=.001&&(o.delete(i),t.target=null)}function da(e,t=new Set){let n=null;for(let o of vn(e)){if(t.has(nr(o)))continue;let r=Bt(o);r<=.001||(!n||r>Bt(n))&&(n=o)}return n||ca(e)}function fa(e){let t=0,n="none";for(let o of vn(e)){let r=Bt(o);r>t&&(t=r,n=o.label)}return{ratio:t,percent:Math.round(t*100),label:n}}function or(e){let t=fa(e),n=Qo(e);return{worst:t,avgBeltPerformance:n,repairman:e.repairman||null,repairmen:e.repairmen||[],rooms:e.maintenanceRooms||[]}}var pa=Ie.commonWeight,ya=Ie.rareWeight,ha=Ie.ultraRareWeight||.45,Lt=Ie.baseDraftSize,Qt=$r;function Xt(e,t){let n=Le(e);return Math.max(0,Number(n[t])||0)}function Le(e){e.cardEffects||(e.cardEffects={...wo});for(let[t,n]of Object.entries(wo))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),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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=0),e.cardEffects}function fs(e){let t=Math.max(.5,1-.05*Math.min(10,Xt(e,"crowdedFarming"))),n=Math.pow(.96,Xt(e,"hatchingFeed"));return t*n}function ps(e,t=null){return Math.min(3,Math.max(0,Number(t?.extraEggOutlet)||0))}function ys(e){return Math.pow(.85,Xt(e,"scannerQueueSpacing"))}function Xn(e,t=null){let n=Le(e),o=Tn*Math.pow(En,Math.max(0,n.bearing||0)),r=t?Math.max(.1,Number(e?.conveyorMeta?.get?.(t)?.speedMultiplier)||1):1,i=t?1:Qo(e),l=Math.max(.01,Number(e?.eventActive?.conveyorSpeedMultiplier)||1);return Math.min(Wt,o*i)*r*l}function nt(e,t=null){let n=Math.max(0,(e?.level||1)-1),o=t?Xt(t,"autoScannerTuning"):0,r=xn*Math.pow(Dr,n)*Math.pow(ho,o),i=Math.max(mo,r),l=t?Math.max(.01,Number(t?.eventActive?.autoScannerCooldownMultiplier)||1):1;return t?Math.max(mo,i*qn(e)*l):i}function is(e){let t=e.cardDraft||{rerolls:0},n=Math.max(1,(t.rerolls||0)+1);return Math.ceil(Math.max(1,e.turn||1)/Ie.rerollCost.dayDivisor*n*Ie.rerollCost.multiplier)}function Jt(e){return Qt.find(t=>t.id===e)||null}function hs(e,t){let n=typeof t=="string"?Jt(t):t;return Le(e),!n||!(n.type==="equipmentUpgrade"||n.type==="cellAction")?[]:We(e,n).map(o=>({key:tt(o),label:sr(e,o),type:o.type}))}function ir(e,t,n={}){let o=typeof t=="string"?Jt(t):t;if(Le(e),!o||o.type==="dud")return{ok:!1,reason:"Card not found."};if(o.id==="extraCards")return e.cardDraft=e.cardDraft||{pending:!1,choices:[],rerolls:0,picksRemaining:0},e.cardDraft.choices.push(...zn(e,2)),{ok:!0,reason:`${o.title} added 2 draft cards.`};if(o.type==="instant")return bs(e,o),{ok:!0,reason:`${o.title} granted.`};if(o.type==="equipmentUpgrade"){let r=We(e,o);if(!r.length)return{ok:!1,reason:`No valid target for ${o.title}.`};let i=n.targetKey&&n.targetKey!=="__auto__"?String(n.targetKey):"",l=i?r.find(c=>tt(c)===i):r[0];return l?(ms(e,l),{ok:!0,reason:`${o.title} applied to ${sr(e,l)}.`}):{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`}}if(o.type==="cellAction"&&o.target==="blockedCell"){let r=We(e,o);if(!r.length)return{ok:!1,reason:"No blocked cells to remove."};let i=new Set((Array.isArray(n.targetKeys)?n.targetKeys:[n.targetKey]).filter(c=>c&&c!=="__auto__").map(String)),l=i.size?r.filter(c=>i.has(tt(c))):r.slice(0,3);if(!l.length)return{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`};for(let c of l.slice(0,3)){e.blockedCells.delete(A(c.col,c.row));let b=B(c.col,c.row);et(e,b.x,b.y),Xe(e,b.x,b.y,y.danger,42),Ze(e,b.x,b.y,8,y.warn)}return me(e),{ok:!0,reason:`${o.title} removed ${Math.min(3,l.length)} blocked cell(s).`}}return{ok:!1,reason:`${o.title} cannot be debug-granted.`}}function sr(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 ${nt(t,e).toFixed(1)}s -> ${nt({...t,level:t.level+1},e).toFixed(1)}s`;if(t.type==="facility"&&(t.baseId||t.id)==="mixer"){let n=t.level,o=ze(e);t.level=n+1;let r=ze(e);return t.level=n,`MIXER L${t.level} -> L${t.level+1} | ${x(o)} -> ${x(r)}`}if(t.type==="facility"&&(t.baseId||t.id)==="truck"){let n=t.level,o=Fe(e);t.level=n+1;let r=Fe(e);return t.level=n,`TRUCK L${t.level} -> L${t.level+1} | ${x(o)} -> ${x(r)}`}if(t.type==="facility"&&t.id==="trash"){let n=It(e),o=Math.min(Vt(),n+1),r=ht(n),i=ht(o);return`SHREDDER L${t.level||1} -> L${(t.level||1)+1} | poop income ${x(r)} -> ${x(i)} per item`}return`${t.name||t.id} L${t.level||1} -> L${(t.level||1)+1}`}function ma(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 We(e,t){let n=typeof t=="string"?Jt(t):t;return Le(e),n?n.target==="blockedCell"?ma(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"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="mixer"):n.target==="truck"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="truck"):n.target==="trash"?Wo(e)(o.baseId||o.id)==="trash"):[]:[]:[]}function ba(e,t){let n=Le(e);if(t.id==="crowdedFarming")return(n.crowdedFarming||0)>=10;if(t.id==="recyclingSubsidy")return(n.recyclingSubsidy||0)>=3;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,Ie.dudChancePerCard||0)),r=Math.max(1e-4,Math.min(1,Ie.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 va(e){return!!((e.maintenanceRooms||[]).length||(e.repairmen||[]).length||e.repairman?.active)}function wa(e){return Qt.filter(t=>!(t.id==="laborExploitation"&&!va(e)||ba(e,t)||(t.type==="equipmentUpgrade"||t.type==="cellAction")&&We(e,t).length<=0))}function ss(e,t){return t.rarity==="ultraRare"?ha:t.rarity==="rare"?ya:pa}function Sa(e,t){let n=t.reduce((r,i)=>r+ss(e,i),0);if(n<=0)return t[Math.floor(Math.random()*t.length)];let o=Math.random()*n;for(let r of t)if(o-=ss(e,r),o<=0)return r;return t[t.length-1]}var ls=0;function ka(){return ls+=1,{id:`dud:${Date.now()}:${ls}`,title:"Dud",rarity:"dud",type:"dud",description:"Click to flick this dud away. It does not consume a pick."}}function Ca(e){let t=Le(e),n=Math.max(0,Math.min(1,Ie.dudChancePerCard||0)),o=Math.max(0,Math.min(1,Ie.dudChanceReductionPerFilter||0));return Math.max(0,n-o*Math.max(0,t.dudFilter||0))}function Ma(e,t){let n=[...t],o=0,r=Math.max(0,Ie.maxDudsPerDraft||0),i=Ca(e);for(let l=0;lc.id===i.id);l>=0&&r.splice(l,1)}return Ma(e,o)}function tt(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 as(e){if(!e)return null;if(e.type==="blockedCell"){let t=B(e.col,e.row);return{x:t.x-f.cell*.48,y:t.y-f.cell*.48,w:f.cell*.96,h:f.cell*.96,cx:t.x,cy:t.y}}if(e.type==="eggFarm"||e.type==="eggOutlet"){let t=B(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=ye(e);return{x:t.x-54,y:t.y-77,w:108,h:154,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 lr(e){if(!e.cardTargetPick?.pending)return[];if(e.cardTargetPick.mode==="autoScannerMenu"){let n=new Set(e.cardTargetPick.targetKeys||[]);return e.scanners.filter(o=>o.kind==="auto"&&n.has(tt(o))).map(o=>({key:tt(o),label:"AUTO ROUTE SETTINGS",target:o,bounds:as(o)})).filter(o=>o.bounds)}let t=new Set(e.cardTargetPick.targetKeys||[]);return We(e,e.cardTargetPick.cardId).filter(n=>t.has(tt(n))).map(n=>({key:tt(n),label:sr(e,n),target:n,bounds:as(n)})).filter(n=>n.bounds)}function ga(e,t){let n=lr(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 ms(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=B(n.col,n.row);K(e,o.x,o.y-30,`OUTLET ${1+n.extraEggOutlet}`,y.green),me(e);return}if(t.level=(t.level||1)+1,t.type==="eggFarm"){t.nextSpawn=Rt(t),t.lastInterval=t.nextSpawn;let n=B(t.col,t.row);K(e,n.x,n.y-30,`LV ${t.level}`,y.green);return}if(t.type==="scanner"){let n=ye(t);K(e,n.x,n.y-34,`LV ${t.level}`,y.green);return}t.type==="facility"&&K(e,t.x+t.w/2,t.y+18,`LV ${t.level}`,y.green)}function bs(e,t){let n=Le(e),o=r=>{n[r]=Math.max(0,n[r]||0)+1};if(t.id==="bearing"&&o("bearing"),t.id==="autoScannerTuning"&&o("autoScannerTuning"),t.id==="legalWork"&&o("legalWork"),t.id==="crowdedFarming"&&(n.crowdedFarming=Math.min(10,(n.crowdedFarming||0)+1)),t.id==="hatchingFeed"&&o("hatchingFeed"),t.id==="poopRateBooster"&&o("poopRateBooster"),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"),Se(e)),t.id==="sparePartsBin"){o("sparePartsBin");let r=ts(e,.02);e.stats.sparePartsRepair=(e.stats.sparePartsRepair||0)+r,e.totals.sparePartsRepair=(e.totals.sparePartsRepair||0)+r,K(e,f.x+f.cols*f.cell/2,f.y-30,"REPAIR +2%",y.green)}t.id==="dudRefund"&&o("dudRefund"),t.id==="freeReroll"&&o("freeReroll"),t.id==="composter"&&o("composter"),t.id==="scannerQueueSpacing"&&o("scannerQueueSpacing"),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"),K(e,f.x+f.cols*f.cell/2,f.y-30,"RESCUE HELD",y.green))}function qe(e){return`${Math.round(Number(e||0)*100)}%`}function cs(e){let t=lt[Math.max(0,Math.min(lt.length-1,e-1))]||lt[0]||[0,0];return`${t[0].toFixed(2)}-${t[1].toFixed(2)}s`}function us(e,t){return Math.ceil(e*Math.pow(Ce.incomeUpgradeRate,Math.max(0,t-1)))}function ds(e,t,n){let r=We(e,t==="mixer"?"upgradeMixer":"upgradeTruck")[0];if(!r)return{before:us(n,1),after:us(n,2)};let i=t==="mixer"?ze(e):Fe(e),l=r.level||1;r.level=l+1;let c=t==="mixer"?ze(e):Fe(e);return r.level=l,{before:i,after:c}}function xa(e,t){let n=Le(e);if(t.id==="upgradeEgg"){let o=We(e,t),r=Math.min(3,Math.max(1,o[0]?.level||1));return`Choose one EGG. Level +1. Production interval ${cs(r)} -> ${cs(r+1)}.`}if(t.id==="upgradeAutoScanner"){let o=We(e,t)[0]||{level:1},r=nt(o,e),i=nt({...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=ds(e,"mixer",Ce.income.mixer);return`Choose one MIXER. Earning +10%. Male-chick income ${x(o.before)} -> ${x(o.after)}.`}if(t.id==="upgradeTruck"){let o=ds(e,"truck",Ce.income.truck);return`Choose one TRUCK. Earning +10%. Correct shipment income ${x(o.before)} -> ${x(o.after)}.`}if(t.id==="upgradeTrash"){let o=It(e),r=Math.min(Vt(),o+1),i=ht(o),l=ht(r);return`SHREDDER level +1. Poop income ${x(i)} -> ${x(l)} per item.`}if(t.id==="bearing"){let o=Math.min(Wt,Tn*Math.pow(En,Math.max(0,n.bearing||0))),r=Math.min(Wt,Tn*Math.pow(En,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`Fairies tribute profit exemption +${x(250)}. After pick: exemption bonus ${x(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 ${qe(Math.max(.5,1-.05*o))}, deterioration ${qe(Math.min(1.4,1+.04*o))}.`}if(t.id==="extraEggOutlet"){let o=We(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 ${qe(Math.pow(.96,(n.hatchingFeed||0)+1))}, poop rate multiplier ${qe(Math.pow(1.03,(n.hatchingFeed||0)+1))}.`;if(t.id==="poopRateBooster")return`Held ${n.poopRateBooster||0}. After pick: base poop rate +${Math.round((n.poopRateBooster||0)+1)*4} percentage points.`;if(t.id==="autoScannerTuning")return`Held ${n.autoScannerTuning||0}. After pick: all AUTO SCANNER default cooldown ${qe(Math.pow(ho,(n.autoScannerTuning||0)+1))}.`;if(t.id==="safetyCover")return`Held ${n.safetyCover||0}. After pick: explosion damage ${qe(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: ${x(1200*((n.chemicalWeaponSubsidy||0)+1))} per 70 truck-shipped poop each day.`;if(t.id==="preventiveMaintenance")return`Held ${n.preventiveMaintenance||0}. After pick: deterioration speed ${qe(Math.pow(.95,(n.preventiveMaintenance||0)+1))}.`;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,Ie.dudChancePerCard||0)),r=Math.max(0,Math.min(1,Ie.dudChanceReductionPerFilter||.05)),i=Math.max(0,n.dudFilter||0),l=Math.max(0,o-r*i),c=Math.max(0,o-r*(i+1));return`Held ${i}. DUD chance per card ${qe(l)} -> ${qe(c)}.`}return t.id==="durabilityCoating"?`Held ${n.durabilityCoating||0}. After pick: maximum durability ${qe(Math.pow(1.03,(n.durabilityCoating||0)+1))}.`:t.id==="sparePartsBin"?`Held ${n.sparePartsBin||0}. Immediately restores 2% durability to every maintained machine. Common card weight.`:t.id==="dudRefund"?`Held ${n.dudRefund||0}. After pick: DUD clicks award ${x(50*((n.dudRefund||0)+1))}.`:t.id==="freeReroll"?`Held ${n.freeReroll||0}. After pick: each card screen starts with ${(n.freeReroll||0)+1} free reroll${(n.freeReroll||0)+1===1?"":"s"}.`:t.id==="composter"?`Held ${n.composter||0}. After pick: SHREDDER poop grants ${x(3*((n.composter||0)+1))}.`:t.id==="scannerQueueSpacing"?`Held ${n.scannerQueueSpacing||0}. After pick: Manual/Auto Scanner queue spacing ${qe(Math.pow(.85,(n.scannerQueueSpacing||0)+1))}.`:t.id==="flattery"?`Next Fairies tribute -50%. Held for next tribute: ${n.fairiesFlatteryNext||0}.`:t.id==="usedMachine"?"Enable Used Machines: future equipment costs 50%, has no SELL refund, and starts with 60% durability.":t.id==="newMachine"?"Cancel Used Machines. Future equipment returns to normal price, refund, and durability.":t.id==="laborExploitation"?"Repairman dispatch paperwork is streamlined. Repair rooms keep operating; one time only.":t.id==="rescueLoan"?`At day-end bankruptcy check, gain ${x(500)} if cash is below ${x(0)}. Held: ${n.rescueLoanCharges||0}.`:t.description}function rr(e,t){let n=e.cardDraft?.choices||[],o=n.findIndex(r=>r.id===t.id);o>=0&&n.splice(o,1)}function vs({game:e,ui:t,onUpdatePanels:n}){function o(){n&&n()}function r(){Le(e),e.cardTargetPick=null,e.cardDraft={pending:!0,choices:zn(e,Lt),rerolls:0,freeRerolls:Xt(e,"freeReroll"),picksRemaining:1}}function i(){Le(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(P=Lt){Le(e),e.cardDraft.choices=zn(e,P)}function c(){Le(e),!e.cardDraft.choices.length&&e.cardDraft.picksRemaining>0&&l(Lt)}function b(P){rr(e,P),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1),e.cardTargetPick=null,c(),e.cardDraft.picksRemaining<=0?i():ie()}function C(P){rr(e,P),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1)+Ie.extraCardsAddedPicks,e.cardDraft.choices.push(...zn(e,2)),ie()}function T(P,G){let H=Xt(e,"dudRefund")*50;if(H>0){let be=Ge(e,H);e.stats.dudRefundIncome=(e.stats.dudRefundIncome||0)+be,e.totals.dudRefundIncome=(e.totals.dudRefundIncome||0)+be,K(e,f.x+f.cols*f.cell/2,f.y-30,`DUD REFUND +${x(be)}`,y.green)}Ft(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)"}),G&&(G.style.setProperty("--fling-x",`${260+Math.random()*260}px`),G.style.setProperty("--fling-y",`${-260-Math.random()*170}px`),G.style.setProperty("--fling-r",`${(Math.random()<.5?-1:1)*(52+Math.random()*38)}deg`),G.classList.add("flung")),window.setTimeout(()=>{rr(e,P),c(),ie()},340)}function I(P,G=null){if(P.type==="dud")return T(P,G);if(P.id==="extraCards")return C(P);if(P.type==="equipmentUpgrade"||P.type==="cellAction")return $(P);bs(e,P),b(P)}function $(P){let G=We(e,P);G.length&&(e.cardTargetPick={pending:!0,cardId:P.id,mode:P.target==="blockedCell"?"blockedCell":"equipment",targetKeys:G.map(tt),remaining:P.id==="dynamite"?Math.min(3,G.length):1},t.modal.classList.remove("visible","equipment-popover"),o())}function O(P){if(!P||P.type!=="blockedCell")return!1;let G=A(P.col,P.row);if(!e.blockedCells?.has(G))return!1;e.blockedCells.delete(G);let H=B(P.col,P.row);return et(e,H.x,H.y),Xe(e,H.x,H.y,y.danger,62),Ze(e,H.x,H.y,18,y.warn),Gn(e,H.x,H.y,8),Ft(e,16,.35),K(e,H.x,H.y-18,"BOOM",y.danger),me(e),e.cardTargetPick.remaining=Math.max(0,(e.cardTargetPick.remaining||1)-1),e.cardTargetPick.targetKeys=We(e,"dynamite").map(tt),o(),!0}function ee(P){if(!e.cardTargetPick?.pending)return!1;let G=Jt(e.cardTargetPick.cardId),H=ga(e,P);return!G||!H?(X(),!0):G.id==="dynamite"?(O(H)&&((e.cardTargetPick.remaining||0)<=0||!We(e,"dynamite").length)&&b(G),!0):(ms(e,H),b(G),!0)}function X(){e.cardTargetPick?.pending&&(e.cardTargetPick=null,ie())}function ae(){let P=Math.max(0,e.cardDraft?.freeRerolls||0);if(P>0){e.cardDraft.freeRerolls=P-1,e.cardDraft.rerolls+=1,l(Lt),ie();return}let G=is(e);e.cash${G.alt||`:``}function se(P,G){let H=document.createElement("button");H.type="button";let be=P.type==="dud"?"dud":P.rarity==="ultraRare"?"ultra-rare":P.rarity==="rare"?"rare":"common";H.className=`card-choice ${be}`;let F=P.type==="dud"?"MISS":P.rarity==="ultraRare"?"ULTRA RARE":P.rarity==="rare"?"RARE":"COMMON",U=[F,...(P.tags||[]).filter(S=>S!==F)].slice(0,5);return H.innerHTML=`${re(P)}
${P.title}
${U.map(S=>`${S}`).join("")}
${xa(e,P)}
`,H.addEventListener("click",()=>I(P,H)),H.dataset.index=String(G),H}function ie(){Le(e),e.cardTargetPick=null,e.cardDraft?.pending||r(),e.cardDraft.choices?.length||l(Lt);let P=e.cardDraft.choices||[],G=is(e),H=Math.max(0,e.cardDraft?.freeRerolls||0),be=Math.max(1,e.cardDraft.picksRemaining||1);t.modalTitle.textContent="Choose Upgrade Card",t.modalBody.innerHTML=`

Choose ${be} card${be===1?"":"s"} before Build phase. Dud cards can be flicked away without consuming a pick. Equipment cards target machines; Dynamite targets blocked cells.

`;let F=t.modalBody.querySelector("#cardChoices");P.forEach((g,N)=>F.appendChild(se(g,N))),t.modalActions.innerHTML="";let U=document.createElement("button");U.type="button",U.className="facility-action warn reroll-button",U.textContent=H>0?`Reroll (FREE x${H})`:`Reroll ${x(G)}`,U.disabled=H<=0&&e.cash0?`${H} free reroll${H===1?"":"s"} remaining.`:U.disabled?"Not enough cash":"",U.addEventListener("click",ae),t.modalActions.appendChild(U);let S=document.createElement("button");S.type="button",S.className="facility-action",S.textContent="No Card",S.title="Skip this upgrade pick and enter Build phase.",S.addEventListener("click",i),t.modalActions.appendChild(S),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible")}return{prepareDraft:r,showDraft:ie,finishDraft:i,chooseTargetAtPoint:ee,cancelTargetPick:X}}var Ta=!0,Ea={chickMale:"./assets/images/chick_male.png",chickFemale:"./assets/images/chick_female.png",poop:"./assets/images/poop.png",conveyorStraightH:"./assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png",conveyorStraightV:"./assets/dark_factory/facilities/conveyor/conveyor_straight_v_16.png",conveyorTurnNe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_ne_16.png",conveyorTurnNw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png",conveyorTurnSe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_se_16.png",conveyorTurnSw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png",boostConveyorStraightH:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_h_16.png",boostConveyorStraightV:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_v_16.png",boostConveyorTurnNe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_ne_16.png",boostConveyorTurnNw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png",boostConveyorTurnSe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_se_16.png",boostConveyorTurnSw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png",scannerManual:"./assets/dark_factory/facilities/machines/manual_scanner_32x48.png",scannerAuto:"./assets/dark_factory/facilities/machines/auto_scanner_32x48.png",eggFarm:"./assets/dark_factory/facilities/machines/egg_farm_16.png",mixer:"./assets/dark_factory/facilities/machines/mixer_32.png",shredder:"./assets/dark_factory/facilities/machines/shredder_32.png",truck:"./assets/dark_factory/facilities/vehicles/truck_32.png",mixerCompact:"./assets/dark_factory/facilities/machines/mixer_compact_16.png",shredderCompact:"./assets/dark_factory/facilities/machines/shredder_compact_16.png",truckCompact:"./assets/dark_factory/facilities/vehicles/truck_compact_16.png",maintenanceRoom:"./assets/dark_factory/facilities/utility/maintenance_room_32.png",repairman:"./assets/dark_factory/facilities/utility/repairman_16.png",obstacleCrate:"./assets/dark_factory/facilities/utility/obstacle_crate_16.png"},ce={};for(let[e,t]of Object.entries(Ea)){let n=new Image;n.loaded=!1,n.onerror=()=>{n.loaded=!1},Ta&&t&&(n.onload=()=>{n.loaded=!0},n.src=t),ce[e]=n}function Cs(e,t,n,o){e.imageSmoothingEnabled=!1,e.clearRect(0,0,t.width,t.height),Ia(e,t),e.save();let r=n.shake.time>0?W(-n.shake.strength,n.shake.strength):0,i=n.shake.time>0?W(-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),Fa(e,n),Ba(e,n),Oa(e,n),za(e,n),nc(e,n),oc(e,n),Xa(e,n),Ja(e,n),Pa(e,n),lc(e,n,o.activeQueuedChick),mc(e,n),fc(e,t,n),dc(e,n,o.selectedObject,o.selectedTitle),pc(e,n),yc(e,n),hc(e,n),e.restore(),vc(e,n,t)}function Ra(e){if(e.type==="eggFarm"){let n=B(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 Pa(e,t){if(t.phase!=="build")return;let n=Ln(t);for(let o of n){let r=Ra(o);e.save(),e.fillStyle="rgba(196,36,36,.22)",e.strokeStyle=y.danger,e.lineWidth=5,e.setLineDash([10,6]),Z(e,r.x,r.y,r.w,r.h,!0,!0),e.setLineDash([]),e.fillStyle=y.danger,e.strokeStyle=y.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 Z(e,t,n,o,r,i=!0,l=!0){e.beginPath(),e.rect(t,n,o,r),i&&e.fill(),l&&e.stroke()}function cr(e,t,n,o,r=y.ink){e.save(),e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.lineWidth=4,e.strokeStyle=y.white,e.fillStyle=r,e.strokeText(o,t,n),e.fillText(o,t,n),e.restore()}function it(e,t,n,o,r,i){if(!t?.loaded)return!1;let l=e.imageSmoothingEnabled;return e.imageSmoothingEnabled=!1,e.drawImage(t,Math.round(n),Math.round(o),Math.round(r),Math.round(i)),e.imageSmoothingEnabled=l,!0}function ws(e,t,n,o,r,i,l=null,c=1){e.fillStyle=i,e.fillRect(Math.round(t),Math.round(n),Math.round(o),Math.round(r)),l&&(e.strokeStyle=l,e.lineWidth=c,e.strokeRect(Math.round(t)+.5,Math.round(n)+.5,Math.round(o)-1,Math.round(r)-1))}function Aa(e,t){let n=(Math.imul(e+37,73856093)^Math.imul(t+71,19349663))>>>0;return n^=n>>>13,n>>>0}function Da(e,t,n,o,r){let i=Aa(o,r);if(i%11>1)return;let l=8+(i>>>4)%Math.max(1,f.cell-20),c=9+(i>>>9)%Math.max(1,f.cell-20),b=7+(i>>>14)%7,C=4+(i>>>18)%5;e.save(),e.globalAlpha=.72,e.fillStyle="#4f9e39",e.strokeStyle="rgba(21,55,21,.72)",e.lineWidth=1.5,e.beginPath(),e.ellipse(t+l,n+c,b,C,(i>>>22)%8*Math.PI/16,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle="rgba(135,214,83,.58)",e.beginPath(),e.ellipse(t+l-b*.22,n+c-C*.28,Math.max(2,b*.34),Math.max(1.5,C*.26),0,0,Math.PI*2),e.fill(),i%3===0&&(e.fillStyle="rgba(55,132,42,.72)",e.beginPath(),e.arc(t+l+b+3,n+c+(i>>>27)%5-2,2.2,0,Math.PI*2),e.fill()),e.restore()}function Ia(e,t){e.fillStyle=y.bg,e.fillRect(0,0,t.width,t.height),e.save(),e.globalAlpha=.85;for(let n=0;n=n;for(let r of Tt(t)){let i=Et(r);e.save(),e.fillStyle=o?"rgba(183,245,198,.34)":"rgba(255,255,255,.22)",e.strokeStyle=o?y.green:y.muted,e.lineWidth=5,e.setLineDash([16,10]),Z(e,i.x,i.y,i.w,i.h,!0,!0),e.setLineDash([]);let l=Mo(r),c=l.cx,b=l.cy;e.fillStyle="rgba(255,255,255,.94)",e.strokeStyle=y.ink,e.lineWidth=4,Z(e,l.x,l.y,l.w,l.h,!0,!0),e.fillStyle=o?y.green:y.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText(r.direction==="right"?"BUY RIGHT LOT":"BUY UPPER LOT",c,b-12),e.fillStyle=y.ink,e.font="900 16px ui-monospace, monospace",e.fillText(`${x(n)} / 10\xD710`,c,b+15),e.fillStyle=y.muted,e.font="900 11px ui-monospace, monospace",e.fillText("blocked tiles included",c,b+30),e.restore()}}function ot(e,t,n,o,r,i,l=0){let c=zt(i);c<.5||(e.save(),e.globalAlpha=Math.min(.62,.12+c*.54),e.fillStyle="#6b4a23",l>0?(e.beginPath(),e.roundRect?.(t,n,o,r,l),e.roundRect?e.fill():Z(e,t,n,o,r,!0,!1)):Z(e,t,n,o,r,!0,!1),e.globalAlpha=Math.min(.9,.25+c*.6),e.strokeStyle="#3a2a16",e.lineWidth=Math.max(2,Math.floor(2+c*5)),e.setLineDash([5,6]),Z(e,t+3,n+3,o-6,r-6,!1,!0),e.restore())}function ar(e,t){let n=e.componentLookup?.get(t);return(n?e.congestion.get(n):null)?.ratio||0}function La(e,t,n={}){let o=Sn(e,t).sort(),i=n.kind==="boostConveyor"?"boostConveyor":"conveyor",l=c=>o.includes(c);if(o.length===2){if(l("left")&&l("right"))return ce[`${i}StraightH`];if(l("up")&&l("down"))return ce[`${i}StraightV`];if(l("up")&&l("right"))return ce[`${i}TurnNe`];if(l("up")&&l("left"))return ce[`${i}TurnNw`];if(l("down")&&l("right"))return ce[`${i}TurnSe`];if(l("down")&&l("left"))return ce[`${i}TurnSw`]}return o.length===1?l("up")||l("down")?ce[`${i}StraightV`]:ce[`${i}StraightH`]:l("up")||l("down")?ce[`${i}StraightV`]:ce[`${i}StraightH`]}function Oa(e,t){let n=[],o=new Set;for(let i of t.conveyorTiles){let{col:l,row:c}=te(i);for(let b of de){let C={col:l+b.dc,row:c+b.dr},T=A(C.col,C.row);if(!t.conveyorTiles.has(T))continue;let I=[i,T].sort().join("|");if(o.has(I))continue;o.add(I);let $=Math.max(ar(t,i),ar(t,T));n.push({a:B(l,c),b:B(C.col,C.row),ratio:$})}}e.save(),e.lineCap="round",e.lineJoin="round";for(let i of[{width:31,color:"#0b0c0f",alpha:1},{width:23,color:"#444b56",alpha:1},{width:15,color:"#171a1f",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=Kt(y.green,y.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=qa(t);for(let i of t.conveyorTiles){let l=B(...Object.values(te(i))),c=t.conveyorMeta.get(i)||{},b=ar(t,i),C=La(t,i,c),T=b>.5;if(e.fillStyle=T?"rgba(196,36,36,.28)":"rgba(0,0,0,.35)",e.strokeStyle=T?y.danger:"rgba(255,184,39,.34)",e.lineWidth=T?3:1,Z(e,l.x-20,l.y-20,40,40,!0,!0),!it(e,C,l.x-19,l.y-19,38,38)){let $=c.kind==="boostConveyor"?"#315e92":"#454b55";e.fillStyle=b>.5?Kt($,"#a12c2c",Math.max(0,(b-.5)/.5)):$,e.strokeStyle=y.ink,e.lineWidth=2,Z(e,l.x-18,l.y-18,36,36,!0,!0)}Na(e,l,i,c,b),ot(e,l.x-18,l.y-18,36,36,{meta:c}),rt(e,t,"conveyor",i,l.x,l.y,38,38),Ya(e,l,r.get(i)||[]);let I=Sn(t,i);Ka(e,l,c,Ua(t,i,I),I),b>.5&&cr(e,l.x,l.y-15,`${Math.floor(b*100)}%`,y.danger)}e.restore()}function Na(e,t,n,o={},r=0){let l=[...new Set([...Array.isArray(o.outDirs)?o.outDirs:[],o.dir].filter(Boolean))][0]||"right",c=l==="up"||l==="down",b=l==="left"||l==="up",C=o.kind==="boostConveyor",T=typeof performance<"u"?performance.now()/(C?70:105):0,I=((b?-T:T)%10+10)%10;e.save(),e.beginPath(),e.rect(t.x-18,t.y-18,36,36),e.clip();let $=C?"rgba(20,126,124,.62)":"rgba(42,47,54,.72)";if(e.fillStyle=$,e.fillRect(t.x-18,t.y-18,36,36),e.strokeStyle=r>.5?"rgba(238,83,61,.90)":"rgba(184,190,198,.92)",e.lineWidth=4,c)for(let O=t.y-28+I;Oe.conveyorTiles.has(A(n.col+o.dc,n.row+o.dr))).map(o=>o.name)}function _a(e,t,n){let o=de.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.(A(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Ms(e,t,n,o=Sn(e,t)){if(o.length<3)return n;let r=te(t),i=new Set(o.filter(b=>_a(e,r,b))),l=o.filter(b=>!i.has(b));if(i.size&&l.length>=2)return l;let c=n.filter(b=>o.includes(b));return c.length>=2?[...new Set(c)]:o}function Ga(e,t,n,o=Sn(e,t),r="random"){let i=Ms(e,t,n,o);return o.length>=3&&r&&r!=="random"&&i.includes(r)?[r]:i}function Ua(e,t,n=Sn(e,t)){let o=e.conveyorMeta?.get?.(t)||{},r=[...new Set([...Array.isArray(o.outDirs)?o.outDirs:[],o.dir].filter(Boolean))];return n.length<3?[]:Ms(e,t,r,n)}function Wa(e,t,n){let o=te(t),r=de.filter(c=>e.conveyorTiles.has(A(o.col+c.dc,o.row+c.dr))).map(c=>c.name),i=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(c=>r.includes(c)),l=r;return i.length?i:l}function Ka(e,t,n,o,r=o){if(r.length<3||o.length<2)return;e.save();let i=o.includes(n.branchMode)?n.branchMode:"random",l=i!=="random";if(e.lineJoin="round",e.lineCap="round",e.lineWidth=2,e.fillStyle="rgba(18,21,26,.94)",e.strokeStyle=l?y.warn:y.green,e.lineWidth=4,Z(e,t.x-18,t.y-18,36,36,!0,!0),e.strokeStyle="#ffd36a",e.lineWidth=3,e.fillStyle="#020304",i!=="random"){let c=de.find(b=>b.name===i);wn(e,t.x,t.y,c?.angle||0,9,6)}else e.beginPath(),e.moveTo(t.x-10,t.y),e.lineTo(t.x-2,t.y),e.lineTo(t.x+8,t.y-8),e.moveTo(t.x-2,t.y),e.lineTo(t.x+8,t.y+8),e.stroke(),wn(e,t.x+9,t.y-9,-Math.PI/4,4,3),wn(e,t.x+9,t.y+9,Math.PI/4,4,3);e.restore()}function Ha(e,t,n){if(!n)return[];let o=te(t),r=de.filter(c=>e.conveyorTiles.has(A(o.col+c.dc,o.row+c.dr))).map(c=>c.name),i=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(c=>r.includes(c));return Ga(e,t,i.length?i:Wa(e,t,n),r,n.branchMode||"random").map(c=>de.find(b=>b.name===c)).filter(Boolean)}function qa(e){let t=new Map;for(let[n,o]of e.conveyorMeta||[]){let r=Ha(e,n,o);r.length&&t.set(n,r)}return t}function Ya(e,t,n){let o=n.slice(0,4);o.length&&(e.save(),e.globalAlpha=1,o.forEach(r=>{let i=t.x+r.dc*11,l=t.y+r.dr*11;e.fillStyle="rgba(255,205,83,.96)",wn(e,i,l,r.angle,9,7),e.fillStyle="#020304",wn(e,i,l,r.angle,6.5,4.6)}),e.restore())}function wn(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 Va(e,t,n,o,r){let i=ye(t),l=null;if(n==="inputA"&&(l={x:i.x,y:i.y-67}),n==="left"&&(l={x:i.x-49,y:i.y+14}),n==="right"&&(l={x:i.x+49,y:i.y+14}),!l)return;let c=n==="inputA"?{x:o.x,y:l.y}:{x:l.x,y:o.y};e.save(),e.lineCap="square",e.lineJoin="bevel",e.strokeStyle="#050609",e.lineWidth=15,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.strokeStyle="#596473",e.lineWidth=9,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.strokeStyle=r||"#7b8795",e.lineWidth=3,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.fillStyle=r||"#7b8795",e.strokeStyle="#050609",e.lineWidth=3,Z(e,l.x-9,l.y-7,18,14,!0,!0),e.restore()}function za(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=Do(n),r=[{type:"inputA",p:Re(n,"inputA"),label:"IN",color:y.green},{type:"left",p:Re(n,"left"),label:$o(o.left),color:Fo(o.left)},{type:"right",p:Re(n,"right"),label:$o(o.right),color:Fo(o.right)}];for(let i of r){if(!i.p)continue;let l=B(i.p.col,i.p.row);Va(e,n,i.type,l,i.color);let c=li(t,n,i.type||(i.label==="IN"?"inputA":null))||t.conveyorTiles.has(A(i.p.col,i.p.row));e.fillStyle=c?Kt("#1a1d23",i.color,.24):"#3a1e22",e.strokeStyle=c?i.color:y.danger,Z(e,l.x-18,l.y-12,36,24,!0,!0),e.fillStyle=y.white,e.fillText(i.label,l.x,l.y+4)}}e.restore()}function Xa(e,t){for(let n of t.eggFarms)Qa(e,n,t)}function Qa(e,t,n){let o=B(t.col,t.row);if(e.save(),it(e,ce.eggFarm,o.x-29,o.y-29,58,58)){ot(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=y.ink,e.lineWidth=2,Z(e,o.x+9,o.y+12,30,18,!0,!0),e.fillStyle=y.ink,e.font="900 10px ui-monospace, monospace",e.textAlign="center",e.fillText(`O${l}`,o.x+24,o.y+24),rt(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore();return}e.fillStyle=y.white,e.strokeStyle=y.ink,e.lineWidth=4,Z(e,o.x-28,o.y-28,56,56,!0,!0),e.fillStyle=y.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=y.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=y.ink,Z(e,o.x-28,o.y-28,56,l,!0,!1),e.strokeStyle=y.white,e.lineWidth=2;for(let c=o.y-24;c=1&&(e.fillStyle=y.white,e.font="900 12px ui-monospace, monospace",e.fillText("SHUT",o.x,o.y+4))}ot(e,o.x-28,o.y-28,56,56,t),rt(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore()}function Ja(e,t){for(let n of t.scanners)ja(e,n,t)}function ja(e,t,n){let o=ye(t);if(e.save(),t.kind==="manual"&&(n.manualCombo?.count||0)>=10){let b=n.manualCombo.count;e.save(),e.globalAlpha=Math.min(.55,.16+b/120),e.strokeStyle=b>=30?y.warn:y.green,e.lineWidth=Math.min(14,5+Math.floor(b/10)),e.shadowColor=e.strokeStyle,e.shadowBlur=Math.min(28,8+b),Z(e,o.x-54,o.y-76,108,152,!1,!0),e.restore()}let r=t.kind==="auto"?ce.scannerAuto:ce.scannerManual;if(it(e,r,o.x-50,o.y-73,100,146)){t.kind==="auto"?ot(e,o.x-50,o.y-73,100,146,t):Ss(e,t,o),rt(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore();return}e.fillStyle=t.kind==="auto"?"#d8ffe2":y.white,e.strokeStyle=y.ink,e.lineWidth=4,Z(e,o.x-50,o.y-73,100,146,!0,!0),e.fillStyle=t.kind==="auto"?y.green:y.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-48),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-28);let c=t.queue.length;t.kind==="manual"?(Ss(e,t,o),e.fillStyle=c>0?y.green:y.muted,e.font="900 10px ui-monospace, monospace",e.fillText(`Q:${c}`,o.x,o.y+54)):(e.fillStyle=c>0?y.green:y.muted,e.font="900 12px ui-monospace, monospace",e.fillText(`Q:${c} CD:${t.cooldown.toFixed(1)}`,o.x,o.y+54),ot(e,o.x-50,o.y-73,100,146,t)),rt(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore()}function Ss(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,c=n.y+18;e.save(),e.lineWidth=3,e.fillStyle="#f7fff5",e.strokeStyle=y.ink,Z(e,l-4,c-4,68,25,!0,!0),e.font="900 19px ui-monospace, monospace",e.textAlign="center";for(let b=0;b.8,i=t.y+Math.sin(t.bob)*(r?5:1.5);if(e.save(),n&&(e.strokeStyle=y.green,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius+8,0,Math.PI*2),e.stroke()),r&&(e.strokeStyle=y.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")hr(e,t.x,i,t.radius);else{let l=t.sex==="male"?ce.chickMale:ce.chickFemale;if(!it(e,l,t.x-t.radius,i-t.radius,t.radius*2,t.radius*2)){let C=t.sex==="male"?y.male:y.female,T=t.sex==="male"?"#164f8f":"#8b2252";e.fillStyle=C,e.strokeStyle=y.ink,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle="rgba(255,255,255,.24)",e.beginPath(),e.arc(t.x-5,i-7,t.radius*.36,0,Math.PI*2),e.fill(),e.fillStyle=y.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.strokeStyle=T,e.lineWidth=3,t.sex==="male"?(e.beginPath(),e.moveTo(t.x-8,i-t.radius-2),e.lineTo(t.x+8,i-t.radius-2),e.stroke()):(e.beginPath(),e.moveTo(t.x-9,i-t.radius+2),e.lineTo(t.x,i-t.radius-6),e.lineTo(t.x+9,i-t.radius+2),e.stroke())}e.fillStyle=t.sex==="male"?"#dff1ff":"#fff0f7",e.strokeStyle="#050609",e.lineWidth=3,e.font=`900 ${Math.max(10,Math.round(t.radius*.72))}px ui-monospace, monospace`,e.textAlign="center";let b=t.sex==="male"?"\u2642":"\u2640";e.strokeText(b,t.x+t.radius*.54,i+t.radius*.7),e.fillText(b,t.x+t.radius*.54,i+t.radius*.7)}e.restore()}function cc(e,t){let n=null,o=1/0;for(let[r,i]of e.componentLookup.entries()){let l=te(r),c=B(l.col,l.row),b=Math.hypot(t.x-c.x,t.y-c.y);bks(o.type,o.id)===ks(t,n))}function rt(e,t,n,o,r,i,l,c){uc(t,n,o)&&(e.save(),e.fillStyle="rgba(34,185,79,.18)",e.strokeStyle=y.green,e.lineWidth=(t.multiSelected||[]).length>1?6:4,e.setLineDash((t.multiSelected||[]).length>1?[]:[8,5]),Z(e,r-l/2,i-c/2,l,c,!0,!0),e.restore())}function dc(e,t,n,o){if(t.phase==="build"&&(t.multiSelected||[]).length>1){e.save(),e.fillStyle="rgba(255,255,255,.96)",e.strokeStyle=y.ink,e.lineWidth=3,Z(e,54-t.view.x,66-t.view.y,214,42,!0,!0),e.fillStyle=y.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=y.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 fc(e,t,n){if(!n.cardTargetPick?.pending)return;let o=lr(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 b of o){let C=b.bounds,T=8;e.rect(C.x-T,C.y-T,C.w+T*2,C.h+T*2)}e.fill("evenodd");let i=n.cardTargetPick?.mode==="blockedCell";if(!o.length){e.fillStyle="rgba(255,255,255,.95)",e.strokeStyle=y.ink,e.lineWidth=3,Z(e,(260-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,420/r,42/r,!0,!0),e.fillStyle=y.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=y.ink,e.lineWidth=3;let l=Math.max(1,n.cardTargetPick?.remaining||1),c=n.cardTargetPick?.mode==="autoScannerMenu"?"AUTO SCANNER ROUTE SETTINGS. CLICK EMPTY AREA TO CLOSE.":i?`CLICK BLOCKED CELL: ${l} LEFT. PRESS ESC TO CANCEL.`:"CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.";Z(e,(216-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,560/r,42/r,!0,!0),e.fillStyle=y.ink,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(c,(496-(n.view?.x||0))/r,(122-(n.view?.y||0))/r),e.restore()}function pc(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=y.green,e.lineWidth=2,e.setLineDash([7,4]),Z(e,o,r,i,l,!0,!0),e.restore()}function yc(e,t){let n=[...t.effects].sort((o,r)=>(o.priority??Me.ambient)-(r.priority??Me.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=y.green,Z(e,o.x-o.size/2,o.y-o.size/2,o.size*1.5,o.size,!0,!1)):o.type==="sludge"?(e.fillStyle=y.poop,Z(e,o.x-o.size/2,o.y-o.size/2,o.size*1.4,o.size,!0,!1)):o.type==="spawn"?(e.strokeStyle=y.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||y.danger,Z(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||y.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||y.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||y.ink,e.save(),e.translate(o.x,o.y),e.rotate(o.rot||0),Z(e,-o.w/2,-o.h/2,o.w,o.h,!0,!1),e.restore()):o.type==="load"?(e.strokeStyle=o.color||y.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=y.ink,e.lineWidth=3,e.setLineDash([4,4]),Z(e,o.x-o.size/2,o.y-o.size/2,o.size,o.size,!1,!0)):o.type==="rage"?(e.fillStyle=o.color||y.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText("!",o.x,o.y)):o.type==="flyingChick"&&(o.sex==="poop"?hr(e,o.x,o.y,o.radius||11):mr(e,o.x,o.y,o.sex,o.sex==="male")),e.restore()}}function hc(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=y.white,e.fillStyle=n.color,e.strokeText(n.text,n.x,n.y),e.fillText(n.text,n.x,n.y)}e.restore()}function mc(e,t){let n=t.repairmen&&t.repairmen.length?t.repairmen:t.repairman?[t.repairman]:[];for(let o of n)bc(e,t,o)}function bc(e,t,n){if(!!!n?.active)return;if(e.save(),it(e,ce.repairman,n.x-18,n.y-18,36,36)){n.target?.label&&cr(e,n.x,n.y-24,n.target.label,y.green),e.restore();return}e.lineWidth=3,e.fillStyle="#fff0d1",e.strokeStyle=y.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?y.danger:y.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=y.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=y.green,Z(e,n.x-9,n.y+14,18,8,!0,!0),e.strokeStyle=y.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=y.ink,e.font="900 11px ui-monospace, monospace",e.textAlign="center",e.fillText("FIX",n.x,n.y+33),n.target?.label&&cr(e,n.x,n.y-24,n.target.label,y.green),e.restore()}function vc(e,t,n){e.save(),e.font="900 19px ui-monospace, monospace",e.textAlign="left",e.fillStyle=y.ink,e.font="900 19px ui-monospace, monospace",e.fillStyle=y.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=y.white,e.lineWidth=4,e.strokeText(i,24,r),e.fillText(i,24,r),r+=20;e.restore()}var Es=[[{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 wc(e){let t=Es[e]||Es[0];return{left:{...t[0]},right:{...t[1]}}}function Rs(e,t,n){let o={type:"eggFarm",id:e.nextId++,col:t,row:n,level:1,nextSpawn:2,lastInterval:2,extraEggOutlet:0,price:at.eggFarm,builtSession:e.buildSession};return o.nextSpawn=Rt(o),o.lastInterval=o.nextSpawn,o}function Ps(e,t,n,o){let r=o==="auto"?ve.autoScanner.price:ve.manualScanner.price,i=new Set(e.scanners.filter(c=>c.kind==="manual").map(c=>c.slot)),l=0;for(;i.has(l);)l+=1;return{type:"scanner",id:e.nextId++,kind:o,slot:o==="manual"?l:null,role:o==="manual"?l%2:0,col:t,row:n,level:1,queue:[],cooldown:0,price:r,builtSession:e.buildSession,autoMode:"standard",keys:o==="manual"?wc(l):null}}function Jn(e){let t=(e.x-f.x)/f.cell,n=(e.y-f.y)/f.cell,o=Math.max(0,Math.min(f.cols-1,Math.round(t-.5))),r=Math.max(0,Math.min(f.rows-1,Math.round(n-.5))),i=Math.abs(e.x-f.x),l=Math.abs(e.x-(f.x+f.cols*f.cell)),c=Math.abs(e.y-f.y),b=Math.abs(e.y-(f.y+f.rows*f.cell)),C=[["left",i],["right",l],["top",c],["bottom",b]].sort((T,I)=>T[1]-I[1])[0][0];return C==="left"?{side:C,entry:{col:0,row:r}}:C==="right"?{side:C,entry:{col:f.cols-1,row:r}}:C==="top"?{side:C,entry:{col:o,row:0}}:{side:C,entry:{col:o,row:f.rows-1}}}function jn(e,t,n){let o={x:f.x+t.col*f.cell+f.cell/2,y:f.y+t.row*f.cell+f.cell/2},r={left:f.x,right:f.x+f.cols*f.cell,top:f.y,bottom:f.y+f.rows*f.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 As(e,t,n,o){let{entry:r,side:i}=Jn(n),l=ve[t],c=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},b={type:"facility",id:t,name:c.name,x:0,y:0,w:c.w,h:c.h,level:1,price:o||c.price,builtSession:e.buildSession};return jn(b,r,i)}function jt(e){return e?[{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function Ds(e,t,n){return{type:"maintenanceRoom",id:e.nextId++,col:t,row:n,price:at.maintenanceRoom,builtSession:e.buildSession,wCells:2,hCells:2}}function Sc(e){return Math.random()({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 $s({game:e,canvasPoint:t,updatePanels:n,equipmentAtPoint:o,fail:r,pointInGrid:i,rectOfFacility:l,rectsOverlap:c}){function b(S){return S?S.type==="conveyor"?`conveyor:${S.id||S.oldKey}`:S.type==="facility"?`facility:${S.id||S.ref?.id}`:S.type==="maintenanceRoom"?`maintenanceRoom:${S.id||S.ref?.id}`:`${S.type}:${S.id||S.ref?.id}`:""}function C(S){return S?S.type==="conveyor"?{type:"conveyor",id:S.oldKey}:{type:S.type,id:S.ref.id}:null}function T(S){let g=b(C(S));return(e.multiSelected||[]).some(N=>b(N)===g)}function I(S){return S?S.type==="eggFarm"?e.eggFarms.find(g=>g.id===S.id)||null:S.type==="scanner"?e.scanners.find(g=>g.id===S.id)||null:S.type==="facility"?e.facilities[S.id]||null:S.type==="maintenanceRoom"?(e.maintenanceRooms||[]).find(g=>g.id===S.id)||null:S.type==="conveyor"&&e.conveyorTiles.has(S.id)?{type:"conveyor",id:S.id}:null:null}function $(){let S=[];for(let g of e.conveyorTiles){let N=te(g),j=B(N.col,N.row);S.push({type:"conveyor",id:g,center:j,cell:N})}for(let g of e.eggFarms)S.push({type:"eggFarm",id:g.id,ref:g,center:B(g.col,g.row),cell:{col:g.col,row:g.row}});for(let g of e.scanners)S.push({type:"scanner",id:g.id,ref:g,center:ye(g),cell:{col:g.col,row:g.row}});for(let g of e.maintenanceRooms||[]){let N=B(g.col,g.row);S.push({type:"maintenanceRoom",id:g.id,ref:g,center:{x:N.x+f.cell/2,y:N.y+f.cell/2},cell:{col:g.col,row:g.row}})}for(let g of Object.values(e.facilities)){let N={x:g.x+g.w/2,y:g.y+g.h/2},j=g.entry?B(g.entry.col,g.entry.row):N;S.push({type:"facility",id:g.id,ref:g,center:N,portCenter:j})}return S}function O(S,g){let N=Math.min(g.x1,g.x2),j=Math.max(g.x1,g.x2),J=Math.min(g.y1,g.y2),pe=Math.max(g.y1,g.y2);return S.x>=N&&S.x<=j&&S.y>=J&&S.y<=pe}function ee(S){let g=[];for(let N of $())(O(N.center,S)||N.portCenter&&O(N.portCenter,S))&&g.push({type:N.type,id:N.id});return e.multiSelected=g,e.selected=g[0]||null,n(),g.length}function X(){e.multiSelected=[],e.selected=null,n()}function ae(S){let g=t(S);return e.selectionBox={x1:g.x,y1:g.y,x2:g.x,y2:g.y},e.multiSelected=[],e.selected=null,n(),!0}function he(S){if(!e.selectionBox)return;let g=t(S);e.selectionBox.x2=g.x,e.selectionBox.y2=g.y}function re(){if(!e.selectionBox)return 0;let S=e.selectionBox,g=Math.abs(S.x2-S.x1),N=Math.abs(S.y2-S.y1);return e.selectionBox=null,g<6&&N<6?(X(),0):ee(S)}function se(S){let g=C(S);return g?(e.multiSelected||[]).length&&T(S)?[...e.multiSelected]:[g]:[]}function ie(S){let g=I(S);if(!g)return null;if(S.type==="conveyor"){let N=te(S.id);return{...S,obj:g,oldKey:S.id,currentKey:S.id,meta:e.conveyorMeta.get(S.id)||{price:Oe("conveyor"),builtSession:null},col:N.col,row:N.row}}return S.type==="eggFarm"||S.type==="scanner"||S.type==="maintenanceRoom"?{...S,obj:g,col:g.col,row:g.row}:S.type==="facility"?{...S,obj:g,x:g.x,y:g.y,w:g.w,h:g.h,entry:g.entry?{...g.entry}:null,side:g.side,center:{x:g.x+g.w/2,y:g.y+g.h/2}}:null}function P(S){let g=t(S),N=o(g);if(!N)return!1;let j=se(N),J=j.map(ie).filter(Boolean);return J.length?(e.groupDrag={start:g,selections:j,origins:J,historySnapshot:hn(e),committed:!1,lastDCol:0,lastDRow:0},e.multiSelected=j,e.selected=j[0]||null,n(),!0):!1}function G(){!e.groupDrag||e.groupDrag.committed||(e.undoStack.push(e.groupDrag.historySnapshot),e.redoStack=[],e.groupDrag.committed=!0)}function H(S,g,N){let j=A(S,g),J=ft(e,S,g);if(J&&!N.has(`eggFarm:${J.id}`))return!0;let pe=pt(e,S,g);if(pe&&!N.has(`scanner:${pe.id}`))return!0;let xe=(e.maintenanceRooms||[]).find(Pe=>jt(Pe).some(Ae=>Ae.col===S&&Ae.row===g));return!!(xe&&!N.has(`maintenanceRoom:${xe.id}`)||e.conveyorTiles.has(j)&&!N.has(`conveyor:${j}`))}function be(S,g,N){let j=[];for(let J of e.groupDrag.origins){if(J.type!=="facility")continue;let pe={x:J.center.x+S,y:J.center.y+g},{entry:xe,side:Pe}=Jn(pe);if(!i(xe.col,xe.row)||e.blockedCells?.has?.(A(xe.col,xe.row)))return!0;let Ae={...J.obj,entry:{...xe},side:Pe};jn(Ae,xe,Pe),j.push({id:J.id,rect:l(Ae)})}for(let J of j)for(let pe of Object.values(e.facilities))if(!N.has(`facility:${pe.id}`)&&c(J.rect,l(pe),12))return!0;for(let J=0;J_.type==="conveyor");for(let _ of Ae){let De=_.currentKey||_.oldKey;e.conveyorTiles.delete(De),e.conveyorMeta.delete(De)}for(let _ of Ae){let De=A(_.col+J,_.row+pe);e.conveyorTiles.add(De),e.conveyorMeta.set(De,_.meta||{price:Oe("conveyor"),builtSession:null,uses:0}),_.currentKey=De}for(let _ of e.groupDrag.origins)if(_.type==="eggFarm")_.obj.col=_.col+J,_.obj.row=_.row+pe;else if(_.type==="scanner")_.obj.col=_.col+J,_.obj.row=_.row+pe;else if(_.type==="maintenanceRoom")_.obj.col=_.col+J,_.obj.row=_.row+pe;else if(_.type==="facility"){let De={x:_.center.x+N,y:_.center.y+j},{entry:Ye,side:Ve}=Jn(De);jn(_.obj,Ye,Ve)}e.groupDrag.selections=e.groupDrag.origins.map(_=>_.type==="conveyor"?{type:"conveyor",id:_.currentKey||_.oldKey}:{type:_.type,id:_.id}),e.multiSelected=[...e.groupDrag.selections],e.selected=e.multiSelected[0]||null,me(e),n()}function U(){e.groupDrag&&(me(e),e.groupDrag=null,n())}return{selectionFromHit:C,startSelectionBox:ae,updateSelectionBox:he,finishSelectionBox:re,startGroupDrag:P,updateGroupDrag:F,finishGroupDrag:U}}function Fs({game:e,ui:t,canvas:n,canvasPoint:o,onUpdatePanels:r}){function i(){r&&r()}let l=null,c=!1,b=null,C=!1,T=["random","up","right","down","left"],I={random:"RND",up:"UP",right:"RT",down:"DN",left:"LF"},$={w:40,h:40,y:0};function O(){return An(e)}function ee(){e.gridCols=f.cols,e.gridRows=f.rows,e.gridOwnedCells=Vr(e)}function X(s){if(s){f.y-=s*f.cell,f.rows+=s,e.gridChunkOriginY=(e.gridChunkOriginY||0)-Math.floor(s/10),e.ownedCells=Dn(e.ownedCells,s),e.blockedCells=Dn(e.blockedCells,s),e.conveyorTiles=Dn(e.conveyorTiles,s),e.conveyorMeta=Jr(e.conveyorMeta,s);for(let a of e.eggFarms||[])a.row+=s;for(let a of e.scanners||[])a.row+=s;for(let a of Object.values(e.facilities||{}))a.entry&&(a.entry.row+=s)}}function ae(s){e.ownedCells=e.ownedCells||new Set;for(let a of Qr(s))e.ownedCells.add(A(a.col,a.row))}function he(s){return e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending?null:Tt(e).find(a=>a&&Xr(a,s))||null}function re(s="right"){if(s&&typeof s=="object"&&Number.isFinite(s.chunkX)&&Number.isFinite(s.chunkY))return s;let a=["right","up"].includes(s)?s:"right";return zr(e,a)}function se(s="right"){let a=re(s);if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return{ok:!1,reason:"Cannot expand now."};if(!a)return{ok:!1,reason:"Invalid expansion lot."};let h=a.direction||"right",m=O();if(e.cashf.cols&&(f.cols=E.colStart+E.cols),E.rowStart+E.rows>f.rows&&(f.rows=E.rowStart+E.rows),ae(E),jr(e,E.chunkX,E.chunkY),e.gridExpansionPurchases=(e.gridExpansionPurchases||0)+1,e.gridExpansionPurchasesByDirection[h]=(e.gridExpansionPurchasesByDirection[h]||0)+1,ee();let ne=Wr({seed:`${e.runSeed}:grid-expansion:${E.chunkX},${E.chunkY}:${e.gridExpansionPurchases}`,colStart:E.colStart,colEnd:E.colStart+E.cols,rowStart:E.rowStart,rowEnd:E.rowStart+E.rows,targetRatio:Y.map.blockedRatio});for(let ke of ne)e.blockedCells.add(ke);me(e);let Q=E.cols*E.rows,ue=Et(E);return K(e,ue.x+ue.w/2,ue.y+ue.h/2,`${h.toUpperCase()} +${Q} CELLS -${x(m)}`,y.green),i(),{ok:!0,direction:h,cost:m,addedCells:Q,blocked:ne.size,chunkX:E.chunkX,chunkY:E.chunkY}}function ie(s,a){return s>=0&&s=0&&a!a.has(m.id)&&H(h,G(m),12))}function F(s,a,h=null){if(!ie(s,a))return!1;if(P(s,a))return!0;let m=A(s,a),w=ft(e,s,a);if(w&&!(h?.type==="eggFarm"&&h.ref?.id===w.id))return!0;let E=pt(e,s,a);if(E&&!(h?.type==="scanner"&&h.ref?.id===E.id))return!0;let ne=U(e,s,a);return!!(ne&&!(h?.type==="maintenanceRoom"&&h.ref?.id===ne.id)||e.conveyorTiles.has(m)&&!(h?.type==="conveyor"&&h.oldKey===m))}function U(s,a,h){return(s.maintenanceRooms||[]).find(m=>jt(m).some(w=>w.col===a&&w.row===h))||null}function S(s,a,h=null){let m={col:s,row:a};for(let w of jt(m)){if(!ie(w.col,w.row)||P(w.col,w.row))return!0;let E=A(w.col,w.row);if(ft(e,w.col,w.row)||pt(e,w.col,w.row))return!0;let ue=U(e,w.col,w.row);if(ue&&!(h?.type==="maintenanceRoom"&&h.ref?.id===ue.id)||e.conveyorTiles.has(E))return!0}return!1}function g(s,a,h=null){let m={col:s,row:a};for(let w of Pt(m)){if(!ie(w.col,w.row)||P(w.col,w.row))return!0;let E=A(w.col,w.row);if(ft(e,w.col,w.row))return!0;let Q=pt(e,w.col,w.row);if(Q&&!(h?.type==="scanner"&&h.ref?.id===Q.id)||e.conveyorTiles.has(E))return!0}return!1}function N(){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:e.selected.type==="maintenanceRoom"&&(e.maintenanceRooms||[]).find(s=>s.id===e.selected.id)||null:null}function j(s){return s?s.type==="eggFarm"?`${ut("eggFarm")} #${s.id}`:s.type==="scanner"?`${s.kind==="auto"?ut("autoScanner"):ut("manualScanner")} #${s.id}`:s.type==="conveyor"?e.conveyorMeta.get(s.id)?.kind==="boostConveyor"?ut("boostConveyor"):ut("conveyor"):s.type==="facility"?s.name:s.type==="maintenanceRoom"?`${ut("maintenanceRoom")} #${s.id}`:"Equipment":"Equipment"}function J(s){return s?.type==="conveyor"?e.conveyorMeta?.get(s.oldKey||s.ref?.id)?.price||Nn(s):Nn(s)}function pe(){return!!e.cardEffects?.usedMachineActive}function xe(){return pe()?{usedMachine:!0,noRefund:!0,durabilityBaseMultiplier:.6}:{usedMachine:!1,noRefund:!1,durabilityBaseMultiplier:1}}function Pe(s){let a=xe();return Object.assign(s,a),s}function Ae(s){let a=s?.ref||s||{};if(s?.type==="eggFarm"||a.type==="eggFarm")return e.eggFarms.length<=1?"Cannot sell the last EGG FARM.":"";if((s?.type==="facility"||a.type==="facility")&&["mixer","trash","truck"].includes(a.baseId||a.id)){let h=a.baseId||a.id;if(Object.values(e.facilities).filter(w=>(w.baseId||w.id)===h).length<=1)return`Cannot sell the last ${a.shortName||a.name||a.id}.`}return""}function _(s){t.buildStatus.textContent=s,K(e,n.width/2-e.view.x,86-e.view.y,s.toUpperCase(),y.danger)}function De(s){if(!s)return null;let a=A(s.col,s.row);return e.conveyorMeta.get(a)||null}function Ye(s){return s?(Array.isArray(s.outDirs)||(s.outDirs=[]),s.outDirs=[...new Set(s.outDirs.filter(a=>["right","left","down","up"].includes(a)))],T.includes(s.branchMode)||(s.branchMode="random"),s.kind||(s.kind="conveyor"),s.speedMultiplier||(s.speedMultiplier=s.kind==="boostConveyor"?2:1),s.outDirs):[]}function Ve(s){return s?de.filter(a=>e.conveyorTiles.has(A(s.col+a.dc,s.row+a.dr))).map(a=>a.name):[]}function Te(s){return Ve(s).length>=3}function kt(s,a){let h=de.find(Q=>Q.name===a);if(!s||!h)return!1;let m=A(s.col+h.dc,s.row+h.dr),w=e.conveyorMeta.get(m);if(!w)return!1;let E=h.opposite;return[...new Set([...Array.isArray(w.outDirs)?w.outDirs:[],w.dir].filter(Boolean))].includes(E)}function oo(s){if(!e.conveyorTiles.has(s))return[];let a=te(s),h=e.conveyorMeta.get(s),m=Ye(h),w=Ve(a),E=[...new Set([...m,h?.dir].filter(Boolean))].filter(ue=>w.includes(ue)),ne=w,Q=E.length?E:ne;return h&&(h.outDirs=m.filter(ue=>w.includes(ue)),h.dir&&!w.includes(h.dir)&&(h.dir=h.outDirs[0]||null),h.branchMode!=="random"&&!w.includes(h.branchMode)&&(h.branchMode="random")),Q}function Cn(s){if(!e.conveyorTiles.has(s))return[];let a=te(s),h=Ve(a);return Te(a)||h.length?h:oo(s)}function ro(s){let a=te(s),h=Cn(s);if(h.length<3)return[];let m=e.conveyorMeta.get(s)||{},w=new Set(h.filter(Q=>kt(a,Q))),E=h.filter(Q=>!w.has(Q));if(w.size&&E.length>=2)return E;let ne=[...new Set([...Array.isArray(m.outDirs)?m.outDirs:[],m.dir].filter(Boolean))].filter(Q=>h.includes(Q));return ne.length>=2?ne:h}function nn(s,a){let h=ct(s,a);if(!h)return!1;let m=A(s.col,s.row),w=A(a.col,a.row),E=e.conveyorMeta.get(m),ne=e.conveyorMeta.get(w);if(!E||!ne)return!1;let Q=Ye(E),ue=!Q.includes(h)||E.dir!==h||!ne.dir;return Q.includes(h)||Q.push(h),E.dir=h,ne.dir||(ne.dir=h),ue}function Ct(s){let a=so(s);return a.length<2?io(s):(Be(e),lo(a),me(e),i(),!0)}function io(s){if(!s)return!1;let a=A(s.col,s.row),h=e.conveyorMeta.get(a);if(!h||Te(s))return!1;let m=de.map(ne=>ne.name),w=h.dir&&m.includes(h.dir)?h.dir:null,E=m[(Math.max(-1,m.indexOf(w))+1)%m.length];return Be(e),h.dir=E,h.outDirs=[E],h.branchMode="random",me(e),i(),!0}function Mn(s){return s?de.map(a=>({col:s.col+a.dc,row:s.row+a.dr})).filter(a=>e.conveyorTiles.has(A(a.col,a.row))):[]}function so(s){if(!s||!e.conveyorTiles.has(A(s.col,s.row))||Te(s))return[];let a=Mn(s);if(!a.length||a.length>2)return[];let h=E=>{let ne=[],Q=new Set([A(s.col,s.row)]),ue=s,ke=E,xr=0;for(;ke&&xr<200;){xr+=1;let Tr=A(ke.col,ke.row);if(Q.has(Tr)||(Q.add(Tr),ne.push(ke),Te(ke)))break;let Er=Mn(ke).filter(Rr=>!(Rr.col===ue.col&&Rr.row===ue.row));if(Er.length!==1)break;ue=ke,ke=Er[0]}return ne},m=a[0]?h(a[0]).reverse():[],w=a[1]?h(a[1]):[];return[...m,s,...w]}function Mt(s,a){return!!s&&[...new Set([...Array.isArray(s.outDirs)?s.outDirs:[],s.dir].filter(Boolean))].includes(a)}function lo(s){let a=0,h=0;for(let w=0;wh?[...s].reverse():s;for(let w=0;w=Math.abs(m)?{col:s.col+Math.sign(h),row:s.row}:{col:s.col,row:s.row+Math.sign(m)}}function ao(s){c=!1,b=s?{col:s.col,row:s.row}:null,C=!1,l=null,on(s)}function d(s){if(!s)return;if(!l)return on(s);let a=l,h=0;for(;(a.col!==s.col||a.row!==s.row)&&h<64;){let m=rn(a,s);if(on(m),a=l||m,h+=1,!l)break}}function p(){!C&&b&&e.conveyorTiles.has(A(b.col,b.row))&&Ct(b),b=null,C=!1,l=null,c=!1}function v(s){if(!s)return _(oe.fail.outOfGrid);let{col:a,row:h}=s;if(e.buildTool==="conveyor"||e.buildTool==="boostConveyor"){let m=_t(s,null);if(!m.ok)return _(m.reason||oe.fail.cellOccupied);me(e);return}if(P(a,h))return _("Cannot build on blocked ground.");if(e.buildTool==="maintenanceRoom")return S(a,h)?_(oe.fail.cellOccupied):D(a,h);if(e.buildTool==="manualScanner"||e.buildTool==="autoScanner"?g(a,h):F(a,h))return _(oe.fail.cellOccupied);e.buildTool==="eggFarm"?k(a,h):e.buildTool==="manualScanner"?R(a,h,"manual"):e.buildTool==="autoScanner"&&R(a,h,"auto")}function M(s){let a=He(s.x,s.y);if(["conveyor","boostConveyor","eggFarm","manualScanner","autoScanner","maintenanceRoom"].includes(e.buildTool))return v(a);if(cn.includes(e.buildTool))return le(s,e.buildTool)}function k(s,a){let h=Oe("eggFarm",e);if(e.cashE.kind==="manual").length>=8)return _("Manual Scanner limit reached (8 max).");let m=h==="auto"?Oe("autoScanner",e):Oe("manualScanner",e);if(e.cashw.id!==a.ref.id),et(e,m.x,m.y),me(e)}if(a.type==="scanner"){let m=ye(a.ref);Ne(a,m.x,m.y),e.scanners=e.scanners.filter(w=>w.id!==a.ref.id),et(e,m.x,m.y),me(e)}if(a.type==="facility"){let m=a.ref;Ne(a,m.x+m.w/2,m.y+m.h/2),delete e.facilities[m.id],et(e,m.x+m.w/2,m.y+m.h/2),me(e)}if(a.type==="maintenanceRoom"){let m=a.ref,w=q(m);Ne(a,w.x,w.y),e.maintenanceRooms=(e.maintenanceRooms||[]).filter(E=>E.id!==m.id),et(e,w.x,w.y)}e.selected=null,e.multiSelected=[],i()}function co(s){let a=Object.values(e.facilities).find(Q=>{if(s.x>=Q.x&&s.x<=Q.x+Q.w&&s.y>=Q.y&&s.y<=Q.y+Q.h)return!0;if(!Q.entry)return!1;let ke=B(Q.entry.col,Q.entry.row);return Math.abs(s.x-ke.x)<=f.cell*.46&&Math.abs(s.y-ke.y)<=f.cell*.46});if(a)return{type:"facility",ref:a};let h=He(s.x,s.y);if(!h)return null;let m=ft(e,h.col,h.row);if(m)return{type:"eggFarm",ref:m};let w=pt(e,h.col,h.row);if(w)return{type:"scanner",ref:w};let E=U(e,h.col,h.row);if(E)return{type:"maintenanceRoom",ref:E};let ne=A(h.col,h.row);return e.conveyorTiles.has(ne)?{type:"conveyor",oldKey:ne,ref:{type:"conveyor",id:ne}}:null}let Ut=$s({game:e,canvasPoint:o,updatePanels:i,equipmentAtPoint:co,fail:_,pointInGrid:ie,rectOfFacility:G,rectsOverlap:H});function js(s){return null}function vr(){let s=N();s&&(s.type==="conveyor"?Gt(B(...Object.values(te(s.id)))):s.type==="eggFarm"?Gt(B(s.col,s.row)):s.type==="scanner"?Gt(ye(s)):s.type==="facility"?Gt({x:s.x+s.w/2,y:s.y+s.h/2}):s.type==="maintenanceRoom"&&Gt(q(s)))}function Ke(s,a,h="primary-button"){let m=document.createElement("button");return m.type="button",m.className=h,m.textContent=s,m.addEventListener("click",a),m}function sn(){e.cardTargetPick?.mode==="autoScannerMenu"&&(e.cardTargetPick=null),t.modal.classList.remove("visible","equipment-popover"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function uo(s){t.modalTitle.textContent="Auto Scanner",e.cardTargetPick={pending:!0,mode:"autoScannerMenu",cardId:null,targetKeys:[`scanner:${s.id}`],remaining:1},t.modalBody.innerHTML=` +
+

Left / right output routing for this AUTO scanner.

+

Current: ${s.role===0?"Male left / others right":"Poop left / others right"}

+

Cooldown: ${nt(s).toFixed(1)}s.

+
`,t.modalActions.innerHTML="";let a=Ke("Male Left / Others Right",()=>{Be(e),s.role=0,sn(),i()},s.role===0?"facility-action warn":"facility-action"),h=Ke("Poop Left / Others Right",()=>{Be(e),s.role=1,sn(),i()},s.role===1?"facility-action warn":"facility-action");t.modalActions.append(a,h,Ke("Close",sn,"facility-action")),fo(s),t.modal.classList.add("visible","equipment-popover"),i()}function wr(s){return s?.label||s?.key||"?"}function Zs(s){let a=s.key===" "?"Space":s.key.length===1?s.key.toUpperCase():s.key.replace(/^Arrow/,"");return{key:s.key.toLowerCase(),code:s.code,label:a}}function el(s,a,h){for(let m of e.scanners.filter(w=>w.kind==="manual"))for(let w of["left","right"]){if(m.id===s.id&&w===a)continue;let E=m.keys?.[w];if(E&&(E.code===h.code||E.key===h.key))return!0}return!1}function ln(s,a=""){if(!s||s.kind!=="manual")return;t.modalTitle.textContent=`Manual Scanner #${s.id}`;let h=wr(s.keys?.left),m=wr(s.keys?.right),w=tl(s);t.modalBody.innerHTML=` +
+

Left route key: ${h}

+

Right route key: ${m}

+ ${a?`

${a}

`:""} + ${w?`

${w}

`:""} +
`,t.modalActions.innerHTML="",t.modalActions.appendChild(Ke("Set Left Key",()=>Sr(s,"left"),"facility-action warn")),t.modalActions.appendChild(Ke("Set Right Key",()=>Sr(s,"right"),"facility-action warn")),t.modalActions.appendChild(Ke("Close",sn,"facility-action")),fo(s),t.modal.classList.add("visible","equipment-popover")}function tl(s){let a=[{side:"left",binding:s.keys?.left},{side:"right",binding:s.keys?.right}];if(a[0].binding&&a[1].binding&&(a[0].binding.code===a[1].binding.code||a[0].binding.key===a[1].binding.key))return"Left and right keys conflict.";for(let h of a)if(h.binding)for(let m of e.scanners.filter(w=>w.kind==="manual"&&w.id!==s.id)){if(m.keys?.left&&(m.keys.left.code===h.binding.code||m.keys.left.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} left.`;if(m.keys?.right&&(m.keys.right.code===h.binding.code||m.keys.right.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} right.`}return""}function Sr(s,a){t.modalBody.innerHTML=`

Press a key for ${a.toUpperCase()} route.

Esc cancels.

`,t.modalActions.innerHTML="";let h=m=>{if(m.preventDefault(),m.stopPropagation(),window.removeEventListener("keydown",h,!0),m.key==="Escape")return ln(s);let w=Zs(m),E=el(s,a,w);Be(e),s.keys=s.keys||{left:null,right:null},s.keys[a]=w,i(),ln(s,E?`${w.label} assigned, but another scanner already uses it.`:`${a.toUpperCase()} set to ${w.label}.`)};window.addEventListener("keydown",h,!0)}function nl(){let s=N();if(!(!s||s.type!=="scanner"))return s.kind==="auto"?uo(s):ln(s)}function ol(s){if(!s)return{x:80,y:80};if(s.type==="conveyor"){let a=te(s.id);return B(a.col,a.row)}return s.type==="eggFarm"?B(s.col,s.row):s.type==="scanner"?ye(s):s.type==="facility"?{x:s.x+s.w/2,y:s.y+10}:{x:80,y:80}}function fo(s){let a=n.getBoundingClientRect(),h=ol(s),m=e.view?.scale||1,w=a.left+(h.x*m+(e.view?.x||0))/n.width*a.width+18,E=a.top+(h.y*m+(e.view?.y||0))/n.height*a.height-12,ne=Math.max(12,window.innerWidth-274),Q=Math.max(12,window.innerHeight-220);t.modal.style.setProperty("--popover-x",`${Math.max(12,Math.min(ne,w))}px`),t.modal.style.setProperty("--popover-y",`${Math.max(12,Math.min(Q,E))}px`)}function kr(){let s=N();if(!s)return;let a=gr(s);if(t.modalTitle.textContent=j(s),t.modalBody.innerHTML=` +
${a.map(w=>`

${w}

`).join("")}
+ ${["mixer","truck"].includes(s.baseId||s.id)?'

Income/Fine = ceil(base x 1.10^upgrades)

':""}`,t.modalActions.innerHTML="",s.type==="scanner"&&s.kind==="auto"&&t.modalActions.appendChild(Ke("Auto Menu",()=>uo(s),"facility-action warn")),s.type==="scanner"&&s.kind==="manual"&&t.modalActions.appendChild(Ke("Set Keys",()=>ln(s),"facility-action warn")),s.type==="conveyor"&&po(s.id)){let w=e.conveyorMeta.get(s.id)?.branchMode||"random";t.modalActions.appendChild(Ke(`Branch: ${Cr(w)}`,()=>{yo(s.id),e.selected={type:"conveyor",id:s.id},kr()},"facility-action warn branch-action"))}let h=s.type==="conveyor"?{type:"conveyor",oldKey:s.id,ref:s}:{type:s.type,ref:s},m=Ae(h);if(m){let w=Ke(m,()=>{},"facility-action danger disabled");w.disabled=!0,t.modalActions.appendChild(w)}else{let w=mt(h,e),E=w.sameBuild?`Remove / Refund ${x(w.amount)}`:`Sell ${x(w.amount)}`;t.modalActions.appendChild(Ke(E,()=>{vr(),sn()},"facility-action danger"))}fo(s),t.modal.classList.add("visible","equipment-popover")}function rl(s){e.phase==="build"&&(p(),e.buildTool=e.buildTool===s?null:s,e.selected=null,e.multiSelected=[],e.selectionBox=null,i())}function il(){let s=[];for(let[a,h]of Object.entries(e.facilities))if(s.push({id:`facility:${a}`,price:J({type:"facility",ref:h}),x:h.x,y:h.y,w:h.w,h:h.h}),h.entry){let m=B(h.entry.col,h.entry.row);s.push({id:`facilityPort:${a}`,price:J({type:"facility",ref:h}),x:m.x-18,y:m.y-18,w:36,h:36})}for(let a of e.maintenanceRooms||[]){let h=q(a);s.push({id:`maintenanceRoom:${a.id}`,price:J({type:"maintenanceRoom",ref:a}),x:h.x-f.cell,y:h.y-f.cell,w:f.cell*2,h:f.cell*2})}for(let a of e.eggFarms){let h=B(a.col,a.row);s.push({id:`eggFarm:${a.id}`,price:J({type:"eggFarm",ref:a}),x:h.x-24,y:h.y-24,w:48,h:48})}for(let a of e.scanners){let h=ye(a);s.push({id:`scanner:${a.id}`,price:J({type:"scanner",ref:a}),x:h.x-50,y:h.y-73,w:100,h:146})}for(let a of e.conveyorTiles){let h=te(a),m=B(h.col,h.row),w=e.conveyorMeta.get(a)||{};s.push({id:`conveyor:${a}`,price:w.price||Oe(w.kind==="boostConveyor"?"boostConveyor":"conveyor",e),x:m.x-22,y:m.y-22,w:44,h:44})}return s}function Cr(s){return I[s]||I.random}function Vc(s){return Cn(s)}function po(s){return e.conveyorTiles.has(s)?Te(te(s)):!1}function Mr(s){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return null;for(let a of e.conveyorTiles){if(!po(a))continue;let h=te(a),m=B(h.col,h.row),w=m.x-$.w/2,E=m.y+$.y-$.h/2;if(s.x>=w&&s.x<=w+$.w&&s.y>=E&&s.y<=E+$.h)return a}return null}function sl(s){let a=Mr(s);return a?yo(a):!1}function yo(s){let a=e.conveyorMeta.get(s);if(!a)return!1;let h=ro(s);if(h.length<2)return!1;Be(e);let m=T.includes(a.branchMode)?a.branchMode:"random",w=["random",...de.map(E=>E.name).filter(E=>h.includes(E))];return a.branchMode=w[(Math.max(0,w.indexOf(m))+1)%w.length],me(e),e.selected=null,e.multiSelected=[],i(),!0}function gr(s){Se(e);let a=[],h=s?.type==="facility"?s.baseId||s.id:"";if(s.type==="eggFarm"){let[m,w]=dn(s);a.push(`Price: ${x(J(s))}`);{let E=Ae({type:s.type,ref:s});a.push(E?`Sale: blocked (${E})`:`Sale value: ${x(mt({type:s.type,ref:s},e).amount)}`)}a.push(`Level: ${s.level}/4`),a.push(`Random interval: ${m.toFixed(2)}-${w.toFixed(2)}s`),a.push(`Durability: ${bn(s)}% | Spawn delay x${Yn(s).toFixed(2)}`)}else if(s.type==="scanner")a.push(`Price: ${x(J(s))}`),a.push(`Sale value: ${x(mt({type:s.type,ref:s},e).amount)}`),a.push(`Type: ${s.kind.toUpperCase()} / Standard`),s.kind==="auto"&&a.push(`Role: ${s.role===0?"Male left / Others right":"Poop left / Others right"}`),a.push(`Queue: ${s.queue.length}`),s.kind==="auto"&&a.push(`Cooldown: ${s.cooldown.toFixed(1)}s / ${nt(s,e).toFixed(1)}s`),s.kind==="auto"&&a.push(`Durability: ${bn(s)}% | Delay x${qn(s).toFixed(2)}`),s.kind==="manual"&&a.push("Durability: none | Always normal");else if(s.type==="conveyor"){let m=e.conveyorMeta.get(s.id),w=e.componentLookup?.get(s.id),E=w?e.congestion.get(w):null;a.push(`Price: ${x(J({type:"conveyor",oldKey:s.id,ref:s}))}`),a.push(`Cell: ${s.id}`),a.push(`Type: ${m?.kind==="boostConveyor"?"BOOST BELT":"Normal Belt"} | Speed x${Number(m?.speedMultiplier||1).toFixed(1)}`),a.push(`Congestion: ${E?Math.floor(E.ratio*100):0}%`),a.push(`Durability: ${bn({meta:m})}% | Speed x${Hn({meta:m}).toFixed(2)}`),po(s.id)?(a.push(`Branch mode: ${Cr(m?.branchMode||"random")}`),a.push("Click the Branch button or the large on-belt badge to cycle RANDOM / fixed exit.")):a.push("Branch mode: needs 3+ conveyor connections."),a.push(`Sale value: ${x(mt({type:"conveyor",oldKey:s.id,ref:s},e).amount)}`)}else if(s.type==="maintenanceRoom")a.push(`Price: ${x(J({type:"maintenanceRoom",ref:s}))}`),a.push(`Sale value: ${x(mt({type:"maintenanceRoom",ref:s},e).amount)}`),a.push("Size: 2\xD72 grid cells"),a.push("Dispatch: 1 repairman during each production day");else if(s.type==="facility"){a.push(`Price: ${x(J(s))}`);{let m=Ae({type:s.type,ref:s});a.push(m?`Sale: blocked (${m})`:`Sale value: ${x(mt({type:s.type,ref:s},e).amount)}`)}if(a.push(["mixer","truck","trash"].includes(s.id)?`Level: ${s.level} / no cap`:`Level: ${s.level}`),h==="truck"&&a.push("Durability: none | Always normal"),["mixer","trash"].includes(h)&&a.push(`Durability: ${bn(s)}% | Extra delay ${Zo(e,s).toFixed(2)}s`),h==="mixer"&&(a.push(`Income: ${x(ze(e))} per chick | upgrade x${yt(e,"mixer").toFixed(3)}`),a.push(`Poop fine: -${x(pn(e))}`)),h==="truck"&&(a.push(`Income: ${x(Fe(e))} per target cargo | upgrade x${yt(e,"truck").toFixed(3)}`),a.push(`Poop shipment fine: -${x(yn(e))}`)),h==="trash"){let m=It(e),w=ht(m);a.push(`Bonus cards: ${m}/${Vt()}`),a.push(`Poop income bonus: ${x(w)} per processed poop.`),a.push("With enough upgrades, poop can out-earn male/female routes.")}s.entry&&a.push(`Receiver: edge cell ${s.entry.col},${s.entry.row} (${s.side})`)}return a}function ll(s){if(!s||e.phase!=="build")return"";let a=Ln(e).find(h=>h.type===s.type&&h.id===s.id);return a?a.message||"Not connected to conveyor route":""}function al(s){return s?s.type==="conveyor"&&e.conveyorMeta.get(s.id)?.kind==="boostConveyor"?"Moves chicks twice as fast. Wears down like a normal belt.":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"?"Slower than hands without upgrades.":s.type==="scanner"?"A manual checkpoint. The operator is the algorithm.":s.type==="facility"&&(s.baseId||s.id)==="mixer"?"Male chicks become revenue here. Do not feed it poop.":s.type==="facility"&&(s.baseId||s.id)==="trash"?"Poop goes in. Sometimes coins come out, for reasons best left unaudited.":s.type==="facility"&&(s.baseId||s.id)==="truck"?"The shipping endpoint. Correct cargo pays; wrong cargo complains.":s.type==="maintenanceRoom"?"A cramped 2\xD72 storage and break room with lockers, spare parts, a bench and one dispatched repairman.":"Factory equipment.":""}return{buildAtCell:v,buildAtPoint:M,eraseAtPoint:Gt,equipmentAtPoint:co,startSelectionBox:Ut.startSelectionBox,updateSelectionBox:Ut.updateSelectionBox,finishSelectionBox:Ut.finishSelectionBox,startGroupDrag:Ut.startGroupDrag,updateGroupDrag:Ut.updateGroupDrag,finishGroupDrag:Ut.finishGroupDrag,selectedObject:N,selectedTitle:j,equipmentPrice:J,selectedUpgradeCost:js,selectedInfoLines:gr,flavorText:al,disconnectedWarningFor:ll,gridExpansionCost:O,buyGridExpansion:se,expansionOfferAtPoint:he,beginConveyorDrag:ao,continueConveyorDrag:d,endConveyorDrag:p,cycleSingleConveyorDirection:Ct,branchSwitcherAtPoint:Mr,cycleBranchModeAtPoint:sl,cycleBranchModeForKey:yo,removeSelected:vr,switchScannerRole:nl,showManualScannerMenu:ln,showAutoScannerMenu:uo,showSelectedMenu:kr,setBuildTool:rl,fail:_,isEquipmentCell:F,equipmentHitBoxes:il,routeFromFarmToScanner:Dt}}function Bs({game:e,ui:t,build:n,startGame:o,beginCardDraft:r,activeQueuedChick:i}){function l(F){return String(F).replace(/[&<>"']/g,U=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[U])}function c(){return Math.round(Xn(e))}function b(){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return!1;let F=!1;for(let U of So)if(F=!0,e.cash>=Oe(U,e))return!1;return F}function C(){T(),I(),ee(),O(),$()}function T(){for(let[U,S]of Object.entries(t.buttons))S?.classList?.contains("tool-button")&&S.classList.toggle("active",e.buildTool===U);for(let U of So){let S=t.buttons[U];if(!S)continue;let g=Oe(U,e),N=S.querySelector("span");N&&(N.textContent=U==="conveyor"||U==="boostConveyor"?`${x(g)} / tile`:x(g));let j=U==="manualScanner"&&e.scanners.filter(pe=>pe.kind==="manual").length>=8,J=e.cashDt(e,j)?.scannerId).length,U=fn(e),S=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),g=Math.max(1,Number(e.turn)||1),N=_n(e,g,S);t.turnSummary.innerHTML=[`Seed: ${l(e.runSeed||"none")} | Grid box: ${e.gridRows||10}x${e.gridCols||20} | Owned: ${e.gridOwnedCells||e.ownedCells?.size||(e.gridRows||10)*(e.gridCols||20)} cells | Blocked: ${e.blockedCells?.size||0} cells`,`Truck target: ${je(e).toUpperCase()} | Male fine: -${x(Uo(e))}`,`Poop fine: Mixer -${x(pn(e))} / Shipment -${x(yn(e))}`,`Fairies tribute on Next Day: -${x(N.amount)} | base ${x(N.base)} + profit share ${x(N.profitTribute)} | basis net ${x(S)} | exemption ${x(N.profitExemption)}${N.reduction?` | reduction -${x(N.reduction)}`:""}`,`Maintenance: worst ${or(e).worst.percent}% dirty (${or(e).worst.label}) | Repair rooms: ${(e.maintenanceRooms||[]).length} | Repairmen: ${(e.repairmen||[]).length}`,`Manual combo: ${e.manualCombo?.count||0} | Card draft: ${e.cardDraft?.pending?Math.max(1,e.cardDraft.picksRemaining||1)+" pick(s) left":"ready after each day"} | Belt: ${c()}px/s | Farms with scanner route: ${F}/${e.eggFarms.length}`,e.cardEffects?.usedMachineActive?'Procurement: USED MACHINE MODE / no refunds / 60% durability':"",U.length?`Blocked: ${U[0]}`:`${oe.status.allPortsConnected}`].join("
")}function ee(){if(!t.eventPanel)return;let F=e.eventOffer;if(e.phase!=="build"){t.eventPanel.innerHTML=oe.status.eventPanelRunning;return}if(!F){t.eventPanel.className="event-card empty",e.turn+1Event lock active.No irregular events during Days 1-7. First possible forced event: Day ${xt}.`:t.eventPanel.innerHTML="No event.Random forced events can appear later.";return}t.eventPanel.className="event-card accepted",t.eventPanel.innerHTML=` +
FORCED NEXT DAY
+

${F.title}

+
+ Effect: ${F.route} + ${F.targetAmount?`Target: ${F.targetAmount}`:"Target: none"} + ${F.reward?`Reward: ${x(F.reward)}`:"Reward: none"} + Time ${F.daySeconds||60}s / Output x${Number(F.productionMultiplier||1).toFixed(2)} / Poop +${Math.round((F.poopRateAdd||0)*100)}pt +
`}function X(){T(),t.shell.classList.toggle("phase-running",e.phase==="running"),t.shell.classList.toggle("phase-build",e.phase==="build"),t.shell.classList.toggle("phase-gameover",e.phase==="gameover"),t.shell.classList.toggle("phase-title",e.phase==="title"),t.shell.classList.toggle("phase-loanDecision",e.phase==="loanDecision"),t.money.textContent=x(e.cash),t.money.classList.toggle("cash-negative",e.cash<0),t.money.classList.toggle("cash-positive",e.cash>an),t.turn.textContent=e.turn,t.timeLeft.textContent=e.phase==="running"&&e.timeLeft<=0&&e.shutdownTimeLeft>0?`+${e.shutdownTimeLeft.toFixed(1)}s`:`${Math.max(0,e.timeLeft).toFixed(1)}s`,t.timeLeft.closest?.(".hud-card")?.classList.toggle("time-critical",e.phase==="running"&&(e.timeLeft<=10||e.timeLeft<=0&&e.shutdownTimeLeft>0)),t.phase.textContent=he(),t.comboCount&&(t.comboCount.textContent=e.manualCombo?.count||0),ae(),t.turnProfit.textContent=x(e.stats.profit),t.turnProfit.classList.toggle("cash-negative",e.stats.profit<0),t.turnProfit.classList.toggle("cash-positive",e.stats.profit>0),t.mixerCount.textContent=e.stats.mixerCount,t.truckFemaleCount.textContent=e.stats.truckFemale,t.truckMaleCount.textContent=e.stats.truckMale,t.poopCount.textContent=e.stats.poopSpawned,t.buttons.s1Left.disabled=e.phase!=="running"||!i(0),t.buttons.s1Right.disabled=e.phase!=="running"||!i(0),t.buttons.s2Left.disabled=e.phase!=="running"||!i(1),t.buttons.s2Right.disabled=e.phase!=="running"||!i(1);let F=e.scanners.find(N=>N.kind==="manual"&&N.slot===0),U=e.scanners.find(N=>N.kind==="manual"&&N.slot===1);F&&(t.buttons.s1Left.textContent=`S1 ${F.keys?.left?.label||"A"} -> Mixer`,t.buttons.s1Right.textContent=`S1 ${F.keys?.right?.label||"D"} -> S2`),U&&(t.buttons.s2Left.textContent=`S2 ${U.keys?.left?.label||"Left"} -> Waste`,t.buttons.s2Right.textContent=`S2 ${U.keys?.right?.label||"Right"} -> Truck`);let S=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),g=_n(e,Math.max(1,Number(e.turn)||1),S).amount;t.buttons.nextTurn.textContent=e.phase==="build"&&g>0?`Next Day - Fairies ${x(g)}`:oe.actions.nextDay,t.buttons.nextTurn.disabled=e.phase!=="build"||!!e.cardDraft?.pending||!!e.cardTargetPick?.pending||!yi(e)}function ae(){if(!t.eventBrief||!t.targetBrief||!t.speedBrief)return;let F=je(e).toUpperCase();t.targetBrief.textContent=`TRUCK TARGET: ${F}`,t.speedBrief.textContent=`BELT SPEED: ${c()} px/s`,t.speedBrief.title=`Conveyor speed does not increase by day. Degraded belts reduce speed. Cap: ${Wt}px/s.`;let U=e.eventActive,S=e.eventOffer;U?(t.eventBrief.textContent=`ACTIVE EVENT: ${U.title} | ${U.route}`,t.eventBrief.className="event-brief active"):e.phase==="build"&&S?(t.eventBrief.textContent=`NEXT DAY EVENT: ${S.title} | ${S.route}${S.targetAmount?` | Target ${S.targetAmount}`:""}${S.reward?` | Reward ${x(S.reward)}`:""}`,t.eventBrief.className="event-brief next"):e.phase==="build"&&e.turn+1
\u2642Male->MixerS1: A
\u2640Female->TruckS1: D, then S2: right
\u{1F4A9}Poop->ShredderS1: D, then S2: left

Build phase: connect at least one EGG through a scanner to Mixer, Shredder, or Truck before Next Day. One day is one run.

',t.modalActions.innerHTML="",t.modalActions.appendChild(G(oe.actions.startGame,o,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function se(F){let U=j=>`${j>0?"+":""}${x(j)}`,S=j=>`${j>0?"-":""}${x(j)}`,g=F.profit>=0?"cash-positive":"cash-negative",N=(F.mixerPoopFine||0)+(F.truckPoopFine||0)+(F.maleTruckFine||0)+(F.explosionDamage||0)+(F.cardRerollCost||0);t.modalTitle.textContent=`Day ${F.turn} Settlement`,t.modalBody.innerHTML=` +
Net result${x(F.profit)}
+
+
Chick shipment income${U(F.chickShipmentIncome||0)}
+
Poop shipment income${U(F.poopShipmentIncome||0)}
+
Mixer income${U(F.mixerRevenue||0)}
+
Composter income${U(F.composterIncome||0)}
+
DUD refund income${U(F.dudRefundIncome||0)}
+
Manual combo bonus${U(F.manualComboBonus||0)}
+
Chemical subsidy${U(F.chemicalWeaponSubsidy||0)}
+
Event bonus${U(F.eventBonus||0)}
+
Penalties${S(N)}
+
Fairies fee${S(F.fairiesTribute?.amount||F.fairiesTribute||0)}
+
+

Income ${x(F.revenue)} - losses ${x(F.penalty)} = ${x(F.profit)}

`,t.modalActions.innerHTML="",t.modalActions.appendChild(G("Choose Upgrade Card",r||H,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function ie(F,U){let S=Math.max(0,e.cardEffects?.rescueLoanCharges||0);t.modalTitle.textContent="Emergency Loan Available",t.modalBody.innerHTML=` +

End-of-day cash is below ${x(0)}.

+
+
Current money${x(e.cash)}
+
Emergency Loan+${x(500)}
+
Cards remaining${S}
+
+

Use one Emergency Loan to gain ${x(500)} immediately. If cash is still negative, another decision will be shown if another card remains.

`,t.modalActions.innerHTML="",t.modalActions.appendChild(G("Accept Game Over",U,"facility-action danger")),t.modalActions.appendChild(G("Use Emergency Loan",F,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function P(){let F=e.totals.processed,U=F?Math.round(e.totals.correct/F*100):0,S=_i(e);t.modalTitle.textContent=oe.phases.gameover,t.modalBody.innerHTML=`

Your cash went negative.

+
Final Score${S.score}
Survival${e.totals.turnsCompleted} days
Final Cash${x(e.cash)}
Accuracy${U}%
+
Score breakdown +
Formula
Base = Cash + Total revenue + Factory value \xD70.5 + Event bonus \xD70.5 = ${x(S.base)}
Daily earned = ceil(Base \xF7 Days) = ${x(S.dailyEarned)}
Score = max(0, floor(Base + Daily earned + Correct bonus - Total outflow - Day penalty)) = ${S.score}
+
Factory Value${x(S.factoryValue)}
Total Revenue${x(e.totals.revenue)}
Daily Earned${x(S.dailyEarned)} / day
Total Outflow${x(e.totals.penalty)}
Fairies Tribute${x(e.totals.fairiesTribute||0)}
Correct Sorts${e.totals.correct}
Auto Sorted${e.totals.autoSorted}
Poop Control${e.totals.poopTrash} trashed / ${e.totals.poopTruck} shipped / ${e.totals.poopMixer} mixer
Explosion Penalty${x(e.totals.explosionDamage)}
Event Bonus${x(e.totals.eventBonus)}
Day Penalty-${S.dayPenalty}
Events${e.totals.eventSuccess} success / ${e.totals.eventFailed} failed
+
`,t.modalActions.innerHTML="",t.modalActions.appendChild(G(oe.actions.restart||"Restart",o,"primary-button restart-button")),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible","gameover-modal")}function G(F,U,S="primary-button"){let g=document.createElement("button");return g.type="button",g.className=S,g.textContent=F,g.addEventListener("click",U),g}function H(){t.modal.classList.remove("visible","equipment-popover","gameover-modal"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function be(){}return{updatePanels:C,updateUI:X,showTitle:re,showTurnResult:se,showEmergencyLoanDecision:ie,showGameOver:P,hideModal:H,checkGameOver:be}}function br(e){e.totals.processed+=1}function Zt(e){e.stats.correct+=1,e.totals.correct+=1}function vt(e){e.stats.mistakes+=1,e.totals.mistakes+=1}function Ls(e){e.stats.autoSorted+=1,e.totals.autoSorted+=1}function Os(e){e.stats.poopSpawned+=1}function Ns(e){e.stats.mixerCount+=1,br(e)}function _s(e){e.stats.trashCount+=1,br(e)}function Gs(e,t){t==="female"?e.stats.truckFemale+=1:t==="male"&&(e.stats.truckMale+=1),br(e)}function Zn(e,t){let n=t==="truck"?"poopTruck":t==="trash"?"poopTrash":t==="mixer"?"poopMixer":null;n&&(e.stats[n]+=1,e.totals[n]+=1)}function Us({game:e,currentConveyorSpeed:t,onGameOverCheck:n}){function o(d){return Rt(d)*Yn(d)*fs(e)/ki(e)}function r(d){let p=B(d.col,d.row),v=1+ps(e,d),M=l(d,v);if(!M.length)return i(d,p),!0;let k=0,R=0;for(let D of M){let q=B(D.col,D.row),le=c(q);if(le){le.stoppedTimer=.85,R+=1;continue}let Ne=Is(e,{stage:"belt",scannerId:null,route:[q]});Ne.sex==="poop"&&Os(e),e.chicks.push(Ne),Ji(e,d),k+=1}return k>0?(Ui(e,p.x,p.y),k>1&&K(e,p.x,p.y-28,`x${k}`,y.green),!0):R===0}function i(d,p){(d.noRouteNoticeCooldown||0)<=0&&(K(e,p.x,p.y-24,"NO BELT: PAUSED",y.warn),d.noRouteNoticeCooldown=2.5)}function l(d,p){let M=de.map(k=>({col:d.col+k.dc,row:d.row+k.dr})).filter(k=>Ee(k.col,k.row)&&e.conveyorTiles.has(A(k.col,k.row))).map(k=>({p:k,blocked:$(null,B(k.col,k.row))?1:0,roll:Math.random()}));return M.sort((k,R)=>k.blocked-R.blocked||k.roll-R.roll),M.slice(0,Math.max(1,p||1)).map(k=>k.p)}function c(d){return e.chicks.find(p=>p.stage!=="flying"&&Math.hypot(p.x-d.x,p.y-d.y)0;if(e.timeLeft=Math.max(0,e.timeLeft-d),M&&e.timeLeft<=0&&p(),e.timeLeft<=0){e.shutdownTimeLeft>0&&(e.shutdownTimeLeft=Math.max(0,e.shutdownTimeLeft-d));for(let k of e.eggFarms)k.shutterProgress=Math.min(1,(k.shutterProgress||0)+d*2.8)}if(M&&e.timeLeft>0){for(let k of e.eggFarms)if(k.noRouteNoticeCooldown>0&&(k.noRouteNoticeCooldown=Math.max(0,k.noRouteNoticeCooldown-d)),k.nextSpawn-=d,k.nextSpawn<=0){let R=r(k);k.nextSpawn=R?o(k):.15,k.lastInterval=k.nextSpawn}}for(let k=e.chicks.length-1;k>=0;k-=1){let R=e.chicks[k];R.bob+=d*7,R.stoppedTimer>0&&(R.stoppedTimer=Math.max(0,R.stoppedTimer-d)),R.stage!=="queued"&&T(R,k,d)}_(d),_t(),on(),e.timeLeft<=0&&(e.chicks.length===0?v():e.shutdownTimeLeft<=0&&C())}function C(){if(e.cleanupBlown)return;e.cleanupBlown=!0,e.cleanupTimer=1;let d=[...e.chicks];for(let p of d)qo(e,p.sex,p.x,p.y,-Math.PI/2,!0);e.chicks=[];for(let p of e.scanners)p.queue=[];if(_t(),d.length){let p=d.reduce((M,k)=>M+k.x,0)/d.length,v=d.reduce((M,k)=>M+k.y,0)/d.length;Xe(e,p,v,y.warn,58),K(e,p,v-24,"CLEANUP",y.warn)}}function T(d,p,v){if(I(d)){d.stoppedTimer=.35;return}if(pe(d,v),!(d.route&&d.targetIndex=d.route.length)return!1;let p=d.route[d.targetIndex];return $(d,p)}function $(d,p){if(!p)return!1;for(let v of e.chicks)if(!(d&&v.id===d.id)&&v.stage!=="flying"&&Math.hypot(v.x-p.x,v.y-p.y)1)&&d.push({x:p.x,y:p.y})}function ee(d){let p=e.conveyorMeta?.get?.(d)||{},v=[];Array.isArray(p.outDirs)&&v.push(...p.outDirs),p.dir&&v.push(p.dir);let M=[...new Set(v)].filter(le=>de.some(Ne=>Ne.name===le)),k=te(d),R=de.filter(le=>P(k,le.name)).map(le=>le.name),D=M.filter(le=>R.includes(le)),q=R;return D.length?D:q}function X(d){return de.find(p=>p.name===d)||null}function ae(d,p){return e.scanners.find(v=>v.col<=d&&d<=v.col+1&&v.row-1<=p&&p<=v.row+1)||null}function he(d,p){let v=X(p);if(!v)return null;let M=ae(d.col+v.dc,d.row+v.dr);if(!M)return null;let k=Re(M,"inputA");return k&&k.col===d.col&&k.row===d.row?M:null}function re(d){return Object.entries(e.facilities||{}).find(([,p])=>p?.entry&&p.entry.col===d.col&&p.entry.row===d.row)||null}function se(d){return d?.baseId||d?.id||""}function ie(d,p){return d.side==="left"&&p==="left"||d.side==="right"&&p==="right"||d.side==="top"&&p==="up"||d.side==="bottom"&&p==="down"}function P(d,p){let v=X(p);if(!v)return null;let M={col:d.col+v.dc,row:d.row+v.dr};if(Ee(M.col,M.row)&&e.conveyorTiles.has(A(M.col,M.row)))return{type:"conveyor",dirName:p,target:B(M.col,M.row),nextCell:M};let k=he(d,p);if(k)return{type:"scanner",dirName:p,target:ye(k),scanner:k};let R=re(d);return R&&ie(R[1],p)?{type:"facility",dirName:p,facilityId:R[0],facility:R[1],target:B(d.col,d.row)}:null}function G(d,p){let v=X(p);if(!v)return!1;let M=e.conveyorMeta?.get?.(A(d.col+v.dc,d.row+v.dr));return M?[...new Set([...Array.isArray(M.outDirs)?M.outDirs:[],M.dir].filter(Boolean))].includes(v.opposite):!1}function H(d){return de.filter(p=>Ee(d.col+p.dc,d.row+p.dr)&&e.conveyorTiles.has(A(d.col+p.dc,d.row+p.dr))).map(p=>p.name)}function be(d,p,v="random"){let M=H(d);if(M.length<3)return p;let k=new Set(M.filter(q=>G(d,q))),R=M.filter(q=>!k.has(q)),D=k.size&&R.length>=2?R:[...new Set(p.filter(q=>M.includes(q)))];return D.length<2&&(D=M),v&&v!=="random"&&v!=="pass"&&D.includes(v)?[v]:D}function F(d,p){return p&&(p.type==="facility"||!$(d,p.target))}function U(d,p,v,M="random"){let k=v.map(le=>P(p,le)).filter(Boolean);if(!k.length)return null;let D=k.filter(le=>le.type!=="facility").filter(le=>!$(d,le.target)),q=D.length?D:k.filter(le=>le.type==="facility");return q.length?q[Math.floor(Math.random()*q.length)]:null}function S(d,p){let v=[];O(v,{x:d.x,y:d.y}),O(v,p),d.route=v.length?v:[{x:d.x,y:d.y}],d.targetIndex=d.route.length>1?1:d.route.length}function g(d,p){let v=He(d.x,d.y);if(!v)return Mt(p,"OFF GRID");let M=A(v.col,v.row);if(!e.conveyorTiles.has(M))return Mt(p,"OFF BELT");let k=e.conveyorMeta?.get(M)||{},R=be(v,ee(M),k.branchMode||"random");if(!R.length){d.stoppedTimer=.25;return}let D=U(d,v,R,k.branchMode||"random");if(!D){d.stoppedTimer=.25;return}if(D.type==="facility"){let q=se(D.facility);q==="mixer"?io(p,D.facility):q==="truck"?Mn(p,D.facility):q==="trash"?so(p,D.facility):Mt(p,"DONE");return}D.type==="scanner"&&(d.pendingScannerId=D.scanner.id),d.prevConveyorCell=M,S(d,D.target)}function N(d){let p=He(d.x,d.y);if(!p)return null;let v=A(p.col,p.row);return e.conveyorTiles.has(v)?v:null}function j(d){let p=N(d)||N(d.route?.[d.targetIndex]||d);return t(p)}function J(d,p){let v=N(p);!v||d.lastWearKey===v||(d.lastWearKey=v,Qi(e,v))}function pe(d,p){let v=j(d)*p;for(;v>0&&d.targetIndex=D?(d.x=M.x,d.y=M.y,J(d,M),d.targetIndex+=1,v-=D):(d.x+=k/D*v,d.y+=R/D*v,v=0)}}function xe(d,p,v){d.stage="queued",d.route=null,d.queueRoute=v?v.map(M=>({x:M.x,y:M.y})):[ye(p)],d.scannerId=p.id,p.queue.includes(d.id)||p.queue.push(d.id),Pe(p)}function Pe(d){d.queue=d.queue.filter(v=>e.chicks.some(M=>M.id===v&&M.stage==="queued"));let p=f.cell*.86*ys(e);d.queue.forEach((v,M)=>{let k=e.chicks.find(R=>R.id===v);k&&(Ae(k,k.queueRoute||[ye(d)],M*p),k.queueIndex=M)})}function Ae(d,p,v){if(!p||!p.length)return;if(p.length===1||v<=0){let R=p[p.length-1];d.x=R.x,d.y=R.y;return}let M=v;for(let R=p.length-1;R>0;R-=1){let D=p[R-1],q=p[R],le=Math.hypot(q.x-D.x,q.y-D.y);if(M<=le){let Ne=1-M/le;d.x=D.x+(q.x-D.x)*Ne,d.y=D.y+(q.y-D.y)*Ne;return}M-=le}let k=p[0];d.x=k.x,d.y=k.y}function _(d){for(let p of e.scanners){if(p.cooldown>0&&(p.cooldown=Math.max(0,p.cooldown-d)),p.keyPressTime>0&&(p.keyPressTime=Math.max(0,p.keyPressTime-d)),Pe(p),p.kind!=="auto"||p.cooldown>0||!p.queue.length)continue;let v=p.queue[0],M=e.chicks.findIndex(k=>k.id===v);if(M<0){p.queue.shift();continue}nn(M,Io(p,e.chicks[M]),!0)&&(ji(e,p),p.cooldown=nt(p,e),Ls(e))}}function De(d){let p=Ro(e,d);return!p||!p.queue.length?null:e.chicks.find(v=>v.id===p.queue[0])||null}function Ye(d,p){if(e.phase!=="running")return;let v=Ro(e,d);Ve(v,p)}function Ve(d,p){if(e.phase!=="running"||!d||d.kind!=="manual"||(d.keyPressTime=.18,d.keyPressSide=p,!d.queue.length))return;let v=e.chicks.findIndex(M=>M.id===d.queue[0]);v>=0&&nn(v,p,!1)}function Te(d,p,v){return d.kind==="manual"&&Io(d,p)===v}function kt(d){let p=e.manualCombo?.count||0;if(e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=0,e.manualCombo.lastBonus=0,e.stats.manualComboFailure=(e.stats.manualComboFailure||0)+1,e.totals.manualComboFailure=(e.totals.manualComboFailure||0)+1,p>=10){let v=ye(d);Ft(e,10,.25),K(e,v.x,v.y-36,"COMBO RESET",y.danger)}}function oo(d){e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=Math.max(0,e.manualCombo.count||0)+1,e.stats.manualComboSuccess=(e.stats.manualComboSuccess||0)+1,e.totals.manualComboSuccess=(e.totals.manualComboSuccess||0)+1;let p=e.manualCombo.count;if(e.manualCombo.lastBonus=0,p<10)return 0;let v=Math.max(1,Math.floor(p/10)),M=e.scanners.filter(q=>q.kind==="manual").length,k=Math.min(1,(20+M*10)/100),R=0;for(let q=0;q0){Ge(e,D),e.stats.manualComboBonus=(e.stats.manualComboBonus||0)+D,e.totals.manualComboBonus=(e.totals.manualComboBonus||0)+D,e.manualCombo.lastBonus=D;let q=ye(d);K(e,q.x,q.y-42,`COMBO +${x(D)}`,y.green)}return D}function Cn(d,p){let v=Re(d,p);if(!v)return null;let M=A(v.col,v.row);if(e.conveyorTiles.has(M))return{...v};let R=(_e(e).scannerPorts.get(d.id)?.[p]?.keys||[]).filter(Boolean);if(!R.length)return null;let D=R.map(te);return D.find(le=>le.col===v.col&&le.row===v.row)||D[0]||null}function ro(d,p,v,M){let k=[];O(k,{x:d.x,y:d.y});let R=Re(p,v);return R&&O(k,B(R.col,R.row)),O(k,B(M.col,M.row)),k}function nn(d,p,v){let M=e.chicks[d];if(!M||M.stage!=="queued")return!1;let k=At(e,M.scannerId);if(!k)return!1;let R=Cn(k,p);if(!R)return!v&&k.kind==="manual"&&kt(k),K(e,M.x,M.y-16,p==="left"?"NO LEFT BELT":"NO RIGHT BELT",y.danger),!1;!v&&k.kind==="manual"&&(Te(k,M,p)?oo(k):kt(k)),k.queue=k.queue.filter(q=>q!==M.id),M.stage="belt",M.route=ro(M,k,p,R),M.targetIndex=M.route.length>1?1:M.route.length,M.scannerId=null,M.nextScannerId=null,M.pendingScannerId=null,M.queueRoute=null,M.queueIndex=-1;let D=v?y.green:p==="left"?y.mixerBlue:y.truckPink;return Wi(e,ye(k).x,ye(k).y,D),K(e,M.x,M.y-20,v?"AUTO":p.toUpperCase(),D),!0}function Ct(d){let p=e.chicks[d];return p?(e.chicks.splice(d,1),p):null}function io(d,p=e.facilities.mixer){if(p?.processingCooldown>0){let D=e.chicks[d];D&&(D.stoppedTimer=.25);return}let v=Ct(d);if(!v)return;let{x:M,y:k}=v;if(Ns(e),er(e,p),tr(e,p),v.sex==="poop"){let D=Ii(e);Zn(e,"mixer"),vt(e),Hi(e,M,k),K(e,M,k-18,`-${x(D)}`,y.danger);return}let R=Di(e);v.sex==="male"?Zt(e):vt(e),Ki(e,M,k),K(e,M,k-18,`+${x(R)}`,y.green)}function Mn(d,p=e.facilities.truck){let v=Ct(d);if(!v)return;let{x:M,y:k}=v;lo(v.sex,p),Yi(e,M,k,v.sex),Gs(e,v.sex);let R=je(e),D=Mi(e,v.sex);if(v.sex==="poop"){if(Zn(e,"truck"),D)Zt(e),K(e,M,k-18,`+${x(Fe(e))}`,y.green);else{let q=$i(e);vt(e),K(e,M,k-18,`-${x(q)}`,y.danger)}return}if(v.sex==="female"){D?(Zt(e),K(e,M,k-18,`+${x(Fe(e))}`,y.green)):(vt(e),K(e,M,k-18,R==="male"?"REJECT":"NO SALE",y.warn));return}if(D){Zt(e),K(e,M,k-18,`+${x(Fe(e))}`,y.green);return}if(gi(e)){let q=Fi(e);vt(e),K(e,M,k-18,`-${x(q)}`,y.danger)}else vt(e),K(e,M,k-18,"REJECT",y.warn)}function so(d,p=e.facilities.trash){if(p?.processingCooldown>0){let q=e.chicks[d];q&&(q.stoppedTimer=.25);return}let v=Ct(d);if(!v)return;let{x:M,y:k}=v;qi(e,M,k,v.sex),_s(e),er(e,p),tr(e,p);let R={amount:0},D="";if(v.sex==="poop"){R=Ri(e),D=R.amount>0?` +${x(R.amount)}`:"",Zn(e,"trash"),Zt(e);let q=Math.ceil(Math.max(0,Number(e.cardEffects?.composter)||0)*3*On(e));if(q>0){let le=Ge(e,q);e.stats.composterIncome=(e.stats.composterIncome||0)+le,e.totals.composterIncome=(e.totals.composterIncome||0)+le,K(e,M,k-36,`COMPOST +${x(le)}`,y.green)}K(e,M,k-18,`CLEAN${D}`,R.amount>0?y.green:y.green)}else vt(e),K(e,M,k-18,R.amount>0?`WASTE${D}`:"WASTE",R.amount>0?y.green:y.ink)}function Mt(d,p){let v=Ct(d);v&&K(e,v.x,v.y-12,p,y.muted)}function lo(d,p=e.facilities.truck){let v=p||e.facilities.truck;v&&(e.truckCargo.push({sex:d,x:W(22,v.w-22),y:W(66,v.h-24)}),e.truckCargo.length>45&&e.truckCargo.shift())}function gn(d){let p=He(d.x,d.y);if(p){let R=A(p.col,p.row);if(e.conveyorTiles.has(R))return R}let v=ui(e,d.x,d.y);if(!v)return null;let M=te(v),k=B(M.col,M.row);return Math.hypot(d.x-k.x,d.y-k.y)<=f.cell*.55?v:null}function _t(){let{components:d,cellToComponent:p}=ci(e);for(let v of e.chicks){if(v.stage==="flying")continue;let M=gn(v);if(!M)continue;let k=p.get(M),R=d.get(k);R&&(R.count+=1)}for(let v of d.values())v.ratio=v.count/v.capacity;e.congestion=d,e.componentLookup=p}function on(){for(let d of e.congestion.values()){let p=_o(e),v=xi(e);if(d.ratio>v&&d.ratio=p){let M=rn(d.id);if(!M.length||M.some(D=>D.stage!=="queued"&&D.stoppedTimer<=.2))continue;let k=e.lastExplodedComponent.get(d.id)||0,R=performance.now();R-k>900&&(e.lastExplodedComponent.set(d.id,R),ao(d))}}}function rn(d){return e.chicks.filter(p=>{let v=gn(p);return v&&e.componentLookup?.get(v)===d})}function ao(d){let p=rn(d.id);if(!p.length)return;for(let k of p)qo(e,k.sex,k.x,k.y);e.chicks=e.chicks.filter(k=>!p.some(R=>R.id===k.id));for(let k of e.scanners)k.queue=k.queue.filter(R=>e.chicks.some(D=>D.id===R));for(let k of d.cells){let R=te(k),D=B(R.col,R.row);Xe(e,D.x,D.y,y.danger),Ze(e,D.x,D.y,6),Gn(e,D.x,D.y,4)}Ft(e,18,.75);let v=te(d.cells[0]),M=B(v.col,v.row);e.stats.explosions=(e.stats.explosions||0)+1,e.totals.explosions=(e.totals.explosions||0)+1,K(e,M.x,M.y-22,`${Math.round(_o(e)*100)}% JAM EXPLOSION`,y.danger)}return{activeQueuedChick:De,currentSpawnDelay:o,sortSlot:Ye,updateCongestion:_t,sortScanner:Ve,updateRunning:b}}var fe=document.getElementById("gameCanvas"),kc=fe.getContext("2d"),L={shell:document.getElementById("gameShell"),money:document.getElementById("money"),turn:document.getElementById("turn"),timeLeft:document.getElementById("timeLeft"),phase:document.getElementById("phaseLabel"),comboCount:document.getElementById("comboCount"),eventBrief:document.getElementById("eventBrief"),targetBrief:document.getElementById("targetBrief"),speedBrief:document.getElementById("speedBrief"),turnProfit:document.getElementById("turnProfit"),mixerCount:document.getElementById("mixerCount"),truckFemaleCount:document.getElementById("truckFemaleCount"),truckMaleCount:document.getElementById("truckMaleCount"),poopCount:document.getElementById("poopCount"),buildStatus:document.getElementById("buildStatus"),turnSummary:document.getElementById("turnSummary"),eventPanel:document.getElementById("eventPanel"),modal:document.getElementById("modal"),modalTitle:document.getElementById("modalTitle"),modalBody:document.getElementById("modalBody"),modalActions:document.getElementById("modalActions"),hoverTooltip:document.getElementById("hoverTooltip"),manualScannerMonitor:document.getElementById("manualScannerMonitor"),debug:{panel:document.getElementById("debugPanel"),infiniteCash:document.getElementById("debugInfiniteCash"),dayInput:document.getElementById("debugDayInput"),setDay:document.getElementById("debugSetDayButton"),zeroTimer:document.getElementById("debugZeroTimerButton"),cardSelect:document.getElementById("debugCardSelect"),targetSelect:document.getElementById("debugTargetSelect"),grantCard:document.getElementById("debugGrantCardButton"),grantAllCards:document.getElementById("debugGrantAllCardsButton"),readout:document.getElementById("debugReadout")},buttons:{s1Left:document.getElementById("scanner1MixerButton"),s1Right:document.getElementById("scanner1TruckButton"),s2Left:document.getElementById("scanner2MixerButton"),s2Right:document.getElementById("scanner2TruckButton"),nextTurn:document.getElementById("nextTurnButton"),conveyor:document.getElementById("buildConveyorButton"),boostConveyor:document.getElementById("buildBoostConveyorButton"),eggFarm:document.getElementById("buildEggFarmButton"),autoScanner:document.getElementById("buildAutoScannerButton"),manualScanner:document.getElementById("buildManualScannerButton"),mixer:document.getElementById("buildMixerButton"),trash:document.getElementById("buildTrashButton"),truck:document.getElementById("buildTruckButton"),maintenanceRoom:document.getElementById("buildMaintenanceRoomButton"),erase:document.getElementById("eraseButton"),undo:document.getElementById("undoButton"),redo:document.getElementById("redoButton")}};function Cc(){let e={conveyor:"conveyor",boostConveyor:"boostConveyor",eggFarm:"eggFarm",autoScanner:"autoScanner",manualScanner:"manualScanner",mixer:"mixer",trash:"trash",truck:"truck",maintenanceRoom:"maintenanceRoom"};for(let[t,n]of Object.entries(e))L.buttons[t]&&(L.buttons[t].innerHTML=Or(n))}function Mc(e){let t=new Set(e.tags||[]);return["upgradeEgg","crowdedFarming","hatchingFeed","extraEggOutlet"].includes(e.id)||t.has("EGG")?"Production / EGG":["upgradeTrash","poopRateBooster","composter","chemicalWeaponSubsidy"].includes(e.id)||t.has("POOP")?"Poop / Shredder":["upgradeAutoScanner","autoScannerTuning","scannerQueueSpacing"].includes(e.id)||t.has("SCANNER")?"Scanner":["bearing","dynamite"].includes(e.id)||t.has("CONVEYOR")?"Conveyor / Map":["safetyCover","preventiveMaintenance","durabilityCoating","sparePartsBin","laborExploitation"].includes(e.id)||t.has("MAINTENANCE")?"Maintenance / Risk":["dudFilter","dudRefund","freeReroll","extraCards"].includes(e.id)||t.has("CARD")?"Card Engine":t.has("ULTRA RARE")?"Ultra Rare":t.has("ECONOMY")||["upgradeMixer","upgradeTruck","recyclingSubsidy","usedMachine","newMachine","flattery","legalWork","rescueLoan"].includes(e.id)?"Economy / Shipment":"Other"}function gc(){if(!L.debug?.panel||!L.debug.cardSelect)return;let e=["Production / EGG","Poop / Shredder","Scanner","Conveyor / Map","Maintenance / Risk","Card Engine","Economy / Shipment","Ultra Rare","Other"],t=new Map(e.map(n=>[n,[]]));for(let n of Qt){let o=Mc(n);t.has(o)||t.set(o,[]),t.get(o).push(n)}L.debug.cardSelect.innerHTML="";for(let n of e){let o=t.get(n)||[];if(!o.length)continue;let r=document.createElement("optgroup");r.label=n;for(let i of o){let l=document.createElement("option");l.value=i.id;let c=i.rarity==="ultraRare"?"UR":i.rarity==="rare"?"R":"C";l.textContent=`[${c}] ${i.title}`,r.appendChild(l)}L.debug.cardSelect.appendChild(r)}L.debug.cardSelect.addEventListener("change",Ot),Ot()}function Ot(){if(!L.debug?.targetSelect)return;let e=L.debug.cardSelect?.value,t=Jt(e),n=t?hs(u,t):[];if(L.debug.targetSelect.innerHTML="",!n.length){let r=document.createElement("option");r.value="__none__",r.textContent=t?"No target required":"No card selected",L.debug.targetSelect.appendChild(r),L.debug.targetSelect.disabled=!0;return}let o=document.createElement("option");o.value="__auto__",o.textContent=t?.id==="dynamite"?"Auto: first 3 blocked cells":"Auto: first valid target",L.debug.targetSelect.appendChild(o);for(let r of n){let i=document.createElement("option");i.value=r.key,i.textContent=r.label,L.debug.targetSelect.appendChild(i)}L.debug.targetSelect.disabled=!1}function xc(){let e=Math.max(1,Math.floor(Number(L.debug.dayInput?.value)||1));u.turn=e,L.debug.dayInput&&(L.debug.dayInput.value=String(e)),K(u,fe.width/2-u.view.x,86-u.view.y,`DAY ${e}`,y.green),z.updatePanels(),z.updateUI(),Ot(),Nt(`Day set to ${e}.`)}function Tc(){u.timeLeft=0,u.phase==="running"&&Vs(),K(u,fe.width/2-u.view.x,86-u.view.y,"TIMER 0",y.warn),z.updatePanels(),z.updateUI(),Nt("Timer set to 0.")}function Ec(){let e=L.debug.cardSelect?.value,t=L.debug.targetSelect?.disabled?void 0:L.debug.targetSelect?.value,n=ir(u,e,{targetKey:t});L.debug.grantCard&&(L.debug.grantCard.textContent=n.ok?"Granted":"Failed",window.setTimeout(()=>{L.debug.grantCard&&(L.debug.grantCard.textContent="Grant Selected")},900)),ge?.updateCongestion?.(),z.updatePanels(),z.updateUI(),Ot(),Nt(n.reason)}function Rc(){let t=Qt.map(n=>ir(u,n,{targetKey:"__auto__"})).filter(n=>n.ok).length;ge?.updateCongestion?.(),z.updatePanels(),z.updateUI(),Ot(),Nt(`Granted ${t}/${Qt.length} cards.`)}function Pc(){L.debug?.infiniteCash?.checked&&u.cash<999999&&(u.cash=999999,u.totals.maxCash=Math.max(u.totals.maxCash,u.cash))}function Nt(e=""){L.debug?.readout&&(L.debug.readout.textContent=[e,`D${u.turn}`,x(u.cash),`Combo ${u.manualCombo?.count||0}`,`Event ${u.eventActive?.title||u.eventOffer?.title||"none"}`,`Rescue ${u.cardEffects?.rescueLoanCharges||0}`,`Chem ${u.cardEffects?.chemicalWeaponSubsidy||0}`].filter(Boolean).join(" | "))}var u=To(),V,z,ge,tn;function Ac(e=null){let t=Xn(u,e);return e?t*Xo(u,e):t}function Dc(){Object.assign(u,To()),u.phase="running",u.view={x:0,y:0,scale:1},Eo(u),Xs(),Se(u),z.hideModal(),ge.updateCongestion(),z.updatePanels(),z.updateUI(),Nt()}function Ic(){if(u.phase!=="build")return;if(u.cardDraft?.pending||u.cardTargetPick?.pending){V.fail(u.cardTargetPick?.pending?"Choose upgrade target first.":"Choose an upgrade card first."),z.updatePanels();return}let e=fn(u);if(e.length){V.fail(`Cannot start: ${e[0]}`),z.updatePanels();return}Se(u),ai(u),ns(u);let t=Math.max(0,Math.floor(u.lastResult?.profit??u.stats?.profit??0)),n=Oi(u,Math.max(1,u.turn||1),t);u.lastStartFees={fairiesTribute:n.amount||0,tribute:n},n.amount>0&&K(u,fe.width/2-u.view.x,116-u.view.y,`FAIRIES -${x(n.amount)}`,y.danger),vi(u),u.phase="running",u.turn+=1,u.timeLeft=Si(u),u.shutdownTimeLeft=0,u.cleanupTimer=null,u.cleanupBlown=!1,u.chicks=[],u.effects=[],u.floatingTexts=[],u.shake={time:0,strength:0},u.truckCargo=[],Xs(),u.stats=xo(),u.stats.fairiesTribute=u.lastStartFees?.fairiesTribute||0,u.stats.fairiesTribute>0&&(u.stats.penalty+=u.stats.fairiesTribute,u.stats.profit-=u.stats.fairiesTribute);for(let o of u.scanners)o.queue=[],o.cooldown=0;for(let o of u.eggFarms)o.nextSpawn=ge.currentSpawnDelay(o),o.lastInterval=o.nextSpawn,o.shutterProgress=0,o.shutterSparked=!1;u.buildTool=null,u.selected=null,u.groupDrag=null,u.selectionBox=null,u.pan=null,ge.updateCongestion(),z.updatePanels(),z.updateUI()}function $c(){if(u.phase!=="running")return;let e=Li(u),t=u.eventActive?{...u.eventActive}:null,n=Ei(u),o=Ni(u);if(e.adjusted>0){let i=u.facilities.truck,l=i?i.x+i.w/2:fe.width/2-u.view.x,c=i?i.y+26:96-u.view.y;K(u,l,c,`${e.target==="poop"?"POOP SHIP":"SHIP"} +${x(e.adjusted)}`,y.green)}n?.bonus>0&&K(u,fe.width/2-u.view.x,96-u.view.y,`EVENT +${x(n.bonus)}`,y.green),o.amount>0&&K(u,fe.width/2-u.view.x,116-u.view.y,`CHEM SUBSIDY +${x(o.amount)}`,y.green),wi(u),u.totals.turnsCompleted+=1;let r=Ti(t);if(r!==1&&(u.pendingFairiesTributeMultiplier=r),u.lastResult={...u.stats,ship:e,event:n,chemical:o,rescue:{amount:0,used:0,remaining:u.cardEffects?.rescueLoanCharges||0},fairiesTribute:{amount:u.stats.fairiesTribute||0},tributeMultiplier:r,turn:u.turn,cash:u.cash},u.cash<0){if((u.cardEffects?.rescueLoanCharges||0)>0){u.phase="loanDecision",z.showEmergencyLoanDecision(Ys,eo);return}u.phase="gameover",z.showGameOver();return}qs()}function qs(){u.phase="build",u.truckCargo=[],u.chicks=[],u.shutdownTimeLeft=0,u.cleanupTimer=null,u.cleanupBlown=!1,u.buildSession+=1,u.undoStack=[],u.redoStack=[],u.timeLeft=0;for(let e of u.scanners)e.queue=[];for(let e of u.eggFarms)e.shutterProgress=0,e.shutterSparked=!1;os(u),u.eventOffer=bi(u),tn&&tn.prepareDraft(),u.cardTargetPick=null,u.buildTool=null,u.groupDrag=null,u.selectionBox=null,u.pan=null,z.updatePanels(),z.showTurnResult(u.lastResult)}function Ys(){if((u.cardEffects?.rescueLoanCharges||0)<=0)return eo();u.cardEffects.rescueLoanCharges-=1,u.stats.rescueLoan=(u.stats.rescueLoan||0)+500,u.totals.rescueLoan=(u.totals.rescueLoan||0)+500;let e=Ge(u,500);u.lastResult={...u.lastResult||{},...u.stats,rescue:{amount:(u.lastResult?.rescue?.amount||0)+e,used:(u.lastResult?.rescue?.used||0)+1,remaining:u.cardEffects.rescueLoanCharges},cash:u.cash},K(u,fe.width/2-u.view.x,176-u.view.y,`RESCUE +${x(e)}`,y.green),u.cash>=0?qs():(u.cardEffects?.rescueLoanCharges||0)>0?(u.phase="loanDecision",z.showEmergencyLoanDecision(Ys,eo)):eo()}function eo(){u.phase="gameover",z.showGameOver()}function Vs(){u.shutdownTimeLeft<=0&&(u.shutdownTimeLeft=u.shutdownGraceSeconds||10);for(let e of u.eggFarms){if(e.shutterSparked)continue;e.shutterProgress=.02,e.shutterSparked=!0;let t=B(e.col,e.row);Xe(u,t.x,t.y,y.ink),Ze(u,t.x,t.y+10,10),K(u,t.x,t.y-34,"SHUT +10s",y.ink)}}function zs(e){u.lastTimestamp||(u.lastTimestamp=e);let t=Math.min((e-u.lastTimestamp)/1e3,.05);u.lastTimestamp=e,u.phase==="running"&&ge.updateRunning(t,{closeFarmShutters:Vs,completeTurn:$c}),zi(u,t,fe,V.equipmentHitBoxes),ge.updateCongestion(),Cs(kc,fe,u,{activeQueuedChick:ge.activeQueuedChick,selectedObject:V.selectedObject,selectedTitle:V.selectedTitle}),Pc(),z.updateUI(),Js(),Nt(),requestAnimationFrame(zs)}function to(){return u.view?.scale||1}function kn(){u.view||(u.view={x:0,y:0,scale:1}),u.view.scale==null&&(u.view.scale=1)}function no(e){let t=fe.getBoundingClientRect();return{x:(e.clientX-t.left)*fe.width/t.width,y:(e.clientY-t.top)*fe.height/t.height}}function wt(e){let t=no(e),n=to();return{x:(t.x-(u.view?.x||0))/n,y:(t.y-(u.view?.y||0))/n}}function Fc(e){let t=to();return{x:e.x*t+(u.view?.x||0),y:e.y*t+(u.view?.y||0)}}function Bc(){let e={left:f.x-90,top:f.y-130,right:f.x+f.cols*f.cell+260,bottom:f.y+f.rows*f.cell+220};if(u.phase==="build")for(let t of Tt(u)){let n=Et(t);e.left=Math.min(e.left,n.x-60),e.top=Math.min(e.top,n.y-80),e.right=Math.max(e.right,n.x+n.w+80),e.bottom=Math.max(e.bottom,n.y+n.h+80)}return e}function Ws(e,t){if(e<=t)return[e,t];let n=(e+t)/2;return[n,n]}function St(){kn();let e=to(),t=Bc(),[n,o]=Ws(fe.width-160-t.right*e,110-t.left*e),[r,i]=Ws(fe.height-150-t.bottom*e,150-t.top*e);u.view.x=un(u.view.x,n,o),u.view.y=un(u.view.y,r,i)}function Xs(){kn(),u.view.scale=1;let e=u.eggFarms?.[0],t=e?B(e.col,e.row):{x:f.x,y:f.y};u.view.x=280-t.x,u.view.y=190-t.y,St()}function Lc(e){let t=no(e);kn(),u.pan={start:t,viewX:u.view.x,viewY:u.view.y,moved:!1}}function Oc(e){if(!u.pan)return;let t=no(e);Math.hypot(t.x-u.pan.start.x,t.y-u.pan.start.y)>5&&(u.pan.moved=!0),kn(),u.view.x=u.pan.viewX+t.x-u.pan.start.x,u.view.y=u.pan.viewY+t.y-u.pan.start.y,St()}function Nc(e){e.preventDefault(),kn();let t=no(e),n=wt(e),o=Math.exp(-e.deltaY*.0012),r=un(to()*o,.55,1.8);u.view.scale=r,u.view.x=t.x-n.x*r,u.view.y=t.y-n.y*r,St(),st()}function _c(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:{type:e.type,id:e.ref.id}:null}function Gc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:e.ref||null:null}function st(){L.hoverTooltip&&(L.hoverTooltip.classList.remove("visible"),L.hoverTooltip.setAttribute("aria-hidden","true"),u.hover=null)}function Uc(e,t){if(!L.hoverTooltip||u.phase!=="build"||u.cardTargetPick?.pending||u.groupDrag||u.selectionBox||u.pan)return st();let n=Gc(t);if(!n)return st();let o=V.selectedTitle(n),r=V.flavorText?V.flavorText(n):"",i=V.disconnectedWarningFor?V.disconnectedWarningFor(n):"",l=V.selectedInfoLines(n).slice(0,7);L.hoverTooltip.innerHTML=`${o}${i?`${i}`:r?`${r}`:""}${l.map(C=>`${C}`).join("")}`;let c=Math.min(window.innerWidth-330,e.clientX+18),b=Math.min(window.innerHeight-220,e.clientY+18);L.hoverTooltip.style.left=`${Math.max(8,c)}px`,L.hoverTooltip.style.top=`${Math.max(8,b)}px`,L.hoverTooltip.classList.add("visible"),L.hoverTooltip.setAttribute("aria-hidden","false"),u.hover={type:t.type,id:t.oldKey||t.ref?.id||null}}function Wc(e){if(u.phase!=="build")return st();Uc(e,V.equipmentAtPoint(wt(e)))}function Qs(e){st();let t=wt(e),n=V.equipmentAtPoint(t),o=_c(n);if(!o){u.selected=null,u.multiSelected=[],z.updatePanels();return}u.selected=o,u.multiSelected=[o],z.updatePanels();let r=V.selectedObject();r?.type==="scanner"&&r.kind==="manual"&&V.showManualScannerMenu(r),r?.type==="scanner"&&r.kind==="auto"&&V.showAutoScannerMenu(r)}function en(){u.buildTool=null,u.selected=null,u.multiSelected=[],u.selectionBox=null,u.cardTargetPick?.mode==="autoScannerMenu"&&(u.cardTargetPick=null),z.hideModal(),st(),z.updatePanels(),z.updateUI()}function Ks(e){return String(e).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function Kc(e){let t=e?.queue?.[0];return t==null?null:u.chicks.find(n=>n.id===t)||null}function Hc(e){if(!e)return'WAIT';let t=e.sex==="poop"?"\u{1F4A9} POOP":e.sex==="male"?"\u2642 MALE":"\u2640 FEMALE";return`${t}`}function qc(e,t){let n=new Set(u.eggFarms.map(T=>A(T.col,T.row))),o=new Map(u.scanners.map(T=>[A(T.col,T.row),T])),r=Re(e,"inputA"),i=r?A(r.col,r.row):null,l=new Set(Object.values(u.facilities||{}).map(T=>T.entry?A(T.entry.col,T.entry.row):null).filter(Boolean)),c=t?.sex||"",b=c==="poop"?"\u{1F4A9}":c==="male"?"\u2642":c==="female"?"\u2640":"",C=[];for(let T=e.row-2;T<=e.row+2;T+=1)for(let I=e.col-2;I<=e.col+2;I+=1){let $=A(I,T),O=["mini-cell"],ee="";I===e.col&&T===e.row?(O.push("scanner"),c&&O.push(c),ee=b||"S"):$===i?(O.push("input"),ee="IN"):n.has($)?(O.push("egg"),ee="E"):o.has($)?(O.push("scanner-other"),ee="S"):l.has($)?(O.push("port"),ee="P"):u.conveyorTiles.has($)?(O.push("belt"),ee="\u2022"):u.blockedCells?.has?.($)&&(O.push("blocked"),ee="\xD7"),C.push(`${ee}`)}return`
${C.join("")}
`}function Yc(e){let t=Fc(B(e.col,e.row)),n=76;return t.x<-n||t.y<-n||t.x>fe.width+n||t.y>fe.height+n}function Js(){if(!L.manualScannerMonitor)return;if(u.phase!=="running"){L.manualScannerMonitor.classList.remove("visible"),L.manualScannerMonitor.innerHTML="";return}let e=u.scanners.filter(t=>t.kind==="manual"&&Yc(t));if(!e.length){L.manualScannerMonitor.classList.remove("visible"),L.manualScannerMonitor.innerHTML="";return}L.manualScannerMonitor.innerHTML=e.map(t=>{let n=Kc(t),o=t.keys?.left?.label||(t.slot===0?"A":"Left"),r=t.keys?.right?.label||(t.slot===0?"D":"Right"),i=t.role===0?"MIXER":"WASTE",l=t.role===0?"S2":"TRUCK",c=n?"":" disabled";return` +
+
S${(t.slot??0)+1}OFFSCREEN / Q:${t.queue.length}
+
+ IN${Hc(n)}SCANNER +
+ ${qc(t,n)} +
+ + +
+
`}).join(""),L.manualScannerMonitor.classList.add("visible")}L.manualScannerMonitor?.addEventListener("click",e=>{let t=e.target.closest("button[data-scanner-id]");if(!t||t.disabled)return;let n=u.scanners.find(o=>o.id===Number(t.dataset.scannerId));n&&(ge.sortScanner(n,t.dataset.side),Js())});fe.addEventListener("contextmenu",e=>e.preventDefault());fe.addEventListener("wheel",Nc,{passive:!1});fe.addEventListener("pointerdown",e=>{if(u.phase!=="build")return;fe.setPointerCapture(e.pointerId);let t=wt(e);if(e.button===2){Lc(e);return}if(e.button!==0)return;if(u.cardTargetPick?.mode==="autoScannerMenu"){en();return}if(u.cardTargetPick?.pending){tn.chooseTargetAtPoint(t);return}let n=V.expansionOfferAtPoint?.(t);if(n){V.buyGridExpansion(n),St(),z.updatePanels(),z.updateUI();return}if(V.cycleBranchModeAtPoint?.(t)){z.updatePanels(),z.updateUI();return}let o=He(t.x,t.y),r=V.equipmentAtPoint(t);if(!u.buildTool&&r?.type==="conveyor"&&o&&V.cycleSingleConveyorDirection?.(o)){z.updatePanels(),z.updateUI();return}if(u.buildTool==="erase"){if(!V.equipmentAtPoint(t)){en();return}V.eraseAtPoint(t);return}if(u.buildTool){let i=He(t.x,t.y);if(!i&&!["mixer","trash","truck"].includes(u.buildTool)){en();return}if(u.buildTool==="conveyor"||u.buildTool==="boostConveyor"){V.beginConveyorDrag(i);return}if(V.equipmentAtPoint(t)){u.buildTool=null,Qs(e);return}V.buildAtPoint(t);return}V.startGroupDrag(e)||V.startSelectionBox(e)});fe.addEventListener("pointermove",e=>{if(u.phase!=="build"){st();return}Wc(e),u.pan&&e.buttons&2&&Oc(e),u.groupDrag&&e.buttons&1&&V.updateGroupDrag(e),u.selectionBox&&e.buttons&1&&V.updateSelectionBox(e),(u.buildTool==="conveyor"||u.buildTool==="boostConveyor")&&e.buttons&1&&V.continueConveyorDrag(He(wt(e).x,wt(e).y)),u.buildTool==="erase"&&e.buttons&1&&V.eraseAtPoint(wt(e))});fe.addEventListener("pointerup",e=>{u.selectionBox?V.finishSelectionBox():u.groupDrag&&(u.groupDrag.committed||Qs(e),V.finishGroupDrag()),e.button===2&&u.pan&&!u.pan.moved&&u.buildTool&&en(),(u.buildTool==="conveyor"||u.buildTool==="boostConveyor")&&V.endConveyorDrag?.(),u.groupDrag=null,u.pan=null;try{fe.releasePointerCapture(e.pointerId)}catch{}});fe.addEventListener("pointerleave",st);fe.addEventListener("pointercancel",()=>{V?.endConveyorDrag?.(),u.groupDrag=null,u.selectionBox=null,u.pan=null,st()});document.addEventListener("pointerdown",e=>{!L.modal.classList.contains("visible")||!L.modal.classList.contains("equipment-popover")||e.target.closest("#modal .modal-card")||en()},!0);L.buttons.s1Left.addEventListener("click",()=>ge.sortSlot(0,"left"));L.buttons.s1Right.addEventListener("click",()=>ge.sortSlot(0,"right"));L.buttons.s2Left.addEventListener("click",()=>ge.sortSlot(1,"left"));L.buttons.s2Right.addEventListener("click",()=>ge.sortSlot(1,"right"));L.buttons.nextTurn.addEventListener("click",Ic);L.buttons.conveyor.addEventListener("click",()=>V.setBuildTool("conveyor"));L.buttons.boostConveyor.addEventListener("click",()=>V.setBuildTool("boostConveyor"));L.buttons.eggFarm.addEventListener("click",()=>V.setBuildTool("eggFarm"));L.buttons.autoScanner.addEventListener("click",()=>V.setBuildTool("autoScanner"));L.buttons.manualScanner.addEventListener("click",()=>V.setBuildTool("manualScanner"));L.buttons.mixer.addEventListener("click",()=>V.setBuildTool("mixer"));L.buttons.trash.addEventListener("click",()=>V.setBuildTool("trash"));L.buttons.truck.addEventListener("click",()=>V.setBuildTool("truck"));L.buttons.maintenanceRoom.addEventListener("click",()=>V.setBuildTool("maintenanceRoom"));L.buttons.erase.addEventListener("click",()=>V.setBuildTool("erase"));L.debug.setDay?.addEventListener("click",xc);L.debug.zeroTimer?.addEventListener("click",Tc);L.debug.grantCard?.addEventListener("click",Ec);L.debug.grantAllCards?.addEventListener("click",Rc);L.buttons.undo.addEventListener("click",()=>{Ko(u)&&(St(),z.updatePanels(),z.updateUI(),Ot())});L.buttons.redo.addEventListener("click",()=>{Ho(u)&&(St(),z.updatePanels(),z.updateUI(),Ot())});function Hs(e,t,n){let o=e.keys?.[t];return o?o.code&&n.code===o.code||o.key&&n.key.toLowerCase()===o.key:!1}window.addEventListener("keydown",e=>{if(e.repeat)return;let t=e.key.toLowerCase();if(u.phase==="running")for(let n of u.scanners.filter(o=>o.kind==="manual")){if(Hs(n,"left",e)){e.preventDefault(),ge.sortScanner(n,"left");return}if(Hs(n,"right",e)){e.preventDefault(),ge.sortScanner(n,"right");return}}u.phase==="build"&&(e.ctrlKey||e.metaKey)&&t==="z"&&(e.preventDefault(),Ko(u)&&(St(),z.updatePanels(),z.updateUI())),u.phase==="build"&&(e.ctrlKey||e.metaKey)&&(t==="y"||e.shiftKey&&t==="z")&&(e.preventDefault(),Ho(u)&&(St(),z.updatePanels(),z.updateUI())),e.key==="Escape"&&u.cardTargetPick?.pending&&(e.preventDefault(),u.cardTargetPick.mode==="autoScannerMenu"?en():tn.cancelTargetPick())});V=Fs({game:u,ui:L,canvas:fe,canvasPoint:wt,onUpdatePanels:()=>z?.updatePanels()});ge=Us({game:u,currentConveyorSpeed:Ac,onGameOverCheck:()=>z?.checkGameOver()});tn=vs({game:u,ui:L,onUpdatePanels:()=>z?.updatePanels()});z=Bs({game:u,ui:L,build:V,startGame:Dc,beginCardDraft:()=>tn.showDraft(),activeQueuedChick:ge.activeQueuedChick});Cc();gc();Eo(u);Se(u);ge.updateCongestion();z.updatePanels();z.updateUI();z.showTitle();Nt();requestAnimationFrame(zs); diff --git a/dist/game-v27.19.js b/dist/game-v27.19.js new file mode 100644 index 0000000..29d8c43 --- /dev/null +++ b/dist/game-v27.19.js @@ -0,0 +1,51 @@ +var q={version:"v27.19 LAND + UI PATCH",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:.03,blockedExpansionIncrement:.005,blockedRatioMax:.1},economy:{income:{mixer:5,truck:10},poopFine:10,fairiesTribute:{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},incomeUpgradeRate:1.1,explosionDamageDivisor:30,maleTruckFinePerHalfDay:30,shredderBonus:{maxCards:30,incomePerUpgrade:1.25},chemicalWeaponSubsidy:{poopPerBlock:70,yenPerBlock:1200}},production:{poopRate:.08,autoScannerCooldown:3.5,autoScannerUpgradeRate:.95,autoScannerCardUpgradeRate:.95,autoScannerMinCooldown:.5,poopRateCardBonus:.04,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:"autoScannerTuning",title:"AUTO SCANNER Tuning",rarity:"common",type:"instant",description:"All AUTO SCANNER cooldowns use default cooldown x0.95 per copy.",tags:["SCANNER","PASSIVE"]},{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",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:"poopRateBooster",title:"Poop Culture",rarity:"common",type:"instant",description:"Base poop rate +4 percentage points. No card limit.",tags:["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:"sparePartsBin",title:"SPARE PARTS BIN",rarity:"common",type:"instant",description:"Restores 2% durability to every machine. A box of almost-compatible parts.",tags:["MAINTENANCE","ACTIVE"]},{id:"dudRefund",title:"DUD REFUND",rarity:"common",type:"instant",description:"DUDs now come with paperwork. Gain JPY 50 per copy when you pick a DUD.",tags:["CARD","ECONOMY","PASSIVE"]},{id:"freeReroll",title:"FREE REROLL",rarity:"common",type:"instant",description:"The first bad ideas are free.",tags:["CARD","PASSIVE"]},{id:"composter",title:"COMPOSTER",rarity:"common",type:"instant",description:"Turns shredder waste into suspicious fertilizer. Gain JPY 3 per copy when SHREDDER processes poop.",tags:["POOP","ECONOMY","PASSIVE"]},{id:"scannerQueueSpacing",title:"Scanner Queue Spacing",rarity:"common",type:"instant",description:"Manual and Auto Scanner queue spacing -15%. No card limit.",tags:["SCANNER","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:"Choose and remove up to 3 unbuildable cells.",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:"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:"Fairies tribute profit exemption +JPY 250.",tags:["ECONOMY","RARE","PASSIVE"]},{id:"chemicalWeaponSubsidy",title:"Chemical Weapons Subsidy",rarity:"ultraRare",type:"instant",description:"Each day, gain JPY 1200 per 70 poop shipped by truck. No card limit.",tags:["POOP","ULTRA RARE","PASSIVE"]},{id:"laborExploitation",title:"Motivational Exploitation",rarity:"ultraRare",type:"instant",description:"Repair room work time -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,autoScannerTuning:0,poopRateBooster:0,crowdedFarming:0,hatchingFeed:0,safetyCover:0,recyclingSubsidy:0,chemicalWeaponSubsidy:0,preventiveMaintenance:0,dudFilter:0,durabilityCoating:0,sparePartsBin:0,dudRefund:0,freeReroll:0,composter:0,scannerQueueSpacing:0,laborExploitation:0,usedMachineActive:!1,rescueLoanCharges:0},commonWeight:8,rareWeight:2,ultraRareWeight:.45,baseDraftSize:3,maxDudsPerDraft:2,dudChancePerCard:.3,dudChanceReductionPerFilter:.05,extraCardsAddedPicks:2,rerollCost:{dayDivisor:2,multiplier:100}},events:{eventChance:.1,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:{secondsPerOnePercent:.5,walkSpeed:90}},facilities:{conveyor:{id:"conveyor",type:"conveyor",name:"Conveyor",shortName:"Belt",price:30,buildable:!0,upgradeable:!1},boostConveyor:{id:"boostConveyor",type:"conveyor",name:"Boost Conveyor",shortName:"BOOST BELT",price:75,buildable:!0,upgradeable:!1,speedMultiplier:2},eggFarm:{id:"eggFarm",type:"eggFarm",name:"Egg Farm",shortName:"EGG",price:250,buildable:!0,upgradeable:!0,maxLevel:4},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:180,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}},maintenanceRoom:{id:"maintenanceRoom",type:"maintenanceRoom",name:"Maintenance Room",shortName:"REPAIR ROOM",price:220,buildable:!0,upgradeable:!1,footprint:{cols:2,rows:2}}}};var Pr=q.version,xt=q.time.daySeconds,an=q.cash.starting,ke=q.economy,Ar=q.time.farmShutdownGraceSeconds,Tn=q.production.autoScannerCooldown,Ir=q.production.autoScannerUpgradeRate,ho=q.production.autoScannerCardUpgradeRate||q.production.autoScannerUpgradeRate,mo=q.production.autoScannerMinCooldown,Dr=q.events.eventChance,cn=q.events.firstTurn,bo=q.production.poopRate,vo=q.production.poopRateCardBonus||0,En=q.conveyor.baseSpeed,Kt=q.conveyor.maxSpeed,Rn=q.conveyor.bearingSpeedMultiplier,De=q.cards,$r=q.cards.definitions,wo=q.cards.defaultEffects,st=q.production.eggSpawnRanges,f=q.grid,ve=q.facilities,So=["conveyor","boostConveyor","eggFarm","autoScanner","manualScanner","mixer","trash","truck","maintenanceRoom"],un=["mixer","trash","truck"],Fr=["mixer","truck"],lt=Object.fromEntries(Object.entries(ve).map(([e,t])=>[e,t.price])),de=[{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"}],y={bg:"#111318",ink:"#090a0d",muted:"#8f9bab",green:"#7bd84f",greenSoft:"#273c24",mixerBlue:"#4aa3ff",truckPink:"#ffb33e",wasteGreen:"#88d35a",danger:"#e34a36",warn:"#ffb827",white:"#e6edf2",poop:"#7b4a23",male:"#4aa3ff",female:"#ff6fae"},Ce={ambient:0,important:1,critical:2};function T(e){let t=Number(e)||0;return`${t<0?"-":""}\uFFE5${Math.ceil(Math.abs(t)).toLocaleString("ja-JP")}`}function I(e,t){return`${e},${t}`}function te(e){let[t,n]=String(e).split(",").map(Number);return{col:t,row:n}}function dn(e,t,n){return Math.max(t,Math.min(n,e))}function K(e,t){return e+Math.random()*(t-e)}function Ee(e,t){return e>=0&&e=0&&tMath.round(dn(r,0,255)).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`}function Ht(e,t,n){let o=Br(e),r=Br(t);return cl(ko(o.r,r.r,n),ko(o.g,r.g,n),ko(o.b,r.b,n))}var re={appTitle:"Chick Sorter",versionTitle:`Chick Sorter ${Pr}`,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."},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 ct(e){return ve[e]?.name||String(e||"").replace(/^[a-z]/,t=>t.toUpperCase())}function ul(e){let t=ve[e];return t?e==="conveyor"||e==="boostConveyor"?`${T(t.price)} / tile`:e==="autoScanner"?`${T(t.price)} / ${Tn.toFixed(1)}s cooldown`:e==="trash"?T(t.price):T(t.price):""}function dl(e){return{conveyor:"A narrow green belt. Routes decide whether chicks live, ship, or become invoices.",boostConveyor:"Moves chicks twice as fast. Wears down like a normal belt.",eggFarm:"A tiny gatehouse producing questionable eggs on schedule.",autoScanner:"Slower than hands without upgrades.",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.",maintenanceRoom:"2\xD72 repair bay. Each room dispatches one repairman during the day."}[e]||""}function Or(e){let t=dl(e);return`${ct(e)}${ul(e)}${t?`${t}`:""}`}function Nr(e){return re.routeLabels[e]||String(e).toUpperCase()}function _r(e){let t=2166136261;for(let n=0;n>>0}function Gr(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 Ur(e,{base:t=.03,increment:n=.005,max:o=.1}={}){let r=Math.max(0,Math.floor(Number(e)||0));return Number(Math.min(o,t+r*n).toFixed(6))}function An(){return`RUN-${Date.now().toString(36)}-${Math.floor(Math.random()*1e6).toString(36)}`.toUpperCase()}function Wr({seed:e,targetRatio:t=.2,reserved:n=[]}={}){let o=Gr(_r(e||An())),r=new Set(n.map(c=>typeof c=="string"?c:I(c.col,c.row))),i=[];for(let c=0;c0;c-=1){let b=Math.floor(o()*(c+1));[i[c],i[b]]=[i[b],i[c]]}let l=Math.round(f.cols*f.rows*t+1e-9);return new Set(i.slice(0,Math.min(l,i.length)).map(c=>c.k))}function Kr({seed:e,colStart:t=0,colEnd:n=f.cols,rowStart:o=0,rowEnd:r=f.rows,targetRatio:i=.2,reserved:l=[]}={}){let c=Gr(_r(e||An())),b=new Set(l.map(z=>typeof z=="string"?z:I(z.col,z.row))),C=[],x=Math.max(0,Math.floor(t)),A=Math.max(x,Math.floor(n)),$=Math.max(0,Math.floor(o)),B=Math.max($,Math.floor(r));for(let z=$;z0;z-=1){let ce=Math.floor(c()*(z+1));[C[z],C[ce]]=[C[ce],C[z]]}let j=Math.round((A-x)*(B-$)*i+1e-9);return new Set(C.slice(0,Math.min(j,C.length)).map(z=>z.k))}var qt=10,Hr=2,qr=1;function Yt(e,t){return`${e},${t}`}function fl(e){let[t,n]=String(e).split(",").map(Number);return{chunkX:t,chunkY:n}}function In(e){let t=q.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 Yr(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 C=Yt(b.chunkX,b.chunkY);t.has(C)||n.has(C)||n.set(C,Co(e,b.chunkX,b.chunkY,b.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 Xr(e,t="right"){let n=Tt(e);return n.find(o=>o.direction===t)||n[0]||null}function Et(e){return{x:f.x+e.colStart*f.cell,y:f.y+e.rowStart*f.cell,w:e.cols*f.cell,h:e.rows*f.cell}}function Mo(e){let t=Et(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 Qr(e,t){let n=Mo(e);return t.x>=n.x&&t.x<=n.x+n.w&&t.y>=n.y&&t.y<=n.y+n.h}function Jr(e){let t=[];for(let n=e.rowStart;nEe(t.col,t.row))}function Sl(e){return[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}].filter(t=>Ee(t.col,t.row))}function kl(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 oi(e){let t=new Set([...e.conveyorTiles]),n=o=>{o&&Ee(o.col,o.row)&&t.add(I(o.col,o.row))};for(let o of e.scanners){for(let r of Sl(o))n(r);for(let r of wl(o))n(r)}for(let o of e.eggFarms){n(o);for(let r of kl(o))n(r)}for(let o of Object.values(e.facilities))n(o.entry);return t}function ti(e){let t=hl.map(([n,o])=>({col:n,row:o}));for(let{col:n,row:o}of t)ni(e,n,o);for(let n=0;n({...n,keys:n.keys?{left:{...n.keys.left},right:{...n.keys.right}}:null,queue:[]})),e.eggFarms=bl.map(n=>{let o=Rt(n);return{...n,nextSpawn:o,lastInterval:o}});let t=oi(e);e.blockedCells=Wr({seed:e.runSeed,targetRatio:q.map.blockedRatio,reserved:[...t]}),Cl(e),ti(e),e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function Pt(e){return e?[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function ye(e){let t=F(e.col,e.row);return{x:t.x+f.cell/2,y:t.y}}function dt(e,t,n){return e.eggFarms.find(o=>o.col===t&&o.row===n)||null}function ft(e,t,n){return e.scanners.find(o=>Pt(o).some(r=>r.col===t&&r.row===n))||null}function At(e,t){return e.scanners.find(n=>n.id===t)||null}function Ro(e,t){return e.scanners.find(n=>n.kind==="manual"&&n.slot===t)||null}function Bn(e){return e?.baseId||e?.id||""}function Po(e,t){return Object.entries(e.facilities||{}).filter(([,n])=>Bn(n)===t)}function Re(e,t){return{inputA:{col:e.col,row:e.row-2},inputB:null,left:{col:e.col-1,row:e.row},right:{col:e.col+2,row:e.row}}[t]}function si(e){return e?de.map(t=>({col:e.col+t.dc,row:e.row+t.dr})).filter(t=>Ee(t.col,t.row)):[]}function li(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(I(l.col,l.row))||n.some(c=>c&&Pn(l,c))||r.some(c=>Pn(c,l))||r.push({...l,viaTolerance:!Pn(l,t)})};i(t);for(let l of o)i(l);for(let l of si(t))i(l);return r}function ri(e,t,n=[],o=[]){let r=li(e,t,n,o),i=r.filter(l=>!l.viaTolerance);return i.length?i:r}function Ml(e,t){let n=Re(t,"inputA");return!n||!Ee(n.col,n.row)?[]:e.conveyorTiles.has(I(n.col,n.row))?[{...n,viaTolerance:!1}]:[]}function gl(e,t,n){let o=Re(t,n);return li(e,o,Pt(t))}function xl(e,t){let n=e.facilities[t]||Po(e,t)[0]?.[1];if(!n)return null;if(n.entry)return F(n.entry.col,n.entry.row);let o=Bn(n)||t;return o==="mixer"?{x:n.x+n.w,y:n.y+n.h*.52}:o==="truck"?{x:n.x,y:n.y+n.h*.52}:o==="trash"?{x:n.x+n.w/2,y:n.y+8}:{x:n.x+n.w/2,y:n.y+n.h/2}}function ai(e,t,n){return n==="inputA"?Ml(e,t).length>0:gl(e,t,n).length>0}function be(e){e.branchCounters?.clear?.(),e.routeCache=null,e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function $e(e,t){return I(e,t)}function Vt(e){return te(e)}function Tl(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=>de.some(i=>i.name===r))}function El(e,t,n){let o=de.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.($e(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Rl(e,t){let n=Vt(t),o=e.conveyorMeta?.get?.(t)||{},r=de.filter(x=>e.conveyorTiles.has($e(n.col+x.dc,n.row+x.dr))).map(x=>x.name),i=Tl(e,t).filter(x=>r.includes(x)),l=i.length?i:r;if(r.length<3)return l;let c=new Set(r.filter(x=>El(e,n,x))),b=r.filter(x=>!c.has(x)),C=c.size&&b.length>=2?b:[...new Set(l)];return C.length<2&&(C=r),o.branchMode&&o.branchMode!=="random"&&C.includes(o.branchMode)?[o.branchMode]:C}function Pl(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 Al(e){let t=Pl(e);for(let o of e.conveyorTiles)t.cells.add(o),t.adjacency.set(o,[]);for(let o of t.cells){let r=Vt(o),i=Rl(e,o),l=de.filter(c=>i.includes(c.name));for(let c of l){let b=$e(r.col+c.dc,r.row+c.dr);t.cells.has(b)&&t.adjacency.get(o).push({key:b,dir:c.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),Il(t),Dl(e,t),t.issues=Kl(e,t,{includeRoutes:!1}),t}function Il(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 c of e.adjacency.get(l)||[])e.cellToComponent.has(c.key)||(e.cellToComponent.set(c.key,o),r.push(c.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 Dl(e,t){for(let n of e.scanners){let o={};for(let r of["inputA","left","right"]){let i=Re(n,r),l=r==="inputA"?i&&t.cells.has($e(i.col,i.row))?[{...i}]:[]:ri(e,i,Pt(n)).filter(C=>t.cells.has($e(C.col,C.row))),c=l.map(C=>$e(C.col,C.row)),b=c.length>0;if(o[r]={type:r,cell:i,cells:l,keys:c,key:c[0]||null,connected:b},t.metrics.scannerPorts+=1,b&&(t.metrics.connectedScannerPorts+=1),r==="inputA")for(let C of c)t.scannerInputs.set(C,n.id)}t.scannerPorts.set(n.id,o)}for(let[n,o]of Object.entries(e.facilities)){if(!o.entry)continue;let r=ri(e,o.entry).filter(c=>t.cells.has($e(c.col,c.row))),i=r.map(c=>$e(c.col,c.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=si({col:n.col,row:n.row}).map(r=>$e(r.col,r.row)).filter(r=>t.cells.has(r));t.farmOutputs.set(n.id,o),t.metrics.farmOutputs+=o.length}}function _e(e){let t=e.routingVersion||0;return(!e.factoryGraph||e.factoryGraph.version!==t)&&(e.factoryGraph=Al(e)),e.factoryGraph}function ci(e){let t=_e(e);return e.factoryGraphCommittedVersion=t.version,e.factoryGraphSnapshot=$l(t),t}function $l(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 Fl(e,t){let n=t.col-e.col,o=t.row-e.row;return de.find(r=>r.dc===n&&r.dr===o)?.name||null}function Ao(e,t,n){let o=_e(e),r=$e(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(le=>le.map(se=>({...se})));let l=`${r}|none`,c=[{key:r,col:t.col,row:t.row,incoming:"none",depth:0}],b=new Map([[l,0]]),C=new Map,x=[],A=1/0,$=8,B=24,j=80;for(;c.length;){let le=c.shift();if(le.depth>A)break;let se=`${le.key}|${le.incoming}`;if(n(le)){if(x.push(se),A=le.depth,x.length>=B)break;continue}for(let R of o.adjacency.get(le.key)||[]){let _=Vt(R.key),Y=Fl(le,_),O=le.depth+1;if(O>A)continue;let W=`${R.key}|${Y}`,U=b.get(W);if(U==null)b.set(W,O),C.set(W,[se]),c.push({key:R.key,col:_.col,row:_.row,incoming:Y,depth:O});else if(U===O){let M=C.get(W)||[];M.length<$&&!M.includes(se)&&M.push(se),C.set(W,M)}}}let z=[],ce=(le,se)=>{if(z.length>=j)return;let[R]=le.split("|"),_=[Vt(R),...se];if(le===l||R===r){z.push(_);return}for(let Y of C.get(le)||[])ce(Y,_)};for(let le of x)ce(le,[]);let he=[],ie=new Set;for(let le of z){let se=le.map(R=>$e(R.col,R.row)).join(">");ie.has(se)||(ie.add(se),he.push(le))}return n.cacheKey&&o.pathCache.set(i,he.map(le=>le.map(se=>({...se})))),he}function ui(e){let t=_e(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 di(e,t,n){let o=_e(e),r=null,i=1/0;for(let l of o.cells){let c=te(l),b=F(c.col,c.row),C=Math.hypot(b.x-t,b.y-n);CF(o.col,o.row));return t&&n.push(t),n}function ut(e,t){t&&(!e.length||Lr(e[e.length-1],t)>1)&&e.push(t)}function Bl(e,t,n,o=null){let r=[{x:e.x,y:e.y}];ut(r,F(t.col,t.row));for(let i of Ln(n,o))ut(r,i);return r}function Ll(e,t){let n=Ln(e),o=Re(t,"inputA");return o&&ut(n,F(o.col,o.row)),ut(n,ye(t)),n}function Ol(e,t,n,o){let r=[{x:e.x,y:e.y}];ut(r,F(t.col,t.row));for(let l of Ln(n))ut(r,l);let i=Re(o,"inputA");return i&&ut(r,F(i.col,i.row)),ut(r,ye(o)),r}function Nl(e,t,n=0){let o=F(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 A=C.roleBias??0,$=x.roleBias??0;if(A!==$)return A-$;let B=C.cells?.length??C.route?.length??Number.POSITIVE_INFINITY,j=x.cells?.length??x.route?.length??Number.POSITIVE_INFINITY;if(B!==j)return B-j;let z=C.key||JSON.stringify(C.route||C.cells||C),ce=x.key||JSON.stringify(x.route||x.cells||x);return z.localeCompare(ce)});if(!o||r.length===1)return r[0];let i=r[0].roleBias??0,l=r.filter(C=>(C.roleBias??0)===i),c=Math.min(...l.map(C=>ii(e,C)));l=l.filter(C=>ii(e,C)===c);let b=e.branchCounters.get(t)||0;return e.branchCounters.set(t,b+1),l[Math.floor(Math.random()*l.length)]}function fi(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 Io(e){let t=fi(e);return{left:t.left.destination,right:t.right.destination}}function Do(e,t){return fi(e).left.match===t.sex?"left":"right"}function $o(e){return Nr(e)}function Fo(e){return{mixer:"#2477ff",truck:"#ff6aa8",trash:"#22b94f","scanner-role-1":"#526456",scanner:"#526456",input:"#526456"}[e]||"#102015"}function It(e,t,n=!1){let o=_e(e),r=(o.farmOutputs.get(t.id)||[]).map(Vt),i=[];for(let b of r){let C=A=>o.scannerInputs.has($e(A.col,A.row));C.cacheKey=`farmInput:${b.col},${b.row}:v${o.version}`;let x=Ao(e,b,C);for(let A of x){let $=A[A.length-1],B=o.scannerInputs.get($e($.col,$.row)),j=At(e,B);j&&i.push({key:`${j.id}:${$.col},${$.row}:${A.length}`,scanner:j,cells:A})}}let l=Fn(e,`farm:${t.id}`,i,n);if(l)return{scannerId:l.scanner.id,route:Ll(l.cells,l.scanner)};let c=Fn(e,`farm:${t.id}:output`,r.map(b=>({key:I(b.col,b.row),cells:[b]})),n);return c?{scannerId:null,route:Ln(c.cells)}:null}function pi(e,t,n,o,r=!1){let i=At(e,o);if(!i)return null;let c=_e(e).scannerPorts.get(i.id)?.[t],b=Re(i,t),C=c?.connected?(c.keys||[c.key]).filter(Boolean).map(Vt):[];if(!b||!C.length)return null;let x=Io(i)[t];return x==="scanner-role-1"?_l(e,i,t,n,b,C,r):Gl(e,i,t,n,b,C,x,r)}function _l(e,t,n,o,r,i,l){let c=_e(e),b=e.scanners.filter(A=>A.id!==t.id&&c.scannerPorts.get(A.id)?.inputA?.connected),C=[];for(let A of i)for(let $ of b){let B=c.scannerPorts.get($.id)?.inputA?.key;if(!B)continue;let j=(c.scannerPorts.get($.id)?.inputA?.keys||[B]).filter(Boolean),z=ie=>j.includes($e(ie.col,ie.row));z.cacheKey=`toScanner:${A.col},${A.row}:${$.id}:v${c.version}`;let ce=Ao(e,A,z),he=$.role===1?0:1;for(let ie of ce)C.push({key:`${he}:start${I(A.col,A.row)}:s${$.id}:${ie.length}:${I(ie[ie.length-1].col,ie[ie.length-1].row)}`,target:$,cells:ie,roleBias:he})}let x=Fn(e,`scanner:${t.id}:${n}:toRole1`,C,l);return x?{destination:"scanner",nextScannerId:x.target.id,route:Ol(o,r,x.cells,x.target)}:null}function Gl(e,t,n,o,r,i,l,c){let b=_e(e),C=[...b.facilityPorts.entries()].filter(([$,B])=>B?.connected&&Bn(e.facilities?.[$])===l);if(!C.length)return null;let x=[];for(let $ of i)for(let[B,j]of C){let z=(j.keys||[j.key]).filter(Boolean);if(!z.length)continue;let ce=ie=>z.includes($e(ie.col,ie.row));ce.cacheKey=`toFacility:${$.col},${$.row}:${B}:v${b.version}`;let he=Ao(e,$,ce);for(let ie of he)x.push({key:`start${I($.col,$.row)}:${B}:${ie.length}:${I(ie[ie.length-1].col,ie[ie.length-1].row)}`,cells:ie,facilityId:B})}let A=Fn(e,`scanner:${t.id}:${n}:${l}`,x,c);return A?{destination:l,facilityId:A.facilityId,route:Bl(o,r,A.cells,xl(e,A.facilityId))}:null}function yi(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=pi(e,o,ye(t),t.id,!1);if(r){if(["mixer","trash","truck"].includes(r.destination))return!0;if(r.destination==="scanner"){let i=At(e,r.nextScannerId);if(yi(e,i,n))return!0}}}return!1}function Ul(e,t){return!!It(e,t,!1)?.scannerId}function On(e){if(e.phase!=="build")return[];let t=[];for(let n of e.eggFarms||[])Ul(e,n)||t.push({type:"eggFarm",id:n.id,ref:n,message:"This Egg will not produce chicks"});for(let n of un)for(let[o,r]of Po(e,n))_e(e).facilityPorts.get(o)?.connected||t.push({type:"facility",id:o,ref:r,message:"This facility cannot receive items"});return t}function Wl(e){let t=_e(e);for(let r of e.eggFarms||[]){let i=It(e,r,!1);if(!i?.scannerId)continue;let l=At(e,i.scannerId);if(yi(e,l))return[]}let n=e.eggFarms?.length||0,o=[...t.facilityPorts.entries()].filter(([r,i])=>i?.connected&&["mixer","trash","truck"].includes(Bn(e.facilities?.[r]))).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 $n(e){return e.kind==="manual"?`S${(e.slot??0)+1}`:`Auto Scanner #${e.id}`}function Kl(e,t=_e(e),n={}){let o=n.includeRoutes!==!1,r=[],i={mixer:"Mixer",trash:"Shredder",truck:"Truck"};for(let l of un){let c=Po(e,l);if(!c.length){r.push(`${i[l]||l} is missing`);continue}for(let[b]of c)t.facilityPorts.get(b)?.connected||r.push(`${i[l]||l} receiver has no conveyor`)}for(let l of e.scanners){let c=t.scannerPorts.get(l.id)||{};if(c.inputA?.connected||r.push(`${$n(l)} input has no conveyor`),c.left?.connected||r.push(`${$n(l)} left output has no conveyor`),c.right?.connected||r.push(`${$n(l)} right output has no conveyor`),!!o)for(let b of["left","right"])c[b]?.connected&&!pi(e,b,ye(l),l.id)&&r.push(`${$n(l)} ${b} route is incomplete`)}if(o)for(let l of e.eggFarms)It(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 pn(e){return Wl(e)}function hi(e){return pn(e).length===0}var mi=[{key:"premiumFemaleShipment",target:"female",truckTarget:"female",title:"Premium Female Shipment",route:"Female -> Truck",note:"Today only: ship female chicks to Truck. Meet the export target for a bonus.",objective:"truckTarget"},{key:"contaminantSampleExport",target:"poop",truckTarget:"poop",title:"Contaminant Sample Export",route:"Poop value x2",note:"Today only: poop is valid Truck cargo and all poop income is doubled.",objective:"truckTarget",poopValueMultiplier:2},{key:"healthInspection",title:"Health Inspection",route:"Poop -> Shredder",note:"Today only: poop mistakes are fined double. Shred enough poop for an inspection bonus.",objective:"poopTrash",poopFineMultiplier:2},{key:"conveyorJamWarning",title:"Conveyor Jam Warning",route:"No explosions",note:"Today only: jam explosions trigger at 85% congestion. Finish with zero explosions for a bonus.",objective:"noExplosion",congestionExplosionThreshold:.85,congestionWarningThreshold:.68},{key:"powerSavingOrder",title:"Power Saving Order",route:"Slow factory subsidy",note:"Today only: conveyors -20% speed and Auto Scanners +20% cooldown. A subsidy is paid at settlement.",objective:"flatBonus",conveyorSpeedMultiplier:.8,autoScannerCooldownMultiplier:1.2},{key:"overtimeDay",title:"Overtime Day",route:"80 second day",note:"Today only: the work day is longer. No extra reward or penalty.",objective:"none",daySeconds:80},{key:"shortShift",title:"Short Shift",route:"40 second day",note:"Today only: the work day is shorter. The next Fairies tribute is reduced by 10%.",objective:"none",daySeconds:40,fairiesTributeMultiplier:.9},{key:"chickBoom",title:"Chick Boom",route:"EGG interval x0.65",note:"Today only: eggs hatch faster and poop rate rises by 5 percentage points.",objective:"none",productionMultiplier:1/.65,poopRateAdd:.05},{key:"rottenFeed",title:"Rotten Feed",route:"Poop surge",note:"Today only: poop rate rises by 20 percentage points and Shredder poop income is multiplied by 1.5.",objective:"none",poopRateAdd:.2,shredderIncomeMultiplier:1.5},{key:"maintenanceAudit",title:"Maintenance Audit",route:"Durability check",note:"Today only: machines below 50% remaining durability fail the audit. Passing with none below 50% pays a bonus.",objective:"maintenanceAudit"}];function we(e,t=0){let n=Number(e);return Number.isFinite(n)?n:t}function Hl(e,t=0,n=1){let o=Math.max(1,Number(e?.turn||1)+1),r=Math.floor(Bo(e)*(.08+Math.random()*.08)),i=Math.floor(Math.max(0,e.cash||0)*.25),l=Math.floor(Math.max(0,t)*Math.max(1,o)*.75);return Math.max(120,Math.ceil(Math.max(r,i,l)*n))}function bi(e){return Math.max(0,Math.ceil(500+Math.max(1,e?.turn||1)*25))}function Bo(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 ql(e,t=1,n=xt){return e.eggFarms.reduce((o,r)=>{let[i,l]=fn(r),c=Math.max(.1,(i+l)/2);return o+Math.max(1,n)/c*Math.max(.01,t||1)},0)}function Yl(e,t){let n=we(t.productionMultiplier,1),o=we(t.daySeconds,xt),r=ql(e,n,o),i=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),l=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),c=Math.pow(1.03,i),b=bo+vo*l,C=Math.min(.95,Math.max(0,(b+we(t.poopRateAdd,0))*we(t.poopMultiplier,1)*c));return{estimate:r,poopRate:C}}function vi(e){if(e.turn+1Dr)return null;let n=mi[Math.floor(Math.random()*mi.length)],{estimate:o,poopRate:r}=Yl(e,n),i=0;n.objective==="truckTarget"?i=Math.max(1,Math.ceil(o*.3)):n.objective==="poopTrash"&&(i=Math.max(1,Math.ceil(o*r*.8)));let l=0;return["truckTarget","poopTrash","noExplosion"].includes(n.objective)&&(l=Hl(e,o)),n.objective==="flatBonus"&&(l=bi(e)),n.objective==="maintenanceAudit"&&(l=bi(e)),{id:`event-${e.turn}-${Date.now()}-${Math.floor(Math.random()*9999)}`,...n,target:n.target||null,truckTarget:n.truckTarget||null,forced:!0,productionMultiplier:we(n.productionMultiplier,1),poopMultiplier:we(n.poopMultiplier,1),poopRateAdd:we(n.poopRateAdd,0),daySeconds:we(n.daySeconds,xt),targetAmount:i,estimatedOutput:Math.round(o),reward:l,createdTurn:e.turn,oneTurnOnly:!0}}function wi(e){e.eventActive=e.eventOffer?{...e.eventOffer}:null,e.eventOffer=null}function Si(e){e.eventActive=null}function ki(e){return Math.max(1,we(e.eventActive?.daySeconds,xt))}function Ci(e){return we(e.eventActive?.productionMultiplier,1)}function Mi(e){let t=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),n=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),o=Math.pow(1.03,t),r=bo+vo*n,i=we(e.eventActive?.poopRateAdd,0);return Math.min(.95,Math.max(0,(r+i)*we(e.eventActive?.poopMultiplier,1)*o))}function pt(e){return e.eventActive?.truckTarget||e.eventActive?.target||"female"}function Lo(e,t){return t==="male"?e.truckMale||0:t==="poop"?e.poopTruck||0:e.truckFemale||0}function gi(e,t){return pt(e)===t}function xi(e){return pt(e)!=="male"}function Oo(e){return Math.max(.01,we(e.eventActive?.poopValueMultiplier,1))}function Nn(e){return Math.max(.01,Oo(e)*we(e.eventActive?.shredderIncomeMultiplier,1))}function No(e){return Math.max(.01,we(e.eventActive?.poopFineMultiplier,1))}function _o(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionExplosionThreshold,1)))}function Ti(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionWarningThreshold,.8)))}function Ei(e){return Math.max(.01,we(e?.fairiesTributeMultiplier,1))}function Vl(e){let t=0,n=(o,r)=>{let i=Math.max(1,we(r,1)),l=Math.max(0,we(o,0));1-Math.min(1,l/i)<.5&&(t+=1)};for(let o of e.conveyorMeta?.values?.()||[])n(o.uses,o.durability);for(let o of e.eggFarms||[])n(o.maintenance?.uses,o.maintenance?.durability);for(let o of e.scanners||[])o.kind==="auto"&&n(o.maintenance?.uses,o.maintenance?.durability);for(let o of Object.values(e.facilities||{})){let r=o?.baseId||o?.id;(r==="mixer"||r==="trash")&&n(o.maintenance?.uses,o.maintenance?.durability)}return t}function Ri(e){let t=e.eventActive;if(!t)return null;let n=0,o=!0,r=0,i="";t.objective==="truckTarget"?(n=Lo(e.stats,t.target),o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="poopTrash"?(n=e.stats.poopTrash||0,o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="noExplosion"?(n=e.stats.explosions||0,o=n===0,r=o?t.reward:0,i=`${n} explosion(s)`):t.objective==="flatBonus"?(o=!0,r=t.reward):t.objective==="maintenanceAudit"?(n=Vl(e),o=n===0,o&&(r=t.reward),i=`${n} machine(s) below 50%`):o=!0,r>0?(Ge(e,r),e.stats.eventBonus=(e.stats.eventBonus||0)+r,e.totals.eventBonus+=r,e.totals.eventSuccess+=1):t.objective&&t.objective!=="none"&&(e.stats.eventBonus=e.stats.eventBonus||0,e.totals.eventFailed+=o?0:1,o&&(e.totals.eventSuccess+=1));let l={title:t.title,key:t.key,target:t.target,route:t.route,objective:t.objective,targetAmount:t.targetAmount||0,count:n,success:o,bonus:r,reward:t.reward||0,productionMultiplier:t.productionMultiplier,poopMultiplier:t.poopMultiplier,daySeconds:t.daySeconds,detail:i};return e.stats.eventResult=l,l}function Go(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function zl(e){return!!e?.cardEffects?.usedMachineActive}function Xl(e,t){return t?1:Math.min(.8,.5+.1*Math.min(3,Go(e,"recyclingSubsidy")))}function Ql(e){return Math.pow(.95,Go(e,"safetyCover"))}function _n(e){let t=e?.ref||e||{},n=e?.type||t.type;return n==="conveyor"?t.price||ve[t.kind]?.price||ve.conveyor.price:n==="eggFarm"?t.price||ve.eggFarm.price:n==="scanner"?t.price||(t.kind==="auto"?ve.autoScanner.price:ve.manualScanner.price):n==="facility"?t.price||ve[t.id]?.price||0:n==="maintenanceRoom"?t.price||ve.maintenanceRoom.price:ve[t.id]?.price||0}function Oe(e,t=null){let n=ve[e]?.price||0;return zl(t)?Math.ceil(n*.5):n}function Jl(e,t){return e?.facilities?Object.values(e.facilities).filter(n=>(n?.baseId||n?.id)===t).reduce((n,o)=>n+Math.max(0,(o.level||1)-1),0):0}function yt(e,t){return Fr.includes(t)?Math.pow(ke.incomeUpgradeRate,Jl(e,t)):1}function ze(e){return Math.ceil(ke.income.mixer*yt(e,"mixer"))}function Fe(e){return Math.ceil(ke.income.truck*yt(e,"truck"))}function yn(e){return Math.ceil(ke.poopFine*yt(e,"mixer")*No(e))}function hn(e){return Math.ceil(ke.poopFine*yt(e,"truck")*No(e))}function Uo(e){let t=ke.maleTruckFinePerHalfDay*(e.turn/2);return Math.ceil(t*yt(e,"truck"))}function Wo(e){return e?.facilities?Object.values(e.facilities).filter(t=>(t?.baseId||t?.id)==="trash").reduce((t,n)=>t+Math.max(0,(n.level||1)-1),0):0}function Dt(e){return Math.min(ke.shredderBonus.maxCards,Wo(e))}function zt(){return ke.shredderBonus.maxCards}function ht(e){let t=typeof e=="number"?e:Dt(e),n=Math.min(ke.shredderBonus.maxCards,Math.max(0,t));return n>0?Math.ceil(n*(ke.shredderBonus.incomePerUpgrade||1)):0}function jl(e){let t=Dt(e),n=ht(t),o=Math.ceil(n*Nn(e));return{cards:t,chance:o>0?1:0,amount:o,expected:o,baseAmount:n}}function Pi(e){let t=jl(e);return t.amount>0&&(e.stats.shredderBonus=(e.stats.shredderBonus||0)+t.amount,e.totals.shredderBonus=(e.totals.shredderBonus||0)+t.amount,Ge(e,t.amount)),t}function Ko(e,t=e.turn,n=null){let o=Math.max(1,Math.floor(Number(t)||1)),r=ke.fairiesTribute||{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},i=Math.ceil(o*(r.perDay||10)),l=Math.max(0,Math.floor(Number(n??e?.lastResult?.profit??e?.stats?.profit??0)||0)),c=Math.max(0,e?.cardEffects?.legalWork||0),b=Math.max(0,(r.profitExemption||0)+c*(r.legalWorkExemptionBonus||0)),C=Math.max(0,l-b),x=Math.ceil(C*Math.max(0,Number(r.profitRate)||0)),A=i+x,$=Math.max(0,e?.cardEffects?.fairiesFlatteryNext||e?.cardEffects?.flattery||0),B=$>0?Math.pow(.5,$):1,j=Math.max(.01,Number(e?.pendingFairiesTributeMultiplier)||1),z=B*j,ce=Math.max(0,Math.ceil(A*z)),he=Math.max(0,A-ce);return{day:o,base:i,profit:l,legalWork:c,profitExemption:b,taxableProfit:C,profitTribute:x,gross:A,flatteryCount:$,eventMultiplier:j,perCardReduction:Math.ceil(A*.5),reduction:he,amount:ce}}function mt(e,t){let n=e?.ref||e||{},o=e?.type==="conveyor"?t?.conveyorMeta?.get(e.oldKey||n.id):n,r=o?.price||_n(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=Xl(t,i);return{amount:Math.max(0,Math.ceil(r*l)),sameBuild:i,price:r,rate:l,noRefund:!1}}function Zl(e,t=null){let n=Math.max(1,Math.ceil((Number(e)||0)/ke.explosionDamageDivisor));return Math.max(1,Math.ceil(n*Ql(t)))}function ea(e,t){return Math.max(0,Math.ceil(t))}function Ai(e,t){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 Ge(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Ai(e,n),n}function bt(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Ai(e,-n),n}function $t(e,t){bt(e,t)}function Ii(e,t){t<=0||(e.cash+=t,e.stats.profit+=t,e.totals.profit+=t,e.totals.maxCash=Math.max(e.totals.maxCash,e.cash))}function Di(e){let t=ze(e);return e.stats.mixerRevenue+=t,Ge(e,t),t}function $i(e){let t=yn(e);return e.stats.mixerPoopFine+=t,e.totals.mixerPoopFine+=t,bt(e,t),t}function Fi(e){let t=hn(e);return e.stats.truckPoopFine+=t,e.totals.truckPoopFine+=t,bt(e,t),t}function Bi(e){let t=Uo(e);return e.stats.maleTruckFine+=t,e.totals.maleTruckFine+=t,bt(e,t),t}function Li(e,t){let n=Zl(t,e);return e.stats.explosionDamage+=n,e.totals.explosionDamage+=n,bt(e,n),n}function Oi(e){let t=pt(e),n=Lo(e.stats,t),o=t==="poop"?Math.ceil(Fe(e)*Oo(e)):Fe(e),r=n*o,i=ea(e,r);return e.stats.pendingTruckRevenue=i,e.stats.truckRevenue=i,t==="poop"?e.stats.poopShipmentIncome=i:e.stats.chickShipmentIncome=i,i>0&&Ge(e,i),{base:r,adjusted:i,target:t,targetCount:n,unitPrice:o}}function Ni(e,t=e.turn,n=null,o={}){let r=Ko(e,t,n);return e.cardEffects&&(e.cardEffects.fairiesFlatteryNext=0,e.cardEffects.flattery!=null&&delete e.cardEffects.flattery),e.pendingFairiesTributeMultiplier!=null&&(e.pendingFairiesTributeMultiplier=1),r.amount<=0||(o.recordStats?(e.stats.fairiesTribute=(e.stats.fairiesTribute||0)+r.amount,e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,bt(e,r.amount)):(e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,e.totals.penalty=(e.totals.penalty||0)+r.amount,e.totals.profit=(e.totals.profit||0)-r.amount,e.cash-=r.amount)),r}function _i(e){let t=Go(e,"chemicalWeaponSubsidy"),n=Math.max(0,e?.stats?.poopTruck||0),o=ke.chemicalWeaponSubsidy||{poopPerBlock:70,yenPerBlock:1200},r=Math.floor(n/Math.max(1,o.poopPerBlock||70)),i=t>0&&r>0?r*Math.max(0,o.yenPerBlock||1200)*t:0;return i>0&&(e.stats.chemicalWeaponSubsidy=(e.stats.chemicalWeaponSubsidy||0)+i,e.totals.chemicalWeaponSubsidy=(e.totals.chemicalWeaponSubsidy||0)+i,Ge(e,i)),{cards:t,poopTruck:n,blocks:r,amount:i}}function Gi(e){let t=Bo(e),n=Math.max(1,e.totals.turnsCompleted||e.turn||1),o=Math.max(0,e.cash+e.totals.revenue+t*.5+e.totals.eventBonus*.5),r=Math.ceil(o/n),i=Math.floor(n*35+Math.max(0,n-5)*15),l=e.totals.correct*5,c=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:c,days:n}}function ta(e){return{...e,keys:e.keys?{left:{...e.keys.left},right:{...e.keys.right}}:null,queue:[],cooldown:e.cooldown||0}}function mn(e){return JSON.stringify({cash:e.cash,stats:e.stats,totals:e.totals,nextId:e.nextId,gridX:f.x,gridY:f.y,gridCols:e.gridCols||f.cols,gridRows:e.gridRows||f.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(ta),conveyorTiles:[...e.conveyorTiles],conveyorMeta:[...e.conveyorMeta.entries()],branchCounters:[...e.branchCounters.entries()],cardEffects:e.cardEffects,cardDraft:e.cardDraft,cardTargetPick:e.cardTargetPick})}function Ui(e,t){let n=JSON.parse(t);e.cash=n.cash,e.stats=n.stats,e.totals=n.totals,e.nextId=n.nextId,f.x=n.gridX??q.grid.x,f.y=n.gridY??q.grid.y,f.cols=n.gridCols||q.grid.cols,f.rows=n.gridRows||q.grid.rows,e.gridCols=f.cols,e.gridRows=f.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||f.cols*f.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,fairiesFlatteryNext:0,scannerQueueSpacing: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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=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 Be(e){e.phase==="build"&&(e.undoStack.push(mn(e)),e.undoStack.length>80&&e.undoStack.shift(),e.redoStack=[])}function Ho(e){return e.phase!=="build"||!e.undoStack.length?!1:(e.redoStack.push(mn(e)),Ui(e,e.undoStack.pop()),!0)}function qo(e){return e.phase!=="build"||!e.redoStack.length?!1:(e.undoStack.push(mn(e)),Ui(e,e.redoStack.pop()),!0)}function H(e,t,n,o,r=y.ink){e.floatingTexts.push({x:t,y:n,text:o,color:r,life:1,maxLife:1})}function Ft(e,t,n){e.shake.strength=Math.max(e.shake.strength,t),e.shake.time=Math.max(e.shake.time,n)}function Wi(e,t,n){e.effects.push({type:"spawn",priority:Ce.ambient,x:t,y:n,life:.42,maxLife:.42,size:12})}function Ki(e,t,n,o=y.green){e.effects.push({type:"scannerPulse",priority:Ce.important,x:t,y:n,color:o,life:.42,maxLife:.42,size:24})}function Hi(e,t,n){for(let o=0;o<12;o+=1)e.effects.push({type:"meat",priority:Ce.important,x:t+K(-18,18),y:n+K(-12,16),vx:K(-60,60),vy:K(-90,-25),life:K(.45,.85),maxLife:.85,size:K(4,8)})}function qi(e,t,n){for(let o=0;o<16;o+=1)e.effects.push({type:"sludge",priority:Ce.important,x:t+K(-18,18),y:n+K(-12,16),vx:K(-46,46),vy:K(-70,-20),life:K(.45,.9),maxLife:.9,size:K(4,8)})}function Yi(e,t,n,o){let r=o==="poop"?y.poop:o==="male"?y.male:y.female;for(let i=0;i<22;i+=1)e.effects.push({type:"shred",priority:Ce.important,x:t+K(-16,16),y:n+K(-8,8),vx:K(-70,70),vy:K(40,160),color:i%3===0?y.white:r,life:K(.45,.95),maxLife:.95,w:K(3,7),h:K(10,24),rot:K(-Math.PI,Math.PI)});Xe(e,t,n,y.green,34,Ce.important)}function Vi(e,t,n,o){let r=o==="poop"?y.poop:o==="male"?y.danger:y.green;for(let i=0;i<8;i+=1)e.effects.push({type:"load",priority:Ce.important,x:t+K(-18,18),y:n+K(-18,18),vx:K(-42,42),vy:K(-90,-25),color:r,life:K(.35,.65),maxLife:.65,size:8})}function Xe(e,t,n,o=y.danger,r=52,i=Ce.critical){e.effects.push({type:"shockwave",priority:i,x:t,y:n,color:o,life:.55,maxLife:.55,size:8,maxSize:r})}function Ze(e,t,n,o=12,r=y.danger,i=Ce.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||na(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 na(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=Li(e,o.price);H(e,t.x,t.y-10,`-${T(r)}`,y.danger),Xe(e,t.x,t.y,y.danger,30),Ze(e,t.x,t.y,5,y.danger),Ft(e,5,.18)}}var Ue=q.maintenance;function Vo(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Wn(e){let t=Math.min(1.4,1+.04*Math.min(10,Vo(e,"crowdedFarming"))),n=Math.pow(.95,Vo(e,"preventiveMaintenance"));return t*n}function oa(e){return Math.pow(1.03,Vo(e,"durabilityCoating"))}function Kn(e,t,n=1){let o=Ue.durability[t]||1e3;return Math.max(1,Math.ceil(o*Math.max(.1,n||1)*oa(e)))}function Qi(e){return Math.max(.1,Number(e?.durabilityBaseMultiplier)||1)}function ra(e,t=0){if(!e)return{x:f.x+f.cell*(.5+t*.55),y:f.y+f.rows*f.cell+84};let n=f.x+e.col*f.cell+f.cell,o=f.y+e.row*f.cell+f.cell;return{x:n,y:o}}function ia(e,t=0){let n=(e.maintenanceRooms||[])[t];return ra(n,t)}function Se(e){e.repairman||(e.repairman={active:!1,x:f.x+f.cell*.5,y:f.y+f.rows*f.cell+84,target:null,repairedToday:0}),Array.isArray(e.maintenanceRooms)||(e.maintenanceRooms=[]),Array.isArray(e.repairmen)||(e.repairmen=[]);for(let[t,n]of e.conveyorMeta||[]){n.uses==null&&(n.uses=0),n.maintenanceType==null&&(n.maintenanceType="conveyor"),n.kind||(n.kind="conveyor"),n.speedMultiplier||(n.speedMultiplier=n.kind==="boostConveyor"?2:1),n.branchMode||(n.branchMode="random");let o=Kn(e,"conveyor",Qi(n));(n.durability==null||n.durability0&&(n.processingCooldown=Math.max(0,n.processingCooldown-t))}function wn(e){Se(e);let t=[];for(let[n,o]of e.conveyorMeta||[])t.push({type:"conveyor",key:n,meta:o,label:`${o.kind==="boostConveyor"?"Boost Belt":"Belt"} ${n}`,center:F(te(n).col,te(n).row)});for(let n of e.eggFarms||[])t.push({type:"eggFarm",ref:n,label:`EGG #${n.id}`,center:F(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:F(n.col,n.row)});for(let n of Object.values(e.facilities||{})){let o=Vn(n);["mixer","trash"].includes(o)&&t.push({type:o,ref:n,label:`${n.shortName||n.name||o} #${n.id}`,center:{x:n.x+n.w/2,y:n.y+n.h/2}})}return t}function Bt(e){return e.meta?Xt(e):Xt(e.ref)}function bn(e){return e.meta?zo(e):zo(e.ref)}function Un(e){return e.meta?Xo(e):Xo(e.ref)}function ts(e,t){sa(e.meta?e:e.ref,Math.max(0,bn(e)-t))}function or(e){return e.type==="conveyor"?`conveyor:${e.key}`:`${e.type}:${e.ref?.id||e.ref?.type||e.type}`}function ns(e,t=.02){Se(e);let n=Math.max(0,Number(t)||0),o=0;for(let r of wn(e)){let i=bn(r);ts(r,Un(r)*n),o+=Math.max(0,i-bn(r))/Un(r)*100}return o}function os(e){Se(e);let t=e.maintenanceRooms||[];e.repairmen=t.map((o,r)=>{let i=ia(e,r);return{id:`room-${o.id}`,roomId:o.id,active:!0,x:i.x,y:i.y,target:null,repairedToday:0}});let n=e.repairmen[0];e.repairman.active=!!n,e.repairman.target=n?.target||null,e.repairman.repairedToday=0,n&&(e.repairman.x=n.x,e.repairman.y=n.y)}function rs(e){Se(e);for(let t of e.repairmen||[])t.active=!1,t.target=null;e.repairmen=[],e.repairman.active=!1,e.repairman.target=null}function aa(e,t){return t&&wn(e).find(o=>or(o)===t.key)||null}function ca(e){let t=null;for(let n of wn(e)){let o=Bt(n);o<=.001||(!t||o>Bt(t))&&(t=n)}return t}function is(e,t){Se(e);let n=e.repairmen?.length?e.repairmen:e.repairman?.active?[e.repairman]:[];if(!n.length||e.phase!=="running")return;let o=new Set(n.map(i=>i.target?.key).filter(Boolean));for(let i of n)ua(e,i,t,o);let r=n[0];r&&e.repairman!==r&&(e.repairman.active=!0,e.repairman.x=r.x,e.repairman.y=r.y,e.repairman.target=r.target,e.repairman.repairedToday=r.repairedToday||0)}function ua(e,t,n,o){if(!t.active)return;let r=aa(e,t.target);if((!r||Bt(r)<=.001)&&(t.target?.key&&o.delete(t.target.key),r=da(e,o)),!r){t.target=null;return}let i=or(r);o.add(i),t.target={key:i,label:r.label};let l=Ue.repairman.walkSpeed,c=r.center.x-t.x,b=r.center.y-t.y,C=Math.hypot(c,b);if(C>8){let z=Math.min(C,l*n);t.x+=c/C*z,t.y+=b/C*z;return}let x=e?.cardEffects?.laborExploitation?.7:1,A=n/(Ue.repairman.secondsPerOnePercent*x*100),$=bn(r),B=A*Un(r);ts(r,B);let j=Math.max(0,($-bn(r))/Un(r)*100);t.repairedToday=(t.repairedToday||0)+j,j>0&&Math.random()<.02&&H(e,t.x,t.y-28,"REPAIR",y.green),Bt(r)<=.001&&(o.delete(i),t.target=null)}function da(e,t=new Set){let n=null;for(let o of wn(e)){if(t.has(or(o)))continue;let r=Bt(o);r<=.001||(!n||r>Bt(n))&&(n=o)}return n||ca(e)}function fa(e){let t=0,n="none";for(let o of wn(e)){let r=Bt(o);r>t&&(t=r,n=o.label)}return{ratio:t,percent:Math.round(t*100),label:n}}function rr(e){let t=fa(e),n=Jo(e);return{worst:t,avgBeltPerformance:n,repairman:e.repairman||null,repairmen:e.repairmen||[],rooms:e.maintenanceRooms||[]}}var pa=De.commonWeight,ya=De.rareWeight,ha=De.ultraRareWeight||.45,Lt=De.baseDraftSize,Jt=$r;function Qt(e,t){let n=Le(e);return Math.max(0,Number(n[t])||0)}function Le(e){e.cardEffects||(e.cardEffects={...wo});for(let[t,n]of Object.entries(wo))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),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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=0),e.cardEffects}function ps(e){let t=Math.max(.5,1-.05*Math.min(10,Qt(e,"crowdedFarming"))),n=Math.pow(.96,Qt(e,"hatchingFeed"));return t*n}function ys(e,t=null){return Math.min(3,Math.max(0,Number(t?.extraEggOutlet)||0))}function hs(e){return Math.pow(.85,Qt(e,"scannerQueueSpacing"))}function Xn(e,t=null){let n=Le(e),o=En*Math.pow(Rn,Math.max(0,n.bearing||0)),r=t?Math.max(.1,Number(e?.conveyorMeta?.get?.(t)?.speedMultiplier)||1):1,i=t?1:Jo(e),l=Math.max(.01,Number(e?.eventActive?.conveyorSpeedMultiplier)||1);return Math.min(Kt,o*i)*r*l}function nt(e,t=null){let n=Math.max(0,(e?.level||1)-1),o=t?Qt(t,"autoScannerTuning"):0,r=Tn*Math.pow(Ir,n)*Math.pow(ho,o),i=Math.max(mo,r),l=t?Math.max(.01,Number(t?.eventActive?.autoScannerCooldownMultiplier)||1):1;return t?Math.max(mo,i*qn(e)*l):i}function ss(e){let t=e.cardDraft||{rerolls:0},n=Math.max(1,(t.rerolls||0)+1);return Math.ceil(Math.max(1,e.turn||1)/De.rerollCost.dayDivisor*n*De.rerollCost.multiplier)}function Ot(e){return Jt.find(t=>t.id===e)||null}function ms(e,t){let n=typeof t=="string"?Ot(t):t;return Le(e),!n||!(n.type==="equipmentUpgrade"||n.type==="cellAction")?[]:We(e,n).map(o=>({key:tt(o),label:lr(e,o),type:o.type}))}function sr(e,t,n={}){let o=typeof t=="string"?Ot(t):t;if(Le(e),!o||o.type==="dud")return{ok:!1,reason:"Card not found."};if(o.id==="extraCards")return e.cardDraft=e.cardDraft||{pending:!1,choices:[],rerolls:0,picksRemaining:0},e.cardDraft.choices.push(...zn(e,2)),{ok:!0,reason:`${o.title} added 2 draft cards.`};if(o.type==="instant")return vs(e,o),{ok:!0,reason:`${o.title} granted.`};if(o.type==="equipmentUpgrade"){let r=We(e,o);if(!r.length)return{ok:!1,reason:`No valid target for ${o.title}.`};let i=n.targetKey&&n.targetKey!=="__auto__"?String(n.targetKey):"",l=i?r.find(c=>tt(c)===i):r[0];return l?(bs(e,l),{ok:!0,reason:`${o.title} applied to ${lr(e,l)}.`}):{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`}}if(o.type==="cellAction"&&o.target==="blockedCell"){let r=We(e,o);if(!r.length)return{ok:!1,reason:"No blocked cells to remove."};let i=new Set((Array.isArray(n.targetKeys)?n.targetKeys:[n.targetKey]).filter(c=>c&&c!=="__auto__").map(String)),l=i.size?r.filter(c=>i.has(tt(c))):r.slice(0,3);if(!l.length)return{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`};for(let c of l.slice(0,3)){e.blockedCells.delete(I(c.col,c.row));let b=F(c.col,c.row);et(e,b.x,b.y),Xe(e,b.x,b.y,y.danger,42),Ze(e,b.x,b.y,8,y.warn)}return be(e),{ok:!0,reason:`${o.title} removed ${Math.min(3,l.length)} blocked cell(s).`}}return{ok:!1,reason:`${o.title} cannot be debug-granted.`}}function lr(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 ${nt(t,e).toFixed(1)}s -> ${nt({...t,level:t.level+1},e).toFixed(1)}s`;if(t.type==="facility"&&(t.baseId||t.id)==="mixer"){let n=t.level,o=ze(e);t.level=n+1;let r=ze(e);return t.level=n,`MIXER L${t.level} -> L${t.level+1} | ${T(o)} -> ${T(r)}`}if(t.type==="facility"&&(t.baseId||t.id)==="truck"){let n=t.level,o=Fe(e);t.level=n+1;let r=Fe(e);return t.level=n,`TRUCK L${t.level} -> L${t.level+1} | ${T(o)} -> ${T(r)}`}if(t.type==="facility"&&t.id==="trash"){let n=Dt(e),o=Math.min(zt(),n+1),r=ht(n),i=ht(o);return`SHREDDER L${t.level||1} -> L${(t.level||1)+1} | poop income ${T(r)} -> ${T(i)} per item`}return`${t.name||t.id} L${t.level||1} -> L${(t.level||1)+1}`}function ma(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 We(e,t){let n=typeof t=="string"?Ot(t):t;return Le(e),n?n.target==="blockedCell"?ma(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"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="mixer"):n.target==="truck"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="truck"):n.target==="trash"?Wo(e)(o.baseId||o.id)==="trash"):[]:[]:[]}function ba(e,t){let n=Le(e);if(t.id==="crowdedFarming")return(n.crowdedFarming||0)>=10;if(t.id==="recyclingSubsidy")return(n.recyclingSubsidy||0)>=3;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,De.dudChancePerCard||0)),r=Math.max(1e-4,Math.min(1,De.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 va(e){return!!((e.maintenanceRooms||[]).length||(e.repairmen||[]).length||e.repairman?.active)}function wa(e){return Jt.filter(t=>!(t.id==="laborExploitation"&&!va(e)||ba(e,t)||(t.type==="equipmentUpgrade"||t.type==="cellAction")&&We(e,t).length<=0))}function ls(e,t){return t.rarity==="ultraRare"?ha:t.rarity==="rare"?ya:pa}function Sa(e,t){let n=t.reduce((r,i)=>r+ls(e,i),0);if(n<=0)return t[Math.floor(Math.random()*t.length)];let o=Math.random()*n;for(let r of t)if(o-=ls(e,r),o<=0)return r;return t[t.length-1]}var as=0;function ka(){return as+=1,{id:`dud:${Date.now()}:${as}`,title:"Dud",rarity:"dud",type:"dud",description:"Click to flick this dud away. It does not consume a pick."}}function Ca(e){let t=Le(e),n=Math.max(0,Math.min(1,De.dudChancePerCard||0)),o=Math.max(0,Math.min(1,De.dudChanceReductionPerFilter||0));return Math.max(0,n-o*Math.max(0,t.dudFilter||0))}function Ma(e,t){let n=[...t],o=0,r=Math.max(0,De.maxDudsPerDraft||0),i=Ca(e);for(let l=0;lc.id===i.id);l>=0&&r.splice(l,1)}return Ma(e,o)}function tt(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 cs(e){if(!e)return null;if(e.type==="blockedCell"){let t=F(e.col,e.row);return{x:t.x-f.cell*.48,y:t.y-f.cell*.48,w:f.cell*.96,h:f.cell*.96,cx:t.x,cy:t.y}}if(e.type==="eggFarm"||e.type==="eggOutlet"){let t=F(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=ye(e);return{x:t.x-54,y:t.y-77,w:108,h:154,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 ar(e){if(!e.cardTargetPick?.pending)return[];if(e.cardTargetPick.mode==="autoScannerMenu"){let n=new Set(e.cardTargetPick.targetKeys||[]);return e.scanners.filter(o=>o.kind==="auto"&&n.has(tt(o))).map(o=>({key:tt(o),label:"AUTO ROUTE SETTINGS",target:o,bounds:cs(o)})).filter(o=>o.bounds)}let t=new Set(e.cardTargetPick.targetKeys||[]);return We(e,e.cardTargetPick.cardId).filter(n=>t.has(tt(n))).map(n=>({key:tt(n),label:lr(e,n),target:n,bounds:cs(n)})).filter(n=>n.bounds)}function ga(e,t){let n=ar(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 bs(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=F(n.col,n.row);H(e,o.x,o.y-30,`OUTLET ${1+n.extraEggOutlet}`,y.green),be(e);return}if(t.level=(t.level||1)+1,t.type==="eggFarm"){t.nextSpawn=Rt(t),t.lastInterval=t.nextSpawn;let n=F(t.col,t.row);H(e,n.x,n.y-30,`LV ${t.level}`,y.green);return}if(t.type==="scanner"){let n=ye(t);H(e,n.x,n.y-34,`LV ${t.level}`,y.green);return}t.type==="facility"&&H(e,t.x+t.w/2,t.y+18,`LV ${t.level}`,y.green)}function vs(e,t){let n=Le(e),o=r=>{n[r]=Math.max(0,n[r]||0)+1};if(t.id==="bearing"&&o("bearing"),t.id==="autoScannerTuning"&&o("autoScannerTuning"),t.id==="legalWork"&&o("legalWork"),t.id==="crowdedFarming"&&(n.crowdedFarming=Math.min(10,(n.crowdedFarming||0)+1)),t.id==="hatchingFeed"&&o("hatchingFeed"),t.id==="poopRateBooster"&&o("poopRateBooster"),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"),Se(e)),t.id==="sparePartsBin"){o("sparePartsBin");let r=ns(e,.02);e.stats.sparePartsRepair=(e.stats.sparePartsRepair||0)+r,e.totals.sparePartsRepair=(e.totals.sparePartsRepair||0)+r,H(e,f.x+f.cols*f.cell/2,f.y-30,"REPAIR +2%",y.green)}t.id==="dudRefund"&&o("dudRefund"),t.id==="freeReroll"&&o("freeReroll"),t.id==="composter"&&o("composter"),t.id==="scannerQueueSpacing"&&o("scannerQueueSpacing"),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"),H(e,f.x+f.cols*f.cell/2,f.y-30,"RESCUE HELD",y.green))}function qe(e){return`${Math.round(Number(e||0)*100)}%`}function us(e){let t=st[Math.max(0,Math.min(st.length-1,e-1))]||st[0]||[0,0];return`${t[0].toFixed(2)}-${t[1].toFixed(2)}s`}function ds(e,t){return Math.ceil(e*Math.pow(ke.incomeUpgradeRate,Math.max(0,t-1)))}function fs(e,t,n){let r=We(e,t==="mixer"?"upgradeMixer":"upgradeTruck")[0];if(!r)return{before:ds(n,1),after:ds(n,2)};let i=t==="mixer"?ze(e):Fe(e),l=r.level||1;r.level=l+1;let c=t==="mixer"?ze(e):Fe(e);return r.level=l,{before:i,after:c}}function xa(e,t){let n=Le(e);if(t.id==="upgradeEgg"){let o=We(e,t),r=Math.min(3,Math.max(1,o[0]?.level||1));return`Choose one EGG. Level +1. Production interval ${us(r)} -> ${us(r+1)}.`}if(t.id==="upgradeAutoScanner"){let o=We(e,t)[0]||{level:1},r=nt(o,e),i=nt({...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=fs(e,"mixer",ke.income.mixer);return`Choose one MIXER. Earning +10%. Male-chick income ${T(o.before)} -> ${T(o.after)}.`}if(t.id==="upgradeTruck"){let o=fs(e,"truck",ke.income.truck);return`Choose one TRUCK. Earning +10%. Correct shipment income ${T(o.before)} -> ${T(o.after)}.`}if(t.id==="upgradeTrash"){let o=Dt(e),r=Math.min(zt(),o+1),i=ht(o),l=ht(r);return`SHREDDER level +1. Poop income ${T(i)} -> ${T(l)} per item.`}if(t.id==="bearing"){let o=Math.min(Kt,En*Math.pow(Rn,Math.max(0,n.bearing||0))),r=Math.min(Kt,En*Math.pow(Rn,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`Fairies tribute profit exemption +${T(250)}. After pick: exemption bonus ${T(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 ${qe(Math.max(.5,1-.05*o))}, deterioration ${qe(Math.min(1.4,1+.04*o))}.`}if(t.id==="extraEggOutlet"){let o=We(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 ${qe(Math.pow(.96,(n.hatchingFeed||0)+1))}, poop rate multiplier ${qe(Math.pow(1.03,(n.hatchingFeed||0)+1))}.`;if(t.id==="poopRateBooster")return`Held ${n.poopRateBooster||0}. After pick: base poop rate +${Math.round((n.poopRateBooster||0)+1)*4} percentage points.`;if(t.id==="autoScannerTuning")return`Held ${n.autoScannerTuning||0}. After pick: all AUTO SCANNER default cooldown ${qe(Math.pow(ho,(n.autoScannerTuning||0)+1))}.`;if(t.id==="safetyCover")return`Held ${n.safetyCover||0}. After pick: explosion damage ${qe(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: ${T(1200*((n.chemicalWeaponSubsidy||0)+1))} per 70 truck-shipped poop each day.`;if(t.id==="preventiveMaintenance")return`Held ${n.preventiveMaintenance||0}. After pick: deterioration speed ${qe(Math.pow(.95,(n.preventiveMaintenance||0)+1))}.`;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,De.dudChancePerCard||0)),r=Math.max(0,Math.min(1,De.dudChanceReductionPerFilter||.05)),i=Math.max(0,n.dudFilter||0),l=Math.max(0,o-r*i),c=Math.max(0,o-r*(i+1));return`Held ${i}. DUD chance per card ${qe(l)} -> ${qe(c)}.`}return t.id==="durabilityCoating"?`Held ${n.durabilityCoating||0}. After pick: maximum durability ${qe(Math.pow(1.03,(n.durabilityCoating||0)+1))}.`:t.id==="sparePartsBin"?`Held ${n.sparePartsBin||0}. Immediately restores 2% durability to every maintained machine. Common card weight.`:t.id==="dudRefund"?`Held ${n.dudRefund||0}. After pick: DUD clicks award ${T(50*((n.dudRefund||0)+1))}.`:t.id==="freeReroll"?`Held ${n.freeReroll||0}. After pick: each card screen starts with ${(n.freeReroll||0)+1} free reroll${(n.freeReroll||0)+1===1?"":"s"}.`:t.id==="composter"?`Held ${n.composter||0}. After pick: SHREDDER poop grants ${T(3*((n.composter||0)+1))}.`:t.id==="scannerQueueSpacing"?`Held ${n.scannerQueueSpacing||0}. After pick: Manual/Auto Scanner queue spacing ${qe(Math.pow(.85,(n.scannerQueueSpacing||0)+1))}.`:t.id==="flattery"?`Next Fairies tribute -50%. Held for next tribute: ${n.fairiesFlatteryNext||0}.`:t.id==="usedMachine"?"Enable Used Machines: future equipment costs 50%, has no SELL refund, and starts with 60% durability.":t.id==="newMachine"?"Cancel Used Machines. Future equipment returns to normal price, refund, and durability.":t.id==="laborExploitation"?"Repairman dispatch paperwork is streamlined. Repair rooms keep operating; one time only.":t.id==="rescueLoan"?`At day-end bankruptcy check, gain ${T(500)} if cash is below ${T(0)}. Held: ${n.rescueLoanCharges||0}.`:t.id==="dynamite"?"Choose any blocked tiles on the map and destroy up to 3. Empty-space clicks are ignored; press Esc to finish after at least one blast.":t.description}function ir(e,t){let n=e.cardDraft?.choices||[],o=n.findIndex(r=>r.id===t.id);o>=0&&n.splice(o,1)}function ws({game:e,ui:t,onUpdatePanels:n}){function o(){n&&n()}function r(){Le(e),e.cardTargetPick=null,e.cardDraft={pending:!0,choices:zn(e,Lt),rerolls:0,freeRerolls:Qt(e,"freeReroll"),picksRemaining:1}}function i(){Le(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(R=Lt){Le(e),e.cardDraft.choices=zn(e,R)}function c(){Le(e),!e.cardDraft.choices.length&&e.cardDraft.picksRemaining>0&&l(Lt)}function b(R){ir(e,R),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1),e.cardTargetPick=null,c(),e.cardDraft.picksRemaining<=0?i():se()}function C(R){ir(e,R),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1)+De.extraCardsAddedPicks,e.cardDraft.choices.push(...zn(e,2)),se()}function x(R,_){let Y=Qt(e,"dudRefund")*50;if(Y>0){let O=Ge(e,Y);e.stats.dudRefundIncome=(e.stats.dudRefundIncome||0)+O,e.totals.dudRefundIncome=(e.totals.dudRefundIncome||0)+O,H(e,f.x+f.cols*f.cell/2,f.y-30,`DUD REFUND +${T(O)}`,y.green)}Ft(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)"}),_&&(_.style.setProperty("--fling-x",`${260+Math.random()*260}px`),_.style.setProperty("--fling-y",`${-260-Math.random()*170}px`),_.style.setProperty("--fling-r",`${(Math.random()<.5?-1:1)*(52+Math.random()*38)}deg`),_.classList.add("flung")),window.setTimeout(()=>{ir(e,R),c(),se()},340)}function A(R,_=null){if(R.type==="dud")return x(R,_);if(R.id==="extraCards")return C(R);if(R.type==="equipmentUpgrade"||R.type==="cellAction")return $(R);vs(e,R),b(R)}function $(R){let _=We(e,R);_.length&&(e.cardTargetPick={pending:!0,cardId:R.id,mode:R.target==="blockedCell"?"blockedCell":"equipment",targetKeys:_.map(tt),remaining:R.id==="dynamite"?Math.min(3,_.length):1,used:0},t.modal.classList.remove("visible","equipment-popover"),o())}function B(R){if(!R||R.type!=="blockedCell")return!1;let _=I(R.col,R.row);if(!e.blockedCells?.has(_))return!1;e.blockedCells.delete(_);let Y=F(R.col,R.row);return et(e,Y.x,Y.y),Xe(e,Y.x,Y.y,y.danger,62),Ze(e,Y.x,Y.y,18,y.warn),Gn(e,Y.x,Y.y,8),Ft(e,16,.35),H(e,Y.x,Y.y-18,"BOOM",y.danger),be(e),e.cardTargetPick.remaining=Math.max(0,(e.cardTargetPick.remaining||1)-1),e.cardTargetPick.used=Math.max(0,e.cardTargetPick.used||0)+1,e.cardTargetPick.targetKeys=We(e,"dynamite").map(tt),o(),!0}function j(R){if(!e.cardTargetPick?.pending)return!1;let _=Ot(e.cardTargetPick.cardId),Y=ga(e,R);return _?_.id==="dynamite"?(!Y||!B(Y)||((e.cardTargetPick.remaining||0)<=0||!We(e,"dynamite").length)&&b(_),!0):Y?(bs(e,Y),b(_),!0):(z(),!0):(z(),!0)}function z(){if(!e.cardTargetPick?.pending)return;let R=e.cardTargetPick,_=Ot(R.cardId);if(_?.id==="dynamite"&&(R.used||0)>0){b(_);return}e.cardTargetPick=null,se()}function ce(){let R=Math.max(0,e.cardDraft?.freeRerolls||0);if(R>0){e.cardDraft.freeRerolls=R-1,e.cardDraft.rerolls+=1,l(Lt),se();return}let _=ss(e);e.cash<_||(bt(e,_),e.stats.cardRerollCost=(e.stats.cardRerollCost||0)+_,e.totals.cardRerollCost=(e.totals.cardRerollCost||0)+_,e.cardDraft.rerolls+=1,l(Lt),se())}function he(R){let _=new Set(R.tags||[]),Y={eggFarm:{type:"image",src:"./assets/dark_factory/facilities/machines/egg_farm_16.png",alt:"EGG"},eggOutlet:{type:"image",src:"./assets/dark_factory/facilities/machines/egg_farm_16.png",alt:"EGG"},autoScanner:{type:"image",src:"./assets/dark_factory/facilities/machines/auto_scanner_32x48.png",alt:"SCAN"},mixer:{type:"image",src:"./assets/dark_factory/facilities/machines/mixer_compact_16.png",alt:"MIX"},truck:{type:"image",src:"./assets/dark_factory/facilities/vehicles/truck_compact_16.png",alt:"TRUCK"},trash:{type:"image",src:"./assets/dark_factory/facilities/machines/shredder_compact_16.png",alt:"SHR"},blockedCell:{type:"image",src:"./assets/dark_factory/facilities/utility/obstacle_crate_16.png",alt:"BLOCK"}};return Y[R.target]?Y[R.target]:R.id==="bearing"||_.has("CONVEYOR")?{type:"image",src:"./assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png",alt:"BELT"}:_.has("SCANNER")?{type:"image",src:"./assets/dark_factory/facilities/machines/auto_scanner_32x48.png",alt:"SCAN"}:_.has("EGG")?{type:"image",src:"./assets/dark_factory/facilities/machines/egg_farm_16.png",alt:"EGG"}:_.has("POOP")?{type:"glyph",text:"\u{1F4A9}"}:_.has("MAINTENANCE")?{type:"image",src:"./assets/dark_factory/facilities/utility/repairman_16.png",alt:"FIX"}:_.has("CARD")?{type:"glyph",text:"\u25A3"}:_.has("ECONOMY")?{type:"glyph",text:"\uFFE5"}:_.has("RISK")?{type:"glyph",text:"!"}:{type:"glyph",text:"\u25C6"}}function ie(R){let _=he(R);return _.type==="image"?`
${_.alt||
`:``}function le(R,_){let Y=document.createElement("button");Y.type="button";let O=R.type==="dud"?"dud":R.rarity==="ultraRare"?"ultra-rare":R.rarity==="rare"?"rare":"common";Y.className=`card-choice ${O}`;let W=R.type==="dud"?"MISS":R.rarity==="ultraRare"?"ULTRA RARE":R.rarity==="rare"?"RARE":"COMMON",U=[W,...(R.tags||[]).filter(M=>M!==W)].slice(0,5);return Y.innerHTML=`${ie(R)}
${R.title}
${U.map(M=>`${M}`).join("")}
${xa(e,R)}
`,Y.addEventListener("click",()=>A(R,Y)),Y.dataset.index=String(_),Y}function se(){Le(e),e.cardTargetPick=null,e.cardDraft?.pending||r(),e.cardDraft.choices?.length||l(Lt);let R=e.cardDraft.choices||[],_=ss(e),Y=Math.max(0,e.cardDraft?.freeRerolls||0),O=Math.max(1,e.cardDraft.picksRemaining||1);t.modalTitle.textContent="Choose Upgrade Card",t.modalBody.innerHTML=`

Choose ${O} card${O===1?"":"s"} before Build phase. Dud cards can be flicked away without consuming a pick. Equipment cards target machines; Dynamite targets blocked cells.

`;let W=t.modalBody.querySelector("#cardChoices");R.forEach((g,G)=>W.appendChild(le(g,G))),t.modalActions.innerHTML="";let U=document.createElement("button");U.type="button",U.className="facility-action warn reroll-button",U.textContent=Y>0?`Reroll (FREE x${Y})`:`Reroll ${T(_)}`,U.disabled=Y<=0&&e.cash<_,U.title=Y>0?`${Y} free reroll${Y===1?"":"s"} remaining.`:U.disabled?"Not enough cash":"",U.addEventListener("click",ce),t.modalActions.appendChild(U);let M=document.createElement("button");M.type="button",M.className="facility-action",M.textContent="No Card",M.title="Skip this upgrade pick and enter Build phase.",M.addEventListener("click",i),t.modalActions.appendChild(M),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible")}return{prepareDraft:r,showDraft:se,finishDraft:i,chooseTargetAtPoint:j,cancelTargetPick:z}}var Ta=!0,Ea={chickMale:"./assets/images/chick_male.png",chickFemale:"./assets/images/chick_female.png",poop:"./assets/images/poop.png",conveyorStraightH:"./assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png",conveyorStraightV:"./assets/dark_factory/facilities/conveyor/conveyor_straight_v_16.png",conveyorTurnNe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_ne_16.png",conveyorTurnNw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png",conveyorTurnSe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_se_16.png",conveyorTurnSw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png",boostConveyorStraightH:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_h_16.png",boostConveyorStraightV:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_v_16.png",boostConveyorTurnNe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_ne_16.png",boostConveyorTurnNw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png",boostConveyorTurnSe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_se_16.png",boostConveyorTurnSw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png",scannerManual:"./assets/dark_factory/facilities/machines/manual_scanner_32x48.png",scannerAuto:"./assets/dark_factory/facilities/machines/auto_scanner_32x48.png",eggFarm:"./assets/dark_factory/facilities/machines/egg_farm_16.png",mixer:"./assets/dark_factory/facilities/machines/mixer_32.png",shredder:"./assets/dark_factory/facilities/machines/shredder_32.png",truck:"./assets/dark_factory/facilities/vehicles/truck_32.png",mixerCompact:"./assets/dark_factory/facilities/machines/mixer_compact_16.png",shredderCompact:"./assets/dark_factory/facilities/machines/shredder_compact_16.png",truckCompact:"./assets/dark_factory/facilities/vehicles/truck_compact_16.png",maintenanceRoom:"./assets/dark_factory/facilities/utility/maintenance_room_32.png",repairman:"./assets/dark_factory/facilities/utility/repairman_16.png",obstacleCrate:"./assets/dark_factory/facilities/utility/obstacle_crate_16.png"},ue={};for(let[e,t]of Object.entries(Ea)){let n=new Image;n.loaded=!1,n.onerror=()=>{n.loaded=!1},Ta&&t&&(n.onload=()=>{n.loaded=!0},n.src=t),ue[e]=n}function Cs(e,t,n,o){e.imageSmoothingEnabled=!1,e.clearRect(0,0,t.width,t.height),$a(e,t),e.save();let r=n.shake.time>0?K(-n.shake.strength,n.shake.strength):0,i=n.shake.time>0?K(-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),Ba(e,n),La(e,n),Na(e,n),Xa(e,n),oc(e,n),rc(e,n),Qa(e,n),ja(e,n),Pa(e,n),ac(e,n,o.activeQueuedChick),bc(e,n),pc(e,t,n),fc(e,n,o.selectedObject,o.selectedTitle),yc(e,n),hc(e,n),mc(e,n),e.restore(),wc(e,n,t)}function Ra(e){if(e.type==="eggFarm"){let n=F(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 Pa(e,t){if(t.phase!=="build")return;let n=On(t);for(let o of n){let r=Ra(o);e.save(),e.fillStyle="rgba(196,36,36,.22)",e.strokeStyle=y.danger,e.lineWidth=5,e.setLineDash([10,6]),ee(e,r.x,r.y,r.w,r.h,!0,!0),e.setLineDash([]),e.fillStyle=y.danger,e.strokeStyle=y.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 ee(e,t,n,o,r,i=!0,l=!0){e.beginPath(),e.rect(t,n,o,r),i&&e.fill(),l&&e.stroke()}function ur(e,t,n,o,r=y.ink){e.save(),e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.lineWidth=4,e.strokeStyle=y.white,e.fillStyle=r,e.strokeText(o,t,n),e.fillText(o,t,n),e.restore()}function vt(e,t,n,o,r,i){if(!t?.loaded)return!1;let l=e.imageSmoothingEnabled;return e.imageSmoothingEnabled=!1,e.drawImage(t,Math.round(n),Math.round(o),Math.round(r),Math.round(i)),e.imageSmoothingEnabled=l,!0}function Aa(e,t,n,o,r,i,l=null,c=1){e.fillStyle=i,e.fillRect(Math.round(t),Math.round(n),Math.round(o),Math.round(r)),l&&(e.strokeStyle=l,e.lineWidth=c,e.strokeRect(Math.round(t)+.5,Math.round(n)+.5,Math.round(o)-1,Math.round(r)-1))}function Ia(e,t){let n=(Math.imul(e+37,73856093)^Math.imul(t+71,19349663))>>>0;return n^=n>>>13,n>>>0}function Da(e,t,n,o,r){let i=Ia(o,r);if(i%31!==0)return;let l=10+(i>>>4)%Math.max(1,f.cell-22),c=10+(i>>>9)%Math.max(1,f.cell-22),b=(i>>>14)%16*Math.PI/16;e.save(),e.globalAlpha=.46,e.fillStyle="#4d9638",e.strokeStyle="rgba(30,66,27,.48)",e.lineWidth=1,e.beginPath();for(let x=0;x<8;x+=1){let A=b+x*Math.PI/4,$=3.5+(i>>>x+2&3),B=t+l+Math.cos(A)*$*1.35,j=n+c+Math.sin(A)*$*.75;x===0?e.moveTo(B,j):e.lineTo(B,j)}e.closePath(),e.fill(),e.stroke();let C=3+(i>>>24)%4;for(let x=0;x>>x+8&3)*.18,$=8+(i>>>x+11&7),B=1.1+(i>>>x+17&3)*.45;e.beginPath(),e.arc(t+l+Math.cos(A)*$,n+c+Math.sin(A)*$*.72,B,0,Math.PI*2),e.fill()}e.fillStyle="rgba(151,218,101,.40)",e.beginPath(),e.arc(t+l-2,n+c-2,1.7,0,Math.PI*2),e.fill(),e.restore()}function $a(e,t){e.fillStyle=y.bg,e.fillRect(0,0,t.width,t.height),e.save(),e.globalAlpha=.85;for(let n=0;n=n;for(let r of Tt(t)){let i=Et(r);e.save(),e.fillStyle=o?"rgba(183,245,198,.34)":"rgba(255,255,255,.22)",e.strokeStyle=o?y.green:y.muted,e.lineWidth=5,e.setLineDash([16,10]),ee(e,i.x,i.y,i.w,i.h,!0,!0),e.setLineDash([]);let l=Mo(r),c=l.cx,b=l.cy;e.fillStyle="rgba(255,255,255,.94)",e.strokeStyle=y.ink,e.lineWidth=4,ee(e,l.x,l.y,l.w,l.h,!0,!0),e.fillStyle=o?y.green:y.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText(r.direction==="right"?"BUY RIGHT LOT":"BUY UPPER LOT",c,b-12),e.fillStyle=y.ink,e.font="900 16px ui-monospace, monospace",e.fillText(`${T(n)} / 10\xD710`,c,b+15),e.fillStyle=y.muted,e.font="900 11px ui-monospace, monospace",e.fillText("blocked tiles included",c,b+30),e.restore()}}function ot(e,t,n,o,r,i,l=0){let c=Xt(i);c<.5||(e.save(),e.globalAlpha=Math.min(.62,.12+c*.54),e.fillStyle="#6b4a23",l>0?(e.beginPath(),e.roundRect?.(t,n,o,r,l),e.roundRect?e.fill():ee(e,t,n,o,r,!0,!1)):ee(e,t,n,o,r,!0,!1),e.globalAlpha=Math.min(.9,.25+c*.6),e.strokeStyle="#3a2a16",e.lineWidth=Math.max(2,Math.floor(2+c*5)),e.setLineDash([5,6]),ee(e,t+3,n+3,o-6,r-6,!1,!0),e.restore())}function cr(e,t){let n=e.componentLookup?.get(t);return(n?e.congestion.get(n):null)?.ratio||0}function Oa(e,t,n={}){let o=kn(e,t).sort(),i=n.kind==="boostConveyor"?"boostConveyor":"conveyor",l=c=>o.includes(c);if(o.length===2){if(l("left")&&l("right"))return ue[`${i}StraightH`];if(l("up")&&l("down"))return ue[`${i}StraightV`];if(l("up")&&l("right"))return ue[`${i}TurnNe`];if(l("up")&&l("left"))return ue[`${i}TurnNw`];if(l("down")&&l("right"))return ue[`${i}TurnSe`];if(l("down")&&l("left"))return ue[`${i}TurnSw`]}return o.length===1?l("up")||l("down")?ue[`${i}StraightV`]:ue[`${i}StraightH`]:l("up")||l("down")?ue[`${i}StraightV`]:ue[`${i}StraightH`]}function Na(e,t){let n=[],o=new Set;for(let i of t.conveyorTiles){let{col:l,row:c}=te(i);for(let b of de){let C={col:l+b.dc,row:c+b.dr},x=I(C.col,C.row);if(!t.conveyorTiles.has(x))continue;let A=[i,x].sort().join("|");if(o.has(A))continue;o.add(A);let $=Math.max(cr(t,i),cr(t,x));n.push({a:F(l,c),b:F(C.col,C.row),ratio:$})}}e.save(),e.lineCap="round",e.lineJoin="round";for(let i of[{width:31,color:"#0b0c0f",alpha:1},{width:23,color:"#444b56",alpha:1},{width:15,color:"#171a1f",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=Ht(y.green,y.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=Ya(t);for(let i of t.conveyorTiles){let l=F(...Object.values(te(i))),c=t.conveyorMeta.get(i)||{},b=cr(t,i),C=Oa(t,i,c),x=b>.5;if(e.fillStyle=x?"rgba(196,36,36,.28)":"rgba(0,0,0,.35)",e.strokeStyle=x?y.danger:"rgba(255,184,39,.34)",e.lineWidth=x?3:1,ee(e,l.x-20,l.y-20,40,40,!0,!0),!vt(e,C,l.x-19,l.y-19,38,38)){let $=c.kind==="boostConveyor"?"#315e92":"#454b55";e.fillStyle=b>.5?Ht($,"#a12c2c",Math.max(0,(b-.5)/.5)):$,e.strokeStyle=y.ink,e.lineWidth=2,ee(e,l.x-18,l.y-18,36,36,!0,!0)}_a(e,l,i,c,b),ot(e,l.x-18,l.y-18,36,36,{meta:c}),rt(e,t,"conveyor",i,l.x,l.y,38,38),Va(e,l,r.get(i)||[]);let A=kn(t,i);Ha(e,l,c,Wa(t,i,A),A),b>.5&&ur(e,l.x,l.y-15,`${Math.floor(b*100)}%`,y.danger)}e.restore()}function _a(e,t,n,o={},r=0){let l=[...new Set([...Array.isArray(o.outDirs)?o.outDirs:[],o.dir].filter(Boolean))][0]||"right",c=l==="up"||l==="down",b=l==="left"||l==="up",C=o.kind==="boostConveyor",x=typeof performance<"u"?performance.now()/(C?70:105):0,A=((b?-x:x)%10+10)%10;e.save(),e.beginPath(),e.rect(t.x-18,t.y-18,36,36),e.clip();let $=C?"rgba(20,126,124,.62)":"rgba(42,47,54,.72)";if(e.fillStyle=$,e.fillRect(t.x-18,t.y-18,36,36),e.strokeStyle=r>.5?"rgba(238,83,61,.90)":"rgba(184,190,198,.92)",e.lineWidth=4,c)for(let B=t.y-28+A;Be.conveyorTiles.has(I(n.col+o.dc,n.row+o.dr))).map(o=>o.name)}function Ga(e,t,n){let o=de.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.(I(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Ms(e,t,n,o=kn(e,t)){if(o.length<3)return n;let r=te(t),i=new Set(o.filter(b=>Ga(e,r,b))),l=o.filter(b=>!i.has(b));if(i.size&&l.length>=2)return l;let c=n.filter(b=>o.includes(b));return c.length>=2?[...new Set(c)]:o}function Ua(e,t,n,o=kn(e,t),r="random"){let i=Ms(e,t,n,o);return o.length>=3&&r&&r!=="random"&&i.includes(r)?[r]:i}function Wa(e,t,n=kn(e,t)){let o=e.conveyorMeta?.get?.(t)||{},r=[...new Set([...Array.isArray(o.outDirs)?o.outDirs:[],o.dir].filter(Boolean))];return n.length<3?[]:Ms(e,t,r,n)}function Ka(e,t,n){let o=te(t),r=de.filter(c=>e.conveyorTiles.has(I(o.col+c.dc,o.row+c.dr))).map(c=>c.name),i=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(c=>r.includes(c)),l=r;return i.length?i:l}function Ha(e,t,n,o,r=o){if(r.length<3||o.length<2)return;e.save();let i=o.includes(n.branchMode)?n.branchMode:"random",l=i!=="random";if(e.lineJoin="round",e.lineCap="round",e.lineWidth=2,e.fillStyle="rgba(18,21,26,.94)",e.strokeStyle=l?y.warn:y.green,e.lineWidth=4,ee(e,t.x-18,t.y-18,36,36,!0,!0),e.strokeStyle="#ffd36a",e.lineWidth=3,e.fillStyle="#020304",i!=="random"){let c=de.find(b=>b.name===i);Sn(e,t.x,t.y,c?.angle||0,9,6)}else e.beginPath(),e.moveTo(t.x-10,t.y),e.lineTo(t.x-2,t.y),e.lineTo(t.x+8,t.y-8),e.moveTo(t.x-2,t.y),e.lineTo(t.x+8,t.y+8),e.stroke(),Sn(e,t.x+9,t.y-9,-Math.PI/4,4,3),Sn(e,t.x+9,t.y+9,Math.PI/4,4,3);e.restore()}function qa(e,t,n){if(!n)return[];let o=te(t),r=de.filter(c=>e.conveyorTiles.has(I(o.col+c.dc,o.row+c.dr))).map(c=>c.name),i=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(c=>r.includes(c));return Ua(e,t,i.length?i:Ka(e,t,n),r,n.branchMode||"random").map(c=>de.find(b=>b.name===c)).filter(Boolean)}function Ya(e){let t=new Map;for(let[n,o]of e.conveyorMeta||[]){let r=qa(e,n,o);r.length&&t.set(n,r)}return t}function Va(e,t,n){let o=n.slice(0,4);o.length&&(e.save(),e.globalAlpha=1,o.forEach(r=>{let i=t.x+r.dc*11,l=t.y+r.dr*11;e.fillStyle="rgba(255,205,83,.96)",Sn(e,i,l,r.angle,9,7),e.fillStyle="#020304",Sn(e,i,l,r.angle,6.5,4.6)}),e.restore())}function Sn(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 za(e,t,n,o,r){let i=ye(t),l=null;if(n==="inputA"&&(l={x:i.x,y:i.y-67}),n==="left"&&(l={x:i.x-49,y:i.y+14}),n==="right"&&(l={x:i.x+49,y:i.y+14}),!l)return;let c=n==="inputA"?{x:o.x,y:l.y}:{x:l.x,y:o.y};e.save(),e.lineCap="square",e.lineJoin="bevel",e.strokeStyle="#050609",e.lineWidth=15,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.strokeStyle="#596473",e.lineWidth=9,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.strokeStyle=r||"#7b8795",e.lineWidth=3,e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(c.x,c.y),e.lineTo(l.x,l.y),e.stroke(),e.fillStyle=r||"#7b8795",e.strokeStyle="#050609",e.lineWidth=3,ee(e,l.x-9,l.y-7,18,14,!0,!0),e.restore()}function Xa(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=Io(n),r=[{type:"inputA",p:Re(n,"inputA"),label:"IN",color:y.green},{type:"left",p:Re(n,"left"),label:$o(o.left),color:Fo(o.left)},{type:"right",p:Re(n,"right"),label:$o(o.right),color:Fo(o.right)}];for(let i of r){if(!i.p)continue;let l=F(i.p.col,i.p.row);za(e,n,i.type,l,i.color);let c=ai(t,n,i.type||(i.label==="IN"?"inputA":null))||t.conveyorTiles.has(I(i.p.col,i.p.row));e.fillStyle=c?Ht("#1a1d23",i.color,.24):"#3a1e22",e.strokeStyle=c?i.color:y.danger,ee(e,l.x-18,l.y-12,36,24,!0,!0),e.fillStyle=y.white,e.fillText(i.label,l.x,l.y+4)}}e.restore()}function Qa(e,t){for(let n of t.eggFarms)Ja(e,n,t)}function Ja(e,t,n){let o=F(t.col,t.row);if(e.save(),vt(e,ue.eggFarm,o.x-29,o.y-29,58,58)){ot(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=y.ink,e.lineWidth=2,ee(e,o.x+9,o.y+12,30,18,!0,!0),e.fillStyle=y.ink,e.font="900 10px ui-monospace, monospace",e.textAlign="center",e.fillText(`O${l}`,o.x+24,o.y+24),rt(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore();return}e.fillStyle=y.white,e.strokeStyle=y.ink,e.lineWidth=4,ee(e,o.x-28,o.y-28,56,56,!0,!0),e.fillStyle=y.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=y.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=y.ink,ee(e,o.x-28,o.y-28,56,l,!0,!1),e.strokeStyle=y.white,e.lineWidth=2;for(let c=o.y-24;c=1&&(e.fillStyle=y.white,e.font="900 12px ui-monospace, monospace",e.fillText("SHUT",o.x,o.y+4))}ot(e,o.x-28,o.y-28,56,56,t),rt(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore()}function ja(e,t){for(let n of t.scanners)Za(e,n,t)}function Za(e,t,n){let o=ye(t);if(e.save(),t.kind==="manual"&&(n.manualCombo?.count||0)>=10){let b=n.manualCombo.count;e.save(),e.globalAlpha=Math.min(.55,.16+b/120),e.strokeStyle=b>=30?y.warn:y.green,e.lineWidth=Math.min(14,5+Math.floor(b/10)),e.shadowColor=e.strokeStyle,e.shadowBlur=Math.min(28,8+b),ee(e,o.x-54,o.y-76,108,152,!1,!0),e.restore()}let r=t.kind==="auto"?ue.scannerAuto:ue.scannerManual;if(vt(e,r,o.x-50,o.y-73,100,146)){t.kind==="auto"?ot(e,o.x-50,o.y-73,100,146,t):Ss(e,t,o),rt(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore();return}e.fillStyle=t.kind==="auto"?"#d8ffe2":y.white,e.strokeStyle=y.ink,e.lineWidth=4,ee(e,o.x-50,o.y-73,100,146,!0,!0),e.fillStyle=t.kind==="auto"?y.green:y.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-48),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-28);let c=t.queue.length;t.kind==="manual"?(Ss(e,t,o),e.fillStyle=c>0?y.green:y.muted,e.font="900 10px ui-monospace, monospace",e.fillText(`Q:${c}`,o.x,o.y+54)):(e.fillStyle=c>0?y.green:y.muted,e.font="900 12px ui-monospace, monospace",e.fillText(`Q:${c} CD:${t.cooldown.toFixed(1)}`,o.x,o.y+54),ot(e,o.x-50,o.y-73,100,146,t)),rt(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore()}function Ss(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,c=n.y+18;e.save(),e.lineWidth=3,e.fillStyle="#f7fff5",e.strokeStyle=y.ink,ee(e,l-4,c-4,68,25,!0,!0),e.font="900 19px ui-monospace, monospace",e.textAlign="center";for(let b=0;b.8,i=t.y+Math.sin(t.bob)*(r?5:1.5);if(e.save(),n&&(e.strokeStyle=y.green,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius+8,0,Math.PI*2),e.stroke()),r&&(e.strokeStyle=y.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")mr(e,t.x,i,t.radius);else{let l=t.sex==="male"?ue.chickMale:ue.chickFemale;if(!vt(e,l,t.x-t.radius,i-t.radius,t.radius*2,t.radius*2)){let C=t.sex==="male"?y.male:y.female,x=t.sex==="male"?"#164f8f":"#8b2252";e.fillStyle=C,e.strokeStyle=y.ink,e.lineWidth=5,e.beginPath(),e.arc(t.x,i,t.radius,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle="rgba(255,255,255,.24)",e.beginPath(),e.arc(t.x-5,i-7,t.radius*.36,0,Math.PI*2),e.fill(),e.fillStyle=y.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.strokeStyle=x,e.lineWidth=3,t.sex==="male"?(e.beginPath(),e.moveTo(t.x-8,i-t.radius-2),e.lineTo(t.x+8,i-t.radius-2),e.stroke()):(e.beginPath(),e.moveTo(t.x-9,i-t.radius+2),e.lineTo(t.x,i-t.radius-6),e.lineTo(t.x+9,i-t.radius+2),e.stroke())}e.fillStyle=t.sex==="male"?"#dff1ff":"#fff0f7",e.strokeStyle="#050609",e.lineWidth=3,e.font=`900 ${Math.max(10,Math.round(t.radius*.72))}px ui-monospace, monospace`,e.textAlign="center";let b=t.sex==="male"?"\u2642":"\u2640";e.strokeText(b,t.x+t.radius*.54,i+t.radius*.7),e.fillText(b,t.x+t.radius*.54,i+t.radius*.7)}e.restore()}function uc(e,t){let n=null,o=1/0;for(let[r,i]of e.componentLookup.entries()){let l=te(r),c=F(l.col,l.row),b=Math.hypot(t.x-c.x,t.y-c.y);bks(o.type,o.id)===ks(t,n))}function rt(e,t,n,o,r,i,l,c){dc(t,n,o)&&(e.save(),e.fillStyle="rgba(34,185,79,.18)",e.strokeStyle=y.green,e.lineWidth=(t.multiSelected||[]).length>1?6:4,e.setLineDash((t.multiSelected||[]).length>1?[]:[8,5]),ee(e,r-l/2,i-c/2,l,c,!0,!0),e.restore())}function fc(e,t,n,o){if(t.phase==="build"&&(t.multiSelected||[]).length>1){e.save(),e.fillStyle="rgba(255,255,255,.96)",e.strokeStyle=y.ink,e.lineWidth=3,ee(e,54-t.view.x,66-t.view.y,214,42,!0,!0),e.fillStyle=y.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=y.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 pc(e,t,n){if(!n.cardTargetPick?.pending)return;let o=ar(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 C of o){let x=C.bounds,A=8;e.rect(x.x-A,x.y-A,x.w+A*2,x.h+A*2)}e.fill("evenodd");let i=n.cardTargetPick?.mode==="blockedCell";if(!o.length){e.fillStyle="rgba(255,255,255,.95)",e.strokeStyle=y.ink,e.lineWidth=3,ee(e,(260-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,420/r,42/r,!0,!0),e.fillStyle=y.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=y.ink,e.lineWidth=3;let l=Math.max(1,n.cardTargetPick?.remaining||1),c=Math.max(0,n.cardTargetPick?.used||0),b=n.cardTargetPick?.mode==="autoScannerMenu"?"AUTO SCANNER ROUTE SETTINGS. CLICK EMPTY AREA TO CLOSE.":i?`DYNAMITE: CLICK ANY BLOCKED TILE (${l} LEFT). ESC ${c>0?"FINISHES":"CANCELS"}.`:"CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.";ee(e,(216-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,560/r,42/r,!0,!0),e.fillStyle=y.ink,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(b,(496-(n.view?.x||0))/r,(122-(n.view?.y||0))/r),e.restore()}function yc(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=y.green,e.lineWidth=2,e.setLineDash([7,4]),ee(e,o,r,i,l,!0,!0),e.restore()}function hc(e,t){let n=[...t.effects].sort((o,r)=>(o.priority??Ce.ambient)-(r.priority??Ce.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=y.green,ee(e,o.x-o.size/2,o.y-o.size/2,o.size*1.5,o.size,!0,!1)):o.type==="sludge"?(e.fillStyle=y.poop,ee(e,o.x-o.size/2,o.y-o.size/2,o.size*1.4,o.size,!0,!1)):o.type==="spawn"?(e.strokeStyle=y.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||y.danger,ee(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||y.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||y.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||y.ink,e.save(),e.translate(o.x,o.y),e.rotate(o.rot||0),ee(e,-o.w/2,-o.h/2,o.w,o.h,!0,!1),e.restore()):o.type==="load"?(e.strokeStyle=o.color||y.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=y.ink,e.lineWidth=3,e.setLineDash([4,4]),ee(e,o.x-o.size/2,o.y-o.size/2,o.size,o.size,!1,!0)):o.type==="rage"?(e.fillStyle=o.color||y.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText("!",o.x,o.y)):o.type==="flyingChick"&&(o.sex==="poop"?mr(e,o.x,o.y,o.radius||11):br(e,o.x,o.y,o.sex,o.sex==="male")),e.restore()}}function mc(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=y.white,e.fillStyle=n.color,e.strokeText(n.text,n.x,n.y),e.fillText(n.text,n.x,n.y)}e.restore()}function bc(e,t){let n=t.repairmen&&t.repairmen.length?t.repairmen:t.repairman?[t.repairman]:[];for(let o of n)vc(e,t,o)}function vc(e,t,n){if(!!!n?.active)return;if(e.save(),vt(e,ue.repairman,n.x-18,n.y-18,36,36)){n.target?.label&&ur(e,n.x,n.y-24,n.target.label,y.green),e.restore();return}e.lineWidth=3,e.fillStyle="#fff0d1",e.strokeStyle=y.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?y.danger:y.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=y.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=y.green,ee(e,n.x-9,n.y+14,18,8,!0,!0),e.strokeStyle=y.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=y.ink,e.font="900 11px ui-monospace, monospace",e.textAlign="center",e.fillText("FIX",n.x,n.y+33),n.target?.label&&ur(e,n.x,n.y-24,n.target.label,y.green),e.restore()}function wc(e,t,n){e.save(),e.font="900 19px ui-monospace, monospace",e.textAlign="left",e.fillStyle=y.ink,e.font="900 19px ui-monospace, monospace",e.fillStyle=y.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=y.white,e.lineWidth=4,e.strokeText(i,24,r),e.fillText(i,24,r),r+=20;e.restore()}var Es=[[{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 Sc(e){let t=Es[e]||Es[0];return{left:{...t[0]},right:{...t[1]}}}function Rs(e,t,n){let o={type:"eggFarm",id:e.nextId++,col:t,row:n,level:1,nextSpawn:2,lastInterval:2,extraEggOutlet:0,price:lt.eggFarm,builtSession:e.buildSession};return o.nextSpawn=Rt(o),o.lastInterval=o.nextSpawn,o}function Ps(e,t,n,o){let r=o==="auto"?ve.autoScanner.price:ve.manualScanner.price,i=new Set(e.scanners.filter(c=>c.kind==="manual").map(c=>c.slot)),l=0;for(;i.has(l);)l+=1;return{type:"scanner",id:e.nextId++,kind:o,slot:o==="manual"?l:null,role:o==="manual"?l%2:0,col:t,row:n,level:1,queue:[],cooldown:0,price:r,builtSession:e.buildSession,autoMode:"standard",keys:o==="manual"?Sc(l):null}}function Jn(e){let t=(e.x-f.x)/f.cell,n=(e.y-f.y)/f.cell,o=Math.max(0,Math.min(f.cols-1,Math.round(t-.5))),r=Math.max(0,Math.min(f.rows-1,Math.round(n-.5))),i=Math.abs(e.x-f.x),l=Math.abs(e.x-(f.x+f.cols*f.cell)),c=Math.abs(e.y-f.y),b=Math.abs(e.y-(f.y+f.rows*f.cell)),C=[["left",i],["right",l],["top",c],["bottom",b]].sort((x,A)=>x[1]-A[1])[0][0];return C==="left"?{side:C,entry:{col:0,row:r}}:C==="right"?{side:C,entry:{col:f.cols-1,row:r}}:C==="top"?{side:C,entry:{col:o,row:0}}:{side:C,entry:{col:o,row:f.rows-1}}}function jn(e,t,n){let o={x:f.x+t.col*f.cell+f.cell/2,y:f.y+t.row*f.cell+f.cell/2},r={left:f.x,right:f.x+f.cols*f.cell,top:f.y,bottom:f.y+f.rows*f.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 As(e,t,n,o){let{entry:r,side:i}=Jn(n),l=ve[t],c=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},b={type:"facility",id:t,name:c.name,x:0,y:0,w:c.w,h:c.h,level:1,price:o||c.price,builtSession:e.buildSession};return jn(b,r,i)}function jt(e){return e?[{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function Is(e,t,n){return{type:"maintenanceRoom",id:e.nextId++,col:t,row:n,price:lt.maintenanceRoom,builtSession:e.buildSession,wCells:2,hCells:2}}function kc(e){return Math.random()({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 $s({game:e,canvasPoint:t,updatePanels:n,equipmentAtPoint:o,fail:r,pointInGrid:i,rectOfFacility:l,rectsOverlap:c}){function b(M){return M?M.type==="conveyor"?`conveyor:${M.id||M.oldKey}`:M.type==="facility"?`facility:${M.id||M.ref?.id}`:M.type==="maintenanceRoom"?`maintenanceRoom:${M.id||M.ref?.id}`:`${M.type}:${M.id||M.ref?.id}`:""}function C(M){return M?M.type==="conveyor"?{type:"conveyor",id:M.oldKey}:{type:M.type,id:M.ref.id}:null}function x(M){let g=b(C(M));return(e.multiSelected||[]).some(G=>b(G)===g)}function A(M){return M?M.type==="eggFarm"?e.eggFarms.find(g=>g.id===M.id)||null:M.type==="scanner"?e.scanners.find(g=>g.id===M.id)||null:M.type==="facility"?e.facilities[M.id]||null:M.type==="maintenanceRoom"?(e.maintenanceRooms||[]).find(g=>g.id===M.id)||null:M.type==="conveyor"&&e.conveyorTiles.has(M.id)?{type:"conveyor",id:M.id}:null:null}function $(){let M=[];for(let g of e.conveyorTiles){let G=te(g),oe=F(G.col,G.row);M.push({type:"conveyor",id:g,center:oe,cell:G})}for(let g of e.eggFarms)M.push({type:"eggFarm",id:g.id,ref:g,center:F(g.col,g.row),cell:{col:g.col,row:g.row}});for(let g of e.scanners)M.push({type:"scanner",id:g.id,ref:g,center:ye(g),cell:{col:g.col,row:g.row}});for(let g of e.maintenanceRooms||[]){let G=F(g.col,g.row);M.push({type:"maintenanceRoom",id:g.id,ref:g,center:{x:G.x+f.cell/2,y:G.y+f.cell/2},cell:{col:g.col,row:g.row}})}for(let g of Object.values(e.facilities)){let G={x:g.x+g.w/2,y:g.y+g.h/2},oe=g.entry?F(g.entry.col,g.entry.row):G;M.push({type:"facility",id:g.id,ref:g,center:G,portCenter:oe})}return M}function B(M,g){let G=Math.min(g.x1,g.x2),oe=Math.max(g.x1,g.x2),Z=Math.min(g.y1,g.y2),me=Math.max(g.y1,g.y2);return M.x>=G&&M.x<=oe&&M.y>=Z&&M.y<=me}function j(M){let g=[];for(let G of $())(B(G.center,M)||G.portCenter&&B(G.portCenter,M))&&g.push({type:G.type,id:G.id});return e.multiSelected=g,e.selected=g[0]||null,n(),g.length}function z(){e.multiSelected=[],e.selected=null,n()}function ce(M){let g=t(M);return e.selectionBox={x1:g.x,y1:g.y,x2:g.x,y2:g.y},e.multiSelected=[],e.selected=null,n(),!0}function he(M){if(!e.selectionBox)return;let g=t(M);e.selectionBox.x2=g.x,e.selectionBox.y2=g.y}function ie(){if(!e.selectionBox)return 0;let M=e.selectionBox,g=Math.abs(M.x2-M.x1),G=Math.abs(M.y2-M.y1);return e.selectionBox=null,g<6&&G<6?(z(),0):j(M)}function le(M){let g=C(M);return g?(e.multiSelected||[]).length&&x(M)?[...e.multiSelected]:[g]:[]}function se(M){let g=A(M);if(!g)return null;if(M.type==="conveyor"){let G=te(M.id);return{...M,obj:g,oldKey:M.id,currentKey:M.id,meta:e.conveyorMeta.get(M.id)||{price:Oe("conveyor"),builtSession:null},col:G.col,row:G.row}}return M.type==="eggFarm"||M.type==="scanner"||M.type==="maintenanceRoom"?{...M,obj:g,col:g.col,row:g.row}:M.type==="facility"?{...M,obj:g,x:g.x,y:g.y,w:g.w,h:g.h,entry:g.entry?{...g.entry}:null,side:g.side,center:{x:g.x+g.w/2,y:g.y+g.h/2}}:null}function R(M){let g=t(M),G=o(g);if(!G)return!1;let oe=le(G),Z=oe.map(se).filter(Boolean);return Z.length?(e.groupDrag={start:g,selections:oe,origins:Z,historySnapshot:mn(e),committed:!1,lastDCol:0,lastDRow:0},e.multiSelected=oe,e.selected=oe[0]||null,n(),!0):!1}function _(){!e.groupDrag||e.groupDrag.committed||(e.undoStack.push(e.groupDrag.historySnapshot),e.redoStack=[],e.groupDrag.committed=!0)}function Y(M,g,G){let oe=I(M,g),Z=dt(e,M,g);if(Z&&!G.has(`eggFarm:${Z.id}`))return!0;let me=ft(e,M,g);if(me&&!G.has(`scanner:${me.id}`))return!0;let ge=(e.maintenanceRooms||[]).find(Pe=>jt(Pe).some(Ae=>Ae.col===M&&Ae.row===g));return!!(ge&&!G.has(`maintenanceRoom:${ge.id}`)||e.conveyorTiles.has(oe)&&!G.has(`conveyor:${oe}`))}function O(M,g,G){let oe=[];for(let Z of e.groupDrag.origins){if(Z.type!=="facility")continue;let me={x:Z.center.x+M,y:Z.center.y+g},{entry:ge,side:Pe}=Jn(me);if(!i(ge.col,ge.row)||e.blockedCells?.has?.(I(ge.col,ge.row)))return!0;let Ae={...Z.obj,entry:{...ge},side:Pe};jn(Ae,ge,Pe),oe.push({id:Z.id,rect:l(Ae)})}for(let Z of oe)for(let me of Object.values(e.facilities))if(!G.has(`facility:${me.id}`)&&c(Z.rect,l(me),12))return!0;for(let Z=0;ZN.type==="conveyor");for(let N of Ae){let Ie=N.currentKey||N.oldKey;e.conveyorTiles.delete(Ie),e.conveyorMeta.delete(Ie)}for(let N of Ae){let Ie=I(N.col+Z,N.row+me);e.conveyorTiles.add(Ie),e.conveyorMeta.set(Ie,N.meta||{price:Oe("conveyor"),builtSession:null,uses:0}),N.currentKey=Ie}for(let N of e.groupDrag.origins)if(N.type==="eggFarm")N.obj.col=N.col+Z,N.obj.row=N.row+me;else if(N.type==="scanner")N.obj.col=N.col+Z,N.obj.row=N.row+me;else if(N.type==="maintenanceRoom")N.obj.col=N.col+Z,N.obj.row=N.row+me;else if(N.type==="facility"){let Ie={x:N.center.x+G,y:N.center.y+oe},{entry:Ye,side:Ve}=Jn(Ie);jn(N.obj,Ye,Ve)}e.groupDrag.selections=e.groupDrag.origins.map(N=>N.type==="conveyor"?{type:"conveyor",id:N.currentKey||N.oldKey}:{type:N.type,id:N.id}),e.multiSelected=[...e.groupDrag.selections],e.selected=e.multiSelected[0]||null,be(e),n()}function U(){e.groupDrag&&(be(e),e.groupDrag=null,n())}return{selectionFromHit:C,startSelectionBox:ce,updateSelectionBox:he,finishSelectionBox:ie,startGroupDrag:R,updateGroupDrag:W,finishGroupDrag:U}}function Fs({game:e,ui:t,canvas:n,canvasPoint:o,onUpdatePanels:r}){function i(){r&&r()}let l=null,c=!1,b=null,C=!1,x=["random","up","right","down","left"],A={random:"RND",up:"UP",right:"RT",down:"DN",left:"LF"},$={w:40,h:40,y:0};function B(){return In(e)}function j(){e.gridCols=f.cols,e.gridRows=f.rows,e.gridOwnedCells=zr(e)}function z(s){if(s){f.y-=s*f.cell,f.rows+=s,e.gridChunkOriginY=(e.gridChunkOriginY||0)-Math.floor(s/10),e.ownedCells=Dn(e.ownedCells,s),e.blockedCells=Dn(e.blockedCells,s),e.conveyorTiles=Dn(e.conveyorTiles,s),e.conveyorMeta=jr(e.conveyorMeta,s);for(let a of e.eggFarms||[])a.row+=s;for(let a of e.scanners||[])a.row+=s;for(let a of Object.values(e.facilities||{}))a.entry&&(a.entry.row+=s)}}function ce(s){e.ownedCells=e.ownedCells||new Set;for(let a of Jr(s))e.ownedCells.add(I(a.col,a.row))}function he(s){return e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending?null:Tt(e).find(a=>a&&Qr(a,s))||null}function ie(s="right"){if(s&&typeof s=="object"&&Number.isFinite(s.chunkX)&&Number.isFinite(s.chunkY))return s;let a=["right","up"].includes(s)?s:"right";return Xr(e,a)}function le(s="right"){let a=ie(s);if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return{ok:!1,reason:"Cannot expand now."};if(!a)return{ok:!1,reason:"Invalid expansion lot."};let h=a.direction||"right",m=B();if(e.cashf.cols&&(f.cols=E.colStart+E.cols),E.rowStart+E.rows>f.rows&&(f.rows=E.rowStart+E.rows),ce(E),Zr(e,E.chunkX,E.chunkY),e.gridExpansionPurchases=(e.gridExpansionPurchases||0)+1,e.gridExpansionPurchasesByDirection[h]=(e.gridExpansionPurchasesByDirection[h]||0)+1,j();let ne=Ur(e.gridExpansionPurchases,{base:q.map.blockedRatio??.03,increment:q.map.blockedExpansionIncrement??.005,max:q.map.blockedRatioMax??.1}),J=Kr({seed:`${e.runSeed}:grid-expansion:${E.chunkX},${E.chunkY}:${e.gridExpansionPurchases}`,colStart:E.colStart,colEnd:E.colStart+E.cols,rowStart:E.rowStart,rowEnd:E.rowStart+E.rows,targetRatio:ne});for(let Je of J)e.blockedCells.add(Je);be(e);let pe=E.cols*E.rows,Te=Et(E);return H(e,Te.x+Te.w/2,Te.y+Te.h/2,`${h.toUpperCase()} +${pe} CELLS -${T(m)}`,y.green),i(),{ok:!0,direction:h,cost:m,addedCells:pe,blocked:J.size,blockedRatio:ne,chunkX:E.chunkX,chunkY:E.chunkY}}function se(s,a){return s>=0&&s=0&&a!a.has(m.id)&&Y(h,_(m),12))}function W(s,a,h=null){if(!se(s,a))return!1;if(R(s,a))return!0;let m=I(s,a),w=dt(e,s,a);if(w&&!(h?.type==="eggFarm"&&h.ref?.id===w.id))return!0;let E=ft(e,s,a);if(E&&!(h?.type==="scanner"&&h.ref?.id===E.id))return!0;let ne=U(e,s,a);return!!(ne&&!(h?.type==="maintenanceRoom"&&h.ref?.id===ne.id)||e.conveyorTiles.has(m)&&!(h?.type==="conveyor"&&h.oldKey===m))}function U(s,a,h){return(s.maintenanceRooms||[]).find(m=>jt(m).some(w=>w.col===a&&w.row===h))||null}function M(s,a,h=null){let m={col:s,row:a};for(let w of jt(m)){if(!se(w.col,w.row)||R(w.col,w.row))return!0;let E=I(w.col,w.row);if(dt(e,w.col,w.row)||ft(e,w.col,w.row))return!0;let pe=U(e,w.col,w.row);if(pe&&!(h?.type==="maintenanceRoom"&&h.ref?.id===pe.id)||e.conveyorTiles.has(E))return!0}return!1}function g(s,a,h=null){let m={col:s,row:a};for(let w of Pt(m)){if(!se(w.col,w.row)||R(w.col,w.row))return!0;let E=I(w.col,w.row);if(dt(e,w.col,w.row))return!0;let J=ft(e,w.col,w.row);if(J&&!(h?.type==="scanner"&&h.ref?.id===J.id)||e.conveyorTiles.has(E))return!0}return!1}function G(){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:e.selected.type==="maintenanceRoom"&&(e.maintenanceRooms||[]).find(s=>s.id===e.selected.id)||null:null}function oe(s){return s?s.type==="eggFarm"?`${ct("eggFarm")} #${s.id}`:s.type==="scanner"?`${s.kind==="auto"?ct("autoScanner"):ct("manualScanner")} #${s.id}`:s.type==="conveyor"?e.conveyorMeta.get(s.id)?.kind==="boostConveyor"?ct("boostConveyor"):ct("conveyor"):s.type==="facility"?s.name:s.type==="maintenanceRoom"?`${ct("maintenanceRoom")} #${s.id}`:"Equipment":"Equipment"}function Z(s){return s?.type==="conveyor"?e.conveyorMeta?.get(s.oldKey||s.ref?.id)?.price||_n(s):_n(s)}function me(){return!!e.cardEffects?.usedMachineActive}function ge(){return me()?{usedMachine:!0,noRefund:!0,durabilityBaseMultiplier:.6}:{usedMachine:!1,noRefund:!1,durabilityBaseMultiplier:1}}function Pe(s){let a=ge();return Object.assign(s,a),s}function Ae(s){let a=s?.ref||s||{};if(s?.type==="eggFarm"||a.type==="eggFarm")return e.eggFarms.length<=1?"Cannot sell the last EGG FARM.":"";if((s?.type==="facility"||a.type==="facility")&&["mixer","trash","truck"].includes(a.baseId||a.id)){let h=a.baseId||a.id;if(Object.values(e.facilities).filter(w=>(w.baseId||w.id)===h).length<=1)return`Cannot sell the last ${a.shortName||a.name||a.id}.`}return""}function N(s){t.buildStatus.textContent=s,H(e,n.width/2-e.view.x,86-e.view.y,s.toUpperCase(),y.danger)}function Ie(s){if(!s)return null;let a=I(s.col,s.row);return e.conveyorMeta.get(a)||null}function Ye(s){return s?(Array.isArray(s.outDirs)||(s.outDirs=[]),s.outDirs=[...new Set(s.outDirs.filter(a=>["right","left","down","up"].includes(a)))],x.includes(s.branchMode)||(s.branchMode="random"),s.kind||(s.kind="conveyor"),s.speedMultiplier||(s.speedMultiplier=s.kind==="boostConveyor"?2:1),s.outDirs):[]}function Ve(s){return s?de.filter(a=>e.conveyorTiles.has(I(s.col+a.dc,s.row+a.dr))).map(a=>a.name):[]}function xe(s){return Ve(s).length>=3}function Ct(s,a){let h=de.find(J=>J.name===a);if(!s||!h)return!1;let m=I(s.col+h.dc,s.row+h.dr),w=e.conveyorMeta.get(m);if(!w)return!1;let E=h.opposite;return[...new Set([...Array.isArray(w.outDirs)?w.outDirs:[],w.dir].filter(Boolean))].includes(E)}function oo(s){if(!e.conveyorTiles.has(s))return[];let a=te(s),h=e.conveyorMeta.get(s),m=Ye(h),w=Ve(a),E=[...new Set([...m,h?.dir].filter(Boolean))].filter(pe=>w.includes(pe)),ne=w,J=E.length?E:ne;return h&&(h.outDirs=m.filter(pe=>w.includes(pe)),h.dir&&!w.includes(h.dir)&&(h.dir=h.outDirs[0]||null),h.branchMode!=="random"&&!w.includes(h.branchMode)&&(h.branchMode="random")),J}function Mn(s){if(!e.conveyorTiles.has(s))return[];let a=te(s),h=Ve(a);return xe(a)||h.length?h:oo(s)}function ro(s){let a=te(s),h=Mn(s);if(h.length<3)return[];let m=e.conveyorMeta.get(s)||{},w=new Set(h.filter(J=>Ct(a,J))),E=h.filter(J=>!w.has(J));if(w.size&&E.length>=2)return E;let ne=[...new Set([...Array.isArray(m.outDirs)?m.outDirs:[],m.dir].filter(Boolean))].filter(J=>h.includes(J));return ne.length>=2?ne:h}function nn(s,a){let h=at(s,a);if(!h)return!1;let m=I(s.col,s.row),w=I(a.col,a.row),E=e.conveyorMeta.get(m),ne=e.conveyorMeta.get(w);if(!E||!ne)return!1;let J=Ye(E),pe=!J.includes(h)||E.dir!==h||!ne.dir;return J.includes(h)||J.push(h),E.dir=h,ne.dir||(ne.dir=h),pe}function Mt(s){let a=so(s);return a.length<2?io(s):(Be(e),lo(a),be(e),i(),!0)}function io(s){if(!s)return!1;let a=I(s.col,s.row),h=e.conveyorMeta.get(a);if(!h||xe(s))return!1;let m=de.map(ne=>ne.name),w=h.dir&&m.includes(h.dir)?h.dir:null,E=m[(Math.max(-1,m.indexOf(w))+1)%m.length];return Be(e),h.dir=E,h.outDirs=[E],h.branchMode="random",be(e),i(),!0}function gn(s){return s?de.map(a=>({col:s.col+a.dc,row:s.row+a.dr})).filter(a=>e.conveyorTiles.has(I(a.col,a.row))):[]}function so(s){if(!s||!e.conveyorTiles.has(I(s.col,s.row))||xe(s))return[];let a=gn(s);if(!a.length||a.length>2)return[];let h=E=>{let ne=[],J=new Set([I(s.col,s.row)]),pe=s,Te=E,Je=0;for(;Te&&Je<200;){Je+=1;let Tr=I(Te.col,Te.row);if(J.has(Tr)||(J.add(Tr),ne.push(Te),xe(Te)))break;let Er=gn(Te).filter(Rr=>!(Rr.col===pe.col&&Rr.row===pe.row));if(Er.length!==1)break;pe=Te,Te=Er[0]}return ne},m=a[0]?h(a[0]).reverse():[],w=a[1]?h(a[1]):[];return[...m,s,...w]}function gt(s,a){return!!s&&[...new Set([...Array.isArray(s.outDirs)?s.outDirs:[],s.dir].filter(Boolean))].includes(a)}function lo(s){let a=0,h=0;for(let w=0;wh?[...s].reverse():s;for(let w=0;w=Math.abs(m)?{col:s.col+Math.sign(h),row:s.row}:{col:s.col,row:s.row+Math.sign(m)}}function ao(s){c=!1,b=s?{col:s.col,row:s.row}:null,C=!1,l=null,on(s)}function d(s){if(!s)return;if(!l)return on(s);let a=l,h=0;for(;(a.col!==s.col||a.row!==s.row)&&h<64;){let m=rn(a,s);if(on(m),a=l||m,h+=1,!l)break}}function p(){!C&&b&&e.conveyorTiles.has(I(b.col,b.row))&&Mt(b),b=null,C=!1,l=null,c=!1}function v(s){if(!s)return N(re.fail.outOfGrid);let{col:a,row:h}=s;if(e.buildTool==="conveyor"||e.buildTool==="boostConveyor"){let m=Gt(s,null);if(!m.ok)return N(m.reason||re.fail.cellOccupied);be(e);return}if(R(a,h))return N("Cannot build on blocked ground.");if(e.buildTool==="maintenanceRoom")return M(a,h)?N(re.fail.cellOccupied):D(a,h);if(e.buildTool==="manualScanner"||e.buildTool==="autoScanner"?g(a,h):W(a,h))return N(re.fail.cellOccupied);e.buildTool==="eggFarm"?S(a,h):e.buildTool==="manualScanner"?P(a,h,"manual"):e.buildTool==="autoScanner"&&P(a,h,"auto")}function k(s){let a=He(s.x,s.y);if(["conveyor","boostConveyor","eggFarm","manualScanner","autoScanner","maintenanceRoom"].includes(e.buildTool))return v(a);if(un.includes(e.buildTool))return ae(s,e.buildTool)}function S(s,a){let h=Oe("eggFarm",e);if(e.cashE.kind==="manual").length>=8)return N("Manual Scanner limit reached (8 max).");let m=h==="auto"?Oe("autoScanner",e):Oe("manualScanner",e);if(e.cashw.id!==a.ref.id),et(e,m.x,m.y),be(e)}if(a.type==="scanner"){let m=ye(a.ref);Ne(a,m.x,m.y),e.scanners=e.scanners.filter(w=>w.id!==a.ref.id),et(e,m.x,m.y),be(e)}if(a.type==="facility"){let m=a.ref;Ne(a,m.x+m.w/2,m.y+m.h/2),delete e.facilities[m.id],et(e,m.x+m.w/2,m.y+m.h/2),be(e)}if(a.type==="maintenanceRoom"){let m=a.ref,w=V(m);Ne(a,w.x,w.y),e.maintenanceRooms=(e.maintenanceRooms||[]).filter(E=>E.id!==m.id),et(e,w.x,w.y)}e.selected=null,e.multiSelected=[],i()}function co(s){let a=Object.values(e.facilities).find(J=>{if(s.x>=J.x&&s.x<=J.x+J.w&&s.y>=J.y&&s.y<=J.y+J.h)return!0;if(!J.entry)return!1;let Te=F(J.entry.col,J.entry.row);return Math.abs(s.x-Te.x)<=f.cell*.46&&Math.abs(s.y-Te.y)<=f.cell*.46});if(a)return{type:"facility",ref:a};let h=He(s.x,s.y);if(!h)return null;let m=dt(e,h.col,h.row);if(m)return{type:"eggFarm",ref:m};let w=ft(e,h.col,h.row);if(w)return{type:"scanner",ref:w};let E=U(e,h.col,h.row);if(E)return{type:"maintenanceRoom",ref:E};let ne=I(h.col,h.row);return e.conveyorTiles.has(ne)?{type:"conveyor",oldKey:ne,ref:{type:"conveyor",id:ne}}:null}let Wt=$s({game:e,canvasPoint:o,updatePanels:i,equipmentAtPoint:co,fail:N,pointInGrid:se,rectOfFacility:_,rectsOverlap:Y});function js(s){return null}function wr(){let s=G();s&&(s.type==="conveyor"?Ut(F(...Object.values(te(s.id)))):s.type==="eggFarm"?Ut(F(s.col,s.row)):s.type==="scanner"?Ut(ye(s)):s.type==="facility"?Ut({x:s.x+s.w/2,y:s.y+s.h/2}):s.type==="maintenanceRoom"&&Ut(V(s)))}function Ke(s,a,h="primary-button"){let m=document.createElement("button");return m.type="button",m.className=h,m.textContent=s,m.addEventListener("click",a),m}function sn(){e.cardTargetPick?.mode==="autoScannerMenu"&&(e.cardTargetPick=null),t.modal.classList.remove("visible","equipment-popover"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function uo(s){t.modalTitle.textContent="Auto Scanner",e.cardTargetPick={pending:!0,mode:"autoScannerMenu",cardId:null,targetKeys:[`scanner:${s.id}`],remaining:1},t.modalBody.innerHTML=` +
+

Left / right output routing for this AUTO scanner.

+

Current: ${s.role===0?"Male left / others right":"Poop left / others right"}

+

Cooldown: ${nt(s).toFixed(1)}s.

+
`,t.modalActions.innerHTML="";let a=Ke("Male Left / Others Right",()=>{Be(e),s.role=0,sn(),i()},s.role===0?"facility-action warn":"facility-action"),h=Ke("Poop Left / Others Right",()=>{Be(e),s.role=1,sn(),i()},s.role===1?"facility-action warn":"facility-action");t.modalActions.append(a,h,Ke("Close",sn,"facility-action")),fo(s),t.modal.classList.add("visible","equipment-popover"),i()}function Sr(s){return s?.label||s?.key||"?"}function Zs(s){let a=s.key===" "?"Space":s.key.length===1?s.key.toUpperCase():s.key.replace(/^Arrow/,"");return{key:s.key.toLowerCase(),code:s.code,label:a}}function el(s,a,h){for(let m of e.scanners.filter(w=>w.kind==="manual"))for(let w of["left","right"]){if(m.id===s.id&&w===a)continue;let E=m.keys?.[w];if(E&&(E.code===h.code||E.key===h.key))return!0}return!1}function ln(s,a=""){if(!s||s.kind!=="manual")return;t.modalTitle.textContent=`Manual Scanner #${s.id}`;let h=Sr(s.keys?.left),m=Sr(s.keys?.right),w=tl(s);t.modalBody.innerHTML=` +
+

Left route key: ${h}

+

Right route key: ${m}

+ ${a?`

${a}

`:""} + ${w?`

${w}

`:""} +
`,t.modalActions.innerHTML="",t.modalActions.appendChild(Ke("Set Left Key",()=>kr(s,"left"),"facility-action warn")),t.modalActions.appendChild(Ke("Set Right Key",()=>kr(s,"right"),"facility-action warn")),t.modalActions.appendChild(Ke("Close",sn,"facility-action")),fo(s),t.modal.classList.add("visible","equipment-popover")}function tl(s){let a=[{side:"left",binding:s.keys?.left},{side:"right",binding:s.keys?.right}];if(a[0].binding&&a[1].binding&&(a[0].binding.code===a[1].binding.code||a[0].binding.key===a[1].binding.key))return"Left and right keys conflict.";for(let h of a)if(h.binding)for(let m of e.scanners.filter(w=>w.kind==="manual"&&w.id!==s.id)){if(m.keys?.left&&(m.keys.left.code===h.binding.code||m.keys.left.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} left.`;if(m.keys?.right&&(m.keys.right.code===h.binding.code||m.keys.right.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} right.`}return""}function kr(s,a){t.modalBody.innerHTML=`

Press a key for ${a.toUpperCase()} route.

Esc cancels.

`,t.modalActions.innerHTML="";let h=m=>{if(m.preventDefault(),m.stopPropagation(),window.removeEventListener("keydown",h,!0),m.key==="Escape")return ln(s);let w=Zs(m),E=el(s,a,w);Be(e),s.keys=s.keys||{left:null,right:null},s.keys[a]=w,i(),ln(s,E?`${w.label} assigned, but another scanner already uses it.`:`${a.toUpperCase()} set to ${w.label}.`)};window.addEventListener("keydown",h,!0)}function nl(){let s=G();if(!(!s||s.type!=="scanner"))return s.kind==="auto"?uo(s):ln(s)}function ol(s){if(!s)return{x:80,y:80};if(s.type==="conveyor"){let a=te(s.id);return F(a.col,a.row)}return s.type==="eggFarm"?F(s.col,s.row):s.type==="scanner"?ye(s):s.type==="facility"?{x:s.x+s.w/2,y:s.y+10}:{x:80,y:80}}function fo(s){let a=n.getBoundingClientRect(),h=ol(s),m=e.view?.scale||1,w=a.left+(h.x*m+(e.view?.x||0))/n.width*a.width+18,E=a.top+(h.y*m+(e.view?.y||0))/n.height*a.height-12,ne=Math.max(12,window.innerWidth-274),J=Math.max(12,window.innerHeight-220);t.modal.style.setProperty("--popover-x",`${Math.max(12,Math.min(ne,w))}px`),t.modal.style.setProperty("--popover-y",`${Math.max(12,Math.min(J,E))}px`)}function Cr(){let s=G();if(!s)return;let a=xr(s);if(t.modalTitle.textContent=oe(s),t.modalBody.innerHTML=` +
${a.map(w=>`

${w}

`).join("")}
+ ${["mixer","truck"].includes(s.baseId||s.id)?'

Income/Fine = ceil(base x 1.10^upgrades)

':""}`,t.modalActions.innerHTML="",s.type==="scanner"&&s.kind==="auto"&&t.modalActions.appendChild(Ke("Auto Menu",()=>uo(s),"facility-action warn")),s.type==="scanner"&&s.kind==="manual"&&t.modalActions.appendChild(Ke("Set Keys",()=>ln(s),"facility-action warn")),s.type==="conveyor"&&po(s.id)){let w=e.conveyorMeta.get(s.id)?.branchMode||"random";t.modalActions.appendChild(Ke(`Branch: ${Mr(w)}`,()=>{yo(s.id),e.selected={type:"conveyor",id:s.id},Cr()},"facility-action warn branch-action"))}let h=s.type==="conveyor"?{type:"conveyor",oldKey:s.id,ref:s}:{type:s.type,ref:s},m=Ae(h);if(m){let w=Ke(m,()=>{},"facility-action danger disabled");w.disabled=!0,t.modalActions.appendChild(w)}else{let w=mt(h,e),E=w.sameBuild?`Remove / Refund ${T(w.amount)}`:`Sell ${T(w.amount)}`;t.modalActions.appendChild(Ke(E,()=>{wr(),sn()},"facility-action danger"))}fo(s),t.modal.classList.add("visible","equipment-popover")}function rl(s){e.phase==="build"&&(p(),e.buildTool=e.buildTool===s?null:s,e.selected=null,e.multiSelected=[],e.selectionBox=null,i())}function il(){let s=[];for(let[a,h]of Object.entries(e.facilities))if(s.push({id:`facility:${a}`,price:Z({type:"facility",ref:h}),x:h.x,y:h.y,w:h.w,h:h.h}),h.entry){let m=F(h.entry.col,h.entry.row);s.push({id:`facilityPort:${a}`,price:Z({type:"facility",ref:h}),x:m.x-18,y:m.y-18,w:36,h:36})}for(let a of e.maintenanceRooms||[]){let h=V(a);s.push({id:`maintenanceRoom:${a.id}`,price:Z({type:"maintenanceRoom",ref:a}),x:h.x-f.cell,y:h.y-f.cell,w:f.cell*2,h:f.cell*2})}for(let a of e.eggFarms){let h=F(a.col,a.row);s.push({id:`eggFarm:${a.id}`,price:Z({type:"eggFarm",ref:a}),x:h.x-24,y:h.y-24,w:48,h:48})}for(let a of e.scanners){let h=ye(a);s.push({id:`scanner:${a.id}`,price:Z({type:"scanner",ref:a}),x:h.x-50,y:h.y-73,w:100,h:146})}for(let a of e.conveyorTiles){let h=te(a),m=F(h.col,h.row),w=e.conveyorMeta.get(a)||{};s.push({id:`conveyor:${a}`,price:w.price||Oe(w.kind==="boostConveyor"?"boostConveyor":"conveyor",e),x:m.x-22,y:m.y-22,w:44,h:44})}return s}function Mr(s){return A[s]||A.random}function zc(s){return Mn(s)}function po(s){return e.conveyorTiles.has(s)?xe(te(s)):!1}function gr(s){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return null;for(let a of e.conveyorTiles){if(!po(a))continue;let h=te(a),m=F(h.col,h.row),w=m.x-$.w/2,E=m.y+$.y-$.h/2;if(s.x>=w&&s.x<=w+$.w&&s.y>=E&&s.y<=E+$.h)return a}return null}function sl(s){let a=gr(s);return a?yo(a):!1}function yo(s){let a=e.conveyorMeta.get(s);if(!a)return!1;let h=ro(s);if(h.length<2)return!1;Be(e);let m=x.includes(a.branchMode)?a.branchMode:"random",w=["random",...de.map(E=>E.name).filter(E=>h.includes(E))];return a.branchMode=w[(Math.max(0,w.indexOf(m))+1)%w.length],be(e),e.selected=null,e.multiSelected=[],i(),!0}function xr(s){Se(e);let a=[],h=s?.type==="facility"?s.baseId||s.id:"";if(s.type==="eggFarm"){let[m,w]=fn(s);a.push(`Price: ${T(Z(s))}`);{let E=Ae({type:s.type,ref:s});a.push(E?`Sale: blocked (${E})`:`Sale value: ${T(mt({type:s.type,ref:s},e).amount)}`)}a.push(`Level: ${s.level}/4`),a.push(`Random interval: ${m.toFixed(2)}-${w.toFixed(2)}s`),a.push(`Durability: ${vn(s)}% | Spawn delay x${Yn(s).toFixed(2)}`)}else if(s.type==="scanner")a.push(`Price: ${T(Z(s))}`),a.push(`Sale value: ${T(mt({type:s.type,ref:s},e).amount)}`),a.push(`Type: ${s.kind.toUpperCase()} / Standard`),s.kind==="auto"&&a.push(`Role: ${s.role===0?"Male left / Others right":"Poop left / Others right"}`),a.push(`Queue: ${s.queue.length}`),s.kind==="auto"&&a.push(`Cooldown: ${s.cooldown.toFixed(1)}s / ${nt(s,e).toFixed(1)}s`),s.kind==="auto"&&a.push(`Durability: ${vn(s)}% | Delay x${qn(s).toFixed(2)}`),s.kind==="manual"&&a.push("Durability: none | Always normal");else if(s.type==="conveyor"){let m=e.conveyorMeta.get(s.id),w=e.componentLookup?.get(s.id),E=w?e.congestion.get(w):null;a.push(`Price: ${T(Z({type:"conveyor",oldKey:s.id,ref:s}))}`),a.push(`Cell: ${s.id}`),a.push(`Type: ${m?.kind==="boostConveyor"?"BOOST BELT":"Normal Belt"} | Speed x${Number(m?.speedMultiplier||1).toFixed(1)}`),a.push(`Congestion: ${E?Math.floor(E.ratio*100):0}%`),a.push(`Durability: ${vn({meta:m})}% | Speed x${Hn({meta:m}).toFixed(2)}`),po(s.id)?(a.push(`Branch mode: ${Mr(m?.branchMode||"random")}`),a.push("Click the Branch button or the large on-belt badge to cycle RANDOM / fixed exit.")):a.push("Branch mode: needs 3+ conveyor connections."),a.push(`Sale value: ${T(mt({type:"conveyor",oldKey:s.id,ref:s},e).amount)}`)}else if(s.type==="maintenanceRoom")a.push(`Price: ${T(Z({type:"maintenanceRoom",ref:s}))}`),a.push(`Sale value: ${T(mt({type:"maintenanceRoom",ref:s},e).amount)}`),a.push("Size: 2\xD72 grid cells"),a.push("Dispatch: 1 repairman during each production day");else if(s.type==="facility"){a.push(`Price: ${T(Z(s))}`);{let m=Ae({type:s.type,ref:s});a.push(m?`Sale: blocked (${m})`:`Sale value: ${T(mt({type:s.type,ref:s},e).amount)}`)}if(a.push(["mixer","truck","trash"].includes(s.id)?`Level: ${s.level} / no cap`:`Level: ${s.level}`),h==="truck"&&a.push("Durability: none | Always normal"),["mixer","trash"].includes(h)&&a.push(`Durability: ${vn(s)}% | Extra delay ${er(e,s).toFixed(2)}s`),h==="mixer"&&(a.push(`Income: ${T(ze(e))} per chick | upgrade x${yt(e,"mixer").toFixed(3)}`),a.push(`Poop fine: -${T(yn(e))}`)),h==="truck"&&(a.push(`Income: ${T(Fe(e))} per target cargo | upgrade x${yt(e,"truck").toFixed(3)}`),a.push(`Poop shipment fine: -${T(hn(e))}`)),h==="trash"){let m=Dt(e),w=ht(m);a.push(`Bonus cards: ${m}/${zt()}`),a.push(`Poop income bonus: ${T(w)} per processed poop.`),a.push("With enough upgrades, poop can out-earn male/female routes.")}s.entry&&a.push(`Receiver: edge cell ${s.entry.col},${s.entry.row} (${s.side})`)}return a}function ll(s){if(!s||e.phase!=="build")return"";let a=On(e).find(h=>h.type===s.type&&h.id===s.id);return a?a.message||"Not connected to conveyor route":""}function al(s){return s?s.type==="conveyor"&&e.conveyorMeta.get(s.id)?.kind==="boostConveyor"?"Moves chicks twice as fast. Wears down like a normal belt.":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"?"Slower than hands without upgrades.":s.type==="scanner"?"A manual checkpoint. The operator is the algorithm.":s.type==="facility"&&(s.baseId||s.id)==="mixer"?"Male chicks become revenue here. Do not feed it poop.":s.type==="facility"&&(s.baseId||s.id)==="trash"?"Poop goes in. Sometimes coins come out, for reasons best left unaudited.":s.type==="facility"&&(s.baseId||s.id)==="truck"?"The shipping endpoint. Correct cargo pays; wrong cargo complains.":s.type==="maintenanceRoom"?"A cramped 2\xD72 storage and break room with lockers, spare parts, a bench and one dispatched repairman.":"Factory equipment.":""}return{buildAtCell:v,buildAtPoint:k,eraseAtPoint:Ut,equipmentAtPoint:co,startSelectionBox:Wt.startSelectionBox,updateSelectionBox:Wt.updateSelectionBox,finishSelectionBox:Wt.finishSelectionBox,startGroupDrag:Wt.startGroupDrag,updateGroupDrag:Wt.updateGroupDrag,finishGroupDrag:Wt.finishGroupDrag,selectedObject:G,selectedTitle:oe,equipmentPrice:Z,selectedUpgradeCost:js,selectedInfoLines:xr,flavorText:al,disconnectedWarningFor:ll,gridExpansionCost:B,buyGridExpansion:le,expansionOfferAtPoint:he,beginConveyorDrag:ao,continueConveyorDrag:d,endConveyorDrag:p,cycleSingleConveyorDirection:Mt,branchSwitcherAtPoint:gr,cycleBranchModeAtPoint:sl,cycleBranchModeForKey:yo,removeSelected:wr,switchScannerRole:nl,showManualScannerMenu:ln,showAutoScannerMenu:uo,showSelectedMenu:Cr,setBuildTool:rl,fail:N,isEquipmentCell:W,equipmentHitBoxes:il,routeFromFarmToScanner:It}}function Bs({game:e,ui:t,build:n,startGame:o,beginCardDraft:r,activeQueuedChick:i}){function l(O){return String(O).replace(/[&<>"']/g,W=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[W])}function c(){return Math.round(Xn(e))}function b(){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return!1;let O=!1;for(let W of So)if(O=!0,e.cash>=Oe(W,e))return!1;return O}function C(){x(),A(),B(),$()}function x(){for(let[W,U]of Object.entries(t.buttons))U?.classList?.contains("tool-button")&&U.classList.toggle("active",e.buildTool===W);for(let W of So){let U=t.buttons[W];if(!U)continue;let M=Oe(W,e),g=U.querySelector("span");g&&(g.textContent=W==="conveyor"||W==="boostConveyor"?`${T(M)} / tile`:T(M));let G=W==="manualScanner"&&e.scanners.filter(Z=>Z.kind==="manual").length>=8,oe=e.cashIt(e,U)?.scannerId).length,W=pn(e);t.turnSummary.innerHTML=[`Seed: ${l(e.runSeed||"none")} | Grid box: ${e.gridRows||10}x${e.gridCols||20} | Owned: ${e.gridOwnedCells||e.ownedCells?.size||(e.gridRows||10)*(e.gridCols||20)} cells | Blocked: ${e.blockedCells?.size||0} cells`,`Penalties: wrong shipment -${T(Uo(e))} | Mixer poop -${T(yn(e))} | Shipment poop -${T(hn(e))}`,`Maintenance: worst ${rr(e).worst.percent}% dirty (${rr(e).worst.label}) | Rooms: ${(e.maintenanceRooms||[]).length} | Repairmen: ${(e.repairmen||[]).length}`,`Card draft: ${e.cardDraft?.pending?Math.max(1,e.cardDraft.picksRemaining||1)+" pick(s) left":"ready after each day"} | Farms with scanner route: ${O}/${e.eggFarms.length}`,e.cardEffects?.usedMachineActive?'Procurement: USED MACHINE MODE / no refunds / 60% durability':"",W.length?`Blocked: ${W[0]}`:`${re.status.allPortsConnected}`].filter(Boolean).join("
")}function j(){x(),t.shell.classList.toggle("phase-running",e.phase==="running"),t.shell.classList.toggle("phase-build",e.phase==="build"),t.shell.classList.toggle("phase-gameover",e.phase==="gameover"),t.shell.classList.toggle("phase-title",e.phase==="title"),t.shell.classList.toggle("phase-loanDecision",e.phase==="loanDecision"),t.money.textContent=T(e.cash),t.money.classList.toggle("cash-negative",e.cash<0),t.money.classList.toggle("cash-positive",e.cash>an),t.turn.textContent=e.turn,t.timeLeft.textContent=e.phase==="running"&&e.timeLeft<=0&&e.shutdownTimeLeft>0?`+${e.shutdownTimeLeft.toFixed(1)}s`:`${Math.max(0,e.timeLeft).toFixed(1)}s`,t.timeLeft.closest?.(".hud-card")?.classList.toggle("time-critical",e.phase==="running"&&(e.timeLeft<=10||e.timeLeft<=0&&e.shutdownTimeLeft>0)),t.phase.textContent=ce(),t.comboCount&&(t.comboCount.textContent=e.manualCombo?.count||0),z(),t.turnProfit.textContent=T(e.stats.profit),t.turnProfit.classList.toggle("cash-negative",e.stats.profit<0),t.turnProfit.classList.toggle("cash-positive",e.stats.profit>0),t.mixerCount.textContent=e.stats.mixerCount,t.truckFemaleCount.textContent=e.stats.truckFemale,t.truckMaleCount.textContent=e.stats.truckMale,t.poopCount.textContent=e.stats.poopSpawned,t.buttons.s1Left.disabled=e.phase!=="running"||!i(0),t.buttons.s1Right.disabled=e.phase!=="running"||!i(0),t.buttons.s2Left.disabled=e.phase!=="running"||!i(1),t.buttons.s2Right.disabled=e.phase!=="running"||!i(1);let O=e.scanners.find(g=>g.kind==="manual"&&g.slot===0),W=e.scanners.find(g=>g.kind==="manual"&&g.slot===1);O&&(t.buttons.s1Left.textContent=`S1 ${O.keys?.left?.label||"A"} -> Mixer`,t.buttons.s1Right.textContent=`S1 ${O.keys?.right?.label||"D"} -> S2`),W&&(t.buttons.s2Left.textContent=`S2 ${W.keys?.left?.label||"Left"} -> Waste`,t.buttons.s2Right.textContent=`S2 ${W.keys?.right?.label||"Right"} -> Truck`);let U=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),M=Ko(e,Math.max(1,Number(e.turn)||1),U).amount;t.buttons.nextTurn.innerHTML=e.phase==="build"&&M>0?`NEXT DAYFAIRIES -${T(M)}`:`${re.actions.nextDay}`,t.buttons.nextTurn.disabled=e.phase!=="build"||!!e.cardDraft?.pending||!!e.cardTargetPick?.pending||!hi(e)}function z(){if(!t.eventBrief||!t.targetBrief||!t.speedBrief)return;let O=pt(e).toUpperCase();t.targetBrief.textContent=`TRUCK TARGET: ${O}`,t.speedBrief.textContent=`BELT SPEED: ${c()} px/s`,t.speedBrief.title=`Conveyor speed does not increase by day. Degraded belts reduce speed. Cap: ${Kt}px/s.`;let W=e.eventActive,U=e.eventOffer;W?(t.eventBrief.textContent=`ACTIVE EVENT: ${W.title} | ${W.route}`,t.eventBrief.className="event-brief active"):e.phase==="build"&&U?(t.eventBrief.textContent=`NEXT DAY EVENT: ${U.title} | ${U.route}${U.targetAmount?` | Target ${U.targetAmount}`:""}${U.reward?` | Reward ${T(U.reward)}`:""}`,t.eventBrief.className="event-brief next"):e.phase==="build"&&e.turn+1
\u2642Male->MixerS1: A
\u2640Female->TruckS1: D, then S2: right
\u{1F4A9}Poop->ShredderS1: D, then S2: left

Build phase: connect at least one EGG through a scanner to Mixer, Shredder, or Truck before Next Day. One day is one run.

',t.modalActions.innerHTML="",t.modalActions.appendChild(R(re.actions.startGame,o,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function ie(O){let W=G=>`${G>0?"+":""}${T(G)}`,U=G=>`${G>0?"-":""}${T(G)}`,M=O.profit>=0?"cash-positive":"cash-negative",g=(O.mixerPoopFine||0)+(O.truckPoopFine||0)+(O.maleTruckFine||0)+(O.explosionDamage||0)+(O.cardRerollCost||0);t.modalTitle.textContent=`Day ${O.turn} Settlement`,t.modalBody.innerHTML=` +
Net result${T(O.profit)}
+
+
Chick shipment income${W(O.chickShipmentIncome||0)}
+
Poop shipment income${W(O.poopShipmentIncome||0)}
+
Mixer income${W(O.mixerRevenue||0)}
+
Composter income${W(O.composterIncome||0)}
+
DUD refund income${W(O.dudRefundIncome||0)}
+
Manual combo bonus${W(O.manualComboBonus||0)}
+
Chemical subsidy${W(O.chemicalWeaponSubsidy||0)}
+
Event bonus${W(O.eventBonus||0)}
+
Penalties${U(g)}
+
Fairies fee${U(O.fairiesTribute?.amount||O.fairiesTribute||0)}
+
+

Income ${T(O.revenue)} - losses ${T(O.penalty)} = ${T(O.profit)}

`,t.modalActions.innerHTML="",t.modalActions.appendChild(R("Choose Upgrade Card",r||_,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function le(O,W){let U=Math.max(0,e.cardEffects?.rescueLoanCharges||0);t.modalTitle.textContent="Emergency Loan Available",t.modalBody.innerHTML=` +

End-of-day cash is below ${T(0)}.

+
+
Current money${T(e.cash)}
+
Emergency Loan+${T(500)}
+
Cards remaining${U}
+
+

Use one Emergency Loan to gain ${T(500)} immediately. If cash is still negative, another decision will be shown if another card remains.

`,t.modalActions.innerHTML="",t.modalActions.appendChild(R("Accept Game Over",W,"facility-action danger")),t.modalActions.appendChild(R("Use Emergency Loan",O,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function se(){let O=e.totals.processed,W=O?Math.round(e.totals.correct/O*100):0,U=Gi(e);t.modalTitle.textContent=re.phases.gameover,t.modalBody.innerHTML=`

Your cash went negative.

+
Final Score${U.score}
Survival${e.totals.turnsCompleted} days
Final Cash${T(e.cash)}
Accuracy${W}%
+
Score breakdown +
Formula
Base = Cash + Total revenue + Factory value \xD70.5 + Event bonus \xD70.5 = ${T(U.base)}
Daily earned = ceil(Base \xF7 Days) = ${T(U.dailyEarned)}
Score = max(0, floor(Base + Daily earned + Correct bonus - Total outflow - Day penalty)) = ${U.score}
+
Factory Value${T(U.factoryValue)}
Total Revenue${T(e.totals.revenue)}
Daily Earned${T(U.dailyEarned)} / day
Total Outflow${T(e.totals.penalty)}
Fairies Tribute${T(e.totals.fairiesTribute||0)}
Correct Sorts${e.totals.correct}
Auto Sorted${e.totals.autoSorted}
Poop Control${e.totals.poopTrash} trashed / ${e.totals.poopTruck} shipped / ${e.totals.poopMixer} mixer
Explosion Penalty${T(e.totals.explosionDamage)}
Event Bonus${T(e.totals.eventBonus)}
Day Penalty-${U.dayPenalty}
Events${e.totals.eventSuccess} success / ${e.totals.eventFailed} failed
+
`,t.modalActions.innerHTML="",t.modalActions.appendChild(R(re.actions.restart||"Restart",o,"primary-button restart-button")),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible","gameover-modal")}function R(O,W,U="primary-button"){let M=document.createElement("button");return M.type="button",M.className=U,M.textContent=O,M.addEventListener("click",W),M}function _(){t.modal.classList.remove("visible","equipment-popover","gameover-modal"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function Y(){}return{updatePanels:C,updateUI:j,showTitle:he,showTurnResult:ie,showEmergencyLoanDecision:le,showGameOver:se,hideModal:_,checkGameOver:Y}}function vr(e){e.totals.processed+=1}function Zt(e){e.stats.correct+=1,e.totals.correct+=1}function wt(e){e.stats.mistakes+=1,e.totals.mistakes+=1}function Ls(e){e.stats.autoSorted+=1,e.totals.autoSorted+=1}function Os(e){e.stats.poopSpawned+=1}function Ns(e){e.stats.mixerCount+=1,vr(e)}function _s(e){e.stats.trashCount+=1,vr(e)}function Gs(e,t){t==="female"?e.stats.truckFemale+=1:t==="male"&&(e.stats.truckMale+=1),vr(e)}function Zn(e,t){let n=t==="truck"?"poopTruck":t==="trash"?"poopTrash":t==="mixer"?"poopMixer":null;n&&(e.stats[n]+=1,e.totals[n]+=1)}function Us({game:e,currentConveyorSpeed:t,onGameOverCheck:n}){function o(d){return Rt(d)*Yn(d)*ps(e)/Ci(e)}function r(d){let p=F(d.col,d.row),v=1+ys(e,d),k=l(d,v);if(!k.length)return i(d,p),!0;let S=0,P=0;for(let D of k){let V=F(D.col,D.row),ae=c(V);if(ae){ae.stoppedTimer=.85,P+=1;continue}let Ne=Ds(e,{stage:"belt",scannerId:null,route:[V]});Ne.sex==="poop"&&Os(e),e.chicks.push(Ne),ji(e,d),S+=1}return S>0?(Wi(e,p.x,p.y),S>1&&H(e,p.x,p.y-28,`x${S}`,y.green),!0):P===0}function i(d,p){(d.noRouteNoticeCooldown||0)<=0&&(H(e,p.x,p.y-24,"NO BELT: PAUSED",y.warn),d.noRouteNoticeCooldown=2.5)}function l(d,p){let k=de.map(S=>({col:d.col+S.dc,row:d.row+S.dr})).filter(S=>Ee(S.col,S.row)&&e.conveyorTiles.has(I(S.col,S.row))).map(S=>({p:S,blocked:$(null,F(S.col,S.row))?1:0,roll:Math.random()}));return k.sort((S,P)=>S.blocked-P.blocked||S.roll-P.roll),k.slice(0,Math.max(1,p||1)).map(S=>S.p)}function c(d){return e.chicks.find(p=>p.stage!=="flying"&&Math.hypot(p.x-d.x,p.y-d.y)0;if(e.timeLeft=Math.max(0,e.timeLeft-d),k&&e.timeLeft<=0&&p(),e.timeLeft<=0){e.shutdownTimeLeft>0&&(e.shutdownTimeLeft=Math.max(0,e.shutdownTimeLeft-d));for(let S of e.eggFarms)S.shutterProgress=Math.min(1,(S.shutterProgress||0)+d*2.8)}if(k&&e.timeLeft>0){for(let S of e.eggFarms)if(S.noRouteNoticeCooldown>0&&(S.noRouteNoticeCooldown=Math.max(0,S.noRouteNoticeCooldown-d)),S.nextSpawn-=d,S.nextSpawn<=0){let P=r(S);S.nextSpawn=P?o(S):.15,S.lastInterval=S.nextSpawn}}for(let S=e.chicks.length-1;S>=0;S-=1){let P=e.chicks[S];P.bob+=d*7,P.stoppedTimer>0&&(P.stoppedTimer=Math.max(0,P.stoppedTimer-d)),P.stage!=="queued"&&x(P,S,d)}N(d),Gt(),on(),e.timeLeft<=0&&(e.chicks.length===0?v():e.shutdownTimeLeft<=0&&C())}function C(){if(e.cleanupBlown)return;e.cleanupBlown=!0,e.cleanupTimer=1;let d=[...e.chicks];for(let p of d)Yo(e,p.sex,p.x,p.y,-Math.PI/2,!0);e.chicks=[];for(let p of e.scanners)p.queue=[];if(Gt(),d.length){let p=d.reduce((k,S)=>k+S.x,0)/d.length,v=d.reduce((k,S)=>k+S.y,0)/d.length;Xe(e,p,v,y.warn,58),H(e,p,v-24,"CLEANUP",y.warn)}}function x(d,p,v){if(A(d)){d.stoppedTimer=.35;return}if(me(d,v),!(d.route&&d.targetIndex=d.route.length)return!1;let p=d.route[d.targetIndex];return $(d,p)}function $(d,p){if(!p)return!1;for(let v of e.chicks)if(!(d&&v.id===d.id)&&v.stage!=="flying"&&Math.hypot(v.x-p.x,v.y-p.y)1)&&d.push({x:p.x,y:p.y})}function j(d){let p=e.conveyorMeta?.get?.(d)||{},v=[];Array.isArray(p.outDirs)&&v.push(...p.outDirs),p.dir&&v.push(p.dir);let k=[...new Set(v)].filter(ae=>de.some(Ne=>Ne.name===ae)),S=te(d),P=de.filter(ae=>R(S,ae.name)).map(ae=>ae.name),D=k.filter(ae=>P.includes(ae)),V=P;return D.length?D:V}function z(d){return de.find(p=>p.name===d)||null}function ce(d,p){return e.scanners.find(v=>v.col<=d&&d<=v.col+1&&v.row-1<=p&&p<=v.row+1)||null}function he(d,p){let v=z(p);if(!v)return null;let k=ce(d.col+v.dc,d.row+v.dr);if(!k)return null;let S=Re(k,"inputA");return S&&S.col===d.col&&S.row===d.row?k:null}function ie(d){return Object.entries(e.facilities||{}).find(([,p])=>p?.entry&&p.entry.col===d.col&&p.entry.row===d.row)||null}function le(d){return d?.baseId||d?.id||""}function se(d,p){return d.side==="left"&&p==="left"||d.side==="right"&&p==="right"||d.side==="top"&&p==="up"||d.side==="bottom"&&p==="down"}function R(d,p){let v=z(p);if(!v)return null;let k={col:d.col+v.dc,row:d.row+v.dr};if(Ee(k.col,k.row)&&e.conveyorTiles.has(I(k.col,k.row)))return{type:"conveyor",dirName:p,target:F(k.col,k.row),nextCell:k};let S=he(d,p);if(S)return{type:"scanner",dirName:p,target:ye(S),scanner:S};let P=ie(d);return P&&se(P[1],p)?{type:"facility",dirName:p,facilityId:P[0],facility:P[1],target:F(d.col,d.row)}:null}function _(d,p){let v=z(p);if(!v)return!1;let k=e.conveyorMeta?.get?.(I(d.col+v.dc,d.row+v.dr));return k?[...new Set([...Array.isArray(k.outDirs)?k.outDirs:[],k.dir].filter(Boolean))].includes(v.opposite):!1}function Y(d){return de.filter(p=>Ee(d.col+p.dc,d.row+p.dr)&&e.conveyorTiles.has(I(d.col+p.dc,d.row+p.dr))).map(p=>p.name)}function O(d,p,v="random"){let k=Y(d);if(k.length<3)return p;let S=new Set(k.filter(V=>_(d,V))),P=k.filter(V=>!S.has(V)),D=S.size&&P.length>=2?P:[...new Set(p.filter(V=>k.includes(V)))];return D.length<2&&(D=k),v&&v!=="random"&&v!=="pass"&&D.includes(v)?[v]:D}function W(d,p){return p&&(p.type==="facility"||!$(d,p.target))}function U(d,p,v,k="random"){let S=v.map(ae=>R(p,ae)).filter(Boolean);if(!S.length)return null;let D=S.filter(ae=>ae.type!=="facility").filter(ae=>!$(d,ae.target)),V=D.length?D:S.filter(ae=>ae.type==="facility");return V.length?V[Math.floor(Math.random()*V.length)]:null}function M(d,p){let v=[];B(v,{x:d.x,y:d.y}),B(v,p),d.route=v.length?v:[{x:d.x,y:d.y}],d.targetIndex=d.route.length>1?1:d.route.length}function g(d,p){let v=He(d.x,d.y);if(!v)return gt(p,"OFF GRID");let k=I(v.col,v.row);if(!e.conveyorTiles.has(k))return gt(p,"OFF BELT");let S=e.conveyorMeta?.get(k)||{},P=O(v,j(k),S.branchMode||"random");if(!P.length){d.stoppedTimer=.25;return}let D=U(d,v,P,S.branchMode||"random");if(!D){d.stoppedTimer=.25;return}if(D.type==="facility"){let V=le(D.facility);V==="mixer"?io(p,D.facility):V==="truck"?gn(p,D.facility):V==="trash"?so(p,D.facility):gt(p,"DONE");return}D.type==="scanner"&&(d.pendingScannerId=D.scanner.id),d.prevConveyorCell=k,M(d,D.target)}function G(d){let p=He(d.x,d.y);if(!p)return null;let v=I(p.col,p.row);return e.conveyorTiles.has(v)?v:null}function oe(d){let p=G(d)||G(d.route?.[d.targetIndex]||d);return t(p)}function Z(d,p){let v=G(p);!v||d.lastWearKey===v||(d.lastWearKey=v,Ji(e,v))}function me(d,p){let v=oe(d)*p;for(;v>0&&d.targetIndex=D?(d.x=k.x,d.y=k.y,Z(d,k),d.targetIndex+=1,v-=D):(d.x+=S/D*v,d.y+=P/D*v,v=0)}}function ge(d,p,v){d.stage="queued",d.route=null,d.queueRoute=v?v.map(k=>({x:k.x,y:k.y})):[ye(p)],d.scannerId=p.id,p.queue.includes(d.id)||p.queue.push(d.id),Pe(p)}function Pe(d){d.queue=d.queue.filter(v=>e.chicks.some(k=>k.id===v&&k.stage==="queued"));let p=f.cell*.86*hs(e);d.queue.forEach((v,k)=>{let S=e.chicks.find(P=>P.id===v);S&&(Ae(S,S.queueRoute||[ye(d)],k*p),S.queueIndex=k)})}function Ae(d,p,v){if(!p||!p.length)return;if(p.length===1||v<=0){let P=p[p.length-1];d.x=P.x,d.y=P.y;return}let k=v;for(let P=p.length-1;P>0;P-=1){let D=p[P-1],V=p[P],ae=Math.hypot(V.x-D.x,V.y-D.y);if(k<=ae){let Ne=1-k/ae;d.x=D.x+(V.x-D.x)*Ne,d.y=D.y+(V.y-D.y)*Ne;return}k-=ae}let S=p[0];d.x=S.x,d.y=S.y}function N(d){for(let p of e.scanners){if(p.cooldown>0&&(p.cooldown=Math.max(0,p.cooldown-d)),p.keyPressTime>0&&(p.keyPressTime=Math.max(0,p.keyPressTime-d)),Pe(p),p.kind!=="auto"||p.cooldown>0||!p.queue.length)continue;let v=p.queue[0],k=e.chicks.findIndex(S=>S.id===v);if(k<0){p.queue.shift();continue}nn(k,Do(p,e.chicks[k]),!0)&&(Zi(e,p),p.cooldown=nt(p,e),Ls(e))}}function Ie(d){let p=Ro(e,d);return!p||!p.queue.length?null:e.chicks.find(v=>v.id===p.queue[0])||null}function Ye(d,p){if(e.phase!=="running")return;let v=Ro(e,d);Ve(v,p)}function Ve(d,p){if(e.phase!=="running"||!d||d.kind!=="manual"||(d.keyPressTime=.18,d.keyPressSide=p,!d.queue.length))return;let v=e.chicks.findIndex(k=>k.id===d.queue[0]);v>=0&&nn(v,p,!1)}function xe(d,p,v){return d.kind==="manual"&&Do(d,p)===v}function Ct(d){let p=e.manualCombo?.count||0;if(e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=0,e.manualCombo.lastBonus=0,e.stats.manualComboFailure=(e.stats.manualComboFailure||0)+1,e.totals.manualComboFailure=(e.totals.manualComboFailure||0)+1,p>=10){let v=ye(d);Ft(e,10,.25),H(e,v.x,v.y-36,"COMBO RESET",y.danger)}}function oo(d){e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=Math.max(0,e.manualCombo.count||0)+1,e.stats.manualComboSuccess=(e.stats.manualComboSuccess||0)+1,e.totals.manualComboSuccess=(e.totals.manualComboSuccess||0)+1;let p=e.manualCombo.count;if(e.manualCombo.lastBonus=0,p<10)return 0;let v=Math.max(1,Math.floor(p/10)),k=e.scanners.filter(V=>V.kind==="manual").length,S=Math.min(1,(20+k*10)/100),P=0;for(let V=0;V0){Ge(e,D),e.stats.manualComboBonus=(e.stats.manualComboBonus||0)+D,e.totals.manualComboBonus=(e.totals.manualComboBonus||0)+D,e.manualCombo.lastBonus=D;let V=ye(d);H(e,V.x,V.y-42,`COMBO +${T(D)}`,y.green)}return D}function Mn(d,p){let v=Re(d,p);if(!v)return null;let k=I(v.col,v.row);if(e.conveyorTiles.has(k))return{...v};let P=(_e(e).scannerPorts.get(d.id)?.[p]?.keys||[]).filter(Boolean);if(!P.length)return null;let D=P.map(te);return D.find(ae=>ae.col===v.col&&ae.row===v.row)||D[0]||null}function ro(d,p,v,k){let S=[];B(S,{x:d.x,y:d.y});let P=Re(p,v);return P&&B(S,F(P.col,P.row)),B(S,F(k.col,k.row)),S}function nn(d,p,v){let k=e.chicks[d];if(!k||k.stage!=="queued")return!1;let S=At(e,k.scannerId);if(!S)return!1;let P=Mn(S,p);if(!P)return!v&&S.kind==="manual"&&Ct(S),H(e,k.x,k.y-16,p==="left"?"NO LEFT BELT":"NO RIGHT BELT",y.danger),!1;!v&&S.kind==="manual"&&(xe(S,k,p)?oo(S):Ct(S)),S.queue=S.queue.filter(V=>V!==k.id),k.stage="belt",k.route=ro(k,S,p,P),k.targetIndex=k.route.length>1?1:k.route.length,k.scannerId=null,k.nextScannerId=null,k.pendingScannerId=null,k.queueRoute=null,k.queueIndex=-1;let D=v?y.green:p==="left"?y.mixerBlue:y.truckPink;return Ki(e,ye(S).x,ye(S).y,D),H(e,k.x,k.y-20,v?"AUTO":p.toUpperCase(),D),!0}function Mt(d){let p=e.chicks[d];return p?(e.chicks.splice(d,1),p):null}function io(d,p=e.facilities.mixer){if(p?.processingCooldown>0){let D=e.chicks[d];D&&(D.stoppedTimer=.25);return}let v=Mt(d);if(!v)return;let{x:k,y:S}=v;if(Ns(e),tr(e,p),nr(e,p),v.sex==="poop"){let D=$i(e);Zn(e,"mixer"),wt(e),qi(e,k,S),H(e,k,S-18,`-${T(D)}`,y.danger);return}let P=Di(e);v.sex==="male"?Zt(e):wt(e),Hi(e,k,S),H(e,k,S-18,`+${T(P)}`,y.green)}function gn(d,p=e.facilities.truck){let v=Mt(d);if(!v)return;let{x:k,y:S}=v;lo(v.sex,p),Vi(e,k,S,v.sex),Gs(e,v.sex);let P=pt(e),D=gi(e,v.sex);if(v.sex==="poop"){if(Zn(e,"truck"),D)Zt(e),H(e,k,S-18,`+${T(Fe(e))}`,y.green);else{let V=Fi(e);wt(e),H(e,k,S-18,`-${T(V)}`,y.danger)}return}if(v.sex==="female"){D?(Zt(e),H(e,k,S-18,`+${T(Fe(e))}`,y.green)):(wt(e),H(e,k,S-18,P==="male"?"REJECT":"NO SALE",y.warn));return}if(D){Zt(e),H(e,k,S-18,`+${T(Fe(e))}`,y.green);return}if(xi(e)){let V=Bi(e);wt(e),H(e,k,S-18,`-${T(V)}`,y.danger)}else wt(e),H(e,k,S-18,"REJECT",y.warn)}function so(d,p=e.facilities.trash){if(p?.processingCooldown>0){let V=e.chicks[d];V&&(V.stoppedTimer=.25);return}let v=Mt(d);if(!v)return;let{x:k,y:S}=v;Yi(e,k,S,v.sex),_s(e),tr(e,p),nr(e,p);let P={amount:0},D="";if(v.sex==="poop"){P=Pi(e),D=P.amount>0?` +${T(P.amount)}`:"",Zn(e,"trash"),Zt(e);let V=Math.ceil(Math.max(0,Number(e.cardEffects?.composter)||0)*3*Nn(e));if(V>0){let ae=Ge(e,V);e.stats.composterIncome=(e.stats.composterIncome||0)+ae,e.totals.composterIncome=(e.totals.composterIncome||0)+ae,H(e,k,S-36,`COMPOST +${T(ae)}`,y.green)}H(e,k,S-18,`CLEAN${D}`,P.amount>0?y.green:y.green)}else wt(e),H(e,k,S-18,P.amount>0?`WASTE${D}`:"WASTE",P.amount>0?y.green:y.ink)}function gt(d,p){let v=Mt(d);v&&H(e,v.x,v.y-12,p,y.muted)}function lo(d,p=e.facilities.truck){let v=p||e.facilities.truck;v&&(e.truckCargo.push({sex:d,x:K(22,v.w-22),y:K(66,v.h-24)}),e.truckCargo.length>45&&e.truckCargo.shift())}function xn(d){let p=He(d.x,d.y);if(p){let P=I(p.col,p.row);if(e.conveyorTiles.has(P))return P}let v=di(e,d.x,d.y);if(!v)return null;let k=te(v),S=F(k.col,k.row);return Math.hypot(d.x-S.x,d.y-S.y)<=f.cell*.55?v:null}function Gt(){let{components:d,cellToComponent:p}=ui(e);for(let v of e.chicks){if(v.stage==="flying")continue;let k=xn(v);if(!k)continue;let S=p.get(k),P=d.get(S);P&&(P.count+=1)}for(let v of d.values())v.ratio=v.count/v.capacity;e.congestion=d,e.componentLookup=p}function on(){for(let d of e.congestion.values()){let p=_o(e),v=Ti(e);if(d.ratio>v&&d.ratio=p){let k=rn(d.id);if(!k.length||k.some(D=>D.stage!=="queued"&&D.stoppedTimer<=.2))continue;let S=e.lastExplodedComponent.get(d.id)||0,P=performance.now();P-S>900&&(e.lastExplodedComponent.set(d.id,P),ao(d))}}}function rn(d){return e.chicks.filter(p=>{let v=xn(p);return v&&e.componentLookup?.get(v)===d})}function ao(d){let p=rn(d.id);if(!p.length)return;for(let S of p)Yo(e,S.sex,S.x,S.y);e.chicks=e.chicks.filter(S=>!p.some(P=>P.id===S.id));for(let S of e.scanners)S.queue=S.queue.filter(P=>e.chicks.some(D=>D.id===P));for(let S of d.cells){let P=te(S),D=F(P.col,P.row);Xe(e,D.x,D.y,y.danger),Ze(e,D.x,D.y,6),Gn(e,D.x,D.y,4)}Ft(e,18,.75);let v=te(d.cells[0]),k=F(v.col,v.row);e.stats.explosions=(e.stats.explosions||0)+1,e.totals.explosions=(e.totals.explosions||0)+1,H(e,k.x,k.y-22,`${Math.round(_o(e)*100)}% JAM EXPLOSION`,y.danger)}return{activeQueuedChick:Ie,currentSpawnDelay:o,sortSlot:Ye,updateCongestion:Gt,sortScanner:Ve,updateRunning:b}}var fe=document.getElementById("gameCanvas"),Cc=fe.getContext("2d"),L={shell:document.getElementById("gameShell"),money:document.getElementById("money"),turn:document.getElementById("turn"),timeLeft:document.getElementById("timeLeft"),phase:document.getElementById("phaseLabel"),comboCount:document.getElementById("comboCount"),eventBrief:document.getElementById("eventBrief"),targetBrief:document.getElementById("targetBrief"),speedBrief:document.getElementById("speedBrief"),turnProfit:document.getElementById("turnProfit"),mixerCount:document.getElementById("mixerCount"),truckFemaleCount:document.getElementById("truckFemaleCount"),truckMaleCount:document.getElementById("truckMaleCount"),poopCount:document.getElementById("poopCount"),buildStatus:document.getElementById("buildStatus"),turnSummary:document.getElementById("turnSummary"),modal:document.getElementById("modal"),modalTitle:document.getElementById("modalTitle"),modalBody:document.getElementById("modalBody"),modalActions:document.getElementById("modalActions"),hoverTooltip:document.getElementById("hoverTooltip"),manualScannerMonitor:document.getElementById("manualScannerMonitor"),debug:{panel:document.getElementById("debugPanel"),infiniteCash:document.getElementById("debugInfiniteCash"),dayInput:document.getElementById("debugDayInput"),setDay:document.getElementById("debugSetDayButton"),zeroTimer:document.getElementById("debugZeroTimerButton"),cardSelect:document.getElementById("debugCardSelect"),targetSelect:document.getElementById("debugTargetSelect"),grantCard:document.getElementById("debugGrantCardButton"),grantAllCards:document.getElementById("debugGrantAllCardsButton"),readout:document.getElementById("debugReadout")},buttons:{s1Left:document.getElementById("scanner1MixerButton"),s1Right:document.getElementById("scanner1TruckButton"),s2Left:document.getElementById("scanner2MixerButton"),s2Right:document.getElementById("scanner2TruckButton"),nextTurn:document.getElementById("nextTurnButton"),conveyor:document.getElementById("buildConveyorButton"),boostConveyor:document.getElementById("buildBoostConveyorButton"),eggFarm:document.getElementById("buildEggFarmButton"),autoScanner:document.getElementById("buildAutoScannerButton"),manualScanner:document.getElementById("buildManualScannerButton"),mixer:document.getElementById("buildMixerButton"),trash:document.getElementById("buildTrashButton"),truck:document.getElementById("buildTruckButton"),maintenanceRoom:document.getElementById("buildMaintenanceRoomButton"),erase:document.getElementById("eraseButton"),undo:document.getElementById("undoButton"),redo:document.getElementById("redoButton")}};function Mc(){let e={conveyor:"conveyor",boostConveyor:"boostConveyor",eggFarm:"eggFarm",autoScanner:"autoScanner",manualScanner:"manualScanner",mixer:"mixer",trash:"trash",truck:"truck",maintenanceRoom:"maintenanceRoom"};for(let[t,n]of Object.entries(e))L.buttons[t]&&(L.buttons[t].innerHTML=Or(n))}function gc(e){let t=new Set(e.tags||[]);return["upgradeEgg","crowdedFarming","hatchingFeed","extraEggOutlet"].includes(e.id)||t.has("EGG")?"Production / EGG":["upgradeTrash","poopRateBooster","composter","chemicalWeaponSubsidy"].includes(e.id)||t.has("POOP")?"Poop / Shredder":["upgradeAutoScanner","autoScannerTuning","scannerQueueSpacing"].includes(e.id)||t.has("SCANNER")?"Scanner":["bearing","dynamite"].includes(e.id)||t.has("CONVEYOR")?"Conveyor / Map":["safetyCover","preventiveMaintenance","durabilityCoating","sparePartsBin","laborExploitation"].includes(e.id)||t.has("MAINTENANCE")?"Maintenance / Risk":["dudFilter","dudRefund","freeReroll","extraCards"].includes(e.id)||t.has("CARD")?"Card Engine":t.has("ULTRA RARE")?"Ultra Rare":t.has("ECONOMY")||["upgradeMixer","upgradeTruck","recyclingSubsidy","usedMachine","newMachine","flattery","legalWork","rescueLoan"].includes(e.id)?"Economy / Shipment":"Other"}function xc(){if(!L.debug?.panel||!L.debug.cardSelect)return;let e=["Production / EGG","Poop / Shredder","Scanner","Conveyor / Map","Maintenance / Risk","Card Engine","Economy / Shipment","Ultra Rare","Other"],t=new Map(e.map(n=>[n,[]]));for(let n of Jt){let o=gc(n);t.has(o)||t.set(o,[]),t.get(o).push(n)}L.debug.cardSelect.innerHTML="";for(let n of e){let o=t.get(n)||[];if(!o.length)continue;let r=document.createElement("optgroup");r.label=n;for(let i of o){let l=document.createElement("option");l.value=i.id;let c=i.rarity==="ultraRare"?"UR":i.rarity==="rare"?"R":"C";l.textContent=`[${c}] ${i.title}`,r.appendChild(l)}L.debug.cardSelect.appendChild(r)}L.debug.cardSelect.addEventListener("change",Nt),Nt()}function Nt(){if(!L.debug?.targetSelect)return;let e=L.debug.cardSelect?.value,t=Ot(e),n=t?ms(u,t):[];if(L.debug.targetSelect.innerHTML="",!n.length){let r=document.createElement("option");r.value="__none__",r.textContent=t?"No target required":"No card selected",L.debug.targetSelect.appendChild(r),L.debug.targetSelect.disabled=!0;return}let o=document.createElement("option");o.value="__auto__",o.textContent=t?.id==="dynamite"?"Auto: first 3 blocked cells":"Auto: first valid target",L.debug.targetSelect.appendChild(o);for(let r of n){let i=document.createElement("option");i.value=r.key,i.textContent=r.label,L.debug.targetSelect.appendChild(i)}L.debug.targetSelect.disabled=!1}function Tc(){let e=Math.max(1,Math.floor(Number(L.debug.dayInput?.value)||1));u.turn=e,L.debug.dayInput&&(L.debug.dayInput.value=String(e)),H(u,fe.width/2-u.view.x,86-u.view.y,`DAY ${e}`,y.green),Q.updatePanels(),Q.updateUI(),Nt(),_t(`Day set to ${e}.`)}function Ec(){u.timeLeft=0,u.phase==="running"&&Vs(),H(u,fe.width/2-u.view.x,86-u.view.y,"TIMER 0",y.warn),Q.updatePanels(),Q.updateUI(),_t("Timer set to 0.")}function Rc(){let e=L.debug.cardSelect?.value,t=L.debug.targetSelect?.disabled?void 0:L.debug.targetSelect?.value,n=sr(u,e,{targetKey:t});L.debug.grantCard&&(L.debug.grantCard.textContent=n.ok?"Granted":"Failed",window.setTimeout(()=>{L.debug.grantCard&&(L.debug.grantCard.textContent="Grant Selected")},900)),Me?.updateCongestion?.(),Q.updatePanels(),Q.updateUI(),Nt(),_t(n.reason)}function Pc(){let t=Jt.map(n=>sr(u,n,{targetKey:"__auto__"})).filter(n=>n.ok).length;Me?.updateCongestion?.(),Q.updatePanels(),Q.updateUI(),Nt(),_t(`Granted ${t}/${Jt.length} cards.`)}function Ac(){L.debug?.infiniteCash?.checked&&u.cash<999999&&(u.cash=999999,u.totals.maxCash=Math.max(u.totals.maxCash,u.cash))}function _t(e=""){L.debug?.readout&&(L.debug.readout.textContent=[e,`D${u.turn}`,T(u.cash),`Combo ${u.manualCombo?.count||0}`,`Event ${u.eventActive?.title||u.eventOffer?.title||"none"}`,`Rescue ${u.cardEffects?.rescueLoanCharges||0}`,`Chem ${u.cardEffects?.chemicalWeaponSubsidy||0}`].filter(Boolean).join(" | "))}var u=To(),X,Q,Me,tn;function Ic(e=null){let t=Xn(u,e);return e?t*Qo(u,e):t}function Dc(){Object.assign(u,To()),u.phase="running",u.view={x:0,y:0,scale:1},Eo(u),Xs(),Se(u),Q.hideModal(),Me.updateCongestion(),Q.updatePanels(),Q.updateUI(),_t()}function $c(){if(u.phase!=="build")return;if(u.cardDraft?.pending||u.cardTargetPick?.pending){X.fail(u.cardTargetPick?.pending?"Choose upgrade target first.":"Choose an upgrade card first."),Q.updatePanels();return}let e=pn(u);if(e.length){X.fail(`Cannot start: ${e[0]}`),Q.updatePanels();return}Se(u),ci(u),os(u);let t=Math.max(0,Math.floor(u.lastResult?.profit??u.stats?.profit??0)),n=Ni(u,Math.max(1,u.turn||1),t);u.lastStartFees={fairiesTribute:n.amount||0,tribute:n},n.amount>0&&H(u,fe.width/2-u.view.x,116-u.view.y,`FAIRIES -${T(n.amount)}`,y.danger),wi(u),u.phase="running",u.turn+=1,u.timeLeft=ki(u),u.shutdownTimeLeft=0,u.cleanupTimer=null,u.cleanupBlown=!1,u.chicks=[],u.effects=[],u.floatingTexts=[],u.shake={time:0,strength:0},u.truckCargo=[],Xs(),u.stats=xo(),u.stats.fairiesTribute=u.lastStartFees?.fairiesTribute||0,u.stats.fairiesTribute>0&&(u.stats.penalty+=u.stats.fairiesTribute,u.stats.profit-=u.stats.fairiesTribute);for(let o of u.scanners)o.queue=[],o.cooldown=0;for(let o of u.eggFarms)o.nextSpawn=Me.currentSpawnDelay(o),o.lastInterval=o.nextSpawn,o.shutterProgress=0,o.shutterSparked=!1;u.buildTool=null,u.selected=null,u.groupDrag=null,u.selectionBox=null,u.pan=null,Me.updateCongestion(),Q.updatePanels(),Q.updateUI()}function Fc(){if(u.phase!=="running")return;let e=Oi(u),t=u.eventActive?{...u.eventActive}:null,n=Ri(u),o=_i(u);if(e.adjusted>0){let i=u.facilities.truck,l=i?i.x+i.w/2:fe.width/2-u.view.x,c=i?i.y+26:96-u.view.y;H(u,l,c,`${e.target==="poop"?"POOP SHIP":"SHIP"} +${T(e.adjusted)}`,y.green)}n?.bonus>0&&H(u,fe.width/2-u.view.x,96-u.view.y,`EVENT +${T(n.bonus)}`,y.green),o.amount>0&&H(u,fe.width/2-u.view.x,116-u.view.y,`CHEM SUBSIDY +${T(o.amount)}`,y.green),Si(u),u.totals.turnsCompleted+=1;let r=Ei(t);if(r!==1&&(u.pendingFairiesTributeMultiplier=r),u.lastResult={...u.stats,ship:e,event:n,chemical:o,rescue:{amount:0,used:0,remaining:u.cardEffects?.rescueLoanCharges||0},fairiesTribute:{amount:u.stats.fairiesTribute||0},tributeMultiplier:r,turn:u.turn,cash:u.cash},u.cash<0){if((u.cardEffects?.rescueLoanCharges||0)>0){u.phase="loanDecision",Q.showEmergencyLoanDecision(Ys,eo);return}u.phase="gameover",Q.showGameOver();return}qs()}function qs(){u.phase="build",u.truckCargo=[],u.chicks=[],u.shutdownTimeLeft=0,u.cleanupTimer=null,u.cleanupBlown=!1,u.buildSession+=1,u.undoStack=[],u.redoStack=[],u.timeLeft=0;for(let e of u.scanners)e.queue=[];for(let e of u.eggFarms)e.shutterProgress=0,e.shutterSparked=!1;rs(u),u.eventOffer=vi(u),tn&&tn.prepareDraft(),u.cardTargetPick=null,u.buildTool=null,u.groupDrag=null,u.selectionBox=null,u.pan=null,Q.updatePanels(),Q.showTurnResult(u.lastResult)}function Ys(){if((u.cardEffects?.rescueLoanCharges||0)<=0)return eo();u.cardEffects.rescueLoanCharges-=1,u.stats.rescueLoan=(u.stats.rescueLoan||0)+500,u.totals.rescueLoan=(u.totals.rescueLoan||0)+500;let e=Ge(u,500);u.lastResult={...u.lastResult||{},...u.stats,rescue:{amount:(u.lastResult?.rescue?.amount||0)+e,used:(u.lastResult?.rescue?.used||0)+1,remaining:u.cardEffects.rescueLoanCharges},cash:u.cash},H(u,fe.width/2-u.view.x,176-u.view.y,`RESCUE +${T(e)}`,y.green),u.cash>=0?qs():(u.cardEffects?.rescueLoanCharges||0)>0?(u.phase="loanDecision",Q.showEmergencyLoanDecision(Ys,eo)):eo()}function eo(){u.phase="gameover",Q.showGameOver()}function Vs(){u.shutdownTimeLeft<=0&&(u.shutdownTimeLeft=u.shutdownGraceSeconds||10);for(let e of u.eggFarms){if(e.shutterSparked)continue;e.shutterProgress=.02,e.shutterSparked=!0;let t=F(e.col,e.row);Xe(u,t.x,t.y,y.ink),Ze(u,t.x,t.y+10,10),H(u,t.x,t.y-34,"SHUT +10s",y.ink)}}function zs(e){u.lastTimestamp||(u.lastTimestamp=e);let t=Math.min((e-u.lastTimestamp)/1e3,.05);u.lastTimestamp=e,u.phase==="running"&&Me.updateRunning(t,{closeFarmShutters:Vs,completeTurn:Fc}),Xi(u,t,fe,X.equipmentHitBoxes),Me.updateCongestion(),Cs(Cc,fe,u,{activeQueuedChick:Me.activeQueuedChick,selectedObject:X.selectedObject,selectedTitle:X.selectedTitle}),Ac(),Q.updateUI(),Js(),_t(),requestAnimationFrame(zs)}function to(){return u.view?.scale||1}function Cn(){u.view||(u.view={x:0,y:0,scale:1}),u.view.scale==null&&(u.view.scale=1)}function no(e){let t=fe.getBoundingClientRect();return{x:(e.clientX-t.left)*fe.width/t.width,y:(e.clientY-t.top)*fe.height/t.height}}function St(e){let t=no(e),n=to();return{x:(t.x-(u.view?.x||0))/n,y:(t.y-(u.view?.y||0))/n}}function Bc(e){let t=to();return{x:e.x*t+(u.view?.x||0),y:e.y*t+(u.view?.y||0)}}function Lc(){let e={left:f.x-90,top:f.y-130,right:f.x+f.cols*f.cell+260,bottom:f.y+f.rows*f.cell+220};if(u.phase==="build")for(let t of Tt(u)){let n=Et(t);e.left=Math.min(e.left,n.x-60),e.top=Math.min(e.top,n.y-80),e.right=Math.max(e.right,n.x+n.w+80),e.bottom=Math.max(e.bottom,n.y+n.h+80)}return e}function Ws(e,t){if(e<=t)return[e,t];let n=(e+t)/2;return[n,n]}function kt(){Cn();let e=to(),t=Lc(),[n,o]=Ws(fe.width-160-t.right*e,110-t.left*e),[r,i]=Ws(fe.height-150-t.bottom*e,150-t.top*e);u.view.x=dn(u.view.x,n,o),u.view.y=dn(u.view.y,r,i)}function Xs(){Cn(),u.view.scale=1;let e=u.eggFarms?.[0],t=e?F(e.col,e.row):{x:f.x,y:f.y};u.view.x=280-t.x,u.view.y=190-t.y,kt()}function Oc(e){let t=no(e);Cn(),u.pan={start:t,viewX:u.view.x,viewY:u.view.y,moved:!1}}function Nc(e){if(!u.pan)return;let t=no(e);Math.hypot(t.x-u.pan.start.x,t.y-u.pan.start.y)>5&&(u.pan.moved=!0),Cn(),u.view.x=u.pan.viewX+t.x-u.pan.start.x,u.view.y=u.pan.viewY+t.y-u.pan.start.y,kt()}function _c(e){e.preventDefault(),Cn();let t=no(e),n=St(e),o=Math.exp(-e.deltaY*.0012),r=dn(to()*o,.55,1.8);u.view.scale=r,u.view.x=t.x-n.x*r,u.view.y=t.y-n.y*r,kt(),it()}function Gc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:{type:e.type,id:e.ref.id}:null}function Uc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:e.ref||null:null}function it(){L.hoverTooltip&&(L.hoverTooltip.classList.remove("visible"),L.hoverTooltip.setAttribute("aria-hidden","true"),u.hover=null)}function Wc(e,t){if(!L.hoverTooltip||u.phase!=="build"||u.cardTargetPick?.pending||u.groupDrag||u.selectionBox||u.pan)return it();let n=Uc(t);if(!n)return it();let o=X.selectedTitle(n),r=X.flavorText?X.flavorText(n):"",i=X.disconnectedWarningFor?X.disconnectedWarningFor(n):"",l=X.selectedInfoLines(n).slice(0,7);L.hoverTooltip.innerHTML=`${o}${i?`${i}`:r?`${r}`:""}${l.map(C=>`${C}`).join("")}`;let c=Math.min(window.innerWidth-330,e.clientX+18),b=Math.min(window.innerHeight-220,e.clientY+18);L.hoverTooltip.style.left=`${Math.max(8,c)}px`,L.hoverTooltip.style.top=`${Math.max(8,b)}px`,L.hoverTooltip.classList.add("visible"),L.hoverTooltip.setAttribute("aria-hidden","false"),u.hover={type:t.type,id:t.oldKey||t.ref?.id||null}}function Kc(e){if(u.phase!=="build")return it();Wc(e,X.equipmentAtPoint(St(e)))}function Qs(e){it();let t=St(e),n=X.equipmentAtPoint(t),o=Gc(n);if(!o){u.selected=null,u.multiSelected=[],Q.updatePanels();return}u.selected=o,u.multiSelected=[o],Q.updatePanels();let r=X.selectedObject();r?.type==="scanner"&&r.kind==="manual"&&X.showManualScannerMenu(r),r?.type==="scanner"&&r.kind==="auto"&&X.showAutoScannerMenu(r)}function en(){u.buildTool=null,u.selected=null,u.multiSelected=[],u.selectionBox=null,u.cardTargetPick?.mode==="autoScannerMenu"&&(u.cardTargetPick=null),Q.hideModal(),it(),Q.updatePanels(),Q.updateUI()}function Ks(e){return String(e).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function Hc(e){let t=e?.queue?.[0];return t==null?null:u.chicks.find(n=>n.id===t)||null}function qc(e){if(!e)return'WAIT';let t=e.sex==="poop"?"\u{1F4A9} POOP":e.sex==="male"?"\u2642 MALE":"\u2640 FEMALE";return`${t}`}function Yc(e,t){let n=new Set(u.eggFarms.map(x=>I(x.col,x.row))),o=new Map(u.scanners.map(x=>[I(x.col,x.row),x])),r=Re(e,"inputA"),i=r?I(r.col,r.row):null,l=new Set(Object.values(u.facilities||{}).map(x=>x.entry?I(x.entry.col,x.entry.row):null).filter(Boolean)),c=t?.sex||"",b=c==="poop"?"\u{1F4A9}":c==="male"?"\u2642":c==="female"?"\u2640":"",C=[];for(let x=e.row-2;x<=e.row+2;x+=1)for(let A=e.col-2;A<=e.col+2;A+=1){let $=I(A,x),B=["mini-cell"],j="";A===e.col&&x===e.row?(B.push("scanner"),c&&B.push(c),j=b||"S"):$===i?(B.push("input"),j="IN"):n.has($)?(B.push("egg"),j="E"):o.has($)?(B.push("scanner-other"),j="S"):l.has($)?(B.push("port"),j="P"):u.conveyorTiles.has($)?(B.push("belt"),j="\u2022"):u.blockedCells?.has?.($)&&(B.push("blocked"),j="\xD7"),C.push(`${j}`)}return`
${C.join("")}
`}function Vc(e){let t=Bc(F(e.col,e.row)),n=76;return t.x<-n||t.y<-n||t.x>fe.width+n||t.y>fe.height+n}function Js(){if(!L.manualScannerMonitor)return;if(u.phase!=="running"){L.manualScannerMonitor.classList.remove("visible"),L.manualScannerMonitor.innerHTML="";return}let e=u.scanners.filter(t=>t.kind==="manual"&&Vc(t));if(!e.length){L.manualScannerMonitor.classList.remove("visible"),L.manualScannerMonitor.innerHTML="";return}L.manualScannerMonitor.innerHTML=e.map(t=>{let n=Hc(t),o=t.keys?.left?.label||(t.slot===0?"A":"Left"),r=t.keys?.right?.label||(t.slot===0?"D":"Right"),i=t.role===0?"MIXER":"WASTE",l=t.role===0?"S2":"TRUCK",c=n?"":" disabled";return` +
+
S${(t.slot??0)+1}OFFSCREEN / Q:${t.queue.length}
+
+ IN${qc(n)}SCANNER +
+ ${Yc(t,n)} +
+ + +
+
`}).join(""),L.manualScannerMonitor.classList.add("visible")}L.manualScannerMonitor?.addEventListener("click",e=>{let t=e.target.closest("button[data-scanner-id]");if(!t||t.disabled)return;let n=u.scanners.find(o=>o.id===Number(t.dataset.scannerId));n&&(Me.sortScanner(n,t.dataset.side),Js())});fe.addEventListener("contextmenu",e=>e.preventDefault());fe.addEventListener("wheel",_c,{passive:!1});fe.addEventListener("pointerdown",e=>{if(u.phase!=="build")return;fe.setPointerCapture(e.pointerId);let t=St(e);if(e.button===2){Oc(e);return}if(e.button!==0)return;if(u.cardTargetPick?.mode==="autoScannerMenu"){en();return}if(u.cardTargetPick?.pending){tn.chooseTargetAtPoint(t);return}let n=X.expansionOfferAtPoint?.(t);if(n){X.buyGridExpansion(n),kt(),Q.updatePanels(),Q.updateUI();return}if(X.cycleBranchModeAtPoint?.(t)){Q.updatePanels(),Q.updateUI();return}let o=He(t.x,t.y),r=X.equipmentAtPoint(t);if(!u.buildTool&&r?.type==="conveyor"&&o&&X.cycleSingleConveyorDirection?.(o)){Q.updatePanels(),Q.updateUI();return}if(u.buildTool==="erase"){if(!X.equipmentAtPoint(t)){en();return}X.eraseAtPoint(t);return}if(u.buildTool){let i=He(t.x,t.y);if(!i&&!["mixer","trash","truck"].includes(u.buildTool)){en();return}if(u.buildTool==="conveyor"||u.buildTool==="boostConveyor"){X.beginConveyorDrag(i);return}if(X.equipmentAtPoint(t)){u.buildTool=null,Qs(e);return}X.buildAtPoint(t);return}X.startGroupDrag(e)||X.startSelectionBox(e)});fe.addEventListener("pointermove",e=>{if(u.phase!=="build"){it();return}Kc(e),u.pan&&e.buttons&2&&Nc(e),u.groupDrag&&e.buttons&1&&X.updateGroupDrag(e),u.selectionBox&&e.buttons&1&&X.updateSelectionBox(e),(u.buildTool==="conveyor"||u.buildTool==="boostConveyor")&&e.buttons&1&&X.continueConveyorDrag(He(St(e).x,St(e).y)),u.buildTool==="erase"&&e.buttons&1&&X.eraseAtPoint(St(e))});fe.addEventListener("pointerup",e=>{u.selectionBox?X.finishSelectionBox():u.groupDrag&&(u.groupDrag.committed||Qs(e),X.finishGroupDrag()),e.button===2&&u.pan&&!u.pan.moved&&u.buildTool&&en(),(u.buildTool==="conveyor"||u.buildTool==="boostConveyor")&&X.endConveyorDrag?.(),u.groupDrag=null,u.pan=null;try{fe.releasePointerCapture(e.pointerId)}catch{}});fe.addEventListener("pointerleave",it);fe.addEventListener("pointercancel",()=>{X?.endConveyorDrag?.(),u.groupDrag=null,u.selectionBox=null,u.pan=null,it()});document.addEventListener("pointerdown",e=>{!L.modal.classList.contains("visible")||!L.modal.classList.contains("equipment-popover")||e.target.closest("#modal .modal-card")||en()},!0);L.buttons.s1Left.addEventListener("click",()=>Me.sortSlot(0,"left"));L.buttons.s1Right.addEventListener("click",()=>Me.sortSlot(0,"right"));L.buttons.s2Left.addEventListener("click",()=>Me.sortSlot(1,"left"));L.buttons.s2Right.addEventListener("click",()=>Me.sortSlot(1,"right"));L.buttons.nextTurn.addEventListener("click",$c);L.buttons.conveyor.addEventListener("click",()=>X.setBuildTool("conveyor"));L.buttons.boostConveyor.addEventListener("click",()=>X.setBuildTool("boostConveyor"));L.buttons.eggFarm.addEventListener("click",()=>X.setBuildTool("eggFarm"));L.buttons.autoScanner.addEventListener("click",()=>X.setBuildTool("autoScanner"));L.buttons.manualScanner.addEventListener("click",()=>X.setBuildTool("manualScanner"));L.buttons.mixer.addEventListener("click",()=>X.setBuildTool("mixer"));L.buttons.trash.addEventListener("click",()=>X.setBuildTool("trash"));L.buttons.truck.addEventListener("click",()=>X.setBuildTool("truck"));L.buttons.maintenanceRoom.addEventListener("click",()=>X.setBuildTool("maintenanceRoom"));L.buttons.erase.addEventListener("click",()=>X.setBuildTool("erase"));L.debug.setDay?.addEventListener("click",Tc);L.debug.zeroTimer?.addEventListener("click",Ec);L.debug.grantCard?.addEventListener("click",Rc);L.debug.grantAllCards?.addEventListener("click",Pc);L.buttons.undo.addEventListener("click",()=>{Ho(u)&&(kt(),Q.updatePanels(),Q.updateUI(),Nt())});L.buttons.redo.addEventListener("click",()=>{qo(u)&&(kt(),Q.updatePanels(),Q.updateUI(),Nt())});function Hs(e,t,n){let o=e.keys?.[t];return o?o.code&&n.code===o.code||o.key&&n.key.toLowerCase()===o.key:!1}window.addEventListener("keydown",e=>{if(e.repeat)return;let t=e.key.toLowerCase();if(u.phase==="running")for(let n of u.scanners.filter(o=>o.kind==="manual")){if(Hs(n,"left",e)){e.preventDefault(),Me.sortScanner(n,"left");return}if(Hs(n,"right",e)){e.preventDefault(),Me.sortScanner(n,"right");return}}u.phase==="build"&&(e.ctrlKey||e.metaKey)&&t==="z"&&(e.preventDefault(),Ho(u)&&(kt(),Q.updatePanels(),Q.updateUI())),u.phase==="build"&&(e.ctrlKey||e.metaKey)&&(t==="y"||e.shiftKey&&t==="z")&&(e.preventDefault(),qo(u)&&(kt(),Q.updatePanels(),Q.updateUI())),e.key==="Escape"&&u.cardTargetPick?.pending&&(e.preventDefault(),u.cardTargetPick.mode==="autoScannerMenu"?en():tn.cancelTargetPick())});X=Fs({game:u,ui:L,canvas:fe,canvasPoint:St,onUpdatePanels:()=>Q?.updatePanels()});Me=Us({game:u,currentConveyorSpeed:Ic,onGameOverCheck:()=>Q?.checkGameOver()});tn=ws({game:u,ui:L,onUpdatePanels:()=>Q?.updatePanels()});Q=Bs({game:u,ui:L,build:X,startGame:Dc,beginCardDraft:()=>tn.showDraft(),activeQueuedChick:Me.activeQueuedChick});Mc();xc();Eo(u);Se(u);Me.updateCongestion();Q.updatePanels();Q.updateUI();Q.showTitle();_t();requestAnimationFrame(zs); diff --git a/dist/game.js b/dist/game.js index c6ea3cf..0bd90d6 100644 --- a/dist/game.js +++ b/dist/game.js @@ -1,60 +1,60 @@ -var q={version:"v27.14 debug restore consistency patch",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,fairiesTribute:{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},incomeUpgradeRate:1.1,explosionDamageDivisor:30,maleTruckFinePerHalfDay:30,shredderBonus:{maxCards:30,incomePerUpgrade:1.25},chemicalWeaponSubsidy:{poopPerBlock:70,yenPerBlock:1200}},production:{poopRate:.08,autoScannerCooldown:3.5,autoScannerUpgradeRate:.95,autoScannerCardUpgradeRate:.95,autoScannerMinCooldown:.5,poopRateCardBonus:.04,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:"autoScannerTuning",title:"AUTO SCANNER Tuning",rarity:"common",type:"instant",description:"All AUTO SCANNER cooldowns use default cooldown x0.95 per copy.",tags:["SCANNER","PASSIVE"]},{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",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:"poopRateBooster",title:"Poop Culture",rarity:"common",type:"instant",description:"Base poop rate +4 percentage points. No card limit.",tags:["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:"sparePartsBin",title:"SPARE PARTS BIN",rarity:"common",type:"instant",description:"Restores 2% durability to every machine. A box of almost-compatible parts.",tags:["MAINTENANCE","ACTIVE"]},{id:"dudRefund",title:"DUD REFUND",rarity:"common",type:"instant",description:"DUDs now come with paperwork. Gain JPY 50 per copy when you pick a DUD.",tags:["CARD","ECONOMY","PASSIVE"]},{id:"freeReroll",title:"FREE REROLL",rarity:"common",type:"instant",description:"The first bad ideas are free.",tags:["CARD","PASSIVE"]},{id:"composter",title:"COMPOSTER",rarity:"common",type:"instant",description:"Turns shredder waste into suspicious fertilizer. Gain JPY 3 per copy when SHREDDER processes poop.",tags:["POOP","ECONOMY","PASSIVE"]},{id:"scannerQueueSpacing",title:"Scanner Queue Spacing",rarity:"common",type:"instant",description:"Manual and Auto Scanner queue spacing -15%. No card limit.",tags:["SCANNER","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 unbuildable cells",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:"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:"Fairies tribute profit exemption +JPY 250.",tags:["ECONOMY","RARE","PASSIVE"]},{id:"chemicalWeaponSubsidy",title:"Chemical Weapons Subsidy",rarity:"ultraRare",type:"instant",description:"Each day, gain JPY 1200 per 70 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,autoScannerTuning:0,poopRateBooster:0,crowdedFarming:0,hatchingFeed:0,safetyCover:0,recyclingSubsidy:0,chemicalWeaponSubsidy:0,preventiveMaintenance:0,dudFilter:0,durabilityCoating:0,sparePartsBin:0,dudRefund:0,freeReroll:0,composter:0,scannerQueueSpacing:0,laborExploitation:0,usedMachineActive:!1,rescueLoanCharges:0},commonWeight:8,rareWeight:2,ultraRareWeight:.45,baseDraftSize:3,maxDudsPerDraft:2,dudChancePerCard:.3,dudChanceReductionPerFilter:.05,extraCardsAddedPicks:2,rerollCost:{dayDivisor:2,multiplier:100}},events:{eventChance:.1,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},boostConveyor:{id:"boostConveyor",type:"conveyor",name:"Boost Conveyor",shortName:"BOOST BELT",price:75,buildable:!0,upgradeable:!1,speedMultiplier:2},eggFarm:{id:"eggFarm",type:"eggFarm",name:"Egg Farm",shortName:"EGG",price:250,buildable:!0,upgradeable:!0,maxLevel:4},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:180,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 wn=q.version,vt=q.time.daySeconds,tn=q.cash.starting,xe=q.economy,xr=q.time.farmShutdownGraceSeconds,Sn=q.production.autoScannerCooldown,kr=q.production.autoScannerUpgradeRate,so=q.production.autoScannerCardUpgradeRate||q.production.autoScannerUpgradeRate,lo=q.production.autoScannerMinCooldown,Cr=q.events.eventChance,wt=q.events.firstTurn,ao=q.production.poopRate,co=q.production.poopRateCardBonus||0,xn=q.conveyor.baseSpeed,Gt=q.conveyor.maxSpeed,kn=q.conveyor.bearingSpeedMultiplier,Re=q.cards,Mr=q.cards.definitions,uo=q.cards.defaultEffects,st=q.production.eggSpawnRanges,y=q.grid,Se=q.facilities,fo=["conveyor","boostConveyor","eggFarm","autoScanner","manualScanner","mixer","trash","truck"],nn=["mixer","trash","truck"],gr=["mixer","truck"],St=Object.fromEntries(Object.entries(Se).map(([e,t])=>[e,t.price])),ue=[{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"}],f={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"},ke={ambient:0,important:1,critical:2};function M(e){let t=Number(e)||0;return`${t<0?"-":""}\uFFE5${Math.ceil(Math.abs(t)).toLocaleString("ja-JP")}`}function $(e,t){return`${e},${t}`}function Q(e){let[t,n]=String(e).split(",").map(Number);return{col:t,row:n}}function on(e,t,n){return Math.max(t,Math.min(n,e))}function U(e,t){return e+Math.random()*(t-e)}function Te(e,t){return e>=0&&e=0&&tMath.round(on(r,0,255)).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`}function yo(e,t,n){let o=Tr(e),r=Tr(t);return tl(po(o.r,r.r,n),po(o.g,r.g,n),po(o.b,r.b,n))}var re={appTitle:"Chick Sorter",versionTitle:`Chick Sorter ${wn}`,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 xt(e){return Se[e]?.name||String(e||"").replace(/^[a-z]/,t=>t.toUpperCase())}function nl(e){let t=Se[e];return t?e==="conveyor"||e==="boostConveyor"?`${M(t.price)} / tile`:e==="autoScanner"?`${M(t.price)} / ${Sn.toFixed(1)}s cooldown`:e==="trash"?M(t.price):M(t.price):""}function ol(e){return{conveyor:"A narrow green belt. Routes decide whether chicks live, ship, or become invoices.",boostConveyor:"Moves chicks twice as fast. Wears down like a normal belt.",eggFarm:"A tiny gatehouse producing questionable eggs on schedule.",autoScanner:"Slower than hands without upgrades.",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 Pr(e){let t=ol(e);return`${xt(e)}${nl(e)}${t?`${t}`:""}`}function Rr(e){return re.routeLabels[e]||String(e).toUpperCase()}function Ar(e){let t=2166136261;for(let n=0;n>>0}function Dr(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 Mn(){return`RUN-${Date.now().toString(36)}-${Math.floor(Math.random()*1e6).toString(36)}`.toUpperCase()}function Ir({seed:e,targetRatio:t=.2,reserved:n=[]}={}){let o=Dr(Ar(e||Mn())),r=new Set(n.map(d=>typeof d=="string"?d:$(d.col,d.row))),s=[];for(let d=0;d0;d-=1){let v=Math.floor(o()*(d+1));[s[d],s[v]]=[s[v],s[d]]}let l=Math.round(y.cols*y.rows*t);return new Set(s.slice(0,Math.min(l,s.length)).map(d=>d.k))}function $r({seed:e,colStart:t=0,colEnd:n=y.cols,rowStart:o=0,rowEnd:r=y.rows,targetRatio:s=.2,reserved:l=[]}={}){let d=Dr(Ar(e||Mn())),v=new Set(l.map(z=>typeof z=="string"?z:$(z.col,z.row))),C=[],P=Math.max(0,Math.floor(t)),A=Math.max(P,Math.floor(n)),L=Math.max(0,Math.floor(o)),V=Math.max(L,Math.floor(r));for(let z=L;z0;z-=1){let se=Math.floor(d()*(z+1));[C[z],C[se]]=[C[se],C[z]]}let ne=Math.round((A-P)*(V-L)*s);return new Set(C.slice(0,Math.min(ne,C.length)).map(z=>z.k))}var Ut=10,Fr=2,Br=1;function Wt(e,t){return`${e},${t}`}function rl(e){let[t,n]=String(e).split(",").map(Number);return{chunkX:t,chunkY:n}}function gn(e){let t=q.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 Lr(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 C=Wt(v.chunkX,v.chunkY);t.has(C)||n.has(C)||n.set(C,ho(e,v.chunkX,v.chunkY,v.direction))}}return[...n.values()].sort((o,r)=>{let s=o.direction===r.direction?0:o.direction==="right"?-1:1;return s||(o.chunkY!==r.chunkY?o.chunkY-r.chunkY:o.chunkX-r.chunkX)})}function Gr(e,t="right"){let n=kt(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 mo(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 Ur(e,t){let n=mo(e);return t.x>=n.x&&t.x<=n.x+n.w&&t.y>=n.y&&t.y<=n.y+n.h}function Wr(e){let t=[];for(let n=e.rowStart;nTe(t.col,t.row))}function fl(e){return[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}].filter(t=>Te(t.col,t.row))}function pl(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=>Te(t.col,t.row))}function Vr(e){let t=new Set([...e.conveyorTiles]),n=o=>{o&&Te(o.col,o.row)&&t.add($(o.col,o.row))};for(let o of e.scanners){for(let r of fl(o))n(r);for(let r of dl(o))n(r)}for(let o of e.eggFarms){n(o);for(let r of pl(o))n(r)}for(let o of Object.values(e.facilities))n(o.entry);return t}function qr(e){let t=ll.map(([n,o])=>({col:n,row:o}));for(let{col:n,row:o}of t)Yr(e,n,o);for(let n=0;n({...n,keys:n.keys?{left:{...n.keys.left},right:{...n.keys.right}}:null,queue:[]})),e.eggFarms=cl.map(n=>{let o=Mt(n);return{...n,nextSpawn:o,lastInterval:o}});let t=Vr(e);e.blockedCells=Ir({seed:e.runSeed,targetRatio:q.map.blockedRatio,reserved:[...t]}),yl(e),qr(e),e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function gt(e){return e?[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function pe(e){let t=F(e.col,e.row);return{x:t.x+y.cell/2,y:t.y}}function Tt(e,t,n){return e.eggFarms.find(o=>o.col===t&&o.row===n)||null}function Et(e,t,n){return e.scanners.find(o=>gt(o).some(r=>r.col===t&&r.row===n))||null}function Pt(e,t){return e.scanners.find(n=>n.id===t)||null}function xo(e,t){return e.scanners.find(n=>n.kind==="manual"&&n.slot===t)||null}function Rn(e){return e?.baseId||e?.id||""}function ko(e,t){return Object.entries(e.facilities||{}).filter(([,n])=>Rn(n)===t)}function Ee(e,t){return{inputA:{col:e.col,row:e.row-2},inputB:null,left:{col:e.col-1,row:e.row},right:{col:e.col+2,row:e.row}}[t]}function Qr(e){return e?ue.map(t=>({col:e.col+t.dc,row:e.row+t.dr})).filter(t=>Te(t.col,t.row)):[]}function Jr(e,t,n=[],o=[]){if(!t||!Te(t.col,t.row))return[];let r=[],s=l=>{!l||!Te(l.col,l.row)||!e.conveyorTiles.has($(l.col,l.row))||n.some(d=>d&&Cn(l,d))||r.some(d=>Cn(d,l))||r.push({...l,viaTolerance:!Cn(l,t)})};s(t);for(let l of o)s(l);for(let l of Qr(t))s(l);return r}function zr(e,t,n=[],o=[]){let r=Jr(e,t,n,o),s=r.filter(l=>!l.viaTolerance);return s.length?s:r}function hl(e,t){let n=Ee(t,"inputA");return!n||!Te(n.col,n.row)?[]:e.conveyorTiles.has($(n.col,n.row))?[{...n,viaTolerance:!1}]:[]}function ml(e,t,n){let o=Ee(t,n);return Jr(e,o,gt(t))}function bl(e,t){let n=e.facilities[t]||ko(e,t)[0]?.[1];if(!n)return null;if(n.entry)return F(n.entry.col,n.entry.row);let o=Rn(n)||t;return o==="mixer"?{x:n.x+n.w,y:n.y+n.h*.52}:o==="truck"?{x:n.x,y:n.y+n.h*.52}:o==="trash"?{x:n.x+n.w/2,y:n.y+8}:{x:n.x+n.w/2,y:n.y+n.h/2}}function jr(e,t,n){return n==="inputA"?hl(e,t).length>0:ml(e,t,n).length>0}function be(e){e.branchCounters?.clear?.(),e.routeCache=null,e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function Ae(e,t){return $(e,t)}function _t(e){return Q(e)}function vl(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=>ue.some(s=>s.name===r))}function wl(e,t,n){let o=ue.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.(Ae(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Sl(e,t){let n=_t(t),o=e.conveyorMeta?.get?.(t)||{},r=ue.filter(A=>e.conveyorTiles.has(Ae(n.col+A.dc,n.row+A.dr))).map(A=>A.name),s=vl(e,t).filter(A=>r.includes(A)),l=r,d=s.length?s:l;if(r.length<3)return d;let v=new Set(r.filter(A=>wl(e,n,A)));if(o.branchMode&&o.branchMode!=="random"&&r.includes(o.branchMode)){let A=new Set(v);A.add(o.branchMode),r.filter(L=>!A.has(L)).length>=2&&v.add(o.branchMode)}let C=r.filter(A=>!v.has(A));if(C.length)return C;let P=d.filter(A=>!v.has(A));return P.length?P:d}function xl(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 kl(e){let t=xl(e);for(let o of e.conveyorTiles)t.cells.add(o),t.adjacency.set(o,[]);for(let o of t.cells){let r=_t(o),s=Sl(e,o),l=ue.filter(d=>s.includes(d.name));for(let d of l){let v=Ae(r.col+d.dc,r.row+d.dr);t.cells.has(v)&&t.adjacency.get(o).push({key:v,dir:d.name})}}let n=0;for(let[o,r]of t.adjacency.entries()){n+=r.length;let s=new Set(r.map(l=>l.dir));r.length===1&&(t.metrics.deadEnds+=1),r.length===4&&s.has("left")&&s.has("right")&&s.has("up")&&s.has("down")&&(t.metrics.crosses+=1)}return t.metrics.conveyorCells=t.cells.size,t.metrics.edges=Math.floor(n/2),Cl(t),Ml(e,t),t.issues=Bl(e,t,{includeRoutes:!1}),t}function Cl(e){let t=1;for(let n of e.cells){if(e.cellToComponent.has(n))continue;let o=t++,r=[n],s=[];for(e.cellToComponent.set(n,o);r.length;){let l=r.shift();s.push(l);for(let d of e.adjacency.get(l)||[])e.cellToComponent.has(d.key)||(e.cellToComponent.set(d.key,o),r.push(d.key))}e.components.set(o,{id:o,cells:s,capacity:Math.max(1,s.length),count:0,ratio:0})}e.metrics.components=e.components.size}function Ml(e,t){for(let n of e.scanners){let o={};for(let r of["inputA","left","right"]){let s=Ee(n,r),l=r==="inputA"?s&&t.cells.has(Ae(s.col,s.row))?[{...s}]:[]:zr(e,s,gt(n)).filter(C=>t.cells.has(Ae(C.col,C.row))),d=l.map(C=>Ae(C.col,C.row)),v=d.length>0;if(o[r]={type:r,cell:s,cells:l,keys:d,key:d[0]||null,connected:v},t.metrics.scannerPorts+=1,v&&(t.metrics.connectedScannerPorts+=1),r==="inputA")for(let C of d)t.scannerInputs.set(C,n.id)}t.scannerPorts.set(n.id,o)}for(let[n,o]of Object.entries(e.facilities)){if(!o.entry)continue;let r=zr(e,o.entry).filter(d=>t.cells.has(Ae(d.col,d.row))),s=r.map(d=>Ae(d.col,d.row)),l=s.length>0;t.facilityPorts.set(n,{id:n,cell:{...o.entry},cells:r,keys:s,key:s[0]||null,connected:l}),t.metrics.facilityPorts+=1,l&&(t.metrics.connectedFacilityPorts+=1)}for(let n of e.eggFarms){let o=Qr({col:n.col,row:n.row}).map(r=>Ae(r.col,r.row)).filter(r=>t.cells.has(r));t.farmOutputs.set(n.id,o),t.metrics.farmOutputs+=o.length}}function Le(e){let t=e.routingVersion||0;return(!e.factoryGraph||e.factoryGraph.version!==t)&&(e.factoryGraph=kl(e)),e.factoryGraph}function Zr(e){let t=Le(e);return e.factoryGraphCommittedVersion=t.version,e.factoryGraphSnapshot=gl(t),t}function gl(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 Tl(e,t){let n=t.col-e.col,o=t.row-e.row;return ue.find(r=>r.dc===n&&r.dr===o)?.name||null}function Co(e,t,n){let o=Le(e),r=Ae(t.col,t.row);if(!o.cells.has(r))return[];let s=`${r}|${n.cacheKey||"dynamic"}`;if(n.cacheKey&&o.pathCache.has(s))return o.pathCache.get(s).map(I=>I.map(W=>({...W})));let l=`${r}|none`,d=[{key:r,col:t.col,row:t.row,incoming:"none",depth:0}],v=new Map([[l,0]]),C=new Map,P=[],A=1/0,L=8,V=24,ne=80;for(;d.length;){let I=d.shift();if(I.depth>A)break;let W=`${I.key}|${I.incoming}`;if(n(I)){if(P.push(W),A=I.depth,P.length>=V)break;continue}for(let N of o.adjacency.get(I.key)||[]){let le=_t(N.key),we=Tl(I,le),he=I.depth+1;if(he>A)continue;let R=`${N.key}|${we}`,G=v.get(R);if(G==null)v.set(R,he),C.set(R,[W]),d.push({key:N.key,col:le.col,row:le.row,incoming:we,depth:he});else if(G===he){let x=C.get(R)||[];x.length{if(z.length>=ne)return;let[N]=I.split("|"),le=[_t(N),...W];if(I===l||N===r){z.push(le);return}for(let we of C.get(I)||[])se(we,le)};for(let I of P)se(I,[]);let ye=[],Z=new Set;for(let I of z){let W=I.map(N=>Ae(N.col,N.row)).join(">");Z.has(W)||(Z.add(W),ye.push(I))}return n.cacheKey&&o.pathCache.set(s,ye.map(I=>I.map(W=>({...W})))),ye}function ei(e){let t=Le(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 ti(e,t,n){let o=Le(e),r=null,s=1/0;for(let l of o.cells){let d=Q(l),v=F(d.col,d.row),C=Math.hypot(v.x-t,v.y-n);CF(o.col,o.row));return t&&n.push(t),n}function at(e,t){t&&(!e.length||Er(e[e.length-1],t)>1)&&e.push(t)}function El(e,t,n,o=null){let r=[{x:e.x,y:e.y}];at(r,F(t.col,t.row));for(let s of An(n,o))at(r,s);return r}function Pl(e,t){let n=An(e),o=Ee(t,"inputA");return o&&at(n,F(o.col,o.row)),at(n,pe(t)),n}function Rl(e,t,n,o){let r=[{x:e.x,y:e.y}];at(r,F(t.col,t.row));for(let l of An(n))at(r,l);let s=Ee(o,"inputA");return s&&at(r,F(s.col,s.row)),at(r,pe(o)),r}function Al(e,t,n=0){let o=F(t.col,t.row),r=0;for(let s of e.chicks||[]){if(s.stage==="flying"||s.stage==="queued")continue;Math.hypot(s.x-o.x,s.y-o.y){let A=C.roleBias??0,L=P.roleBias??0;if(A!==L)return A-L;let V=C.cells?.length??C.route?.length??Number.POSITIVE_INFINITY,ne=P.cells?.length??P.route?.length??Number.POSITIVE_INFINITY;if(V!==ne)return V-ne;let z=C.key||JSON.stringify(C.route||C.cells||C),se=P.key||JSON.stringify(P.route||P.cells||P);return z.localeCompare(se)});if(!o||r.length===1)return r[0];let s=r[0].roleBias??0,l=r.filter(C=>(C.roleBias??0)===s),d=Math.min(...l.map(C=>Xr(e,C)));l=l.filter(C=>Xr(e,C)===d);let v=e.branchCounters.get(t)||0;return e.branchCounters.set(t,v+1),l[Math.floor(Math.random()*l.length)]}function ni(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 Mo(e){let t=ni(e);return{left:t.left.destination,right:t.right.destination}}function go(e,t){return ni(e).left.match===t.sex?"left":"right"}function To(e){return Rr(e)}function Eo(e){return{mixer:"#2477ff",truck:"#ff6aa8",trash:"#22b94f","scanner-role-1":"#526456",scanner:"#526456",input:"#526456"}[e]||"#102015"}function Rt(e,t,n=!1){let o=Le(e),r=(o.farmOutputs.get(t.id)||[]).map(_t),s=[];for(let v of r){let C=A=>o.scannerInputs.has(Ae(A.col,A.row));C.cacheKey=`farmInput:${v.col},${v.row}:v${o.version}`;let P=Co(e,v,C);for(let A of P){let L=A[A.length-1],V=o.scannerInputs.get(Ae(L.col,L.row)),ne=Pt(e,V);ne&&s.push({key:`${ne.id}:${L.col},${L.row}:${A.length}`,scanner:ne,cells:A})}}let l=Pn(e,`farm:${t.id}`,s,n);if(l)return{scannerId:l.scanner.id,route:Pl(l.cells,l.scanner)};let d=Pn(e,`farm:${t.id}:output`,r.map(v=>({key:$(v.col,v.row),cells:[v]})),n);return d?{scannerId:null,route:An(d.cells)}:null}function oi(e,t,n,o,r=!1){let s=Pt(e,o);if(!s)return null;let d=Le(e).scannerPorts.get(s.id)?.[t],v=Ee(s,t),C=d?.connected?(d.keys||[d.key]).filter(Boolean).map(_t):[];if(!v||!C.length)return null;let P=Mo(s)[t];return P==="scanner-role-1"?Dl(e,s,t,n,v,C,r):Il(e,s,t,n,v,C,P,r)}function Dl(e,t,n,o,r,s,l){let d=Le(e),v=e.scanners.filter(A=>A.id!==t.id&&d.scannerPorts.get(A.id)?.inputA?.connected),C=[];for(let A of s)for(let L of v){let V=d.scannerPorts.get(L.id)?.inputA?.key;if(!V)continue;let ne=(d.scannerPorts.get(L.id)?.inputA?.keys||[V]).filter(Boolean),z=Z=>ne.includes(Ae(Z.col,Z.row));z.cacheKey=`toScanner:${A.col},${A.row}:${L.id}:v${d.version}`;let se=Co(e,A,z),ye=L.role===1?0:1;for(let Z of se)C.push({key:`${ye}:start${$(A.col,A.row)}:s${L.id}:${Z.length}:${$(Z[Z.length-1].col,Z[Z.length-1].row)}`,target:L,cells:Z,roleBias:ye})}let P=Pn(e,`scanner:${t.id}:${n}:toRole1`,C,l);return P?{destination:"scanner",nextScannerId:P.target.id,route:Rl(o,r,P.cells,P.target)}:null}function Il(e,t,n,o,r,s,l,d){let v=Le(e),C=[...v.facilityPorts.entries()].filter(([L,V])=>V?.connected&&Rn(e.facilities?.[L])===l);if(!C.length)return null;let P=[];for(let L of s)for(let[V,ne]of C){let z=(ne.keys||[ne.key]).filter(Boolean);if(!z.length)continue;let se=Z=>z.includes(Ae(Z.col,Z.row));se.cacheKey=`toFacility:${L.col},${L.row}:${V}:v${v.version}`;let ye=Co(e,L,se);for(let Z of ye)P.push({key:`start${$(L.col,L.row)}:${V}:${Z.length}:${$(Z[Z.length-1].col,Z[Z.length-1].row)}`,cells:Z,facilityId:V})}let A=Pn(e,`scanner:${t.id}:${n}:${l}`,P,d);return A?{destination:l,facilityId:A.facilityId,route:El(o,r,A.cells,bl(e,A.facilityId))}:null}function ri(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=oi(e,o,pe(t),t.id,!1);if(r){if(["mixer","trash","truck"].includes(r.destination))return!0;if(r.destination==="scanner"){let s=Pt(e,r.nextScannerId);if(ri(e,s,n))return!0}}}return!1}function $l(e,t){return!!Rt(e,t,!1)?.scannerId}function Dn(e){if(e.phase!=="build")return[];let t=[];for(let n of e.eggFarms||[])$l(e,n)||t.push({type:"eggFarm",id:n.id,ref:n,message:"This Egg will not produce chicks"});for(let n of nn)for(let[o,r]of ko(e,n))Le(e).facilityPorts.get(o)?.connected||t.push({type:"facility",id:o,ref:r,message:"This facility cannot receive items"});return t}function Fl(e){let t=Le(e);for(let r of e.eggFarms||[]){let s=Rt(e,r,!1);if(!s?.scannerId)continue;let l=Pt(e,s.scannerId);if(ri(e,l))return[]}let n=e.eggFarms?.length||0,o=[...t.facilityPorts.entries()].filter(([r,s])=>s?.connected&&["mixer","trash","truck"].includes(Rn(e.facilities?.[r]))).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 En(e){return e.kind==="manual"?`S${(e.slot??0)+1}`:`Auto Scanner #${e.id}`}function Bl(e,t=Le(e),n={}){let o=n.includeRoutes!==!1,r=[],s={mixer:"Mixer",trash:"Shredder",truck:"Truck"};for(let l of nn){let d=ko(e,l);if(!d.length){r.push(`${s[l]||l} is missing`);continue}for(let[v]of d)t.facilityPorts.get(v)?.connected||r.push(`${s[l]||l} receiver has no conveyor`)}for(let l of e.scanners){let d=t.scannerPorts.get(l.id)||{};if(d.inputA?.connected||r.push(`${En(l)} input has no conveyor`),d.left?.connected||r.push(`${En(l)} left output has no conveyor`),d.right?.connected||r.push(`${En(l)} right output has no conveyor`),!!o)for(let v of["left","right"])d[v]?.connected&&!oi(e,v,pe(l),l.id)&&r.push(`${En(l)} ${v} route is incomplete`)}if(o)for(let l of e.eggFarms)Rt(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 sn(e){return Fl(e)}function ii(e){return sn(e).length===0}var si=[{key:"premiumFemaleShipment",target:"female",truckTarget:"female",title:"Premium Female Shipment",route:"Female -> Truck",note:"Today only: ship female chicks to Truck. Meet the export target for a bonus.",objective:"truckTarget"},{key:"contaminantSampleExport",target:"poop",truckTarget:"poop",title:"Contaminant Sample Export",route:"Poop value x2",note:"Today only: poop is valid Truck cargo and all poop income is doubled.",objective:"truckTarget",poopValueMultiplier:2},{key:"healthInspection",title:"Health Inspection",route:"Poop -> Shredder",note:"Today only: poop mistakes are fined double. Shred enough poop for an inspection bonus.",objective:"poopTrash",poopFineMultiplier:2},{key:"conveyorJamWarning",title:"Conveyor Jam Warning",route:"No explosions",note:"Today only: jam explosions trigger at 85% congestion. Finish with zero explosions for a bonus.",objective:"noExplosion",congestionExplosionThreshold:.85,congestionWarningThreshold:.68},{key:"powerSavingOrder",title:"Power Saving Order",route:"Slow factory subsidy",note:"Today only: conveyors -20% speed and Auto Scanners +20% cooldown. A subsidy is paid at settlement.",objective:"flatBonus",conveyorSpeedMultiplier:.8,autoScannerCooldownMultiplier:1.2},{key:"overtimeDay",title:"Overtime Day",route:"80 second day",note:"Today only: the work day is longer. No extra reward or penalty.",objective:"none",daySeconds:80},{key:"shortShift",title:"Short Shift",route:"40 second day",note:"Today only: the work day is shorter. The next Fairies tribute is reduced by 10%.",objective:"none",daySeconds:40,fairiesTributeMultiplier:.9},{key:"chickBoom",title:"Chick Boom",route:"EGG interval x0.65",note:"Today only: eggs hatch faster and poop rate rises by 5 percentage points.",objective:"none",productionMultiplier:1/.65,poopRateAdd:.05},{key:"rottenFeed",title:"Rotten Feed",route:"Poop surge",note:"Today only: poop rate rises by 20 percentage points and Shredder poop income is multiplied by 1.5.",objective:"none",poopRateAdd:.2,shredderIncomeMultiplier:1.5},{key:"maintenanceAudit",title:"Maintenance Audit",route:"Durability check",note:"Today only: machines below 50% remaining durability fail the audit. Passing with none below 50% pays a bonus.",objective:"maintenanceAudit"}];function ve(e,t=0){let n=Number(e);return Number.isFinite(n)?n:t}function Ll(e,t=0,n=1){let o=Math.max(1,Number(e?.turn||1)+1),r=Math.floor(Po(e)*(.08+Math.random()*.08)),s=Math.floor(Math.max(0,e.cash||0)*.25),l=Math.floor(Math.max(0,t)*Math.max(1,o)*.75);return Math.max(120,Math.ceil(Math.max(r,s,l)*n))}function li(e){return Math.max(0,Math.ceil(500+Math.max(1,e?.turn||1)*25))}function Po(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 Ol(e,t=1,n=vt){return e.eggFarms.reduce((o,r)=>{let[s,l]=rn(r),d=Math.max(.1,(s+l)/2);return o+Math.max(1,n)/d*Math.max(.01,t||1)},0)}function Nl(e,t){let n=ve(t.productionMultiplier,1),o=ve(t.daySeconds,vt),r=Ol(e,n,o),s=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),l=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),d=Math.pow(1.03,s),v=ao+co*l,C=Math.min(.95,Math.max(0,(v+ve(t.poopRateAdd,0))*ve(t.poopMultiplier,1)*d));return{estimate:r,poopRate:C}}function ai(e){if(e.turn+1Cr)return null;let n=si[Math.floor(Math.random()*si.length)],{estimate:o,poopRate:r}=Nl(e,n),s=0;n.objective==="truckTarget"?s=Math.max(1,Math.ceil(o*.3)):n.objective==="poopTrash"&&(s=Math.max(1,Math.ceil(o*r*.8)));let l=0;return["truckTarget","poopTrash","noExplosion"].includes(n.objective)&&(l=Ll(e,o)),n.objective==="flatBonus"&&(l=li(e)),n.objective==="maintenanceAudit"&&(l=li(e)),{id:`event-${e.turn}-${Date.now()}-${Math.floor(Math.random()*9999)}`,...n,target:n.target||null,truckTarget:n.truckTarget||null,forced:!0,productionMultiplier:ve(n.productionMultiplier,1),poopMultiplier:ve(n.poopMultiplier,1),poopRateAdd:ve(n.poopRateAdd,0),daySeconds:ve(n.daySeconds,vt),targetAmount:s,estimatedOutput:Math.round(o),reward:l,createdTurn:e.turn,oneTurnOnly:!0}}function ci(e){e.eventActive=e.eventOffer?{...e.eventOffer}:null,e.eventOffer=null}function ui(e){e.eventActive=null}function di(e){return Math.max(1,ve(e.eventActive?.daySeconds,vt))}function fi(e){return ve(e.eventActive?.productionMultiplier,1)}function pi(e){let t=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),n=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),o=Math.pow(1.03,t),r=ao+co*n,s=ve(e.eventActive?.poopRateAdd,0);return Math.min(.95,Math.max(0,(r+s)*ve(e.eventActive?.poopMultiplier,1)*o))}function Je(e){return e.eventActive?.truckTarget||e.eventActive?.target||"female"}function Ro(e,t){return t==="male"?e.truckMale||0:t==="poop"?e.poopTruck||0:e.truckFemale||0}function yi(e,t){return Je(e)===t}function hi(e){return Je(e)!=="male"}function Ao(e){return Math.max(.01,ve(e.eventActive?.poopValueMultiplier,1))}function In(e){return Math.max(.01,Ao(e)*ve(e.eventActive?.shredderIncomeMultiplier,1))}function Do(e){return Math.max(.01,ve(e.eventActive?.poopFineMultiplier,1))}function Io(e){return Math.max(.1,Math.min(1,ve(e.eventActive?.congestionExplosionThreshold,1)))}function mi(e){return Math.max(.1,Math.min(1,ve(e.eventActive?.congestionWarningThreshold,.8)))}function bi(e){return Math.max(.01,ve(e?.fairiesTributeMultiplier,1))}function Gl(e){let t=0,n=(o,r)=>{let s=Math.max(1,ve(r,1)),l=Math.max(0,ve(o,0));1-Math.min(1,l/s)<.5&&(t+=1)};for(let o of e.conveyorMeta?.values?.()||[])n(o.uses,o.durability);for(let o of e.eggFarms||[])n(o.maintenance?.uses,o.maintenance?.durability);for(let o of e.scanners||[])o.kind==="auto"&&n(o.maintenance?.uses,o.maintenance?.durability);for(let o of Object.values(e.facilities||{})){let r=o?.baseId||o?.id;(r==="mixer"||r==="trash")&&n(o.maintenance?.uses,o.maintenance?.durability)}return t}function vi(e){let t=e.eventActive;if(!t)return null;let n=0,o=!0,r=0,s="";t.objective==="truckTarget"?(n=Ro(e.stats,t.target),o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="poopTrash"?(n=e.stats.poopTrash||0,o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="noExplosion"?(n=e.stats.explosions||0,o=n===0,r=o?t.reward:0,s=`${n} explosion(s)`):t.objective==="flatBonus"?(o=!0,r=t.reward):t.objective==="maintenanceAudit"?(n=Gl(e),o=n===0,o&&(r=t.reward),s=`${n} machine(s) below 50%`):o=!0,r>0?(Oe(e,r),e.stats.eventBonus=(e.stats.eventBonus||0)+r,e.totals.eventBonus+=r,e.totals.eventSuccess+=1):t.objective&&t.objective!=="none"&&(e.stats.eventBonus=e.stats.eventBonus||0,e.totals.eventFailed+=o?0:1,o&&(e.totals.eventSuccess+=1));let l={title:t.title,key:t.key,target:t.target,route:t.route,objective:t.objective,targetAmount:t.targetAmount||0,count:n,success:o,bonus:r,reward:t.reward||0,productionMultiplier:t.productionMultiplier,poopMultiplier:t.poopMultiplier,daySeconds:t.daySeconds,detail:s};return e.stats.eventResult=l,l}function $o(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Ul(e){return!!e?.cardEffects?.usedMachineActive}function Wl(e,t){return t?1:Math.min(.8,.5+.1*Math.min(3,$o(e,"recyclingSubsidy")))}function _l(e){return Math.pow(.95,$o(e,"safetyCover"))}function $n(e){let t=e?.ref||e||{},n=e?.type||t.type;return n==="conveyor"?t.price||Se[t.kind]?.price||Se.conveyor.price:n==="eggFarm"?t.price||Se.eggFarm.price:n==="scanner"?t.price||(t.kind==="auto"?Se.autoScanner.price:Se.manualScanner.price):n==="facility"?t.price||Se[t.id]?.price||0:Se[t.id]?.price||0}function Ne(e,t=null){let n=Se[e]?.price||0;return Ul(t)?Math.ceil(n*.5):n}function Kl(e,t){return e?.facilities?Object.values(e.facilities).filter(n=>(n?.baseId||n?.id)===t).reduce((n,o)=>n+Math.max(0,(o.level||1)-1),0):0}function ct(e,t){return gr.includes(t)?Math.pow(xe.incomeUpgradeRate,Kl(e,t)):1}function qe(e){return Math.ceil(xe.income.mixer*ct(e,"mixer"))}function De(e){return Math.ceil(xe.income.truck*ct(e,"truck"))}function ln(e){return Math.ceil(xe.poopFine*ct(e,"mixer")*Do(e))}function an(e){return Math.ceil(xe.poopFine*ct(e,"truck")*Do(e))}function Fo(e){let t=xe.maleTruckFinePerHalfDay*(e.turn/2);return Math.ceil(t*ct(e,"truck"))}function Bo(e){return e?.facilities?Object.values(e.facilities).filter(t=>(t?.baseId||t?.id)==="trash").reduce((t,n)=>t+Math.max(0,(n.level||1)-1),0):0}function At(e){return Math.min(xe.shredderBonus.maxCards,Bo(e))}function Kt(){return xe.shredderBonus.maxCards}function ut(e){let t=typeof e=="number"?e:At(e),n=Math.min(xe.shredderBonus.maxCards,Math.max(0,t));return n>0?Math.ceil(n*(xe.shredderBonus.incomePerUpgrade||1)):0}function Hl(e){let t=At(e),n=ut(t),o=Math.ceil(n*In(e));return{cards:t,chance:o>0?1:0,amount:o,expected:o,baseAmount:n}}function wi(e){let t=Hl(e);return t.amount>0&&(e.stats.shredderBonus=(e.stats.shredderBonus||0)+t.amount,e.totals.shredderBonus=(e.totals.shredderBonus||0)+t.amount,Oe(e,t.amount)),t}function Fn(e,t=e.turn,n=null){let o=Math.max(1,Math.floor(Number(t)||1)),r=xe.fairiesTribute||{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},s=Math.ceil(o*(r.perDay||10)),l=Math.max(0,Math.floor(Number(n??e?.lastResult?.profit??e?.stats?.profit??0)||0)),d=Math.max(0,e?.cardEffects?.legalWork||0),v=Math.max(0,(r.profitExemption||0)+d*(r.legalWorkExemptionBonus||0)),C=Math.max(0,l-v),P=Math.ceil(C*Math.max(0,Number(r.profitRate)||0)),A=s+P,L=Math.max(0,e?.cardEffects?.fairiesFlatteryNext||e?.cardEffects?.flattery||0),V=L>0?Math.pow(.5,L):1,ne=Math.max(.01,Number(e?.pendingFairiesTributeMultiplier)||1),z=V*ne,se=Math.max(0,Math.ceil(A*z)),ye=Math.max(0,A-se);return{day:o,base:s,profit:l,legalWork:d,profitExemption:v,taxableProfit:C,profitTribute:P,gross:A,flatteryCount:L,eventMultiplier:ne,perCardReduction:Math.ceil(A*.5),reduction:ye,amount:se}}function Dt(e,t){let n=e?.ref||e||{},o=e?.type==="conveyor"?t?.conveyorMeta?.get(e.oldKey||n.id):n,r=o?.price||$n(e||n),s=o?.builtSession===t?.buildSession;if(o?.noRefund||n?.noRefund)return{amount:0,sameBuild:s,price:r,rate:0,noRefund:!0};let l=Wl(t,s);return{amount:Math.max(0,Math.ceil(r*l)),sameBuild:s,price:r,rate:l,noRefund:!1}}function ql(e,t=null){let n=Math.max(1,Math.ceil((Number(e)||0)/xe.explosionDamageDivisor));return Math.max(1,Math.ceil(n*_l(t)))}function Yl(e,t){return Math.max(0,Math.ceil(t))}function Si(e,t){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 Oe(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Si(e,n),n}function dt(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Si(e,-n),n}function ft(e,t){dt(e,t)}function xi(e,t){t<=0||(e.cash+=t,e.stats.profit+=t,e.totals.profit+=t,e.totals.maxCash=Math.max(e.totals.maxCash,e.cash))}function ki(e){let t=qe(e);return e.stats.mixerRevenue+=t,Oe(e,t),t}function Ci(e){let t=ln(e);return e.stats.mixerPoopFine+=t,e.totals.mixerPoopFine+=t,dt(e,t),t}function Mi(e){let t=an(e);return e.stats.truckPoopFine+=t,e.totals.truckPoopFine+=t,dt(e,t),t}function gi(e){let t=Fo(e);return e.stats.maleTruckFine+=t,e.totals.maleTruckFine+=t,dt(e,t),t}function Ti(e,t){let n=ql(t,e);return e.stats.explosionDamage+=n,e.totals.explosionDamage+=n,dt(e,n),n}function Ei(e){let t=Je(e),n=Ro(e.stats,t),o=t==="poop"?Math.ceil(De(e)*Ao(e)):De(e),r=n*o,s=Yl(e,r);return e.stats.pendingTruckRevenue=s,e.stats.truckRevenue=s,t==="poop"?e.stats.poopShipmentIncome=s:e.stats.chickShipmentIncome=s,s>0&&Oe(e,s),{base:r,adjusted:s,target:t,targetCount:n,unitPrice:o}}function Pi(e,t=e.turn,n=null,o={}){let r=Fn(e,t,n);return e.cardEffects&&(e.cardEffects.fairiesFlatteryNext=0,e.cardEffects.flattery!=null&&delete e.cardEffects.flattery),e.pendingFairiesTributeMultiplier!=null&&(e.pendingFairiesTributeMultiplier=1),r.amount<=0||(o.recordStats?(e.stats.fairiesTribute=(e.stats.fairiesTribute||0)+r.amount,e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,dt(e,r.amount)):(e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,e.totals.penalty=(e.totals.penalty||0)+r.amount,e.totals.profit=(e.totals.profit||0)-r.amount,e.cash-=r.amount)),r}function Ri(e){let t=$o(e,"chemicalWeaponSubsidy"),n=Math.max(0,e?.stats?.poopTruck||0),o=xe.chemicalWeaponSubsidy||{poopPerBlock:70,yenPerBlock:1200},r=Math.floor(n/Math.max(1,o.poopPerBlock||70)),s=t>0&&r>0?r*Math.max(0,o.yenPerBlock||1200)*t:0;return s>0&&(e.stats.chemicalWeaponSubsidy=(e.stats.chemicalWeaponSubsidy||0)+s,e.totals.chemicalWeaponSubsidy=(e.totals.chemicalWeaponSubsidy||0)+s,Oe(e,s)),{cards:t,poopTruck:n,blocks:r,amount:s}}function Ai(e){let t=Po(e),n=Math.max(1,e.totals.turnsCompleted||e.turn||1),o=Math.max(0,e.cash+e.totals.revenue+t*.5+e.totals.eventBonus*.5),r=Math.ceil(o/n),s=Math.floor(n*35+Math.max(0,n-5)*15),l=e.totals.correct*5,d=e.totals.explosionDamage;return{score:Math.max(0,Math.floor(o+r+l-e.totals.penalty-s)),factoryValue:t,base:o,dailyEarned:r,dayPenalty:s,correctBonus:l,explosionPenalty:d,days:n}}function Vl(e){return{...e,keys:e.keys?{left:{...e.keys.left},right:{...e.keys.right}}:null,queue:[],cooldown:e.cooldown||0}}function cn(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(Vl),conveyorTiles:[...e.conveyorTiles],conveyorMeta:[...e.conveyorMeta.entries()],branchCounters:[...e.branchCounters.entries()],cardEffects:e.cardEffects,cardDraft:e.cardDraft,cardTargetPick:e.cardTargetPick})}function Di(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??q.grid.x,y.y=n.gridY??q.grid.y,y.cols=n.gridCols||q.grid.cols,y.rows=n.gridRows||q.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,fairiesFlatteryNext:0,scannerQueueSpacing: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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=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 $e(e){e.phase==="build"&&(e.undoStack.push(cn(e)),e.undoStack.length>80&&e.undoStack.shift(),e.redoStack=[])}function Lo(e){return e.phase!=="build"||!e.undoStack.length?!1:(e.redoStack.push(cn(e)),Di(e,e.undoStack.pop()),!0)}function Oo(e){return e.phase!=="build"||!e.redoStack.length?!1:(e.undoStack.push(cn(e)),Di(e,e.redoStack.pop()),!0)}function _(e,t,n,o,r=f.ink){e.floatingTexts.push({x:t,y:n,text:o,color:r,life:1,maxLife:1})}function It(e,t,n){e.shake.strength=Math.max(e.shake.strength,t),e.shake.time=Math.max(e.shake.time,n)}function Ii(e,t,n){e.effects.push({type:"spawn",priority:ke.ambient,x:t,y:n,life:.42,maxLife:.42,size:12})}function $i(e,t,n,o=f.green){e.effects.push({type:"scannerPulse",priority:ke.important,x:t,y:n,color:o,life:.42,maxLife:.42,size:24})}function Fi(e,t,n){for(let o=0;o<12;o+=1)e.effects.push({type:"meat",priority:ke.important,x:t+U(-18,18),y:n+U(-12,16),vx:U(-60,60),vy:U(-90,-25),life:U(.45,.85),maxLife:.85,size:U(4,8)})}function Bi(e,t,n){for(let o=0;o<16;o+=1)e.effects.push({type:"sludge",priority:ke.important,x:t+U(-18,18),y:n+U(-12,16),vx:U(-46,46),vy:U(-70,-20),life:U(.45,.9),maxLife:.9,size:U(4,8)})}function Li(e,t,n,o){let r=o==="poop"?f.poop:o==="male"?f.male:f.female;for(let s=0;s<22;s+=1)e.effects.push({type:"shred",priority:ke.important,x:t+U(-16,16),y:n+U(-8,8),vx:U(-70,70),vy:U(40,160),color:s%3===0?f.white:r,life:U(.45,.95),maxLife:.95,w:U(3,7),h:U(10,24),rot:U(-Math.PI,Math.PI)});Ye(e,t,n,f.green,34,ke.important)}function Oi(e,t,n,o){let r=o==="poop"?f.poop:o==="male"?f.danger:f.green;for(let s=0;s<8;s+=1)e.effects.push({type:"load",priority:ke.important,x:t+U(-18,18),y:n+U(-18,18),vx:U(-42,42),vy:U(-90,-25),color:r,life:U(.35,.65),maxLife:.65,size:8})}function Ye(e,t,n,o=f.danger,r=52,s=ke.critical){e.effects.push({type:"shockwave",priority:s,x:t,y:n,color:o,life:.55,maxLife:.55,size:8,maxSize:r})}function je(e,t,n,o=12,r=f.danger,s=ke.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||zl(e,r,o);let s=r.x+e.view.x,l=r.y+e.view.y;(s<-100||l<-100||s>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 zl(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=Ti(e,o.price);_(e,t.x,t.y-10,`-${M(r)}`,f.danger),Ye(e,t.x,t.y,f.danger,30),je(e,t.x,t.y,5,f.danger),It(e,5,.18)}}var Fe=q.maintenance;function Go(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Nn(e){let t=Math.min(1.4,1+.04*Math.min(10,Go(e,"crowdedFarming"))),n=Math.pow(.95,Go(e,"preventiveMaintenance"));return t*n}function Xl(e){return Math.pow(1.03,Go(e,"durabilityCoating"))}function Gn(e,t,n=1){let o=Fe.durability[t]||1e3;return Math.max(1,Math.ceil(o*Math.max(.1,n||1)*Xl(e)))}function _o(e){let t=Fe.repairman.dailyCost;return e?.cardEffects?.laborExploitation?Math.ceil(t*.7):t}function Ui(e){return Math.max(.1,Number(e?.durabilityBaseMultiplier)||1)}function me(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"),n.kind||(n.kind="conveyor"),n.speedMultiplier||(n.speedMultiplier=n.kind==="boostConveyor"?2:1),n.branchMode||(n.branchMode="random");let o=Gn(e,"conveyor",Ui(n));(n.durability==null||n.durability0&&(n.processingCooldown=Math.max(0,n.processingCooldown-t))}function Hn(e){me(e);let t=[];for(let[n,o]of e.conveyorMeta||[])t.push({type:"conveyor",key:n,meta:o,label:`${o.kind==="boostConveyor"?"Boost Belt":"Belt"} ${n}`,center:F(Q(n).col,Q(n).row)});for(let n of e.eggFarms||[])t.push({type:"eggFarm",ref:n,label:`EGG #${n.id}`,center:F(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:F(n.col,n.row)});for(let n of Object.values(e.facilities||{})){let o=Kn(n);["mixer","trash"].includes(o)&&t.push({type:o,ref:n,label:`${n.shortName||n.name||o} #${n.id}`,center:{x:n.x+n.w/2,y:n.y+n.h/2}})}return t}function Ln(e){return e.meta?Ht(e):Ht(e.ref)}function un(e){return e.meta?Uo(e):Uo(e.ref)}function On(e){return e.meta?Wo(e):Wo(e.ref)}function qi(e,t){Ql(e.meta?e:e.ref,Math.max(0,un(e)-t))}function Yi(e){return e.type==="conveyor"?`conveyor:${e.key}`:`${e.type}:${e.ref?.id||e.ref?.type||e.type}`}function Vi(e,t=.02){me(e);let n=Math.max(0,Number(t)||0),o=0;for(let r of Hn(e)){let s=un(r);qi(r,On(r)*n),o+=Math.max(0,s-un(r))/On(r)*100}return o}function zi(e){if(me(e),e.repairman.hiredForNextDay)return{ok:!1,reason:"Repairman already hired."};let t=_o(e);return e.cashYi(o)===t.key)||null}function Zl(e){let t=null;for(let n of Hn(e)){let o=Ln(n);o<=.001||(!t||o>Ln(t))&&(t=n)}return t}function Ji(e,t){me(e);let n=e.repairman;if(!n.active||e.phase!=="running")return;let o=jl(e,n.target)||Zl(e);if(!o){n.target=null;return}n.target={key:Yi(o),label:o.label};let r=Fe.repairman.walkSpeed,s=o.center.x-n.x,l=o.center.y-n.y,d=Math.hypot(s,l);if(d>8){let L=Math.min(d,r*t);n.x+=s/d*L,n.y+=l/d*L;return}let v=t/(Fe.repairman.secondsPerOnePercent*100),C=un(o),P=v*On(o);qi(o,P);let A=Math.max(0,(C-un(o))/On(o)*100);n.repairedToday=(n.repairedToday||0)+A,A>0&&Math.random()<.02&&_(e,n.x,n.y-28,"REPAIR",f.green),Ln(o)<=.001&&(n.target=null)}function ea(e){let t=0,n="none";for(let o of Hn(e)){let r=Ln(o);r>t&&(t=r,n=o.label)}return{ratio:t,percent:Math.round(t*100),label:n}}function Qo(e){let t=ea(e),n=Ho(e);return{worst:t,avgBeltPerformance:n,repairman:e.repairman||null}}var ta=Re.commonWeight,na=Re.rareWeight,oa=Re.ultraRareWeight||.45,$t=Re.baseDraftSize,Yt=Mr;function qt(e,t){let n=Ie(e);return Math.max(0,Number(n[t])||0)}function Ie(e){e.cardEffects||(e.cardEffects={...uo});for(let[t,n]of Object.entries(uo))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),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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=0),e.cardEffects}function is(e){let t=Math.max(.5,1-.05*Math.min(10,qt(e,"crowdedFarming"))),n=Math.pow(.96,qt(e,"hatchingFeed"));return t*n}function ss(e,t=null){return Math.min(3,Math.max(0,Number(t?.extraEggOutlet)||0))}function ls(e){return Math.pow(.85,qt(e,"scannerQueueSpacing"))}function Yn(e,t=null){let n=Ie(e),o=xn*Math.pow(kn,Math.max(0,n.bearing||0)),r=t?Math.max(.1,Number(e?.conveyorMeta?.get?.(t)?.speedMultiplier)||1):1,s=t?1:Ho(e),l=Math.max(.01,Number(e?.eventActive?.conveyorSpeedMultiplier)||1);return Math.min(Gt,o*s)*r*l}function et(e,t=null){let n=Math.max(0,(e?.level||1)-1),o=t?qt(t,"autoScannerTuning"):0,r=Sn*Math.pow(kr,n)*Math.pow(so,o),s=Math.max(lo,r),l=t?Math.max(.01,Number(t?.eventActive?.autoScannerCooldownMultiplier)||1):1;return t?Math.max(lo,s*Wn(e)*l):s}function ji(e){let t=e.cardDraft||{rerolls:0},n=Math.max(1,(t.rerolls||0)+1);return Math.ceil(Math.max(1,e.turn||1)/Re.rerollCost.dayDivisor*n*Re.rerollCost.multiplier)}function Vt(e){return Yt.find(t=>t.id===e)||null}function as(e,t){let n=typeof t=="string"?Vt(t):t;return Ie(e),!n||!(n.type==="equipmentUpgrade"||n.type==="cellAction")?[]:Ue(e,n).map(o=>({key:Ze(o),label:Zo(e,o),type:o.type}))}function jo(e,t,n={}){let o=typeof t=="string"?Vt(t):t;if(Ie(e),!o||o.type==="dud")return{ok:!1,reason:"Card not found."};if(o.id==="extraCards")return e.cardDraft=e.cardDraft||{pending:!1,choices:[],rerolls:0,picksRemaining:0},e.cardDraft.choices.push(...qn(e,2)),{ok:!0,reason:`${o.title} added 2 draft cards.`};if(o.type==="instant")return us(e,o),{ok:!0,reason:`${o.title} granted.`};if(o.type==="equipmentUpgrade"){let r=Ue(e,o);if(!r.length)return{ok:!1,reason:`No valid target for ${o.title}.`};let s=n.targetKey&&n.targetKey!=="__auto__"?String(n.targetKey):"",l=s?r.find(d=>Ze(d)===s):r[0];return l?(cs(e,l),{ok:!0,reason:`${o.title} applied to ${Zo(e,l)}.`}):{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`}}if(o.type==="cellAction"&&o.target==="blockedCell"){let r=Ue(e,o);if(!r.length)return{ok:!1,reason:"No blocked cells to remove."};let s=new Set((Array.isArray(n.targetKeys)?n.targetKeys:[n.targetKey]).filter(d=>d&&d!=="__auto__").map(String)),l=s.size?r.filter(d=>s.has(Ze(d))):r.slice(0,3);if(!l.length)return{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`};for(let d of l.slice(0,3)){e.blockedCells.delete($(d.col,d.row));let v=F(d.col,d.row);pt(e,v.x,v.y),Ye(e,v.x,v.y,f.danger,42),je(e,v.x,v.y,8,f.warn)}return be(e),{ok:!0,reason:`${o.title} removed ${Math.min(3,l.length)} blocked cell(s).`}}return{ok:!1,reason:`${o.title} cannot be debug-granted.`}}function Zo(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 ${et(t,e).toFixed(1)}s -> ${et({...t,level:t.level+1},e).toFixed(1)}s`;if(t.type==="facility"&&(t.baseId||t.id)==="mixer"){let n=t.level,o=qe(e);t.level=n+1;let r=qe(e);return t.level=n,`MIXER L${t.level} -> L${t.level+1} | ${M(o)} -> ${M(r)}`}if(t.type==="facility"&&(t.baseId||t.id)==="truck"){let n=t.level,o=De(e);t.level=n+1;let r=De(e);return t.level=n,`TRUCK L${t.level} -> L${t.level+1} | ${M(o)} -> ${M(r)}`}if(t.type==="facility"&&t.id==="trash"){let n=At(e),o=Math.min(Kt(),n+1),r=ut(n),s=ut(o);return`SHREDDER L${t.level||1} -> L${(t.level||1)+1} | poop income ${M(r)} -> ${M(s)} per item`}return`${t.name||t.id} L${t.level||1} -> L${(t.level||1)+1}`}function ra(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"?Vt(t):t;return Ie(e),n?n.target==="blockedCell"?ra(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"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="mixer"):n.target==="truck"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="truck"):n.target==="trash"?Bo(e)(o.baseId||o.id)==="trash"):[]:[]:[]}function ia(e,t){let n=Ie(e);if(t.id==="crowdedFarming")return(n.crowdedFarming||0)>=10;if(t.id==="recyclingSubsidy")return(n.recyclingSubsidy||0)>=3;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,Re.dudChancePerCard||0)),r=Math.max(1e-4,Math.min(1,Re.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 sa(e){let t=e.repairman||{};return!!(t.active||t.hiredForNextDay||e.pendingRepairWorkerWages>0)}function la(e){return Yt.filter(t=>!(t.id==="laborExploitation"&&!sa(e)||ia(e,t)||(t.type==="equipmentUpgrade"||t.type==="cellAction")&&Ue(e,t).length<=0))}function Zi(e,t){return t.rarity==="ultraRare"?oa:t.rarity==="rare"?na:ta}function aa(e,t){let n=t.reduce((r,s)=>r+Zi(e,s),0);if(n<=0)return t[Math.floor(Math.random()*t.length)];let o=Math.random()*n;for(let r of t)if(o-=Zi(e,r),o<=0)return r;return t[t.length-1]}var es=0;function ca(){return es+=1,{id:`dud:${Date.now()}:${es}`,title:"Dud",rarity:"dud",type:"dud",description:"Click to flick this dud away. It does not consume a pick."}}function ua(e){let t=Ie(e),n=Math.max(0,Math.min(1,Re.dudChancePerCard||0)),o=Math.max(0,Math.min(1,Re.dudChanceReductionPerFilter||0));return Math.max(0,n-o*Math.max(0,t.dudFilter||0))}function da(e,t){let n=[...t],o=0,r=Math.max(0,Re.maxDudsPerDraft||0),s=ua(e);for(let l=0;ld.id===s.id);l>=0&&r.splice(l,1)}return da(e,o)}function Ze(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 ts(e){if(!e)return null;if(e.type==="blockedCell"){let t=F(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=F(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=pe(e);return{x:t.x-54,y:t.y-77,w:108,h:154,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 er(e){if(!e.cardTargetPick?.pending)return[];if(e.cardTargetPick.mode==="autoScannerMenu"){let n=new Set(e.cardTargetPick.targetKeys||[]);return e.scanners.filter(o=>o.kind==="auto"&&n.has(Ze(o))).map(o=>({key:Ze(o),label:"AUTO ROUTE SETTINGS",target:o,bounds:ts(o)})).filter(o=>o.bounds)}let t=new Set(e.cardTargetPick.targetKeys||[]);return Ue(e,e.cardTargetPick.cardId).filter(n=>t.has(Ze(n))).map(n=>({key:Ze(n),label:Zo(e,n),target:n,bounds:ts(n)})).filter(n=>n.bounds)}function fa(e,t){let n=er(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 cs(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=F(n.col,n.row);_(e,o.x,o.y-30,`OUTLET ${1+n.extraEggOutlet}`,f.green),be(e);return}if(t.level=(t.level||1)+1,t.type==="eggFarm"){t.nextSpawn=Mt(t),t.lastInterval=t.nextSpawn;let n=F(t.col,t.row);_(e,n.x,n.y-30,`LV ${t.level}`,f.green);return}if(t.type==="scanner"){let n=pe(t);_(e,n.x,n.y-34,`LV ${t.level}`,f.green);return}t.type==="facility"&&_(e,t.x+t.w/2,t.y+18,`LV ${t.level}`,f.green)}function us(e,t){let n=Ie(e),o=r=>{n[r]=Math.max(0,n[r]||0)+1};if(t.id==="bearing"&&o("bearing"),t.id==="autoScannerTuning"&&o("autoScannerTuning"),t.id==="legalWork"&&o("legalWork"),t.id==="crowdedFarming"&&(n.crowdedFarming=Math.min(10,(n.crowdedFarming||0)+1)),t.id==="hatchingFeed"&&o("hatchingFeed"),t.id==="poopRateBooster"&&o("poopRateBooster"),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"),me(e)),t.id==="sparePartsBin"){o("sparePartsBin");let r=Vi(e,.02);e.stats.sparePartsRepair=(e.stats.sparePartsRepair||0)+r,e.totals.sparePartsRepair=(e.totals.sparePartsRepair||0)+r,_(e,y.x+y.cols*y.cell/2,y.y-30,"REPAIR +2%",f.green)}t.id==="dudRefund"&&o("dudRefund"),t.id==="freeReroll"&&o("freeReroll"),t.id==="composter"&&o("composter"),t.id==="scannerQueueSpacing"&&o("scannerQueueSpacing"),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"),_(e,y.x+y.cols*y.cell/2,y.y-30,"RESCUE HELD",f.green))}function _e(e){return`${Math.round(Number(e||0)*100)}%`}function ns(e){let t=st[Math.max(0,Math.min(st.length-1,e-1))]||st[0]||[0,0];return`${t[0].toFixed(2)}-${t[1].toFixed(2)}s`}function os(e,t){return Math.ceil(e*Math.pow(xe.incomeUpgradeRate,Math.max(0,t-1)))}function rs(e,t,n){let r=Ue(e,t==="mixer"?"upgradeMixer":"upgradeTruck")[0];if(!r)return{before:os(n,1),after:os(n,2)};let s=t==="mixer"?qe(e):De(e),l=r.level||1;r.level=l+1;let d=t==="mixer"?qe(e):De(e);return r.level=l,{before:s,after:d}}function pa(e,t){let n=Ie(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 ${ns(r)} -> ${ns(r+1)}.`}if(t.id==="upgradeAutoScanner"){let o=Ue(e,t)[0]||{level:1},r=et(o,e),s=et({...o,level:(o.level||1)+1},e);return`Choose one AUTO SCANNER. Level +1. Cooldown ${r.toFixed(2)}s -> ${s.toFixed(2)}s.`}if(t.id==="upgradeMixer"){let o=rs(e,"mixer",xe.income.mixer);return`Choose one MIXER. Earning +10%. Male-chick income ${M(o.before)} -> ${M(o.after)}.`}if(t.id==="upgradeTruck"){let o=rs(e,"truck",xe.income.truck);return`Choose one TRUCK. Earning +10%. Correct shipment income ${M(o.before)} -> ${M(o.after)}.`}if(t.id==="upgradeTrash"){let o=At(e),r=Math.min(Kt(),o+1),s=ut(o),l=ut(r);return`SHREDDER level +1. Poop income ${M(s)} -> ${M(l)} per item.`}if(t.id==="bearing"){let o=Math.min(Gt,xn*Math.pow(kn,Math.max(0,n.bearing||0))),r=Math.min(Gt,xn*Math.pow(kn,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`Fairies tribute profit exemption +${M(250)}. After pick: exemption bonus ${M(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 ${_e(Math.max(.5,1-.05*o))}, deterioration ${_e(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 ${_e(Math.pow(.96,(n.hatchingFeed||0)+1))}, poop rate multiplier ${_e(Math.pow(1.03,(n.hatchingFeed||0)+1))}.`;if(t.id==="poopRateBooster")return`Held ${n.poopRateBooster||0}. After pick: base poop rate +${Math.round((n.poopRateBooster||0)+1)*4} percentage points.`;if(t.id==="autoScannerTuning")return`Held ${n.autoScannerTuning||0}. After pick: all AUTO SCANNER default cooldown ${_e(Math.pow(so,(n.autoScannerTuning||0)+1))}.`;if(t.id==="safetyCover")return`Held ${n.safetyCover||0}. After pick: explosion damage ${_e(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: ${M(1200*((n.chemicalWeaponSubsidy||0)+1))} per 70 truck-shipped poop each day.`;if(t.id==="preventiveMaintenance")return`Held ${n.preventiveMaintenance||0}. After pick: deterioration speed ${_e(Math.pow(.95,(n.preventiveMaintenance||0)+1))}.`;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,Re.dudChancePerCard||0)),r=Math.max(0,Math.min(1,Re.dudChanceReductionPerFilter||.05)),s=Math.max(0,n.dudFilter||0),l=Math.max(0,o-r*s),d=Math.max(0,o-r*(s+1));return`Held ${s}. DUD chance per card ${_e(l)} -> ${_e(d)}.`}return t.id==="durabilityCoating"?`Held ${n.durabilityCoating||0}. After pick: maximum durability ${_e(Math.pow(1.03,(n.durabilityCoating||0)+1))}.`:t.id==="sparePartsBin"?`Held ${n.sparePartsBin||0}. Immediately restores 2% durability to every maintained machine. Common card weight.`:t.id==="dudRefund"?`Held ${n.dudRefund||0}. After pick: DUD clicks award ${M(50*((n.dudRefund||0)+1))}.`:t.id==="freeReroll"?`Held ${n.freeReroll||0}. After pick: each card screen starts with ${(n.freeReroll||0)+1} free reroll${(n.freeReroll||0)+1===1?"":"s"}.`:t.id==="composter"?`Held ${n.composter||0}. After pick: SHREDDER poop grants ${M(3*((n.composter||0)+1))}.`:t.id==="scannerQueueSpacing"?`Held ${n.scannerQueueSpacing||0}. After pick: Manual/Auto Scanner queue spacing ${_e(Math.pow(.85,(n.scannerQueueSpacing||0)+1))}.`:t.id==="flattery"?`Next Fairies tribute -50%. Held for next tribute: ${n.fairiesFlatteryNext||0}.`:t.id==="usedMachine"?"Enable Used Machines: future equipment costs 50%, has no SELL refund, and starts with 60% durability.":t.id==="newMachine"?"Cancel Used Machines. Future equipment returns to normal price, refund, and durability.":t.id==="laborExploitation"?"Repairman labor cost -30% permanently. One time only.":t.id==="rescueLoan"?`At day-end bankruptcy check, gain ${M(500)} if cash is below ${M(0)}. Held: ${n.rescueLoanCharges||0}.`:t.description}function Jo(e,t){let n=e.cardDraft?.choices||[],o=n.findIndex(r=>r.id===t.id);o>=0&&n.splice(o,1)}function ds({game:e,ui:t,onUpdatePanels:n}){function o(){n&&n()}function r(){Ie(e),e.cardTargetPick=null,e.cardDraft={pending:!0,choices:qn(e,$t),rerolls:0,freeRerolls:qt(e,"freeReroll"),picksRemaining:1}}function s(){Ie(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(I=$t){Ie(e),e.cardDraft.choices=qn(e,I)}function d(){Ie(e),!e.cardDraft.choices.length&&e.cardDraft.picksRemaining>0&&l($t)}function v(I){Jo(e,I),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1),e.cardTargetPick=null,d(),e.cardDraft.picksRemaining<=0?s():Z()}function C(I){Jo(e,I),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1)+Re.extraCardsAddedPicks,e.cardDraft.choices.push(...qn(e,2)),Z()}function P(I,W){let N=qt(e,"dudRefund")*50;if(N>0){let le=Oe(e,N);e.stats.dudRefundIncome=(e.stats.dudRefundIncome||0)+le,e.totals.dudRefundIncome=(e.totals.dudRefundIncome||0)+le,_(e,y.x+y.cols*y.cell/2,y.y-30,`DUD REFUND +${M(le)}`,f.green)}It(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(()=>{Jo(e,I),d(),Z()},340)}function A(I,W=null){if(I.type==="dud")return P(I,W);if(I.id==="extraCards")return C(I);if(I.type==="equipmentUpgrade"||I.type==="cellAction")return L(I);us(e,I),v(I)}function L(I){let W=Ue(e,I);W.length&&(e.cardTargetPick={pending:!0,cardId:I.id,mode:I.target==="blockedCell"?"blockedCell":"equipment",targetKeys:W.map(Ze),remaining:I.id==="dynamite"?Math.min(3,W.length):1},t.modal.classList.remove("visible","equipment-popover"),o())}function V(I){if(!I||I.type!=="blockedCell")return!1;let W=$(I.col,I.row);if(!e.blockedCells?.has(W))return!1;e.blockedCells.delete(W);let N=F(I.col,I.row);return pt(e,N.x,N.y),Ye(e,N.x,N.y,f.danger,62),je(e,N.x,N.y,18,f.warn),Bn(e,N.x,N.y,8),It(e,16,.35),_(e,N.x,N.y-18,"BOOM",f.danger),be(e),e.cardTargetPick.remaining=Math.max(0,(e.cardTargetPick.remaining||1)-1),e.cardTargetPick.targetKeys=Ue(e,"dynamite").map(Ze),o(),!0}function ne(I){if(!e.cardTargetPick?.pending)return!1;let W=Vt(e.cardTargetPick.cardId),N=fa(e,I);return!W||!N?(z(),!0):W.id==="dynamite"?(V(N)&&((e.cardTargetPick.remaining||0)<=0||!Ue(e,"dynamite").length)&&v(W),!0):(cs(e,N),v(W),!0)}function z(){e.cardTargetPick?.pending&&(e.cardTargetPick=null,Z())}function se(){let I=Math.max(0,e.cardDraft?.freeRerolls||0);if(I>0){e.cardDraft.freeRerolls=I-1,e.cardDraft.rerolls+=1,l($t),Z();return}let W=ji(e);e.cashR!==we)].slice(0,5);return N.innerHTML=`${I.title}
${he.map(R=>`${R}`).join("")}
${pa(e,I)}`,N.addEventListener("click",()=>A(I,N)),N.dataset.index=String(W),N}function Z(){Ie(e),e.cardTargetPick=null,e.cardDraft?.pending||r(),e.cardDraft.choices?.length||l($t);let I=e.cardDraft.choices||[],W=ji(e),N=Math.max(0,e.cardDraft?.freeRerolls||0),le=Math.max(1,e.cardDraft.picksRemaining||1);t.modalTitle.textContent="Choose Upgrade Card",t.modalBody.innerHTML=`

Choose ${le} card${le===1?"":"s"} before Build phase. Dud cards can be flicked away without consuming a pick. Equipment cards target machines; Dynamite targets blocked cells.

`;let we=t.modalBody.querySelector("#cardChoices");I.forEach((G,x)=>we.appendChild(ye(G,x))),t.modalActions.innerHTML="";let he=document.createElement("button");he.type="button",he.className="facility-action warn reroll-button",he.textContent=N>0?`Reroll (FREE x${N})`:`Reroll ${M(W)}`,he.disabled=N<=0&&e.cash0?`${N} free reroll${N===1?"":"s"} remaining.`:he.disabled?"Not enough cash":"",he.addEventListener("click",se),t.modalActions.appendChild(he);let R=document.createElement("button");R.type="button",R.className="facility-action",R.textContent="No Card",R.title="Skip this upgrade pick and enter Build phase.",R.addEventListener("click",s),t.modalActions.appendChild(R),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible")}return{prepareDraft:r,showDraft:Z,finishDraft:s,chooseTargetAtPoint:ne,cancelTargetPick:z}}var ya=!1,ha={chickMale:"./assets/images/chick_male.png",chickFemale:"./assets/images/chick_female.png",poop:new URL("../../assets/images/poop.png",import.meta.url).href,conveyor:"./assets/images/conveyor.png",scannerManual:"./assets/images/scanner_manual.png",scannerAuto:"./assets/images/scanner_auto.png",eggFarm:"./assets/images/egg_farm.png",mixer:"./assets/images/mixer.png",shredder:"./assets/images/shredder.png",truck:"./assets/images/truck.png"},ze={};for(let[e,t]of Object.entries(ha)){let n=new Image;n.loaded=!1,n.onerror=()=>{n.loaded=!1},(ya||e==="poop")&&t&&(n.onload=()=>{n.loaded=!0},n.src=t),ze[e]=n}function ys(e,t,n,o){e.clearRect(0,0,t.width,t.height),va(e,t),e.save();let r=n.shake.time>0?U(-n.shake.strength,n.shake.strength):0,s=n.shake.time>0?U(-n.shake.strength,n.shake.strength):0,l=n.view?.scale||1;e.translate((n.view?.x||0)+r,(n.view?.y||0)+s),e.scale(l,l),Sa(e,n),xa(e,n),ka(e,n),Aa(e,n),Oa(e,n),Da(e,n),$a(e,n),ba(e,n),Wa(e,n,o.activeQueuedChick),Qa(e,n),Ya(e,t,n),qa(e,n,o.selectedObject,o.selectedTitle),Va(e,n),za(e,n),Xa(e,n),e.restore(),Ja(e,n,t)}function ma(e){if(e.type==="eggFarm"){let n=F(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 ba(e,t){if(t.phase!=="build")return;let n=Dn(t);for(let o of n){let r=ma(o);e.save(),e.fillStyle="rgba(196,36,36,.22)",e.strokeStyle=f.danger,e.lineWidth=5,e.setLineDash([10,6]),te(e,r.x,r.y,r.w,r.h,!0,!0),e.setLineDash([]),e.fillStyle=f.danger,e.strokeStyle=f.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 te(e,t,n,o,r,s=!0,l=!0){e.beginPath(),e.rect(t,n,o,r),s&&e.fill(),l&&e.stroke()}function nr(e,t,n,o,r=f.ink){e.save(),e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.lineWidth=4,e.strokeStyle=f.white,e.fillStyle=r,e.strokeText(o,t,n),e.fillText(o,t,n),e.restore()}function Ft(e,t,n,o,r,s){return t?.loaded?(e.drawImage(t,n,o,r,s),!0):!1}function va(e,t){e.fillStyle=f.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 kt(t)){let s=Ct(r);e.save(),e.fillStyle=o?"rgba(183,245,198,.34)":"rgba(255,255,255,.22)",e.strokeStyle=o?f.green:f.muted,e.lineWidth=5,e.setLineDash([16,10]),te(e,s.x,s.y,s.w,s.h,!0,!0),e.setLineDash([]);let l=mo(r),d=l.cx,v=l.cy;e.fillStyle="rgba(255,255,255,.94)",e.strokeStyle=f.ink,e.lineWidth=4,te(e,l.x,l.y,l.w,l.h,!0,!0),e.fillStyle=o?f.green:f.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText(r.direction==="right"?"BUY RIGHT LOT":"BUY UPPER LOT",d,v-12),e.fillStyle=f.ink,e.font="900 16px ui-monospace, monospace",e.fillText(`${M(n)} / 10\xD710`,d,v+15),e.fillStyle=f.muted,e.font="900 11px ui-monospace, monospace",e.fillText("blocked tiles included",d,v+30),e.restore()}}function tt(e,t,n,o,r,s,l=0){let d=Ht(s);d<.5||(e.save(),e.globalAlpha=Math.min(.62,.12+d*.54),e.fillStyle="#6b4a23",l>0?(e.beginPath(),e.roundRect?.(t,n,o,r,l),e.roundRect?e.fill():te(e,t,n,o,r,!0,!1)):te(e,t,n,o,r,!0,!1),e.globalAlpha=Math.min(.9,.25+d*.6),e.strokeStyle="#3a2a16",e.lineWidth=Math.max(2,Math.floor(2+d*5)),e.setLineDash([5,6]),te(e,t+3,n+3,o-6,r-6,!1,!0),e.restore())}function tr(e,t){let n=e.componentLookup?.get(t);return(n?e.congestion.get(n):null)?.ratio||0}function ka(e,t){let n=[],o=new Set;for(let s of t.conveyorTiles){let{col:l,row:d}=Q(s);for(let v of ue){let C={col:l+v.dc,row:d+v.dr},P=$(C.col,C.row);if(!t.conveyorTiles.has(P))continue;let A=[s,P].sort().join("|");if(o.has(A))continue;o.add(A);let L=Math.max(tr(t,s),tr(t,P));n.push({a:F(l,d),b:F(C.col,C.row),ratio:L})}}e.save(),e.lineCap="round",e.lineJoin="round";for(let s of[{width:33,color:f.ink,alpha:1},{width:25,color:f.white,alpha:1},{width:17,color:f.greenSoft,alpha:1}]){e.globalAlpha=s.alpha,e.strokeStyle=s.color,e.lineWidth=s.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 s of n){let l=Math.max(0,(s.ratio-.5)/.5);e.strokeStyle=yo(f.green,f.danger,l),e.globalAlpha=s.ratio>.5?.35+l*.55:.8,e.lineWidth=6,e.beginPath(),e.moveTo(s.a.x,s.a.y),e.lineTo(s.b.x,s.b.y),e.stroke()}let r=Pa(t);for(let s of t.conveyorTiles){let l=F(...Object.values(Q(s))),d=t.conveyorMeta.get(s)||{},v=tr(t,s),C=d.kind==="boostConveyor"?"#fff2b8":f.white;e.fillStyle=v>.5?yo(C,"#ffd6d6",Math.max(0,(v-.5)/.5)):C,e.strokeStyle=f.ink,e.lineWidth=2,te(e,l.x-8,l.y-8,16,16,!0,!0),d.kind==="boostConveyor"&&(e.save(),e.strokeStyle=f.warn,e.lineWidth=3,e.beginPath(),e.moveTo(l.x-15,l.y+13),e.lineTo(l.x-3,l.y-13),e.lineTo(l.x+2,l.y-2),e.lineTo(l.x+15,l.y-13),e.stroke(),e.restore()),tt(e,l.x-14,l.y-14,28,28,{meta:d}),Ke(e,t,"conveyor",s,l.x,l.y,38,38),Ra(e,l,r.get(s)||[]);let P=rr(t,s);Ta(e,l,d,Ma(t,s,P),P),v>.5&&nr(e,l.x,l.y-15,`${Math.floor(v*100)}%`,f.danger)}e.restore()}function rr(e,t){let n=Q(t);return ue.filter(o=>e.conveyorTiles.has($(n.col+o.dc,n.row+o.dr))).map(o=>o.name)}function hs(e,t,n){let o=ue.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.($(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function Ca(e,t,n,o=rr(e,t),r="random"){if(o.length<3)return n;let s=Q(t),l=new Set(o.filter(C=>hs(e,s,C)));if(r&&r!=="random"&&o.includes(r)){let C=new Set(l);C.add(r),o.filter(P=>!C.has(P)).length>=2&&l.add(r)}let d=o.filter(C=>!l.has(C));if(d.length)return d;let v=n.filter(C=>!l.has(C));return v.length?v:n}function Ma(e,t,n=rr(e,t)){if(n.length<3)return[];let o=Q(t),r=new Set(n.filter(s=>hs(e,o,s)));return n.filter(s=>{let l=new Set(r);return l.add(s),n.filter(d=>!l.has(d)).length>=2})}function ga(e,t,n){let o=Q(t),r=ue.filter(d=>e.conveyorTiles.has($(o.col+d.dc,o.row+d.dr))).map(d=>d.name),s=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(d=>r.includes(d)),l=r;return s.length?s:l}function Ta(e,t,n,o,r=o){if(r.length<3||o.length<2)return;e.save();let s=o.includes(n.branchMode)?n.branchMode:"random",l=s!=="random";if(e.lineJoin="round",e.lineCap="round",e.lineWidth=2,e.fillStyle="rgba(255,255,255,.9)",e.strokeStyle=l?f.warn:f.green,te(e,t.x-17,t.y-17,34,34,!0,!0),e.strokeStyle=f.ink,e.lineWidth=2,e.fillStyle=f.ink,s!=="random"){let d=ue.find(v=>v.name===s);Vn(e,t.x,t.y,d?.angle||0,9,6)}else e.beginPath(),e.moveTo(t.x-10,t.y),e.lineTo(t.x-2,t.y),e.lineTo(t.x+8,t.y-8),e.moveTo(t.x-2,t.y),e.lineTo(t.x+8,t.y+8),e.stroke(),Vn(e,t.x+9,t.y-9,-Math.PI/4,4,3),Vn(e,t.x+9,t.y+9,Math.PI/4,4,3);e.restore()}function Ea(e,t,n){if(!n)return[];let o=Q(t),r=ue.filter(d=>e.conveyorTiles.has($(o.col+d.dc,o.row+d.dr))).map(d=>d.name),s=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(d=>r.includes(d));return Ca(e,t,s.length?s:ga(e,t,n),r,n.branchMode||"random").map(d=>ue.find(v=>v.name===d)).filter(Boolean)}function Pa(e){let t=new Map;for(let[n,o]of e.conveyorMeta||[]){let r=Ea(e,n,o);r.length&&t.set(n,r)}return t}function Ra(e,t,n){let o=n.slice(0,4);o.length&&(e.save(),e.fillStyle=f.ink,e.globalAlpha=.86,o.forEach(r=>{Vn(e,t.x+r.dc*12,t.y+r.dr*12,r.angle,6,5)}),e.restore())}function Vn(e,t,n,o,r=11,s=8){e.save(),e.translate(t,n),e.rotate(o),e.beginPath(),e.moveTo(r,0),e.lineTo(-r*.72,-s),e.lineTo(-r*.72,s),e.closePath(),e.fill(),e.restore()}function Aa(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=Mo(n),r=[{type:"inputA",p:Ee(n,"inputA"),label:"IN",color:f.green},{type:"left",p:Ee(n,"left"),label:To(o.left),color:Eo(o.left)},{type:"right",p:Ee(n,"right"),label:To(o.right),color:Eo(o.right)}];for(let s of r){if(!s.p)continue;let l=F(s.p.col,s.p.row),d=jr(t,n,s.type||(s.label==="IN"?"inputA":null))||t.conveyorTiles.has($(s.p.col,s.p.row));e.fillStyle=d?s.color:"#f4c2c2",e.strokeStyle=f.ink,te(e,l.x-18,l.y-12,36,24,!0,!0),e.fillStyle=d&&s.color===f.white?f.ink:f.white,e.fillText(s.label,l.x,l.y+4)}}e.restore()}function Da(e,t){for(let n of t.eggFarms)Ia(e,n,t)}function Ia(e,t,n){let o=F(t.col,t.row);if(e.save(),Ft(e,ze.eggFarm,o.x-29,o.y-29,58,58)){tt(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=f.ink,e.lineWidth=2,te(e,o.x+9,o.y+12,30,18,!0,!0),e.fillStyle=f.ink,e.font="900 10px ui-monospace, monospace",e.textAlign="center",e.fillText(`O${l}`,o.x+24,o.y+24),Ke(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore();return}e.fillStyle=f.white,e.strokeStyle=f.ink,e.lineWidth=4,te(e,o.x-28,o.y-28,56,56,!0,!0),e.fillStyle=f.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=f.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 s=Math.max(0,Math.min(1,t.shutterProgress||0));if(s>0){let l=56*s;e.fillStyle=f.ink,te(e,o.x-28,o.y-28,56,l,!0,!1),e.strokeStyle=f.white,e.lineWidth=2;for(let d=o.y-24;d=1&&(e.fillStyle=f.white,e.font="900 12px ui-monospace, monospace",e.fillText("SHUT",o.x,o.y+4))}tt(e,o.x-28,o.y-28,56,56,t),Ke(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore()}function $a(e,t){for(let n of t.scanners)Fa(e,n,t)}function Fa(e,t,n){let o=pe(t);if(e.save(),t.kind==="manual"&&(n.manualCombo?.count||0)>=10){let v=n.manualCombo.count;e.save(),e.globalAlpha=Math.min(.55,.16+v/120),e.strokeStyle=v>=30?f.warn:f.green,e.lineWidth=Math.min(14,5+Math.floor(v/10)),e.shadowColor=e.strokeStyle,e.shadowBlur=Math.min(28,8+v),te(e,o.x-54,o.y-76,108,152,!1,!0),e.restore()}let r=t.kind==="auto"?ze.scannerAuto:ze.scannerManual;if(Ft(e,r,o.x-50,o.y-73,100,146)){t.kind==="auto"?tt(e,o.x-50,o.y-73,100,146,t):fs(e,t,o),Ke(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore();return}e.fillStyle=t.kind==="auto"?"#d8ffe2":f.white,e.strokeStyle=f.ink,e.lineWidth=4,te(e,o.x-50,o.y-73,100,146,!0,!0),e.fillStyle=t.kind==="auto"?f.green:f.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-48),e.font="900 11px ui-monospace, monospace";let s=t.keys?.left?.label||(t.slot===0?"A":"Left"),l=t.keys?.right?.label||(t.slot===0?"D":"Right");e.fillText(t.role===0?`${s}:M ${l}:NEXT`:`${s}:WASTE ${l}:TRUCK`,o.x,o.y-28);let d=t.queue.length;t.kind==="manual"?(fs(e,t,o),e.fillStyle=d>0?f.green:f.muted,e.font="900 10px ui-monospace, monospace",e.fillText(`Q:${d}`,o.x,o.y+54)):(e.fillStyle=d>0?f.green:f.muted,e.font="900 12px ui-monospace, monospace",e.fillText(`Q:${d} CD:${t.cooldown.toFixed(1)}`,o.x,o.y+54),tt(e,o.x-50,o.y-73,100,146,t)),Ke(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore()}function fs(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 s=t.keyPressTime>0?t.keyPressSide:null,l=n.x-30,d=n.y+18;e.save(),e.lineWidth=3,e.fillStyle="#f7fff5",e.strokeStyle=f.ink,te(e,l-4,d-4,68,25,!0,!0),e.font="900 19px ui-monospace, monospace",e.textAlign="center";for(let v=0;v.8,s=t.y+Math.sin(t.bob)*(r?5:1.5);if(e.save(),n&&(e.strokeStyle=f.green,e.lineWidth=5,e.beginPath(),e.arc(t.x,s,t.radius+8,0,Math.PI*2),e.stroke()),r&&(e.strokeStyle=f.danger,e.lineWidth=3,e.beginPath(),e.arc(t.x,s,t.radius+12+Math.sin(t.bob*2)*4,0,Math.PI*2),e.stroke()),t.sex==="poop")lr(e,t.x,s,t.radius);else{let l=t.sex==="male"?ze.chickMale:ze.chickFemale;Ft(e,l,t.x-t.radius,s-t.radius,t.radius*2,t.radius*2)||(e.fillStyle=t.sex==="male"?f.male:f.female,e.strokeStyle=f.ink,e.lineWidth=5,e.beginPath(),e.arc(t.x,s,t.radius,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle=f.ink,e.beginPath(),e.arc(t.x-6,s-5,2.5,0,Math.PI*2),e.arc(t.x+6,s-5,2.5,0,Math.PI*2),e.fill(),e.fillStyle="#ffaa2e",e.beginPath(),e.moveTo(t.x,s+2),e.lineTo(t.x+9,s+6),e.lineTo(t.x,s+10),e.closePath(),e.fill())}e.restore()}function Ka(e,t){let n=null,o=1/0;for(let[r,s]of e.componentLookup.entries()){let l=Q(r),d=F(l.col,l.row),v=Math.hypot(t.x-d.x,t.y-d.y);vps(o.type,o.id)===ps(t,n))}function Ke(e,t,n,o,r,s,l,d){Ha(t,n,o)&&(e.save(),e.fillStyle="rgba(34,185,79,.18)",e.strokeStyle=f.green,e.lineWidth=(t.multiSelected||[]).length>1?6:4,e.setLineDash((t.multiSelected||[]).length>1?[]:[8,5]),te(e,r-l/2,s-d/2,l,d,!0,!0),e.restore())}function qa(e,t,n,o){if(t.phase==="build"&&(t.multiSelected||[]).length>1){e.save(),e.fillStyle="rgba(255,255,255,.96)",e.strokeStyle=f.ink,e.lineWidth=3,te(e,54-t.view.x,66-t.view.y,214,42,!0,!0),e.fillStyle=f.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=f.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 Ya(e,t,n){if(!n.cardTargetPick?.pending)return;let o=er(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 v of o){let C=v.bounds,P=8;e.rect(C.x-P,C.y-P,C.w+P*2,C.h+P*2)}e.fill("evenodd");let s=n.cardTargetPick?.mode==="blockedCell";if(!o.length){e.fillStyle="rgba(255,255,255,.95)",e.strokeStyle=f.ink,e.lineWidth=3,te(e,(260-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,420/r,42/r,!0,!0),e.fillStyle=f.danger,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(s?"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=f.ink,e.lineWidth=3;let l=Math.max(1,n.cardTargetPick?.remaining||1),d=n.cardTargetPick?.mode==="autoScannerMenu"?"AUTO SCANNER ROUTE SETTINGS. CLICK EMPTY AREA TO CLOSE.":s?`CLICK BLOCKED CELL: ${l} LEFT. PRESS ESC TO CANCEL.`:"CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.";te(e,(216-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,560/r,42/r,!0,!0),e.fillStyle=f.ink,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(d,(496-(n.view?.x||0))/r,(122-(n.view?.y||0))/r),e.restore()}function Va(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),s=Math.abs(n.x2-n.x1),l=Math.abs(n.y2-n.y1);e.save(),e.fillStyle="rgba(34,185,79,.12)",e.strokeStyle=f.green,e.lineWidth=2,e.setLineDash([7,4]),te(e,o,r,s,l,!0,!0),e.restore()}function za(e,t){let n=[...t.effects].sort((o,r)=>(o.priority??ke.ambient)-(r.priority??ke.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=f.green,te(e,o.x-o.size/2,o.y-o.size/2,o.size*1.5,o.size,!0,!1)):o.type==="sludge"?(e.fillStyle=f.poop,te(e,o.x-o.size/2,o.y-o.size/2,o.size*1.4,o.size,!0,!1)):o.type==="spawn"?(e.strokeStyle=f.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||f.danger,te(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||f.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||f.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||f.ink,e.save(),e.translate(o.x,o.y),e.rotate(o.rot||0),te(e,-o.w/2,-o.h/2,o.w,o.h,!0,!1),e.restore()):o.type==="load"?(e.strokeStyle=o.color||f.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=f.ink,e.lineWidth=3,e.setLineDash([4,4]),te(e,o.x-o.size/2,o.y-o.size/2,o.size,o.size,!1,!0)):o.type==="rage"?(e.fillStyle=o.color||f.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText("!",o.x,o.y)):o.type==="flyingChick"&&(o.sex==="poop"?lr(e,o.x,o.y,o.radius||11):ar(e,o.x,o.y,o.sex,o.sex==="male")),e.restore()}}function Xa(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=f.white,e.fillStyle=n.color,e.strokeText(n.text,n.x,n.y),e.fillText(n.text,n.x,n.y)}e.restore()}function Qa(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=f.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?f.danger:f.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=f.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=f.green,te(e,n.x-9,n.y+14,18,8,!0,!0),e.strokeStyle=f.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=f.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?nr(e,n.x,n.y-24,n.target.label,f.green):!n.active&&n.hiredForNextDay&&nr(e,n.x,n.y-24,"NEXT DAY",f.green),e.restore()}function Ja(e,t,n){e.save(),e.font="900 19px ui-monospace, monospace",e.textAlign="left",e.fillStyle=f.ink,e.fillStyle="rgba(255,255,255,.92)",e.strokeStyle=f.ink,e.lineWidth=3,te(e,n.width-284,18,260,34,!0,!0),e.fillStyle=f.green,e.font="900 12px ui-monospace, monospace",e.fillText(wn,n.width-270,40),e.font="900 19px ui-monospace, monospace",e.fillStyle=f.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 s of o)e.strokeStyle=f.white,e.lineWidth=4,e.strokeText(s,24,r),e.fillText(s,24,r),r+=20;e.restore()}var ws=[[{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 ja(e){let t=ws[e]||ws[0];return{left:{...t[0]},right:{...t[1]}}}function Ss(e,t,n){let o={type:"eggFarm",id:e.nextId++,col:t,row:n,level:1,nextSpawn:2,lastInterval:2,extraEggOutlet:0,price:St.eggFarm,builtSession:e.buildSession};return o.nextSpawn=Mt(o),o.lastInterval=o.nextSpawn,o}function xs(e,t,n,o){let r=o==="auto"?Se.autoScanner.price:Se.manualScanner.price,s=new Set(e.scanners.filter(d=>d.kind==="manual").map(d=>d.slot)),l=0;for(;s.has(l);)l+=1;return{type:"scanner",id:e.nextId++,kind:o,slot:o==="manual"?l:null,role:o==="manual"?l%2:0,col:t,row:n,level:1,queue:[],cooldown:0,price:r,builtSession:e.buildSession,autoMode:"standard",keys:o==="manual"?ja(l):null}}function zn(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))),s=Math.abs(e.x-y.x),l=Math.abs(e.x-(y.x+y.cols*y.cell)),d=Math.abs(e.y-y.y),v=Math.abs(e.y-(y.y+y.rows*y.cell)),C=[["left",s],["right",l],["top",d],["bottom",v]].sort((P,A)=>P[1]-A[1])[0][0];return C==="left"?{side:C,entry:{col:0,row:r}}:C==="right"?{side:C,entry:{col:y.cols-1,row:r}}:C==="top"?{side:C,entry:{col:o,row:0}}:{side:C,entry:{col:o,row:y.rows-1}}}function Xn(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 ks(e,t,n,o){let{entry:r,side:s}=zn(n),l=Se[t],d=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},v={type:"facility",id:t,name:d.name,x:0,y:0,w:d.w,h:d.h,level:1,price:o||d.price,builtSession:e.buildSession};return Xn(v,r,s)}function Za(e){return Math.random()({x:s.x,y:s.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 Ms({game:e,canvasPoint:t,updatePanels:n,equipmentAtPoint:o,fail:r,pointInGrid:s,rectOfFacility:l,rectsOverlap:d}){function v(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 C(x){return x?x.type==="conveyor"?{type:"conveyor",id:x.oldKey}:{type:x.type,id:x.ref.id}:null}function P(x){let g=v(C(x));return(e.multiSelected||[]).some(O=>v(O)===g)}function A(x){return x?x.type==="eggFarm"?e.eggFarms.find(g=>g.id===x.id)||null:x.type==="scanner"?e.scanners.find(g=>g.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 L(){let x=[];for(let g of e.conveyorTiles){let O=Q(g),X=F(O.col,O.row);x.push({type:"conveyor",id:g,center:X,cell:O})}for(let g of e.eggFarms)x.push({type:"eggFarm",id:g.id,ref:g,center:F(g.col,g.row),cell:{col:g.col,row:g.row}});for(let g of e.scanners)x.push({type:"scanner",id:g.id,ref:g,center:pe(g),cell:{col:g.col,row:g.row}});for(let g of Object.values(e.facilities)){let O={x:g.x+g.w/2,y:g.y+g.h/2},X=g.entry?F(g.entry.col,g.entry.row):O;x.push({type:"facility",id:g.id,ref:g,center:O,portCenter:X})}return x}function V(x,g){let O=Math.min(g.x1,g.x2),X=Math.max(g.x1,g.x2),oe=Math.min(g.y1,g.y2),de=Math.max(g.y1,g.y2);return x.x>=O&&x.x<=X&&x.y>=oe&&x.y<=de}function ne(x){let g=[];for(let O of L())(V(O.center,x)||O.portCenter&&V(O.portCenter,x))&&g.push({type:O.type,id:O.id});return e.multiSelected=g,e.selected=g[0]||null,n(),g.length}function z(){e.multiSelected=[],e.selected=null,n()}function se(x){let g=t(x);return e.selectionBox={x1:g.x,y1:g.y,x2:g.x,y2:g.y},e.multiSelected=[],e.selected=null,n(),!0}function ye(x){if(!e.selectionBox)return;let g=t(x);e.selectionBox.x2=g.x,e.selectionBox.y2=g.y}function Z(){if(!e.selectionBox)return 0;let x=e.selectionBox,g=Math.abs(x.x2-x.x1),O=Math.abs(x.y2-x.y1);return e.selectionBox=null,g<6&&O<6?(z(),0):ne(x)}function I(x){let g=C(x);return g?(e.multiSelected||[]).length&&P(x)?[...e.multiSelected]:[g]:[]}function W(x){let g=A(x);if(!g)return null;if(x.type==="conveyor"){let O=Q(x.id);return{...x,obj:g,oldKey:x.id,currentKey:x.id,meta:e.conveyorMeta.get(x.id)||{price:Ne("conveyor"),builtSession:null},col:O.col,row:O.row}}return x.type==="eggFarm"||x.type==="scanner"?{...x,obj:g,col:g.col,row:g.row}:x.type==="facility"?{...x,obj:g,x:g.x,y:g.y,w:g.w,h:g.h,entry:g.entry?{...g.entry}:null,side:g.side,center:{x:g.x+g.w/2,y:g.y+g.h/2}}:null}function N(x){let g=t(x),O=o(g);if(!O)return!1;let X=I(O),oe=X.map(W).filter(Boolean);return oe.length?(e.groupDrag={start:g,selections:X,origins:oe,historySnapshot:cn(e),committed:!1,lastDCol:0,lastDRow:0},e.multiSelected=X,e.selected=X[0]||null,n(),!0):!1}function le(){!e.groupDrag||e.groupDrag.committed||(e.undoStack.push(e.groupDrag.historySnapshot),e.redoStack=[],e.groupDrag.committed=!0)}function we(x,g,O){let X=$(x,g),oe=Tt(e,x,g);if(oe&&!O.has(`eggFarm:${oe.id}`))return!0;let de=Et(e,x,g);return!!(de&&!O.has(`scanner:${de.id}`)||e.conveyorTiles.has(X)&&!O.has(`conveyor:${X}`))}function he(x,g,O){let X=[];for(let oe of e.groupDrag.origins){if(oe.type!=="facility")continue;let de={x:oe.center.x+x,y:oe.center.y+g},{entry:ge,side:ce}=zn(de);if(!s(ge.col,ge.row)||e.blockedCells?.has?.($(ge.col,ge.row)))return!0;let ot={...oe.obj,entry:{...ge},side:ce};Xn(ot,ge,ce),X.push({id:oe.id,rect:l(ot)})}for(let oe of X)for(let de of Object.values(e.facilities))if(!O.has(`facility:${de.id}`)&&d(oe.rect,l(de),12))return!0;for(let oe=0;oeJ.type==="conveyor");for(let J of ot){let Me=J.currentKey||J.oldKey;e.conveyorTiles.delete(Me),e.conveyorMeta.delete(Me)}for(let J of ot){let Me=$(J.col+oe,J.row+de);e.conveyorTiles.add(Me),e.conveyorMeta.set(Me,J.meta||{price:Ne("conveyor"),builtSession:null,uses:0}),J.currentKey=Me}for(let J of e.groupDrag.origins)if(J.type==="eggFarm")J.obj.col=J.col+oe,J.obj.row=J.row+de;else if(J.type==="scanner")J.obj.col=J.col+oe,J.obj.row=J.row+de;else if(J.type==="facility"){let Me={x:J.center.x+O,y:J.center.y+X},{entry:Be,side:rt}=zn(Me);Xn(J.obj,Be,rt)}e.groupDrag.selections=e.groupDrag.origins.map(J=>J.type==="conveyor"?{type:"conveyor",id:J.currentKey||J.oldKey}:{type:J.type,id:J.id}),e.multiSelected=[...e.groupDrag.selections],e.selected=e.multiSelected[0]||null,be(e),n()}function G(){e.groupDrag&&(be(e),e.groupDrag=null,n())}return{selectionFromHit:C,startSelectionBox:se,updateSelectionBox:ye,finishSelectionBox:Z,startGroupDrag:N,updateGroupDrag:R,finishGroupDrag:G}}function gs({game:e,ui:t,canvas:n,canvasPoint:o,onUpdatePanels:r}){function s(){r&&r()}let l=null,d=!1,v=null,C=!1,P=["random","up","right","down","left"],A={random:"RND",up:"UP",right:"RT",down:"DN",left:"LF"},L={w:40,h:40,y:0};function V(){return gn(e)}function ne(){e.gridCols=y.cols,e.gridRows=y.rows,e.gridOwnedCells=Nr(e)}function z(i){if(i){y.y-=i*y.cell,y.rows+=i,e.gridChunkOriginY=(e.gridChunkOriginY||0)-Math.floor(i/10),e.ownedCells=Tn(e.ownedCells,i),e.blockedCells=Tn(e.blockedCells,i),e.conveyorTiles=Tn(e.conveyorTiles,i),e.conveyorMeta=_r(e.conveyorMeta,i);for(let c of e.eggFarms||[])c.row+=i;for(let c of e.scanners||[])c.row+=i;for(let c of Object.values(e.facilities||{}))c.entry&&(c.entry.row+=i)}}function se(i){e.ownedCells=e.ownedCells||new Set;for(let c of Wr(i))e.ownedCells.add($(c.col,c.row))}function ye(i){return e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending?null:kt(e).find(c=>c&&Ur(c,i))||null}function Z(i="right"){if(i&&typeof i=="object"&&Number.isFinite(i.chunkX)&&Number.isFinite(i.chunkY))return i;let c=["right","up"].includes(i)?i:"right";return Gr(e,c)}function I(i="right"){let c=Z(i);if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return{ok:!1,reason:"Cannot expand now."};if(!c)return{ok:!1,reason:"Invalid expansion lot."};let h=c.direction||"right",m=V();if(e.cashy.cols&&(y.cols=T.colStart+T.cols),T.rowStart+T.rows>y.rows&&(y.rows=T.rowStart+T.rows),se(T),Kr(e,T.chunkX,T.chunkY),e.gridExpansionPurchases=(e.gridExpansionPurchases||0)+1,e.gridExpansionPurchasesByDirection[h]=(e.gridExpansionPurchasesByDirection[h]||0)+1,ne();let j=$r({seed:`${e.runSeed}:grid-expansion:${T.chunkX},${T.chunkY}:${e.gridExpansionPurchases}`,colStart:T.colStart,colEnd:T.colStart+T.cols,rowStart:T.rowStart,rowEnd:T.rowStart+T.rows,targetRatio:q.map.blockedRatio});for(let Pe of j)e.blockedCells.add(Pe);be(e);let ie=T.cols*T.rows,fe=Ct(T);return _(e,fe.x+fe.w/2,fe.y+fe.h/2,`${h.toUpperCase()} +${ie} CELLS -${M(m)}`,f.green),s(),{ok:!0,direction:h,cost:m,addedCells:ie,blocked:j.size,chunkX:T.chunkX,chunkY:T.chunkY}}function W(i,c){return i>=0&&i=0&&c!c.has(m.id)&&we(h,le(m),12))}function R(i,c,h=null){if(!W(i,c))return!1;if(N(i,c))return!0;let m=$(i,c),k=Tt(e,i,c);if(k&&!(h?.type==="eggFarm"&&h.ref?.id===k.id))return!0;let T=Et(e,i,c);return!!(T&&!(h?.type==="scanner"&&h.ref?.id===T.id)||e.conveyorTiles.has(m)&&!(h?.type==="conveyor"&&h.oldKey===m))}function G(i,c,h=null){let m={col:i,row:c};for(let k of gt(m)){if(!W(k.col,k.row)||N(k.col,k.row))return!0;let T=$(k.col,k.row);if(Tt(e,k.col,k.row))return!0;let ie=Et(e,k.col,k.row);if(ie&&!(h?.type==="scanner"&&h.ref?.id===ie.id)||e.conveyorTiles.has(T))return!0}return!1}function x(){return e.selected?e.selected.type==="eggFarm"?e.eggFarms.find(i=>i.id===e.selected.id)||null:e.selected.type==="scanner"?e.scanners.find(i=>i.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 g(i){return i?i.type==="eggFarm"?`${xt("eggFarm")} #${i.id}`:i.type==="scanner"?`${i.kind==="auto"?xt("autoScanner"):xt("manualScanner")} #${i.id}`:i.type==="conveyor"?e.conveyorMeta.get(i.id)?.kind==="boostConveyor"?xt("boostConveyor"):xt("conveyor"):i.type==="facility"?i.name:"Equipment":"Equipment"}function O(i){return i?.type==="conveyor"?e.conveyorMeta?.get(i.oldKey||i.ref?.id)?.price||$n(i):$n(i)}function X(){return!!e.cardEffects?.usedMachineActive}function oe(){return X()?{usedMachine:!0,noRefund:!0,durabilityBaseMultiplier:.6}:{usedMachine:!1,noRefund:!1,durabilityBaseMultiplier:1}}function de(i){let c=oe();return Object.assign(i,c),i}function ge(i){let c=i?.ref||i||{};if(i?.type==="eggFarm"||c.type==="eggFarm")return e.eggFarms.length<=1?"Cannot sell the last EGG FARM.":"";if((i?.type==="facility"||c.type==="facility")&&["mixer","trash","truck"].includes(c.baseId||c.id)){let h=c.baseId||c.id;if(Object.values(e.facilities).filter(k=>(k.baseId||k.id)===h).length<=1)return`Cannot sell the last ${c.shortName||c.name||c.id}.`}return""}function ce(i){t.buildStatus.textContent=i,_(e,n.width/2-e.view.x,86-e.view.y,i.toUpperCase(),f.danger)}function ot(i){if(!i)return null;let c=$(i.col,i.row);return e.conveyorMeta.get(c)||null}function J(i){return i?(Array.isArray(i.outDirs)||(i.outDirs=[]),i.outDirs=[...new Set(i.outDirs.filter(c=>["right","left","down","up"].includes(c)))],P.includes(i.branchMode)||(i.branchMode="random"),i.kind||(i.kind="conveyor"),i.speedMultiplier||(i.speedMultiplier=i.kind==="boostConveyor"?2:1),i.outDirs):[]}function Me(i){return i?ue.filter(c=>e.conveyorTiles.has($(i.col+c.dc,i.row+c.dr))).map(c=>c.name):[]}function Be(i){return Me(i).length>=3}function rt(i,c){let h=ue.find(ie=>ie.name===c);if(!i||!h)return!1;let m=$(i.col+h.dc,i.row+h.dr),k=e.conveyorMeta.get(m);if(!k)return!1;let T=h.opposite;return[...new Set([...Array.isArray(k.outDirs)?k.outDirs:[],k.dir].filter(Boolean))].includes(T)}function Ge(i){if(!e.conveyorTiles.has(i))return[];let c=Q(i),h=e.conveyorMeta.get(i),m=J(h),k=Me(c),T=[...new Set([...m,h?.dir].filter(Boolean))].filter(fe=>k.includes(fe)),j=k,ie=T.length?T:j;return h&&(h.outDirs=m.filter(fe=>k.includes(fe)),h.dir&&!k.includes(h.dir)&&(h.dir=h.outDirs[0]||null),h.branchMode!=="random"&&!k.includes(h.branchMode)&&(h.branchMode="random")),ie}function it(i){if(!e.conveyorTiles.has(i))return[];let c=Q(i),h=Me(c);return Be(c)||h.length?h:Ge(i)}function eo(i){let c=Q(i),h=it(i);if(h.length<3)return[];let m=new Set(h.filter(k=>rt(c,k)));return h.filter(k=>{let T=new Set(m);return T.add(k),h.filter(j=>!T.has(j)).length>=2})}function pn(i,c){let h=lt(i,c);if(!h)return!1;let m=$(i.col,i.row),k=$(c.col,c.row),T=e.conveyorMeta.get(m),j=e.conveyorMeta.get(k);if(!T||!j)return!1;let ie=J(T),fe=!ie.includes(h)||T.dir!==h||!j.dir;return ie.includes(h)||ie.push(h),T.dir=h,j.dir||(j.dir=h),fe}function yn(i){let c=to(i);return c.length<2?hn(i):($e(e),no(c),be(e),s(),!0)}function hn(i){if(!i)return!1;let c=$(i.col,i.row),h=e.conveyorMeta.get(c);if(!h||Be(i))return!1;let m=ue.map(j=>j.name),k=h.dir&&m.includes(h.dir)?h.dir:null,T=m[(Math.max(-1,m.indexOf(k))+1)%m.length];return $e(e),h.dir=T,h.outDirs=[T],h.branchMode="random",be(e),s(),!0}function bt(i){return i?ue.map(c=>({col:i.col+c.dc,row:i.row+c.dr})).filter(c=>e.conveyorTiles.has($(c.col,c.row))):[]}function to(i){if(!i||!e.conveyorTiles.has($(i.col,i.row))||Be(i))return[];let c=bt(i);if(!c.length||c.length>2)return[];let h=T=>{let j=[],ie=new Set([$(i.col,i.row)]),fe=i,Pe=T,br=0;for(;Pe&&br<200;){br+=1;let vr=$(Pe.col,Pe.row);if(ie.has(vr)||(ie.add(vr),j.push(Pe),Be(Pe)))break;let wr=bt(Pe).filter(Sr=>!(Sr.col===fe.col&&Sr.row===fe.row));if(wr.length!==1)break;fe=Pe,Pe=wr[0]}return j},m=c[0]?h(c[0]).reverse():[],k=c[1]?h(c[1]):[];return[...m,i,...k]}function mn(i,c){return!!i&&[...new Set([...Array.isArray(i.outDirs)?i.outDirs:[],i.dir].filter(Boolean))].includes(c)}function no(i){let c=0,h=0;for(let k=0;kh?[...i].reverse():i;for(let k=0;k=Math.abs(m)?{col:i.col+Math.sign(h),row:i.row}:{col:i.col,row:i.row+Math.sign(m)}}function oo(i){d=!1,v=i?{col:i.col,row:i.row}:null,C=!1,l=null,Nt(i)}function jt(i){if(!i)return;if(!l)return Nt(i);let c=l,h=0;for(;(c.col!==i.col||c.row!==i.row)&&h<64;){let m=Jt(c,i);if(Nt(m),c=l||m,h+=1,!l)break}}function vn(){!C&&v&&e.conveyorTiles.has($(v.col,v.row))&&yn(v),v=null,C=!1,l=null,d=!1}function u(i){if(!i)return ce(re.fail.outOfGrid);let{col:c,row:h}=i;if(e.buildTool==="conveyor"||e.buildTool==="boostConveyor"){let m=bn(i,null);if(!m.ok)return ce(m.reason||re.fail.cellOccupied);be(e);return}if(N(c,h))return ce("Cannot build on blocked ground.");if(e.buildTool==="manualScanner"||e.buildTool==="autoScanner"?G(c,h):R(c,h))return ce(re.fail.cellOccupied);e.buildTool==="eggFarm"?b(c,h):e.buildTool==="manualScanner"?S(c,h,"manual"):e.buildTool==="autoScanner"&&S(c,h,"auto")}function p(i){let c=We(i.x,i.y);if(["conveyor","boostConveyor","eggFarm","manualScanner","autoScanner"].includes(e.buildTool))return u(c);if(nn.includes(e.buildTool))return w(i,e.buildTool)}function b(i,c){let h=Ne("eggFarm",e);if(e.cashT.kind==="manual").length>=8)return ce("Manual Scanner limit reached (8 max).");let m=h==="auto"?Ne("autoScanner",e):Ne("manualScanner",e);if(e.cashk.id!==c.ref.id),pt(e,m.x,m.y),be(e)}if(c.type==="scanner"){let m=pe(c.ref);E(c,m.x,m.y),e.scanners=e.scanners.filter(k=>k.id!==c.ref.id),pt(e,m.x,m.y),be(e)}if(c.type==="facility"){let m=c.ref;E(c,m.x+m.w/2,m.y+m.h/2),delete e.facilities[m.id],pt(e,m.x+m.w/2,m.y+m.h/2),be(e)}e.selected=null,e.multiSelected=[],s()}function K(i){let c=Object.values(e.facilities).find(j=>{if(i.x>=j.x&&i.x<=j.x+j.w&&i.y>=j.y&&i.y<=j.y+j.h)return!0;if(!j.entry)return!1;let fe=F(j.entry.col,j.entry.row);return Math.abs(i.x-fe.x)<=y.cell*.46&&Math.abs(i.y-fe.y)<=y.cell*.46});if(c)return{type:"facility",ref:c};let h=We(i.x,i.y);if(!h)return null;let m=Tt(e,h.col,h.row);if(m)return{type:"eggFarm",ref:m};let k=Et(e,h.col,h.row);if(k)return{type:"scanner",ref:k};let T=$(h.col,h.row);return e.conveyorTiles.has(T)?{type:"conveyor",oldKey:T,ref:{type:"conveyor",id:T}}:null}let ee=Ms({game:e,canvasPoint:o,updatePanels:s,equipmentAtPoint:K,fail:ce,pointInGrid:W,rectOfFacility:le,rectsOverlap:we});function Xe(i){return null}function ur(){let i=x();i&&(i.type==="conveyor"?D(F(...Object.values(Q(i.id)))):i.type==="eggFarm"?D(F(i.col,i.row)):i.type==="scanner"?D(pe(i)):i.type==="facility"&&D({x:i.x+i.w/2,y:i.y+i.h/2}))}function He(i,c,h="primary-button"){let m=document.createElement("button");return m.type="button",m.className=h,m.textContent=i,m.addEventListener("click",c),m}function Zt(){e.cardTargetPick?.mode==="autoScannerMenu"&&(e.cardTargetPick=null),t.modal.classList.remove("visible","equipment-popover"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function ro(i){t.modalTitle.textContent="Auto Scanner",e.cardTargetPick={pending:!0,mode:"autoScannerMenu",cardId:null,targetKeys:[`scanner:${i.id}`],remaining:1},t.modalBody.innerHTML=` +var q={version:"v27.15 dark factory visual patch",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,fairiesTribute:{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},incomeUpgradeRate:1.1,explosionDamageDivisor:30,maleTruckFinePerHalfDay:30,shredderBonus:{maxCards:30,incomePerUpgrade:1.25},chemicalWeaponSubsidy:{poopPerBlock:70,yenPerBlock:1200}},production:{poopRate:.08,autoScannerCooldown:3.5,autoScannerUpgradeRate:.95,autoScannerCardUpgradeRate:.95,autoScannerMinCooldown:.5,poopRateCardBonus:.04,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:"autoScannerTuning",title:"AUTO SCANNER Tuning",rarity:"common",type:"instant",description:"All AUTO SCANNER cooldowns use default cooldown x0.95 per copy.",tags:["SCANNER","PASSIVE"]},{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",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:"poopRateBooster",title:"Poop Culture",rarity:"common",type:"instant",description:"Base poop rate +4 percentage points. No card limit.",tags:["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:"sparePartsBin",title:"SPARE PARTS BIN",rarity:"common",type:"instant",description:"Restores 2% durability to every machine. A box of almost-compatible parts.",tags:["MAINTENANCE","ACTIVE"]},{id:"dudRefund",title:"DUD REFUND",rarity:"common",type:"instant",description:"DUDs now come with paperwork. Gain JPY 50 per copy when you pick a DUD.",tags:["CARD","ECONOMY","PASSIVE"]},{id:"freeReroll",title:"FREE REROLL",rarity:"common",type:"instant",description:"The first bad ideas are free.",tags:["CARD","PASSIVE"]},{id:"composter",title:"COMPOSTER",rarity:"common",type:"instant",description:"Turns shredder waste into suspicious fertilizer. Gain JPY 3 per copy when SHREDDER processes poop.",tags:["POOP","ECONOMY","PASSIVE"]},{id:"scannerQueueSpacing",title:"Scanner Queue Spacing",rarity:"common",type:"instant",description:"Manual and Auto Scanner queue spacing -15%. No card limit.",tags:["SCANNER","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 unbuildable cells",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:"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:"Fairies tribute profit exemption +JPY 250.",tags:["ECONOMY","RARE","PASSIVE"]},{id:"chemicalWeaponSubsidy",title:"Chemical Weapons Subsidy",rarity:"ultraRare",type:"instant",description:"Each day, gain JPY 1200 per 70 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,autoScannerTuning:0,poopRateBooster:0,crowdedFarming:0,hatchingFeed:0,safetyCover:0,recyclingSubsidy:0,chemicalWeaponSubsidy:0,preventiveMaintenance:0,dudFilter:0,durabilityCoating:0,sparePartsBin:0,dudRefund:0,freeReroll:0,composter:0,scannerQueueSpacing:0,laborExploitation:0,usedMachineActive:!1,rescueLoanCharges:0},commonWeight:8,rareWeight:2,ultraRareWeight:.45,baseDraftSize:3,maxDudsPerDraft:2,dudChancePerCard:.3,dudChanceReductionPerFilter:.05,extraCardsAddedPicks:2,rerollCost:{dayDivisor:2,multiplier:100}},events:{eventChance:.1,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},boostConveyor:{id:"boostConveyor",type:"conveyor",name:"Boost Conveyor",shortName:"BOOST BELT",price:75,buildable:!0,upgradeable:!1,speedMultiplier:2},eggFarm:{id:"eggFarm",type:"eggFarm",name:"Egg Farm",shortName:"EGG",price:250,buildable:!0,upgradeable:!0,maxLevel:4},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:180,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 Sn=q.version,wt=q.time.daySeconds,tn=q.cash.starting,xe=q.economy,kr=q.time.farmShutdownGraceSeconds,kn=q.production.autoScannerCooldown,xr=q.production.autoScannerUpgradeRate,co=q.production.autoScannerCardUpgradeRate||q.production.autoScannerUpgradeRate,uo=q.production.autoScannerMinCooldown,Cr=q.events.eventChance,St=q.events.firstTurn,fo=q.production.poopRate,po=q.production.poopRateCardBonus||0,xn=q.conveyor.baseSpeed,_t=q.conveyor.maxSpeed,Cn=q.conveyor.bearingSpeedMultiplier,Ae=q.cards,Mr=q.cards.definitions,yo=q.cards.defaultEffects,lt=q.production.eggSpawnRanges,y=q.grid,ke=q.facilities,ho=["conveyor","boostConveyor","eggFarm","autoScanner","manualScanner","mixer","trash","truck"],nn=["mixer","trash","truck"],gr=["mixer","truck"],kt=Object.fromEntries(Object.entries(ke).map(([e,t])=>[e,t.price])),ue=[{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"}],p={bg:"#111318",ink:"#090a0d",muted:"#8f9bab",green:"#7bd84f",greenSoft:"#273c24",mixerBlue:"#4aa3ff",truckPink:"#ffb33e",wasteGreen:"#88d35a",danger:"#e34a36",warn:"#ffb827",white:"#e6edf2",poop:"#7b4a23",male:"#ffd23d",female:"#ffdf69"},Ce={ambient:0,important:1,critical:2};function M(e){let t=Number(e)||0;return`${t<0?"-":""}\uFFE5${Math.ceil(Math.abs(t)).toLocaleString("ja-JP")}`}function I(e,t){return`${e},${t}`}function Q(e){let[t,n]=String(e).split(",").map(Number);return{col:t,row:n}}function on(e,t,n){return Math.max(t,Math.min(n,e))}function G(e,t){return e+Math.random()*(t-e)}function Ee(e,t){return e>=0&&e=0&&tMath.round(on(r,0,255)).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}`}function gn(e,t,n){let o=Tr(e),r=Tr(t);return nl(mo(o.r,r.r,n),mo(o.g,r.g,n),mo(o.b,r.b,n))}var re={appTitle:"Chick Sorter",versionTitle:`Chick Sorter ${Sn}`,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 xt(e){return ke[e]?.name||String(e||"").replace(/^[a-z]/,t=>t.toUpperCase())}function ol(e){let t=ke[e];return t?e==="conveyor"||e==="boostConveyor"?`${M(t.price)} / tile`:e==="autoScanner"?`${M(t.price)} / ${kn.toFixed(1)}s cooldown`:e==="trash"?M(t.price):M(t.price):""}function rl(e){return{conveyor:"A narrow green belt. Routes decide whether chicks live, ship, or become invoices.",boostConveyor:"Moves chicks twice as fast. Wears down like a normal belt.",eggFarm:"A tiny gatehouse producing questionable eggs on schedule.",autoScanner:"Slower than hands without upgrades.",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 Pr(e){let t=rl(e);return`${xt(e)}${ol(e)}${t?`${t}`:""}`}function Rr(e){return re.routeLabels[e]||String(e).toUpperCase()}function Ar(e){let t=2166136261;for(let n=0;n>>0}function Dr(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 Tn(){return`RUN-${Date.now().toString(36)}-${Math.floor(Math.random()*1e6).toString(36)}`.toUpperCase()}function $r({seed:e,targetRatio:t=.2,reserved:n=[]}={}){let o=Dr(Ar(e||Tn())),r=new Set(n.map(d=>typeof d=="string"?d:I(d.col,d.row))),s=[];for(let d=0;d0;d-=1){let v=Math.floor(o()*(d+1));[s[d],s[v]]=[s[v],s[d]]}let l=Math.round(y.cols*y.rows*t);return new Set(s.slice(0,Math.min(l,s.length)).map(d=>d.k))}function Ir({seed:e,colStart:t=0,colEnd:n=y.cols,rowStart:o=0,rowEnd:r=y.rows,targetRatio:s=.2,reserved:l=[]}={}){let d=Dr(Ar(e||Tn())),v=new Set(l.map(z=>typeof z=="string"?z:I(z.col,z.row))),C=[],P=Math.max(0,Math.floor(t)),R=Math.max(P,Math.floor(n)),L=Math.max(0,Math.floor(o)),V=Math.max(L,Math.floor(r));for(let z=L;z0;z-=1){let se=Math.floor(d()*(z+1));[C[z],C[se]]=[C[se],C[z]]}let te=Math.round((R-P)*(V-L)*s);return new Set(C.slice(0,Math.min(te,C.length)).map(z=>z.k))}var Gt=10,Fr=2,Br=1;function Ut(e,t){return`${e},${t}`}function il(e){let[t,n]=String(e).split(",").map(Number);return{chunkX:t,chunkY:n}}function En(e){let t=q.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 Lr(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 C=Ut(v.chunkX,v.chunkY);t.has(C)||n.has(C)||n.set(C,bo(e,v.chunkX,v.chunkY,v.direction))}}return[...n.values()].sort((o,r)=>{let s=o.direction===r.direction?0:o.direction==="right"?-1:1;return s||(o.chunkY!==r.chunkY?o.chunkY-r.chunkY:o.chunkX-r.chunkX)})}function _r(e,t="right"){let n=Ct(e);return n.find(o=>o.direction===t)||n[0]||null}function Mt(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 vo(e){let t=Mt(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 Gr(e,t){let n=vo(e);return t.x>=n.x&&t.x<=n.x+n.w&&t.y>=n.y&&t.y<=n.y+n.h}function Ur(e){let t=[];for(let n=e.rowStart;nEe(t.col,t.row))}function pl(e){return[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}].filter(t=>Ee(t.col,t.row))}function yl(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 Vr(e){let t=new Set([...e.conveyorTiles]),n=o=>{o&&Ee(o.col,o.row)&&t.add(I(o.col,o.row))};for(let o of e.scanners){for(let r of pl(o))n(r);for(let r of fl(o))n(r)}for(let o of e.eggFarms){n(o);for(let r of yl(o))n(r)}for(let o of Object.values(e.facilities))n(o.entry);return t}function qr(e){let t=al.map(([n,o])=>({col:n,row:o}));for(let{col:n,row:o}of t)Yr(e,n,o);for(let n=0;n({...n,keys:n.keys?{left:{...n.keys.left},right:{...n.keys.right}}:null,queue:[]})),e.eggFarms=ul.map(n=>{let o=gt(n);return{...n,nextSpawn:o,lastInterval:o}});let t=Vr(e);e.blockedCells=$r({seed:e.runSeed,targetRatio:q.map.blockedRatio,reserved:[...t]}),hl(e),qr(e),e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function Tt(e){return e?[{col:e.col,row:e.row-1},{col:e.col+1,row:e.row-1},{col:e.col,row:e.row},{col:e.col+1,row:e.row},{col:e.col,row:e.row+1},{col:e.col+1,row:e.row+1}]:[]}function pe(e){let t=F(e.col,e.row);return{x:t.x+y.cell/2,y:t.y}}function Et(e,t,n){return e.eggFarms.find(o=>o.col===t&&o.row===n)||null}function Pt(e,t,n){return e.scanners.find(o=>Tt(o).some(r=>r.col===t&&r.row===n))||null}function Rt(e,t){return e.scanners.find(n=>n.id===t)||null}function Co(e,t){return e.scanners.find(n=>n.kind==="manual"&&n.slot===t)||null}function Dn(e){return e?.baseId||e?.id||""}function Mo(e,t){return Object.entries(e.facilities||{}).filter(([,n])=>Dn(n)===t)}function Pe(e,t){return{inputA:{col:e.col,row:e.row-2},inputB:null,left:{col:e.col-1,row:e.row},right:{col:e.col+2,row:e.row}}[t]}function Qr(e){return e?ue.map(t=>({col:e.col+t.dc,row:e.row+t.dr})).filter(t=>Ee(t.col,t.row)):[]}function Jr(e,t,n=[],o=[]){if(!t||!Ee(t.col,t.row))return[];let r=[],s=l=>{!l||!Ee(l.col,l.row)||!e.conveyorTiles.has(I(l.col,l.row))||n.some(d=>d&&Mn(l,d))||r.some(d=>Mn(d,l))||r.push({...l,viaTolerance:!Mn(l,t)})};s(t);for(let l of o)s(l);for(let l of Qr(t))s(l);return r}function zr(e,t,n=[],o=[]){let r=Jr(e,t,n,o),s=r.filter(l=>!l.viaTolerance);return s.length?s:r}function ml(e,t){let n=Pe(t,"inputA");return!n||!Ee(n.col,n.row)?[]:e.conveyorTiles.has(I(n.col,n.row))?[{...n,viaTolerance:!1}]:[]}function bl(e,t,n){let o=Pe(t,n);return Jr(e,o,Tt(t))}function vl(e,t){let n=e.facilities[t]||Mo(e,t)[0]?.[1];if(!n)return null;if(n.entry)return F(n.entry.col,n.entry.row);let o=Dn(n)||t;return o==="mixer"?{x:n.x+n.w,y:n.y+n.h*.52}:o==="truck"?{x:n.x,y:n.y+n.h*.52}:o==="trash"?{x:n.x+n.w/2,y:n.y+8}:{x:n.x+n.w/2,y:n.y+n.h/2}}function jr(e,t,n){return n==="inputA"?ml(e,t).length>0:bl(e,t,n).length>0}function ve(e){e.branchCounters?.clear?.(),e.routeCache=null,e.routingVersion=(e.routingVersion||0)+1,e.factoryGraph=null,e.factoryGraphCommittedVersion=-1}function De(e,t){return I(e,t)}function Wt(e){return Q(e)}function wl(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=>ue.some(s=>s.name===r))}function Sl(e,t,n){let o=ue.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.(De(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function kl(e,t){let n=Wt(t),o=e.conveyorMeta?.get?.(t)||{},r=ue.filter(R=>e.conveyorTiles.has(De(n.col+R.dc,n.row+R.dr))).map(R=>R.name),s=wl(e,t).filter(R=>r.includes(R)),l=r,d=s.length?s:l;if(r.length<3)return d;let v=new Set(r.filter(R=>Sl(e,n,R)));if(o.branchMode&&o.branchMode!=="random"&&r.includes(o.branchMode)){let R=new Set(v);R.add(o.branchMode),r.filter(L=>!R.has(L)).length>=2&&v.add(o.branchMode)}let C=r.filter(R=>!v.has(R));if(C.length)return C;let P=d.filter(R=>!v.has(R));return P.length?P:d}function xl(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 Cl(e){let t=xl(e);for(let o of e.conveyorTiles)t.cells.add(o),t.adjacency.set(o,[]);for(let o of t.cells){let r=Wt(o),s=kl(e,o),l=ue.filter(d=>s.includes(d.name));for(let d of l){let v=De(r.col+d.dc,r.row+d.dr);t.cells.has(v)&&t.adjacency.get(o).push({key:v,dir:d.name})}}let n=0;for(let[o,r]of t.adjacency.entries()){n+=r.length;let s=new Set(r.map(l=>l.dir));r.length===1&&(t.metrics.deadEnds+=1),r.length===4&&s.has("left")&&s.has("right")&&s.has("up")&&s.has("down")&&(t.metrics.crosses+=1)}return t.metrics.conveyorCells=t.cells.size,t.metrics.edges=Math.floor(n/2),Ml(t),gl(e,t),t.issues=Ll(e,t,{includeRoutes:!1}),t}function Ml(e){let t=1;for(let n of e.cells){if(e.cellToComponent.has(n))continue;let o=t++,r=[n],s=[];for(e.cellToComponent.set(n,o);r.length;){let l=r.shift();s.push(l);for(let d of e.adjacency.get(l)||[])e.cellToComponent.has(d.key)||(e.cellToComponent.set(d.key,o),r.push(d.key))}e.components.set(o,{id:o,cells:s,capacity:Math.max(1,s.length),count:0,ratio:0})}e.metrics.components=e.components.size}function gl(e,t){for(let n of e.scanners){let o={};for(let r of["inputA","left","right"]){let s=Pe(n,r),l=r==="inputA"?s&&t.cells.has(De(s.col,s.row))?[{...s}]:[]:zr(e,s,Tt(n)).filter(C=>t.cells.has(De(C.col,C.row))),d=l.map(C=>De(C.col,C.row)),v=d.length>0;if(o[r]={type:r,cell:s,cells:l,keys:d,key:d[0]||null,connected:v},t.metrics.scannerPorts+=1,v&&(t.metrics.connectedScannerPorts+=1),r==="inputA")for(let C of d)t.scannerInputs.set(C,n.id)}t.scannerPorts.set(n.id,o)}for(let[n,o]of Object.entries(e.facilities)){if(!o.entry)continue;let r=zr(e,o.entry).filter(d=>t.cells.has(De(d.col,d.row))),s=r.map(d=>De(d.col,d.row)),l=s.length>0;t.facilityPorts.set(n,{id:n,cell:{...o.entry},cells:r,keys:s,key:s[0]||null,connected:l}),t.metrics.facilityPorts+=1,l&&(t.metrics.connectedFacilityPorts+=1)}for(let n of e.eggFarms){let o=Qr({col:n.col,row:n.row}).map(r=>De(r.col,r.row)).filter(r=>t.cells.has(r));t.farmOutputs.set(n.id,o),t.metrics.farmOutputs+=o.length}}function Oe(e){let t=e.routingVersion||0;return(!e.factoryGraph||e.factoryGraph.version!==t)&&(e.factoryGraph=Cl(e)),e.factoryGraph}function Zr(e){let t=Oe(e);return e.factoryGraphCommittedVersion=t.version,e.factoryGraphSnapshot=Tl(t),t}function Tl(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 El(e,t){let n=t.col-e.col,o=t.row-e.row;return ue.find(r=>r.dc===n&&r.dr===o)?.name||null}function go(e,t,n){let o=Oe(e),r=De(t.col,t.row);if(!o.cells.has(r))return[];let s=`${r}|${n.cacheKey||"dynamic"}`;if(n.cacheKey&&o.pathCache.has(s))return o.pathCache.get(s).map($=>$.map(U=>({...U})));let l=`${r}|none`,d=[{key:r,col:t.col,row:t.row,incoming:"none",depth:0}],v=new Map([[l,0]]),C=new Map,P=[],R=1/0,L=8,V=24,te=80;for(;d.length;){let $=d.shift();if($.depth>R)break;let U=`${$.key}|${$.incoming}`;if(n($)){if(P.push(U),R=$.depth,P.length>=V)break;continue}for(let N of o.adjacency.get($.key)||[]){let le=Wt(N.key),Se=El($,le),he=$.depth+1;if(he>R)continue;let A=`${N.key}|${Se}`,_=v.get(A);if(_==null)v.set(A,he),C.set(A,[U]),d.push({key:N.key,col:le.col,row:le.row,incoming:Se,depth:he});else if(_===he){let k=C.get(A)||[];k.length{if(z.length>=te)return;let[N]=$.split("|"),le=[Wt(N),...U];if($===l||N===r){z.push(le);return}for(let Se of C.get($)||[])se(Se,le)};for(let $ of P)se($,[]);let ye=[],Z=new Set;for(let $ of z){let U=$.map(N=>De(N.col,N.row)).join(">");Z.has(U)||(Z.add(U),ye.push($))}return n.cacheKey&&o.pathCache.set(s,ye.map($=>$.map(U=>({...U})))),ye}function ei(e){let t=Oe(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 ti(e,t,n){let o=Oe(e),r=null,s=1/0;for(let l of o.cells){let d=Q(l),v=F(d.col,d.row),C=Math.hypot(v.x-t,v.y-n);CF(o.col,o.row));return t&&n.push(t),n}function ct(e,t){t&&(!e.length||Er(e[e.length-1],t)>1)&&e.push(t)}function Pl(e,t,n,o=null){let r=[{x:e.x,y:e.y}];ct(r,F(t.col,t.row));for(let s of $n(n,o))ct(r,s);return r}function Rl(e,t){let n=$n(e),o=Pe(t,"inputA");return o&&ct(n,F(o.col,o.row)),ct(n,pe(t)),n}function Al(e,t,n,o){let r=[{x:e.x,y:e.y}];ct(r,F(t.col,t.row));for(let l of $n(n))ct(r,l);let s=Pe(o,"inputA");return s&&ct(r,F(s.col,s.row)),ct(r,pe(o)),r}function Dl(e,t,n=0){let o=F(t.col,t.row),r=0;for(let s of e.chicks||[]){if(s.stage==="flying"||s.stage==="queued")continue;Math.hypot(s.x-o.x,s.y-o.y){let R=C.roleBias??0,L=P.roleBias??0;if(R!==L)return R-L;let V=C.cells?.length??C.route?.length??Number.POSITIVE_INFINITY,te=P.cells?.length??P.route?.length??Number.POSITIVE_INFINITY;if(V!==te)return V-te;let z=C.key||JSON.stringify(C.route||C.cells||C),se=P.key||JSON.stringify(P.route||P.cells||P);return z.localeCompare(se)});if(!o||r.length===1)return r[0];let s=r[0].roleBias??0,l=r.filter(C=>(C.roleBias??0)===s),d=Math.min(...l.map(C=>Xr(e,C)));l=l.filter(C=>Xr(e,C)===d);let v=e.branchCounters.get(t)||0;return e.branchCounters.set(t,v+1),l[Math.floor(Math.random()*l.length)]}function ni(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 To(e){let t=ni(e);return{left:t.left.destination,right:t.right.destination}}function Eo(e,t){return ni(e).left.match===t.sex?"left":"right"}function Po(e){return Rr(e)}function Ro(e){return{mixer:"#2477ff",truck:"#ff6aa8",trash:"#22b94f","scanner-role-1":"#526456",scanner:"#526456",input:"#526456"}[e]||"#102015"}function At(e,t,n=!1){let o=Oe(e),r=(o.farmOutputs.get(t.id)||[]).map(Wt),s=[];for(let v of r){let C=R=>o.scannerInputs.has(De(R.col,R.row));C.cacheKey=`farmInput:${v.col},${v.row}:v${o.version}`;let P=go(e,v,C);for(let R of P){let L=R[R.length-1],V=o.scannerInputs.get(De(L.col,L.row)),te=Rt(e,V);te&&s.push({key:`${te.id}:${L.col},${L.row}:${R.length}`,scanner:te,cells:R})}}let l=An(e,`farm:${t.id}`,s,n);if(l)return{scannerId:l.scanner.id,route:Rl(l.cells,l.scanner)};let d=An(e,`farm:${t.id}:output`,r.map(v=>({key:I(v.col,v.row),cells:[v]})),n);return d?{scannerId:null,route:$n(d.cells)}:null}function oi(e,t,n,o,r=!1){let s=Rt(e,o);if(!s)return null;let d=Oe(e).scannerPorts.get(s.id)?.[t],v=Pe(s,t),C=d?.connected?(d.keys||[d.key]).filter(Boolean).map(Wt):[];if(!v||!C.length)return null;let P=To(s)[t];return P==="scanner-role-1"?$l(e,s,t,n,v,C,r):Il(e,s,t,n,v,C,P,r)}function $l(e,t,n,o,r,s,l){let d=Oe(e),v=e.scanners.filter(R=>R.id!==t.id&&d.scannerPorts.get(R.id)?.inputA?.connected),C=[];for(let R of s)for(let L of v){let V=d.scannerPorts.get(L.id)?.inputA?.key;if(!V)continue;let te=(d.scannerPorts.get(L.id)?.inputA?.keys||[V]).filter(Boolean),z=Z=>te.includes(De(Z.col,Z.row));z.cacheKey=`toScanner:${R.col},${R.row}:${L.id}:v${d.version}`;let se=go(e,R,z),ye=L.role===1?0:1;for(let Z of se)C.push({key:`${ye}:start${I(R.col,R.row)}:s${L.id}:${Z.length}:${I(Z[Z.length-1].col,Z[Z.length-1].row)}`,target:L,cells:Z,roleBias:ye})}let P=An(e,`scanner:${t.id}:${n}:toRole1`,C,l);return P?{destination:"scanner",nextScannerId:P.target.id,route:Al(o,r,P.cells,P.target)}:null}function Il(e,t,n,o,r,s,l,d){let v=Oe(e),C=[...v.facilityPorts.entries()].filter(([L,V])=>V?.connected&&Dn(e.facilities?.[L])===l);if(!C.length)return null;let P=[];for(let L of s)for(let[V,te]of C){let z=(te.keys||[te.key]).filter(Boolean);if(!z.length)continue;let se=Z=>z.includes(De(Z.col,Z.row));se.cacheKey=`toFacility:${L.col},${L.row}:${V}:v${v.version}`;let ye=go(e,L,se);for(let Z of ye)P.push({key:`start${I(L.col,L.row)}:${V}:${Z.length}:${I(Z[Z.length-1].col,Z[Z.length-1].row)}`,cells:Z,facilityId:V})}let R=An(e,`scanner:${t.id}:${n}:${l}`,P,d);return R?{destination:l,facilityId:R.facilityId,route:Pl(o,r,R.cells,vl(e,R.facilityId))}:null}function ri(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=oi(e,o,pe(t),t.id,!1);if(r){if(["mixer","trash","truck"].includes(r.destination))return!0;if(r.destination==="scanner"){let s=Rt(e,r.nextScannerId);if(ri(e,s,n))return!0}}}return!1}function Fl(e,t){return!!At(e,t,!1)?.scannerId}function In(e){if(e.phase!=="build")return[];let t=[];for(let n of e.eggFarms||[])Fl(e,n)||t.push({type:"eggFarm",id:n.id,ref:n,message:"This Egg will not produce chicks"});for(let n of nn)for(let[o,r]of Mo(e,n))Oe(e).facilityPorts.get(o)?.connected||t.push({type:"facility",id:o,ref:r,message:"This facility cannot receive items"});return t}function Bl(e){let t=Oe(e);for(let r of e.eggFarms||[]){let s=At(e,r,!1);if(!s?.scannerId)continue;let l=Rt(e,s.scannerId);if(ri(e,l))return[]}let n=e.eggFarms?.length||0,o=[...t.facilityPorts.entries()].filter(([r,s])=>s?.connected&&["mixer","trash","truck"].includes(Dn(e.facilities?.[r]))).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 Rn(e){return e.kind==="manual"?`S${(e.slot??0)+1}`:`Auto Scanner #${e.id}`}function Ll(e,t=Oe(e),n={}){let o=n.includeRoutes!==!1,r=[],s={mixer:"Mixer",trash:"Shredder",truck:"Truck"};for(let l of nn){let d=Mo(e,l);if(!d.length){r.push(`${s[l]||l} is missing`);continue}for(let[v]of d)t.facilityPorts.get(v)?.connected||r.push(`${s[l]||l} receiver has no conveyor`)}for(let l of e.scanners){let d=t.scannerPorts.get(l.id)||{};if(d.inputA?.connected||r.push(`${Rn(l)} input has no conveyor`),d.left?.connected||r.push(`${Rn(l)} left output has no conveyor`),d.right?.connected||r.push(`${Rn(l)} right output has no conveyor`),!!o)for(let v of["left","right"])d[v]?.connected&&!oi(e,v,pe(l),l.id)&&r.push(`${Rn(l)} ${v} route is incomplete`)}if(o)for(let l of e.eggFarms)At(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 sn(e){return Bl(e)}function ii(e){return sn(e).length===0}var si=[{key:"premiumFemaleShipment",target:"female",truckTarget:"female",title:"Premium Female Shipment",route:"Female -> Truck",note:"Today only: ship female chicks to Truck. Meet the export target for a bonus.",objective:"truckTarget"},{key:"contaminantSampleExport",target:"poop",truckTarget:"poop",title:"Contaminant Sample Export",route:"Poop value x2",note:"Today only: poop is valid Truck cargo and all poop income is doubled.",objective:"truckTarget",poopValueMultiplier:2},{key:"healthInspection",title:"Health Inspection",route:"Poop -> Shredder",note:"Today only: poop mistakes are fined double. Shred enough poop for an inspection bonus.",objective:"poopTrash",poopFineMultiplier:2},{key:"conveyorJamWarning",title:"Conveyor Jam Warning",route:"No explosions",note:"Today only: jam explosions trigger at 85% congestion. Finish with zero explosions for a bonus.",objective:"noExplosion",congestionExplosionThreshold:.85,congestionWarningThreshold:.68},{key:"powerSavingOrder",title:"Power Saving Order",route:"Slow factory subsidy",note:"Today only: conveyors -20% speed and Auto Scanners +20% cooldown. A subsidy is paid at settlement.",objective:"flatBonus",conveyorSpeedMultiplier:.8,autoScannerCooldownMultiplier:1.2},{key:"overtimeDay",title:"Overtime Day",route:"80 second day",note:"Today only: the work day is longer. No extra reward or penalty.",objective:"none",daySeconds:80},{key:"shortShift",title:"Short Shift",route:"40 second day",note:"Today only: the work day is shorter. The next Fairies tribute is reduced by 10%.",objective:"none",daySeconds:40,fairiesTributeMultiplier:.9},{key:"chickBoom",title:"Chick Boom",route:"EGG interval x0.65",note:"Today only: eggs hatch faster and poop rate rises by 5 percentage points.",objective:"none",productionMultiplier:1/.65,poopRateAdd:.05},{key:"rottenFeed",title:"Rotten Feed",route:"Poop surge",note:"Today only: poop rate rises by 20 percentage points and Shredder poop income is multiplied by 1.5.",objective:"none",poopRateAdd:.2,shredderIncomeMultiplier:1.5},{key:"maintenanceAudit",title:"Maintenance Audit",route:"Durability check",note:"Today only: machines below 50% remaining durability fail the audit. Passing with none below 50% pays a bonus.",objective:"maintenanceAudit"}];function we(e,t=0){let n=Number(e);return Number.isFinite(n)?n:t}function Ol(e,t=0,n=1){let o=Math.max(1,Number(e?.turn||1)+1),r=Math.floor(Ao(e)*(.08+Math.random()*.08)),s=Math.floor(Math.max(0,e.cash||0)*.25),l=Math.floor(Math.max(0,t)*Math.max(1,o)*.75);return Math.max(120,Math.ceil(Math.max(r,s,l)*n))}function li(e){return Math.max(0,Math.ceil(500+Math.max(1,e?.turn||1)*25))}function Ao(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 Nl(e,t=1,n=wt){return e.eggFarms.reduce((o,r)=>{let[s,l]=rn(r),d=Math.max(.1,(s+l)/2);return o+Math.max(1,n)/d*Math.max(.01,t||1)},0)}function _l(e,t){let n=we(t.productionMultiplier,1),o=we(t.daySeconds,wt),r=Nl(e,n,o),s=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),l=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),d=Math.pow(1.03,s),v=fo+po*l,C=Math.min(.95,Math.max(0,(v+we(t.poopRateAdd,0))*we(t.poopMultiplier,1)*d));return{estimate:r,poopRate:C}}function ai(e){if(e.turn+1Cr)return null;let n=si[Math.floor(Math.random()*si.length)],{estimate:o,poopRate:r}=_l(e,n),s=0;n.objective==="truckTarget"?s=Math.max(1,Math.ceil(o*.3)):n.objective==="poopTrash"&&(s=Math.max(1,Math.ceil(o*r*.8)));let l=0;return["truckTarget","poopTrash","noExplosion"].includes(n.objective)&&(l=Ol(e,o)),n.objective==="flatBonus"&&(l=li(e)),n.objective==="maintenanceAudit"&&(l=li(e)),{id:`event-${e.turn}-${Date.now()}-${Math.floor(Math.random()*9999)}`,...n,target:n.target||null,truckTarget:n.truckTarget||null,forced:!0,productionMultiplier:we(n.productionMultiplier,1),poopMultiplier:we(n.poopMultiplier,1),poopRateAdd:we(n.poopRateAdd,0),daySeconds:we(n.daySeconds,wt),targetAmount:s,estimatedOutput:Math.round(o),reward:l,createdTurn:e.turn,oneTurnOnly:!0}}function ci(e){e.eventActive=e.eventOffer?{...e.eventOffer}:null,e.eventOffer=null}function ui(e){e.eventActive=null}function di(e){return Math.max(1,we(e.eventActive?.daySeconds,wt))}function fi(e){return we(e.eventActive?.productionMultiplier,1)}function pi(e){let t=Math.max(0,Number(e?.cardEffects?.hatchingFeed)||0),n=Math.max(0,Number(e?.cardEffects?.poopRateBooster)||0),o=Math.pow(1.03,t),r=fo+po*n,s=we(e.eventActive?.poopRateAdd,0);return Math.min(.95,Math.max(0,(r+s)*we(e.eventActive?.poopMultiplier,1)*o))}function je(e){return e.eventActive?.truckTarget||e.eventActive?.target||"female"}function Do(e,t){return t==="male"?e.truckMale||0:t==="poop"?e.poopTruck||0:e.truckFemale||0}function yi(e,t){return je(e)===t}function hi(e){return je(e)!=="male"}function $o(e){return Math.max(.01,we(e.eventActive?.poopValueMultiplier,1))}function Fn(e){return Math.max(.01,$o(e)*we(e.eventActive?.shredderIncomeMultiplier,1))}function Io(e){return Math.max(.01,we(e.eventActive?.poopFineMultiplier,1))}function Fo(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionExplosionThreshold,1)))}function mi(e){return Math.max(.1,Math.min(1,we(e.eventActive?.congestionWarningThreshold,.8)))}function bi(e){return Math.max(.01,we(e?.fairiesTributeMultiplier,1))}function Gl(e){let t=0,n=(o,r)=>{let s=Math.max(1,we(r,1)),l=Math.max(0,we(o,0));1-Math.min(1,l/s)<.5&&(t+=1)};for(let o of e.conveyorMeta?.values?.()||[])n(o.uses,o.durability);for(let o of e.eggFarms||[])n(o.maintenance?.uses,o.maintenance?.durability);for(let o of e.scanners||[])o.kind==="auto"&&n(o.maintenance?.uses,o.maintenance?.durability);for(let o of Object.values(e.facilities||{})){let r=o?.baseId||o?.id;(r==="mixer"||r==="trash")&&n(o.maintenance?.uses,o.maintenance?.durability)}return t}function vi(e){let t=e.eventActive;if(!t)return null;let n=0,o=!0,r=0,s="";t.objective==="truckTarget"?(n=Do(e.stats,t.target),o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="poopTrash"?(n=e.stats.poopTrash||0,o=n>=t.targetAmount,r=o?t.reward:0):t.objective==="noExplosion"?(n=e.stats.explosions||0,o=n===0,r=o?t.reward:0,s=`${n} explosion(s)`):t.objective==="flatBonus"?(o=!0,r=t.reward):t.objective==="maintenanceAudit"?(n=Gl(e),o=n===0,o&&(r=t.reward),s=`${n} machine(s) below 50%`):o=!0,r>0?(Ne(e,r),e.stats.eventBonus=(e.stats.eventBonus||0)+r,e.totals.eventBonus+=r,e.totals.eventSuccess+=1):t.objective&&t.objective!=="none"&&(e.stats.eventBonus=e.stats.eventBonus||0,e.totals.eventFailed+=o?0:1,o&&(e.totals.eventSuccess+=1));let l={title:t.title,key:t.key,target:t.target,route:t.route,objective:t.objective,targetAmount:t.targetAmount||0,count:n,success:o,bonus:r,reward:t.reward||0,productionMultiplier:t.productionMultiplier,poopMultiplier:t.poopMultiplier,daySeconds:t.daySeconds,detail:s};return e.stats.eventResult=l,l}function Bo(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Ul(e){return!!e?.cardEffects?.usedMachineActive}function Wl(e,t){return t?1:Math.min(.8,.5+.1*Math.min(3,Bo(e,"recyclingSubsidy")))}function Kl(e){return Math.pow(.95,Bo(e,"safetyCover"))}function Bn(e){let t=e?.ref||e||{},n=e?.type||t.type;return n==="conveyor"?t.price||ke[t.kind]?.price||ke.conveyor.price:n==="eggFarm"?t.price||ke.eggFarm.price:n==="scanner"?t.price||(t.kind==="auto"?ke.autoScanner.price:ke.manualScanner.price):n==="facility"?t.price||ke[t.id]?.price||0:ke[t.id]?.price||0}function _e(e,t=null){let n=ke[e]?.price||0;return Ul(t)?Math.ceil(n*.5):n}function Hl(e,t){return e?.facilities?Object.values(e.facilities).filter(n=>(n?.baseId||n?.id)===t).reduce((n,o)=>n+Math.max(0,(o.level||1)-1),0):0}function ut(e,t){return gr.includes(t)?Math.pow(xe.incomeUpgradeRate,Hl(e,t)):1}function Ye(e){return Math.ceil(xe.income.mixer*ut(e,"mixer"))}function $e(e){return Math.ceil(xe.income.truck*ut(e,"truck"))}function ln(e){return Math.ceil(xe.poopFine*ut(e,"mixer")*Io(e))}function an(e){return Math.ceil(xe.poopFine*ut(e,"truck")*Io(e))}function Lo(e){let t=xe.maleTruckFinePerHalfDay*(e.turn/2);return Math.ceil(t*ut(e,"truck"))}function Oo(e){return e?.facilities?Object.values(e.facilities).filter(t=>(t?.baseId||t?.id)==="trash").reduce((t,n)=>t+Math.max(0,(n.level||1)-1),0):0}function Dt(e){return Math.min(xe.shredderBonus.maxCards,Oo(e))}function Kt(){return xe.shredderBonus.maxCards}function dt(e){let t=typeof e=="number"?e:Dt(e),n=Math.min(xe.shredderBonus.maxCards,Math.max(0,t));return n>0?Math.ceil(n*(xe.shredderBonus.incomePerUpgrade||1)):0}function ql(e){let t=Dt(e),n=dt(t),o=Math.ceil(n*Fn(e));return{cards:t,chance:o>0?1:0,amount:o,expected:o,baseAmount:n}}function wi(e){let t=ql(e);return t.amount>0&&(e.stats.shredderBonus=(e.stats.shredderBonus||0)+t.amount,e.totals.shredderBonus=(e.totals.shredderBonus||0)+t.amount,Ne(e,t.amount)),t}function Ln(e,t=e.turn,n=null){let o=Math.max(1,Math.floor(Number(t)||1)),r=xe.fairiesTribute||{perDay:10,profitExemption:300,legalWorkExemptionBonus:250,profitRate:.12},s=Math.ceil(o*(r.perDay||10)),l=Math.max(0,Math.floor(Number(n??e?.lastResult?.profit??e?.stats?.profit??0)||0)),d=Math.max(0,e?.cardEffects?.legalWork||0),v=Math.max(0,(r.profitExemption||0)+d*(r.legalWorkExemptionBonus||0)),C=Math.max(0,l-v),P=Math.ceil(C*Math.max(0,Number(r.profitRate)||0)),R=s+P,L=Math.max(0,e?.cardEffects?.fairiesFlatteryNext||e?.cardEffects?.flattery||0),V=L>0?Math.pow(.5,L):1,te=Math.max(.01,Number(e?.pendingFairiesTributeMultiplier)||1),z=V*te,se=Math.max(0,Math.ceil(R*z)),ye=Math.max(0,R-se);return{day:o,base:s,profit:l,legalWork:d,profitExemption:v,taxableProfit:C,profitTribute:P,gross:R,flatteryCount:L,eventMultiplier:te,perCardReduction:Math.ceil(R*.5),reduction:ye,amount:se}}function $t(e,t){let n=e?.ref||e||{},o=e?.type==="conveyor"?t?.conveyorMeta?.get(e.oldKey||n.id):n,r=o?.price||Bn(e||n),s=o?.builtSession===t?.buildSession;if(o?.noRefund||n?.noRefund)return{amount:0,sameBuild:s,price:r,rate:0,noRefund:!0};let l=Wl(t,s);return{amount:Math.max(0,Math.ceil(r*l)),sameBuild:s,price:r,rate:l,noRefund:!1}}function Yl(e,t=null){let n=Math.max(1,Math.ceil((Number(e)||0)/xe.explosionDamageDivisor));return Math.max(1,Math.ceil(n*Kl(t)))}function Vl(e,t){return Math.max(0,Math.ceil(t))}function Si(e,t){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 Ne(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Si(e,n),n}function ft(e,t){let n=Math.max(0,Math.ceil(t));return n>0&&Si(e,-n),n}function pt(e,t){ft(e,t)}function ki(e,t){t<=0||(e.cash+=t,e.stats.profit+=t,e.totals.profit+=t,e.totals.maxCash=Math.max(e.totals.maxCash,e.cash))}function xi(e){let t=Ye(e);return e.stats.mixerRevenue+=t,Ne(e,t),t}function Ci(e){let t=ln(e);return e.stats.mixerPoopFine+=t,e.totals.mixerPoopFine+=t,ft(e,t),t}function Mi(e){let t=an(e);return e.stats.truckPoopFine+=t,e.totals.truckPoopFine+=t,ft(e,t),t}function gi(e){let t=Lo(e);return e.stats.maleTruckFine+=t,e.totals.maleTruckFine+=t,ft(e,t),t}function Ti(e,t){let n=Yl(t,e);return e.stats.explosionDamage+=n,e.totals.explosionDamage+=n,ft(e,n),n}function Ei(e){let t=je(e),n=Do(e.stats,t),o=t==="poop"?Math.ceil($e(e)*$o(e)):$e(e),r=n*o,s=Vl(e,r);return e.stats.pendingTruckRevenue=s,e.stats.truckRevenue=s,t==="poop"?e.stats.poopShipmentIncome=s:e.stats.chickShipmentIncome=s,s>0&&Ne(e,s),{base:r,adjusted:s,target:t,targetCount:n,unitPrice:o}}function Pi(e,t=e.turn,n=null,o={}){let r=Ln(e,t,n);return e.cardEffects&&(e.cardEffects.fairiesFlatteryNext=0,e.cardEffects.flattery!=null&&delete e.cardEffects.flattery),e.pendingFairiesTributeMultiplier!=null&&(e.pendingFairiesTributeMultiplier=1),r.amount<=0||(o.recordStats?(e.stats.fairiesTribute=(e.stats.fairiesTribute||0)+r.amount,e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,ft(e,r.amount)):(e.totals.fairiesTribute=(e.totals.fairiesTribute||0)+r.amount,e.totals.penalty=(e.totals.penalty||0)+r.amount,e.totals.profit=(e.totals.profit||0)-r.amount,e.cash-=r.amount)),r}function Ri(e){let t=Bo(e,"chemicalWeaponSubsidy"),n=Math.max(0,e?.stats?.poopTruck||0),o=xe.chemicalWeaponSubsidy||{poopPerBlock:70,yenPerBlock:1200},r=Math.floor(n/Math.max(1,o.poopPerBlock||70)),s=t>0&&r>0?r*Math.max(0,o.yenPerBlock||1200)*t:0;return s>0&&(e.stats.chemicalWeaponSubsidy=(e.stats.chemicalWeaponSubsidy||0)+s,e.totals.chemicalWeaponSubsidy=(e.totals.chemicalWeaponSubsidy||0)+s,Ne(e,s)),{cards:t,poopTruck:n,blocks:r,amount:s}}function Ai(e){let t=Ao(e),n=Math.max(1,e.totals.turnsCompleted||e.turn||1),o=Math.max(0,e.cash+e.totals.revenue+t*.5+e.totals.eventBonus*.5),r=Math.ceil(o/n),s=Math.floor(n*35+Math.max(0,n-5)*15),l=e.totals.correct*5,d=e.totals.explosionDamage;return{score:Math.max(0,Math.floor(o+r+l-e.totals.penalty-s)),factoryValue:t,base:o,dailyEarned:r,dayPenalty:s,correctBonus:l,explosionPenalty:d,days:n}}function zl(e){return{...e,keys:e.keys?{left:{...e.keys.left},right:{...e.keys.right}}:null,queue:[],cooldown:e.cooldown||0}}function cn(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(zl),conveyorTiles:[...e.conveyorTiles],conveyorMeta:[...e.conveyorMeta.entries()],branchCounters:[...e.branchCounters.entries()],cardEffects:e.cardEffects,cardDraft:e.cardDraft,cardTargetPick:e.cardTargetPick})}function Di(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??q.grid.x,y.y=n.gridY??q.grid.y,y.cols=n.gridCols||q.grid.cols,y.rows=n.gridRows||q.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,fairiesFlatteryNext:0,scannerQueueSpacing: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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=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 Fe(e){e.phase==="build"&&(e.undoStack.push(cn(e)),e.undoStack.length>80&&e.undoStack.shift(),e.redoStack=[])}function No(e){return e.phase!=="build"||!e.undoStack.length?!1:(e.redoStack.push(cn(e)),Di(e,e.undoStack.pop()),!0)}function _o(e){return e.phase!=="build"||!e.redoStack.length?!1:(e.undoStack.push(cn(e)),Di(e,e.redoStack.pop()),!0)}function W(e,t,n,o,r=p.ink){e.floatingTexts.push({x:t,y:n,text:o,color:r,life:1,maxLife:1})}function It(e,t,n){e.shake.strength=Math.max(e.shake.strength,t),e.shake.time=Math.max(e.shake.time,n)}function $i(e,t,n){e.effects.push({type:"spawn",priority:Ce.ambient,x:t,y:n,life:.42,maxLife:.42,size:12})}function Ii(e,t,n,o=p.green){e.effects.push({type:"scannerPulse",priority:Ce.important,x:t,y:n,color:o,life:.42,maxLife:.42,size:24})}function Fi(e,t,n){for(let o=0;o<12;o+=1)e.effects.push({type:"meat",priority:Ce.important,x:t+G(-18,18),y:n+G(-12,16),vx:G(-60,60),vy:G(-90,-25),life:G(.45,.85),maxLife:.85,size:G(4,8)})}function Bi(e,t,n){for(let o=0;o<16;o+=1)e.effects.push({type:"sludge",priority:Ce.important,x:t+G(-18,18),y:n+G(-12,16),vx:G(-46,46),vy:G(-70,-20),life:G(.45,.9),maxLife:.9,size:G(4,8)})}function Li(e,t,n,o){let r=o==="poop"?p.poop:o==="male"?p.male:p.female;for(let s=0;s<22;s+=1)e.effects.push({type:"shred",priority:Ce.important,x:t+G(-16,16),y:n+G(-8,8),vx:G(-70,70),vy:G(40,160),color:s%3===0?p.white:r,life:G(.45,.95),maxLife:.95,w:G(3,7),h:G(10,24),rot:G(-Math.PI,Math.PI)});Ve(e,t,n,p.green,34,Ce.important)}function Oi(e,t,n,o){let r=o==="poop"?p.poop:o==="male"?p.danger:p.green;for(let s=0;s<8;s+=1)e.effects.push({type:"load",priority:Ce.important,x:t+G(-18,18),y:n+G(-18,18),vx:G(-42,42),vy:G(-90,-25),color:r,life:G(.35,.65),maxLife:.65,size:8})}function Ve(e,t,n,o=p.danger,r=52,s=Ce.critical){e.effects.push({type:"shockwave",priority:s,x:t,y:n,color:o,life:.55,maxLife:.55,size:8,maxSize:r})}function Ze(e,t,n,o=12,r=p.danger,s=Ce.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||Xl(e,r,o);let s=r.x+e.view.x,l=r.y+e.view.y;(s<-100||l<-100||s>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 Xl(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=Ti(e,o.price);W(e,t.x,t.y-10,`-${M(r)}`,p.danger),Ve(e,t.x,t.y,p.danger,30),Ze(e,t.x,t.y,5,p.danger),It(e,5,.18)}}var Be=q.maintenance;function Uo(e,t){return Math.max(0,Number(e?.cardEffects?.[t])||0)}function Gn(e){let t=Math.min(1.4,1+.04*Math.min(10,Uo(e,"crowdedFarming"))),n=Math.pow(.95,Uo(e,"preventiveMaintenance"));return t*n}function Ql(e){return Math.pow(1.03,Uo(e,"durabilityCoating"))}function Un(e,t,n=1){let o=Be.durability[t]||1e3;return Math.max(1,Math.ceil(o*Math.max(.1,n||1)*Ql(e)))}function Ho(e){let t=Be.repairman.dailyCost;return e?.cardEffects?.laborExploitation?Math.ceil(t*.7):t}function Gi(e){return Math.max(.1,Number(e?.durabilityBaseMultiplier)||1)}function me(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"),n.kind||(n.kind="conveyor"),n.speedMultiplier||(n.speedMultiplier=n.kind==="boostConveyor"?2:1),n.branchMode||(n.branchMode="random");let o=Un(e,"conveyor",Gi(n));(n.durability==null||n.durability0&&(n.processingCooldown=Math.max(0,n.processingCooldown-t))}function Yn(e){me(e);let t=[];for(let[n,o]of e.conveyorMeta||[])t.push({type:"conveyor",key:n,meta:o,label:`${o.kind==="boostConveyor"?"Boost Belt":"Belt"} ${n}`,center:F(Q(n).col,Q(n).row)});for(let n of e.eggFarms||[])t.push({type:"eggFarm",ref:n,label:`EGG #${n.id}`,center:F(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:F(n.col,n.row)});for(let n of Object.values(e.facilities||{})){let o=qn(n);["mixer","trash"].includes(o)&&t.push({type:o,ref:n,label:`${n.shortName||n.name||o} #${n.id}`,center:{x:n.x+n.w/2,y:n.y+n.h/2}})}return t}function Nn(e){return e.meta?Ht(e):Ht(e.ref)}function un(e){return e.meta?Wo(e):Wo(e.ref)}function _n(e){return e.meta?Ko(e):Ko(e.ref)}function qi(e,t){Jl(e.meta?e:e.ref,Math.max(0,un(e)-t))}function Yi(e){return e.type==="conveyor"?`conveyor:${e.key}`:`${e.type}:${e.ref?.id||e.ref?.type||e.type}`}function Vi(e,t=.02){me(e);let n=Math.max(0,Number(t)||0),o=0;for(let r of Yn(e)){let s=un(r);qi(r,_n(r)*n),o+=Math.max(0,s-un(r))/_n(r)*100}return o}function zi(e){if(me(e),e.repairman.hiredForNextDay)return{ok:!1,reason:"Repairman already hired."};let t=Ho(e);return e.cashYi(o)===t.key)||null}function ea(e){let t=null;for(let n of Yn(e)){let o=Nn(n);o<=.001||(!t||o>Nn(t))&&(t=n)}return t}function Ji(e,t){me(e);let n=e.repairman;if(!n.active||e.phase!=="running")return;let o=Zl(e,n.target)||ea(e);if(!o){n.target=null;return}n.target={key:Yi(o),label:o.label};let r=Be.repairman.walkSpeed,s=o.center.x-n.x,l=o.center.y-n.y,d=Math.hypot(s,l);if(d>8){let L=Math.min(d,r*t);n.x+=s/d*L,n.y+=l/d*L;return}let v=t/(Be.repairman.secondsPerOnePercent*100),C=un(o),P=v*_n(o);qi(o,P);let R=Math.max(0,(C-un(o))/_n(o)*100);n.repairedToday=(n.repairedToday||0)+R,R>0&&Math.random()<.02&&W(e,n.x,n.y-28,"REPAIR",p.green),Nn(o)<=.001&&(n.target=null)}function ta(e){let t=0,n="none";for(let o of Yn(e)){let r=Nn(o);r>t&&(t=r,n=o.label)}return{ratio:t,percent:Math.round(t*100),label:n}}function jo(e){let t=ta(e),n=Yo(e);return{worst:t,avgBeltPerformance:n,repairman:e.repairman||null}}var na=Ae.commonWeight,oa=Ae.rareWeight,ra=Ae.ultraRareWeight||.45,Ft=Ae.baseDraftSize,Yt=Mr;function qt(e,t){let n=Ie(e);return Math.max(0,Number(n[t])||0)}function Ie(e){e.cardEffects||(e.cardEffects={...yo});for(let[t,n]of Object.entries(yo))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),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.cardDraft.freeRerolls==null&&(e.cardDraft.freeRerolls=0),e.cardEffects}function is(e){let t=Math.max(.5,1-.05*Math.min(10,qt(e,"crowdedFarming"))),n=Math.pow(.96,qt(e,"hatchingFeed"));return t*n}function ss(e,t=null){return Math.min(3,Math.max(0,Number(t?.extraEggOutlet)||0))}function ls(e){return Math.pow(.85,qt(e,"scannerQueueSpacing"))}function zn(e,t=null){let n=Ie(e),o=xn*Math.pow(Cn,Math.max(0,n.bearing||0)),r=t?Math.max(.1,Number(e?.conveyorMeta?.get?.(t)?.speedMultiplier)||1):1,s=t?1:Yo(e),l=Math.max(.01,Number(e?.eventActive?.conveyorSpeedMultiplier)||1);return Math.min(_t,o*s)*r*l}function tt(e,t=null){let n=Math.max(0,(e?.level||1)-1),o=t?qt(t,"autoScannerTuning"):0,r=kn*Math.pow(xr,n)*Math.pow(co,o),s=Math.max(uo,r),l=t?Math.max(.01,Number(t?.eventActive?.autoScannerCooldownMultiplier)||1):1;return t?Math.max(uo,s*Kn(e)*l):s}function ji(e){let t=e.cardDraft||{rerolls:0},n=Math.max(1,(t.rerolls||0)+1);return Math.ceil(Math.max(1,e.turn||1)/Ae.rerollCost.dayDivisor*n*Ae.rerollCost.multiplier)}function Vt(e){return Yt.find(t=>t.id===e)||null}function as(e,t){let n=typeof t=="string"?Vt(t):t;return Ie(e),!n||!(n.type==="equipmentUpgrade"||n.type==="cellAction")?[]:Ue(e,n).map(o=>({key:et(o),label:tr(e,o),type:o.type}))}function er(e,t,n={}){let o=typeof t=="string"?Vt(t):t;if(Ie(e),!o||o.type==="dud")return{ok:!1,reason:"Card not found."};if(o.id==="extraCards")return e.cardDraft=e.cardDraft||{pending:!1,choices:[],rerolls:0,picksRemaining:0},e.cardDraft.choices.push(...Vn(e,2)),{ok:!0,reason:`${o.title} added 2 draft cards.`};if(o.type==="instant")return us(e,o),{ok:!0,reason:`${o.title} granted.`};if(o.type==="equipmentUpgrade"){let r=Ue(e,o);if(!r.length)return{ok:!1,reason:`No valid target for ${o.title}.`};let s=n.targetKey&&n.targetKey!=="__auto__"?String(n.targetKey):"",l=s?r.find(d=>et(d)===s):r[0];return l?(cs(e,l),{ok:!0,reason:`${o.title} applied to ${tr(e,l)}.`}):{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`}}if(o.type==="cellAction"&&o.target==="blockedCell"){let r=Ue(e,o);if(!r.length)return{ok:!1,reason:"No blocked cells to remove."};let s=new Set((Array.isArray(n.targetKeys)?n.targetKeys:[n.targetKey]).filter(d=>d&&d!=="__auto__").map(String)),l=s.size?r.filter(d=>s.has(et(d))):r.slice(0,3);if(!l.length)return{ok:!1,reason:`Selected target is no longer valid for ${o.title}.`};for(let d of l.slice(0,3)){e.blockedCells.delete(I(d.col,d.row));let v=F(d.col,d.row);yt(e,v.x,v.y),Ve(e,v.x,v.y,p.danger,42),Ze(e,v.x,v.y,8,p.warn)}return ve(e),{ok:!0,reason:`${o.title} removed ${Math.min(3,l.length)} blocked cell(s).`}}return{ok:!1,reason:`${o.title} cannot be debug-granted.`}}function tr(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 ${tt(t,e).toFixed(1)}s -> ${tt({...t,level:t.level+1},e).toFixed(1)}s`;if(t.type==="facility"&&(t.baseId||t.id)==="mixer"){let n=t.level,o=Ye(e);t.level=n+1;let r=Ye(e);return t.level=n,`MIXER L${t.level} -> L${t.level+1} | ${M(o)} -> ${M(r)}`}if(t.type==="facility"&&(t.baseId||t.id)==="truck"){let n=t.level,o=$e(e);t.level=n+1;let r=$e(e);return t.level=n,`TRUCK L${t.level} -> L${t.level+1} | ${M(o)} -> ${M(r)}`}if(t.type==="facility"&&t.id==="trash"){let n=Dt(e),o=Math.min(Kt(),n+1),r=dt(n),s=dt(o);return`SHREDDER L${t.level||1} -> L${(t.level||1)+1} | poop income ${M(r)} -> ${M(s)} per item`}return`${t.name||t.id} L${t.level||1} -> L${(t.level||1)+1}`}function ia(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"?Vt(t):t;return Ie(e),n?n.target==="blockedCell"?ia(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"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="mixer"):n.target==="truck"?Object.values(e.facilities||{}).filter(o=>(o.baseId||o.id)==="truck"):n.target==="trash"?Oo(e)(o.baseId||o.id)==="trash"):[]:[]:[]}function sa(e,t){let n=Ie(e);if(t.id==="crowdedFarming")return(n.crowdedFarming||0)>=10;if(t.id==="recyclingSubsidy")return(n.recyclingSubsidy||0)>=3;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,Ae.dudChancePerCard||0)),r=Math.max(1e-4,Math.min(1,Ae.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 la(e){let t=e.repairman||{};return!!(t.active||t.hiredForNextDay||e.pendingRepairWorkerWages>0)}function aa(e){return Yt.filter(t=>!(t.id==="laborExploitation"&&!la(e)||sa(e,t)||(t.type==="equipmentUpgrade"||t.type==="cellAction")&&Ue(e,t).length<=0))}function Zi(e,t){return t.rarity==="ultraRare"?ra:t.rarity==="rare"?oa:na}function ca(e,t){let n=t.reduce((r,s)=>r+Zi(e,s),0);if(n<=0)return t[Math.floor(Math.random()*t.length)];let o=Math.random()*n;for(let r of t)if(o-=Zi(e,r),o<=0)return r;return t[t.length-1]}var es=0;function ua(){return es+=1,{id:`dud:${Date.now()}:${es}`,title:"Dud",rarity:"dud",type:"dud",description:"Click to flick this dud away. It does not consume a pick."}}function da(e){let t=Ie(e),n=Math.max(0,Math.min(1,Ae.dudChancePerCard||0)),o=Math.max(0,Math.min(1,Ae.dudChanceReductionPerFilter||0));return Math.max(0,n-o*Math.max(0,t.dudFilter||0))}function fa(e,t){let n=[...t],o=0,r=Math.max(0,Ae.maxDudsPerDraft||0),s=da(e);for(let l=0;ld.id===s.id);l>=0&&r.splice(l,1)}return fa(e,o)}function et(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 ts(e){if(!e)return null;if(e.type==="blockedCell"){let t=F(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=F(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=pe(e);return{x:t.x-54,y:t.y-77,w:108,h:154,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 nr(e){if(!e.cardTargetPick?.pending)return[];if(e.cardTargetPick.mode==="autoScannerMenu"){let n=new Set(e.cardTargetPick.targetKeys||[]);return e.scanners.filter(o=>o.kind==="auto"&&n.has(et(o))).map(o=>({key:et(o),label:"AUTO ROUTE SETTINGS",target:o,bounds:ts(o)})).filter(o=>o.bounds)}let t=new Set(e.cardTargetPick.targetKeys||[]);return Ue(e,e.cardTargetPick.cardId).filter(n=>t.has(et(n))).map(n=>({key:et(n),label:tr(e,n),target:n,bounds:ts(n)})).filter(n=>n.bounds)}function pa(e,t){let n=nr(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 cs(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=F(n.col,n.row);W(e,o.x,o.y-30,`OUTLET ${1+n.extraEggOutlet}`,p.green),ve(e);return}if(t.level=(t.level||1)+1,t.type==="eggFarm"){t.nextSpawn=gt(t),t.lastInterval=t.nextSpawn;let n=F(t.col,t.row);W(e,n.x,n.y-30,`LV ${t.level}`,p.green);return}if(t.type==="scanner"){let n=pe(t);W(e,n.x,n.y-34,`LV ${t.level}`,p.green);return}t.type==="facility"&&W(e,t.x+t.w/2,t.y+18,`LV ${t.level}`,p.green)}function us(e,t){let n=Ie(e),o=r=>{n[r]=Math.max(0,n[r]||0)+1};if(t.id==="bearing"&&o("bearing"),t.id==="autoScannerTuning"&&o("autoScannerTuning"),t.id==="legalWork"&&o("legalWork"),t.id==="crowdedFarming"&&(n.crowdedFarming=Math.min(10,(n.crowdedFarming||0)+1)),t.id==="hatchingFeed"&&o("hatchingFeed"),t.id==="poopRateBooster"&&o("poopRateBooster"),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"),me(e)),t.id==="sparePartsBin"){o("sparePartsBin");let r=Vi(e,.02);e.stats.sparePartsRepair=(e.stats.sparePartsRepair||0)+r,e.totals.sparePartsRepair=(e.totals.sparePartsRepair||0)+r,W(e,y.x+y.cols*y.cell/2,y.y-30,"REPAIR +2%",p.green)}t.id==="dudRefund"&&o("dudRefund"),t.id==="freeReroll"&&o("freeReroll"),t.id==="composter"&&o("composter"),t.id==="scannerQueueSpacing"&&o("scannerQueueSpacing"),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"),W(e,y.x+y.cols*y.cell/2,y.y-30,"RESCUE HELD",p.green))}function Ke(e){return`${Math.round(Number(e||0)*100)}%`}function ns(e){let t=lt[Math.max(0,Math.min(lt.length-1,e-1))]||lt[0]||[0,0];return`${t[0].toFixed(2)}-${t[1].toFixed(2)}s`}function os(e,t){return Math.ceil(e*Math.pow(xe.incomeUpgradeRate,Math.max(0,t-1)))}function rs(e,t,n){let r=Ue(e,t==="mixer"?"upgradeMixer":"upgradeTruck")[0];if(!r)return{before:os(n,1),after:os(n,2)};let s=t==="mixer"?Ye(e):$e(e),l=r.level||1;r.level=l+1;let d=t==="mixer"?Ye(e):$e(e);return r.level=l,{before:s,after:d}}function ya(e,t){let n=Ie(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 ${ns(r)} -> ${ns(r+1)}.`}if(t.id==="upgradeAutoScanner"){let o=Ue(e,t)[0]||{level:1},r=tt(o,e),s=tt({...o,level:(o.level||1)+1},e);return`Choose one AUTO SCANNER. Level +1. Cooldown ${r.toFixed(2)}s -> ${s.toFixed(2)}s.`}if(t.id==="upgradeMixer"){let o=rs(e,"mixer",xe.income.mixer);return`Choose one MIXER. Earning +10%. Male-chick income ${M(o.before)} -> ${M(o.after)}.`}if(t.id==="upgradeTruck"){let o=rs(e,"truck",xe.income.truck);return`Choose one TRUCK. Earning +10%. Correct shipment income ${M(o.before)} -> ${M(o.after)}.`}if(t.id==="upgradeTrash"){let o=Dt(e),r=Math.min(Kt(),o+1),s=dt(o),l=dt(r);return`SHREDDER level +1. Poop income ${M(s)} -> ${M(l)} per item.`}if(t.id==="bearing"){let o=Math.min(_t,xn*Math.pow(Cn,Math.max(0,n.bearing||0))),r=Math.min(_t,xn*Math.pow(Cn,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`Fairies tribute profit exemption +${M(250)}. After pick: exemption bonus ${M(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 ${Ke(Math.max(.5,1-.05*o))}, deterioration ${Ke(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 ${Ke(Math.pow(.96,(n.hatchingFeed||0)+1))}, poop rate multiplier ${Ke(Math.pow(1.03,(n.hatchingFeed||0)+1))}.`;if(t.id==="poopRateBooster")return`Held ${n.poopRateBooster||0}. After pick: base poop rate +${Math.round((n.poopRateBooster||0)+1)*4} percentage points.`;if(t.id==="autoScannerTuning")return`Held ${n.autoScannerTuning||0}. After pick: all AUTO SCANNER default cooldown ${Ke(Math.pow(co,(n.autoScannerTuning||0)+1))}.`;if(t.id==="safetyCover")return`Held ${n.safetyCover||0}. After pick: explosion damage ${Ke(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: ${M(1200*((n.chemicalWeaponSubsidy||0)+1))} per 70 truck-shipped poop each day.`;if(t.id==="preventiveMaintenance")return`Held ${n.preventiveMaintenance||0}. After pick: deterioration speed ${Ke(Math.pow(.95,(n.preventiveMaintenance||0)+1))}.`;if(t.id==="dudFilter"){let o=Math.max(0,Math.min(1,Ae.dudChancePerCard||0)),r=Math.max(0,Math.min(1,Ae.dudChanceReductionPerFilter||.05)),s=Math.max(0,n.dudFilter||0),l=Math.max(0,o-r*s),d=Math.max(0,o-r*(s+1));return`Held ${s}. DUD chance per card ${Ke(l)} -> ${Ke(d)}.`}return t.id==="durabilityCoating"?`Held ${n.durabilityCoating||0}. After pick: maximum durability ${Ke(Math.pow(1.03,(n.durabilityCoating||0)+1))}.`:t.id==="sparePartsBin"?`Held ${n.sparePartsBin||0}. Immediately restores 2% durability to every maintained machine. Common card weight.`:t.id==="dudRefund"?`Held ${n.dudRefund||0}. After pick: DUD clicks award ${M(50*((n.dudRefund||0)+1))}.`:t.id==="freeReroll"?`Held ${n.freeReroll||0}. After pick: each card screen starts with ${(n.freeReroll||0)+1} free reroll${(n.freeReroll||0)+1===1?"":"s"}.`:t.id==="composter"?`Held ${n.composter||0}. After pick: SHREDDER poop grants ${M(3*((n.composter||0)+1))}.`:t.id==="scannerQueueSpacing"?`Held ${n.scannerQueueSpacing||0}. After pick: Manual/Auto Scanner queue spacing ${Ke(Math.pow(.85,(n.scannerQueueSpacing||0)+1))}.`:t.id==="flattery"?`Next Fairies tribute -50%. Held for next tribute: ${n.fairiesFlatteryNext||0}.`:t.id==="usedMachine"?"Enable Used Machines: future equipment costs 50%, has no SELL refund, and starts with 60% durability.":t.id==="newMachine"?"Cancel Used Machines. Future equipment returns to normal price, refund, and durability.":t.id==="laborExploitation"?"Repairman labor cost -30% permanently. One time only.":t.id==="rescueLoan"?`At day-end bankruptcy check, gain ${M(500)} if cash is below ${M(0)}. Held: ${n.rescueLoanCharges||0}.`:t.description}function Zo(e,t){let n=e.cardDraft?.choices||[],o=n.findIndex(r=>r.id===t.id);o>=0&&n.splice(o,1)}function ds({game:e,ui:t,onUpdatePanels:n}){function o(){n&&n()}function r(){Ie(e),e.cardTargetPick=null,e.cardDraft={pending:!0,choices:Vn(e,Ft),rerolls:0,freeRerolls:qt(e,"freeReroll"),picksRemaining:1}}function s(){Ie(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($=Ft){Ie(e),e.cardDraft.choices=Vn(e,$)}function d(){Ie(e),!e.cardDraft.choices.length&&e.cardDraft.picksRemaining>0&&l(Ft)}function v($){Zo(e,$),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1),e.cardTargetPick=null,d(),e.cardDraft.picksRemaining<=0?s():Z()}function C($){Zo(e,$),e.cardDraft.picksRemaining=Math.max(0,(e.cardDraft.picksRemaining||1)-1)+Ae.extraCardsAddedPicks,e.cardDraft.choices.push(...Vn(e,2)),Z()}function P($,U){let N=qt(e,"dudRefund")*50;if(N>0){let le=Ne(e,N);e.stats.dudRefundIncome=(e.stats.dudRefundIncome||0)+le,e.totals.dudRefundIncome=(e.totals.dudRefundIncome||0)+le,W(e,y.x+y.cols*y.cell/2,y.y-30,`DUD REFUND +${M(le)}`,p.green)}It(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)"}),U&&(U.style.setProperty("--fling-x",`${260+Math.random()*260}px`),U.style.setProperty("--fling-y",`${-260-Math.random()*170}px`),U.style.setProperty("--fling-r",`${(Math.random()<.5?-1:1)*(52+Math.random()*38)}deg`),U.classList.add("flung")),window.setTimeout(()=>{Zo(e,$),d(),Z()},340)}function R($,U=null){if($.type==="dud")return P($,U);if($.id==="extraCards")return C($);if($.type==="equipmentUpgrade"||$.type==="cellAction")return L($);us(e,$),v($)}function L($){let U=Ue(e,$);U.length&&(e.cardTargetPick={pending:!0,cardId:$.id,mode:$.target==="blockedCell"?"blockedCell":"equipment",targetKeys:U.map(et),remaining:$.id==="dynamite"?Math.min(3,U.length):1},t.modal.classList.remove("visible","equipment-popover"),o())}function V($){if(!$||$.type!=="blockedCell")return!1;let U=I($.col,$.row);if(!e.blockedCells?.has(U))return!1;e.blockedCells.delete(U);let N=F($.col,$.row);return yt(e,N.x,N.y),Ve(e,N.x,N.y,p.danger,62),Ze(e,N.x,N.y,18,p.warn),On(e,N.x,N.y,8),It(e,16,.35),W(e,N.x,N.y-18,"BOOM",p.danger),ve(e),e.cardTargetPick.remaining=Math.max(0,(e.cardTargetPick.remaining||1)-1),e.cardTargetPick.targetKeys=Ue(e,"dynamite").map(et),o(),!0}function te($){if(!e.cardTargetPick?.pending)return!1;let U=Vt(e.cardTargetPick.cardId),N=pa(e,$);return!U||!N?(z(),!0):U.id==="dynamite"?(V(N)&&((e.cardTargetPick.remaining||0)<=0||!Ue(e,"dynamite").length)&&v(U),!0):(cs(e,N),v(U),!0)}function z(){e.cardTargetPick?.pending&&(e.cardTargetPick=null,Z())}function se(){let $=Math.max(0,e.cardDraft?.freeRerolls||0);if($>0){e.cardDraft.freeRerolls=$-1,e.cardDraft.rerolls+=1,l(Ft),Z();return}let U=ji(e);e.cashA!==Se)].slice(0,5);return N.innerHTML=`${$.title}
${he.map(A=>`${A}`).join("")}
${ya(e,$)}`,N.addEventListener("click",()=>R($,N)),N.dataset.index=String(U),N}function Z(){Ie(e),e.cardTargetPick=null,e.cardDraft?.pending||r(),e.cardDraft.choices?.length||l(Ft);let $=e.cardDraft.choices||[],U=ji(e),N=Math.max(0,e.cardDraft?.freeRerolls||0),le=Math.max(1,e.cardDraft.picksRemaining||1);t.modalTitle.textContent="Choose Upgrade Card",t.modalBody.innerHTML=`

Choose ${le} card${le===1?"":"s"} before Build phase. Dud cards can be flicked away without consuming a pick. Equipment cards target machines; Dynamite targets blocked cells.

`;let Se=t.modalBody.querySelector("#cardChoices");$.forEach((_,k)=>Se.appendChild(ye(_,k))),t.modalActions.innerHTML="";let he=document.createElement("button");he.type="button",he.className="facility-action warn reroll-button",he.textContent=N>0?`Reroll (FREE x${N})`:`Reroll ${M(U)}`,he.disabled=N<=0&&e.cash0?`${N} free reroll${N===1?"":"s"} remaining.`:he.disabled?"Not enough cash":"",he.addEventListener("click",se),t.modalActions.appendChild(he);let A=document.createElement("button");A.type="button",A.className="facility-action",A.textContent="No Card",A.title="Skip this upgrade pick and enter Build phase.",A.addEventListener("click",s),t.modalActions.appendChild(A),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible")}return{prepareDraft:r,showDraft:Z,finishDraft:s,chooseTargetAtPoint:te,cancelTargetPick:z}}var ha=!0,ma={chickMale:"./assets/images/chick_male.png",chickFemale:"./assets/images/chick_female.png",poop:"./assets/images/poop.png",conveyorStraightH:"./assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png",conveyorStraightV:"./assets/dark_factory/facilities/conveyor/conveyor_straight_v_16.png",conveyorTurnNe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_ne_16.png",conveyorTurnNw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png",conveyorTurnSe:"./assets/dark_factory/facilities/conveyor/conveyor_turn_se_16.png",conveyorTurnSw:"./assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png",boostConveyorStraightH:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_h_16.png",boostConveyorStraightV:"./assets/dark_factory/facilities/conveyor/boost_conveyor_straight_v_16.png",boostConveyorTurnNe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_ne_16.png",boostConveyorTurnNw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png",boostConveyorTurnSe:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_se_16.png",boostConveyorTurnSw:"./assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png",scannerManual:"./assets/dark_factory/facilities/machines/manual_scanner_32x48.png",scannerAuto:"./assets/dark_factory/facilities/machines/auto_scanner_32x48.png",eggFarm:"./assets/dark_factory/facilities/machines/egg_farm_16.png",mixer:"./assets/dark_factory/facilities/machines/mixer_32.png",shredder:"./assets/dark_factory/facilities/machines/shredder_32.png",truck:"./assets/dark_factory/facilities/vehicles/truck_32.png",repairman:"./assets/dark_factory/facilities/utility/repairman_16.png",obstacleCrate:"./assets/dark_factory/facilities/utility/obstacle_crate_16.png"},be={};for(let[e,t]of Object.entries(ma)){let n=new Image;n.loaded=!1,n.onerror=()=>{n.loaded=!1},(ha&&e!=="chickMale"&&e!=="chickFemale"||e==="poop")&&t&&(n.onload=()=>{n.loaded=!0},n.src=t),be[e]=n}function hs(e,t,n,o){e.imageSmoothingEnabled=!1,e.clearRect(0,0,t.width,t.height),wa(e,t),e.save();let r=n.shake.time>0?G(-n.shake.strength,n.shake.strength):0,s=n.shake.time>0?G(-n.shake.strength,n.shake.strength):0,l=n.view?.scale||1;e.translate((n.view?.x||0)+r,(n.view?.y||0)+s),e.scale(l,l),ka(e,n),xa(e,n),Ma(e,n),$a(e,n),_a(e,n),Ia(e,n),Ba(e,n),va(e,n),Ka(e,n,o.activeQueuedChick),ja(e,n),za(e,t,n),Va(e,n,o.selectedObject,o.selectedTitle),Xa(e,n),Qa(e,n),Ja(e,n),e.restore(),Za(e,n,t)}function ba(e){if(e.type==="eggFarm"){let n=F(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 va(e,t){if(t.phase!=="build")return;let n=In(t);for(let o of n){let r=ba(o);e.save(),e.fillStyle="rgba(196,36,36,.22)",e.strokeStyle=p.danger,e.lineWidth=5,e.setLineDash([10,6]),ne(e,r.x,r.y,r.w,r.h,!0,!0),e.setLineDash([]),e.fillStyle=p.danger,e.strokeStyle=p.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 ne(e,t,n,o,r,s=!0,l=!0){e.beginPath(),e.rect(t,n,o,r),s&&e.fill(),l&&e.stroke()}function fn(e,t,n,o,r=p.ink){e.save(),e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.lineWidth=4,e.strokeStyle=p.white,e.fillStyle=r,e.strokeText(o,t,n),e.fillText(o,t,n),e.restore()}function Xe(e,t,n,o,r,s){if(!t?.loaded)return!1;let l=e.imageSmoothingEnabled;return e.imageSmoothingEnabled=!1,e.drawImage(t,Math.round(n),Math.round(o),Math.round(r),Math.round(s)),e.imageSmoothingEnabled=l,!0}function fs(e,t,n,o,r,s,l=null,d=1){e.fillStyle=s,e.fillRect(Math.round(t),Math.round(n),Math.round(o),Math.round(r)),l&&(e.strokeStyle=l,e.lineWidth=d,e.strokeRect(Math.round(t)+.5,Math.round(n)+.5,Math.round(o)-1,Math.round(r)-1))}function wa(e,t){e.fillStyle=p.bg,e.fillRect(0,0,t.width,t.height),e.save(),e.globalAlpha=.85;for(let n=0;n=n;for(let r of Ct(t)){let s=Mt(r);e.save(),e.fillStyle=o?"rgba(183,245,198,.34)":"rgba(255,255,255,.22)",e.strokeStyle=o?p.green:p.muted,e.lineWidth=5,e.setLineDash([16,10]),ne(e,s.x,s.y,s.w,s.h,!0,!0),e.setLineDash([]);let l=vo(r),d=l.cx,v=l.cy;e.fillStyle="rgba(255,255,255,.94)",e.strokeStyle=p.ink,e.lineWidth=4,ne(e,l.x,l.y,l.w,l.h,!0,!0),e.fillStyle=o?p.green:p.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText(r.direction==="right"?"BUY RIGHT LOT":"BUY UPPER LOT",d,v-12),e.fillStyle=p.ink,e.font="900 16px ui-monospace, monospace",e.fillText(`${M(n)} / 10\xD710`,d,v+15),e.fillStyle=p.muted,e.font="900 11px ui-monospace, monospace",e.fillText("blocked tiles included",d,v+30),e.restore()}}function nt(e,t,n,o,r,s,l=0){let d=Ht(s);d<.5||(e.save(),e.globalAlpha=Math.min(.62,.12+d*.54),e.fillStyle="#6b4a23",l>0?(e.beginPath(),e.roundRect?.(t,n,o,r,l),e.roundRect?e.fill():ne(e,t,n,o,r,!0,!1)):ne(e,t,n,o,r,!0,!1),e.globalAlpha=Math.min(.9,.25+d*.6),e.strokeStyle="#3a2a16",e.lineWidth=Math.max(2,Math.floor(2+d*5)),e.setLineDash([5,6]),ne(e,t+3,n+3,o-6,r-6,!1,!0),e.restore())}function or(e,t){let n=e.componentLookup?.get(t);return(n?e.congestion.get(n):null)?.ratio||0}function Ca(e,t,n={}){let o=Qn(e,t).sort(),s=n.kind==="boostConveyor"?"boostConveyor":"conveyor",l=d=>o.includes(d);if(o.length===2){if(l("left")&&l("right"))return be[`${s}StraightH`];if(l("up")&&l("down"))return be[`${s}StraightV`];if(l("up")&&l("right"))return be[`${s}TurnNe`];if(l("up")&&l("left"))return be[`${s}TurnNw`];if(l("down")&&l("right"))return be[`${s}TurnSe`];if(l("down")&&l("left"))return be[`${s}TurnSw`]}return o.length===1?l("up")||l("down")?be[`${s}StraightV`]:be[`${s}StraightH`]:l("up")||l("down")?be[`${s}StraightV`]:be[`${s}StraightH`]}function Ma(e,t){let n=[],o=new Set;for(let s of t.conveyorTiles){let{col:l,row:d}=Q(s);for(let v of ue){let C={col:l+v.dc,row:d+v.dr},P=I(C.col,C.row);if(!t.conveyorTiles.has(P))continue;let R=[s,P].sort().join("|");if(o.has(R))continue;o.add(R);let L=Math.max(or(t,s),or(t,P));n.push({a:F(l,d),b:F(C.col,C.row),ratio:L})}}e.save(),e.lineCap="round",e.lineJoin="round";for(let s of[{width:31,color:"#0b0c0f",alpha:1},{width:23,color:"#444b56",alpha:1},{width:15,color:"#171a1f",alpha:1}]){e.globalAlpha=s.alpha,e.strokeStyle=s.color,e.lineWidth=s.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 s of n){let l=Math.max(0,(s.ratio-.5)/.5);e.strokeStyle=gn(p.green,p.danger,l),e.globalAlpha=s.ratio>.5?.35+l*.55:.8,e.lineWidth=6,e.beginPath(),e.moveTo(s.a.x,s.a.y),e.lineTo(s.b.x,s.b.y),e.stroke()}let r=Aa(t);for(let s of t.conveyorTiles){let l=F(...Object.values(Q(s))),d=t.conveyorMeta.get(s)||{},v=or(t,s),C=Ca(t,s,d),P=v>.5;if(e.fillStyle=P?"rgba(196,36,36,.28)":"rgba(0,0,0,.35)",e.strokeStyle=P?p.danger:"rgba(255,184,39,.34)",e.lineWidth=P?3:1,ne(e,l.x-20,l.y-20,40,40,!0,!0),!Xe(e,C,l.x-19,l.y-19,38,38)){let L=d.kind==="boostConveyor"?"#315e92":"#454b55";e.fillStyle=v>.5?gn(L,"#a12c2c",Math.max(0,(v-.5)/.5)):L,e.strokeStyle=p.ink,e.lineWidth=2,ne(e,l.x-18,l.y-18,36,36,!0,!0)}nt(e,l.x-18,l.y-18,36,36,{meta:d}),He(e,t,"conveyor",s,l.x,l.y,38,38),Da(e,l,r.get(s)||[]);let R=Qn(t,s);Pa(e,l,d,Ta(t,s,R),R),v>.5&&fn(e,l.x,l.y-15,`${Math.floor(v*100)}%`,p.danger)}e.restore()}function Qn(e,t){let n=Q(t);return ue.filter(o=>e.conveyorTiles.has(I(n.col+o.dc,n.row+o.dr))).map(o=>o.name)}function ms(e,t,n){let o=ue.find(l=>l.name===n);if(!o)return!1;let r=e.conveyorMeta?.get?.(I(t.col+o.dc,t.row+o.dr));return r?[...new Set([...Array.isArray(r.outDirs)?r.outDirs:[],r.dir].filter(Boolean))].includes(o.opposite):!1}function ga(e,t,n,o=Qn(e,t),r="random"){if(o.length<3)return n;let s=Q(t),l=new Set(o.filter(C=>ms(e,s,C)));if(r&&r!=="random"&&o.includes(r)){let C=new Set(l);C.add(r),o.filter(P=>!C.has(P)).length>=2&&l.add(r)}let d=o.filter(C=>!l.has(C));if(d.length)return d;let v=n.filter(C=>!l.has(C));return v.length?v:n}function Ta(e,t,n=Qn(e,t)){if(n.length<3)return[];let o=Q(t),r=new Set(n.filter(s=>ms(e,o,s)));return n.filter(s=>{let l=new Set(r);return l.add(s),n.filter(d=>!l.has(d)).length>=2})}function Ea(e,t,n){let o=Q(t),r=ue.filter(d=>e.conveyorTiles.has(I(o.col+d.dc,o.row+d.dr))).map(d=>d.name),s=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(d=>r.includes(d)),l=r;return s.length?s:l}function Pa(e,t,n,o,r=o){if(r.length<3||o.length<2)return;e.save();let s=o.includes(n.branchMode)?n.branchMode:"random",l=s!=="random";if(e.lineJoin="round",e.lineCap="round",e.lineWidth=2,e.fillStyle="rgba(255,255,255,.9)",e.strokeStyle=l?p.warn:p.green,ne(e,t.x-17,t.y-17,34,34,!0,!0),e.strokeStyle=p.ink,e.lineWidth=2,e.fillStyle=p.ink,s!=="random"){let d=ue.find(v=>v.name===s);Xn(e,t.x,t.y,d?.angle||0,9,6)}else e.beginPath(),e.moveTo(t.x-10,t.y),e.lineTo(t.x-2,t.y),e.lineTo(t.x+8,t.y-8),e.moveTo(t.x-2,t.y),e.lineTo(t.x+8,t.y+8),e.stroke(),Xn(e,t.x+9,t.y-9,-Math.PI/4,4,3),Xn(e,t.x+9,t.y+9,Math.PI/4,4,3);e.restore()}function Ra(e,t,n){if(!n)return[];let o=Q(t),r=ue.filter(d=>e.conveyorTiles.has(I(o.col+d.dc,o.row+d.dr))).map(d=>d.name),s=[...new Set([...Array.isArray(n.outDirs)?n.outDirs:[],n.dir].filter(Boolean))].filter(d=>r.includes(d));return ga(e,t,s.length?s:Ea(e,t,n),r,n.branchMode||"random").map(d=>ue.find(v=>v.name===d)).filter(Boolean)}function Aa(e){let t=new Map;for(let[n,o]of e.conveyorMeta||[]){let r=Ra(e,n,o);r.length&&t.set(n,r)}return t}function Da(e,t,n){let o=n.slice(0,4);o.length&&(e.save(),e.fillStyle=p.ink,e.globalAlpha=.86,o.forEach(r=>{Xn(e,t.x+r.dc*12,t.y+r.dr*12,r.angle,6,5)}),e.restore())}function Xn(e,t,n,o,r=11,s=8){e.save(),e.translate(t,n),e.rotate(o),e.beginPath(),e.moveTo(r,0),e.lineTo(-r*.72,-s),e.lineTo(-r*.72,s),e.closePath(),e.fill(),e.restore()}function $a(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=To(n),r=[{type:"inputA",p:Pe(n,"inputA"),label:"IN",color:p.green},{type:"left",p:Pe(n,"left"),label:Po(o.left),color:Ro(o.left)},{type:"right",p:Pe(n,"right"),label:Po(o.right),color:Ro(o.right)}];for(let s of r){if(!s.p)continue;let l=F(s.p.col,s.p.row),d=jr(t,n,s.type||(s.label==="IN"?"inputA":null))||t.conveyorTiles.has(I(s.p.col,s.p.row));e.fillStyle=d?gn("#1a1d23",s.color,.24):"#3a1e22",e.strokeStyle=d?s.color:p.danger,ne(e,l.x-18,l.y-12,36,24,!0,!0),e.fillStyle=p.white,e.fillText(s.label,l.x,l.y+4)}}e.restore()}function Ia(e,t){for(let n of t.eggFarms)Fa(e,n,t)}function Fa(e,t,n){let o=F(t.col,t.row);if(e.save(),Xe(e,be.eggFarm,o.x-29,o.y-29,58,58)){nt(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=p.ink,e.lineWidth=2,ne(e,o.x+9,o.y+12,30,18,!0,!0),e.fillStyle=p.ink,e.font="900 10px ui-monospace, monospace",e.textAlign="center",e.fillText(`O${l}`,o.x+24,o.y+24),He(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore();return}e.fillStyle=p.white,e.strokeStyle=p.ink,e.lineWidth=4,ne(e,o.x-28,o.y-28,56,56,!0,!0),e.fillStyle=p.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=p.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 s=Math.max(0,Math.min(1,t.shutterProgress||0));if(s>0){let l=56*s;e.fillStyle=p.ink,ne(e,o.x-28,o.y-28,56,l,!0,!1),e.strokeStyle=p.white,e.lineWidth=2;for(let d=o.y-24;d=1&&(e.fillStyle=p.white,e.font="900 12px ui-monospace, monospace",e.fillText("SHUT",o.x,o.y+4))}nt(e,o.x-28,o.y-28,56,56,t),He(e,n,"eggFarm",t.id,o.x,o.y,68,68),e.restore()}function Ba(e,t){for(let n of t.scanners)La(e,n,t)}function La(e,t,n){let o=pe(t);if(e.save(),t.kind==="manual"&&(n.manualCombo?.count||0)>=10){let v=n.manualCombo.count;e.save(),e.globalAlpha=Math.min(.55,.16+v/120),e.strokeStyle=v>=30?p.warn:p.green,e.lineWidth=Math.min(14,5+Math.floor(v/10)),e.shadowColor=e.strokeStyle,e.shadowBlur=Math.min(28,8+v),ne(e,o.x-54,o.y-76,108,152,!1,!0),e.restore()}let r=t.kind==="auto"?be.scannerAuto:be.scannerManual;if(Xe(e,r,o.x-50,o.y-73,100,146)){t.kind==="auto"?nt(e,o.x-50,o.y-73,100,146,t):ps(e,t,o),He(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore();return}e.fillStyle=t.kind==="auto"?"#d8ffe2":p.white,e.strokeStyle=p.ink,e.lineWidth=4,ne(e,o.x-50,o.y-73,100,146,!0,!0),e.fillStyle=t.kind==="auto"?p.green:p.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-48),e.font="900 11px ui-monospace, monospace";let s=t.keys?.left?.label||(t.slot===0?"A":"Left"),l=t.keys?.right?.label||(t.slot===0?"D":"Right");e.fillText(t.role===0?`${s}:M ${l}:NEXT`:`${s}:WASTE ${l}:TRUCK`,o.x,o.y-28);let d=t.queue.length;t.kind==="manual"?(ps(e,t,o),e.fillStyle=d>0?p.green:p.muted,e.font="900 10px ui-monospace, monospace",e.fillText(`Q:${d}`,o.x,o.y+54)):(e.fillStyle=d>0?p.green:p.muted,e.font="900 12px ui-monospace, monospace",e.fillText(`Q:${d} CD:${t.cooldown.toFixed(1)}`,o.x,o.y+54),nt(e,o.x-50,o.y-73,100,146,t)),He(e,n,"scanner",t.id,o.x,o.y,108,154),e.restore()}function ps(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 s=t.keyPressTime>0?t.keyPressSide:null,l=n.x-30,d=n.y+18;e.save(),e.lineWidth=3,e.fillStyle="#f7fff5",e.strokeStyle=p.ink,ne(e,l-4,d-4,68,25,!0,!0),e.font="900 19px ui-monospace, monospace",e.textAlign="center";for(let v=0;v.8,s=t.y+Math.sin(t.bob)*(r?5:1.5);if(e.save(),n&&(e.strokeStyle=p.green,e.lineWidth=5,e.beginPath(),e.arc(t.x,s,t.radius+8,0,Math.PI*2),e.stroke()),r&&(e.strokeStyle=p.danger,e.lineWidth=3,e.beginPath(),e.arc(t.x,s,t.radius+12+Math.sin(t.bob*2)*4,0,Math.PI*2),e.stroke()),t.sex==="poop")lr(e,t.x,s,t.radius);else{let l=t.sex==="male"?be.chickMale:be.chickFemale;Xe(e,l,t.x-t.radius,s-t.radius,t.radius*2,t.radius*2)||(e.fillStyle=t.sex==="male"?p.male:p.female,e.strokeStyle=p.ink,e.lineWidth=5,e.beginPath(),e.arc(t.x,s,t.radius,0,Math.PI*2),e.fill(),e.stroke(),e.fillStyle=p.ink,e.beginPath(),e.arc(t.x-6,s-5,2.5,0,Math.PI*2),e.arc(t.x+6,s-5,2.5,0,Math.PI*2),e.fill(),e.fillStyle="#ffaa2e",e.beginPath(),e.moveTo(t.x,s+2),e.lineTo(t.x+9,s+6),e.lineTo(t.x,s+10),e.closePath(),e.fill())}e.restore()}function qa(e,t){let n=null,o=1/0;for(let[r,s]of e.componentLookup.entries()){let l=Q(r),d=F(l.col,l.row),v=Math.hypot(t.x-d.x,t.y-d.y);vys(o.type,o.id)===ys(t,n))}function He(e,t,n,o,r,s,l,d){Ya(t,n,o)&&(e.save(),e.fillStyle="rgba(34,185,79,.18)",e.strokeStyle=p.green,e.lineWidth=(t.multiSelected||[]).length>1?6:4,e.setLineDash((t.multiSelected||[]).length>1?[]:[8,5]),ne(e,r-l/2,s-d/2,l,d,!0,!0),e.restore())}function Va(e,t,n,o){if(t.phase==="build"&&(t.multiSelected||[]).length>1){e.save(),e.fillStyle="rgba(255,255,255,.96)",e.strokeStyle=p.ink,e.lineWidth=3,ne(e,54-t.view.x,66-t.view.y,214,42,!0,!0),e.fillStyle=p.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=p.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 za(e,t,n){if(!n.cardTargetPick?.pending)return;let o=nr(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 v of o){let C=v.bounds,P=8;e.rect(C.x-P,C.y-P,C.w+P*2,C.h+P*2)}e.fill("evenodd");let s=n.cardTargetPick?.mode==="blockedCell";if(!o.length){e.fillStyle="rgba(255,255,255,.95)",e.strokeStyle=p.ink,e.lineWidth=3,ne(e,(260-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,420/r,42/r,!0,!0),e.fillStyle=p.danger,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(s?"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=p.ink,e.lineWidth=3;let l=Math.max(1,n.cardTargetPick?.remaining||1),d=n.cardTargetPick?.mode==="autoScannerMenu"?"AUTO SCANNER ROUTE SETTINGS. CLICK EMPTY AREA TO CLOSE.":s?`CLICK BLOCKED CELL: ${l} LEFT. PRESS ESC TO CANCEL.`:"CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.";ne(e,(216-(n.view?.x||0))/r,(96-(n.view?.y||0))/r,560/r,42/r,!0,!0),e.fillStyle=p.ink,e.font="900 12px ui-monospace, monospace",e.textAlign="center",e.fillText(d,(496-(n.view?.x||0))/r,(122-(n.view?.y||0))/r),e.restore()}function Xa(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),s=Math.abs(n.x2-n.x1),l=Math.abs(n.y2-n.y1);e.save(),e.fillStyle="rgba(34,185,79,.12)",e.strokeStyle=p.green,e.lineWidth=2,e.setLineDash([7,4]),ne(e,o,r,s,l,!0,!0),e.restore()}function Qa(e,t){let n=[...t.effects].sort((o,r)=>(o.priority??Ce.ambient)-(r.priority??Ce.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=p.green,ne(e,o.x-o.size/2,o.y-o.size/2,o.size*1.5,o.size,!0,!1)):o.type==="sludge"?(e.fillStyle=p.poop,ne(e,o.x-o.size/2,o.y-o.size/2,o.size*1.4,o.size,!0,!1)):o.type==="spawn"?(e.strokeStyle=p.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||p.danger,ne(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||p.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||p.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||p.ink,e.save(),e.translate(o.x,o.y),e.rotate(o.rot||0),ne(e,-o.w/2,-o.h/2,o.w,o.h,!0,!1),e.restore()):o.type==="load"?(e.strokeStyle=o.color||p.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=p.ink,e.lineWidth=3,e.setLineDash([4,4]),ne(e,o.x-o.size/2,o.y-o.size/2,o.size,o.size,!1,!0)):o.type==="rage"?(e.fillStyle=o.color||p.danger,e.font="900 16px ui-monospace, monospace",e.textAlign="center",e.fillText("!",o.x,o.y)):o.type==="flyingChick"&&(o.sex==="poop"?lr(e,o.x,o.y,o.radius||11):ar(e,o.x,o.y,o.sex,o.sex==="male")),e.restore()}}function Ja(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=p.white,e.fillStyle=n.color,e.strokeText(n.text,n.x,n.y),e.fillText(n.text,n.x,n.y)}e.restore()}function ja(e,t){let n=t.repairman;if(!(!!n?.active||t.phase==="build"&&!!n?.hiredForNextDay))return;if(e.save(),Xe(e,be.repairman,n.x-18,n.y-18,36,36)){n.target?.label?fn(e,n.x,n.y-24,n.target.label,p.green):!n.active&&n.hiredForNextDay&&fn(e,n.x,n.y-24,"NEXT DAY",p.green),e.restore();return}e.lineWidth=3,e.fillStyle="#fff0d1",e.strokeStyle=p.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?p.danger:p.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=p.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=p.green,ne(e,n.x-9,n.y+14,18,8,!0,!0),e.strokeStyle=p.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=p.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?fn(e,n.x,n.y-24,n.target.label,p.green):!n.active&&n.hiredForNextDay&&fn(e,n.x,n.y-24,"NEXT DAY",p.green),e.restore()}function Za(e,t,n){e.save(),e.font="900 19px ui-monospace, monospace",e.textAlign="left",e.fillStyle=p.ink,e.fillStyle="rgba(255,255,255,.92)",e.strokeStyle=p.ink,e.lineWidth=3,ne(e,n.width-284,18,260,34,!0,!0),e.fillStyle=p.green,e.font="900 12px ui-monospace, monospace",e.fillText(Sn,n.width-270,40),e.font="900 19px ui-monospace, monospace",e.fillStyle=p.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 s of o)e.strokeStyle=p.white,e.lineWidth=4,e.strokeText(s,24,r),e.fillText(s,24,r),r+=20;e.restore()}var Ss=[[{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 ec(e){let t=Ss[e]||Ss[0];return{left:{...t[0]},right:{...t[1]}}}function ks(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=gt(o),o.lastInterval=o.nextSpawn,o}function xs(e,t,n,o){let r=o==="auto"?ke.autoScanner.price:ke.manualScanner.price,s=new Set(e.scanners.filter(d=>d.kind==="manual").map(d=>d.slot)),l=0;for(;s.has(l);)l+=1;return{type:"scanner",id:e.nextId++,kind:o,slot:o==="manual"?l:null,role:o==="manual"?l%2:0,col:t,row:n,level:1,queue:[],cooldown:0,price:r,builtSession:e.buildSession,autoMode:"standard",keys:o==="manual"?ec(l):null}}function Jn(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))),s=Math.abs(e.x-y.x),l=Math.abs(e.x-(y.x+y.cols*y.cell)),d=Math.abs(e.y-y.y),v=Math.abs(e.y-(y.y+y.rows*y.cell)),C=[["left",s],["right",l],["top",d],["bottom",v]].sort((P,R)=>P[1]-R[1])[0][0];return C==="left"?{side:C,entry:{col:0,row:r}}:C==="right"?{side:C,entry:{col:y.cols-1,row:r}}:C==="top"?{side:C,entry:{col:o,row:0}}:{side:C,entry:{col:o,row:y.rows-1}}}function jn(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 Cs(e,t,n,o){let{entry:r,side:s}=Jn(n),l=ke[t],d=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},v={type:"facility",id:t,name:d.name,x:0,y:0,w:d.w,h:d.h,level:1,price:o||d.price,builtSession:e.buildSession};return jn(v,r,s)}function tc(e){return Math.random()({x:s.x,y:s.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 gs({game:e,canvasPoint:t,updatePanels:n,equipmentAtPoint:o,fail:r,pointInGrid:s,rectOfFacility:l,rectsOverlap:d}){function v(k){return k?k.type==="conveyor"?`conveyor:${k.id||k.oldKey}`:k.type==="facility"?`facility:${k.id||k.ref?.id}`:`${k.type}:${k.id||k.ref?.id}`:""}function C(k){return k?k.type==="conveyor"?{type:"conveyor",id:k.oldKey}:{type:k.type,id:k.ref.id}:null}function P(k){let g=v(C(k));return(e.multiSelected||[]).some(O=>v(O)===g)}function R(k){return k?k.type==="eggFarm"?e.eggFarms.find(g=>g.id===k.id)||null:k.type==="scanner"?e.scanners.find(g=>g.id===k.id)||null:k.type==="facility"?e.facilities[k.id]||null:k.type==="conveyor"&&e.conveyorTiles.has(k.id)?{type:"conveyor",id:k.id}:null:null}function L(){let k=[];for(let g of e.conveyorTiles){let O=Q(g),X=F(O.col,O.row);k.push({type:"conveyor",id:g,center:X,cell:O})}for(let g of e.eggFarms)k.push({type:"eggFarm",id:g.id,ref:g,center:F(g.col,g.row),cell:{col:g.col,row:g.row}});for(let g of e.scanners)k.push({type:"scanner",id:g.id,ref:g,center:pe(g),cell:{col:g.col,row:g.row}});for(let g of Object.values(e.facilities)){let O={x:g.x+g.w/2,y:g.y+g.h/2},X=g.entry?F(g.entry.col,g.entry.row):O;k.push({type:"facility",id:g.id,ref:g,center:O,portCenter:X})}return k}function V(k,g){let O=Math.min(g.x1,g.x2),X=Math.max(g.x1,g.x2),oe=Math.min(g.y1,g.y2),de=Math.max(g.y1,g.y2);return k.x>=O&&k.x<=X&&k.y>=oe&&k.y<=de}function te(k){let g=[];for(let O of L())(V(O.center,k)||O.portCenter&&V(O.portCenter,k))&&g.push({type:O.type,id:O.id});return e.multiSelected=g,e.selected=g[0]||null,n(),g.length}function z(){e.multiSelected=[],e.selected=null,n()}function se(k){let g=t(k);return e.selectionBox={x1:g.x,y1:g.y,x2:g.x,y2:g.y},e.multiSelected=[],e.selected=null,n(),!0}function ye(k){if(!e.selectionBox)return;let g=t(k);e.selectionBox.x2=g.x,e.selectionBox.y2=g.y}function Z(){if(!e.selectionBox)return 0;let k=e.selectionBox,g=Math.abs(k.x2-k.x1),O=Math.abs(k.y2-k.y1);return e.selectionBox=null,g<6&&O<6?(z(),0):te(k)}function $(k){let g=C(k);return g?(e.multiSelected||[]).length&&P(k)?[...e.multiSelected]:[g]:[]}function U(k){let g=R(k);if(!g)return null;if(k.type==="conveyor"){let O=Q(k.id);return{...k,obj:g,oldKey:k.id,currentKey:k.id,meta:e.conveyorMeta.get(k.id)||{price:_e("conveyor"),builtSession:null},col:O.col,row:O.row}}return k.type==="eggFarm"||k.type==="scanner"?{...k,obj:g,col:g.col,row:g.row}:k.type==="facility"?{...k,obj:g,x:g.x,y:g.y,w:g.w,h:g.h,entry:g.entry?{...g.entry}:null,side:g.side,center:{x:g.x+g.w/2,y:g.y+g.h/2}}:null}function N(k){let g=t(k),O=o(g);if(!O)return!1;let X=$(O),oe=X.map(U).filter(Boolean);return oe.length?(e.groupDrag={start:g,selections:X,origins:oe,historySnapshot:cn(e),committed:!1,lastDCol:0,lastDRow:0},e.multiSelected=X,e.selected=X[0]||null,n(),!0):!1}function le(){!e.groupDrag||e.groupDrag.committed||(e.undoStack.push(e.groupDrag.historySnapshot),e.redoStack=[],e.groupDrag.committed=!0)}function Se(k,g,O){let X=I(k,g),oe=Et(e,k,g);if(oe&&!O.has(`eggFarm:${oe.id}`))return!0;let de=Pt(e,k,g);return!!(de&&!O.has(`scanner:${de.id}`)||e.conveyorTiles.has(X)&&!O.has(`conveyor:${X}`))}function he(k,g,O){let X=[];for(let oe of e.groupDrag.origins){if(oe.type!=="facility")continue;let de={x:oe.center.x+k,y:oe.center.y+g},{entry:Te,side:ce}=Jn(de);if(!s(Te.col,Te.row)||e.blockedCells?.has?.(I(Te.col,Te.row)))return!0;let rt={...oe.obj,entry:{...Te},side:ce};jn(rt,Te,ce),X.push({id:oe.id,rect:l(rt)})}for(let oe of X)for(let de of Object.values(e.facilities))if(!O.has(`facility:${de.id}`)&&d(oe.rect,l(de),12))return!0;for(let oe=0;oeJ.type==="conveyor");for(let J of rt){let ge=J.currentKey||J.oldKey;e.conveyorTiles.delete(ge),e.conveyorMeta.delete(ge)}for(let J of rt){let ge=I(J.col+oe,J.row+de);e.conveyorTiles.add(ge),e.conveyorMeta.set(ge,J.meta||{price:_e("conveyor"),builtSession:null,uses:0}),J.currentKey=ge}for(let J of e.groupDrag.origins)if(J.type==="eggFarm")J.obj.col=J.col+oe,J.obj.row=J.row+de;else if(J.type==="scanner")J.obj.col=J.col+oe,J.obj.row=J.row+de;else if(J.type==="facility"){let ge={x:J.center.x+O,y:J.center.y+X},{entry:Le,side:it}=Jn(ge);jn(J.obj,Le,it)}e.groupDrag.selections=e.groupDrag.origins.map(J=>J.type==="conveyor"?{type:"conveyor",id:J.currentKey||J.oldKey}:{type:J.type,id:J.id}),e.multiSelected=[...e.groupDrag.selections],e.selected=e.multiSelected[0]||null,ve(e),n()}function _(){e.groupDrag&&(ve(e),e.groupDrag=null,n())}return{selectionFromHit:C,startSelectionBox:se,updateSelectionBox:ye,finishSelectionBox:Z,startGroupDrag:N,updateGroupDrag:A,finishGroupDrag:_}}function Ts({game:e,ui:t,canvas:n,canvasPoint:o,onUpdatePanels:r}){function s(){r&&r()}let l=null,d=!1,v=null,C=!1,P=["random","up","right","down","left"],R={random:"RND",up:"UP",right:"RT",down:"DN",left:"LF"},L={w:40,h:40,y:0};function V(){return En(e)}function te(){e.gridCols=y.cols,e.gridRows=y.rows,e.gridOwnedCells=Nr(e)}function z(i){if(i){y.y-=i*y.cell,y.rows+=i,e.gridChunkOriginY=(e.gridChunkOriginY||0)-Math.floor(i/10),e.ownedCells=Pn(e.ownedCells,i),e.blockedCells=Pn(e.blockedCells,i),e.conveyorTiles=Pn(e.conveyorTiles,i),e.conveyorMeta=Wr(e.conveyorMeta,i);for(let c of e.eggFarms||[])c.row+=i;for(let c of e.scanners||[])c.row+=i;for(let c of Object.values(e.facilities||{}))c.entry&&(c.entry.row+=i)}}function se(i){e.ownedCells=e.ownedCells||new Set;for(let c of Ur(i))e.ownedCells.add(I(c.col,c.row))}function ye(i){return e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending?null:Ct(e).find(c=>c&&Gr(c,i))||null}function Z(i="right"){if(i&&typeof i=="object"&&Number.isFinite(i.chunkX)&&Number.isFinite(i.chunkY))return i;let c=["right","up"].includes(i)?i:"right";return _r(e,c)}function $(i="right"){let c=Z(i);if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return{ok:!1,reason:"Cannot expand now."};if(!c)return{ok:!1,reason:"Invalid expansion lot."};let h=c.direction||"right",m=V();if(e.cashy.cols&&(y.cols=T.colStart+T.cols),T.rowStart+T.rows>y.rows&&(y.rows=T.rowStart+T.rows),se(T),Kr(e,T.chunkX,T.chunkY),e.gridExpansionPurchases=(e.gridExpansionPurchases||0)+1,e.gridExpansionPurchasesByDirection[h]=(e.gridExpansionPurchasesByDirection[h]||0)+1,te();let j=Ir({seed:`${e.runSeed}:grid-expansion:${T.chunkX},${T.chunkY}:${e.gridExpansionPurchases}`,colStart:T.colStart,colEnd:T.colStart+T.cols,rowStart:T.rowStart,rowEnd:T.rowStart+T.rows,targetRatio:q.map.blockedRatio});for(let Re of j)e.blockedCells.add(Re);ve(e);let ie=T.cols*T.rows,fe=Mt(T);return W(e,fe.x+fe.w/2,fe.y+fe.h/2,`${h.toUpperCase()} +${ie} CELLS -${M(m)}`,p.green),s(),{ok:!0,direction:h,cost:m,addedCells:ie,blocked:j.size,chunkX:T.chunkX,chunkY:T.chunkY}}function U(i,c){return i>=0&&i=0&&c!c.has(m.id)&&Se(h,le(m),12))}function A(i,c,h=null){if(!U(i,c))return!1;if(N(i,c))return!0;let m=I(i,c),x=Et(e,i,c);if(x&&!(h?.type==="eggFarm"&&h.ref?.id===x.id))return!0;let T=Pt(e,i,c);return!!(T&&!(h?.type==="scanner"&&h.ref?.id===T.id)||e.conveyorTiles.has(m)&&!(h?.type==="conveyor"&&h.oldKey===m))}function _(i,c,h=null){let m={col:i,row:c};for(let x of Tt(m)){if(!U(x.col,x.row)||N(x.col,x.row))return!0;let T=I(x.col,x.row);if(Et(e,x.col,x.row))return!0;let ie=Pt(e,x.col,x.row);if(ie&&!(h?.type==="scanner"&&h.ref?.id===ie.id)||e.conveyorTiles.has(T))return!0}return!1}function k(){return e.selected?e.selected.type==="eggFarm"?e.eggFarms.find(i=>i.id===e.selected.id)||null:e.selected.type==="scanner"?e.scanners.find(i=>i.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 g(i){return i?i.type==="eggFarm"?`${xt("eggFarm")} #${i.id}`:i.type==="scanner"?`${i.kind==="auto"?xt("autoScanner"):xt("manualScanner")} #${i.id}`:i.type==="conveyor"?e.conveyorMeta.get(i.id)?.kind==="boostConveyor"?xt("boostConveyor"):xt("conveyor"):i.type==="facility"?i.name:"Equipment":"Equipment"}function O(i){return i?.type==="conveyor"?e.conveyorMeta?.get(i.oldKey||i.ref?.id)?.price||Bn(i):Bn(i)}function X(){return!!e.cardEffects?.usedMachineActive}function oe(){return X()?{usedMachine:!0,noRefund:!0,durabilityBaseMultiplier:.6}:{usedMachine:!1,noRefund:!1,durabilityBaseMultiplier:1}}function de(i){let c=oe();return Object.assign(i,c),i}function Te(i){let c=i?.ref||i||{};if(i?.type==="eggFarm"||c.type==="eggFarm")return e.eggFarms.length<=1?"Cannot sell the last EGG FARM.":"";if((i?.type==="facility"||c.type==="facility")&&["mixer","trash","truck"].includes(c.baseId||c.id)){let h=c.baseId||c.id;if(Object.values(e.facilities).filter(x=>(x.baseId||x.id)===h).length<=1)return`Cannot sell the last ${c.shortName||c.name||c.id}.`}return""}function ce(i){t.buildStatus.textContent=i,W(e,n.width/2-e.view.x,86-e.view.y,i.toUpperCase(),p.danger)}function rt(i){if(!i)return null;let c=I(i.col,i.row);return e.conveyorMeta.get(c)||null}function J(i){return i?(Array.isArray(i.outDirs)||(i.outDirs=[]),i.outDirs=[...new Set(i.outDirs.filter(c=>["right","left","down","up"].includes(c)))],P.includes(i.branchMode)||(i.branchMode="random"),i.kind||(i.kind="conveyor"),i.speedMultiplier||(i.speedMultiplier=i.kind==="boostConveyor"?2:1),i.outDirs):[]}function ge(i){return i?ue.filter(c=>e.conveyorTiles.has(I(i.col+c.dc,i.row+c.dr))).map(c=>c.name):[]}function Le(i){return ge(i).length>=3}function it(i,c){let h=ue.find(ie=>ie.name===c);if(!i||!h)return!1;let m=I(i.col+h.dc,i.row+h.dr),x=e.conveyorMeta.get(m);if(!x)return!1;let T=h.opposite;return[...new Set([...Array.isArray(x.outDirs)?x.outDirs:[],x.dir].filter(Boolean))].includes(T)}function Ge(i){if(!e.conveyorTiles.has(i))return[];let c=Q(i),h=e.conveyorMeta.get(i),m=J(h),x=ge(c),T=[...new Set([...m,h?.dir].filter(Boolean))].filter(fe=>x.includes(fe)),j=x,ie=T.length?T:j;return h&&(h.outDirs=m.filter(fe=>x.includes(fe)),h.dir&&!x.includes(h.dir)&&(h.dir=h.outDirs[0]||null),h.branchMode!=="random"&&!x.includes(h.branchMode)&&(h.branchMode="random")),ie}function st(i){if(!e.conveyorTiles.has(i))return[];let c=Q(i),h=ge(c);return Le(c)||h.length?h:Ge(i)}function oo(i){let c=Q(i),h=st(i);if(h.length<3)return[];let m=new Set(h.filter(x=>it(c,x)));return h.filter(x=>{let T=new Set(m);return T.add(x),h.filter(j=>!T.has(j)).length>=2})}function yn(i,c){let h=at(i,c);if(!h)return!1;let m=I(i.col,i.row),x=I(c.col,c.row),T=e.conveyorMeta.get(m),j=e.conveyorMeta.get(x);if(!T||!j)return!1;let ie=J(T),fe=!ie.includes(h)||T.dir!==h||!j.dir;return ie.includes(h)||ie.push(h),T.dir=h,j.dir||(j.dir=h),fe}function hn(i){let c=ro(i);return c.length<2?mn(i):(Fe(e),io(c),ve(e),s(),!0)}function mn(i){if(!i)return!1;let c=I(i.col,i.row),h=e.conveyorMeta.get(c);if(!h||Le(i))return!1;let m=ue.map(j=>j.name),x=h.dir&&m.includes(h.dir)?h.dir:null,T=m[(Math.max(-1,m.indexOf(x))+1)%m.length];return Fe(e),h.dir=T,h.outDirs=[T],h.branchMode="random",ve(e),s(),!0}function vt(i){return i?ue.map(c=>({col:i.col+c.dc,row:i.row+c.dr})).filter(c=>e.conveyorTiles.has(I(c.col,c.row))):[]}function ro(i){if(!i||!e.conveyorTiles.has(I(i.col,i.row))||Le(i))return[];let c=vt(i);if(!c.length||c.length>2)return[];let h=T=>{let j=[],ie=new Set([I(i.col,i.row)]),fe=i,Re=T,br=0;for(;Re&&br<200;){br+=1;let vr=I(Re.col,Re.row);if(ie.has(vr)||(ie.add(vr),j.push(Re),Le(Re)))break;let wr=vt(Re).filter(Sr=>!(Sr.col===fe.col&&Sr.row===fe.row));if(wr.length!==1)break;fe=Re,Re=wr[0]}return j},m=c[0]?h(c[0]).reverse():[],x=c[1]?h(c[1]):[];return[...m,i,...x]}function bn(i,c){return!!i&&[...new Set([...Array.isArray(i.outDirs)?i.outDirs:[],i.dir].filter(Boolean))].includes(c)}function io(i){let c=0,h=0;for(let x=0;xh?[...i].reverse():i;for(let x=0;x=Math.abs(m)?{col:i.col+Math.sign(h),row:i.row}:{col:i.col,row:i.row+Math.sign(m)}}function so(i){d=!1,v=i?{col:i.col,row:i.row}:null,C=!1,l=null,Nt(i)}function jt(i){if(!i)return;if(!l)return Nt(i);let c=l,h=0;for(;(c.col!==i.col||c.row!==i.row)&&h<64;){let m=Jt(c,i);if(Nt(m),c=l||m,h+=1,!l)break}}function wn(){!C&&v&&e.conveyorTiles.has(I(v.col,v.row))&&hn(v),v=null,C=!1,l=null,d=!1}function u(i){if(!i)return ce(re.fail.outOfGrid);let{col:c,row:h}=i;if(e.buildTool==="conveyor"||e.buildTool==="boostConveyor"){let m=vn(i,null);if(!m.ok)return ce(m.reason||re.fail.cellOccupied);ve(e);return}if(N(c,h))return ce("Cannot build on blocked ground.");if(e.buildTool==="manualScanner"||e.buildTool==="autoScanner"?_(c,h):A(c,h))return ce(re.fail.cellOccupied);e.buildTool==="eggFarm"?b(c,h):e.buildTool==="manualScanner"?S(c,h,"manual"):e.buildTool==="autoScanner"&&S(c,h,"auto")}function f(i){let c=We(i.x,i.y);if(["conveyor","boostConveyor","eggFarm","manualScanner","autoScanner"].includes(e.buildTool))return u(c);if(nn.includes(e.buildTool))return w(i,e.buildTool)}function b(i,c){let h=_e("eggFarm",e);if(e.cashT.kind==="manual").length>=8)return ce("Manual Scanner limit reached (8 max).");let m=h==="auto"?_e("autoScanner",e):_e("manualScanner",e);if(e.cashx.id!==c.ref.id),yt(e,m.x,m.y),ve(e)}if(c.type==="scanner"){let m=pe(c.ref);E(c,m.x,m.y),e.scanners=e.scanners.filter(x=>x.id!==c.ref.id),yt(e,m.x,m.y),ve(e)}if(c.type==="facility"){let m=c.ref;E(c,m.x+m.w/2,m.y+m.h/2),delete e.facilities[m.id],yt(e,m.x+m.w/2,m.y+m.h/2),ve(e)}e.selected=null,e.multiSelected=[],s()}function K(i){let c=Object.values(e.facilities).find(j=>{if(i.x>=j.x&&i.x<=j.x+j.w&&i.y>=j.y&&i.y<=j.y+j.h)return!0;if(!j.entry)return!1;let fe=F(j.entry.col,j.entry.row);return Math.abs(i.x-fe.x)<=y.cell*.46&&Math.abs(i.y-fe.y)<=y.cell*.46});if(c)return{type:"facility",ref:c};let h=We(i.x,i.y);if(!h)return null;let m=Et(e,h.col,h.row);if(m)return{type:"eggFarm",ref:m};let x=Pt(e,h.col,h.row);if(x)return{type:"scanner",ref:x};let T=I(h.col,h.row);return e.conveyorTiles.has(T)?{type:"conveyor",oldKey:T,ref:{type:"conveyor",id:T}}:null}let ee=gs({game:e,canvasPoint:o,updatePanels:s,equipmentAtPoint:K,fail:ce,pointInGrid:U,rectOfFacility:le,rectsOverlap:Se});function Qe(i){return null}function ur(){let i=k();i&&(i.type==="conveyor"?D(F(...Object.values(Q(i.id)))):i.type==="eggFarm"?D(F(i.col,i.row)):i.type==="scanner"?D(pe(i)):i.type==="facility"&&D({x:i.x+i.w/2,y:i.y+i.h/2}))}function qe(i,c,h="primary-button"){let m=document.createElement("button");return m.type="button",m.className=h,m.textContent=i,m.addEventListener("click",c),m}function Zt(){e.cardTargetPick?.mode==="autoScannerMenu"&&(e.cardTargetPick=null),t.modal.classList.remove("visible","equipment-popover"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function lo(i){t.modalTitle.textContent="Auto Scanner",e.cardTargetPick={pending:!0,mode:"autoScannerMenu",cardId:null,targetKeys:[`scanner:${i.id}`],remaining:1},t.modalBody.innerHTML=`

Left / right output routing for this AUTO scanner.

Current: ${i.role===0?"Male left / others right":"Poop left / others right"}

-

Cooldown: ${et(i).toFixed(1)}s.

-
`,t.modalActions.innerHTML="";let c=He("Male Left / Others Right",()=>{$e(e),i.role=0,Zt(),s()},i.role===0?"facility-action warn":"facility-action"),h=He("Poop Left / Others Right",()=>{$e(e),i.role=1,Zt(),s()},i.role===1?"facility-action warn":"facility-action");t.modalActions.append(c,h,He("Close",Zt,"facility-action")),io(i),t.modal.classList.add("visible","equipment-popover"),s()}function dr(i){return i?.label||i?.key||"?"}function Ks(i){let c=i.key===" "?"Space":i.key.length===1?i.key.toUpperCase():i.key.replace(/^Arrow/,"");return{key:i.key.toLowerCase(),code:i.code,label:c}}function Hs(i,c,h){for(let m of e.scanners.filter(k=>k.kind==="manual"))for(let k of["left","right"]){if(m.id===i.id&&k===c)continue;let T=m.keys?.[k];if(T&&(T.code===h.code||T.key===h.key))return!0}return!1}function en(i,c=""){if(!i||i.kind!=="manual")return;t.modalTitle.textContent=`Manual Scanner #${i.id}`;let h=dr(i.keys?.left),m=dr(i.keys?.right),k=qs(i);t.modalBody.innerHTML=` +

Cooldown: ${tt(i).toFixed(1)}s.

+ `,t.modalActions.innerHTML="";let c=qe("Male Left / Others Right",()=>{Fe(e),i.role=0,Zt(),s()},i.role===0?"facility-action warn":"facility-action"),h=qe("Poop Left / Others Right",()=>{Fe(e),i.role=1,Zt(),s()},i.role===1?"facility-action warn":"facility-action");t.modalActions.append(c,h,qe("Close",Zt,"facility-action")),ao(i),t.modal.classList.add("visible","equipment-popover"),s()}function dr(i){return i?.label||i?.key||"?"}function Hs(i){let c=i.key===" "?"Space":i.key.length===1?i.key.toUpperCase():i.key.replace(/^Arrow/,"");return{key:i.key.toLowerCase(),code:i.code,label:c}}function qs(i,c,h){for(let m of e.scanners.filter(x=>x.kind==="manual"))for(let x of["left","right"]){if(m.id===i.id&&x===c)continue;let T=m.keys?.[x];if(T&&(T.code===h.code||T.key===h.key))return!0}return!1}function en(i,c=""){if(!i||i.kind!=="manual")return;t.modalTitle.textContent=`Manual Scanner #${i.id}`;let h=dr(i.keys?.left),m=dr(i.keys?.right),x=Ys(i);t.modalBody.innerHTML=`

Left route key: ${h}

Right route key: ${m}

${c?`

${c}

`:""} - ${k?`

${k}

`:""} -
`,t.modalActions.innerHTML="",t.modalActions.appendChild(He("Set Left Key",()=>fr(i,"left"),"facility-action warn")),t.modalActions.appendChild(He("Set Right Key",()=>fr(i,"right"),"facility-action warn")),t.modalActions.appendChild(He("Close",Zt,"facility-action")),io(i),t.modal.classList.add("visible","equipment-popover")}function qs(i){let c=[{side:"left",binding:i.keys?.left},{side:"right",binding:i.keys?.right}];if(c[0].binding&&c[1].binding&&(c[0].binding.code===c[1].binding.code||c[0].binding.key===c[1].binding.key))return"Left and right keys conflict.";for(let h of c)if(h.binding)for(let m of e.scanners.filter(k=>k.kind==="manual"&&k.id!==i.id)){if(m.keys?.left&&(m.keys.left.code===h.binding.code||m.keys.left.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} left.`;if(m.keys?.right&&(m.keys.right.code===h.binding.code||m.keys.right.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} right.`}return""}function fr(i,c){t.modalBody.innerHTML=`

Press a key for ${c.toUpperCase()} route.

Esc cancels.

`,t.modalActions.innerHTML="";let h=m=>{if(m.preventDefault(),m.stopPropagation(),window.removeEventListener("keydown",h,!0),m.key==="Escape")return en(i);let k=Ks(m),T=Hs(i,c,k);$e(e),i.keys=i.keys||{left:null,right:null},i.keys[c]=k,s(),en(i,T?`${k.label} assigned, but another scanner already uses it.`:`${c.toUpperCase()} set to ${k.label}.`)};window.addEventListener("keydown",h,!0)}function Ys(){let i=x();if(!(!i||i.type!=="scanner"))return i.kind==="auto"?ro(i):en(i)}function Vs(i){if(!i)return{x:80,y:80};if(i.type==="conveyor"){let c=Q(i.id);return F(c.col,c.row)}return i.type==="eggFarm"?F(i.col,i.row):i.type==="scanner"?pe(i):i.type==="facility"?{x:i.x+i.w/2,y:i.y+10}:{x:80,y:80}}function io(i){let c=n.getBoundingClientRect(),h=Vs(i),m=e.view?.scale||1,k=c.left+(h.x*m+(e.view?.x||0))/n.width*c.width+18,T=c.top+(h.y*m+(e.view?.y||0))/n.height*c.height-12,j=Math.max(12,window.innerWidth-274),ie=Math.max(12,window.innerHeight-220);t.modal.style.setProperty("--popover-x",`${Math.max(12,Math.min(j,k))}px`),t.modal.style.setProperty("--popover-y",`${Math.max(12,Math.min(ie,T))}px`)}function zs(){let i=x();if(!i)return;let c=mr(i);t.modalTitle.textContent=g(i),t.modalBody.innerHTML=` -
${c.map(k=>`

${k}

`).join("")}
- ${["mixer","truck"].includes(i.baseId||i.id)?'

Income/Fine = ceil(base x 1.10^upgrades)

':""}`,t.modalActions.innerHTML="",i.type==="scanner"&&i.kind==="auto"&&t.modalActions.appendChild(He("Auto Menu",()=>ro(i),"facility-action warn")),i.type==="scanner"&&i.kind==="manual"&&t.modalActions.appendChild(He("Set Keys",()=>en(i),"facility-action warn"));let h=i.type==="conveyor"?{type:"conveyor",oldKey:i.id,ref:i}:{type:i.type,ref:i},m=ge(h);if(m){let k=He(m,()=>{},"facility-action danger disabled");k.disabled=!0,t.modalActions.appendChild(k)}else{let k=Dt(h,e),T=k.sameBuild?`Remove / Refund ${M(k.amount)}`:`Sell ${M(k.amount)}`;t.modalActions.appendChild(He(T,()=>{ur(),Zt()},"facility-action danger"))}io(i),t.modal.classList.add("visible","equipment-popover")}function Xs(i){e.phase==="build"&&(vn(),e.buildTool=e.buildTool===i?null:i,e.selected=null,e.multiSelected=[],e.selectionBox=null,s())}function Qs(){let i=[];for(let[c,h]of Object.entries(e.facilities))if(i.push({id:`facility:${c}`,price:O({type:"facility",ref:h}),x:h.x,y:h.y,w:h.w,h:h.h}),h.entry){let m=F(h.entry.col,h.entry.row);i.push({id:`facilityPort:${c}`,price:O({type:"facility",ref:h}),x:m.x-18,y:m.y-18,w:36,h:36})}for(let c of e.eggFarms){let h=F(c.col,c.row);i.push({id:`eggFarm:${c.id}`,price:O({type:"eggFarm",ref:c}),x:h.x-24,y:h.y-24,w:48,h:48})}for(let c of e.scanners){let h=pe(c);i.push({id:`scanner:${c.id}`,price:O({type:"scanner",ref:c}),x:h.x-50,y:h.y-73,w:100,h:146})}for(let c of e.conveyorTiles){let h=Q(c),m=F(h.col,h.row),k=e.conveyorMeta.get(c)||{};i.push({id:`conveyor:${c}`,price:k.price||Ne(k.kind==="boostConveyor"?"boostConveyor":"conveyor",e),x:m.x-22,y:m.y-22,w:44,h:44})}return i}function Js(i){return A[i]||A.random}function Ec(i){return it(i)}function pr(i){return e.conveyorTiles.has(i)?Be(Q(i)):!1}function yr(i){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return null;for(let c of e.conveyorTiles){if(!pr(c))continue;let h=Q(c),m=F(h.col,h.row),k=m.x-L.w/2,T=m.y+L.y-L.h/2;if(i.x>=k&&i.x<=k+L.w&&i.y>=T&&i.y<=T+L.h)return c}return null}function js(i){let c=yr(i);return c?(hr(c),!0):!1}function hr(i){let c=e.conveyorMeta.get(i);if(!c)return!1;let h=eo(i);if(h.length<2)return!1;$e(e);let m=P.includes(c.branchMode)?c.branchMode:"random",k=["random",...ue.map(T=>T.name).filter(T=>h.includes(T))];return c.branchMode=k[(Math.max(0,k.indexOf(m))+1)%k.length],e.selected=null,e.multiSelected=[],s(),!0}function mr(i){me(e);let c=[],h=i?.type==="facility"?i.baseId||i.id:"";if(i.type==="eggFarm"){let[m,k]=rn(i);c.push(`Price: ${M(O(i))}`);{let T=ge({type:i.type,ref:i});c.push(T?`Sale: blocked (${T})`:`Sale value: ${M(Dt({type:i.type,ref:i},e).amount)}`)}c.push(`Level: ${i.level}/4`),c.push(`Random interval: ${m.toFixed(2)}-${k.toFixed(2)}s`),c.push(`Durability: ${dn(i)}% | Spawn delay x${_n(i).toFixed(2)}`)}else if(i.type==="scanner")c.push(`Price: ${M(O(i))}`),c.push(`Sale value: ${M(Dt({type:i.type,ref:i},e).amount)}`),c.push(`Type: ${i.kind.toUpperCase()} / Standard`),i.kind==="auto"&&c.push(`Role: ${i.role===0?"Male left / Others right":"Poop left / Others right"}`),c.push(`Queue: ${i.queue.length}`),i.kind==="auto"&&c.push(`Cooldown: ${i.cooldown.toFixed(1)}s / ${et(i,e).toFixed(1)}s`),i.kind==="auto"&&c.push(`Durability: ${dn(i)}% | Delay x${Wn(i).toFixed(2)}`),i.kind==="manual"&&c.push("Durability: none | Always normal");else if(i.type==="conveyor"){let m=e.conveyorMeta.get(i.id),k=e.componentLookup?.get(i.id),T=k?e.congestion.get(k):null;c.push(`Price: ${M(O({type:"conveyor",oldKey:i.id,ref:i}))}`),c.push(`Cell: ${i.id}`),c.push(`Type: ${m?.kind==="boostConveyor"?"BOOST BELT":"Normal Belt"} | Speed x${Number(m?.speedMultiplier||1).toFixed(1)}`),c.push(`Congestion: ${T?Math.floor(T.ratio*100):0}%`),c.push(`Durability: ${dn({meta:m})}% | Speed x${Un({meta:m}).toFixed(2)}`),pr(i.id)?(c.push(`Branch mode: ${Js(m?.branchMode||"random")}`),c.push("Use the Branch button below or the on-belt branch badge.")):c.push("Branch mode: needs 3+ conveyor connections."),c.push(`Sale value: ${M(Dt({type:"conveyor",oldKey:i.id,ref:i},e).amount)}`)}else if(i.type==="facility"){c.push(`Price: ${M(O(i))}`);{let m=ge({type:i.type,ref:i});c.push(m?`Sale: blocked (${m})`:`Sale value: ${M(Dt({type:i.type,ref:i},e).amount)}`)}if(c.push(["mixer","truck","trash"].includes(i.id)?`Level: ${i.level} / no cap`:`Level: ${i.level}`),h==="truck"&&c.push("Durability: none | Always normal"),["mixer","trash"].includes(h)&&c.push(`Durability: ${dn(i)}% | Extra delay ${Vo(e,i).toFixed(2)}s`),h==="mixer"&&(c.push(`Income: ${M(qe(e))} per chick | upgrade x${ct(e,"mixer").toFixed(3)}`),c.push(`Poop fine: -${M(ln(e))}`)),h==="truck"&&(c.push(`Income: ${M(De(e))} per target cargo | upgrade x${ct(e,"truck").toFixed(3)}`),c.push(`Poop shipment fine: -${M(an(e))}`)),h==="trash"){let m=At(e),k=ut(m);c.push(`Bonus cards: ${m}/${Kt()}`),c.push(`Poop income bonus: ${M(k)} per processed poop.`),c.push("With enough upgrades, poop can out-earn male/female routes.")}i.entry&&c.push(`Receiver: edge cell ${i.entry.col},${i.entry.row} (${i.side})`)}return c}function Zs(i){if(!i||e.phase!=="build")return"";let c=Dn(e).find(h=>h.type===i.type&&h.id===i.id);return c?c.message||"Not connected to conveyor route":""}function el(i){return i?i.type==="conveyor"&&e.conveyorMeta.get(i.id)?.kind==="boostConveyor"?"Moves chicks twice as fast. Wears down like a normal belt.":i.type==="conveyor"?"A stubborn belt tile. It only cares about the next cell.":i.type==="eggFarm"?"A tiny gatehouse producing questionable eggs on schedule.":i.type==="scanner"&&i.kind==="auto"?"Slower than hands without upgrades.":i.type==="scanner"?"A manual checkpoint. The operator is the algorithm.":i.type==="facility"&&(i.baseId||i.id)==="mixer"?"Male chicks become revenue here. Do not feed it poop.":i.type==="facility"&&(i.baseId||i.id)==="trash"?"Poop goes in. Sometimes coins come out, for reasons best left unaudited.":i.type==="facility"&&(i.baseId||i.id)==="truck"?"The shipping endpoint. Correct cargo pays; wrong cargo complains.":"Factory equipment.":""}return{buildAtCell:u,buildAtPoint:p,eraseAtPoint:D,equipmentAtPoint:K,startSelectionBox:ee.startSelectionBox,updateSelectionBox:ee.updateSelectionBox,finishSelectionBox:ee.finishSelectionBox,startGroupDrag:ee.startGroupDrag,updateGroupDrag:ee.updateGroupDrag,finishGroupDrag:ee.finishGroupDrag,selectedObject:x,selectedTitle:g,equipmentPrice:O,selectedUpgradeCost:Xe,selectedInfoLines:mr,flavorText:el,disconnectedWarningFor:Zs,gridExpansionCost:V,buyGridExpansion:I,expansionOfferAtPoint:ye,beginConveyorDrag:oo,continueConveyorDrag:jt,endConveyorDrag:vn,cycleSingleConveyorDirection:yn,branchSwitcherAtPoint:yr,cycleBranchModeAtPoint:js,cycleBranchModeForKey:hr,removeSelected:ur,switchScannerRole:Ys,showManualScannerMenu:en,showAutoScannerMenu:ro,showSelectedMenu:zs,setBuildTool:Xs,fail:ce,isEquipmentCell:R,equipmentHitBoxes:Qs,routeFromFarmToScanner:Rt}}function Ts({game:e,ui:t,build:n,startGame:o,beginCardDraft:r,activeQueuedChick:s}){function l(R){return String(R).replace(/[&<>"']/g,G=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[G])}function d(){return Math.round(Yn(e))}function v(){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return!1;let R=!1;for(let G of fo)if(R=!0,e.cash>=Ne(G,e))return!1;return R}function C(){P(),A(),ne(),V(),L()}function P(){for(let[G,x]of Object.entries(t.buttons))x?.classList?.contains("tool-button")&&x.classList.toggle("active",e.buildTool===G);for(let G of fo){let x=t.buttons[G];if(!x)continue;let g=Ne(G,e),O=x.querySelector("span");O&&(O.textContent=G==="conveyor"||G==="boostConveyor"?`${M(g)} / tile`:M(g));let X=G==="manualScanner"&&e.scanners.filter(de=>de.kind==="manual").length>=8,oe=e.cashRt(e,X)?.scannerId).length,G=sn(e),x=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),g=Math.max(1,Number(e.turn)||1),O=Fn(e,g,x);t.turnSummary.innerHTML=[`Seed: ${l(e.runSeed||"none")} | Grid box: ${e.gridRows||10}x${e.gridCols||20} | Owned: ${e.gridOwnedCells||e.ownedCells?.size||(e.gridRows||10)*(e.gridCols||20)} cells | Blocked: ${e.blockedCells?.size||0} cells`,`Truck target: ${Je(e).toUpperCase()} | Male fine: -${M(Fo(e))}`,`Poop fine: Mixer -${M(ln(e))} / Shipment -${M(an(e))}`,`Fairies tribute on Next Day: -${M(O.amount)} | base ${M(O.base)} + profit share ${M(O.profitTribute)} | basis net ${M(x)} | exemption ${M(O.profitExemption)}${O.reduction?` | reduction -${M(O.reduction)}`:""}`,`Maintenance: worst ${Qo(e).worst.percent}% dirty (${Qo(e).worst.label}) | Repairman: ${e.repairman?.hiredForNextDay?"hired next day":e.repairman?.active?"working":"none"}`,`Manual combo: ${e.manualCombo?.count||0} | Card draft: ${e.cardDraft?.pending?Math.max(1,e.cardDraft.picksRemaining||1)+" pick(s) left":"ready after each day"} | Belt: ${d()}px/s | Farms with scanner route: ${R}/${e.eggFarms.length}`,e.cardEffects?.usedMachineActive?'Procurement: USED MACHINE MODE / no refunds / 60% durability':"",G.length?`Blocked: ${G[0]}`:`${re.status.allPortsConnected}`].join("
")}function ne(){if(!t.eventPanel)return;let R=e.eventOffer;if(e.phase!=="build"){t.eventPanel.innerHTML=re.status.eventPanelRunning;return}if(!R){t.eventPanel.className="event-card empty",e.turn+1Event lock active.No irregular events during Days 1-7. First possible forced event: Day ${wt}.`:t.eventPanel.innerHTML="No event.Random forced events can appear later.";return}t.eventPanel.className="event-card accepted",t.eventPanel.innerHTML=` + ${x?`

${x}

`:""} + `,t.modalActions.innerHTML="",t.modalActions.appendChild(qe("Set Left Key",()=>fr(i,"left"),"facility-action warn")),t.modalActions.appendChild(qe("Set Right Key",()=>fr(i,"right"),"facility-action warn")),t.modalActions.appendChild(qe("Close",Zt,"facility-action")),ao(i),t.modal.classList.add("visible","equipment-popover")}function Ys(i){let c=[{side:"left",binding:i.keys?.left},{side:"right",binding:i.keys?.right}];if(c[0].binding&&c[1].binding&&(c[0].binding.code===c[1].binding.code||c[0].binding.key===c[1].binding.key))return"Left and right keys conflict.";for(let h of c)if(h.binding)for(let m of e.scanners.filter(x=>x.kind==="manual"&&x.id!==i.id)){if(m.keys?.left&&(m.keys.left.code===h.binding.code||m.keys.left.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} left.`;if(m.keys?.right&&(m.keys.right.code===h.binding.code||m.keys.right.key===h.binding.key))return`Key conflicts with Manual Scanner #${m.id} right.`}return""}function fr(i,c){t.modalBody.innerHTML=`

Press a key for ${c.toUpperCase()} route.

Esc cancels.

`,t.modalActions.innerHTML="";let h=m=>{if(m.preventDefault(),m.stopPropagation(),window.removeEventListener("keydown",h,!0),m.key==="Escape")return en(i);let x=Hs(m),T=qs(i,c,x);Fe(e),i.keys=i.keys||{left:null,right:null},i.keys[c]=x,s(),en(i,T?`${x.label} assigned, but another scanner already uses it.`:`${c.toUpperCase()} set to ${x.label}.`)};window.addEventListener("keydown",h,!0)}function Vs(){let i=k();if(!(!i||i.type!=="scanner"))return i.kind==="auto"?lo(i):en(i)}function zs(i){if(!i)return{x:80,y:80};if(i.type==="conveyor"){let c=Q(i.id);return F(c.col,c.row)}return i.type==="eggFarm"?F(i.col,i.row):i.type==="scanner"?pe(i):i.type==="facility"?{x:i.x+i.w/2,y:i.y+10}:{x:80,y:80}}function ao(i){let c=n.getBoundingClientRect(),h=zs(i),m=e.view?.scale||1,x=c.left+(h.x*m+(e.view?.x||0))/n.width*c.width+18,T=c.top+(h.y*m+(e.view?.y||0))/n.height*c.height-12,j=Math.max(12,window.innerWidth-274),ie=Math.max(12,window.innerHeight-220);t.modal.style.setProperty("--popover-x",`${Math.max(12,Math.min(j,x))}px`),t.modal.style.setProperty("--popover-y",`${Math.max(12,Math.min(ie,T))}px`)}function Xs(){let i=k();if(!i)return;let c=mr(i);t.modalTitle.textContent=g(i),t.modalBody.innerHTML=` +
${c.map(x=>`

${x}

`).join("")}
+ ${["mixer","truck"].includes(i.baseId||i.id)?'

Income/Fine = ceil(base x 1.10^upgrades)

':""}`,t.modalActions.innerHTML="",i.type==="scanner"&&i.kind==="auto"&&t.modalActions.appendChild(qe("Auto Menu",()=>lo(i),"facility-action warn")),i.type==="scanner"&&i.kind==="manual"&&t.modalActions.appendChild(qe("Set Keys",()=>en(i),"facility-action warn"));let h=i.type==="conveyor"?{type:"conveyor",oldKey:i.id,ref:i}:{type:i.type,ref:i},m=Te(h);if(m){let x=qe(m,()=>{},"facility-action danger disabled");x.disabled=!0,t.modalActions.appendChild(x)}else{let x=$t(h,e),T=x.sameBuild?`Remove / Refund ${M(x.amount)}`:`Sell ${M(x.amount)}`;t.modalActions.appendChild(qe(T,()=>{ur(),Zt()},"facility-action danger"))}ao(i),t.modal.classList.add("visible","equipment-popover")}function Qs(i){e.phase==="build"&&(wn(),e.buildTool=e.buildTool===i?null:i,e.selected=null,e.multiSelected=[],e.selectionBox=null,s())}function Js(){let i=[];for(let[c,h]of Object.entries(e.facilities))if(i.push({id:`facility:${c}`,price:O({type:"facility",ref:h}),x:h.x,y:h.y,w:h.w,h:h.h}),h.entry){let m=F(h.entry.col,h.entry.row);i.push({id:`facilityPort:${c}`,price:O({type:"facility",ref:h}),x:m.x-18,y:m.y-18,w:36,h:36})}for(let c of e.eggFarms){let h=F(c.col,c.row);i.push({id:`eggFarm:${c.id}`,price:O({type:"eggFarm",ref:c}),x:h.x-24,y:h.y-24,w:48,h:48})}for(let c of e.scanners){let h=pe(c);i.push({id:`scanner:${c.id}`,price:O({type:"scanner",ref:c}),x:h.x-50,y:h.y-73,w:100,h:146})}for(let c of e.conveyorTiles){let h=Q(c),m=F(h.col,h.row),x=e.conveyorMeta.get(c)||{};i.push({id:`conveyor:${c}`,price:x.price||_e(x.kind==="boostConveyor"?"boostConveyor":"conveyor",e),x:m.x-22,y:m.y-22,w:44,h:44})}return i}function js(i){return R[i]||R.random}function Rc(i){return st(i)}function pr(i){return e.conveyorTiles.has(i)?Le(Q(i)):!1}function yr(i){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return null;for(let c of e.conveyorTiles){if(!pr(c))continue;let h=Q(c),m=F(h.col,h.row),x=m.x-L.w/2,T=m.y+L.y-L.h/2;if(i.x>=x&&i.x<=x+L.w&&i.y>=T&&i.y<=T+L.h)return c}return null}function Zs(i){let c=yr(i);return c?(hr(c),!0):!1}function hr(i){let c=e.conveyorMeta.get(i);if(!c)return!1;let h=oo(i);if(h.length<2)return!1;Fe(e);let m=P.includes(c.branchMode)?c.branchMode:"random",x=["random",...ue.map(T=>T.name).filter(T=>h.includes(T))];return c.branchMode=x[(Math.max(0,x.indexOf(m))+1)%x.length],e.selected=null,e.multiSelected=[],s(),!0}function mr(i){me(e);let c=[],h=i?.type==="facility"?i.baseId||i.id:"";if(i.type==="eggFarm"){let[m,x]=rn(i);c.push(`Price: ${M(O(i))}`);{let T=Te({type:i.type,ref:i});c.push(T?`Sale: blocked (${T})`:`Sale value: ${M($t({type:i.type,ref:i},e).amount)}`)}c.push(`Level: ${i.level}/4`),c.push(`Random interval: ${m.toFixed(2)}-${x.toFixed(2)}s`),c.push(`Durability: ${dn(i)}% | Spawn delay x${Hn(i).toFixed(2)}`)}else if(i.type==="scanner")c.push(`Price: ${M(O(i))}`),c.push(`Sale value: ${M($t({type:i.type,ref:i},e).amount)}`),c.push(`Type: ${i.kind.toUpperCase()} / Standard`),i.kind==="auto"&&c.push(`Role: ${i.role===0?"Male left / Others right":"Poop left / Others right"}`),c.push(`Queue: ${i.queue.length}`),i.kind==="auto"&&c.push(`Cooldown: ${i.cooldown.toFixed(1)}s / ${tt(i,e).toFixed(1)}s`),i.kind==="auto"&&c.push(`Durability: ${dn(i)}% | Delay x${Kn(i).toFixed(2)}`),i.kind==="manual"&&c.push("Durability: none | Always normal");else if(i.type==="conveyor"){let m=e.conveyorMeta.get(i.id),x=e.componentLookup?.get(i.id),T=x?e.congestion.get(x):null;c.push(`Price: ${M(O({type:"conveyor",oldKey:i.id,ref:i}))}`),c.push(`Cell: ${i.id}`),c.push(`Type: ${m?.kind==="boostConveyor"?"BOOST BELT":"Normal Belt"} | Speed x${Number(m?.speedMultiplier||1).toFixed(1)}`),c.push(`Congestion: ${T?Math.floor(T.ratio*100):0}%`),c.push(`Durability: ${dn({meta:m})}% | Speed x${Wn({meta:m}).toFixed(2)}`),pr(i.id)?(c.push(`Branch mode: ${js(m?.branchMode||"random")}`),c.push("Use the Branch button below or the on-belt branch badge.")):c.push("Branch mode: needs 3+ conveyor connections."),c.push(`Sale value: ${M($t({type:"conveyor",oldKey:i.id,ref:i},e).amount)}`)}else if(i.type==="facility"){c.push(`Price: ${M(O(i))}`);{let m=Te({type:i.type,ref:i});c.push(m?`Sale: blocked (${m})`:`Sale value: ${M($t({type:i.type,ref:i},e).amount)}`)}if(c.push(["mixer","truck","trash"].includes(i.id)?`Level: ${i.level} / no cap`:`Level: ${i.level}`),h==="truck"&&c.push("Durability: none | Always normal"),["mixer","trash"].includes(h)&&c.push(`Durability: ${dn(i)}% | Extra delay ${Xo(e,i).toFixed(2)}s`),h==="mixer"&&(c.push(`Income: ${M(Ye(e))} per chick | upgrade x${ut(e,"mixer").toFixed(3)}`),c.push(`Poop fine: -${M(ln(e))}`)),h==="truck"&&(c.push(`Income: ${M($e(e))} per target cargo | upgrade x${ut(e,"truck").toFixed(3)}`),c.push(`Poop shipment fine: -${M(an(e))}`)),h==="trash"){let m=Dt(e),x=dt(m);c.push(`Bonus cards: ${m}/${Kt()}`),c.push(`Poop income bonus: ${M(x)} per processed poop.`),c.push("With enough upgrades, poop can out-earn male/female routes.")}i.entry&&c.push(`Receiver: edge cell ${i.entry.col},${i.entry.row} (${i.side})`)}return c}function el(i){if(!i||e.phase!=="build")return"";let c=In(e).find(h=>h.type===i.type&&h.id===i.id);return c?c.message||"Not connected to conveyor route":""}function tl(i){return i?i.type==="conveyor"&&e.conveyorMeta.get(i.id)?.kind==="boostConveyor"?"Moves chicks twice as fast. Wears down like a normal belt.":i.type==="conveyor"?"A stubborn belt tile. It only cares about the next cell.":i.type==="eggFarm"?"A tiny gatehouse producing questionable eggs on schedule.":i.type==="scanner"&&i.kind==="auto"?"Slower than hands without upgrades.":i.type==="scanner"?"A manual checkpoint. The operator is the algorithm.":i.type==="facility"&&(i.baseId||i.id)==="mixer"?"Male chicks become revenue here. Do not feed it poop.":i.type==="facility"&&(i.baseId||i.id)==="trash"?"Poop goes in. Sometimes coins come out, for reasons best left unaudited.":i.type==="facility"&&(i.baseId||i.id)==="truck"?"The shipping endpoint. Correct cargo pays; wrong cargo complains.":"Factory equipment.":""}return{buildAtCell:u,buildAtPoint:f,eraseAtPoint:D,equipmentAtPoint:K,startSelectionBox:ee.startSelectionBox,updateSelectionBox:ee.updateSelectionBox,finishSelectionBox:ee.finishSelectionBox,startGroupDrag:ee.startGroupDrag,updateGroupDrag:ee.updateGroupDrag,finishGroupDrag:ee.finishGroupDrag,selectedObject:k,selectedTitle:g,equipmentPrice:O,selectedUpgradeCost:Qe,selectedInfoLines:mr,flavorText:tl,disconnectedWarningFor:el,gridExpansionCost:V,buyGridExpansion:$,expansionOfferAtPoint:ye,beginConveyorDrag:so,continueConveyorDrag:jt,endConveyorDrag:wn,cycleSingleConveyorDirection:hn,branchSwitcherAtPoint:yr,cycleBranchModeAtPoint:Zs,cycleBranchModeForKey:hr,removeSelected:ur,switchScannerRole:Vs,showManualScannerMenu:en,showAutoScannerMenu:lo,showSelectedMenu:Xs,setBuildTool:Qs,fail:ce,isEquipmentCell:A,equipmentHitBoxes:Js,routeFromFarmToScanner:At}}function Es({game:e,ui:t,build:n,startGame:o,beginCardDraft:r,activeQueuedChick:s}){function l(A){return String(A).replace(/[&<>"']/g,_=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[_])}function d(){return Math.round(zn(e))}function v(){if(e.phase!=="build"||e.cardDraft?.pending||e.cardTargetPick?.pending)return!1;let A=!1;for(let _ of ho)if(A=!0,e.cash>=_e(_,e))return!1;return A}function C(){P(),R(),te(),V(),L()}function P(){for(let[_,k]of Object.entries(t.buttons))k?.classList?.contains("tool-button")&&k.classList.toggle("active",e.buildTool===_);for(let _ of ho){let k=t.buttons[_];if(!k)continue;let g=_e(_,e),O=k.querySelector("span");O&&(O.textContent=_==="conveyor"||_==="boostConveyor"?`${M(g)} / tile`:M(g));let X=_==="manualScanner"&&e.scanners.filter(de=>de.kind==="manual").length>=8,oe=e.cashAt(e,X)?.scannerId).length,_=sn(e),k=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),g=Math.max(1,Number(e.turn)||1),O=Ln(e,g,k);t.turnSummary.innerHTML=[`Seed: ${l(e.runSeed||"none")} | Grid box: ${e.gridRows||10}x${e.gridCols||20} | Owned: ${e.gridOwnedCells||e.ownedCells?.size||(e.gridRows||10)*(e.gridCols||20)} cells | Blocked: ${e.blockedCells?.size||0} cells`,`Truck target: ${je(e).toUpperCase()} | Male fine: -${M(Lo(e))}`,`Poop fine: Mixer -${M(ln(e))} / Shipment -${M(an(e))}`,`Fairies tribute on Next Day: -${M(O.amount)} | base ${M(O.base)} + profit share ${M(O.profitTribute)} | basis net ${M(k)} | exemption ${M(O.profitExemption)}${O.reduction?` | reduction -${M(O.reduction)}`:""}`,`Maintenance: worst ${jo(e).worst.percent}% dirty (${jo(e).worst.label}) | Repairman: ${e.repairman?.hiredForNextDay?"hired next day":e.repairman?.active?"working":"none"}`,`Manual combo: ${e.manualCombo?.count||0} | Card draft: ${e.cardDraft?.pending?Math.max(1,e.cardDraft.picksRemaining||1)+" pick(s) left":"ready after each day"} | Belt: ${d()}px/s | Farms with scanner route: ${A}/${e.eggFarms.length}`,e.cardEffects?.usedMachineActive?'Procurement: USED MACHINE MODE / no refunds / 60% durability':"",_.length?`Blocked: ${_[0]}`:`${re.status.allPortsConnected}`].join("
")}function te(){if(!t.eventPanel)return;let A=e.eventOffer;if(e.phase!=="build"){t.eventPanel.innerHTML=re.status.eventPanelRunning;return}if(!A){t.eventPanel.className="event-card empty",e.turn+1Event lock active.No irregular events during Days 1-7. First possible forced event: Day ${St}.`:t.eventPanel.innerHTML="No event.Random forced events can appear later.";return}t.eventPanel.className="event-card accepted",t.eventPanel.innerHTML=`
FORCED NEXT DAY
-

${R.title}

+

${A.title}

- Effect: ${R.route} - ${R.targetAmount?`Target: ${R.targetAmount}`:"Target: none"} - ${R.reward?`Reward: ${M(R.reward)}`:"Reward: none"} - Time ${R.daySeconds||60}s / Output x${Number(R.productionMultiplier||1).toFixed(2)} / Poop +${Math.round((R.poopRateAdd||0)*100)}pt -
`}function z(){P(),t.shell.classList.toggle("phase-running",e.phase==="running"),t.shell.classList.toggle("phase-build",e.phase==="build"),t.shell.classList.toggle("phase-gameover",e.phase==="gameover"),t.shell.classList.toggle("phase-title",e.phase==="title"),t.shell.classList.toggle("phase-loanDecision",e.phase==="loanDecision"),t.money.textContent=M(e.cash),t.money.classList.toggle("cash-negative",e.cash<0),t.money.classList.toggle("cash-positive",e.cash>tn),t.turn.textContent=e.turn,t.timeLeft.textContent=e.phase==="running"&&e.timeLeft<=0&&e.shutdownTimeLeft>0?`+${e.shutdownTimeLeft.toFixed(1)}s`:`${Math.max(0,e.timeLeft).toFixed(1)}s`,t.timeLeft.closest?.(".hud-card")?.classList.toggle("time-critical",e.phase==="running"&&(e.timeLeft<=10||e.timeLeft<=0&&e.shutdownTimeLeft>0)),t.phase.textContent=ye(),t.comboCount&&(t.comboCount.textContent=e.manualCombo?.count||0),se(),t.turnProfit.textContent=M(e.stats.profit),t.turnProfit.classList.toggle("cash-negative",e.stats.profit<0),t.turnProfit.classList.toggle("cash-positive",e.stats.profit>0),t.mixerCount.textContent=e.stats.mixerCount,t.truckFemaleCount.textContent=e.stats.truckFemale,t.truckMaleCount.textContent=e.stats.truckMale,t.poopCount.textContent=e.stats.poopSpawned,t.buttons.s1Left.disabled=e.phase!=="running"||!s(0),t.buttons.s1Right.disabled=e.phase!=="running"||!s(0),t.buttons.s2Left.disabled=e.phase!=="running"||!s(1),t.buttons.s2Right.disabled=e.phase!=="running"||!s(1);let R=e.scanners.find(O=>O.kind==="manual"&&O.slot===0),G=e.scanners.find(O=>O.kind==="manual"&&O.slot===1);R&&(t.buttons.s1Left.textContent=`S1 ${R.keys?.left?.label||"A"} -> Mixer`,t.buttons.s1Right.textContent=`S1 ${R.keys?.right?.label||"D"} -> S2`),G&&(t.buttons.s2Left.textContent=`S2 ${G.keys?.left?.label||"Left"} -> Waste`,t.buttons.s2Right.textContent=`S2 ${G.keys?.right?.label||"Right"} -> Truck`);let x=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),g=Fn(e,Math.max(1,Number(e.turn)||1),x).amount;t.buttons.nextTurn.textContent=e.phase==="build"&&g>0?`Next Day - Fairies ${M(g)}`:re.actions.nextDay,t.buttons.nextTurn.disabled=e.phase!=="build"||!!e.cardDraft?.pending||!!e.cardTargetPick?.pending||!ii(e)}function se(){if(!t.eventBrief||!t.targetBrief||!t.speedBrief)return;let R=Je(e).toUpperCase();t.targetBrief.textContent=`TRUCK TARGET: ${R}`,t.speedBrief.textContent=`BELT: ${d()} px/s | COMBO: ${e.manualCombo?.count||0}`,t.speedBrief.title=`Conveyor speed does not increase by day. Degraded belts reduce speed. Cap: ${Gt}px/s.`;let G=e.eventActive,x=e.eventOffer;G?(t.eventBrief.textContent=`ACTIVE EVENT: ${G.title} | ${G.route}`,t.eventBrief.className="event-brief active"):e.phase==="build"&&x?(t.eventBrief.textContent=`NEXT DAY EVENT: ${x.title} | ${x.route}${x.targetAmount?` | Target ${x.targetAmount}`:""}${x.reward?` | Reward ${M(x.reward)}`:""}`,t.eventBrief.className="event-brief next"):e.phase==="build"&&e.turn+1
\u2642Male->MixerS1: A
\u2640Female->TruckS1: D, then S2: right
\u{1F4A9}Poop->ShredderS1: D, then S2: left

Build phase: connect at least one EGG through a scanner to Mixer, Shredder, or Truck before Next Day. One day is one run.

',t.modalActions.innerHTML="",t.modalActions.appendChild(le(re.actions.startGame,o,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function I(R){let G=X=>`${X>0?"+":""}${M(X)}`,x=X=>`${X>0?"-":""}${M(X)}`,g=R.profit>=0?"cash-positive":"cash-negative",O=(R.mixerPoopFine||0)+(R.truckPoopFine||0)+(R.maleTruckFine||0)+(R.explosionDamage||0)+(R.cardRerollCost||0);t.modalTitle.textContent=`Day ${R.turn} Settlement`,t.modalBody.innerHTML=` -
Net result${M(R.profit)}
+ Effect: ${A.route} + ${A.targetAmount?`Target: ${A.targetAmount}`:"Target: none"} + ${A.reward?`Reward: ${M(A.reward)}`:"Reward: none"} + Time ${A.daySeconds||60}s / Output x${Number(A.productionMultiplier||1).toFixed(2)} / Poop +${Math.round((A.poopRateAdd||0)*100)}pt + `}function z(){P(),t.shell.classList.toggle("phase-running",e.phase==="running"),t.shell.classList.toggle("phase-build",e.phase==="build"),t.shell.classList.toggle("phase-gameover",e.phase==="gameover"),t.shell.classList.toggle("phase-title",e.phase==="title"),t.shell.classList.toggle("phase-loanDecision",e.phase==="loanDecision"),t.money.textContent=M(e.cash),t.money.classList.toggle("cash-negative",e.cash<0),t.money.classList.toggle("cash-positive",e.cash>tn),t.turn.textContent=e.turn,t.timeLeft.textContent=e.phase==="running"&&e.timeLeft<=0&&e.shutdownTimeLeft>0?`+${e.shutdownTimeLeft.toFixed(1)}s`:`${Math.max(0,e.timeLeft).toFixed(1)}s`,t.timeLeft.closest?.(".hud-card")?.classList.toggle("time-critical",e.phase==="running"&&(e.timeLeft<=10||e.timeLeft<=0&&e.shutdownTimeLeft>0)),t.phase.textContent=ye(),t.comboCount&&(t.comboCount.textContent=e.manualCombo?.count||0),se(),t.turnProfit.textContent=M(e.stats.profit),t.turnProfit.classList.toggle("cash-negative",e.stats.profit<0),t.turnProfit.classList.toggle("cash-positive",e.stats.profit>0),t.mixerCount.textContent=e.stats.mixerCount,t.truckFemaleCount.textContent=e.stats.truckFemale,t.truckMaleCount.textContent=e.stats.truckMale,t.poopCount.textContent=e.stats.poopSpawned,t.buttons.s1Left.disabled=e.phase!=="running"||!s(0),t.buttons.s1Right.disabled=e.phase!=="running"||!s(0),t.buttons.s2Left.disabled=e.phase!=="running"||!s(1),t.buttons.s2Right.disabled=e.phase!=="running"||!s(1);let A=e.scanners.find(O=>O.kind==="manual"&&O.slot===0),_=e.scanners.find(O=>O.kind==="manual"&&O.slot===1);A&&(t.buttons.s1Left.textContent=`S1 ${A.keys?.left?.label||"A"} -> Mixer`,t.buttons.s1Right.textContent=`S1 ${A.keys?.right?.label||"D"} -> S2`),_&&(t.buttons.s2Left.textContent=`S2 ${_.keys?.left?.label||"Left"} -> Waste`,t.buttons.s2Right.textContent=`S2 ${_.keys?.right?.label||"Right"} -> Truck`);let k=Math.max(0,Math.floor(e.lastResult?.profit??e.stats?.profit??0)),g=Ln(e,Math.max(1,Number(e.turn)||1),k).amount;t.buttons.nextTurn.textContent=e.phase==="build"&&g>0?`Next Day - Fairies ${M(g)}`:re.actions.nextDay,t.buttons.nextTurn.disabled=e.phase!=="build"||!!e.cardDraft?.pending||!!e.cardTargetPick?.pending||!ii(e)}function se(){if(!t.eventBrief||!t.targetBrief||!t.speedBrief)return;let A=je(e).toUpperCase();t.targetBrief.textContent=`TRUCK TARGET: ${A}`,t.speedBrief.textContent=`BELT: ${d()} px/s | COMBO: ${e.manualCombo?.count||0}`,t.speedBrief.title=`Conveyor speed does not increase by day. Degraded belts reduce speed. Cap: ${_t}px/s.`;let _=e.eventActive,k=e.eventOffer;_?(t.eventBrief.textContent=`ACTIVE EVENT: ${_.title} | ${_.route}`,t.eventBrief.className="event-brief active"):e.phase==="build"&&k?(t.eventBrief.textContent=`NEXT DAY EVENT: ${k.title} | ${k.route}${k.targetAmount?` | Target ${k.targetAmount}`:""}${k.reward?` | Reward ${M(k.reward)}`:""}`,t.eventBrief.className="event-brief next"):e.phase==="build"&&e.turn+1
\u2642Male->MixerS1: A
\u2640Female->TruckS1: D, then S2: right
\u{1F4A9}Poop->ShredderS1: D, then S2: left

Build phase: connect at least one EGG through a scanner to Mixer, Shredder, or Truck before Next Day. One day is one run.

',t.modalActions.innerHTML="",t.modalActions.appendChild(le(re.actions.startGame,o,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function $(A){let _=X=>`${X>0?"+":""}${M(X)}`,k=X=>`${X>0?"-":""}${M(X)}`,g=A.profit>=0?"cash-positive":"cash-negative",O=(A.mixerPoopFine||0)+(A.truckPoopFine||0)+(A.maleTruckFine||0)+(A.explosionDamage||0)+(A.cardRerollCost||0);t.modalTitle.textContent=`Day ${A.turn} Settlement`,t.modalBody.innerHTML=` +
Net result${M(A.profit)}
-
Chick shipment income${G(R.chickShipmentIncome||0)}
-
Poop shipment income${G(R.poopShipmentIncome||0)}
-
Mixer income${G(R.mixerRevenue||0)}
-
Composter income${G(R.composterIncome||0)}
-
DUD refund income${G(R.dudRefundIncome||0)}
-
Manual combo bonus${G(R.manualComboBonus||0)}
-
Chemical subsidy${G(R.chemicalWeaponSubsidy||0)}
-
Event bonus${G(R.eventBonus||0)}
-
Penalties${x(O)}
-
Fairies fee${x(R.fairiesTribute?.amount||R.fairiesTribute||0)}
-
Repair worker wages${x(R.repairWorkerWages||0)}
+
Chick shipment income${_(A.chickShipmentIncome||0)}
+
Poop shipment income${_(A.poopShipmentIncome||0)}
+
Mixer income${_(A.mixerRevenue||0)}
+
Composter income${_(A.composterIncome||0)}
+
DUD refund income${_(A.dudRefundIncome||0)}
+
Manual combo bonus${_(A.manualComboBonus||0)}
+
Chemical subsidy${_(A.chemicalWeaponSubsidy||0)}
+
Event bonus${_(A.eventBonus||0)}
+
Penalties${k(O)}
+
Fairies fee${k(A.fairiesTribute?.amount||A.fairiesTribute||0)}
+
Repair worker wages${k(A.repairWorkerWages||0)}
-

Income ${M(R.revenue)} - losses ${M(R.penalty)} = ${M(R.profit)}

`,t.modalActions.innerHTML="",t.modalActions.appendChild(le("Choose Upgrade Card",r||we,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function W(R,G){let x=Math.max(0,e.cardEffects?.rescueLoanCharges||0);t.modalTitle.textContent="Emergency Loan Available",t.modalBody.innerHTML=` +

Income ${M(A.revenue)} - losses ${M(A.penalty)} = ${M(A.profit)}

`,t.modalActions.innerHTML="",t.modalActions.appendChild(le("Choose Upgrade Card",r||Se,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function U(A,_){let k=Math.max(0,e.cardEffects?.rescueLoanCharges||0);t.modalTitle.textContent="Emergency Loan Available",t.modalBody.innerHTML=`

End-of-day cash is below ${M(0)}.

Current money${M(e.cash)}
Emergency Loan+${M(500)}
-
Cards remaining${x}
+
Cards remaining${k}
-

Use one Emergency Loan to gain ${M(500)} immediately. If cash is still negative, another decision will be shown if another card remains.

`,t.modalActions.innerHTML="",t.modalActions.appendChild(le("Accept Game Over",G,"facility-action danger")),t.modalActions.appendChild(le("Use Emergency Loan",R,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function N(){let R=e.totals.processed,G=R?Math.round(e.totals.correct/R*100):0,x=Ai(e);t.modalTitle.textContent=re.phases.gameover,t.modalBody.innerHTML=`

Your cash went negative.

-
Final Score${x.score}
Survival${e.totals.turnsCompleted} days
Final Cash${M(e.cash)}
Accuracy${G}%
+

Use one Emergency Loan to gain ${M(500)} immediately. If cash is still negative, another decision will be shown if another card remains.

`,t.modalActions.innerHTML="",t.modalActions.appendChild(le("Accept Game Over",_,"facility-action danger")),t.modalActions.appendChild(le("Use Emergency Loan",A,"primary-button")),t.modal.classList.remove("equipment-popover","gameover-modal"),t.modal.classList.add("visible")}function N(){let A=e.totals.processed,_=A?Math.round(e.totals.correct/A*100):0,k=Ai(e);t.modalTitle.textContent=re.phases.gameover,t.modalBody.innerHTML=`

Your cash went negative.

+
Final Score${k.score}
Survival${e.totals.turnsCompleted} days
Final Cash${M(e.cash)}
Accuracy${_}%
Score breakdown -
Formula
Base = Cash + Total revenue + Factory value \xD70.5 + Event bonus \xD70.5 = ${M(x.base)}
Daily earned = ceil(Base \xF7 Days) = ${M(x.dailyEarned)}
Score = max(0, floor(Base + Daily earned + Correct bonus - Total outflow - Day penalty)) = ${x.score}
-
Factory Value${M(x.factoryValue)}
Total Revenue${M(e.totals.revenue)}
Daily Earned${M(x.dailyEarned)} / day
Total Outflow${M(e.totals.penalty)}
Fairies Tribute${M(e.totals.fairiesTribute||0)}
Correct Sorts${e.totals.correct}
Auto Sorted${e.totals.autoSorted}
Poop Control${e.totals.poopTrash} trashed / ${e.totals.poopTruck} shipped / ${e.totals.poopMixer} mixer
Explosion Penalty${M(e.totals.explosionDamage)}
Event Bonus${M(e.totals.eventBonus)}
Day Penalty-${x.dayPenalty}
Events${e.totals.eventSuccess} success / ${e.totals.eventFailed} failed
-
`,t.modalActions.innerHTML="",t.modalActions.appendChild(le(re.actions.restart||"Restart",o,"primary-button restart-button")),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible","gameover-modal")}function le(R,G,x="primary-button"){let g=document.createElement("button");return g.type="button",g.className=x,g.textContent=R,g.addEventListener("click",G),g}function we(){t.modal.classList.remove("visible","equipment-popover","gameover-modal"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function he(){}return{updatePanels:C,updateUI:z,showTitle:Z,showTurnResult:I,showEmergencyLoanDecision:W,showGameOver:N,hideModal:we,checkGameOver:he}}function cr(e){e.totals.processed+=1}function zt(e){e.stats.correct+=1,e.totals.correct+=1}function yt(e){e.stats.mistakes+=1,e.totals.mistakes+=1}function Es(e){e.stats.autoSorted+=1,e.totals.autoSorted+=1}function Ps(e){e.stats.poopSpawned+=1}function Rs(e){e.stats.mixerCount+=1,cr(e)}function As(e){e.stats.trashCount+=1,cr(e)}function Ds(e,t){t==="female"?e.stats.truckFemale+=1:t==="male"&&(e.stats.truckMale+=1),cr(e)}function Qn(e,t){let n=t==="truck"?"poopTruck":t==="trash"?"poopTrash":t==="mixer"?"poopMixer":null;n&&(e.stats[n]+=1,e.totals[n]+=1)}function Is({game:e,currentConveyorSpeed:t,onGameOverCheck:n}){function o(u){return Mt(u)*_n(u)*is(e)/fi(e)}function r(u){let p=F(u.col,u.row),b=1+ss(e,u),S=l(u,b);if(!S.length)return s(u,p),!0;let w=0,E=0;for(let D of S){let K=F(D.col,D.row),ee=d(K);if(ee){ee.stoppedTimer=.85,E+=1;continue}let Xe=Cs(e,{stage:"belt",scannerId:null,route:[K]});Xe.sex==="poop"&&Ps(e),e.chicks.push(Xe),_i(e,u),w+=1}return w>0?(Ii(e,p.x,p.y),w>1&&_(e,p.x,p.y-28,`x${w}`,f.green),!0):E===0}function s(u,p){(u.noRouteNoticeCooldown||0)<=0&&(_(e,p.x,p.y-24,"NO BELT: PAUSED",f.warn),u.noRouteNoticeCooldown=2.5)}function l(u,p){let S=ue.map(w=>({col:u.col+w.dc,row:u.row+w.dr})).filter(w=>Te(w.col,w.row)&&e.conveyorTiles.has($(w.col,w.row))).map(w=>({p:w,blocked:L(null,F(w.col,w.row))?1:0,roll:Math.random()}));return S.sort((w,E)=>w.blocked-E.blocked||w.roll-E.roll),S.slice(0,Math.max(1,p||1)).map(w=>w.p)}function d(u){return e.chicks.find(p=>p.stage!=="flying"&&Math.hypot(p.x-u.x,p.y-u.y)0;if(e.timeLeft=Math.max(0,e.timeLeft-u),S&&e.timeLeft<=0&&p(),e.timeLeft<=0){e.shutdownTimeLeft>0&&(e.shutdownTimeLeft=Math.max(0,e.shutdownTimeLeft-u));for(let w of e.eggFarms)w.shutterProgress=Math.min(1,(w.shutterProgress||0)+u*2.8)}if(S&&e.timeLeft>0){for(let w of e.eggFarms)if(w.noRouteNoticeCooldown>0&&(w.noRouteNoticeCooldown=Math.max(0,w.noRouteNoticeCooldown-u)),w.nextSpawn-=u,w.nextSpawn<=0){let E=r(w);w.nextSpawn=E?o(w):.15,w.lastInterval=w.nextSpawn}}for(let w=e.chicks.length-1;w>=0;w-=1){let E=e.chicks[w];E.bob+=u*7,E.stoppedTimer>0&&(E.stoppedTimer=Math.max(0,E.stoppedTimer-u)),E.stage!=="queued"&&P(E,w,u)}J(u),Jt(),oo(),e.timeLeft<=0&&(e.chicks.length===0?b():e.shutdownTimeLeft<=0&&C())}function C(){if(e.cleanupBlown)return;e.cleanupBlown=!0,e.cleanupTimer=1;let u=[...e.chicks];for(let p of u)No(e,p.sex,p.x,p.y,-Math.PI/2,!0);e.chicks=[];for(let p of e.scanners)p.queue=[];if(Jt(),u.length){let p=u.reduce((S,w)=>S+w.x,0)/u.length,b=u.reduce((S,w)=>S+w.y,0)/u.length;Ye(e,p,b,f.warn,58),_(e,p,b-24,"CLEANUP",f.warn)}}function P(u,p,b){if(A(u)){u.stoppedTimer=.35;return}if(de(u,b),!(u.route&&u.targetIndex=u.route.length)return!1;let p=u.route[u.targetIndex];return L(u,p)}function L(u,p){if(!p)return!1;for(let b of e.chicks)if(!(u&&b.id===u.id)&&b.stage!=="flying"&&Math.hypot(b.x-p.x,b.y-p.y)1)&&u.push({x:p.x,y:p.y})}function ne(u){let p=e.conveyorMeta?.get?.(u)||{},b=[];Array.isArray(p.outDirs)&&b.push(...p.outDirs),p.dir&&b.push(p.dir);let S=[...new Set(b)].filter(ee=>ue.some(Xe=>Xe.name===ee)),w=Q(u),E=ue.filter(ee=>N(w,ee.name)).map(ee=>ee.name),D=S.filter(ee=>E.includes(ee)),K=E;return D.length?D:K}function z(u){return ue.find(p=>p.name===u)||null}function se(u,p){return e.scanners.find(b=>b.col<=u&&u<=b.col+1&&b.row-1<=p&&p<=b.row+1)||null}function ye(u,p){let b=z(p);if(!b)return null;let S=se(u.col+b.dc,u.row+b.dr);if(!S)return null;let w=Ee(S,"inputA");return w&&w.col===u.col&&w.row===u.row?S:null}function Z(u){return Object.entries(e.facilities||{}).find(([,p])=>p?.entry&&p.entry.col===u.col&&p.entry.row===u.row)||null}function I(u){return u?.baseId||u?.id||""}function W(u,p){return u.side==="left"&&p==="left"||u.side==="right"&&p==="right"||u.side==="top"&&p==="up"||u.side==="bottom"&&p==="down"}function N(u,p){let b=z(p);if(!b)return null;let S={col:u.col+b.dc,row:u.row+b.dr};if(Te(S.col,S.row)&&e.conveyorTiles.has($(S.col,S.row)))return{type:"conveyor",dirName:p,target:F(S.col,S.row),nextCell:S};let w=ye(u,p);if(w)return{type:"scanner",dirName:p,target:pe(w),scanner:w};let E=Z(u);return E&&W(E[1],p)?{type:"facility",dirName:p,facilityId:E[0],facility:E[1],target:F(u.col,u.row)}:null}function le(u,p){let b=z(p);if(!b)return!1;let S=e.conveyorMeta?.get?.($(u.col+b.dc,u.row+b.dr));return S?[...new Set([...Array.isArray(S.outDirs)?S.outDirs:[],S.dir].filter(Boolean))].includes(b.opposite):!1}function we(u){return ue.filter(p=>Te(u.col+p.dc,u.row+p.dr)&&e.conveyorTiles.has($(u.col+p.dc,u.row+p.dr))).map(p=>p.name)}function he(u,p,b="random"){let S=we(u);if(S.length<3)return p;let w=new Set(S.filter(K=>le(u,K)));if(b&&b!=="random"&&b!=="pass"&&S.includes(b)){let K=new Set(w);K.add(b),S.filter(ee=>!K.has(ee)).length>=2&&w.add(b)}let E=S.filter(K=>!w.has(K));if(E.length)return E;let D=p.filter(K=>!w.has(K));return D.length?D:p}function R(u,p){return p&&(p.type==="facility"||!L(u,p.target))}function G(u,p,b,S="random"){let w=b.map(ee=>N(p,ee)).filter(Boolean);if(!w.length)return null;let D=w.filter(ee=>ee.type!=="facility").filter(ee=>!L(u,ee.target)),K=D.length?D:w.filter(ee=>ee.type==="facility");return K.length?K[Math.floor(Math.random()*K.length)]:null}function x(u,p){let b=[];V(b,{x:u.x,y:u.y}),V(b,p),u.route=b.length?b:[{x:u.x,y:u.y}],u.targetIndex=u.route.length>1?1:u.route.length}function g(u,p){let b=We(u.x,u.y);if(!b)return Ot(p,"OFF GRID");let S=$(b.col,b.row);if(!e.conveyorTiles.has(S))return Ot(p,"OFF BELT");let w=e.conveyorMeta?.get(S)||{},E=he(b,ne(S),w.branchMode||"random");if(!E.length){u.stoppedTimer=.25;return}let D=G(u,b,E,w.branchMode||"random");if(!D){u.stoppedTimer=.25;return}if(D.type==="facility"){let K=I(D.facility);K==="mixer"?to(p,D.facility):K==="truck"?mn(p,D.facility):K==="trash"?no(p,D.facility):Ot(p,"DONE");return}D.type==="scanner"&&(u.pendingScannerId=D.scanner.id),u.prevConveyorCell=S,x(u,D.target)}function O(u){let p=We(u.x,u.y);if(!p)return null;let b=$(p.col,p.row);return e.conveyorTiles.has(b)?b:null}function X(u){let p=O(u)||O(u.route?.[u.targetIndex]||u);return t(p)}function oe(u,p){let b=O(p);!b||u.lastWearKey===b||(u.lastWearKey=b,Wi(e,b))}function de(u,p){let b=X(u)*p;for(;b>0&&u.targetIndex=D?(u.x=S.x,u.y=S.y,oe(u,S),u.targetIndex+=1,b-=D):(u.x+=w/D*b,u.y+=E/D*b,b=0)}}function ge(u,p,b){u.stage="queued",u.route=null,u.queueRoute=b?b.map(S=>({x:S.x,y:S.y})):[pe(p)],u.scannerId=p.id,p.queue.includes(u.id)||p.queue.push(u.id),ce(p)}function ce(u){u.queue=u.queue.filter(b=>e.chicks.some(S=>S.id===b&&S.stage==="queued"));let p=y.cell*.86*ls(e);u.queue.forEach((b,S)=>{let w=e.chicks.find(E=>E.id===b);w&&(ot(w,w.queueRoute||[pe(u)],S*p),w.queueIndex=S)})}function ot(u,p,b){if(!p||!p.length)return;if(p.length===1||b<=0){let E=p[p.length-1];u.x=E.x,u.y=E.y;return}let S=b;for(let E=p.length-1;E>0;E-=1){let D=p[E-1],K=p[E],ee=Math.hypot(K.x-D.x,K.y-D.y);if(S<=ee){let Xe=1-S/ee;u.x=D.x+(K.x-D.x)*Xe,u.y=D.y+(K.y-D.y)*Xe;return}S-=ee}let w=p[0];u.x=w.x,u.y=w.y}function J(u){for(let p of e.scanners){if(p.cooldown>0&&(p.cooldown=Math.max(0,p.cooldown-u)),p.keyPressTime>0&&(p.keyPressTime=Math.max(0,p.keyPressTime-u)),ce(p),p.kind!=="auto"||p.cooldown>0||!p.queue.length)continue;let b=p.queue[0],S=e.chicks.findIndex(w=>w.id===b);if(S<0){p.queue.shift();continue}hn(S,go(p,e.chicks[S]),!0)&&(Ki(e,p),p.cooldown=et(p,e),Es(e))}}function Me(u){let p=xo(e,u);return!p||!p.queue.length?null:e.chicks.find(b=>b.id===p.queue[0])||null}function Be(u,p){if(e.phase!=="running")return;let b=xo(e,u);rt(b,p)}function rt(u,p){if(e.phase!=="running"||!u||u.kind!=="manual"||(u.keyPressTime=.18,u.keyPressSide=p,!u.queue.length))return;let b=e.chicks.findIndex(S=>S.id===u.queue[0]);b>=0&&hn(b,p,!1)}function Ge(u,p,b){return u.kind==="manual"&&go(u,p)===b}function it(u){let p=e.manualCombo?.count||0;if(e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=0,e.manualCombo.lastBonus=0,e.stats.manualComboFailure=(e.stats.manualComboFailure||0)+1,e.totals.manualComboFailure=(e.totals.manualComboFailure||0)+1,p>=10){let b=pe(u);It(e,10,.25),_(e,b.x,b.y-36,"COMBO RESET",f.danger)}}function eo(u){e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=Math.max(0,e.manualCombo.count||0)+1,e.stats.manualComboSuccess=(e.stats.manualComboSuccess||0)+1,e.totals.manualComboSuccess=(e.totals.manualComboSuccess||0)+1;let p=e.manualCombo.count;if(e.manualCombo.lastBonus=0,p<10)return 0;let b=Math.max(1,Math.floor(p/10)),S=e.scanners.filter(K=>K.kind==="manual").length,w=Math.min(1,(20+S*10)/100),E=0;for(let K=0;K0){Oe(e,D),e.stats.manualComboBonus=(e.stats.manualComboBonus||0)+D,e.totals.manualComboBonus=(e.totals.manualComboBonus||0)+D,e.manualCombo.lastBonus=D;let K=pe(u);_(e,K.x,K.y-42,`COMBO +${M(D)}`,f.green)}return D}function pn(u,p){let b=Ee(u,p);if(!b)return null;let S=$(b.col,b.row);if(e.conveyorTiles.has(S))return{...b};let E=(Le(e).scannerPorts.get(u.id)?.[p]?.keys||[]).filter(Boolean);if(!E.length)return null;let D=E.map(Q);return D.find(ee=>ee.col===b.col&&ee.row===b.row)||D[0]||null}function yn(u,p,b,S){let w=[];V(w,{x:u.x,y:u.y});let E=Ee(p,b);return E&&V(w,F(E.col,E.row)),V(w,F(S.col,S.row)),w}function hn(u,p,b){let S=e.chicks[u];if(!S||S.stage!=="queued")return!1;let w=Pt(e,S.scannerId);if(!w)return!1;let E=pn(w,p);if(!E)return!b&&w.kind==="manual"&&it(w),_(e,S.x,S.y-16,p==="left"?"NO LEFT BELT":"NO RIGHT BELT",f.danger),!1;!b&&w.kind==="manual"&&(Ge(w,S,p)?eo(w):it(w)),w.queue=w.queue.filter(K=>K!==S.id),S.stage="belt",S.route=yn(S,w,p,E),S.targetIndex=S.route.length>1?1:S.route.length,S.scannerId=null,S.nextScannerId=null,S.pendingScannerId=null,S.queueRoute=null,S.queueIndex=-1;let D=b?f.green:p==="left"?f.mixerBlue:f.truckPink;return $i(e,pe(w).x,pe(w).y,D),_(e,S.x,S.y-20,b?"AUTO":p.toUpperCase(),D),!0}function bt(u){let p=e.chicks[u];return p?(e.chicks.splice(u,1),p):null}function to(u,p=e.facilities.mixer){if(p?.processingCooldown>0){let D=e.chicks[u];D&&(D.stoppedTimer=.25);return}let b=bt(u);if(!b)return;let{x:S,y:w}=b;if(Rs(e),zo(e,p),Xo(e,p),b.sex==="poop"){let D=Ci(e);Qn(e,"mixer"),yt(e),Bi(e,S,w),_(e,S,w-18,`-${M(D)}`,f.danger);return}let E=ki(e);b.sex==="male"?zt(e):yt(e),Fi(e,S,w),_(e,S,w-18,`+${M(E)}`,f.green)}function mn(u,p=e.facilities.truck){let b=bt(u);if(!b)return;let{x:S,y:w}=b;bn(b.sex,p),Oi(e,S,w,b.sex),Ds(e,b.sex);let E=Je(e),D=yi(e,b.sex);if(b.sex==="poop"){if(Qn(e,"truck"),D)zt(e),_(e,S,w-18,`+${M(De(e))}`,f.green);else{let K=Mi(e);yt(e),_(e,S,w-18,`-${M(K)}`,f.danger)}return}if(b.sex==="female"){D?(zt(e),_(e,S,w-18,`+${M(De(e))}`,f.green)):(yt(e),_(e,S,w-18,E==="male"?"REJECT":"NO SALE",f.warn));return}if(D){zt(e),_(e,S,w-18,`+${M(De(e))}`,f.green);return}if(hi(e)){let K=gi(e);yt(e),_(e,S,w-18,`-${M(K)}`,f.danger)}else yt(e),_(e,S,w-18,"REJECT",f.warn)}function no(u,p=e.facilities.trash){if(p?.processingCooldown>0){let K=e.chicks[u];K&&(K.stoppedTimer=.25);return}let b=bt(u);if(!b)return;let{x:S,y:w}=b;Li(e,S,w,b.sex),As(e),zo(e,p),Xo(e,p);let E={amount:0},D="";if(b.sex==="poop"){E=wi(e),D=E.amount>0?` +${M(E.amount)}`:"",Qn(e,"trash"),zt(e);let K=Math.ceil(Math.max(0,Number(e.cardEffects?.composter)||0)*3*In(e));if(K>0){let ee=Oe(e,K);e.stats.composterIncome=(e.stats.composterIncome||0)+ee,e.totals.composterIncome=(e.totals.composterIncome||0)+ee,_(e,S,w-36,`COMPOST +${M(ee)}`,f.green)}_(e,S,w-18,`CLEAN${D}`,E.amount>0?f.green:f.green)}else yt(e),_(e,S,w-18,E.amount>0?`WASTE${D}`:"WASTE",E.amount>0?f.green:f.ink)}function Ot(u,p){let b=bt(u);b&&_(e,b.x,b.y-12,p,f.muted)}function bn(u,p=e.facilities.truck){let b=p||e.facilities.truck;b&&(e.truckCargo.push({sex:u,x:U(22,b.w-22),y:U(66,b.h-24)}),e.truckCargo.length>45&&e.truckCargo.shift())}function Nt(u){let p=We(u.x,u.y);if(p){let E=$(p.col,p.row);if(e.conveyorTiles.has(E))return E}let b=ti(e,u.x,u.y);if(!b)return null;let S=Q(b),w=F(S.col,S.row);return Math.hypot(u.x-w.x,u.y-w.y)<=y.cell*.55?b:null}function Jt(){let{components:u,cellToComponent:p}=ei(e);for(let b of e.chicks){if(b.stage==="flying")continue;let S=Nt(b);if(!S)continue;let w=p.get(S),E=u.get(w);E&&(E.count+=1)}for(let b of u.values())b.ratio=b.count/b.capacity;e.congestion=u,e.componentLookup=p}function oo(){for(let u of e.congestion.values()){let p=Io(e),b=mi(e);if(u.ratio>b&&u.ratio=p){let S=jt(u.id);if(!S.length||S.some(D=>D.stage!=="queued"&&D.stoppedTimer<=.2))continue;let w=e.lastExplodedComponent.get(u.id)||0,E=performance.now();E-w>900&&(e.lastExplodedComponent.set(u.id,E),vn(u))}}}function jt(u){return e.chicks.filter(p=>{let b=Nt(p);return b&&e.componentLookup?.get(b)===u})}function vn(u){let p=jt(u.id);if(!p.length)return;for(let w of p)No(e,w.sex,w.x,w.y);e.chicks=e.chicks.filter(w=>!p.some(E=>E.id===w.id));for(let w of e.scanners)w.queue=w.queue.filter(E=>e.chicks.some(D=>D.id===E));for(let w of u.cells){let E=Q(w),D=F(E.col,E.row);Ye(e,D.x,D.y,f.danger),je(e,D.x,D.y,6),Bn(e,D.x,D.y,4)}It(e,18,.75);let b=Q(u.cells[0]),S=F(b.col,b.row);e.stats.explosions=(e.stats.explosions||0)+1,e.totals.explosions=(e.totals.explosions||0)+1,_(e,S.x,S.y-22,`${Math.round(Io(e)*100)}% JAM EXPLOSION`,f.danger)}return{activeQueuedChick:Me,currentSpawnDelay:o,sortSlot:Be,updateCongestion:Jt,sortScanner:rt,updateRunning:v}}var ae=document.getElementById("gameCanvas"),ec=ae.getContext("2d"),B={shell:document.getElementById("gameShell"),money:document.getElementById("money"),turn:document.getElementById("turn"),timeLeft:document.getElementById("timeLeft"),phase:document.getElementById("phaseLabel"),comboCount:document.getElementById("comboCount"),eventBrief:document.getElementById("eventBrief"),targetBrief:document.getElementById("targetBrief"),speedBrief:document.getElementById("speedBrief"),turnProfit:document.getElementById("turnProfit"),mixerCount:document.getElementById("mixerCount"),truckFemaleCount:document.getElementById("truckFemaleCount"),truckMaleCount:document.getElementById("truckMaleCount"),poopCount:document.getElementById("poopCount"),buildStatus:document.getElementById("buildStatus"),turnSummary:document.getElementById("turnSummary"),eventPanel:document.getElementById("eventPanel"),modal:document.getElementById("modal"),modalTitle:document.getElementById("modalTitle"),modalBody:document.getElementById("modalBody"),modalActions:document.getElementById("modalActions"),hoverTooltip:document.getElementById("hoverTooltip"),manualScannerMonitor:document.getElementById("manualScannerMonitor"),hireRepairmanButton:document.getElementById("hireRepairmanButton"),debug:{panel:document.getElementById("debugPanel"),infiniteCash:document.getElementById("debugInfiniteCash"),dayInput:document.getElementById("debugDayInput"),setDay:document.getElementById("debugSetDayButton"),zeroTimer:document.getElementById("debugZeroTimerButton"),cardSelect:document.getElementById("debugCardSelect"),targetSelect:document.getElementById("debugTargetSelect"),grantCard:document.getElementById("debugGrantCardButton"),grantAllCards:document.getElementById("debugGrantAllCardsButton"),readout:document.getElementById("debugReadout")},buttons:{s1Left:document.getElementById("scanner1MixerButton"),s1Right:document.getElementById("scanner1TruckButton"),s2Left:document.getElementById("scanner2MixerButton"),s2Right:document.getElementById("scanner2TruckButton"),nextTurn:document.getElementById("nextTurnButton"),conveyor:document.getElementById("buildConveyorButton"),boostConveyor:document.getElementById("buildBoostConveyorButton"),eggFarm:document.getElementById("buildEggFarmButton"),autoScanner:document.getElementById("buildAutoScannerButton"),manualScanner:document.getElementById("buildManualScannerButton"),mixer:document.getElementById("buildMixerButton"),trash:document.getElementById("buildTrashButton"),truck:document.getElementById("buildTruckButton"),erase:document.getElementById("eraseButton"),undo:document.getElementById("undoButton"),redo:document.getElementById("redoButton")}};function tc(){let e={conveyor:"conveyor",boostConveyor:"boostConveyor",eggFarm:"eggFarm",autoScanner:"autoScanner",manualScanner:"manualScanner",mixer:"mixer",trash:"trash",truck:"truck"};for(let[t,n]of Object.entries(e))B.buttons[t]&&(B.buttons[t].innerHTML=Pr(n))}function nc(e){let t=new Set(e.tags||[]);return["upgradeEgg","crowdedFarming","hatchingFeed","extraEggOutlet"].includes(e.id)||t.has("EGG")?"Production / EGG":["upgradeTrash","poopRateBooster","composter","chemicalWeaponSubsidy"].includes(e.id)||t.has("POOP")?"Poop / Shredder":["upgradeAutoScanner","autoScannerTuning","scannerQueueSpacing"].includes(e.id)||t.has("SCANNER")?"Scanner":["bearing","dynamite"].includes(e.id)||t.has("CONVEYOR")?"Conveyor / Map":["safetyCover","preventiveMaintenance","durabilityCoating","sparePartsBin","laborExploitation"].includes(e.id)||t.has("MAINTENANCE")?"Maintenance / Risk":["dudFilter","dudRefund","freeReroll","extraCards"].includes(e.id)||t.has("CARD")?"Card Engine":t.has("ULTRA RARE")?"Ultra Rare":t.has("ECONOMY")||["upgradeMixer","upgradeTruck","recyclingSubsidy","usedMachine","newMachine","flattery","legalWork","rescueLoan"].includes(e.id)?"Economy / Shipment":"Other"}function oc(){if(!B.debug?.panel||!B.debug.cardSelect)return;let e=["Production / EGG","Poop / Shredder","Scanner","Conveyor / Map","Maintenance / Risk","Card Engine","Economy / Shipment","Ultra Rare","Other"],t=new Map(e.map(n=>[n,[]]));for(let n of Yt){let o=nc(n);t.has(o)||t.set(o,[]),t.get(o).push(n)}B.debug.cardSelect.innerHTML="";for(let n of e){let o=t.get(n)||[];if(!o.length)continue;let r=document.createElement("optgroup");r.label=n;for(let s of o){let l=document.createElement("option");l.value=s.id;let d=s.rarity==="ultraRare"?"UR":s.rarity==="rare"?"R":"C";l.textContent=`[${d}] ${s.title}`,r.appendChild(l)}B.debug.cardSelect.appendChild(r)}B.debug.cardSelect.addEventListener("change",Bt),Bt()}function Bt(){if(!B.debug?.targetSelect)return;let e=B.debug.cardSelect?.value,t=Vt(e),n=t?as(a,t):[];if(B.debug.targetSelect.innerHTML="",!n.length){let r=document.createElement("option");r.value="__none__",r.textContent=t?"No target required":"No card selected",B.debug.targetSelect.appendChild(r),B.debug.targetSelect.disabled=!0;return}let o=document.createElement("option");o.value="__auto__",o.textContent=t?.id==="dynamite"?"Auto: first 3 blocked cells":"Auto: first valid target",B.debug.targetSelect.appendChild(o);for(let r of n){let s=document.createElement("option");s.value=r.key,s.textContent=r.label,B.debug.targetSelect.appendChild(s)}B.debug.targetSelect.disabled=!1}function rc(){let e=Math.max(1,Math.floor(Number(B.debug.dayInput?.value)||1));a.turn=e,B.debug.dayInput&&(B.debug.dayInput.value=String(e)),_(a,ae.width/2-a.view.x,86-a.view.y,`DAY ${e}`,f.green),H.updatePanels(),H.updateUI(),Bt(),Lt(`Day set to ${e}.`)}function ic(){a.timeLeft=0,a.phase==="running"&&Ns(),_(a,ae.width/2-a.view.x,86-a.view.y,"TIMER 0",f.warn),H.updatePanels(),H.updateUI(),Lt("Timer set to 0.")}function sc(){let e=B.debug.cardSelect?.value,t=B.debug.targetSelect?.disabled?void 0:B.debug.targetSelect?.value,n=jo(a,e,{targetKey:t});B.debug.grantCard&&(B.debug.grantCard.textContent=n.ok?"Granted":"Failed",window.setTimeout(()=>{B.debug.grantCard&&(B.debug.grantCard.textContent="Grant Selected")},900)),Ce?.updateCongestion?.(),H.updatePanels(),H.updateUI(),Bt(),Lt(n.reason)}function lc(){let t=Yt.map(n=>jo(a,n,{targetKey:"__auto__"})).filter(n=>n.ok).length;Ce?.updateCongestion?.(),H.updatePanels(),H.updateUI(),Bt(),Lt(`Granted ${t}/${Yt.length} cards.`)}function ac(){B.debug?.infiniteCash?.checked&&a.cash<999999&&(a.cash=999999,a.totals.maxCash=Math.max(a.totals.maxCash,a.cash))}function Lt(e=""){B.debug?.readout&&(B.debug.readout.textContent=[e,`D${a.turn}`,M(a.cash),`Combo ${a.manualCombo?.count||0}`,`Event ${a.eventActive?.title||a.eventOffer?.title||"none"}`,`Rescue ${a.cardEffects?.rescueLoanCharges||0}`,`Chem ${a.cardEffects?.chemicalWeaponSubsidy||0}`].filter(Boolean).join(" | "))}var a=wo(),Y,H,Ce,Qt;function cc(e=null){let t=Yn(a,e);return e?t*Ko(a,e):t}function uc(){Object.assign(a,wo()),a.phase="running",a.view={x:0,y:0,scale:1},So(a),Us(),me(a),H.hideModal(),Ce.updateCongestion(),H.updatePanels(),H.updateUI(),Lt()}function dc(){if(a.phase!=="build")return;if(a.cardDraft?.pending||a.cardTargetPick?.pending){Y.fail(a.cardTargetPick?.pending?"Choose upgrade target first.":"Choose an upgrade card first."),H.updatePanels();return}let e=sn(a);if(e.length){Y.fail(`Cannot start: ${e[0]}`),H.updatePanels();return}me(a),Zr(a),Xi(a);let t=Math.max(0,Math.floor(a.lastResult?.profit??a.stats?.profit??0)),n=Pi(a,Math.max(1,a.turn||1),t);a.lastStartFees={fairiesTribute:n.amount||0,tribute:n},n.amount>0&&_(a,ae.width/2-a.view.x,116-a.view.y,`FAIRIES -${M(n.amount)}`,f.danger),ci(a),a.phase="running",a.turn+=1,a.timeLeft=di(a),a.shutdownTimeLeft=0,a.cleanupTimer=null,a.cleanupBlown=!1,a.chicks=[],a.effects=[],a.floatingTexts=[],a.shake={time:0,strength:0},a.truckCargo=[],Us(),a.stats=vo(),a.stats.fairiesTribute=a.lastStartFees?.fairiesTribute||0,a.stats.repairWorkerWages=a.pendingRepairWorkerWages||0;let o=a.stats.fairiesTribute+a.stats.repairWorkerWages;o>0&&(a.stats.penalty+=o,a.stats.profit-=o),a.pendingRepairWorkerWages=0;for(let r of a.scanners)r.queue=[],r.cooldown=0;for(let r of a.eggFarms)r.nextSpawn=Ce.currentSpawnDelay(r),r.lastInterval=r.nextSpawn,r.shutterProgress=0,r.shutterSparked=!1;a.buildTool=null,a.selected=null,a.groupDrag=null,a.selectionBox=null,a.pan=null,Ce.updateCongestion(),H.updatePanels(),H.updateUI()}function fc(){me(a);let e=zi(a);e.ok?_(a,ae.width/2-a.view.x,96-a.view.y,`Repairman hired -${M(e.cost)}`,f.green):(_(a,ae.width/2-a.view.x,96-a.view.y,e.reason||"Cannot hire repairman.",f.danger),Y?.fail?.(e.reason||"Cannot hire repairman.")),H.updatePanels(),H.updateUI()}function pc(){if(a.phase!=="running")return;let e=Ei(a),t=a.eventActive?{...a.eventActive}:null,n=vi(a),o=Ri(a);if(e.adjusted>0){let s=a.facilities.truck,l=s?s.x+s.w/2:ae.width/2-a.view.x,d=s?s.y+26:96-a.view.y;_(a,l,d,`${e.target==="poop"?"POOP SHIP":"SHIP"} +${M(e.adjusted)}`,f.green)}n?.bonus>0&&_(a,ae.width/2-a.view.x,96-a.view.y,`EVENT +${M(n.bonus)}`,f.green),o.amount>0&&_(a,ae.width/2-a.view.x,116-a.view.y,`CHEM SUBSIDY +${M(o.amount)}`,f.green),ui(a),a.totals.turnsCompleted+=1;let r=bi(t);if(r!==1&&(a.pendingFairiesTributeMultiplier=r),a.lastResult={...a.stats,ship:e,event:n,chemical:o,rescue:{amount:0,used:0,remaining:a.cardEffects?.rescueLoanCharges||0},fairiesTribute:{amount:a.stats.fairiesTribute||0},tributeMultiplier:r,turn:a.turn,cash:a.cash},a.cash<0){if((a.cardEffects?.rescueLoanCharges||0)>0){a.phase="loanDecision",H.showEmergencyLoanDecision(Os,Jn);return}a.phase="gameover",H.showGameOver();return}Ls()}function Ls(){a.phase="build",a.truckCargo=[],a.chicks=[],a.shutdownTimeLeft=0,a.cleanupTimer=null,a.cleanupBlown=!1,a.buildSession+=1,a.undoStack=[],a.redoStack=[],a.timeLeft=0;for(let e of a.scanners)e.queue=[];for(let e of a.eggFarms)e.shutterProgress=0,e.shutterSparked=!1;Qi(a),a.eventOffer=ai(a),Qt&&Qt.prepareDraft(),a.cardTargetPick=null,a.buildTool=null,a.groupDrag=null,a.selectionBox=null,a.pan=null,H.updatePanels(),H.showTurnResult(a.lastResult)}function Os(){if((a.cardEffects?.rescueLoanCharges||0)<=0)return Jn();a.cardEffects.rescueLoanCharges-=1,a.stats.rescueLoan=(a.stats.rescueLoan||0)+500,a.totals.rescueLoan=(a.totals.rescueLoan||0)+500;let e=Oe(a,500);a.lastResult={...a.lastResult||{},...a.stats,rescue:{amount:(a.lastResult?.rescue?.amount||0)+e,used:(a.lastResult?.rescue?.used||0)+1,remaining:a.cardEffects.rescueLoanCharges},cash:a.cash},_(a,ae.width/2-a.view.x,176-a.view.y,`RESCUE +${M(e)}`,f.green),a.cash>=0?Ls():(a.cardEffects?.rescueLoanCharges||0)>0?(a.phase="loanDecision",H.showEmergencyLoanDecision(Os,Jn)):Jn()}function Jn(){a.phase="gameover",H.showGameOver()}function Ns(){a.shutdownTimeLeft<=0&&(a.shutdownTimeLeft=a.shutdownGraceSeconds||10);for(let e of a.eggFarms){if(e.shutterSparked)continue;e.shutterProgress=.02,e.shutterSparked=!0;let t=F(e.col,e.row);Ye(a,t.x,t.y,f.ink),je(a,t.x,t.y+10,10),_(a,t.x,t.y-34,"SHUT +10s",f.ink)}}function Gs(e){a.lastTimestamp||(a.lastTimestamp=e);let t=Math.min((e-a.lastTimestamp)/1e3,.05);a.lastTimestamp=e,a.phase==="running"&&Ce.updateRunning(t,{closeFarmShutters:Ns,completeTurn:pc}),Gi(a,t,ae,Y.equipmentHitBoxes),Ce.updateCongestion(),ys(ec,ae,a,{activeQueuedChick:Ce.activeQueuedChick,selectedObject:Y.selectedObject,selectedTitle:Y.selectedTitle}),ac(),H.updateUI(),_s(),Lt(),requestAnimationFrame(Gs)}function jn(){return a.view?.scale||1}function fn(){a.view||(a.view={x:0,y:0,scale:1}),a.view.scale==null&&(a.view.scale=1)}function Zn(e){let t=ae.getBoundingClientRect();return{x:(e.clientX-t.left)*ae.width/t.width,y:(e.clientY-t.top)*ae.height/t.height}}function ht(e){let t=Zn(e),n=jn();return{x:(t.x-(a.view?.x||0))/n,y:(t.y-(a.view?.y||0))/n}}function yc(e){let t=jn();return{x:e.x*t+(a.view?.x||0),y:e.y*t+(a.view?.y||0)}}function hc(){let e={left:y.x-90,top:y.y-130,right:y.x+y.cols*y.cell+260,bottom:y.y+y.rows*y.cell+220};if(a.phase==="build")for(let t of kt(a)){let n=Ct(t);e.left=Math.min(e.left,n.x-60),e.top=Math.min(e.top,n.y-80),e.right=Math.max(e.right,n.x+n.w+80),e.bottom=Math.max(e.bottom,n.y+n.h+80)}return e}function $s(e,t){if(e<=t)return[e,t];let n=(e+t)/2;return[n,n]}function mt(){fn();let e=jn(),t=hc(),[n,o]=$s(ae.width-160-t.right*e,110-t.left*e),[r,s]=$s(ae.height-150-t.bottom*e,150-t.top*e);a.view.x=on(a.view.x,n,o),a.view.y=on(a.view.y,r,s)}function Us(){fn(),a.view.scale=1;let e=a.eggFarms?.[0],t=e?F(e.col,e.row):{x:y.x,y:y.y};a.view.x=280-t.x,a.view.y=190-t.y,mt()}function mc(e){let t=Zn(e);fn(),a.pan={start:t,viewX:a.view.x,viewY:a.view.y,moved:!1}}function bc(e){if(!a.pan)return;let t=Zn(e);Math.hypot(t.x-a.pan.start.x,t.y-a.pan.start.y)>5&&(a.pan.moved=!0),fn(),a.view.x=a.pan.viewX+t.x-a.pan.start.x,a.view.y=a.pan.viewY+t.y-a.pan.start.y,mt()}function vc(e){e.preventDefault(),fn();let t=Zn(e),n=ht(e),o=Math.exp(-e.deltaY*.0012),r=on(jn()*o,.55,1.8);a.view.scale=r,a.view.x=t.x-n.x*r,a.view.y=t.y-n.y*r,mt(),nt()}function wc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:{type:e.type,id:e.ref.id}:null}function Sc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:e.ref||null:null}function nt(){B.hoverTooltip&&(B.hoverTooltip.classList.remove("visible"),B.hoverTooltip.setAttribute("aria-hidden","true"),a.hover=null)}function xc(e,t){if(!B.hoverTooltip||a.phase!=="build"||a.cardTargetPick?.pending||a.groupDrag||a.selectionBox||a.pan)return nt();let n=Sc(t);if(!n)return nt();let o=Y.selectedTitle(n),r=Y.flavorText?Y.flavorText(n):"",s=Y.disconnectedWarningFor?Y.disconnectedWarningFor(n):"",l=Y.selectedInfoLines(n).slice(0,7);B.hoverTooltip.innerHTML=`${o}${s?`${s}`:r?`${r}`:""}${l.map(C=>`${C}`).join("")}`;let d=Math.min(window.innerWidth-330,e.clientX+18),v=Math.min(window.innerHeight-220,e.clientY+18);B.hoverTooltip.style.left=`${Math.max(8,d)}px`,B.hoverTooltip.style.top=`${Math.max(8,v)}px`,B.hoverTooltip.classList.add("visible"),B.hoverTooltip.setAttribute("aria-hidden","false"),a.hover={type:t.type,id:t.oldKey||t.ref?.id||null}}function kc(e){if(a.phase!=="build")return nt();xc(e,Y.equipmentAtPoint(ht(e)))}function Ws(e){nt();let t=ht(e),n=Y.equipmentAtPoint(t),o=wc(n);if(!o){a.selected=null,a.multiSelected=[],H.updatePanels();return}a.selected=o,a.multiSelected=[o],H.updatePanels();let r=Y.selectedObject();r?.type==="scanner"&&r.kind==="manual"&&Y.showManualScannerMenu(r),r?.type==="scanner"&&r.kind==="auto"&&Y.showAutoScannerMenu(r)}function Xt(){a.buildTool=null,a.selected=null,a.multiSelected=[],a.selectionBox=null,a.cardTargetPick?.mode==="autoScannerMenu"&&(a.cardTargetPick=null),H.hideModal(),nt(),H.updatePanels(),H.updateUI()}function Fs(e){return String(e).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function Cc(e){let t=e?.queue?.[0];return t==null?null:a.chicks.find(n=>n.id===t)||null}function Mc(e){if(!e)return'WAIT';let t=e.sex==="poop"?"\u{1F4A9} POOP":e.sex==="male"?"\u2642 MALE":"\u2640 FEMALE";return`${t}`}function gc(e,t){let n=new Set(a.eggFarms.map(P=>$(P.col,P.row))),o=new Map(a.scanners.map(P=>[$(P.col,P.row),P])),r=Ee(e,"inputA"),s=r?$(r.col,r.row):null,l=new Set(Object.values(a.facilities||{}).map(P=>P.entry?$(P.entry.col,P.entry.row):null).filter(Boolean)),d=t?.sex||"",v=d==="poop"?"\u{1F4A9}":d==="male"?"\u2642":d==="female"?"\u2640":"",C=[];for(let P=e.row-2;P<=e.row+2;P+=1)for(let A=e.col-2;A<=e.col+2;A+=1){let L=$(A,P),V=["mini-cell"],ne="";A===e.col&&P===e.row?(V.push("scanner"),d&&V.push(d),ne=v||"S"):L===s?(V.push("input"),ne="IN"):n.has(L)?(V.push("egg"),ne="E"):o.has(L)?(V.push("scanner-other"),ne="S"):l.has(L)?(V.push("port"),ne="P"):a.conveyorTiles.has(L)?(V.push("belt"),ne="\u2022"):a.blockedCells?.has?.(L)&&(V.push("blocked"),ne="\xD7"),C.push(`${ne}`)}return`
${C.join("")}
`}function Tc(e){let t=yc(F(e.col,e.row)),n=76;return t.x<-n||t.y<-n||t.x>ae.width+n||t.y>ae.height+n}function _s(){if(!B.manualScannerMonitor)return;if(a.phase!=="running"){B.manualScannerMonitor.classList.remove("visible"),B.manualScannerMonitor.innerHTML="";return}let e=a.scanners.filter(t=>t.kind==="manual"&&Tc(t));if(!e.length){B.manualScannerMonitor.classList.remove("visible"),B.manualScannerMonitor.innerHTML="";return}B.manualScannerMonitor.innerHTML=e.map(t=>{let n=Cc(t),o=t.keys?.left?.label||(t.slot===0?"A":"Left"),r=t.keys?.right?.label||(t.slot===0?"D":"Right"),s=t.role===0?"MIXER":"WASTE",l=t.role===0?"S2":"TRUCK",d=n?"":" disabled";return` +
Formula
Base = Cash + Total revenue + Factory value \xD70.5 + Event bonus \xD70.5 = ${M(k.base)}
Daily earned = ceil(Base \xF7 Days) = ${M(k.dailyEarned)}
Score = max(0, floor(Base + Daily earned + Correct bonus - Total outflow - Day penalty)) = ${k.score}
+
Factory Value${M(k.factoryValue)}
Total Revenue${M(e.totals.revenue)}
Daily Earned${M(k.dailyEarned)} / day
Total Outflow${M(e.totals.penalty)}
Fairies Tribute${M(e.totals.fairiesTribute||0)}
Correct Sorts${e.totals.correct}
Auto Sorted${e.totals.autoSorted}
Poop Control${e.totals.poopTrash} trashed / ${e.totals.poopTruck} shipped / ${e.totals.poopMixer} mixer
Explosion Penalty${M(e.totals.explosionDamage)}
Event Bonus${M(e.totals.eventBonus)}
Day Penalty-${k.dayPenalty}
Events${e.totals.eventSuccess} success / ${e.totals.eventFailed} failed
+ `,t.modalActions.innerHTML="",t.modalActions.appendChild(le(re.actions.restart||"Restart",o,"primary-button restart-button")),t.modal.classList.remove("equipment-popover"),t.modal.classList.add("visible","gameover-modal")}function le(A,_,k="primary-button"){let g=document.createElement("button");return g.type="button",g.className=k,g.textContent=A,g.addEventListener("click",_),g}function Se(){t.modal.classList.remove("visible","equipment-popover","gameover-modal"),t.modal.style.removeProperty("--popover-x"),t.modal.style.removeProperty("--popover-y")}function he(){}return{updatePanels:C,updateUI:z,showTitle:Z,showTurnResult:$,showEmergencyLoanDecision:U,showGameOver:N,hideModal:Se,checkGameOver:he}}function cr(e){e.totals.processed+=1}function zt(e){e.stats.correct+=1,e.totals.correct+=1}function ht(e){e.stats.mistakes+=1,e.totals.mistakes+=1}function Ps(e){e.stats.autoSorted+=1,e.totals.autoSorted+=1}function Rs(e){e.stats.poopSpawned+=1}function As(e){e.stats.mixerCount+=1,cr(e)}function Ds(e){e.stats.trashCount+=1,cr(e)}function $s(e,t){t==="female"?e.stats.truckFemale+=1:t==="male"&&(e.stats.truckMale+=1),cr(e)}function Zn(e,t){let n=t==="truck"?"poopTruck":t==="trash"?"poopTrash":t==="mixer"?"poopMixer":null;n&&(e.stats[n]+=1,e.totals[n]+=1)}function Is({game:e,currentConveyorSpeed:t,onGameOverCheck:n}){function o(u){return gt(u)*Hn(u)*is(e)/fi(e)}function r(u){let f=F(u.col,u.row),b=1+ss(e,u),S=l(u,b);if(!S.length)return s(u,f),!0;let w=0,E=0;for(let D of S){let K=F(D.col,D.row),ee=d(K);if(ee){ee.stoppedTimer=.85,E+=1;continue}let Qe=Ms(e,{stage:"belt",scannerId:null,route:[K]});Qe.sex==="poop"&&Rs(e),e.chicks.push(Qe),Wi(e,u),w+=1}return w>0?($i(e,f.x,f.y),w>1&&W(e,f.x,f.y-28,`x${w}`,p.green),!0):E===0}function s(u,f){(u.noRouteNoticeCooldown||0)<=0&&(W(e,f.x,f.y-24,"NO BELT: PAUSED",p.warn),u.noRouteNoticeCooldown=2.5)}function l(u,f){let S=ue.map(w=>({col:u.col+w.dc,row:u.row+w.dr})).filter(w=>Ee(w.col,w.row)&&e.conveyorTiles.has(I(w.col,w.row))).map(w=>({p:w,blocked:L(null,F(w.col,w.row))?1:0,roll:Math.random()}));return S.sort((w,E)=>w.blocked-E.blocked||w.roll-E.roll),S.slice(0,Math.max(1,f||1)).map(w=>w.p)}function d(u){return e.chicks.find(f=>f.stage!=="flying"&&Math.hypot(f.x-u.x,f.y-u.y)0;if(e.timeLeft=Math.max(0,e.timeLeft-u),S&&e.timeLeft<=0&&f(),e.timeLeft<=0){e.shutdownTimeLeft>0&&(e.shutdownTimeLeft=Math.max(0,e.shutdownTimeLeft-u));for(let w of e.eggFarms)w.shutterProgress=Math.min(1,(w.shutterProgress||0)+u*2.8)}if(S&&e.timeLeft>0){for(let w of e.eggFarms)if(w.noRouteNoticeCooldown>0&&(w.noRouteNoticeCooldown=Math.max(0,w.noRouteNoticeCooldown-u)),w.nextSpawn-=u,w.nextSpawn<=0){let E=r(w);w.nextSpawn=E?o(w):.15,w.lastInterval=w.nextSpawn}}for(let w=e.chicks.length-1;w>=0;w-=1){let E=e.chicks[w];E.bob+=u*7,E.stoppedTimer>0&&(E.stoppedTimer=Math.max(0,E.stoppedTimer-u)),E.stage!=="queued"&&P(E,w,u)}J(u),Jt(),so(),e.timeLeft<=0&&(e.chicks.length===0?b():e.shutdownTimeLeft<=0&&C())}function C(){if(e.cleanupBlown)return;e.cleanupBlown=!0,e.cleanupTimer=1;let u=[...e.chicks];for(let f of u)Go(e,f.sex,f.x,f.y,-Math.PI/2,!0);e.chicks=[];for(let f of e.scanners)f.queue=[];if(Jt(),u.length){let f=u.reduce((S,w)=>S+w.x,0)/u.length,b=u.reduce((S,w)=>S+w.y,0)/u.length;Ve(e,f,b,p.warn,58),W(e,f,b-24,"CLEANUP",p.warn)}}function P(u,f,b){if(R(u)){u.stoppedTimer=.35;return}if(de(u,b),!(u.route&&u.targetIndex=u.route.length)return!1;let f=u.route[u.targetIndex];return L(u,f)}function L(u,f){if(!f)return!1;for(let b of e.chicks)if(!(u&&b.id===u.id)&&b.stage!=="flying"&&Math.hypot(b.x-f.x,b.y-f.y)1)&&u.push({x:f.x,y:f.y})}function te(u){let f=e.conveyorMeta?.get?.(u)||{},b=[];Array.isArray(f.outDirs)&&b.push(...f.outDirs),f.dir&&b.push(f.dir);let S=[...new Set(b)].filter(ee=>ue.some(Qe=>Qe.name===ee)),w=Q(u),E=ue.filter(ee=>N(w,ee.name)).map(ee=>ee.name),D=S.filter(ee=>E.includes(ee)),K=E;return D.length?D:K}function z(u){return ue.find(f=>f.name===u)||null}function se(u,f){return e.scanners.find(b=>b.col<=u&&u<=b.col+1&&b.row-1<=f&&f<=b.row+1)||null}function ye(u,f){let b=z(f);if(!b)return null;let S=se(u.col+b.dc,u.row+b.dr);if(!S)return null;let w=Pe(S,"inputA");return w&&w.col===u.col&&w.row===u.row?S:null}function Z(u){return Object.entries(e.facilities||{}).find(([,f])=>f?.entry&&f.entry.col===u.col&&f.entry.row===u.row)||null}function $(u){return u?.baseId||u?.id||""}function U(u,f){return u.side==="left"&&f==="left"||u.side==="right"&&f==="right"||u.side==="top"&&f==="up"||u.side==="bottom"&&f==="down"}function N(u,f){let b=z(f);if(!b)return null;let S={col:u.col+b.dc,row:u.row+b.dr};if(Ee(S.col,S.row)&&e.conveyorTiles.has(I(S.col,S.row)))return{type:"conveyor",dirName:f,target:F(S.col,S.row),nextCell:S};let w=ye(u,f);if(w)return{type:"scanner",dirName:f,target:pe(w),scanner:w};let E=Z(u);return E&&U(E[1],f)?{type:"facility",dirName:f,facilityId:E[0],facility:E[1],target:F(u.col,u.row)}:null}function le(u,f){let b=z(f);if(!b)return!1;let S=e.conveyorMeta?.get?.(I(u.col+b.dc,u.row+b.dr));return S?[...new Set([...Array.isArray(S.outDirs)?S.outDirs:[],S.dir].filter(Boolean))].includes(b.opposite):!1}function Se(u){return ue.filter(f=>Ee(u.col+f.dc,u.row+f.dr)&&e.conveyorTiles.has(I(u.col+f.dc,u.row+f.dr))).map(f=>f.name)}function he(u,f,b="random"){let S=Se(u);if(S.length<3)return f;let w=new Set(S.filter(K=>le(u,K)));if(b&&b!=="random"&&b!=="pass"&&S.includes(b)){let K=new Set(w);K.add(b),S.filter(ee=>!K.has(ee)).length>=2&&w.add(b)}let E=S.filter(K=>!w.has(K));if(E.length)return E;let D=f.filter(K=>!w.has(K));return D.length?D:f}function A(u,f){return f&&(f.type==="facility"||!L(u,f.target))}function _(u,f,b,S="random"){let w=b.map(ee=>N(f,ee)).filter(Boolean);if(!w.length)return null;let D=w.filter(ee=>ee.type!=="facility").filter(ee=>!L(u,ee.target)),K=D.length?D:w.filter(ee=>ee.type==="facility");return K.length?K[Math.floor(Math.random()*K.length)]:null}function k(u,f){let b=[];V(b,{x:u.x,y:u.y}),V(b,f),u.route=b.length?b:[{x:u.x,y:u.y}],u.targetIndex=u.route.length>1?1:u.route.length}function g(u,f){let b=We(u.x,u.y);if(!b)return Ot(f,"OFF GRID");let S=I(b.col,b.row);if(!e.conveyorTiles.has(S))return Ot(f,"OFF BELT");let w=e.conveyorMeta?.get(S)||{},E=he(b,te(S),w.branchMode||"random");if(!E.length){u.stoppedTimer=.25;return}let D=_(u,b,E,w.branchMode||"random");if(!D){u.stoppedTimer=.25;return}if(D.type==="facility"){let K=$(D.facility);K==="mixer"?ro(f,D.facility):K==="truck"?bn(f,D.facility):K==="trash"?io(f,D.facility):Ot(f,"DONE");return}D.type==="scanner"&&(u.pendingScannerId=D.scanner.id),u.prevConveyorCell=S,k(u,D.target)}function O(u){let f=We(u.x,u.y);if(!f)return null;let b=I(f.col,f.row);return e.conveyorTiles.has(b)?b:null}function X(u){let f=O(u)||O(u.route?.[u.targetIndex]||u);return t(f)}function oe(u,f){let b=O(f);!b||u.lastWearKey===b||(u.lastWearKey=b,Ui(e,b))}function de(u,f){let b=X(u)*f;for(;b>0&&u.targetIndex=D?(u.x=S.x,u.y=S.y,oe(u,S),u.targetIndex+=1,b-=D):(u.x+=w/D*b,u.y+=E/D*b,b=0)}}function Te(u,f,b){u.stage="queued",u.route=null,u.queueRoute=b?b.map(S=>({x:S.x,y:S.y})):[pe(f)],u.scannerId=f.id,f.queue.includes(u.id)||f.queue.push(u.id),ce(f)}function ce(u){u.queue=u.queue.filter(b=>e.chicks.some(S=>S.id===b&&S.stage==="queued"));let f=y.cell*.86*ls(e);u.queue.forEach((b,S)=>{let w=e.chicks.find(E=>E.id===b);w&&(rt(w,w.queueRoute||[pe(u)],S*f),w.queueIndex=S)})}function rt(u,f,b){if(!f||!f.length)return;if(f.length===1||b<=0){let E=f[f.length-1];u.x=E.x,u.y=E.y;return}let S=b;for(let E=f.length-1;E>0;E-=1){let D=f[E-1],K=f[E],ee=Math.hypot(K.x-D.x,K.y-D.y);if(S<=ee){let Qe=1-S/ee;u.x=D.x+(K.x-D.x)*Qe,u.y=D.y+(K.y-D.y)*Qe;return}S-=ee}let w=f[0];u.x=w.x,u.y=w.y}function J(u){for(let f of e.scanners){if(f.cooldown>0&&(f.cooldown=Math.max(0,f.cooldown-u)),f.keyPressTime>0&&(f.keyPressTime=Math.max(0,f.keyPressTime-u)),ce(f),f.kind!=="auto"||f.cooldown>0||!f.queue.length)continue;let b=f.queue[0],S=e.chicks.findIndex(w=>w.id===b);if(S<0){f.queue.shift();continue}mn(S,Eo(f,e.chicks[S]),!0)&&(Ki(e,f),f.cooldown=tt(f,e),Ps(e))}}function ge(u){let f=Co(e,u);return!f||!f.queue.length?null:e.chicks.find(b=>b.id===f.queue[0])||null}function Le(u,f){if(e.phase!=="running")return;let b=Co(e,u);it(b,f)}function it(u,f){if(e.phase!=="running"||!u||u.kind!=="manual"||(u.keyPressTime=.18,u.keyPressSide=f,!u.queue.length))return;let b=e.chicks.findIndex(S=>S.id===u.queue[0]);b>=0&&mn(b,f,!1)}function Ge(u,f,b){return u.kind==="manual"&&Eo(u,f)===b}function st(u){let f=e.manualCombo?.count||0;if(e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=0,e.manualCombo.lastBonus=0,e.stats.manualComboFailure=(e.stats.manualComboFailure||0)+1,e.totals.manualComboFailure=(e.totals.manualComboFailure||0)+1,f>=10){let b=pe(u);It(e,10,.25),W(e,b.x,b.y-36,"COMBO RESET",p.danger)}}function oo(u){e.manualCombo||(e.manualCombo={count:0,lastBonus:0}),e.manualCombo.count=Math.max(0,e.manualCombo.count||0)+1,e.stats.manualComboSuccess=(e.stats.manualComboSuccess||0)+1,e.totals.manualComboSuccess=(e.totals.manualComboSuccess||0)+1;let f=e.manualCombo.count;if(e.manualCombo.lastBonus=0,f<10)return 0;let b=Math.max(1,Math.floor(f/10)),S=e.scanners.filter(K=>K.kind==="manual").length,w=Math.min(1,(20+S*10)/100),E=0;for(let K=0;K0){Ne(e,D),e.stats.manualComboBonus=(e.stats.manualComboBonus||0)+D,e.totals.manualComboBonus=(e.totals.manualComboBonus||0)+D,e.manualCombo.lastBonus=D;let K=pe(u);W(e,K.x,K.y-42,`COMBO +${M(D)}`,p.green)}return D}function yn(u,f){let b=Pe(u,f);if(!b)return null;let S=I(b.col,b.row);if(e.conveyorTiles.has(S))return{...b};let E=(Oe(e).scannerPorts.get(u.id)?.[f]?.keys||[]).filter(Boolean);if(!E.length)return null;let D=E.map(Q);return D.find(ee=>ee.col===b.col&&ee.row===b.row)||D[0]||null}function hn(u,f,b,S){let w=[];V(w,{x:u.x,y:u.y});let E=Pe(f,b);return E&&V(w,F(E.col,E.row)),V(w,F(S.col,S.row)),w}function mn(u,f,b){let S=e.chicks[u];if(!S||S.stage!=="queued")return!1;let w=Rt(e,S.scannerId);if(!w)return!1;let E=yn(w,f);if(!E)return!b&&w.kind==="manual"&&st(w),W(e,S.x,S.y-16,f==="left"?"NO LEFT BELT":"NO RIGHT BELT",p.danger),!1;!b&&w.kind==="manual"&&(Ge(w,S,f)?oo(w):st(w)),w.queue=w.queue.filter(K=>K!==S.id),S.stage="belt",S.route=hn(S,w,f,E),S.targetIndex=S.route.length>1?1:S.route.length,S.scannerId=null,S.nextScannerId=null,S.pendingScannerId=null,S.queueRoute=null,S.queueIndex=-1;let D=b?p.green:f==="left"?p.mixerBlue:p.truckPink;return Ii(e,pe(w).x,pe(w).y,D),W(e,S.x,S.y-20,b?"AUTO":f.toUpperCase(),D),!0}function vt(u){let f=e.chicks[u];return f?(e.chicks.splice(u,1),f):null}function ro(u,f=e.facilities.mixer){if(f?.processingCooldown>0){let D=e.chicks[u];D&&(D.stoppedTimer=.25);return}let b=vt(u);if(!b)return;let{x:S,y:w}=b;if(As(e),Qo(e,f),Jo(e,f),b.sex==="poop"){let D=Ci(e);Zn(e,"mixer"),ht(e),Bi(e,S,w),W(e,S,w-18,`-${M(D)}`,p.danger);return}let E=xi(e);b.sex==="male"?zt(e):ht(e),Fi(e,S,w),W(e,S,w-18,`+${M(E)}`,p.green)}function bn(u,f=e.facilities.truck){let b=vt(u);if(!b)return;let{x:S,y:w}=b;vn(b.sex,f),Oi(e,S,w,b.sex),$s(e,b.sex);let E=je(e),D=yi(e,b.sex);if(b.sex==="poop"){if(Zn(e,"truck"),D)zt(e),W(e,S,w-18,`+${M($e(e))}`,p.green);else{let K=Mi(e);ht(e),W(e,S,w-18,`-${M(K)}`,p.danger)}return}if(b.sex==="female"){D?(zt(e),W(e,S,w-18,`+${M($e(e))}`,p.green)):(ht(e),W(e,S,w-18,E==="male"?"REJECT":"NO SALE",p.warn));return}if(D){zt(e),W(e,S,w-18,`+${M($e(e))}`,p.green);return}if(hi(e)){let K=gi(e);ht(e),W(e,S,w-18,`-${M(K)}`,p.danger)}else ht(e),W(e,S,w-18,"REJECT",p.warn)}function io(u,f=e.facilities.trash){if(f?.processingCooldown>0){let K=e.chicks[u];K&&(K.stoppedTimer=.25);return}let b=vt(u);if(!b)return;let{x:S,y:w}=b;Li(e,S,w,b.sex),Ds(e),Qo(e,f),Jo(e,f);let E={amount:0},D="";if(b.sex==="poop"){E=wi(e),D=E.amount>0?` +${M(E.amount)}`:"",Zn(e,"trash"),zt(e);let K=Math.ceil(Math.max(0,Number(e.cardEffects?.composter)||0)*3*Fn(e));if(K>0){let ee=Ne(e,K);e.stats.composterIncome=(e.stats.composterIncome||0)+ee,e.totals.composterIncome=(e.totals.composterIncome||0)+ee,W(e,S,w-36,`COMPOST +${M(ee)}`,p.green)}W(e,S,w-18,`CLEAN${D}`,E.amount>0?p.green:p.green)}else ht(e),W(e,S,w-18,E.amount>0?`WASTE${D}`:"WASTE",E.amount>0?p.green:p.ink)}function Ot(u,f){let b=vt(u);b&&W(e,b.x,b.y-12,f,p.muted)}function vn(u,f=e.facilities.truck){let b=f||e.facilities.truck;b&&(e.truckCargo.push({sex:u,x:G(22,b.w-22),y:G(66,b.h-24)}),e.truckCargo.length>45&&e.truckCargo.shift())}function Nt(u){let f=We(u.x,u.y);if(f){let E=I(f.col,f.row);if(e.conveyorTiles.has(E))return E}let b=ti(e,u.x,u.y);if(!b)return null;let S=Q(b),w=F(S.col,S.row);return Math.hypot(u.x-w.x,u.y-w.y)<=y.cell*.55?b:null}function Jt(){let{components:u,cellToComponent:f}=ei(e);for(let b of e.chicks){if(b.stage==="flying")continue;let S=Nt(b);if(!S)continue;let w=f.get(S),E=u.get(w);E&&(E.count+=1)}for(let b of u.values())b.ratio=b.count/b.capacity;e.congestion=u,e.componentLookup=f}function so(){for(let u of e.congestion.values()){let f=Fo(e),b=mi(e);if(u.ratio>b&&u.ratio=f){let S=jt(u.id);if(!S.length||S.some(D=>D.stage!=="queued"&&D.stoppedTimer<=.2))continue;let w=e.lastExplodedComponent.get(u.id)||0,E=performance.now();E-w>900&&(e.lastExplodedComponent.set(u.id,E),wn(u))}}}function jt(u){return e.chicks.filter(f=>{let b=Nt(f);return b&&e.componentLookup?.get(b)===u})}function wn(u){let f=jt(u.id);if(!f.length)return;for(let w of f)Go(e,w.sex,w.x,w.y);e.chicks=e.chicks.filter(w=>!f.some(E=>E.id===w.id));for(let w of e.scanners)w.queue=w.queue.filter(E=>e.chicks.some(D=>D.id===E));for(let w of u.cells){let E=Q(w),D=F(E.col,E.row);Ve(e,D.x,D.y,p.danger),Ze(e,D.x,D.y,6),On(e,D.x,D.y,4)}It(e,18,.75);let b=Q(u.cells[0]),S=F(b.col,b.row);e.stats.explosions=(e.stats.explosions||0)+1,e.totals.explosions=(e.totals.explosions||0)+1,W(e,S.x,S.y-22,`${Math.round(Fo(e)*100)}% JAM EXPLOSION`,p.danger)}return{activeQueuedChick:ge,currentSpawnDelay:o,sortSlot:Le,updateCongestion:Jt,sortScanner:it,updateRunning:v}}var ae=document.getElementById("gameCanvas"),nc=ae.getContext("2d"),B={shell:document.getElementById("gameShell"),money:document.getElementById("money"),turn:document.getElementById("turn"),timeLeft:document.getElementById("timeLeft"),phase:document.getElementById("phaseLabel"),comboCount:document.getElementById("comboCount"),eventBrief:document.getElementById("eventBrief"),targetBrief:document.getElementById("targetBrief"),speedBrief:document.getElementById("speedBrief"),turnProfit:document.getElementById("turnProfit"),mixerCount:document.getElementById("mixerCount"),truckFemaleCount:document.getElementById("truckFemaleCount"),truckMaleCount:document.getElementById("truckMaleCount"),poopCount:document.getElementById("poopCount"),buildStatus:document.getElementById("buildStatus"),turnSummary:document.getElementById("turnSummary"),eventPanel:document.getElementById("eventPanel"),modal:document.getElementById("modal"),modalTitle:document.getElementById("modalTitle"),modalBody:document.getElementById("modalBody"),modalActions:document.getElementById("modalActions"),hoverTooltip:document.getElementById("hoverTooltip"),manualScannerMonitor:document.getElementById("manualScannerMonitor"),hireRepairmanButton:document.getElementById("hireRepairmanButton"),debug:{panel:document.getElementById("debugPanel"),infiniteCash:document.getElementById("debugInfiniteCash"),dayInput:document.getElementById("debugDayInput"),setDay:document.getElementById("debugSetDayButton"),zeroTimer:document.getElementById("debugZeroTimerButton"),cardSelect:document.getElementById("debugCardSelect"),targetSelect:document.getElementById("debugTargetSelect"),grantCard:document.getElementById("debugGrantCardButton"),grantAllCards:document.getElementById("debugGrantAllCardsButton"),readout:document.getElementById("debugReadout")},buttons:{s1Left:document.getElementById("scanner1MixerButton"),s1Right:document.getElementById("scanner1TruckButton"),s2Left:document.getElementById("scanner2MixerButton"),s2Right:document.getElementById("scanner2TruckButton"),nextTurn:document.getElementById("nextTurnButton"),conveyor:document.getElementById("buildConveyorButton"),boostConveyor:document.getElementById("buildBoostConveyorButton"),eggFarm:document.getElementById("buildEggFarmButton"),autoScanner:document.getElementById("buildAutoScannerButton"),manualScanner:document.getElementById("buildManualScannerButton"),mixer:document.getElementById("buildMixerButton"),trash:document.getElementById("buildTrashButton"),truck:document.getElementById("buildTruckButton"),erase:document.getElementById("eraseButton"),undo:document.getElementById("undoButton"),redo:document.getElementById("redoButton")}};function oc(){let e={conveyor:"conveyor",boostConveyor:"boostConveyor",eggFarm:"eggFarm",autoScanner:"autoScanner",manualScanner:"manualScanner",mixer:"mixer",trash:"trash",truck:"truck"};for(let[t,n]of Object.entries(e))B.buttons[t]&&(B.buttons[t].innerHTML=Pr(n))}function rc(e){let t=new Set(e.tags||[]);return["upgradeEgg","crowdedFarming","hatchingFeed","extraEggOutlet"].includes(e.id)||t.has("EGG")?"Production / EGG":["upgradeTrash","poopRateBooster","composter","chemicalWeaponSubsidy"].includes(e.id)||t.has("POOP")?"Poop / Shredder":["upgradeAutoScanner","autoScannerTuning","scannerQueueSpacing"].includes(e.id)||t.has("SCANNER")?"Scanner":["bearing","dynamite"].includes(e.id)||t.has("CONVEYOR")?"Conveyor / Map":["safetyCover","preventiveMaintenance","durabilityCoating","sparePartsBin","laborExploitation"].includes(e.id)||t.has("MAINTENANCE")?"Maintenance / Risk":["dudFilter","dudRefund","freeReroll","extraCards"].includes(e.id)||t.has("CARD")?"Card Engine":t.has("ULTRA RARE")?"Ultra Rare":t.has("ECONOMY")||["upgradeMixer","upgradeTruck","recyclingSubsidy","usedMachine","newMachine","flattery","legalWork","rescueLoan"].includes(e.id)?"Economy / Shipment":"Other"}function ic(){if(!B.debug?.panel||!B.debug.cardSelect)return;let e=["Production / EGG","Poop / Shredder","Scanner","Conveyor / Map","Maintenance / Risk","Card Engine","Economy / Shipment","Ultra Rare","Other"],t=new Map(e.map(n=>[n,[]]));for(let n of Yt){let o=rc(n);t.has(o)||t.set(o,[]),t.get(o).push(n)}B.debug.cardSelect.innerHTML="";for(let n of e){let o=t.get(n)||[];if(!o.length)continue;let r=document.createElement("optgroup");r.label=n;for(let s of o){let l=document.createElement("option");l.value=s.id;let d=s.rarity==="ultraRare"?"UR":s.rarity==="rare"?"R":"C";l.textContent=`[${d}] ${s.title}`,r.appendChild(l)}B.debug.cardSelect.appendChild(r)}B.debug.cardSelect.addEventListener("change",Bt),Bt()}function Bt(){if(!B.debug?.targetSelect)return;let e=B.debug.cardSelect?.value,t=Vt(e),n=t?as(a,t):[];if(B.debug.targetSelect.innerHTML="",!n.length){let r=document.createElement("option");r.value="__none__",r.textContent=t?"No target required":"No card selected",B.debug.targetSelect.appendChild(r),B.debug.targetSelect.disabled=!0;return}let o=document.createElement("option");o.value="__auto__",o.textContent=t?.id==="dynamite"?"Auto: first 3 blocked cells":"Auto: first valid target",B.debug.targetSelect.appendChild(o);for(let r of n){let s=document.createElement("option");s.value=r.key,s.textContent=r.label,B.debug.targetSelect.appendChild(s)}B.debug.targetSelect.disabled=!1}function sc(){let e=Math.max(1,Math.floor(Number(B.debug.dayInput?.value)||1));a.turn=e,B.debug.dayInput&&(B.debug.dayInput.value=String(e)),W(a,ae.width/2-a.view.x,86-a.view.y,`DAY ${e}`,p.green),H.updatePanels(),H.updateUI(),Bt(),Lt(`Day set to ${e}.`)}function lc(){a.timeLeft=0,a.phase==="running"&&_s(),W(a,ae.width/2-a.view.x,86-a.view.y,"TIMER 0",p.warn),H.updatePanels(),H.updateUI(),Lt("Timer set to 0.")}function ac(){let e=B.debug.cardSelect?.value,t=B.debug.targetSelect?.disabled?void 0:B.debug.targetSelect?.value,n=er(a,e,{targetKey:t});B.debug.grantCard&&(B.debug.grantCard.textContent=n.ok?"Granted":"Failed",window.setTimeout(()=>{B.debug.grantCard&&(B.debug.grantCard.textContent="Grant Selected")},900)),Me?.updateCongestion?.(),H.updatePanels(),H.updateUI(),Bt(),Lt(n.reason)}function cc(){let t=Yt.map(n=>er(a,n,{targetKey:"__auto__"})).filter(n=>n.ok).length;Me?.updateCongestion?.(),H.updatePanels(),H.updateUI(),Bt(),Lt(`Granted ${t}/${Yt.length} cards.`)}function uc(){B.debug?.infiniteCash?.checked&&a.cash<999999&&(a.cash=999999,a.totals.maxCash=Math.max(a.totals.maxCash,a.cash))}function Lt(e=""){B.debug?.readout&&(B.debug.readout.textContent=[e,`D${a.turn}`,M(a.cash),`Combo ${a.manualCombo?.count||0}`,`Event ${a.eventActive?.title||a.eventOffer?.title||"none"}`,`Rescue ${a.cardEffects?.rescueLoanCharges||0}`,`Chem ${a.cardEffects?.chemicalWeaponSubsidy||0}`].filter(Boolean).join(" | "))}var a=ko(),Y,H,Me,Qt;function dc(e=null){let t=zn(a,e);return e?t*qo(a,e):t}function fc(){Object.assign(a,ko()),a.phase="running",a.view={x:0,y:0,scale:1},xo(a),Us(),me(a),H.hideModal(),Me.updateCongestion(),H.updatePanels(),H.updateUI(),Lt()}function pc(){if(a.phase!=="build")return;if(a.cardDraft?.pending||a.cardTargetPick?.pending){Y.fail(a.cardTargetPick?.pending?"Choose upgrade target first.":"Choose an upgrade card first."),H.updatePanels();return}let e=sn(a);if(e.length){Y.fail(`Cannot start: ${e[0]}`),H.updatePanels();return}me(a),Zr(a),Xi(a);let t=Math.max(0,Math.floor(a.lastResult?.profit??a.stats?.profit??0)),n=Pi(a,Math.max(1,a.turn||1),t);a.lastStartFees={fairiesTribute:n.amount||0,tribute:n},n.amount>0&&W(a,ae.width/2-a.view.x,116-a.view.y,`FAIRIES -${M(n.amount)}`,p.danger),ci(a),a.phase="running",a.turn+=1,a.timeLeft=di(a),a.shutdownTimeLeft=0,a.cleanupTimer=null,a.cleanupBlown=!1,a.chicks=[],a.effects=[],a.floatingTexts=[],a.shake={time:0,strength:0},a.truckCargo=[],Us(),a.stats=So(),a.stats.fairiesTribute=a.lastStartFees?.fairiesTribute||0,a.stats.repairWorkerWages=a.pendingRepairWorkerWages||0;let o=a.stats.fairiesTribute+a.stats.repairWorkerWages;o>0&&(a.stats.penalty+=o,a.stats.profit-=o),a.pendingRepairWorkerWages=0;for(let r of a.scanners)r.queue=[],r.cooldown=0;for(let r of a.eggFarms)r.nextSpawn=Me.currentSpawnDelay(r),r.lastInterval=r.nextSpawn,r.shutterProgress=0,r.shutterSparked=!1;a.buildTool=null,a.selected=null,a.groupDrag=null,a.selectionBox=null,a.pan=null,Me.updateCongestion(),H.updatePanels(),H.updateUI()}function yc(){me(a);let e=zi(a);e.ok?W(a,ae.width/2-a.view.x,96-a.view.y,`Repairman hired -${M(e.cost)}`,p.green):(W(a,ae.width/2-a.view.x,96-a.view.y,e.reason||"Cannot hire repairman.",p.danger),Y?.fail?.(e.reason||"Cannot hire repairman.")),H.updatePanels(),H.updateUI()}function hc(){if(a.phase!=="running")return;let e=Ei(a),t=a.eventActive?{...a.eventActive}:null,n=vi(a),o=Ri(a);if(e.adjusted>0){let s=a.facilities.truck,l=s?s.x+s.w/2:ae.width/2-a.view.x,d=s?s.y+26:96-a.view.y;W(a,l,d,`${e.target==="poop"?"POOP SHIP":"SHIP"} +${M(e.adjusted)}`,p.green)}n?.bonus>0&&W(a,ae.width/2-a.view.x,96-a.view.y,`EVENT +${M(n.bonus)}`,p.green),o.amount>0&&W(a,ae.width/2-a.view.x,116-a.view.y,`CHEM SUBSIDY +${M(o.amount)}`,p.green),ui(a),a.totals.turnsCompleted+=1;let r=bi(t);if(r!==1&&(a.pendingFairiesTributeMultiplier=r),a.lastResult={...a.stats,ship:e,event:n,chemical:o,rescue:{amount:0,used:0,remaining:a.cardEffects?.rescueLoanCharges||0},fairiesTribute:{amount:a.stats.fairiesTribute||0},tributeMultiplier:r,turn:a.turn,cash:a.cash},a.cash<0){if((a.cardEffects?.rescueLoanCharges||0)>0){a.phase="loanDecision",H.showEmergencyLoanDecision(Ns,eo);return}a.phase="gameover",H.showGameOver();return}Os()}function Os(){a.phase="build",a.truckCargo=[],a.chicks=[],a.shutdownTimeLeft=0,a.cleanupTimer=null,a.cleanupBlown=!1,a.buildSession+=1,a.undoStack=[],a.redoStack=[],a.timeLeft=0;for(let e of a.scanners)e.queue=[];for(let e of a.eggFarms)e.shutterProgress=0,e.shutterSparked=!1;Qi(a),a.eventOffer=ai(a),Qt&&Qt.prepareDraft(),a.cardTargetPick=null,a.buildTool=null,a.groupDrag=null,a.selectionBox=null,a.pan=null,H.updatePanels(),H.showTurnResult(a.lastResult)}function Ns(){if((a.cardEffects?.rescueLoanCharges||0)<=0)return eo();a.cardEffects.rescueLoanCharges-=1,a.stats.rescueLoan=(a.stats.rescueLoan||0)+500,a.totals.rescueLoan=(a.totals.rescueLoan||0)+500;let e=Ne(a,500);a.lastResult={...a.lastResult||{},...a.stats,rescue:{amount:(a.lastResult?.rescue?.amount||0)+e,used:(a.lastResult?.rescue?.used||0)+1,remaining:a.cardEffects.rescueLoanCharges},cash:a.cash},W(a,ae.width/2-a.view.x,176-a.view.y,`RESCUE +${M(e)}`,p.green),a.cash>=0?Os():(a.cardEffects?.rescueLoanCharges||0)>0?(a.phase="loanDecision",H.showEmergencyLoanDecision(Ns,eo)):eo()}function eo(){a.phase="gameover",H.showGameOver()}function _s(){a.shutdownTimeLeft<=0&&(a.shutdownTimeLeft=a.shutdownGraceSeconds||10);for(let e of a.eggFarms){if(e.shutterSparked)continue;e.shutterProgress=.02,e.shutterSparked=!0;let t=F(e.col,e.row);Ve(a,t.x,t.y,p.ink),Ze(a,t.x,t.y+10,10),W(a,t.x,t.y-34,"SHUT +10s",p.ink)}}function Gs(e){a.lastTimestamp||(a.lastTimestamp=e);let t=Math.min((e-a.lastTimestamp)/1e3,.05);a.lastTimestamp=e,a.phase==="running"&&Me.updateRunning(t,{closeFarmShutters:_s,completeTurn:hc}),_i(a,t,ae,Y.equipmentHitBoxes),Me.updateCongestion(),hs(nc,ae,a,{activeQueuedChick:Me.activeQueuedChick,selectedObject:Y.selectedObject,selectedTitle:Y.selectedTitle}),uc(),H.updateUI(),Ks(),Lt(),requestAnimationFrame(Gs)}function to(){return a.view?.scale||1}function pn(){a.view||(a.view={x:0,y:0,scale:1}),a.view.scale==null&&(a.view.scale=1)}function no(e){let t=ae.getBoundingClientRect();return{x:(e.clientX-t.left)*ae.width/t.width,y:(e.clientY-t.top)*ae.height/t.height}}function mt(e){let t=no(e),n=to();return{x:(t.x-(a.view?.x||0))/n,y:(t.y-(a.view?.y||0))/n}}function mc(e){let t=to();return{x:e.x*t+(a.view?.x||0),y:e.y*t+(a.view?.y||0)}}function bc(){let e={left:y.x-90,top:y.y-130,right:y.x+y.cols*y.cell+260,bottom:y.y+y.rows*y.cell+220};if(a.phase==="build")for(let t of Ct(a)){let n=Mt(t);e.left=Math.min(e.left,n.x-60),e.top=Math.min(e.top,n.y-80),e.right=Math.max(e.right,n.x+n.w+80),e.bottom=Math.max(e.bottom,n.y+n.h+80)}return e}function Fs(e,t){if(e<=t)return[e,t];let n=(e+t)/2;return[n,n]}function bt(){pn();let e=to(),t=bc(),[n,o]=Fs(ae.width-160-t.right*e,110-t.left*e),[r,s]=Fs(ae.height-150-t.bottom*e,150-t.top*e);a.view.x=on(a.view.x,n,o),a.view.y=on(a.view.y,r,s)}function Us(){pn(),a.view.scale=1;let e=a.eggFarms?.[0],t=e?F(e.col,e.row):{x:y.x,y:y.y};a.view.x=280-t.x,a.view.y=190-t.y,bt()}function vc(e){let t=no(e);pn(),a.pan={start:t,viewX:a.view.x,viewY:a.view.y,moved:!1}}function wc(e){if(!a.pan)return;let t=no(e);Math.hypot(t.x-a.pan.start.x,t.y-a.pan.start.y)>5&&(a.pan.moved=!0),pn(),a.view.x=a.pan.viewX+t.x-a.pan.start.x,a.view.y=a.pan.viewY+t.y-a.pan.start.y,bt()}function Sc(e){e.preventDefault(),pn();let t=no(e),n=mt(e),o=Math.exp(-e.deltaY*.0012),r=on(to()*o,.55,1.8);a.view.scale=r,a.view.x=t.x-n.x*r,a.view.y=t.y-n.y*r,bt(),ot()}function kc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:{type:e.type,id:e.ref.id}:null}function xc(e){return e?e.type==="conveyor"?{type:"conveyor",id:e.oldKey}:e.ref||null:null}function ot(){B.hoverTooltip&&(B.hoverTooltip.classList.remove("visible"),B.hoverTooltip.setAttribute("aria-hidden","true"),a.hover=null)}function Cc(e,t){if(!B.hoverTooltip||a.phase!=="build"||a.cardTargetPick?.pending||a.groupDrag||a.selectionBox||a.pan)return ot();let n=xc(t);if(!n)return ot();let o=Y.selectedTitle(n),r=Y.flavorText?Y.flavorText(n):"",s=Y.disconnectedWarningFor?Y.disconnectedWarningFor(n):"",l=Y.selectedInfoLines(n).slice(0,7);B.hoverTooltip.innerHTML=`${o}${s?`${s}`:r?`${r}`:""}${l.map(C=>`${C}`).join("")}`;let d=Math.min(window.innerWidth-330,e.clientX+18),v=Math.min(window.innerHeight-220,e.clientY+18);B.hoverTooltip.style.left=`${Math.max(8,d)}px`,B.hoverTooltip.style.top=`${Math.max(8,v)}px`,B.hoverTooltip.classList.add("visible"),B.hoverTooltip.setAttribute("aria-hidden","false"),a.hover={type:t.type,id:t.oldKey||t.ref?.id||null}}function Mc(e){if(a.phase!=="build")return ot();Cc(e,Y.equipmentAtPoint(mt(e)))}function Ws(e){ot();let t=mt(e),n=Y.equipmentAtPoint(t),o=kc(n);if(!o){a.selected=null,a.multiSelected=[],H.updatePanels();return}a.selected=o,a.multiSelected=[o],H.updatePanels();let r=Y.selectedObject();r?.type==="scanner"&&r.kind==="manual"&&Y.showManualScannerMenu(r),r?.type==="scanner"&&r.kind==="auto"&&Y.showAutoScannerMenu(r)}function Xt(){a.buildTool=null,a.selected=null,a.multiSelected=[],a.selectionBox=null,a.cardTargetPick?.mode==="autoScannerMenu"&&(a.cardTargetPick=null),H.hideModal(),ot(),H.updatePanels(),H.updateUI()}function Bs(e){return String(e).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function gc(e){let t=e?.queue?.[0];return t==null?null:a.chicks.find(n=>n.id===t)||null}function Tc(e){if(!e)return'WAIT';let t=e.sex==="poop"?"\u{1F4A9} POOP":e.sex==="male"?"\u2642 MALE":"\u2640 FEMALE";return`${t}`}function Ec(e,t){let n=new Set(a.eggFarms.map(P=>I(P.col,P.row))),o=new Map(a.scanners.map(P=>[I(P.col,P.row),P])),r=Pe(e,"inputA"),s=r?I(r.col,r.row):null,l=new Set(Object.values(a.facilities||{}).map(P=>P.entry?I(P.entry.col,P.entry.row):null).filter(Boolean)),d=t?.sex||"",v=d==="poop"?"\u{1F4A9}":d==="male"?"\u2642":d==="female"?"\u2640":"",C=[];for(let P=e.row-2;P<=e.row+2;P+=1)for(let R=e.col-2;R<=e.col+2;R+=1){let L=I(R,P),V=["mini-cell"],te="";R===e.col&&P===e.row?(V.push("scanner"),d&&V.push(d),te=v||"S"):L===s?(V.push("input"),te="IN"):n.has(L)?(V.push("egg"),te="E"):o.has(L)?(V.push("scanner-other"),te="S"):l.has(L)?(V.push("port"),te="P"):a.conveyorTiles.has(L)?(V.push("belt"),te="\u2022"):a.blockedCells?.has?.(L)&&(V.push("blocked"),te="\xD7"),C.push(`${te}`)}return`
${C.join("")}
`}function Pc(e){let t=mc(F(e.col,e.row)),n=76;return t.x<-n||t.y<-n||t.x>ae.width+n||t.y>ae.height+n}function Ks(){if(!B.manualScannerMonitor)return;if(a.phase!=="running"){B.manualScannerMonitor.classList.remove("visible"),B.manualScannerMonitor.innerHTML="";return}let e=a.scanners.filter(t=>t.kind==="manual"&&Pc(t));if(!e.length){B.manualScannerMonitor.classList.remove("visible"),B.manualScannerMonitor.innerHTML="";return}B.manualScannerMonitor.innerHTML=e.map(t=>{let n=gc(t),o=t.keys?.left?.label||(t.slot===0?"A":"Left"),r=t.keys?.right?.label||(t.slot===0?"D":"Right"),s=t.role===0?"MIXER":"WASTE",l=t.role===0?"S2":"TRUCK",d=n?"":" disabled";return`
S${(t.slot??0)+1}OFFSCREEN / Q:${t.queue.length}
- IN${Mc(n)}SCANNER + IN${Tc(n)}SCANNER
- ${gc(t,n)} + ${Ec(t,n)}
- - + +
-
`}).join(""),B.manualScannerMonitor.classList.add("visible")}B.manualScannerMonitor?.addEventListener("click",e=>{let t=e.target.closest("button[data-scanner-id]");if(!t||t.disabled)return;let n=a.scanners.find(o=>o.id===Number(t.dataset.scannerId));n&&(Ce.sortScanner(n,t.dataset.side),_s())});ae.addEventListener("contextmenu",e=>e.preventDefault());ae.addEventListener("wheel",vc,{passive:!1});ae.addEventListener("pointerdown",e=>{if(a.phase!=="build")return;ae.setPointerCapture(e.pointerId);let t=ht(e);if(e.button===2){mc(e);return}if(e.button!==0)return;if(a.cardTargetPick?.mode==="autoScannerMenu"){Xt();return}if(a.cardTargetPick?.pending){Qt.chooseTargetAtPoint(t);return}let n=Y.expansionOfferAtPoint?.(t);if(n){Y.buyGridExpansion(n),mt(),H.updatePanels(),H.updateUI();return}if(Y.cycleBranchModeAtPoint?.(t)){H.updatePanels(),H.updateUI();return}let o=We(t.x,t.y),r=Y.equipmentAtPoint(t);if(!a.buildTool&&r?.type==="conveyor"&&o&&Y.cycleSingleConveyorDirection?.(o)){H.updatePanels(),H.updateUI();return}if(a.buildTool==="erase"){if(!Y.equipmentAtPoint(t)){Xt();return}Y.eraseAtPoint(t);return}if(a.buildTool){let s=We(t.x,t.y);if(!s&&!["mixer","trash","truck"].includes(a.buildTool)){Xt();return}if(a.buildTool==="conveyor"||a.buildTool==="boostConveyor"){Y.beginConveyorDrag(s);return}if(Y.equipmentAtPoint(t)){a.buildTool=null,Ws(e);return}Y.buildAtPoint(t);return}Y.startGroupDrag(e)||Y.startSelectionBox(e)});ae.addEventListener("pointermove",e=>{if(a.phase!=="build"){nt();return}kc(e),a.pan&&e.buttons&2&&bc(e),a.groupDrag&&e.buttons&1&&Y.updateGroupDrag(e),a.selectionBox&&e.buttons&1&&Y.updateSelectionBox(e),(a.buildTool==="conveyor"||a.buildTool==="boostConveyor")&&e.buttons&1&&Y.continueConveyorDrag(We(ht(e).x,ht(e).y)),a.buildTool==="erase"&&e.buttons&1&&Y.eraseAtPoint(ht(e))});ae.addEventListener("pointerup",e=>{a.selectionBox?Y.finishSelectionBox():a.groupDrag&&(a.groupDrag.committed||Ws(e),Y.finishGroupDrag()),e.button===2&&a.pan&&!a.pan.moved&&a.buildTool&&Xt(),(a.buildTool==="conveyor"||a.buildTool==="boostConveyor")&&Y.endConveyorDrag?.(),a.groupDrag=null,a.pan=null;try{ae.releasePointerCapture(e.pointerId)}catch{}});ae.addEventListener("pointerleave",nt);ae.addEventListener("pointercancel",()=>{Y?.endConveyorDrag?.(),a.groupDrag=null,a.selectionBox=null,a.pan=null,nt()});document.addEventListener("pointerdown",e=>{!B.modal.classList.contains("visible")||!B.modal.classList.contains("equipment-popover")||e.target.closest("#modal .modal-card")||Xt()},!0);B.buttons.s1Left.addEventListener("click",()=>Ce.sortSlot(0,"left"));B.buttons.s1Right.addEventListener("click",()=>Ce.sortSlot(0,"right"));B.buttons.s2Left.addEventListener("click",()=>Ce.sortSlot(1,"left"));B.buttons.s2Right.addEventListener("click",()=>Ce.sortSlot(1,"right"));B.buttons.nextTurn.addEventListener("click",dc);B.buttons.conveyor.addEventListener("click",()=>Y.setBuildTool("conveyor"));B.buttons.boostConveyor.addEventListener("click",()=>Y.setBuildTool("boostConveyor"));B.buttons.eggFarm.addEventListener("click",()=>Y.setBuildTool("eggFarm"));B.buttons.autoScanner.addEventListener("click",()=>Y.setBuildTool("autoScanner"));B.buttons.manualScanner.addEventListener("click",()=>Y.setBuildTool("manualScanner"));B.buttons.mixer.addEventListener("click",()=>Y.setBuildTool("mixer"));B.buttons.trash.addEventListener("click",()=>Y.setBuildTool("trash"));B.buttons.truck.addEventListener("click",()=>Y.setBuildTool("truck"));B.buttons.erase.addEventListener("click",()=>Y.setBuildTool("erase"));B.hireRepairmanButton?.addEventListener("click",fc);B.debug.setDay?.addEventListener("click",rc);B.debug.zeroTimer?.addEventListener("click",ic);B.debug.grantCard?.addEventListener("click",sc);B.debug.grantAllCards?.addEventListener("click",lc);B.buttons.undo.addEventListener("click",()=>{Lo(a)&&(mt(),H.updatePanels(),H.updateUI(),Bt())});B.buttons.redo.addEventListener("click",()=>{Oo(a)&&(mt(),H.updatePanels(),H.updateUI(),Bt())});function Bs(e,t,n){let o=e.keys?.[t];return o?o.code&&n.code===o.code||o.key&&n.key.toLowerCase()===o.key:!1}window.addEventListener("keydown",e=>{if(e.repeat)return;let t=e.key.toLowerCase();if(a.phase==="running")for(let n of a.scanners.filter(o=>o.kind==="manual")){if(Bs(n,"left",e)){e.preventDefault(),Ce.sortScanner(n,"left");return}if(Bs(n,"right",e)){e.preventDefault(),Ce.sortScanner(n,"right");return}}a.phase==="build"&&(e.ctrlKey||e.metaKey)&&t==="z"&&(e.preventDefault(),Lo(a)&&(mt(),H.updatePanels(),H.updateUI())),a.phase==="build"&&(e.ctrlKey||e.metaKey)&&(t==="y"||e.shiftKey&&t==="z")&&(e.preventDefault(),Oo(a)&&(mt(),H.updatePanels(),H.updateUI())),e.key==="Escape"&&a.cardTargetPick?.pending&&(e.preventDefault(),a.cardTargetPick.mode==="autoScannerMenu"?Xt():Qt.cancelTargetPick())});Y=gs({game:a,ui:B,canvas:ae,canvasPoint:ht,onUpdatePanels:()=>H?.updatePanels()});Ce=Is({game:a,currentConveyorSpeed:cc,onGameOverCheck:()=>H?.checkGameOver()});Qt=ds({game:a,ui:B,onUpdatePanels:()=>H?.updatePanels()});H=Ts({game:a,ui:B,build:Y,startGame:uc,beginCardDraft:()=>Qt.showDraft(),activeQueuedChick:Ce.activeQueuedChick});tc();oc();So(a);me(a);Ce.updateCongestion();H.updatePanels();H.updateUI();H.showTitle();Lt();requestAnimationFrame(Gs); + `}).join(""),B.manualScannerMonitor.classList.add("visible")}B.manualScannerMonitor?.addEventListener("click",e=>{let t=e.target.closest("button[data-scanner-id]");if(!t||t.disabled)return;let n=a.scanners.find(o=>o.id===Number(t.dataset.scannerId));n&&(Me.sortScanner(n,t.dataset.side),Ks())});ae.addEventListener("contextmenu",e=>e.preventDefault());ae.addEventListener("wheel",Sc,{passive:!1});ae.addEventListener("pointerdown",e=>{if(a.phase!=="build")return;ae.setPointerCapture(e.pointerId);let t=mt(e);if(e.button===2){vc(e);return}if(e.button!==0)return;if(a.cardTargetPick?.mode==="autoScannerMenu"){Xt();return}if(a.cardTargetPick?.pending){Qt.chooseTargetAtPoint(t);return}let n=Y.expansionOfferAtPoint?.(t);if(n){Y.buyGridExpansion(n),bt(),H.updatePanels(),H.updateUI();return}if(Y.cycleBranchModeAtPoint?.(t)){H.updatePanels(),H.updateUI();return}let o=We(t.x,t.y),r=Y.equipmentAtPoint(t);if(!a.buildTool&&r?.type==="conveyor"&&o&&Y.cycleSingleConveyorDirection?.(o)){H.updatePanels(),H.updateUI();return}if(a.buildTool==="erase"){if(!Y.equipmentAtPoint(t)){Xt();return}Y.eraseAtPoint(t);return}if(a.buildTool){let s=We(t.x,t.y);if(!s&&!["mixer","trash","truck"].includes(a.buildTool)){Xt();return}if(a.buildTool==="conveyor"||a.buildTool==="boostConveyor"){Y.beginConveyorDrag(s);return}if(Y.equipmentAtPoint(t)){a.buildTool=null,Ws(e);return}Y.buildAtPoint(t);return}Y.startGroupDrag(e)||Y.startSelectionBox(e)});ae.addEventListener("pointermove",e=>{if(a.phase!=="build"){ot();return}Mc(e),a.pan&&e.buttons&2&&wc(e),a.groupDrag&&e.buttons&1&&Y.updateGroupDrag(e),a.selectionBox&&e.buttons&1&&Y.updateSelectionBox(e),(a.buildTool==="conveyor"||a.buildTool==="boostConveyor")&&e.buttons&1&&Y.continueConveyorDrag(We(mt(e).x,mt(e).y)),a.buildTool==="erase"&&e.buttons&1&&Y.eraseAtPoint(mt(e))});ae.addEventListener("pointerup",e=>{a.selectionBox?Y.finishSelectionBox():a.groupDrag&&(a.groupDrag.committed||Ws(e),Y.finishGroupDrag()),e.button===2&&a.pan&&!a.pan.moved&&a.buildTool&&Xt(),(a.buildTool==="conveyor"||a.buildTool==="boostConveyor")&&Y.endConveyorDrag?.(),a.groupDrag=null,a.pan=null;try{ae.releasePointerCapture(e.pointerId)}catch{}});ae.addEventListener("pointerleave",ot);ae.addEventListener("pointercancel",()=>{Y?.endConveyorDrag?.(),a.groupDrag=null,a.selectionBox=null,a.pan=null,ot()});document.addEventListener("pointerdown",e=>{!B.modal.classList.contains("visible")||!B.modal.classList.contains("equipment-popover")||e.target.closest("#modal .modal-card")||Xt()},!0);B.buttons.s1Left.addEventListener("click",()=>Me.sortSlot(0,"left"));B.buttons.s1Right.addEventListener("click",()=>Me.sortSlot(0,"right"));B.buttons.s2Left.addEventListener("click",()=>Me.sortSlot(1,"left"));B.buttons.s2Right.addEventListener("click",()=>Me.sortSlot(1,"right"));B.buttons.nextTurn.addEventListener("click",pc);B.buttons.conveyor.addEventListener("click",()=>Y.setBuildTool("conveyor"));B.buttons.boostConveyor.addEventListener("click",()=>Y.setBuildTool("boostConveyor"));B.buttons.eggFarm.addEventListener("click",()=>Y.setBuildTool("eggFarm"));B.buttons.autoScanner.addEventListener("click",()=>Y.setBuildTool("autoScanner"));B.buttons.manualScanner.addEventListener("click",()=>Y.setBuildTool("manualScanner"));B.buttons.mixer.addEventListener("click",()=>Y.setBuildTool("mixer"));B.buttons.trash.addEventListener("click",()=>Y.setBuildTool("trash"));B.buttons.truck.addEventListener("click",()=>Y.setBuildTool("truck"));B.buttons.erase.addEventListener("click",()=>Y.setBuildTool("erase"));B.hireRepairmanButton?.addEventListener("click",yc);B.debug.setDay?.addEventListener("click",sc);B.debug.zeroTimer?.addEventListener("click",lc);B.debug.grantCard?.addEventListener("click",ac);B.debug.grantAllCards?.addEventListener("click",cc);B.buttons.undo.addEventListener("click",()=>{No(a)&&(bt(),H.updatePanels(),H.updateUI(),Bt())});B.buttons.redo.addEventListener("click",()=>{_o(a)&&(bt(),H.updatePanels(),H.updateUI(),Bt())});function Ls(e,t,n){let o=e.keys?.[t];return o?o.code&&n.code===o.code||o.key&&n.key.toLowerCase()===o.key:!1}window.addEventListener("keydown",e=>{if(e.repeat)return;let t=e.key.toLowerCase();if(a.phase==="running")for(let n of a.scanners.filter(o=>o.kind==="manual")){if(Ls(n,"left",e)){e.preventDefault(),Me.sortScanner(n,"left");return}if(Ls(n,"right",e)){e.preventDefault(),Me.sortScanner(n,"right");return}}a.phase==="build"&&(e.ctrlKey||e.metaKey)&&t==="z"&&(e.preventDefault(),No(a)&&(bt(),H.updatePanels(),H.updateUI())),a.phase==="build"&&(e.ctrlKey||e.metaKey)&&(t==="y"||e.shiftKey&&t==="z")&&(e.preventDefault(),_o(a)&&(bt(),H.updatePanels(),H.updateUI())),e.key==="Escape"&&a.cardTargetPick?.pending&&(e.preventDefault(),a.cardTargetPick.mode==="autoScannerMenu"?Xt():Qt.cancelTargetPick())});Y=Ts({game:a,ui:B,canvas:ae,canvasPoint:mt,onUpdatePanels:()=>H?.updatePanels()});Me=Is({game:a,currentConveyorSpeed:dc,onGameOverCheck:()=>H?.checkGameOver()});Qt=ds({game:a,ui:B,onUpdatePanels:()=>H?.updatePanels()});H=Es({game:a,ui:B,build:Y,startGame:fc,beginCardDraft:()=>Qt.showDraft(),activeQueuedChick:Me.activeQueuedChick});oc();ic();xo(a);me(a);Me.updateCongestion();H.updatePanels();H.updateUI();H.showTitle();Lt();requestAnimationFrame(Gs); diff --git a/index.html b/index.html index c4d8f27..ee5d73e 100644 --- a/index.html +++ b/index.html @@ -3,12 +3,16 @@ - Chick Sorter v27.14 - + + + + Chick Sorter v27.19 — Land and UI Patch +
-
+
+
v27.19 VERIFIED
@@ -17,7 +21,6 @@
NET¥0
DAY1
PHASETitle
-
COMBO0
@@ -27,16 +30,17 @@
POOP0
-
-
NO ACTIVE EVENT
-
TRUCK TARGET: FEMALE
-
BELT: 52 px/s
+
+
NO ACTIVE EVENT
+
BELT: 52 px/s
+
COMBO0
+
TRUCK TARGET: FEMALE
-

CHICK SORTER v27.14

+

CHICK SORTER v27.19

Build, expand, connect at least one valid EGG route, then start the next day.

@@ -55,7 +59,7 @@ - +
Build tools unlock after each day.
@@ -64,10 +68,6 @@

Status

-
-

Next Event

-
-
@@ -110,6 +110,6 @@ - + diff --git a/package-lock.json b/package-lock.json index 8ba8995..8035d10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "zunda-shiwake", - "version": "27.13.0", + "version": "27.19.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "zunda-shiwake", - "version": "27.13.0", + "version": "27.19.0", "devDependencies": { "esbuild": "^0.25.0" } }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", "cpu": [ "ppc64" @@ -30,7 +30,7 @@ }, "node_modules/@esbuild/android-arm": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" @@ -47,7 +47,7 @@ }, "node_modules/@esbuild/android-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ "arm64" @@ -64,7 +64,7 @@ }, "node_modules/@esbuild/android-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ "x64" @@ -81,7 +81,7 @@ }, "node_modules/@esbuild/darwin-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" @@ -98,7 +98,7 @@ }, "node_modules/@esbuild/darwin-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ "x64" @@ -114,7 +114,7 @@ }, "node_modules/@esbuild/freebsd-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ "arm64" @@ -131,7 +131,7 @@ }, "node_modules/@esbuild/freebsd-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ "x64" @@ -148,7 +148,7 @@ }, "node_modules/@esbuild/linux-arm": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ "arm" @@ -165,7 +165,7 @@ }, "node_modules/@esbuild/linux-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", "cpu": [ "arm64" @@ -182,7 +182,7 @@ }, "node_modules/@esbuild/linux-ia32": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", "cpu": [ "ia32" @@ -199,7 +199,7 @@ }, "node_modules/@esbuild/linux-loong64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", "cpu": [ "loong64" @@ -216,7 +216,7 @@ }, "node_modules/@esbuild/linux-mips64el": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", "cpu": [ "mips64el" @@ -233,7 +233,7 @@ }, "node_modules/@esbuild/linux-ppc64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", "cpu": [ "ppc64" @@ -250,7 +250,7 @@ }, "node_modules/@esbuild/linux-riscv64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", "cpu": [ "riscv64" @@ -267,7 +267,7 @@ }, "node_modules/@esbuild/linux-s390x": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" @@ -284,7 +284,7 @@ }, "node_modules/@esbuild/linux-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" @@ -301,7 +301,7 @@ }, "node_modules/@esbuild/netbsd-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", "cpu": [ "arm64" @@ -318,7 +318,7 @@ }, "node_modules/@esbuild/netbsd-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", "cpu": [ "x64" @@ -335,7 +335,7 @@ }, "node_modules/@esbuild/openbsd-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", "cpu": [ "arm64" @@ -352,7 +352,7 @@ }, "node_modules/@esbuild/openbsd-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ "x64" @@ -369,7 +369,7 @@ }, "node_modules/@esbuild/openharmony-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", "cpu": [ "arm64" @@ -386,7 +386,7 @@ }, "node_modules/@esbuild/sunos-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" @@ -403,7 +403,7 @@ }, "node_modules/@esbuild/win32-arm64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" @@ -420,7 +420,7 @@ }, "node_modules/@esbuild/win32-ia32": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" @@ -437,7 +437,7 @@ }, "node_modules/@esbuild/win32-x64": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" @@ -453,7 +453,7 @@ }, "node_modules/esbuild": { "version": "0.25.12", - "resolved": "https://packages.applied-caas-gateway1.internal.api.openai.org/artifactory/api/npm/npm-public/esbuild/-/esbuild-0.25.12.tgz", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, "hasInstallScript": true, diff --git a/package.json b/package.json index 94483f5..8ff31e7 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "zunda-shiwake", - "version": "27.14.0", + "version": "27.19.0", "private": true, "type": "module", "scripts": { "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"", - "build": "npm run clean && esbuild src/game.js --bundle --format=esm --target=es2020 --minify --outfile=dist/game.js" + "build": "npm run clean && node -e \"require('fs').copyFileSync('styles.css', 'styles-v27.19.css')\" && esbuild src/game.js --bundle --format=esm --target=es2020 --minify --outfile=dist/game-v27.19.js" }, "devDependencies": { "esbuild": "^0.25.0" diff --git a/src/core/balance.js b/src/core/balance.js index 6135bd5..58adddb 100644 --- a/src/core/balance.js +++ b/src/core/balance.js @@ -1,7 +1,7 @@ // Central balance sheet for tuning gameplay. // Edit this file first when adjusting prices, income, penalties, timing, card rates, or caps. export const BALANCE = { - version: 'v27.14 debug restore consistency patch', + version: 'v27.19 LAND + UI PATCH', time: { daySeconds: 60, farmShutdownGraceSeconds: 10 @@ -24,7 +24,9 @@ export const BALANCE = { } }, map: { - blockedRatio: 0.075 + blockedRatio: 0.03, + blockedExpansionIncrement: 0.005, + blockedRatioMax: 0.10 }, economy: { income: { @@ -251,7 +253,7 @@ export const BALANCE = { rarity: 'rare', type: 'cellAction', target: 'blockedCell', - description: 'Remove any 3 unbuildable cells', + description: 'Choose and remove up to 3 unbuildable cells.', tags: ['RISK', 'RARE', 'ONE-SHOT'] }, { @@ -307,7 +309,7 @@ export const BALANCE = { title: 'Motivational Exploitation', rarity: 'ultraRare', type: 'instant', - description: 'Repairman labor cost -30%. The repairman smiles with bloodshot eyes. One time only.', + description: 'Repair room work time -30%. The repairman smiles with bloodshot eyes. One time only.', tags: ['MAINTENANCE', 'ULTRA RARE', 'PASSIVE'] }, { @@ -374,7 +376,6 @@ export const BALANCE = { trash: 1.00 }, repairman: { - dailyCost: 100, secondsPerOnePercent: 0.5, walkSpeed: 90 } @@ -411,6 +412,10 @@ export const BALANCE = { truck: { id: 'truck', type: 'facility', name: 'Truck', shortName: 'TRUCK', price: 450, buildable: true, upgradeable: true, incomeKey: 'truck', body: { w: 176, h: 138 } + }, + maintenanceRoom: { + id: 'maintenanceRoom', type: 'maintenanceRoom', name: 'Maintenance Room', shortName: 'REPAIR ROOM', price: 220, + buildable: true, upgradeable: false, footprint: { cols: 2, rows: 2 } } } }; diff --git a/src/core/config.js b/src/core/config.js index 595dcb9..dfa135f 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -26,7 +26,7 @@ export const EGG_SPAWN_RANGES = BALANCE.production.eggSpawnRanges; export const GRID = BALANCE.grid; export const FACILITY_DEFS = BALANCE.facilities; -export const BUILD_TOOL_IDS = ['conveyor', 'boostConveyor', 'eggFarm', 'autoScanner', 'manualScanner', 'mixer', 'trash', 'truck']; +export const BUILD_TOOL_IDS = ['conveyor', 'boostConveyor', 'eggFarm', 'autoScanner', 'manualScanner', 'mixer', 'trash', 'truck', 'maintenanceRoom']; export const MACHINE_FACILITY_IDS = ['mixer', 'trash', 'truck']; export const INCOME_FACILITY_IDS = ['mixer', 'truck']; @@ -40,20 +40,20 @@ export const DIRS = [ ]; export const THEME = { - bg: '#eefbea', - ink: '#102015', - muted: '#526456', - green: '#22b94f', - greenSoft: '#b7f5c6', - mixerBlue: '#2477ff', - truckPink: '#ff6aa8', - wasteGreen: '#22b94f', - danger: '#c42424', - warn: '#f0a020', - white: '#ffffff', + bg: '#111318', + ink: '#090a0d', + muted: '#8f9bab', + green: '#7bd84f', + greenSoft: '#273c24', + mixerBlue: '#4aa3ff', + truckPink: '#ffb33e', + wasteGreen: '#88d35a', + danger: '#e34a36', + warn: '#ffb827', + white: '#e6edf2', poop: '#7b4a23', - male: '#62a9ff', - female: '#ff8bc6' + male: '#4aa3ff', + female: '#ff6fae' }; export const EFFECT_PRIORITY = { diff --git a/src/core/entities.js b/src/core/entities.js index 71e9c7a..75d699e 100644 --- a/src/core/entities.js +++ b/src/core/entities.js @@ -94,6 +94,26 @@ export function createFacility(game, id, p, price) { return layoutFacilityOnEdge(f, entry, side); } + +export function maintenanceRoomFootprint(room) { + if (!room) return []; + return [ + { col: room.col, row: room.row }, + { col: room.col + 1, row: room.row }, + { col: room.col, row: room.row + 1 }, + { col: room.col + 1, row: room.row + 1 } + ]; +} + +export function createMaintenanceRoom(game, col, row) { + return { + type: 'maintenanceRoom', id: game.nextId++, col, row, + price: BUILD_COSTS.maintenanceRoom, + builtSession: game.buildSession, + wCells: 2, hCells: 2 + }; +} + export function rollChickSex(game) { return Math.random() < currentPoopRate(game) ? 'poop' : (Math.random() < 0.5 ? 'male' : 'female'); } diff --git a/src/core/mapGen.js b/src/core/mapGen.js index 15712ad..dde8d4f 100644 --- a/src/core/mapGen.js +++ b/src/core/mapGen.js @@ -20,6 +20,12 @@ function mulberry32(seed) { }; } + +export function blockedRatioForExpansionPurchase(purchaseCount, { base = 0.03, increment = 0.005, max = 0.10 } = {}) { + const count = Math.max(0, Math.floor(Number(purchaseCount) || 0)); + return Number(Math.min(max, base + count * increment).toFixed(6)); +} + export function createRunSeed() { return `RUN-${Date.now().toString(36)}-${Math.floor(Math.random() * 1e6).toString(36)}`.toUpperCase(); } @@ -38,7 +44,7 @@ export function generateBlockedCells({ seed, targetRatio = 0.20, reserved = [] } const j = Math.floor(rng() * (i + 1)); [candidates[i], candidates[j]] = [candidates[j], candidates[i]]; } - const target = Math.round(GRID.cols * GRID.rows * targetRatio); + const target = Math.round(GRID.cols * GRID.rows * targetRatio + 1e-9); return new Set(candidates.slice(0, Math.min(target, candidates.length)).map(c => c.k)); } @@ -60,6 +66,6 @@ export function generateBlockedCellsInRect({ seed, colStart = 0, colEnd = GRID.c const j = Math.floor(rng() * (i + 1)); [candidates[i], candidates[j]] = [candidates[j], candidates[i]]; } - const target = Math.round((c1 - c0) * (r1 - r0) * targetRatio); + const target = Math.round((c1 - c0) * (r1 - r0) * targetRatio + 1e-9); return new Set(candidates.slice(0, Math.min(target, candidates.length)).map(c => c.k)); } diff --git a/src/core/state.js b/src/core/state.js index d44b5ac..783cd54 100644 --- a/src/core/state.js +++ b/src/core/state.js @@ -26,7 +26,6 @@ export function newTurnStats() { manualComboBonus: 0, manualComboSuccess: 0, manualComboFailure: 0, - repairWorkerWages: 0, fairiesTribute: 0, chemicalWeaponSubsidy: 0, rescueLoan: 0, @@ -73,7 +72,6 @@ export function newTotalStats() { manualComboBonus: 0, manualComboSuccess: 0, manualComboFailure: 0, - repairWorkerWages: 0, cardRerollCost: 0, dudRefundIncome: 0, composterIncome: 0, @@ -129,6 +127,8 @@ export function createGame() { eggFarms: [], scanners: [], facilities: {}, + maintenanceRooms: [], + repairmen: [], branchCounters: new Map(), routingVersion: 0, factoryGraph: null, @@ -144,8 +144,7 @@ export function createGame() { cardDraft: { pending: false, choices: [], rerolls: 0, picksRemaining: 0 }, cardTargetPick: null, manualCombo: { count: 0, lastBonus: 0 }, - pendingRepairWorkerWages: 0, - repairman: { hiredForNextDay: false, active: false, x: GRID.x + GRID.cell * 0.5, y: GRID.y + BALANCE.grid.rows * GRID.cell + 84, target: null, repairedToday: 0 }, + repairman: { active: false, x: GRID.x + GRID.cell * 0.5, y: GRID.y + BALANCE.grid.rows * GRID.cell + 84, target: null, repairedToday: 0 }, stats: newTurnStats(), lastResult: null, totals: newTotalStats() @@ -319,10 +318,11 @@ export function resetLayout(game) { game.repairman.y = GRID.y + GRID.rows * GRID.cell + 84; game.repairman.target = null; game.repairman.active = false; - game.repairman.hiredForNextDay = false; } game.conveyorTiles.clear(); game.conveyorMeta.clear(); + game.maintenanceRooms = []; + game.repairmen = []; game.blockedCells = new Set(); installInitialConveyorBackbone(game); game.facilities = defaultFacilities(); @@ -336,7 +336,7 @@ export function resetLayout(game) { // installed. The protected footprint includes every default conveyor segment, // scanner body/ports, farm output, and machine receiver. This guarantees that // the starter line is always continuous from Egg Farm -> S1 -> S2 -> exits even - // when roughly 20% of the map is blocked. + // when roughly 3% of the initial map is blocked. const reserved = protectedInitialCells(game); game.blockedCells = generateBlockedCells({ seed: game.runSeed, targetRatio: BALANCE.map.blockedRatio, reserved: [...reserved] }); scrubBlockedCellsFromInitialBackbone(game); diff --git a/src/core/text.js b/src/core/text.js index 065f9a3..fb14317 100644 --- a/src/core/text.js +++ b/src/core/text.js @@ -28,7 +28,6 @@ export const TEXT = { 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', @@ -71,7 +70,8 @@ export function buildToolFlavorText(id) { 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.' + truck: 'Ships the target cargo. Wrong cargo still leaves a paper trail.', + maintenanceRoom: '2×2 repair bay. Each room dispatches one repairman during the day.' }; return flavors[id] || ''; } diff --git a/src/game.js b/src/game.js index de630df..254230d 100644 --- a/src/game.js +++ b/src/game.js @@ -13,7 +13,7 @@ import { createChickSystem } from './systems/chickSystem.js'; import { CARD_DEFS, cardById, conveyorSpeedForGame, createCardSystem, debugCardTargets, debugGrantCard } from './systems/cards.js'; import { floating, shockwave, sparkBurst, updateEffects } from './systems/effects.js'; import { rollEventOffer, activateEventOffer, clearActiveEvent, resolveEvent, eventDaySeconds, fairiesTributeMultiplierFromEvent } from './systems/events.js'; -import { ensureMaintenanceState, hireRepairmanForNextDay, activateRepairmanForDay, deactivateRepairman, conveyorSpeedFactorForKey } from './systems/maintenance.js'; +import { ensureMaintenanceState, activateRepairmanForDay, deactivateRepairman, conveyorSpeedFactorForKey } from './systems/maintenance.js'; const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); @@ -23,11 +23,10 @@ const ui = { money: document.getElementById('money'), turn: document.getElementById('turn'), timeLeft: document.getElementById('timeLeft'), phase: document.getElementById('phaseLabel'), comboCount: document.getElementById('comboCount'), eventBrief: document.getElementById('eventBrief'), targetBrief: document.getElementById('targetBrief'), speedBrief: document.getElementById('speedBrief'), turnProfit: document.getElementById('turnProfit'), mixerCount: document.getElementById('mixerCount'), truckFemaleCount: document.getElementById('truckFemaleCount'), truckMaleCount: document.getElementById('truckMaleCount'), poopCount: document.getElementById('poopCount'), - buildStatus: document.getElementById('buildStatus'), turnSummary: document.getElementById('turnSummary'), eventPanel: document.getElementById('eventPanel'), + buildStatus: document.getElementById('buildStatus'), turnSummary: document.getElementById('turnSummary'), modal: document.getElementById('modal'), modalTitle: document.getElementById('modalTitle'), modalBody: document.getElementById('modalBody'), modalActions: document.getElementById('modalActions'), hoverTooltip: document.getElementById('hoverTooltip'), manualScannerMonitor: document.getElementById('manualScannerMonitor'), - hireRepairmanButton: document.getElementById('hireRepairmanButton'), debug: { panel: document.getElementById('debugPanel'), infiniteCash: document.getElementById('debugInfiniteCash'), @@ -42,7 +41,7 @@ const ui = { }, buttons: { s1Left: document.getElementById('scanner1MixerButton'), s1Right: document.getElementById('scanner1TruckButton'), s2Left: document.getElementById('scanner2MixerButton'), s2Right: document.getElementById('scanner2TruckButton'), - nextTurn: document.getElementById('nextTurnButton'), conveyor: document.getElementById('buildConveyorButton'), boostConveyor: document.getElementById('buildBoostConveyorButton'), eggFarm: document.getElementById('buildEggFarmButton'), autoScanner: document.getElementById('buildAutoScannerButton'), manualScanner: document.getElementById('buildManualScannerButton'), mixer: document.getElementById('buildMixerButton'), trash: document.getElementById('buildTrashButton'), truck: document.getElementById('buildTruckButton'), erase: document.getElementById('eraseButton'), undo: document.getElementById('undoButton'), redo: document.getElementById('redoButton') + nextTurn: document.getElementById('nextTurnButton'), conveyor: document.getElementById('buildConveyorButton'), boostConveyor: document.getElementById('buildBoostConveyorButton'), eggFarm: document.getElementById('buildEggFarmButton'), autoScanner: document.getElementById('buildAutoScannerButton'), manualScanner: document.getElementById('buildManualScannerButton'), mixer: document.getElementById('buildMixerButton'), trash: document.getElementById('buildTrashButton'), truck: document.getElementById('buildTruckButton'), maintenanceRoom: document.getElementById('buildMaintenanceRoomButton'), erase: document.getElementById('eraseButton'), undo: document.getElementById('undoButton'), redo: document.getElementById('redoButton') } }; @@ -56,7 +55,8 @@ function initializeStaticText() { manualScanner: 'manualScanner', mixer: 'mixer', trash: 'trash', - truck: 'truck' + truck: 'truck', + maintenanceRoom: 'maintenanceRoom' }; for (const [buttonKey, toolId] of Object.entries(buttonToolMap)) { if (ui.buttons[buttonKey]) ui.buttons[buttonKey].innerHTML = buildToolButtonHtml(toolId); @@ -259,13 +259,10 @@ function startNextTurn() { resetCameraToFactoryStart(); game.stats = newTurnStats(); game.stats.fairiesTribute = game.lastStartFees?.fairiesTribute || 0; - game.stats.repairWorkerWages = game.pendingRepairWorkerWages || 0; - const carriedStartCosts = game.stats.fairiesTribute + game.stats.repairWorkerWages; - if (carriedStartCosts > 0) { - game.stats.penalty += carriedStartCosts; - game.stats.profit -= carriedStartCosts; + if (game.stats.fairiesTribute > 0) { + game.stats.penalty += game.stats.fairiesTribute; + game.stats.profit -= game.stats.fairiesTribute; } - game.pendingRepairWorkerWages = 0; for (const scanner of game.scanners) { scanner.queue = []; scanner.cooldown = 0; } for (const farm of game.eggFarms) { farm.nextSpawn = chicks.currentSpawnDelay(farm); farm.lastInterval = farm.nextSpawn; farm.shutterProgress = 0; farm.shutterSparked = false; } game.buildTool = null; @@ -279,19 +276,6 @@ function startNextTurn() { } -function hireRepairman() { - ensureMaintenanceState(game); - const result = hireRepairmanForNextDay(game); - if (!result.ok) { - floating(game, canvas.width / 2 - game.view.x, 96 - game.view.y, result.reason || 'Cannot hire repairman.', THEME.danger); - build?.fail?.(result.reason || 'Cannot hire repairman.'); - } else { - floating(game, canvas.width / 2 - game.view.x, 96 - game.view.y, `Repairman hired -${yen(result.cost)}`, THEME.green); - } - uiSystem.updatePanels(); - uiSystem.updateUI(); -} - function completeTurn() { if (game.phase !== 'running') return; const ship = settleTruckRevenue(game); @@ -713,8 +697,7 @@ document.addEventListener('pointerdown', event => { }, true); ui.buttons.s1Left.addEventListener('click', () => chicks.sortSlot(0, 'left')); ui.buttons.s1Right.addEventListener('click', () => chicks.sortSlot(0, 'right')); ui.buttons.s2Left.addEventListener('click', () => chicks.sortSlot(1, 'left')); ui.buttons.s2Right.addEventListener('click', () => chicks.sortSlot(1, 'right')); -ui.buttons.nextTurn.addEventListener('click', startNextTurn); ui.buttons.conveyor.addEventListener('click', () => build.setBuildTool('conveyor')); ui.buttons.boostConveyor.addEventListener('click', () => build.setBuildTool('boostConveyor')); ui.buttons.eggFarm.addEventListener('click', () => build.setBuildTool('eggFarm')); ui.buttons.autoScanner.addEventListener('click', () => build.setBuildTool('autoScanner')); ui.buttons.manualScanner.addEventListener('click', () => build.setBuildTool('manualScanner')); ui.buttons.mixer.addEventListener('click', () => build.setBuildTool('mixer')); ui.buttons.trash.addEventListener('click', () => build.setBuildTool('trash')); ui.buttons.truck.addEventListener('click', () => build.setBuildTool('truck')); ui.buttons.erase.addEventListener('click', () => build.setBuildTool('erase')); -ui.hireRepairmanButton?.addEventListener('click', hireRepairman); +ui.buttons.nextTurn.addEventListener('click', startNextTurn); ui.buttons.conveyor.addEventListener('click', () => build.setBuildTool('conveyor')); ui.buttons.boostConveyor.addEventListener('click', () => build.setBuildTool('boostConveyor')); ui.buttons.eggFarm.addEventListener('click', () => build.setBuildTool('eggFarm')); ui.buttons.autoScanner.addEventListener('click', () => build.setBuildTool('autoScanner')); ui.buttons.manualScanner.addEventListener('click', () => build.setBuildTool('manualScanner')); ui.buttons.mixer.addEventListener('click', () => build.setBuildTool('mixer')); ui.buttons.trash.addEventListener('click', () => build.setBuildTool('trash')); ui.buttons.truck.addEventListener('click', () => build.setBuildTool('truck')); ui.buttons.maintenanceRoom.addEventListener('click', () => build.setBuildTool('maintenanceRoom')); ui.buttons.erase.addEventListener('click', () => build.setBuildTool('erase')); ui.debug.setDay?.addEventListener('click', debugSetDay); ui.debug.zeroTimer?.addEventListener('click', debugZeroTimer); ui.debug.grantCard?.addEventListener('click', debugGrantSelectedCard); diff --git a/src/render/draw.js b/src/render/draw.js index 93a274d..dd7c62b 100644 --- a/src/render/draw.js +++ b/src/render/draw.js @@ -9,18 +9,36 @@ import { wearRatio } from '../systems/maintenance.js'; // Optional art overlay hook. // Keep external art probing disabled by default so a clean checkout does not emit 404s for missing PNGs. // To use replacement art, set ENABLE_EXTERNAL_ART_ASSETS to true and place files under assets/images/. -const ENABLE_EXTERNAL_ART_ASSETS = false; +const ENABLE_EXTERNAL_ART_ASSETS = true; const ASSET_PATHS = { + // User-supplied chick/poop assets remain optional. Facility/UI art is wired below. chickMale: './assets/images/chick_male.png', chickFemale: './assets/images/chick_female.png', - poop: new URL('../../assets/images/poop.png', import.meta.url).href, - conveyor: './assets/images/conveyor.png', - scannerManual: './assets/images/scanner_manual.png', - scannerAuto: './assets/images/scanner_auto.png', - eggFarm: './assets/images/egg_farm.png', - mixer: './assets/images/mixer.png', - shredder: './assets/images/shredder.png', - truck: './assets/images/truck.png' + poop: './assets/images/poop.png', + conveyorStraightH: './assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png', + conveyorStraightV: './assets/dark_factory/facilities/conveyor/conveyor_straight_v_16.png', + conveyorTurnNe: './assets/dark_factory/facilities/conveyor/conveyor_turn_ne_16.png', + conveyorTurnNw: './assets/dark_factory/facilities/conveyor/conveyor_turn_nw_16.png', + conveyorTurnSe: './assets/dark_factory/facilities/conveyor/conveyor_turn_se_16.png', + conveyorTurnSw: './assets/dark_factory/facilities/conveyor/conveyor_turn_sw_16.png', + boostConveyorStraightH: './assets/dark_factory/facilities/conveyor/boost_conveyor_straight_h_16.png', + boostConveyorStraightV: './assets/dark_factory/facilities/conveyor/boost_conveyor_straight_v_16.png', + boostConveyorTurnNe: './assets/dark_factory/facilities/conveyor/boost_conveyor_turn_ne_16.png', + boostConveyorTurnNw: './assets/dark_factory/facilities/conveyor/boost_conveyor_turn_nw_16.png', + boostConveyorTurnSe: './assets/dark_factory/facilities/conveyor/boost_conveyor_turn_se_16.png', + boostConveyorTurnSw: './assets/dark_factory/facilities/conveyor/boost_conveyor_turn_sw_16.png', + scannerManual: './assets/dark_factory/facilities/machines/manual_scanner_32x48.png', + scannerAuto: './assets/dark_factory/facilities/machines/auto_scanner_32x48.png', + eggFarm: './assets/dark_factory/facilities/machines/egg_farm_16.png', + mixer: './assets/dark_factory/facilities/machines/mixer_32.png', + shredder: './assets/dark_factory/facilities/machines/shredder_32.png', + truck: './assets/dark_factory/facilities/vehicles/truck_32.png', + mixerCompact: './assets/dark_factory/facilities/machines/mixer_compact_16.png', + shredderCompact: './assets/dark_factory/facilities/machines/shredder_compact_16.png', + truckCompact: './assets/dark_factory/facilities/vehicles/truck_compact_16.png', + maintenanceRoom: './assets/dark_factory/facilities/utility/maintenance_room_32.png', + repairman: './assets/dark_factory/facilities/utility/repairman_16.png', + obstacleCrate: './assets/dark_factory/facilities/utility/obstacle_crate_16.png' }; export const assets = {}; @@ -28,7 +46,7 @@ for (const [name, src] of Object.entries(ASSET_PATHS)) { const img = new Image(); img.loaded = false; img.onerror = () => { img.loaded = false; }; - if ((ENABLE_EXTERNAL_ART_ASSETS || name === 'poop') && src) { + if (ENABLE_EXTERNAL_ART_ASSETS && src) { img.onload = () => { img.loaded = true; }; img.src = src; } @@ -38,6 +56,7 @@ for (const [name, src] of Object.entries(ASSET_PATHS)) { // Each draw* function first checks whether an image loaded; if not, it falls back to simple canvas shapes. export function drawAll(ctx, canvas, game, helpers) { + ctx.imageSmoothingEnabled = false; ctx.clearRect(0, 0, canvas.width, canvas.height); drawBackground(ctx, canvas); ctx.save(); @@ -50,6 +69,7 @@ export function drawAll(ctx, canvas, game, helpers) { drawExpansionOffers(ctx, game); drawConveyors(ctx, game); drawScannerConnectors(ctx, game); + drawMaintenanceRooms(ctx, game); drawFacilities(ctx, game); drawEggFarms(ctx, game); drawScanners(ctx, game); @@ -108,17 +128,84 @@ function label(ctx, x, y, text, color = THEME.ink) { } function drawImageIfLoaded(ctx, image, x, y, w, h) { if (!image?.loaded) return false; - ctx.drawImage(image, x, y, w, h); + const previous = ctx.imageSmoothingEnabled; + ctx.imageSmoothingEnabled = false; + ctx.drawImage(image, Math.round(x), Math.round(y), Math.round(w), Math.round(h)); + ctx.imageSmoothingEnabled = previous; return true; } +function pixelRect(ctx, x, y, w, h, fill, stroke = null, lineWidth = 1) { + ctx.fillStyle = fill; + ctx.fillRect(Math.round(x), Math.round(y), Math.round(w), Math.round(h)); + if (stroke) { + ctx.strokeStyle = stroke; + ctx.lineWidth = lineWidth; + ctx.strokeRect(Math.round(x) + 0.5, Math.round(y) + 0.5, Math.round(w) - 1, Math.round(h) - 1); + } +} +function floorCellHash(col, row) { + let n = (Math.imul(col + 37, 73856093) ^ Math.imul(row + 71, 19349663)) >>> 0; + n ^= n >>> 13; + return n >>> 0; +} +function drawFloorSlime(ctx, x, y, col, row) { + const h = floorCellHash(col, row); + // Sparse, deterministic splashes: about 3% of owned floor cells. + if (h % 31 !== 0) return; + const ox = 10 + ((h >>> 4) % Math.max(1, GRID.cell - 22)); + const oy = 10 + ((h >>> 9) % Math.max(1, GRID.cell - 22)); + const angle = ((h >>> 14) % 16) * Math.PI / 16; + ctx.save(); + ctx.globalAlpha = 0.46; + ctx.fillStyle = '#4d9638'; + ctx.strokeStyle = 'rgba(30,66,27,.48)'; + ctx.lineWidth = 1; + + // Small irregular core rather than a large puddle. + ctx.beginPath(); + for (let i = 0; i < 8; i += 1) { + const a = angle + i * Math.PI / 4; + const r = 3.5 + ((h >>> (i + 2)) & 3); + const px = x + ox + Math.cos(a) * r * 1.35; + const py = y + oy + Math.sin(a) * r * .75; + if (i === 0) ctx.moveTo(px, py); else ctx.lineTo(px, py); + } + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + + // Several separated droplets produce a splattered silhouette. + const droplets = 3 + ((h >>> 24) % 4); + for (let i = 0; i < droplets; i += 1) { + const a = angle + i * 2.17 + ((h >>> (i + 8)) & 3) * .18; + const dist = 8 + ((h >>> (i + 11)) & 7); + const radius = 1.1 + ((h >>> (i + 17)) & 3) * .45; + ctx.beginPath(); + ctx.arc(x + ox + Math.cos(a) * dist, y + oy + Math.sin(a) * dist * .72, radius, 0, Math.PI * 2); + ctx.fill(); + } + ctx.fillStyle = 'rgba(151,218,101,.40)'; + ctx.beginPath(); + ctx.arc(x + ox - 2, y + oy - 2, 1.7, 0, Math.PI * 2); + ctx.fill(); + ctx.restore(); +} function drawBackground(ctx, canvas) { ctx.fillStyle = THEME.bg; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.save(); - ctx.strokeStyle = 'rgba(16, 32, 21, 0.035)'; + ctx.globalAlpha = 0.85; + for (let y = 0; y < canvas.height; y += 16) { + for (let x = 0; x < canvas.width; x += 16) { + const even = ((x / 16 + y / 16) | 0) % 2 === 0; + ctx.fillStyle = even ? '#181b20' : '#20242b'; + ctx.fillRect(x, y, 16, 16); + } + } + ctx.strokeStyle = 'rgba(255,184,39,.08)'; ctx.lineWidth = 1; - for (let x = 0; x < canvas.width; x += 32) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke(); } - for (let y = 0; y < canvas.height; y += 32) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke(); } + for (let x = 0; x < canvas.width; x += 64) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke(); } + for (let y = 0; y < canvas.height; y += 64) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke(); } ctx.restore(); } function ownedCellKeys(game) { @@ -131,15 +218,20 @@ function ownedCellKeys(game) { function drawGrid(ctx, game) { ctx.save(); const cells = ownedCellKeys(game); - ctx.fillStyle = 'rgba(255,255,255,.46)'; - ctx.strokeStyle = 'rgba(16,32,21,.055)'; - ctx.lineWidth = 1; for (const k of cells) { const p = parseKey(k); const c = cellCenter(p.col, p.row); - rect(ctx, c.x - GRID.cell / 2, c.y - GRID.cell / 2, GRID.cell, GRID.cell, true, true); + const x = c.x - GRID.cell / 2; + const y = c.y - GRID.cell / 2; + const tone = ((p.col + p.row) % 2 === 0) ? '#59616d' : '#505965'; + pixelRect(ctx, x, y, GRID.cell, GRID.cell, tone, 'rgba(190,199,210,.28)', 1); + ctx.fillStyle = 'rgba(255,255,255,.055)'; + ctx.fillRect(Math.round(x + 2), Math.round(y + 2), Math.round(GRID.cell - 4), 2); + ctx.fillStyle = 'rgba(0,0,0,.18)'; + ctx.fillRect(Math.round(x + 1), Math.round(y + GRID.cell - 3), Math.round(GRID.cell - 2), 2); + drawFloorSlime(ctx, x, y, p.col, p.row); } - ctx.strokeStyle = 'rgba(16,32,21,.16)'; + ctx.strokeStyle = 'rgba(255,184,39,.32)'; ctx.lineWidth = 3; for (const k of cells) { const p = parseKey(k); @@ -154,14 +246,41 @@ function drawGrid(ctx, game) { const p = parseKey(k); if (!isOwnedCell(game, p.col, p.row)) continue; const c = cellCenter(p.col, p.row); - ctx.fillStyle = 'rgba(16,32,21,.30)'; - ctx.strokeStyle = 'rgba(16,32,21,.60)'; + const x = c.x - GRID.cell / 2; + const y = c.y - GRID.cell / 2; + // Muted floor-level hazard striping. It remains readable without dominating machines. + ctx.save(); + ctx.beginPath(); + ctx.rect(Math.round(x + 1), Math.round(y + 1), GRID.cell - 2, GRID.cell - 2); + ctx.clip(); + ctx.fillStyle = 'rgba(42,45,48,.42)'; + ctx.fillRect(Math.round(x), Math.round(y), GRID.cell, GRID.cell); + ctx.lineWidth = 8; + ctx.strokeStyle = 'rgba(196,163,79,.38)'; + for (let stripe = -GRID.cell; stripe < GRID.cell * 2; stripe += 16) { + ctx.beginPath(); + ctx.moveTo(x + stripe, y + GRID.cell); + ctx.lineTo(x + stripe + GRID.cell, y); + ctx.stroke(); + } + ctx.lineWidth = 8; + ctx.strokeStyle = 'rgba(20,23,26,.32)'; + for (let stripe = -GRID.cell + 8; stripe < GRID.cell * 2; stripe += 16) { + ctx.beginPath(); + ctx.moveTo(x + stripe, y + GRID.cell); + ctx.lineTo(x + stripe + GRID.cell, y); + ctx.stroke(); + } + ctx.restore(); + ctx.strokeStyle = 'rgba(17,19,22,.72)'; ctx.lineWidth = 2; - rect(ctx, c.x - GRID.cell / 2 + 4, c.y - GRID.cell / 2 + 4, GRID.cell - 8, GRID.cell - 8, true, true); + ctx.strokeRect(Math.round(x) + 1, Math.round(y) + 1, GRID.cell - 2, GRID.cell - 2); + ctx.strokeStyle = 'rgba(224,194,112,.24)'; + ctx.lineWidth = 1; + ctx.strokeRect(Math.round(x) + 4, Math.round(y) + 4, GRID.cell - 8, GRID.cell - 8); } ctx.restore(); } - function drawExpansionOffers(ctx, game) { if (game.phase !== 'build' || game.cardDraft?.pending || game.cardTargetPick?.pending) return; const cost = expansionCost(game); @@ -220,6 +339,22 @@ function componentRatio(game, k) { const data = id ? game.congestion.get(id) : null; return data?.ratio || 0; } +function conveyorAssetForTile(game, k, meta = {}) { + const dirs = connectedConveyorDirs(game, k).sort(); + const boost = meta.kind === 'boostConveyor'; + const prefix = boost ? 'boostConveyor' : 'conveyor'; + const has = name => dirs.includes(name); + if (dirs.length === 2) { + if (has('left') && has('right')) return assets[`${prefix}StraightH`]; + if (has('up') && has('down')) return assets[`${prefix}StraightV`]; + if (has('up') && has('right')) return assets[`${prefix}TurnNe`]; + if (has('up') && has('left')) return assets[`${prefix}TurnNw`]; + if (has('down') && has('right')) return assets[`${prefix}TurnSe`]; + if (has('down') && has('left')) return assets[`${prefix}TurnSw`]; + } + if (dirs.length === 1) return has('up') || has('down') ? assets[`${prefix}StraightV`] : assets[`${prefix}StraightH`]; + return has('up') || has('down') ? assets[`${prefix}StraightV`] : assets[`${prefix}StraightH`]; +} function drawConveyors(ctx, game) { const edges = []; const seen = new Set(); @@ -239,9 +374,9 @@ function drawConveyors(ctx, game) { ctx.save(); ctx.lineCap = 'round'; ctx.lineJoin = 'round'; for (const layer of [ - { width: 33, color: THEME.ink, alpha: 1 }, - { width: 25, color: THEME.white, alpha: 1 }, - { width: 17, color: THEME.greenSoft, alpha: 1 } + { width: 31, color: '#0b0c0f', alpha: 1 }, + { width: 23, color: '#444b56', alpha: 1 }, + { width: 15, color: '#171a1f', alpha: 1 } ]) { ctx.globalAlpha = layer.alpha; ctx.strokeStyle = layer.color; ctx.lineWidth = layer.width; for (const e of edges) { ctx.beginPath(); ctx.moveTo(e.a.x, e.a.y); ctx.lineTo(e.b.x, e.b.y); ctx.stroke(); } @@ -258,27 +393,80 @@ function drawConveyors(ctx, game) { const c = cellCenter(...Object.values(parseKey(k))); const meta = game.conveyorMeta.get(k) || {}; const ratio = componentRatio(game, k); - const baseFill = meta.kind === 'boostConveyor' ? '#fff2b8' : THEME.white; - ctx.fillStyle = ratio > 0.5 ? mixHex(baseFill, '#ffd6d6', Math.max(0, (ratio - .5) / .5)) : baseFill; - ctx.strokeStyle = THEME.ink; ctx.lineWidth = 2; - rect(ctx, c.x - 8, c.y - 8, 16, 16, true, true); - if (meta.kind === 'boostConveyor') { - ctx.save(); - ctx.strokeStyle = THEME.warn; - ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(c.x - 15, c.y + 13); ctx.lineTo(c.x - 3, c.y - 13); ctx.lineTo(c.x + 2, c.y - 2); ctx.lineTo(c.x + 15, c.y - 13); ctx.stroke(); - ctx.restore(); + const sprite = conveyorAssetForTile(game, k, meta); + const congested = ratio > 0.5; + ctx.fillStyle = congested ? 'rgba(196,36,36,.28)' : 'rgba(0,0,0,.35)'; + ctx.strokeStyle = congested ? THEME.danger : 'rgba(255,184,39,.34)'; + ctx.lineWidth = congested ? 3 : 1; + rect(ctx, c.x - 20, c.y - 20, 40, 40, true, true); + if (!drawImageIfLoaded(ctx, sprite, c.x - 19, c.y - 19, 38, 38)) { + const baseFill = meta.kind === 'boostConveyor' ? '#315e92' : '#454b55'; + ctx.fillStyle = ratio > 0.5 ? mixHex(baseFill, '#a12c2c', Math.max(0, (ratio - .5) / .5)) : baseFill; + ctx.strokeStyle = THEME.ink; ctx.lineWidth = 2; + rect(ctx, c.x - 18, c.y - 18, 36, 36, true, true); } - drawDirtOverlay(ctx, c.x - 14, c.y - 14, 28, 28, { meta }); + drawAnimatedConveyorStripes(ctx, c, k, meta, ratio); + drawDirtOverlay(ctx, c.x - 18, c.y - 18, 36, 36, { meta }); drawSelection(ctx, game, 'conveyor', k, c.x, c.y, 38, 38); drawConveyorDirectionMarkers(ctx, c, directionMarkers.get(k) || []); const connectedDirs = connectedConveyorDirs(game, k); - drawBranchModeIcon(ctx, c, meta, branchSelectableEntranceDirs(game, k, connectedDirs), connectedDirs); + drawBranchModeIcon(ctx, c, meta, branchSelectableExitDirs(game, k, connectedDirs), connectedDirs); if (ratio > 0.5) label(ctx, c.x, c.y - 15, `${Math.floor(ratio * 100)}%`, THEME.danger); } ctx.restore(); } + +function drawAnimatedConveyorStripes(ctx, center, tileKey, meta = {}, ratio = 0) { + const names = [...new Set([...(Array.isArray(meta.outDirs) ? meta.outDirs : []), meta.dir].filter(Boolean))]; + const primary = names[0] || 'right'; + const verticalTravel = primary === 'up' || primary === 'down'; + const reverse = primary === 'left' || primary === 'up'; + const boost = meta.kind === 'boostConveyor'; + const t = typeof performance !== 'undefined' ? performance.now() / (boost ? 70 : 105) : 0; + const phase = ((reverse ? -t : t) % 10 + 10) % 10; + ctx.save(); + ctx.beginPath(); + ctx.rect(center.x - 18, center.y - 18, 36, 36); + ctx.clip(); + + // Blue-green rubber for boost belts; dark steel/rubber for standard belts. + const rubber = boost ? 'rgba(20,126,124,.62)' : 'rgba(42,47,54,.72)'; + ctx.fillStyle = rubber; + ctx.fillRect(center.x - 18, center.y - 18, 36, 36); + + // Slats are always perpendicular to travel and move in the travel direction. + ctx.strokeStyle = ratio > 0.5 ? 'rgba(238,83,61,.90)' : 'rgba(184,190,198,.92)'; + ctx.lineWidth = 4; + if (verticalTravel) { + for (let yy = center.y - 28 + phase; yy < center.y + 28; yy += 10) { + ctx.beginPath(); ctx.moveTo(center.x - 17, yy); ctx.lineTo(center.x + 17, yy); ctx.stroke(); + } + } else { + for (let xx = center.x - 28 + phase; xx < center.x + 28; xx += 10) { + ctx.beginPath(); ctx.moveTo(xx, center.y - 17); ctx.lineTo(xx, center.y + 17); ctx.stroke(); + } + } + + ctx.globalAlpha = 0.55; + ctx.strokeStyle = '#050609'; + ctx.lineWidth = 1; + if (verticalTravel) { + for (let yy = center.y - 23 + phase; yy < center.y + 28; yy += 10) { + ctx.beginPath(); ctx.moveTo(center.x - 17, yy); ctx.lineTo(center.x + 17, yy); ctx.stroke(); + } + } else { + for (let xx = center.x - 23 + phase; xx < center.x + 28; xx += 10) { + ctx.beginPath(); ctx.moveTo(xx, center.y - 17); ctx.lineTo(xx, center.y + 17); ctx.stroke(); + } + } + ctx.globalAlpha = 1; + ctx.strokeStyle = 'rgba(8,9,12,.92)'; + ctx.lineWidth = 2; + rect(ctx, center.x - 18, center.y - 18, 36, 36, false, true); + ctx.restore(); +} + function reachableConveyorDirs(game, k, meta) { const p = parseKey(k); const neighborNames = DIRS @@ -306,30 +494,27 @@ function neighborPointsIntoCell(game, p, dirName) { return names.includes(d.opposite); } -function branchExitDirs(game, k, dirs, connectedDirs = connectedConveyorDirs(game, k), branchMode = 'random') { +function branchExitCandidates(game, k, dirs, connectedDirs = connectedConveyorDirs(game, k)) { if (connectedDirs.length < 3) return dirs; const p = parseKey(k); - const entrances = new Set(connectedDirs.filter(dir => neighborPointsIntoCell(game, p, dir))); - if (branchMode && branchMode !== 'random' && connectedDirs.includes(branchMode)) { - const selectedEntrances = new Set(entrances); - selectedEntrances.add(branchMode); - if (connectedDirs.filter(dir => !selectedEntrances.has(dir)).length >= 2) entrances.add(branchMode); - } - const exits = connectedDirs.filter(dir => !entrances.has(dir)); - if (exits.length) return exits; - const fallback = dirs.filter(dir => !entrances.has(dir)); - return fallback.length ? fallback : dirs; + const physicalEntrances = new Set(connectedDirs.filter(dir => neighborPointsIntoCell(game, p, dir))); + const physicalExits = connectedDirs.filter(dir => !physicalEntrances.has(dir)); + if (physicalEntrances.size && physicalExits.length >= 2) return physicalExits; + const explicit = dirs.filter(dir => connectedDirs.includes(dir)); + if (explicit.length >= 2) return [...new Set(explicit)]; + return connectedDirs; } -function branchSelectableEntranceDirs(game, k, connectedDirs = connectedConveyorDirs(game, k)) { - if (connectedDirs.length < 3) return []; - const p = parseKey(k); - const physicalEntrances = new Set(connectedDirs.filter(dir => neighborPointsIntoCell(game, p, dir))); - return connectedDirs.filter(dir => { - const entrances = new Set(physicalEntrances); - entrances.add(dir); - return connectedDirs.filter(item => !entrances.has(item)).length >= 2; - }); +function branchExitDirs(game, k, dirs, connectedDirs = connectedConveyorDirs(game, k), branchMode = 'random') { + const candidates = branchExitCandidates(game, k, dirs, connectedDirs); + if (connectedDirs.length >= 3 && branchMode && branchMode !== 'random' && candidates.includes(branchMode)) return [branchMode]; + return candidates; +} + +function branchSelectableExitDirs(game, k, connectedDirs = connectedConveyorDirs(game, k)) { + const meta = game.conveyorMeta?.get?.(k) || {}; + const explicit = [...new Set([...(Array.isArray(meta.outDirs) ? meta.outDirs : []), meta.dir].filter(Boolean))]; + return connectedDirs.length < 3 ? [] : branchExitCandidates(game, k, explicit, connectedDirs); } function effectiveConveyorDirs(game, k, meta) { @@ -351,12 +536,13 @@ function drawBranchModeIcon(ctx, center, meta, dirs, connectedDirs = dirs) { ctx.lineJoin = 'round'; ctx.lineCap = 'round'; ctx.lineWidth = 2; - ctx.fillStyle = 'rgba(255,255,255,.9)'; + ctx.fillStyle = 'rgba(18,21,26,.94)'; ctx.strokeStyle = isFixed ? THEME.warn : THEME.green; - rect(ctx, center.x - 17, center.y - 17, 34, 34, true, true); - ctx.strokeStyle = THEME.ink; - ctx.lineWidth = 2; - ctx.fillStyle = THEME.ink; + ctx.lineWidth = 4; + rect(ctx, center.x - 18, center.y - 18, 36, 36, true, true); + ctx.strokeStyle = '#ffd36a'; + ctx.lineWidth = 3; + ctx.fillStyle = '#020304'; if (mode !== 'random') { const d = DIRS.find(item => item.name === mode); drawDirectionTriangle(ctx, center.x, center.y, d?.angle || 0, 9, 6); @@ -400,10 +586,14 @@ function drawConveyorDirectionMarkers(ctx, center, dirs) { const limited = dirs.slice(0, 4); if (!limited.length) return; ctx.save(); - ctx.fillStyle = THEME.ink; - ctx.globalAlpha = 0.86; + ctx.globalAlpha = 1; limited.forEach(d => { - drawDirectionTriangle(ctx, center.x + d.dc * 12, center.y + d.dr * 12, d.angle, 6, 5); + const x = center.x + d.dc * 11; + const y = center.y + d.dr * 11; + ctx.fillStyle = 'rgba(255,205,83,.96)'; + drawDirectionTriangle(ctx, x, y, d.angle, 9, 7); + ctx.fillStyle = '#020304'; + drawDirectionTriangle(ctx, x, y, d.angle, 6.5, 4.6); }); ctx.restore(); } @@ -413,6 +603,36 @@ function drawDirectionTriangle(ctx, x, y, angle, length = 11, halfWidth = 8) { ctx.beginPath(); ctx.moveTo(length, 0); ctx.lineTo(-length * 0.72, -halfWidth); ctx.lineTo(-length * 0.72, halfWidth); ctx.closePath(); ctx.fill(); ctx.restore(); } + +function drawScannerPortDuct(ctx, scanner, type, p, color) { + const c = scannerCenter(scanner); + let target = null; + if (type === 'inputA') target = { x: c.x, y: c.y - 67 }; + if (type === 'left') target = { x: c.x - 49, y: c.y + 14 }; + if (type === 'right') target = { x: c.x + 49, y: c.y + 14 }; + if (!target) return; + const elbow = type === 'inputA' + ? { x: p.x, y: target.y } + : { x: target.x, y: p.y }; + ctx.save(); + ctx.lineCap = 'square'; + ctx.lineJoin = 'bevel'; + ctx.strokeStyle = '#050609'; + ctx.lineWidth = 15; + ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(elbow.x, elbow.y); ctx.lineTo(target.x, target.y); ctx.stroke(); + ctx.strokeStyle = '#596473'; + ctx.lineWidth = 9; + ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(elbow.x, elbow.y); ctx.lineTo(target.x, target.y); ctx.stroke(); + ctx.strokeStyle = color || '#7b8795'; + ctx.lineWidth = 3; + ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(elbow.x, elbow.y); ctx.lineTo(target.x, target.y); ctx.stroke(); + ctx.fillStyle = color || '#7b8795'; + ctx.strokeStyle = '#050609'; + ctx.lineWidth = 3; + rect(ctx, target.x - 9, target.y - 7, 18, 14, true, true); + ctx.restore(); +} + function drawScannerConnectors(ctx, game) { ctx.save(); ctx.lineWidth = 2; @@ -428,11 +648,12 @@ function drawScannerConnectors(ctx, game) { for (const item of items) { if (!item.p) continue; const p = cellCenter(item.p.col, item.p.row); + drawScannerPortDuct(ctx, scanner, item.type, p, item.color); const connected = scannerPortHasConveyor(game, scanner, item.type || (item.label === 'IN' ? 'inputA' : null)) || game.conveyorTiles.has(key(item.p.col, item.p.row)); - ctx.fillStyle = connected ? item.color : '#f4c2c2'; - ctx.strokeStyle = THEME.ink; + ctx.fillStyle = connected ? mixHex('#1a1d23', item.color, 0.24) : '#3a1e22'; + ctx.strokeStyle = connected ? item.color : THEME.danger; rect(ctx, p.x - 18, p.y - 12, 36, 24, true, true); - ctx.fillStyle = connected && item.color === THEME.white ? THEME.ink : THEME.white; + ctx.fillStyle = THEME.white; ctx.fillText(item.label, p.x, p.y + 4); } } @@ -598,7 +819,7 @@ function drawFacilityReceiver(ctx, game, facility) { const c = cellCenter(f.entry.col, f.entry.row); const info = receiverTitle(id, game); ctx.save(); - ctx.fillStyle = THEME.white; + ctx.fillStyle = '#191c22'; ctx.strokeStyle = info.color; ctx.lineWidth = 5; rect(ctx, c.x - 22, c.y - 22, 44, 44, true, true); @@ -612,6 +833,90 @@ function drawFacilityReceiver(ctx, game, facility) { ctx.fillText(info.title, c.x, c.y + 20); ctx.restore(); } + + +function drawMetalPanel(ctx, x, y, w, h, fill = '#252b34', stroke = '#08090c', accent = '#606a78') { + ctx.save(); + const g = ctx.createLinearGradient(x, y, x, y + h); + g.addColorStop(0, mixHex(fill, '#ffffff', 0.12)); + g.addColorStop(0.55, fill); + g.addColorStop(1, mixHex(fill, '#000000', 0.28)); + ctx.fillStyle = g; + ctx.strokeStyle = stroke; + ctx.lineWidth = 4; + rect(ctx, x, y, w, h, true, true); + ctx.fillStyle = 'rgba(255,255,255,.08)'; + ctx.fillRect(x + 5, y + 5, Math.max(0, w - 10), 3); + ctx.strokeStyle = 'rgba(0,0,0,.34)'; + ctx.lineWidth = 1; + for (let yy = y + 11; yy < y + h - 8; yy += 13) { ctx.beginPath(); ctx.moveTo(x + 6, yy); ctx.lineTo(x + w - 6, yy); ctx.stroke(); } + ctx.fillStyle = accent; + for (const [rx, ry] of [[x + 8, y + 8], [x + w - 8, y + 8], [x + 8, y + h - 8], [x + w - 8, y + h - 8]]) { + ctx.beginPath(); ctx.arc(rx, ry, 2.2, 0, Math.PI * 2); ctx.fill(); + } + ctx.restore(); +} + +function drawFacilityDetails(ctx, f, accent = THEME.green) { + ctx.save(); + ctx.strokeStyle = '#06070a'; ctx.lineWidth = 4; + ctx.beginPath(); ctx.moveTo(f.x + 12, f.y + f.h - 18); ctx.lineTo(f.x + f.w - 12, f.y + f.h - 18); ctx.stroke(); + ctx.strokeStyle = accent; ctx.lineWidth = 2; + ctx.beginPath(); ctx.moveTo(f.x + 16, f.y + 22); ctx.lineTo(f.x + f.w - 18, f.y + 22); ctx.stroke(); + ctx.fillStyle = '#20242b'; ctx.strokeStyle = '#07080a'; ctx.lineWidth = 2; + rect(ctx, f.x + f.w - 44, f.y + 12, 30, 22, true, true); + ctx.fillStyle = accent; ctx.fillRect(f.x + f.w - 38, f.y + 18, 6, 6); + ctx.fillStyle = THEME.danger; ctx.fillRect(f.x + f.w - 27, f.y + 18, 6, 6); + ctx.strokeStyle = '#47515f'; ctx.lineWidth = 3; + ctx.beginPath(); ctx.moveTo(f.x + 12, f.y + f.h - 35); ctx.bezierCurveTo(f.x + 42, f.y + f.h - 52, f.x + 60, f.y + f.h - 20, f.x + 88, f.y + f.h - 38); ctx.stroke(); + ctx.restore(); +} + +function drawFacilityTexture(ctx, image, f, maxCells = 1.45) { + if (!image?.loaded) return false; + // Keep external-machine sprites at roughly the same pixel density as a grid object. + const maxSize = GRID.cell * Math.min(1.45, maxCells); + const size = Math.max(42, Math.min(maxSize, f.w - 34, f.h - 42)); + const x = f.x + Math.round((f.w - size) / 2); + const y = f.y + Math.round((f.h - size) / 2) + 2; + return drawImageIfLoaded(ctx, image, x, y, size, size); +} + +function roomBounds(room) { + const first = cellCenter(room.col, room.row); + return { x: first.x - GRID.cell / 2, y: first.y - GRID.cell / 2, w: GRID.cell * 2, h: GRID.cell * 2, cx: first.x + GRID.cell / 2, cy: first.y + GRID.cell / 2 }; +} +function drawMaintenanceRooms(ctx, game) { + for (const room of game.maintenanceRooms || []) { + const b = roomBounds(room); + ctx.save(); + drawMetalPanel(ctx, b.x + 2, b.y + 2, b.w - 4, b.h - 4, '#343b45', '#0a0b0e', '#7a6750'); + if (!drawImageIfLoaded(ctx, assets.maintenanceRoom, b.x + 5, b.y + 5, b.w - 10, b.h - 10)) { + ctx.fillStyle = '#414a55'; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 3; + rect(ctx, b.x + 8, b.y + 8, b.w - 16, b.h - 16, true, true); + // Storage shelves, spare-parts crates, a workbench, lockers and a small break stool. + ctx.fillStyle = '#6e573e'; ctx.strokeStyle = '#111318'; ctx.lineWidth = 2; + rect(ctx, b.x + 13, b.y + 14, 24, 51, true, true); + ctx.strokeStyle = '#b58a52'; + for (const yy of [b.y + 29, b.y + 44, b.y + 59]) { ctx.beginPath(); ctx.moveTo(b.x + 14, yy); ctx.lineTo(b.x + 36, yy); ctx.stroke(); } + ctx.fillStyle = '#515b68'; ctx.strokeStyle = '#111318'; + rect(ctx, b.x + b.w - 34, b.y + 13, 20, 43, true, true); + ctx.fillStyle = '#d49d28'; ctx.fillRect(b.x + b.w - 21, b.y + 32, 3, 3); + ctx.fillStyle = '#735431'; ctx.strokeStyle = '#111318'; + rect(ctx, b.x + 41, b.y + b.h - 31, 34, 14, true, true); + ctx.fillStyle = '#1b2027'; ctx.fillRect(b.x + 46, b.y + b.h - 39, 24, 8); + ctx.fillStyle = '#7b8795'; ctx.fillRect(b.x + 51, b.y + b.h - 37, 4, 5); + ctx.fillStyle = '#805b35'; ctx.strokeStyle = '#111318'; + rect(ctx, b.x + b.w - 32, b.y + b.h - 28, 16, 12, true, true); + ctx.fillStyle = '#222831'; ctx.beginPath(); ctx.arc(b.x + b.w - 46, b.y + b.h - 20, 7, 0, Math.PI * 2); ctx.fill(); + ctx.fillStyle = '#ddd0ad'; ctx.font = '900 8px ui-monospace, monospace'; ctx.textAlign = 'center'; ctx.fillText('STORE / REST', b.cx, b.y + 11); + } + drawDirtOverlay(ctx, b.x + 5, b.y + 5, b.w - 10, b.h - 10, room); + drawSelection(ctx, game, 'maintenanceRoom', room.id, b.cx, b.cy, b.w + 6, b.h + 6); + ctx.restore(); + } +} + function drawFacilities(ctx, game) { for (const f of Object.values(game.facilities || {})) { const kind = facilityKind(f); @@ -630,24 +935,29 @@ function drawExternalDuct(ctx, f) { else if (f.side === 'top') { bx = c.x; by = f.y + f.h; } else if (f.side === 'bottom') { bx = c.x; by = f.y; } ctx.save(); - ctx.strokeStyle = THEME.ink; - ctx.lineWidth = 9; + ctx.strokeStyle = '#07080a'; + ctx.lineWidth = 11; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(c.x, c.y); ctx.lineTo(bx, by); ctx.stroke(); - ctx.strokeStyle = THEME.white; ctx.lineWidth = 5; + ctx.strokeStyle = '#555f70'; ctx.lineWidth = 5; ctx.beginPath(); ctx.moveTo(c.x, c.y); ctx.lineTo(bx, by); ctx.stroke(); ctx.restore(); } function drawMixer(ctx, game, m = game.facilities.mixer) { ctx.save(); drawExternalDuct(ctx, m); - if (drawImageIfLoaded(ctx, assets.mixer, m.x, m.y, m.w, m.h)) { drawDirtOverlay(ctx, m.x, m.y, m.w, m.h, m); drawSelection(ctx, game, 'facility', m.id, m.x + m.w / 2, m.y + m.h / 2, m.w + 12, m.h + 12); ctx.restore(); return; } - ctx.fillStyle = THEME.white; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 4; rect(ctx, m.x, m.y, m.w, m.h, true, true); - ctx.fillStyle = THEME.ink; ctx.font = '900 19px ui-monospace, monospace'; ctx.textAlign = 'center'; ctx.fillText(`MIXER L${m.level}`, m.x + m.w / 2, m.y + 28); - ctx.font = '900 12px ui-monospace, monospace'; ctx.fillText(`PAY ${yen(upgradedMixerPrice(game))}`, m.x + m.w / 2, m.y + 48); + drawMetalPanel(ctx, m.x, m.y, m.w, m.h, '#2b333d', THEME.ink, THEME.mixerBlue); + drawFacilityDetails(ctx, m, THEME.mixerBlue); + ctx.fillStyle = THEME.white; ctx.font = '900 14px ui-monospace, monospace'; ctx.textAlign = 'left'; + ctx.fillText(`MIXER L${m.level}`, m.x + 14, m.y + 18); + ctx.fillStyle = THEME.muted; ctx.font = '900 10px ui-monospace, monospace'; + ctx.fillText(`PAY ${yen(upgradedMixerPrice(game))}`, m.x + 14, m.y + 34); + const drew = drawFacilityTexture(ctx, assets.mixerCompact.loaded ? assets.mixerCompact : assets.mixer, m, 2.05); + if (!drew) { + ctx.strokeStyle = THEME.green; ctx.lineWidth = 5; + for (let i = 0; i < 3; i += 1) { ctx.beginPath(); ctx.arc(m.x + m.w / 2, m.y + m.h / 2 + 6, 11 + i * 8, 0, Math.PI * 1.5); ctx.stroke(); } + } drawTargetBadge(ctx, m.x + 14, m.y + m.h - 40, m.w - 28, 'SEND MALE', 'male', 'safe meat route'); - ctx.strokeStyle = THEME.green; ctx.lineWidth = 5; - for (let i = 0; i < 3; i += 1) { ctx.beginPath(); ctx.arc(m.x + m.w / 2, m.y + 78, 16 + i * 8, 0, Math.PI * 1.5); ctx.stroke(); } drawDirtOverlay(ctx, m.x, m.y, m.w, m.h, m); drawSelection(ctx, game, 'facility', m.id, m.x + m.w / 2, m.y + m.h / 2, m.w + 12, m.h + 12); ctx.restore(); @@ -655,10 +965,15 @@ function drawMixer(ctx, game, m = game.facilities.mixer) { function drawTrash(ctx, game, t = game.facilities.trash) { ctx.save(); drawExternalDuct(ctx, t); - if (drawImageIfLoaded(ctx, assets.shredder, t.x, t.y, t.w, t.h)) { drawDirtOverlay(ctx, t.x, t.y, t.w, t.h, t); drawSelection(ctx, game, 'facility', t.id, t.x + t.w / 2, t.y + t.h / 2, t.w + 12, t.h + 12); ctx.restore(); return; } - ctx.fillStyle = THEME.white; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 4; rect(ctx, t.x, t.y, t.w, t.h, true, true); - ctx.fillStyle = THEME.ink; ctx.font = '900 19px ui-monospace, monospace'; ctx.textAlign = 'center'; ctx.fillText(`SHREDDER L${t.level}`, t.x + t.w / 2, t.y + 25); - for (let i = 0; i < 7; i += 1) { ctx.fillRect(t.x + 34 + i * 16, t.y + 48, 7, t.h - 66); } + drawMetalPanel(ctx, t.x, t.y, t.w, t.h, '#29342d', THEME.ink, THEME.wasteGreen); + drawFacilityDetails(ctx, t, THEME.wasteGreen); + ctx.fillStyle = THEME.white; ctx.font = '900 14px ui-monospace, monospace'; ctx.textAlign = 'left'; + ctx.fillText(`SHREDDER L${t.level}`, t.x + 14, t.y + 18); + const drew = drawFacilityTexture(ctx, assets.shredderCompact.loaded ? assets.shredderCompact : assets.shredder, t, 1.85); + if (!drew) { + ctx.fillStyle = '#0a0b0e'; + for (let i = 0; i < 7; i += 1) ctx.fillRect(t.x + 40 + i * 12, t.y + 42, 6, Math.max(20, t.h - 72)); + } drawTargetBadge(ctx, t.x + 14, t.y + t.h - 42, t.w - 28, 'SEND POOP', 'poop', 'shredder'); drawDirtOverlay(ctx, t.x, t.y, t.w, t.h, t); drawSelection(ctx, game, 'facility', t.id, t.x + t.w / 2, t.y + t.h / 2, t.w + 12, t.h + 12); @@ -667,14 +982,18 @@ function drawTrash(ctx, game, t = game.facilities.trash) { function drawTruck(ctx, game, t = game.facilities.truck) { ctx.save(); drawExternalDuct(ctx, t); - if (drawImageIfLoaded(ctx, assets.truck, t.x, t.y, t.w, t.h)) { drawSelection(ctx, game, 'facility', t.id, t.x + t.w / 2, t.y + t.h / 2, t.w + 12, t.h + 12); ctx.restore(); return; } - ctx.fillStyle = THEME.white; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 4; rect(ctx, t.x, t.y, t.w, t.h, true, true); - ctx.fillStyle = THEME.ink; ctx.font = '900 19px ui-monospace, monospace'; ctx.textAlign = 'center'; ctx.fillText(`TRUCK L${t.level}`, t.x + t.w / 2, t.y + 24); - ctx.font = '900 11px ui-monospace, monospace'; ctx.fillText(`UNIT ${yen(upgradedTruckPrice(game))}`, t.x + t.w / 2, t.y + 42); + drawMetalPanel(ctx, t.x, t.y, t.w, t.h, '#343128', THEME.ink, THEME.truckPink); + drawFacilityDetails(ctx, t, THEME.truckPink); + ctx.fillStyle = THEME.white; ctx.font = '900 14px ui-monospace, monospace'; ctx.textAlign = 'left'; + ctx.fillText(`TRUCK L${t.level}`, t.x + 14, t.y + 18); + ctx.fillStyle = THEME.muted; ctx.font = '900 10px ui-monospace, monospace'; + ctx.fillText(`UNIT ${yen(upgradedTruckPrice(game))}`, t.x + 14, t.y + 34); + drawFacilityTexture(ctx, assets.truckCompact.loaded ? assets.truckCompact : assets.truck, t, 2.0); const truckTargetType = targetForTruck(game); drawTargetBadge(ctx, t.x + 15, t.y + 50, t.w - 30, `SEND ${truckTargetType.toUpperCase()}`, truckTargetType, game.eventOffer && !game.eventActive ? 'next event' : 'truck cargo'); - ctx.fillStyle = THEME.greenSoft; rect(ctx, t.x + 13, t.y + 88, t.w - 26, t.h - 103, true, false); + ctx.fillStyle = 'rgba(39,60,36,.9)'; rect(ctx, t.x + 13, t.y + 88, t.w - 26, Math.max(18, t.h - 103), true, false); for (const cargo of game.truckCargo) cargo.sex === 'poop' ? drawTinyPoop(ctx, t.x + cargo.x, t.y + cargo.y) : drawTinyChick(ctx, t.x + cargo.x, t.y + cargo.y, cargo.sex, cargo.sex === 'male'); + drawDirtOverlay(ctx, t.x, t.y, t.w, t.h, t); drawSelection(ctx, game, 'facility', t.id, t.x + t.w / 2, t.y + t.h / 2, t.w + 12, t.h + 12); ctx.restore(); } @@ -695,13 +1014,32 @@ function drawChick(ctx, chick, active, game) { if (chick.sex === 'poop') drawPoop(ctx, chick.x, y, chick.radius); else { const img = chick.sex === 'male' ? assets.chickMale : assets.chickFemale; - if (!drawImageIfLoaded(ctx, img, chick.x - chick.radius, y - chick.radius, chick.radius * 2, chick.radius * 2)) { - ctx.fillStyle = chick.sex === 'male' ? THEME.male : THEME.female; + const spriteDrawn = drawImageIfLoaded(ctx, img, chick.x - chick.radius, y - chick.radius, chick.radius * 2, chick.radius * 2); + if (!spriteDrawn) { + const bodyColor = chick.sex === 'male' ? THEME.male : THEME.female; + const accent = chick.sex === 'male' ? '#164f8f' : '#8b2252'; + ctx.fillStyle = bodyColor; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 5; ctx.beginPath(); ctx.arc(chick.x, y, chick.radius, 0, Math.PI * 2); ctx.fill(); ctx.stroke(); + ctx.fillStyle = 'rgba(255,255,255,.24)'; ctx.beginPath(); ctx.arc(chick.x - 5, y - 7, chick.radius * .36, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = THEME.ink; ctx.beginPath(); ctx.arc(chick.x - 6, y - 5, 2.5, 0, Math.PI * 2); ctx.arc(chick.x + 6, y - 5, 2.5, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#ffaa2e'; ctx.beginPath(); ctx.moveTo(chick.x, y + 2); ctx.lineTo(chick.x + 9, y + 6); ctx.lineTo(chick.x, y + 10); ctx.closePath(); ctx.fill(); + ctx.strokeStyle = accent; ctx.lineWidth = 3; + if (chick.sex === 'male') { + ctx.beginPath(); ctx.moveTo(chick.x - 8, y - chick.radius - 2); ctx.lineTo(chick.x + 8, y - chick.radius - 2); ctx.stroke(); + } else { + ctx.beginPath(); ctx.moveTo(chick.x - 9, y - chick.radius + 2); ctx.lineTo(chick.x, y - chick.radius - 6); ctx.lineTo(chick.x + 9, y - chick.radius + 2); ctx.stroke(); + } } + // Symbols remain legible even when custom sprites are replaced. + ctx.fillStyle = chick.sex === 'male' ? '#dff1ff' : '#fff0f7'; + ctx.strokeStyle = '#050609'; + ctx.lineWidth = 3; + ctx.font = `900 ${Math.max(10, Math.round(chick.radius * .72))}px ui-monospace, monospace`; + ctx.textAlign = 'center'; + const sexMark = chick.sex === 'male' ? '♂' : '♀'; + ctx.strokeText(sexMark, chick.x + chick.radius * .54, y + chick.radius * .70); + ctx.fillText(sexMark, chick.x + chick.radius * .54, y + chick.radius * .70); } ctx.restore(); } @@ -721,8 +1059,14 @@ function drawPoop(ctx, x, y, radius) { } function drawTinyPoop(ctx, x, y) { drawPoop(ctx, x, y, 7); } function drawTinyChick(ctx, x, y, sex, warning = false) { - ctx.save(); ctx.fillStyle = sex === 'male' ? THEME.male : THEME.female; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 2; + ctx.save(); + const bodyColor = sex === 'male' ? THEME.male : THEME.female; + const accent = sex === 'male' ? '#164f8f' : '#8b2252'; + ctx.fillStyle = bodyColor; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(x, y, 7, 0, Math.PI * 2); ctx.fill(); ctx.stroke(); + ctx.strokeStyle = accent; ctx.lineWidth = 2; + if (sex === 'male') { ctx.beginPath(); ctx.moveTo(x - 4, y - 8); ctx.lineTo(x + 4, y - 8); ctx.stroke(); } + else { ctx.beginPath(); ctx.moveTo(x - 5, y - 7); ctx.lineTo(x, y - 11); ctx.lineTo(x + 5, y - 7); ctx.stroke(); } if (warning) { ctx.fillStyle = THEME.danger; ctx.font = '900 12px ui-monospace, monospace'; ctx.textAlign = 'center'; ctx.fillText('!', x, y + 15); } ctx.restore(); } @@ -784,9 +1128,12 @@ function drawCardTargetOverlay(ctx, canvas, game) { ctx.strokeStyle = THEME.ink; ctx.lineWidth = 3; const remaining = Math.max(1, game.cardTargetPick?.remaining || 1); + const dynamiteUsed = Math.max(0, game.cardTargetPick?.used || 0); const msg = game.cardTargetPick?.mode === 'autoScannerMenu' ? 'AUTO SCANNER ROUTE SETTINGS. CLICK EMPTY AREA TO CLOSE.' - : isBlockedCellMode ? `CLICK BLOCKED CELL: ${remaining} LEFT. PRESS ESC TO CANCEL.` : 'CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.'; + : isBlockedCellMode + ? `DYNAMITE: CLICK ANY BLOCKED TILE (${remaining} LEFT). ESC ${dynamiteUsed > 0 ? 'FINISHES' : 'CANCELS'}.` + : 'CLICK AN UPGRADEABLE MACHINE. PRESS ESC TO CANCEL.'; rect(ctx, (216 - (game.view?.x || 0)) / scale, (96 - (game.view?.y || 0)) / scale, 560 / scale, 42 / scale, true, true); ctx.fillStyle = THEME.ink; ctx.font = '900 12px ui-monospace, monospace'; @@ -835,10 +1182,19 @@ function drawFloatingTexts(ctx, game) { } function drawRepairman(ctx, game) { - const r = game.repairman; - const visible = !!r?.active || (game.phase === 'build' && !!r?.hiredForNextDay); + const list = (game.repairmen && game.repairmen.length) ? game.repairmen : (game.repairman ? [game.repairman] : []); + for (const r of list) drawSingleRepairman(ctx, game, r); +} + +function drawSingleRepairman(ctx, game, r) { + const visible = !!r?.active; if (!visible) return; ctx.save(); + if (drawImageIfLoaded(ctx, assets.repairman, r.x - 18, r.y - 18, 36, 36)) { + if (r.target?.label) label(ctx, r.x, r.y - 24, r.target.label, THEME.green); + ctx.restore(); + return; + } ctx.lineWidth = 3; ctx.fillStyle = '#fff0d1'; ctx.strokeStyle = THEME.ink; @@ -862,19 +1218,15 @@ function drawRepairman(ctx, game) { ctx.fillStyle = THEME.ink; ctx.font = '900 11px ui-monospace, monospace'; ctx.textAlign = 'center'; - ctx.fillText(r.active ? 'FIX' : 'HIRED', r.x, r.y + 33); + ctx.fillText('FIX', r.x, r.y + 33); if (r.target?.label) label(ctx, r.x, r.y - 24, r.target.label, THEME.green); - else if (!r.active && r.hiredForNextDay) label(ctx, r.x, r.y - 24, 'NEXT DAY', THEME.green); ctx.restore(); } + function drawCanvasHints(ctx, game, canvas) { ctx.save(); ctx.font = '900 19px ui-monospace, monospace'; ctx.textAlign = 'left'; ctx.fillStyle = THEME.ink; - // Visible version marker helps avoid browser/file-cache confusion when testing zips. - ctx.fillStyle = 'rgba(255,255,255,.92)'; ctx.strokeStyle = THEME.ink; ctx.lineWidth = 3; - rect(ctx, canvas.width - 284, 18, 260, 34, true, true); - ctx.fillStyle = THEME.green; ctx.font = '900 12px ui-monospace, monospace'; ctx.fillText(VERSION, canvas.width - 270, 40); ctx.font = '900 19px ui-monospace, monospace'; ctx.fillStyle = THEME.ink; const lines = []; if (game.phase === 'running') lines.push(game.timeLeft <= 0 ? 'TIME UP: FARMS SHUT. CLEAR LINE.' : 'A/D: S1 ←/→: S2'); diff --git a/src/systems/buildSystem.js b/src/systems/buildSystem.js index c10bc6f..6a94566 100644 --- a/src/systems/buildSystem.js +++ b/src/systems/buildSystem.js @@ -1,8 +1,8 @@ import { BALANCE } from '../core/balance.js'; import { DIRS, MACHINE_FACILITY_IDS, GRID, THEME } from '../core/config.js'; import { getSpawnRange } from '../core/state.js'; -import { createEggFarm, createScanner, createFacility } from '../core/entities.js'; -import { generateBlockedCellsInRect } from '../core/mapGen.js'; +import { createEggFarm, createScanner, createFacility, createMaintenanceRoom, maintenanceRoomFootprint } from '../core/entities.js'; +import { generateBlockedCellsInRect, blockedRatioForExpansionPurchase } from '../core/mapGen.js'; import { expansionCost, expansionLot, expansionLots, lotFromChunk, lotBounds, lotContainsPoint, cellsInLot, isOwnedCell, countOwnedCells, shiftRowIndexedSet, shiftRowIndexedMap, ownChunk } from '../core/gridExpansion.js'; import { key, parseKey, pointToCell, cellCenter, yen, directionNameBetweenCells } from '../core/utils.js'; import { TEXT, equipmentName } from '../core/text.js'; @@ -92,13 +92,18 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel game.gridExpansionPurchases = (game.gridExpansionPurchases || 0) + 1; game.gridExpansionPurchasesByDirection[direction] = (game.gridExpansionPurchasesByDirection[direction] || 0) + 1; syncGridSizeToGame(); + const blockedRatio = blockedRatioForExpansionPurchase(game.gridExpansionPurchases, { + base: BALANCE.map.blockedRatio ?? 0.03, + increment: BALANCE.map.blockedExpansionIncrement ?? 0.005, + max: BALANCE.map.blockedRatioMax ?? 0.10 + }); const blocked = generateBlockedCellsInRect({ seed: `${game.runSeed}:grid-expansion:${lot.chunkX},${lot.chunkY}:${game.gridExpansionPurchases}`, colStart: lot.colStart, colEnd: lot.colStart + lot.cols, rowStart: lot.rowStart, rowEnd: lot.rowStart + lot.rows, - targetRatio: BALANCE.map.blockedRatio + targetRatio: blockedRatio }); for (const k of blocked) game.blockedCells.add(k); refreshRoutingAfterEdit(game); @@ -106,7 +111,7 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel const b = lotBounds(lot); floating(game, b.x + b.w / 2, b.y + b.h / 2, `${direction.toUpperCase()} +${addedCells} CELLS -${yen(cost)}`, THEME.green); updatePanels(); - return { ok: true, direction, cost, addedCells, blocked: blocked.size, chunkX: lot.chunkX, chunkY: lot.chunkY }; + return { ok: true, direction, cost, addedCells, blocked: blocked.size, blockedRatio, chunkX: lot.chunkX, chunkY: lot.chunkY }; } function pointInGrid(col, row) { return col >= 0 && col < GRID.cols && row >= 0 && row < GRID.rows && isOwnedCell(game, col, row); } @@ -129,10 +134,32 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel if (existingFarm && !(moving?.type === 'eggFarm' && moving.ref?.id === existingFarm.id)) return true; const existingScanner = scannerAt(game, col, row); if (existingScanner && !(moving?.type === 'scanner' && moving.ref?.id === existingScanner.id)) return true; + const existingRoom = maintenanceRoomAt(game, col, row); + if (existingRoom && !(moving?.type === 'maintenanceRoom' && moving.ref?.id === existingRoom.id)) return true; if (game.conveyorTiles.has(k) && !(moving?.type === 'conveyor' && moving.oldKey === k)) return true; return false; } + function maintenanceRoomAt(gameRef, col, row) { + return (gameRef.maintenanceRooms || []).find(room => maintenanceRoomFootprint(room).some(cell => cell.col === col && cell.row === row)) || null; + } + + function maintenanceRoomPlacementBlocked(col, row, moving = null) { + const draft = { col, row }; + for (const cell of maintenanceRoomFootprint(draft)) { + if (!pointInGrid(cell.col, cell.row) || isBlockedCell(cell.col, cell.row)) return true; + const k = key(cell.col, cell.row); + const existingFarm = farmAt(game, cell.col, cell.row); + if (existingFarm) return true; + const existingScanner = scannerAt(game, cell.col, cell.row); + if (existingScanner) return true; + const existingRoom = maintenanceRoomAt(game, cell.col, cell.row); + if (existingRoom && !(moving?.type === 'maintenanceRoom' && moving.ref?.id === existingRoom.id)) return true; + if (game.conveyorTiles.has(k)) return true; + } + return false; + } + function scannerPlacementBlocked(col, row, moving = null) { const draft = { col, row }; for (const cell of scannerFootprintCells(draft)) { @@ -153,6 +180,7 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel if (game.selected.type === 'scanner') return game.scanners.find(s => s.id === game.selected.id) || null; if (game.selected.type === 'conveyor') return game.conveyorTiles.has(game.selected.id) ? { type: 'conveyor', id: game.selected.id } : null; if (game.selected.type === 'facility') return game.facilities[game.selected.id] || null; + if (game.selected.type === 'maintenanceRoom') return (game.maintenanceRooms || []).find(r => r.id === game.selected.id) || null; return null; } @@ -162,6 +190,7 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel if (obj.type === 'scanner') return `${obj.kind === 'auto' ? equipmentName('autoScanner') : equipmentName('manualScanner')} #${obj.id}`; if (obj.type === 'conveyor') return game.conveyorMeta.get(obj.id)?.kind === 'boostConveyor' ? equipmentName('boostConveyor') : equipmentName('conveyor'); if (obj.type === 'facility') return obj.name; + if (obj.type === 'maintenanceRoom') return `${equipmentName('maintenanceRoom')} #${obj.id}`; return 'Equipment'; } @@ -266,16 +295,18 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel return connected; } - function branchSelectableEntranceDirsForKey(k) { + function branchSelectableExitDirsForKey(k) { const cell = parseKey(k); const connected = branchExitDirsForKey(k); if (connected.length < 3) return []; + const meta = game.conveyorMeta.get(k) || {}; const physicalEntrances = new Set(connected.filter(dir => neighborPointsIntoCell(cell, dir))); - return connected.filter(dir => { - const entrances = new Set(physicalEntrances); - entrances.add(dir); - return connected.filter(item => !entrances.has(item)).length >= 2; - }); + const physicalExits = connected.filter(dir => !physicalEntrances.has(dir)); + if (physicalEntrances.size && physicalExits.length >= 2) return physicalExits; + const explicit = [...new Set([...(Array.isArray(meta.outDirs) ? meta.outDirs : []), meta.dir].filter(Boolean))] + .filter(dir => connected.includes(dir)); + if (explicit.length >= 2) return explicit; + return connected; } function markConveyorDirection(from, to) { @@ -502,6 +533,10 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel return; } if (isBlockedCell(col, row)) return fail('Cannot build on blocked ground.'); + if (game.buildTool === 'maintenanceRoom') { + if (maintenanceRoomPlacementBlocked(col, row)) return fail(TEXT.fail.cellOccupied); + return buildMaintenanceRoom(col, row); + } if ((game.buildTool === 'manualScanner' || game.buildTool === 'autoScanner') ? scannerPlacementBlocked(col, row) : isEquipmentCell(col, row)) return fail(TEXT.fail.cellOccupied); if (game.buildTool === 'eggFarm') buildFarm(col, row); else if (game.buildTool === 'manualScanner') buildScanner(col, row, 'manual'); @@ -510,7 +545,7 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel function buildAtPoint(p) { const cell = pointToCell(p.x, p.y); - if (['conveyor', 'boostConveyor', 'eggFarm', 'manualScanner', 'autoScanner'].includes(game.buildTool)) return buildAtCell(cell); + if (['conveyor', 'boostConveyor', 'eggFarm', 'manualScanner', 'autoScanner', 'maintenanceRoom'].includes(game.buildTool)) return buildAtCell(cell); if (MACHINE_FACILITY_IDS.includes(game.buildTool)) return buildFacility(p, game.buildTool); } @@ -542,6 +577,26 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel floating(game, cellCenter(col, row).x, cellCenter(col, row).y, `-${yen(cost)}`, THEME.ink); } + function buildMaintenanceRoom(col, row) { + const cost = buildPrice('maintenanceRoom', game); + if (game.cash < cost) return fail(TEXT.fail.notEnoughCash); + if (maintenanceRoomPlacementBlocked(col, row)) return fail(TEXT.fail.cellOccupied); + record(game); + spendCash(game, cost); + const room = applyBuildQuality(createMaintenanceRoom(game, col, row)); + room.price = cost; + game.maintenanceRooms = game.maintenanceRooms || []; + game.maintenanceRooms.push(room); + game.selected = { type: 'maintenanceRoom', id: room.id }; + const center = roomCenter(room); + floating(game, center.x, center.y, `-${yen(cost)}`, THEME.ink); + } + + function roomCenter(room) { + const first = cellCenter(room.col, room.row); + return { x: first.x + GRID.cell / 2, y: first.y + GRID.cell / 2 }; + } + function buildFacility(p, id) { const cost = buildPrice(id, game); if (game.cash < cost) return fail(TEXT.fail.notEnoughCash); @@ -603,6 +658,13 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel eraseEffect(game, f.x + f.w / 2, f.y + f.h / 2); refreshRoutingAfterEdit(game); } + if (hit.type === 'maintenanceRoom') { + const room = hit.ref; + const center = roomCenter(room); + refundOrSell(hit, center.x, center.y); + game.maintenanceRooms = (game.maintenanceRooms || []).filter(r => r.id !== room.id); + eraseEffect(game, center.x, center.y); + } game.selected = null; game.multiSelected = []; updatePanels(); @@ -623,6 +685,8 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel if (farm) return { type: 'eggFarm', ref: farm }; const scanner = scannerAt(game, cell.col, cell.row); if (scanner) return { type: 'scanner', ref: scanner }; + const room = maintenanceRoomAt(game, cell.col, cell.row); + if (room) return { type: 'maintenanceRoom', ref: room }; const k = key(cell.col, cell.row); if (game.conveyorTiles.has(k)) return { type: 'conveyor', oldKey: k, ref: { type: 'conveyor', id: k } }; return null; @@ -641,6 +705,7 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel else if (obj.type === 'eggFarm') eraseAtPoint(cellCenter(obj.col, obj.row)); else if (obj.type === 'scanner') eraseAtPoint(scannerCenter(obj)); else if (obj.type === 'facility') eraseAtPoint({ x: obj.x + obj.w / 2, y: obj.y + obj.h / 2 }); + else if (obj.type === 'maintenanceRoom') eraseAtPoint(roomCenter(obj)); } function modalButton(text, onClick, className = 'primary-button') { @@ -798,6 +863,14 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel ui.modalActions.innerHTML = ''; if (obj.type === 'scanner' && obj.kind === 'auto') ui.modalActions.appendChild(modalButton('Auto Menu', () => showAutoScannerMenu(obj), 'facility-action warn')); if (obj.type === 'scanner' && obj.kind === 'manual') ui.modalActions.appendChild(modalButton('Set Keys', () => showManualScannerMenu(obj), 'facility-action warn')); + if (obj.type === 'conveyor' && isBranchKey(obj.id)) { + const mode = game.conveyorMeta.get(obj.id)?.branchMode || 'random'; + ui.modalActions.appendChild(modalButton(`Branch: ${branchModeLabel(mode)}`, () => { + cycleBranchModeForKey(obj.id); + game.selected = { type: 'conveyor', id: obj.id }; + showSelectedMenu(); + }, 'facility-action warn branch-action')); + } const hit = obj.type === 'conveyor' ? { type: 'conveyor', oldKey: obj.id, ref: obj } : { type: obj.type, ref: obj }; const saleReason = lastProtectedSaleReason(hit); if (saleReason) { @@ -829,6 +902,7 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel boxes.push({ id: `facility:${id}`, price: equipmentPrice({ type: 'facility', ref: f }), x: f.x, y: f.y, w: f.w, h: f.h }); if (f.entry) { const c = cellCenter(f.entry.col, f.entry.row); boxes.push({ id: `facilityPort:${id}`, price: equipmentPrice({ type: 'facility', ref: f }), x: c.x - 18, y: c.y - 18, w: 36, h: 36 }); } } + for (const room of game.maintenanceRooms || []) { const c = roomCenter(room); boxes.push({ id: `maintenanceRoom:${room.id}`, price: equipmentPrice({ type: 'maintenanceRoom', ref: room }), x: c.x - GRID.cell, y: c.y - GRID.cell, w: GRID.cell * 2, h: GRID.cell * 2 }); } for (const farm of game.eggFarms) { const c = cellCenter(farm.col, farm.row); boxes.push({ id: `eggFarm:${farm.id}`, price: equipmentPrice({ type: 'eggFarm', ref: farm }), x: c.x - 24, y: c.y - 24, w: 48, h: 48 }); } for (const scanner of game.scanners) { const c = scannerCenter(scanner); boxes.push({ id: `scanner:${scanner.id}`, price: equipmentPrice({ type: 'scanner', ref: scanner }), x: c.x - 50, y: c.y - 73, w: 100, h: 146 }); } for (const k of game.conveyorTiles) { @@ -869,19 +943,19 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel function cycleBranchModeAtPoint(p) { const k = branchSwitcherAtPoint(p); if (!k) return false; - cycleBranchModeForKey(k); - return true; + return cycleBranchModeForKey(k); } function cycleBranchModeForKey(k) { const meta = game.conveyorMeta.get(k); if (!meta) return false; - const reachable = branchSelectableEntranceDirsForKey(k); + const reachable = branchSelectableExitDirsForKey(k); if (reachable.length < 2) return false; record(game); const current = BRANCH_MODES.includes(meta.branchMode) ? meta.branchMode : 'random'; const modes = ['random', ...DIRS.map(d => d.name).filter(mode => reachable.includes(mode))]; meta.branchMode = modes[(Math.max(0, modes.indexOf(current)) + 1) % modes.length]; + refreshRoutingAfterEdit(game); game.selected = null; game.multiSelected = []; updatePanels(); @@ -920,11 +994,16 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel lines.push(`Durability: ${remainingPercent({ meta })}% | Speed x${performanceFactor({ meta }).toFixed(2)}`); if (isBranchKey(obj.id)) { lines.push(`Branch mode: ${branchModeLabel(meta?.branchMode || 'random')}`); - lines.push('Use the Branch button below or the on-belt branch badge.'); + lines.push('Click the Branch button or the large on-belt badge to cycle RANDOM / fixed exit.'); } else { lines.push('Branch mode: needs 3+ conveyor connections.'); } lines.push(`Sale value: ${yen(resaleValueFor({ type: 'conveyor', oldKey: obj.id, ref: obj }, game).amount)}`); + } else if (obj.type === 'maintenanceRoom') { + lines.push(`Price: ${yen(equipmentPrice({ type: 'maintenanceRoom', ref: obj }))}`); + lines.push(`Sale value: ${yen(resaleValueFor({ type: 'maintenanceRoom', ref: obj }, game).amount)}`); + lines.push('Size: 2×2 grid cells'); + lines.push('Dispatch: 1 repairman during each production day'); } else if (obj.type === 'facility') { lines.push(`Price: ${yen(equipmentPrice(obj))}`); { const reason = lastProtectedSaleReason({ type: obj.type, ref: obj }); lines.push(reason ? `Sale: blocked (${reason})` : `Sale value: ${yen(resaleValueFor({ type: obj.type, ref: obj }, game).amount)}`); } @@ -969,6 +1048,7 @@ export function createBuildSystem({ game, ui, canvas, canvasPoint, onUpdatePanel if (obj.type === 'facility' && (obj.baseId || obj.id) === 'mixer') return 'Male chicks become revenue here. Do not feed it poop.'; if (obj.type === 'facility' && (obj.baseId || obj.id) === 'trash') return 'Poop goes in. Sometimes coins come out, for reasons best left unaudited.'; if (obj.type === 'facility' && (obj.baseId || obj.id) === 'truck') return 'The shipping endpoint. Correct cargo pays; wrong cargo complains.'; + if (obj.type === 'maintenanceRoom') return 'A cramped 2×2 storage and break room with lockers, spare parts, a bench and one dispatched repairman.'; return 'Factory equipment.'; } diff --git a/src/systems/cards.js b/src/systems/cards.js index 091504a..098cfb0 100644 --- a/src/systems/cards.js +++ b/src/systems/cards.js @@ -213,8 +213,7 @@ function cardAtCap(game, card) { } function repairmanCardVisible(game) { - const r = game.repairman || {}; - return !!(r.active || r.hiredForNextDay || game.pendingRepairWorkerWages > 0); + return !!((game.maintenanceRooms || []).length || (game.repairmen || []).length || game.repairman?.active); } function availableCards(game) { @@ -506,8 +505,9 @@ function cardDescription(game, card) { if (card.id === 'flattery') return `Next Fairies tribute -50%. Held for next tribute: ${e.fairiesFlatteryNext || 0}.`; if (card.id === 'usedMachine') return 'Enable Used Machines: future equipment costs 50%, has no SELL refund, and starts with 60% durability.'; if (card.id === 'newMachine') return 'Cancel Used Machines. Future equipment returns to normal price, refund, and durability.'; - if (card.id === 'laborExploitation') return 'Repairman labor cost -30% permanently. One time only.'; + if (card.id === 'laborExploitation') return 'Repairman dispatch paperwork is streamlined. Repair rooms keep operating; one time only.'; if (card.id === 'rescueLoan') return `At day-end bankruptcy check, gain ${yen(500)} if cash is below ${yen(0)}. Held: ${e.rescueLoanCharges || 0}.`; + if (card.id === 'dynamite') return 'Choose any blocked tiles on the map and destroy up to 3. Empty-space clicks are ignored; press Esc to finish after at least one blast.'; return card.description; } @@ -610,7 +610,8 @@ export function createCardSystem({ game, ui, onUpdatePanels }) { cardId: card.id, mode: card.target === 'blockedCell' ? 'blockedCell' : 'equipment', targetKeys: targets.map(targetKey), - remaining: card.id === 'dynamite' ? Math.min(3, targets.length) : 1 + remaining: card.id === 'dynamite' ? Math.min(3, targets.length) : 1, + used: 0 }; ui.modal.classList.remove('visible', 'equipment-popover'); updatePanels(); @@ -630,6 +631,7 @@ export function createCardSystem({ game, ui, onUpdatePanels }) { floating(game, c.x, c.y - 18, 'BOOM', THEME.danger); refreshRoutingAfterEdit(game); game.cardTargetPick.remaining = Math.max(0, (game.cardTargetPick.remaining || 1) - 1); + game.cardTargetPick.used = Math.max(0, game.cardTargetPick.used || 0) + 1; game.cardTargetPick.targetKeys = targetsForCard(game, 'dynamite').map(targetKey); updatePanels(); return true; @@ -639,15 +641,21 @@ export function createCardSystem({ game, ui, onUpdatePanels }) { if (!game.cardTargetPick?.pending) return false; const card = cardById(game.cardTargetPick.cardId); const target = targetAtPoint(game, p); - if (!card || !target) { + if (!card) { cancelTargetPick(); return true; } if (card.id === 'dynamite') { + // Empty-space clicks do nothing: the player may freely choose any highlighted tile. + if (!target) return true; if (!applyDynamiteTarget(target)) return true; if ((game.cardTargetPick.remaining || 0) <= 0 || !targetsForCard(game, 'dynamite').length) completePickedCard(card); return true; } + if (!target) { + cancelTargetPick(); + return true; + } applyEquipmentUpgrade(game, target); completePickedCard(card); return true; @@ -655,6 +663,15 @@ export function createCardSystem({ game, ui, onUpdatePanels }) { function cancelTargetPick() { if (!game.cardTargetPick?.pending) return; + const activePick = game.cardTargetPick; + const card = cardById(activePick.cardId); + // Once a dynamite charge has been used, Escape finishes the card instead of + // returning a partially consumed card to the draft. Before the first blast, + // Escape still cancels normally. + if (card?.id === 'dynamite' && (activePick.used || 0) > 0) { + completePickedCard(card); + return; + } game.cardTargetPick = null; showDraft(); } @@ -678,6 +695,36 @@ export function createCardSystem({ game, ui, onUpdatePanels }) { showDraft(); } + + function cardIconFor(card) { + const tags = new Set(card.tags || []); + const byTarget = { + eggFarm: { type: 'image', src: './assets/dark_factory/facilities/machines/egg_farm_16.png', alt: 'EGG' }, + eggOutlet: { type: 'image', src: './assets/dark_factory/facilities/machines/egg_farm_16.png', alt: 'EGG' }, + autoScanner: { type: 'image', src: './assets/dark_factory/facilities/machines/auto_scanner_32x48.png', alt: 'SCAN' }, + mixer: { type: 'image', src: './assets/dark_factory/facilities/machines/mixer_compact_16.png', alt: 'MIX' }, + truck: { type: 'image', src: './assets/dark_factory/facilities/vehicles/truck_compact_16.png', alt: 'TRUCK' }, + trash: { type: 'image', src: './assets/dark_factory/facilities/machines/shredder_compact_16.png', alt: 'SHR' }, + blockedCell: { type: 'image', src: './assets/dark_factory/facilities/utility/obstacle_crate_16.png', alt: 'BLOCK' } + }; + if (byTarget[card.target]) return byTarget[card.target]; + if (card.id === 'bearing' || tags.has('CONVEYOR')) return { type: 'image', src: './assets/dark_factory/facilities/conveyor/conveyor_straight_h_16.png', alt: 'BELT' }; + if (tags.has('SCANNER')) return { type: 'image', src: './assets/dark_factory/facilities/machines/auto_scanner_32x48.png', alt: 'SCAN' }; + if (tags.has('EGG')) return { type: 'image', src: './assets/dark_factory/facilities/machines/egg_farm_16.png', alt: 'EGG' }; + if (tags.has('POOP')) return { type: 'glyph', text: '💩' }; + if (tags.has('MAINTENANCE')) return { type: 'image', src: './assets/dark_factory/facilities/utility/repairman_16.png', alt: 'FIX' }; + if (tags.has('CARD')) return { type: 'glyph', text: '▣' }; + if (tags.has('ECONOMY')) return { type: 'glyph', text: '¥' }; + if (tags.has('RISK')) return { type: 'glyph', text: '!' }; + return { type: 'glyph', text: '◆' }; + } + + function cardIconHtml(card) { + const icon = cardIconFor(card); + if (icon.type === 'image') return `
${icon.alt || ''}
`; + return ``; + } + function cardButton(card, index) { const b = document.createElement('button'); b.type = 'button'; @@ -685,7 +732,7 @@ export function createCardSystem({ game, ui, onUpdatePanels }) { b.className = `card-choice ${kind}`; const rarity = card.type === 'dud' ? 'MISS' : (card.rarity === 'ultraRare' ? 'ULTRA RARE' : (card.rarity === 'rare' ? 'RARE' : 'COMMON')); const tags = [rarity, ...(card.tags || []).filter(tag => tag !== rarity)].slice(0, 5); - b.innerHTML = `${card.title}
${tags.map(tag => `${tag}`).join('')}
${cardDescription(game, card)}`; + b.innerHTML = `${cardIconHtml(card)}
${card.title}
${tags.map(tag => `${tag}`).join('')}
${cardDescription(game, card)}
`; b.addEventListener('click', () => chooseCard(card, b)); b.dataset.index = String(index); return b; diff --git a/src/systems/chickSystem.js b/src/systems/chickSystem.js index 0282165..1662557 100644 --- a/src/systems/chickSystem.js +++ b/src/systems/chickSystem.js @@ -249,15 +249,13 @@ export function createChickSystem({ game, currentConveyorSpeed, onGameOverCheck const connected = conveyorNeighborDirNames(cell); if (connected.length < 3) return dirs; const entrances = new Set(connected.filter(dir => neighborPointsIntoCell(cell, dir))); - if (branchMode && branchMode !== 'random' && branchMode !== 'pass' && connected.includes(branchMode)) { - const selectedEntrances = new Set(entrances); - selectedEntrances.add(branchMode); - if (connected.filter(dir => !selectedEntrances.has(dir)).length >= 2) entrances.add(branchMode); - } - const exits = connected.filter(dir => !entrances.has(dir)); - if (exits.length) return exits; - const fallback = dirs.filter(dir => !entrances.has(dir)); - return fallback.length ? fallback : dirs; + const physicalExits = connected.filter(dir => !entrances.has(dir)); + let candidates = entrances.size && physicalExits.length >= 2 + ? physicalExits + : [...new Set(dirs.filter(dir => connected.includes(dir)))]; + if (candidates.length < 2) candidates = connected; + if (branchMode && branchMode !== 'random' && branchMode !== 'pass' && candidates.includes(branchMode)) return [branchMode]; + return candidates; } function optionAvailableForBranch(chick, opt) { diff --git a/src/systems/economy.js b/src/systems/economy.js index 8dd772d..89a094a 100644 --- a/src/systems/economy.js +++ b/src/systems/economy.js @@ -25,6 +25,7 @@ export function equipmentBasePrice(objOrHit) { if (type === 'eggFarm') return obj.price || FACILITY_DEFS.eggFarm.price; if (type === 'scanner') return obj.price || (obj.kind === 'auto' ? FACILITY_DEFS.autoScanner.price : FACILITY_DEFS.manualScanner.price); if (type === 'facility') return obj.price || FACILITY_DEFS[obj.id]?.price || 0; + if (type === 'maintenanceRoom') return obj.price || FACILITY_DEFS.maintenanceRoom.price; return FACILITY_DEFS[obj.id]?.price || 0; } diff --git a/src/systems/maintenance.js b/src/systems/maintenance.js index 2c9ffaa..6321b38 100644 --- a/src/systems/maintenance.js +++ b/src/systems/maintenance.js @@ -1,7 +1,6 @@ import { BALANCE } from '../core/balance.js'; import { GRID, THEME } from '../core/config.js'; -import { cellCenter, parseKey, key, yen } from '../core/utils.js'; -import { spendCash } from './economy.js'; +import { cellCenter, parseKey, key } from '../core/utils.js'; import { floating } from './effects.js'; const RULES = BALANCE.maintenance; @@ -25,19 +24,25 @@ export function durabilityCapFor(game, type, qualityMultiplier = 1) { return Math.max(1, Math.ceil(base * Math.max(0.1, qualityMultiplier || 1) * durabilityMultiplier(game))); } -export function repairmanDailyCost(game) { - const base = RULES.repairman.dailyCost; - return game?.cardEffects?.laborExploitation ? Math.ceil(base * 0.7) : base; -} - function qualityMultiplierOf(objOrMeta) { return Math.max(0.1, Number(objOrMeta?.durabilityBaseMultiplier) || 1); } +function maintenanceRoomCenter(room, index = 0) { + if (!room) return { x: GRID.x + GRID.cell * (0.5 + index * 0.55), y: GRID.y + GRID.rows * GRID.cell + 84 }; + const x = GRID.x + room.col * GRID.cell + GRID.cell; + const y = GRID.y + room.row * GRID.cell + GRID.cell; + return { x, y }; +} + +function repairmanHome(game, index = 0) { + const room = (game.maintenanceRooms || [])[index]; + return maintenanceRoomCenter(room, index); +} + export function ensureMaintenanceState(game) { if (!game.repairman) { game.repairman = { - hiredForNextDay: false, active: false, x: GRID.x + GRID.cell * 0.5, y: GRID.y + GRID.rows * GRID.cell + 84, @@ -45,6 +50,8 @@ export function ensureMaintenanceState(game) { repairedToday: 0 }; } + if (!Array.isArray(game.maintenanceRooms)) game.maintenanceRooms = []; + if (!Array.isArray(game.repairmen)) game.repairmen = []; for (const [k, meta] of game.conveyorMeta || []) { if (meta.uses == null) meta.uses = 0; if (meta.maintenanceType == null) meta.maintenanceType = 'conveyor'; @@ -240,28 +247,32 @@ export function repairAllEquipment(game, percent = 0.02) { return repaired; } -export function hireRepairmanForNextDay(game) { - ensureMaintenanceState(game); - if (game.repairman.hiredForNextDay) return { ok: false, reason: 'Repairman already hired.' }; - const cost = repairmanDailyCost(game); - if (game.cash < cost) return { ok: false, reason: `Need ${yen(cost - game.cash)} more.` }; - spendCash(game, cost); - game.pendingRepairWorkerWages = (game.pendingRepairWorkerWages || 0) + cost; - game.totals.repairWorkerWages = (game.totals.repairWorkerWages || 0) + cost; - game.repairman.hiredForNextDay = true; - return { ok: true, cost }; -} - export function activateRepairmanForDay(game) { ensureMaintenanceState(game); - game.repairman.active = !!game.repairman.hiredForNextDay; - game.repairman.hiredForNextDay = false; - game.repairman.target = null; + const rooms = game.maintenanceRooms || []; + game.repairmen = rooms.map((room, index) => { + const home = repairmanHome(game, index); + return { + id: `room-${room.id}`, + roomId: room.id, + active: true, + x: home.x, + y: home.y, + target: null, + repairedToday: 0 + }; + }); + const first = game.repairmen[0]; + game.repairman.active = !!first; + game.repairman.target = first?.target || null; game.repairman.repairedToday = 0; + if (first) { game.repairman.x = first.x; game.repairman.y = first.y; } } export function deactivateRepairman(game) { ensureMaintenanceState(game); + for (const r of game.repairmen || []) { r.active = false; r.target = null; } + game.repairmen = []; game.repairman.active = false; game.repairman.target = null; } @@ -284,14 +295,34 @@ function chooseRepairTarget(game) { export function updateRepairman(game, dt) { ensureMaintenanceState(game); - const r = game.repairman; - if (!r.active || game.phase !== 'running') return; - let target = resolveStoredTarget(game, r.target) || chooseRepairTarget(game); + const repairmen = game.repairmen?.length ? game.repairmen : (game.repairman?.active ? [game.repairman] : []); + if (!repairmen.length || game.phase !== 'running') return; + const assigned = new Set(repairmen.map(r => r.target?.key).filter(Boolean)); + for (const r of repairmen) updateSingleRepairman(game, r, dt, assigned); + const first = repairmen[0]; + if (first && game.repairman !== first) { + game.repairman.active = true; + game.repairman.x = first.x; + game.repairman.y = first.y; + game.repairman.target = first.target; + game.repairman.repairedToday = first.repairedToday || 0; + } +} + +function updateSingleRepairman(game, r, dt, assigned) { + if (!r.active) return; + let target = resolveStoredTarget(game, r.target); + if (!target || targetWear(target) <= 0.001) { + if (r.target?.key) assigned.delete(r.target.key); + target = chooseRepairTargetAvoiding(game, assigned); + } if (!target) { r.target = null; return; } - r.target = { key: targetKey(target), label: target.label }; + const tKey = targetKey(target); + assigned.add(tKey); + r.target = { key: tKey, label: target.label }; const speed = RULES.repairman.walkSpeed; const dx = target.center.x - r.x; const dy = target.center.y - r.y; @@ -302,16 +333,32 @@ export function updateRepairman(game, dt) { r.y += dy / dist * step; return; } - const repairWear = dt / (RULES.repairman.secondsPerOnePercent * 100); + const workTimeMultiplier = game?.cardEffects?.laborExploitation ? 0.7 : 1; + const repairWear = dt / (RULES.repairman.secondsPerOnePercent * workTimeMultiplier * 100); const usesBefore = targetUses(target); const usesDelta = repairWear * targetDurability(target); reduceTargetUses(target, usesDelta); const repairedPct = Math.max(0, (usesBefore - targetUses(target)) / targetDurability(target) * 100); r.repairedToday = (r.repairedToday || 0) + repairedPct; if (repairedPct > 0 && Math.random() < 0.02) floating(game, r.x, r.y - 28, 'REPAIR', THEME.green); - if (targetWear(target) <= 0.001) r.target = null; + if (targetWear(target) <= 0.001) { + assigned.delete(tKey); + r.target = null; + } } +function chooseRepairTargetAvoiding(game, assigned = new Set()) { + let best = null; + for (const t of equipmentMaintenanceTargets(game)) { + if (assigned.has(targetKey(t))) continue; + const w = targetWear(t); + if (w <= 0.001) continue; + if (!best || w > targetWear(best)) best = t; + } + return best || chooseRepairTarget(game); +} + + function worstDegradation(game) { let worst = 0; let label = 'none'; @@ -325,5 +372,5 @@ function worstDegradation(game) { export function maintenanceSummary(game) { const worst = worstDegradation(game); const avgBeltPerformance = averageConveyorPerformance(game); - return { worst, avgBeltPerformance, repairman: game.repairman || null }; + return { worst, avgBeltPerformance, repairman: game.repairman || null, repairmen: game.repairmen || [], rooms: game.maintenanceRooms || [] }; } diff --git a/src/systems/routing.js b/src/systems/routing.js index a7f9a52..99a74c2 100644 --- a/src/systems/routing.js +++ b/src/systems/routing.js @@ -138,19 +138,14 @@ function inferredConveyorOutDirNames(game, cellKey) { .filter(d => game.conveyorTiles.has(graphNodeKey(p.col + d.dc, p.row + d.dr))) .map(d => d.name); const explicit = conveyorOutDirNames(game, cellKey).filter(dir => neighbors.includes(dir)); - const inferred = neighbors; - const dirs = explicit.length ? explicit : inferred; + const dirs = explicit.length ? explicit : neighbors; if (neighbors.length < 3) return dirs; const entrances = new Set(neighbors.filter(dir => neighborPointsIntoCell(game, p, dir))); - if (meta.branchMode && meta.branchMode !== 'random' && neighbors.includes(meta.branchMode)) { - const selectedEntrances = new Set(entrances); - selectedEntrances.add(meta.branchMode); - if (neighbors.filter(dir => !selectedEntrances.has(dir)).length >= 2) entrances.add(meta.branchMode); - } - const exits = neighbors.filter(dir => !entrances.has(dir)); - if (exits.length) return exits; - const fallback = dirs.filter(dir => !entrances.has(dir)); - return fallback.length ? fallback : dirs; + const physicalExits = neighbors.filter(dir => !entrances.has(dir)); + let candidates = entrances.size && physicalExits.length >= 2 ? physicalExits : [...new Set(dirs)]; + if (candidates.length < 2) candidates = neighbors; + if (meta.branchMode && meta.branchMode !== 'random' && candidates.includes(meta.branchMode)) return [meta.branchMode]; + return candidates; } function emptyFactoryGraph(game) { diff --git a/src/systems/selectionSystem.js b/src/systems/selectionSystem.js index 505a729..0aaab89 100644 --- a/src/systems/selectionSystem.js +++ b/src/systems/selectionSystem.js @@ -1,6 +1,6 @@ import { GRID } from '../core/config.js'; import { key, parseKey, cellCenter } from '../core/utils.js'; -import { nearestGridEdge, layoutFacilityOnEdge } from '../core/entities.js'; +import { nearestGridEdge, layoutFacilityOnEdge, maintenanceRoomFootprint } from '../core/entities.js'; import { farmAt, scannerAt, scannerCenter, scannerFootprintCells, refreshRoutingAfterEdit } from './routing.js'; import { snapshot } from './history.js'; import { buildPrice } from './economy.js'; @@ -10,6 +10,7 @@ export function createSelectionSystem({ game, canvasPoint, updatePanels, equipme if (!item) return ''; if (item.type === 'conveyor') return `conveyor:${item.id || item.oldKey}`; if (item.type === 'facility') return `facility:${item.id || item.ref?.id}`; + if (item.type === 'maintenanceRoom') return `maintenanceRoom:${item.id || item.ref?.id}`; return `${item.type}:${item.id || item.ref?.id}`; } @@ -29,6 +30,7 @@ export function createSelectionSystem({ game, canvasPoint, updatePanels, equipme if (sel.type === 'eggFarm') return game.eggFarms.find(f => f.id === sel.id) || null; if (sel.type === 'scanner') return game.scanners.find(sc => sc.id === sel.id) || null; if (sel.type === 'facility') return game.facilities[sel.id] || null; + if (sel.type === 'maintenanceRoom') return (game.maintenanceRooms || []).find(r => r.id === sel.id) || null; if (sel.type === 'conveyor') return game.conveyorTiles.has(sel.id) ? { type: 'conveyor', id: sel.id } : null; return null; } @@ -42,6 +44,10 @@ export function createSelectionSystem({ game, canvasPoint, updatePanels, equipme } for (const farm of game.eggFarms) items.push({ type: 'eggFarm', id: farm.id, ref: farm, center: cellCenter(farm.col, farm.row), cell: { col: farm.col, row: farm.row } }); for (const scanner of game.scanners) items.push({ type: 'scanner', id: scanner.id, ref: scanner, center: scannerCenter(scanner), cell: { col: scanner.col, row: scanner.row } }); + for (const room of game.maintenanceRooms || []) { + const c = cellCenter(room.col, room.row); + items.push({ type: 'maintenanceRoom', id: room.id, ref: room, center: { x: c.x + GRID.cell / 2, y: c.y + GRID.cell / 2 }, cell: { col: room.col, row: room.row } }); + } for (const f of Object.values(game.facilities)) { const bodyCenter = { x: f.x + f.w / 2, y: f.y + f.h / 2 }; const portCenter = f.entry ? cellCenter(f.entry.col, f.entry.row) : bodyCenter; @@ -117,7 +123,7 @@ export function createSelectionSystem({ game, canvasPoint, updatePanels, equipme const cell = parseKey(sel.id); return { ...sel, obj, oldKey: sel.id, currentKey: sel.id, meta: game.conveyorMeta.get(sel.id) || { price: buildPrice('conveyor'), builtSession: null }, col: cell.col, row: cell.row }; } - if (sel.type === 'eggFarm' || sel.type === 'scanner') return { ...sel, obj, col: obj.col, row: obj.row }; + if (sel.type === 'eggFarm' || sel.type === 'scanner' || sel.type === 'maintenanceRoom') return { ...sel, obj, col: obj.col, row: obj.row }; if (sel.type === 'facility') return { ...sel, obj, x: obj.x, y: obj.y, w: obj.w, h: obj.h, entry: obj.entry ? { ...obj.entry } : null, side: obj.side, center: { x: obj.x + obj.w / 2, y: obj.y + obj.h / 2 } }; return null; } @@ -149,6 +155,8 @@ export function createSelectionSystem({ game, canvasPoint, updatePanels, equipme if (farm && !selectedTokens.has(`eggFarm:${farm.id}`)) return true; const scanner = scannerAt(game, col, row); if (scanner && !selectedTokens.has(`scanner:${scanner.id}`)) return true; + const room = (game.maintenanceRooms || []).find(item => maintenanceRoomFootprint(item).some(cell => cell.col === col && cell.row === row)); + if (room && !selectedTokens.has(`maintenanceRoom:${room.id}`)) return true; if (game.conveyorTiles.has(k) && !selectedTokens.has(`conveyor:${k}`)) return true; return false; } @@ -192,7 +200,7 @@ export function createSelectionSystem({ game, canvasPoint, updatePanels, equipme for (const origin of game.groupDrag.origins) { if (origin.type === 'facility') continue; const col = origin.col + dcol, row = origin.row + drow; - const cells = origin.type === 'scanner' ? scannerFootprintCells({ col, row }) : [{ col, row }]; + const cells = origin.type === 'scanner' ? scannerFootprintCells({ col, row }) : (origin.type === 'maintenanceRoom' ? maintenanceRoomFootprint({ col, row }) : [{ col, row }]); for (const cell of cells) { if (!pointInGrid(cell.col, cell.row)) return fail('Selection outside grid'); if (game.blockedCells?.has?.(key(cell.col, cell.row))) return fail('Selection hits blocked ground'); @@ -224,6 +232,9 @@ export function createSelectionSystem({ game, canvasPoint, updatePanels, equipme } else if (origin.type === 'scanner') { origin.obj.col = origin.col + dcol; origin.obj.row = origin.row + drow; + } else if (origin.type === 'maintenanceRoom') { + origin.obj.col = origin.col + dcol; + origin.obj.row = origin.row + drow; } else if (origin.type === 'facility') { const nextCenter = { x: origin.center.x + dx, y: origin.center.y + dy }; const { entry, side } = nearestGridEdge(nextCenter); diff --git a/src/systems/uiSystem.js b/src/systems/uiSystem.js index 0c57b2a..ebe08c6 100644 --- a/src/systems/uiSystem.js +++ b/src/systems/uiSystem.js @@ -5,7 +5,7 @@ import { routeFromFarmToScanner, factoryReady, facilityConnectionIssues } from ' import { buildPrice, fairiesTributeInfo, finalScore, maleTruckPenalty, mixerPoopPenalty, truckPoopPenalty } from './economy.js'; import { truckTarget } from './events.js'; import { conveyorSpeedForGame } from './cards.js'; -import { maintenanceSummary, repairmanDailyCost } from './maintenance.js'; +import { maintenanceSummary } from './maintenance.js'; export function createUISystem({ game, ui, build, startGame, beginCardDraft, activeQueuedChick }) { function escapeHtml(value) { @@ -27,7 +27,6 @@ export function createUISystem({ game, ui, build, startGame, beginCardDraft, act function updatePanels() { updateToolButtons(); updateBuildStatus(); - updateEventPanel(); updateTurnSummary(); updateHistoryButtons(); } @@ -56,15 +55,6 @@ export function createUISystem({ game, ui, build, startGame, beginCardDraft, act : ''; } if (ui.buttons.erase) ui.buttons.erase.disabled = game.phase !== 'build' || !!game.cardDraft?.pending || !!game.cardTargetPick?.pending; - if (ui.hireRepairmanButton) { - const hired = !!game.repairman?.hiredForNextDay; - const cost = repairmanDailyCost(game); - const blocked = game.phase !== 'build' || !!game.cardDraft?.pending || !!game.cardTargetPick?.pending || hired || game.cash < cost; - ui.hireRepairmanButton.disabled = blocked; - ui.hireRepairmanButton.classList.toggle('active', hired); - ui.hireRepairmanButton.classList.toggle('unaffordable', game.cash < cost); - ui.hireRepairmanButton.title = hired ? 'Repairman is hired for the next production phase.' : `Hire for ${yen(cost)} for one day. Repairs 2% durability per second.`; - } const cashout = noAffordableBuildTools(); ui.buttons.nextTurn?.classList.toggle('cashout-emphasis', cashout); ui.buttons.erase?.classList.toggle('cashout-emphasis', cashout); @@ -89,47 +79,14 @@ export function createUISystem({ game, ui, build, startGame, beginCardDraft, act function updateTurnSummary() { const connected = game.eggFarms.filter(f => routeFromFarmToScanner(game, f)?.scannerId).length; const issues = facilityConnectionIssues(game); - const tributeBasisProfit = Math.max(0, Math.floor(game.lastResult?.profit ?? game.stats?.profit ?? 0)); - const tributeDay = Math.max(1, Number(game.turn) || 1); - const tribute = fairiesTributeInfo(game, tributeDay, tributeBasisProfit); ui.turnSummary.innerHTML = [ `Seed: ${escapeHtml(game.runSeed || 'none')} | Grid box: ${game.gridRows || 10}x${game.gridCols || 20} | Owned: ${game.gridOwnedCells || game.ownedCells?.size || ((game.gridRows || 10) * (game.gridCols || 20))} cells | Blocked: ${game.blockedCells?.size || 0} cells`, - `Truck target: ${truckTarget(game).toUpperCase()} | Male fine: -${yen(maleTruckPenalty(game))}`, - `Poop fine: Mixer -${yen(mixerPoopPenalty(game))} / Shipment -${yen(truckPoopPenalty(game))}`, - `Fairies tribute on Next Day: -${yen(tribute.amount)} | base ${yen(tribute.base)} + profit share ${yen(tribute.profitTribute)} | basis net ${yen(tributeBasisProfit)} | exemption ${yen(tribute.profitExemption)}${tribute.reduction ? ` | reduction -${yen(tribute.reduction)}` : ''}`, - `Maintenance: worst ${maintenanceSummary(game).worst.percent}% dirty (${maintenanceSummary(game).worst.label}) | Repairman: ${game.repairman?.hiredForNextDay ? 'hired next day' : game.repairman?.active ? 'working' : 'none'}`, - `Manual combo: ${game.manualCombo?.count || 0} | Card draft: ${game.cardDraft?.pending ? Math.max(1, game.cardDraft.picksRemaining || 1) + ' pick(s) left' : 'ready after each day'} | Belt: ${displaySpeed()}px/s | Farms with scanner route: ${connected}/${game.eggFarms.length}`, + `Penalties: wrong shipment -${yen(maleTruckPenalty(game))} | Mixer poop -${yen(mixerPoopPenalty(game))} | Shipment poop -${yen(truckPoopPenalty(game))}`, + `Maintenance: worst ${maintenanceSummary(game).worst.percent}% dirty (${maintenanceSummary(game).worst.label}) | Rooms: ${(game.maintenanceRooms || []).length} | Repairmen: ${(game.repairmen || []).length}`, + `Card draft: ${game.cardDraft?.pending ? Math.max(1, game.cardDraft.picksRemaining || 1) + ' pick(s) left' : 'ready after each day'} | Farms with scanner route: ${connected}/${game.eggFarms.length}`, game.cardEffects?.usedMachineActive ? 'Procurement: USED MACHINE MODE / no refunds / 60% durability' : '', issues.length ? `Blocked: ${issues[0]}` : `${TEXT.status.allPortsConnected}` - ].join('
'); - } - function updateEventPanel() { - if (!ui.eventPanel) return; - const offer = game.eventOffer; - if (game.phase !== 'build') { - ui.eventPanel.innerHTML = TEXT.status.eventPanelRunning; - return; - } - if (!offer) { - ui.eventPanel.className = 'event-card empty'; - const nextTurn = game.turn + 1; - if (nextTurn < DAILY_EVENT_FIRST_TURN) { - ui.eventPanel.innerHTML = `Event lock active.No irregular events during Days 1-7. First possible forced event: Day ${DAILY_EVENT_FIRST_TURN}.`; - } else { - ui.eventPanel.innerHTML = 'No event.Random forced events can appear later.'; - } - return; - } - ui.eventPanel.className = 'event-card accepted'; - ui.eventPanel.innerHTML = ` -
FORCED NEXT DAY
-

${offer.title}

-
- Effect: ${offer.route} - ${offer.targetAmount ? `Target: ${offer.targetAmount}` : 'Target: none'} - ${offer.reward ? `Reward: ${yen(offer.reward)}` : 'Reward: none'} - Time ${offer.daySeconds || 60}s / Output x${Number(offer.productionMultiplier || 1).toFixed(2)} / Poop +${Math.round((offer.poopRateAdd || 0) * 100)}pt -
`; + ].filter(Boolean).join('
'); } function updateUI() { updateToolButtons(); @@ -172,7 +129,9 @@ export function createUISystem({ game, ui, build, startGame, beginCardDraft, act } const nextTributeBasis = Math.max(0, Math.floor(game.lastResult?.profit ?? game.stats?.profit ?? 0)); const nextTribute = fairiesTributeInfo(game, Math.max(1, Number(game.turn) || 1), nextTributeBasis).amount; - ui.buttons.nextTurn.textContent = game.phase === 'build' && nextTribute > 0 ? `Next Day - Fairies ${yen(nextTribute)}` : TEXT.actions.nextDay; + ui.buttons.nextTurn.innerHTML = game.phase === 'build' && nextTribute > 0 + ? `NEXT DAYFAIRIES -${yen(nextTribute)}` + : `${TEXT.actions.nextDay}`; ui.buttons.nextTurn.disabled = game.phase !== 'build' || !!game.cardDraft?.pending || !!game.cardTargetPick?.pending || !factoryReady(game); } @@ -180,7 +139,7 @@ export function createUISystem({ game, ui, build, startGame, beginCardDraft, act if (!ui.eventBrief || !ui.targetBrief || !ui.speedBrief) return; const target = truckTarget(game).toUpperCase(); ui.targetBrief.textContent = `TRUCK TARGET: ${target}`; - ui.speedBrief.textContent = `BELT: ${displaySpeed()} px/s | COMBO: ${game.manualCombo?.count || 0}`; + ui.speedBrief.textContent = `BELT SPEED: ${displaySpeed()} px/s`; ui.speedBrief.title = `Conveyor speed does not increase by day. Degraded belts reduce speed. Cap: ${CONVEYOR_SPEED_MAX}px/s.`; const active = game.eventActive; const offer = game.eventOffer; @@ -235,7 +194,6 @@ export function createUISystem({ game, ui, build, startGame, beginCardDraft, act
Event bonus${positive(r.eventBonus || 0)}
Penalties${negative(penalties)}
Fairies fee${negative(r.fairiesTribute?.amount || r.fairiesTribute || 0)}
-
Repair worker wages${negative(r.repairWorkerWages || 0)}

Income ${yen(r.revenue)} - losses ${yen(r.penalty)} = ${yen(r.profit)}

`; ui.modalActions.innerHTML = ''; diff --git a/styles-v27.17.css b/styles-v27.17.css new file mode 100644 index 0000000..1219389 --- /dev/null +++ b/styles-v27.17.css @@ -0,0 +1,1130 @@ +:root { + --bg: #f2fff0; + --screen: #eefbea; + --panel: rgba(245, 255, 242, 0.96); + --ink: #102015; + --muted: #526456; + --line: #102015; + --green: #22b94f; + --green-soft: #b7f5c6; + --white: #ffffff; + --danger: #c42424; + --shadow: 8px 8px 0 rgba(16, 32, 21, 0.22); +} +* { box-sizing: border-box; } +html, body { min-height: 100%; } +body { margin: 0; background: var(--bg); color: var(--ink); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; overflow-x: hidden; } +button { font: inherit; } +h1, h2, p { margin: 0; } +#app { width: min(100vw, 1680px); margin: 0 auto; padding: 0 8px 12px; } +.game-shell { position: relative; width: 100%; min-height: min(100vh, 920px); border: 4px solid var(--line); border-top: 0; background: var(--screen); overflow: hidden; box-shadow: var(--shadow); } +#gameCanvas { display: block; width: 100%; height: min(calc(100vh - 10px), 900px); min-height: 720px; background: var(--screen); touch-action: none; } +.hud { position: absolute; z-index: 4; display: grid; gap: 6px; pointer-events: none; } +.hud-top-left { top: 10px; left: 10px; grid-template-columns: repeat(6, minmax(82px, auto)); } +.hud-top-right { top: 10px; right: 10px; grid-template-columns: repeat(4, minmax(78px, auto)); } +.hud-card { min-width: 82px; padding: 7px 9px; border: 3px solid var(--line); background: rgba(255,255,255,.88); box-shadow: 4px 4px 0 rgba(16,32,21,.16); } +.hud-card.primary { min-width: 116px; padding: 10px 12px; background: rgba(255,255,255,.96); } +.hud-card.primary span { font-size: 9px; } +.hud-card.primary strong { font-size: clamp(22px, 2vw, 32px); } +.hud-card.time-critical { background: #fff0d1; box-shadow: inset 0 0 0 4px var(--danger), 4px 4px 0 rgba(16,32,21,.16); } +.hud-card span { display: block; font-size: 9px; letter-spacing: .1em; color: var(--muted); margin-bottom: 4px; } +.hud-card strong { font-size: clamp(15px, 1.3vw, 22px); line-height: 1; color: var(--ink); } +.hud-card.cash strong, .hud-card.profit strong, .hud-card.combo strong, .cash-positive { color: var(--green) !important; } +.cash-negative { color: var(--danger) !important; } + +.priority-strip { position: absolute; z-index: 5; top: 76px; left: 10px; display: grid; grid-template-columns: minmax(280px, 1.2fr) minmax(170px, .75fr) minmax(130px, .55fr); gap: 8px; max-width: calc(100% - 420px); pointer-events: none; } +.priority-strip > div { border: 3px solid var(--line); background: rgba(255,255,255,.94); padding: 8px 10px; font-weight: 900; text-transform: uppercase; box-shadow: 4px 4px 0 rgba(16,32,21,.14); font-size: 12px; letter-spacing: .03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.event-brief.active { background: #fff0d1; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.14); } +.event-brief.next { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.14); } +.event-brief.locked { background: #edf3ec; color: var(--muted); } +.target-brief { color: var(--green); } +.speed-brief { color: var(--ink); } + +.build-panel { position: absolute; z-index: 6; top: 118px; right: 12px; bottom: 12px; width: clamp(278px, 23vw, 360px); min-height: 0; padding: 10px; border: 4px solid var(--line); background: var(--panel); box-shadow: var(--shadow); overflow: auto; } +.panel-head { display: grid; gap: 8px; margin-bottom: 10px; } +.panel-head h1 { font-size: 15px; letter-spacing: .06em; } +.panel-head h1 span { font-size: 9px; color: var(--white); background: var(--green); border: 2px solid var(--line); padding: 1px 6px; } +.panel-head p { color: var(--muted); margin-top: 4px; font-size: 9px; line-height: 1.25; } +.panel-grid { display: grid; grid-template-columns: 1fr; gap: 10px; } +.build-panel h2 { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; margin-bottom: 7px; } +.large-tools { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; } +.history-tools { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; grid-column: 1 / -1; } +.tool-button.small { min-height: 40px; padding: 6px; } +.tool-button, .primary-button, .sort-button, .facility-action { border: 3px solid var(--line); background: var(--white); color: var(--ink); font-weight: 900; text-transform: uppercase; cursor: pointer; box-shadow: 4px 4px 0 rgba(16,32,21,.18); } +.tool-button { min-height: 50px; text-align: left; padding: 8px; } +.tool-button strong { display: block; font-size: 12px; } +.tool-button span { display: block; margin-top: 4px; font-size: 9px; color: var(--muted); } +.tool-button.active { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.18); } +.tool-button.danger.active { background: #ffdada; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.18); } +.primary-button { padding: 10px 12px; background: var(--green); color: var(--white); white-space: nowrap; } +.primary-button:disabled, .tool-button:disabled, .sort-button:disabled, .facility-action:disabled { opacity: .42; cursor: not-allowed; } +.mini-box { border: 3px solid var(--line); background: var(--white); padding: 12px; line-height: 1.45; color: var(--muted); font-size: 11px; } +.facility-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; } +.facility-action { padding: 7px 9px; font-size: 9px; } +.facility-action.good { background: var(--green-soft); } +.facility-action.warn { background: #fff0d1; } +.facility-action.danger { background: #ffdada; } +.control-dock { position: absolute; z-index: 7; left: 50%; bottom: 12px; transform: translateX(-50%); display: grid; grid-template-columns: repeat(4, 150px); gap: 8px; padding: 7px; border: 3px solid var(--line); background: rgba(255,255,255,.90); } +.sort-button { min-height: 46px; font-size: 12px; } +/* Debug UI is intentionally kept for active balancing builds. Do not remove during cleanup/audit passes unless explicitly requested. */ +.debug-panel { + position: absolute; + z-index: 9; + left: 10px; + bottom: 10px; + width: min(410px, calc(100% - 20px)); + border: 3px solid var(--line); + background: rgba(255,255,255,.96); + box-shadow: 4px 4px 0 rgba(16,32,21,.16); + font-weight: 900; +} +.debug-panel summary { + cursor: pointer; + padding: 5px 8px; + color: var(--danger); + font-size: 14px; + line-height: 1.1; +} +.debug-body { + display: grid; + grid-template-columns: 1fr 92px; + gap: 6px; + padding: 7px; + border-top: 3px solid var(--line); + font-size: 12px; + line-height: 1.15; +} +.debug-body label, +.debug-body button, +.debug-body select, +.debug-body input { + min-width: 0; + font: inherit; +} +.debug-check, +.debug-card, +.debug-target, +.debug-readout { + grid-column: 1 / -1; +} +.debug-row { + display: grid; + grid-template-columns: 1fr 92px; + gap: 6px; + grid-column: 1 / -1; +} +.debug-day { + display: grid; + grid-template-columns: 38px 1fr; + align-items: center; + gap: 4px; +} +.debug-body button { + border: 2px solid var(--line); + background: var(--white); + cursor: pointer; + font-weight: 900; + padding: 5px 6px; + line-height: 1.05; +} +.debug-body input[type="number"], +.debug-body select { + width: 100%; + border: 2px solid var(--line); + background: var(--white); + padding: 4px 5px; + min-height: 29px; +} +.debug-target select:disabled { + opacity: .55; +} +.debug-readout { + border: 2px solid var(--line); + background: #f7fff5; + color: var(--muted); + padding: 5px; + line-height: 1.25; + max-height: 64px; + overflow: auto; +} +.modal { position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; padding: 22px; background: rgba(16,32,21,.45); } +.modal.visible { display: flex; } +.modal-card { width: min(860px, 96vw); border: 4px solid var(--line); padding: 24px; background: var(--white); box-shadow: var(--shadow); } +.modal-card h2 { font-size: 26px; text-transform: uppercase; margin-bottom: 12px; } +.modal-card p { line-height: 1.55; } +.modal-card ul { margin: 12px 0 0; padding-left: 22px; line-height: 1.55; color: var(--muted); } +.modal-actions { margin-top: 18px; display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap; } +.route-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 14px 0; } +.route-card { border: 3px solid var(--line); background: #f7fff5; padding: 14px; display: grid; grid-template-columns: 44px 1fr 28px 1fr; align-items: center; gap: 4px 8px; } +.route-card .route-icon { grid-row: 1 / span 2; font-size: 30px; text-align: center; } +.route-card strong, .route-card em { font-style: normal; font-weight: 900; text-transform: uppercase; } +.route-card b { font-size: 24px; color: var(--green); text-align: center; } +.route-card small { grid-column: 2 / span 3; color: var(--muted); font-weight: 900; } +.result-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 12px; } +.result-grid div { border: 3px solid var(--line); padding: 10px; background: #f7fff5; } +.result-grid strong { display: block; font-size: 11px; color: var(--muted); text-transform: uppercase; margin-bottom: 6px; } +.result-grid span { font-size: 16px; font-weight: 900; color: var(--ink); } +.game-shell:not(.phase-build) .build-panel { display: none; } +.game-shell.phase-running .hud-top-right { display: none; } +.game-shell:not(.phase-running) .control-dock { display: none; } +@media (max-width: 1180px) { + #app { padding: 0; } + .game-shell { min-height: 100vh; } + #gameCanvas { height: 100vh; } + .hud-top-left, .hud-top-right { grid-template-columns: repeat(2, minmax(76px, auto)); } + .priority-strip { top: 150px; left: 8px; right: 8px; max-width: none; grid-template-columns: 1fr; } + .build-panel { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 42vh; } + .large-tools { grid-template-columns: 1fr 1fr; } + .control-dock { grid-template-columns: repeat(2, 150px); } + .route-cards, .result-grid { grid-template-columns: 1fr; } +} + +.event-card { border: 3px solid var(--line); background: #f7fff5; padding: 12px; line-height: 1.35; color: var(--ink); font-size: 11px; box-shadow: 4px 4px 0 rgba(16,32,21,.14); } +.event-card.empty { color: var(--muted); background: rgba(255,255,255,.72); } +.event-card.empty strong { display: block; color: var(--ink); margin-bottom: 4px; } +.event-card h3 { margin: 2px 0 7px; font-size: 14px; text-transform: uppercase; letter-spacing: .04em; } +.event-card p { margin: 5px 0; } +.event-card.accepted { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.14); } +.event-card.declined { background: #f1f1f1; color: var(--muted); } +.event-status { display: inline-block; padding: 2px 7px; border: 2px solid var(--line); background: var(--white); font-size: 9px; font-weight: 900; letter-spacing: .1em; margin-bottom: 4px; } +.event-metrics { display: grid; grid-template-columns: 1fr; gap: 4px; margin: 8px 0; } +.event-metrics span { display: block; border: 2px solid rgba(16,32,21,.55); background: rgba(255,255,255,.82); padding: 5px; font-weight: 900; color: var(--ink); } +.event-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; } +.result-section-title { margin: 16px 0 8px; font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .12em; color: var(--green); } +.result-section-title:first-child { margin-top: 0; } +.muted-title { color: var(--muted); border: 3px solid var(--line); padding: 10px; background: #f7fff5; } + +.compact-rules .mini-box { padding: 8px; font-size: 9px; } +.primary-button:disabled { filter: grayscale(1); background: #c9d2ca; color: #526456; } +.formula-box { + border: 3px solid var(--line); + background: #f7fff5; + padding: 10px; + margin: 10px 0; + line-height: 1.5; + color: var(--ink); + font-size: 12px; + font-weight: 700; +} +.equipment-menu-lines { + border: 3px solid var(--line); + background: #ffffff; + padding: 10px; + margin: 8px 0; + color: var(--muted); + line-height: 1.45; +} +.equipment-menu-lines p { margin: 4px 0; } + +/* v11 compact clicked-equipment bubble */ +.modal.equipment-popover { + background: transparent; + align-items: flex-start; + justify-content: flex-start; + padding: 0; + pointer-events: none; +} +.modal.equipment-popover .modal-card { + position: absolute; + left: var(--popover-x, 16px); + top: var(--popover-y, 16px); + width: min(250px, calc(100vw - 24px)); + max-height: min(280px, calc(100vh - 24px)); + overflow: auto; + padding: 8px; + border-width: 3px; + pointer-events: auto; + box-shadow: 6px 6px 0 rgba(16,32,21,.18); +} +.modal.equipment-popover .modal-card h2 { + font-size: 14px; + margin-bottom: 6px; +} +.modal.equipment-popover .modal-actions { + margin-top: 8px; + gap: 6px; + justify-content: flex-start; +} +.modal.equipment-popover .modal-actions button { + padding: 5px 7px; + font-size: 9px; +} +.equipment-menu-lines.compact { + padding: 7px; + margin: 6px 0; + font-size: 9px; +} +.formula-box.compact { + padding: 7px; + margin: 6px 0; + font-size: 9px; +} + +/* v15 pre-build card draft */ +.card-choices { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(190px, 220px)); + justify-content: center; + align-items: stretch; + gap: 10px; + margin-top: 14px; +} +.card-choice { + min-height: 132px; + border: 3px solid var(--line); + background: #f7fff5; + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.16); + padding: 12px; + text-align: left; + cursor: pointer; + font-weight: 900; +} +.card-choice:hover { transform: translate(-1px, -1px); box-shadow: 6px 6px 0 rgba(16,32,21,.18); } +.card-choice strong { display: block; font-size: 14px; text-transform: uppercase; line-height: 1.2; } +.card-choice span { display: inline-block; margin: 8px 0; padding: 2px 7px; border: 2px solid var(--line); background: var(--white); font-size: 9px; letter-spacing: .1em; } +.card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin: 7px 0; } +.card-tags span { margin: 0; padding: 2px 5px; font-size: 8px; line-height: 1.1; letter-spacing: .04em; } +.card-choice small { display: block; color: var(--muted); font-size: 11px; line-height: 1.35; } +.card-choice.rare { background: #fff0d1; box-shadow: inset 0 0 0 3px #f0a020, 5px 5px 0 rgba(16,32,21,.16); } +.card-choice.ultra-rare { background: #ffe6f0; box-shadow: inset 0 0 0 3px #c42424, 5px 5px 0 rgba(16,32,21,.18); } +.card-choice.ultra-rare span { background: #c42424; color: #fff; } +.muted-card-note { color: var(--muted); font-weight: 700; } +.card-targets { display: grid; gap: 8px; margin-top: 14px; } +.card-target-button { border: 3px solid var(--line); background: #f7fff5; padding: 10px 12px; text-align: left; cursor: pointer; font-weight: 900; box-shadow: 4px 4px 0 rgba(16,32,21,.14); } +.card-target-button:hover { background: var(--green-soft); } + +/* v19 readability pass */ +body { font-size: 16px; } +.hud-card span { font-size: 11px; } +.hud-card strong { font-size: clamp(18px, 1.5vw, 25px); } +.priority-strip > div { font-size: 14px; } +.panel-head h1 { font-size: 18px; } +.panel-head p { font-size: 11px; } +.build-panel h2 { font-size: 13px; } +.tool-button strong { font-size: 14px; } +.tool-button span { font-size: 11px; } +.mini-box, .event-card { font-size: 12px; } +.sort-button { font-size: 14px; } +.modal-card h2 { font-size: 29px; } +.card-choice strong { font-size: 16px; } +.card-choice small { font-size: 13px; } + +.tool-button.unaffordable, .tool-button.already-built { opacity: .42; filter: grayscale(.7); } + +.hover-tooltip { + position: fixed; + z-index: 30; + width: min(320px, calc(100vw - 20px)); + display: none; + border: 3px solid var(--line); + background: rgba(255,255,255,.96); + color: var(--ink); + box-shadow: 6px 6px 0 rgba(16,32,21,.18); + padding: 10px; + pointer-events: none; + line-height: 1.35; +} +.hover-tooltip.visible { display: block; } +.hover-tooltip strong { display: block; font-size: 15px; text-transform: uppercase; margin-bottom: 5px; } +.hover-tooltip em { display: block; font-style: normal; color: var(--green); font-weight: 900; margin-bottom: 7px; } +.hover-tooltip em.warning { color: var(--danger); } +.hover-tooltip span { display: block; color: var(--muted); font-size: 12px; } + + +.card-choice.dud { + background: #eeeeee; + color: #777; + filter: grayscale(1); + border-style: dashed; + box-shadow: 5px 5px 0 rgba(16,32,21,.10); +} +.card-choice.dud span { background: #f8f8f8; } +.card-choice.flung { + pointer-events: none; + transform: translate(var(--fling-x, 480px), var(--fling-y, -320px)) rotate(var(--fling-r, 68deg)) scale(.68); + opacity: 0; + transition: transform .34s cubic-bezier(.18,.84,.26,.99), opacity .28s ease-in; +} + + + +.route-card .route-icon.male, +.route-card .route-icon.female, +.route-card .route-icon.poop { + display: inline-grid; + place-items: center; + width: 38px; + height: 38px; + border-radius: 999px; + border: 3px solid var(--line, #102015); + background: var(--white, #fff); + line-height: 1; +} +.route-card .route-icon.male { color: #2477ff; background: #d9ecff; } +.route-card .route-icon.female { color: #d62a85; background: #ffe0f0; } +.route-card .route-icon.poop { color: #7b4a23; background: #fff0d1; font-size: 24px; } +.restart-button { min-width: 160px; } +.restart-fallback-note { margin-top: 12px; color: var(--muted, #526456); font-weight: 700; } + +/* v24.4 hover-only build-button flavor / cashout guidance / compact game-over */ +.tool-button .tool-flavor { + display: block; + max-height: 0; + opacity: 0; + overflow: hidden; + margin-top: 0; + color: var(--muted); + font-size: 8px; + line-height: 1.22; + text-transform: none; + letter-spacing: 0; + transition: max-height .12s ease, opacity .12s ease, margin-top .12s ease; +} +.tool-button:hover .tool-flavor { + max-height: 42px; + opacity: 1; + margin-top: 5px; +} +.large-tools .tool-button { min-height: 58px; } +.large-tools .tool-button:hover { min-height: 78px; } +.history-tools .tool-button.small { min-height: 40px; } +.primary-button.cashout-emphasis, +.tool-button.cashout-emphasis { + opacity: 1 !important; + filter: none !important; + animation: cashoutPulse 0.9s ease-in-out infinite alternate; +} +.primary-button.cashout-emphasis { + box-shadow: inset 0 0 0 4px #fff0d1, 6px 6px 0 rgba(16,32,21,.22); +} +.tool-button.cashout-emphasis { + background: #fff0d1; + box-shadow: inset 0 0 0 3px var(--danger), 6px 6px 0 rgba(16,32,21,.20); +} +@keyframes cashoutPulse { + from { transform: translate(0, 0); } + to { transform: translate(-1px, -1px); } +} +.modal.gameover-modal { padding: 12px; } +.modal.gameover-modal .modal-card { + width: min(640px, 92vw); + max-height: min(82vh, 720px); + overflow: auto; + padding: 16px; +} +.modal.gameover-modal .modal-card h2 { + font-size: 22px; + margin-bottom: 8px; +} +.gameover-reason { font-weight: 900; color: var(--danger); margin-bottom: 8px; } +.settlement-net { + border: 3px solid var(--line); + background: #f7fff5; + padding: 10px 12px; + margin-bottom: 10px; + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + font-weight: 900; + text-transform: uppercase; +} +.settlement-net strong { font-size: 24px; } +.settlement-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; } +.settlement-grid div { padding: 8px; } +.settlement-grid span { display: block; font-size: 14px; } +.gameover-summary { + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 6px; + margin-top: 8px; +} +.gameover-breakdown { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 6px; + margin-top: 8px; +} +.modal.gameover-modal .result-grid div { padding: 7px; } +.modal.gameover-modal .result-grid strong { font-size: 9px; margin-bottom: 3px; } +.modal.gameover-modal .result-grid span { font-size: 12px; } +.gameover-details { + margin-top: 10px; + border: 3px solid var(--line); + background: #f7fff5; + padding: 8px; +} +.gameover-details summary { + cursor: pointer; + font-weight: 900; + text-transform: uppercase; +} +.modal.gameover-modal .formula-box.compact { font-size: 9px; line-height: 1.35; } +@media (max-width: 720px) { + .gameover-summary, .gameover-breakdown { grid-template-columns: 1fr 1fr; } +} + +/* v27.0 cleanup and stable build-menu tooltip pass */ +body { font-size: 18px; } +.build-panel { width: clamp(330px, 26vw, 420px); } +.panel-head h1 { font-size: 20px; } +.panel-head h1 span { font-size: 12px; } +.panel-head p { font-size: 13px; line-height: 1.35; } +.build-panel h2 { font-size: 14px; } +.priority-strip > div { font-size: 15px; } +.hud-card span { font-size: 12px; } +.hud-card strong { font-size: clamp(20px, 1.7vw, 28px); } +.mini-box, .event-card { font-size: 14px; line-height: 1.45; } +.compact-rules .mini-box { font-size: 13px; } +.tool-button { + position: relative; + overflow: visible; + min-height: 62px; + padding: 10px; +} +.large-tools .tool-button { min-height: 62px; } +.large-tools .tool-button:hover { min-height: 62px; } +.tool-button strong { font-size: 15px; line-height: 1.15; } +.tool-button span { font-size: 12px; } +.tool-button .tool-flavor { + display: none; + position: absolute; + z-index: 60; + left: 0; + top: calc(100% + 7px); + width: min(300px, calc(100vw - 40px)); + max-height: none; + opacity: 1; + overflow: visible; + margin: 0; + padding: 10px 12px; + border: 3px solid var(--line); + background: rgba(255,255,255,.98); + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + font-size: 13px; + line-height: 1.35; + text-transform: none; + letter-spacing: 0; + pointer-events: none; + transition: none; +} +.tool-button .tool-flavor::before { + content: ''; + position: absolute; + left: 16px; + top: -10px; + width: 16px; + height: 16px; + border-left: 3px solid var(--line); + border-top: 3px solid var(--line); + background: rgba(255,255,255,.98); + transform: rotate(45deg); +} +.tool-button:hover .tool-flavor { + display: block; + max-height: none; + opacity: 1; + margin: 0; +} +.primary-button { font-size: 16px; padding: 13px 16px; } +#nextTurnButton { min-height: 56px; font-size: 18px; } +@keyframes cashoutPulse { + from { box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.18); filter: brightness(1); } + to { box-shadow: inset 0 0 0 5px #fff0d1, 4px 4px 0 rgba(16,32,21,.20); filter: brightness(1.08); } +} +.card-choices { grid-template-columns: repeat(auto-fill, minmax(230px, 270px)); gap: 14px; } +.card-choice { min-height: 164px; padding: 15px; } +.card-choice strong { font-size: 18px; } +.card-choice span { font-size: 11px; } +.card-choice small { font-size: 15px; line-height: 1.4; } +.muted-card-note { font-size: 15px; line-height: 1.45; } +.modal-card { width: min(980px, 96vw); } +.modal-card p, .modal-card li { font-size: 16px; } +.modal-actions .reroll-button { + order: 99; + flex: 1 1 100%; + min-height: 64px; + margin-top: 8px; + font-size: 20px; + text-align: center; + justify-content: center; + background: #fff0d1; + box-shadow: inset 0 0 0 4px var(--green), 6px 6px 0 rgba(16,32,21,.20); +} +.modal-actions .reroll-button:disabled { box-shadow: 4px 4px 0 rgba(16,32,21,.12); } +.hover-tooltip strong { font-size: 17px; } +.hover-tooltip span { font-size: 14px; } +.sort-button { font-size: 16px; min-height: 56px; } +.control-dock { grid-template-columns: repeat(4, 172px); } +@media (max-width: 1180px) { + .build-panel { width: auto; } + .control-dock { grid-template-columns: repeat(2, 172px); } +} + +/* v27.1 expansion/readability pass */ +body { font-size: 20px; } +.panel-head h1 { font-size: 22px; } +.panel-head h1 span { font-size: 13px; } +.panel-head p { font-size: 14px; line-height: 1.35; } +.build-panel h2 { font-size: 15px; } +.priority-strip > div { font-size: 16px; } +.hud-card span { font-size: 13px; } +.hud-card strong { font-size: clamp(22px, 1.8vw, 30px); } +.mini-box, .event-card { font-size: 15px; line-height: 1.5; } +.compact-rules .mini-box { font-size: 14px; } +.tool-button strong { font-size: 16px; line-height: 1.15; } +.tool-button span { font-size: 13px; line-height: 1.2; } +.tool-button .tool-flavor { + left: auto; + right: 0; + width: min(320px, calc(100vw - 40px)); + font-size: 14px; + line-height: 1.4; + overflow-wrap: anywhere; +} +.tool-button .tool-flavor::before { left: auto; right: 18px; } +.tool-button.unaffordable .tool-flavor, +.tool-button.unaffordable:hover .tool-flavor, +.tool-button:disabled .tool-flavor, +.tool-button:disabled:hover .tool-flavor { display: none; } +.facility-action { font-size: 12px; } +.primary-button { font-size: 17px; } +#nextTurnButton { font-size: 19px; } +.card-choice strong { font-size: 19px; } +.card-choice span { font-size: 12px; } +.card-choice small { font-size: 16px; line-height: 1.45; } +.muted-card-note { font-size: 16px; } +.modal-card p, .modal-card li { font-size: 17px; } +.modal.equipment-popover .modal-card h2 { font-size: 16px; } +.modal.equipment-popover .modal-actions button { font-size: 11px; } +.equipment-menu-lines.compact, .formula-box.compact { font-size: 11px; } +.hover-tooltip strong { font-size: 18px; } + +/* Keep construction flavor text readable as a hover bubble, not button content. */ +.large-tools .tool-button { + min-height: 62px; + position: relative; + overflow: visible; +} +.large-tools .tool-button:hover { + min-height: 62px; +} +.large-tools .tool-button .tool-flavor { + display: none; + position: absolute; + z-index: 90; + right: 0; + top: calc(100% + 8px); + width: min(320px, calc(100vw - 40px)); + max-height: none; + opacity: 1; + overflow: visible; + margin: 0; + padding: 10px 12px; + border: 3px solid var(--line); + background: rgba(255,255,255,.98); + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + font-size: 14px; + line-height: 1.35; + pointer-events: none; + overflow-wrap: anywhere; +} +.large-tools .tool-button:hover .tool-flavor { + display: block; +} +.large-tools .tool-button .tool-flavor::before { + content: ''; + position: absolute; + right: 18px; + top: -10px; + width: 16px; + height: 16px; + border-left: 3px solid var(--line); + border-top: 3px solid var(--line); + background: rgba(255,255,255,.98); + transform: rotate(45deg); +} +.hover-tooltip span { font-size: 15px; } +.sort-button { font-size: 17px; } + +/* v27.3 offscreen scanner monitor / expansion UI pass */ +.scanner-monitor { + position: absolute; + z-index: 8; + left: 12px; + bottom: 92px; + display: none; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 8px; + width: min(560px, calc(100% - 24px)); + pointer-events: auto; +} +.scanner-monitor.visible { display: grid; } +.scanner-monitor-card { + border: 3px solid var(--line); + background: rgba(255,255,255,.95); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + padding: 9px; + font-weight: 900; +} +.scanner-monitor-card header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin-bottom: 7px; + text-transform: uppercase; +} +.scanner-monitor-card header strong { font-size: 20px; color: var(--green); } +.scanner-monitor-card header span { font-size: 12px; color: var(--muted); } +.scanner-mini-map { + display: grid; + grid-template-columns: 42px 1fr 82px; + align-items: center; + gap: 6px; + margin-bottom: 8px; +} +.scanner-mini-map > span, +.scanner-mini-map > b { + border: 2px solid var(--line); + background: #f7fff5; + padding: 7px 6px; + text-align: center; + font-size: 13px; + min-height: 36px; +} +.scanner-current { display: block; color: var(--ink); } +.scanner-current.male { color: #2477ff; } +.scanner-current.female { color: #d62a85; } +.scanner-current.poop { color: #7b4a23; } +.scanner-current.empty { color: var(--muted); } + +.scanner-mini-grid { + display: grid; + grid-template-columns: repeat(5, 27px); + gap: 3px; + justify-content: center; + align-items: center; + padding: 6px; + margin: 0 0 8px; + border: 2px solid var(--line); + background: #f6f1df; +} +.scanner-mini-grid .mini-cell { + width: 27px; + height: 27px; + display: grid; + place-items: center; + border: 1px solid rgba(22,38,25,.28); + background: #fffdfa; + color: var(--muted); + font-size: 11px; + font-weight: 900; + line-height: 1; +} +.scanner-mini-grid .mini-cell.belt { background: #e7f7e4; color: var(--green-dark); } +.scanner-mini-grid .mini-cell.input { background: #fff3bf; color: var(--ink); font-size: 9px; } +.scanner-mini-grid .mini-cell.scanner { background: var(--green); color: #fff; border-color: var(--line); font-size: 16px; } +.scanner-mini-grid .mini-cell.scanner.male { background: #2477ff; } +.scanner-mini-grid .mini-cell.scanner.female { background: #d62a85; } +.scanner-mini-grid .mini-cell.scanner.poop { background: #7b4a23; } +.scanner-mini-grid .mini-cell.scanner-other { background: #b7f5c6; color: var(--ink); } +.scanner-mini-grid .mini-cell.egg { background: #fff7c4; color: #7a5a00; } +.scanner-mini-grid .mini-cell.port { background: #dbe7ff; color: #27427d; } +.scanner-mini-grid .mini-cell.blocked { background: #d7cfc1; color: #6d4d35; } + +.scanner-monitor-actions { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 7px; +} +.scanner-monitor-actions button { + border: 3px solid var(--line); + background: var(--green-soft); + color: var(--ink); + cursor: pointer; + font: inherit; + font-size: 14px; + font-weight: 900; + min-height: 44px; + box-shadow: 3px 3px 0 rgba(16,32,21,.18); +} +.scanner-monitor-actions button:disabled { + background: #edf3ec; + color: var(--muted); + opacity: .62; + cursor: not-allowed; +} +@media (max-width: 1180px) { + .scanner-monitor { bottom: 132px; width: min(520px, calc(100% - 16px)); left: 8px; } +} + +/* ------------------------------------------------------------------ + DARK FACTORY VISUAL PASS + - Facility sprites are now loaded from assets/dark_factory/. + - Debug UI is intentionally retained for balancing builds. Do not remove. + ------------------------------------------------------------------ */ +:root { + --bg: #0b0c0f; + --screen: #111318; + --panel: rgba(24, 27, 34, 0.96); + --panel-2: #20242b; + --panel-3: #2a303a; + --ink: #e6edf2; + --muted: #8f9bab; + --line: #050609; + --green: #7bd84f; + --green-soft: #273c24; + --white: #e6edf2; + --danger: #e34a36; + --warn: #ffb827; + --cyan: #4aa3ff; + --orange: #c86a2b; + --shadow: 6px 6px 0 rgba(0, 0, 0, 0.62); +} +html, body { background: #050609; color: var(--ink); } +body { + background: + linear-gradient(90deg, rgba(255,184,39,.035) 1px, transparent 1px) 0 0 / 32px 32px, + linear-gradient(rgba(255,184,39,.028) 1px, transparent 1px) 0 0 / 32px 32px, + #050609; +} +#app { width: min(100vw, 1720px); padding: 0; } +.game-shell { + min-height: 100vh; + border: 0; + background: var(--screen); + box-shadow: inset 0 0 0 4px #050609, inset 0 0 0 8px #303744; +} +#gameCanvas { + height: 100vh; + min-height: 720px; + background: var(--screen); + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.hud { gap: 4px; } +.hud-top-left { + top: 8px; + left: 8px; + right: 420px; + grid-template-columns: 1.25fr repeat(5, minmax(92px, .65fr)); +} +.hud-top-right { + top: 8px; + right: 8px; + grid-template-columns: repeat(4, minmax(74px, auto)); +} +.hud-card { + min-width: 74px; + padding: 7px 9px; + border: 3px solid var(--line); + background: linear-gradient(#242a33, #171a20); + box-shadow: 4px 4px 0 rgba(0,0,0,.7), inset 0 0 0 2px rgba(255,184,39,.10); + color: var(--ink); +} +.hud-card span { color: var(--warn); font-size: 9px; letter-spacing: .12em; } +.hud-card strong { color: var(--ink); text-shadow: 2px 2px 0 #050609; } +.hud-card.cash strong, .hud-card.profit strong, .hud-card.combo strong, .cash-positive { color: var(--green) !important; } +.hud-card.time-critical { background: #3a1f1f; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.7); } +.priority-strip { + top: 74px; + left: 10px; + width: clamp(250px, 21vw, 330px); + max-width: none; + grid-template-columns: 1fr; + gap: 6px; +} +.priority-strip > div { + border: 3px solid var(--line); + background: linear-gradient(#222832, #15181e); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.12); +} +.event-brief.active { background: #38251a; box-shadow: inset 0 0 0 3px var(--orange), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.next { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.locked { background: #181b20; color: var(--muted); } +.target-brief { color: var(--warn); } +.speed-brief { color: var(--cyan); } +.build-panel { + top: 82px; + right: 8px; + bottom: 8px; + width: clamp(320px, 24vw, 410px); + padding: 9px; + border: 4px solid var(--line); + background: linear-gradient(#222832, #14171d); + box-shadow: 6px 6px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.10); + scrollbar-color: var(--warn) #111318; +} +.panel-head { + display: grid; + grid-template-columns: 1fr 126px; + align-items: stretch; + gap: 8px; + margin-bottom: 8px; +} +.panel-head h1 { color: var(--warn); text-shadow: 2px 2px 0 #050609; font-size: 17px; } +.panel-head h1 span { color: #050609; background: var(--warn); border-color: var(--line); } +.panel-head p { color: var(--muted); } +.panel-grid { + display: grid; + grid-template-columns: 1fr; + gap: 8px; +} +.build-panel h2, .result-section-title { color: var(--warn); } +.large-tools { + grid-template-columns: 1fr 1fr; + gap: 6px; +} +.tool-button, .primary-button, .sort-button, .facility-action { + border: 3px solid var(--line); + background: linear-gradient(#2a303a, #171a20); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.70), inset 0 0 0 2px rgba(255,184,39,.08); + text-shadow: 1px 1px 0 #050609; +} +.tool-button { min-height: 48px; padding: 8px; } +.tool-button strong { color: var(--ink); } +.tool-button span { color: var(--muted); } +.tool-button.active { + background: linear-gradient(#33311d, #1e2117); + box-shadow: inset 0 0 0 3px var(--warn), 4px 4px 0 rgba(0,0,0,.70); +} +.tool-button.danger.active { background: linear-gradient(#4b1f1c, #241014); box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.70); } +.primary-button { background: linear-gradient(#8b2d23, #4b1714); color: #fff3d2; } +.primary-button:not(:disabled) { box-shadow: inset 0 0 0 3px #ffb827, 5px 5px 0 rgba(0,0,0,.72); } +.primary-button:disabled, .tool-button:disabled, .sort-button:disabled, .facility-action:disabled { opacity: .42; filter: grayscale(1); } +.mini-box, .event-card, .formula-box, .equipment-menu-lines, .route-card, .result-grid div, .muted-title { + border: 3px solid var(--line); + background: #15181e; + color: var(--muted); + box-shadow: inset 0 0 0 2px rgba(255,184,39,.08); +} +.event-card h3, .event-card strong, .event-metrics span { color: var(--ink); } +.event-card.accepted { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-card.empty { background: #15181e; color: var(--muted); } +.event-metrics span { border-color: #3d4654; background: #20242b; } +.event-status { background: #2a303a; color: var(--warn); border-color: var(--line); } +.control-dock { + left: 50%; + right: auto; + bottom: 8px; + transform: translateX(-50%); + grid-template-columns: repeat(4, minmax(135px, 160px)); + gap: 6px; + padding: 6px; + border: 4px solid var(--line); + background: rgba(13,15,19,.96); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(255,184,39,.10); +} +.sort-button { min-height: 44px; font-size: 12px; } +.scanner-monitor { + position: absolute; + z-index: 5; + left: 10px; + top: 198px; + width: clamp(250px, 21vw, 330px); +} +.scanner-monitor-card { + border: 3px solid var(--line) !important; + background: linear-gradient(#222832, #15181e) !important; + color: var(--ink) !important; + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.10) !important; +} +.scanner-monitor-card strong { color: var(--warn); } +.debug-panel { + left: auto; + right: 12px; + bottom: 10px; + width: min(420px, calc(100% - 24px)); + border-color: var(--line); + background: rgba(16,18,23,.97); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(227,74,54,.18); + color: var(--ink); +} +.debug-panel summary { color: var(--danger); } +.debug-body { border-top-color: var(--line); } +.debug-body button, .debug-body input[type="number"], .debug-body select, .debug-readout { + border-color: var(--line); + background: #20242b; + color: var(--ink); +} +.debug-readout { color: var(--muted); } +.modal { background: rgba(3,4,6,.72); } +.modal-card { + border-color: var(--line); + background: linear-gradient(#242a33, #15181e); + color: var(--ink); + box-shadow: 8px 8px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.12); +} +.modal-card h2 { color: var(--warn); text-shadow: 2px 2px 0 #050609; } +.modal-card ul, .modal-card p { color: var(--muted); } +.hover-tooltip { + border-color: var(--line) !important; + background: rgba(20,23,29,.98) !important; + color: var(--ink) !important; + box-shadow: 5px 5px 0 rgba(0,0,0,.72) !important; +} +::-webkit-scrollbar { width: 14px; height: 14px; } +::-webkit-scrollbar-track { background: #111318; } +::-webkit-scrollbar-thumb { background: #333b48; border: 3px solid #111318; } +::-webkit-scrollbar-thumb:hover { background: #ffb827; } +@media (max-width: 1180px) { + .hud-top-left { right: 8px; grid-template-columns: repeat(3, minmax(80px, 1fr)); } + .hud-top-right { top: 132px; left: 8px; right: auto; grid-template-columns: repeat(2, minmax(82px, auto)); } + .priority-strip { top: 226px; } + .scanner-monitor { top: 348px; } + .build-panel { left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 46vh; } + .control-dock { grid-template-columns: repeat(2, 150px); } +} + +/* v27.16: compact collapsed debug panel + icon card layout */ +.debug-panel:not([open]) { + width: 104px !important; + min-width: 0; + overflow: hidden; +} +.debug-panel:not([open]) summary { + display: block; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.debug-panel[open] { + width: min(420px, calc(100% - 24px)); +} + +.card-choice { + position: relative; + display: grid; + grid-template-columns: 54px minmax(0, 1fr); + gap: 10px; + align-items: start; + min-height: 150px; + overflow: hidden; + background: + linear-gradient(135deg, rgba(255,255,255,.08), rgba(0,0,0,.20)), + #20242b; + border-color: var(--line); +} +.card-choice::before { + content: ""; + position: absolute; + inset: 5px; + border: 1px solid rgba(255,184,39,.18); + pointer-events: none; +} +.card-icon { + position: relative; + z-index: 1; + width: 46px; + height: 46px; + display: grid; + place-items: center; + border: 3px solid var(--line); + background: #15181e; + box-shadow: inset 0 0 0 2px rgba(255,184,39,.10), 3px 3px 0 rgba(0,0,0,.35); + image-rendering: pixelated; +} +.card-icon img { + width: 36px; + height: 36px; + object-fit: contain; + image-rendering: pixelated; +} +.card-icon.glyph { + color: var(--warn, #ffb827); + font-size: 24px; + font-weight: 900; + text-align: center; + line-height: 1; +} +.card-copy { + position: relative; + z-index: 1; + min-width: 0; +} +.card-choice strong { + color: var(--warn, #ffb827); + text-shadow: 1px 1px 0 #050609; +} +.card-choice small { color: var(--muted); } +.card-tags span { + background: #15181e; + color: var(--white); + border-color: var(--line); +} +.card-choice.common { background: linear-gradient(145deg, #262c35, #171a20); } +.card-choice.rare { + background: linear-gradient(145deg, #3b3020, #191b20); + box-shadow: inset 0 0 0 3px #f0a020, 5px 5px 0 rgba(0,0,0,.50); +} +.card-choice.ultra-rare { + background: linear-gradient(145deg, #401d2a, #171a20); + box-shadow: inset 0 0 0 3px #c42424, 5px 5px 0 rgba(0,0,0,.55); +} +.card-choice.dud { + background: linear-gradient(145deg, #2b2b2b, #191919); + color: #878787; +} +.card-choice.dud .card-tags span { background: #222; color: #aaa; } + +@media (max-width: 1180px) { + .debug-panel:not([open]) { + width: 92px !important; + right: 8px; + bottom: 8px; + } +} + + +/* v27.17 verified visual patch: cache-proof identity and final UI overrides */ +.build-stamp { + position: absolute; + z-index: 12; + right: 14px; + top: 76px; + padding: 5px 9px; + border: 2px solid #ffb827; + background: rgba(14, 17, 22, .94); + color: #80e067; + box-shadow: 3px 3px 0 rgba(0,0,0,.7); + font: 900 11px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + letter-spacing: .04em; + pointer-events: none; +} +.debug-panel:not([open]) { + width: 58px !important; + max-width: 58px !important; + height: 30px; + min-height: 0; +} +.debug-panel:not([open]) summary { + box-sizing: border-box; + width: 58px; + height: 27px; + padding: 5px 7px; + text-align: center; + overflow: hidden; + text-overflow: clip; +} +.debug-panel[open] { + width: min(390px, calc(100% - 24px)) !important; + height: auto; +} +.card-choice { + border-width: 3px; + box-shadow: 4px 4px 0 rgba(0,0,0,.55), inset 0 0 0 1px rgba(255,184,39,.14); +} +.card-choice:hover { + transform: translateY(-2px); + box-shadow: 4px 6px 0 rgba(0,0,0,.65), inset 0 0 0 2px rgba(128,224,103,.24); +} +.card-icon img { + image-rendering: pixelated; + filter: drop-shadow(2px 2px 0 rgba(0,0,0,.7)); +} +#gameCanvas { image-rendering: pixelated; } diff --git a/styles-v27.18.css b/styles-v27.18.css new file mode 100644 index 0000000..8bb1b90 --- /dev/null +++ b/styles-v27.18.css @@ -0,0 +1,1253 @@ +:root { + --bg: #f2fff0; + --screen: #eefbea; + --panel: rgba(245, 255, 242, 0.96); + --ink: #102015; + --muted: #526456; + --line: #102015; + --green: #22b94f; + --green-soft: #b7f5c6; + --white: #ffffff; + --danger: #c42424; + --shadow: 8px 8px 0 rgba(16, 32, 21, 0.22); +} +* { box-sizing: border-box; } +html, body { min-height: 100%; } +body { margin: 0; background: var(--bg); color: var(--ink); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; overflow-x: hidden; } +button { font: inherit; } +h1, h2, p { margin: 0; } +#app { width: min(100vw, 1680px); margin: 0 auto; padding: 0 8px 12px; } +.game-shell { position: relative; width: 100%; min-height: min(100vh, 920px); border: 4px solid var(--line); border-top: 0; background: var(--screen); overflow: hidden; box-shadow: var(--shadow); } +#gameCanvas { display: block; width: 100%; height: min(calc(100vh - 10px), 900px); min-height: 720px; background: var(--screen); touch-action: none; } +.hud { position: absolute; z-index: 4; display: grid; gap: 6px; pointer-events: none; } +.hud-top-left { top: 10px; left: 10px; grid-template-columns: repeat(6, minmax(82px, auto)); } +.hud-top-right { top: 10px; right: 10px; grid-template-columns: repeat(4, minmax(78px, auto)); } +.hud-card { min-width: 82px; padding: 7px 9px; border: 3px solid var(--line); background: rgba(255,255,255,.88); box-shadow: 4px 4px 0 rgba(16,32,21,.16); } +.hud-card.primary { min-width: 116px; padding: 10px 12px; background: rgba(255,255,255,.96); } +.hud-card.primary span { font-size: 9px; } +.hud-card.primary strong { font-size: clamp(22px, 2vw, 32px); } +.hud-card.time-critical { background: #fff0d1; box-shadow: inset 0 0 0 4px var(--danger), 4px 4px 0 rgba(16,32,21,.16); } +.hud-card span { display: block; font-size: 9px; letter-spacing: .1em; color: var(--muted); margin-bottom: 4px; } +.hud-card strong { font-size: clamp(15px, 1.3vw, 22px); line-height: 1; color: var(--ink); } +.hud-card.cash strong, .hud-card.profit strong, .hud-card.combo strong, .cash-positive { color: var(--green) !important; } +.cash-negative { color: var(--danger) !important; } + +.priority-strip { position: absolute; z-index: 5; top: 76px; left: 10px; display: grid; grid-template-columns: minmax(280px, 1.2fr) minmax(170px, .75fr) minmax(130px, .55fr); gap: 8px; max-width: calc(100% - 420px); pointer-events: none; } +.priority-strip > div { border: 3px solid var(--line); background: rgba(255,255,255,.94); padding: 8px 10px; font-weight: 900; text-transform: uppercase; box-shadow: 4px 4px 0 rgba(16,32,21,.14); font-size: 12px; letter-spacing: .03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.event-brief.active { background: #fff0d1; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.14); } +.event-brief.next { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.14); } +.event-brief.locked { background: #edf3ec; color: var(--muted); } +.target-brief { color: var(--green); } +.speed-brief { color: var(--ink); } + +.build-panel { position: absolute; z-index: 6; top: 118px; right: 12px; bottom: 12px; width: clamp(278px, 23vw, 360px); min-height: 0; padding: 10px; border: 4px solid var(--line); background: var(--panel); box-shadow: var(--shadow); overflow: auto; } +.panel-head { display: grid; gap: 8px; margin-bottom: 10px; } +.panel-head h1 { font-size: 15px; letter-spacing: .06em; } +.panel-head h1 span { font-size: 9px; color: var(--white); background: var(--green); border: 2px solid var(--line); padding: 1px 6px; } +.panel-head p { color: var(--muted); margin-top: 4px; font-size: 9px; line-height: 1.25; } +.panel-grid { display: grid; grid-template-columns: 1fr; gap: 10px; } +.build-panel h2 { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; margin-bottom: 7px; } +.large-tools { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; } +.history-tools { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; grid-column: 1 / -1; } +.tool-button.small { min-height: 40px; padding: 6px; } +.tool-button, .primary-button, .sort-button, .facility-action { border: 3px solid var(--line); background: var(--white); color: var(--ink); font-weight: 900; text-transform: uppercase; cursor: pointer; box-shadow: 4px 4px 0 rgba(16,32,21,.18); } +.tool-button { min-height: 50px; text-align: left; padding: 8px; } +.tool-button strong { display: block; font-size: 12px; } +.tool-button span { display: block; margin-top: 4px; font-size: 9px; color: var(--muted); } +.tool-button.active { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.18); } +.tool-button.danger.active { background: #ffdada; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.18); } +.primary-button { padding: 10px 12px; background: var(--green); color: var(--white); white-space: nowrap; } +.primary-button:disabled, .tool-button:disabled, .sort-button:disabled, .facility-action:disabled { opacity: .42; cursor: not-allowed; } +.mini-box { border: 3px solid var(--line); background: var(--white); padding: 12px; line-height: 1.45; color: var(--muted); font-size: 11px; } +.facility-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; } +.facility-action { padding: 7px 9px; font-size: 9px; } +.facility-action.good { background: var(--green-soft); } +.facility-action.warn { background: #fff0d1; } +.facility-action.danger { background: #ffdada; } +.control-dock { position: absolute; z-index: 7; left: 50%; bottom: 12px; transform: translateX(-50%); display: grid; grid-template-columns: repeat(4, 150px); gap: 8px; padding: 7px; border: 3px solid var(--line); background: rgba(255,255,255,.90); } +.sort-button { min-height: 46px; font-size: 12px; } +/* Debug UI is intentionally kept for active balancing builds. Do not remove during cleanup/audit passes unless explicitly requested. */ +.debug-panel { + position: absolute; + z-index: 9; + left: 10px; + bottom: 10px; + width: min(410px, calc(100% - 20px)); + border: 3px solid var(--line); + background: rgba(255,255,255,.96); + box-shadow: 4px 4px 0 rgba(16,32,21,.16); + font-weight: 900; +} +.debug-panel summary { + cursor: pointer; + padding: 5px 8px; + color: var(--danger); + font-size: 14px; + line-height: 1.1; +} +.debug-body { + display: grid; + grid-template-columns: 1fr 92px; + gap: 6px; + padding: 7px; + border-top: 3px solid var(--line); + font-size: 12px; + line-height: 1.15; +} +.debug-body label, +.debug-body button, +.debug-body select, +.debug-body input { + min-width: 0; + font: inherit; +} +.debug-check, +.debug-card, +.debug-target, +.debug-readout { + grid-column: 1 / -1; +} +.debug-row { + display: grid; + grid-template-columns: 1fr 92px; + gap: 6px; + grid-column: 1 / -1; +} +.debug-day { + display: grid; + grid-template-columns: 38px 1fr; + align-items: center; + gap: 4px; +} +.debug-body button { + border: 2px solid var(--line); + background: var(--white); + cursor: pointer; + font-weight: 900; + padding: 5px 6px; + line-height: 1.05; +} +.debug-body input[type="number"], +.debug-body select { + width: 100%; + border: 2px solid var(--line); + background: var(--white); + padding: 4px 5px; + min-height: 29px; +} +.debug-target select:disabled { + opacity: .55; +} +.debug-readout { + border: 2px solid var(--line); + background: #f7fff5; + color: var(--muted); + padding: 5px; + line-height: 1.25; + max-height: 64px; + overflow: auto; +} +.modal { position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; padding: 22px; background: rgba(16,32,21,.45); } +.modal.visible { display: flex; } +.modal-card { width: min(860px, 96vw); border: 4px solid var(--line); padding: 24px; background: var(--white); box-shadow: var(--shadow); } +.modal-card h2 { font-size: 26px; text-transform: uppercase; margin-bottom: 12px; } +.modal-card p { line-height: 1.55; } +.modal-card ul { margin: 12px 0 0; padding-left: 22px; line-height: 1.55; color: var(--muted); } +.modal-actions { margin-top: 18px; display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap; } +.route-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 14px 0; } +.route-card { border: 3px solid var(--line); background: #f7fff5; padding: 14px; display: grid; grid-template-columns: 44px 1fr 28px 1fr; align-items: center; gap: 4px 8px; } +.route-card .route-icon { grid-row: 1 / span 2; font-size: 30px; text-align: center; } +.route-card strong, .route-card em { font-style: normal; font-weight: 900; text-transform: uppercase; } +.route-card b { font-size: 24px; color: var(--green); text-align: center; } +.route-card small { grid-column: 2 / span 3; color: var(--muted); font-weight: 900; } +.result-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 12px; } +.result-grid div { border: 3px solid var(--line); padding: 10px; background: #f7fff5; } +.result-grid strong { display: block; font-size: 11px; color: var(--muted); text-transform: uppercase; margin-bottom: 6px; } +.result-grid span { font-size: 16px; font-weight: 900; color: var(--ink); } +.game-shell:not(.phase-build) .build-panel { display: none; } +.game-shell.phase-running .hud-top-right { display: none; } +.game-shell:not(.phase-running) .control-dock { display: none; } +@media (max-width: 1180px) { + #app { padding: 0; } + .game-shell { min-height: 100vh; } + #gameCanvas { height: 100vh; } + .hud-top-left, .hud-top-right { grid-template-columns: repeat(2, minmax(76px, auto)); } + .priority-strip { top: 150px; left: 8px; right: 8px; max-width: none; grid-template-columns: 1fr; } + .build-panel { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 42vh; } + .large-tools { grid-template-columns: 1fr 1fr; } + .control-dock { grid-template-columns: repeat(2, 150px); } + .route-cards, .result-grid { grid-template-columns: 1fr; } +} + +.event-card { border: 3px solid var(--line); background: #f7fff5; padding: 12px; line-height: 1.35; color: var(--ink); font-size: 11px; box-shadow: 4px 4px 0 rgba(16,32,21,.14); } +.event-card.empty { color: var(--muted); background: rgba(255,255,255,.72); } +.event-card.empty strong { display: block; color: var(--ink); margin-bottom: 4px; } +.event-card h3 { margin: 2px 0 7px; font-size: 14px; text-transform: uppercase; letter-spacing: .04em; } +.event-card p { margin: 5px 0; } +.event-card.accepted { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.14); } +.event-card.declined { background: #f1f1f1; color: var(--muted); } +.event-status { display: inline-block; padding: 2px 7px; border: 2px solid var(--line); background: var(--white); font-size: 9px; font-weight: 900; letter-spacing: .1em; margin-bottom: 4px; } +.event-metrics { display: grid; grid-template-columns: 1fr; gap: 4px; margin: 8px 0; } +.event-metrics span { display: block; border: 2px solid rgba(16,32,21,.55); background: rgba(255,255,255,.82); padding: 5px; font-weight: 900; color: var(--ink); } +.event-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; } +.result-section-title { margin: 16px 0 8px; font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .12em; color: var(--green); } +.result-section-title:first-child { margin-top: 0; } +.muted-title { color: var(--muted); border: 3px solid var(--line); padding: 10px; background: #f7fff5; } + +.compact-rules .mini-box { padding: 8px; font-size: 9px; } +.primary-button:disabled { filter: grayscale(1); background: #c9d2ca; color: #526456; } +.formula-box { + border: 3px solid var(--line); + background: #f7fff5; + padding: 10px; + margin: 10px 0; + line-height: 1.5; + color: var(--ink); + font-size: 12px; + font-weight: 700; +} +.equipment-menu-lines { + border: 3px solid var(--line); + background: #ffffff; + padding: 10px; + margin: 8px 0; + color: var(--muted); + line-height: 1.45; +} +.equipment-menu-lines p { margin: 4px 0; } + +/* v11 compact clicked-equipment bubble */ +.modal.equipment-popover { + background: transparent; + align-items: flex-start; + justify-content: flex-start; + padding: 0; + pointer-events: none; +} +.modal.equipment-popover .modal-card { + position: absolute; + left: var(--popover-x, 16px); + top: var(--popover-y, 16px); + width: min(250px, calc(100vw - 24px)); + max-height: min(280px, calc(100vh - 24px)); + overflow: auto; + padding: 8px; + border-width: 3px; + pointer-events: auto; + box-shadow: 6px 6px 0 rgba(16,32,21,.18); +} +.modal.equipment-popover .modal-card h2 { + font-size: 14px; + margin-bottom: 6px; +} +.modal.equipment-popover .modal-actions { + margin-top: 8px; + gap: 6px; + justify-content: flex-start; +} +.modal.equipment-popover .modal-actions button { + padding: 5px 7px; + font-size: 9px; +} +.equipment-menu-lines.compact { + padding: 7px; + margin: 6px 0; + font-size: 9px; +} +.formula-box.compact { + padding: 7px; + margin: 6px 0; + font-size: 9px; +} + +/* v15 pre-build card draft */ +.card-choices { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(190px, 220px)); + justify-content: center; + align-items: stretch; + gap: 10px; + margin-top: 14px; +} +.card-choice { + min-height: 132px; + border: 3px solid var(--line); + background: #f7fff5; + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.16); + padding: 12px; + text-align: left; + cursor: pointer; + font-weight: 900; +} +.card-choice:hover { transform: translate(-1px, -1px); box-shadow: 6px 6px 0 rgba(16,32,21,.18); } +.card-choice strong { display: block; font-size: 14px; text-transform: uppercase; line-height: 1.2; } +.card-choice span { display: inline-block; margin: 8px 0; padding: 2px 7px; border: 2px solid var(--line); background: var(--white); font-size: 9px; letter-spacing: .1em; } +.card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin: 7px 0; } +.card-tags span { margin: 0; padding: 2px 5px; font-size: 8px; line-height: 1.1; letter-spacing: .04em; } +.card-choice small { display: block; color: var(--muted); font-size: 11px; line-height: 1.35; } +.card-choice.rare { background: #fff0d1; box-shadow: inset 0 0 0 3px #f0a020, 5px 5px 0 rgba(16,32,21,.16); } +.card-choice.ultra-rare { background: #ffe6f0; box-shadow: inset 0 0 0 3px #c42424, 5px 5px 0 rgba(16,32,21,.18); } +.card-choice.ultra-rare span { background: #c42424; color: #fff; } +.muted-card-note { color: var(--muted); font-weight: 700; } +.card-targets { display: grid; gap: 8px; margin-top: 14px; } +.card-target-button { border: 3px solid var(--line); background: #f7fff5; padding: 10px 12px; text-align: left; cursor: pointer; font-weight: 900; box-shadow: 4px 4px 0 rgba(16,32,21,.14); } +.card-target-button:hover { background: var(--green-soft); } + +/* v19 readability pass */ +body { font-size: 16px; } +.hud-card span { font-size: 11px; } +.hud-card strong { font-size: clamp(18px, 1.5vw, 25px); } +.priority-strip > div { font-size: 14px; } +.panel-head h1 { font-size: 18px; } +.panel-head p { font-size: 11px; } +.build-panel h2 { font-size: 13px; } +.tool-button strong { font-size: 14px; } +.tool-button span { font-size: 11px; } +.mini-box, .event-card { font-size: 12px; } +.sort-button { font-size: 14px; } +.modal-card h2 { font-size: 29px; } +.card-choice strong { font-size: 16px; } +.card-choice small { font-size: 13px; } + +.tool-button.unaffordable, .tool-button.already-built { opacity: .42; filter: grayscale(.7); } + +.hover-tooltip { + position: fixed; + z-index: 30; + width: min(320px, calc(100vw - 20px)); + display: none; + border: 3px solid var(--line); + background: rgba(255,255,255,.96); + color: var(--ink); + box-shadow: 6px 6px 0 rgba(16,32,21,.18); + padding: 10px; + pointer-events: none; + line-height: 1.35; +} +.hover-tooltip.visible { display: block; } +.hover-tooltip strong { display: block; font-size: 15px; text-transform: uppercase; margin-bottom: 5px; } +.hover-tooltip em { display: block; font-style: normal; color: var(--green); font-weight: 900; margin-bottom: 7px; } +.hover-tooltip em.warning { color: var(--danger); } +.hover-tooltip span { display: block; color: var(--muted); font-size: 12px; } + + +.card-choice.dud { + background: #eeeeee; + color: #777; + filter: grayscale(1); + border-style: dashed; + box-shadow: 5px 5px 0 rgba(16,32,21,.10); +} +.card-choice.dud span { background: #f8f8f8; } +.card-choice.flung { + pointer-events: none; + transform: translate(var(--fling-x, 480px), var(--fling-y, -320px)) rotate(var(--fling-r, 68deg)) scale(.68); + opacity: 0; + transition: transform .34s cubic-bezier(.18,.84,.26,.99), opacity .28s ease-in; +} + + + +.route-card .route-icon.male, +.route-card .route-icon.female, +.route-card .route-icon.poop { + display: inline-grid; + place-items: center; + width: 38px; + height: 38px; + border-radius: 999px; + border: 3px solid var(--line, #102015); + background: var(--white, #fff); + line-height: 1; +} +.route-card .route-icon.male { color: #2477ff; background: #d9ecff; } +.route-card .route-icon.female { color: #d62a85; background: #ffe0f0; } +.route-card .route-icon.poop { color: #7b4a23; background: #fff0d1; font-size: 24px; } +.restart-button { min-width: 160px; } +.restart-fallback-note { margin-top: 12px; color: var(--muted, #526456); font-weight: 700; } + +/* v24.4 hover-only build-button flavor / cashout guidance / compact game-over */ +.tool-button .tool-flavor { + display: block; + max-height: 0; + opacity: 0; + overflow: hidden; + margin-top: 0; + color: var(--muted); + font-size: 8px; + line-height: 1.22; + text-transform: none; + letter-spacing: 0; + transition: max-height .12s ease, opacity .12s ease, margin-top .12s ease; +} +.tool-button:hover .tool-flavor { + max-height: 42px; + opacity: 1; + margin-top: 5px; +} +.large-tools .tool-button { min-height: 58px; } +.large-tools .tool-button:hover { min-height: 78px; } +.history-tools .tool-button.small { min-height: 40px; } +.primary-button.cashout-emphasis, +.tool-button.cashout-emphasis { + opacity: 1 !important; + filter: none !important; + animation: cashoutPulse 0.9s ease-in-out infinite alternate; +} +.primary-button.cashout-emphasis { + box-shadow: inset 0 0 0 4px #fff0d1, 6px 6px 0 rgba(16,32,21,.22); +} +.tool-button.cashout-emphasis { + background: #fff0d1; + box-shadow: inset 0 0 0 3px var(--danger), 6px 6px 0 rgba(16,32,21,.20); +} +@keyframes cashoutPulse { + from { transform: translate(0, 0); } + to { transform: translate(-1px, -1px); } +} +.modal.gameover-modal { padding: 12px; } +.modal.gameover-modal .modal-card { + width: min(640px, 92vw); + max-height: min(82vh, 720px); + overflow: auto; + padding: 16px; +} +.modal.gameover-modal .modal-card h2 { + font-size: 22px; + margin-bottom: 8px; +} +.gameover-reason { font-weight: 900; color: var(--danger); margin-bottom: 8px; } +.settlement-net { + border: 3px solid var(--line); + background: #f7fff5; + padding: 10px 12px; + margin-bottom: 10px; + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + font-weight: 900; + text-transform: uppercase; +} +.settlement-net strong { font-size: 24px; } +.settlement-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; } +.settlement-grid div { padding: 8px; } +.settlement-grid span { display: block; font-size: 14px; } +.gameover-summary { + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 6px; + margin-top: 8px; +} +.gameover-breakdown { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 6px; + margin-top: 8px; +} +.modal.gameover-modal .result-grid div { padding: 7px; } +.modal.gameover-modal .result-grid strong { font-size: 9px; margin-bottom: 3px; } +.modal.gameover-modal .result-grid span { font-size: 12px; } +.gameover-details { + margin-top: 10px; + border: 3px solid var(--line); + background: #f7fff5; + padding: 8px; +} +.gameover-details summary { + cursor: pointer; + font-weight: 900; + text-transform: uppercase; +} +.modal.gameover-modal .formula-box.compact { font-size: 9px; line-height: 1.35; } +@media (max-width: 720px) { + .gameover-summary, .gameover-breakdown { grid-template-columns: 1fr 1fr; } +} + +/* v27.0 cleanup and stable build-menu tooltip pass */ +body { font-size: 18px; } +.build-panel { width: clamp(330px, 26vw, 420px); } +.panel-head h1 { font-size: 20px; } +.panel-head h1 span { font-size: 12px; } +.panel-head p { font-size: 13px; line-height: 1.35; } +.build-panel h2 { font-size: 14px; } +.priority-strip > div { font-size: 15px; } +.hud-card span { font-size: 12px; } +.hud-card strong { font-size: clamp(20px, 1.7vw, 28px); } +.mini-box, .event-card { font-size: 14px; line-height: 1.45; } +.compact-rules .mini-box { font-size: 13px; } +.tool-button { + position: relative; + overflow: visible; + min-height: 62px; + padding: 10px; +} +.large-tools .tool-button { min-height: 62px; } +.large-tools .tool-button:hover { min-height: 62px; } +.tool-button strong { font-size: 15px; line-height: 1.15; } +.tool-button span { font-size: 12px; } +.tool-button .tool-flavor { + display: none; + position: absolute; + z-index: 60; + left: 0; + top: calc(100% + 7px); + width: min(300px, calc(100vw - 40px)); + max-height: none; + opacity: 1; + overflow: visible; + margin: 0; + padding: 10px 12px; + border: 3px solid var(--line); + background: rgba(255,255,255,.98); + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + font-size: 13px; + line-height: 1.35; + text-transform: none; + letter-spacing: 0; + pointer-events: none; + transition: none; +} +.tool-button .tool-flavor::before { + content: ''; + position: absolute; + left: 16px; + top: -10px; + width: 16px; + height: 16px; + border-left: 3px solid var(--line); + border-top: 3px solid var(--line); + background: rgba(255,255,255,.98); + transform: rotate(45deg); +} +.tool-button:hover .tool-flavor { + display: block; + max-height: none; + opacity: 1; + margin: 0; +} +.primary-button { font-size: 16px; padding: 13px 16px; } +#nextTurnButton { min-height: 56px; font-size: 18px; } +@keyframes cashoutPulse { + from { box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.18); filter: brightness(1); } + to { box-shadow: inset 0 0 0 5px #fff0d1, 4px 4px 0 rgba(16,32,21,.20); filter: brightness(1.08); } +} +.card-choices { grid-template-columns: repeat(auto-fill, minmax(230px, 270px)); gap: 14px; } +.card-choice { min-height: 164px; padding: 15px; } +.card-choice strong { font-size: 18px; } +.card-choice span { font-size: 11px; } +.card-choice small { font-size: 15px; line-height: 1.4; } +.muted-card-note { font-size: 15px; line-height: 1.45; } +.modal-card { width: min(980px, 96vw); } +.modal-card p, .modal-card li { font-size: 16px; } +.modal-actions .reroll-button { + order: 99; + flex: 1 1 100%; + min-height: 64px; + margin-top: 8px; + font-size: 20px; + text-align: center; + justify-content: center; + background: #fff0d1; + box-shadow: inset 0 0 0 4px var(--green), 6px 6px 0 rgba(16,32,21,.20); +} +.modal-actions .reroll-button:disabled { box-shadow: 4px 4px 0 rgba(16,32,21,.12); } +.hover-tooltip strong { font-size: 17px; } +.hover-tooltip span { font-size: 14px; } +.sort-button { font-size: 16px; min-height: 56px; } +.control-dock { grid-template-columns: repeat(4, 172px); } +@media (max-width: 1180px) { + .build-panel { width: auto; } + .control-dock { grid-template-columns: repeat(2, 172px); } +} + +/* v27.1 expansion/readability pass */ +body { font-size: 20px; } +.panel-head h1 { font-size: 22px; } +.panel-head h1 span { font-size: 13px; } +.panel-head p { font-size: 14px; line-height: 1.35; } +.build-panel h2 { font-size: 15px; } +.priority-strip > div { font-size: 16px; } +.hud-card span { font-size: 13px; } +.hud-card strong { font-size: clamp(22px, 1.8vw, 30px); } +.mini-box, .event-card { font-size: 15px; line-height: 1.5; } +.compact-rules .mini-box { font-size: 14px; } +.tool-button strong { font-size: 16px; line-height: 1.15; } +.tool-button span { font-size: 13px; line-height: 1.2; } +.tool-button .tool-flavor { + left: auto; + right: 0; + width: min(320px, calc(100vw - 40px)); + font-size: 14px; + line-height: 1.4; + overflow-wrap: anywhere; +} +.tool-button .tool-flavor::before { left: auto; right: 18px; } +.tool-button.unaffordable .tool-flavor, +.tool-button.unaffordable:hover .tool-flavor, +.tool-button:disabled .tool-flavor, +.tool-button:disabled:hover .tool-flavor { display: none; } +.facility-action { font-size: 12px; } +.primary-button { font-size: 17px; } +#nextTurnButton { font-size: 19px; } +.card-choice strong { font-size: 19px; } +.card-choice span { font-size: 12px; } +.card-choice small { font-size: 16px; line-height: 1.45; } +.muted-card-note { font-size: 16px; } +.modal-card p, .modal-card li { font-size: 17px; } +.modal.equipment-popover .modal-card h2 { font-size: 16px; } +.modal.equipment-popover .modal-actions button { font-size: 11px; } +.equipment-menu-lines.compact, .formula-box.compact { font-size: 11px; } +.hover-tooltip strong { font-size: 18px; } + +/* Keep construction flavor text readable as a hover bubble, not button content. */ +.large-tools .tool-button { + min-height: 62px; + position: relative; + overflow: visible; +} +.large-tools .tool-button:hover { + min-height: 62px; +} +.large-tools .tool-button .tool-flavor { + display: none; + position: absolute; + z-index: 90; + right: 0; + top: calc(100% + 8px); + width: min(320px, calc(100vw - 40px)); + max-height: none; + opacity: 1; + overflow: visible; + margin: 0; + padding: 10px 12px; + border: 3px solid var(--line); + background: rgba(255,255,255,.98); + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + font-size: 14px; + line-height: 1.35; + pointer-events: none; + overflow-wrap: anywhere; +} +.large-tools .tool-button:hover .tool-flavor { + display: block; +} +.large-tools .tool-button .tool-flavor::before { + content: ''; + position: absolute; + right: 18px; + top: -10px; + width: 16px; + height: 16px; + border-left: 3px solid var(--line); + border-top: 3px solid var(--line); + background: rgba(255,255,255,.98); + transform: rotate(45deg); +} +.hover-tooltip span { font-size: 15px; } +.sort-button { font-size: 17px; } + +/* v27.3 offscreen scanner monitor / expansion UI pass */ +.scanner-monitor { + position: absolute; + z-index: 8; + left: 12px; + bottom: 92px; + display: none; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 8px; + width: min(560px, calc(100% - 24px)); + pointer-events: auto; +} +.scanner-monitor.visible { display: grid; } +.scanner-monitor-card { + border: 3px solid var(--line); + background: rgba(255,255,255,.95); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + padding: 9px; + font-weight: 900; +} +.scanner-monitor-card header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin-bottom: 7px; + text-transform: uppercase; +} +.scanner-monitor-card header strong { font-size: 20px; color: var(--green); } +.scanner-monitor-card header span { font-size: 12px; color: var(--muted); } +.scanner-mini-map { + display: grid; + grid-template-columns: 42px 1fr 82px; + align-items: center; + gap: 6px; + margin-bottom: 8px; +} +.scanner-mini-map > span, +.scanner-mini-map > b { + border: 2px solid var(--line); + background: #f7fff5; + padding: 7px 6px; + text-align: center; + font-size: 13px; + min-height: 36px; +} +.scanner-current { display: block; color: var(--ink); } +.scanner-current.male { color: #2477ff; } +.scanner-current.female { color: #d62a85; } +.scanner-current.poop { color: #7b4a23; } +.scanner-current.empty { color: var(--muted); } + +.scanner-mini-grid { + display: grid; + grid-template-columns: repeat(5, 27px); + gap: 3px; + justify-content: center; + align-items: center; + padding: 6px; + margin: 0 0 8px; + border: 2px solid var(--line); + background: #f6f1df; +} +.scanner-mini-grid .mini-cell { + width: 27px; + height: 27px; + display: grid; + place-items: center; + border: 1px solid rgba(22,38,25,.28); + background: #fffdfa; + color: var(--muted); + font-size: 11px; + font-weight: 900; + line-height: 1; +} +.scanner-mini-grid .mini-cell.belt { background: #e7f7e4; color: var(--green-dark); } +.scanner-mini-grid .mini-cell.input { background: #fff3bf; color: var(--ink); font-size: 9px; } +.scanner-mini-grid .mini-cell.scanner { background: var(--green); color: #fff; border-color: var(--line); font-size: 16px; } +.scanner-mini-grid .mini-cell.scanner.male { background: #2477ff; } +.scanner-mini-grid .mini-cell.scanner.female { background: #d62a85; } +.scanner-mini-grid .mini-cell.scanner.poop { background: #7b4a23; } +.scanner-mini-grid .mini-cell.scanner-other { background: #b7f5c6; color: var(--ink); } +.scanner-mini-grid .mini-cell.egg { background: #fff7c4; color: #7a5a00; } +.scanner-mini-grid .mini-cell.port { background: #dbe7ff; color: #27427d; } +.scanner-mini-grid .mini-cell.blocked { background: #d7cfc1; color: #6d4d35; } + +.scanner-monitor-actions { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 7px; +} +.scanner-monitor-actions button { + border: 3px solid var(--line); + background: var(--green-soft); + color: var(--ink); + cursor: pointer; + font: inherit; + font-size: 14px; + font-weight: 900; + min-height: 44px; + box-shadow: 3px 3px 0 rgba(16,32,21,.18); +} +.scanner-monitor-actions button:disabled { + background: #edf3ec; + color: var(--muted); + opacity: .62; + cursor: not-allowed; +} +@media (max-width: 1180px) { + .scanner-monitor { bottom: 132px; width: min(520px, calc(100% - 16px)); left: 8px; } +} + +/* ------------------------------------------------------------------ + DARK FACTORY VISUAL PASS + - Facility sprites are now loaded from assets/dark_factory/. + - Debug UI is intentionally retained for balancing builds. Do not remove. + ------------------------------------------------------------------ */ +:root { + --bg: #0b0c0f; + --screen: #111318; + --panel: rgba(24, 27, 34, 0.96); + --panel-2: #20242b; + --panel-3: #2a303a; + --ink: #e6edf2; + --muted: #8f9bab; + --line: #050609; + --green: #7bd84f; + --green-soft: #273c24; + --white: #e6edf2; + --danger: #e34a36; + --warn: #ffb827; + --cyan: #4aa3ff; + --orange: #c86a2b; + --shadow: 6px 6px 0 rgba(0, 0, 0, 0.62); +} +html, body { background: #050609; color: var(--ink); } +body { + background: + linear-gradient(90deg, rgba(255,184,39,.035) 1px, transparent 1px) 0 0 / 32px 32px, + linear-gradient(rgba(255,184,39,.028) 1px, transparent 1px) 0 0 / 32px 32px, + #050609; +} +#app { width: min(100vw, 1720px); padding: 0; } +.game-shell { + min-height: 100vh; + border: 0; + background: var(--screen); + box-shadow: inset 0 0 0 4px #050609, inset 0 0 0 8px #303744; +} +#gameCanvas { + height: 100vh; + min-height: 720px; + background: var(--screen); + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.hud { gap: 4px; } +.hud-top-left { + top: 8px; + left: 8px; + right: 420px; + grid-template-columns: 1.25fr repeat(5, minmax(92px, .65fr)); +} +.hud-top-right { + top: 8px; + right: 8px; + grid-template-columns: repeat(4, minmax(74px, auto)); +} +.hud-card { + min-width: 74px; + padding: 7px 9px; + border: 3px solid var(--line); + background: linear-gradient(#242a33, #171a20); + box-shadow: 4px 4px 0 rgba(0,0,0,.7), inset 0 0 0 2px rgba(255,184,39,.10); + color: var(--ink); +} +.hud-card span { color: var(--warn); font-size: 9px; letter-spacing: .12em; } +.hud-card strong { color: var(--ink); text-shadow: 2px 2px 0 #050609; } +.hud-card.cash strong, .hud-card.profit strong, .hud-card.combo strong, .cash-positive { color: var(--green) !important; } +.hud-card.time-critical { background: #3a1f1f; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.7); } +.priority-strip { + top: 74px; + left: 10px; + width: clamp(250px, 21vw, 330px); + max-width: none; + grid-template-columns: 1fr; + gap: 6px; +} +.priority-strip > div { + border: 3px solid var(--line); + background: linear-gradient(#222832, #15181e); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.12); +} +.event-brief.active { background: #38251a; box-shadow: inset 0 0 0 3px var(--orange), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.next { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.locked { background: #181b20; color: var(--muted); } +.target-brief { color: var(--warn); } +.speed-brief { color: var(--cyan); } +.build-panel { + top: 82px; + right: 8px; + bottom: 8px; + width: clamp(320px, 24vw, 410px); + padding: 9px; + border: 4px solid var(--line); + background: linear-gradient(#222832, #14171d); + box-shadow: 6px 6px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.10); + scrollbar-color: var(--warn) #111318; +} +.panel-head { + display: grid; + grid-template-columns: 1fr 126px; + align-items: stretch; + gap: 8px; + margin-bottom: 8px; +} +.panel-head h1 { color: var(--warn); text-shadow: 2px 2px 0 #050609; font-size: 17px; } +.panel-head h1 span { color: #050609; background: var(--warn); border-color: var(--line); } +.panel-head p { color: var(--muted); } +.panel-grid { + display: grid; + grid-template-columns: 1fr; + gap: 8px; +} +.build-panel h2, .result-section-title { color: var(--warn); } +.large-tools { + grid-template-columns: 1fr 1fr; + gap: 6px; +} +.tool-button, .primary-button, .sort-button, .facility-action { + border: 3px solid var(--line); + background: linear-gradient(#2a303a, #171a20); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.70), inset 0 0 0 2px rgba(255,184,39,.08); + text-shadow: 1px 1px 0 #050609; +} +.tool-button { min-height: 48px; padding: 8px; } +.tool-button strong { color: var(--ink); } +.tool-button span { color: var(--muted); } +.tool-button.active { + background: linear-gradient(#33311d, #1e2117); + box-shadow: inset 0 0 0 3px var(--warn), 4px 4px 0 rgba(0,0,0,.70); +} +.tool-button.danger.active { background: linear-gradient(#4b1f1c, #241014); box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.70); } +.primary-button { background: linear-gradient(#8b2d23, #4b1714); color: #fff3d2; } +.primary-button:not(:disabled) { box-shadow: inset 0 0 0 3px #ffb827, 5px 5px 0 rgba(0,0,0,.72); } +.primary-button:disabled, .tool-button:disabled, .sort-button:disabled, .facility-action:disabled { opacity: .42; filter: grayscale(1); } +.mini-box, .event-card, .formula-box, .equipment-menu-lines, .route-card, .result-grid div, .muted-title { + border: 3px solid var(--line); + background: #15181e; + color: var(--muted); + box-shadow: inset 0 0 0 2px rgba(255,184,39,.08); +} +.event-card h3, .event-card strong, .event-metrics span { color: var(--ink); } +.event-card.accepted { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-card.empty { background: #15181e; color: var(--muted); } +.event-metrics span { border-color: #3d4654; background: #20242b; } +.event-status { background: #2a303a; color: var(--warn); border-color: var(--line); } +.control-dock { + left: 50%; + right: auto; + bottom: 8px; + transform: translateX(-50%); + grid-template-columns: repeat(4, minmax(135px, 160px)); + gap: 6px; + padding: 6px; + border: 4px solid var(--line); + background: rgba(13,15,19,.96); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(255,184,39,.10); +} +.sort-button { min-height: 44px; font-size: 12px; } +.scanner-monitor { + position: absolute; + z-index: 5; + left: 10px; + top: 198px; + width: clamp(250px, 21vw, 330px); +} +.scanner-monitor-card { + border: 3px solid var(--line) !important; + background: linear-gradient(#222832, #15181e) !important; + color: var(--ink) !important; + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.10) !important; +} +.scanner-monitor-card strong { color: var(--warn); } +.debug-panel { + left: auto; + right: 12px; + bottom: 10px; + width: min(420px, calc(100% - 24px)); + border-color: var(--line); + background: rgba(16,18,23,.97); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(227,74,54,.18); + color: var(--ink); +} +.debug-panel summary { color: var(--danger); } +.debug-body { border-top-color: var(--line); } +.debug-body button, .debug-body input[type="number"], .debug-body select, .debug-readout { + border-color: var(--line); + background: #20242b; + color: var(--ink); +} +.debug-readout { color: var(--muted); } +.modal { background: rgba(3,4,6,.72); } +.modal-card { + border-color: var(--line); + background: linear-gradient(#242a33, #15181e); + color: var(--ink); + box-shadow: 8px 8px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.12); +} +.modal-card h2 { color: var(--warn); text-shadow: 2px 2px 0 #050609; } +.modal-card ul, .modal-card p { color: var(--muted); } +.hover-tooltip { + border-color: var(--line) !important; + background: rgba(20,23,29,.98) !important; + color: var(--ink) !important; + box-shadow: 5px 5px 0 rgba(0,0,0,.72) !important; +} +::-webkit-scrollbar { width: 14px; height: 14px; } +::-webkit-scrollbar-track { background: #111318; } +::-webkit-scrollbar-thumb { background: #333b48; border: 3px solid #111318; } +::-webkit-scrollbar-thumb:hover { background: #ffb827; } +@media (max-width: 1180px) { + .hud-top-left { right: 8px; grid-template-columns: repeat(3, minmax(80px, 1fr)); } + .hud-top-right { top: 132px; left: 8px; right: auto; grid-template-columns: repeat(2, minmax(82px, auto)); } + .priority-strip { top: 226px; } + .scanner-monitor { top: 348px; } + .build-panel { left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 46vh; } + .control-dock { grid-template-columns: repeat(2, 150px); } +} + +/* v27.16: compact collapsed debug panel + icon card layout */ +.debug-panel:not([open]) { + width: 104px !important; + min-width: 0; + overflow: hidden; +} +.debug-panel:not([open]) summary { + display: block; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.debug-panel[open] { + width: min(420px, calc(100% - 24px)); +} + +.card-choice { + position: relative; + display: grid; + grid-template-columns: 54px minmax(0, 1fr); + gap: 10px; + align-items: start; + min-height: 150px; + overflow: hidden; + background: + linear-gradient(135deg, rgba(255,255,255,.08), rgba(0,0,0,.20)), + #20242b; + border-color: var(--line); +} +.card-choice::before { + content: ""; + position: absolute; + inset: 5px; + border: 1px solid rgba(255,184,39,.18); + pointer-events: none; +} +.card-icon { + position: relative; + z-index: 1; + width: 46px; + height: 46px; + display: grid; + place-items: center; + border: 3px solid var(--line); + background: #15181e; + box-shadow: inset 0 0 0 2px rgba(255,184,39,.10), 3px 3px 0 rgba(0,0,0,.35); + image-rendering: pixelated; +} +.card-icon img { + width: 36px; + height: 36px; + object-fit: contain; + image-rendering: pixelated; +} +.card-icon.glyph { + color: var(--warn, #ffb827); + font-size: 24px; + font-weight: 900; + text-align: center; + line-height: 1; +} +.card-copy { + position: relative; + z-index: 1; + min-width: 0; +} +.card-choice strong { + color: var(--warn, #ffb827); + text-shadow: 1px 1px 0 #050609; +} +.card-choice small { color: var(--muted); } +.card-tags span { + background: #15181e; + color: var(--white); + border-color: var(--line); +} +.card-choice.common { background: linear-gradient(145deg, #262c35, #171a20); } +.card-choice.rare { + background: linear-gradient(145deg, #3b3020, #191b20); + box-shadow: inset 0 0 0 3px #f0a020, 5px 5px 0 rgba(0,0,0,.50); +} +.card-choice.ultra-rare { + background: linear-gradient(145deg, #401d2a, #171a20); + box-shadow: inset 0 0 0 3px #c42424, 5px 5px 0 rgba(0,0,0,.55); +} +.card-choice.dud { + background: linear-gradient(145deg, #2b2b2b, #191919); + color: #878787; +} +.card-choice.dud .card-tags span { background: #222; color: #aaa; } + +@media (max-width: 1180px) { + .debug-panel:not([open]) { + width: 92px !important; + right: 8px; + bottom: 8px; + } +} + + +/* v27.18 inherited cache-proof identity and final UI overrides */ +.build-stamp { + position: absolute; + z-index: 12; + right: 14px; + top: 76px; + padding: 5px 9px; + border: 2px solid #ffb827; + background: rgba(14, 17, 22, .94); + color: #80e067; + box-shadow: 3px 3px 0 rgba(0,0,0,.7); + font: 900 11px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + letter-spacing: .04em; + pointer-events: none; +} +.debug-panel:not([open]) { + width: 58px !important; + max-width: 58px !important; + height: 30px; + min-height: 0; +} +.debug-panel:not([open]) summary { + box-sizing: border-box; + width: 58px; + height: 27px; + padding: 5px 7px; + text-align: center; + overflow: hidden; + text-overflow: clip; +} +.debug-panel[open] { + width: min(390px, calc(100% - 24px)) !important; + height: auto; +} +.card-choice { + border-width: 3px; + box-shadow: 4px 4px 0 rgba(0,0,0,.55), inset 0 0 0 1px rgba(255,184,39,.14); +} +.card-choice:hover { + transform: translateY(-2px); + box-shadow: 4px 6px 0 rgba(0,0,0,.65), inset 0 0 0 2px rgba(128,224,103,.24); +} +.card-icon img { + image-rendering: pixelated; + filter: drop-shadow(2px 2px 0 rgba(0,0,0,.7)); +} +#gameCanvas { image-rendering: pixelated; } + +/* v27.18: status relocation, consistent industrial controls, card watermarks */ +.hud-top-left { grid-template-columns: repeat(5, minmax(82px, auto)); } + +.left-bottom-status { + position: absolute; + z-index: 6; + left: 10px; + bottom: 10px; + width: min(310px, calc(100% - 20px)); + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; + pointer-events: none; +} +.left-bottom-status > div { + min-width: 0; + border: 3px solid var(--line); + background: rgba(22, 26, 32, .95); + color: var(--ink); + padding: 8px 10px; + box-shadow: 4px 4px 0 rgba(0,0,0,.68), inset 0 0 0 1px rgba(255,184,39,.10); + font-size: 12px; + line-height: 1.2; + font-weight: 900; + text-transform: uppercase; + letter-spacing: .025em; + overflow: hidden; + text-overflow: ellipsis; +} +.left-bottom-status .event-brief { grid-column: 1 / -1; white-space: normal; min-height: 39px; } +.left-bottom-status .event-brief.active { background: #35221c; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.68); } +.left-bottom-status .event-brief.next { background: #22301f; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.68); } +.left-bottom-status .event-brief.locked { background: #1c2027; color: var(--muted); } +.left-bottom-status .speed-brief { color: #d9e2e8; } +.left-bottom-status .target-brief { color: #ffcf68; } +.left-bottom-status .combo-brief { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; } +.left-bottom-status .combo-brief span { color: var(--muted); font-size: 10px; } +.left-bottom-status .combo-brief strong { color: var(--green); font-size: 22px; line-height: 1; } + +/* Remove the remaining bright green/white control styling from modal actions. */ +.modal-actions button, +.facility-action, +.card-target-button { + border: 3px solid #07080a; + background: linear-gradient(#353d48, #1b1f25); + color: #e6edf2; + box-shadow: inset 0 0 0 1px rgba(255,184,39,.14), 4px 4px 0 rgba(0,0,0,.68); +} +.modal-actions button:hover:not(:disabled), +.facility-action:hover:not(:disabled), +.card-target-button:hover:not(:disabled) { + background: linear-gradient(#424b58, #242930); + color: #fff0c9; + box-shadow: inset 0 0 0 2px rgba(255,184,39,.42), 4px 4px 0 rgba(0,0,0,.72); +} +.facility-action.warn, +.modal-actions .reroll-button { + background: linear-gradient(#554221, #2b2419); + color: #ffd36a; + box-shadow: inset 0 0 0 3px #b97810, 5px 5px 0 rgba(0,0,0,.72); +} +.modal-actions .reroll-button:hover:not(:disabled) { + background: linear-gradient(#6b5227, #342919); + color: #fff0bd; + box-shadow: inset 0 0 0 3px #ffb827, 5px 5px 0 rgba(0,0,0,.76); +} +.facility-action.good { background: linear-gradient(#29422a, #19271a); color: #a9ed91; } +.facility-action.danger { background: linear-gradient(#57251f, #2d1715); color: #ffb1a3; } +.modal-actions button:disabled, +.facility-action:disabled, +.card-target-button:disabled { opacity: .42; filter: grayscale(.85); box-shadow: 3px 3px 0 rgba(0,0,0,.45); } + +/* Icons are now translucent background art rather than separate foreground badges. */ +.card-choice { + display: block; + min-height: 170px; + padding: 16px; + isolation: isolate; +} +.card-choice::before { z-index: 1; } +.card-copy { position: relative; z-index: 3; padding-right: 6px; } +.card-icon { + position: absolute; + z-index: 0; + right: -9px; + bottom: -12px; + width: 124px; + height: 124px; + border: 0; + background: transparent; + box-shadow: none; + opacity: .14; + transform: rotate(-7deg); + pointer-events: none; + overflow: visible; +} +.card-icon img { + width: 100%; + height: 100%; + object-fit: contain; + filter: grayscale(.12) contrast(1.2) drop-shadow(3px 3px 0 rgba(0,0,0,.55)); +} +.card-icon.glyph { + display: grid; + place-items: center; + color: #f0b437; + font-size: 88px; + line-height: 1; + text-shadow: 4px 4px 0 rgba(0,0,0,.55); +} +.card-choice.rare .card-icon { opacity: .16; } +.card-choice.ultra-rare .card-icon { opacity: .17; } +.card-choice.dud .card-icon { opacity: .08; filter: grayscale(1); } + +@media (max-width: 1180px) { + .hud-top-left { grid-template-columns: repeat(3, minmax(80px, 1fr)); } + .left-bottom-status { width: 290px; left: 8px; bottom: 8px; } +} +@media (max-width: 760px) { + .left-bottom-status { width: min(270px, calc(100% - 16px)); grid-template-columns: 1fr; } + .left-bottom-status .event-brief { grid-column: auto; } +} diff --git a/styles-v27.19.css b/styles-v27.19.css new file mode 100644 index 0000000..3ddf905 --- /dev/null +++ b/styles-v27.19.css @@ -0,0 +1,1279 @@ +:root { + --bg: #f2fff0; + --screen: #eefbea; + --panel: rgba(245, 255, 242, 0.96); + --ink: #102015; + --muted: #526456; + --line: #102015; + --green: #22b94f; + --green-soft: #b7f5c6; + --white: #ffffff; + --danger: #c42424; + --shadow: 8px 8px 0 rgba(16, 32, 21, 0.22); +} +* { box-sizing: border-box; } +html, body { min-height: 100%; } +body { margin: 0; background: var(--bg); color: var(--ink); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; overflow-x: hidden; } +button { font: inherit; } +h1, h2, p { margin: 0; } +#app { width: min(100vw, 1680px); margin: 0 auto; padding: 0 8px 12px; } +.game-shell { position: relative; width: 100%; min-height: min(100vh, 920px); border: 4px solid var(--line); border-top: 0; background: var(--screen); overflow: hidden; box-shadow: var(--shadow); } +#gameCanvas { display: block; width: 100%; height: min(calc(100vh - 10px), 900px); min-height: 720px; background: var(--screen); touch-action: none; } +.hud { position: absolute; z-index: 4; display: grid; gap: 6px; pointer-events: none; } +.hud-top-left { top: 10px; left: 10px; grid-template-columns: repeat(6, minmax(82px, auto)); } +.hud-top-right { top: 10px; right: 10px; grid-template-columns: repeat(4, minmax(78px, auto)); } +.hud-card { min-width: 82px; padding: 7px 9px; border: 3px solid var(--line); background: rgba(255,255,255,.88); box-shadow: 4px 4px 0 rgba(16,32,21,.16); } +.hud-card.primary { min-width: 116px; padding: 10px 12px; background: rgba(255,255,255,.96); } +.hud-card.primary span { font-size: 9px; } +.hud-card.primary strong { font-size: clamp(22px, 2vw, 32px); } +.hud-card.time-critical { background: #fff0d1; box-shadow: inset 0 0 0 4px var(--danger), 4px 4px 0 rgba(16,32,21,.16); } +.hud-card span { display: block; font-size: 9px; letter-spacing: .1em; color: var(--muted); margin-bottom: 4px; } +.hud-card strong { font-size: clamp(15px, 1.3vw, 22px); line-height: 1; color: var(--ink); } +.hud-card.cash strong, .hud-card.profit strong, .hud-card.combo strong, .cash-positive { color: var(--green) !important; } +.cash-negative { color: var(--danger) !important; } + +.priority-strip { position: absolute; z-index: 5; top: 76px; left: 10px; display: grid; grid-template-columns: minmax(280px, 1.2fr) minmax(170px, .75fr) minmax(130px, .55fr); gap: 8px; max-width: calc(100% - 420px); pointer-events: none; } +.priority-strip > div { border: 3px solid var(--line); background: rgba(255,255,255,.94); padding: 8px 10px; font-weight: 900; text-transform: uppercase; box-shadow: 4px 4px 0 rgba(16,32,21,.14); font-size: 12px; letter-spacing: .03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.event-brief.active { background: #fff0d1; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.14); } +.event-brief.next { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.14); } +.event-brief.locked { background: #edf3ec; color: var(--muted); } +.target-brief { color: var(--green); } +.speed-brief { color: var(--ink); } + +.build-panel { position: absolute; z-index: 6; top: 118px; right: 12px; bottom: 12px; width: clamp(278px, 23vw, 360px); min-height: 0; padding: 10px; border: 4px solid var(--line); background: var(--panel); box-shadow: var(--shadow); overflow: auto; } +.panel-head { display: grid; gap: 8px; margin-bottom: 10px; } +.panel-head h1 { font-size: 15px; letter-spacing: .06em; } +.panel-head h1 span { font-size: 9px; color: var(--white); background: var(--green); border: 2px solid var(--line); padding: 1px 6px; } +.panel-head p { color: var(--muted); margin-top: 4px; font-size: 9px; line-height: 1.25; } +.panel-grid { display: grid; grid-template-columns: 1fr; gap: 10px; } +.build-panel h2 { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; margin-bottom: 7px; } +.large-tools { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; } +.history-tools { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; grid-column: 1 / -1; } +.tool-button.small { min-height: 40px; padding: 6px; } +.tool-button, .primary-button, .sort-button, .facility-action { border: 3px solid var(--line); background: var(--white); color: var(--ink); font-weight: 900; text-transform: uppercase; cursor: pointer; box-shadow: 4px 4px 0 rgba(16,32,21,.18); } +.tool-button { min-height: 50px; text-align: left; padding: 8px; } +.tool-button strong { display: block; font-size: 12px; } +.tool-button span { display: block; margin-top: 4px; font-size: 9px; color: var(--muted); } +.tool-button.active { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.18); } +.tool-button.danger.active { background: #ffdada; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.18); } +.primary-button { padding: 10px 12px; background: var(--green); color: var(--white); white-space: nowrap; } +.primary-button:disabled, .tool-button:disabled, .sort-button:disabled, .facility-action:disabled { opacity: .42; cursor: not-allowed; } +.mini-box { border: 3px solid var(--line); background: var(--white); padding: 12px; line-height: 1.45; color: var(--muted); font-size: 11px; } +.facility-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; } +.facility-action { padding: 7px 9px; font-size: 9px; } +.facility-action.good { background: var(--green-soft); } +.facility-action.warn { background: #fff0d1; } +.facility-action.danger { background: #ffdada; } +.control-dock { position: absolute; z-index: 7; left: 50%; bottom: 12px; transform: translateX(-50%); display: grid; grid-template-columns: repeat(4, 150px); gap: 8px; padding: 7px; border: 3px solid var(--line); background: rgba(255,255,255,.90); } +.sort-button { min-height: 46px; font-size: 12px; } +/* Debug UI is intentionally kept for active balancing builds. Do not remove during cleanup/audit passes unless explicitly requested. */ +.debug-panel { + position: absolute; + z-index: 9; + left: 10px; + bottom: 10px; + width: min(410px, calc(100% - 20px)); + border: 3px solid var(--line); + background: rgba(255,255,255,.96); + box-shadow: 4px 4px 0 rgba(16,32,21,.16); + font-weight: 900; +} +.debug-panel summary { + cursor: pointer; + padding: 5px 8px; + color: var(--danger); + font-size: 14px; + line-height: 1.1; +} +.debug-body { + display: grid; + grid-template-columns: 1fr 92px; + gap: 6px; + padding: 7px; + border-top: 3px solid var(--line); + font-size: 12px; + line-height: 1.15; +} +.debug-body label, +.debug-body button, +.debug-body select, +.debug-body input { + min-width: 0; + font: inherit; +} +.debug-check, +.debug-card, +.debug-target, +.debug-readout { + grid-column: 1 / -1; +} +.debug-row { + display: grid; + grid-template-columns: 1fr 92px; + gap: 6px; + grid-column: 1 / -1; +} +.debug-day { + display: grid; + grid-template-columns: 38px 1fr; + align-items: center; + gap: 4px; +} +.debug-body button { + border: 2px solid var(--line); + background: var(--white); + cursor: pointer; + font-weight: 900; + padding: 5px 6px; + line-height: 1.05; +} +.debug-body input[type="number"], +.debug-body select { + width: 100%; + border: 2px solid var(--line); + background: var(--white); + padding: 4px 5px; + min-height: 29px; +} +.debug-target select:disabled { + opacity: .55; +} +.debug-readout { + border: 2px solid var(--line); + background: #f7fff5; + color: var(--muted); + padding: 5px; + line-height: 1.25; + max-height: 64px; + overflow: auto; +} +.modal { position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; padding: 22px; background: rgba(16,32,21,.45); } +.modal.visible { display: flex; } +.modal-card { width: min(860px, 96vw); border: 4px solid var(--line); padding: 24px; background: var(--white); box-shadow: var(--shadow); } +.modal-card h2 { font-size: 26px; text-transform: uppercase; margin-bottom: 12px; } +.modal-card p { line-height: 1.55; } +.modal-card ul { margin: 12px 0 0; padding-left: 22px; line-height: 1.55; color: var(--muted); } +.modal-actions { margin-top: 18px; display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap; } +.route-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 14px 0; } +.route-card { border: 3px solid var(--line); background: #f7fff5; padding: 14px; display: grid; grid-template-columns: 44px 1fr 28px 1fr; align-items: center; gap: 4px 8px; } +.route-card .route-icon { grid-row: 1 / span 2; font-size: 30px; text-align: center; } +.route-card strong, .route-card em { font-style: normal; font-weight: 900; text-transform: uppercase; } +.route-card b { font-size: 24px; color: var(--green); text-align: center; } +.route-card small { grid-column: 2 / span 3; color: var(--muted); font-weight: 900; } +.result-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 12px; } +.result-grid div { border: 3px solid var(--line); padding: 10px; background: #f7fff5; } +.result-grid strong { display: block; font-size: 11px; color: var(--muted); text-transform: uppercase; margin-bottom: 6px; } +.result-grid span { font-size: 16px; font-weight: 900; color: var(--ink); } +.game-shell:not(.phase-build) .build-panel { display: none; } +.game-shell.phase-running .hud-top-right { display: none; } +.game-shell:not(.phase-running) .control-dock { display: none; } +@media (max-width: 1180px) { + #app { padding: 0; } + .game-shell { min-height: 100vh; } + #gameCanvas { height: 100vh; } + .hud-top-left, .hud-top-right { grid-template-columns: repeat(2, minmax(76px, auto)); } + .priority-strip { top: 150px; left: 8px; right: 8px; max-width: none; grid-template-columns: 1fr; } + .build-panel { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 42vh; } + .large-tools { grid-template-columns: 1fr 1fr; } + .control-dock { grid-template-columns: repeat(2, 150px); } + .route-cards, .result-grid { grid-template-columns: 1fr; } +} + +.event-card { border: 3px solid var(--line); background: #f7fff5; padding: 12px; line-height: 1.35; color: var(--ink); font-size: 11px; box-shadow: 4px 4px 0 rgba(16,32,21,.14); } +.event-card.empty { color: var(--muted); background: rgba(255,255,255,.72); } +.event-card.empty strong { display: block; color: var(--ink); margin-bottom: 4px; } +.event-card h3 { margin: 2px 0 7px; font-size: 14px; text-transform: uppercase; letter-spacing: .04em; } +.event-card p { margin: 5px 0; } +.event-card.accepted { background: var(--green-soft); box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(16,32,21,.14); } +.event-card.declined { background: #f1f1f1; color: var(--muted); } +.event-status { display: inline-block; padding: 2px 7px; border: 2px solid var(--line); background: var(--white); font-size: 9px; font-weight: 900; letter-spacing: .1em; margin-bottom: 4px; } +.event-metrics { display: grid; grid-template-columns: 1fr; gap: 4px; margin: 8px 0; } +.event-metrics span { display: block; border: 2px solid rgba(16,32,21,.55); background: rgba(255,255,255,.82); padding: 5px; font-weight: 900; color: var(--ink); } +.event-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; } +.result-section-title { margin: 16px 0 8px; font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .12em; color: var(--green); } +.result-section-title:first-child { margin-top: 0; } +.muted-title { color: var(--muted); border: 3px solid var(--line); padding: 10px; background: #f7fff5; } + +.compact-rules .mini-box { padding: 8px; font-size: 9px; } +.primary-button:disabled { filter: grayscale(1); background: #c9d2ca; color: #526456; } +.formula-box { + border: 3px solid var(--line); + background: #f7fff5; + padding: 10px; + margin: 10px 0; + line-height: 1.5; + color: var(--ink); + font-size: 12px; + font-weight: 700; +} +.equipment-menu-lines { + border: 3px solid var(--line); + background: #ffffff; + padding: 10px; + margin: 8px 0; + color: var(--muted); + line-height: 1.45; +} +.equipment-menu-lines p { margin: 4px 0; } + +/* v11 compact clicked-equipment bubble */ +.modal.equipment-popover { + background: transparent; + align-items: flex-start; + justify-content: flex-start; + padding: 0; + pointer-events: none; +} +.modal.equipment-popover .modal-card { + position: absolute; + left: var(--popover-x, 16px); + top: var(--popover-y, 16px); + width: min(250px, calc(100vw - 24px)); + max-height: min(280px, calc(100vh - 24px)); + overflow: auto; + padding: 8px; + border-width: 3px; + pointer-events: auto; + box-shadow: 6px 6px 0 rgba(16,32,21,.18); +} +.modal.equipment-popover .modal-card h2 { + font-size: 14px; + margin-bottom: 6px; +} +.modal.equipment-popover .modal-actions { + margin-top: 8px; + gap: 6px; + justify-content: flex-start; +} +.modal.equipment-popover .modal-actions button { + padding: 5px 7px; + font-size: 9px; +} +.equipment-menu-lines.compact { + padding: 7px; + margin: 6px 0; + font-size: 9px; +} +.formula-box.compact { + padding: 7px; + margin: 6px 0; + font-size: 9px; +} + +/* v15 pre-build card draft */ +.card-choices { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(190px, 220px)); + justify-content: center; + align-items: stretch; + gap: 10px; + margin-top: 14px; +} +.card-choice { + min-height: 132px; + border: 3px solid var(--line); + background: #f7fff5; + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.16); + padding: 12px; + text-align: left; + cursor: pointer; + font-weight: 900; +} +.card-choice:hover { transform: translate(-1px, -1px); box-shadow: 6px 6px 0 rgba(16,32,21,.18); } +.card-choice strong { display: block; font-size: 14px; text-transform: uppercase; line-height: 1.2; } +.card-choice span { display: inline-block; margin: 8px 0; padding: 2px 7px; border: 2px solid var(--line); background: var(--white); font-size: 9px; letter-spacing: .1em; } +.card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin: 7px 0; } +.card-tags span { margin: 0; padding: 2px 5px; font-size: 8px; line-height: 1.1; letter-spacing: .04em; } +.card-choice small { display: block; color: var(--muted); font-size: 11px; line-height: 1.35; } +.card-choice.rare { background: #fff0d1; box-shadow: inset 0 0 0 3px #f0a020, 5px 5px 0 rgba(16,32,21,.16); } +.card-choice.ultra-rare { background: #ffe6f0; box-shadow: inset 0 0 0 3px #c42424, 5px 5px 0 rgba(16,32,21,.18); } +.card-choice.ultra-rare span { background: #c42424; color: #fff; } +.muted-card-note { color: var(--muted); font-weight: 700; } +.card-targets { display: grid; gap: 8px; margin-top: 14px; } +.card-target-button { border: 3px solid var(--line); background: #f7fff5; padding: 10px 12px; text-align: left; cursor: pointer; font-weight: 900; box-shadow: 4px 4px 0 rgba(16,32,21,.14); } +.card-target-button:hover { background: var(--green-soft); } + +/* v19 readability pass */ +body { font-size: 16px; } +.hud-card span { font-size: 11px; } +.hud-card strong { font-size: clamp(18px, 1.5vw, 25px); } +.priority-strip > div { font-size: 14px; } +.panel-head h1 { font-size: 18px; } +.panel-head p { font-size: 11px; } +.build-panel h2 { font-size: 13px; } +.tool-button strong { font-size: 14px; } +.tool-button span { font-size: 11px; } +.mini-box, .event-card { font-size: 12px; } +.sort-button { font-size: 14px; } +.modal-card h2 { font-size: 29px; } +.card-choice strong { font-size: 16px; } +.card-choice small { font-size: 13px; } + +.tool-button.unaffordable, .tool-button.already-built { opacity: .42; filter: grayscale(.7); } + +.hover-tooltip { + position: fixed; + z-index: 30; + width: min(320px, calc(100vw - 20px)); + display: none; + border: 3px solid var(--line); + background: rgba(255,255,255,.96); + color: var(--ink); + box-shadow: 6px 6px 0 rgba(16,32,21,.18); + padding: 10px; + pointer-events: none; + line-height: 1.35; +} +.hover-tooltip.visible { display: block; } +.hover-tooltip strong { display: block; font-size: 15px; text-transform: uppercase; margin-bottom: 5px; } +.hover-tooltip em { display: block; font-style: normal; color: var(--green); font-weight: 900; margin-bottom: 7px; } +.hover-tooltip em.warning { color: var(--danger); } +.hover-tooltip span { display: block; color: var(--muted); font-size: 12px; } + + +.card-choice.dud { + background: #eeeeee; + color: #777; + filter: grayscale(1); + border-style: dashed; + box-shadow: 5px 5px 0 rgba(16,32,21,.10); +} +.card-choice.dud span { background: #f8f8f8; } +.card-choice.flung { + pointer-events: none; + transform: translate(var(--fling-x, 480px), var(--fling-y, -320px)) rotate(var(--fling-r, 68deg)) scale(.68); + opacity: 0; + transition: transform .34s cubic-bezier(.18,.84,.26,.99), opacity .28s ease-in; +} + + + +.route-card .route-icon.male, +.route-card .route-icon.female, +.route-card .route-icon.poop { + display: inline-grid; + place-items: center; + width: 38px; + height: 38px; + border-radius: 999px; + border: 3px solid var(--line, #102015); + background: var(--white, #fff); + line-height: 1; +} +.route-card .route-icon.male { color: #2477ff; background: #d9ecff; } +.route-card .route-icon.female { color: #d62a85; background: #ffe0f0; } +.route-card .route-icon.poop { color: #7b4a23; background: #fff0d1; font-size: 24px; } +.restart-button { min-width: 160px; } +.restart-fallback-note { margin-top: 12px; color: var(--muted, #526456); font-weight: 700; } + +/* v24.4 hover-only build-button flavor / cashout guidance / compact game-over */ +.tool-button .tool-flavor { + display: block; + max-height: 0; + opacity: 0; + overflow: hidden; + margin-top: 0; + color: var(--muted); + font-size: 8px; + line-height: 1.22; + text-transform: none; + letter-spacing: 0; + transition: max-height .12s ease, opacity .12s ease, margin-top .12s ease; +} +.tool-button:hover .tool-flavor { + max-height: 42px; + opacity: 1; + margin-top: 5px; +} +.large-tools .tool-button { min-height: 58px; } +.large-tools .tool-button:hover { min-height: 78px; } +.history-tools .tool-button.small { min-height: 40px; } +.primary-button.cashout-emphasis, +.tool-button.cashout-emphasis { + opacity: 1 !important; + filter: none !important; + animation: cashoutPulse 0.9s ease-in-out infinite alternate; +} +.primary-button.cashout-emphasis { + box-shadow: inset 0 0 0 4px #fff0d1, 6px 6px 0 rgba(16,32,21,.22); +} +.tool-button.cashout-emphasis { + background: #fff0d1; + box-shadow: inset 0 0 0 3px var(--danger), 6px 6px 0 rgba(16,32,21,.20); +} +@keyframes cashoutPulse { + from { transform: translate(0, 0); } + to { transform: translate(-1px, -1px); } +} +.modal.gameover-modal { padding: 12px; } +.modal.gameover-modal .modal-card { + width: min(640px, 92vw); + max-height: min(82vh, 720px); + overflow: auto; + padding: 16px; +} +.modal.gameover-modal .modal-card h2 { + font-size: 22px; + margin-bottom: 8px; +} +.gameover-reason { font-weight: 900; color: var(--danger); margin-bottom: 8px; } +.settlement-net { + border: 3px solid var(--line); + background: #f7fff5; + padding: 10px 12px; + margin-bottom: 10px; + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + font-weight: 900; + text-transform: uppercase; +} +.settlement-net strong { font-size: 24px; } +.settlement-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; } +.settlement-grid div { padding: 8px; } +.settlement-grid span { display: block; font-size: 14px; } +.gameover-summary { + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 6px; + margin-top: 8px; +} +.gameover-breakdown { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 6px; + margin-top: 8px; +} +.modal.gameover-modal .result-grid div { padding: 7px; } +.modal.gameover-modal .result-grid strong { font-size: 9px; margin-bottom: 3px; } +.modal.gameover-modal .result-grid span { font-size: 12px; } +.gameover-details { + margin-top: 10px; + border: 3px solid var(--line); + background: #f7fff5; + padding: 8px; +} +.gameover-details summary { + cursor: pointer; + font-weight: 900; + text-transform: uppercase; +} +.modal.gameover-modal .formula-box.compact { font-size: 9px; line-height: 1.35; } +@media (max-width: 720px) { + .gameover-summary, .gameover-breakdown { grid-template-columns: 1fr 1fr; } +} + +/* v27.0 cleanup and stable build-menu tooltip pass */ +body { font-size: 18px; } +.build-panel { width: clamp(330px, 26vw, 420px); } +.panel-head h1 { font-size: 20px; } +.panel-head h1 span { font-size: 12px; } +.panel-head p { font-size: 13px; line-height: 1.35; } +.build-panel h2 { font-size: 14px; } +.priority-strip > div { font-size: 15px; } +.hud-card span { font-size: 12px; } +.hud-card strong { font-size: clamp(20px, 1.7vw, 28px); } +.mini-box, .event-card { font-size: 14px; line-height: 1.45; } +.compact-rules .mini-box { font-size: 13px; } +.tool-button { + position: relative; + overflow: visible; + min-height: 62px; + padding: 10px; +} +.large-tools .tool-button { min-height: 62px; } +.large-tools .tool-button:hover { min-height: 62px; } +.tool-button strong { font-size: 15px; line-height: 1.15; } +.tool-button span { font-size: 12px; } +.tool-button .tool-flavor { + display: none; + position: absolute; + z-index: 60; + left: 0; + top: calc(100% + 7px); + width: min(300px, calc(100vw - 40px)); + max-height: none; + opacity: 1; + overflow: visible; + margin: 0; + padding: 10px 12px; + border: 3px solid var(--line); + background: rgba(255,255,255,.98); + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + font-size: 13px; + line-height: 1.35; + text-transform: none; + letter-spacing: 0; + pointer-events: none; + transition: none; +} +.tool-button .tool-flavor::before { + content: ''; + position: absolute; + left: 16px; + top: -10px; + width: 16px; + height: 16px; + border-left: 3px solid var(--line); + border-top: 3px solid var(--line); + background: rgba(255,255,255,.98); + transform: rotate(45deg); +} +.tool-button:hover .tool-flavor { + display: block; + max-height: none; + opacity: 1; + margin: 0; +} +.primary-button { font-size: 16px; padding: 13px 16px; } +#nextTurnButton { min-height: 56px; font-size: 18px; } +@keyframes cashoutPulse { + from { box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(16,32,21,.18); filter: brightness(1); } + to { box-shadow: inset 0 0 0 5px #fff0d1, 4px 4px 0 rgba(16,32,21,.20); filter: brightness(1.08); } +} +.card-choices { grid-template-columns: repeat(auto-fill, minmax(230px, 270px)); gap: 14px; } +.card-choice { min-height: 164px; padding: 15px; } +.card-choice strong { font-size: 18px; } +.card-choice span { font-size: 11px; } +.card-choice small { font-size: 15px; line-height: 1.4; } +.muted-card-note { font-size: 15px; line-height: 1.45; } +.modal-card { width: min(980px, 96vw); } +.modal-card p, .modal-card li { font-size: 16px; } +.modal-actions .reroll-button { + order: 99; + flex: 1 1 100%; + min-height: 64px; + margin-top: 8px; + font-size: 20px; + text-align: center; + justify-content: center; + background: #fff0d1; + box-shadow: inset 0 0 0 4px var(--green), 6px 6px 0 rgba(16,32,21,.20); +} +.modal-actions .reroll-button:disabled { box-shadow: 4px 4px 0 rgba(16,32,21,.12); } +.hover-tooltip strong { font-size: 17px; } +.hover-tooltip span { font-size: 14px; } +.sort-button { font-size: 16px; min-height: 56px; } +.control-dock { grid-template-columns: repeat(4, 172px); } +@media (max-width: 1180px) { + .build-panel { width: auto; } + .control-dock { grid-template-columns: repeat(2, 172px); } +} + +/* v27.1 expansion/readability pass */ +body { font-size: 20px; } +.panel-head h1 { font-size: 22px; } +.panel-head h1 span { font-size: 13px; } +.panel-head p { font-size: 14px; line-height: 1.35; } +.build-panel h2 { font-size: 15px; } +.priority-strip > div { font-size: 16px; } +.hud-card span { font-size: 13px; } +.hud-card strong { font-size: clamp(22px, 1.8vw, 30px); } +.mini-box, .event-card { font-size: 15px; line-height: 1.5; } +.compact-rules .mini-box { font-size: 14px; } +.tool-button strong { font-size: 16px; line-height: 1.15; } +.tool-button span { font-size: 13px; line-height: 1.2; } +.tool-button .tool-flavor { + left: auto; + right: 0; + width: min(320px, calc(100vw - 40px)); + font-size: 14px; + line-height: 1.4; + overflow-wrap: anywhere; +} +.tool-button .tool-flavor::before { left: auto; right: 18px; } +.tool-button.unaffordable .tool-flavor, +.tool-button.unaffordable:hover .tool-flavor, +.tool-button:disabled .tool-flavor, +.tool-button:disabled:hover .tool-flavor { display: none; } +.facility-action { font-size: 12px; } +.primary-button { font-size: 17px; } +#nextTurnButton { font-size: 19px; } +.card-choice strong { font-size: 19px; } +.card-choice span { font-size: 12px; } +.card-choice small { font-size: 16px; line-height: 1.45; } +.muted-card-note { font-size: 16px; } +.modal-card p, .modal-card li { font-size: 17px; } +.modal.equipment-popover .modal-card h2 { font-size: 16px; } +.modal.equipment-popover .modal-actions button { font-size: 11px; } +.equipment-menu-lines.compact, .formula-box.compact { font-size: 11px; } +.hover-tooltip strong { font-size: 18px; } + +/* Keep construction flavor text readable as a hover bubble, not button content. */ +.large-tools .tool-button { + min-height: 62px; + position: relative; + overflow: visible; +} +.large-tools .tool-button:hover { + min-height: 62px; +} +.large-tools .tool-button .tool-flavor { + display: none; + position: absolute; + z-index: 90; + right: 0; + top: calc(100% + 8px); + width: min(320px, calc(100vw - 40px)); + max-height: none; + opacity: 1; + overflow: visible; + margin: 0; + padding: 10px 12px; + border: 3px solid var(--line); + background: rgba(255,255,255,.98); + color: var(--ink); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + font-size: 14px; + line-height: 1.35; + pointer-events: none; + overflow-wrap: anywhere; +} +.large-tools .tool-button:hover .tool-flavor { + display: block; +} +.large-tools .tool-button .tool-flavor::before { + content: ''; + position: absolute; + right: 18px; + top: -10px; + width: 16px; + height: 16px; + border-left: 3px solid var(--line); + border-top: 3px solid var(--line); + background: rgba(255,255,255,.98); + transform: rotate(45deg); +} +.hover-tooltip span { font-size: 15px; } +.sort-button { font-size: 17px; } + +/* v27.3 offscreen scanner monitor / expansion UI pass */ +.scanner-monitor { + position: absolute; + z-index: 8; + left: 12px; + bottom: 92px; + display: none; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 8px; + width: min(560px, calc(100% - 24px)); + pointer-events: auto; +} +.scanner-monitor.visible { display: grid; } +.scanner-monitor-card { + border: 3px solid var(--line); + background: rgba(255,255,255,.95); + box-shadow: 5px 5px 0 rgba(16,32,21,.18); + padding: 9px; + font-weight: 900; +} +.scanner-monitor-card header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin-bottom: 7px; + text-transform: uppercase; +} +.scanner-monitor-card header strong { font-size: 20px; color: var(--green); } +.scanner-monitor-card header span { font-size: 12px; color: var(--muted); } +.scanner-mini-map { + display: grid; + grid-template-columns: 42px 1fr 82px; + align-items: center; + gap: 6px; + margin-bottom: 8px; +} +.scanner-mini-map > span, +.scanner-mini-map > b { + border: 2px solid var(--line); + background: #f7fff5; + padding: 7px 6px; + text-align: center; + font-size: 13px; + min-height: 36px; +} +.scanner-current { display: block; color: var(--ink); } +.scanner-current.male { color: #2477ff; } +.scanner-current.female { color: #d62a85; } +.scanner-current.poop { color: #7b4a23; } +.scanner-current.empty { color: var(--muted); } + +.scanner-mini-grid { + display: grid; + grid-template-columns: repeat(5, 27px); + gap: 3px; + justify-content: center; + align-items: center; + padding: 6px; + margin: 0 0 8px; + border: 2px solid var(--line); + background: #f6f1df; +} +.scanner-mini-grid .mini-cell { + width: 27px; + height: 27px; + display: grid; + place-items: center; + border: 1px solid rgba(22,38,25,.28); + background: #fffdfa; + color: var(--muted); + font-size: 11px; + font-weight: 900; + line-height: 1; +} +.scanner-mini-grid .mini-cell.belt { background: #e7f7e4; color: var(--green-dark); } +.scanner-mini-grid .mini-cell.input { background: #fff3bf; color: var(--ink); font-size: 9px; } +.scanner-mini-grid .mini-cell.scanner { background: var(--green); color: #fff; border-color: var(--line); font-size: 16px; } +.scanner-mini-grid .mini-cell.scanner.male { background: #2477ff; } +.scanner-mini-grid .mini-cell.scanner.female { background: #d62a85; } +.scanner-mini-grid .mini-cell.scanner.poop { background: #7b4a23; } +.scanner-mini-grid .mini-cell.scanner-other { background: #b7f5c6; color: var(--ink); } +.scanner-mini-grid .mini-cell.egg { background: #fff7c4; color: #7a5a00; } +.scanner-mini-grid .mini-cell.port { background: #dbe7ff; color: #27427d; } +.scanner-mini-grid .mini-cell.blocked { background: #d7cfc1; color: #6d4d35; } + +.scanner-monitor-actions { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 7px; +} +.scanner-monitor-actions button { + border: 3px solid var(--line); + background: var(--green-soft); + color: var(--ink); + cursor: pointer; + font: inherit; + font-size: 14px; + font-weight: 900; + min-height: 44px; + box-shadow: 3px 3px 0 rgba(16,32,21,.18); +} +.scanner-monitor-actions button:disabled { + background: #edf3ec; + color: var(--muted); + opacity: .62; + cursor: not-allowed; +} +@media (max-width: 1180px) { + .scanner-monitor { bottom: 132px; width: min(520px, calc(100% - 16px)); left: 8px; } +} + +/* ------------------------------------------------------------------ + DARK FACTORY VISUAL PASS + - Facility sprites are now loaded from assets/dark_factory/. + - Debug UI is intentionally retained for balancing builds. Do not remove. + ------------------------------------------------------------------ */ +:root { + --bg: #0b0c0f; + --screen: #111318; + --panel: rgba(24, 27, 34, 0.96); + --panel-2: #20242b; + --panel-3: #2a303a; + --ink: #e6edf2; + --muted: #8f9bab; + --line: #050609; + --green: #7bd84f; + --green-soft: #273c24; + --white: #e6edf2; + --danger: #e34a36; + --warn: #ffb827; + --cyan: #4aa3ff; + --orange: #c86a2b; + --shadow: 6px 6px 0 rgba(0, 0, 0, 0.62); +} +html, body { background: #050609; color: var(--ink); } +body { + background: + linear-gradient(90deg, rgba(255,184,39,.035) 1px, transparent 1px) 0 0 / 32px 32px, + linear-gradient(rgba(255,184,39,.028) 1px, transparent 1px) 0 0 / 32px 32px, + #050609; +} +#app { width: min(100vw, 1720px); padding: 0; } +.game-shell { + min-height: 100vh; + border: 0; + background: var(--screen); + box-shadow: inset 0 0 0 4px #050609, inset 0 0 0 8px #303744; +} +#gameCanvas { + height: 100vh; + min-height: 720px; + background: var(--screen); + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.hud { gap: 4px; } +.hud-top-left { + top: 8px; + left: 8px; + right: 420px; + grid-template-columns: 1.25fr repeat(5, minmax(92px, .65fr)); +} +.hud-top-right { + top: 8px; + right: 8px; + grid-template-columns: repeat(4, minmax(74px, auto)); +} +.hud-card { + min-width: 74px; + padding: 7px 9px; + border: 3px solid var(--line); + background: linear-gradient(#242a33, #171a20); + box-shadow: 4px 4px 0 rgba(0,0,0,.7), inset 0 0 0 2px rgba(255,184,39,.10); + color: var(--ink); +} +.hud-card span { color: var(--warn); font-size: 9px; letter-spacing: .12em; } +.hud-card strong { color: var(--ink); text-shadow: 2px 2px 0 #050609; } +.hud-card.cash strong, .hud-card.profit strong, .hud-card.combo strong, .cash-positive { color: var(--green) !important; } +.hud-card.time-critical { background: #3a1f1f; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.7); } +.priority-strip { + top: 74px; + left: 10px; + width: clamp(250px, 21vw, 330px); + max-width: none; + grid-template-columns: 1fr; + gap: 6px; +} +.priority-strip > div { + border: 3px solid var(--line); + background: linear-gradient(#222832, #15181e); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.12); +} +.event-brief.active { background: #38251a; box-shadow: inset 0 0 0 3px var(--orange), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.next { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.locked { background: #181b20; color: var(--muted); } +.target-brief { color: var(--warn); } +.speed-brief { color: var(--cyan); } +.build-panel { + top: 82px; + right: 8px; + bottom: 8px; + width: clamp(320px, 24vw, 410px); + padding: 9px; + border: 4px solid var(--line); + background: linear-gradient(#222832, #14171d); + box-shadow: 6px 6px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.10); + scrollbar-color: var(--warn) #111318; +} +.panel-head { + display: grid; + grid-template-columns: 1fr 126px; + align-items: stretch; + gap: 8px; + margin-bottom: 8px; +} +.panel-head h1 { color: var(--warn); text-shadow: 2px 2px 0 #050609; font-size: 17px; } +.panel-head h1 span { color: #050609; background: var(--warn); border-color: var(--line); } +.panel-head p { color: var(--muted); } +.panel-grid { + display: grid; + grid-template-columns: 1fr; + gap: 8px; +} +.build-panel h2, .result-section-title { color: var(--warn); } +.large-tools { + grid-template-columns: 1fr 1fr; + gap: 6px; +} +.tool-button, .primary-button, .sort-button, .facility-action { + border: 3px solid var(--line); + background: linear-gradient(#2a303a, #171a20); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.70), inset 0 0 0 2px rgba(255,184,39,.08); + text-shadow: 1px 1px 0 #050609; +} +.tool-button { min-height: 48px; padding: 8px; } +.tool-button strong { color: var(--ink); } +.tool-button span { color: var(--muted); } +.tool-button.active { + background: linear-gradient(#33311d, #1e2117); + box-shadow: inset 0 0 0 3px var(--warn), 4px 4px 0 rgba(0,0,0,.70); +} +.tool-button.danger.active { background: linear-gradient(#4b1f1c, #241014); box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.70); } +.primary-button { background: linear-gradient(#8b2d23, #4b1714); color: #fff3d2; } +.primary-button:not(:disabled) { box-shadow: inset 0 0 0 3px #ffb827, 5px 5px 0 rgba(0,0,0,.72); } +.primary-button:disabled, .tool-button:disabled, .sort-button:disabled, .facility-action:disabled { opacity: .42; filter: grayscale(1); } +.mini-box, .event-card, .formula-box, .equipment-menu-lines, .route-card, .result-grid div, .muted-title { + border: 3px solid var(--line); + background: #15181e; + color: var(--muted); + box-shadow: inset 0 0 0 2px rgba(255,184,39,.08); +} +.event-card h3, .event-card strong, .event-metrics span { color: var(--ink); } +.event-card.accepted { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-card.empty { background: #15181e; color: var(--muted); } +.event-metrics span { border-color: #3d4654; background: #20242b; } +.event-status { background: #2a303a; color: var(--warn); border-color: var(--line); } +.control-dock { + left: 50%; + right: auto; + bottom: 8px; + transform: translateX(-50%); + grid-template-columns: repeat(4, minmax(135px, 160px)); + gap: 6px; + padding: 6px; + border: 4px solid var(--line); + background: rgba(13,15,19,.96); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(255,184,39,.10); +} +.sort-button { min-height: 44px; font-size: 12px; } +.scanner-monitor { + position: absolute; + z-index: 5; + left: 10px; + top: 198px; + width: clamp(250px, 21vw, 330px); +} +.scanner-monitor-card { + border: 3px solid var(--line) !important; + background: linear-gradient(#222832, #15181e) !important; + color: var(--ink) !important; + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.10) !important; +} +.scanner-monitor-card strong { color: var(--warn); } +.debug-panel { + left: auto; + right: 12px; + bottom: 10px; + width: min(420px, calc(100% - 24px)); + border-color: var(--line); + background: rgba(16,18,23,.97); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(227,74,54,.18); + color: var(--ink); +} +.debug-panel summary { color: var(--danger); } +.debug-body { border-top-color: var(--line); } +.debug-body button, .debug-body input[type="number"], .debug-body select, .debug-readout { + border-color: var(--line); + background: #20242b; + color: var(--ink); +} +.debug-readout { color: var(--muted); } +.modal { background: rgba(3,4,6,.72); } +.modal-card { + border-color: var(--line); + background: linear-gradient(#242a33, #15181e); + color: var(--ink); + box-shadow: 8px 8px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.12); +} +.modal-card h2 { color: var(--warn); text-shadow: 2px 2px 0 #050609; } +.modal-card ul, .modal-card p { color: var(--muted); } +.hover-tooltip { + border-color: var(--line) !important; + background: rgba(20,23,29,.98) !important; + color: var(--ink) !important; + box-shadow: 5px 5px 0 rgba(0,0,0,.72) !important; +} +::-webkit-scrollbar { width: 14px; height: 14px; } +::-webkit-scrollbar-track { background: #111318; } +::-webkit-scrollbar-thumb { background: #333b48; border: 3px solid #111318; } +::-webkit-scrollbar-thumb:hover { background: #ffb827; } +@media (max-width: 1180px) { + .hud-top-left { right: 8px; grid-template-columns: repeat(3, minmax(80px, 1fr)); } + .hud-top-right { top: 132px; left: 8px; right: auto; grid-template-columns: repeat(2, minmax(82px, auto)); } + .priority-strip { top: 226px; } + .scanner-monitor { top: 348px; } + .build-panel { left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 46vh; } + .control-dock { grid-template-columns: repeat(2, 150px); } +} + +/* v27.16: compact collapsed debug panel + icon card layout */ +.debug-panel:not([open]) { + width: 104px !important; + min-width: 0; + overflow: hidden; +} +.debug-panel:not([open]) summary { + display: block; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.debug-panel[open] { + width: min(420px, calc(100% - 24px)); +} + +.card-choice { + position: relative; + display: grid; + grid-template-columns: 54px minmax(0, 1fr); + gap: 10px; + align-items: start; + min-height: 150px; + overflow: hidden; + background: + linear-gradient(135deg, rgba(255,255,255,.08), rgba(0,0,0,.20)), + #20242b; + border-color: var(--line); +} +.card-choice::before { + content: ""; + position: absolute; + inset: 5px; + border: 1px solid rgba(255,184,39,.18); + pointer-events: none; +} +.card-icon { + position: relative; + z-index: 1; + width: 46px; + height: 46px; + display: grid; + place-items: center; + border: 3px solid var(--line); + background: #15181e; + box-shadow: inset 0 0 0 2px rgba(255,184,39,.10), 3px 3px 0 rgba(0,0,0,.35); + image-rendering: pixelated; +} +.card-icon img { + width: 36px; + height: 36px; + object-fit: contain; + image-rendering: pixelated; +} +.card-icon.glyph { + color: var(--warn, #ffb827); + font-size: 24px; + font-weight: 900; + text-align: center; + line-height: 1; +} +.card-copy { + position: relative; + z-index: 1; + min-width: 0; +} +.card-choice strong { + color: var(--warn, #ffb827); + text-shadow: 1px 1px 0 #050609; +} +.card-choice small { color: var(--muted); } +.card-tags span { + background: #15181e; + color: var(--white); + border-color: var(--line); +} +.card-choice.common { background: linear-gradient(145deg, #262c35, #171a20); } +.card-choice.rare { + background: linear-gradient(145deg, #3b3020, #191b20); + box-shadow: inset 0 0 0 3px #f0a020, 5px 5px 0 rgba(0,0,0,.50); +} +.card-choice.ultra-rare { + background: linear-gradient(145deg, #401d2a, #171a20); + box-shadow: inset 0 0 0 3px #c42424, 5px 5px 0 rgba(0,0,0,.55); +} +.card-choice.dud { + background: linear-gradient(145deg, #2b2b2b, #191919); + color: #878787; +} +.card-choice.dud .card-tags span { background: #222; color: #aaa; } + +@media (max-width: 1180px) { + .debug-panel:not([open]) { + width: 92px !important; + right: 8px; + bottom: 8px; + } +} + + +/* v27.18 inherited cache-proof identity and final UI overrides */ +.build-stamp { + position: absolute; + z-index: 12; + right: 14px; + top: 76px; + padding: 5px 9px; + border: 2px solid #ffb827; + background: rgba(14, 17, 22, .94); + color: #80e067; + box-shadow: 3px 3px 0 rgba(0,0,0,.7); + font: 900 11px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + letter-spacing: .04em; + pointer-events: none; +} +.debug-panel:not([open]) { + width: 58px !important; + max-width: 58px !important; + height: 30px; + min-height: 0; +} +.debug-panel:not([open]) summary { + box-sizing: border-box; + width: 58px; + height: 27px; + padding: 5px 7px; + text-align: center; + overflow: hidden; + text-overflow: clip; +} +.debug-panel[open] { + width: min(390px, calc(100% - 24px)) !important; + height: auto; +} +.card-choice { + border-width: 3px; + box-shadow: 4px 4px 0 rgba(0,0,0,.55), inset 0 0 0 1px rgba(255,184,39,.14); +} +.card-choice:hover { + transform: translateY(-2px); + box-shadow: 4px 6px 0 rgba(0,0,0,.65), inset 0 0 0 2px rgba(128,224,103,.24); +} +.card-icon img { + image-rendering: pixelated; + filter: drop-shadow(2px 2px 0 rgba(0,0,0,.7)); +} +#gameCanvas { image-rendering: pixelated; } + +/* v27.18: status relocation, consistent industrial controls, card watermarks */ +.hud-top-left { grid-template-columns: repeat(5, minmax(82px, auto)); } + +.left-bottom-status { + position: absolute; + z-index: 6; + left: 10px; + bottom: 10px; + width: min(310px, calc(100% - 20px)); + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; + pointer-events: none; +} +.left-bottom-status > div { + min-width: 0; + border: 3px solid var(--line); + background: rgba(22, 26, 32, .95); + color: var(--ink); + padding: 8px 10px; + box-shadow: 4px 4px 0 rgba(0,0,0,.68), inset 0 0 0 1px rgba(255,184,39,.10); + font-size: 12px; + line-height: 1.2; + font-weight: 900; + text-transform: uppercase; + letter-spacing: .025em; + overflow: hidden; + text-overflow: ellipsis; +} +.left-bottom-status .event-brief { grid-column: 1 / -1; white-space: normal; min-height: 39px; } +.left-bottom-status .event-brief.active { background: #35221c; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.68); } +.left-bottom-status .event-brief.next { background: #22301f; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.68); } +.left-bottom-status .event-brief.locked { background: #1c2027; color: var(--muted); } +.left-bottom-status .speed-brief { color: #d9e2e8; } +.left-bottom-status .target-brief { color: #ffcf68; } +.left-bottom-status .combo-brief { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; } +.left-bottom-status .combo-brief span { color: var(--muted); font-size: 10px; } +.left-bottom-status .combo-brief strong { color: var(--green); font-size: 22px; line-height: 1; } + +/* Remove the remaining bright green/white control styling from modal actions. */ +.modal-actions button, +.facility-action, +.card-target-button { + border: 3px solid #07080a; + background: linear-gradient(#353d48, #1b1f25); + color: #e6edf2; + box-shadow: inset 0 0 0 1px rgba(255,184,39,.14), 4px 4px 0 rgba(0,0,0,.68); +} +.modal-actions button:hover:not(:disabled), +.facility-action:hover:not(:disabled), +.card-target-button:hover:not(:disabled) { + background: linear-gradient(#424b58, #242930); + color: #fff0c9; + box-shadow: inset 0 0 0 2px rgba(255,184,39,.42), 4px 4px 0 rgba(0,0,0,.72); +} +.facility-action.warn, +.modal-actions .reroll-button { + background: linear-gradient(#554221, #2b2419); + color: #ffd36a; + box-shadow: inset 0 0 0 3px #b97810, 5px 5px 0 rgba(0,0,0,.72); +} +.modal-actions .reroll-button:hover:not(:disabled) { + background: linear-gradient(#6b5227, #342919); + color: #fff0bd; + box-shadow: inset 0 0 0 3px #ffb827, 5px 5px 0 rgba(0,0,0,.76); +} +.facility-action.good { background: linear-gradient(#29422a, #19271a); color: #a9ed91; } +.facility-action.danger { background: linear-gradient(#57251f, #2d1715); color: #ffb1a3; } +.modal-actions button:disabled, +.facility-action:disabled, +.card-target-button:disabled { opacity: .42; filter: grayscale(.85); box-shadow: 3px 3px 0 rgba(0,0,0,.45); } + +/* Icons are now translucent background art rather than separate foreground badges. */ +.card-choice { + display: block; + min-height: 170px; + padding: 16px; + isolation: isolate; +} +.card-choice::before { z-index: 1; } +.card-copy { position: relative; z-index: 3; padding-right: 6px; } +.card-icon { + position: absolute; + z-index: 0; + right: -9px; + bottom: -12px; + width: 124px; + height: 124px; + border: 0; + background: transparent; + box-shadow: none; + opacity: .14; + transform: rotate(-7deg); + pointer-events: none; + overflow: visible; +} +.card-icon img { + width: 100%; + height: 100%; + object-fit: contain; + filter: grayscale(.12) contrast(1.2) drop-shadow(3px 3px 0 rgba(0,0,0,.55)); +} +.card-icon.glyph { + display: grid; + place-items: center; + color: #f0b437; + font-size: 88px; + line-height: 1; + text-shadow: 4px 4px 0 rgba(0,0,0,.55); +} +.card-choice.rare .card-icon { opacity: .16; } +.card-choice.ultra-rare .card-icon { opacity: .17; } +.card-choice.dud .card-icon { opacity: .08; filter: grayscale(1); } + +@media (max-width: 1180px) { + .hud-top-left { grid-template-columns: repeat(3, minmax(80px, 1fr)); } + .left-bottom-status { width: 290px; left: 8px; bottom: 8px; } +} +@media (max-width: 760px) { + .left-bottom-status { width: min(270px, calc(100% - 16px)); grid-template-columns: 1fr; } + .left-bottom-status .event-brief { grid-column: auto; } +} + + +/* v27.19: compact Next Day fee label and deduplicated side panel */ +.panel-head { grid-template-columns: minmax(0, 1fr) minmax(112px, 126px); } +.primary-button#nextTurnButton { + min-width: 0; + max-width: 126px; + padding: 8px 7px; + white-space: normal; + overflow: hidden; + line-height: 1.08; + display: grid; + place-content: center; + gap: 4px; + text-align: center; +} +#nextTurnButton .next-day-main { display: block; font-size: 15px; letter-spacing: .035em; } +#nextTurnButton .next-day-fee { + display: block; + max-width: 100%; + color: #ffd36a; + font-size: 9px; + line-height: 1.15; + letter-spacing: 0; + overflow-wrap: anywhere; +} diff --git a/styles.css b/styles.css index 83b96a5..3ddf905 100644 --- a/styles.css +++ b/styles.css @@ -759,3 +759,521 @@ body { font-size: 20px; } @media (max-width: 1180px) { .scanner-monitor { bottom: 132px; width: min(520px, calc(100% - 16px)); left: 8px; } } + +/* ------------------------------------------------------------------ + DARK FACTORY VISUAL PASS + - Facility sprites are now loaded from assets/dark_factory/. + - Debug UI is intentionally retained for balancing builds. Do not remove. + ------------------------------------------------------------------ */ +:root { + --bg: #0b0c0f; + --screen: #111318; + --panel: rgba(24, 27, 34, 0.96); + --panel-2: #20242b; + --panel-3: #2a303a; + --ink: #e6edf2; + --muted: #8f9bab; + --line: #050609; + --green: #7bd84f; + --green-soft: #273c24; + --white: #e6edf2; + --danger: #e34a36; + --warn: #ffb827; + --cyan: #4aa3ff; + --orange: #c86a2b; + --shadow: 6px 6px 0 rgba(0, 0, 0, 0.62); +} +html, body { background: #050609; color: var(--ink); } +body { + background: + linear-gradient(90deg, rgba(255,184,39,.035) 1px, transparent 1px) 0 0 / 32px 32px, + linear-gradient(rgba(255,184,39,.028) 1px, transparent 1px) 0 0 / 32px 32px, + #050609; +} +#app { width: min(100vw, 1720px); padding: 0; } +.game-shell { + min-height: 100vh; + border: 0; + background: var(--screen); + box-shadow: inset 0 0 0 4px #050609, inset 0 0 0 8px #303744; +} +#gameCanvas { + height: 100vh; + min-height: 720px; + background: var(--screen); + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.hud { gap: 4px; } +.hud-top-left { + top: 8px; + left: 8px; + right: 420px; + grid-template-columns: 1.25fr repeat(5, minmax(92px, .65fr)); +} +.hud-top-right { + top: 8px; + right: 8px; + grid-template-columns: repeat(4, minmax(74px, auto)); +} +.hud-card { + min-width: 74px; + padding: 7px 9px; + border: 3px solid var(--line); + background: linear-gradient(#242a33, #171a20); + box-shadow: 4px 4px 0 rgba(0,0,0,.7), inset 0 0 0 2px rgba(255,184,39,.10); + color: var(--ink); +} +.hud-card span { color: var(--warn); font-size: 9px; letter-spacing: .12em; } +.hud-card strong { color: var(--ink); text-shadow: 2px 2px 0 #050609; } +.hud-card.cash strong, .hud-card.profit strong, .hud-card.combo strong, .cash-positive { color: var(--green) !important; } +.hud-card.time-critical { background: #3a1f1f; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.7); } +.priority-strip { + top: 74px; + left: 10px; + width: clamp(250px, 21vw, 330px); + max-width: none; + grid-template-columns: 1fr; + gap: 6px; +} +.priority-strip > div { + border: 3px solid var(--line); + background: linear-gradient(#222832, #15181e); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.12); +} +.event-brief.active { background: #38251a; box-shadow: inset 0 0 0 3px var(--orange), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.next { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-brief.locked { background: #181b20; color: var(--muted); } +.target-brief { color: var(--warn); } +.speed-brief { color: var(--cyan); } +.build-panel { + top: 82px; + right: 8px; + bottom: 8px; + width: clamp(320px, 24vw, 410px); + padding: 9px; + border: 4px solid var(--line); + background: linear-gradient(#222832, #14171d); + box-shadow: 6px 6px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.10); + scrollbar-color: var(--warn) #111318; +} +.panel-head { + display: grid; + grid-template-columns: 1fr 126px; + align-items: stretch; + gap: 8px; + margin-bottom: 8px; +} +.panel-head h1 { color: var(--warn); text-shadow: 2px 2px 0 #050609; font-size: 17px; } +.panel-head h1 span { color: #050609; background: var(--warn); border-color: var(--line); } +.panel-head p { color: var(--muted); } +.panel-grid { + display: grid; + grid-template-columns: 1fr; + gap: 8px; +} +.build-panel h2, .result-section-title { color: var(--warn); } +.large-tools { + grid-template-columns: 1fr 1fr; + gap: 6px; +} +.tool-button, .primary-button, .sort-button, .facility-action { + border: 3px solid var(--line); + background: linear-gradient(#2a303a, #171a20); + color: var(--ink); + box-shadow: 4px 4px 0 rgba(0,0,0,.70), inset 0 0 0 2px rgba(255,184,39,.08); + text-shadow: 1px 1px 0 #050609; +} +.tool-button { min-height: 48px; padding: 8px; } +.tool-button strong { color: var(--ink); } +.tool-button span { color: var(--muted); } +.tool-button.active { + background: linear-gradient(#33311d, #1e2117); + box-shadow: inset 0 0 0 3px var(--warn), 4px 4px 0 rgba(0,0,0,.70); +} +.tool-button.danger.active { background: linear-gradient(#4b1f1c, #241014); box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.70); } +.primary-button { background: linear-gradient(#8b2d23, #4b1714); color: #fff3d2; } +.primary-button:not(:disabled) { box-shadow: inset 0 0 0 3px #ffb827, 5px 5px 0 rgba(0,0,0,.72); } +.primary-button:disabled, .tool-button:disabled, .sort-button:disabled, .facility-action:disabled { opacity: .42; filter: grayscale(1); } +.mini-box, .event-card, .formula-box, .equipment-menu-lines, .route-card, .result-grid div, .muted-title { + border: 3px solid var(--line); + background: #15181e; + color: var(--muted); + box-shadow: inset 0 0 0 2px rgba(255,184,39,.08); +} +.event-card h3, .event-card strong, .event-metrics span { color: var(--ink); } +.event-card.accepted { background: #1c2c20; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.66); } +.event-card.empty { background: #15181e; color: var(--muted); } +.event-metrics span { border-color: #3d4654; background: #20242b; } +.event-status { background: #2a303a; color: var(--warn); border-color: var(--line); } +.control-dock { + left: 50%; + right: auto; + bottom: 8px; + transform: translateX(-50%); + grid-template-columns: repeat(4, minmax(135px, 160px)); + gap: 6px; + padding: 6px; + border: 4px solid var(--line); + background: rgba(13,15,19,.96); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(255,184,39,.10); +} +.sort-button { min-height: 44px; font-size: 12px; } +.scanner-monitor { + position: absolute; + z-index: 5; + left: 10px; + top: 198px; + width: clamp(250px, 21vw, 330px); +} +.scanner-monitor-card { + border: 3px solid var(--line) !important; + background: linear-gradient(#222832, #15181e) !important; + color: var(--ink) !important; + box-shadow: 4px 4px 0 rgba(0,0,0,.66), inset 0 0 0 2px rgba(255,184,39,.10) !important; +} +.scanner-monitor-card strong { color: var(--warn); } +.debug-panel { + left: auto; + right: 12px; + bottom: 10px; + width: min(420px, calc(100% - 24px)); + border-color: var(--line); + background: rgba(16,18,23,.97); + box-shadow: 5px 5px 0 rgba(0,0,0,.72), inset 0 0 0 2px rgba(227,74,54,.18); + color: var(--ink); +} +.debug-panel summary { color: var(--danger); } +.debug-body { border-top-color: var(--line); } +.debug-body button, .debug-body input[type="number"], .debug-body select, .debug-readout { + border-color: var(--line); + background: #20242b; + color: var(--ink); +} +.debug-readout { color: var(--muted); } +.modal { background: rgba(3,4,6,.72); } +.modal-card { + border-color: var(--line); + background: linear-gradient(#242a33, #15181e); + color: var(--ink); + box-shadow: 8px 8px 0 rgba(0,0,0,.72), inset 0 0 0 3px rgba(255,184,39,.12); +} +.modal-card h2 { color: var(--warn); text-shadow: 2px 2px 0 #050609; } +.modal-card ul, .modal-card p { color: var(--muted); } +.hover-tooltip { + border-color: var(--line) !important; + background: rgba(20,23,29,.98) !important; + color: var(--ink) !important; + box-shadow: 5px 5px 0 rgba(0,0,0,.72) !important; +} +::-webkit-scrollbar { width: 14px; height: 14px; } +::-webkit-scrollbar-track { background: #111318; } +::-webkit-scrollbar-thumb { background: #333b48; border: 3px solid #111318; } +::-webkit-scrollbar-thumb:hover { background: #ffb827; } +@media (max-width: 1180px) { + .hud-top-left { right: 8px; grid-template-columns: repeat(3, minmax(80px, 1fr)); } + .hud-top-right { top: 132px; left: 8px; right: auto; grid-template-columns: repeat(2, minmax(82px, auto)); } + .priority-strip { top: 226px; } + .scanner-monitor { top: 348px; } + .build-panel { left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 46vh; } + .control-dock { grid-template-columns: repeat(2, 150px); } +} + +/* v27.16: compact collapsed debug panel + icon card layout */ +.debug-panel:not([open]) { + width: 104px !important; + min-width: 0; + overflow: hidden; +} +.debug-panel:not([open]) summary { + display: block; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.debug-panel[open] { + width: min(420px, calc(100% - 24px)); +} + +.card-choice { + position: relative; + display: grid; + grid-template-columns: 54px minmax(0, 1fr); + gap: 10px; + align-items: start; + min-height: 150px; + overflow: hidden; + background: + linear-gradient(135deg, rgba(255,255,255,.08), rgba(0,0,0,.20)), + #20242b; + border-color: var(--line); +} +.card-choice::before { + content: ""; + position: absolute; + inset: 5px; + border: 1px solid rgba(255,184,39,.18); + pointer-events: none; +} +.card-icon { + position: relative; + z-index: 1; + width: 46px; + height: 46px; + display: grid; + place-items: center; + border: 3px solid var(--line); + background: #15181e; + box-shadow: inset 0 0 0 2px rgba(255,184,39,.10), 3px 3px 0 rgba(0,0,0,.35); + image-rendering: pixelated; +} +.card-icon img { + width: 36px; + height: 36px; + object-fit: contain; + image-rendering: pixelated; +} +.card-icon.glyph { + color: var(--warn, #ffb827); + font-size: 24px; + font-weight: 900; + text-align: center; + line-height: 1; +} +.card-copy { + position: relative; + z-index: 1; + min-width: 0; +} +.card-choice strong { + color: var(--warn, #ffb827); + text-shadow: 1px 1px 0 #050609; +} +.card-choice small { color: var(--muted); } +.card-tags span { + background: #15181e; + color: var(--white); + border-color: var(--line); +} +.card-choice.common { background: linear-gradient(145deg, #262c35, #171a20); } +.card-choice.rare { + background: linear-gradient(145deg, #3b3020, #191b20); + box-shadow: inset 0 0 0 3px #f0a020, 5px 5px 0 rgba(0,0,0,.50); +} +.card-choice.ultra-rare { + background: linear-gradient(145deg, #401d2a, #171a20); + box-shadow: inset 0 0 0 3px #c42424, 5px 5px 0 rgba(0,0,0,.55); +} +.card-choice.dud { + background: linear-gradient(145deg, #2b2b2b, #191919); + color: #878787; +} +.card-choice.dud .card-tags span { background: #222; color: #aaa; } + +@media (max-width: 1180px) { + .debug-panel:not([open]) { + width: 92px !important; + right: 8px; + bottom: 8px; + } +} + + +/* v27.18 inherited cache-proof identity and final UI overrides */ +.build-stamp { + position: absolute; + z-index: 12; + right: 14px; + top: 76px; + padding: 5px 9px; + border: 2px solid #ffb827; + background: rgba(14, 17, 22, .94); + color: #80e067; + box-shadow: 3px 3px 0 rgba(0,0,0,.7); + font: 900 11px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + letter-spacing: .04em; + pointer-events: none; +} +.debug-panel:not([open]) { + width: 58px !important; + max-width: 58px !important; + height: 30px; + min-height: 0; +} +.debug-panel:not([open]) summary { + box-sizing: border-box; + width: 58px; + height: 27px; + padding: 5px 7px; + text-align: center; + overflow: hidden; + text-overflow: clip; +} +.debug-panel[open] { + width: min(390px, calc(100% - 24px)) !important; + height: auto; +} +.card-choice { + border-width: 3px; + box-shadow: 4px 4px 0 rgba(0,0,0,.55), inset 0 0 0 1px rgba(255,184,39,.14); +} +.card-choice:hover { + transform: translateY(-2px); + box-shadow: 4px 6px 0 rgba(0,0,0,.65), inset 0 0 0 2px rgba(128,224,103,.24); +} +.card-icon img { + image-rendering: pixelated; + filter: drop-shadow(2px 2px 0 rgba(0,0,0,.7)); +} +#gameCanvas { image-rendering: pixelated; } + +/* v27.18: status relocation, consistent industrial controls, card watermarks */ +.hud-top-left { grid-template-columns: repeat(5, minmax(82px, auto)); } + +.left-bottom-status { + position: absolute; + z-index: 6; + left: 10px; + bottom: 10px; + width: min(310px, calc(100% - 20px)); + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; + pointer-events: none; +} +.left-bottom-status > div { + min-width: 0; + border: 3px solid var(--line); + background: rgba(22, 26, 32, .95); + color: var(--ink); + padding: 8px 10px; + box-shadow: 4px 4px 0 rgba(0,0,0,.68), inset 0 0 0 1px rgba(255,184,39,.10); + font-size: 12px; + line-height: 1.2; + font-weight: 900; + text-transform: uppercase; + letter-spacing: .025em; + overflow: hidden; + text-overflow: ellipsis; +} +.left-bottom-status .event-brief { grid-column: 1 / -1; white-space: normal; min-height: 39px; } +.left-bottom-status .event-brief.active { background: #35221c; box-shadow: inset 0 0 0 3px var(--danger), 4px 4px 0 rgba(0,0,0,.68); } +.left-bottom-status .event-brief.next { background: #22301f; box-shadow: inset 0 0 0 3px var(--green), 4px 4px 0 rgba(0,0,0,.68); } +.left-bottom-status .event-brief.locked { background: #1c2027; color: var(--muted); } +.left-bottom-status .speed-brief { color: #d9e2e8; } +.left-bottom-status .target-brief { color: #ffcf68; } +.left-bottom-status .combo-brief { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; } +.left-bottom-status .combo-brief span { color: var(--muted); font-size: 10px; } +.left-bottom-status .combo-brief strong { color: var(--green); font-size: 22px; line-height: 1; } + +/* Remove the remaining bright green/white control styling from modal actions. */ +.modal-actions button, +.facility-action, +.card-target-button { + border: 3px solid #07080a; + background: linear-gradient(#353d48, #1b1f25); + color: #e6edf2; + box-shadow: inset 0 0 0 1px rgba(255,184,39,.14), 4px 4px 0 rgba(0,0,0,.68); +} +.modal-actions button:hover:not(:disabled), +.facility-action:hover:not(:disabled), +.card-target-button:hover:not(:disabled) { + background: linear-gradient(#424b58, #242930); + color: #fff0c9; + box-shadow: inset 0 0 0 2px rgba(255,184,39,.42), 4px 4px 0 rgba(0,0,0,.72); +} +.facility-action.warn, +.modal-actions .reroll-button { + background: linear-gradient(#554221, #2b2419); + color: #ffd36a; + box-shadow: inset 0 0 0 3px #b97810, 5px 5px 0 rgba(0,0,0,.72); +} +.modal-actions .reroll-button:hover:not(:disabled) { + background: linear-gradient(#6b5227, #342919); + color: #fff0bd; + box-shadow: inset 0 0 0 3px #ffb827, 5px 5px 0 rgba(0,0,0,.76); +} +.facility-action.good { background: linear-gradient(#29422a, #19271a); color: #a9ed91; } +.facility-action.danger { background: linear-gradient(#57251f, #2d1715); color: #ffb1a3; } +.modal-actions button:disabled, +.facility-action:disabled, +.card-target-button:disabled { opacity: .42; filter: grayscale(.85); box-shadow: 3px 3px 0 rgba(0,0,0,.45); } + +/* Icons are now translucent background art rather than separate foreground badges. */ +.card-choice { + display: block; + min-height: 170px; + padding: 16px; + isolation: isolate; +} +.card-choice::before { z-index: 1; } +.card-copy { position: relative; z-index: 3; padding-right: 6px; } +.card-icon { + position: absolute; + z-index: 0; + right: -9px; + bottom: -12px; + width: 124px; + height: 124px; + border: 0; + background: transparent; + box-shadow: none; + opacity: .14; + transform: rotate(-7deg); + pointer-events: none; + overflow: visible; +} +.card-icon img { + width: 100%; + height: 100%; + object-fit: contain; + filter: grayscale(.12) contrast(1.2) drop-shadow(3px 3px 0 rgba(0,0,0,.55)); +} +.card-icon.glyph { + display: grid; + place-items: center; + color: #f0b437; + font-size: 88px; + line-height: 1; + text-shadow: 4px 4px 0 rgba(0,0,0,.55); +} +.card-choice.rare .card-icon { opacity: .16; } +.card-choice.ultra-rare .card-icon { opacity: .17; } +.card-choice.dud .card-icon { opacity: .08; filter: grayscale(1); } + +@media (max-width: 1180px) { + .hud-top-left { grid-template-columns: repeat(3, minmax(80px, 1fr)); } + .left-bottom-status { width: 290px; left: 8px; bottom: 8px; } +} +@media (max-width: 760px) { + .left-bottom-status { width: min(270px, calc(100% - 16px)); grid-template-columns: 1fr; } + .left-bottom-status .event-brief { grid-column: auto; } +} + + +/* v27.19: compact Next Day fee label and deduplicated side panel */ +.panel-head { grid-template-columns: minmax(0, 1fr) minmax(112px, 126px); } +.primary-button#nextTurnButton { + min-width: 0; + max-width: 126px; + padding: 8px 7px; + white-space: normal; + overflow: hidden; + line-height: 1.08; + display: grid; + place-content: center; + gap: 4px; + text-align: center; +} +#nextTurnButton .next-day-main { display: block; font-size: 15px; letter-spacing: .035em; } +#nextTurnButton .next-day-fee { + display: block; + max-width: 100%; + color: #ffd36a; + font-size: 9px; + line-height: 1.15; + letter-spacing: 0; + overflow-wrap: anywhere; +}