Pela Gardens full code (index.html)
Copy all code
Download index.html
<!DOCTYPE html> <!-- Pela Gardens (c) 2026 Kusal K Jayalath. All rights reserved. Unauthorized copying, redistribution or rehosting is prohibited. --> <html lang="en"><head><meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: blob:; font-src data:; media-src data: blob:"> <meta name="theme-color" content="#7cc0ef"><title>Pela Gardens - From Seed to Harvest</title> <style> /* Embedded font: Fredoka Copyright 2016 The Fredoka Project Authors (https://github.com/hafontia/Fredoka-One) This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. */ @font-face{font-family:'Fredoka';src:url(data:font/woff2;base64,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) format('woff2');font-weight:300 700;font-stretch:75% 125%;font-display:block} *{box-sizing:border-box;-webkit-tap-highlight-color:transparent} html,body{-webkit-text-size-adjust:100%;text-size-adjust:100%;margin:0;height:100%;overflow:hidden;background:#17241a;font-family:Fredoka,ui-rounded,'Segoe UI',system-ui,sans-serif;user-select:none;-webkit-user-select:none;touch-action:none;color:#5a3418} #stage{position:absolute;left:0;top:0;transform-origin:0 0;overflow:hidden;background:#7cc0ef} #scene,#fx{position:absolute;left:0;top:0;width:100%;height:100%;display:block} #scene{cursor:pointer} #fx{pointer-events:none;z-index:60} button{font-family:inherit;cursor:pointer;border:none;outline:none} svg{display:block} /* ---------- HUD ---------- */ #hud{position:absolute;left:24px;right:24px;top:20px;height:100px;display:flex;align-items:center;gap:18px;z-index:20;pointer-events:none} #hud>*{pointer-events:auto} .chip{background:linear-gradient(#fffaf0,#fbecd0);border:4px solid #fff;border-radius:999px;box-shadow:0 6px 0 rgba(120,70,25,.28),0 12px 26px rgba(0,0,0,.18);display:flex;align-items:center;font-weight:600} #lvlBox{position:relative;height:84px;padding:0 26px 0 96px;gap:14px} #lvlBadge{position:absolute;left:-10px;top:-12px;width:104px;height:104px;display:flex;align-items:center;justify-content:center} #lvlBadge svg{position:absolute;inset:0;filter:drop-shadow(0 5px 0 rgba(150,80,0,.35))} #lvlNum{position:relative;font-size:38px;font-weight:700;color:#fff;text-shadow:0 3px 0 #c06a00,0 0 6px rgba(160,80,0,.6);margin-top:6px} .xpwrap{display:flex;flex-direction:column;gap:4px} .xplabel{font-size:20px;color:#9a6a3e;font-weight:600;letter-spacing:.5px} .xpbar{width:250px;height:26px;border-radius:20px;background:#e9d4b0;box-shadow:inset 0 3px 0 rgba(0,0,0,.12);overflow:hidden;position:relative} .xpbar i{position:absolute;left:0;top:0;bottom:0;width:0;border-radius:20px;background:linear-gradient(#8fe36a,#4cb83a);box-shadow:inset 0 -4px 0 rgba(0,0,0,.12),inset 0 4px 0 rgba(255,255,255,.4);transition:width .4s cubic-bezier(.3,1.4,.6,1)} #coinBox{height:84px;padding:0 30px 0 14px;gap:12px;font-size:44px;color:#7a4a1c;min-width:200px} .coinIco{width:56px;height:56px;border-radius:50%;background:radial-gradient(circle at 35% 30%,#fff6b0 0 12%,#ffd23f 30%,#f0a400 75%,#c87800);box-shadow:inset 0 0 0 5px rgba(200,120,0,.55),0 3px 0 rgba(150,80,0,.4);position:relative;flex:none} .coinIco:after{content:'';position:absolute;inset:14px;border-radius:50%;border:4px solid rgba(255,250,200,.7)} .coinIco.sm{width:34px;height:34px}.coinIco.sm:after{inset:8px;border-width:3px} .bump{animation:bump .35s cubic-bezier(.3,1.8,.5,1)} @keyframes bump{0%{transform:scale(1)}40%{transform:scale(1.18)}100%{transform:scale(1)}} #timeBox{height:72px;padding:0 26px 0 12px;gap:12px;font-size:28px;margin-left:auto} #timeIco{width:52px;height:52px} .tag{font-size:21px;padding:5px 14px;border-radius:999px;color:#fff;font-weight:600} .tag.spring{background:#ef7aa8}.tag.summer{background:#3faa48}.tag.autumn{background:#e0702a}.tag.winter{background:#5a94d6} #weatherIco{width:46px;height:46px} #hudBtns{display:flex;gap:14px;margin-left:auto} .rbtn{width:84px;height:84px;border-radius:28px;background:linear-gradient(#fffaf0,#f6e2bd);border:4px solid #fff;box-shadow:0 6px 0 rgba(120,70,25,.3),0 12px 22px rgba(0,0,0,.18);display:flex;align-items:center;justify-content:center;position:relative;transition:transform .12s} @media (hover:hover) and (pointer:fine){.rbtn:hover{transform:translateY(-3px)}} .rbtn:active{transform:translateY(4px);box-shadow:0 2px 0 rgba(120,70,25,.3)} .rbtn svg{width:50px;height:50px} .rbtn.big{width:auto;padding:0 26px 0 18px;gap:10px;font-size:32px;font-weight:600;color:#6a3d16;background:linear-gradient(#ffe68a,#ffc446)} .rbtn .dot{position:absolute;top:-8px;right:-8px;min-width:34px;height:34px;border-radius:20px;background:#ff5a4a;color:#fff;font-size:22px;font-weight:700;display:none;align-items:center;justify-content:center;border:3px solid #fff;padding:0 6px} .rbtn .dot.on{display:flex;animation:pulse 1.2s infinite} @keyframes pulse{50%{transform:scale(1.15)}} .keyhint{position:absolute;bottom:-10px;right:6px;pointer-events:none;line-height:1.2;font-size:16px;background:#6a3d16;color:#fff;border-radius:8px;padding:1px 7px;opacity:.85} /* ---------- Hotbar ---------- */ #hotbar{position:absolute;left:24px;bottom:22px;z-index:20;display:flex;gap:10px;padding:12px 14px;border-radius:36px;background:linear-gradient(#c88b52,#a5663a);border:5px solid #7d4521;box-shadow:inset 0 4px 0 rgba(255,255,255,.25),0 8px 0 rgba(70,35,10,.35),0 16px 30px rgba(0,0,0,.25);overflow-x:auto;scrollbar-width:none;max-width:calc(100% - 48px)} #hotbar::-webkit-scrollbar{display:none} .slot{flex:none;width:102px;height:120px;border-radius:24px;background:linear-gradient(#fffaf0,#f3dfb8);box-shadow:inset 0 -5px 0 rgba(150,90,40,.2),0 4px 0 rgba(60,30,8,.35);position:relative;display:flex;align-items:center;justify-content:center;transition:transform .18s cubic-bezier(.3,1.6,.5,1);cursor:pointer} .slot img{width:80px;height:80px;pointer-events:none;filter:drop-shadow(0 3px 2px rgba(0,0,0,.2))} .slot:hover{transform:translateY(-6px)} .slot.sel{transform:translateY(-12px) scale(1.06);background:linear-gradient(#fff9d6,#ffe48a);box-shadow:0 0 0 5px #fff,0 0 0 10px #ffb92e,0 10px 18px rgba(0,0,0,.3)} .slot .cnt{position:absolute;right:-6px;bottom:-6px;min-width:42px;height:38px;border-radius:20px;background:#5a8f2e;color:#fff;font-size:24px;font-weight:700;display:flex;align-items:center;justify-content:center;border:3px solid #fff;padding:0 6px} .slot .cnt.zero{background:#b55a4a} .slot .key{position:absolute;left:8px;top:5px;font-size:17px;font-weight:700;color:#b08050} .slot .sea{position:absolute;right:6px;top:5px;width:24px;height:24px} .slot.locked img{filter:grayscale(1) brightness(1.15) opacity(.45)} .slot.locked .lk{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;font-size:22px;font-weight:700;color:#8a6040} .slot.sep{width:6px;background:rgba(0,0,0,.18);box-shadow:none;cursor:default;border-radius:4px} .slot.sep:hover{transform:none} /* ---------- Orders ---------- */ #orders{position:absolute;right:24px;top:136px;bottom:24px;width:470px;z-index:15;display:flex;flex-direction:column} .panel{background:linear-gradient(#fff8ea,#f7e6c6);border:6px solid #fff;border-radius:34px;box-shadow:0 0 0 5px #b97a43,0 10px 0 5px #7d4521,0 20px 40px rgba(0,0,0,.3)} .ribbon{align-self:center;margin-top:-30px;background:linear-gradient(#ff8f6b,#e9573f);color:#fff;font-size:34px;font-weight:700;padding:8px 40px;border-radius:20px;box-shadow:0 6px 0 #b03a26,0 10px 18px rgba(0,0,0,.2);text-shadow:0 3px 0 rgba(0,0,0,.2);white-space:nowrap;position:relative;z-index:2} #orderList{flex:1;overflow-y:auto;padding:18px 18px 10px;display:flex;flex-direction:column;gap:14px;scrollbar-width:thin} .goal{margin:0 18px 16px;padding:12px 16px;border-radius:20px;background:#efe0bf;font-size:20px;color:#7a5530;line-height:1.3} .goal b{color:#5a3418} .ocard{background:#fff;border-radius:26px;padding:14px 16px;box-shadow:0 5px 0 rgba(150,95,45,.25);display:flex;flex-direction:column;gap:10px;animation:popin .45s cubic-bezier(.3,1.6,.5,1)} @keyframes popin{0%{transform:scale(.6);opacity:0}100%{transform:scale(1);opacity:1}} .ocard.done{animation:popout .4s ease-in forwards} @keyframes popout{to{transform:scale(.7) translateX(80px);opacity:0}} .ohead{display:flex;align-items:center;gap:12px} .ohead canvas{width:64px;height:64px;border-radius:50%;flex:none} .oname{font-size:26px;font-weight:600;flex:1;line-height:1.05} .oname small{display:block;font-size:18px;color:#a07850;font-weight:500} .oskip{width:40px;height:40px;border-radius:50%;background:#f1e2c6;color:#a07850;font-size:26px;font-weight:700;line-height:1} .oitems{display:flex;gap:10px;flex-wrap:wrap} .oit{display:flex;align-items:center;gap:4px;background:#fbf2df;border-radius:16px;padding:4px 12px 4px 4px;font-size:24px;font-weight:600} .oit img{width:46px;height:46px} .oit.ok{background:#e1f5cf;color:#3f8a24} .ofoot{display:flex;align-items:center;gap:12px;font-size:24px;font-weight:600} .ofoot .rw{display:flex;align-items:center;gap:6px} .ofoot .xp{color:#4c9a2e} .ofoot .btn{margin-left:auto;font-size:24px;padding:10px 22px} .owait{font-size:22px;color:#a07850;text-align:center;padding:26px 0} /* ---------- Buttons ---------- */ .btn{font-size:28px;font-weight:600;padding:14px 30px;border-radius:22px;background:linear-gradient(#86da5e,#4fae36);color:#fff;text-shadow:0 2px 0 rgba(0,0,0,.25);box-shadow:inset 0 3px 0 rgba(255,255,255,.35),0 6px 0 #2f7d22,0 10px 16px rgba(0,0,0,.2);transition:transform .1s,filter .1s;white-space:nowrap} .btn:hover{filter:brightness(1.07)} .btn:active{transform:translateY(4px);box-shadow:0 2px 0 #2f7d22} .btn.orange{background:linear-gradient(#ffc04a,#f08a1c);box-shadow:inset 0 3px 0 rgba(255,255,255,.35),0 6px 0 #b05a08,0 10px 16px rgba(0,0,0,.2)} .btn.blue{background:linear-gradient(#6cc6ff,#2f8fe0);box-shadow:inset 0 3px 0 rgba(255,255,255,.35),0 6px 0 #1a5fa8,0 10px 16px rgba(0,0,0,.2)} .btn.red{background:linear-gradient(#ff8a72,#e0503a);box-shadow:inset 0 3px 0 rgba(255,255,255,.35),0 6px 0 #a02e1e,0 10px 16px rgba(0,0,0,.2)} .btn.off,.btn:disabled{background:linear-gradient(#d9cdb8,#bfb09a);box-shadow:0 6px 0 #9a8b74;cursor:default;filter:none;transform:none} /* ---------- Modal ---------- */ #modalWrap{position:absolute;inset:0;z-index:40;display:none;align-items:center;justify-content:center;background:rgba(30,20,10,.5)} #modalWrap.on{display:flex} #modal{width:min(1240px,92%);max-height:88%;display:flex;flex-direction:column;animation:popin .4s cubic-bezier(.3,1.5,.5,1);position:relative} #modal .mclose{position:absolute;right:-22px;top:-26px;width:76px;height:76px;border-radius:50%;background:linear-gradient(#ff8a72,#e0503a);color:#fff;font-size:44px;font-weight:700;box-shadow:0 6px 0 #a02e1e,0 10px 16px rgba(0,0,0,.25);border:5px solid #fff;z-index:3;line-height:1} .mbody{padding:20px 34px 30px;overflow-y:auto;scrollbar-width:thin} #mTabs{display:flex;gap:10px;justify-content:center;margin:22px 0 4px} .tab{font-size:28px;font-family:inherit;font-weight:600;padding:10px 30px;border-radius:20px;background:#ead6b2;color:#8a6040} .tab.on{background:#fff;color:#5a3418;box-shadow:0 5px 0 rgba(150,95,45,.3)} .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:18px} .card{background:#fff;border-radius:26px;padding:16px;box-shadow:0 5px 0 rgba(150,95,45,.25);display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;position:relative} .card img,.card canvas.ic{width:96px;height:96px} .card h3{margin:0;font-size:28px;font-weight:600} .card .sub{font-size:20px;color:#a07850;line-height:1.25} .card .row{display:flex;gap:10px;margin-top:6px;flex-wrap:wrap;justify-content:center} .card .btn{font-size:22px;padding:10px 16px;display:inline-flex;align-items:center;gap:4px} .card.lock{opacity:.6} .card .badge{position:absolute;top:10px;right:10px;font-size:18px;background:#e1f5cf;color:#3f8a24;border-radius:12px;padding:3px 10px;font-weight:600} .card .badge.hot{background:#ffe0d6;color:#d04a2a} .price{display:inline-flex;align-items:center;gap:6px} .mtext{font-size:26px;line-height:1.45;text-align:center} .srow{display:flex;align-items:center;gap:16px;background:#fff;border-radius:22px;padding:10px 18px;margin-bottom:12px;font-size:26px;box-shadow:0 4px 0 rgba(150,95,45,.2)} .srow img{width:64px;height:64px} .srow .grow{flex:1} .srow .btn{font-size:22px;padding:10px 18px} .slider{flex:1;accent-color:#4fae36;height:30px} .toggle{width:90px;height:48px;border-radius:30px;background:#cdbb9c;position:relative;transition:background .2s} .toggle:after{content:'';position:absolute;left:5px;top:5px;width:38px;height:38px;border-radius:50%;background:#fff;transition:left .2s cubic-bezier(.3,1.5,.5,1);box-shadow:0 2px 4px rgba(0,0,0,.2)} .toggle.on{background:#4fae36}.toggle.on:after{left:47px} .keys{display:grid;grid-template-columns:auto 1fr auto 1fr;gap:6px 14px;font-size:21px} .keys kbd{font-family:inherit;background:#6a3d16;color:#fff;border-radius:8px;padding:1px 10px;font-weight:600;justify-self:start} /* ---------- Toast / tooltip / tutorial ---------- */ #toast{position:absolute;left:50%;top:140px;transform:translateX(-50%);z-index:45;display:flex;flex-direction:column;align-items:center;gap:10px;pointer-events:none} .tmsg{background:rgba(60,35,15,.88);color:#fff;font-size:28px;font-weight:600;padding:12px 30px;border-radius:999px;animation:tin .35s cubic-bezier(.3,1.6,.5,1);box-shadow:0 8px 20px rgba(0,0,0,.25);white-space:nowrap} .tmsg.good{background:rgba(60,130,40,.92)}.tmsg.bad{background:rgba(190,60,40,.92)} @keyframes tin{from{transform:translateY(-20px) scale(.8);opacity:0}} #tooltip{position:absolute;z-index:30;pointer-events:none;background:rgba(255,250,240,.97);border:4px solid #fff;border-radius:22px;padding:10px 18px;font-size:22px;box-shadow:0 6px 0 rgba(120,70,25,.25),0 10px 20px rgba(0,0,0,.2);display:none;min-width:200px;line-height:1.35} #tooltip b{font-size:26px} #tut{position:absolute;inset:0;z-index:35;pointer-events:none;display:none;overflow:hidden;contain:paint} #tut.on{display:block} #tutRing{position:absolute;border-radius:30px;box-shadow:0 0 0 6px #fff,0 0 0 12px #ffb92e,0 0 0 2600px rgba(20,10,0,.25);animation:ring 1.2s infinite;transition:all .35s cubic-bezier(.3,1.3,.5,1)} @keyframes ring{50%{box-shadow:0 0 0 10px #fff,0 0 0 18px #ffb92e,0 0 0 2600px rgba(20,10,0,.25)}} #tutBub{position:absolute;width:520px;background:#fff;border-radius:28px;padding:20px 26px;font-size:28px;line-height:1.35;box-shadow:0 8px 0 rgba(120,70,25,.25),0 16px 30px rgba(0,0,0,.25);transition:all .35s cubic-bezier(.3,1.3,.5,1);pointer-events:auto} #tutBub .who{display:flex;align-items:center;gap:12px;font-weight:700;color:#e9573f;margin-bottom:6px;font-size:24px} #tutBub .who canvas{width:56px;height:56px;border-radius:50%} #tutBub .tb{display:flex;justify-content:space-between;align-items:center;margin-top:12px} #tutBub .skip{background:none;color:#a07850;font-size:20px;text-decoration:underline} #tutHand{position:absolute;width:80px;height:80px;transition:all .35s;animation:tap 1s infinite} @keyframes tap{50%{transform:translate(-8px,-12px) rotate(-8deg)}} /* ---------- Title ---------- */ #title{position:absolute;inset:0;z-index:55;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;background:radial-gradient(ellipse at center,rgba(255,255,255,0) 30%,rgba(40,20,0,.35))} #title.hide{animation:fadeout .6s forwards;pointer-events:none} @keyframes fadeout{to{opacity:0;transform:scale(1.08)}} .logo{position:relative;text-align:center;animation:float 4s ease-in-out infinite} @keyframes float{50%{transform:translateY(-14px) rotate(-1deg)}} .logo h1{margin:0;font-size:190px;font-weight:700;line-height:.95;color:#ffd84a;letter-spacing:2px;-webkit-text-stroke:0;text-shadow:0 0 0 #fff,6px 0 0 #fff,-6px 0 0 #fff,0 6px 0 #fff,0 -6px 0 #fff,5px 5px 0 #fff,-5px 5px 0 #fff,5px -5px 0 #fff,-5px -5px 0 #fff,0 14px 0 #c86a1a,0 22px 30px rgba(0,0,0,.35)} .logo h1 span{color:#7bd04a} .logo .sub{font-size:40px;font-weight:600;color:#fff;background:linear-gradient(#ff8f6b,#e9573f);display:inline-block;padding:8px 36px;border-radius:24px;box-shadow:0 7px 0 #b03a26;margin-top:18px;transform:rotate(-2deg)} .logo svg.sprout{position:absolute;width:150px;height:150px;left:50%;top:-118px;margin-left:-75px;animation:sway 3s ease-in-out infinite;transform-origin:50% 100%} @keyframes sway{50%{transform:rotate(6deg)}} .tbtns{display:flex;flex-direction:column;gap:22px;margin-top:40px;align-items:center} .tbtns .btn{font-size:44px;padding:20px 70px;min-width:440px;border-radius:30px} .tbtns .row{display:flex;gap:20px} .tbtns .row .btn{font-size:30px;min-width:210px;padding:14px 30px} .tfoot{position:absolute;bottom:24px;font-size:22px;color:rgba(255,255,255,.9);text-shadow:0 2px 4px rgba(0,0,0,.5)} /* ---------- Portrait ---------- */ .portrait #orders{left:30px;right:30px;width:auto;top:auto;bottom:200px;height:62%;transform:translateY(130%);transition:transform .4s cubic-bezier(.3,1.2,.5,1);z-index:32} .portrait #orders.open{transform:none} .portrait #hud{flex-wrap:wrap;height:auto} .portrait #timeBox{order:5;margin:6px auto 0} .portrait #hotbar{left:20px;right:20px;max-width:none} .portrait #btnOrders{display:flex!important} .portrait #tutBub{width:760px} .portrait .logo h1{font-size:150px} .portrait .grid{grid-template-columns:repeat(2,1fr)} #btnOrders{display:none} .ontitle #hud,.ontitle #hotbar,.ontitle #orders,.ontitle #toast{opacity:0;pointer-events:none} #hud,#hotbar,#orders{transition:opacity .6s} .reduce *{animation-duration:0s!important} .stk{text-align:center} .stkWin{font-size:24px;line-height:1.4;color:#7a5530;margin-bottom:8px} .stkTitle{font-size:40px;font-weight:700;color:#e9573f;line-height:1.15;margin:4px 0 14px;text-shadow:0 3px 0 #fff} .stkGrid{display:grid;grid-template-columns:repeat(8,1fr);gap:8px;background:linear-gradient(#e6f6ff,#fff6dc);border-radius:24px;padding:14px;box-shadow:inset 0 3px 0 rgba(150,95,45,.12)} .stkGrid img{width:100%;aspect-ratio:1;display:block;animation:popin .5s cubic-bezier(.3,1.5,.5,1) both} .stkGrid img:not([src]){visibility:hidden} .stkInfo{font-size:22px;color:#a07850;margin:12px 0 6px} .stkBtns{display:flex;gap:18px;justify-content:center;flex-wrap:wrap;margin-top:8px} .stkBtns .btn{font-size:30px} .stkTip{font-size:18px;color:#a07850;margin-top:14px} .stkRow{background:linear-gradient(90deg,#fff3c8,#ffe3d4)} .stkRow.lock{background:#f3ebde;color:#8a7458} .stkIco{width:84px;height:84px;flex:none} .stkSub{font-size:20px;color:#a07850} .stkLockWrap{position:relative;flex:none} .stkLockWrap .stkIco{filter:grayscale(1) opacity(.45)} .stkLockWrap svg{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)} @media (max-aspect-ratio:1/1){.stkGrid{grid-template-columns:repeat(4,1fr)}} /* ---------- v1.1 Animal yard ---------- */ #btnYard{background:linear-gradient(#fff3d6,#ffd9a8)} #btnYard #yardIco{width:52px;height:52px;display:block} #btnYard #yardIco img{width:100%;height:100%;display:block} #btnYard.locked{filter:grayscale(.7);opacity:.8} #btnYard.locked #yardLbl:after{content:' Lv 4';font-size:20px;color:#8a6040} #btnYard.attn{animation:pulse 1.6s infinite} #yardbar{position:absolute;left:24px;bottom:22px;z-index:20;display:none;align-items:center;gap:16px;padding:14px 18px;border-radius:36px;background:linear-gradient(#c88b52,#a5663a);border:5px solid #7d4521;box-shadow:inset 0 4px 0 rgba(255,255,255,.25),0 8px 0 rgba(70,35,10,.35),0 16px 30px rgba(0,0,0,.25)} .yardview #hotbar{display:none} .yardview #yardbar{display:flex} .ychip{display:flex;align-items:center;gap:8px;background:linear-gradient(#fffaf0,#f3dfb8);border-radius:24px;padding:6px 22px 6px 10px;box-shadow:inset 0 -5px 0 rgba(150,90,40,.2),0 4px 0 rgba(60,30,8,.35)} .ychip img{width:76px;height:76px} .ychip b{font-size:40px;display:block;line-height:1;color:#6a3d16} .ychip small{font-size:18px;color:#a07850;font-weight:600} #yardbar .btn{font-size:28px;padding:16px 26px} .acard img{width:120px!important;height:120px!important} .aniRow{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin:0 0 18px} .aniRow .card{width:170px;padding:10px;gap:2px} .aniRow .card img{width:84px;height:84px} .aniRow .card h3{font-size:22px} .aniRow .card .sub{font-size:17px} .gma{display:flex;gap:22px;align-items:flex-start;text-align:left} .gma canvas{width:120px;height:120px;border-radius:50%;flex:none;background:#ffe1a8} #stage:not(.portrait) .slot:not(.sep){width:92px;height:112px} #stage:not(.portrait) .slot img{width:74px;height:74px} #stage:not(.portrait) #hotbar{gap:8px;max-width:calc(100% - 548px)} .portrait #yardbar{left:20px;right:20px;justify-content:center;flex-wrap:wrap;gap:12px} .portrait #yardbar .btn{font-size:30px;padding:16px 22px} .portrait #hudBtns{gap:12px} .portrait #btnYard,.portrait #btnShop{padding:0 18px 0 12px;font-size:28px} /* v1.1 four seasons (journal) */ .seaRow .card{width:200px} .seaRow .card.cur{outline:5px solid #ffb92e;outline-offset:-2px} .seaRow .sicons{display:flex;flex-wrap:wrap;justify-content:center;gap:2px;min-height:48px} .seaRow .sicons img{width:44px;height:44px} .seaRow .sea_spring h3{color:#d0457a}.seaRow .sea_summer h3{color:#2f8a3a}.seaRow .sea_autumn h3{color:#c0501a}.seaRow .sea_winter h3{color:#3a74b6} /* ownership line */ .tfoot{text-align:center}.tfoot .tcopy{font-size:16px;opacity:.75;margin-top:6px}.copy{font-size:17px;opacity:.7} .ontitle #modalWrap.ttop{z-index:60} /* v1.2 */ .mboard{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin:8px 0 14px} .mprice{display:flex;align-items:center;gap:6px;background:#fffaf0;border-radius:14px;padding:4px 10px;font-size:22px;box-shadow:0 3px 0 rgba(150,95,45,.18)} .mprice img{width:40px;height:40px} .dstars{font-size:84px;line-height:1;letter-spacing:6px;color:#e8dcc8}.dstars .on{color:#ffc22e;text-shadow:0 4px 0 #d08a00} .dgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:14px 0} .dstat{background:#fffaf0;border-radius:18px;padding:12px 8px;display:flex;flex-direction:column;align-items:center;gap:2px;font-size:20px;color:#a07850;box-shadow:0 4px 0 rgba(150,95,45,.18)} .dstat img{width:52px;height:52px}.dstat b{font-size:34px;color:#5a3418} .portrait .dgrid{grid-template-columns:repeat(2,1fr)} .slot.frost img{filter:grayscale(.7) brightness(1.1)} .lk.frostlk{background:rgba(200,230,255,.85);color:#2a5a8a} #orders.bump{animation:obump .5s} @keyframes obump{0%{transform:scale(1)}40%{transform:scale(1.04)}100%{transform:scale(1)}} .wnew li{margin:6px 0} #tutBub small{font-size:.8em;color:#7a5a3a} .slot.frost .lk{position:absolute;left:0;right:0;bottom:0;font-size:16px;font-weight:700;text-align:center;border-radius:0 0 12px 12px;padding:2px 0} /* v1.2.1: touch devices: no keyboard badges, no hover tooltips; evenly spaced top-right row */ @media (hover:none),(pointer:coarse){.keyhint{display:none!important}#tooltip{display:none!important}} html.touch .keyhint,html.touch #tooltip{display:none!important} #hudBtns{align-items:center} .portrait #hudBtns{justify-content:flex-end} .rbtn.big{white-space:nowrap} /* order-ready feedback */ #ordDot.on{background:linear-gradient(#ff6a4a,#e0302a);border-color:#ffe14a;animation:obounce .9s infinite} @keyframes obounce{0%,100%{transform:translateY(0) scale(1)}40%{transform:translateY(-8px) scale(1.12)}} #btnOrders.ready{animation:oglow 1.4s infinite} @keyframes oglow{0%,100%{box-shadow:0 6px 0 rgba(120,70,25,.3),0 0 0 0 rgba(255,210,60,.0)}50%{box-shadow:0 6px 0 rgba(120,70,25,.3),0 0 0 10px rgba(255,210,60,.55)}} .ocard{position:relative}.ocard.ready{box-shadow:0 0 0 4px #7bd04a,0 5px 0 rgba(150,95,45,.25)} .oready{position:absolute;top:-12px;left:18px;background:#4cb82a;color:#fff;font-weight:700;font-size:20px;padding:2px 12px;border-radius:12px;border:3px solid #fff;animation:obounce 1.2s infinite} /* Order Complete pop-up */ #ordPop{position:absolute;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;background:rgba(60,30,10,.18)} #ordPop .opcard{background:linear-gradient(#fffaf0,#fff1d6);border:6px solid #fff;border-radius:36px;box-shadow:0 10px 0 rgba(150,95,45,.3),0 24px 50px rgba(0,0,0,.25);padding:26px 40px 18px;min-width:560px;text-align:center;animation:oppop .55s cubic-bezier(.3,1.7,.5,1)} #ordPop.out .opcard{animation:opout .26s ease-in forwards} @keyframes oppop{0%{transform:scale(.3)}100%{transform:scale(1)}}@keyframes opout{to{transform:scale(.6);opacity:0}} .optitle{font-size:56px;font-weight:700;color:#ffb92e;-webkit-text-stroke:3px #8a4a1a;paint-order:stroke fill;text-shadow:0 5px 0 rgba(138,74,26,.35);margin-bottom:10px} .ophead{display:flex;align-items:center;gap:18px;justify-content:center;font-size:32px;color:#5a3418;text-align:left}.ophead canvas{width:96px;height:96px;border-radius:50%;border:4px solid #fff;box-shadow:0 4px 0 rgba(150,95,45,.25)} .opthx{font-size:24px;color:#a07850;font-style:italic} .opitems,.oprew{display:flex;gap:16px;justify-content:center;align-items:center;margin-top:14px;font-size:28px;font-weight:600;color:#5a3418}.opitems img{width:52px;height:52px;vertical-align:middle} .oprew{font-size:34px}.opxp{color:#3a9a2a;font-weight:700} .opbonus{display:inline-block;margin-top:12px;background:#ffe14a;color:#8a4a00;font-weight:700;font-size:24px;padding:4px 16px;border-radius:14px;border:3px solid #fff} .optap{margin-top:12px;font-size:18px;color:#b09070} .portrait #ordPop .opcard{min-width:0;width:86%} #ordDot.on{min-width:44px;height:38px;padding:0 9px;font-size:22px;letter-spacing:1px;top:-12px;right:-14px} .aniInfo img{width:110px;height:110px;object-fit:contain}.aniInfo .aisub{font-size:21px;color:#a07850} .lvStk{margin:12px auto;max-width:440px;background:linear-gradient(#e6f6ff,#fff6dc);border-radius:24px;padding:12px}.lvStkT{font-size:34px;font-weight:700;color:#e9573f}.lvStk img{width:200px;height:200px;display:block;margin:4px auto;animation:popin .6s cubic-bezier(.3,1.5,.5,1) both}.lvStkN{font-size:24px;color:#7a5530;margin-bottom:8px} .album{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;background:linear-gradient(#e6f6ff,#fff6dc);border-radius:24px;padding:14px}.alb{background:#fff;border-radius:18px;padding:6px;box-shadow:0 3px 0 rgba(150,95,45,.15)}.alb img{width:100%;aspect-ratio:1;display:block}.alb img:not([src]){visibility:hidden}.alb.lock img{filter:brightness(0) opacity(.18)}.albN{font-size:18px;font-weight:700;color:#5a3418;line-height:1.1}.albL{font-size:16px;color:#a07850}.alb.lock .albN{color:#b8a48a} @media (max-aspect-ratio:1/1){.album{grid-template-columns:repeat(3,1fr)}} .alb.lock{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}.alb.lock .albLock{width:100%;aspect-ratio:1;display:block;pointer-events:none} .alb.own{cursor:pointer}.stkBig{width:340px;height:340px;display:block;margin:0 auto}.lvStk .stkBtns .btn{font-size:24px} </style></head><body> <div id="stage"> <canvas id="scene"></canvas> <div id="hud"> <div id="lvlBox" class="chip" title="Level and XP"> <div id="lvlBadge"><svg viewBox="0 0 100 100"><defs><linearGradient id="sg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#ffe56b"/><stop offset="1" stop-color="#ff9d1c"/></linearGradient></defs><path d="M50 4l13 27 30 4-22 21 6 30-27-15-27 15 6-30L7 35l30-4z" fill="url(#sg)" stroke="#fff" stroke-width="6" stroke-linejoin="round"/></svg><span id="lvlNum">1</span></div> <div class="xpwrap"><div class="xplabel" id="xpText">XP 0 / 30</div><div class="xpbar"><i id="xpFill"></i></div></div> </div> <div id="coinBox" class="chip"><span class="coinIco"></span><b id="coinNum">0</b></div> <div id="timeBox" class="chip"><canvas id="timeIco" width="104" height="104"></canvas><span id="dayText">Day 1</span><span id="seasonTag" class="tag spring">Spring</span><canvas id="weatherIco" width="92" height="92"></canvas></div> <div id="hudBtns"> <button class="rbtn big" id="btnYard" title="Animal Yard (Y)"><span id="yardIco"></span><span id="yardLbl">Animals</span><span class="dot" id="yardDot">!</span><span class="keyhint">Y</span></button> <button class="rbtn big" id="btnShop" title="Shop (B)"><svg viewBox="0 0 64 64"><path d="M8 26h48v30H8z" fill="#fff4dc" stroke="#8a4a1a" stroke-width="4" stroke-linejoin="round"/><path d="M6 12h52l4 16H2z" fill="#ff6b4a" stroke="#8a4a1a" stroke-width="4" stroke-linejoin="round"/><path d="M15 12l-3 16M28 12l-1 16M37 12l1 16M50 12l3 16" stroke="#fff" stroke-width="5"/><rect x="24" y="36" width="16" height="20" fill="#c97a3a" stroke="#8a4a1a" stroke-width="4"/></svg>Shop<span class="keyhint">B</span></button> <button class="rbtn" id="btnOrders" title="Orders (O)"><svg viewBox="0 0 64 64"><rect x="10" y="8" width="44" height="50" rx="6" fill="#fff4dc" stroke="#8a4a1a" stroke-width="4"/><rect x="22" y="4" width="20" height="10" rx="3" fill="#c97a3a" stroke="#8a4a1a" stroke-width="4"/><path d="M19 26h26M19 36h26M19 46h16" stroke="#8a4a1a" stroke-width="4" stroke-linecap="round"/></svg><span class="dot" id="ordDot">!</span></button> <button class="rbtn" id="btnJournal" title="Journal (J)"><svg viewBox="0 0 64 64"><path d="M10 10h20c2 0 2 2 2 2v44s0-2-2-2H10z" fill="#7bd04a" stroke="#2f6d1a" stroke-width="4" stroke-linejoin="round"/><path d="M54 10H34c-2 0-2 2-2 2v44s0-2 2-2h20z" fill="#8fe06a" stroke="#2f6d1a" stroke-width="4" stroke-linejoin="round"/><path d="M42 20l3 6 6 1-4 4 1 6-6-3-6 3 1-6-4-4 6-1z" fill="#ffd84a"/></svg><span class="dot" id="achDot">!</span><span class="keyhint">J</span></button> <button class="rbtn" id="btnSettings" title="Settings (Esc)"><svg viewBox="0 0 64 64"><path d="M25.31 14.22 L26.74 6.03 L37.26 6.03 L38.69 14.22 L39.84 14.69 L46.64 9.91 L54.09 17.36 L49.31 24.16 L49.78 25.31 L57.97 26.74 L57.97 37.26 L49.78 38.69 L49.31 39.84 L54.09 46.64 L46.64 54.09 L39.84 49.31 L38.69 49.78 L37.26 57.97 L26.74 57.97 L25.31 49.78 L24.16 49.31 L17.36 54.09 L9.91 46.64 L14.69 39.84 L14.22 38.69 L6.03 37.26 L6.03 26.74 L14.22 25.31 L14.69 24.16 L9.91 17.36 L17.36 9.91 L24.16 14.69Z" fill="#a8b8c8" stroke="#4a5a6a" stroke-width="4" stroke-linejoin="round"/><circle cx="32" cy="32" r="9" fill="#fff" stroke="#4a5a6a" stroke-width="4"/></svg></button> <button class="rbtn" id="btnFull" title="Fullscreen (F)"><svg viewBox="0 0 64 64" fill="none" stroke="#5a3418" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"><path d="M10 24V10h14M40 10h14v14M54 40v14H40M24 54H10V40"/></svg></button> <button class="rbtn" id="btnMute" title="Sound (M)"><svg viewBox="0 0 64 64"><path d="M8 24h12l14-12v40L20 40H8z" fill="#ffd84a" stroke="#8a4a1a" stroke-width="4" stroke-linejoin="round"/><g id="sndOn" fill="none" stroke="#8a4a1a" stroke-width="4" stroke-linecap="round"><path d="M42 24c4 4 4 12 0 16"/><path d="M48 18c8 8 8 20 0 28"/></g><g id="sndOff" stroke="#e0503a" stroke-width="5" stroke-linecap="round" style="display:none"><path d="M42 24l14 16M56 24L42 40"/></g></svg></button> </div> </div> <div id="orders" class="panel"><div class="ribbon">Orders Board</div><div id="orderList"></div><div class="goal" id="goalBox"></div></div> <div id="hotbar"></div> <div id="yardbar"><div class="ychip" title="Animal feed"><img id="yFeedIco" alt=""><div><b id="yFeedNum">0</b><small>feed</small></div></div><button class="btn" id="yFeedAll">Feed all</button><button class="btn orange" id="yMake">Make feed</button><button class="btn blue" id="yAd" style="display:none">▶ Free meals</button><button class="btn blue" id="yBack">Back to farm</button></div> <div id="tooltip"></div> <div id="toast"></div> <div id="tut"><div id="tutRing"></div><svg id="tutHand" viewBox="0 0 64 64"><path d="M24 30V10a5 5 0 0110 0v18l14 3c4 1 6 4 5 8l-3 14c-1 4-4 7-8 7H30c-3 0-5-1-7-4l-9-14c-2-3 0-7 4-7 2 0 4 1 6 3z" fill="#ffe0c0" stroke="#5a3418" stroke-width="4" stroke-linejoin="round"/></svg><div id="tutBub"><div class="who"><canvas id="tutAva" width="112" height="112"></canvas>Grandma says</div><div id="tutText"></div><div class="tb"><button class="skip" id="tutSkip">Skip tutorial</button><button class="btn" id="tutNext" style="display:none">Got it!</button></div></div></div> <div id="modalWrap"><div id="modal" class="panel"><div class="ribbon" id="mTitle">Shop</div><button class="mclose" id="mClose">×</button><div id="mTabs"></div><div class="mbody" id="mBody"></div></div></div> <div id="title"> <div class="logo"><svg class="sprout" viewBox="0 0 100 100"><path d="M50 98C50 70 48 55 50 40" stroke="#3f8a24" stroke-width="7" fill="none" stroke-linecap="round"/><path d="M50 48C30 50 12 38 8 18c22-4 40 8 42 30z" fill="#7bd04a" stroke="#fff" stroke-width="5"/><path d="M50 40C58 18 78 8 96 12c-2 22-22 34-46 28z" fill="#9ae36a" stroke="#fff" stroke-width="5"/></svg><h1>Pela <span>Gardens</span></h1><div class="sub">Grow, care, sell: a cozy farm life</div></div> <div class="tbtns"><button class="btn" id="tPlay">Play</button><button class="btn orange" id="tNew" style="display:none">New Farm</button><div class="row"><button class="btn blue" id="tSettings">Settings</button><button class="btn blue" id="tCredits">Credits</button></div></div> <div class="tfoot">A cozy village farm sim · v1.2 · New: your own farmer, market and crop care! · Press Enter to play<div class="tcopy">© 2026 Kusal K Jayalath. All rights reserved.</div></div> </div> <canvas id="fx"></canvas> </div> <script> 'use strict'; /* Pela Gardens - all art, music and code are original and generated at runtime. */ const $=s=>document.querySelector(s); const TAU=Math.PI*2; const rand=(a,b)=>a+Math.random()*(b-a); const randi=(a,b)=>Math.floor(a+Math.random()*(b-a+1)); const clamp=(v,a,b)=>v<a?a:v>b?b:v; const lerp=(a,b,t)=>a+(b-a)*t; const sstep=t=>{t=clamp(t,0,1);return t*t*(3-2*t);}; function hash(n){n=(n|0)^61^((n|0)>>>16);n=Math.imul(n,9);n^=n>>>4;n=Math.imul(n,0x27d4eb2d);n^=n>>>15;return (n>>>0)/4294967296;} function mulberry(a){return function(){a|=0;a=a+0x6D2B79F5|0;let t=Math.imul(a^a>>>15,1|a);t=t+Math.imul(t^t>>>7,61|t)^t;return((t^t>>>14)>>>0)/4294967296;};} const hex=h=>[parseInt(h.slice(1,3),16),parseInt(h.slice(3,5),16),parseInt(h.slice(5,7),16)]; const mixc=(a,b,t)=>[lerp(a[0],b[0],t),lerp(a[1],b[1],t),lerp(a[2],b[2],t)]; const rgb=(c,a=1)=>`rgba(${c[0]|0},${c[1]|0},${c[2]|0},${a})`; const fmt=n=>Math.floor(n).toLocaleString('en-US'); const fmtT=s=>{s=Math.ceil(s);return s>=60?Math.floor(s/60)+'m '+(s%60)+'s':s+'s';}; /* ---------------- Crops ---------------- */ const CROPS=[ {id:'chili',name:'Chili',local:'Hot & spicy',kind:'bush',time:15,seeds:[1,3],prod:[2,3],sell:4,price:5,xp:2,lvl:1,season:['spring','summer','winter'],leaf:'#3f8f3a',pack:'#ffd9c9'}, {id:'tomato',name:'Tomato',local:'Juicy & red',kind:'bush',time:22,seeds:[1,2],prod:[2,3],sell:6,price:8,xp:3,lvl:1,season:['spring','summer'],leaf:'#4c9a3c',pack:'#ffe1d0'}, {id:'paddy',name:'Rice',local:'Golden grain',kind:'grass',time:30,seeds:[2,4],prod:[3,4],sell:5,price:10,xp:4,lvl:2,season:['spring','autumn'],leaf:'#6cb84a',pack:'#fff0b8'}, {id:'corn',name:'Corn',local:'Animal feed',kind:'corn',time:25,seeds:[2,3],prod:[3,4],sell:3,price:6,xp:3,lvl:4,season:'all',leaf:'#5aa848',pack:'#fff3c0',fodder:true}, {id:'brinjal',name:'Eggplant',local:'Purple veggie',kind:'bush',time:40,seeds:[1,3],prod:[2,3],sell:11,price:15,xp:5,lvl:3,season:['autumn','winter'],leaf:'#4a8a3a',pack:'#ecdcff'}, {id:'banana',name:'Banana',local:'Sweet fruit',kind:'banana',time:55,seeds:[1,2],prod:[1,2],sell:18,price:30,xp:7,lvl:4,season:['summer'],leaf:'#62b44c',pack:'#fff5b0'}, {id:'pineapple',name:'Pineapple',local:'Sweet & tangy',kind:'pine',time:70,seeds:[1,2],prod:[1,1],sell:32,price:45,xp:9,lvl:5,season:['spring','summer'],leaf:'#4e9a5a',pack:'#ffe9a8'}, {id:'rambutan',name:'Rambutan',local:'Hairy red fruit',kind:'tree',time:90,regrow:3,seeds:[1,2],prod:[3,5],sell:10,price:80,xp:12,lvl:6,season:['autumn'],leaf:'#4f9c3e',pack:'#ffd6dc'}, {id:'mango',name:'Mango',local:'Sunny fruit',kind:'tree',time:110,regrow:3,seeds:[1,2],prod:[2,4],sell:16,price:120,xp:14,lvl:8,season:['summer'],leaf:'#357d34',pack:'#ffe6b8'}, {id:'jackfruit',name:'Jackfruit',local:'Giant fruit',kind:'tree',time:140,regrow:3,seeds:[1,3],prod:[1,1],sell:70,price:180,xp:18,lvl:10,season:'all',leaf:'#2f7a3a',pack:'#e4f3c4'}, {id:'coconut',name:'Coconut',local:'Fresh and cool',kind:'palm',time:180,regrow:4,seeds:[1,1],prod:[2,3],sell:40,price:250,xp:22,lvl:12,season:['summer'],leaf:'#5aa848',pack:'#ffe0c0'}, ]; const CROP={};CROPS.forEach((c,i)=>{c.idx=i;CROP[c.id]=c;}); const MAXPLOTS=24, START_PLOTS=6, MAXLVL=20; const xpNeed=l=>Math.round(20*Math.pow(l,1.55)+10); const plotPrice=n=>Math.round(50*Math.pow(1.3,n-START_PLOTS)/5)*5; // n = index of plot being bought const UPG={ can:{name:'Watering Can',max:3,cost:[0,150,650],lvl:[1,3,6],desc:['Waters 1 plot','Waters a + shape (5 plots)','Waters a 3x3 area (9 plots)']}, hoe:{name:'Golden Hoe',max:2,cost:[400,1600],lvl:[4,9],desc:['35% chance of +1 seed','70% chance of +1 seed']}, basket:{name:'Big Basket',max:2,cost:[700,2500],lvl:[5,11],desc:['+1 produce per harvest','+2 produce per harvest']}, stall:{name:'Market Stall',max:2,cost:[900,3000],lvl:[7,12],desc:['Sell prices +20%','Sell prices +40%']}, lantern:{name:'Paper Lantern',max:1,cost:[500],lvl:[3],desc:['A glowing lantern for your hut. Orders give +10% coins']}, }; const WATER_TIME=[40,55,75]; const DRY_RATE=0.25, SEASON_BONUS=1.3; /* v1.2 simulation: crops wilt when dry too long, manure-fertilized crops grow faster and give bigger yields, off-season crops grow slowly and tender crops can't be planted in winter frost */ const WILT_T=30, FERT_GROW=1.4, FERT_YIELD=0.5, OFF_SEASON=0.6; const canPlantNow=(c,se)=>se!=='winter'||inSeason(c,'winter'); const NAMES=['Aunt Rose','Uncle Ben','Leo','Grace','Uncle Ray','Emma','Sam','Lily','Max','Grandpa','Grandma','Noah','Mia','Oliver']; // same order as v1.0 (orders store the index) const ACH=[ {id:'first',name:'First Harvest',desc:'Harvest your first plant',t:s=>s.stats.harvests>=1,r:20}, {id:'h50',name:'Busy Hands',desc:'Harvest 50 times',t:s=>s.stats.harvests>=50,r:100}, {id:'h250',name:'Green Thumb',desc:'Harvest 250 times',t:s=>s.stats.harvests>=250,r:400}, {id:'paddy',name:'Rice Farmer',desc:'Harvest rice 25 times',t:s=>(s.stats.by.paddy||0)>=25,r:150}, {id:'ord10',name:'Helpful Neighbor',desc:'Complete 10 orders',t:s=>s.ordersDone>=10,r:150}, {id:'ord40',name:'Village Hero',desc:'Complete 40 orders',t:s=>s.ordersDone>=40,r:600}, {id:'p12',name:'Growing Farm',desc:'Own 12 plots',t:s=>s.unlocked>=12,r:100}, {id:'p24',name:'Big Farm',desc:'Own all 24 plots',t:s=>s.unlocked>=24,r:800}, {id:'lv5',name:'Rising Farmer',desc:'Reach level 5',t:s=>s.level>=5,r:100}, {id:'lv10',name:'Skilled Farmer',desc:'Reach level 10',t:s=>s.level>=10,r:300}, {id:'lv15',name:'Farm Master',desc:'Reach level 15',t:s=>s.level>=15,r:800}, {id:'rich',name:'Full Pocket',desc:'Earn 5,000 coins in total',t:s=>s.stats.earned>=5000,r:250}, {id:'rain',name:'Rain Dancer',desc:'Harvest 10 times in the rain',t:s=>s.stats.rainH>=10,r:120}, {id:'night',name:'Night Owl',desc:'Harvest 10 times at night',t:s=>s.stats.nightH>=10,r:120}, {id:'tree',name:'Tree Planter',desc:'Plant 5 fruit trees',t:s=>s.stats.trees>=5,r:150}, {id:'coco',name:'Coconut Time',desc:'Harvest a Coconut',t:s=>(s.stats.by.coconut||0)>=1,r:300}, {id:'all',name:'Collector',desc:'Harvest every crop type',t:s=>CROPS.filter(c=>!c.fodder).every(c=>(s.stats.by[c.id]||0)>0),r:1000}, {id:'egg',name:'Fresh Eggs',desc:'Collect your first animal product',t:s=>(s.stats.collected||0)>=1,r:50}, {id:'feed100',name:'Animal Friend',desc:'Feed your animals 100 meals',t:s=>(s.stats.fed||0)>=100,r:300}, {id:'herd',name:'Happy Herd',desc:'Keep 4 animals in your yard',t:s=>(s.animals||[]).filter(a=>a).length>=4,r:250}, {id:'manure',name:'Manure Magic',desc:'Get 10 fertilizer from your animals',t:s=>(s.stats.manure||0)>=10,r:200}, {id:'feather',name:'Peacock Dance',desc:'Collect 5 Peacock Feathers',t:s=>((s.stats.byA||{}).peacock||0)>=5,r:300}, {id:'gentle',name:'Gentle Giant',desc:'Welcome an elephant to your yard',t:s=>(s.animals||[]).some(a=>a&&a.t==='elephant'),r:400}, ]; /* ---------------- Animals (v1.1) ---------------- Loop: grow crops -> make feed (Corn, Rice) -> animals make goods -> cows/buffalo/goats give manure (= Fertilizer) and bees pollinate -> better crops. */ const YARD_LVL=4, PENS=9, ELE_PEN=8, MEALS=3, STORE_CAP=3; // 8 pens + 1 big Elephant Enclosure (pen 8) const ANIMALS=[ {id:'chicken',name:'Chicken',prod:'egg',lvl:4,price:120,time:60,eat:1,size:0.92,desc:'Lays an egg after every meal'}, {id:'duck',name:'Duck',prod:'duckegg',lvl:5,price:220,time:80,eat:1,size:0.92,rain:true,desc:'Loves the rain: works faster when it rains'}, {id:'goat',name:'Goat',prod:'goatmilk',lvl:7,price:450,time:110,eat:2,size:0.92,manure:0.5,desc:'Goat milk, and sometimes manure for your plants'}, {id:'cow',name:'Cow',prod:'milk',lvl:9,price:700,time:140,eat:3,size:1.08,manure:1,desc:'Fresh milk + 1 manure (Fertilizer) each time'}, {id:'buffalo',name:'Buffalo',prod:'curd',lvl:11,price:950,time:180,eat:3,size:1.14,manure:1,desc:'Creamy buffalo curd + 1 manure (Fertilizer)'}, {id:'bees',name:'Bee Hive',prod:'honey',lvl:13,price:1200,time:200,eat:0,size:0.95,desc:'Bees visit your crops: +20% chance of an extra harvest'}, {id:'peacock',name:'Peacock',prod:'feather',lvl:14,price:1600,time:240,eat:2,size:0.95,desc:'Fans its tail when happy and drops a rare Peacock Feather'}, {id:'elephant',name:'Elephant',prod:'elegift',lvl:15,price:3000,time:300,eat:6,size:1,manure:3,big:true,max:1,rainOk:true,desc:'A gentle giant for the big enclosure. Showers all your crops with water and gives 3 manure'}, ]; const ANI={};ANIMALS.forEach(a=>ANI[a.id]=a); const PRODS=[ {id:'egg',name:'Egg',sell:12,xp:3,from:'chicken'},{id:'duckegg',name:'Duck Egg',sell:18,xp:4,from:'duck'},{id:'goatmilk',name:'Goat Milk',sell:32,xp:6,from:'goat'}, {id:'milk',name:'Milk',sell:45,xp:8,from:'cow'},{id:'curd',name:'Curd',sell:66,xp:11,from:'buffalo'},{id:'honey',name:'Honey',sell:80,xp:13,from:'bees'}, {id:'feather',name:'Peacock Feather',sell:130,xp:20,from:'peacock',rare:true},{id:'elegift',name:'Elephant Gift',sell:170,xp:28,from:'elephant',rare:true}]; const PROD={};PRODS.forEach(p=>PROD[p.id]=p); const itemDef=id=>CROP[id]||PROD[id]; const FEED_VAL={corn:2,paddy:1}; // feed made from 1 crop const FEED_SACKS=[[5,40],[20,140]]; // shop fallback: [feed, coins] (much pricier than growing corn) const aniPrice=id=>{const n=(S.animals||[]).filter(a=>a&&a.t===id).length;return Math.round(ANI[id].price*Math.pow(1.6,n)/5)*5;}; function newAnimal(id){return{t:id,meals:0,stored:0,prog:0,hap:70,ph:Math.random()*6,x:0.6,y:1,fx:1,wt:0};} /* v1.2 animal happiness 0..100: fed animals get happier, hungry ones get sad. Happiness speeds up (or slows) production and can give a bonus product. */ const hapMul=a=>0.6+0.7*clamp(a.hap==null?70:a.hap,0,100)/100; const hapWord=h=>h>=80?'Very happy':h>=55?'Happy':h>=30?'Okay':'Sad'; function aniRate(a,T){const d=ANI[a.t];let r=hapMul(a)/d.time;const night=isNight(T),rain=rainAt(T); const win=seasonAt(T)==='winter'; if(a.t==='bees'){if(night||rain)r*=0.3;if(win)r*=0.6;const pl=S.plots.filter((p,i)=>i<S.unlocked&&p.c).length;return r*(pl>=3?1:0.5);} if(night)r*=0.5;if(rain&&!d.rainOk)r*=d.rain&&!win?1.3:0.85;if(win)r*=0.9;return r;} const aniBusy=a=>a.stored<STORE_CAP&&(ANI[a.t].eat===0||a.meals>0); function aniStep(a,T,dt){if(a.hap==null)a.hap=70;if(!isNight(T)){const d=ANI[a.t];if(d.eat===0)a.hap=Math.min(100,a.hap+dt*0.03);else if(a.meals>0)a.hap=Math.min(100,a.hap+dt*0.02);else a.hap=Math.max(0,a.hap-dt*0.06);}if(!aniBusy(a))return;a.prog+=aniRate(a,T)*dt;if(a.prog>=1){a.prog=0;a.stored++;if(ANI[a.t].eat>0)a.meals--;}} /* ---------------- Time & world ---------------- */ let debugOffset=0; const now=()=>Date.now()/1000+debugOffset; const DAY=360, WPER=75; function hourAt(T){const f=((T%DAY)+DAY)%DAY/DAY;return f<0.72?6+f/0.72*13:(19+(f-0.72)/0.28*11)%24;} const dayNum=T=>Math.floor(T/DAY)+1; /* Four seasons (v1.1): Spring -> Summer -> Autumn -> Winter, 2 days each. S.seaOff (days) lets old saves keep a matching season. */ const SEASON_DAYS=2; const SEASONS=[ {id:'spring',name:'Spring',rain:0.3,msg:'Cherry blossoms are blooming!'}, {id:'summer',name:'Summer',rain:0.18,msg:'Long sunny days and fireflies at night.'}, {id:'autumn',name:'Autumn',rain:0.28,msg:'Maple leaves are turning red.'}, {id:'winter',name:'Winter',rain:0.32,msg:'Snow is falling. Snow waters your plots too!'}]; const SEA={};SEASONS.forEach((q,i)=>{q.i=i;SEA[q.id]=q;}); const seaX=T=>(T/DAY+((S&&S.seaOff)||0))/SEASON_DAYS; const seasonIdx=T=>((Math.floor(seaX(T))%4)+4)%4; const seasonAt=T=>SEASONS[seasonIdx(T)].id; const seasonProg=T=>{const q=seaX(T);return q-Math.floor(q);}; const inSeason=(c,se)=>c.season==='all'||c.season.includes(se); const WINTER_SLOW=0.8; // off-season crops grow a bit slower in winter (hardy crops are fine) function rainPer(p){if(p<2)return false;const s=SEA[seasonAt(p*WPER)];return hash(p*7919+13)<s.rain;} const snowAt=T=>seasonAt(T)==='winter'&&rainAt(T); // in winter, rain falls as snow const rainAt=T=>rainPer(Math.floor(T/WPER)); function rainAmt(T){const p=Math.floor(T/WPER),f=T/WPER-p;const r=rainPer(p)?1:0; if(f<0.1)return lerp((rainPer(p-1)?1:0)*0.5+r*0.5,r,f/0.1);if(f>0.9)return lerp(r,r*0.5+(rainPer(p+1)?1:0)*0.5,(f-0.9)/0.1);return r;} const isNight=T=>{const h=hourAt(T);return h>=19.3||h<5.2;}; function hotCrop(T,lvl){const un=CROPS.filter(c=>c.lvl<=lvl);return un[Math.floor(hash(dayNum(T)*313)*un.length)];} /* ---------------- State ---------------- */ let S=null; const SAVE_KEY='pelaGardens.save.v1', SET_KEY='pelaGardens.settings.v1'; let SET={music:0.55,sfx:0.8,muted:false,shake:true,timers:true}; function newState(){const t=now();const s={v:1,coins:60,xp:0,level:1,seeds:{chili:6,tomato:3},produce:{}, plots:Array.from({length:MAXPLOTS},()=>newPlot()), unlocked:START_PLOTS,up:{can:1,hoe:0,basket:0,stall:0,lantern:0},items:{fert:3,spr:0},orders:[],ordersDone:0, stats:{harvests:0,planted:0,earned:0,by:{},trees:0,rainH:0,nightH:0,collected:0,fed:0,manure:0,byA:{},showers:0},ach:{},tut:0,start:t-DAY*0.12,last:t,won:false,oid:1, animals:Array(PENS).fill(null),feed:0,aIntro:0,atut:0,seaOff:0,sv:5,farmer:{x:1.5,y:-0.1},mkt:{day:0,sold:{}},today:null}; // v1.2 hook: the farm starts with ripe chili ready to pick and a tomato already sprouting for(let k=0;k<3;k++)Object.assign(s.plots[k],{c:'chili',g:1,left:1});Object.assign(s.plots[3],{c:'tomato',g:0.55,left:1,wet:t+60}); s.stats.sold=0;s.stats.wilted=0;s.stats.fertUsed=0;s.stats.days=0;return s;} function newPlot(){return{c:null,g:0,wet:0,left:0,spr:false,ph:Math.random()*6,dry:0,wilt:0,fert:0,hurt:0};} function newToday(T){return{day:dayNum(T),harv:0,coins:0,sold:0,orders:0,goods:0,wilted:0,fed:0,xp:0};} const store={ // Works in browsers and Electron (localStorage persists in the app's userData folder). get(k){try{if(window.pelaNative&&window.pelaNative.load)return window.pelaNative.load(k);return localStorage.getItem(k);}catch(e){return null;}}, set(k,v){try{if(window.pelaNative&&window.pelaNative.save)window.pelaNative.save(k,v);else localStorage.setItem(k,v);}catch(e){}}, del(k){try{if(window.pelaNative&&window.pelaNative.remove)window.pelaNative.remove(k);else localStorage.removeItem(k);}catch(e){}}}; function save(){if(!S)return;S.last=now();store.set(SAVE_KEY,JSON.stringify(S));} function saveSet(){store.set(SET_KEY,JSON.stringify(SET));} function loadSet(){try{const j=JSON.parse(store.get(SET_KEY));if(j)Object.assign(SET,j);}catch(e){}} function loadSave(){try{const j=JSON.parse(store.get(SAVE_KEY));if(j&&j.v===1&&Array.isArray(j.plots)){const d=newState(),oldSv=j.sv||1;for(const k in d)if(j[k]===undefined)j[k]=d[k]; for(const k in d.stats)if(j.stats[k]===undefined)j.stats[k]=d.stats[k];for(const k in d.up)if(j.up[k]===undefined)j.up[k]=d.up[k]; while(j.plots.length<MAXPLOTS)j.plots.push(newPlot()); // v1.0 -> v1.1 migration: add the animal yard without touching crops, coins, orders or progress if(!Array.isArray(j.animals))j.animals=[];j.animals=j.animals.slice(0,PENS).map(a=>a&&ANI[a.t]?Object.assign(newAnimal(a.t),a):null);while(j.animals.length<PENS)j.animals.push(null); // v1.1 (6 pens) -> v1.1b (8 pens + Elephant Enclosure): keep every animal; only an elephant may live in the big enclosure j.animals.forEach((a,i)=>{if(!a)return;const big=!!ANI[a.t].big;if(big!==(i===ELE_PEN)){j.animals[i]=null;const k=big?(j.animals[ELE_PEN]?-1:ELE_PEN):j.animals.findIndex((b,q)=>!b&&q!==ELE_PEN);if(k>=0)j.animals[k]=a;}}); if(!j.items)j.items=d.items;if(typeof j.items.fert!=='number')j.items.fert=0;if(typeof j.feed!=='number')j.feed=0;if(!j.stats.byA)j.stats.byA={};if(typeof j.stats.showers!=='number')j.stats.showers=0; // old 2-season saves (v1.0 rainy / dry season) -> four seasons: rainy -> Spring, dry -> Summer, starting at the beginning of that season if(oldSv<4){const T=now()-j.start,old=Math.floor(T/(DAY*3))%2===0?'maha':'yala',tgt=old==='maha'?0:1,dn=Math.floor(T/DAY);j.seaOff=(((tgt*SEASON_DAYS-dn)%(4*SEASON_DAYS))+4*SEASON_DAYS)%(4*SEASON_DAYS);j.oldSeason=old;} if(typeof j.seaOff!=='number')j.seaOff=0; // v1.1 (sv4) -> v1.2 (sv5): crop care, animal happiness, market, farmer, day summary. Keeps every crop, coin, seed, animal and order. if(oldSv<5)migrateV12(j);j.sv=5;return j;}}catch(e){console.warn('save load failed',e);}return null;} function migrateV12(j){const T=now()-j.start; j.plots.forEach(p=>{if(typeof p.dry!=='number')p.dry=0;p.wilt=p.wilt?1:0;p.fert=p.fert?1:0;p.hurt=p.hurt?1:0;}); j.animals.forEach(a=>{if(a&&typeof a.hap!=='number')a.hap=a.meals>0?75:60;}); const dn=dayNum(T);(j.orders||[]).forEach(o=>{if(!o.empty){if(!o.due)o.due=dn+1;if(!o.posted)o.posted=dn;}}); if(!j.farmer)j.farmer={x:1.5,y:-0.1};if(!j.mkt)j.mkt={day:dn,sold:{}};j.today=null; ['sold','wilted','fertUsed','days'].forEach(k=>{if(typeof j.stats[k]!=='number')j.stats[k]=0;}); // old 7-step tutorial -> new 5-step tutorial (finished stays finished) if(typeof j.tut!=='number')j.tut=0;j.tut=j.tut>=7?5:j.tut>=5?3:j.tut>=1?1:0; j.migratedFrom=j.migratedFrom||'1.1';j.whatsNew=1;} /* ---------------- Grid ---------------- */ let COLS=6,ROWS=4,CELLS=[]; // CELLS[i]={c,r} function buildCells(){CELLS=[];const all=[];for(let r=0;r<ROWS;r++)for(let c=0;c<COLS;c++){const dx=c-(COLS-1)/2,dy=(r-(ROWS-1)/2)*1.25;all.push({c,r,d:dx*dx+dy*dy+r*0.01+c*0.001});} all.sort((a,b)=>a.d-b.d);CELLS=all;} function cellIndex(c,r){return CELLS.findIndex(o=>o.c===c&&o.r===r);} function neighbors(i,shape){const {c,r}=CELLS[i];const out=[];for(let dy=-1;dy<=1;dy++)for(let dx=-1;dx<=1;dx++){ if(shape==='plus'&&dx&&dy)continue;if(shape==='one'&&(dx||dy))continue;const j=cellIndex(c+dx,r+dy);if(j>=0)out.push(j);}return out;} function sprinklerNear(i){const {c,r}=CELLS[i];for(let dy=-1;dy<=1;dy++)for(let dx=-1;dx<=1;dx++){const j=cellIndex(c+dx,r+dy);if(j>=0&&j<S.unlocked&&S.plots[j].spr)return true;}return false;} let SPRMAP=[];function refreshSpr(){SPRMAP=S.plots.map((p,i)=>i<S.unlocked&&sprinklerNear(i));} /* ---------------- Simulation ---------------- */ // T is farm time (seconds since S.start); p.wet is an absolute timestamp function plotWet(p,i,T){return T+S.start<p.wet||SPRMAP[i]||rainAt(T);} function growRate(p,i,T){const c=CROP[p.c],se=seasonAt(T);if(p.wilt)return 0;let r=plotWet(p,i,T)?1:DRY_RATE;if(inSeason(c,se))r*=SEASON_BONUS;else r*=se==='winter'?OFF_SEASON*WINTER_SLOW:OFF_SEASON;if(p.fert)r*=FERT_GROW;return r/c.time;} const wiltOn=()=>!(typeof TUT!=='undefined'&&S.tut<TUT.length); function simulate(from,to){ // advance growth from time `from` to `to` (seconds) let t=from;while(t<to){const dt=Math.min(2,to-t);const raining=rainAt(t-S.start); for(let i=0;i<S.unlocked;i++){const p=S.plots[i];if(!p.c)continue;if(raining)p.wet=Math.max(p.wet,t+12); if(p.g<1){const T=t-S.start;if(plotWet(p,i,T)){if(p.wilt){p.wilt=0;p.hurt=1;}p.dry=0;} else if(!p.wilt&&wiltOn()){p.dry=(p.dry||0)+dt;if(p.dry>=WILT_T){p.wilt=1;S.stats.wilted=(S.stats.wilted||0)+1;if(S.today)S.today.wilted++;}} p.g=Math.min(1,p.g+growRate(p,i,T)*dt);}} if(S.animals){const T=t-S.start;for(const a of S.animals)if(a)aniStep(a,T,dt);} t+=dt;}} const stageOf=g=>g>=1?3:g>=0.4?2:g>=0.12?1:0; const STAGE_NAMES=['Seed','Sprout','Growing','Ready']; /* ---------------- Audio (all synthesized) ---------------- */ const AU={ctx:null,on:false, init(){if(this.ctx)return;const AC=window.AudioContext||window.webkitAudioContext;if(!AC)return;const c=this.ctx=new AC(); this.master=c.createGain();this.master.connect(c.destination); this.comp=c.createDynamicsCompressor();this.comp.threshold.value=-14;this.comp.connect(this.master); this.mus=c.createGain();this.sfx=c.createGain();this.mus.connect(this.comp);this.sfx.connect(this.comp); this.rev=c.createConvolver();const len=c.sampleRate*2.4,b=c.createBuffer(2,len,c.sampleRate); for(let ch=0;ch<2;ch++){const d=b.getChannelData(ch);for(let i=0;i<len;i++)d[i]=(Math.random()*2-1)*Math.pow(1-i/len,3);} this.rev.buffer=b;this.revG=c.createGain();this.revG.gain.value=0.35;this.rev.connect(this.revG);this.revG.connect(this.comp); const nb=c.createBuffer(1,c.sampleRate*2,c.sampleRate),nd=nb.getChannelData(0);for(let i=0;i<nd.length;i++)nd[i]=Math.random()*2-1;this.noiseBuf=nb; // rain ambience loop const rs=c.createBufferSource();rs.buffer=nb;rs.loop=true;const rf=c.createBiquadFilter();rf.type='lowpass';rf.frequency.value=1400; this.rainG=c.createGain();this.rainG.gain.value=0;rs.connect(rf);rf.connect(this.rainG);this.rainG.connect(this.sfx);rs.start(); this.applyVol();this.on=true;MUSIC.start();}, applyVol(){if(!this.ctx)return;const m=SET.muted?0:1;const t=this.ctx.currentTime; this.mus.gain.setTargetAtTime(SET.music*0.55*m,t,0.1);this.sfx.gain.setTargetAtTime(SET.sfx*m,t,0.05);}, resume(){if(this.ctx&&this.ctx.state!=='running')this.ctx.resume();}, tone(f,dur,o={}){if(!this.on)return;const c=this.ctx,t=(o.when||c.currentTime)+(o.delay||0);const os=c.createOscillator(),g=c.createGain(); os.type=o.type||'sine';os.frequency.setValueAtTime(f,t);if(o.slide)os.frequency.exponentialRampToValueAtTime(o.slide,t+dur);if(o.det)os.detune.value=o.det; const v=o.vol||0.2,a=o.att||0.005;g.gain.setValueAtTime(0.0001,t);g.gain.linearRampToValueAtTime(v,t+a);g.gain.exponentialRampToValueAtTime(0.0001,t+dur); os.connect(g);const dst=o.dest||this.sfx;g.connect(dst);if(o.rev){const rg=c.createGain();rg.gain.value=o.rev;g.connect(rg);rg.connect(this.rev);} os.start(t);os.stop(t+dur+0.05);}, noise(dur,o={}){if(!this.on)return;const c=this.ctx,t=c.currentTime+(o.delay||0);const s=c.createBufferSource();s.buffer=this.noiseBuf; const f=c.createBiquadFilter();f.type=o.ft||'bandpass';f.frequency.setValueAtTime(o.f||1000,t);if(o.slide)f.frequency.exponentialRampToValueAtTime(o.slide,t+dur);f.Q.value=o.q||1; const g=c.createGain(),v=o.vol||0.2;g.gain.setValueAtTime(0.0001,t);g.gain.linearRampToValueAtTime(v,t+(o.att||0.01));g.gain.exponentialRampToValueAtTime(0.0001,t+dur); s.connect(f);f.connect(g);g.connect(o.dest||this.sfx);s.start(t,Math.random());s.stop(t+dur+0.05);}, click(){this.tone(880,0.06,{vol:0.08,type:'triangle'});this.tone(1320,0.05,{vol:0.04,delay:0.02});}, select(){this.tone(660,0.08,{vol:0.1,type:'triangle',slide:990});}, plant(){this.noise(0.18,{ft:'lowpass',f:500,vol:0.35});this.tone(200,0.18,{type:'sine',slide:120,vol:0.25});this.tone(523,0.25,{type:'triangle',vol:0.08,delay:0.05,rev:0.3});}, water(){this.noise(0.45,{f:2600,slide:700,q:0.8,vol:0.22});for(let i=0;i<4;i++)this.tone(rand(700,1400),0.08,{vol:0.07,delay:0.05+i*0.07,slide:rand(1500,2200)});}, harvest(combo){const sc=[0,2,4,7,9,12,14,16,19,21,24];const n=72+sc[Math.min(combo,sc.length-1)];const f=440*Math.pow(2,(n-69)/12); this.tone(300,0.1,{slide:900,vol:0.2});this.noise(0.08,{f:3000,vol:0.1});this.tone(f,0.5,{type:'triangle',vol:0.13,delay:0.04,rev:0.5});this.tone(f*2,0.35,{vol:0.05,delay:0.04,rev:0.5});}, coin(d=0){this.tone(1568,0.07,{type:'square',vol:0.035,delay:d});this.tone(2093,0.3,{type:'triangle',vol:0.08,delay:d+0.06,rev:0.3});}, buy(){this.coin();this.coin(0.08);this.noise(0.25,{f:1500,slide:5000,vol:0.08,delay:0.05});}, err(){this.tone(196,0.15,{type:'square',vol:0.05});this.tone(165,0.2,{type:'square',vol:0.05,delay:0.1});}, deliver(){[0,4,7,12].forEach((s,i)=>this.tone(523*Math.pow(2,s/12),0.4,{type:'triangle',vol:0.12,delay:i*0.08,rev:0.5}));}, level(){[0,4,7,12,16,19,24].forEach((s,i)=>{this.tone(523*Math.pow(2,s/12),0.6,{type:'triangle',vol:0.12,delay:i*0.07,rev:0.6});this.tone(1046*Math.pow(2,s/12),0.3,{vol:0.04,delay:i*0.07+0.03});});}, fert(){this.noise(0.4,{f:4000,slide:8000,vol:0.08});[0,7,12].forEach((s,i)=>this.tone(880*Math.pow(2,s/12),0.3,{vol:0.07,delay:i*0.06,rev:0.5}));}, pop(){this.tone(500,0.08,{slide:1100,vol:0.12});}, chirp(){const b=rand(2600,3800);for(let i=0;i<randi(2,4);i++)this.tone(b,0.07,{slide:b*rand(1.2,1.5),vol:0.025,delay:i*0.11});}, animal(id){const T=(f,d,o)=>this.tone(f,d,o); if(id==='chicken'){[0,0.09,0.18].forEach((d,i)=>T(i===2?720:620,0.07,{type:'square',vol:0.04,delay:d,slide:i===2?980:520}));} else if(id==='duck'){[0,0.14].forEach(d=>{T(380,0.12,{type:'sawtooth',vol:0.05,delay:d,slide:300});T(760,0.1,{type:'square',vol:0.02,delay:d});});} else if(id==='goat'){for(let i=0;i<5;i++)T(520+(i%2)*40,0.07,{type:'triangle',vol:0.07,delay:i*0.06});} else if(id==='cow'||id==='buffalo'){const b=id==='cow'?150:118;T(b,0.75,{type:'sawtooth',vol:0.05,slide:b*0.8,att:0.12});T(b*2,0.7,{type:'triangle',vol:0.04,slide:b*1.7,att:0.15});} else if(id==='peacock'){[[0,620,1150,0.34],[0.38,980,640,0.46]].forEach(q=>{T(q[1],q[3],{type:'sawtooth',vol:0.035,delay:q[0],slide:q[2],att:0.03});T(q[1]*2,q[3]*0.9,{type:'triangle',vol:0.03,delay:q[0],slide:q[2]*2});});} else if(id==='elephant'){T(260,0.25,{type:'sawtooth',vol:0.05,slide:420,att:0.04});T(420,0.9,{type:'sawtooth',vol:0.06,delay:0.2,slide:560,att:0.05,rev:0.5});T(840,0.85,{type:'square',vol:0.018,delay:0.22,slide:1100});this.noise(0.6,{f:900,q:3,vol:0.05,delay:0.2});} else{this.noise(0.5,{f:220,q:8,vol:0.12});T(230,0.5,{type:'sawtooth',vol:0.02,slide:250});}}, cicada(){for(let i=0;i<3;i++)this.noise(0.9,{f:5200+i*300,q:14,vol:0.035,delay:i*0.5,att:0.25});}, crunch(){for(let i=0;i<3;i++)this.noise(0.05,{f:rand(1800,3200),vol:0.12,delay:i*0.07});}, cricket(){for(let i=0;i<6;i++)this.tone(4600,0.03,{vol:0.012,delay:i*0.05,type:'triangle'});}, }; const MUSIC={step:0,next:0,timer:null,bpm:80, start(){if(this.timer)return;const rng=mulberry(20261019); // pre-compose a 16-bar theme (pentatonic) so the loop is consistent const scale=[60,62,64,67,69,72,74,76,79];this.mel=[];let idx=4; const rhythms=[[1,0,1,0,1,0,0,0],[1,0,0,1,0,0,1,0],[1,1,0,1,0,1,0,0],[1,0,0,0,1,0,1,1],[0,0,1,0,1,0,1,0]]; for(let bar=0;bar<16;bar++){const rh=rhythms[Math.floor(rng()*rhythms.length)];for(let s=0;s<8;s++){ if(rh[s]&&!(bar%4===3&&s>4)){idx=clamp(idx+Math.round((rng()-0.5)*4),0,scale.length-1);this.mel.push(scale[idx]);}else this.mel.push(0);}} this.next=AU.ctx.currentTime+0.2;this.timer=setInterval(()=>this.tick(),90);}, chords:[[48,55,64,67],[45,52,60,64],[41,48,57,60],[43,50,59,62]], tick(){const c=AU.ctx;if(!c||SET.muted||SET.music<=0.001){if(c)this.next=Math.max(this.next,c.currentTime);return;} const e=60/this.bpm/2;const night=S?isNight(now()-S.start):false; while(this.next<c.currentTime+0.35){const st=this.step%128,bar=Math.floor(st/8),s=st%8,ch=this.chords[bar%4],w=this.next; const m=n=>440*Math.pow(2,(n-69)/12); if(s===0){ch.forEach((n,k)=>{AU.tone(m(n+12),e*8.5,{type:k%2?'sine':'triangle',vol:0.028,att:0.6,dest:AU.mus,when:w,rev:0.6,det:k*4-6});}); AU.tone(m(ch[0]-12),e*3,{vol:0.13,att:0.01,dest:AU.mus,when:w});} if(s===4)AU.tone(m(ch[0]-12+7),e*2.5,{vol:0.09,dest:AU.mus,when:w}); const n=this.mel[st];if(n&&(!night||s%2===0)){const f=m(night?n-12:n);AU.tone(f,e*3.2,{vol:night?0.06:0.075,dest:AU.mus,when:w,rev:0.7});AU.tone(f*4,e*0.8,{vol:0.012,dest:AU.mus,when:w});} if(!night&&s%2===1&&bar>=4){ /* soft shaker */ const t=w;const src=c.createBufferSource();src.buffer=AU.noiseBuf;const f=c.createBiquadFilter();f.type='highpass';f.frequency.value=7000;const g=c.createGain(); g.gain.setValueAtTime(0.0001,t);g.gain.linearRampToValueAtTime(0.018,t+0.01);g.gain.exponentialRampToValueAtTime(0.0001,t+0.08);src.connect(f);f.connect(g);g.connect(AU.mus);src.start(t,Math.random());src.stop(t+0.1);} this.next+=e;this.step++;}} }; /* ---------------- Art: produce ---------------- */ function rgrad(c,x,y,r,stops,ox=-0.35,oy=-0.4){const g=c.createRadialGradient(x+r*ox,y+r*oy,r*0.05,x,y,r*1.05);stops.forEach((s,i)=>g.addColorStop(s[0],s[1]));return g;} function shine(c,x,y,rx,ry,a=0.55){c.fillStyle=`rgba(255,255,255,${a})`;c.beginPath();c.ellipse(x,y,rx,ry,-0.6,0,TAU);c.fill();} function leaf(c,x,y,len,wid,ang,col,vein=true){c.save();c.translate(x,y);c.rotate(ang);c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(len*0.45,-wid,len,0);c.quadraticCurveTo(len*0.45,wid,0,0);c.fillStyle=col;c.fill(); if(vein&&len>6){c.strokeStyle='rgba(255,255,255,0.22)';c.lineWidth=Math.max(1,len*0.035);c.beginPath();c.moveTo(len*0.05,0);c.quadraticCurveTo(len*0.5,-wid*0.08,len*0.9,0);c.stroke();}c.restore();} const UNRIPE='#86c450'; function ripeMix(col,ripe){return rgb(mixc(hex(UNRIPE),hex(col),ripe));} function drawProduce(c,id,x,y,r,ripe=1,rot=0){c.save();c.translate(x,y);c.rotate(rot); const R=ripe; switch(id){ case 'chili':{c.rotate(0.35);c.beginPath();c.moveTo(-r*0.3,-r*0.75);c.bezierCurveTo(r*0.55,-r*0.75,r*0.45,r*0.45,-r*0.05,r*1.05);c.bezierCurveTo(r*0.05,r*0.35,-r*0.15,-r*0.2,-r*0.55,-r*0.55);c.closePath(); const g=c.createLinearGradient(-r*0.5,0,r*0.5,0);g.addColorStop(0,ripeMix('#ff5a3a',R));g.addColorStop(1,ripeMix('#c0141a',R));c.fillStyle=g;c.fill(); c.strokeStyle='rgba(255,255,255,0.5)';c.lineWidth=r*0.1;c.lineCap='round';c.beginPath();c.moveTo(-r*0.15,-r*0.5);c.quadraticCurveTo(r*0.2,-r*0.3,r*0.1,r*0.2);c.stroke(); c.fillStyle='#3f8a2a';c.beginPath();c.ellipse(-r*0.38,-r*0.66,r*0.28,r*0.16,-0.3,0,TAU);c.fill();c.strokeStyle='#3f8a2a';c.lineWidth=r*0.12;c.beginPath();c.moveTo(-r*0.4,-r*0.7);c.quadraticCurveTo(-r*0.5,-r*1.0,-r*0.25,-r*1.1);c.stroke();break;} case 'tomato':{c.fillStyle=rgrad(c,0,0,r,[[0,ripeMix('#ff8a6a',R)],[0.55,ripeMix('#ec3a2a',R)],[1,ripeMix('#b01e18',R)]]);c.beginPath();c.ellipse(0,0,r*0.95,r*0.85,0,0,TAU);c.fill(); shine(c,-r*0.35,-r*0.32,r*0.22,r*0.13);c.fillStyle='#3f8a2a';c.beginPath();for(let i=0;i<10;i++){const a=i/10*TAU-Math.PI/2,rr=i%2?r*0.14:r*0.42;c.lineTo(Math.cos(a)*rr,-r*0.72+Math.sin(a)*rr*0.5);}c.fill(); c.fillRect(-r*0.05,-r*1.0,r*0.1,r*0.3);break;} case 'paddy':{const gc=ripeMix('#f2c23a',R);c.strokeStyle=ripeMix('#d8a52a',R);c.lineWidth=r*0.09;c.lineCap='round'; for(let i=-3;i<=3;i++){c.beginPath();c.moveTo(i*r*0.06,r*0.95);c.quadraticCurveTo(i*r*0.1,-r*0.1,i*r*0.25+r*0.2,-r*0.75);c.stroke();} c.fillStyle=gc;for(let i=-3;i<=3;i++)for(let k=0;k<4;k++){const tx=i*r*0.22+r*0.2+k*r*0.06,ty=-r*0.55-k*r*0.15+Math.abs(i)*r*0.05;c.beginPath();c.ellipse(tx,ty,r*0.07,r*0.12,0.5,0,TAU);c.fill();} c.fillStyle='#b5651d';c.fillRect(-r*0.32,r*0.3,r*0.64,r*0.16);break;} case 'brinjal':{c.rotate(0.5);c.fillStyle=rgrad(c,0,r*0.2,r,[[0,ripeMix('#b07ae0',R)],[0.5,ripeMix('#6a2fa0',R)],[1,ripeMix('#3a1560',R)]]);c.beginPath();c.moveTo(0,-r*0.6);c.bezierCurveTo(r*0.55,-r*0.6,r*0.7,r*1.0,0,r*1.0);c.bezierCurveTo(-r*0.7,r*1.0,-r*0.55,-r*0.6,0,-r*0.6);c.fill(); shine(c,-r*0.22,r*0.05,r*0.1,r*0.28,0.45);c.fillStyle='#4e9a32';c.beginPath();c.moveTo(-r*0.4,-r*0.45);c.quadraticCurveTo(0,-r*0.85,r*0.4,-r*0.45);c.quadraticCurveTo(0,-r*0.25,-r*0.4,-r*0.45);c.fill();c.fillRect(-r*0.07,-r*1.0,r*0.14,r*0.4);break;} case 'banana':{c.strokeStyle='#7a6a2a';c.lineWidth=r*0.14;c.beginPath();c.moveTo(0,-r*0.9);c.lineTo(0,-r*0.4);c.stroke(); for(let i=-1;i<=1;i++){c.save();c.rotate(i*0.45);c.beginPath();c.moveTo(0,-r*0.45);c.bezierCurveTo(r*0.6,-r*0.4,r*0.55,r*0.6,r*0.05,r*0.95);c.bezierCurveTo(r*0.3,r*0.4,r*0.25,-r*0.15,-r*0.12,-r*0.35);c.closePath(); const g=c.createLinearGradient(0,0,r*0.6,0);g.addColorStop(0,ripeMix('#fff07a',R));g.addColorStop(1,ripeMix('#f0b51c',R));c.fillStyle=g;c.fill();c.fillStyle='#6a4a1a';c.beginPath();c.arc(r*0.07,r*0.93,r*0.06,0,TAU);c.fill();c.restore();}break;} case 'pineapple':{for(let i=0;i<7;i++){const a=-Math.PI/2+(i-3)*0.32;leaf(c,0,-r*0.55,r*(0.75-Math.abs(i-3)*0.1),r*0.12,a,i%2?'#3f8a4a':'#5aa85a',false);} c.save();c.beginPath();c.ellipse(0,r*0.2,r*0.6,r*0.8,0,0,TAU);c.fillStyle=rgrad(c,0,r*0.2,r*0.8,[[0,ripeMix('#ffd75a',R)],[0.6,ripeMix('#f0a020',R)],[1,ripeMix('#b8680a',R)]]);c.fill();c.clip(); c.strokeStyle='rgba(120,60,0,0.45)';c.lineWidth=r*0.05;for(let k=-4;k<=4;k++){c.beginPath();c.moveTo(k*r*0.28-r,-r);c.lineTo(k*r*0.28+r,r*1.4);c.stroke();c.beginPath();c.moveTo(k*r*0.28+r,-r);c.lineTo(k*r*0.28-r,r*1.4);c.stroke();}c.restore(); shine(c,-r*0.22,-r*0.05,r*0.1,r*0.22,0.35);break;} case 'rambutan':{c.strokeStyle=ripeMix('#d02a3a',R);c.lineWidth=r*0.09;c.lineCap='round';for(let i=0;i<26;i++){const a=i/26*TAU;c.beginPath();c.moveTo(Math.cos(a)*r*0.6,Math.sin(a)*r*0.6);c.quadraticCurveTo(Math.cos(a+0.2)*r*0.95,Math.sin(a+0.2)*r*0.95,Math.cos(a+0.35)*r*1.02,Math.sin(a+0.35)*r*1.02);c.stroke();} c.fillStyle=R>0.9?'#b8d84a':'#9ac84a';for(let i=0;i<26;i++){const a=i/26*TAU+0.35;c.beginPath();c.arc(Math.cos(a)*r*1.0,Math.sin(a)*r*1.0,r*0.05,0,TAU);c.fill();} c.fillStyle=rgrad(c,0,0,r*0.7,[[0,ripeMix('#ff6a6a',R)],[0.6,ripeMix('#e02a3a',R)],[1,ripeMix('#a01020',R)]]);c.beginPath();c.arc(0,0,r*0.7,0,TAU);c.fill();shine(c,-r*0.25,-r*0.25,r*0.16,r*0.1);break;} case 'mango':{c.rotate(0.25);c.beginPath();c.moveTo(0,-r*0.8);c.bezierCurveTo(r*0.85,-r*0.85,r*0.85,r*0.9,0,r*0.9);c.bezierCurveTo(-r*0.75,r*0.9,-r*0.65,-r*0.2,-r*0.2,-r*0.6);c.closePath(); const g=c.createLinearGradient(-r*0.6,-r*0.7,r*0.6,r*0.8);g.addColorStop(0,R>0.5?'#ff6a3a':'#7aba3a');g.addColorStop(0.45,ripeMix('#ffb02a',R));g.addColorStop(1,ripeMix('#ffd84a',R*0.9));c.fillStyle=g;c.fill(); shine(c,-r*0.25,-r*0.3,r*0.12,r*0.25,0.4);c.strokeStyle='#5a3a1a';c.lineWidth=r*0.1;c.beginPath();c.moveTo(-r*0.1,-r*0.7);c.lineTo(-r*0.15,-r*1.0);c.stroke();leaf(c,-r*0.15,-r*0.95,r*0.7,r*0.2,-0.3,'#3f8a2a');break;} case 'jackfruit':{c.beginPath();c.ellipse(0,0,r*0.7,r*0.95,0,0,TAU);c.fillStyle=rgrad(c,0,0,r*0.95,[[0,ripeMix('#e8e05a',R)],[0.6,ripeMix('#b8c43a',R)],[1,ripeMix('#7a8a20',R)]]);c.fill();c.save();c.clip(); c.fillStyle='rgba(90,100,20,0.35)';for(let yy=-6;yy<=6;yy++)for(let xx=-4;xx<=4;xx++){c.beginPath();c.arc(xx*r*0.17+(yy%2)*r*0.085,yy*r*0.16,r*0.045,0,TAU);c.fill();}c.restore(); shine(c,-r*0.25,-r*0.35,r*0.12,r*0.25,0.35);c.fillStyle='#6a4a20';c.fillRect(-r*0.07,-r*1.15,r*0.14,r*0.25);break;} case 'coconut':{c.fillStyle=rgrad(c,0,0,r,[[0,ripeMix('#ffc56a',R)],[0.55,ripeMix('#f5901e',R)],[1,ripeMix('#c4600a',R)]]);c.beginPath();c.ellipse(0,r*0.05,r*0.88,r*0.92,0,0,TAU);c.fill(); shine(c,-r*0.32,-r*0.3,r*0.2,r*0.12);c.fillStyle='#8a5a2a';c.beginPath();for(let i=0;i<8;i++){const a=i/8*TAU,rr=i%2?r*0.1:r*0.26;c.lineTo(Math.cos(a)*rr,-r*0.8+Math.sin(a)*rr*0.5);}c.fill();break;} case 'corn':{c.rotate(0.3);[[-1,-0.55],[1,-0.4]].forEach(q=>{c.fillStyle=q[0]<0?'#7bc04a':'#5aa83a';c.beginPath();c.moveTo(0,r*0.9);c.quadraticCurveTo(q[0]*r*0.75,r*0.2,q[0]*r*0.25,q[1]*r);c.quadraticCurveTo(q[0]*r*0.3,r*0.2,0,r*0.9);c.fill();}); c.beginPath();c.ellipse(0,-r*0.05,r*0.36,r*0.82,0,0,TAU);c.fillStyle=rgrad(c,0,-r*0.05,r*0.8,[[0,ripeMix('#fff3a0',R)],[0.55,ripeMix('#ffd23a',R)],[1,ripeMix('#e8a010',R)]]);c.fill(); c.save();c.clip();c.fillStyle='rgba(200,120,0,0.28)';for(let yy=-6;yy<=5;yy++)for(let xx=-2;xx<=2;xx++){c.beginPath();c.arc(xx*r*0.15+(yy%2?r*0.075:0),yy*r*0.14-r*0.05,r*0.04,0,TAU);c.fill();}c.restore(); shine(c,-r*0.12,-r*0.4,r*0.07,r*0.2,0.5);c.fillStyle='#8ad05a';c.beginPath();c.moveTo(-r*0.3,r*0.55);c.quadraticCurveTo(-r*0.45,-r*0.2,-r*0.1,-r*0.6);c.quadraticCurveTo(-r*0.2,0,0,r*0.8);c.fill(); c.strokeStyle='#e8c070';c.lineWidth=r*0.05;c.lineCap='round';c.beginPath();c.moveTo(0,-r*0.85);c.quadraticCurveTo(r*0.1,-r*1.05,r*0.05,-r*1.15);c.moveTo(0,-r*0.85);c.quadraticCurveTo(-r*0.12,-r*1.0,-r*0.14,-r*1.1);c.stroke();break;} case 'egg':case 'duckegg':{const duck=id==='duckegg';c.fillStyle=rgrad(c,0,0,r,duck?[[0,'#fbfff8'],[0.6,'#d6efe2'],[1,'#a8cfbc']]:[[0,'#fff3e0'],[0.6,'#f2c896'],[1,'#c98a52']]); c.beginPath();c.moveTo(0,-r*0.95);c.bezierCurveTo(r*0.72,-r*0.95,r*0.82,r*0.85,0,r*0.85);c.bezierCurveTo(-r*0.82,r*0.85,-r*0.72,-r*0.95,0,-r*0.95);c.fill(); if(duck){c.fillStyle='rgba(90,140,120,0.25)';[[0.2,-0.2],[-0.25,0.2],[0.25,0.4]].forEach(q=>{c.beginPath();c.arc(q[0]*r,q[1]*r,r*0.07,0,TAU);c.fill();});}shine(c,-r*0.25,-r*0.4,r*0.14,r*0.24,0.6);break;} case 'goatmilk':case 'milk':{const goat=id==='goatmilk';const lab=goat?'#7bd04a':'#5aa8ec';c.fillStyle='#fff';c.strokeStyle='rgba(120,140,170,0.6)';c.lineWidth=r*0.06; c.beginPath();c.moveTo(-r*0.18,-r*0.85);c.lineTo(r*0.18,-r*0.85);c.lineTo(r*0.2,-r*0.55);c.quadraticCurveTo(r*0.55,-r*0.35,r*0.55,0);c.lineTo(r*0.55,r*0.75);c.quadraticCurveTo(r*0.55,r*0.95,r*0.35,r*0.95);c.lineTo(-r*0.35,r*0.95);c.quadraticCurveTo(-r*0.55,r*0.95,-r*0.55,r*0.75);c.lineTo(-r*0.55,0);c.quadraticCurveTo(-r*0.55,-r*0.35,-r*0.2,-r*0.55);c.closePath();c.fill();c.stroke(); c.fillStyle=lab;roundRect(c,-r*0.55,-r*0.05,r*1.1,r*0.6,r*0.1);c.fill();c.fillStyle='#fff';if(goat){c.beginPath();c.ellipse(0,r*0.25,r*0.2,r*0.16,0,0,TAU);c.fill();c.strokeStyle='#fff';c.lineWidth=r*0.06;c.beginPath();c.moveTo(-r*0.12,r*0.12);c.quadraticCurveTo(-r*0.25,-r*0.02,-r*0.3,r*0.05);c.moveTo(r*0.12,r*0.12);c.quadraticCurveTo(r*0.25,-r*0.02,r*0.3,r*0.05);c.stroke();} else{c.beginPath();c.moveTo(0,r*0.05);c.bezierCurveTo(r*0.2,r*0.25,r*0.15,r*0.45,0,r*0.45);c.bezierCurveTo(-r*0.15,r*0.45,-r*0.2,r*0.25,0,r*0.05);c.fill();} c.fillStyle=goat?'#5aa83a':'#e9573f';roundRect(c,-r*0.24,-r*1.0,r*0.48,r*0.2,r*0.06);c.fill();shine(c,-r*0.32,-r*0.25,r*0.07,r*0.16,0.7);break;} case 'curd':{c.fillStyle=rgrad(c,0,r*0.2,r,[[0,'#e8955a'],[0.6,'#c0602e'],[1,'#8a3e1a']]);c.beginPath();c.moveTo(-r*0.75,-r*0.35);c.quadraticCurveTo(-r*0.95,r*0.5,-r*0.35,r*0.85);c.lineTo(r*0.35,r*0.85);c.quadraticCurveTo(r*0.95,r*0.5,r*0.75,-r*0.35);c.closePath();c.fill(); c.fillStyle='#fffaf0';c.beginPath();c.ellipse(0,-r*0.38,r*0.8,r*0.24,0,0,TAU);c.fill();c.strokeStyle='#a84e22';c.lineWidth=r*0.1;c.stroke();c.fillStyle='#fff';c.beginPath();c.ellipse(-r*0.1,-r*0.45,r*0.42,r*0.1,0,0,TAU);c.fill(); c.fillStyle='#ffc84a';c.beginPath();c.ellipse(r*0.32,-r*0.38,r*0.16,r*0.06,0,0,TAU);c.fill();c.strokeStyle='rgba(255,220,180,0.5)';c.lineWidth=r*0.05;c.beginPath();c.moveTo(-r*0.7,r*0.1);c.quadraticCurveTo(0,r*0.25,r*0.7,r*0.1);c.stroke();break;} case 'honey':{c.fillStyle=rgrad(c,0,r*0.15,r,[[0,'#ffe680'],[0.55,'#f8b21c'],[1,'#c87400']]);roundRect(c,-r*0.62,-r*0.5,r*1.24,r*1.38,r*0.3);c.fill();shine(c,-r*0.32,-r*0.1,r*0.08,r*0.28,0.6); c.fillStyle='#fff4dc';roundRect(c,-r*0.72,-r*0.82,r*1.44,r*0.38,r*0.12);c.fill();c.strokeStyle='#e0503a';c.lineWidth=r*0.07;c.setLineDash([r*0.12,r*0.1]);c.beginPath();c.moveTo(-r*0.7,-r*0.48);c.lineTo(r*0.7,-r*0.48);c.stroke();c.setLineDash([]); c.fillStyle='#f8b21c';c.beginPath();c.moveTo(-r*0.2,-r*0.5);c.quadraticCurveTo(-r*0.2,-r*0.1,-r*0.1,-r*0.05);c.quadraticCurveTo(0,-r*0.1,0,-r*0.5);c.fill(); c.fillStyle='#8a4a00';c.font=`700 ${r*0.5}px Fredoka`;c.textAlign='center';c.textBaseline='middle';c.fillText('♥',r*0.05,r*0.35);break;} case 'feather':{c.rotate(0.55);const vg=c.createLinearGradient(0,r*0.95,0,-r*0.95);vg.addColorStop(0,'#2f7a3a');vg.addColorStop(0.55,'#3fae5a');vg.addColorStop(1,'#1f8a8a');c.fillStyle=vg; c.beginPath();c.moveTo(0,r*0.6);c.quadraticCurveTo(-r*0.5,r*0.1,-r*0.42,-r*0.45);c.quadraticCurveTo(-r*0.3,-r*0.98,0,-r*0.98);c.quadraticCurveTo(r*0.3,-r*0.98,r*0.42,-r*0.45);c.quadraticCurveTo(r*0.5,r*0.1,0,r*0.6);c.fill(); c.strokeStyle='rgba(200,255,200,0.45)';c.lineWidth=r*0.03;for(let k=-3;k<=3;k++){if(!k)continue;c.beginPath();c.moveTo(0,r*0.3-Math.abs(k)*r*0.05);c.lineTo(k*r*0.14,-r*0.1-Math.abs(k)*r*0.06);c.stroke();} [[r*0.34,'#e8c040'],[r*0.25,'#1aa6a0'],[r*0.15,'#1a2a7a']].forEach(q=>{c.fillStyle=q[1];c.beginPath();c.ellipse(0,-r*0.55,q[0]*0.85,q[0],0,0,TAU);c.fill();}); c.fillStyle='#5a3aa0';c.beginPath();c.ellipse(0,-r*0.52,r*0.07,r*0.09,0,0,TAU);c.fill(); c.strokeStyle='#f6ecd0';c.lineWidth=r*0.07;c.lineCap='round';c.beginPath();c.moveTo(0,r*0.98);c.lineTo(0,-r*0.3);c.stroke();shine(c,-r*0.16,-r*0.66,r*0.06,r*0.14,0.6);break;} case 'elegift':{c.fillStyle='#ffd23a';c.beginPath();c.ellipse(-r*0.4,-r*0.28,r*0.2,r*0.42,-0.7,0,TAU);c.fill(); c.fillStyle=rgrad(c,r*0.2,-r*0.35,r*0.3,[[0,'#ffc070'],[1,'#ef7a1a']]);c.beginPath();c.arc(r*0.22,-r*0.32,r*0.3,0,TAU);c.fill(); c.fillStyle=rgrad(c,-r*0.05,-r*0.24,r*0.24,[[0,'#ff8a7a'],[1,'#d8302a']]);c.beginPath();c.arc(-r*0.06,-r*0.22,r*0.24,0,TAU);c.fill(); c.fillStyle='#ff9ac0';[-0.9,-0.45,0,0.45,0.9].forEach(a=>{c.save();c.translate(r*0.48,-r*0.58);c.rotate(a);c.beginPath();c.ellipse(0,-r*0.14,r*0.08,r*0.17,0,0,TAU);c.fill();c.restore();});c.fillStyle='#ffe14a';c.beginPath();c.arc(r*0.48,-r*0.6,r*0.06,0,TAU);c.fill(); c.fillStyle=rgrad(c,0,r*0.3,r,[[0,'#e2a868'],[0.6,'#c07a3a'],[1,'#8a4e1e']]);c.beginPath();c.moveTo(-r*0.9,-r*0.1);c.lineTo(r*0.9,-r*0.1);c.quadraticCurveTo(r*0.8,r*0.85,r*0.4,r*0.88);c.lineTo(-r*0.4,r*0.88);c.quadraticCurveTo(-r*0.8,r*0.85,-r*0.9,-r*0.1);c.fill(); c.strokeStyle='rgba(110,60,20,0.45)';c.lineWidth=r*0.05;for(let k=1;k<4;k++){c.beginPath();c.moveTo(-r*0.86+k*0.02*r,-r*0.1+k*r*0.24);c.lineTo(r*0.86-k*0.02*r,-r*0.1+k*r*0.24);c.stroke();} for(let k=-3;k<=3;k++){c.beginPath();c.moveTo(k*r*0.24,-r*0.08);c.lineTo(k*r*0.17,r*0.86);c.stroke();} c.fillStyle='#d8955a';roundRect(c,-r*0.95,-r*0.2,r*1.9,r*0.18,r*0.08);c.fill(); c.fillStyle='#e9573f';c.beginPath();c.arc(r*0.02,r*0.38,r*0.24,0,TAU);c.fill();c.fillStyle='#fff';c.font=`700 ${r*0.34}px Fredoka`;c.textAlign='center';c.textBaseline='middle';c.fillText('♥',r*0.02,r*0.4);break;} case 'feed':{c.fillStyle=rgrad(c,0,r*0.2,r,[[0,'#f6deaa'],[0.6,'#ddb878'],[1,'#b08848']]);c.beginPath();c.moveTo(-r*0.5,-r*0.55);c.quadraticCurveTo(-r*0.95,r*0.2,-r*0.7,r*0.85);c.lineTo(r*0.7,r*0.85);c.quadraticCurveTo(r*0.95,r*0.2,r*0.5,-r*0.55);c.closePath();c.fill(); c.fillStyle='#ffd23a';for(let i=0;i<9;i++){c.beginPath();c.ellipse(-r*0.4+i*r*0.1,-r*0.62-Math.sin(i/8*Math.PI)*r*0.22,r*0.08,r*0.06,i,0,TAU);c.fill();} c.strokeStyle='#8a5a2a';c.lineWidth=r*0.08;c.beginPath();c.moveTo(-r*0.55,-r*0.45);c.quadraticCurveTo(0,-r*0.3,r*0.55,-r*0.45);c.stroke(); c.fillStyle='#e9573f';c.beginPath();c.arc(0,r*0.25,r*0.24,0,TAU);c.fill();c.save();c.translate(0,r*0.25);c.fillStyle='#fff';c.scale(r/60,r/60);c.beginPath();c.ellipse(0,-2,6,9,0,0,TAU);c.fill();c.restore();break;} }c.restore();} /* ---------------- Icons (canvas → image) ---------------- */ const ICON={},PACK={}; function makeCanvas(w,h){const c=document.createElement('canvas');c.width=w;c.height=h;return c;} function buildIcons(){CROPS.forEach(cr=>{let cv=makeCanvas(128,128),c=cv.getContext('2d'); c.shadowColor='rgba(0,0,0,0.25)';c.shadowOffsetY=4;c.shadowBlur=4;drawProduce(c,cr.id,64,68,46,1);ICON[cr.id]=cv;ICON[cr.id+'_url']=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawSeedPack(c,cr);PACK[cr.id]=cv.toDataURL();}); let cv=makeCanvas(128,128),c=cv.getContext('2d');drawFertIcon(c,64,64,1);PACK.fert=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawSprinklerIcon(c,64,70,1);PACK.spr=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawCan(c,64,70,1,'#5ab0e8');PACK.can=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawHoe(c,64,64);PACK.hoe=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawBasket(c,64,70);PACK.basket=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawStall(c,64,70);PACK.stall=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawLantern(c,64,60,1.3,0);PACK.lantern=cv.toDataURL(); cv=makeCanvas(128,128);c=cv.getContext('2d');drawFertIcon(c,64,66,0.85);ICON.fert=cv; PRODS.concat([{id:'feed'}]).forEach(pr=>{const cv=makeCanvas(128,128),c=cv.getContext('2d');c.shadowColor='rgba(0,0,0,0.25)';c.shadowOffsetY=4;c.shadowBlur=4;drawProduce(c,pr.id,64,68,46,1);ICON[pr.id]=cv;ICON[pr.id+'_url']=cv.toDataURL();}); PACK.feed=ICON.feed_url; ANIMALS.forEach(a=>{const cv=makeCanvas(160,160),c=cv.getContext('2d');c.shadowColor='rgba(0,0,0,0.2)';c.shadowOffsetY=3;c.shadowBlur=4;const k=a.size;const big=a.id==='elephant',pk=a.id==='peacock';drawAnimal(c,a.id,big?60:pk?84:a.id==='bees'?80:76,big?146:142,big?0.64:pk?0.74:1.15/Math.max(0.85,k),{t:0,fan:pk?1:0,trunk:big?1:0});PACK['a_'+a.id]=cv.toDataURL();}); cv=makeCanvas(128,128);c=cv.getContext('2d');c.fillStyle='#8fd16a';roundRect(c,14,30,100,70,18);c.fill();c.fillStyle='#9b6a3d';roundRect(c,24,40,80,50,12);c.fill();c.strokeStyle='#6b4426';c.lineWidth=4;for(let i=0;i<3;i++){c.beginPath();c.moveTo(32,52+i*13);c.lineTo(96,52+i*13);c.stroke();} c.fillStyle='#fff';c.font='700 46px Fredoka';c.textAlign='center';c.strokeStyle='#4a8a2a';c.lineWidth=8;c.strokeText('+',96,44);c.fillText('+',96,44);PACK.plot=cv.toDataURL();} function drawSeedPack(c,cr){c.save();c.translate(64,64);c.rotate(-0.06); c.shadowColor='rgba(80,40,0,0.3)';c.shadowOffsetY=5;c.shadowBlur=6;c.fillStyle=cr.pack;roundRect(c,-40,-50,80,102,14);c.fill();c.shadowColor='transparent'; c.fillStyle='rgba(255,255,255,0.5)';roundRect(c,-40,-50,80,20,[14,14,0,0]);c.fill();c.fillStyle='#c98b4a';c.beginPath();for(let i=0;i<=8;i++)c.lineTo(-40+i*10,-31+(i%2)*6);c.lineTo(40,-27);c.lineTo(-40,-27);c.fill(); c.strokeStyle='rgba(120,70,20,0.35)';c.lineWidth=3;roundRect(c,-40,-50,80,102,14);c.stroke();drawProduce(c,cr.id,0,12,30,1);c.restore();} function roundRect(c,x,y,w,h,r){c.beginPath();if(c.roundRect)c.roundRect(x,y,w,h,r);else c.rect(x,y,w,h);} function drawFertIcon(c,x,y,s){c.save();c.translate(x,y);c.scale(s,s);c.fillStyle='#c98b4a';c.beginPath();c.moveTo(-34,-30);c.lineTo(34,-30);c.lineTo(40,44);c.lineTo(-40,44);c.closePath();c.fill(); c.fillStyle='#e8b47a';c.fillRect(-34,-40,68,14);c.fillStyle='#fff6dc';roundRect(c,-24,-8,48,36,10);c.fill();c.fillStyle='#7bd04a';leaf(c,-6,20,26,9,-1.2,'#5ab03a');leaf(c,-4,18,24,9,-0.4,'#7bd04a'); c.fillStyle='#ffd84a';[[-18,-50],[14,-56],[30,-44]].forEach(p=>{star(c,p[0],p[1],8);});c.restore();} function star(c,x,y,r){c.beginPath();for(let i=0;i<10;i++){const a=i/10*TAU-Math.PI/2,rr=i%2?r*0.45:r;c.lineTo(x+Math.cos(a)*rr,y+Math.sin(a)*rr);}c.fill();} function drawSprinklerIcon(c,x,y,s,t=0){c.save();c.translate(x,y);c.scale(s,s);c.fillStyle='#7a8a9a';c.beginPath();c.ellipse(0,30,22,8,0,0,TAU);c.fill();c.fillStyle='#b8c8d8';c.fillRect(-5,-24,10,54); c.fillStyle='#e0503a';roundRect(c,-18,-36,36,16,8);c.fill();c.fillStyle='#ffd84a';c.beginPath();c.arc(0,-28,5,0,TAU);c.fill(); c.strokeStyle='rgba(90,176,232,0.9)';c.lineWidth=5;c.lineCap='round';for(let i=-1;i<=1;i+=2){c.beginPath();c.arc(i*30,-28,22,i>0?Math.PI*1.1:Math.PI*1.6,i>0?Math.PI*1.4:Math.PI*1.9);c.stroke();}c.restore();} function drawCan(c,x,y,s,col){c.save();c.translate(x,y);c.scale(s,s);c.fillStyle=col;roundRect(c,-30,-24,52,50,12);c.fill();c.strokeStyle=col;c.lineWidth=9;c.lineCap='round';c.beginPath();c.moveTo(18,0);c.lineTo(46,-28);c.stroke(); c.beginPath();c.arc(-4,-28,18,Math.PI,0);c.stroke();c.fillStyle='rgba(255,255,255,0.35)';roundRect(c,-24,-18,10,36,5);c.fill();c.fillStyle='#3a7ab0';c.beginPath();c.ellipse(48,-30,8,5,-0.8,0,TAU);c.fill();c.restore();} function drawHoe(c,x,y){c.save();c.translate(x,y);c.rotate(-0.6);c.fillStyle='#a5663a';roundRect(c,-6,-50,12,100,6);c.fill();c.fillStyle=rgrad(c,0,-50,30,[[0,'#fff6a0'],[0.5,'#ffc83a'],[1,'#d08a10']]);c.beginPath();c.moveTo(-6,-52);c.lineTo(34,-46);c.lineTo(30,-24);c.lineTo(-6,-36);c.fill();c.restore();} function drawBasket(c,x,y){c.save();c.translate(x,y);c.strokeStyle='#a5663a';c.lineWidth=7;c.beginPath();c.arc(0,-6,32,Math.PI,0);c.stroke();drawProduce(c,'tomato',-14,-8,14);drawProduce(c,'mango',10,-12,15);drawProduce(c,'chili',22,-4,12); c.fillStyle='#c98b4a';c.beginPath();c.moveTo(-42,-4);c.lineTo(42,-4);c.lineTo(32,38);c.lineTo(-32,38);c.fill();c.strokeStyle='#8a5a2a';c.lineWidth=4;for(let i=0;i<3;i++){c.beginPath();c.moveTo(-40+i*2,8+i*11);c.lineTo(40-i*2,8+i*11);c.stroke();}c.restore();} function drawStall(c,x,y){c.save();c.translate(x,y);c.fillStyle='#c98b4a';c.fillRect(-40,0,80,36);c.fillStyle='#8a5a2a';c.fillRect(-44,-40,8,76);c.fillRect(36,-40,8,76); for(let i=0;i<5;i++){c.fillStyle=i%2?'#fff':'#e9573f';c.beginPath();c.moveTo(-48+i*19.2,-44);c.lineTo(-48+(i+1)*19.2,-44);c.lineTo(-48+(i+1)*19.2,-28);c.arc(-48+(i+0.5)*19.2,-28,9.6,0,Math.PI);c.fill();} drawProduce(c,'banana',-18,-4,14);drawProduce(c,'pineapple',12,-6,13);c.restore();} function drawLantern(c,x,y,s,t){c.save();c.translate(x,y);c.scale(s,s);c.rotate(Math.sin(t*1.5)*0.06);c.strokeStyle='#5a3418';c.lineWidth=2;c.beginPath();c.moveTo(0,-40);c.lineTo(0,-26);c.stroke(); const cols=['#ff5a7a','#ffd84a','#5ac8ff','#7bd04a'];c.fillStyle=cols[0];c.beginPath();c.moveTo(0,-28);c.lineTo(22,-8);c.lineTo(0,12);c.lineTo(-22,-8);c.fill();c.fillStyle='rgba(255,255,255,0.35)';c.beginPath();c.moveTo(0,-28);c.lineTo(22,-8);c.lineTo(0,-8);c.fill(); c.fillStyle=cols[1];c.beginPath();c.moveTo(-22,-8);c.lineTo(-30,-14);c.lineTo(-26,-2);c.fill();c.beginPath();c.moveTo(22,-8);c.lineTo(30,-14);c.lineTo(26,-2);c.fill(); c.strokeStyle=cols[2];c.lineWidth=2.5;for(let i=-2;i<=2;i++){c.beginPath();c.moveTo(i*4,12);c.quadraticCurveTo(i*5+Math.sin(t*2+i)*3,26,i*6,40);c.stroke();}c.restore();} /* ---------------- Plants ---------------- */ function drawPlant(c,p,x,y,s,t,wind){const cr=CROP[p.c];const g=p.g;c.save();c.translate(x,y); const an=p.an||0;if(an>0){const q=Math.sin(an*Math.PI*3)*an*0.28;c.scale(1+q,1-q);} const sway=Math.sin(t*1.4+p.ph)*0.03*wind+Math.sin(t*2.3+p.ph*2)*0.01*wind; // shadow const big=p.big||g>=1;const zs=g<0.4?0.3:(big?1:0.45+0.55*(g-0.4)/0.6); c.fillStyle='rgba(40,20,5,0.22)';c.beginPath();c.ellipse(0,s*0.02,s*(0.12+0.18*zs)*(cr.kind==='tree'||cr.kind==='palm'?1.2:1),s*0.06*(0.5+zs*0.5),0,0,TAU);c.fill(); if(g<0.12){c.fillStyle='#7a4f2a';c.beginPath();c.ellipse(0,0,s*0.12,s*0.05,0,Math.PI,0);c.fill();c.fillStyle='#5a3418';c.beginPath();c.ellipse(0,-s*0.01,s*0.12,s*0.03,0,0,TAU);c.fill(); c.fillStyle='#f5deb0';c.beginPath();c.ellipse(s*0.02,-s*0.03,s*0.035,s*0.025,0.4,0,TAU);c.fill();c.restore();return;} if(g<0.4){const k=(g-0.12)/0.28;c.rotate(sway*2);const h=s*(0.05+0.1*k);c.strokeStyle='#5aa83a';c.lineWidth=s*0.025;c.lineCap='round';c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(s*0.01,-h*0.5,0,-h);c.stroke(); const L=s*(0.06+0.08*k);leaf(c,0,-h,L,L*0.45,-0.5,'#8ad85a');leaf(c,0,-h,L,L*0.45,-Math.PI+0.5,'#6cc04a');c.restore();return;} const z=zs;const f=g>=1?1:clamp((g-0.72)/0.28,0,1);const ripe=g>=1?1:f*0.35;const pulse=g>=1?1+Math.sin(t*4+p.ph)*0.05:1; c.rotate(sway); switch(cr.kind){ case 'bush':{const h=s*0.5*z;if(cr.id==='tomato'){c.fillStyle='#b5824a';c.fillRect(s*0.04,-h*1.15,s*0.03,h*1.15);} c.strokeStyle=cr.id==='brinjal'?'#5a4a6a':'#4a7a2a';c.lineWidth=s*0.03;c.lineCap='round';c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(-s*0.03,-h*0.5,0,-h);c.stroke(); const Ls=[[0.22,-1,-2.75],[0.32,1,-0.4],[0.48,-1,-2.55],[0.58,1,-0.6],[0.72,-1,-2.3],[0.8,1,-0.85],[1,0,-1.57],[0.95,-1,-2.0],[0.92,1,-1.15]]; Ls.forEach((l,i)=>{const ly=-h*l[0];c.beginPath();c.moveTo(0,ly);c.lineTo(l[1]*s*0.04,ly-s*0.02);c.stroke();leaf(c,l[1]*s*0.03,ly,s*0.2*z*(1-l[0]*0.3),s*0.08*z,l[2]+Math.sin(t*1.8+i+p.ph)*0.06*wind,i%2?cr.leaf:shade(cr.leaf,18));}); if(f>0){const fr=s*(cr.id==='tomato'?0.075:cr.id==='brinjal'?0.09:0.08)*f*pulse;const pos=[[-0.17,0.5],[0.15,0.62],[-0.04,0.78],[0.2,0.35],[-0.2,0.3]]; pos.slice(0,cr.id==='brinjal'?3:5).forEach((q,i)=>drawProduce(c,cr.id,q[0]*s*z,-q[1]*h,fr,ripe,cr.id==='chili'?0.3*(i%2?1:-1):0));}break;} case 'grass':{const n=11,H=s*0.62*z;const col=mixc(hex('#6cc04a'),hex('#d9b53a'),ripe);const col2=mixc(hex('#4a9a3a'),hex('#c0952a'),ripe);c.lineCap='round'; for(let i=0;i<n;i++){const bx=(i-(n-1)/2)*s*0.025,a=(i-(n-1)/2)*0.09,hh=H*(0.8+hash(i*31)*0.25),sw=Math.sin(t*2+i+p.ph)*s*0.02*wind; c.strokeStyle=rgb(i%2?col:col2);c.lineWidth=s*0.022;c.beginPath();c.moveTo(bx,0);c.quadraticCurveTo(bx+a*s*0.3,-hh*0.6,bx+a*s*0.8+sw,-hh);c.stroke(); if(f>0&&i%2===0){const tx=bx+a*s*0.8+sw,ty=-hh;c.fillStyle=rgb(mixc(hex('#a8d06a'),hex('#f2c83a'),ripe)); const sg=Math.sign(a)||1;c.strokeStyle=rgb(mixc(hex('#8ab84a'),hex('#c8962a'),ripe));c.lineWidth=s*0.008;c.beginPath();c.moveTo(tx,ty);c.quadraticCurveTo(tx+sg*s*0.07,ty-s*0.02,tx+sg*s*0.1,ty+s*0.09*f);c.stroke();for(let k=0;k<8;k++){const d=k/7,gx=tx+sg*s*(0.02+0.08*d),gy=ty+s*(-0.01+0.1*d*d)*f;c.beginPath();c.ellipse(gx,gy,s*0.011*f,s*0.019*f,sg*(0.3+d),0,TAU);c.fill();}}}break;} case 'banana':{const h=s*0.5*z;const g2=c.createLinearGradient(-s*0.05,0,s*0.05,0);g2.addColorStop(0,'#9ccf5a');g2.addColorStop(1,'#5f9a3a');c.fillStyle=g2; c.beginPath();c.moveTo(-s*0.05,0);c.lineTo(-s*0.035,-h);c.lineTo(s*0.035,-h);c.lineTo(s*0.05,0);c.fill(); const Lv=[[-2.75,1,-0.5],[-0.4,1,0.5],[-2.2,0.9,-0.35],[-0.95,0.95,0.35],[-1.75,0.75,-0.2],[-1.35,0.8,0.2]];Lv.forEach((l,i)=>{const sw=Math.sin(t*1.5+i+p.ph)*0.05*wind;bigLeaf(c,0,-h,s*0.44*z*l[1],s*0.1*z,l[0]+sw,l[2]>0?0.45:-0.45,i%2?cr.leaf:shade(cr.leaf,15));}); if(f>0){c.strokeStyle='#6a7a2a';c.lineWidth=s*0.018;c.beginPath();c.moveTo(0,-h);c.quadraticCurveTo(s*0.12,-h*0.95,s*0.13,-h*0.55);c.stroke(); for(let r=0;r<2;r++)drawProduce(c,'banana',s*0.12,-h*(0.78-r*0.13),s*0.07*f*pulse,ripe,0.2);c.fillStyle='#8a2a4a';c.beginPath();c.ellipse(s*0.13,-h*0.5,s*0.02,s*0.035,0,0,TAU);c.fill();}break;} case 'corn':{const h=s*0.72*z;c.lineCap='round';const st=c.createLinearGradient(-s*0.02,0,s*0.02,0);st.addColorStop(0,'#8ad05a');st.addColorStop(1,'#4e9a36');c.strokeStyle=st;c.lineWidth=s*0.035; c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(-s*0.02,-h*0.5,0,-h);c.stroke(); const L=[[0.15,1,-0.5],[0.3,-1,-2.6],[0.48,1,-0.7],[0.62,-1,-2.45],[0.78,1,-0.95],[0.9,-1,-2.2]];L.forEach((l,i)=>{const sw=Math.sin(t*1.7+i+p.ph)*0.07*wind;bigLeaf(c,0,-h*l[0],s*0.32*z*(1.1-l[0]*0.4),s*0.06*z,l[2]+sw,l[1]>0?0.5:-0.5,i%2?cr.leaf:shade(cr.leaf,18));}); c.strokeStyle=rgb(mixc(hex('#c8d878'),hex('#d8a84a'),ripe));c.lineWidth=s*0.012;for(let k=-2;k<=2;k++){c.beginPath();c.moveTo(0,-h);c.quadraticCurveTo(k*s*0.02,-h-s*0.06,k*s*0.04,-h-s*0.1);c.stroke();} if(f>0){[[0.05,0.55,0.4],[-0.05,0.4,-0.4]].forEach((q,i)=>{if(i===1&&f<0.6)return;drawProduce(c,'corn',q[0]*s,-h*q[1],s*0.11*f*pulse,ripe,q[2]);});}break;} case 'pine':{const R=s*0.3*z;for(let i=0;i<13;i++){const a=-Math.PI+0.15+i/12*(Math.PI-0.3);leaf(c,0,-s*0.02,R*(0.7+0.3*Math.sin(i*1.7)),s*0.03,a,i%2?'#4e9a5a':'#3f8a4a',false);} if(f>0)drawProduce(c,'pineapple',0,-R*0.55,s*0.13*f*pulse,ripe);for(let i=0;i<5;i++){const a=-Math.PI+0.5+i/4*(Math.PI-1);leaf(c,0,0,R*0.55,s*0.03,a,'#5aa86a',false);}break;} case 'tree':{const h=s*0.5*z;const tg=c.createLinearGradient(-s*0.05,0,s*0.05,0);tg.addColorStop(0,'#9a6a3a');tg.addColorStop(1,'#6a4220');c.fillStyle=tg; c.beginPath();c.moveTo(-s*0.055,0);c.quadraticCurveTo(-s*0.02,-h*0.5,-s*0.03,-h);c.lineTo(s*0.03,-h);c.quadraticCurveTo(s*0.02,-h*0.5,s*0.055,0);c.fill(); c.strokeStyle='#7a4f2a';c.lineWidth=s*0.025;c.beginPath();c.moveTo(0,-h*0.7);c.lineTo(-s*0.12*z,-h*1.05);c.moveTo(0,-h*0.75);c.lineTo(s*0.13*z,-h*1.08);c.stroke(); const cy=-h-s*0.12*z,S2=s*z;const blobs=[[0,0,0.27],[-0.19,0.07,0.2],[0.19,0.07,0.2],[-0.1,-0.15,0.19],[0.12,-0.14,0.19],[0,0.1,0.2]]; const lc=hex(cr.leaf);c.fillStyle=rgb(mixc(lc,[20,50,20],0.45));blobs.forEach(b=>{c.beginPath();c.arc(b[0]*S2,cy+b[1]*S2+S2*0.04,b[2]*S2,0,TAU);c.fill();}); blobs.forEach(b=>{c.fillStyle=rgrad(c,b[0]*S2,cy+b[1]*S2,b[2]*S2,[[0,rgb(mixc(lc,[255,255,200],0.35))],[0.7,rgb(lc)],[1,rgb(mixc(lc,[0,30,0],0.25))]]);c.beginPath();c.arc(b[0]*S2,cy+b[1]*S2,b[2]*S2,0,TAU);c.fill();}); c.fillStyle='rgba(255,255,220,0.18)';for(let i=0;i<7;i++){c.beginPath();c.ellipse((hash(i*7+3)-0.6)*S2*0.4,cy+(hash(i*11)-0.7)*S2*0.3,S2*0.05,S2*0.025,-0.5,0,TAU);c.fill();} if(f>0){const fp=cr.id==='jackfruit'?[[-0.06,0.3,0.1],[0.08,0.22,0.09],[0.15,0.1,0.08]]:cr.id==='rambutan'?[[-0.18,0.12],[-0.13,0.17],[-0.2,0.2],[0.14,0.14],[0.2,0.18],[0.1,0.2],[0.02,0.02],[-0.06,0.06]]:[[-0.17,0.14],[0.16,0.16],[0.02,0.2],[-0.06,0.0],[0.2,-0.02]]; fp.forEach(q=>{const fr=(q[2]||(cr.id==='rambutan'?0.045:0.065))*S2*f*pulse;drawProduce(c,cr.id,q[0]*S2,cy+q[1]*S2+(cr.id==='jackfruit'?S2*0.05:0),fr,ripe,cr.id==='mango'?0.3:0);});}break;} case 'palm':{const h=s*1.15*z,lean=s*0.14*z;c.lineCap='round'; const tgp=c.createLinearGradient(-s*0.05,0,s*0.05,0);tgp.addColorStop(0,'#b08a5a');tgp.addColorStop(1,'#7a5430');c.strokeStyle=tgp;for(let i=0;i<14;i++){const q=i/14,q2=(i+1)/14;c.lineWidth=s*(0.085-0.03*q);c.beginPath();c.moveTo(lean*q*q,-h*q);c.lineTo(lean*q2*q2,-h*q2);c.stroke();} for(let i=0;i<=14;i++){const q=i/14,px=lean*q*q,py=-h*q;c.strokeStyle='rgba(70,40,15,0.45)';c.lineWidth=2;c.beginPath();c.ellipse(px,py,s*(0.042-0.015*q),s*0.012,0,0,Math.PI);c.stroke();} const tx=lean,ty=-h;if(f>0){[[-0.05,0.04],[0.05,0.05],[0,0.08],[-0.03,0.11],[0.04,0.11]].forEach(q=>drawProduce(c,'coconut',tx+q[0]*s*1.3,ty+q[1]*s*1.1,s*0.065*f*pulse,ripe));} for(let i=0;i<9;i++){const a=-Math.PI+0.1+i/8*(Math.PI-0.2)+Math.sin(t*1.2+i+p.ph)*0.06*wind;const L=s*0.56*z;const ex=tx+Math.cos(a)*L,ey=ty+Math.sin(a)*L*0.45+L*0.32;const mx=tx+Math.cos(a)*L*0.5,my=ty+Math.sin(a)*L*0.55-s*0.04; c.strokeStyle=i%2?'#4a9a3a':'#5aa848';c.lineWidth=s*0.012;for(let k=1;k<10;k++){const q=k/10,bx=(1-q)*(1-q)*tx+2*(1-q)*q*mx+q*q*ex,by=(1-q)*(1-q)*ty+2*(1-q)*q*my+q*q*ey;const ll=s*0.1*(1-q*0.6)*z; c.beginPath();c.moveTo(bx,by);c.lineTo(bx+Math.cos(a+1.9)*ll,by+Math.sin(a+1.9)*ll+ll*0.5);c.moveTo(bx,by);c.lineTo(bx+Math.cos(a-1.9)*ll,by+Math.sin(a-1.9)*ll+ll*0.5);c.stroke();} c.strokeStyle='#3f7a2a';c.lineWidth=s*0.014;c.beginPath();c.moveTo(tx,ty);c.quadraticCurveTo(mx,my,ex,ey);c.stroke();}break;} } c.restore();} function bigLeaf(c,x,y,len,wid,ang,droop,col){c.save();c.translate(x,y);c.rotate(ang);const n=12,top=[],bot=[]; for(let k=0;k<=n;k++){const q=k/n,px=q*len,py=droop*len*q*q,w=Math.sin(Math.PI*Math.pow(q,0.8))*wid*(1-q*0.3);const a=Math.atan2(2*droop*q,1);top.push([px-Math.sin(a)*w,py-Math.cos(a)*w]);bot.push([px+Math.sin(a)*w,py+Math.cos(a)*w]);} c.beginPath();c.moveTo(0,0);top.forEach(p=>c.lineTo(p[0],p[1]));for(let k=bot.length-1;k>=0;k--)c.lineTo(bot[k][0],bot[k][1]);c.closePath(); const g=c.createLinearGradient(0,-wid,0,wid);g.addColorStop(0,shade(col,25));g.addColorStop(0.5,col);g.addColorStop(1,shade(col,-25));c.fillStyle=g;c.fill(); c.strokeStyle='rgba(255,255,220,0.4)';c.lineWidth=Math.max(1.5,wid*0.12);c.beginPath();c.moveTo(0,0);for(let k=0;k<=n;k++){const q=k/n;c.lineTo(q*len,droop*len*q*q);}c.stroke(); c.strokeStyle='rgba(0,40,0,0.15)';c.lineWidth=1.5;for(let k=2;k<n;k+=2){const q=k/n;c.beginPath();c.moveTo(q*len,droop*len*q*q);c.lineTo(top[k][0]+len*0.05,top[k][1]);c.moveTo(q*len,droop*len*q*q);c.lineTo(bot[k][0]+len*0.05,bot[k][1]);c.stroke();} c.restore();} function shade(h,a){const c=hex(h);return rgb(c.map(v=>clamp(v+a,0,255)));} /* ---------------- Animals (v1.1) ---------------- drawAnimal(c,id,x,y,s,st): (x,y) = feet on the ground, s = scale (about 120*s px wide). st: {t, ph, fx (facing 1/-1), sleep, sad, eat, walk} */ function aniEye(c,x,y,r,st){if(st.sleep){c.strokeStyle='#3a1a10';c.lineWidth=r*0.7;c.lineCap='round';c.beginPath();c.arc(x,y-r*0.3,r*1.1,0.3,Math.PI-0.3);c.stroke();return;} c.fillStyle='#2a1408';c.beginPath();c.ellipse(x,y,r,r*1.15,0,0,TAU);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(x-r*0.3,y-r*0.4,r*0.38,0,TAU);c.fill(); if(st.sad){c.strokeStyle='#3a1a10';c.lineWidth=r*0.5;c.lineCap='round';c.beginPath();c.moveTo(x-r*1.3,y-r*2.1);c.lineTo(x+r*1.1,y-r*1.6);c.stroke();}} function aniBlush(c,x,y,r){c.fillStyle='rgba(255,110,120,0.4)';c.beginPath();c.ellipse(x,y,r,r*0.6,0,0,TAU);c.fill();} function aniLegs(c,xs,top,len,w,col,hoof,t,st){c.lineCap='round';xs.forEach((x,i)=>{const k=st.walk?Math.sin(t*10+i*Math.PI)*w*0.5:0;c.strokeStyle=col;c.lineWidth=w;c.beginPath();c.moveTo(x,top);c.lineTo(x+k,-w*0.5);c.stroke(); if(hoof){c.strokeStyle=hoof;c.lineWidth=w*1.02;c.beginPath();c.moveTo(x+k,-w*0.9);c.lineTo(x+k,-w*0.45);c.stroke();}});} function drawAnimal(c,id,x,y,s,st){const t=st.t||0,ph=st.ph||0;c.save();c.translate(x,y);c.scale(s*(st.fx||1),s); const bob=st.sleep?Math.sin(t*1.6+ph)*1.2:st.walk?-Math.abs(Math.sin(t*10+ph))*4:Math.sin(t*2.2+ph)*1.6; const peck=st.eat?Math.pow(Math.max(0,Math.sin(t*4+ph)),6):(!st.sleep&&!st.sad?Math.pow(Math.max(0,Math.sin(t*0.9+ph*3)),24):0); c.fillStyle='rgba(40,20,5,0.22)';c.beginPath();c.ellipse(0,0,id==='chicken'||id==='duck'||id==='peacock'?40:id==='bees'?44:id==='elephant'?96:58,id==='elephant'?14:9,0,0,TAU);c.fill(); if(id==='chicken'){c.strokeStyle='#f0a020';c.lineWidth=5;c.lineCap='round';[-9,9].forEach(lx=>{c.beginPath();c.moveTo(lx,-18);c.lineTo(lx,-1);c.lineTo(lx+8,0);c.moveTo(lx,-1);c.lineTo(lx-5,1);c.stroke();}); c.save();c.translate(0,bob); [[-0.9,'#2f5a3a'],[-0.55,'#3a6a2a'],[-0.25,'#a8401e']].forEach(q=>leaf(c,-26,-44,34,11,Math.PI+q[0],q[1],false)); c.fillStyle=rgrad(c,0,-38,36,[[0,'#f6b070'],[0.6,'#d9783a'],[1,'#a9541e']]);c.beginPath();c.ellipse(0,-38,36,28,0,0,TAU);c.fill(); c.fillStyle='#fff1d8';c.beginPath();c.ellipse(10,-30,18,15,0.3,0,TAU);c.fill(); c.fillStyle='#b5602a';c.beginPath();c.ellipse(-8,-38,19,12,-0.25+(st.sleep?0:Math.sin(t*6+ph)*0.04),0,TAU);c.fill();c.strokeStyle='rgba(120,50,10,0.35)';c.lineWidth=2.5;c.beginPath();c.moveTo(-20,-36);c.quadraticCurveTo(-8,-30,4,-36);c.stroke(); c.save();c.translate(22,-56);c.rotate(peck*0.9);c.translate(peck*6,peck*4); c.fillStyle=rgrad(c,0,-6,18,[[0,'#f8bc80'],[1,'#c9682e']]);c.beginPath();c.arc(2,-6,16,0,TAU);c.fill(); c.fillStyle='#ff4a3a';[[-4,-22,6],[3,-24,6.5],[10,-20,5.5]].forEach(q=>{c.beginPath();c.arc(q[0],q[1],q[2],0,TAU);c.fill();});c.beginPath();c.ellipse(15,4,4,6,0,0,TAU);c.fill(); c.fillStyle='#ffb21c';c.beginPath();c.moveTo(14,-9);c.lineTo(26,-4);c.lineTo(14,0);c.closePath();c.fill();aniEye(c,7,-9,3.4,st);aniBlush(c,4,0,4);c.restore();c.restore();} else if(id==='duck'){c.fillStyle='#f39a1c';[-10,8].forEach(lx=>{c.beginPath();c.ellipse(lx+6,-1,10,4,0,0,TAU);c.fill();c.fillRect(lx-2,-14,4,13);}); c.save();c.translate(0,bob); c.fillStyle=rgrad(c,-2,-30,40,[[0,'#ffffff'],[0.7,'#f4f1e8'],[1,'#d8d2c0']]);c.beginPath();c.moveTo(-40,-46);c.quadraticCurveTo(-44,-14,-10,-12);c.quadraticCurveTo(28,-10,32,-30);c.quadraticCurveTo(30,-48,8,-48);c.quadraticCurveTo(-20,-44,-40,-46);c.fill(); c.fillStyle='#e8e2d2';c.beginPath();c.ellipse(-6,-32,20,11,-0.15,0,TAU);c.fill(); c.save();c.translate(22,-48);c.rotate(peck*1.1);c.translate(peck*8,peck*6); c.fillStyle='#fff';c.beginPath();c.ellipse(0,-10,9,16,0.1,0,TAU);c.fill();c.beginPath();c.arc(3,-24,15,0,TAU);c.fill(); c.fillStyle='#ff9a1c';c.beginPath();c.ellipse(20,-20,12,5.5,0.1,0,TAU);c.fill();c.fillStyle='#e07a10';c.beginPath();c.ellipse(19,-17,10,2.5,0.1,0,Math.PI);c.fill(); aniEye(c,7,-28,3.2,st);aniBlush(c,4,-18,4);c.strokeStyle='#ffd84a';c.lineWidth=3;c.lineCap='round';c.beginPath();c.moveTo(0,-39);c.quadraticCurveTo(4,-46,0,-50);c.stroke();c.restore();c.restore();} else if(id==='goat'||id==='cow'||id==='buffalo'){const cow=id==='cow',buf=id==='buffalo'; const P=cow?{bw:52,bh:29,by:-58,leg:34,lw:11,body:['#fffaf0','#efe2c8'],patch:'#9a5a32',head:'#fffaf0'}:buf?{bw:56,bh:31,by:-60,leg:32,lw:13,body:['#6e7480','#454a54'],patch:null,head:'#5a606b'}:{bw:42,bh:23,by:-48,leg:30,lw:9,body:['#fffdf6','#ece4d4'],patch:'#c08850',head:'#fffdf6'}; aniLegs(c,[-P.bw*0.62,-P.bw*0.3,P.bw*0.36,P.bw*0.66],P.by+P.bh*0.5,P.leg,P.lw,buf?'#4a4f58':cow?'#f3e8d4':'#f2ecdf',buf?'#2a2d33':'#5a4030',t,st); if(buf){c.fillStyle='rgba(120,80,40,0.55)';[-P.bw*0.62,-P.bw*0.3,P.bw*0.36,P.bw*0.66].forEach(lx=>{c.beginPath();c.ellipse(lx,-8,P.lw*0.62,8,0,0,TAU);c.fill();});} c.save();c.translate(0,bob); c.strokeStyle=buf?'#3a3f48':cow?'#e8dcc4':'#e6dccb';c.lineWidth=5;c.lineCap='round';const tw=Math.sin(t*3+ph)*0.3;c.beginPath();c.moveTo(-P.bw*0.95,P.by-P.bh*0.3);c.quadraticCurveTo(-P.bw*1.2,P.by+(id==='goat'?-P.bh*0.9:P.bh*0.3),-P.bw*(1.12+tw*0.1),P.by+(id==='goat'?-P.bh*0.9:P.bh*0.9));c.stroke(); if(id!=='goat'){c.fillStyle=buf?'#2a2d33':'#9a5a32';c.beginPath();c.ellipse(-P.bw*(1.12+tw*0.1),P.by+P.bh*0.95,5,8,0,0,TAU);c.fill();} c.fillStyle=rgrad(c,0,P.by,P.bw,[[0,P.body[0]],[0.75,P.body[1]],[1,shade(P.body[1],-25)]]);c.beginPath();c.ellipse(0,P.by,P.bw,P.bh,0,0,TAU);c.fill(); if(P.patch){c.save();c.beginPath();c.ellipse(0,P.by,P.bw,P.bh,0,0,TAU);c.clip();c.fillStyle=P.patch; (cow?[[-24,-12,17,13],[12,6,14,11],[30,-16,9,8]]:[[-20,-8,16,12],[16,-14,10,8]]).forEach(q=>{c.beginPath();c.ellipse(q[0],P.by+q[1],q[2],q[3],0.4,0,TAU);c.fill();});c.restore();} if(cow){c.fillStyle='#ffb6b0';c.beginPath();c.ellipse(-4,P.by+P.bh*0.9,10,6,0,0,TAU);c.fill();} if(buf){c.fillStyle='rgba(255,255,255,0.12)';c.beginPath();c.ellipse(-10,P.by-P.bh*0.45,P.bw*0.6,P.bh*0.3,0,0,TAU);c.fill();} const hx=P.bw*0.92,hy=P.by-P.bh*(id==='goat'?0.9:0.55);c.save();c.translate(hx,hy);c.rotate(peck*0.7+(st.sleep?0.35:0));c.translate(peck*4,peck*10); if(cow){c.fillStyle='#e8c040';c.beginPath();c.arc(-6,22,7,0,TAU);c.fill();c.strokeStyle='#e9573f';c.lineWidth=4;c.beginPath();c.moveTo(-16,12);c.quadraticCurveTo(-6,20,4,12);c.stroke();} // ears const ec=buf?'#4a4f58':cow?'#f3e2c8':'#f2ecdf';c.fillStyle=ec;c.save();c.translate(-4,-8);c.rotate(id==='goat'?0.9:0.35);c.beginPath();c.ellipse(-14,0,14,6,0,0,TAU);c.fill();c.restore(); // horns if(buf){c.strokeStyle='#e0d4b8';c.lineWidth=7;c.lineCap='round';c.beginPath();c.moveTo(0,-14);c.quadraticCurveTo(-30,-26,-40,-6);c.stroke();c.lineWidth=5;c.beginPath();c.moveTo(6,-16);c.quadraticCurveTo(-18,-34,-32,-22);c.stroke();} else if(cow){c.strokeStyle='#f6ecd0';c.lineWidth=6;c.lineCap='round';c.beginPath();c.moveTo(-2,-16);c.quadraticCurveTo(-4,-28,4,-30);c.stroke();} else{c.strokeStyle='#b89a70';c.lineWidth=5;c.lineCap='round';c.beginPath();c.moveTo(-2,-16);c.quadraticCurveTo(-8,-34,-22,-34);c.stroke();} const hw=id==='goat'?15:19,hh=id==='goat'?18:21;c.fillStyle=rgrad(c,4,0,hh,[[0,shade(P.head,15)],[1,shade(P.head,-18)]]);c.beginPath();c.ellipse(6,0,hw,hh,-0.5,0,TAU);c.fill(); if(cow&&!st.sleep){c.fillStyle='#9a5a32';c.beginPath();c.ellipse(0,-10,7,6,0,0,TAU);c.fill();} c.fillStyle=cow?'#ffb6b0':buf?'#8a909a':'#f4d8c8';c.beginPath();c.ellipse(16,12,cow?14:buf?14:9,cow?10:buf?11:7,-0.4,0,TAU);c.fill(); c.fillStyle='rgba(60,30,20,0.6)';[[14,12],[21,9]].forEach(q=>{c.beginPath();c.arc(q[0],q[1],2.2,0,TAU);c.fill();}); if(id==='goat'){c.fillStyle='#e6dccb';c.beginPath();c.moveTo(8,16);c.lineTo(12,34);c.lineTo(16,17);c.fill();} aniEye(c,8,-4,3.6,st);if(!buf)aniBlush(c,2,8,5);c.restore();c.restore();} else if(id==='bees'){c.fillStyle='#8a5a2a';c.fillRect(-30,-20,8,20);c.fillRect(22,-20,8,20); c.fillStyle=rgrad(c,0,-40,40,[[0,'#ffd27a'],[1,'#d8902a']]);roundRect(c,-38,-56,76,36,8);c.fill();c.fillStyle=rgrad(c,0,-74,40,[[0,'#ffe08a'],[1,'#e0a038']]);roundRect(c,-35,-86,70,32,8);c.fill(); c.strokeStyle='rgba(140,80,20,0.35)';c.lineWidth=2.5;c.beginPath();c.moveTo(-34,-56);c.lineTo(34,-56);c.stroke(); c.fillStyle='#c0602e';c.beginPath();c.moveTo(-46,-84);c.lineTo(0,-108);c.lineTo(46,-84);c.closePath();c.fill();c.fillStyle='rgba(255,255,255,0.18)';c.beginPath();c.moveTo(-46,-84);c.lineTo(0,-108);c.lineTo(0,-98);c.closePath();c.fill(); c.fillStyle='#4a2a10';roundRect(c,-12,-30,24,7,3);c.fill();c.fillStyle='#ffb21c';c.beginPath();c.moveTo(18,-56);c.quadraticCurveTo(20,-46,24,-44);c.quadraticCurveTo(28,-46,28,-56);c.fill(); if(!st.sleep)for(let k=0;k<4;k++){const a=t*(1.6+k*0.3)+k*1.7+ph,bx=Math.cos(a)*(46+k*6),by=-58+Math.sin(a*1.3)*26;drawBee(c,bx,by,1,t*30+k,Math.cos(a)>0?1:-1);}} else if(id==='peacock')drawPeacock(c,t,ph,bob,peck,st); else if(id==='elephant')drawElephant(c,t,ph,bob,peck,st); c.restore();} /* Peacock (v1.1): st.fan 0..1 opens the tail into a big eyespot fan */ function drawPeacock(c,t,ph,bob,peck,st){const fan=clamp(st.fan||0,0,1),fe=fan*fan*(3-2*fan); c.strokeStyle='#b8a890';c.lineWidth=4.5;c.lineCap='round';[-7,8].forEach(lx=>{c.beginPath();c.moveTo(lx,-22);c.lineTo(lx,-1);c.lineTo(lx+8,0);c.moveTo(lx,-1);c.lineTo(lx-5,1);c.stroke();}); c.save();c.translate(0,bob); if(fe<0.98){c.globalAlpha=1-fe;const tg=c.createLinearGradient(-110,0,-10,0);tg.addColorStop(0,'#1f8a6a');tg.addColorStop(1,'#3a9a4a');c.fillStyle=tg; c.beginPath();c.moveTo(-14,-42);c.quadraticCurveTo(-70,-46,-112,-14);c.quadraticCurveTo(-118,-6,-106,-6);c.quadraticCurveTo(-60,-14,-12,-26);c.closePath();c.fill(); [[-100,-11],[-82,-18],[-64,-24],[-46,-30]].forEach((q,k)=>{[[6.5,'#e8c040'],[4.6,'#1aa6a0'],[2.8,'#1a2a7a']].forEach(e=>{c.fillStyle=e[1];c.beginPath();c.ellipse(q[0],q[1],e[0]*1.2,e[0],-0.35,0,TAU);c.fill();});});c.globalAlpha=1;} if(fe>0.02){const R=lerp(34,92,fe),spr=lerp(0.25,1,fe),cx=-14,cy=-46,n=15,sh=Math.sin(t*9+ph)*0.025*fe;c.save();c.translate(cx,cy);c.rotate(sh); for(let k=0;k<n;k++){const a=-Math.PI/2+(k/(n-1)-0.5)*Math.PI*1.12*spr;c.save();c.rotate(a+Math.PI/2);const L=R*(0.88+((k%2)?0.12:0)); const fg=c.createLinearGradient(0,0,0,-L);fg.addColorStop(0,'#2f7a3a');fg.addColorStop(0.7,'#3fae5a');fg.addColorStop(1,'#1f9a8a');c.fillStyle=fg; c.beginPath();c.moveTo(-3,0);c.quadraticCurveTo(-L*0.16,-L*0.6,-L*0.11,-L*0.92);c.quadraticCurveTo(0,-L*1.04,L*0.11,-L*0.92);c.quadraticCurveTo(L*0.16,-L*0.6,3,0);c.fill(); [[0.13,'#e8c040'],[0.095,'#1aa6a0'],[0.055,'#1a2a7a']].forEach(e=>{c.fillStyle=e[1];c.beginPath();c.ellipse(0,-L*0.84,L*e[0]*0.8,L*e[0],0,0,TAU);c.fill();});c.restore();} c.restore();} c.fillStyle=rgrad(c,0,-38,30,[[0,'#5a9af0'],[0.7,'#2a5ac8'],[1,'#1a3a8a']]);c.beginPath();c.ellipse(0,-36,26,20,0,0,TAU);c.fill(); c.fillStyle='#c8a878';c.beginPath();c.ellipse(-8,-36,17,11,-0.2,0,TAU);c.fill();c.strokeStyle='rgba(110,70,30,0.45)';c.lineWidth=2;for(let k=0;k<3;k++){c.beginPath();c.moveTo(-20+k*7,-42);c.lineTo(-16+k*7,-30);c.stroke();} c.save();c.translate(14,-48);c.rotate(peck*0.9);c.translate(peck*6,peck*6); c.strokeStyle='#2a5ac8';c.lineWidth=13;c.lineCap='round';c.beginPath();c.moveTo(0,4);c.quadraticCurveTo(8,-12,6,-28);c.stroke(); c.fillStyle=rgrad(c,6,-32,12,[[0,'#6aa8ff'],[1,'#2a5ac8']]);c.beginPath();c.arc(6,-32,11,0,TAU);c.fill(); c.strokeStyle='#2a4aa8';c.lineWidth=2;[[-4,-54],[4,-57],[12,-54]].forEach(q=>{c.beginPath();c.moveTo(5,-42);c.lineTo(q[0],q[1]);c.stroke();c.fillStyle='#3a7ae0';c.beginPath();c.arc(q[0],q[1],3.4,0,TAU);c.fill();}); c.fillStyle='#fff';c.beginPath();c.ellipse(9,-33,6,3.6,0.2,0,TAU);c.fill();c.fillStyle='#e8d8b0';c.beginPath();c.moveTo(15,-32);c.lineTo(24,-29);c.lineTo(15,-26);c.closePath();c.fill(); aniEye(c,9,-33,2.8,st);aniBlush(c,8,-25,3.5);c.restore();c.restore();} /* Elephant (v1.1): gentle, cute, no tusks/chains. st.trunk 0..1 raises the trunk, st.spray shows a water shower */ function drawElephant(c,t,ph,bob,peck,st){const up=clamp(st.trunk||0,0,1),eat=st.eat?Math.max(0,Math.sin(t*3+ph)):0; const lw=26,legs=[[-50,'#7d8698'],[20,'#7d8698'],[-26,null],[46,null]]; legs.forEach((q,i)=>{const k=st.walk?Math.sin(t*6+i*Math.PI*0.5)*6:0;c.fillStyle=q[1]||rgrad(c,q[0],-30,30,[[0,'#b6bfcf'],[1,'#8c95a8']]);roundRect(c,q[0]-lw/2+k,-58,lw,58,[8,8,10,10]);c.fill(); if(!q[1]){c.fillStyle='#f4ead8';[-7,0,7].forEach(dx=>{c.beginPath();c.ellipse(q[0]+k+dx,-4,3.6,3,0,0,TAU);c.fill();});}}); c.save();c.translate(0,bob); c.strokeStyle='#8c95a8';c.lineWidth=5;c.lineCap='round';const tw=Math.sin(t*2.6+ph)*6;c.beginPath();c.moveTo(-74,-84);c.quadraticCurveTo(-86,-64,-84+tw,-46);c.stroke();c.fillStyle='#6a7284';c.beginPath();c.ellipse(-84+tw,-42,4,7,0,0,TAU);c.fill(); c.fillStyle=rgrad(c,-6,-82,82,[[0,'#c8d0de'],[0.65,'#a2abbd'],[1,'#7f889b']]);c.beginPath();c.ellipse(-4,-82,78,50,0,0,TAU);c.fill(); c.fillStyle='rgba(255,255,255,0.14)';c.beginPath();c.ellipse(-20,-112,46,14,-0.1,0,TAU);c.fill(); const hx=58,hy=-100;c.save();c.translate(hx,hy);c.rotate(st.sleep?0.12:peck*0.12); // ear (flaps gently) c.save();c.translate(-22,4);c.scale(1+(st.sleep?0:Math.sin(t*2.4+ph)*0.07),1);c.fillStyle=rgrad(c,0,0,36,[[0,'#b2bbcb'],[1,'#8892a6']]);c.beginPath();c.ellipse(0,0,30,38,-0.15,0,TAU);c.fill(); c.fillStyle='#e9b6c0';c.beginPath();c.ellipse(-3,2,18,26,-0.15,0,TAU);c.fill();c.restore(); c.fillStyle=rgrad(c,10,-6,44,[[0,'#ccd4e2'],[1,'#98a1b4']]);c.beginPath();c.ellipse(12,-2,38,36,0,0,TAU);c.fill(); // lotus behind the ear c.save();c.translate(-12,-38);c.fillStyle='#ff9ac0';[-0.8,-0.4,0,0.4,0.8].forEach(a=>{c.save();c.rotate(a);c.beginPath();c.ellipse(0,-8,4.5,10,0,0,TAU);c.fill();c.restore();});c.fillStyle='#ffe14a';c.beginPath();c.arc(0,-2,3.5,0,TAU);c.fill();c.restore(); // trunk: tapered tube along a curve (down / raised / curled to the mouth when eating) const p0=[38,6],dn={c:[62,40],e:[50,78]},rs={c:[86,4],e:[84,-46]},mo={c:[60,40],e:[34,30]}; const lerp2=(a,b,k)=>[lerp(a[0],b[0],k),lerp(a[1],b[1],k)];let cc=lerp2(dn.c,rs.c,up),ee=lerp2(dn.e,rs.e,up);if(eat){cc=lerp2(cc,mo.c,eat);ee=lerp2(ee,mo.e,eat);} ee=[ee[0]+(st.sleep?0:Math.sin(t*1.8+ph)*3),ee[1]]; const bz=k=>[(1-k)*(1-k)*p0[0]+2*(1-k)*k*cc[0]+k*k*ee[0],(1-k)*(1-k)*p0[1]+2*(1-k)*k*cc[1]+k*k*ee[1]]; for(let k=0;k<=24;k++){const q=k/24,pt=bz(q);c.fillStyle=k%6===5?'#98a1b4':'#a9b2c4';c.beginPath();c.arc(pt[0],pt[1],lerp(15,8,q),0,TAU);c.fill();} const tip=bz(1);c.fillStyle='#8a92a6';c.beginPath();c.ellipse(tip[0],tip[1],7.5,5,0,0,TAU);c.fill(); c.strokeStyle='#5a3a3a';c.lineWidth=3;c.lineCap='round';c.beginPath();c.arc(20,22,8,0.3,Math.PI-0.6);c.stroke(); aniEye(c,22,-12,4.6,st);aniBlush(c,30,4,7); if(st.spray&&!st.sleep){c.fillStyle='rgba(120,200,255,0.9)';for(let k=0;k<14;k++){const q=((t*1.6+k/14)%1),dx=(hash(k*3)-0.3)*80,px=tip[0]+dx*q,py=tip[1]-90*q+130*q*q;c.globalAlpha=1-q;c.beginPath();c.ellipse(px,py,3.5,5,0,0,TAU);c.fill();}c.globalAlpha=1;} c.restore();c.restore();} function drawBee(c,x,y,s,fl,dir=1){c.save();c.translate(x,y);c.scale(s*dir,s);c.fillStyle='rgba(255,255,255,0.75)';const w=Math.abs(Math.sin(fl))*5+2;c.beginPath();c.ellipse(-2,-6,4,w,-0.4,0,TAU);c.ellipse(3,-6,4,w,0.4,0,TAU);c.fill(); c.fillStyle='#ffd23a';c.beginPath();c.ellipse(0,0,8,5.5,0,0,TAU);c.fill();c.fillStyle='#3a2410';c.fillRect(-3,-5,2.5,10);c.fillRect(2,-5,2.5,10);c.beginPath();c.arc(7,-1,1.4,0,TAU);c.fill();c.restore();} /* ---------------- Layout ---------------- */ let W=1920,H=1080,SCALE=1,DPR=1,PORTRAIT=false,HORIZON=330;const F={x:0,y:0,tw:100,th:66,dep:10}; const Y={x:0,y:0,w:0,h:0,cols:3,rows:2,pw:100,ph:60,gap:20,s:1}; // animal yard pens let VIEW='farm',viewT=1,viewDir=1; const stage=$('#stage'),scv=$('#scene'),sc=scv.getContext('2d'),fcv=$('#fx'),fc=fcv.getContext('2d'); let DECOR={tufts:[],flowers:[],stars:[],clouds:[],trees:[],bfly:[],ffly:[]}; // CSS zoom lays the UI out at real screen size (no giant scaled layer: much less WebKit memory). Falls back to transform where zoom is unsupported. let USE_ZOOM=!!(window.CSS&&CSS.supports&&CSS.supports('zoom','0.5')); // Safety net: if the browser inflates text inside the zoomed stage (iOS text autosizing), go back to the transform layout. function zoomTextOk(){const mk=(par,fs)=>{const p=document.createElement('span');p.style.cssText=`position:absolute;left:0;top:0;visibility:hidden;font-size:${fs}px;white-space:nowrap`;p.textContent='Shop Animals Lv 4 Journal';par.appendChild(p);return p;}; const a=mk(stage,20),b=mk(document.body,20*SCALE);const fs=parseFloat(getComputedStyle(a).fontSize),wa=a.getBoundingClientRect().width,wb=b.getBoundingClientRect().width;a.remove();b.remove(); return Math.abs(fs-20)<0.5&&wb>0&&Math.abs(wa/wb-1)<0.08;} function resize(){const vw=window.innerWidth,vh=window.innerHeight;PORTRAIT=vh>vw*1.05; if(!PORTRAIT){H=1080;W=clamp(Math.round(1080*vw/vh),1500,2560);}else{W=1080;H=clamp(Math.round(1080*vh/vw),1600,2400);} SCALE=Math.min(vw/W,vh/H);const ox=(vw-W*SCALE)/2,oy=(vh-H*SCALE)/2; stage.style.width=W+'px';stage.style.height=H+'px';if(USE_ZOOM){stage.style.zoom=SCALE;stage.style.transform='';stage.style.left=(ox/SCALE)+'px';stage.style.top=(oy/SCALE)+'px';}if(USE_ZOOM&&!zoomTextOk()){USE_ZOOM=false;stage.style.zoom='';stage.style.left='0px';stage.style.top='0px';}if(!USE_ZOOM)stage.style.transform=`translate(${ox}px,${oy}px) scale(${SCALE})`; stage.classList.toggle('portrait',PORTRAIT); DPR=Math.min(3,window.devicePixelRatio||1);const k=SCALE*DPR; for(const cv of [scv,fcv]){cv.width=Math.round(W*k);cv.height=Math.round(H*k);} sc.setTransform(k,0,0,k,0,0);fc.setTransform(k,0,0,k,0,0); if(!PORTRAIT){COLS=6;ROWS=4;HORIZON=330;const ax=40,aw=W-600-ax,ay=360,ah=1080-ay-195;const tw=Math.min(aw/COLS,ah/(ROWS*0.66+0.13)); F.tw=tw;F.th=tw*0.66;F.dep=tw*0.12;F.x=ax+(aw-tw*COLS)/2;F.y=ay+ah-(F.th*ROWS+F.dep);} else{COLS=4;ROWS=6;HORIZON=560;const ax=50,aw=W-100,ay=620,ah=H-ay-250;const tw=Math.min(aw/COLS,ah/(ROWS*0.66+0.13)); F.tw=tw;F.th=tw*0.66;F.dep=tw*0.12;F.x=ax+(aw-tw*COLS)/2;F.y=ay+(ah-(F.th*ROWS+F.dep))/2;} // Yard: 8 pens + a big Elephant Enclosure. Landscape 4x3 (enclosure 2x2, bottom right); portrait 2 columns with a wide enclosure row, or 3x4 on short screens. if(!PORTRAIT)yardGrid(50,W-650,290,1080-290-190,4,[1,1,1],[2,1,2,2],0.62,false); else{const L=[[2,[1,1,1,1,1.45],[0,4,2,1]],[3,[1,1,1,1],[1,2,2,2]]].map(q=>yardGrid(40,W-80,660,H-660-250,q[0],q[1],q[2],0.72,true,true)); const k=L[0].s>=L[1].s?0:1;const q=[[2,[1,1,1,1,1.45],[0,4,2,1]],[3,[1,1,1,1],[1,2,2,2]]][k];yardGrid(40,W-80,660,H-660-250,q[0],q[1],q[2],0.72,true);} buildCells();buildDecor();if(S)refreshSpr();} function plotRect(i){const o=CELLS[i];return{x:F.x+o.c*F.tw,y:F.y+o.r*F.th,w:F.tw,h:F.th,cx:F.x+(o.c+0.5)*F.tw,base:F.y+o.r*F.th+F.th*0.6};} function plotAt(x,y){const c=Math.floor((x-F.x)/F.tw),r=Math.floor((y-F.y)/F.th);if(c<0||r<0||c>=COLS||r>=ROWS){ // allow tapping the tall part of a plant on the row below's hit box return -1;}return cellIndex(c,r);} function plotAtPlant(x,y){let i=plotAt(x,y);if(i>=0)return i;if(y>=F.y)return -1; // try plant bodies that extend above their tile (tall trees) const c=Math.floor((x-F.x)/F.tw);for(let r=0;r<ROWS;r++){const j=cellIndex(c,r);if(j<0||j>=S.unlocked)continue;const p=S.plots[j];if(!p.c)continue;const R=plotRect(j); const tall=CROP[p.c].kind==='tree'||CROP[p.c].kind==='palm'||CROP[p.c].kind==='banana'?1.0:0.6;if(y<R.base&&y>R.base-F.tw*tall*(p.g>0.4?1:0.3)&&Math.abs(x-R.cx)<F.tw*0.45&&y<R.y)return j;}return i;} function hillY(x,a,b,c,d){return a+Math.sin(x*b+c)*d+Math.sin(x*b*2.3+c*1.7)*d*0.4;} function buildDecor(){const rng=mulberry(77);const fx0=F.x-30,fx1=F.x+F.tw*COLS+30,fy0=F.y-40,fy1=F.y+F.th*ROWS+F.dep+30; DECOR.tufts=[];DECOR.flowers=[];for(let i=0;i<(PORTRAIT?110:140);i++){const x=rng()*W,y=HORIZON+40+rng()*(H-HORIZON-40);if(x>fx0&&x<fx1&&y>fy0&&y<fy1)continue; if(rng()<0.25)DECOR.flowers.push({x,y,c:['#ff7a9a','#ffd84a','#fff','#c08aff','#ff9a4a'][Math.floor(rng()*5)],s:0.7+rng()*0.6,ph:rng()*6});else DECOR.tufts.push({x,y,s:0.6+rng()*0.8,ph:rng()*6});} DECOR.tufts.sort((a,b)=>a.y-b.y); DECOR.stars=[];for(let i=0;i<120;i++)DECOR.stars.push({x:rng()*W,y:rng()*HORIZON*0.95,r:rng()*1.8+0.4,ph:rng()*6}); if(!DECOR.clouds.length)for(let i=0;i<7;i++)DECOR.clouds.push({x:rng()*W,y:40+rng()*HORIZON*0.45,s:0.6+rng()*0.9,v:6+rng()*10,seed:i}); DECOR.trees=[];let x=-40;while(x<W+40){DECOR.trees.push({x,type:rng()<0.38?'pine':'decid',v:Math.floor(rng()*3),s:0.7+rng()*0.75,ph:rng()*6});x+=40+rng()*70;} DECOR.big=[];{const n=PORTRAIT?5:7,gw=F.tw*COLS+120;for(let k=0;k<n;k++)DECOR.big.push({x:F.x-60+(k+0.5)*gw/n+(rng()-0.5)*40,y:F.y-48-rng()*14,type:k%3===2?'pine':'decid',v:k%3,s:(PORTRAIT?1.7:1.5)+rng()*0.5,ph:rng()*6});} if(!DECOR.bfly.length)for(let i=0;i<5;i++)DECOR.bfly.push({x:rng()*W,y:HORIZON+100+rng()*500,tx:0,ty:0,c:['#ffd84a','#ff8ab0','#8ad0ff','#ffffff','#ffa04a'][i],ph:rng()*6,t:0}); if(!DECOR.ffly.length)for(let i=0;i<30;i++)DECOR.ffly.push({x:rng()*W,y:HORIZON+rng()*(H-HORIZON),ph:rng()*6,v:rng()});} /* ---------------- Seasons: visual state (v1.1) ---------------- SEAV.w = weights of [spring,summer,autumn,winter] (cross-fades over the first 10% of a season); SEAV.snow = snow on the ground. */ let SEAV={i:0,f:0,w:[1,0,0,0],snow:0,id:'spring'}; function seasonVis(T){const i=seasonIdx(T),f=seasonProg(T),w=[0,0,0,0],b=Math.min(1,f/0.1);w[i]=b;w[(i+3)%4]+=1-b; const snow=w[3]*(i===3?Math.min(1,0.35+f*3):1);return{i,f,w,snow,id:SEASONS[i].id};} function mix4(cols,w){const r=[0,0,0];cols.forEach((c,k)=>{const h=hex(c);for(let j=0;j<3;j++)r[j]+=h[j]*w[k];});return r;} const SPAL={ground:[['#9ad468','#86c95a','#68ae46'],['#8fd060','#7cc252','#5ea640'],['#c4c868','#acae52','#8c943e'],['#f2f6fb','#e2eaf3','#cbd8e6']], hill:[['#8cd060','#a8e07a','#74b84e'],['#7cc25a','#9ad66a','#68b04a'],['#d0b850','#e2c868','#b89a3a'],['#e8eff6','#f6f9fc','#d2deea']], canopy:[['#f7b2cc','#f7b2cc','#f7b2cc'],['#3f8a3a','#4a9440','#3a8240'],['#e0502a','#f08a2a','#e8b030'],['#8a6a50','#8a6a50','#8a6a50']], tuft:['#5aa83e','#4e9a36','#8a9a3a','#b8c8c4']}; const snowy=(col,k=1)=>rgb(mixc(hex(col),hex('#eef3f8'),SEAV.snow*k)); const seaGrass=(col,k=1)=>rgb(mixc(mixc(mixc(hex(col),hex('#c0b85a'),SEAV.w[2]*0.45),hex('#a8dc78'),SEAV.w[0]*0.2),hex('#eef3f8'),SEAV.snow*k)); function drawFlake(c,x,y,r){c.save();c.translate(x,y);c.strokeStyle='#fff';c.lineWidth=Math.max(1.5,r*0.28);c.lineCap='round';for(let k=0;k<3;k++){c.rotate(Math.PI/3);c.beginPath();c.moveTo(-r,0);c.lineTo(r,0);c.stroke();}c.restore();} function snowCap(c,pts,th,a){if(a<0.02)return;c.save();c.globalAlpha=Math.min(1,a);c.fillStyle='#fbfdff';c.beginPath();c.moveTo(pts[0][0],pts[0][1]-th*0.3);pts.forEach(p=>c.lineTo(p[0],p[1]-th*0.5)); for(let k=pts.length-1;k>0;k--){const a2=pts[k],b2=pts[k-1];const mx=(a2[0]+b2[0])/2,my=(a2[1]+b2[1])/2;c.quadraticCurveTo(a2[0],a2[1]+th*0.6,mx,my+th*0.8);c.quadraticCurveTo(b2[0],b2[1]+th*0.9,b2[0],b2[1]+th*0.4);} c.closePath();c.fill();c.fillStyle='rgba(190,215,240,0.6)';c.beginPath();pts.forEach((p,k)=>k?c.lineTo(p[0],p[1]+th*0.25):c.moveTo(p[0],p[1]+th*0.25));c.lineWidth=th*0.18;c.strokeStyle='rgba(180,205,235,0.55)';c.stroke();c.restore();} function drawJTree(c,tr,y,t){const s=tr.s,w=SEAV.w,sw=Math.sin(t*1.1+tr.ph)*2*s; if(tr.type==='pine'){c.fillStyle='#6a4a30';c.fillRect(tr.x-3*s,y-14*s,6*s,14*s);const g=rgb(mixc(hex('#2f6a3a'),hex('#3a6a5a'),w[3]*0.5)); [[0,30,26],[-16,24,20],[-30,16,15]].forEach((q,k)=>{const ty=y-14*s+q[0]*s-k*4*s;c.fillStyle=g;c.beginPath();c.moveTo(tr.x-q[1]*s,ty);c.lineTo(tr.x+sw*0.3,ty-q[2]*1.3*s);c.lineTo(tr.x+q[1]*s,ty);c.closePath();c.fill(); if(SEAV.snow>0.02){c.globalAlpha=SEAV.snow;c.fillStyle='#fbfdff';c.beginPath();c.moveTo(tr.x-q[1]*0.55*s,ty-q[2]*0.62*s);c.lineTo(tr.x+sw*0.3,ty-q[2]*1.3*s);c.lineTo(tr.x+q[1]*0.55*s,ty-q[2]*0.62*s);c.quadraticCurveTo(tr.x,ty-q[2]*0.45*s,tr.x-q[1]*0.55*s,ty-q[2]*0.62*s);c.fill();c.globalAlpha=1;}});return;} // deciduous: sakura in spring, green in summer, maple red/orange in autumn, bare + snow in winter c.strokeStyle='#6a4a34';c.lineCap='round';c.lineWidth=5*s;c.beginPath();c.moveTo(tr.x,y);c.lineTo(tr.x,y-22*s);c.stroke();c.lineWidth=3*s; c.beginPath();c.moveTo(tr.x,y-18*s);c.lineTo(tr.x-16*s,y-34*s);c.moveTo(tr.x,y-20*s);c.lineTo(tr.x+15*s,y-36*s);c.moveTo(tr.x,y-22*s);c.lineTo(tr.x+2*s,y-44*s);c.stroke(); const leafA=1-w[3];if(leafA>0.02){const col=rgb(mix4(SPAL.canopy.map(q=>q[tr.v]),[w[0],w[1],w[2],0].map(v=>v/Math.max(0.001,leafA))));c.globalAlpha=leafA;c.fillStyle=col; c.beginPath();c.arc(tr.x+sw,y-34*s,22*s,0,TAU);c.arc(tr.x+16*s+sw,y-26*s,17*s,0,TAU);c.arc(tr.x-16*s+sw,y-25*s,16*s,0,TAU);c.fill(); if(w[0]>0.05){c.globalAlpha=leafA*w[0];c.fillStyle='#ffe0ec';for(let k=0;k<6;k++){c.beginPath();c.arc(tr.x+sw+Math.cos(k*2.4+tr.ph)*16*s,y-30*s+Math.sin(k*1.7+tr.ph)*12*s,3*s,0,TAU);c.fill();}} c.globalAlpha=leafA*0.2;c.fillStyle='#fff';c.beginPath();c.arc(tr.x-6*s+sw,y-42*s,9*s,0,TAU);c.fill();c.globalAlpha=1;} if(SEAV.snow>0.02){c.globalAlpha=SEAV.snow;c.strokeStyle='#fbfdff';c.lineWidth=2.4*s;c.beginPath();c.moveTo(tr.x-4*s,y-30*s);c.lineTo(tr.x-14*s,y-36*s);c.moveTo(tr.x+4*s,y-31*s);c.lineTo(tr.x+14*s,y-38*s);c.moveTo(tr.x+1*s,y-40*s);c.lineTo(tr.x+2*s,y-45*s);c.stroke();c.globalAlpha=1;}} let sfx=[]; // seasonal particles: petals, maple leaves, snowflakes function drawSeasonFx(c,t,rain,night){const w=SEAV.w;const want={petal:Math.round(w[0]*(1-rain*0.7)*(PORTRAIT?36:48)),leaf:Math.round(w[2]*(PORTRAIT?20:26)),flake:Math.round(w[3]*((PORTRAIT?30:40)+rain*(PORTRAIT?220:300)))}; for(const k in want){let n=sfx.filter(p=>p.k===k).length;while(n<want[k]){sfx.push({k,x:rand(-60,W),y:rand(-H*0.6,H),v:k==='flake'?rand(50,130):rand(40,80),vx:k==='flake'?rand(-15,15):rand(30,70),r:k==='flake'?rand(2.5,6):rand(8,13),rot:rand(0,6),vr:rand(-2,2),ph:rand(0,6),c:k==='leaf'?['#e0502a','#f08a2a','#e8b030','#d0402a'][randi(0,3)]:k==='petal'?['#ffc0d6','#ffd8e6','#f7a8c4'][randi(0,2)]:'#fff'});n++;} if(n>want[k]){let drop=n-want[k];sfx=sfx.filter(p=>!(p.k===k&&p.y<-10&&drop-->0));}} c.save();c.globalAlpha=1-night*0.45;sfx.forEach(p=>{p.y+=p.v*dtFrame;p.x+=(p.vx+Math.sin(t*1.3+p.ph)*20)*dtFrame;p.rot+=p.vr*dtFrame;if(p.y>H+20||p.x>W+60){p.y=rand(-120,-10);p.x=rand(-60,W);} c.save();c.translate(p.x,p.y);c.rotate(p.rot);if(p.k==='flake'){c.fillStyle='rgba(255,255,255,0.92)';c.beginPath();c.arc(0,0,p.r,0,TAU);c.fill();if(p.r>5)drawFlake(c,0,0,p.r*1.4);} else if(p.k==='petal'){c.fillStyle=p.c;c.beginPath();c.moveTo(0,-p.r*0.5);c.quadraticCurveTo(p.r*0.7,-p.r*0.4,0,p.r*0.6);c.quadraticCurveTo(-p.r*0.7,-p.r*0.4,0,-p.r*0.5);c.fill();} else{c.fillStyle=p.c;c.beginPath();for(let q=0;q<10;q++){const a=q/10*TAU-Math.PI/2,rr=q%2?p.r*0.45:p.r;c.lineTo(Math.cos(a)*rr,Math.sin(a)*rr);}c.closePath();c.fill();c.strokeStyle='rgba(120,40,10,0.5)';c.lineWidth=1.5;c.beginPath();c.moveTo(0,0);c.lineTo(0,p.r*1.3);c.stroke();} c.restore();});c.restore();} /* ---------------- Sky & landscape ---------------- */ const SKY=[[0,'#0b1236','#232c5a'],[4.6,'#0f1840','#2c3466'],[5.8,'#4a5a9a','#ff9a7a'],[7,'#5aa0e6','#ffd8a8'],[9,'#3f9bf0','#bfe6ff'],[16,'#3f97ec','#c8ecff'],[17.8,'#4a7ac8','#ffc890'],[18.9,'#3a4a8a','#ff8a6a'],[19.8,'#1a2256','#5a4a7a'],[21,'#0d1440','#2a3062'],[24,'#0b1236','#232c5a']]; const TINT=[[0,'#4a58a8'],[4.8,'#4a58a8'],[6.2,'#ffc8b0'],[8,'#ffffff'],[16.6,'#ffffff'],[18.2,'#ffd0a0'],[19.3,'#b08ab8'],[20.4,'#4a58a8'],[24,'#4a58a8']]; function keyAt(arr,h,idx){for(let i=0;i<arr.length-1;i++)if(h>=arr[i][0]&&h<=arr[i+1][0]){const t=(h-arr[i][0])/(arr[i+1][0]-arr[i][0]);return mixc(hex(arr[i][idx]),hex(arr[i+1][idx]),sstep(t));}return hex(arr[0][idx]);} function nightAmt(h){if(h>=20.4||h<4.8)return 1;if(h>=18.6)return (h-18.6)/1.8;if(h<6.2)return 1-(h-4.8)/1.4;return 0;} function drawSky(c,T,t,rain){const h=hourAt(T);let top=keyAt(SKY,h,1),bot=keyAt(SKY,h,2);const gray=[120,130,145];top=mixc(top,gray,rain*0.55);bot=mixc(bot,[170,178,188],rain*0.55); const g=c.createLinearGradient(0,0,0,HORIZON+60);g.addColorStop(0,rgb(top));g.addColorStop(1,rgb(bot));c.fillStyle=g;c.fillRect(0,0,W,HORIZON+80); const na=nightAmt(h);if(na>0){DECOR.stars.forEach(s=>{c.fillStyle=`rgba(255,255,230,${na*(1-rain)*(0.5+0.5*Math.sin(t*2+s.ph))})`;c.beginPath();c.arc(s.x,s.y,s.r,0,TAU);c.fill();});} // sun if(h>5.5&&h<19.6){const q=(h-5.5)/14.1;const sx=lerp(W*0.08,W*0.92,q),sy=HORIZON+20-Math.sin(q*Math.PI)*(HORIZON*0.78);const sun=c.createRadialGradient(sx,sy,10,sx,sy,170); const warm=Math.abs(q-0.5)*2;sun.addColorStop(0,`rgba(255,250,220,${0.95-rain*0.6})`);sun.addColorStop(0.25,`rgba(255,${230-warm*60},${150-warm*60},${0.45-rain*0.3})`);sun.addColorStop(1,'rgba(255,200,120,0)');c.fillStyle=sun;c.beginPath();c.arc(sx,sy,170,0,TAU);c.fill(); c.fillStyle=`rgba(255,${248-warm*40},${200-warm*80},${1-rain*0.6})`;c.beginPath();c.arc(sx,sy,42,0,TAU);c.fill();} if(na>0.05){const hh=h>=19?h-19:h+5;const q=hh/11;const mx=lerp(W*0.12,W*0.88,q),my=HORIZON-Math.sin(q*Math.PI)*HORIZON*0.7;c.globalAlpha=na*(1-rain*0.7); const mg=c.createRadialGradient(mx,my,10,mx,my,120);mg.addColorStop(0,'rgba(220,230,255,0.5)');mg.addColorStop(1,'rgba(200,210,255,0)');c.fillStyle=mg;c.beginPath();c.arc(mx,my,120,0,TAU);c.fill(); c.fillStyle='#f4f2e0';c.beginPath();c.arc(mx,my,32,0,TAU);c.fill();c.fillStyle='rgba(180,180,160,0.35)';[[-8,-6,7],[10,8,5],[4,-14,4]].forEach(a=>{c.beginPath();c.arc(mx+a[0],my+a[1],a[2],0,TAU);c.fill();});c.globalAlpha=1;} // clouds const ccol=mixc(mixc([255,255,255],hex('#8890b8'),na*0.8),[150,155,165],rain*0.6); DECOR.clouds.forEach((cl,k)=>{cl.x+=cl.v*(1+rain*2)*dtFrame;if(cl.x>W+220*cl.s)cl.x=-220*cl.s;drawCloud(c,cl.x,cl.y,cl.s*(1+rain*0.3),ccol,cl.seed);}); if(rain>0.01){for(let k=0;k<4;k++){const x=((t*25+k*W/4)%(W+500))-250;c.globalAlpha=rain*0.85;drawCloud(c,x,40+k%2*50,1.8,mixc(ccol,[110,115,125],0.4),k+20);c.globalAlpha=1;}}} function drawCloud(c,x,y,s,col,seed){const r=mulberry(seed*99+1);c.save();c.translate(x,y);c.scale(s,s); c.fillStyle=rgb(mixc(col,[0,0,0],0.12),0.9);for(let i=0;i<6;i++){const px=(i-2.5)*34,py=10-Math.sin(i/5*Math.PI)*22;c.beginPath();c.arc(px,py+10,30+r()*16,0,TAU);c.fill();} c.fillStyle=rgb(col,0.96);for(let i=0;i<6;i++){const px=(i-2.5)*34,py=-Math.sin(i/5*Math.PI)*24;c.beginPath();c.arc(px,py,28+r()*18,0,TAU);c.fill();}c.restore();} function drawLand(c,T,t,rain){const h=hourAt(T); // far mountains with a tall peak c.fillStyle=rgb(mixc(hex('#7f9fc8'),[150,160,170],rain*0.4));c.beginPath();c.moveTo(0,HORIZON); for(let x=0;x<=W;x+=20){let y=hillY(x,HORIZON-80,0.004,1,40);const pk=Math.exp(-Math.pow((x-W*0.66)/120,2))*110;c.lineTo(x,y-pk);}c.lineTo(W,HORIZON+20);c.lineTo(0,HORIZON+20);c.fill(); {const cw=[70,48,70,120],ca=[0.75,0.45,0.7,0.95];const capW=cw.reduce((a,v,k)=>a+v*SEAV.w[k],0),capA=ca.reduce((a,v,k)=>a+v*SEAV.w[k],0); c.fillStyle=`rgba(255,255,255,${capA*(1-rain*0.3)})`;c.beginPath();const x0=W*0.66-capW,x1=W*0.66+capW;for(let x=x0;x<=x1+0.1;x+=8){const y=hillY(x,HORIZON-80,0.004,1,40)-Math.exp(-Math.pow((x-W*0.66)/120,2))*110;x===x0?c.moveTo(x,y):c.lineTo(x,y);} for(let x=x1;x>=x0;x-=capW/5){const y=hillY(x,HORIZON-80,0.004,1,40)-Math.exp(-Math.pow((x-W*0.66)/120,2))*110;c.lineTo(x,y+capW*0.35+Math.sin(x*0.15)*capW*0.12);}c.fill(); if(SEAV.snow>0.02){c.fillStyle=`rgba(255,255,255,${0.35*SEAV.snow})`;c.beginPath();c.moveTo(0,HORIZON);for(let x=0;x<=W;x+=20){c.lineTo(x,hillY(x,HORIZON-80,0.004,1,40)-Math.exp(-Math.pow((x-W*0.66)/120,2))*110);}c.lineTo(W,HORIZON+20);c.lineTo(0,HORIZON+20);c.fill();}} // terraced paddy hill const hy=x=>hillY(x,HORIZON-30,0.0032,3.2,28);c.save();c.beginPath();c.moveTo(0,HORIZON+40);for(let x=0;x<=W;x+=20)c.lineTo(x,hy(x));c.lineTo(W,HORIZON+40);c.closePath(); const hl=j=>rgb(mixc(mix4(SPAL.hill.map(q=>q[j]),[SEAV.w[0],SEAV.w[1],SEAV.w[2],SEAV.w[3]]),hex(SPAL.hill[3][j]),0)); c.fillStyle=hl(0);c.fill();c.clip();for(let k=0;k<7;k++){c.beginPath();for(let x=0;x<=W;x+=20){const y=hy(x)+8+k*11+Math.sin(x*0.01+k)*3;x?c.lineTo(x,y):c.moveTo(x,y);}c.strokeStyle=k%2?hl(1):hl(2);c.lineWidth=6;c.stroke();} c.strokeStyle='rgba(200,235,255,0.35)';c.lineWidth=2;for(let k=0;k<7;k++){c.beginPath();for(let x=0;x<=W;x+=20){const y=hy(x)+12+k*11+Math.sin(x*0.01+k)*3;x?c.lineTo(x,y):c.moveTo(x,y);}c.stroke();}c.restore(); // tree line DECOR.trees.forEach(tr=>drawJTree(c,tr,HORIZON+6,t)); // ground const gw=[SEAV.w[0],SEAV.w[1],SEAV.w[2],0];const gs=gw.reduce((a,b)=>a+b,0)||1;const gc=j=>rgb(mixc(mix4(SPAL.ground.map(q=>q[j]),gw.map(v=>v/gs)),hex(SPAL.ground[3][j]),SEAV.snow)); const gg=c.createLinearGradient(0,HORIZON,0,H);gg.addColorStop(0,gc(0));gg.addColorStop(0.35,gc(1));gg.addColorStop(1,gc(2));c.fillStyle=gg;c.fillRect(0,HORIZON,W,H-HORIZON); c.fillStyle='rgba(255,255,255,0.06)';for(let i=0;i<14;i++){c.beginPath();c.ellipse((i*397)%W,HORIZON+60+((i*211)%(H-HORIZON)),160,30,0,0,TAU);c.fill();} DECOR.big.forEach(tr=>drawJTree(c,tr,tr.y,t)); // dirt path c.fillStyle=rgb(mixc(hex('#d9b27a'),hex('#e6e9ee'),SEAV.snow*0.6));c.beginPath();const px=PORTRAIT?W*0.5:F.x-0;c.moveTo(px-50,H);c.bezierCurveTo(px-20,H*0.8,PORTRAIT?px-260:px-140,HORIZON+120,PORTRAIT?140:F.x-60,HORIZON+20);c.lineTo(PORTRAIT?200:F.x-20,HORIZON+20);c.bezierCurveTo(PORTRAIT?px-200:px-90,HORIZON+120,px+30,H*0.8,px+60,H);c.fill();} function drawHut(c,x,y,s,t,night){c.save();c.translate(x,y);c.scale(s,s); c.fillStyle='rgba(40,20,5,0.22)';c.beginPath();c.ellipse(0,4,150,18,0,0,TAU);c.fill(); c.fillStyle='#f3e6c8';c.fillRect(-110,-90,220,92);c.fillStyle='#e2cfa6';c.fillRect(-110,-20,220,22); c.fillStyle='#a8683a';for(const px of [-100,-30,30,100]){c.fillRect(px-5,-92,10,94);} c.fillStyle='#7a4a24';roundRect(c,-24,-66,48,68,[24,24,0,0]);c.fill(); const wg=night>0.1?`rgba(255,${200+night*30},120,${0.6+night*0.4})`:'#5a8ab0';c.fillStyle=wg;roundRect(c,-85,-68,40,32,6);c.fill();roundRect(c,48,-68,40,32,6);c.fill(); c.strokeStyle='#7a4a24';c.lineWidth=4;c.strokeRect(-85,-68,40,32);c.strokeRect(48,-68,40,32); // clay tile roof c.fillStyle='#c8603a';c.beginPath();c.moveTo(-150,-82);c.lineTo(-70,-150);c.lineTo(70,-150);c.lineTo(150,-82);c.closePath();c.fill(); c.strokeStyle='#a8482a';c.lineWidth=3;for(let i=0;i<14;i++){const q=i/13;c.beginPath();c.moveTo(lerp(-150,150,q),-82);c.lineTo(lerp(-70,70,q),-150);c.stroke();} c.fillStyle='#e07a4a';c.fillRect(-72,-156,144,10);c.fillStyle='rgba(0,0,0,0.15)';c.fillRect(-150,-84,300,8); snowCap(c,[[-150,-84],[-70,-152],[70,-152],[150,-84]],22,SEAV.snow); if(S&&S.up.lantern){drawLantern(c,128,-60,1,t);} c.restore();} function drawTuft(c,x,y,s,t,wind,col='#4e9a36'){const sw=Math.sin(t*2+x*0.02)*3*wind;c.strokeStyle=col;c.lineWidth=3*s;c.lineCap='round';c.beginPath(); for(let i=-2;i<=2;i++){c.moveTo(x+i*3*s,y);c.quadraticCurveTo(x+i*5*s,y-10*s,x+i*7*s+sw,y-(16-Math.abs(i)*3)*s);}c.stroke();} function drawFlower(c,f,t){c.save();c.translate(f.x,f.y);c.scale(f.s,f.s);c.rotate(Math.sin(t*1.5+f.ph)*0.08);c.strokeStyle='#4e9a36';c.lineWidth=2.5;c.beginPath();c.moveTo(0,0);c.lineTo(0,-14);c.stroke(); c.fillStyle=f.c;for(let i=0;i<5;i++){const a=i/5*TAU;c.beginPath();c.arc(Math.cos(a)*5,-14+Math.sin(a)*5,4.5,0,TAU);c.fill();}c.fillStyle='#ffb02a';c.beginPath();c.arc(0,-14,3.5,0,TAU);c.fill();c.restore();} /* ---------------- Field ---------------- */ function drawField(c,T,t,wind,rain){const gx=F.x,gy=F.y,gw=F.tw*COLS,gh=F.th*ROWS; // fence behind c.strokeStyle='#a5703f';c.lineWidth=8;c.lineCap='round';const fy=gy-14;c.beginPath();c.moveTo(gx-20,fy-26);c.lineTo(gx+gw+20,fy-26);c.moveTo(gx-20,fy-8);c.lineTo(gx+gw+20,fy-8);c.stroke(); c.fillStyle='#8a5a30';for(let x=gx-20;x<=gx+gw+21;x+=gw/COLS/1.5){roundRect(c,x-6,fy-44,12,46,[6,6,2,2]);c.fill();} if(SEAV.snow>0.02){c.globalAlpha=SEAV.snow;c.strokeStyle='#fbfdff';c.lineWidth=5;c.beginPath();c.moveTo(gx-20,fy-30);c.lineTo(gx+gw+20,fy-30);c.stroke();c.fillStyle='#fbfdff';for(let x=gx-20;x<=gx+gw+21;x+=gw/COLS/1.5){c.beginPath();c.ellipse(x,fy-44,8,5,0,0,TAU);c.fill();}c.globalAlpha=1;} // dirt rim c.fillStyle='rgba(40,20,5,0.25)';roundRect(c,gx-18,gy-8,gw+36,gh+F.dep+34,28);c.fill(); c.fillStyle='#b98250';roundRect(c,gx-16,gy-12,gw+32,gh+F.dep+28,28);c.fill(); c.fillStyle='#d3a06a';roundRect(c,gx-16,gy-12,gw+32,14,[28,28,0,0]);c.fill(); if(SEAV.snow>0.02){c.globalAlpha=SEAV.snow;c.fillStyle='#fbfdff';roundRect(c,gx-16,gy-16,gw+32,16,[28,28,6,6]);c.fill();c.globalAlpha=1;} drawAnchors(c,t); const hov=hoverPlot;let fmDone=false; for(let r=0;r<ROWS;r++){ for(let col=0;col<COLS;col++){const i=cellIndex(col,r);drawTile(c,i,T,t,i===hov);} if(!fmDone&&FM.y<r+0.7){drawFarmerNow(c,t);fmDone=true;} for(let col=0;col<COLS;col++){const i=cellIndex(col,r);if(i>=S.unlocked)continue;const p=S.plots[i],R=plotRect(i); if(p.spr)drawSprinkler(c,R.cx,R.base,F.tw/150,t);else if(p.c)drawCropInPlot(c,i,p,R,t,wind);}} if(!fmDone)drawFarmerNow(c,t);} /* Tall crops (fruit trees, coconut, banana, corn) are sized to stay within ~1.3x their own cell. Their upper part fades out (soft gradient mask on an offscreen layer) when the plot above holds a crop, so smaller plants and tags behind stay visible; it fades more when the pointer/finger is on that plot. Taps always follow the plot cell (see plotAtPlant). */ const PLANT_SCALE={tree:0.84,palm:0.64,banana:0.92,corn:1.0}; const TALL={tree:1,palm:1,banana:1,corn:1}; const plantScale=cr=>F.tw*(PLANT_SCALE[cr.kind]||1.3); let plantLayer=null; function plotAbove(i){const o=CELLS[i];if(!o||o.r===0)return -1;return cellIndex(o.c,o.r-1);} function drawCropInPlot(c,i,p,R,t,wind){if(p.wilt){c.save();const by0=TALL[CROP[p.c].kind]?R.y+F.th*0.84:R.base;c.translate(R.cx,by0);c.scale(1.04,0.8);c.rotate(Math.sin(t*0.8+p.ph)*0.03+0.08);c.translate(-R.cx,-by0);c.filter='saturate(0.3) sepia(0.55) brightness(0.95)';drawCropInPlot0(c,i,p,R,t,0.2);c.filter='none';c.restore();return;}drawCropInPlot0(c,i,p,R,t,wind);} function drawCropInPlot0(c,i,p,R,t,wind){const cr=CROP[p.c],s=plantScale(cr),by=TALL[cr.kind]?R.y+F.th*0.84:R.base; let tgt=1;if(TALL[cr.kind]&&p.g>=0.4){const j=plotAbove(i);if(j>=0&&j<S.unlocked){const q=S.plots[j];if(q.c||q.spr)tgt=0.42;if(hoverPlot===j||touchPlot===j)tgt=0.22;}} p.fade=lerp(typeof p.fade==='number'?p.fade:tgt,tgt,Math.min(1,dtFrame*6)); if(p.fade>0.985){drawPlant(c,p,R.cx,by,s,t,wind);return;} // offscreen layer in scene units (same device scale as the scene canvas) const k=SCALE*DPR,bw=F.tw*1.9,bh=F.tw*1.75,x0=R.cx-bw/2,y0=by-bh+F.tw*0.18;const pw=Math.ceil(bw*k),ph=Math.ceil(bh*k); if(!plantLayer)plantLayer=document.createElement('canvas');const L=plantLayer;if(L.width<pw||L.height<ph){L.width=Math.max(L.width,pw);L.height=Math.max(L.height,ph);} const o=L.getContext('2d');o.setTransform(1,0,0,1,0,0);o.clearRect(0,0,pw+2,ph+2);o.setTransform(k,0,0,k,-x0*k,-y0*k);drawPlant(o,p,R.cx,by,s,t,wind); // mask: full alpha inside its own cell, fading to p.fade above the cell top edge const cut=R.y+F.th*0.04;const g=o.createLinearGradient(0,cut-F.th*0.22,0,cut+F.th*0.1);g.addColorStop(0,`rgba(0,0,0,${p.fade})`);g.addColorStop(1,'rgba(0,0,0,1)'); o.globalCompositeOperation='destination-in';o.fillStyle=g;o.fillRect(x0,y0,bw,bh);o.globalCompositeOperation='source-over'; c.drawImage(L,0,0,pw,ph,x0,y0,pw/k,ph/k);} function drawTile(c,i,T,t,hov){const R=plotRect(i),m=F.tw*0.045,x=R.x+m,y=R.y+m,w=R.w-m*2,h=R.h-m*2,d=F.dep; if(i>=S.unlocked){c.fillStyle=seaGrass('#6eb048',0.8);roundRect(c,x,y+d*0.4,w,h+d*0.6,14);c.fill();c.fillStyle=seaGrass('#86c95a');roundRect(c,x,y,w,h,14);c.fill(); const tcol=seaGrass('#5aa83e',0.6);drawTuft(c,x+w*0.25,y+h*0.6,0.9,t,1,tcol);drawTuft(c,x+w*0.7,y+h*0.45,0.8,t,1,tcol); if(i===S.unlocked){c.save();c.setLineDash([10,8]);c.strokeStyle=hov?'#fff':'rgba(255,255,255,0.7)';c.lineWidth=4;roundRect(c,x+4,y+4,w-8,h-8,12);c.stroke();c.restore();}return;} const p=S.plots[i];const wet=p.c||p.spr?(plotWet(p,i,T)?1:0):0;p.wv=lerp(p.wv||0,wet,0.06); const top=mixc(hex('#a8743f'),hex('#6e4526'),p.wv),side=mixc(hex('#7a4d28'),hex('#4e2f18'),p.wv); c.fillStyle=rgb(side);roundRect(c,x,y+d,w,h,14);c.fill();c.fillStyle=rgb(top);roundRect(c,x,y,w,h,14);c.fill(); c.strokeStyle=rgb(mixc(top,[40,20,5],0.35));c.lineWidth=F.tw*0.02;c.lineCap='round';for(let k=1;k<4;k++){const yy=y+h*k/4;c.beginPath();c.moveTo(x+w*0.12,yy);c.quadraticCurveTo(x+w*0.5,yy+3,x+w*0.88,yy);c.stroke();} c.strokeStyle=rgb(mixc(top,[255,230,190],0.25));c.lineWidth=F.tw*0.012;for(let k=1;k<4;k++){const yy=y+h*k/4-F.tw*0.018;c.beginPath();c.moveTo(x+w*0.14,yy);c.quadraticCurveTo(x+w*0.5,yy+3,x+w*0.86,yy);c.stroke();} if(p.fert&&p.c){c.fillStyle='rgba(70,40,15,0.55)';for(let k=0;k<9;k++){const fx=x+w*(0.18+0.64*hash(i*31+k*7)),fy=y+h*(0.2+0.6*hash(i*17+k*13));c.beginPath();c.arc(fx,fy,F.tw*0.018,0,TAU);c.fill();} c.fillStyle='rgba(140,230,90,0.9)';const sp=(t*2+i)%3;if(sp<1){c.beginPath();c.arc(x+w*0.85,y+h*0.25-sp*10,4,0,TAU);c.fill();}} if(p.wv>0.05){c.fillStyle=`rgba(180,220,255,${0.18*p.wv})`;c.beginPath();c.ellipse(x+w*0.3,y+h*0.3,w*0.15,h*0.08,-0.2,0,TAU);c.fill();} if(hov){c.strokeStyle='rgba(255,255,255,0.95)';c.lineWidth=5;roundRect(c,x+2,y+2,w-4,h-4,13);c.stroke();}} function drawSprinkler(c,x,y,s,t){drawSprinklerIcon(c,x,y-s*30,s*1.1);c.save();c.translate(x,y-s*62);c.rotate(t*2);c.strokeStyle='rgba(120,200,255,0.75)';c.lineWidth=3; for(let k=0;k<3;k++){c.rotate(TAU/3);c.beginPath();for(let q=0;q<10;q++){const r=q*s*9;c.lineTo(r,Math.pow(q,1.6)*s*2);}c.stroke();}c.restore();} function drawSign(c,i,t){const R=plotRect(i);const x=R.cx,y=R.y+R.h*0.5+Math.sin(t*2)*3;const price=plotPrice(S.unlocked); c.fillStyle='#8a5a30';c.fillRect(x-4,y,8,R.h*0.35);c.fillStyle='rgba(0,0,0,0.2)';roundRect(c,x-62,y-38,124,58,14);c.fill(); c.fillStyle=S.coins>=price?'#ffe68a':'#f3dfb8';roundRect(c,x-62,y-44,124,58,14);c.fill();c.strokeStyle='#a5663a';c.lineWidth=4;roundRect(c,x-62,y-44,124,58,14);c.stroke(); drawCoin(c,x-34,y-15,15);c.fillStyle='#6a3d16';c.font='700 26px Fredoka';c.textAlign='left';c.textBaseline='middle';c.fillText(fmt(price),x-14,y-14);} function drawCoin(c,x,y,r){c.fillStyle=rgrad(c,x,y,r,[[0,'#fff6b0'],[0.3,'#ffd23f'],[0.8,'#f0a400'],[1,'#c87800']]);c.beginPath();c.arc(x,y,r,0,TAU);c.fill();c.strokeStyle='rgba(255,250,200,0.75)';c.lineWidth=r*0.16;c.beginPath();c.arc(x,y,r*0.6,0,TAU);c.stroke();} function drawDrop(c,x,y,r,col='#4aa8f0'){c.fillStyle=col;c.beginPath();c.moveTo(x,y-r*1.3);c.bezierCurveTo(x+r*1.1,y-r*0.1,x+r,y+r,x,y+r);c.bezierCurveTo(x-r,y+r,x-r*1.1,y-r*0.1,x,y-r*1.3);c.fill();c.fillStyle='rgba(255,255,255,0.6)';c.beginPath();c.ellipse(x-r*0.35,y+r*0.1,r*0.18,r*0.32,0.3,0,TAU);c.fill();} function pill(c,x,y,w,h,fill,stroke){c.fillStyle='rgba(60,30,10,0.25)';roundRect(c,x-w/2,y-h/2+4,w,h,h/2);c.fill();c.fillStyle=fill;roundRect(c,x-w/2,y-h/2,w,h,h/2);c.fill();if(stroke){c.strokeStyle=stroke;c.lineWidth=3;roundRect(c,x-w/2,y-h/2,w,h,h/2);c.stroke();}} function drawIndicators(c,T,t){c.textBaseline='middle';for(let i=0;i<S.unlocked;i++){const p=S.plots[i];if(!p.c)continue;const R=plotRect(i);const x=R.cx,y=R.y+R.h-F.tw*0.02; if(p.g>=1){const b=Math.abs(Math.sin(t*4+p.ph))*6;pill(c,x,y-b,96,34,'#ffe14a','#fff');c.fillStyle='#8a4a00';c.font='700 22px Fredoka';c.textAlign='center';c.fillText('Ready!',x,y-b+1); if(Math.random()<0.04)spawn('spark',R.cx+rand(-F.tw*0.3,F.tw*0.3),R.base-rand(10,F.tw*0.6),{n:1});continue;} if(p.wilt){const b=Math.abs(Math.sin(t*5))*5;pill(c,x,y-b,132,36,'#ffd0b0','#e0603a');c.fillStyle='#8a2a00';c.font='700 21px Fredoka';c.textAlign='center';c.fillText('Wilted!',x-12,y-b+1);drawDrop(c,x+48,y-b,11);continue;} const wet=plotWet(p,i,T);const left=(1-p.g)/growRate(p,i,T);const w=SET.timers?118:52; pill(c,x,y,w,36,wet?'rgba(255,250,240,0.95)':'#dff0ff',wet?null:'#4aa8f0');const rx=x-w/2+20; c.strokeStyle='rgba(120,80,40,0.25)';c.lineWidth=6;c.beginPath();c.arc(rx,y,11,0,TAU);c.stroke();c.strokeStyle=wet?'#5ab83a':'#f0a020';c.beginPath();c.arc(rx,y,11,-Math.PI/2,-Math.PI/2+TAU*p.g);c.stroke(); if(SET.timers){c.fillStyle='#6a3d16';c.font='600 22px Fredoka';c.textAlign='left';c.fillText(fmtT(left),rx+18,y+1);} if(!wet){const thirsty=(p.dry||0)>WILT_T*0.5;const s=1+Math.sin(t*(thirsty?12:6))*(thirsty?0.22:0.12);drawDrop(c,x+w/2+4,y-28,11*s,thirsty?'#ff8a4a':'#4aa8f0');} if(p.fert){c.fillStyle='#7bd04a';c.strokeStyle='#fff';c.lineWidth=3;c.beginPath();c.arc(x-w/2-6,y-22,11,0,TAU);c.fill();c.stroke();c.fillStyle='#fff';c.font='700 18px Fredoka';c.textAlign='center';c.fillText('+',x-w/2-6,y-21);} const cr=CROP[p.c];if(cr.regrow&&p.left>0){for(let k=0;k<p.left;k++){c.fillStyle=k<p.left?'#7bd04a':'#ccc';c.beginPath();c.arc(x-(p.left-1)*7+k*14,y+26,5,0,TAU);c.fill();}}}} /* ---------------- Ambient life ---------------- */ let birds=[]; function drawAmbient(c,T,t,rain,night){ if(night<0.5&&rain<0.3&&SEAV.w[3]<0.5){DECOR.bfly.forEach(b=>{b.t-=dtFrame;if(b.t<=0){b.tx=rand(40,PORTRAIT?W-40:W-560);b.ty=rand(HORIZON+60,PORTRAIT?H-300:H-200);b.t=rand(2,5);} b.x+=(b.tx-b.x)*dtFrame*0.6+Math.sin(t*3+b.ph)*0.8;b.y+=(b.ty-b.y)*dtFrame*0.6+Math.cos(t*4.3+b.ph)*0.8;const fl=Math.abs(Math.sin(t*14+b.ph)); c.save();c.translate(b.x,b.y);c.globalAlpha=1-night*2;c.fillStyle=b.c;c.beginPath();c.ellipse(-7*fl,-3,9*fl+1,7,0.4,0,TAU);c.ellipse(7*fl,-3,9*fl+1,7,-0.4,0,TAU);c.fill(); c.fillStyle='rgba(0,0,0,0.15)';c.beginPath();c.ellipse(-5*fl,5,6*fl+1,4,0.6,0,TAU);c.ellipse(5*fl,5,6*fl+1,4,-0.6,0,TAU);c.fill();c.fillStyle='#4a3020';c.fillRect(-1.5,-7,3,14);c.restore();c.globalAlpha=1;});} if(night<0.4&&Math.random()<dtFrame*0.05&&birds.length===0){const n=randi(3,6),y=rand(70,HORIZON*0.6),dir=Math.random()<0.5?1:-1;for(let k=0;k<n;k++)birds.push({x:dir>0?-40-k*30:W+40+k*30,y:y+Math.abs(k-n/2)*16,v:dir*rand(90,120),ph:rand(0,6)});if(Math.random()<0.6)AU.chirp();} birds.forEach(b=>{b.x+=b.v*dtFrame;const f=Math.sin(t*10+b.ph)*8;c.strokeStyle=rgb(mixc([60,50,60],[30,30,50],night));c.lineWidth=3;c.lineCap='round';c.beginPath();c.moveTo(b.x-12,b.y-f);c.quadraticCurveTo(b.x-5,b.y-4,b.x,b.y);c.quadraticCurveTo(b.x+5,b.y-4,b.x+12,b.y-f);c.stroke();}); birds=birds.filter(b=>b.x>-200&&b.x<W+200);} function drawGlows(c,T,t,night,rain){if(night<0.02)return;c.save();c.globalCompositeOperation='lighter'; const hx=HUT.x,hy=HUT.y;(VIEW==='yard'?[[0,-128*HUT.s],[-70*HUT.s,-52*HUT.s],[70*HUT.s,-52*HUT.s]]:[[-65*HUT.s,-52*HUT.s],[68*HUT.s,-52*HUT.s]]).forEach(o=>{const g=c.createRadialGradient(hx+o[0],hy+o[1],4,hx+o[0],hy+o[1],90*HUT.s);g.addColorStop(0,`rgba(255,190,90,${0.5*night})`);g.addColorStop(1,'rgba(255,150,50,0)');c.fillStyle=g;c.beginPath();c.arc(hx+o[0],hy+o[1],90*HUT.s,0,TAU);c.fill();}); if(S.up.lantern&&VIEW!=='yard'){const lx=hx+128*HUT.s,ly=hy-60*HUT.s;const g=c.createRadialGradient(lx,ly,4,lx,ly,160*HUT.s);g.addColorStop(0,`rgba(255,120,160,${0.6*night})`);g.addColorStop(1,'rgba(255,100,150,0)');c.fillStyle=g;c.beginPath();c.arc(lx,ly,160*HUT.s,0,TAU);c.fill();} const ffA=SEAV.w[1]+0.3*(SEAV.w[0]+SEAV.w[2]);if(rain<0.5&&ffA>0.02)DECOR.ffly.forEach((f,k)=>{if(k/DECOR.ffly.length>ffA)return;const x=f.x+Math.sin(t*0.5+f.ph)*40,y=f.y+Math.cos(t*0.7+f.ph*2)*25;const a=night*(0.5+0.5*Math.sin(t*3+f.ph*5));const g=c.createRadialGradient(x,y,0,x,y,14);g.addColorStop(0,`rgba(230,255,120,${a})`);g.addColorStop(1,'rgba(200,255,80,0)');c.fillStyle=g;c.beginPath();c.arc(x,y,14,0,TAU);c.fill();}); c.restore();} let rainDrops=[]; function drawRain(c,rain,t){if(rain<0.01){rainDrops.length=0;return;}const want=Math.floor(rain*(PORTRAIT?260:340));while(rainDrops.length<want)rainDrops.push({x:rand(-100,W),y:rand(-H,0),v:rand(900,1300)}); if(rainDrops.length>want)rainDrops.length=want;c.strokeStyle=`rgba(210,225,255,${0.55*rain})`;c.lineWidth=2;c.beginPath(); rainDrops.forEach(d=>{d.y+=d.v*dtFrame;d.x+=d.v*0.18*dtFrame;if(d.y>H){if(Math.random()<0.25)ripples.push({x:d.x,y:rand(HORIZON+20,H),r:0});d.y=rand(-200,0);d.x=rand(-200,W);}c.moveTo(d.x,d.y);c.lineTo(d.x-5,d.y-26);});c.stroke(); c.strokeStyle=`rgba(230,240,255,${0.5*rain})`;c.lineWidth=1.5;ripples.forEach(r=>{r.r+=dtFrame*30;c.globalAlpha=Math.max(0,1-r.r/14)*rain;c.beginPath();c.ellipse(r.x,r.y,r.r,r.r*0.35,0,0,TAU);c.stroke();});c.globalAlpha=1;ripples=ripples.filter(r=>r.r<14);} let ripples=[]; let HUT={x:0,y:0,s:1}; /* ---------------- Main scene render ---------------- */ let dtFrame=0.016,shake=0,hoverPlot=-1,hoverPen=-1,touchPlot=-1; function renderScene(t){const c=sc;const T=now()-S.start;SEAV=seasonVis(T);const rain=rainAmt(T),h=hourAt(T),night=nightAmt(h);const wind=1+rain*1.6*(1-SEAV.w[3]*0.6); c.save();if(shake>0&&SET.shake){c.translate(rand(-1,1)*shake*12,rand(-1,1)*shake*12);}shake=Math.max(0,shake-dtFrame*3); drawSky(c,T,t,rain); viewT=Math.min(1,viewT+dtFrame*3.2);const ve=1-Math.pow(1-viewT,3);c.save();if(viewT<1)c.translate((1-ve)*viewDir*W*0.18,0); drawLand(c,T,t,rain); const yard=VIEW==='yard'; HUT=yard?(PORTRAIT?{x:W*0.24,y:Y.y-14,s:0.66}:{x:Y.x+Y.w-150,y:Y.y-12,s:0.6}):PORTRAIT?{x:W*0.76,y:F.y-30,s:0.7}:{x:F.x+120,y:F.y-22,s:0.62}; if(yard)drawBarn(c,HUT.x,HUT.y,HUT.s,t,night);else drawHut(c,HUT.x,HUT.y,HUT.s,t,night); const fA=1-SEAV.snow;if(fA>0.05){c.globalAlpha=fA;DECOR.flowers.forEach(f=>drawFlower(c,f,t));c.globalAlpha=1;}const tc=rgb(mixc(mix4(SPAL.tuft,[SEAV.w[0],SEAV.w[1],SEAV.w[2],0].map(v=>v/Math.max(0.001,1-SEAV.w[3]))),hex(SPAL.tuft[3]),SEAV.snow));DECOR.tufts.forEach(f=>drawTuft(c,f.x,f.y,f.s*1.3,t,wind,tc)); if(yard)drawYard(c,T,t,wind,rain,night);else drawField(c,T,t,wind,rain); c.restore(); drawAmbient(c,T,t,rain,night); // global light tint let tint=keyAt(TINT,h,1);tint=mixc(tint,[175,185,200],rain*0.45*(1-SEAV.w[3]*0.5));tint=mixc(tint,[255,240,246],SEAV.w[0]*0.25);tint=mixc(tint,[255,232,206],SEAV.w[2]*0.4);tint=mixc(tint,[226,236,255],SEAV.w[3]*0.42);c.globalCompositeOperation='multiply';c.fillStyle=rgb(tint);c.fillRect(-20,-20,W+40,H+40);c.globalCompositeOperation='source-over'; drawGlows(c,T,t,night,rain);drawRain(c,rain*(1-SEAV.w[3]),t);drawSeasonFx(c,t,rain,night); c.save();if(viewT<1)c.translate((1-ve)*viewDir*W*0.18,0); if(yard)drawYardIndicators(c,T,t,night,rain);else{if(S.unlocked<MAXPLOTS)drawSign(c,S.unlocked,t);drawIndicators(c,T,t);} c.restore();if(viewT<1){c.fillStyle=`rgba(255,250,235,${(1-ve)*0.55})`;c.fillRect(-20,-20,W+40,H+40);}c.restore(); return {T,rain,h,night};} /* ---------------- Animal yard (v1.1) ---------------- */ // cols, row height weights, enclosure cell [col,row,colSpan,rowSpan]; fills Y.rects[0..PENS-1] (pen ELE_PEN = enclosure) function yardGrid(ax,aw,ay,ah,cols,rw,ele,ratio,center,dry){const gap=26,rows=rw.length,tw=rw.reduce((a,b)=>a+b,0);const pw=(aw-gap*(cols-1))/cols,u=Math.min((ah-gap*(rows-1))/tw,pw*ratio); const w=pw*cols+gap*(cols-1),h=u*tw+gap*(rows-1),x0=ax+(aw-w)/2,y0=center?ay+(ah-h)/2:ay+(ah-h),sc=Math.min(pw/430,u/250)*1.05;if(dry)return{s:sc}; const rowY=r=>y0+rw.slice(0,r).reduce((a,b)=>a+b,0)*u+r*gap;const cell=(c,r,cw,rh)=>{const x=x0+c*(pw+gap),y=rowY(r),W2=cw*pw+(cw-1)*gap,H2=rw.slice(r,r+rh).reduce((a,b)=>a+b,0)*u+(rh-1)*gap;return{x,y,w:W2,h:H2,cx:x+W2/2,base:y+H2*0.76,s:Math.min(W2/430,H2/250)*1.05};}; const rects=[];for(let r=0;r<rows;r++)for(let c=0;c<cols;c++){if(c>=ele[0]&&c<ele[0]+ele[2]&&r>=ele[1]&&r<ele[1]+ele[3])continue;if(rects.length<ELE_PEN)rects.push(cell(c,r,1,1));} rects[ELE_PEN]=cell(ele[0],ele[1],ele[2],ele[3]);rects[ELE_PEN].s=Math.min(rects[ELE_PEN].s,sc*2.1); Object.assign(Y,{cols,rows,gap,pw,ph:u,w,h,x:x0,y:y0,s:sc,rects});return Y;} function penRect(i){return Y.rects[i];} function penAt(x,y){for(let i=0;i<PENS;i++){const R=penRect(i);if(x>=R.x-6&&x<=R.x+R.w+6&&y>=R.y-Math.min(R.h,Y.ph)*0.25&&y<=R.y+R.h+8)return i;}return -1;} function drawBarn(c,x,y,s,t,night){c.save();c.translate(x,y);c.scale(s,s); c.fillStyle='rgba(40,20,5,0.22)';c.beginPath();c.ellipse(0,4,170,18,0,0,TAU);c.fill(); c.fillStyle='#d9583a';c.beginPath();c.moveTo(-120,0);c.lineTo(-120,-110);c.lineTo(0,-180);c.lineTo(120,-110);c.lineTo(120,0);c.closePath();c.fill(); c.strokeStyle='rgba(120,30,15,0.35)';c.lineWidth=3;for(let k=-100;k<=100;k+=20){c.beginPath();c.moveTo(k,0);c.lineTo(k,-110-(120-Math.abs(k))*0.58+8);c.stroke();} c.fillStyle='#fff6e6';c.beginPath();c.moveTo(-132,-104);c.lineTo(0,-192);c.lineTo(132,-104);c.lineTo(132,-92);c.lineTo(0,-178);c.lineTo(-132,-92);c.closePath();c.fill(); c.fillStyle='#7a3020';roundRect(c,-44,-92,88,92,[10,10,0,0]);c.fill();c.strokeStyle='#fff6e6';c.lineWidth=7;c.strokeRect(-44,-88,88,88);c.beginPath();c.moveTo(-44,-88);c.lineTo(44,0);c.moveTo(44,-88);c.lineTo(-44,0);c.stroke(); const wg=night>0.1?`rgba(255,${200+night*30},120,${0.6+night*0.4})`:'#5a8ab0';c.fillStyle=wg;c.beginPath();c.arc(0,-128,18,0,TAU);c.fill();roundRect(c,-92,-66,40,30,6);c.fill();roundRect(c,52,-66,40,30,6);c.fill(); c.strokeStyle='#fff6e6';c.lineWidth=5;c.beginPath();c.arc(0,-128,18,0,TAU);c.stroke(); snowCap(c,[[-132,-100],[0,-188],[132,-100]],20,SEAV.snow); // hay bales [[-160,0],[-205,0],[-182,-34]].forEach(q=>{c.fillStyle='#f0c860';roundRect(c,q[0]-24,q[1]-34,48,34,8);c.fill();c.strokeStyle='#c89a38';c.lineWidth=3;c.beginPath();c.moveTo(q[0]-12,q[1]-34);c.lineTo(q[0]-12,q[1]);c.moveTo(q[0]+12,q[1]-34);c.lineTo(q[0]+12,q[1]);c.stroke();snowCap(c,[[q[0]-24,q[1]-32],[q[0]+24,q[1]-32]],12,SEAV.snow);}); c.restore();} function aniView(a,i,T,t,night,rain){ // animation state + walking targets (transient fields) const d=ANI[a.t],dark=night>0.55;const shelter=a.t!=='bees'&&(dark||(rain>0.3&&(SEAV.id==='winter'||(!d.rain&&!d.rainOk))));const hungry=d.eat>0&&a.meals<=0&&a.stored<=0; // peacock fans its tail when happy (and when tapped: fanT); elephant raises its trunk (trunkT) and showers water (sprayT) if(a.t==='peacock'||a.t==='elephant'){const happy=!dark&&!hungry&&!shelter;a.fanT=Math.max(0,(a.fanT||0)-dtFrame);a.sprayT=Math.max(0,(a.sprayT||0)-dtFrame); if(happy){a.fanCd=(a.fanCd===undefined?rand(2,6):a.fanCd)-dtFrame;if(a.fanCd<=0){a.fanT=a.t==='peacock'?3.4:1.8;a.fanCd=rand(9,16);}} a.fan=lerp(a.fan||0,a.fanT>0&&!dark?1:0,Math.min(1,dtFrame*(a.t==='peacock'?3.5:4)));} let tx;if(a.t==='bees')tx=0.56;else if(shelter)tx=d.big?0.3:0.22;else if(hungry)tx=d.big?0.58:0.6;else if(a.t==='peacock'&&a.fanT>0)tx=a.x;else{a.wt-=dtFrame;if(a.wt<=0||a.tx===undefined){a.tx=d.big?rand(0.4,0.6):rand(0.42,0.66);a.wt=rand(2.5,6);}tx=a.tx;} if(typeof a.x!=='number'||isNaN(a.x))a.x=tx;const dx=tx-a.x;const walk=Math.abs(dx)>0.01;if(walk){a.x+=Math.sign(dx)*Math.min(Math.abs(dx),dtFrame*(d.big?0.1:0.22));a.fx=dx>0?1:-1;}else if(hungry)a.fx=1; const ty=shelter?0.66:0.78;a.y=lerp(typeof a.y==='number'?a.y:ty,ty,Math.min(1,dtFrame*3)); return{sleep:dark&&a.t!=='bees'?true:dark,shelter,hungry,walk,eat:!walk&&!dark&&a.feedT>0,sad:hungry&&!dark};} function drawPen(c,i,T,t,night,rain,hov){const R=penRect(i),a=S.animals[i],s=R.s;const {x,y,w,h}=R; c.fillStyle='rgba(40,20,5,0.22)';roundRect(c,x-6,y+8,w+12,h+6,26);c.fill(); if(i===ELE_PEN)return drawEnclosure(c,i,R,a,T,t,night,rain,hov); if(!a){c.fillStyle=seaGrass('#86c95a');roundRect(c,x,y,w,h,24);c.fill();drawTuft(c,x+w*0.2,y+h*0.6,1,t,1,'#5aa83e');drawTuft(c,x+w*0.8,y+h*0.4,0.9,t,1,'#5aa83e'); c.save();c.setLineDash([12,10]);c.strokeStyle=hov?'#fff':'rgba(255,255,255,0.75)';c.lineWidth=5;roundRect(c,x+8,y+8,w-16,h-16,20);c.stroke();c.restore(); const by=y+h*0.5+Math.sin(t*2+i)*3;pill(c,R.cx,by,190*Math.max(0.8,s),56*Math.max(0.8,s),S.coins>=Math.min(...ANIMALS.filter(q=>q.lvl<=S.level&&!q.big).map(q=>aniPrice(q.id)))?'#ffe68a':'#f3dfb8','#fff'); c.fillStyle='#6a3d16';c.font=`700 ${Math.round(28*Math.max(0.8,s))}px Fredoka`;c.textAlign='center';c.textBaseline='middle';c.fillText('+ Animal',R.cx,by+1);return;} const st=aniView(a,i,T,t,night,rain); // ground: straw + dirt c.fillStyle='#b98250';roundRect(c,x,y,w,h,24);c.fill();c.fillStyle=a.t==='bees'?snowy('#9ad66a'):'#e2c486';roundRect(c,x+6,y+6,w-12,h-12,20);c.fill(); c.strokeStyle=a.t==='bees'?'rgba(70,140,40,0.35)':'rgba(170,120,50,0.35)';c.lineWidth=3;c.lineCap='round';for(let k=0;k<14;k++){const sx=x+w*(0.08+hash(i*31+k)*0.84),sy=y+h*(0.35+hash(i*17+k*3)*0.55),a2=hash(k*7+i)*3;c.beginPath();c.moveTo(sx,sy);c.lineTo(sx+Math.cos(a2)*12,sy+Math.sin(a2)*4);c.stroke();} if(a.t==='duck'||a.t==='buffalo'){const px=x+w*0.72,py=y+h*0.5;c.fillStyle=a.t==='duck'?snowy('#6ab8f0',0.7):'#8a6a48';c.beginPath();c.ellipse(px,py,w*0.17,h*0.11,0,0,TAU);c.fill();c.fillStyle='rgba(255,255,255,0.35)';c.beginPath();c.ellipse(px-w*0.05,py-h*0.03,w*0.06,h*0.025,0,0,TAU);c.fill();} if(a.t==='bees'&&SEAV.snow<0.5)DECOR.flowers.slice(0,6).forEach((f,k)=>drawFlower(c,{x:x+w*(0.12+k*0.15),y:y+h*(k%2?0.42:0.9),s:1.1,c:f.c,ph:f.ph},t)); // back fence c.strokeStyle='#a5703f';c.lineWidth=7;c.lineCap='round';c.beginPath();c.moveTo(x+10,y+h*0.12);c.lineTo(x+w-10,y+h*0.12);c.moveTo(x+10,y+h*0.24);c.lineTo(x+w-10,y+h*0.24);c.stroke(); c.fillStyle='#8a5a30';for(let k=0;k<=4;k++){roundRect(c,x+10+k*(w-20)/4-5,y-4,10,h*0.3,[5,5,2,2]);c.fill();} // shelter (palm-leaf roof lean-to) const sx0=x+w*0.04,sx1=x+w*0.42,eave=y+h*0.26; if(a.t!=='bees'){c.fillStyle='#c8a060';c.fillRect(sx0+6,y+h*0.06,sx1-sx0-12,h*0.5);c.strokeStyle='rgba(120,80,30,0.35)';c.lineWidth=2;for(let k=1;k<6;k++){const yy=y+h*0.06+k*h*0.08;c.beginPath();c.moveTo(sx0+6,yy);c.lineTo(sx1-6,yy);c.stroke();} c.fillStyle='#7a4f2a';c.fillRect(sx0+4,eave,7,h*0.42);c.fillRect(sx1-11,eave,7,h*0.42);} // trough if(ANI[a.t].eat>0){const tx=x+w*0.86,ty=y+h*0.86,tw=w*0.2;c.fillStyle='#8a5a30';roundRect(c,tx-tw/2,ty-h*0.1,tw,h*0.12,8);c.fill();c.fillStyle='#a5703f';roundRect(c,tx-tw/2,ty-h*0.12,tw,h*0.05,6);c.fill(); for(let k=0;k<a.meals*5;k++){c.fillStyle=k%2?'#ffd23a':'#f0b020';c.beginPath();c.ellipse(tx-tw*0.38+hash(k*13+i)*tw*0.76,ty-h*0.12-hash(k*7)*h*0.03,5,3.5,0,0,TAU);c.fill();}} // animal const ax=x+w*a.x,ay=y+h*a.y;const sc2=s*ANI[a.t].size*1.3;const an=a.an||0; c.save();c.translate(ax,ay);if(an>0){const q=Math.sin(an*Math.PI*3)*an*0.22;c.scale(1+q,1-q);} if(a.t==='duck'&&rain>0.3&&!st.sleep&&Math.random()<0.05)ripples.push({x:ax+rand(-30,30),y:ay,r:0}); drawAnimal(c,a.t,0,0,sc2,{t,ph:a.ph,fx:a.fx,sleep:st.sleep,sad:st.sad,walk:st.walk,eat:st.eat,fan:a.fan});c.restore(); // shelter roof over the animal if(a.t!=='bees'){c.fillStyle='#8a6a2a';c.beginPath();c.moveTo(sx0-10,eave+6);c.lineTo(sx0+12,y-h*0.04);c.lineTo(sx1-12,y-h*0.04);c.lineTo(sx1+10,eave+6);c.closePath();c.fill(); c.strokeStyle='#b8943a';c.lineWidth=3;for(let k=0;k<12;k++){const q=k/11;c.beginPath();c.moveTo(lerp(sx0+12,sx1-12,q),y-h*0.04);c.lineTo(lerp(sx0-10,sx1+10,q),eave+6);c.stroke();} c.fillStyle='rgba(0,0,0,0.12)';c.fillRect(sx0-10,eave+2,sx1-sx0+20,5);snowCap(c,[[sx0-6,eave+2],[sx0+12,y-h*0.04],[sx1-12,y-h*0.04],[sx1+6,eave+2]],12*s,SEAV.snow);} if(SEAV.snow>0.02){c.globalAlpha=SEAV.snow;c.strokeStyle='#fbfdff';c.lineWidth=4;c.beginPath();c.moveTo(x+12,y+h*0.12-4);c.lineTo(x+w-12,y+h*0.12-4);c.stroke();c.globalAlpha=1;} // front fence (low) c.strokeStyle='#b07a45';c.lineWidth=7;c.beginPath();c.moveTo(x+10,y+h-12);c.lineTo(x+w*0.36,y+h-12);c.moveTo(x+w*0.64,y+h-12);c.lineTo(x+w-10,y+h-12);c.stroke(); c.fillStyle='#8a5a30';[0.03,0.36,0.64,0.97].forEach(q=>{roundRect(c,x+w*q-6,y+h-34,12,34,[6,6,2,2]);c.fill();}); if(st.sleep){const zx=ax+40*sc2*(a.fx||1),zy=ay-80*sc2;c.fillStyle='rgba(255,255,255,0.9)';c.font=`700 ${Math.round(26*s)}px Fredoka`;c.textAlign='center';for(let k=0;k<3;k++){const q=((t*0.5+k/3+a.ph)%1);c.globalAlpha=Math.sin(q*Math.PI);c.fillText('z',zx+q*30*s+k*4,zy-q*50*s);}c.globalAlpha=1;} if(hov){c.strokeStyle='rgba(255,255,255,0.95)';c.lineWidth=5;roundRect(c,x+2,y+2,w-4,h-4,22);c.stroke();}} function drawEnclosure(c,i,R,a,T,t,night,rain,hov){const {x,y,w,h}=R,s=R.s,ys=Math.max(0.8,Y.s);const st=a?aniView(a,i,T,t,night,rain):null; c.fillStyle='#b98250';roundRect(c,x,y,w,h,26);c.fill();c.fillStyle=snowy('#93d266');roundRect(c,x+6,y+6,w-12,h-12,22);c.fill(); c.fillStyle=snowy('#d9bb80',0.5);c.beginPath();c.ellipse(x+w*0.56,y+h*0.8,w*0.36,h*0.13,0,0,TAU);c.fill(); drawTuft(c,x+w*0.08,y+h*0.9,1.1,t,1,'#5aa83e');drawTuft(c,x+w*0.95,y+h*0.62,1,t,1,'#5aa83e');drawTuft(c,x+w*0.36,y+h*0.5,0.9,t,1,'#5aa83e'); // pond with lotus (elephants love a bath) const px=x+w*0.76,py=y+h*0.42;c.fillStyle=snowy('#5aaee8',0.7);c.beginPath();c.ellipse(px,py,w*0.15,h*0.085,0,0,TAU);c.fill();c.fillStyle='rgba(255,255,255,0.35)';c.beginPath();c.ellipse(px-w*0.04,py-h*0.025,w*0.05,h*0.018,0,0,TAU);c.fill(); [[-0.08,0.02],[0.07,-0.01]].forEach((q,k)=>{const lx=px+w*q[0],ly=py+h*q[1];c.fillStyle='#4aa84a';c.beginPath();c.ellipse(lx,ly,14*ys,7*ys,0,0.4,TAU);c.fill();if(!k){c.fillStyle='#ff9ac0';[-0.6,0,0.6].forEach(r=>{c.save();c.translate(lx,ly-4*ys);c.rotate(r);c.beginPath();c.ellipse(0,-6*ys,4*ys,8*ys,0,0,TAU);c.fill();c.restore();});}}); // back fence c.strokeStyle='#a5703f';c.lineWidth=7;c.lineCap='round';c.beginPath();c.moveTo(x+10,y+h*0.1);c.lineTo(x+w-10,y+h*0.1);c.moveTo(x+10,y+h*0.19);c.lineTo(x+w-10,y+h*0.19);c.stroke(); c.fillStyle='#8a5a30';const np=Math.max(4,Math.round(w/110));for(let k=0;k<=np;k++){roundRect(c,x+10+k*(w-20)/np-5,y-4,10,h*0.24,[5,5,2,2]);c.fill();} // shady rain tree (night shelter) const kk=Math.min(w,h*1.6),tx=x+kk*0.24,tb=y+h*0.7,th=Math.min(h*0.5,kk*0.36);c.fillStyle='#7a4f2a';c.beginPath();c.moveTo(tx-kk*0.03,tb);c.quadraticCurveTo(tx-kk*0.01,tb-th*0.5,tx-kk*0.012,tb-th);c.lineTo(tx+kk*0.012,tb-th);c.quadraticCurveTo(tx+kk*0.01,tb-th*0.5,tx+kk*0.03,tb);c.closePath();c.fill(); c.fillStyle='rgba(40,20,5,0.18)';c.beginPath();c.ellipse(tx,tb,kk*0.1,kk*0.02,0,0,TAU);c.fill(); const CAN=[['#f7b2cc','#f9c8da'],['#3f9a3a','#4fb048'],['#e0602a','#f09a30'],['#e2eaf0','#f6f9fc']];[[0,-1,0.15],[-0.08,-0.88,0.11],[0.08,-0.9,0.12],[0.0,-1.15,0.1]].forEach((q,k)=>{const sw=Math.sin(t*1.2+k)*2;c.fillStyle=rgb(mix4(CAN.map(cc=>cc[k%2]),SEAV.w.map((v,j)=>j===3?SEAV.snow:v*(1-SEAV.snow)/Math.max(0.001,1-SEAV.w[3]+1e-9))));c.beginPath();c.ellipse(tx+kk*q[0]+sw,tb+th*q[1],kk*q[2],kk*q[2]*0.66,0,0,TAU);c.fill();}); c.fillStyle='rgba(255,255,255,0.12)';c.beginPath();c.ellipse(tx-kk*0.03,tb-th*1.08,kk*0.06,kk*0.025,0,0,TAU);c.fill(); // sign const sgx=x+w*0.9,sgy=y+h*0.15;c.fillStyle='#7a4f2a';c.fillRect(sgx-3,sgy,6,h*0.12);c.fillStyle='#f0d7a0';roundRect(c,sgx-62*ys,sgy-20*ys,124*ys,36*ys,8);c.fill();c.strokeStyle='#a5703f';c.lineWidth=3;c.stroke(); c.fillStyle='#6a3d16';c.font=`700 ${Math.round(18*ys)}px Fredoka`;c.textAlign='center';c.textBaseline='middle';c.fillText('Elephant Home',sgx,sgy-1*ys); // trough if(a){const tx2=x+w*0.86,ty=y+h*0.88,tw=w*0.16,tH=h*0.07;c.fillStyle='#8a5a30';roundRect(c,tx2-tw/2,ty-tH,tw,tH*1.2,8);c.fill();c.fillStyle='#a5703f';roundRect(c,tx2-tw/2,ty-tH*1.2,tw,tH*0.5,6);c.fill(); for(let k=0;k<a.meals*7;k++){c.fillStyle=k%2?'#ffd23a':'#f0b020';c.beginPath();c.ellipse(tx2-tw*0.4+hash(k*13+i)*tw*0.8,ty-tH*1.2-hash(k*7)*h*0.02,6*ys,4*ys,0,0,TAU);c.fill();}} if(a){const ax=x+w*a.x,ay=y+h*a.y,sc2=s*ANI[a.t].size*1.3,an=a.an||0;c.save();c.translate(ax,ay);if(an>0){const q=Math.sin(an*Math.PI*3)*an*0.12;c.scale(1+q,1-q);} drawAnimal(c,a.t,0,0,sc2,{t,ph:a.ph,fx:a.fx,sleep:st.sleep,sad:st.sad,walk:st.walk,eat:st.eat,trunk:a.fan,spray:a.sprayT>0});c.restore(); if(st.sleep){const zx=ax+60*sc2*(a.fx||1),zy=ay-130*sc2;c.fillStyle='rgba(255,255,255,0.9)';c.font=`700 ${Math.round(30*ys)}px Fredoka`;c.textAlign='center';for(let k=0;k<3;k++){const q=((t*0.5+k/3+a.ph)%1);c.globalAlpha=Math.sin(q*Math.PI);c.fillText('z',zx+q*34*ys+k*4,zy-q*56*ys);}c.globalAlpha=1;}} // front fence (low) c.strokeStyle='#b07a45';c.lineWidth=7;c.beginPath();c.moveTo(x+10,y+h-12);c.lineTo(x+w*0.4,y+h-12);c.moveTo(x+w*0.6,y+h-12);c.lineTo(x+w-10,y+h-12);c.stroke(); c.fillStyle='#8a5a30';[0.02,0.21,0.4,0.6,0.79,0.98].forEach(q=>{roundRect(c,x+w*q-6,y+h-34,12,34,[6,6,2,2]);c.fill();}); if(!a){const lock=ANI.elephant.lvl>S.level;const by=y+h*0.55+Math.sin(t*2)*3;c.save();c.globalAlpha=lock?0.55:0.8;drawAnimal(c,'elephant',x+w*0.5,y+h*0.72,s*0.7,{t:0,ph:0,sleep:lock});c.restore(); if(lock){c.fillStyle='rgba(255,255,255,0.18)';roundRect(c,x+6,y+6,w-12,h-12,22);c.fill();} pill(c,R.cx,by,(lock?300:240)*ys,58*ys,lock?'#efe3cc':S.coins>=aniPrice('elephant')?'#ffe68a':'#f3dfb8','#fff');c.fillStyle='#6a3d16';c.font=`700 ${Math.round(27*ys)}px Fredoka`;c.textAlign='center';c.textBaseline='middle'; c.fillText(lock?`Elephant · Level ${ANI.elephant.lvl}`:'+ Elephant',R.cx,by+1); if(!lock){c.save();c.setLineDash([12,10]);c.strokeStyle=hov?'#fff':'rgba(255,255,255,0.75)';c.lineWidth=5;roundRect(c,x+8,y+8,w-16,h-16,20);c.stroke();c.restore();}} if(hov){c.strokeStyle='rgba(255,255,255,0.95)';c.lineWidth=5;roundRect(c,x+2,y+2,w-4,h-4,22);c.stroke();}} function drawYard(c,T,t,wind,rain,night){ c.fillStyle='rgba(40,20,5,0.18)';roundRect(c,Y.x-22,Y.y-20,Y.w+44,Y.h+44,34);c.fill();c.fillStyle='#c79a62';roundRect(c,Y.x-20,Y.y-24,Y.w+40,Y.h+44,34);c.fill(); c.fillStyle='#d9b27a';roundRect(c,Y.x-20,Y.y-24,Y.w+40,16,[34,34,0,0]);c.fill(); for(let i=0;i<PENS;i++)drawPen(c,i,T,t,night,rain,i===hoverPen);} function drawYardIndicators(c,T,t,night,rain){c.textBaseline='middle';for(let i=0;i<PENS;i++){const a=S.animals[i];if(!a)continue;const R=penRect(i),d=ANI[a.t],s=Math.max(0.85,Y.s); {const hp=clamp(a.hap==null?70:a.hap,0,100)/100,bw=74*s,hx=R.x+R.w-bw-34*s,hy=R.y+24*s;c.fillStyle='rgba(255,250,240,0.92)';roundRect(c,hx-18*s,hy-15*s,bw+34*s,30*s,15*s);c.fill(); const hc=hp>=0.8?'#ff4a7a':hp>=0.55?'#ff7a9a':hp>=0.3?'#f0a050':'#9a8a8a';c.fillStyle=hc;c.beginPath();const r=9*s;c.moveTo(hx,hy+r*0.9);c.bezierCurveTo(hx-r*1.6,hy-r*0.2,hx-r*0.6,hy-r*1.4,hx,hy-r*0.5);c.bezierCurveTo(hx+r*0.6,hy-r*1.4,hx+r*1.6,hy-r*0.2,hx,hy+r*0.9);c.fill(); c.fillStyle='rgba(120,80,40,0.25)';roundRect(c,hx+14*s,hy-5*s,bw,10*s,5*s);c.fill();c.fillStyle=hc;roundRect(c,hx+14*s,hy-5*s,Math.max(6*s,bw*hp),10*s,5*s);c.fill();} const x=R.cx,y=R.y+R.h-12;const ax=R.x+R.w*a.x,ay=R.y+R.h*a.y,top=Math.max(R.y+34*s,ay-({chicken:84,duck:78,goat:96,cow:98,buffalo:96,bees:112,peacock:96,elephant:150}[a.t])*R.s*d.size*1.3-30*s); if(a.stored>0){const b=Math.abs(Math.sin(t*4+a.ph))*8;// product bubble c.fillStyle='rgba(60,30,10,0.2)';c.beginPath();c.arc(ax,top-b+5,34*s,0,TAU);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(ax,top-b,34*s,0,TAU);c.fill();c.beginPath();c.moveTo(ax-10,top-b+28*s);c.lineTo(ax,top-b+46*s);c.lineTo(ax+10,top-b+28*s);c.fill(); c.drawImage(ICON[d.prod],ax-30*s,top-b-30*s,60*s,60*s);if(a.stored>1){c.fillStyle='#e9573f';c.beginPath();c.arc(ax+28*s,top-b-24*s,15*s,0,TAU);c.fill();c.fillStyle='#fff';c.font=`700 ${Math.round(20*s)}px Fredoka`;c.textAlign='center';c.fillText(a.stored,ax+28*s,top-b-23*s);} if(Math.random()<0.03)spawn('spark',ax+rand(-40,40),top+rand(-30,30),{n:1}); const full=a.stored>=STORE_CAP;pill(c,x,y-b*0.4,128*s,38*s,'#ffe14a','#fff');c.fillStyle='#8a4a00';c.font=`700 ${Math.round(22*s)}px Fredoka`;c.textAlign='center';c.fillText(full?'Full! Tap':'Collect!',x,y-b*0.4+1);continue;} if(d.eat>0&&a.meals<=0){const b=Math.abs(Math.sin(t*3+a.ph))*5;c.fillStyle='rgba(255,255,255,0.95)';c.beginPath();c.arc(ax,top-b,28*s,0,TAU);c.fill();[[-18,24,7],[-26,36,4]].forEach(q=>{c.beginPath();c.arc(ax+q[0]*s,top-b+q[1]*s,q[2]*s,0,TAU);c.fill();}); c.drawImage(ICON.feed,ax-24*s,top-b-24*s,48*s,48*s);pill(c,x,y,132*s,38*s,'#ffb070','#fff');c.fillStyle='#7a2a00';c.font=`700 ${Math.round(22*s)}px Fredoka`;c.textAlign='center';c.fillText('Hungry!',x,y+1);continue;} const left=(1-a.prog)/aniRate(a,T);const w=(SET.timers?150:84)*s;pill(c,x,y,w,38*s,'rgba(255,250,240,0.95)',null);const rx=x-w/2+20*s; c.strokeStyle='rgba(120,80,40,0.25)';c.lineWidth=6;c.beginPath();c.arc(rx,y,11*s,0,TAU);c.stroke();c.strokeStyle='#5ab83a';c.beginPath();c.arc(rx,y,11*s,-Math.PI/2,-Math.PI/2+TAU*a.prog);c.stroke(); if(SET.timers){c.fillStyle='#6a3d16';c.font=`600 ${Math.round(21*s)}px Fredoka`;c.textAlign='left';c.fillText(fmtT(left),rx+18*s,y+1);} if(d.eat>0){for(let k=0;k<MEALS;k++){c.fillStyle=k<a.meals?'#ffc23a':'rgba(160,120,80,0.35)';c.beginPath();c.arc(x-(MEALS-1)*9*s+k*18*s,y+28*s,6*s,0,TAU);c.fill();}}}} /* ---------------- FX: particles, floating text, flying icons ---------------- */ let parts=[],floats=[],flyers=[]; function spawn(type,x,y,o={}){const n=o.n||8;for(let k=0;k<n;k++){const p={type,x,y,life:0,max:rand(0.6,1.1),rot:rand(0,6),vr:rand(-6,6),s:rand(0.7,1.3)}; if(type==='leaf'){p.vx=rand(-260,260);p.vy=rand(-520,-220);p.g=900;p.col=o.col||['#6cc04a','#4e9a36','#9ad66a'][k%3];} else if(type==='dirt'){p.vx=rand(-200,200);p.vy=rand(-380,-120);p.g=1100;p.col=['#7a4f2a','#9b6a3d','#5a3418'][k%3];p.max=0.6;} else if(type==='drop'){p.x=x+rand(-o.w||-40,o.w||40);p.y=y-rand(60,140);p.vx=rand(-30,30);p.vy=rand(150,350);p.g=1200;p.max=rand(0.25,0.45);p.col='#6ab8f0';} else if(type==='spark'){p.vx=rand(-30,30);p.vy=rand(-70,-20);p.g=0;p.max=rand(0.6,1);p.col=o.col||'#fff6a0';} else if(type==='confetti'){p.x=rand(0,W);p.y=rand(-200,-10);p.vx=rand(-60,60);p.vy=rand(150,350);p.g=80;p.max=rand(2.5,4);p.col=['#ff5a7a','#ffd84a','#5ac8ff','#7bd04a','#ff9a4a','#c08aff'][k%6];} else if(type==='ring'){p.max=0.5;p.col=o.col||'#fff';p.r0=o.r||20;} else if(type==='heart'){p.x=x+rand(-30,30);p.vx=rand(-40,40);p.vy=rand(-160,-90);p.g=-20;p.max=rand(0.9,1.4);p.col=o.col||['#ff6b8a','#ff8fa8','#ff4a6a'][k%3];} else if(type==='crumb'){p.vx=rand(-160,160);p.vy=rand(-300,-120);p.g=1000;p.max=0.7;p.col=['#ffd23a','#f0b020','#e8c070'][k%3];} parts.push(p);}} function floatText(text,x,y,col='#fff',icon=null,size=34){floats.push({text,x,y,col,icon,size,life:0,max:1.3});} function stagePos(el){const r=el.getBoundingClientRect(),s=stage.getBoundingClientRect();return{x:(r.left+r.width/2-s.left)/SCALE,y:(r.top+r.height/2-s.top)/SCALE};} function flyTo(img,x,y,el,cb,delay=0,size=52){const tp=stagePos(el);flyers.push({img,x,y,sx:x,sy:y,tx:tp.x,ty:tp.y,el,cb,t:-delay,dur:rand(0.65,0.85),size,cx:x+rand(-160,160),cy:Math.min(y,tp.y)-rand(80,240)});} const COINIMG=(()=>{const cv=makeCanvas(64,64),c=cv.getContext('2d');drawCoin(c,32,32,28);return cv;})(); const STARIMG=(()=>{const cv=makeCanvas(64,64),c=cv.getContext('2d');c.fillStyle='#ffd84a';c.strokeStyle='#fff';c.lineWidth=5;star(c,32,32,26);c.stroke();c.fillStyle='#ffb92e';star(c,32,32,26);return cv;})(); function renderFx(dt){const c=fc;c.clearRect(0,0,W,H); parts.forEach(p=>{p.life+=dt;p.vy+=p.g*dt;p.x+=p.vx*dt;p.y+=p.vy*dt;p.rot+=p.vr*dt;const a=1-p.life/p.max;if(a<=0)return;c.globalAlpha=Math.min(1,a*1.5); if(p.type==='leaf'){leaf(c,p.x,p.y,18*p.s,7*p.s,p.rot,p.col,false);} else if(p.type==='dirt'){c.fillStyle=p.col;c.beginPath();c.arc(p.x,p.y,5*p.s,0,TAU);c.fill();} else if(p.type==='drop'){drawDrop(c,p.x,p.y,6*p.s,p.col);} else if(p.type==='spark'){c.fillStyle=p.col;c.save();c.translate(p.x,p.y);c.rotate(p.rot*0.3);const r=10*p.s*Math.sin(Math.PI*p.life/p.max);c.beginPath();c.moveTo(0,-r*1.6);c.quadraticCurveTo(0,0,r*1.6,0);c.quadraticCurveTo(0,0,0,r*1.6);c.quadraticCurveTo(0,0,-r*1.6,0);c.quadraticCurveTo(0,0,0,-r*1.6);c.fill();c.restore();} else if(p.type==='confetti'){c.save();c.translate(p.x+Math.sin(p.life*5+p.rot)*20,p.y);c.rotate(p.rot);c.fillStyle=p.col;c.fillRect(-8,-4,16,8*Math.abs(Math.cos(p.life*6+p.rot)));c.restore();} else if(p.type==='heart'){c.save();c.translate(p.x+Math.sin(p.life*6+p.rot)*8,p.y);const r=11*p.s*Math.min(1,p.life*6);c.fillStyle=p.col;c.beginPath();c.moveTo(0,r*0.9);c.bezierCurveTo(-r*1.6,-r*0.2,-r*0.6,-r*1.4,0,-r*0.5);c.bezierCurveTo(r*0.6,-r*1.4,r*1.6,-r*0.2,0,r*0.9);c.fill();c.restore();} else if(p.type==='crumb'){c.fillStyle=p.col;c.beginPath();c.ellipse(p.x,p.y,5*p.s,3.5*p.s,p.rot,0,TAU);c.fill();} else if(p.type==='ring'){c.strokeStyle=p.col;c.lineWidth=6*a;c.beginPath();c.ellipse(p.x,p.y,p.r0+p.life*220,(p.r0+p.life*220)*0.5,0,0,TAU);c.stroke();}}); c.globalAlpha=1;parts=parts.filter(p=>p.life<p.max); floats.forEach(f=>{f.life+=dt;const q=f.life/f.max;const y=f.y-q*90,sc2=q<0.15?q/0.15*1.2:q<0.25?1.2-(q-0.15)*2:1;c.globalAlpha=q>0.7?1-(q-0.7)/0.3:1;c.save();c.translate(f.x,y);c.scale(sc2,sc2); c.font=`700 ${f.size}px Fredoka`;c.textAlign='center';c.textBaseline='middle';const tw=c.measureText(f.text).width;const ox=f.icon?-24:0; c.lineWidth=8;c.strokeStyle='rgba(60,30,10,0.85)';c.lineJoin='round';c.strokeText(f.text,ox+tw*0,0);c.fillStyle=f.col;c.fillText(f.text,ox,0);if(f.icon)c.drawImage(f.icon,ox+tw/2+2,-f.size*0.75,f.size*1.5,f.size*1.5);c.restore();}); c.globalAlpha=1;floats=floats.filter(f=>f.life<f.max); flyers.forEach(f=>{f.t+=dt;if(f.t<0)return;const q=clamp(f.t/f.dur,0,1),e=q*q*(3-2*q)*0.6+q*0.4; const x=(1-e)*(1-e)*f.sx+2*(1-e)*e*f.cx+e*e*f.tx,y=(1-e)*(1-e)*f.sy+2*(1-e)*e*f.cy+e*e*f.ty;const s=f.size*(q<0.2?0.6+q*3:1.2-q*0.5); c.drawImage(f.img,x-s/2,y-s/2,s,s);if(q>=1&&!f.done){f.done=true;if(f.el){f.el.classList.remove('bump');void f.el.offsetWidth;f.el.classList.add('bump');}f.cb&&f.cb();}}); flyers=flyers.filter(f=>!f.done);} /* ---------------- Actions ---------------- */ let SEL='chili',combo=0,comboT=0; const T_=()=>now()-S.start; function canShape(){return S.up.can>=3?'all':S.up.can>=2?'plus':'one';} function interact(i,lock){if(i<0)return null; if(i>=S.unlocked){if(i===S.unlocked&&!lock)askBuyPlot();return null;} const p=S.plots[i]; if(p.spr){if(SEL==='spr'&&(!lock||lock==='spr'))return removeSpr(i)?'spr':null;if(!lock)toast('A sprinkler waters the 8 plots around it.');return null;} if(!p.c){if(lock&&lock!=='plant'&&lock!=='spr')return null; if(SEL==='spr'){if(lock&&lock!=='spr')return null;return placeSpr(i)?'spr':null;} if(SEL==='fert'){if(!lock)toast('Fertilizer works on growing plants.');return null;} return plant(i,lock)?'plant':null;} if(p.g>=1){if(lock&&lock!=='harvest')return null;harvest(i);return 'harvest';} if(SEL==='fert'&&(!lock||lock==='fert')){return useFert(i)?'fert':null;} if(p.wilt||!plotWet(p,i,T_())||lock==='water'){if(lock&&lock!=='water')return null;if(lock==='water'&&plotWet(p,i,T_())&&p.wet-now()>WATER_TIME[S.up.can-1]-3)return 'water';water(i);return 'water';} if(!lock){const left=(1-p.g)/growRate(p,i,T_());toast(`${CROP[p.c].name}: ready in ${fmtT(left)}${p.fert?' (fertilized)':S.items.fert>0?'. Tip: select Fertilizer to boost it':''}`);AU.pop();p.an=0.5;} return null;} function plant(i,lock){const cr=CROP[SEL];if(!cr){return false;} if(cr.lvl>S.level){if(!lock){toast(`${cr.name} unlocks at level ${cr.lvl}`,'bad');AU.err();}return false;} if(!canPlantNow(cr,seasonAt(T_()))){if(!lock){toast(`Too cold! ${cr.name} can't be planted in Winter. Try ${CROPS.filter(c=>c.lvl<=S.level&&canPlantNow(c,'winter')).map(c=>c.name).join(', ')}.`,'bad');AU.err();shakeSlot(SEL);}return false;} if(!(S.seeds[SEL]>0)){if(!lock){toast(`No ${cr.name} seeds left. Buy more in the Shop!`,'bad');AU.err();shakeSlot(SEL);}return false;} S.seeds[SEL]--;const p=S.plots[i];Object.assign(p,{c:SEL,g:0,left:cr.regrow||1,big:0,an:1,dry:0,wilt:0,hurt:0,fert:p.fert||0});if(sprinklerNear(i))p.wet=now()+5; S.stats.planted++;if(cr.regrow)S.stats.trees++;const R=plotRect(i);spawn('dirt',R.cx,R.base,{n:10});spawn('ring',R.cx,R.base,{r:10,col:'rgba(255,255,255,0.8)'}); AU.plant();updateSlots();tutEvent('plant',i);return true;} function water(i){const sh=canShape();const area=sh==='all'?neighbors(i,'all'):sh==='plus'?neighbors(i,'plus'):[i];const dur=WATER_TIME[S.up.can-1];let any=false; area.forEach(j=>{if(j>=S.unlocked)return;const p=S.plots[j];const R=plotRect(j);spawn('drop',R.cx,R.base,{n:6,w:F.tw*0.35});if(!p.c||p.g>=1)return;p.wet=now()+dur;p.dry=0;if(p.wilt){p.wilt=0;p.hurt=1;floatText('Revived!',R.cx,R.base-F.tw*0.5,'#bfe8ff',null,26);}p.an=Math.max(p.an||0,0.6);any=true;}); AU.water();tutEvent('water',i);return any;} function useFert(i){const p=S.plots[i];if(p.fert){toast('Already fertilized: it will give a bigger harvest.');AU.pop();return false;}if(!(S.items.fert>0)){toast('No fertilizer left. Animals give manure, or buy some in the Shop.','bad');AU.err();return false;}S.items.fert--;S.stats.fertUsed=(S.stats.fertUsed||0)+1;p.fert=1;p.g=Math.min(1,p.g+0.1);p.an=1;floatText('Fertilized! Bigger harvest',plotRect(i).cx,plotRect(i).base-F.tw*0.5,'#d8ff9a',null,26); const R=plotRect(i);spawn('spark',R.cx,R.base-F.tw*0.3,{n:12,col:'#c8ff8a'});AU.fert();updateSlots();return true;} function placeSpr(i){if(!(S.items.spr>0)){toast('Buy a sprinkler in the Shop first.','bad');AU.err();return false;}S.items.spr--;S.plots[i].spr=true;refreshSpr(); const R=plotRect(i);spawn('drop',R.cx,R.base,{n:16,w:F.tw*1.2});AU.water();updateSlots();toast('Sprinkler placed! It waters the plots around it.','good');return true;} function removeSpr(i){S.plots[i].spr=false;S.items.spr++;refreshSpr();AU.pop();updateSlots();toast('Sprinkler picked up.');return true;} function harvest(i){const p=S.plots[i],cr=CROP[p.c],R=plotRect(i),T=T_(); let n=randi(cr.prod[0],cr.prod[1])+S.up.basket;const n0=n;if(p.fert)n+=Math.max(1,Math.round(n*FERT_YIELD));if(p.hurt)n=Math.max(1,n-1); if(p.fert)setTimeout(()=>floatText(`Fertilized +${n-n0}`,R.cx,R.base-F.tw*1.15,'#d8ff9a',null,28),380);else if(p.hurt)setTimeout(()=>floatText('Wilted earlier: -1',R.cx,R.base-F.tw*1.15,'#ffc8a0',null,24),380);const hives=aniCount('bees');if(hives&&Math.random()<Math.min(0.4,hives*0.2)){n++;setTimeout(()=>floatText('+1 Bees!',R.cx,R.base-F.tw*0.9,'#ffe14a',null,28),300);}let sd=randi(cr.seeds[0],cr.seeds[1]);if(S.up.hoe&&Math.random()<S.up.hoe*0.35)sd++; S.produce[cr.id]=(S.produce[cr.id]||0)+n;S.seeds[cr.id]=(S.seeds[cr.id]||0)+sd; S.stats.harvests++;if(S.today)S.today.harv+=n;S.stats.by[cr.id]=(S.stats.by[cr.id]||0)+1;if(rainAt(T))S.stats.rainH++;if(isNight(T))S.stats.nightH++; if(comboT>0)combo++;else combo=0;comboT=1.0; spawn('leaf',R.cx,R.base-F.tw*0.3,{n:10,col:null});spawn('spark',R.cx,R.base-F.tw*0.35,{n:6});spawn('ring',R.cx,R.base,{r:F.tw*0.2,col:'rgba(255,240,150,0.9)'}); const shopBtn=$('#btnShop');for(let k=0;k<Math.min(n,5);k++)flyTo(ICON[cr.id],R.cx+rand(-20,20),R.base-F.tw*0.35,shopBtn,null,k*0.06,64); const slot=document.querySelector(`.slot[data-id="${cr.id}"]`);if(slot)for(let k=0;k<Math.min(sd,4);k++)flyTo(ICON[cr.id],R.cx,R.base-F.tw*0.2,slot,()=>updateSlots(),0.15+k*0.07,40); floatText(`+${n}`,R.cx,R.base-F.tw*0.6,'#fff',ICON[cr.id]);setTimeout(()=>floatText(`+${sd} seeds`,R.cx,R.base-F.tw*0.3,'#d8ff9a',null,26),180); AU.harvest(combo);addXP(cr.xp,R.cx,R.base-F.tw*0.5); if(combo>=2){floatText(`Combo x${combo+1}!`,R.cx,R.base-F.tw*1.0,'#ffd84a',null,40);shake=Math.min(1,0.25+combo*0.07);} if(cr.regrow&&p.left>1){p.left--;p.g=0.55;p.big=1;p.an=1;p.fert=0;p.hurt=0;p.dry=0;}else{Object.assign(p,{c:null,g:0,left:0,big:0,an:0,fert:0,hurt:0,dry:0,wilt:0});} renderOrders();tutEvent('harvest',i);} function shakeSlot(id){const el=document.querySelector(`.slot[data-id="${id}"]`);if(el){el.animate([{transform:'translateX(0)'},{transform:'translateX(-10px)'},{transform:'translateX(10px)'},{transform:'translateX(0)'}],{duration:300});}} function addCoins(n,x,y){S.coins+=n;S.stats.earned+=n;if(S.today)S.today.coins+=n;const el=$('#coinBox');const k=Math.min(10,Math.ceil(n/8));for(let i=0;i<k;i++)flyTo(COINIMG,x+rand(-30,30),y+rand(-20,20),el,i===0?()=>{AU.coin();}:null,i*0.05,48);} function addXP(n,x,y){S.xp+=n;if(S.today)S.today.xp+=n;flyTo(STARIMG,x,y,$('#lvlBox'),null,0.1,40);let ups=0;while(S.level<MAXLVL&&S.xp>=xpNeed(S.level)){S.xp-=xpNeed(S.level);S.level++;ups++;} if(ups)setTimeout(()=>levelUp(),700);} function levelUp(){const L=S.level;const reward=25*L;S.coins+=reward;const newC=CROPS.filter(c=>c.lvl===L),newA=ANIMALS.filter(a=>a.lvl===L);newC.forEach(c=>S.seeds[c.id]=(S.seeds[c.id]||0)+3); AU.level();spawn('confetti',0,0,{n:120});shake=0.4;buildHotbar(); const ups=Object.entries(UPG).filter(([k,u])=>u.lvl.includes(L)).map(([k,u])=>u.name); openModal(stkForLevel(L)?'Level Up! New Sticker':'Level Up!',`<div style="text-align:center"><div style="font-size:120px;font-weight:700;color:#ffb92e;text-shadow:0 6px 0 #c06a00;line-height:1">${L}</div> <p class="mtext">Great farming! You got <span class="price"><span class="coinIco sm"></span><b>${reward}</b></span></p> ${newC.map(c=>`<div class="card" style="max-width:420px;margin:10px auto"><img src="${PACK[c.id]}"><h3>New crop: ${c.name}</h3><div class="sub">${c.local} · You got 3 free seeds!</div></div>`).join('')} ${L===YARD_LVL?'<p class="mtext"><b>The Animal Yard is open!</b> Animals eat feed made from your Corn and ${CROP.paddy.name}.</p>':''} ${L===ANI.elephant.lvl?'<p class="mtext"><b>The Elephant Enclosure is open!</b> A gentle elephant can now join your yard.</p>':''} ${newA.map(a=>`<div class="card" style="max-width:420px;margin:10px auto"><img src="${PACK['a_'+a.id]}"><h3>New animal: ${a.name}</h3><div class="sub">Gives ${PROD[a.prod].name} · ${a.desc}</div></div>`).join('')} ${ups.length?`<p class="mtext">New in the Shop: <b>${ups.join(', ')}</b></p>`:''} ${L===6?'<p class="mtext">You can now take <b>4 orders</b> at once!</p>':''} ${levelStickerHTML(L)} <button class="btn" onclick="closeModal()" style="margin-top:16px;font-size:34px">Yay!</button></div>`);} /* v1.2 market: every item has a daily price (0.7x-1.4x), today's hot crop pays 1.6x, and selling lots of one item the same day lowers its price (2% each, down to 60%). */ const itemIdx=id=>{const k=CROPS.findIndex(c=>c.id===id);return k>=0?k:20+PRODS.findIndex(p=>p.id===id);}; function dayMul(id,day){return 0.7+0.7*hash(day*7919+itemIdx(id)*104729+17);} function mktDay(){const d=dayNum(T_());if(!S.mkt||S.mkt.day!==d)S.mkt={day:d,sold:{}};return S.mkt;} function sellPrice(id,day,extra=0){const cr=itemDef(id);const d=day||dayNum(T_());let p=cr.sell*(1+S.up.stall*0.2)*dayMul(id,d);if(hotCrop((d-1)*DAY+1,S.level)===cr)p*=1.6; if(!day){const sold=(mktDay().sold[id]||0)+extra;p*=Math.max(0.6,1-0.02*sold);}return Math.max(1,Math.round(p));} function priceTrend(id){const d=dayNum(T_());return d>1?sellPrice(id,d)-sellPrice(id,d-1):0;} function sell(id,n,el){n=Math.min(n,S.produce[id]||0);if(n<=0)return;let v=0;for(let k=0;k<n;k++)v+=sellPrice(id,0,k);S.produce[id]-=n;const m=mktDay();m.sold[id]=(m.sold[id]||0)+n;S.stats.sold=(S.stats.sold||0)+n;if(S.today)S.today.sold+=n;const p=el?stagePos(el):{x:W/2,y:H/2};addCoins(v,p.x,p.y);AU.buy();renderOrders();return v;} function askBuyPlot(){const price=plotPrice(S.unlocked);if(S.unlocked>=MAXPLOTS)return; openModal('New Plot',`<div style="text-align:center"><img src="${PACK.plot}" style="width:140px"><p class="mtext">Clear this land for a new plot?<br>Plots: ${S.unlocked} / ${MAXPLOTS}</p> <button class="btn ${S.coins>=price?'':'off'}" id="bpBtn" style="font-size:34px"><span class="price"><span class="coinIco sm"></span>${fmt(price)}</span> Buy</button></div>`); $('#bpBtn').onclick=()=>{if(buyPlot())closeModal();};} function buyPlot(){const price=plotPrice(S.unlocked);if(S.unlocked>=MAXPLOTS)return false;if(S.coins<price){toast('Not enough coins','bad');AU.err();return false;} S.coins-=price;const i=S.unlocked;S.unlocked++;refreshSpr();const R=plotRect(i);spawn('dirt',R.cx,R.base,{n:20});spawn('leaf',R.cx,R.base,{n:12});spawn('ring',R.cx,R.base,{r:30});AU.buy();shake=0.3; toast('New plot ready!','good');return true;} /* ---------------- Orders ---------------- */ function orderSlots(){return S.level>=6?4:3;} function genOrder(){const un=CROPS.filter(c=>c.lvl<=S.level);const maxN=S.level<3?1:S.level<6?2:3;const n=Math.min(un.length,randi(1,maxN)); const pool=un.slice();const items=[];for(let k=0;k<n;k++){const w=pool.map((c,i)=>1+i*0.6+(S.produce[c.id]?1:0));let r=Math.random()*w.reduce((a,b)=>a+b,0),j=0;while(r>w[j]){r-=w[j];j++;} const c=pool.splice(j,1)[0];const q=Math.max(1,Math.round(rand(0.6,1.25)*(34/(c.sell+4))*(1+S.level*0.06)));items.push({c:c.id,n:q});} const ap=animalProds();if(ap.length&&Math.random()<(S.stats.collected>0&&!S.orders.some(o=>o.items&&o.items.some(it=>PROD[it.c]))?0.7:0.35)){const pr=PROD[ap[randi(0,ap.length-1)]]; const q=Math.max(1,Math.round(rand(0.7,1.2)*(30/(pr.sell+4))*(1+S.level*0.05)));const it={c:pr.id,n:Math.min(q,4)};if(items.length<maxN)items.push(it);else items[items.length-1]=it;} const base=items.reduce((a,it)=>a+it.n*itemDef(it.c).sell,0);const coins=Math.round(base*rand(1.7,2.1)+10);const xp=Math.round(items.reduce((a,it)=>a+it.n*itemDef(it.c).xp*0.9,0)+6); const used=S.orders.map(o=>o.who);let who;do{who=Math.floor(Math.random()*NAMES.length);}while(used.includes(who)&&used.length<NAMES.length-1); const dn=dayNum(T_());const o={id:S.oid++,who,ava:randi(1,99999),items,coins,xp,posted:dn,due:dn+1}; if(Math.random()<0.25){const sc=CROPS.filter(c=>c.lvl<=S.level+1);const c=sc[randi(Math.max(0,sc.length-3),sc.length-1)];o.seed={c:c.id,n:randi(1,3)};} if(S.ordersDone<1&&S.oid<=2)o.items=[{c:'chili',n:2}],o.coins=20,o.xp=8,delete o.seed; return o;} function fillOrders(){const t=now(),dn=dayNum(T_());S.orders.forEach((o,k)=>{if(!o.empty&&o.due&&dn>o.due&&!canFill(o)){if(!titleOn)toast(`${NAMES[o.who]} couldn't wait and bought elsewhere. A new order is posted.`);S.orders[k]=genOrder();}}); S.orders=S.orders.filter(o=>!(o.wait&&o.wait<=t&&o.empty));while(S.orders.length<orderSlots())S.orders.push(genOrder()); S.orders.forEach((o,k)=>{if(o.empty&&o.wait<=t)S.orders[k]=genOrder();});} function canFill(o){return !o.empty&&o.items.every(it=>(S.produce[it.c]||0)>=it.n);} /* v1.2: the farmer walks to the Order Board to hand the goods over in person */ function deliver(id,el){const o=S.orders.find(o=>o.id===id);if(!o||!canFill(o))return;const p=el?stagePos(el):null;farmerGo('board',()=>deliverNow(id,el,p));} const sameDay=o=>o.posted&&o.posted===dayNum(T_()); function deliverNow(id,el,pp){const o=S.orders.find(o=>o.id===id);if(!o||!canFill(o))return;o.items.forEach(it=>S.produce[it.c]-=it.n); if(!el||!document.body.contains(el)){el=null;} const bonus=(S.up.lantern?1.1:1)*(sameDay(o)?1.2:1);if(S.today)S.today.orders++;const p=el?stagePos(el):pp||boardSpot();addCoins(Math.round(o.coins*bonus),p.x,p.y);queueOrderPop({who:o.who,ava:o.ava,items:o.items.slice(),coins:Math.round(o.coins*bonus),xp:o.xp,same:sameDay(o),seed:o.seed});addXP(o.xp,p.x,p.y);if(sameDay(o))floatText('Same-day bonus +20%',p.x,p.y-60,'#ffe14a',null,28);floatText(`${NAMES[o.who]}: Thank you!`,boardSpot().x,boardSpot().y-120,'#fff',null,30);if(o.seed){S.seeds[o.seed.c]=(S.seeds[o.seed.c]||0)+o.seed.n;updateSlots();} S.ordersDone++;AU.deliver();spawn('spark',p.x,p.y,{n:14});const card=el&&el.closest('.ocard');if(card)card.classList.add('done'); setTimeout(()=>{const k=S.orders.indexOf(o);if(k>=0)S.orders[k]=genOrder();renderOrders();},450);tutEvent('deliver');} function skipOrder(id){const k=S.orders.findIndex(o=>o.id===id);if(k<0)return;S.orders[k]={id:S.oid++,empty:true,wait:now()+20};AU.click();renderOrders();} /* ---------------- Achievements ---------------- */ let achNew=0; function checkAch(){ACH.forEach(a=>{if(!S.ach[a.id]&&a.t(S)){S.ach[a.id]=Date.now();S.coins+=a.r;achNew++;toast(`Achievement: ${a.name}! +${a.r} coins`,'good');AU.deliver(); if(window.pelaNative&&window.pelaNative.achievement)window.pelaNative.achievement(a.id);}}); $('#achDot').classList.toggle('on',achNew>0);$('#achDot').textContent=achNew; if(!S.won&&S.level>=15&&S.unlocked>=MAXPLOTS&&S.ordersDone>=30){S.won=true;spawn('confetti',0,0,{n:200});AU.level(); save();openStickerReward(true);}} /* ---------------- Animals (v1.1) ---------------- */ const aniCount=id=>S.animals.filter(a=>a&&a.t===id).length; const animalProds=()=>[...new Set(S.animals.filter(a=>a).map(a=>ANI[a.t].prod))]; const yardOpen=()=>S.level>=YARD_LVL; // first free pen for this animal: the elephant lives only in the big enclosure, everyone else in the 8 regular pens function freePen(id){const d=ANI[id];if(d.big)return S.animals[ELE_PEN]||(d.max&&aniCount(id)>=d.max)?-1:ELE_PEN;return S.animals.findIndex((a,i)=>!a&&i!==ELE_PEN);} function buyAnimal(id,pen){const d=ANI[id];if(!d||!yardOpen())return false;if(d.lvl>S.level){toast(`${d.name} unlocks at level ${d.lvl}`,'bad');AU.err();return false;} if(pen===undefined||pen<0||S.animals[pen]||(pen===ELE_PEN)!==!!d.big)pen=freePen(id);if(pen<0){toast(d.big?'Your Elephant Enclosure already has a gentle giant!':'All 8 pens are full!','bad');AU.err();return false;} const pr=aniPrice(id);if(S.coins<pr){toast('Not enough coins','bad');AU.err();return false;}S.coins-=pr;const a=S.animals[pen]=newAnimal(id);a.paid=pr;a.an=1;a.x=0.55; S.stats.byA[id]=S.stats.byA[id]||0;AU.buy();setTimeout(()=>AU.animal(id),250); if(VIEW==='yard'){const R=penRect(pen);spawn('heart',R.cx,R.base-60,{n:d.big?16:8});if(d.big||id==='peacock'){a.fanT=3;a.fanCd=8;}spawn('ring',R.cx,R.base,{r:30});spawn('leaf',R.cx,R.base-30,{n:10});shake=0.2;} toast(`${d.name} moved into your Animal Yard!`,'good');updateYardUI();save();return true;} function makeFeed(id,n){const v=FEED_VAL[id];if(!v)return 0;n=Math.min(n,S.produce[id]||0);if(n<=0)return 0;S.produce[id]-=n;S.feed+=n*v;AU.crunch();updateYardUI();renderOrders();return n*v;} function feedAnimal(i,quiet){const a=S.animals[i];if(!a)return false;const d=ANI[a.t]; if(d.eat===0){if(!quiet)toast('Bees find their own food in your flowers and crops.');return false;} if(a.meals>=MEALS){if(!quiet){toast(`${d.name} is full!`);AU.pop();a.an=0.5;}return false;} if(S.feed<d.eat&&FEED_VAL.corn&&(S.produce.corn||0)>0){const k=Math.min(S.produce.corn,Math.ceil((d.eat-S.feed)/FEED_VAL.corn));makeFeed('corn',k);if(!quiet)toast(`Used ${k} Corn as feed`);} if(S.feed<d.eat){if(!quiet){toast(`Not enough feed! Grow Corn, or make feed from ${CROP.paddy.name}.`,'bad');AU.err();}return false;} S.feed-=d.eat;a.meals++;a.an=1;a.feedT=1.6;S.stats.fed++;a.hap=Math.min(100,(a.hap==null?70:a.hap)+12);if(S.today)S.today.fed++;if(d.big)a.fanCd=Math.min(a.fanCd||9,2.5); if(VIEW==='yard'){const R=penRect(i);const ax=R.x+R.w*0.86,ay=R.y+R.h*0.78;spawn('crumb',ax,ay,{n:10});spawn('heart',R.x+R.w*a.x,R.y+R.h*a.y-80*Y.s,{n:3});} AU.crunch();if(Math.random()<0.6)setTimeout(()=>AU.animal(a.t),120);updateYardUI();tutEvent('feed');return true;} function feedAll(free){let n=0;for(let k=0;k<MEALS;k++)S.animals.forEach((a,i)=>{if(!a||ANI[a.t].eat===0||a.meals>=MEALS)return;if(free){a.meals++;a.an=1;a.feedT=1.6;S.stats.fed++;a.hap=Math.min(100,(a.hap==null?70:a.hap)+12);n++;if(VIEW==='yard'){const R=penRect(i);spawn('heart',R.x+R.w*a.x,R.y+R.h*a.y-80*Y.s,{n:2});}}else if(feedAnimal(i,true))n++;}); if(n){AU.crunch();toast(free?`Free meals for everyone! (${n})`:`Fed ${n} meal${n>1?'s':''}`,'good');tutEvent('feed');} else if(S.animals.some(a=>a&&ANI[a.t].eat>0&&a.meals<MEALS)){toast(`Not enough feed! Grow Corn, or make feed from ${CROP.paddy.name}.`,'bad');AU.err();}else toast(S.animals.some(a=>a)?'Everyone is full!':'Buy an animal first.'); updateYardUI();return n;} function collectAnimal(i){const a=S.animals[i];if(!a||a.stored<=0)return false;const d=ANI[a.t],pr=PROD[d.prod];let n=a.stored;a.stored=0;a.an=1;const happy=(a.hap==null?70:a.hap)>=80&&Math.random()<0.35;if(happy)n++;if(S.today)S.today.goods+=n; S.produce[pr.id]=(S.produce[pr.id]||0)+n;S.stats.collected+=n;S.stats.byA[a.t]=(S.stats.byA[a.t]||0)+n; let man=0;if(d.manure)for(let k=0;k<n;k++)man+=Math.floor(d.manure)+(Math.random()<d.manure%1?1:0);if(man){S.items.fert+=man;S.stats.manure+=man;} const R=penRect(i),ax=R.x+R.w*a.x,ay=R.y+R.h*a.y-60*R.s*(d.big?2:1); if(a.t==='peacock'){a.fanT=3.4;a.fanCd=10;} if(d.big){a.fanT=2.4;a.sprayT=2.4;const w=elephantShower();spawn('drop',ax,ay-40,{n:24,w:160});setTimeout(()=>floatText(w?`Elephant shower! ${w} crop${w>1?'s':''} watered`:'Elephant shower!',ax,ay-70,'#bfe8ff',null,28),500);} spawn('spark',ax,ay,{n:12});spawn('ring',ax,R.y+R.h*a.y,{r:30,col:'rgba(255,240,150,0.9)'});spawn('heart',ax,ay-20,{n:4}); const shopBtn=$('#btnShop');for(let k=0;k<Math.min(n,5);k++)flyTo(ICON[pr.id],ax+rand(-20,20),ay,shopBtn,null,k*0.07,64); floatText(`+${n}`,ax,ay-40,'#fff',ICON[pr.id]);if(happy)setTimeout(()=>floatText('Happy bonus +1!',ax,ay-90,'#ffb3c8',null,28),300);if(man)setTimeout(()=>floatText(`+${man} Fertilizer`,ax,ay-10,'#d8ff9a',ICON.fert,26),200); if(comboT>0)combo++;else combo=0;comboT=1.0;AU.harvest(combo);setTimeout(()=>AU.animal(a.t),80);addXP(pr.xp*n,ax,ay); renderOrders();updateSlots();updateYardUI();tutEvent('collect');return true;} // Elephant bonus: waters every growing crop on the farm for a long time function elephantShower(){let n=0;const t=now();S.plots.forEach((p,j)=>{if(j>=S.unlocked||!p.c||p.g>=1)return;p.wet=Math.max(p.wet||0,t+120);p.an=Math.max(p.an||0,0.6);n++;});S.stats.showers=(S.stats.showers||0)+1;return n;} function interactPen(i,lock){if(i<0)return null;const a=S.animals[i]; if(!a){if(!lock){if(i===ELE_PEN&&ANI.elephant.lvl>S.level){toast(`The Elephant Enclosure opens at level ${ANI.elephant.lvl}`);AU.pop();}else openBuyAnimal(i);}return null;} if(a.stored>0){if(lock&&lock!=='collect')return null;collectAnimal(i);return 'collect';} const d=ANI[a.t];if(d.eat>0&&a.meals<MEALS&&(!lock||lock==='feed')){if(feedAnimal(i,!!lock))return 'feed';if(!lock)openAnimalInfo(i);return null;} if(!lock){const T=T_();a.an=0.6;AU.animal(a.t);if(!(a.petT>Date.now())){a.petT=Date.now()+20000;a.hap=Math.min(100,(a.hap==null?70:a.hap)+5);if(VIEW==='yard'){const R=penRect(i);spawn('heart',R.x+R.w*a.x,R.y+R.h*a.y-70*R.s,{n:3});}}if(a.t==='peacock'||a.t==='elephant'){a.fanT=3.2;a.fanCd=10;if(VIEW==='yard'){const R=penRect(i);spawn('heart',R.x+R.w*a.x,R.y+R.h*a.y-90*R.s*(ANI[a.t].big?2:1),{n:5});}}openAnimalInfo(i);} return null;} // v1.2: release an animal back to the village for half of what it cost const aniRefund=a=>Math.floor((a.paid!=null?a.paid:ANI[a.t].price)/2); function removeAnimal(i){const a=S.animals[i];if(!a)return 0;const d=ANI[a.t],r=aniRefund(a); if(VIEW==='yard'){const R=penRect(i);spawn('heart',R.x+R.w*a.x,R.y+R.h*a.y-70*R.s,{n:6});spawn('ring',R.cx,R.base,{r:30});if(r)floatText(`+${r} coins`,R.cx,R.base-80*R.s,'#ffe68a');} S.animals[i]=null;S.coins+=r;AU.coin();toast(`${d.name} went to a happy new home. +${r} coins`,'good');hideTip();updateYardUI();renderOrders();save();return r;} function setView(v){if(v===VIEW)return;if(v==='yard'&&!yardOpen()){toast(`The Animal Yard opens at level ${YARD_LVL}`,'bad');AU.err();return;} viewDir=v==='yard'?1:-1;VIEW=v;viewT=0;stage.classList.toggle('yardview',v==='yard');hideTip();hoverPlot=-1;hoverPen=-1;AU.select();updateYardUI();tutRefresh();} /* ---------------- Toast / modal ---------------- */ function toast(msg,kind=''){const box=$('#toast');const lastT=box.lastChild;if(lastT&&lastT.textContent===msg&&lastT.style.opacity!=='0')return;const d=document.createElement('div');d.className='tmsg '+kind;d.textContent=msg;box.appendChild(d);while(box.children.length>3)box.firstChild.remove(); setTimeout(()=>{d.style.transition='opacity .4s';d.style.opacity='0';setTimeout(()=>d.remove(),400);},2200);} let modalOn=false,modalKind=''; function openModal(title,html,tabs=null,kind=''){$('#mTitle').textContent=title;$('#mBody').innerHTML=html;$('#mTabs').innerHTML=tabs||'';$('#modalWrap').classList.add('on');modalOn=true;modalKind=kind; const m=$('#modal');m.style.animation='none';void m.offsetWidth;m.style.animation='';AU.click();} function closeModal(){$('#modalWrap').classList.remove('on','ttop');modalOn=false;modalKind='';if(!S)return;tutRefresh();} window.closeModal=closeModal; /* ---------------- Avatars ---------------- */ function drawAvatar(cv,seed,who){const c=cv.getContext('2d'),s=cv.width;const r=mulberry(seed);c.clearRect(0,0,s,s); const bg=['#ffe1a8','#cdeeff','#ffd6e0','#dff5c8','#e8dcff'][Math.floor(r()*5)];c.fillStyle=bg;c.beginPath();c.arc(s/2,s/2,s/2,0,TAU);c.fill(); const name=NAMES[who]||'';const old=/Grandma|Grandpa/.test(name),fem=/Aunt|Grace|Emma|Lily|Grandma|Mia/.test(name); const skin=['#c68a5a','#a8703f','#d9a070','#8a5a34'][Math.floor(r()*4)],hair=old?'#e8e8e8':'#2a1a10'; c.fillStyle=['#e9573f','#3f8fd6','#7bd04a','#f0a020','#c060c0'][Math.floor(r()*5)];c.beginPath();c.ellipse(s/2,s*1.02,s*0.36,s*0.25,0,0,TAU);c.fill(); c.fillStyle=skin;c.fillRect(s*0.44,s*0.62,s*0.12,s*0.14);c.beginPath();c.ellipse(s/2,s*0.48,s*0.22,s*0.25,0,0,TAU);c.fill(); c.fillStyle=hair;c.beginPath();c.ellipse(s/2,s*0.36,s*0.23,s*0.15,0,Math.PI,0);c.fill();c.fillRect(s*0.27,s*0.33,s*0.06,s*0.12);c.fillRect(s*0.67,s*0.33,s*0.06,s*0.12); if(fem){c.beginPath();c.arc(s/2,s*0.2,s*0.1,0,TAU);c.fill();} c.fillStyle='#2a1a10';c.beginPath();c.arc(s*0.42,s*0.48,s*0.025,0,TAU);c.arc(s*0.58,s*0.48,s*0.025,0,TAU);c.fill(); c.fillStyle='rgba(255,120,120,0.35)';c.beginPath();c.arc(s*0.37,s*0.56,s*0.04,0,TAU);c.arc(s*0.63,s*0.56,s*0.04,0,TAU);c.fill(); c.strokeStyle='#5a2a1a';c.lineWidth=s*0.025;c.lineCap='round';c.beginPath();c.arc(s/2,s*0.55,s*0.07,0.2,Math.PI-0.2);c.stroke(); if(!fem&&(old||r()<0.5)){c.strokeStyle=hair;c.lineWidth=s*0.03;c.beginPath();c.moveTo(s*0.42,s*0.57);c.quadraticCurveTo(s/2,s*0.53,s*0.58,s*0.57);c.stroke();} if(fem&&!old){c.fillStyle='#e0302a';c.beginPath();c.arc(s/2,s*0.39,s*0.018,0,TAU);c.fill();} if(old){c.strokeStyle='#5a3418';c.lineWidth=s*0.015;c.strokeRect(s*0.36,s*0.44,s*0.11,s*0.08);c.strokeRect(s*0.53,s*0.44,s*0.11,s*0.08);}} /* ---------------- HUD ---------------- */ let dispCoins=0; function updateHUD(){dispCoins+=(S.coins-dispCoins)*0.2;if(Math.abs(S.coins-dispCoins)<0.5)dispCoins=S.coins;$('#coinNum').textContent=fmt(dispCoins); $('#lvlNum').textContent=S.level;const need=xpNeed(S.level);$('#xpFill').style.width=(S.level>=MAXLVL?100:clamp(S.xp/need*100,0,100))+'%';$('#xpText').textContent=S.level>=MAXLVL?'MAX LEVEL':`XP ${Math.floor(S.xp)} / ${need}`;} function updateClock(){const T=T_();const h=hourAt(T);const hh=Math.floor(h),mm=Math.floor((h-hh)*60/10)*10;const ap=hh>=12?'PM':'AM';const h12=hh%12===0?12:hh%12; $('#dayText').textContent=`Day ${dayNum(T)} · ${h12}:${String(mm).padStart(2,'0')} ${ap}`;const se=seasonAt(T);const tg=$('#seasonTag');tg.textContent=SEA[se].name;tg.className='tag '+se; const c=$('#timeIco').getContext('2d');c.clearRect(0,0,104,104);const night=nightAmt(h); if(night<0.5){c.fillStyle='#ffd84a';c.strokeStyle='#ffb02a';c.lineWidth=7;c.lineCap='round';for(let i=0;i<8;i++){const a=i/8*TAU;c.beginPath();c.moveTo(52+Math.cos(a)*30,52+Math.sin(a)*30);c.lineTo(52+Math.cos(a)*44,52+Math.sin(a)*44);c.stroke();}c.beginPath();c.arc(52,52,22,0,TAU);c.fill();} else{c.fillStyle='#ffe9a0';c.beginPath();c.arc(52,52,30,0,TAU);c.fill();c.fillStyle='#fbecd0';c.beginPath();c.arc(66,42,26,0,TAU);c.fill();} const w=$('#weatherIco').getContext('2d');w.clearRect(0,0,92,92);const rn=rainAt(T),sn=snowAt(T); drawCloud(w,46,44,0.38,rn?[170,180,195]:[255,255,255],3);if(sn){for(let i=0;i<3;i++)drawFlake(w,26+i*20,76,7);}else if(rn){for(let i=0;i<3;i++)drawDrop(w,26+i*20,74,6);} $('#weatherIco').title=sn?'Snow: melting snow waters all plots':rn?'Rain: all plots get water':'Clear sky';} /* ---------------- Hotbar ---------------- */ function hotItems(){const a=CROPS.map(c=>c.id);a.push('|','fert');if(S.items.spr>0||S.plots.some(p=>p.spr)||S.level>=5)a.push('spr');return a;} function buildHotbar(){const hb=$('#hotbar');hb.innerHTML='';let key=1;hotItems().forEach(id=>{if(id==='|'){const s=document.createElement('div');s.className='slot sep';hb.appendChild(s);return;} const d=document.createElement('div');d.className='slot';d.dataset.id=id;const cr=CROP[id];const k=key<=10?(key%10):null;key++; d.innerHTML=`<img src="${PACK[id]}" alt="">${k!==null?`<span class="key">${k}</span>`:''}<span class="cnt"></span>`; if(cr&&cr.lvl>S.level){d.classList.add('locked');d.innerHTML+=`<div class="lk"><svg viewBox="0 0 24 24" width="40" height="40"><rect x="5" y="10" width="14" height="11" rx="3" fill="#a07850"/><path d="M8 10V7a4 4 0 018 0v3" stroke="#a07850" stroke-width="3" fill="none"/></svg>Lv ${cr.lvl}</div>`;} if(cr&&cr.lvl<=S.level&&!canPlantNow(cr,seasonAt(T_()))){d.classList.add('frost');d.innerHTML+=`<div class="lk frostlk">❄ Too cold</div>`;} if(cr&&inSeason(cr,seasonAt(T_()))&&cr.lvl<=S.level){d.innerHTML+=`<svg class="sea" viewBox="0 0 24 24"><path d="M4 20C4 10 10 4 20 4c0 10-6 16-16 16z" fill="#7bd04a" stroke="#fff" stroke-width="2"/></svg>`;} d.onpointerdown=e=>{e.stopPropagation();selectItem(id);};d.onmouseenter=()=>showSlotTip(id,d);d.onmouseleave=()=>hideTip();hb.appendChild(d);});updateSlots();} let lastSeason=''; function updateSlots(){document.querySelectorAll('.slot[data-id]').forEach(d=>{const id=d.dataset.id;const n=id==='fert'?S.items.fert:id==='spr'?S.items.spr:(S.seeds[id]||0);const c=d.querySelector('.cnt'); c.textContent=n;c.classList.toggle('zero',n===0);d.classList.toggle('sel',id===SEL);});} function selectItem(id){const cr=CROP[id];if(cr&&cr.lvl>S.level){toast(`${cr.name} unlocks at level ${cr.lvl}`);AU.err();return;}SEL=id;AU.select();updateSlots();tutEvent('select',id); const d=document.querySelector(`.slot[data-id="${id}"]`);if(d)d.scrollIntoView({block:'nearest',inline:'nearest',behavior:'smooth'});} function showSlotTip(id,el){const cr=CROP[id];let h;if(cr)h=`<b>${cr.name}</b> <span style="color:#a07850">(${cr.local})</span><br>Grows in ${fmtT(cr.time)} with water (in season)<br>Market price today: ${sellPrice(id)} coins${cr.regrow?`<br>Fruit tree: harvest ${cr.regrow} times`:''}<br>Best in ${seasonText(cr)}${canPlantNow(cr,'winter')?'':'<br>Can\'t be planted in Winter'}`; else if(id==='fert')h='<b>Fertilizer (manure)</b><br>Tap a growing plant: it grows 40% faster and gives a bigger harvest (+50%)';else h='<b>Sprinkler</b><br>Place on an empty plot. Waters the 8 plots around it.<br>Select it and tap a sprinkler to pick it up.'; const tp=$('#tooltip');tp.innerHTML=h;tp.style.display='block';const p=stagePos(el);tp.style.left=clamp(p.x-140,10,W-420)+'px';tp.style.top=(p.y-80-tp.offsetHeight)+'px';} function hideTip(){$('#tooltip').style.display='none';} function plotTip(i,x,y){if(i<0||modalOn){hideTip();return;}const tp=$('#tooltip');let h; if(i>=S.unlocked){if(i!==S.unlocked){hideTip();return;}h=`<b>Empty land</b><br>Tap to buy for ${fmt(plotPrice(S.unlocked))} coins`;} else{const p=S.plots[i];if(p.spr)h='<b>Sprinkler</b><br>Keeps nearby plots wet';else if(!p.c){const cr=CROP[SEL];h=cr?`<b>Empty plot</b><br>Tap to plant ${cr.name} (${S.seeds[SEL]||0} seeds)`:'<b>Empty plot</b>';} else{const cr=CROP[p.c],T=T_();const wet=plotWet(p,i,T);h=`<b>${cr.name}</b> · ${p.wilt?'Wilted':STAGE_NAMES[stageOf(p.g)]}${p.fert?' · <span style="color:#4a9a2a">Fertilized</span>':''}<br>`+(p.g>=1?'Tap to harvest!':p.wilt?'<span style="color:#d0402a">Wilted! Tap to water and revive it</span>':`${Math.floor(p.g*100)}% · ${fmtT((1-p.g)/growRate(p,i,T))} left<br>${wet?'<span style="color:#3f8fd6">Watered</span>':'<span style="color:#e08a1a">Dry - tap to water or it will wilt</span>'}`)+(cr.regrow?`<br>Harvests left: ${p.left}`:'');}} tp.innerHTML=h;tp.style.display='block';tp.style.left=clamp(x+24,10,W-tp.offsetWidth-10)+'px';tp.style.top=clamp(y+24,10,H-tp.offsetHeight-10)+'px';} /* ---------------- Orders panel ---------------- */ let seenOrd=new Set(),seenInit=false; function renderOrders(){if(!S)return;fillOrders();const L=$('#orderList');const html=[];let ready=0; S.orders.forEach(o=>{if(o.empty){html.push(`<div class="ocard"><div class="owait">A new customer comes in ${Math.max(0,Math.ceil(o.wait-now()))}s</div></div>`);return;} const ok=canFill(o);if(ok)ready++;if(!seenOrd.has(o.id)){seenOrd.add(o.id);if(seenInit&&!titleOn&&S.tut>=TUT.length)toast(`New order from ${NAMES[o.who]}!`,'good');} html.push(`<div class="ocard ${ok?'ready':''}" data-o="${o.id}">${ok?'<span class="oready">Ready!</span>':''}<div class="ohead"><canvas width="128" height="128" data-ava="${o.ava}" data-who="${o.who}"></canvas><div class="oname">${NAMES[o.who]}<small>${o.due?(o.due<=dayNum(T_())?'<b style="color:#d0402a">Due today</b>':'Due tomorrow')+(sameDay(o)?' · <b style="color:#e08a1a">+20% today</b>':''):'wants:'}</small></div><button class="oskip" title="Skip order" data-skip="${o.id}">×</button></div> <div class="oitems">${o.items.map(it=>{const have=S.produce[it.c]||0;return `<div class="oit ${have>=it.n?'ok':''}"><img src="${ICON[it.c+'_url']}">${Math.min(have,it.n)}/${it.n}</div>`;}).join('')}</div> <div class="ofoot"><span class="rw"><span class="coinIco sm"></span>${fmt(Math.round(o.coins*(S.up.lantern?1.1:1)*(sameDay(o)?1.2:1)))}</span><span class="rw xp">+${o.xp} XP</span>${o.seed?`<span class="rw"><img src="${PACK[o.seed.c]}" style="width:40px">×${o.seed.n}</span>`:''}<button class="btn ${ok?'':'off'}" data-del="${o.id}">Deliver</button></div></div>`);}); const sig=html.join('');if(L._sig!==sig){L.innerHTML=sig;L._sig=sig;L.querySelectorAll('canvas[data-ava]').forEach(cv=>drawAvatar(cv,+cv.dataset.ava,+cv.dataset.who)); L.querySelectorAll('[data-del]').forEach(b=>b.onclick=()=>deliver(+b.dataset.del,b));L.querySelectorAll('[data-skip]').forEach(b=>b.onclick=()=>skipOrder(+b.dataset.skip));} seenInit=true;$('#ordDot').classList.toggle('on',ready>0);$('#ordDot').textContent=ready>0?'!'+ready:'';$('#btnOrders').classList.toggle('ready',ready>0); $('#goalBox').innerHTML=`<b>Farm goal:</b> Become Farm Master! Level ${Math.min(S.level,15)}/15 · Plots ${S.unlocked}/24 · Orders ${Math.min(S.ordersDone,30)}/30`;} /* ---------------- Shop ---------------- */ let shopTab='seeds'; function openShop(tab){shopTab=tab||shopTab;const tabs=['seeds','tools','animals','farm','sell'].map(t=>`<button class="tab ${t===shopTab?'on':''}" data-tab="${t}">${{seeds:'Seeds',tools:'Tools',animals:'Animals',farm:'Farm',sell:'Market'}[t]}</button>`).join(''); openModal('Village Shop','',tabs,'shop');renderShop();document.querySelectorAll('[data-tab]').forEach(b=>b.onclick=()=>{shopTab=b.dataset.tab;document.querySelectorAll('[data-tab]').forEach(x=>x.classList.toggle('on',x===b));renderShop();AU.click();});tutEvent('shop');} const cost=n=>`<span class="price"><span class="coinIco sm"></span>${fmt(n)}</span>`; function renderShop(){const B=$('#mBody');let h='';const T=T_(); if(shopTab==='seeds'){h='<div class="grid">'+CROPS.map(c=>{const lock=c.lvl>S.level;const ins=inSeason(c,seasonAt(T)); return `<div class="card ${lock?'lock':''}">${ins&&!lock?'<span class="badge">In season</span>':''}<img src="${PACK[c.id]}"><h3>${c.name}</h3><div class="sub">${c.local} · grows in ${fmtT(c.time)}<br>Sells for ${sellPrice(c.id)} · ${c.regrow?`tree, ${c.regrow} harvests`:`${c.seeds[0]}-${c.seeds[1]} seeds back`}<br>You have ${S.seeds[c.id]||0} seeds</div> <div class="row">${lock?`<button class="btn off">Level ${c.lvl}</button>`:`<button class="btn ${S.coins>=c.price?'':'off'}" data-buy="${c.id}" data-n="1">${cost(c.price)}</button><button class="btn orange ${S.coins>=c.price*5?'':'off'}" data-buy="${c.id}" data-n="5">×5 ${cost(c.price*5)}</button>`}</div></div>`;}).join('')+'</div>';} else if(shopTab==='tools'){const items=[];Object.entries(UPG).forEach(([k,u])=>{const lv=S.up[k];const maxed=lv>=u.max;const ci=k==='can'?lv:lv;// index of next purchase const nextCost=maxed?0:u.cost[ci],nextLvl=maxed?0:u.lvl[ci];const lock=!maxed&&S.level<nextLvl; items.push(`<div class="card ${lock?'lock':''}"><img src="${PACK[k]}"><h3>${u.name}${u.max>1?` ${maxed?u.max:lv+(k==='can'?0:0)}/${u.max}`:''}</h3><div class="sub">${maxed?'Fully upgraded!<br>'+u.desc[u.max-1]:(k==='can'?`Now: ${u.desc[lv-1]}<br>Next: ${u.desc[lv]}`:u.desc[lv])}</div> <div class="row">${maxed?'<button class="btn off">Owned</button>':lock?`<button class="btn off">Level ${nextLvl}</button>`:`<button class="btn ${S.coins>=nextCost?'':'off'}" data-up="${k}">${cost(nextCost)}</button>`}</div></div>`);}); items.push(`<div class="card"><img src="${PACK.fert}"><h3>Fertilizer</h3><div class="sub">Faster growth and +50% harvest. Free as manure from cows, buffalo and goats<br>You have ${S.items.fert}</div><div class="row"><button class="btn ${S.coins>=30?'':'off'}" data-item="fert" data-n="1">${cost(30)}</button><button class="btn orange ${S.coins>=130?'':'off'}" data-item="fert" data-n="5">×5 ${cost(130)}</button></div></div>`); const sprTotal=S.items.spr+S.plots.filter(p=>p.spr).length;const sprCost=350+sprTotal*250; items.push(`<div class="card ${S.level<5?'lock':''}"><img src="${PACK.spr}"><h3>Sprinkler ${sprTotal}/4</h3><div class="sub">Waters the 8 plots around it, day and night<br>Place it from your item bar</div><div class="row">${S.level<5?'<button class="btn off">Level 5</button>':sprTotal>=4?'<button class="btn off">Max</button>':`<button class="btn ${S.coins>=sprCost?'':'off'}" data-item="spr" data-n="1">${cost(sprCost)}</button>`}</div></div>`); h='<div class="grid">'+items.join('')+'</div>';} else if(shopTab==='animals'){h=animalShopHTML();} else if(shopTab==='farm'){const full=S.unlocked>=MAXPLOTS,pr=plotPrice(S.unlocked); h=`<div style="text-align:center"><img src="${PACK.plot}" style="width:150px"><h3 style="font-size:36px;margin:6px">Bigger Farm</h3><p class="mtext">You have <b>${S.unlocked} / ${MAXPLOTS}</b> plots.<br>${full?'Your farm is full size!':'Clear more land to grow more crops at once.'}</p> ${full?'':`<button class="btn ${S.coins>=pr?'':'off'}" id="shopPlot" style="font-size:34px">Buy plot ${cost(pr)}</button>`}<p class="mtext" style="font-size:22px;color:#a07850;margin-top:24px">Tip: you can also tap the sign on the field.</p></div>`;} else if(shopTab==='sell'){const hot=hotCrop(T,S.level);h=`<div style="text-align:center"><p class="mtext">Sell your harvest in person at the <b>Market stall</b> on your farm.<br>Today's hot crop: <b>${hot.name}</b> (1.6x). Prices change every day!</p><button class="btn" id="goMkt" style="font-size:34px">Walk to the Market</button></div>`;} else{const hot=hotCrop(T,S.level);const have=[...CROPS,...PRODS].filter(c=>(S.produce[c.id]||0)>0);const total=have.reduce((a,c)=>a+S.produce[c.id]*sellPrice(c.id),0); h=`<div class="srow" style="background:#ffe9d6"><img src="${ICON[hot.id+'_url']}"><div class="grow"><b>Today's hot crop: ${hot.name}</b><br><span style="font-size:20px;color:#a07850">Sells for 1.5x today. Prices change every day.</span></div></div>`+ (have.length?have.map(c=>`<div class="srow"><img src="${ICON[c.id+'_url']}"><div class="grow"><b>${c.name}</b> × ${S.produce[c.id]}<br><span style="font-size:20px;color:#a07850">${sellPrice(c.id)} coins each</span></div><button class="btn orange" data-sell="${c.id}" data-n="1">Sell 1</button><button class="btn" data-sell="${c.id}" data-n="999">Sell all ${cost(S.produce[c.id]*sellPrice(c.id))}</button></div>`).join('')+ `<div style="text-align:center;margin-top:16px"><button class="btn" id="sellAll" style="font-size:32px">Sell everything ${cost(total)}</button><p class="mtext" style="font-size:20px;color:#a07850">Tip: orders pay more than the market!</p></div>` :'<p class="mtext">Your basket is empty. Harvest some crops first!</p>');} B.innerHTML=h; B.querySelectorAll('[data-buy]').forEach(b=>b.onclick=()=>{const c=CROP[b.dataset.buy],n=+b.dataset.n;if(S.coins<c.price*n){AU.err();toast('Not enough coins','bad');return;}S.coins-=c.price*n;S.seeds[c.id]=(S.seeds[c.id]||0)+n;AU.buy(); const p=stagePos(b);const slot=document.querySelector(`.slot[data-id="${c.id}"]`);for(let k=0;k<Math.min(n,5);k++)flyTo(ICON[c.id],p.x,p.y,slot,null,k*0.06,48);updateSlots();renderShop();tutEvent('buy');}); B.querySelectorAll('[data-up]').forEach(b=>b.onclick=()=>{const k=b.dataset.up,u=UPG[k],lv=S.up[k];const ci=lv;const pr=u.cost[ci];if(S.coins<pr){AU.err();toast('Not enough coins','bad');return;}S.coins-=pr;S.up[k]++;AU.buy();spawn('spark',W/2,H/2,{n:20});toast(`${u.name} upgraded!`,'good');renderShop();renderOrders();}); B.querySelectorAll('[data-item]').forEach(b=>b.onclick=()=>{const k=b.dataset.item,n=+b.dataset.n;let pr=k==='fert'?(n===5?130:30):350+(S.items.spr+S.plots.filter(p=>p.spr).length)*250;if(S.coins<pr){AU.err();toast('Not enough coins','bad');return;} S.coins-=pr;S.items[k]+=n;AU.buy();if(k==='spr')buildHotbar();updateSlots();renderShop();}); B.querySelectorAll('[data-sell]').forEach(b=>b.onclick=()=>{sell(b.dataset.sell,+b.dataset.n,b);renderShop();}); const sa=$('#sellAll');if(sa)sa.onclick=()=>{[...CROPS,...PRODS].forEach(c=>{if(S.produce[c.id]>0)sell(c.id,999,sa);});renderShop();}; const sp=$('#shopPlot');if(sp)sp.onclick=()=>{buyPlot();renderShop();};const gm=$('#goMkt');if(gm)gm.onclick=goMarket; B.querySelectorAll('[data-ani]').forEach(b=>b.onclick=()=>{if(buyAnimal(b.dataset.ani)){const p=stagePos(b);spawn('heart',p.x,p.y,{n:6});}renderShop();}); B.querySelectorAll('[data-sack]').forEach(b=>b.onclick=()=>{const q=FEED_SACKS[+b.dataset.sack];if(S.coins<q[1]){AU.err();toast('Not enough coins','bad');return;}S.coins-=q[1];S.feed+=q[0];AU.buy();toast(`+${q[0]} feed`,'good');updateYardUI();renderShop();});} /* ---------------- Journal & settings ---------------- */ function seasonText(c){return c.season==='all'?'every season':c.season.map(q=>SEA[q].name).join(' & ');} function seasonMsg(se){const q=SEA[se],list=CROPS.filter(c=>c.lvl<=S.level&&c.season!=='all'&&inSeason(c,se)).map(c=>c.name); return `${q.name} is here! ${q.msg}${list.length?` ${list.join(', ')} grow${list.length>1?'':'s'} faster.`:''}${se==='winter'?' Other crops grow a little slower.':''}`;} function journalSeasons(){const cur=seasonAt(T_());return `<div class="aniRow seaRow">${SEASONS.map(q=>{const cs=CROPS.filter(c=>c.season!=='all'&&inSeason(c,q.id));return `<div class="card sea_${q.id} ${q.id===cur?'cur':''}"><h3>${q.name}${q.id===cur?' (now)':''}</h3><div class="sicons">${cs.map(c=>`<img title="${c.name}" src="${ICON[c.id+'_url']}">`).join('')}</div><div class="sub">${q.msg}</div></div>`;}).join('')}</div>`;} function openJournal(){achNew=0;$('#achDot').classList.remove('on');const st=S.stats; const h=journalStickerRow()+journalSeasons()+journalAnimals()+`<div class="grid" style="grid-template-columns:repeat(auto-fill,minmax(250px,1fr))">${ACH.map(a=>{const got=!!S.ach[a.id];return `<div class="card ${got?'':'lock'}" style="padding:12px"><svg viewBox="0 0 64 64" width="70" height="70"><circle cx="32" cy="32" r="28" fill="${got?'#ffd84a':'#ddd0bb'}" stroke="#fff" stroke-width="5"/><path d="M32 14l5 11 12 1-9 8 3 12-11-6-11 6 3-12-9-8 12-1z" fill="${got?'#ff9d1c':'#c8b89c'}"/></svg><h3 style="font-size:24px">${a.name}</h3><div class="sub">${a.desc}<br>Reward: ${a.r} coins</div></div>`;}).join('')}</div> <div class="srow" style="margin-top:20px;flex-wrap:wrap;font-size:22px;gap:26px;justify-content:center"><span>Harvests: <b>${st.harvests}</b></span><span>Planted: <b>${st.planted}</b></span><span>Orders: <b>${S.ordersDone}</b></span><span>Animal goods: <b>${st.collected||0}</b></span><span>Coins earned: <b>${fmt(st.earned)}</b></span><span>Achievements: <b>${Object.keys(S.ach).length}/${ACH.length}</b></span></div>`; openModal('Farm Journal',h,null,'journal');journalStickerBind();} function openSettings(){const row=(label,ctrl)=>`<div class="srow"><div class="grow">${label}</div>${ctrl}</div>`; const h=row('Music volume',`<input type="range" class="slider" min="0" max="100" value="${SET.music*100}" id="sMus">`)+row('Sound effects volume',`<input type="range" class="slider" min="0" max="100" value="${SET.sfx*100}" id="sSfx">`)+ row('Mute all sound',`<button class="toggle ${SET.muted?'on':''}" id="sMute"></button>`)+row('Fullscreen',`<button class="toggle ${document.fullscreenElement?'on':''}" id="sFull"></button>`)+ row('Screen shake',`<button class="toggle ${SET.shake?'on':''}" id="sShake"></button>`)+row('Show timers on plots',`<button class="toggle ${SET.timers?'on':''}" id="sTim"></button>`)+ `<div class="srow"><div class="keys"><kbd>WASD / Arrows</kbd><span>Walk your farmer</span><kbd>Space</kbd><span>Work the plot / stall next to you</span><kbd>Click / tap</kbd><span>Walk there and work</span><kbd>1-0</kbd><span>Pick a seed</span><kbd>Q / E</kbd><span>Previous / next item</span><kbd>Y</kbd><span>Animal Yard / farm</span><kbd>B</kbd><span>Shop</span><kbd>O</kbd><span>Orders</span><kbd>J</kbd><span>Journal</span><kbd>F</kbd><span>Fullscreen</span><kbd>M</kbd><span>Mute</span><kbd>Esc</kbd><span>Close / settings</span></div></div>`+ (S?`<div style="display:flex;gap:16px;justify-content:center;margin-top:10px"><button class="btn blue" id="sTitle">Title screen</button><button class="btn red" id="sReset">Reset farm</button></div>`:'')+ `<div class="copy" style="text-align:center;margin-top:12px"><b>Created by Kusal K Jayalath</b><br>Pela Gardens v1.2 · © 2026 Kusal K Jayalath. All rights reserved.<br>Font: Fredoka by the Fredoka Project Authors, licensed under the SIL Open Font License 1.1.</div>`; openModal('Settings',h,null,'settings'); $('#sMus').oninput=e=>{SET.music=e.target.value/100;AU.applyVol();saveSet();};$('#sSfx').oninput=e=>{SET.sfx=e.target.value/100;AU.applyVol();saveSet();};$('#sSfx').onchange=()=>AU.coin(); const tg=(id,fn)=>{$(id).onclick=e=>{fn();e.target.classList.toggle('on');saveSet();AU.click();};}; tg('#sMute',()=>{SET.muted=!SET.muted;AU.applyVol();muteIcon();});tg('#sFull',toggleFull);tg('#sShake',()=>SET.shake=!SET.shake);tg('#sTim',()=>SET.timers=!SET.timers); if(S){$('#sTitle').onclick=()=>{save();closeModal();showTitle();};$('#sReset').onclick=()=>confirmBox('Start a new farm? All progress will be lost.',()=>{store.del(SAVE_KEY);location.reload();});}} function confirmBox(msg,yes){openModal('Are you sure?',`<p class="mtext">${msg}</p><div style="display:flex;gap:20px;justify-content:center;margin-top:20px"><button class="btn gray off" id="cNo" style="cursor:pointer">No</button><button class="btn red" id="cYes">Yes</button></div>`); $('#cNo').onclick=closeModal;$('#cYes').onclick=()=>{closeModal();yes();};} function credits(){openModal('Credits',`<div class="mtext"><b>Pela Gardens</b> ("pela" means "seedling")<br><br>Created by <b>Kusal K Jayalath</b><br><br>Game design, code, art and music: made for this game.<br>All pictures are drawn with code. All music and sounds are made live with the Web Audio API.<br><br>Font: <b>Fredoka</b> by the Fredoka Project Authors, licensed under the SIL Open Font License 1.1.<br><br>Thank you for playing!<br><br><span class="copy">© 2026 Kusal K Jayalath. All rights reserved.</span></div>`);} function toggleFull(){const d=document;if(window.pelaNative&&window.pelaNative.toggleFullscreen){window.pelaNative.toggleFullscreen();return;} if(!d.fullscreenElement){(d.documentElement.requestFullscreen||d.documentElement.webkitRequestFullscreen||(()=>{})).call(d.documentElement);}else{(d.exitFullscreen||d.webkitExitFullscreen).call(d);}} function muteIcon(){$('#sndOn').style.display=SET.muted?'none':'';$('#sndOff').style.display=SET.muted?'':'none';} /* ---------------- Tutorial ---------------- */ const TUT=[ // v1.2: short 5-step tutorial that starts with a ripe crop (quick hook) {t:'Good morning! Your <b>Chili is ripe</b>. Tap it and your farmer runs over to pick it!',ev:'harvest',plot:()=>S.plots.findIndex((p,i)=>i<S.unlocked&&p.c&&p.g>=1)}, {t:'Now <b>plant a seed</b>: tap an empty plot.<br><small>Desktop: walk with WASD or arrows, work with Space.</small>',ev:'plant',plot:()=>S.plots.findIndex((p,i)=>i<S.unlocked&&!p.c&&!p.spr)}, {t:'<b>Water</b> your seedling! Dry crops grow slowly and <b>wilt</b> if you forget them.',ev:'water',plot:()=>TUTP}, {t:'Neighbors post <b>orders</b> on the board. Deliver them for coins and XP!',ev:'next',el:()=>PORTRAIT?$('#btnOrders'):$('#orders')}, {t:'Sell extra crops at the <b>Market stall</b>. Prices change every day. Happy farming!',ev:'next',rect:()=>{const a=anchorsPx().stall;return{x:a.x-130*a.s,y:a.y-235*a.s,w:260*a.s,h:250*a.s};}}, ]; let TUTP=-1; const ATUT=[ {t:'This is your <b>Animal Yard</b>! Your new hen is hungry. <b>Tap her</b> to feed her.',ev:'feed',pen:()=>S.animals.findIndex(a=>a&&ANI[a.t].eat>0)}, {t:'Yummy! Each meal makes one good, even while you are away. Animals sleep at night and hide from the rain.',ev:'next',pen:()=>S.animals.findIndex(a=>a)}, {t:`Animals eat <b>feed</b>. Grow <b>Corn</b> (or ${CROP.paddy.name}) on your farm, then tap <b>Make feed</b>. Corn is used by itself when feed runs out.`,ev:'next',el:()=>$('#yMake')}, {t:'Cows, buffalo and goats give <b>manure</b> = free Fertilizer for your plants. Bees help crops give more. Neighbors will ask for eggs and milk too!',ev:'next',el:()=>$('#btnYard')}, ]; function tutStep(){if(!S)return null;if(S.tut<TUT.length)return{st:TUT[S.tut],k:'main'};if(S.aIntro&&S.atut<ATUT.length&&VIEW==='yard')return{st:ATUT[S.atut],k:'ani'};return null;} function tutEvent(ev,arg){if(!S)return;if(S.tut>=TUT.length){if(S.aIntro&&S.atut<ATUT.length&&ATUT[S.atut].ev===ev&&VIEW==='yard'){S.atut++;if(S.atut>=ATUT.length)toast('You are a real animal keeper now!','good');tutRefresh();}return;}const st=TUT[S.tut]; if(ev==='plant'&&S.tut===1)TUTP=arg;if(ev==='harvest'&&S.tut===0&&S.stats.harvests===1){spawn('confetti',0,0,{n:60});} if(ev==='select'&&S.tut===0&&arg!=='chili')return; if(st.ev===ev){S.tut++;if(S.tut>=TUT.length){toast('Tutorial done! Have fun!','good');}tutRefresh();}} function tutRefresh(){const on=S&&S.tut<TUT.length&&!modalOn&&!$('#title').offsetParent===false?true:false;const box=$('#tut'); const cur=tutStep();if(!cur||modalOn||titleOn||(PORTRAIT&&$('#orders').classList.contains('open')&&(cur.k!=='main'||S.tut!==3))||(cur.k==='main'&&VIEW==='yard')){box.classList.remove('on');return;}box.classList.add('on');const st=cur.st;$('#tutText').innerHTML=st.t; $('#tutNext').style.display=st.ev==='next'?'':'none';let r=null; if(st.el){const el=st.el();if(el){const p=el.getBoundingClientRect(),s=stage.getBoundingClientRect();r={x:(p.left-s.left)/SCALE,y:(p.top-s.top)/SCALE,w:p.width/SCALE,h:p.height/SCALE};}} else if(st.pen){const i=st.pen();if(i>=0){const R=penRect(i);r={x:R.x,y:R.y,w:R.w,h:R.h};}} else if(st.rect){r=st.rect();} else if(st.plot){const i=st.plot();if(i>=0){const R=plotRect(i);const up=S.plots[i].c&&S.plots[i].g>0.12?F.tw*0.35:0;r={x:R.x,y:R.y-up,w:R.w,h:R.h+F.dep+up};}} const ring=$('#tutRing'),hand=$('#tutHand'),bub=$('#tutBub'); if(r){ring.style.display='';ring.style.left=(r.x-8)+'px';ring.style.top=(r.y-8)+'px';ring.style.width=(r.w+16)+'px';ring.style.height=(r.h+16)+'px';hand.style.display='';hand.style.left=(r.x+r.w*0.6)+'px';hand.style.top=(r.y+r.h*0.55)+'px';} else{ring.style.display='none';hand.style.display='none';} const bw=bub.offsetWidth,bh=bub.offsetHeight;let bx,by; if(r){bx=clamp(r.x+r.w/2-bw/2,20,W-bw-20);by=r.y>H*0.5||(cur.k==='ani'&&r.y-bh-40>=96)?r.y-bh-40:r.y+r.h+40;if(by+bh>H-20)by=H-bh-20;if(by<130)by=130; if(st.el&&st.el()===$('#orders')){bx=r.x-bw-40;by=300;}}else{bx=PORTRAIT?(W-bw)/2:F.x+F.tw*COLS/2-bw/2;by=PORTRAIT?H*0.28:150;} bub.style.left=bx+'px';bub.style.top=by+'px';} /* ---------------- Title ---------------- */ let titleOn=true; function showTitle(){titleOn=true;stage.classList.add('ontitle');const t=$('#title');t.classList.remove('hide');t.style.display='';$('#tPlay').textContent=store.get(SAVE_KEY)?'Continue':'Play';$('#tNew').style.display=store.get(SAVE_KEY)?'':'none';tutRefresh();} function startGame(fresh){AU.init();AU.resume();introAt=Date.now()+1600;if(fresh){store.del(SAVE_KEY);S=newState();boot();}titleOn=false;stage.classList.remove('ontitle');FM.hello=S.tut<TUT.length?5:0;if(!S.today)S.today=newToday(T_());$('#title').classList.add('hide');setTimeout(()=>{$('#title').style.display='none';},600); AU.deliver();setTimeout(tutRefresh,650);if(welcome){const w=welcome;welcome=null;setTimeout(()=>openModal('Welcome back!',w),700);}} /* ---------------- Input ---------------- */ let ptrDown=false,dragMode=null,lastPlot=-1,mouse={x:-1,y:-1}; function evPos(e){const s=stage.getBoundingClientRect();return{x:(e.clientX-s.left)/SCALE,y:(e.clientY-s.top)/SCALE};} scv.addEventListener('pointerdown',e=>{if(titleOn||!S)return;if(PORTRAIT&&$('#orders').classList.contains('open')){$('#orders').classList.remove('open');tutRefresh();return;}AU.init();AU.resume();const p=evPos(e);ptrDown=true;scv.setPointerCapture&&scv.setPointerCapture(e.pointerId); if(VIEW==='yard'){const j=penAt(p.x,p.y);lastPlot=j;dragMode=interactPen(j,null);if(e.pointerType==='touch')mouse={x:-1,y:-1};return;} const i=plotAtPlant(p.x,p.y);lastPlot=i;touchPlot=e.pointerType==='touch'?i:-1;if(e.pointerType==='touch')mouse={x:-1,y:-1}; // v1.2: the farmer walks over and does the work in person const an=anchorAt(p.x,p.y);if(an&&!(i>=0&&i<S.unlocked)){farmerGo(an,an==='stall'?openMarket:openOrdersPanel);dragMode=null;return;} if(i>=S.unlocked||i<0&&false){dragMode=interact(i,null);return;} if(i>=0){dragGrp={first:false,lock:null};farmerTapPlot(i,dragGrp);dragMode='walk';return;} const b=fmBounds(),gx=(p.x-F.x)/F.tw,gy=(p.y-F.y)/F.th;if(gx>b.x0-0.6&&gx<b.x1+0.6&&gy>b.y0-0.8&&gy<b.y1+0.6)farmerWalkTo(gx,gy);dragMode=null;}); let dragGrp=null; scv.addEventListener('pointermove',e=>{if(!S)return;const p=evPos(e);mouse=p; if(VIEW==='yard'){const j=penAt(p.x,p.y);hoverPen=e.pointerType==='touch'?-1:j;if(ptrDown&&dragMode&&j!==lastPlot&&j>=0){lastPlot=j;interactPen(j,dragMode);}if(e.pointerType!=='touch'&&!ptrDown)penTip(j,p.x,p.y);else hideTip();return;}const i=plotAtPlant(p.x,p.y);hoverPlot=e.pointerType==='touch'?-1:i;if(e.pointerType==='touch'&&ptrDown)touchPlot=i; if(ptrDown&&dragMode==='walk'&&i!==lastPlot&&i>=0&&i<S.unlocked){lastPlot=i;farmerTapPlot(i,dragGrp);}if(e.pointerType!=='touch'&&!ptrDown)plotTip(i,p.x,p.y);else hideTip();}); const endPtr=()=>{ptrDown=false;dragMode=null;lastPlot=-1;const tp=touchPlot;setTimeout(()=>{if(touchPlot===tp&&!ptrDown)touchPlot=-1;},900);};scv.addEventListener('pointerup',endPtr);scv.addEventListener('pointercancel',endPtr); scv.addEventListener('pointerleave',()=>{hoverPlot=-1;hoverPen=-1;hideTip();}); const MOVEK={w:'up',arrowup:'up',s:'down',arrowdown:'down',a:'left',arrowleft:'left',d:'right',arrowright:'right'}; window.addEventListener('keyup',e=>{const m=MOVEK[e.key.toLowerCase()];if(m)FM.keys[m]=false;});window.addEventListener('blur',()=>{FM.keys={};}); window.addEventListener('keydown',e=>{const k=e.key.toLowerCase();if(!titleOn&&!modalOn&&MOVEK[k]&&VIEW==='farm'){FM.keys[MOVEK[k]]=true;e.preventDefault();return;}if(e.repeat&&e.key!==' ')return; if(titleOn){if(modalOn&&$('#modalWrap').classList.contains('ttop')){if(k==='escape')closeModal();return;}if(k==='enter'||k===' '){startGame(false);e.preventDefault();}return;} if(k==='escape'){if(modalOn)closeModal();else openSettings();return;} if(k==='f'||k==='f11'){e.preventDefault();toggleFull();return;}if(k==='m'){SET.muted=!SET.muted;AU.applyVol();muteIcon();saveSet();return;} if(modalOn){if(k==='b'&&modalKind==='shop')closeModal();if(k==='j'&&modalKind==='journal')closeModal();return;} if(k==='b'){openShop();return;}if(k==='j'){openJournal();return;}if(k==='y'){setView(VIEW==='yard'?'farm':'yard');return;} if(VIEW==='yard'){if(k===' '||k==='enter'){e.preventDefault();interactPen(penAt(mouse.x,mouse.y),null);}return;}if(k==='o'){$('#orders').classList.toggle('open');return;} const items=hotItems().filter(x=>x!=='|');if(/^[0-9]$/.test(k)){const idx=(+k+9)%10;if(items[idx])selectItem(items[idx]);return;} if(k==='q'||k==='e'){const avail=items.filter(id=>!CROP[id]||CROP[id].lvl<=S.level);let j=avail.indexOf(SEL);j=(j+(k==='e'?1:-1)+avail.length)%avail.length;selectItem(avail[j]);return;} if(k===' '||k==='enter'){e.preventDefault();farmerUse(e.repeat);}}); $('#btnShop').onclick=()=>openShop();$('#btnYard').onclick=()=>{AU.init();setView(VIEW==='yard'?'farm':'yard');};$('#yBack').onclick=()=>setView('farm'); $('#yFeedAll').onclick=()=>feedAll(false);$('#yMake').onclick=()=>openMakeFeed();$('#yAd').onclick=()=>rewardFeed();$('#btnJournal').onclick=openJournal;$('#btnSettings').onclick=openSettings;$('#btnFull').onclick=toggleFull; $('#btnMute').onclick=()=>{AU.init();SET.muted=!SET.muted;AU.applyVol();muteIcon();saveSet();};$('#btnOrders').onclick=()=>{$('#orders').classList.toggle('open');AU.click();if(S.tut===3)tutEvent('next');tutRefresh();}; $('#mClose').onclick=closeModal;$('#modalWrap').addEventListener('pointerdown',e=>{if(e.target.id==='modalWrap')closeModal();}); $('#tutSkip').onclick=()=>{if(S.tut<TUT.length)S.tut=TUT.length;else S.atut=ATUT.length;tutRefresh();};$('#tutNext').onclick=()=>tutEvent('next'); $('#tPlay').onclick=()=>startGame(false);$('#tNew').onclick=()=>confirmBox('Start a new farm? Your old farm will be lost.',()=>{startGame(true);}); $('#tSettings').onclick=()=>{AU.init();openSettings();$('#modalWrap').classList.add('ttop');};$('#tCredits').onclick=()=>{credits();$('#modalWrap').classList.add('ttop');}; document.addEventListener('fullscreenchange',()=>setTimeout(resize,50));window.addEventListener('resize',()=>{resize();tutRefresh();}); document.addEventListener('visibilitychange',()=>{if(document.hidden)save();else if(S){simulate(lastSimT,now());lastSimT=now();}});window.addEventListener('pagehide',save);window.addEventListener('beforeunload',save); /* ---------------- Boot & loop ---------------- */ let lastSimT=0,lastFrame=0,welcome=null,acc=0,acc2=0; function boot(){VIEW='farm';FM.q=[];FM.keys={};if(S.farmer){FM.x=S.farmer.x;FM.y=S.farmer.y;}else{FM.x=0.7;FM.y=-0.15;}stage.classList.remove('yardview');refreshSpr();lastSimT=now();dispCoins=S.coins;SEL=S.seeds.chili>0||S.level<2?'chili':SEL;buildHotbar();renderOrders();updateHUD();updateClock();lastSeason=seasonAt(T_());updateYardUI();} function init(){loadSet();muteIcon();resize();buildIcons();S=loadSave(); if(S){const away=Math.min(now()-S.last,12*3600);const before=S.plots.filter((p,i)=>i<S.unlocked&&p.c&&p.g>=1).length;const aBefore=S.animals.reduce((n,a)=>n+(a?a.stored:0),0);if(away>5){refreshSpr();simulate(S.last,S.last+away);} const aMade=S.animals.reduce((n,a)=>n+(a?a.stored:0),0)-aBefore; const after=S.plots.filter((p,i)=>i<S.unlocked&&p.c&&p.g>=1).length;const wil=S.plots.filter((p,i)=>i<S.unlocked&&p.wilt).length;if(away>30)welcome=`<p class="mtext">You were away for <b>${fmtT(away).replace(/^(\d+)m.*$/,(m,a)=>a>=60?Math.floor(a/60)+'h '+(a%60)+'m':a+'m')}</b>.<br>Your plants kept growing!${after>before?`<br><b>${after-before}</b> more plants are ready to harvest.`:''}${aMade>0?`<br>Your animals made <b>${aMade}</b> goods for you!`:''}${wil?`<br><b>${wil}</b> thirsty crop${wil>1?'s':''} wilted. Water them to revive!`:''}</p><div style="text-align:center;margin-top:16px"><button class="btn" onclick="closeModal()">Let's farm!</button></div>`;} else S=newState(); boot();drawAvatar($('#tutAva'),7,NAMES.indexOf('Grandma'));showTitle();requestAnimationFrame(loop);setInterval(save,3000);} function loop(ts){const dt=Math.min(0.05,(ts-lastFrame)/1000||0.016);lastFrame=ts;dtFrame=dt;const t=ts/1000; const n=now();if(n>lastSimT){simulate(lastSimT,n);lastSimT=n;} for(const a of S.animals)if(a){if(a.an>0)a.an=Math.max(0,a.an-dt*1.6);if(a.feedT>0)a.feedT-=dt;if(a.stored>0&&!a._rdy){a._rdy=true;if(!titleOn&&VIEW==='yard'){AU.pop();a.an=0.6;}}if(a.stored<=0)a._rdy=false;} for(let i=0;i<S.unlocked;i++){const p=S.plots[i];if(p.an>0)p.an=Math.max(0,p.an-dt*1.6);if(p.c&&p.g>=1&&!p._ripe){p._ripe=true;if(!titleOn){const R=plotRect(i);spawn('spark',R.cx,R.base-F.tw*0.3,{n:8});AU.pop();tutEvent('ripe');}}if(!p.c||p.g<1)p._ripe=false;} if(comboT>0)comboT-=dt; farmerUpdate(dt);renderScene(t);renderFx(dt);updateHUD(); acc+=dt;if(acc>0.25){acc=0;updateClock();if(S.tut<TUT.length||$('#tut').classList.contains('on'))tutRefresh();const se=seasonAt(T_());if(se!==lastSeason){lastSeason=se;buildHotbar();if(!titleOn)toast(seasonMsg(se),'good');}} acc2+=dt;if(acc2>1){acc2=0;renderOrders();checkAch();rescue();updateYardUI();animalIntro();dayTick();whatsNew();dprWatch();if(VIEW==='farm'&&hoverPlot>=0&&!ptrDown)plotTip(hoverPlot,mouse.x,mouse.y);if(VIEW==='yard'&&hoverPen>=0&&!ptrDown)penTip(hoverPen,mouse.x,mouse.y); const T=T_();if(AU.on){const se=seasonAt(T);AU.rainG.gain.setTargetAtTime(rainAmt(T)*(se==='winter'?0.02:0.12),AU.ctx.currentTime,0.5);if(!rainAt(T)&&!isNight(T)&&se!=='winter'&&Math.random()<0.08)AU.chirp();if(se==='summer'&&!rainAt(T)&&!isNight(T)&&Math.random()<0.05)AU.cicada();if(isNight(T)&&se!=='winter'&&Math.random()<0.25)AU.cricket();}} requestAnimationFrame(loop);} function rescue(){if(titleOn)return;const seeds=Object.values(S.seeds).reduce((a,b)=>a+b,0),prod=Object.values(S.produce).reduce((a,b)=>a+b,0); if(seeds===0&&prod===0&&S.coins<5&&!S.plots.some(p=>p.c)){S.seeds.chili=3;updateSlots();openModal('A little gift',`<div style="text-align:center"><canvas id="giftAva" width="160" height="160" style="width:110px;border-radius:50%"></canvas><p class="mtext">Grandma gave you <b>3 Chili seeds</b>.<br>"Every farm starts with one seed, child!"</p><button class="btn" onclick="closeModal()">Thank you!</button></div>`);drawAvatar($('#giftAva'),7,NAMES.indexOf('Grandma'));}} /* ---------------- Animal yard UI (v1.1) ---------------- */ function updateYardUI(){if(!S)return;const open=yardOpen(),y=VIEW==='yard';const b=$('#btnYard');b.classList.toggle('locked',!open); $('#yardLbl').textContent=y?'Farm':'Animals';const ico=y?'farm':'ani';if($('#yardIco')._k!==ico){$('#yardIco')._k=ico;$('#yardIco').innerHTML=`<img alt="" src="${y?ICON.corn_url:PACK.a_chicken}">`;} const need=S.animals.filter(a=>a&&(a.stored>0||(ANI[a.t].eat>0&&a.meals<=0))).length;const dot=$('#yardDot');dot.classList.toggle('on',open&&!y&&need>0);dot.textContent=need; b.classList.toggle('attn',open&&!S.aIntro);$('#yFeedNum').textContent=fmt(S.feed);if(!$('#yFeedIco').getAttribute('src'))$('#yFeedIco').src=ICON.feed_url; const P=window.PORTAL;const adOk=!!(P&&P.canReward&&P.canReward()&&S.animals.some(a=>a&&ANI[a.t].eat>0&&a.meals<MEALS));$('#yAd').style.display=adOk?'':'none';} function rewardFeed(){const P=window.PORTAL;if(!(P&&P.rewardAd))return;$('#yAd').disabled=true; P.rewardAd().then(ok=>{$('#yAd').disabled=false;if(ok){feedAll(true);save();}else toast('No ad available right now. Try again later.');updateYardUI();});} function animalCard(a,pen){const lock=a.lvl>S.level,pr=aniPrice(a.id),own=aniCount(a.id),P=PROD[a.prod],full=freePen(a.id)<0,fullTxt=a.big?(own?'Home is full':'Enclosure full'):'Pens full'; return `<div class="card acard ${lock?'lock':''}">${own?`<span class="badge">You have ${own}</span>`:''}<img src="${PACK['a_'+a.id]}"><h3>${a.name}</h3><div class="sub">Gives <b>${P.name}</b> (sells ${sellPrice(P.id)}) every ${fmtT(a.time)}<br>${a.eat?`Eats ${a.eat} feed per meal`:'Needs no feed'} · ${a.desc}${a.big?'<br><b>Lives in the big Elephant Enclosure</b>':''}${P.rare?' · <b style="color:#b0459a">Rare item!</b>':''}</div> <div class="row">${lock?`<button class="btn off">Level ${a.lvl}</button>`:full?`<button class="btn off">${fullTxt}</button>`:`<button class="btn ${S.coins>=pr?'':'off'}" data-ani="${a.id}"${pen!==undefined?` data-pen="${pen}"`:''}>${cost(pr)}</button>`}</div></div>`;} function animalShopHTML(){if(!yardOpen())return `<div style="text-align:center"><img src="${PACK.a_chicken}" style="width:150px"><p class="mtext">The <b>Animal Yard</b> opens at <b>level ${YARD_LVL}</b>.<br>Chickens, ducks, goats, cows, buffalo, bees, peacocks and a gentle elephant are waiting for you!</p></div>`; return '<div class="grid">'+ANIMALS.map(a=>animalCard(a)).join('')+FEED_SACKS.map((q,k)=>`<div class="card"><img src="${PACK.feed}"><h3>Feed sack ×${q[0]}</h3><div class="sub">For when you run out. Cheaper: grow <b>Corn</b> and tap Make feed in the yard.<br>You have ${fmt(S.feed)} feed</div><div class="row"><button class="btn orange ${S.coins>=q[1]?'':'off'}" data-sack="${k}">${cost(q[1])}</button></div></div>`).join('')+'</div>';} function openBuyAnimal(pen){if(!yardOpen())return;const big=pen===ELE_PEN;const list=ANIMALS.filter(a=>!!a.big===big); openModal(big?'Elephant Enclosure':'New Animal',`<p class="mtext" style="margin-top:0">${big?'A big, shady home with a pond, made for one gentle elephant.':`Pick an animal for this pen. Pens: ${S.animals.filter((a,i)=>a&&i!==ELE_PEN).length} / ${ELE_PEN}`}</p><div class="grid">${list.map(a=>animalCard(a,pen)).join('')}</div>`,null,'buyani'); $('#mBody').querySelectorAll('[data-ani]').forEach(b=>b.onclick=()=>{if(buyAnimal(b.dataset.ani,+b.dataset.pen))closeModal();});} function openMakeFeed(){const rows=Object.keys(FEED_VAL).map(id=>{const c=CROP[id],n=S.produce[id]||0,v=FEED_VAL[id];return `<div class="srow"><img src="${ICON[id+'_url']}"><div class="grow"><b>${c.name}</b> × ${n}<br><span style="font-size:20px;color:#a07850">1 ${c.name} = ${v} feed${c.lvl>S.level?` · unlocks at level ${c.lvl}`:''}</span></div><button class="btn orange ${n?'':'off'}" data-mf="${id}" data-n="1">Use 1</button><button class="btn ${n?'':'off'}" data-mf="${id}" data-n="999">Use all (+${n*v})</button></div>`;}).join(''); openModal('Make Feed',`<div class="srow" style="background:#fff3c8"><img src="${PACK.feed}"><div class="grow"><b>You have ${fmt(S.feed)} feed</b><br><span style="font-size:20px;color:#a07850">Turn crops from your farm into animal feed. Plant Corn: it grows fast and gives the most feed.</span></div></div>${rows} <p class="mtext" style="font-size:20px;color:#a07850">Out of crops? Feed sacks are in the Shop (Animals tab), but growing Corn is much cheaper.</p>`,null,'feed'); $('#mBody').querySelectorAll('[data-mf]').forEach(b=>b.onclick=()=>{const v=makeFeed(b.dataset.mf,+b.dataset.n);if(v){const p=stagePos(b);spawn('crumb',p.x,p.y,{n:12});toast(`+${v} feed`,'good');openMakeFeed();}});} function openAnimalInfo(i){const a=S.animals[i];if(!a)return;const d=ANI[a.t],P=PROD[d.prod],T=T_(),r=aniRefund(a); const st=a.stored>0?`${a.stored} ${P.name} ready to collect`:aniBusy(a)?`${P.name} in ${fmtT((1-a.prog)/aniRate(a,T))}`:'All done for now. Pets make animals happier!'; openModal(d.name,`<div class="srow aniInfo"><img src="${PACK['a_'+a.t]}"><div class="grow"><b>${d.name}</b> · makes ${P.name}<br><span class="aisub">${st}<br>Mood: <b>${hapWord(a.hap)}</b> (${Math.round(a.hap==null?70:a.hap)}%)${d.eat>0?` · Meals: ${a.meals}/${MEALS}`:''}</span></div></div> <div style="display:flex;gap:20px;justify-content:center;margin-top:18px;flex-wrap:wrap"><button class="btn blue" id="aiOk">OK</button><button class="btn red" id="aiRemove">Remove</button></div>`,null,'aniinfo'); $('#aiOk').onclick=closeModal;$('#aiRemove').onclick=()=>{AU.click();confirmBox(`Remove ${d.name}? You get 50% coins back (${r} coins).`,()=>removeAnimal(i));};} function penTip(i,x,y){if(i<0||modalOn){hideTip();return;}const a=S.animals[i],tp=$('#tooltip');let h; if(!a)h=i===ELE_PEN?`<b>Elephant Enclosure</b><br>${ANI.elephant.lvl>S.level?`Opens at level ${ANI.elephant.lvl}`:'Tap to welcome a gentle elephant'}`:`<b>Empty pen</b><br>Tap to buy an animal`;else{const d=ANI[a.t],P=PROD[d.prod],T=T_(); h=`<b>${d.name}</b> · ${P.name}<br>`+(a.stored>0?`Tap to collect ${a.stored} ${P.name}!`:d.eat>0&&a.meals<=0?'<span style="color:#e08a1a">Hungry - tap to feed</span>':`${Math.floor(a.prog*100)}% · ${fmtT((1-a.prog)/aniRate(a,T))} left`)+ `<br>Mood: <b>${hapWord(a.hap)}</b> (${Math.round(a.hap==null?70:a.hap)}%) · makes ${Math.round(hapMul(a)*100)}% speed`+(d.eat>0?`<br>Meals: ${a.meals}/${MEALS} · eats ${d.eat} feed`:`<br>Bees visit your crops (+20% extra harvest chance)`)+(d.manure?`<br>Gives ${d.manure>=1?Math.round(d.manure)+' ':''}manure (Fertilizer)`:'')+(d.big?'<br>Showers all your crops with water':'')+(a.t==='peacock'?'<br>Tap me to see my tail!':'');} tp.innerHTML=h;tp.style.display='block';tp.style.left=clamp(x+24,10,W-tp.offsetWidth-10)+'px';tp.style.top=clamp(y+24,10,H-tp.offsetHeight-10)+'px';} function journalAnimals(){return `<div class="aniRow">${ANIMALS.map(a=>{const lock=a.lvl>S.level;const n=S.stats.byA&&S.stats.byA[a.id]||0;return `<div class="card ${lock?'lock':''}"><img src="${PACK['a_'+a.id]}"><h3>${a.name}</h3><div class="sub">${lock?`Level ${a.lvl}`:`${PROD[a.prod].name}: ${n}`}</div></div>`;}).join('')}</div>`;} let introAt=0; function animalIntro(){if(!S||titleOn||modalOn||welcome||Date.now()<introAt||S.aIntro||!yardOpen()||S.tut<TUT.length)return; openModal('Animals are here!',`<div class="gma"><canvas id="gmaAva" width="160" height="160"></canvas><div class="mtext" style="text-align:left;font-size:25px"><b>Grandma:</b> "Good news, child! Animals have come to our village. I brought you one of my hens and some feed. Animals eat <b>feed</b> made from the <b>Corn</b> and <b>${CROP.paddy.name}</b> you grow. In return they give eggs, milk and honey, and cows and buffalo give <b>manure</b>: free Fertilizer for your plants!"</div></div> <div style="text-align:center;margin-top:18px"><button class="btn" id="gmaGo" style="font-size:34px">Show me the yard!</button></div>`,null,'intro'); drawAvatar($('#gmaAva'),7,NAMES.indexOf('Grandma')); S.aIntro=1;S.atut=0;if(!S.animals.some(a=>a)){S.animals[0]=newAnimal('chicken');}S.feed+=4;S.seeds.corn=(S.seeds.corn||0)+3;buildHotbar();save(); $('#gmaGo').onclick=()=>{closeModal();setView('yard');};} /* ---------------- Sticker pack (Farm Master reward) ---------------- All stickers are drawn at download time with the game's own canvas art (no embedded images, no network). */ const STK_SIZE=512; const SPROUT_P=['M50 98C50 70 48 55 50 40','M50 48C30 50 12 38 8 18c22-4 40 8 42 30z','M50 40C58 18 78 8 96 12c-2 22-22 34-46 28z']; function stkSprout(c,x,y,s){c.save();c.translate(x,y);c.scale(s,s);c.translate(-50,-50);c.lineJoin='round';c.lineCap='round'; c.strokeStyle='#3f8a24';c.lineWidth=7;c.stroke(new Path2D(SPROUT_P[0])); [['#7bd04a',SPROUT_P[1]],['#9ae36a',SPROUT_P[2]]].forEach(q=>{const p=new Path2D(q[1]);c.fillStyle=q[0];c.fill(p);c.strokeStyle='#fff';c.lineWidth=5;c.stroke(p);});c.restore();} function stkFace(c,x,y,s,dark='#3a1a10'){c.save();c.translate(x,y);c.fillStyle=dark; [-1,1].forEach(k=>{c.beginPath();c.ellipse(k*s*0.42,0,s*0.13,s*0.17,0,0,TAU);c.fill();});c.fillStyle='#fff';[-1,1].forEach(k=>{c.beginPath();c.arc(k*s*0.42-s*0.04,-s*0.06,s*0.05,0,TAU);c.fill();}); c.fillStyle='rgba(255,90,110,0.45)';[-1,1].forEach(k=>{c.beginPath();c.ellipse(k*s*0.72,s*0.22,s*0.15,s*0.09,0,0,TAU);c.fill();}); c.strokeStyle=dark;c.lineWidth=s*0.09;c.lineCap='round';c.beginPath();c.arc(0,s*0.12,s*0.2,0.25,Math.PI-0.25);c.stroke();c.restore();} function stkText(c,str,x,y,size,maxW,fill,stroke,rot=0){c.save();c.translate(x,y);c.rotate(rot);c.font=`700 ${size}px Fredoka`;const w=c.measureText(str).width;if(w>maxW)c.scale(maxW/w,maxW/w); c.textAlign='center';c.textBaseline='middle';c.lineJoin='round';c.strokeStyle=stroke;c.lineWidth=size*0.22;c.strokeText(str,0,size*0.06);c.strokeText(str,0,0); const g=c.createLinearGradient(0,-size*0.45,0,size*0.45);g.addColorStop(0,fill[0]);g.addColorStop(1,fill[1]);c.fillStyle=g;c.fillText(str,0,0); c.globalAlpha=0.35;c.fillStyle='#fff';c.save();c.beginPath();c.rect(-2000,-size,4000,size*0.62);c.clip();c.fillText(str,0,0);c.restore();c.restore();} function stkSparkle(c,x,y,r,col='#ffd84a'){c.fillStyle=col;c.beginPath();for(let i=0;i<8;i++){const a=i/8*TAU-Math.PI/2,rr=i%2?r*0.28:r;c.lineTo(x+Math.cos(a)*rr,y+Math.sin(a)*rr);}c.fill();} function stkAvatar(c,x,y,d,seed,who){const cv=makeCanvas(d,d);drawAvatar(cv,seed,who);c.save();c.beginPath();c.arc(x,y,d/2,0,TAU);c.clip();c.drawImage(cv,x-d/2,y-d/2);c.restore(); c.strokeStyle='rgba(90,52,24,0.18)';c.lineWidth=d*0.02;c.beginPath();c.arc(x,y,d/2-d*0.01,0,TAU);c.stroke();} function stkBubble(c,x,y,w,h,str,size){c.save();c.fillStyle='#fff';c.strokeStyle='#5a3418';c.lineWidth=7;roundRect(c,x-w/2,y-h/2,w,h,h*0.45);c.fill();c.stroke(); c.beginPath();c.moveTo(x-w*0.22,y+h/2-4);c.lineTo(x-w*0.36,y+h/2+30);c.lineTo(x-w*0.06,y+h/2-4);c.closePath();c.fill();c.stroke();c.fillRect(x-w*0.22+2,y+h/2-9,w*0.16-4,8); c.fillStyle='#5a3418';c.font=`700 ${size}px Fredoka`;c.textAlign='center';c.textBaseline='middle';const tw=c.measureText(str).width;if(tw>w-30){c.translate(x,y);c.scale((w-30)/tw,1);c.fillText(str,0,2);}else c.fillText(str,x,y+2);c.restore();} function stkRibbon(c,x,y,w,h,col,dark){c.save();c.fillStyle=dark;[-1,1].forEach(k=>{c.beginPath();c.moveTo(x+k*w*0.42,y-h*0.2);c.lineTo(x+k*(w*0.5+h*0.55),y+h*0.05);c.lineTo(x+k*(w*0.5+h*0.25),y+h*0.4);c.lineTo(x+k*(w*0.5+h*0.55),y+h*0.75);c.lineTo(x+k*w*0.42,y+h*0.75);c.closePath();c.fill();}); const g=c.createLinearGradient(0,y-h/2,0,y+h/2);g.addColorStop(0,col[0]);g.addColorStop(1,col[1]);c.fillStyle=g;roundRect(c,x-w/2,y-h/2,w,h,h*0.3);c.fill();c.restore();} function stkStar(c,x,y,r){c.save();c.translate(x,y);c.beginPath();for(let i=0;i<10;i++){const a=i/10*TAU-Math.PI/2,rr=i%2?r*0.5:r;c.lineTo(Math.cos(a)*rr,Math.sin(a)*rr);}c.closePath(); const g=c.createLinearGradient(0,-r,0,r);g.addColorStop(0,'#ffe56b');g.addColorStop(1,'#ff9d1c');c.fillStyle=g;c.lineJoin='round';c.strokeStyle='#fff';c.lineWidth=r*0.12;c.fill();c.stroke();c.restore();} const STICKERS=[ {id:'farm_master',name:'Farm Master!',draw(c){[[-150,-150,30],[160,-130,24],[-170,30,18],[175,40,20]].forEach(q=>stkSparkle(c,256+q[0],230+q[1],q[2],'#fff3a0')); stkStar(c,256,190,150);stkText(c,'15',256,200,110,200,['#fff','#fff4c0'],'#c86a1a');stkRibbon(c,256,380,400,100,['#ff8f6b','#e9573f'],'#b03a26');stkText(c,'Farm Master!',256,378,72,370,['#fff','#ffe9e0'],'#9a2e1c');}}, {id:'pela_gardens_logo',name:'Pela Gardens logo',draw(c){stkSprout(c,256,128,1.7);stkText(c,'Pela',256,236,120,380,['#ffe56b','#ffc23a'],'#c86a1a');stkText(c,'Gardens',256,346,120,420,['#9ae36a','#5fb83a'],'#2f6d1a'); stkRibbon(c,256,440,330,56,['#ff8f6b','#e9573f'],'#b03a26');stkText(c,'From seed to harvest',256,440,34,300,['#fff','#fff'],'#b03a26');}}, {id:'grandma',name:'Grandma',draw(c){stkAvatar(c,230,290,330,7,NAMES.indexOf('Grandma'));stkBubble(c,350,110,240,96,'Hello, child!',44);drawProduce(c,'mango',380,400,62,1,0.2);}}, {id:'neighbor',name:'Neighbor Ben',draw(c){stkAvatar(c,256,236,320,40,NAMES.indexOf('Uncle Ben'));c.save();c.translate(256,430);c.scale(2.6,2.6);drawBasket(c,0,0);c.restore();}}, {id:'coins',name:'Coins',draw(c){[[0,150,1],[-110,130,0.9],[110,130,0.9],[-55,40,0.95],[60,50,0.95],[0,-60,1.05]].forEach(q=>drawCoin(c,256+q[0],240+q[1],80*q[2])); stkText(c,'+100',380,110,78,200,['#fff6b0','#ffc23a'],'#a05a00',0.15);stkSparkle(c,120,110,34,'#fff3a0');stkSparkle(c,420,260,24,'#fff3a0');}}, {id:'watering_can',name:'Watering can',draw(c){drawCan(c,220,300,3.6,'#5ab0e8');[[410,250,22],[440,320,18],[395,380,20],[455,410,14]].forEach(q=>drawDrop(c,q[0],q[1],q[2]));}}, {id:'tomato',name:'Tomato',draw(c){drawProduce(c,'tomato',256,280,190,1);stkFace(c,256,300,110);}}, {id:'chili',name:'Chili',draw(c){drawProduce(c,'chili',200,250,165,1,-0.35);drawProduce(c,'chili',320,270,165,1,0.15);}}, {id:'mango',name:'Mango',draw(c){drawProduce(c,'mango',266,280,180,1);stkFace(c,250,320,95);}}, {id:'king_coconut',name:'Coconut',draw(c){drawProduce(c,'coconut',256,280,190,1);stkFace(c,256,310,105);c.strokeStyle='#fff';c.lineWidth=12;c.lineCap='round';c.beginPath();c.moveTo(300,130);c.lineTo(340,40);c.stroke();c.strokeStyle='#ff6b8a';c.setLineDash([18,18]);c.stroke();c.setLineDash([]);}}, {id:'pineapple',name:'Pineapple',draw(c){drawProduce(c,'pineapple',256,300,190,1);stkFace(c,256,360,85);}}, {id:'banana',name:'Banana',draw(c){drawProduce(c,'banana',236,262,235,1);[[110,140,26],[400,420,22]].forEach(q=>stkSparkle(c,q[0],q[1],q[2],'#fff3a0'));}}, {id:'seed_packet',name:'Seed packet',draw(c){c.save();c.translate(256,262);c.scale(3.4,3.4);c.translate(-64,-64);drawSeedPack(c,CROP.tomato);c.restore();stkSparkle(c,420,110,30,'#fff3a0');}}, {id:'plant_it',name:'Plant it!',draw(c){stkSprout(c,256,160,2.2);stkText(c,'Plant it!',256,370,120,430,['#9ae36a','#4fae36'],'#24561a',-0.05);}}, {id:'harvest_time',name:'Harvest time!',draw(c){c.save();c.translate(256,215);c.scale(3.1,3.1);drawBasket(c,0,0);c.restore();stkText(c,'Harvest',256,345,104,430,['#ffd06a','#f08a1c'],'#8a4a1a',-0.04);stkText(c,'time!',256,440,96,300,['#ff9a7a','#e9573f'],'#8a2a1a',-0.04);}}, {id:'grow',name:'Grow!',draw(c){stkSprout(c,256,140,1.9);stkText(c,'Grow!',256,350,170,430,['#ffe56b','#ffb02a'],'#2f6d1a');[[90,180,26],[420,170,30],[440,440,20]].forEach(q=>stkSparkle(c,q[0],q[1],q[2],'#fff3a0'));}}, {id:'happy_hen',name:'Happy Hen',draw(c){drawAnimal(c,'chicken',250,380,3.4,{t:0,ph:0});drawProduce(c,'egg',400,400,58,1,0.25);[[110,130,28],[420,120,22]].forEach(q=>stkSparkle(c,q[0],q[1],q[2],'#fff3a0'));}}, {id:'moo_cow',name:'Moo!',draw(c){drawAnimal(c,'cow',230,440,2.5,{t:0,ph:0});stkBubble(c,360,96,220,96,'Moo!',58);}}, {id:'honey_bee',name:'Honey Bee',draw(c){drawProduce(c,'honey',256,300,170,1);drawBee(c,120,140,5,1.2,1);drawBee(c,410,190,3.4,2.4,-1);[[420,420,24],[90,400,20]].forEach(q=>stkSparkle(c,q[0],q[1],q[2],'#fff3a0'));}}, {id:'proud_peacock',name:'Proud Peacock',draw(c){drawAnimal(c,'peacock',280,440,2.3,{t:0,ph:0,fan:1});[[90,110,26],[440,90,22],[450,300,16]].forEach(q=>stkSparkle(c,q[0],q[1],q[2],'#fff3a0'));}}, {id:'gentle_giant',name:'Gentle Giant',draw(c){drawAnimal(c,'elephant',230,440,1.85,{t:0.3,ph:0,trunk:1,spray:true});[[420,120,30,'#ff8aa8'],[470,210,20,'#ff8aa8']].forEach(q=>{c.save();c.translate(q[0],q[1]);c.fillStyle=q[3];c.strokeStyle='#fff';c.lineWidth=7;c.beginPath();const r=q[2];c.moveTo(0,r*0.9);c.bezierCurveTo(-r*1.6,-r*0.2,-r*0.7,-r*1.3,0,-r*0.5);c.bezierCurveTo(r*0.7,-r*1.3,r*1.6,-r*0.2,0,r*0.9);c.closePath();c.stroke();c.fill();c.restore();});}}, {id:'spring_blossom',name:'Spring Blossom',draw(c){for(let i=0;i<5;i++){const a=i/5*TAU-Math.PI/2;c.save();c.translate(256+Math.cos(a)*92,230+Math.sin(a)*92);c.rotate(a+Math.PI/2);c.fillStyle='#ffb3cf';c.strokeStyle='#fff';c.lineWidth=10;c.beginPath();c.ellipse(0,0,74,98,0,0,TAU);c.fill();c.stroke();c.restore();} c.fillStyle='#ffe56b';c.beginPath();c.arc(256,230,70,0,TAU);c.fill();stkFace(c,256,236,80);stkText(c,'Spring!',256,430,96,380,['#ffd1e3','#ff7aa8'],'#9a2e5c',-0.04);}}, {id:'summer_sun',name:'Summer Sun',draw(c){c.fillStyle='#ffb02a';for(let i=0;i<12;i++){const a=i/12*TAU;c.save();c.translate(256,220);c.rotate(a);c.beginPath();c.moveTo(-28,-120);c.lineTo(0,-186);c.lineTo(28,-120);c.closePath();c.fill();c.restore();} const g=c.createRadialGradient(240,190,20,256,220,130);g.addColorStop(0,'#fff3a0');g.addColorStop(1,'#ffc23a');c.fillStyle=g;c.strokeStyle='#fff';c.lineWidth=12;c.beginPath();c.arc(256,220,125,0,TAU);c.fill();c.stroke();stkFace(c,256,236,120);stkText(c,'Summer!',256,440,96,380,['#fff6b0','#ffb02a'],'#a05a00',-0.04);}}, {id:'autumn_leaf',name:'Autumn Leaf',draw(c){c.save();c.translate(256,220);const p=new Path2D('M0 -150 L30 -70 L95 -110 L80 -30 L150 -20 L90 30 L120 90 L40 70 L0 130 L-40 70 L-120 90 L-90 30 L-150 -20 L-80 -30 L-95 -110 L-30 -70 Z'); c.lineJoin='round';c.fillStyle='#ff8a3a';c.strokeStyle='#fff';c.lineWidth=14;c.stroke(p);c.fill(p);c.strokeStyle='#c8501a';c.lineWidth=7;c.beginPath();c.moveTo(0,190);c.lineTo(0,-90);c.stroke();c.restore();stkFace(c,256,226,80);stkText(c,'Autumn!',256,440,96,380,['#ffd06a','#f0601c'],'#7a2a0a',-0.04);}}, {id:'winter_snowman',name:'Winter Snowman',draw(c){c.strokeStyle='#cfe6f5';c.lineWidth=10;c.fillStyle='#fff';[[256,300,110],[256,160,78]].forEach(q=>{c.beginPath();c.arc(q[0],q[1],q[2],0,TAU);c.fill();c.stroke();}); stkFace(c,256,160,62);c.fillStyle='#ff8a1c';c.beginPath();c.moveTo(250,170);c.lineTo(300,182);c.lineTo(250,186);c.fill();c.fillStyle='#e9573f';roundRect(c,176,222,160,30,14);c.fill(); [[120,90,22],[400,120,26],[420,330,18],[90,330,16]].forEach(q=>stkSparkle(c,q[0],q[1],q[2],'#bfe8ff'));stkText(c,'Winter!',256,445,90,380,['#e6f6ff','#7cc0ef'],'#1f5a8a',-0.04);}}, ]; /* v1.2 level stickers: every level from 2 to 20 gifts one sticker (collected = level reached, so it is saved with the farm). */ const LEVEL_STK=[[2,'plant_it'],[3,'tomato'],[4,'happy_hen'],[5,'chili'],[6,'watering_can'],[7,'moo_cow'],[8,'mango'],[9,'spring_blossom'],[10,'honey_bee'],[11,'banana'],[12,'summer_sun'],[13,'king_coconut'],[14,'proud_peacock'],[15,'autumn_leaf'],[16,'pineapple'],[17,'harvest_time'],[18,'winter_snowman'],[19,'gentle_giant'],[20,'grow']]; const stkLvl=id=>{const q=LEVEL_STK.find(q=>q[1]===id);return q?q[0]:0;}; const stkOwned=id=>!S||S.level>=stkLvl(id);const ownedStickers=()=>STICKERS.filter(s=>stkOwned(s.id)); const LOCK_CARD='<svg class="albLock" viewBox="0 0 100 100" aria-hidden="true"><rect x="8" y="8" width="84" height="84" rx="22" fill="#efe4d2"/><rect x="31" y="46" width="38" height="30" rx="7" fill="#c8b496"/><path d="M38 46V37a12 12 0 0124 0v9" stroke="#c8b496" stroke-width="7" fill="none"/><text x="50" y="68" font-size="18" font-weight="700" text-anchor="middle" fill="#efe4d2">?</text></svg>'; const stkForLevel=L=>{const q=LEVEL_STK.find(q=>q[0]===L);return q?STICKERS.find(s=>s.id===q[1]):null;}; // iOS memory: UI stickers are rendered lazily (full 512px), kept only as a PNG data URL, and their canvases are released right away. const STK_URL={};const cvFree=cv=>{if(cv){cv.width=0;cv.height=0;}}; function stkUrl(id){if(!stkOwned(id))return '';if(STK_URL[id])return STK_URL[id];const cv=stickerCanvas(id);const u=cv.toDataURL('image/png');cvFree(cv);return STK_URL[id]=u;} function levelStickerHTML(L){const st=stkForLevel(L);if(!st)return '';return `<div class="lvStk"><div class="lvStkT">New Sticker!</div><img alt="${st.name}" src="${stkUrl(st.id)}"><div class="lvStkN">${st.name}</div><div class="stkBtns"><button class="btn orange" onclick="downloadSticker('${st.id}')">Download PNG</button><button class="btn blue" onclick="openStickerAlbum()">Sticker Album</button></div></div>`;} // Download one unlocked sticker as a 512px transparent PNG. iPhone/Android: share sheet with the file when available; else <a download>; last resort: open the image. async function downloadSticker(id){if(!stkOwned(id))return false;const st=STICKERS.find(s=>s.id===id);if(!st)return false; const cv=stickerCanvas(id);const blob=await toBlobP(cv,'image/png');cvFree(cv);const name='pela-sticker-'+st.name.toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'')+'.png'; const mobile=/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)||(navigator.maxTouchPoints>1&&/Macintosh/.test(navigator.userAgent)); try{if(mobile&&navigator.canShare&&window.File){const f=new File([blob],name,{type:'image/png'});if(navigator.canShare({files:[f]})){await navigator.share({files:[f],title:st.name});return true;}}}catch(e){if(e&&e.name==='AbortError')return true;} const url=URL.createObjectURL(blob);const a=document.createElement('a'); if('download' in a){a.href=url;a.download=name;a.style.display='none';document.body.appendChild(a);a.click();setTimeout(()=>{a.remove();URL.revokeObjectURL(url);},60000);toast('Sticker saved!','good');return true;} const w=window.open(url,'_blank');if(!w)toast('Long-press the sticker to save it.');setTimeout(()=>URL.revokeObjectURL(url),60000);return true;} function openStickerDetail(id){if(!stkOwned(id))return;const st=STICKERS.find(s=>s.id===id),L=stkLvl(id); openModal(st.name,`<div class="stk"><img class="stkBig" alt="${st.name}" src="${stkUrl(id)}"><div class="stkInfo">${L?`Level ${L} sticker · `:''}512 × 512 PNG</div><div class="stkBtns"><button class="btn orange" id="stkOne">Download PNG</button><button class="btn blue" id="stkBack">Sticker Album</button></div></div>`,null,'stkdetail'); $('#stkOne').onclick=()=>downloadSticker(id);$('#stkBack').onclick=()=>openStickerAlbum();} function openStickerAlbum(){const got=LEVEL_STK.filter(q=>S.level>=q[0]).length; const h=`<div class="stk"><div class="stkTitle">${got} / ${LEVEL_STK.length} stickers collected</div><div class="album">${LEVEL_STK.map(([L,id])=>{const st=STICKERS.find(s=>s.id===id),own=S.level>=L; return `<div class="alb ${own?'own':'lock'}" data-alb="${L}"${own?'':' draggable="false"'}>${own?`<img alt="${st.name}" data-albimg="${id}">`:LOCK_CARD}<div class="albN">${own?st.name:'???'}</div><div class="albL">Level ${L}</div></div>`;}).join('')}</div> <div class="stkTip">Level up your farm to collect them all!</div></div>`; openModal('Sticker Album',h,null,'album');document.querySelectorAll('.alb.own').forEach(el=>el.onclick=()=>openStickerDetail(el.querySelector('img').dataset.albimg));const imgs=[...document.querySelectorAll('img[data-albimg]')];let k=0;(function next(){if(k>=imgs.length||!imgs[k].isConnected)return;const im=imgs[k++];im.src=stkUrl(im.dataset.albimg);setTimeout(next,0);})();} function stkDieCut(art,ow){const S=art.width,sil=makeCanvas(S,S),sc=sil.getContext('2d'); [[1,40],[0.66,28],[0.33,16]].forEach(([k,n])=>{for(let i=0;i<n;i++){const a=i/n*TAU;sc.drawImage(art,Math.cos(a)*ow*k,Math.sin(a)*ow*k);}}); sc.globalCompositeOperation='source-in';sc.fillStyle='#fff';sc.fillRect(0,0,S,S); const out=makeCanvas(S,S),o=out.getContext('2d');o.save();o.shadowColor='rgba(50,35,10,0.38)';o.shadowBlur=S*0.028;o.shadowOffsetY=S*0.014;o.drawImage(sil,0,0);o.restore(); o.globalAlpha=0.5;o.drawImage(sil,0,0);o.globalAlpha=1;o.drawImage(art,0,0);cvFree(sil);return out;} function stickerCanvas(id,size=STK_SIZE){const st=STICKERS.find(s=>s.id===id);const S=size; const art=makeCanvas(S,S),c=art.getContext('2d');c.save();c.scale(S/STK_SIZE,S/STK_SIZE);c.translate(STK_SIZE/2,STK_SIZE/2);c.scale(0.86,0.86);c.translate(-STK_SIZE/2,-STK_SIZE/2);st.draw(c);c.restore(); const out=stkDieCut(art,S*0.03);cvFree(art);return out;} function stkTray(){const cv=makeCanvas(96,96),c=cv.getContext('2d');c.imageSmoothingQuality='high';const l=stickerCanvas('pela_gardens_logo');c.drawImage(l,0,0,96,96);cvFree(l);return cv;} /* ---- tiny ZIP writer (STORE; PNG/WebP are already compressed) ---- */ const CRC_T=(()=>{const t=new Uint32Array(256);for(let n=0;n<256;n++){let c=n;for(let k=0;k<8;k++)c=c&1?0xEDB88320^(c>>>1):c>>>1;t[n]=c>>>0;}return t;})(); function crc32(u){let c=0xFFFFFFFF;for(let i=0;i<u.length;i++)c=CRC_T[(c^u[i])&255]^(c>>>8);return (c^0xFFFFFFFF)>>>0;} function makeZip(files){const enc=new TextEncoder(),parts=[],cen=[];let off=0;const d=new Date(); const tm=(d.getHours()<<11)|(d.getMinutes()<<5)|(d.getSeconds()>>1),dt=((d.getFullYear()-1980)<<9)|((d.getMonth()+1)<<5)|d.getDate(); files.forEach(f=>{const nm=enc.encode(f.name),data=f.data,crc=crc32(data);const h=new DataView(new ArrayBuffer(30)); h.setUint32(0,0x04034b50,true);h.setUint16(4,20,true);h.setUint16(6,0x0800,true);h.setUint16(8,0,true);h.setUint16(10,tm,true);h.setUint16(12,dt,true); h.setUint32(14,crc,true);h.setUint32(18,data.length,true);h.setUint32(22,data.length,true);h.setUint16(26,nm.length,true);h.setUint16(28,0,true);parts.push(h.buffer,nm,data); const e=new DataView(new ArrayBuffer(46));e.setUint32(0,0x02014b50,true);e.setUint16(4,20,true);e.setUint16(6,20,true);e.setUint16(8,0x0800,true);e.setUint16(10,0,true); e.setUint16(12,tm,true);e.setUint16(14,dt,true);e.setUint32(16,crc,true);e.setUint32(20,data.length,true);e.setUint32(24,data.length,true);e.setUint16(28,nm.length,true); e.setUint32(42,off,true);cen.push(e.buffer,nm);off+=30+nm.length+data.length;}); const cs=cen.reduce((a,b)=>a+b.byteLength,0),end=new DataView(new ArrayBuffer(22));end.setUint32(0,0x06054b50,true);end.setUint16(8,files.length,true);end.setUint16(10,files.length,true); end.setUint32(12,cs,true);end.setUint32(16,off,true);return new Blob([...parts,...cen,end.buffer],{type:'application/zip'});} const toBlobP=(cv,type,q)=>new Promise(r=>cv.toBlob(r,type,q)); async function blobBytes(b){return new Uint8Array(await b.arrayBuffer());} async function stkWebp(cv){for(const q of [0.9,0.82,0.72,0.6]){const b=await toBlobP(cv,'image/webp',q);if(!b||b.type!=='image/webp')return null;if(b.size<100*1024)return b;}return null;} async function buildStickerZip(){const files=[];let webp=0; const OWN=ownedStickers();for(let i=0;i<OWN.length;i++){const st=OWN[i],cv=stickerCanvas(st.id),nm=String(i+1).padStart(2,'0')+'_'+st.id; files.push({name:'png/'+nm+'.png',data:await blobBytes(await toBlobP(cv,'image/png'))}); const w=await stkWebp(cv);cvFree(cv);if(w){files.push({name:'webp/'+nm+'.webp',data:await blobBytes(w)});webp++;} await new Promise(r=>setTimeout(r,0));} files.push({name:'tray_icon_96.png',data:await blobBytes(await toBlobP(stkTray(),'image/png'))}); files.push({name:'README.txt',data:new TextEncoder().encode(`Pela Gardens - Free Sticker Pack\r\n\r\nThank you for playing Pela Gardens and becoming Farm Master!\r\n\r\n${OWN.length} original stickers, 512x512 with transparent background.\r\n png/ - PNG stickers for any app or for printing\r\n webp/ - WebP stickers (under 100 KB each, WhatsApp sticker friendly)\r\n tray_icon_96.png - 96x96 tray icon for sticker maker apps\r\n${webp?'':'\r\nNote: this browser cannot create WebP files, so only PNG stickers are included.\r\nOpen the game in Chrome, Edge or Firefox to get the WebP versions too.\r\n'}\r\nStickers:\r\n${OWN.map((s,i)=>' '+String(i+1).padStart(2,'0')+'. '+s.name).join('\r\n')}\r\n\r\nFor personal use. Made with love by Kusal K Jayalath.\r\n`)}); return {blob:makeZip(files),count:files.length,webp};} let stkBusy=false; async function downloadStickers(btn){if(stkBusy)return;stkBusy=true;const lbl=btn?btn.innerHTML:'';if(btn){btn.classList.add('off');btn.textContent='Making your stickers...';} try{const z=await buildStickerZip();const url=URL.createObjectURL(z.blob);const a=document.createElement('a');a.href=url;a.download='pela-gardens-sticker-pack.zip';a.style.display='none';document.body.appendChild(a);a.click(); setTimeout(()=>{a.remove();URL.revokeObjectURL(url);},60000);toast('Sticker pack downloaded!','good');AU.coin&&AU.coin();if(btn){btn.innerHTML='Download again';}} catch(e){toast('Download failed. Right-click or long-press a sticker to save it.','bad');if(btn)btn.innerHTML=lbl;} finally{stkBusy=false;if(btn)btn.classList.remove('off');}} function openStickerReward(first){const h=`<div class="stk">${first?`<div class="stkWin">You did it! Pela Gardens is now the best farm in the village.<br>Everyone loves your fruit and rice. You can keep farming as long as you like.</div>`:''} <div class="stkTitle">You unlocked the free Pela Gardens sticker pack!</div> <div class="stkGrid">${ownedStickers().map(s=>`<img alt="${s.name}" title="${s.name}" data-stk="${s.id}">`).join('')}</div> <div class="stkInfo">${ownedStickers().length} stickers · PNG + WebP · WhatsApp sticker friendly</div> <div class="stkBtns"><button class="btn orange" id="stkDl">Download sticker pack</button><button class="btn" onclick="closeModal()">Keep farming</button></div> <div class="stkTip">Tip: you can also right-click or long-press a sticker to save it.</div></div>`; openModal(first?'Farm Master!':'Sticker Pack',h,null,'stickers');$('#stkDl').onclick=e=>downloadStickers(e.currentTarget); const imgs=[...document.querySelectorAll('img[data-stk]')];let k=0;(function next(){if(k>=imgs.length||!imgs[k].isConnected)return;const im=imgs[k++];im.src=stkUrl(im.dataset.stk);setTimeout(next,0);})();} function journalStickerRow(){return albumRow()+journalStickerRow0();} function albumRow(){const got=LEVEL_STK.filter(q=>S.level>=q[0]).length;return `<div class="srow stkRow"><div class="grow"><b>Sticker Album</b><br><span class="stkSub">${got} / ${LEVEL_STK.length} level stickers collected</span></div><button class="btn orange" id="jAlb">Sticker Album</button></div>`;} function journalStickerRow0(){if(S.won)return `<div class="srow stkRow"><canvas class="stkIco" width="96" height="96" data-stkico="1"></canvas><div class="grow"><b>Free sticker pack unlocked!</b><br><span class="stkSub">${ownedStickers().length} Pela Gardens stickers to download and share</span></div><button class="btn orange" id="jStk">Sticker pack</button></div>`; return `<div class="srow stkRow lock"><div class="stkLockWrap"><canvas class="stkIco" width="96" height="96" data-stkico="1"></canvas><svg viewBox="0 0 24 24" width="44" height="44"><rect x="5" y="10" width="14" height="11" rx="3" fill="#a07850"/><path d="M8 10V7a4 4 0 018 0v3" stroke="#a07850" stroke-width="3" fill="none"/></svg></div><div class="grow"><b>Free sticker pack (locked)</b><br><span class="stkSub">Become Farm Master to unlock a free sticker pack<br>Level ${Math.min(S.level,15)}/15 · Plots ${S.unlocked}/24 · Orders ${Math.min(S.ordersDone,30)}/30</span></div></div>`;} function journalStickerBind(){const ab=$('#jAlb');if(ab)ab.onclick=()=>openStickerAlbum();const cv=document.querySelector('canvas[data-stkico]');if(cv){const c=cv.getContext('2d');c.imageSmoothingQuality='high';{const im=new Image();im.onload=()=>c.drawImage(im,0,0,96,96);im.src=stkUrl('pela_gardens_logo');}} const b=$('#jStk');if(b)b.onclick=()=>openStickerReward(false);} /* ================= v1.2: the farmer, the market stall, the order board, day summary ================= */ /* The farmer lives in field units: x = columns from F.x, y = rows from F.y (so the layout can resize freely). */ const FM={x:0.7,y:-0.15,dir:1,walk:0,act:0,actK:'',q:[],keys:{},moving:false,hello:0}; const FM_SPEED=5.2; // tiles per second function fmPx(x,y){return{x:F.x+x*F.tw,y:F.y+y*F.th};} function fmBounds(){return{x0:-0.35,x1:COLS+0.35,y0:-0.22,y1:ROWS+0.1};} function anchorsPx(){ if(!PORTRAIT)return{stall:{x:F.x+F.tw*COLS-118,y:F.y-18,s:0.62},board:{x:F.x+F.tw*COLS*0.5+20,y:F.y-18,s:0.62}}; return{stall:{x:W*0.25,y:F.y-26,s:0.72},board:{x:W*0.5,y:F.y-26,s:0.66}};} function anchorStand(k){const a=anchorsPx()[k];return{x:(a.x-F.x)/F.tw+(k==='stall'?-0.05:0),y:-0.08};} function boardSpot(){const a=anchorsPx().board;return{x:a.x,y:a.y-90*a.s};} function anchorAt(x,y){const A=anchorsPx();for(const k of ['stall','board']){const a=A[k];if(Math.abs(x-a.x)<120*a.s*1.25&&y<a.y+26&&y>a.y-230*a.s)return k;}return null;} function plotStand(i){const o=CELLS[i];return{x:o.c+0.5,y:o.r+0.93};} /* Tasks: walk somewhere, then run cb. Plot taps queue up (drag across plots = a little work route). */ function farmerTask(x,y,cb,key,front){if(key&&FM.q.some(q=>q.key===key))return;const t={x,y,cb,key};if(front)FM.q.unshift(t);else FM.q.push(t);if(FM.q.length>14)FM.q.length=14;} function farmerGo(target,cb){let p;if(target==='stall'||target==='board')p=anchorStand(target);else if(typeof target==='number')p=plotStand(target);else p=target; FM.q=FM.q.filter(q=>q.key&&q.key.startsWith('p'));farmerTask(p.x,p.y,cb,'a'+target,false);} function farmerTapPlot(i,grp){const p=plotStand(i);farmerTask(p.x,p.y,()=>{const lock=grp?grp.first?(grp.lock||'none'):null:null;const r=interact(i,lock);if(grp&&!grp.first){grp.first=true;grp.lock=r;}if(r){FM.act=0.45;FM.actK=r;}},'p'+i);} function farmerWalkTo(x,y){const b=fmBounds();FM.q=[];farmerTask(clamp(x,b.x0,b.x1),clamp(y,b.y0,b.y1),null,'w');} function farmerNear(){ // what is the farmer standing next to? -> plot index, 'stall', 'board' or -1 const st=anchorStand('stall'),bd=anchorStand('board');if(Math.hypot(FM.x-st.x,(FM.y-st.y)*0.66)<0.7)return 'stall';if(Math.hypot(FM.x-bd.x,(FM.y-bd.y)*0.66)<0.7)return 'board'; let best=-1,bd2=0.75;for(let i=0;i<=Math.min(S.unlocked,MAXPLOTS-1);i++){const o=CELLS[i];if(!o)continue;const d=Math.hypot(FM.x-(o.c+0.5),(FM.y-(o.r+0.62))*0.66);if(d<bd2){bd2=d;best=i;}}return best;} function farmerUse(rep){const n=farmerNear();if(n==='stall'){openMarket();return;}if(n==='board'){openOrdersPanel();return;} if(n>=0){const r=interact(n,rep?'harvest':null);if(r){FM.act=0.45;FM.actK=r;}return;} const i=plotAtPlant(mouse.x,mouse.y);if(i>=0&&i<S.unlocked)farmerTapPlot(i,null);} function farmerUpdate(dt){if(!S)return;if(FM.act>0)FM.act=Math.max(0,FM.act-dt);if(FM.hello>0)FM.hello-=dt; const k=FM.keys;let vx=(k.right?1:0)-(k.left?1:0),vy=(k.down?1:0)-(k.up?1:0);FM.moving=false; if(VIEW!=='farm'||titleOn||modalOn){vx=vy=0;} if(vx||vy){FM.q=[];const l=Math.hypot(vx,vy);const sp=FM_SPEED*dt;const b=fmBounds();FM.x=clamp(FM.x+vx/l*sp,b.x0,b.x1);FM.y=clamp(FM.y+vy/l*sp/0.66,b.y0,b.y1);if(vx)FM.dir=vx>0?1:-1;FM.moving=true;} else if(FM.q.length&&!modalOn){const q=FM.q[0];const dx=(q.x-FM.x)*F.tw,dy=(q.y-FM.y)*F.th,d=Math.hypot(dx,dy),sp=FM_SPEED*F.tw*dt; if(d<=sp||d<2){FM.x=q.x;FM.y=q.y;FM.q.shift();if(q.cb)q.cb();}else{FM.x+=dx/d*sp/F.tw;FM.y+=dy/d*sp/F.th;if(Math.abs(dx)>3)FM.dir=dx>0?1:-1;FM.moving=true;}} if(FM.moving)FM.walk+=dt*11;else FM.walk=0;S.farmer={x:Math.round(FM.x*100)/100,y:Math.round(FM.y*100)/100};} /* ---------- art ---------- */ function drawFarmer(c,x,y,s,t){const w=FM.walk,step=Math.sin(w),bob=FM.moving?Math.abs(Math.cos(w))*6*s:Math.sin(t*2.2)*1.5*s;const act=FM.act>0?Math.sin((0.45-FM.act)/0.45*Math.PI):0; c.save();c.translate(x,y);c.fillStyle='rgba(40,20,5,0.28)';c.beginPath();c.ellipse(0,0,34*s,10*s,0,0,TAU);c.fill();c.scale(FM.dir,1); const O='#4a2a12';c.lineJoin='round';c.lineCap='round';c.lineWidth=4*s;c.strokeStyle=O; // legs + boots [[-1,step],[1,-step]].forEach(([sd,ph])=>{const lx=sd*10*s+ph*7*s,ly=-6*s-Math.max(0,ph)*5*s;c.fillStyle='#3b6fc4';roundRect(c,lx-7*s,-38*s-bob,14*s,30*s+(ly+6*s),5*s);c.fill();c.stroke(); c.fillStyle='#7a4a24';roundRect(c,lx-9*s,ly-6*s,20*s,10*s,4*s);c.fill();c.stroke();}); c.translate(0,-bob-act*6*s);c.rotate(act*0.18); // back arm c.fillStyle='#e9573f';roundRect(c,-26*s,-78*s+step*3*s,12*s,30*s,6*s);c.fill();c.stroke(); // body: red shirt + blue overalls c.fillStyle='#e9573f';roundRect(c,-22*s,-84*s,44*s,46*s,14*s);c.fill();c.stroke(); c.fillStyle='#3f86e0';roundRect(c,-19*s,-62*s,38*s,28*s,8*s);c.fill();c.stroke();c.fillRect(-12*s,-74*s,24*s,14*s); c.strokeStyle='#2c5ea8';c.beginPath();c.moveTo(-14*s,-82*s);c.lineTo(-10*s,-66*s);c.moveTo(14*s,-82*s);c.lineTo(10*s,-66*s);c.stroke();c.strokeStyle=O; c.fillStyle='#ffd84a';c.beginPath();c.arc(-9*s,-66*s,3*s,0,TAU);c.arc(9*s,-66*s,3*s,0,TAU);c.fill(); // front arm + tool c.save();c.translate(18*s,-78*s);c.rotate(-0.35-step*0.4*(FM.moving?1:0)-act*1.1);c.fillStyle='#e9573f';roundRect(c,-6*s,0,12*s,26*s,6*s);c.fill();c.stroke(); c.fillStyle='#f2b48a';c.beginPath();c.arc(0,28*s,6*s,0,TAU);c.fill();c.stroke(); if(FM.actK==='water'&&FM.act>0){c.translate(4*s,30*s);c.fillStyle='#5ab0ec';roundRect(c,-2*s,-8*s,26*s,18*s,5*s);c.fill();c.stroke();c.beginPath();c.moveTo(22*s,-2*s);c.lineTo(36*s,-10*s);c.stroke();} else if(FM.actK==='harvest'&&FM.act>0){c.translate(2*s,32*s);c.fillStyle='#d9a45a';c.beginPath();c.ellipse(8*s,0,16*s,9*s,0,0,Math.PI);c.fill();c.stroke();} c.restore(); // head c.fillStyle='#f2b48a';c.beginPath();c.ellipse(0,-104*s,21*s,22*s,0,0,TAU);c.fill();c.stroke(); c.fillStyle='#3a2414';c.beginPath();c.ellipse(-2*s,-115*s,20*s,9*s,0,Math.PI,0);c.fill(); c.fillStyle='#2a1a10';c.beginPath();c.ellipse(7*s,-104*s,3*s,4*s,0,0,TAU);c.ellipse(-6*s,-104*s,3*s,4*s,0,0,TAU);c.fill(); c.fillStyle='rgba(255,110,110,0.45)';c.beginPath();c.arc(12*s,-96*s,5*s,0,TAU);c.arc(-11*s,-96*s,5*s,0,TAU);c.fill(); c.strokeStyle='#7a2a1a';c.lineWidth=3*s;c.beginPath();c.arc(1*s,-97*s,6*s,0.25,Math.PI-0.25);c.stroke();c.strokeStyle=O;c.lineWidth=4*s; // straw hat c.fillStyle='#ffd65a';c.beginPath();c.ellipse(0,-118*s,36*s,9*s,0,0,TAU);c.fill();c.stroke(); c.beginPath();c.moveTo(-18*s,-118*s);c.quadraticCurveTo(-17*s,-142*s,0,-142*s);c.quadraticCurveTo(17*s,-142*s,18*s,-118*s);c.closePath();c.fill();c.stroke(); c.fillStyle='#e9573f';c.fillRect(-17*s,-127*s,34*s,7*s); c.restore();} function drawMarketStall(c,a,t,glow){const s=a.s;c.save();c.translate(a.x,a.y);c.scale(s,s);c.lineJoin='round'; c.fillStyle='rgba(40,20,5,0.22)';c.beginPath();c.ellipse(0,4,135,16,0,0,TAU);c.fill(); c.fillStyle='#8a5a30';c.fillRect(-104,-150,12,150);c.fillRect(92,-150,12,150); c.fillStyle='#c98a4a';roundRect(c,-115,-62,230,62,8);c.fill();c.strokeStyle='#7a4a24';c.lineWidth=5;roundRect(c,-115,-62,230,62,8);c.stroke(); c.strokeStyle='rgba(122,74,36,0.5)';c.lineWidth=3;c.beginPath();c.moveTo(-115,-40);c.lineTo(115,-40);c.moveTo(-115,-20);c.lineTo(115,-20);c.stroke(); // produce on the counter const show=[...CROPS,...PRODS].filter(q=>(S.produce[q.id]||0)>0).slice(0,4);const ids=show.length?show.map(q=>q.id):['tomato','chili','corn'].filter(id=>ICON[id]); ids.forEach((id,k)=>{const n=ids.length;const x=-80+k*(160/Math.max(1,n-1||1));c.drawImage(ICON[id],(n===1?0:x)-30,-104,60,60);}); // striped awning for(let k=0;k<8;k++){c.fillStyle=k%2?'#fff4dc':'#ff6b4a';c.beginPath();c.moveTo(-125+k*31.25,-185);c.lineTo(-125+(k+1)*31.25,-185);c.lineTo(-125+(k+1)*31.25,-150);c.quadraticCurveTo(-125+(k+0.5)*31.25,-138,-125+k*31.25,-150);c.closePath();c.fill();} c.strokeStyle='#8a4a1a';c.lineWidth=4;c.strokeRect(-125,-185,250,35); snowCap(c,[[-125,-186],[125,-186]],18,SEAV.snow); // sign c.fillStyle='#fff4dc';roundRect(c,-70,-226,140,40,12);c.fill();c.strokeStyle='#8a4a1a';c.lineWidth=4;roundRect(c,-70,-226,140,40,12);c.stroke(); c.fillStyle='#8a4a1a';c.font='700 27px Fredoka';c.textAlign='center';c.textBaseline='middle';c.fillText('MARKET',0,-205); c.restore(); if(glow){const b=Math.abs(Math.sin(t*3))*8;drawCoin(c,a.x+92*s,a.y-250*s-b,20);}} function drawBoard(c,a,t,ready){const s=a.s;c.save();c.translate(a.x,a.y);c.scale(s,s);c.lineJoin='round'; c.fillStyle='rgba(40,20,5,0.22)';c.beginPath();c.ellipse(0,4,90,12,0,0,TAU);c.fill(); c.fillStyle='#8a5a30';c.fillRect(-70,-150,12,152);c.fillRect(58,-150,12,152); c.fillStyle='#c98a4a';roundRect(c,-88,-190,176,110,10);c.fill();c.strokeStyle='#7a4a24';c.lineWidth=5;roundRect(c,-88,-190,176,110,10);c.stroke(); c.fillStyle='#a8683a';c.beginPath();c.moveTo(-100,-188);c.lineTo(0,-226);c.lineTo(100,-188);c.closePath();c.fill();c.stroke();snowCap(c,[[-100,-190],[0,-228],[100,-190]],16,SEAV.snow); const n=Math.min(4,S.orders.filter(o=>!o.empty).length);for(let k=0;k<n;k++){const x=-66+k*36+((k%2)*4),y=-176+(k%2)*10;c.save();c.translate(x+16,y+30);c.rotate((k%2?1:-1)*0.07);c.fillStyle='#fffaf0';c.fillRect(-16,-28,32,54);c.fillStyle='#e9573f';c.beginPath();c.arc(0,-24,4,0,TAU);c.fill();c.fillStyle='rgba(120,80,40,0.5)';for(let l=0;l<3;l++)c.fillRect(-10,-12+l*10,20,3);c.restore();} c.fillStyle='#fff4dc';roundRect(c,-62,-80,124,30,10);c.fill();c.fillStyle='#8a4a1a';c.font='700 21px Fredoka';c.textAlign='center';c.textBaseline='middle';c.fillText('ORDERS',0,-64); if(ready){const b=Math.abs(Math.sin(t*4))*8;c.fillStyle='#ffe14a';c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.arc(0,-262-b,ready>1?30:24,0,TAU);c.fill();c.stroke();c.fillStyle='#8a4a00';c.font='700 32px Fredoka';c.fillText(ready>1?'!'+ready:'!',0,-260-b);c.globalAlpha=0.25+0.2*Math.sin(t*4);c.strokeStyle='#ffe14a';c.lineWidth=10;roundRect(c,-92,-194,184,118,14);c.stroke();c.globalAlpha=1;} c.restore();} function drawAnchors(c,t){const A=anchorsPx();const sellable=[...CROPS,...PRODS].some(q=>(S.produce[q.id]||0)>0);drawMarketStall(c,A.stall,t,sellable);drawBoard(c,A.board,t,S.orders.filter(o=>canFill(o)).length);} function drawFarmerNow(c,t){const p=fmPx(FM.x,FM.y);const s=F.tw/200*(PORTRAIT?0.95:1.05); // queued plot markers FM.q.forEach((q,k)=>{if(!q.key||q.key[0]!=='p')return;const i=+q.key.slice(1),R=plotRect(i);c.strokeStyle=`rgba(255,255,255,${0.55+0.3*Math.sin(t*6+k)})`;c.lineWidth=4;c.setLineDash([8,8]);roundRect(c,R.x+10,R.y+10,R.w-20,R.h-20,12);c.stroke();c.setLineDash([]);}); drawFarmer(c,p.x,p.y,s,t); if(FM.hello>0){c.globalAlpha=Math.min(1,FM.hello);pill(c,p.x,p.y-170*s,190,40,'#fff','#ffb92e');c.fillStyle='#8a4a00';c.font='700 24px Fredoka';c.textAlign='center';c.textBaseline='middle';c.fillText('This is you!',p.x,p.y-169*s);c.globalAlpha=1;}} /* ---------- Market ---------- */ function openMarket(){const d=dayNum(T_()),hot=hotCrop(T_(),S.level);mktDay(); const have=[...CROPS,...PRODS].filter(c=>(S.produce[c.id]||0)>0); const arrow=id=>{const tr=priceTrend(id);return tr>0?`<b style="color:#3a9a2a">▲ ${tr}</b>`:tr<0?`<b style="color:#d0402a">▼ ${-tr}</b>`:'<b style="color:#a07850">=</b>';}; const val=id=>{let v=0;for(let k=0;k<S.produce[id];k++)v+=sellPrice(id,0,k);return v;};const total=have.reduce((a,c)=>a+val(c.id),0); const board=CROPS.filter(c=>c.lvl<=S.level).map(c=>`<div class="mprice"><img src="${ICON[c.id+'_url']}"><b>${sellPrice(c.id)}</b>${arrow(c.id)}</div>`).join(''); const h=`<div class="srow" style="background:#ffe9d6"><img src="${ICON[hot.id+'_url']}"><div class="grow"><b>Day ${d} market · Hot crop: ${hot.name} (1.6x)</b><br><span style="font-size:20px;color:#a07850">Prices change every morning at 6 AM. Selling lots of one item today lowers its price a little.</span></div></div> <div class="mboard">${board}</div>`+ (have.length?have.map(c=>`<div class="srow"><img src="${ICON[c.id+'_url']}"><div class="grow"><b>${c.name}</b> × ${S.produce[c.id]}<br><span style="font-size:20px;color:#a07850">${sellPrice(c.id)} coins each today ${arrow(c.id)}${(mktDay().sold[c.id]||0)?` · sold ${mktDay().sold[c.id]} today`:''}</span></div><button class="btn orange" data-msell="${c.id}" data-n="1">Sell 1</button><button class="btn" data-msell="${c.id}" data-n="999">Sell all ${cost(val(c.id))}</button></div>`).join('')+ `<div style="text-align:center;margin-top:16px"><button class="btn" id="mSellAll" style="font-size:32px">Sell everything ${cost(total)}</button><p class="mtext" style="font-size:20px;color:#a07850">Tip: neighbor orders usually pay more than the market!</p></div>` :'<p class="mtext">Your basket is empty. Harvest crops or collect animal goods first!</p>'); const again=modalOn&&modalKind==='market';openModal('Market Stall',h,null,'market');if(again){const m=$('#modal');m.style.animation='none';} $('#mBody').querySelectorAll('[data-msell]').forEach(b=>b.onclick=()=>{sell(b.dataset.msell,+b.dataset.n,b);openMarket();}); const sa=$('#mSellAll');if(sa)sa.onclick=()=>{[...CROPS,...PRODS].forEach(c=>{if(S.produce[c.id]>0)sell(c.id,999,sa);});openMarket();};tutEvent('market');} function goMarket(){if(modalOn)closeModal();if(VIEW!=='farm')setView('farm');farmerGo('stall',openMarket);} function openOrdersPanel(){if(PORTRAIT){$('#orders').classList.add('open');tutRefresh();}else{const o=$('#orders');o.classList.remove('bump');void o.offsetWidth;o.classList.add('bump');}} /* ---------- Day cycle: end-of-day summary ---------- */ let pendingDay=null,_ordImg=null; function ORDIMG(){if(_ordImg)return _ordImg;const cv=makeCanvas(64,64),c=cv.getContext('2d');c.fillStyle='#fff4dc';c.strokeStyle='#8a4a1a';c.lineWidth=4;roundRect(c,12,8,40,50,6);c.fill();c.stroke();c.fillStyle='#c97a3a';roundRect(c,22,4,20,10,3);c.fill();c.stroke();c.strokeStyle='#8a4a1a';c.lineCap='round';[24,34,44].forEach(y=>{c.beginPath();c.moveTo(20,y);c.lineTo(44,y);c.stroke();});return _ordImg=cv.toDataURL();} function dayTick(){if(!S)return;const T=T_(),d=dayNum(T);if(!S.today||typeof S.today.day!=='number'){S.today=newToday(T);return;} if(d!==S.today.day){const prev=S.today;S.today=newToday(T);S.stats.days=(S.stats.days||0)+1;if(!titleOn&&d-prev.day===1&&(prev.harv||prev.coins||prev.orders||prev.goods||prev.sold))pendingDay=prev;buildHotbar();} if(pendingDay&&!modalOn&&!titleOn&&VIEW!=='x'){const p=pendingDay;pendingDay=null;showDaySummary(p);}} function showDaySummary(p){const T=T_(),d=dayNum(T),start=(d-1)*DAY;const se=seasonAt(start+DAY*0.5),hot=hotCrop(start+1,S.level); let rainN=0;for(let k=0;k<6;k++)if(rainAt(start+DAY*k/6))rainN++;const wx=rainN>=2?(se==='winter'?'Snowy':'Rainy'):rainN?'Showers':'Sunny'; const un=CROPS.filter(c=>c.lvl<=S.level);const best=un.reduce((b,c)=>dayMul(c.id,d)>dayMul(b.id,d)?c:b,un[0]); const stars=p.coins>=120+S.level*40?3:p.coins>=40+S.level*15?2:1; const st=(ico,label,v)=>`<div class="dstat">${ico?`<img src="${ico}">`:''}<span>${label}</span><b>${v}</b></div>`; openModal(`Day ${p.day} Complete!`,`<div style="text-align:center"><div class="dstars">${[0,1,2].map(k=>`<span class="${k<stars?'on':''}">★</span>`).join('')}</div> <div class="dgrid">${st(ICON.chili_url,'Crops harvested',p.harv)}${st(ICON.corn_url,'Items sold',p.sold)}${st(PACK.a_chicken,'Animal goods',p.goods)}${st(ORDIMG(),'Orders delivered',p.orders)}${st(COINIMG.toDataURL(),'Coins earned','+'+fmt(p.coins))}${st(STARIMG.toDataURL(),'XP gained','+'+fmt(p.xp))}</div> ${p.wilted?`<p class="mtext" style="color:#c0502a">${p.wilted} crop${p.wilted>1?'s':''} wilted from thirst. Water them to revive!</p>`:''} <div class="srow" style="background:#e6f6ff;text-align:left"><div class="grow"><b>Tomorrow: Day ${d}</b> · ${SEA[se].name} · ${wx}<br><span style="font-size:21px;color:#5a7890">Hot crop: <b>${hot.name}</b> (1.6x) · Best market price: <b>${best.name}</b></span></div></div> <button class="btn" id="dNext" style="font-size:34px;margin-top:14px">Start Day ${d}</button></div>`,null,'day'); spawn('confetti',0,0,{n:50});AU.level();$('#dNext').onclick=closeModal;} /* ---------- What's new (for players coming from v1.1) ---------- */ function whatsNew(){if(!S||!S.whatsNew||titleOn||modalOn||welcome)return;S.whatsNew=0; openModal('New in v1.2!',`<div class="gma"><canvas id="gmaAva" width="160" height="160"></canvas><div class="mtext" style="text-align:left;font-size:24px"><b>Grandma:</b> "Look, child, your farm has grown! Your crops, coins and animals are all here."</div></div> <ul class="mtext wnew" style="text-align:left;font-size:23px"><li><b>Meet your farmer!</b> Tap a plot and they walk over to do the work. Desktop: WASD / arrows + Space.</li><li><b>Crop care:</b> water often or crops wilt. Manure (Fertilizer) now gives bigger harvests.</li><li><b>Market stall</b> with prices that change every day.</li><li><b>Happy animals</b> make more. Feed and pet them!</li><li><b>Orders</b> have due dates, with a bonus for same-day delivery.</li><li>A <b>summary</b> at the end of every day.</li></ul> <div style="text-align:center"><button class="btn" onclick="closeModal()" style="font-size:32px">Let's farm!</button></div>`,null,'whatsnew');drawAvatar($('#gmaAva'),7,NAMES.indexOf('Grandma'));} /* ---------- DPR watch: keep the canvas crisp when moving between screens or zooming ---------- */ let lastDPR=window.devicePixelRatio||1; function dprWatch(){const d=window.devicePixelRatio||1;if(d!==lastDPR){lastDPR=d;resize();}} /* ---------- Order Complete pop-up (queued, auto-closes, tap to dismiss) ---------- */ const ORDPOP={q:[],on:false,timer:null};const THANKS=['Thank you so much!','You saved my dinner!','Fresh and perfect. Thanks!','My family will love this!','Best farm in the village!']; function queueOrderPop(info){ORDPOP.q.push(info);if(!ORDPOP.on)nextOrderPop();} function nextOrderPop(){const info=ORDPOP.q.shift();const old=$('#ordPop');if(old)old.remove();if(!info){ORDPOP.on=false;return;}ORDPOP.on=true; const d=document.createElement('div');d.id='ordPop';d.innerHTML=`<div class="opcard"><div class="optitle">Order Complete!</div><div class="ophead"><canvas width="160" height="160"></canvas><div><b>${NAMES[info.who]}</b><div class="opthx">"${THANKS[info.ava%THANKS.length]}"</div></div></div> <div class="opitems">${info.items.map(it=>`<span><img src="${ICON[it.c+'_url']}">×${it.n}</span>`).join('')}</div> <div class="oprew"><span class="price"><span class="coinIco sm"></span><b>+${fmt(info.coins)}</b></span><span class="opxp">+${info.xp} XP</span>${info.seed?`<span><img src="${PACK[info.seed.c]}" style="width:40px">×${info.seed.n}</span>`:''}</div>${info.same?'<div class="opbonus">Same-day bonus +20%</div>':''}<div class="optap">Tap to continue</div></div>`; stage.appendChild(d);drawAvatar(d.querySelector('canvas'),info.ava,info.who);spawn('confetti',0,0,{n:70});try{AU.deliver();setTimeout(()=>AU.coin(),250);}catch(e){} const close=()=>{if(d._c)return;d._c=1;clearTimeout(ORDPOP.timer);d.classList.add('out');setTimeout(nextOrderPop,260);};d.addEventListener('pointerdown',e=>{e.stopPropagation();close();});ORDPOP.timer=setTimeout(close,2500);} (function(){const t=()=>document.documentElement.classList.add('touch');if(window.matchMedia&&matchMedia('(pointer:coarse)').matches)t();window.addEventListener('touchstart',t,{once:true,passive:true});})(); document.fonts&&document.fonts.load('600 20px Fredoka').finally(init);if(!document.fonts)init(); </script></body></html>