Sniffies Integrated Location Spoofer

Integrate location spoofing with Sniffies' existing Travel Mode button using natural language inputs. Disable native Travel Mode and provide a custom spoofing popup with reset functionality in dark mode, including customizable quick location presets and an integrated spoofing indicator that shows real location when spoofing is deactivated.

// ==UserScript==
// @name         Sniffies Integrated Location Spoofer
// @namespace    https://sniffies.com/
// @version      3.6
// @description  Integrate location spoofing with Sniffies' existing Travel Mode button using natural language inputs. Disable native Travel Mode and provide a custom spoofing popup with reset functionality in dark mode, including customizable quick location presets and an integrated spoofing indicator that shows real location when spoofing is deactivated.
// @author       Your Name
// @match        https://sniffies.com/*
// @grant        none
// @license      MIT
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    // Constants
    const STORAGE_KEY = 'sniffiesLocationSpoofer';
    const PRESETS_KEY = 'sniffiesLocationPresets';
    const GEOCODING_API_URL = 'https://nominatim.openstreetmap.org/search';
    const REVERSE_GEOCODING_API_URL = 'https://nominatim.openstreetmap.org/reverse';
    const MODAL_ID = 'spoofModalOverlay';
    const TRAVEL_MODE_ICON_SELECTOR = 'i[data-testid="travelModeIcon"]';
    const INDICATOR_ID = 'locationSpoofingIndicator'; // New ID for the indicator

    // Default Preset Locations
    const DEFAULT_PRESET_LOCATIONS = [
        { name: 'New York, USA', latitude: 40.7128, longitude: -74.0060 },
        { name: 'London, UK', latitude: 51.5074, longitude: -0.1278 },
        { name: 'Tokyo, Japan', latitude: 35.6762, longitude: 139.6503 },
        { name: 'Sydney, Australia', latitude: -33.8688, longitude: 151.2093 },
        { name: 'Paris, France', latitude: 48.8566, longitude: 2.3522 },
        { name: 'Berlin, Germany', latitude: 52.5200, longitude: 13.4050 },
    ];

    // Default Location Data
    const DEFAULT_LOCATION = {
        enabled: false,
        locationName: '',
        latitude: null,
        longitude: null,
    };

    // Global variables
    let activeWatchId = null;
    let originalTravelModeButton = null;
    let originalTravelModeIconClasses = [];
    let isUserscriptDisabled = false;

    /**
     * Retrieves stored location data from localStorage.
     * @returns {Object} Stored location data or default if none exists.
     */
    function getStoredLocation() {
        try {
            const data = localStorage.getItem(STORAGE_KEY);
            return data ? JSON.parse(data) : { ...DEFAULT_LOCATION };
        } catch (error) {
            console.error('Error retrieving stored location:', error);
            return { ...DEFAULT_LOCATION };
        }
    }

    /**
     * Saves location data to localStorage.
     * @param {Object} locationData - The location data to store.
     */
    function setStoredLocation(locationData) {
        try {
            localStorage.setItem(STORAGE_KEY, JSON.stringify(locationData));
        } catch (error) {
            console.error('Error setting stored location:', error);
        }
    }

    /**
     * Clears stored location data from localStorage.
     */
    function clearStoredLocation() {
        try {
            localStorage.removeItem(STORAGE_KEY);
        } catch (error) {
            console.error('Error clearing stored location:', error);
        }
    }

    /**
     * Retrieves preset locations from localStorage.
     * @returns {Array} Array of preset location objects.
     */
    function getPresetLocations() {
        try {
            const data = localStorage.getItem(PRESETS_KEY);
            return data ? JSON.parse(data) : [...DEFAULT_PRESET_LOCATIONS];
        } catch (error) {
            console.error('Error retrieving preset locations:', error);
            return [...DEFAULT_PRESET_LOCATIONS];
        }
    }

    /**
     * Saves preset locations to localStorage.
     * @param {Array} presets - Array of preset location objects.
     */
    function setPresetLocations(presets) {
        try {
            localStorage.setItem(PRESETS_KEY, JSON.stringify(presets));
        } catch (error) {
            console.error('Error setting preset locations:', error);
        }
    }

    /**
     * Geocodes a location name to latitude and longitude using Nominatim.
     * @param {string} locationName - The location name to geocode.
     * @returns {Promise<Object>} A promise that resolves to an object containing latitude and longitude.
     */
    async function geocodeLocation(locationName) {
        const params = new URLSearchParams({
            q: locationName,
            format: 'json',
            limit: 1,
        });

        try {
            const response = await fetch(`${GEOCODING_API_URL}?${params.toString()}`, {
                headers: {
                    'User-Agent': 'SniffiesLocationSpoofer/1.0 (+https://yourwebsite.com/)',
                },
            });
            if (!response.ok) {
                throw new Error(`Geocoding API error: ${response.statusText}`);
            }
            const data = await response.json();
            if (data.length === 0) {
                throw new Error('Location not found. Please try a different query.');
            }

            return {
                latitude: parseFloat(data[0].lat),
                longitude: parseFloat(data[0].lon),
            };
        } catch (error) {
            console.error(`Failed to geocode location: ${error.message}`);
            throw new Error('Failed to fetch location. Please try again later.');
        }
    }

    /**
     * Reverse geocodes latitude and longitude to a human-readable location name using Nominatim.
     * @param {number} latitude - The latitude to reverse geocode.
     * @param {number} longitude - The longitude to reverse geocode.
     * @returns {Promise<string>} A promise that resolves to the location name.
     */
    async function reverseGeocodeLocation(latitude, longitude) {
        const params = new URLSearchParams({
            lat: latitude,
            lon: longitude,
            format: 'json',
        });

        try {
            const response = await fetch(`${REVERSE_GEOCODING_API_URL}?${params.toString()}`, {
                headers: {
                    'User-Agent': 'SniffiesLocationSpoofer/1.0 (+https://yourwebsite.com/)',
                },
            });
            if (!response.ok) {
                throw new Error(`Reverse geocoding API error: ${response.statusText}`);
            }
            const data = await response.json();
            return data.display_name || 'Unknown Location';
        } catch (error) {
            console.error(`Failed to reverse geocode location: ${error.message}`);
            return 'Unknown Location';
        }
    }

    /**
     * Overrides the navigator.geolocation object with spoofed coordinates.
     * @param {Object} spoofedLocation - The spoofed latitude and longitude.
     */
    function overrideGeolocation(spoofedLocation) {
        // Store the original navigator.geolocation if not already stored
        if (!window.__originalGeolocation) {
            window.__originalGeolocation = navigator.geolocation;
        }

        const spoofedGeolocation = {
            getCurrentPosition: function (success, error, options) {
                if (!spoofedLocation.latitude || !spoofedLocation.longitude) {
                    error && error(new Error('Spoofed location is invalid.'));
                    return;
                }
                success && success({
                    coords: {
                        latitude: spoofedLocation.latitude,
                        longitude: spoofedLocation.longitude,
                        accuracy: 100,
                        altitude: null,
                        altitudeAccuracy: null,
                        heading: null,
                        speed: null,
                    },
                    timestamp: Date.now(),
                });
            },
            watchPosition: function (success, error, options) {
                if (!spoofedLocation.latitude || !spoofedLocation.longitude) {
                    error && error(new Error('Spoofed location is invalid.'));
                    return;
                }
                // Return a mock watch ID and store the interval
                activeWatchId = setInterval(() => {
                    success && success({
                        coords: {
                            latitude: spoofedLocation.latitude,
                            longitude: spoofedLocation.longitude,
                            accuracy: 100,
                            altitude: null,
                            altitudeAccuracy: null,
                            heading: null,
                            speed: null,
                        },
                        timestamp: Date.now(),
                    });
                }, 1000);
                return activeWatchId;
            },
            clearWatch: function (id) {
                if (id === activeWatchId) {
                    clearInterval(id);
                    activeWatchId = null;
                }
            },
            // Other geolocation methods can be added if necessary
        };

        // Override the navigator.geolocation
        Object.defineProperty(navigator, 'geolocation', {
            get: () => spoofedGeolocation,
            configurable: true,
        });
    }

    /**
     * Restores the original navigator.geolocation object.
     */
    function restoreOriginalGeolocation() {
        if (window.__originalGeolocation) {
            Object.defineProperty(navigator, 'geolocation', {
                value: window.__originalGeolocation,
                writable: true,
                configurable: true,
            });
            delete window.__originalGeolocation;
        }
    }

    /**
     * Reverts the Travel Mode button and icon to their original state.
     */
    function restoreOriginalTravelModeButton() {
        if (originalTravelModeButton) {
            const currentTravelModeIcon = originalTravelModeButton.querySelector(TRAVEL_MODE_ICON_SELECTOR);
            if (currentTravelModeIcon) {
                // Remove spoofed classes
                currentTravelModeIcon.className = '';
                // Restore original classes
                originalTravelModeIconClasses.forEach(cls => currentTravelModeIcon.classList.add(cls));
            }
            // Remove the custom event listener by cloning the node again
            const newTravelModeButton = originalTravelModeButton.cloneNode(true);
            originalTravelModeButton.parentNode.replaceChild(newTravelModeButton, originalTravelModeButton);
            originalTravelModeButton = null;
            originalTravelModeIconClasses = [];
        }
    }

    /**
     * Creates and returns the spoofing modal element with enhanced dark mode styling and customizable presets.
     * Implements responsive design for dynamic sizing and formatting.
     * @returns {HTMLElement} The modal overlay element.
     */
    function createModal() {
        // Create overlay
        const overlay = document.createElement('div');
        overlay.id = MODAL_ID;
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(11, 17, 31, 0.85); /* Reduced opacity for less darkened background */
            display: none;
            align-items: center;
            justify-content: center;
            z-index: 10000;
            overflow: auto; /* Allow scrolling on smaller screens */
        `;

        // Create modal container
        const modal = document.createElement('div');
        modal.style.cssText = `
            background-color: #111d33;
            border-radius: 8px;
            padding: 20px 25px;
            width: 90%;
            max-width: 500px; /* Base max-width */
            position: relative;
            box-shadow: 0 4px 16px rgba(0,0,0,0.5);
            font-family: Arial, sans-serif;
            color: #ffffff; /* White text for readability */
            display: flex;
            flex-direction: column;
            box-sizing: border-box;
        `;

        // Responsive adjustments using media queries
        const responsiveStyles = document.createElement('style');
        responsiveStyles.textContent = `
            @media (max-width: 768px) {
                #${MODAL_ID} div {
                    padding: 15px 20px;
                }
                #${MODAL_ID} h2 {
                    font-size: 18px;
                }
                #${MODAL_ID} input {
                    font-size: 14px;
                    padding: 8px 12px;
                }
                #${MODAL_ID} button {
                    font-size: 14px;
                    padding: 8px 0;
                }
            }

            @media (max-width: 480px) {
                #${MODAL_ID} div {
                    padding: 10px 15px;
                }
                #${MODAL_ID} h2 {
                    font-size: 16px;
                }
                #${MODAL_ID} input {
                    font-size: 12px;
                    padding: 6px 10px;
                }
                #${MODAL_ID} button {
                    font-size: 12px;
                    padding: 6px 0;
                }
                #${MODAL_ID} button {
                    flex: 100%;
                }
                #${MODAL_ID} .buttonsContainer {
                    flex-direction: column;
                }
            }
        `;
        document.head.appendChild(responsiveStyles);

        // Close button
        const closeButton = document.createElement('span');
        closeButton.innerHTML = '&times;';
        closeButton.style.cssText = `
            position: absolute;
            top: 15px;
            right: 20px;
            font-size: 24px;
            cursor: pointer;
            color: #ffffff;
            transition: color 0.3s;
        `;
        closeButton.addEventListener('mouseover', () => {
            closeButton.style.color = '#304065';
        });
        closeButton.addEventListener('mouseout', () => {
            closeButton.style.color = '#ffffff';
        });
        closeButton.addEventListener('click', () => {
            overlay.style.display = 'none';
            // Ensure the addPresetButton is visible if it was replaced
            showAddPresetButton();
        });

        // Modal title aligned to the left
        const title = document.createElement('h2');
        title.textContent = 'Location Spoofer';
        title.style.cssText = `
            margin: 0;
            margin-bottom: 15px;
            color: #ffffff;
            font-size: 20px;
            text-align: left;
        `;

        // Spoofing Indicator Container (Redesigned)
        const spoofingIndicatorContainer = document.createElement('div');
        spoofingIndicatorContainer.id = INDICATOR_ID; // Updated ID
        spoofingIndicatorContainer.style.cssText = `
            margin-bottom: 20px;
            padding: 10px 15px;
            background-color: #1e2a4a;
            border-radius: 4px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            cursor: pointer;
            transition: background-color 0.3s;
            flex-wrap: wrap;
        `;
        spoofingIndicatorContainer.title = 'Click to toggle spoofing';

        const indicatorStatus = document.createElement('span');
        indicatorStatus.id = 'indicatorStatusText';
        indicatorStatus.style.cssText = `
            font-weight: bold;
            font-size: 16px;
        `;
        indicatorStatus.textContent = 'Disabled'; // Default text

        // **Added: Location Info Span**
        const locationInfo = document.createElement('span');
        locationInfo.id = 'locationInfoText';
        locationInfo.style.cssText = `
            font-size: 16px;
        `;
        // Initially empty; will be populated when spoofing is enabled
        locationInfo.textContent = '';

        spoofingIndicatorContainer.appendChild(indicatorStatus);
        spoofingIndicatorContainer.appendChild(locationInfo); // Append the new span

        // Event listener to toggle spoofing on indicator click
        spoofingIndicatorContainer.addEventListener('click', () => {
            const storedLocation = getStoredLocation();
            if (storedLocation.enabled) {
                resetSpoofing();
                window.location.reload(); // Refresh to apply changes
            } else {
                overlay.style.display = 'flex';
            }
        });

        // Preset Locations Container
        const presetsContainer = document.createElement('div');
        presetsContainer.style.cssText = `
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            justify-content: flex-start;
            margin-bottom: 15px;
            /* Removed position: relative; */
        `;

        // Trash Icon
        const trashIcon = document.createElement('button');
        trashIcon.innerHTML = '🗑️'; // Unicode trash can icon
        trashIcon.title = 'Delete Presets';
        trashIcon.style.cssText = `
            padding: 6px 12px;
            background-color: #dc3545;
            color: #ffffff;
            border: none;
            border-radius: 20px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
            display: none; /* Hidden by default */
            align-items: center;
            justify-content: center;
            width: 36px;
            height: 36px;
        `;
        trashIcon.addEventListener('mouseover', () => {
            trashIcon.style.backgroundColor = '#a71d2a';
        });
        trashIcon.addEventListener('mouseout', () => {
            trashIcon.style.backgroundColor = '#dc3545';
        });

        // Make trashIcon a drop target
        trashIcon.addEventListener('dragover', (e) => {
            e.preventDefault();
            trashIcon.style.backgroundColor = '#ff1a1a';
        });

        trashIcon.addEventListener('dragleave', () => {
            trashIcon.style.backgroundColor = '#dc3545';
        });

        trashIcon.addEventListener('drop', (e) => {
            e.preventDefault();
            const presetName = e.dataTransfer.getData('text/plain');
            if (presetName) {
                removePreset(presetName);
                trashIcon.style.backgroundColor = '#dc3545';
                // Hide the trash icon after dropping
                trashIcon.style.display = 'none';
                // Show the addPresetButton again
                showAddPresetButton();
            }
        });

        // Function to show the addPresetButton
        function showAddPresetButton() {
            addPresetButton.style.display = 'flex';
            trashIcon.style.display = 'none';
        }

        // Function to show the trashIcon
        function showTrashIcon() {
            addPresetButton.style.display = 'none';
            trashIcon.style.display = 'flex';
        }

        // Function to handle drag start
        function handleDragStart(e, presetName) {
            e.dataTransfer.setData('text/plain', presetName);
            // Show the trash icon
            showTrashIcon();
        }

        // Function to handle drag end
        function handleDragEnd() {
            // Hide the trash icon
            trashIcon.style.display = 'none';
            // Show the addPresetButton again
            showAddPresetButton();
        }

        // Add Preset Button (with "+" sign)
        const addPresetButton = document.createElement('button');
        addPresetButton.innerHTML = '+';
        addPresetButton.title = 'Add Preset';
        addPresetButton.style.cssText = `
            padding: 6px 12px;
            background-color: #304065;
            color: #ffffff;
            border: none;
            border-radius: 20px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            width: 36px;
            height: 36px;
        `;
        addPresetButton.addEventListener('mouseover', () => {
            addPresetButton.style.backgroundColor = '#1e2a4a';
        });
        addPresetButton.addEventListener('mouseout', () => {
            addPresetButton.style.backgroundColor = '#304065';
        });
        addPresetButton.addEventListener('click', () => {
            // Prompt the user to enter a new preset location
            const presetName = prompt('Enter the name of the new preset location:');
            if (presetName) {
                addNewPreset(presetName.trim());
            }
        });
        presetsContainer.appendChild(addPresetButton);

        // Append the trashIcon to presetsContainer (after the last preset)
        presetsContainer.appendChild(trashIcon);

        /**
         * Adds a new preset location.
         * @param {string} presetName - The name of the preset location.
         */
        async function addNewPreset(presetName) {
            if (!presetName) {
                // Removed alert
                return;
            }
            const currentPresets = getPresetLocations();
            // Check for duplicates
            if (currentPresets.some(p => p.name.toLowerCase() === presetName.toLowerCase())) {
                // Removed alert
                return;
            }
            try {
                const coords = await geocodeLocation(presetName);
                const newPreset = {
                    name: presetName,
                    latitude: coords.latitude,
                    longitude: coords.longitude,
                };
                currentPresets.push(newPreset);
                setPresetLocations(currentPresets);
                // Add the new preset button
                const newPresetButton = createPresetButton(newPreset);
                // Insert before the addPresetButton
                presetsContainer.insertBefore(newPresetButton, addPresetButton);
                // Optionally, log success instead of alert
                console.log(`Preset "${presetName}" added successfully.`);
            } catch (error) {
                console.error(error.message);
            }
        }

        /**
         * Removes a preset location by name.
         * @param {string} presetName - The name of the preset to remove.
         */
        function removePreset(presetName) {
            const currentPresets = getPresetLocations();
            const updatedPresets = currentPresets.filter(p => p.name !== presetName);
            setPresetLocations(updatedPresets);
            // Remove the preset button from the modal
            const allPresetButtons = presetsContainer.querySelectorAll('button');
            allPresetButtons.forEach(button => {
                if (button.textContent.startsWith(presetName)) {
                    button.remove();
                }
            });
            // Optionally, log removal instead of alert
            console.log(`Preset "${presetName}" removed successfully.`);
        }

        /**
         * Function to create a preset button with draggable functionality.
         * @param {Object} preset - The preset location object.
         * @returns {HTMLElement} The created preset button element.
         */
        function createPresetButton(preset) {
            const presetButton = document.createElement('button');
            presetButton.textContent = preset.name;
            presetButton.style.cssText = `
                padding: 6px 12px;
                background-color: #304065;
                color: #ffffff;
                border: none;
                border-radius: 20px;
                cursor: pointer;
                font-size: 14px;
                transition: background-color 0.3s;
                display: flex;
                align-items: center;
                gap: 5px;
            `;
            presetButton.setAttribute('draggable', 'true'); // Make the button draggable

            presetButton.addEventListener('mouseover', () => {
                presetButton.style.backgroundColor = '#1e2a4a';
            });
            presetButton.addEventListener('mouseout', () => {
                presetButton.style.backgroundColor = '#304065';
            });
            presetButton.addEventListener('click', () => {
                setStoredLocation({
                    enabled: true,
                    locationName: preset.name,
                    latitude: preset.latitude,
                    longitude: preset.longitude,
                });
                overrideGeolocation({
                    latitude: preset.latitude,
                    longitude: preset.longitude,
                });
                updateSpoofingIndicator();
                // Removed alert
                console.log(`Location spoofed to ${preset.name}.`);
                // Refresh the page after saving and applying spoofing
                window.location.reload(); // **Added to refresh the page**
            });

            // Add event listeners for drag events
            presetButton.addEventListener('dragstart', (e) => handleDragStart(e, preset.name));
            presetButton.addEventListener('dragend', handleDragEnd);

            return presetButton;
        }

        // Load and display preset buttons
        const presets = getPresetLocations();
        presets.forEach(preset => {
            const presetButton = createPresetButton(preset);
            presetsContainer.insertBefore(presetButton, addPresetButton);
        });

        // Location Input
        const locationInput = document.createElement('input');
        locationInput.type = 'text';
        locationInput.id = 'locationInput';
        // **Changed placeholder text as per user request**
        locationInput.placeholder = 'Where to?'; // **Updated placeholder**
        locationInput.style.cssText = `
            width: 100%;
            padding: 10px 15px;
            margin: 10px 0;
            border: none;
            border-radius: 4px;
            background-color: #0b111f;
            color: #ffffff;
            font-size: 16px;
            box-sizing: border-box;
        `;
        locationInput.addEventListener('focus', () => {
            locationInput.style.backgroundColor = '#304065';
            locationInput.style.outline = 'none';
        });
        locationInput.addEventListener('blur', () => {
            locationInput.style.backgroundColor = '#0b111f';
        });

        // Action Buttons Container
        const buttonsContainer = document.createElement('div');
        buttonsContainer.className = 'buttonsContainer'; // Added class for media query
        buttonsContainer.style.cssText = `
            display: flex;
            justify-content: space-between;
            flex-wrap: wrap;
            gap: 10px;
            margin-top: 10px;
        `;

        // Apply Button (formerly "Save & Apply")
        const applyButton = document.createElement('button');
        applyButton.textContent = 'Apply'; // **Changed button text to "Apply"**
        applyButton.style.cssText = `
            flex: 1;
            padding: 10px 0;
            background-color: #304065;
            color: #ffffff;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
            min-width: 100px;
        `;
        applyButton.addEventListener('mouseover', () => {
            applyButton.style.backgroundColor = '#1e2a4a';
        });
        applyButton.addEventListener('mouseout', () => {
            applyButton.style.backgroundColor = '#304065';
        });
        applyButton.addEventListener('click', async () => {
            const locationName = locationInput.value.trim();
            if (!locationName) {
                // Removed alert
                return;
            }
            try {
                const coords = await geocodeLocation(locationName);
                setStoredLocation({
                    enabled: true,
                    locationName,
                    latitude: coords.latitude,
                    longitude: coords.longitude,
                });
                overrideGeolocation({
                    latitude: coords.latitude,
                    longitude: coords.longitude,
                });
                updateSpoofingIndicator();
                // Removed alert
                console.log('Location spoofing applied.');
                // **Added to refresh the page after saving and applying spoofing**
                window.location.reload(); // **Ensures page refreshes upon clicking "Apply"**
            } catch (error) {
                console.error(error.message);
            }
        });

        // Reset Button
        const resetButton = document.createElement('button');
        resetButton.textContent = 'Reset';
        resetButton.style.cssText = `
            flex: 1;
            padding: 10px 0;
            background-color: #dc3545;
            color: #ffffff;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
            min-width: 100px;
        `;
        resetButton.addEventListener('mouseover', () => {
            resetButton.style.backgroundColor = '#a71d2a';
        });
        resetButton.addEventListener('mouseout', () => {
            resetButton.style.backgroundColor = '#dc3545';
        });
        resetButton.addEventListener('click', () => {
            // Trigger the reset functionality without confirmation
            resetSpoofing();
            // **Added to refresh the page after resetting spoofing**
            window.location.reload(); // **Ensures page refreshes upon clicking "Reset"**
        });

        // Append buttons to buttons container
        buttonsContainer.appendChild(applyButton); // **Changed from saveButton to applyButton**
        buttonsContainer.appendChild(resetButton);

        // Append elements to modal
        modal.appendChild(closeButton);
        modal.appendChild(title);
        modal.appendChild(spoofingIndicatorContainer);
        modal.appendChild(presetsContainer);
        modal.appendChild(locationInput);
        modal.appendChild(buttonsContainer);

        // Append modal to overlay
        overlay.appendChild(modal);

        // Append overlay to body
        document.body.appendChild(overlay);

        // **Added: Dismiss modal when clicking outside the modal box**
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) { // Ensure the click is on the overlay, not the modal
                overlay.style.display = 'none';
                // Ensure the addPresetButton is visible if it was replaced
                showAddPresetButton();
            }
        });

        return overlay;
    }

    /**
     * Attaches the spoofing modal to the Travel Mode button.
     */
    function attachModalToTravelMode() {
        const overlay = createModal();

        // Function to handle Travel Mode button clicks
        const handleTravelModeClick = (event) => {
            event.preventDefault();
            event.stopPropagation();
            overlay.style.display = 'flex';
        };

        // Wait for the Travel Mode icon to be available in the DOM
        const observer = new MutationObserver((mutations, obs) => {
            const travelModeIcon = document.querySelector(TRAVEL_MODE_ICON_SELECTOR);
            if (travelModeIcon) {
                // Find the closest clickable parent (assuming it's a button or clickable element)
                const travelModeButton = travelModeIcon.closest('button, a, div');
                if (travelModeButton) {
                    // Store references to original elements and classes
                    originalTravelModeButton = travelModeButton;
                    originalTravelModeIconClasses = [...travelModeIcon.classList];

                    // Remove existing event listeners by cloning the node
                    const newTravelModeButton = travelModeButton.cloneNode(true);
                    travelModeButton.parentNode.replaceChild(newTravelModeButton, travelModeButton);

                    // Attach new event listener
                    newTravelModeButton.addEventListener('click', handleTravelModeClick);

                    // Optionally, change the icon to indicate spoofing functionality
                    // Example: Change plane icon to a location pin
                    travelModeIcon.classList.remove('fa-plane');
                    travelModeIcon.classList.add('fa-map-marker-alt'); // Ensure FontAwesome supports this class
                }
                obs.disconnect();
            }
        });

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

    /**
     * Updates the spoofing indicator within the modal based on spoofing status.
     * Shows spoofed location if enabled, otherwise shows real location.
     */
    async function updateSpoofingIndicator() {
        const storedLocation = getStoredLocation();
        const indicatorContainer = document.getElementById(INDICATOR_ID);
        const statusText = document.getElementById('indicatorStatusText');
        const locationInfo = document.getElementById('locationInfoText'); // Access the new span

        if (storedLocation.enabled && storedLocation.locationName) {
            // Spoofing is active
            indicatorContainer.style.backgroundColor = '#1e2a4a';
            indicatorContainer.style.borderLeft = '5px solid #28a745'; // Green border
            statusText.textContent = 'Enabled';
            statusText.style.color = '#28a745'; // Green text
            // Display spoofed location with location pin emoji on the left
            locationInfo.textContent = `📍 ${storedLocation.locationName}`;
        } else {
            // Spoofing is inactive; show actual location
            indicatorContainer.style.backgroundColor = '#1e2a4a';
            indicatorContainer.style.borderLeft = '5px solid #dc3545'; // Red border
            statusText.textContent = 'Disabled';
            statusText.style.color = '#dc3545'; // Red text

            // Clear the locationInfo span
            locationInfo.textContent = '';

            // Fetch and display the real location
            try {
                const position = await getRealPosition();
                const { latitude, longitude } = position.coords;
                const locationName = await reverseGeocodeLocation(latitude, longitude);
                // Optionally, you can display the real location if desired
                // For now, we're keeping the indicator as 'Disabled'
            } catch (error) {
                statusText.textContent = 'Disabled';
                statusText.style.color = '#dc3545'; // Red text
                console.error(error.message);
            }
        }
    }

    /**
     * Gets the real geolocation of the user.
     * @returns {Promise<GeolocationPosition>} Promise resolving to the user's real geolocation.
     */
    function getRealPosition() {
        return new Promise((resolve, reject) => {
            navigator.geolocation.getCurrentPosition(resolve, reject, {
                enableHighAccuracy: true,
                timeout: 10000,
                maximumAge: 0,
            });
        });
    }

    /**
     * Resets the spoofing by restoring original geolocation and removing all spoofing effects.
     */
    function resetSpoofing() {
        // Set the disabled flag
        isUserscriptDisabled = true;

        // Clear stored location data
        clearStoredLocation();

        // Restore the original geolocation
        restoreOriginalGeolocation();

        // Clear any active watch intervals
        if (activeWatchId) {
            navigator.geolocation.clearWatch(activeWatchId);
        }

        // Restore the original Travel Mode button and icon
        restoreOriginalTravelModeButton();

        // Update spoofing indicator
        updateSpoofingIndicator();

        // Hide the modal if it's open
        const overlay = document.getElementById(MODAL_ID);
        if (overlay) {
            overlay.style.display = 'none';
        }

        // Removed alert
        console.log('Location reset to actual position. The userscript has been disabled.');
    }

    /**
     * Overrides the Geolocation API if spoofing is enabled and the userscript is not disabled.
     */
    function initSpoofing() {
        if (isUserscriptDisabled) return;

        const storedLocation = getStoredLocation();

        if (storedLocation.enabled && storedLocation.latitude && storedLocation.longitude) {
            overrideGeolocation({
                latitude: storedLocation.latitude,
                longitude: storedLocation.longitude,
            });
            updateSpoofingIndicator();
            console.log(`Location spoofed to: ${storedLocation.locationName} (${storedLocation.latitude}, ${storedLocation.longitude})`);
        } else {
            // Ensure the original Geolocation API is restored
            restoreOriginalGeolocation();
            updateSpoofingIndicator();
        }
    }

    /**
     * Initializes the userscript by setting up the UI and spoofing functionality.
     */
    function init() {
        if (isUserscriptDisabled) return;

        attachModalToTravelMode();
        initSpoofing();
    }

    // Wait for the DOM to be fully loaded before initializing
    window.addEventListener('DOMContentLoaded', init);
})();