WME Multi Map Overlay

Erweiterte Version mit TopPlus, Dark Map, Basemap.de und allen DACH Geoportal Overlays - MIT GEO-LOKALISIERUNG

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name WME Multi Map Overlay
// @namespace https://greasyfork.org/de/users/863740-horst-wittlich
// @version 2025.12.07
// @description Erweiterte Version mit TopPlus, Dark Map, Basemap.de und allen DACH Geoportal Overlays - MIT GEO-LOKALISIERUNG
// @author Hiwi234
// @match https://www.waze.com/editor*
// @match https://www.waze.com/*/editor*
// @match https://beta.waze.com/editor*
// @match https://beta.waze.com/*/editor*
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_info
// @connect sgx.geodatenzentrum.de
// @connect owsproxy.lgl-bw.de
// @connect www.wmts.nrw.de
// @connect geoservices.bayern.de
// @connect mapsneu.wien.gv.at
// @connect basemap.at
// @connect wmts.geo.admin.ch
// @connect www.geoportal.hessen.de
// @connect www.gds-srv.hessen.de
// @connect cdnjs.cloudflare.com
// @connect a.tile.openstreetmap.org
// @connect b.tile.openstreetmap.org
// @connect c.tile.openstreetmap.org
// @connect a.basemaps.cartocdn.com
// @connect b.basemaps.cartocdn.com
// @connect c.basemaps.cartocdn.com
// @connect a.tile.opentopomap.org
// @connect b.tile.opentopomap.org
// @connect c.tile.opentopomap.org
// @connect opendata.lgln.niedersachsen.de
// @connect www.gds-srv.hessen.de
// @connect gdi.berlin.de
// @connect isk.geobasis-bb.de
// @connect geodienste.hamburg.de
// @connect www.geodaten-mv.de
// @connect geo5.service24.rlp.de
// @connect geoportal.saarland.de
// @connect geodienste.sachsen.de
// @connect www.geodatenportal.sachsen-anhalt.de
// @connect dienste.gdi-sh.de
// @connect www.geoproxy.geoportal-th.de
// @license MIT
// ==/UserScript==

(function() {
'use strict';

const SCRIPT_NAME = 'WME Multi Overlay';
const SCRIPT_ID = 'wme-multi-overlay';
const DEFAULT_OPACITY = 0.64;
const DEFAULT_ZINDEX = 2010;
const STORAGE_KEY = 'wme-overlay-settings';
const COLLAPSED_STATE_KEY = 'wme-overlay-collapsed-groups';
const GEO_FILTER_KEY = 'wme-overlay-geo-filter-enabled';

// Layer storage
const layers = {};
const layerMetadata = {};
let collapsedGroups = {};

// Layer-Status-Tracking
const layerStatus = {};  // { layerId: { status: 'ok'|'loading'|'error'|'offline', message: '', retries: 0 } }
const MAX_RETRIES = 3;
const RETRY_DELAY = 5000; // 5 Sekunden

// Globaler Ein/Aus-Schalter
let scriptEnabled = true;
const ENABLED_KEY = 'wme-overlay-enabled';

// ============================================
// GEO-LOKALISIERUNG SYSTEM
// ============================================

// Geo-Filter aktiviert/deaktiviert
let geoFilterEnabled = true;

// Aktuelle erkannte Region
let currentRegion = {
    country: null,      // 'DE', 'AT', 'CH' oder null
    state: null,        // Bundesland-Code (z.B. 'BY', 'NW', 'HE') oder null
    stateName: null     // Voller Name des Bundeslandes
};

// Mapping von WME State-Namen zu Bundesland-Codes
const stateNameToCode = {
    // Deutschland
    'Baden-Württemberg': 'BW',
    'Bayern': 'BY',
    'Berlin': 'BE',
    'Brandenburg': 'BB',
    'Bremen': 'HB',
    'Hamburg': 'HH',
    'Hessen': 'HE',
    'Mecklenburg-Vorpommern': 'MV',
    'Niedersachsen': 'NDS',
    'Nordrhein-Westfalen': 'NW',
    'Rheinland-Pfalz': 'RP',
    'Saarland': 'SL',
    'Sachsen': 'SN',
    'Sachsen-Anhalt': 'ST',
    'Schleswig-Holstein': 'SH',
    'Thüringen': 'TH',
    // Englische Varianten
    'Bavaria': 'BY',
    'Lower Saxony': 'NDS',
    'North Rhine-Westphalia': 'NW',
    'Rhineland-Palatinate': 'RP',
    'Saxony': 'SN',
    'Saxony-Anhalt': 'ST',
    'Thuringia': 'TH',
    'Mecklenburg-Western Pomerania': 'MV'
};

// Mapping von Länder-Namen zu Codes
const countryNameToCode = {
    'Germany': 'DE',
    'Deutschland': 'DE',
    'Austria': 'AT',
    'Österreich': 'AT',
    'Switzerland': 'CH',
    'Schweiz': 'CH',
    'Suisse': 'CH',
    'Svizzera': 'CH'
};

// Layer-Regionen-Zuordnung
const layerRegions = {
    // Basis Layer - überall in DACH verfügbar
    'basemap-de': { countries: ['DE'] },
    'basemap-de-grau': { countries: ['DE'] },
    'topplus': { countries: ['DE'] },
    'topplus-grau': { countries: ['DE'] },

    // Liegenschaftskarten - bundeslandspezifisch
    'alkis-by': { countries: ['DE'], states: ['BY'] },
    'alkis-be': { countries: ['DE'], states: ['BE'] },
    'alkis-bw': { countries: ['DE'], states: ['BW'] },
    'alkis-bb': { countries: ['DE'], states: ['BB'] },
    'alkis-hb': { countries: ['DE'], states: ['HB', 'NDS'] }, // Bremen nutzt NDS-Server
    'alkis-hh': { countries: ['DE'], states: ['HH'] },
    'alkis-he': { countries: ['DE'], states: ['HE'] },
    'alkis-mv': { countries: ['DE'], states: ['MV'] },
    'alkis-nds': { countries: ['DE'], states: ['NDS', 'HB'] },
    'alkis-nw': { countries: ['DE'], states: ['NW'] },
    'alkis-nw-grau': { countries: ['DE'], states: ['NW'] },
    'alkis-rp': { countries: ['DE'], states: ['RP'] },
    'alkis-sl': { countries: ['DE'], states: ['SL'] },
    'alkis-sn': { countries: ['DE'], states: ['SN'] },
    'alkis-st': { countries: ['DE'], states: ['ST'] },
    'alkis-sh': { countries: ['DE'], states: ['SH'] },
    'alkis-th': { countries: ['DE'], states: ['TH'] },

    // GeoOverlays DE - bundeslandspezifisch
    'geoportal-nrw': { countries: ['DE'], states: ['NW'] },
    'geoportal-nrw-overlay': { countries: ['DE'], states: ['NW'] },
    'geoportal-by': { countries: ['DE'], states: ['BY'] },
    'dop-nrw': { countries: ['DE'], states: ['NW'] },
    'dop-by': { countries: ['DE'], states: ['BY'] },
    'dop-nds': { countries: ['DE'], states: ['NDS', 'HB'] },
    'vg25-de': { countries: ['DE'] },
    'vg25-li-de': { countries: ['DE'] },
    'truedop-hessen': { countries: ['DE'], states: ['HE'] },

    // Österreich
    'basemap-at': { countries: ['AT'] },
    'overlay-at': { countries: ['AT'] },

    // Schweiz
    'swiss-strassen': { countries: ['CH'] },
    'swiss-basis': { countries: ['CH'] },
    'swiss-luft': { countries: ['CH'] },

    // Nicht amtliche Karten - überall verfügbar
    'osm-standard': { countries: ['DE', 'AT', 'CH'], global: true },
    'darkmap': { countries: ['DE', 'AT', 'CH'], global: true },
    'opentopomap': { countries: ['DE', 'AT', 'CH'], global: true }
};

// Ermittle aktuelle Region aus WME
function detectCurrentRegion() {
    try {
        // Methode 1: Über W.model.getTopCountry() und W.model.getTopState()
        if (W && W.model) {
            const topCountry = W.model.getTopCountry && W.model.getTopCountry();
            const topState = W.model.getTopState && W.model.getTopState();

            if (topCountry) {
                const countryName = topCountry.name || topCountry.attributes?.name;
                currentRegion.country = countryNameToCode[countryName] || null;
            }

            if (topState) {
                const stateName = topState.name || topState.attributes?.name;
                currentRegion.stateName = stateName;
                currentRegion.state = stateNameToCode[stateName] || null;
            }
        }

        // Methode 2: Fallback über Kartenzentrums-Koordinaten
        if (!currentRegion.country && W && W.map) {
            const center = W.map.getCenter();
            if (center) {
                // Grobe Koordinaten-basierte Erkennung
                const lon = center.lon;
                const lat = center.lat;

                // Transformiere von Web Mercator zu WGS84 falls nötig
                let wgs84Lon = lon, wgs84Lat = lat;
                if (Math.abs(lon) > 180 || Math.abs(lat) > 90) {
                    // Web Mercator -> WGS84
                    wgs84Lon = (lon / 20037508.34) * 180;
                    wgs84Lat = (Math.atan(Math.exp(lat * Math.PI / 20037508.34)) * 360 / Math.PI) - 90;
                }

                // Grobe Ländererkennung basierend auf Koordinaten
                if (wgs84Lon >= 5.8 && wgs84Lon <= 15.1 && wgs84Lat >= 47.2 && wgs84Lat <= 55.1) {
                    currentRegion.country = 'DE';
                    // Grobe Bundesland-Erkennung
                    currentRegion.state = detectGermanStateByCoords(wgs84Lon, wgs84Lat);
                } else if (wgs84Lon >= 9.5 && wgs84Lon <= 17.2 && wgs84Lat >= 46.3 && wgs84Lat <= 49.0) {
                    currentRegion.country = 'AT';
                } else if (wgs84Lon >= 5.9 && wgs84Lon <= 10.5 && wgs84Lat >= 45.8 && wgs84Lat <= 47.8) {
                    currentRegion.country = 'CH';
                }
            }
        }

        return currentRegion;
    } catch (error) {
        console.warn(SCRIPT_NAME + ': Fehler bei Region-Erkennung:', error);
        return currentRegion;
    }
}

// Grobe Bundesland-Erkennung basierend auf Koordinaten
function detectGermanStateByCoords(lon, lat) {
    // Vereinfachte Bounding Boxes für deutsche Bundesländer
    const stateBounds = {
        'SH': { minLon: 8.3, maxLon: 11.4, minLat: 53.3, maxLat: 55.1 },
        'HH': { minLon: 9.7, maxLon: 10.3, minLat: 53.4, maxLat: 53.7 },
        'MV': { minLon: 10.6, maxLon: 14.5, minLat: 53.1, maxLat: 54.7 },
        'HB': { minLon: 8.5, maxLon: 9.0, minLat: 53.0, maxLat: 53.6 },
        'NDS': { minLon: 6.6, maxLon: 11.6, minLat: 51.3, maxLat: 53.9 },
        'BE': { minLon: 13.1, maxLon: 13.8, minLat: 52.3, maxLat: 52.7 },
        'BB': { minLon: 11.3, maxLon: 14.8, minLat: 51.4, maxLat: 53.6 },
        'ST': { minLon: 10.5, maxLon: 13.2, minLat: 50.9, maxLat: 53.0 },
        'NW': { minLon: 5.8, maxLon: 9.5, minLat: 50.3, maxLat: 52.6 },
        'HE': { minLon: 7.8, maxLon: 10.3, minLat: 49.4, maxLat: 51.7 },
        'TH': { minLon: 9.9, maxLon: 12.7, minLat: 50.2, maxLat: 51.6 },
        'SN': { minLon: 11.9, maxLon: 15.1, minLat: 50.2, maxLat: 51.7 },
        'RP': { minLon: 6.1, maxLon: 8.5, minLat: 48.9, maxLat: 50.9 },
        'SL': { minLon: 6.4, maxLon: 7.4, minLat: 49.1, maxLat: 49.7 },
        'BW': { minLon: 7.5, maxLon: 10.5, minLat: 47.5, maxLat: 49.8 },
        'BY': { minLon: 8.9, maxLon: 13.9, minLat: 47.3, maxLat: 50.6 }
    };

    // Prüfe jedes Bundesland (Reihenfolge wichtig für überlappende Bereiche)
    const checkOrder = ['BE', 'HH', 'HB', 'SL', 'SH', 'MV', 'BB', 'ST', 'TH', 'SN', 'NW', 'HE', 'RP', 'BW', 'BY', 'NDS'];

    for (const state of checkOrder) {
        const bounds = stateBounds[state];
        if (lon >= bounds.minLon && lon <= bounds.maxLon &&
            lat >= bounds.minLat && lat <= bounds.maxLat) {
            return state;
        }
    }

    return null;
}

// Prüfe ob ein Layer für die aktuelle Region relevant ist
function isLayerRelevantForRegion(layerId) {
    // Wenn Geo-Filter deaktiviert, zeige alle Layer
    if (!geoFilterEnabled) return true;

    const regionConfig = layerRegions[layerId];

    // Wenn keine Region-Config, zeige Layer immer
    if (!regionConfig) return true;

    // Globale Layer immer anzeigen
    if (regionConfig.global) return true;

    // Prüfe Land
    if (regionConfig.countries && currentRegion.country) {
        if (!regionConfig.countries.includes(currentRegion.country)) {
            return false;
        }
    }

    // Prüfe Bundesland (nur wenn definiert)
    if (regionConfig.states && currentRegion.state) {
        if (!regionConfig.states.includes(currentRegion.state)) {
            return false;
        }
    } else if (regionConfig.states && !currentRegion.state) {
        // Wenn Layer bundeslandspezifisch ist aber kein Bundesland erkannt wurde,
        // zeige Layer trotzdem an (bessere UX)
        return true;
    }

    return true;
}

// Speichere Geo-Filter-Einstellung
function saveGeoFilterState() {
    try {
        localStorage.setItem(GEO_FILTER_KEY, JSON.stringify(geoFilterEnabled));
    } catch (e) {}
}

// Lade Geo-Filter-Einstellung
function loadGeoFilterState() {
    try {
        const saved = localStorage.getItem(GEO_FILTER_KEY);
        if (saved !== null) {
            geoFilterEnabled = JSON.parse(saved);
        }
    } catch (e) {
        geoFilterEnabled = true;
    }
}

// ============================================
// ENDE GEO-LOKALISIERUNG SYSTEM
// ============================================

function updateAllLayersVisibilityFromEnabled() {
    const settings = loadSettings();
    Object.keys(layers).forEach(layerId => {
        const layer = layers[layerId];
        if (!layer) return;
        const layerSettings = (settings.layers || {})[layerId] || {};
        const visible = !!layerSettings.visible;
        layer.setVisibility(scriptEnabled && visible);
    });
}

function setScriptEnabled(enabled, silent = false) {
    scriptEnabled = !!enabled;
    try { localStorage.setItem(ENABLED_KEY, JSON.stringify(scriptEnabled)); } catch (e) {}
    updateAllLayersVisibilityFromEnabled();
    const btn = document.getElementById('wme-overlay-toggle-btn');
    if (btn) {
        btn.textContent = scriptEnabled ? '🟢 Overlays AN' : '🔴 Overlays AUS';
        btn.setAttribute('aria-pressed', String(scriptEnabled));
    }
    document.dispatchEvent(new CustomEvent('wme-overlay-enabled-changed', { detail: { enabled: scriptEnabled } }));
}

function loadEnabledState() {
    let saved = null;
    try { saved = localStorage.getItem(ENABLED_KEY); } catch (e) {}
    if (saved !== null) {
        try { setScriptEnabled(JSON.parse(saved), true); return; } catch (e) {}
    }
    setScriptEnabled(true, true);
}

function toggleScriptEnabled() {
    setScriptEnabled(!scriptEnabled);
}

function createGlobalToggleUI() {
    let layerSidebarCheckbox = null;

    function buildSideItem() {
        const item = document.createElement('wz-checkbox');
        item.id = 'wme-overlay-side-toggle';
        item.checked = scriptEnabled;
        item.textContent = 'Multi Map';

        item.addEventListener('change', () => {
            toggleScriptEnabled();
            updateLayerSidebarCheckboxState();
        });

        layerSidebarCheckbox = item;

        document.addEventListener('wme-overlay-enabled-changed', (ev) => {
            updateLayerSidebarCheckboxState();
        });

        return item;
    }

    function updateLayerSidebarCheckboxState() {
        if (layerSidebarCheckbox) {
            layerSidebarCheckbox.checked = scriptEnabled;
        }
    }

    function findRightPanelInsertionPoint() {
        const sat = Array.from(document.querySelectorAll('label,div,span,button'))
            .find(el => /^\s*Satellitenbild\s*$/i.test((el.textContent||'')));
        if (sat) return { parent: sat.parentElement, mode: 'after' };

        const otherHeader = Array.from(document.querySelectorAll('h3,h4,button,div'))
            .find(el => /\bAndere Daten\b|\bOther Data\b|\bOther layers\b/i.test((el.textContent||'')));
        if (otherHeader) {
            const section = otherHeader.closest('section') || otherHeader.parentElement;
            const list = section && (section.querySelector('ul') || section.querySelector('div[role="group"],div'));
            if (list) return { parent: list, mode: 'prepend' };
        }

        const rightPanel = document.querySelector('[aria-label="Karten-Ebenen"],[data-testid="layers-panel"],.layers-panel,.panel-right');
        if (rightPanel) return { parent: rightPanel, mode: 'append' };
        return null;
    }

    function mountInPanel() {
        const target = findRightPanelInsertionPoint();
        if (!target) return false;
        if (document.getElementById('wme-overlay-side-toggle')) return true;
        const item = buildSideItem();
        if (target.mode === 'after' && target.parent) {
            target.parent.insertAdjacentElement('afterend', item);
        } else if (target.mode === 'prepend' && target.parent) {
            target.parent.insertBefore(item, target.parent.firstChild);
        } else if (target.parent) {
            target.parent.appendChild(item);
        } else {
            return false;
        }
        return true;
    }

    const mounted = mountInPanel();

    if (!mounted) {
        const observer = new MutationObserver(() => {
            if (mountInPanel()) observer.disconnect();
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    document.addEventListener('keydown', (ev) => {
        if (ev.altKey && (ev.key === 'o' || ev.key === 'O')) {
            ev.preventDefault();
            toggleScriptEnabled();
            updateLayerSidebarCheckboxState();
        }
    });

    window.updateLayerSidebarCheckbox = updateLayerSidebarCheckboxState;
}

// Settings Management
function saveSettings() {
    const settings = {
        version: GM_info.script.version,
        layers: {}
    };

    Object.keys(layers).forEach(layerId => {
        const layer = layers[layerId];
        if (layer) {
            const metadata = layerMetadata[layerId] || {};
            settings.layers[layerId] = {
                visible: layer.getVisibility(),
                opacity: layer.opacity || DEFAULT_OPACITY,
                zIndex: metadata.zIndex || layer.getZIndex() || DEFAULT_ZINDEX
            };
        }
    });

    try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
    } catch (error) {
        console.error('Fehler beim Speichern der Settings:', error);
    }
}

function saveCollapsedState() {
    try {
        localStorage.setItem(COLLAPSED_STATE_KEY, JSON.stringify(collapsedGroups));
    } catch (error) {
        console.error('Fehler beim Speichern des Collapsed State:', error);
    }
}

function loadCollapsedState() {
    try {
        const saved = localStorage.getItem(COLLAPSED_STATE_KEY);
        if (saved) {
            collapsedGroups = JSON.parse(saved);
        }
    } catch (error) {
        console.error('Fehler beim Laden der Collapsed State:', error);
        collapsedGroups = {};
    }
}

function saveGlobalFilters() {
    try {
        localStorage.setItem('wme-overlay-global-filters', JSON.stringify(globalFilters));
    } catch (error) {
        console.error('Fehler beim Speichern der globalen Filter:', error);
    }
}

// ============================================
// LAYER-STATUS-SYSTEM
// ============================================

// Setze Layer-Status und aktualisiere UI
function setLayerStatus(layerId, status, message = '') {
    layerStatus[layerId] = layerStatus[layerId] || { status: 'ok', message: '', retries: 0 };
    layerStatus[layerId].status = status;
    layerStatus[layerId].message = message;

    // UI aktualisieren
    updateLayerStatusUI(layerId);
}

// Aktualisiere Status-Anzeige in der UI
function updateLayerStatusUI(layerId) {
    const statusEl = document.querySelector(`[data-layer-status="${layerId}"]`);
    if (!statusEl) return;

    const info = layerStatus[layerId];
    if (!info) {
        statusEl.style.display = 'none';
        return;
    }

    statusEl.style.display = 'inline-block';

    switch (info.status) {
        case 'loading':
            statusEl.innerHTML = '⏳';
            statusEl.title = 'Wird geladen...';
            statusEl.style.color = '#ff9800';
            break;
        case 'error':
            statusEl.innerHTML = '⚠️';
            statusEl.title = info.message || 'Fehler beim Laden';
            statusEl.style.color = '#f44336';
            break;
        case 'offline':
            statusEl.innerHTML = '📡';
            statusEl.title = info.message ? `${info.message} - Klicken zum erneuten Versuch` : 'Server nicht erreichbar - Klicken zum erneuten Versuch';
            statusEl.style.color = '#9e9e9e';
            statusEl.style.cursor = 'pointer';
            break;
        case 'retrying':
            const retries = info.retries || 0;
            statusEl.innerHTML = '🔄';
            statusEl.title = `Verbindungsversuch ${retries}/${MAX_RETRIES}...`;
            statusEl.style.color = '#ff9800';
            break;
        default:
            statusEl.style.display = 'none';
    }
}

// Zeige Toast-Benachrichtigung
function showLayerToast(message, type = 'info') {
    // Validiere Nachricht - zeige keine leeren oder unverständlichen Meldungen
    if (!message || message.trim().length === 0) {
        return; // Keine leeren Toasts
    }

    // Entferne alte Toasts
    const oldToast = document.querySelector('.layer-toast');
    if (oldToast) oldToast.remove();

    const toast = document.createElement('div');
    toast.className = 'layer-toast';

    const colors = {
        'error': { bg: '#ffebee', border: '#f44336', icon: '⚠️' },
        'warning': { bg: '#fff3e0', border: '#ff9800', icon: '⏳' },
        'success': { bg: '#e8f5e9', border: '#4caf50', icon: '✅' },
        'info': { bg: '#e3f2fd', border: '#2196f3', icon: 'ℹ️' }
    };
    const style = colors[type] || colors.info;

    toast.style.cssText = `
        position: fixed;
        bottom: 20px;
        right: 20px;
        background: ${style.bg};
        border: 1px solid ${style.border};
        border-left: 4px solid ${style.border};
        padding: 12px 16px;
        border-radius: 6px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.15);
        z-index: 10000;
        font-size: 13px;
        max-width: 300px;
        animation: slideIn 0.3s ease;
    `;

    toast.innerHTML = `${style.icon} ${message}`;
    document.body.appendChild(toast);

    // Auto-hide nach 5 Sekunden
    setTimeout(() => {
        toast.style.animation = 'slideOut 0.3s ease';
        setTimeout(() => toast.remove(), 300);
    }, 5000);
}

function loadGlobalFilters() {
    try {
        const saved = localStorage.getItem('wme-overlay-global-filters');
        if (saved) {
            const filters = JSON.parse(saved);
            globalFilters = { ...globalFilters, ...filters };
        }
    } catch (error) {
        console.error('Fehler beim Laden der globalen Filter:', error);
    }
}

function loadSettings() {
    try {
        const saved = localStorage.getItem(STORAGE_KEY);
        if (saved) {
            return JSON.parse(saved);
        }
    } catch (error) {
        console.error('Fehler beim Laden der Settings:', error);
    }
    return { layers: {} };
}

function applySettingsToLayer(layerId, layer) {
    const settings = loadSettings();
    const layerSettings = settings.layers[layerId];

    if (layerSettings) {
        if (!layerMetadata[layerId]) {
            layerMetadata[layerId] = {};
        }

        const shouldBeVisible = scriptEnabled && (layerSettings.visible || false);
        layer.setVisibility(shouldBeVisible);
        layer.setOpacity(layerSettings.opacity || DEFAULT_OPACITY);

        const zIndex = layerSettings.zIndex || DEFAULT_ZINDEX;
        layer.setZIndex(zIndex);
        layerMetadata[layerId].zIndex = zIndex;
    } else {
        if (!layerMetadata[layerId]) {
            layerMetadata[layerId] = {};
        }
        layer.setZIndex(DEFAULT_ZINDEX);
        layerMetadata[layerId].zIndex = DEFAULT_ZINDEX;
    }
}

// Filter-Updates
function updateAllLayerFilters() {
    const brightness = globalFilters.brightness;
    const contrast = globalFilters.contrast;
    const saturation = globalFilters.saturation;
    const sharpness = globalFilters.sharpness;

    let filterString = `brightness(${brightness}%) contrast(${contrast}%) saturate(${saturation}%)`;

    if (sharpness < 100) {
        const blurAmount = (100 - sharpness) / 100 * 2;
        filterString += ` blur(${blurAmount}px)`;
    } else if (sharpness > 100) {
        const extraContrast = 100 + (sharpness - 100) * 0.5;
        filterString += ` contrast(${extraContrast}%)`;
    }

    setTimeout(() => {
        const resetElems = document.querySelectorAll('#map canvas, #WazeMap canvas, .olLayerDiv');
        resetElems.forEach(el => {
            el.style.filter = '';
            el.style.webkitFilter = '';
        });

        Object.keys(layers).forEach(layerId => {
            const layer = layers[layerId];
            if (layer && layer.div) {
                layer.div.style.filter = filterString;
                layer.div.style.webkitFilter = filterString;
            }
        });

        const layerElements = document.querySelectorAll('.olLayerDiv');
        layerElements.forEach(element => {
            element.style.filter = filterString;
            element.style.webkitFilter = filterString;
        });

        const canvasElements = document.querySelectorAll('#map canvas, #WazeMap canvas');
        canvasElements.forEach(canvas => {
            canvas.style.filter = filterString;
            canvas.style.webkitFilter = filterString;
        });
    }, 100);
}


// Neu organisierte Layer-Konfiguration mit Region-Info
const layerGroups = {
    basic: {
        name: "🔧 Basis Layer",
        layers: [
            {
                id: 'basemap-de',
                name: 'Basemap.de',
                type: 'wms',
                url: 'https://sgx.geodatenzentrum.de/wms_basemapde',
                params: {
                    layers: 'de_basemapde_web_raster_farbe',
                    format: 'image/png',
                    transparent: true
                },
                attribution: '© <a href="https://www.basemap.de">basemap.de</a>',
                region: { countries: ['DE'] }
            },
            {
                id: 'basemap-de-grau',
                name: 'Basemap.de Grau',
                type: 'wms',
                url: 'https://sgx.geodatenzentrum.de/wms_basemapde',
                params: {
                    layers: 'de_basemapde_web_raster_grau',
                    format: 'image/png',
                    transparent: true
                },
                attribution: '© <a href="https://www.basemap.de">basemap.de</a>',
                region: { countries: ['DE'] }
            },
            {
                id: 'topplus',
                name: 'TopPlus WMS',
                type: 'wms',
                url: 'https://sgx.geodatenzentrum.de/wms_topplus_web_open',
                params: {
                    layers: 'web',
                    format: 'image/png',
                    transparent: true
                },
                attribution: '© BKG',
                region: { countries: ['DE'] }
            },
            {
                id: 'topplus-grau',
                name: 'TopPlus Grau',
                type: 'wms',
                url: 'https://sgx.geodatenzentrum.de/wms_topplus_web_open',
                params: {
                    layers: 'web_grau',
                    format: 'image/png',
                    transparent: true
                },
                attribution: '© BKG',
                region: { countries: ['DE'] }
            }
        ]
    },
    cadastre: {
        name: "📐 Liegenschaftskarten",
        layers: [
            {
                id: "alkis-by",
                name: "Liegenschaftskarte Bayern",
                type: "wmts",
                source: "https://geoservices.bayern.de/od/wmts/geobasis/v1/1.0.0/WMTSCapabilities.xml",
                layerName: "by_webkarte",
                matrixSet: "smerc",
                attribution: 'Bayerische Vermessungsverwaltung, GeoBasis-DE / BKG',
                region: { countries: ['DE'], states: ['BY'] }
            },
            {
                id: 'alkis-be',
                name: 'Liegenschaftskarte Berlin',
                type: 'wms',
                url: 'https://gdi.berlin.de/services/wms/alkis?SERVICE=wms',
                params: {
                    layers: 'a_alkis_raster',
                    format: 'image/png',
                    version: '1.3.0'
                },
                region: { countries: ['DE'], states: ['BE'] }
            },
            {
                id: 'alkis-bw',
                name: 'Liegenschaftskarte BW',
                type: 'wms',
                url: 'https://owsproxy.lgl-bw.de/owsproxy/ows/WMS_LGL-BW_ALKIS_Basis_Vertrieb?service=WMS',
                params: {
                    layers: 'nora:ALKIS_Basis_Vertrieb,nora:ALKIS_Beschriftung',
                    format: 'image/png',
                    version: '1.3.0'
                },
                attribution: 'LGL-BW',
                region: { countries: ['DE'], states: ['BW'] }
            },
            {
                id: 'alkis-bb',
                name: 'Liegenschaftskarte BB',
                type: 'wms',
                url: 'https://isk.geobasis-bb.de/ows/alkis_wms?service=WMS',
                params: {
                    layers: 'adv_alkis_gewaesser,adv_alkis_vegetation,adv_alkis_verkehr,adv_alkis_siedlung,adv_alkis_gebaeude,adv_alkis_flurstuecke',
                    format: 'image/png',
                    version: '1.3.0'
                },
                attribution: 'GeoBasis-DE/LGB',
                region: { countries: ['DE'], states: ['BB'] }
            },
            {
                id: 'alkis-hb',
                name: 'Liegenschaftskarte Bremen',
                type: 'wms',
                url: 'https://opendata.lgln.niedersachsen.de/doorman/noauth/alkishb_wms',
                params: {
                    layers: 'ALKIS',
                    styles: 'Farbe',
                    format: 'image/png',
                    version: '1.3.0'
                },
                attribution: 'Landesamt GeoInformation Bremen',
                region: { countries: ['DE'], states: ['HB'] }
            },
            {
                id: 'alkis-hh',
                name: 'Liegenschaftskarte Hamburg',
                type: 'wms',
                url: 'https://geodienste.hamburg.de/HH_WMS_ALKIS_Basiskarte?SERVICE=WMS',
                params: {
                    layers: '0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,27,25,23,29,30',
                    format: 'image/png',
                    version: '1.3.0'
                },
                attribution: 'Freie und Hansestadt Hamburg, Landesbetrieb Geoinformation und Vermessung, 2014',
                region: { countries: ['DE'], states: ['HH'] }
            },
            {
                id: 'alkis-he',
                name: 'Liegenschaftskarte Hessen',
                type: 'wms',
                url: 'https://www.gds-srv.hessen.de/cgi-bin/lika-services/ogc-free-maps.ows',
                params: {
                    layers: 'he_alk',
                    format: 'image/png',
                    transparent: true,
                    version: '1.3.0'
                },
                attribution: 'Hessische Verwaltung für Bodenmanagement und Geoinformation',
                region: { countries: ['DE'], states: ['HE'] }
            },
            {
                id: 'alkis-mv',
                name: 'Liegenschaftskarte MV',
                type: 'wms',
                url: 'https://www.geodaten-mv.de/dienste/alkis_wms',
                params: {
                    layers: 'adv_alkis_tatsaechliche_nutzung,adv_alkis_gebaeude,adv_alkis_flurstuecke',
                    format: 'image/png',
                    version: '1.3.0'
                },
                attribution: 'GeoBasis-DE/M-V',
                region: { countries: ['DE'], states: ['MV'] }
            },
            {
                id: 'alkis-nds',
                name: 'Liegenschaftskarte NDS',
                type: 'wms',
                url: 'https://opendata.lgln.niedersachsen.de/doorman/noauth/alkis_wms',
                params: {
                    layers: 'ALKIS',
                    styles: 'Farbe',
                    format: 'image/png',
                    transparent: true,
                    version: '1.3.0'
                },
                attribution: 'GeoBasis-DE/LGLN',
                region: { countries: ['DE'], states: ['NDS'] }
            },
            {
                id: "alkis-nw",
                name: "Liegenschaftskarte NRW (Farbe)",
                type: "wmts",
                source: "https://www.wmts.nrw.de/geobasis/wmts_nw_alkis/1.0.0/WMTSCapabilities.xml",
                layerName: "nw_alkis",
                matrixSet: "EPSG_3857_16",
                region: { countries: ['DE'], states: ['NW'] }
            },
            {
                id: "alkis-nw-grau",
                name: "Liegenschaftskarte NRW (Grau)",
                type: "wmts",
                source: "https://www.wmts.nrw.de/geobasis/wmts_nw_alkis/1.0.0/WMTSCapabilities.xml",
                layerName: "nw_alkis_grau",
                matrixSet: "EPSG_3857_16",
                region: { countries: ['DE'], states: ['NW'] }
            },
            {
                id: 'alkis-rp',
                name: 'Liegenschaftskarte RLP',
                type: 'wms',
                url: 'https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi',
                params: {
                    layers: 'Nutzung,GebaeudeBauwerke,Flurstueck,Lagebezeichnungen',
                    format: 'image/png',
                    version: '1.3.0'
                },
                attribution: 'GeoBasis-DE / LVermGeoRP',
                region: { countries: ['DE'], states: ['RP'] }
            },
            {
                id: 'alkis-sl',
                name: 'Liegenschaftskarte Saarland',
                type: 'wms',
                url: 'https://geoportal.saarland.de/geobasisdaten/mapserv?map=/mapfiles/geobasisdaten/Internet/alkis.map&SERVICE=WMS',
                params: {
                    layers: 'adv_alkis',
                    format: 'image/png',
                    version: '1.1.1'
                },
                attribution: 'GeoBasis DE/LVGL-SL',
                region: { countries: ['DE'], states: ['SL'] }
            },
            {
                id: 'alkis-sn',
                name: 'Liegenschaftskarte Sachsen',
                type: 'wms',
                url: 'https://geodienste.sachsen.de/wms_geosn_alkis-adv/guest',
                params: {
                    layers: 'adv_alkis_tatsaechliche_nutzung,adv_alkis_gebaeude,adv_alkis_flurstuecke,adv_alkis_fgp',
                    format: 'image/png'
                },
                attribution: 'Geodaten Sachsen',
                region: { countries: ['DE'], states: ['SN'] }
            },
            {
                id: 'alkis-st',
                name: 'Liegenschaftskarte ST',
                type: 'wms',
                url: 'https://www.geodatenportal.sachsen-anhalt.de/wss/service/ST_LVermGeo_ALKIS_WMS_AdV_konform_App/guest',
                params: {
                    layers: 'adv_alkis_tatsaechliche_nutzung,adv_alkis_gebaeude,st_alkis_flurstuecke',
                    format: 'image/png'
                },
                attribution: 'GeoBasis DE/LVermGeo ST',
                region: { countries: ['DE'], states: ['ST'] }
            },
            {
                id: 'alkis-sh',
                name: 'Liegenschaftskarte SH',
                type: 'wms',
                url: 'https://dienste.gdi-sh.de/WMS_SH_ALKIS_OpenGBD',
                params: {
                    layers: 'SH_ALKIS',
                    format: 'image/png'
                },
                attribution: 'GeoBasis-DE/LVermGeo SH',
                region: { countries: ['DE'], states: ['SH'] }
            },
            {
                id: 'alkis-th',
                name: 'Liegenschaftskarte Thüringen',
                type: 'wms',
                url: 'https://www.geoproxy.geoportal-th.de/geoproxy/services/adv_alkis_wms_th',
                params: {
                    layers: 'adv_alkis_gewaesser,adv_alkis_siedlung,adv_alkis_vegetation,adv_alkis_verkehr,adv_alkis_flurstuecke,adv_alkis_gebaeude',
                    format: 'image/png',
                    version: '1.3.0'
                },
                attribution: 'GDI-Th',
                region: { countries: ['DE'], states: ['TH'] }
            }
        ]
    },
    germany: {
        name: "🇩🇪 GeoOverlays DE",
        layers: [
            {
                id: "geoportal-nrw",
                name: "GeoPortal NRW",
                type: "wmts",
                source: "https://www.wmts.nrw.de/geobasis/wmts_nw_dtk/1.0.0/WMTSCapabilities.xml",
                layerName: "nw_dtk_col",
                matrixSet: "EPSG_3857_16",
                region: { countries: ['DE'], states: ['NW'] }
            },
            {
                id: "geoportal-nrw-overlay",
                name: "GeoPortal NRW Overlay",
                type: "wmts",
                source: "https://www.wmts.nrw.de/geobasis/wmts_nw_dop_overlay/1.0.0/WMTSCapabilities.xml",
                layerName: "nw_dop_overlay",
                matrixSet: "EPSG_3857_16",
                region: { countries: ['DE'], states: ['NW'] }
            },
            {
                id: "geoportal-by",
                name: "GeoPortal BY",
                type: "wmts",
                source: "https://geoservices.bayern.de/od/wmts/geobasis/v1/1.0.0/WMTSCapabilities.xml",
                layerName: "by_webkarte",
                matrixSet: "smerc",
                region: { countries: ['DE'], states: ['BY'] }
            },
            {
                id: "dop-nrw",
                name: "Luftbild NRW",
                type: "wmts",
                source: "https://www.wmts.nrw.de/geobasis/wmts_nw_dop/1.0.0/WMTSCapabilities.xml",
                layerName: "nw_dop",
                matrixSet: "EPSG_3857_16",
                region: { countries: ['DE'], states: ['NW'] }
            },
            {
                id: "dop-by",
                name: "Luftbild BY",
                type: "wmts",
                source: "https://geoservices.bayern.de/od/wmts/geobasis/v1/1.0.0/WMTSCapabilities.xml",
                layerName: "by_dop",
                matrixSet: "smerc",
                region: { countries: ['DE'], states: ['BY'] }
            },
            {
                id: 'dop-nds',
                name: 'Luftbild NDS',
                type: 'wms',
                url: 'https://opendata.lgln.niedersachsen.de/doorman/noauth/dop_wms',
                params: {
                    layers: 'ni_dop20',
                    format: 'image/png',
                    transparent: false,
                    version: '1.3.0',
                    crs: 'EPSG:3857'
                },
                attribution: '© LGLN 2024',
                region: { countries: ['DE'], states: ['NDS'] }
            },
            {
                id: 'vg25-de',
                name: 'Verwaltungsgebiete DE 1:25.000',
                type: 'wms',
                url: 'https://sg.geodatenzentrum.de/wms_vg25',
                params: {
                    layers: 'vg25',
                    format: 'image/png',
                    transparent: true
                },
                attribution: '© BKG',
                region: { countries: ['DE'] }
            },
            {
                id: 'vg25-li-de',
                name: 'Grenzlinien DE 1:25.000',
                type: 'wms',
                url: 'https://sg.geodatenzentrum.de/wms_vg25',
                params: {
                    layers: 'vg25_li',
                    format: 'image/png',
                    transparent: true
                },
                attribution: '© BKG',
                region: { countries: ['DE'] }
            },
            {
                id: 'truedop-hessen',
                name: 'TrueDOP Hessen (Luftbild)',
                type: 'wms',
                url: 'https://www.gds-srv.hessen.de/cgi-bin/lika-services/de-viewer/access/ogc-free-images.ows',
                params: {
                    layers: 'he_dop20_rgb',
                    format: 'image/jpeg',
                    transparent: false,
                    version: '1.3.0',
                    crs: 'EPSG:3857'
                },
                attribution: '© Hessische Verwaltung für Bodenmanagement und Geoinformation',
                region: { countries: ['DE'], states: ['HE'] }
            }
        ]
    },
    austria: {
        name: "🇦🇹 GeoOverlays AT",
        layers: [
            {
                id: "basemap-at",
                name: "Basemap AT",
                type: "wmts",
                source: "https://mapsneu.wien.gv.at/basemapneu/1.0.0/WMTSCapabilities.xml",
                layerName: "geolandbasemap",
                matrixSet: "google3857",
                region: { countries: ['AT'] }
            },
            {
                id: "overlay-at",
                name: "Overlay AT",
                type: "wmts",
                source: "https://www.basemap.at/wmts/1.0.0/WMTSCapabilities.xml",
                layerName: "bmapoverlay",
                matrixSet: "google3857",
                region: { countries: ['AT'] }
            }
        ]
    },
    switzerland: {
        name: "🇨🇭 GeoOverlays CH",
        layers: [
            {
                id: "swiss-strassen",
                name: "Strassenkarte",
                type: "wmts",
                source: "https://wmts.geo.admin.ch/EPSG/3857/1.0.0/WMTSCapabilities.xml",
                layerName: "ch.swisstopo.swisstne-base",
                matrixSet: "3857_18",
                region: { countries: ['CH'] }
            },
            {
                id: "swiss-basis",
                name: "Basisnetz",
                type: "wmts",
                source: "https://wmts.geo.admin.ch/EPSG/3857/1.0.0/WMTSCapabilities.xml",
                layerName: "ch.swisstopo.swisstlm3d-strassen",
                matrixSet: "3857_18",
                region: { countries: ['CH'] }
            },
            {
                id: "swiss-luft",
                name: "Luftbild",
                type: "wmts",
                source: "https://wmts.geo.admin.ch/EPSG/3857/1.0.0/WMTSCapabilities.xml",
                layerName: "ch.swisstopo.swissimage-product",
                matrixSet: "3857_20",
                region: { countries: ['CH'] }
            }
        ]
    },
    unofficial: {
        name: "🌍 Nicht Amtliche Karten",
        layers: [
            {
                id: 'osm-standard',
                name: 'OpenStreetMap Standard',
                type: 'xyz',
                urls: [
                    'https://a.tile.openstreetmap.org/${z}/${x}/${y}.png',
                    'https://b.tile.openstreetmap.org/${z}/${x}/${y}.png',
                    'https://c.tile.openstreetmap.org/${z}/${x}/${y}.png'
                ],
                attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
                region: { global: true }
            },
            {
                id: 'darkmap',
                name: 'OSM Dark Matter',
                type: 'xyz',
                urls: [
                    'https://a.basemaps.cartocdn.com/dark_all/${z}/${x}/${y}@2x.png',
                    'https://b.basemaps.cartocdn.com/dark_all/${z}/${x}/${y}@2x.png',
                    'https://c.basemaps.cartocdn.com/dark_all/${z}/${x}/${y}@2x.png'
                ],
                attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
                region: { global: true }
            },
            {
                id: 'opentopomap',
                name: 'OpenTopoMap',
                type: 'xyz',
                urls: [
                    'https://a.tile.opentopomap.org/${z}/${x}/${y}.png',
                    'https://b.tile.opentopomap.org/${z}/${x}/${y}.png',
                    'https://c.tile.opentopomap.org/${z}/${x}/${y}.png'
                ],
                attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, SRTM | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (CC-BY-SA)',
                region: { global: true }
            }
        ]
    }
};


// Hilfsfunktionen für OpenLayers Patches
function loadOLScript(filename) {
    const version = OpenLayers.VERSION_NUMBER.replace(/Release /, "");
    const url = `https://cdnjs.cloudflare.com/ajax/libs/openlayers/${version}/${filename}.js`;
    console.info("Loading openlayers/" + version + "/" + filename + ".js");
    const nonceEl = document.querySelector('script[nonce]');
    const nonce = nonceEl ? (nonceEl.nonce || nonceEl.getAttribute('nonce')) : null;

    try {
        GM_xmlhttpRequest({
            method: "GET",
            url,
            onload: (response) => {
                if (!response || typeof response.responseText !== 'string' || response.status !== 200) {
                    console.error(SCRIPT_NAME + ': Fehler beim Laden von', url, response && response.status);
                    return;
                }
                const script = document.createElement('script');
                script.type = 'text/javascript';
                if (nonce) script.setAttribute('nonce', nonce);
                script.textContent = response.responseText;
                document.head.appendChild(script);
            },
            onerror: (err) => {
                console.error(SCRIPT_NAME + ': Netzwerkfehler beim Laden von', url, err);
            }
        });
    } catch (e) {
        console.error(SCRIPT_NAME + ': Ausnahme beim Laden von', url, e);
    }
}

function patchOpenLayers() {
    if (!OpenLayers.VERSION_NUMBER.match(/^Release [0-9.]*$/)) {
        console.error("OpenLayers version mismatch - cannot apply patch");
        return;
    }

    const scripts = [
        "lib/OpenLayers/Format/XML",
        "lib/OpenLayers/Format/XML/VersionedOGC",
        "lib/OpenLayers/Layer/WMTS",
        "lib/OpenLayers/Format/OWSCommon",
        "lib/OpenLayers/Format/OWSCommon/v1",
        "lib/OpenLayers/Format/OWSCommon/v1_1_0",
        "lib/OpenLayers/Format/WMSCapabilities",
        "lib/OpenLayers/Format/WMSCapabilities/v1",
        "lib/OpenLayers/Format/WMSCapabilities/v1_3",
        "lib/OpenLayers/Format/WMSCapabilities/v1_3_0",
        "lib/OpenLayers/Format/WMTSCapabilities",
        "lib/OpenLayers/Format/WMTSCapabilities/v1_0_0"
    ];

    scripts.forEach((script, index) => {
        setTimeout(() => {
            loadOLScript(script);
        }, index * 50);
    });

    setTimeout(() => {
        const hasWMTS = typeof OpenLayers.Layer.WMTS === 'function';
        const hasCaps = typeof OpenLayers.Format.WMTSCapabilities === 'function';
        if (!hasWMTS || !hasCaps) {
            console.warn(SCRIPT_NAME + ': WMTS Komponenten nicht vollständig geladen, versuche erneut...');
            [
                "lib/OpenLayers/Layer/WMTS",
                "lib/OpenLayers/Format/WMTSCapabilities",
                "lib/OpenLayers/Format/WMTSCapabilities/v1_0_0"
            ].forEach((m, i) => setTimeout(() => loadOLScript(m), i * 50));
        } else {
            console.info(SCRIPT_NAME + ': WMTS Komponenten bereit.');
        }
    }, scripts.length * 50 + 600);
}

// Warte auf WMTS-Komponenten mit Timeout und Retry
async function waitForWMTSComponents(maxWaitMs = 10000) {
    const startTime = Date.now();
    const checkInterval = 200; // Prüfe alle 200ms
    
    return new Promise((resolve) => {
        const check = () => {
            const hasWMTS = typeof OpenLayers.Layer.WMTS === 'function';
            const hasCaps = typeof OpenLayers.Format.WMTSCapabilities === 'function';
            
            if (hasWMTS && hasCaps) {
                console.info(SCRIPT_NAME + ': WMTS-Komponenten verfügbar');
                resolve(true);
                return;
            }
            
            const elapsed = Date.now() - startTime;
            if (elapsed >= maxWaitMs) {
                console.warn(SCRIPT_NAME + ': WMTS-Komponenten nach ' + (maxWaitMs/1000) + 's nicht vollständig geladen');
                resolve(false);
                return;
            }
            
            setTimeout(check, checkInterval);
        };
        
        // Starte erste Prüfung nach kurzer Verzögerung
        setTimeout(check, 500);
    });
}

// Basis Layer erstellen
function createBasicLayer(config) {
    const olMap = W.map.getOLMap();
    let layer;

    switch (config.type) {
        case 'wms':
            layer = new OpenLayers.Layer.WMS(
                config.name,
                config.url,
                config.params,
                {
                    transitionEffect: 'resize',
                    attribution: config.attribution,
                    isBaseLayer: false,
                    visibility: false,
                    opacity: DEFAULT_OPACITY,
                    projection: new OpenLayers.Projection("EPSG:3857"),
                    displayInLayerSwitcher: false,
                    alwaysInRange: true,
                    zIndex: DEFAULT_ZINDEX
                }
            );
            break;

        case 'xyz':
            if (config.id === 'opentopomap') {
                layer = new OpenLayers.Layer.XYZ(
                    config.name,
                    config.urls,
                    {
                        attribution: config.attribution,
                        transitionEffect: 'resize',
                        isBaseLayer: false,
                        visibility: false,
                        opacity: DEFAULT_OPACITY,
                        displayInLayerSwitcher: false,
                        alwaysInRange: true,
                        sphericalMercator: true,
                        projection: new OpenLayers.Projection("EPSG:3857"),
                        zIndex: DEFAULT_ZINDEX,
                        getURL: function(bounds) {
                            var res = this.getServerResolution();
                            var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
                            var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
                            var z = this.getServerZoom();
                            var path = z + "/" + x + "/" + y + ".png";
                            var url = this.url;
                            if (OpenLayers.Util.isArray(url)) {
                                url = this.selectUrl(path, url);
                            }
                            return url.replace(/\$\{z\}/g, z).replace(/\$\{x\}/g, x).replace(/\$\{y\}/g, y);
                        }
                    }
                );
            } else {
                layer = new OpenLayers.Layer.XYZ(
                    config.name,
                    config.urls,
                    {
                        attribution: config.attribution,
                        transitionEffect: 'resize',
                        isBaseLayer: false,
                        visibility: false,
                        opacity: DEFAULT_OPACITY,
                        displayInLayerSwitcher: false,
                        alwaysInRange: true,
                        sphericalMercator: true,
                        projection: new OpenLayers.Projection("EPSG:3857"),
                        zIndex: DEFAULT_ZINDEX
                    }
                );
            }
            break;
    }

    if (layer) {
        layer.setOpacity(DEFAULT_OPACITY);
        olMap.addLayer(layer);
        layers[config.id] = layer;
        layerMetadata[config.id] = { zIndex: DEFAULT_ZINDEX };
        applySettingsToLayer(config.id, layer);
    }
}

// WMTS Layer erstellen mit Retry-Logik
function createWMTSLayer(layerConfig, retryCount = 0) {
    return new Promise((resolve, reject) => {
        // Prüfe ob Layer bereits erfolgreich geladen wurde (verhindert Race Conditions)
        if (layers[layerConfig.id] && layerStatus[layerConfig.id]?.status === 'ok') {
            console.log(`✓ ${layerConfig.name} bereits geladen, überspringe...`);
            resolve(layers[layerConfig.id]);
            return;
        }

        if (typeof OpenLayers.Format.WMTSCapabilities !== 'function') {
            console.warn(`⚠ WMTSCapabilities not available for ${layerConfig.name}, skipping...`);
            setLayerStatus(layerConfig.id, 'error', 'WMTS nicht verfügbar');
            reject(new Error("WMTSCapabilities constructor not available"));
            return;
        }

        // Status auf "loading" setzen
        if (retryCount === 0) {
            setLayerStatus(layerConfig.id, 'loading');
        } else {
            layerStatus[layerConfig.id] = layerStatus[layerConfig.id] || {};
            layerStatus[layerConfig.id].retries = retryCount;
            setLayerStatus(layerConfig.id, 'retrying', `Versuch ${retryCount}/${MAX_RETRIES}`);
        }

        GM_xmlhttpRequest({
            method: "GET",
            url: layerConfig.source,
            timeout: 15000, // 15 Sekunden Timeout
            onload: (response) => {
                try {
                    // Prüfe HTTP-Status
                    if (response.status >= 400) {
                        throw new Error(`HTTP ${response.status}`);
                    }

                    // Prüfe ob Antwort leer ist
                    if (!response.responseText || response.responseText.trim().length === 0) {
                        throw new Error("Leere Server-Antwort");
                    }

                    let responseXML = response.responseXML;
                    if (!responseXML) {
                        responseXML = new DOMParser().parseFromString(response.responseText, "text/xml");
                    }

                    if (!responseXML || !(responseXML instanceof XMLDocument)) {
                        throw new Error("Ungültige XML-Antwort");
                    }

                    // Prüfe auf XML-Parser-Fehler
                    const parserError = responseXML.querySelector('parsererror');
                    if (parserError) {
                        throw new Error("XML-Parsing fehlgeschlagen");
                    }

                    // Prüfe ob WMTS-Format verfügbar ist
                    if (typeof OpenLayers.Format.WMTSCapabilities !== 'function') {
                        throw new Error("WMTS-Komponenten noch nicht geladen");
                    }
                    
                    const format = new OpenLayers.Format.WMTSCapabilities();
                    let capabilities;
                    try {
                        capabilities = format.read(responseXML);
                    } catch (parseError) {
                        console.warn(`WMTS-Parse-Fehler für ${layerConfig.name}:`, parseError);
                        // Prüfe ob es ein bekanntes Problem ist
                        if (parseError.message && parseError.message.includes('contents')) {
                            throw new Error("Server-Antwort unvollständig");
                        }
                        throw new Error("WMTS-Format nicht lesbar");
                    }

                    if (!capabilities) {
                        throw new Error("Leere Capabilities-Antwort");
                    }
                    
                    // Prüfe ob Contents vorhanden sind
                    if (!capabilities.contents || !capabilities.contents.layers) {
                        console.warn(`Keine Layer in Capabilities für ${layerConfig.name}`);
                        throw new Error("Keine Layer im Dienst gefunden");
                    }

                    let layer;
                    try {
                        layer = format.createLayer(capabilities, {
                            layer: layerConfig.layerName,
                            matrixSet: layerConfig.matrixSet,
                            opacity: DEFAULT_OPACITY,
                            isBaseLayer: false,
                            requestEncoding: layerConfig.requestEncoding || "REST",
                            visibility: false,
                            zIndex: DEFAULT_ZINDEX
                        });
                    } catch (layerError) {
                        console.warn(`Layer-Erstellung fehlgeschlagen für ${layerConfig.name}:`, layerError);
                        // Prüfe ob der Layer-Name existiert
                        const availableLayers = capabilities.contents.layers.map(l => l.identifier).join(', ');
                        console.info(`Verfügbare Layer: ${availableLayers}`);
                        throw new Error(`Layer "${layerConfig.layerName}" nicht gefunden`);
                    }

                    if (layer && layer.url && layer.url.length) {
                        const olMap = W.map.getOLMap();
                        olMap.addLayer(layer);
                        olMap.setLayerIndex(layer, 9);

                        layers[layerConfig.id] = layer;
                        layerMetadata[layerConfig.id] = { zIndex: DEFAULT_ZINDEX };
                        applySettingsToLayer(layerConfig.id, layer);

                        // Erfolg - Status zurücksetzen
                        setLayerStatus(layerConfig.id, 'ok');
                        if (retryCount > 0) {
                            showLayerToast(`${layerConfig.name} erfolgreich geladen`, 'success');
                        }

                        resolve(layer);
                    } else {
                        throw new Error("Keine gültigen Tile-URLs");
                    }

                } catch (error) {
                    console.error(`✗ Fehler beim Laden von ${layerConfig.name}:`, error);
                    handleLayerError(layerConfig, error, retryCount, resolve, reject);
                }
            },
            onerror: (error) => {
                console.error(`✗ Netzwerkfehler für ${layerConfig.name}:`, error);
                // Versuche mehr Details aus dem Error-Objekt zu extrahieren
                let errorMsg = "Netzwerkfehler";
                if (error && error.status) {
                    errorMsg = `HTTP ${error.status}`;
                } else if (error && error.message) {
                    errorMsg = error.message;
                }
                handleLayerError(layerConfig, new Error(errorMsg), retryCount, resolve, reject);
            },
            ontimeout: () => {
                console.error(`✗ Zeitüberschreitung für ${layerConfig.name}`);
                handleLayerError(layerConfig, new Error("Zeitüberschreitung (15s)"), retryCount, resolve, reject);
            }
        });
    });
}

// Fehlerbehandlung mit Retry-Logik
function handleLayerError(layerConfig, error, retryCount, resolve, reject) {
    // Prüfe ob Layer in der Zwischenzeit erfolgreich geladen wurde
    if (layers[layerConfig.id] && layerStatus[layerConfig.id]?.status === 'ok') {
        console.log(`✓ ${layerConfig.name} wurde in der Zwischenzeit geladen, ignoriere Fehler`);
        resolve(layers[layerConfig.id]);
        return;
    }

    const nextRetry = retryCount + 1;
    const errorMsg = error?.message || '';
    
    // Bei WMTS-Komponenten-Fehler länger warten
    const isComponentError = errorMsg.includes('Komponenten') || errorMsg.includes('nicht geladen');
    const retryDelay = isComponentError ? RETRY_DELAY * 2 : RETRY_DELAY;

    if (nextRetry <= MAX_RETRIES) {
        // Retry nach Verzögerung
        console.log(`🔄 Retry ${nextRetry}/${MAX_RETRIES} für ${layerConfig.name} in ${retryDelay/1000}s...`);
        setLayerStatus(layerConfig.id, 'retrying', `Versuch ${nextRetry}/${MAX_RETRIES}`);

        setTimeout(() => {
            createWMTSLayer(layerConfig, nextRetry).then(resolve).catch(reject);
        }, retryDelay);
    } else {
        // Alle Versuche fehlgeschlagen - bessere Fehlermeldung generieren
        const readableMsg = getReadableErrorMessage(error);
        setLayerStatus(layerConfig.id, 'offline', readableMsg);
        showLayerToast(`${layerConfig.name}: ${readableMsg}`, 'error');
        reject(error);
    }
}

// Generiere lesbare Fehlermeldung aus Error-Objekt
function getReadableErrorMessage(error) {
    // Wenn kein Error-Objekt
    if (!error) {
        return 'Verbindungsfehler';
    }

    // Wenn String
    if (typeof error === 'string') {
        return translateErrorMessage(error);
    }

    // Wenn Error-Objekt mit Message
    if (error.message) {
        return translateErrorMessage(error.message);
    }

    // Wenn Error-Objekt mit Status (HTTP-Fehler)
    if (error.status) {
        return getHttpErrorMessage(error.status);
    }

    // Wenn Error-Objekt mit statusText
    if (error.statusText) {
        return translateErrorMessage(error.statusText);
    }

    // Fallback: Versuche toString
    try {
        const str = String(error);
        if (str && str !== '[object Object]') {
            return translateErrorMessage(str);
        }
    } catch (e) {}

    return 'Verbindungsfehler';
}

// Übersetze englische Fehlermeldungen ins Deutsche
function translateErrorMessage(msg) {
    if (!msg) return 'Verbindungsfehler';

    const translations = {
        'No valid URLs found': 'Keine gültigen URLs gefunden',
        'Invalid XML response': 'Ungültige Server-Antwort',
        'Network error': 'Netzwerkfehler',
        'Timeout': 'Zeitüberschreitung',
        'timeout': 'Zeitüberschreitung',
        'Netzwerkfehler': 'Netzwerkfehler',
        'Zeitüberschreitung': 'Zeitüberschreitung',
        'Failed to fetch': 'Server nicht erreichbar',
        'NetworkError': 'Netzwerkfehler',
        'AbortError': 'Anfrage abgebrochen',
        'CORS': 'Zugriff verweigert (CORS)',
        'cors': 'Zugriff verweigert (CORS)'
    };

    // Exakte Übereinstimmung
    if (translations[msg]) {
        return translations[msg];
    }

    // Teilweise Übereinstimmung
    for (const [key, value] of Object.entries(translations)) {
        if (msg.toLowerCase().includes(key.toLowerCase())) {
            return value;
        }
    }

    // HTTP-Fehler erkennen
    const httpMatch = msg.match(/HTTP\s*(\d{3})/i);
    if (httpMatch) {
        return getHttpErrorMessage(parseInt(httpMatch[1]));
    }

    // Wenn Nachricht kurz genug, direkt zurückgeben
    if (msg.length < 50) {
        return msg;
    }

    return 'Server-Fehler';
}

// HTTP-Statuscode in lesbare Meldung umwandeln
function getHttpErrorMessage(status) {
    const httpErrors = {
        400: 'Ungültige Anfrage',
        401: 'Nicht autorisiert',
        403: 'Zugriff verweigert',
        404: 'Dienst nicht gefunden',
        408: 'Zeitüberschreitung',
        429: 'Zu viele Anfragen',
        500: 'Server-Fehler',
        502: 'Server nicht erreichbar',
        503: 'Dienst nicht verfügbar',
        504: 'Gateway-Zeitüberschreitung'
    };

    return httpErrors[status] || `HTTP-Fehler ${status}`;
}

// Manueller Retry für einen Layer
function retryLayerLoad(layerId) {
    // Finde Layer-Config
    let layerConfig = null;
    for (const group of Object.values(layerGroups)) {
        if (group.layers) {
            layerConfig = group.layers.find(l => l.id === layerId);
            if (layerConfig) break;
        }
    }

    if (!layerConfig) {
        console.error(`Layer-Config für ${layerId} nicht gefunden`);
        return;
    }

    // Reset Retry-Counter
    if (layerStatus[layerId]) {
        layerStatus[layerId].retries = 0;
    }

    showLayerToast(`${layerConfig.name} wird neu geladen...`, 'info');

    // Starte neuen Ladeversuch
    if (layerConfig.type === 'wmts') {
        createWMTSLayer(layerConfig, 0).catch(() => {
            // Fehler wird bereits in handleLayerError behandelt
        });
    } else {
        createBasicLayer(layerConfig);
        setLayerStatus(layerId, 'ok');
    }
}

// Update Notification System
function showUpdateNotification() {
    const lastShown = localStorage.getItem('wme-overlay-update-shown');
    const currentVersion = GM_info.script.version;

    if (lastShown === currentVersion) {
        return;
    }

    const overlay = document.createElement('div');
    overlay.className = 'update-notification-overlay';
    overlay.innerHTML = `
        <div class="update-notification">
            <div class="update-header">
                <h2>WME Multi Map Overlay</h2>
                <div class="header-right">
                    <span class="version-badge">v${currentVersion}</span>
                    <button class="close-btn" id="header-close-btn">×</button>
                </div>
            </div>
            <div class="update-content">
                <h3>NEU: Geo-Filter & Verbindungsverbesserungen!</h3>
                <div class="new-features">
                    <div class="feature-group">
                        <h4>Geo-Filter:</h4>
                        <ul>
                            <li><strong>Automatische Regionserkennung</strong> - Erkennt Land und Bundesland</li>
                            <li><strong>Relevante Karten</strong> - Zeigt nur Karten fuer deine Region</li>
                            <li><strong>Kartenanzahl</strong> - Zeigt wie viele Karten verfuegbar sind</li>
                            <li><strong>Ein/Aus-Schalter</strong> - Filter kann deaktiviert werden</li>
                        </ul>
                    </div>
                    <div class="feature-group">
                        <h4>Verbindungsverbesserungen:</h4>
                        <ul>
                            <li><strong>Automatische Wiederholung</strong> - Bis zu 3 Versuche bei Fehlern</li>
                            <li><strong>Timeout-Erkennung</strong> - Erkennt langsame Server</li>
                            <li><strong>Status-Anzeige</strong> - Zeigt Ladestatus pro Karte</li>
                            <li><strong>Benachrichtigungen</strong> - Info bei Verbindungsproblemen</li>
                        </ul>
                    </div>
                </div>
                <div class="feature-info">
                    <p><strong>Tipp:</strong> Bei Verbindungsproblemen auf das Status-Symbol klicken zum erneuten Laden.</p>
                </div>
            </div>
            <div class="update-actions">
                <button class="btn-primary" id="explore-maps-btn">Los geht's!</button>
            </div>
        </div>
    `;

    const updateStyle = document.createElement('style');
    updateStyle.textContent = `
        .update-notification-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            z-index: 999999;
            display: flex;
            align-items: center;
            justify-content: center;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }
        .update-notification {
            background: white;
            border-radius: 12px;
            max-width: 600px;
            width: 90%;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
            animation: slideIn 0.3s ease-out;
        }
        @keyframes slideIn {
            from { opacity: 0; transform: scale(0.9) translateY(-20px); }
            to { opacity: 1; transform: scale(1) translateY(0); }
        }
        .update-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 12px 12px 0 0;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .header-right {
            display: flex;
            align-items: center;
            gap: 12px;
        }
        .close-btn {
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            width: 32px;
            height: 32px;
            border-radius: 50%;
            font-size: 18px;
            font-weight: bold;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.2s;
        }
        .close-btn:hover { background: rgba(255, 255, 255, 0.3); }
        .update-header h2 { margin: 0; font-size: 24px; font-weight: 600; }
        .version-badge {
            background: rgba(255, 255, 255, 0.2);
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 14px;
            font-weight: 500;
        }
        .update-content { padding: 24px; }
        .update-content h3 { margin: 0 0 20px 0; color: #333; font-size: 20px; }
        .new-features {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
            margin-bottom: 24px;
        }
        .feature-group {
            background: #f8f9fa;
            padding: 16px;
            border-radius: 8px;
            border-left: 4px solid #667eea;
        }
        .feature-group h4 { margin: 0 0 12px 0; color: #333; font-size: 16px; font-weight: 600; }
        .feature-group ul { margin: 0; padding-left: 0; list-style: none; }
        .feature-group li { margin: 6px 0; color: #555; font-size: 14px; }
        .feature-info {
            background: #e3f2fd;
            padding: 16px;
            border-radius: 8px;
            border-left: 4px solid #2196f3;
        }
        .feature-info p { margin: 0; color: #1565c0; font-size: 14px; }
        .feature-info strong { font-weight: 600; }
        .update-actions {
            padding: 20px 24px;
            border-top: 1px solid #eee;
            display: flex;
            gap: 12px;
            justify-content: flex-end;
        }
        .btn-primary {
            padding: 12px 24px;
            border: none;
            border-radius: 6px;
            font-size: 14px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.2s;
            background: #667eea;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            text-align: center;
        }
        .btn-primary:hover { background: #5a6fd8; transform: translateY(-1px); }
    `;
    document.head.appendChild(updateStyle);
    document.body.appendChild(overlay);

    overlay.querySelector('#explore-maps-btn').addEventListener('click', function() {
        overlay.remove();
        localStorage.setItem('wme-overlay-update-shown', currentVersion);
    });

    overlay.querySelector('#header-close-btn').addEventListener('click', function() {
        overlay.remove();
        localStorage.setItem('wme-overlay-update-shown', currentVersion);
    });

    overlay.addEventListener('click', function(e) {
        if (e.target === overlay) {
            overlay.remove();
            localStorage.setItem('wme-overlay-update-shown', currentVersion);
        }
    });

    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape' && document.contains(overlay)) {
            overlay.remove();
            localStorage.setItem('wme-overlay-update-shown', currentVersion);
        }
    });
}

// Drag & Drop Funktionalität für Hauptmenüs/Kategorien
function makeGroupDraggable(container, groupKey) {
    container.dataset.groupKey = groupKey;

    const header = container.querySelector('.group-header');
    if (!header) return;

    const dragHandle = document.createElement('span');
    dragHandle.className = 'group-drag-handle';
    dragHandle.innerHTML = '⋮⋮';
    dragHandle.title = 'Kategorie verschieben';
    dragHandle.draggable = true;

    header.appendChild(dragHandle);

    dragHandle.addEventListener('dragstart', (e) => {
        container.classList.add('group-dragging');
        e.dataTransfer.setData('text/plain', groupKey);
        e.dataTransfer.effectAllowed = 'move';
        e.stopPropagation();
    });

    dragHandle.addEventListener('dragend', () => {
        container.classList.remove('group-dragging');
        document.querySelectorAll('.layer-group').forEach(el => {
            el.classList.remove('group-drop-target-above', 'group-drop-target-below');
        });
    });

    container.addEventListener('dragover', (e) => {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'move';

        const draggingElement = document.querySelector('.group-dragging');
        if (draggingElement && draggingElement !== container) {
            const rect = container.getBoundingClientRect();
            const midY = rect.top + rect.height / 2;

            container.classList.remove('group-drop-target-above', 'group-drop-target-below');

            if (e.clientY < midY) {
                container.classList.add('group-drop-target-above');
            } else {
                container.classList.add('group-drop-target-below');
            }
        }
    });

    container.addEventListener('dragleave', (e) => {
        if (!container.contains(e.relatedTarget)) {
            container.classList.remove('group-drop-target-above', 'group-drop-target-below');
        }
    });

    container.addEventListener('drop', (e) => {
        e.preventDefault();
        const draggedGroupKey = e.dataTransfer.getData('text/plain');
        const draggedElement = document.querySelector(`[data-group-key="${draggedGroupKey}"]`);

        if (draggedElement && draggedElement !== container) {
            const rect = container.getBoundingClientRect();
            const midY = rect.top + rect.height / 2;
            const parent = container.parentNode;

            if (e.clientY < midY) {
                parent.insertBefore(draggedElement, container);
            } else {
                parent.insertBefore(draggedElement, container.nextSibling);
            }

            saveGroupOrder();
        }

        container.classList.remove('group-drop-target-above', 'group-drop-target-below');
    });

    dragHandle.addEventListener('click', (e) => {
        e.stopPropagation();
        e.preventDefault();
    });
}

function saveGroupOrder() {
    const overlayTab = document.querySelector('.overlay-tab');
    if (!overlayTab) return;

    const groupElements = overlayTab.querySelectorAll('.layer-group[data-group-key]');
    const order = Array.from(groupElements).map(el => el.dataset.groupKey);

    try {
        localStorage.setItem('wme-overlay-group-order', JSON.stringify(order));
    } catch (error) {
        console.error('Fehler beim Speichern der Gruppenreihenfolge:', error);
    }
}

function loadGroupOrder() {
    try {
        const saved = localStorage.getItem('wme-overlay-group-order');
        if (saved) {
            return JSON.parse(saved);
        }
    } catch (error) {
        console.error('Fehler beim Laden der Gruppenreihenfolge:', error);
    }
    return ['basic', 'cadastre', 'germany', 'austria', 'switzerland', 'unofficial'];
}


// Layer Control erstellen mit Geo-Filter-Unterstützung
function createLayerControl(layerId, name, isGroup = false, groupKey = null) {
    const container = document.createElement('div');
    container.className = isGroup ? 'layer-group' : 'layer-control';

    if (isGroup) {
        const header = document.createElement('div');
        header.className = 'group-header';
        header.style.cursor = 'pointer';

        const toggleButton = document.createElement('span');
        toggleButton.className = 'toggle-button';
        const shouldBeOpenByDefault = (
            groupKey === 'basic' ||
            groupKey === 'global-filters' ||
            groupKey === 'geo-settings' ||
            (typeof name === 'string' && name.indexOf('Karten Einstellungen') !== -1)
        );
        const isCollapsed = shouldBeOpenByDefault ? (collapsedGroups[groupKey] === false) : (collapsedGroups[groupKey] !== true);
        toggleButton.innerHTML = isCollapsed ? '▶' : '▼';

        const titleSpan = document.createElement('span');
        titleSpan.className = 'group-title';
        titleSpan.textContent = name;

        header.appendChild(toggleButton);
        header.appendChild(titleSpan);

        const content = document.createElement('div');
        content.className = 'group-content';
        content.style.display = isCollapsed ? 'none' : 'block';

        header.addEventListener('click', () => {
            const isCurrentlyCollapsed = content.style.display === 'none';
            content.style.display = isCurrentlyCollapsed ? 'block' : 'none';
            toggleButton.innerHTML = isCurrentlyCollapsed ? '▼' : '▶';

            collapsedGroups[groupKey] = isCurrentlyCollapsed;
            saveCollapsedState();
        });

        container.appendChild(header);
        container.appendChild(content);
        container.content = content;

        makeGroupDraggable(container, groupKey);

        return container;
    }

    const layer = layers[layerId];
    if (!layer) return container;

    // Sichtbarkeits-Checkbox
    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.checked = layer.getVisibility();
    checkbox.addEventListener('change', () => {
        layer.setVisibility(checkbox.checked);
        saveSettings();
    });

    const label = document.createElement('label');
    label.appendChild(checkbox);
    label.appendChild(document.createTextNode(name));

    // Status-Indikator für Layer
    const statusIndicator = document.createElement('span');
    statusIndicator.className = 'layer-status-indicator';
    statusIndicator.dataset.layerStatus = layerId;
    statusIndicator.style.cssText = 'margin-left: 6px; font-size: 12px; display: none;';

    // Klick auf Offline-Status startet Retry
    statusIndicator.addEventListener('click', (e) => {
        e.stopPropagation();
        const status = layerStatus[layerId];
        if (status && status.status === 'offline') {
            retryLayerLoad(layerId);
        }
    });

    label.appendChild(statusIndicator);

    // Initial Status anzeigen
    updateLayerStatusUI(layerId);

    // Transparenz-Slider
    const opacityContainer = document.createElement('div');
    opacityContainer.className = 'slider-container';

    const opacityLabel = document.createElement('span');
    opacityLabel.textContent = 'Transparenz: ';

    const opacityValue = document.createElement('span');
    opacityValue.className = 'slider-value';
    opacityValue.textContent = Math.round((layer.opacity || DEFAULT_OPACITY) * 100) + '%';

    const opacitySlider = document.createElement('input');
    opacitySlider.type = 'range';
    opacitySlider.min = '0';
    opacitySlider.max = '100';
    opacitySlider.step = '1';
    opacitySlider.value = Math.round((layer.opacity || DEFAULT_OPACITY) * 100);

    opacitySlider.addEventListener('input', () => {
        const value = parseInt(opacitySlider.value) / 100;
        layer.setOpacity(value);
        layer.opacity = value;
        opacityValue.textContent = opacitySlider.value + '%';
        saveSettings();
    });

    opacityContainer.appendChild(opacityLabel);
    opacityContainer.appendChild(opacitySlider);
    opacityContainer.appendChild(opacityValue);

    // Z-Index-Slider
    const zIndexContainer = document.createElement('div');
    zIndexContainer.className = 'slider-container';

    const zIndexLabel = document.createElement('span');
    zIndexLabel.textContent = 'Ebene: ';

    const zIndexValue = document.createElement('span');
    zIndexValue.className = 'slider-value';

    const currentZIndex = layerMetadata[layerId]?.zIndex || layer.getZIndex() || DEFAULT_ZINDEX;
    zIndexValue.textContent = currentZIndex;

    const zIndexSlider = document.createElement('input');
    zIndexSlider.type = 'range';
    zIndexSlider.min = '1900';
    zIndexSlider.max = '2500';
    zIndexSlider.step = '5';
    zIndexSlider.value = currentZIndex;

    zIndexSlider.addEventListener('input', () => {
        const zIndex = parseInt(zIndexSlider.value);
        layer.setZIndex(zIndex);

        if (!layerMetadata[layerId]) {
            layerMetadata[layerId] = {};
        }
        layerMetadata[layerId].zIndex = zIndex;

        zIndexValue.textContent = zIndex;
        saveSettings();
    });

    zIndexContainer.appendChild(zIndexLabel);
    zIndexContainer.appendChild(zIndexSlider);
    zIndexContainer.appendChild(zIndexValue);

    container.appendChild(label);
    container.appendChild(opacityContainer);
    container.appendChild(zIndexContainer);

    // Legende-Buttons für Basemap.de
    if (layerId === 'basemap-de') {
        const legendContainer = document.createElement('div');
        legendContainer.className = 'legend-container';
        legendContainer.style.cssText = 'margin-top: 6px; display: flex; gap: 3px;';

        const legendButton = createSmallButton('📋 Legende', '#4CAF50', '#45a049', () => {
            window.open('https://basemap.de/produkte-und-dienste/web-raster/legende-web-raster-farbe/', '_blank');
        });

        const kartenstadButton = createSmallButton('📅 Kartenstand', '#2196F3', '#1976D2', () => {
            window.open('https://basemap.de/data/produkte/web_raster/meta/bm_web_raster_datenaktualitaet.html', '_blank');
        });

        legendContainer.appendChild(legendButton);
        legendContainer.appendChild(kartenstadButton);
        container.appendChild(legendContainer);
    }

    // Legende-Buttons für TopPlus WMS
    if (layerId === 'topplus') {
        const legendContainer = document.createElement('div');
        legendContainer.className = 'legend-container';
        legendContainer.style.cssText = 'margin-top: 6px; display: flex; gap: 3px;';

        const legendButton = createSmallButton('📋 Legende', '#4CAF50', '#45a049', () => {
            window.open('https://sgx.geodatenzentrum.de/web_public/gdz/dokumentation/deu/topplusopen.pdf', '_blank');
        });

        const kartenstadButton = createSmallButton('📅 Kartenstand', '#2196F3', '#1976D2', () => {
            window.open('https://sgx.geodatenzentrum.de/web_public/gdz/datenquellen/datenquellen_topplusopen.pdf', '_blank');
        });

        legendContainer.appendChild(legendButton);
        legendContainer.appendChild(kartenstadButton);
        container.appendChild(legendContainer);
    }

    return container;
}

// Hilfsfunktion für kleine Buttons
function createSmallButton(text, bgColor, hoverColor, onClick) {
    const button = document.createElement('button');
    button.textContent = text;
    button.style.cssText = `
        background: linear-gradient(135deg, ${bgColor}, ${hoverColor});
        color: white;
        border: none;
        padding: 0px 6px;
        border-radius: 4px;
        font-size: 10px;
        line-height: 1;
        height: 20px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.2s ease;
        box-shadow: 0 1px 2px rgba(0,0,0,0.1);
        flex: 1;
    `;

    button.addEventListener('mouseenter', () => {
        button.style.transform = 'translateY(-1px)';
        button.style.boxShadow = '0 2px 3px rgba(0,0,0,0.15)';
    });

    button.addEventListener('mouseleave', () => {
        button.style.transform = 'translateY(0)';
        button.style.boxShadow = '0 1px 2px rgba(0,0,0,0.1)';
    });

    button.addEventListener('click', onClick);
    return button;
}

// Globale Filter-Einstellungen
let globalFilters = {
    brightness: 100,
    contrast: 100,
    saturation: 100,
    sharpness: 100
};

function createGlobalFilterControls() {
    const container = createLayerControl(null, '🎨 Karten Einstellungen', true, 'global-filters');
    const content = container.content;

    // Helligkeit-Slider
    content.appendChild(createFilterSlider('Helligkeit', globalFilters.brightness, (value) => {
        globalFilters.brightness = value;
        updateAllLayerFilters();
        saveGlobalFilters();
    }));

    // Kontrast-Slider
    content.appendChild(createFilterSlider('Kontrast', globalFilters.contrast, (value) => {
        globalFilters.contrast = value;
        updateAllLayerFilters();
        saveGlobalFilters();
    }));

    // Sättigung-Slider
    content.appendChild(createFilterSlider('Sättigung', globalFilters.saturation, (value) => {
        globalFilters.saturation = value;
        updateAllLayerFilters();
        saveGlobalFilters();
    }));

    // Schärfe-Slider
    content.appendChild(createFilterSlider('Schärfe', globalFilters.sharpness, (value) => {
        globalFilters.sharpness = value;
        updateAllLayerFilters();
        saveGlobalFilters();
    }));

    return container;
}

function createFilterSlider(label, initialValue, onChange) {
    const container = document.createElement('div');
    container.className = 'slider-container global-filter';

    const labelSpan = document.createElement('span');
    labelSpan.textContent = label + ': ';

    const valueSpan = document.createElement('span');
    valueSpan.className = 'slider-value';
    valueSpan.textContent = initialValue + '%';

    const slider = document.createElement('input');
    slider.type = 'range';
    slider.min = '0';
    slider.max = '300';
    slider.step = '1';
    slider.value = initialValue;

    slider.addEventListener('input', () => {
        const value = parseInt(slider.value);
        valueSpan.textContent = value + '%';
        onChange(value);
    });

    container.appendChild(labelSpan);
    container.appendChild(slider);
    container.appendChild(valueSpan);

    return container;
}

// ============================================
// GEO-FILTER UI (Kompakt)
// ============================================

// Erstelle kompakte Geo-Filter Sektion
function createGeoSettingsControls() {
    const container = document.createElement('div');
    container.className = 'layer-group geo-filter-section';
    container.dataset.groupKey = 'geo-settings';

    // Funktion zum Aktualisieren des Styles (aktiv = grün, inaktiv = normal)
    const updateContainerStyle = (isActive) => {
        if (isActive) {
            container.classList.add('geo-filter-active');
        } else {
            container.classList.remove('geo-filter-active');
        }
    };

    // Collapsed State laden
    const isCollapsed = collapsedGroups['geo-settings'] === true;

    // Header mit Toggle (wie group-header)
    const header = document.createElement('div');
    header.className = 'geo-filter-header group-header';
    header.style.cssText = `
        display: flex;
        align-items: center;
        justify-content: space-between;
        cursor: pointer;
    `;

    const leftSide = document.createElement('div');
    leftSide.style.cssText = 'display: flex; align-items: center; gap: 6px;';

    // Toggle-Pfeil für Ein-/Ausklappen
    const toggleArrow = document.createElement('span');
    toggleArrow.className = 'toggle-button';
    toggleArrow.innerHTML = isCollapsed ? '▶' : '▼';
    toggleArrow.style.cssText = 'font-size: 10px; color: #666; width: 12px;';

    const icon = document.createElement('span');
    icon.textContent = '📍';
    icon.style.fontSize = '14px';

    const title = document.createElement('span');
    title.textContent = 'Geo-Filter';
    title.style.cssText = 'font-weight: 600; font-size: 13px; color: #333;';

    leftSide.appendChild(toggleArrow);
    leftSide.appendChild(icon);
    leftSide.appendChild(title);

    // Aktiv-Checkbox rechts (mit Abstand für Drag-Handle)
    const rightSide = document.createElement('div');
    rightSide.style.cssText = 'display: flex; align-items: center; gap: 5px; margin-right: 24px;';
    rightSide.addEventListener('click', (e) => e.stopPropagation());

    const toggleLabel = document.createElement('label');
    toggleLabel.htmlFor = 'geo-filter-toggle';
    toggleLabel.textContent = 'Aktiv';
    toggleLabel.style.cssText = 'cursor: pointer; font-size: 13px; color: #555;';

    const toggleCheckbox = document.createElement('input');
    toggleCheckbox.type = 'checkbox';
    toggleCheckbox.id = 'geo-filter-toggle';
    toggleCheckbox.checked = geoFilterEnabled;
    toggleCheckbox.style.cssText = 'width: 14px; height: 14px; cursor: pointer; margin: 0; accent-color: auto;';

    rightSide.appendChild(toggleLabel);
    rightSide.appendChild(toggleCheckbox);

    header.appendChild(leftSide);
    header.appendChild(rightSide);
    container.appendChild(header);

    // Content (Region-Anzeige)
    const content = document.createElement('div');
    content.className = 'geo-filter-content group-content';
    content.id = 'geo-status-display';
    content.style.cssText = `
        padding: 8px 10px;
        font-size: 12px;
        color: #555;
        display: ${isCollapsed ? 'none' : 'block'};
    `;
    updateGeoStatusDisplay(content);
    container.appendChild(content);
    container.content = content;

    // Initial Style setzen
    updateContainerStyle(geoFilterEnabled);

    // Toggle Event für Checkbox
    toggleCheckbox.addEventListener('change', () => {
        geoFilterEnabled = toggleCheckbox.checked;
        updateContainerStyle(geoFilterEnabled);
        saveGeoFilterState();
        updateGeoStatusDisplay(content);
        refreshLayerUI();
    });

    // Klick auf Header klappt ein/aus
    header.addEventListener('click', () => {
        const isCurrentlyCollapsed = content.style.display === 'none';
        content.style.display = isCurrentlyCollapsed ? 'block' : 'none';
        toggleArrow.innerHTML = isCurrentlyCollapsed ? '▼' : '▶';

        // Speichere Collapsed State
        collapsedGroups['geo-settings'] = !isCurrentlyCollapsed;
        saveCollapsedState();
    });

    // Drag & Drop aktivieren
    makeGroupDraggable(container, 'geo-settings');

    return container;
}

// Zähle verfügbare Layer für aktuelle Region
function countVisibleLayers() {
    let total = 0;
    let visible = 0;

    Object.values(layerGroups).forEach(group => {
        if (group.layers) {
            group.layers.forEach(layerConfig => {
                if (layerConfig.id && layers[layerConfig.id]) {
                    total++;
                    if (isLayerRelevantForRegion(layerConfig.id)) {
                        visible++;
                    }
                }
            });
        }
    });

    return { total, visible };
}

// Aktualisiere Geo-Status-Anzeige (kompakt)
function updateGeoStatusDisplay(element) {
    if (!element) {
        element = document.getElementById('geo-status-display');
    }
    if (!element) return;

    detectCurrentRegion();

    let statusHTML = '';

    // Bundesland-Badge immer anzeigen wenn erkannt
    let regionText = '';
    if (currentRegion.stateName) {
        regionText = `🗺️ ${currentRegion.stateName}`;
    } else if (currentRegion.country) {
        const countryNames = { 'DE': 'Deutschland', 'AT': 'Österreich', 'CH': 'Schweiz' };
        regionText = `🗺️ ${countryNames[currentRegion.country] || currentRegion.country}`;
    }

    if (regionText) {
        statusHTML = `<span style="background:#fff;padding:3px 8px;border-radius:4px;border:1px solid #ddd;display:inline-block;">${regionText}</span>`;
    } else {
        statusHTML = '<span style="color:#999;font-style:italic;">Region wird erkannt...</span>';
    }

    // Zusatzinfo je nach Filter-Status
    if (geoFilterEnabled) {
        const counts = countVisibleLayers();
        statusHTML += `<div style="color:#666;font-size:11px;margin-top:4px;">${counts.visible} von ${counts.total} Karten</div>`;
    } else {
        statusHTML += '<div style="color:#888;font-style:italic;font-size:11px;margin-top:4px;">Alle Layer werden angezeigt (Filter deaktiviert).</div>';
    }

    element.innerHTML = statusHTML;
}

// Aktualisiere Layer-UI basierend auf Geo-Filter
function refreshLayerUI() {
    const overlayTab = document.querySelector('.overlay-tab');
    if (!overlayTab) return;

    // Entferne alte Layer-Gruppen (außer Einstellungen)
    const oldGroups = overlayTab.querySelectorAll('.layer-group:not([data-group-key="global-filters"]):not([data-group-key="geo-settings"])');
    oldGroups.forEach(g => g.remove());

    // Füge Layer-Gruppen neu hinzu
    const savedGroupOrder = loadGroupOrder();
    const geoSettingsGroup = overlayTab.querySelector('[data-group-key="geo-settings"]');
    const insertBefore = geoSettingsGroup || overlayTab.querySelector('[data-group-key="global-filters"]');

    savedGroupOrder.forEach(groupKey => {
        if (layerGroups[groupKey]) {
            const group = layerGroups[groupKey];

            // Filtere Layer basierend auf Region
            const relevantLayers = group.layers.filter(layerConfig => {
                if (!layerConfig.id) return false;
                return isLayerRelevantForRegion(layerConfig.id);
            });

            // Überspringe leere Gruppen
            if (relevantLayers.length === 0) return;

            const groupContainer = createLayerControl(null, group.name, true, groupKey);

            relevantLayers.forEach(layerConfig => {
                if (layers[layerConfig.id]) {
                    groupContainer.content.appendChild(createLayerControl(layerConfig.id, layerConfig.name));
                }
            });

            if (insertBefore) {
                overlayTab.insertBefore(groupContainer, insertBefore);
            } else {
                overlayTab.appendChild(groupContainer);
            }
        }
    });
}

// Event-Listener für Kartenverschiebung
function setupMapMoveListener() {
    if (W && W.map) {
        // Debounce für Performance
        let moveTimeout = null;

        W.map.events.register('moveend', null, () => {
            if (moveTimeout) clearTimeout(moveTimeout);
            moveTimeout = setTimeout(() => {
                const oldState = currentRegion.state;
                const oldCountry = currentRegion.country;

                detectCurrentRegion();

                // Nur UI aktualisieren wenn sich Region geändert hat
                if (oldState !== currentRegion.state || oldCountry !== currentRegion.country) {
                    updateGeoStatusDisplay();
                    if (geoFilterEnabled) {
                        refreshLayerUI();
                    }
                }
            }, 500);
        });
    }
}


// ============================================
// INITIALISIERUNG
// ============================================

async function initializeScript() {
    try {
        // Registriere Script-Info
        W.userscripts[SCRIPT_ID] = {
            name: SCRIPT_NAME,
            author: 'Hiwi234',
            version: GM_info.script.version
        };

        // Lade gespeicherte Zustände
        loadCollapsedState();
        loadGeoFilterState();

        // Globaler Overlayschalter: Zustand laden und UI erstellen
        loadEnabledState();
        createGlobalToggleUI();

        // Patche OpenLayers für WMTS Support
        patchOpenLayers();

        // Warte auf WMTS-Komponenten mit Prüfung
        await waitForWMTSComponents();

        // Erkenne initiale Region
        detectCurrentRegion();
        console.info(SCRIPT_NAME + ': Region erkannt -', currentRegion.country, currentRegion.state);

        // Erstelle alle Layer
        const wmtsPromises = [];

        Object.keys(layerGroups).forEach(groupKey => {
            const group = layerGroups[groupKey];
            group.layers.forEach(layerConfig => {
                if (!layerConfig.id) return;

                if (layerConfig.type === 'wmts') {
                    wmtsPromises.push(createWMTSLayer(layerConfig));
                } else {
                    createBasicLayer(layerConfig);
                }
            });
        });

        // Warte auf alle WMTS Layer
        await Promise.allSettled(wmtsPromises);

        // Wende globalen Ein/Aus-Zustand auf alle Layer an
        setScriptEnabled(scriptEnabled, true);

        // Erstelle Sidebar Tab
        const { tabLabel, tabPane } = W.userscripts.registerSidebarTab(SCRIPT_ID);
        tabLabel.textContent = 'Multi Map 🗺️';
        tabLabel.title = 'Erweiterte Karten-Overlays mit Geo-Lokalisierung';

        await W.userscripts.waitForElementConnected(tabPane);

        // Erstelle Content Container
        const content = document.createElement('div');
        content.className = 'overlay-tab';

        // Lade globale Filter-Einstellungen
        loadGlobalFilters();

        // Füge alle Gruppen in der gespeicherten Reihenfolge hinzu (gefiltert nach Region)
        const savedGroupOrder = loadGroupOrder();
        savedGroupOrder.forEach(groupKey => {
            if (layerGroups[groupKey]) {
                const group = layerGroups[groupKey];

                // Filtere Layer basierend auf Region
                const relevantLayers = group.layers.filter(layerConfig => {
                    if (!layerConfig.id) return false;
                    return isLayerRelevantForRegion(layerConfig.id);
                });

                // Überspringe leere Gruppen
                if (relevantLayers.length === 0) return;

                const groupContainer = createLayerControl(null, group.name, true, groupKey);

                relevantLayers.forEach(layerConfig => {
                    if (layers[layerConfig.id]) {
                        groupContainer.content.appendChild(createLayerControl(layerConfig.id, layerConfig.name));
                    }
                });
                content.appendChild(groupContainer);
            }
        });

        // Füge Geo-Filter über Karten Einstellungen hinzu
        content.appendChild(createGeoSettingsControls());

        // Füge globale Filter-Kontrollen am Ende hinzu
        content.appendChild(createGlobalFilterControls());

        tabPane.appendChild(content);

        // Füge Reset-Button hinzu
        const resetContainer = document.createElement('div');
        resetContainer.className = 'reset-container';

        const resetButton = document.createElement('button');
        resetButton.textContent = '🔄 Alles zurücksetzen';
        resetButton.className = 'reset-button';
        resetButton.addEventListener('click', () => {
            if (confirm('Alle Einstellungen zurücksetzen?')) {
                localStorage.removeItem(STORAGE_KEY);
                localStorage.removeItem('wme-overlay-global-filters');
                localStorage.removeItem(COLLAPSED_STATE_KEY);
                localStorage.removeItem('wme-overlay-group-order');
                localStorage.removeItem(GEO_FILTER_KEY);
                location.reload();
            }
        });

        resetContainer.appendChild(resetButton);
        tabPane.appendChild(resetContainer);

        // Füge Styles hinzu
        addStyles();

        // Zeige Update-Benachrichtigung
        showUpdateNotification();

        // Initiale Anwendung der globalen Filter
        setTimeout(() => {
            updateAllLayerFilters();
        }, 2000);

        // Setup Map Move Listener für dynamische Region-Updates
        setupMapMoveListener();

        console.info(SCRIPT_NAME + ': Initialisierung abgeschlossen');

    } catch (error) {
        console.error(SCRIPT_NAME + ': Fehler bei der Initialisierung:', error);
    }
}

function addStyles() {
    const style = document.createElement('style');
    style.textContent = `
        .overlay-tab {
            padding: 6px;
            max-height: 70vh;
            overflow-y: auto;
        }

        .master-toggle-container {
            background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
            border: 1px solid #dee2e6;
            border-radius: 6px;
            padding: 8px;
            margin-bottom: 10px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        .master-toggle-label {
            display: flex;
            align-items: center;
            cursor: pointer;
            font-weight: 600;
            font-size: 14px;
            gap: 8px;
            user-select: none;
        }

        .master-toggle-checkbox {
            width: 18px;
            height: 18px;
            cursor: pointer;
            accent-color: #4CAF50;
        }

        .master-toggle-text {
            transition: color 0.3s ease;
            font-weight: 600;
        }

        .layer-group {
            margin-bottom: 8px;
            border: 1px solid #ddd;
            border-radius: 5px;
            overflow: hidden;
        }

        .group-header {
            background: #f5f5f5;
            padding: 6px 10px;
            font-weight: bold;
            border-bottom: 1px solid #ddd;
            display: flex;
            align-items: center;
            gap: 6px;
            transition: background-color 0.2s ease;
            position: relative;
        }

        .group-header:hover {
            background: #e8e8e8;
        }

        .group-drag-handle {
            position: absolute;
            right: 8px;
            top: 50%;
            transform: translateY(-50%);
            cursor: grab;
            color: #999;
            font-size: 13px;
            user-select: none;
            padding: 3px 5px;
            border-radius: 3px;
            transition: all 0.2s ease;
            background: rgba(255,255,255,0.8);
            border: 1px solid #ddd;
        }

        .group-drag-handle:hover {
            background: rgba(0,0,0,0.1);
            color: #666;
            border-color: #999;
        }

        .toggle-button {
            font-size: 11px;
            color: #666;
            transition: transform 0.2s ease;
            display: inline-block;
            width: 14px;
            text-align: center;
        }

        .group-title {
            font-size: 13px;
            flex: 1;
        }

        .group-content {
            transition: all 0.3s ease;
            overflow: hidden;
        }

        .layer-control {
            margin: 0;
            padding: 8px;
            border-bottom: 1px solid #eee;
        }

        .layer-control:last-child {
            border-bottom: none;
        }

        .layer-control label {
            display: block;
            margin-bottom: 4px;
            font-weight: 500;
            cursor: pointer;
        }

        .layer-control input[type="checkbox"] {
            margin-right: 6px;
        }

        .slider-container {
            margin: 4px 0;
            display: flex;
            align-items: center;
        }

        .global-filter {
            padding: 6px 10px;
            border-bottom: 1px solid #eee;
        }

        .global-filter:last-child {
            border-bottom: none;
        }

        .layer-group[data-group-key="global-filters"] .group-title {
            font-weight: 700;
        }
        .global-filter span {
            font-weight: 700;
        }

        .slider-container span {
            display: inline-block;
            width: 78px;
            font-size: 11px;
            color: #666;
        }

        .slider-container input[type="range"] {
            flex: 1;
            margin: 0 6px;
        }

        .slider-value {
            width: 40px !important;
            text-align: right;
            font-weight: 500;
            color: #333 !important;
        }

        .reset-container {
            margin-top: 10px;
            padding: 10px;
            border-top: 1px solid #ddd;
            text-align: center;
        }

        .reset-button {
            background: #f44336;
            color: white;
            border: none;
            padding: 6px 12px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 11px;
            transition: background 0.2s;
        }

        .reset-button:hover {
            background: #d32f2f;
        }

        /* Drag & Drop Styles für Gruppen */
        .layer-group[draggable="true"] {
            transition: all 0.2s ease;
        }

        .layer-group.group-dragging {
            opacity: 0.6;
            transform: rotate(1deg);
            box-shadow: 0 8px 25px rgba(0,0,0,0.3);
            z-index: 1000;
            border: 2px dashed #666;
        }

        .layer-group.group-drop-target-above {
            border-top: 4px solid #4CAF50;
            margin-top: 4px;
        }

        .layer-group.group-drop-target-below {
            border-bottom: 4px solid #4CAF50;
            margin-bottom: 4px;
        }

        .group-drag-handle[draggable="true"]:active {
            cursor: grabbing;
        }

        /* Geo-Lokalisierung Styles */
        .geo-status {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }

        .geo-toggle-container {
            border-bottom: 1px solid #eee;
            padding-bottom: 8px;
        }

        /* Geo-Settings Gruppe - aktiv = grün, inaktiv = normal */
        .layer-group[data-group-key="geo-settings"].geo-filter-active {
            border-color: #c8e6c9;
            background: linear-gradient(to bottom, #e8f5e9, #fff);
        }

        .layer-group[data-group-key="geo-settings"].geo-filter-active .geo-filter-header {
            background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
        }

        /* Layer-Status-Indikator */
        .layer-status-indicator {
            cursor: default;
            vertical-align: middle;
        }

        .layer-status-indicator[title*="Klicken"] {
            cursor: pointer;
        }

        .layer-status-indicator:hover[title*="Klicken"] {
            transform: scale(1.2);
        }

        /* Toast-Benachrichtigungen */
        .layer-toast {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }

        @keyframes slideIn {
            from {
                transform: translateX(100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }

        @keyframes slideOut {
            from {
                transform: translateX(0);
                opacity: 1;
            }
            to {
                transform: translateX(100%);
                opacity: 0;
            }
        }
    `;
    document.head.appendChild(style);
}

// Starte Initialisierung wenn WME bereit ist
if (W?.userscripts?.state.isReady) {
    initializeScript();
} else {
    document.addEventListener('wme-ready', initializeScript, { once: true });
}

})();