PageSourceSearch

https://egorod.online/js/chunks/garden.d77f8be10491.bundle.js

js egorod.online collected 2026-10-06 07:04:11 UTC 128,181 bytes, 265 lines download raw bytes

1const GardenPage={state:null,_cleanup:[],_joined:!1,_raf:null,_flash:{},_geom:null,_hover:-1,_introAt:0,_chatId:null,_chatBound:!1,_cd:{plant:0,water:0,harvest:0},_penCd:0,_penRenderAt:0,_penBound:!1,_penReactions:{},_penReactionTimers:{},_cdTimer:null,_accountTimer:null,_sceneClockTimer:null,_accountRefreshTimer:null,_leaderboard:[],_leaderboardMe:null,_limits:null,_limitsTickAt:0,_scoreFormat:"compact",_limitReleaseRefreshAt:0,_civicStatus:null,_civicCeremony:null,_civicCeremonyTimer:null,_timeOffset:0,_cropArtCache:null,_cropTransitions:{},_waterEffects:{},_waterEffectTimers:{},CROP_EMOJI:["\u{1F955}","\u{1F33F}","\u{1F336}\uFE0F","\u{1F96C}","\u{1F954}","\u{1F345}","\u{1F952}","\u{1F33D}","\u{1F9C5}","\u{1F346}"],CROP_ART:["/img/garden-crops/carrot-imagegen.webp","/img/garden-crops/herb-imagegen.webp","/img/garden-crops/radish-imagegen.webp","/img/garden-crops/cabbage-imagegen.webp","/img/garden-crops/potato-imagegen.webp","/img/garden-crops/tomato-imagegen.webp","/img/garden-crops/cucumber-imagegen.webp","/img/garden-crops/corn-imagegen.webp","/img/garden-crops/onion-imagegen.webp","/img/garden-crops/eggplant-imagegen.webp"],CROP_GROWTH_ART:["/img/garden-crops/carrot-growing-imagegen.webp","/img/garden-crops/herb-growing-imagegen.webp","/img/garden-crops/radish-growing-imagegen.webp","/img/garden-crops/cabbage-growing-imagegen.webp","/img/garden-crops/potato-growing-imagegen.webp","/img/garden-crops/tomato-growing-imagegen.webp","/img/garden-crops/cucumber-growing-imagegen.webp","/img/garden-crops/corn-growing-imagegen.webp","/img/garden-crops/onion-growing-imagegen.webp","/img/garden-crops/eggplant-growing-imagegen.webp"],WEED_ART:{single:"/img/garden-crops/weed-single-imagegen.webp",thicket:"/img/garden-crops/weed-thicket-imagegen.webp"},WET_SOIL_SECONDS:300,ANIMAL_EMOJI:["\u{1F404}","\u{1F414}","\u{1F411}","\u{1F416}","\u{1F410}"],ANIMAL_ART:["/img/garden-pen/cow.webp","/img/garden-pen/chicken.webp","/img/garden-pen/sheep.webp","/img/garden-pets/piglet-linen.webp","/img/garden-pets/goat-linen.webp"],ACTION_WORD:{plant:"\u0437\u0430\u0441\u0435\u044F\u043B \u043D\u0430\u0434\u0435\u043B",water:"\u043F\u043E\u043B\u0438\u043B",harvest:"\u0441\u043D\u044F\u043B \u0443\u0440\u043E\u0436\u0430\u0439",weed:"\u043F\u0440\u043E\u043F\u043E\u043B\u043E\u043B",feed:"\u043F\u043E\u043A\u043E\u0440\u043C\u0438\u043B",collect:"\u0441\u043E\u0431\u0440\u0430\u043B \u043F\u0440\u043E\u0434\u0443\u043A\u0442"},_text(key,fallback="",params={}){return typeof I18n>"u"||!I18n||typeof I18n.t!="function"?fallback:Object.keys(params).length?I18n.t(key,fallback,params):I18n.t(key,fallback)},actionWord(action){const fallback=this.ACTION_WORD[action]||"";return this._text(`garden.action_${action}`,fallback)},_errorMessage(error,fallbackKey="garden.action_failed",fallback="\u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043E\u0442\u043A\u043B\u043E\u043D\u0438\u043B\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435."){const data=error&&typeof error=="object"&&error.data&&typeof error.data=="object"?error.data:{},codes=[error&&typeof error=="object"?error.code:null,data.code,data.error_code,error&&typeof error=="object"&&typeof error.error=="string"?error.error:null,error&&typeof error=="object"&&typeof error.message=="string"?error.message:null,typeof data.error=="string"?data.error:null].filter(code=>/^[A-Za-z0-9_.-]+$/.test(String(code||""))),params=data.params&&typeof data.params=="object"?data.params:error&&error.params&&typeof error.params=="object"?error.params:{};for(const code of codes){const key=`errors.${String(code).toLowerCase()}`;if(typeof I18n<"u"&&I18n&&typeof I18n.has=="function"&&I18n.has(key))return this._text(key,fallback,params)}const raw=typeof error=="string"?error:error&&typeof error=="object"?error.message||error.error||data.message||data.error:"";return raw&&!(typeof I18n<"u"&&I18n&&I18n.locale==="en"&&/[\u0400-\u04ff]/i.test(String(raw)))?String(raw):this._text(fallbackKey,fallback)},_seasonResetAnnouncement(announce){if(!announce||typeof announce!="string")return"";if(typeof I18n>"u"||!I18n||I18n.locale!=="en"||!/[\u0400-\u04ff]/u.test(announce))return announce;const match=/^Сезон\s+(\S+)\s+закрыт\.\s+Учреждён\s+Сезон\s+(\S+)\s+—\s+План\s+(\d+)\s+ц\.\s+Грядка\s+перепахана\.$/.exec(announce);return match?this._text("garden.season_reset_announce","Season {closed} closed. Season {next} established \u2014 plan {target} cwt. The garden has been re-plowed.",{closed:match[1],next:match[2],target:match[3]}):this._text("garden.season_reset_generic","A new garden season has been established. The garden has been re-plowed.",{})},async render(){Utils.setTitle(I18n.t("garden.title","\u041E\u0433\u043E\u0440\u043E\u0434")),this.cleanup(),this._introAt=performance.now();try{this._scoreFormat=localStorage.getItem("garden_score_format")==="exact"?"exact":"compact"}catch{this._scoreFormat="compact"}if(document.getElementById("content").innerHTML=`
2      <div class="garden-page">
3        <!-- \u0413\u0435\u0440\u043E\u0439-\u0443\u043A\u0430\u0437 \u043A\u0430\u043A \u0432 \u043F\u0440\u043E\u0442\u043E\u0442\u0438\u043F\u0435 (.card.garden-board): \u043A\u0438\u043A\u0435\u0440 \u2192 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0441
4             \u043F\u043E\u0434\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u043C \u0438 \u043F\u0438\u043B\u044E\u043B\u044F\u043C\u0438 \u0441\u0435\u0437\u043E\u043D\u0430/\u043F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044F \u2192 \u041F\u043B\u0430\u043D \u043F\u043E \u0423\u0440\u043E\u0436\u0430\u044E \u0441 \u043F\u043E\u043B\u043E\u0441\u043E\u0439. -->
5        <header class="gc-hero gc-hero--garden garden-hero">
6          <div class="gc-kicker">${I18n.t("garden.decree_kicker","\u0423\u043A\u0430\u0437 \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u0438 \xB7 \u043E\u0442\u0434\u0435\u043B \u0437\u0435\u043C\u043B\u0435\u0434\u0435\u043B\u0438\u044F")}</div>
7          <div class="gc-page-head">
8            <div>
9              <h1 class="gc-h1">${I18n.t("garden.public_garden","\u041E\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0439 \u041E\u0433\u043E\u0440\u043E\u0434")}</h1>
10              <p class="gc-page-sub">${I18n.t("garden.decree_sub","\u0413\u043E\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043D\u043D\u0430\u044F \u0433\u0440\u044F\u0434\u043A\u0430 \u0432 \u043E\u0431\u0449\u0435\u043C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0438 \u0433\u0440\u0430\u0436\u0434\u0430\u043D. \u0412\u043E\u0437\u0434\u0435\u043B\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u0441\u043E\u043E\u0431\u0449\u0430: \u0441\u0430\u0436\u0430\u0439\u0442\u0435, \u043F\u043E\u043B\u0438\u0432\u0430\u0439\u0442\u0435 \u0447\u0443\u0436\u0438\u0435 \u0432\u0441\u0445\u043E\u0434\u044B, \u0441\u043D\u0438\u043C\u0430\u0439\u0442\u0435 \u043F\u043E\u0441\u043F\u0435\u0432\u0448\u0438\u0439 \u0443\u0440\u043E\u0436\u0430\u0439 \u0438 \u0432\u044B\u043F\u0430\u043B\u044B\u0432\u0430\u0439\u0442\u0435 \u0431\u0443\u0440\u044C\u044F\u043D \u2014 \u0432\u043E \u0441\u043B\u0430\u0432\u0443 \u041F\u043B\u0430\u043D\u0430 \u043F\u043E \u0423\u0440\u043E\u0436\u0430\u044E \u043E\u0431\u043B\u0430\u0441\u0442\u0438.")}</p>
11            </div>
12            <div class="garden-decree-meta">
13              <span class="garden-chip garden-chip--live" id="garden-presence" aria-live="polite">${I18n.t("garden.presence_loading","\u2014 \u043D\u0430 \u0433\u0440\u044F\u0434\u043A\u0435")}</span>
14              <span class="garden-chip garden-chip--mono" id="garden-season-chip">${I18n.t("garden.season_chip",{season:"I"})}</span>
15            </div>
16          </div>
17          <section class="garden-season" id="garden-season" aria-live="polite">
18            <div class="garden-spin"></div>
19          </section>
20        </header>
21
22        <!-- \u0421\u0443\u0442\u043E\u0447\u043D\u0430\u044F \u0432\u0435\u0434\u043E\u043C\u043E\u0441\u0442\u044C \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u0430 \u0432 \u041E\u0433\u043E\u0440\u043E\u0434 \u0438 \u0437\u0430\u043F\u043E\u043B\u043D\u044F\u0435\u0442\u0441\u044F \u043E\u0431\u044B\u0447\u043D\u043E\u0439 \u0438\u0433\u0440\u043E\u0439:
23             \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0433\u043E \u0434\u0435\u0439\u043B\u0438\u043A\u0430, \u0432\u0430\u043B\u044E\u0442\u044B \u0438\u043B\u0438 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0433\u043E \u044D\u043A\u0440\u0430\u043D\u0430 \u043D\u0435\u0442. -->
24        <section class="garden-civic" id="garden-civic" aria-live="polite" hidden></section>
25
26        <!-- \u0413\u0440\u044F\u0434\u043A\u0430 \u2014 \u0433\u0435\u0440\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B: \u0441\u0432\u0435\u0440\u0445\u0443, \u0432\u043E \u0432\u0441\u044E \u0448\u0438\u0440\u0438\u043D\u0443. -->
27        <section class="garden-board-wrap">
28          <div class="garden-board-plate">
29            <div class="garden-board-head">
30              <span class="garden-board-title">${I18n.t("garden.board_title","\u0413\u0440\u044F\u0434\u043A\u0430")}</span>
31              <span class="garden-cd" id="garden-cd" hidden></span>
32              <span class="garden-board-hint" id="garden-hint">${I18n.t("garden.preparing_tools","\u0413\u043E\u0442\u043E\u0432\u0438\u043C \u0438\u043D\u0432\u0435\u043D\u0442\u0430\u0440\u044C\u2026")}</span>
33            </div>
34            <div class="garden-board-frame">
35              <canvas id="garden-canvas" class="garden-canvas" aria-hidden="true"></canvas>
36            </div>
37            <!-- \u0414\u043E\u0441\u0442\u0443\u043F\u043D\u0430\u044F \u0430\u043B\u044C\u0442\u0435\u0440\u043D\u0430\u0442\u0438\u0432\u0430 canvas: \u0444\u043E\u043A\u0443\u0441\u0438\u0440\u0443\u0435\u043C\u044B\u0435 \u043A\u043D\u043E\u043F\u043A\u0438-\u043D\u0430\u0434\u0435\u043B\u044B \u0434\u043B\u044F
38                 \u043A\u043B\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044B \u0438 \u0441\u043A\u0440\u0438\u043D\u0440\u0438\u0434\u0435\u0440\u043E\u0432 (canvas \u0441\u0430\u043C \u043F\u043E \u0441\u0435\u0431\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D).
39                 Skip-link, \u0447\u0442\u043E\u0431\u044B \u043D\u0435 \u0442\u0430\u0431\u0430\u0442\u044C \u0432\u0441\u0435 \u043D\u0430\u0434\u0435\u043B\u044B \u0434\u043E \u0411\u0435\u0441\u0435\u0434\u043A\u0438. -->
40            <a href="#garden-chat-input" class="garden-sr-skip">${I18n.t("garden.skip_to_chat","\u041F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u043D\u0430\u0434\u0435\u043B\u044B \u2192 \u043A \u0411\u0435\u0441\u0435\u0434\u043A\u0435 \u0443 \u043F\u043B\u0435\u0442\u043D\u044F")}</a>
41            <div id="garden-sr" class="garden-sr" role="group" aria-label="${I18n.t("garden.grid_aria","\u0413\u0440\u044F\u0434\u043A\u0430: \u043D\u0430\u0434\u0435\u043B\u044B (\u043A\u043B\u0430\u0432\u0438\u0448\u0430\u043C\u0438 Tab/Enter; \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043F\u043E\u0434\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u0430\u043C\u0430)")}"></div>
42            <div class="garden-legend" id="garden-legend">
43              <span class="garden-legend-item"><i class="gl-soil"></i> ${I18n.t("garden.legend_free","\u0441\u0432\u043E\u0431\u043E\u0434\u043D\u044B\u0439 \u043D\u0430\u0434\u0435\u043B \u2014 <b>\u0437\u0430\u0441\u0435\u044F\u0442\u044C</b>")}</span>
44              <span class="garden-legend-item"><i class="garden-legend-art"><img src="/img/garden-crops/herb-growing-imagegen.webp" alt="" aria-hidden="true" decoding="async"></i> ${I18n.t("garden.legend_sprout","\u0432\u0441\u0445\u043E\u0434\u044B \u2014 <b>\u043F\u043E\u043B\u0438\u0442\u044C</b>")}</span>
45              <span class="garden-legend-item"><i class="garden-legend-art"><img src="/img/garden-crops/carrot-imagegen.webp" alt="" aria-hidden="true" decoding="async"></i> ${I18n.t("garden.legend_ripe","\u043F\u043E\u0441\u043F\u0435\u043B\u043E \u2014 <b>\u0441\u043E\u0431\u0440\u0430\u0442\u044C</b>")}</span>
46              <span class="garden-legend-item"><i class="garden-legend-art garden-legend-art--weed"><img src="/img/garden-crops/weed-single-imagegen.webp" alt="" aria-hidden="true" decoding="async"></i> ${I18n.t("garden.legend_weed","\u0431\u0443\u0440\u044C\u044F\u043D \u2014 <b>\u043F\u0440\u043E\u043F\u043E\u043B\u043E\u0442\u044C</b>")}</span>
47            </div>
48          </div>
49        </section>
50
51        <!-- \u0417\u0430\u0433\u043E\u043D \u043F\u0440\u0438 \u041E\u0433\u043E\u0440\u043E\u0434\u0435 \u2014 \u043E\u0431\u0449\u0438\u043D\u043D\u044B\u0439 \u0441\u043A\u043E\u0442\u043D\u044B\u0439 \u0434\u0432\u043E\u0440 (\u0442\u0430\u043C\u0430\u0433\u043E\u0447\u0438). \u0421\u043A\u0440\u044B\u0442, \u043F\u043E\u043A\u0430 \u043D\u0435 \u043F\u0440\u0438\u0434\u0451\u0442
52             \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0441 pen (\u0444\u043B\u0430\u0433 garden_pen_enabled). -->
53        <section class="garden-pen-wrap" id="garden-pen-wrap" hidden>
54          <div class="garden-board-plate">
55            <div class="garden-board-head" id="garden-pen-shared-head">
56              <span class="garden-board-title">${I18n.t("garden.pen_title","\u0417\u0430\u0433\u043E\u043D")}</span>
57              <span class="garden-board-hint">${I18n.t("garden.pen_hint","\u041A\u043E\u0440\u043C\u0438\u0442\u0435 \u0436\u0438\u0432\u043E\u0442\u043D\u044B\u0445 \u0441\u043E\u043E\u0431\u0449\u0430 \u2014 \u0441 \u043E\u0442\u043A\u043E\u0440\u043C\u0430 \u0437\u0440\u0435\u0435\u0442 \u043F\u0440\u043E\u0434\u0443\u043A\u0442 \u0432 \u043E\u0431\u0449\u0438\u0439 \u041F\u043B\u0430\u043D")}</span>
58            </div>
59            <!-- \u041B\u0438\u0447\u043D\u044B\u0439 \u043F\u043E\u0434\u043E\u043F\u0435\u0447\u043D\u044B\u0439 \u2014 \u043E\u0434\u043D\u0430 \u043A\u043E\u043C\u043F\u0430\u043A\u0442\u043D\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u0432\u043D\u0443\u0442\u0440\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0433\u043E
60                 \u0417\u0430\u0433\u043E\u043D\u0430. \u0412\u0441\u0451 \u0434\u0435\u043B\u043E/\u043A\u043E\u0440\u043C\u043B\u0435\u043D\u0438\u0435/\u0433\u0430\u0440\u0434\u0435\u0440\u043E\u0431 \u043E\u0442\u043A\u0440\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u043F\u043E\u0432\u0435\u0440\u0445 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B. -->
61            <div id="garden-pet-dock" class="garden-pet-dock-host" hidden></div>
62            <div id="garden-pet-show" class="garden-pet-show-host" hidden></div>
63            <div class="garden-pen-grid" id="garden-pen-grid"></div>
64          </div>
65        </section>
66
67        <!-- \u0414\u043E\u0441\u043A\u0430 \u043F\u043E\u0447\u0451\u0442\u0430 + \u041B\u0438\u0447\u043D\u044B\u0439 \u043B\u0438\u043C\u0438\u0442 \u2014 \u0441\u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u044B \u0441\u0440\u0430\u0437\u0443 \u043F\u043E\u0434 \u0433\u0440\u044F\u0434\u043A\u043E\u0439/\u0437\u0430\u0433\u043E\u043D\u043E\u043C (\u044D\u0442\u043E
68             \u0436\u0438\u0432\u043E\u0439 \u0441\u043E\u0446-\u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u0438 \xAB\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u043C\u043D\u0435 \u0435\u0449\u0451 \u043C\u043E\u0436\u043D\u043E\xBB), \u0432\u044B\u0448\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u043D\u043E\u0433\u043E \u0440\u0430\u0437\u044A\u044F\u0441\u043D\u0435\u043D\u0438\u044F. -->
69        <div class="garden-panel garden-leaderboard">
70          <div class="garden-panel-head garden-lb-head">
71            <span class="garden-panel-title">${Icons.render("trophy",16)} ${I18n.t("garden.honor_roll","\u0414\u043E\u0441\u043A\u0430 \u043F\u043E\u0447\u0451\u0442\u0430")}</span>
72            <div class="garden-lb-tools">
73              <span class="garden-panel-note">${I18n.t("garden.top_season",{season:"I"})}</span>
74              <div class="garden-score-switch" role="group" aria-label="${Utils.esc(I18n.t("garden.score_format","\u0424\u043E\u0440\u043C\u0430\u0442 \u0441\u0435\u0437\u043E\u043D\u043D\u044B\u0445 \u043E\u0447\u043A\u043E\u0432"))}">
75                <button type="button" data-format="compact" onclick="GardenPage.setScoreFormat('compact')" aria-label="${Utils.esc(I18n.t("garden.format_short","\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0441\u043E\u043A\u0440\u0430\u0449\u0451\u043D\u043D\u043E, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 1,1 \u0442\u044B\u0441\u044F\u0447\u0438"))}">${I18n.locale==="en"?"1.1K":"1,1\u043A"}</button>
76                <button type="button" data-format="exact" onclick="GardenPage.setScoreFormat('exact')" aria-label="${Utils.esc(I18n.t("garden.format_exact","\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0442\u043E\u0447\u043D\u043E, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 1 110"))}">1 110</button>
77              </div>
78            </div>
79          </div>
80          <div class="garden-panel-body" id="garden-leaderboard"><div class="garden-spin"></div></div>
81        </div>
82
83        <!-- \u041F\u0440\u043E\u0448\u0435\u043D\u0438\u0435 \u2116734: \xAB\u043E\u043D\u0438 \u043F\u0430\u0445\u0430\u043B\u0438, \u043D\u043E\u0432\u044B\u0439 \u0441\u0435\u0437\u043E\u043D \u0438 \u0438\u0445 \u043D\u0435\u0442\xBB. \u0412\u0435\u0434\u043E\u043C\u043E\u0441\u0442\u0438 \u043F\u0440\u043E\u0448\u043B\u044B\u0445
84             \u0441\u0435\u0437\u043E\u043D\u043E\u0432 \u043D\u0438\u043A\u0443\u0434\u0430 \u043D\u0435 \u0434\u0435\u0432\u0430\u043B\u0438\u0441\u044C \u2014 \u043D\u0435 \u0445\u0432\u0430\u0442\u0430\u043B\u043E \u043C\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043D\u0430 \u043D\u0438\u0445 \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C.
85             \u0413\u0440\u0443\u0437\u0438\u043C \u041F\u041E \u041D\u0410\u0416\u0410\u0422\u0418\u042E: \u041E\u0433\u043E\u0440\u043E\u0434 \u0438 \u0442\u0430\u043A \u0442\u044F\u0436\u0451\u043B\u044B\u0439, \u0430 \u043F\u0440\u043E\u0448\u043B\u043E\u0435 \u0441\u043C\u043E\u0442\u0440\u044F\u0442 \u0440\u0435\u0434\u043A\u043E. -->
86        <div class="garden-panel garden-past">
87          <div class="garden-panel-head">
88            <span class="garden-panel-title">${Icons.render("award",16)} ${I18n.t("garden.past_seasons","\u041F\u0440\u043E\u0448\u043B\u044B\u0435 \u0441\u0435\u0437\u043E\u043D\u044B")}</span>
89          </div>
90          <div class="garden-panel-body" id="garden-past">
91            <button type="button" class="btn btn-secondary garden-past-load" onclick="GardenPage.loadPastSeasons()">${I18n.t("garden.past_show","\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u0440\u043E\u0448\u043B\u044B\u0435 \u0441\u0435\u0437\u043E\u043D\u044B")}</button>
92          </div>
93        </div>
94
95        <!-- \u041B\u0438\u0447\u043D\u0430\u044F \u043A\u0432\u0438\u0442\u0430\u043D\u0446\u0438\u044F: \u0442\u043E\u043B\u044C\u043A\u043E \u043E\u0431\u044A\u044F\u0441\u043D\u044F\u0435\u0442 \u0443\u0436\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0435 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u0438 \u0432\u044B\u0434\u0435\u0440\u0436\u043A\u0438;
96             \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0441\u0435\u0437\u043E\u043D\u0430 \u0438 \u0430\u0432\u0442\u043E\u0440\u0438\u0442\u0435\u0442\u043D\u044B\u0435 \u0440\u0430\u0441\u0447\u0451\u0442\u044B \u043E\u0441\u0442\u0430\u044E\u0442\u0441\u044F \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. -->
97        <section class="garden-panel garden-limits" aria-labelledby="garden-limits-title">
98          <div class="garden-panel-head">
99            <span class="garden-panel-title" id="garden-limits-title">${Icons.render("chart",16)} ${I18n.t("garden.personal_limit","\u041B\u0438\u0447\u043D\u044B\u0439 \u043B\u0438\u043C\u0438\u0442 \u043E\u0447\u043A\u043E\u0432")}</span>
100            <span class="garden-panel-note">${I18n.t("garden.garden_and_pen","\u041E\u0413\u041E\u0420\u041E\u0414 + \u0417\u0410\u0413\u041E\u041D")}</span>
101          </div>
102          <div class="garden-limits-body" id="garden-limits"><div class="garden-spin"></div></div>
103        </section>
104
105        <!-- \u0411\u0435\u0441\u0435\u0434\u043A\u0430 \u2014 \u0432\u043E \u0432\u0441\u044E \u0448\u0438\u0440\u0438\u043D\u0443, \u0441 \u0444\u0438\u043A\u0441-\u0432\u044B\u0441\u043E\u0442\u043E\u0439 (\u043B\u043E\u0433 \u0441\u043A\u0440\u043E\u043B\u043B\u0438\u0442\u0441\u044F \u0432\u043D\u0443\u0442\u0440\u0438). -->
106        <div class="garden-panel garden-chat">
107          <div class="garden-panel-head"><span class="garden-panel-title">${Icons.render("chat",16)} ${I18n.t("garden.gazebo_title","\u0411\u0435\u0441\u0435\u0434\u043A\u0430 \u0443 \u043F\u043B\u0435\u0442\u043D\u044F")}</span><span class="garden-panel-note" id="garden-chat-note"></span></div>
108          <div class="garden-chat-log" id="garden-chat-log"><div class="garden-spin"></div></div>
109          <form class="garden-chat-form" id="garden-chat-form" autocomplete="off">
110            <input class="garden-chat-input" id="garden-chat-input" maxlength="500" placeholder="${Utils.esc(I18n.t("garden.say_at_garden","\u0421\u043A\u0430\u0437\u0430\u0442\u044C \u0443 \u0433\u0440\u044F\u0434\u043A\u0438\u2026"))}">
111            <button class="garden-chat-send" type="submit" aria-label="${Utils.esc(I18n.t("common.send","\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C"))}">${Icons.render("send",18)}</button>
112          </form>
113        </div>
114
115        <!-- \xAB\u041A\u0430\u043A \u0443\u0441\u0442\u0440\u043E\u0435\u043D\xBB \u2014 \u0441\u0442\u0430\u0442\u0438\u0447\u043D\u043E\u0435 \u0440\u0430\u0437\u044A\u044F\u0441\u043D\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u043D\u043E\u0432\u0438\u0447\u043A\u043E\u0432, \u0432 \u0441\u0430\u043C\u043E\u043C \u043D\u0438\u0437\u0443 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B. -->
116        <section class="garden-manual" aria-labelledby="garden-manual-title">
117          <div class="garden-manual-head">
118            <div class="garden-decree-kicker">${I18n.t("garden.kanzellaria_explains","\u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \xB7 \u0440\u0430\u0437\u044A\u044F\u0441\u043D\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u0433\u0440\u0430\u0436\u0434\u0430\u043D")}</div>
119            <h2 class="garden-manual-title" id="garden-manual-title">${I18n.t("garden.how_garden_works","\u041A\u0430\u043A \u0443\u0441\u0442\u0440\u043E\u0435\u043D \u041E\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0439 \u041E\u0433\u043E\u0440\u043E\u0434")}</h2>
120            <p class="garden-manual-lead">${I18n.t("garden.manual_lead","\u0413\u0440\u044F\u0434\u043A\u0430 \u043E\u0434\u043D\u0430 \u043D\u0430 \u0432\u0441\u044E \u043E\u0431\u043B\u0430\u0441\u0442\u044C, \u0438 \u0432\u043E\u0437\u0434\u0435\u043B\u044B\u0432\u0430\u044E\u0442 \u0435\u0451 \u0441\u043E\u043E\u0431\u0449\u0430, \u0432 \u0440\u0435\u0430\u043B\u044C\u043D\u043E\u043C \u0432\u0440\u0435\u043C\u0435\u043D\u0438: \u0447\u0442\u043E \u043E\u0434\u0438\u043D \u0415\u0433\u043E\u0440 \u043F\u043E\u0441\u0435\u044F\u043B \u2014 \u0434\u0440\u0443\u0433\u043E\u0439 \u043F\u043E\u043B\u044C\u0451\u0442, \u0442\u0440\u0435\u0442\u0438\u0439 \u0441\u043E\u0431\u0435\u0440\u0451\u0442. \u041B\u0438\u0447\u043D\u044B\u0445 \u0434\u0435\u043B\u044F\u043D\u043E\u043A \u043D\u0435\u0442 \u2014 \u0435\u0441\u0442\u044C \u043E\u0431\u0449\u0438\u0439 \u0442\u0440\u0443\u0434 \u0438 \u043E\u0431\u0449\u0438\u0439 \u041F\u043B\u0430\u043D. \u0417\u0430\u0445\u043E\u0434\u0438\u0442\u0435, \u043A\u043B\u0438\u043A\u0430\u0439\u0442\u0435 \u043F\u043E \u043D\u0430\u0434\u0435\u043B\u0430\u043C \u2014 \u043D\u0443\u0436\u043D\u043E\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043F\u043E\u0434\u0431\u0435\u0440\u0451\u0442 \u0441\u0430\u043C\u0430.")}</p>
121          </div>
122
123          <div class="garden-manual-steps">
124            <div class="gm-step">
125              <span class="gm-step-ic gm-soil"></span>
126              <div class="gm-step-b"><b>${I18n.t("garden.manual_step_plant","1. \u0417\u0430\u0441\u0435\u044F\u0442\u044C")}</b><span>${I18n.t("garden.manual_step_plant_desc","\u0421\u0432\u043E\u0431\u043E\u0434\u043D\u044B\u0439 \u043D\u0430\u0434\u0435\u043B \u2014 \u043A\u0438\u043D\u044C\u0442\u0435 \u0441\u0435\u043C\u044F. \u0418\u0437 \u043D\u0435\u0433\u043E \u043F\u0440\u043E\u043A\u043B\u044E\u043D\u0443\u0442\u0441\u044F \u0432\u0441\u0445\u043E\u0434\u044B.")}</span></div>
127            </div>
128            <div class="gm-step">
129              <span class="gm-step-ic gm-art"><img src="/img/garden-crops/herb-growing-imagegen.webp" alt="" aria-hidden="true" decoding="async"></span>
130              <div class="gm-step-b"><b>${I18n.t("garden.manual_step_water","2. \u041F\u043E\u043B\u0438\u0442\u044C")}</b><span>${I18n.t("garden.manual_step_water_desc","\u0412\u0441\u0445\u043E\u0434\u044B \u0437\u0440\u0435\u044E\u0442 \u0438 \u0441\u0430\u043C\u0438, \u043D\u043E \u043F\u043E\u043B\u0438\u0432 \u2014 \u0441\u0432\u043E\u0439 \u0438\u043B\u0438 \u0447\u0443\u0436\u043E\u0439 \u2014 \u0443\u0441\u043A\u043E\u0440\u044F\u0435\u0442 \u0434\u0435\u043B\u043E.")}</span></div>
131            </div>
132            <div class="gm-step">
133              <span class="gm-step-ic gm-art"><img src="/img/garden-crops/carrot-imagegen.webp" alt="" aria-hidden="true" decoding="async"></span>
134              <div class="gm-step-b"><b>${I18n.t("garden.manual_step_harvest","3. \u0421\u043E\u0431\u0440\u0430\u0442\u044C")}</b><span>${I18n.t("garden.manual_step_harvest_desc","\u041F\u043E\u0441\u043B\u0435 \u0441\u043E\u0437\u0440\u0435\u0432\u0430\u043D\u0438\u044F \u043F\u043E\u0441\u0435\u044F\u0432\u0448\u0438\u0439 \u043F\u043E\u043B\u0443\u0447\u0430\u0435\u0442 \u043A\u043E\u0440\u043E\u0442\u043A\u043E\u0435 \u043E\u043A\u043D\u043E \u043F\u0435\u0440\u0432\u043E\u043E\u0447\u0435\u0440\u0435\u0434\u043D\u043E\u0433\u043E \u0441\u0431\u043E\u0440\u0430, \u0437\u0430\u0442\u0435\u043C \u0443\u0440\u043E\u0436\u0430\u0439 \u0441\u043D\u043E\u0432\u0430 \u043E\u0431\u0449\u0438\u0439. \u042D\u0442\u043E \u0438 \u0435\u0441\u0442\u044C \u043E\u0447\u043A\u0438 \u2014 \u0432 \u041F\u043B\u0430\u043D \u0438 \u043D\u0430 \u0414\u043E\u0441\u043A\u0443 \u043F\u043E\u0447\u0451\u0442\u0430.")}</span></div>
135            </div>
136          </div>
137          <p class="garden-manual-aside"><span class="gm-aside-ic gm-art gm-art--weed"><img src="/img/garden-crops/weed-single-imagegen.webp" alt="" aria-hidden="true" decoding="async"></span><span>${I18n.t("garden.manual_weeds","\u0410 \u0438\u043D\u043E\u0433\u0434\u0430 \u0432\u043C\u0435\u0441\u0442\u043E \u0443\u0440\u043E\u0436\u0430\u044F \u043B\u0435\u0437\u0435\u0442 <b>\u0431\u0443\u0440\u044C\u044F\u043D</b> \u2014 \u0435\u0433\u043E \u0432\u044B\u043F\u0430\u043B\u044B\u0432\u0430\u044E\u0442 (<b>\u043F\u0440\u043E\u043F\u043E\u043B\u043E\u0442\u044C</b>). \u041F\u043E\u043B\u044C\u0437\u0430 \u043C\u0430\u043B\u0430\u044F, \u0437\u0430\u0442\u043E \u0433\u0440\u044F\u0434\u043A\u0430 \u0432 \u043F\u043E\u0440\u044F\u0434\u043A\u0435.")}</span></p>
138
139          <div class="garden-manual-grid">
140            <div class="gm-card">
141              <div class="gm-card-ic">${Icons.render("sprout",18)}</div>
142              <div class="gm-card-t">${I18n.t("garden.harvest_plan","\u041F\u043B\u0430\u043D \u043F\u043E \u0423\u0440\u043E\u0436\u0430\u044E")}</div>
143              <div class="gm-card-d">${I18n.t("garden.season_goal","\u041E\u0431\u0449\u0430\u044F \u0446\u0435\u043B\u044C \u0441\u0435\u0437\u043E\u043D\u0430 \u2014 \u043D\u0430\u043F\u043E\u043B\u043D\u044F\u0435\u0442\u0441\u044F \u0443\u0441\u0438\u043B\u0438\u044F\u043C\u0438 \u0432\u0441\u0435\u0445 \u0415\u0433\u043E\u0440\u043E\u0432 \u0440\u0430\u0437\u043E\u043C. \u0412\u044B\u043F\u043E\u043B\u043D\u0438\u043B\u0438 \u041F\u043B\u0430\u043D \u2014 \u043E\u0431\u043B\u0430\u0441\u0442\u044C \u043E\u0442\u0447\u0438\u0442\u0430\u043B\u0430\u0441\u044C, \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043E\u0431\u044A\u044F\u0432\u043B\u044F\u0435\u0442 \u043D\u043E\u0432\u044B\u0439.")}</div>
144            </div>
145            <div class="gm-card">
146              <div class="gm-card-ic">${Icons.render("trophy",18)}</div>
147              <div class="gm-card-t">${I18n.t("garden.honor_roll","\u0414\u043E\u0441\u043A\u0430 \u043F\u043E\u0447\u0451\u0442\u0430")}</div>
148              <div class="gm-card-d">${I18n.t("garden.honor_roll_desc","\u0421\u0435\u0437\u043E\u043D\u043D\u044B\u0439 \u0441\u0447\u0451\u0442 \u0441\u043E\u0431\u0440\u0430\u043D\u043D\u043E\u0433\u043E \u043F\u043E \u043A\u0430\u0436\u0434\u043E\u043C\u0443 \u0440\u0430\u0434\u0435\u0442\u0435\u043B\u044E. \u041A\u0442\u043E \u0431\u043E\u043B\u044C\u0448\u0435 \u0440\u0430\u0434\u0435\u043B \u0437\u0430 \u0443\u0440\u043E\u0436\u0430\u0439 \u2014 \u0442\u043E\u0442 \u0432\u044B\u0448\u0435. \u0421 \u043D\u043E\u0432\u044B\u043C \u0441\u0435\u0437\u043E\u043D\u043E\u043C \u0441\u0447\u0451\u0442 \u043E\u0431\u043D\u0443\u043B\u044F\u0435\u0442\u0441\u044F.")}</div>
149            </div>
150            <div class="gm-card">
151              <div class="gm-card-ic">${Icons.render("star",18)}</div>
152              <div class="gm-card-t">${I18n.t("garden.eg_level","\u0423\u0440\u043E\u0432\u0435\u043D\u044C \u0415\u0433\u043E\u0440\u0438\u0437\u043C\u0430")}</div>
153              <div class="gm-card-d">${I18n.t("garden.eg_rewards","\u0417\u0430 \u0441\u043D\u044F\u0442\u044B\u0439 \u0443\u0440\u043E\u0436\u0430\u0439 \u0438\u0434\u0443\u0442 \u043E\u0447\u043A\u0438 \u0415\u0413 \u2014 \u043D\u043E \u0442\u043E\u043B\u044C\u043A\u043E <b>\u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\u043D\u044B\u043C \u0415\u0433\u043E\u0440\u0430\u043C</b>. \u0421\u0435\u0437\u043E\u043D\u043D\u044B\u0439 \u0441\u0447\u0451\u0442 \u0440\u0430\u0441\u0442\u0451\u0442 \u0443 \u0432\u0441\u0435\u0445, \u0430 \u0432\u043E\u0442 \u0440\u0435\u043F\u0443\u0442\u0430\u0446\u0438\u044E \u0437\u0430\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u044E\u0442 \u043F\u043E\u043B\u043D\u043E\u043F\u0440\u0430\u0432\u043D\u044B\u0435 \u0433\u0440\u0430\u0436\u0434\u0430\u043D\u0435.")}</div>
154            </div>
155          </div>
156
157          <div class="garden-manual-rules">
158            <span class="gm-rule">${I18n.t("garden.pause_rule","\u041C\u0435\u0436\u0434\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F\u043C\u0438 \u2014 \u043A\u043E\u0440\u043E\u0442\u043A\u0430\u044F \u0432\u044B\u0434\u0435\u0440\u0436\u043A\u0430: \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043D\u0435 \u0442\u0435\u0440\u043F\u0438\u0442 \u0441\u0443\u0435\u0442\u044B \u0438 \u043D\u0430\u043A\u0440\u0443\u0442\u043A\u0438.")}</span>
159            <span class="gm-rule">${I18n.t("garden.who_can_cultivate","\u0412\u043E\u0437\u0434\u0435\u043B\u044B\u0432\u0430\u0442\u044C \u043C\u043E\u0436\u0435\u0442 \u043B\u044E\u0431\u043E\u0439 \u0432\u043E\u0448\u0435\u0434\u0448\u0438\u0439 \u0433\u0440\u0430\u0436\u0434\u0430\u043D\u0438\u043D; \u0415\u0413 \u0437\u0430 \u0442\u0440\u0443\u0434 \u2014 \u043F\u0440\u0438\u0432\u0438\u043B\u0435\u0433\u0438\u044F \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\u043D\u044B\u0445 \u0415\u0433\u043E\u0440\u043E\u0432.")}</span>
160            <span class="gm-rule">${I18n.t("garden.realtime_rule","\u0413\u0440\u044F\u0434\u043A\u0430 \u0436\u0438\u0432\u0451\u0442 \u0432 \u0440\u0435\u0430\u043B\u044C\u043D\u043E\u043C \u0432\u0440\u0435\u043C\u0435\u043D\u0438: \u0440\u043E\u0441\u0442 \u043D\u0430\u0434\u0435\u043B\u043E\u0432, \u0447\u0443\u0436\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0438 \u0441\u0447\u0451\u0442 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u044E\u0442\u0441\u044F \u0441\u0430\u043C\u0438.")}</span>
161          </div>
162        </section>
163
164        <div class="garden-tip" id="garden-tip" hidden></div>
165      </div>
166    `,App.state.user?(this._bindSocket(),SocketClient.gardenJoin(),this._joined=!0,setTimeout(()=>{this.state||this._loadViaRest()},1200)):this._startGuestObserver(),this.loadLeaderboard(),this._bindCanvas(),this._bindLifecycle(),this._installTextState(),GardenPet.mountDock("garden-pet-dock"),GardenPetShow.mount("garden-pet-show"),this._reduceMotion=Utils.reduceMotion(),!this._reduceMotion){let last=0;const loop=ts=>{this._raf=requestAnimationFrame(loop),!(document.hidden||ts-last<33)&&(last=ts,this.state&&this.draw())};this._raf=requestAnimationFrame(loop)}this._cdTimer=setInterval(()=>this.updateCd(),250),this._accountTimer=setInterval(()=>this.loadLeaderboard(),6e4),this._sceneClockTimer=setInterval(()=>{this.state&&this.draw()},6e4),this._syncScoreFormat(),this._relayoutSoon()},_relayoutSoon(){requestAnimationFrame(()=>requestAnimationFrame(()=>{this.state&&(this._geom=null,this.draw())}))},_bindSocket(){this._cleanup.push(SocketClient.on("garden:state",st=>this.applyState(st))),this._cleanup.push(SocketClient.on("garden:update",d=>this.applyDelta(d))),this._cleanup.push(SocketClient.on("garden:civic",civic=>{this.state&&(this._trackCivicCompletion(civic,!0),this.state.civic=civic,this.renderCivic(),this.draw())})),this._cleanup.push(SocketClient.on("garden:reset",d=>this.applyReset(d))),this._cleanup.push(SocketClient.on("garden:presence",({count})=>this.setPresence(count))),this._cleanup.push(SocketClient.on("garden:error",payload=>{Utils.showToast(this._errorMessage(payload,"garden.action_failed","\u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043E\u0442\u043A\u043B\u043E\u043D\u0438\u043B\u0430 \u0440\u0430\u0431\u043E\u0442\u0443 \u043D\u0430 \u0433\u0440\u044F\u0434\u043A\u0435. \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435."),"error")})),this._cleanup.push(SocketClient.on("garden:pet-treat",detail=>GardenPet.onTreat(detail))),this._cleanup.push(SocketClient.on("garden:pet-supply",detail=>GardenPet.onSupply(detail))),this._cleanup.push(SocketClient.on("new_message",d=>this._onChatMessage(d))),this._cleanup.push(SocketClient.on("socket:connect",()=>{this._joined&&SocketClient.gardenJoin(),this._chatId&&SocketClient.joinChat(this._chatId)}))},_bindLifecycle(){const onHash=()=>{location.hash.startsWith("#/garden")||(this.cleanup(),window.removeEventListener("hashchange",onHash))};window.addEventListener("hashchange",onHash),this._cleanup.push(()=>window.removeEventListener("hashchange",onHash));const onResize=()=>{this.state&&this.draw()};window.addEventListener("resize",onResize),this._cleanup.push(()=>window.removeEventListener("resize",onResize));const onVis=()=>{!document.hidden&&this.state&&(this._geom=null,this.draw())};document.addEventListener("visibilitychange",onVis),this._cleanup.push(()=>document.removeEventListener("visibilitychange",onVis));
166const themeObserver=new MutationObserver(()=>{this.state&&this.draw()});themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),this._cleanup.push(()=>themeObserver.disconnect())},_installTextState(){const renderText=()=>JSON.stringify({screen:"garden",coordinates:"origin top-left; x increases right; y increases down; cell index = y * width + x",scoreFormat:this._scoreFormat,season:this.state&&this.state.season?{id:this.state.season.id,progress:this.state.season.progress,target:this.state.season.target,completed:!!this.state.season.completed}:null,board:this.state?{width:this.state.w,height:this.state.h,cells:this.state.cells.map((cell,index)=>({index,stage:cell.s,crop:cell.c,trait:cell.s!=="empty"&&cell.s!=="weeds"&&(this.cropTrait(cell.c)||{}).code||null,wet:this._isRecentlyWatered(cell,Math.floor(Date.now()/1e3)),harvestPrioritySeconds:this.harvestPriorityLeft(cell)})),weedClusters:this._weedClusterData(this.state.cells,this.state.w,this.state.h).clusters.map(cells=>({size:cells.length,cells})),transitions:this._cropTransitionState(),effects:this._waterEffectState(),scene:this._gardenSceneState()}:null,leaderboard:this._leaderboard.map(row=>({id:row.id,rank:row.rank,points:row.points})),limits:this._limits&&this._limits.points?{...this._limits.points}:null,civic:this.state&&this.state.civic?{day:this.state.civic.day,weather:this.state.civic.weather&&this.state.civic.weather.code,tasks:this.state.civic.tasks.map(task=>({code:task.code,progress:task.progress,target:task.target})),order:this.state.civic.order.map(item=>({crop:item.crop,progress:item.progress,target:item.target})),development:this.state.civic.beautification,ceremony:this._civicCeremonyActive(),cropBook:this.state.civic.book?{stamps:this.state.civic.book.stamps,total:this.state.civic.book.stamps_total,badges:this.state.civic.book.badges.filter(item=>item.earned).map(item=>item.code)}:null}:null,pen:this.state&&this.state.pen?{target:this.state.pen.target,animals:this.state.pen.animals.map((animal,index)=>({index,name:animal.name,fill:animal.fill,ready:!!animal.ready,resting:Number(animal.restAt||0)>Math.floor(Date.now()/1e3),reaction:(this._activePenReaction(index,this._animationNow())||{}).type||null}))}:null,pet:GardenPet.textState(),petShow:GardenPetShow.textState()}),advanceTime=ms=>{this._timeOffset+=Math.max(0,Number(ms)||0),this.state&&(this.renderCivic(),this.draw())};window.render_game_to_text=renderText,window.advanceTime=advanceTime,this._cleanup.push(()=>{window.render_game_to_text===renderText&&delete window.render_game_to_text,window.advanceTime===advanceTime&&delete window.advanceTime})},_bindCanvas(){const canvas=document.getElementById("garden-canvas");if(!canvas)return;if(window.ResizeObserver){const ro=new window.ResizeObserver(()=>{this.state&&(this._geom=null,this.draw())});ro.observe(canvas),this._cleanup.push(()=>ro.disconnect())}const onMove=e=>this.onHover(e),onLeave=()=>{this._hover=-1,this.hideTip()},onClick=e=>this.onClick(e),onTouch=e=>{if(!e.touches||!e.touches.length)return;const i=this._cellAt(e.touches[0]);i>=0&&(this.showTip(e.touches[0],i),clearTimeout(this._tipTimer),this._tipTimer=setTimeout(()=>this.hideTip(),2600))};canvas.addEventListener("mousemove",onMove),canvas.addEventListener("mouseleave",onLeave),canvas.addEventListener("click",onClick),canvas.addEventListener("touchstart",onTouch,{passive:!0}),this._cleanup.push(()=>{canvas.removeEventListener("mousemove",onMove),canvas.removeEventListener("mouseleave",onLeave),canvas.removeEventListener("click",onClick),canvas.removeEventListener("touchstart",onTouch)});const sr=document.getElementById("garden-sr");if(sr){const onSr=e=>{const btn=e.target.closest("button[data-i]");btn&&this.act(parseInt(btn.dataset.i,10))};sr.addEventListener("click",onSr),this._cleanup.push(()=>sr.removeEventListener("click",onSr))}const form=document.getElementById("garden-chat-form");if(form){const onSubmit=e=>{e.preventDefault(),this.sendChat()};form.addEventListener("submit",onSubmit),this._cleanup.push(()=>form.removeEventListener("submit",onSubmit))}},cleanup(){typeof GardenPetShow<"u"&&GardenPetShow.unmount(),this._joined&&(SocketClient.gardenLeave(),this._joined=!1),this._chatId&&(SocketClient.leaveChat(this._chatId),this._chatId=null),this._cleanup.forEach(fn=>
166{try{fn()}catch{}}),this._cleanup=[],this._raf&&cancelAnimationFrame(this._raf),this._raf=null,clearTimeout(this._tipTimer),clearInterval(this._cdTimer),clearInterval(this._accountTimer),clearInterval(this._sceneClockTimer),clearTimeout(this._accountRefreshTimer),clearTimeout(this._civicCeremonyTimer),this._cd={plant:0,water:0,harvest:0},this._penCd=0,this._penBound=!1,this.state=null,this._flash={},this._hover=-1,this._avCache=null,this._leaderboard=[],this._leaderboardMe=null,this._limits=null,this._limitReleaseRefreshAt=0,this._civicStatus=null,this._civicCeremony=null,this._civicCeremonyTimer=null,this._timeOffset=0,this._cropArtCache=null,this._cropTransitions={},Object.values(this._waterEffectTimers).forEach(timer=>clearTimeout(timer)),this._waterEffects={},this._waterEffectTimers={},Object.values(this._penReactionTimers).forEach(timer=>clearTimeout(timer)),this._penReactions={},this._penReactionTimers={}},async _loadViaRest(){try{const st=await Api.garden.state();this.state||this.applyState(st)}catch{this.state||this._renderUnavailable()}},_startGuestObserver(){this._renderGuestChat();const chip=document.getElementById("garden-presence");chip&&(chip.textContent=I18n.t("garden.guest_observer","\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \xB7 \u0433\u043E\u0441\u0442\u044C")),this._refreshViaRest();let tick=0;const poll=setInterval(()=>{document.hidden||(this._refreshViaRest(),++tick%3===0&&this.loadLeaderboard())},7e3);this._cleanup.push(()=>clearInterval(poll))},async _refreshViaRest(){try{const st=await Api.garden.state();this.applyState(st)}catch{this.state||this._renderUnavailable()}},_renderGuestChat(){const log=document.getElementById("garden-chat-log");log&&(log.innerHTML=`<div class="garden-empty">${I18n.t("garden.guest_chat_html",'\u0411\u0435\u0441\u0435\u0434\u043A\u0430 \u0443 \u043F\u043B\u0435\u0442\u043D\u044F \u2014 \u0434\u043B\u044F \u0433\u0440\u0430\u0436\u0434\u0430\u043D.<br><a href="#/login">\u0412\u043E\u0439\u0434\u0438\u0442\u0435</a>, \u0447\u0442\u043E\u0431\u044B \u0447\u0438\u0442\u0430\u0442\u044C \u0438 \u0433\u043E\u0432\u043E\u0440\u0438\u0442\u044C \u0443 \u0433\u0440\u044F\u0434\u043A\u0438.')}</div>`);const input=document.getElementById("garden-chat-input");input&&(input.disabled=!0,input.placeholder=I18n.t("garden.guest_chat_placeholder","\u0411\u0435\u0441\u0435\u0434\u043A\u0430 \u2014 \u0434\u043B\u044F \u0433\u0440\u0430\u0436\u0434\u0430\u043D"));const note=document.getElementById("garden-chat-note");note&&(note.textContent=I18n.t("garden.guest_chat_note","\u0432\u043E\u0439\u0434\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0443\u0447\u0430\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C"))},_promptLogin(){Utils.showToast(I18n.t("garden.must_login","\u0412\u043E\u0437\u0434\u0435\u043B\u044B\u0432\u0430\u0442\u044C \u041E\u0433\u043E\u0440\u043E\u0434 \u043C\u043E\u0436\u0435\u0442 \u0433\u0440\u0430\u0436\u0434\u0430\u043D\u0438\u043D. \u0412\u043E\u0439\u0434\u0438\u0442\u0435 \u0438\u043B\u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435\u0441\u044C."),"info")},_renderUnavailable(){const hint=document.getElementById("garden-hint");hint&&(hint.textContent=I18n.t("garden.unavailable","\u041E\u0433\u043E\u0440\u043E\u0434 \u0441\u0435\u0439\u0447\u0430\u0441 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D"));const season=document.getElementById("garden-season");season&&(season.innerHTML=`<div class="garden-empty">${I18n.t("garden.closed","\u041E\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0439 \u041E\u0433\u043E\u0440\u043E\u0434 \u0441\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u043A\u0440\u044B\u0442 \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u0435\u0439 \u0438\u043B\u0438 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D. \u0417\u0430\u0433\u043B\u044F\u043D\u0438\u0442\u0435 \u043F\u043E\u0437\u0436\u0435.")}</div>`);const log=document.getElementById("garden-chat-log");log&&log.querySelector(".garden-spin")&&(log.innerHTML=`<div class="garden-empty">${I18n.t("garden.gazebo_unavailable","\u0411\u0435\u0441\u0435\u0434\u043A\u0430 \u0443 \u043F\u043B\u0435\u0442\u043D\u044F \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430.")}</div>`)},applyState(st){if(!st||!Array.isArray(st.cells))return;const previousCells=this.state&&this.state.cells;if(Array.isArray(previousCells))for(let i=0;i<Math.min(previousCells.length,st.cells.length);i++)this._trackCropTransition(i,previousCells[i],st.cells[i]);const previousPen=this.state&&this.state.pen&&this.state.pen.animals,nextPen=st.pen&&st.pen.animals;if(Array.isArray(previousPen)&&Array.isArray(nextPen))for(let i=0;i<Math.min(previousPen.length,nextPen.length);i++)this._trackPenTransition(i,previousPen[i],nextPen[i]);const hadCivic=!!this._civicStatus;this._trackCivicCompletion(st.civic,hadCivic),this.state=st;const guest=!App.state.user,hint=document.getElementById("garden-hint");hint&&(hint.textContent=guest?I18n.t("garden.guest_view","\u0412\u044B \u0441\u043C\u043E\u0442\u0440\u0438\u0442\u0435 \u041E\u0433\u043E\u0440\u043E\u0434 \u043A\u0430\u043A \u0433\u043E\u0441\u0442\u044C \u2014 \u0432\u043E\u0439\u0434\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0432\u0437\u044F\u0442\u044C\u0441\u044F \u0437\u0430 \u043B\u043E\u043F\u0430\u0442\u0443"):I18n.t("garden.click_plot_hint","\u041A\u043B\u0438\u043A\u043D\u0438\u0442\u0435 \u043F\u043E \u043D\u0430\u0434\u0435\u043B\u0443 \u2014 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043F\u043E\u0434\u0431\u0435\u0440\u0451\u0442\u0441\u044F \u043F\u043E \u0435\u0433\u043E \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u044E")),this.renderSeason(),this.renderCivic(),this.draw(),this._relayoutSoon(),this.renderSrPlots(),this.renderPen(),st.chatId&&!guest&&this.initChat(st.chatId)}
166,applyDelta(d){if(!this.state||!d)return;if(Array.isArray(d.cells))for(const{i,cell}of d.cells)i>=0&&i<this.state.cells.length&&(this._trackCropTransition(i,this.state.cells[i],cell),this.state.cells[i]=cell,this.updateSrPlot(i));if(Array.isArray(d.penAnimals)&&this.state.pen&&Array.isArray(this.state.pen.animals)){for(const{i,animal}of d.penAnimals)i>=0&&i<this.state.pen.animals.length&&(this._trackPenTransition(i,this.state.pen.animals[i],animal),this.state.pen.animals[i]=animal);this.renderPen()}if(d.season&&(this.state.season=d.season,this.renderSeason()),d.civic){const personalBook=this.state.civic&&this.state.civic.book,nextCivic={...d.civic,book:d.civic.book||personalBook||null};this._trackCivicCompletion(nextCivic,!0),this.state.civic=nextCivic,this.renderCivic()}const me=App.state.user&&App.state.user.id;if(d.leaderboard){const rows=d.leaderboard.slice(0,10),own=me&&d.leaderboard.find(row=>row.id===me);this._leaderboard=rows,this._leaderboardMe=own&&!rows.some(row=>row.id===own.id)?own:this._leaderboardMe,this._leaderboardMe&&rows.some(row=>row.id===this._leaderboardMe.id)&&(this._leaderboardMe=null),this.renderLeaderboard(this._leaderboard,this._leaderboardMe)}d.actor&&d.actor.id===me&&this._scheduleAccountRefresh(),d.actor&&d.actor.action==="water"&&Number.isInteger(Number(d.actor.cell))&&this._startWaterEffect(Number(d.actor.cell)),d.actor&&d.actor.id!==me&&d.actor.cell!==void 0&&(this._flash[d.actor.cell]={name:d.actor.name,action:d.actor.action,until:Date.now()+2e3}),this.draw()},_trackCropTransition(i,previous,next){if(!previous||!next||previous.s===next.s||this._reduceMotion)return;const startedAt=this._animationNow();previous.s==="empty"&&next.s==="seed"?this._cropTransitions[i]={type:"plant",crop:next.c,startedAt,until:startedAt+1050}:previous.s==="sprout"&&next.s==="ripe"?this._cropTransitions[i]={type:"ripen",crop:next.c,startedAt,until:startedAt+780}:previous.s==="ripe"&&next.s==="empty"&&(this._cropTransitions[i]={type:"harvest",crop:previous.c,startedAt,until:startedAt+720})},_activeCropTransition(i,t){const transition=this._cropTransitions[i];return transition?t>=transition.until?(delete this._cropTransitions[i],null):transition:null},_cropTransitionState(){const now=this._animationNow();return Object.entries(this._cropTransitions).filter(([,transition])=>transition.until>now).map(([index,transition])=>({index:Number(index),type:transition.type,crop:transition.crop}))},_startWaterEffect(index){if(!this.state||index<0||index>=this.state.cells.length)return;const startedAt=this._animationNow(),duration=this._reduceMotion?900:1900;this._waterEffects[index]={type:"water",startedAt,until:startedAt+duration},clearTimeout(this._waterEffectTimers[index]),this._waterEffectTimers[index]=setTimeout(()=>{delete this._waterEffectTimers[index];const effect=this._waterEffects[index];effect&&effect.startedAt===startedAt&&delete this._waterEffects[index],this.state&&this.draw()},duration+30)},_activeWaterEffect(index,t){const effect=this._waterEffects[index];return effect?t>=effect.until?(delete this._waterEffects[index],null):effect:null},_waterEffectState(){const now=this._animationNow();return Object.entries(this._waterEffects).filter(([,effect])=>effect.until>now).map(([index,effect])=>({index:Number(index),type:effect.type,remainingMs:Math.max(0,Math.round(effect.until-now))}))},_trackPenTransition(i,previous,next){if(!previous||!next||this._reduceMotion)return;const before=Number(previous.fill)||0,after=Number(next.fill)||0;let type=null;if(previous.ready&&!next.ready&&Number(next.restAt||0)>Number(previous.restAt||0)?type="collect":after>before&&(type=!previous.ready&&next.ready?"ready":"feed"),!type)return;const startedAt=this._animationNow(),duration=type==="ready"?1100:type==="collect"?1050:760;this._penReactions[i]={type,startedAt,until:startedAt+duration,product:previous.product||next.product||this._text("garden.product_fallback","\u041F\u0440\u043E\u0434\u0443\u043A\u0442")},clearTimeout(this._penReactionTimers[i]),this._penReactionTimers[i]=setTimeout(()=>{delete this._penReactionTimers[i];
166const reaction=this._penReactions[i];reaction&&reaction.startedAt===startedAt&&delete this._penReactions[i],this.state&&this._paintPen()},duration+30)},_activePenReaction(i,t){const reaction=this._penReactions[i];return reaction?t>=reaction.until?(delete this._penReactions[i],null):reaction:null},applyReset(d){if(!d||!d.state)return;const personalBook=this.state&&this.state.civic&&this.state.civic.book;this.state=d.state,this.state.civic&&!this.state.civic.book&&(this.state.civic.book=personalBook||null),this.renderSeason(),this.renderCivic(),this._geom=null,this.draw(),this._relayoutSoon(),this.renderSrPlots(),this.renderPen(),this._leaderboard=[],this._leaderboardMe=null,this.renderLeaderboard([],null),d.announce&&Utils.showToast(this._seasonResetAnnouncement(d.announce),"info",6e3)},setPresence(count){const el=document.getElementById("garden-presence");el&&(el.textContent=this._text("garden.presence_count","{count} \u043D\u0430 \u0433\u0440\u044F\u0434\u043A\u0435",{count}))},_plural(n,one,few,many){const m10=n%10,m100=n%100;return m10===1&&m100!==11?one:m10>=2&&m10<=4&&(m100<10||m100>=20)?few:many},renderSeason(){const el=document.getElementById("garden-season");if(!el||!this.state)return;const s=this.state.season,chip=document.getElementById("garden-season-chip");chip&&(chip.textContent=I18n.t("garden.season_chip",{season:s.roman||"I"}));const boardNote=document.querySelector(".garden-leaderboard .garden-panel-note");boardNote&&(boardNote.textContent=I18n.t("garden.top_season",{season:s.roman||"I"}));const pct=Math.min(100,Math.round(s.progress/s.target*100));el.className="garden-season"+(s.completed?" is-done":""),el.innerHTML=`
167      <div class="garden-season-row">
168        <div class="garden-season-label">
169          <div class="garden-season-name">${I18n.t("garden.harvest_plan","\u041F\u043B\u0430\u043D \u043F\u043E \u0423\u0440\u043E\u0436\u0430\u044E \u043E\u0431\u043B\u0430\u0441\u0442\u0438")}</div>
170          <div class="garden-season-sub">${s.completed?I18n.t("garden.kanzellaria_thanks","\u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u0431\u043B\u0430\u0433\u043E\u0434\u0430\u0440\u0438\u0442 \u0433\u0440\u0430\u0436\u0434\u0430\u043D \u0437\u0430 \u0441\u0430\u043C\u043E\u043E\u0442\u0432\u0435\u0440\u0436\u0435\u043D\u043D\u044B\u0439 \u0442\u0440\u0443\u0434"):I18n.t("garden.fill_together","\u043D\u0430\u043F\u043E\u043B\u043D\u044F\u0435\u0442\u0441\u044F \u0443\u0441\u0438\u043B\u0438\u044F\u043C\u0438 \u0432\u0441\u0435\u0445 \u0415\u0433\u043E\u0440\u043E\u0432 \u2014 \u0441\u043E\u0431\u0438\u0440\u0430\u0439\u0442\u0435 \u0441\u043E\u043E\u0431\u0449\u0430")}</div>
171        </div>
172        <div class="garden-season-num"><b>${this.formatProduce(s.progress)}</b> / ${this.formatProduce(s.target)}</div>
173      </div>
174      <div class="garden-meter" role="progressbar" aria-valuenow="${pct}" aria-valuemin="0" aria-valuemax="100" aria-label="${Utils.esc(I18n.t("garden.plan_execution","\u0412\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u041F\u043B\u0430\u043D\u0430 \u043F\u043E \u0423\u0440\u043E\u0436\u0430\u044E"))}">
175        <div class="garden-meter-fill" style="width:${pct}%"></div>
176        <span class="garden-meter-pct">${pct}%</span></div>
177      ${s.completed?`<div class="garden-stamp">${I18n.t("garden.plan_complete","\u041F\u041B\u0410\u041D \u0412\u042B\u041F\u041E\u041B\u041D\u0415\u041D")}</div>`:""}
178    `},renderCivic(){const el=document.getElementById("garden-civic"),civic=this.state&&this.state.civic;if(!el)return;if(!civic){el.hidden=!0,el.innerHTML="";return}el.hidden=!1;const pct=(progress,target)=>Math.min(100,Math.round((Number(progress)||0)/Math.max(1,Number(target)||1)*100)),meter=(item,icon)=>`<div class="garden-civic-duty${item.complete?" is-complete":""}">
179      <span class="garden-civic-duty-icon" aria-hidden="true">${Icons.render(icon,19)}</span>
180      <span class="garden-civic-duty-copy"><b>${Utils.esc(this.civicTaskLabel(item.code,item.label))}</b><small>${Number(item.progress)}/${Number(item.target)}${Number(item.mine)?` \xB7 ${I18n.t("garden.your_contribution",{count:Number(item.mine)})}`:""}</small></span>
181      <i><em style="width:${pct(item.progress,item.target)}%"></em></i>
182      <strong aria-label="${Utils.esc(item.complete?I18n.t("garden.done","\u0412\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u043E"):I18n.t("garden.in_progress","\u0412 \u0440\u0430\u0431\u043E\u0442\u0435"))}">${item.complete?"\u2713":`${pct(item.progress,item.target)}%`}</strong>
183    </div>`,order=civic.order.map(item=>`<div class="garden-civic-order-item${item.complete?" is-complete":""}">
184      <span class="garden-crop-icon">${this.cropIconHtml(item.crop)}</span><div><b>${Utils.esc(this.cropName(item.crop,item.name))}</b><small>${Number(item.progress)}/${Number(item.target)}${Number(item.mine)?` \xB7 ${I18n.t("garden.from_you",{count:Number(item.mine)})}`:""}</small></div><em>${item.complete?"\u2713":`${pct(item.progress,item.target)}%`}</em>
185    </div>`).join(""),stage=Math.max(Number(civic.beautification&&civic.beautification.daily_stage)||0,Number(civic.beautification&&civic.beautification.season_stage)||0),landmarks=[["garden_landmark_bounds",I18n.t("garden.landmark_bounds","\u0420\u0430\u0437\u043C\u0435\u0447\u0435\u043D\u044B \u043C\u0435\u0436\u0438")],["garden_landmark_sign",I18n.t("garden.landmark_sign","\u041F\u043E\u0441\u0442\u0430\u0432\u043B\u0435\u043D\u0430 \u0432\u044B\u0432\u0435\u0441\u043A\u0430")],["garden_landmark_fence",I18n.t("garden.landmark_fence","\u0423\u043A\u0440\u0435\u043F\u043B\u0435\u043D\u0430 \u043E\u0433\u0440\u0430\u0434\u0430")],["garden_landmark_shed",I18n.t("garden.landmark_shed","\u041E\u0442\u043A\u0440\u044B\u0442 \u0441\u0430\u0440\u0430\u0439")],["garden_landmark_lantern",I18n.t("garden.landmark_lantern","\u0417\u0430\u0436\u0436\u0435\u043D\u044B \u0444\u043E\u043D\u0430\u0440\u0438")]],book=civic.book,bookCopy=book?I18n.t("garden.stamps_count",{count:Number(book.stamps),total:Number(book.stamps_total)}):I18n.t("garden.personal_inventory","\u043B\u0438\u0447\u043D\u0430\u044F \u043E\u043F\u0438\u0441\u044C"),weatherIcon={rain:"garden_weather_rain",sun:"sun",cool:"garden_weather_cool",fair:"garden_weather_fair"}[civic.weather.code]||"garden_weather_fair",celebrating=this._civicCeremonyActive();el.classList.toggle("is-celebrating",celebrating);const bookRows=book&&Array.isArray(book.entries)?book.entries.slice(0,3).map(entry=>{const kinds=Object.keys(entry.stamps||{}).length||4,filled=Object.values(entry.stamps||{}).filter(Boolean).length;return`<div class="gc-split${entry.complete?" is-complete":""}"><span><span class="garden-crop-icon" aria-hidden="true">${this.cropIconHtml(entry.crop)}</span>${Utils.esc(this.cropName(entry.crop,entry.name))}</span><b>${filled}/${kinds}</b></div>`}).join(""):"";el.innerHTML=`
186      <div class="gc-garden-grid">
187        <section class="gc-card garden-civic-main">
188          <div class="gc-widget-head garden-civic-head">
189            <div class="garden-civic-weather"><span aria-hidden="true">${Icons.render(weatherIcon,24)}</span><div><small>${I18n.t("garden.weather_register","\u041F\u043E\u0433\u043E\u0434\u0430 \u043F\u043E \u0432\u0435\u0434\u043E\u043C\u043E\u0441\u0442\u0438")}</small><b>${Utils.esc(this.weatherName(civic.weather.code,civic.weather.name))}</b></div></div>
190            <span class="gc-widget-note"><em>${Utils.esc(this.weatherNote(civic.weather.code,civic.weather.note))}</em></span>
191          </div>
192          <div class="garden-civic-grid">
193            <section><div class="garden-civic-label"><b>${I18n.t("garden.daily_detail","\u041D\u0430\u0440\u044F\u0434 \u041E\u0433\u043E\u0440\u043E\u0434\u0430")} \xB7 ${I18n.t("garden.completed_count",{count:civic.tasks.filter(item=>item.complete).length,total:civic.tasks.length})}</b></div>
194              <div class="garden-civic-duties gc-task-grid">${meter(civic.tasks[0],"garden_harvest")}${meter(civic.tasks[1],"garden_water")}${meter(civic.tasks[2],"garden_feed")}</div></section>
195            <section><div class="garden-civic-label"><b>${I18n.t("garden.city_order","\u0413\u043E\u0440\u043E\u0434\u0441\u043A\u043E\u0439 \u0437\u0430\u043A\u0430\u0437")}</b><span>${civic.order.every(item=>item.complete)?I18n.t("garden.order_delivered","\u0441\u0434\u0430\u043D"):I18n.t("garden.order_open","\u043F\u0440\u0438\u0451\u043C \u043E\u0442\u043A\u0440\u044B\u0442")}</span></div>
196              <div class="garden-civic-order">${order}</div>
197              ${civic.orderReward?.amount>0?`<p class="gc-muted garden-order-reward">${Utils.esc(I18n.t("garden.order_reward","\u0417\u0430 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u043D\u044B\u0439 \u0437\u0430\u043A\u0430\u0437 \u2014 \u0434\u043E {amount} \u0415-\u0411\u0430\u043B\u043B\u043E\u0432 \u043A\u0430\u0436\u0434\u043E\u043C\u0443, \u043A\u0442\u043E \u0432\u043D\u0451\u0441 \u043D\u0443\u0436\u043D\u044B\u0439 \u0443\u0440\u043E\u0436\u0430\u0439 \u0434\u043E \u0437\u0430\u043A\u0440\u044B\u0442\u0438\u044F. \u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0430\u044F. \u041E\u0433\u043E\u0440\u043E\u0434 \u0438 \u041E\u0431\u043E\u0440\u043E\u043D\u0430 \u0434\u0435\u043B\u044F\u0442 {steps} \u044D\u0442\u0430\u043F\u0430 \u0432 \u043D\u0435\u0434\u0435\u043B\u044E \u0438 \u043E\u0431\u0449\u0438\u0439 \u0438\u0433\u0440\u043E\u0432\u043E\u0439 \u043F\u0440\u0435\u0434\u0435\u043B {cap} \u0415-\u0411\u0430\u043B\u043B\u043E\u0432.",{amount:civic.orderReward.amount,steps:civic.orderReward.steps,cap:civic.orderReward.weeklyCap}))}</p>`:""}</section>
198          </div>
199        </section>
200        <aside class="gc-card garden-civic-aside">
201          <div class="gc-kicker">${I18n.t("garden.personal_collection","\u041B\u0438\u0447\u043D\u0430\u044F \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u044F")}</div>
202          <h2 class="gc-h2">${I18n.t("garden.culture_book","\u041A\u043D\u0438\u0433\u0430 \u043A\u0443\u043B\u044C\u0442\u0443\u0440")}</h2>
203          <div class="garden-civic-book-rows">${bookRows||`<div class="gc-split"><span>${Utils.esc(bookCopy)}</span></div>`}</div>
204          <button type="button" class="gc-btn gc-btn--block garden-civic-book-btn" onclick="GardenPage.openCropBook()">${Icons.render("book",18)} <span>${I18n.t("garden.open_crop_book","\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u043A\u043D\u0438\u0433\u0443")}</span> <span class="gc-muted">${Utils.esc(bookCopy)}</span></button>
205          <div class="garden-civic-development">
206            <div><small>${I18n.t("garden.plot_improvement","\u0411\u043B\u0430\u0433\u043E\u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u043E \u0443\u0447\u0430\u0441\u0442\u043A\u0430")}</small><b>${stage>=4?I18n.t("garden.model_plot","\u0423\u0447\u0430\u0441\u0442\u043E\u043A \u043E\u0431\u0440\u0430\u0437\u0446\u043E\u0432\u043E\u0433\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u043D\u0438\u044F"):landmarks[stage][1]}</b></div>
207            <div class="garden-civic-landmarks" aria-label="${Utils.esc(I18n.t("garden.improvement_stage_value",{stage}))}">${landmarks.map((item,index)=>`<span class="${index<=stage?"is-active":""}" role="img" aria-label="${Utils.esc(item[1])}" title="${Utils.esc(item[1])}">${Icons.render(item[0],20)}</span>`).join("")}</div>
208            <em>${I18n.t("garden.development_progress",{season:Number(civic.beautification.season_stage)||0,today:Number(civic.beautification.daily_stage)||0})}</em>
209          </div>
210          <a class="gc-btn gc-btn--primary gc-btn--block" href="#garden-canvas" onclick="GardenPage.scrollToBoard(event)">${I18n.t("garden.open_board","\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0433\u0440\u044F\u0434\u043A\u0443")}</a>
211        </aside>
212      </div>
213      ${celebrating?`<div class="garden-civic-ceremony" role="status" aria-l
213ive="assertive">
214        <span class="garden-civic-ceremony-seal" aria-hidden="true">\u2713</span>
215        <span><small>${this._text("garden.ceremony_department","\u041E\u0442\u0434\u0435\u043B \u0437\u0435\u043C\u043B\u0435\u0434\u0435\u043B\u0438\u044F \u0443\u0434\u043E\u0441\u0442\u043E\u0432\u0435\u0440\u044F\u0435\u0442")}</small><b>${this._text("garden.ceremony_complete","\u041D\u0430\u0440\u044F\u0434 \u0438\u0441\u043F\u043E\u043B\u043D\u0435\u043D")}</b><em>${this._text("garden.ceremony_note","\u0412\u0435\u0434\u043E\u043C\u043E\u0441\u0442\u044C \u0437\u0430\u043A\u0440\u044B\u0442\u0430 \xB7 \u0443\u0447\u0430\u0441\u0442\u043E\u043A \u043E\u0436\u0438\u0432\u043B\u0451\u043D")}</em></span>
216        <i aria-hidden="true">\u2726</i><i aria-hidden="true">\u2726</i><i aria-hidden="true">\u2726</i>
217      </div>`:""}`},_trackCivicCompletion(civic,allowCeremony){if(!civic||!civic.day){this._civicStatus=null;return}const next={day:civic.day,complete:!!civic.complete},previous=this._civicStatus;this._civicStatus=next,allowCeremony&&previous&&previous.day===next.day&&!previous.complete&&next.complete&&this._startCivicCeremony(next.day)},_animationNow(){return performance.now()+this._timeOffset},_civicCeremonyActive(){return!!(this._civicCeremony&&this._animationNow()<this._civicCeremony.until)},_startCivicCeremony(day){const startedAt=this._animationNow();this._civicCeremony={day,startedAt,until:startedAt+5200},clearTimeout(this._civicCeremonyTimer),this._civicCeremonyTimer=setTimeout(()=>{!this._civicCeremony||this._civicCeremony.day!==day||(this._civicCeremony=null,this._civicCeremonyTimer=null,this.renderCivic(),this.draw())},5250),this.renderCivic(),this.draw()},updateCropBook(book){!this.state||!this.state.civic||!book||(this.state.civic.book=book,this.renderCivic())},cropIconHtml(crop){const index=Number(crop),art=this.CROP_ART[index];return art?`<img src="${art}" alt="" decoding="async">`:this.CROP_EMOJI[index]||"\u{1F331}"},scrollToBoard(event){event&&typeof event.preventDefault=="function"&&event.preventDefault();const board=document.querySelector(".garden-board-wrap");if(!board)return;let smooth=!0;try{smooth=!window.matchMedia("(prefers-reduced-motion: reduce)").matches}catch{smooth=!0}board.scrollIntoView({behavior:smooth?"smooth":"auto",block:"start"});const skip=document.getElementById("garden-sr"),first=skip&&skip.querySelector("button");first&&first.focus({preventScroll:!0})},openCropBook(){if(!App.state.user)return this._promptLogin();const civic=this.state&&this.state.civic,book=civic&&civic.book;if(!book)return Utils.showToast(I18n.t("garden.crop_book_unavailable","\u041A\u043D\u0438\u0433\u0430 \u043A\u0443\u043B\u044C\u0442\u0443\u0440 \u043F\u043E\u043A\u0430 \u043D\u0435 \u043F\u043E\u0434\u043D\u044F\u0442\u0430 \u0438\u0437 \u0430\u0440\u0445\u0438\u0432\u0430."),"info");const stampDefs=[["harvested","garden_harvest",I18n.t("garden.stamp_harvested","\u0421\u043E\u0431\u0440\u0430\u043D\u043E")],["rain","garden_weather_rain",I18n.t("garden.stamp_rain","\u0421\u043E\u0431\u0440\u0430\u043D\u043E \u0432 \u0434\u043E\u0436\u0434\u044C")],["order","garden_order",I18n.t("garden.stamp_order","\u0421\u0434\u0430\u043D\u043E \u0432 \u0437\u0430\u043A\u0430\u0437")],["pet","garden_pet",I18n.t("garden.stamp_pet","\u0412\u044B\u0434\u0430\u043D\u043E \u0436\u0438\u0432\u043E\u0442\u043D\u043E\u043C\u0443")]],rows=book.entries.map(entry=>{const trait=this.displayTrait(this.cropTrait(entry.crop)),traitHtml=trait?`<em class="garden-crop-book-trait"><b>${Utils.esc(trait.name)}</b> \xB7 ${Utils.esc(trait.note)}</em>`:"",stamps=Object.values(entry.stamps).filter(Boolean).length;return`<div class="garden-crop-book-row${entry.complete?" is-complete":""}">
218        <span class="garden-crop-book-crop">${this.cropIconHtml(entry.crop)}</span>
219        <div><b>${Utils.esc(this.cropName(entry.crop,this.state.crops[entry.crop]))}</b><small>${entry.complete?I18n.t("garden.full_cycle_registered","\u043F\u043E\u043B\u043D\u044B\u0439 \u043E\u0431\u043E\u0440\u043E\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D"):I18n.t("garden.stamps_count",{count:stamps,total:4})}</small>${traitHtml}</div>
220        <div class="garden-crop-book-stamps">${stampDefs.map(([key,icon,label])=>`<span class="${entry.stamps[key]?"is-earned":""}" title="${Utils.esc(label)}" aria-label="${Utils.esc(I18n.t("garden.stamp_state",{label,state:entry.stamps[key]?I18n.t("garden.granted","\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E"):I18n.t("garden.not_granted","\u043D\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E")}))}">${Icons.render(icon,13)}</span>`).join("")}</div>
221      </div>`}).join(""),badges=book.badges.map(item=>`<div class="garden-crop-book-badge${item.earned?" is-earned":""}"><span aria-hidden="true">${Icons.render("award",16)}</span><div><b>${Utils.esc(I18n.t(`garden.badge_${item.code}_name`,item.name))}</b><small>${Utils.esc(I18n.t(`garden.badge_${item.code}_note`,item.note))} \xB7 ${Number(item.progress)}/${Number(item.target)}</small></div></div>`).join("");Modals.open(`<div class="modal garden-crop-book-modal">
222      <div class="modal-header"><div class="modal-title">${I18n.t("garden.crop_book","\u041A\u043D\u0438\u0433\u0430 \u043A\u0443\u043B\u044C\u0442\u0443\u0440")}</div><button class="modal-close" onclick="Modals.close()" aria-label="${Utils.esc(I18n.t("common.close","\u0417\u0430\u043A\u0440\u044B\u0442\u044C"))}">${Icons.render("close")}</button></div>
223      <div class="modal-body garden-crop-book-sheet">
224        <header><div><small>${I18n.t("garden.personal_long_collection","\u041B\u0438\u0447\u043D\u0430\u044F \u0434\u043E\u043B\u0433\u043E\u0441\u0440\u043E\u0447\u043D\u0430\u044F \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u044F")}</small><h3>${I18n.t("garden.crop_turnover_register","\u0412\u0435\u0434\u043E\u043C\u043E\u0441\u0442\u044C \u0441\u0435\u043B\u044C\u0445\u043E\u0437\u043E\u0431\u043E\u0440\u043E\u0442\u0430")}</h3><p>${I18n.t("garden.crop_book_intro","\u041E\u0431\u044B\u0447\u043D\u044B\u0435 \u0440\u0430\u0431\u043E\u0442\u044B \u0441\u0430\u043C\u0438 \u0441\u0442\u0430\u0432\u044F\u0442 \u0447\u0435\u0442\u044B\u0440\u0435 \u043F\u0435\u0447\u0430\u0442\u0438 \u043A\u0430\u0436\u0434\u043E\u0439 \u043A\u0443\u043B\u044C\u0442\u0443\u0440\u0435. \u0421\u0440\u043E\u043A\u0430 \u0438 \u0448\u0442\u0440\u0430\u0444\u0430 \u043D\u0435\u0442.")}</p></div><strong>${Number(book.stamps)}/${Number(book.stamps_total)}</strong></header>
225        <div class="garden-crop-book-legend">${stampDefs.map(([,icon,label])=>`<span>${Icons.render(icon,13)} ${Utils.esc(label)}</span>`).join("")}</div>
226        <div class="garden-crop-book-rows">${rows}</div>
227        <section class="garden-crop-book-badges"><h4>${I18n.t("garden.mini_achievements","\u041C\u0438\u043D\u0438-\u0434\u043E\u0441\u0442\u0438\u0436\u0435\u043D\u0438\u044F")}</h4><div>${badges}</div></section>
228      </div>
229    </div>`)},async loadLeaderboard(){try{const data=await Api.garden.leaderboard();this._leaderboard=data.leaderboard||[],this._leaderboardMe=data.me||null,this._limits=data.limits||null,this.renderLeaderboard(this._leaderboard,this._leaderboardMe),this.renderLimits(this._limits)}catch{const lb=document.getElementById("garden-leaderboard");lb&&(lb.innerHTML=`<div class="garden-empty">${I18n.t("garden.leaderboard_err","\u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043D\u0435 \u0441\u043C\u043E\u0433\u043B\u0430 \u043F\u043E\u0434\u043D\u044F\u0442\u044C \u0414\u043E\u0441\u043A\u0443 \u043F\u043E\u0447\u0451\u0442\u0430. \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u0437\u0436\u0435.")}</div>`);const lim=document.getElementById("garden-limits");lim&&lim.querySelector(".garden-spin")&&(lim.innerHTML=`<p class="garden-limit-summary">${I18n.t("garden.limit_unavailable","\u041B\u0438\u0447\u043D\u044B\u0439 \u043E\u0441\u0442\u0430\u0442\u043E\u043A \u0441\u0435\u0439\u0447\u0430\u0441 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D. \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u0437\u0436\u0435.")}</p>`)}},_scheduleAccountRefresh(){clearTimeout(this._accountRefreshTimer),this._accountRefreshTimer=setTimeout(()=>this.loadLeaderboard(),350)},setScoreFormat(format){this._scoreFormat=format==="compact"?"compact":"exact";try{localStorage.setItem("garden_score_format",this._scoreFormat)}catch{}this._syncScoreFormat(),this.renderSeason(),this.renderLeaderboard(this._leaderboard,this._leaderboardMe),this.renderLimits(this._limits),this.renderPen()},_syncScoreFormat(){document.querySelectorAll(".garden-score-switch button[data-format]").forEach(btn=>{const active=btn.dataset.format===this._scoreFormat;btn.classList.toggle("is-active",active),btn.setAttribute("aria-pressed",active?"true":"false")})},formatProduce(value){const base=Number(value)||0;return this._scoreFormat==="compact"&&base>=1e6?I18n.t("garden.produce_millions",{count:I18n.formatNumber(base/1e6,{minimumFractionDigits:1,maximumFractionDigits:1})}):this._scoreFormat==="compact"&&base>=1e3?I18n.t("garden.produce_thousands",{count:I18n.formatNumber(base/1e3,{minimumFractionDigits:1,maximumFractionDigits:1})}):I18n.t("garden.produce_exact",{count:I18n.formatNumber(base)})},async loadPastSeasons(){const box=document.getElementById("garden-past");if(!(!box||box.dataset.loading==="1")){box.dataset.loading="1",box.innerHTML='<div class="garden-spin"></div>';
229try{const data=await Api.garden.seasons(8,3);this.renderPastSeasons(data&&data.seasons)}catch{box.innerHTML=`<div class="garden-empty">${Utils.esc(I18n.t("garden.past_error","\u0412\u0435\u0434\u043E\u043C\u043E\u0441\u0442\u0438 \u043F\u0440\u043E\u0448\u043B\u044B\u0445 \u0441\u0435\u0437\u043E\u043D\u043E\u0432 \u0441\u0435\u0439\u0447\u0430\u0441 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B."))}</div>`}finally{box.dataset.loading=""}}},renderPastSeasons(seasons){const box=document.getElementById("garden-past");if(box){if(!seasons||!seasons.length){box.innerHTML=`<div class="garden-empty">${I18n.t("garden.past_empty","\u041F\u0440\u043E\u0448\u043B\u044B\u0445 \u0441\u0435\u0437\u043E\u043D\u043E\u0432 \u043F\u043E\u043A\u0430 \u043D\u0435\u0442 \u2014 \u044D\u0442\u043E\u0442 \u043F\u0435\u0440\u0432\u044B\u0439.")}</div>`;return}box.innerHTML=seasons.map(s=>{const heads=(s.top||[]).map((it,i)=>{const name=Utils.localizedDisplayName?Utils.localizedDisplayName(it.name||it.username,""):it.name;return`<a class="garden-past-hero" href="#/profile/${it.id}">
230          <b>${["\u2460","\u2461","\u2462"][i]||i+1}</b>
231          <span>${Utils.esc(name)}</span>
232          <small>${this.formatProduce(it.points)}</small>
233        </a>`}).join(""),line=I18n.t("garden.past_line",{progress:this.formatProduce(s.progress),target:this.formatProduce(s.target),workers:s.workers});return`<section class="garden-past-season">
234        <div class="garden-past-head">
235          <b>${I18n.t("garden.past_season_no",{roman:Utils.esc(s.roman||String(s.no))})}</b>
236          <small>${Utils.esc(line)}</small>
237        </div>
238        ${heads?`<div class="garden-past-heroes">${heads}</div>`:`<div class="garden-empty">${I18n.t("garden.past_nobody","\u0412 \u044D\u0442\u043E\u0442 \u0441\u0435\u0437\u043E\u043D \u0437\u0430 \u043B\u043E\u043F\u0430\u0442\u0443 \u043D\u0438\u043A\u0442\u043E \u043D\u0435 \u0432\u0437\u044F\u043B\u0441\u044F.")}</div>`}
239      </section>`}).join("")}},renderLeaderboard(lb,me){const el=document.getElementById("garden-leaderboard");if(!el)return;if(!lb||!lb.length){el.innerHTML=me?this.leaderboardRow(me,!0):`<div class="garden-empty">${I18n.t("garden.leaderboard_empty","\u0414\u043E\u0441\u043A\u0430 \u043F\u043E\u0447\u0451\u0442\u0430 \u043F\u0443\u0441\u0442\u0430.<br>\u041D\u0438 \u043E\u0434\u0438\u043D \u0415\u0433\u043E\u0440 \u0435\u0449\u0451 \u043D\u0435 \u0431\u0440\u0430\u043B\u0441\u044F \u0437\u0430 \u043B\u043E\u043F\u0430\u0442\u0443.")}</div>`;return}const top=lb.slice(0,10),ownOutside=me&&!top.some(row=>row.id===me.id);el.innerHTML=top.map(it=>this.leaderboardRow(it,App.state.user&&App.state.user.id===it.id)).join("")+(ownOutside?`<div class="garden-lb-gap" aria-hidden="true">\xB7&nbsp; \xB7&nbsp; \xB7</div>${this.leaderboardRow(me,!0)}`:"")},leaderboardRow(it,mine){const rank=Number(it.rank)||0,place=rank?rank<=3?["\u2460","\u2461","\u2462"][rank-1]:rank:"\u2014",placeLabel=rank?I18n.t("garden.place_value",{rank}):I18n.t("garden.no_place_yet","\u041F\u043E\u043A\u0430 \u0431\u0435\u0437 \u043C\u0435\u0441\u0442\u0430"),displayName=Utils.localizedDisplayName?Utils.localizedDisplayName(it.name||it.username,""):it.name,rowLabel=I18n.t("garden.leaderboard_row_aria",{mine:mine?I18n.t("garden.your_row","\u0412\u0430\u0448\u0430 \u0441\u0442\u0440\u043E\u043A\u0430. "):"",place:placeLabel,name:displayName}),exactPoints=I18n.formatNumber(Number(it.points)||0);return`
240      <div class="garden-lb-row${rank>0&&rank<=3?" is-top":""}${mine?" is-me":""}" onclick="App.navigate('#/profile/${it.id}')" ${Utils.clickable()} aria-label="${Utils.esc(rowLabel)}">
241        <div class="garden-lb-rank">${place}</div>
242        ${Utils.getAvatar({avatar_url:it.avatar_url,name:it.name,role:it.role,party_color:it.party_color,party_name:it.party_name},28)}
243        <div class="garden-lb-name">${Utils.userNameHtml(it)}</div>
244        <div class="garden-lb-pts" title="${Utils.esc(I18n.t("garden.exact_contribution",{points:exactPoints}))}">${this.formatProduce(it.points)}</div>
245      </div>
246    `},renderLimits(limits){const el=document.getElementById("garden-limits");if(!el||!limits)return;const points=limits.points||{},guest=points.used==null,capEnabled=Number(points.cap)>0,limitReached=!guest&&capEnabled&&Number(points.used)>=Number(points.cap),remaining=!guest&&capEnabled?Math.max(0,Number(points.cap)-Number(points.used)):null;let summary=I18n.t("garden.limit_guest","\u0412\u043E\u0439\u0434\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0443\u0432\u0438\u0434\u0435\u0442\u044C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0439 \u043E\u0441\u0442\u0430\u0442\u043E\u043A \u0441\u0435\u0437\u043E\u043D\u043D\u044B\u0445 \u043E\u0447\u043A\u043E\u0432.");!guest&&!capEnabled?summary=I18n.t("garden.limit_unlimited","\u0421\u0435\u0437\u043E\u043D\u043D\u044B\u0435 \u043E\u0447\u043A\u0438 \u043D\u0430\u0447\u0438\u0441\u043B\u044F\u044E\u0442\u0441\u044F \u0431\u0435\u0437 \u0441\u0443\u0442\u043E\u0447\u043D\u043E\u0433\u043E \u043F\u043E\u0442\u043E\u043B\u043A\u0430."):!guest&&limitReached&&points.nextReleaseAt&&points.nextReleaseAt*1e3>Date.now()?summary=I18n.t("garden.limit_exhausted_in",{duration:this._until(points.nextReleaseAt)}):!guest&&limitReached?summary=I18n.t("garden.limit_refreshing","\u0421\u0443\u0442\u043E\u0447\u043D\u044B\u0439 \u043B\u0438\u043C\u0438\u0442 \u0438\u0441\u0447\u0435\u0440\u043F\u0430\u043D. \u041E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u043C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0439 \u043E\u0441\u0442\u0430\u0442\u043E\u043A\u2026"):guest||(summary=I18n.t("garden.limit_remaining",{remaining:this.formatProduce(remaining)})),el.innerHTML=`
247      <p class="garden-limit-summary">${summary}</p>
248    `},_until(unixSeconds){let seconds=Math.max(0,Math.ceil(Number(unixSeconds)-Date.now()/1e3));const hours=Math.floor(seconds/3600);seconds%=3600;const minutes=Math.floor(seconds/60),secs=seconds%60;return hours?I18n.t("garden.duration_hours_minutes",{hours,minutes}):minutes?I18n.t("garden.duration_minutes_seconds",{minutes,seconds:secs}):I18n.t("garden.duration_seconds",{seconds:secs})}
248,async initChat(chatId){if(this._chatId===chatId)return;this._chatId=chatId,SocketClient.joinChat(chatId);const note=document.getElementById("garden-chat-note"),input=document.getElementById("garden-chat-input");!App.can("chat")&&input&&(input.disabled=!0,input.placeholder=I18n.t("garden.chat_readonly_placeholder","\u0411\u0435\u0441\u0435\u0434\u043A\u0430 \u2014 \u0434\u043B\u044F \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\u043D\u044B\u0445 \u0415\u0433\u043E\u0440\u043E\u0432"),note&&(note.textContent=I18n.t("garden.readonly","\u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u0435\u043D\u0438\u0435")));try{const{messages}=await Api.chats.messages(chatId,{limit:40});this.renderChatLog(messages)}catch{const log=document.getElementById("garden-chat-log");log&&(log.innerHTML=`<div class="garden-empty">${I18n.t("garden.gazebo_error","\u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u044F \u043D\u0435 \u0441\u043C\u043E\u0433\u043B\u0430 \u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0411\u0435\u0441\u0435\u0434\u043A\u0443. \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u0437\u0436\u0435.")}</div>`)}},renderChatLog(messages){const log=document.getElementById("garden-chat-log");if(log){if(!messages||!messages.length){log.innerHTML=`<div class="garden-empty">${I18n.t("garden.chat_empty","\u0422\u0438\u0448\u0438\u043D\u0430 \u0443 \u043F\u043B\u0435\u0442\u043D\u044F.<br>\u0421\u043A\u0430\u0436\u0438\u0442\u0435 \u0441\u043B\u043E\u0432\u043E \u0441\u043E\u0441\u0435\u0434\u044F\u043C \u043F\u043E \u0433\u0440\u044F\u0434\u043A\u0435.")}</div>`;return}log.innerHTML=messages.map(m=>this.chatRow(m)).join(""),log.scrollTop=log.scrollHeight}},chatRow(m){const me=App.state.user&&App.state.user.id===m.user_id,go=`onclick="App.navigate('#/profile/${m.user_id}')" ${Utils.clickable()}`;return`
249      <div class="garden-msg${me?" is-me":""}">
250        <span ${go} aria-label="${Utils.esc(I18n.t("garden.open_profile",{name:m.name}))}">${Utils.getAvatar({avatar_url:m.avatar_url,name:m.name,role:m.role},26)}</span>
251        <div class="garden-msg-body">
252          <div class="garden-msg-head"><span class="garden-msg-name" ${go}>${Utils.userNameHtml(m)}</span>
253            <span class="garden-msg-time">${Utils.timeAgo(m.created_at)}</span></div>
254          <div class="garden-msg-text">${Utils.esc(m.content)}</div>
255        </div>
256      </div>`},_onChatMessage(d){const m=d&&d.message;if(!m||!this._chatId||m.chat_id!==this._chatId)return;const log=document.getElementById("garden-chat-log");if(!log)return;log.querySelector(".garden-empty")&&(log.innerHTML="");const near=log.scrollHeight-log.scrollTop-log.clientHeight<60;log.insertAdjacentHTML("beforeend",this.chatRow(m)),near&&(log.scrollTop=log.scrollHeight)},sendChat(){const input=document.getElementById("garden-chat-input");if(!input||input.disabled)return;const text=input.value.trim();!text||!this._chatId||(SocketClient.sendMessage(this._chatId,text),input.value="")},layout(){const canvas=document.getElementById("garden-canvas");if(!canvas||!this.state)return!1;const{w,h}=this.state;(w<4||h<3)&&this._lastWarnGrid!==w+"x"+h&&(this._lastWarnGrid=w+"x"+h,console.warn(`[garden] \u0441\u0435\u0440\u0432\u0435\u0440 \u043F\u0440\u0438\u0441\u043B\u0430\u043B \u0441\u0435\u0442\u043A\u0443 ${w}\xD7${h} (cells=${this.state.cells?this.state.cells.length:"?"}). \u041E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C \u22654\xD73. \u0418\u0441\u0442\u043E\u0447\u043D\u0438\u043A \u2014 applyState \u043E\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430; \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043D\u044B\u0439 \u043F\u0440\u043E\u0446\u0435\u0441\u0441.`));const dpr=window.devicePixelRatio||1,cssW=Math.round(canvas.clientWidth||canvas.parentElement.clientWidth||0);if(cssW<80)return canvas.width!==0&&(canvas.width=0,canvas.height=0),this._geom=null,!1;const pad=Math.max(5,Math.round(cssW*.012)),MAX_CELL=104,MIN_CELL=22;let size=Math.floor((cssW-pad*(w+1))/w);size=Math.max(MIN_CELL,Math.min(size,MAX_CELL));const sceneTop=Math.max(38,Math.min(58,Math.round(size*.62))),sceneBottom=Math.max(18,Math.min(30,Math.round(size*.28))),gridH=size*h+pad*(h+1),cssH=sceneTop+gridH+sceneBottom,offX=Math.max(0,Math.floor((cssW-(w*size+(w+1)*pad))/2));return this._geom={pad,size,cols:w,rows:h,cssW,cssH,dpr,offX,gridY:sceneTop,gridH,sceneBottom},canvas.width=Math.round(cssW*dpr),canvas.height=Math.round(cssH*dpr),canvas.style.height=cssH+"px",!0},draw(){const canvas=document.getElementById("garden-canvas");if(!canvas||!this.state)return;const cw=Math.round(canvas.clientWidth||0),dpr=window.devicePixelRatio||1;if((!this._geom||this._geom.cssW!==cw||canvas.width!==Math.round(cw*dpr))&&!this.layout())return;const g=this._geom,cells=this.state.cells,ctx=canvas.getContext("2d");ctx.setTransform(g.dpr,0,0,g.dpr,0,0),ctx.clearRect(0,0,g.cssW,g.cssH);const t=this._animationNow(),nowSec=Math.floor(Date.now()/1e3),intro=t-this._introAt,weeds=this._weedClusterData(cells,g.cols,g.rows);this.drawGardenScene(ctx,g,t,!1),this.drawWeedConnections(ctx,g,cells,weeds);for(let r=0;r<g.rows;r++)for(let c=0;c<g.cols;c++){const i=r*g.cols+c,x=g.offX+g.pad+c*(g.size+g.pad),y=g.gridY+g.pad+r*(g.size+g.pad),appear=this._reduceMotion?1:Math.max(0,Math.min(1,(intro-i*9)/260));this.drawCell(ctx,cells[i],i,x,y,g.size,t,nowSec,appear,weeds.sizes[i]||0,!!weeds.leaders[i])}this.drawGardenScene(ctx,g,t,!0)},_weedClusterData(cells,cols,rows){const visited=new Set,clusters=[],sizes={},leaders={},total=Math.min(cells.length,cols*rows);for(let start=0;start<total;start++){if(visited.has(start)||!cells[start]||cells[start].s!=="weeds")continue;const group=[],queue=[start];for(visited.add(start);queue.length;){const index=queue.shift();group.push(index);const x=index%cols,y=Math.floor(index/cols),neighbors=[x>0?index-1:-1,x+1<cols?index+1:-1,y>0?index-cols:-1,y+1<rows?index+cols:-1];for(const next of neighbors)next<0||next>=total||visited.has(next)||!cells[next]||cells[next].s!=="weeds"||(visited.add(next),queue.push(next))}group.sort((a,b)=>
256a-b),clusters.push(group),leaders[group[0]]=!0;for(const index of group)sizes[index]=group.length}return{clusters,sizes,leaders}},_gardenSceneState(){const civic=this.state&&this.state.civic;if(!civic)return null;const stage=Math.max(Number(civic.beautification&&civic.beautification.daily_stage)||0,Number(civic.beautification&&civic.beautification.season_stage)||0),timeOfDay=this._gardenTimeOfDay(),calendar=this._gardenCalendarSeason();return{weather:civic.weather&&civic.weather.code||null,timeOfDay,calendar,cropMotion:this._reduceMotion?"off":civic.weather&&civic.weather.code==="rain"?"rain-lean":civic.weather&&["cool","fair"].includes(civic.weather.code)?"breeze":"still",stage,celebrating:this._civicCeremonyActive(),features:["bounds",...stage>=1?["sign"]:[],...stage>=2?["fence"]:[],...stage>=3?["shed"]:[],...stage>=4?["lanterns"]:[]]}},_gardenCalendarSeason(referenceMs=Date.now()+this._timeOffset){let month=new Date(Number(referenceMs)+108e5).getUTCMonth()+1;if(typeof location<"u"&&["localhost","127.0.0.1"].includes(location.hostname)){const qaMonth=Number(new URLSearchParams(location.search).get("garden_month"));Number.isInteger(qaMonth)&&qaMonth>=1&&qaMonth<=12&&(month=qaMonth)}const code=month===12||month<=2?"winter":month<=5?"spring":month<=8?"summer":"autumn",names={winter:["garden.calendar_winter","\u0417\u0438\u043C\u0430"],spring:["garden.calendar_spring","\u0412\u0435\u0441\u043D\u0430"],summer:["garden.calendar_summer","\u041B\u0435\u0442\u043E"],autumn:["garden.calendar_autumn","\u041E\u0441\u0435\u043D\u044C"]},[key,fallback]=names[code];return{code,name:this._text(key,fallback),month}},_gardenTimeOfDay(referenceMs=Date.now()+this._timeOffset){if(typeof location<"u"&&["localhost","127.0.0.1"].includes(location.hostname)){const qa=new URLSearchParams(location.search).get("garden_time"),match=/^(\d{1,2}):(\d{2})$/.exec(qa||"");if(match&&Number(match[1])<24&&Number(match[2])<60){const fixed=new Date(Number(referenceMs)+108e5);fixed.setUTCHours(Number(match[1]),Number(match[2]),0,0),referenceMs=fixed.getTime()-108e5}}const moscow=new Date(Number(referenceMs)+3*60*60*1e3),hour=moscow.getUTCHours(),minute=moscow.getUTCMinutes(),second=moscow.getUTCSeconds(),minutes=hour*60+minute+second/60,ease=value=>{const x=Math.max(0,Math.min(1,value));return x*x*(3-2*x)};let code="night",progress=1,night=1,warmth=0;minutes>=300&&minutes<480?(code="dawn",progress=ease((minutes-300)/180),night=1-progress,warmth=Math.sin(progress*Math.PI)):minutes>=480&&minutes<1080?(code="day",progress=(minutes-480)/600,night=0):minutes>=1080&&minutes<1320&&(code="dusk",progress=ease((minutes-1080)/240),night=progress,warmth=Math.sin(progress*Math.PI));const stars=Math.max(0,Math.min(1,(night-.28)/.72)),names={night:["garden.time_night","\u041D\u043E\u0447\u044C"],dawn:["garden.time_dawn","\u0420\u0430\u0441\u0441\u0432\u0435\u0442"],day:["garden.time_day","\u0414\u0435\u043D\u044C"],dusk:["garden.time_dusk","\u0417\u0430\u043A\u0430\u0442"]},[nameKey,nameFallback]=names[code];return{code,name:this._text(nameKey,nameFallback),timeMsk:`${String(hour).padStart(2,"0")}:${String(minute).padStart(2,"0")}`,progress:Math.round(progress*1e3)/1e3,night:Math.round(night*1e3)/1e3,warmth:Math.round(warmth*1e3)/1e3,stars:Math.round(stars*1e3)/1e3,lanterns:Math.round(night*1e3)/1e3}},_mixGardenColor(from,to,amount){const a=Math.max(0,Math.min(1,Number(amount)||0)),rgb=hex=>[1,3,5].map(start=>parseInt(hex.slice(start,start+2),16)),left=rgb(from),right=rgb(to);return"#"+left.map((value,i)=>Math.round(value+(right[i]-value)*a).toString(16).padStart(2,"0")).join("")},_gardenSkyPalette(weather,dark,timeOfDay,calendar=null){const day=dark?weather==="rain"?["#26333a","#222b25"]:weather==="sun"?["#403924","#292d22"]:["#2d3428","#242a22"]:weather==="rain"?["#809b9d","#61785e"]:weather==="sun"?["#c7b477","#809667"]:["#9dac83","#758b67"],night=dark?["#111827","#172522"]:["#263a58","#354f43"],warm=timeOfDay.code==="dawn"?dark?["#765460","#3f514a"]:["#d59a7f","#7c987b"]:dark?["#774437","#38443f"]:["#ce765d","#677764"],base=day.map((color,i)=>this._mixGardenColor(color,night[i],timeOfDay.night)),warmth=timeOfDay.warmth*(dark?.32:.48),lit=base.map((color,i)=>this._mixGardenColor(color,warm[i],warmth)),season=calendar&&calendar.code,seasonTint=season==="winter"?dark?["#334253","#2a3b3d"]:["#a8c0c7","#789494"]:season==="spring"?dark?["#35453b","#293a31"]:["#abc39a","#7e9e76"]:season==="autumn"?dark?["#4b3e31","#32352c"]:["#bd966c","#7d8061"]:null,strength=season==="winter"?.2:seasonTint?.11:0;return seasonTint?lit.map((color,i)=>this._mixGardenColor(color,seasonTint[i],strength)):lit},drawGardenScene(ctx,g,t,front){const scene=this._gardenSceneState();if(!scene)return;const dark=document.documentElement.getAttribute("data-theme")==="dark",left=g.offX+g.pad,right=left+g.cols*g.size+(g.cols-1)*g.pad,top=g.gridY+g.pad,bottom=top+g.rows*g.size+(g.rows-1)*g.pad,weather=scene.weather,timeOfDay=scene.timeOfDay,calendar=scene.calendar;if(!front){const palette=this._gardenSkyPalette(weather,dark,timeOfDay,calendar),bg=ctx.createLinearGradient(0,0,0,g.cssH);if(bg.addColorStop(0,palette[0]),bg.addColorStop(1,palette[1]),ctx.fillStyle=bg,ctx.fillRect(0,0,g.cssW,g.cssH),this.drawGardenCalendarSeason(ctx,g,calendar,dark,t,!1),this.drawGardenNightSky(ctx,g,timeOfDay,weather,dark),weather==="sun"&&timeOfDay.night<.86){const sx=g.cssW*.52,horizon=timeOfDay.code==="dawn"||timeOfDay.code==="dusk",sy=Math.max(12,g.gridY*(horizon?.62:.34)),glow=ctx.createRadialGradient(sx,sy,2,sx,sy,g.gridY*.8),sunAlpha=Math.max(0,1-timeOfDay.night);glow.addColorStop(0,`rgba(255,220,135,${.72*sunAlpha})`),glow.addColorStop(1,"rgba(255,235,150,0)"),ctx.fillStyle=glow,ctx.beginPath(),ctx.arc(sx,sy,g.gridY*.8,0,Math.PI*2),ctx.fill(),ctx.globalAlpha=sunAlpha,ctx.fillStyle=horizon?"#efb56f":"#ead88d",ctx.beginPath(),ctx.arc(sx,sy,Math.max(7,g.gridY*.17),0,Math.PI*2),ctx.fill(),ctx.globalAlpha=1}else weather==="cool"||weather==="rain"?this.drawGardenCloud(ctx,g.cssW*.48,g.gridY*.36,Math.max(18,g.gridY*.42),weather==="rain"):weather==="fair"&&this.drawGardenBunting(ctx,left+(right-left)*.34,right-(right-left)*.24,Math.max(9,g.gridY*.22));ctx.fillStyle=dark?"rgba(211,190,141,.12)":"rgba(227,206,151,.28)";for(let r=1;r<g.rows;r++){const y=top+r*g.size+(r-.5)*g.pad;ctx.fillRect(left,y-Math.max(1,g.pad*.18),right-left,Math.max(2,g.pad*.36))}if(scene.stage>=2&&this.drawGardenFence(ctx,left,right,top,bottom,dark),scene.stage>=1&&this.drawGardenSign(ctx,left+Math.max(5,g.pad),Math.max(5,g.gridY*.12),g,dark),scene.stage>=3&&this.drawGardenShed(ctx,right-Math.max(48,g.size*.58),Math.max(4,g.gridY-Math.max(43,g.size*.52)),Math.max(48,g.size*.58),dark,timeOfDay.lanterns),scene.stage>=4){const lanternY=Math.max(5,g.gridY*.12);this.drawGardenLantern(ctx,left+(right-left)*.3,lanternY,dark,t,timeOfDay.lanterns),this.drawGardenLantern(ctx,left+(right-left)*.7,lanternY,dark,t,timeOfDay.lanterns)}timeOfDay.code==="dawn"&&this.drawGardenDawnMist(ctx,g,timeOfDay.warmth,dark);return}if(timeOfDay.night>0&&(ctx.fillStyle=`rgba(12,24,48,${timeOfDay.night*(dark?.08:.15)})`,ctx.fillRect(0,g.gridY*.72,g.cssW,g.cssH-g.gridY*.72)),this.drawGardenCalendarSeason(ctx,g,calendar,dark,t,!0),weather==="rain"){const drift=this._reduceMotion?0:t/28%58;ctx.save(),ctx.strokeStyle=dark?"rgba(169,207,224,.22)":"rgba(225,245,250,.34)",ctx.lineWidth=1.2,ctx.lineCap="round";for(let i=0;i<22;i++){const x=(i*53+drift)%(g.cssW+36)-18,y=(i*79+drift*1.8)%(g.cssH+32)-16;ctx.beginPath(),ctx.moveTo(x,y),ctx.lineTo(x-5,y+12),ctx.stroke()}
256ctx.restore()}scene.celebrating&&this.drawGardenCelebration(ctx,g,t)},drawGardenCalendarSeason(ctx,g,calendar,dark,t,front){if(!calendar)return;const code=calendar.code,left=g.offX+g.pad,right=left+g.cols*g.size+(g.cols-1)*g.pad,bottom=g.gridY+g.gridH;if(ctx.save(),!front){if(code==="winter")ctx.fillStyle=dark?"rgba(201,218,224,.36)":"rgba(240,247,245,.72)",ctx.fillRect(left-4,g.gridY-3,right-left+8,3),ctx.fillRect(left-5,bottom+6,right-left+10,4);else if(code==="spring"||code==="summer"){const grass=code==="spring"?"#668158":"#587748";ctx.strokeStyle=grass,ctx.lineWidth=1.4;for(let i=0;i<18;i++){const x=left+(right-left)*(i+.5)/18,h=3+i%4;ctx.beginPath(),ctx.moveTo(x,bottom+8),ctx.lineTo(x-2,bottom+8-h),ctx.stroke(),ctx.beginPath(),ctx.moveTo(x,bottom+8),ctx.lineTo(x+2,bottom+7-h*.8),ctx.stroke()}}ctx.restore();return}if(code==="spring"){const colors=["#f3dfdf","#e8bdc5","#f5edcf"];for(let i=0;i<11;i++){const x=left+(right-left)*(i*37%101/100),y=bottom+5+i%3*3;ctx.fillStyle=colors[i%colors.length],ctx.beginPath(),ctx.arc(x,y,1.5+i%2*.5,0,Math.PI*2),ctx.fill()}}else if(code==="summer")for(let i=0;i<9;i++){const x=left+(right-left)*(i*43%97/96),y=bottom+5+i%2*4;ctx.fillStyle=i%3?"#e7cf72":"#f1ead0",ctx.beginPath(),ctx.arc(x,y,1.4,0,Math.PI*2),ctx.fill()}else if(code==="autumn"){const drift=this._reduceMotion?0:t/90%Math.max(1,g.cssW),colors=["#c4793d","#a95736","#d2a24a","#8d6638"];for(let i=0;i<12;i++){const x=(i*83+drift*(.35+i%3*.12))%(g.cssW+30)-15,y=7+(i*29+(this._reduceMotion?0:t/150))%Math.max(12,g.gridY*.72);ctx.save(),ctx.translate(x,y),ctx.rotate(i*.8+(this._reduceMotion?0:t/1700)),ctx.fillStyle=colors[i%colors.length],ctx.beginPath(),ctx.ellipse(0,0,3.2,1.7,0,0,Math.PI*2),ctx.fill(),ctx.restore()}}else if(code==="winter"){ctx.fillStyle=dark?"rgba(221,235,239,.7)":"rgba(255,255,255,.86)";for(let i=0;i<14;i++){const x=left+(right-left)*(i*47%103/102),y=5+i%4*Math.max(4,g.gridY*.13);ctx.beginPath(),ctx.arc(x,y,1+i%3*.35,0,Math.PI*2),ctx.fill()}}ctx.restore()},drawGardenNightSky(ctx,g,timeOfDay,weather,dark){const alpha=timeOfDay.stars;if(alpha<=0)return;const weatherAlpha=weather==="rain"?.12:weather==="cool"?.42:1;ctx.save(),ctx.globalAlpha=alpha*weatherAlpha;const topH=Math.max(28,g.gridY*.82),stars=[[.08,.24,1.1],[.16,.56,.8],[.28,.18,1.4],[.37,.48,.75],[.61,.22,1.2],[.7,.53,.8],[.79,.17,1.35],[.89,.44,.9],[.47,.13,.7],[.56,.62,.7]];ctx.fillStyle=dark?"#dce8f3":"#fff3c7";for(const[px,py,radius]of stars)ctx.beginPath(),ctx.arc(g.cssW*px,topH*py,radius,0,Math.PI*2),ctx.fill();if(weather!=="rain"){const x=g.cssW*.53,y=Math.max(12,g.gridY*.34),radius=Math.max(6,g.gridY*.14);ctx.fillStyle="#f1e6bd",ctx.beginPath(),ctx.arc(x,y,radius,0,Math.PI*2),ctx.fill(),ctx.fillStyle=dark?"#172522":"#2f4650",ctx.beginPath(),ctx.arc(x+radius*.42,y-radius*.16,radius*.9,0,Math.PI*2),ctx.fill()}ctx.restore()},drawGardenDawnMist(ctx,g,strength,dark){if(strength<=0)return;ctx.save(),ctx.globalAlpha=strength*(dark?.12:.2);const mist=ctx.createLinearGradient(0,g.gridY*.55,0,g.gridY+g.gridH*.32);mist.addColorStop(0,"rgba(255,244,220,0)"),mist.addColorStop(.5,"rgba(255,244,220,.85)"),mist.addColorStop(1,"rgba(255,244,220,0)"),ctx.fillStyle=mist,ctx.fillRect(0,g.gridY*.45,g.cssW,g.gridY+g.gridH*.32),ctx.restore()},drawGardenCelebration(ctx,g,t){const ceremony=this._civicCeremony;if(!ceremony)return;const elapsed=Math.max(0,t-ceremony.startedAt),remaining=Math.max(0,ceremony.until-t),alpha=Math.min(1,elapsed/360,remaining/650);if(alpha<=0)return;const left=g.offX+g.pad,right=left+g.cols*g.size+(g.cols-1)*g.pad;ctx.save(),ctx.globalAlpha=alpha,this.drawGardenBunting(ctx,left+7,right-7,Math.max(12,g.gridY*.72)),ctx.strokeStyle="rgba(255,221,128,.82)",ctx.lineWidth=2.5,ctx.strokeRect(2,2,Math.max(0,g.cssW-4),Math.max(0,g.cssH-4));const travel=this._reduceMotion?0:elapsed/18,colors=["#f6d675","#fff1af","#e8a95b","#d8e7a1"];for(let i=0;i<18;i++){const x=left+(i*71+19)%Math.max(1,right-left),y=this._reduceMotion?g.gridY+i*43%Math.max(1,g.cssH-g.gridY):g.cssH-(travel+i*47)%Math.max(1,g.cssH-8),radius=2.3+i%3*.9;ctx.fillStyle=colors[i%colors.length],ctx.beginPath(),ctx.arc(x,y,radius,0,Math.PI*2),ctx.fill(),i%4===0&&(ctx.strokeStyle=colors[(i+1)%colors.length],ctx.lineWidth=1,ctx.beginPath(),ctx.moveTo(x-4,y),ctx.lineTo(x+4,y),ctx.moveTo(x,y-4),ctx.lineTo(x,y+4),ctx.stroke())}
256ctx.restore()},drawGardenCloud(ctx,x,y,size,rainy){ctx.save(),ctx.fillStyle=rainy?"rgba(205,218,219,.46)":"rgba(239,236,213,.52)",ctx.beginPath(),ctx.arc(x-size*.25,y+size*.08,size*.22,0,Math.PI*2),ctx.arc(x,y-size*.05,size*.3,0,Math.PI*2),ctx.arc(x+size*.28,y+size*.08,size*.2,0,Math.PI*2),ctx.fillRect(x-size*.42,y+size*.05,size*.84,size*.24),ctx.fill(),ctx.restore()},drawGardenBunting(ctx,fromX,toX,y){ctx.save(),ctx.strokeStyle="rgba(72,58,35,.55)",ctx.lineWidth=1.2,ctx.beginPath(),ctx.moveTo(fromX,y),ctx.quadraticCurveTo((fromX+toX)/2,y+7,toX,y),ctx.stroke();const colors=["#b8553e","#d4ad50","#6f8a5a","#637ca1"];for(let i=0;i<7;i++){const x=fromX+(toX-fromX)*(i+.5)/7,yy=y+Math.sin((i+.5)/7*Math.PI)*6;ctx.fillStyle=colors[i%colors.length],ctx.beginPath(),ctx.moveTo(x-4,yy),ctx.lineTo(x+4,yy),ctx.lineTo(x,yy+8),ctx.closePath(),ctx.fill()}ctx.restore()},drawGardenFence(ctx,left,right,top,bottom,dark){ctx.save();const wood=dark?"#796044":"#92724d",edge=dark?"#403527":"#614a31";ctx.fillStyle=wood,ctx.strokeStyle=edge,ctx.lineWidth=1;const railY=bottom+8;ctx.fillRect(left-5,railY,right-left+10,5),ctx.strokeRect(left-5,railY,right-left+10,5);const count=Math.max(2,Math.round((right-left)/64));for(let i=0;i<=count;i++){const x=left+(right-left)*i/count;ctx.fillRect(x-3,railY-8,6,18),ctx.strokeRect(x-3,railY-8,6,18)}for(const x of[left-5,right+5])ctx.fillRect(x-3,top+5,6,17),ctx.strokeRect(x-3,top+5,6,17);ctx.restore()},drawGardenSign(ctx,x,y,g,dark){const w=Math.min(122,Math.max(82,g.cssW*.24)),h=Math.max(24,Math.min(31,g.gridY*.55));ctx.save(),ctx.fillStyle=dark?"#6f573d":"#9a774d",ctx.strokeStyle=dark?"#332b22":"#59432d",ctx.lineWidth=1.5,ctx.fillRect(x+9,y+h-1,4,Math.max(9,g.gridY-y-h+4)),ctx.fillRect(x+w-13,y+h-1,4,Math.max(9,g.gridY-y-h+4)),this.roundRect(ctx,x,y,w,h,5),ctx.fill(),ctx.stroke(),ctx.fillStyle="#f2e4bd",ctx.font=`700 ${Math.max(8,Math.round(h*.34))}px 'Golos Text', sans-serif`,ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillText(this._text("garden.canvas_shared_plot","\u041E\u0411\u0429\u0418\u0419 \u041D\u0410\u0414\u0415\u041B"),x+w/2,y+h/2+1),ctx.restore()},drawGardenShed(ctx,x,y,w,dark,light=0){const h=Math.max(32,w*.68);ctx.save(),ctx.fillStyle=dark?"#594634":"#876643",ctx.strokeStyle=dark?"#2c251e":"#503b28",ctx.lineWidth=1.4,ctx.fillRect(x+5,y+h*.28,w-10,h*.7),ctx.strokeRect(x+5,y+h*.28,w-10,h*.7),ctx.fillStyle=dark?"#7d553c":"#a86645",ctx.beginPath(),ctx.moveTo(x,y+h*.32),ctx.lineTo(x+w/2,y),ctx.lineTo(x+w,y+h*.32),ctx.closePath(),ctx.fill(),ctx.stroke(),ctx.fillStyle=light>.08?this._mixGardenColor(dark?"#302820":"#59432f","#e3b85e",light):dark?"#302820":"#59432f",ctx.fillRect(x+w*.4,y+h*.55,w*.2,h*.43),ctx.fillStyle="#d4b765",ctx.beginPath(),ctx.arc(x+w*.55,y+h*.75,1.3,0,Math.PI*2),ctx.fill(),ctx.restore()},drawGardenLantern(ctx,x,y,dark,t,light=0){const pulse=this._reduceMotion?1:.92+Math.sin(t/520+x)*.08;if(ctx.save(),light>.02){const glow=ctx.createRadialGradient(x,y+14,2,x,y+14,24*pulse);glow.addColorStop(0,`rgba(255,210,94,${.6*light})`),glow.addColorStop(1,"rgba(255,210,94,0)"),ctx.fillStyle=glow,ctx.beginPath(),ctx.arc(x,y+14,24*pulse,0,Math.PI*2),ctx.fill()}ctx.strokeStyle=dark?"#17191a":"#473d2d",ctx.lineWidth=2,ctx.beginPath(),ctx.moveTo(x,y-2),ctx.lineTo(x,y+8),ctx.stroke(),ctx.fillStyle=this._mixGardenColor("#78694b","#e4b447",light),ctx.strokeStyle="#4b3b27",ctx.lineWidth=1,this.roundRect(ctx,x-5,y+7,10,14,2),ctx.fill(),ctx.stroke(),ctx.restore()},drawWeedConnections(ctx,g,cells,weeds){ctx.save(),ctx.lineCap="round",ctx.lineJoin="round";for(let i=0;i<cells.length;i++){if(!cells[i]||cells[i].s!=="weeds"||(weeds.sizes[i]||0)<2)continue;const col=i%g.cols,row=Math.floor(i/g.cols),cx=g.offX+g.pad+col*(g.size+g.pad)+g.size/2,cy=g.gridY+g.pad+row*(g.size+g.pad)+g.size/2,neighbors=[];col+1<g.cols&&cells[i+1]&&cells[i+1].s==="weeds"&&neighbors.push([cx+g.size+g.pad,cy]),row+1<g.rows&&cells[i+g.cols]&&cells[i+g.cols].s==="weeds"&&neighbors.push([cx,cy+g.size+g.pad]);for(const[nx,ny]of neighbors){ctx.strokeStyle="#344827",ctx.lineWidth=Math.max(5,g.pad*1.25),ctx.beginPath(),ctx.moveTo(cx,cy),ctx.lineTo(nx,ny),ctx.stroke(),ctx.strokeStyle="#71864a",ctx.lineWidth=Math.max(1.5,g.pad*.34),ctx.beginPath(),ctx.moveTo(cx,cy),ctx.lineTo(nx,ny),ctx.stroke();const mx=(cx+nx)/2,my=(cy+ny)/2;ctx.fillStyle="#879653",ctx.save(),ctx.translate(mx,my),ctx.rotate(Math.atan2(ny-cy,nx-cx)+.55),ctx.beginPath(),ctx.moveTo(0,-g.pad*.72),ctx.lineTo(g.pad*.6,0),ctx.lineTo(0,g.pad*.72),ctx.lineTo(-g.pad*.6,0),ctx.closePath(),ctx.fill(),ctx.restore(
256)}}ctx.restore()},drawCell(ctx,cell,i,x,y,size,t,nowSec,appear,weedClusterSize=0,weedClusterLead=!1){if(appear<=0)return;const rad=Math.max(7,size*.18),hover=this._hover===i,ease=appear<1?1-Math.pow(1-appear,3):1;ctx.save(),ctx.globalAlpha=ease;const lift=(1-ease)*size*.25+(hover?-2:0);ctx.translate(0,lift);const weedy=cell.s==="weeds",waterEffect=this._activeWaterEffect(i,t),wetFreshness=this._wetSoilFreshness(cell,nowSec),wet=!!waterEffect||wetFreshness>0,g=ctx.createLinearGradient(x,y,x,y+size);weedy?(g.addColorStop(0,"#7c7148"),g.addColorStop(1,"#5d5436")):wet?(g.addColorStop(0,"#6d5a43"),g.addColorStop(1,"#494638")):(g.addColorStop(0,"#8a6647"),g.addColorStop(1,"#6b4d36")),ctx.fillStyle=g,this.roundRect(ctx,x,y,size,size,rad),ctx.fill(),ctx.fillStyle=weedy?"#52492f":wet?"#3f4436":"#5c4130",this.roundRect(ctx,x+size*.09,y+size*.09,size*.82,size*.82,rad*.7),ctx.fill(),ctx.strokeStyle="rgba(0,0,0,0.07)",ctx.lineWidth=1;for(let f=1;f<=3;f++){const fy=y+size*(.09+.205*f);ctx.beginPath(),ctx.moveTo(x+size*.14,fy),ctx.lineTo(x+size*.86,fy),ctx.stroke()}wet&&this.drawWetSoil(ctx,x,y,size,waterEffect?1:wetFreshness),waterEffect&&this.drawWaterEffect(ctx,waterEffect,x,y,size,t),hover?(ctx.strokeStyle="rgba(199,147,40,0.95)",ctx.lineWidth=Math.max(2,size*.04),this.roundRect(ctx,x+1.5,y+1.5,size-3,size-3,rad),ctx.stroke()):cell.s==="empty"&&(ctx.strokeStyle="rgba(255,255,255,0.10)",ctx.lineWidth=1.5,ctx.setLineDash([4,5]),this.roundRect(ctx,x+size*.16,y+size*.16,size*.68,size*.68,rad*.5),ctx.stroke(),ctx.setLineDash([]));const cx=x+size/2,cy=y+size/2;if(cell.s==="empty"){hover&&(ctx.fillStyle="rgba(255,255,255,0.5)",ctx.font=`${Math.round(size*.34)}px Golos Text, sans-serif`,ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillText("\uFF0B",cx,cy));const transition2=this._activeCropTransition(i,t);transition2&&transition2.type==="harvest"&&this.drawHarvestTransition(ctx,transition2,cx,cy,size,t),ctx.restore();return}const rm=this._reduceMotion,weatherTilt=this._cropWeatherTilt(i,t,cell),ripe=cell.s==="ripe",pulse=ripe&&!rm?1+Math.sin(t/420)*.05:1,emoji=this.stageEmoji(cell),transition=this._activeCropTransition(i,t);if(ctx.fillStyle="rgba(0,0,0,0.16)",ctx.beginPath(),ctx.ellipse(cx,y+size*.82,size*.22,size*.07,0,0,Math.PI*2),ctx.fill(),ripe){const ga=rm?.3:.28+Math.sin(t/320)*.12,rg=ctx.createRadialGradient(cx,cy,size*.1,cx,cy,size*.5);rg.addColorStop(0,`rgba(231,207,138,${ga})`),rg.addColorStop(1,"rgba(231,207,138,0)"),ctx.fillStyle=rg,ctx.beginPath(),ctx.arc(cx,cy,size*.5,0,Math.PI*2),ctx.fill()}const growing=cell.s==="seed"||cell.s==="sprout",cropArt=weedy?this._weedImg(weedClusterSize>1):ripe?this._cropImg(cell.c):growing?this._cropImg(cell.c,!0):null;if(growing&&transition&&transition.type==="plant"&&this.drawPlantTransition(ctx,transition,cx,cy,size,t),cropArt){let artScale=weedy?weedClusterSize>1?1.14:.92:growing?this.growthArtScale(cell,nowSec):pulse,artAlpha=1;if(ripe&&transition&&transition.type==="ripen"){const p=this.transitionProgress(transition,t);artScale*=.72+.28*this.easeOutCubic(p),artAlpha=.35+p*.65}else if(growing&&transition&&transition.type==="plant"){const p=this.easeOutCubic(this.transitionProgress(transition,t));artScale*=.18+p*.82,artAlpha=Math.max(.12,p)}this.drawCropArt(ctx,cropArt,cx,cy-size*.04,size,artScale,artAlpha,weatherTilt),ripe&&transition&&transition.type==="ripen"&&this.drawRipenFragments(ctx,transition,cx,cy-size*.04,size,t)}else ctx.font=`${Math.round(size*.46*pulse)}px serif`,ctx.textAlign="center",ctx.textBaseline="middle",ctx.save(),ctx.translate(cx,cy-size*.04),ctx.rotate(weatherTilt),ctx.fillText(emoji,0,0),ctx.restore();if(this.drawRing(ctx,cell,cx,cy,size,nowSec),growing&&this.drawCultivatorAvatar(ctx,x+size*.77,y+size*.23,size,this._avatarImg(cell.byAv),cell.by,.4),weedy&&(weedClusterSize<=1||weedClusterLead)){const mark=weedClusterSize>1?`\xD7${weedClusterSize}`:"!";ctx.fillStyle="#b4452f",ctx.font=`bold ${Math.round(size*.2)}px Golos Text, sans-serif`,ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillText(mark,x+size*.82,y+size*.2)}if(cell.by){const tagY=y+size-size*.16;ctx.fillStyle="rgba(26,32,48,0.62)",this.roundRect(ctx,x+size*.1,tagY-size*.11,size*.8,size*.2,size*.07),ctx.fill(),ctx.fillStyle="#f3e8cd",ctx.font=`600 ${Math.round(size*.12)}px 'Golos Text', sans-serif`,ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillText(this._short(cell.by,12),cx,tagY-size*.01)}
256ctx.restore();const fl=this._flash[i];fl&&fl.until>Date.now()?this.drawFlash(ctx,fl,x,y,size):fl&&delete this._flash[i]},_wetSoilFreshness(cell,nowSec){const wateredAt=Number(cell&&cell.wa)||0,age=nowSec-wateredAt;return!wateredAt||age<0||age>=this.WET_SOIL_SECONDS?0:Math.max(0,1-age/this.WET_SOIL_SECONDS)},_isRecentlyWatered(cell,nowSec){return this._wetSoilFreshness(cell,nowSec)>0},drawWetSoil(ctx,x,y,size,freshness=1){ctx.save(),ctx.globalAlpha*=.38+Math.max(0,Math.min(1,freshness))*.42;const sheen=ctx.createLinearGradient(x,y,x+size,y+size);sheen.addColorStop(0,"rgba(153,205,202,.06)"),sheen.addColorStop(.48,"rgba(121,184,187,.24)"),sheen.addColorStop(1,"rgba(76,126,139,.06)"),ctx.fillStyle=sheen,this.roundRect(ctx,x+size*.1,y+size*.1,size*.8,size*.8,size*.13),ctx.fill();const puddles=[[.31,.69,.16,.055],[.68,.35,.115,.043]];ctx.fillStyle="rgba(116,175,181,.22)",ctx.strokeStyle="rgba(190,224,215,.28)",ctx.lineWidth=Math.max(.8,size*.01);for(const[px,py,rx,ry]of puddles){const cx=x+size*px,cy=y+size*py,rw=size*rx,rh=size*ry;ctx.beginPath(),ctx.moveTo(cx-rw,cy),ctx.bezierCurveTo(cx-rw*.72,cy-rh*1.2,cx+rw*.25,cy-rh*.85,cx+rw,cy-rh*.08),ctx.bezierCurveTo(cx+rw*.62,cy+rh*1.05,cx-rw*.38,cy+rh*.92,cx-rw,cy),ctx.closePath(),ctx.fill(),ctx.stroke()}ctx.restore()},drawWaterEffect(ctx,effect,x,y,size,t){const duration=Math.max(1,effect.until-effect.startedAt),raw=Math.max(0,Math.min(1,(t-effect.startedAt)/duration)),fade=this._reduceMotion?.72:Math.max(0,1-raw*raw);if(ctx.save(),ctx.globalAlpha*=fade,!this._reduceMotion&&raw<.58){const fall=raw/.58;ctx.strokeStyle="rgba(177,224,225,.9)",ctx.lineWidth=Math.max(1.2,size*.018),ctx.lineCap="round";for(let k=0;k<5;k++){const phase=(fall+k*.17)%1,dx=x+size*(.24+k*.13),dy=y+size*(.08+phase*.48);ctx.beginPath(),ctx.moveTo(dx+size*.025,dy-size*.065),ctx.lineTo(dx,dy),ctx.stroke()}}ctx.strokeStyle="rgba(161,215,215,.72)",ctx.lineWidth=Math.max(1,size*.014);for(let k=0;k<3;k++){const local=this._reduceMotion?.42:(raw*1.7+k*.27)%1,radius=size*(.035+local*.12),rx=x+size*(.3+k*.2),ry=y+size*(.67-k%2*.08);ctx.globalAlpha*=1-local*.72,ctx.beginPath(),ctx.ellipse(rx,ry,radius,radius*.38,0,0,Math.PI*2),ctx.stroke(),ctx.globalAlpha/=Math.max(.01,1-local*.72)}ctx.restore()},drawRing(ctx,cell,cx,cy,size,nowSec){const d=this.state.durations||{};let dur=0,frac=0,color="#7aa84f";if(cell.s==="seed"||cell.s==="sprout"){dur=cell.s==="seed"?d.seed:d.sprout;const left=Math.max(0,cell.g-nowSec);frac=dur?Math.max(0,Math.min(1,1-left/dur)):0}else if(cell.s==="ripe"){dur=d.ripe;const left=Math.max(0,cell.g-nowSec);frac=dur?Math.max(0,Math.min(1,left/dur)):1,color=frac>.5?"#c79328":frac>.25?"#c77d2a":"#b4452f"}else return;const r=size*.4;ctx.lineWidth=Math.max(2,size*.045),ctx.strokeStyle="rgba(0,0,0,0.12)",ctx.beginPath(),ctx.arc(cx,cy,r,0,Math.PI*2),ctx.stroke(),ctx.strokeStyle=color,ctx.beginPath(),ctx.arc(cx,cy,r,-Math.PI/2,-Math.PI/2+Math.PI*2*frac),ctx.stroke()},drawFlash(ctx,fl,x,y,size){const left=(fl.until-Date.now())/2e3;ctx.save(),ctx.globalAlpha=Math.max(0,Math.min(1,left));const label=`${this._short(fl.name,10)} ${this.actionWord(fl.action)}`.trim();ctx.font=`600 ${Math.round(size*.13)}px 'Golos Text', sans-serif`;const tw=ctx.measureText(label).width+size*.18,bx=x+size/2-tw/2,by=y-size*.14;ctx.fillStyle="rgba(39,71,168,0.95)",this.roundRect(ctx,bx,by,tw,size*.26,size*.1),ctx.fill(),ctx.fillStyle="#fff",ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillText(label,x+size/2,by+size*.13),ctx.restore()},drawCultivatorAvatar(ctx,cx,cy,size,img,name,scale=1){const r=size*.3*scale;if(ctx.save(),ctx.beginPath(),ctx.arc(cx,cy,r,0,Math.PI*2),ctx.closePath(),ctx.clip(),img){const iw=img.naturalWidth,ih=img.naturalHeight,s=Math.min(iw,ih);ctx.drawImage(img,(iw-s)/2,(ih-s)/2,s,s,cx-r,cy-r,r*2,r*2)}else ctx.fillStyle="#e7dfce",ctx.fillRect(cx-r,cy-r,r*2,r*2),ctx.fillStyle="#7c6f50",ctx.font=`700 ${Math.round(r*1.05)}px Golos Text, sans-serif`,ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillText(String(name||"?").charAt(0).toUpperCase(),cx,cy+1);ctx.restore(),ctx.lineWidth=Math.max(1.5,size*.03),ctx.strokeStyle="rgba(255,255,255,0.9)",ctx.beginPath(),ctx.arc(cx,cy,r,0,Math.PI*2),ctx.stroke()},_avatarImg(url){if(!url)return null;const safe=Utils.safeUrl(url);if(!safe)return null;const cache=this._avCache||(this._avCache={});
256let e=cache[safe];return e||(e={img:new Image,ok:!1},e.img.onload=()=>{e.ok=!0,this.draw()},e.img.onerror=()=>{e.failed=!0},e.img.src=safe,cache[safe]=e),e.ok?e.img:null},_cropImg(crop,growing=!1){const url=(growing?this.CROP_GROWTH_ART:this.CROP_ART)[Number(crop)];return this._artImg(url)},_weedImg(thicket=!1){return this._artImg(thicket?this.WEED_ART.thicket:this.WEED_ART.single)},_artImg(url){if(!url)return null;const cache=this._cropArtCache||(this._cropArtCache={});let entry=cache[url];return entry||(entry={img:new Image,ok:!1},entry.img.onload=()=>{entry.ok=!0,this.draw()},entry.img.onerror=()=>{entry.failed=!0},entry.img.src=url,cache[url]=entry),entry.ok?entry.img:null},drawCropArt(ctx,img,cx,cy,size,scale=1,alpha=1,rotation=0){const box=size*.72,iw=img.naturalWidth||img.width||1,ih=img.naturalHeight||img.height||1,fit=Math.min(box/iw,box/ih),w=iw*fit,h=ih*fit;ctx.save(),ctx.translate(cx,cy),ctx.scale(scale,scale),ctx.translate(0,h*.38),ctx.rotate(rotation),ctx.translate(0,-h*.38),ctx.globalAlpha*=alpha,ctx.drawImage(img,-w/2,-h/2,w,h),ctx.restore()},_cropWeatherTilt(index,t,cell){if(this._reduceMotion||!cell||!["seed","sprout","ripe"].includes(cell.s))return 0;const civic=this.state&&this.state.civic,weather=civic&&civic.weather&&civic.weather.code,phase=Number(index||0)*1.618,young=cell.s==="seed"?.58:cell.s==="sprout"?.78:1;return weather==="rain"?(-.026+Math.sin(t/2100+phase)*.0055)*young:weather==="cool"?Math.sin(t/2500+phase)*.006*young:weather==="fair"?Math.sin(t/3e3+phase)*.0035*young:0},growthArtScale(cell,nowSec){const durations=this.state.durations||{},duration=cell.s==="seed"?Number(durations.seed):Number(durations.sprout),left=Math.max(0,Number(cell.g)-nowSec),progress=duration>0?Math.max(0,Math.min(1,1-left/duration)):.5,eased=this.easeOutCubic(progress);return cell.s==="seed"?.42+eased*.16:.58+eased*.34},transitionProgress(transition,t){return Math.max(0,Math.min(1,(t-transition.startedAt)/(transition.until-transition.startedAt)))},easeOutCubic(p){return 1-Math.pow(1-p,3)},drawPlantTransition(ctx,transition,cx,cy,size,t){const raw=this.transitionProgress(transition,t),fall=Math.min(1,raw/.56),settle=this.easeOutCubic(fall);if(ctx.save(),raw<.68){const alpha=raw<.52?1:Math.max(0,1-(raw-.52)/.16),px=cx+size*(.18-settle*.13),py=cy-size*(.43-settle*.34),w=size*.19,h=size*.24*(1-settle*.48);ctx.save(),ctx.translate(px,py),ctx.rotate(-.2+settle*.34),ctx.globalAlpha*=alpha,ctx.fillStyle="#eadcb2",ctx.strokeStyle="#8f713b",ctx.lineWidth=Math.max(.8,size*.012),this.roundRect(ctx,-w/2,-h/2,w,h,size*.025),ctx.fill(),ctx.stroke(),ctx.fillStyle="#b99138",ctx.beginPath(),ctx.ellipse(0,0,w*.12,h*.1,.3,0,Math.PI*2),ctx.fill(),ctx.strokeStyle="rgba(90,69,35,.4)",ctx.beginPath(),ctx.moveTo(-w*.28,-h*.26),ctx.lineTo(w*.22,-h*.26),ctx.stroke(),ctx.restore()}if(raw>.34){const q=Math.min(1,(raw-.34)/.66),colors=["#947050","#76543b","#c29a58","#5f4835"];ctx.globalAlpha*=Math.sin(q*Math.PI)*.8;for(let k=0;k<6;k++){const angle=-Math.PI*.92+k*Math.PI*.37,distance=size*(.05+q*(.11+k%2*.035)),px=cx+Math.cos(angle)*distance,py=cy+size*.18+Math.sin(angle)*distance*.42,shard=size*(.027+k%3*.007)*(1-q*.35);ctx.save(),ctx.translate(px,py),ctx.rotate(angle+q),ctx.fillStyle=colors[k%colors.length],ctx.beginPath(),ctx.moveTo(0,-shard),ctx.lineTo(shard,shard*.55),ctx.lineTo(-shard*.8,shard*.7),ctx.closePath(),ctx.fill(),ctx.restore()}}ctx.restore()},drawRipenFragments(ctx,transition,cx,cy,size,t){const p=this.easeOutCubic(this.transitionProgress(transition,t)),radius=(1-p)*size*.34,colors=["#e6c65f","#90a84e","#d9a53a","#f0df9b"];ctx.save(),ctx.globalAlpha=Math.max(0,(1-p)*.9);for(let k=0;k<7;k++){const angle=k*Math.PI*2/7+transition.crop*.31,x=cx+Math.cos(angle)*radius,y=cy+Math.sin(angle)*radius*.72,shard=size*(.045+k%3*.012);ctx.save(),ctx.translate(x,y),ctx.rotate(angle+p*1.4),ctx.fillStyle=colors[k%colors.length],ctx.beginPath(),ctx.moveTo(0,-shard),ctx.lineTo(shard*.72,shard*.65),ctx.lineTo(-shard*.72,shard*.45),ctx.closePath(),ctx.fill(),ctx.restore()}ctx.restore()},drawHarvestTransition(ctx,transition,cx,cy,size,t){const raw=this.transitionProgress(transition,t),p=this.easeOutCubic(raw),x=cx+p*size*.28,y=cy-p*size*.36,img=this._cropImg(transition.crop);if(img&&(ctx.save(),ctx.translate(x,y),ctx.rotate(p*.22),ctx.scale(1-p*.55,1-p*.82),this.drawCropArt(ctx,img,0,0,size,1,1-raw*.85),ctx.restore(
256)),raw>.34){const q=Math.min(1,(raw-.34)/.66),w=size*.2,h=size*.27;ctx.save(),ctx.translate(x,y),ctx.rotate(-.12+q*.2),ctx.globalAlpha=Math.sin(q*Math.PI),ctx.fillStyle="#efe2bd",ctx.strokeStyle="#9b7b3a",ctx.lineWidth=Math.max(1,size*.014),this.roundRect(ctx,-w/2,-h/2,w,h,size*.025),ctx.fill(),ctx.stroke(),ctx.strokeStyle="rgba(94,73,38,.5)",ctx.lineWidth=Math.max(.7,size*.01);for(let line=-1;line<=1;line++){const ly=line*h*.18;ctx.beginPath(),ctx.moveTo(-w*.28,ly),ctx.lineTo(w*.28,ly),ctx.stroke()}ctx.restore()}},stageEmoji(cell){switch(cell.s){case"seed":return"\xB7";case"sprout":return"\u{1F331}";case"ripe":return this.CROP_EMOJI[cell.c]||"\u{1F955}";case"weeds":return"\u{1F33F}";default:return""}},roundRect(ctx,x,y,w,h,r){ctx.beginPath(),ctx.moveTo(x+r,y),ctx.arcTo(x+w,y,x+w,y+h,r),ctx.arcTo(x+w,y+h,x,y+h,r),ctx.arcTo(x,y+h,x,y,r),ctx.arcTo(x,y,x+w,y,r),ctx.closePath()},_short(s,n){return s=String(s||""),s.length>n?s.slice(0,n-1)+"\u2026":s},_cellAt(ev){if(!this._geom)return-1;const rect=document.getElementById("garden-canvas").getBoundingClientRect(),{pad,size,cols,rows,offX,gridY}=this._geom,px=ev.clientX-rect.left-offX,py=ev.clientY-rect.top-gridY,c=Math.floor((px-pad)/(size+pad)),r=Math.floor((py-pad)/(size+pad));return c<0||c>=cols||r<0||r>=rows||px-pad-c*(size+pad)>size||py-pad-r*(size+pad)>size?-1:r*cols+c},onHover(ev){const i=this._cellAt(ev);this._hover=i;const canvas=document.getElementById("garden-canvas");if(i<0){canvas.style.cursor="default",this.hideTip();return}canvas.style.cursor=this.state.cells[i].s?"pointer":"default",this.showTip(ev,i)},showTip(ev,i){const tip=document.getElementById("garden-tip");if(!tip)return;const cell=this.state.cells[i],crop=this.cropName(cell.c,this.state.crops[cell.c]),trait=cell.s!=="empty"&&cell.s!=="weeds"?this.displayTrait(this.cropTrait(cell.c)):null,pts=this.state.points||{},nowSec=Math.floor(Date.now()/1e3),left=Math.max(0,(cell.g||0)-nowSec);let title="",body="",act="";if(cell.s==="empty")title=I18n.t("garden.plot_title",{n:i+1}),body=I18n.t("garden.plot_free","\u0421\u0432\u043E\u0431\u043E\u0434\u0435\u043D"),act=I18n.t("garden.tip_plant","\u043A\u043B\u0438\u043A\u043D\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0437\u0430\u0441\u0435\u044F\u0442\u044C");else if(cell.s==="seed")title=crop,body=I18n.t("garden.tip_planted_by",{name:Utils.esc(cell.by||"\u2014")}),act=I18n.t("garden.tip_sprouts_in",{duration:this._dur(left)});else if(cell.s==="sprout")title=crop,body=I18n.t("garden.tip_tended_by",{name:Utils.esc(cell.by||"\u2014")}),act=I18n.t("garden.tip_ripe_in",{duration:this._dur(left)});else if(cell.s==="ripe"){title=I18n.t("garden.tip_crop_ripe",{crop}),body=I18n.t("garden.tip_sown_by",{name:Utils.esc(cell.by||"\u2014")});const priorityLeft=this.harvestPriorityLeft(cell);act=priorityLeft>0?I18n.t("garden.tip_harvest_priority",{seconds:priorityLeft}):I18n.t("garden.tip_harvest",{points:this.formatProduce(pts.harvest||0)})}else cell.s==="weeds"&&(title=I18n.t("garden.weeds","\u0411\u0443\u0440\u044C\u044F\u043D"),body=I18n.t("garden.plot_abandoned","\u041D\u0430\u0434\u0435\u043B \u0437\u0430\u0431\u0440\u043E\u0448\u0435\u043D"),act=I18n.t("garden.tip_weed",{points:this.formatProduce(pts.weed||0)}));const traitHtml=trait?`<div class="gt-trait"><b>${Utils.esc(trait.name)}</b><span>${Utils.esc(trait.note)}</span></div>`:"";tip.innerHTML=`<div class="gt-title">${Utils.esc(title)}</div><div class="gt-body">${body}</div>${traitHtml}<div class="gt-act">${act}</div>`,tip.hidden=!1;const wrap=document.querySelector(".garden-page").getBoundingClientRect();let lx=ev.clientX-wrap.left+14,ly=ev.clientY-wrap.top+14;lx+tip.offsetWidth>wrap.width&&(lx=ev.clientX-wrap.left-tip.offsetWidth-14),tip.style.left=lx+"px",tip.style.top=ly+"px"},hideTip(){const tip=document.getElementById("garden-tip");tip&&(tip.hidden=!0)},_dur(sec){if(sec<=0)return this._text("garden.duration_moment","\u043C\u0438\u0433");if(sec<60)return this._text("garden.duration_seconds_short","{seconds}s",{seconds:sec});const m=Math.floor(sec/60);return sec%60?this._text("garden.duration_minutes_seconds_short","{minutes}m {seconds}s",{minutes:m,seconds:sec%60}):this._text("garden.duration_minutes_short","{minutes}m",{minutes:m})},cropTrait(index){const traits=this.state&&this.state.cropTraits;return Array.isArray(traits)&&traits[Number(index)]||null},cropName(index,fallback){const n=Number(index)+1,rawFallback=fallback||"",english=typeof I18n<"u"&&I18
256n&&I18n.locale==="en",safeFallback=rawFallback&&!(english&&/[\u0400-\u04ff]/u.test(rawFallback))?rawFallback:this._text("garden.crop_unknown","\u041A\u0443\u043B\u044C\u0442\u0443\u0440\u0430 \u2116{n}",{n});return I18n.t(`garden.crop_${Number(index)}`,safeFallback)},displayTrait(trait){return trait?{...trait,name:I18n.t(`garden.trait_${trait.code}_name`,trait.name||""),note:I18n.t(`garden.trait_${trait.code}_note`,trait.note||"")}:null},weatherName(code,fallback){const raw=fallback||"",safe=raw&&!(I18n.locale==="en"&&/[\u0400-\u04ff]/u.test(raw))?raw:this._text("garden.weather_unknown_name","Weather");return I18n.t(`garden.weather_${code}_name`,safe)},weatherNote(code,fallback){const raw=fallback||"",safe=raw&&!(I18n.locale==="en"&&/[\u0400-\u04ff]/u.test(raw))?raw:this._text("garden.weather_unknown_note","Weather details unavailable");return I18n.t(`garden.weather_${code}_note`,safe)},civicTaskLabel(code,fallback){const raw=fallback||"",safe=raw&&!(I18n.locale==="en"&&/[\u0400-\u04ff]/u.test(raw))?raw:this._text("garden.task_unknown","Garden duty");return I18n.t(`garden.task_${code}`,safe)},animalName(index,fallback){const raw=fallback||"",safe=raw&&!(I18n.locale==="en"&&/[\u0400-\u04ff]/u.test(raw))?raw:this._text("garden.animal_fallback","\u0416\u0438\u0432\u043E\u0442\u043D\u043E\u0435");return I18n.t(`garden.animal_${Number(index)}_name`,safe)},animalProduct(index,fallback){const raw=fallback||"",safe=raw&&!(I18n.locale==="en"&&/[\u0400-\u04ff]/u.test(raw))?raw:this._text("garden.product_fallback","\u043F\u0440\u043E\u0434\u0443\u043A\u0442");return I18n.t(`garden.animal_${Number(index)}_product`,safe)},onClick(ev){this.act(this._cellAt(ev)),this.hideTip()},actionFor(s){return s==="empty"?"plant":s==="seed"||s==="sprout"?"water":s==="ripe"?"harvest":s==="weeds"?"weed":null},harvestPriorityLeft(cell,viewerId=App.state.user&&App.state.user.id,at=Math.floor(Date.now()/1e3)){const seconds=Math.max(0,Number(this.state&&this.state.harvestPrioritySeconds)||0),ripeAt=Number(cell&&cell.r)||0;return!seconds||!cell||cell.s!=="ripe"||!ripeAt||!cell.byId||Number(cell.byId)===Number(viewerId)?0:Math.max(0,Math.min(seconds,ripeAt+seconds-Number(at||0)))},act(i){if(i<0||!this.state)return;if(!App.state.user){this._promptLogin();return}const a=this.actionFor(this.state.cells[i].s);if(!a)return;const priorityLeft=a==="harvest"?this.harvestPriorityLeft(this.state.cells[i]):0;if(priorityLeft>0){Utils.showToast(I18n.t("garden.harvest_priority_wait",{seconds:priorityLeft}),"info");return}if(!SocketClient.isConnected()){Utils.showToast(this._text("garden.connection_lost","\u0421\u0432\u044F\u0437\u044C \u0441 \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u0435\u0439 \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430 \u2014 \u0440\u0430\u0431\u043E\u0442\u0430 \u043D\u0430 \u0433\u0440\u044F\u0434\u043A\u0435 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0430."),"error");return}const cdKey=a==="plant"||a==="water"?a:"harvest",cdSec=this.state.cooldowns&&this.state.cooldowns[cdKey]||0;if(cdSec>0){const now=Date.now();if(now<(this._cd[cdKey]||0)){this.updateCd();return}this._cd[cdKey]=now+cdSec*1e3,this.updateCd()}SocketClient.gardenAction(a,i),this.hideTip()},updateCd(){const el=document.getElementById("garden-cd");if(!el)return;const now=Date.now(),order=[["plant","garden.cooldown_plant","\u043F\u043E\u0441\u0430\u0434\u043A\u0430"],["water","garden.cooldown_water","\u043F\u043E\u043B\u0438\u0432"],["harvest","garden.cooldown_harvest","\u0441\u0431\u043E\u0440"]],parts=[];for(const[k,key,fallback]of order){const s=Math.ceil(((this._cd[k]||0)-now)/1e3);s>0&&parts.push(this._text("garden.cooldown_item","{action} {seconds}s",{action:this._text(key,fallback),seconds:s}))}if(parts.length?(el.textContent=parts.join(" \xB7 "),el.hidden=!1):el.hidden=!0,this.state&&this.state.pen&&this.state.pen.enabled&&now-this._penRenderAt>900&&(this._penRenderAt=now,this.renderPen()),this._limits&&now-this._limitsTickAt>900){this._limitsTickAt=now,this.renderLimits(this._limits);const releaseAt=Number(this._limits.points&&this._limits.points.nextReleaseAt)||0;releaseAt&&releaseAt*1e3<=now&&releaseAt>this._limitReleaseRefreshAt&&(this._limitReleaseRefreshAt=releaseAt,this.loadLeaderboard())}},srPlotLabel(i){const cell=this.state.cells[i],crop=this.cropName(cell.c,this.state.crops[cell.c]),by=cell.by||I18n.t("common.unknown","\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u043E"),trait=this.displayTrait(this.cropTrait(cell.c)),feature=trait?I18n.t("garden.plot_trait",{name:trait.name,note:trait.note}):"",n=i+1;switch(cell.s){case"empty":return I18n.t("garden.plot_empty",{n});case"seed":return I18n.t("garden.plot_seed",{n,crop,by,feature});case"sprout":return I18n.t("garden.plot_sprout",{n,crop,by,feature});case"ripe":return I18n.t("garden.plot_ripe",{n,crop,by,feature});case"weeds":return I18n.t("garden.plot_weeds",{n});default:return I18n.t("garden.plot_name",{n})}},renderSrPlots(){const box=document.getElementById("garden-sr");
256if(!box||!this.state)return;const frag=document.createDocumentFragment();for(let i=0;i<this.state.cells.length;i++){const b=document.createElement("button");b.type="button",b.className="garden-sr-plot",b.dataset.i=i,b.setAttribute("aria-label",this.srPlotLabel(i)),b.textContent=I18n.t("garden.plot_name",{n:i+1}),frag.appendChild(b)}box.innerHTML="",box.appendChild(frag)},updateSrPlot(i){const b=document.querySelector(`#garden-sr button[data-i="${i}"]`);b&&b.setAttribute("aria-label",this.srPlotLabel(i))},renderPen(){const wrap=document.getElementById("garden-pen-wrap"),grid=document.getElementById("garden-pen-grid"),head=document.getElementById("garden-pen-shared-head"),dock=document.getElementById("garden-pet-dock");if(!wrap||!grid)return;const pen=this.state&&this.state.pen;if(!pen||!pen.enabled||!Array.isArray(pen.animals)||!pen.animals.length){grid.hidden=!0,head&&(head.hidden=!0),wrap.hidden=!dock||dock.hidden;return}wrap.hidden=!1,grid.hidden=!1,head&&(head.hidden=!1),this._penBound||(grid.addEventListener("click",e=>{const btn=e.target.closest("button[data-act]");!btn||btn.disabled||this.penAction(btn.dataset.act,parseInt(btn.dataset.i,10))}),this._penBound=!0),grid.children.length!==pen.animals.length&&(grid.innerHTML=pen.animals.map((a,i)=>{const emoji=this.ANIMAL_EMOJI[i]||"\u{1F43E}",art=this.ANIMAL_ART[i];return`<div class="garden-pen-card" data-i="${i}">
257          <div class="gp-ic" aria-hidden="true">${art?`<img src="${art}" alt="" draggable="false" decoding="async" onerror="this.hidden=true;this.nextElementSibling.hidden=false"><span class="gp-ic-fallback" hidden>${emoji}</span>`:`<span class="gp-ic-fallback">${emoji}</span>`}</div>
258          <div class="gp-body">
259            <div class="gp-name">${Utils.esc(this.animalName(i,a.name))}</div>
260            <div class="gp-state"></div>
261            <div class="garden-meter gp-meter" role="progressbar" aria-valuemin="0" aria-valuemax="100" hidden><div class="garden-meter-fill"></div></div>
262          </div>
263          <div class="gp-dispatch" aria-hidden="true"></div>
264          <button class="gp-btn" data-i="${i}" data-act="feed"></button>
265        </div>`}).join("")),this._paintPen()},_paintPen(){const grid=document.getElementById("garden-pen-grid"),pen=this.state&&this.state.pen;if(!grid||!pen||!Array.isArray(pen.animals))return;const nowSec=Math.floor(Date.now()/1e3),nowMs=Date.now(),target=pen.target||1,pts=pen.points||{feed:0,collect:0},feedCdLeft=Math.max(0,Math.ceil((this._penCd-nowMs)/1e3)),harvCdLeft=Math.max(0,Math.ceil(((this._cd.harvest||0)-nowMs)/1e3));pen.animals.forEach((a,i)=>{const card=grid.children[i];if(!card)return;const stateEl=card.querySelector(".gp-state"),meterEl=card.querySelector(".gp-meter"),fillEl=card.querySelector(".garden-meter-fill"),dispatchEl=card.querySelector(".gp-dispatch"),btn=card.querySelector(".gp-btn");if(!stateEl||!btn)return;const name=this.animalName(i,a.name),product=this.animalProduct(i,a.product),restLeft=Math.max(0,(a.restAt||0)-nowSec),reaction=this._activePenReaction(i,this._animationNow()),reactionClass=reaction?` is-reaction-${reaction.type}`:"";if(dispatchEl&&(dispatchEl.textContent=reaction&&reaction.type==="collect"?this._text("garden.pen_dispatch_to_plan","{product} \u2192 to the Plan",{product:reaction.product||product}):""),restLeft>0)card.className="garden-pen-card is-rest"+reactionClass,stateEl.className="gp-state",stateEl.textContent=I18n.t("garden.pen_resting_for",{duration:this._dur(restLeft)}),meterEl.hidden=!0,btn.className="gp-btn",btn.dataset.act="feed",btn.disabled=!0,btn.textContent=I18n.t("garden.pen_resting","\u041E\u0442\u0434\u044B\u0445\u0430\u0435\u0442"),btn.setAttribute("aria-label",I18n.t("garden.pen_resting_aria",{name,duration:this._dur(restLeft)}));else if(a.ready){card.className="garden-pen-card is-ready"+reactionClass,stateEl.className="gp-state gp-ready",stateEl.innerHTML=`${I18n.t("garden.pen_product_ready","\u041F\u0440\u043E\u0434\u0443\u043A\u0442 \u0433\u043E\u0442\u043E\u0432")}: <b>${Utils.esc(product)}</b>`,meterEl.hidden=!0;const off=harvCdLeft>0;btn.className="gp-btn gp-collect",btn.dataset.act="collect",btn.disabled=off,btn.textContent=off?I18n.t("garden.pen_too_early",{seconds:harvCdLeft}):I18n.t("garden.pen_collect",{points:this.formatProduce(pts.collect)}),btn.setAttribute("aria-label",off?I18n.t("garden.pen_collect_cooldown",{name,product,seconds:harvCdLeft}):I18n.t("garden.pen_collect_aria",{name,product}))}else{card.className="garden-pen-card"+reactionClass,stateEl.className="gp-state",stateEl.textContent=I18n.t("garden.pen_fattening",{fill:a.fill,target}),meterEl.hidden=!1;const fillPct=Math.min(100,Math.round(a.fill/target*100));fillEl&&(fillEl.style.width=fillPct+"%"),meterEl.setAttribute("aria-valuenow",String(fillPct)),meterEl.setAttribute("aria-label",I18n.t("garden.pen_fattening_aria",{name,fill:a.fill,target}));const off=feedCdLeft>0;btn.className="gp-btn",btn.dataset.act="feed",btn.disabled=off,btn.textContent=off?I18n.t("garden.pen_too_early",{seconds:feedCdLeft}):I18n.t("garden.pen_feed",{points:this.formatProduce(pts.feed)}),btn.setAttribute("aria-label",off?I18n.t("garden.pen_feed_cooldown",{name,seconds:feedCdLeft}):I18n.t("garden.pen_feed_aria",{name}))}})},penAction(act,i){const pen=this.state&&this.state.pen;if(!pen||!pen.enabled||!Array.isArray(pen.animals)||!(i>=0&&i<pen.animals.length))return;if(!App.state.user){this._promptLogin();return}if(!SocketClient.isConnected()){Utils.showToast(this._text("garden.connection_lost_pen","\u0421\u0432\u044F\u0437\u044C \u0441 \u041A\u0430\u043D\u0446\u0435\u043B\u044F\u0440\u0438\u0435\u0439 \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430 \u2014 \u0440\u0430\u0431\u043E\u0442\u0430 \u0432 \u0437\u0430\u0433\u043E\u043D\u0435 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0430."),"error");return}const now=Date.now();if(act==="feed"){const cdSec=pen.feedCooldown||0;if(cdSec>
2650){if(now<this._penCd){this.renderPen();return}this._penCd=now+cdSec*1e3}}else if(act==="collect"){const cdSec=this.state.cooldowns&&this.state.cooldowns.harvest||0;if(cdSec>0){if(now<(this._cd.harvest||0)){this.updateCd();return}this._cd.harvest=now+cdSec*1e3,this.updateCd()}}else return;SocketClient.gardenPenAction(act,i),this.renderPen()}};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.