Torn Racing Guide

In-game racing overlay detailing optimal cars, track-specific loadouts, and custom template saving. Includes dynamic upgrade highlighting.

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey, Greasemonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

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

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Torn Racing Guide
// @namespace    TornRacingGuideGNSC4
// @version      1.1.5.1
// @description  In-game racing overlay detailing optimal cars, track-specific loadouts, and custom template saving. Includes dynamic upgrade highlighting.
// @author       GNS-C4 [3960752]
// @license      MIT
// @match        https://www.torn.com/page.php?sid=racing*
// @match        https://torn.com/page.php?sid=racing*
// @include      *://*torn.com/page.php?sid=racing*
// @match        https://www.torn.com/loader.php?sid=racing*
// @match        https://torn.com/loader.php?sid=racing*
// @include      *://*torn.com/loader.php?sid=racing*
// @run-at       document-idle
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // ==========================================
    // CONFIGURATION & DEBUG
    // ==========================================
    const DEBUG = true;

    function debugLog(message, data = null, isError = false) {
        if (!DEBUG) return;
        
        const prefix = `[Torn Racing Guide v1.1.6]`;
        if (isError) {
            if (data) console.error(`${prefix} ERROR: ${message}`, data);
            else console.error(`${prefix} ERROR: ${message}`);
        } else {
            if (data) console.log(`${prefix} ${message}`, data);
            else console.log(`${prefix} ${message}`);
        }
    }

    debugLog("Userscript parsed and execution started.");

    // ==========================================
    // DATA SOURCE (Hybridized)
    // ==========================================
    const racingData = {
        progression: [
            { class: "E", car: "Edomondo Localé", cost: "1 Point", strat: "<strong>Custom Build (1 pt):</strong> Strip Out." },
            { class: "D", car: "Tabata RM2 or Coche Basurero", cost: "15 Points", strat: "<strong>Custom Build (15 pts):</strong> Strip Out, Fast Road Tyres, Polished Throttle Body, Uprated Air Filter Element, Back Box." },
            { class: "C", car: "Bavaria Z8 or Echo S3", cost: "63 Points", strat: "<strong>Custom Build (63 pts):</strong> Strip Out, Track/Rally Tyres, Competition Polished Throttle Body, Full Exhaust System, Uprated Air Filter Element, Stage One Turbo Kit, Grooved & Drilled Brake Discs, Competition Racing Fuel Pump, Uprated Forged Pistons, Ultra-Light Flywheel, Fixed Rear Spoiler, Ported and Polished Head." },
            { class: "B", car: "Colina Tanprice or Echo S4", cost: "130 Points", strat: "<strong>Custom Build (130 pts):</strong> Strip Out, Track/Rally/Rally-Cross Tyres, Bored Out Engine & Forged Pistons, Competition Polished Throttle Body, Forced Induction Kit, Full Exhaust System, Stage Two Turbo Kit, Adjustable Rear Spoiler, Paddle Shift/Rally Gearbox (Long/Short), Grooved & Drilled Brake Discs, Competition Racing Fuel Pump, Stainless Steel 4-1 Manifold, Ultra-Light Flywheel, Ported and Polished Head, Coil-over Suspension (Hard/Soft/Medium), 4 Pot Uprated Brakes, Competition Racing Brake Pads, Air Cooling Ducts for Brakes, Front Mounted Intercooler, 4 Pin Differential, Air Forced Engine Cooling, Quick Shift." },
            { class: "A", car: "Multiple (See Tracks)", cost: "266 Points", strat: "<strong>Ideal Build (266 pts):</strong> Utilize Grando's exact 266-point optimal build. Use the Auto-Scanner to highlight required parts." }
        ],
        tracks: [
            // Tarmac
            { name: "Speedway", car: "Veloria LFA", tuning: "TL3", notes: "Raw top speed dominance." },
            { name: "Commerce", car: "Edomondo NSX", tuning: "TS2", notes: "High turn density, needs flawless handling." },
            { name: "Vector", car: "Edomondo NSX", tuning: "TS3", notes: "Similar to Commerce, slightly longer exits." },
            { name: "Meltdown", car: "Edomondo NSX", tuning: "TS3", notes: "Aggressive late braking required." },
            { name: "Industrial", car: "Edomondo NSX", tuning: "TS3", notes: "Tight 90-degree corners." },
            { name: "Sewage", car: "Edomondo NSX", tuning: "TS2", notes: "Tight subterranean. Smooth power band needed." },
            { name: "Convict", car: "Mercia SLR", tuning: "TL3", notes: "High speed open stretches." },
            { name: "Underdog", car: "Edomondo NSX", tuning: "TS2", notes: "Highly technical tarmac circuit." },
            { name: "Uptown", car: "Veloria LFA", tuning: "TL3", notes: "Massive sweeping curves." },
            { name: "Withdrawal", car: "Veloria LFA", tuning: "TL3", notes: "Very long, top speed mandatory." },
            { name: "Docks", car: "Volt GT", tuning: "TS3", notes: "Longest track. Unique aero profile & braking. (Note: Meta shifted GT to TS3 recently)" },
            // Dirt
            { name: "Mudpit", car: "Colina Tanprice (Class B)", tuning: "DS3", notes: "Telemetry anomaly. Outpaces Class A here. (Meta often runs DS3)" },
            { name: "Hammerhead", car: "Edomondo NSX", tuning: "DS2", notes: "Treated as a Dirt track despite tarmac appearance." },
            { name: "Stone Park", car: "Echo R8", tuning: "DS3", notes: "Gravel corners require acceleration burst." },
            { name: "Two Islands", car: "Edomondo NSX", tuning: "DL2", notes: "Maintain momentum through dirt + long bridges." },
            { name: "Parkland", car: "Edomondo NSX", tuning: "DS3", notes: "Deep mud corners require short gears." }
        ],
        tuningLegend: {
            "T": "Tarmac: Hard Suspension, Track Tires",
            "D": "Dirt: Soft Suspension, Rally Tires",
            "S": "Short Ratio Transmission (Acceleration)",
            "L": "Long Ratio Transmission (Top Speed)",
            "2": "Turbo 2 combined with Stage 3 ECU Remap",
            "3": "Turbo 3 (No specific ECU required)"
        },
        hfParts: {
            base: ['Air Forced Engine Cooling','Air Cooling Ducts for Brakes','Adjustable Rear Spoiler','Front Diffuser','Rear Diffuser','Fast Road Brake Fluid','Braided Brake Hoses', 'Grooved and Drilled Brake Discs','Competition Racing Brake Pads','Brake Balance Bias Control','6 Pot Uprated Brakes','Ported and Polished Head','Competition Racing Fuel Pump', 'Competition Polished Throttle Body','Bored Out Engine + Forged Pistons','Front Mounted Intercooler','Stage Three Remap','Competition Racing Camshaft','Full Exhaust System', 'Stainless Steel 4-1 Manifold','Custom Forced Induction Kit','Super Octane Fuel Plus Nitrous','Polyurethane Bushings Front','Polyurethane Bushings Rear','Upper Front Strut Brace', 'Lower Front Strut Brace','Rear Strut Brace','Front Adjustable Tie Rods','Adjustable Rear Control arms','Quick Shift','4 Pin Differential','Competition Racing Clutch','Ultra-Light Flywheel', 'Strip Out','Racing Steering Wheel','Lightweight Flocked Dash','Polycarbonate Windows','Carbon Fiber Roof','Carbon Fiber Trunk','Carbon Fiber Hood','Ultra-Lightweight Alloys'],
            dirtShort: ['Group N Rally Suspension','Rally Gearbox (Short Ratio)','Rally Tires'],
            dirtLong: ['Group N Rally Suspension','Rally Gearbox (Long Ratio)','Rally Tires'],
            tarmacShort: ['Adjustable Coilover Suspension','Paddle Shift Gearbox (Short Ratio)','Track Tires'],
            tarmacLong: ['Adjustable Coilover Suspension','Paddle Shift Gearbox (Long Ratio)','Track Tires'],
            turbo2: ['Stage Two Turbo kit'],
            turbo3: ['Stage Three Turbo Kit']
        }
    };

    // ==========================================
    // STATE VARIABLES
    // ==========================================
    let isHighlighterActive = false;
    let detectedTrack = "";
    
    // Inline UI State memory (to persist across Torn DOM redraws)
    let currentInlineSurf = 'T';
    let currentInlineRatio = 'S';
    let currentInlineTurbo = '2';
    let currentChkGreen = true;
    let currentChkBlue = true;
    let currentChkRed = true;

    // Helper: Build the complete array of needed parts based on Tune ID
    function getRequiredParts(tuneId) {
        let parts = [...racingData.hfParts.base];
        
        if (tuneId.includes('D') && tuneId.includes('S')) parts.push(...racingData.hfParts.dirtShort);
        if (tuneId.includes('D') && tuneId.includes('L')) parts.push(...racingData.hfParts.dirtLong);
        if (tuneId.includes('T') && tuneId.includes('S')) parts.push(...racingData.hfParts.tarmacShort);
        if (tuneId.includes('T') && tuneId.includes('L')) parts.push(...racingData.hfParts.tarmacLong);
        
        if (tuneId.includes('2')) parts.push(...racingData.hfParts.turbo2);
        if (tuneId.includes('3')) parts.push(...racingData.hfParts.turbo3);
        
        return parts;
    }

    // ==========================================
    // UI STATE MANAGEMENT (LocalStorage)
    // ==========================================
    function getUIState() {
        try {
            const stored = localStorage.getItem('trg_ui_state');
            if (stored) {
                return JSON.parse(stored);
            }
        } catch(e) {
            debugLog("Failed to parse saved UI state.", e, true);
        }
        return { x: null, y: null, collapsed: false };
    }

    function saveUIState(container) {
        if (!container) return;
        const rect = container.getBoundingClientRect();
        const state = {
            x: rect.left,
            y: rect.top,
            collapsed: container.classList.contains('trg-collapsed')
        };
        localStorage.setItem('trg_ui_state', JSON.stringify(state));
    }

    // ==========================================
    // TEMPLATE MANAGEMENT (LocalStorage)
    // ==========================================
    function getCustomTemplates() {
        return JSON.parse(localStorage.getItem('trg_custom_templates')) || [];
    }

    function saveCustomTemplate(name, tune) {
        let templates = getCustomTemplates();
        const existingIndex = templates.findIndex(t => t.name.toLowerCase() === name.toLowerCase());
        
        if (existingIndex > -1) {
            templates[existingIndex].tune = tune;
        } else {
            templates.push({ name, tune });
        }
        
        localStorage.setItem('trg_custom_templates', JSON.stringify(templates));
        debugLog(`Saved template: ${name} with tune: ${tune}`);
    }

    function deleteCustomTemplate(name) {
        let templates = getCustomTemplates();
        templates = templates.filter(t => t.name !== name);
        localStorage.setItem('trg_custom_templates', JSON.stringify(templates));
        debugLog(`Deleted template: ${name}`);
    }

    function updateTemplateDropdown() {
        const select = document.getElementById('trg-inline-template-select');
        if (!select) return;

        const templates = getCustomTemplates();
        let html = `<option value="none">-- Select a Template --</option>`;
        templates.forEach(t => {
            html += `<option value="${t.tune}" data-name="${t.name}">${t.name} (${t.tune})</option>`;
        });
        select.innerHTML = html;
    }

    // ==========================================
    // INLINE SCANNER INJECTION
    // ==========================================
    function injectInlineScanner() {
        const partsContainer = document.querySelector('.info-msg-cont .msg.right-round');
        
        // Check if we are on the upgrades page AND if the scanner isn't already there
        if (partsContainer && !document.getElementById('trg-inline-scanner')) {
            debugLog("Upgrades menu detected. Injecting inline Auto-Scanner.");
            
            const upgradesList = partsContainer.querySelector('.tt-race-upgrades');
            
            const scannerDiv = document.createElement('div');
            scannerDiv.id = 'trg-inline-scanner';
            
            // Build the track dropdown HTML
            const trackOptions = racingData.tracks.map(t => `<option value="${t.tuning}">${t.name} (Meta: ${t.tuning})</option>`).join('');

            scannerDiv.innerHTML = `
                <div style="border: 1px solid #3a3a44; border-radius: 8px; background: #1a1a20; margin: 15px 0 15px 0; padding: 16px; color: #e0e0e0; text-align: left; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; box-shadow: 0 4px 12px rgba(0,0,0,0.2);">
                   <div style="font-weight: 600; font-size: 15px; color: #85b200; margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
                       <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
                       <span>TRG Auto-Scanner & Loadouts</span>
                   </div>
                   
                   <div style="display: flex; gap: 24px; flex-wrap: wrap;">
                       <!-- Column 1: Loaders -->
                       <div class="trg-inline-col" style="flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 12px;">
                           <div>
                               <div style="font-size: 12px; color: #999; margin-bottom: 4px; font-weight: 500;">Load Track Meta Tune (Applies to current car):</div>
                               <select id="trg-inline-track-select" class="trg-inline-select">
                                   <option value="custom">-- Select Track --</option>
                                   ${trackOptions}
                               </select>
                           </div>
                           <div>
                               <div style="font-size: 12px; color: #999; margin-bottom: 4px; font-weight: 500;">Load Custom Template:</div>
                               <div style="display: flex; gap: 6px;">
                                   <select id="trg-inline-template-select" class="trg-inline-select" style="flex:1;"></select>
                                   <button id="trg-inline-delete-template" class="trg-inline-btn trg-inline-btn-danger" title="Delete Selected">
                                       <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
                                   </button>
                               </div>
                           </div>
                           <div>
                               <div style="font-size: 12px; color: #999; margin-bottom: 4px; font-weight: 500;">Save Current Tune:</div>
                               <div style="display: flex; gap: 6px;">
                                   <input type="text" id="trg-inline-template-name" placeholder="E.g. Civic Mudpit..." class="trg-inline-input" style="flex: 1;">
                                   <button id="trg-inline-save-template" class="trg-inline-btn">Save</button>
                               </div>
                           </div>
                       </div>
                       
                       <!-- Column 2: Parameters -->
                       <div class="trg-inline-col" style="flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: 12px;">
                           <div style="font-size: 12px; color: #999; margin-bottom: -4px; font-weight: 500;">Tune Parameters:</div>
                           <div style="display: flex; gap: 8px;">
                               <button class="trg-inline-filter-btn ${currentInlineSurf === 'T' ? 'active' : ''}" data-group="surf" data-val="T">Tarmac</button>
                               <button class="trg-inline-filter-btn ${currentInlineSurf === 'D' ? 'active' : ''}" data-group="surf" data-val="D">Dirt</button>
                           </div>
                           <div style="display: flex; gap: 8px;">
                               <button class="trg-inline-filter-btn ${currentInlineRatio === 'S' ? 'active' : ''}" data-group="ratio" data-val="S">Short Ratio</button>
                               <button class="trg-inline-filter-btn ${currentInlineRatio === 'L' ? 'active' : ''}" data-group="ratio" data-val="L">Long Ratio</button>
                           </div>
                           <div style="display: flex; gap: 8px;">
                               <button class="trg-inline-filter-btn ${currentInlineTurbo === '2' ? 'active' : ''}" data-group="turbo" data-val="2">Turbo 2</button>
                               <button class="trg-inline-filter-btn ${currentInlineTurbo === '3' ? 'active' : ''}" data-group="turbo" data-val="3">Turbo 3</button>
                           </div>
                       </div>
                       
                       <!-- Column 3: Toggles & Activate -->
                       <div class="trg-inline-col" style="flex: 1; min-width: 200px; display: flex; flex-direction: column; justify-content: space-between;">
                           <div>
                               <div style="font-size: 12px; color: #999; margin-bottom: 8px; font-weight: 500;">Scanner Colors:</div>
                               <label class="trg-inline-chk-container">
                                   <input type="checkbox" id="trg-inline-chk-green" ${currentChkGreen ? 'checked' : ''}>
                                   <span class="trg-inline-chk-box" style="background:rgba(116,184,22,0.8); border-color:rgba(116,184,22,1);"></span> 
                                   <span>Required, Fitted</span>
                               </label>
                               <label class="trg-inline-chk-container">
                                   <input type="checkbox" id="trg-inline-chk-blue" ${currentChkBlue ? 'checked' : ''}>
                                   <span class="trg-inline-chk-box" style="background:rgba(20,113,151,0.8); border-color:rgba(20,113,151,1);"></span> 
                                   <span>Required, Missing</span>
                               </label>
                               <label class="trg-inline-chk-container" style="margin-bottom: 12px;">
                                   <input type="checkbox" id="trg-inline-chk-red" ${currentChkRed ? 'checked' : ''}>
                                   <span class="trg-inline-chk-box" style="background:rgba(247,103,7,0.8); border-color:rgba(247,103,7,1);"></span> 
                                   <span>Wrong Part (Trap)</span>
                               </label>
                           </div>
                            
                           <button id="trg-inline-toggle-btn" class="trg-inline-btn ${isHighlighterActive ? 'active' : ''}" style="width: 100%; padding: 10px; font-size: 14px;">
                               ${isHighlighterActive ? 'Scanner Active' : 'Enable Auto-Scanner'}
                           </button>
                       </div>
                   </div>
                </div>
            `;
            
            // Insert it before the paragraph listing points, or append if not found
            if (upgradesList) {
                partsContainer.insertBefore(scannerDiv, upgradesList);
            } else {
                partsContainer.appendChild(scannerDiv);
            }

            // Populate the custom templates dropdown
            updateTemplateDropdown();

            // Attach all event listeners to the new inline HTML
            attachInlineScannerEvents();
            
            // If scanner was left active prior to a DOM reload, reapply highlights
            if (isHighlighterActive) {
                setTimeout(applyHighlights, 100);
            }
        }
    }

    function attachInlineScannerEvents() {
        const filterBtns = document.querySelectorAll('.trg-inline-filter-btn');
        const trackSelect = document.getElementById('trg-inline-track-select');
        const templateSelect = document.getElementById('trg-inline-template-select');
        const saveBtn = document.getElementById('trg-inline-save-template');
        const deleteBtn = document.getElementById('trg-inline-delete-template');
        const toggleBtn = document.getElementById('trg-inline-toggle-btn');
        const nameInput = document.getElementById('trg-inline-template-name');
        
        const chkGreen = document.getElementById('trg-inline-chk-green');
        const chkBlue = document.getElementById('trg-inline-chk-blue');
        const chkRed = document.getElementById('trg-inline-chk-red');

        // Helper to update active buttons visually, in memory, and auto-enable the scanner
        function setFilterButtonsFromTune(tuneId) {
            currentInlineSurf = tuneId.charAt(0) || 'T';
            currentInlineRatio = tuneId.charAt(1) || 'S';
            currentInlineTurbo = tuneId.charAt(2) || '2';

            filterBtns.forEach(b => b.classList.remove('active'));
            document.querySelector(`.trg-inline-filter-btn[data-group="surf"][data-val="${currentInlineSurf}"]`)?.classList.add('active');
            document.querySelector(`.trg-inline-filter-btn[data-group="ratio"][data-val="${currentInlineRatio}"]`)?.classList.add('active');
            document.querySelector(`.trg-inline-filter-btn[data-group="turbo"][data-val="${currentInlineTurbo}"]`)?.classList.add('active');
            
            // Auto-activate the scanner whenever a preset or track is chosen
            if (!isHighlighterActive) {
                isHighlighterActive = true;
                if (toggleBtn) {
                    toggleBtn.classList.add('active');
                    toggleBtn.innerText = "Scanner Active";
                }
            }

            applyHighlights();
        }

        // Track Select (Loads Meta)
        trackSelect.addEventListener('change', (e) => {
            const tune = e.target.value;
            if (tune !== 'custom') {
                templateSelect.value = 'none'; // Reset template select
                setFilterButtonsFromTune(tune);
            }
        });

        // Template Select (Loads Custom)
        templateSelect.addEventListener('change', (e) => {
            const tune = e.target.value;
            if (tune !== 'none') {
                trackSelect.value = 'custom'; // Reset track select
                setFilterButtonsFromTune(tune);
            }
        });

        // Filter Buttons (Manual Override)
        filterBtns.forEach(btn => {
            btn.addEventListener('click', (e) => {
                const group = e.target.getAttribute('data-group');
                const val = e.target.getAttribute('data-val');
                
                // Update memory
                if (group === 'surf') currentInlineSurf = val;
                if (group === 'ratio') currentInlineRatio = val;
                if (group === 'turbo') currentInlineTurbo = val;

                // Update UI
                document.querySelectorAll(`.trg-inline-filter-btn[data-group="${group}"]`).forEach(b => b.classList.remove('active'));
                e.target.classList.add('active');
                
                // Reset selects since we are manually editing
                trackSelect.value = 'custom';
                templateSelect.value = 'none';

                if (isHighlighterActive) applyHighlights();
            });
        });

        // Checkboxes
        [chkGreen, chkBlue, chkRed].forEach(chk => {
            chk.addEventListener('change', () => {
                currentChkGreen = chkGreen.checked;
                currentChkBlue = chkBlue.checked;
                currentChkRed = chkRed.checked;
                if (isHighlighterActive) applyHighlights();
            });
        });

        // Save Template
        saveBtn.addEventListener('click', () => {
            const name = nameInput.value.trim();
            if (!name) {
                alert("Please enter a name for your template.");
                return;
            }
            const currentTune = currentInlineSurf + currentInlineRatio + currentInlineTurbo;
            saveCustomTemplate(name, currentTune);
            updateTemplateDropdown();
            
            // Auto-select the newly saved template
            const opts = Array.from(templateSelect.options);
            const newOpt = opts.find(o => o.getAttribute('data-name') === name);
            if (newOpt) templateSelect.value = newOpt.value;
            
            nameInput.value = ""; // clear input
        });

        // Delete Template
        deleteBtn.addEventListener('click', () => {
            const selectedOption = templateSelect.options[templateSelect.selectedIndex];
            if (selectedOption.value === 'none') return;
            
            const name = selectedOption.getAttribute('data-name');
            if (confirm(`Delete custom template: ${name}?`)) {
                deleteCustomTemplate(name);
                updateTemplateDropdown();
            }
        });

        // Toggle Scanner
        toggleBtn.addEventListener('click', () => {
            isHighlighterActive = !isHighlighterActive;
            if (isHighlighterActive) {
                toggleBtn.classList.add('active');
                toggleBtn.innerText = "Scanner Active";
                applyHighlights(); 
            } else {
                toggleBtn.classList.remove('active');
                toggleBtn.innerText = "Enable Auto-Scanner";
                removeHighlights(); 
            }
        });
    }

    // ==========================================
    // MOVABLE UI INJECTION & STYLING
    // ==========================================
    function injectStyles() {
        debugLog("Attempting to inject CSS styles.");
        try {
            GM_addStyle(`
                /* Global Custom Scrollbar for Script UI */
                #trg-container ::-webkit-scrollbar {
                    width: 6px;
                }
                #trg-container ::-webkit-scrollbar-track {
                    background: transparent;
                }
                #trg-container ::-webkit-scrollbar-thumb {
                    background: #444;
                    border-radius: 3px;
                }
                #trg-container ::-webkit-scrollbar-thumb:hover {
                    background: #666;
                }

                /* Movable UI Container (Responsive) */
                #trg-container {
                    position: fixed;
                    top: 100px;
                    right: 20px;
                    width: 90vw !important;
                    max-width: 440px !important;
                    background-color: #1a1a20 !important;
                    color: #e0e0e0 !important;
                    border: 1px solid #333 !important;
                    border-radius: 12px !important;
                    font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif !important;
                    font-size: 13px !important;
                    z-index: 999999 !important;
                    box-shadow: 0 8px 24px rgba(0,0,0,0.5) !important;
                    display: flex;
                    flex-direction: column;
                    max-height: 85vh;
                    transition: opacity 0.2s ease;
                }
                #trg-container.trg-collapsed { 
                    width: max-content !important; 
                }
                #trg-container * { box-sizing: border-box !important; color: inherit; }
                
                /* Header */
                #trg-header {
                    background-color: #24242c !important;
                    padding: 12px 16px !important;
                    border-radius: 12px 12px 0 0 !important;
                    font-weight: 600 !important;
                    display: flex !important;
                    justify-content: space-between !important;
                    align-items: center !important;
                    gap: 16px !important;
                    cursor: move !important;
                    border-bottom: 1px solid #333 !important;
                    user-select: none !important;
                    white-space: nowrap !important;
                    font-size: 14px !important;
                    touch-action: none; /* Prevents scroll while dragging on mobile */
                }
                #trg-toggle-btn { 
                    background: none !important; 
                    border: none !important; 
                    color: #888 !important; 
                    cursor: pointer !important; 
                    font-size: 14px !important; 
                    transition: color 0.2s;
                }
                #trg-toggle-btn:hover { color: #fff !important; }
                
                /* Content Area & Tabs */
                #trg-content { display: flex; flex-direction: column; overflow: hidden; }
                .trg-tabs { 
                    display: flex !important; 
                    background: transparent !important; 
                    border-bottom: 1px solid #333 !important; 
                }
                .trg-tab {
                    flex: 1 !important; 
                    padding: 10px 4px !important; 
                    text-align: center !important; 
                    cursor: pointer !important;
                    background: transparent !important; 
                    border: none !important; 
                    border-bottom: 2px solid transparent !important;
                    color: #888 !important;
                    font-weight: 600 !important; 
                    user-select: none !important; 
                    font-size: 12px !important;
                    transition: color 0.2s, border-color 0.2s;
                }
                .trg-tab:hover { color: #ccc !important; }
                .trg-tab.active { 
                    color: #fff !important; 
                    border-bottom: 2px solid #85b200 !important; 
                }
                
                /* Panels */
                .trg-panel { 
                    display: none; 
                    padding: 16px !important; 
                    overflow-y: auto !important; 
                    max-height: 55vh !important; 
                }
                .trg-panel.active { display: block; }
                
                /* Lists & Tables styling (Card based) */
                .trg-grid-header { 
                    display: grid !important; 
                    grid-template-columns: 2fr 2fr 1fr !important; 
                    font-weight: 600 !important; 
                    background-color: #24242c !important; 
                    padding: 8px 12px !important; 
                    border-radius: 6px !important;
                    margin-bottom: 8px !important;
                    color: #aaa !important;
                    font-size: 12px !important;
                    position: sticky !important; 
                    top: 0 !important; 
                    z-index: 2 !important;
                }
                .trg-grid-row { 
                    display: grid !important; 
                    grid-template-columns: 2fr 2fr 1fr !important; 
                    padding: 10px 12px !important; 
                    background-color: #2a2a32 !important;
                    border: 1px solid #333 !important;
                    border-radius: 6px !important;
                    margin-bottom: 6px !important; 
                    align-items: center !important; 
                    transition: background-color 0.2s, border-color 0.2s;
                }
                .trg-grid-row:hover { background-color: #303038 !important; border-color: #444 !important; }
                .trg-track-detected { 
                    background-color: rgba(133, 178, 0, 0.1) !important; 
                    border-color: rgba(133, 178, 0, 0.4) !important;
                    border-left: 4px solid #85b200 !important; 
                }
                .trg-grid-notes { 
                    grid-column: 1 / -1 !important; 
                    font-size: 11px !important; 
                    color: #888 !important; 
                    padding-top: 6px !important; 
                    margin-top: 4px !important;
                    border-top: 1px dashed #3a3a44 !important;
                }
                
                /* Typography & Utilities */
                .trg-highlight { color: #85b200 !important; font-weight: 600 !important; }
                .trg-collapsed #trg-content { display: none !important; }
                .trg-list { margin: 8px 0 16px 0 !important; padding-left: 20px !important; }
                .trg-list li { margin-bottom: 6px !important; color: #bbb !important; }
                
                /* Footer / Credits */
                .trg-footer-info { 
                    font-size: 11px !important; 
                    color: #888 !important; 
                    text-align: center !important; 
                    padding: 10px !important; 
                    background-color: #1a1a20 !important; 
                    border-top: 1px solid #333 !important; 
                    border-radius: 0 0 12px 12px !important;
                }
                .trg-footer-info a { color: #85b200 !important; text-decoration: none !important; font-weight: 600 !important; transition: color 0.2s; }
                .trg-footer-info a:hover { color: #9dd300 !important; text-decoration: underline !important; }

                /* ========================================== */
                /* Inline Scanner Specific Styles             */
                /* ========================================== */
                .trg-inline-btn { 
                    background: #2a2a32; 
                    color: #ccc; 
                    border: 1px solid #3d3d47; 
                    padding: 6px 12px; 
                    border-radius: 6px; 
                    cursor: pointer; 
                    font-weight: 600; 
                    transition: all 0.2s ease; 
                    font-size: 12px; 
                    display: inline-flex;
                    align-items: center;
                    justify-content: center;
                }
                .trg-inline-btn:hover { background: #363640; color: #fff; }
                .trg-inline-btn.active { 
                    background: rgba(133, 178, 0, 0.15); 
                    border-color: #85b200; 
                    color: #85b200; 
                }
                .trg-inline-btn-danger {
                    background: rgba(220, 53, 69, 0.1);
                    border-color: rgba(220, 53, 69, 0.3);
                    color: #dc3545;
                }
                .trg-inline-btn-danger:hover {
                    background: #dc3545;
                    border-color: #dc3545;
                    color: #fff;
                }
                .trg-inline-input, .trg-inline-select { 
                    background: #24242c; 
                    color: #eee; 
                    border: 1px solid #3d3d47; 
                    padding: 6px 8px; 
                    border-radius: 6px; 
                    font-size: 13px; 
                    outline: none;
                    transition: border-color 0.2s;
                }
                .trg-inline-select { width: 100%; cursor: pointer; }
                .trg-inline-input:focus, .trg-inline-select:focus { border-color: #85b200; }
                
                .trg-inline-filter-btn { 
                    background: #24242c; 
                    color: #888; 
                    border: 1px solid #3d3d47; 
                    padding: 6px 10px; 
                    border-radius: 6px; 
                    cursor: pointer; 
                    font-size: 12px; 
                    flex: 1; 
                    transition: all 0.2s ease; 
                    font-weight: 500;
                }
                .trg-inline-filter-btn:hover { background: #2a2a32; color: #ccc; }
                .trg-inline-filter-btn.active { 
                    background: rgba(133, 178, 0, 0.15); 
                    color: #85b200; 
                    border-color: #85b200; 
                    font-weight: 600; 
                }
                
                .trg-inline-chk-container {
                    display: flex; 
                    align-items: center; 
                    gap: 8px; 
                    font-size: 13px; 
                    margin-bottom: 8px; 
                    cursor: pointer;
                    color: #ccc;
                    transition: color 0.2s;
                }
                .trg-inline-chk-container:hover { color: #fff; }
                .trg-inline-chk-container input { display: none; }
                .trg-inline-chk-box {
                    display: inline-block;
                    width: 14px;
                    height: 14px;
                    border-radius: 3px;
                    border: 1px solid transparent;
                    position: relative;
                }
                .trg-inline-chk-container input:not(:checked) + .trg-inline-chk-box {
                    background: transparent !important;
                    border-color: #555 !important;
                }
                .trg-inline-chk-container input:checked + .trg-inline-chk-box::after {
                    content: '';
                    position: absolute;
                    left: 4px;
                    top: 1px;
                    width: 4px;
                    height: 8px;
                    border: solid #fff;
                    border-width: 0 2px 2px 0;
                    transform: rotate(45deg);
                }

                /* ========================================== */
                /* Mobile & Small Screen Media Queries        */
                /* ========================================== */
                @media (max-width: 600px) {
                    .trg-inline-col {
                        min-width: 100% !important;
                        flex: 1 1 100% !important;
                    }
                    .trg-grid-header, .trg-grid-row {
                        grid-template-columns: 1fr 1fr 1fr !important;
                        font-size: 11px !important;
                        padding: 8px !important;
                    }
                    .trg-tab {
                        font-size: 11px !important;
                        padding: 10px 2px !important;
                    }
                    #trg-container {
                        right: 5vw !important;
                        top: auto !important;
                        bottom: 20px !important;
                    }
                }
            `);
            debugLog("CSS styles injected successfully.");
        } catch (error) {
            debugLog("Failed to inject CSS styles.", error, true);
        }
    }

    function buildUI() {
        debugLog("Attempting to build UI elements.");
        try {
            const container = document.createElement('div');
            container.id = 'trg-container';
            
            // Apply saved state before appending to DOM
            const uiState = getUIState();
            if (uiState.collapsed) {
                container.classList.add('trg-collapsed');
            }
            
            // Header
            const header = document.createElement('div');
            header.id = 'trg-header';
            header.innerHTML = `<span>🏎️ Torn Racing Guide <span class="trg-meta-text" style="font-size: 11px; color: #888; margin-left: 5px;">by GNS-C4</span></span><button id="trg-toggle-btn">${uiState.collapsed ? '▲' : '▼'}</button>`;
            container.appendChild(header);

            // Content Area
            const content = document.createElement('div');
            content.id = 'trg-content';

            // Tabs
            const tabsDiv = document.createElement('div');
            tabsDiv.className = 'trg-tabs';
            tabsDiv.innerHTML = `
                <div class="trg-tab active" data-target="panel-tracks">Tracks</div>
                <div class="trg-tab" data-target="panel-progression">Class Path</div>
                <div class="trg-tab" data-target="panel-tuning">Legend</div>
                <div class="trg-tab" data-target="panel-credits">Credits</div>
            `;
            content.appendChild(tabsDiv);

            // Panel 1: Tracks
            const pTracks = document.createElement('div');
            pTracks.id = 'panel-tracks';
            pTracks.className = 'trg-panel active';
            
            let trackHtml = `<div id="trg-detected-track-alert" style="display:none; color: #85b200; font-size: 13px; font-weight: 500; margin-bottom: 12px; text-align: center; background: rgba(133,178,0,0.1); border: 1px solid rgba(133,178,0,0.3); border-radius: 6px; padding: 10px;"></div>`;
            trackHtml += `<div class="trg-grid-header"><div>Track</div><div>Optimal Car</div><div>Tune</div></div>`;
            racingData.tracks.forEach(t => {
                const safeName = t.name.replace(/\s+/g, '-').toLowerCase();
                trackHtml += `
                    <div class="trg-grid-row" id="trg-track-row-${safeName}">
                        <div style="font-weight: 500; color: #ddd;">${t.name}</div>
                        <div class="trg-highlight">${t.car}</div>
                        <div><span style="background: #333; padding: 2px 6px; border-radius: 4px; font-size: 11px;">${t.tuning}</span></div>
                        <div class="trg-grid-notes">${t.notes}</div>
                    </div>
                `;
            });
            pTracks.innerHTML = trackHtml;
            content.appendChild(pTracks);

            // Panel 2: Progression
            const pProgression = document.createElement('div');
            pProgression.id = 'panel-progression';
            pProgression.className = 'trg-panel';
            let progRows = racingData.progression.map(p => `
                <div style="margin-bottom: 12px; background: #2a2a32; border: 1px solid #333; border-radius: 6px; padding: 12px;">
                    <div style="font-size: 14px;"><strong class="trg-highlight">Class ${p.class}</strong> &mdash; ${p.car}</div>
                    <div style="color: #999; font-size: 12px; margin-top: 4px; border-bottom: 1px dashed #3a3a44; padding-bottom: 6px;"><strong>Cost:</strong> ${p.cost}</div>
                    <div style="font-size: 13px; color: #ccc; margin-top: 8px; line-height: 1.5;">${p.strat}</div>
                </div>
            `).join('');
            pProgression.innerHTML = progRows;
            content.appendChild(pProgression);

            // Panel 3: Parts Legend
            const pTuning = document.createElement('div');
            pTuning.id = 'panel-tuning';
            pTuning.className = 'trg-panel';
            
            let tuneHtml = `
                <div style="background: #2a2a32; border: 1px solid #333; border-radius: 6px; padding: 12px; margin-bottom: 12px;">
                    <div style="font-size: 14px; color: #85b200; font-weight: 600; margin-bottom: 10px;">Tuning Shorthand</div>
                    <div style="display: grid; grid-template-columns: 1fr 5fr; gap: 8px; align-items: center;">
            `;
            for (const [code, desc] of Object.entries(racingData.tuningLegend)) {
                tuneHtml += `
                    <div style="text-align:center; font-weight:bold; font-size:13px; background:#3a3a44; color:#eee; border-radius:4px; padding:4px;">${code}</div>
                    <div style="font-size: 13px; color: #ccc;">${desc}</div>
                `;
            }
            tuneHtml += `</div></div>`;
            pTuning.innerHTML = tuneHtml;
            content.appendChild(pTuning);

            // Panel 4: Credits
            const pCredits = document.createElement('div');
            pCredits.id = 'panel-credits';
            pCredits.className = 'trg-panel';
            let creditsHtml = `
                <div style="line-height: 1.6; background: #2a2a32; border: 1px solid #333; border-radius: 6px; padding: 16px;">
                    <div style="font-size: 15px; color: #85b200; font-weight: 600; margin-bottom: 8px; border-bottom: 1px dashed #444; padding-bottom: 8px;">Credits & Sources</div>
                    <ul class="trg-list" style="margin-top: 12px !important;">
                        <li><strong style="color: #eee;">Heartflower [2626587]</strong>: Original "Racing: Car Templates" concept. UI scanner flow and core array filtering frameworks were adapted from their tool.</li>
                        <li><strong style="color: #eee;">Grando [2833733]</strong>: Author of the definitive racing meta analysis utilized for track builds and class progression data.</li>
                        <li><strong style="color: #eee;">Torn Wiki / Reddit</strong>: Historical telemetry data and mechanics documentation.</li>
                        <li><strong style="color: #eee;">GNS-C4 [3960752]</strong>: Developer and compiler of this modernized hybrid overlay.</li>
                    </ul>
                </div>
            `;
            pCredits.innerHTML = creditsHtml;
            content.appendChild(pCredits);

            // Version and Author Footer
            const footerInfo = document.createElement('div');
            footerInfo.className = 'trg-footer-info';
            footerInfo.innerHTML = `v1.1.6 | Developed by <a href="https://www.torn.com/profiles.php?XID=3960752" target="_blank">GNS-C4 [3960752]</a>`;
            content.appendChild(footerInfo);
            
            container.appendChild(content); // Ensure content gets appended!

            if (!document.body) {
                throw new Error("document.body is null or undefined.");
            }
            
            // Apply Position State
            if (uiState.x !== null && uiState.y !== null) {
                // Keep it within viewport bounds in case window resized
                let safeX = Math.max(0, Math.min(uiState.x, window.innerWidth - 100));
                let safeY = Math.max(0, Math.min(uiState.y, window.innerHeight - 50));
                
                container.style.left = safeX + 'px';
                container.style.top = safeY + 'px';
                container.style.right = 'auto'; // override CSS default
                container.style.bottom = 'auto'; // override CSS default
            }
            
            document.body.appendChild(container);
            debugLog("Movable UI appended to document.body successfully.");

            // ==========================================
            // EVENT LISTENERS & DRAG LOGIC (MOUSE + TOUCH)
            // ==========================================
            try {
                // Collapse Toggle
                document.getElementById('trg-toggle-btn').addEventListener('click', () => {
                    container.classList.toggle('trg-collapsed');
                    document.getElementById('trg-toggle-btn').innerText = container.classList.contains('trg-collapsed') ? '▲' : '▼';
                    saveUIState(container);
                });

                // Tab Switching
                const tabs = document.querySelectorAll('.trg-tab');
                const panels = document.querySelectorAll('.trg-panel');

                tabs.forEach(tab => {
                    tab.addEventListener('click', (e) => {
                        const target = e.target.getAttribute('data-target');
                        
                        tabs.forEach(t => t.classList.remove('active'));
                        panels.forEach(p => p.classList.remove('active'));
                        
                        e.target.classList.add('active');
                        document.getElementById(target).classList.add('active');
                    });
                });
                
                // Drag Logic variables
                let isDragging = false;
                let dragOffsetX = 0;
                let dragOffsetY = 0;

                // Shared Drag Start
                const handleDragStart = (e) => {
                    if (e.target.id === 'trg-toggle-btn') return;
                    isDragging = true;
                    
                    const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
                    const clientY = e.type.includes('touch') ? e.touches[0].clientY : e.clientY;
                    
                    const rect = container.getBoundingClientRect();
                    dragOffsetX = clientX - rect.left;
                    dragOffsetY = clientY - rect.top;
                    
                    container.style.left = rect.left + 'px';
                    container.style.top = rect.top + 'px';
                    container.style.right = 'auto';
                    container.style.bottom = 'auto';
                    container.style.opacity = '0.9'; // Slight transparency while dragging
                };

                // Shared Drag Move
                const handleDragMove = (e) => {
                    if (!isDragging) return;
                    e.preventDefault(); // crucial to prevent page scrolling on mobile while dragging
                    
                    const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
                    const clientY = e.type.includes('touch') ? e.touches[0].clientY : e.clientY;
                    
                    let newLeft = clientX - dragOffsetX;
                    let newTop = clientY - dragOffsetY;
                    
                    newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - container.offsetWidth));
                    newTop = Math.max(0, Math.min(newTop, window.innerHeight - container.offsetHeight));

                    container.style.left = newLeft + 'px';
                    container.style.top = newTop + 'px';
                };

                // Shared Drag End
                const handleDragEnd = () => {
                    if (isDragging) {
                        isDragging = false;
                        container.style.opacity = '1';
                        saveUIState(container);
                    }
                };

                // Mouse Listeners
                header.addEventListener('mousedown', handleDragStart);
                document.addEventListener('mousemove', handleDragMove);
                document.addEventListener('mouseup', handleDragEnd);

                // Touch Listeners (Mobile support)
                header.addEventListener('touchstart', handleDragStart, { passive: false });
                document.addEventListener('touchmove', handleDragMove, { passive: false });
                document.addEventListener('touchend', handleDragEnd);

                debugLog("Movable UI Event listeners attached successfully.");
            } catch (eventError) {
                debugLog("Failed while attaching event listeners.", eventError, true);
            }

        } catch (error) {
            debugLog("Failed to build Movable UI.", error, true);
        }
    }

    // ==========================================
    // AUTO-SCANNER HIGHLIGHTING LOGIC
    // ==========================================
    function applyHighlights() {
        if (!isHighlighterActive) {
            removeHighlights();
            return;
        }
        
        const tuneId = currentInlineSurf + currentInlineRatio + currentInlineTurbo;
        const requiredPartsArray = getRequiredParts(tuneId);

        const pmItemsWraps = document.querySelectorAll('.pm-items-wrap');
        if (!pmItemsWraps || pmItemsWraps.length === 0) return;

        pmItemsWraps.forEach(wrap => {
            const titles = wrap.querySelectorAll('.title.t-overflow');
            titles.forEach(titleElement => {
                const partName = titleElement.textContent.trim();
                
                // Navigate DOM to find the wrapper box
                const bgWrap = titleElement.closest('.bg-wrap');
                const boxWrap = titleElement.closest('.box-wrap');
                const targetWrap = bgWrap || (boxWrap ? boxWrap.parentElement : null);
                
                if (!targetWrap) return;

                // Check if the part is already installed on the car
                const infoDiv = targetWrap.querySelector('.info');
                const isFitted = infoDiv && infoDiv.textContent.trim() === 'Upgrade is already fitted to this car';

                // Apply Colors conditionally based on active memory filters
                if (requiredPartsArray.includes(partName)) {
                    if (isFitted) {
                        targetWrap.style.background = currentChkGreen ? 'rgba(116,184,22,0.15)' : ''; // Green - Good
                    } else {
                        targetWrap.style.background = currentChkBlue ? 'rgba(20, 113, 151, 0.25)' : ''; // Blue - Missing
                    }
                } else {
                    if (isFitted) {
                        targetWrap.style.background = currentChkRed ? 'rgba(247,103,7,0.15)' : ''; // Red - Trap/Wrong
                    } else {
                        targetWrap.style.background = ''; // Clear - Ignored part
                    }
                }
            });
        });
    }

    function removeHighlights() {
        const pmItemsWraps = document.querySelectorAll('.pm-items-wrap');
        if (!pmItemsWraps) return;

        pmItemsWraps.forEach(wrap => {
            const titles = wrap.querySelectorAll('.title.t-overflow');
            titles.forEach(titleElement => {
                const bgWrap = titleElement.closest('.bg-wrap');
                const boxWrap = titleElement.closest('.box-wrap');
                const targetWrap = bgWrap || (boxWrap ? boxWrap.parentElement : null);
                
                if (targetWrap) {
                    targetWrap.style.background = ''; 
                }
            });
        });
    }

    // ==========================================
    // TRACK AUTO-DETECTION LOGIC
    // ==========================================
    function detectTrackFromPage() {
        let newDetectedTrack = "";

        // Scenario 1: Joining an official race
        const enlistWrap = document.querySelector('.enlist-wrap');
        if (enlistWrap) {
            const trackElement = document.querySelector('.enlisted-btn-wrap');
            if (trackElement && trackElement.textContent) {
                newDetectedTrack = trackElement.textContent.split(' - Official race')[0].trim();
            }
        }

        // Scenario 2: Creating a custom race (Dropdown)
        const selectMenu = document.querySelector('.ui-selectmenu');
        if (selectMenu && selectMenu.textContent) {
            newDetectedTrack = selectMenu.textContent.trim();
        }

        // Scenario 3: Custom race lobby list (Active row)
        const successRow = document.querySelector('.active-row');
        if (successRow) {
            const trackElement = successRow.querySelector('.track');
            if (trackElement && trackElement.textContent) {
                let trackText = trackElement.textContent.trim();
                newDetectedTrack = trackText.split('(')[0].trim();
                const raceName = trackElement.querySelector('.hf-race-name');
                if (raceName) {
                    newDetectedTrack = newDetectedTrack.replace(raceName.textContent, '').trim();
                }
            }
        }

        if (newDetectedTrack !== "" && newDetectedTrack !== detectedTrack && newDetectedTrack !== "ENLIST ANOTHER CAR") {
            detectedTrack = newDetectedTrack;
            highlightTrackInUI(detectedTrack);
        }
    }

    function highlightTrackInUI(trackName) {
        document.querySelectorAll('.trg-grid-row').forEach(row => {
            row.classList.remove('trg-track-detected');
        });

        const alertDiv = document.getElementById('trg-detected-track-alert');
        const matchedTrack = racingData.tracks.find(t => trackName.includes(t.name));
        
        if (matchedTrack) {
            const safeName = matchedTrack.name.replace(/\s+/g, '-').toLowerCase();
            const rowEl = document.getElementById(`trg-track-row-${safeName}`);
            
            if (rowEl) {
                rowEl.classList.add('trg-track-detected');
                if (alertDiv) {
                    alertDiv.style.display = "block";
                    alertDiv.innerHTML = `📍 Detected race on: <strong style="color:#fff;">${matchedTrack.name}</strong> &mdash; Optimal Build: <strong style="color:#fff;">${matchedTrack.car} (${matchedTrack.tuning})</strong>`;
                }
                
                // Auto-update the inline scanner dropdown if it is present on the page and differs
                const trackSelect = document.getElementById('trg-inline-track-select');
                if (trackSelect && trackSelect.value !== matchedTrack.tuning) {
                    // Update value and dispatch change event to auto-load filters & auto-enable scanner
                    trackSelect.value = matchedTrack.tuning;
                    trackSelect.dispatchEvent(new Event('change'));
                }
            }
        } else {
            if (alertDiv) alertDiv.style.display = "none";
        }
    }

    // ==========================================
    // INITIALIZATION & POLLING
    // ==========================================
    function init() {
        debugLog("init() function called.");
        try {
            if (document.getElementById('trg-container')) {
                debugLog("Script already injected. Aborting secondary injection.");
                return;
            }
            injectStyles();
            buildUI();
            
            // Set up polling for dynamic Torn DOM changes (Parts Menu & Track Lobby)
            setInterval(() => {
                injectInlineScanner();
                detectTrackFromPage();
                
                // Reapply highlights continuously if active (covers AJAX part buys/changes)
                if (isHighlighterActive) {
                    applyHighlights();
                }
            }, 500);
            
            debugLog("Initialization sequence complete.");
        } catch (error) {
            debugLog("Critical error during initialization.", error, true);
        }
    }

    function checkBodyAndInit() {
        if (document.body) {
            init();
        } else {
            setTimeout(checkBodyAndInit, 500);
        }
    }

    // Wait for basic DOM to load, then run
    try {
        if (document.readyState === "complete" || document.readyState === "interactive") {
            checkBodyAndInit();
        } else {
            document.addEventListener("DOMContentLoaded", checkBodyAndInit);
        }
    } catch (error) {
        debugLog("Failed to attach load events.", error, true);
    }

})();