Greasy Fork

Greasy Fork is available in English.

[MWI] Ultimate Enhancement Notifier v3.2.0

Added persistence between reloads and option to clear data.

当前为 2025-04-06 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         [MWI] Ultimate Enhancement Notifier v3.2.0
// @namespace    http://tampermonkey.net/
// @version      3.2.1
// @description  Added persistence between reloads and option to clear data.
// @author       Truth_Light (modified by Nex, styled by Cosmic, cost tracking by Assistant)
// @match        https://www.milkywayidle.com/*
// @match        https://test.milkywayidle.com/*
// @license      MIT
// @grant        GM_registerMenuCommand
// @icon         https://www.google.com/s2/favicons?sz=64&domain=milkywayidle.com
// ==/UserScript==

/*
    Market price fetching relies on having MWI Tools installed, get it here:
    http://greasyfork.icu/en/scripts/494467-mwitools

    获取市场价格取决于是否安装了 MWI 工具,在此获取:
    https://greasyfork.cc/zh-CN/scripts/494467-mwitools
*/

(function() {
    'use strict';
    // ======================
    // STYLE CONFIGURATION
    // ======================
    const STYLE = {
      colors: {
        primary: '#00ffe7', // Bright neon cyan
        background: 'rgba(5, 5, 15, 0.95)', // Deep black-blue
        border: '1px solid rgba(0, 255, 234, 0.4)', // Glowing border
        textPrimary: '#e0f7ff', // Soft neon white-blue
        textSecondary: '#9b9bff', // Neon purple tint
        accent: '#ff00d4', // Vibrant pink-magenta
        danger: '#ff0055', // Electric red
        success: '#00ff99', // Neon green
        headerBg: 'rgba(15, 5, 35, 0.7)', // Dark purple gradient tint
        epic: '#c63dff', // Deep neon purple
        legendary: '#ff6f1a', // Bright orange neon
        mythic: '#ff0033', // Intense mythic red
        blessed: 'linear-gradient(135deg, #ff00d4, #c63dff, #00ffe7)', // Trippy neon gradient
        gold: '#FFD700' // Gold color for cost display
      },
      fonts: {
        primary: '14px "Orbitron", "Segoe UI", Roboto, sans-serif', // Futuristic font
        secondary: '12px "Orbitron", "Segoe UI", Roboto, sans-serif',
        header: 'bold 16px "Orbitron", "Segoe UI", Roboto, sans-serif',
        milestone: 'bold 18px "Orbitron", "Segoe UI", Roboto, sans-serif',
        cost: 'bold 13px "Orbitron", "Segoe UI", Roboto, sans-serif'
      },
      shadows: {
        panel: '0 0 20px rgba(0, 255, 234, 0.3)', // Neon glow panel
        notification: '0 0 15px rgba(255, 0, 212, 0.3)', // Pink neon soft glow
        milestone: '0 0 25px rgba(198, 61, 255, 0.4)', // Epic purple glow
        text: '0 0 6px rgba(0, 255, 234, 0.3)', // Soft text glow
        gold: '0 0 8px rgba(255, 215, 0, 0.7)' // Gold glow
      },
      borderRadius: {
        medium: '14px', // Rounded with a modern edge
        small: '8px'
      },
      transitions: {
        fast: 'all 0.15s ease-in-out',
        medium: 'all 0.3s ease-in-out',
        slow: 'all 0.5s ease-in-out'
      },
    };

    STYLE.scrollable = {
        maxHeight: '50vh',  // Maximum height before scrolling kicks in
        overflowY: 'auto',
        scrollbarWidth: 'thin',
        scrollbarColor: `${STYLE.colors.primary} transparent`
    };

    // Core Variables
    const userLanguage = localStorage.getItem('i18nextLng');
    let enhancementLevel;
    // Load enhancementData from localStorage if available
    let enhancementData = JSON.parse(localStorage.getItem('enhancementData')) || {};
    let currentTrackingIndex = parseInt(localStorage.getItem('enhancementCurrentTrackingIndex')) || 0;
    let currentViewingIndex = parseInt(localStorage.getItem('enhancementCurrentViewingIndex')) || 0;

    cleanSessionIndices();

    // Function to save enhancementData to localStorage
    function saveEnhancementData() {
        localStorage.setItem('enhancementData', JSON.stringify(enhancementData));
        localStorage.setItem('enhancementCurrentTrackingIndex', currentTrackingIndex);
        localStorage.setItem('enhancementCurrentViewingIndex', currentViewingIndex);
    }

    function clearAllSessions() {
    if (confirm(isZH ? "确定要清除所有强化会话数据吗?此操作不可撤销。" : "Are you sure you want to clear all enhancement sessions? This cannot be undone.")) {
        enhancementData = {};
        currentTrackingIndex = 0;
        currentViewingIndex = 0;
        localStorage.removeItem('enhancementData');
        updateFloatingUI();
        showUINotification(isZH ? "已清除所有会话数据" : "All session data cleared");
    }
}

    currentViewingIndex = currentTrackingIndex; // Start viewing current session
    let item_name_to_hrid;
    let item_hrid_to_name;

    var isZH = userLanguage.startsWith("zh");
    // Add this near your language detection
    let lastLangCheck = userLanguage;
    setInterval(() => {
        const currentLang = localStorage.getItem('i18nextLng');
        if (currentLang !== lastLangCheck) {
            lastLangCheck = currentLang;
            isZH = currentLang.startsWith("zh");

            // Force refresh all displayed names
            Object.keys(enhancementData).forEach(key => {
                const session = enhancementData[key];
                if (session["其他数据"]) {
                    session["其他数据"]["物品名称"] = translateItemName(
                        session["其他数据"]["物品HRID"],
                        session["其他数据"]["物品名称"]
                    );
                }
            });

            updateFloatingUI();
            saveEnhancementData(); // Save after updating names
        }
    }, 1000);

    cleanSessionIndices();

    function cleanSessionIndices() {
        const sortedIndices = Object.keys(enhancementData)
            .map(Number)
            .sort((a, b) => a - b);

        if (sortedIndices.some((v, i) => v !== i + 1)) {
            const newData = {};
            sortedIndices.forEach((oldIndex, i) => {
                newData[i + 1] = enhancementData[oldIndex];
            });
            enhancementData = newData;
            currentTrackingIndex = sortedIndices.length > 0 ?
                Math.max(...Object.keys(newData).map(Number)) : 1;
            currentViewingIndex = currentTrackingIndex;
            saveEnhancementData();
        }

        // Ensure loaded indices are valid
        if (!enhancementData[currentViewingIndex]) {
            currentViewingIndex = currentTrackingIndex;
        }
        if (!enhancementData[currentTrackingIndex]) {
            currentTrackingIndex = sortedIndices.length > 0 ? Math.max(...sortedIndices) : 0;
        }
    }

    // ======================
    // MARKET DATA HANDLING
    // ======================

    let MWITools_marketAPI_json = null;
    let lastMarketUpdate = 0;
    const MARKET_REFRESH_INTERVAL = 30000; // 30 seconds

    function loadMarketData() {
        try {
            // Try to load from localStorage
            const marketDataStr = localStorage.getItem('MWITools_marketAPI_json');
            if (marketDataStr) {
                MWITools_marketAPI_json = JSON.parse(marketDataStr);
                lastMarketUpdate = MWITools_marketAPI_json?.time || 0;
                // console.log('[Market] Loaded market data from storage', lastMarketUpdate);
            }

            // Set up periodic refresh
            setInterval(refreshMarketData, MARKET_REFRESH_INTERVAL);

            // Initial refresh
            refreshMarketData();
        } catch (e) {
            console.error('[Market] Error loading market data:', e);
        }
    }

    function refreshMarketData() {
        try {
            // Check if we have the market data object in memory
            if (typeof window.MWITools_marketAPI_json !== 'undefined') {
                MWITools_marketAPI_json = window.MWITools_marketAPI_json;
                lastMarketUpdate = MWITools_marketAPI_json?.time || 0;
                localStorage.setItem('MWITools_marketAPI_json', JSON.stringify(MWITools_marketAPI_json));
                // console.log('[Market] Updated market data from memory', lastMarketUpdate);
            }
        } catch (e) {
            console.error('[Market] Error refreshing market data:', e);
        }
    }

    function getMarketPrice(itemHRID) {
        try {
            // Special case for coins - always worth 1 gold
            if (itemHRID === '/items/coin' || itemHRID === '/items/coins') {
                return 1;
            }

            // Validate input
            if (!itemHRID || typeof itemHRID !== 'string') {
                console.log('[Market] Invalid item HRID:', itemHRID);
                return 0;
            }

            // Refresh market data if stale
            if (Date.now() - lastMarketUpdate > MARKET_REFRESH_INTERVAL) {
                refreshMarketData();
            }

            // Check if market data is available
            if (!MWITools_marketAPI_json?.market) {
                console.log('[Market] No market data available');
                return 0;
            }

            // Try to get the display name (either from dictionary or HRID)
            let itemName = item_hrid_to_name?.[itemHRID];
            if (!itemName) {
                // Extract from HRID format: /items/aqua_essence → Aqua Essence
                const parts = itemHRID.split('/');
                const lastPart = parts[parts.length - 1] || '';
                itemName = lastPart
                    .replace(/_/g, ' ')
                    .replace(/(^|\s)\S/g, t => t.toUpperCase())
                    .trim();
            }

            // Return 0 if we still don't have a name
            if (!itemName) {
                console.log('[Market] Could not determine item name for:', itemHRID);
                return 0;
            }

            // Find market entry (case insensitive)
            const marketEntry = Object.entries(MWITools_marketAPI_json.market).find(
                ([name]) => name.toLowerCase() === itemName.toLowerCase()
            );

            if (!marketEntry) {
                console.log('[Market] No entry for:', itemName);
                return 0;
            }

            // Use ask price if available, otherwise bid price
            const price = marketEntry[1]?.ask || marketEntry[1]?.bid || 0;
            // console.log('[Market] Price for', itemName, ':', price);

            return price;
        } catch (e) {
            console.error("[Market] Error getting price for", itemHRID, ":", e);
            return 0;
        }
    }

    // ======================
    // ENHANCEMENT COST TRACKING (updated to use new market functions)
    // ======================

    function getEnhancementMaterials(itemHRID) {
        try {
            const initData = JSON.parse(localStorage.getItem('initClientData'));
            const itemData = initData.itemDetailMap?.[itemHRID];

            if (!itemData) {
                console.log('[Materials] Item not found:', itemHRID);
                return null;
            }

            // Get the costs array (try different possible property names)
            const costs = itemData.enhancementCosts || itemData.upgradeCosts ||
                         itemData.enhanceCosts || itemData.enhanceCostArray;

            if (!costs) {
                console.log('[Materials] No enhancement costs found for:', itemHRID);
                return null;
            }

            // Convert to our desired format
            let materials = [];

            // Case 1: Array of objects (current format)
            if (Array.isArray(costs) && costs.length > 0 && typeof costs[0] === 'object') {
                materials = costs.map(cost => [cost.itemHrid, cost.count]);
            }
            // Case 2: Already in correct format [["/items/foo", 30], ["/items/bar", 20]]
            else if (Array.isArray(costs) && costs.length > 0 && Array.isArray(costs[0])) {
                materials = costs;
            }
            // Case 3: Simple array ["/items/foo", 30]
            else if (Array.isArray(costs) && costs.length === 2 && typeof costs[0] === 'string') {
                materials = [costs];
            }
            // Case 4: Object format {"/items/foo": 30, "/items/bar": 20}
            else if (typeof costs === 'object' && !Array.isArray(costs)) {
                materials = Object.entries(costs);
            }

            // Filter out any invalid entries
            materials = materials.filter(m =>
                Array.isArray(m) &&
                m.length === 2 &&
                typeof m[0] === 'string' &&
                typeof m[1] === 'number'
            );

            // console.log('[Materials] Processed costs:', materials);
            return materials.length > 0 ? materials : null;
        } catch (e) {
            console.error('[Materials] Error:', e);
            return null;
        }
    }

    // Updated trackMaterialCosts():
    function trackMaterialCosts(itemHRID) {
        try {
            const materials = getEnhancementMaterials(itemHRID);
            if (!materials || materials.length === 0) {
                console.log('[Cost] No materials to track for:', itemHRID);
                return 0;
            }

            let totalCost = 0;
            const session = enhancementData[currentTrackingIndex];

            if (!session["材料消耗"]) {
                session["材料消耗"] = {};
            }

            materials.forEach(material => {
                let materialHrid, count;

                if (Array.isArray(material)) {
                    materialHrid = material[0];
                    count = material[1] || 0;
                } else {
                    console.log('[Cost] Invalid material format:', material);
                    return;
                }

                if (!materialHrid || count <= 0) {
                    console.log('[Cost] Invalid material entry:', {materialHrid, count});
                    return;
                }

                const cost = getMarketPrice(materialHrid) * count;
                totalCost += cost;

                if (!session["材料消耗"][materialHrid]) {
                    session["材料消耗"][materialHrid] = {
                        name: item_hrid_to_name[materialHrid] || materialHrid,
                        count: 0,
                        totalCost: 0
                    };
                }

                session["材料消耗"][materialHrid].count += count;
                session["材料消耗"][materialHrid].totalCost += cost;

                // console.log('[Cost] Tracked:', count, 'x', materialHrid, '=', cost, 'gold');
            });

            session["总成本"] = (session["总成本"] || 0) + totalCost;
            // console.log('[Cost] Total for this attempt:', totalCost, 'gold');

            return totalCost;
        } catch (e) {
            console.error('[Cost] Error tracking materials:', e);
            return 0;
        }
    }

    // ======================
    // NOTIFICATION SYSTEM
    // ======================

    function createNotificationContainer(headerElement) {
        const container = document.createElement("div");
        container.id = "enhancementNotificationContainer";
        Object.assign(container.style, {
            position: "absolute",
            top: "calc(100% + 5px)",
            left: "50%",
            transform: "translateX(-50%)",
            zIndex: "9999",
            display: "flex",
            flexDirection: "column",
            gap: "5px",
            width: "220px",
            pointerEvents: "none"
        });

        if (getComputedStyle(headerElement).position === "static") {
            headerElement.style.position = "relative";
        }

        headerElement.appendChild(container);
        return container;
    }

    function showNotification(message, type, level, isBlessed = false) {
        const headerElement = document.querySelector('[class^="Header_myActions"]');
        if (!headerElement) return;

        let container = document.getElementById("enhancementNotificationContainer");
        if (!container) {
            container = createNotificationContainer(headerElement);
        }

        if (type === "success") {
            createStandardNotification(container, level, isBlessed);

            if (level >= 10) {
                setTimeout(() => {
                    createMilestoneNotification(container, level);
                }, 300);
            }
        } else {
            createFailureNotification(container);
        }
    }

    function createStandardNotification(container, level, isBlessed) {
        const notification = document.createElement("div");
        notification.className = "enhancement-notification standard";

        Object.assign(notification.style, {
            padding: "10px 15px",
            borderRadius: STYLE.borderRadius.small,
            color: "white",
            fontWeight: "bold",
            boxShadow: STYLE.shadows.notification,
            transform: "translateY(-20px)",
            opacity: "0",
            transition: STYLE.transitions.medium,
            textAlign: "center",
            marginBottom: "5px",
            position: "relative",
            overflow: "hidden",
            pointerEvents: "auto",
            textShadow: STYLE.shadows.text
        });

        if (isBlessed) {
            Object.assign(notification.style, {
                background: STYLE.colors.blessed,
                color: "#8B4513"
            });
            notification.textContent = isZH ? `祝福强化! +${level}` : `BLESSED! +${level}`;
            addHolyEffects(notification);
        } else {
            notification.style.background = getLevelGradient(level);
            notification.textContent = isZH ? `强化成功 +${level}` : `Success +${level}`;
        }

        animateNotification(notification, container, level, isBlessed);
    }

    function createMilestoneNotification(container, level) {
        const milestone = document.createElement("div");
        milestone.className = "enhancement-notification milestone";

        Object.assign(milestone.style, {
            padding: "12px 15px",
            borderRadius: STYLE.borderRadius.small,
            color: "white",
            fontWeight: "bolder",
            boxShadow: STYLE.shadows.milestone,
            transform: "translateY(-20px)",
            opacity: "0",
            transition: STYLE.transitions.medium,
            textAlign: "center",
            marginBottom: "5px",
            animation: "pulse 2s infinite",
            position: "relative",
            overflow: "hidden",
            pointerEvents: "auto",
            textShadow: STYLE.shadows.text,
            font: STYLE.fonts.milestone
        });

        if (level >= 20) {
            milestone.style.background = `
                linear-gradient(
                    135deg,
                    ${STYLE.colors.mythic},
                    #ff0044,
                    #ff2200,
                    #ff0055
                )
            `;
            milestone.style.backgroundSize = "400% 400%";
            milestone.style.animation = "mythicPulse 2.5s ease-in-out infinite";

            milestone.style.color = "#fff";
            milestone.style.fontWeight = "bold";
            milestone.style.textShadow = `
                0 0 4px #ff0044,
                0 0 8px #ff0044,
                0 0 12px #ff0044
            `;
            milestone.textContent = isZH ? "命中注定!" : "IT. IS. DESTINY.";
        }
        else if (level >= 15) {
            milestone.style.background = `linear-gradient(135deg, ${STYLE.colors.legendary}, #FF6600)`;
            milestone.style.textShadow = "0 0 8px rgba(255, 102, 0, 0.8)";
            milestone.textContent = isZH ? "奇迹发生!" : "IT'S A MIRACLE!";
        }
        else if (level >= 10) {
            milestone.style.background = `linear-gradient(135deg, ${STYLE.colors.epic}, #8000FF)`;
            milestone.style.textShadow = "0 0 8px rgba(153, 51, 255, 0.8)";
            milestone.textContent = isZH ? "运气不错!" : "NICE LUCK!";
        }

        animateNotification(milestone, container, level, false);
    }

    function createFailureNotification(container) {
        const notification = document.createElement("div");
        notification.className = "enhancement-notification failure";

        Object.assign(notification.style, {
            padding: "10px 15px",
            borderRadius: STYLE.borderRadius.small,
            color: "white",
            fontWeight: "bold",
            boxShadow: STYLE.shadows.notification,
            transform: "translateY(-20px)",
            opacity: "0",
            transition: STYLE.transitions.medium,
            textAlign: "center",
            marginBottom: "5px",
            position: "relative",
            overflow: "hidden",
            pointerEvents: "auto",
            textShadow: STYLE.shadows.text,
            backgroundColor: STYLE.colors.danger,
            borderTop: "3px solid #C62828"
        });
        notification.textContent = isZH ? "强化失败!" : "Failed!";

        animateNotification(notification, container, 0, false);
    }

    function animateNotification(notification, container, level, isBlessed) {
        container.appendChild(notification);

        setTimeout(() => {
            notification.style.transform = "translateY(0)";
            notification.style.opacity = "1";
        }, 10);

        setTimeout(() => {
            notification.style.transform = "translateY(20px)";
            notification.style.opacity = "0";
            setTimeout(() => notification.remove(), 300);
        }, getNotificationDuration(level, isBlessed));

        notification.addEventListener("click", () => {
            notification.style.transform = "translateY(20px)";
            notification.style.opacity = "0";
            setTimeout(() => notification.remove(), 300);
        });
    }

    function addHolyEffects(notification) {
        const rays = document.createElement("div");
        rays.className = "holy-rays";
        Object.assign(rays.style, {
            position: "absolute",
            top: "0",
            left: "0",
            width: "100%",
            height: "100%",
            background: "radial-gradient(circle, transparent 20%, rgba(255,215,0,0.3) 70%)",
            pointerEvents: "none",
            animation: "raysRotate 4s linear infinite"
        });
        notification.appendChild(rays);

        for (let i = 0; i < 4; i++) {
            const cross = document.createElement("div");
            cross.textContent = "✝";
            Object.assign(cross.style, {
                position: "absolute",
                fontSize: "16px",
                animation: `floatUp ${3 + Math.random() * 2}s linear infinite`,
                opacity: "0.7",
                left: `${10 + (i * 25)}%`,
                top: "100%"
            });
            notification.appendChild(cross);
        }
    }

    function getLevelGradient(level) {
        if (level >= 20) {
            return `linear-gradient(135deg, ${STYLE.colors.mythic}, #FF0000)`;
        }
        else if (level >= 15) {
            return `linear-gradient(135deg, ${STYLE.colors.legendary}, #FF6600)`;
        }
        else if (level >= 10) {
            return `linear-gradient(135deg, ${STYLE.colors.epic}, #8000FF)`;
        }
        else if (level >= 5) {
            return "linear-gradient(135deg, #3399FF, #0066FF)";
        }
        else if (level >= 1) {
            return "linear-gradient(135deg, #33CC33, #009900)";
        }
        else {
            return "linear-gradient(135deg, #CCCCCC, #999999)";
        }
    }

    function getNotificationDuration(level, isBlessed) {
        if (isBlessed) return 5000;
        if (level >= 20) return 5000;
        if (level >= 15) return 4000;
        if (level >= 10) return 3000;
        return 2500;
    }

    // ======================
    // ENHANCEMENT TRACKING
    // ======================

    function hookWS() {
        const dataProperty = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
        const oriGet = dataProperty.get;

        dataProperty.get = hookedGet;
        Object.defineProperty(MessageEvent.prototype, "data", dataProperty);

        function hookedGet() {
            const socket = this.currentTarget;
            if (!(socket instanceof WebSocket)) return oriGet.call(this);
            if (!socket.url.includes("api.milkywayidle.com/ws") && !socket.url.includes("api-test.milkywayidle.com/ws")) {
                return oriGet.call(this);
            }

            const message = oriGet.call(this);
            Object.defineProperty(this, "data", { value: message });
            return handleMessage(message);
        }
    }

    function handleMessage(message) {
        try {
            const obj = JSON.parse(message);
            if (!obj) return message;

            if (obj.type === "init_character_data") {
                handleInitData();
            } else if (obj.type === "action_completed" && obj.endCharacterAction?.actionHrid === "/actions/enhancing/enhance") {
                handleEnhancement(obj.endCharacterAction);
            }
        } catch (error) {
            console.error("Error processing message:", error);
        }
        return message;
    }

    function handleInitData() {
        const initClientData = localStorage.getItem('initClientData');
        if (!initClientData) {
            setTimeout(handleInitData, 500); // Retry if not ready
            return;
        }

        try {
            const data = JSON.parse(initClientData);
            item_hrid_to_name = {};

            // Properly map all item names
            for (const [hrid, details] of Object.entries(data.itemDetailMap)) {
                item_hrid_to_name[hrid] = details.name;
            }

            console.log("Translations loaded:", item_hrid_to_name);
        } catch (error) {
            console.error('Data parsing failed:', error);
        }
    }

    function extractBaseItemHrid(primaryItemHash) {
        try {
            // Handle different possible formats:
            // 1. "/item_locations/inventory::/items/enhancers_bottoms::0"
            // 2. "161296::/item_locations/inventory::/items/enhancers_bottoms::0"
            // 3. Direct HRID like "/items/enhancers_bottoms"

            // Split by :: and find the part that starts with /items/
            const parts = primaryItemHash.split('::');
            const itemPart = parts.find(part => part.startsWith('/items/'));

            if (itemPart) {
                return itemPart;
            }

            // If no /items/ found but it's a direct HRID
            if (primaryItemHash.startsWith('/items/')) {
                return primaryItemHash;
            }

            console.log('[Extract] Could not find item HRID in:', primaryItemHash);
            return null;
        } catch (e) {
            console.error('[Extract] Error parsing primaryItemHash:', e);
            return null;
        }
    }
    // Updated handleEnhancement with cost tracking and localStorage saving
        function handleEnhancement(action) {
            const newLevel = parseInt(action.primaryItemHash.match(/::(\d+)$/)[1]);
            const currentCount = action.currentCount;
            const wasBlessed = enhancementLevel !== undefined && (newLevel - enhancementLevel) >= 2;
            const itemHRID = extractBaseItemHrid(action.primaryItemHash);

            if (!itemHRID) return;

            // Determine previous level properly
            const previousLevel = (enhancementLevel !== undefined) ? enhancementLevel : (currentCount === 1 ? newLevel : 0);

            // Update the current level immediately so it's accurate for next run
            enhancementLevel = newLevel;

            // First enhancement detection
            if (currentTrackingIndex === 0) {
                // Properly initialize first session
                currentTrackingIndex = 1;
                enhancementData[currentTrackingIndex] = {
                    "强化数据": {},
                    "其他数据": {
                        "物品HRID": itemHRID,
                        "物品名称": item_hrid_to_name[itemHRID] || "Unknown",
                        "目标强化等级": action.enhancingMaxLevel,
                        "是否保护": action.enhancingProtectionMinLevel >= 2,
                        "保护物品HRID": getProtectionItemHrid(action),
                        "保护物品名称": item_hrid_to_name[getProtectionItemHrid(action)] || null,
                        "保护消耗总数": 0,
                        "保护总成本": 0,
                        "保护最小等级": action.enhancingProtectionMinLevel
                    },
                    "材料消耗": {},
                    "保护消耗": {},
                    "总成本": 0,
                    "强化次数": 0,
                    "强化状态": "进行中"
                };
                currentViewingIndex = currentTrackingIndex;
                saveEnhancementData(); // Save new session
            } // Session initialization logic (unchanged)
            else if (currentCount === 1 || !enhancementData[currentTrackingIndex] ||
                currentCount <= enhancementData[currentTrackingIndex]["强化次数"]) {
                startNewEnhancementSession(action);
                initializeNewItem(action, itemHRID, newLevel);
                saveEnhancementData(); // Save new session
            }

            // Get current session reference
            const session = enhancementData[currentTrackingIndex];

            // Initialize data for the new level if it doesn't exist
            if (!enhancementData[currentTrackingIndex]["强化数据"][newLevel]) {
                enhancementData[currentTrackingIndex]["强化数据"][newLevel] = {
                    "成功次数": 0,
                    "失败次数": 0,
                    "成功率": 0
                };
                saveEnhancementData(); // Save new level data
            }

            if(currentCount == 1){
              const cost = trackMaterialCosts(itemHRID);
              session["总成本"] += cost;
              saveEnhancementData(); // Save after material cost tracking
            }

            // Skip enhancement logic if currentCount is 1 or enhancementLevel is undefined
            if (currentCount !== 1 && previousLevel !== undefined) {
                // Initialize level data for the previous level if needed
                if (!enhancementData[currentTrackingIndex]["强化数据"][previousLevel]) {
                    enhancementData[currentTrackingIndex]["强化数据"][previousLevel] = {
                        "成功次数": 0,
                        "失败次数": 0,
                        "成功率": 0
                    };
                    saveEnhancementData(); // Save new level data
                }

                const levelData = enhancementData[currentTrackingIndex]["强化数据"][previousLevel];
                const session = enhancementData[currentTrackingIndex];

                const materialCost = trackMaterialCosts(itemHRID);
                session["总成本"] += materialCost;
                saveEnhancementData(); // Save after material cost tracking

                if (newLevel > previousLevel) {
                    handleSuccess(levelData, newLevel, wasBlessed);
                } else {
                    handleFailure(action, levelData, session);

                    // Protection cost handling
                    if (session["其他数据"]["是否保护"] &&
                        previousLevel >= session["其他数据"]["保护最小等级"]) {

                        const protectionHrid = session["其他数据"]["保护物品HRID"];
                        const protectionCost = getMarketPrice(protectionHrid);

                        if (!session["保护消耗"][protectionHrid]) {
                            session["保护消耗"][protectionHrid] = {
                                name: session["其他数据"]["保护物品名称"],
                                count: 0,
                                totalCost: 0
                            };
                        }

                        session["保护消耗"][protectionHrid].count++;
                        session["保护消耗"][protectionHrid].totalCost += protectionCost;
                        session["其他数据"]["保护消耗总数"]++;
                        session["其他数据"]["保护总成本"] += protectionCost;
                        session["总成本"] += protectionCost;
                        saveEnhancementData(); // Save after protection cost tracking
                    }
                }

                updateStats(levelData);
                session["强化次数"] = currentCount;
                saveEnhancementData(); // Save after stats update
            }

            // Final updates
            if (newLevel >= enhancementData[currentTrackingIndex]["其他数据"]["目标强化等级"]) {
                showTargetAchievedCelebration(newLevel, enhancementData[currentTrackingIndex]["其他数据"]["目标强化等级"]);
            }

            updateDisplay();
            updateFloatingUI();
        }

    function startNewEnhancementSession(action) {
      // Only create new sessions after first one exists
      if (currentTrackingIndex === 0) return;

      currentTrackingIndex++;

        enhancementData[currentTrackingIndex] = {
            "强化数据": {},
            "其他数据": {
                "物品HRID": "",
                "物品名称": "Unknown",
                "目标强化等级": 0,
                "是否保护": false,
                "保护物品HRID": null,
                "保护物品名称": null,
                "保护消耗总数": 0,
                "保护总成本": 0,
                "保护最小等级": 0
            },
            "材料消耗": {},  // Material costs storage
            "保护消耗": {},  // Protection costs storage
            "总成本": 0,     // Total gold cost
            "强化次数": 0,
            "强化状态": "进行中"
        };
    }

    // Keep handleSuccess as is but ensure it's safe
    function handleSuccess(levelData, newLevel, wasBlessed) {
        levelData["成功次数"] = (levelData["成功次数"] || 0) + 1;
        const message = isZH ? `强化成功 +${newLevel}` : `Success +${newLevel}`;
        showNotification(
            wasBlessed ? (isZH ? `祝福强化! +${newLevel}` : `BLESSED! +${newLevel}`) : message,
            "success",
            newLevel,
            wasBlessed
        );
    }

    // Updated handleFailure with proper safety checks
    function handleFailure(action, levelData, session) {
        // Initialize if undefined
        levelData["失败次数"] = (levelData["失败次数"] || 0) + 1;

        // Only process protection if session data exists
        if (session["其他数据"]?.["是否保护"] &&
            enhancementLevel >= session["其他数据"]?.["保护最小等级"]) {

            const protectionHrid = session["其他数据"]["保护物品HRID"];
            if (protectionHrid) {
                // Initialize protection tracking if needed
                if (!session["保护消耗"]) {
                    session["保护消耗"] = {};
                }

                if (!session["保护消耗"][protectionHrid]) {
                    session["保护消耗"][protectionHrid] = {
                        name: session["其他数据"]["保护物品名称"],
                        count: 0,
                        totalCost: 0
                    };
                }

                // Update protection stats
                const protectionCost = getMarketPrice(protectionHrid);
                session["保护消耗"][protectionHrid].count++;
                session["保护消耗"][protectionHrid].totalCost += protectionCost;
                session["其他数据"]["保护消耗总数"] = (session["其他数据"]["保护消耗总数"] || 0) + 1;
                session["其他数据"]["保护总成本"] = (session["其他数据"]["保护总成本"] || 0) + protectionCost;
                session["总成本"] = (session["总成本"] || 0) + protectionCost;
            }
        }

        showNotification(isZH ? "强化失败!" : "Failed!", "failure", 0);
    }

    function updateStats(levelData) {
        // Safe access with default values
        const success = levelData["成功次数"] || 0;
        const failure = levelData["失败次数"] || 0;
        levelData["成功率"] = (success + failure) > 0 ? success / (success + failure) : 0;
    }

    function getEnhancementState(currentItem) {
        const highestSuccessLevel = Math.max(...Object.keys(currentItem).filter(level => currentItem[level]["成功次数"] > 0));
        return (highestSuccessLevel + 1 >= enhancementData[currentTrackingIndex]["其他数据"]["目标强化等级"]) ? "强化成功" : "强化失败";
    }

    // Updated initializeNewItem():
    function initializeNewItem(action, itemHRID, newLevel) {
        const rawItemName = item_hrid_to_name[itemHRID] || "Unknown";
        const protectionHrid = getProtectionItemHrid(action);
        const isProtected = protectionHrid !== null;

        enhancementData[currentTrackingIndex]["其他数据"] = {
            "物品HRID": itemHRID,
            "物品名称": rawItemName,
            "目标强化等级": action.enhancingMaxLevel,
            "是否保护": isProtected,
            "保护物品HRID": protectionHrid,
            "保护物品名称": isProtected ? (item_hrid_to_name[protectionHrid] || protectionHrid) : null,
            "保护消耗总数": 0,
            "保护总成本": 0,
            "保护最小等级": action.enhancingProtectionMinLevel
        };

        // Initialize current level data with all required properties
        enhancementData[currentTrackingIndex]["强化数据"][newLevel] = {
            "成功次数": 0,
            "失败次数": 0,
            "成功率": 0
        };
    }

    function getProtectionItemHrid(action) {
        // If protection is disabled (min level < 2)
        if (action.enhancingProtectionMinLevel < 2) {
            return null;
        }

        // Extract protection item from secondaryItemHash
        if (action.secondaryItemHash) {
            const parts = action.secondaryItemHash.split('::');
            if (parts.length >= 3 && parts[2].startsWith('/items/')) {
                return parts[2];
            }
        }

        // No protection being used
        return null;
    }

    function translateItemName(hrid, fallbackName) {

        if (!isZH) {
            return fallbackName;
        }

        try {
            const gameData = JSON.parse(localStorage.getItem('initClientData'));

            if (gameData?.itemDetailMap?.[hrid]?.name) {
                const translated = gameData.itemDetailMap[hrid].name;
                return translated;
            }
        } catch (e) {
            console.error("Translation error:", e);
        }

        return item_hrid_to_name?.[hrid] || fallbackName || "Unknown";
    }

    function getCurrentItemName(session) {
        if (!session["其他数据"] || !session["其他数据"]["物品HRID"]) return "Unknown";
        const itemHRID = session["其他数据"]["物品HRID"];

        // Always get fresh translation from game data
        if (item_hrid_to_name && item_hrid_to_name[itemHRID]) {
            return item_hrid_to_name[itemHRID];
        }

        // Fallback to English if needed
        const initData = JSON.parse(localStorage.getItem('initClientData') || '{}');
        if (initData.itemDetailMap && initData.itemDetailMap[itemHRID]) {
            return initData.itemDetailMap[itemHRID].name;
        }

        return "Unknown";
    }

    function showTargetAchievedCelebration(achievedLevel, targetLevel) {
        const celebration = document.createElement("div");
        celebration.id = "enhancementCelebration";
        Object.assign(celebration.style, {
            position: "fixed",
            top: "0",
            left: "0",
            width: "100%",
            height: "100%",
            zIndex: "99999",
            pointerEvents: "none",
            display: "flex",
            flexDirection: "column",
            justifyContent: "center",
            alignItems: "center",
            background: "radial-gradient(circle, rgba(0,0,0,0.7), transparent 70%)"
        });

        const text = document.createElement("div");
        text.textContent = isZH ? `目标达成! +${achievedLevel}` : `TARGET ACHIEVED! +${achievedLevel}`;
        Object.assign(text.style, {
            fontSize: "3rem",
            fontWeight: "900",
            color: "#FFD700",
            textShadow: "0 0 20px #FF0000, 0 0 30px #FF8C00",
            animation: "celebrateText 2s ease-out both"
        });
        celebration.appendChild(text);

        for (let i = 0; i < 100; i++) {
            const confetti = document.createElement("div");
            Object.assign(confetti.style, {
                position: "absolute",
                width: "10px",
                height: "10px",
                backgroundColor: getRandomColor(),
                borderRadius: "50%",
                left: "50%",
                top: "50%",
                opacity: "0",
                animation: `confettiFly ${Math.random() * 2 + 1}s ease-out ${Math.random() * 0.5}s both`
            });
            celebration.appendChild(confetti);
        }

        for (let i = 0; i < 8; i++) {
            setTimeout(() => {
                createFireworkBurst(celebration);
            }, i * 300);
        }

        document.body.appendChild(celebration);

        setTimeout(() => {
            celebration.style.opacity = "0";
            celebration.style.transition = "opacity 1s ease-out";
            setTimeout(() => celebration.remove(), 1000);
        }, 4000);
    }

    function createFireworkBurst(container) {
        const burst = document.createElement("div");
        Object.assign(burst.style, {
            position: "absolute",
            left: `${Math.random() * 80 + 10}%`,
            top: `${Math.random() * 80 + 10}%`,
            width: "5px",
            height: "5px",
            borderRadius: "50%",
            background: getRandomColor(),
            boxShadow: `0 0 10px 5px ${getRandomColor()}`,
            animation: `fireworkExpand 0.8s ease-out both`
        });
        container.appendChild(burst);

        for (let i = 0; i < 30; i++) {
            setTimeout(() => {
                const particle = document.createElement("div");
                Object.assign(particle.style, {
                    position: "absolute",
                    left: burst.style.left,
                    top: burst.style.top,
                    width: "3px",
                    height: "3px",
                    backgroundColor: burst.style.background,
                    borderRadius: "50%",
                    animation: `fireworkTrail ${Math.random() * 0.5 + 0.5}s ease-out both`
                });
                container.appendChild(particle);
            }, i * 20);
        }
    }

    function getRandomColor() {
        const colors = ["#FF0000", "#FF8C00", "#FFD700", "#4CAF50", "#2196F3", "#9C27B0"];
        return colors[Math.floor(Math.random() * colors.length)];
    }

    // ======================
    // DISPLAY SYSTEM
    // ======================

    function updateDisplay() {
        const targetElement = document.querySelector(".SkillActionDetail_enhancingComponent__17bOx");
        if (!targetElement) return;

        let parentContainer = document.querySelector("#enhancementParentContainer");
        if (!parentContainer) {
            parentContainer = createDisplayContainer(targetElement);
        }

        updateDropdown(parentContainer);
    }

    function createDisplayContainer(targetElement) {
        const parentContainer = document.createElement("div");
        parentContainer.id = "enhancementParentContainer";
        Object.assign(parentContainer.style, {
            display: "block",
            borderLeft: `2px solid ${STYLE.colors.border}`,
            padding: "0 4px"
        });

        const title = document.createElement("div");
        title.textContent = isZH ? "强化数据" : "Enhancement Data";
        Object.assign(title.style, {
            fontWeight: "bold",
            marginBottom: "10px",
            textAlign: "center",
            color: STYLE.colors.textSecondary,
            font: STYLE.fonts.header
        });
        parentContainer.appendChild(title);

        const dropdownContainer = document.createElement("div");
        dropdownContainer.style.marginBottom = "10px";
        const dropdown = document.createElement("select");
        dropdown.id = "enhancementDropdown";
        Object.assign(dropdown.style, {
            width: "100%",
            padding: "4px",
            borderRadius: STYLE.borderRadius.small,
            background: STYLE.colors.background,
            color: STYLE.colors.textPrimary,
            border: STYLE.colors.border
        });
        dropdown.addEventListener("change", function() {
            renderStats(this.value);
            updateDropdownColor();
        });
        dropdownContainer.appendChild(dropdown);
        parentContainer.appendChild(dropdownContainer);

        const statsContainer = document.createElement("div");
        statsContainer.id = "enhancementStatsContainer";
        Object.assign(statsContainer.style, {
            display: "grid",
            gridTemplateColumns: "repeat(4, 1fr)",
            gap: "10px",
            textAlign: "center",
            marginTop: "10px",
            font: STYLE.fonts.secondary
        });
        parentContainer.appendChild(statsContainer);

        targetElement.appendChild(parentContainer);
        return parentContainer;
    }

    function updateDropdown(parentContainer) {
        const dropdown = parentContainer.querySelector("#enhancementDropdown");
        const previousSelectedValue = dropdown.value;
        dropdown.innerHTML = "";

        Object.keys(enhancementData).forEach(key => {
            const item = enhancementData[key];
            if (!item["其他数据"]) return;

            const option = document.createElement("option");
            const itemName = translateItemName(
                item["其他数据"]["物品HRID"],
                item["其他数据"]["物品名称"]
            );
            const targetLevel = item["其他数据"]["目标强化等级"] || 0;
            const currentLevel = Math.max(...Object.keys(item["强化数据"] || {}).map(Number).filter(n => !isNaN(n))) || 0;
            const enhancementState = item["强化状态"] || "";

            option.text = isZH
                ? `${itemName} (目标: ${targetLevel}, 总计: ${item["强化次数"] || 0}${item["其他数据"]["保护消耗总数"] > 0 ? `, 垫子: ${item["其他数据"]["保护消耗总数"]}` : ""})`
                : `${itemName} (Target: ${targetLevel}, Total: ${item["强化次数"] || 0}${item["其他数据"]["保护消耗总数"] > 0 ? `, Protectors: ${item["其他数据"]["保护消耗总数"]}` : ""})`;

            option.value = key;
            option.style.color = enhancementState === "强化成功" ? STYLE.colors.success
                : (currentLevel < targetLevel && Object.keys(enhancementData).indexOf(key) === Object.keys(enhancementData).length - 1) ? STYLE.colors.accent
                : STYLE.colors.danger;

            dropdown.appendChild(option);
        });

        if (Object.keys(enhancementData).length > 0) {
            dropdown.value = previousSelectedValue || Object.keys(enhancementData)[0];
            updateDropdownColor();
            renderStats(dropdown.value);
        }
    }

    function updateDropdownColor() {
        const dropdown = document.querySelector("#enhancementDropdown");
        if (!dropdown) return;
        const selectedOption = dropdown.options[dropdown.selectedIndex];
        dropdown.style.color = selectedOption ? selectedOption.style.color : STYLE.colors.textPrimary;
    }

    function renderStats(selectedKey) {
        const statsContainer = document.querySelector("#enhancementStatsContainer");
        if (!statsContainer) return;
        statsContainer.innerHTML = "";

        const item = enhancementData[selectedKey];
        if (!item || !item["强化数据"]) return;

        const headers = ["等级", "成功", "失败", "概率"];
        headers.forEach(headerText => {
            const headerDiv = document.createElement("div");
            headerDiv.style.fontWeight = "bold";
            headerDiv.textContent = isZH ? headerText :
                headerText === "等级" ? "Level" :
                headerText === "成功" ? "Success" :
                headerText === "失败" ? "Failure" :
                "Success Rate";
            statsContainer.appendChild(headerDiv);
        });

        const totalSuccess = Object.values(item["强化数据"]).reduce((acc, val) => acc + (val["成功次数"] || 0), 0);
        const totalFailure = Object.values(item["强化数据"]).reduce((acc, val) => acc + (val["失败次数"] || 0), 0);
        const totalCount = totalSuccess + totalFailure;
        const totalRate = totalCount > 0 ? (totalSuccess / totalCount * 100).toFixed(2) : "0.00";

        ["总计", totalSuccess, totalFailure, `${totalRate}%`].forEach((totalText, index) => {
            const totalDiv = document.createElement("div");
            totalDiv.textContent = isZH ? totalText : index === 0 ? "Total" : totalText;
            statsContainer.appendChild(totalDiv);
        });

        Object.keys(item["强化数据"])
            .map(Number)
            .sort((a, b) => b - a)
            .forEach(level => {
                const levelData = item["强化数据"][level];
                const levelDivs = [
                    level,
                    levelData["成功次数"] || 0,
                    levelData["失败次数"] || 0,
                    `${((levelData["成功率"] || 0) * 100).toFixed(2)}%`
                ];

                levelDivs.forEach(data => {
                    const dataDiv = document.createElement("div");
                    dataDiv.textContent = data;
                    statsContainer.appendChild(dataDiv);
                });
            });
    }

    // ======================
    // FLOATING UI SYSTEM (F9 TOGGLE)
    // ======================

    let floatingUI = null;
    let cleanupFunctions = [];

    function createFloatingUI() {
        if (floatingUI && document.body.contains(floatingUI)) {
            return floatingUI;
        }

        // Create main container (existing code remains the same)
        floatingUI = document.createElement("div");
        floatingUI.id = "enhancementFloatingUI";
        Object.assign(floatingUI.style, {
            position: "fixed",
            top: "50px",
            left: "50px",
            zIndex: "9998",
            fontSize: "14px",
            padding: "0",
            borderRadius: STYLE.borderRadius.medium,
            boxShadow: '0 8px 32px rgba(0, 0, 0, 0.6)',
            overflow: "hidden",
            width: "320px",
            minHeight: "auto",
            background: 'rgba(25, 0, 35, 0.92)',
            backdropFilter: 'blur(12px)',
            border: `1px solid ${STYLE.colors.primary}`,
            color: STYLE.colors.textPrimary,
            willChange: "transform",
            transform: "translateZ(0)",
            backfaceVisibility: "hidden",
            perspective: "1000px",
            display: "flex",
            flexDirection: "column"
        });

        // Create header
        const header = document.createElement("div");
        header.id = "enhancementPanelHeader";
        Object.assign(header.style, {
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
            cursor: "move",
            padding: "10px 15px",
            background: STYLE.colors.headerBg,
            borderBottom: `1px solid ${STYLE.colors.border}`,
            userSelect: "none",
            WebkitUserSelect: "none",
            flexShrink: "0"
        });

        // Create title with session counter
        const titleContainer = document.createElement("div");
        titleContainer.style.display = "flex";
        titleContainer.style.alignItems = "center";
        titleContainer.style.gap = "10px";

        const title = document.createElement("span");
        title.textContent = isZH ? "强化追踪器" : "Enhancement Tracker";
        title.style.fontWeight = "bold";

        const sessionCounter = document.createElement("span");
        sessionCounter.id = "enhancementSessionCounter";
        sessionCounter.style.fontSize = "12px";
        sessionCounter.style.opacity = "0.7";
        sessionCounter.style.marginLeft = "5px";

        titleContainer.appendChild(title);
        titleContainer.appendChild(sessionCounter);

        // Create navigation arrows container
        const navContainer = document.createElement("div");
        Object.assign(navContainer.style, {
            display: "flex",
            gap: "5px",
            alignItems: "center",
            marginLeft: "auto"
        });

        // Create clear sessions button
         const clearButton = document.createElement("button");
         clearButton.innerHTML = "🗑️";
         clearButton.title = isZH ? "清除所有会话" : "Clear all sessions";
         Object.assign(clearButton.style, {
             background: "none",
             border: "none",
             color: STYLE.colors.textPrimary,
             cursor: "pointer",
             fontSize: "14px",
             padding: "2px 8px",
             borderRadius: "3px",
             transition: STYLE.transitions.fast,
             marginRight: "5px"
         });
         clearButton.addEventListener("mouseover", () => {
             clearButton.style.color = STYLE.colors.danger;
             clearButton.style.background = "rgba(255, 0, 0, 0.1)";
         });
         clearButton.addEventListener("mouseout", () => {
             clearButton.style.color = STYLE.colors.textPrimary;
             clearButton.style.background = "none";
         });
         clearButton.addEventListener("click", (e) => {
             e.stopPropagation();
             clearAllSessions();
         });

        // Create previous arrow
        const prevArrow = document.createElement("button");
        prevArrow.innerHTML = "&larr;";
        Object.assign(prevArrow.style, {
            background: "none",
            border: "none",
            color: STYLE.colors.textPrimary,
            cursor: "pointer",
            fontSize: "14px",
            padding: "2px 8px",
            borderRadius: "3px",
            transition: STYLE.transitions.fast
        });
        prevArrow.addEventListener("mouseover", () => {
            prevArrow.style.color = STYLE.colors.accent;
            prevArrow.style.background = "rgba(255, 255, 255, 0.1)";
        });
        prevArrow.addEventListener("mouseout", () => {
            prevArrow.style.color = STYLE.colors.textPrimary;
            prevArrow.style.background = "none";
        });
        prevArrow.addEventListener("click", (e) => {
            e.stopPropagation();
            navigateSessions(-1);
        });

        // Create next arrow
        const nextArrow = document.createElement("button");
        nextArrow.innerHTML = "&rarr;";
        Object.assign(nextArrow.style, {
            background: "none",
            border: "none",
            color: STYLE.colors.textPrimary,
            cursor: "pointer",
            fontSize: "14px",
            padding: "2px 8px",
            borderRadius: "3px",
            transition: STYLE.transitions.fast
        });
        nextArrow.addEventListener("mouseover", () => {
            nextArrow.style.color = STYLE.colors.accent;
            nextArrow.style.background = "rgba(255, 255, 255, 0.1)";
        });
        nextArrow.addEventListener("mouseout", () => {
            nextArrow.style.color = STYLE.colors.textPrimary;
            nextArrow.style.background = "none";
        });
        nextArrow.addEventListener("click", (e) => {
            e.stopPropagation();
            navigateSessions(1);
        });

        // Add elements to header
        header.appendChild(titleContainer);
        navContainer.appendChild(clearButton);
        navContainer.appendChild(prevArrow);
        navContainer.appendChild(nextArrow);
        header.appendChild(navContainer);

        // Rest of the existing code (drag functionality, content area, etc.) remains the same
        let isDragging = false;
        let offsetX, offsetY;
        let animationFrameId;

        header.addEventListener("mousedown", (e) => {
            isDragging = true;
            offsetX = e.clientX - floatingUI.offsetLeft;
            offsetY = e.clientY - floatingUI.offsetTop;
            floatingUI.classList.add("dragging");
            e.preventDefault();
        });

        const mouseMoveHandler = (e) => {
            if (!isDragging) return;
            cancelAnimationFrame(animationFrameId);
            animationFrameId = requestAnimationFrame(() => {
                floatingUI.style.left = `${e.clientX - offsetX}px`;
                floatingUI.style.top = `${e.clientY - offsetY}px`;
            });
        };

        const mouseUpHandler = () => {
            if (!isDragging) return;
            isDragging = false;
            floatingUI.classList.remove("dragging");
            cancelAnimationFrame(animationFrameId);
        };

        document.addEventListener("mousemove", mouseMoveHandler, { passive: true });
        document.addEventListener("mouseup", mouseUpHandler, { passive: true });

        cleanupFunctions.push(() => {
            document.removeEventListener("mousemove", mouseMoveHandler);
            document.removeEventListener("mouseup", mouseUpHandler);
        });

        floatingUI.appendChild(header);

        // Create content area
        const content = document.createElement("div");
        content.id = "enhancementPanelContent";
        Object.assign(content.style, {
            padding: "8px",
            overflowY: "hidden",
            flexGrow: "1",
            minHeight: "0",
            contain: "strict",
            boxSizing: "border-box",
            display: "flex",
            flexDirection: "column"
        });

        const resizeObserver = new ResizeObserver((entries) => {
                cancelAnimationFrame(animationFrameId);
                animationFrameId = requestAnimationFrame(() => {
                    const headerHeight = header.offsetHeight;
                    const contentHeight = content.scrollHeight;
                    const newHeight = headerHeight + contentHeight;

                    // Disable transitions temporarily when shrinking
                    if (newHeight < parseInt(floatingUI.style.height || 0)) {
                        floatingUI.style.transition = 'none';
                        floatingUI.style.height = `${newHeight}px`;
                        // Force reflow before re-enabling transitions
                        void floatingUI.offsetHeight;
                        floatingUI.style.transition = STYLE.transitions.medium;
                    } else {
                        floatingUI.style.height = `${newHeight}px`;
                    }
                });
            });
            resizeObserver.observe(content);

        cleanupFunctions.push(() => resizeObserver.disconnect());
        floatingUI.appendChild(content);

        document.body.appendChild(floatingUI);
        // Initial class for empty state
        floatingUI.classList.toggle('has-data', false);
        return floatingUI;
    }

    function navigateSessions(direction) {
        const sessionKeys = Object.keys(enhancementData).map(Number).sort((a, b) => a - b);
        if (sessionKeys.length <= 1) return;

        const currentIndex = sessionKeys.indexOf(currentViewingIndex);
        const newIndex = currentIndex + direction;

        if (newIndex >= 0 && newIndex < sessionKeys.length) {
            currentViewingIndex = sessionKeys[newIndex];
            saveEnhancementData(); // Save the new viewing index
            updateSessionCounter();
            updateFloatingUI();
        }
    }

    function updateSessionCounter() {
        const sessionCounter = document.getElementById("enhancementSessionCounter");
        if (!sessionCounter) return;

        const sessionKeys = Object.keys(enhancementData).map(Number).sort((a, b) => a - b);
        const currentPosition = sessionKeys.indexOf(currentViewingIndex) + 1;
        const totalSessions = sessionKeys.length;

        sessionCounter.textContent = isZH
            ? `(${currentPosition}/${totalSessions}) [${currentViewingIndex}]`
            : `(${currentPosition}/${totalSessions}) [${currentViewingIndex}]`;

        // Visual indicator
        sessionCounter.style.color = currentViewingIndex === currentTrackingIndex ?
            STYLE.colors.accent : STYLE.colors.textSecondary;
        sessionCounter.style.fontWeight = currentViewingIndex === currentTrackingIndex ?
            "bold" : "normal";
    }

    function refreshFloatingUIHeight() {
        const header = document.getElementById("enhancementPanelHeader");
        const content = document.getElementById("enhancementPanelContent");
        if (!header || !content || !floatingUI) return;

        const headerHeight = header.offsetHeight;
        const contentHeight = content.scrollHeight;

        floatingUI.style.height = `min(${headerHeight + contentHeight}px, 80vh)`;
    }


    // Define table styles
    const compactTableStyle = `
        width: 100%;
        border-collapse: separate;
        border-spacing: 0;
        font-size: 13px;
        margin: 5px 0;
        background: rgba(30, 0, 40, 0.6);
        border-radius: ${STYLE.borderRadius.small};
        overflow: hidden;
    `;

    const compactCellStyle = `
        padding: 4px 8px;
        line-height: 1.3;
        border-bottom: 1px solid rgba(126, 87, 194, 0.2);
    `;

    const compactHeaderStyle = `
        ${compactCellStyle}
        font-weight: bold;
        text-align: center;
        background: ${STYLE.colors.headerBg};
        color: ${STYLE.colors.textPrimary};
        border-bottom: 2px solid ${STYLE.colors.primary};
    `;

    function updateFloatingUI() {
        updateSessionCounter();
        const floatingUI = document.getElementById("enhancementFloatingUI") || createFloatingUI();
        const content = document.getElementById("enhancementPanelContent");

        // Clear existing content
        content.innerHTML = '';

        if (currentViewingIndex === 0 || !enhancementData[currentViewingIndex]) {
            floatingUI.classList.toggle('has-data', false);
            content.innerHTML = `
                <div class="empty-state">
                    <div class="empty-icon">✧</div>
                    <div class="empty-text">${isZH ? "开始强化以记录数据" : "Begin enhancing to populate data"}</div>
                </div>
            `;
            floatingUI.style.height = 'auto';
            return;
        }

        floatingUI.classList.toggle('has-data', true);

        const session = enhancementData[currentViewingIndex];
        if (!session || !session["其他数据"]) {
            content.innerHTML = isZH ? "没有活跃的强化数据" : "No active enhancement data";
            floatingUI.style.height = 'auto';
            return;
        }

        // Get market status
        const marketStatus = lastMarketUpdate > 0 ?
            `${isZH ? '市场数据' : 'Market data'} ${new Date(lastMarketUpdate * 1000).toLocaleTimeString()}` :
            `${isZH ? '无市场数据' : 'No market data'}`;

        const itemData = session["其他数据"] || {};
        const itemName = translateItemName(itemData["物品HRID"], itemData["物品名称"]) || "Unknown";
        const targetLevel = itemData["目标强化等级"] || 0;

        // Create main container with fixed height
        const container = document.createElement("div");
        container.style.display = 'flex';
        container.style.flexDirection = 'column';
        container.style.height = '100%';

        // Create fixed header content with market status
        const headerContent = document.createElement("div");
        headerContent.style.flexShrink = '0';
        headerContent.innerHTML = `
            <div style="margin-bottom: 5px; font-size: 12px; color: ${lastMarketUpdate > 0 ? STYLE.colors.success : STYLE.colors.danger};">
                ${marketStatus}
            </div>
            <div style="margin-bottom: 10px; font-size: 13px;">
                <div style="display: flex; justify-content: space-between;">
                    <span>${isZH ? "物品" : "Item"}:</span>
                    <strong>${itemName}</strong>
                </div>
                <div style="display: flex; justify-content: space-between;">
                    <span>${isZH ? "目标" : "Target"}:</span>
                    <span>+${targetLevel}</span>
                </div>
            </div>
        `;

        // Create scrollable content area
        const scrollContent = document.createElement("div");
        scrollContent.style.flexGrow = '1';
        scrollContent.style.overflowY = 'auto';
        scrollContent.style.minHeight = '333px';
        scrollContent.style.maxHeight = '500px';
        scrollContent.style.paddingRight = '5px';

        // Build content using the proper functions
        scrollContent.innerHTML = buildTableHTML(session);

        if (session["材料消耗"] && Object.keys(session["材料消耗"]).length > 0) {
            scrollContent.innerHTML += generateMaterialCostsHTML(session);
        }

        // Assemble the UI
        container.appendChild(headerContent);
        container.appendChild(scrollContent);
        content.appendChild(container);

        // Set floating UI dimensions
        floatingUI.style.height = '600px';
        floatingUI.style.minHeight = '150px';
        floatingUI.style.maxHeight = '80vh';
        floatingUI.style.overflow = 'hidden';
    }


    function buildTableHTML(session) {
        const totalAttempts = session["强化次数"];
        const totalSuccess = Object.values(session["强化数据"]).reduce((sum, level) => sum + (level["成功次数"] || 0), 0);
        const totalFailure = Object.values(session["强化数据"]).reduce((sum, level) => sum + (level["失败次数"] || 0), 0);
        const totalRate = totalAttempts > 0 ? (totalSuccess / totalAttempts * 100).toFixed(2) : 0;

        return `
            <table style="${compactTableStyle}">
                <thead>
                    <tr>
                        <th style="${compactHeaderStyle}">${isZH ? "等级" : "Lvl"}</th>
                        <th style="${compactHeaderStyle}">${isZH ? "成功" : "Success"}</th>
                        <th style="${compactHeaderStyle}">${isZH ? "失败" : "Fail"}</th>
                        <th style="${compactHeaderStyle}">%</th>
                    </tr>
                </thead>
                <tbody>
                    ${Object.keys(session["强化数据"])
                        .sort((a, b) => b - a)
                        .map(level => {
                            const levelData = session["强化数据"][level];
                            const rate = ((levelData["成功率"] || 0) * 100).toFixed(1);
                            const isCurrent = (level == enhancementLevel) && (currentTrackingIndex == currentViewingIndex);
                            return `
                            <tr ${isCurrent ? `
                                style="
                                    background: linear-gradient(90deg, rgba(126, 87, 194, 0.25), rgba(0, 242, 255, 0.1));
                                    box-shadow: 0 0 12px rgba(126, 87, 194, 0.5), inset 0 0 6px rgba(0, 242, 255, 0.3);
                                    border-left: 3px solid ${STYLE.colors.accent};
                                    font-weight: bold;
                                "` : ''}>
                                <td style="${compactCellStyle} text-align: center;">${level}</td>
                                <td style="${compactCellStyle} text-align: right;">${levelData["成功次数"] || 0}</td>
                                <td style="${compactCellStyle} text-align: right;">${levelData["失败次数"] || 0}</td>
                                <td style="${compactCellStyle} text-align: right;">${rate}%</td>
                            </tr>`;
                        }).join('')}
                </tbody>
            </table>

            <div style="margin-top: 8px; display: flex; justify-content: space-between; font-size: 13px;">
                <span>${isZH ? "总计尝试次数" : "Total Attempts"}:</span>
                <strong>${totalAttempts}</strong>
            </div>
        `;
    }

    function generateProtectionHTML(session) {
        return `
            <div style="margin-top: 8px; padding-top: 8px; border-top: 1px dashed ${STYLE.colors.border}">
                <div style="display: flex; justify-content: space-between;">
                    <span>${isZH ? "保护物品" : "Protection Item"}:</span>
                    <span>${translateItemName(
                        session["其他数据"]["保护物品HRID"],
                        session["其他数据"]["保护物品名称"]
                    )}</span>
                </div>
                <div style="display: flex; justify-content: space-between;">
                    <span>${isZH ? "使用数量" : "Used"}:</span>
                    <span>${session["其他数据"]["保护消耗总数"]}</span>
                </div>
                <div style="display: flex; justify-content: space-between;">
                    <span>${isZH ? "保护总成本" : "Protection Cost"}:</span>
                    <strong style="color: ${STYLE.colors.gold}">${formatNumber(session["其他数据"]["保护总成本"])}</strong>
                </div>
            </div>
        `;
    }

    function formatNumber(num) {
        if (typeof num !== 'number') return '0';
        return num.toLocaleString('en-US', { maximumFractionDigits: 0 });
    }

    function toggleFloatingUI() {
        if (!floatingUI || !document.body.contains(floatingUI)) {
            createFloatingUI();
            updateFloatingUI();
            floatingUI.style.display = "block";
            showUINotification(
                isZH ? "强化追踪器已启用" : "Enhancement Tracker Enabled"
            );
        } else {
            const willShow = floatingUI.style.display === "none";
            floatingUI.style.display = willShow ? "flex" : "none";
            showUINotification(
                isZH ? `强化追踪器${willShow ? "已显示" : "已隐藏"}` :
                      `Enhancement Tracker ${willShow ? "Shown" : "Hidden"}`
            );
        }
        localStorage.setItem("enhancementUIVisible", floatingUI.style.display !== "none");
    }

    function generateMaterialCostsHTML(session) {
        const totalCost = session["总成本"] || 0;
        let html = `
            <div style="margin-top: 10px; border-top: 1px solid ${STYLE.colors.border}; padding-top: 8px;">
                <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
                    <span>${isZH ? "材料成本" : "Material Costs"}:</span>
                    <strong style="color: ${STYLE.colors.gold}; text-shadow: ${STYLE.shadows.gold};">${formatNumber(totalCost)}</strong>
                </div>
                <table style="${compactTableStyle}">
                    <thead>
                        <tr>
                            <th style="${compactHeaderStyle}">${isZH ? "材料" : "Material"}</th>
                            <th style="${compactHeaderStyle}">${isZH ? "数量" : "Qty"}</th>
                            <th style="${compactHeaderStyle}">${isZH ? "成本" : "Cost"}</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${Object.entries(session["材料消耗"])
                            .sort(([hridA, dataA], [hridB, dataB]) => {
                                if (hridA.includes('/items/coin')) return 1;
                                if (hridB.includes('/items/coin')) return -1;
                                return dataB.totalCost - dataA.totalCost;
                            })
                            .map(([hrid, data]) => {
                                const isCoin = hrid.includes('/items/coin');
                                return `
                                <tr>
                                    <td style="${compactCellStyle}">${translateItemName(hrid, data.name)}</td>
                                    <td style="${compactCellStyle} text-align: right;">${isCoin ? '' : data.count}</td>
                                    <td style="${compactCellStyle} text-align: right; color: ${STYLE.colors.gold}">${formatNumber(data.totalCost)}</td>
                                </tr>
                                `;
                            }).join('')}
                    </tbody>
                </table>
            </div>
        `;

        // Add protection cost to the materials display if used
        if (session["其他数据"]["保护消耗总数"] > 0) {
            html += `
                <div style="margin-top: 8px; padding-top: 8px; border-top: 1px dashed ${STYLE.colors.border}">
                    <div style="display: flex; justify-content: space-between;">
                        <span>${isZH ? "保护物品" : "Protection Item"}:</span>
                        <span>${translateItemName(
                            session["其他数据"]["保护物品HRID"],
                            session["其他数据"]["保护物品名称"]
                        )}</span>
                    </div>
                    <div style="display: flex; justify-content: space-between;">
                        <span>${isZH ? "使用数量" : "Used"}:</span>
                        <span>${session["其他数据"]["保护消耗总数"]}</span>
                    </div>
                    <div style="display: flex; justify-content: space-between;">
                        <span>${isZH ? "保护总成本" : "Protection Cost"}:</span>
                        <strong style="color: ${STYLE.colors.gold}">${formatNumber(session["其他数据"]["保护总成本"])}</strong>
                    </div>
                </div>
            `;
        }

        return html;
    }

    function refreshFloatingUIHeight() {
        const floatingUI = document.getElementById("enhancementFloatingUI");
        if (!floatingUI) return;

        // Keep the fixed height but ensure it's within bounds
        floatingUI.style.height = '400px';
        floatingUI.style.minHeight = '200px';
        floatingUI.style.maxHeight = '70vh';
    }

function cleanupFloatingUI() {
    if (floatingUI && document.body.contains(floatingUI)) {
        floatingUI.remove();
    }
    cleanupFunctions.forEach(fn => fn());
    cleanupFunctions = [];
    floatingUI = null;
}

// ======================
// UI NOTIFICATION SYSTEM
// ======================

function showUINotification(message, duration = 2000) {
    const notification = document.createElement("div");
    Object.assign(notification.style, {
        position: "fixed",
        bottom: "20px",
        left: "50%",
        transform: "translateX(-50%)",
        padding: '8px 12px',
        borderRadius: "4px",
        backdropFilter: 'blur(4px)',
        border: `1px solid ${STYLE.colors.primary}`,
        background: 'rgba(40, 0, 60, 0.9)',
        backgroundColor: "rgba(0, 0, 0, 0.8)",
        color: "white",
        zIndex: "10000",
        fontSize: "14px",
        animation: "fadeInOut 2s ease-in-out",
        pointerEvents: "none"
    });
    notification.textContent = message;
    document.body.appendChild(notification);

    setTimeout(() => {
        notification.style.opacity = "0";
        setTimeout(() => notification.remove(), 300);
    }, duration);
}

// ======================
// KEYBOARD SHORTCUT
// ======================

function setupKeyboardShortcut() {
    document.addEventListener("keydown", (e) => {
        if (e.key === "F9") {
            e.preventDefault();
            toggleFloatingUI();
        }
    });
}

    // ======================
    // TESTING SYSTEM
    // ======================

    function initializeTesting() {
        if (typeof GM_registerMenuCommand !== 'undefined') {
            GM_registerMenuCommand("🔧 Test Success Notifications", () => testNotifications("success"));
            GM_registerMenuCommand("🔧 Test Failure Notifications", () => testNotifications("failure"));
            GM_registerMenuCommand("✨ Test Blessed Success", () => testNotifications("blessed"));
            GM_registerMenuCommand("🌀 Test All Notifications", () => testNotifications("all"));

            GM_registerMenuCommand("💎 Test Hitting Target Level", () => {
                const level = 15;
                const type = "success";
                const targetLevel = 15;

                const isBlessed = type === "blessed";
                const isSuccess = type !== "failure";
                showNotification(
                    isBlessed ? "BLESSED!" : isSuccess ? "Success" : "Failed!",
                    isSuccess ? "success" : "failure",
                    level,
                    isBlessed
                );

                if (level >= targetLevel) {
                    showTargetAchievedCelebration(level, targetLevel);
                }
            });
        }

        window.testEnhancement = {
            success: () => testNotifications("success"),
            allSuccess: () => testNotifications("allSuccess"),
            failure: () => testNotifications("failure"),
            blessed: () => testNotifications("blessed"),
            all: () => testNotifications("all"),
            custom: (level, type, targetLevel) => {
                const isBlessed = type === "blessed";
                const isSuccess = type !== "failure";
                showNotification(
                    isBlessed ? "BLESSED!" : isSuccess ? "Success" : "Failed!",
                    isSuccess ? "success" : "failure",
                    level,
                    isBlessed
                );

                if (level >= targetLevel) {
                    showTargetAchievedCelebration(level, targetLevel);
                }
            }
        };
    }

    function testNotifications(type) {
        const tests = {
            success: [
                { level: 1, blessed: false },
                { level: 5, blessed: false },
                { level: 10, blessed: false },
                { level: 15, blessed: false },
                { level: 20, blessed: false }
            ],
            allSuccess: [
                { level: 1, blessed: false },
                { level: 2, blessed: false },
                { level: 3, blessed: false },
                { level: 4, blessed: false },
                { level: 5, blessed: false },
                { level: 6, blessed: false },
                { level: 7, blessed: false },
                { level: 8, blessed: false },
                { level: 9, blessed: false },
                { level: 10, blessed: false },
                { level: 11, blessed: false },
                { level: 12, blessed: false },
                { level: 13, blessed: false },
                { level: 14, blessed: false },
                { level: 15, blessed: false },
                { level: 16, blessed: false },
                { level: 17, blessed: false },
                { level: 18, blessed: false },
                { level: 19, blessed: false },
                { level: 20, blessed: false }
            ],
            blessed: [
                { level: 3, blessed: true },
                { level: 8, blessed: true },
                { level: 12, blessed: true },
                { level: 17, blessed: true },
                { level: 22, blessed: true }
            ],
            failure: [
                { level: 0, blessed: false }
            ],
            all: [
                { level: 1, blessed: false },
                { level: 0, blessed: false },
                { level: 3, blessed: true },
                { level: 0, blessed: false },
                { level: 10, blessed: false },
                { level: 12, blessed: true },
                { level: 15, blessed: false },
                { level: 0, blessed: false },
                { level: 20, blessed: false }
            ]
        };

        tests[type].forEach((test, i) => {
            setTimeout(() => {
                const message = test.blessed ?
                    (isZH ? `祝福强化! +${test.level}` : `BLESSED! +${test.level}`) :
                    (test.level > 0 ?
                        (isZH ? `强化成功 +${test.level}` : `Success +${test.level}`) :
                        (isZH ? "强化失败!" : "Failed!"));

                showNotification(
                    message,
                    test.level > 0 ? "success" : "failure",
                    test.level,
                    test.blessed
                );
            }, i * 800);
        });
    }

    // ======================
    // INITIALIZATION
    // ======================

    function addGlobalStyles() {
        const style = document.createElement("style");
        style.textContent = `
            @keyframes pulse {
                0% { transform: scale(1); }
                50% { transform: scale(1.05); }
                100% { transform: scale(1); }
            }
            @keyframes holyGlow {
                0% { box-shadow: 0 0 10px #FFD700; }
                50% { box-shadow: 0 0 25px #FFD700, 0 0 40px white; }
                100% { box-shadow: 0 0 10px #FFD700; }
            }
            @keyframes raysRotate {
                from { transform: rotate(0deg); }
                to { transform: rotate(360deg); }
            }
            @keyframes floatUp {
                0% { transform: translateY(0) rotate(0deg); opacity: 0; }
                10% { opacity: 0.7; }
                90% { opacity: 0.7; }
                100% { transform: translateY(-100px) rotate(20deg); opacity: 0; }
            }
            @keyframes celebrateText {
                0% { transform: scale(0.5); opacity: 0; }
                50% { transform: scale(1.2); opacity: 1; }
                100% { transform: scale(1); }
            }
            @keyframes confettiFly {
                0% { transform: translate(0,0) rotate(0deg); opacity: 1; }
                100% { transform: translate(${Math.random() > 0.5 ? '-' : ''}${Math.random() * 300 + 100}px, ${Math.random() * 300 + 100}px) rotate(360deg); opacity: 0; }
            }
            @keyframes fireworkExpand {
                0% { transform: scale(0); opacity: 1; }
                100% { transform: scale(20); opacity: 0; }
            }
            @keyframes fireworkTrail {
                0% { transform: translate(0,0); opacity: 1; }
                100% { transform: translate(${Math.random() > 0.5 ? '-' : ''}${Math.random() * 100 + 50}px, ${Math.random() * 100 + 50}px); opacity: 0; }
            }
            .enhancement-notification {
                position: relative;
                overflow: hidden;
                transition: ${STYLE.transitions.medium};
                backdrop-filter: blur(4px);
                -webkit-backdrop-filter: blur(4px);
                background: 'rgba(255, 255, 255, 0.1)',
                border: '1px solid rgba(255, 255, 255, 0.2)',
            }
            #enhancementFloatingUI {
              transition: height 0.15s ease-out, opacity 0.2s ease, transform 0.2s ease;
              height: auto;
              max-height: 80vh;
              backdrop-filter: blur(8px);
              -webkit-backdrop-filter: blur(8px);
              background: 'rgba(255, 255, 255, 0.1)',
              border: '1px solid rgba(255, 255, 255, 0.2)',
            }
            #enhancementFloatingUI.no-transition {
                transition: none !important;
            }
            #enhancementPanelContent {
                scrollbar-width: thin;
                scrollbar-color: ${STYLE.colors.border} transparent;
            }
            #enhancementPanelContent::-webkit-scrollbar {
                width: 6px;
            }

            #enhancementPanelContent::-webkit-scrollbar-thumb {
                background: ${STYLE.colors.primary};
                border-radius: 3px;
            }

            #enhancementPanelContent::-webkit-scrollbar-track {
                background: rgba(30, 0, 40, 0.4);
            }
            #enhancementFloatingUI[style*="display: none"] {
                display: block !important;
                opacity: 0;
                pointer-events: none;
                transform: translateY(10px);
            }
            #enhancementFloatingUI.dragging {
                cursor: grabbing;
                box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
                transition: none;
            }
            @keyframes floatIn {
                0% { opacity: 0; transform: translateY(10px); }
                100% { opacity: 1; transform: translateY(0); }
            }
            #enhancementFloatingUI:not([style*="display: none"]) {
                animation: floatIn 0.2s ease-out;
            }
            @keyframes fadeInOut {
                0% { opacity: 0; transform: translateX(-50%) translateY(10px); }
                20% { opacity: 1; transform: translateX(-50%) translateY(0); }
                80% { opacity: 1; transform: translateX(-50%) translateY(0); }
                100% { opacity: 0; transform: translateX(-50%) translateY(-10px); }
            }
            @keyframes mythicPulse {
                0% {
                    background-position: 0% 50%;
                    transform: scale(1);
                    box-shadow: 0 0 8px #ff0033;
                }
                50% {
                    background-position: 100% 50%;
                    transform: scale(1.05);
                    box-shadow: 0 0 16px #ff2200, 0 0 24px #ff2200;
                }
                100% {
                    background-position: 0% 50%;
                    transform: scale(1);
                    box-shadow: 0 0 8px #ff0033;
                }
            }
            #enhancementPanelHeader button {
                background: none;
                border: none;
                color: ${STYLE.colors.textPrimary};
                cursor: pointer;
                font-size: 14px;
                padding: 2px 8px;
                border-radius: 3px;
                transition: ${STYLE.transitions.fast};
                display: flex;
                align-items: center;
                justify-content: center;
                width: 24px;
                height: 24px;
            }
            #enhancementPanelHeader button:hover {
                color: ${STYLE.colors.accent};
                background: rgba(255, 255, 255, 0.1);
            }
            #enhancementPanelHeader button:active {
                transform: scale(0.9);
            }
            #enhancementPanelHeader .nav-arrows {
                display: flex;
                gap: 5px;
                margin-left: auto;
            }
            /* Enhanced scrollbar styling */
            #enhancementPanelContent > div::-webkit-scrollbar {
                width: 6px;
                height: 6px;
            }

            #enhancementPanelContent > div::-webkit-scrollbar-thumb {
                background-color: ${STYLE.colors.primary};
                border-radius: 3px;
            }

            #enhancementPanelContent > div::-webkit-scrollbar-track {
                background-color: rgba(30, 0, 40, 0.4);
                border-radius: 3px;
            }

            #enhancementPanelContent > div {
                scrollbar-width: thin;
                scrollbar-color: ${STYLE.colors.primary} rgba(30, 0, 40, 0.4);
            }

            /* Better empty state for scroll container */
            .empty-state {
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                height: 100px;
                color: ${STYLE.colors.textSecondary};
                padding: 20px;
                text-align: center;
            }
            .empty-icon {
                font-size: 32px;
                margin-bottom: 10px;
                opacity: 0.5;
            }

            .empty-text {
                font-size: 14px;
            }

            #enhancementFloatingUI:not(.has-data) {
                height: 150px !important; /* Fixed height for empty state */
            }
        `;
        document.head.appendChild(style);
    }

    function initializeFloatingUI() {
        const checkReady = setInterval(() => {
            if (document.body && typeof item_hrid_to_name !== "undefined") {
                clearInterval(checkReady);
                setupKeyboardShortcut();

                if (localStorage.getItem("enhancementUIVisible") !== "false") {
                    createFloatingUI();
                    updateFloatingUI();
                }
            }
        }, 500);
    }

    // Start everything
    addGlobalStyles();
    initializeTesting();
    initializeFloatingUI();
    // Initialize market data loading when script starts
    loadMarketData();
    hookWS();

    console.log("Enhancement Notifier v3.2.0 loaded - With Cost Tracking/Session Nav and Persistent Data");
})();