Item Market Armor Preview

Try an armor before buying in the Item Market

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Item Market Armor Preview
// @namespace    https://torn.com
// @version      1.4.6
// @description  Try an armor before buying in the Item Market
// @author       JESUUS [2353554]
// @copyright    2025, JESUUS - All rights reserved
// @license      MIT
// @match        *://www.torn.com/page.php?sid=ItemMarket*
// @match        *://www.torn.com/imarket.php*
// @match        *://www.torn.com/bazaar.php*
// @grant        none
// @run-at       document-idle
// ==/UserScript==


(function() {
    'use strict';

    if (typeof PDA_httpGet !== 'undefined' || window.innerWidth < 768) return;

    const API_KEY = localStorage.getItem('tornApiKey') || '';

    let currentEquipment = [];
    let tryOnConfig = JSON.parse(localStorage.getItem('armorPreviewTryOn') || '{}');

    function formatPrice(price) {
        if (!price && price !== 0) return '-';
        return '$' + price.toLocaleString('en-US');
    }

    function parsePrice(priceStr) {
        if (!priceStr) return 0;
        const cleaned = priceStr.replace(/[$,\s]/g, '');
        return parseInt(cleaned, 10) || 0;
    }

    function getTotalPrice() {
        return Object.values(tryOnConfig).reduce((sum, item) => sum + (item.price || 0), 0);
    }

    let bazaarAvailabilityCache = {};
    let marketAvailabilityCache = {};

    function extractBazaarUserId(url) {
        if (!url || !url.includes('bazaar.php')) return null;
        const match = url.match(/user[Ii][Dd]=(\d+)/);
        return match ? match[1] : null;
    }

    async function checkBazaarAvailability(item) {
        if (!API_KEY || !item.sourceUrl) return null;

        const userId = extractBazaarUserId(item.sourceUrl);
        if (!userId) return null;

        const cacheKey = `${userId}_${item.id}`;
        if (bazaarAvailabilityCache[cacheKey] !== undefined) {
            return bazaarAvailabilityCache[cacheKey];
        }

        try {
            const response = await fetch(`https://api.torn.com/user/${userId}?selections=bazaar&key=${API_KEY}`);
            const data = await response.json();

            if (data.error) {
                bazaarAvailabilityCache[cacheKey] = null;
                return null;
            }

            const bazaarItems = data.bazaar || [];
            const totalQuantity = bazaarItems
                .filter(bazaarItem => bazaarItem.ID === item.id)
                .reduce((sum, bazaarItem) => sum + (bazaarItem.quantity || 1), 0);
            const result = totalQuantity > 0 ? { available: true, quantity: totalQuantity } : { available: false, quantity: 0 };

            bazaarAvailabilityCache[cacheKey] = result;
            return result;
        } catch (error) {
            bazaarAvailabilityCache[cacheKey] = null;
            return null;
        }
    }

    async function checkMarketAvailability(item) {
        if (!API_KEY || !item.id) return null;

        const cacheKey = `market_${item.id}`;
        if (marketAvailabilityCache[cacheKey] !== undefined) {
            return marketAvailabilityCache[cacheKey];
        }

        try {
            const response = await fetch(`https://api.torn.com/v2/market/${item.id}/itemmarket?key=${API_KEY}`);
            const data = await response.json();

            if (data.error) {
                marketAvailabilityCache[cacheKey] = null;
                return null;
            }

            const listings = data.itemmarket?.listings || [];
            const totalQuantity = listings.reduce((sum, listing) => sum + (listing.quantity || 1), 0);
            const result = totalQuantity > 0 ? { available: true, quantity: totalQuantity } : { available: false, quantity: 0 };

            marketAvailabilityCache[cacheKey] = result;
            return result;
        } catch (error) {
            marketAvailabilityCache[cacheKey] = null;
            return null;
        }
    }

    async function checkAllBazaarAvailability() {
        if (!API_KEY) return {};

        const results = {};
        const promises = [];

        Object.entries(tryOnConfig).forEach(([slot, item]) => {
            if (item.sourceUrl && item.sourceUrl.includes('bazaar.php')) {
                promises.push(
                    checkBazaarAvailability(item).then(available => {
                        results[slot] = available;
                    })
                );
            } else {
                promises.push(
                    checkMarketAvailability(item).then(available => {
                        results[slot] = available;
                    })
                );
            }
        });

        await Promise.all(promises);
        return results;
    }

    const DEFENSIVE_SLOTS = {
        helmet: { name: 'Helmet', zIndex: 5 },
        body: { name: 'Body', zIndex: 4 },
        pants: { name: 'Pants', zIndex: 3 },
        gloves: { name: 'Gloves', zIndex: 2 },
        boots: { name: 'Boots', zIndex: 1 }
    };

    const CLOTHING_SLOTS = {
        head: { name: 'Head', zIndex: 20 },
        eye: { name: 'Eye', zIndex: 19 },
        mouth: { name: 'Mouth', zIndex: 18 },
        nose: { name: 'Nose', zIndex: 17 },
        mask: { name: 'Mask', zIndex: 16 },
        neck: { name: 'Neck', zIndex: 15 },
        shirt: { name: 'Shirt', zIndex: 14 },
        torso: { name: 'Torso', zIndex: 15 },
        hand: { name: 'Hand', zIndex: 13 },
        leg: { name: 'Leg', zIndex: 12 },
        foot: { name: 'Foot', zIndex: 11 }
    };

    const ALL_SLOTS = { ...DEFENSIVE_SLOTS, ...CLOTHING_SLOTS };

    const DEFENSIVE_IDS = new Set([32,33,34,49,50,176,178,332,333,334,348,538,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,848,1164,1165,1166,1167,1168,1174,1307,1308,1309,1310,1311,1355,1356,1357,1358,1359]);
    const CLOTHING_IDS = new Set([46,47,48,101,107,278,347,404,412,413,414,430,562,582,598,606,607,608,609,610,621,622,623,624,625,626,633,635,698,703,704,719,726,727,728,729,730,743,791,803,806,807,808,809,810,811,812,813,816,828,834,835,836,841,842,843,849,851,869,921,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,982,983,988,989,990,991,992,995,996,998,1001,1002,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1036,1037,1038,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1150,1151,1169,1177,1180,1181,1182,1183,1184,1185,1186,1187,1188,1190,1191,1192,1193,1194,1195,1196,1197,1291,1295,1299,1313,1360,1367,1368,1369,1449,1450,1452,1453,1475]);
    const EOD_IDS = new Set([680, 681, 682, 683, 684]);

    const DEFENSIVE_LAYERS = {
        helmet: [
            { id: 665, item: "Assault Helmet", layers: [3] },
            { id: 651, item: "Combat Helmet", layers: [3] },
            { id: 660, item: "Dune Helmet", layers: [3] },
            { id: 670, item: "Delta Gas Mask", layers: [5, 4, 3] },
            { id: 680, item: "EOD Helmet", layers: [5, 4, 3] },
            { id: 538, item: "Medieval Helmet", layers: [5, 4, 3] },
            { id: 642, item: "Motorcycle Helmet", layers: [5, 4, 3] },
            { id: 644, item: "Welding Helmet", layers: [5, 4, 3] },
            { id: 655, item: "Riot Helmet", layers: [4, 3] },
            { id: 675, item: "Marauder Face Mask", layers: [3] },
            { id: 647, item: "Leather Helmet", layers: [3] },
            { id: 641, item: "WWII Helmet", layers: [3] },
            { id: 643, item: "Construction Helmet", layers: [3] }
        ],
        body: [
            { id: 666, item: "Assault Body", layers: [3] },
            { id: 332, item: "Combat Vest", layers: [3] },
            { id: 661, item: "Dune Vest", layers: [3] },
            { id: 671, item: "Delta Body", layers: [3] },
            { id: 681, item: "EOD Apron", layers: [3] },
            { id: 348, item: "Hazmat Suit", layers: [5, 4, 3] },
            { id: 676, item: "Marauder Body", layers: [3] },
            { id: 656, item: "Riot Body", layers: [3] },
            { id: 32, item: "Leather Vest", layers: [3] },
            { id: 33, item: "Police Vest", layers: [3] },
            { id: 34, item: "Bulletproof Vest", layers: [3] },
            { id: 49, item: "Full Body Armor", layers: [3] },
            { id: 50, item: "Outer Tactical Vest", layers: [3] },
            { id: 176, item: "Chain Mail", layers: [3] },
            { id: 178, item: "Flak Jacket", layers: [3] },
            { id: 333, item: "Liquid Body Armor", layers: [3] },
            { id: 334, item: "Flexible Body Armor", layers: [3] },
            { id: 848, item: "Kevlar Lab Coat", layers: [3] }
        ],
        pants: [
            { id: 667, item: "Assault Pants", layers: [3] },
            { id: 652, item: "Combat Pants", layers: [3] },
            { id: 662, item: "Dune Pants", layers: [3] },
            { id: 672, item: "Delta Pants", layers: [3] },
            { id: 682, item: "EOD Pants", layers: [3] },
            { id: 648, item: "Leather Pants", layers: [3] },
            { id: 677, item: "Marauder Pants", layers: [3] },
            { id: 657, item: "Riot Pants", layers: [3] }
        ],
        gloves: [
            { id: 669, item: "Assault Gloves", layers: [3] },
            { id: 654, item: "Combat Gloves", layers: [3] },
            { id: 664, item: "Dune Gloves", layers: [3] },
            { id: 674, item: "Delta Gloves", layers: [3] },
            { id: 684, item: "EOD Gloves", layers: [3] },
            { id: 640, item: "Kevlar Gloves", layers: [3] },
            { id: 650, item: "Leather Gloves", layers: [3] },
            { id: 679, item: "Marauder Gloves", layers: [3] },
            { id: 659, item: "Riot Gloves", layers: [3] }
        ],
        boots: [
            { id: 668, item: "Assault Boots", layers: [3] },
            { id: 653, item: "Combat Boots", layers: [3] },
            { id: 663, item: "Dune Boots", layers: [3] },
            { id: 673, item: "Delta Boots", layers: [3] },
            { id: 683, item: "EOD Boots", layers: [3] },
            { id: 649, item: "Leather Boots", layers: [3] },
            { id: 678, item: "Marauder Boots", layers: [3] },
            { id: 658, item: "Riot Boots", layers: [3] },
            { id: 645, item: "Safety Boots", layers: [3] },
            { id: 646, item: "Hiking Boots", layers: [3] }
        ]
    };

    const CLOTHING_LAYERS = {
        head: [
            { id: 680, item: "Paper Bag", layers: [5, 4] },
            { id: 726, item: "Scrooge's Top Hat", layers: [5, 4] },
            { id: 995, item: "Sun Hat", layers: [5, 4] },
            { id: 598, item: "Witch's Hat", layers: [5, 4] },
            { id: 1130, item: "Bunny Ears", layers: [5] },
            { id: 1149, item: "Bunny Suit", layers: [5] },
            { id: 1129, item: "Cat Ears", layers: [5] },
            { id: 1133, item: "Hair Bow", layers: [5] },
            { id: 1131, item: "Puppy Ears", layers: [5] },
            { id: 608, item: "Santa Hat", layers: [5] },
            { id: 1135, item: "Unicorn Horn", layers: [6] },
            { id: 1108, item: "Wedding Veil", layers: [5] },
            { id: 927, item: "Baseball Cap", layers: [4] },
            { id: 1019, item: "Bingo Visor", layers: [4] },
            { id: 1068, item: "Bucket Hat", layers: [4] },
            { id: 931, item: "Bush Hat", layers: [4] },
            { id: 935, item: "Cork Hat", layers: [4] },
            { id: 1052, item: "Denim Cap", layers: [4] },
            { id: 1106, item: "Fascinator Hat", layers: [4] },
            { id: 937, item: "Fisherman Hat", layers: [4] },
            { id: 990, item: "Fur Hat", layers: [4] },
            { id: 1109, item: "Head Scarf", layers: [4] },
            { id: 719, item: "Helmet of Justice", layers: [4] },
            { id: 636, item: "Jester's Cap", layers: [4] },
            { id: 1104, item: "Maid Hat", layers: [4] },
            { id: 1074, item: "Panama Hat", layers: [4] },
            { id: 1043, item: "Paper Crown - Green", layers: [4] },
            { id: 1044, item: "Paper Crown - Yellow", layers: [4] },
            { id: 1045, item: "Paper Crown - Red", layers: [4] },
            { id: 1046, item: "Paper Crown - Blue", layers: [4] },
            { id: 1070, item: "Durag", layers: [2] },
            { id: 582, item: "Tin Foil Hat", layers: [4] }
        ],
        nose: [
            { id: 1151, item: "Bunny Nose", layers: [4] },
            { id: 621, item: "Snorkel", layers: [4] },
            { id: 1182, item: "Head Bandage", layers: [3] }
        ],
        mask: [
            { id: 1177, item: "Sandworm Mask", layers: [6] }, // Layers over EVERYTHING
            { id: 597, item: "Scream Mask", layers: [5] },
            { id: 1075, item: "Pipe", layers: [4] },
            { id: 1037, item: "Anatomy Mask", layers: [3] },
            { id: 1101, item: "Ball Gag", layers: [3] },
            { id: 404, item: "Bandana", layers: [3] },
            { id: 1144, item: "Chin Diaper", layers: [3] },
            { id: 828, item: "Donald Trump Mask", layers: [3] },
            { id: 869, item: "Elon Musk Mask", layers: [3] },
            { id: 807, item: "Exotic Gentleman Mask", layers: [3] },
            { id: 808, item: "Ginger Kid Mask", layers: [3] },
            { id: 1036, item: "Greta Mask", layers: [3] },
            { id: 926, item: "Gronch Mask", layers: [3] },
            { id: 1295, item: "Hell Priest Mask", layers: [3] },
            { id: 1013, item: "Jigsaw Mask", layers: [3] },
            { id: 278, item: "Kabuki Mask", layers: [3] },
            { id: 1181, item: "Krampus Mask", layers: [3] },
            { id: 1143, item: "Medical Mask", layers: [3] },
            { id: 921, item: "Michael Myers Mask", layers: [3] },
            { id: 810, item: "Moustache Man Mask", layers: [3] },
            { id: 813, item: "Nun Mask", layers: [3] },
            { id: 816, item: "Old Lady Mask", layers: [3] },
            { id: 1141, item: "Pennywise Mask", layers: [3] },
            { id: 1180, item: "Prince Philip Mask", layers: [3] },
            { id: 812, item: "Psycho Clown Mask", layers: [3] },
            { id: 1299, item: "Queen Elizabeth II Mask", layers: [3] },
            { id: 611, item: "Santa Beard", layers: [3] },
            { id: 811, item: "Scarred Man Mask", layers: [3] },
            { id: 1150, item: "Balaclava", layers: [2] },
            { id: 803, item: "Duke's Gimp Mask", layers: [3] }
        ],
        neck: [
            { id: 1193, item: "Neck Brace", layers: [5] },
            { id: 968, item: "Bow Tie", layers: [4] },
            { id: 959, item: "Choker", layers: [3] },
            { id: 1100, item: "Collar", layers: [3] },
            { id: 989, item: "Fur Scarf", layers: [3] },
            { id: 969, item: "Neck Tie", layers: [3] },
            { id: 1076, item: "Shoulder Sweater", layers: [3] }
        ],
        eye: [
            { id: 1020, item: "Cover-ups", layers: [5] },
            { id: 983, item: "Bandit Mask", layers: [4] },
            { id: 1102, item: "Blindfold", layers: [4] },
            { id: 414, item: "Glasses", layers: [4] },
            { id: 1132, item: "Heart Sunglasses", layers: [4] },
            { id: 1183, item: "Medical Eye Patch", layers: [4] },
            { id: 975, item: "Monocle", layers: [4] },
            { id: 1014, item: "Reading Glasses", layers: [4] },
            { id: 1066, item: "Shutter Shades", layers: [4] },
            { id: 412, item: "Sports Shades", layers: [4] },
            { id: 996, item: "Square Sunglasses", layers: [4] }
        ],
        shirt: [
            { id: 1105, item: "Ball Gown", layers: [2] },
            { id: 929, item: "Blouse", layers: [2] },
            { id: 743, item: "Christmas Sweater '15", layers: [2] },
            { id: 936, item: "Crop Top", layers: [2] },
            { id: 1047, item: "Denim Shirt", layers: [2] },
            { id: 1103, item: "Maid Uniform", layers: [2] },
            { id: 943, item: "Peplum Top", layers: [2] },
            { id: 1137, item: "Polka Dot Dress", layers: [2] },
            { id: 944, item: "Polo Shirt", layers: [2] },
            { id: 1067, item: "Silver Hoodie", layers: [2] },
            { id: 835, item: "String Vest", layers: [2] },
            { id: 562, item: "Sweater", layers: [2] },
            { id: 1107, item: "Wedding Dress", layers: [2] },
            { id: 624, item: "Bikini", layers: [1] },
            { id: 930, item: "Boob Tube", layers: [1] },
            { id: 932, item: "Camisole", layers: [1] },
            { id: 430, item: "Coconut Bra", layers: [1] },
            { id: 967, item: "Fitted Shirt", layers: [1] },
            { id: 791, item: "Mediocre T-Shirt", layers: [1] },
            { id: 46, item: "Tank Top", layers: [1] },
            { id: 1064, item: "Tube Dress", layers: [1] },
            { id: 625, item: "Wetsuit", layers: [1] }
        ],
        torso: [
            { id: 1027, item: "Badge : 15th Anniversary", layers: [6] },
            { id: 1186, item: "Torso Bandage", layers: [6] },
            { id: 1071, item: "Onesie", layers: [5, 4] },
            { id: 945, item: "Poncho", layers: [5, 4] },
            { id: 635, item: "Straitjacket", layers: [5, 4] },
            { id: 1025, item: "Bathrobe", layers: [5] },
            { id: 1049, item: "Denim Jacket", layers: [5] },
            { id: 843, item: "Duster", layers: [5] },
            { id: 988, item: "Fur Coat", layers: [5] },
            { id: 1197, item: "Hospital Gown", layers: [5] },
            { id: 947, item: "Mackintosh", layers: [5] },
            { id: 1110, item: "Nightgown", layers: [5] },
            { id: 965, item: "Nipple Tassels", layers: [5] },
            { id: 727, item: "Scrooge's Topcoat", layers: [5] },
            { id: 1077, item: "Sports Jacket", layers: [5] },
            { id: 107, item: "Trench Coat", layers: [5] },
            { id: 1072, item: "Baseball Jacket", layers: [4] },
            { id: 1062, item: "Basketball Shirt", layers: [4] },
            { id: 971, item: "Blazer", layers: [4] },
            { id: 1073, item: "Braces", layers: [4] },
            { id: 934, item: "Cardigan", layers: [4] },
            { id: 958, item: "Chest Harness", layers: [4] },
            { id: 1016, item: "Collared Shawl", layers: [4] },
            { id: 1048, item: "Denim Vest", layers: [4] },
            { id: 998, item: "Floral Dress", layers: [4] },
            { id: 48, item: "Jacket", layers: [4] },
            { id: 1061, item: "Oversized Shirt", layers: [4] },
            { id: 1069, item: "Puffer Jacket", layers: [4] },
            { id: 946, item: "Puffer Vest", layers: [4] },
            { id: 1111, item: "Pullover", layers: [4] },
            { id: 940, item: "Raincoat", layers: [4] },
            { id: 609, item: "Santa Jacket", layers: [4] },
            { id: 1001, item: "Shrug", layers: [4] },
            { id: 974, item: "Smoking Jacket", layers: [4] }
        ],
        hand: [
            { id: 1192, item: "Plaster Cast Arm", layers: [6] },
            { id: 626, item: "Diving Gloves", layers: [4] },
            { id: 1190, item: "Hook Hand", layers: [4] },
            { id: 633, item: "Latex Gloves", layers: [4] },
            { id: 1098, item: "Opera Gloves", layers: [4] },
            { id: 607, item: "Santa Gloves", layers: [4] },
            { id: 730, item: "Scrooge's Gloves", layers: [4] },
            { id: 1187, item: "Prosthetic Arm", layers: [6] }
        ],
        leg: [
            { id: 1191, item: "Plaster Cast Leg", layers: [6] },
            { id: 1188, item: "Prosthetic Leg", layers: [6] },
            { id: 1184, item: "Knee Brace", layers: [5] },
            { id: 1097, item: "Assless Chaps", layers: [4] },
            { id: 928, item: "Bermudas", layers: [4] },
            { id: 1136, item: "Check Skirt", layers: [4] },
            { id: 1015, item: "Chinos", layers: [4] },
            { id: 1050, item: "Denim Jeans", layers: [4] },
            { id: 1139, item: "Dungarees", layers: [4] },
            { id: 1134, item: "Lolita Dress", layers: [4] },
            { id: 1196, item: "Medical Diaper", layers: [4] },
            { id: 964, item: "Mini Skirt", layers: [4] },
            { id: 1063, item: "Parachute Pants", layers: [4] },
            { id: 698, item: "Peg Leg", layers: [4] },
            { id: 942, item: "Pencil Skirt", layers: [4] },
            { id: 842, item: "Pinstripe Suit Trousers", layers: [4] },
            { id: 1017, item: "Pleated Skirt", layers: [4] },
            { id: 982, item: "Ripped Jeans", layers: [4] },
            { id: 1060, item: "Saggy Pants", layers: [4] },
            { id: 610, item: "Santa Trousers", layers: [4] },
            { id: 728, item: "Scrooge's Trousers", layers: [4] },
            { id: 948, item: "Shorts", layers: [4] },
            { id: 949, item: "Skirt", layers: [4] },
            { id: 972, item: "Suit Trousers", layers: [4] },
            { id: 834, item: "Sweatpants", layers: [4] },
            { id: 1126, item: "Tutu", layers: [4] },
            { id: 933, item: "Capri Pants", layers: [3] },
            { id: 1099, item: "Booty Shorts", layers: [2] },
            { id: 938, item: "Gym Shorts", layers: [2] },
            { id: 1145, item: "Tighty Whities", layers: [2] },
            { id: 960, item: "Fishnet Stockings", layers: [1] },
            { id: 941, item: "Pantyhose", layers: [1] },
            { id: 623, item: "Speedo", layers: [1] },
            { id: 347, item: "Thong", layers: [1] },
            { id: 1140, item: "Tights", layers: [1] },
            { id: 952, item: "Yoga Pants", layers: [1] }
        ],
        foot: [
            { id: 622, item: "Flippers", layers: [5] },
            { id: 606, item: "Santa Boots", layers: [5] },
            { id: 973, item: "Derby Shoes", layers: [4] },
            { id: 1138, item: "Ballet Shoes", layers: [4] },
            { id: 836, item: "Black Oxfords", layers: [4] },
            { id: 1051, item: "Denim Shoes", layers: [4] },
            { id: 1018, item: "Flip Flops", layers: [4] },
            { id: 1065, item: "Gold Sneakers", layers: [4] },
            { id: 1128, item: "Kitty Shoes", layers: [4] },
            { id: 991, item: "Platform Shoes", layers: [4] },
            { id: 1021, item: "Sandals", layers: [4] },
            { id: 729, item: "Scrooge's Boots", layers: [4] },
            { id: 992, item: "Silver Flats", layers: [4] },
            { id: 1024, item: "Slippers", layers: [4] },
            { id: 950, item: "Sports Sneakers", layers: [4] },
            { id: 953, item: "Trainers", layers: [4] },
            { id: 314, item: "Hiking Boots", layers: [3] },
            { id: 703, item: "Festive Socks", layers: [2] },
            { id: 1022, item: "Golf Socks", layers: [2] },
            { id: 1127, item: "Knee Socks", layers: [2] },
            { id: 1023, item: "Travel Socks", layers: [2] }
        ]
    };

    function getItemLayers(itemId) {
        for (const slot in DEFENSIVE_LAYERS) {
            const item = DEFENSIVE_LAYERS[slot].find(i => i.id === itemId);
            if (item) {
                return { slot, layers: item.layers, name: item.item, isDefensive: true };
            }
        }
        for (const bodyPart in CLOTHING_LAYERS) {
            const item = CLOTHING_LAYERS[bodyPart].find(i => i.id === itemId);
            if (item) {
                return { slot: bodyPart, layers: item.layers, name: item.item, isDefensive: false };
            }
        }
        return null;
    }

    function getItemZIndex(itemId) {
        const layerInfo = getItemLayers(itemId);
        if (layerInfo) {
            const maxLayer = Math.max(...layerInfo.layers);
            let zIndex = maxLayer * 10;
            if (layerInfo.isDefensive) {
                if (layerInfo.slot === 'body') zIndex += 15;
                if (layerInfo.slot === 'helmet') zIndex += 5;
                if (EOD_IDS.has(itemId)) zIndex += 20;
            }
            else if (layerInfo.slot === 'torso' || layerInfo.slot === 'shirt') {
                zIndex += 6;
            }
            return zIndex;
        }
        if (DEFENSIVE_IDS.has(itemId)) {
            return 35;
        }
        if (CLOTHING_IDS.has(itemId)) {
            return 20;
        }
        return 30;
    }

    function isPreviewableItem(itemId) {
        return DEFENSIVE_IDS.has(itemId) || CLOTHING_IDS.has(itemId);
    }

    function saveTryOnConfig() {
        const data = JSON.stringify(tryOnConfig);
        try {
            localStorage.removeItem('armorPreviewTryOn');
            localStorage.setItem('armorPreviewTryOn', data);
        } catch (e) {
            console.error('localStorage quota exceeded');
            alert('localStorage is full! Clear browser data for torn.com');
        }
    }

    function resetTryOnConfig() {
        tryOnConfig = {};
        localStorage.removeItem('armorPreviewTryOn');
    }

    async function loadCurrentEquipment() {
        if (!API_KEY) return;

        try {
            const response = await fetch(`https://api.torn.com/v2/user/equipment?key=${API_KEY}`);
            const data = await response.json();

            if (data.error) return;

            if (data.equipment && Array.isArray(data.equipment)) {
                currentEquipment = data.equipment.filter(item => {
                    return isPreviewableItem(item.id);
                }).map(item => ({
                    id: item.id,
                    name: item.name,
                    type: item.type,
                    slot: item.slot
                }));
            }
        } catch (error) {}
    }

    const style = document.createElement('style');
    style.textContent = `
        .armor-preview-btn {
            background: linear-gradient(180deg, #4a9 0%, #286 100%);
            border: 1px solid #1a5;
            color: white;
            padding: 4px 8px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 11px;
            margin-left: 5px;
        }
        .armor-preview-btn:hover {
            background: linear-gradient(180deg, #5ba 0%, #397 100%);
        }
        .armor-preview-btn.remove {
            background: linear-gradient(180deg, #c55 0%, #933 100%);
            border-color: #a33;
            padding: 2px 6px;
            font-size: 10px;
        }
        .armor-preview-btn.remove:hover {
            background: linear-gradient(180deg, #d66 0%, #a44 100%);
        }
        .armor-preview-btn.buy {
            background: linear-gradient(180deg, #48f 0%, #26c 100%);
            border-color: #15b;
            padding: 2px 6px;
            font-size: 10px;
        }
        .armor-preview-btn.buy:hover {
            background: linear-gradient(180deg, #5af 0%, #37d 100%);
        }
        .armor-preview-modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            z-index: 999999;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .armor-preview-content {
            background: #2a2a2a;
            border-radius: 10px;
            padding: 20px;
            max-width: 1100px;
            width: 95%;
            border: 1px solid #444;
            position: relative;
            display: flex;
            gap: 20px;
        }
        .armor-preview-close {
            position: absolute;
            top: 10px;
            right: 15px;
            background: #c33;
            border: none;
            color: white;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            cursor: pointer;
            font-size: 18px;
            z-index: 10;
        }
        .armor-preview-close:hover {
            background: #e44;
        }
        .armor-preview-title {
            color: #fff;
            text-align: center;
            margin: 0 0 10px;
            font-size: 12px;
        }
        .armor-preview-left {
            flex: 1;
        }
        .armor-preview-right {
            flex: 1;
            border-left: 1px solid #444;
            padding-left: 20px;
        }
        .armor-preview-models {
            display: flex;
            justify-content: center;
            gap: 20px;
        }
        .armor-preview-model-col {
            text-align: center;
        }
        .armor-preview-model {
            position: relative;
            width: 200px;
            height: 300px;
            margin: 0 auto;
        }
        .armor-preview-model img {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            object-fit: contain;
        }
        .armor-preview-toggle-container {
            text-align: center;
            margin-top: 15px;
        }
        .armor-preview-toggle-btn {
            background: #444;
            border: 1px solid #555;
            color: #fff;
            padding: 6px 12px;
            border-radius: 4px;
            cursor: pointer;
            margin: 5px;
        }
        .armor-preview-toggle-btn.active {
            background: #4a9;
            border-color: #5ba;
        }
        .armor-preview-toggle-btn:hover {
            background: #555;
        }
        .armor-preview-toggle-btn.active:hover {
            background: #5ba;
        }
        .armor-preview-slot-list {
            margin-top: 10px;
        }
        .armor-preview-slot {
            background: #333;
            border: 1px solid #555;
            border-radius: 6px;
            padding: 8px 10px;
            margin-bottom: 8px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .armor-preview-slot.has-item {
            border-color: #4a9;
        }
        .armor-preview-slot.trying-on {
            border-color: #f90;
            background: #3a3020;
        }
        .armor-preview-slot-icon {
            width: 40px;
            height: 40px;
            background: #222;
            border-radius: 4px;
            display: flex;
            align-items: center;
            justify-content: center;
            overflow: hidden;
        }
        .armor-preview-slot-icon img {
            width: 100%;
            height: 100%;
            object-fit: contain;
        }
        .armor-preview-slot-info {
            flex: 1;
            min-width: 0;
        }
        .armor-preview-slot-name {
            color: #fff;
            font-size: 11px;
            font-weight: bold;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            margin-top: 2px;
        }
        .armor-preview-slot-label {
            color: #888;
            font-size: 10px;
            text-transform: uppercase;
            line-height: 1.4;
        }
        .armor-preview-slot-trying {
            color: #f90;
            font-size: 9px;
        }
        .armor-preview-actions {
            display: flex;
            gap: 5px;
            margin-top: 15px;
            flex-wrap: wrap;
        }
        .armor-preview-actions button {
            flex: 1;
            min-width: 80px;
        }
        .armor-preview-section-title {
            color: #aaa;
            font-size: 12px;
            text-transform: uppercase;
            margin-bottom: 10px;
            padding-bottom: 5px;
            border-bottom: 1px solid #444;
        }
        .armor-preview-badge {
            font-size: 9px;
            padding: 1px 4px;
            border-radius: 3px;
            margin-left: 5px;
        }
        .armor-preview-badge.in-list {
            background: #4a9;
            color: #fff;
        }
        .armor-preview-badge.trying {
            background: #f90;
            color: #000;
        }
        .armor-preview-slot.is-previewing {
            border-color: #58f;
            background: #203050;
        }
        .armor-preview-slot-price {
            color: #82C91E;
            font-size: 10px;
            margin-top: 2px;
        }
        .armor-preview-total {
            color: #888;
            font-size: 10px;
            margin-top: 10px;
            text-align: center;
            padding: 8px;
            background: #222;
            border-radius: 4px;
        }
        .armor-preview-total-price {
            color: #82C91E;
            font-size: 12px;
            font-weight: bold;
            margin-top: 4px;
        }
    `;
    document.head.appendChild(style);

    let playerGender = 'male';

    function getSlotFromItem(itemName, itemId) {
        for (const slot in DEFENSIVE_LAYERS) {
            const found = DEFENSIVE_LAYERS[slot].find(i => i.id === itemId);
            if (found) return slot;
        }
        for (const bodyPart in CLOTHING_LAYERS) {
            const found = CLOTHING_LAYERS[bodyPart].find(i => i.id === itemId);
            if (found) return bodyPart;
        }
        const name = (itemName || '').toLowerCase();
        const isDefensive = DEFENSIVE_IDS.has(itemId);
        if (isDefensive) {
            if (name.includes('helmet') || name.includes('respirator') || name.includes('mask') || name.includes('visage')) return 'helmet';
            if (name.includes('vest') || name.includes('armor') || name.includes('apron') || name.includes('mail') || name.includes('spathe') || name.includes('breastplate') || name.includes('body')) return 'body';
            if (name.includes('pants') || name.includes('britches')) return 'pants';
            if (name.includes('gloves') || name.includes('clawshields')) return 'gloves';
            if (name.includes('boots') || name.includes('hooves')) return 'boots';
            return 'body';
        }
        const isClothing = CLOTHING_IDS.has(itemId);
        if (isClothing) {
            if (name.includes('hat') || name.includes('cap') || name.includes('helmet') || name.includes('ears') || name.includes('horn') || name.includes('veil') || name.includes('crown') || name.includes('visor') || name.includes('durag')) return 'head';
            if (name.includes('glasses') || name.includes('shades') || name.includes('monocle') || name.includes('blindfold') || name.includes('patch') || name.includes('cover-up')) return 'eye';
            if (name.includes('nose') || name.includes('snorkel') || name.includes('bandage')) return 'nose';
            if (name.includes('mask') || name.includes('bandana') || name.includes('balaclava') || name.includes('beard') || name.includes('gag') || name.includes('pipe')) return 'mask';
            if (name.includes('tie') || name.includes('collar') || name.includes('choker') || name.includes('scarf') || name.includes('brace') || name.includes('sweater')) return 'neck';
            if (name.includes('glove') || name.includes('cast arm') || name.includes('hook hand') || name.includes('prosthetic arm')) return 'hand';
            if (name.includes('jacket') || name.includes('coat') || name.includes('blazer') || name.includes('cardigan') || name.includes('poncho') || name.includes('pullover') || name.includes('raincoat') || name.includes('bathrobe') || name.includes('duster')) return 'torso';
            if (name.includes('t-shirt') || name.includes('shirt') || name.includes('top') || name.includes('blouse') || name.includes('camisole') || name.includes('tank') || name.includes('bikini') || name.includes('bra') || name.includes('lingerie') || name.includes('mankini') || name.includes('wetsuit') || name.includes('tube')) return 'shirt';
            if (name.includes('pants') || name.includes('trousers') || name.includes('shorts') || name.includes('skirt') || name.includes('jeans') || name.includes('dress') || name.includes('gown') || name.includes('robe') || name.includes('uniform') || name.includes('chaps') || name.includes('tutu') || name.includes('diaper') || name.includes('onesie') || name.includes('dungarees') || name.includes('speedo') || name.includes('thong') || name.includes('stockings') || name.includes('pantyhose') || name.includes('tights') || name.includes('yoga') || name.includes('cast leg') || name.includes('prosthetic leg')) return 'leg';
            if (name.includes('boots') || name.includes('shoes') || name.includes('trainers') || name.includes('sneakers') || name.includes('flippers') || name.includes('sandals') || name.includes('slippers') || name.includes('socks') || name.includes('flats') || name.includes('oxfords') || name.includes('flip flop')) return 'foot';
            return 'shirt';
        }
        return 'body';
    }

    function getItemForSlot(slot) {
        if (tryOnConfig[slot]) {
            return { ...tryOnConfig[slot], isTryingOn: true };
        }
        const equipped = currentEquipment.find(item => getSlotFromItem(item.name, item.id) === slot);
        return equipped ? { ...equipped, isTryingOn: false } : null;
    }

    function buildLayers(includeNewItem = null, excludeSlot = null) {
        let layers = '';

        Object.keys(ALL_SLOTS).forEach(slot => {
            if (slot === excludeSlot) return;

            const item = getItemForSlot(slot);
            if (item) {
                const zIndex = getItemZIndex(item.id);
                layers += `<img src="/images/v2/items/model-items/${item.id}${playerGender.charAt(0)}.png" style="position:absolute;z-index:${zIndex}" onerror="this.src='/images/v2/items/model-items/${item.id}.png'">`;
            }
        });

        if (includeNewItem) {
            const zIndex = getItemZIndex(includeNewItem.id);
            layers += `<img src="/images/v2/items/model-items/${includeNewItem.id}${playerGender.charAt(0)}.png" style="position:absolute;z-index:${zIndex}" onerror="this.src='/images/v2/items/model-items/${includeNewItem.id}.png'">`;
        }

        return layers;
    }

    async function showPreview(itemId, itemName, itemPrice = 0) {
        document.querySelectorAll('.armor-preview-modal').forEach(m => m.remove());

        const newItemSlot = getSlotFromItem(itemName, itemId);
        const isAlreadyInList = tryOnConfig[newItemSlot]?.id === itemId;

        const bazaarAvailability = await checkAllBazaarAvailability();

        function generateSlotHtml(slots, hideEmpty = false) {
            let html = '';
            Object.entries(slots).forEach(([slotKey, slotInfo]) => {
                const item = getItemForSlot(slotKey);
                const isCurrentSlot = slotKey === newItemSlot;
                const hasItem = !!item;
                const isInList = item?.isTryingOn;

                let displayItem = item;
                let isPreviewing = false;

                if (isCurrentSlot && !isAlreadyInList) {
                    isPreviewing = true;
                    displayItem = { id: itemId, name: itemName };
                } else if (isCurrentSlot && isAlreadyInList) {
                    displayItem = item;
                }

                if (hideEmpty && !hasItem && !isPreviewing) {
                    return;
                }

                let slotClass = 'armor-preview-slot';
                if (hasItem || isPreviewing) slotClass += ' has-item';
                if (isInList && !isPreviewing) slotClass += ' trying-on';
                if (isPreviewing) slotClass += ' is-previewing';

                let badge = '';
                if (isPreviewing) {
                    badge = '<span class="armor-preview-badge trying">TRYING</span>';
                } else if (isInList) {
                    badge = '<span class="armor-preview-badge in-list">IN LIST</span>';
                }

                const showItem = displayItem || item;
                const showRemoveBtn = isInList && !isPreviewing;

                let priceDisplay = '';
                if (isPreviewing && itemPrice) {
                    priceDisplay = `<div class="armor-preview-slot-price">${formatPrice(itemPrice)}</div>`;
                } else if (isInList && item?.price) {
                    priceDisplay = `<div class="armor-preview-slot-price">${formatPrice(item.price)}</div>`;
                }

                let buyBtnHtml = '';
                if (isInList && item?.id) {
                    const buyUrl = (item.sourceUrl && item.sourceUrl.length > 0) ? item.sourceUrl : `https://www.torn.com/page.php?sid=ItemMarket#/market/view=search&itemID=${item.id}`;
                    const isBazaarItem = item.sourceUrl && item.sourceUrl.includes('bazaar.php');

                    let availabilityHtml = '';
                    let isOutOfStock = false;

                    if (API_KEY) {
                        const availability = bazaarAvailability[slotKey];
                        const qty = availability?.quantity || 0;
                        isOutOfStock = availability && qty === 0;

                        if (availability) {
                            const qtyDisplay = qty > 10 ? '+10' : qty;
                            const sourceType = isBazaarItem ? 'bazaar' : 'market';

                            let color;
                            if (qty >= 3) {
                                color = '#82C91E';
                            } else if (qty >= 1) {
                                color = '#f90';
                            } else {
                                color = '#c55';
                            }

                            availabilityHtml = `<div style="font-size:9px;text-align:center;margin-top:2px;color:${color}" title="${sourceType}: ${qty}">● (${qtyDisplay})</div>`;
                        }
                    }

                    const cartBtnStyle = isOutOfStock ? 'opacity:0.4;pointer-events:none;cursor:not-allowed' : '';
                    const cartTitle = isOutOfStock ? 'Out of stock' : `Buy ${item.name}`;

                    buyBtnHtml = `<div style="display:flex;flex-direction:column;align-items:center">
                        <a href="${buyUrl}" target="_blank" class="armor-preview-btn buy" data-item-id="${item.id}" title="${cartTitle}" style="${cartBtnStyle}"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg></a>
                        ${availabilityHtml}
                    </div>`;
                }

                html += `
                    <div class="${slotClass}" data-slot="${slotKey}">
                        <div class="armor-preview-slot-icon">
                            ${showItem ? `<img src="/images/items/${showItem.id}/medium.png" onerror="this.style.display='none'">` : ''}
                        </div>
                        <div class="armor-preview-slot-info">
                            <div class="armor-preview-slot-label">${slotInfo.name}${badge}</div>
                            <div class="armor-preview-slot-name">${showItem ? showItem.name : '(empty)'}</div>
                            ${priceDisplay}
                        </div>
                        ${buyBtnHtml}
                        ${showRemoveBtn ? `<button class="armor-preview-btn remove" data-slot="${slotKey}">✕</button>` : ''}
                    </div>
                `;
            });
            return html;
        }

        const defensiveSlotsHtml = generateSlotHtml(DEFENSIVE_SLOTS, false);
        const clothingSlotsHtml = generateSlotHtml(CLOTHING_SLOTS, true);

        const isCurrentItemClothing = CLOTHING_IDS.has(itemId);
        const hasClothingEquipped = currentEquipment.some(item => CLOTHING_IDS.has(item.id));
        const hasClothingInList = Object.keys(CLOTHING_SLOTS).some(slot => tryOnConfig[slot]);
        const showClothingColumn = isCurrentItemClothing || hasClothingEquipped || hasClothingInList;

        const beforeLayers = buildLayers();
        const afterLayers = buildLayers(null, newItemSlot) +
            `<img src="/images/v2/items/model-items/${itemId}${playerGender.charAt(0)}.png" style="position:absolute;z-index:${getItemZIndex(itemId)}" onerror="this.src='/images/v2/items/model-items/${itemId}.png'">`;

        const modal = document.createElement('div');
        modal.className = 'armor-preview-modal';
        modal.innerHTML = `
            <div class="armor-preview-content">
                <button class="armor-preview-close">&times;</button>

                <div class="armor-preview-left" style="flex:${showClothingColumn ? '1' : '3'}">
                    <h3 class="armor-preview-title">Try On: ${itemName}</h3>
                    <div class="armor-preview-models">
                        <div class="armor-preview-model-col">
                            <div style="color:#aaa;margin-bottom:10px;font-size:12px">Current Setup</div>
                            <div class="armor-preview-model" id="preview-before">
                                <img src="/images/v2/attack/models/${playerGender}_model.png" alt="Model" style="z-index:1">
                                ${beforeLayers}
                            </div>
                        </div>
                        <div class="armor-preview-model-col">
                            <div style="color:#4a9;margin-bottom:10px;font-size:12px">With ${itemName}</div>
                            <div class="armor-preview-model" id="preview-after">
                                <img src="/images/v2/attack/models/${playerGender}_model.png" alt="Model" style="z-index:1">
                                ${afterLayers}
                            </div>
                        </div>
                    </div>
                    <div class="armor-preview-toggle-container">
                        <button class="armor-preview-toggle-btn" data-gender="male">Male</button>
                        <button class="armor-preview-toggle-btn" data-gender="female">Female</button>
                    </div>
                </div>

                <div class="armor-preview-right" style="display:flex;flex-direction:column;${showClothingColumn ? 'flex:1;min-width:420px' : 'flex:2'}">
                    <div style="display:flex;gap:15px">
                        <div class="armor-preview-column" style="flex:1">
                            <div class="armor-preview-section-title">Defensive</div>
                            <div class="armor-preview-slot-list">
                                ${defensiveSlotsHtml}
                            </div>
                        </div>
                        ${showClothingColumn ? `
                        <div class="armor-preview-column" style="flex:1;min-width:200px">
                            <div class="armor-preview-section-title">Clothing</div>
                            <div class="armor-preview-slot-list">
                                ${clothingSlotsHtml}
                            </div>
                        </div>
                        ` : ''}
                    </div>
                    <div style="padding:15px 0;border-top:1px solid #444;margin-top:15px">
                        <div class="armor-preview-actions" style="margin:0;display:flex;gap:5px">
                            <button class="armor-preview-btn" id="add-to-tryon" style="flex:1;background:linear-gradient(180deg,#f90 0%,#c60 100%);border-color:#a50">
                                + Add List
                            </button>
                            <button class="armor-preview-btn" id="reset-tryon" style="flex:1;background:linear-gradient(180deg,#666 0%,#444 100%);border-color:#555">
                                Reset All
                            </button>
                        </div>
                        <div class="armor-preview-total" style="margin-top:10px;text-align:center">
                            ${Object.keys(tryOnConfig).length > 0
                                ? `<div>${Object.keys(tryOnConfig).length} item(s) in list</div><div class="armor-preview-total-price">Total: ${formatPrice(getTotalPrice())}</div>`
                                : 'No items in list'}
                        </div>
                    </div>
                </div>
                <div style="position:absolute;bottom:10px;left:0;right:0;text-align:center;font-size:12px;color:#888">
                    Item Market Armor Preview Script (By <a href="https://www.torn.com/profiles.php?XID=2353554" target="_blank" style="color:#4a9;text-decoration:none">JESUUS</a>)
                </div>
            </div>
        `;

        modal.querySelector('.armor-preview-close').addEventListener('click', () => modal.remove());
        modal.addEventListener('click', (e) => {
            if (e.target === modal) modal.remove();
        });

        modal.querySelectorAll('.armor-preview-toggle-btn').forEach(btn => {
            if (btn.dataset.gender === playerGender) btn.classList.add('active');
            btn.addEventListener('click', () => {
                playerGender = btn.dataset.gender;
                modal.remove();
                showPreview(itemId, itemName);
            });
        });

        modal.querySelector('#add-to-tryon').addEventListener('click', async () => {
            const newItem = {
                id: itemId,
                name: itemName,
                price: itemPrice,
                sourceUrl: window.location.href
            };
            tryOnConfig[newItemSlot] = newItem;
            saveTryOnConfig();

            const beforeModel = modal.querySelector('#preview-before');
            if (beforeModel) {
                const modelImg = beforeModel.querySelector('img[alt="Model"]');
                beforeModel.innerHTML = '';
                if (modelImg) beforeModel.appendChild(modelImg);
                beforeModel.insertAdjacentHTML('beforeend', buildLayers());
            }

            const slotEl = modal.querySelector(`.armor-preview-slot[data-slot="${newItemSlot}"]`);
            if (slotEl) {
                slotEl.classList.remove('is-previewing', 'has-item');
                slotEl.classList.add('trying-on');
                slotEl.style.borderColor = '#f90';
                slotEl.style.background = '#3a3020';
                const badge = slotEl.querySelector('.armor-preview-badge');
                if (badge) {
                    badge.className = 'armor-preview-badge in-list';
                    badge.textContent = 'IN LIST';
                }

                if (!slotEl.querySelector('.armor-preview-btn.remove')) {
                    const removeBtn = document.createElement('button');
                    removeBtn.className = 'armor-preview-btn remove';
                    removeBtn.dataset.slot = newItemSlot;
                    removeBtn.textContent = '✕';
                    removeBtn.addEventListener('click', (e) => {
                        e.stopPropagation();
                        delete tryOnConfig[newItemSlot];
                        saveTryOnConfig();
                        modal.remove();
                        showPreview(itemId, itemName, itemPrice);
                    });
                    slotEl.appendChild(removeBtn);
                }

                if (!slotEl.querySelector('.armor-preview-btn.buy')) {
                    const isBazaarItem = newItem.sourceUrl && newItem.sourceUrl.includes('bazaar.php');
                    const buyUrl = newItem.sourceUrl || `https://www.torn.com/page.php?sid=ItemMarket#/market/view=search&itemID=${itemId}`;

                    const buyContainer = document.createElement('div');
                    buyContainer.style.cssText = 'display:flex;flex-direction:column;align-items:center';

                    const buyLink = document.createElement('a');
                    buyLink.href = buyUrl;
                    buyLink.target = '_blank';
                    buyLink.className = 'armor-preview-btn buy';
                    buyLink.dataset.itemId = itemId;
                    buyLink.title = `Buy ${itemName}`;
                    buyLink.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg>';
                    buyContainer.appendChild(buyLink);

                    slotEl.insertBefore(buyContainer, slotEl.querySelector('.armor-preview-btn.remove'));

                    if (API_KEY) {
                        const availability = isBazaarItem
                            ? await checkBazaarAvailability(newItem)
                            : await checkMarketAvailability(newItem);

                        if (availability) {
                            const qty = availability.quantity || 0;
                            const qtyDisplay = qty > 10 ? '+10' : qty;
                            const sourceType = isBazaarItem ? 'bazaar' : 'market';
                            const isOutOfStock = qty === 0;

                            let color;
                            if (qty >= 3) color = '#82C91E';
                            else if (qty >= 1) color = '#f90';
                            else color = '#c55';

                            const availabilityDiv = document.createElement('div');
                            availabilityDiv.style.cssText = `font-size:9px;text-align:center;margin-top:2px;color:${color}`;
                            availabilityDiv.title = `${sourceType}: ${qty}`;
                            availabilityDiv.textContent = `● (${qtyDisplay})`;
                            buyContainer.appendChild(availabilityDiv);

                            if (isOutOfStock) {
                                buyLink.style.cssText = 'opacity:0.4;pointer-events:none;cursor:not-allowed';
                                buyLink.title = 'Out of stock';
                            }
                        }
                    }
                }
            }

            const totalEl = modal.querySelector('.armor-preview-total');
            if (totalEl) {
                const count = Object.keys(tryOnConfig).length;
                totalEl.innerHTML = count > 0
                    ? `<div>${count} item(s) in list</div><div class="armor-preview-total-price">Total: ${formatPrice(getTotalPrice())}</div>`
                    : 'No items in list';
            }

            const headerIndicator = document.querySelector('.armor-preview-tryon-indicator');
            const tryOnCount = Object.keys(tryOnConfig).length;
            if (headerIndicator) {
                headerIndicator.innerHTML = `<span style="font-weight:bold">${tryOnCount}</span> in try-on list`;
            } else if (tryOnCount > 0) {
                const headerContainer = document.querySelector('.armor-preview-header-container');
                if (headerContainer) {
                    const tryOnIndicator = document.createElement('div');
                    tryOnIndicator.className = 'armor-preview-tryon-indicator';
                    tryOnIndicator.style.cssText = `
                        display:inline-flex;align-items:center;gap:4px;
                        padding:4px 8px;border-radius:4px;font-size:11px;
                        background:#3a2015;border:1px solid #5a3520;color:#C66230;
                    `;
                    tryOnIndicator.innerHTML = `<span style="font-weight:bold">${tryOnCount}</span> in try-on list`;
                    headerContainer.appendChild(tryOnIndicator);
                }
            }
        });

        modal.querySelector('#reset-tryon').addEventListener('click', () => {
            resetTryOnConfig();
            modal.remove();
            showPreview(itemId, itemName, itemPrice);
        });

        modal.querySelectorAll('.armor-preview-btn.remove').forEach(btn => {
            btn.addEventListener('click', (e) => {
                e.stopPropagation();
                const slot = btn.dataset.slot;
                delete tryOnConfig[slot];
                saveTryOnConfig();
                modal.remove();
                showPreview(itemId, itemName, itemPrice);
            });
        });

        document.body.appendChild(modal);
    }


    function addButtons() {
        const isBazaar = window.location.href.includes('bazaar.php');

        if (isBazaar) {
            const bazaarItems = document.querySelectorAll('[data-testid="item"]');
            bazaarItems.forEach(item => {
                if (item.querySelector('.armor-preview-btn')) return;

                const img = item.querySelector('img[alt]');
                const itemName = img?.alt;

                const imgSrc = img?.src || '';
                const idMatch = imgSrc.match(/\/images\/items\/(\d+)\//);
                const itemId = idMatch ? parseInt(idMatch[1]) : null;

                if (itemId && itemName && isPreviewableItem(itemId)) {
                    const priceEl = item.querySelector('[data-testid="price"]');
                    const priceText = priceEl?.textContent || '';
                    const itemPrice = parsePrice(priceText);

                    const btn = document.createElement('button');
                    btn.className = 'armor-preview-btn';
                    btn.textContent = 'Try On';
                    btn.addEventListener('click', (e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        showPreview(itemId, itemName, itemPrice);
                    });

                    const controlPanel = item.querySelector('[data-testid="control-panel"]');
                    if (controlPanel) {
                        controlPanel.appendChild(btn);
                    }
                }
            });
        } else {
            const itemTiles = document.querySelectorAll('[class*="itemTile"]');
            itemTiles.forEach(item => {
                if (item.querySelector('.armor-preview-btn')) return;

                const infoBtn = item.querySelector('button[aria-controls*="itemInfo-"]');
                const match = infoBtn?.getAttribute('aria-controls')?.match(/itemInfo-(\d+)/);
                const itemId = match ? parseInt(match[1]) : null;

                const img = item.querySelector('img[alt]');
                const itemName = img?.alt;

                if (itemId && itemName && isPreviewableItem(itemId)) {
                    const priceEl = item.querySelector('[class*="priceAndTotal"]');
                    const priceText = priceEl?.textContent || '';
                    const itemPrice = parsePrice(priceText);

                    const btn = document.createElement('button');
                    btn.className = 'armor-preview-btn';
                    btn.textContent = 'Try On';
                    btn.addEventListener('click', (e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        showPreview(itemId, itemName, itemPrice);
                    });

                    const actionsWrapper = item.querySelector('[class*="actionsWrapper"]');
                    if (actionsWrapper) {
                        actionsWrapper.appendChild(btn);
                    }
                }
            });
        }
    }

    function showApiModal() {
        document.querySelectorAll('.armor-api-modal').forEach(m => m.remove());

        const modal = document.createElement('div');
        modal.className = 'armor-preview-modal armor-api-modal';
        modal.innerHTML = `
            <div style="background:#2a2a2a;border-radius:8px;padding:15px;max-width:300px;width:90%;border:1px solid #444;position:relative">
                <button class="armor-preview-close" style="width:24px;height:24px;font-size:14px;top:8px;right:10px">&times;</button>
                <h3 style="color:#fff;text-align:center;margin:0 0 12px;font-size:13px">API Key Setup</h3>
                ${API_KEY ? `
                    <div style="color:#82C91E;text-align:center;margin-bottom:10px;font-size:11px">● Connected</div>
                    <input type="text" id="api-key-input" value="${API_KEY}" style="width:100%;padding:8px;border-radius:4px;border:1px solid #555;background:#333;color:#fff;font-family:monospace;font-size:11px;box-sizing:border-box;margin-bottom:10px">
                    <div style="display:flex;gap:8px">
                        <button id="api-save-btn" class="armor-preview-btn" style="flex:1;padding:6px;font-size:11px">Save</button>
                        <button id="api-remove-btn" class="armor-preview-btn remove" style="flex:1;padding:6px;font-size:11px">Remove</button>
                    </div>
                ` : `
                    <button id="api-create-btn" class="armor-preview-btn" style="width:100%;padding:8px;margin-bottom:8px;font-size:11px;background:linear-gradient(180deg,#f90 0%,#c60 100%);border-color:#a50">
                        Create New Key (Auto)
                    </button>
                    <div style="color:#555;text-align:center;margin:6px 0;font-size:10px">— or paste existing —</div>
                    <input type="text" id="api-key-input" placeholder="API key (16 chars)" style="width:100%;padding:8px;border-radius:4px;border:1px solid #555;background:#333;color:#fff;font-family:monospace;font-size:11px;box-sizing:border-box;margin-bottom:8px">
                    <button id="api-save-btn" class="armor-preview-btn" style="width:100%;padding:6px;font-size:11px">Save Key</button>
                `}
            </div>
        `;

        modal.querySelector('.armor-preview-close').addEventListener('click', () => modal.remove());
        modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); });

        const createBtn = modal.querySelector('#api-create-btn');
        if (createBtn) {
            createBtn.addEventListener('click', () => {
                window.open('https://www.torn.com/preferences.php#tab=api?step=addNewKey&title=ArmorPreview&type=4&user=bazaar,equipment&market=itemmarket', '_blank');
                modal.querySelector('#api-key-input').focus();
            });
        }

        modal.querySelector('#api-save-btn').addEventListener('click', () => {
            const key = modal.querySelector('#api-key-input').value.trim();
            if (key.length === 16) {
                localStorage.setItem('tornApiKey', key);
                location.reload();
            } else {
                alert('API key must be 16 characters');
            }
        });

        const removeBtn = modal.querySelector('#api-remove-btn');
        if (removeBtn) {
            removeBtn.addEventListener('click', () => {
                localStorage.removeItem('tornApiKey');
                location.reload();
            });
        }

        document.body.appendChild(modal);
        modal.querySelector('#api-key-input')?.focus();
    }

    function addConfigButton() {
        if (document.querySelector('.armor-preview-header-container')) return;

        const header = document.querySelector('[class*="itemsHeader"]');
        if (header) {
            const container = document.createElement('div');
            container.className = 'armor-preview-header-container';
            container.style.cssText = 'display:inline-flex;align-items:center;gap:8px;margin-left:10px;vertical-align:middle';

            const apiStatus = document.createElement('div');
            apiStatus.className = 'armor-preview-api-status';
            apiStatus.style.cssText = `
                display:inline-flex;align-items:center;gap:4px;
                padding:4px 8px;border-radius:4px;font-size:11px;cursor:pointer;
                background:${API_KEY ? '#1a2e12' : '#3a2015'};
                border:1px solid ${API_KEY ? '#3a5a25' : '#5a3520'};
                color:${API_KEY ? '#82C91E' : '#C66230'};
            `;
            apiStatus.innerHTML = API_KEY
                ? '<span style="color:#82C91E">●</span> API Connected'
                : '<span style="color:#C66230">○</span> API Not Set';
            apiStatus.title = API_KEY ? 'Click to change API key' : 'Click to set your API key';
            apiStatus.addEventListener('click', showApiModal);
            container.appendChild(apiStatus);

            const tryOnCount = Object.keys(tryOnConfig).length;
            if (tryOnCount > 0) {
                const tryOnIndicator = document.createElement('div');
                tryOnIndicator.className = 'armor-preview-tryon-indicator';
                tryOnIndicator.style.cssText = `
                    display:inline-flex;align-items:center;gap:4px;
                    padding:4px 8px;border-radius:4px;font-size:11px;
                    background:#3a2015;border:1px solid #5a3520;color:#C66230;
                `;
                tryOnIndicator.innerHTML = `<span style="font-weight:bold">${tryOnCount}</span> in try-on list`;
                container.appendChild(tryOnIndicator);
            }

            header.appendChild(container);
        }
    }

    async function init() {
        await loadCurrentEquipment();
        addButtons();
        addConfigButton();
    }

    const observer = new MutationObserver(() => {
        setTimeout(() => {
            addButtons();
            addConfigButton();
        }, 100);
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    setTimeout(init, 500);
    setTimeout(addButtons, 1500);
    setTimeout(addButtons, 3000);
})();