Google Maps Enhanced Edits

Adds quality of life tweaks to the editing experience in Google Maps.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Google Maps Enhanced Edits
// @namespace    https://github.com/gncnpk/google-maps-enhanced-edits
// @version      0.0.17
// @description  Adds quality of life tweaks to the editing experience in Google Maps.
// @author       Gavin Canon-Phratsachack (https://github.com/gncnpk)
// @match        https://www.google.com/maps/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=google.com/maps
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let isInit = false;
    let isEventHandlersInit = false;
    let oldHref = document.location.href;

    // Store observers for cleanup
    let autoCleanupObserver = null;
    let containerObserver = null;
    let bodyObserver = null;

    // inject a global CSS rule
    const style = document.createElement('style');
    style.textContent = `
    .qjoALb {
      margin-bottom: 0 !important;
    }
    .n6N0W {
      margin-bottom: 0 !important;
    }
    .zOQ8Le {
      margin-bottom: 4px !important;
    }
    .BjkJBb {
      margin: 6px !important;
    }
    .JjQyvd {
      margin: 0 8px 10px !important;
    }
    .mOLNZc {
      padding-top: 10px !important;
    }
    .Jo6p1e {
      padding: 10px !important;
    }
    .uLTO2d {
      margin: 8px !important;
    }
    .fontTitleLarge.HYVdIf:hover {
      text-decoration: underline;
    }

    /* Date filter disabled states */
    .quick-date-btn:disabled,
    .clear-date-btn:disabled {
      background: #e0e0e0 !important;
      color: #999 !important;
      cursor: not-allowed !important;
      border-color: #ccc !important;
    }
    input[type="date"]:disabled {
      background: #f5f5f5 !important;
      color: #999 !important;
      cursor: not-allowed !important;
    }

    /* Edit numbering styles */
    .edit-number {
      position: relative;
      margin-top: auto;
      margin-bottom: auto;
      margin-right: 5px;
      background: #4285f4;
      color: white;
      font-size: 12px;
      font-weight: bold;
      width: 24px;
      height: 24px;
      border-radius: 0%;
      z-index: 10;
      display: flex;
      align-items: center;
      justify-content: center;
      min-width: 24px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.2);
      transition: all 0.3s ease;
    }
    .edit-number.hidden {
      display: none !important;
    }
    .edit-number.highlight {
      background: #ea4335 !important;
      transform: scale(1.2);
      box-shadow: 0 0 15px rgba(234, 67, 53, 0.8);
    }
    .Jo6p1e {
      position: relative !important;
    }
    .m6QErb.XiKgde.ecceSd.JoFlEe {
      width: auto !important;
    }
    .YWlkcf.fVTiyc {
      margin-top: auto !important;
      margin-bottom: auto !important;
    }
    .PInAKb {
      border-radius: 0% !important;
      margin-right: 5px !important;
    }

    /* Go to edit number styles */
    .go-to-edit-container {
      display: flex;
      gap: 4px;
      align-items: center;
      margin-bottom: 8px;
    }
    .go-to-edit-input {
      flex: 1;
      padding: 4px 6px;
      border: 1px solid #ccc;
      border-radius: 4px;
      font-size: 12px;
    }
    .go-to-edit-btn {
      background: #4285f4;
      border: none;
      border-radius: 4px;
      color: white;
      padding: 4px 8px;
      font-size: 12px;
      cursor: pointer;
      white-space: nowrap;
    }
    .go-to-edit-btn:hover {
      background: #3367d6;
    }
    .go-to-edit-btn:disabled {
      background: #e0e0e0;
      color: #999;
      cursor: not-allowed;
    }

    /* Filter list styles */
    .filter-list {
      list-style: none;
      padding: 0;
      margin: 0;
      max-height: 120px;
      overflow-y: auto;
      border: 1px solid #e0e0e0;
      border-radius: 4px;
      background: #f9f9f9;
    }
    .filter-list-item {
      padding: 8px 12px;
      cursor: pointer;
      border-bottom: 1px solid #e0e0e0;
      font-size: 13px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      transition: background-color 0.2s ease;
    }
    .filter-list-item:last-child {
      border-bottom: none;
    }
    .filter-list-item:hover {
      background: #e8f0fe;
    }
    .filter-list-item.active {
      background: #4285f4;
      color: white;
      font-weight: bold;
    }
    .filter-list-item.active:hover {
      background: #3367d6;
    }
    .filter-count {
      font-size: 11px;
      background: rgba(0,0,0,0.1);
      padding: 2px 6px;
      border-radius: 10px;
      margin-left: 8px;
    }
    .filter-list-item.active .filter-count {
      background: rgba(255,255,255,0.2);
    }
    .status-indicator {
      width: 12px;
      height: 12px;
      border-radius: 50%;
      margin-right: 8px;
      flex-shrink: 0;
    }

    /* ===== PURE CSS CLEANUP RULES ===== */

    /* Hide first child of .eYfez elements */
    .eYfez > *:first-child {
      display: none !important;
    }

    /* Hide parent elements containing the symbol */
    *:has(> .MaIKSd.google-symbols.G47vBd) {
      display: none !important;
    }

    /* Hide status elements (they'll be replaced with colored borders) */
    .cLk0Bb, .UgJ9Rc, .ehaAif, .gZbGnf {
      display: none !important;
    }

    /* Add colored left borders based on status classes */
    .Jo6p1e:has(.cLk0Bb) {
      border-left: 10px solid #198639 !important; /* Accepted - Green */
    }
    .Jo6p1e:has(.UgJ9Rc) {
      border-left: 10px solid #b26c00 !important; /* Pending - Orange */
    }
    .Jo6p1e:has(.ehaAif) {
      border-left: 10px solid #dc362e !important; /* Not Accepted - Red */
    }
    .Jo6p1e:has(.gZbGnf) {
      border-left: 10px solid #5e5e5e !important; /* Incorrect - Gray */
    }

    /* Add tooltip styling and behavior */
    .fontTitleLarge.HYVdIf {
      cursor: pointer;
      position: relative;
    }
    .fontTitleLarge.HYVdIf::after {
      content: "Go to map edit";
      position: absolute;
      display: none;
      background: rgba(0,0,0,0.8);
      color: white;
      padding: 4px 8px;
      border-radius: 4px;
      font-size: 12px;
      white-space: nowrap;
      z-index: 1000;
      pointer-events: none;
      top: 100%;
      left: 0;
      margin-top: 4px;
    }
    .fontTitleLarge.HYVdIf:hover::after {
      display: block;
    }

    /* Fallback for browsers without :has() support */
    @supports not selector(*:has(*)) {
      .gmee-symbol-parent {
        display: none !important;
      }
      /* Fallback colored borders using class-based approach */
      .gmee-status-accepted .Jo6p1e {
        border-left: 10px solid #198639 !important;
      }
      .gmee-status-pending .Jo6p1e {
        border-left: 10px solid #b26c00 !important;
      }
      .gmee-status-not-accepted .Jo6p1e {
        border-left: 10px solid #dc362e !important;
      }
      .gmee-status-incorrect .Jo6p1e {
        border-left: 10px solid #5e5e5e !important;
      }
    }
  `;
    document.head.appendChild(style);

    // current filters
    let currentStatusFilter = null;
    let currentTypeFilter = null;
    let currentDateFilter = null; // Date object or null
    let currentDateRangeEnd = null; // Date object for range end or null
    let editsContainer = null;

    // DOM & state - Load numbering preference from localStorage
    let popup, btnContainer, typeContainer, dateContainer, statsDiv;
    let autoLoadEnabled = false;
    let numberingEnabled = localStorage.getItem('gmee-numbering-enabled') !== 'false'; // Default to true, false only if explicitly set
    let scrollContainer = null;
    let statusList = null;
    let typeList = null;

    // LocalStorage key for user preferences
    const STORAGE_KEY = 'gmee-numbering-enabled';

    // Function to save numbering preference
    function saveNumberingPreference() {
        localStorage.setItem(STORAGE_KEY, numberingEnabled.toString());
    }

    // Replace your old STATUSES definition with this:
    const STATUSES = [{
            name: 'Accepted',
            className: 'cLk0Bb',
            color: '#198639'
        },
        {
            name: 'Pending',
            className: 'UgJ9Rc',
            color: '#b26c00'
        },
        {
            name: 'Not Accepted',
            className: 'ehaAif',
            color: '#dc362e'
        },
        {
            name: 'Incorrect',
            className: 'gZbGnf',
            color: '#5e5e5e'
        }
    ];

    // Improved function to find edits container with multiple strategies
    function findEditsContainer() {
        // Strategy 1: Look for containers with edit items (.EhpEb class)
        const editItems = document.querySelectorAll('.EhpEb');
        if (editItems.length > 0) {
            // Find the common parent container
            let container = editItems[0].parentElement;
            while (container && container.children.length < editItems.length) {
                container = container.parentElement;
            }
            if (container && container.children.length >= editItems.length) {
                return container;
            }
        }

        // Strategy 2: Look for containers with multiple m6QErb XiKgde elements
        const containers = Array.from(document.querySelectorAll('.m6QErb.XiKgde'))
            .filter(el => {
                const parent = el.parentElement;
                return parent && Array.from(parent.children).filter(child =>
                    child.classList.contains('m6QErb') && child.classList.contains('XiKgde')
                ).length > 1;
            });

        if (containers.length > 0) {
            // Find the container with the most edit-like items
            let bestContainer = null;
            let maxEditItems = 0;

            containers.forEach(container => {
                const editCount = container.querySelectorAll('.EhpEb, .Jo6p1e').length;
                if (editCount > maxEditItems) {
                    maxEditItems = editCount;
                    bestContainer = container;
                }
            });

            if (bestContainer) {
                return bestContainer;
            }
        }

        // Strategy 3: Original fallback method
        const potentialContainers = document.getElementsByClassName('m6QErb XiKgde');
        for (let i = 0; i < potentialContainers.length; i++) {
            const container = potentialContainers[i];
            const editItems = container.querySelectorAll('.EhpEb');
            if (editItems.length > 0) {
                return container;
            }
        }

        return null;
    }

    // Improved function to find scroll container
    function findScrollContainer() {
        // Strategy 1: Find container with edits
        if (editsContainer) {
            let container = editsContainer;
            while (container && container !== document.body) {
                const style = getComputedStyle(container);
                if ((style.overflowY === 'auto' || style.overflowY === 'scroll') &&
                    container.scrollHeight > container.clientHeight) {
                    return container;
                }
                container = container.parentElement;
            }
        }

        // Strategy 2: Look for common Google Maps scroll containers
        const commonScrollSelectors = [
            '.m6QErb.DxyBCb.kA9KIf.dS8AEf.XiKgde',
            '.CsJaGe',
            '.siAUzd.Vetdqc',
            '[role="main"]'
        ];

        for (const selector of commonScrollSelectors) {
            const container = document.querySelector(selector);
            if (container) {
                const style = getComputedStyle(container);
                if ((style.overflowY === 'auto' || style.overflowY === 'scroll') &&
                    container.scrollHeight > container.clientHeight) {
                    return container;
                }
            }
        }

        // Strategy 3: Find any scrollable container that contains edits
        const scrollableElements = Array.from(document.querySelectorAll('*')).filter(el => {
            const style = getComputedStyle(el);
            return (style.overflowY === 'auto' || style.overflowY === 'scroll') &&
                el.scrollHeight > el.clientHeight &&
                el.querySelector('.EhpEb');
        });

        return scrollableElements.length > 0 ? scrollableElements[0] : null;
    }

    // Function to go to specific edit number
    function goToEditNumber(targetNumber) {
        if (!editsContainer || !numberingEnabled) {
            alert('Edit numbering must be enabled to use this feature');
            return;
        }

        // Get all visible edit items
        const allItems = Array.from(editsContainer.children);
        const visibleItems = allItems.filter(item => getComputedStyle(item).display !== 'none');

        if (targetNumber < 1 || targetNumber > visibleItems.length) {
            alert(`Please enter a number between 1 and ${visibleItems.length}`);
            return;
        }

        const targetItem = visibleItems[targetNumber - 1];
        if (!targetItem) return;

        // Clear any existing highlights
        document.querySelectorAll('.edit-number.highlight').forEach(el => {
            el.classList.remove('highlight');
        });

        // Find and highlight the target edit number
        const numberElement = targetItem.querySelector('.edit-number');
        if (numberElement) {
            numberElement.classList.add('highlight');

            // Remove highlight after 3 seconds
            setTimeout(() => {
                numberElement.classList.remove('highlight');
            }, 3000);
        }

        // Scroll to the target item
        if (scrollContainer) {
            const containerRect = scrollContainer.getBoundingClientRect();
            const itemRect = targetItem.getBoundingClientRect();

            // Calculate scroll position to center the item
            const scrollTop = scrollContainer.scrollTop + itemRect.top - containerRect.top - (containerRect.height / 2) + (itemRect.height / 2);

            scrollContainer.scrollTo({
                top: scrollTop,
                behavior: 'smooth'
            });
        } else {
            // Fallback: scroll into view
            targetItem.scrollIntoView({
                behavior: 'smooth',
                block: 'center'
            });
        }
    }

    // Deinitialize function to clean up when leaving edits page
    function deinitializeEditsUI() {
        console.log('Deinitializing Google Maps Enhanced Edits UI');

        // Remove popup
        if (popup && popup.parentNode) {
            popup.parentNode.removeChild(popup);
            popup = null;
        }

        // Disconnect observers
        if (autoCleanupObserver) {
            autoCleanupObserver.disconnect();
            autoCleanupObserver = null;
        }

        if (containerObserver) {
            containerObserver.disconnect();
            containerObserver = null;
        }

        if (bodyObserver) {
            bodyObserver.disconnect();
            bodyObserver = null;
        }

        // Reset variables
        currentStatusFilter = null;
        currentTypeFilter = null;
        currentDateFilter = null;
        currentDateRangeEnd = null;
        editsContainer = null;
        btnContainer = null;
        typeContainer = null;
        dateContainer = null;
        statsDiv = null;
        autoLoadEnabled = false;
        scrollContainer = null;
        statusList = null;
        typeList = null;

        // Reset initialization flags
        isInit = false;

        // Hide edit numbers instead of removing them
        document.querySelectorAll('.edit-number').forEach(el => el.classList.add('hidden'));

        // Remove CSS classes for symbol parents (fallback cleanup)
        document.querySelectorAll('.gmee-symbol-parent').forEach(el => {
            el.classList.remove('gmee-symbol-parent');
        });

        console.log('UI deinitialized successfully');
    }

    // Toggle auto load on/off
    function toggleAutoLoad() {
        autoLoadEnabled = !autoLoadEnabled;

        if (autoLoadEnabled && scrollContainer) {
            scrollContainer.scrollTop = scrollContainer.scrollHeight;
        }

        // Update toggle button text and color
        const autoLoadBtn = document.querySelector('.toggle-autoload-btn');
        if (autoLoadBtn) {
            autoLoadBtn.textContent = autoLoadEnabled ? 'Disable Auto Load' : 'Enable Auto Load';
            autoLoadBtn.style.backgroundColor = autoLoadEnabled ? '#ea4335' : '#34a853';
        }
    }

    // Helper function to parse date from edit text
    function parseEditDate(dateText) {
        if (!dateText) return null;

        const now = new Date();
        let editDate;

        // Handle "Submitted [Month] [Day]" format (e.g., "Submitted Aug 7")
        if (dateText.includes('Submitted')) {
            const submittedMatch = dateText.match(/Submitted\s+([A-Za-z]+)\s+(\d+)/i);
            if (submittedMatch) {
                const monthStr = submittedMatch[1];
                const day = parseInt(submittedMatch[2]);
                const currentYear = now.getFullYear();

                // Parse the month name to get month index
                const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
                ];
                const fullMonthNames = ['January', 'February', 'March', 'April', 'May', 'June',
                    'July', 'August', 'September', 'October', 'November', 'December'
                ];

                let monthIndex = monthNames.findIndex(m => monthStr.toLowerCase().startsWith(m.toLowerCase()));
                if (monthIndex === -1) {
                    monthIndex = fullMonthNames.findIndex(m => monthStr.toLowerCase() === m.toLowerCase());
                }

                if (monthIndex !== -1) {
                    editDate = new Date(currentYear, monthIndex, day);

                    // If the date is in the future, assume it's from last year
                    if (editDate > now) {
                        editDate.setFullYear(currentYear - 1);
                    }
                }
            }
        }
        // Handle relative dates like "2 days ago", "1 week ago", etc.
        else if (dateText.includes('ago')) {
            const match = dateText.match(/(\d+)\s*(day|week|month|year)s?\s*ago/i);
            if (match) {
                const amount = parseInt(match[1]);
                const unit = match[2].toLowerCase();
                editDate = new Date(now);

                switch (unit) {
                    case 'day':
                        editDate.setDate(editDate.getDate() - amount);
                        break;
                    case 'week':
                        editDate.setDate(editDate.getDate() - (amount * 7));
                        break;
                    case 'month':
                        editDate.setMonth(editDate.getMonth() - amount);
                        break;
                    case 'year':
                        editDate.setFullYear(editDate.getFullYear() - amount);
                        break;
                }
            }
        }
        // Handle "today", "yesterday" text
        else if (dateText.toLowerCase().includes('today')) {
            editDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
        } else if (dateText.toLowerCase().includes('yesterday')) {
            editDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
            editDate.setDate(editDate.getDate() - 1);
        } else {
            // Try to parse absolute dates
            editDate = new Date(dateText);
            if (isNaN(editDate.getTime())) {
                return null;
            }
        }

        return editDate && !isNaN(editDate.getTime()) ? editDate : null;
    }

    // Helper function to get date range of available edits
    function getEditDateRange() {
        if (!editsContainer) return {
            min: null,
            max: null,
            hasEdits: false
        };

        const editItems = Array.from(editsContainer.children);
        const dates = [];

        editItems.forEach(item => {
            // Skip items that are still loading
            if (isEditItemLoading(item)) return;

            const dateElement = item.querySelector('.fontBodySmall.eYfez');
            if (dateElement) {
                const dateText = dateElement.textContent.trim();
                const parsedDate = parseEditDate(dateText);
                if (parsedDate) {
                    dates.push(parsedDate);
                }
            }
        });

        if (dates.length === 0) {
            return {
                min: null,
                max: null,
                hasEdits: false
            };
        }

        const sortedDates = dates.sort((a, b) => a - b);
        return {
            min: sortedDates[0],
            max: sortedDates[sortedDates.length - 1],
            hasEdits: true
        };
    }

    // Helper function to update date input constraints
    function updateDateInputConstraints() {
        const startDateInput = dateContainer.querySelector('input[type="date"]:first-of-type');
        const endDateInput = dateContainer.querySelector('input[type="date"]:last-of-type');
        const quickDateButtons = dateContainer.querySelectorAll('.quick-date-btn');
        const clearBtn = dateContainer.querySelector('.clear-date-btn');

        if (!startDateInput || !endDateInput) return;

        const dateRange = getEditDateRange();
        const today = new Date();
        const todayStr = today.toISOString().split('T')[0];

        // Set max date to today for both inputs
        startDateInput.max = todayStr;
        endDateInput.max = todayStr;

        if (dateRange.hasEdits) {
            // Set min date to earliest edit date
            const minDateStr = dateRange.min.toISOString().split('T')[0];
            startDateInput.min = minDateStr;
            endDateInput.min = minDateStr;

            // Enable inputs and buttons
            startDateInput.disabled = false;
            endDateInput.disabled = false;
            quickDateButtons.forEach(btn => btn.disabled = false);
            clearBtn.disabled = currentDateFilter === null;

            // Update placeholder text
            startDateInput.title = `Select date between ${dateRange.min.toLocaleDateString()} and ${today.toLocaleDateString()}`;
            endDateInput.title = `Select date between ${dateRange.min.toLocaleDateString()} and ${today.toLocaleDateString()}`;
        } else {
            // Disable inputs and buttons when no edits are available
            startDateInput.disabled = true;
            endDateInput.disabled = true;
            startDateInput.value = '';
            endDateInput.value = '';
            quickDateButtons.forEach(btn => btn.disabled = true);
            clearBtn.disabled = true;

            // Update placeholder text
            startDateInput.title = 'No edits available for date filtering';
            endDateInput.title = 'No edits available for date filtering';
        }
    }

    // Helper function to update go-to-edit input constraints
    function updateGoToEditConstraints() {
        const goToInput = popup?.querySelector('.go-to-edit-input');
        const goToBtn = popup?.querySelector('.go-to-edit-btn');

        if (!goToInput || !goToBtn || !editsContainer) return;

        const visibleItems = Array.from(editsContainer.children).filter(item =>
            getComputedStyle(item).display !== 'none'
        );

        const maxNumber = visibleItems.length;

        if (maxNumber === 0) {
            goToInput.disabled = true;
            goToBtn.disabled = true;
            goToInput.placeholder = 'No edits available';
            goToInput.title = 'No edits available to navigate to';
        } else {
            goToInput.disabled = false;
            goToBtn.disabled = !numberingEnabled;
            goToInput.placeholder = `1-${maxNumber}`;
            goToInput.title = numberingEnabled ?
                `Enter edit number between 1 and ${maxNumber}` :
                'Enable edit numbering to use this feature';
            goToInput.max = maxNumber;
            goToInput.min = 1;
        }
    }

    // Helper function to check if an edit item is still loading
    function isEditItemLoading(item) {
        // Check for common indicators that content is still loading
        const dateElement = item.querySelector('.fontBodySmall.eYfez');
        const titleElement = item.querySelector('.fontTitleLarge.HYVdIf');
        const typeElement = item.querySelectorAll('.BjkJBb')[0]?.children[1];

        // If key elements are missing or empty, consider it still loading
        if (!dateElement || !titleElement || !typeElement) return true;
        if (!dateElement.textContent.trim() || !titleElement.textContent.trim() || !typeElement.textContent.trim()) return true;

        // Check for loading indicators or placeholder text
        const dateText = dateElement.textContent.trim();
        const titleText = titleElement.textContent.trim();

        if (dateText.includes('Loading') || titleText.includes('Loading') ||
            dateText === '...' || titleText === '...') return true;

        return false;
    }

    // Helper function to check if edit date is in selected range
    function isDateInRange(dateText) {
        if (!currentDateFilter) return true;

        // If date text is empty or not yet loaded, don't filter it out
        if (!dateText || dateText.trim() === '') return true;

        const editDate = parseEditDate(dateText);
        if (!editDate) return true; // Include items we can't parse or that haven't loaded yet

        const editDateOnly = new Date(editDate.getFullYear(), editDate.getMonth(), editDate.getDate());
        const filterDateOnly = new Date(currentDateFilter.getFullYear(), currentDateFilter.getMonth(), currentDateFilter.getDate());

        if (currentDateRangeEnd) {
            // Range filtering
            const endDateOnly = new Date(currentDateRangeEnd.getFullYear(), currentDateRangeEnd.getMonth(), currentDateRangeEnd.getDate());
            return editDateOnly >= filterDateOnly && editDateOnly <= endDateOnly;
        } else {
            // Single date filtering
            return editDateOnly.getTime() === filterDateOnly.getTime();
        }
    }

    // Add numbering to all edit items
    function addEditNumbering() {
        const PANE_SELECTOR = '.EhpEb';
        document.querySelectorAll(PANE_SELECTOR).forEach((item, index) => {
            const wrap = item.querySelector('.qjoALb');
            if (!wrap) return;

            // Look for existing number element
            let existingNumber = wrap.querySelector('.edit-number');

            if (numberingEnabled) {
                if (existingNumber) {
                    // Reuse existing number element
                    existingNumber.textContent = index + 1;
                    existingNumber.classList.remove('hidden');
                } else {
                    // Create new number element if it doesn't exist
                    const numberElement = document.createElement('div');
                    numberElement.className = 'edit-number';
                    numberElement.textContent = index + 1;
                    wrap.insertBefore(numberElement, wrap.children[0]);
                }
            } else {
                // Hide existing number instead of removing it
                if (existingNumber) {
                    existingNumber.classList.add('hidden');
                }
            }
        });
    }

    // Simplified auto cleanup - only JS-dependent functions remain
    // Simplified auto cleanup - most functionality moved to CSS
    function setupAutoCleanup() {
        autoCleanupObserver = new MutationObserver(() => {
            if (autoLoadEnabled) {
                return;
            }
            replaceSpecificEdit();
            addEditNumberingLocal();
            legacyBrowserFallbacks();
        });

        function replaceSpecificEdit() {
            autoCleanupObserver.disconnect();
            document.querySelectorAll('.EhpEb').forEach(item => {
                const mediumEl = item.querySelector('.fontBodyMedium.JjQyvd.TqOXoe');
                const smallEl = item.querySelectorAll('.BjkJBb')[0]?.children[1];
                if (mediumEl && smallEl) {
                    const texts = Array.from(
                        mediumEl.querySelectorAll('.NlVald.xMSdlb')
                    ).map(el => el.textContent.trim());
                    smallEl.textContent = texts.join(', ');
                }
            });
            autoCleanupObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        function addEditNumberingLocal() {
            autoCleanupObserver.disconnect();
            addEditNumbering();
            autoCleanupObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        // Only needed for browsers that don't support :has() selector
        function legacyBrowserFallbacks() {
            if (!CSS.supports('selector(*:has(*))')) {
                // Fallback for hiding symbol parents
                document.querySelectorAll('.MaIKSd.google-symbols.G47vBd').forEach(el => {
                    const p = el.parentElement;
                    if (p && !p.classList.contains('gmee-symbol-parent')) {
                        p.classList.add('gmee-symbol-parent');
                    }
                });

                // Fallback for status-based colored borders
                document.querySelectorAll('.EhpEb').forEach(item => {
                    // Remove old status classes
                    item.classList.remove('gmee-status-accepted', 'gmee-status-pending',
                        'gmee-status-not-accepted', 'gmee-status-incorrect');

                    // Add appropriate status class
                    if (item.querySelector('.cLk0Bb')) {
                        item.classList.add('gmee-status-accepted');
                    } else if (item.querySelector('.UgJ9Rc')) {
                        item.classList.add('gmee-status-pending');
                    } else if (item.querySelector('.ehaAif')) {
                        item.classList.add('gmee-status-not-accepted');
                    } else if (item.querySelector('.gZbGnf')) {
                        item.classList.add('gmee-status-incorrect');
                    }
                });
            }
        }

        // Initial pass
        replaceSpecificEdit();
        addEditNumberingLocal();
        legacyBrowserFallbacks();

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

    // Update edit numbering based on visible items
    function updateEditNumbering() {
        if (!editsContainer || !numberingEnabled) return;

        const allItems = Array.from(editsContainer.children);
        let visibleIndex = 1;

        allItems.forEach(item => {
            const wrap = item.querySelector('.qjoALb');
            const numberElement = wrap?.querySelector('.edit-number');

            if (getComputedStyle(item).display !== 'none') {
                // Item is visible, update number
                if (numberElement) {
                    numberElement.textContent = visibleIndex;
                    numberElement.classList.remove('hidden');
                }
                visibleIndex++;
            } else {
                // Item is hidden, hide number
                if (numberElement) {
                    numberElement.classList.add('hidden');
                }
            }
        });
    }

    // Toggle edit numbering on/off
    function toggleEditNumbering() {
        numberingEnabled = !numberingEnabled;
        saveNumberingPreference(); // Save to localStorage

        // Update all existing numbers
        addEditNumbering();
        updateEditNumbering();

        // Update toggle button text
        const toggleBtn = document.querySelector('.toggle-numbering-btn');
        if (toggleBtn) {
            toggleBtn.textContent = numberingEnabled ? 'Hide Numbers' : 'Show Numbers';
            toggleBtn.style.backgroundColor = numberingEnabled ? '#ea4335' : '#34a853';
        }

        // Update go-to-edit constraints
        updateGoToEditConstraints();
    }

    // --- filterEdits() ---
    function filterEdits() {
        if (!editsContainer) return;

        // Find scroll container if not found yet
        if (!scrollContainer) {
            scrollContainer = findScrollContainer();
        }

        if (scrollContainer) {
            scrollContainer.scrollTop = 0;
        }

        Array.from(editsContainer.children).forEach(item => {
            let visible = true;

            // If the item is still loading, always keep it visible to avoid premature filtering
            if (isEditItemLoading(item)) {
                item.style.display = '';
                return;
            }

            // status filter via CSS class
            if (currentStatusFilter) {
                const statusObj = STATUSES.find(s => s.name === currentStatusFilter);
                if (
                    !statusObj ||
                    !item.querySelector(`.${statusObj.className}`)
                ) {
                    visible = false;
                }
            }

            // type filter remains unchanged
            if (visible && currentTypeFilter) {
                const b = item.querySelectorAll('.BjkJBb')[0]?.children[1];
                if (!b) {
                    visible = false;
                } else {
                    const parts = b.textContent.split(',').map(p => p.trim());
                    if (!parts.includes(currentTypeFilter)) {
                        visible = false;
                    }
                }
            }

            // date filter
            if (visible && currentDateFilter) {
                const dateElement = item.querySelector('.fontBodySmall.eYfez');
                if (!dateElement) {
                    // If no date element exists yet, don't filter it out (content may still be loading)
                    visible = true;
                } else {
                    const dateText = dateElement.textContent.trim();
                    // If date text is empty or just whitespace, assume content is still loading
                    if (!dateText || dateText === '') {
                        visible = true;
                    } else {
                        if (!isDateInRange(dateText)) {
                            visible = false;
                        }
                    }
                }
            }

            item.style.display = visible ? '' : 'none';
        });

        // Update numbering after filtering
        updateEditNumbering();
    }

    // Update list item active states
    function updateActiveListItems() {
        // Update status list items
        if (statusList) {
            const statusItems = statusList.querySelectorAll('.filter-list-item');
            statusItems.forEach(item => {
                const isActive = item.dataset.status === currentStatusFilter;
                item.classList.toggle('active', isActive);
            });
        }

        // Update type list items
        if (typeList) {
            const typeItems = typeList.querySelectorAll('.filter-list-item');
            typeItems.forEach(item => {
                const isActive = item.dataset.type === currentTypeFilter;
                item.classList.toggle('active', isActive);
            });
        }
    }

    // make an element draggable by its header
    function makeDraggable(el, handleSelector) {
        const handle = el.querySelector(handleSelector);
        if (!handle) return;
        handle.style.cursor = 'move';
        let offsetX = 0,
            offsetY = 0;

        handle.addEventListener('pointerdown', e => {
            const r = el.getBoundingClientRect();
            el.style.left = `${r.left}px`;
            el.style.top = `${r.top}px`;
            el.style.right = 'auto';
            el.style.transform = 'none';
            offsetX = e.clientX - r.left;
            offsetY = e.clientY - r.top;
            el.setPointerCapture(e.pointerId);
            e.preventDefault();
        });

        el.addEventListener('pointermove', e => {
            if (!el.hasPointerCapture(e.pointerId)) return;
            el.style.left = `${e.clientX - offsetX}px`;
            el.style.top = `${e.clientY - offsetY}px`;
        });
        ['pointerup', 'pointercancel'].forEach(evt => {
            el.addEventListener(evt, e => {
                if (el.hasPointerCapture(e.pointerId)) {
                    el.releasePointerCapture(e.pointerId);
                }
            });
        });
    }

    function updateButtonsAndStats() {
        // find scroll container if not found yet
        if (!scrollContainer) {
            scrollContainer = findScrollContainer();
        }

        // grab only those items not hidden by filterEdits()
        const visibleItems = Array.from(editsContainer.children)
            .filter(item => getComputedStyle(item).display !== 'none');

        // --- STATUS COUNTS based on visibleItems ---
        const sCounts = {};
        STATUSES.forEach(s => {
            sCounts[s.name] = 0;
        });
        visibleItems.forEach(item => {
            STATUSES.forEach(s => {
                if (item.querySelector(`.${s.className}`)) {
                    sCounts[s.name]++;
                }
            });
        });

        const total = Object.values(sCounts).reduce((a, b) => a + b, 0);
        statsDiv.textContent = `Total edits: ${total}`;

        // Update status list
        updateStatusList(sCounts);

        // --- TYPE COUNTS based on visibleItems ---
        const typeCounts = {};
        visibleItems.forEach(item => {
            const b = item.querySelectorAll('.BjkJBb')[0]?.children[1];
            if (!b) return;
            b.textContent.split(',').forEach(part => {
                const txt = part.trim();
                if (!txt) return;
                typeCounts[txt] = (typeCounts[txt] || 0) + 1;
            });
        });

        // Update type list
        updateTypeList(typeCounts);

        // Update date filter display
        updateDateFilterDisplay();

        // Update date input constraints based on available edits
        updateDateInputConstraints();

        // Update go-to-edit constraints
        updateGoToEditConstraints();

        // Update edit numbering
        updateEditNumbering();

        // auto-scroll if needed
        if (autoLoadEnabled && scrollContainer) {
            scrollContainer.scrollTop = scrollContainer.scrollHeight;
        }

        updateActiveListItems();
    }

    // Update status list
    function updateStatusList(sCounts) {
        if (!statusList) return;

        // Clear existing items
        statusList.innerHTML = '';

        STATUSES.forEach(s => {
            const count = sCounts[s.name] || 0;
            if (count > 0) {
                const listItem = document.createElement('li');
                listItem.className = 'filter-list-item';
                listItem.dataset.status = s.name;

                const statusIndicator = document.createElement('div');
                statusIndicator.className = 'status-indicator';
                statusIndicator.style.backgroundColor = s.color;

                const nameSpan = document.createElement('span');
                nameSpan.textContent = s.name;

                const countSpan = document.createElement('span');
                countSpan.className = 'filter-count';
                countSpan.textContent = count;

                listItem.appendChild(statusIndicator);
                listItem.appendChild(nameSpan);
                listItem.appendChild(countSpan);

                listItem.addEventListener('click', () => {
                    currentStatusFilter = currentStatusFilter === s.name ? null : s.name;
                    filterEdits();
                    updateButtonsAndStats();
                });

                statusList.appendChild(listItem);
            }
        });
    }

    // Update type list
    function updateTypeList(typeCounts) {
        if (!typeList) return;

        // Clear existing items
        typeList.innerHTML = '';

        Object.entries(typeCounts).forEach(([type, count]) => {
            if (count > 0) {
                const listItem = document.createElement('li');
                listItem.className = 'filter-list-item';
                listItem.dataset.type = type;

                const nameSpan = document.createElement('span');
                nameSpan.textContent = type;

                const countSpan = document.createElement('span');
                countSpan.className = 'filter-count';
                countSpan.textContent = count;

                listItem.appendChild(nameSpan);
                listItem.appendChild(countSpan);

                listItem.addEventListener('click', () => {
                    currentTypeFilter = currentTypeFilter === type ? null : type;
                    filterEdits();
                    updateButtonsAndStats();
                });

                typeList.appendChild(listItem);
            }
        });
    }

    // Update date filter display
    function updateDateFilterDisplay() {
        const dateStatus = dateContainer.querySelector('.date-status');
        if (dateStatus) {
            if (currentDateFilter) {
                const startDate = currentDateFilter.toLocaleDateString();
                if (currentDateRangeEnd) {
                    const endDate = currentDateRangeEnd.toLocaleDateString();
                    dateStatus.textContent = `Filtering: ${startDate} - ${endDate}`;
                } else {
                    dateStatus.textContent = `Filtering: ${startDate}`;
                }
                dateStatus.style.color = '#4285f4';
                dateStatus.style.fontWeight = 'bold';
            } else {
                dateStatus.textContent = 'No date filter active';
                dateStatus.style.color = '#666';
                dateStatus.style.fontWeight = 'normal';
            }
        }
    }

    // Clear date filter
    function clearDateFilter() {
        currentDateFilter = null;
        currentDateRangeEnd = null;
        filterEdits();
        updateButtonsAndStats();
    }

    // build the floating popup
    function createPopup() {
        popup = document.createElement('div');
        Object.assign(popup.style, {
            position: 'fixed',
            top: '10px',
            right: '10px',
            backgroundColor: '#fff',
            border: '1px solid #ccc',
            borderRadius: '6px',
            boxShadow: '0 2px 8px rgba(0,0,0,0.2)',
            padding: '10px',
            zIndex: '9999',
            textAlign: 'left',
            width: '280px'
        });

        // stats
        statsDiv = document.createElement('div');
        statsDiv.textContent = 'Total edits: 0';
        statsDiv.classList.add('drag-handle');
        statsDiv.style.marginBottom = '8px';
        popup.appendChild(statsDiv);

        // status header
        const statusHeader = document.createElement('div');
        statusHeader.textContent = 'Filter edits by status:';
        statusHeader.style.marginBottom = '4px';
        statusHeader.style.fontWeight = 'bold';
        popup.appendChild(statusHeader);

        // status list container
        btnContainer = document.createElement('div');
        btnContainer.style.marginBottom = '12px';

        statusList = document.createElement('ul');
        statusList.className = 'filter-list';
        btnContainer.appendChild(statusList);
        popup.appendChild(btnContainer);

        // type header
        const typeHeader = document.createElement('div');
        typeHeader.textContent = 'Filter edits by type:';
        typeHeader.style.marginBottom = '4px';
        typeHeader.style.fontWeight = 'bold';
        popup.appendChild(typeHeader);

        // type list container
        typeContainer = document.createElement('div');
        typeContainer.style.marginBottom = '12px';

        typeList = document.createElement('ul');
        typeList.className = 'filter-list';
        typeContainer.appendChild(typeList);
        popup.appendChild(typeContainer);

        // date header + container
        const dateHeader = document.createElement('div');
        dateHeader.textContent = 'Filter edits by date:';
        dateHeader.style.margin = '8px 0 4px';
        dateHeader.style.fontWeight = 'bold';
        popup.appendChild(dateHeader);

        dateContainer = document.createElement('div');

        // Date status display
        const dateStatus = document.createElement('div');
        dateStatus.className = 'date-status';
        dateStatus.textContent = 'No date filter active';
        dateStatus.style.cssText = `
            margin-bottom: 8px;
            font-size: 12px;
            color: #666;
        `;
        dateContainer.appendChild(dateStatus);

        // Date input container
        const dateInputContainer = document.createElement('div');
        dateInputContainer.style.cssText = `
            display: flex;
            flex-direction: column;
            gap: 4px;
            margin-bottom: 8px;
        `;

        // Start date input
        const startDateInput = document.createElement('input');
        startDateInput.type = 'date';
        startDateInput.style.cssText = `
            padding: 4px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 12px;
        `;
        startDateInput.addEventListener('change', () => {
            if (startDateInput.value) {
                const selectedDate = new Date(startDateInput.value + 'T00:00:00');
                const today = new Date();
                today.setHours(23, 59, 59, 999); // End of today

                // Validate date is not in the future
                if (selectedDate > today) {
                    alert('Cannot select a future date');
                    startDateInput.value = '';
                    return;
                }

                // Validate date is within available edit range
                const dateRange = getEditDateRange();
                if (dateRange.hasEdits && (selectedDate < dateRange.min || selectedDate > dateRange.max)) {
                    alert(`Please select a date between ${dateRange.min.toLocaleDateString()} and ${dateRange.max.toLocaleDateString()}`);
                    startDateInput.value = '';
                    return;
                }

                currentDateFilter = selectedDate;
                // If end date is set and start > end, clear end date
                if (currentDateRangeEnd && currentDateFilter > currentDateRangeEnd) {
                    currentDateRangeEnd = null;
                    endDateInput.value = '';
                }
                filterEdits();
                updateButtonsAndStats();
            } else {
                currentDateFilter = null;
                currentDateRangeEnd = null;
                filterEdits();
                updateButtonsAndStats();
            }
        });

        // End date input (for range selection)
        const endDateInput = document.createElement('input');
        endDateInput.type = 'date';
        endDateInput.placeholder = 'End date (optional)';
        endDateInput.style.cssText = `
            padding: 4px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 12px;
        `;
        endDateInput.addEventListener('change', () => {
            if (endDateInput.value) {
                const selectedDate = new Date(endDateInput.value + 'T23:59:59');
                const today = new Date();
                today.setHours(23, 59, 59, 999); // End of today

                // Validate date is not in the future
                if (selectedDate > today) {
                    alert('Cannot select a future date');
                    endDateInput.value = '';
                    return;
                }

                // Validate date is within available edit range
                const dateRange = getEditDateRange();
                if (dateRange.hasEdits && (selectedDate < dateRange.min || selectedDate > dateRange.max)) {
                    alert(`Please select a date between ${dateRange.min.toLocaleDateString()} and ${dateRange.max.toLocaleDateString()}`);
                    endDateInput.value = '';
                    return;
                }

                if (currentDateFilter && selectedDate >= currentDateFilter) {
                    currentDateRangeEnd = selectedDate;
                } else if (!currentDateFilter) {
                    // If no start date, set both to same date
                    currentDateFilter = new Date(endDateInput.value + 'T00:00:00');
                    currentDateRangeEnd = selectedDate;
                    startDateInput.value = endDateInput.value;
                } else {
                    // End date is before start date, swap them
                    currentDateRangeEnd = currentDateFilter;
                    currentDateFilter = new Date(endDateInput.value + 'T00:00:00');
                    startDateInput.value = endDateInput.value;
                }
                filterEdits();
                updateButtonsAndStats();
            } else {
                currentDateRangeEnd = null;
                filterEdits();
                updateButtonsAndStats();
            }
        });

        // Labels and inputs
        const startLabel = document.createElement('label');
        startLabel.textContent = 'Start date:';
        startLabel.style.fontSize = '12px';

        const endLabel = document.createElement('label');
        endLabel.textContent = 'End date (optional):';
        endLabel.style.fontSize = '12px';

        dateInputContainer.appendChild(startLabel);
        dateInputContainer.appendChild(startDateInput);
        dateInputContainer.appendChild(endLabel);
        dateInputContainer.appendChild(endDateInput);

        // Quick date buttons
        const quickDateContainer = document.createElement('div');
        quickDateContainer.style.cssText = `
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            margin-bottom: 8px;
        `;

        const quickDates = [{
                name: 'Today',
                days: 0
            },
            {
                name: 'Yesterday',
                days: 1
            },
            {
                name: 'Last 7 days',
                days: 7
            },
            {
                name: 'Last 30 days',
                days: 30
            }
        ];

        quickDates.forEach(({
            name,
            days
        }) => {
            const btn = document.createElement('button');
            btn.textContent = name;
            btn.className = 'quick-date-btn';
            btn.style.cssText = `
                background: #f0f0f0;
                border: 1px solid #ccc;
                border-radius: 4px;
                padding: 4px 8px;
                font-size: 11px;
                cursor: pointer;
                flex: 1;
            `;
            btn.addEventListener('click', () => {
                // Check if we have edits available
                const dateRange = getEditDateRange();
                if (!dateRange.hasEdits) {
                    alert('No edits available for date filtering');
                    return;
                }

                const now = new Date();
                if (days === 0) {
                    // Today only - check if we have edits for today
                    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
                    if (today < dateRange.min || today > dateRange.max) {
                        alert('No edits available for today');
                        return;
                    }
                    currentDateFilter = today;
                    currentDateRangeEnd = null;
                    startDateInput.value = currentDateFilter.toISOString().split('T')[0];
                    endDateInput.value = '';
                } else {
                    // Range from X days ago to today
                    let startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - days + 1);
                    const endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());

                    // Adjust start date if it's before our earliest edit
                    if (startDate < dateRange.min) {
                        startDate = dateRange.min;
                    }

                    // Check if the range contains any edits
                    if (startDate > dateRange.max) {
                        alert(`No edits available in the last ${days} days`);
                        return;
                    }

                    currentDateFilter = startDate;
                    currentDateRangeEnd = endDate;
                    startDateInput.value = startDate.toISOString().split('T')[0];
                    endDateInput.value = endDate.toISOString().split('T')[0];
                }
                filterEdits();
                updateButtonsAndStats();
            });
            quickDateContainer.appendChild(btn);
        });

        // Clear button
        const clearBtn = document.createElement('button');
        clearBtn.textContent = 'Clear Filter';
        clearBtn.className = 'clear-date-btn';
        clearBtn.style.cssText = `
            background: #dc362e;
            border: none;
            border-radius: 4px;
            color: white;
            padding: 6px 12px;
            font-size: 12px;
            cursor: pointer;
            width: 100%;
        `;
        clearBtn.addEventListener('click', () => {
            startDateInput.value = '';
            endDateInput.value = '';
            clearDateFilter();
        });

        dateContainer.appendChild(dateInputContainer);
        dateContainer.appendChild(quickDateContainer);
        dateContainer.appendChild(clearBtn);
        popup.appendChild(dateContainer);

        // Go to edit number section
        const goToEditHeader = document.createElement('div');
        goToEditHeader.textContent = 'Go to edit number:';
        goToEditHeader.style.margin = '8px 0 4px';
        goToEditHeader.style.fontWeight = 'bold';
        popup.appendChild(goToEditHeader);

        const goToEditContainer = document.createElement('div');
        goToEditContainer.className = 'go-to-edit-container';

        const goToEditInput = document.createElement('input');
        goToEditInput.type = 'number';
        goToEditInput.className = 'go-to-edit-input';
        goToEditInput.placeholder = 'Edit #';
        goToEditInput.min = 1;
        goToEditInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                const targetNumber = parseInt(goToEditInput.value);
                if (targetNumber) {
                    goToEditNumber(targetNumber);
                    goToEditInput.value = '';
                }
            }
        });

        const goToEditBtn = document.createElement('button');
        goToEditBtn.textContent = 'Go';
        goToEditBtn.className = 'go-to-edit-btn';
        goToEditBtn.addEventListener('click', () => {
            const targetNumber = parseInt(goToEditInput.value);
            if (targetNumber) {
                goToEditNumber(targetNumber);
                goToEditInput.value = '';
            }
        });

        goToEditContainer.appendChild(goToEditInput);
        goToEditContainer.appendChild(goToEditBtn);
        popup.appendChild(goToEditContainer);

        // Edit numbering controls
        const numberingHeader = document.createElement('div');
        numberingHeader.textContent = 'Options: ';
        numberingHeader.style.margin = '8px 0 4px';
        numberingHeader.style.fontWeight = 'bold';
        popup.appendChild(numberingHeader);

        const numberingContainer = document.createElement('div');
        numberingContainer.style.marginBottom = '8px';

        const toggleBtn = document.createElement('button');
        toggleBtn.textContent = numberingEnabled ? 'Hide Numbers' : 'Show Numbers';
        toggleBtn.className = 'toggle-numbering-btn';
        toggleBtn.style.cssText = `
            background: ${numberingEnabled ? '#ea4335' : '#34a853'};
            border: none;
            border-radius: 4px;
            color: white;
            padding: 6px 12px;
            font-size: 12px;
            cursor: pointer;
            width: 100%;
        `;
        toggleBtn.addEventListener('click', toggleEditNumbering);

        // auto-load button

        const autoLoadBtn = document.createElement('button');
        autoLoadBtn.textContent = autoLoadEnabled ? 'Disable Auto Load' : 'Enable Auto Load';
        autoLoadBtn.className = 'toggle-autoload-btn';
        autoLoadBtn.style.cssText = `
            background: ${autoLoadEnabled ? '#ea4335' : '#34a853'};
            border: none;
            border-radius: 4px;
            color: white;
            padding: 6px 12px;
            font-size: 12px;
            cursor: pointer;
            width: 100%;
            margin-bottom: 8px;
        `;
        autoLoadBtn.addEventListener('click', toggleAutoLoad);

        numberingContainer.appendChild(autoLoadBtn);
        numberingContainer.appendChild(toggleBtn);

        popup.appendChild(numberingContainer);

        document.body.appendChild(popup);
        makeDraggable(popup, '.drag-handle');
    }

    // Updated function to watch for container with better retry logic
    function watchForContainer() {
        let retryCount = 0;
        const maxRetries = 30; // Try for 30 seconds
        const retryDelay = 1000; // 1 second intervals

        function trySetup() {
            console.log(`Attempting to find edits container (attempt ${retryCount + 1}/${maxRetries})`);

            const edits = findEditsContainer();
            if (!edits) {
                retryCount++;
                if (retryCount < maxRetries) {
                    setTimeout(trySetup, retryDelay);
                } else {
                    console.warn('Could not find edits container after maximum retries');
                }
                return false;
            }

            console.log('Found edits container:', edits);
            editsContainer = edits;

            // Find scroll container
            scrollContainer = findScrollContainer();
            if (scrollContainer) {
                console.log('Found scroll container:', scrollContainer);
            }

            updateButtonsAndStats();
            if (currentStatusFilter || currentTypeFilter || currentDateFilter) {
                filterEdits();
            }

            containerObserver = new MutationObserver(() => {
                updateButtonsAndStats();
                if (currentStatusFilter || currentTypeFilter || currentDateFilter) {
                    filterEdits();
                }
            });
            containerObserver.observe(editsContainer, {
                childList: true
            });
            return true;
        }

        trySetup();
    }

    function waitForElementAndClick(className, index = 0) {
        const checkForElement = () => {
            const elements = document.getElementsByClassName(className);

            if (elements.length > index) {
                elements[index].click();
                console.log(`Clicked element: ${className}[${index}]`);
                return;
            }

            setTimeout(checkForElement, 1000); // Check again in 1 second
        };

        checkForElement();
    }

    function checkInitState() {
        if (window.location.href.includes("/contrib/") && !window.location.href.includes("/photos/") && !window.location.href.includes("/answers/") && !window.location.href.includes("/reviews/") && !window.location.href.includes("/contribute/")) {
            if (isInit === false) {
                console.log('Initializing Google Maps Enhanced Edits UI');
                isInit = true;
                createPopup();
                setupAutoCleanup();
                watchForContainer();
            }
        } else {
            // Not on edits page anymore, deinitialize
            if (isInit === true) {
                deinitializeEditsUI();
            }
        }

        if (isEventHandlersInit === false) {
            isEventHandlersInit = true;
            waitForElementAndClick("okDpye PpaGLb", 1);
        }
    }

    document.addEventListener("DOMContentLoaded", function() {
        var bodyList = document.querySelector('body');

        var observer = new MutationObserver(function(mutations) {
            if (oldHref != document.location.href) {
                oldHref = document.location.href;
                checkInitState();
            }
        });

        var config = {
            childList: true,
            subtree: true
        };

        observer.observe(bodyList, config);
        // Check on window load
        checkInitState();
    });
})();