Cookie Clicker Ultimate Automation

Automated clicker, auto-buy, auto-harvest, garden manager, stock market, season manager, Santa evolver, and Smart Sugar Lump harvester.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Cookie Clicker Ultimate Automation
// @name:zh-TW   餅乾點點樂全自動掛機輔助 (Cookie Clicker)
// @name:zh-CN   饼干点点乐全自动挂机辅助 (Cookie Clicker)
// @namespace    http://tampermonkey.net/
// @version      8.5.4-hotfix
// @description  Automated clicker, auto-buy, auto-harvest, garden manager, stock market, season manager, Santa evolver, and Smart Sugar Lump harvester.
// @description:zh-TW 全功能自動掛機腳本 v8.5.4 Hotfix:修復網格定位抖動 + 盾牌歸屬錯誤
// @author       You & AI Architect
// @match        https://wws.justnainai.com/*
// @match        https://orteil.dashnet.org/cookieclicker/*
// @icon         https://orteil.dashnet.org/cookieclicker/img/favicon.ico
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_openInTab
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // ═══════════════════════════════════════════════════════════════
    // 0. 全域配置與狀態 (Configuration & State)
    // ═══════════════════════════════════════════════════════════════
    const Config = {
        // 開關狀態
        Flags: {
            GlobalMasterSwitch: GM_getValue('isGlobalMasterSwitchEnabled', true),

            Click: GM_getValue('isClickEnabled', true),
            Buy: GM_getValue('isBuyEnabled', true),
            Golden: GM_getValue('isGoldenEnabled', true),
            Spell: GM_getValue('isSpellEnabled', true),
            Garden: GM_getValue('isGardenEnabled', true),
            Research: GM_getValue('isResearchEnabled', true),
            AutoWrinkler: GM_getValue('isAutoWrinklerEnabled', true),
            Stock: GM_getValue('isStockEnabled', true),
            SE: GM_getValue('isSEEnabled', true),
            Season: GM_getValue('isSeasonEnabled', true),
            Santa: GM_getValue('isSantaEnabled', true),

            GardenOverlay: GM_getValue('isGardenOverlayEnabled', true),
            GardenAvoidBuff: GM_getValue('isGardenAvoidBuff', true),
            GardenMutation: GM_getValue('isGardenMutationEnabled', false),

            ShowCountdown: GM_getValue('showCountdown', true),
            ShowBuffMonitor: GM_getValue('showBuffMonitor', true),
            ShowGardenProtection: GM_getValue('showGardenProtection', true),
            SpendingLocked: GM_getValue('spendingLocked', false), // ⭐ 核心狀態

            GodzamokCombo: GM_getValue('isGodzamokComboEnabled', false),
            ShowGardenGrid: GM_getValue('isShowGardenGrid', false)
        },
        // 參數
        Settings: {
            Volume: GM_getValue('gameVolume', 50),
            ClickInterval: GM_getValue('clickInterval', 10),
            BuyStrategy: GM_getValue('buyStrategy', 'expensive'),
            BuyIntervalMs: (GM_getValue('buyIntervalHours', 0) * 3600 + GM_getValue('buyIntervalMinutes', 3) * 60 + GM_getValue('buyIntervalSeconds', 0)) * 1000,
            RestartIntervalMs: (GM_getValue('restartIntervalHours', 1) * 3600 + GM_getValue('restartIntervalMinutes', 0) * 60 + GM_getValue('restartIntervalSeconds', 0)) * 1000,
            MaxWizardTowers: 800,
            SugarLumpGoal: 100,
            SpellCooldownSuccess: 60000,
            SpellCooldownFail: 60000,
            SEFailThreshold: 3,
            SEFailResetCooldown: 300000,

            GodzamokMinMult: 1000,
            GodzamokSellAmount: 100,
            GodzamokTargetBuilding: 'Farm',
            GodzamokCooldown: 15000,
            GodzamokBuyBackTime: 11000
        },
        // 記憶
        Memory: {
            SavedGardenPlot: GM_getValue('savedGardenPlot', Array(6).fill().map(() => Array(6).fill(-1))),
            PanelX: GM_getValue('panelX', window.innerWidth / 2 - 200),
            PanelY: GM_getValue('panelY', 100),
            BuffX: GM_getValue('buffX', window.innerWidth - 340),
            BuffY: GM_getValue('buffY', 150),
            CountdownX: GM_getValue('countdownX', window.innerWidth - 170),
            CountdownY: GM_getValue('countdownY', 10),
            ButtonX: GM_getValue('buttonX', 50),
            ButtonY: GM_getValue('buttonY', 50),
            GardenProtectionX: GM_getValue('gardenProtectionX', 10),
            GardenProtectionY: GM_getValue('gardenProtectionY', 10),
            ActionLogX: GM_getValue('actionLogX', window.innerWidth - 420),
            ActionLogY: GM_getValue('actionLogY', window.innerHeight - 350),
            GardenGridX: GM_getValue('gardenGridX', 100),
            GardenGridY: GM_getValue('gardenGridY', 100),

            // ⭐ v8.5.3 新增 UI 記憶
            LastActiveTab: GM_getValue('lastActiveTab', 'core'),
            GardenLeftExpanded: GM_getValue('gardenLeftExpanded', false),
            GardenRightExpanded: GM_getValue('gardenRightExpanded', false),
            LogFontSize: GM_getValue('logFontSize', 12),
            LogOpacity: GM_getValue('logOpacity', 0.95),

            SavedSpendingStates: GM_getValue('savedSpendingStates', {
                Buy: true,
                Garden: true,
                Research: true,
                Stock: true
            }),
            
            // ⭐ v8.5.4 新增記憶
            GardenProtectionMinimized: GM_getValue('gardenProtectionMinimized', false),
            GardenShieldX: GM_getValue('gardenShieldX', 20),
            GardenShieldY: GM_getValue('gardenShieldY', 100)
        }
    };

    // 運行時計時器與緩存
    const Runtime = {
        Timers: {
            NextBuy: 0,
            NextRestart: 0,
            NextGarden: 0,
            NextStock: 0,
            NextSeasonCheck: 0,
            NextSpontaneousEdifice: 0,
            NextGodzamokCombo: 0
        },
        Stats: {
            ClickCount: 0,
            BuyUpgradeCount: 0,
            BuyBuildingCount: 0,
            SEFailCount: 0
        },
        GodzamokState: {
            isActive: false,
            soldAmount: 0,
            originalBuyState: true
        },
        OriginalTitle: document.title,
        SeasonState: {
            CurrentStage: 0,
            Roadmap: [
                { name: 'Valentine', id: 'fools', target: 'BuyAllUpgrades' },
                { name: 'Christmas', id: 'christmas', target: 'MaxSanta' }
            ]
        }
    };

    // ═══════════════════════════════════════════════════════════════
    // Logger 模組
    // ═══════════════════════════════════════════════════════════════
    const Logger = {
        log: function(module, message) {
            const formatted = `[${module}] ${message}`;
            console.log(`ℹ️ ${formatted}`);
            if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'info');
        },
        warn: function(module, message) {
            const formatted = `[${module}] ${message}`;
            console.warn(`⚠️ ${formatted}`);
            if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'warn');
        },
        error: function(module, message) {
            const formatted = `[${module}] ${message}`;
            console.error(`❌ ${formatted}`);
            if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'error');
        },
        success: function(module, message) {
            const formatted = `[${module}] ${message}`;
            console.log(`%c✅ ${formatted}`, 'color: #4caf50; font-weight: bold;');
            if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'success');
        }
    };

    // ═══════════════════════════════════════════════════════════════
    // 1. UI 模組
    // ═══════════════════════════════════════════════════════════════
    const UI = {
        Elements: {
            Panel: null,
            FloatingBtn: null,
            Countdown: null,
            BuffMonitor: null
        },

        initStyles: function() {
            const style = document.createElement('style');
            style.type = 'text/css';
            style.innerHTML = `
                .cc-overlay-missing { border: 3px dashed #2196f3 !important; box-sizing: border-box; background: rgba(33, 150, 243, 0.1); }
                .cc-overlay-anomaly { border: 3px solid #ff4444 !important; box-shadow: inset 0 0 15px rgba(255, 0, 0, 0.6) !important; box-sizing: border-box; z-index: 10; }
                .cc-overlay-new { border: 3px solid #9c27b0 !important; box-shadow: inset 0 0 15px rgba(156, 39, 176, 0.8), 0 0 10px rgba(156, 39, 176, 0.5) !important; box-sizing: border-box; z-index: 12; }
                .cc-overlay-correct { border: 1px solid rgba(76, 175, 80, 0.4) !important; box-sizing: border-box; }

                .cc-close-btn { position:absolute; top:5px; right:5px; cursor:pointer; color:#aaa; font-weight:bold; padding:2px 6px; z-index:100; font-family:sans-serif; }
                .cc-close-btn:hover { color:white; background:rgba(255,255,255,0.2); border-radius:4px; }

                /* Tab System - v8.5.4 響應式修復 */
                .cc-tab-header { 
                    display: flex; 
                    border-bottom: 2px solid #ddd; 
                    background: #f5f7fa; 
                    white-space: nowrap; 
                    overflow-x: auto; 
                    overflow-y: hidden;
                }
                .cc-tab-btn { 
                    flex: 1 0 auto; 
                    padding: 12px 5px; 
                    border: none; 
                    background: transparent; 
                    cursor: pointer; 
                    font-weight: bold; 
                    color: #555; 
                    transition: all 0.2s; 
                    font-size: 14px; 
                    min-width: 0;
                    overflow: hidden;
                    text-overflow: ellipsis;
                }
                .cc-tab-btn:hover { background: rgba(0,0,0,0.05); color: #333; }
                .cc-tab-btn.active { border-bottom: 3px solid #667eea; color: #667eea; background: #fff; }
                .cc-tab-pane { display: none; padding: 15px; animation: fadeIn 0.2s; }
                .cc-tab-pane.active { display: block; }
                @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

                /* Log Controls */
                .cc-log-controls { display: flex; gap: 10px; padding: 5px 10px; background: rgba(0,0,0,0.3); border-bottom: 1px solid #444; font-size: 12px; align-items: center; }
                .cc-range-mini { width: 60px; height: 4px; }

                /* Garden Grid V8.5.3 Drawer Styles - ✅ v8.5.4-hotfix 修正 */
                .cc-garden-row { display: flex; align-items: flex-start; justify-content: center; }
                .cc-drawer {
                    width: 0px; opacity: 0; overflow: hidden;
                    transition: width 0.3s ease, opacity 0.2s ease;
                    background: rgba(0,0,0,0.3); border-radius: 6px;
                }
                .cc-drawer.open {
                    width: 220px; opacity: 1; margin: 0 5px;
                    border: 1px solid #555;
                }
                .cc-center-stage {
                    width: 320px !important; /* ✅ 固定寬度,防止抖動 */
                    flex-shrink: 0; 
                    display: flex;
                    flex-direction: column; 
                    align-items: center; 
                    z-index: 10;
                }
                .cc-garden-side ul { list-style: none; padding: 0; margin: 0; }
                .cc-garden-side ul li { padding: 5px 8px; border-bottom: 1px solid #333; transition: background 0.2s; font-size: 13px; }
                .cc-garden-side ul li:hover { background: rgba(255, 255, 255, 0.1); }
                
                /* v8.5.4-hotfix 修正:小盾牌圖示 */
                .cc-garden-shield {
                    position: absolute !important; /* ✅ 改為 absolute,附著在花園面板上 */
                    width: 32px;
                    height: 32px;
                    background: linear-gradient(135deg, #81c784 0%, #4caf50 100%);
                    border-radius: 50%;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    cursor: pointer;
                    z-index: 10001; /* ✅ 更高 z-index */
                    box-shadow: 0 2px 10px rgba(0,0,0,0.3);
                    font-size: 18px;
                    border: 2px solid #fff;
                    transition: transform 0.3s, box-shadow 0.3s;
                    right: 45px; /* ✅ 固定位置在花園面板右上角 */
                    top: 4px;
                }
                .cc-garden-shield:hover {
                    transform: scale(1.1);
                    box-shadow: 0 4px 15px rgba(129, 199, 132, 0.6);
                }
            `;
            document.head.appendChild(style);
        },

        formatMs: function(ms) {
            if (ms < 0) return '00:00';
            const totalSecs = Math.floor(ms / 1000);
            const h = Math.floor(totalSecs / 3600);
            const m = Math.floor((totalSecs % 3600) / 60);
            const s = totalSecs % 60;
            const pad = (n) => n < 10 ? '0' + n : n;
            return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${pad(m)}:${pad(s)}`;
        },

        cleanName: function(str) {
            if (!str) return '';
            if (typeof str !== 'string') return String(str);
            return str.replace(/<[^>]*>/g, '').trim();
        },

        createFloatingButton: function() {
            if (this.Elements.FloatingBtn) return;
            this.Elements.FloatingBtn = $(`
                <div id="cookie-floating-button" style="
                    position: fixed; left: ${Config.Memory.ButtonX}px; top: ${Config.Memory.ButtonY}px; width: 50px; height: 50px;
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 50%;
                    display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 999999;
                    font-size: 24px; box-shadow: 0 4px 15px rgba(0,0,0,0.3); transition: filter 0.3s, background 0.3s;
                ">🍪</div>
            `);

            this.Elements.FloatingBtn.click((e) => { e.stopPropagation(); this.togglePanel(); });

            let isD = false;
            this.Elements.FloatingBtn.mousedown(() => isD = true);
            $(document).mousemove((e) => {
                if(isD) {
                    Config.Memory.ButtonX = e.clientX - 25;
                    Config.Memory.ButtonY = e.clientY - 25;
                    this.Elements.FloatingBtn.css({left: Config.Memory.ButtonX, top: Config.Memory.ButtonY});
                }
            }).mouseup(() => {
                if(isD) { isD = false; GM_setValue('buttonX', Config.Memory.ButtonX); GM_setValue('buttonY', Config.Memory.ButtonY); }
            });
            $('body').append(this.Elements.FloatingBtn);
            this.updateButtonState();
        },

        updateButtonState: function() {
            if (this.Elements.FloatingBtn) {
                if (Config.Flags.GlobalMasterSwitch) {
                    this.Elements.FloatingBtn.css({
                        'filter': Config.Flags.Click ? 'hue-rotate(0deg)' : 'grayscale(100%)',
                        'background': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
                    }).html('🍪');
                } else {
                    this.Elements.FloatingBtn.css({ 'filter': 'none', 'background': '#f44336' }).html('⏸️');
                }
            }
        },

        createControlPanel: function() {
            if (this.Elements.Panel) return;
            const generateOptions = (min, max, sel, unit) => {
                let h=''; for(let i=min; i<=max; i++) h+=`<option value="${i}" ${i === sel?'selected':''}>${i}${unit}</option>`; return h;
            };
            const buyMin = Math.floor(Config.Settings.BuyIntervalMs / 60000);
            const buySec = (Config.Settings.BuyIntervalMs % 60000) / 1000;
            const rstHr = Math.floor(Config.Settings.RestartIntervalMs / 3600000);
            const rstMin = (Config.Settings.RestartIntervalMs % 3600000) / 60000;

            this.Elements.Panel = $(`
                <div id="cookie-control-panel" style="
                    position: fixed; left: ${Config.Memory.PanelX}px; top: ${Config.Memory.PanelY}px; width: 420px;
                    max-height: 85vh; background: #fff; border-radius: 12px;
                    box-shadow: 0 10px 40px rgba(0,0,0,0.4); z-index: 999998;
                    font-family: Arial, sans-serif; display: none; overflow: hidden; color: #333;
                ">
                    <div id="panel-header" style="
                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                        color: white; padding: 15px; font-weight: bold; font-size: 18px;
                        cursor: move; display: flex; justify-content: space-between; align-items: center;
                    ">
                        <span>🍪 控制面板 v8.5.4-hotfix</span>
                        <div class="cc-close-btn" id="main-panel-close">✕</div>
                    </div>
                    <div id="global-status-bar" style="
                        padding: 10px 15px; background: #4caf50; color: white; font-weight: bold;
                        font-size: 14px; text-align: center; display: flex; align-items: center; justify-content: center; gap: 10px;
                    ">
                        <span id="status-icon">🟢</span>
                        <span id="status-text">系統運行中</span>
                        <button id="btn-toggle-master" style="
                            padding: 4px 12px; background: rgba(255, 255, 255, 0.2); color: white;
                            border: 1px solid rgba(255, 255, 255, 0.5); border-radius: 4px; cursor: pointer; font-size: 12px;
                        ">暫停 (F8)</button>
                    </div>

                    <div class="cc-tab-header">
                        <button class="cc-tab-btn active" data-target="core">核心</button>
                        <button class="cc-tab-btn" data-target="advanced">進階</button>
                        <button class="cc-tab-btn" data-target="garden">花園</button>
                        <button class="cc-tab-btn" data-target="settings">設定</button>
                    </div>

                    <div style="padding-bottom: 20px; overflow-y: auto; max-height: calc(85vh - 165px);">

                        <!-- 1. 核心頁籤 -->
                        <div id="tab-core" class="cc-tab-pane active">
                            <div class="panel-section" style="margin-bottom:15px; padding:10px; background:#f5f7fa; border-radius:8px;">
                                <div style="font-weight:bold; color:#222; margin-bottom:10px; border-bottom:2px solid #ddd; padding-bottom:5px;">🎛️ 核心模組</div>
                                <div style="display:grid; grid-template-columns: 1fr 1fr; gap:10px; color:#333;">
                                    <label><input type="checkbox" id="chk-auto-click" ${Config.Flags.Click?'checked':''}> 👉 自動點擊</label>
                                    <label><input type="checkbox" id="chk-auto-buy" ${Config.Flags.Buy?'checked':''}> 🛒 自動購買</label>
                                    <label><input type="checkbox" id="chk-auto-golden" ${Config.Flags.Golden?'checked':''}> ⭐ 金餅乾/糖塊</label>
                                    <label><input type="checkbox" id="chk-auto-garden" ${Config.Flags.Garden?'checked':''}> 🌻 花園維護</label>
                                    <label><input type="checkbox" id="chk-research" ${Config.Flags.Research?'checked':''}> 🔬 自動科技研發</label>
                                    <label><input type="checkbox" id="chk-wrinkler" ${Config.Flags.AutoWrinkler?'checked':''}> 🐛 自動戳皺紋蟲</label>
                                </div>
                                <div id="lump-status" style="margin-top: 10px; padding: 6px; background: rgba(0,0,0,0.05); border-radius: 4px; font-size: 12px; color: #666; border-left: 3px solid #ccc;">🍬 糖塊監控:初始化中...</div>
                            </div>
                            <div class="panel-section" style="margin-bottom:15px; padding:10px; background:#fff3e0; border-radius:8px;">
                                <div style="font-weight:bold; color:#e65100; margin-bottom:5px;">🛒 購買策略</div>
                                <select id="buy-strategy" style="width:100%; padding:5px;">
                                    <option value="expensive" ${Config.Settings.BuyStrategy==='expensive'?'selected':''}>最貴優先</option>
                                    <option value="cheapest" ${Config.Settings.BuyStrategy==='cheapest'?'selected':''}>最便宜優先</option>
                                </select>
                                 <div style="display:flex; gap:5px; align-items:center; margin-top:5px; color:#333;">
                                    <span style="font-size:13px;">間隔:</span>
                                    <select id="buy-min">${generateOptions(0, 59, buyMin, '分')}</select>
                                    <select id="buy-sec">${generateOptions(0, 59, buySec, '秒')}</select>
                                </div>
                            </div>
                        </div>

                        <!-- 2. 進階頁籤 -->
                        <div id="tab-advanced" class="cc-tab-pane">
                            <div class="panel-section" style="margin-bottom:15px; padding:10px; background:#e1f5fe; border-radius:8px;">
                                <div style="font-weight:bold; color:#0277bd; margin-bottom:5px;">📈 進階掛機</div>
                                <div style="color:#333; font-size:13px; display:grid; gap:8px;">
                                    <label><input type="checkbox" id="chk-stock" ${Config.Flags.Stock?'checked':''}> 股市自動交易</label>
                                    <label><input type="checkbox" id="chk-se" ${Config.Flags.SE?'checked':''}> 🧙‍♂️ 閒置魔法: 憑空建築</label>
                                    <label><input type="checkbox" id="chk-season" ${Config.Flags.Season?'checked':''}> 🍂 季節管理</label>
                                    <label><input type="checkbox" id="chk-santa" ${Config.Flags.Santa?'checked':''}> 🎅 聖誕老人進化</label>
                                </div>
                                <div style="margin-top:10px; padding-top:10px; border-top:1px dashed #bcd; display:block;">
                                    <label style="font-weight:bold; color:#01579b;">
                                        <input type="checkbox" id="chk-godzamok" ${Config.Flags.GodzamokCombo?'checked':''}> 🐲 Godzamok 連擊
                                    </label>
                                    <div style="font-size:11px; color:#555; margin-left:20px; margin-top:4px;">
                                        賣出 <input type="number" id="val-godzamok-amount" value="${Config.Settings.GodzamokSellAmount}" style="width:40px;"> 座
                                        <select id="val-godzamok-target" style="width:80px; padding:2px; border-radius:4px; border:1px solid #ccc;">
                                            <option value="Farm" ${Config.Settings.GodzamokTargetBuilding==='Farm'?'selected':''}>Farm (農場)</option>
                                            <option value="Mine" ${Config.Settings.GodzamokTargetBuilding==='Mine'?'selected':''}>Mine (礦坑)</option>
                                            <option value="Factory" ${Config.Settings.GodzamokTargetBuilding==='Factory'?'selected':''}>Factory (工廠)</option>
                                        </select>
                                        (倍率 > <input type="number" id="val-godzamok-min" value="${Config.Settings.GodzamokMinMult}" style="width:50px;">x)
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- 3. 花園頁籤 -->
                        <div id="tab-garden" class="cc-tab-pane">
                            <div class="panel-section" style="margin-bottom:15px; padding:10px; background:#e8f5e9; border-radius:8px;">
                                <div style="font-weight:bold; color:#1b5e20; margin-bottom:5px;">🌻 花園自動化</div>
                                <label style="display:block; margin-bottom:8px; font-weight:bold; color:#1565c0;">
                                    <input type="checkbox" id="chk-show-garden-protection" ${Config.Flags.ShowGardenProtection?'checked':''}> 🖥️ 於花園顯示保護介面
                                </label>
                                <label style="display:block; margin-bottom:8px; font-weight:bold; color:#2e7d32;">
                                    <input type="checkbox" id="chk-garden-overlay" ${Config.Flags.GardenOverlay?'checked':''}> [x] 顯示陣型輔助網格
                                </label>
                                <label style="display:block; margin-bottom:8px; font-weight:bold; color:#d84315;">
                                    <input type="checkbox" id="chk-garden-mutation" ${Config.Flags.GardenMutation?'checked':''}> 🧬 啟用自動突變管理
                                </label>
                                <label style="display:block; margin-bottom:8px; font-weight:bold; color:#1565c0;">
                                    <input type="checkbox" id="chk-garden-smart" ${Config.Flags.GardenAvoidBuff?'checked':''}> 🧠 聰明補種 (Buff 期間暫停)
                                </label>
                                <div style="display:flex; gap:5px;">
                                    <button id="garden-save-btn" style="flex:1; padding:6px; background:#2196f3; color:white; border:none; border-radius:4px; cursor:pointer;">💾 記憶陣型</button>
                                    <button id="btn-show-grid" style="flex:1; padding:6px; background:#8d6e63; color:white; border:none; border-radius:4px; cursor:pointer;">🗺️ 顯示記憶</button>
                                </div>
                            </div>
                        </div>

                        <!-- 4. 設定頁籤 -->
                        <div id="tab-settings" class="cc-tab-pane">
                            <div class="panel-section" style="margin-bottom:10px; padding:10px; background:#f3e5f5; border-radius:8px;">
                                <div style="font-weight:bold; color:#4a148c; margin-bottom:5px;">⚙️ 其他設定</div>
                                <label style="display:block; font-size:13px; color:#333;"><input type="checkbox" id="chk-spell" ${Config.Flags.Spell?'checked':''}> 🧙‍♂️ 基礎魔法連擊</label>
                                <label style="display:block; font-size:13px; color:#333;"><input type="checkbox" id="chk-ui-count" ${Config.Flags.ShowCountdown?'checked':''}> ⏱️ 倒數計時</label>
                                <label style="display:block; font-size:13px; color:#333;"><input type="checkbox" id="chk-ui-buff" ${Config.Flags.ShowBuffMonitor?'checked':''}> 🔥 Buff 監控</label>
                                <label style="display:block; font-size:13px; color:#333; font-weight: bold; margin-top: 5px;">
                                    <input type="checkbox" id="chk-ui-log" checked> 📜 操作日誌面板
                                </label>

                                <div style="margin-top:12px; color:#333;">
                                    <span style="font-size:13px; font-weight:bold;">點擊速度: <span id="spd-val">${Config.Settings.ClickInterval}</span>ms</span>
                                    <input type="range" id="spd-slider" min="10" max="200" value="${Config.Settings.ClickInterval}" style="width:100%; margin-top: 8px;">
                                </div>
                                 <div style="margin-top:10px; border-top:1px solid #ccc; padding-top:8px; color:#333;">
                                     <span style="font-size:13px;">自動重啟:</span>
                                     <select id="rst-hr">${generateOptions(0, 24, rstHr, '時')}</select>
                                     <select id="rst-min">${generateOptions(0, 59, rstMin, '分')}</select>
                                     <button id="btn-force-restart" style="float:right; background:#ff5252; color:white; border:none; padding:4px 10px; border-radius:4px; cursor:pointer;">立即重啟</button>
                                </div>
                            </div>
                        </div>

                    </div>
                </div>
            `);
            this.makeDraggable(this.Elements.Panel, 'panelX', 'panelY', '#panel-header');
            $('body').append(this.Elements.Panel);
            this.bindEvents();
            this.restoreTab();
        },

        restoreTab: function() {
            const lastTab = Config.Memory.LastActiveTab;
            $(`.cc-tab-btn[data-target="${lastTab}"]`).click();
        },

        togglePanel: function() {
            if (!this.Elements.Panel) this.createControlPanel();
            this.Elements.Panel.is(':visible') ? this.Elements.Panel.fadeOut(200) : this.Elements.Panel.fadeIn(200);
        },

        toggleMasterSwitch: function() {
            Config.Flags.GlobalMasterSwitch = !Config.Flags.GlobalMasterSwitch;
            GM_setValue('isGlobalMasterSwitchEnabled', Config.Flags.GlobalMasterSwitch);

            const statusBar = $('#global-status-bar');
            const statusIcon = $('#status-icon');
            const statusText = $('#status-text');
            const btn = $('#btn-toggle-master');

            if (Config.Flags.GlobalMasterSwitch) {
                statusBar.css('background', '#4caf50');
                statusIcon.text('🟢');
                statusText.text('系統運行中');
                btn.text('暫停 (F8)');
                Logger.success('Core', '全局自動化已啟動');
            } else {
                statusBar.css('background', '#f44336');
                statusIcon.text('🔴');
                statusText.text('系統已暫停');
                btn.text('恢復 (F8)');
                Logger.warn('Core', '全局自動化已暫停');
            }
            this.updateButtonState();
        },

        createCountdown: function() {
            if (this.Elements.Countdown) return;
            this.Elements.Countdown = $(`
                <div id="cookie-countdown" style="
                    position: fixed; left: ${Config.Memory.CountdownX}px; top: ${Config.Memory.CountdownY}px; padding: 8px; background: rgba(0,0,0,0.85); color: white;
                    border-radius: 8px; font-family: monospace; font-size: 12px; z-index: 999997; display: ${Config.Flags.ShowCountdown ? 'block' : 'none'};
                    width: 150px; cursor: move; border: 1px solid #444;
                ">
                    <div style="text-align: center; border-bottom: 1px solid #555; margin-bottom: 4px;">
                        ⏱️ 倒數計時 v8.5.4-hotfix
                        <div class="cc-close-btn" id="countdown-close" style="top:2px; right:2px; font-size:10px;">✕</div>
                    </div>
                    <div style="display:flex; justify-content:space-between;"><span>🔄 重啟:</span><span id="txt-rst">--:--</span></div>
                    <div style="display:flex; justify-content:space-between; margin-bottom:5px;"><span>🛒 購買:</span><span id="txt-buy">--:--</span></div>
                    <div style="border-top:1px solid #555; padding-top:5px; text-align:center;">
                        <div style="font-size:10px; margin-bottom:2px;">🔊 音量: <span id="vol-disp">${Config.Settings.Volume}</span>%</div>
                        <input type="range" id="volume-slider-mini" min="0" max="100" value="${Config.Settings.Volume}" style="width:90%;">
                    </div>
                </div>
            `);
            this.Elements.Countdown.find('#volume-slider-mini').on('input', function() {
                Config.Settings.Volume = parseInt($(this).val());
                $('#vol-disp').text(Config.Settings.Volume);
                try { if (Game.setVolume) Game.setVolume(Config.Settings.Volume); } catch(e) {}
                GM_setValue('gameVolume', Config.Settings.Volume);
            });
            this.Elements.Countdown.find('#countdown-close').click(() => {
                $('#chk-ui-count').prop('checked', false).trigger('change');
            });
            this.makeDraggable(this.Elements.Countdown, 'countdownX', 'countdownY');
            $('body').append(this.Elements.Countdown);
        },

        createBuffMonitor: function() {
            if (this.Elements.BuffMonitor) return;
            this.Elements.BuffMonitor = $(`
                <div id="cookie-buff-monitor" style="
                    position: fixed; left: ${Config.Memory.BuffX}px; top: ${Config.Memory.BuffY}px; padding: 10px; background: rgba(0,0,0,0.85);
                    color: white; border-radius: 12px; font-family: 'Microsoft YaHei', sans-serif; z-index: 999996;
                    display: ${Config.Flags.ShowBuffMonitor ? 'block' : 'none'}; cursor: move; width: 320px;
                    border: 1px solid rgba(255,255,255,0.2); backdrop-filter: blur(4px);
                ">
                    <div style="font-weight: bold; margin-bottom: 10px; border-bottom: 2px solid rgba(255,255,255,0.2); padding-bottom: 8px; text-align: center; color: #ffd700;">
                        🔥 Buff 監控
                        <div class="cc-close-btn" id="buff-monitor-close">✕</div>
                    </div>
                    <div id="buff-list-content" style="display: flex; flex-direction: column; gap: 8px;"></div>
                </div>
            `);
            this.Elements.BuffMonitor.find('#buff-monitor-close').click(() => {
                $('#chk-ui-buff').prop('checked', false).trigger('change');
            });
            this.makeDraggable(this.Elements.BuffMonitor, 'buffX', 'buffY');
            $('body').append(this.Elements.BuffMonitor);
        },

        updateBuffDisplay: function() {
            if (!Config.Flags.ShowBuffMonitor || !this.Elements.BuffMonitor) return;
            const buffList = $('#buff-list-content');
            buffList.empty();

            let totalCpsMult = 1;
            let totalClickMult = 1;
            let hasBuff = false;

            if (Game.buffs) {
                for (let i in Game.buffs) {
                    hasBuff = true;
                    const buff = Game.buffs[i];

                    if (buff.multCpS > 0) totalCpsMult *= buff.multCpS;
                    if (buff.multClick > 0) totalClickMult *= buff.multClick;

                    const iconUrl = 'img/icons.png';
                    const iconX = buff.icon[0] * 48;
                    const iconY = buff.icon[1] * 48;

                    const isPowerful = buff.multCpS > 50 || buff.multClick > 10;
                    const textColor = isPowerful ? '#ff4444' : 'white';
                    const bgColor = isPowerful ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.2)';

                    const buffName = UI.cleanName(buff.dname ? buff.dname : buff.name);

                    let multDisplay = '';
                    if (buff.multCpS > 0 && buff.multCpS !== 1) multDisplay = `產量 x${Math.round(buff.multCpS*10)/10}`;
                    if (buff.multClick > 0 && buff.multClick !== 1) {
                        if(multDisplay) multDisplay += ', ';
                        multDisplay += `點擊 x${Math.round(buff.multClick)}`;
                    }

                    buffList.append(`
                        <div style="display: flex; align-items: center; padding: 6px; background: ${bgColor}; border-radius: 8px; border: 1px solid rgba(255,255,255,0.05);">
                            <div style="width: 48px; height: 48px; background: url(${iconUrl}) -${iconX}px -${iconY}px; margin-right: 12px; flex-shrink: 0; border-radius:4px; box-shadow: 0 0 5px rgba(0,0,0,0.5);"></div>
                            <div>
                                <div style="font-size: 14px; font-weight: bold; color: ${textColor};">${buffName}</div>
                                <div style="font-size: 12px; color: #ffd700;">${multDisplay}</div>
                                <div style="font-size: 12px; color: #ccc;">剩餘: ${Math.ceil(buff.time / 30)}s</div>
                            </div>
                        </div>
                    `);
                }
            }

            if (!hasBuff) buffList.append('<div style="text-align: center; color: #666; font-size: 13px; padding: 10px;">無活性效果</div>');

            let summaryHtml = '<div style="margin-top: 8px; padding-top: 8px; border-top: 1px dashed rgba(255,255,255,0.3); text-align: right;">';
            let effectiveClickPower = totalCpsMult * totalClickMult;

            if (totalCpsMult !== 1) {
                let val = totalCpsMult < 1 ? totalCpsMult.toFixed(2) : Math.round(totalCpsMult).toLocaleString();
                summaryHtml += `<div style="color: #4caf50; font-weight: bold; font-size: 14px;">🏭 總產量: x${val}</div>`;
            }

            if (effectiveClickPower > 1) {
                let val = Math.round(effectiveClickPower).toLocaleString();
                summaryHtml += `<div style="color: #ff9800; font-weight: bold; font-size: 16px; margin-top: 2px;">⚡ 點擊倍率: x${val}</div>`;
            }

            if (typeof Game.computedMouseCps !== 'undefined') {
                let clickVal = Game.computedMouseCps;
                let formattedClick = typeof Beautify !== 'undefined' ? Beautify(clickVal) : Math.round(clickVal).toLocaleString();
                summaryHtml += `<div style="margin-top:5px; padding-top:5px; border-top:1px solid rgba(255,255,255,0.1); color:#fff; font-size:15px; font-family:monospace;">👆 點擊力: <span style="color: #ffd700;">+${formattedClick}</span></div>`;
            }

            summaryHtml += '</div>';
            buffList.append(summaryHtml);
        },

        makeDraggable: function(element, keyX, keyY, handleSelector = null) {
            let isDragging = false, startX = 0, startY = 0;
            const handle = handleSelector ? element.find(handleSelector) : element;
            handle.on('mousedown', function(e) {
                if ($(e.target).is('input, select, button')) return;
                isDragging = true; startX = e.clientX - parseInt(element.css('left')); startY = e.clientY - parseInt(element.css('top'));
            });
            $(document).on('mousemove', function(e) {
                if (isDragging) element.css({left: e.clientX - startX + 'px', top: e.clientY - startY + 'px'});
            }).on('mouseup', function() {
                if (isDragging) { isDragging = false; GM_setValue(keyX, parseInt(element.css('left'))); GM_setValue(keyY, parseInt(element.css('top'))); }
            });
        },

        bindEvents: function() {
            const self = this;

            $('.cc-tab-btn').click(function() {
                const target = $(this).data('target');
                $('.cc-tab-btn').removeClass('active');
                $(this).addClass('active');
                $('.cc-tab-pane').removeClass('active');
                $('#tab-' + target).addClass('active');
                Config.Memory.LastActiveTab = target;
                GM_setValue('lastActiveTab', target);
            });

            const bindChkWithLock = (id, key) => {
                $('#' + id).change(function() {
                    if (Config.Flags.SpendingLocked) {
                        this.checked = Config.Flags[key];
                        Logger.warn('花園保護', '支出鎖定期間無法修改此項目');
                        return false;
                    }
                    Config.Flags[key] = this.checked;
                    GM_setValue('is' + key + 'Enabled', this.checked);
                    if(key==='Click') self.updateButtonState();
                });
            };

            const bindChk = (id, key) => {
                $('#'+id).change(function() {
                    Config.Flags[key] = this.checked;
                    GM_setValue('is'+key+(key.includes('Enabled')?'':'Enabled'), this.checked);
                    if(key==='Click') self.updateButtonState();
                    if(key==='ShowCountdown') self.Elements.Countdown.toggle(this.checked);
                    if(key==='ShowBuffMonitor') self.Elements.BuffMonitor.toggle(this.checked);
                    if(key==='GardenOverlay') Logic.Garden.clearOverlay();
                });
            };

            bindChk('chk-auto-click', 'Click');
            bindChkWithLock('chk-auto-buy', 'Buy');
            bindChk('chk-auto-golden', 'Golden');
            bindChkWithLock('chk-auto-garden', 'Garden');
            bindChkWithLock('chk-research', 'Research');
            bindChk('chk-wrinkler', 'AutoWrinkler');
            bindChkWithLock('chk-stock', 'Stock');
            bindChk('chk-se', 'SE');
            bindChk('chk-spell', 'Spell');
            bindChk('chk-ui-count', 'ShowCountdown');
            bindChk('chk-ui-buff', 'ShowBuffMonitor');
            bindChk('chk-garden-overlay', 'GardenOverlay');
            bindChk('chk-garden-mutation', 'GardenMutation');
            bindChk('chk-garden-smart', 'GardenAvoidBuff');
            bindChk('chk-season', 'Season');
            bindChk('chk-santa', 'Santa');

            $('#chk-ui-log').change(function() { UI.ActionLog.toggle(this.checked); });
            $('#btn-toggle-master').click(function() { UI.toggleMasterSwitch(); });
            $('#btn-toggle-master').hover(
                function() { $(this).css('background', 'rgba(255, 255, 255, 0.3)'); },
                function() { $(this).css('background', 'rgba(255, 255, 255, 0.2)'); }
            );

            $('#chk-show-garden-protection').change(function() {
                Config.Flags.ShowGardenProtection = this.checked;
                GM_setValue('showGardenProtection', this.checked);
                UI.GardenProtection.updateVisibility();
            });

            $('#garden-save-btn').click(() => Logic.Garden.saveLayout());
            $('#main-panel-close').click(() => self.togglePanel());

            $('#chk-godzamok').change(function() { Config.Flags.GodzamokCombo = this.checked; GM_setValue('isGodzamokComboEnabled', this.checked); });
            $('#val-godzamok-amount').change(function() { Config.Settings.GodzamokSellAmount = parseInt(this.value); });
            $('#val-godzamok-target').change(function() { Config.Settings.GodzamokTargetBuilding = this.value; });
            $('#val-godzamok-min').change(function() { Config.Settings.GodzamokMinMult = parseInt(this.value); });

            $('#btn-show-grid').click(() => UI.GardenGrid.toggle());

            $('#buy-strategy').change(function() { Config.Settings.BuyStrategy = $(this).val(); GM_setValue('buyStrategy', Config.Settings.BuyStrategy); });
            $('#spd-slider').on('input', function() { Config.Settings.ClickInterval = parseInt($(this).val()); $('#spd-val').text(Config.Settings.ClickInterval); GM_setValue('clickInterval', Config.Settings.ClickInterval); });

            const updateBuyInt = () => {
                const min = parseInt($('#buy-min').val()); const sec = parseInt($('#buy-sec').val());
                Config.Settings.BuyIntervalMs = (min * 60 + sec) * 1000;
                GM_setValue('buyIntervalMinutes', min); GM_setValue('buyIntervalSeconds', sec);
            };
            $('#buy-min, #buy-sec').change(updateBuyInt);

            const updateRstInt = () => {
                const hr = parseInt($('#rst-hr').val()); const min = parseInt($('#rst-min').val());
                Config.Settings.RestartIntervalMs = (hr * 3600 + min * 60) * 1000;
                Core.scheduleRestart();
                GM_setValue('restartIntervalHours', hr); GM_setValue('restartIntervalMinutes', min);
            };
            $('#rst-hr, #rst-min').change(updateRstInt);

            $('#btn-force-restart').click(() => { if(confirm('確定要刷新?')) Core.performRestart(); });
        }
    };

    // ═══════════════════════════════════════════════════════════════
    // 可視化操作日誌面板
    // ═══════════════════════════════════════════════════════════════
    UI.ActionLog = {
        Elements: {
            Container: null,
            LogList: null,
            Counter: null
        },
        MaxEntries: 100,
        lastMsgContent: null,
        lastMsgCount: 1,
        lastMsgElement: null,

        create: function() {
            if (this.Elements.Container) return;
            const fontSize = Config.Memory.LogFontSize;
            const opacity = Config.Memory.LogOpacity;

            this.Elements.Container = $(`
                <div id="action-log-panel" style="
                    position: fixed; left: ${Config.Memory.ActionLogX}px; top: ${Config.Memory.ActionLogY}px;
                    width: 400px; max-height: 400px; background: rgba(0, 0, 0, ${opacity}); color: white;
                    border: 2px solid #2196f3; border-radius: 8px; padding: 0; z-index: 999995;
                    font-family: 'Consolas', 'Monaco', monospace; font-size: ${fontSize}px;
                    box-shadow: 0 4px 20px rgba(33, 150, 243, 0.5); cursor: move; display: none; overflow: hidden;
                ">
                    <div style="padding: 10px; font-weight: bold; font-size: 14px; text-align: center; border-bottom: 1px solid #2196f3; display: flex; justify-content: space-between; align-items: center; background: rgba(33, 150, 243, 0.2);">
                        <span>📜 操作日誌</span>
                        <div>
                            <span id="log-counter" style="font-size: 11px; color: #64b5f6; margin-right: 15px;">0 條</span>
                            <div class="cc-close-btn" id="action-log-close">✕</div>
                        </div>
                    </div>

                    <div class="cc-log-controls">
                        <span>A</span>
                        <input type="range" class="cc-range-mini" id="log-font-slider" min="10" max="30" value="${fontSize}">
                        <span>A</span>
                        <span style="border-left:1px solid #555; height:12px; margin:0 5px;"></span>
                        <span>👁️</span>
                        <input type="range" class="cc-range-mini" id="log-opacity-slider" min="30" max="100" value="${opacity * 100}">
                    </div>

                    <div id="log-list" style="max-height: 250px; overflow-y: auto; overflow-x: hidden; padding: 5px;">
                        <div style="text-align: center; color: #999; padding: 20px;">尚無日誌</div>
                    </div>
                    <div style="padding: 6px; border-top: 1px solid #444; display: flex; gap: 5px; background: rgba(0,0,0,0.2);">
                        <button id="btn-clear-log" style="flex: 1; padding: 4px; background: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 11px;">🗑️ 清空</button>
                    </div>
                </div>
            `);

            $('body').append(this.Elements.Container);
            this.Elements.LogList = $('#log-list');
            this.Elements.Counter = $('#log-counter');
            this.bindEvents();
            UI.makeDraggable(this.Elements.Container, 'actionLogX', 'actionLogY');
        },

        bindEvents: function() {
            $('#btn-clear-log').click(() => this.clear());
            $('#btn-clear-log').hover(
                function() { $(this).css('background', '#d32f2f'); },
                function() { $(this).css('background', '#f44336'); }
            );
            this.Elements.Container.find('#action-log-close').click(() => {
                this.toggle(false);
            });

            $('#log-font-slider').on('input', function() {
                const size = $(this).val();
                $('#action-log-panel').css('font-size', size + 'px');
                Config.Memory.LogFontSize = size;
                GM_setValue('logFontSize', size);
            });

            $('#log-opacity-slider').on('input', function() {
                const opacity = $(this).val() / 100;
                $('#action-log-panel').css('background', `rgba(0, 0, 0, ${opacity})`);
                Config.Memory.LogOpacity = opacity;
                GM_setValue('logOpacity', opacity);
            });
        },

        append: function(message, level = 'info') {
            if (!this.Elements.LogList) return;
            const colors = { info: '#2196f3', warn: '#ff9800', error: '#f44336', success: '#4caf50' };
            const icons = { info: 'ℹ️', warn: '⚠️', error: '❌', success: '✅' };
            const color = colors[level] || colors.info;
            const icon = icons[level] || icons.info;
            const cleanMsg = UI.cleanName(message);

            if (this.lastMsgContent === cleanMsg && this.lastMsgElement && this.Elements.LogList.has(this.lastMsgElement).length) {
                this.lastMsgCount++;
                const timestamp = new Date().toLocaleTimeString('zh-TW', { hour12: false });
                this.lastMsgElement.find('.log-time').text(timestamp);

                let countBadge = this.lastMsgElement.find('.log-count');
                if (countBadge.length === 0) {
                    this.lastMsgElement.append(`<span class="log-count" style="float:right; background:#ffd700; color:#000; padding:0 4px; border-radius:4px; font-size:10px; font-weight:bold;">x${this.lastMsgCount}</span>`);
                } else {
                    countBadge.text(`x${this.lastMsgCount}`);
                }
                this.Elements.LogList.prepend(this.lastMsgElement);
                return;
            }

            this.lastMsgContent = cleanMsg;
            this.lastMsgCount = 1;
            const timestamp = new Date().toLocaleTimeString('zh-TW', { hour12: false });

            const entry = $(`
                <div style="padding: 4px; margin-bottom: 2px; background: rgba(255, 255, 255, 0.05); border-left: 3px solid ${color}; border-radius: 4px; line-height: 1.4; word-break: break-word;">
                    <span class="log-time" style="color: #999;">${timestamp}</span>
                    <span style="color: ${color}; margin: 0 4px;">${icon}</span>
                    <span class="log-content" style="color: #fff;">${cleanMsg}</span>
                </div>
            `);

            this.lastMsgElement = entry;
            this.Elements.LogList.find('div:contains("尚無日誌")').remove();
            this.Elements.LogList.prepend(entry);

            const entries = this.Elements.LogList.children();
            if (entries.length > this.MaxEntries) entries.last().remove();
            this.Elements.Counter.text(`${entries.length} 條`);
        },

        clear: function() {
            if (!this.Elements.LogList) return;
            this.Elements.LogList.html(`<div style="text-align: center; color: #999; padding: 20px;">尚無日誌</div>`);
            this.Elements.Counter.text('0 條');
            this.lastMsgContent = null;
            this.lastMsgElement = null;
        },

        toggle: function(visible) {
            if (!this.Elements.Container) return;
            visible ? this.Elements.Container.fadeIn(200) : this.Elements.Container.fadeOut(200);
            $('#chk-ui-log').prop('checked', visible);
        }
    };

    // ═══════════════════════════════════════════════════════════════
    // 花園陣型可視化 (✅ v8.5.4-hotfix 修正:抽屜定位抖動問題)
    // ═══════════════════════════════════════════════════════════════
    UI.GardenGrid = {
        Elements: { Container: null },

        create: function() {
            if (this.Elements.Container) return;

            // 構建 DOM:核心三欄 + 底部清單
            this.Elements.Container = $(`
                <div id="garden-grid-panel" style="
                    position: fixed; left: ${Config.Memory.GardenGridX}px; top: ${Config.Memory.GardenGridY}px;
                    background: rgba(0,0,0,0.95); color: white; border: 2px solid #8d6e63;
                    border-radius: 8px; padding: 15px; z-index: 999997; display: none;
                    cursor: move; font-family: Arial;
                    /* 寬度隨內容變化,transition 讓展開平滑 */
                    width: fit-content; transition: all 0.3s ease;
                    max-height: 85vh; overflow-y: auto;
                ">
                    <div style="font-weight:bold; font-size:15px; margin-bottom:12px; border-bottom:1px solid #8d6e63; padding-bottom:6px; display:flex; justify-content:space-between;">
                        <span>🗺️ 記憶陣型預覽</span>
                        <div class="cc-close-btn" id="garden-grid-close" style="font-size:14px;">✕</div>
                    </div>

                    <!-- 核心三欄區 -->
                    <div class="cc-garden-row">

                        <!-- 左抽屜:已解鎖 -->
                        <div id="drawer-left" class="cc-drawer cc-garden-side">
                            <div style="padding: 10px; width: 220px; box-sizing: border-box;">
                                <div style="text-align:center; font-weight:bold; color:#81c784; font-size:14px; border-bottom:1px solid #444; margin-bottom:5px; padding-bottom:3px;">
                                    已解鎖圖鑑
                                </div>
                                <ul id="cc-garden-list-unlocked" style="font-size:13px;"></ul>
                            </div>
                        </div>

                        <!-- 中央:田 + 按鈕 (定海神針) -->
                        <div class="cc-center-stage">
                            <!-- 控制列 -->
                            <div style="display:flex; justify-content:center; align-items:center; gap:10px; margin-bottom:12px; width:100%;">
                                <button id="cc-btn-expand-left" style="
                                    padding: 4px 10px; background: #333; color: white; border: 1px solid #555;
                                    border-radius: 4px; cursor: pointer; font-size: 13px; font-weight:bold;
                                ">◀ 展開</button>

                                <span id="cc-garden-progress" style="
                                    font-size: 18px; font-weight: bold; color: #ffd700;
                                    min-width: 80px; text-align: center;
                                ">--/--</span>

                                <button id="cc-btn-expand-right" style="
                                    padding: 4px 10px; background: #333; color: white; border: 1px solid #555;
                                    border-radius: 4px; cursor: pointer; font-size: 13px; font-weight:bold;
                                ">展開 ▶</button>
                            </div>

                            <!-- 6×6 網格 -->
                            <div id="garden-grid-content" style="
                                display: grid; grid-template-columns: repeat(6, 48px); grid-template-rows: repeat(6, 48px);
                                gap: 4px; justify-content: center; background: #111; padding: 10px;
                                border: 2px solid #8d6e63; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.5);
                            "></div>
                        </div>

                        <!-- 右抽屜:未解鎖 -->
                        <div id="drawer-right" class="cc-drawer cc-garden-side">
                            <div style="padding: 10px; width: 220px; box-sizing: border-box;">
                                <div style="text-align:center; font-weight:bold; color:#ffcc80; font-size:14px; border-bottom:1px solid #444; margin-bottom:5px; padding-bottom:3px;">
                                    未解鎖清單
                                </div>
                                <ul id="cc-garden-list-locked" style="font-size:13px;"></ul>
                            </div>
                        </div>
                    </div>

                    <!-- 底部:當前陣型清單 (永遠顯示) -->
                    <div style="margin-top: 15px; padding-top: 10px; border-top: 2px solid #8d6e63; width: 100%;">
                        <div style="text-align:center; font-weight:bold; color:#64b5f6; font-size:14px; margin-bottom:8px;">
                            📋 當前陣型清單
                        </div>
                        <ul id="cc-garden-current-layout" style="
                            list-style: none; padding: 0; margin: 0;
                            display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px;
                            font-size: 13px; color: #ccc;
                        "></ul>
                        <div id="cc-garden-empty-hint" style="text-align: center; color: #777; font-size: 13px; padding: 10px; display: none;">
                            尚未記憶任何陣型
                        </div>
                    </div>
                </div>
            `);

            $('body').append(this.Elements.Container);
            this.Elements.Container.find('#garden-grid-close').click(() => this.toggle());

            // 綁定按鈕
            $('#cc-btn-expand-left').click(() => this.toggleSide('left'));
            $('#cc-btn-expand-right').click(() => this.toggleSide('right'));

            // 恢復記憶的狀態
            if (Config.Memory.GardenLeftExpanded) this.toggleSide('left', true);
            if (Config.Memory.GardenRightExpanded) this.toggleSide('right', true);

            UI.makeDraggable(this.Elements.Container, 'gardenGridX', 'gardenGridY');
        },

        toggle: function() {
            if (!this.Elements.Container) this.create();
            if (this.Elements.Container.is(':visible')) {
                this.Elements.Container.fadeOut(200);
            } else {
                this.update();
                this.Elements.Container.fadeIn(200);
            }
        },

        toggleSide: function(side, forceOpen = null) {
            const drawer = $(`#drawer-${side}`);
            const btn = $(`#cc-btn-expand-${side}`);
            const container = this.Elements.Container;
            
            // ✅ v8.5.4-hotfix 修正:不再修改 centerStage 寬度,只移動容器位置
            const drawerWidth = 220;
            const currentX = parseInt(container.css('left')) || Config.Memory.GardenGridX;

            const isOpen = forceOpen !== null ? forceOpen : !drawer.hasClass('open');

            if (isOpen) {
                // 開啟抽屜
                if (side === 'left') {
                    // 左抽屜開啟:左移面板防止Grid右跑
                    const newX = Math.max(0, currentX - drawerWidth);
                    container.css('left', newX + 'px');
                    // ✅ 刪除 centerStage 寬度修改
                } else {
                    // 右抽屜開啟:保持位置,不修改寬度
                    // ✅ 刪除 centerStage 寬度修改
                }
                
                drawer.addClass('open');
                btn.text(side === 'left' ? '▶ 收起' : '收起 ◀');
                Config.Memory[side === 'left' ? 'GardenLeftExpanded' : 'GardenRightExpanded'] = true;
                GM_setValue(side === 'left' ? 'gardenLeftExpanded' : 'gardenRightExpanded', true);
                
                // 保存新位置(左抽屜)
                if (side === 'left') {
                    Config.Memory.GardenGridX = newX;
                    GM_setValue('gardenGridX', newX);
                }
            } else {
                // 關閉抽屜
                if (side === 'left') {
                    // 左抽屜關閉:右移面板恢復位置
                    const newX = currentX + drawerWidth;
                    container.css('left', newX + 'px');
                    // ✅ 刪除 centerStage 寬度修改
                    
                    // 保存新位置
                    Config.Memory.GardenGridX = newX;
                    GM_setValue('gardenGridX', newX);
                } else {
                    // 右抽屜關閉:不修改寬度
                    // ✅ 刪除 centerStage 寬度修改
                }
                
                drawer.removeClass('open');
                btn.text(side === 'left' ? '◀ 展開' : '展開 ▶');
                Config.Memory[side === 'left' ? 'GardenLeftExpanded' : 'GardenRightExpanded'] = false;
                GM_setValue(side === 'left' ? 'gardenLeftExpanded' : 'gardenRightExpanded', false);
            }
        },

        update: function() {
            const plot = Config.Memory.SavedGardenPlot;
            const gridContent = $('#garden-grid-content').empty();
            const unlockedList = $('#cc-garden-list-unlocked').empty();
            const lockedList = $('#cc-garden-list-locked').empty();
            const currentLayoutList = $('#cc-garden-current-layout').empty();
            const emptyHint = $('#cc-garden-empty-hint');

            let plantStats = {};

            if (typeof Game !== 'undefined' && Game.Objects['Farm'].minigame) {
                const M = Game.Objects['Farm'].minigame;
                const totalPlants = 34;
                let unlockedCount = 0;

                // 1. 渲染網格
                plot.forEach(row => {
                    row.forEach(cellId => {
                        let bg = '#222';
                        let text = '';
                        let title = '空';

                        if (cellId > 0) {
                            const plant = M.plantsById[cellId - 1];
                            if (plant) {
                                bg = '#4caf50';
                                text = cellId;
                                title = plant.name;
                                // 統計
                                if (!plantStats[cellId]) plantStats[cellId] = { name: plant.name, count: 0 };
                                plantStats[cellId].count++;
                            }
                        } else if (cellId === -1) {
                            bg = '#111';
                            title = '未解鎖格子';
                        }

                        gridContent.append(`
                            <div style="
                                background:${bg}; border:1px solid #444; border-radius:4px;
                                display:flex; align-items:center; justify-content:center;
                                font-size:14px; font-weight:bold; color:white;
                                transition: transform 0.2s; cursor: default;
                            " title="${title}">
                                ${text}
                            </div>
                        `);
                    });
                });

                // 2. 左側:已解鎖
                for (let i = 1; i <= totalPlants; i++) {
                    const plant = M.plantsById[i];
                    if (plant && plant.unlocked) {
                        unlockedCount++;
                        unlockedList.append(`
                            <li><span style="color:#aaa; display:inline-block; width:24px;">[${plant.id}]</span> ${plant.name}</li>
                        `);
                    }
                }
                if (unlockedCount === 0) unlockedList.append('<li style="color:#777;">(無)</li>');

                // 3. 右側:未解鎖
                let lockedCount = 0;
                for (let i = 1; i <= totalPlants; i++) {
                    const plant = M.plantsById[i];
                    if (plant && !plant.unlocked) {
                        lockedCount++;
                        lockedList.append(`
                            <li><span style="color:#aaa; display:inline-block; width:24px;">[${plant.id}]</span> ${plant.name}</li>
                        `);
                    }
                }
                if (lockedCount === 0) lockedList.append('<li style="color:#4caf50;">✓ 全解鎖!</li>');

                // 4. 底部:當前陣型
                const sortedIds = Object.keys(plantStats).map(Number).sort((a, b) => a - b);
                if (sortedIds.length > 0) {
                    emptyHint.hide();
                    currentLayoutList.show();
                    sortedIds.forEach(id => {
                        const data = plantStats[id];
                        currentLayoutList.append(`
                            <li style="
                                padding: 6px 10px; background: rgba(13, 71, 161, 0.3);
                                border-left: 4px solid #42a5f5; border-radius: 4px;
                                display: flex; justify-content: space-between; align-items: center;
                            ">
                                <div><span style="color:#aaa;">[${id}]</span> ${data.name}</div>
                                <b style="color:#ffd700;">x${data.count}</b>
                            </li>
                        `);
                    });
                } else {
                    currentLayoutList.hide();
                    emptyHint.show();
                }

                // 5. 進度文字
                const progressColor = unlockedCount === totalPlants ? '#4caf50' : '#ffd700';
                $('#cc-garden-progress').text(`${unlockedCount}/${totalPlants}`).css('color', progressColor);

            } else {
                gridContent.html('<div style="grid-column:1/-1; text-align:center; color:#999; padding:20px;">花園未加載</div>');
                emptyHint.show();
                currentLayoutList.hide();
            }
        }
    };

    // ═══════════════════════════════════════════════════════════════
    // 花園保護模組 (✅ v8.5.4-hotfix 修正:盾牌歸屬錯誤)
    // ═══════════════════════════════════════════════════════════════
    UI.GardenProtection = {
        Elements: { 
            Container: null,
            Shield: null  // 新增:小盾牌圖示
        },
        SavedStates: { Buy: null, Garden: null, Research: null, Stock: null },
        _cachedGardenPanel: null,

        create: function() {
            if (this.Elements.Container) return;
            const Farm = Game.Objects['Farm'];
            if (!Farm || !Farm.minigameLoaded) return;
            
            // 等待花園面板加載
            const checkGardenPanel = () => {
                const gardenPanel = document.getElementById('gardenPanel');
                if (!gardenPanel) {
                    setTimeout(checkGardenPanel, 500);
                    return;
                }
                
                this.createProtectionUI(gardenPanel);
                this.createShield(gardenPanel);
            };
            
            checkGardenPanel();
        },
        
        createProtectionUI: function(gardenPanel) {
            // ✅ v8.5.4 改版:按鈕拆分為兩個
            this.Elements.Container = $(`
                <div id="garden-protection-ui" style="
                    position: absolute; left: ${Config.Memory.GardenProtectionX}px; top: ${Config.Memory.GardenProtectionY}px;
                    width: 260px; background: rgba(0, 0, 0, 0.9); color: white; border: 2px solid #81c784;
                    border-radius: 8px; padding: 12px; z-index: 10000; font-family: Arial, sans-serif;
                    box-shadow: 0 4px 20px rgba(129, 199, 132, 0.5); cursor: move; display: none;
                ">
                    <div style="font-weight: bold; font-size: 14px; margin-bottom: 10px; text-align: center; border-bottom: 1px solid #81c784; padding-bottom: 8px; display: flex; justify-content: space-between; align-items: center;">
                        <span>🛡️ 花園保護模式</span>
                        <div class="cc-close-btn" id="garden-prot-minimize">_</div>
                    </div>
                    <label id="spending-lock-label" style="display: flex; align-items: center; font-size: 13px; cursor: pointer; padding: 8px; background: rgba(255, 255, 255, 0.1); border-radius: 4px; transition: background 0.3s;">
                        <input type="checkbox" id="chk-spending-lock" style="margin-right: 8px; width: 16px; height: 16px;">
                        <span style="flex: 1;">🔒 立刻停止支出</span>
                    </label>
                    
                    <!-- ✅ v8.5.4 改版:兩個按鈕並排 -->
                    <div style="display: flex; gap: 10px; margin-top: 10px;">
                        <button id="btn-save-garden-layout" style="
                            flex: 1; padding: 8px; background: #2196f3; color: white; border: none; 
                            border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold; 
                            transition: background 0.3s;
                        ">💾 記憶陣型</button>
                        <button id="btn-show-grid" style="
                            flex: 1; padding: 8px; background: #8d6e63; color: white; border: none; 
                            border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold; 
                            transition: background 0.3s;
                        ">🗺️ 顯示記憶</button>
                    </div>
                    
                    <div style="margin-top: 10px; font-size: 11px; color: #ffcccc; text-align: center; line-height: 1.4;">
                        勾選後將鎖定:<br>購買 (誓約除外) | 花園 | 科技 | 股市
                    </div>
                </div>
            `);

            $(gardenPanel).append(this.Elements.Container);
            
            // ✅ v8.5.4 改版:最小化按鈕行為
            this.Elements.Container.find('#garden-prot-minimize').click(() => {
                this.minimize();
            });
            
            $('#spending-lock-label').hover(
                function() { $(this).css('background', 'rgba(255, 255, 255, 0.2)'); },
                function() { $(this).css('background', 'rgba(255, 255, 255, 0.1)'); }
            );
            $('#btn-save-garden-layout').hover(
                function() { $(this).css('background', '#1976d2'); },
                function() { $(this).css('background', '#2196f3'); }
            );
            $('#btn-show-grid').hover(
                function() { $(this).css('background', '#795548'); },
                function() { $(this).css('background', '#8d6e63'); }
            );

            this.bindEvents();
            UI.makeDraggable(this.Elements.Container, 'gardenProtectionX', 'gardenProtectionY');
        },
        
        createShield: function(gardenPanel) {
            if (this.Elements.Shield) return;
            
            // ✅ v8.5.4-hotfix 修正:盾牌附著在花園面板上
            this.Elements.Shield = $(`
                <div class="cc-garden-shield">🛡️</div>
            `);
            
            $(gardenPanel).append(this.Elements.Shield);
            
            // 點擊盾牌恢復面板
            this.Elements.Shield.click(() => {
                this.restore();
            });
            
            // ✅ v8.5.4-hotfix 修正:移除拖曳功能,固定在花園工具欄右上角
            this.Elements.Shield.hide();
        },

        bindEvents: function() {
            $('#chk-spending-lock').change(function() { UI.GardenProtection.toggle(this.checked); });
            $('#btn-save-garden-layout').click(function() { UI.GardenProtection.saveCurrentLayout(); });
            $('#btn-show-grid').click(function() { UI.GardenGrid.toggle(); });
        },
        
        minimize: function() {
            // 隱藏主面板
            if (this.Elements.Container) {
                this.Elements.Container.hide();
            }
            
            // 顯示小盾牌
            if (this.Elements.Shield) {
                this.Elements.Shield.show();
            }
            
            // 保存最小化狀態
            Config.Memory.GardenProtectionMinimized = true;
            GM_setValue('gardenProtectionMinimized', true);
            
            Logger.log('花園保護', '面板已最小化(點擊盾牌恢復)');
        },
        
        restore: function() {
            // 隱藏小盾牌
            if (this.Elements.Shield) {
                this.Elements.Shield.hide();
            }
            
            // 顯示主面板
            if (this.Elements.Container && Config.Flags.ShowGardenProtection) {
                this.Elements.Container.show();
            }
            
            // 保存恢復狀態
            Config.Memory.GardenProtectionMinimized = false;
            GM_setValue('gardenProtectionMinimized', false);
            
            Logger.log('花園保護', '面板已恢復');
        },

        toggle: function(enabled, uiOnly = false) {
            if (enabled) {
                if (!uiOnly) {
                    this.SavedStates.Buy = Config.Flags.Buy;
                    this.SavedStates.Garden = Config.Flags.Garden;
                    this.SavedStates.Research = Config.Flags.Research;
                    this.SavedStates.Stock = Config.Flags.Stock;

                    Config.Memory.SavedSpendingStates = { ...this.SavedStates };
                    GM_setValue('savedSpendingStates', Config.Memory.SavedSpendingStates);
                    GM_setValue('spendingLocked', true);
                }

                // ✅ v8.5.2: 不關閉 Config.Flags.Buy,只關閉其他
                Config.Flags.Garden = false;
                Config.Flags.Research = false;
                Config.Flags.Stock = false;

                // UI 視覺更新
                const buyChk = $('#chk-auto-buy');
                if (this.SavedStates.Buy) {
                    buyChk.prop('checked', true).prop('disabled', true).css('opacity', '0.5').parent().attr('title', '資金保護中:僅允許購買誓約');
                } else {
                    buyChk.prop('checked', false).prop('disabled', true).css('opacity', '0.5');
                }

                $('#chk-auto-garden').prop('checked', false).prop('disabled', true).css('opacity', '0.5');
                $('#chk-research').prop('checked', false).prop('disabled', true).css('opacity', '0.5');
                $('#chk-stock').prop('checked', false).prop('disabled', true).css('opacity', '0.5');

                this.showLockWarning();
                if (!uiOnly) Logger.log('花園保護', '已啟用支出鎖定 (允許誓約)');

            } else {
                Config.Flags.Buy = this.SavedStates.Buy !== null ? this.SavedStates.Buy : true;
                Config.Flags.Garden = this.SavedStates.Garden !== null ? this.SavedStates.Garden : true;
                Config.Flags.Research = this.SavedStates.Research !== null ? this.SavedStates.Research : true;
                Config.Flags.Stock = this.SavedStates.Stock !== null ? this.SavedStates.Stock : true;

                $('#chk-auto-buy').prop('checked', Config.Flags.Buy).prop('disabled', false).css('opacity', '1').parent().removeAttr('title');
                $('#chk-auto-garden').prop('checked', Config.Flags.Garden).prop('disabled', false).css('opacity', '1');
                $('#chk-research').prop('checked', Config.Flags.Research).prop('disabled', false).css('opacity', '1');
                $('#chk-stock').prop('checked', Config.Flags.Stock).prop('disabled', false).css('opacity', '1');

                this.hideLockWarning();
                if (!uiOnly) {
                    GM_setValue('spendingLocked', false);
                    this.SavedStates = { Buy: null, Garden: null, Research: null, Stock: null };
                    Logger.log('花園保護', '已解除支出鎖定');
                }
            }
            Config.Flags.SpendingLocked = enabled;
        },

        showLockWarning: function() {
            const panel = $('#cookie-control-panel');
            if (panel.length && !$('#spending-lock-warning').length) {
                const warning = $(`
                    <div id="spending-lock-warning" style="
                        background: linear-gradient(135deg, #ff4444 0%, #cc0000 100%); color: white; padding: 12px;
                        text-align: center; font-weight: bold; font-size: 14px; border-bottom: 2px solid rgba(255,255,255,0.3);
                        animation: pulse 2s infinite;
                    ">🔒 支出已鎖定 | 花園保護模式啟用中</div>
                    <style>@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } }</style>
                `);
                panel.prepend(warning);
            }
        },

        hideLockWarning: function() { $('#spending-lock-warning').remove(); },

        updateVisibility: function() {
            if (!this.Elements.Container || !this.Elements.Shield) return;
            
            // ✅ v8.5.4-hotfix 修正:使用 jQuery 檢查花園面板可見性
            const gardenPanel = $('#gardenPanel');
            const isGardenOpen = gardenPanel.length > 0 && gardenPanel.is(':visible');
            
            if (isGardenOpen && Config.Flags.ShowGardenProtection) {
                if (Config.Memory.GardenProtectionMinimized) {
                    // 最小化狀態:顯示盾牌,隱藏面板
                    this.Elements.Container.hide();
                    this.Elements.Shield.show();
                } else {
                    // 正常狀態:顯示面板,隱藏盾牌
                    this.Elements.Container.fadeIn(200);
                    this.Elements.Shield.hide();
                }
            } else {
                // 花園沒開,或是保護功能被禁用 -> 全部隱藏
                this.Elements.Container.fadeOut(200);
                this.Elements.Shield.hide();
            }
        },

        saveCurrentLayout: function() {
            if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigame) {
                Logger.warn('花園保護', '花園未就緒,無法記憶陣型');
                if (typeof Game !== 'undefined' && Game.Notify) Game.Notify('花園未就緒', '請先解鎖花園功能', [10, 6]);
                return;
            }
            const M = Game.Objects['Farm'].minigame;
            let newLayout = [];
            let savedCount = 0;
            for (let y = 0; y < 6; y++) {
                let row = [];
                for (let x = 0; x < 6; x++) {
                    if (M.isTileUnlocked(x, y)) {
                        const tile = M.plot[y][x];
                        const tileId = tile[0];
                        if (tileId === 0) {
                            row.push(-1);
                        } else {
                            const plant = M.plantsById[tileId - 1];
                            if (plant && plant.unlocked) {
                                row.push(tileId);
                                savedCount++;
                            } else {
                                row.push(-1);
                            }
                        }
                    } else {
                        row.push(-1);
                    }
                }
                newLayout.push(row);
            }
            Config.Memory.SavedGardenPlot = newLayout;
            GM_setValue('savedGardenPlot', Config.Memory.SavedGardenPlot);
            Logger.success('花園保護', `花園陣型已記憶(${savedCount} 種種子)`);
            if (typeof Game !== 'undefined' && Game.Notify) Game.Notify('花園陣型已記憶', `已記錄 ${savedCount} 種種子`, [10, 6], 4);
            const btn = $('#btn-save-garden-layout');
            const originalText = btn.text();
            const originalBg = btn.css('background-color');
            btn.text('✅ 已儲存!').css('background', '#4caf50');
            setTimeout(() => { btn.text(originalText).css('background', originalBg); }, 1500);
        }
    };

    // ═══════════════════════════════════════════════════════════════
    // 2. 核心邏輯模組 (Business Logic)
    // ═══════════════════════════════════════════════════════════════
    const Logic = {
        Click: {
            lastRun: 0,
            isMagicSufficient: function(current, max, threshold = 0.95, tolerance = 0.001) {
                if (max === 0) return false;
                const ratio = current / max;
                return ratio >= (threshold - tolerance);
            },
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch) return;
                if (Config.Flags.Click && now - this.lastRun >= Config.Settings.ClickInterval) {
                    const bigCookie = document.querySelector('#bigCookie');
                    if (bigCookie) { bigCookie.click(); Runtime.Stats.ClickCount++; }
                    this.lastRun = now;
                }
                if (Config.Flags.Golden) {
                    document.querySelectorAll('#shimmers > div.shimmer').forEach(c => c.click());
                }
                this.handleSpells();
            },
            handleSpells: function() {
                if ((!Config.Flags.Spell && !Config.Flags.SE) || !Game.Objects['Wizard tower'].minigame) return;
                const M = Game.Objects['Wizard tower'].minigame;
                const now = Date.now();
                if (Config.Flags.Spell && M.magic >= M.getSpellCost(M.spells['hand of fate'])) {
                    let shouldCast = false;
                    for (let i in Game.buffs) {
                        if (Game.buffs[i].multCpS > 7 || Game.buffs[i].multClick > 10) { shouldCast = true; break; }
                        if (Game.buffs[i].multCpS === 7 && M.magic >= M.magicM * 0.95) { shouldCast = true; break; }
                    }
                    if (shouldCast) {
                        M.castSpell(M.spells['hand of fate']);
                        Logger.log('AutoSpell', '觸發連擊:命運之手');
                    }
                }
                if (Config.Flags.SE && now >= Runtime.Timers.NextSpontaneousEdifice) {
                    const spell = M.spells['spontaneous edifice'];
                    const spellCost = M.getSpellCost(spell);
                    if (M.magic >= spellCost && this.isMagicSufficient(M.magic, M.magicM, 0.95) && Object.keys(Game.buffs).length === 0 && document.querySelectorAll('.shimmer').length === 0) {
                        const magicBefore = M.magic;
                        const castResult = M.castSpell(spell);
                        if (castResult && M.magic < magicBefore) {
                            Logger.log('AutoSpell', '閒置期:免費召喚了一座建築 (Spontaneous Edifice)');
                            Runtime.Stats.SEFailCount = 0;
                            Runtime.Timers.NextSpontaneousEdifice = now + Config.Settings.SpellCooldownSuccess;
                        } else {
                            Runtime.Stats.SEFailCount++;
                            if (Runtime.Stats.SEFailCount >= Config.Settings.SEFailThreshold) {
                                const fthof = M.spells['hand of fate'];
                                const fthofCost = M.getSpellCost(fthof);
                                if (M.magic >= fthofCost) {
                                    const fthofBefore = M.magic;
                                    const fthofResult = M.castSpell(fthof);
                                    if (fthofResult && M.magic < fthofBefore) {
                                        Logger.log('AutoSpell', `SE 連續失敗 ${Config.Settings.SEFailThreshold} 次,已轉為施放 FtHoF`);
                                        Runtime.Stats.SEFailCount = 0;
                                        Runtime.Timers.NextSpontaneousEdifice = now + Config.Settings.SEFailResetCooldown;
                                    } else {
                                        Logger.warn('AutoSpell', 'FtHoF 施放失敗,SE 冷卻 5 分鐘');
                                        Runtime.Stats.SEFailCount = 0;
                                        Runtime.Timers.NextSpontaneousEdifice = now + Config.Settings.SEFailResetCooldown;
                                    }
                                } else {
                                    Logger.warn('AutoSpell', '魔力不足以施放 FtHoF,SE 冷卻 5 分鐘');
                                    Runtime.Stats.SEFailCount = 0;
                                    Runtime.Timers.NextSpontaneousEdifice = now + Config.Settings.SEFailResetCooldown;
                                }
                            } else {
                                Logger.warn('AutoSpell', `SE 施法失敗 (${Runtime.Stats.SEFailCount}/${Config.Settings.SEFailThreshold}),冷卻 60 秒`);
                                Runtime.Timers.NextSpontaneousEdifice = now + Config.Settings.SpellCooldownFail;
                            }
                        }
                    }
                }
            },
            handlePrompts: function() {
                const yesButton = document.querySelector('#promptOption0');
                if (yesButton && document.querySelector('#promptContent')) {
                    const txt = document.querySelector('#promptContent').textContent;
                    if (['Warning', 'One Mind', 'revoke', '警告', '不好的结果'].some(k => txt.includes(k))) {
                        Logger.log('Safe', `Auto-confirming prompt: ${txt}`);
                        yesButton.click();
                    }
                }
            }
        },

        GodzamokCombo: {
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch || !Config.Flags.GodzamokCombo) return;
                if (now < Runtime.Timers.NextGodzamokCombo) return;

                const Temple = Game.Objects['Temple'];
                if (!Temple || !Temple.minigameLoaded) return;
                const M = Temple.minigame;
                if (M.slot[0] !== 2) return;

                let totalMult = 1;
                for (let i in Game.buffs) {
                    totalMult *= (Game.buffs[i].multCpS * Game.buffs[i].multClick);
                }
                if (totalMult < Config.Settings.GodzamokMinMult) return;

                const targetName = Config.Settings.GodzamokTargetBuilding;
                const building = Game.Objects[targetName];
                if (!building || building.amount < Config.Settings.GodzamokSellAmount) return;

                this.trigger(targetName, building, now);
            },

            trigger: function(targetName, building, now) {
                const ALLOWED_BUILDINGS = ['Farm', 'Mine', 'Factory'];
                if (!ALLOWED_BUILDINGS.includes(targetName)) {
                    Logger.error('Godzamok', `禁止賣出 ${targetName}!已攔截操作`);
                    return false;
                }

                const costToBuyBack = building.price * Config.Settings.GodzamokSellAmount * 1.5;
                if (Game.cookies < costToBuyBack) {
                    Logger.warn('Godzamok', `觸發失敗:資金不足以買回 (需 ${costToBuyBack})`);
                    Runtime.Timers.NextGodzamokCombo = now + 5000;
                    return;
                }

                Logger.log('Godzamok', `觸發連擊!倍率滿足條件`);

                if (!Config.Flags.SpendingLocked) {
                     $('#chk-spending-lock').prop('checked', true).trigger('change');
                }

                building.sell(Config.Settings.GodzamokSellAmount);
                Runtime.GodzamokState.soldAmount = Config.Settings.GodzamokSellAmount;
                Runtime.GodzamokState.isActive = true;

                setTimeout(() => {
                    this.buyBack(targetName);
                }, Config.Settings.GodzamokBuyBackTime);

                Runtime.Timers.NextGodzamokCombo = now + Config.Settings.GodzamokCooldown;
            },

            buyBack: function(targetName) {
                const building = Game.Objects[targetName];
                const targetAmount = building.amount + Runtime.GodzamokState.soldAmount;

                Logger.log('Godzamok', `開始買回 ${targetName}...`);

                let bought = 0;
                let loops = 0;
                while (building.amount < targetAmount && building.price <= Game.cookies && loops < 1000) {
                    building.buy(1);
                    bought++;
                    loops++;
                }

                if (bought >= Runtime.GodzamokState.soldAmount) {
                    Logger.success('Godzamok', `已買回 ${bought} 座建築`);
                } else {
                    Logger.warn('Godzamok', `資金不足/迴圈限制,僅買回 ${bought}/${Runtime.GodzamokState.soldAmount}`);
                }

                Runtime.GodzamokState.isActive = false;
                Runtime.GodzamokState.soldAmount = 0;

                if (Config.Flags.SpendingLocked) {
                     $('#chk-spending-lock').prop('checked', false).trigger('change');
                }
            }
        },

        SugarLump: {
            update: function(now) {
                const statusEl = $('#lump-status');
                if (!Config.Flags.Golden) {
                    if (statusEl.length) statusEl.text('🍬 糖塊監控:已停用').css('color', '#999').css('border-left-color', '#999');
                    return;
                }
                if (typeof Game === 'undefined' || !Game.canLumps()) {
                    if (statusEl.length) statusEl.text('🍬 糖塊監控:未解鎖').css('color', '#999').css('border-left-color', '#999');
                    return;
                }
                const age = Date.now() - Game.lumpT;
                const type = Game.lumpCurrentType;
                const ripeAge = Game.lumpRipeAge;
                let statusText = ''; let statusColor = '#666'; let borderColor = '#ccc'; let action = '';
                switch (type) {
                    case 3:
                        statusText = '⛔ [肉色糖塊] 啟動保護:等待自然掉落'; statusColor = '#d32f2f'; borderColor = '#d32f2f'; action = 'SKIP';
                        break;
                    case 2: case 4:
                        if (age >= ripeAge) action = 'HARVEST_NOW';
                        else { statusText = `💎 [稀有糖塊] 等待成熟 (${UI.formatMs(ripeAge - age)})`; statusColor = '#e65100'; borderColor = '#ffd700'; }
                        break;
                    case 1:
                        if (age >= ripeAge) {
                            if ((Game.lumps / Config.Settings.SugarLumpGoal) > 0.9) action = 'HARVEST_NOW';
                            else action = 'HARVEST_NOW';
                        } else { statusText = `🌿 [雙倍糖塊] 等待成熟 (${UI.formatMs(ripeAge - age)})`; statusColor = '#2e7d32'; borderColor = '#4caf50'; }
                        break;
                    default:
                        if (age >= ripeAge) action = 'HARVEST_NOW';
                        else { statusText = `🍬 [普通糖塊] 等待成熟 (${UI.formatMs(ripeAge - age)})`; statusColor = '#555'; borderColor = '#ccc'; }
                        break;
                }
                if (action === 'HARVEST_NOW') {
                    if (Config.Flags.GlobalMasterSwitch) {
                        if (Game.lumpCurrentType !== 3) {
                            Game.clickLump();
                            Logger.log('SmartLump', `自動收割糖塊 (Type: ${type})`);
                            statusText = '⚡ 正在收割...'; statusColor = '#4caf50'; borderColor = '#4caf50';
                        } else {
                            Logger.warn('SmartLump', '攔截危險操作:試圖點擊肉色糖塊!');
                        }
                    }
                }
                if (statusEl.length) { statusEl.text(statusText).css({ 'color': statusColor, 'border-left-color': borderColor }); }
            }
        },

        Buy: {
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch) return;
                if (!Config.Flags.Buy || now < Runtime.Timers.NextBuy) return;
                if (typeof Game === 'undefined') return;

                // ⭐ 1. 誓約例外 (最高優先)
                const pledge = Game.Upgrades['Elder Pledge'];
                if (pledge && pledge.unlocked && pledge.canBuy()) {
                    if (typeof Game.pledgeT === 'undefined' || Game.pledgeT <= 0) {
                        Logger.log('自動購買', '誓約過期,強制優先購買!');
                        pledge.buy();
                        Runtime.Timers.NextBuy = now + Config.Settings.BuyIntervalMs;
                        return;
                    }
                }

                // ⭐ 2. 智慧鎖定攔截
                if (Config.Flags.SpendingLocked) return;

                // 3. 科技研發
                if (Config.Flags.Research) {
                    const research = document.querySelectorAll('#techUpgrades .crate.upgrade.enabled');
                    if (research.length > 0) {
                        const item = research[0];
                        let resName = "未知科技";
                        const dataId = item.getAttribute('data-id');
                        if (dataId && Game.UpgradesById[dataId]) {
                            resName = Game.UpgradesById[dataId].dname || Game.UpgradesById[dataId].name;
                        } else {
                            const onMouseOver = item.getAttribute('onmouseover');
                            if (onMouseOver) {
                                 const match = /<div class="name">(.+?)<\/div>/.exec(onMouseOver);
                                 if (match) resName = match[1];
                            }
                        }
                        Logger.log('自動購買', `研發科技:${UI.cleanName(resName)}`);
                        item.click();
                        Runtime.Timers.NextBuy = now + Config.Settings.BuyIntervalMs;
                        return;
                    }
                }

                // 4. 升級購買
                let affordable = Game.UpgradesInStore.filter(u => u.canBuy());
                affordable = affordable.filter(u => {
                    if (u.id === 84) return false;
                    if (u.id === 85) return false;
                    if (u.id === 74) return false;
                    if (u.pool === 'toggle') {
                        const seasonSwitchIds = [182, 183, 184, 185, 209];
                        if (!seasonSwitchIds.includes(u.id)) return false;
                    }
                    if (Config.Flags.Season) {
                        const seasonSwitchIds = [182, 183, 184, 185, 209];
                        if (seasonSwitchIds.includes(u.id)) return false;
                    }
                    return true;
                });
                if (affordable.length > 0) {
                    if (Config.Settings.BuyStrategy === 'expensive') affordable.sort((a, b) => b.getPrice() - a.getPrice());
                    else affordable.sort((a, b) => a.getPrice() - b.getPrice());
                    const target = affordable[0];
                    let upName = target.dname || target.name;
                    Logger.log('自動購買-升級', UI.cleanName(upName));
                    target.buy();
                    Runtime.Stats.BuyUpgradeCount++;
                    Runtime.Timers.NextBuy = now + Config.Settings.BuyIntervalMs;
                    return;
                }

                // 5. 種子檢查
                if (Config.Flags.Garden) {
                    const Farm = Game.Objects['Farm'];
                    if (Farm.minigameLoaded && Farm.minigame) {
                        const M = Farm.minigame;
                        let needsSeeds = false;
                        outerLoop:
                        for (let y = 0; y < 6; y++) {
                            for (let x = 0; x < 6; x++) {
                                if (M.isTileUnlocked(x, y)) {
                                    const savedId = Config.Memory.SavedGardenPlot[y][x];
                                    const currentTile = M.plot[y][x];
                                    if (savedId > -1 && currentTile[0] === 0) {
                                        const seed = M.plantsById[savedId - 1];
                                        if (seed && seed.unlocked) {
                                            needsSeeds = true;
                                            break outerLoop;
                                        }
                                    }
                                }
                            }
                        }
                        if (needsSeeds) {
                            if (Math.random() < 0.1) Logger.log('Resource', '資金保護中:優先保留給花園種子');
                            return;
                        }
                    }
                }

                // 6. 建築購買
                let affordableBuildings = [];
                for (let i in Game.ObjectsById) {
                    const obj = Game.ObjectsById[i];
                    if (obj.locked) continue;
                    if (obj.name === 'Wizard tower' && obj.amount >= Config.Settings.MaxWizardTowers) continue;
                    if (obj.price <= Game.cookies) affordableBuildings.push(obj);
                }
                if (affordableBuildings.length > 0) {
                    if (Config.Settings.BuyStrategy === 'expensive') affordableBuildings.sort((a, b) => b.price - a.price);
                    else affordableBuildings.sort((a, b) => a.price - b.price);
                    const targetB = affordableBuildings[0];
                    let buildName = targetB.displayName || targetB.name;
                    const domElement = document.getElementById('productName' + targetB.id);
                    if (domElement) buildName = domElement.innerText;
                    Logger.log('自動購買-建築', UI.cleanName(buildName));
                    targetB.buy(1);
                    Runtime.Stats.BuyBuildingCount++;
                    Runtime.Timers.NextBuy = now + Config.Settings.BuyIntervalMs;
                }
            }
        },

        Wrinkler: {
            hasLoggedShiny: false,
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch) return;
                if (!Config.Flags.AutoWrinkler) return;
                if (typeof Game === 'undefined' || !Game.wrinklers) return;
                let currentShinyPresent = false;
                for (let i in Game.wrinklers) {
                    let w = Game.wrinklers[i];
                    if (w.phase > 0 && w.close === 1) {
                        if (w.type === 1) {
                            currentShinyPresent = true;
                            if (!this.hasLoggedShiny) {
                                Logger.success('Wrinkler', '發現閃光皺紋蟲!已啟動保護機制!');
                                this.hasLoggedShiny = true;
                            }
                        } else {
                            w.hp = 0;
                        }
                    }
                }
                if (!currentShinyPresent) this.hasLoggedShiny = false;
            }
        },

        Garden: {
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch) return;
                if (!Config.Flags.Garden || now < Runtime.Timers.NextGarden) return;
                if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigameLoaded) return;

                const M = Game.Objects['Farm'].minigame;
                if (!M) return;
                let isCpsBuffActive = false;
                if (Config.Flags.GardenAvoidBuff) {
                    for (let i in Game.buffs) {
                        if (Game.buffs[i].multCpS > 1) { isCpsBuffActive = true; break; }
                    }
                }
                for (let y = 0; y < 6; y++) {
                    for (let x = 0; x < 6; x++) {
                        if (!M.isTileUnlocked(x, y)) continue;
                        const tile = M.plot[y][x];
                        const tileId = tile[0];
                        const tileAge = tile[1];
                        const savedId = Config.Memory.SavedGardenPlot[y][x];
                        if (tileId > 0) {
                            const plant = M.plantsById[tileId - 1];
                            const isAnomaly = (savedId !== -1 && tileId !== savedId) || (savedId === -1);
                            const plantName = UI.cleanName(plant.name);
                            if (!isAnomaly) {
                                if (tileAge >= 98 && tileAge >= plant.mature) M.harvest(x, y);
                                continue;
                            }
                            if (Config.Flags.GardenMutation) {
                                if (plant.unlocked) {
                                    M.harvest(x, y);
                                    Logger.log('花園', `鏟除雜物/已知變異 (紅框): ${plantName}`);
                                } else {
                                    if (tileAge >= plant.mature) {
                                        M.harvest(x, y);
                                        Logger.success('花園', `成功收割新品種種子 (紫框): ${plantName}`);
                                    }
                                }
                            } else {
                                if (plant.weed) M.harvest(x, y);
                            }
                            continue;
                        }
                        if (tileId === 0) {
                            if (savedId !== -1 && savedId !== null) {
                                const seed = M.plantsById[savedId - 1];
                                if (seed && seed.unlocked && M.canPlant(seed)) {
                                    if (Config.Flags.GardenAvoidBuff && isCpsBuffActive) continue;
                                    M.useTool(seed.id, x, y);
                                }
                            }
                        }
                    }
                }
                Runtime.Timers.NextGarden = now + 2500;
            },
            updateOverlay: function() {
                if (!Config.Flags.GardenOverlay) return;
                if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigameLoaded) return;
                const M = Game.Objects['Farm'].minigame;
                if (!M) return;
                for (let y = 0; y < 6; y++) {
                    for (let x = 0; x < 6; x++) {
                        const tileDiv = document.getElementById(`gardenTile-${x}-${y}`);
                        if (!tileDiv) continue;
                        tileDiv.classList.remove('cc-overlay-missing', 'cc-overlay-anomaly', 'cc-overlay-correct', 'cc-overlay-new');
                        if (!M.isTileUnlocked(x, y)) continue;
                        const savedId = Config.Memory.SavedGardenPlot[y][x];
                        const realId = M.plot[y][x][0];
                        if (realId === 0 && savedId !== -1) tileDiv.classList.add('cc-overlay-missing');
                        else if (realId !== 0) {
                            const plant = M.plantsById[realId - 1];
                            const isAnomaly = (savedId !== -1 && realId !== savedId) || (savedId === -1);
                            if (isAnomaly) {
                                if (plant.unlocked) tileDiv.classList.add('cc-overlay-anomaly');
                                else tileDiv.classList.add('cc-overlay-new');
                            } else if (realId === savedId) tileDiv.classList.add('cc-overlay-correct');
                        }
                    }
                }
            },
            clearOverlay: function() {
                $('.cc-overlay-missing, .cc-overlay-anomaly, .cc-overlay-correct, .cc-overlay-new').removeClass('cc-overlay-missing cc-overlay-anomaly cc-overlay-correct cc-overlay-new');
            },
            saveLayout: function() {
                if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigame) { alert('花園未就緒!'); return; }
                const M = Game.Objects['Farm'].minigame;
                let newLayout = [];
                for (let y = 0; y < 6; y++) {
                    let row = [];
                    for (let x = 0; x < 6; x++) {
                        if (M.isTileUnlocked(x, y)) {
                            const tile = M.plot[y][x];
                            row.push(tile[0] === 0 ? -1 : tile[0]);
                        } else row.push(-1);
                    }
                    newLayout.push(row);
                }
                Config.Memory.SavedGardenPlot = newLayout;
                GM_setValue('savedGardenPlot', Config.Memory.SavedGardenPlot);
                const btn = $('#garden-save-btn');
                const originalText = btn.text();
                btn.text('✅ 已儲存!').css('background', '#4caf50');
                setTimeout(() => btn.text(originalText).css('background', '#2196f3'), 1500);
            }
        },

        Stock: {
            checkSeedPriority: function() {
                if (!Config.Flags.Garden) return false;
                const Farm = Game.Objects['Farm'];
                if (!Farm.minigameLoaded || !Farm.minigame) return false;
                const M = Farm.minigame;
                for (let y = 0; y < 6; y++) {
                    for (let x = 0; x < 6; x++) {
                        if (M.isTileUnlocked(x, y)) {
                            const savedId = Config.Memory.SavedGardenPlot[y][x];
                            const currentTile = M.plot[y][x];
                            if (savedId > -1 && currentTile[0] === 0) {
                                const seed = M.plantsById[savedId - 1];
                                if (seed && seed.unlocked) return true;
                            }
                        }
                    }
                }
                return false;
            },
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch) return;
                if (!Config.Flags.Stock || now < Runtime.Timers.NextStock) return;
                const Bank = Game.Objects['Bank'];
                if (!Bank || !Bank.minigameLoaded || !Bank.minigame) return;
                if (this.checkSeedPriority()) {
                    if (Math.random() < 0.05) Logger.log('Stock', '暫停交易:優先保留資金給花園種子');
                    Runtime.Timers.NextStock = now + 5000;
                    return;
                }
                const M = Bank.minigame;
                for (let i = 0; i < M.goodsById.length; i++) {
                    const good = M.goodsById[i];
                    const price = M.getGoodPrice(good);
                    const rv = M.getRestingVal(good.id);
                    const goodName = UI.cleanName(good.name);
                    if (price < rv * 0.5) {
                        const maxStock = M.getGoodMaxStock(good);
                        if (good.stock < maxStock && Game.cookies > price) M.buyGood(good.id, 10000);
                    }
                    if (price > rv * 1.5) {
                        if (good.stock > 0) {
                            M.sellGood(good.id, 10000);
                            Logger.log('股市', `獲利賣出 ${goodName} @ $${price.toFixed(2)} (RV: ${rv.toFixed(2)})`);
                        }
                    }
                }
                Runtime.Timers.NextStock = now + 3000;
            }
        },

        Season: {
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch) return;
                if (!Config.Flags.Season || now < Runtime.Timers.NextSeasonCheck) return;
                const currentStage = Runtime.SeasonState.Roadmap[Runtime.SeasonState.CurrentStage];
                if (!currentStage) return;
                const currentSeason = Game.season;
                const targetSeasonId = currentStage.id;
                if (currentSeason !== targetSeasonId) {
                    const switcher = Object.values(Game.Upgrades).find(u => u.toggle && u.season === targetSeasonId);
                    if (switcher) {
                        if (!switcher.bought && switcher.canBuy()) {
                            Logger.log('Season', `切換季節至: ${currentStage.name}`);
                            switcher.buy();
                        }
                    }
                    Runtime.Timers.NextSeasonCheck = now + 2000;
                    return;
                }
                let isComplete = false;
                if (currentStage.target === 'BuyAllUpgrades') {
                    const remaining = Object.values(Game.Upgrades).filter(u => u.season === targetSeasonId && !u.bought && u.unlocked);
                    if (remaining.length === 0) isComplete = true;
                    else {
                        remaining.forEach(u => { if (u.canBuy()) { u.buy(); Logger.log('Season', `購買季節餅乾: ${u.name}`); } } );
                    }
                } else if (currentStage.target === 'MaxSanta') {
                    if (Game.santaLevel >= 14) {
                        const remaining = Object.values(Game.Upgrades).filter(u => u.season === targetSeasonId && !u.bought && u.unlocked);
                        if (remaining.length === 0) isComplete = true;
                    }
                }
                if (isComplete) {
                    Logger.log('Season', `階段完成: ${currentStage.name}`);
                    Runtime.SeasonState.CurrentStage++;
                }
                Runtime.Timers.NextSeasonCheck = now + 5000;
            }
        },

        Santa: {
            update: function(now) {
                if (!Config.Flags.GlobalMasterSwitch) return;
                if (!Config.Flags.Santa || Game.season !== 'christmas') return;
                if (Game.Has('A festive hat') && !Game.Has('Santa Claus')) {}
                if (Game.santaLevel < 14) {
                    if (typeof Game.UpgradeSanta === 'function') Game.UpgradeSanta();
                }
            }
        },

        updateTitle: function() {
            if (typeof Game === 'undefined') return;
            let totalMult = 1;
            let isWorthClicking = false;
            if (Game.buffs) {
                for (let i in Game.buffs) {
                    const buff = Game.buffs[i];
                    if (buff.multCpS > 0) totalMult *= buff.multCpS;
                    if (buff.multClick > 0) totalMult *= buff.multClick;
                    if (buff.multClick > 1 || buff.multCpS > 7) isWorthClicking = true;
                }
            }
            let coords = "0,0";
            const bigCookie = document.querySelector('#bigCookie');
            if (bigCookie) {
                const rect = bigCookie.getBoundingClientRect();
                coords = `${Math.round(rect.left + rect.width / 2)},${Math.round(rect.top + rect.height / 2)}`;
            }
            const signal = isWorthClicking ? "⚡ATTACK" : "💤IDLE";
            const displayMult = totalMult > 1000 ? (totalMult/1000).toFixed(1) + 'k' : Math.round(totalMult);
            document.title = `[${signal}|${displayMult}x|${coords}] ${Runtime.OriginalTitle}`;
        }
    };

    // ═══════════════════════════════════════════════════════════════
    // 3. 系統核心 (System Core)
    // ═══════════════════════════════════════════════════════════════
    const Core = {
        waitForGame: function(callback, maxRetries = 100) {
            if (typeof Game !== 'undefined' && Game.ready && document.readyState === 'complete') {
                callback();
            } else if (maxRetries > 0) {
                setTimeout(() => { this.waitForGame(callback, maxRetries - 1); }, 100);
            } else {
                Logger.error('Core', '遊戲初始化超時(10秒),部分功能可能無法使用');
            }
        },

        init: function() {
            Logger.success('Core', 'Cookie Clicker Ultimate v8.5.4-hotfix Loading...');

            // ✅ 1. 優先恢復鎖定狀態 (Fix Race Condition)
            const savedSpendingState = GM_getValue('spendingLocked', false);
            Config.Flags.SpendingLocked = savedSpendingState;

            if (savedSpendingState) {
                Logger.warn('Core', '偵測到支出鎖定狀態,已優先啟用保護');
                const savedStates = GM_getValue('savedSpendingStates', null);
                if (savedStates) {
                    UI.GardenProtection.SavedStates = savedStates;
                }
            }

            const scriptRestarted = localStorage.getItem('cookieScriptRestarted');
            if (scriptRestarted) {
                Logger.log('Core', '腳本已自動重啟');
                localStorage.removeItem('cookieScriptRestarted');
            }

            UI.initStyles();
            UI.createFloatingButton();
            UI.createControlPanel();
            UI.createCountdown();
            UI.createBuffMonitor();
            UI.ActionLog.create();
            UI.GardenGrid.create();

            try {
                if (Game.setVolume) Game.setVolume(Config.Settings.Volume);
            } catch(e) {
                Logger.warn('Core', '音量設定失敗,遊戲可能未完全載入');
            }

            this.scheduleRestart();
            this.startHeartbeat();

            setTimeout(() => {
                UI.GardenProtection.create();
                const restoreLockState = () => {
                    if ($('#chk-auto-buy').length === 0) {
                        Logger.warn('花園保護', '主 UI 尚未就緒,延遲恢復狀態');
                        setTimeout(restoreLockState, 200);
                        return;
                    }
                    if (Config.Flags.SpendingLocked) {
                        $('#chk-spending-lock').prop('checked', true);
                        UI.GardenProtection.toggle(true, true);
                    }
                };
                restoreLockState();
                
                // ✅ v8.5.4 新增:恢復最小化狀態
                if (Config.Memory.GardenProtectionMinimized) {
                    // 延遲執行以確保花園面板已加載
                    setTimeout(() => {
                        UI.GardenProtection.minimize();
                    }, 1000);
                }
            }, 2000);

            setTimeout(() => {
                Logic.Garden.clearOverlay();
                UI.updateButtonState();
                UI.ActionLog.toggle(true);
                Logger.log('Core', '初始化完成,所有模組已就緒');
            }, 3000);

            document.addEventListener('keydown', function(e) {
                if (e.key === 'F8') {
                    e.preventDefault();
                    UI.toggleMasterSwitch();
                }
            });

            // ✅ Debug 接口:讓控制台可以訪問
            window.CookieBot = { UI, Logic, Config, Core };
        },

        startHeartbeat: function() {
            const self = this;
            const fastLoop = () => {
                const now = Date.now();
                Logic.Click.update(now);
                const nextDelay = Config.Flags.Click ? Math.max(10, Config.Settings.ClickInterval) : 1000;
                setTimeout(fastLoop, nextDelay);
            };
            fastLoop();

            setInterval(() => {
                const now = Date.now();
                Logic.Buy.update(now);
                Logic.Garden.update(now);
                Logic.Garden.updateOverlay();
                Logic.SugarLump.update(now);
                Logic.Wrinkler.update(now);
                Logic.Stock.update(now);
                Logic.Season.update(now);
                Logic.Santa.update(now);
                Logic.GodzamokCombo.update(now);
                Logic.updateTitle();
                Logic.Click.handlePrompts();

                UI.updateBuffDisplay();
                UI.GardenProtection.updateVisibility();

                if (Config.Flags.ShowCountdown) {
                    $('#txt-rst').text(UI.formatMs(Math.max(0, Runtime.Timers.NextRestart - now)));
                    $('#txt-buy').text(Config.Flags.Buy ? UI.formatMs(Math.max(0, Runtime.Timers.NextBuy - now)) : '--:--');
                }
            }, 1000);
        },

        scheduleRestart: function() {
            if (Runtime.Timers.RestartInterval) clearInterval(Runtime.Timers.RestartInterval);
            let interval = Config.Settings.RestartIntervalMs;
            if (interval < 60000) interval = 60000;
            Runtime.Timers.NextRestart = Date.now() + interval;
            if(this.restartTimer) clearTimeout(this.restartTimer);
            this.restartTimer = setTimeout(() => this.performRestart(), interval);
        },

        performRestart: function() {
            if (Game.WriteSave) Game.WriteSave();
            localStorage.setItem('cookieScriptRestarted', 'true');
            setTimeout(() => {
                GM_openInTab(window.location.href, { active: true, insert: true, setParent: false });
                setTimeout(() => window.close(), 1000);
            }, 500);
        }
    };

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => { Core.waitForGame(() => Core.init()); });
    } else {
        Core.waitForGame(() => Core.init());
    }

})();