GeoPixelcons++

Unified GeoPixels enhancement suite - by Pixelcons

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

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

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

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

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

ستحتاج إلى تثبيت إضافة مثل Stylus لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتتمكن من تثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

(لدي بالفعل مثبت أنماط للمستخدم، دعني أقم بتثبيته!)

// ==UserScript==
// @name         GeoPixelcons++
// @namespace    http://tampermonkey.net/
// @version      1.9.6
// @description  Unified GeoPixels enhancement suite - by Pixelcons
// @author       ariapokoteng, Manako, D.V.H., JainIlluverii
// @match        *://geopixels.net/*
// @match        *://*.geopixels.net/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_registerMenuCommand
// @grant        unsafeWindow
// @connect      *
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=geopixels.net
// ==/UserScript==

(function(){"use strict";const VERSION="1.9.6",STORAGE_KEY="geopixelcons_settings",FEATURE_LIST=[{key:"bulkPurchaseColors",name:"Bulk Purchase Colors",icon:"🛒",desc:"Advanced color purchasing with queue management.",features:["Bulk color purchase with preview modal","Queue management in profile panel","Duplicate detection & insufficient-pixels handling","Purchase progress tracking"]},{key:"ghostPlusPlus",name:"Ghost++ Template Overlay",icon:"👻",desc:"A scalable, multi-template ghost/overlay manager that replaces the native ghost image tool.",features:["Indexed-core rendering that scales to large, high-colour templates","Draggable, resizable, fully collapsible manager with a two-column layout","Thumbnail template library with hover preview, edit/teleport, and bulk export/delete","Sort/filter/search palette with hover-to-copy hex readout","Segmented completion progress bar with per-colour breakdown, unaffected by which colours are toggled on/off","One-click full-opacity template Preview toggle"]},{key:"guildOverhaul",name:"Guild Overhaul",icon:"⚔️",desc:"Comprehensive guild interface improvements.",features:["Enhanced member management UI","Bank/treasury system","Color limit tracking","Role hierarchy display","Guild-specific moderation tools"]},{key:"hidePaintMenu",name:"Paint Menu Controls",icon:"🫣",desc:"Adds a collapse/expand toggle for the bottom controls panel.",features:["Collapse & expand the bottom paint controls","Reposition controls (left/center/right)","Smooth CSS animations"]},{key:"paintBrushSwap",name:"Paint Brush Swap",icon:"🖌️",desc:"Rapid paintbrush tool switching with keyboard shortcuts.",features:["Configurable keyboard shortcuts for brush swap","Brush preset profiles for different painting patterns","Quick-switch between brush types"]},{key:"regionScreenshot",name:"Region Screenshot",icon:"📸",desc:"Capture region-level screenshots with coordinate overlays.",features:["Region image capture with coordinate overlay","Alpha channel support","Save as PNG directly"]},{key:"regionsHighscore",name:"Regions Highscore",icon:"🏆",desc:"Displays regional pixel/color contribution rankings.",features:["Sort rankings by player or guild","Filter by pixel count, color, or region","Historical contribution statistics"]},{key:"themeEditor",name:"Theme Editor",icon:"🎨",desc:"Visual map theme editor — edit MapLibre GL styles with color pickers, save/load/manage custom themes.",features:["Bundled themes (Fjord, Obsidian, Monokai, Ayu Mirage, etc.)","Simple & Full color editing modes","Live preview toggle for instant feedback","Import/export themes as JSON files","Quick theme-switch submenu in the dropdown","Theme manager with create, edit & delete"]},{key:"mapMarkers",name:"Map Markers",icon:"📌",desc:"Place and manage image stickers on the map canvas. Images scale and persist with the map.",features:["Upload PNG/JPEG/WebP files or use image URLs","Drag to define placement bounds (click-only rejected with prompt)","Hold Shift during drag to force aspect-ratio lock","Per-marker lock/unlock aspect ratio toggle","Per-marker opacity slider and visibility toggle","Edit mode with 8 fixed-size handles (corners + edge midpoints)","Drag-to-sort cards to reorder rendering order","Compact card view with click-to-expand controls","Draggable management modal","Persistent storage via IndexedDB"]}],EXTENSION_LIST=[{key:"extAutoHoverMenus",name:"Auto-open Menus on Hover",icon:"🖱️",desc:"Automatically opens group button dropdown menus when you hover over them.",features:["Hover over any group button to auto-open its dropdown","Configurable vertical hover zone (250px)","Per-button cooldown to prevent rapid toggles","MutationObserver-based — detects new buttons automatically"]},{key:"extGoToLastLocation",name:"Auto-Go to Last Location",icon:"📍",desc:"Automatically returns you to your last location on page load if you spawned at the default area.",features:["Detects if you spawned in the default area",'Auto-clicks the "Last Location" button on load',"One-shot — only fires once per page load","Automatic cleanup after 10 seconds to prevent leaks"]},{key:"extPillHoverLabels",name:"Hover Labels",icon:"💊",desc:"Adds the expanding pill-style hover animation with text labels to all submenu buttons under controls-left.",features:["Expanding pill animation on hover","Shows button title/name as a label","Applies to all native dropdown submenu buttons","Respects dark mode colors","MutationObserver-based — detects dynamically added buttons"]},{key:"extJanitorView",name:"Janitor View",icon:"🛡️",desc:"Reveals the hidden moderation button for janitors/moderators.",features:["Removes the hidden class from the moderation group button","Makes the 🛡️ Moderation button visible in the controls"]},{key:"extMapMovementLock",name:"Map Movement Lock",icon:"🔒",desc:"Adds a right-side lock button that freezes map panning, zooming, and page scrolling until you unlock it.",features:["Creates a lock toggle in controls-right","Blocks mouse, touch, keyboard, zoom button, scripted pan/zoom movement, and page-wide scrolling while locked","Preserves the locked state across reloads while the extension is enabled"]},{key:"extGuildSearch",name:"Guild Search Button",icon:"🔎",desc:"Inserts a search icon button in the guild submenu to open the Guild Search modal — allows searching other guilds without leaving your own.",features:["Adds a search button directly below the Guild menu button in its submenu","Calls the native toggleGuildSearchModal() when clicked"]},{key:"extLogOutButton",name:"Log Out Button",icon:"🚪",desc:"Appends a Log Out button to the bottom of the right controls panel. Hides automatically when you are not logged in.",features:["Exit-icon Log Out button at the bottom of controls-right","Calls the native logOut() when clicked","Auto-hides while the user is logged out and reappears on login"]},{key:"ghostPaletteSearch",name:"Ghost Palette Color Search (legacy)",icon:"🔍",desc:"Superseded by Ghost++ Template Overlay. Adds a searchable color filter to the native ghost image palette — only useful if Ghost++ is disabled.",features:["Search ghost palette colors by hex code","Hide unmatched colors with a toggle","Enable filtered: enable matched colors and disable all others in the ghost palette","Enable owned and filtered: enable only owned colors currently shown by filters","Real-time glow/highlight on matching swatches"]},{key:"ghostTemplateManager",name:"Ghost Template Manager (legacy)",icon:"👻",desc:"Superseded by Ghost++ Template Overlay. Full ghost image template history with import/export and overlay preview on the native ghost tool — only useful if Ghost++ is disabled.",features:["IndexedDB-backed template history","Import/export ghost templates as files","Preview overlay on the map","Position encoding in image header","Duplicate detection"]}],DEFAULT_SETTINGS={useEmojiIcon:!1,compactPaintOverflow:!1,disableGroupNoise:!1,startShiftLock:!1,startInspectMode:!1,smoothZoomButtons:!1,mobileCompatibility:!1,enableDebug:!1,modernizeGhostPaletteBtns:!1,showSyncGhostBtn:!1,rememberGhostModalPos:!1,keybinds:{openSettings:{key:"P",ctrl:!0,shift:!0},mapMovementLock:{key:"L",ctrl:!0,shift:!0}}};function loadSettings(){try{const e=localStorage.getItem(STORAGE_KEY);if(!e)return{...DEFAULT_SETTINGS};const t=JSON.parse(e),n={...DEFAULT_SETTINGS,...t},o=t.keybinds||{},r=o.openSettings;return r&&"H"===r.key&&!0===r.ctrl&&!0===r.shift&&(o.openSettings={key:"P",ctrl:!0,shift:!0}),n.keybinds={...o},Object.entries(DEFAULT_SETTINGS.keybinds).forEach(([e,t])=>{n.keybinds[e]={...t,...o[e]||{}}}),n}catch(e){return{...DEFAULT_SETTINGS}}}function saveSettings(e){localStorage.setItem(STORAGE_KEY,JSON.stringify(e))}FEATURE_LIST.forEach(e=>DEFAULT_SETTINGS[e.key]=!0),DEFAULT_SETTINGS.ghostPlusPlus=!1,EXTENSION_LIST.forEach(e=>DEFAULT_SETTINGS[e.key]="extPillHoverLabels"===e.key);const _settings=loadSettings();function gpcMobileCompatibilityActive(){if(!_settings.mobileCompatibility)return!1;try{return window.matchMedia("(max-width: 768px)").matches||window.matchMedia("(pointer: coarse)").matches}catch(e){return window.innerWidth<=768}}const _debugLog=[];function dbgPush(e,t={}){if(!_settings.enableDebug)return;const n={timestamp:(new Date).toISOString(),message:e};t.uiComponent&&(n.uiComponent=t.uiComponent),null!=t.error&&(n.error=String(t.error),t.error&&t.error.stack&&(n.stack=t.error.stack)),_debugLog.push(n)}function dbgCount(){return _debugLog.length}function dbgCaptureStateSnapshot(){const e={capturedAt:(new Date).toISOString(),version:VERSION,page:{url:location.href,userAgent:navigator.userAgent,readyState:document.readyState,viewport:{width:window.innerWidth,height:window.innerHeight},darkMode:(()=>{try{return isDarkMode()}catch(e){return null}})()},settings:_settings,featureStatus:_featureStatus};if(void 0!==gppState){try{const t=document.getElementById("loadGhostImageBtn"),n=document.getElementById("gpp-modal");e.ghostPlusPlus={settings:gppState.settings,runtimeReady:gppState.runtimeReady,templateCount:gppState.templates?gppState.templates.length:null,guildTemplateCount:gppState.guildTemplates?gppState.guildTemplates.length:null,focusedTemplateId:gppState.focusedTemplateId,shimActive:void 0!==gppShimActive?gppShimActive:null,openerMounted:!!document.getElementById("gpp-opener"),nativeButtonFound:!!t,nativeButtonHidden:t?t.classList.contains("hidden"):null,modalMounted:!!n,modalCurrentlyOpen:n?!n.classList.contains("gpp-hidden"):null}}catch(t){e.ghostPlusPlus={error:"Failed to capture Ghost++ state: "+(t&&t.message?t.message:String(t))}}try{e.nativeGhostState="function"==typeof gppReadNativeGhostSnapshot?gppReadNativeGhostSnapshot():null}catch(t){e.nativeGhostState={error:"Failed to read native ghost state: "+(t&&t.message?t.message:String(t))}}}return e}function dbgExport(){const e=_debugLog.map(e=>{let t=`[${e.timestamp}] ${e.message}`;return e.uiComponent&&(t+=`\n  UI Component : ${e.uiComponent}`),e.error&&(t+=`\n  Error        : ${e.error}`),e.stack&&(t+=`\n  Stack        :\n    ${e.stack.replace(/\n/g,"\n    ")}`),t}),t="\n"+"─".repeat(60)+"\n",n=`GeoPixelcons++ Debug Log\nVersion : ${VERSION}\nGenerated: ${(new Date).toISOString()}\nEntries  : ${_debugLog.length}\n${"=".repeat(60)}\n\n`,o=_debugLog.length?e.join(t):"(No timestamped log entries recorded yet.)";let r;try{r="\n\n"+"=".repeat(60)+"\nSTATE SNAPSHOT (captured just now, at export time)\n"+"=".repeat(60)+"\n"+JSON.stringify(dbgCaptureStateSnapshot(),null,2)+"\n"}catch(e){r="\n\n(Failed to capture state snapshot: "+(e&&e.message?e.message:String(e))+")\n"}const a=new Blob([n+o+r],{type:"text/plain"}),i=document.createElement("a");i.href=URL.createObjectURL(a),i.download=`gpc-debug-${(new Date).toISOString().replace(/[:.]/g,"-")}.txt`,document.body.appendChild(i),i.click(),setTimeout(()=>{try{i.remove(),URL.revokeObjectURL(i.href)}catch(e){}},1e3)}("undefined"!=typeof unsafeWindow?unsafeWindow:window).__gpcDebugBridge=Object.freeze({push:(e,t)=>dbgPush(e,t),isEnabled:()=>!!_settings.enableDebug});let _themeEditor=null,_regionScreenshot=null,_regionsHighscore=null,_mapMarkers=null;const COORD_CACHE_KEY="gpc_cachedCoords",AUTO_SS_KEY="gpc_autoScreenshotEnabled";function loadCachedCoords(){try{return JSON.parse(localStorage.getItem(COORD_CACHE_KEY))}catch{return null}}function saveCachedCoords(e){localStorage.setItem(COORD_CACHE_KEY,JSON.stringify(e))}function isAutoScreenshotEnabled(){return"1"===localStorage.getItem(AUTO_SS_KEY)}function setAutoScreenshot(e){localStorage.setItem(AUTO_SS_KEY,e?"1":"0")}const _featureStatus={};function isDarkMode(){const e=localStorage.getItem("geo++_settings");if(e)try{const t=JSON.parse(e);if(t.theme&&"system"!==t.theme)return"simple_black"===t.theme}catch(e){}return document.body.classList.contains("dark")||window.matchMedia("(prefers-color-scheme: dark)").matches}function t(e,t){return isDarkMode()?t:e}function createSettingsModal(){const e=document.getElementById("gpc-settings-modal");if(e)return void e.remove();const t=isDarkMode(),n=document.createElement("div");n.id="gpc-settings-modal",n.style.cssText="\n            position: fixed; inset: 0; z-index: 100000;\n            background: rgba(0,0,0,0.5); display: flex;\n            align-items: center; justify-content: center;\n            font-family: system-ui, -apple-system, sans-serif;\n        ";const o=document.createElement("div");o.style.cssText=`\n            background: ${t?"#1e1e2e":"#ffffff"};\n            color: ${t?"#cdd6f4":"#1e293b"};\n            border-radius: 12px; padding: 0; width: 460px; max-width: 95vw;\n            box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n            overflow: hidden;\n        `;const r=document.createElement("div");r.style.cssText=`\n            padding: 16px 20px; display: flex; align-items: center;\n            justify-content: space-between;\n            background: ${t?"#313244":"#f1f5f9"};\n            border-bottom: 1px solid ${t?"#45475a":"#e2e8f0"};\n        `,r.innerHTML='<span style="font-weight:700;font-size:16px;">⚙️ GeoPixelcons++</span>';const a=document.createElement("button");a.textContent="✕",a.style.cssText=`\n            background:none; border:none; font-size:18px; cursor:pointer;\n            color:${t?"#a6adc8":"#64748b"}; padding:4px 8px; border-radius:4px;\n        `,a.onmouseenter=()=>a.style.background=t?"#45475a":"#e2e8f0",a.onmouseleave=()=>a.style.background="none",a.onclick=()=>n.remove(),r.appendChild(a),o.appendChild(r);const i=document.createElement("div");i.style.cssText=`\n            display: flex; background: ${t?"#1e1e2e":"#ffffff"};\n            border-bottom: 1px solid ${t?"#45475a":"#e2e8f0"};\n        `;const l=[],s=[];["Extensions","GPC Settings","Keybindings"].forEach((e,n)=>{const o=document.createElement("button");o.textContent=e,o.style.cssText=`\n                flex: 1; padding: 10px 16px; font-size: 13px; font-weight: 600;\n                border: none; cursor: pointer; transition: 0.2s;\n                background: ${0===n?t?"#1e1e2e":"#ffffff":t?"#313244":"#f1f5f9"};\n                color: ${0===n?t?"#cdd6f4":"#1e293b":t?"#6c7086":"#94a3b8"};\n                border-bottom: 2px solid ${0===n?"#22c55e":"transparent"};\n            `,o.addEventListener("click",()=>{return e=n,l.forEach((n,o)=>{const r=o===e;n.style.background=r?t?"#1e1e2e":"#ffffff":t?"#313244":"#f1f5f9",n.style.color=r?t?"#cdd6f4":"#1e293b":t?"#6c7086":"#94a3b8",n.style.borderBottom=r?"2px solid #22c55e":"2px solid transparent"}),void s.forEach((t,n)=>{t.style.display=n===e?"block":"none"});var e}),l.push(o),i.appendChild(o)}),o.appendChild(i);const c=document.createElement("div");c.id="gpc-restart-banner",c.style.cssText=`\n            display: none; padding: 10px 20px;\n            background: ${t?"#f9e2af33":"#fef3c7"};\n            color: ${t?"#f9e2af":"#92400e"};\n            font-size: 13px; font-weight: 600;\n            border-bottom: 1px solid ${t?"#f9e2af44":"#fde68a"};\n        `,c.textContent="⚠️ Refresh the page to apply changes",o.appendChild(c);let d=null;function p(){d&&(d.remove(),d=null)}function g(e,n){p();const o=document.createElement("div");o.style.cssText=`\n                position: fixed; z-index: 100001; padding: 10px 14px; border-radius: 8px;\n                background: ${t?"#313244":"#ffffff"}; color: ${t?"#cdd6f4":"#1e293b"};\n                box-shadow: 0 8px 24px rgba(0,0,0,0.25); font-size: 13px; max-width: 260px;\n                border: 1px solid ${t?"#45475a":"#e2e8f0"}; pointer-events: none; line-height: 1.5;\n            `,o.textContent=n,document.body.appendChild(o);const r=o.offsetWidth,a=o.offsetHeight;let i=e.clientX+12,l=e.clientY+12;i+r>window.innerWidth-8&&(i=e.clientX-r-12),l+a>window.innerHeight-8&&(l=e.clientY-a-12),o.style.left=i+"px",o.style.top=l+"px",d=o}function u(e){function t(e){e&&(e.scrollIntoView?.({behavior:"smooth",block:"center"}),e.style.transition="box-shadow .3s",e.style.boxShadow="0 0 0 3px #facc15, 0 0 16px 4px rgba(250,204,21,.5)",setTimeout(()=>{e.style.boxShadow="",setTimeout(()=>{e.style.transition=""},300)},1500))}const n="undefined"!=typeof unsafeWindow?unsafeWindow:window,o={ghostPaletteSearch:()=>{"function"==typeof n.toggleGhostModal&&n.toggleGhostModal(!0),setTimeout(()=>t(document.querySelector(".color-search-container")),400)},ghostTemplateManager:()=>{"function"==typeof n.toggleGhostModal&&n.toggleGhostModal(!0),setTimeout(()=>{Array.from(document.querySelectorAll(".gp-to-btn")).forEach(e=>t(e))},400)},guildOverhaul:()=>{const e=document.querySelector("#guildMenuBtn");e&&e.click()},hidePaintMenu:()=>{t(document.querySelector("#gpc-hide-paint-toggle"))},paintBrushSwap:()=>{t(document.querySelector("#brush-swap-toggle"))},regionsHighscore:()=>{_regionsHighscore&&_regionsHighscore.toggleSelectionMode()},regionScreenshot:()=>{_regionScreenshot&&_regionScreenshot.toggleSelectionMode()},bulkPurchaseColors:()=>{"function"==typeof n.toggleProfile&&n.toggleProfile(),setTimeout(()=>t(document.querySelector("#gp-bulk-profile-card")),400)},themeEditor:()=>{_themeEditor&&_themeEditor.toggleModal()},extAutoHoverMenus:()=>{},extGoToLastLocation:()=>{},extPillHoverLabels:()=>{},extJanitorView:()=>{const e=document.getElementById("modGroupBtn");e&&t(e)},extMapMovementLock:()=>{t(document.getElementById("gpc-map-movement-lock-btn"))},extGuildSearch:()=>{t(document.getElementById("gpc-guild-search-btn"))},extLogOutButton:()=>{t(document.getElementById("gpc-logout-btn"))}}[e];o&&o()}function m(e,o){const r=_featureStatus[e.key],a=!1!==_settings[e.key],i=document.createElement("div");i.style.cssText=`\n                display: flex; align-items: center; justify-content: space-between;\n                padding: 10px 14px; border-radius: 8px;\n                background: ${a?"error"===r?t?"#f9e2af22":"#fefce8":t?"#a6e3a122":"#f0fdf4":t?"#f38ba822":"#fef2f2"};\n                border: 1px solid ${a?"error"===r?t?"#f9e2af44":"#fde68a":t?"#a6e3a144":"#bbf7d0":t?"#f38ba844":"#fecaca"};\n                transition: all 0.2s;\n            `;const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;min-width:0;";const s=document.createElement("span");s.textContent=e.icon;const g=document.createElement("span");if(g.textContent=e.name,g.style.cssText="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;border-bottom:1px dashed "+(t?"#6c7086":"#94a3b8")+";transition:color .15s,border-color .15s;",g.addEventListener("mouseenter",()=>{g.style.color="#3b82f6",g.style.borderBottomColor="#3b82f6"}),g.addEventListener("mouseleave",()=>{g.style.color="",g.style.borderBottomColor=t?"#6c7086":"#94a3b8"}),g.addEventListener("click",()=>{n.remove(),u(e.key)}),l.appendChild(s),l.appendChild(g),o&&e.desc){const n=document.createElement("span");n.textContent="❓",n.style.cssText="cursor:help;font-size:14px;flex-shrink:0;margin-left:2px;",n.addEventListener("mouseenter",n=>function(e,n){p();const o=document.createElement("div");o.style.cssText=`\n                position: fixed; z-index: 100001; padding: 12px 16px; border-radius: 8px;\n                background: ${t?"#313244":"#ffffff"}; color: ${t?"#cdd6f4":"#1e293b"};\n                box-shadow: 0 8px 24px rgba(0,0,0,0.25); font-size: 13px; max-width: 280px;\n                border: 1px solid ${t?"#45475a":"#e2e8f0"}; pointer-events: none;\n            `;let r=`<div style="font-weight:700;margin-bottom:6px;">${n.icon} ${n.name}</div>`;r+=`<div style="margin-bottom:6px;color:${t?"#a6adc8":"#64748b"};">${n.desc}</div>`,r+='<ul style="margin:0;padding-left:18px;">',n.features.forEach(e=>{r+=`<li style="margin-bottom:2px;">${e}</li>`}),r+="</ul>",o.innerHTML=r,document.body.appendChild(o);const a=o.offsetWidth,i=o.offsetHeight;let l=e.clientX+12,s=e.clientY+12;l+a>window.innerWidth-8&&(l=e.clientX-a-12),s+i>window.innerHeight-8&&(s=e.clientY-i-12),o.style.left=l+"px",o.style.top=s+"px",d=o}(n,e)),n.addEventListener("mouseleave",p),l.appendChild(n)}const m=document.createElement("label");m.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0; margin-left:8px;";const h=document.createElement("input");h.type="checkbox",h.checked=a,h.style.cssText="opacity:0;width:0;height:0;";const f=document.createElement("span");f.style.cssText=`\n                position:absolute; inset:0; border-radius:12px; transition:0.2s;\n                background: ${a?"#22c55e":t?"#585b70":"#cbd5e1"};\n            `;const b=document.createElement("span");return b.style.cssText=`\n                position:absolute; top:2px; left:${a?"22px":"2px"};\n                width:20px; height:20px; border-radius:50%; transition:0.2s;\n                background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n            `,f.appendChild(b),h.addEventListener("change",()=>{_settings[e.key]=h.checked,saveSettings(_settings),f.style.background=h.checked?"#22c55e":t?"#585b70":"#cbd5e1",b.style.left=h.checked?"22px":"2px",i.style.background=h.checked?t?"#a6e3a122":"#f0fdf4":t?"#f38ba822":"#fef2f2",i.style.borderColor=h.checked?t?"#a6e3a144":"#bbf7d0":t?"#f38ba844":"#fecaca",c.style.display="block"}),m.appendChild(h),m.appendChild(f),i.appendChild(l),i.appendChild(m),i}const h=document.createElement("div");h.style.cssText="padding: 12px 20px; display: flex; flex-direction: column; gap: 8px; max-height: 50vh; overflow-y: auto;";const f=document.createElement("div");f.style.cssText=`font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.5px;color:${t?"#6c7086":"#94a3b8"};margin-bottom:2px;`,f.textContent="Built-in Features",h.appendChild(f),FEATURE_LIST.forEach(e=>h.appendChild(m(e,!0)));const b=document.createElement("div");b.style.cssText=`font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.5px;color:${t?"#6c7086":"#94a3b8"};margin-top:8px;margin-bottom:2px;`,b.textContent="Additional Extensions",h.appendChild(b),EXTENSION_LIST.forEach(e=>h.appendChild(m(e,!0)));const y=!!_settings.showSyncGhostBtn,x=document.createElement("div");x.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${y?t?"#a6e3a122":"#f0fdf4":t?"#f38ba822":"#fef2f2"};\n            border: 1px solid ${y?t?"#a6e3a144":"#bbf7d0":t?"#f38ba844":"#fecaca"};\n            transition: all 0.2s;\n        `;const v=document.createElement("div");v.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;min-width:0;";const w=document.createElement("span");w.textContent="♻️";const k=document.createElement("span");k.textContent="Sync Ghost With Selected Color";const E=document.createElement("span");E.textContent="❓",E.style.cssText="cursor:help;font-size:14px;flex-shrink:0;margin-left:2px;",E.addEventListener("mouseenter",e=>g(e,"Shows the ♻️ Sync Ghost With Selected Color button in the Image Tools (🖼️) dropdown. When toggled on in-game, changing your active paint color automatically enables only that color in the ghost palette and disables all others.")),E.addEventListener("mouseleave",p),v.appendChild(w),v.appendChild(k),v.appendChild(E);const C=document.createElement("label");C.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0; margin-left:8px;";const S=document.createElement("input");S.type="checkbox",S.checked=y,S.style.cssText="opacity:0;width:0;height:0;";const T=document.createElement("span");T.style.cssText=`position:absolute; inset:0; border-radius:12px; transition:0.2s; background: ${y?"#22c55e":t?"#585b70":"#cbd5e1"};`;const P=document.createElement("span");P.style.cssText=`position:absolute; top:2px; left:${y?"22px":"2px"}; width:20px; height:20px; border-radius:50%; transition:0.2s; background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);`,T.appendChild(P),S.addEventListener("change",()=>{_settings.showSyncGhostBtn=S.checked,saveSettings(_settings),T.style.background=S.checked?"#22c55e":t?"#585b70":"#cbd5e1",P.style.left=S.checked?"22px":"2px",x.style.background=S.checked?t?"#a6e3a122":"#f0fdf4":t?"#f38ba822":"#fef2f2",x.style.borderColor=S.checked?t?"#a6e3a144":"#bbf7d0":t?"#f38ba844":"#fecaca";const e=document.getElementById("gpc-sync-ghost-btn");e&&e.classList.toggle("hidden",!S.checked),dbgPush('Settings: "Sync Ghost With Selected Color" display option toggled '+(S.checked?"ON":"OFF")+(e?" -- live button updated.":" -- #gpc-sync-ghost-btn does not exist in the DOM yet (Ghost Palette Search feature not enabled, or its button has not mounted yet); the new value is saved and will take effect once it mounts."),{uiComponent:"Ghost Palette Search"})}),C.appendChild(S),C.appendChild(T),x.appendChild(v),x.appendChild(C),h.appendChild(x),s.push(h),o.appendChild(h);const L=document.createElement("div");L.style.cssText="padding: 12px 20px; display: none; flex-direction: column; gap: 12px;";const M=document.createElement("div");M.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n        `;const I=document.createElement("div");I.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",I.innerHTML="<span>😢</span><span>Use emoji for menu button</span>";const _=document.createElement("span");_.textContent="❓",_.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",_.addEventListener("mouseenter",e=>g(e,"When enabled, replaces the GeoPixelcons++ button icon with the 😢 emoji.")),_.addEventListener("mouseleave",p),I.appendChild(_);const G=document.createElement("label");G.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const R=document.createElement("input");R.type="checkbox",R.checked=!!_settings.useEmojiIcon,R.style.cssText="opacity:0;width:0;height:0;";const N=document.createElement("span");N.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.useEmojiIcon?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const A=document.createElement("span");A.style.cssText=`\n            position:absolute; top:2px; left:${_settings.useEmojiIcon?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,N.appendChild(A),R.addEventListener("change",()=>{_settings.useEmojiIcon=R.checked,saveSettings(_settings),N.style.background=R.checked?"#22c55e":t?"#585b70":"#cbd5e1",A.style.left=R.checked?"22px":"2px";const e=document.getElementById("geopixelconsGroupBtn");e&&(R.checked?(e.style.backgroundImage="none",e.textContent="😢",e.style.fontSize="20px"):(e.textContent="",e.style.fontSize="",e.style.backgroundImage=e.dataset.iconBg||""))}),G.appendChild(R),G.appendChild(N),M.appendChild(I),M.appendChild(G),L.appendChild(M);const z=document.createElement("div");z.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const B=document.createElement("div");B.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",B.innerHTML="<span>🖌️</span><span>Compact paint controls</span>";const O=document.createElement("span");O.textContent="❓",O.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",O.addEventListener("mouseenter",e=>g(e,"Moves the ✕ close button and 🖌️ brushes button from inside the paint modal to compact icons above it, alongside the collapse/drag controls. Helps on small or zoomed-in screens.")),O.addEventListener("mouseleave",p),B.appendChild(O);const D=document.createElement("label");D.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const j=document.createElement("input");j.type="checkbox",j.checked=!!_settings.compactPaintOverflow,j.style.cssText="opacity:0;width:0;height:0;";const H=document.createElement("span");H.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.compactPaintOverflow?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const F=document.createElement("span");F.style.cssText=`\n            position:absolute; top:2px; left:${_settings.compactPaintOverflow?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,H.appendChild(F),j.addEventListener("change",()=>{_settings.compactPaintOverflow=j.checked,saveSettings(_settings),H.style.background=j.checked?"#22c55e":t?"#585b70":"#cbd5e1",F.style.left=j.checked?"22px":"2px",c.style.display="block"}),D.appendChild(j),D.appendChild(H),z.appendChild(B),z.appendChild(D),L.appendChild(z);const X=document.createElement("div");X.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const q=document.createElement("div");q.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",q.innerHTML="<span>🚫</span><span>Disable Group Noise</span>";const U=document.createElement("span");U.textContent="❓",U.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",U.addEventListener("mouseenter",e=>g(e,'Permanently unchecks and hides the "Group Noise" toggle in the ghost template modal. Prevents automatic color grouping so every unique color is treated individually.')),U.addEventListener("mouseleave",p),q.appendChild(U);const W=document.createElement("label");W.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const Y=document.createElement("input");Y.type="checkbox",Y.checked=!!_settings.disableGroupNoise,Y.style.cssText="opacity:0;width:0;height:0;";const V=document.createElement("span");V.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.disableGroupNoise?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const J=document.createElement("span");J.style.cssText=`\n            position:absolute; top:2px; left:${_settings.disableGroupNoise?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,V.appendChild(J),Y.addEventListener("change",()=>{_settings.disableGroupNoise=Y.checked,saveSettings(_settings),V.style.background=Y.checked?"#22c55e":t?"#585b70":"#cbd5e1",J.style.left=Y.checked?"22px":"2px",c.style.display="block"}),W.appendChild(Y),W.appendChild(V),X.appendChild(q),X.appendChild(W),L.appendChild(X);const $=document.createElement("div");$.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const Z=document.createElement("div");Z.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",Z.innerHTML="<span>🔒</span><span>Start in Shift Lock</span>";const K=document.createElement("span");K.textContent="❓",K.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",K.addEventListener("mouseenter",e=>g(e,"Automatically enables Shift Lock on page load so you can paint without holding Shift.")),K.addEventListener("mouseleave",p),Z.appendChild(K);const Q=document.createElement("label");Q.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const ee=document.createElement("input");ee.type="checkbox",ee.checked=!!_settings.startShiftLock,ee.style.cssText="opacity:0;width:0;height:0;";const te=document.createElement("span");te.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.startShiftLock?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const ne=document.createElement("span");ne.style.cssText=`\n            position:absolute; top:2px; left:${_settings.startShiftLock?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,te.appendChild(ne),ee.addEventListener("change",()=>{_settings.startShiftLock=ee.checked,saveSettings(_settings),te.style.background=ee.checked?"#22c55e":t?"#585b70":"#cbd5e1",ne.style.left=ee.checked?"22px":"2px"}),Q.appendChild(ee),Q.appendChild(te),$.appendChild(Z),$.appendChild(Q),L.appendChild($);const oe=document.createElement("div");oe.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const re=document.createElement("div");re.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",re.innerHTML="<span>🔍</span><span>Start in Inspect Mode</span>";const ae=document.createElement("span");ae.textContent="❓",ae.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",ae.addEventListener("mouseenter",e=>g(e,"Automatically switches to Inspect Mode on page load instead of starting in Paint (Action) mode.")),ae.addEventListener("mouseleave",p),re.appendChild(ae);const ie=document.createElement("label");ie.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const le=document.createElement("input");le.type="checkbox",le.checked=!!_settings.startInspectMode,le.style.cssText="opacity:0;width:0;height:0;";const se=document.createElement("span");se.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.startInspectMode?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const ce=document.createElement("span");ce.style.cssText=`\n            position:absolute; top:2px; left:${_settings.startInspectMode?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,se.appendChild(ce),le.addEventListener("change",()=>{_settings.startInspectMode=le.checked,saveSettings(_settings),se.style.background=le.checked?"#22c55e":t?"#585b70":"#cbd5e1",ce.style.left=le.checked?"22px":"2px"}),ie.appendChild(le),ie.appendChild(se),oe.appendChild(re),oe.appendChild(ie),L.appendChild(oe);const de=document.createElement("div");de.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const pe=document.createElement("div");pe.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",pe.innerHTML="<span>🔢</span><span>Smooth Zoom Buttons</span>";const ge=document.createElement("span");ge.textContent="❓",ge.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",ge.addEventListener("mouseenter",e=>g(e,"Replaces the +/− zoom buttons with a smooth zoom control: vertical slider, exact value input, hold-to-repeat ± buttons, and scroll-wheel zoom on the widget.")),ge.addEventListener("mouseleave",p),pe.appendChild(ge);const ue=document.createElement("label");ue.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const me=document.createElement("input");me.type="checkbox",me.checked=!!_settings.smoothZoomButtons,me.style.cssText="opacity:0;width:0;height:0;";const he=document.createElement("span");he.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.smoothZoomButtons?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const fe=document.createElement("span");fe.style.cssText=`\n            position:absolute; top:2px; left:${_settings.smoothZoomButtons?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,he.appendChild(fe),me.addEventListener("change",()=>{_settings.smoothZoomButtons=me.checked,saveSettings(_settings),he.style.background=me.checked?"#22c55e":t?"#585b70":"#cbd5e1",fe.style.left=me.checked?"22px":"2px",c.style.display="block"}),ue.appendChild(me),ue.appendChild(he),de.appendChild(pe),de.appendChild(ue),L.appendChild(de);const be=document.createElement("div");be.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const ye=document.createElement("div");ye.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",ye.innerHTML="<span>📱</span><span>Mobile Compatibility</span>";const xe=document.createElement("span");xe.textContent="❓",xe.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",xe.addEventListener("mouseenter",e=>g(e,"Mobile-focused fixes for small or touch screens. Currently disables draggable guild/ghost modals on mobile and makes the ghost menu overhaul switch between controls and preview using the preview collapse button. Refresh the page after toggling.")),xe.addEventListener("mouseleave",p),ye.appendChild(xe);const ve=document.createElement("label");ve.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const we=document.createElement("input");we.type="checkbox",we.checked=!!_settings.mobileCompatibility,we.style.cssText="opacity:0;width:0;height:0;";const ke=document.createElement("span");ke.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.mobileCompatibility?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const Ee=document.createElement("span");Ee.style.cssText=`\n            position:absolute; top:2px; left:${_settings.mobileCompatibility?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,ke.appendChild(Ee),we.addEventListener("change",()=>{_settings.mobileCompatibility=we.checked,saveSettings(_settings),ke.style.background=we.checked?"#22c55e":t?"#585b70":"#cbd5e1",Ee.style.left=we.checked?"22px":"2px",c.style.display="block"}),ve.appendChild(we),ve.appendChild(ke),be.appendChild(ye),be.appendChild(ve),L.appendChild(be);const Ce=document.createElement("div");Ce.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const Se=document.createElement("div");Se.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",Se.innerHTML="<span>🔶</span><span>Enable Debugging</span>";const Te=document.createElement("span");Te.textContent="❓",Te.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",Te.addEventListener("mouseenter",e=>g(e,"When enabled, errors are recorded in memory and a Debug Logs button appears in the dropdown. Click it to export a log file. Refresh the page after toggling.")),Te.addEventListener("mouseleave",p),Se.appendChild(Te);const Pe=document.createElement("label");Pe.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const Le=document.createElement("input");Le.type="checkbox",Le.checked=!!_settings.enableDebug,Le.style.cssText="opacity:0;width:0;height:0;";const Me=document.createElement("span");Me.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.enableDebug?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const Ie=document.createElement("span");Ie.style.cssText=`\n            position:absolute; top:2px; left:${_settings.enableDebug?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,Me.appendChild(Ie),Le.addEventListener("change",()=>{_settings.enableDebug=Le.checked,saveSettings(_settings),Me.style.background=Le.checked?"#22c55e":t?"#585b70":"#cbd5e1",Ie.style.left=Le.checked?"22px":"2px",c.style.display="block"}),Pe.appendChild(Le),Pe.appendChild(Me),Ce.appendChild(Se),Ce.appendChild(Pe),L.appendChild(Ce);const _e=document.createElement("div");_e.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const Ge=document.createElement("div");Ge.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",Ge.innerHTML="<span>🎛️</span><span>Ghost Menu UI Overhaul</span>";const Re=document.createElement("span");Re.textContent="❓",Re.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",Re.addEventListener("mouseenter",e=>g(e,"Requires Ghost Template Manager. Removes the ✚₊ collapse toggle added by geopixels++, shows all its hidden buttons permanently, and applies consistent flat styling to every action button in the ghost palette panel.")),Re.addEventListener("mouseleave",p),Ge.appendChild(Re);const Ne=document.createElement("label");Ne.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const Ae=document.createElement("input");Ae.type="checkbox",Ae.checked=!!_settings.modernizeGhostPaletteBtns,Ae.style.cssText="opacity:0;width:0;height:0;";const ze=document.createElement("span");ze.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.modernizeGhostPaletteBtns?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const Be=document.createElement("span");Be.style.cssText=`\n            position:absolute; top:2px; left:${_settings.modernizeGhostPaletteBtns?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,ze.appendChild(Be),Ae.addEventListener("change",()=>{_settings.modernizeGhostPaletteBtns=Ae.checked,saveSettings(_settings),ze.style.background=Ae.checked?"#22c55e":t?"#585b70":"#cbd5e1",Be.style.left=Ae.checked?"22px":"2px",c.style.display="block"}),Ne.appendChild(Ae),Ne.appendChild(ze),_e.appendChild(Ge),_e.appendChild(Ne),L.appendChild(_e);const Oe=document.createElement("div");Oe.style.cssText=`\n            display: flex; align-items: center; justify-content: space-between;\n            padding: 10px 14px; border-radius: 8px;\n            background: ${t?"#313244":"#f1f5f9"};\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            margin-top: 4px;\n        `;const De=document.createElement("div");De.style.cssText="display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;",De.innerHTML="<span>📌</span><span>Remember ghost template position and size</span>";const je=document.createElement("span");je.textContent="❓",je.style.cssText="cursor:help;font-size:12px;flex-shrink:0;margin-left:4px;opacity:0.6;",je.addEventListener("mouseenter",e=>g(e,"When enabled, saves and restores the ghost template modal's on-screen position and size across page refreshes and re-opens. Requires Ghost Template Manager.")),je.addEventListener("mouseleave",p),De.appendChild(je);const He=document.createElement("label");He.style.cssText="position:relative; width:44px; height:24px; cursor:pointer; flex-shrink:0;";const Fe=document.createElement("input");Fe.type="checkbox",Fe.checked=!!_settings.rememberGhostModalPos,Fe.style.cssText="opacity:0;width:0;height:0;";const Xe=document.createElement("span");Xe.style.cssText=`\n            position:absolute; inset:0; border-radius:12px; transition:0.2s;\n            background: ${_settings.rememberGhostModalPos?"#22c55e":t?"#585b70":"#cbd5e1"};\n        `;const qe=document.createElement("span");qe.style.cssText=`\n            position:absolute; top:2px; left:${_settings.rememberGhostModalPos?"22px":"2px"};\n            width:20px; height:20px; border-radius:50%; transition:0.2s;\n            background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        `,Xe.appendChild(qe),Fe.addEventListener("change",()=>{_settings.rememberGhostModalPos=Fe.checked,saveSettings(_settings),Xe.style.background=Fe.checked?"#22c55e":t?"#585b70":"#cbd5e1",qe.style.left=Fe.checked?"22px":"2px"}),He.appendChild(Fe),He.appendChild(Xe),Oe.appendChild(De),Oe.appendChild(He),L.appendChild(Oe),s.push(L),o.appendChild(L);const Ue=document.createElement("div");Ue.style.cssText="padding: 12px 20px; display: none;";const We=[{key:"openSettings",label:"Open GeoPixelcons++ Settings",defKey:"P",defCtrl:!0,defShift:!0},{key:"mapMovementLock",label:"Toggle Map Movement Lock",defKey:"L",defCtrl:!0,defShift:!0}],Ye={};We.forEach(({key:e,label:n,defKey:o,defCtrl:r,defShift:a})=>{const i=_settings.keybinds&&_settings.keybinds[e]||{key:o,ctrl:r,shift:a},l=document.createElement("div");l.style.cssText=`\n                padding: 10px 14px; border-radius: 8px;\n                background: ${t?"#313244":"#f1f5f9"};\n                border: 1px solid ${t?"#45475a":"#e2e8f0"};\n                margin-bottom: 8px;\n            `;const s=document.createElement("div");s.style.cssText=`font-size:13px;font-weight:600;margin-bottom:8px;color:${t?"#cdd6f4":"#1e293b"};`,s.textContent=n;const c=document.createElement("div");c.style.cssText="display:flex;align-items:center;gap:14px;flex-wrap:wrap;";const d=document.createElement("label");d.style.cssText=`display:flex;align-items:center;gap:5px;font-size:13px;cursor:pointer;color:${t?"#cdd6f4":"#1e293b"};`;const p=document.createElement("input");p.type="checkbox",p.checked=!!i.ctrl,d.appendChild(p),d.appendChild(Object.assign(document.createElement("span"),{textContent:"Ctrl"}));const g=document.createElement("label");g.style.cssText=d.style.cssText;const u=document.createElement("input");u.type="checkbox",u.checked=!!i.shift,g.appendChild(u),g.appendChild(Object.assign(document.createElement("span"),{textContent:"Shift"}));const m=document.createElement("label");m.style.cssText=`display:flex;align-items:center;gap:6px;font-size:13px;color:${t?"#cdd6f4":"#1e293b"};`,m.appendChild(Object.assign(document.createElement("span"),{textContent:"Key:"}));const h=document.createElement("input");h.type="text",h.maxLength=1,h.value=(i.key||o).toUpperCase(),h.style.cssText=`\n                width:36px; padding:4px 8px; border-radius:5px; text-align:center;\n                text-transform:uppercase; font-family:monospace; font-size:13px; font-weight:700;\n                border:1px solid ${t?"#45475a":"#d1d5db"};\n                background:${t?"#181825":"#fff"};\n                color:${t?"#cdd6f4":"#1e293b"};\n            `,h.addEventListener("input",()=>{h.value=h.value.replace(/[^a-zA-Z0-9]/g,"").slice(-1).toUpperCase(),b()}),m.appendChild(h);const f=document.createElement("span");function b(){const e=[];p.checked&&e.push("Ctrl"),u.checked&&e.push("Shift"),h.value&&e.push(h.value.toUpperCase()),f.textContent=e.length?"→ "+e.join("+"):""}f.style.cssText=`font-size:11px;color:${t?"#6c7086":"#94a3b8"};font-family:monospace;`,p.addEventListener("change",b),u.addEventListener("change",b),b(),c.appendChild(d),c.appendChild(g),c.appendChild(m),c.appendChild(f),l.appendChild(s),l.appendChild(c),Ue.appendChild(l),Ye[e]={ctrlEl:p,shiftEl:u,keyEl:h}});const Ve=document.createElement("button");Ve.textContent="💾 Save Shortcuts",Ve.style.cssText="\n            width: 100%; padding: 10px 20px; border-radius: 8px; border: none; cursor: pointer;\n            background: #22c55e; color: #fff; font-size: 14px; font-weight: 600;\n            transition: opacity 0.15s; margin-top: 4px;\n        ",Ve.onmouseover=()=>{Ve.style.opacity="0.85"},Ve.onmouseleave=()=>{Ve.style.opacity="1"},Ve.onclick=()=>{_settings.keybinds||(_settings.keybinds={}),We.forEach(({key:e})=>{const{ctrlEl:t,shiftEl:n,keyEl:o}=Ye[e];_settings.keybinds[e]={ctrl:t.checked,shift:n.checked,key:(o.value||"").toUpperCase().slice(0,1)}}),saveSettings(_settings),c.style.display="block",Ve.textContent="✅ Saved!",setTimeout(()=>{Ve.textContent="💾 Save Shortcuts"},2e3)},Ue.appendChild(Ve),s.push(Ue),o.appendChild(Ue);const Je=document.createElement("div");Je.style.cssText=`\n            padding: 12px 20px;\n            background: ${t?"#313244":"#f8fafc"};\n            border-top: 1px solid ${t?"#45475a":"#e2e8f0"};\n            font-size: 11px;\n            color: ${t?"#6c7086":"#94a3b8"};\n            text-align: center;\n        `,Je.textContent="GeoPixelcons++ v"+VERSION,o.appendChild(Je),n.appendChild(o),n.addEventListener("click",e=>{e.target===n&&(p(),n.remove())}),document.body.appendChild(n)}FEATURE_LIST.forEach(e=>{_featureStatus[e.key]=_settings[e.key]?"pending":"disabled"}),EXTENSION_LIST.forEach(e=>{_featureStatus[e.key]=_settings[e.key]?"pending":"disabled"}),document.addEventListener("keydown",e=>{if(e.repeat||e.altKey||e.metaKey)return;const t=e.target;if(t&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName||t.isContentEditable))return;const n={...DEFAULT_SETTINGS.keybinds.openSettings,..._settings.keybinds&&_settings.keybinds.openSettings||{}},o=n.key||DEFAULT_SETTINGS.keybinds.openSettings.key;n.ctrl===e.ctrlKey&&n.shift===e.shiftKey&&e.key.toUpperCase()===o.toUpperCase()&&(e.preventDefault(),e.stopImmediatePropagation(),createSettingsModal())},!0);const CHANGELOG=[{version:"1.9.6",date:"2026-07-28",items:[{type:"changed",text:"Debug System: six more features (Paint Menu Controls, Region Screenshot, Regions Highscore, Auto-open Menus on Hover, Ghost Template Manager, Pill Hover Labels) that wait for a native page element or global to appear now retry with a bounded giveup and log every step to the Debug Log, instead of polling forever with no diagnostic trail if they never found what they were waiting for"}]},{version:"1.9.5",date:"2026-07-28",items:[{type:"fixed",text:'Ghost Palette Color Search: the ♻️ "Sync Ghost With Selected Color" button could silently fail to mount if the game\'s Image Tools menu hadn\'t rendered yet, with no giveup and no way to tell why from a Debug Log — it now retries the same way Ghost++\'s own button does and logs every step, including whether it stayed hidden behind its own separate "Sync Ghost With Selected Color" display-option checkbox in Settings'}]},{version:"1.9.4",date:"2026-07-28",items:[{type:"added",text:"Debug System: other installed userscripts can now feed their own diagnostic events into this script's Debug Log, so a single exported file can cover more than one addon at once when troubleshooting an interaction between them"}]},{version:"1.9.3",date:"2026-07-28",items:[{type:"fixed",text:'Ghost++: other addons that read the native "which ghost colors are enabled" state directly could see it as empty even with colors correctly enabled in Ghost++ itself, until you happened to open Ghost++\'s own menu at least once — that native state now stays correctly in sync from the moment Ghost++ finishes loading, not just after its menu has been opened'}]},{version:"1.9.2",date:"2026-07-28",items:[{type:"fixed",text:'Ghost++: the separate GeoPixels++ addon\'s "Toggle ghost image" keybind (Y by default) stopped doing anything visible once Ghost++ took over the overlay slot, since it only toggles the native ghost canvas Ghost++ had already emptied out — Y now also toggles Ghost++\'s own overlay, so it still works as a quick "peek at the map" shortcut'}]},{version:"1.9.1",date:"2026-07-27",items:[{type:"fixed",text:"Ghost++: fixed a bug (reported on Firefox) where enabling the Ghost++ setting and reloading could still leave the OLD native ghost tool active instead of switching to Ghost++ — its own init now waits for the page to finish loading, and its native-button replacement now retries if that button hasn't mounted yet instead of silently giving up"},{type:"fixed",text:"Ghost++: the native ghost button was hidden immediately, but a keyboard shortcut (or anything else that clicks it programmatically) could still pop the old native ghost tool before you'd ever manually opened Ghost++ once — the click-blocking that prevents this now activates immediately instead of waiting for your first open"},{type:"added",text:'Ghost++ Progress: clicking "Show errors" or "Show missing" now pops an alert with the resulting count (e.g. "Found 12 errors among your currently enabled colors"), matching the native ghost tool\'s own scan alerts'},{type:"changed",text:"Ghost++ palette: a fully-completed color now shows a large checkmark (with a thin black outline so it stays visible on bright colors) across the whole swatch instead of a small white circle with a tiny check mark, similar in style to how a disabled color shows its diagonal slash"},{type:"added",text:'Ghost++: with Enable Debugging on (Settings), the exported Debug Log now records whether Ghost++ started immediately or waited for the page to finish loading, whether it found (or had to wait for) the native ghost button, and whether it finished initializing successfully or hit an error — so a "Ghost++ doesn\'t seem to be working" report can be diagnosed from an exported log instead of guesswork'},{type:"added",text:'Debug Logs: the exported file now also includes a live state snapshot (every feature\'s enabled/ok/error status, plus a deeper Ghost++-specific dive) captured at the moment you click "Debug Logs" — and the button now always exports something, even with zero recorded events, since the snapshot alone can be the more useful half when something failed too early to log anything'}]},{version:"1.9.0",date:"2026-07-26",items:[{type:"added",text:"New: Ghost++ Template Overlay — a scalable, multi-template ghost/overlay manager (opt-in, enable it in Settings) that can replace the native ghost image tool: draggable/resizable two-column panel, thumbnail template library with hover preview and drag-reorder, sort/filter/search palette with hover-to-copy hex values, segmented completion progress bar, click-to-place positioning with a live cursor-following preview, and a Group Noise implementation matching the native tool's own near-identical-color merging"},{type:"added",text:"Ghost++: keyboard shortcuts — arrow keys nudge the focused template's position one cell at a time, and E enters click-to-place mode"},{type:"added",text:"Ghost++: a \"Guild Templates\" section lists your guild's project templates and loads them in at 0% opacity so they don't immediately cover the map — these are never saved to your template library or written to disk, since guild projects change frequently; they're re-fetched fresh every page load"},{type:"changed",text:"Ghost++ Guild Templates are now TRUE lazy-loaded for real performance with large guilds — expanding the section only fetches the lightweight project list and shows browser-native thumbnails; a template's actual pixel data is only fetched/decoded the first time you click to view it, not for the whole guild up front"},{type:"fixed",text:"Ghost++: a hidden template (0% opacity) — guild or regular — no longer holds a GPU texture / canvas resource at all; previously it was still fully uploaded and just skipped drawing, which was real, avoidable memory and upload cost for large templates"},{type:"added",text:'Ghost++ View Settings: new "Auto-hide unfocused templates" checkbox (off by default) — when on, focusing a template automatically hides every other one, so only ever one is visible at a time; also reduces memory/GPU usage for large libraries'},{type:"fixed",text:'The guild menu\'s "Set as Ghost" button no longer fails with "Could not find the selected project" — it now loads the guild project straight into Ghost++, position included, without ever saving it to your library either'},{type:"added",text:"Ghost++ Manage Templates: a fixed-size Grid view (now the default) alongside the existing List view — click a thumbnail to load/focus that template, plus per-card multiselect, show/hide, and go-to-location buttons; template previews render at full resolution instead of a blurrier shared thumbnail, darkened until you hover, with always-visible corner buttons"},{type:"changed",text:'Ghost++: shows a "Loading templates…" placeholder while your library decodes in the background instead of looking empty; bulk export in Manage Templates now shows real progress and encodes noticeably faster (native browser base64 conversion instead of a manual byte-by-byte loop, small-batch parallel re-encoding)'},{type:"added",text:'Ghost++ palette: bulk actions (All/None/Owned/Match palette/Set palette), "Buy all colors", a "Get hex values" export menu, left/right-click-drag to enable/disable colors, and a "Group Noise Changes" section showing exactly which colors got merged and their combined hex value'},{type:"added",text:'Ghost++ Progress: "Nearest error" teleports instantly and pulses a highlight ring on the exact cell that needs correcting; all teleports (grid/Manage Templates/Nearest error) zoom out further for a better overview and never zoom back in if you\'re already closer'},{type:"fixed",text:"Ghost++: fixed poor performance with thousands of error/missing crosshairs on screen — the redraw math is now computed once per frame instead of once per marker"},{type:"changed",text:"Ghost++ Progress: error/missing pixel counts now always show under the progress bar whenever there are any, instead of only after checking Show errors/Show missing"},{type:"changed",text:"Ghost++ Template Settings: Preview is a separate, transient full-opacity view that never touches your saved Opacity slider; flip/rotate buttons were removed (easy to do in any image editor beforehand)"},{type:"fixed",text:"Ghost++: Unset position, drag-reorder order, and each section's collapsed/expanded state now all persist correctly across reloads"},{type:"fixed",text:"Ghost++: scrollable sections (palette grid, Manage Templates list, main panel) no longer shift the rest of the layout when their scrollbar appears or disappears"},{type:"changed",text:"Ghost++: the whole compatibility shim keeps the guild menu, queue-ghost-color, and other native-ghost-aware tools working correctly while Ghost++ owns the overlay slot"},{type:"changed",text:"Ghost Template Manager and Ghost Palette Color Search remain available as legacy fallbacks, unaffected if you already had them enabled"},{type:"added",text:'Ghost Template Manager: the Group Noise checkbox state is now saved with each history entry and restored automatically when you reload it — overridden as always if "Disable Group Noise" is enabled; templates saved before this update (or imported from older JSON bundles) default to disabled'},{type:"changed",text:"The shipped script is now minified, cutting its file size roughly in half — keeps room to grow well under Greasyfork's size limit"},{type:"added",text:'Ghost++ View Settings: new "Gray unselected color boxes" checkbox (on by default) — turn it off to keep only the diagonal slash on a disabled color and see its true color underneath, instead of also graying/dimming it'},{type:"added",text:'Ghost++ View Settings: new "Palette view" grid/list toggle — list mode turns the color grid into compact rows showing the hex value, placed/total, and a mini progress bar, still affected by the same sort and filters as the grid'},{type:"fixed",text:'Ghost++ guild menu: fixed a crash ("Unsupported index type: null") and a "click does nothing" bug that could both occur if the same guild project was viewed from both the Guild Templates section and "Set as Ghost" — they now correctly share one entry instead of quietly creating a duplicate'},{type:"fixed",text:'Ghost++ Progress: the Scan button (and the rest of that row) no longer gets stuck showing "Scanning…" after you switch templates while a large template\'s scan is still finishing in the background — it now reflects whichever template is actually focused'},{type:"fixed",text:'Ghost++ Progress: automatic scans (on focusing a template, or after placing pixels with Autoscan on) now reliably update the Scan button when they finish, instead of sometimes staying stuck on "Scanning…" until an unrelated action (like toggling a color) happened to refresh it'},{type:"fixed",text:"Ghost Palette Color Search's \"Sync Ghost With Selected Color\" button (under the image group dropdown) works again once Ghost++ is enabled — it now drives Ghost++'s own focused template instead of the native color palette, which Ghost++ leaves empty"},{type:"fixed",text:"Ghost++: a guild template loaded via the guild menu's \"Set as Ghost\" now shows its preview thumbnail and full Template Settings panel like any other template; its position is always locked (checkbox forced on and disabled) since guild templates can't be moved from this UI"},{type:"fixed",text:"Ghost++: worked around a Firefox-only CSS Grid bug where the color palette and Templates grids could collapse/stack their cells on top of each other (instead of showing squares) once the side panel got narrow"},{type:"removed",text:'Ghost++: removed the in-panel "Guild Templates" browsing section — the guild menu\'s own "Set as Ghost" button remains fully supported for loading a guild project into Ghost++'},{type:"changed",text:'Ghost++ View Settings: "Auto-hide unfocused templates" is now on by default and renamed to "Only show current template on map"'},{type:"fixed",text:"Ghost++: reopening the panel repeatedly no longer gets progressively slower — the panel's content areas are now built once instead of torn down and rebuilt on every open, which was silently piling up duplicate event listeners the longer a session went on (worse with a larger template library)"},{type:"fixed",text:"Ghost++: the left panel's header and every section's horizontal divider now reach the true edge of the panel instead of stopping short — an ambient padding rule (plus a redundant, unused scrollbar reservation) on the panel container was insetting content that should have spanned edge to edge"},{type:"changed",text:'Ghost++ palette: "Get hex values", "Filters", and the Sort dropdown now have centered text'},{type:"changed",text:"Ghost++ palette: the bulk color-selection buttons are now three clearer rows — Enable all/Disable all, Enable owned/Enable filtered, Match palette/Set palette — instead of one row of terse labels"},{type:"added",text:'Ghost++ palette: new "Enable filtered" button — enables only the colors currently matching your search/filters and disables the rest'},{type:"fixed",text:"Ghost++ Progress: a template that was already loaded before you refreshed the page now automatically scans the first time you open Ghost++, instead of sitting with no progress shown until you manually click Scan or switch templates away and back"},{type:"fixed",text:"Ghost++: the Place/Unset/Go to/Preview button row now wraps onto extra lines as you drag the panel splitter narrower, instead of overflowing past the right panel's edge and disappearing behind the left panel"},{type:"added",text:'Ghost++: the drop zone now has an "or load from a URL" option alongside drop/paste/click-to-choose, matching the legacy Ghost Template Manager\'s own URL upload — paste an image or exported .json template URL and it ingests the same way a local file would'}]},{version:"1.8.2",date:"2026-06-15",items:[{type:"fixed",text:"Keyboard Shortcuts: Ctrl+Shift+P now reliably opens the GeoPixelcons++ Settings modal without conflicting with the site's H shortcut; saved copies of the old Ctrl+Shift+H default migrate automatically"}]},{version:"1.8.1",date:"2026-06-15",items:[{type:"fixed",text:'Guild Search Button: the search control now expands to show its "Search Guilds" hover label like the other left-side submenu buttons'}]},{version:"1.8.0",date:"2026-06-15",items:[{type:"added",text:'GeoPixelcons++ Settings: new "Keybindings" tab to customise the keyboard shortcuts for "Open Settings" and "Toggle Map Movement Lock" — each has Ctrl / Shift checkboxes and a single key input; changes take effect after a page refresh'},{type:"changed",text:'Ghost Palette Color Search: "Pixel count range" filter is now a checkbox called "Filter within pixel count…" matching the other filter options — checking it reveals the min / max inputs beneath'},{type:"added",text:'Ghost Palette Color Search: new "Owned colors only" filter checkbox — hides all ghost palette colors not owned by the current user'},{type:"added",text:'Region Screenshot: "Show Palette" button in the preview modal extracts all unique colors from the captured region, shows pixel counts per color, and provides a copy-to-clipboard hex list'},{type:"added",text:"Guild Search Button: new extra extension — inserts a search icon button below the Guild menu button that opens the Guild Search modal, letting guild members search other guilds without leaving their own"},{type:"added",text:"Log Out Button: new extra extension — appends a log-out icon button to the right controls panel; auto-hides while the user is signed out and reappears on login"}]},{version:"1.7.0",date:"2026-06-14",items:[{type:"added",text:'Theme Editor: light themes now have a "Marsh / Wetland (tufts)" control under Land & Nature — a visibility toggle plus opacity slider to hide or fade the grass-tuft texture that previously could not be removed or recolored'},{type:"added",text:'Theme Editor: added a "Grass" color row under Land & Nature to recolor or hide the flat grass landcover tint'},{type:"added",text:'Theme Editor: added a global "Road Width" slider under Roads that scales all road line widths (light and dark bases) while preserving zoom-based scaling'},{type:"changed",text:'Theme Editor: light "Roads" controls now cover casings, ramps/links, service roads, bridges and tunnels (grouped by class) so orange road outlines can be fully hidden or recolored — previously the casing stayed visible'},{type:"added",text:'Ghost Palette Color Search: added a "Pixel count range" (min/max) filter in the Filters dropdown to show only colors within a given pixel-count range'},{type:"added",text:"Map Movement Lock: added a Ctrl+Shift+L keyboard shortcut to toggle the lock"},{type:"fixed",text:"Ghost Template Manager: collapsing/expanding the preview panel no longer resets the modal's total width — it keeps the controls width fixed and only adds or removes the preview on the right"}]},{version:"1.6.0",date:"2026-06-01",items:[{type:"added",text:"GeoPixelcons++ main panel: added Ctrl+Shift+H keyboard shortcut to toggle the main dropdown panel open and closed"}]},{version:"1.5.0",date:"2026-05-25",items:[{type:"added",text:'Ghost Template Manager: added an "Enable owned and filtered" button beside "Enable filtered" that enables only owned ghost colors currently shown by the active search/filter controls'},{type:"added",text:"Map Movement Lock: added a settings-controlled extension that creates a right-side lock button to freeze map panning and zooming until unlocked"},{type:"added",text:"GeoPixelcons++ Settings: added a Mobile Compatibility toggle that disables draggable guild/ghost modals on mobile and makes the Ghost Menu UI Overhaul switch between controls and preview instead of squeezing both panels onscreen"},{type:"fixed",text:'Ghost Template Manager: clicking "Place on Map" now temporarily hides the ghost menu overhaul so the map is unobstructed while choosing the ghost placement point'},{type:"changed",text:"Map Movement Lock: locking movement now also suppresses page-wide browser scrolling so oversized UI cannot move the viewport separately from the map"}]},{version:"1.4.0",date:"2026-05-21",items:[{type:"added",text:'GeoPixelcons++ Settings: new "Remember ghost template position and size" toggle — when enabled, saves and restores the ghost template modal\'s on-screen position and size across page refreshes; requires Ghost Template Manager to be enabled'},{type:"changed",text:'Ghost Palette Color Search: replaced the bulky multi-select list with a compact Filters dropdown of checkboxes; added "Hide in-progress colors" and "Hide unstarted colors" alongside the existing unmatched/completed filters'},{type:"changed",text:'Ghost Palette Color Search: search is now a compact one-line textarea that also accepts space-separated and newline-separated terms, and "Show search results first" now sits directly below it'},{type:"added",text:'Ghost Palette Color Search: new wheelable "Sort by" dropdown — sort by most/least used, most/least remaining, most/least percent remaining, or color hex; returning to Most used now re-sorts correctly after other methods'},{type:"changed",text:"Ghost Palette Color Search: Sort by is now self-labeled inside the dropdown text, matching the compact Filters control without a separate external label"},{type:"changed",text:"Ghost Palette Color Search: Filters and Sort by now stack vertically based on the actual search panel width, so narrowing the Ghost Menu UI Overhaul left panel moves Sort by below Filters even on wide screens"},{type:"changed",text:"Ghost Palette Color Search: progress-dependent filters and sort methods now hide automatically until placed/total ghost progress stats are detected, while search, unmatched filtering, most/least used, and color sorting remain available"},{type:"changed",text:'Ghost Palette Color Search: "Enable filtered" now enables the colors currently visible in the ghost palette and disables hidden colors, so it works with search plus every filter combination'},{type:"fixed",text:'Ghost Template Manager: "Remember ghost template position and size" now reapplies saved geometry after the modal layout initializes and after the native open button runs, preventing the default centered size from overwriting saved placement'},{type:"changed",text:"Ghost Template Manager: the middle divider in the Ghost Menu UI Overhaul modal can now be dragged from roughly 5% to 95% of the modal width, allowing either side to be nearly minimized or maximized"},{type:"fixed",text:"Ghost Template Manager: bottom-right modal resizing now preserves the current left/right split ratio so the whole modal feels like it is resizing instead of only expanding the left panel"},{type:"added",text:"Ghost Template Manager: Recent thumbnails now show compact inline more/less tiles when history has more than 10 images, expanding from 10 to 50 recent templates in a scrollable fixed-square grid"},{type:"added",text:"Region Screenshot: preview modal now has a Background selector with the existing transparent export plus a new solid color option; the chosen color applies to preview, download, and clipboard copy"},{type:"changed",text:"Region Screenshot: Background mode and solid color are now remembered between screenshots, including silent downloads, so repeated captures reuse the last chosen background"},{type:"added",text:"Bulk Purchase Colors: the profile queue now has the same sorting methods as the ghost palette controls, including wheel-to-change sorting and ghost-progress-aware remaining/% remaining options"},{type:"changed",text:"Bulk Purchase Colors: profile queue rows and the queue Sort by dropdown now use Tailwind-compatible theme colors so they match GeoPixels++ Simple Black and other site themes; ghost counts now show color-formatted total, placed/total, and completion percentage"}]},{version:"1.3.25",date:"2026-05-18",items:[{type:"added",text:"Ghost Template Manager: added a draggable horizontal divider between the preview image and the action buttons — drag up/down to freely set the preview height, overriding the default aspect-ratio sizing"}]},{version:"1.3.24",date:"2026-05-18",items:[{type:"fixed",text:"Ghost Template Manager: preview image container now uses aspect-ratio (4:3) instead of a fixed 210px height, so the preview scales taller as the user widens the right panel with the splitter"}]},{version:"1.3.23",date:"2026-05-18",items:[{type:"added",text:"Ghost Template Manager: added a draggable panel splitter on the left edge of the preview panel — drag left to widen the right panel (giving the image preview more space), drag right to shrink it; width is remembered across collapse/expand cycles"}]},{version:"1.3.22",date:"2026-05-17",items:[{type:"added",text:"Ghost Palette Color Search: new ♻️ 'Sync Ghost With Selected Color' toggle button injected into the Image Tools (🖼️) dropdown — when active (green), changing the selected paint color automatically enables only that color in the ghost palette and disables all others; ignored if the color is not in the template"},{type:"added",text:"Ghost Palette Color Search: Sync Ghost button is hidden by default; enabled via a new ♻️ Sync Ghost With Selected Color row in the Extensions tab (under Additional Extensions), with the same green/red state styling as other extension rows"},{type:"changed",text:"Settings modal — Extra Settings tab: replaced all nine per-row description divs with compact inline ❓ tooltip icons; hovering shows the description in a floating tooltip, significantly reducing the tab height"},{type:"changed",text:"Settings modal — Extensions tab: removed the 🟢/🔴/🟡 status dot from all feature and extension toggle rows; enabled/disabled state is already conveyed by the toggle switch color"}]},{version:"1.3.21",date:"2026-05-14",items:[{type:"fixed",text:"Start Shift Lock: the Find Art button now works correctly when shift-lock is active — FindRandomArt is patched to temporarily call toggleShiftDown() around each invocation, since shiftDown is a closure variable that cannot be overridden directly"}]},{version:"1.3.20",date:"2026-05-13",items:[{type:"fixed",text:"Ghost Template Manager (overhaul): the bottom-right resize handle now correctly adjusts the modal width while the preview panel is collapsed, updating the collapsed width variable so the CSS rule does not block the resize"}]},{version:"1.3.19",date:"2026-05-13",items:[{type:"fixed",text:"Ghost Template Manager (overhaul): rebuilt the Collapse preview / Expand preview animation so the modal and right preview panel resize together using a coordinated CSS state, avoiding the left-panel jump/reflow jank during toggles"}]},{version:"1.3.18",date:"2026-05-13",items:[{type:"fixed",text:"Ghost Template Manager (overhaul): action buttons (Toggle All, Set Palette, Match My Palette, Bulk Purchase Colors, Enable Only Owned Ghost Colors, Get/Set Ghost Colors, Enable filtered) no longer wrap text — long labels truncate with ellipsis and the full text appears on hover"},{type:"fixed",text:'Ghost Template Manager (overhaul): clicking "Collapse preview" now shrinks the entire modal instead of expanding the left panel to fill the freed space; the modal width is restored when the right panel is re-expanded'}]},{version:"1.3.17",date:"2026-05-13",items:[{type:"fixed",text:"Ghost Template Manager: importing a JSON history export then immediately re-opening history no longer reverses the order — entries are now inserted oldest-first so the newest-first display order is preserved after import"},{type:"fixed",text:"Ghost Template Manager: loading a template from the history modal (card click or Load & Go To) now moves that entry to the top of history to reflect recency; the recent-image strip (Ghost Menu UI Overhaul) is also refreshed to stay in sync"},{type:"fixed",text:"Ghost Template Manager: clicking a recent-image thumbnail now promotes that entry to the top of history and immediately refreshes the recent strip so the order stays accurate"}]},{version:"1.3.16",date:"2026-05-12",items:[{type:"added",text:'Ghost Template Manager: new "Ghost Menu UI Overhaul" setting (off by default) — when enabled, removes the ✚₊ collapse toggle injected by geopixels++, makes all its hidden buttons permanently visible, and applies a unified flat slate styling to every action button under the ghost palette container'},{type:"changed",text:'Ghost Palette Color Search: removed the ✅ emoji from the "Enable filtered" button and moved it out of the search filter box into its own row above the search container, closer to the other ghost color enable/disable buttons'},{type:"added",text:'Ghost Template Manager: full modal layout overhaul (requires "Ghost Menu UI Overhaul") — widens the modal to a two-column layout with a collapsible right panel; image preview, action buttons (URL / File / History / Save Pos / Place on Map / Clear Image), and recent-image history are moved to the right panel; left panel retains scroll content (progress, filter controls, color palette)'},{type:"added",text:'Ghost Palette Color Search: "Hide completed colors" checkbox — when checked, hides all color swatches whose geopixels++ progress badge shows 100% (detected from the multiline title set by the Refresh % button); works independently of and combines with the existing "Hide unmatched colors" filter'},{type:"added",text:"Ghost Template Manager: modal is draggable from the header bar and all 4 edges (grab cursor feedback); resizable from the bottom-right SE corner handle only (guild modal pattern); initial size 800×75vh; conflicting Tailwind classes stripped so resize works without !important fights"},{type:"fixed",text:"Ghost Template Manager: ghostColorPalette max-height (Tailwind max-h-48) overridden so the palette expands freely with its content instead of capping at 192px"},{type:"fixed",text:"Ghost Template Manager: recent-image grid rows no longer spread to fill the panel height — align-content:start packs them to the top"},{type:"fixed",text:"Ghost Template Manager: close button was invisible (bg-white on bg-white header); now theme-aware with transparent background and visible hover state; falls back to a freshly created button if the site's onclick selector returns null"},{type:"fixed",text:"Ghost Template Manager: preview image was not showing — container detection was matching the outermost ancestor div instead of the direct parent of #ghostPreviewImage; fixed to use parentElement of the image itself"}]},{version:"1.3.15",date:"2026-05-11",items:[{type:"changed",text:"Source refactored into modular build system (src/ + build.js) — no functional changes for end users; versioned output files are unchanged"}]},{version:"1.3.14",date:"2026-05-11",items:[{type:"added",text:"Map Markers: re-added GIF support — upload animated GIFs as map markers; rendered as a live DOM overlay (positioned relative to the map container, using CSS-pixel coordinates to fix the zoom-level skew bug) so animation plays correctly while the canvas handles static images as before"}]},{version:"1.3.13",date:"2026-05-10",items:[{type:"removed",text:"Map Markers: removed GIF and MP4/video upload support — file picker now accepts PNG/JPEG/WebP only; the Video URL button has been removed; all GIF/video overlay rendering code has been eliminated"}]},{version:"1.3.12",date:"2026-05-10",items:[{type:"changed",text:"Map Markers: compact card view is now the default on open"},{type:"fixed",text:"Map Markers: drag-to-sort handle in full card view no longer blocks the opacity slider — only the ⠇ grip icon initiates a drag; the rest of the card is fully interactive"},{type:"fixed",text:"Map Markers: uploaded MP4/WebM video markers now render visibly — the data URL is converted to a blob URL before being set as the video src (browsers silently fail to play large data-URL videos); autoplay is deferred until after the element is in the DOM"},{type:"fixed",text:"Map Markers: GIF overlays no longer compress horizontally when zooming — removed contain:strict from the overlay container, which was preventing objectFit from applying correctly to img elements inside a CSS containment context"}]},{version:"1.3.11",date:"2026-05-10",items:[{type:"added",text:"Ghost Palette Color Search: “Enable filtered” button next to “Hide unmatched colors” — when clicked, every color whose hex matches the current search terms is enabled in the ghost palette and every non-matching color is disabled; also clears the “Show All” (disable filter) toggle if it was active"},{type:"fixed",text:"Map Markers: YouTube markers no longer use an <iframe> (blocked by site CSP frame-src) — now renders as a clickable thumbnail overlay (thumbnail fetched via GM_xmlhttpRequest to bypass img-src CSP); clicking opens the video in a new tab"},{type:"removed",text:"Map Markers: YouTube embed markers removed — the site CSP blocks both iframe embedding and direct thumbnail image loading; the workaround was too limited to be useful"}]},{version:"1.3.10",date:"2026-05-10",items:[{type:"fixed",text:'Map Markers: image/GIF/video data now stored in IndexedDB instead of GM_setValue — eliminates the "Message exceeded maximum allowed size of 64MiB" Chrome extension runtime error that occurred when many large images were stored, which blocked all other Tampermonkey userscripts from loading'},{type:"added",text:"Map Markers: automatic one-time migration — existing marker images stored in the old GM_setValue keys are moved to IndexedDB on first load and the old keys are cleaned up"}]},{version:"1.3.9",date:"2026-05-10",items:[{type:"added",text:"Map Markers: GIF and MP4 embeds — upload animated GIFs or MP4 videos as map markers; rendered as live DOM overlays so animation/playback is preserved (GIF plays, video autoplays muted/looped)"},{type:"added",text:"Map Markers: drag-to-sort — grab the ⠿ handle on any marker card and drag it up or down to reorder the marker rendering/list order; new order is persisted immediately"},{type:"added",text:"Map Markers: compact card view — toggle button in the modal header switches to a condensed single-row view showing thumbnail, name, and coordinates only; clicking any compact card expands it in-place to reveal the full controls"}]},{version:"1.3.8",date:"2026-05-10",items:[{type:"added",text:"Smooth Zoom Buttons: new extra setting (on by default) — replaces the native +/− zoom buttons with a smooth zoom control: vertical slider, exact value input box, hold-to-repeat ± buttons, and scroll-wheel zoom on the widget"}]},{version:"1.3.7",date:"2026-05-10",items:[{type:"added",text:"Map Markers: new feature — upload any PNG/JPEG/WebP/GIF image and place it as a persistent sticker on the map canvas; images scale and translate with the map in real time using the same grid coordinate system as Censor rects in GeoPixels++"},{type:"added",text:"Map Markers: “Place on Map” button enters placement mode for a specific marker — hold and drag to define the bounding box; click without dragging is rejected with an instructional message"},{type:"added",text:"Map Markers: Hold Shift during placement drag to lock the image’s natural aspect ratio; per-marker 🔒/🔓 toggle persists the lock preference for future edits"},{type:"added",text:"Map Markers: “Edit” button shows 8 fixed-size handles (4 corners + 4 edge midpoints) for resizing/stretching; handles are a consistent 6 px radius regardless of map zoom level; corner drags respect the Shift / lock-aspect setting, edge midpoints stretch freely"},{type:"added",text:"Map Markers: draggable management modal with per-image thumbnail, name input, opacity slider, visibility toggle, Place / Edit / Remove actions, and placement status"},{type:"added",text:"Map Markers: images and placement state persisted via GM_setValue — survive page refreshes; image data stored per-marker under separate keys to keep the metadata payload small"}]},{version:"1.3.6",date:"2026-05-09",items:[{type:"fixed",text:"Ghost Template Manager: loading from Image History with encoded coords placed the image at the old position — root cause: applyCoordinatesToGame called initializeGhostFromStorage before the game's FileReader had written ghostImageData to localStorage, so it returned early; fix: write ghostImageCoords immediately, then poll until BOTH the place button is re-enabled AND ghostImageData is present before calling initializeGhostFromStorage"},{type:"fixed",text:"Ghost Template Manager: ‘Go To’ button said “No ghost image template currently set” after loading from History — ghostImageCoords is now written before the poll starts so it is always available"},{type:"fixed",text:"Ghost Template Manager: loading a new image with no encoded position cleared ghostImageCoords from localStorage — if the user had manually placed a previous image the overlay appeared positioned but saving produced no coords; coords are now only cleared by the explicit Clear button"},{type:"fixed",text:"Ghost Template Manager: ‘Go To’ button in the panel said “No ghost image template currently set” after loading from History because ghostImageTopLeft (in-memory, page scope) was never set by the race-losing initializeGhostFromStorage call — fixed by the same direct-assignment approach above"},{type:"fixed",text:"Region Screenshot: screenshot filenames now use local time instead of UTC — falls back to UTC if local time formatting fails"}]},{version:"1.3.5",date:"2026-05-08",items:[{type:"changed",text:"Paint Brush Swap: reduced to a single resize handle — top-right corner when the paint menu is at the bottom (default), bottom-right corner when the paint menu is docked to the top; height drag direction flips accordingly"},{type:"added",text:"Paint Brush Swap: ↺ reset-size button in the footer clears the stored width/height and restores the dropdown to its natural size"}]},{version:"1.3.4",date:"2026-05-08",items:[{type:"fixed",text:"Paint Brush Swap: collapsed brush dropdown was intercepting canvas clicks after any resize drag — the div retained its physical footprint despite being visually hidden; fixed with pointer-events:none on the closed state and pointer-events:auto on .open"},{type:"fixed",text:"Paint Brush Swap: resize drag was laggy because the CSS max-height transition kept firing on every mousemove; transitions are now disabled for the duration of the drag via a .brush-swap-resizing class and restored on mouseup"}]},{version:"1.3.3",date:"2026-05-08",items:[{type:"fixed",text:"Paint Brush Swap: resize handles on the brush dropdown were jittery and drifting — now use capture-phase listeners, a single start-size snapshot, and set explicit width alongside maxWidth/maxHeight to match the guild panel resize behavior"}]},{version:"1.3.2",date:"2026-05-08",items:[{type:"changed",text:"Paint Brush Swap — Export: brush list now shows as a scrollable checklist with checkboxes; Select All / Select None controls; JSON output and Copy/Download actions only include checked brushes; header updates live to show selection count"},{type:"changed",text:"Paint Brush Swap — Import: JSON is parsed on input/file-upload and immediately rendered as a scrollable checklist; only checked brushes are committed when clicking “Import Selected”; invalid entries still reported with a count"}]},{version:"1.3.1",date:"2026-05-08",items:[{type:"changed",text:'Paint Brush Swap: Export/Import footer buttons now show "📤 Export" and "📥 Import" labels instead of bare arrows — same height, wider to fit the text'}]},{version:"1.3.0",date:"2026-05-07",items:[{type:"added",text:"Paint Brush Swap: Export Brushes — ⬆ button at the bottom of the brush dropdown opens a modal with the full brush list as JSON; copy to clipboard or download as a .json file"},{type:"added",text:"Paint Brush Swap: Import Brushes — ⬇ button opens a modal where you can paste JSON or upload a .json file; imported brushes are appended to your existing list (no overwrites), invalid entries are skipped with a count"}]},{version:"1.2.2",date:"2026-05-07",items:[{type:"fixed",text:'Ghost Template Manager: loading a template from Image History that was saved without coordinates threw "parameter 1 is not of type File" — images retrieved from IndexedDB are Blobs, not Files; when no encoded position is decoded the blob is now wrapped in a File before being passed to DataTransfer'}]},{version:"1.2.1",date:"2026-05-06",items:[{type:"fixed",text:"Debug System: applyCoordinatesToGame now logs to the debug file when the place button never becomes enabled (5s timeout) or when initializeGhostFromStorage is missing from page scope — both are silent failures that previously produced no debug output"},{type:"fixed",text:"Debug System: IndexedDB open failure now rejects with a real Error object (was a bare string) and is captured in the debug log, making DB unavailability visible"},{type:"fixed",text:"Debug System: HistoryManager.getAll transaction errors now reject (instead of hanging forever) and are captured in the debug log"},{type:"fixed",text:"Debug System: cleanCanvas.toBlob inside processAndLoadImage now has a 10s timeout — if the browser never calls the callback the hang is caught, logged, and the load fails gracefully instead of stalling silently"}]},{version:"1.2.0",date:"2026-05-06",items:[{type:"added",text:'Debug System: new "Enable Debugging" toggle in Settings — when on, a "Debug Logs" button appears in the dropdown that exports a timestamped .txt log of all caught errors with their UI component, message, and stack trace'},{type:"added",text:"Debug System: all feature initialization catch blocks, Ghost Template Manager operations (processAndLoadImage, URL upload, Save Pos, Auto-Cache, Export, Import history), and card interactions now feed into dbgPush when debugging is enabled"}]},{version:"1.1.9",date:"2026-04-26",items:[{type:"fixed",text:"Guild XP Tracker: player markers on map showed numeric user IDs instead of display names — buildPlayerMarkerData was using the dict key (now a numeric ID) as the name; fixed to use data.name with key as fallback"},{type:"added",text:'Ghost Template Manager: selective export in Image History — ☐ per-card checkbox, Select All / Select None buttons, and "Export Selected" exports only checked templates (same JSON format; compatible with import); "Export All" removed in favour of Select All + Export Selected'}]},{version:"1.1.8",date:"2026-04-26",items:[{type:"fixed",text:"Auto-Hover Menus: menuGroupBtn and modGroupBtn have class=\"... relative ...\" on the button element itself — button.closest('.relative') returned the button instead of the wrapper div, so parent/dropdown/isMenuOpen were all wrong and every button→dropdown mousemove re-toggled the menu closed; fixed by using button.closest('div.relative'); also added _gpcOpened flag + wrapper mouseleave guard as a defensive layer against re-clicks on re-hover"},{type:"fixed",text:"Guild XP Tracker: users who rename no longer appear as LEFT + JOINED — snapshots now key by numeric user ID; display name is stored separately and stays current"},{type:"fixed",text:"Guild XP Tracker: one-time migration auto-converts old name-keyed snapshots to ID-keyed format so existing history remains valid"},{type:"fixed",text:"Brush Editor (Opera GX failsafe — pending end-user validation): after panel closes, overlay gets pointer-events:none + visibility:hidden to prevent ghost click-through on browsers that may not apply Tailwind hidden reliably"},{type:"added",text:"Brush Editor: left-click (or drag) immediately activates cells; right-click (or drag) erases — no toggle delay"},{type:"added",text:'Brush Editor: "Fill All" button beside "Reset Active Brush" — instantly activates every cell in the grid'}]},{version:"1.1.7",date:"2026-04-19",items:[{type:"added",text:'Setting: Disable Group Noise — permanently unchecks and grays out the "Group Noise" toggle in the ghost modal'},{type:"added",text:"Setting: Start in Shift Lock — auto-enables Shift Lock on page load"},{type:"added",text:"Setting: Start in Inspect Mode — auto-switches to Inspect Mode on page load"},{type:"added",text:"Changelog modal accessible from the GeoPixelcons++ dropdown menu"}]},{version:"1.1.6",date:"2026-04-19",items:[{type:"renamed",text:'Extension: "Janny Tools" renamed to "Janitor View" throughout'},{type:"added",text:"Setting: Compact Paint Controls — moves ✕ close and 🖌️ brushes buttons above the paint modal as compact icons"},{type:"added",text:"Compact brush button forwards scroll-to-swap wheel events"},{type:"added",text:"Compact brush dropdown repositioned via fixed positioning on document.body to avoid transform issues"},{type:"added",text:"Compact ✕ button positioned absolutely to the right of the topBar, isolated from centered buttons"},{type:"improved",text:"Ghost template colors now sorted by pixel count (most used → least used) in both bulk purchase paths"},{type:"added",text:"Bulk purchase modal and profile queue now show ghost template pixel counts per color (purple labels)"},{type:"added",text:'Legend in bulk purchase modal: "Purple numbers = pixels used in the loaded ghost template"'},{type:"added",text:"Ghost palette MutationObserver auto-refreshes queue ghost counts when template is loaded/unloaded"}]},{version:"1.1.4",date:"2026-04-18",items:[{type:"added",text:"Extension: Janitor View — reveals the hidden moderation button for janitors/moderators"},{type:"fixed",text:"VERSION constant now correctly synced with @version header (was stuck at 1.0.3)"}]},{version:"1.1.3",date:"2026-04-17",items:[{type:"note",text:"Version bump — identical to 1.0.3 (header version sync)"}]},{version:"1.0.3",date:"2026-04-17",items:[{type:"fixed",text:"Guild Overhaul: auto-center panel on open — fixes draggable guild panel getting stuck off-screen"},{type:"improved",text:"Bulk Purchase: newly purchased colors are now automatically added to the active palette"}]},{version:"1.0.2",date:"2026-04-16",items:[{type:"added",text:"Paint Brush Swap: click-to-expand brush preview grids (36×36 → 120×120)"},{type:"added",text:'Brush preview tooltip on hover ("click to expand")'},{type:"fixed",text:"Region Screenshot & Regions Highscore: no longer re-enable doubleClickZoom (respects site default)"}]},{version:"1.0.0",date:"2026-04-15",items:[{type:"note",text:"Initial release — unified enhancement suite"},{type:"added",text:"Features: Bulk Purchase Colors, Ghost Palette Search, Ghost Template Manager, Guild Overhaul, Paint Menu Controls, Paint Brush Swap, Region Screenshot, Regions Highscore, Theme Editor"},{type:"added",text:"Extensions: Auto-open Menus on Hover, Auto-Go to Last Location, Hover Labels"},{type:"added",text:"Settings modal with per-feature toggles, status indicators, and emoji icon option"}]}];function showChangelog(){const e=document.getElementById("gpc-changelog-modal");e&&e.remove();const t=isDarkMode(),n=document.createElement("div");n.id="gpc-changelog-modal",n.style.cssText="position:fixed;inset:0;z-index:100001;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.5);";const o={added:{bg:t?"#052e16":"#f0fdf4",text:t?"#4ade80":"#166534",label:"NEW"},improved:{bg:t?"#1e1b4b":"#eef2ff",text:t?"#818cf8":"#4338ca",label:"IMPROVED"},fixed:{bg:t?"#422006":"#fffbeb",text:t?"#fbbf24":"#92400e",label:"FIX"},renamed:{bg:t?"#164e63":"#ecfeff",text:t?"#22d3ee":"#0e7490",label:"RENAMED"},changed:{bg:t?"#1c1917":"#fafaf9",text:t?"#a8a29e":"#57534e",label:"CHANGED"},removed:{bg:t?"#450a0a":"#fff1f2",text:t?"#f87171":"#9f1239",label:"REMOVED"},note:{bg:t?"#1e293b":"#f8fafc",text:t?"#94a3b8":"#64748b",label:"NOTE"}},r=document.createElement("div");r.style.cssText=`\n            background: ${t?"#1e1e2e":"#ffffff"};\n            color: ${t?"#cdd6f4":"#1e293b"};\n            border-radius: 16px;\n            width: 90%;\n            max-width: 560px;\n            max-height: 80vh;\n            display: flex;\n            flex-direction: column;\n            box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n            overflow: hidden;\n        `;const a=document.createElement("div");a.style.cssText=`\n            padding: 20px 24px 16px;\n            border-bottom: 1px solid ${t?"#45475a":"#e2e8f0"};\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            flex-shrink: 0;\n        `;const i=document.createElement("h2");i.style.cssText="margin:0;font-size:1.25rem;font-weight:700;",i.textContent="📋 Changelog";const l=document.createElement("button");l.style.cssText=`width:2rem;height:2rem;border-radius:50%;border:none;background:${t?"#45475a":"#f1f5f9"};cursor:pointer;font-size:1rem;display:flex;align-items:center;justify-content:center;color:${t?"#cdd6f4":"#64748b"};`,l.textContent="✕",l.addEventListener("click",()=>n.remove()),a.appendChild(i),a.appendChild(l),r.appendChild(a);const s=[...new Set(CHANGELOG.flatMap(e=>e.items.map(e=>e.type)))],c=["added","fixed","improved","changed","removed","renamed","note"];s.sort((e,t)=>{const n=c.indexOf(e),o=c.indexOf(t);return(-1===n?99:n)-(-1===o?99:o)});const d=document.createElement("div");d.style.cssText=`display:flex;flex-wrap:wrap;gap:6px;padding:10px 24px;border-bottom:1px solid ${t?"#45475a":"#e2e8f0"};flex-shrink:0;`;const p=new Set(s);s.forEach(e=>{const t=o[e]||o.note,n=document.createElement("button");n.style.cssText=`font-size:0.6rem;font-weight:700;padding:3px 8px;border-radius:4px;border:none;cursor:pointer;transition:opacity .15s;background:${t.text}18;color:${t.text};`,n.textContent=t.label,n.title=`Toggle ${t.label} entries`,n.dataset.active="1",n.addEventListener("click",()=>{p.has(e)?(p.delete(e),n.dataset.active="0",n.style.opacity="0.35"):(p.add(e),n.dataset.active="1",n.style.opacity="1"),g.querySelectorAll("[data-cl-type]").forEach(e=>{e.style.display=p.has(e.dataset.clType)?"":"none"}),g.querySelectorAll("[data-cl-section]").forEach(e=>{const t=[...e.querySelectorAll("[data-cl-type]")].some(e=>"none"!==e.style.display);e.style.display=t?"":"none"})}),d.appendChild(n)}),r.appendChild(d);const g=document.createElement("div");g.style.cssText="overflow-y:auto;padding:16px 24px 24px;flex:1;",CHANGELOG.forEach((e,n)=>{const r=document.createElement("div");r.dataset.clSection=e.version,r.style.cssText=`margin-bottom:${n<CHANGELOG.length-1?"20px":"0"};`;const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:10px;margin-bottom:10px;";const i=document.createElement("span");i.style.cssText=`font-size:0.95rem;font-weight:700;color:${t?"#cba6f7":"#7c3aed"};`,i.textContent="v"+e.version;const l=document.createElement("span");if(l.style.cssText=`font-size:0.75rem;color:${t?"#6c7086":"#94a3b8"};`,l.textContent=e.date,a.appendChild(i),a.appendChild(l),0===n){const e=document.createElement("span");e.style.cssText=`font-size:0.6rem;font-weight:700;padding:2px 6px;border-radius:4px;background:${t?"#22c55e33":"#dcfce7"};color:${t?"#4ade80":"#166534"};`,e.textContent="CURRENT",a.appendChild(e)}if(r.appendChild(a),e.items.forEach(e=>{const n=o[e.type]||o.note,a=document.createElement("div");a.dataset.clType=e.type,a.style.cssText=`display:flex;align-items:flex-start;gap:8px;padding:5px 8px;margin-bottom:3px;border-radius:6px;background:${n.bg};`;const i=document.createElement("span");i.style.cssText=`font-size:0.55rem;font-weight:700;padding:2px 5px;border-radius:3px;color:${n.text};background:${n.text}18;white-space:nowrap;margin-top:2px;flex-shrink:0;`,i.textContent=n.label;const l=document.createElement("span");l.style.cssText=`font-size:0.8rem;color:${t?"#bac2de":"#334155"};line-height:1.4;`,l.textContent=e.text,a.appendChild(i),a.appendChild(l),r.appendChild(a)}),n<CHANGELOG.length-1){const e=document.createElement("div");e.style.cssText=`height:1px;background:${t?"#45475a":"#e2e8f0"};margin-top:16px;`,r.appendChild(e)}g.appendChild(r)}),r.appendChild(g),n.appendChild(r),n.addEventListener("click",e=>{e.target===n&&n.remove()}),document.body.appendChild(n)}function waitForControlsLeft(e){const t=document.getElementById("controls-left");if(t)return e(t);setTimeout(()=>waitForControlsLeft(e),500)}function gppCreateCore(){const e=128,t=65534,n=4096,o=255,r=65535,a=2147483648,i=Object.freeze([71,80,88,255]),l=Object.freeze({UNCHECKED:0,CORRECT:1,WRONG:2,MISSING:3,UNKNOWN:4});function s(){const e=new Error("Operation cancelled.");return e.name="AbortError",e}function c(e,t,n){if(!Number.isInteger(t)||!Number.isInteger(n)||t<=0||n<=0)throw new TypeError("Image dimensions must be positive integers.");if(!e||"number"!=typeof e.length||e.length!==t*n*4)throw new TypeError("RGBA length does not match image dimensions.")}function d(e,t,n){return(255&e)<<16|(255&t)<<8|255&n}function p(e){return Object.freeze({r:e>>>16&255,g:e>>>8&255,b:255&e})}function g(e){if("u8"===e)return o;if("u16"===e)return r;throw new TypeError(`Unsupported index type: ${e}`)}function u(e,t,n){if("u8"===e)return n?new Uint8Array(n):new Uint8Array(t);if("u16"===e)return n?new Uint16Array(n):new Uint16Array(t);throw new TypeError(`Unsupported index type: ${e}`)}function m(e,t){const n=new Uint32Array(Math.ceil(e/32));for(let o=0;o<e;o++)(!t||t[o]>0)&&(n[o>>>5]|=1<<(31&o));return n}function h(e,t){return t>=0&&t>>>5<e.length&&!!(e[t>>>5]&1<<(31&t))}function f(e,t,n){if(t<0||t>>>5>=e.length)return!1;const o=t>>>5,r=1<<(31&t),a=e[o];return e[o]=n?a|r:a&~r,a!==e[o]}return Object.freeze({constants:Object.freeze({ALPHA_THRESHOLD:e,MAX_EXACT_COLORS:t,MAX_U8_COLORS:254,EMPTY_U8:o,EMPTY_U16:r,POSITION_OFFSET:a,POSITION_MARKER:i,ERROR_STATE:l,GROUPING_THRESHOLD_SQUARED:2}),packRgb:d,unpackRgb:p,packedToHex:function(e){return`#${(16777215&e).toString(16).padStart(6,"0").toUpperCase()}`},packedToRgbaString:function(e){const{r:t,g:n,b:o}=p(e);return`rgba(${t},${n},${o},1)`},hexToPacked:function(e){const t=/^#?([0-9a-f]{6})$/i.exec(String(e||"").trim());return t?parseInt(t[1],16):null},emptyValue:g,makeIndexArray:u,makeFullMask:m,normalizeMask:function(e,t,n){const o=Math.ceil(t/32),r=new Uint32Array(o);if(e){const t=e instanceof Uint32Array?e:new Uint32Array(e);r.set(t.subarray(0,o))}else r.set(m(t,n));const a=31&t;return a&&r.length&&(r[r.length-1]&=4294967295>>>32-a),r},maskHas:h,maskSet:f,maskToggle:function(e,t){return!(t<0||t>>>5>=e.length)&&(e[t>>>5]^=1<<(31&t),h(e,t))},maskOnly:function(e,t){const n=new Uint32Array(Math.ceil(e/32));return f(n,t,!0),n},indexRgba:function(a,i,l,p={}){c(a,i,l);const g=function(n,a,i,l){const c=a*i,p=new Uint16Array(c);p.fill(r);const g=[],u=[],m=new Map;let h=0;for(let o=0;o<c;o++){if(l.isCancelled&&l.isCancelled())throw s();const r=4*o;if(n[r+3]<=e)continue;h++;const a=d(n[r],n[r+1],n[r+2]);let i=m.get(a);if(void 0===i){if(g.length>=t)return null;i=g.length,g.push(a),u.push(0),m.set(a,i)}p[o]=i,u[i]++,!l.onProgress||262143&o||l.onProgress(Math.min(.48,o/c*.48),"Indexing exact colours")}const f=Uint32Array.from(g),b=Uint32Array.from(u);if(g.length<=254){const e=new Uint8Array(c);e.fill(o);for(let t=0;t<c;t++){const n=p[t];n!==r&&(e[t]=n)}return{indices:e,indexType:"u8",palette:f,counts:b,opaquePixelCount:h,quantized:!1,poorMatchPixelCount:0}}return{indices:p,indexType:"u16",palette:f,counts:b,opaquePixelCount:h,quantized:!1,poorMatchPixelCount:0}}(a,i,l,p)||function(t,o,a,i){const l=o*a,c=new Uint32Array(n),p=new Float64Array(n),g=new Float64Array(n),u=new Float64Array(n);let m=0;for(let n=0;n<l;n++){if(i.isCancelled&&i.isCancelled())throw s();const o=4*n;if(t[o+3]<=e)continue;const r=t[o],a=t[o+1],d=t[o+2],h=r>>>4<<8|a>>>4<<4|d>>>4;c[h]++,p[h]+=r,g[h]+=a,u[h]+=d,m++,!i.onProgress||262143&n||i.onProgress(.48+n/l*.24,"Reducing a high-colour image")}const h=new Int32Array(n);h.fill(-1);const f=[],b=[];for(let e=0;e<n;e++){const t=c[e];if(!t)continue;const n=f.length;h[e]=n,f.push(d(Math.round(p[e]/t),Math.round(g[e]/t),Math.round(u[e]/t))),b.push(t)}const y=new Uint16Array(l);y.fill(r);let x=0;for(let n=0;n<l;n++){if(i.isCancelled&&i.isCancelled())throw s();const o=4*n;if(t[o+3]<=e)continue;const r=t[o],a=t[o+1],c=t[o+2],p=h[r>>>4<<8|a>>>4<<4|c>>>4];y[n]=p,f[p]!==d(r,a,c)&&x++,!i.onProgress||262143&n||i.onProgress(.72+n/l*.27,"Writing indexed cells")}return{indices:y,indexType:"u16",palette:Uint32Array.from(f),counts:Uint32Array.from(b),opaquePixelCount:m,quantized:!0,poorMatchPixelCount:x}}(a,i,l,p);return g.width=i,g.height=l,g.mask=m(g.palette.length,g.counts),p.onProgress&&p.onProgress(1,"Ready"),g},indexRgbaAsync:async function(a,i,l,p={}){c(a,i,l);const g=i*l,u=Math.max(4096,p.yieldEvery||65536),h=p.yieldControl||(()=>new Promise(e=>setTimeout(e,0))),f=new Uint16Array(g);f.fill(r);const b=[],y=[],x=new Map;let v,w=0,k=!1;for(let n=0;n<g;n+=u){if(p.isCancelled&&p.isCancelled())throw s();const o=Math.min(g,n+u);for(let r=n;r<o;r++){const n=4*r;if(a[n+3]<=e)continue;w++;const o=d(a[n],a[n+1],a[n+2]);let i=x.get(o);if(void 0===i){if(b.length>=t){k=!0;break}i=b.length,b.push(o),y.push(0),x.set(o,i)}f[r]=i,y[i]++}if(p.onProgress&&p.onProgress(Math.min(.48,o/g*.48),"Indexing exact colours"),k)break;await h()}if(k){const t=new Uint32Array(n),o=new Float64Array(n),i=new Float64Array(n),l=new Float64Array(n);w=0;for(let n=0;n<g;n+=u){if(p.isCancelled&&p.isCancelled())throw s();const r=Math.min(g,n+u);for(let s=n;s<r;s++){const n=4*s;if(a[n+3]<=e)continue;const r=a[n],c=a[n+1],d=a[n+2],p=r>>>4<<8|c>>>4<<4|d>>>4;t[p]++,o[p]+=r,i[p]+=c,l[p]+=d,w++}p.onProgress&&p.onProgress(.48+r/g*.24,"Reducing a high-colour image"),await h()}const c=new Int32Array(n);c.fill(-1);const m=[],f=[];for(let e=0;e<n;e++){const n=t[e];n&&(c[e]=m.length,m.push(d(Math.round(o[e]/n),Math.round(i[e]/n),Math.round(l[e]/n))),f.push(n))}const b=new Uint16Array(g);b.fill(r);let y=0;for(let t=0;t<g;t+=u){if(p.isCancelled&&p.isCancelled())throw s();const n=Math.min(g,t+u);for(let o=t;o<n;o++){const t=4*o;if(a[t+3]<=e)continue;const n=a[t],r=a[t+1],i=a[t+2],l=c[n>>>4<<8|r>>>4<<4|i>>>4];b[o]=l,m[l]!==d(n,r,i)&&y++}p.onProgress&&p.onProgress(.72+n/g*.27,"Writing indexed cells"),await h()}v={indices:b,indexType:"u16",palette:Uint32Array.from(m),counts:Uint32Array.from(f),opaquePixelCount:w,quantized:!0,poorMatchPixelCount:y}}else{const e=Uint32Array.from(b),t=Uint32Array.from(y);if(b.length<=254){const n=new Uint8Array(g);n.fill(o);for(let e=0;e<g;e+=u){if(p.isCancelled&&p.isCancelled())throw s();const t=Math.min(g,e+u);for(let o=e;o<t;o++)f[o]!==r&&(n[o]=f[o]);p.onProgress&&p.onProgress(.48+t/g*.51,"Finalizing compact indices"),await h()}v={indices:n,indexType:"u8",palette:e,counts:t,opaquePixelCount:w,quantized:!1,poorMatchPixelCount:0}}else v={indices:f,indexType:"u16",palette:e,counts:t,opaquePixelCount:w,quantized:!1,poorMatchPixelCount:0}}return v.width=i,v.height=l,v.mask=m(v.palette.length,v.counts),p.onProgress&&p.onProgress(1,"Ready"),v},indexedToRgba:function(e,t,n){const o=g(t),r=new Uint8ClampedArray(4*e.length);for(let t=0;t<e.length;t++){const a=e[t];if(a===o)continue;const i=n[a],l=4*t;r[l]=i>>>16&255,r[l+1]=i>>>8&255,r[l+2]=255&i,r[l+3]=255}return r},computeGridBounds:function(e,t,n){return e&&Number.isFinite(e.gridX)&&Number.isFinite(e.gridY)?Object.freeze({left:Math.round(e.gridX),top:Math.round(e.gridY),right:Math.round(e.gridX)+t-1,bottom:Math.round(e.gridY)-n+1}):null},transformIndexed:function(e,t,n,o,r){let a=n,i=o;"rotate-cw"!==r&&"rotate-ccw"!==r||(a=o,i=n);const l=u(t,a*i);l.fill(g(t));for(let t=0;t<o;t++)for(let i=0;i<n;i++){let s=i,c=t;if("flip-x"===r)s=n-1-i;else if("flip-y"===r)c=o-1-t;else if("rotate-cw"===r)s=o-1-t,c=i;else{if("rotate-ccw"!==r)throw new TypeError(`Unsupported transform: ${r}`);s=t,c=n-1-i}l[c*a+s]=e[t*n+i]}return{indices:l,width:a,height:i}},templateHash:function(e,t,n,o){let r=2166136261;function a(e){r^=255&e,r=Math.imul(r,16777619)>>>0}a(n),a(n>>>8),a(o),a(o>>>8);const i=new Uint8Array(e.buffer,e.byteOffset,e.byteLength);for(let e=0;e<i.length;e++)a(i[e]);for(let e=0;e<t.length;e++){const n=t[e];a(n),a(n>>>8),a(n>>>16)}return r.toString(16).padStart(8,"0")},decodePositionHeader:function(e,t,n){if(c(e,t,n),n<2||t<5)return{position:null,rgba:e,width:t,height:n};const o=new Map,r=new Map;for(let n=0;n+4<t;n+=5){const t=4*n;if(e[t]!==i[0]||e[t+1]!==i[1]||e[t+2]!==i[2]||e[t+3]!==i[3])continue;const a=4*(n+1),l=4*(n+2),s=4*(n+3),c=4*(n+4),d=(e[a]<<24>>>0|e[a+1]<<16|e[l]<<8|e[l+1])>>>0,p=(e[s]<<24>>>0|e[s+1]<<16|e[c]<<8|e[c+1])>>>0;o.set(d,(o.get(d)||0)+1),r.set(p,(r.get(p)||0)+1)}if(!o.size||!r.size)return{position:null,rgba:e,width:t,height:n};const l=e=>{let t=null,n=-1;for(const[o,r]of e)r>n&&(t=o,n=r);return t},s=l(o),d=l(r),p={gridX:Number(BigInt(s)-BigInt(a)),gridY:Number(BigInt(d)-BigInt(a))},g=new Uint8ClampedArray(t*(n-1)*4);return g.set(e.subarray(4*t)),{position:p,rgba:g,width:t,height:n-1}},encodePositionHeader:function(e,t,n,o){if(c(e,t,n),!o||!Number.isInteger(o.gridX)||!Number.isInteger(o.gridY))throw new TypeError("Integer grid coordinates are required for position export.");const r=new Uint8ClampedArray(t*(n+1)*4);r.set(e,4*t);const l=Number(BigInt(o.gridX)+BigInt(a)&0xFFFFFFFFn)>>>0,s=Number(BigInt(o.gridY)+BigInt(a)&0xFFFFFFFFn)>>>0;for(let e=0;e+4<t;e+=5){const t=4*e;r.set(i,t);const n=4*(e+1),o=4*(e+2),a=4*(e+3),c=4*(e+4);r[n]=l>>>24&255,r[n+1]=l>>>16&255,r[n+3]=255,r[o]=l>>>8&255,r[o+1]=255&l,r[o+3]=255,r[a]=s>>>24&255,r[a+1]=s>>>16&255,r[a+3]=255,r[c]=s>>>8&255,r[c+1]=255&s,r[c+3]=255}return{rgba:r,width:t,height:n+1}},compareRealityPixel:function(t,n,o,r,a,i,s,c){if(!s)return l.UNKNOWN;if(a<=e)return l.MISSING;const p=i.get(d(n,o,r));return p===t||c&&void 0!==p&&c[p]===c[t]?l.CORRECT:l.WRONG},groupPaletteColors:function(e,t){"number"!=typeof t&&(t=2);const n=e.length,o=new Int32Array(n),r=[],a=new Map,i=Math.max(0,Math.floor(Math.sqrt(t))),l=new Map,s=(e,t,n)=>256*(256*e+t)+n;for(let c=0;c<n;c++){const n=e[c],d=n>>>16&255,p=n>>>8&255,g=255&n;let u=-1,m=1/0;for(let e=-i;e<=i;e++){const n=d+e;if(!(n<0||n>255))for(let o=-i;o<=i;o++){const r=p+o;if(!(r<0||r>255))for(let a=-i;a<=i;a++){const i=g+a;if(i<0||i>255)continue;const c=l.get(s(n,r,i));if(void 0===c)continue;const d=e*e+o*o+a*a;d<=t&&d<m&&(m=d,u=c)}}}if(-1!==u)o[c]=u,a.get(u).memberIndices.push(c);else{o[c]=c;const e={representativeIndex:c,memberIndices:[c]};r.push(e),a.set(c,e),l.set(s(d,p,g),c)}}return Object.freeze({groupOfIndex:o,groups:r,groupByRepresentative:a})}})}function gppIngestWorkerMain(e){const t=e();self.onmessage=async e=>{const n=e.data||{};if("ingest"!==n.type)return;const o=n.operationId;let r=null;try{self.postMessage({type:"progress",operationId:o,fraction:.02,label:"Decoding image"}),r=await createImageBitmap(n.file);const e=new OffscreenCanvas(r.width,r.height).getContext("2d",{willReadFrequently:!0,colorSpace:"srgb"});e.drawImage(r,0,0);let a=e.getImageData(0,0,r.width,r.height).data,i=r.width,l=r.height;const s=t.decodePositionHeader(a,i,l);a=s.rgba,i=s.width,l=s.height;const c=t.indexRgba(a,i,l,{onProgress:(e,t)=>self.postMessage({type:"progress",operationId:o,fraction:.05+.94*e,label:t})}),d={type:"complete",operationId:o,width:i,height:l,position:s.position,indexType:c.indexType,indices:c.indices.buffer,palette:c.palette.buffer,counts:c.counts.buffer,mask:c.mask.buffer,opaquePixelCount:c.opaquePixelCount,quantized:c.quantized,poorMatchPixelCount:c.poorMatchPixelCount};self.postMessage(d,[d.indices,d.palette,d.counts,d.mask])}catch(e){self.postMessage({type:"error",operationId:o,name:e&&e.name?e.name:"Error",message:e&&e.message?e.message:String(e)})}finally{r&&r.close()}}}function gppBuildIngestWorkerSource(){return";("+gppIngestWorkerMain.toString()+")("+gppCreateCore.toString()+");"}function gppEvalPageExpr(e){try{const t=(0,eval)(e);if(void 0!==t)return t}catch(e){}if("undefined"!=typeof unsafeWindow)try{return unsafeWindow.eval(e)}catch(e){}}function gppGetMap(){const e=gppEvalPageExpr("map");return e&&"function"==typeof e.project?e:null}function gppGetTurf(){const e=gppEvalPageExpr("turf");return e&&"function"==typeof e.toWgs84?e:null}function gppReadGridConstants(){return gppEvalPageExpr('({gridSize: (typeof gridSize !== "undefined" ? gridSize : 25),halfSize: (typeof halfSize !== "undefined" ? halfSize : 12.5),minZoom: (typeof minZoom !== "undefined" ? minZoom : 10.5),tileSize: (typeof SYNC_TILE_SIZE !== "undefined" ? SYNC_TILE_SIZE : 1000),offsetMetersX: (typeof offsetMetersX !== "undefined" ? offsetMetersX : 0),offsetMetersY: (typeof offsetMetersY !== "undefined" ? offsetMetersY : 0)})')||{gridSize:25,halfSize:12.5,minZoom:10.5,tileSize:1e3,offsetMetersX:0,offsetMetersY:0}}function gppReadGamePalette(){return gppEvalPageExpr('(function(){if (typeof Colors === "undefined" || !Array.isArray(Colors)) return null;var active = (typeof activeColors !== "undefined" && Array.isArray(activeColors)) ? activeColors : [];var activeSet = {};for (var i = 0; i < active.length; i++) activeSet[active[i]] = true;var out = [];for (var j = 0; j < Colors.length; j++) out.push({ hex: Colors[j], index: j, active: !!activeSet[j] });return out;})()')||[]}function gppReadQueuedPixelKeys(){const e=gppEvalPageExpr('(typeof queuedPixels !== "undefined" && queuedPixels && typeof queuedPixels.keys === "function") ? Array.from(queuedPixels.keys()) : []');return Array.isArray(e)?e:[]}function gppGetTileBitmap(e,t){return gppEvalPageExpr('(function(){if (typeof tileImageCache === "undefined") return null;var entry = tileImageCache.get("'+e+","+t+'");return (entry && entry.colorBitmap) ? entry.colorBitmap : null;})()')||null}function gppReadNativeGuildData(){return gppEvalPageExpr('(typeof userGuildData !== "undefined" ? userGuildData : null)')||null}function gppReadNativeAuth(){return gppEvalPageExpr('({token: (typeof tokenUser !== "undefined" ? tokenUser : null),userId: (typeof userData !== "undefined" && userData ? userData.id : null)})')||{token:null,userId:null}}function gppRunInPageRealm(e){const t=document.createElement("script");t.textContent='(function(){ "use strict"; '+e+" })();",(document.head||document.documentElement).appendChild(t),t.remove()}function gppReadNativeGhostSnapshot(){return gppEvalPageExpr('(function(){return {hasGhostImage: (typeof ghostImage !== "undefined" && !!ghostImage),ghostImageTopLeft: (typeof ghostImageTopLeft !== "undefined" ? ghostImageTopLeft : null),isColorFilterDisabled: (typeof isColorFilterDisabled !== "undefined" ? isColorFilterDisabled : null)};})()')}function gppClearNativeGhostCanvasPaint(){gppRunInPageRealm('if (typeof ghostCanvasCtx !== "undefined" && ghostCanvasCtx && typeof ghostCanvas !== "undefined" && ghostCanvas) {ghostCanvasCtx.clearRect(0, 0, ghostCanvas.width, ghostCanvas.height);}')}function gppWriteNativeGhostMirror(e){gppRunInPageRealm(e)}waitForControlsLeft(e=>{const t=document.createElement("div");t.className="relative";const n=document.createElement("button");n.id="geopixelconsGroupBtn",n.className="w-10 h-10 bg-white shadow rounded-full flex items-center justify-center hover:bg-gray-100 cursor-pointer",n.title="GeoPixelcons++";const o="url(data:image/png;base64,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);background-size:cover;background-position:center;border:none;padding:0;";n.style.cssText="background-image:"+o,n.dataset.iconBg=o.substring(0,o.indexOf(");")+1),_settings.useEmojiIcon&&(n.style.backgroundImage="none",n.textContent="😢",n.style.fontSize="20px");const r=document.createElement("div");r.className="dropdown-menu absolute left-0 mt-2 flex flex-col gap-2 transition-all duration-150 ease-out opacity-0 scale-95 hidden";const a="var(--color-white, #fff)",i="var(--color-gray-100, #f3f4f6)",l="var(--color-gray-700, #374151)",s="var(--color-white, #fff)",c="var(--color-gray-100, #f3f4f6)",d="var(--color-gray-700, #374151)",p="var(--color-gray-500, #6b7280)",g="var(--color-white, #fff)",u="var(--color-gray-300, #d1d5db)",m="var(--color-gray-900, #111827)",h="0 1px 3px rgba(0,0,0,.12)",f="var(--color-green-100, #bbf7d0)",b="var(--color-green-800, #166534)",y="var(--color-purple-500, #7c3aed)",x="var(--color-purple-50, #f3e8ff)",v="var(--color-purple-400, #c4b5fd)",w="var(--color-white, #fff)",k="var(--color-purple-100, #ede9fe)",E="var(--color-white, #fff)",C="var(--color-gray-500, #6b7280)";function S(){r.classList.add("opacity-0","scale-95"),setTimeout(()=>{r.classList.add("hidden")},150)}function T(e,t,n){const o=document.createElement("button");o.className="gpc-pill-btn",o.title=t,o.style.cssText="position:relative;width:40px;height:40px;border-radius:9999px;background:"+a+";box-shadow:"+h+";display:flex;align-items:center;justify-content:flex-start;border:none;cursor:pointer;overflow:hidden;transition:width .25s cubic-bezier(.4,0,.2,1);padding:0;font-size:16px;flex-shrink:0;";const r=document.createElement("span");r.style.cssText="width:40px;min-width:40px;text-align:center;flex-shrink:0;line-height:40px;",r.textContent=e;const s=document.createElement("span");return s.style.cssText="white-space:nowrap;font-size:12px;font-weight:600;color:"+l+";opacity:0;transition:opacity .2s .05s;padding-right:12px;pointer-events:none;",s.textContent=t,o.appendChild(r),o.appendChild(s),o.addEventListener("mouseenter",()=>{const e=s.scrollWidth+12;o.style.width=40+e+"px",s.style.opacity="1",o.style.background=i}),o.addEventListener("mouseleave",()=>{o.style.width="40px",s.style.opacity="0",o.style.background=a}),o.addEventListener("click",e=>{e.stopPropagation(),o.style.width="40px",s.style.opacity="0",o.style.background=a,S(),n()}),o}r.id="geopixelconsDropdown",n.addEventListener("click",e=>{e.stopPropagation(),"function"==typeof closeAllDropdowns?closeAllDropdowns():document.querySelectorAll(".dropdown-menu").forEach(e=>{e===r||e.classList.contains("hidden")||(e.classList.add("opacity-0","scale-95"),setTimeout(()=>e.classList.add("hidden"),150))});!r.classList.contains("hidden")?S():function(){if(_settings.enableDebug){const e=document.querySelector("#gpc-debug-dropdown-btn span:nth-child(2)");e&&(e.textContent=`Debug Logs (${dbgCount()})`)}r.classList.remove("hidden"),setTimeout(()=>{r.classList.remove("opacity-0","scale-95")},10)}()});const P=[];function L(){for(const e of P)e()}function M(e){const t=document.createElement("div");t.style.cssText="position:relative;";const n=document.createElement("button");n.className="gpc-pill-btn",n.title=e.title,n.style.cssText="position:relative;width:40px;height:40px;border-radius:9999px;background:"+a+";box-shadow:"+h+";display:flex;align-items:center;justify-content:flex-start;border:none;cursor:pointer;overflow:hidden;transition:width .25s cubic-bezier(.4,0,.2,1);padding:0;font-size:16px;flex-shrink:0;",n.id="gpc-"+e.id+"-sub";const o=document.createElement("span");o.style.cssText="width:40px;min-width:40px;text-align:center;flex-shrink:0;line-height:40px;",o.textContent=e.icon;const r=document.createElement("span");r.style.cssText="white-space:nowrap;font-size:12px;font-weight:600;color:"+l+";opacity:0;transition:opacity .2s .05s;padding-right:12px;pointer-events:none;",r.textContent=e.title,n.appendChild(o),n.appendChild(r),n.addEventListener("mouseenter",()=>{if(x)return;const e=r.scrollWidth+12;n.style.width=40+e+"px",r.style.opacity="1",n.style.background=i}),n.addEventListener("mouseleave",()=>{n.style.width="40px",r.style.opacity="0",n.style.background=a});const y=document.createElement("div");y.id="gpc-"+e.id+"-flyout",Object.assign(y.style,{position:"absolute",left:"calc(100% + 8px)",top:"0",transform:"scale(0.95)",display:"flex",flexDirection:"column",gap:"4px",transition:"all 0.15s ease-out",opacity:"0",pointerEvents:"none",zIndex:"21"});let x=!1;const v="display:flex;align-items:center;gap:6px;min-width:200px;padding:5px 10px;background:"+s+";box-shadow:"+h+";border-radius:6px;border:none;cursor:pointer;font-size:11px;font-weight:500;color:"+d+";white-space:nowrap;height:28px;transition:background .12s;",w=v.replace("background:"+s,"background:"+f).replace("color:"+d,"color:"+b);function k(e,t,n,o){const r=document.createElement("button");return r.style.cssText=v,r.innerHTML=t+" "+e,o&&(r.id=o),r.addEventListener("mouseenter",()=>{r.dataset.active||(r.style.background=c)}),r.addEventListener("mouseleave",()=>{r.dataset.active||(r.style.background=s)}),r.addEventListener("click",e=>{e.stopPropagation(),E(),S(),n()}),r}function E(){x=!1,y.style.opacity="0",y.style.pointerEvents="none",y.style.transform="scale(0.95)"}y.appendChild(k("Select Area","🔲",()=>{const t=document.getElementById("gpc-"+e.id+"-trigger");t&&t.click()})),y.appendChild(k("Pick Points","📌",()=>{!function(e){I&&_();const t=R();if(!t)return void N("Map not ready.",!0);I={opts:e,step:0,markers:[],handler:null,keyHandler:null},N("Click top-left corner…"),document.body.style.cursor="crosshair",I.handler=function(e){const n="undefined"!=typeof gridSize?gridSize:25,o=turf.toMercator([e.lngLat.lng,e.lngLat.lat]),r=Math.round(o[0]/n),a=Math.round(o[1]/n);if(0===I.step){I.p1={x:r,y:a};const n=G("NW","#ef4444"),o=new maplibregl.Marker({element:n}).setLngLat(e.lngLat).addTo(t);I.markers.push(o),I.step=1,N("Click bottom-right corner…")}else{I.p2={x:r,y:a};const n=G("SE","#3b82f6"),o=new maplibregl.Marker({element:n}).setLngLat(e.lngLat).addTo(t);I.markers.push(o);const i=I.p1,l=I.p2,s={minX:Math.min(i.x,l.x),maxX:Math.max(i.x,l.x),minY:Math.min(i.y,l.y),maxY:Math.max(i.y,l.y)};saveCachedCoords(s),_(),N("Coords applied! ("+s.minX+","+s.maxY+") → ("+s.maxX+","+s.minY+")")}},I.keyHandler=function(e){"Escape"===e.key&&(_(),N("Cancelled."))},t.on("click",I.handler),document.addEventListener("keydown",I.keyHandler)}(e)}));const C=document.createElement("div");Object.assign(C.style,{display:"flex",flexDirection:"column",gap:"4px",minWidth:"200px",padding:"6px 10px",background:s,boxShadow:h,borderRadius:"6px",fontSize:"11px"});const T=loadCachedCoords(),M="width:60px;padding:2px 4px;border:1px solid "+u+";border-radius:4px;font-size:11px;background:"+g+";color:"+m+";";if(C.innerHTML='<div style="font-weight:600;color:'+d+';margin-bottom:2px;">📝 Input Coords</div><div style="display:flex;gap:4px;align-items:center;">  <span style="width:22px;color:'+p+';font-size:10px;">NW</span>  <input id="gpc-'+e.id+'-nw-x" type="number" placeholder="X" style="'+M+'" value="'+(T?T.minX:"")+'">  <input id="gpc-'+e.id+'-nw-y" type="number" placeholder="Y" style="'+M+'" value="'+(T?T.maxY:"")+'"></div><div style="display:flex;gap:4px;align-items:center;">  <span style="width:22px;color:'+p+';font-size:10px;">SE</span>  <input id="gpc-'+e.id+'-se-x" type="number" placeholder="X" style="'+M+'" value="'+(T?T.maxX:"")+'">  <input id="gpc-'+e.id+'-se-y" type="number" placeholder="Y" style="'+M+'" value="'+(T?T.minY:"")+'"></div><button id="gpc-'+e.id+'-coord-go" style="margin-top:2px;padding:4px 8px;background:'+(e.color||"#3b82f6")+';color:white;border:none;border-radius:4px;font-size:11px;font-weight:600;cursor:pointer;">Go</button>',C.addEventListener("click",e=>e.stopPropagation()),y.appendChild(C),setTimeout(()=>{const t=document.getElementById("gpc-"+e.id+"-coord-go");t&&t.addEventListener("click",()=>{const t=parseInt(document.getElementById("gpc-"+e.id+"-nw-x").value),n=parseInt(document.getElementById("gpc-"+e.id+"-nw-y").value),o=parseInt(document.getElementById("gpc-"+e.id+"-se-x").value),r=parseInt(document.getElementById("gpc-"+e.id+"-se-y").value);if([t,n,o,r].some(isNaN))return;const a={minX:Math.min(t,o),maxX:Math.max(t,o),minY:Math.min(r,n),maxY:Math.max(r,n)};saveCachedCoords(a),E(),S();const i=e.getModule();i&&i.processWithBounds&&i.processWithBounds(a)})},0),"screenshot"===e.id){const e=document.createElement("button");e.id="gpc-auto-screenshot-btn";const t=isAutoScreenshotEnabled()&&loadCachedCoords();e.style.cssText=t?w:v,e.innerHTML="📷 Auto-save on paint",t&&(e.dataset.active="1"),e.title="Takes a screenshot of the cached area every time you paint. Requires Input Coords.",e.addEventListener("mouseenter",()=>{e.dataset.active||(e.style.background=c)}),e.addEventListener("mouseleave",()=>{e.dataset.active||(e.style.background=isAutoScreenshotEnabled()&&loadCachedCoords()?f:s)}),e.addEventListener("click",t=>{t.stopPropagation();if(!loadCachedCoords())return void N("Set coords first (Input Coords or Pick Points).",!0);const n=!isAutoScreenshotEnabled();setAutoScreenshot(n),e.style.cssText=n?w:v,n?(e.dataset.active="1",e.innerHTML="📷 Auto-save on paint ✅"):(delete e.dataset.active,e.innerHTML="📷 Auto-save on paint"),N(n?"Auto-screenshot ON":"Auto-screenshot OFF")}),y.appendChild(e)}return P.push(E),n.addEventListener("click",t=>{t.stopPropagation(),n.style.width="40px",r.style.opacity="0",n.style.background=a;const o=x;if(L(),!o){x=!0;const t=loadCachedCoords(),n=(t,n)=>{const o=document.getElementById("gpc-"+e.id+"-"+t);o&&(o.value=n??"")};n("nw-x",t?.minX),n("nw-y",t?.maxY),n("se-x",t?.maxX),n("se-y",t?.minY),y.style.opacity="1",y.style.pointerEvents="auto",y.style.transform="scale(1)";const o=document.getElementById("gpc-auto-screenshot-btn");if(o){const e=isAutoScreenshotEnabled()&&loadCachedCoords();o.style.cssText=e?w:v,o.innerHTML=e?"📷 Auto-save on paint ✅":"📷 Auto-save on paint",e?o.dataset.active="1":delete o.dataset.active}}}),document.addEventListener("click",e=>{x&&!t.contains(e.target)&&E()}),t.appendChild(n),t.appendChild(y),t}let I=null;function _(){if(!I)return;const e=R();e&&I.handler&&e.off("click",I.handler);for(const e of I.markers)e.remove();I.keyHandler&&document.removeEventListener("keydown",I.keyHandler),document.body.style.cursor="",I=null}function G(e,t){const n=document.createElement("div");return n.style.cssText="display:flex;flex-direction:column;align-items:center;pointer-events:none;",n.innerHTML='<svg width="28" height="40" viewBox="0 0 24 36"><path d="M12 0C5.4 0 0 5.4 0 12c0 9 12 24 12 24s12-15 12-24C24 5.4 18.6 0 12 0z" fill="'+t+'"/><circle cx="12" cy="11" r="4.5" fill="white"/></svg><span style="font-size:10px;font-weight:700;color:'+t+';text-shadow:0 0 2px white,0 0 2px white;">'+e+"</span>",n}function R(){try{const e=(0,eval)("map");if(e&&"function"==typeof e.setStyle)return e}catch{}if("undefined"!=typeof unsafeWindow)try{const e=unsafeWindow.eval("map");if(e&&"function"==typeof e.setStyle)return e}catch{}return null}function N(e,t){const n=document.getElementById("gpc-flyout-toast");n&&n.remove();const o=document.createElement("div");o.id="gpc-flyout-toast",o.textContent=e,Object.assign(o.style,{position:"fixed",top:"70px",left:"50%",transform:"translateX(-50%)",background:t?"#fca5a5":"#bbf7d0",color:t?"#7f1d1d":"#166534",padding:"8px 18px",borderRadius:"8px",fontSize:"13px",fontWeight:"600",zIndex:"100001",boxShadow:"0 4px 12px rgba(0,0,0,.2)",transition:"opacity .3s",fontFamily:"system-ui,sans-serif"}),document.body.appendChild(o),setTimeout(()=>{o.style.opacity="0",setTimeout(()=>o.remove(),300)},2500)}if(_settings.regionScreenshot&&r.appendChild(M({id:"screenshot",icon:"📸",title:"Region Screenshot",featureKey:"regionScreenshot",color:"#10b981",getModule:()=>_regionScreenshot})),_settings.regionsHighscore&&r.appendChild(M({id:"highscore",icon:"🏆",title:"Region Highscore",featureKey:"regionsHighscore",color:"#3b82f6",getModule:()=>_regionsHighscore})),_settings.themeEditor){const z=document.createElement("div");z.style.cssText="position:relative;";const B=document.createElement("button");B.className="gpc-pill-btn",B.title="Theme Editor",B.style.cssText="position:relative;width:40px;height:40px;border-radius:9999px;background:"+a+";box-shadow:"+h+";display:flex;align-items:center;justify-content:flex-start;border:none;cursor:pointer;overflow:hidden;transition:width .25s cubic-bezier(.4,0,.2,1);padding:0;font-size:16px;flex-shrink:0;",B.id="gpc-theme-sub";const O=document.createElement("span");O.style.cssText="width:40px;min-width:40px;text-align:center;flex-shrink:0;line-height:40px;",O.textContent="🎨";const D=document.createElement("span");D.style.cssText="white-space:nowrap;font-size:12px;font-weight:600;color:"+l+";opacity:0;transition:opacity .2s .05s;padding-right:12px;pointer-events:none;",D.textContent="Theme Editor",B.appendChild(O),B.appendChild(D),B.addEventListener("mouseenter",()=>{if(H)return;const e=D.scrollWidth+12;B.style.width=40+e+"px",D.style.opacity="1",B.style.background=i}),B.addEventListener("mouseleave",()=>{B.style.width="40px",D.style.opacity="0",B.style.background=a});const j=document.createElement("div");j.id="gpc-theme-flyout",Object.assign(j.style,{position:"absolute",left:"calc(100% + 8px)",top:"0",transform:"scale(0.95)",display:"flex",flexDirection:"column",gap:"3px",transition:"all 0.15s ease-out",opacity:"0",pointerEvents:"none",zIndex:"21"});let H=!1,F=0;const X=4;function q(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function U(){if(j.innerHTML="",!_themeEditor)return;const e=_themeEditor.loadThemes(),t=_themeEditor.getActiveThemeName(),n=Object.keys(e).sort((e,t)=>{const n="Default"===e?0:"Default Dark"===e?1:2,o="Default"===t?0:"Default Dark"===t?1:2;return n!==o?n-o:e.localeCompare(t)}),o=Math.max(1,Math.ceil(n.length/X));F>=o&&(F=0);const r=F*X,a=n.slice(r,r+X);for(const n of a){const o=e[n],r=n===t,a=document.createElement("button");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"6px",minWidth:"130px",maxWidth:"190px",padding:"4px 8px",background:r?v:w,boxShadow:h,borderRadius:"6px",border:"none",cursor:"pointer",fontSize:"11px",fontWeight:r?"700":"500",color:r?x:d,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",transition:"background .12s",height:"28px"});const i=o.overrides?.["background::background-color"]||o.overrides?.["water::fill-color"]||"#808080";a.innerHTML='<span style="width:14px;height:14px;border-radius:3px;border:1px solid rgba(0,0,0,.15);flex-shrink:0;background:'+i+'"></span>'+q(n),a.title=n,a.addEventListener("click",async e=>{e.stopPropagation(),await _themeEditor.applyThemeByName(n),U()}),a.addEventListener("mouseenter",()=>{r||(a.style.background=k)}),a.addEventListener("mouseleave",()=>{r||(a.style.background=w)}),j.appendChild(a)}if(o>1){const e=document.createElement("button");Object.assign(e.style,{display:"flex",alignItems:"center",justifyContent:"center",minWidth:"130px",maxWidth:"190px",padding:"3px 8px",background:E,boxShadow:h,borderRadius:"6px",border:"none",cursor:"pointer",fontSize:"10px",color:C,height:"22px",transition:"background .12s"}),e.textContent="▸ "+(F+1)+"/"+o,e.title="Next page",e.addEventListener("click",e=>{e.stopPropagation(),F=(F+1)%o,U()}),j.appendChild(e)}const i=document.createElement("button");Object.assign(i.style,{display:"flex",alignItems:"center",justifyContent:"center",gap:"4px",minWidth:"130px",maxWidth:"190px",padding:"4px 8px",background:y,boxShadow:h,borderRadius:"6px",border:"none",cursor:"pointer",fontSize:"11px",fontWeight:"600",color:x,whiteSpace:"nowrap",height:"28px",transition:"filter .12s"}),i.textContent="⚙️ Editor",i.title="Open full Theme Editor",i.addEventListener("mouseenter",()=>{i.style.filter="brightness(1.1)"}),i.addEventListener("mouseleave",()=>{i.style.filter=""}),i.addEventListener("click",e=>{e.stopPropagation(),S(),W(),_themeEditor&&_themeEditor.toggleModal()}),j.appendChild(i)}function W(){H=!1,j.style.opacity="0",j.style.pointerEvents="none",j.style.transform="scale(0.95)"}P.push(W),B.addEventListener("click",e=>{e.stopPropagation(),B.style.width="40px",D.style.opacity="0",B.style.background=a;const t=H;L(),t||(H=!0,U(),j.style.opacity="1",j.style.pointerEvents="auto",j.style.transform="scale(1)")}),document.addEventListener("click",e=>{H&&!z.contains(e.target)&&W()}),z.appendChild(B),z.appendChild(j),r.appendChild(z)}if(_settings.mapMarkers&&r.appendChild(T("📌","Map Markers",()=>{_mapMarkers&&_mapMarkers.openModal()})),r.appendChild(T("⚙️","Settings...",createSettingsModal)),r.appendChild(T("📋","Changelog",showChangelog)),_settings.enableDebug){const Y=T("🔶",`Debug Logs (${dbgCount()})`,dbgExport);Y.id="gpc-debug-dropdown-btn",r.appendChild(Y)}function A(){const n=e.querySelector("#geopixels-plusplus")?.closest(".relative");return!(!n||n.nextSibling===t)&&(n.after(t),!0)}if(t.appendChild(n),t.appendChild(r),e.appendChild(t),!A()){const V=new MutationObserver(()=>{A()&&V.disconnect()});V.observe(e,{childList:!0,subtree:!0}),setTimeout(()=>V.disconnect(),3e4)}});const GPP_NATIVE_FN_NAMES=["drawGhostImageOnCanvas","regenerateGhostCanvas","initializeGhostFromStorage"];function gppSetNativeFunction(e,t){const n="undefined"!=typeof unsafeWindow?unsafeWindow:window;if(-1===GPP_NATIVE_FN_NAMES.indexOf(e))throw new Error("gppSetNativeFunction: unexpected name "+e);n[e]=t}const GPP_LEGACY_DB_NAME="GP_Ghost_History",GPP_LEGACY_DB_VERSION=3,GPP_LEGACY_STORE_NAME="images";let gppLegacyDbPromise=null;function gppLegacyOpenDatabase(){return gppLegacyDbPromise||(gppLegacyDbPromise=new Promise((e,t)=>{const n=indexedDB.open(GPP_LEGACY_DB_NAME,GPP_LEGACY_DB_VERSION);n.onupgradeneeded=()=>{const e=n.result,t=n.transaction;let o;o=e.objectStoreNames.contains(GPP_LEGACY_STORE_NAME)?t.objectStore(GPP_LEGACY_STORE_NAME):e.createObjectStore(GPP_LEGACY_STORE_NAME,{keyPath:"id",autoIncrement:!0}),o.indexNames.contains("hash")||o.createIndex("hash","hash",{unique:!1}),o.indexNames.contains("templateId")||o.createIndex("templateId","templateId",{unique:!1})},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}).catch(e=>{throw gppLegacyDbPromise=null,e})),gppLegacyDbPromise}async function gppLegacyComputeFileHash(e){const t=await e.arrayBuffer(),n=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,"0")).join("")}async function gppLegacyComputeTemplateId(e){try{const t=gppCreateCore(),n=await createImageBitmap(e),o=document.createElement("canvas");o.width=n.width,o.height=n.height;const r=o.getContext("2d",{willReadFrequently:!0});r.drawImage(n,0,0),n.close();const a=r.getImageData(0,0,o.width,o.height).data,i=t.decodePositionHeader(a,o.width,o.height);if(!i.position)return await gppLegacyComputeFileHash(e);const l=document.createElement("canvas");l.width=i.width,l.height=i.height,l.getContext("2d").putImageData(new ImageData(new Uint8ClampedArray(i.rgba),i.width,i.height),0,0);const s=await new Promise(e=>l.toBlob(e,"image/png"));return await gppLegacyComputeFileHash(s)}catch(t){return await gppLegacyComputeFileHash(e)}}function gppLegacyListImages(){return gppLegacyOpenDatabase().then(e=>new Promise((t,n)=>{const o=e.transaction(GPP_LEGACY_STORE_NAME,"readonly").objectStore(GPP_LEGACY_STORE_NAME).getAll();o.onsuccess=()=>t(o.result||[]),o.onerror=()=>n(o.error)}))}async function gppLegacyAddImage(e,t,n){const o=await gppLegacyOpenDatabase(),r=await gppLegacyComputeFileHash(e),a=await gppLegacyComputeTemplateId(e),i=t||"Image_"+Date.now(),l=Date.now();return new Promise((t,s)=>{const c=o.transaction(GPP_LEGACY_STORE_NAME,"readwrite"),d=c.objectStore(GPP_LEGACY_STORE_NAME),p=d.index("templateId").get(a);let g=null;p.onsuccess=()=>{const t=p.result,o={blob:e,name:i,date:l,hash:r,templateId:a,groupNoise:!!n};if(t)o.id=t.id,g=t.id,d.put(o);else{const e=d.add(o);e.onsuccess=()=>{g=e.result}}},c.oncomplete=()=>t({id:g,hash:r,templateId:a,name:i,date:l,groupNoise:!!n}),c.onerror=()=>s(c.error)})}function gppLegacyDeleteImage(e){return gppLegacyOpenDatabase().then(t=>new Promise((n,o)=>{const r=t.transaction(GPP_LEGACY_STORE_NAME,"readwrite");r.objectStore(GPP_LEGACY_STORE_NAME).delete(e),r.oncomplete=()=>n(),r.onerror=()=>o(r.error)}))}const GPP_SETTINGS_KEY="gpGhostPlusPlusSettings.v1",GPP_DB_NAME="GP_Ghost_Plus_Plus",GPP_DB_VERSION=1,GPP_TEMPLATE_STORE="templates",GPP_STATE_STORE="templateState",GPP_DEFAULT_SETTINGS=Object.freeze({gapRatio:.6,focusedTemplateId:null,showErrors:!0,autoscanEnabled:!1,hideQueuedCrosses:!0,errorShape:"x",errorColor:"#dc2626",errorOpacity:1,errorSizeScale:1,autoHideUnfocused:!0,grayDisabledSwatches:!0,paletteViewMode:"grid"});let gppSettings=gppLoadSettings(),gppDatabase=null,gppTemplates=[],gppFocusedTemplateId=gppSettings.focusedTemplateId,gppGuildTemplates=[],gppIngestOperation=null,gppIngestToken=0;function gppLoadSettings(){try{const e=localStorage.getItem(GPP_SETTINGS_KEY);return e?{...GPP_DEFAULT_SETTINGS,...JSON.parse(e)}:{...GPP_DEFAULT_SETTINGS}}catch(e){return{...GPP_DEFAULT_SETTINGS}}}function gppSaveSettings(){localStorage.setItem(GPP_SETTINGS_KEY,JSON.stringify(gppSettings))}function gppOpenDatabase(){return new Promise((e,t)=>{const n=indexedDB.open(GPP_DB_NAME,GPP_DB_VERSION);n.onupgradeneeded=()=>{const e=n.result;e.objectStoreNames.contains(GPP_TEMPLATE_STORE)||e.createObjectStore(GPP_TEMPLATE_STORE,{keyPath:"id"}),e.objectStoreNames.contains(GPP_STATE_STORE)||e.createObjectStore(GPP_STATE_STORE,{keyPath:"id"})},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}function gppDbGetAll(e){return new Promise((t,n)=>{const o=gppDatabase.transaction(e,"readonly").objectStore(e).getAll();o.onsuccess=()=>t(o.result||[]),o.onerror=()=>n(o.error)})}function gppDbPut(e,t){return new Promise((n,o)=>{const r=gppDatabase.transaction(e,"readwrite");r.objectStore(e).put(t),r.oncomplete=()=>n(),r.onerror=()=>o(r.error)})}function gppDbDelete(e,t){return new Promise((n,o)=>{const r=gppDatabase.transaction(e,"readwrite");r.objectStore(e).delete(t),r.oncomplete=()=>n(),r.onerror=()=>o(r.error)})}function gppMakeTemplateId(){return"gpp_"+Date.now().toString(36)+"_"+Math.random().toString(36).slice(2,8)}const gppLegacyDecodeCache=new Map;async function gppLegacyDecodeCached(e){if(e.hash&&gppLegacyDecodeCache.has(e.hash))return gppLegacyDecodeCache.get(e.hash);const t=await gppDecodeImageBlob(e.blob);return e.hash&&gppLegacyDecodeCache.set(e.hash,t),t}async function gppLoadSharedLibraryTemplates(e){const t=await gppLegacyListImages(),n=[];for(const o of t){const t="legacy_"+o.id,r=e.get(t)||{};try{const e=await gppLegacyDecodeCached(o),a=gppCreateCore();n.push({id:t,legacySourceId:o.id,name:r.name||o.name||"Untitled template",width:e.width,height:e.height,indexType:e.indexType,indices:e.indices,palette:e.palette,counts:e.counts,opaquePixelCount:e.opaquePixelCount,quantized:e.quantized,poorMatchPixelCount:e.poorMatchPixelCount,sourceBlob:o.blob,mask:r.mask?new Uint32Array(r.mask):a.makeFullMask(e.palette.length,e.counts),position:"position"in r?r.position:e.position||null,opacity:"number"==typeof r.opacity?r.opacity:1,locked:!!r.locked,groupNoise:!!r.groupNoise,order:"number"==typeof r.order?r.order:1e6+o.id,scanSummary:null})}catch(e){console.error('[GeoPixelcons++] Ghost++: failed to decode shared history image "'+(o.name||o.id)+'".',e)}}return n}async function gppLoadTemplateLibrary(){const[e,t]=await Promise.all([gppDbGetAll(GPP_TEMPLATE_STORE),gppDbGetAll(GPP_STATE_STORE)]),n=new Map(t.map(e=>[e.id,e])),o=e.map(e=>{const t=n.get(e.id)||{},o=gppCreateCore();return{id:e.id,name:t.name||e.name||"Untitled template",width:e.width,height:e.height,indexType:e.indexType,indices:o.makeIndexArray(e.indexType,0,e.indices),palette:new Uint32Array(e.palette),counts:new Uint32Array(e.counts),opaquePixelCount:e.opaquePixelCount,quantized:e.quantized,poorMatchPixelCount:e.poorMatchPixelCount,sourceBlob:e.sourceBlob||null,mask:t.mask?new Uint32Array(t.mask):o.makeFullMask(e.palette.length,e.counts),position:t.position||null,opacity:"number"==typeof t.opacity?t.opacity:1,locked:!!t.locked,groupNoise:!!t.groupNoise,order:"number"==typeof t.order?t.order:0,scanSummary:null}});let r=[];try{r=await gppLoadSharedLibraryTemplates(n)}catch(e){console.error("[GeoPixelcons++] Ghost++: failed to load the shared legacy history.",e)}const a=o.concat(r);return a.sort((e,t)=>e.order-t.order),a}async function gppReloadTemplateLibrary(){return gppTemplates=await gppLoadTemplateLibrary(),gppNormalizeTemplateOrder(),gppTemplates.some(e=>e.id===gppFocusedTemplateId)||(gppFocusedTemplateId=gppTemplates[0]?gppTemplates[0].id:null,gppSettings.focusedTemplateId=gppFocusedTemplateId,gppSaveSettings()),"function"==typeof gppRendererSchedule&&gppRendererSchedule(),gppTemplates}function gppNormalizeTemplateOrder(){gppTemplates.forEach((e,t)=>{e.order=t})}async function gppPersistTemplateState(e){e.ephemeral||await gppDbPut(GPP_STATE_STORE,{id:e.id,name:e.name,position:e.position,opacity:e.opacity,locked:e.locked,groupNoise:!!e.groupNoise,order:e.order,mask:Array.from(e.mask)})}async function gppPersistTemplateCore(e){if(!e.ephemeral){if("number"==typeof e.legacySourceId){const t=e.id,n=e.legacySourceId,o=await gppEncodeTemplateToPngBlob(e),r=await gppLegacyAddImage(o,e.name,!!e.groupNoise);e.sourceBlob=o,e.id="legacy_"+r.id,e.legacySourceId=r.id,r.hash&&gppLegacyDecodeCache.set(r.hash,{width:e.width,height:e.height,indexType:e.indexType,indices:e.indices,palette:e.palette,counts:e.counts,opaquePixelCount:e.opaquePixelCount,quantized:e.quantized,poorMatchPixelCount:e.poorMatchPixelCount,position:e.position}),r.id!==n&&await Promise.all([gppLegacyDeleteImage(n),gppDbDelete(GPP_STATE_STORE,t)]),await gppPersistTemplateState(e);const a=gppTemplates.findIndex(e=>e.id===t);return-1!==a&&(gppTemplates[a]=e),void(gppFocusedTemplateId===t&&(gppFocusedTemplateId=e.id,gppSettings.focusedTemplateId=e.id,gppSaveSettings()))}await gppDbPut(GPP_TEMPLATE_STORE,{id:e.id,name:e.name,width:e.width,height:e.height,indexType:e.indexType,indices:e.indices.buffer,palette:Array.from(e.palette),counts:Array.from(e.counts),opaquePixelCount:e.opaquePixelCount,quantized:e.quantized,poorMatchPixelCount:e.poorMatchPixelCount,sourceBlob:e.sourceBlob})}}async function gppDeleteTemplate(e){const t=[gppDbDelete(GPP_STATE_STORE,e.id)];"number"==typeof e.legacySourceId?t.push(gppLegacyDeleteImage(e.legacySourceId)):t.push(gppDbDelete(GPP_TEMPLATE_STORE,e.id)),await Promise.all(t),gppTemplates=gppTemplates.filter(t=>t.id!==e.id),gppNormalizeTemplateOrder(),gppFocusedTemplateId===e.id&&(gppFocusedTemplateId=gppTemplates[0]?gppTemplates[0].id:null,gppSettings.focusedTemplateId=gppFocusedTemplateId,gppSaveSettings()),await Promise.all(gppTemplates.map(gppPersistTemplateState))}const GPP_ACCEPTED_IMAGE_TYPES=["image/png","image/jpeg","image/jfif","image/webp"];function gppCancelIngest(){if(gppIngestOperation){gppIngestToken++;try{gppIngestOperation.worker&&gppIngestOperation.worker.terminate()}catch(e){}gppIngestOperation=null}}function gppIngestViaWorker(e,t){return new Promise((n,o)=>{let r;try{const e=gppBuildIngestWorkerSource(),t=new Blob([e],{type:"text/javascript"}),n=URL.createObjectURL(t);r=new Worker(n),URL.revokeObjectURL(n)}catch(e){return void o(e)}const a="op_"+Date.now()+"_"+Math.random().toString(36).slice(2,6),i=++gppIngestToken;gppIngestOperation={worker:r,operationId:a,cancel:()=>{gppIngestToken++,r.terminate()}},r.onmessage=e=>{if(gppIngestToken!==i)return;const l=e.data||{};if(l.operationId===a)if("progress"===l.type)t&&t(l.fraction,l.label);else if("complete"===l.type)gppIngestOperation=null,r.terminate(),n(l);else if("error"===l.type){gppIngestOperation=null,r.terminate();const e=new Error(l.message);e.name=l.name,o(e)}},r.onerror=e=>{gppIngestToken===i&&(gppIngestOperation=null,r.terminate(),o(e&&e.message?new Error(e.message):new Error("Worker failed to start.")))},r.postMessage({type:"ingest",operationId:a,file:e})})}async function gppIngestOnMainThread(e,t){const n=gppCreateCore(),o=await createImageBitmap(e),r=document.createElement("canvas");r.width=o.width,r.height=o.height;const a=r.getContext("2d",{willReadFrequently:!0,colorSpace:"srgb"});a.drawImage(o,0,0),o.close();let i=a.getImageData(0,0,r.width,r.height).data,l=r.width,s=r.height;const c=n.decodePositionHeader(i,l,s);i=c.rgba,l=c.width,s=c.height;const d=++gppIngestToken,p=await n.indexRgbaAsync(i,l,s,{isCancelled:()=>gppIngestToken!==d,onProgress:(e,n)=>t&&t(.05+.94*e,n)});return{width:l,height:s,position:c.position,indexType:p.indexType,indices:p.indices,palette:p.palette,counts:p.counts,mask:p.mask,opaquePixelCount:p.opaquePixelCount,quantized:p.quantized,poorMatchPixelCount:p.poorMatchPixelCount}}async function gppDecodeImageBlob(e,t){let n;try{n=await gppIngestViaWorker(e,t),n.indices=gppCreateCore().makeIndexArray(n.indexType,0,n.indices),n.palette=new Uint32Array(n.palette),n.counts=new Uint32Array(n.counts),n.mask=new Uint32Array(n.mask)}catch(o){console.warn("[GeoPixelcons++] Ghost++: Worker ingest failed, falling back to main thread.",o),n=await gppIngestOnMainThread(e,t)}return n}async function gppFindMatchingPrivateTemplate(e){for(const t of gppTemplates)if(0!==t.id.indexOf("legacy_")&&t.sourceBlob)try{if(await gppLegacyComputeTemplateId(t.sourceBlob)===e)return t}catch(e){}return null}async function gppRemoveSupersededPrivateTemplate(e){await Promise.all([gppDbDelete(GPP_TEMPLATE_STORE,e.id),gppDbDelete(GPP_STATE_STORE,e.id)]),gppTemplates=gppTemplates.filter(t=>t.id!==e.id)}function gppBuildGuildTemplateStub(e){const t=Number.isFinite(e.imageGridX)&&Number.isFinite(e.imageGridY);return{id:"guild_"+e.id,name:"Guild project "+e.id,width:0,height:0,indexType:null,indices:null,palette:null,counts:null,opaquePixelCount:0,quantized:!1,poorMatchPixelCount:0,sourceBlob:null,mask:null,position:t?{gridX:Math.round(e.imageGridX),gridY:Math.round(e.imageGridY)}:null,opacity:0,locked:!1,groupNoise:!1,order:0,scanSummary:null,ephemeral:!0,guildProject:e,guildDecoded:!1}}async function gppDecodeGuildTemplateRaw(e){if(e.guildDecoded)return e;const t=e.guildProject,n=await fetch(t.image),o=await n.blob(),r=await gppDecodeImageBlob(o);return e.width=r.width,e.height=r.height,e.indexType=r.indexType,e.indices=r.indices,e.palette=r.palette,e.counts=r.counts,e.opaquePixelCount=r.opaquePixelCount,e.quantized=r.quantized,e.poorMatchPixelCount=r.poorMatchPixelCount,e.mask=r.mask,e.position||(e.position=r.position||null),e.guildDecoded=!0,e}let gppGuildDecodeQueue=Promise.resolve();function gppQueueGuildDecode(e){const t=gppGuildDecodeQueue.then(()=>gppDecodeGuildTemplateRaw(e));return gppGuildDecodeQueue=t.then(()=>{},()=>{}),t}function gppAddGuildTemplate(e){gppGuildTemplates.push(e),"function"==typeof gppRendererSchedule&&gppRendererSchedule()}function gppGetOrCreateGuildTemplate(e){const t="guild_"+e.id,n=gppGuildTemplates.find(e=>e.id===t);if(n)return n;const o=gppBuildGuildTemplateStub(e);return gppAddGuildTemplate(o),o}async function gppIngestImageFile(e,t){t&&t(0,"Starting");const n=await gppDecodeImageBlob(e,t),o=(e.name||"Untitled template").replace(/\.[a-z0-9]+$/i,""),r=await gppLegacyComputeTemplateId(e),a=await gppFindMatchingPrivateTemplate(r),i=await gppLegacyAddImage(e,o,!1),l="legacy_"+i.id,s=i.id;i.hash&&gppLegacyDecodeCache.set(i.hash,n);const c={id:l,legacySourceId:s,name:o,width:n.width,height:n.height,indexType:n.indexType,indices:n.indices,palette:n.palette,counts:n.counts,opaquePixelCount:n.opaquePixelCount,quantized:n.quantized,poorMatchPixelCount:n.poorMatchPixelCount,sourceBlob:e,mask:n.mask,position:n.position||null,opacity:1,locked:!1,groupNoise:!1,order:gppTemplates.length,scanSummary:null},d=gppTemplates.findIndex(e=>e.id===l),p=-1!==d?gppTemplates[d]:a;return p&&(c.order=p.order,c.opacity=p.opacity,c.locked=p.locked,c.groupNoise=p.groupNoise,c.position=p.position||c.position,c.mask=p.mask),-1!==d?gppTemplates[d]=c:(a&&await gppRemoveSupersededPrivateTemplate(a),gppTemplates.push(c)),await gppPersistTemplateState(c),gppFocusedTemplateId=c.id,gppSettings.focusedTemplateId=c.id,gppSaveSettings(),gppTriggerLoadTimeScan(c),c}function gppBase64ToBlob(e,t){const n=atob(e),o=new Uint8Array(n.length);for(let e=0;e<n.length;e++)o[e]=n.charCodeAt(e);return new Blob([o],{type:t})}async function gppIngestJsonFile(e,t){const n=await e.text(),o=JSON.parse(n);if(o&&Array.isArray(o.images)){const e=[],n=[];for(const r of o.images){if(!r||"string"!=typeof r.imageData){n.push(r&&r.name);continue}const o=r.mimeType||"image/png",a=gppBase64ToBlob(r.imageData,o),i=o.split("/")[1]||"png",l=new File([a],(r.name||"Imported template")+"."+i,{type:o}),s=await gppIngestImageFile(l,t);"boolean"==typeof r.groupNoise&&s.groupNoise!==r.groupNoise&&(s.groupNoise=r.groupNoise,await gppPersistTemplateState(s)),e.push(s)}if(!e.length)throw new Error("That export did not contain any recognisable images.");return e}if(!o||"ghost-plus-plus-template"!==o.kind||!o.width||!o.height)throw new Error("That JSON file is not a Ghost++ template export or a GeoPixelcons++ ghost history export.");const r=o.name||"Imported template",a={id:gppMakeTemplateId(),name:r,width:o.width,height:o.height,indexType:o.indexType,indices:gppCreateCore().makeIndexArray(o.indexType,0,new Uint8Array(o.indices).buffer),palette:Uint32Array.from(o.palette),counts:Uint32Array.from(o.counts),opaquePixelCount:o.opaquePixelCount,quantized:!!o.quantized,poorMatchPixelCount:o.poorMatchPixelCount||0,sourceBlob:null,mask:o.mask?Uint32Array.from(o.mask):gppCreateCore().makeFullMask(o.palette.length,o.counts),position:o.position||null,opacity:"number"==typeof o.opacity?o.opacity:1,locked:!1,groupNoise:"boolean"==typeof o.groupNoise&&o.groupNoise,order:gppTemplates.length,scanSummary:null},i=await gppEncodeTemplateToPngBlob(a),l=await gppLegacyComputeTemplateId(i),s=await gppFindMatchingPrivateTemplate(l),c=await gppLegacyAddImage(i,r,a.groupNoise);a.id="legacy_"+c.id,a.legacySourceId=c.id,a.sourceBlob=i,c.hash&&gppLegacyDecodeCache.set(c.hash,{width:a.width,height:a.height,indexType:a.indexType,indices:a.indices,palette:a.palette,counts:a.counts,opaquePixelCount:a.opaquePixelCount,quantized:a.quantized,poorMatchPixelCount:a.poorMatchPixelCount,position:a.position});const d=gppTemplates.findIndex(e=>e.id===a.id),p=-1!==d?gppTemplates[d]:s;return p&&(a.order=p.order,a.opacity=p.opacity,a.locked=p.locked,a.groupNoise=p.groupNoise,a.position=p.position||a.position,a.mask=p.mask),-1!==d?gppTemplates[d]=a:(s&&await gppRemoveSupersededPrivateTemplate(s),gppTemplates.push(a)),await gppPersistTemplateState(a),gppFocusedTemplateId=a.id,gppSettings.focusedTemplateId=a.id,gppSaveSettings(),gppTriggerLoadTimeScan(a),[a]}async function gppExportTemplateAsJson(e){const t={kind:"ghost-plus-plus-template",name:e.name,width:e.width,height:e.height,indexType:e.indexType,indices:Array.from(e.indices),palette:Array.from(e.palette),counts:Array.from(e.counts),mask:Array.from(e.mask),opaquePixelCount:e.opaquePixelCount,quantized:e.quantized,poorMatchPixelCount:e.poorMatchPixelCount,position:e.position,opacity:e.opacity,groupNoise:!!e.groupNoise},n=new Blob([JSON.stringify(t)],{type:"application/json"}),o=URL.createObjectURL(n),r=document.createElement("a");r.href=o,r.download=(e.name||"template")+".ghostplusplus.json",r.click(),URL.revokeObjectURL(o)}async function gppEncodeTemplateToPngBlob(e){const t=gppCreateCore();let n=t.indexedToRgba(e.indices,e.indexType,e.palette),o=e.width,r=e.height;if(e.position){const a=t.encodePositionHeader(n,o,r,e.position);n=a.rgba,o=a.width,r=a.height}const a=document.createElement("canvas");a.width=o,a.height=r;return a.getContext("2d").putImageData(new ImageData(n,o,r),0,0),new Promise(e=>a.toBlob(e,"image/png"))}function gppBlobToBase64(e){return new Promise((t,n)=>{const o=new FileReader;o.onloadend=()=>t(o.result.split(",")[1]),o.onerror=n,o.readAsDataURL(e)})}async function gppTemplateToBase64Png(e){return gppBlobToBase64(await gppEncodeTemplateToPngBlob(e))}const GPP_EXPORT_BATCH_SIZE=4;async function gppExportTemplatesAsJson(e,t,n){const o=gppCreateCore(),r=new Array(e.length);let a=0;for(let t=0;t<e.length;t+=GPP_EXPORT_BATCH_SIZE){const i=e.slice(t,t+GPP_EXPORT_BATCH_SIZE),l=await Promise.all(i.map(e=>gppTemplateToBase64Png(e)));i.forEach((i,s)=>{const c=o.templateHash(i.indices,i.palette,i.width,i.height);r[t+s]={id:t+s+1,name:i.name||"Untitled template",date:Date.now(),hash:c,templateId:c,imageData:l[s],mimeType:"image/png",groupNoise:!!i.groupNoise},a++,n&&n(a/e.length,"Exporting "+(i.name||"template"))})}const i={version:"1.0",exportDate:(new Date).toISOString(),images:r},l=new Blob([JSON.stringify(i)],{type:"application/json"}),s=URL.createObjectURL(l),c=document.createElement("a");c.href=s,c.download=t||"ghost-plus-plus-export-"+r.length+".json",c.click(),URL.revokeObjectURL(s)}function gppGetFocusedTemplate(){return gppTemplates.find(e=>e.id===gppFocusedTemplateId)||gppGuildTemplates.find(e=>e.id===gppFocusedTemplateId)||null}async function gppBumpFocusedTemplateToTop(e){const t=gppTemplates.findIndex(t=>t.id===e);if(-1===t)return;const n=gppTemplates[t],o=gppTemplates.filter(t=>t.id!==e);if(!o.length)return;const r=Math.min(...o.map(e=>e.order)),a=0===t&&n.order<r;gppTemplates.splice(t,1),gppTemplates.unshift(n),a||(n.order=r-1,await gppPersistTemplateState(n))}async function gppApplyAutoHideUnfocused(e){const t=[];for(const n of gppTemplates)n.id===e?n.opacity<=0&&(n.opacity=1,t.push(n)):n.opacity>0&&(n.opacity=0,t.push(n));t.length&&(await Promise.all(t.map(e=>gppPersistTemplateState(e))),"function"==typeof gppRendererSchedule&&gppRendererSchedule())}async function gppFocusTemplate(e){const t=gppFocusedTemplateId;gppFocusedTemplateId=e,gppGuildTemplates.some(t=>t.id===e)||(gppSettings.focusedTemplateId=e,gppSaveSettings(),e&&await gppBumpFocusedTemplateToTop(e),e&&e!==t&&(gppTriggerLoadTimeScan(gppTemplates.find(t=>t.id===e)),gppSettings.autoHideUnfocused&&await gppApplyAutoHideUnfocused(e)))}function gppTriggerLoadTimeScan(e){if(!e||!e.position||gppScanRunning)return;if("function"!=typeof gppScanTemplate)return;const t=gppScanTemplate(e);"function"==typeof gppRequestUiRefresh&&gppRequestUiRefresh(),t.catch(e=>{console.error("[GeoPixelcons++] Ghost++ load-time scan failed:",e)}).finally(()=>{"function"==typeof gppRequestUiRefresh&&gppRequestUiRefresh()})}const gppState={get settings(){return gppSettings},get templates(){return gppTemplates},get guildTemplates(){return gppGuildTemplates},get focusedTemplateId(){return gppFocusedTemplateId},get runtimeReady(){return gppRuntimeReady},buildGuildTemplateStub:gppBuildGuildTemplateStub,getOrCreateGuildTemplate:gppGetOrCreateGuildTemplate,decodeGuildTemplate:gppQueueGuildDecode,addGuildTemplate:gppAddGuildTemplate,applyAutoHideUnfocused:gppApplyAutoHideUnfocused,getFocusedTemplate:gppGetFocusedTemplate,focusTemplate:gppFocusTemplate,saveSettings:gppSaveSettings,ingestImageFile:gppIngestImageFile,ingestJsonFile:gppIngestJsonFile,exportTemplateAsJson:gppExportTemplateAsJson,exportTemplatesAsJson:gppExportTemplatesAsJson,deleteTemplate:gppDeleteTemplate,persistTemplateState:gppPersistTemplateState,persistTemplateCore:gppPersistTemplateCore,normalizeTemplateOrder:gppNormalizeTemplateOrder,cancelIngest:gppCancelIngest,reloadLibrary:gppReloadTemplateLibrary,acceptedImageTypes:GPP_ACCEPTED_IMAGE_TYPES};let gppRuntimeInitPromise=null,gppRuntimeReady=!1;function gppTriggerScanForRestoredFocus(){const e=gppTemplates.find(e=>e.id===gppFocusedTemplateId);e&&gppTriggerLoadTimeScan(e)}function gppInitRuntime(){return gppRuntimeInitPromise||(gppRuntimeInitPromise=(async()=>(gppDatabase=await gppOpenDatabase(),gppTemplates=await gppLoadTemplateLibrary(),gppNormalizeTemplateOrder(),gppTemplates.some(e=>e.id===gppFocusedTemplateId)||(gppFocusedTemplateId=gppTemplates[0]?gppTemplates[0].id:null),gppRuntimeReady=!0,gppRequestUiRefresh(),gppTriggerScanForRestoredFocus(),gppState))().catch(e=>{throw gppRuntimeInitPromise=null,e})),gppRuntimeInitPromise}const GPP_IDS=Object.freeze({opener:"gpp-opener",modal:"gpp-modal",style:"gpp-shell-style",left:"gpp-modal-left",right:"gpp-modal-right",rightContent:"gpp-modal-right-content",editingLabel:"gpp-editing-label"});function gppInjectShellStyle(){let e=document.getElementById(GPP_IDS.style);e||(e=document.createElement("style"),e.id=GPP_IDS.style,document.head.appendChild(e)),e.textContent=`\n            #${GPP_IDS.modal} {\n                position: fixed; left: 24px; top: 90px; z-index: 2000;\n                display: flex; flex-direction: row;\n                width: min(92vw, 800px); height: 75vh; min-width: 480px; min-height: 320px;\n                border-radius: .75rem; overflow: hidden;\n                background: ${t2("#ffffff","#1e1e2e")}; color: ${t2("#111827","#f5f5f5")};\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                box-shadow: 0 12px 32px ${t2("rgba(15,23,42,.28)","rgba(0,0,0,.62)")};\n                font: 13px system-ui, sans-serif;\n            }\n            #${GPP_IDS.modal}.gpp-hidden { display: none; }\n            /* Only present for the duration of a collapse/expand toggle (see\n               the toggle-right handler below) — ports ghost-template-manager.js's\n               own .gpc-preview-animating: without a matching width transition\n               on the MODAL itself, right's own width animates smoothly while\n               the modal's outer edge snaps instantly, which reads as a janky,\n               uncoordinated "weird animation" since the two related widths\n               move at different paces. Scoped to a temporary class (not a\n               permanent rule) so it never fights gppWireModalResize's own\n               drag-to-resize, which needs instant, untransitioned width\n               updates while dragging.\n               Duration/easing MUST match #${GPP_IDS.right}'s own width\n               transition exactly (.15s ease, below) — #${GPP_IDS.left} is\n               flex:1 1 0 with no width transition of its own, so at every\n               frame its rendered width is just "modal's current width minus\n               right's current width". If the two transitions run for\n               different durations, that difference is momentarily nonzero\n               partway through (one side finishes shrinking before the\n               other), which reads as the left panel visibly bulging and\n               settling instead of staying rock-steady while only the right\n               side moves. Keeping both transitions identical keeps that\n               difference constant (= left's true width) at every frame. */\n            #${GPP_IDS.modal}.gpp-modal-animating-width { transition: width .15s ease; overflow: hidden; }\n            #${GPP_IDS.modal} .gpp-head {\n                display: flex; align-items: center; gap: 8px; padding: 8px 10px; cursor: move;\n                background: ${t2("#f8fafc","#181825")}; border-bottom: 1px solid ${t2("#d1d5db","#45475a")};\n            }\n            #${GPP_IDS.modal} .gpp-head .gpp-spacer { flex: 1; }\n            #${GPP_IDS.modal} .gpp-head button {\n                border: none; background: transparent; color: inherit; cursor: pointer; font-size: 14px;\n            }\n            #${GPP_IDS.editingLabel} {\n                font-size: 11px; font-weight: 600;\n                color: ${t2("#475569","#a6adc8")};\n            }\n            /* No overflow-y/scrollbar-gutter here — #gpp-left-body (its\n               child, below) is the one that actually scrolls (.gpp-head\n               plus #gpp-left-body's own flex:1 exactly fill this\n               container's height between them), so this element itself\n               never shows a scrollbar. It used to carry both properties\n               anyway — pure dead weight that silently reserved ~15px of\n               scrollbar-gutter space on the right for a scrollbar that\n               could never appear, on top of the horizontal padding bug\n               above; together they were the "invisible padding" that kept\n               .gpp-head and every divider from reaching gpp-panel-splitter. */\n            #${GPP_IDS.left} {\n                flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;\n                padding: 10px 0;\n            }\n            /* Horizontal inset intentionally does NOT live on the container\n               above — .gpp-head is a direct child of it and needs to span\n               the full panel width, flush to .gpp-panel-splitter (so does\n               every details.gpp-collapsible section's own border-top\n               divider, below). Each piece that actually needs breathing\n               room insets ITSELF instead: .gpp-head via its own padding\n               (below), #gpp-drop-zone/#gpp-ingest-status via their own\n               margin, and details.gpp-collapsible via its own padding\n               (further down) — none of which affect where a border drawn\n               on that same element's box actually sits. */\n            #gpp-drop-zone, #gpp-ingest-status { margin-left: 12px; margin-right: 12px; }\n            /* Reserves the scrollbar's own width whether or not it's\n               currently needed, on every scrollable region below — per\n               explicit product feedback, content (Progress/Error Settings/\n               palette/etc.) was visibly shifting left/right as filtering or\n               scanning made a container's content just barely cross the\n               scroll threshold. */\n            #gpp-left-body { scrollbar-gutter: stable; }\n            #${GPP_IDS.right} {\n                position: relative;\n                width: 280px; flex-shrink: 0; display: flex; flex-direction: column; overflow: hidden;\n                border-left: 1px solid ${t2("#d1d5db","#45475a")};\n                background: ${t2("#f8fafc","#181825")};\n                transition: width .15s ease;\n            }\n            #${GPP_IDS.right}.gpp-collapsed { width: 34px; }\n            #${GPP_IDS.right}.gpp-collapsed #${GPP_IDS.rightContent} { opacity: 0; pointer-events: none; }\n            #${GPP_IDS.right}.gpp-collapsed .gpp-panel-splitter { display: none; }\n            #${GPP_IDS.rightContent} { flex: 1; overflow-y: auto; padding: 10px; scrollbar-gutter: stable; }\n            .gpp-panel-splitter {\n                position: absolute; left: -4px; top: 0; bottom: 0; width: 8px;\n                cursor: ew-resize; z-index: 20; background: transparent; transition: background .15s;\n            }\n            .gpp-panel-splitter:hover, .gpp-panel-splitter.gpp-ps-dragging { background: rgba(99,102,241,.25); }\n            .gpp-collapse-btn {\n                width: 20px; height: 20px; border-radius: 9999px; border: 1px solid ${t2("#d1d5db","#45475a")};\n                background: ${t2("#ffffff","#313244")}; color: inherit; cursor: pointer; font-size: 10px;\n                display: flex; align-items: center; justify-content: center; flex-shrink: 0;\n            }\n            .gpp-edge { position: absolute; z-index: 5; cursor: move; }\n            .gpp-edge.n, .gpp-edge.s { left: 12px; right: 12px; height: 6px; }\n            .gpp-edge.n { top: 0; } .gpp-edge.s { bottom: 0; }\n            .gpp-edge.e, .gpp-edge.w { top: 12px; bottom: 12px; width: 6px; }\n            .gpp-edge.e { right: 0; } .gpp-edge.w { left: 0; }\n            .gpp-corner { position: absolute; z-index: 6; width: 14px; height: 14px; }\n            .gpp-corner.nw { top: 0; left: 0; cursor: nwse-resize; }\n            .gpp-corner.ne { top: 0; right: 0; cursor: nesw-resize; }\n            .gpp-corner.sw { bottom: 0; left: 0; cursor: nesw-resize; }\n            .gpp-corner.se { bottom: 0; right: 0; cursor: nwse-resize; }\n            /* Horizontal padding lives HERE (not on the ambient #gpp-modal-left\n               container above) so the summary heading and .gpp-body content\n               stay inset, while border-top itself — drawn on this element's\n               own border box, which padding never moves — still spans the\n               full, true panel width flush to .gpp-panel-splitter. */\n            details.gpp-collapsible { border-top: 1px solid ${t2("#e5e7eb","#313244")}; padding: 8px 12px; }\n            details.gpp-collapsible > summary {\n                cursor: pointer; font-weight: 600; list-style: none; display: flex; align-items: center; gap: 6px;\n            }\n            details.gpp-collapsible > summary::-webkit-details-marker { display: none; }\n            details.gpp-collapsible > summary::before { content: '\\25B8'; transition: transform .1s; }\n            details.gpp-collapsible[open] > summary::before { transform: rotate(90deg); }\n            details.gpp-collapsible .gpp-body { padding: 8px 2px 2px; }\n            #gpp-drop-zone {\n                border: 2px dashed ${t2("#cbd5e1","#45475a")}; border-radius: 8px;\n                padding: 14px; text-align: center; cursor: pointer;\n                color: ${t2("#334155","#cdd6f4")};\n                transition: border-color .1s, background .1s;\n            }\n            #gpp-drop-zone:hover, #gpp-drop-zone.gpp-dragging {\n                border-color: ${t2("#2563eb","#89b4fa")};\n                background: ${t2("rgba(37,99,235,.06)","rgba(137,180,250,.08)")};\n            }\n            #gpp-drop-zone .gpp-muted { color: ${t2("#64748b","#a6adc8")}; }\n            #gpp-url-upload-btn {\n                display: inline-block; margin-top: 6px; padding: 0; border: none; background: none;\n                font: inherit; font-size: 11px; text-decoration: underline; cursor: pointer;\n                color: ${t2("#64748b","#a6adc8")};\n            }\n            #gpp-url-upload-btn:hover { color: ${t2("#2563eb","#89b4fa")}; }\n        `}function t2(e,n){return t(e,n)}function gppReplaceNativeOpener(e){const t=document.createElement("button");t.type="button",t.id=GPP_IDS.opener,t.title="Ghost++ template overlay",t.setAttribute("aria-label","Open Ghost++"),t.textContent="👻",t.className="w-10 h-10 bg-white shadow rounded-full flex items-center justify-center hover:bg-gray-100 cursor-pointer",t.style.fontSize="16px",t.addEventListener("click",e);const n={opener:t,native:null};function o(e){n.native=e,e.style.display="none",e.classList.add("hidden"),e.setAttribute("data-gpc-pill","1"),e.parentElement?e.insertAdjacentElement("afterend",t):t.isConnected||document.body.appendChild(t),"function"==typeof gppShimEnable&&(gppShimEnable(),dbgPush("Ghost++ opener/native-button: native-control click captures installed immediately (blocks the hidden native ghost button from still opening the old UI via a keyboard shortcut or other programmatic click, before the user has ever opened Ghost++ once).",{uiComponent:"Ghost++ Template Overlay"}))}const r=document.getElementById("loadGhostImageBtn");if(r)dbgPush("Ghost++ opener/native-button: #loadGhostImageBtn found on the first synchronous check — replaced immediately.",{uiComponent:"Ghost++ Template Overlay"}),o(r);else{dbgPush('Ghost++ opener/native-button: #loadGhostImageBtn NOT found on the first synchronous check — this is the exact condition behind the reported "toggled Ghost++ on, still see the old menu" bug. Watching for it to appear instead of giving up.',{uiComponent:"Ghost++ Template Overlay"});const e=Date.now();document.body.appendChild(t);const n=document.getElementById("controls-left")||document.body,r=new MutationObserver(()=>{const t=document.getElementById("loadGhostImageBtn");t&&(r.disconnect(),clearTimeout(a),dbgPush("Ghost++ opener/native-button: #loadGhostImageBtn appeared "+(Date.now()-e)+"ms after Ghost++ started watching for it — replaced now.",{uiComponent:"Ghost++ Template Overlay"}),o(t))});r.observe(n,{childList:!0,subtree:!0});const a=setTimeout(()=>{r.disconnect(),dbgPush("Ghost++ opener/native-button: gave up after 15s — #loadGhostImageBtn was never found. The native ghost tool will keep working alongside the Ghost++ button instead of being hidden.",{uiComponent:"Ghost++ Template Overlay"}),console.error("[GeoPixelcons++] Ghost++: never found the native #loadGhostImageBtn to replace -- it will keep working alongside the Ghost++ button instead of being hidden.")},15e3)}return n}function gppRestoreNativeOpener(e){e&&e.opener&&e.opener.remove(),e&&e.native&&(e.native.style.display="",e.native.classList.remove("hidden"),e.native.removeAttribute("data-gpc-pill"))}function gppBuildModalShell(){gppInjectShellStyle();const e=document.createElement("div");return e.id=GPP_IDS.modal,e.className="gpp-hidden",e.setAttribute("role","dialog"),e.setAttribute("aria-label","Ghost++ template overlay manager"),e.innerHTML=`\n            <div class="gpp-edge n" data-gpp-drag></div>\n            <div class="gpp-edge s" data-gpp-drag></div>\n            <div class="gpp-edge e" data-gpp-drag></div>\n            <div class="gpp-edge w" data-gpp-drag></div>\n            <div class="gpp-corner nw" data-gpp-resize="nw"></div>\n            <div class="gpp-corner ne" data-gpp-resize="ne"></div>\n            <div class="gpp-corner sw" data-gpp-resize="sw"></div>\n            <div class="gpp-corner se" data-gpp-resize="se"></div>\n            <div id="${GPP_IDS.left}">\n                <div class="gpp-head" data-gpp-drag>\n                    <strong>Ghost++</strong>\n                    <span id="${GPP_IDS.editingLabel}"></span>\n                    <span class="gpp-spacer"></span>\n                    <button type="button" data-gpp-action="close" aria-label="Close">✕</button>\n                </div>\n                <div id="gpp-left-body" style="flex:1; overflow-y:auto;"></div>\n            </div>\n            <div id="${GPP_IDS.right}">\n                <div class="gpp-panel-splitter" data-gpp-splitter title="Drag to resize"></div>\n                <div style="display:flex; align-items:center; padding:6px 8px; gap:6px;">\n                    <button type="button" class="gpp-collapse-btn" data-gpp-action="toggle-right" title="Collapse">◀</button>\n                    <span class="gpp-muted" style="font-size:11px;">Preview &amp; library</span>\n                </div>\n                <div id="${GPP_IDS.rightContent}"></div>\n            </div>\n        `,document.body.appendChild(e),gppWireModalDrag(e),gppWireModalResize(e),gppWirePanelSplitter(e),e.addEventListener("transitionend",t=>{t.target===e&&"width"===t.propertyName&&e.classList.remove("gpp-modal-animating-width")}),e.querySelector('[data-gpp-action="toggle-right"]').addEventListener("click",()=>{const t=document.getElementById(GPP_IDS.right);e.classList.add("gpp-modal-animating-width");const n=Math.round(e.getBoundingClientRect().width);if(!t.classList.contains("gpp-collapsed")){const o=Math.round(t.getBoundingClientRect().width);o>38&&(e.dataset.gppRightWidth=o+"px"),e.style.width=Math.max(320,n-o+34)+"px"}else{const t=n-34,o=parseInt(e.dataset.gppRightWidth,10)||280;e.style.width=Math.max(480,t+o)+"px"}const o=t.classList.toggle("gpp-collapsed");o?(t.style.width&&(t.dataset.gppExpandedWidth=t.style.width),t.style.width=""):t.dataset.gppExpandedWidth&&(t.style.width=t.dataset.gppExpandedWidth),e.querySelector('[data-gpp-action="toggle-right"]').textContent=o?"▶":"◀",e.querySelector('[data-gpp-action="toggle-right"]').title=o?"Expand":"Collapse"}),e}function gppWirePanelSplitter(e){const t=e.querySelector("[data-gpp-splitter]"),n=document.getElementById(GPP_IDS.right);t.addEventListener("pointerdown",o=>{if(0!==o.button||n.classList.contains("gpp-collapsed"))return;o.preventDefault(),o.stopPropagation();const r=o.clientX,a=n.getBoundingClientRect().width;n.style.transition="none",t.classList.add("gpp-ps-dragging"),t.setPointerCapture(o.pointerId);const i=t=>{const o=r-t.clientX,i=e.getBoundingClientRect().width,l=Math.max(34,Math.floor(.05*i)),s=Math.max(l,Math.floor(.95*i)),c=Math.min(Math.max(l,a+o),s);n.style.width=c+"px"},l=()=>{t.classList.remove("gpp-ps-dragging"),n.style.transition="",t.removeEventListener("pointermove",i),t.removeEventListener("pointerup",l)};t.addEventListener("pointermove",i),t.addEventListener("pointerup",l)})}function gppWireModalDrag(e){e.querySelectorAll("[data-gpp-drag]").forEach(t=>{let n=null;t.addEventListener("pointerdown",o=>{if(0!==o.button||o.target.closest("button"))return;const r=e.getBoundingClientRect();n={id:o.pointerId,dx:o.clientX-r.left,dy:o.clientY-r.top},t.setPointerCapture(o.pointerId),o.stopPropagation()}),t.addEventListener("pointermove",t=>{n&&n.id===t.pointerId&&(e.style.left=Math.max(0,t.clientX-n.dx)+"px",e.style.top=Math.max(0,t.clientY-n.dy)+"px",e.style.right="auto")}),t.addEventListener("pointerup",e=>{n&&n.id===e.pointerId&&(n=null)})})}function gppWireModalResize(e){e.querySelectorAll("[data-gpp-resize]").forEach(t=>{const n=t.dataset.gppResize;let o=null;t.addEventListener("pointerdown",n=>{if(0!==n.button)return;const r=e.getBoundingClientRect();o={id:n.pointerId,startX:n.clientX,startY:n.clientY,rect:r},t.setPointerCapture(n.pointerId),n.stopPropagation()}),t.addEventListener("pointermove",t=>{if(!o||o.id!==t.pointerId)return;const r=t.clientX-o.startX,a=t.clientY-o.startY;if(n.includes("e")&&(e.style.width=Math.max(480,o.rect.width+r)+"px"),n.includes("s")&&(e.style.height=Math.max(320,o.rect.height+a)+"px"),n.includes("w")){const t=Math.max(480,o.rect.width-r);e.style.width=t+"px",e.style.left=o.rect.left+o.rect.width-t+"px"}if(n.includes("n")){const t=Math.max(320,o.rect.height-a);e.style.height=t+"px",e.style.top=o.rect.top+o.rect.height-t+"px"}}),t.addEventListener("pointerup",e=>{o&&o.id===e.pointerId&&(o=null)})})}const GPP_RENDERER_CANVAS_ID="gpp-renderer-canvas",GPP_RENDERER_MAP_POLL_MS=100,GPP_RENDERER_MAP_POLL_MAX_ATTEMPTS=300,gppRendererCore=gppCreateCore();let gppRendererState=null,gppRendererRuntimeReady=null;function gppRendererClamp(e,t,n){return Math.min(n,Math.max(t,e))}function gppRendererMaskSignature(e){let t=-1640531527;for(let n=0;n<e.length;n++)t=0|Math.imul(t^e[n],2246822507);return t>>>0}function gppRendererCreateCanvasElement(){const e=document.createElement("canvas");return e.id=GPP_RENDERER_CANVAS_ID,e.setAttribute("aria-hidden","true"),Object.assign(e.style,{position:"absolute",inset:"0",width:"100%",height:"100%",pointerEvents:"none",imageRendering:"pixelated",zIndex:"1"}),e}function gppRendererEnsureRuntime(){return gppRendererRuntimeReady||(gppRendererRuntimeReady=(gppDatabase?Promise.resolve(gppState):gppInitRuntime()).catch(e=>{throw gppRendererRuntimeReady=null,e})),gppRendererRuntimeReady}function gppRendererMount(){if(gppRendererState)return gppRendererState.handle;const e={destroyed:!1,attached:!1,canvas:null,map:null,turf:null,gl:null,ctx2d:null,program:null,vertexBuffer:null,mode:"pending",resources:new Map,resizeObserver:null,frameRequest:0,moveHandler:null,zoomHandler:null,contextLostHandler:null,pollTimer:0,pollAttempts:0};return e.handle=Object.freeze({get mounted(){return e.attached},get mode(){return e.mode},schedule:gppRendererSchedule,destroy:gppRendererDestroy}),gppRendererState=e,gppRendererWaitForMap(e),e.handle}function gppRendererWaitForMap(e){if(e.destroyed)return;const t=gppGetMap(),n=gppGetTurf();if(t&&n)try{gppRendererAttach(e,t,n)}catch(e){console.error("[GeoPixelcons++] Ghost++ renderer failed to attach:",e)}else e.pollAttempts++>=GPP_RENDERER_MAP_POLL_MAX_ATTEMPTS?console.warn("[GeoPixelcons++] Ghost++ renderer: map never became available; giving up."):e.pollTimer=setTimeout(()=>gppRendererWaitForMap(e),GPP_RENDERER_MAP_POLL_MS)}function gppRendererAttach(e,t,n){if(e.destroyed||e.attached)return;const o=document.getElementById(GPP_RENDERER_CANVAS_ID);o&&o.remove();const r=gppRendererCreateCanvasElement();t.getContainer().appendChild(r),e.canvas=r,e.map=t,e.turf=n;let a=null;try{a=r.getContext("webgl2",{alpha:!0,antialias:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!1})}catch(e){a=null}if(a){e.gl=a;try{gppRendererInitWebGl(e),e.mode="webgl2"}catch(t){console.warn("[GeoPixelcons++] Ghost++ renderer: WebGL2 unavailable, falling back to Canvas2D.",t),gppRendererSwitchToCanvas2d(e,t)}}if(!e.gl){if(e.ctx2d=e.canvas.getContext("2d",{alpha:!0,colorSpace:"srgb"}),!e.ctx2d)return void console.error("[GeoPixelcons++] Ghost++ renderer: no supported canvas backend is available.");e.ctx2d.imageSmoothingEnabled=!1,e.mode="canvas2d"}e.resizeObserver=new ResizeObserver(()=>gppRendererScheduleInternal(e)),e.resizeObserver.observe(t.getContainer()),e.gl&&(e.contextLostHandler=t=>{t.preventDefault();try{gppRendererSwitchToCanvas2d(e,new Error("WebGL context lost")),gppRendererScheduleInternal(e)}catch(e){console.error("[GeoPixelcons++] Ghost++ renderer: context lost and Canvas2D fallback failed.",e)}},e.canvas.addEventListener("webglcontextlost",e.contextLostHandler)),e.moveHandler=()=>gppRendererScheduleInternal(e),e.zoomHandler=()=>gppRendererScheduleInternal(e),t.on("move",e.moveHandler),t.on("zoom",e.zoomHandler),e.attached=!0,gppRendererEnsureRuntime().then(()=>gppRendererScheduleInternal(e)).catch(e=>console.error("[GeoPixelcons++] Ghost++ renderer: failed to load the template library.",e)),gppRendererScheduleInternal(e)}function gppRendererDestroy(){if(!gppRendererState)return;const e=gppRendererState;if(e.destroyed=!0,gppRendererState=null,e.pollTimer&&clearTimeout(e.pollTimer),e.frameRequest&&window.cancelAnimationFrame(e.frameRequest),e.resizeObserver)try{e.resizeObserver.disconnect()}catch(e){}if(e.map)try{e.moveHandler&&e.map.off("move",e.moveHandler),e.zoomHandler&&e.map.off("zoom",e.zoomHandler)}catch(e){}if(e.canvas&&e.contextLostHandler)try{e.canvas.removeEventListener("webglcontextlost",e.contextLostHandler)}catch(e){}try{for(const t of e.resources.values())gppRendererDeleteResource(e,t);e.resources.clear(),e.gl&&(e.vertexBuffer&&e.gl.deleteBuffer(e.vertexBuffer),e.program&&e.gl.deleteProgram(e.program))}catch(e){}e.canvas&&e.canvas.parentNode&&e.canvas.remove()}function gppRendererScheduleInternal(e){e&&!e.destroyed&&e.attached&&(e.frameRequest||(e.frameRequest=window.requestAnimationFrame(()=>gppRendererDraw(e))))}function gppRendererSchedule(){gppRendererState&&gppRendererScheduleInternal(gppRendererState)}function gppRendererCompileShader(e,t,n){const o=e.createShader(t);if(e.shaderSource(o,n),e.compileShader(o),!e.getShaderParameter(o,e.COMPILE_STATUS)){const t=e.getShaderInfoLog(o);throw e.deleteShader(o),new Error("Ghost++ renderer shader failed: "+t)}return o}function gppRendererInitWebGl(e){const t=e.gl,n=gppRendererCompileShader(t,t.VERTEX_SHADER,"#version 300 es\n            in vec2 a_position;\n            uniform vec4 u_rect;\n            uniform vec2 u_viewport;\n            out vec2 v_uv;\n            void main() {\n                vec2 pixel = u_rect.xy + (a_position * u_rect.zw);\n                vec2 clip = vec2((pixel.x / u_viewport.x) * 2.0 - 1.0,\n                                 1.0 - (pixel.y / u_viewport.y) * 2.0);\n                gl_Position = vec4(clip, 0.0, 1.0);\n                v_uv = a_position;\n            }"),o=gppRendererCompileShader(t,t.FRAGMENT_SHADER,"#version 300 es\n            precision highp float;\n            precision highp int;\n            precision highp usampler2D;\n            in vec2 v_uv;\n            uniform usampler2D u_indices;\n            uniform usampler2D u_palette;\n            uniform usampler2D u_mask;\n            uniform ivec2 u_template_size;\n            uniform int u_palette_width;\n            uniform uint u_empty;\n            uniform float u_gap_ratio;\n            uniform float u_opacity;\n            out vec4 out_color;\n            void main() {\n                vec2 safe_uv = min(v_uv, vec2(0.9999999));\n                ivec2 cell = ivec2(floor(safe_uv * vec2(u_template_size)));\n                uint palette_index = texelFetch(u_indices, cell, 0).r;\n                if (palette_index == u_empty) discard;\n                int word_index = int(palette_index >> 5u);\n                uint word = texelFetch(u_mask, ivec2(word_index, 0), 0).r;\n                if ((word & (1u << (palette_index & 31u))) == 0u) discard;\n                if (u_gap_ratio <= 0.0) discard;\n                if (u_gap_ratio < 1.0) {\n                    vec2 within = fract(safe_uv * vec2(u_template_size));\n                    float inset = (1.0 - u_gap_ratio) * 0.5;\n                    if (within.x < inset || within.x > 1.0 - inset || within.y < inset || within.y > 1.0 - inset) discard;\n                }\n                int palette_x = int(palette_index) % u_palette_width;\n                int palette_y = int(palette_index) / u_palette_width;\n                uint packed = texelFetch(u_palette, ivec2(palette_x, palette_y), 0).r;\n                vec3 rgb = vec3(float((packed >> 16u) & 255u), float((packed >> 8u) & 255u), float(packed & 255u)) / 255.0;\n                out_color = vec4(rgb, u_opacity);\n            }"),r=t.createProgram();if(t.attachShader(r,n),t.attachShader(r,o),t.linkProgram(r),t.deleteShader(n),t.deleteShader(o),!t.getProgramParameter(r,t.LINK_STATUS))throw new Error(t.getProgramInfoLog(r)||"Could not link Ghost++ renderer shaders.");e.program=r;const a=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,a),t.bufferData(t.ARRAY_BUFFER,new Float32Array([0,0,1,0,0,1,1,1]),t.STATIC_DRAW),e.vertexBuffer=a,t.useProgram(r);const i=t.getAttribLocation(r,"a_position");t.enableVertexAttribArray(i),t.vertexAttribPointer(i,2,t.FLOAT,!1,0,0),t.uniform1i(t.getUniformLocation(r,"u_indices"),0),t.uniform1i(t.getUniformLocation(r,"u_palette"),1),t.uniform1i(t.getUniformLocation(r,"u_mask"),2),t.enable(t.BLEND),t.blendFuncSeparate(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE_MINUS_SRC_ALPHA),t.pixelStorei(t.UNPACK_ALIGNMENT,1)}function gppRendererSwitchToCanvas2d(e,t){if(!e.gl)return;try{for(const t of e.resources.values())gppRendererDeleteResource(e,t);e.vertexBuffer&&e.gl.deleteBuffer(e.vertexBuffer),e.program&&e.gl.deleteProgram(e.program)}catch(e){}e.resources.clear(),e.vertexBuffer=null,e.program=null;const n=e.canvas,o=gppRendererCreateCanvasElement();if(n&&n.parentNode?n.parentNode.replaceChild(o,n):e.map&&e.map.getContainer().appendChild(o),e.canvas=o,e.gl=null,e.ctx2d=o.getContext("2d",{alpha:!0,colorSpace:"srgb"}),!e.ctx2d)throw new Error("Canvas2D fallback could not be created.");e.ctx2d.imageSmoothingEnabled=!1,e.mode="canvas2d",t&&console.warn("[GeoPixelcons++] Ghost++ renderer: using Canvas2D.",t)}function gppRendererCreateTexture(e,t){const n=e.createTexture();return e.activeTexture(e.TEXTURE0+t),e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),n}function gppRendererDeleteResource(e,t){if(!e.gl||!t)return;const n=e.gl;["indexTexture","paletteTexture","maskTexture"].forEach(e=>{t[e]&&n.deleteTexture(t[e])})}function gppRendererRemoveTemplateResource(e,t){const n=e.resources.get(t);gppRendererDeleteResource(e,n),e.resources.delete(t)}function gppRendererUploadTemplateGl(e,t){const n=e.gl;gppRendererRemoveTemplateResource(e,t.id);const o=n.getParameter(n.MAX_TEXTURE_SIZE);if(t.width>o||t.height>o)throw new Error((t.name||"Template")+" exceeds this browser's "+o+"px WebGL texture limit.");const r=gppRendererCreateTexture(n,0);"u8"===t.indexType?n.texImage2D(n.TEXTURE_2D,0,n.R8UI,t.width,t.height,0,n.RED_INTEGER,n.UNSIGNED_BYTE,t.indices):n.texImage2D(n.TEXTURE_2D,0,n.R16UI,t.width,t.height,0,n.RED_INTEGER,n.UNSIGNED_SHORT,t.indices);const a=gppRendererCreateTexture(n,1),i=Math.max(1,Math.min(o,t.palette.length||1)),l=Math.max(1,Math.ceil(Math.max(1,t.palette.length)/i)),s=new Uint32Array(i*l);s.set(t.palette),n.texImage2D(n.TEXTURE_2D,0,n.R32UI,i,l,0,n.RED_INTEGER,n.UNSIGNED_INT,s);const c=gppRendererCreateTexture(n,2),d=t.mask.length?t.mask:new Uint32Array(1);n.texImage2D(n.TEXTURE_2D,0,n.R32UI,d.length,1,0,n.RED_INTEGER,n.UNSIGNED_INT,d),e.resources.set(t.id,{indexTexture:r,paletteTexture:a,maskTexture:c,maskSig:gppRendererMaskSignature(t.mask),paletteWidth:i,indicesRef:t.indices,paletteRef:t.palette,width:t.width,height:t.height})}function gppRendererUploadTemplateCanvas2d(e,t){gppRendererRemoveTemplateResource(e,t.id),e.resources.set(t.id,{colorStrings:Array.from(t.palette,e=>gppRendererCore.packedToHex(e)),indicesRef:t.indices,paletteRef:t.palette,width:t.width,height:t.height})}function gppRendererReconcile(e,t){const n=new Set(t.map(e=>e.id));for(const t of Array.from(e.resources.keys()))n.has(t)||gppRendererRemoveTemplateResource(e,t);for(const n of t){const o=e.resources.get(n.id);if(!o||o.indicesRef!==n.indices||o.paletteRef!==n.palette||o.width!==n.width||o.height!==n.height)try{e.gl?gppRendererUploadTemplateGl(e,n):gppRendererUploadTemplateCanvas2d(e,n)}catch(n){if(e.gl){console.warn("[GeoPixelcons++] Ghost++ renderer: WebGL2 upload failed, falling back to Canvas2D.",n),gppRendererSwitchToCanvas2d(e,n);for(const n of t)try{gppRendererUploadTemplateCanvas2d(e,n)}catch(e){console.error("[GeoPixelcons++] Ghost++ renderer: could not prepare template for Canvas2D.",e)}return}console.error("[GeoPixelcons++] Ghost++ renderer: could not prepare template.",n)}}}function gppRendererSyncMaskGl(e,t,n){const o=gppRendererMaskSignature(t.mask);if(n.maskSig===o)return;n.maskSig=o;const r=e.gl;r.activeTexture(r.TEXTURE2),r.bindTexture(r.TEXTURE_2D,n.maskTexture);const a=t.mask.length?t.mask:new Uint32Array(1);r.texImage2D(r.TEXTURE_2D,0,r.R32UI,a.length,1,0,r.RED_INTEGER,r.UNSIGNED_INT,a)}function gppRendererProjectTemplate(e,t,n,o){const r=gppPlacementPreview,a=r&&r.templateId===o.id?r.position:o.position;if(!a)return null;try{const r=n.gridSize,i=n.halfSize,l=n.offsetMetersX,s=n.offsetMetersY,c=[a.gridX*r-i+l,a.gridY*r+i+s],d=a.gridX+o.width-1,p=[d*r+i+l,(a.gridY-o.height+1)*r-i+s],g=e.project(t.toWgs84(c)),u=e.project(t.toWgs84(p));return[g.x,g.y,u.x,u.y].every(Number.isFinite)?{x:g.x,y:g.y,width:u.x-g.x,height:u.y-g.y}:null}catch(e){return null}}function gppRendererViewportIntersects(e,t,n){return e&&e.x+e.width>=0&&e.x<=t&&e.y+e.height>=0&&e.y<=n}function gppRendererEnsureSize(e){const t=e.map.getContainer().getBoundingClientRect(),n=Math.max(1,t.width),o=Math.max(1,t.height),r=Math.max(1,window.devicePixelRatio||1),a=Math.max(1,Math.round(n*r)),i=Math.max(1,Math.round(o*r));return e.canvas.width===a&&e.canvas.height===i||(e.canvas.width=a,e.canvas.height=i),e.gl?e.gl.viewport(0,0,a,i):e.ctx2d&&(e.ctx2d.setTransform(a/n,0,0,i/o,0,0),e.ctx2d.imageSmoothingEnabled=!1),{cssWidth:n,cssHeight:o,dpr:r}}function gppRendererIsTemplateVisible(e,t){if(e.id===t)return!0;return(gppForcedVisibleTemplateIds.has(e.id)?1:e.opacity)>0}function gppRendererDraw(e){if(e.frameRequest=0,e.destroyed||!e.attached)return;let t=e.turf;t||(t=gppGetTurf(),t&&(e.turf=t));const n=gppRendererEnsureSize(e);if(e.gl?(e.gl.clearColor(0,0,0,0),e.gl.clear(e.gl.COLOR_BUFFER_BIT)):e.ctx2d&&e.ctx2d.clearRect(0,0,n.cssWidth,n.cssHeight),!t)return;let o;try{o=e.map.getZoom()}catch(e){o=-1/0}const r=gppReadGridConstants();if(o<r.minZoom)return;const a=gppPlacementPreview?gppPlacementPreview.templateId:null,i=gppState.templates.concat(gppState.guildTemplates).filter(e=>(e.position||e.id===a)&&gppRendererIsTemplateVisible(e,a)).slice().sort((e,t)=>e.order-t.order);gppRendererReconcile(e,i);const l=gppSettings;e.gl?gppRendererDrawWebGl(e,n,i,r,t,l):e.ctx2d&&gppRendererDrawCanvas2d(e,n,i,r,t,l)}function gppRendererDrawWebGl(e,t,n,o,r,a){const i=e.gl;i.useProgram(e.program),i.bindBuffer(i.ARRAY_BUFFER,e.vertexBuffer);const l=t=>i.getUniformLocation(e.program,t);i.uniform2f(l("u_viewport"),t.cssWidth,t.cssHeight);for(const s of n){const n=gppForcedVisibleTemplateIds.has(s.id),c=n?1:s.opacity;if(c<=0)continue;const d=e.resources.get(s.id);if(!d)continue;const p=gppRendererProjectTemplate(e.map,r,o,s);gppRendererViewportIntersects(p,t.cssWidth,t.cssHeight)&&(i.uniform4f(l("u_rect"),p.x,p.y,p.width,p.height),i.uniform1f(l("u_opacity"),c),i.uniform1f(l("u_gap_ratio"),n?1:a.gapRatio),gppRendererSyncMaskGl(e,s,d),i.uniform2i(l("u_template_size"),s.width,s.height),i.uniform1i(l("u_palette_width"),d.paletteWidth),i.uniform1ui(l("u_empty"),gppRendererCore.emptyValue(s.indexType)),i.activeTexture(i.TEXTURE0),i.bindTexture(i.TEXTURE_2D,d.indexTexture),i.activeTexture(i.TEXTURE1),i.bindTexture(i.TEXTURE_2D,d.paletteTexture),i.activeTexture(i.TEXTURE2),i.bindTexture(i.TEXTURE_2D,d.maskTexture),i.drawArrays(i.TRIANGLE_STRIP,0,4))}}function gppRendererDrawCanvas2d(e,t,n,o,r,a){const i=e.ctx2d;for(const l of n){const n=gppForcedVisibleTemplateIds.has(l.id),s=n?1:l.opacity;if(s<=0)continue;const c=e.resources.get(l.id);if(!c)continue;const d=gppRendererProjectTemplate(e.map,r,o,l);if(!gppRendererViewportIntersects(d,t.cssWidth,t.cssHeight))continue;i.globalAlpha=s;const p=n?1:a.gapRatio;if(p<=0){i.globalAlpha=1;continue}const g=d.width/l.width,u=d.height/l.height,m=Math.abs(g),h=Math.abs(u),f=Math.max(1,Math.ceil(1/Math.max(m,1e-4))),b=Math.max(1,Math.ceil(1/Math.max(h,1e-4))),y=gppRendererClamp(Math.floor((0-d.x)/g),0,l.width-1),x=gppRendererClamp(Math.ceil((t.cssWidth-d.x)/g),0,l.width),v=gppRendererClamp(Math.floor((0-d.y)/u),0,l.height-1),w=gppRendererClamp(Math.ceil((t.cssHeight-d.y)/u),0,l.height),k=Math.max(0,Math.floor(y/f)*f),E=Math.max(0,Math.floor(v/b)*b),C=gppRendererCore.emptyValue(l.indexType);for(let e=E;e<w;e+=b)for(let t=k;t<x;t+=f){const n=Math.min(l.width-1,t+Math.floor(f/2)),o=Math.min(l.height-1,e+Math.floor(b/2)),r=l.indices[o*l.width+n];if(r===C||!gppRendererCore.maskHas(l.mask,r))continue;const a=d.x+t*g,s=d.y+e*u,m=g*f,h=u*b,y=m*(1-p)*.5,x=h*(1-p)*.5,v=m-2*y,w=h-2*x;v<=0||w<=0||(i.fillStyle=c.colorStrings[r],i.fillRect(a+y,s+x,v,w))}i.globalAlpha=1}}if(_settings.ghostPlusPlus)try{gppRendererMount()}catch(e){console.error("[GeoPixelcons++] Ghost++ renderer failed to mount:",e)}const GPP_NATIVE_MIRROR_GLOBAL="__gppNativeMirrorPayload",GPP_NATIVE_CONTROL_TARGETS=[["loadGhostImageBtn","click"],["ghostImageInput","change"],["initiatePlaceGhostBtn","click"],["clearGhostImageBtn","click"]];let gppShimActive=!1,gppNativeControlCaptures=[],gppGuildProjectHookInstalled=!1,gppMirroredTemplateId=null,gppMirroredIndices=null,gppMirroredPalette=null;function gppNativeBridgeTarget(){return"undefined"!=typeof unsafeWindow?unsafeWindow:window}function gppWriteNativeGhostLocalStorage(e,t){try{e&&localStorage.setItem("ghostImageCoords",JSON.stringify(e)),t&&localStorage.setItem("ghostImageData",t)}catch(e){}}function gppClearNativeGhostLocalStorage(){try{localStorage.removeItem("ghostImageCoords"),localStorage.removeItem("ghostImageData")}catch(e){}}function gppEncodeRgbaToDataUrl(e,t,n){const o=document.createElement("canvas");o.width=t,o.height=n;const r=o.getContext("2d"),a=r.createImageData(t,n);return a.data.set(e),r.putImageData(a,0,0),o.toDataURL("image/png")}function gppNativeDrawReplacement(){}function gppNativeRegenerateReplacement(){}function gppNativeInitializeReplacement(){gppShimSyncFocusedTemplate()}function gppBlockNativeGhostControl(e){if(!gppShimActive)return;if(e.preventDefault(),e.stopImmediatePropagation(),e.target&&"ghostImageInput"===e.target.id)try{e.target.value=""}catch(e){}console.warn("[GeoPixelcons++] Ghost++: native ghost control blocked while Ghost++ owns the overlay slot. Use the Ghost++ (👻) panel instead.");const t=document.getElementById(GPP_IDS.opener);t&&t.click()}function gppInstallNativeControlCaptures(){gppRemoveNativeControlCaptures(),GPP_NATIVE_CONTROL_TARGETS.forEach(e=>{const t=e[0],n=e[1],o=document.getElementById(t);o&&(o.addEventListener(n,gppBlockNativeGhostControl,!0),gppNativeControlCaptures.push({element:o,type:n}))})}function gppRemoveNativeControlCaptures(){gppNativeControlCaptures.forEach(e=>{e.element.removeEventListener(e.type,gppBlockNativeGhostControl,!0)}),gppNativeControlCaptures=[]}async function gppLoadGuildProjectIntoGhostPlusPlus(e){const t=gppNativeBridgeTarget(),n=gppReadNativeGuildData(),o=n&&Array.isArray(n.projects)?n.projects.find(t=>t.id===e):null;if(o)try{const e=gppState.getOrCreateGuildTemplate(o);await gppState.decodeGuildTemplate(e),e.opacity=1,await gppState.focusTemplate(e.id),gppShimSyncFocusedTemplate();const t=document.getElementById(GPP_IDS.opener);t&&t.click()}catch(n){console.error("[GeoPixelcons++] Ghost++: failed to load guild project "+e+" as a Ghost++ template.",n),"function"==typeof t.showAlert&&t.showAlert("Error","Could not load that guild project into Ghost++.")}else"function"==typeof t.showAlert&&t.showAlert("Error","Could not find the selected project.")}function gppEnsureGuildProjectHook(){if(gppGuildProjectHookInstalled)return;const e=gppNativeBridgeTarget();"function"==typeof e.setProjectAsGhost&&(gppGuildProjectHookInstalled=!0,e.setProjectAsGhost=function(e){gppLoadGuildProjectIntoGhostPlusPlus(e)})}function gppClearNativeMirror(){gppWriteNativeGhostMirror("ghostImage = null;ghostImageTopLeft = null;ghostImageOriginalData = null;ghostImageCanvas = null;ghostPaletteColors = [];ghostActivePaletteColors = new Set();ghostAllImageColors = new Map();paletteToImageColorMap = new Map();imageColorToDominantColorMap = new Map();isColorFilterDisabled = false;ghostImageFileObject = null;"),gppClearNativeGhostLocalStorage(),gppMirroredTemplateId=null,gppMirroredIndices=null,gppMirroredPalette=null}function gppBuildPaletteMirrorData(e,t){const n=[],o=[];for(let r=0;r<t.palette.length;r++){const a=t.palette[r],i=e.unpackRgb(a),l=e.packedToRgbaString(a),s=e.packedToHex(a),c=t.counts[r]||0;n.push({r:i.r,g:i.g,b:i.b,rgba:l,hex:s,count:c,totalCount:c}),e.maskHas(t.mask,r)&&o.push(l)}return{paletteColors:n,activeRgba:o}}function gppWriteFullNativeMirror(e){const t=gppCreateCore(),n=t.indexedToRgba(e.indices,e.indexType,e.palette),o=gppBuildPaletteMirrorData(t,e),r=[],a=[];for(let e=0;e<o.paletteColors.length;e++){const t=o.paletteColors[e];r.push([t.rgba,t.count]),a.push([t.rgba,t.rgba])}if(gppNativeBridgeTarget()[GPP_NATIVE_MIRROR_GLOBAL]={width:e.width,height:e.height,rgbaBuffer:n.buffer,topLeft:e.position?{gridX:e.position.gridX,gridY:e.position.gridY}:null,paletteColors:o.paletteColors,activeRgba:o.activeRgba,allColorsEntries:r,dominantEntries:a},gppWriteNativeGhostMirror('var _p = window["'+GPP_NATIVE_MIRROR_GLOBAL+'"];if (!_p) return;var _bytes = new Uint8ClampedArray(_p.rgbaBuffer);var _imageData;try {  _imageData = new ImageData(_bytes, _p.width, _p.height, { colorSpace: "srgb" });} catch (e) {  var _scratch = document.createElement("canvas").getContext("2d");  _imageData = _scratch.createImageData(_p.width, _p.height);  _imageData.data.set(_bytes);}var _paletteColors = [];for (var _i = 0; _i < _p.paletteColors.length; _i++) {  var _pc = _p.paletteColors[_i];  _paletteColors.push({ r: _pc.r, g: _pc.g, b: _pc.b, rgba: _pc.rgba, hex: _pc.hex, count: _pc.count, totalCount: _pc.totalCount });}var _activeSet = new Set();for (var _j = 0; _j < _p.activeRgba.length; _j++) _activeSet.add(_p.activeRgba[_j]);var _allColors = new Map();for (var _k = 0; _k < _p.allColorsEntries.length; _k++) _allColors.set(_p.allColorsEntries[_k][0], _p.allColorsEntries[_k][1]);var _dominant = new Map();for (var _m = 0; _m < _p.dominantEntries.length; _m++) _dominant.set(_p.dominantEntries[_m][0], _p.dominantEntries[_m][1]);ghostImage = { width: _p.width, height: _p.height };ghostImageTopLeft = _p.topLeft ? { gridX: _p.topLeft.gridX, gridY: _p.topLeft.gridY } : null;ghostImageOriginalData = _imageData;ghostImageCanvas = null;ghostPaletteColors = _paletteColors;ghostActivePaletteColors = _activeSet;ghostAllImageColors = _allColors;paletteToImageColorMap = new Map();imageColorToDominantColorMap = _dominant;isColorFilterDisabled = false;ghostImageFileObject = null;delete window["'+GPP_NATIVE_MIRROR_GLOBAL+'"];'),e.position){const t=gppEncodeRgbaToDataUrl(n,e.width,e.height);gppWriteNativeGhostLocalStorage({gridX:e.position.gridX,gridY:e.position.gridY},t)}gppMirroredTemplateId=e.id,gppMirroredIndices=e.indices,gppMirroredPalette=e.palette}function gppWriteLightNativeMirror(e){const t=gppBuildPaletteMirrorData(gppCreateCore(),e);gppNativeBridgeTarget()[GPP_NATIVE_MIRROR_GLOBAL]={topLeft:e.position?{gridX:e.position.gridX,gridY:e.position.gridY}:null,paletteColors:t.paletteColors,activeRgba:t.activeRgba},gppWriteNativeGhostMirror('var _p = window["'+GPP_NATIVE_MIRROR_GLOBAL+'"];if (!_p) return;var _paletteColors = [];for (var _i = 0; _i < _p.paletteColors.length; _i++) {  var _pc = _p.paletteColors[_i];  _paletteColors.push({ r: _pc.r, g: _pc.g, b: _pc.b, rgba: _pc.rgba, hex: _pc.hex, count: _pc.count, totalCount: _pc.totalCount });}var _activeSet = new Set();for (var _j = 0; _j < _p.activeRgba.length; _j++) _activeSet.add(_p.activeRgba[_j]);ghostImageTopLeft = _p.topLeft ? { gridX: _p.topLeft.gridX, gridY: _p.topLeft.gridY } : null;ghostPaletteColors = _paletteColors;ghostActivePaletteColors = _activeSet;isColorFilterDisabled = false;delete window["'+GPP_NATIVE_MIRROR_GLOBAL+'"];'),e.position&&gppWriteNativeGhostLocalStorage({gridX:e.position.gridX,gridY:e.position.gridY},null)}function gppShimSyncFocusedTemplate(){if(!gppShimActive)return;const e=gppState.getFocusedTemplate();if(!e)return void gppClearNativeMirror();e.id===gppMirroredTemplateId&&e.indices===gppMirroredIndices&&e.palette===gppMirroredPalette?gppWriteLightNativeMirror(e):gppWriteFullNativeMirror(e)}let gppNativeGhostCanvasObserver=null;function gppSyncRendererVisibility(e){const t=document.getElementById(GPP_RENDERER_CANVAS_ID);t&&(t.style.display=e?"none":"")}function gppInstallGhostCanvasVisibilitySync(){if(gppNativeGhostCanvasObserver)return;const e=e=>{gppSyncRendererVisibility(e.hidden),gppNativeGhostCanvasObserver=new MutationObserver(()=>gppSyncRendererVisibility(e.hidden)),gppNativeGhostCanvasObserver.observe(e,{attributes:!0,attributeFilter:["hidden"]})},t=document.getElementById("ghost-canvas");if(t)return void e(t);const n=new MutationObserver(()=>{const t=document.getElementById("ghost-canvas");t&&(n.disconnect(),e(t))});n.observe(document.body,{childList:!0,subtree:!0})}function gppShimEnable(){if(gppShimActive)gppShimSyncFocusedTemplate();else{gppShimActive=!0,gppSetNativeFunction("drawGhostImageOnCanvas",gppNativeDrawReplacement),gppSetNativeFunction("regenerateGhostCanvas",gppNativeRegenerateReplacement),gppSetNativeFunction("initializeGhostFromStorage",gppNativeInitializeReplacement),gppInstallNativeControlCaptures(),gppInstallGhostCanvasVisibilitySync(),gppClearNativeGhostCanvasPaint();try{const e=gppReadNativeGhostSnapshot();e&&e.hasGhostImage&&console.warn("[GeoPixelcons++] Ghost++: a native ghost image was already active; Ghost++ is taking over the overlay slot.")}catch(e){}gppShimSyncFocusedTemplate()}}let gppForcedVisibleTemplateIds=new Set;function gppIsPositionLocked(e){return!(!e||!e.locked&&!e.ephemeral)}let gppOpacityPersistTimer=null;function gppScheduleOpacityPersist(e){gppOpacityPersistTimer&&clearTimeout(gppOpacityPersistTimer),gppOpacityPersistTimer=setTimeout(()=>{gppOpacityPersistTimer=null,gppState.persistTemplateState(e).catch(e=>{console.error("[GeoPixelcons++] Ghost++ placement: failed to persist template opacity.",e)})},300)}let gppPlacementCaptureCleanup=null,gppPlacementPreview=null;function gppCancelPlacementCapture(){if(gppPlacementCaptureCleanup){try{gppPlacementCaptureCleanup()}catch(e){}gppPlacementCaptureCleanup=null}}function gppMapClientPointToGrid(e,t,n,o,r){const a=e.getContainer().getBoundingClientRect(),i=e.unproject([o-a.left,r-a.top]);if(!i)return null;const l="number"==typeof i.lng?i.lng:i[0],s="number"==typeof i.lat?i.lat:i[1];if(!Number.isFinite(l)||!Number.isFinite(s))return null;const c=t.toMercator([l,s]);return c?{gridX:Math.round((c[0]-n.offsetMetersX)/n.gridSize),gridY:Math.round((c[1]-n.offsetMetersY)/n.gridSize)}:null}function gppBeginPlacementCapture(e,t,n){if(gppCancelPlacementCapture(),gppIsPositionLocked(e))return void(n&&n("This template’s position is locked.",!0));const o=gppGetMap(),r=gppGetTurf();if(!o||!r)return void(n&&n("Map is not ready yet.",!0));const a=o.getContainer(),i=gppReadGridConstants(),l=a.style.cursor;function s(){a.removeEventListener("click",p,!0),a.removeEventListener("mousemove",c),a.removeEventListener("mouseleave",d),document.removeEventListener("keydown",g,!0),a.style.cursor=l,gppPlacementCaptureCleanup=null,gppPlacementPreview&&gppPlacementPreview.templateId===e.id&&(gppPlacementPreview=null,gppNotifyRendererSchedule())}function c(t){const n=gppMapClientPointToGrid(o,r,i,t.clientX,t.clientY);n&&(gppPlacementPreview={templateId:e.id,position:n},gppNotifyRendererSchedule())}function d(){gppPlacementPreview&&gppPlacementPreview.templateId===e.id&&(gppPlacementPreview=null,gppNotifyRendererSchedule())}function p(e){e.preventDefault(),e.stopPropagation(),"function"==typeof e.stopImmediatePropagation&&e.stopImmediatePropagation();const a=gppMapClientPointToGrid(o,r,i,e.clientX,e.clientY);s(),a?t(a):n&&n("Could not resolve that click to a grid cell.",!0)}function g(e){"Escape"===e.key&&(s(),n&&n("Placement cancelled.",!1))}a.style.cursor="crosshair",a.addEventListener("click",p,!0),a.addEventListener("mousemove",c),a.addEventListener("mouseleave",d),document.addEventListener("keydown",g,!0),gppPlacementCaptureCleanup=s,n&&n("Move the pointer over the map to preview the template, then click to set its top-left cell. Escape cancels.",!1)}function gppInjectPlacementStyle(){let e=document.getElementById("gpp-pt-style");e||(e=document.createElement("style"),e.id="gpp-pt-style",document.head.appendChild(e)),e.textContent=`\n            .gpp-pt-btn {\n                padding: 3px 9px; border-radius: 4px; cursor: pointer; font-size: 12px;\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                background: ${t2("#f8fafc","#313244")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-pt-btn:hover:not(:disabled) { background: ${t2("#e2e8f0","#45475a")}; }\n            .gpp-pt-btn:disabled { opacity: .45; cursor: not-allowed; }\n            /* Place / Unset / Go to / Preview line up as roughly-equal-width\n               columns via flex-grow, but (unlike a fixed-column grid, which\n               has no wrap mechanism and forces this row to overflow its\n               container once shrunk past the buttons' combined min-content\n               width) flex-wrap lets them reflow onto a second line as the\n               right panel narrows — matching the nudge-arrow row below,\n               which already uses this same pattern. */\n            .gpp-pt-row3 {\n                display: flex; flex-wrap: wrap; gap: 6px;\n            }\n            .gpp-pt-row3 .gpp-pt-btn { flex: 1 1 64px; box-sizing: border-box; text-align: center; }\n            .gpp-pt-btn-active { border-color: ${t2("#2563eb","#89b4fa")}; color: ${t2("#2563eb","#89b4fa")}; }\n            .gpp-pt-opacity-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }\n            .gpp-pt-opacity-row label { flex: 0 0 auto; min-width: 50px; font-size: 12px; color: ${t2("#1f2937","#e2e2f5")}; }\n            .gpp-pt-opacity-row input[type="range"] { flex: 1 1 auto; min-width: 0; }\n            .gpp-pt-opacity-value {\n                flex: 0 0 auto; min-width: 34px; text-align: right; font-size: 11px;\n                font-variant-numeric: tabular-nums; color: ${t2("#475569","#a6adc8")};\n            }\n            .gpp-pt-reset-btn {\n                border: none; background: transparent; cursor: pointer; font-size: 13px;\n                padding: 0 2px; flex-shrink: 0; color: ${t2("#64748b","#a6adc8")};\n            }\n            .gpp-pt-input {\n                width: 100%; box-sizing: border-box; padding: 4px 6px; border-radius: 4px; font-size: 12px;\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                background: ${t2("#ffffff","#11111b")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-pt-input:disabled { opacity: .5; }\n            .gpp-pt-field { flex: 1; display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: ${t2("#64748b","#a6adc8")}; }\n            .gpp-pt-lock { display: flex; align-items: center; gap: 4px; font-size: 12px; color: ${t2("#111827","#f5f5f5")}; margin-left: auto; }\n        `}function gppNotifyRendererSchedule(){"function"==typeof gppRendererSchedule&&gppRendererSchedule()}function gppRenderPositionTransform(e,t,n){if(!e)return;gppCancelPlacementCapture(),gppInjectPlacementStyle();const o=e.querySelector("details.gpp-collapsible"),r=!o||o.open;e.innerHTML="";const a=document.createElement("details");a.className="gpp-collapsible",a.open=r;const i=document.createElement("summary");i.textContent="Template Settings";const l=document.createElement("div");if(l.className="gpp-body",a.appendChild(i),a.appendChild(l),e.appendChild(a),!t){const e=document.createElement("p");return e.style.cssText=`margin: 0; font-size: 12px; color: ${t2("#64748b","#a6adc8")};`,e.textContent="No template selected.",void l.appendChild(e)}const s=gppIsPositionLocked(t),c=s?"disabled":"",d=!!t.groupNoise;l.innerHTML=`\n            <div style="display:flex; gap:8px; margin-bottom:8px;">\n                <label class="gpp-pt-field">Top-left X\n                    <input id="gpp-pt-x" class="gpp-pt-input" type="number" step="1" ${c}>\n                </label>\n                <label class="gpp-pt-field">Top-left Y\n                    <input id="gpp-pt-y" class="gpp-pt-input" type="number" step="1" ${c}>\n                </label>\n            </div>\n            <div class="gpp-pt-row3" style="margin-bottom:6px;">\n                <button type="button" id="gpp-pt-place" class="gpp-pt-btn" ${c}>Place</button>\n                <button type="button" id="gpp-pt-unset" class="gpp-pt-btn" ${t.position&&!s?"":"disabled"} title="Unloads the template from the map — click Place again to put it back">Unset</button>\n                <button type="button" id="gpp-pt-goto" class="gpp-pt-btn" ${t.position?"":"disabled"}>Go to</button>\n                <button type="button" id="gpp-pt-preview" class="gpp-pt-btn" title="Temporarily show this template at 100% opacity with no cell gaps, without changing its actual Opacity setting">Preview</button>\n            </div>\n            <div style="display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin-bottom:6px;">\n                <button type="button" id="gpp-pt-nudge-left" class="gpp-pt-btn" title="Nudge left" ${c}>&larr;</button>\n                <button type="button" id="gpp-pt-nudge-up" class="gpp-pt-btn" title="Nudge up" ${c}>&uarr;</button>\n                <button type="button" id="gpp-pt-nudge-down" class="gpp-pt-btn" title="Nudge down" ${c}>&darr;</button>\n                <button type="button" id="gpp-pt-nudge-right" class="gpp-pt-btn" title="Nudge right" ${c}>&rarr;</button>\n            </div>\n            <div class="gpp-pt-opacity-row">\n                <label for="gpp-pt-opacity">Opacity</label>\n                <input id="gpp-pt-opacity" type="range" min="0" max="100" step="1" title="Template overlay opacity. 0% is fully invisible.">\n                <span id="gpp-pt-opacity-value" class="gpp-pt-opacity-value"></span>\n                <button type="button" id="gpp-pt-opacity-reset" class="gpp-pt-reset-btn" title="Reset to default opacity">&#8630;</button>\n            </div>\n            <div style="display:flex; align-items:center; margin-bottom:6px;">\n                <label class="gpp-pt-lock" style="margin-left:0;" ${t.ephemeral?'title="Guild templates are always position-locked — you can\'t move them from this UI."':""}><input id="gpp-pt-lock" type="checkbox" ${s?"checked":""} ${t.ephemeral?"disabled":""}> Lock Position</label>\n            </div>\n            <div style="display:flex; align-items:center; margin-bottom:2px;">\n                <label class="gpp-pt-lock" style="margin-left:0;" title="Matches the native ghost tool's Group Noise: merges near-identical source colors and loosens progress/error matching for them."><input id="gpp-pt-group-noise" type="checkbox" ${d?"checked":""}> Group noise</label>\n            </div>\n            <div id="gpp-pt-status" style="font-size:11px; min-height:14px; color:${t2("#64748b","#a6adc8")};"></div>\n        `;const p=l.querySelector("#gpp-pt-x"),g=l.querySelector("#gpp-pt-y");p.value=t.position?String(t.position.gridX):"",g.value=t.position?String(t.position.gridY):"";const u=l.querySelector("#gpp-pt-status");function m(e,t){u.textContent=e||"",u.style.color=t?t2("#dc2626","#f38ba8"):t2("#64748b","#a6adc8")}async function h(e,o){gppIsPositionLocked(t)||Number.isFinite(e)&&Number.isFinite(o)&&(t.position={gridX:Math.round(e),gridY:Math.round(o)},await gppState.persistTemplateState(t),gppNotifyRendererSchedule(),n())}function f(){const e=function(){const e=p.value.trim(),t=g.value.trim(),n=Number(e),o=Number(t);return e&&t&&Number.isInteger(n)&&Number.isInteger(o)?{gridX:n,gridY:o}:(m("Enter both coordinates as whole numbers.",!0),null)}();e&&h(e.gridX,e.gridY).catch(e=>m(e&&e.message?e.message:String(e),!0))}p.addEventListener("change",f),g.addEventListener("change",f),l.querySelector("#gpp-pt-place").addEventListener("click",()=>{gppIsPositionLocked(t)||gppBeginPlacementCapture(t,e=>{h(e.gridX,e.gridY).then(()=>m(`Placed at ${e.gridX}, ${e.gridY}.`,!1)).catch(e=>m(e&&e.message?e.message:String(e),!0))},(e,t)=>m(e,t))});const b=l.querySelector("#gpp-pt-goto");b&&!b.disabled&&b.addEventListener("click",()=>{"function"==typeof gppLibraryFlyToTemplate&&gppLibraryFlyToTemplate(t)});const y=l.querySelector("#gpp-pt-unset");y&&!y.disabled&&y.addEventListener("click",()=>{gppIsPositionLocked(t)||(gppCancelPlacementCapture(),t.position=null,gppState.persistTemplateState(t).then(()=>{gppNotifyRendererSchedule(),m("Position cleared — click Place to show it again.",!1),n()}).catch(e=>m(e&&e.message?e.message:String(e),!0)))});const x=l.querySelector("#gpp-pt-preview"),v=()=>{x.classList.toggle("gpp-pt-btn-active",gppForcedVisibleTemplateIds.has(t.id))};v(),x.addEventListener("click",()=>{gppForcedVisibleTemplateIds.has(t.id)?gppForcedVisibleTemplateIds.delete(t.id):gppForcedVisibleTemplateIds.add(t.id),v(),gppNotifyRendererSchedule()});const w=l.querySelector("#gpp-pt-opacity"),k=l.querySelector("#gpp-pt-opacity-value");function E(e,n){if(gppIsPositionLocked(t))return;const o=t.position||{gridX:0,gridY:0};h(o.gridX+e,o.gridY+n).catch(e=>m(e&&e.message?e.message:String(e),!0))}w.value=String(Math.round(100*gppClamp(t.opacity,0,1))),k.textContent=w.value+"%",w.addEventListener("input",()=>{k.textContent=w.value+"%",t.opacity=gppClamp(Number(w.value)/100,0,1),gppNotifyRendererSchedule(),gppScheduleOpacityPersist(t)}),w.addEventListener("change",()=>{gppScheduleOpacityPersist(t),n()}),l.querySelector("#gpp-pt-opacity-reset").addEventListener("click",()=>{w.value="100",k.textContent="100%",t.opacity=1,gppNotifyRendererSchedule(),gppScheduleOpacityPersist(t),n()}),l.querySelector("#gpp-pt-nudge-left").addEventListener("click",()=>E(-1,0)),l.querySelector("#gpp-pt-nudge-right").addEventListener("click",()=>E(1,0)),l.querySelector("#gpp-pt-nudge-up").addEventListener("click",()=>E(0,1)),l.querySelector("#gpp-pt-nudge-down").addEventListener("click",()=>E(0,-1)),l.querySelector("#gpp-pt-lock").addEventListener("change",e=>{t.locked=!!e.target.checked,t.locked&&gppCancelPlacementCapture(),gppState.persistTemplateState(t).then(()=>n()).catch(e=>m(e&&e.message?e.message:String(e),!0))}),l.querySelector("#gpp-pt-group-noise").addEventListener("change",e=>{t.groupNoise=!!e.target.checked,gppState.persistTemplateState(t).then(()=>{"function"==typeof gppShimSyncFocusedTemplate&&gppShimSyncFocusedTemplate(),n()}).catch(e=>m(e&&e.message?e.message:String(e),!0))})}async function gppShortcutCommitPosition(e,t,n){e&&!gppIsPositionLocked(e)&&Number.isFinite(t)&&Number.isFinite(n)&&(e.position={gridX:Math.round(t),gridY:Math.round(n)},await gppState.persistTemplateState(e),gppNotifyRendererSchedule(),gppRequestUiRefresh())}function gppNudgeFocusedTemplateByKeyboard(e,t){const n=gppState.getFocusedTemplate();n&&!gppIsPositionLocked(n)&&n.position&&gppShortcutCommitPosition(n,n.position.gridX+e,n.position.gridY+t).catch(e=>console.error("[GeoPixelcons++] Ghost++ keyboard nudge failed:",e))}function gppTriggerPlaceShortcut(){const e=gppState.getFocusedTemplate();e&&!gppIsPositionLocked(e)&&gppBeginPlacementCapture(e,t=>{gppShortcutCommitPosition(e,t.gridX,t.gridY).catch(e=>console.error("[GeoPixelcons++] Ghost++ keyboard place failed:",e))},null)}function gppHandlePlacementKeydown(e){const t=document.getElementById(GPP_IDS.modal);if(!t||t.classList.contains("gpp-hidden"))return;if(e.defaultPrevented)return;const n=e.target;if(n&&"function"==typeof n.matches&&n.matches('input, textarea, select, [contenteditable="true"]'))return;const o={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,1],ArrowDown:[0,-1]}[e.key];if(o)return e.preventDefault(),e.stopPropagation(),void gppNudgeFocusedTemplateByKeyboard(o[0],o[1]);1!==e.key.length||"e"!==e.key.toLowerCase()||e.ctrlKey||e.metaKey||e.altKey||(e.preventDefault(),e.stopPropagation(),gppTriggerPlaceShortcut())}_settings.ghostPlusPlus&&document.addEventListener("keydown",gppHandlePlacementKeydown,!0);const GPP_SCAN_BAND_HEIGHT=128;let gppScanRunning=!1,gppScanningTemplateId=null;function gppScanIsBusyFor(e){return gppScanRunning&&!!e&&gppScanningTemplateId===e.id}let gppAutoscanHookInstalled=!1,gppAutoscanDebounceTimer=null;function gppScheduleAutoscan(){gppSettings.autoscanEnabled&&(clearTimeout(gppAutoscanDebounceTimer),gppAutoscanDebounceTimer=setTimeout(()=>{const e=gppState.getFocusedTemplate();if(!e||!e.position||gppScanRunning)return;const t=gppScanTemplate(e);"function"==typeof gppRequestUiRefresh&&gppRequestUiRefresh(),t.catch(e=>{console.error("[GeoPixelcons++] Ghost++ autoscan failed:",e)}).finally(()=>{"function"==typeof gppRequestUiRefresh&&gppRequestUiRefresh()})},1500))}function gppEnsureAutoscanHook(){if(gppAutoscanHookInstalled)return;const e="undefined"!=typeof unsafeWindow?unsafeWindow:window,t=e.placePixelAt;"function"==typeof t&&(gppAutoscanHookInstalled=!0,e.placePixelAt=function(){const e=t.apply(this,arguments);return gppScheduleAutoscan(),gppScanScheduleErrorRedraw(),e})}function gppScanYield(){return new Promise(e=>{"function"==typeof window.requestIdleCallback?window.requestIdleCallback(()=>e(),{timeout:50}):window.setTimeout(e,0)})}function gppScanProcessBand(e,t,n,o,r,a,i,l,s,c,d){const p=t.constants.ERROR_STATE,g=t.emptyValue(e.indexType);for(let u=0;u<a;u++){let a=(i+u)*e.width+l,m=u*r*4;for(let i=0;i<r;i++,a++,m+=4){const r=e.indices[a];if(r===g)continue;const i=o?t.compareRealityPixel(r,o[m],o[m+1],o[m+2],o[m+3],n,!0,d):p.UNKNOWN;s[a]=i;const l=c[r];i===p.CORRECT?l.correct++:i===p.WRONG?l.wrong++:i===p.MISSING?l.missing++:l.unknown++}}}async function gppScanRunInternal(e){const t=gppCreateCore(),n=(t.constants.ERROR_STATE,gppReadGridConstants().tileSize),o=t.computeGridBounds(e.position,e.width,e.height);if(!o)throw new Error("Template has no position.");const r=new Map;e.palette.forEach((e,t)=>r.set(e,t)),e.groupNoise&&!e.groupNoiseData&&(e.groupNoiseData=t.groupPaletteColors(e.palette));const a=e.groupNoise&&e.groupNoiseData?e.groupNoiseData.groupOfIndex:null,i=new Uint8Array(e.width*e.height),l=new Array(e.palette.length);for(let e=0;e<l.length;e++)l[e]={correct:0,wrong:0,missing:0,unknown:0};const s=Math.floor(o.left/n)*n,c=Math.floor(o.right/n)*n,d=Math.floor(o.bottom/n)*n,p=Math.floor(o.top/n)*n,g=document.createElement("canvas"),u=g.getContext("2d",{willReadFrequently:!0,colorSpace:"srgb"});for(let m=s;m<=c;m+=n)for(let s=d;s<=p;s+=n){const c=Math.max(o.left,m),d=Math.min(o.right,m+n-1),p=Math.max(o.bottom,s),h=Math.min(o.top,s+n-1);if(c>d||p>h)continue;const f=d-c+1,b=h-p+1,y=c-o.left,x=gppGetTileBitmap(m,s);let v=null;if(x)try{v=await createImageBitmap(x,c-m,p-s,f,b)}catch(e){v=null}try{for(let n=h;n>=p;n-=GPP_SCAN_BAND_HEIGHT){const s=Math.max(p,n-GPP_SCAN_BAND_HEIGHT+1),c=n-s+1,d=o.top-n;let m=null;v&&(g.width===f&&g.height===c||(g.width=f,g.height=c),u.setTransform(1,0,0,1,0,0),u.clearRect(0,0,f,c),u.save(),u.translate(0,c),u.scale(1,-1),u.drawImage(v,0,s-p,f,c,0,0,f,c),u.restore(),m=u.getImageData(0,0,f,c).data),gppScanProcessBand(e,t,r,m,f,c,d,y,i,l,a),await gppScanYield()}}finally{v&&v.close()}}let m=0,h=0,f=0,b=0,y=0;const x=[];for(let n=0;n<e.palette.length;n++){const o=e.counts[n]||0;if(!o)continue;const r=t.maskHas(e.mask,n),a=l[n];x.push({index:n,enabled:r,correct:a.correct,wrong:a.wrong,missing:a.missing,unknown:a.unknown,total:o}),m+=o,h+=a.correct,f+=a.wrong,b+=a.missing,y+=a.unknown}return e.scanSummary={scannedAt:(new Date).toISOString(),total:m,correct:h,wrong:f,missing:b,unknown:y,perColour:x,states:i},e.scanSummary}async function gppScanTemplate(e){if(!e||!e.position)return{ok:!1,reason:"not-positioned"};if(gppScanRunning)return{ok:!1,reason:"busy"};gppScanRunning=!0,gppScanningTemplateId=e.id;try{return await gppScanRunInternal(e),gppScanScheduleErrorRedraw(),{ok:!0}}catch(e){return console.error("[GeoPixelcons++] Ghost++ scan failed:",e),{ok:!1,reason:"error",error:e}}finally{gppScanRunning=!1,gppScanningTemplateId=null}}async function gppFlyToNearestError(e){if(!e||!e.position||!e.scanSummary)return{ok:!1,reason:"nothing-to-search"};const t=gppGetMap(),n=gppGetTurf();if(!t||!n)return{ok:!1,reason:"map-unavailable"};const o=gppCreateCore(),r=o.constants.ERROR_STATE,a=gppReadGridConstants(),i=e.scanSummary.states,l=t.getCenter(),s=n.toMercator([l.lng,l.lat]),c=(s[0]-a.offsetMetersX)/a.gridSize,d=(s[1]-a.offsetMetersY)/a.gridSize,p=e._gppShowWrong||!e._gppShowMissing,g=e._gppShowMissing||!e._gppShowWrong;let u=null,m=1/0;for(let t=0;t<i.length;t+=65536){const n=Math.min(i.length,t+65536);for(let a=t;a<n;a++){const t=i[a];if(t===r.WRONG&&!p)continue;if(t===r.MISSING&&!g)continue;if(t!==r.WRONG&&t!==r.MISSING)continue;const n=e.indices[a];if(!o.maskHas(e.mask,n))continue;const l=a%e.width,s=Math.floor(a/e.width),h=e.position.gridX+l,f=e.position.gridY-s,b=h-c,y=f-d,x=b*b+y*y;x<m&&(m=x,u={gridX:h,gridY:f})}await gppScanYield()}if(!u)return{ok:!1,reason:"none-found"};const h=n.toWgs84([u.gridX*a.gridSize+a.offsetMetersX,u.gridY*a.gridSize+a.offsetMetersY]);return t.jumpTo({center:h,zoom:Math.max(t.getZoom(),17)}),gppScanStartNearestErrorGlow(e.id,u.gridX,u.gridY),{ok:!0}}function gppClearTemplateErrors(e){e&&(e._gppShowWrong=!1,e._gppShowMissing=!1,gppScanScheduleErrorRedraw())}function gppScanComputeViewportGridBounds(){const e=gppGetMap(),t=gppGetTurf();if(!e||!t||"function"!=typeof e.getBounds)return null;const n=gppReadGridConstants(),o=e.getBounds(),r=o.getNorthWest(),a=o.getSouthEast(),i=t.toMercator([r.lng,r.lat]),l=t.toMercator([a.lng,a.lat]);return{left:Math.floor((i[0]-n.offsetMetersX)/n.gridSize)-1,right:Math.ceil((l[0]-n.offsetMetersX)/n.gridSize)+1,bottom:Math.floor((l[1]-n.offsetMetersY)/n.gridSize)-1,top:Math.ceil((i[1]-n.offsetMetersY)/n.gridSize)+1}}let gppScanOverlayCanvas=null,gppScanMapWired=!1,gppScanRedrawScheduled=!1,gppNearestErrorGlow=null,gppNearestErrorGlowRafId=0;const GPP_NEAREST_ERROR_GLOW_DURATION_MS=2200,GPP_NEAREST_ERROR_GLOW_PULSE_MS=650;function gppScanStartNearestErrorGlow(e,t,n){if(gppNearestErrorGlow={templateId:e,gridX:t,gridY:n,startTime:Date.now()},gppNearestErrorGlowRafId)return;const o=()=>{if(!gppNearestErrorGlow)return void(gppNearestErrorGlowRafId=0);if(Date.now()-gppNearestErrorGlow.startTime>=GPP_NEAREST_ERROR_GLOW_DURATION_MS)return gppNearestErrorGlow=null,gppNearestErrorGlowRafId=0,void gppScanRedrawErrors();gppScanRedrawErrors(),gppNearestErrorGlowRafId=requestAnimationFrame(o)};gppNearestErrorGlowRafId=requestAnimationFrame(o)}function gppScanEnsureOverlay(){const e=gppGetMap();if(!e||"function"!=typeof e.getContainer)return null;const t=e.getContainer();if(gppScanOverlayCanvas&&gppScanOverlayCanvas.parentElement===t)return gppScanOverlayCanvas;gppScanOverlayCanvas&&gppScanOverlayCanvas.parentElement&&gppScanOverlayCanvas.remove();const n=document.createElement("canvas");return n.id="gpp-scan-error-layer",n.style.cssText="position:absolute; left:0; top:0; width:100%; height:100%; pointer-events:none; z-index:5;",t.appendChild(n),gppScanOverlayCanvas=n,n}function gppScanWireMapEvents(){if(gppScanMapWired)return;const e=gppGetMap();e&&"function"==typeof e.on&&(e.on("move",gppScanScheduleErrorRedraw),e.on("zoom",gppScanScheduleErrorRedraw),e.on("resize",gppScanScheduleErrorRedraw),window.addEventListener("resize",gppScanScheduleErrorRedraw),gppScanMapWired=!0)}function gppScanScheduleErrorRedraw(){if(gppScanWireMapEvents(),"function"==typeof gppRendererSchedule)try{gppRendererSchedule()}catch(e){}gppScanRedrawScheduled||(gppScanRedrawScheduled=!0,requestAnimationFrame(()=>{gppScanRedrawScheduled=!1,gppScanRedrawErrors()}))}function gppScanRedrawErrors(){const e=gppScanEnsureOverlay();if(!e)return;const t=e.getContext("2d"),n=e.parentElement.getBoundingClientRect(),o=window.devicePixelRatio||1,r=Math.max(1,Math.round(n.width*o)),a=Math.max(1,Math.round(n.height*o));e.width===r&&e.height===a||(e.width=r,e.height=a),t.setTransform(o,0,0,o,0,0),t.clearRect(0,0,n.width,n.height);const i=void 0!==gppState?gppState.getFocusedTemplate():null,l=gppGetMap(),s=gppGetTurf();if(gppNearestErrorGlow&&i&&i.id===gppNearestErrorGlow.templateId&&i.opacity>0&&l&&s){const e=gppReadGridConstants(),n=Date.now()-gppNearestErrorGlow.startTime;try{const o=s.toWgs84([gppNearestErrorGlow.gridX*e.gridSize+e.offsetMetersX,gppNearestErrorGlow.gridY*e.gridSize+e.offsetMetersY]),r=l.project(o);if(Number.isFinite(r.x)&&Number.isFinite(r.y)){const e=Math.max(0,1-n/GPP_NEAREST_ERROR_GLOW_DURATION_MS),o=n%GPP_NEAREST_ERROR_GLOW_PULSE_MS/GPP_NEAREST_ERROR_GLOW_PULSE_MS,a=6+14*o;t.globalAlpha=(1-o)*e,t.strokeStyle="#fbbf24",t.lineWidth=3,t.beginPath(),t.arc(r.x,r.y,a,0,2*Math.PI),t.stroke(),t.globalAlpha=1}}catch(e){}}if(!gppSettings.showErrors)return;const c=!(!i||!i._gppShowWrong),d=!(!i||!i._gppShowMissing);if(!i||i.opacity<=0||!i.position||!i.scanSummary)return;if(!c&&!d)return;if(!l||!s)return;const p=gppCreateCore(),g=p.constants.ERROR_STATE,u=p.emptyValue(i.indexType),m=gppReadGridConstants(),h=p.computeGridBounds(i.position,i.width,i.height),f=gppScanComputeViewportGridBounds();if(!h||!f)return;const b=Math.max(h.left,f.left),y=Math.min(h.right,f.right),x=Math.max(h.bottom,f.bottom),v=Math.min(h.top,f.top);if(b>y||x>v)return;if((y-b+1)*(v-x+1)>4e5)return;const w=s.toWgs84([b*m.gridSize+m.offsetMetersX,v*m.gridSize+m.offsetMetersY]),k=s.toWgs84([(b+1)*m.gridSize+m.offsetMetersX,v*m.gridSize+m.offsetMetersY]),E=s.toWgs84([b*m.gridSize+m.offsetMetersX,(v-1)*m.gridSize+m.offsetMetersY]),C=l.project(w),S=l.project(k),T=l.project(E),P=S.x-C.x,L=S.y-C.y,M=T.x-C.x,I=T.y-C.y,_=Math.abs(P);if(!(_>=2))return;const G=gppState.settings||{},R=G.errorShape||"x",N=Number.isFinite(G.errorOpacity)?G.errorOpacity:1;if(N<=0)return;const A=Number.isFinite(G.errorSizeScale)?G.errorSizeScale:1,z=Math.max(1.5,.32*_*A),B=i.scanSummary.states,O=!1!==gppSettings.hideQueuedCrosses?new Set(gppReadQueuedPixelKeys()):null,D=[];for(let e=v;e>=x;e--){const t=i.position.gridY-e;if(t<0||t>=i.height)continue;const n=v-e;for(let o=b;o<=y;o++){const r=o-i.position.gridX;if(r<0||r>=i.width)continue;const a=t*i.width+r,l=i.indices[a];if(l===u)continue;if(!p.maskHas(i.mask,l))continue;const s=B[a];if(s===g.WRONG&&!c)continue;if(s===g.MISSING&&!d)continue;if(s!==g.WRONG&&s!==g.MISSING)continue;if(O&&O.has(o+","+e))continue;const m=o-b;D.push(C.x+m*P+n*M,C.y+m*L+n*I)}}if(D.length){if(t.globalAlpha=N,t.strokeStyle=G.errorColor||"#dc2626",t.fillStyle=G.errorColor||"#dc2626",t.lineWidth=Math.max(1,Math.min(2,_/4)),"circle"===R){t.beginPath();for(let e=0;e<D.length;e+=2)t.moveTo(D[e]+z,D[e+1]),t.arc(D[e],D[e+1],z,0,2*Math.PI);t.fill()}else if("square"===R){t.beginPath();for(let e=0;e<D.length;e+=2)t.rect(D[e]-z,D[e+1]-z,2*z,2*z);t.fill()}else{t.beginPath();for(let e=0;e<D.length;e+=2)t.moveTo(D[e]-z,D[e+1]-z),t.lineTo(D[e]+z,D[e+1]+z),t.moveTo(D[e]+z,D[e+1]-z),t.lineTo(D[e]-z,D[e+1]+z);t.stroke()}t.globalAlpha=1}}function gppScanFormatRelativeTime(e){if(!e)return"";const t=new Date(e).getTime();if(!Number.isFinite(t))return"";const n=Math.max(0,Math.round((Date.now()-t)/1e3));if(n<5)return"just now";if(n<60)return`${n}s ago`;const o=Math.round(n/60);if(o<60)return`${o}m ago`;const r=Math.round(o/60);return r<24?`${r}h ago`:new Date(e).toLocaleDateString()}function gppScanStyleButton(e,t){e.style.cssText="font:inherit; padding:3px 8px; border-radius:5px; cursor:pointer;border:1px solid "+t2("#cbd5e1","#45475a")+";background:"+(t?t2("#2563eb","#89b4fa"):t2("#ffffff","#313244"))+";color:"+(t?t2("#ffffff","#1e1e2e"):t2("#111827","#f5f5f5"))+";"+(e.disabled?"opacity:.5; cursor:default;":"")}function gppScanCountEnabledErrors(e,t){const n=e.scanSummary;if(!n||!Array.isArray(n.perColour))return 0;const o=gppCreateCore();let r=0;return n.perColour.forEach(n=>{o.maskHas(e.mask,n.index)&&(r+=n[t]||0)}),r}function gppScanAlertEnabledCount(e,t){const n=gppNativeBridgeTarget();if("function"!=typeof n.showAlert)return;const o=gppScanCountEnabledErrors(e,t),r="wrong"===t?"error":"missing pixel";0===o?n.showAlert("Success",("wrong"===t?"Perfect match! No errors":"No missing pixels")+" found among your currently enabled colors."):n.showAlert("Info","Found "+o.toLocaleString()+" "+r+(1===o?"":"s")+" among your currently enabled colors.")}function gppRenderProgressBar(e,t,n){if(!e)return;gppScanScheduleErrorRedraw();const o=e.querySelector("details.gpp-collapsible"),r=!o||o.open;e.innerHTML="";const a=document.createElement("details");a.className="gpp-collapsible",a.open=r;const i=document.createElement("summary");i.textContent="Progress",a.appendChild(i);const l=document.createElement("div");l.className="gpp-body",a.appendChild(l);const s=document.createElement("div");s.style.cssText="display:flex; align-items:center; gap:6px; margin-bottom:6px; flex-wrap:wrap; justify-content:flex-start;";const c=gppScanIsBusyFor(t),d=document.createElement("button");d.type="button",d.textContent=c?"Scanning…":"Scan progress",d.disabled=!t||!t.position||c,d.title=t?t.position?"Compare this template against the live map.":"Place the template on the map first.":"",gppScanStyleButton(d,!0),s.appendChild(d);const p=document.createElement("button");p.type="button";const g=!(!t||!t._gppShowWrong);p.textContent=g?"Hide errors":"Show errors",p.disabled=!t||!t.scanSummary||c,p.title="Mark cells painted the wrong color.",gppScanStyleButton(p,g),s.appendChild(p);const u=document.createElement("button");u.type="button";const m=!(!t||!t._gppShowMissing);u.textContent=m?"Hide missing":"Show missing",u.disabled=!t||!t.scanSummary||c,u.title="Mark cells that are not painted at all yet.",gppScanStyleButton(u,m),s.appendChild(u);const h=document.createElement("button");h.type="button",h.textContent="Nearest error",h.disabled=!t||!t.scanSummary||c,gppScanStyleButton(h,!1),s.appendChild(h);const f=document.createElement("button");f.type="button",f.textContent="Clear",f.title="Hide error/missing markers. Does not discard the scan — progress above stays.",f.disabled=!t||!t._gppShowWrong&&!t._gppShowMissing||c,gppScanStyleButton(f,!1),s.appendChild(f),l.appendChild(s);const b=document.createElement("label");b.style.cssText="display:flex; align-items:center; gap:6px; font-size:11px; margin:0 0 6px; cursor:pointer; color:"+t2("#1f2937","#e2e2f5")+";";const y=document.createElement("input");y.type="checkbox",y.checked=!!gppSettings.autoscanEnabled,y.addEventListener("change",()=>{gppSettings.autoscanEnabled=y.checked,gppState.saveSettings()}),b.title="Automatically re-scans the focused template shortly after you place pixels",b.append(y,document.createTextNode("Autoscan")),l.appendChild(b);const x=document.createElement("div");x.style.cssText="display:flex; height:10px; border-radius:5px; overflow:hidden; background:"+t2("#e5e7eb","#313244")+";",l.appendChild(x);const v=document.createElement("div");if(v.style.cssText="font-size:11px; margin-top:4px; color:"+t2("#475569","#a6adc8")+";",l.appendChild(v),t)if(t.position)if(t.scanSummary){const e=t.scanSummary,n=e.total,o=Math.max(0,n-e.correct-e.wrong),r=Math.max(0,o-e.missing-e.unknown),a=e=>n>0?e/n*100:0;if(n<=0){const e=document.createElement("div");e.style.cssText="width:100%; background:"+t2("#cbd5e1","#45475a")+";",e.title="Template has no opaque pixels",x.appendChild(e),v.textContent="Template has no opaque pixels — nothing to show."}else{const t=document.createElement("div");t.style.cssText=`width:${a(e.correct)}%; background:${t2("#16a34a","#a6e3a1")};`,t.title=`Correct: ${e.correct.toLocaleString()} px`,x.appendChild(t);const i=document.createElement("div");i.style.cssText=`width:${a(e.wrong)}%; background:${t2("#dc2626","#f38ba8")};`,i.title=`Wrong color: ${e.wrong.toLocaleString()} px`,x.appendChild(i);const s=document.createElement("div");s.style.cssText=`width:${a(o)}%; background:${t2("#94a3b8","#6c7086")};`,s.title=`Not yet placed: ${o.toLocaleString()} px (missing: ${e.missing.toLocaleString()}, tile not loaded: ${e.unknown.toLocaleString()}`+(r?`, not yet scanned: ${r.toLocaleString()}`:"")+")",x.appendChild(s);const c=Math.round(a(e.correct));if(v.textContent=`${e.correct.toLocaleString()} completed of ${n.toLocaleString()} total (${c}%)`+(e.scannedAt?` — scanned ${gppScanFormatRelativeTime(e.scannedAt)}`:""),e.wrong>0||e.missing>0){const t=[];e.wrong>0&&t.push(`${e.wrong.toLocaleString()} error${1===e.wrong?"":"s"}`),e.missing>0&&t.push(`${e.missing.toLocaleString()} missing`);const n=document.createElement("div");n.style.cssText="font-size:11px; margin-top:2px; color:"+t2("#475569","#a6adc8")+";",n.textContent=t.join(", ")+(e.wrong>0&&e.missing>0?` (${(e.wrong+e.missing).toLocaleString()} combined)`:""),l.appendChild(n)}}}else{const e=document.createElement("div");e.style.cssText="width:100%; background:"+t2("#cbd5e1","#45475a")+";",e.title="Not scanned yet",x.appendChild(e),v.textContent="Not scanned yet."}else x.style.opacity="0.4",v.textContent="Place the template on the map, then scan to see progress.";else x.style.opacity="0.4",v.textContent="Select or import a template.";e.appendChild(a),d.addEventListener("click",()=>{if(gppScanRunning||!t||!t.position)return;const e=gppScanTemplate(t);n(),e.then(()=>n())}),p.addEventListener("click",()=>{t&&t.scanSummary&&(t._gppShowWrong=!t._gppShowWrong,t._gppShowWrong&&gppScanAlertEnabledCount(t,"wrong"),gppScanScheduleErrorRedraw(),n())}),u.addEventListener("click",()=>{t&&t.scanSummary&&(t._gppShowMissing=!t._gppShowMissing,t._gppShowMissing&&gppScanAlertEnabledCount(t,"missing"),gppScanScheduleErrorRedraw(),n())}),h.addEventListener("click",()=>{t&&t.scanSummary&&gppFlyToNearestError(t)}),f.addEventListener("click",()=>{t&&(gppClearTemplateErrors(t),n())})}function gppRenderErrorSettings(e){if(!e)return;const t=e.querySelector("details.gpp-collapsible"),n=!!t&&t.open;e.innerHTML="";const o=document.createElement("details");o.className="gpp-collapsible",o.open=n;const r=document.createElement("summary");r.textContent="Error Settings",o.appendChild(r);const a=document.createElement("div");function i(e,t,n){const o=document.createElement("button");o.type="button",o.innerHTML="↺",o.title=t,o.style.cssText="border:none; background:transparent; cursor:pointer; font-size:13px; padding:0 2px; flex-shrink:0; color:"+t2("#64748b","#a6adc8")+";",o.addEventListener("click",n),e.appendChild(o)}function l(e){const t=document.createElement("div");t.style.cssText="display:flex; align-items:center; gap:8px; margin:6px 0;";const n=document.createElement("label");return n.style.cssText="flex:0 0 auto; min-width:70px; font-size:12px; color:"+t2("#1f2937","#e2e2f5")+";",n.textContent=e,t.appendChild(n),a.appendChild(t),t}a.className="gpp-body";const s=document.createElement("div");s.style.cssText="display:flex; align-items:center; gap:8px; margin:6px 0;";const c=document.createElement("label");c.style.cssText="display:flex; align-items:center; gap:6px; font-size:12px; cursor:pointer; color:"+t2("#1f2937","#e2e2f5")+";";const d=document.createElement("input");d.type="checkbox",d.checked=!!gppSettings.showErrors;const p=document.createElement("span");p.textContent="Show error crosses",c.append(d,p),s.appendChild(c);const g=document.createElement("label");g.style.cssText="display:flex; align-items:center; gap:6px; font-size:12px; cursor:pointer; margin-left:14px; color:"+t2("#1f2937","#e2e2f5")+";";const u=document.createElement("input");u.type="checkbox",u.checked=!1!==gppSettings.hideQueuedCrosses;const m=document.createElement("span");function h(){const e=d.checked;[b,x,w,C].forEach(t=>{t.disabled=!e}),[f,y,v,E].forEach(t=>{t.style.opacity=e?"":".45"})}m.textContent="Hide queued crosshairs",g.title="Stop showing a crosshair once you've queued a pixel over it, even before it actually paints — only the crosshairs you still need to queue stay visible.",g.append(u,m),s.appendChild(g),u.addEventListener("change",()=>{gppSettings.hideQueuedCrosses=u.checked,gppState.saveSettings(),gppScanScheduleErrorRedraw()}),a.appendChild(s),d.addEventListener("change",()=>{gppSettings.showErrors=d.checked,gppState.saveSettings(),h(),gppScanScheduleErrorRedraw()});const f=l("Shape"),b=document.createElement("select");["x","circle","square"].forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent="x"===e?"X mark":"circle"===e?"Circle":"Square",(gppSettings.errorShape||"x")===e&&(t.selected=!0),b.appendChild(t)}),b.addEventListener("change",()=>{gppSettings.errorShape=b.value,gppState.saveSettings(),gppScanScheduleErrorRedraw()}),f.appendChild(b);const y=l("Color"),x=document.createElement("input");x.type="color",x.value=gppSettings.errorColor||"#dc2626",x.addEventListener("input",()=>{gppSettings.errorColor=x.value,gppState.saveSettings(),gppScanScheduleErrorRedraw()}),y.appendChild(x),i(y,"Reset to default color",()=>{x.value="#dc2626",gppSettings.errorColor="#dc2626",gppState.saveSettings(),gppScanScheduleErrorRedraw()});const v=l("Opacity"),w=document.createElement("input");w.type="range",w.min="0",w.max="100",w.step="1",w.value=String(Math.round(100*(Number.isFinite(gppSettings.errorOpacity)?gppSettings.errorOpacity:1))),w.style.flex="1";const k=document.createElement("span");k.style.cssText="font-size:11px; min-width:32px; text-align:right;",k.textContent=w.value+"%",w.addEventListener("input",()=>{k.textContent=w.value+"%",gppSettings.errorOpacity=Number(w.value)/100,gppState.saveSettings(),gppScanScheduleErrorRedraw()}),v.append(w,k),i(v,"Reset to default opacity",()=>{w.value="100",k.textContent="100%",gppSettings.errorOpacity=1,gppState.saveSettings(),gppScanScheduleErrorRedraw()});const E=l("Size"),C=document.createElement("input");C.type="range",C.min="25",C.max="250",C.step="5",C.value=String(Math.round(100*(Number.isFinite(gppSettings.errorSizeScale)?gppSettings.errorSizeScale:1))),C.style.flex="1";const S=document.createElement("span");S.style.cssText="font-size:11px; min-width:32px; text-align:right;",S.textContent=C.value+"%",C.addEventListener("input",()=>{S.textContent=C.value+"%",gppSettings.errorSizeScale=Number(C.value)/100,gppState.saveSettings(),gppScanScheduleErrorRedraw()}),E.append(C,S),i(E,"Reset to default size",()=>{C.value="100",S.textContent="100%",gppSettings.errorSizeScale=1,gppState.saveSettings(),gppScanScheduleErrorRedraw()}),h(),o.appendChild(a),e.appendChild(o)}const GPP_PALETTE_STYLE_ID="gpp-palette-style",GPP_PALETTE_SORT_OPTIONS=[{value:"default",text:"Sort: Most used (default)"},{value:"leastUsed",text:"Sort: Least used"},{value:"mostRemaining",text:"Sort: Most remaining"},{value:"leastRemaining",text:"Sort: Least remaining"},{value:"mostPct",text:"Sort: Most % remaining"},{value:"leastPct",text:"Sort: Least % remaining"},{value:"byColor",text:"Sort: Color"},{value:"byColorRev",text:"Sort: Color reversed"}],GPP_PALETTE_PROGRESS_SORT_VALUES=new Set(["mostRemaining","leastRemaining","mostPct","leastPct"]),GPP_PALETTE_FILTER_OPTIONS=[{value:"hideUnmatched",text:"Show search results only"},{value:"hideCompleted",text:"Hide completed colors"},{value:"hideInProgress",text:"Hide in-progress colors"},{value:"hideUnstarted",text:"Hide unstarted colors"},{value:"ownedOnly",text:"Owned colors only"},{value:"countRange",text:"Filter within pixel count…"}];function gppInjectPaletteStyle(){let e=document.getElementById(GPP_PALETTE_STYLE_ID);e||(e=document.createElement("style"),e.id=GPP_PALETTE_STYLE_ID,document.head.appendChild(e)),e.textContent=`\n            .gpp-palette-empty { font-size: 12px; color: ${t2("#64748b","#a6adc8")}; padding: 6px 2px; }\n            .gpp-palette-panel { display: flex; flex-direction: column; gap: 7px; margin: 8px 0; }\n            .gpp-gnc-group {\n                padding: 6px 0; border-bottom: 1px solid ${t2("#e5e7eb","#313244")};\n            }\n            .gpp-gnc-group:last-child { border-bottom: none; }\n            .gpp-gnc-heading {\n                display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;\n                color: ${t2("#111827","#f5f5f5")}; margin-bottom: 4px;\n            }\n            .gpp-gnc-heading .gpp-gnc-meta { font-weight: 400; color: ${t2("#64748b","#a6adc8")}; }\n            .gpp-gnc-members { display: flex; flex-direction: column; gap: 2px; padding-left: 4px; }\n            .gpp-gnc-member {\n                display: flex; align-items: center; gap: 6px; font-size: 11px;\n                color: ${t2("#1f2937","#e2e2f5")};\n            }\n            .gpp-gnc-member .gpp-gnc-kept { font-weight: 600; color: ${t2("#16a34a","#a6e3a1")}; }\n            .gpp-gnc-swatch {\n                display: inline-block; width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0;\n                border: 1px solid ${t2("rgba(0,0,0,.28)","rgba(255,255,255,.28)")};\n            }\n            .gpp-gnc-hex { font-family: ui-monospace, Menlo, Consolas, monospace; }\n            #gpp-palette-tooltip {\n                position: fixed; z-index: 10070; pointer-events: none; display: none;\n                padding: 6px 9px; border-radius: 7px; font-size: 12px; line-height: 1.4;\n                background: ${t2("#ffffff","#1e1e2e")};\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                box-shadow: 0 8px 20px ${t2("rgba(15,23,42,.28)","rgba(0,0,0,.6)")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            #gpp-palette-tooltip .gpp-palette-tooltip-hex {\n                font-family: ui-monospace, Menlo, Consolas, monospace; font-weight: 700;\n                display: flex; align-items: center; gap: 6px;\n            }\n            #gpp-palette-tooltip .gpp-palette-tooltip-swatch {\n                display: inline-block; width: 10px; height: 10px; border-radius: 3px;\n                border: 1px solid ${t2("rgba(0,0,0,.28)","rgba(255,255,255,.28)")};\n            }\n            #gpp-palette-tooltip .gpp-palette-tooltip-stats {\n                margin-top: 2px; color: ${t2("#64748b","#a6adc8")};\n            }\n            .gpp-palette-search-input {\n                width: 100%; box-sizing: border-box; padding: 5px 8px; border-radius: 6px;\n                border: 2px solid ${t2("#d1d5db","#45475a")};\n                background: ${t2("#ffffff","#11111b")}; color: ${t2("#111827","#f5f5f5")};\n                font-size: 12px;\n            }\n            .gpp-palette-search-input:focus { outline: none; border-color: ${t2("#3b82f6","#89b4fa")}; }\n            .gpp-palette-search-input::placeholder { color: ${t2("#94a3b8","#7f849c")}; }\n            .gpp-palette-bulk-row { display: flex; gap: 6px; }\n            .gpp-palette-bulk-row button,\n            .gpp-palette-bulk-row .gpp-palette-filter-dropdown {\n                flex: 1 1 0; min-width: 0;\n            }\n            .gpp-palette-bulk-row button {\n                border: 2px solid ${t2("#d1d5db","#45475a")}; border-radius: 6px;\n                background: ${t2("#ffffff","#11111b")}; color: ${t2("#111827","#f5f5f5")};\n                font-size: 11px; font-weight: 600; cursor: pointer; padding: 4px 6px;\n            }\n            .gpp-palette-bulk-row button:hover { background: ${t2("#f3f4f6","#313244")}; }\n            /* Buy all colors/Get hex values and Sort/Filters both use this\n               exact 2-column CSS Grid (not flex:1 1 0) so their column\n               boundaries are pixel-identical regardless of content — a grid\n               track's minmax(0, 1fr) has no "shrink to content" ambiguity\n               the way a flex item's automatic minimum size can, which is\n               what caused these two rows to drift out of alignment before. */\n            .gpp-palette-2col-row {\n                display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6px;\n            }\n            .gpp-palette-2col-row button,\n            .gpp-palette-2col-row .gpp-palette-filter-dropdown,\n            .gpp-palette-2col-row .gpp-palette-sort-wrap {\n                width: 100%; box-sizing: border-box; min-width: 0;\n            }\n            .gpp-palette-filter-dropdown { position: relative; }\n            .gpp-palette-filter-button,\n            .gpp-palette-sort-select {\n                width: 100%; box-sizing: border-box; min-height: 28px;\n                border: 2px solid ${t2("#d1d5db","#45475a")}; border-radius: 6px;\n                background: ${t2("#ffffff","#11111b")}; color: ${t2("#111827","#f5f5f5")};\n                font-size: 11px; cursor: pointer;\n                text-align: center; text-align-last: center;\n            }\n            .gpp-palette-filter-button {\n                display: flex; align-items: center; justify-content: center;\n                gap: 6px; padding: 3px 8px;\n            }\n            .gpp-palette-filter-menu {\n                display: none; position: absolute; top: calc(100% + 4px); left: 0; z-index: 20;\n                min-width: 204px; padding: 6px; border-radius: 8px;\n                border: 1px solid ${t2("#e5e7eb","#313244")};\n                background: ${t2("#ffffff","#181825")};\n                box-shadow: 0 8px 24px rgba(0,0,0,.28);\n            }\n            .gpp-palette-filter-menu.gpp-open { display: flex; flex-direction: column; gap: 2px; }\n            .gpp-palette-filter-option {\n                display: flex; align-items: center; gap: 6px; padding: 3px 4px; border-radius: 5px;\n                font-size: 12px; cursor: pointer; user-select: none;\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-palette-filter-option:hover { background: ${t2("#f3f4f6","#313244")}; }\n            .gpp-palette-filter-option input { width: 13px; height: 13px; cursor: pointer; }\n            .gpp-palette-filter-count {\n                display: flex; align-items: center; gap: 6px; flex-wrap: wrap;\n                padding: 3px 4px 4px 22px; font-size: 12px; color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-palette-count-input {\n                width: 58px; box-sizing: border-box; padding: 2px 5px; font-size: 11px;\n                border-radius: 5px; border: 2px solid ${t2("#d1d5db","#45475a")};\n                background: ${t2("#ffffff","#11111b")}; color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-palette-sort-wrap { flex: 1 1 0; min-width: 0; }\n            .gpp-palette-grid {\n                display: grid; grid-template-columns: repeat(auto-fill, minmax(26px, 1fr));\n                /* Explicit row floor matching the column formula — Firefox\n                   (unlike Chrome) can fail to derive a correct implicit row\n                   height from aspect-ratio alone on grid items once the\n                   container gets narrow enough to reflow the column count,\n                   collapsing rows and stacking swatches on top of each\n                   other. This gives it a real number to size rows from\n                   instead of depending on that computation. */\n                grid-auto-rows: minmax(26px, 1fr);\n                gap: 3px; max-height: 260px; overflow-y: auto; padding: 2px;\n                scrollbar-gutter: stable;\n            }\n            /* View Settings > Global > "Palette view" — list mode. Space-\n               efficient rectangular rows instead of square tiles; same\n               sort/filter pipeline (performFilterSort), just a different\n               per-entry DOM shape (see gppPaletteApplyListLayout). Overrides\n               the grid's own display:grid/grid-template-columns above. */\n            .gpp-palette-grid.gpp-palette-list-mode {\n                display: flex; flex-direction: column;\n            }\n            .gpp-swatch.gpp-swatch-list {\n                aspect-ratio: auto; min-height: 26px; width: 100%;\n                flex-direction: row; align-items: center; justify-content: flex-start;\n                gap: 7px; padding: 3px 8px; border-radius: 6px;\n                background: ${t2("#ffffff","#181825")};\n            }\n            .gpp-swatch.gpp-swatch-list:hover { transform: none; background: ${t2("#f3f4f6","#232336")}; }\n            .gpp-palette-list-chip {\n                width: 16px; height: 16px; border-radius: 4px; flex-shrink: 0;\n                border: 1px solid ${t2("rgba(0,0,0,.28)","rgba(255,255,255,.28)")};\n            }\n            .gpp-palette-list-hex {\n                font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11px; flex-shrink: 0;\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-palette-list-progress-text {\n                font-size: 10px; margin-left: auto; flex-shrink: 0;\n                color: ${t2("#64748b","#a6adc8")};\n            }\n            .gpp-palette-list-bar-outer {\n                width: 46px; height: 5px; border-radius: 3px; overflow: hidden; flex-shrink: 0;\n                display: block; background: ${t2("#e5e7eb","#313244")};\n            }\n            .gpp-palette-list-bar-fill { display: block; height: 100%; }\n            .gpp-swatch {\n                position: relative; aspect-ratio: 1 / 1; min-height: 15px; border-radius: 4px;\n                border: 1px solid ${t2("rgba(0,0,0,.28)","rgba(255,255,255,.28)")};\n                cursor: pointer; display: flex; align-items: center; justify-content: center;\n                padding: 0; transition: transform .08s ease;\n            }\n            .gpp-swatch:hover { transform: scale(1.15); z-index: 2; }\n            /* Grayscale/opacity dimming is gated behind the grid's own\n               .gpp-palette-gray-disabled modifier class (toggled in\n               performFilterSort from gppSettings.grayDisabledSwatches — a\n               View Settings > Global checkbox, on by default) — the\n               diagonal slash below is NOT gated by it and always applies\n               regardless, per explicit product decision: "gray" is an\n               optional extra emphasis on top of the slash, not a\n               replacement for it. */\n            .gpp-palette-gray-disabled .gpp-swatch.gpp-swatch-off { filter: grayscale(.7) opacity(.4); }\n            /* Diagonal slash across the whole tile — the merged progress/\n               enabled indicator alone wasn't visually distinct enough from\n               "enabled but low progress" at a glance (explicit product\n               decision); this is on top of the grayscale/opacity above when\n               that's also on, not a replacement for it. */\n            .gpp-swatch.gpp-swatch-off::after {\n                content: ''; position: absolute; inset: 0; pointer-events: none;\n                border-radius: inherit;\n                background: linear-gradient(to top right,\n                    transparent calc(50% - 1px), rgba(50,50,50,.75) calc(50% - 1px),\n                    rgba(50,50,50,.75) calc(50% + 1px), transparent calc(50% + 1px));\n            }\n            /* Single top-right indicator — merges the old separate on/off dot\n               and completion-progress badge into one (per explicit product\n               decision). pointer-events:none so it never intercepts the\n               swatch's own hover/click/drag handling. The off-state rule\n               below layers extra grayscale/opacity on top of the whole-button\n               graying above, so the SAME dot communicates both progress and\n               enabled/disabled. */\n            .gpp-swatch-progress {\n                position: absolute; top: 3px; right: 3px; width: 7px; height: 7px;\n                border-radius: 50%; pointer-events: none; box-sizing: border-box;\n                display: flex; align-items: center; justify-content: center;\n                font-size: 6px; line-height: 1; font-weight: 900; color: #16a34a;\n                box-shadow: 0 0 0 1px rgba(0,0,0,.55);\n            }\n            .gpp-swatch-progress-complete {\n                top: 0; right: 0; width: 100%; height: 100%;\n                background-color: transparent; box-shadow: none;\n                /* Two overlapping strokes of the same path: a wider black\n                   one drawn first, then the theme green on top narrower —\n                   leaves a thin black outline visible on both edges so the\n                   checkmark stays legible on bright/light swatch colors\n                   (explicit product request, after the earlier white\n                   drop-shadow glow was removed). */\n                background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 13l5 5L20 6' fill='none' stroke='black' stroke-width='5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M4 13l5 5L20 6' fill='none' stroke='${t2("%2316a34a","%23a6e3a1")}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");\n                background-repeat: no-repeat; background-position: center; background-size: 65% 65%;\n            }\n            .gpp-swatch-progress-unstarted { background: transparent; border: 1.5px solid #000; }\n            .gpp-swatch-progress-inprogress { border: 1px solid rgba(0,0,0,.4); }\n            .gpp-palette-gray-disabled .gpp-swatch.gpp-swatch-off .gpp-swatch-progress { filter: grayscale(1) opacity(.6); }\n            /* Search-match glow — same pulse timing/box-shadow values as\n               ghost-palette-search.js's .color-search-glow / pulse-glow, plus an\n               added static white+black double ring so the gold glow itself\n               stays visible no matter the swatch's own hue. */\n            .gpp-swatch.gpp-palette-glow {\n                animation: gpp-palette-pulse-glow 1.5s ease-in-out infinite;\n                box-shadow: 0 0 0 2px rgba(255,255,255,.95), 0 0 0 4px rgba(0,0,0,.85), 0 0 8px 2px rgba(255,215,0,.8);\n            }\n            @keyframes gpp-palette-pulse-glow {\n                0%, 100% { box-shadow: 0 0 0 2px rgba(255,255,255,.95), 0 0 0 4px rgba(0,0,0,.85), 0 0 8px 2px rgba(255,215,0,.8); }\n                50% { box-shadow: 0 0 0 2px rgba(255,255,255,.95), 0 0 0 4px rgba(0,0,0,.85), 0 0 12px 3px rgba(255,215,0,1); }\n            }\n        `}function gppPaletteBuildColourLookup(e){const t=new Map;return e.scanSummary&&e.scanSummary.perColour.forEach(e=>t.set(e.index,e)),t}function gppPaletteStats(e,t,n){const o=e.counts[t]||0,r=e.scanSummary,a=n?n.get(t):null,i=r&&a?a.correct:0,l=r?Math.max(0,o-i):0;return{total:o,completed:i,remaining:l,remainingPercent:o>0?l/o*100:0}}function gppPaletteProgressColor(e){const t=Math.max(0,Math.min(1,e)),n=[34,197,94],o=[220,38,38].map((e,o)=>Math.round(e+(n[o]-e)*t));return`rgb(${o[0]}, ${o[1]}, ${o[2]})`}function gppApplySelectedColorToFocusedTemplate(e){if(void 0===gppState||"string"!=typeof e||!e)return!1;const t=gppState.getFocusedTemplate();if(!t||!t.palette||!t.palette.length)return!1;const n=(e.length>=7?e.slice(0,7):e).toUpperCase(),o=gppCreateCore();let r=!1;for(let e=0;e<t.palette.length;e++){const a=o.packedToHex(t.palette[e])===n;o.maskHas(t.mask,e)!==a&&(o.maskSet(t.mask,e,a),r=!0)}return r&&(gppState.persistTemplateState(t).catch(e=>{console.error("[GeoPixelcons++] Ghost++ palette: failed to persist color-sync mask change.",e)}),"function"==typeof gppRendererSchedule&&gppRendererSchedule(),"function"==typeof gppRequestUiRefresh&&gppRequestUiRefresh()),!0}function gppPaletteApplyListLayout(e,t,n,o){const r=document.createElement("span");r.className="gpp-palette-list-chip",r.style.backgroundColor=t,r.setAttribute("aria-hidden","true");const a=document.createElement("span");a.className="gpp-palette-list-hex",a.textContent=t;const i=document.createElement("span");i.className="gpp-palette-list-progress-text",i.textContent=o?`${n.completed.toLocaleString()}/${n.total.toLocaleString()}`:`${n.total.toLocaleString()} px`;const l=document.createElement("span");if(l.className="gpp-palette-list-bar-outer",o&&n.total>0){const e=Math.max(0,Math.min(1,n.completed/n.total)),t=document.createElement("span");t.className="gpp-palette-list-bar-fill",t.style.width=Math.round(100*e)+"%",t.style.background=gppPaletteProgressColor(e),l.appendChild(t)}e.append(r,a,i,l)}let gppPaletteTooltipEl=null;function gppPaletteEnsureTooltipEl(){if(gppPaletteTooltipEl&&document.body.contains(gppPaletteTooltipEl))return gppPaletteTooltipEl;const e=document.createElement("div");return e.id="gpp-palette-tooltip",document.body.appendChild(e),gppPaletteTooltipEl=e,e}function gppPaletteShowTooltip(e,t,n,o){const r=gppPaletteEnsureTooltipEl(),a=document.createElement("div");a.className="gpp-palette-tooltip-hex";const i=document.createElement("span");i.className="gpp-palette-tooltip-swatch",i.style.backgroundColor=t,a.append(i,document.createTextNode(t));const l=document.createElement("div");l.className="gpp-palette-tooltip-stats",l.textContent=o?`${n.completed.toLocaleString()} / ${n.total.toLocaleString()} placed`:`${n.total.toLocaleString()} px`,r.innerHTML="",r.append(a,l),r.style.display="block",gppPaletteMoveTooltip(e)}function gppPaletteMoveTooltip(e){const t=gppPaletteTooltipEl;if(!t||"none"===t.style.display)return;let n=e.clientX+14,o=e.clientY+14;const r=t.getBoundingClientRect();n+r.width>window.innerWidth&&(n=e.clientX-r.width-14),o+r.height>window.innerHeight&&(o=e.clientY-r.height-14),t.style.left=Math.max(4,n)+"px",t.style.top=Math.max(4,o)+"px"}function gppPaletteHideTooltip(){gppPaletteTooltipEl&&(gppPaletteTooltipEl.style.display="none")}const gppPaletteControllers=new WeakMap;function gppRenderPalette(e,t,n){if(!e)return;gppInjectPaletteStyle();const o=t?t.id:null;let r=gppPaletteControllers.get(e);r&&r.templateKey===o||(r=gppCreatePaletteController(e),r.templateKey=o,gppPaletteControllers.set(e,r)),r.update(t,n)}function gppCreatePaletteController(e){const t=gppCreateCore(),n=e.querySelector("details.gpp-collapsible"),o=!n||n.open,r=e.querySelector("#gpp-palette-gnc-details"),a=!!r&&r.open;e.innerHTML="";const i={template:null,onChange:null,templateKey:void 0},l=document.createElement("details");l.className="gpp-collapsible",l.open=o;const s=document.createElement("summary");s.textContent="Template Colors",l.appendChild(s);const c=document.createElement("div");c.className="gpp-body",l.appendChild(c),e.appendChild(l);const d=document.createElement("details");d.id="gpp-palette-gnc-details",d.className="gpp-collapsible",d.open=a,d.style.display="none";const p=document.createElement("summary");p.textContent="Group Noise Changes",d.appendChild(p);const g=document.createElement("div");g.className="gpp-body",d.appendChild(g),e.appendChild(d);const u=document.createElement("div");u.className="gpp-palette-empty",c.appendChild(u);const m=document.createElement("div");m.className="gpp-palette-panel",m.style.display="none",c.appendChild(m);const h=document.createElement("input");h.type="text",h.className="gpp-palette-search-input",h.placeholder="Search hex (comma/space separated for multiple)",m.appendChild(h);const f=document.createElement("div");f.className="gpp-palette-bulk-row";const b=document.createElement("button");b.type="button",b.textContent="Enable all",b.title="Enable every color";const y=document.createElement("button");y.type="button",y.textContent="Disable all",y.title="Disable every color";const x=document.createElement("div");x.className="gpp-palette-bulk-row";const v=document.createElement("button");v.type="button",v.textContent="Enable owned",v.title="Enable only colors you own";const w=document.createElement("button");w.type="button",w.textContent="Enable filtered",w.title="Enable only colors currently matching the search box / filter checkboxes below, and disable the rest";const k=document.createElement("div");k.className="gpp-palette-bulk-row";const E=document.createElement("button");E.type="button",E.textContent="Match palette",E.title="Enable only colors currently active in your game palette";const C=document.createElement("button");C.type="button",C.textContent="Set palette",C.title="Set your in-game active palette to exactly this template's enabled colors (same as the native ghost tool's own \"Set Palette\")",C.addEventListener("click",()=>{const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;"function"==typeof e.setGhostColorsAsActivePalette&&e.setGhostColorsAsActivePalette()}),f.append(b,y),x.append(v,w),k.append(E,C),m.append(f,x,k);const S=document.createElement("div");S.className="gpp-palette-bulk-row gpp-palette-2col-row";const T=document.createElement("button");T.type="button",T.textContent="Buy all colors",T.title="Reveal the profile panel's Bulk Purchase Colors card, pre-filled with every color in this template you don't already own",S.appendChild(T);const P=document.createElement("div");P.className="gpp-palette-filter-dropdown";const L=document.createElement("button");L.type="button",L.className="gpp-palette-filter-button";const M=document.createElement("span");M.textContent="Get hex values";const I=document.createElement("span");I.textContent="▾",I.style.cssText="font-size:10px;opacity:.7;",L.append(M,I);const _=document.createElement("div");_.className="gpp-palette-filter-menu";[{value:"all",text:"All colors"},{value:"owned",text:"Owned colors only"},{value:"notOwned",text:"Not owned colors only"},{value:"enabled",text:"Enabled colors only"},{value:"enabledOwned",text:"Enabled + owned colors"},{value:"filtered",text:"Filtered colors only"},{value:"filteredOwned",text:"Filtered + owned colors only"}].forEach(({value:e,text:n})=>{const o=document.createElement("div");o.className="gpp-palette-filter-option",o.textContent=n,o.addEventListener("click",()=>{_.classList.remove("gpp-open"),function(e){const n=i.template;if(!n)return;const o=new Set(gppReadGamePalette().map(e=>String(e.hex).toUpperCase())),r=new Set(J.visible||[]),a=[];for(let i=0;i<n.palette.length;i++){const l=t.packedToHex(n.palette[i]),s=o.has(l),c=t.maskHas(n.mask,i),d=r.has(i);let p;switch(e){case"all":p=!0;break;case"owned":p=s;break;case"notOwned":p=!s;break;case"enabled":p=c;break;case"enabledOwned":p=c&&s;break;case"filtered":p=d;break;case"filteredOwned":p=d&&s;break;default:p=!1}p&&a.push(l)}const l=a.join(", "),s=()=>{M.textContent=a.length?`Copied ${a.length}!`:"Nothing to copy",setTimeout(()=>{M.textContent="Get hex values"},1200)};navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(l).then(s).catch(()=>alert(l||"No matching colors.")):alert(l||"No matching colors.")}(e)}),_.appendChild(o)}),L.addEventListener("click",e=>{e.stopPropagation(),_.classList.toggle("gpp-open")}),_.addEventListener("click",e=>e.stopPropagation()),document.addEventListener("click",()=>_.classList.remove("gpp-open")),P.append(L,_),S.appendChild(P),m.appendChild(S);const G=document.createElement("div");G.className="gpp-palette-controls-row gpp-palette-2col-row";const R=document.createElement("div");R.className="gpp-palette-filter-dropdown";const N=document.createElement("button");N.type="button",N.className="gpp-palette-filter-button";const A=document.createElement("span");A.textContent="Filters";const z=document.createElement("span");z.textContent="▾",z.style.cssText="font-size:10px;opacity:.7;",N.append(A,z);const B=document.createElement("div");B.className="gpp-palette-filter-menu";const O=[];let D=null,j=null;GPP_PALETTE_FILTER_OPTIONS.forEach(({value:e,text:t})=>{const n=document.createElement("label");n.className="gpp-palette-filter-option";const o=document.createElement("input");o.type="checkbox",o.value=e,o.addEventListener("change",()=>{q(),ae()}),O.push({input:o,label:n,value:e});const r=document.createElement("span");r.textContent=t,n.append(o,r),B.appendChild(n)});const H=document.createElement("div");H.className="gpp-palette-filter-count",H.style.display="none",D=document.createElement("input"),D.type="number",D.min="0",D.placeholder="min",D.className="gpp-palette-count-input",j=document.createElement("input"),j.type="number",j.min="0",j.placeholder="max",j.className="gpp-palette-count-input";const F=document.createElement("span");F.textContent="–",F.style.opacity=".6",[D,j].forEach(e=>e.addEventListener("input",()=>ae())),H.append(D,F,j),B.appendChild(H);const X=O.find(e=>"countRange"===e.value);function q(){const e=O.filter(e=>e.input.checked).length;A.textContent=e?`Filters (${e})`:"Filters"}X&&X.input.addEventListener("change",()=>{H.style.display=X.input.checked?"":"none",X.input.checked||(D.value="",j.value="")}),N.addEventListener("click",e=>{e.stopPropagation(),B.classList.toggle("gpp-open")}),B.addEventListener("click",e=>e.stopPropagation()),document.addEventListener("click",()=>B.classList.remove("gpp-open")),R.append(N,B);const U=document.createElement("div");U.className="gpp-palette-sort-wrap";const W=document.createElement("select");W.className="gpp-palette-sort-select",W.title="Scroll while hovering to change sort order",GPP_PALETTE_SORT_OPTIONS.forEach(({value:e,text:t})=>{const n=document.createElement("option");n.value=e,n.textContent=t,W.appendChild(n)}),W.addEventListener("change",()=>ae()),W.addEventListener("wheel",e=>{e.preventDefault();const t=e.deltaY>0?1:-1;let n=W.selectedIndex+t;for(;n>=0&&n<W.options.length&&W.options[n].disabled;)n+=t;n=Math.min(Math.max(n,0),W.options.length-1),n!==W.selectedIndex&&(W.selectedIndex=n,ae())},{passive:!1}),U.appendChild(W),G.append(U,R),m.appendChild(G);const Y=document.createElement("div");Y.className="gpp-palette-grid",m.appendChild(Y);const V=200;let J={visible:[],visibleGroups:null,matching:null,colourLookup:null,shownCount:0};function $(){const{visible:e,visibleGroups:t,matching:n,colourLookup:o}=J,r=t||e,a=t?i.template.groupNoiseData:null;let l=J.shownCount;for(;;){const e=Math.min(r.length,l+V);for(let s=l;s<e;s++){const e=r[s];Y.appendChild(t?le(i.template,e,a,n,o):ie(i.template,e,n.has(e),o))}if(J.shownCount=e,e===l||J.shownCount>=r.length||Y.scrollHeight>Y.clientHeight)break;l=e}}Y.addEventListener("scroll",()=>{const e=(J.visibleGroups||J.visible).length;J.shownCount>=e||Y.scrollTop+Y.clientHeight>=Y.scrollHeight-400&&$()});let Z=null,K=!1,Q=!1,ee=null;function te(e,t,n){e.classList.toggle("gpp-swatch-off",!n),e.setAttribute("aria-pressed",String(n)),e.setAttribute("aria-label",`${n?"Hide":"Show"} ${t}`);const o=i.template;o&&gppState.persistTemplateState(o).catch(e=>{console.error("[GeoPixelcons++] Ghost++ palette: failed to persist template state",e)}),"function"==typeof gppRendererSchedule&&gppRendererSchedule(),"function"==typeof i.onChange&&i.onChange()}function ne(e){if(!Z||!e)return;const n=Number(e.dataset.colorIndex);if(Number.isNaN(n)||Z.visited.has(n))return;Z.visited.add(n);const o=i.template;if(!o)return;const r=0===Z.button,a=e.dataset.groupMembers?e.dataset.groupMembers.split(",").map(Number):[n];a.every(e=>t.maskHas(o.mask,e)===r)||(a.forEach(e=>t.maskSet(o.mask,e,r)),te(e,t.packedToHex(o.palette[n]),r))}function oe(e){gppState.persistTemplateState(e).catch(e=>{console.error("[GeoPixelcons++] Ghost++ palette: failed to persist template state",e)}),"function"==typeof gppRendererSchedule&&gppRendererSchedule(),ae(),"function"==typeof i.onChange&&i.onChange()}function re(e){const n=i.template;if(!n)return;const o=gppReadGamePalette(),r=new Set;o.forEach(t=>{!t||e&&!t.active||t.hex&&r.add(String(t.hex).toUpperCase())});const a=new Uint32Array(Math.ceil(n.palette.length/32));for(let e=0;e<n.palette.length;e++)r.has(t.packedToHex(n.palette[e]))&&t.maskSet(a,e,!0);n.mask=a,oe(n)}function ae(){const e=i.template;if(!e)return;!function(){const e=i.template,t=!(!e||!e.scanSummary);Array.from(W.options).forEach(e=>{const n=GPP_PALETTE_PROGRESS_SORT_VALUES.has(e.value);e.hidden=n&&!t,e.disabled=n&&!t}),!t&&GPP_PALETTE_PROGRESS_SORT_VALUES.has(W.value)&&(W.value="default"),q()}(),Y.classList.toggle("gpp-palette-gray-disabled",!1!==gppSettings.grayDisabledSwatches),Y.classList.toggle("gpp-palette-list-mode","list"===gppSettings.paletteViewMode);const n=h.value.trim().split(/[\s,]+/).map(e=>e.toUpperCase()).filter(Boolean),o=new Set(O.filter(e=>e.input.checked).map(e=>e.value)),r=o.has("hideUnmatched"),a=o.has("hideCompleted"),l=o.has("hideInProgress"),s=o.has("hideUnstarted"),c=o.has("ownedOnly"),p=o.has("countRange"),u=p&&""!==D.value?parseInt(D.value,10):NaN,m=p&&""!==j.value?parseInt(j.value,10):NaN,f=!isNaN(u),b=!isNaN(m);let y=null;c&&(y=new Set,gppReadGamePalette().forEach(e=>{e&&e.hex&&y.add(String(e.hex).toUpperCase())}));const x=e.palette.length,v=new Set;if(n.length)for(let o=0;o<x;o++){const r=t.packedToHex(e.palette[o]);n.some(e=>r.includes(e))&&v.add(o)}const w=gppPaletteBuildColourLookup(e),k=[];for(let o=0;o<x;o++){const i=gppPaletteStats(e,o,w),d=n.length>0&&!v.has(o),p=i.total>0&&i.completed>=i.total,g=i.total>0&&i.completed>0&&i.completed<i.total,h=i.total>0&&0===i.completed,x=t.packedToHex(e.palette[o]),E=c&&y&&!y.has(x),C=(f||b)&&(f&&i.total<u||b&&i.total>m);r&&d||a&&p||l&&g||s&&h||E||C||k.push(o)}const E=n.length>0&&v.size>0,C=W.value;k.sort((n,o)=>{if(E){const e=v.has(n);if(e!==v.has(o))return e?-1:1}const r=gppPaletteStats(e,n,w),a=gppPaletteStats(e,o,w),i=n-o;switch(C){case"default":return a.total-r.total||i;case"leastUsed":return r.total-a.total||i;case"mostRemaining":return a.remaining-r.remaining||i;case"leastRemaining":return r.remaining-a.remaining||i;case"mostPct":return a.remainingPercent-r.remainingPercent||i;case"leastPct":return r.remainingPercent-a.remainingPercent||i;case"byColor":{const r=t.packedToHex(e.palette[n]),a=t.packedToHex(e.palette[o]);return(r<a?-1:r>a?1:0)||i}case"byColorRev":{const r=t.packedToHex(e.palette[n]),a=t.packedToHex(e.palette[o]);return(r>a?-1:r<a?1:0)||i}default:return i}});let S=null;if(e.groupNoise){e.groupNoiseData||(e.groupNoiseData=t.groupPaletteColors(e.palette));const n=new Set;S=[];for(const t of k){const o=e.groupNoiseData.groupOfIndex[t];n.has(o)||(n.add(o),S.push(o))}}!function(e){const n=e.groupNoiseData,o=n?n.groups.filter(e=>e.memberIndices.length>1):[];e.groupNoise&&o.length?(d.style.display="",g.innerHTML="",o.sort((e,t)=>t.memberIndices.length-e.memberIndices.length),o.forEach(n=>{const o=t.packedToHex(e.palette[n.representativeIndex]),r=n.memberIndices.reduce((t,n)=>t+(e.counts[n]||0),0),a=document.createElement("div");a.className="gpp-gnc-group";const i=document.createElement("div");i.className="gpp-gnc-heading";const l=document.createElement("span");l.className="gpp-gnc-swatch",l.style.backgroundColor=o;const s=document.createElement("span");s.innerHTML=`<span class="gpp-gnc-hex">${o}</span> <span class="gpp-gnc-meta">(${n.memberIndices.length} colors merged, ${r.toLocaleString()} px total)</span>`,i.append(l,s),a.appendChild(i);const c=document.createElement("div");c.className="gpp-gnc-members",n.memberIndices.forEach(o=>{const r=t.packedToHex(e.palette[o]),a=e.counts[o]||0,i=o===n.representativeIndex,l=document.createElement("div");l.className="gpp-gnc-member";const s=document.createElement("span");s.className="gpp-gnc-swatch",s.style.backgroundColor=r;const d=document.createElement("span");d.innerHTML=`<span class="gpp-gnc-hex">${r}</span> — ${a.toLocaleString()} px`+(i?' <span class="gpp-gnc-kept">(kept)</span>':""),l.append(s,d),c.appendChild(l)}),a.appendChild(c),g.appendChild(a)})):d.style.display="none"}(e);const T=Y.scrollTop;Y.innerHTML="",J={visible:k,visibleGroups:S,matching:v,colourLookup:w,shownCount:0},$();const P=(S||k).length;for(;J.shownCount<P&&Y.scrollHeight-Y.clientHeight<T;)$();Y.scrollTop=T}function ie(e,n,o,r){const a=e.palette[n],l=t.packedToHex(a),s=t.maskHas(e.mask,n),c=gppPaletteStats(e,n,r),d="list"===gppSettings.paletteViewMode,p=document.createElement("button");p.type="button",p.className="gpp-swatch"+(s?"":" gpp-swatch-off")+(o?" gpp-palette-glow":"")+(d?" gpp-swatch-list":""),p.setAttribute("aria-pressed",String(s)),p.setAttribute("aria-label",`${s?"Hide":"Show"} ${l}`),p.dataset.colorIndex=String(n);const g=!!e.scanSummary;if(d)gppPaletteApplyListLayout(p,l,c,g);else if(p.style.backgroundColor=l,g&&c.total>0){const e=document.createElement("span");c.completed>=c.total?e.className="gpp-swatch-progress gpp-swatch-progress-complete":c.completed<=0?e.className="gpp-swatch-progress gpp-swatch-progress-unstarted":(e.className="gpp-swatch-progress gpp-swatch-progress-inprogress",e.style.background=gppPaletteProgressColor(c.completed/c.total)),e.setAttribute("aria-hidden","true"),p.appendChild(e)}return p.addEventListener("mouseenter",e=>gppPaletteShowTooltip(e,l,c,g)),p.addEventListener("mousemove",e=>gppPaletteMoveTooltip(e)),p.addEventListener("mouseleave",gppPaletteHideTooltip),p.addEventListener("click",()=>{if(K)return void(K=!1);const e=i.template;if(!e)return;const o=t.maskToggle(e.mask,n);te(p,l,o)}),p}function le(e,n,o,r,a){const l=o.groupByRepresentative.get(n).memberIndices,s=e.palette[n],c=t.packedToHex(s),d=l.every(n=>t.maskHas(e.mask,n)),p=l.some(e=>r.has(e));let g=0,u=0;l.forEach(t=>{const n=gppPaletteStats(e,t,a);g+=n.total,u+=n.completed});const m={total:g,completed:u,remaining:Math.max(0,g-u),remainingPercent:g>0?Math.max(0,g-u)/g*100:0},h="list"===gppSettings.paletteViewMode,f=document.createElement("button");f.type="button",f.className="gpp-swatch"+(d?"":" gpp-swatch-off")+(p?" gpp-palette-glow":"")+(h?" gpp-swatch-list":""),f.setAttribute("aria-pressed",String(d)),f.setAttribute("aria-label",`${d?"Hide":"Show"} ${c} (${l.length} grouped colors)`),f.dataset.colorIndex=String(n),f.dataset.groupMembers=l.join(",");const b=!!e.scanSummary;if(h)gppPaletteApplyListLayout(f,c,m,b);else if(f.style.backgroundColor=c,b&&m.total>0){const e=document.createElement("span");m.completed>=m.total?e.className="gpp-swatch-progress gpp-swatch-progress-complete":m.completed<=0?e.className="gpp-swatch-progress gpp-swatch-progress-unstarted":(e.className="gpp-swatch-progress gpp-swatch-progress-inprogress",e.style.background=gppPaletteProgressColor(m.completed/m.total)),e.setAttribute("aria-hidden","true"),f.appendChild(e)}return f.addEventListener("mouseenter",e=>gppPaletteShowTooltip(e,c,m,b)),f.addEventListener("mousemove",e=>gppPaletteMoveTooltip(e)),f.addEventListener("mouseleave",gppPaletteHideTooltip),f.addEventListener("click",()=>{if(K)return void(K=!1);const e=i.template;if(!e)return;const n=!l.every(n=>t.maskHas(e.mask,n));l.forEach(o=>t.maskSet(e.mask,o,n)),te(f,c,n)}),f}return Y.addEventListener("mousedown",e=>{if(0!==e.button&&2!==e.button)return;const t=e.target.closest&&e.target.closest(".gpp-swatch");t&&i.template&&(2===e.button&&(Q=!0,clearTimeout(ee),ee=setTimeout(()=>{Q=!1},2e3)),Z={button:e.button,originEl:t,visited:new Set})}),Y.addEventListener("mousemove",e=>{if(!Z)return;const t=e.target.closest&&e.target.closest(".gpp-swatch");t&&(0===Z.visited.size&&t!==Z.originEl&&(0===Z.button&&(K=!0),ne(Z.originEl)),ne(t))}),document.addEventListener("mouseup",()=>{Z=null}),document.addEventListener("contextmenu",e=>{Q&&(Q=!1,clearTimeout(ee),e.preventDefault())}),h.addEventListener("input",()=>ae()),b.addEventListener("click",()=>{const e=i.template;e&&(e.mask=t.makeFullMask(e.palette.length,e.counts),oe(e))}),y.addEventListener("click",()=>{const e=i.template;e&&(e.mask=new Uint32Array(Math.ceil(e.palette.length/32)),oe(e))}),E.addEventListener("click",()=>re(!0)),v.addEventListener("click",()=>re(!1)),w.addEventListener("click",()=>{const e=i.template;if(!e)return;const n=h.value.trim().length>0,o=J.matching||new Set,r=new Uint32Array(Math.ceil(e.palette.length/32));(J.visible||[]).forEach(e=>{n&&!o.has(e)||t.maskSet(r,e,!0)}),e.mask=r,oe(e)}),T.addEventListener("click",()=>{const e=i.template;if(!e)return;if("function"!=typeof gppBulkPurchaseOpenProfilePanel)return void alert("Bulk Purchase Colors is disabled in GeoPixelcons++ settings.");const n=new Set(gppReadGamePalette().map(e=>String(e.hex).toUpperCase())),o=new Set,r=[];for(let a=0;a<e.palette.length;a++){const i=t.packedToHex(e.palette[a]);n.has(i)||o.has(i)||(o.add(i),r.push(i))}r.length?gppBulkPurchaseOpenProfilePanel(r):alert("Every color in this template is already owned.")}),i.update=function(e,t){if(i.template=e||null,i.onChange="function"==typeof t?t:null,gppPaletteHideTooltip(),!i.template)return u.style.display="",m.style.display="none",void(d.style.display="none");u.style.display="none",m.style.display="",ae()},i}const GPP_LIB_STYLE_ID="gpp-library-style",GPP_LIB_MANAGE_ID="gpp-lib-manage-modal",GPP_LIB_HOVER_ID="gpp-lib-hover-preview",GPP_LIB_FULLVIEW_ID="gpp-lib-fullview-overlay",GPP_LIB_CURRENT_PT_ID="gpp-lib-current-pt",GPP_LIB_GRID_DETAILS_ID="gpp-lib-grid-collapsible",GPP_LIB_THUMB_SIZE=52,GPP_LIB_THUMB_RENDER_SIZE=256,GPP_LIB_PREVIEW_SIZE=220,gppLibraryThumbCache=new Map;let gppLibraryHoverEl=null,gppGridDragState={id:null},gppManageViewMode="grid";function gppLibraryInjectStyle(){let e=document.getElementById(GPP_LIB_STYLE_ID);e||(e=document.createElement("style"),e.id=GPP_LIB_STYLE_ID,document.head.appendChild(e)),e.textContent=`\n            .gpp-lib-toolbar {\n                display: flex; align-items: center; justify-content: space-between; gap: 8px;\n                padding-bottom: 8px; margin-bottom: 8px;\n                border-bottom: 1px solid ${t2("#d1d5db","#45475a")};\n            }\n            .gpp-lib-count { font-size: 11px; color: ${t2("#64748b","#a6adc8")}; }\n            .gpp-lib-current {\n                display: flex; flex-direction: column; align-items: center; gap: 6px;\n                padding-bottom: 10px; margin-bottom: 10px;\n                border-bottom: 1px solid ${t2("#d1d5db","#45475a")};\n            }\n            /* .gpp-lib-current's own border-bottom above already divides it\n               from the Templates grid — details.gpp-collapsible's generic\n               border-top would otherwise stack a second line right beneath\n               it with no gap, since this collapsible is its very next\n               sibling. */\n            #${GPP_LIB_GRID_DETAILS_ID} { border-top: none; }\n            .gpp-lib-current canvas {\n                display: block; max-width: 100%; max-height: 220px; width: auto; height: auto;\n                image-rendering: pixelated; border-radius: 6px;\n                background: ${t2("#f1f5f9","#292a3a")};\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n            }\n            .gpp-lib-current-canvas-wrap { position: relative; max-width: 100%; }\n            .gpp-lib-current-canvas-wrap canvas { cursor: zoom-in; }\n            /* .gpp-lib-current's align-items:center is meant for the\n               (narrower-than-full-width) canvas thumbnail above this, not\n               for the Position/Transform controls gpp-init.js mounts here —\n               those should span the full available width. Without this,\n               #gpp-lib-current-pt shrink-wraps to fit-content, and since a\n               flex item's default min-width:auto floors that at its content's\n               min-content size, it stays pinned near its widest row's natural\n               width even when the right panel is dragged much narrower —\n               pushing that row to overflow past both the container's own\n               edges instead of actually reflowing into the space available. */\n            #${GPP_LIB_CURRENT_PT_ID} { align-self: stretch; min-width: 0; }\n            .gpp-lib-current-unload {\n                position: absolute; top: 3px; right: 3px; width: 18px; height: 18px;\n                border-radius: 9999px; border: none; display: flex; align-items: center; justify-content: center;\n                font-size: 10px; line-height: 1; cursor: pointer; opacity: .65; transition: opacity .1s;\n                background: ${t2("rgba(255,255,255,.85)","rgba(30,30,46,.85)")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-current-unload:hover { opacity: 1; }\n            .gpp-lib-current-name {\n                font-size: 12px; font-weight: 600; text-align: center; max-width: 100%;\n                overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-editable-name {\n                cursor: text; border-radius: 4px; padding: 1px 4px; margin: -1px -4px;\n            }\n            .gpp-lib-editable-name:hover {\n                background: ${t2("rgba(37,99,235,.08)","rgba(137,180,250,.12)")};\n            }\n            .gpp-lib-rename-input {\n                font: inherit; width: 100%; box-sizing: border-box;\n                padding: 1px 3px; border-radius: 4px;\n                border: 1px solid ${t2("#2563eb","#89b4fa")};\n                background: ${t2("#ffffff","#11111b")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-btn {\n                font: inherit; font-size: 11px; cursor: pointer; border-radius: 6px;\n                padding: 4px 9px; border: 1px solid ${t2("#d1d5db","#45475a")};\n                background: ${t2("#ffffff","#313244")}; color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-btn:hover:not(:disabled) { background: ${t2("#f3f4f6","#45475a")}; }\n            .gpp-lib-btn:disabled { opacity: .45; cursor: not-allowed; }\n            .gpp-lib-btn-danger { color: ${t2("#dc2626","#f38ba8")}; }\n            .gpp-lib-empty {\n                font-size: 11px; color: ${t2("#64748b","#a6adc8")}; padding: 10px 2px;\n            }\n            .gpp-lib-grid {\n                display: grid; grid-template-columns: repeat(auto-fill, minmax(${GPP_LIB_THUMB_SIZE}px, 1fr));\n                /* Explicit row floor matching the column formula — see\n                   gpp-palette.js's identical .gpp-palette-grid fix for why:\n                   Firefox can fail to derive implicit row height from\n                   .gpp-lib-card's aspect-ratio (nested inside the\n                   .gpp-lib-cell flex wrapper) once the panel narrows enough\n                   to reflow the column count, collapsing cards toward zero\n                   height — which also swallows their click area and hides\n                   their canvas thumbnail, since both size off the\n                   collapsed card. */\n                grid-auto-rows: minmax(${GPP_LIB_THUMB_SIZE}px, 1fr);\n                gap: 10px 6px;\n            }\n            .gpp-lib-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }\n            .gpp-lib-card {\n                position: relative; aspect-ratio: 1 / 1; border-radius: 6px; overflow: hidden;\n                cursor: pointer; box-sizing: border-box;\n                background: ${t2("#f1f5f9","#292a3a")};\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                transition: box-shadow .1s, border-color .1s;\n            }\n            .gpp-lib-card:hover { border-color: ${t2("#2563eb","#89b4fa")}; }\n            .gpp-lib-card-focused {\n                border-color: ${t2("#2563eb","#89b4fa")};\n                box-shadow: 0 0 0 2px ${t2("rgba(37,99,235,.35)","rgba(137,180,250,.35)")};\n            }\n            /* Drag-reorder — analogous to .gpp-lib-row-dragging/-dragover\n               (Manage Templates modal) but scoped separately since these are\n               square grid cards, not list rows. */\n            .gpp-lib-card-dragging { opacity: .4; }\n            .gpp-lib-card-dragover { border-color: ${t2("#2563eb","#89b4fa")}; box-shadow: 0 0 0 2px ${t2("rgba(37,99,235,.35)","rgba(137,180,250,.35)")}; }\n            .gpp-lib-card canvas.gpp-lib-thumb-canvas {\n                display: block; width: 100%; height: 100%; image-rendering: pixelated;\n            }\n            .gpp-lib-arrow {\n                position: absolute; top: 3px; right: 3px; width: 17px; height: 17px;\n                border-radius: 9999px; border: none; display: flex; align-items: center; justify-content: center;\n                font-size: 9px; line-height: 1; cursor: pointer; opacity: .55; transition: opacity .1s;\n                background: ${t2("rgba(255,255,255,.85)","rgba(30,30,46,.85)")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-card:hover .gpp-lib-arrow { opacity: 1; }\n            .gpp-lib-vis-btn {\n                position: absolute; bottom: 3px; right: 3px; width: 17px; height: 17px;\n                border-radius: 9999px; border: none; display: flex; align-items: center; justify-content: center;\n                font-size: 9px; line-height: 1; cursor: pointer; opacity: .55; transition: opacity .1s;\n                background: ${t2("rgba(255,255,255,.85)","rgba(30,30,46,.85)")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-card:hover .gpp-lib-vis-btn { opacity: 1; }\n            #${GPP_LIB_HOVER_ID} {\n                position: fixed; z-index: 10060; pointer-events: none; display: none;\n                padding: 6px; border-radius: 8px;\n                background: ${t2("#ffffff","#1e1e2e")};\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                box-shadow: 0 8px 24px ${t2("rgba(15,23,42,.28)","rgba(0,0,0,.6)")};\n            }\n            #${GPP_LIB_HOVER_ID} canvas {\n                display: block; max-width: ${GPP_LIB_PREVIEW_SIZE}px; max-height: ${GPP_LIB_PREVIEW_SIZE}px; width: auto; height: auto;\n                image-rendering: pixelated; border-radius: 4px;\n                background: ${t2("#f1f5f9","#292a3a")};\n            }\n            .gpp-lib-hover-caption {\n                margin-top: 4px; font-size: 10px; text-align: center;\n                max-width: ${GPP_LIB_PREVIEW_SIZE}px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n                color: ${t2("#64748b","#a6adc8")};\n            }\n            .gpp-lib-fullview-overlay {\n                position: fixed; inset: 0; z-index: 10070; background: rgba(0,0,0,.55);\n                display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;\n                padding: 32px; box-sizing: border-box;\n            }\n            .gpp-lib-fullview-canvas {\n                display: block; max-width: 90vw; max-height: 82vh; width: auto; height: auto;\n                image-rendering: pixelated; border-radius: 6px;\n                box-shadow: 0 12px 32px rgba(0,0,0,.5);\n            }\n            .gpp-lib-fullview-caption {\n                font-size: 12px; text-align: center; max-width: 90vw;\n                overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n                color: ${t2("#64748b","#a6adc8")};\n            }\n            .gpp-lib-fullview-close {\n                position: absolute; top: 16px; right: 20px; width: 28px; height: 28px;\n                border-radius: 9999px; border: none; display: flex; align-items: center; justify-content: center;\n                font-size: 14px; cursor: pointer;\n                background: ${t2("rgba(255,255,255,.85)","rgba(30,30,46,.85)")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-fullview-close:hover { background: ${t2("#f3f4f6","#45475a")}; }\n            .gpp-lib-manage-overlay {\n                position: fixed; inset: 0; z-index: 10050; background: rgba(0,0,0,.55);\n                display: flex; align-items: center; justify-content: center;\n            }\n            .gpp-lib-manage-panel {\n                width: min(92vw, 560px); max-height: 82vh; display: flex; flex-direction: column; gap: 10px;\n                border-radius: 10px; padding: 14px; box-sizing: border-box;\n                background: ${t2("#ffffff","#1e1e2e")}; color: ${t2("#111827","#f5f5f5")};\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                box-shadow: 0 12px 32px rgba(0,0,0,.35);\n                font: 13px system-ui, sans-serif;\n            }\n            .gpp-lib-manage-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n            .gpp-lib-manage-title { font-weight: 600; font-size: 14px; }\n            .gpp-lib-manage-close { border: none; background: transparent; color: inherit; cursor: pointer; font-size: 15px; }\n            .gpp-lib-manage-toolbar {\n                display: flex; align-items: center; gap: 8px; padding: 6px 0;\n                border-top: 1px solid ${t2("#e5e7eb","#313244")}; border-bottom: 1px solid ${t2("#e5e7eb","#313244")};\n            }\n            .gpp-lib-manage-toolbar-spacer { flex: 1; }\n            .gpp-lib-manage-selectall { display: flex; align-items: center; gap: 6px; font-size: 12px; }\n            .gpp-lib-manage-export-progress { display: flex; flex-direction: column; gap: 4px; padding: 2px 0 4px; }\n            .gpp-lib-manage-export-progress-label {\n                font-size: 11px; color: ${t2("#64748b","#a6adc8")};\n                overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n            }\n            .gpp-lib-manage-export-progress-bar {\n                height: 6px; border-radius: 9999px; overflow: hidden;\n                background: ${t2("#e5e7eb","#313244")};\n            }\n            .gpp-lib-manage-export-progress-fill {\n                height: 100%; width: 0%; border-radius: 9999px;\n                background: ${t2("#2563eb","#89b4fa")};\n                transition: width .12s ease;\n            }\n            .gpp-lib-manage-list {\n                flex: 1; min-height: 120px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px;\n                scrollbar-gutter: stable;\n            }\n            .gpp-lib-manage-empty { font-size: 12px; color: ${t2("#64748b","#a6adc8")}; padding: 12px 4px; text-align: center; }\n            .gpp-lib-row {\n                display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 6px;\n                border: 1px solid transparent;\n            }\n            .gpp-lib-row:hover { background: ${t2("#f3f4f6","#292a3a")}; }\n            .gpp-lib-row-dragging { opacity: .4; }\n            .gpp-lib-row-dragover { border-color: ${t2("#2563eb","#89b4fa")}; }\n            .gpp-lib-row-handle { cursor: grab; user-select: none; color: ${t2("#94a3b8","#6c7086")}; font-size: 12px; flex-shrink: 0; }\n            .gpp-lib-row-thumb {\n                width: 22px; height: 22px; border-radius: 3px; flex-shrink: 0; image-rendering: pixelated;\n                background: ${t2("#f1f5f9","#292a3a")};\n            }\n            .gpp-lib-row-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\n            .gpp-lib-row-name { font-size: 12px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n            .gpp-lib-row-dims { font-size: 10px; color: ${t2("#64748b","#a6adc8")}; }\n            .gpp-lib-row-vis {\n                border: none; background: transparent; cursor: pointer; font-size: 13px; flex-shrink: 0;\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-row-goto {\n                border: none; background: transparent; cursor: pointer; font-size: 12px; flex-shrink: 0;\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-row-goto:disabled { opacity: .35; cursor: not-allowed; }\n            .gpp-lib-manage-header-right { display: flex; align-items: center; gap: 8px; }\n            .gpp-lib-manage-view-toggle {\n                display: flex; border-radius: 6px; overflow: hidden;\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n            }\n            .gpp-lib-manage-view-btn {\n                font: inherit; font-size: 12px; line-height: 1; cursor: pointer; border: none; padding: 4px 7px;\n                background: ${t2("#ffffff","#313244")}; color: ${t2("#64748b","#a6adc8")};\n            }\n            .gpp-lib-manage-view-btn:hover { background: ${t2("#f3f4f6","#45475a")}; }\n            .gpp-lib-manage-view-btn-active {\n                background: ${t2("#2563eb","#89b4fa")}; color: ${t2("#ffffff","#1e1e2e")};\n            }\n            /* Fixed-size cards (no 1fr stretch) — scroll, don't reflow, as\n               the column count changes; overrides .gpp-lib-manage-list's\n               flex column layout when this modifier class is also present. */\n            .gpp-lib-manage-list-grid {\n                display: grid; grid-template-columns: repeat(auto-fill, 92px); grid-auto-rows: min-content;\n                gap: 10px; align-content: start; justify-content: start;\n            }\n            .gpp-lib-manage-grid-card {\n                position: relative; width: 92px; box-sizing: border-box;\n                display: flex; flex-direction: column; gap: 3px; cursor: pointer;\n            }\n            .gpp-lib-manage-grid-card-dragging { opacity: .4; }\n            .gpp-lib-manage-grid-thumb-wrap {\n                position: relative; width: 92px; height: 92px; border-radius: 6px; overflow: hidden; box-sizing: border-box;\n                background: ${t2("#f1f5f9","#292a3a")};\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n                transition: box-shadow .1s, border-color .1s;\n            }\n            .gpp-lib-manage-grid-card:hover .gpp-lib-manage-grid-thumb-wrap { border-color: ${t2("#2563eb","#89b4fa")}; }\n            .gpp-lib-manage-grid-card-focused .gpp-lib-manage-grid-thumb-wrap {\n                border-color: ${t2("#2563eb","#89b4fa")};\n                box-shadow: 0 0 0 2px ${t2("rgba(37,99,235,.35)","rgba(137,180,250,.35)")};\n            }\n            .gpp-lib-manage-grid-card-dragover .gpp-lib-manage-grid-thumb-wrap {\n                border-color: ${t2("#2563eb","#89b4fa")};\n                box-shadow: 0 0 0 2px ${t2("rgba(37,99,235,.35)","rgba(137,180,250,.35)")};\n            }\n            .gpp-lib-manage-grid-card-selected .gpp-lib-manage-grid-thumb-wrap {\n                border-color: ${t2("#d97706","#f9a825")};\n                box-shadow: 0 0 0 2px ${t2("rgba(217,119,6,.35)","rgba(249,168,37,.35)")};\n            }\n            /* object-fit: contain (not width/height:100% stretch) — the\n               canvas now renders at the template's own true, possibly\n               non-square resolution (gppLibraryRenderFullCanvas), so it\n               must letterbox to fit this square box instead of distorting.\n               Slightly darkened by default, full brightness on hover —\n               per explicit product feedback, makes the overlaid corner\n               buttons (opaque at all times, see below) read clearly\n               against any thumbnail without needing their own opacity\n               dance, and gives a clear hover affordance for the whole card. */\n            .gpp-lib-manage-grid-thumb-wrap canvas {\n                display: block; width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated;\n                filter: brightness(0.72); transition: filter .1s;\n            }\n            .gpp-lib-manage-grid-card:hover .gpp-lib-manage-grid-thumb-wrap canvas { filter: brightness(1); }\n            .gpp-lib-manage-grid-name {\n                font-size: 10px; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            /* Always fully opaque (not translucent-until-hover) — per\n               explicit product feedback, these need to be readable at a\n               glance without hovering first; the thumbnail's own darken/\n               brighten-on-hover treatment above is what now carries the\n               hover affordance instead. */\n            .gpp-lib-manage-grid-sel, .gpp-lib-manage-grid-vis, .gpp-lib-manage-grid-goto {\n                position: absolute; width: 17px; height: 17px; border-radius: 9999px; border: none;\n                display: flex; align-items: center; justify-content: center; font-size: 9px; line-height: 1; cursor: pointer;\n                background: ${t2("rgba(255,255,255,.85)","rgba(30,30,46,.85)")};\n                color: ${t2("#111827","#f5f5f5")};\n            }\n            .gpp-lib-manage-grid-sel { top: 3px; left: 3px; }\n            .gpp-lib-manage-grid-vis { top: 3px; right: 3px; }\n            .gpp-lib-manage-grid-goto { bottom: 3px; left: 3px; }\n            .gpp-lib-manage-grid-sel-active { background: ${t2("#d97706","#f9a825")}; color: ${t2("#ffffff","#1e1e2e")}; opacity: 1; }\n        `}function gppLibraryRenderThumbCanvas(e,t){const n=document.createElement("canvas");n.className="gpp-lib-thumb-canvas",n.width=t,n.height=t;const o=e.width,r=e.height,a=e.indices,i=e.palette;if(!(o&&r&&a&&i&&i.length))return n;const l=gppCreateCore().emptyValue(e.indexType),s=Math.min(t/o,t/r),c=Math.max(1,Math.round(o*s)),d=Math.max(1,Math.round(r*s)),p=Math.floor((t-c)/2),g=Math.floor((t-d)/2),u=n.getContext("2d"),m=u.createImageData(c,d),h=m.data;for(let e=0;e<d;e++){const t=Math.min(r-1,Math.floor(e/s))*o,n=e*c;for(let e=0;e<c;e++){const r=a[t+Math.min(o-1,Math.floor(e/s))];if(r===l)continue;const c=i[r],d=4*(n+e);h[d]=c>>>16&255,h[d+1]=c>>>8&255,h[d+2]=255&c,h[d+3]=255}}return u.putImageData(m,p,g),n}function gppLibraryRenderFullCanvas(e){const t=document.createElement("canvas");t.className="gpp-lib-thumb-canvas";const n=e.width||1,o=e.height||1;t.width=n,t.height=o;const r=e.indices,a=e.palette;if(!(e.width&&e.height&&r&&a&&a.length))return t;const i=gppCreateCore().emptyValue(e.indexType),l=t.getContext("2d"),s=l.createImageData(n,o),c=s.data;for(let e=0;e<n*o;e++){const t=r[e];if(t===i)continue;const n=a[t],o=4*e;c[o]=n>>>16&255,c[o+1]=n>>>8&255,c[o+2]=255&n,c[o+3]=255}return l.putImageData(s,0,0),t}function gppLibraryEnsureThumb(e){let t=gppLibraryThumbCache.get(e.id);return(!t||t.indicesRef!==e.indices||t.paletteRef!==e.palette||t.width!==e.width||t.height!==e.height)&&(t={indicesRef:e.indices,paletteRef:e.palette,width:e.width,height:e.height,small:gppLibraryRenderThumbCanvas(e,GPP_LIB_THUMB_RENDER_SIZE)},gppLibraryThumbCache.set(e.id,t)),t}function gppLibraryPruneThumbCache(){if(!gppLibraryThumbCache.size)return;const e=new Set(gppState.templates.map(e=>e.id));for(const t of Array.from(gppLibraryThumbCache.keys()))e.has(t)||gppLibraryThumbCache.delete(t)}function gppLibraryEnsureHoverEl(){if(gppLibraryHoverEl&&document.body.contains(gppLibraryHoverEl))return gppLibraryHoverEl;const e=document.createElement("div");return e.id=GPP_LIB_HOVER_ID,document.body.appendChild(e),gppLibraryHoverEl=e,e}function gppLibraryShowHoverPreview(e,t){const n=gppLibraryEnsureHoverEl(),o=gppLibraryRenderFullCanvas(t);n.innerHTML="",n.appendChild(o);const r=document.createElement("div");r.className="gpp-lib-hover-caption",r.textContent=(t.name||"Untitled template")+"  "+t.width+"×"+t.height,n.appendChild(r),n.style.display="block",gppLibraryMoveHoverPreview(e)}function gppLibraryMoveHoverPreview(e){const t=gppLibraryHoverEl;if(!t||"none"===t.style.display)return;const n=t.getBoundingClientRect();let o=e.clientX+16,r=e.clientY+16;o+n.width>window.innerWidth&&(o=e.clientX-n.width-16),r+n.height>window.innerHeight&&(r=e.clientY-n.height-16),t.style.left=Math.max(4,o)+"px",t.style.top=Math.max(4,r)+"px"}function gppLibraryHideHoverPreview(){gppLibraryHoverEl&&(gppLibraryHoverEl.style.display="none")}function gppLibraryComputeTemplateCenterGrid(e){if(!e.position||!Number.isFinite(e.position.gridX)||!Number.isFinite(e.position.gridY))return null;const t=e.width||1,n=e.height||1;return{gridX:e.position.gridX+(t-1)/2,gridY:e.position.gridY-(n-1)/2}}function gppLibraryFlyToTemplate(e){const t=gppLibraryComputeTemplateCenterGrid(e);if(!t)return;const n=gppGetMap(),o=gppGetTurf();if(!n||!o||"function"!=typeof n.jumpTo)return;const r=gppReadGridConstants(),a=t.gridX*r.gridSize+r.offsetMetersX,i=t.gridY*r.gridSize+r.offsetMetersY;try{const e=o.toWgs84([a,i]);if(!e)return;const t="function"==typeof n.getZoom?n.getZoom():12.5;n.jumpTo({center:e,zoom:Math.max(t,12.5)})}catch(e){}}async function gppLibraryRenameTemplate(e,t){const n=(t||"").trim();n&&n!==e.name&&(e.name=n,await gppState.persistTemplateState(e))}function gppLibraryStartRename(e,t,n){if(e.querySelector("input"))return;const o=t.name||"Untitled template";e.textContent="",e.style.alignSelf="stretch";const r=document.createElement("input");r.type="text",r.className="gpp-lib-rename-input",r.value=o,r.maxLength=200,e.appendChild(r),r.focus(),r.select();let a=!1;function i(e){a||(a=!0,r.removeEventListener("blur",l),r.removeEventListener("keydown",s),e?gppLibraryRenameTemplate(t,r.value).then(n):n())}function l(){i(!0)}function s(e){e.stopPropagation(),"Enter"===e.key?(e.preventDefault(),i(!0)):"Escape"===e.key&&(e.preventDefault(),i(!1))}r.addEventListener("blur",l),r.addEventListener("keydown",s),r.addEventListener("click",e=>e.stopPropagation()),r.addEventListener("mousedown",e=>e.stopPropagation())}function gppLibraryOpenFullPreview(e){if(document.getElementById(GPP_LIB_FULLVIEW_ID))return;const t=document.createElement("div");t.id=GPP_LIB_FULLVIEW_ID,t.className="gpp-lib-fullview-overlay";const n=gppLibraryRenderFullCanvas(e);n.className="gpp-lib-fullview-canvas",t.appendChild(n);const o=document.createElement("div");o.className="gpp-lib-fullview-caption",o.textContent=(e.name||"Untitled template")+"  "+e.width+"×"+e.height,t.appendChild(o);const r=document.createElement("button");function a(){document.removeEventListener("keydown",i),t.remove()}function i(e){"Escape"===e.key&&a()}r.type="button",r.className="gpp-lib-fullview-close",r.textContent="✕",r.setAttribute("aria-label","Close preview"),t.appendChild(r),document.addEventListener("keydown",i),r.addEventListener("click",a),t.addEventListener("click",e=>{e.target===t&&a()}),document.body.appendChild(t)}function gppLibraryBuildCard(e,t,n){const o=document.createElement("div");o.className="gpp-lib-cell";const r=document.createElement("div");r.className="gpp-lib-card"+(e.id===t?" gpp-lib-card-focused":""),r.title=e.name||"Untitled template";const a=gppLibraryEnsureThumb(e);r.appendChild(a.small);if(!!gppLibraryComputeTemplateCenterGrid(e)){const t=document.createElement("button");t.type="button",t.className="gpp-lib-arrow",t.textContent="➤",t.title="Go to this template’s location",t.addEventListener("click",t=>{t.stopPropagation(),(async()=>{await gppState.focusTemplate(e.id),gppLibraryFlyToTemplate(e),n()})()}),r.appendChild(t)}const i=document.createElement("button");i.type="button",i.className="gpp-lib-vis-btn";const l=()=>{const t=e.opacity>0;i.textContent=t?"👁️":"🚫",i.title=t?"Visible — click to hide":"Hidden — click to show"};return l(),i.addEventListener("click",t=>{t.stopPropagation(),gppLibraryToggleVisibility(e).then(()=>{l(),n()})}),r.appendChild(i),r.addEventListener("click",()=>{e.id!==gppState.focusedTemplateId&&(async()=>{await gppState.focusTemplate(e.id),n()})()}),r.addEventListener("mouseenter",t=>gppLibraryShowHoverPreview(t,e)),r.addEventListener("mousemove",gppLibraryMoveHoverPreview),r.addEventListener("mouseleave",gppLibraryHideHoverPreview),r.draggable=!0,r.addEventListener("dragstart",t=>{gppGridDragState.id=e.id,t.dataTransfer.effectAllowed="move";try{t.dataTransfer.setData("text/plain",e.id)}catch(e){}gppLibraryHideHoverPreview(),r.classList.add("gpp-lib-card-dragging")}),r.addEventListener("dragend",()=>{gppGridDragState.id=null,r.classList.remove("gpp-lib-card-dragging"),r.classList.remove("gpp-lib-card-dragover")}),r.addEventListener("dragover",t=>{gppGridDragState.id&&gppGridDragState.id!==e.id&&(t.preventDefault(),t.dataTransfer.dropEffect="move",r.classList.add("gpp-lib-card-dragover"))}),r.addEventListener("dragleave",()=>r.classList.remove("gpp-lib-card-dragover")),r.addEventListener("drop",t=>{t.preventDefault(),r.classList.remove("gpp-lib-card-dragover");const o=gppGridDragState.id;gppGridDragState.id=null,o&&o!==e.id&&(async()=>{await gppLibraryReorderTemplates(o,e.id),n()})()}),o.appendChild(r),o}function gppRenderTemplateLibrary(e,t){if(!e)return;gppLibraryInjectStyle(),gppLibraryHideHoverPreview(),gppLibraryPruneThumbCache();const n=e.querySelector("#"+GPP_LIB_CURRENT_PT_ID+" details.gpp-collapsible"),o=!n||n.open,r=e.querySelector("#"+GPP_LIB_GRID_DETAILS_ID),a=!r||r.open;e.innerHTML="";const i=gppState.templates,l=document.createElement("div");l.className="gpp-lib-toolbar";const s=document.createElement("span");s.className="gpp-lib-count",s.textContent=i.length||gppState.runtimeReady?1===i.length?"1 template":i.length+" templates":"Loading…";const c=document.createElement("button");c.type="button",c.className="gpp-lib-btn",c.textContent="🗂️ Manage",c.title="Manage templates",c.addEventListener("click",()=>gppOpenManageTemplatesModal(t)),l.appendChild(s),l.appendChild(c),e.appendChild(l);const d=gppState.focusedTemplateId;let p=i.find(e=>e.id===d);if(p||(p=gppState.guildTemplates.find(e=>e.id===d)),!i.length&&!p){if(!gppState.runtimeReady){const t=document.createElement("div");t.className="gpp-lib-empty",t.textContent="Loading templates...",e.appendChild(t)}return}const g=document.createElement("div");if(g.className="gpp-lib-current",p){const e=document.createElement("div");e.className="gpp-lib-current-canvas-wrap";const n=gppLibraryRenderFullCanvas(p);n.title="Click for a full-screen preview",n.addEventListener("click",()=>gppLibraryOpenFullPreview(p)),e.appendChild(n);const o=document.createElement("button");o.type="button",o.className="gpp-lib-current-unload",o.textContent="✕",o.title=p.ephemeral?"Unload template":"Unload template (keeps it in your library)",o.setAttribute("aria-label","Unload template"),o.addEventListener("click",e=>{e.stopPropagation(),(async()=>{await gppState.focusTemplate(null),t()})()}),e.appendChild(o),g.appendChild(e);const r=document.createElement("div");r.className="gpp-lib-current-name gpp-lib-editable-name",r.textContent=p.name||"Untitled template",r.title="Click to rename",r.addEventListener("click",e=>{e.stopPropagation(),gppLibraryStartRename(r,p,t)}),g.appendChild(r)}const u=document.createElement("div");u.id=GPP_LIB_CURRENT_PT_ID;const m=document.createElement("details");if(m.className="gpp-collapsible",m.open=o,u.appendChild(m),g.appendChild(u),e.appendChild(g),i.length){const n=document.createElement("details");n.className="gpp-collapsible",n.id=GPP_LIB_GRID_DETAILS_ID,n.open=a;const o=document.createElement("summary");o.textContent="Templates";const r=document.createElement("div");r.className="gpp-body",n.appendChild(o),n.appendChild(r);const l=document.createElement("div");l.className="gpp-lib-grid",i.forEach(e=>l.appendChild(gppLibraryBuildCard(e,d,t))),r.appendChild(l),e.appendChild(n)}}async function gppLibraryReorderTemplates(e,t){const n=gppState.templates,o=n.findIndex(t=>t.id===e),r=n.findIndex(e=>e.id===t);if(-1===o||-1===r||o===r)return;const[a]=n.splice(o,1);n.splice(r,0,a),gppState.normalizeTemplateOrder(),await Promise.all(n.map(e=>gppState.persistTemplateState(e)))}function gppLibraryBuildManageRow(e,t){const n=document.createElement("div");n.className="gpp-lib-row",n.draggable=!0,n.addEventListener("dragstart",o=>{t.dragState.id=e.id,o.dataTransfer.effectAllowed="move";try{o.dataTransfer.setData("text/plain",e.id)}catch(e){}n.classList.add("gpp-lib-row-dragging")}),n.addEventListener("dragend",()=>{t.dragState.id=null,n.classList.remove("gpp-lib-row-dragging"),n.classList.remove("gpp-lib-row-dragover")}),n.addEventListener("dragover",o=>{t.dragState.id&&t.dragState.id!==e.id&&(o.preventDefault(),o.dataTransfer.dropEffect="move",n.classList.add("gpp-lib-row-dragover"))}),n.addEventListener("dragleave",()=>n.classList.remove("gpp-lib-row-dragover")),n.addEventListener("drop",o=>{o.preventDefault(),n.classList.remove("gpp-lib-row-dragover");const r=t.dragState.id;t.dragState.id=null,r&&r!==e.id&&(async()=>{await gppLibraryReorderTemplates(r,e.id),t.renderList(),t.onChange()})()});const o=document.createElement("span");o.className="gpp-lib-row-handle",o.textContent="⠿",o.title="Drag to reorder",n.appendChild(o);const r=document.createElement("input");r.type="checkbox",r.checked=t.selectedIds.has(e.id),r.addEventListener("change",()=>{r.checked?t.selectedIds.add(e.id):t.selectedIds.delete(e.id),t.syncBulkButtons()}),n.appendChild(r);const a=document.createElement("canvas");a.className="gpp-lib-row-thumb",a.width=22,a.height=22;const i=a.getContext("2d");i.imageSmoothingEnabled=!1;const l=gppLibraryEnsureThumb(e);i.drawImage(l.small,0,0,22,22),n.appendChild(a);const s=document.createElement("div");s.className="gpp-lib-row-meta";const c=document.createElement("div");c.className="gpp-lib-row-name gpp-lib-editable-name",c.textContent=e.name||"Untitled template",c.title="Click to rename",c.addEventListener("click",o=>{o.stopPropagation(),n.draggable=!1,gppLibraryStartRename(c,e,()=>{n.draggable=!0,t.renderList(),t.onChange()})});const d=document.createElement("div");d.className="gpp-lib-row-dims",d.textContent=e.width+"×"+e.height+(e.position?"":" · unplaced"),s.appendChild(c),s.appendChild(d),n.appendChild(s);const p=!!gppLibraryComputeTemplateCenterGrid(e),g=document.createElement("button");g.type="button",g.className="gpp-lib-row-goto",g.textContent="➤",g.title=p?"Go to this template’s location":"No saved location yet",g.disabled=!p,g.addEventListener("click",t=>{t.stopPropagation(),p&&gppLibraryFlyToTemplate(e)}),n.appendChild(g);const u=document.createElement("button");u.type="button",u.className="gpp-lib-row-vis";const m=()=>{const t=e.opacity>0;u.textContent=t?"👁️":"🚫",u.title=t?"Visible — click to hide":"Hidden — click to show"};return m(),u.addEventListener("click",n=>{n.stopPropagation(),gppLibraryToggleVisibility(e).then(()=>{m(),t.onChange()})}),n.appendChild(u),n}function gppLibraryBuildManageGridCard(e,t){const n=document.createElement("div"),o=e.id===gppState.focusedTemplateId,r=t.selectedIds.has(e.id);n.className="gpp-lib-manage-grid-card"+(o?" gpp-lib-manage-grid-card-focused":"")+(r?" gpp-lib-manage-grid-card-selected":""),n.title=e.name||"Untitled template",n.draggable=!0,n.addEventListener("dragstart",o=>{t.dragState.id=e.id,o.dataTransfer.effectAllowed="move";try{o.dataTransfer.setData("text/plain",e.id)}catch(e){}gppLibraryHideHoverPreview(),n.classList.add("gpp-lib-manage-grid-card-dragging")}),n.addEventListener("dragend",()=>{t.dragState.id=null,n.classList.remove("gpp-lib-manage-grid-card-dragging"),n.classList.remove("gpp-lib-manage-grid-card-dragover")}),n.addEventListener("dragover",o=>{t.dragState.id&&t.dragState.id!==e.id&&(o.preventDefault(),o.dataTransfer.dropEffect="move",n.classList.add("gpp-lib-manage-grid-card-dragover"))}),n.addEventListener("dragleave",()=>n.classList.remove("gpp-lib-manage-grid-card-dragover")),n.addEventListener("drop",o=>{o.preventDefault(),n.classList.remove("gpp-lib-manage-grid-card-dragover");const r=t.dragState.id;t.dragState.id=null,r&&r!==e.id&&(async()=>{await gppLibraryReorderTemplates(r,e.id),t.renderList(),t.onChange()})()});const a=document.createElement("div");a.className="gpp-lib-manage-grid-thumb-wrap",a.appendChild(gppLibraryRenderFullCanvas(e));const i=document.createElement("button");i.type="button",i.className="gpp-lib-manage-grid-sel"+(r?" gpp-lib-manage-grid-sel-active":""),i.textContent=r?"☑":"☐",i.title="Select for bulk actions",i.addEventListener("click",o=>{o.stopPropagation();const r=!t.selectedIds.has(e.id);r?t.selectedIds.add(e.id):t.selectedIds.delete(e.id),i.textContent=r?"☑":"☐",i.classList.toggle("gpp-lib-manage-grid-sel-active",r),n.classList.toggle("gpp-lib-manage-grid-card-selected",r),t.listEl.classList.toggle("gpp-lib-manage-list-grid-selmode",t.selectedIds.size>0),t.syncBulkButtons()}),a.appendChild(i);const l=document.createElement("button");l.type="button",l.className="gpp-lib-manage-grid-vis";const s=()=>{const t=e.opacity>0;l.textContent=t?"👁️":"🚫",l.title=t?"Visible — click to hide":"Hidden — click to show"};s(),l.addEventListener("click",n=>{n.stopPropagation(),gppLibraryToggleVisibility(e).then(()=>{s(),t.onChange()})}),a.appendChild(l);if(!!gppLibraryComputeTemplateCenterGrid(e)){const n=document.createElement("button");n.type="button",n.className="gpp-lib-manage-grid-goto",n.textContent="🎯",n.title="Load & go to this template’s location",n.addEventListener("click",n=>{n.stopPropagation(),(async()=>{await gppState.focusTemplate(e.id),gppLibraryFlyToTemplate(e),t.renderList(),t.onChange()})()}),a.appendChild(n)}a.addEventListener("mouseenter",t=>gppLibraryShowHoverPreview(t,e)),a.addEventListener("mousemove",gppLibraryMoveHoverPreview),a.addEventListener("mouseleave",gppLibraryHideHoverPreview),n.appendChild(a);const c=document.createElement("div");return c.className="gpp-lib-manage-grid-name",c.textContent=e.name||"Untitled template",n.appendChild(c),n.addEventListener("click",()=>{e.id!==gppState.focusedTemplateId&&(async()=>{await gppState.focusTemplate(e.id),t.renderList(),t.onChange()})()}),n}async function gppLibraryToggleVisibility(e){e.opacity=e.opacity>0?0:1,await gppState.persistTemplateState(e),"function"==typeof gppRendererSchedule&&gppRendererSchedule()}async function gppLibrarySetVisibility(e,t){const n=t?1:0;e.opacity!==n&&(e.opacity=n,await gppState.persistTemplateState(e))}function gppOpenManageTemplatesModal(e){if(document.getElementById(GPP_LIB_MANAGE_ID))return;gppLibraryInjectStyle();const t=new Set,n=document.createElement("div");n.id=GPP_LIB_MANAGE_ID,n.className="gpp-lib-manage-overlay";const o=document.createElement("div");o.className="gpp-lib-manage-panel",n.appendChild(o);const r=document.createElement("div");r.className="gpp-lib-manage-header";const a=document.createElement("span");a.className="gpp-lib-manage-title",a.textContent="Manage templates";const i=document.createElement("div");i.className="gpp-lib-manage-header-right";const l=document.createElement("div");l.className="gpp-lib-manage-view-toggle";const s=document.createElement("button");s.type="button",s.className="gpp-lib-manage-view-btn",s.textContent="▦",s.title="Grid view";const c=document.createElement("button");c.type="button",c.className="gpp-lib-manage-view-btn",c.textContent="☰",c.title="List view",l.appendChild(s),l.appendChild(c);const d=document.createElement("button");d.type="button",d.className="gpp-lib-manage-close",d.textContent="✕",d.setAttribute("aria-label","Close"),i.appendChild(l),i.appendChild(d),r.appendChild(a),r.appendChild(i),o.appendChild(r);const p=document.createElement("div");p.className="gpp-lib-manage-toolbar";const g=document.createElement("label");g.className="gpp-lib-manage-selectall";const u=document.createElement("input");u.type="checkbox";const m=document.createElement("span");m.textContent="All",g.appendChild(u),g.appendChild(m);const h=document.createElement("div");h.className="gpp-lib-manage-toolbar-spacer";const f=document.createElement("button");f.type="button",f.className="gpp-lib-btn",f.textContent="Show selected";const b=document.createElement("button");b.type="button",b.className="gpp-lib-btn",b.textContent="Hide selected";const y=document.createElement("button");y.type="button",y.className="gpp-lib-btn",y.textContent="Export selected";const x=document.createElement("button");x.type="button",x.className="gpp-lib-btn gpp-lib-btn-danger",x.textContent="Delete selected",p.appendChild(g),p.appendChild(h),p.appendChild(f),p.appendChild(b),p.appendChild(y),p.appendChild(x),o.appendChild(p);const v=document.createElement("div");v.className="gpp-lib-manage-export-progress",v.style.display="none";const w=document.createElement("div");w.className="gpp-lib-manage-export-progress-label";const k=document.createElement("div");k.className="gpp-lib-manage-export-progress-bar";const E=document.createElement("div");function C(e,t,n){v.style.display=e?"":"none",e&&(E.style.width=Math.round(100*Math.max(0,Math.min(1,t||0)))+"%",w.textContent=n||"Exporting…")}E.className="gpp-lib-manage-export-progress-fill",k.appendChild(E),v.appendChild(w),v.appendChild(k),o.appendChild(v);const S=document.createElement("div");function T(){const e=gppState.templates,n=t.size>0;f.disabled=!n,b.disabled=!n,y.disabled=!n,x.disabled=!n,u.checked=e.length>0&&t.size===e.length,u.indeterminate=t.size>0&&t.size<e.length}S.className="gpp-lib-manage-list",o.appendChild(S);const P={selectedIds:t,dragState:{id:null},renderList:M,onChange:e,syncBulkButtons:T,listEl:S};function L(){s.classList.toggle("gpp-lib-manage-view-btn-active","grid"===gppManageViewMode),c.classList.toggle("gpp-lib-manage-view-btn-active","list"===gppManageViewMode)}function M(){const e=gppState.templates,n=new Set(e.map(e=>e.id));t.forEach(e=>{n.has(e)||t.delete(e)});const o="grid"===gppManageViewMode;if(S.classList.toggle("gpp-lib-manage-list-grid",o),S.classList.toggle("gpp-lib-manage-list-grid-selmode",o&&t.size>0),S.innerHTML="",e.length)o?e.forEach(e=>S.appendChild(gppLibraryBuildManageGridCard(e,P))):e.forEach(e=>S.appendChild(gppLibraryBuildManageRow(e,P)));else{const e=document.createElement("div");e.className="gpp-lib-manage-empty",e.textContent="No templates yet.",S.appendChild(e)}T()}function I(){document.removeEventListener("keydown",_),n.remove()}function _(e){"Escape"===e.key&&I()}L(),s.addEventListener("click",()=>{"grid"!==gppManageViewMode&&(gppManageViewMode="grid",L(),M())}),c.addEventListener("click",()=>{"list"!==gppManageViewMode&&(gppManageViewMode="list",L(),M())}),u.addEventListener("change",()=>{t.clear(),u.checked&&gppState.templates.forEach(e=>t.add(e.id)),M()}),f.addEventListener("click",()=>{const n=gppState.templates.filter(e=>t.has(e.id));n.length&&(async()=>{for(const e of n)try{await gppLibrarySetVisibility(e,!0)}catch(e){console.error("[GeoPixelcons++] Ghost++ bulk show failed:",e)}"function"==typeof gppRendererSchedule&&gppRendererSchedule(),M(),e()})()}),b.addEventListener("click",()=>{const n=gppState.templates.filter(e=>t.has(e.id));n.length&&(async()=>{for(const e of n)try{await gppLibrarySetVisibility(e,!1)}catch(e){console.error("[GeoPixelcons++] Ghost++ bulk hide failed:",e)}"function"==typeof gppRendererSchedule&&gppRendererSchedule(),M(),e()})()}),y.addEventListener("click",()=>{(async()=>{const e=gppState.templates.filter(e=>t.has(e.id));if(e.length){y.disabled=!0,C(!0,0,"Exporting 0 / "+e.length+"…");try{await gppState.exportTemplatesAsJson(e,void 0,(t,n)=>{C(!0,t,n+" ("+Math.round(t*e.length)+" / "+e.length+")")})}catch(e){console.error("[GeoPixelcons++] Ghost++ bulk export failed:",e)}finally{C(!1),T()}}})()}),x.addEventListener("click",()=>{const n=gppState.templates.filter(e=>t.has(e.id));if(!n.length)return;const o=1===n.length?'"'+(n[0].name||"this template")+'"':n.length+" templates";confirm("Delete "+o+"? This cannot be undone.")&&(async()=>{for(const e of n)try{await gppState.deleteTemplate(e)}catch(e){console.error("[GeoPixelcons++] Ghost++ delete failed:",e)}t.clear(),M(),e()})()}),document.addEventListener("keydown",_),d.addEventListener("click",I),n.addEventListener("click",e=>{e.target===n&&I()}),document.body.appendChild(n),M()}function gppClamp(e,t,n){return Number.isFinite(e)?Math.min(n,Math.max(t,e)):t}function gppScheduleRenderer(){if("function"==typeof gppRendererSchedule)try{gppRendererSchedule()}catch(e){console.error("[GeoPixelcons++] Ghost++ view settings: gppRendererSchedule() failed.",e)}}function gppInjectViewSettingsStyle(){let e=document.getElementById("gpp-view-settings-style");e||(e=document.createElement("style"),e.id="gpp-view-settings-style",document.head.appendChild(e)),e.textContent=`\n            .gpp-vs-subhead {\n                font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;\n                color: ${t2("#64748b","#a6adc8")};\n                margin: 10px 0 6px;\n            }\n            .gpp-vs-subhead:first-child { margin-top: 0; }\n            .gpp-vs-row {\n                display: flex; align-items: center; gap: 8px; margin: 6px 0;\n            }\n            .gpp-vs-row.gpp-vs-disabled .gpp-vs-label,\n            .gpp-vs-row.gpp-vs-disabled .gpp-vs-value { opacity: .5; }\n            .gpp-vs-label {\n                flex: 0 0 auto; min-width: 108px; font-size: 12px;\n                color: ${t2("#1f2937","#e2e2f5")};\n            }\n            .gpp-vs-row input[type="range"] { flex: 1 1 auto; min-width: 0; }\n            .gpp-vs-value {\n                flex: 0 0 auto; min-width: 34px; text-align: right; font-size: 11px;\n                font-variant-numeric: tabular-nums;\n                color: ${t2("#475569","#a6adc8")};\n            }\n            .gpp-vs-checkbox label {\n                display: flex; align-items: center; gap: 6px; font-size: 12px; cursor: pointer;\n                color: ${t2("#1f2937","#e2e2f5")};\n            }\n            .gpp-vs-empty { font-size: 12px; color: ${t2("#64748b","#a6adc8")}; }\n            .gpp-vs-view-toggle {\n                display: flex; border-radius: 6px; overflow: hidden; flex-shrink: 0;\n                border: 1px solid ${t2("#d1d5db","#45475a")};\n            }\n            .gpp-vs-view-btn {\n                font: inherit; font-size: 12px; line-height: 1; cursor: pointer; border: none; padding: 4px 8px;\n                background: ${t2("#ffffff","#313244")}; color: ${t2("#64748b","#a6adc8")};\n            }\n            .gpp-vs-view-btn:hover { background: ${t2("#f3f4f6","#45475a")}; }\n            .gpp-vs-view-btn-active {\n                background: ${t2("#2563eb","#89b4fa")}; color: ${t2("#ffffff","#1e1e2e")};\n            }\n        `}function gppAddResetButton(e,t,n){const o=document.createElement("button");o.type="button",o.innerHTML="↺",o.title=t,o.style.cssText="border:none; background:transparent; cursor:pointer; font-size:13px; padding:0 2px; flex-shrink:0; color:"+t2("#64748b","#a6adc8")+";",o.addEventListener("click",n),e.appendChild(o)}function gppBuildGlobalViewSettingsSection(e){const t=document.createElement("div"),n=document.createElement("div");n.className="gpp-vs-subhead",n.textContent="Global",t.appendChild(n);const o=document.createElement("div");o.className="gpp-vs-row";const r=document.createElement("label");r.className="gpp-vs-label",r.htmlFor="gpp-vs-gap-ratio",r.textContent="Cell fill";const a=document.createElement("input");a.type="range",a.id="gpp-vs-gap-ratio",a.min="0",a.max="100",a.step="1",a.title="Ratio between filled cell and gap. 0% is fully invisible, 100% leaves no gap.",a.value=String(Math.round(100*gppClamp(gppSettings.gapRatio,0,1)));const i=document.createElement("span");i.className="gpp-vs-value",i.textContent=a.value+"%",a.addEventListener("input",()=>{i.textContent=a.value+"%",gppSettings.gapRatio=gppClamp(Number(a.value)/100,0,1),gppState.saveSettings(),gppScheduleRenderer()}),a.addEventListener("change",()=>{e&&e()}),o.append(r,a,i),gppAddResetButton(o,"Reset to default cell fill",()=>{a.value="60",i.textContent="60%",gppSettings.gapRatio=.6,gppState.saveSettings(),gppScheduleRenderer(),e&&e()}),t.appendChild(o);const l=document.createElement("div");l.className="gpp-vs-row gpp-vs-checkbox";const s=document.createElement("label"),c=document.createElement("input");c.type="checkbox",c.id="gpp-vs-auto-hide-unfocused",c.checked=!!gppSettings.autoHideUnfocused;const d=document.createElement("span");d.textContent="Only show current template on map",s.htmlFor=c.id,s.title="Only ever show the template you're currently focused on — every other template hides automatically. Also reduces memory/GPU usage when you have many (or very large) templates.",s.append(c,d),l.appendChild(s),c.addEventListener("change",()=>{gppSettings.autoHideUnfocused=c.checked,gppState.saveSettings(),c.checked&&gppState.focusedTemplateId?gppState.applyAutoHideUnfocused(gppState.focusedTemplateId).then(()=>e&&e()):e&&e()}),t.appendChild(l);const p=document.createElement("div");p.className="gpp-vs-row gpp-vs-checkbox";const g=document.createElement("label"),u=document.createElement("input");u.type="checkbox",u.id="gpp-vs-gray-disabled-swatches",u.checked=!1!==gppSettings.grayDisabledSwatches;const m=document.createElement("span");m.textContent="Gray unselected color boxes",g.htmlFor=u.id,g.title="A disabled color always gets the diagonal slash; this also dims/grays it. Turn off to keep only the slash and see the true color underneath.",g.append(u,m),p.appendChild(g),u.addEventListener("change",()=>{gppSettings.grayDisabledSwatches=u.checked,gppState.saveSettings(),e&&e()}),t.appendChild(p);const h=document.createElement("div");h.className="gpp-vs-row";const f=document.createElement("span");f.className="gpp-vs-label",f.textContent="Palette view";const b=document.createElement("div");b.className="gpp-vs-view-toggle";const y=document.createElement("button");y.type="button",y.className="gpp-vs-view-btn",y.id="gpp-vs-palette-view-grid",y.textContent="▦",y.title="Grid view";const x=document.createElement("button");function v(){const e="list"===gppSettings.paletteViewMode?"list":"grid";y.classList.toggle("gpp-vs-view-btn-active","grid"===e),x.classList.toggle("gpp-vs-view-btn-active","list"===e)}return x.type="button",x.className="gpp-vs-view-btn",x.id="gpp-vs-palette-view-list",x.textContent="☰",x.title="List view",v(),y.addEventListener("click",()=>{"grid"!==gppSettings.paletteViewMode&&(gppSettings.paletteViewMode="grid",gppState.saveSettings(),v(),e&&e())}),x.addEventListener("click",()=>{"list"!==gppSettings.paletteViewMode&&(gppSettings.paletteViewMode="list",gppState.saveSettings(),v(),e&&e())}),b.append(y,x),h.append(f,b),t.appendChild(h),t}function gppRenderViewSettings(e,t,n){if(!e)return;gppInjectViewSettingsStyle();const o=e.querySelector("details.gpp-collapsible"),r=!!o&&o.open;e.innerHTML="";const a=document.createElement("details");a.className="gpp-collapsible",a.open=r;const i=document.createElement("summary");i.textContent="View Settings",a.appendChild(i);const l=document.createElement("div");l.className="gpp-body",l.appendChild(gppBuildGlobalViewSettingsSection(n)),a.appendChild(l),e.appendChild(a)}let gppLastRefreshAll=null;function gppRequestUiRefresh(){"function"==typeof gppLastRefreshAll&&gppLastRefreshAll()}if(_settings.ghostPlusPlus){function n(){try{!function(){const e=gppBuildModalShell();gppLastRefreshAll=l;const t=gppReplaceNativeOpener(()=>{e.classList.contains("gpp-hidden")?async function(){e.classList.remove("gpp-hidden");const t=e.getBoundingClientRect();e.style.left=Math.max(0,(window.innerWidth-t.width)/2)+"px",e.style.top=Math.max(0,(window.innerHeight-t.height)/2)+"px",e.style.right="auto";const n=document.getElementById("gpp-left-body");(function(){if(document.getElementById("gpp-drop-zone"))return;document.getElementById("gpp-left-body").innerHTML='\n                        <div id="gpp-drop-zone">\n                            <div><strong>Drop, paste, or click to choose template files</strong></div>\n                            <div class="gpp-muted" style="font-size:11px;">PNG, JPEG/JFIF, WebP, or .json (export) supported</div>\n                            <button type="button" id="gpp-url-upload-btn">or load from a URL</button>\n                            <input id="gpp-file-input" type="file" accept="image/png,image/jpeg,image/jfif,image/webp,application/json,.json" multiple style="display:none;">\n                        </div>\n                        <div id="gpp-ingest-status" class="gpp-muted" style="font-size:11px; min-height:14px;"></div>\n                        <div id="gpp-progress-section"></div>\n                        <div id="gpp-error-settings-section"></div>\n                        <div id="gpp-view-settings-section"></div>\n                        <div id="gpp-palette-section"></div>\n                    ',function(){const t=document.getElementById("gpp-drop-zone"),n=document.getElementById("gpp-file-input");document.getElementById("gpp-url-upload-btn").addEventListener("click",g),t.addEventListener("click",()=>n.click()),n.addEventListener("change",()=>{c(n.files),n.value=""}),t.addEventListener("dragover",e=>{e.dataTransfer&&Array.from(e.dataTransfer.types||[]).includes("Files")&&(e.preventDefault(),t.classList.add("gpp-dragging"))}),t.addEventListener("dragleave",()=>t.classList.remove("gpp-dragging")),t.addEventListener("drop",e=>{e.dataTransfer&&e.dataTransfer.files.length&&(e.preventDefault(),t.classList.remove("gpp-dragging"),c(e.dataTransfer.files))}),e.addEventListener("paste",e=>{if(!e.clipboardData)return;const t=Array.from(e.clipboardData.items||[]).filter(e=>"file"===e.kind).map(e=>e.getAsFile()).filter(Boolean);t.length&&c(t)})}()})(),gppState.runtimeReady||l();try{await function(){a||(a=gppInitRuntime().then(e=>("function"==typeof gppShimEnable&&gppShimEnable(),"function"==typeof gppEnsureAutoscanHook&&gppEnsureAutoscanHook(),"function"==typeof gppEnsureGuildProjectHook&&gppEnsureGuildProjectHook(),e)).catch(e=>{throw a=null,e}));return a}(),l()}catch(e){n.innerHTML="";const t=document.createElement("p");t.style.cssText="font-size:12px; color:#ef4444;",t.textContent="Ghost++ failed to start: "+(e&&e.message?e.message:String(e)),n.appendChild(t),console.error("[GeoPixelcons++] Ghost++ runtime init failed:",e)}}():i()});e.addEventListener("click",e=>{e.target.closest('[data-gpp-action="close"]')&&i()});let n=!1;function o(){n||(n=!0,Promise.resolve().then(()=>{n=!1,[gppInjectShellStyle,gppInjectPaletteStyle,gppLibraryInjectStyle,gppInjectPlacementStyle,gppInjectViewSettingsStyle].forEach(e=>{if("function"==typeof e)try{e()}catch(e){console.error("[GeoPixelcons++] Ghost++ theme refresh failed.",e)}}),!e.classList.contains("gpp-hidden")&&a&&l()}))}new MutationObserver(o).observe(document.body,{attributes:!0,attributeFilter:["class"]});let r=isDarkMode();setInterval(()=>{const e=isDarkMode();e!==r&&(r=e,o())},1e3);let a=null;function i(){e.classList.add("gpp-hidden")}function l(){const e=gppState.getFocusedTemplate(),t=document.getElementById(GPP_IDS.editingLabel);e?e.position?t.textContent=e.name+" — X: "+e.position.gridX+", Y: "+e.position.gridY:t.textContent=e.name+" — not placed":t.textContent="","function"==typeof gppShimSyncFocusedTemplate&&gppShimSyncFocusedTemplate();const n=document.getElementById("gpp-progress-section");"function"==typeof gppRenderProgressBar&&n&&gppRenderProgressBar(n,e,l);const o=document.getElementById("gpp-error-settings-section");"function"==typeof gppRenderErrorSettings&&o&&gppRenderErrorSettings(o,e,l);const r=document.getElementById("gpp-view-settings-section");"function"==typeof gppRenderViewSettings&&r&&gppRenderViewSettings(r,e,l);const a=document.getElementById("gpp-palette-section");"function"==typeof gppRenderPalette&&a&&gppRenderPalette(a,e,l);const i=document.getElementById(GPP_IDS.rightContent);"function"==typeof gppRenderTemplateLibrary&&i&&gppRenderTemplateLibrary(i,l);const s=document.getElementById(GPP_LIB_CURRENT_PT_ID);"function"==typeof gppRenderPositionTransform&&s&&gppRenderPositionTransform(s,e,l)}function s(e,t){const n=document.getElementById("gpp-ingest-status");n&&(n.textContent=e,n.style.color=t?"#ef4444":"")}async function c(e){const t=Array.from(e||[]);for(const e of t)try{if("application/json"===e.type||/\.json$/i.test(e.name||"")){const t=await gppState.ingestJsonFile(e,(t,n)=>{s((n||"Importing")+" — "+e.name+" ("+Math.round(100*t)+"%)")});s("Imported "+t.length+(1===t.length?" template":" templates")+" from "+e.name+".");continue}if(!gppState.acceptedImageTypes.includes(e.type)){s("Skipped "+(e.name||"file")+": unsupported type.",!0);continue}await gppState.ingestImageFile(e,(t,n)=>{s((n||"Importing")+" — "+e.name+" ("+Math.round(100*t)+"%)")}),s("Imported "+e.name+".")}catch(t){s("Failed to import "+(e.name||"file")+": "+(t&&t.message?t.message:String(t)),!0),console.error("[GeoPixelcons++] Ghost++ ingest failed:",t)}l()}const d={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",jfif:"image/jfif",webp:"image/webp",json:"application/json"};async function p(e){const t=/^https?:\/\//i.test(e)?e:"https://"+e;let n;s("Fetching "+t+"…");try{n=await function(e){return new Promise((t,n)=>{"function"==typeof GM_xmlhttpRequest?GM_xmlhttpRequest({method:"GET",url:e,responseType:"blob",onload:e=>{e.status>=200&&e.status<300?t(e.response):n(new Error("HTTP "+e.status+(e.statusText?" "+e.statusText:"")))},onerror:()=>n(new Error("Network error while fetching the URL.")),ontimeout:()=>n(new Error("Request timed out."))}):n(new Error("URL upload is unavailable (GM_xmlhttpRequest is missing)."))})}(t)}catch(e){return s("Failed to fetch URL: "+(e&&e.message?e.message:String(e)),!0),void console.error("[GeoPixelcons++] Ghost++ URL ingest fetch failed:",e)}let o=(n.type||"").split(";")[0].trim().toLowerCase();if("application/json"===o||gppState.acceptedImageTypes.includes(o)||(o=function(e){try{const t=/\.([a-z0-9]+)$/i.exec(new URL(e).pathname);if(t)return d[t[1].toLowerCase()]||null}catch(e){}return null}(t)||o),"application/json"!==o&&!gppState.acceptedImageTypes.includes(o))return void s("Could not tell what that URL points to — make sure it ends in .png/.jpg/.jpeg/.webp/.json or the server sends a matching Content-Type.",!0);const r=new File([n],function(e,t){let n="";try{n=decodeURIComponent(new URL(e).pathname.split("/").pop()||"")}catch(e){}n||(n="url-upload");const o=Object.keys(d).find(e=>d[e]===t);return o&&!new RegExp("\\."+o+"$","i").test(n)&&(n+="."+o),n}(t,o),{type:o});await c([r])}function g(e){e.stopPropagation();const t=prompt("Enter an image or .json template URL:");if(!t)return;const n=t.trim();n&&p(n)}_featureStatus.ghostPlusPlus="ok",dbgPush("Ghost++ Template Overlay initialized successfully — opener mounted"+(t&&t.native?" next to the native ghost button":" (native ghost button not found synchronously — see the gpp-opener-native-button log entries above for how that was handled)")+".",{uiComponent:"Ghost++ Template Overlay"}),console.log("[GeoPixelcons++] ✅ Ghost++ Template Overlay loaded")}()}catch(e){_featureStatus.ghostPlusPlus="error",dbgPush(`Ghost++ Template Overlay init failed: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:"Ghost++ Template Overlay"}),console.error("[GeoPixelcons++] ❌ Ghost++ Template Overlay failed:",e)}}dbgPush('Ghost++ init: document.readyState was "'+document.readyState+'" at script-execution time — '+("loading"===document.readyState?"waiting for DOMContentLoaded before starting.":"starting immediately."),{uiComponent:"Ghost++ Template Overlay"}),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",function(){dbgPush("Ghost++ init: DOMContentLoaded fired — starting now.",{uiComponent:"Ghost++ Template Overlay"}),n()}):n()}if(_settings.ghostPaletteSearch)try{!function(){const e=document.createElement("style");e.textContent="\n        .color-search-glow {\n            box-shadow: 0 0 8px 2px rgba(255, 215, 0, 0.8) !important;\n            animation: pulse-glow 1.5s ease-in-out infinite;\n        }\n\n        @keyframes pulse-glow {\n            0%, 100% {\n                box-shadow: 0 0 8px 2px rgba(255, 215, 0, 0.8) !important;\n            }\n            50% {\n                box-shadow: 0 0 12px 3px rgba(255, 215, 0, 1) !important;\n            }\n        }\n\n        .color-search-container {\n            margin-bottom: 12px;\n            padding: 12px;\n            background: var(--color-gray-200, #f9fafb);\n            border-radius: 8px;\n            border: 1px solid var(--color-gray-300, #e5e7eb);\n        }\n\n        .color-search-input {\n            width: 100%;\n            min-height: 34px;\n            height: 34px;\n            max-height: 110px;\n            padding: 8px 12px;\n            border: 2px solid var(--color-gray-400, #d1d5db);\n            border-radius: 6px;\n            font-size: 14px;\n            line-height: 18px;\n            transition: border-color 0.2s;\n            background: var(--color-gray-100, #fff);\n            color: var(--color-gray-900, inherit);\n            resize: vertical;\n            overflow-y: auto;\n            box-sizing: border-box;\n        }\n\n        .color-search-input:focus {\n            outline: none;\n            border-color: #3b82f6;\n        }\n\n        .color-search-input::placeholder {\n            color: var(--color-gray-600, #9ca3af);\n        }\n\n        .gpc-search-toggle-row {\n            display: flex;\n            align-items: center;\n            gap: 6px;\n            margin-top: 8px;\n            font-size: 14px;\n            color: var(--color-gray-800, #374151);\n        }\n\n        .gpc-search-toggle-row input {\n            width: 15px;\n            height: 15px;\n            cursor: pointer;\n        }\n\n        .gpc-search-toggle-row label {\n            cursor: pointer;\n            user-select: none;\n        }\n\n        .gpc-search-controls-row {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            margin-top: 8px;\n        }\n\n        .gpc-filter-dropdown {\n            position: relative;\n            width: 42%;\n            min-width: 142px;\n            flex: 0 0 42%;\n        }\n\n        .gpc-filter-button,\n        .gpc-sort-select {\n            width: 100%;\n            min-height: 30px;\n            border: 2px solid var(--color-gray-400, #d1d5db);\n            border-radius: 6px;\n            background: var(--color-gray-100, #fff);\n            color: var(--color-gray-900, inherit);\n            font-size: 13px;\n            cursor: pointer;\n        }\n\n        .gpc-filter-button {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            gap: 8px;\n            padding: 3px 8px;\n            text-align: left;\n        }\n\n        .gpc-filter-menu {\n            display: none;\n            position: absolute;\n            top: calc(100% + 4px);\n            left: 0;\n            z-index: 100000;\n            min-width: 210px;\n            padding: 6px;\n            border: 1px solid var(--color-gray-300, #e5e7eb);\n            border-radius: 8px;\n            background: var(--color-gray-100, #fff);\n            box-shadow: 0 8px 24px rgba(0,0,0,0.16);\n        }\n\n        .gpc-filter-menu.gpc-open {\n            display: flex;\n            flex-direction: column;\n            gap: 2px;\n        }\n\n        .gpc-filter-option {\n            display: flex;\n            align-items: center;\n            gap: 7px;\n            padding: 4px 5px;\n            border-radius: 5px;\n            font-size: 13px;\n            color: var(--color-gray-900, inherit);\n            cursor: pointer;\n            user-select: none;\n        }\n\n        .gpc-filter-option:hover {\n            background: var(--color-gray-200, #f3f4f6);\n        }\n\n        .gpc-filter-option input {\n            width: 14px;\n            height: 14px;\n            cursor: pointer;\n        }\n\n        .gpc-filter-count {\n            display: flex;\n            align-items: center;\n            gap: 6px;\n            flex-wrap: wrap;\n            padding: 2px 5px 4px 26px;\n            font-size: 13px;\n            color: var(--color-gray-900, inherit);\n        }\n\n        .gpc-count-input {\n            width: 64px;\n            min-height: 26px;\n            border: 2px solid var(--color-gray-400, #d1d5db);\n            border-radius: 5px;\n            background: var(--color-gray-100, #fff);\n            color: var(--color-gray-900, inherit);\n            font-size: 12px;\n            padding: 2px 6px;\n        }\n\n        .gpc-sort-wrap {\n            display: flex;\n            align-items: center;\n            gap: 6px;\n            flex: 1 1 auto;\n            min-width: 190px;\n        }\n\n        .gpc-sort-select {\n            flex: 1 1 auto;\n            padding: 3px 6px;\n        }\n\n        .color-search-container.gpc-controls-stacked .gpc-search-controls-row {\n            flex-direction: column;\n            align-items: stretch;\n        }\n\n        .color-search-container.gpc-controls-stacked .gpc-filter-dropdown {\n            width: 100%;\n            flex: 0 0 auto;\n        }\n\n        .color-search-container.gpc-controls-stacked .gpc-sort-wrap {\n            width: 100%;\n            min-width: 0;\n        }\n\n        @media (max-width: 520px) {\n            .gpc-search-controls-row { flex-direction: column; align-items: stretch; }\n            .gpc-filter-dropdown { flex: 1 1 100%; width: 100%; }\n            .gpc-sort-wrap { min-width: 100%; }\n        }\n    ",document.head.appendChild(e);let t=!1;function n(e){const t=String(e||"").trim().match(/^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})\b/);if(!t)return null;let n=t[1];return 3===n.length&&(n=n.split("").map(e=>e+e).join("")),8===n.length&&(n=n.slice(0,6)),"#"+n.toUpperCase()}function o(e){return n((e.getAttribute("title")||"").split(/[\r\n]+/)[0])||function(e){const t=String(e||"").match(/[\d.]+/g);return!t||t.length<3?null:"#"+t.slice(0,3).map(e=>Math.max(0,Math.min(255,parseInt(e,10)||0)).toString(16).toUpperCase().padStart(2,"0")).join("")}(e.dataset.colorRgba||e.style.backgroundColor)}function r(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window,t=Array.isArray(e.__gpcOwnedGhostColors)?e.__gpcOwnedGhostColors:[],o=new Set;return t.forEach(e=>{const t=n(e);t&&o.add(t)}),o}!function(){const e=document.createElement("script");e.textContent="(function(){\nif(window.__gpcOwnedGhostColorsBridge)return;\nwindow.__gpcOwnedGhostColorsBridge=true;\nObject.defineProperty(window,'__gpcOwnedGhostColors',{configurable:true,get:function(){\n    try{\n        if(typeof Colors==='undefined'||!Array.isArray(Colors))return[];\n        return Colors.slice(0,Math.max(0,Colors.length-1));\n    }catch(e){return[];}\n}});\n})();",document.head.appendChild(e),e.remove()}(),function(){const e=document.createElement("script");e.textContent="(function(){\nif(window.__gpc_colorPatchApplied)return;\nwindow.__gpc_colorPatchApplied=true;\nvar _orig=window.changeColor;\nif(typeof _orig!=='function')return;\nwindow.changeColor=function(color){\n    _orig.call(this,color);\n    document.dispatchEvent(new CustomEvent('gpc:pixelColorChanged',{detail:color}));\n};\n})();",document.head.appendChild(e),e.remove()}(),document.addEventListener("gpc:pixelColorChanged",e=>{t&&function(e){if("function"==typeof gppApplySelectedColorToFocusedTemplate&&gppApplySelectedColorToFocusedTemplate(e))return;const t=document.getElementById("ghostColorPalette");if(!t)return;const n=t.querySelectorAll("button[data-color-rgba]");if(!n.length)return;const o=e.toUpperCase();let r=!1;const a=[],i=[];if(n.forEach(e=>{const t=e.dataset.colorRgba;if(!t)return;let n="";const l=(e.getAttribute("title")||"").split(/[\r\n]+/)[0].trim().toUpperCase();if(/^#[0-9A-F]{6}$/.test(l))n=l;else{const e=t.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);e&&(n="#"+[e[1],e[2],e[3]].map(e=>parseInt(e).toString(16).toUpperCase().padStart(2,"0")).join(""))}const s=e.classList.contains("border-blue-500"),c=n===o;c&&(r=!0),c&&!s?a.push(t):!c&&s&&i.push(t)}),!r)return;if(!a.length&&!i.length)return;const l=document.createElement("script");l.textContent=`(function(en,dis){en.forEach(r=>ghostActivePaletteColors.add(r));dis.forEach(r=>ghostActivePaletteColors.delete(r));if(typeof updateColorPaletteUI==='function')updateColorPaletteUI();if(typeof regenerateGhostCanvas==='function')regenerateGhostCanvas();})(${JSON.stringify(a)},${JSON.stringify(i)});`,document.head.appendChild(l),l.remove()}(e.detail)}),function(){const e=document.createElement("style");function n(e){if(document.getElementById("gpc-sync-ghost-btn"))return;const n=document.createElement("button");n.id="gpc-sync-ghost-btn",n.className="w-10 h-10 bg-white shadow rounded-full flex items-center justify-center hover:bg-gray-100 cursor-pointer";const o=!!_settings.showSyncGhostBtn;o||n.classList.add("hidden"),n.title="Sync Ghost With Selected Color",n.textContent="♻️",n.addEventListener("click",()=>{t=!t,n.dataset.active=t?"true":"false"}),e.appendChild(n),dbgPush('Ghost Palette Search: "Sync Ghost With Selected Color" button mounted into #imageGroupDropdown, '+(o?'and is visible (Settings > Extensions > "Sync Ghost With Selected Color" is currently ON).':'but starts HIDDEN because Settings > Extensions > "Sync Ghost With Selected Color" is currently OFF for this browser profile -- that is a separate checkbox from the "Ghost Palette Color Search" feature toggle itself, and defaults to off on every fresh profile. If a user reports the button "not rendering", check this line first.'),{uiComponent:"Ghost Palette Search"})}e.textContent='#gpc-sync-ghost-btn[data-active="true"]{background:#dcfce7!important;}#gpc-sync-ghost-btn[data-active="true"]:hover{background:#bbf7d0!important;}',document.head.appendChild(e);const o=Date.now(),r=document.getElementById("imageGroupDropdown");if(r)return dbgPush("Ghost Palette Search: #imageGroupDropdown found on the first synchronous check -- mounting the sync button now.",{uiComponent:"Ghost Palette Search"}),void n(r);dbgPush("Ghost Palette Search: #imageGroupDropdown NOT found on the first synchronous check -- watching for it to appear.",{uiComponent:"Ghost Palette Search"});const a=document.getElementById("controls-left")||document.body,i=new MutationObserver(()=>{const e=document.getElementById("imageGroupDropdown");e&&(i.disconnect(),clearTimeout(l),dbgPush("Ghost Palette Search: #imageGroupDropdown appeared "+(Date.now()-o)+"ms after watching started -- mounting the sync button now.",{uiComponent:"Ghost Palette Search"}),n(e))});i.observe(a,{childList:!0,subtree:!0});const l=setTimeout(()=>{i.disconnect(),dbgPush('Ghost Palette Search: gave up after 15s -- #imageGroupDropdown was never found, so the "Sync Ghost With Selected Color" button could not be mounted at all.',{uiComponent:"Ghost Palette Search"}),console.error("[GeoPixelcons++] Ghost Palette Search: never found #imageGroupDropdown to mount the sync-ghost button into.")},15e3)}(),function e(t,n){const o=document.querySelector(t);o?n(o):setTimeout(()=>e(t,n),500)}("#ghostColorPalette",e=>{const t=document.createElement("div");t.className="color-search-container";const n=document.createElement("textarea");n.rows=1,n.className="color-search-input",n.placeholder="Search color(s) (comma, space, or newline separated)";const a=()=>{n.style.height="34px",n.style.height=Math.min(Math.max(34,n.scrollHeight),110)+"px"},i=n,l=document.createElement("div");l.className="gpc-search-toggle-row";const s=document.createElement("input");s.type="checkbox",s.id="gpc-showResultsFirst";const c=document.createElement("label");c.htmlFor="gpc-showResultsFirst",c.textContent="Show search results first",l.appendChild(s),l.appendChild(c);const d=document.createElement("div");d.className="gpc-search-controls-row";const p=document.createElement("div");p.className="gpc-filter-dropdown";const g=document.createElement("button");g.type="button",g.className="gpc-filter-button";const u=document.createElement("span");u.textContent="Filters";const m=document.createElement("span");m.textContent="▾",m.style.cssText="font-size:10px;opacity:0.7;",g.appendChild(u),g.appendChild(m);const h=document.createElement("div");h.className="gpc-filter-menu";const f=new Set,b=[];let y=null,x=null;const v=new Set(["hideCompleted","hideInProgress","hideUnstarted"]),w=new Set(["mostRemaining","leastRemaining","mostPct","leastPct"]);[{value:"hideUnmatched",text:"Hide unmatched colors"},{value:"hideCompleted",text:"Hide completed colors"},{value:"hideInProgress",text:"Hide in-progress colors"},{value:"hideUnstarted",text:"Hide unstarted colors"},{value:"ownedOnly",text:"Owned colors only"},{value:"countRange",text:"Filter within pixel count…"}].forEach(({value:e,text:t})=>{const n=document.createElement("label");n.className="gpc-filter-option",n.dataset.filterValue=e,v.has(e)&&(n.dataset.requiresProgress="true");const o=document.createElement("input");o.type="checkbox",o.value=e,o.addEventListener("change",()=>{o.checked?f.add(e):f.delete(e),S(),D()}),b.push(o);const r=document.createElement("span");r.textContent=t,n.appendChild(o),n.appendChild(r),h.appendChild(n)});const k=document.createElement("div");k.className="gpc-filter-count",k.style.display="none",y=document.createElement("input"),y.type="number",y.min="0",y.placeholder="min",y.className="gpc-count-input",x=document.createElement("input"),x.type="number",x.min="0",x.placeholder="max",x.className="gpc-count-input";const E=document.createElement("span");E.textContent="–",E.style.opacity="0.6",[y,x].forEach(e=>e.addEventListener("input",()=>D())),k.appendChild(y),k.appendChild(E),k.appendChild(x),h.appendChild(k);const C=b.find(e=>"countRange"===e.value);function S(){const e=f.size;u.textContent=e?`Filters (${e})`:"Filters"}C&&C.addEventListener("change",()=>{k.style.display=C.checked?"":"none",C.checked||(y&&(y.value=""),x&&(x.value=""))}),g.addEventListener("click",e=>{e.stopPropagation(),h.classList.toggle("gpc-open")}),h.addEventListener("click",e=>e.stopPropagation()),document.addEventListener("click",()=>h.classList.remove("gpc-open")),p.appendChild(g),p.appendChild(h);const T=document.createElement("div");T.className="gpc-sort-wrap";const P=document.createElement("select");function L(e){Object.assign(e.style,{padding:"3px 10px",background:"var(--color-blue-500, #3b82f6)",color:"var(--color-white, #fff)",border:"none",borderRadius:"5px",cursor:"pointer",fontSize:"12px",fontWeight:"700",whiteSpace:"nowrap"}),e.onmouseenter=()=>e.style.opacity="0.82",e.onmouseleave=()=>e.style.opacity="1"}P.className="gpc-sort-select",P.title="Scroll while hovering to change sort order",[{value:"default",text:"Sort by: Most used (default)"},{value:"leastUsed",text:"Sort by: Least used"},{value:"mostRemaining",text:"Sort by: Most remaining"},{value:"leastRemaining",text:"Sort by: Least remaining"},{value:"mostPct",text:"Sort by: Most % remaining"},{value:"leastPct",text:"Sort by: Least % remaining"},{value:"byColor",text:"Sort by: Color"},{value:"byColorRev",text:"Sort by: Color reversed"}].forEach(({value:e,text:t})=>{const n=document.createElement("option");n.value=e,n.textContent=t,w.has(e)&&(n.dataset.requiresProgress="true"),P.appendChild(n)}),T.appendChild(P),d.appendChild(p),d.appendChild(T);const M=document.createElement("button");M.textContent="Enable filtered",M.title="Enable colors currently shown in the ghost palette and disable hidden colors",L(M),M.onclick=()=>function(){D();const t=e.querySelectorAll("button[data-color-rgba]");if(!t.length)return void("function"==typeof showAlert?showAlert:alert)("No ghost palette colors found","Make sure a ghost image is loaded.");H();const n=[],o=[];let r=0;if(t.forEach(e=>{const t=e.dataset.colorRgba;if(!t)return;const a=!e.classList.contains("hidden");a&&r++;const i=e.classList.contains("border-blue-500");a&&!i?n.push(t):!a&&i&&o.push(t)}),0===r)return void("function"==typeof showAlert?showAlert:alert)("Enable Filtered","No visible ghost palette colors are currently shown.");if(!n.length&&!o.length)return;j(n,o)}();const I=document.createElement("button");I.textContent="Enable owned and filtered",I.title="Enable only owned ghost colors currently shown by the active filters",L(I),I.onclick=()=>function(){D();const t=e.querySelectorAll("button[data-color-rgba]");if(!t.length)return void("function"==typeof showAlert?showAlert:alert)("No ghost palette colors found","Make sure a ghost image is loaded.");const n=r();if(!n.size)return void("function"==typeof showAlert?showAlert:alert)("Enable Owned and Filtered","No owned colors were detected yet. Refresh your palette or reload GeoPixels, then try again.");H();const a=[],i=[];let l=0;if(t.forEach(e=>{const t=e.dataset.colorRgba;if(!t)return;const r=!e.classList.contains("hidden");r&&l++;const s=r&&n.has(o(e)),c=e.classList.contains("border-blue-500");s&&!c?a.push(t):!s&&c&&i.push(t)}),0===l)return void("function"==typeof showAlert?showAlert:alert)("Enable Owned and Filtered","No visible ghost palette colors are currently shown.");j(a,i)}();const _=document.createElement("div");_.className="gpc-filtered-row",_.style.cssText="display:flex;justify-content:flex-start;gap:6px;flex-wrap:wrap;padding:0 0 6px 0;",_.appendChild(M),_.appendChild(I),t.appendChild(i),t.appendChild(l),t.appendChild(d),e.parentNode.insertBefore(t,e),e.parentNode.insertBefore(_,t);const G=()=>{const e=t.getBoundingClientRect().width;e>0&&t.classList.toggle("gpc-controls-stacked",e<420)};function R(e){const t=(e.getAttribute("title")||"").split(/\n/).map(e=>e.trim()).filter(e=>e.length>0),n=t[0]||"";let o=0,r=0,a=0;const i=(t[1]||"").match(/^([\d,]+)\s*\/\s*([\d,]+)/);if(i)o=parseInt(i[1].replace(/,/g,""),10),r=parseInt(i[2].replace(/,/g,""),10);else{const e=(t[1]||"").match(/([\d,]+)\s*pixel/i);e&&(r=parseInt(e[1].replace(/,/g,""),10))}const l=(t[2]||"").match(/([\d.]+)%/);l&&(a=parseFloat(l[1]));const s=Math.max(0,r-o);return{hex:n,completed:o,total:r,remaining:s,percent:a,remainingPercent:r>0?s/r*100:0,hasProgress:!!i}}function N(){const t=Array.from(e.querySelectorAll('[title^="#"]')).some(e=>R(e).hasProgress);return b.forEach(e=>{const n=v.has(e.value),o=e.closest(".gpc-filter-option");o&&n&&(o.style.display=t?"":"none",e.disabled=!t,!t&&e.checked&&(e.checked=!1,f.delete(e.value)))}),Array.from(P.options).forEach(e=>{const n=w.has(e.value);e.hidden=n&&!t,e.disabled=n&&!t}),!t&&w.has(P.value)&&(P.value="default"),S(),t}"undefined"!=typeof ResizeObserver?new ResizeObserver(G).observe(t):window.addEventListener("resize",G),setTimeout(G,0);let A=null,z=new Map,B=null;function O(){A=Array.from(e.querySelectorAll('[title^="#"]')),z=new Map(A.map((e,t)=>[e,t]))}function D(){N();const t=i.value.trim(),n=f.has("hideUnmatched"),a=f.has("hideCompleted"),l=f.has("hideInProgress"),c=f.has("hideUnstarted"),d=f.has("ownedOnly"),p=f.has("countRange"),g=p&&y&&""!==y.value?parseInt(y.value,10):NaN,u=p&&x&&""!==x.value?parseInt(x.value,10):NaN,m=!isNaN(g),h=!isNaN(u),b=d?r():null,v=Array.from(e.querySelectorAll('[title^="#"]'));v.forEach(e=>e.classList.remove("color-search-glow","hidden"));const w=t.split(/[\s,]+/).map(e=>e.trim().toUpperCase()).filter(e=>e.length>0),k=new Set;w.length>0&&v.forEach(e=>{const t=(e.getAttribute("title")||"").toUpperCase();w.some(e=>t.includes(e))&&(e.classList.add("color-search-glow"),k.add(e))}),v.forEach(e=>{const t=R(e),r=t.total>0,i=w.length>0&&!k.has(e),s=r&&t.completed>=t.total,p=r&&t.completed>0&&t.completed<t.total,f=r&&0===t.completed,y=d&&b&&!b.has(o(e)),x=(m||h)&&(m&&t.total<g||h&&t.total>u);(n&&i||a&&s||l&&p||c&&f||y||x)&&e.classList.add("hidden")}),function(t){const n=P.value,o=s.checked,r=t.size>0,a=A&&A.length>0&&A.every(t=>e.contains(t))?A:Array.from(e.querySelectorAll('[title^="#"]')),i=(e,t)=>(z.get(e)??0)-(z.get(t)??0);let l=[...a].sort((e,t)=>{const o=R(e),r=R(t);switch(n){case"default":return r.total-o.total||i(e,t);case"leastUsed":return o.total-r.total||i(e,t);case"mostRemaining":return r.remaining-o.remaining||i(e,t);case"leastRemaining":return o.remaining-r.remaining||i(e,t);case"mostPct":return r.remainingPercent-o.remainingPercent||i(e,t);case"leastPct":return o.remainingPercent-r.remainingPercent||i(e,t);case"byColor":return(o.hex<r.hex?-1:o.hex>r.hex?1:0)||i(e,t);case"byColorRev":return(o.hex>r.hex?-1:o.hex<r.hex?1:0)||i(e,t);default:return i(e,t)}});if(o&&r){const e=l.filter(e=>t.has(e)),n=l.filter(e=>!t.has(e));l=[...e,...n]}B&&B.disconnect();const c=document.createDocumentFragment();l.forEach(e=>c.appendChild(e)),e.appendChild(c),B&&B.observe(e,{childList:!0,subtree:!0})}(k)}function j(e,t){if(!e.length&&!t.length)return;const n=document.createElement("script");n.textContent=`(function(en,dis){en.forEach(r=>ghostActivePaletteColors.add(r));dis.forEach(r=>ghostActivePaletteColors.delete(r));if(typeof updateColorPaletteUI==='function')updateColorPaletteUI();if(typeof regenerateGhostCanvas==='function')regenerateGhostCanvas();})(${JSON.stringify(e)},${JSON.stringify(t)});`,document.head.appendChild(n),n.remove()}function H(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window,t=document.getElementById("disableColorFilterToggle");t&&t.checked&&(t.checked=!1,"function"==typeof e.handleColorFilterToggle&&e.handleColorFilterToggle())}i.addEventListener("input",()=>{a(),D()}),P.addEventListener("change",D),P.addEventListener("wheel",e=>{e.preventDefault();const t=e.deltaY>0?1:-1;let n=P.selectedIndex+t;for(;n>=0&&n<P.options.length&&P.options[n].disabled;)n+=t;n=Math.min(Math.max(n,0),P.options.length-1),n!==P.selectedIndex&&(P.selectedIndex=n,D())},{passive:!1}),s.addEventListener("change",D);let F=0;B=new MutationObserver(()=>{const t=e.querySelectorAll('[title^="#"]').length;F>0&&Math.abs(t-F)>5&&(i.value="",b.forEach(e=>{e.checked=!1}),f.clear(),k&&(k.style.display="none"),y&&(y.value=""),x&&(x.value=""),S(),a(),P.value="default",s.checked=!1,O()),F=t,D()}),B.observe(e,{childList:!0,subtree:!0}),O(),F=e.querySelectorAll('[title^="#"]').length,N(),a()})}(),_featureStatus.ghostPaletteSearch="ok",console.log("[GeoPixelcons++] ✅ Ghost Palette Color Search loaded")}catch(o){_featureStatus.ghostPaletteSearch="error",dbgPush(`Ghost Palette Color Search init failed: ${o&&o.message?o.message:String(o)}`,{error:o,uiComponent:"Ghost Palette Color Search"}),console.error("[GeoPixelcons++] ❌ Ghost Palette Color Search failed:",o)}if(_settings.hidePaintMenu)try{!function(){const e=(e,t)=>{let n=!1,o=!1,r=0;const a="gpc-paint-drag-offset",i="gpc-paint-is-top";try{r=parseFloat(localStorage.getItem(a))||0}catch{}try{o="true"===localStorage.getItem(i)}catch{}e.classList.remove("-translate-x-1/2"),e.classList.remove("left-1/2"),e.style.position="fixed",e.style.bottom="1rem",e.style.transition="all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",e.style.width="",e.style.maxWidth="",e.style.left="50%",e.style.transform="translateX(-50%)";const l=document.createElement("div");l.style.cssText="\n            position: absolute;\n            top: -24px;\n            left: 0;\n            right: 0;\n            height: 24px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            z-index: 20;\n            pointer-events: none;\n        ";const s=document.createElement("button");s.innerHTML="▼",s.id="gpc-hide-paint-toggle",s.style.cssText="\n            pointer-events: auto;\n            width: 28px;\n            height: 24px;\n            border-bottom: none;\n            border-radius: 8px 8px 0 0;\n            cursor: pointer;\n            font-size: 12px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n        ",s.className="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 text-gray-500 dark:text-gray-300";const c=document.createElement("div");c.id="gpc-paint-drag-bar",c.style.cssText="\n            pointer-events: auto;\n            cursor: grab;\n            height: 24px;\n            width: 28px;\n            border-radius: 8px 8px 0 0;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            user-select: none;\n            border-bottom: none;\n            margin-left: 2px;\n        ",c.className="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 text-gray-400 dark:text-gray-500",c.innerHTML='<span style="font-size:10px;pointer-events:none;">⋮⋮</span>';const d=document.createElement("button");d.id="gpc-paint-reset-pos",d.title="Reset position to center",d.innerHTML="↺",d.style.cssText="\n            pointer-events: auto;\n            width: 28px;\n            height: 24px;\n            border-bottom: none;\n            border-radius: 8px 8px 0 0;\n            cursor: pointer;\n            font-size: 13px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            margin-left: 2px;\n        ",d.className="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 text-gray-500 dark:text-gray-300";const p=document.createElement("button");p.id="gpc-paint-flip-pos",p.title="Move to top / bottom",p.innerHTML=o?"⬇":"⬆",p.style.cssText="\n            pointer-events: auto;\n            width: 28px;\n            height: 24px;\n            border-bottom: none;\n            border-radius: 8px 8px 0 0;\n            cursor: pointer;\n            font-size: 12px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            margin-left: 2px;\n        ",p.className="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 text-gray-500 dark:text-gray-300";const g=document.createElement("button");if(g.id="gpc-paint-close",g.title="Switch to Inspect Mode",g.innerHTML="✕",g.style.cssText="\n            width: 24px;\n            height: 24px;\n            border-radius: 6px;\n            cursor: pointer;\n            font-size: 13px;\n            font-weight: 700;\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n            margin-left: 6px;\n            flex-shrink: 0;\n            vertical-align: middle;\n        ",g.className="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 text-gray-500 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-600",g.addEventListener("click",()=>{const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;"function"==typeof e.togglePrimaryMode&&e.togglePrimaryMode()}),t.parentElement.style.display="flex",t.parentElement.style.alignItems="center",t.insertAdjacentElement("afterend",g),l.appendChild(s),l.appendChild(c),l.appendChild(d),l.appendChild(p),e.appendChild(l),_settings.compactPaintOverflow){const S=document.createElement("button");S.id="gpc-compact-close",S.title="Switch to Inspect Mode",S.innerHTML="✕",S.style.cssText="\n                pointer-events: auto;\n                width: 28px;\n                height: 24px;\n                border-bottom: none;\n                border-radius: 8px 8px 0 0;\n                cursor: pointer;\n                font-size: 13px;\n                font-weight: 700;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n                margin-left: 2px;\n            ",S.className="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 text-gray-500 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-600",S.addEventListener("click",()=>{const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;"function"==typeof e.togglePrimaryMode&&e.togglePrimaryMode()});const T=document.createElement("button");function P(){const e=document.getElementById("brush-swap-toggle");return!!e&&(e.style.visibility="hidden",e.style.width="0",e.style.padding="0",e.style.margin="0",e.style.border="none",e.style.overflow="hidden",T.style.display="flex",!0)}if(T.id="gpc-compact-brush",T.title="Toggle saved brushes",T.innerHTML="🖌️",T.style.cssText="\n                pointer-events: auto;\n                width: 28px;\n                height: 24px;\n                border-bottom: none;\n                border-radius: 8px 8px 0 0;\n                cursor: pointer;\n                font-size: 13px;\n                display: none;\n                align-items: center;\n                justify-content: center;\n                margin-left: 2px;\n            ",T.className="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 text-gray-500 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-600",T.addEventListener("click",e=>{e.stopPropagation();const t=document.getElementById("brush-swap-toggle");t&&t.click(),requestAnimationFrame(()=>{const e=document.getElementById("brush-swap-dropdown");if(!e)return;e.parentElement!==document.body&&document.body.appendChild(e);const t=T.getBoundingClientRect(),n="true"===localStorage.getItem("gpc-paint-is-top");e.style.position="fixed",e.style.right="auto",e.style.margin="0",e.style.left=t.left+"px",n?(e.style.top=t.bottom+4+"px",e.style.bottom="auto"):(e.style.top="auto",e.style.bottom=window.innerHeight-t.top+4+"px")})}),T.addEventListener("wheel",e=>{const t=document.getElementById("brush-swap-toggle");t&&t.dispatchEvent(new WheelEvent("wheel",{deltaY:e.deltaY,clientX:e.clientX,clientY:e.clientY,bubbles:!1})),e.preventDefault()},{passive:!1}),l.appendChild(T),l.appendChild(S),S.style.position="absolute",S.style.right="20px",S.style.marginLeft="0",g.style.display="none",!P()){const L=new MutationObserver(()=>{P()&&L.disconnect()});L.observe(e,{childList:!0,subtree:!0}),setTimeout(()=>L.disconnect(),3e4)}}function u(){if(document.getElementById("gpc-paint-here-btn"))return;const e=document.getElementById("hoverInfo");if(!e)return;const t=document.createElement("button");t.id="gpc-paint-here-btn",t.className="w-full bg-green-500 text-white py-2 px-4 rounded-lg hover:bg-green-600 transition-colors flex items-center justify-center gap-2 cursor-pointer",t.style.marginTop="8px",t.innerHTML="🎨 Paint Here",t.addEventListener("click",()=>{const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;"function"==typeof e.togglePrimaryMode&&e.togglePrimaryMode()});const n=document.getElementById("shareLocationBtn"),o=n?.parentElement;o?o.insertAdjacentElement("afterend",t):e.appendChild(t)}new MutationObserver(()=>u()).observe(document.body,{childList:!0,subtree:!0}),u();const m=e.querySelector(":scope > div"),h=m?m.querySelector(":scope > .w-full.flex"):null,f=m?m.querySelector(":scope > .control-container-colors"):null,b=h?.parentElement,y=()=>{if(o){e.style.bottom="auto",e.style.top="1rem",b&&f&&h&&b.insertBefore(f,h),l.style.top="auto",l.style.bottom="-24px",[s,c,d,p].forEach(e=>{e.style.borderRadius="0 0 8px 8px",e.style.borderBottom="",e.style.borderTop="none"});const t=document.getElementById("gpc-compact-close"),n=document.getElementById("gpc-compact-brush");t&&(t.style.borderRadius="0 0 8px 8px",t.style.borderBottom="",t.style.borderTop="none"),n&&(n.style.borderRadius="0 0 8px 8px",n.style.borderBottom="",n.style.borderTop="none")}else{e.style.top="auto",e.style.bottom="1rem",b&&f&&h&&b.insertBefore(h,f),l.style.bottom="auto",l.style.top="-24px",[s,c,d,p].forEach(e=>{e.style.borderRadius="8px 8px 0 0",e.style.borderBottom="none",e.style.borderTop=""});const t=document.getElementById("gpc-compact-close"),n=document.getElementById("gpc-compact-brush");t&&(t.style.borderRadius="8px 8px 0 0",t.style.borderBottom="none",t.style.borderTop=""),n&&(n.style.borderRadius="8px 8px 0 0",n.style.borderBottom="none",n.style.borderTop="")}const t=n?o?"translateY(calc(-100% + 48px))":"translateY(calc(100% - 48px))":"translateY(0)";e.style.left="50%",e.style.right="auto",e.style.transform=`translateX(calc(-50% + ${r}px)) ${t}`,s.innerHTML=n?o?"▼":"▲":o?"▲":"▼",p.innerHTML=o?"⬇":"⬆"};let x=!1,v=0,w=0;function k(t){x=!0,v=t.touches?t.touches[0].clientX:t.clientX,w=r,c.style.cursor="grabbing",e.style.transition="none",t.preventDefault()}function E(t){if(!x)return;const n=t.touches?t.touches[0].clientX:t.clientX;r=w+(n-v);e.offsetWidth;const o=window.innerWidth/2-60;r=Math.max(-o,Math.min(o,r)),y()}function C(){x&&(x=!1,c.style.cursor="grab",e.style.transition="all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",localStorage.setItem(a,String(r)))}c.addEventListener("mousedown",k),document.addEventListener("mousemove",E),document.addEventListener("mouseup",C),c.addEventListener("touchstart",k,{passive:!1}),document.addEventListener("touchmove",E,{passive:!1}),document.addEventListener("touchend",C),s.addEventListener("click",()=>{n=!n,y()}),d.addEventListener("click",()=>{r=0,localStorage.removeItem(a),y()}),p.addEventListener("click",()=>{o=!o,n=!1,localStorage.setItem(i,String(o)),y()}),y(),console.log("Bottom controls enhanced: properly centered with left/right positioning.")},t=()=>{const t=Date.now(),n=()=>{const e=document.getElementById("bottomControls"),t=document.getElementById("currentEnergyDisplay");return e&&t?{bottomControls:e,energyDisplay:t}:null},o=n();if(o)return dbgPush("Paint Menu Controls: #bottomControls and #currentEnergyDisplay found on the first synchronous check -- mounting now.",{uiComponent:"Paint Menu Controls"}),void e(o.bottomControls,o.energyDisplay);dbgPush("Paint Menu Controls: #bottomControls and #currentEnergyDisplay NOT found on the first synchronous check -- watching for them to appear.",{uiComponent:"Paint Menu Controls"});const r=new MutationObserver(()=>{const o=n();o&&(r.disconnect(),clearTimeout(a),dbgPush("Paint Menu Controls: #bottomControls and #currentEnergyDisplay appeared "+(Date.now()-t)+"ms after watching started -- mounting now.",{uiComponent:"Paint Menu Controls"}),e(o.bottomControls,o.energyDisplay))});r.observe(document.body,{childList:!0,subtree:!0});const a=setTimeout(()=>{r.disconnect(),dbgPush("Paint Menu Controls: gave up after 15s -- #bottomControls and #currentEnergyDisplay were never found together, could not be mounted at all.",{uiComponent:"Paint Menu Controls"}),console.error("[GeoPixelcons++] Paint Menu Controls: never found #bottomControls and #currentEnergyDisplay.")},15e3)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}(),_featureStatus.hidePaintMenu="ok",console.log("[GeoPixelcons++] ✅ Paint Menu Controls loaded")}catch(r){_featureStatus.hidePaintMenu="error",dbgPush(`Paint Menu Controls init failed: ${r&&r.message?r.message:String(r)}`,{error:r,uiComponent:"Paint Menu Controls"}),console.error("[GeoPixelcons++] ❌ Paint Menu Controls failed:",r)}if(_settings.ghostTemplateManager)try{!function(){const e="GP_Ghost_History",t="images",n=2147483648;let o=!1,r=!1,a=null;function i(e,t=null){}function l(e){if("undefined"!=typeof window&&void 0!==window[e]){const t=window[e];if(!("map"===e&&t instanceof HTMLElement))return t}if("undefined"!=typeof unsafeWindow&&void 0!==unsafeWindow[e]){const t=unsafeWindow[e];if("map"===e&&t instanceof HTMLElement){if(void 0!==unsafeWindow.wrappedJSObject&&unsafeWindow.wrappedJSObject[e]){const t=unsafeWindow.wrappedJSObject[e];if(!(t instanceof HTMLElement))return t}return function(e){try{const t=`__gp_bridge_${e}_${Date.now()}`,n=document.createElement("script");n.textContent=`\n                (function() {\n                    if (typeof ${e} !== 'undefined' && ${e}) {\n                        // Store a marker that the variable exists\n                        document.documentElement.setAttribute('${t}', 'exists');\n                        // For map object, we can't directly transfer it, so we'll access it differently\n                        if ('${e}' === 'map' && typeof ${e}.project === 'function') {\n                            document.documentElement.setAttribute('${t}_hasProject', 'true');\n                        }\n                    }\n                })();\n            `,document.documentElement.appendChild(n),n.remove();const o=document.documentElement.getAttribute(t);if(document.documentElement.removeAttribute(t),document.documentElement.removeAttribute(`${t}_hasProject`),"exists"===o){if("map"===e)return{project:function(e){const t=document.createElement("script"),n=`__gp_map_result_${Date.now()}`;t.textContent=`\n                    (function() {\n                        try {\n                            const result = map.project([${e[0]}, ${e[1]}]);\n                            document.documentElement.setAttribute('${n}', JSON.stringify({x: result.x, y: result.y}));\n                        } catch(e) {\n                            document.documentElement.setAttribute('${n}_error', e.message);\n                        }\n                    })();\n                `,document.documentElement.appendChild(t),t.remove();const o=document.documentElement.getAttribute(n),r=document.documentElement.getAttribute(`${n}_error`);if(document.documentElement.removeAttribute(n),document.documentElement.removeAttribute(`${n}_error`),r)throw new Error(r);return JSON.parse(o)},on:function(e,t){this._handlers||(this._handlers={}),this._handlers[e]||(this._handlers[e]=[]),this._handlers[e].push(t);const n=`__gp_map_listener_${e}_${Date.now()}`,o=document.createElement("script");o.textContent=`\n                    (function() {\n                        if (typeof map !== 'undefined' && map.on) {\n                            map.on('${e}', function() {\n                                document.documentElement.setAttribute('${n}', Date.now());\n                            });\n                        }\n                    })();\n                `,document.documentElement.appendChild(o),o.remove(),new MutationObserver(()=>{document.documentElement.getAttribute(n)&&(document.documentElement.removeAttribute(n),t())}).observe(document.documentElement,{attributes:!0})},off:function(e,t){},getContainer:function(){return document.getElementById("map")}};if("turf"===e)return{toWgs84:function(e){const t=document.createElement("script"),n=`__gp_turf_result_${Date.now()}`;t.textContent=`\n                    (function() {\n                        try {\n                            const result = turf.toWgs84([${e[0]}, ${e[1]}]);\n                            document.documentElement.setAttribute('${n}', JSON.stringify(result));\n                        } catch(e) {\n                            document.documentElement.setAttribute('${n}_error', e.message);\n                        }\n                    })();\n                `,document.documentElement.appendChild(t),t.remove();const o=document.documentElement.getAttribute(n),r=document.documentElement.getAttribute(`${n}_error`);if(document.documentElement.removeAttribute(n),document.documentElement.removeAttribute(`${n}_error`),r)throw new Error(r);return JSON.parse(o)}}}return null}catch(e){return e.message,null}}(e)}return t}return"undefined"!=typeof unsafeWindow&&void 0!==unsafeWindow.wrappedJSObject&&void 0!==unsafeWindow.wrappedJSObject[e]?unsafeWindow.wrappedJSObject[e]:null}function s(e,t){const n=l("showAlert");"function"==typeof n?n(e,t):(console.log(`[${e}] ${t}`),alert(`${e}: ${t}`))}function c(){const e=document.getElementById("groupNoiseToggle");return!!e&&!!e.checked}function d(){const e=localStorage.getItem("ghostImageCoords");if(e)try{const t=JSON.parse(e);if("number"!=typeof t.gridX||"number"!=typeof t.gridY)return void s("Error","Invalid coordinates in template.");const n=l("goToGridLocation");"function"==typeof n?(t.gridX,t.gridY,n(t.gridX,t.gridY)):s("Error","Navigation function not available.")}catch(e){dbgPush(`goToTemplateLocation failed to parse coordinates: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:"Ghost Template Manager - Go To Location button"}),console.error("Failed to parse coordinates:",e),s("Error","Failed to read template coordinates.")}else s("No Template","No ghost image template is currently set.")}async function p(e){const t=await e.arrayBuffer(),n=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,"0")).join("")}"undefined"!=typeof window&&window.map,"undefined"!=typeof window&&window.turf,"undefined"!=typeof unsafeWindow&&unsafeWindow.map,"undefined"!=typeof unsafeWindow&&unsafeWindow.turf;const g=document.createElement("style");g.textContent="\n        .gp-to-modal-overlay {\n            position: fixed; inset: 0; background: rgba(0, 0, 0, 0.75);\n            display: flex; align-items: center; justify-content: center; z-index: 10000;\n        }\n        .gp-to-modal-panel {\n            background: var(--color-gray-100, white); color: var(--color-gray-900, inherit); border-radius: 1rem; padding: 1.5rem;\n            width: 95%; max-width: 600px; max-height: 80vh;\n            display: flex; flex-direction: column; gap: 1rem;\n            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n        }\n        .gp-to-header { display: flex; flex-direction: column; gap: 8px; border-bottom: 1px solid var(--color-gray-300, #eee); padding-bottom: 10px; }\n        .gp-to-header-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }\n        .gp-to-title { font-size: 1.25rem; font-weight: bold; color: var(--color-gray-900, #1f2937); }\n\n        .gp-to-grid {\n            display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n            gap: 10px; overflow-y: auto; padding: 4px;\n        }\n        .gp-to-card {\n            border: 1px solid var(--color-gray-300, #e5e7eb); border-radius: 8px; overflow: hidden;\n            position: relative; transition: transform 0.1s, box-shadow 0.1s;\n            cursor: pointer; background: var(--color-gray-200, #f9fafb);\n        }\n        .gp-to-card:hover { transform: translateY(-2px); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); border-color: #3b82f6; }\n        .gp-to-card img { width: 100%; height: 100px; object-fit: cover; display: block; }\n        .gp-to-card-footer {\n            padding: 4px; font-size: 10px; text-align: center;\n            background: var(--color-gray-100, #fff); color: var(--color-gray-500, #6b7280); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n        }\n        .gp-to-delete-btn {\n            position: absolute; top: 2px; right: 2px;\n            background: rgba(239, 68, 68, 0.9); color: white;\n            border: none; border-radius: 4px; width: 20px; height: 20px;\n            display: flex; align-items: center; justify-content: center;\n            font-size: 12px; cursor: pointer; z-index: 2;\n            opacity: 0; transition: opacity 0.15s;\n        }\n        .gp-to-card:hover .gp-to-delete-btn { opacity: 1; }\n        .gp-to-delete-btn:hover { background: #dc2626; }\n        .gp-to-sel-btn {\n            position: absolute; top: 2px; left: 2px;\n            background: rgba(255,255,255,0.9); color: #374151;\n            border: none; border-radius: 4px; width: 20px; height: 20px;\n            display: flex; align-items: center; justify-content: center;\n            font-size: 13px; cursor: pointer; z-index: 2; line-height: 1;\n            opacity: 0; transition: opacity 0.15s;\n        }\n        .gp-to-card:hover .gp-to-sel-btn { opacity: 1; }\n        .gp-to-sel-btn:hover { background: #dbeafe; }\n        .gp-to-sel-btn.selected { background: #3b82f6; color: white; opacity: 1; }\n        .gp-to-grid.gp-sel-active .gp-to-sel-btn { opacity: 1; }\n        .gp-to-goto-btn {\n            position: absolute; bottom: 22px; left: 2px;\n            background: rgba(251, 146, 60, 0.92); color: white;\n            border: none; border-radius: 4px; width: 20px; height: 20px;\n            display: flex; align-items: center; justify-content: center;\n            font-size: 11px; cursor: pointer; z-index: 2; line-height: 1;\n            opacity: 0; transition: opacity 0.15s;\n        }\n        .gp-to-card:hover .gp-to-goto-btn { opacity: 1; }\n        .gp-to-goto-btn:hover { background: rgba(234, 88, 12, 0.95); }\n        .gp-to-card.gp-selected { border-color: #3b82f6; box-shadow: 0 0 0 2px #93c5fd; }\n\n        .gp-to-btn {\n            padding: 0.5rem 1rem; border-radius: 0.5rem; font-weight: 600; cursor: pointer; border: none;\n            display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;\n            transition: all 0.2s;\n        }\n        .gp-to-modal-panel .gp-to-btn { font-size: 0.75rem; }\n        .gp-to-btn-blue { background-color: #3b82f6; color: white; }\n        .gp-to-btn-blue:hover { background-color: #2563eb; }\n        .gp-to-btn-green { background-color: #10b981; color: white; }\n        .gp-to-btn-green:hover { background-color: #059669; }\n        .gp-to-btn-purple { background-color: #8b5cf6; color: white; }\n        .gp-to-btn-purple:hover { background-color: #7c3aed; }\n        .gp-to-btn-red { background-color: #ef4444; color: white; }\n        .gp-to-btn-gray { background-color: var(--color-gray-300, #e5e7eb); color: var(--color-gray-800, #374151); }\n        .gp-to-btn-orange { background-color: #f97316; color: white; }\n        .gp-to-btn-orange:hover { background-color: #ea580c; }\n        .gp-to-btn-cyan { background-color: #06b6d4; color: white; border: 2px solid transparent; }\n        .gp-to-btn-cyan:hover { background-color: #0891b2; }\n        .gp-to-btn-cyan.active { \n            background-color: #0e7490; \n            border: 2px solid #fbbf24;\n            box-shadow: 0 0 0 3px rgba(251, 191, 36, 0.3);\n        }\n\n        .gp-to-preview-overlay {\n            position: fixed;\n            pointer-events: none;\n            z-index: 9999;\n            opacity: 0.7;\n            transition: opacity 0.2s;\n        }\n    ",document.head.appendChild(g);const u=new Promise((n,o)=>{const r=indexedDB.open(e,3);r.onupgradeneeded=e=>{const n=e.target.result,o=e.target.transaction;let r;r=n.objectStoreNames.contains(t)?o.objectStore(t):n.createObjectStore(t,{keyPath:"id",autoIncrement:!0}),r.indexNames.contains("hash")||r.createIndex("hash","hash",{unique:!1}),r.indexNames.contains("templateId")||r.createIndex("templateId","templateId",{unique:!1})},r.onsuccess=e=>n(e.target.result),r.onerror=t=>{const n=new Error(`IndexedDB failed to open '${e}' v3: ${t.target.error}`);dbgPush(`dbPromise rejected — IndexedDB unavailable: ${n.message}`,{error:n,uiComponent:"Ghost Template Manager - IndexedDB init"}),o(n)}}),m={async add(e,n,o){const r=await u,a=await p(e),i=await async function(e){try{const t=y(await E(e));if(t&&t.cleanCanvas){const e=await new Promise(e=>t.cleanCanvas.toBlob(e,"image/png"));return await p(e)}return await p(e)}catch(t){return await p(e)}}(e);return new Promise((l,s)=>{const c=r.transaction(t,"readwrite"),d=c.objectStore(t),p=d.index("templateId").get(i);p.onsuccess=()=>{const t=p.result,r={blob:e,name:n||`Image_${Date.now()}`,date:Date.now(),hash:a,templateId:i,groupNoise:!!o};t?(r.id=t.id,d.put(r)):d.add(r)},c.oncomplete=()=>l(),c.onerror=()=>s(c.error)})},async getAll(){const e=await u;return new Promise((n,o)=>{const r=e.transaction(t,"readonly"),a=r.objectStore(t).getAll();a.onsuccess=()=>n(a.result.sort((e,t)=>t.date-e.date)),r.onerror=()=>{const e=new Error(`HistoryManager.getAll transaction failed: ${r.error}`);dbgPush(e.message,{error:e,uiComponent:"Ghost Template Manager - HistoryManager.getAll"}),o(e)}})},async delete(e){const n=await u;return new Promise(o=>{const r=n.transaction(t,"readwrite");r.objectStore(t).delete(e),r.oncomplete=()=>o()})},async clear(){const e=await u;return new Promise(n=>{const o=e.transaction(t,"readwrite");o.objectStore(t).clear(),o.oncomplete=()=>n()})}};function h(e){return new Promise((t,n)=>{const o=new FileReader;o.onloadend=()=>t(o.result.split(",")[1]),o.onerror=n,o.readAsDataURL(e)})}async function f(e){try{if(e.name,e.name.endsWith(".json")){const t=await e.text(),n=JSON.parse(t);if(!n.images||!Array.isArray(n.images))return void s("Error","Invalid JSON: 'images' array not found.");let o=0;for(const e of[...n.images].reverse()){const t=atob(e.imageData),n=new Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);const r=new Uint8Array(n),a=new Blob([r],{type:e.mimeType||"image/png"}),l=await m.getAll();l.some(t=>t.hash===e.hash)||(await m.add(a,e.name,!!e.groupNoise),o++),i(e.name)}return void s("Success",`Imported ${o} images from JSON bundle.`)}const t=await JSZip.loadAsync(e),n=t.file("metadata.json");if(!n)return void s("Error","Invalid ZIP: metadata.json not found.");const o=await n.async("text"),r=JSON.parse(o);let a=0;for(const e of r){const n=t.file(e.filename);if(n){const t=await n.async("blob");await m.add(t,e.name),a++}}return s("Success",`Imported ${a} images from ZIP.`),!0}catch(e){return console.error(e),s("Error","Failed to import file."),!1}}function b(e,t,o){const r=e.width,a=e.height,i=document.createElement("canvas");i.width=r,i.height=a+1;const l=i.getContext("2d",{willReadFrequently:!0});l.drawImage(e,0,1);const s=l.getImageData(0,0,r,1),c=s.data,d=t+n>>>0,p=o+n>>>0,g=Math.floor(r/5);for(let e=0;e<g;e++){const t=5*e*4;c[t]=71,c[t+1]=80,c[t+2]=88,c[t+3]=255,c[t+4]=d>>>24&255,c[t+5]=d>>>16&255,c[t+6]=0,c[t+7]=255,c[t+8]=d>>>8&255,c[t+9]=255&d,c[t+10]=0,c[t+11]=255,c[t+12]=p>>>24&255,c[t+13]=p>>>16&255,c[t+14]=0,c[t+15]=255,c[t+16]=p>>>8&255,c[t+17]=255&p,c[t+18]=0,c[t+19]=255}return l.putImageData(s,0,0),i}function y(e){const t=document.createElement("canvas");t.width=e.width,t.height=e.height;const o=t.getContext("2d",{willReadFrequently:!0});o.drawImage(e,0,0);const r=o.getImageData(0,0,e.width,1).data,a=new Map,i=new Map;let l=0;const s=Math.floor(e.width/5);for(let e=0;e<s;e++){const t=5*e*4;if(71===r[t]&&80===r[t+1]&&88===r[t+2]&&255===r[t+3]){const e=(r[t+4]<<24|r[t+5]<<16|r[t+8]<<8|r[t+9])>>>0,n=(r[t+12]<<24|r[t+13]<<16|r[t+16]<<8|r[t+17])>>>0;a.set(e,(a.get(e)||0)+1),i.set(n,(i.get(n)||0)+1),l++}}if(0===l)return null;const c=e=>[...e.entries()].reduce((e,t)=>t[1]>e[1]?t:e)[0],d=c(a)-n,p=c(i)-n,g=document.createElement("canvas");g.width=e.width,g.height=e.height-1;return g.getContext("2d").drawImage(t,0,1,e.width,e.height-1,0,0,e.width,e.height-1),{gridX:d,gridY:p,cleanCanvas:g}}let x=null,v=null;function w(){if(!a)return;if(!r)return;const e=localStorage.getItem("ghostImageData"),t=localStorage.getItem("ghostImageCoords");if(!t||!e)return;const n=JSON.parse(t);x&&x.src===e||(x=new Image,x.src=e);const o=x;if(!o.complete)return void(o.onload=()=>{w()});o.width,o.height;const i=document.getElementById("pixel-canvas");if(!i)return;a.width===i.width&&a.height===i.height||(a.width=i.width,a.height=i.height,i.width,i.height);const s=a.getContext("2d"),{width:c,height:d}=a;s.clearRect(0,0,c,d);const p=l("map"),g=l("turf");let u=l("gridSize")||25,m=l("halfSize")||u/2,h=l("offsetMetersX")||0,f=l("offsetMetersY")||0;if(!p||!g)return;if("function"!=typeof p.project)return;const b=[n.gridX*u-m+h,n.gridY*u+m+f],y=[(n.gridX+o.width-1)*u+m+h,(n.gridY-o.height+1)*u-m+f],v=p.project(g.toWgs84(b)),k=p.project(g.toWgs84(y)),E=v.x,C=v.y,S=k.x-E,T=k.y-C;E+S<0||E>c||C+T<0||C>d||(s.imageSmoothingEnabled=!1,s.drawImage(o,E,C,S,T))}async function k(){const e=localStorage.getItem("ghostImageCoords"),t=localStorage.getItem("ghostImageData");if(!e||!t)return;const n=JSON.parse(e),o=new Image;o.src=t,await new Promise(e=>o.onload=e);const r=document.createElement("canvas");r.width=o.width,r.height=o.height,r.getContext("2d").drawImage(o,0,0);b(r,n.gridX,n.gridY).toBlob(async e=>{if(e)try{await m.add(e,`Backup_${n.gridX}_${n.gridY}`,c()),s("Auto-Cache",`Ghost image position ${n.gridX}, ${n.gridY} auto-cached.`)}catch(e){dbgPush(`cacheCurrentGhostPosition HistoryManager.add failed: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:"Ghost Template Manager - Auto-Cache"}),console.error("Auto-Cache failed",e),s("Auto-Cache Error","Failed to auto-cache the image position.")}},"image/png")}async function E(e){return new Promise((t,n)=>{const o=new Image;o.onload=()=>t(o),o.onerror=n,o.src=URL.createObjectURL(e)})}async function C(e,t=!0,n=null,r=void 0){const a=document.getElementById("initiatePlaceGhostBtn");a&&(a.innerText="Analyzing...",a.disabled=!0);try{const a=y(await E(e));let i=e,d=null;if(a){a.gridX,a.gridY,d={gridX:a.gridX,gridY:a.gridY};const t=await new Promise((e,t)=>{const o=setTimeout(()=>{const e=new Error("cleanCanvas.toBlob timed out after 10s — canvas may be invalid or too large");dbgPush(e.message,{error:e,uiComponent:n||"Ghost Template Manager - processAndLoadImage"}),t(e)},1e4);a.cleanCanvas.toBlob(t=>{clearTimeout(o),e(t)},"image/png")});i=new File([t],e.name||"ghost.png",{type:"image/png"})}else i instanceof File||(i=new File([i],"ghost.png",{type:i.type||"image/png"}));if(t&&await m.add(e,e.name,c()),void 0!==r){const e=document.getElementById("groupNoiseToggle");e&&(e.checked=!!r)}const p=document.getElementById("ghostImageInput"),g=new DataTransfer;g.items.add(i),p.files=g.files,o=!0,p.dispatchEvent(new Event("change",{bubbles:!0})),o=!1,await new Promise(e=>setTimeout(e,100)),d&&function(e){localStorage.setItem("ghostImageCoords",JSON.stringify(e));let t=0;const n=setInterval(()=>{const o=document.getElementById("initiatePlaceGhostBtn"),r=!!localStorage.getItem("ghostImageData");if(o&&!o.disabled&&r){clearInterval(n);const t=l("initializeGhostFromStorage");if("function"==typeof t)t(),s("Auto-Place",`Position detected: ${e.gridX}, ${e.gridY}`);else{dbgPush(`initializeGhostFromStorage not found in page scope — template loaded but coordinates not applied (${e.gridX}, ${e.gridY})`,{uiComponent:"Ghost Template Manager - applyCoordinatesToGame"}),s("Warning",`Position set to ${e.gridX}, ${e.gridY} but auto-place failed. Click 'Place on Map' manually.`)}}if(++t>100){clearInterval(n);dbgPush(`applyCoordinatesToGame timed out after 10s waiting for place button + ghostImageData (coords: ${e.gridX}, ${e.gridY}).`,{uiComponent:"Ghost Template Manager - applyCoordinatesToGame"}),s("Warning",`Position set to ${e.gridX}, ${e.gridY} but image may still be loading. Try clicking 'Place on Map' manually.`)}},100)}(d)}catch(e){dbgPush(`processAndLoadImage failed: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:n||"Ghost Template Manager"}),console.error(e),s("Error","Failed to process image.")}finally{a&&(a.innerText="Place on Map")}}async function S(){const e=prompt("Enter Image or ZIP URL:");if(e)try{const t=await new Promise((t,n)=>{GM_xmlhttpRequest({method:"GET",url:e,responseType:"blob",onload:e=>{e.status>=200&&e.status<300?t(e.response):n(new Error(`HTTP ${e.status}: ${e.statusText}`))},onerror:e=>{n(new Error("Failed to fetch URL"))},ontimeout:()=>{n(new Error("Request timed out"))}})});if("application/zip"===t.type||"application/x-zip-compressed"===t.type||e.toLowerCase().endsWith(".zip"))return await f(t),void s("Success","Imported cache from URL!");if(!t.type.startsWith("image/"))throw new Error("Invalid image");C(new File([t],"url_upload.png",{type:t.type}),!1,"Ghost Template Manager - URL Upload")}catch(e){dbgPush(`handleUrlUpload failed: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:"Ghost Template Manager - URL Upload"}),console.error(e),s("Error","Could not load file from URL: "+e.message)}}async function T(){const e=localStorage.getItem("ghostImageData");if(!e)return void s("Error","No ghost image loaded.");const t=localStorage.getItem("ghostImageCoords"),n=new Image;n.src=e,await new Promise(e=>n.onload=e);const o=document.createElement("canvas");o.width=n.width,o.height=n.height,o.getContext("2d").drawImage(n,0,0);const r=c();if(t){const e=JSON.parse(t);b(o,e.gridX,e.gridY).toBlob(async t=>{if(t)try{await m.add(t,`Backup_${e.gridX}_${e.gridY}`,r),s("Success","Template saved to history!")}catch(e){dbgPush(`downloadWithPos (with coords) HistoryManager.add failed: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:"Ghost Template Manager - Save Pos button"}),console.error("Cache failed",e),s("Error","Failed to save template")}},"image/png")}else o.toBlob(async e=>{if(e)try{await m.add(e,`Image_${Date.now()}`,r),s("Success","Template saved to history!")}catch(e){dbgPush(`downloadWithPos (no coords) HistoryManager.add failed: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:"Ghost Template Manager - Save Pos button"}),console.error("Cache failed",e),s("Error","Failed to save template")}},"image/png")}async function P(){const e=document.getElementById("gp-history-modal");e&&e.remove();const t=await m.getAll(),n=document.createElement("div");n.id="gp-history-modal",n.className="gp-to-modal-overlay",n.innerHTML=`\n            <div class="gp-to-modal-panel">\n                <div class="gp-to-header">\n                    <div class="gp-to-header-row">\n                        <span class="gp-to-title">Image History (${t.length})</span>\n                        <button id="gp-close-hist" class="gp-to-btn gp-to-btn-gray">Close</button>\n                    </div>\n                    <div class="gp-to-header-row">\n                        <button id="gp-select-all" class="gp-to-btn gp-to-btn-blue">☑ Select All</button>\n                        <button id="gp-select-none" class="gp-to-btn gp-to-btn-gray">☐ Select None</button>\n                        <button id="gp-export-selected" class="gp-to-btn gp-to-btn-blue" disabled style="opacity:0.5">📤 Export Selected</button>\n                        <button id="gp-import-zip" class="gp-to-btn gp-to-btn-green">📁 Import JSON</button>\n                    </div>\n                </div>\n                <div class="gp-to-grid" id="gp-history-grid">\n                    ${0===t.length?'<p class="p-4 text-gray-500 col-span-full text-center">No images found.</p>':""}\n                </div>\n                <div style="border-top: 1px solid var(--color-gray-300, #eee); padding-top: 10px; display: flex; justify-content: flex-end;">\n                    <button id="gp-clear-all" class="gp-to-btn gp-to-btn-red">🗑️ Clear All</button>\n                </div>\n            </div>\n        `,document.body.appendChild(n);const o=n.querySelector("#gp-history-grid"),r=new Set;function a(){const e=n.querySelector("#gp-export-selected");e&&(r.size>0?(e.textContent=`📤 Export Selected (${r.size})`,e.disabled=!1,e.style.opacity="1",o.classList.add("gp-sel-active")):(e.textContent="📤 Export Selected",e.disabled=!0,e.style.opacity="0.5",o.classList.remove("gp-sel-active")))}t.forEach(e=>{const t=document.createElement("div");t.className="gp-to-card",t.dataset.imgId=e.id,t.innerHTML=`\n                <button class="gp-to-delete-btn" title="Delete">✖</button>\n                <button class="gp-to-sel-btn" title="Select for export">☐</button>\n                <button class="gp-to-goto-btn" title="Load &amp; Go To">🎯</button>\n                <img src="${URL.createObjectURL(e.blob)}" />\n                <div class="gp-to-card-footer">${new Date(e.date).toLocaleTimeString()} - ${e.name.substring(0,12)}</div>\n            `,t.onclick=async t=>{t.target.closest(".gp-to-delete-btn")||t.target.closest(".gp-to-sel-btn")||t.target.closest(".gp-to-goto-btn")||(await C(e.blob,!1,"Image History - card click",e.groupNoise),await m.add(e.blob,e.name,e.groupNoise),_settings.modernizeGhostPaletteBtns&&D(),n.remove())},t.querySelector(".gp-to-delete-btn").onclick=async()=>{await m.delete(e.id),r.delete(e.id),a(),t.remove()},t.querySelector(".gp-to-sel-btn").onclick=n=>{n.stopPropagation();const o=t.querySelector(".gp-to-sel-btn");r.has(e.id)?(r.delete(e.id),o.textContent="☐",o.classList.remove("selected"),t.classList.remove("gp-selected")):(r.add(e.id),o.textContent="☑",o.classList.add("selected"),t.classList.add("gp-selected")),a()},t.querySelector(".gp-to-goto-btn").onclick=async t=>{t.stopPropagation();let o=null;try{const t=y(await E(e.blob));t&&(o={gridX:t.gridX,gridY:t.gridY})}catch(e){dbgPush("Image History Load & Go To: failed to decode position from blob",{error:e,uiComponent:"Image History - Load & Go To"})}if(n.remove(),await C(e.blob,!1,"Image History - Load & Go To",e.groupNoise),await m.add(e.blob,e.name,e.groupNoise),_settings.modernizeGhostPaletteBtns&&D(),o){const e=l("goToGridLocation");"function"==typeof e&&e(o.gridX,o.gridY)}else s("Load & Go","No encoded coordinates found in this template.")},o.appendChild(t)}),n.querySelector("#gp-select-all").onclick=()=>{t.forEach(e=>{if(!r.has(e.id)){r.add(e.id);const t=o.querySelector(`[data-img-id="${e.id}"]`);t&&(t.querySelector(".gp-to-sel-btn").textContent="☑",t.querySelector(".gp-to-sel-btn").classList.add("selected"),t.classList.add("gp-selected"))}}),a()},n.querySelector("#gp-select-none").onclick=()=>{r.clear(),o.querySelectorAll(".gp-to-card").forEach(e=>{e.querySelector(".gp-to-sel-btn").textContent="☐",e.querySelector(".gp-to-sel-btn").classList.remove("selected"),e.classList.remove("gp-selected")}),a()},n.querySelector("#gp-export-selected").onclick=async()=>{await async function(e){if(0===e.size)return void s("Info","No images selected.");const t=(await m.getAll()).filter(t=>e.has(t.id));if(0!==t.length)try{const e={version:"3.5",exportDate:(new Date).toISOString(),images:[]};for(let n=0;n<t.length;n++){const o=t[n],r=await h(o.blob);e.images.push({id:o.id,name:o.name,date:o.date,hash:o.hash,templateId:o.templateId,imageData:r,mimeType:o.blob.type||"image/png",groupNoise:!!o.groupNoise})}const n=JSON.stringify(e),o=new Blob([n],{type:"application/json"}),r=URL.createObjectURL(o),a=document.createElement("a");a.href=r,a.download=`GeoPixels_Selected_${Date.now()}.json`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(r),s("Success",`Exported ${t.length} image${1!==t.length?"s":""}.`)}catch(e){dbgPush(`exportSelectedToJson failed: ${e&&e.message?e.message:String(e)}`,{error:e,uiComponent:"Image History - Export Selected"}),console.error("exportSelectedToJson failed:",e),s("Error","Failed to export: "+e.message)}else s("Info","No matching images found.")}(new Set(r))},n.querySelector("#gp-import-zip").onclick=()=>{const e=document.createElement("input");e.type="file",e.accept=".json, .zip, application/json, application/zip",e.onchange=async e=>{const t=e.target.files[0];t&&(await f(t),n.remove(),P())},e.click()},n.querySelector("#gp-clear-all").onclick=async()=>{confirm("Clear all cached images?")&&(await m.clear(),n.remove())},n.querySelector("#gp-close-hist").onclick=()=>n.remove()}window.cacheCurrentGhostPosition=k;const L="gpc-ghost-modal-pos";let M=null;function I(){return("function"!=typeof gpcMobileCompatibilityActive||!gpcMobileCompatibilityActive())&&!(!_settings.ghostTemplateManager||!_settings.rememberGhostModalPos)}function _(e){if(!e||!I())return!1;const t=function(){try{const e=JSON.parse(localStorage.getItem(L)||"null");return e&&"object"==typeof e?e:null}catch(e){return null}}();return!!t&&(e.dataset.gpcRememberRestoring="1",t.top&&(e.style.top=t.top),t.left&&(e.style.left=t.left),t.width&&(e.style.width=t.width),t.height&&(e.style.height=t.height),(t.top||t.left)&&(e.style.transform="none"),setTimeout(()=>{delete e.dataset.gpcRememberRestoring},120),!0)}function G(e){clearTimeout(M),M=setTimeout(()=>function(e){if(!e||!I()||e.dataset.gpcRememberRestoring)return;const t=e.getBoundingClientRect();if(!t.width||!t.height)return;const n="1"===e.dataset.gpcPreviewCollapsed&&e.dataset.gpcExpandedWidth?e.dataset.gpcExpandedWidth:e.style.width||`${Math.round(t.width)}px`;localStorage.setItem(L,JSON.stringify({top:e.style.top||`${Math.round(t.top)}px`,left:e.style.left||`${Math.round(t.left)}px`,width:n,height:e.style.height||`${Math.round(t.height)}px`}))}(e),350)}function R(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;if(e.__gpcGhostModalRememberPatchQueued)return;e.__gpcGhostModalRememberPatchQueued=!0;const t=Date.now();!function n(){if("function"!=typeof e.toggleGhostModal)return Date.now()-t>=15e3?(dbgPush("Ghost Template Manager: gave up after 15s -- w.toggleGhostModal was never found, so the ghost modal position could not be patched for remembering.",{uiComponent:"Ghost Template Manager"}),void console.error("[GeoPixelcons++] Ghost Template Manager: never found w.toggleGhostModal to patch for remembering ghost modal position.")):void setTimeout(n,500);if(e.toggleGhostModal.__gpcRememberPatched)return;dbgPush("Ghost Template Manager: w.toggleGhostModal found "+(Date.now()-t)+"ms after watching started -- patching now.",{uiComponent:"Ghost Template Manager"});const o=e.toggleGhostModal;e.toggleGhostModal=function(...e){const t=o.apply(this,e);if(!1!==e[0]&&I()){const e=document.getElementById("ghostImageModal");N(e),[0,60,180].forEach(t=>setTimeout(()=>{_(e)},t))}return t},e.toggleGhostModal.__gpcRememberPatched=!0}()}function N(e){e&&I()&&(R(),e.dataset.gpcRememberObserver||(e.dataset.gpcRememberObserver="1",new MutationObserver(()=>G(e)).observe(e,{attributes:!0,attributeFilter:["style"]})),[0,80,240].forEach(t=>setTimeout(()=>_(e),t)))}function A(){const e=document.getElementById("ghostImageModal");if(!e)return;const t=e.querySelector(".flex.flex-wrap.items-center.justify-center.gap-3");if(!t||t.dataset.gpInjected)return;t.dataset.gpInjected="true",R(),N(e),function(){if(document.documentElement.dataset.gpcGhostPlacementAutoHide)return;document.documentElement.dataset.gpcGhostPlacementAutoHide="1";const e=document.createElement("script");e.textContent="(function(){\nif(window.__gpcToolModeEventPatch)return;\nwindow.__gpcToolModeEventPatch=true;\nvar watchStartedAt=Date.now();\nfunction patch(){\n    if(typeof setToolMode!=='function'){\n        if(Date.now()-watchStartedAt>=15000){\n            if(window.__gpcDebugBridge&&window.__gpcDebugBridge.isEnabled()){\n                window.__gpcDebugBridge.push('Ghost Template Manager: gave up after 15s -- setToolMode was never found, so the toolModeChanged event patch could not be applied.',{uiComponent:'Ghost Template Manager'});\n            }\n            console.error('[GeoPixelcons++] Ghost Template Manager: never found setToolMode to patch for the toolModeChanged event.');\n            return;\n        }\n        setTimeout(patch,500);\n        return;\n    }\n    if(setToolMode.__gpcToolModeEventPatched)return;\n    if(window.__gpcDebugBridge&&window.__gpcDebugBridge.isEnabled()){\n        window.__gpcDebugBridge.push('Ghost Template Manager: setToolMode found '+(Date.now()-watchStartedAt)+'ms after watching started -- patching now.',{uiComponent:'Ghost Template Manager'});\n    }\n    var original=setToolMode;\n    window.setToolMode=function(tool){\n        var result=original.apply(this,arguments);\n        document.dispatchEvent(new CustomEvent('gpc:toolModeChanged',{detail:{tool:tool}}));\n        return result;\n    };\n    window.setToolMode.__gpcToolModeEventPatched=true;\n}\npatch();\n})();",document.head.appendChild(e),e.remove();let t=null,n=null;const o=()=>{t&&(clearTimeout(n),t.classList.remove("hidden"),delete t.dataset.gpcHiddenForPlacement,t=null)};document.addEventListener("click",e=>{const r=e.target&&e.target.closest?e.target.closest("#initiatePlaceGhostBtn"):null;r&&e.isTrusted&&!r.disabled&&setTimeout(()=>{const e=document.getElementById("ghostImageModal");e&&(t=e,e.dataset.gpcHiddenForPlacement="1",e.classList.add("hidden"),clearTimeout(n),n=setTimeout(o,6e4))},0)},!0),document.addEventListener("gpc:toolModeChanged",e=>{t&&(e.detail&&"ghostPlacement"===e.detail.tool||o())})}();const n=document.getElementById("hexDisplay");n&&n.classList.remove("hidden"),function(){const e=document.getElementById("ghostImageInput");e&&(e.setAttribute("accept","image/png, image/jpeg, image/webp, image/gif, application/zip, .zip"),e.addEventListener("change",async t=>{if(o)return;const n=t.target.files[0];if(n){if(t.stopImmediatePropagation(),t.preventDefault(),"application/zip"===n.type||"application/x-zip-compressed"===n.type||n.name.toLowerCase().endsWith(".zip"))return void(await f(n)&&(e.value=""));C(n,!1,"Ghost Image Input - file picker")}},!0))}();const i=document.createElement("button");i.innerHTML="🔗 URL",i.className="gp-to-btn gp-to-btn-blue shadow",i.title="Load from URL (Image or ZIP)",i.onclick=S;const c=document.createElement("button");c.innerHTML="📂 File",c.className="gp-to-btn gp-to-btn-green shadow",c.title="Upload Image or ZIP",c.onclick=()=>document.getElementById("ghostImageInput").click();const p=document.createElement("button");p.innerHTML="📜 History",p.className="gp-to-btn gp-to-btn-purple shadow",p.onclick=P;const g=document.createElement("button");g.innerHTML="💾 Save",g.className="gp-to-btn gp-to-btn-gray shadow",g.onclick=T;const u=document.createElement("button");u.innerHTML="👁️ Preview",u.className="gp-to-btn gp-to-btn-cyan shadow",u.title="Toggle image preview overlay",u.onclick=()=>function(e){if("undefined"!=typeof window&&Object.keys(window).filter(e=>e.includes("map")||e.includes("turf")).slice(0,10),"undefined"!=typeof unsafeWindow&&Object.keys(unsafeWindow).filter(e=>e.includes("map")||e.includes("turf")).slice(0,10),r){if(a&&a.parentNode&&a.parentNode.removeChild(a),v){const e=l("map");if(e&&"function"==typeof e.off)try{e.off("move",v),e.off("zoom",v),e.off("rotate",v)}catch(e){}}a=null,x=null,v=null,r=!1,e.innerHTML="👁️ Preview",e.classList.remove("active")}else{const t=localStorage.getItem("ghostImageData"),n=localStorage.getItem("ghostImageCoords");if(!t||!n)return void s("Error","No ghost image on map to preview.");const o=document.getElementById("pixel-canvas");if(!o)return void s("Error","Pixel canvas not found. Make sure you're on the map view.");o.width,o.height;const i=l("map");if(!i)return void s("Error","Map not initialized yet. Please wait a moment and try again.");if(i.project,HTMLElement,i.constructor&&i.constructor.name,"function"!=typeof i.project)return i.project,Object.keys(i).slice(0,20),i.constructor&&i.constructor.name,void s("Error","Map projection not available. Page may not be fully loaded.");const c=l("turf");if(!c)return void s("Error","Turf.js library not loaded. Page may not be fully loaded.");if(c.toWgs84,"function"!=typeof c.toWgs84)return c.toWgs84,Object.keys(c).slice(0,20),void s("Error","Map projection not available. Page may not be fully loaded.");a=document.createElement("canvas"),a.id="gp-preview-canvas",a.className="pixel-perfect",a.width=o.width,a.height=o.height,a.style.cssText="display: block; image-rendering: pixelated; position: absolute; top: 0; left: 0; pointer-events: none; z-index: 5;";const d=i.getContainer?i.getContainer():document.getElementById("map");d?d.appendChild(a):document.body.appendChild(a),r=!0,e.innerHTML="👁️ Hide Preview",e.classList.add("active"),v=()=>{w()};try{i.on("move",v),i.on("zoom",v),i.on("rotate",v)}catch(e){}w()}}(u);const m=document.createElement("button");m.innerHTML="🎯 Go To",m.className="gp-to-btn gp-to-btn-orange shadow",m.title="Teleport to template location",m.onclick=d,t.prepend(m),t.prepend(u),t.prepend(g),t.prepend(p),t.prepend(c),t.prepend(i)}if(new MutationObserver(()=>A()).observe(document.body,{childList:!0,subtree:!0}),document.querySelector('label[for="ghostImageInput"]')?.classList.add("hidden"),_settings.modernizeGhostPaletteBtns){const j=["Toggle All","Set Palette","Match My Palette","Bulk Purchase Colors","Enable Only Owned Ghost Colors","Get Ghost Colors","Get Enabled Ghost Colors","Set Enabled Ghost Colors","Enable filtered","Enable owned and filtered"],H={"Toggle All":{bg:"#bfdbfe",hover:"#93c5fd",fg:"#1e3a8a"},"Set Palette":{bg:"#bbf7d0",hover:"#86efac",fg:"#14532d"},"Match My Palette":{bg:"#bbf7d0",hover:"#86efac",fg:"#14532d"},"Bulk Purchase Colors":{bg:"#e9d5ff",hover:"#d8b4fe",fg:"#581c87"},"Enable Only Owned Ghost Colors":{bg:"#fbcfe8",hover:"#f9a8d4",fg:"#831843"},"Get Ghost Colors":{bg:"#fbcfe8",hover:"#f9a8d4",fg:"#831843"},"Get Enabled Ghost Colors":{bg:"#fbcfe8",hover:"#f9a8d4",fg:"#831843"},"Set Enabled Ghost Colors":{bg:"#fbcfe8",hover:"#f9a8d4",fg:"#831843"},"Enable filtered":{bg:"#fed7aa",hover:"#fdba74",fg:"#7c2d12"}};function F(e,t){if(e.dataset.gpcStyled)return;e.dataset.gpcStyled="1",e.className="";const n=H[t]||{bg:"#e2e8f0",hover:"#cbd5e1",fg:"#334155"};Object.assign(e.style,{fontSize:"12px",fontWeight:"600",padding:"6px 8px",borderRadius:"6px",border:"none",cursor:"pointer",background:n.bg,color:n.fg,transition:"background 0.15s",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",lineHeight:"1.3",boxShadow:"none",width:"100%",textAlign:"center"}),e.title||(e.title=t),e.addEventListener("mouseenter",()=>{e.style.background=n.hover}),e.addEventListener("mouseleave",()=>{e.style.background=n.bg})}if(H["Enable owned and filtered"]=H["Enable filtered"],!document.getElementById("gpc-modern-gp-btn-style")){const U=document.createElement("style");U.id="gpc-modern-gp-btn-style",U.textContent="\n                [data-gp-injected] button, #gpc-modern-gp-grid button {\n                    font-size:12px!important; font-weight:600!important;\n                    padding:6px 8px!important; border-radius:6px!important;\n                    box-shadow:none!important; width:100%!important;\n                    white-space:nowrap!important; overflow:hidden!important;\n                    text-overflow:ellipsis!important; line-height:1.3!important;\n                    text-align:center!important;\n                }\n                .gp-to-btn-blue   { background-color:#bfdbfe!important; color:#1e3a8a!important; }\n                .gp-to-btn-blue:hover { background-color:#93c5fd!important; }\n                .gp-to-btn-green  { background-color:#bbf7d0!important; color:#14532d!important; }\n                .gp-to-btn-green:hover { background-color:#86efac!important; }\n                .gp-to-btn-purple { background-color:#e9d5ff!important; color:#581c87!important; }\n                .gp-to-btn-purple:hover { background-color:#d8b4fe!important; }\n                .gp-to-btn-gray   { background-color:#f1f5f9!important; color:#475569!important; }\n                .gp-to-btn-gray:hover { background-color:#e2e8f0!important; }\n                .gp-to-btn-orange { background-color:#fed7aa!important; color:#7c2d12!important; }\n                .gp-to-btn-orange:hover { background-color:#fdba74!important; }\n                .gp-to-btn-cyan   { background-color:#a5f3fc!important; color:#164e63!important; border:none!important; }\n                .gp-to-btn-cyan:hover { background-color:#67e8f9!important; }\n                .gp-to-btn-cyan.active { background-color:#0e7490!important; color:#ecfeff!important; border:2px solid #fbbf24!important; box-shadow:0 0 0 3px rgba(251,191,36,.3)!important; }\n                .gp-to-btn-red    { background-color:#fecaca!important; color:#991b1b!important; }\n                .gp-to-btn-red:hover { background-color:#fca5a5!important; }\n                #initiatePlaceGhostBtn { background-color:#bbf7d0!important; color:#14532d!important; }\n                #initiatePlaceGhostBtn:hover:not(:disabled) { background-color:#86efac!important; }\n                #clearGhostImageBtn    { background-color:#fecaca!important; color:#991b1b!important; }\n                #clearGhostImageBtn:hover:not(:disabled) { background-color:#fca5a5!important; }\n                #_z_dock_btn { background-color:#c7d2fe!important; color:#312e81!important; }\n                #_z_dock_btn:hover { background-color:#a5b4fc!important; }\n            ",document.head.appendChild(U)}function X(){const e=document.getElementById("ghostColorPaletteContainer");if(!e)return;e.querySelectorAll("button[data-expanded]").forEach(e=>{let t=e.nextElementSibling;for(;t;)"BUTTON"===t.tagName&&t.style.removeProperty("display"),t=t.nextElementSibling;e.remove()});const t=Array.from(e.querySelectorAll("button")).filter(e=>!e.closest("#ghostColorPalette")&&(!e.closest(".color-search-container")&&"gpc-modern-btn-grid"!==e.id)),n=t.map(e=>e.textContent.trim()).sort().join("|");if(e.dataset.gpcSig===n)return;e.dataset.gpcSig=n;const o=new Map;t.forEach(e=>o.set(e.textContent.trim(),e));let r=document.getElementById("gpc-modern-btn-grid");if(!r){r=document.createElement("div"),r.id="gpc-modern-btn-grid",r.style.cssText="display:grid;grid-template-columns:1fr 1fr;gap:6px;padding:0 0 8px 0;";const t=e.querySelector("h3");t?t.insertAdjacentElement("afterend",r):e.prepend(r)}j.forEach(e=>{const t=o.get(e);t&&(F(t,e),r.appendChild(t))});const a=e.querySelector(".gpc-filtered-row");a&&!a.querySelector("button")&&(a.style.display="none"),Array.from(e.querySelectorAll(":scope > div")).forEach(e=>{e.id||e.closest(".color-search-container")||e.closest(".gpc-filtered-row")||e.querySelector("button, input, label, select")||e.remove()})}function q(){const e=document.querySelector('[data-gp-injected="true"]');if(!e)return;const t=Array.from(e.querySelectorAll("button"));if(!t.length)return;const n=t.map(e=>(e.id||"")+e.textContent.trim()).sort().join("|");if(e.dataset.gpcGpSig===n)return;e.dataset.gpcGpSig=n;let o=document.getElementById("gpc-modern-gp-grid");o||(o=document.createElement("div"),o.id="gpc-modern-gp-grid",o.style.cssText="display:grid;grid-template-columns:repeat(4,1fr);gap:6px;padding:0 0 8px 0;",e.parentNode.insertBefore(o,e)),t.forEach(e=>o.appendChild(e)),e.style.display="none"}new MutationObserver(()=>{X(),q(),O()}).observe(document.body,{childList:!0,subtree:!0}),X(),q(),O()}let z=[],B=10;function O(){const e=document.getElementById("ghostImageModal");if(!e||e.dataset.gpcModernModal)return;if(!e.querySelector("[data-gp-injected]"))return;e.dataset.gpcModernModal="1";const t="function"==typeof gpcMobileCompatibilityActive&&gpcMobileCompatibilityActive();if(!document.getElementById("gpc-modal-layout-style")){const e=document.createElement("style");e.id="gpc-modal-layout-style",e.textContent="\n                #gpc-modal-left {\n                    flex: 1 1 0;\n                    min-width: 0;\n                    display: flex;\n                    flex-direction: column;\n                    overflow: hidden;\n                    transition: width 0.22s ease, flex-basis 0.22s ease, opacity 0.18s ease;\n                }\n                #gpc-modal-left-scroll {\n                    flex: 1 1 0;\n                    min-height: 0;\n                    overflow-y: auto;\n                    padding: 10px 14px;\n                }\n                #gpc-modal-right {\n                    width: 280px;\n                    flex-shrink: 0;\n                    display: flex;\n                    flex-direction: column;\n                    overflow: hidden;\n                    transition: width 0.22s ease, opacity 0.18s ease;\n                }\n                #ghostImageModal.gpc-preview-animating {\n                    transition: width 0.22s ease;\n                    overflow: hidden;\n                }\n                #ghostImageModal.gpc-preview-collapsed {\n                    width: var(--gpc-collapsed-width) !important;\n                }\n                #ghostImageModal.gpc-preview-expanded {\n                    width: var(--gpc-expanded-width) !important;\n                }\n                #gpc-modal-right.gpc-collapsed {\n                    width: 34px !important;\n                    opacity: 0.95;\n                }\n                #gpc-modal-right.gpc-collapsed #gpc-modal-right-content {\n                    opacity: 0;\n                    pointer-events: none;\n                }\n                #gpc-modal-right.gpc-collapsed .gpc-collapse-label { display: none !important; }\n                #gpc-modal-right-content {\n                    flex: 1 1 0;\n                    min-height: 0;\n                    display: flex;\n                    flex-direction: column;\n                    overflow: hidden;\n                    opacity: 1;\n                    transition: opacity 0.12s ease;\n                }\n                #gpc-recent-grid {\n                    display: grid;\n                    grid-template-columns: repeat(5, minmax(0, 1fr));\n                    grid-auto-rows: var(--gpc-recent-cell-size, 48px);\n                    gap: 3px;\n                    padding: 4px 8px 8px;\n                    overflow-y: auto;\n                    overflow-x: hidden;\n                    flex: 1 1 0;\n                    min-height: 0;\n                    align-content: start;\n                    justify-items: stretch;\n                }\n                /* Remove the palette's hardcoded max-height so it expands with content */\n                #ghostColorPalette {\n                    max-height: none !important;\n                    overflow-y: visible !important;\n                }\n                /* Action buttons grid inside the right panel — force 2-col minimum */\n                #gpc-modal-right #gpc-modern-gp-grid {\n                    display: grid !important;\n                    grid-template-columns: repeat(2, 1fr) !important;\n                    gap: 4px !important;\n                    padding: 4px 0 !important;\n                }\n                /* Edge drag strips */\n                .gpc-edge-drag {\n                    position: absolute;\n                    z-index: 102;\n                    pointer-events: auto;\n                    cursor: grab;\n                }\n                .gpc-edge-drag:active { cursor: grabbing; }\n                .gpc-edge-drag.top    { top: 0;    left: 12px; right: 12px; height: 12px; }\n                .gpc-edge-drag.bottom { bottom: 0; left: 12px; right: 30px; height: 12px; }\n                .gpc-edge-drag.left   { left: 0;   top: 12px;  bottom: 12px; width: 12px; }\n                /* .right is a child of #gpc-modal-right, not modal — see JS below */\n                .gpc-edge-drag.right  { right: 0;  top: 0; bottom: 30px; width: 12px; z-index: 50; }\n                /* Panel splitter — left edge of #gpc-modal-right, drag to resize the split */\n                .gpc-panel-splitter {\n                    position: absolute;\n                    left: -4px; top: 0; bottom: 0;\n                    width: 8px;\n                    cursor: ew-resize;\n                    z-index: 106;\n                    background: transparent;\n                    transition: background 0.15s;\n                }\n                .gpc-panel-splitter:hover,\n                .gpc-panel-splitter.gpc-ps-dragging {\n                    background: rgba(99,102,241,0.25);\n                }\n                #gpc-modal-right.gpc-collapsed .gpc-panel-splitter { display: none; }\n                /* Horizontal preview-height resize strip */\n                .gpc-preview-hresize {\n                    flex-shrink: 0;\n                    height: 8px;\n                    cursor: ns-resize;\n                    position: relative;\n                    z-index: 10;\n                    background: transparent;\n                    transition: background 0.15s;\n                }\n                .gpc-preview-hresize::after {\n                    content: '';\n                    position: absolute;\n                    left: 12px; right: 12px;\n                    top: 50%; transform: translateY(-50%);\n                    height: 1px;\n                    background: var(--color-gray-200, #e5e7eb);\n                    transition: background 0.15s;\n                }\n                .gpc-preview-hresize:hover,\n                .gpc-preview-hresize.gpc-ps-dragging {\n                    background: rgba(99,102,241,0.15);\n                }\n                .gpc-preview-hresize:hover::after,\n                .gpc-preview-hresize.gpc-ps-dragging::after {\n                    background: rgba(99,102,241,0.6);\n                }\n                /* SE resize grip — bottom-right corner only, like guild modal */\n                .gpc-resize-se {\n                    position: absolute;\n                    bottom: 0; right: 0;\n                    width: 20px; height: 20px;\n                    cursor: nwse-resize;\n                    z-index: 101;\n                    border-radius: 0 0 1rem 0;\n                    background: linear-gradient(135deg, transparent 50%, #94a3b8 50%);\n                    opacity: 0.5;\n                    pointer-events: auto;\n                    transition: opacity 0.15s;\n                }\n                .gpc-resize-se:hover { opacity: 1; }\n                #ghostImageModal.gpc-mobile-compat {\n                    width: calc(100vw - 12px) !important;\n                    height: calc(100dvh - 12px) !important;\n                    min-width: 0 !important;\n                    min-height: 0 !important;\n                    max-width: none !important;\n                    max-height: none !important;\n                    left: 6px !important;\n                    top: 6px !important;\n                    transform: none !important;\n                }\n                #ghostImageModal.gpc-mobile-compat #gpc-modal-left {\n                    flex: 1 1 auto;\n                    width: calc(100% - 34px);\n                    min-width: 0;\n                }\n                #ghostImageModal.gpc-mobile-compat #gpc-modal-right {\n                    width: 34px !important;\n                    flex: 0 0 34px;\n                }\n                #ghostImageModal.gpc-mobile-compat.gpc-mobile-preview-open #gpc-modal-left {\n                    display: none !important;\n                }\n                #ghostImageModal.gpc-mobile-compat.gpc-mobile-preview-open #gpc-modal-right {\n                    width: 100% !important;\n                    flex: 1 1 auto;\n                }\n                #ghostImageModal.gpc-mobile-compat.gpc-mobile-preview-open #gpc-modal-right-content {\n                    opacity: 1;\n                    pointer-events: auto;\n                }\n                #ghostImageModal.gpc-mobile-compat .gpc-edge-drag,\n                #ghostImageModal.gpc-mobile-compat .gpc-panel-splitter,\n                #ghostImageModal.gpc-mobile-compat .gpc-preview-hresize,\n                #ghostImageModal.gpc-mobile-compat .gpc-resize-se {\n                    display: none !important;\n                }\n                #ghostImageModal.gpc-mobile-compat #gpc-modern-gp-grid {\n                    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;\n                }\n            ",document.head.appendChild(e)}["w-[90%]","max-w-lg","p-6","max-h-[90vh]","cursor-move"].forEach(t=>e.classList.remove(t)),Object.assign(e.style,{width:"min(92vw, 800px)",height:"75vh",maxWidth:"none",maxHeight:"none",minWidth:"480px",minHeight:"320px",flexDirection:"row",gap:"0",padding:"0",alignItems:"stretch"}),t&&(e.classList.add("gpc-mobile-compat","gpc-mobile-controls-open"),Object.assign(e.style,{width:"calc(100vw - 12px)",height:"calc(100dvh - 12px)",minWidth:"0",minHeight:"0",left:"6px",top:"6px",transform:"none"}));const n=e.querySelector('button[onclick*="toggleGhostModal"]'),o=e.querySelector("h2"),r=e.querySelector(".flex-grow.overflow-y-auto, .overflow-y-auto");let a=null;if(r){const e=r.querySelector("#ghostPreviewImage");a=e?e.parentElement:r.querySelector('[class*="border-dashed"]')}a?.parentNode&&a.parentNode.removeChild(a);const i=r?r.querySelector("#gpc-modern-gp-grid")||r.querySelector("[data-gp-injected]"):null;i?.parentNode&&i.parentNode.removeChild(i);const l=r?r.querySelector("[data-gp-injected]"):null;l?.parentNode&&l.parentNode.removeChild(l);const s=document.createElement("div");s.id="gpc-modal-left";const c=document.createElement("div");c.id="gpc-modal-left-header",c.className="flex items-center justify-between px-4 py-3 border-b border-gray-100 dark:border-gray-700 cursor-move select-none flex-shrink-0 bg-white dark:bg-gray-800",t&&c.classList.remove("cursor-move");const d=document.createElement("div");d.className="flex items-center gap-2 min-w-0",o&&(o.style.cssText="margin:0;font-size:1.05rem;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;",d.appendChild(o)),c.appendChild(d);const p=n||(()=>{const e=document.createElement("button");return e.innerHTML="&#10005;",e.onclick=()=>{"function"==typeof toggleGhostModal&&toggleGhostModal(!1)},e})();function g(t){if(0!==t.button||t.target.closest("button"))return;t.preventDefault();const n=e.getBoundingClientRect();let o=t.clientX,r=t.clientY,a=n.left,i=n.top;const l=document.body.style.cursor;document.body.style.cursor="grabbing";const s=t=>{e.style.left=a+t.clientX-o+"px",e.style.top=i+t.clientY-r+"px",e.style.transform="none"},c=()=>{document.body.style.cursor=l,document.removeEventListener("mousemove",s,!0),document.removeEventListener("mouseup",c,!0)};document.addEventListener("mousemove",s,!0),document.addEventListener("mouseup",c,!0)}p.className="flex-shrink-0 rounded-full cursor-pointer flex items-center justify-center hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100",p.style.cssText="position:static;border:none;background:transparent;width:2rem;height:2rem;font-size:1.1rem;line-height:1;flex-shrink:0;",c.appendChild(p),s.appendChild(c),c.style.cursor=t?"default":"grab",t||c.addEventListener("mousedown",g),r&&(r.id="gpc-modal-left-scroll",r.className=r.className.replace(/\bflex-grow\b|\boverflow-y-auto\b|\bpr-\S+\b|\b-mr-\S+\b/g,"").trim(),s.appendChild(r));const u=document.createElement("div");u.id="gpc-modal-right",u.style.position="relative",u.className="border-l border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800";const m=document.createElement("div");m.className="flex items-center gap-1 px-2 border-b border-gray-200 dark:border-gray-700 flex-shrink-0 select-none",m.style.minHeight="34px";const h=document.createElement("button");h.className="rounded-full bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 text-gray-600 dark:text-gray-300 flex-shrink-0 flex items-center justify-center border-none cursor-pointer",h.style.cssText="width:20px;height:20px;font-size:8px;padding:0;line-height:1;",h.textContent="◀",h.title="Collapse preview";const f=document.createElement("span");f.className="gpc-collapse-label text-xs font-bold text-gray-500 dark:text-gray-400",f.textContent="🖼 Preview",m.appendChild(h),m.appendChild(f),u.appendChild(m);const b=document.createElement("div");if(b.id="gpc-modal-right-content",a){a.className="",a.style.cssText="flex-shrink:0;margin:10px;border-radius:8px;overflow:hidden;background:var(--color-gray-100,#f3f4f6);border:1px solid var(--color-gray-200,#e5e7eb);display:flex;align-items:center;justify-content:center;aspect-ratio:4/3;max-height:340px;position:relative;";const e=a.querySelector("#ghostPreviewImage");e&&(e.style.cssText="position:absolute;inset:0;width:100%;height:100%;object-fit:contain;image-rendering:pixelated;image-rendering:crisp-edges;");const n=a.querySelector("#ghostPreviewText");if(n&&(n.className="text-gray-400 dark:text-gray-500 text-xs text-center",n.style.cssText="position:relative;z-index:1;padding:8px;"),b.appendChild(a),!t){const e=document.createElement("div");e.className="gpc-preview-hresize",e.title="Drag to resize preview height",e.addEventListener("mousedown",t=>{if(0!==t.button)return;t.preventDefault(),t.stopPropagation();const n=t.clientY,o=a.getBoundingClientRect().height;a.style.height=o+"px",a.style.maxHeight="none",e.classList.add("gpc-ps-dragging"),document.body.style.cursor="ns-resize";const r=e=>{const t=Math.max(60,o+e.clientY-n);a.style.height=t+"px"},i=()=>{e.classList.remove("gpc-ps-dragging"),document.body.style.cursor="",document.removeEventListener("mousemove",r,!0),document.removeEventListener("mouseup",i,!0)};document.addEventListener("mousemove",r,!0),document.addEventListener("mouseup",i,!0)}),b.appendChild(e)}}if(i){const e=document.createElement("div");e.className="flex-shrink-0 px-2 py-2",i.style.display="",e.appendChild(i),b.appendChild(e)}const y=document.createElement("div");y.className="border-t border-gray-200 dark:border-gray-700",y.style.cssText="flex:1 1 0;min-height:0;display:flex;flex-direction:column;overflow:hidden;";const x=document.createElement("div");x.className="flex items-center px-2 gap-1 select-none cursor-pointer flex-shrink-0 text-xs font-bold text-gray-500 dark:text-gray-400",x.style.minHeight="28px";const v=document.createElement("span");v.textContent="▾",v.style.cssText="transition:transform 0.15s;flex-shrink:0;";const w=document.createElement("span");w.textContent="🕐 Recent";const k=document.createElement("button");k.textContent="↺",k.title="Refresh",k.className="ml-auto border-none bg-transparent cursor-pointer text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300",k.style.cssText="font-size:13px;padding:0 2px;line-height:1;",k.addEventListener("click",e=>{e.stopPropagation(),D()}),x.appendChild(v),x.appendChild(w),x.appendChild(k);const E=document.createElement("div");E.id="gpc-recent-grid";const C=()=>{const e=E.clientWidth;if(!e)return;const t=getComputedStyle(E),n=parseFloat(t.paddingLeft||"0")+parseFloat(t.paddingRight||"0"),o=parseFloat(t.columnGap||t.gap||"0")||0,r=Math.max(24,Math.floor((e-n-4*o)/5));E.style.setProperty("--gpc-recent-cell-size",`${r}px`)};"undefined"!=typeof ResizeObserver?new ResizeObserver(C).observe(E):window.addEventListener("resize",C),setTimeout(C,0);let S=!0;x.addEventListener("click",()=>{S=!S,E.style.display=S?"grid":"none",v.style.transform=S?"":"rotate(-90deg)"}),y.appendChild(x),y.appendChild(E),b.appendChild(y),u.appendChild(b);let T=t,P=280;t&&(u.classList.add("gpc-collapsed"),h.textContent="▶",h.title="Show preview"),h.addEventListener("click",n=>{if(n.stopPropagation(),T=!T,t)return u.classList.toggle("gpc-collapsed",T),e.classList.toggle("gpc-mobile-controls-open",T),e.classList.toggle("gpc-mobile-preview-open",!T),h.textContent=T?"▶":"◀",void(h.title=T?"Show preview":"Show controls");if(T){e.classList.remove("gpc-preview-expanded");const t=Math.round(e.getBoundingClientRect().width),n=Math.round(u.getBoundingClientRect().width);n>38&&(P=n);const o=t-n,r=Math.max(320,o+34);e.style.setProperty("--gpc-expanded-width",`${t}px`),e.style.setProperty("--gpc-collapsed-width",`${r}px`),e.classList.add("gpc-preview-animating","gpc-preview-collapsed"),u.classList.add("gpc-collapsed"),e.dataset.gpcExpandedWidth=`${t}px`,e.dataset.gpcPreviewCollapsed="1"}else{e.classList.remove("gpc-preview-collapsed");const t=Math.round(e.getBoundingClientRect().width)-34,n=Math.max(480,t+P);u.style.width=`${P}px`,e.style.setProperty("--gpc-expanded-width",`${n}px`),e.style.removeProperty("--gpc-collapsed-width"),e.classList.add("gpc-preview-animating","gpc-preview-expanded"),u.classList.remove("gpc-collapsed"),e.dataset.gpcExpandedWidth=`${n}px`,e.dataset.gpcPreviewCollapsed="0"}h.textContent=T?"▶":"◀",h.title=T?"Expand preview":"Collapse preview"}),e.addEventListener("transitionend",t=>{t.target===e&&"width"===t.propertyName&&(T?e.style.width=e.style.getPropertyValue("--gpc-collapsed-width"):(e.classList.remove("gpc-preview-expanded"),e.style.width=e.style.getPropertyValue("--gpc-expanded-width")||"min(92vw, 800px)"),e.classList.remove("gpc-preview-animating"))});const L=document.createElement("div");L.className="gpc-resize-se";let M=null;for(t||L.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation();const n=e.getBoundingClientRect(),o=u.getBoundingClientRect();M={mx:t.clientX,my:t.clientY,w:n.width,h:n.height,rightRatio:T?null:o.width/Math.max(1,n.width),rightTransition:u.style.transition},e.classList.remove("gpc-preview-animating","gpc-preview-expanded"),e.style.userSelect="none",u.style.transition="none";const r=t=>{if(!M)return;const n=T?320:480,o=Math.max(n,M.w+t.clientX-M.mx),r=o+"px";if(e.style.width=r,!T&&M.rightRatio){const e=Math.max(34,Math.floor(.05*o)),t=Math.max(e,Math.floor(.95*o)),n=Math.min(Math.max(e,Math.round(o*M.rightRatio)),t);u.style.width=n+"px",P=n}T?e.style.setProperty("--gpc-collapsed-width",r):(e.style.setProperty("--gpc-expanded-width",r),e.dataset.gpcExpandedWidth=r),e.style.height=Math.max(320,M.h+t.clientY-M.my)+"px"},a=()=>{M&&(u.style.transition=M.rightTransition||""),M=null,e.style.userSelect="",document.removeEventListener("mousemove",r,!0),document.removeEventListener("mouseup",a,!0)};document.addEventListener("mousemove",r,!0),document.addEventListener("mouseup",a,!0)});e.firstChild;)e.removeChild(e.firstChild);if(e.appendChild(s),e.appendChild(u),!t){["top","bottom","left"].forEach(t=>{const n=document.createElement("div");n.className=`gpc-edge-drag ${t}`,n.style.cursor="grab",n.addEventListener("mousedown",g),e.appendChild(n)});const t=document.createElement("div");t.className="gpc-edge-drag right",t.style.cursor="grab",t.addEventListener("mousedown",g),u.appendChild(t);const n=document.createElement("div");n.className="gpc-panel-splitter",n.title="Drag to resize preview panel",n.addEventListener("mousedown",t=>{if(0!==t.button||T)return;t.preventDefault(),t.stopPropagation();const o=t.clientX,r=u.getBoundingClientRect().width;u.style.transition="none",n.classList.add("gpc-ps-dragging"),document.body.style.cursor="ew-resize";const a=t=>{const n=o-t.clientX,a=e.getBoundingClientRect().width,i=Math.max(34,Math.floor(.05*a)),l=Math.max(i,Math.floor(.95*a)),s=Math.min(Math.max(i,r+n),l);u.style.width=s+"px",P=s},i=()=>{n.classList.remove("gpc-ps-dragging"),document.body.style.cursor="",u.style.transition="",document.removeEventListener("mousemove",a,!0),document.removeEventListener("mouseup",i,!0)};document.addEventListener("mousemove",a,!0),document.addEventListener("mouseup",i,!0)}),u.appendChild(n),e.appendChild(L)}D(),N(e)}async function D(){const e=document.getElementById("gpc-recent-grid");if(!e)return;z.forEach(e=>URL.revokeObjectURL(e)),z=[];const t=document.body.classList.contains("dark")?"#6b7280":"#94a3b8";e.innerHTML=`<span style="font-size:10px;color:${t};padding:4px;grid-column:span 5">Loading…</span>`;try{const n=await m.getAll(),o=n.slice(0,B);if(e.innerHTML="",!o.length)return void(e.innerHTML=`<span style="font-size:10px;color:${t};padding:4px;grid-column:span 5">No history yet</span>`);if(o.forEach(t=>{const n=URL.createObjectURL(t.blob);z.push(n);const o=document.createElement("div");o.className="rounded bg-gray-200 dark:bg-gray-700 cursor-pointer",o.style.cssText="width:100%;height:100%;min-width:0;overflow:hidden;border:2px solid transparent;box-sizing:border-box;transition:border-color 0.15s;",o.title=t.name;const r=document.createElement("img");r.src=n,r.style.cssText="width:100%;height:100%;object-fit:cover;image-rendering:pixelated;display:block;",o.appendChild(r),o.addEventListener("mouseenter",()=>{o.style.borderColor="#3b82f6"}),o.addEventListener("mouseleave",()=>{o.style.borderColor="transparent"}),o.addEventListener("click",async()=>{await C(t.blob,!1,"Recent thumbnails",t.groupNoise),await m.add(t.blob,t.name,t.groupNoise),D()}),e.appendChild(o)}),n.length>10){const t=(e,t)=>{const n=document.createElement("button");return n.type="button",n.textContent=e,n.className="rounded bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400 border border-gray-200 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-gray-700 cursor-pointer",n.style.cssText="width:100%;height:100%;min-width:0;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;text-decoration:underline;padding:0;box-sizing:border-box;transition:background-color 0.15s,border-color 0.15s;",n.addEventListener("click",e=>{e.stopPropagation(),t()}),n};B<Math.min(50,n.length)&&e.appendChild(t("more",()=>{B=50,D()})),B>10&&e.appendChild(t("less",()=>{B=10,D()}))}}catch(t){e.innerHTML='<span style="font-size:10px;color:#ef4444;padding:4px;grid-column:span 5">Failed to load</span>'}}}(),_featureStatus.ghostTemplateManager="ok",console.log("[GeoPixelcons++] ✅ Ghost Template Manager loaded")}catch(a){_featureStatus.ghostTemplateManager="error",dbgPush(`Ghost Template Manager init failed: ${a&&a.message?a.message:String(a)}`,{error:a,uiComponent:"Ghost Template Manager"}),console.error("[GeoPixelcons++] ❌ Ghost Template Manager failed:",a)}if(_settings.disableGroupNoise)try{function i(){const e=document.getElementById("groupNoiseToggle");if(!e)return!1;e.checked&&(e.checked=!1,"function"==typeof handleGroupingToggle&&handleGroupingToggle()),e.disabled=!0,e.style.opacity="0.4",e.style.cursor="not-allowed";const t=e.closest("label")||e.parentElement;if(t&&(t.style.opacity="0.4",t.style.cursor="not-allowed",!t.querySelector(".gpc-noise-disabled-badge"))){const e=document.createElement("span");e.className="gpc-noise-disabled-badge",e.style.cssText="font-size:10px;font-weight:600;color:#ef4444;margin-left:6px;vertical-align:middle;",e.textContent="(disabled by GeoPixelcons++)",t.appendChild(e)}return Object.defineProperty(e,"checked",{get:()=>!1,set(){},configurable:!0}),!0}if(!i()){const l=new MutationObserver(()=>{i()&&l.disconnect()});l.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>l.disconnect(),6e4)}_featureStatus.disableGroupNoise="ok",console.log("[GeoPixelcons++] ✅ Disable Group Noise loaded")}catch(s){_featureStatus.disableGroupNoise="error",dbgPush(`Disable Group Noise init failed: ${s&&s.message?s.message:String(s)}`,{error:s,uiComponent:"Disable Group Noise"}),console.error("[GeoPixelcons++] ❌ Disable Group Noise failed:",s)}if(_settings.startShiftLock)try{const c="undefined"!=typeof unsafeWindow?unsafeWindow:window;let d=!1;if("function"==typeof c.toggleShiftDown){const p=c.toggleShiftDown;c.toggleShiftDown=function(){return d=!d,dbgPush("toggleShiftDown: _lockOn → "+d),p.apply(this,arguments)}}if("function"==typeof c.toggleShiftDown&&(c.toggleShiftDown(),console.log("[GeoPixelcons++] ✅ Shift Lock enabled on startup"),dbgPush("startShiftLock: enabled on startup, _lockOn="+d)),"function"==typeof c.FindRandomArt){const g=c.FindRandomArt;c.FindRandomArt=async function(){const e=d;e&&"function"==typeof c.toggleShiftDown&&c.toggleShiftDown();try{return await g.apply(this,arguments)}finally{e&&"function"==typeof c.toggleShiftDown&&c.toggleShiftDown()}},dbgPush("startShiftLock: FindRandomArt patched")}_featureStatus.startShiftLock="ok"}catch(u){_featureStatus.startShiftLock="error",dbgPush(`Start in Shift Lock init failed: ${u&&u.message?u.message:String(u)}`,{error:u,uiComponent:"Start in Shift Lock"}),console.error("[GeoPixelcons++] ❌ Start in Shift Lock failed:",u)}if(_settings.startInspectMode)try{const m="undefined"!=typeof unsafeWindow?unsafeWindow:window;function h(e,t){t=t||2e4;const n=Date.now();!function o(){m.map&&"function"==typeof m.map.getCanvas&&document.getElementById("pixel-canvas")&&document.getElementById("pixel-canvas").getContext?e():Date.now()-n>=t||setTimeout(o,300)}()}function f(e,t){const n=document.getElementById(e);if(n)return void t(n);const o=new MutationObserver(()=>{const n=document.getElementById(e);n&&(o.disconnect(),t(n))});o.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>o.disconnect(),15e3)}function b(e,t){let n=null,o=!1;function r(){o||(o=!0,clearTimeout(n),a.disconnect(),t(e))}const a=new MutationObserver(()=>{clearTimeout(n),n=setTimeout(r,500)});a.observe(e,{attributes:!0,attributeFilter:["title"]}),n=setTimeout(r,500),setTimeout(r,6e3)}f("togglePrimaryModeBtn",e=>{h(()=>{b(e,()=>{if("action"===((e.title||"").toLowerCase().includes("action")?"inspect":"action")){try{"function"==typeof m.togglePrimaryMode?m.togglePrimaryMode():e.click()}catch(t){try{e.click()}catch(e){}}console.log("[GeoPixelcons++] ✅ Switched to Inspect Mode on startup")}})})}),_featureStatus.startInspectMode="ok"}catch(y){_featureStatus.startInspectMode="error",dbgPush(`Start in Inspect Mode init failed: ${y&&y.message?y.message:String(y)}`,{error:y,uiComponent:"Start in Inspect Mode"}),console.error("[GeoPixelcons++] ❌ Start in Inspect Mode failed:",y)}if(_settings.smoothZoomButtons)try{const x="undefined"!=typeof unsafeWindow?unsafeWindow:window,v=.5,w=22,k=.01,E=.1,C=400,S=50,T=document.createElement("style");function P(e,t,n){e.style.display="none",t.style.display="none";const o=document.createElement("div");function r(e,t){const n=document.createElement("button");return n.className="gpc-sz-btn w-10 h-10 bg-white dark:bg-gray-700 shadow rounded-full flex items-center justify-center hover:bg-gray-100 dark:hover:bg-gray-600 cursor-pointer select-none flex-shrink-0 text-gray-700 dark:text-gray-200 border-0",n.textContent=e,n.title=t,n.style.cssText="font-size:20px;line-height:1;",n}o.id="gpc-smooth-zoom",o.style.cssText="display:flex;flex-direction:column;align-items:flex-end;gap:2px;";const a=r("+","Zoom In"),i=r("−","Zoom Out"),l=document.createElement("div");l.className="bg-white dark:bg-gray-700 shadow flex items-center justify-center",l.style.cssText="width:40px;height:120px;border-radius:20px;";const s=document.createElement("input");s.type="range",s.min=v,s.max=w,s.step=k,l.appendChild(s);const c=document.createElement("input");c.type="number",c.min=v,c.max=w,c.step=.01,c.className="text-center text-xs font-semibold border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded-lg shadow",c.style.cssText="width:40px;height:28px;padding:0 4px;box-sizing:border-box;",o.appendChild(a),o.appendChild(l),o.appendChild(i),o.appendChild(c),n.insertBefore(o,e),function(e){if(x.map&&"function"==typeof x.map.getZoom)return void e(x.map);const t=setInterval(()=>{x.map&&"function"==typeof x.map.getZoom&&(clearInterval(t),e(x.map))},200);setTimeout(()=>clearInterval(t),2e4)}(e=>{function t(){return e.getZoom()}function n(t){const n=Math.max(v,Math.min(w,Math.round(100*parseFloat(t))/100));e.setZoom(n)}function r(){const e=t();s.value=e,c.value=e.toFixed(2)}r(),e.on("zoom",r),s.addEventListener("input",()=>n(parseFloat(s.value))),c.addEventListener("change",()=>{const e=parseFloat(c.value);isNaN(e)||n(e),r()}),c.addEventListener("keydown",e=>{"Enter"===e.key&&c.blur()});let l=null,d=null;function p(e){n(t()+e),l=setTimeout(()=>{d=setInterval(()=>n(t()+e),S)},C)}function g(){clearTimeout(l),clearInterval(d),l=null,d=null}[[a,k],[i,-k]].forEach(([e,t])=>{e.addEventListener("mousedown",()=>p(t)),e.addEventListener("mouseup",g),e.addEventListener("mouseleave",g),e.addEventListener("touchstart",e=>{e.preventDefault(),p(t)},{passive:!1}),e.addEventListener("touchend",g)}),o.addEventListener("wheel",e=>{e.preventDefault(),n(t()+(e.deltaY<0?E:-E))},{passive:!1})})}function L(e){const t=document.getElementById("zoomIn"),n=document.getElementById("zoomOut"),o=document.getElementById("controls-right");if(t&&n&&o)return void e(t,n,o);const r=new MutationObserver(()=>{const t=document.getElementById("zoomIn"),n=document.getElementById("zoomOut"),o=document.getElementById("controls-right");t&&n&&o&&(r.disconnect(),e(t,n,o))});r.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>r.disconnect(),15e3)}T.textContent="\n                #gpc-smooth-zoom input[type=range] {\n                    writing-mode: vertical-lr;\n                    direction: rtl;\n                    width: 8px;\n                    height: 94px;\n                    cursor: pointer;\n                    accent-color: #22c55e;\n                    margin: 0;\n                }\n                #gpc-smooth-zoom input[type=number]::-webkit-outer-spin-button,\n                #gpc-smooth-zoom input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }\n                #gpc-smooth-zoom input[type=number] { -moz-appearance: textfield; }\n            ",document.head.appendChild(T),L(P),_featureStatus.smoothZoomButtons="ok",console.log("[GeoPixelcons++] ✅ Smooth Zoom Buttons loaded")}catch(M){_featureStatus.smoothZoomButtons="error",dbgPush(`Smooth Zoom Buttons init failed: ${M&&M.message?M.message:String(M)}`,{error:M,uiComponent:"Smooth Zoom Buttons"}),console.error("[GeoPixelcons++] ❌ Smooth Zoom Buttons failed:",M)}if(_settings.guildOverhaul)try{!function(){const e={debugMode:!1,timeOffset:GM_getValue("debug_time_offset",0),minSnapshotInterval:GM_getValue("min_snapshot_interval",36e5),maxSnapshots:GM_getValue("max_snapshots",750)},t=36e5,n=432e5,o=864e5,r={visitedCoords:new Set};!function(){try{const e=GM_getValue("guild_xp_history",[]);if(!e.length)return;let t=!1;e.forEach(e=>{if(!e.members)return;const n=e.members,o={};for(const[e,r]of Object.entries(n)){if(/^\d+$/.test(e)){o[e]=r;continue}const n=e.match(/#(\d+)$/);if(n){const a=n[1];o[a]="number"==typeof r?{xp:r,coords:null,name:e}:{...r,name:r.name||e},t=!0}else o[e]=r}e.members=o}),t&&(GM_setValue("guild_xp_history",e),console.log("[Guild XP] Migrated old name-keyed snapshots to ID keys"))}catch(e){console.warn("[Guild XP] Migration failed:",e)}}();const a="guildOverhaul_territorySettings";let i=null,l=!1,s=[],c={},d=function(){try{const e=GM_getValue(a,null);if(e)return e}catch(e){}return{borderColor:"#3b82f6",borderThickness:2,showLabels:!0,labelFontSize:12,showFill:!0,fillColor:"#3b82f6",fillAlpha:.15,colorByActivity:!1,activeBorderColor:"#22c55e",activeFillColor:"#22c55e",abandonedBorderColor:"#6b7280",abandonedFillColor:"#6b7280"}}();const p="guildOverhaul_playerSettings";let g=null,u=!1,m=[],h=!1,f=!0,b=!0,y=!0,x=function(){try{const e=GM_getValue(p,null);if(e)return e}catch(e){}return{markerSize:28,labelFontSize:11,defaultColor:"#ef4444",territoryColor:"#3b82f6"}}();function v(){GM_setValue(p,x)}const w=document.createElement("style");function k(){return Date.now()+e.timeOffset}async function E(e){try{if(!e)return console.error("Missing targetId"),null;const t=await fetch("/GetUserProfile",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({targetId:parseInt(e)})});if(!t.ok)throw new Error(`Server returned ${t.status}`);return await t.json()}catch(e){return console.error("Failed to fetch user profile:",e),null}}function C(e,t,n){let o=document.getElementById("custom-tooltip");o||(o=document.createElement("div"),o.id="custom-tooltip",o.className="tooltip-popup",document.body.appendChild(o)),o.textContent=n,o.style.left=e+10+"px",o.style.top=t+"px",o.classList.add("visible"),setTimeout(()=>o.classList.remove("visible"),2e3)}function S(){const e=document.getElementById("guildMembersContainer");if(!e)return null;const t={};return e.querySelectorAll("div.flex.items-center.justify-between.p-2.rounded-md.bg-white.shadow-sm").forEach(e=>{const n=e.querySelector("p.font-semibold"),o=e.querySelector("p.text-xs.text-gray-500");if(n&&o){let r=n.textContent.trim();const a=n.querySelector("span");a&&(r=r.replace(a.textContent,"").trim());const i=o.textContent.match(/([\d,.]+)\s*XP$/);let l=null;const s=e.querySelector('button[onclick^="goToGridLocation"]');if(s){const e=s.getAttribute("onclick").match(/goToGridLocation\((-?\d+),\s*(-?\d+)\)/);e&&(l=[parseInt(e[1]),parseInt(e[2])])}if(r&&i){const e=parseInt(i[1].replace(/[.,]/g,""),10),n=r.match(/#(\d+)$/),o=n?n[1]:r;t[o]={xp:e,coords:l,name:r}}}}),t}function T(t,n=!1){const o=k();let r=GM_getValue("guild_xp_history",[]);const a=r[r.length-1],i=a?a.bucketStartTime||a.timestamp:0,l={timestamp:o,bucketStartTime:o,members:t};return!n&&a&&o-i<e.minSnapshotInterval?(l.bucketStartTime=i,r[r.length-1]=l,e.debugMode&&console.log("[Guild XP] Updated recent snapshot")):(r.push(l),console.log("[Guild XP] Created new snapshot")),r.length>e.maxSnapshots&&(r=r.slice(r.length-e.maxSnapshots)),GM_setValue("guild_xp_history",r),r}function P(e){return"number"==typeof e?e:e&&"object"==typeof e&&void 0!==e.xp?e.xp:0}function L(e){return e&&"object"==typeof e&&e.coords?e.coords:null}function M(e,t){const n=[];for(const[o,r]of Object.entries(e)){const e=P(r),a=r&&"object"==typeof r&&r.name||o;if(t.hasOwnProperty(o)){const i=t[o],l=P(i),s=l-e,c=L(i)||L(r),d=(i&&"object"==typeof i?i.name:null)||a;n.push({type:"gain",id:o,name:d,diff:s,oldXp:e,newXp:l,coords:c})}else{const t=L(r);n.push({type:"left",id:o,name:a,oldXp:e,coords:t})}}for(const[o,r]of Object.entries(t))if(!e.hasOwnProperty(o)){const e=P(r),t=L(r),a=r&&"object"==typeof r&&r.name||o;n.push({type:"join",id:o,name:a,newXp:e,coords:t})}return n}function I(){const e=document.getElementById("infoTabBtn");if(!e)return void(document.getElementById("infoTab")&&(console.log("[Guild XP] Could not find tab buttons, appending to infoTab instead"),_()));const t=e.parentElement;if(document.getElementById("xpTrackerTabBtn"))return;document.querySelectorAll("#xpTrackerPane").forEach(e=>e.remove());const n=document.createElement("button");n.textContent="XP Tracker",n.id="xpTrackerTabBtn",n.className=e.className,n.classList.remove("text-blue-600","border-blue-500"),n.classList.add("text-gray-500","border-transparent"),n.style.borderBottom="2px solid transparent";const o=document.createElement("div");o.id="xpTrackerPane",o.style.display="none",o.className="hidden guild-tab-content";const r=document.getElementById("infoTab"),a=r?.parentElement;if(!a)return console.log("[Guild XP] Could not find content container"),void _();n.onclick=e=>{e.preventDefault(),e.stopPropagation();a.querySelectorAll('.guild-tab-content, [id$="Tab"], [id$="Pane"]').forEach(e=>{e.style.display="none",e.classList.add("hidden")});t.querySelectorAll("button").forEach(e=>{e.classList.remove("text-blue-600","border-blue-500"),e.classList.add("text-gray-500","border-transparent"),e.style.borderBottom="2px solid transparent",e.style.color=""}),o.style.display="block",o.classList.remove("hidden"),n.classList.remove("text-gray-500","border-transparent"),n.classList.add("text-blue-600","border-blue-500"),n.style.borderBottom="2px solid #3b82f6",n.style.color="#3b82f6",R(o)};t.querySelectorAll("button").forEach(e=>{if("xpTrackerTabBtn"===e.id||e.dataset.xpTrackerHooked)return;const t=e.onclick;e.onclick=r=>{o.style.display="none",o.classList.add("hidden");a.querySelectorAll(".guild-tab-content").forEach(e=>{"xpTrackerPane"!==e.id&&(e.style.display="")}),n.classList.remove("text-blue-600","border-blue-500"),n.classList.add("text-gray-500","border-transparent"),n.style.borderBottom="2px solid transparent",n.style.color="",t&&t.call(e,r)},e.dataset.xpTrackerHooked="true"}),t.appendChild(n),a.appendChild(o);new MutationObserver(()=>{document.getElementById("xpTrackerTabBtn")||t.appendChild(n)}).observe(t,{childList:!0})}function _(){const e=document.getElementById("infoTab");if(!e||document.getElementById("xpChangesSection"))return;const t=document.createElement("div");t.id="xpChangesSection",t.className="xp-changes-section";const n=document.createElement("div");n.className="xp-changes-header",n.innerHTML='<span>XP Changes Tracker</span><span class="toggle-icon">▼</span>';const o=document.createElement("div");o.className="xp-changes-content hidden",o.id="xpChangesContent",n.onclick=()=>{o.classList.toggle("hidden");n.querySelector(".toggle-icon").style.transform=o.classList.contains("hidden")?"rotate(0deg)":"rotate(180deg)",o.classList.contains("hidden")||R(o)},t.appendChild(n),t.appendChild(o),e.appendChild(t)}function G(r){let a=GM_getValue("guild_xp_history",[]);const i=new Set,l=document.createElement("div");l.className="gmi-modal-overlay";const s=document.createElement("div");s.className="gmi-modal",s.style.cssText="\n            width: 90%;\n            max-width: 600px;\n            max-height: 80vh;\n            display: flex;\n            flex-direction: column;\n        ";const c=document.createElement("div");c.style.cssText="margin-bottom: 15px; border-bottom: 2px solid var(--color-gray-200, #e5e7eb); padding-bottom: 10px;";const d=document.createElement("h3");d.textContent="Manage Snapshots",c.appendChild(d);const p=document.createElement("p");p.textContent=`Total snapshots: ${a.length}`,p.style.cssText="margin: 0; font-size: 12px; color: var(--color-gray-500, #6b7280);",c.appendChild(p),s.appendChild(c);const g=document.createElement("div");g.style.cssText="\n            display: flex;\n            align-items: center;\n            gap: 10px;\n            margin-bottom: 15px;\n            padding: 10px;\n            background: #f9fafb;\n            border-radius: 4px;\n            border: 1px solid var(--color-gray-200, #e5e7eb);\n        ";const u=document.createElement("label");u.textContent="Max Snapshots:",u.className="gmi-modal-label",g.appendChild(u);const m=document.createElement("select");m.className="gmi-modal-select";[50,100,250,500,750,1e3,2500,5e3,1e4].forEach(t=>{const n=document.createElement("option");n.value=t,n.textContent=t,t===e.maxSnapshots&&(n.selected=!0),m.appendChild(n)}),m.onchange=t=>{const n=parseInt(t.target.value);e.maxSnapshots=n,GM_setValue("max_snapshots",n)},g.appendChild(m),s.appendChild(g);const h=document.createElement("div");h.className="gmi-modal-section",h.style.cssText="\n            display: grid;\n            grid-template-columns: 150px 1fr;\n            align-items: center;\n            gap: 12px;\n        ";const f=document.createElement("label");f.textContent="Snapshot Interval:",f.className="gmi-modal-label",f.style.whiteSpace="nowrap",h.appendChild(f);const b=document.createElement("select");b.id="snapshotIntervalSelect",b.className="gmi-modal-select",b.style.cssText="\n            padding: 8px 12px;\n            border: 2px solid #d1d5db;\n            border-radius: 6px;\n            background: white;\n            font-size: 13px;\n            cursor: pointer;\n            color: #374151;\n            transition: all 0.2s ease;\n            font-weight: 500;\n            max-width: 280px;\n        ",b.onmouseover=()=>{b.style.borderColor="#3b82f6",b.style.boxShadow="0 0 4px rgba(59, 130, 246, 0.2)"},b.onmouseout=()=>{document.activeElement!==b&&(b.style.borderColor="#d1d5db",b.style.boxShadow="none")},b.onfocus=()=>{b.style.borderColor="#3b82f6",b.style.boxShadow="0 0 6px rgba(59, 130, 246, 0.3)"},b.onblur=()=>{b.style.borderColor="#d1d5db",b.style.boxShadow="none"};const y=document.createElement("option");y.value="hourly",y.textContent="Hourly (1h)",b.appendChild(y);const x=document.createElement("option");x.value="12h",x.textContent="12 Hours",b.appendChild(x);const v=document.createElement("option");v.value="24h",v.textContent="24 Hours",b.appendChild(v);const w=document.createElement("option");w.value="custom",w.textContent=`Custom (${N(e.minSnapshotInterval)})`,b.appendChild(w),A(b),b.onchange=r=>{const a=r.target.value;if("hourly"===a)e.minSnapshotInterval=t;else if("12h"===a)e.minSnapshotInterval=n;else if("24h"===a)e.minSnapshotInterval=o;else if("custom"===a){const t=prompt("Enter custom snapshot interval in minutes:",(e.minSnapshotInterval/6e4).toString());if(null===t||""===t.trim())return void A(b);{const n=parseFloat(t);if(isNaN(n)||!(n>0))return alert("Invalid input. Please enter a positive number."),void A(b);{e.minSnapshotInterval=60*n*1e3;const t=b.querySelector('option[value="custom"]');t&&(t.textContent=`Custom (${N(e.minSnapshotInterval)})`)}}}GM_setValue("min_snapshot_interval",e.minSnapshotInterval)},h.appendChild(b),s.appendChild(h);let E=null;const C=document.createElement("div");C.style.cssText="\n            display: grid;\n            grid-template-columns: 1fr 1fr;\n            gap: 8px;\n            margin-bottom: 15px;\n        ";const S="\n            width: 16px;\n            height: 16px;\n            margin-right: 8px;\n            cursor: pointer;\n            accent-color: var(--color-blue-500, #3b82f6);\n        ";function T(e){if(E=E===e?null:e,i.clear(),"all"===E)if(0===a.length)alert("No snapshots to select."),E=null;else for(let e=0;e<a.length;e++)i.add(e);else if("daily"===E){const e=new Map;a.forEach((t,n)=>{const o=new Date(t.timestamp).toISOString().split("T")[0];e.has(o)||e.set(o,[]),e.get(o).push(n)}),e.forEach(e=>{for(let t=0;t<e.length-1;t++)i.add(e[t])})}else if("weekly"===E){const e=new Map;a.forEach((t,n)=>{const o=new Date(t.timestamp),r=o.getUTCDay(),a=o.getUTCDate()-r+(0===r?-6:1),i=new Date(o.setUTCDate(a)).toISOString().split("T")[0];e.has(i)||e.set(i,[]),e.get(i).push(n)}),e.forEach(e=>{for(let t=0;t<e.length-1;t++)i.add(e[t])})}else if("7days"===E){const e=k(),t=6048e5;a.forEach((n,o)=>{e-n.timestamp>t&&i.add(o)})}X(),L.checked="all"===E,_.checked="daily"===E,B.checked="weekly"===E,j.checked="7days"===E}const P=document.createElement("label");P.className="gmi-checkbox-option",P.style.color="var(--color-red-500, #ef4444)";const L=document.createElement("input");L.type="checkbox",L.style.cssText=S;const M=document.createElement("span");M.textContent="Select All",M.style.cssText="user-select: none;",P.appendChild(L),P.appendChild(M),P.onclick=e=>{e.target===L&&T("all")},P.onmouseover=e=>e.currentTarget.style.borderColor="var(--color-red-500, #ef4444)",P.onmouseout=e=>e.currentTarget.style.borderColor="all"===E?"var(--color-red-500, #ef4444)":"var(--color-gray-300, #ddd)",C.appendChild(P);const I=document.createElement("label");I.className="gmi-checkbox-option",I.style.color="var(--color-yellow-500, #f59e0b)";const _=document.createElement("input");_.type="checkbox",_.style.cssText=S,_.style.accentColor="var(--color-yellow-500, #f59e0b)";const G=document.createElement("span");G.textContent="Keep One Per Day",G.style.cssText="user-select: none;",I.appendChild(_),I.appendChild(G),I.onclick=e=>{e.target===_&&T("daily")},I.onmouseover=e=>e.currentTarget.style.borderColor="var(--color-yellow-500, #f59e0b)",I.onmouseout=e=>e.currentTarget.style.borderColor="daily"===E?"var(--color-yellow-500, #f59e0b)":"var(--color-gray-300, #ddd)",C.appendChild(I);const z=document.createElement("label");z.className="gmi-checkbox-option",z.style.color="var(--color-blue-500, #3b82f6)";const B=document.createElement("input");B.type="checkbox",B.style.cssText=S;const O=document.createElement("span");O.textContent="Keep One Per Week",O.style.cssText="user-select: none;",z.appendChild(B),z.appendChild(O),z.onclick=e=>{e.target===B&&T("weekly")},z.onmouseover=e=>e.currentTarget.style.borderColor="var(--color-blue-500, #3b82f6)",z.onmouseout=e=>e.currentTarget.style.borderColor="weekly"===E?"var(--color-blue-500, #3b82f6)":"var(--color-gray-300, #ddd)",C.appendChild(z);const D=document.createElement("label");D.className="gmi-checkbox-option",D.style.color="var(--color-purple-500, #8b5cf6)";const j=document.createElement("input");j.type="checkbox",j.style.cssText=S,j.style.accentColor="var(--color-purple-500, #8b5cf6)";const H=document.createElement("span");H.textContent="Delete 7+ Days Old",H.style.cssText="user-select: none;",D.appendChild(j),D.appendChild(H),D.onclick=e=>{e.target===j&&T("7days")},D.onmouseover=e=>e.currentTarget.style.borderColor="var(--color-purple-500, #8b5cf6)",D.onmouseout=e=>e.currentTarget.style.borderColor="7days"===E?"var(--color-purple-500, #8b5cf6)":"var(--color-gray-300, #ddd)",C.appendChild(D),s.appendChild(C);const F=document.createElement("div");function X(){if(F.innerHTML="",0===a.length)return void(F.innerHTML='<p style="color: #6b7280; text-align: center; padding: 20px;">No snapshots available.</p>');let e=null,t=!1;a.forEach((n,o)=>{const r=document.createElement("div"),a=i.has(o),l=new Date(n.timestamp).toISOString().split("T")[0];l!==e&&(e=l,t=!t),r.className=a?"gmi-snapshot-item selected":"gmi-snapshot-item",!a&&t&&(r.style.background="var(--color-gray-100, #f3f4f6)");const s=document.createElement("input");s.type="checkbox",s.checked=i.has(o),s.style.cssText="margin-right: 10px; cursor: pointer; accent-color: var(--color-blue-500, #3b82f6);",s.onchange=e=>{e.target.checked?i.add(o):i.delete(o),X()},r.appendChild(s);const c=document.createElement("label");c.style.cssText=`flex: 1; cursor: pointer; font-size: 12px; color: ${a?"var(--color-red-700, #991b1b)":"var(--color-gray-700, #374151)"}; ${a?"text-decoration: line-through;":""}`,c.onclick=()=>{s.checked=!s.checked,s.checked?i.add(o):i.delete(o),X()};const d=new Date(n.timestamp),p=Object.keys(n.members).length;c.innerHTML=`\n                    <span style="font-weight: bold;">${o+1})</span>\n                    ${d.toLocaleString()} \n                    <span style="color: ${a?"var(--color-red-600, #b91c1c)":"var(--color-gray-500, #6b7280)"};">(${p} members)</span>\n                `,r.appendChild(c),F.appendChild(r)})}F.className="gmi-snapshot-list",F.style.cssText="\n            flex: 1;\n            overflow-y: auto;\n        ",s.appendChild(F),X();const q=document.createElement("div");q.style.cssText="\n            display: flex;\n            gap: 10px;\n            flex-wrap: wrap;\n            border-top: 1px solid var(--color-gray-200, #e5e7eb);\n            padding-top: 15px;\n        ";const U=document.createElement("button");U.innerHTML="🗑️ Delete Selected",U.className="gmi-action-btn danger",U.onclick=()=>{if(0===i.size)return void alert("No snapshots selected.");const e=a.filter((e,t)=>!i.has(t)),t=a.length-e.length;confirm(`Delete ${t} snapshot(s)?`)&&(GM_setValue("guild_xp_history",e),l.remove(),s.remove(),r(e))},q.appendChild(U);const W=document.createElement("button");W.innerHTML="💾 Export Snapshots",W.className="gmi-action-btn primary",W.onclick=()=>{!function(){let e=GM_getValue("guild_xp_history",[]);if(0===e.length)return void alert("No snapshots to export.");const t={version:1,exportDate:(new Date).toISOString(),snapshotCount:e.length,snapshots:e},n=JSON.stringify(t,null,2),o=new Blob([n],{type:"application/json;charset=utf-8;"}),r=document.createElement("a"),a=URL.createObjectURL(o);r.setAttribute("href",a),r.setAttribute("download",`guild_snapshots_${Date.now()}.json`),r.style.visibility="hidden",document.body.appendChild(r),r.click(),document.body.removeChild(r),alert(`Exported ${e.length} snapshots successfully.`)}()},q.appendChild(W);const Y=document.createElement("button");Y.innerHTML="📥 Import Snapshots",Y.className="gmi-action-btn success",Y.onclick=()=>{!function(){if(!confirm("WARNING: Importing will ERASE all current snapshots and replace them with the imported data.\n\nAre you sure you want to continue?"))return;const e=document.createElement("input");e.type="file",e.accept=".json",e.onchange=e=>{const t=e.target.files[0];if(!t)return;const n=new FileReader;n.onload=e=>{try{const t=JSON.parse(e.target.result);if(!t.snapshots||!Array.isArray(t.snapshots))return void alert("Invalid snapshot file format.");if(0===t.snapshots.length)return void alert("No snapshots found in file.");GM_setValue("guild_xp_history",t.snapshots),alert(`Successfully imported ${t.snapshots.length} snapshots.`);const n=document.getElementById("xpTrackerPane");n&&"none"!==n.style.display&&R(n)}catch(e){alert(`Error importing file: ${e.message}`)}},n.readAsText(t)},e.click()}()},q.appendChild(Y);const V=document.createElement("button");V.innerHTML="✕ Close",V.className="gmi-action-btn neutral",V.onclick=()=>{l.remove(),s.remove()},q.appendChild(V),s.appendChild(q),l.onclick=()=>{l.remove(),s.remove()},document.body.appendChild(l),document.body.appendChild(s)}function R(e){e.innerHTML="",e.style.display="flex",e.style.flexDirection="column",e.style.height="100%";const t=S();let n=GM_getValue("guild_xp_history",[]);if(!t||0===Object.keys(t).length)return void(e.innerHTML='<p class="text-gray-500">Please wait for members to load...</p>');const o=document.createElement("div");o.style.marginBottom="15px",o.style.display="flex",o.style.flexDirection="column",o.style.gap="10px";const a=document.createElement("div");a.style.display="flex",a.style.justifyContent="flex-end",a.style.gap="8px",a.style.flexWrap="wrap";const i=document.createElement("button");i.innerHTML="📷 Take a Snapshot",i.className="control-button",i.onclick=()=>{n=T(t,!0),R(e)},a.appendChild(i);const l=document.createElement("button");l.innerHTML="📥 Export CSV",l.className="control-button",l.onclick=()=>{!function(e,t,n,o){let r="";if(void 0!==n&&void 0!==o){const a=n=>"current"===n?{members:t}:e[n],i=a(n),l=a(o);if(!i||!l)return;const s=M(i.members,l.members);s.sort((e,t)=>"join"===e.type?-1:"join"===t.type||"left"===e.type?1:"left"===t.type?-1:t.diff-e.diff);const c=[["Username","Change Type","XP Change","Old XP","New XP"],...s.map(e=>{const t=e.oldXp||0,n=e.newXp||0,o=void 0!==e.diff?e.diff:n-t;return[`"${e.name||e.id}"`,e.type,o,t,n]})];r=c.map(e=>e.join(",")).join("\n")}else{let n="Snapshot,Timestamp,User,XP\n";e.forEach((e,t)=>{const o=new Date(e.timestamp).toLocaleString();for(const[r,a]of Object.entries(e.members)){const e=P(a),i=a&&"object"==typeof a&&a.name?a.name:r;n+=`${t+1},"${o}","${i}",${e}\n`}});const o=new Date(k()).toLocaleString();for(const[e,r]of Object.entries(t)){const t=P(r),a=r&&"object"==typeof r&&r.name?r.name:e;n+=`Current,"${o}","${a}",${t}\n`}r=n}const a=document.createElement("div");a.className="gmi-modal-overlay",a.style.zIndex="10001",a.onclick=()=>{a.remove(),i.remove()};const i=document.createElement("div");i.className="gmi-csv-modal";const l=document.createElement("h3");l.textContent="CSV Export";const s=document.createElement("textarea");s.value=r,s.readOnly=!0,s.onclick=()=>s.select();const c=document.createElement("div");c.style.display="flex",c.style.justifyContent="flex-end",c.style.gap="10px";const d=document.createElement("button");d.innerHTML="📋 Copy",d.className="control-button",d.onclick=()=>{s.select(),navigator.clipboard.writeText(r).then(()=>{const e=d.innerHTML;d.innerHTML="✅ Copied!",setTimeout(()=>d.innerHTML=e,1e3)})};const p=document.createElement("button");p.innerHTML="💾 Download",p.className="gmi-action-btn success",p.onclick=()=>{const e=new Blob([r],{type:"text/csv;charset=utf-8;"}),t=document.createElement("a");if(void 0!==t.download){const n=URL.createObjectURL(e);t.setAttribute("href",n),t.setAttribute("download",`guild_xp_export_${Date.now()}.csv`),t.style.visibility="hidden",document.body.appendChild(t),t.click(),document.body.removeChild(t)}};const g=document.createElement("button");g.innerHTML="Close",g.className="control-button",g.onclick=()=>{a.remove(),i.remove()},c.appendChild(d),c.appendChild(p),c.appendChild(g),i.appendChild(l),i.appendChild(s),i.appendChild(c),document.body.appendChild(a),document.body.appendChild(i)}(n,t,_.value,N.value)},a.appendChild(l);const s=document.createElement("button");s.innerHTML="🎨 Export All User Data",s.className="control-button",s.style.color="#a855f7",s.title="Fetch and export all guild members' data (including colors) as JSON",s.onclick=async()=>{s.disabled=!0,s.style.opacity="0.5",await async function(){const e=S();if(!e||0===Object.keys(e).length)return alert("No guild members found. Please wait for members to load."),null;const t=Object.keys(e),n=[];let o=0,r=0;const a=document.createElement("div");a.className="gmi-progress-popup",a.innerHTML=`\n            <p style="font-weight: bold; margin-bottom: 10px;">Fetching guild member data...</p>\n            <p id="progressText" style="font-size: 14px;">0/${t.length}</p>\n            <div class="gmi-progress-bar-container">\n                <div id="progressBar" class="gmi-progress-bar" style="width: 0%;"></div>\n            </div>\n        `,document.body.appendChild(a);for(let e=0;e<t.length;e++){const a=t[e],i=/^\d+$/.test(a)?a:(()=>{const e=a.match(/#(\d+)$/);return e?e[1]:null})();if(i){const e=await E(i);e?(n.push(e),o++):r++}else r++;const l=(e+1)/t.length*100;document.getElementById("progressBar").style.width=l+"%",document.getElementById("progressText").textContent=`${e+1}/${t.length} (${o} fetched)`}const i=JSON.stringify(n,null,2);return navigator.clipboard.writeText(i).then(()=>{a.innerHTML=`\n                <p style="font-weight: bold; color: #10b981; margin-bottom: 5px;">✓ Success!</p>\n                <p style="font-size: 14px; color: #666;">Fetched: ${o} users<br>Failed: ${r} users<br><br><strong>JSON copied to clipboard!</strong></p>\n            `,setTimeout(()=>a.remove(),3e3)}).catch(e=>{a.innerHTML=`<p style="font-weight: bold; color: #dc2626;">Error copying to clipboard!</p><p style="font-size: 12px; color: #666;">${e.message}</p>`,setTimeout(()=>a.remove(),3e3)}),n}(),s.disabled=!1,s.style.opacity="1"},a.appendChild(s);const c=document.createElement("button");c.innerHTML="🧹 Manage History",c.className="control-button",c.style.color="#ef4444",c.onclick=()=>{G(t=>{n=t,R(e)})},a.appendChild(c),o.appendChild(a);let{snaps:d,curr:p,all:g}=(()=>{const e=n.map((e,t)=>({label:`${t+1}) ${new Date(e.timestamp).toLocaleString()}`,value:t,members:e.members})),o={label:`Now (${new Date(k()).toLocaleString()})`,value:"current",members:t};return{snaps:e,curr:o,all:[...e,o]}})();const h=document.createElement("div");h.style.display="flex",h.style.gap="8px",h.style.flexWrap="wrap";let f="all";const b=()=>{y.classList.remove("active"),x.classList.remove("active"),v.classList.remove("active"),w.classList.remove("active"),L.classList.remove("active")},y=document.createElement("button");y.innerHTML="Show All",y.className="control-button active",y.onclick=()=>{f="all",b(),y.classList.add("active"),O()},h.appendChild(y);const x=document.createElement("button");x.innerHTML="Active",x.className="control-button",x.onclick=()=>{f="active",b(),x.classList.add("active"),O()},h.appendChild(x);const v=document.createElement("button");v.innerHTML="Inactive",v.className="control-button",v.onclick=()=>{f="inactive",b(),v.classList.add("active"),O()},h.appendChild(v);const w=document.createElement("button");w.innerHTML="🟦 In Territory",w.className="control-button xp-territory-filter-btn",w.style.display=u?"":"none",w.onclick=()=>{f="in-territory",b(),w.classList.add("active"),O()},h.appendChild(w);const L=document.createElement("button");L.innerHTML="🟥 Out of Territory",L.className="control-button xp-territory-filter-btn",L.style.display=u?"":"none",L.onclick=()=>{f="out-of-territory",b(),L.classList.add("active"),O()},h.appendChild(L),o.appendChild(h);const I=document.createElement("div");I.style.display="flex",I.style.gap="10px",I.style.alignItems="center",I.style.flexWrap="wrap";const _=document.createElement("select");_.style.flex="1",_.style.padding="4px",_.style.border="2px solid #3b82f6",_.style.borderRadius="4px";const N=document.createElement("select");N.style.flex="1",N.style.padding="4px",N.style.border="2px solid #3b82f6",N.style.borderRadius="4px",g.forEach(e=>{_.add(new Option(e.label,e.value)),N.add(new Option(e.label,e.value))}),d.length>=1?_.value=d[d.length-1].value:_.value="current",N.value="current",I.appendChild(document.createTextNode("From:")),I.appendChild(_);const A=document.createElement("button");A.className="trash-btn",A.innerHTML="🗑️",A.title="Delete this snapshot",A.onclick=()=>{const t=parseInt(_.value);t>=0&&t<n.length&&confirm("Delete this snapshot?")&&(n.splice(t,1),GM_setValue("guild_xp_history",n),R(e))},I.appendChild(A),I.appendChild(document.createTextNode("To:")),I.appendChild(N);const z=document.createElement("button");z.className="trash-btn",z.innerHTML="🗑️",z.title="Delete this snapshot",z.onclick=()=>{const t=parseInt(N.value);t>=0&&t<n.length&&confirm("Delete this snapshot?")&&(n.splice(t,1),GM_setValue("guild_xp_history",n),R(e))},I.appendChild(z),o.appendChild(I);const B=document.createElement("div");B.style.flex="1",B.style.overflowY="auto",B.style.minHeight="0",B.style.border="1px solid #e5e7eb",B.style.borderRadius="0.5rem";const O=()=>{B.innerHTML="";const e=_.value,t=N.value,n="current"===e?p:d[e],o="current"===t?p:d[t];if(!n||!o)return;let a=M(n.members,o.members);"active"===f?a=a.filter(e=>"join"===e.type||e.diff>0):"inactive"===f?a=a.filter(e=>"left"===e.type||e.diff<=0):"in-territory"===f?a=a.filter(e=>{const t=m.find(t=>t.name===e.name);return t&&t.inTerritory}):"out-of-territory"===f&&(a=a.filter(e=>{const t=m.find(t=>t.name===e.name);return t&&!t.inTerritory})),a.sort((e,t)=>"join"===e.type?-1:"join"===t.type||"left"===e.type?1:"left"===t.type?-1:t.diff-e.diff);const i=document.createElement("table");i.className="daily-brief-table",i.innerHTML="<thead><tr><th>User</th><th>Change</th><th>Details</th></tr></thead>";const l=document.createElement("tbody");0===a.length?l.innerHTML='<tr><td colspan="3" style="text-align:center">No changes.</td></tr>':a.forEach(e=>{const t=document.createElement("tr"),n=document.createElement("td");n.style.display="flex",n.style.alignItems="center",n.style.gap="4px";const o=document.createElement("span");o.className="user-name",o.textContent=e.name||e.id,n.appendChild(o);const a=e.id;if(a&&/^\d+$/.test(a)){const e=document.createElement("button");e.className="member-icon-btn discord-icon",e.title="Check Discord",e.innerHTML='\n                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36" width="16" height="16" fill="currentColor">\n                                <path d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.11,77.11,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22c1.24-23.25-13.28-47.54-18.9-72.15ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/>\n                            </svg>\n                        ',e.onclick=async e=>{e.stopPropagation();const t=await E(a);t&&t.discordUser?navigator.clipboard.writeText(t.discordUser).then(()=>{C(e.clientX,e.clientY,`Discord ID: ${t.discordUser} copied!`)}):C(e.clientX,e.clientY,"No Discord ID found.")},n.appendChild(e)}if(e.coords){const t=document.createElement("button");if(t.className="member-icon-btn map-icon",t.setAttribute("data-player-name",e.name||e.id),u&&m.length>0){const n=m.find(t=>t.name===(e.name||e.id));n&&!n.inTerritory&&t.classList.add("out-of-territory")}t.title="Find on Map",t.innerHTML='\n                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n                                <circle cx="12" cy="10" r="3"/>\n                                <path d="M12 21.7C17.3 17 20 13 20 10a8 8 0 1 0-16 0c0 3 2.7 7 8 11.7z"/>\n                            </svg>\n                        ';const o=`${e.coords[0]},${e.coords[1]}`;r.visitedCoords.has(o)&&t.classList.add("visited"),t.onclick=()=>{const n=e.name||e.id,a=document.querySelectorAll("#guildMembersContainer div.flex.items-center.justify-between");let i=!1;for(const e of a){const t=e.querySelector("p.font-semibold");if(t){let o=t.textContent.trim();const r=t.querySelector("span");if(r&&(o=o.replace(r.textContent,"").trim()),o===n){const t=e.querySelector('button[onclick^="goToGridLocation"]');if(t){t.click(),i=!0;break}}}}!i&&window.goToGridLocation&&window.goToGridLocation(e.coords[0],e.coords[1]),r.visitedCoords.add(o),t.classList.add("visited")},n.appendChild(t)}if(e.coords){const t=document.createElement("div");t.style.flex="1",n.appendChild(t);const o=document.createElement("span");o.className="user-coords";const r=function(e){if(!e||e.length<2)return{bg:"#f3f4f6",text:"#1f2937"};const t=e[0],n=e[1],o=Math.sqrt(t*t+n*n),r=Math.floor(o/25e3);let a;a=t>=0&&n>=0?`hsl(120, 50%, ${97-Math.min(3*r,15)}%)`:t<0&&n>=0?`hsl(0, 50%, ${97-Math.min(3*r,15)}%)`:t<0&&n<0?`hsl(240, 50%, ${97-Math.min(3*r,15)}%)`:`hsl(30, 50%, ${97-Math.min(3*r,15)}%)`;return{bg:a,text:"#1f2937"}}(e.coords);o.style.backgroundColor=r.bg,o.style.padding="2px 6px",o.style.borderRadius="3px";const a=document.createElement("span");a.style.color=r.text,a.textContent="(";const i=document.createElement("span");i.style.color=r.text,i.style.fontWeight="500",i.textContent=e.coords[0];const l=document.createElement("span");l.style.color=r.text,l.textContent=", ";const s=document.createElement("span");s.style.color=r.text,s.style.fontWeight="500",s.textContent=e.coords[1];const c=document.createElement("span");c.style.color=r.text,c.textContent=")",o.appendChild(a),o.appendChild(i),o.appendChild(l),o.appendChild(s),o.appendChild(c),n.appendChild(o)}let i="";"gain"===e.type?i=e.diff>0?`<td class="xp-gain">+${e.diff.toLocaleString()}</td>`:e.diff<0?`<td class="xp-loss">${e.diff.toLocaleString()}</td>`:'<td class="xp-neutral">0</td>':"join"===e.type?i='<td class="xp-gain">JOINED</td>':"left"===e.type&&(i='<td class="xp-loss">LEFT</td>'),t.appendChild(n);const s=document.createElement("td");s.innerHTML=i.replace(/^<td.*?>|<\/td>$/g,""),s.className=i.match(/class="([^"]+)"/)?.[1]||"",t.appendChild(s);const c=document.createElement("td");c.textContent=`${e.oldXp?.toLocaleString()||0} → ${e.newXp?.toLocaleString()||0}`,t.appendChild(c),l.appendChild(t)}),i.appendChild(l),B.appendChild(i)};_.onchange=O,N.onchange=O,O(),e.appendChild(o),e.appendChild(B)}function N(e){const t=e/1e3;if(t<60)return`${t}s`;const n=t/60;if(n<60)return`${n.toFixed(1)}m`;const o=n/60;if(o<24)return`${o.toFixed(1)}h`;return`${(o/24).toFixed(1)}d`}function A(r){if(e.minSnapshotInterval===t)r.value="hourly";else if(e.minSnapshotInterval===n)r.value="12h";else if(e.minSnapshotInterval===o)r.value="24h";else{r.value="custom";const t=r.querySelector('option[value="custom"]');t&&(t.textContent=`Custom (${N(e.minSnapshotInterval)})`)}}function z(e){return new Promise((t,n)=>{const o=new Image;o.onload=()=>t({width:o.naturalWidth,height:o.naturalHeight}),o.onerror=()=>n(new Error("Failed to load image")),o.src=e})}async function B(){if("undefined"==typeof userGuildData||!userGuildData||!userGuildData.projects)return console.warn("[Guild Territories] No guild data or projects available"),[];const e=userGuildData.projects;if(0===e.length)return[];const t=[];for(let n=0;n<e.length;n++){const o=e[n];try{const e=await z(o.image);t.push({gridX:o.imageGridX,gridY:o.imageGridY,width:e.width,height:e.height,index:n+1})}catch(e){console.warn(`[Guild Territories] Failed to get dimensions for project #${n+1} (id ${o.id}):`,e)}}return t}async function O(){const e=document.getElementById("exportTerritoriesBtn");e&&(e.disabled=!0,e.innerHTML="⏳ Loading...");try{"undefined"!=typeof userGuildData&&userGuildData&&"function"==typeof fetchGuildProjects&&await fetchGuildProjects();const t=await B();if(0===t.length)return void alert("No guild projects found to export.");const n=t.map(e=>({name:`Template #${e.index}`,x:e.gridX,y:e.gridY,width:e.width,height:e.height})),o=JSON.stringify(n,null,2);try{await navigator.clipboard.writeText(o),e&&(e.innerHTML="✅ Copied!",setTimeout(()=>{e.innerHTML="📋 Export to Clipboard"},2e3)),console.log(`[Guild Territories] Exported ${n.length} territories to clipboard for Json import`)}catch(e){prompt('Copy this JSON and paste into Json\'s "Import JSON":',o)}}catch(e){console.error("[Guild Territories] Export failed:",e),alert("Failed to export territories: "+e.message)}finally{e&&(e.disabled=!1),e&&!e.innerHTML.includes("✅")&&(e.innerHTML="📋 Export to Clipboard")}}function D(){const e={};if(0===s.length)return e;const t=S();if(!t||0===Object.keys(t).length)return e;for(const n of s){let o=!1;for(const[,e]of Object.entries(t)){const t=L(e);if(t){const[e,r]=t;if(e>=n.gridX&&e<n.gridX+n.width&&r<=n.gridY&&r>n.gridY-n.height){o=!0;break}}}e[n.index]=o}return e}function j(){if(!i||!l)return;const e=document.getElementById("pixel-canvas");if(!e)return;i.width=e.width,i.height=e.height;const t=i.getContext("2d");if(t.clearRect(0,0,i.width,i.height),0===s.length)return;const n="undefined"!=typeof gridSize?gridSize:25,o=d.borderThickness;d.colorByActivity&&(c=D());const r=u&&m.length>0?D():null;s.forEach(e=>{let a=d.borderColor,i=d.fillColor;if(d.colorByActivity){const t=c[e.index]??!1;a=t?d.activeBorderColor:d.abandonedBorderColor,i=t?d.activeFillColor:d.abandonedFillColor}r&&!r[e.index]&&(a="#ef4444",i="#ef4444"),function(e,t,n,o,r,a){if("undefined"==typeof turf||"undefined"==typeof map)return;const i=[(t.gridX-.5)*n,(t.gridY+.5)*n],l=[(t.gridX-.5+t.width)*n,(t.gridY+.5-t.height)*n],s=map.project(turf.toWgs84(i)),c=map.project(turf.toWgs84(l)),p=s.x,g=s.y,u=c.x-s.x,m=c.y-s.y;if(!(p+u<0||p>e.canvas.width||g+m<0||g>e.canvas.height)&&(d.showFill&&(e.fillStyle=a||d.fillColor,e.globalAlpha=d.fillAlpha,e.fillRect(p,g,u,m)),e.strokeStyle=o,e.lineWidth=r,e.globalAlpha=1,e.strokeRect(p,g,u,m),d.showLabels&&u>40&&m>20)){const n=`#${t.index}`;e.font=`bold ${d.labelFontSize}px sans-serif`,e.fillStyle=o,e.globalAlpha=.85,e.textAlign="left",e.textBaseline="top",e.fillText(n,p+4,g+4)}}(t,e,n,a,o,i)})}async function H(){if(l){if(l=!1,i){i.getContext("2d").clearRect(0,0,i.width,i.height)}return F(),void console.log("[Guild Territories] Territories hidden")}const e=document.getElementById("territoryToggleBtn");e&&(e.disabled=!0,e.innerHTML="⏳ Processing...");try{if("undefined"!=typeof userGuildData&&userGuildData&&"function"==typeof fetchGuildProjects&&await fetchGuildProjects(),s=await B(),0===s.length)return e&&(e.disabled=!1,e.innerHTML="🗺️ Show Territories",e.className="territory-toggle-btn inactive"),void alert("No guild projects found to display territories for.");i||(i=document.createElement("canvas"),i.id="territory-canvas",document.body.appendChild(i),console.log("[Guild Territories] Territory canvas created")),l=!0,j(),F(),console.log(`[Guild Territories] Showing ${s.length} territories`)}catch(e){console.error("[Guild Territories] Error building territories:",e),alert("Failed to process territories: "+e.message)}e&&(e.disabled=!1)}function F(){const e=document.getElementById("territoryToggleBtn");e&&(l?(e.innerHTML="🗺️ Hide Territories",e.className="territory-toggle-btn active"):(e.innerHTML="🗺️ Show Territories",e.className="territory-toggle-btn inactive"))}function X(){const e=document.createElement("div");e.className="territory-settings-collapsible",e.id="territorySettingsCollapsible";const t=document.createElement("button");t.className="territory-settings-toggle",t.innerHTML='<span>⚙️ Settings</span><span class="toggle-arrow collapsed">▼</span>';const n=document.createElement("div");n.className="territory-settings-content collapsed";const o=Math.round(100*d.fillAlpha);n.innerHTML=`\n            <div class="territory-setting-row">\n                <label>Border Color</label>\n                <input type="color" id="territoryColorInput" value="${d.borderColor}"\n                       class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n            </div>\n            <div class="territory-setting-row">\n                <label>Border Thickness</label>\n                <select id="territoryThicknessSelect" class="px-2 py-1 rounded-md text-xs min-w-[120px]">\n                    ${[{value:1,label:"Thin (1px)"},{value:2,label:"Normal (2px)"},{value:3,label:"Medium (3px)"},{value:4,label:"Thick (4px)"},{value:6,label:"Heavy (6px)"},{value:8,label:"Extra Heavy (8px)"}].map(e=>`<option value="${e.value}" ${d.borderThickness==e.value?"selected":""}>${e.label}</option>`).join("")}\n                </select>\n            </div>\n            <div class="territory-setting-row">\n                <label>Show Labels</label>\n                <input type="checkbox" id="territoryLabelsCheck" ${d.showLabels?"checked":""}\n                       class="w-4 h-4 cursor-pointer accent-blue-500">\n            </div>\n            <div class="territory-setting-row">\n                <label>Label Size</label>\n                <select id="territoryFontSelect" class="px-2 py-1 rounded-md text-xs min-w-[120px]">\n                    ${[10,12,14,16,18,20].map(e=>`<option value="${e}" ${d.labelFontSize==e?"selected":""}>${e}px</option>`).join("")}\n                </select>\n            </div>\n\n            <div class="territory-section-divider">Fill</div>\n            <div class="territory-setting-row">\n                <label>Enable Fill</label>\n                <input type="checkbox" id="territoryFillCheck" ${d.showFill?"checked":""}\n                       class="w-4 h-4 cursor-pointer accent-blue-500">\n            </div>\n            <div class="territory-setting-row">\n                <label>Fill Color</label>\n                <input type="color" id="territoryFillColorInput" value="${d.fillColor}"\n                       class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n            </div>\n            <div class="territory-setting-row">\n                <label>Fill Opacity</label>\n                <div class="flex items-center gap-1.5">\n                    <input type="range" id="territoryFillAlphaRange" min="0.01" max="1" step="0.01" value="${d.fillAlpha}"\n                           class="w-20 cursor-pointer">\n                    <span id="territoryFillAlphaValue" class="text-xs min-w-[30px]" style="color: var(--color-gray-500, #6b7280);">${o}%</span>\n                </div>\n            </div>\n\n            <div class="territory-section-divider">Activity Coloring</div>\n            <div class="territory-setting-row">\n                <label>Color by activity</label>\n                <input type="checkbox" id="territoryActivityCheck" ${d.colorByActivity?"checked":""}\n                       class="w-4 h-4 cursor-pointer accent-blue-500"\n                       title="Use different colors for territories with active players vs abandoned/finished">\n            </div>\n            <div id="activityColorRows" style="display:${d.colorByActivity?"flex":"none"};flex-direction:column;gap:10px;">\n                <div class="territory-setting-row">\n                    <label>Active Border</label>\n                    <input type="color" id="territoryActiveBorderInput" value="${d.activeBorderColor}"\n                           class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n                </div>\n                <div class="territory-setting-row">\n                    <label>Active Fill</label>\n                    <input type="color" id="territoryActiveFillInput" value="${d.activeFillColor}"\n                           class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n                </div>\n                <div class="territory-setting-row">\n                    <label>Abandoned Border</label>\n                    <input type="color" id="territoryAbandonedBorderInput" value="${d.abandonedBorderColor}"\n                           class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n                </div>\n                <div class="territory-setting-row">\n                    <label>Abandoned Fill</label>\n                    <input type="color" id="territoryAbandonedFillInput" value="${d.abandonedFillColor}"\n                           class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n                </div>\n                <p style="font-size:11px;color:var(--color-gray-500,#6b7280);margin:0;">\n                    Active = guild members drawing inside. Abandoned = no members inside.\n                </p>\n            </div>\n\n            <div class="territory-section-divider">Preview</div>\n            <div id="territoryPreviewContainer" class="flex items-center justify-center gap-2.5 py-1">\n                <div id="territoryPreviewBox" style="width: 70px; height: 44px; border: ${d.borderThickness}px solid ${d.colorByActivity?d.activeBorderColor:d.borderColor}; border-radius: 2px; position: relative; display: flex; align-items: flex-start; justify-content: flex-start; padding: 2px; background: var(--color-white, #fff);">\n                    <div id="territoryPreviewFill" style="position: absolute; inset: 0; background: ${d.colorByActivity?d.activeFillColor:d.fillColor}; opacity: ${d.showFill?d.fillAlpha:0}; border-radius: 1px;"></div>\n                    <span style="font-size: ${d.labelFontSize}px; font-weight: bold; color: ${d.colorByActivity?d.activeBorderColor:d.borderColor}; position: relative; z-index: 1;">${d.colorByActivity?"Active":"#1"}</span>\n                </div>\n                <div id="territoryPreviewBoxAbandoned" style="width: 70px; height: 44px; border: ${d.borderThickness}px solid ${d.abandonedBorderColor}; border-radius: 2px; position: relative; display: ${d.colorByActivity?"flex":"none"}; align-items: flex-start; justify-content: flex-start; padding: 2px; background: var(--color-white, #fff);">\n                    <div id="territoryPreviewFillAbandoned" style="position: absolute; inset: 0; background: ${d.abandonedFillColor}; opacity: ${d.showFill?d.fillAlpha:0}; border-radius: 1px;"></div>\n                    <span style="font-size: ${d.labelFontSize}px; font-weight: bold; color: ${d.abandonedBorderColor}; position: relative; z-index: 1;">Done</span>\n                </div>\n            </div>\n        `,t.addEventListener("click",()=>{n.classList.toggle("collapsed"),t.querySelector(".toggle-arrow").classList.toggle("collapsed")}),e.append(t,n);return setTimeout(()=>{const e=()=>{const e=document.getElementById("territoryColorInput")?.value,t=parseInt(document.getElementById("territoryThicknessSelect")?.value),n=parseInt(document.getElementById("territoryFontSelect")?.value),o=document.getElementById("territoryLabelsCheck")?.checked,r=document.getElementById("territoryFillCheck")?.checked,i=document.getElementById("territoryFillColorInput")?.value,l=parseFloat(document.getElementById("territoryFillAlphaRange")?.value),s=document.getElementById("territoryActivityCheck")?.checked,c=document.getElementById("territoryActiveBorderInput")?.value,p=document.getElementById("territoryActiveFillInput")?.value,g=document.getElementById("territoryAbandonedBorderInput")?.value,u=document.getElementById("territoryAbandonedFillInput")?.value,m=document.getElementById("activityColorRows");m&&(m.style.display=s?"flex":"none");const h=document.getElementById("territoryPreviewBox"),f=document.getElementById("territoryPreviewFill"),b=s?c:e,y=s?p:i;if(h){h.style.borderColor=b,h.style.borderWidth=t+"px";const e=h.querySelector("span");e&&(e.style.color=b,e.style.fontSize=n+"px",e.textContent=s?"Active":"#1")}f&&(f.style.background=y,f.style.opacity=r?l:0);const x=document.getElementById("territoryPreviewBoxAbandoned"),v=document.getElementById("territoryPreviewFillAbandoned");if(x){x.style.display=s?"flex":"none",x.style.borderColor=g,x.style.borderWidth=t+"px";const e=x.querySelector("span");e&&(e.style.color=g,e.style.fontSize=n+"px")}v&&(v.style.background=u,v.style.opacity=r?l:0);const w=document.getElementById("territoryFillAlphaValue");w&&(w.textContent=Math.round(100*l)+"%"),d.borderColor=e,d.borderThickness=t,d.showLabels=o,d.labelFontSize=n,d.showFill=r,d.fillColor=i,d.fillAlpha=l,d.colorByActivity=s,d.activeBorderColor=c,d.activeFillColor=p,d.abandonedBorderColor=g,d.abandonedFillColor=u,GM_setValue(a,d),j()};["territoryColorInput","territoryFillColorInput","territoryActiveBorderInput","territoryActiveFillInput","territoryAbandonedBorderInput","territoryAbandonedFillInput"].forEach(t=>{document.getElementById(t)?.addEventListener("input",e)}),["territoryThicknessSelect","territoryFontSelect"].forEach(t=>{document.getElementById(t)?.addEventListener("change",e)}),["territoryLabelsCheck","territoryFillCheck","territoryActivityCheck"].forEach(t=>{document.getElementById(t)?.addEventListener("change",e)}),document.getElementById("territoryFillAlphaRange")?.addEventListener("input",e)},0),e}function q(){const e=document.getElementById("guildProjectsContainer");if(!e)return;e.querySelectorAll(":scope > div").forEach((e,t)=>{if(e.querySelector(".project-number-badge"))return;e.style.position="relative";const n=document.createElement("div");n.className="project-number-badge",n.textContent=`#${t+1}`,n.style.cssText="\n                position: absolute;\n                top: 6px;\n                left: 6px;\n                background: var(--color-blue-500, #3b82f6);\n                color: var(--color-white, #fff);\n                font-size: 11px;\n                font-weight: 700;\n                padding: 2px 7px;\n                border-radius: 6px;\n                z-index: 5;\n                box-shadow: 0 1px 4px rgba(0,0,0,0.2);\n                pointer-events: none;\n                line-height: 1.4;\n            ",e.insertBefore(n,e.firstChild)})}function U(){const e=document.getElementById("projectsTab");if(!e)return;if(document.getElementById("territoryControlsContainer"))return;const t=document.createElement("div");t.id="territoryControlsContainer",t.className="flex flex-col gap-3 mb-3 p-3 rounded-lg border";const n=document.createElement("div");n.className="flex items-center justify-between gap-2 flex-wrap";const o=document.createElement("button");o.id="territoryToggleBtn",o.className=l?"territory-toggle-btn active":"territory-toggle-btn inactive",o.innerHTML=l?"🗺️ Hide Territories":"🗺️ Show Territories",o.addEventListener("click",H);const r=document.createElement("button");r.id="playersToggleBtn",r.className=u?"territory-toggle-btn active":"territory-toggle-btn inactive",r.innerHTML=u?"👥 Hide Players":"👥 Show Players",r.addEventListener("click",Q);const a=document.createElement("button");a.id="exportTerritoriesBtn",a.className="territory-toggle-btn inactive",a.innerHTML="📋 Export to Clipboard",a.title="Copy guild territories as JSON for the GeoPixels Json import",a.addEventListener("click",O);const i=document.createElement("span");i.className="territory-info-text",i.textContent="Overlay territories or player locations on the map",n.append(o,r,a,i),t.appendChild(n);const s=document.createElement("div");s.id="playersOptionsRow",s.className="player-marker-options",s.style.display=u?"flex":"none";const c=document.createElement("label"),d=document.createElement("input");d.type="checkbox",d.id="playersShowNamesCheck",d.checked=h,d.addEventListener("change",e=>{h=e.target.checked,function(){for(const e of m)e.element.classList.toggle("show-label",h)}()}),c.appendChild(d),c.appendChild(document.createTextNode("Show all names"));const p=document.createElement("label"),g=document.createElement("input");g.type="checkbox",g.id="playersColorTerritoryCheck",g.checked=f,g.addEventListener("change",e=>{f=e.target.checked,Z()}),p.appendChild(g),p.appendChild(document.createTextNode("Blue if in territory"));const w=document.createElement("label"),k=document.createElement("input");k.type="checkbox",k.id="playersShowInTerritoryCheck",k.checked=b,k.addEventListener("change",e=>{b=e.target.checked,J()}),w.appendChild(k),w.appendChild(document.createTextNode("Show in-territory"));const E=document.createElement("label"),C=document.createElement("input");C.type="checkbox",C.id="playersShowOutsideTerritoryCheck",C.checked=y,C.addEventListener("change",e=>{y=e.target.checked,J()}),E.appendChild(C),E.appendChild(document.createTextNode("Show outside territory")),s.append(c,p,w,E),t.appendChild(s),t.appendChild(X()),t.appendChild(function(){const e=document.createElement("div");e.className="territory-settings-collapsible",e.id="playerSettingsCollapsible";const t=document.createElement("button");t.className="territory-settings-toggle",t.innerHTML='<span>👥 Player Settings</span><span class="toggle-arrow collapsed">▼</span>';const n=document.createElement("div");n.className="territory-settings-content collapsed";const o=[{value:16,label:"Tiny (16px)"},{value:20,label:"Small (20px)"},{value:24,label:"Medium (24px)"},{value:28,label:"Default (28px)"},{value:34,label:"Large (34px)"},{value:42,label:"Extra Large (42px)"}];n.innerHTML=`\n            <div class="territory-setting-row">\n                <label>Marker Size</label>\n                <select id="playerSizeSelect" class="px-2 py-1 rounded-md text-xs min-w-[120px]">\n                    ${o.map(e=>`<option value="${e.value}" ${x.markerSize==e.value?"selected":""}>${e.label}</option>`).join("")}\n                </select>\n            </div>\n            <div class="territory-setting-row">\n                <label>Label Size</label>\n                <select id="playerLabelSizeSelect" class="px-2 py-1 rounded-md text-xs min-w-[120px]">\n                    ${[9,10,11,12,13,14,16].map(e=>`<option value="${e}" ${x.labelFontSize==e?"selected":""}>${e}px</option>`).join("")}\n                </select>\n            </div>\n            <div class="territory-setting-row">\n                <label>Default Color</label>\n                <input type="color" id="playerDefaultColorInput" value="${x.defaultColor}"\n                       class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n            </div>\n            <div class="territory-setting-row">\n                <label>Territory Color</label>\n                <input type="color" id="playerTerritoryColorInput" value="${x.territoryColor}"\n                       class="w-10 h-7 rounded-md cursor-pointer p-0.5">\n            </div>\n\n            <div class="territory-section-divider">Preview</div>\n            <div class="flex items-center justify-center gap-4 py-1">\n                <div style="display:flex;flex-direction:column;align-items:center;gap:2px;">\n                    <svg id="playerPreviewDefault" xmlns="http://www.w3.org/2000/svg" width="${x.markerSize}" height="${Math.round(40*x.markerSize/28)}" viewBox="0 0 24 36">\n                        <path d="M12 0C5.4 0 0 5.4 0 12c0 9 12 24 12 24s12-15 12-24C24 5.4 18.6 0 12 0z" fill="${x.defaultColor}"/>\n                        <circle cx="12" cy="11" r="4.5" fill="white"/>\n                    </svg>\n                    <span style="font-size:10px;color:var(--color-gray-500,#6b7280);">Outside</span>\n                </div>\n                <div style="display:flex;flex-direction:column;align-items:center;gap:2px;">\n                    <svg id="playerPreviewTerritory" xmlns="http://www.w3.org/2000/svg" width="${x.markerSize}" height="${Math.round(40*x.markerSize/28)}" viewBox="0 0 24 36">\n                        <path d="M12 0C5.4 0 0 5.4 0 12c0 9 12 24 12 24s12-15 12-24C24 5.4 18.6 0 12 0z" fill="${x.territoryColor}"/>\n                        <circle cx="12" cy="11" r="4.5" fill="white"/>\n                    </svg>\n                    <span style="font-size:10px;color:var(--color-gray-500,#6b7280);">In Territory</span>\n                </div>\n            </div>\n        `,t.addEventListener("click",()=>{n.classList.toggle("collapsed"),t.querySelector(".toggle-arrow").classList.toggle("collapsed")}),e.append(t,n);return setTimeout(()=>{const e=()=>{const e=parseInt(document.getElementById("playerSizeSelect")?.value);const t=parseInt(document.getElementById("playerLabelSizeSelect")?.value);const n=document.getElementById("playerDefaultColorInput")?.value;const o=document.getElementById("playerTerritoryColorInput")?.value;x.markerSize=e;x.labelFontSize=t;x.defaultColor=n;x.territoryColor=o;const r=Math.round(e*40/28);const a=document.getElementById("playerPreviewDefault");const i=document.getElementById("playerPreviewTerritory");if(a){a.setAttribute("width",e);a.setAttribute("height",r);a.querySelector("path").setAttribute("fill",n)}if(i){i.setAttribute("width",e);i.setAttribute("height",r);i.querySelector("path").setAttribute("fill",o)}v();K();Z()};["playerSizeSelect","playerLabelSizeSelect"].forEach(t=>{document.getElementById(t)?.addEventListener("change",e)});["playerDefaultColorInput","playerTerritoryColorInput"].forEach(t=>{document.getElementById(t)?.addEventListener("input",e)})},0),e}()),e.insertBefore(t,e.firstChild)}function W(e,t){for(const n of s)if(e>=n.gridX&&e<n.gridX+n.width&&t<=n.gridY&&t>n.gridY-n.height)return!0;return!1}function Y(e){return f&&e?x.territoryColor:x.defaultColor}function V(e,t,n){if("undefined"==typeof turf||"undefined"==typeof map)return null;const o=[e*n,t*n];return map.project(turf.toWgs84(o))}function J(){if(!g||!u)return;const e="undefined"!=typeof gridSize?gridSize:25,t=window.innerWidth,n=window.innerHeight;for(const o of m){if(o.inTerritory&&!b){o.element.style.display="none";continue}if(!o.inTerritory&&!y){o.element.style.display="none";continue}const r=V(o.gridX,o.gridY,e);r&&(r.x<-60||r.x>t+60||r.y<-60||r.y>n+60?o.element.style.display="none":(o.element.style.display="",o.element.style.left=r.x+"px",o.element.style.top=r.y+"px"))}}function $(){const e=document.getElementById("xpTrackerPane");if(!e)return;e.querySelectorAll(".map-icon[data-player-name]").forEach(e=>{const t=e.getAttribute("data-player-name");if(t&&!e.classList.contains("visited"))if(u&&m.length>0){const n=m.find(e=>e.name===t);n&&!n.inTerritory?e.classList.add("out-of-territory"):e.classList.remove("out-of-territory")}else e.classList.remove("out-of-territory")});e.querySelectorAll(".xp-territory-filter-btn").forEach(e=>{e.style.display=u?"":"none"})}function Z(){for(const e of m){const t=e.element.querySelector(".pin-body");t&&t.setAttribute("fill",Y(e.inTerritory))}}function K(){const e=x.markerSize,t=Math.round(40*e/28);for(const n of m){const o=n.element.querySelector("svg");o&&(o.setAttribute("width",e),o.setAttribute("height",t));const r=n.element.querySelector(".player-marker-tooltip");r&&(r.style.fontSize=x.labelFontSize+"px")}}function Q(){if(u)return u=!1,m.forEach(e=>e.element.remove()),m=[],ee(),te(),$(),j(),void console.log("[Guild Players] Player markers hidden");const e=document.getElementById("playersToggleBtn");e&&(e.disabled=!0,e.innerHTML="⏳ Loading...");const t=function(){const e=S();if(!e)return[];const t=[];for(const[n,o]of Object.entries(e)){const e=L(o);if(e){const r=o&&o.name||n;t.push({name:r,gridX:e[0],gridY:e[1]})}}return t}();if(0===t.length)return e&&(e.disabled=!1,e.innerHTML="👥 Show Players",e.className="territory-toggle-btn inactive"),void alert("No guild members with coordinates found. Make sure the guild Info tab has loaded.");(async()=>{if(0===s.length)try{"undefined"!=typeof userGuildData&&userGuildData&&"function"==typeof fetchGuildProjects&&await fetchGuildProjects(),s=await B()}catch(e){console.warn("[Guild Players] Could not build territory rects for coloring:",e)}for(const e of t)e.inTerritory=W(e.gridX,e.gridY);g||(g=document.createElement("div"),g.id="players-container",document.body.appendChild(g),console.log("[Guild Players] Players container created")),m=t.map(e=>{const t=function(e){const t=document.createElement("div");t.className="player-marker"+(h?" show-label":""),t.setAttribute("data-player",e.name);const n=Y(e.inTerritory),o=x.markerSize,a=Math.round(40*o/28);return t.innerHTML=`\n            <svg xmlns="http://www.w3.org/2000/svg" width="${o}" height="${a}" viewBox="0 0 24 36">\n                <path class="pin-body" d="M12 0C5.4 0 0 5.4 0 12c0 9 12 24 12 24s12-15 12-24C24 5.4 18.6 0 12 0z" fill="${n}"/>\n                <circle cx="12" cy="11" r="4.5" fill="white"/>\n            </svg>\n            <div class="player-marker-tooltip" style="font-size:${x.labelFontSize}px">${e.name.replace(/</g,"&lt;")}</div>\n        `,t.addEventListener("click",t=>{t.stopPropagation();let n=!1;const o=document.querySelectorAll("#guildMembersContainer div.flex.items-center.justify-between");for(const t of o){const o=t.querySelector("p.font-semibold");if(o){let r=o.textContent.trim();const a=o.querySelector("span");if(a&&(r=r.replace(a.textContent,"").trim()),r===e.name){const e=t.querySelector('button[onclick^="goToGridLocation"]');if(e){e.click(),n=!0;break}}}}if(!n){const t=document.createElement("script");t.textContent=`if(typeof goToGridLocation==='function')goToGridLocation(${parseInt(e.gridX)},${parseInt(e.gridY)});`,document.documentElement.appendChild(t),t.remove()}const a=`${e.gridX},${e.gridY}`;r.visitedCoords.add(a)}),t}(e);return g.appendChild(t),{...e,element:t}}),u=!0,J(),ee(),te(),$(),j();const n=t.filter(e=>e.inTerritory).length;console.log(`[Guild Players] Showing ${m.length} player markers (${n} in territory)`),e&&(e.disabled=!1)})()}function ee(){const e=document.getElementById("playersToggleBtn");e&&(u?(e.innerHTML="👥 Hide Players",e.className="territory-toggle-btn active"):(e.innerHTML="👥 Show Players",e.className="territory-toggle-btn inactive"))}function te(){const e=document.getElementById("playersOptionsRow");e&&(e.style.display=u?"flex":"none")}async function ne(){try{await function(e,t=1e4){return new Promise((n,o)=>{const r=Date.now(),a=setInterval(()=>{const i=document.querySelector(e);i?(clearInterval(a),n(i)):Date.now()-r>t&&(clearInterval(a),o(new Error(`Element ${e} not found within ${t}ms`)))},100)})}("#myGuildModal",1e4);const e=document.getElementById("myGuildModal"),t=document.getElementById("myGuildPanel");if(!e||!t)return void console.error("[Guild Modal] myGuildModal or myGuildPanel not found");if(t.classList.contains("draggable-panel"))return;const n="function"==typeof gpcMobileCompatibilityActive&&gpcMobileCompatibilityActive();e.style.position="fixed",e.style.inset="auto",e.style.backgroundColor="transparent",e.style.justifyContent="flex-start",e.style.alignItems="flex-start",e.style.padding="0",e.style.pointerEvents="none",t.style.position="fixed",t.style.cursor="default",t.style.transform="none",t.style.opacity="1",t.style.scale="1",t.style.pointerEvents="auto",t.classList.add("draggable-panel"),t.classList.toggle("gpc-mobile-compat",n),n?(t.style.top="8px",t.style.left="8px",t.style.width="calc(100vw - 16px)",t.style.maxWidth="calc(100vw - 16px)",t.style.maxHeight="calc(100dvh - 16px)",t.style.overflowY="auto"):(t.style.top="100px",t.style.left="calc(50% - 25rem)",t.style.width="50rem",t.style.maxWidth="90vw",t.style.maxHeight="85vh",t.style.overflowY="");const o=t.querySelector(".guild-modal-header");o&&o.remove();const r=document.createElement("div");r.className="guild-modal-header",r.style.cssText=`\n                position: absolute; top: 0; left: 0; right: 0; height: 40px;\n                background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n                cursor: ${n?"default":"move"}; border-radius: 0.75rem 0.75rem 0 0;\n                display: flex; align-items: center; justify-content: space-between;\n                padding: 0 16px; color: white; font-weight: 600;\n                user-select: none; z-index: 50; pointer-events: auto;\n            `;const a=document.createElement("span");a.textContent="Guild Panel",a.style.cursor=n?"default":"move";const i=document.createElement("button");i.textContent="✕",i.style.cssText="\n                background: none; border: none; color: white; font-size: 24px;\n                cursor: pointer; padding: 0; margin: 0;\n                display: flex; align-items: center; justify-content: center;\n                width: 30px; height: 30px; border-radius: 4px; transition: background-color 0.2s;\n            ",i.onmouseover=()=>i.style.backgroundColor="rgba(255,255,255,0.2)",i.onmouseout=()=>i.style.backgroundColor="transparent",i.onclick=t=>{if(t.stopPropagation(),"function"==typeof window.toggleMyGuildModal)window.toggleMyGuildModal();else{const t=document.querySelector('#myGuildModal .close-modal, #myGuildModal [onclick*="toggleMyGuildModal"]');t?t.click():e.style.display="none"}},r.appendChild(a),r.appendChild(i);const l=document.createElement("div");l.className="guild-modal-resize",l.style.cssText="\n                position: absolute; bottom: 0; right: 0; width: 20px; height: 20px;\n                cursor: nwse-resize;\n                background: linear-gradient(135deg, transparent 0%, #3b82f6 100%);\n                border-radius: 0 0 0.75rem 0; z-index: 51; pointer-events: auto;\n            ",t.style.paddingTop="50px",t.firstChild?t.insertBefore(r,t.firstChild):t.appendChild(r),n||(t.appendChild(l),function(e,t){let n=!1,o=0,r=0,a=0,i=0;const l=t=>{if(t.target.closest(".guild-modal-resize")||t.target.closest("button"))return;n=!0,o=t.clientX,r=t.clientY;const l=e.getBoundingClientRect();a=l.left,i=l.top,e.style.userSelect="none",document.addEventListener("mousemove",s,!0),document.addEventListener("mouseup",c,!0),t.preventDefault(),t.stopPropagation()},s=t=>{if(!n)return;const l=t.clientX-o,s=t.clientY-r;e.style.left=a+l+"px",e.style.top=i+s+"px"},c=()=>{n=!1,e.style.userSelect="auto",document.removeEventListener("mousemove",s,!0),document.removeEventListener("mouseup",c,!0)};t.addEventListener("mousedown",l,!0);const d=e.querySelector(".guild-modal-header");d&&d!==t&&d.addEventListener("mousedown",l,!0)}(t,a),function(e,t){let n=!1,o=0,r=0,a=0,i=0;t.addEventListener("mousedown",t=>{n=!0,o=t.clientX,r=t.clientY;const c=e.getBoundingClientRect();a=c.width,i=c.height,e.style.userSelect="none",document.addEventListener("mousemove",l,!0),document.addEventListener("mouseup",s,!0),t.preventDefault(),t.stopPropagation()});const l=t=>{if(!n)return;const l=Math.max(300,a+(t.clientX-o)),s=Math.max(200,i+(t.clientY-r));e.style.width=l+"px",e.style.maxHeight=s+"px"},s=()=>{n=!1,e.style.userSelect="auto",document.removeEventListener("mousemove",l,!0),document.removeEventListener("mouseup",s,!0)}}(t,l)),function(){const e=document.getElementById("guildInfoMessage");if(!e)return;const t=e.closest("div");if(!t||t.classList.contains("guild-message-section"))return;const n=document.createElement("div");n.className="guild-message-section";const o=document.createElement("div");o.className="guild-message-header",o.innerHTML='<span>Guild Message</span><span class="guild-message-toggle">▼</span>';const r=document.createElement("div");r.className="guild-message-content",t.parentNode.insertBefore(n,t),r.appendChild(t),n.appendChild(o),n.appendChild(r),o.onclick=()=>{r.classList.toggle("collapsed"),o.querySelector(".guild-message-toggle").classList.toggle("collapsed");const e=document.getElementById("infoTab");e&&e.classList.toggle("message-collapsed",r.classList.contains("collapsed"))}}(),function(){if(!document.getElementById("infoTab"))return;const e=document.getElementById("guildMembersContainer");e&&new MutationObserver(()=>{I();const e=S();e&&Object.keys(e).length>0&&T(e)}).observe(e,{childList:!0,subtree:!0});I();const t=document.getElementById("projectsTab");t&&new MutationObserver(()=>{U(),q()}).observe(t,{childList:!0,subtree:!0,attributes:!0});const n=document.getElementById("guildProjectsContainer");n&&new MutationObserver(()=>{q()}).observe(n,{childList:!0,subtree:!0});const o=document.getElementById("projectsTabBtn");o&&(o.onclick,o.addEventListener("click",()=>{setTimeout(()=>{U(),q()},50)}))}(),function(e,t){if(document.getElementById("guild-loading-bar-container"))return;const n=document.createElement("div");n.id="guild-loading-bar-container",n.style.cssText="\n            position: absolute; top: 40px; left: 0; right: 0; height: 3px;\n            background: rgba(0,0,0,0.1); z-index: 52; overflow: hidden;\n            transition: opacity 0.5s ease; cursor: pointer;\n        ";const o=document.createElement("div");o.id="guild-loading-bar",o.style.cssText="\n            height: 100%; width: 0%; background: linear-gradient(90deg, #60a5fa, #3b82f6);\n            transition: width 0.4s ease; border-radius: 0 2px 2px 0;\n            pointer-events: none;\n        ",n.appendChild(o);const r=document.createElement("div");r.id="guild-loading-tooltip",r.style.cssText=`\n            position: fixed; display: none; padding: 6px 10px;\n            background: ${isDarkMode()?"#1e1e2e":"#1f2937"}; color: #f3f4f6;\n            font-size: 11px; line-height: 1.5; border-radius: 6px;\n            box-shadow: 0 4px 12px rgba(0,0,0,0.3); pointer-events: none;\n            z-index: 100000; white-space: nowrap;\n        `,document.body.appendChild(r),n.addEventListener("mouseenter",()=>{r.style.display="block",i()}),n.addEventListener("mouseleave",()=>{r.style.display="none"}),n.addEventListener("mousemove",e=>{r.style.left=e.clientX+12+"px",r.style.top=e.clientY+12+"px"}),t.insertAdjacentElement("afterend",n);const a={modal:{done:!0,weight:10,label:"Modal ready"},stats:{done:!1,weight:20,label:"Guild stats"},members:{done:!1,weight:40,label:"Members list"},xpTracker:{done:!1,weight:30,label:"XP Tracker"}};function i(){const e=Object.values(a).map(e=>(e.done?"✅":"⏳")+" "+e.label);r.innerHTML=e.join("<br>")}function l(){let e=0,t=0;const l=[];for(const[n,o]of Object.entries(a))t+=o.weight,o.done?e+=o.weight:l.push(n);const s=Math.round(e/t*100);o.style.width=s+"%",0===l.length&&(o.style.width="100%",i(),setTimeout(()=>{n.style.opacity="0",setTimeout(()=>{n.remove(),r.remove()},600)},800)),i()}function s(e){a[e]&&!a[e].done&&(a[e].done=!0,l())}l(),setTimeout(function e(){const t=document.getElementById("guildInfoExperience");t&&t.textContent.trim().length>0&&s("stats");const n=document.getElementById("guildMembersContainer");n&&n.querySelectorAll("div.flex.items-center.justify-between").length>0&&s("members"),(document.getElementById("xpTrackerTabBtn")||document.getElementById("xpChangesSection"))&&s("xpTracker"),Object.values(a).every(e=>e.done)||setTimeout(e,300)},200)}(0,r),setTimeout(()=>{U(),q()},200);const s=()=>{n?(t.style.top="8px",t.style.left="8px",t.style.width="calc(100vw - 16px)",t.style.maxWidth="calc(100vw - 16px)",t.style.maxHeight="calc(100dvh - 16px)"):(t.style.top="100px",t.style.left="calc(50% - 25rem)")};new MutationObserver(()=>{e.classList.contains("hidden")||s()}).observe(e,{attributes:!0,attributeFilter:["class"]}),console.log("[Guild Modal] v3.1 - Transformed to draggable floating panel with territories")}catch(e){console.error("[Guild Modal] Error transforming modal:",e)}}function oe(){ne(),function(e){let t=0;!function n(){"undefined"!=typeof map&&map&&map.on&&map.getContainer?e():t++<100&&setTimeout(n,100)}()}(()=>{["move","rotate","zoom"].forEach(e=>map.on(e,j)),new ResizeObserver(j).observe(map.getContainer()),map.once("load",j),console.log("[Guild Territories] Hooked to map events")}),function(e){let t=0;!function n(){"undefined"!=typeof map&&map&&map.on&&map.getContainer?e():t++<100&&setTimeout(n,100)}()}(()=>{["move","rotate","zoom"].forEach(e=>map.on(e,J)),new ResizeObserver(J).observe(map.getContainer()),map.once("load",J),console.log("[Guild Players] Hooked to map events")});new MutationObserver(e=>{for(const t of e)for(const e of t.addedNodes)e.nodeType===Node.ELEMENT_NODE&&("myGuildModal"===e.id||e.querySelector("#myGuildModal"))&&(console.log("[Guild Modal] Modal detected, re-initializing..."),ne())}).observe(document.body,{childList:!0,subtree:!0})}w.textContent='\n        .guild-modal-header {\n            touch-action: none !important;\n            -webkit-user-select: none !important;\n            user-select: none !important;\n        }\n        \n        .guild-modal-header span {\n            touch-action: none !important;\n            -webkit-user-select: none !important;\n            user-select: none !important;\n            display: block;\n            flex: 1;\n            padding-right: 10px;\n        }\n        \n        .draggable-panel {\n            touch-action: none !important;\n        }\n\n        .draggable-panel.gpc-mobile-compat,\n        .draggable-panel.gpc-mobile-compat .guild-modal-header,\n        .draggable-panel.gpc-mobile-compat .guild-modal-header span {\n            touch-action: auto !important;\n        }\n\n        /* Use Tailwind CSS variables for dark mode compatibility */\n        .guild-message-section {\n            border: 1px solid var(--color-gray-200, #e5e7eb);\n            border-radius: 0.5rem;\n            overflow: hidden;\n            background-color: var(--color-white, #fff);\n        }\n\n        .guild-message-header {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            padding: 0.75rem;\n            background-color: var(--color-gray-50, #f9fafb);\n            cursor: pointer;\n            user-select: none;\n            color: var(--color-gray-900, #111827);\n        }\n\n        .guild-message-header:hover {\n            background-color: var(--color-gray-100, #f3f4f6);\n        }\n\n        .guild-message-toggle {\n            display: inline-block;\n            width: 20px;\n            height: 20px;\n            text-align: center;\n            line-height: 20px;\n            font-weight: bold;\n            color: var(--color-gray-500, #6b7280);\n            transition: transform 0.2s ease;\n        }\n\n        .guild-message-toggle.collapsed {\n            transform: rotate(-90deg);\n        }\n\n        .guild-message-content {\n            max-height: 500px;\n            overflow: hidden;\n            transition: max-height 0.3s ease, padding 0.3s ease;\n            padding: 0.75rem;\n            background-color: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n        }\n\n        .guild-message-content.collapsed {\n            max-height: 0;\n            padding: 0;\n        }\n\n        @media (max-width: 1024px) {\n            #infoTab .grid.grid-cols-1.lg\\:grid-cols-3 {\n                grid-template-columns: 1fr !important;\n            }\n            #infoTab .lg\\:col-span-2 { grid-column: auto !important; }\n            #infoTab .lg\\:col-span-1 { grid-column: auto !important; order: 1; }\n            #infoTab > .grid { display: flex; flex-direction: column; }\n            #guildMembersContainer { order: 1; margin-top: 2rem; }\n        }\n\n        #infoTab.message-collapsed > .grid { display: block; }\n        #infoTab.message-collapsed #guildMembersContainer { margin-top: 1rem; }\n\n        .guild-find-btn.visited { background-color: var(--color-purple-500, #a855f7) !important; }\n        .guild-find-btn.visited:hover { background-color: var(--color-purple-600, #9333ea) !important; }\n\n        .xp-changes-section {\n            margin-top: 1.5rem;\n            border: 1px solid var(--color-gray-200, #e5e7eb);\n            border-radius: 0.5rem;\n            overflow: hidden;\n            width: 100%;\n            background-color: var(--color-white, #fff);\n        }\n\n        .xp-changes-header {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            padding: 0.75rem;\n            background-color: var(--color-gray-100, #f1f5f9);\n            cursor: pointer;\n            user-select: none;\n            font-weight: 600;\n            color: var(--color-gray-700, #334155);\n        }\n        .xp-changes-header:hover { background-color: var(--color-gray-200, #e2e8f0); }\n\n        .xp-changes-content { \n            padding: 1rem; \n            background-color: var(--color-white, #fff); \n            color: var(--color-gray-900, #111827);\n            display: block; \n        }\n        .xp-changes-content.hidden { display: none; }\n\n        .daily-brief-table { \n            width: 100%; \n            border-collapse: collapse; \n            margin-top: 10px;\n            color: var(--color-gray-900, #111827);\n        }\n        .daily-brief-table th, .daily-brief-table td { \n            border: 1px solid var(--color-gray-300, #d1d5db); \n            padding: 8px; \n            text-align: left; \n        }\n        .daily-brief-table th { \n            background-color: var(--color-gray-100, #f2f2f2);\n            color: var(--color-gray-900, #111827);\n        }\n        .daily-brief-table td {\n            background-color: var(--color-white, #fff);\n        }\n\n        .xp-gain { color: var(--color-green-500, #22c55e); }\n        .xp-loss { color: var(--color-red-500, #ef4444); }\n        .xp-neutral { color: var(--color-gray-500, #94a3b8); }\n\n        .user-cell-content { display: flex; flex-direction: column; gap: 2px; }\n        .user-name { font-weight: 500; color: var(--color-gray-900, #111827); }\n        .user-coords { font-size: 13px; }\n\n        .member-icon-btn {\n            display: inline-flex; align-items: center; justify-content: center;\n            width: 24px; height: 24px; border-radius: 4px; cursor: pointer;\n            transition: background-color 0.2s; margin-left: 4px; border: none;\n            background: transparent; padding: 0;\n        }\n        .member-icon-btn:hover { background-color: var(--color-gray-100, rgba(0,0,0,0.05)); }\n        .discord-icon { color: #5865F2; }\n        .map-icon { color: var(--color-sky-500, #0ea5e9); }\n        .map-icon.out-of-territory { color: var(--color-red-500, #ef4444); }\n        .map-icon.visited { color: var(--color-purple-500, #a855f7); }\n        \n        .control-button {\n            padding: 6px 12px; \n            border: 1px solid var(--color-gray-300, #d1d5db); \n            background: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n            border-radius: 4px; \n            cursor: pointer; \n            font-size: 12px; \n            transition: background-color 0.2s;\n        }\n        .control-button:hover { background-color: var(--color-gray-100, #f0f0f0); }\n        .control-button.active { \n            background-color: var(--color-blue-500, #3b82f6); \n            color: var(--color-white, #fff); \n            border-color: var(--color-blue-500, #3b82f6); \n        }\n        \n        .trash-btn {\n            background: none; border: none; \n            color: var(--color-red-500, #ef4444); \n            cursor: pointer;\n            padding: 2px 4px; font-size: 12px;\n        }\n        .trash-btn:hover { color: var(--color-red-600, #dc2626); }\n        \n        .tooltip-popup {\n            position: fixed; \n            background: var(--color-gray-800, #333); \n            color: var(--color-gray-100, #fff); \n            padding: 4px 8px;\n            border-radius: 4px; font-size: 12px; z-index: 10000; pointer-events: none;\n            opacity: 0; transition: opacity 0.2s;\n        }\n        .tooltip-popup.visible { opacity: 1; }\n\n        #snapshotIntervalSelect {\n            background-color: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n        }\n        #snapshotIntervalSelect:hover {\n            border-color: var(--color-blue-500, #3b82f6) !important;\n            box-shadow: 0 0 4px rgba(59, 130, 246, 0.2) !important;\n        }\n\n        #snapshotIntervalSelect:focus {\n            border-color: var(--color-blue-500, #3b82f6) !important;\n            box-shadow: 0 0 6px rgba(59, 130, 246, 0.3) !important;\n            outline: none !important;\n        }\n\n        /* --- Player Markers Overlay Styles --- */\n        #players-container {\n            position: absolute;\n            inset: 0;\n            pointer-events: none;\n            z-index: 5;\n            overflow: hidden;\n        }\n\n        .player-marker {\n            position: absolute;\n            pointer-events: auto;\n            cursor: pointer;\n            transform: translate(-50%, -100%);\n            transition: transform 0.15s ease;\n            filter: drop-shadow(0 2px 4px rgba(0,0,0,0.35));\n        }\n\n        .player-marker:hover {\n            transform: translate(-50%, -100%) scale(1.25);\n            z-index: 10;\n        }\n\n        .player-marker-tooltip {\n            position: absolute;\n            bottom: 100%;\n            left: 50%;\n            transform: translateX(-50%);\n            margin-bottom: 6px;\n            background: var(--color-gray-800, #1f2937);\n            color: var(--color-gray-100, #f3f4f6);\n            padding: 4px 8px;\n            border-radius: 4px;\n            font-size: 11px;\n            font-weight: 600;\n            white-space: nowrap;\n            pointer-events: none;\n            opacity: 0;\n            transition: opacity 0.15s ease;\n            box-shadow: 0 2px 6px rgba(0,0,0,0.25);\n        }\n\n        .player-marker-tooltip::after {\n            content: \'\';\n            position: absolute;\n            top: 100%;\n            left: 50%;\n            transform: translateX(-50%);\n            border: 5px solid transparent;\n            border-top-color: var(--color-gray-800, #1f2937);\n        }\n\n        .player-marker:hover .player-marker-tooltip {\n            opacity: 1;\n        }\n\n        .player-marker.show-label .player-marker-tooltip {\n            opacity: 1;\n        }\n\n        .player-marker-options {\n            display: flex;\n            align-items: center;\n            gap: 14px;\n            padding: 4px 0;\n        }\n\n        .player-marker-options label {\n            display: flex;\n            align-items: center;\n            gap: 5px;\n            font-size: 12px;\n            font-weight: 500;\n            color: var(--color-gray-600, #4b5563);\n            cursor: pointer;\n            user-select: none;\n        }\n\n        .player-marker-options input[type="checkbox"] {\n            width: 14px;\n            height: 14px;\n            cursor: pointer;\n            accent-color: var(--color-blue-500, #3b82f6);\n        }\n\n        /* --- Territory Overlay Styles --- */\n        #territory-canvas {\n            position: absolute;\n            inset: 0;\n            pointer-events: none;\n            z-index: 5;\n        }\n\n        /* Territory Controls Container */\n        #territoryControlsContainer {\n            background-color: var(--color-gray-100, #f0f9ff);\n            border: 1px solid var(--color-gray-300, #bae6fd);\n        }\n\n        .territory-setting-row {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            gap: 12px;\n        }\n\n        .territory-setting-row label {\n            font-size: 13px;\n            font-weight: 500;\n            color: var(--color-gray-700, #374151);\n        }\n\n        .territory-settings-collapsible {\n            width: 100%;\n            border: 1px solid var(--color-gray-300, #d1d5db);\n            border-radius: 8px;\n            overflow: hidden;\n            background: var(--color-white, #fff);\n        }\n\n        .territory-settings-toggle {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            padding: 8px 12px;\n            background: var(--color-gray-100, #f3f4f6);\n            cursor: pointer;\n            user-select: none;\n            font-size: 13px;\n            font-weight: 600;\n            color: var(--color-blue-500, #3b82f6);\n            border: none;\n            width: 100%;\n        }\n\n        .territory-settings-toggle:hover {\n            background: var(--color-gray-200, #e5e7eb);\n        }\n\n        .territory-settings-toggle .toggle-arrow {\n            transition: transform 0.2s ease;\n            font-size: 11px;\n        }\n\n        .territory-settings-toggle .toggle-arrow.collapsed {\n            transform: rotate(-90deg);\n        }\n\n        .territory-settings-content {\n            padding: 12px;\n            display: flex;\n            flex-direction: column;\n            gap: 10px;\n            border-top: 1px solid var(--color-gray-200, #e5e7eb);\n            background: var(--color-white, #fff);\n        }\n\n        .territory-settings-content.collapsed {\n            display: none;\n        }\n\n        .territory-section-divider {\n            border-top: 1px solid var(--color-gray-200, #e5e7eb);\n            margin: 2px 0;\n            padding-top: 4px;\n            font-size: 11px;\n            font-weight: 600;\n            color: var(--color-gray-500, #6b7280);\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n        }\n\n        .territory-toggle-btn {\n            display: inline-flex;\n            align-items: center;\n            gap: 6px;\n            padding: 8px 16px;\n            border-radius: 8px;\n            font-size: 13px;\n            font-weight: 600;\n            cursor: pointer;\n            border: none;\n            transition: all 0.2s;\n        }\n\n        .territory-toggle-btn.active {\n            background: var(--color-blue-500, #3b82f6);\n            color: var(--color-white, #fff);\n            box-shadow: 0 2px 8px rgba(59,130,246,0.3);\n        }\n\n        .territory-toggle-btn.inactive {\n            background: var(--color-gray-200, #e5e7eb);\n            color: var(--color-gray-700, #374151);\n        }\n\n        .territory-toggle-btn.inactive:hover {\n            background: var(--color-gray-300, #d1d5db);\n        }\n\n        /* Territory settings inputs */\n        .territory-settings-content input[type="color"] {\n            border: 2px solid var(--color-gray-300, #d1d5db);\n        }\n        .territory-settings-content select {\n            background-color: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n            border: 1px solid var(--color-gray-300, #d1d5db);\n        }\n        .territory-settings-content input[type="range"] {\n            accent-color: var(--color-blue-500, #3b82f6);\n        }\n\n        /* Info text in territory controls */\n        .territory-info-text {\n            font-size: 12px;\n            color: var(--color-gray-500, #64748b);\n        }\n\n        /* --- Modal Styling for Dark Mode Compatibility --- */\n        .gmi-modal-overlay {\n            position: fixed;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            background: rgba(0, 0, 0, 0.5);\n            z-index: 9999;\n        }\n\n        .gmi-modal {\n            position: fixed;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n            background: var(--color-white, #fff);\n            border: 2px solid var(--color-blue-500, #3b82f6);\n            border-radius: 8px;\n            padding: 20px;\n            z-index: 10000;\n            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);\n            color: var(--color-gray-900, #111827);\n        }\n\n        .gmi-modal h3 {\n            margin: 0 0 15px 0;\n            font-size: 18px;\n            font-weight: bold;\n            color: var(--color-gray-900, #111827);\n        }\n\n        .gmi-modal-btn {\n            display: block;\n            width: 100%;\n            padding: 10px;\n            margin: 8px 0;\n            border: 1px solid var(--color-gray-300, #d1d5db);\n            border-radius: 4px;\n            background: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n            cursor: pointer;\n            font-size: 14px;\n            transition: background-color 0.2s;\n            text-align: left;\n        }\n\n        .gmi-modal-btn:hover {\n            background-color: var(--color-gray-100, #f3f4f6);\n        }\n\n        .gmi-modal-btn.danger {\n            color: var(--color-red-500, #ef4444);\n        }\n\n        .gmi-modal-btn.danger:hover {\n            background-color: rgba(239, 68, 68, 0.1);\n        }\n\n        .gmi-modal-btn.warning {\n            color: var(--color-yellow-500, #f59e0b);\n        }\n\n        .gmi-modal-btn.warning:hover {\n            background-color: rgba(245, 158, 11, 0.1);\n        }\n\n        .gmi-modal-btn.primary {\n            color: var(--color-blue-500, #3b82f6);\n        }\n\n        .gmi-modal-btn.primary:hover {\n            background-color: rgba(59, 130, 246, 0.1);\n        }\n\n        .gmi-modal-section {\n            padding: 10px;\n            background: var(--color-gray-50, #f9fafb);\n            border-radius: 4px;\n            border: 1px solid var(--color-gray-200, #e5e7eb);\n            margin-bottom: 15px;\n        }\n\n        .gmi-modal-select {\n            padding: 6px 10px;\n            border: 1px solid var(--color-gray-300, #d1d5db);\n            border-radius: 4px;\n            background: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n            font-size: 12px;\n            cursor: pointer;\n        }\n\n        .gmi-modal-label {\n            font-weight: 600;\n            font-size: 12px;\n            color: var(--color-gray-700, #374151);\n            user-select: none;\n        }\n\n        .gmi-checkbox-option {\n            display: flex;\n            align-items: center;\n            padding: 8px;\n            border: 2px solid var(--color-gray-300, #d1d5db);\n            border-radius: 4px;\n            background: var(--color-white, #fff);\n            cursor: pointer;\n            font-size: 12px;\n            transition: all 0.2s;\n        }\n\n        .gmi-checkbox-option:hover {\n            border-color: var(--color-gray-400, #9ca3af);\n        }\n\n        .gmi-checkbox-option input[type="checkbox"] {\n            width: 16px;\n            height: 16px;\n            margin-right: 8px;\n            cursor: pointer;\n            accent-color: var(--color-blue-500, #3b82f6);\n        }\n\n        .gmi-snapshot-list {\n            flex: 1;\n            overflow-y: auto;\n            border: 1px solid var(--color-gray-200, #e5e7eb);\n            border-radius: 4px;\n            padding: 10px;\n            margin-bottom: 15px;\n            background: var(--color-gray-50, #f9fafb);\n        }\n\n        .gmi-snapshot-item {\n            display: flex;\n            align-items: center;\n            padding: 8px;\n            margin: 4px 0;\n            background: var(--color-white, #fff);\n            border-radius: 4px;\n            border: 1px solid var(--color-gray-200, #e5e7eb);\n            transition: background-color 0.2s, border-color 0.2s;\n        }\n\n        .gmi-snapshot-item.selected {\n            background: rgba(239, 68, 68, 0.1);\n            border-color: var(--color-red-300, #fca5a5);\n        }\n\n        .gmi-snapshot-item label {\n            flex: 1;\n            cursor: pointer;\n            font-size: 12px;\n            color: var(--color-gray-700, #374151);\n        }\n\n        .gmi-snapshot-item.selected label {\n            color: var(--color-red-700, #b91c1c);\n            text-decoration: line-through;\n        }\n\n        .gmi-action-btn {\n            flex: 1;\n            min-width: 120px;\n            padding: 12px 16px;\n            border: none;\n            border-radius: 6px;\n            font-weight: 600;\n            font-size: 13px;\n            cursor: pointer;\n            transition: all 0.3s ease;\n            box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 6px;\n        }\n\n        .gmi-action-btn.danger {\n            background: var(--color-red-500, #dc2626);\n            color: var(--color-white, #fff);\n        }\n\n        .gmi-action-btn.danger:hover {\n            background: var(--color-red-600, #b91c1c);\n        }\n\n        .gmi-action-btn.primary {\n            background: var(--color-blue-500, #3b82f6);\n            color: var(--color-white, #fff);\n        }\n\n        .gmi-action-btn.primary:hover {\n            background: var(--color-blue-600, #2563eb);\n        }\n\n        .gmi-action-btn.success {\n            background: var(--color-green-500, #10b981);\n            color: var(--color-white, #fff);\n        }\n\n        .gmi-action-btn.success:hover {\n            background: var(--color-green-600, #059669);\n        }\n\n        .gmi-action-btn.neutral {\n            background: var(--color-gray-100, #f3f4f6);\n            color: var(--color-gray-600, #6b7280);\n        }\n\n        .gmi-action-btn.neutral:hover {\n            background: var(--color-gray-200, #e5e7eb);\n        }\n\n        /* Progress popup */\n        .gmi-progress-popup {\n            position: fixed;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n            background: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n            padding: 20px;\n            border-radius: 8px;\n            box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n            z-index: 10000;\n            min-width: 300px;\n            text-align: center;\n        }\n\n        .gmi-progress-popup p {\n            color: var(--color-gray-700, #374151);\n        }\n\n        .gmi-progress-bar-container {\n            width: 100%;\n            height: 20px;\n            background: var(--color-gray-200, #e5e7eb);\n            border-radius: 4px;\n            margin-top: 10px;\n            overflow: hidden;\n        }\n\n        .gmi-progress-bar {\n            height: 100%;\n            background: var(--color-blue-500, #3b82f6);\n            transition: width 0.3s;\n        }\n\n        /* CSV Modal */\n        .gmi-csv-modal {\n            position: fixed;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n            background-color: var(--color-white, #fff);\n            padding: 20px;\n            border-radius: 8px;\n            box-shadow: 0 4px 20px rgba(0,0,0,0.2);\n            z-index: 10002;\n            width: 500px;\n            max-width: 90%;\n            display: flex;\n            flex-direction: column;\n            gap: 10px;\n        }\n\n        .gmi-csv-modal h3 {\n            margin: 0 0 10px 0;\n            color: var(--color-gray-800, #1e293b);\n            font-size: 1.25rem;\n            font-weight: 600;\n        }\n\n        .gmi-csv-modal textarea {\n            width: 100%;\n            height: 300px;\n            font-family: monospace;\n            font-size: 12px;\n            border: 1px solid var(--color-gray-300, #ccc);\n            border-radius: 4px;\n            resize: vertical;\n            background: var(--color-white, #fff);\n            color: var(--color-gray-900, #111827);\n        }\n    ',document.head.appendChild(w),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",oe):oe(),console.log("[Guild Modal] v3.4.0 - Loaded with territory map overlay, player markers, territory-aware XP tracker, and activity-aware territory coloring")}(),_featureStatus.guildOverhaul="ok",console.log("[GeoPixelcons++] ✅ Guild Overhaul loaded")}catch(I){_featureStatus.guildOverhaul="error",dbgPush(`Guild Overhaul init failed: ${I&&I.message?I.message:String(I)}`,{error:I,uiComponent:"Guild Overhaul"}),console.error("[GeoPixelcons++] ❌ Guild Overhaul failed:",I)}if(_settings.paintBrushSwap)try{!function(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;function t(e,t){try{const n=document.createElement("script");n.textContent=`${e} = ${JSON.stringify(t)};`,(document.head||document.documentElement).appendChild(n),n.remove()}catch{}}function n(e){try{const t=document.createElement("script");t.textContent=e,(document.head||document.documentElement).appendChild(t),t.remove()}catch{}}const o=!1,r="brushPresets",a="brushSwapDropdownSize",i={brushes:[],nextId:1,dropdownOpen:!1,isRenaming:null,scrollIndex:-1,activeBrushId:null,dragState:null};function l(){localStorage.setItem(r,JSON.stringify(i.brushes))}function s(e,t){const n=i.brushes.find(t=>t.id===e);n&&(n.name=t.trim()||`Brush ${e}`,l(),u())}function c(o){i.activeBrushId=o.id,t("BrushSize",o.brushSize),t("currentBrushPattern",[...o.pattern]),e.BrushSize=o.brushSize,e.currentBrushPattern=[...o.pattern],e.userConfig&&(e.userConfig={...e.userConfig,currentBrushPattern:e.currentBrushPattern,brushSize:e.BrushSize},localStorage.setItem("userConfig",JSON.stringify(e.userConfig))),e.saveConfigServer?.(),n("generateBrushGrid(currentBrushPattern)")}function d(){const e=document.getElementById("brushEditorPanel");if(e){if(!e.querySelector("#gpc-brush-fill-btn")){const t=e.querySelector('button[onclick="resetBrush()"]');if(t){const e=t.parentElement;t.classList.remove("w-full"),t.style.width="50%";const n=document.createElement("button");n.id="gpc-brush-fill-btn",n.style.width="50%",n.className="py-2 text-sm text-gray-500 hover:text-green-600 hover:bg-gray-50 rounded transition cursor-pointer text-center",n.textContent="Fill All",n.title="Set all cells to active",n.onclick=()=>{const e=document.getElementById("brushGrid");e&&e.querySelectorAll("[data-x][data-y]").forEach(e=>{e.dataset.active="true",e.classList.add("!bg-gray-800"),e.classList.remove("bg-white","hover:bg-gray-100","bg-red-100","hover:bg-red-200")})},e.style.display="flex",e.style.gap="8px",e.appendChild(n)}}!function(){const e=document.getElementById("brushGrid");if(!e||e._gpcDragInstalled)return;function t(e,t){if(!e||!e.dataset||!("x"in e.dataset))return;const n="true"===e.dataset.isCenter;e.dataset.active=t?"true":"false",t?(e.classList.add("!bg-gray-800"),e.classList.remove("bg-white","hover:bg-gray-100","bg-red-100","hover:bg-red-200")):(e.classList.remove("!bg-gray-800"),n?e.classList.add("bg-red-100","hover:bg-red-200"):e.classList.add("bg-white","hover:bg-gray-100"))}function n(){e.querySelectorAll("[data-x][data-y]").forEach(e=>{e.onclick=null})}e._gpcDragInstalled=!0,n();new MutationObserver(n).observe(e,{childList:!0});let o=!1,r=null;e.addEventListener("mousedown",e=>{const n=e.target.closest("[data-x][data-y]");n&&(e.preventDefault(),0===e.button?(r="paint",o=!0,t(n,!0)):2===e.button&&(r="erase",o=!0,t(n,!1)))}),e.addEventListener("mousemove",e=>{if(!o||!r)return;const n=document.elementFromPoint(e.clientX,e.clientY),a=n?n.closest("[data-x][data-y]"):null;a&&t(a,"paint"===r)}),e.addEventListener("contextmenu",e=>{e.preventDefault()}),document.addEventListener("mouseup",()=>{o=!1,r=null})}()}}function p(e){const t=document.createElement("div");t.className="brush-swap-preview-grid";const n=new Map,o=Math.floor(e.brushSize/2);let r=1/0,a=-1/0,i=1/0,l=-1/0;e.pattern.forEach(e=>{const t=e.x+o,s=-1*e.y+o;n.set(`${t},${s}`,!0),r=Math.min(r,t),a=Math.max(a,t),i=Math.min(i,s),l=Math.max(l,s)});const s=a-r+1,c=l-i+1,d=Math.max(s,c),p=Math.max(4,Math.floor(32/d)),g=r+Math.floor((a-r)/2),u=i+Math.floor((l-i)/2);for(let e=i;e<=l;e++)for(let o=r;o<=a;o++){const r=document.createElement("div");r.className="brush-swap-preview-cell",r.style.width=p+"px",r.style.height=p+"px";const a=o===g&&e===u;n.has(`${o},${e}`)&&(r.classList.add("active"),a&&r.classList.add("center")),t.appendChild(r)}return t.style.gridTemplateColumns=`repeat(${s}, ${p}px)`,t}function g(){const e=document.getElementById("gpc-brush-import-modal");if(e)return void e.remove();const t=document.body.classList.contains("dark")||window.matchMedia("(prefers-color-scheme: dark)").matches,n=document.createElement("div");n.id="gpc-brush-import-modal",n.style.cssText="\n            position: fixed; inset: 0; z-index: 100000;\n            background: rgba(0,0,0,0.5); display: flex;\n            align-items: center; justify-content: center;\n            font-family: system-ui, -apple-system, sans-serif;\n        ",n.addEventListener("click",e=>{e.target===n&&n.remove()});const o=document.createElement("div");o.style.cssText=`\n            background: ${t?"#1e1e2e":"#ffffff"};\n            color: ${t?"#cdd6f4":"#1e293b"};\n            border-radius: 12px; padding: 0; width: 480px; max-width: 95vw;\n            box-shadow: 0 20px 60px rgba(0,0,0,0.3); overflow: hidden;\n        `;const r=document.createElement("div");r.style.cssText=`\n            padding: 14px 20px; display: flex; align-items: center;\n            justify-content: space-between;\n            background: ${t?"#313244":"#f1f5f9"};\n            border-bottom: 1px solid ${t?"#45475a":"#e2e8f0"};\n        `,r.innerHTML='<span style="font-weight:700;font-size:15px;">📥 Import Brushes</span>';const a=document.createElement("button");a.textContent="✕",a.style.cssText=`background:none;border:none;font-size:18px;cursor:pointer;color:${t?"#a6adc8":"#64748b"};padding:4px 8px;border-radius:4px;`,a.onmouseenter=()=>a.style.background=t?"#45475a":"#e2e8f0",a.onmouseleave=()=>a.style.background="none",a.onclick=()=>n.remove(),r.appendChild(a),o.appendChild(r);const s=document.createElement("div");s.style.cssText="padding: 16px 20px; display: flex; flex-direction: column; gap: 12px;";const c=document.createElement("div");c.style.cssText=`font-size:13px;color:${t?"#a6adc8":"#64748b"};`,c.textContent="Paste brush JSON or upload a file. Select which brushes to add — they will be appended to your existing list.",s.appendChild(c);const d=document.createElement("div");d.style.cssText=`font-size:12px;font-weight:600;min-height:16px;color:${t?"#a6e3a1":"#16a34a"};`,s.appendChild(d);const p=document.createElement("textarea");p.placeholder="Paste JSON here…",p.style.cssText=`\n            width: 100%; min-height: 120px; max-height: 200px; box-sizing: border-box;\n            padding: 10px; font-family: monospace; font-size: 12px;\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            border-radius: 8px; resize: vertical; outline: none;\n            background: ${t?"#181825":"#f8fafc"};\n            color: ${t?"#cdd6f4":"#1e293b"};\n        `,s.appendChild(p);const g=document.createElement("div");g.style.cssText=`\n            display: none; flex-direction: column; gap: 2px;\n            max-height: 160px; overflow-y: auto;\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            border-radius: 8px; padding: 6px 8px;\n            background: ${t?"#181825":"#f8fafc"};\n        `;const m=document.createElement("div");m.style.cssText="display:flex;gap:10px;margin-bottom:4px;";const h=document.createElement("button");h.textContent="Select All",h.style.cssText=`background:none;border:none;cursor:pointer;font-size:11px;font-weight:600;padding:0;color:${t?"#89b4fa":"#3b82f6"};`;const f=document.createElement("button");f.textContent="Select None",f.style.cssText=h.style.cssText,m.appendChild(h),m.appendChild(f),g.appendChild(m);let b=[],y=[];function x(e){let n;try{n=JSON.parse(e.trim())}catch(e){return d.style.color=t?"#f38ba8":"#dc2626",d.textContent="❌ Invalid JSON: "+e.message,void(g.style.display="none")}if(!Array.isArray(n))return d.style.color=t?"#f38ba8":"#dc2626",d.textContent="❌ Expected a JSON array of brush objects.",void(g.style.display="none");b=n.filter(e=>Array.isArray(e.pattern)&&"number"==typeof e.brushSize);const o=n.length-b.length;if(0===b.length)return d.style.color=t?"#f38ba8":"#dc2626",d.textContent="❌ No valid brush objects found.",void(g.style.display="none");d.style.color=t?"#a6adc8":"#64748b",d.textContent=`Found ${b.length} brush${1!==b.length?"es":""}${o?` (${o} invalid skipped)`:""} — select which to add:`,function(e){for(;g.children.length>1;)g.removeChild(g.lastChild);y=[],e.forEach(e=>{const n=document.createElement("label");n.style.cssText="display:flex;align-items:center;gap:8px;padding:3px 2px;cursor:pointer;border-radius:4px;font-size:13px;",n.onmouseenter=()=>n.style.background=t?"#313244":"#f1f5f9",n.onmouseleave=()=>n.style.background="none";const o=document.createElement("input");o.type="checkbox",o.checked=!0,o.style.cssText="flex-shrink:0;cursor:pointer;accent-color:#3b82f6;";const r=document.createElement("span");r.textContent="string"==typeof e.name&&e.name.trim()?e.name.trim():"Unnamed brush",r.style.cssText="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",n.appendChild(o),n.appendChild(r),g.appendChild(n),y.push({cb:o,brush:e})}),h.onclick=()=>{y.forEach(e=>{e.cb.checked=!0})},f.onclick=()=>{y.forEach(e=>{e.cb.checked=!1})},g.style.display="flex"}(b)}p.addEventListener("input",()=>{p.value.trim()?x(p.value):(g.style.display="none",d.textContent="")}),s.appendChild(g);const v=document.createElement("div");v.style.cssText="display:flex;gap:8px;justify-content:space-between;align-items:center;";const w=document.createElement("input");w.type="file",w.accept=".json,application/json",w.style.display="none",w.addEventListener("change",()=>{const e=w.files[0];if(!e)return;const t=new FileReader;t.onload=e=>{p.value=e.target.result,x(e.target.result)},t.readAsText(e),w.value=""}),s.appendChild(w);const k=document.createElement("button");k.style.cssText=`\n            padding: 7px 14px; border-radius: 8px; border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            cursor: pointer; font-size: 13px; font-weight: 600;\n            background: ${t?"#313244":"#f1f5f9"}; color: ${t?"#cdd6f4":"#1e293b"};\n            transition: background 0.15s;\n        `,k.textContent="📁 Upload File",k.onmouseenter=()=>k.style.background=t?"#45475a":"#e2e8f0",k.onmouseleave=()=>k.style.background=t?"#313244":"#f1f5f9",k.onclick=()=>w.click();const E=document.createElement("button");E.style.cssText=`\n            padding: 7px 16px; border-radius: 8px; border: none; cursor: pointer; font-size: 13px; font-weight: 600;\n            background: ${t?"#89b4fa":"#3b82f6"}; color: ${t?"#1e1e2e":"#ffffff"};\n            transition: background 0.15s;\n        `,E.textContent="✅ Import Selected",E.onmouseenter=()=>E.style.background=t?"#74c7ec":"#2563eb",E.onmouseleave=()=>E.style.background=t?"#89b4fa":"#3b82f6",E.onclick=()=>{const e=y.filter(e=>e.cb.checked).map(e=>e.brush);if(0===e.length)return d.style.color=t?"#f38ba8":"#dc2626",void(d.textContent="❌ No brushes selected.");e.forEach(e=>{i.brushes.push({id:i.nextId++,name:"string"==typeof e.name&&e.name.trim()?e.name.trim():"Brush "+(i.nextId-1),pattern:e.pattern,brushSize:e.brushSize})}),l(),d.style.color=t?"#a6e3a1":"#16a34a",d.textContent=`✅ Added ${e.length} brush${1!==e.length?"es":""}. Total: ${i.brushes.length}.`,p.value="",g.style.display="none",b=[],y=[],i.dropdownOpen&&u()},v.appendChild(k),v.appendChild(E),s.appendChild(v),o.appendChild(s),n.appendChild(o),document.body.appendChild(n),setTimeout(()=>p.focus(),50)}function u(){let e=document.getElementById("brush-swap-dropdown");if(!e)return;const t=e.querySelector(".brush-swap-items");if(t.innerHTML="",0===i.brushes.length){const e=document.createElement("div");return e.className="text-center text-gray-500 dark:text-gray-400 text-xs py-3 px-2",e.textContent="No saved brushes",void t.appendChild(e)}i.brushes.forEach((e,n)=>{const o=document.createElement("div"),r=e.id===i.activeBrushId;o.className="flex items-center gap-2 p-1.5 border border-gray-200 dark:border-gray-600 rounded bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700"+(r?" brush-swap-item-active":""),o.dataset.brushId=e.id,o.dataset.brushIdx=n;const a=document.createElement("div");a.className="brush-swap-preview-wrap";const d=p(e);a.appendChild(d),a.addEventListener("click",e=>{e.stopPropagation(),a.classList.toggle("expanded")});let g=null;a.addEventListener("mouseenter",e=>{g=document.createElement("div"),g.className="brush-swap-quick-tip",g.textContent="click to expand",g.style.left=e.clientX+12+"px",g.style.top=e.clientY-8+"px",document.body.appendChild(g)}),a.addEventListener("mousemove",e=>{g&&(g.style.left=e.clientX+12+"px",g.style.top=e.clientY-8+"px")}),a.addEventListener("mouseleave",()=>{g&&(g.remove(),g=null)}),o.appendChild(a);const h=document.createElement("div");h.className="flex-1 flex flex-col gap-1";const f=document.createElement("div");if(f.className="flex items-center gap-1 flex-1",i.isRenaming===e.id){const t=document.createElement("input");t.type="text",t.className="flex-1 px-1 py-0.5 text-xs border border-gray-500 dark:border-gray-400 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100",t.value=e.name,t.maxLength=30,t.addEventListener("blur",()=>{s(e.id,t.value),i.isRenaming=null}),t.addEventListener("keydown",n=>{"Enter"===n.key&&(s(e.id,t.value),i.isRenaming=null)}),f.appendChild(t),setTimeout(()=>t.focus(),0)}else{const t=document.createElement("span");t.className="flex-1 text-xs font-medium text-gray-900 dark:text-gray-100 whitespace-nowrap overflow-hidden text-ellipsis",t.textContent=e.name,f.appendChild(t);const n=document.createElement("button");n.className="bg-none border-none cursor-pointer p-0 text-xs opacity-60 hover:opacity-100 transition-opacity flex-shrink-0",n.title="Rename brush",n.innerHTML="✏️",n.addEventListener("click",t=>{t.stopPropagation(),i.isRenaming=e.id,u()}),f.appendChild(n)}h.appendChild(f);const b=document.createElement("div");b.className="flex gap-1 flex-shrink-0";const y=document.createElement("button");y.className="px-1.5 py-0.5 text-xs border border-gray-300 dark:border-gray-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 cursor-pointer rounded transition-colors hover:bg-blue-50 dark:hover:bg-blue-900 hover:border-blue-400 dark:hover:border-blue-400",y.textContent="Load",y.addEventListener("click",t=>{t.stopPropagation(),function(e){const t=i.brushes.find(t=>t.id===e);t&&(c(t),i.activeBrushId=e,m())}(e.id)});const x=document.createElement("button");x.className="px-1 py-0.5 text-xs bg-none border border-gray-300 dark:border-gray-500 opacity-60 hover:opacity-100 transition-opacity cursor-pointer rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 hover:bg-red-50 dark:hover:bg-red-900 hover:border-red-400 dark:hover:border-red-400",x.title="Delete brush",x.innerHTML="✕",x.addEventListener("click",t=>{var n;t.stopPropagation(),n=e.id,i.brushes=i.brushes.filter(e=>e.id!==n),l(),u()}),b.appendChild(y),b.appendChild(x),h.appendChild(b),o.appendChild(h);const v=document.createElement("div");v.className="brush-swap-drag-handle",v.title="Drag to reorder";for(let e=0;e<4;e++){const e=document.createElement("div");e.className="brush-swap-drag-handle-dot",v.appendChild(e)}var w,k,E;w=o,k=n,E=t,v.addEventListener("mousedown",e=>{e.preventDefault(),e.stopPropagation();const t=Array.from(E.querySelectorAll("[data-brush-idx]")),n=t.map(e=>e.getBoundingClientRect());let o=k;w.classList.add("brush-swap-item-dragging");let r=E.querySelector(".brush-swap-drop-indicator");function a(e){const a=e.clientY;let i=t.length;for(let e=0;e<n.length;e++)if(a<n[e].top+n[e].height/2){i=e;break}i!==o&&(o=i,r&&r.remove(),r=document.createElement("div"),r.className="brush-swap-drop-indicator",i<t.length?E.insertBefore(r,t[i]):E.appendChild(r))}document.addEventListener("mousemove",a),document.addEventListener("mouseup",function e(){if(document.removeEventListener("mousemove",a),document.removeEventListener("mouseup",e),w.classList.remove("brush-swap-item-dragging"),r&&r.remove(),o!==k&&o!==k+1){const[e]=i.brushes.splice(k,1),t=o>k?o-1:o;i.brushes.splice(t,0,e),l();const n=i.brushes.findIndex(t=>t.id===e.id);i.scrollIndex===k&&(i.scrollIndex=n)}u()})}),o.appendChild(v),t.appendChild(o)})}function m(){const e=document.getElementById("brush-swap-dropdown");if(e)if(i.dropdownOpen=!i.dropdownOpen,i.dropdownOpen){const t="true"===localStorage.getItem("gpc-paint-is-top"),n=e.querySelector(".brush-swap-resize-handle");t?(e.style.bottom="auto",e.style.top="100%",e.style.marginBottom="0",e.style.marginTop="8px",n&&(n.className="brush-swap-resize-handle brush-swap-resize-br")):(e.style.top="auto",e.style.bottom="100%",e.style.marginTop="0",e.style.marginBottom="8px",n&&(n.className="brush-swap-resize-handle brush-swap-resize-tr"));try{const t=JSON.parse(localStorage.getItem(a));t&&(e.style.maxWidth=t.w+"px",e.style.maxHeight=t.h+"px")}catch{}e.classList.add("open"),u()}else e.classList.remove("open"),i.isRenaming=null}function h(e){const t=e.querySelector("#commitBtn")||e.querySelector("button");if(!t)return void console.warn("Brush Swap: Could not find commitBtn");const n=document.createElement("div");n.className="relative inline-block";const o=document.createElement("button");o.id="brush-swap-toggle",o.className="bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 cursor-pointer px-2.5 py-1.5 text-xs leading-none font-semibold text-gray-800 dark:text-gray-200 ml-2 inline-flex items-center justify-center rounded hover:bg-gray-200 dark:hover:bg-gray-600 hover:border-gray-600 dark:hover:border-gray-500 active:bg-gray-300 dark:active:bg-gray-800",o.title="Toggle saved brushes",o.innerHTML='<span style="font-size: 10px; font-weight: 600; display: flex; align-items: center; gap: 4px;">▲ brushes</span>',o.addEventListener("click",e=>{e.stopPropagation(),m()});const r=document.createElement("div");r.id="brush-swap-toast",document.body.appendChild(r);let l=null;o.addEventListener("wheel",e=>{if(0===i.brushes.length)return;e.preventDefault(),e.stopPropagation();const t=e.deltaY>0?1:-1,n=i.brushes.length;i.scrollIndex<0||i.scrollIndex>=n?i.scrollIndex=t>0?0:n-1:i.scrollIndex=((i.scrollIndex+t)%n+n)%n;const o=i.brushes[i.scrollIndex];c(o),function(e,t,n){r.innerHTML="";const o=document.createElement("span");o.className="toast-preview",o.appendChild(p(e)),r.appendChild(o);const a=document.createElement("span");a.textContent=e.name,r.appendChild(a),r.style.left=t+"px",r.style.top=n+"px",r.classList.add("visible"),clearTimeout(l),l=setTimeout(()=>r.classList.remove("visible"),900)}(o,e.clientX,e.clientY)},{passive:!1});const s=document.createElement("div");s.id="brush-swap-dropdown",s.className="bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 shadow-lg",s.style.position="absolute";const d=document.createElement("div");d.className="brush-swap-resize-handle brush-swap-resize-tr",s.appendChild(d);let u=null;try{u=JSON.parse(localStorage.getItem(a))}catch{}var h;(h=d).addEventListener("mousedown",e=>{e.preventDefault(),e.stopPropagation();const t=e.clientX,n=e.clientY,o=s.getBoundingClientRect(),r=o.width,i=o.height,l=h.classList.contains("brush-swap-resize-br");s.style.userSelect="none",s.classList.add("brush-swap-resizing");const c=e=>{const o=e.clientX-t,a=e.clientY-n,c=Math.max(150,l?i+a:i-a),d=Math.max(200,r+o);s.style.width=d+"px",s.style.maxWidth=d+"px",s.style.maxHeight=c+"px"},d=()=>{s.style.userSelect="",s.classList.remove("brush-swap-resizing"),document.removeEventListener("mousemove",c,!0),document.removeEventListener("mouseup",d,!0);const e=s.getBoundingClientRect();u={w:Math.round(e.width),h:Math.round(e.height)},localStorage.setItem(a,JSON.stringify(u))};document.addEventListener("mousemove",c,!0),document.addEventListener("mouseup",d,!0)});const f=document.createElement("div");f.className="brush-swap-items",s.appendChild(f);const b=document.createElement("div");b.className="brush-swap-footer";const y=document.createElement("button");y.className="brush-swap-footer-btn",y.innerHTML="📤 Export",y.addEventListener("click",e=>{e.stopPropagation(),function(){const e=document.getElementById("gpc-brush-export-modal");if(e)return void e.remove();const t=document.body.classList.contains("dark")||window.matchMedia("(prefers-color-scheme: dark)").matches,n=document.createElement("div");n.id="gpc-brush-export-modal",n.style.cssText="\n            position: fixed; inset: 0; z-index: 100000;\n            background: rgba(0,0,0,0.5); display: flex;\n            align-items: center; justify-content: center;\n            font-family: system-ui, -apple-system, sans-serif;\n        ",n.addEventListener("click",e=>{e.target===n&&n.remove()});const o=document.createElement("div");o.style.cssText=`\n            background: ${t?"#1e1e2e":"#ffffff"};\n            color: ${t?"#cdd6f4":"#1e293b"};\n            border-radius: 12px; padding: 0; width: 480px; max-width: 95vw;\n            box-shadow: 0 20px 60px rgba(0,0,0,0.3); overflow: hidden;\n        `;const r=document.createElement("span");r.style.cssText="font-weight:700;font-size:15px;",r.textContent="📤 Export Brushes";const a=document.createElement("div");a.style.cssText=`\n            padding: 14px 20px; display: flex; align-items: center;\n            justify-content: space-between;\n            background: ${t?"#313244":"#f1f5f9"};\n            border-bottom: 1px solid ${t?"#45475a":"#e2e8f0"};\n        `;const l=document.createElement("button");l.textContent="✕",l.style.cssText=`background:none;border:none;font-size:18px;cursor:pointer;color:${t?"#a6adc8":"#64748b"};padding:4px 8px;border-radius:4px;`,l.onmouseenter=()=>l.style.background=t?"#45475a":"#e2e8f0",l.onmouseleave=()=>l.style.background="none",l.onclick=()=>n.remove(),a.appendChild(r),a.appendChild(l),o.appendChild(a);const s=document.createElement("div");s.style.cssText="padding: 16px 20px; display: flex; flex-direction: column; gap: 12px;";const c=document.createElement("div");c.style.cssText=`font-size:13px;color:${t?"#a6adc8":"#64748b"};`,c.textContent="Select the brushes to export, then copy or download the JSON.",s.appendChild(c);const d=document.createElement("div");d.style.cssText=`\n            display: flex; flex-direction: column; gap: 2px;\n            max-height: 180px; overflow-y: auto;\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            border-radius: 8px; padding: 6px 8px;\n            background: ${t?"#181825":"#f8fafc"};\n        `;const p=document.createElement("div");p.style.cssText="display:flex;gap:10px;margin-bottom:4px;";const g=document.createElement("button");g.textContent="Select All",g.style.cssText=`background:none;border:none;cursor:pointer;font-size:11px;font-weight:600;padding:0;color:${t?"#89b4fa":"#3b82f6"};`;const u=document.createElement("button");u.textContent="Select None",u.style.cssText=g.style.cssText,p.appendChild(g),p.appendChild(u),d.appendChild(p);const m=[];i.brushes.forEach(e=>{const n=document.createElement("label");n.style.cssText="display:flex;align-items:center;gap:8px;padding:3px 2px;cursor:pointer;border-radius:4px;font-size:13px;",n.onmouseenter=()=>n.style.background=t?"#313244":"#f1f5f9",n.onmouseleave=()=>n.style.background="none";const o=document.createElement("input");o.type="checkbox",o.checked=!0,o.style.cssText="flex-shrink:0;cursor:pointer;accent-color:#3b82f6;",o.addEventListener("change",y);const r=document.createElement("span");r.textContent=e.name,r.style.cssText="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",n.appendChild(o),n.appendChild(r),d.appendChild(n),m.push({cb:o,brush:e})}),g.onclick=()=>{m.forEach(e=>{e.cb.checked=!0}),y()},u.onclick=()=>{m.forEach(e=>{e.cb.checked=!1}),y()},s.appendChild(d);const h=document.createElement("textarea");function f(){return m.filter(e=>e.cb.checked).map(e=>e.brush)}function b(e){return JSON.stringify(e.map(e=>({name:e.name,pattern:e.pattern,brushSize:e.brushSize})),null,2)}function y(){const e=f();r.textContent=`📤 Export Brushes (${e.length} of ${i.brushes.length})`,h.value=e.length?b(e):""}h.readOnly=!0,h.style.cssText=`\n            width: 100%; min-height: 120px; max-height: 200px; box-sizing: border-box;\n            padding: 10px; font-family: monospace; font-size: 12px;\n            border: 1px solid ${t?"#45475a":"#e2e8f0"};\n            border-radius: 8px; resize: vertical; outline: none;\n            background: ${t?"#181825":"#f8fafc"};\n            color: ${t?"#cdd6f4":"#1e293b"};\n        `,h.addEventListener("click",()=>h.select()),s.appendChild(h),y();const x=document.createElement("div");x.style.cssText="display:flex;gap:8px;justify-content:flex-end;";const v=document.createElement("button");v.style.cssText=`\n            padding: 7px 16px; border-radius: 8px; border: none; cursor: pointer; font-size: 13px; font-weight: 600;\n            background: ${t?"#585b70":"#e2e8f0"}; color: ${t?"#cdd6f4":"#1e293b"};\n            transition: background 0.15s;\n        `,v.textContent="📋 Copy to Clipboard",v.onmouseenter=()=>v.style.background=t?"#6c7086":"#cbd5e1",v.onmouseleave=()=>v.style.background=t?"#585b70":"#e2e8f0",v.onclick=()=>{const e=b(f());e&&navigator.clipboard.writeText(e).then(()=>{v.textContent="✅ Copied!",setTimeout(()=>{v.textContent="📋 Copy to Clipboard"},1800)}).catch(()=>{h.select(),document.execCommand("copy"),v.textContent="✅ Copied!",setTimeout(()=>{v.textContent="📋 Copy to Clipboard"},1800)})};const w=document.createElement("button");w.style.cssText=`\n            padding: 7px 16px; border-radius: 8px; border: none; cursor: pointer; font-size: 13px; font-weight: 600;\n            background: ${t?"#89b4fa":"#3b82f6"}; color: ${t?"#1e1e2e":"#ffffff"};\n            transition: background 0.15s;\n        `,w.textContent="💾 Download",w.onmouseenter=()=>w.style.background=t?"#74c7ec":"#2563eb",w.onmouseleave=()=>w.style.background=t?"#89b4fa":"#3b82f6",w.onclick=()=>{const e=b(f());if(!e)return;const t=new Blob([e],{type:"application/json"}),n=document.createElement("a");n.href=URL.createObjectURL(t),n.download=`gpc-brushes-${(new Date).toISOString().slice(0,10)}.json`,document.body.appendChild(n),n.click(),setTimeout(()=>{n.remove(),URL.revokeObjectURL(n.href)},1e3)},x.appendChild(v),x.appendChild(w),s.appendChild(x),o.appendChild(s),n.appendChild(o),document.body.appendChild(n)}()});const x=document.createElement("button");x.className="brush-swap-footer-btn",x.innerHTML="📥 Import",x.addEventListener("click",e=>{e.stopPropagation(),g()});const v=document.createElement("button");v.className="brush-swap-footer-btn",v.innerHTML="↺",v.title="Reset size",v.addEventListener("click",e=>{e.stopPropagation(),u=null,localStorage.removeItem(a),s.style.width="",s.style.maxWidth="",s.style.maxHeight=""}),b.appendChild(y),b.appendChild(x),b.appendChild(v),s.appendChild(b),n.appendChild(o),n.appendChild(s),t.parentNode.insertBefore(n,t.nextSibling),document.addEventListener("click",e=>{!n.contains(e.target)&&i.dropdownOpen&&m()})}function f(){const o=e.toggleBrushEditor;"function"==typeof o&&(e.toggleBrushEditor=function(){o.call(this),setTimeout(()=>{!function(){const o=document.getElementById("brushEditorPanel");if(!o)return;if(document.getElementById("brush-swap-dimension-select"))return;const r=o.querySelector("h2");if(!r)return;const a=document.createElement("div");a.className="flex gap-2 items-center mb-3 px-1.5 dark:text-gray-300";const i=document.createElement("label");i.textContent="Grid Size:",i.className="text-xs font-semibold text-gray-700 dark:text-gray-300";const l=document.createElement("select");l.id="brush-swap-dimension-select",l.className="px-2 py-1 text-xs border rounded bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-600 text-gray-900 dark:text-gray-100 cursor-pointer";const s=[{value:1,label:"1×1"},{value:3,label:"3×3"},{value:5,label:"5×5"},{value:7,label:"7×7"},{value:9,label:"9×9"},{value:11,label:"11×11"},{value:13,label:"13×13"},{value:15,label:"15×15"},{value:17,label:"17×17"},{value:19,label:"19×19"},{value:21,label:"21×21"}],c=e.BrushSize||5;s.some(e=>e.value===c)||(s.push({value:c,label:c+"×"+c}),s.sort((e,t)=>e.value-t.value)),s.forEach(e=>{const t=document.createElement("option");t.value=e.value,t.textContent=e.label,l.appendChild(t)}),l.value=e.BrushSize||5,l.addEventListener("change",o=>{const r=parseInt(o.target.value);t("BrushSize",r),e.BrushSize=r,n("generateBrushGrid(currentBrushPattern)")}),a.appendChild(i),a.appendChild(l),r.parentNode.insertBefore(a,r.nextSibling)}(),d()},50),setTimeout(()=>{const e=document.getElementById("brushEditorMenu");e&&e.classList.contains("hidden")&&(e.style.pointerEvents="none",e.style.visibility="hidden")},350),setTimeout(()=>{const e=document.getElementById("brushEditorMenu");e&&!e.classList.contains("hidden")&&(e.style.pointerEvents="",e.style.visibility="")},10)})}function b(){if("function"!=typeof e.saveBrushToPreset)return console.warn("Brush Swap: saveBrushToPreset not yet available, retrying..."),!1;const t=e.saveBrushToPreset;return e.saveBrushToPreset=function(e){t.call(this,e);const n=function(){const e=document.getElementById("brushGrid");if(!e)return console.warn("Brush Swap: brushGrid not found"),null;const t=e.querySelectorAll("div[data-x][data-y]"),n=[];let o=1/0,r=-1/0,a=1/0,i=-1/0,l=-1,s=-1;if(t.forEach(e=>{if("true"===e.dataset.active){const t=parseInt(e.dataset.x),c=parseInt(e.dataset.y);n.push({gridX:t,gridY:c}),o=Math.min(o,t),r=Math.max(r,t),a=Math.min(a,c),i=Math.max(i,c),"true"!==e.dataset.isCenter&&"true"!==e.dataset.isCenter||(l=t,s=c)}}),0===n.length)return console.warn("Brush Swap: No active cells in brush"),null;const c=Math.max(r-o+1,i-a+1);-1!==l&&-1!==s||(l=Math.floor(c/2),s=Math.floor(c/2));return{pattern:n.map(e=>({x:e.gridX-l,y:-1*(e.gridY-s)})),brushSize:c}}();if(n){(function(e,t){i.brushes.length>=100&&i.brushes.shift();const n={id:i.nextId++,name:`Brush ${i.nextId}`,pattern:e,brushSize:t};i.brushes.push(n),l()})(n.pattern,n.brushSize);o,u()}else console.warn("Brush Swap: Failed to capture brush from DOM")},!0}function y(){!function(){const e=localStorage.getItem(r);if(e)try{i.brushes=JSON.parse(e),i.nextId=Math.max(...i.brushes.map(e=>e.id),0)+1}catch(e){console.error("Failed to parse brush presets:",e),i.brushes=[],i.nextId=1}}(),function(){const e=document.createElement("style");e.textContent="\n            /* Paintbrush icon button */\n            #brush-swap-toggle {\n                opacity: 0.85;\n                transition: all 0.2s ease;\n            }\n\n            #brush-swap-toggle:hover {\n                opacity: 1;\n            }\n\n            #brush-swap-toggle:active {\n                opacity: 0.7;\n            }\n\n            /* Dropdown container */\n            #brush-swap-dropdown {\n                position: absolute;\n                bottom: 100%;\n                right: 0;\n                border-radius: 4px;\n                margin-bottom: 8px;\n                max-width: 300px;\n                max-height: 0;\n                overflow: hidden;\n                opacity: 0;\n                pointer-events: none;\n                transition: max-height 0.3s ease, opacity 0.3s ease;\n                z-index: 1000;\n            }\n\n            #brush-swap-dropdown.open {\n                max-height: 600px;\n                opacity: 1;\n                overflow-y: auto;\n                pointer-events: auto;\n            }\n\n            /* Disable all transitions during resize drag to prevent animation lag */\n            #brush-swap-dropdown.brush-swap-resizing {\n                transition: none !important;\n                overflow-y: auto !important;\n            }\n\n            /* Items container */\n            .brush-swap-items {\n                display: flex;\n                flex-direction: column;\n                gap: 4px;\n                padding: 8px;\n                min-width: 250px;\n            }\n\n            /* Preview grid */\n            .brush-swap-preview-grid {\n                display: grid;\n                gap: 1px;\n                flex-shrink: 0;\n                background: var(--color-gray-100, white);\n                padding: 2px;\n                border: 1px solid var(--color-gray-400, #ddd);\n                border-radius: 2px;\n            }\n\n            .brush-swap-quick-tip {\n                position: fixed;\n                pointer-events: none;\n                z-index: 100001;\n                background: rgba(0,0,0,0.8);\n                color: #fff;\n                padding: 3px 7px;\n                border-radius: 4px;\n                font-size: 10px;\n                font-weight: 500;\n                white-space: nowrap;\n                font-family: system-ui, sans-serif;\n            }\n\n            .brush-swap-preview-wrap {\n                width: 36px;\n                height: 36px;\n                overflow: hidden;\n                flex-shrink: 0;\n                border-radius: 3px;\n                cursor: pointer;\n                position: relative;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n            }\n\n            .brush-swap-preview-wrap.expanded {\n                width: auto;\n                height: auto;\n                max-width: 120px;\n                max-height: 120px;\n            }\n\n            .brush-swap-preview-wrap.expanded .brush-swap-preview-grid {\n                max-width: 100%;\n                max-height: 100%;\n            }\n\n            .brush-swap-preview-cell {\n                background: var(--color-gray-100, white);\n                border: 0.5px solid var(--color-gray-300, #eee);\n            }\n\n            .brush-swap-preview-cell.active {\n                background: var(--color-gray-800, #333);\n            }\n\n            .brush-swap-preview-cell.center {\n                background: #ff6b6b;\n            }\n\n            /* Scrollbar styling for dropdown */\n            #brush-swap-dropdown::-webkit-scrollbar {\n                width: 6px;\n            }\n\n            #brush-swap-dropdown::-webkit-scrollbar-track {\n                background: transparent;\n            }\n\n            #brush-swap-dropdown::-webkit-scrollbar-thumb {\n                background: #888;\n                border-radius: 3px;\n            }\n\n            #brush-swap-dropdown::-webkit-scrollbar-thumb:hover {\n                background: #555;\n            }\n\n            /* Dark mode scrollbar */\n            @media (prefers-color-scheme: dark) {\n                #brush-swap-dropdown::-webkit-scrollbar-thumb {\n                    background: #555;\n                }\n\n                #brush-swap-dropdown::-webkit-scrollbar-thumb:hover {\n                    background: #777;\n                }\n            }\n\n            /* Scroll-swap toast */\n            #brush-swap-toast {\n                position: fixed;\n                pointer-events: none;\n                z-index: 10000;\n                background: rgba(0, 0, 0, 0.82);\n                color: #fff;\n                padding: 6px 10px;\n                border-radius: 6px;\n                font-size: 11px;\n                font-weight: 600;\n                font-family: system-ui, sans-serif;\n                white-space: nowrap;\n                opacity: 0;\n                transition: opacity 0.15s ease;\n                transform: translate(12px, -50%);\n                display: flex;\n                align-items: center;\n                gap: 8px;\n            }\n            #brush-swap-toast.visible {\n                opacity: 1;\n            }\n            #brush-swap-toast .toast-preview {\n                flex-shrink: 0;\n            }\n            #brush-swap-toast .toast-preview .brush-swap-preview-cell {\n                background: rgba(255,255,255,0.2);\n                border-color: rgba(255,255,255,0.1);\n            }\n            #brush-swap-toast .toast-preview .brush-swap-preview-cell.active {\n                background: #fff;\n            }\n            #brush-swap-toast .toast-preview .brush-swap-preview-cell.center {\n                background: #ff6b6b;\n            }\n            #brush-swap-toast .toast-preview .brush-swap-preview-grid {\n                background: transparent;\n                border-color: rgba(255,255,255,0.15);\n            }\n\n            /* Active brush highlight */\n            .brush-swap-item-active {\n                outline: 2px solid var(--color-blue-500, #3b82f6) !important;\n                outline-offset: -1px;\n                background: var(--color-blue-50, rgba(59,130,246,0.08)) !important;\n            }\n\n            /* Drag handle */\n            .brush-swap-drag-handle {\n                display: flex;\n                flex-direction: column;\n                justify-content: center;\n                align-items: center;\n                width: 14px;\n                cursor: grab;\n                flex-shrink: 0;\n                opacity: 0.35;\n                transition: opacity 0.15s;\n                user-select: none;\n                padding: 2px 0;\n            }\n            .brush-swap-drag-handle:hover {\n                opacity: 0.8;\n            }\n            .brush-swap-drag-handle:active {\n                cursor: grabbing;\n                opacity: 1;\n            }\n            .brush-swap-drag-handle-dot {\n                width: 3px;\n                height: 3px;\n                border-radius: 50%;\n                background: var(--color-gray-500, #9ca3af);\n                margin: 1px 0;\n            }\n\n            /* Dragging visual */\n            .brush-swap-item-dragging {\n                opacity: 0.4;\n            }\n            .brush-swap-drop-indicator {\n                height: 2px;\n                background: var(--color-blue-500, #3b82f6);\n                border-radius: 1px;\n                margin: -2px 0;\n                pointer-events: none;\n            }\n\n            /* Resize handle — single corner, right side */\n            .brush-swap-resize-handle {\n                position: absolute;\n                right: 0;\n                width: 14px;\n                height: 14px;\n                z-index: 1001;\n                opacity: 0;\n                transition: opacity 0.15s;\n            }\n            #brush-swap-dropdown:hover .brush-swap-resize-handle {\n                opacity: 0.5;\n            }\n            .brush-swap-resize-handle:hover {\n                opacity: 1 !important;\n            }\n            .brush-swap-resize-handle::after {\n                content: '';\n                position: absolute;\n                width: 7px;\n                height: 7px;\n                border-style: solid;\n                border-color: var(--color-gray-500, #6b7280);\n            }\n            /* top-right: open upward */\n            .brush-swap-resize-tr {\n                top: 0;\n                cursor: ne-resize;\n            }\n            .brush-swap-resize-tr::after {\n                top: 2px; right: 2px;\n                border-width: 2px 2px 0 0;\n            }\n            /* bottom-right: open downward (paint menu at top) */\n            .brush-swap-resize-br {\n                bottom: 0;\n                cursor: se-resize;\n            }\n            .brush-swap-resize-br::after {\n                bottom: 2px; right: 2px;\n                border-width: 0 2px 2px 0;\n            }\n\n            /* Export/Import footer */\n            .brush-swap-footer {\n                display: flex;\n                justify-content: flex-end;\n                gap: 4px;\n                padding: 6px 8px;\n                border-top: 1px solid var(--color-gray-200, #e5e7eb);\n            }\n            :is(.dark) .brush-swap-footer,\n            .dark .brush-swap-footer {\n                border-top-color: #374151;\n            }\n            .brush-swap-footer-btn {\n                background: none;\n                border: 1px solid var(--color-gray-300, #d1d5db);\n                border-radius: 5px;\n                cursor: pointer;\n                font-size: 11px;\n                line-height: 1;\n                padding: 3px 8px;\n                color: var(--color-gray-500, #6b7280);\n                transition: background 0.12s, color 0.12s;\n                white-space: nowrap;\n                display: inline-flex;\n                align-items: center;\n                gap: 4px;\n            }\n            .brush-swap-footer-btn:hover {\n                background: var(--color-gray-100, #f3f4f6);\n                color: var(--color-gray-800, #1f2937);\n                border-color: var(--color-gray-400, #9ca3af);\n            }\n            :is(.dark) .brush-swap-footer-btn,\n            .dark .brush-swap-footer-btn {\n                border-color: #4b5563;\n                color: #9ca3af;\n            }\n            :is(.dark) .brush-swap-footer-btn:hover,\n            .dark .brush-swap-footer-btn:hover {\n                background: #374151;\n                color: #e5e7eb;\n                border-color: #6b7280;\n            }\n        ",document.head.appendChild(e)}();let o=0;const a=setInterval(()=>{o++;const r=document.getElementById("bottomControls"),i="function"==typeof e.saveBrushToPreset;if(r&&i&&o<=120){clearInterval(a);const l=9;function s(){t("BrushSize",l),e.BrushSize=l,n('if(typeof generateBrushGrid==="function")generateBrushGrid(currentBrushPattern)');const o=document.getElementById("brush-swap-dimension-select");o&&(o.value=l)}s();let c=0;const d=setInterval(()=>{c++;(localStorage.getItem("userConfig")||c>20)&&(clearInterval(d),s())},250);h(r),b(),f()}else o>120&&(clearInterval(a),console.warn("Brush Swap: Could not initialize - bottomControls or saveBrushToPreset not found",{hasBottomControls:!!r,hasSaveBrushToPreset:i}))},500)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",y):y()}(),_featureStatus.paintBrushSwap="ok",console.log("[GeoPixelcons++] ✅ Paint Brush Swap loaded")}catch(_){_featureStatus.paintBrushSwap="error",dbgPush(`Paint Brush Swap init failed: ${_&&_.message?_.message:String(_)}`,{error:_,uiComponent:"Paint Brush Swap"}),console.error("[GeoPixelcons++] ❌ Paint Brush Swap failed:",_)}if(_settings.regionsHighscore)try{!function(){const e=1e3;let t=!1,n=!1,o=null,r=null,a=null,i=null,l=null,s=null;function c(){if(s)return s;try{const e=(0,eval)("map");if(e&&void 0!==e.scrollZoom)return s=e}catch{}if("undefined"!=typeof unsafeWindow)try{const e=unsafeWindow.eval("map");if(e&&void 0!==e.scrollZoom)return s=e}catch{}return null}function d(){t=!t,t?(l.style.backgroundColor="#3b82f6",l.style.color="white",l.style.boxShadow="0 0 10px rgba(59, 130, 246, 0.5)",document.body.style.cursor="crosshair",function(){const e=c();if(!e)return;e.dragPan.disable(),e.scrollZoom.disable(),e.boxZoom.disable(),e.doubleClickZoom.disable(),e.touchZoomRotate.disable()}(),G("Click and drag to select a region")):g()}function p(){const e=c();e&&(e.dragPan.enable(),e.scrollZoom.enable(),e.boxZoom.enable(),e.touchZoomRotate.enable())}function g(){t=!1,n=!1,o=null,r=null,l&&(l.style.backgroundColor="white",l.style.color="black",l.style.boxShadow=""),document.body.style.cursor="",p(),u()}function u(){i&&a&&i.clearRect(0,0,window.innerWidth,window.innerHeight)}function m(e){t&&0===e.button&&(e.target.closest("#controls-left")||e.target.closest("#controls-right")||e.target.closest(".modal-container")||(n=!0,o=y(e.clientX,e.clientY),r=o,e.preventDefault(),e.stopPropagation()))}function h(e){n&&o&&(r=y(e.clientX,e.clientY),w())}async function f(e){if(!n||!o||!r)return;n=!1;const a=v(),i=a.maxX-a.minX+1,s=a.maxY-a.minY+1;if(i<2||s<2)return G("Selection too small. Please select a larger area."),u(),void g();t=!1,l&&(l.style.backgroundColor="white",l.style.color="black",l.style.boxShadow=""),document.body.style.cursor="",p();const c=T(a,null,!0),d=c.querySelector(".rhs-progress-text"),m=e=>{d&&(d.textContent=e)};try{const e=await k(a,m);m("Fetching usernames...");P(c,a,await C(e))}catch(e){console.error("[Regions Highscore] Error computing leaderboard:",e),G("Error computing leaderboard: "+e.message),c.close()}u(),o=null,r=null}function b(e){"Escape"===e.key&&(t||n)&&g()}function y(e,t){const n=s.getContainer().getBoundingClientRect(),o=[e-n.left,t-n.top],r=s.unproject(o),a=turf.toMercator([r.lng,r.lat]);return{gridX:Math.round(a[0]/25),gridY:Math.round(a[1]/25)}}function x(e,t){const n=25*e,o=25*t,r=turf.toWgs84([n,o]),a=s.project(r),i=s.getContainer().getBoundingClientRect();return{x:a.x+i.left,y:a.y+i.top}}function v(){return{minX:Math.min(o.gridX,r.gridX),maxX:Math.max(o.gridX,r.gridX),minY:Math.min(o.gridY,r.gridY),maxY:Math.max(o.gridY,r.gridY)}}function w(){if(u(),!o||!r)return;const e=v(),t=x(e.minX-.5,e.maxY+.5),n=x(e.maxX+.5,e.minY-.5),a=t.x,l=t.y,s=n.x-t.x,c=n.y-t.y;i.fillStyle="rgba(59, 130, 246, 0.3)",i.fillRect(a,l,s,c),i.strokeStyle="rgba(59, 130, 246, 0.8)",i.lineWidth=2,i.strokeRect(a,l,s,c);const d=`${e.maxX-e.minX+1} × ${e.maxY-e.minY+1}`;i.font="bold 14px sans-serif",i.fillStyle="white",i.strokeStyle="black",i.lineWidth=3;const p=a+s/2,g=l+c/2;i.textAlign="center",i.textBaseline="middle",i.strokeText(d,p,g),i.fillText(d,p,g)}async function k(t,n){const o=new Map,{minX:r,maxX:a,minY:i,maxY:l}=t,s=new Set,c=Math.floor(r/e)*e,d=Math.floor(a/e)*e,p=Math.floor(i/e)*e,g=Math.floor(l/e)*e;for(let t=c;t<=d;t+=e)for(let n=p;n<=g;n+=e)s.add(`${t},${n}`);const u=[...s];console.log(`[Regions Highscore] Need ${u.length} tiles for region ${a-r+1}×${l-i+1}`),console.log(`[Regions Highscore] Selection bounds: X ${r} to ${a}, Y ${i} to ${l}`),console.log("[Regions Highscore] Tiles needed:",u);let m=0,h=0;for(const t of u){const[s,c]=t.split(",").map(Number);m++,n&&n(`Processing tile ${m}/${u.length}...`),await new Promise(e=>setTimeout(e,0));let d=null;const p=tileImageCache.get(t);if(console.log(`[Regions Highscore] Cache lookup for ${t}:`,p?"FOUND":"NOT FOUND"),p&&(console.log("[Regions Highscore] Cache entry keys:",Object.keys(p)),console.log("[Regions Highscore] Cache entry:",p)),p&&p.userBitmap)d=p.userBitmap,console.log(`[Regions Highscore] Using cached userBitmap, size: ${d.width}x${d.height}`);else{console.log(`[Regions Highscore] Fetching tile ${t} from API...`),n&&n(`Fetching tile ${t}...`);try{const e=await E(s,c);console.log(`[Regions Highscore] API response for ${t}:`,e),e&&e.userBitmap&&(d=e.userBitmap,console.log(`[Regions Highscore] Fetched userBitmap, size: ${d.width}x${d.height}`))}catch(e){console.warn(`[Regions Highscore] Failed to fetch tile ${t}:`,e);continue}}if(!d)continue;const g=new OffscreenCanvas(d.width,d.height).getContext("2d",{willReadFrequently:!0});g.drawImage(d,0,0);const f=g.getImageData(0,0,d.width,d.height).data;let b=0;for(let e=0;e<f.length;e+=4)if((0!==f[e]||0!==f[e+1]||0!==f[e+2])&&(b++,b<=3)){const t=e/4,n=t%d.width,o=Math.floor(t/d.width),r=s+n,a=c+(999-o),i=c+o;console.log(`[Regions Highscore] Non-zero pixel at bitmap (${n}, ${o}): RGB(${f[e]},${f[e+1]},${f[e+2]})`),console.log(`  - Grid coords if Y inverted: (${r}, ${a})`),console.log(`  - Grid coords if Y direct: (${r}, ${i})`)}console.log(`[Regions Highscore] Total non-zero pixels in FULL bitmap: ${b}`);const y=-351700,x=218914;if(y>=s&&y<s+e&&x>=c&&x<c+e){const e=y-s,t=999-(x-c),n=x-c;console.log("[Regions Highscore] Test pixel (-351700, 218914):"),console.log(`  - If Y inverted: local (${e}, ${t})`),console.log(`  - If Y direct: local (${e}, ${n})`);const o=4*(t*d.width+e),r=4*(n*d.width+e);console.log(`  - Inverted value: RGB(${f[o]},${f[o+1]},${f[o+2]},${f[o+3]})`),console.log(`  - Direct value: RGB(${f[r]},${f[r+1]},${f[r+2]},${f[r+3]})`)}const v=Math.max(r,s),w=Math.min(a,s+e-1),k=Math.max(i,c),C=Math.min(l,c+e-1),S=w-v+1,T=C-k+1;if(S<=0||T<=0)continue;const P=v-s,L=k-c;console.log(`[Regions Highscore] Tile ${t}: reading region ${S}x${T} at local (${P}, ${L})`),console.log(`[Regions Highscore] Tile bounds: X ${v}-${w}, Y ${k}-${C}`);const M=new OffscreenCanvas(S,T).getContext("2d",{willReadFrequently:!0});M.drawImage(d,P,L,S,T,0,0,S,T);const I=M.getImageData(0,0,S,T),_=I.data;console.log(`[Regions Highscore] ImageData size: ${I.width}x${I.height}, data length: ${_.length}`);const G=[];for(let e=0;e<Math.min(10,S*T);e++){const t=4*e;G.push(`(${_[t]},${_[t+1]},${_[t+2]},${_[t+3]})`)}console.log("[Regions Highscore] First 10 pixels (RGBA):",G.join(" "));const R=5e4,N=S*T;let A=0;for(let e=0;e<N;e++){const t=4*e,n=_[t],r=_[t+1],a=_[t+2],i=_[t+3],l=n<<16|r<<8|a;l>0&&(o.set(l,(o.get(l)||0)+1),h++,A<3&&console.log(`[Regions Highscore] Found user pixel: userId=${l} (R=${n},G=${r},B=${a},A=${i})`),A++),e>0&&e%R===0&&await new Promise(e=>setTimeout(e,0))}console.log(`[Regions Highscore] Found ${A} non-zero pixels in tile region`)}return console.log(`[Regions Highscore] Total pixels with users found: ${h}`),console.log(`[Regions Highscore] Unique users: ${o.size}`),o}async function E(t,n){const o=await fetch("https://geopixels.net/GetPixelsCached",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({Tiles:[{x:t,y:n,timestamp:0}]})});if(!o.ok)throw new Error(`API returned ${o.status}`);const r=await o.json(),a=`tile_${t}_${n}`,i=r.Tiles[a];if(console.log(`[Regions Highscore] API tile key: ${a}`),console.log("[Regions Highscore] Available tiles in response:",Object.keys(r.Tiles)),console.log("[Regions Highscore] Tile info:",i),!i)return null;if("full"===i.Type&&i.UserWebP){return{userBitmap:await async function(e){return new Promise((t,n)=>{const o=new Image;o.onload=()=>{createImageBitmap(o).then(t).catch(n)},o.onerror=n,o.src=`data:image/webp;base64,${e}`})}(i.UserWebP)}}if(i.Pixels&&i.Pixels.length>0){const o=await async function(t,n,o){const r=new OffscreenCanvas(e,e),a=r.getContext("2d");for(const e of t){const[t,r,i,l]=e,s=t-n,c=r-o,d=l>>16&255,p=l>>8&255,g=255&l;a.fillStyle=`rgb(${d},${p},${g})`,a.fillRect(s,c,1,1)}return createImageBitmap(r)}(i.Pixels,t,n);return{userBitmap:o}}return null}async function C(e){const t=[...e.entries()].sort((e,t)=>t[1]-e[1]),n=t.map(([e])=>e),o=await async function(e){const t=new Map;for(let n=0;n<e.length;n+=10){const o=e.slice(n,n+10).map(async e=>{try{const t=await fetch("https://geopixels.net/GetUserProfile",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({targetId:e})});if(t.ok){return{userId:e,name:(await t.json()).name||`User #${e}`}}}catch(t){console.warn(`[Regions Highscore] Failed to fetch user ${e}:`,t)}return{userId:e,name:`User #${e}`}}),r=await Promise.all(o);for(const{userId:e,name:n}of r)t.set(e,n)}return t}(n);return t.map(([e,t],n)=>({rank:n+1,userId:e,username:o.get(e)||`User #${e}`,pixelCount:t}))}function S(){const e="dark"===getComputedStyle(document.documentElement).colorScheme;return{modalBg:e?"#1e2939":"white",overlayBg:e?"rgba(0, 0, 0, 0.7)":"rgba(0, 0, 0, 0.5)",text:e?"#f3f4f6":"#333",textSecondary:e?"#d1d5db":"#666",textMuted:e?"#99a1af":"#888",textSubtle:e?"#6a7282":"#999",border:e?"#364153":"#eee",headerBg:e?"#101828":"#f0f0f0",summaryBg:e?"#101828":"#f8f9fa",summaryText:e?"#d1d5db":"#555",closeBtnColor:e?"#99a1af":"#666",closeBtnHoverBg:e?"#364153":"#f0f0f0",closeBtnHoverColor:e?"#f3f4f6":"#333",notificationBg:e?"#1e2939":"#333",notificationText:e?"#f3f4f6":"white"}}function T(e,t=null,n=!1){const o=document.querySelector(".rhs-modal-container");o&&o.remove();const r=e.maxX-e.minX+1,a=e.maxY-e.minY+1,i=r*a,l=S(),s=document.createElement("div");s.className="rhs-modal-container",s.style.cssText=`\n            position: fixed;\n            inset: 0;\n            z-index: 10000;\n            background: ${l.overlayBg};\n            display: flex;\n            align-items: center;\n            justify-content: center;\n        `;const c=document.createElement("div");c.className="rhs-modal",c.style.cssText=`\n            position: relative;\n            background: ${l.modalBg};\n            color: ${l.text};\n            border-radius: 12px;\n            box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);\n            padding: 24px;\n            min-width: 400px;\n            max-width: 90vw;\n            max-height: 80vh;\n            display: flex;\n            flex-direction: column;\n        `;const d=document.createElement("button");d.innerHTML="✕",d.style.cssText=`\n            position: absolute;\n            top: 12px;\n            right: 12px;\n            background: none;\n            border: none;\n            font-size: 20px;\n            cursor: pointer;\n            color: ${l.closeBtnColor};\n            width: 32px;\n            height: 32px;\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            transition: all 0.2s;\n        `,d.onmouseover=()=>{d.style.background=l.closeBtnHoverBg,d.style.color=l.closeBtnHoverColor},d.onmouseout=()=>{d.style.background="none",d.style.color=l.closeBtnColor};const p=document.createElement("div");p.style.cssText="margin-bottom: 16px; padding-right: 32px;",p.innerHTML=`\n            <h2 style="margin: 0 0 8px 0; font-size: 24px; font-weight: bold; color: ${l.text};">📊 Region Leaderboard</h2>\n            <p style="margin: 0; color: ${l.textSecondary}; font-size: 14px;">Selected area: ${r} × ${a} pixels (${i.toLocaleString()} total)</p>\n            <p style="margin: 4px 0 0 0; color: ${l.textMuted}; font-size: 12px; font-family: monospace;">X: ${e.minX} to ${e.maxX} | Y: ${e.minY} to ${e.maxY}</p>\n        `;const g=document.createElement("button");g.textContent="Adjust…",g.style.cssText=`\n            margin-top: 8px; padding: 5px 12px; border-radius: 6px; border: 1px solid ${l.border};\n            background: ${l.headerBg}; color: ${l.textSecondary}; font-size: 12px; cursor: pointer;\n            transition: background 0.15s; white-space: nowrap;\n        `,g.onmouseover=()=>{g.style.background=l.closeBtnHoverBg},g.onmouseout=()=>{g.style.background=l.headerBg},g.onclick=()=>{!function(e,t){const n=document.querySelector(".rhs-adjust-overlay");n&&n.remove();const o=S(),r=document.createElement("div");r.className="rhs-adjust-overlay",r.style.cssText=`\n            position: fixed; inset: 0; z-index: 10001;\n            background: ${o.overlayBg};\n            display: flex; align-items: center; justify-content: center;\n            font-family: system-ui, sans-serif;\n        `;const a=`width: 100%; margin-top: 2px; padding: 6px 8px; border-radius: 6px; border: 1px solid ${o.border}; background: ${o.headerBg}; color: ${o.text}; font-size: 13px; font-family: monospace;`,i=document.createElement("div");i.style.cssText=`\n            background: ${o.modalBg}; color: ${o.text}; border-radius: 12px;\n            box-shadow: 0 16px 48px rgba(0,0,0,0.5);\n            padding: 24px; min-width: 320px; display: flex; flex-direction: column; gap: 14px;\n        `,i.innerHTML=`\n            <h3 style="margin: 0; font-size: 16px; font-weight: 700;">Adjust Region Bounds</h3>\n            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">\n                <label style="font-size: 12px; color: ${o.textSecondary};">X1 (min)\n                    <input id="rhs-adj-x1" type="number" value="${e.minX}" style="${a}" />\n                </label>\n                <label style="font-size: 12px; color: ${o.textSecondary};">X2 (max)\n                    <input id="rhs-adj-x2" type="number" value="${e.maxX}" style="${a}" />\n                </label>\n                <label style="font-size: 12px; color: ${o.textSecondary};">Y1 (min)\n                    <input id="rhs-adj-y1" type="number" value="${e.minY}" style="${a}" />\n                </label>\n                <label style="font-size: 12px; color: ${o.textSecondary};">Y2 (max)\n                    <input id="rhs-adj-y2" type="number" value="${e.maxY}" style="${a}" />\n                </label>\n            </div>\n            <div id="rhs-adj-error" style="font-size: 12px; color: #ef4444; display: none;"></div>\n            <div style="display: flex; gap: 10px; justify-content: flex-end;">\n                <button id="rhs-adj-cancel" style="padding: 8px 16px; border-radius: 8px; border: 1px solid ${o.border}; background: ${o.headerBg}; color: ${o.textSecondary}; cursor: pointer; font-size: 13px;">Cancel</button>\n                <button id="rhs-adj-confirm" style="padding: 8px 16px; border-radius: 8px; border: none; background: #3b82f6; color: white; cursor: pointer; font-size: 13px; font-weight: 600;">Apply</button>\n            </div>\n        `,r.appendChild(i),document.body.appendChild(r);const l=()=>r.remove();r.addEventListener("click",e=>{e.target===r&&l()}),i.querySelector("#rhs-adj-cancel").onclick=l,i.querySelector("#rhs-adj-confirm").onclick=()=>{const e=parseInt(i.querySelector("#rhs-adj-x1").value),n=parseInt(i.querySelector("#rhs-adj-x2").value),o=parseInt(i.querySelector("#rhs-adj-y1").value),r=parseInt(i.querySelector("#rhs-adj-y2").value),a=i.querySelector("#rhs-adj-error");if([e,n,o,r].some(isNaN))return a.textContent="All fields must be valid numbers.",void(a.style.display="block");const s={minX:Math.min(e,n),maxX:Math.max(e,n),minY:Math.min(o,r),maxY:Math.max(o,r)};if(s.maxX-s.minX+1<2||s.maxY-s.minY+1<2)return a.textContent="Region must be at least 2×2.",void(a.style.display="block");l(),t(s)};const s=e=>{"Escape"===e.key&&(l(),document.removeEventListener("keydown",s))};document.addEventListener("keydown",s)}(e,e=>{!async function(e){const t=document.querySelector(".rhs-modal-container");t&&t.remove();const n=T(e,null,!0),o=n.querySelector(".rhs-progress-text"),r=e=>{o&&(o.textContent=e)};try{const t=await k(e,r);r("Fetching usernames..."),P(n,e,await C(t))}catch(e){console.error("[Regions Highscore] Error:",e),G("Error computing leaderboard: "+e.message),n.close()}}(e)})},p.appendChild(g);const u=document.createElement("div");u.className="rhs-modal-content",u.style.cssText="\n            flex: 1;\n            overflow-y: auto;\n            min-height: 200px;\n        ",n?u.innerHTML=`\n                <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 200px; color: ${l.textSecondary};">\n                    <div style="font-size: 32px; margin-bottom: 16px;">⏳</div>\n                    <div class="rhs-progress-text">Calculating leaderboard...</div>\n                    <div style="font-size: 12px; margin-top: 8px; color: ${l.textSubtle};">This may take a moment for large regions</div>\n                </div>\n            `:t&&u.appendChild(L(t)),c.appendChild(d),c.appendChild(p),c.appendChild(u),s.appendChild(c),document.body.appendChild(s);const m=()=>s.remove();d.onclick=m,s.onclick=e=>{e.target===s&&m()};const h=e=>{"Escape"===e.key&&(m(),document.removeEventListener("keydown",h))};return document.addEventListener("keydown",h),c.close=m,c}function P(e,t,n){const o=e.querySelector(".rhs-modal-content");if(o)if(o.innerHTML="",0===n.length){const e=S();o.innerHTML=`\n                <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 150px; color: ${e.textSecondary};">\n                    <div style="font-size: 32px; margin-bottom: 16px;">🤷</div>\n                    <div>No pixels found in this region</div>\n                </div>\n            `}else o.appendChild(L(n))}function L(e){const t=S(),n=document.createElement("div"),o=e.reduce((e,t)=>e+t.pixelCount,0),r=document.createElement("div");r.style.cssText=`margin-bottom: 16px; padding: 12px; background: ${t.summaryBg}; border-radius: 8px; font-size: 14px; color: ${t.summaryText};`,r.innerHTML=`<strong>${e.length}</strong> users placed <strong>${o.toLocaleString()}</strong> pixels in this region`,n.appendChild(r);const a=document.createElement("table");a.style.cssText=`width: 100%; border-collapse: collapse; font-size: 14px; color: ${t.text};`;const i=document.createElement("thead");i.innerHTML=`\n            <tr style="background: ${t.headerBg}; text-align: left;">\n                <th style="padding: 10px 12px; font-weight: 600; width: 60px;">Rank</th>\n                <th style="padding: 10px 12px; font-weight: 600;">Username</th>\n                <th style="padding: 10px 12px; font-weight: 600; text-align: right; width: 100px;">Pixels</th>\n                <th style="padding: 10px 12px; font-weight: 600; text-align: right; width: 80px;">%</th>\n            </tr>\n        `,a.appendChild(i);const l=document.createElement("tbody");for(const n of e){const e=document.createElement("tr");e.style.cssText=`\n                border-bottom: 1px solid ${t.border};\n                ${n.rank<=3?"background: "+I(n.rank)+";":""}\n            `;const r=(n.pixelCount/o*100).toFixed(1),a=M(n.rank);e.innerHTML=`\n                <td style="padding: 10px 12px; font-weight: ${n.rank<=3?"bold":"normal"};">${a} ${n.rank}</td>\n                <td style="padding: 10px 12px;">${_(n.username)}</td>\n                <td style="padding: 10px 12px; text-align: right; font-family: monospace;">${n.pixelCount.toLocaleString()}</td>\n                <td style="padding: 10px 12px; text-align: right; color: ${t.textSecondary};">${r}%</td>\n            `,l.appendChild(e)}return a.appendChild(l),n.appendChild(a),n}function M(e){switch(e){case 1:return"🥇";case 2:return"🥈";case 3:return"🥉";default:return""}}function I(e){switch(e){case 1:return"rgba(255, 215, 0, 0.15)";case 2:return"rgba(192, 192, 192, 0.15)";case 3:return"rgba(205, 127, 50, 0.15)";default:return"transparent"}}function _(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function G(e){if("function"==typeof showAnnouncement)return void showAnnouncement(e);const t=S(),n=document.createElement("div");n.style.cssText=`\n            position: fixed;\n            top: 20px;\n            left: 50%;\n            transform: translateX(-50%);\n            background: ${t.notificationBg};\n            color: ${t.notificationText};\n            padding: 12px 24px;\n            border-radius: 8px;\n            z-index: 10001;\n            font-size: 14px;\n            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n        `,n.textContent=e,document.body.appendChild(n),setTimeout(()=>{n.style.transition="opacity 0.3s",n.style.opacity="0",setTimeout(()=>n.remove(),300)},3e3)}!async function(){await new Promise(e=>{const t=Date.now();let n=!0,o=!1;const r=()=>{n&&(n=!1,dbgPush("Regions Highscore: waiting for map/turf/tileImageCache/#controls-left to become available -- polling every 500ms.",{uiComponent:"Regions Highscore"}));const a=!!c(),i="undefined"!=typeof turf,l="undefined"!=typeof tileImageCache,s=!!document.getElementById("controls-left");if(a&&i&&l&&s)dbgPush("Regions Highscore: all init conditions met after "+(Date.now()-t)+"ms -- proceeding.",{uiComponent:"Regions Highscore"}),e();else{if(!o&&Date.now()-t>=15e3){o=!0;const e=[];a||e.push("map"),i||e.push("turf"),l||e.push("tileImageCache"),s||e.push("#controls-left"),dbgPush("Regions Highscore: still waiting after 15s -- still unmet: "+e.join(", ")+". This feature has no fallback if it never inits, so polling continues.",{uiComponent:"Regions Highscore"}),console.error("[GeoPixelcons++] Regions Highscore: waitForGeoPixels still unmet after 15s -- missing: "+e.join(", "))}setTimeout(r,500)}};r()}),console.log("[Regions Highscore] Initializing..."),function(){a=document.createElement("canvas"),a.id="highscore-selection-canvas",a.style.cssText="\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100vw;\n            height: 100vh;\n            pointer-events: none;\n            z-index: 1000;\n        ",document.body.appendChild(a),i=a.getContext("2d");const e=()=>{const e=window.devicePixelRatio||1;a.width=window.innerWidth*e,a.height=window.innerHeight*e,i.setTransform(e,0,0,e,0,0)};e(),window.addEventListener("resize",e),["move","rotate","zoom"].forEach(e=>{s.on(e,()=>{n&&w()})})}(),l=document.createElement("button"),l.id="gpc-highscore-trigger",l.style.display="none",l.addEventListener("click",d),document.body.appendChild(l),document.addEventListener("mousedown",m),document.addEventListener("mousemove",h),document.addEventListener("mouseup",f),document.addEventListener("keydown",b),console.log("[Regions Highscore] Ready!")}(),_regionsHighscore={processWithBounds:async function(e){const t=e.maxX-e.minX+1,n=e.maxY-e.minY+1;if(t<2||n<2)return void G("Selection too small. Please select a larger area.");const o=T(e,null,!0),r=o.querySelector(".rhs-progress-text"),a=e=>{r&&(r.textContent=e)};try{const t=await k(e,a);a("Fetching usernames...");P(o,0,await C(t))}catch(e){console.error("[Regions Highscore] Error computing leaderboard:",e),G("Error computing leaderboard: "+e.message);try{o.close()}catch{}}},toggleSelectionMode:d}}(),_featureStatus.regionsHighscore="ok",console.log("[GeoPixelcons++] ✅ Regions Highscore loaded")}catch(G){_featureStatus.regionsHighscore="error",dbgPush(`Regions Highscore init failed: ${G&&G.message?G.message:String(G)}`,{error:G,uiComponent:"Regions Highscore"}),console.error("[GeoPixelcons++] ❌ Regions Highscore failed:",G)}if(_settings.regionScreenshot)try{!function(){const e=1e3,t=225e6,n="#ffffff",o="gpc-region-screenshot-background";let r=!1,a=!1,i=null,l=null,s=null,c=null,d=null,p=null;function g(){try{const e=JSON.parse(localStorage.getItem(o)||"null"),t=e&&"solid"===e.mode?"solid":"transparent";return{mode:t,color:e&&/^#[0-9A-Fa-f]{6}$/.test(e.color||"")?e.color.toLowerCase():n}}catch(e){return{mode:"transparent",color:n}}}function u(e,t){try{localStorage.setItem(o,JSON.stringify({mode:"solid"===e?"solid":"transparent",color:/^#[0-9A-Fa-f]{6}$/.test(t||"")?t.toLowerCase():n}))}catch(e){}}function m(e,t,o){if("solid"!==t)return e;const r=document.createElement("canvas");r.width=e.width,r.height=e.height;const a=r.getContext("2d");return a.fillStyle=/^#[0-9A-Fa-f]{6}$/.test(o||"")?o:n,a.fillRect(0,0,r.width,r.height),a.drawImage(e,0,0),r}function h(){if(p)return p;try{const e=(0,eval)("map");if(e&&void 0!==e.scrollZoom)return p=e}catch{}if("undefined"!=typeof unsafeWindow)try{const e=unsafeWindow.eval("map");if(e&&void 0!==e.scrollZoom)return p=e}catch{}return null}function f(){r=!r,r?(d.style.backgroundColor="#10b981",d.style.color="white",d.style.boxShadow="0 0 10px rgba(16, 185, 129, 0.6)",document.body.style.cursor="crosshair",function(){const e=h();if(!e)return;e.dragPan.disable(),e.scrollZoom.disable(),e.boxZoom.disable(),e.doubleClickZoom.disable(),e.touchZoomRotate.disable()}(),R("Click and drag to select a region to screenshot")):y()}function b(){const e=h();e&&(e.dragPan.enable(),e.scrollZoom.enable(),e.boxZoom.enable(),e.touchZoomRotate.enable())}function y(){r=!1,a=!1,i=null,l=null,d&&(d.style.backgroundColor="white",d.style.color="black",d.style.boxShadow=""),document.body.style.cursor="",b(),x()}function x(){c&&s&&c.clearRect(0,0,window.innerWidth,window.innerHeight)}function v(e){r&&0===e.button&&(e.target.closest("#controls-left")||e.target.closest("#controls-right")||e.target.closest(".rsc-modal-container")||(a=!0,i=C(e.clientX,e.clientY),l=i,e.preventDefault(),e.stopPropagation()))}function w(e){a&&i&&(l=C(e.clientX,e.clientY),P())}async function k(e){if(!a||!i||!l)return;a=!1;const n=T(),o=n.maxX-n.minX+1,s=n.maxY-n.minY+1;if(o<2||s<2)return R("Selection too small — please drag a larger area."),x(),void y();if(o*s>t)return R(`Region too large (${o}×${s}). Maximum is ~15000×15000 px.`),x(),void y();r=!1,d&&(d.style.backgroundColor="white",d.style.color="black",d.style.boxShadow=""),document.body.style.cursor="",b();const c=I(n,null,!0),p=c.querySelector(".rsc-progress-text"),g=e=>{p&&(p.textContent=e)};try{_(c,n,await L(n,g))}catch(e){console.error("[Region Screenshot] Error:",e),R("Error capturing screenshot: "+e.message),c.closeModal()}x(),i=null,l=null}function E(e){"Escape"===e.key&&(r||a)&&y()}function C(e,t){const n=p.getContainer().getBoundingClientRect(),o=p.unproject([e-n.left,t-n.top]),r=turf.toMercator([o.lng,o.lat]);return{gridX:Math.round(r[0]/25),gridY:Math.round(r[1]/25)}}function S(e,t){const n=turf.toWgs84([25*e,25*t]),o=p.project(n),r=p.getContainer().getBoundingClientRect();return{x:o.x+r.left,y:o.y+r.top}}function T(){return{minX:Math.min(i.gridX,l.gridX),maxX:Math.max(i.gridX,l.gridX),minY:Math.min(i.gridY,l.gridY),maxY:Math.max(i.gridY,l.gridY)}}function P(){if(x(),!i||!l)return;const e=T(),t=S(e.minX-.5,e.maxY+.5),n=S(e.maxX+.5,e.minY-.5),o=t.x,r=t.y,a=n.x-t.x,s=n.y-t.y;c.fillStyle="rgba(16, 185, 129, 0.25)",c.fillRect(o,r,a,s),c.strokeStyle="rgba(16, 185, 129, 0.9)",c.lineWidth=2,c.setLineDash([6,3]),c.strokeRect(o,r,a,s),c.setLineDash([]);const d=`${e.maxX-e.minX+1} × ${e.maxY-e.minY+1}`;c.font="bold 14px sans-serif",c.textAlign="center",c.textBaseline="middle",c.lineWidth=3,c.strokeStyle="rgba(0,0,0,0.6)",c.strokeText(d,o+a/2,r+s/2),c.fillStyle="white",c.fillText(d,o+a/2,r+s/2)}async function L(t,n){const{minX:o,maxX:r,minY:a,maxY:i}=t,l=r-o+1,s=i-a+1,c=new OffscreenCanvas(l,s),d=c.getContext("2d");d.clearRect(0,0,l,s);const p=Math.floor(o/e)*e,g=Math.floor(r/e)*e,u=Math.floor(a/e)*e,m=Math.floor(i/e)*e,h=[];for(let t=p;t<=g;t+=e)for(let n=u;n<=m;n+=e)h.push([t,n]);console.log(`[Region Screenshot] ${h.length} tile(s) needed for ${l}×${s} region`);let f=0;for(const[t,l]of h){f++;const s=`${t},${l}`;n&&n(`Processing tile ${f}/${h.length}…`),await new Promise(e=>setTimeout(e,0));let c=null,p=null;const g=tileImageCache.get(s);if(g&&(c=g.colorBitmap||null,p=g.deltas||null),!c){n&&n(`Fetching tile ${s} from server…`);try{const e=await M(t,l);c=e.colorBitmap,p=e.deltas}catch(e){console.warn(`[Region Screenshot] Could not load tile ${s}:`,e);continue}}if(!c)continue;const u=Math.max(o,t),m=Math.min(r,t+e-1),b=Math.max(a,l),y=Math.min(i,l+e-1),x=m-u+1,v=y-b+1;if(x<=0||v<=0)continue;const w=u-t,k=b-l,E=u-o,C=b-a;if(d.drawImage(c,w,k,x,v,E,C,x,v),p&&p.length>0)for(const e of p){const t=e.gridX,n=e.gridY;if(t<u||t>m||n<b||n>y)continue;const r=t-o,i=n-a;"#00000000"===e.color||null===e.color?d.clearRect(r,i,1,1):e.color&&(d.fillStyle=e.color,d.fillRect(r,i,1,1))}}n&&n("Finalizing…");const b=document.createElement("canvas");b.width=l,b.height=s;const y=b.getContext("2d");return y.save(),y.translate(0,s),y.scale(1,-1),y.drawImage(c,0,0),y.restore(),b}async function M(t,n){const o=await fetch("https://geopixels.net/GetPixelsCached",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({Tiles:[{x:t,y:n,timestamp:0}]})});if(!o.ok)throw new Error(`API returned ${o.status}`);const r=await o.json(),a=`tile_${t}_${n}`,i=r.Tiles&&r.Tiles[a];if(!i)return{colorBitmap:null,deltas:null};if("full"===i.Type&&i.ColorWebP){return{colorBitmap:await async function(e){return new Promise((t,n)=>{const o=new Image;o.onload=()=>createImageBitmap(o).then(t).catch(n),o.onerror=n,o.src=`data:image/webp;base64,${e}`})}(i.ColorWebP),deltas:(i.Deltas||[]).map(e=>{const[t,n,o]=e;return-1===o?{gridX:t,gridY:n,color:null}:{gridX:t,gridY:n,color:`rgb(${o>>16&255},${o>>8&255},${255&o})`}})}}if(i.Pixels&&i.Pixels.length>0){const o=await async function(t,n,o){const r=new OffscreenCanvas(e,e),a=r.getContext("2d");for(const[e,r,i]of t){if(-1===i)continue;const t=i>>16&255,l=i>>8&255,s=255&i;a.fillStyle=`rgb(${t},${l},${s})`,a.fillRect(e-n,r-o,1,1)}return createImageBitmap(r)}(i.Pixels,t,n);return{colorBitmap:o,deltas:null}}return{colorBitmap:null,deltas:null}}function I(e,n,o=!1){const r=document.querySelector(".rsc-modal-container");r&&r.remove();const a=e.maxX-e.minX+1,i=e.maxY-e.minY+1,l=document.createElement("div");l.className="rsc-modal-container",l.style.cssText="\n            position: fixed;\n            inset: 0;\n            z-index: 10000;\n            background: rgba(0, 0, 0, 0.6);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n        ";const s=document.createElement("div");s.className="rsc-modal",s.style.cssText="\n            position: relative;\n            background: #1e1e2e;\n            color: #cdd6f4;\n            border-radius: 14px;\n            box-shadow: 0 24px 60px rgba(0,0,0,0.55);\n            padding: 24px;\n            min-width: 380px;\n            max-width: min(90vw, 700px);\n            max-height: 90vh;\n            display: flex;\n            flex-direction: column;\n            gap: 16px;\n            font-family: system-ui, sans-serif;\n        ";const c=document.createElement("div");c.style.cssText="display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;",c.innerHTML=`\n            <div>\n                <h2 style="margin: 0 0 6px 0; font-size: 20px; font-weight: 700; color: #cba6f7;">📷 Region Screenshot</h2>\n                <p style="margin: 0; font-size: 13px; color: #a6adc8;">${a} × ${i} px &nbsp;|&nbsp; X: ${e.minX} → ${e.maxX} &nbsp;|&nbsp; Y: ${e.minY} → ${e.maxY}</p>\n            </div>\n        `;const d=document.createElement("button");d.textContent="Adjust…",d.style.cssText="\n            flex-shrink: 0; padding: 5px 12px; border-radius: 6px; border: 1px solid #45475a;\n            background: #313244; color: #a6adc8; font-size: 12px; cursor: pointer;\n            transition: background 0.15s; white-space: nowrap;\n        ",d.onmouseover=()=>{d.style.background="#45475a"},d.onmouseout=()=>{d.style.background="#313244"},d.onclick=()=>{!function(e,n){const o=document.querySelector(".rsc-adjust-overlay");o&&o.remove();const r=document.createElement("div");r.className="rsc-adjust-overlay",r.style.cssText="\n            position: fixed; inset: 0; z-index: 10001;\n            background: rgba(0,0,0,0.55);\n            display: flex; align-items: center; justify-content: center;\n            font-family: system-ui, sans-serif;\n        ";const a=document.createElement("div");a.style.cssText="\n            background: #1e1e2e; color: #cdd6f4; border-radius: 12px;\n            box-shadow: 0 16px 48px rgba(0,0,0,0.5);\n            padding: 24px; min-width: 320px; display: flex; flex-direction: column; gap: 14px;\n        ",a.innerHTML=`\n            <h3 style="margin: 0; font-size: 16px; font-weight: 700; color: #cba6f7;">Adjust Region Bounds</h3>\n            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">\n                <label style="font-size: 12px; color: #a6adc8;">X1 (min)\n                    <input id="rsc-adj-x1" type="number" value="${e.minX}" style="width: 100%; margin-top: 2px; padding: 6px 8px; border-radius: 6px; border: 1px solid #45475a; background: #313244; color: #cdd6f4; font-size: 13px; font-family: monospace;" />\n                </label>\n                <label style="font-size: 12px; color: #a6adc8;">X2 (max)\n                    <input id="rsc-adj-x2" type="number" value="${e.maxX}" style="width: 100%; margin-top: 2px; padding: 6px 8px; border-radius: 6px; border: 1px solid #45475a; background: #313244; color: #cdd6f4; font-size: 13px; font-family: monospace;" />\n                </label>\n                <label style="font-size: 12px; color: #a6adc8;">Y1 (min)\n                    <input id="rsc-adj-y1" type="number" value="${e.minY}" style="width: 100%; margin-top: 2px; padding: 6px 8px; border-radius: 6px; border: 1px solid #45475a; background: #313244; color: #cdd6f4; font-size: 13px; font-family: monospace;" />\n                </label>\n                <label style="font-size: 12px; color: #a6adc8;">Y2 (max)\n                    <input id="rsc-adj-y2" type="number" value="${e.maxY}" style="width: 100%; margin-top: 2px; padding: 6px 8px; border-radius: 6px; border: 1px solid #45475a; background: #313244; color: #cdd6f4; font-size: 13px; font-family: monospace;" />\n                </label>\n            </div>\n            <div id="rsc-adj-error" style="font-size: 12px; color: #f38ba8; display: none;"></div>\n            <div style="display: flex; gap: 10px; justify-content: flex-end;">\n                <button id="rsc-adj-cancel" style="padding: 8px 16px; border-radius: 8px; border: 1px solid #45475a; background: #313244; color: #a6adc8; cursor: pointer; font-size: 13px;">Cancel</button>\n                <button id="rsc-adj-confirm" style="padding: 8px 16px; border-radius: 8px; border: none; background: #cba6f7; color: #1e1e2e; cursor: pointer; font-size: 13px; font-weight: 600;">Apply</button>\n            </div>\n        `,r.appendChild(a),document.body.appendChild(r);const i=()=>r.remove();r.addEventListener("click",e=>{e.target===r&&i()}),a.querySelector("#rsc-adj-cancel").onclick=i,a.querySelector("#rsc-adj-confirm").onclick=()=>{const e=parseInt(a.querySelector("#rsc-adj-x1").value),o=parseInt(a.querySelector("#rsc-adj-x2").value),r=parseInt(a.querySelector("#rsc-adj-y1").value),l=parseInt(a.querySelector("#rsc-adj-y2").value),s=a.querySelector("#rsc-adj-error");if([e,o,r,l].some(isNaN))return s.textContent="All fields must be valid numbers.",void(s.style.display="block");const c={minX:Math.min(e,o),maxX:Math.max(e,o),minY:Math.min(r,l),maxY:Math.max(r,l)},d=c.maxX-c.minX+1,p=c.maxY-c.minY+1;return d<2||p<2?(s.textContent="Region must be at least 2×2.",void(s.style.display="block")):d*p>t?(s.textContent=`Region too large (${d}×${p}).`,void(s.style.display="block")):(i(),void n(c))};const l=e=>{"Escape"===e.key&&(i(),document.removeEventListener("keydown",l))};document.addEventListener("keydown",l)}(e,e=>{!async function(e){const t=document.querySelector(".rsc-modal-container");t&&t.remove();const n=I(e,null,!0),o=n.querySelector(".rsc-progress-text"),r=e=>{o&&(o.textContent=e)};try{_(n,e,await L(e,r))}catch(e){console.error("[Region Screenshot] Error:",e),R("Error capturing screenshot: "+e.message),n.closeModal()}}(e)})},c.insertBefore(d,null);const p=document.createElement("button");p.innerHTML="✕",p.style.cssText="\n            flex-shrink: 0;\n            background: #313244;\n            border: none;\n            color: #a6adc8;\n            font-size: 16px;\n            width: 32px;\n            height: 32px;\n            border-radius: 8px;\n            cursor: pointer;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            transition: background 0.15s;\n        ",p.onmouseover=()=>{p.style.background="#45475a"},p.onmouseout=()=>{p.style.background="#313244"},c.appendChild(p);const g=document.createElement("div");g.className="rsc-modal-content",g.style.cssText="\n            flex: 1;\n            overflow: auto;\n            display: flex;\n            flex-direction: column;\n            gap: 14px;\n        ",o?g.innerHTML='\n                <div style="display: flex; flex-direction: column; align-items: center; justify-content: center;\n                            min-height: 180px; color: #a6adc8; gap: 12px;">\n                    <div style="font-size: 36px;">⏳</div>\n                    <div class="rsc-progress-text" style="font-size: 14px;">Preparing screenshot…</div>\n                    <div style="font-size: 12px; color: #6c7086;">Large regions may take a moment</div>\n                </div>\n            ':n&&G(g,e,n),s.appendChild(c),s.appendChild(g),l.appendChild(s),document.body.appendChild(l);const u=()=>l.remove();p.onclick=u,l.onclick=e=>{e.target===l&&u()};const m=e=>{"Escape"===e.key&&(u(),document.removeEventListener("keydown",m))};return document.addEventListener("keydown",m),s.closeModal=u,s}function _(e,t,n){const o=e.querySelector(".rsc-modal-content");o&&(o.innerHTML="",G(o,t,n))}function G(e,t,n){const o=t.maxX-t.minX+1,r=t.maxY-t.minY+1,a=document.createElement("div");a.style.cssText="\n            border-radius: 10px;\n            overflow: hidden;\n            max-height: 55vh;\n            background: repeating-conic-gradient(#313244 0% 25%, #45475a 0% 50%) 0 0 / 16px 16px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            border: 2px solid #45475a;\n        ";const i=document.createElement("img");i.style.cssText="\n            max-width: 100%;\n            max-height: 55vh;\n            image-rendering: pixelated;\n            object-fit: contain;\n        ";const l=g();let s=l.mode,c=l.color;const d=()=>m(n,s,c),p=()=>{i.src=d().toDataURL("image/png"),x&&(x.textContent="solid"===s?`${o}×${r} pixels • PNG with ${c.toUpperCase()} background`:`${o}×${r} pixels • PNG with transparent background`)};a.appendChild(i),e.appendChild(a);const h=document.createElement("div");h.style.cssText="display:flex;align-items:center;gap:10px;justify-content:center;flex-wrap:wrap;font-size:12px;color:#a6adc8;";const f=document.createElement("label");f.style.cssText="display:flex;align-items:center;gap:6px;font-weight:600;",f.textContent="Background";const b=document.createElement("select");b.style.cssText="padding:5px 8px;border-radius:6px;border:1px solid #45475a;background:#313244;color:#cdd6f4;font-size:12px;cursor:pointer;",[{value:"transparent",text:"Transparent"},{value:"solid",text:"Solid color"}].forEach(({value:e,text:t})=>{const n=document.createElement("option");n.value=e,n.textContent=t,b.appendChild(n)});const y=document.createElement("input");y.type="color",y.value=c,y.title="Background color",y.style.cssText="width:34px;height:28px;padding:2px;border-radius:6px;border:1px solid #45475a;background:#313244;cursor:pointer;display:none;",b.value=s,y.style.display="solid"===s?"":"none",b.addEventListener("change",()=>{s=b.value,y.style.display="solid"===s?"":"none",u(s,c),p()}),y.addEventListener("input",()=>{c=y.value,u(s,c),p()}),h.appendChild(f),h.appendChild(b),h.appendChild(y),e.appendChild(h);const x=document.createElement("p");x.style.cssText="margin: 0; font-size: 12px; color: #6c7086; text-align: center;",e.appendChild(x),p();const v=document.createElement("div");v.style.cssText="display: flex; gap: 10px; justify-content: stretch;";const w=document.createElement("button");w.innerHTML="⬇ Download PNG",w.style.cssText="\n            flex: 1;\n            padding: 10px 16px;\n            background: #cba6f7;\n            color: #1e1e2e;\n            border: none;\n            border-radius: 8px;\n            font-size: 14px;\n            font-weight: 600;\n            cursor: pointer;\n            transition: opacity 0.15s;\n        ",w.onmouseover=()=>{w.style.opacity="0.85"},w.onmouseout=()=>{w.style.opacity="1"},w.onclick=()=>{const e=document.createElement("a"),t=(()=>{try{const e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}T${String(e.getHours()).padStart(2,"0")}-${String(e.getMinutes()).padStart(2,"0")}-${String(e.getSeconds()).padStart(2,"0")}`}catch(e){return(new Date).toISOString().replace(/[:.]/g,"-").slice(0,19)}})();e.download=`geopixels-screenshot-${t}.png`,e.href=d().toDataURL("image/png"),e.click()};const k=document.createElement("button");k.innerHTML="📋 Copy to Clipboard",k.style.cssText="\n            flex: 1;\n            padding: 10px 16px;\n            background: #89dceb;\n            color: #1e1e2e;\n            border: none;\n            border-radius: 8px;\n            font-size: 14px;\n            font-weight: 600;\n            cursor: pointer;\n            transition: opacity 0.15s;\n        ",k.onmouseover=()=>{k.style.opacity="0.85"},k.onmouseout=()=>{k.style.opacity="1"},k.onclick=()=>{navigator.clipboard&&window.ClipboardItem?d().toBlob(async e=>{try{await navigator.clipboard.write([new ClipboardItem({"image/png":e})]),k.innerHTML="✅ Copied!",setTimeout(()=>{k.innerHTML="📋 Copy to Clipboard"},2e3)}catch(e){console.error("[Region Screenshot] Clipboard write failed:",e),R("Could not write to clipboard: "+e.message)}},"image/png"):R("Clipboard API not supported in this browser.")},v.appendChild(w),v.appendChild(k),e.appendChild(v);const E=document.createElement("button");E.textContent="🎨 Show Palette",E.style.cssText="\n            width: 100%; padding: 8px 16px;\n            background: #45475a; color: #cdd6f4;\n            border: none; border-radius: 8px; font-size: 13px;\n            font-weight: 600; cursor: pointer; transition: opacity 0.15s;\n        ",E.onmouseover=()=>{E.style.opacity="0.82"},E.onmouseout=()=>{E.style.opacity="1"};const C=document.createElement("div");C.style.cssText="\n            display: none;\n            background: #181825; border: 1px solid #45475a;\n            border-radius: 8px; padding: 10px 12px;\n        ";let S=!1;E.onclick=()=>{"none"!==C.style.display?(C.style.display="none",E.textContent="🎨 Show Palette"):(C.style.display="",E.textContent="🎨 Hide Palette",S||(S=!0,function(e,t){const n=function(e){try{const t=e.getContext("2d"),{width:n,height:o}=e,r=t.getImageData(0,0,n,o).data,a=new Map;for(let e=0;e<r.length;e+=4){if(r[e+3]<128)continue;const t="#"+[r[e],r[e+1],r[e+2]].map(e=>e.toString(16).toUpperCase().padStart(2,"0")).join("");a.set(t,(a.get(t)||0)+1)}return Array.from(a.entries()).sort((e,t)=>t[1]-e[1])}catch(e){return console.error("[Region Screenshot] extractPaletteFromCanvas error:",e),[]}}(t);if(!n.length)return void(e.innerHTML='<div style="font-size:12px;color:#6c7086;text-align:center;padding:4px;">No opaque pixels found in selection.</div>');const o=n.map(([e])=>e).join(", "),r=document.createElement("div");r.style.cssText="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;";const a=document.createElement("span");a.style.cssText="font-size:12px;color:#a6adc8;",a.textContent=n.length+" color"+(1!==n.length?"s":"");const i=document.createElement("button");i.textContent="📋 Copy hex list",i.style.cssText="padding:3px 8px;border-radius:5px;border:none;background:#585b70;color:#cdd6f4;font-size:11px;cursor:pointer;",i.onclick=()=>{const e=()=>{try{const e=document.createElement("textarea");e.value=o,e.style.cssText="position:fixed;top:-9999px;left:-9999px;",document.body.appendChild(e),e.select(),document.execCommand("copy"),e.remove(),i.textContent="✅ Copied!",setTimeout(()=>{i.textContent="📋 Copy hex list"},2e3)}catch(e){}};navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(o).then(()=>{i.textContent="✅ Copied!",setTimeout(()=>{i.textContent="📋 Copy hex list"},2e3)}).catch(e):e()},r.appendChild(a),r.appendChild(i),e.appendChild(r);const l=document.createElement("textarea");l.value=o,l.readOnly=!0,l.style.cssText="\n            width: 100%; height: 48px; resize: vertical;\n            background: #1e1e2e; border: 1px solid #45475a; border-radius: 6px;\n            padding: 6px 8px; font-family: monospace; font-size: 11px;\n            color: #cdd6f4; box-sizing: border-box; margin-bottom: 8px;\n        ",e.appendChild(l);const s=document.createElement("div");s.style.cssText="display:flex;flex-direction:column;gap:2px;max-height:180px;overflow-y:auto;",n.forEach(([e,t])=>{const n=document.createElement("div");n.style.cssText="display:flex;align-items:center;gap:8px;padding:2px 0;";const o=document.createElement("span");o.style.cssText=`\n                display:inline-block;width:14px;height:14px;border-radius:3px;\n                background:${e};border:1px solid rgba(255,255,255,0.18);flex-shrink:0;\n            `;const r=document.createElement("span");r.style.cssText="font-family:monospace;font-size:12px;color:#cdd6f4;flex:1;",r.textContent=e;const a=document.createElement("span");a.style.cssText="font-size:11px;color:#6c7086;white-space:nowrap;",a.textContent=t.toLocaleString()+" px",n.appendChild(o),n.appendChild(r),n.appendChild(a),s.appendChild(n)}),e.appendChild(s)}(C,n)))},e.appendChild(E),e.appendChild(C)}function R(e){if("function"==typeof showAnnouncement)return void showAnnouncement(e);const t=document.createElement("div");t.style.cssText="\n            position: fixed;\n            top: 20px;\n            left: 50%;\n            transform: translateX(-50%);\n            background: #313244;\n            color: #cdd6f4;\n            padding: 12px 24px;\n            border-radius: 10px;\n            z-index: 10002;\n            font-size: 14px;\n            box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n            font-family: system-ui, sans-serif;\n            max-width: 400px;\n            text-align: center;\n        ",t.textContent=e,document.body.appendChild(t),setTimeout(()=>{t.style.transition="opacity 0.3s",t.style.opacity="0",setTimeout(()=>t.remove(),300)},3500)}!async function(){await function(){const e=Date.now();let t=!0,n=!1;return new Promise(o=>{const r=()=>{t&&(t=!1,dbgPush("Region Screenshot: starting poll for map / turf / tileImageCache / #controls-left readiness (every 500ms).",{uiComponent:"Region Screenshot"}));const a=!!h(),i="undefined"!=typeof turf,l="undefined"!=typeof tileImageCache,s=!!document.getElementById("controls-left");if(a&&i&&l&&s)return dbgPush("Region Screenshot: all readiness conditions met after "+(Date.now()-e)+"ms -- resolving.",{uiComponent:"Region Screenshot"}),void o();if(!n&&Date.now()-e>=15e3){n=!0;const e="Region Screenshot: still waiting after 15s -- map="+a+", turf="+i+", tileImageCache="+l+", #controls-left="+s+". Will keep retrying every 500ms (this is a one-time diagnostic, not a giveup).";dbgPush(e,{uiComponent:"Region Screenshot"}),console.error("[GeoPixelcons++] "+e)}setTimeout(r,500)};r()})}(),console.log("[Region Screenshot] Initializing..."),function(){s=document.createElement("canvas"),s.id="screenshot-selection-canvas",s.style.cssText="\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100vw;\n            height: 100vh;\n            pointer-events: none;\n            z-index: 1000;\n        ",document.body.appendChild(s),c=s.getContext("2d");const e=()=>{const e=window.devicePixelRatio||1;s.width=window.innerWidth*e,s.height=window.innerHeight*e,c.setTransform(e,0,0,e,0,0)};e(),window.addEventListener("resize",e),["move","rotate","zoom"].forEach(e=>{p.on(e,()=>{a&&P()})})}(),d=document.createElement("button"),d.id="gpc-screenshot-trigger",d.style.display="none",d.addEventListener("click",f),document.body.appendChild(d),document.addEventListener("mousedown",v),document.addEventListener("mousemove",w),document.addEventListener("mouseup",k),document.addEventListener("keydown",E),console.log("[Region Screenshot] Ready!")}(),_regionScreenshot={processWithBounds:async function(e){const n=e.maxX-e.minX+1,o=e.maxY-e.minY+1;if(n<2||o<2)return void R("Selection too small — please select a larger area.");if(n*o>t)return void R(`Region too large (${n}×${o}). Maximum is ~15000×15000 px.`);const r=I(e,null,!0),a=r.querySelector(".rsc-progress-text"),i=e=>{a&&(a.textContent=e)};try{_(r,e,await L(e,i))}catch(e){console.error("[Region Screenshot] Error:",e),R("Error capturing screenshot: "+e.message);try{r.closeModal()}catch{}}},toggleSelectionMode:f,silentDownload:async function(e){const n=e.maxX-e.minX+1,o=e.maxY-e.minY+1;if(!(n<2||o<2||n*o>t))try{const t=await L(e,()=>{}),n=g(),o=m(t,n.mode,n.color),r=document.createElement("a"),a=(()=>{try{const e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}T${String(e.getHours()).padStart(2,"0")}-${String(e.getMinutes()).padStart(2,"0")}-${String(e.getSeconds()).padStart(2,"0")}`}catch(e){return(new Date).toISOString().replace(/[:.]/g,"-").slice(0,19)}})();r.download=`geopixels-screenshot-${a}.png`,r.href=o.toDataURL("image/png"),r.click()}catch(e){console.error("[Region Screenshot] Silent download error:",e)}}}}(),_featureStatus.regionScreenshot="ok",console.log("[GeoPixelcons++] ✅ Region Screenshot loaded")}catch(R){_featureStatus.regionScreenshot="error",dbgPush(`Region Screenshot init failed: ${R&&R.message?R.message:String(R)}`,{error:R,uiComponent:"Region Screenshot"}),console.error("[GeoPixelcons++] ❌ Region Screenshot failed:",R)}let gppBulkPurchaseOpenModal=null,gppBulkPurchaseOpenProfilePanel=null;if(_settings.bulkPurchaseColors)try{!function(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;function t(){return"dark"===getComputedStyle(document.documentElement).colorScheme}function n(){const e=t();return{panelBg:e?"#1e2939":"#fff",text:e?"#f3f4f6":"#1f2937",textMed:e?"#e5e7eb":"#374151",textSec:e?"#d1d5db":"#6b7280",textMuted:e?"#99a1af":"#9ca3af",textOwned:e?"#6a7282":"#b0b0b0",border:e?"#364153":"#e5e7eb",borderLight:e?"#364153":"#ececec",inputBorder:e?"#4a5565":"#d1d5db",rowBg:e?"#101828":"#fff",rowOwnedBg:e?"#1e2939":"#f3f4f6",sepBg:e?"#101828":"#f9fafb",progressBg:e?"#364153":"#e5e7eb",cancelBg:e?"#364153":"#e5e7eb",cancelText:e?"#e5e7eb":"#374151",closeBg:e?"#364153":"#f3f4f6",closeText:e?"#d1d5db":"#6b7280",queueBg:e?"#101828":"#fff",queueBorder:e?"#364153":"#e5e7eb"}}function o(){const t=e._gpAuth,n=t&&t.token||localStorage.getItem("tokenUser"),o=t&&null!=t.userId?t.userId:parseInt(localStorage.getItem("userID")||"",10),r=t&&t.subject||"";return!n||isNaN(o)?null:{token:n,userId:o,subject:r}}function r(e){if(!(e=(e||"").trim().replace(/^["'`]+|["'`]+$/g,"").trim()))return null;if(/^\d+$/.test(e)){const t=parseInt(e,10);return t<0||t>16777215?null:"#"+t.toString(16).toUpperCase().padStart(6,"0")}const t=e.replace(/^#/,"");if(/^[0-9A-Fa-f]{6}$/.test(t))return"#"+t.toUpperCase();if(/^[0-9A-Fa-f]{3}$/.test(t)){return"#"+t.split("").map(e=>e+e).join("").toUpperCase()}return null}function a(e){const t=(e||"").split(/[\s,\n]+/).filter(Boolean),n=new Set,o=[],a=[];for(const e of t){const t=r(e);t?n.has(t)||(n.add(t),o.push(t)):a.push(e)}return{valid:o,invalid:a}}function i(){const e=new Set;let t;try{t=Colors}catch(e){t=window.Colors}return Array.isArray(t)&&t.forEach(t=>{t&&"string"==typeof t&&e.add(t.toUpperCase())}),e}function l(e){return parseInt(e.replace(/^#/,""),16)}function s(){const e=document.querySelectorAll("#ghostColorPalette button[data-color-rgba], #ghostColorPalette button[title]"),t=new Set,n=[];return e.forEach(e=>{let o=null,r=0;const a=e.dataset.colorRgba;if(a){const e=a.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);e&&(o="#"+parseInt(e[1]).toString(16).toUpperCase().padStart(2,"0")+parseInt(e[2]).toString(16).toUpperCase().padStart(2,"0")+parseInt(e[3]).toString(16).toUpperCase().padStart(2,"0"))}if(!o&&e.title){const t=e.title.split(/[\r\n]+/)[0].trim().toUpperCase();/^#[0-9A-F]{6}$/.test(t)&&(o=t)}if(e.title){const t=e.title.split(/[\r\n]+/);for(let e=1;e<t.length;e++){const n=t[e].match(/(\d+)\s*pixel/i);if(n){r=parseInt(n[1],10);break}}}o&&/^#[0-9A-F]{6}$/.test(o)&&!t.has(o)&&(t.add(o),n.push({hex:o,count:r}))}),n.sort((e,t)=>t.count-e.count),n.map(e=>e.hex)}!function(){const e=document.createElement("script");e.textContent="\n            Object.defineProperty(window, '_gpAuth', {\n                configurable: true,\n                get: function() {\n                    return {\n                        token:   typeof tokenUser !== 'undefined' ? tokenUser : null,\n                        userId:  typeof userID   !== 'undefined' ? userID   : null,\n                        subject: typeof subject  !== 'undefined' ? subject  : null,\n                    };\n                }\n            });\n        ",(document.head||document.documentElement).appendChild(e),e.remove()}();let c=null,d=[];function p(){const e=t();return{pending:{label:"",bg:e?"#101828":"#f9fafb",border:e?"#364153":"#e5e7eb",textColor:e?"#6a7282":"#9ca3af"},owned:{label:"Already Owned",bg:e?"#422006":"#fefce8",border:e?"#a16207":"#fde047",textColor:e?"#fbbf24":"#92400e"},purchased:{label:"Purchased ✓",bg:e?"#052e16":"#f0fdf4",border:e?"#16a34a":"#86efac",textColor:e?"#4ade80":"#166534"},failed:{label:"Failed",bg:e?"#450a0a":"#fef2f2",border:e?"#dc2626":"#fca5a5",textColor:e?"#f87171":"#991b1b"},skipped:{label:"Skipped (Insufficient Pixels)",bg:e?"#0f172a":"#f1f5f9",border:e?"#475569":"#cbd5e1",textColor:e?"#94a3b8":"#64748b"}}}function g(e,t){const n=document.getElementById("gp-bulk-list");if(!n)return;const o=n.querySelector(`[data-gp-color="${e}"]`);if(!o)return;const r=p(),a=r[t]||r.pending;o.style.background=a.bg,o.style.borderColor=a.border;const i=o.querySelector(".gp-row-badge");i&&(i.textContent=a.label,i.style.color=a.textColor)}function u(e){!function(){if(c)return;const e=n();c=document.createElement("div"),c.id="gp-bulk-overlay",c.style.cssText="position:fixed;inset:0;z-index:10000;display:none;align-items:center;justify-content:center;background:rgba(0,0,0,0.55);",c.innerHTML=`\n<div id="gp-bulk-panel"\n     style="background:${e.panelBg};color:${e.text};border-radius:1rem;box-shadow:0 20px 60px rgba(0,0,0,0.3);width:90%;max-width:28rem;max-height:85vh;display:flex;flex-direction:column;padding:1.5rem;gap:1rem;overflow:hidden;">\n\n    \x3c!-- Header --\x3e\n    <div style="display:flex;align-items:center;justify-content:space-between;flex-shrink:0;">\n        <h2 id="gp-bulk-title" style="margin:0;font-size:1.25rem;font-weight:700;color:${e.text};">Bulk Purchase Preview</h2>\n        <button id="gp-bulk-close"\n                style="width:2rem;height:2rem;border-radius:50%;border:none;background:${e.closeBg};cursor:pointer;font-size:1rem;display:flex;align-items:center;justify-content:center;color:${e.closeText};"\n                title="Close">✕</button>\n    </div>\n\n    \x3c!-- Subtitle --\x3e\n    <p id="gp-bulk-subtitle" style="margin:0;font-size:0.85rem;color:${e.textSec};flex-shrink:0;"></p>\n\n    \x3c!-- Colour list (all colors in original order, owned grayed out) --\x3e\n    <div id="gp-bulk-list"\n         style="flex:1 1 auto;overflow-y:auto;display:flex;flex-direction:column;gap:0.5rem;padding-right:0.25rem;min-height:0;"></div>\n\n    \x3c!-- Progress bar (shown during purchase) --\x3e\n    <div id="gp-bulk-progress-wrap"\n         style="flex-shrink:0;display:none;">\n        <div style="width:100%;height:0.75rem;background:${e.progressBg};border-radius:9999px;overflow:hidden;">\n            <div id="gp-bulk-progress-bar"\n                 style="height:100%;width:0%;background:#3b82f6;border-radius:9999px;transition:width 0.2s ease;"></div>\n        </div>\n        <p id="gp-bulk-progress-text"\n           style="margin:0.25rem 0 0;font-size:0.75rem;color:${e.textSec};text-align:center;"></p>\n    </div>\n\n    \x3c!-- Action buttons --\x3e\n    <div style="display:flex;gap:0.75rem;flex-shrink:0;">\n        <button id="gp-bulk-cancel"\n                style="flex:1;padding:0.5rem 1rem;background:${e.cancelBg};border:none;border-radius:0.5rem;font-weight:600;cursor:pointer;font-size:0.9rem;color:${e.cancelText};">\n            Cancel\n        </button>\n        <button id="gp-bulk-confirm"\n                style="flex:1;padding:0.5rem 1rem;background:#3b82f6;color:#fff;border:none;border-radius:0.5rem;font-weight:600;cursor:pointer;font-size:0.9rem;">\n            Purchase All\n        </button>\n    </div>\n</div>`,document.body.appendChild(c),document.getElementById("gp-bulk-close").addEventListener("click",m),document.getElementById("gp-bulk-cancel").addEventListener("click",m),c.addEventListener("click",e=>{e.target===c&&m()}),document.getElementById("gp-bulk-confirm").addEventListener("click",h)}(),d=e;const o=i(),r=e.filter(e=>!o.has(e)).length,a=e.length-r,l=function(){const e=document.querySelectorAll("#ghostColorPalette button[data-color-rgba], #ghostColorPalette button[title]"),t=new Map;return e.forEach(e=>{let n=null,o=0;const r=e.dataset.colorRgba;if(r){const e=r.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);e&&(n="#"+parseInt(e[1]).toString(16).toUpperCase().padStart(2,"0")+parseInt(e[2]).toString(16).toUpperCase().padStart(2,"0")+parseInt(e[3]).toString(16).toUpperCase().padStart(2,"0"))}if(!n&&e.title){const t=e.title.split(/[\r\n]+/)[0].trim().toUpperCase();/^#[0-9A-F]{6}$/.test(t)&&(n=t)}if(e.title){const t=e.title.split(/[\r\n]+/);for(let e=1;e<t.length;e++){const n=t[e].match(/(\d+)\s*pixel/i);if(n){o=parseInt(n[1],10);break}}}n&&/^#[0-9A-F]{6}$/.test(n)&&t.set(n,o)}),t}(),s=l.size>0,g=document.getElementById("gp-bulk-list");g.innerHTML="",e.forEach(e=>{const r=s?l.get(e)??0:void 0;g.appendChild(function(e,o,r){const a=p(),i=a[o]||a.pending,l=n(),s=document.createElement("div");s.dataset.gpColor=e,s.style.cssText=`display:flex;align-items:center;gap:0.75rem;padding:0.5rem 0.75rem;background:${i.bg};border:1px solid ${i.border};border-radius:0.5rem;`;const c=document.createElement("div");c.style.cssText=`width:1.75rem;height:1.75rem;border-radius:0.25rem;border:1px solid ${l.inputBorder};flex-shrink:0;background:${e};`;const d=document.createElement("span");d.style.cssText=`font-family:monospace;font-size:0.875rem;color:${l.textMed};flex:1;`,d.textContent=e;const g=document.createElement("span");g.className="gp-row-ghost",null!=r&&(g.style.cssText=`font-size:0.7rem;font-weight:500;color:${r>0?t()?"#a78bfa":"#7c3aed":t()?"#6b7280":"#9ca3af"};white-space:nowrap;`,g.textContent=r>0?`${r} px`:"unused");const u=document.createElement("span");return u.className="gp-row-badge",u.style.cssText=`font-size:0.7rem;font-weight:600;color:${i.textColor};white-space:nowrap;`,u.textContent="pending"===o?"100 px":i.label,s.appendChild(c),s.appendChild(d),null!=r&&s.appendChild(g),s.appendChild(u),s}(e,o.has(e)?"owned":"pending",s?r:void 0))}),document.getElementById("gp-bulk-title").textContent="Bulk Purchase Preview";const u=[`${r} to purchase · est. ${(100*r).toLocaleString()} Pixels`];a>0&&u.push(`${a} already owned (will skip)`),document.getElementById("gp-bulk-subtitle").textContent=u.join(" · ");let f=document.getElementById("gp-bulk-ghost-legend");if(f&&f.remove(),s){f=document.createElement("p"),f.id="gp-bulk-ghost-legend";const e=t()?"#a78bfa":"#7c3aed";f.style.cssText=`margin:0;font-size:0.75rem;color:${t()?"#9ca3af":"#6b7280"};flex-shrink:0;`,f.innerHTML=`<span style="color:${e};font-weight:600;">Purple</span> = pixels used in the loaded ghost template`;document.getElementById("gp-bulk-subtitle").insertAdjacentElement("afterend",f)}document.getElementById("gp-bulk-progress-wrap").style.display="none",document.getElementById("gp-bulk-progress-bar").style.width="0%",document.getElementById("gp-bulk-progress-text").textContent="";const b=document.getElementById("gp-bulk-confirm"),y=document.getElementById("gp-bulk-cancel");b.style.display="",b.textContent="Purchase All",b.disabled=0===r,b.style.opacity=0===r?"0.5":"1",b.style.cursor=0===r?"not-allowed":"pointer",y.textContent="Cancel",y.disabled=!1,c.style.display="flex"}function m(){c&&(c.style.display="none"),d=[],document.getElementById("gp-bulk-queue-list")&&f()}async function h(){const t=document.getElementById("gp-bulk-confirm"),n=document.getElementById("gp-bulk-cancel"),r=document.getElementById("gp-bulk-close");t.disabled=!0,t.style.opacity="0.5",t.style.cursor="not-allowed",n.disabled=!0,r.disabled=!0;const s=[...d],c=await async function(t){const n=document.getElementById("gp-bulk-progress-wrap"),r=document.getElementById("gp-bulk-progress-bar"),a=document.getElementById("gp-bulk-progress-text");n.style.display="block";const s=o();if(!s)return a.textContent="Error: credentials not captured yet.",e.showAlert&&e.showAlert("Error","Credentials not ready. Place a pixel first to initialise auth, then retry."),new Map;const c=i(),d=new Map;t.forEach(e=>{c.has(e)&&d.set(e,"owned")});const p=t.filter(e=>!c.has(e));let u=-1;for(let e=0;e<p.length;e++){const t=p[e],n=Math.round(e/p.length*100);r.style.width=n+"%",a.textContent=`Purchasing ${e+1} of ${p.length}: ${t}`;try{const n=await window.fetch("/MakePurchase",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({Token:s.token,UserId:s.userId,Subject:s.subject,type:"ExtraColor",amount:l(t)})});if(200===n.status)d.set(t,"purchased"),g(t,"purchased");else{if(402===n.status){d.set(t,"skipped"),g(t,"skipped"),u=e;break}d.set(t,"failed"),g(t,"failed"),console.warn(`[BulkPurchase] Failed ${t}: HTTP ${n.status}`)}}catch(e){d.set(t,"failed"),g(t,"failed"),console.error("[BulkPurchase] Error purchasing",t,e)}}if(u>=0)for(let e=u+1;e<p.length;e++){const t=p[e];d.set(t,"skipped"),g(t,"skipped")}r.style.width="100%";const m=p.filter(e=>"purchased"===d.get(e)).length;if(m>0)try{let t;try{t=Colors.length}catch(n){t=(e.Colors||[]).length}const n=document.createElement("script");n.textContent=`(function(){try{for(var i=${t};i<${t+m};i++){if(!activeColors.includes(i))activeColors.push(i);}localStorage.setItem('activeColors',JSON.stringify(activeColors));}catch(e){}})();`,(document.head||document.documentElement).appendChild(n),n.remove()}catch(e){console.warn("[BulkPurchase] Could not auto-enable purchased colors:",e)}"function"==typeof window.synchronize&&window.synchronize();return d}(s),p=document.getElementById("gp-bulk-textarea");if(p){const{valid:e}=a(p.value),t=new Set(s.filter(e=>"purchased"===c.get(e))),n=e.filter(e=>!t.has(e));p.value=n.length?n.join(", "):""}!function(e,t){const n=e.filter(e=>"purchased"===t.get(e)).length,o=e.filter(e=>"owned"===t.get(e)).length,r=e.filter(e=>"failed"===t.get(e)).length,a=e.filter(e=>"skipped"===t.get(e)).length;document.getElementById("gp-bulk-title").textContent="Purchase Complete";const i=[];n>0&&i.push(`${n} purchased`);o>0&&i.push(`${o} already owned`);a>0&&i.push(`${a} skipped — insufficient Pixels`);r>0&&i.push(`${r} failed`);document.getElementById("gp-bulk-subtitle").textContent=i.join(" · "),document.getElementById("gp-bulk-confirm").style.display="none"}(s,c),r.disabled=!1,n.disabled=!1,n.textContent="Close"}function f(){const e=document.getElementById("gp-bulk-textarea"),t=document.getElementById("gp-bulk-queue-list"),n=document.getElementById("gp-bulk-empty-hint"),o=document.getElementById("gp-bulk-buy-all-btn"),r=document.getElementById("gp-bulk-parse-info"),l=document.getElementById("gp-bulk-sort-select");if(!e||!t)return;const{valid:s,invalid:c}=a(e.value),d=i(),p=function(){const e=document.querySelectorAll("#ghostColorPalette button[data-color-rgba], #ghostColorPalette button[title]"),t=new Map;return e.forEach(e=>{let n=null;const o=e.dataset.colorRgba;if(o){const e=o.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);e&&(n="#"+parseInt(e[1]).toString(16).toUpperCase().padStart(2,"0")+parseInt(e[2]).toString(16).toUpperCase().padStart(2,"0")+parseInt(e[3]).toString(16).toUpperCase().padStart(2,"0"))}const r=(e.title||"").split(/[\r\n]+/).map(e=>e.trim()).filter(Boolean);if(!n&&/^#[0-9A-F]{6}$/.test(r[0]||"")&&(n=r[0].toUpperCase()),!n||!/^#[0-9A-F]{6}$/.test(n))return;let a=0,i=0,l=!1;const s=(r[1]||"").match(/^([\d,]+)\s*\/\s*([\d,]+)/);if(s)l=!0,a=parseInt(s[1].replace(/,/g,""),10),i=parseInt(s[2].replace(/,/g,""),10);else for(let e=1;e<r.length;e++){const t=r[e].match(/([\d,]+)\s*pixel/i);if(t){i=parseInt(t[1].replace(/,/g,""),10);break}}const c=Math.max(0,i-a),d=i>0?c/i*100:0,p=i>0?a/i*100:0;t.set(n,{completed:a,total:i,remaining:c,remainingPercent:d,percent:p,hasProgress:l})}),t}(),g=Array.from(p.values()).some(e=>e.hasProgress),u=new Set(["mostRemaining","leastRemaining","mostPct","leastPct"]);l&&(Array.from(l.options).forEach(e=>{const t=u.has(e.value);e.hidden=t&&!g,e.disabled=t&&!g}),!g&&u.has(l.value)&&(l.value="default"));const m=l?l.value:"default";function h(e){const t=e=>p.get(e)||{total:0,remaining:0,remainingPercent:0},n=new Map(s.map((e,t)=>[e,t])),o=(e,t)=>(n.get(e)??0)-(n.get(t)??0);return[...e].sort((e,n)=>{const r=t(e),a=t(n);switch(m){case"default":return a.total-r.total||o(e,n);case"leastUsed":return r.total-a.total||o(e,n);case"mostRemaining":return a.remaining-r.remaining||o(e,n);case"leastRemaining":return r.remaining-a.remaining||o(e,n);case"mostPct":return a.remainingPercent-r.remainingPercent||o(e,n);case"leastPct":return r.remainingPercent-a.remainingPercent||o(e,n);case"byColor":return e.localeCompare(n)||o(e,n);case"byColorRev":return n.localeCompare(e)||o(e,n);default:return o(e,n)}})}const f=h(s.filter(e=>!d.has(e))),y=h(s.filter(e=>d.has(e)));if(r)if(e.value.trim()){const e=[`${f.length} to purchase`];y.length>0&&e.push(`${y.length} already owned`),c.length>0&&e.push(`${c.length} unrecognised`),r.textContent=e.join(" · ")}else r.textContent="";if(o){const e=f.length;o.textContent=`🛒 Buy All (${e})`,o.disabled=0===e,o.style.opacity=0===e?"0.5":"1",o.style.cursor=0===e?"not-allowed":"pointer"}if(t.innerHTML="",0===s.length)return void(n&&(n.style.display="block"));n&&(n.style.display="none");const x=p.size>0,v=e=>p.get(e)||{completed:0,total:0,percent:0};if(f.forEach(e=>t.appendChild(b(e,!1,x?v(e):void 0))),y.length>0){const e=document.createElement("div");e.className="bg-gray-100 dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-500 dark:text-gray-400",e.style.cssText="font-size:0.6rem;color:var(--color-gray-500,#6b7280);text-align:center;padding:0.2rem 0;border-top:1px solid var(--color-gray-300,#d1d5db);border-bottom:1px solid var(--color-gray-300,#d1d5db);background:var(--color-gray-100,#f3f4f6);letter-spacing:0.05em;user-select:none;",e.textContent="── Already Owned ──",t.appendChild(e),y.forEach(e=>t.appendChild(b(e,!0,x?v(e):void 0)))}}function b(t,n,r){const i=document.createElement("div");i.dataset.gpQueueColor=t,i.className=n?"gp-bulk-queue-row gp-bulk-queue-row-owned bg-gray-100 dark:bg-gray-800 border-gray-300 dark:border-gray-700":"gp-bulk-queue-row bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700",i.style.cssText=`display:flex;align-items:center;height:1.625rem;padding:0 0.35rem;background:${n?"var(--color-gray-100,#f3f4f6)":"var(--color-white,#fff)"};border-bottom:1px solid ${n?"var(--color-gray-300,#d1d5db)":"var(--color-gray-200,#e5e7eb)"};`+(n?"opacity:0.45;":"");const s=document.createElement("div");s.style.cssText=`width:0.875rem;height:0.875rem;border-radius:2px;flex-shrink:0;background:${t};border:1px solid rgba(0,0,0,0.12);margin-right:0.35rem;`;const c=document.createElement("span");if(c.style.cssText=`font-family:monospace;font-size:0.68rem;flex:1;overflow:hidden;color:${n?"var(--color-gray-500,#6b7280)":"var(--color-gray-700,#374151)"};letter-spacing:-0.01em;`,c.textContent=t,i.appendChild(s),i.appendChild(c),null!=r){const e=document.createElement("span"),t=r.total||0,n=r.completed||0,o=Math.round(10*(r.percent||0))/10,a=Number.isInteger(o)?String(o):o.toFixed(1);if(e.style.cssText="font-size:0.6rem;font-weight:600;white-space:nowrap;flex-shrink:0;padding:0 0.25rem;color:var(--color-gray-900,#f9fafb);",t>0&&r.hasProgress){const o="var(--color-gray-900,#f9fafb)",r="var(--color-purple-300,#c4b5fd)",i="var(--color-blue-300,#93c5fd)",l=(t,n)=>{const o=document.createElement("span");o.textContent=t,o.style.color=n,e.appendChild(o)};l(`${t.toLocaleString()} px `,o),l("(",o),l(`${n.toLocaleString()} px / ${t.toLocaleString()} px`,r),l(" | ",o),l(`${a}%`,i),l(")",o)}else e.textContent=t>0?`${t.toLocaleString()} px`:"—";i.appendChild(e)}if(n){const e=document.createElement("span");e.style.cssText="font-size:0.6rem;color:var(--color-gray-500,#6b7280);white-space:nowrap;flex-shrink:0;padding-left:0.25rem;",e.textContent="owned",i.appendChild(e)}else{const n=document.createElement("button");n.style.cssText="width:2.25rem;height:1.25rem;flex-shrink:0;background:#3b82f6;color:#fff;border:none;border-radius:3px;font-size:0.65rem;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;letter-spacing:0.02em;",n.textContent="BUY",n.addEventListener("mouseover",()=>{n.disabled||(n.style.background="#2563eb")}),n.addEventListener("mouseout",()=>{n.disabled||(n.style.background="#3b82f6")}),n.addEventListener("click",()=>async function(t,n){n.disabled=!0,n.style.opacity="0.5",n.style.cursor="not-allowed",n.textContent="…";const r=o();if(!r)return e.showAlert&&e.showAlert("Error","Not ready yet — credentials not captured. Try placing a pixel first, then retry."),n.disabled=!1,n.style.opacity="1",n.style.cursor="pointer",void(n.textContent="Buy");try{const o=await window.fetch("/MakePurchase",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({Token:r.token,UserId:r.userId,Subject:r.subject,type:"ExtraColor",amount:l(t)})});if(200===o.status)!function(e){const t=document.getElementById("gp-bulk-textarea");if(!t)return;const{valid:n}=a(t.value),o=n.filter(t=>t!==e);t.value=o.length?o.join(", "):"",t.dispatchEvent(new Event("input"))}(t),"function"==typeof window.synchronize&&window.synchronize(),e.showAlert&&e.showAlert("Success",`${t} purchased successfully!`);else if(402===o.status)e.showAlert&&e.showAlert("Error","Insufficient Pixels to purchase this color."),n.disabled=!1,n.style.opacity="1",n.style.cursor="pointer",n.textContent="Buy";else{const r=await o.text().catch(()=>"");e.showAlert&&e.showAlert("Error",`Failed to purchase ${t}. ${r}`.trim()),n.disabled=!1,n.style.opacity="1",n.style.cursor="pointer",n.textContent="Buy"}}catch(t){console.error("[BulkPurchase] Network error:",t),e.showAlert&&e.showAlert("Error","Network error during purchase."),n.disabled=!1,n.style.opacity="1",n.style.cursor="pointer",n.textContent="Buy"}}(t,n)),i.appendChild(n)}return i}function y(){if(document.getElementById("gp-bulk-profile-card"))return;const e=document.getElementById("freeColorNotice");if(!e)return;const t=e.closest('div[class*="p-4"]');if(!t)return;const o=t.parentElement;if(!o)return;const r=n(),i=document.createElement("div");i.id="gp-bulk-profile-card",i.className="p-4 bg-gray-100 rounded-xl shadow flex flex-col gap-3",i.style.gridColumn="1 / -1",i.innerHTML=`\n<div style="font-weight:600;font-size:1rem;color:${r.text};margin-bottom:0.125rem;">Bulk Purchase Colors</div>\n<div style="display:flex;gap:1rem;align-items:flex-start;flex-wrap:wrap;">\n\n    \x3c!-- Left: textarea input --\x3e\n    <div style="flex:1;min-width:11rem;display:flex;flex-direction:column;gap:0.5rem;">\n        <div class="text-sm text-gray-500">Comma, space, or newline &mdash; hex or decimal</div>\n        <textarea id="gp-bulk-textarea"\n                  rows="6"\n                  placeholder="#FF0000, #00FF00&#10;FF0000 00FF00&#10;16711680"\n                  class="w-full border rounded-lg px-3 py-2 text-sm font-mono resize-y"\n                  style="outline:none;transition:box-shadow 0.15s;"\n                  onfocus="this.style.boxShadow='0 0 0 2px #3b82f6'"\n                  onblur="this.style.boxShadow='none'"\n        ></textarea>\n        <p id="gp-bulk-parse-info" style="margin:0;font-size:0.75rem;color:${r.textMuted};min-height:1rem;"></p>\n    </div>\n\n    \x3c!-- Right: live color queue --\x3e\n    <div style="flex:1;min-width:12rem;display:flex;flex-direction:column;gap:0.5rem;">\n        <button id="gp-bulk-buy-all-btn"\n                style="width:100%;padding:0.5rem 0.75rem;background:#3b82f6;color:#fff;\n                       border:none;border-radius:0.5rem;font-weight:600;font-size:0.875rem;\n                       cursor:not-allowed;opacity:0.5;text-align:center;"\n                disabled>\n            &#x1F6D2; Buy All (0)\n        </button>\n         <div style="display:flex;align-items:center;gap:0.4rem;">\n            <select id="gp-bulk-sort-select"\n                  class="border rounded-md bg-white dark:bg-gray-900 text-gray-700 dark:text-gray-200"\n                    title="Scroll while hovering to change sort order"\n                  style="flex:1;min-width:0;border:1px solid var(--color-gray-300,#d1d5db);border-radius:0.375rem;\n                      background:var(--color-white,#fff);color:var(--color-gray-700,#374151);font-size:0.75rem;padding:0.25rem 0.35rem;cursor:pointer;">\n              <option value="default">Sort by: Most used (default)</option>\n              <option value="leastUsed">Sort by: Least used</option>\n              <option value="mostRemaining">Sort by: Most remaining</option>\n              <option value="leastRemaining">Sort by: Least remaining</option>\n              <option value="mostPct">Sort by: Most % remaining</option>\n              <option value="leastPct">Sort by: Least % remaining</option>\n                <option value="byColor">Sort by: Color</option>\n                <option value="byColorRev">Sort by: Color reversed</option>\n            </select>\n        </div>\n        <div id="gp-bulk-queue-list"\n              class="border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900"\n             style="max-height:260px;overflow-y:auto;display:flex;flex-direction:column;\n                  border:1px solid var(--color-gray-200,#e5e7eb);border-radius:0.375rem;overflow-x:hidden;\n                  background:var(--color-white,#fff);"></div>\n        <p id="gp-bulk-empty-hint"\n           style="margin:0;font-size:0.75rem;color:${r.textMuted};text-align:center;">Enter colors on the left</p>\n    </div>\n\n</div>`,o.appendChild(i);const l=document.getElementById("gp-bulk-textarea");l.addEventListener("input",f);const c=document.getElementById("gp-bulk-sort-select");c&&(c.addEventListener("change",f),c.addEventListener("wheel",e=>{e.preventDefault();const t=e.deltaY>0?1:-1;let n=c.selectedIndex+t;for(;n>=0&&n<c.options.length&&c.options[n].disabled;)n+=t;n=Math.min(Math.max(n,0),c.options.length-1),n!==c.selectedIndex&&(c.selectedIndex=n,f())},{passive:!1})),document.getElementById("gp-bulk-buy-all-btn").addEventListener("click",()=>{const{valid:e}=a(l.value);0!==e.length&&u(e)});const d=document.createElement("button");d.id="gp-bulk-ghost-fetch-btn",d.className="px-3 py-2 text-white text-sm rounded-lg shadow transition cursor-pointer",d.style.background="#7c3aed",d.style.border="none",d.style.fontWeight="600",d.textContent="👻 Add Ghost Template Colors",d.title="Fetch colors from the current ghost template and populate the text field",d.addEventListener("mouseover",()=>{d.style.background="#6d28d9"}),d.addEventListener("mouseout",()=>{d.style.background="#7c3aed"}),d.addEventListener("click",()=>{const e=s();if(0===e.length)return void alert("No ghost palette colors found. Make sure a ghost image is loaded.");const t=l.value.trim();l.value=t?t+", "+e.join(", "):e.join(", "),l.dispatchEvent(new Event("input"))});const p=document.getElementById("gp-bulk-parse-info");p&&p.parentElement&&p.parentElement.appendChild(d),f();const g=document.getElementById("ghostColorPalette");g&&new MutationObserver(()=>{document.getElementById("gp-bulk-queue-list")&&f()}).observe(g,{childList:!0})}function x(){if(document.getElementById("gp-ghost-buy-btn"))return;const e=document.getElementById("filterByUserPaletteBtn");if(!e)return;const t=document.createElement("button");t.id="gp-ghost-buy-btn",t.className="px-3 py-2 text-white text-sm rounded-lg shadow transition cursor-pointer",t.style.background="#7c3aed",t.title="Find ghost-image colors you don't own yet and open the bulk-purchase flow",t.textContent="Bulk Purchase Colors",t.addEventListener("mouseover",()=>{t.style.background="#6d28d9"}),t.addEventListener("mouseout",()=>{t.style.background="#7c3aed"}),t.addEventListener("click",w),e.parentElement.appendChild(t)}function v(t){const n=document.getElementById("profileOverlay");n&&n.classList.contains("hidden")&&"function"==typeof e.toggleProfile&&e.toggleProfile(),setTimeout(()=>{y();const e=document.getElementById("gp-bulk-textarea");e&&(e.value=t.join(", "),e.dispatchEvent(new Event("input")),e.scrollIntoView({behavior:"smooth",block:"center"}));const n=document.getElementById("gp-bulk-profile-card");n&&(n.style.transition="box-shadow 0.15s ease",n.style.boxShadow="0 0 0 3px #fbbf24, 0 0 18px 6px rgba(251,191,36,0.55)",setTimeout(()=>{n.style.boxShadow="none"},900))},300)}async function w(){const e=document.getElementById("gp-ghost-buy-btn");e&&(e.disabled=!0,e.textContent="Checking…");try{const e=s();if(0===e.length)return void(r.showAlert&&r.showAlert("Info","No ghost palette colors found. Make sure a ghost image is loaded and its color palette is visible in the modal."));const t=await async function(){const e=o();if(!e)return console.warn("[BulkPurchase] Credentials not yet captured, falling back to local Colors."),i();try{const t=await window.fetch("/GetUserData",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:e.userId,token:e.token})});if(!t.ok)throw new Error(`HTTP ${t.status}`);const n=await t.json(),o=new Set,r=n.colors;return"string"==typeof r?r.split(",").forEach(e=>{const t=parseInt(e.trim(),10);!isNaN(t)&&t>=0&&t<=16777215&&o.add("#"+t.toString(16).toUpperCase().padStart(6,"0"))}):Array.isArray(r)&&r.forEach(e=>{"number"==typeof e&&e>=0&&e<=16777215&&o.add("#"+e.toString(16).toUpperCase().padStart(6,"0"))}),i().forEach(e=>o.add(e)),o}catch(e){return console.warn("[BulkPurchase] GetUserData failed, falling back to local Colors:",e),i()}}(),n=e.filter(e=>!t.has(e));if(0===n.length)return void(r.showAlert&&r.showAlert("Info","You already own all colors used in this ghost image!"));const r="undefined"!=typeof unsafeWindow?unsafeWindow:window;"function"==typeof r.toggleGhostModal&&r.toggleGhostModal(!1),v(n)}finally{e&&(e.disabled=!1,e.textContent="Bulk Purchase Colors")}}function k(){y(),x();new MutationObserver(()=>{y(),x()}).observe(document.body,{childList:!0,subtree:!0})}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",k):k(),gppBulkPurchaseOpenModal=u,gppBulkPurchaseOpenProfilePanel=v}(),_featureStatus.bulkPurchaseColors="ok",console.log("[GeoPixelcons++] ✅ Bulk Purchase Colors loaded")}catch(N){_featureStatus.bulkPurchaseColors="error",dbgPush(`Bulk Purchase Colors init failed: ${N&&N.message?N.message:String(N)}`,{error:N,uiComponent:"Bulk Purchase Colors"}),console.error("[GeoPixelcons++] ❌ Bulk Purchase Colors failed:",N)}if(_settings.extAutoHoverMenus)try{!function(){const e=new WeakMap;let t=[],n=!1;function o(){const r=document.getElementById("controls-left");if(!r){if(n)return void dbgPush("Auto-open Menus on Hover: scanAndAttach() re-invoked but #controls-left is missing even though it was found previously -- unexpected DOM state, skipping this scan.",{uiComponent:"Auto-open Menus on Hover"});dbgPush("Auto-open Menus on Hover: #controls-left NOT found on the first synchronous check -- watching for it to appear.",{uiComponent:"Auto-open Menus on Hover"});const e=Date.now(),t=new MutationObserver(()=>{document.getElementById("controls-left")&&(t.disconnect(),clearTimeout(r),n=!0,dbgPush("Auto-open Menus on Hover: #controls-left appeared "+(Date.now()-e)+"ms after watching started -- scanning now.",{uiComponent:"Auto-open Menus on Hover"}),o())});t.observe(document.body,{childList:!0,subtree:!0});const r=setTimeout(()=>{t.disconnect(),dbgPush("Auto-open Menus on Hover: gave up after 15s -- #controls-left was never found, hover-to-open menus could not be attached at all.",{uiComponent:"Auto-open Menus on Hover"}),console.error("[GeoPixelcons++] Auto-open Menus on Hover: never found #controls-left.")},15e3);return}n=!0;const a=Array.from(r.querySelectorAll('button[id$="GroupBtn"], button[id$="plusplusBtn"]'));t.forEach(e=>{e.button&&e._hoverHandler&&e.button.removeEventListener("mouseenter",e._hoverHandler),e._parentEl&&e._parentLeaveHandler&&e._parentEl.removeEventListener("mouseleave",e._parentLeaveHandler)}),t=a.map(t=>{const n=t.closest("div.relative")||t.parentElement,o=n&&(n.querySelector(".dropdown-menu")||n.querySelector('[role="menu"]')||n.querySelector("ul"))||null,r={button:t,parent:n,dropdown:o,_gpcOpened:!1};r._hoverHandler=()=>{!function(t){if(t._gpcOpened)return;const n=Date.now();if(!(n-(e.get(t.button)||0)<400||function(e){const{button:t,parent:n}=e;if(!t)return!1;if("true"===t.getAttribute("aria-expanded"))return!0;if(n&&"true"===n.getAttribute("aria-expanded"))return!0;if(t.classList.contains("active")||n&&n.classList.contains("active"))return!0;const o=e.dropdown||n&&(n.querySelector(".dropdown-menu")||n.querySelector('[role="menu"]'))||null;if(o){if(null!==o.offsetParent)return!0;if(o.classList.contains("show")||o.classList.contains("open"))return!0}if(n){const e=n.querySelectorAll('ul, [class*="dropdown"], [class*="menu"]');for(const n of e)if(n!==t&&null!==n.offsetParent&&n.childElementCount>0)return!0}return!1}(t)))try{t.button.click(),e.set(t.button,n),t._gpcOpened=!0}catch(e){}}(r)},t.addEventListener("mouseenter",r._hoverHandler);const a=n||t;return r._parentEl=a,r._parentLeaveHandler=e=>{a.contains(e.relatedTarget)||(r._gpcOpened=!1)},a.addEventListener("mouseleave",r._parentLeaveHandler),r})}let r=null;function a(){o(),function(){const e=document.body;if(!e)return;new MutationObserver(()=>{clearTimeout(r),r=setTimeout(o,150)}).observe(e,{childList:!0,subtree:!0})}()}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",a):a()}(),_featureStatus.extAutoHoverMenus="ok",console.log("[GeoPixelcons++] ✅ Auto-open Menus on Hover loaded")}catch(A){_featureStatus.extAutoHoverMenus="error",dbgPush(`Auto-open Menus on Hover init failed: ${A&&A.message?A.message:String(A)}`,{error:A,uiComponent:"Auto-open Menus on Hover"}),console.error("[GeoPixelcons++] ❌ Auto-open Menus on Hover failed:",A)}if(_settings.extGoToLastLocation)try{(function _ext_goToLastLocation(){const SPAWN_LNG_MIN=-75,SPAWN_LNG_MAX=-73,SPAWN_LAT_MIN=39,SPAWN_LAT_MAX=41;let hasClicked=!1,observer=null;function checkAndClick(){if(hasClicked)return;const button=document.getElementById("lastLocationButton");let mapObj=null;try{mapObj=eval("map")}catch(e){return}if(button&&"function"==typeof window.goToLocation&&mapObj&&"function"==typeof mapObj.getCenter)try{const e=mapObj.getCenter(),t=e.lng,n=e.lat;t>=SPAWN_LNG_MIN&&t<=SPAWN_LNG_MAX&&n>=SPAWN_LAT_MIN&&n<=SPAWN_LAT_MAX&&(hasClicked=!0,observer&&observer.disconnect(),button.click())}catch(e){}}checkAndClick(),hasClicked||(observer=new MutationObserver(()=>{checkAndClick()}),observer.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>{!hasClicked&&observer&&observer.disconnect()},1e4))})(),_featureStatus.extGoToLastLocation="ok",console.log("[GeoPixelcons++] ✅ Auto-Go to Last Location loaded")}catch(z){_featureStatus.extGoToLastLocation="error",dbgPush(`Auto-Go to Last Location init failed: ${z&&z.message?z.message:String(z)}`,{error:z,uiComponent:"Auto-Go to Last Location"}),console.error("[GeoPixelcons++] ❌ Auto-Go to Last Location failed:",z)}if(_settings.extPillHoverLabels)try{!function(){const e="data-gpc-pill";function t(t){if(t.hasAttribute(e))return;if(t.classList.contains("gpc-pill-btn"))return;if(!t.classList.contains("w-10")||!t.classList.contains("h-10"))return;if(!t.classList.contains("rounded-full")&&!t.classList.contains("rounded-xl"))return;if(!t.closest(".dropdown-menu"))return;if(!t.closest("#controls-left"))return;if(t.classList.contains("hidden"))return;t.setAttribute(e,"1");const n=t.title||t.getAttribute("aria-label")||"";if(!n)return;const o=t.querySelector("svg"),r=t.textContent.trim(),a=document.createElement("span");a.style.cssText="width:40px;min-width:40px;display:flex;align-items:center;justify-content:center;flex-shrink:0;line-height:40px;pointer-events:none;",o?a.appendChild(o.cloneNode(!0)):a.textContent=r;const i=document.createElement("span");i.style.cssText="white-space:nowrap;font-size:12px;font-weight:600;color:var(--color-gray-700, #374151);opacity:0;transition:opacity .2s .05s;padding-right:12px;pointer-events:none;",i.textContent=n,t.innerHTML="",t.style.position="relative",t.style.width="40px",t.style.height="40px",t.style.borderRadius="9999px",t.style.background="var(--color-white, #fff)",t.style.boxShadow="0 1px 3px rgba(0,0,0,.12)",t.style.alignItems="center",t.style.justifyContent="flex-start",t.style.border="none",t.style.cursor="pointer",t.style.overflow="hidden",t.style.transition="width .25s cubic-bezier(.4,0,.2,1), background .15s",t.style.padding="0",t.style.fontSize="16px",t.style.flexShrink="0",t.classList.contains("hidden")||(t.style.display="flex"),t.classList.remove("w-10","h-10"),t.appendChild(a),t.appendChild(i),t.addEventListener("mouseenter",()=>{const e=i.scrollWidth+12;t.style.width=40+e+"px",i.style.opacity="1",t.style.background="var(--color-gray-100, #f3f4f6)"}),t.addEventListener("mouseleave",()=>{t.style.width="40px",i.style.opacity="0",t.style.background="var(--color-white, #fff)"})}function n(){const n=document.getElementById("controls-left");n&&(n.querySelectorAll(".dropdown-menu button.rounded-full, .dropdown-menu button.rounded-xl").forEach(t),n.querySelectorAll(".dropdown-menu button["+e+"]").forEach(n=>{n.classList.contains("hidden")||n.querySelector("span")||(n.removeAttribute(e),n.classList.add("w-10","h-10"),t(n))}))}function o(e){n();const t=new MutationObserver(()=>{clearTimeout(o),o=setTimeout(n,150)});let o=null;t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class"]})}function r(){const e=Date.now(),t=document.getElementById("controls-left");if(t)return dbgPush("Pill Hover Labels: #controls-left found on the first synchronous check -- starting scan now.",{uiComponent:"Pill Hover Labels"}),void o(t);dbgPush("Pill Hover Labels: #controls-left NOT found on the first synchronous check -- watching for it to appear.",{uiComponent:"Pill Hover Labels"});const n=new MutationObserver(()=>{const t=document.getElementById("controls-left");t&&(n.disconnect(),clearTimeout(r),dbgPush("Pill Hover Labels: #controls-left appeared "+(Date.now()-e)+"ms after watching started -- starting scan now.",{uiComponent:"Pill Hover Labels"}),o(t))});n.observe(document.body,{childList:!0,subtree:!0});const r=setTimeout(()=>{n.disconnect(),dbgPush("Pill Hover Labels: gave up after 15s -- #controls-left was never found, so pill hover labels could not be initialized at all.",{uiComponent:"Pill Hover Labels"}),console.error("[GeoPixelcons++] Pill Hover Labels: never found #controls-left.")},15e3)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",r):r()}(),_featureStatus.extPillHoverLabels="ok",console.log("[GeoPixelcons++] ✅ Pill Hover Labels loaded")}catch(B){_featureStatus.extPillHoverLabels="error",dbgPush(`Pill Hover Labels init failed: ${B&&B.message?B.message:String(B)}`,{error:B,uiComponent:"Pill Hover Labels"}),console.error("[GeoPixelcons++] ❌ Pill Hover Labels failed:",B)}if(_settings.extJanitorView)try{!function(){function e(){const e=document.getElementById("modGroupBtn");return!(!e||!e.classList.contains("hidden"))&&(e.classList.remove("hidden"),!0)}function t(){if(e())return;const t=new MutationObserver(()=>{e()&&t.disconnect()});t.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class"]}),setTimeout(()=>t.disconnect(),3e4)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}(),_featureStatus.extJanitorView="ok",console.log("[GeoPixelcons++] ✅ Janitor View loaded")}catch(O){_featureStatus.extJanitorView="error",dbgPush(`Janitor View init failed: ${O&&O.message?O.message:String(O)}`,{error:O,uiComponent:"Janitor View"}),console.error("[GeoPixelcons++] ❌ Janitor View failed:",O)}if(_settings.extMapMovementLock)try{!function(){const e="gpc-map-movement-locked",t="gpc-map-movement-lock-btn";function n(){const t="undefined"!=typeof unsafeWindow?unsafeWindow:window;return"function"==typeof t.__gpcGetMapMovementLocked?!!t.__gpcGetMapMovementLocked():"1"===localStorage.getItem(e)}function o(t){const n="undefined"!=typeof unsafeWindow?unsafeWindow:window;return"function"==typeof n.__gpcSetMapMovementLocked?!!n.__gpcSetMapMovementLocked(t):(localStorage.setItem(e,t?"1":"0"),t)}function r(e){const t=n();e.dataset.locked=t?"true":"false",e.setAttribute("aria-pressed",t?"true":"false"),e.textContent=t?"🔒":"🔓";const o=function(){const e=i(),t=[];e.ctrl&&t.push("Ctrl");e.shift&&t.push("Shift");return t.push((e.key||"L").toUpperCase()),t.join("+")}();e.title=t?`Map movement locked – click or press ${o} to unlock`:`Lock map movement (${o})`,e.setAttribute("aria-label",t?"Unlock map movement":"Lock map movement")}function a(e){let a=document.getElementById(t);if(a)return a;a=document.createElement("button"),a.id=t,a.type="button",a.addEventListener("click",()=>{o(!n()),r(a)}),document.addEventListener("gpc:mapMovementLockChanged",()=>r(a)),r(a);const i=document.getElementById("zoomIn");return i&&i.parentElement===e?e.insertBefore(a,i):e.prepend(a),a}function i(){try{const e=JSON.parse(localStorage.getItem("geopixelcons_settings")||"{}"),t=e.keybinds&&e.keybinds.mapMovementLock;if(t&&"string"==typeof t.key&&t.key.length>0)return t}catch(e){}return{key:"L",ctrl:!0,shift:!0}}function l(){!function(){const t=document.createElement("script");t.textContent=`\n(function(){\nif(window.__gpcMapMovementLockBridge)return;\nwindow.__gpcMapMovementLockBridge=true;\nvar storageKey='${e}';\nvar handlerNames=['dragPan','scrollZoom','boxZoom','doubleClickZoom','touchZoomRotate','keyboard','dragRotate','touchPitch'];\nvar movementMethods=['panBy','panTo','zoomIn','zoomOut','zoomTo','setZoom','setCenter','easeTo','flyTo','jumpTo','fitBounds','fitScreenCoordinates','rotateTo','resetNorth','snapToNorth','setBearing','setPitch'];\nvar state={locked:localStorage.getItem(storageKey)==='1',snapshotTaken:false,handlerWasEnabled:{}};\nwindow.__gpcMapMovementLocked=state.locked;\nfunction getMap(){try{return typeof map!=='undefined'&&map&&typeof map.getCanvas==='function'?map:null;}catch(e){return null;}}\nfunction applyPageScrollLock(){\n    var root=document.documentElement;\n    var body=document.body;\n    if(root)root.classList.toggle('gpc-map-movement-page-locked',state.locked);\n    if(body)body.classList.toggle('gpc-map-movement-page-locked',state.locked);\n}\nfunction installGuards(m){\n    if(!m||m.__gpcMapMovementLockGuarded)return;\n    Object.defineProperty(m,'__gpcMapMovementLockGuarded',{value:true,configurable:true});\n    movementMethods.forEach(function(name){\n        if(typeof m[name]!=='function'||m[name].__gpcMapMovementLockGuarded)return;\n        var original=m[name];\n        var guarded=function(){\n            if(window.__gpcMapMovementLocked)return this;\n            return original.apply(this,arguments);\n        };\n        Object.defineProperty(guarded,'__gpcMapMovementLockGuarded',{value:true,configurable:true});\n        Object.defineProperty(guarded,'__gpcMapMovementLockOriginal',{value:original,configurable:true});\n        m[name]=guarded;\n    });\n    handlerNames.forEach(function(name){\n        var handler=m[name];\n        if(!handler||typeof handler.enable!=='function'||handler.__gpcMapMovementLockGuarded)return;\n        var originalEnable=handler.enable;\n        var guardedEnable=function(){\n            if(window.__gpcMapMovementLocked)return this;\n            return originalEnable.apply(this,arguments);\n        };\n        Object.defineProperty(handler,'__gpcMapMovementLockGuarded',{value:true,configurable:true});\n        Object.defineProperty(handler,'__gpcMapMovementLockOriginalEnable',{value:originalEnable,configurable:true});\n        handler.enable=guardedEnable;\n    });\n}\nfunction disableHandlers(m){\n    if(!state.snapshotTaken){\n        state.handlerWasEnabled={};\n        handlerNames.forEach(function(name){\n            var handler=m[name];\n            state.handlerWasEnabled[name]=!!(handler&&typeof handler.isEnabled==='function'&&handler.isEnabled());\n        });\n        state.snapshotTaken=true;\n    }\n    handlerNames.forEach(function(name){\n        var handler=m[name];\n        if(handler&&typeof handler.disable==='function')handler.disable();\n    });\n    if(typeof m.stop==='function')m.stop();\n}\nfunction restoreHandlers(m){\n    if(!state.snapshotTaken)return;\n    handlerNames.forEach(function(name){\n        var handler=m[name];\n        if(!state.handlerWasEnabled[name]||!handler)return;\n        var originalEnable=handler.__gpcMapMovementLockOriginalEnable||handler.enable;\n        if(typeof originalEnable==='function')originalEnable.apply(handler);\n    });\n    state.handlerWasEnabled={};\n    state.snapshotTaken=false;\n}\nfunction applyLockState(){\n    applyPageScrollLock();\n    var m=getMap();\n    if(!m)return false;\n    installGuards(m);\n    if(state.locked)disableHandlers(m);\n    else restoreHandlers(m);\n    return true;\n}\nwindow.__gpcGetMapMovementLocked=function(){return state.locked;};\nwindow.__gpcSetMapMovementLocked=function(locked){\n    state.locked=!!locked;\n    window.__gpcMapMovementLocked=state.locked;\n    localStorage.setItem(storageKey,state.locked?'1':'0');\n    applyLockState();\n    document.dispatchEvent(new CustomEvent('gpc:mapMovementLockChanged',{detail:{locked:state.locked}}));\n    return state.locked;\n};\nwindow.__gpcToggleMapMovementLocked=function(){return window.__gpcSetMapMovementLocked(!state.locked);};\nvar wait=setInterval(function(){if(applyLockState())clearInterval(wait);},250);\nsetTimeout(function(){clearInterval(wait);},30000);\napplyLockState();\n})();`,document.head.appendChild(t),t.remove()}(),function(){if(document.getElementById("gpc-map-movement-lock-style"))return;const e=document.createElement("style");e.id="gpc-map-movement-lock-style",e.textContent=`\n            #${t} {\n                width: 40px;\n                height: 40px;\n                border-radius: 9999px;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n                cursor: pointer;\n                user-select: none;\n                border: 1px solid var(--color-gray-200, #e5e7eb);\n                background: var(--color-gray-100, #fff);\n                color: var(--color-gray-700, #374151);\n                box-shadow: 0 1px 3px rgba(0,0,0,0.16);\n                font-size: 18px;\n                line-height: 1;\n                transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s;\n            }\n            #${t}:hover {\n                background: var(--color-gray-200, #f3f4f6);\n            }\n            #${t}[data-locked="true"] {\n                background: var(--color-green-100, #dcfce7);\n                color: var(--color-green-900, #14532d);\n                border-color: var(--color-green-500, #22c55e);\n            }\n            #${t}[data-locked="true"]:hover {\n                background: var(--color-green-200, #bbf7d0);\n            }\n            #${t}:active {\n                transform: scale(0.96);\n            }\n            html.gpc-map-movement-page-locked,\n            body.gpc-map-movement-page-locked {\n                width: 100% !important;\n                height: 100% !important;\n                max-width: 100vw !important;\n                max-height: 100dvh !important;\n                overflow: hidden !important;\n                overscroll-behavior: none !important;\n            }\n            html.gpc-map-movement-page-locked {\n                scrollbar-width: none;\n            }\n            html.gpc-map-movement-page-locked::-webkit-scrollbar,\n            body.gpc-map-movement-page-locked::-webkit-scrollbar {\n                display: none;\n            }\n        `,document.head.appendChild(e)}(),function(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;e.__gpcMapLockShortcutInstalled||(e.__gpcMapLockShortcutInstalled=!0,document.addEventListener("keydown",e=>{const a=i();if(e.altKey||e.metaKey)return;if(a.ctrl!==e.ctrlKey)return;if(a.shift!==e.shiftKey)return;if(e.key.toUpperCase()!==(a.key||"L").toUpperCase())return;const l=e.target;if(l&&("INPUT"===l.tagName||"TEXTAREA"===l.tagName||l.isContentEditable))return;e.preventDefault(),e.stopImmediatePropagation(),o(!n());const s=document.getElementById(t);s&&r(s)},!0))}();const l=document.getElementById("controls-right");if(l)return void a(l);const s=new MutationObserver(()=>{const e=document.getElementById("controls-right");e&&(s.disconnect(),a(e))});s.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>s.disconnect(),15e3)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",l):l()}(),_featureStatus.extMapMovementLock="ok",console.log("[GeoPixelcons++] ✅ Map Movement Lock loaded")}catch(D){_featureStatus.extMapMovementLock="error",dbgPush(`Map Movement Lock init failed: ${D&&D.message?D.message:String(D)}`,{error:D,uiComponent:"Map Movement Lock"}),console.error("[GeoPixelcons++] ❌ Map Movement Lock failed:",D)}if(_settings.extGuildSearch)try{!function(){const e="gpc-guild-search-btn";function t(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;if("function"==typeof e.toggleGuildSearchModal)return void e.toggleGuildSearchModal();const t=document.createElement("script");t.textContent='if(typeof toggleGuildSearchModal==="function")toggleGuildSearchModal();',document.head.appendChild(t),t.remove()}function n(n){if(document.getElementById(e))return;const o=document.createElement("button");o.id=e,o.type="button",o.className="w-10 h-10 rounded-full",o.title="Search Guilds",o.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>',o.addEventListener("click",t);const r=document.getElementById("guildMenuBtn");r&&r.parentElement?r.parentElement.insertBefore(o,r.nextSibling):n.appendChild(o)}function o(){!function(){if(document.getElementById("gpc-guild-search-style"))return;const t=document.createElement("style");t.id="gpc-guild-search-style",t.textContent=`\n            #${e} {\n                width: 40px;\n                height: 40px;\n                border-radius: 9999px;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n                cursor: pointer;\n                user-select: none;\n                background: var(--color-white, #fff);\n                color: var(--color-gray-700, #374151);\n                border: none;\n                box-shadow: 0 1px 3px rgba(0,0,0,0.16);\n                font-size: 18px;\n                line-height: 1;\n                transition: background 0.15s;\n            }\n            #${e}:hover {\n                background: var(--color-gray-100, #f3f4f6);\n            }\n            .dark #${e} {\n                background: var(--color-gray-700, #374151);\n                color: var(--color-gray-200, #e5e7eb);\n            }\n            .dark #${e}:hover {\n                background: var(--color-gray-600, #4b5563);\n            }\n        `,document.head.appendChild(t)}();const t=document.getElementById("guildMenuBtn");if(t)return void n(t.parentElement);const o=new MutationObserver(()=>{const e=document.getElementById("guildMenuBtn");e&&(o.disconnect(),n(e.parentElement))});o.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>o.disconnect(),3e4)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",o):o()}(),_featureStatus.extGuildSearch="ok",console.log("[GeoPixelcons++] ✅ Guild Search button loaded")}catch(j){_featureStatus.extGuildSearch="error",dbgPush(`Guild Search init failed: ${j&&j.message?j.message:String(j)}`,{error:j,uiComponent:"Guild Search"}),console.error("[GeoPixelcons++] ❌ Guild Search button failed:",j)}if(_settings.extLogOutButton)try{!function(){const e="gpc-logout-btn";function t(){const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;if("function"==typeof e.logOut)return void e.logOut();const t=document.createElement("script");t.textContent='if(typeof logOut==="function")logOut();',document.head.appendChild(t),t.remove()}function n(){const e=document.getElementById("g_id_signin");return!(!e||!e.classList.contains("hidden"))}function o(o){if(document.getElementById(e))return;const r=document.createElement("button");r.id=e,r.type="button",r.title="Log Out",r.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>',r.style.display=n()?"":"none",r.addEventListener("click",t),o.appendChild(r),function(e){const t=document.getElementById("g_id_signin");if(t)return void new MutationObserver(()=>{e.style.display=n()?"":"none"}).observe(t,{attributes:!0,attributeFilter:["class"]});const o=new MutationObserver(()=>{const t=document.getElementById("g_id_signin");t&&(o.disconnect(),e.style.display=n()?"":"none",new MutationObserver(()=>{e.style.display=n()?"":"none"}).observe(t,{attributes:!0,attributeFilter:["class"]}))});o.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>o.disconnect(),3e4)}(r)}function r(){!function(){if(document.getElementById("gpc-logout-style"))return;const t=document.createElement("style");t.id="gpc-logout-style",t.textContent=`\n            #${e} {\n                width: 40px;\n                height: 40px;\n                border-radius: 9999px;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n                cursor: pointer;\n                user-select: none;\n                border: 1px solid var(--color-red-300, #fca5a5);\n                background: var(--color-red-50, #fff1f2);\n                color: var(--color-red-600, #dc2626);\n                box-shadow: 0 1px 3px rgba(0,0,0,0.16);\n                font-size: 18px;\n                line-height: 1;\n                transition: background 0.15s, border-color 0.15s, transform 0.12s;\n            }\n            #${e}:hover {\n                background: var(--color-red-100, #ffe4e6);\n            }\n            #${e}:active {\n                transform: scale(0.94);\n            }\n        `,document.head.appendChild(t)}();const t=document.getElementById("controls-right");if(t)return void o(t);const n=new MutationObserver(()=>{const e=document.getElementById("controls-right");e&&(n.disconnect(),o(e))});n.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>n.disconnect(),15e3)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",r):r()}(),_featureStatus.extLogOutButton="ok",console.log("[GeoPixelcons++] ✅ Log Out Button loaded")}catch(H){_featureStatus.extLogOutButton="error",dbgPush(`Log Out Button init failed: ${H&&H.message?H.message:String(H)}`,{error:H,uiComponent:"Log Out Button"}),console.error("[GeoPixelcons++] ❌ Log Out Button failed:",H)}if(_settings.themeEditor)try{!function(){const e="geoThemeEditor_themes",t="geoThemeEditor_active",n="https://geopixels.net",o="geoThemeEditor_minorRoadsHidden_v1",r="geoThemeEditor_themeFeedback_v2",a={dark:["highway_path::line-color","highway_minor::line-color","highway_name_other::text-color","highway_name_other::text-halo-color"],light:["road_path_pedestrian::line-color","road_minor::line-color","highway-name-minor::text-color"]},i={default_light:{base:"light",name:"Default",overrides:{}},default_dark:{base:"dark",name:"Default Dark",overrides:{}},fjord:{base:"dark",name:"Fjord",overrides:{"background::background-color":"#45516E","water::fill-color":"#38435C","waterway::line-color":"#2f3436","water_name::text-color":"#90a3b7","water_name::text-halo-color":"#45516E","landcover_ice_shelf::fill-color":"#2f3647","landcover_glacier::fill-color":"#2f3647","landcover_wood::fill-color":"#3a3d46","landuse_park::fill-color":"#394854","landuse_residential::fill-color":"#3a3e47","building::fill-color":"#1c232f","building::fill-outline-color":"#2d3440","aeroway-area::fill-color":"#374455","aeroway-taxiway::line-color":"#527386","road_area_pier::fill-color":"#45516E","road_pier::line-color":"#45516E","highway_path::line-color":"#485866","highway_minor::line-color":"#6b7f8f","highway_major_inner::line-color":"#8fa0b0","highway_major_casing::line-color":"#5a6b7d","highway_major_subtle::line-color":"#4a5b6d","highway_motorway_inner::line-color":"#a0b0c0","highway_motorway_casing::line-color":"#6a7b8d","highway_motorway_subtle::line-color":"#5a6b7d","railway::line-color":"#5a6b7d","railway_dashline::line-color":"#3a4b5d","railway_transit::line-color":"#5a6b7d","railway_transit_dashline::line-color":"#3a4b5d","boundary_state::line-color":"#7a8b9d","boundary_country_z0-4::line-color":"#8a9baf","boundary_country_z5-::line-color":"#8a9baf","highway_name_other::text-color":"#b0c0d0","highway_name_other::text-halo-color":"#1a2a3a","highway_name_motorway::text-color":"#c0d0e0","place_other::text-color":"#a0b0c0","place_other::text-halo-color":"#1a2a3a","place_village::text-color":"#a0b0c0","place_village::text-halo-color":"#1a2a3a","place_town::text-color":"#b0c0d0","place_town::text-halo-color":"#1a2a3a","place_city::text-color":"#c0d0e0","place_city::text-halo-color":"#1a2a3a","place_city_large::text-color":"#d0e0f0","place_city_large::text-halo-color":"#1a2a3a","place_state::text-color":"#a0b0c0","place_state::text-halo-color":"#1a2a3a","place_country_major::text-color":"#c0d0e0","place_country_major::text-halo-color":"#1a2a3a","place_country_minor::text-color":"#a0b0c0","place_country_minor::text-halo-color":"#1a2a3a","place_country_other::text-color":"#909fa0","place_country_other::text-halo-color":"#1a2a3a"}},debug_black:{base:"dark",name:"Debug Black",overrides:{"background::background-color":"#000000","water::fill-color":"#000000","waterway::line-color":"#000000","water_name::text-color":"#000000","water_name::text-halo-color":"#000000","landcover_ice_shelf::fill-color":"#000000","landcover_glacier::fill-color":"#000000","landcover_wood::fill-color":"#000000","landuse_park::fill-color":"#000000","landuse_residential::fill-color":"#000000","building::fill-color":"#000000","building::fill-outline-color":"#000000","aeroway-area::fill-color":"#000000","aeroway-taxiway::line-color":"#000000","road_area_pier::fill-color":"#000000","road_pier::line-color":"#000000","highway_path::line-color":"#000000","highway_minor::line-color":"#000000","highway_major_inner::line-color":"#000000","highway_major_casing::line-color":"#000000","highway_major_subtle::line-color":"#000000","highway_motorway_inner::line-color":"#000000","highway_motorway_casing::line-color":"#000000","highway_motorway_subtle::line-color":"#000000","railway::line-color":"#000000","railway_dashline::line-color":"#000000","railway_transit::line-color":"#000000","railway_transit_dashline::line-color":"#000000","boundary_state::line-color":"#000000","boundary_country_z0-4::line-color":"#000000","boundary_country_z5-::line-color":"#000000","highway_name_other::text-color":"#000000","highway_name_other::text-halo-color":"#000000","highway_name_motorway::text-color":"#000000","place_other::text-color":"#000000","place_other::text-halo-color":"#000000","place_village::text-color":"#000000","place_village::text-halo-color":"#000000","place_town::text-color":"#000000","place_town::text-halo-color":"#000000","place_city::text-color":"#000000","place_city::text-halo-color":"#000000","place_city_large::text-color":"#000000","place_city_large::text-halo-color":"#000000","place_state::text-color":"#000000","place_state::text-halo-color":"#000000","place_country_major::text-color":"#000000","place_country_major::text-halo-color":"#000000","place_country_minor::text-color":"#000000","place_country_minor::text-halo-color":"#000000","place_country_other::text-color":"#000000","place_country_other::text-halo-color":"#000000"}},debug_white:{base:"light",name:"Debug White",overrides:{"background::background-color":"#ffffff","water::fill-color":"#ffffff","waterway_river::line-color":"#ffffff","waterway_other::line-color":"#ffffff","water_name_point_label::text-color":"#ffffff","water_name_point_label::text-halo-color":"#ffffff","water_name_line_label::text-color":"#ffffff","water_name_line_label::text-halo-color":"#ffffff","landcover_ice::fill-color":"#ffffff","landcover_wood::fill-color":"#ffffff","park::fill-color":"#ffffff","landuse_residential::fill-color":"#ffffff","building::fill-color":"#ffffff","aeroway_fill::fill-color":"#ffffff","road_path_pedestrian::line-color":"#ffffff","road_minor::line-color":"#ffffff","road_secondary_tertiary::line-color":"#ffffff","road_trunk_primary::line-color":"#ffffff","road_trunk_primary_casing::line-color":"#ffffff","road_motorway::line-color":"#ffffff","road_motorway_casing::line-color":"#ffffff","road_motorway_link::line-color":"#ffffff","road_major_rail::line-color":"#ffffff","road_major_rail_hatching::line-color":"#ffffff","road_transit_rail::line-color":"#ffffff","road_transit_rail_hatching::line-color":"#ffffff","boundary_3::line-color":"#ffffff","boundary_2::line-color":"#ffffff","boundary_disputed::line-color":"#ffffff","highway-name-minor::text-color":"#ffffff","highway-name-major::text-color":"#ffffff","label_other::text-color":"#ffffff","label_other::text-halo-color":"#ffffff","label_village::text-color":"#ffffff","label_village::text-halo-color":"#ffffff","label_town::text-color":"#ffffff","label_town::text-halo-color":"#ffffff","label_city::text-color":"#ffffff","label_city::text-halo-color":"#ffffff","label_city_capital::text-color":"#ffffff","label_city_capital::text-halo-color":"#ffffff","label_state::text-color":"#ffffff","label_state::text-halo-color":"#ffffff","label_country_1::text-color":"#ffffff","label_country_1::text-halo-color":"#ffffff","label_country_2::text-color":"#ffffff","label_country_2::text-halo-color":"#ffffff","label_country_3::text-color":"#ffffff","label_country_3::text-halo-color":"#ffffff"}},ayu_mirage:{base:"light",name:"Ayu Mirage",overrides:{"background::background-color":"#f3f4f6","park::fill-color":"#e6eec8","landuse_residential::fill-color":"hsla(35,57%,88%,0.49)","landcover_wood::fill-color":"#e6eec8","landcover_ice::fill-color":"rgba(224, 236, 236, 1)","waterway_river::line-color":"#dbe6f0","waterway_other::line-color":"#dbe6f0","water::fill-color":"#dbe6f0","building::fill-color":"#e6e1cf","building::fill-outline-color":"#f3f4f6","road_path_pedestrian::line-color":"#cfccc6","road_minor::line-color":"#cfccc6","road_secondary_tertiary::line-color":"#cfccc6","road_trunk_primary::line-color":"#ffae57","road_trunk_primary_casing::line-color":"#ffae57","road_motorway::line-color":"#ffae57","road_motorway_casing::line-color":"#ffae57","road_motorway_link::line-color":"#ffae57","road_major_rail::line-color":"#ffae57","road_major_rail_hatching::line-color":"#ffae57","road_transit_rail::line-color":"#cfccc6","road_transit_rail_hatching::line-color":"#cfccc6","boundary_3::line-color":"#5c6773","boundary_2::line-color":"#5c6773","boundary_disputed::line-color":"#5c6773","highway-name-minor::text-color":"#5c6773","highway-name-major::text-color":"#5c6773","label_other::text-color":"#5c6773","label_other::text-halo-color":"#f3f4f6","label_village::text-color":"#5c6773","label_village::text-halo-color":"#f3f4f6","label_town::text-color":"#5c6773","label_town::text-halo-color":"#f3f4f6","label_city::text-color":"#5c6773","label_city::text-halo-color":"#f3f4f6","label_city_capital::text-color":"#5c6773","label_city_capital::text-halo-color":"#f3f4f6","label_state::text-color":"#5c6773","label_state::text-halo-color":"#f3f4f6","label_country_1::text-color":"#5c6773","label_country_1::text-halo-color":"#f3f4f6","label_country_2::text-color":"#5c6773","label_country_2::text-halo-color":"#f3f4f6","label_country_3::text-color":"#5c6773","label_country_3::text-halo-color":"#f3f4f6"}},cute_pink:{base:"light",name:"Cute & Pink",overrides:{"background::background-color":"#fff0f5","park::fill-color":"#ffe6f2","landcover_wood::fill-color":"#ffe6f2","waterway_river::line-color":"#cceeff","waterway_other::line-color":"#cceeff","water::fill-color":"#cceeff","road_path_pedestrian::line-color":"#ffb3d9","road_minor::line-color":"#ffb3d9","road_secondary_tertiary::line-color":"#ffb3d9","road_trunk_primary::line-color":"#ffb3d9","road_trunk_primary_casing::line-color":"#ffb3d9","road_motorway::line-color":"#ffb3d9","road_motorway_casing::line-color":"#ffb3d9","road_motorway_link::line-color":"#ffb3d9","road_major_rail::line-color":"#ffb3d9","road_transit_rail::line-color":"#ffb3d9","building::fill-color":"#ffdaeb","building::fill-outline-color":"#fff0f5","boundary_3::line-color":"#993366","boundary_2::line-color":"#993366","boundary_disputed::line-color":"#993366","highway-name-minor::text-color":"#993366","highway-name-major::text-color":"#993366","label_other::text-color":"#993366","label_other::text-halo-color":"#fff0f5","label_village::text-color":"#993366","label_village::text-halo-color":"#fff0f5","label_town::text-color":"#993366","label_town::text-halo-color":"#fff0f5","label_city::text-color":"#993366","label_city::text-halo-color":"#fff0f5","label_city_capital::text-color":"#993366","label_city_capital::text-halo-color":"#fff0f5","label_state::text-color":"#993366","label_state::text-halo-color":"#fff0f5","label_country_1::text-color":"#993366","label_country_1::text-halo-color":"#fff0f5","label_country_2::text-color":"#993366","label_country_2::text-halo-color":"#fff0f5","label_country_3::text-color":"#993366","label_country_3::text-halo-color":"#fff0f5"}},discord_gold:{base:"dark",name:"Discord Gold",overrides:{"background::background-color":"#171717","water::fill-color":"#23272A","waterway::line-color":"hsl(232, 23%, 28%)","water_name::text-color":"hsl(38, 60%, 50%)","water_name::text-halo-color":"hsl(232, 5%, 19%)","landcover_ice_shelf::fill-color":"hsl(232, 33%, 34%)","landuse_residential::fill-color":"transparent","landcover_wood::fill-color":"hsla(232, 18%, 30%, 0.57)","landuse_park::fill-color":"hsl(204, 17%, 35%)","building::fill-color":"hsla(232, 47%, 18%, 0.65)","highway_path::line-color":"hsl(211, 29%, 38%)","highway_minor::line-color":"hsl(224, 22%, 45%)","highway_major_casing::line-color":"hsl(224, 22%, 45%)","highway_major_inner::line-color":"#36393F","highway_major_subtle::line-color":"#38393E","highway_motorway_casing::line-color":"hsl(224, 22%, 45%)","highway_motorway_inner::line-color":"hsl(224, 20%, 29%)","highway_motorway_subtle::line-color":"hsla(239, 45%, 69%, 0.2)","railway::line-color":"hsl(200, 10%, 18%)","railway_dashline::line-color":"hsl(224, 20%, 41%)","boundary_state::line-color":"hsla(195, 47%, 62%, 0.26)","boundary_country_z0-4::line-color":"hsl(214, 63%, 76%)","boundary_country_z5-::line-color":"hsl(214, 63%, 76%)","highway_name_other::text-color":"hsl(38, 70%, 60%)","highway_name_other::text-halo-color":"hsl(232, 9%, 23%)","highway_name_motorway::text-color":"hsl(38, 70%, 60%)","place_other::text-color":"hsl(38, 65%, 60%)","place_other::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_village::text-color":"hsl(38, 70%, 45%)","place_village::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_town::text-color":"hsl(38, 75%, 65%)","place_town::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_city::text-color":"hsl(38, 75%, 65%)","place_city::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_city_large::text-color":"hsl(38, 75%, 65%)","place_city_large::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_state::text-color":"rgb(113, 129, 144)","place_state::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_country_other::text-color":"rgb(153, 153, 153)","place_country_other::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_country_minor::text-color":"rgb(153, 153, 153)","place_country_minor::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_country_major::text-color":"rgb(153, 153, 153)","place_country_major::text-halo-color":"hsla(228, 60%, 21%, 0.7)"}},monokai:{base:"dark",name:"Monokai",overrides:{"background::background-color":"#000000","water::fill-color":"#2D2E28","waterway::line-color":"hsl(232, 23%, 28%)","water_name::text-color":"hsl(223, 21%, 52%)","water_name::text-halo-color":"hsl(232, 5%, 19%)","landcover_ice_shelf::fill-color":"hsl(70, 15%, 35%)","landuse_residential::fill-color":"transparent","landcover_wood::fill-color":"hsla(232, 18%, 30%, 0.57)","landuse_park::fill-color":"hsl(204, 17%, 35%)","building::fill-color":"hsla(232, 47%, 18%, 0.65)","highway_path::line-color":"hsl(211, 29%, 38%)","highway_minor::line-color":"hsl(70, 20%, 40%)","highway_major_casing::line-color":"hsl(70, 20%, 40%)","highway_major_inner::line-color":"#3A3E38","highway_major_subtle::line-color":"#273a2d","highway_motorway_casing::line-color":"hsl(70, 20%, 40%)","highway_motorway_inner::line-color":"hsl(70, 18%, 28%)","highway_motorway_subtle::line-color":"hsla(239, 45%, 69%, 0.2)","railway::line-color":"hsl(40, 20%, 18%)","railway_dashline::line-color":"hsl(224, 20%, 41%)","boundary_state::line-color":"hsla(195, 47%, 62%, 0.26)","boundary_country_z0-4::line-color":"hsl(214, 63%, 76%)","boundary_country_z5-::line-color":"hsl(214, 63%, 76%)","highway_name_other::text-color":"hsl(223, 31%, 61%)","highway_name_other::text-halo-color":"hsl(232, 9%, 23%)","place_other::text-color":"hsl(195, 37%, 73%)","place_other::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_village::text-color":"hsl(195, 41%, 49%)","place_village::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_town::text-color":"hsl(195, 25%, 76%)","place_town::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_city::text-color":"hsl(195, 25%, 76%)","place_city::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_city_large::text-color":"hsl(195, 25%, 76%)","place_city_large::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_state::text-color":"rgb(140, 130, 100)","place_state::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_country_other::text-color":"rgb(153, 153, 153)","place_country_other::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_country_minor::text-color":"rgb(153, 153, 153)","place_country_minor::text-halo-color":"hsla(228, 60%, 21%, 0.7)","place_country_major::text-color":"rgb(153, 153, 153)","place_country_major::text-halo-color":"hsla(228, 60%, 21%, 0.7)"}},obsidian:{base:"dark",name:"Obsidian",overrides:{"background::background-color":"#1c1c1c","water::fill-color":"#262626","waterway::line-color":"#262626","water_name::text-color":"#a0a0a0","water_name::text-halo-color":"#1c1c1c","landcover_ice_shelf::fill-color":"rgb(12,12,12)","landcover_glacier::fill-color":"hsl(0, 1%, 2%)","landuse_residential::fill-color":"hsl(0, 2%, 5%)","landcover_wood::fill-color":"#2a2a2a","landuse_park::fill-color":"#2a2a2a","building::fill-color":"#242424","building::fill-outline-color":"#1c1c1c","highway_path::line-color":"#3d3d3d","highway_minor::line-color":"#3d3d3d","highway_major_casing::line-color":"#555555","highway_major_inner::line-color":"#555555","highway_major_subtle::line-color":"#555555","highway_motorway_casing::line-color":"#555555","highway_motorway_inner::line-color":"#555555","highway_motorway_subtle::line-color":"#555555","railway::line-color":"rgb(35,35,35)","railway_dashline::line-color":"rgb(12,12,12)","boundary_state::line-color":"#a0a0a0","boundary_country_z0-4::line-color":"#a0a0a0","boundary_country_z5-::line-color":"#a0a0a0","highway_name_other::text-color":"#a0a0a0","highway_name_other::text-halo-color":"#1c1c1c","highway_name_motorway::text-color":"#a0a0a0","place_other::text-color":"#a0a0a0","place_other::text-halo-color":"#1c1c1c","place_village::text-color":"#a0a0a0","place_village::text-halo-color":"#1c1c1c","place_town::text-color":"#a0a0a0","place_town::text-halo-color":"#1c1c1c","place_city::text-color":"#a0a0a0","place_city::text-halo-color":"#1c1c1c","place_city_large::text-color":"#a0a0a0","place_city_large::text-halo-color":"#1c1c1c","place_state::text-color":"#a0a0a0","place_state::text-halo-color":"#1c1c1c","place_country_other::text-color":"#a0a0a0","place_country_other::text-halo-color":"#1c1c1c","place_country_minor::text-color":"#a0a0a0","place_country_minor::text-halo-color":"#1c1c1c","place_country_major::text-color":"#a0a0a0","place_country_major::text-halo-color":"#1c1c1c"}},vintage_sepia:{base:"light",name:"Vintage Sepia",overrides:{"background::background-color":"#f4e4bc","park::fill-color":"#c5d5a7","landcover_wood::fill-color":"#c5d5a7","waterway_river::line-color":"#d2c29d","waterway_other::line-color":"#d2c29d","water::fill-color":"#d2c29d","road_path_pedestrian::line-color":"#a89f91","road_minor::line-color":"#a89f91","road_secondary_tertiary::line-color":"#a89f91","road_trunk_primary::line-color":"#8f8170","road_trunk_primary_casing::line-color":"#8f8170","road_motorway::line-color":"#8f8170","road_motorway_casing::line-color":"#8f8170","road_motorway_link::line-color":"#8f8170","road_major_rail::line-color":"#8f8170","road_transit_rail::line-color":"#a89f91","building::fill-color":"#e8d5a8","building::fill-outline-color":"#f4e4bc","boundary_3::line-color":"#5b4a42","boundary_2::line-color":"#5b4a42","boundary_disputed::line-color":"#5b4a42","highway-name-minor::text-color":"#5b4a42","highway-name-major::text-color":"#5b4a42","label_other::text-color":"#5b4a42","label_other::text-halo-color":"#f4e4bc","label_village::text-color":"#5b4a42","label_village::text-halo-color":"#f4e4bc","label_town::text-color":"#5b4a42","label_town::text-halo-color":"#f4e4bc","label_city::text-color":"#5b4a42","label_city::text-halo-color":"#f4e4bc","label_city_capital::text-color":"#5b4a42","label_city_capital::text-halo-color":"#f4e4bc","label_state::text-color":"#5b4a42","label_state::text-halo-color":"#f4e4bc","label_country_1::text-color":"#5b4a42","label_country_1::text-halo-color":"#f4e4bc","label_country_2::text-color":"#5b4a42","label_country_2::text-halo-color":"#f4e4bc","label_country_3::text-color":"#5b4a42","label_country_3::text-halo-color":"#f4e4bc"}}},l={dark:[{group:"Base",layers:[{id:"background",prop:"background-color",label:"Background"}]},{group:"Water",layers:[{id:"water",prop:"fill-color",label:"Water Fill"},{id:"waterway",prop:"line-color",label:"Waterways"},{id:"water_name",prop:"text-color",label:"Water Labels"},{id:"water_name",prop:"text-halo-color",label:"Water Label Halo"}]},{group:"Land & Nature",layers:[{id:"landcover_ice_shelf",prop:"fill-color",label:"Ice Shelf"},{id:"landcover_glacier",prop:"fill-color",label:"Glaciers"},{id:"landcover_wood",prop:"fill-color",label:"Forests / Wood"},{id:"landuse_park",prop:"fill-color",label:"Parks"},{id:"landuse_residential",prop:"fill-color",label:"Residential"}]},{group:"Buildings & Areas",layers:[{id:"building",prop:"fill-color",label:"Building Fill"},{id:"building",prop:"fill-outline-color",label:"Building Outline"},{id:"aeroway-area",prop:"fill-color",label:"Airport Area"},{id:"road_area_pier",prop:"fill-color",label:"Pier Area"}]},{group:"Roads",layers:[{id:"highway_path",prop:"line-color",label:"Paths"},{id:"highway_minor",prop:"line-color",label:"Minor Roads"},{id:"highway_major_inner",prop:"line-color",label:"Major Roads"},{id:"highway_major_casing",prop:"line-color",label:"Major Road Casing"},{id:"highway_major_subtle",prop:"line-color",label:"Major Roads (Subtle)"},{id:"highway_motorway_inner",prop:"line-color",label:"Motorway"},{id:"highway_motorway_casing",prop:"line-color",label:"Motorway Casing"},{id:"highway_motorway_subtle",prop:"line-color",label:"Motorway (Subtle)"},{id:"road_pier",prop:"line-color",label:"Pier Roads"},{kind:"mult",label:"Road Width",mkey:"*::line-width-mult",def:1,min:.25,max:3,step:.05}]},{group:"Railways",layers:[{id:"railway",prop:"line-color",label:"Railways"},{id:"railway_dashline",prop:"line-color",label:"Railway Dashes"},{id:"railway_transit",prop:"line-color",label:"Transit Rail"},{id:"railway_transit_dashline",prop:"line-color",label:"Transit Dashes"}]},{group:"Boundaries",layers:[{id:"boundary_state",prop:"line-color",label:"State Borders"},{id:"boundary_country_z0-4",prop:"line-color",label:"Country Borders (Far)"},{id:"boundary_country_z5-",prop:"line-color",label:"Country Borders (Near)"}]},{group:"Labels",layers:[{id:"highway_name_other",prop:"text-color",label:"Road Labels"},{id:"highway_name_other",prop:"text-halo-color",label:"Road Label Halo"},{id:"highway_name_motorway",prop:"text-color",label:"Motorway Labels"},{id:"place_other",prop:"text-color",label:"Hamlet / Neighborhood"},{id:"place_other",prop:"text-halo-color",label:"Hamlet Halo"},{id:"place_village",prop:"text-color",label:"Villages"},{id:"place_village",prop:"text-halo-color",label:"Village Halo"},{id:"place_town",prop:"text-color",label:"Towns"},{id:"place_town",prop:"text-halo-color",label:"Town Halo"},{id:"place_city",prop:"text-color",label:"Cities"},{id:"place_city",prop:"text-halo-color",label:"City Halo"},{id:"place_city_large",prop:"text-color",label:"Major Cities"},{id:"place_city_large",prop:"text-halo-color",label:"Major City Halo"},{id:"place_state",prop:"text-color",label:"States"},{id:"place_state",prop:"text-halo-color",label:"State Halo"},{id:"place_country_major",prop:"text-color",label:"Countries (Major)"},{id:"place_country_major",prop:"text-halo-color",label:"Country Halo (Major)"},{id:"place_country_minor",prop:"text-color",label:"Countries (Minor)"},{id:"place_country_other",prop:"text-color",label:"Countries (Other)"}]}],light:[{group:"Base",layers:[{id:"background",prop:"background-color",label:"Background"}]},{group:"Water",layers:[{id:"water",prop:"fill-color",label:"Water Fill"},{id:"waterway_river",prop:"line-color",label:"Rivers"},{id:"waterway_other",prop:"line-color",label:"Other Waterways"},{id:"water_name_point_label",prop:"text-color",label:"Water Labels"},{id:"water_name_point_label",prop:"text-halo-color",label:"Water Label Halo"}]},{group:"Land & Nature",layers:[{id:"landcover_ice",prop:"fill-color",label:"Ice / Snow"},{id:"landcover_wood",prop:"fill-color",label:"Forests / Wood"},{id:"landcover_grass",prop:"fill-color",label:"Grass"},{id:"park",prop:"fill-color",label:"Parks"},{id:"landuse_residential",prop:"fill-color",label:"Residential"},{kind:"opacity",label:"Marsh / Wetland (tufts)",okey:"landcover_wetland::fill-opacity",def:.8}]},{group:"Buildings & Areas",layers:[{id:"building",prop:"fill-color",label:"Building Fill"},{id:"aeroway_fill",prop:"fill-color",label:"Airport Area"}]},{group:"Roads",layers:[{label:"Paths / Pedestrian",keys:["road_path_pedestrian::line-color","bridge_path_pedestrian::line-color","tunnel_path_pedestrian::line-color"]},{label:"Minor Roads",keys:["road_minor::line-color","bridge_street::line-color","tunnel_minor::line-color"]},{label:"Minor Casing",keys:["road_minor_casing::line-color","bridge_street_casing::line-color","tunnel_street_casing::line-color"]},{label:"Service / Track",keys:["road_service_track::line-color","bridge_service_track::line-color","tunnel_service_track::line-color"]},{label:"Service / Track Casing",keys:["road_service_track_casing::line-color","bridge_service_track_casing::line-color","tunnel_service_track_casing::line-color"]},{label:"Secondary / Tertiary",keys:["road_secondary_tertiary::line-color","bridge_secondary_tertiary::line-color","tunnel_secondary_tertiary::line-color"]},{label:"Secondary / Tertiary Casing",keys:["road_secondary_tertiary_casing::line-color","bridge_secondary_tertiary_casing::line-color","tunnel_secondary_tertiary_casing::line-color"]},{label:"Trunk / Primary",keys:["road_trunk_primary::line-color","bridge_trunk_primary::line-color","tunnel_trunk_primary::line-color"]},{label:"Trunk / Primary Casing",keys:["road_trunk_primary_casing::line-color","bridge_trunk_primary_casing::line-color","tunnel_trunk_primary_casing::line-color"]},{label:"Ramps / Links",keys:["road_link::line-color","bridge_link::line-color","tunnel_link::line-color"]},{label:"Ramps / Links Casing",keys:["road_link_casing::line-color","bridge_link_casing::line-color","tunnel_link_casing::line-color"]},{label:"Motorway",keys:["road_motorway::line-color","bridge_motorway::line-color","tunnel_motorway::line-color"]},{label:"Motorway Casing",keys:["road_motorway_casing::line-color","bridge_motorway_casing::line-color","tunnel_motorway_casing::line-color"]},{label:"Motorway Links",keys:["road_motorway_link::line-color","bridge_motorway_link::line-color","tunnel_motorway_link::line-color"]},{label:"Motorway Link Casing",keys:["road_motorway_link_casing::line-color","bridge_motorway_link_casing::line-color","tunnel_motorway_link_casing::line-color"]},{kind:"mult",label:"Road Width",mkey:"*::line-width-mult",def:1,min:.25,max:3,step:.05}]},{group:"Railways",layers:[{id:"road_major_rail",prop:"line-color",label:"Railways"},{id:"road_major_rail_hatching",prop:"line-color",label:"Railway Hatching"},{id:"road_transit_rail",prop:"line-color",label:"Transit Rail"},{id:"road_transit_rail_hatching",prop:"line-color",label:"Transit Hatching"}]},{group:"Boundaries",layers:[{id:"boundary_3",prop:"line-color",label:"State Borders"},{id:"boundary_2",prop:"line-color",label:"Country Borders"},{id:"boundary_disputed",prop:"line-color",label:"Disputed Borders"}]},{group:"Labels",layers:[{id:"highway-name-minor",prop:"text-color",label:"Road Labels"},{id:"highway-name-major",prop:"text-color",label:"Major Road Labels"},{id:"label_other",prop:"text-color",label:"Hamlet / Neighborhood"},{id:"label_other",prop:"text-halo-color",label:"Hamlet Halo"},{id:"label_village",prop:"text-color",label:"Villages"},{id:"label_village",prop:"text-halo-color",label:"Village Halo"},{id:"label_town",prop:"text-color",label:"Towns"},{id:"label_town",prop:"text-halo-color",label:"Town Halo"},{id:"label_city",prop:"text-color",label:"Cities"},{id:"label_city",prop:"text-halo-color",label:"City Halo"},{id:"label_city_capital",prop:"text-color",label:"Capital Cities"},{id:"label_city_capital",prop:"text-halo-color",label:"Capital City Halo"},{id:"label_state",prop:"text-color",label:"States"},{id:"label_state",prop:"text-halo-color",label:"State Halo"},{id:"label_country_1",prop:"text-color",label:"Countries (Major)"},{id:"label_country_1",prop:"text-halo-color",label:"Country Halo (Major)"},{id:"label_country_2",prop:"text-color",label:"Countries (Minor)"},{id:"label_country_3",prop:"text-color",label:"Countries (Other)"}]}]},s={dark:[{group:"Base",layers:[{label:"Background",keys:["background::background-color"]}]},{group:"Water",layers:[{label:"Water",keys:["water::fill-color","waterway::line-color"]},{label:"Water Labels",keys:["water_name::text-color"]},{label:"Water Label Halo",keys:["water_name::text-halo-color"]}]},{group:"Land & Nature",layers:[{label:"Nature / Parks",keys:["landcover_wood::fill-color","landuse_park::fill-color","landcover_ice_shelf::fill-color","landcover_glacier::fill-color"]},{label:"Residential",keys:["landuse_residential::fill-color"]}]},{group:"Buildings & Areas",layers:[{label:"Buildings",keys:["building::fill-color","building::fill-outline-color"]},{label:"Airports / Piers",keys:["aeroway-area::fill-color","road_area_pier::fill-color"]}]},{group:"Roads",layers:[{label:"Minor Roads",keys:["highway_path::line-color","highway_minor::line-color","road_pier::line-color"]},{label:"Major Roads",keys:["highway_major_inner::line-color","highway_major_casing::line-color","highway_major_subtle::line-color"]},{label:"Motorways",keys:["highway_motorway_inner::line-color","highway_motorway_casing::line-color","highway_motorway_subtle::line-color"]},{kind:"mult",label:"Road Width",mkey:"*::line-width-mult",def:1,min:.25,max:3,step:.05}]},{group:"Railways",layers:[{label:"All Railways",keys:["railway::line-color","railway_dashline::line-color","railway_transit::line-color","railway_transit_dashline::line-color"]}]},{group:"Boundaries",layers:[{label:"All Borders",keys:["boundary_state::line-color","boundary_country_z0-4::line-color","boundary_country_z5-::line-color"]}]},{group:"Labels",layers:[{label:"Road Labels",keys:["highway_name_other::text-color","highway_name_motorway::text-color"]},{label:"Road Label Halo",keys:["highway_name_other::text-halo-color"]},{label:"Place Labels",keys:["place_other::text-color","place_village::text-color","place_town::text-color","place_city::text-color","place_city_large::text-color","place_state::text-color","place_country_major::text-color","place_country_minor::text-color","place_country_other::text-color"]},{label:"Place Label Halo",keys:["place_other::text-halo-color","place_village::text-halo-color","place_town::text-halo-color","place_city::text-halo-color","place_city_large::text-halo-color","place_state::text-halo-color","place_country_major::text-halo-color"]}]}],light:[{group:"Base",layers:[{label:"Background",keys:["background::background-color"]}]},{group:"Water",layers:[{label:"Water",keys:["water::fill-color","waterway_river::line-color","waterway_other::line-color"]},{label:"Water Labels",keys:["water_name_point_label::text-color","water_name_line_label::text-color"]},{label:"Water Label Halo",keys:["water_name_point_label::text-halo-color","water_name_line_label::text-halo-color"]}]},{group:"Land & Nature",layers:[{label:"Nature / Parks",keys:["landcover_wood::fill-color","landcover_grass::fill-color","park::fill-color","landcover_ice::fill-color"]},{label:"Residential",keys:["landuse_residential::fill-color"]},{kind:"opacity",label:"Marsh / Wetland (tufts)",okey:"landcover_wetland::fill-opacity",def:.8}]},{group:"Buildings & Areas",layers:[{label:"Buildings",keys:["building::fill-color"]},{label:"Airports",keys:["aeroway_fill::fill-color"]}]},{group:"Roads",layers:[{label:"Minor Roads",keys:["road_path_pedestrian::line-color","bridge_path_pedestrian::line-color","tunnel_path_pedestrian::line-color","bridge_path_pedestrian_casing::line-color","road_minor::line-color","bridge_street::line-color","tunnel_minor::line-color","road_minor_casing::line-color","bridge_street_casing::line-color","tunnel_street_casing::line-color","road_service_track::line-color","bridge_service_track::line-color","tunnel_service_track::line-color","road_service_track_casing::line-color","bridge_service_track_casing::line-color","tunnel_service_track_casing::line-color","road_link::line-color","bridge_link::line-color","tunnel_link::line-color","road_link_casing::line-color","bridge_link_casing::line-color","tunnel_link_casing::line-color"]},{label:"Major Roads",keys:["road_secondary_tertiary::line-color","bridge_secondary_tertiary::line-color","tunnel_secondary_tertiary::line-color","road_secondary_tertiary_casing::line-color","bridge_secondary_tertiary_casing::line-color","tunnel_secondary_tertiary_casing::line-color","road_trunk_primary::line-color","bridge_trunk_primary::line-color","tunnel_trunk_primary::line-color","road_trunk_primary_casing::line-color","bridge_trunk_primary_casing::line-color","tunnel_trunk_primary_casing::line-color"]},{label:"Motorways",keys:["road_motorway::line-color","bridge_motorway::line-color","tunnel_motorway::line-color","road_motorway_casing::line-color","bridge_motorway_casing::line-color","tunnel_motorway_casing::line-color","road_motorway_link::line-color","bridge_motorway_link::line-color","tunnel_motorway_link::line-color","road_motorway_link_casing::line-color","bridge_motorway_link_casing::line-color","tunnel_motorway_link_casing::line-color"]},{kind:"mult",label:"Road Width",mkey:"*::line-width-mult",def:1,min:.25,max:3,step:.05}]},{group:"Railways",layers:[{label:"All Railways",keys:["road_major_rail::line-color","road_major_rail_hatching::line-color","road_transit_rail::line-color","road_transit_rail_hatching::line-color"]}]},{group:"Boundaries",layers:[{label:"All Borders",keys:["boundary_3::line-color","boundary_2::line-color","boundary_disputed::line-color"]}]},{group:"Labels",layers:[{label:"Road Labels",keys:["highway-name-minor::text-color","highway-name-major::text-color"]},{label:"Place Labels",keys:["label_other::text-color","label_village::text-color","label_town::text-color","label_city::text-color","label_city_capital::text-color","label_state::text-color","label_country_1::text-color","label_country_2::text-color","label_country_3::text-color"]},{label:"Place Label Halo",keys:["label_other::text-halo-color","label_village::text-halo-color","label_town::text-halo-color","label_city::text-halo-color","label_city_capital::text-halo-color","label_state::text-halo-color","label_country_1::text-halo-color"]}]}]},c={dark:{"background::background-color":"#0c0c0c","water::fill-color":"#1b1b1d","waterway::line-color":"#1b1b1d","water_name::text-color":"#000000","water_name::text-halo-color":"#454545","landcover_ice_shelf::fill-color":"#0c0c0c","landcover_glacier::fill-color":"#050505","landcover_wood::fill-color":"#202020","landuse_park::fill-color":"#202020","landuse_residential::fill-color":"#0d0d0d","building::fill-color":"#0a0a0a","building::fill-outline-color":"#1b1b1d","aeroway-area::fill-color":"#000000","road_area_pier::fill-color":"#0c0c0c","road_pier::line-color":"#0c0c0c","highway_path::line-color":"#1b1b1d","highway_minor::line-color":"#181818","highway_major_inner::line-color":"#121212","highway_major_casing::line-color":"#3c3c3c","highway_major_subtle::line-color":"#2a2a2a","highway_motorway_inner::line-color":"#000000","highway_motorway_casing::line-color":"#3c3c3c","highway_motorway_subtle::line-color":"#181818","railway::line-color":"#232323","railway_dashline::line-color":"#0c0c0c","railway_transit::line-color":"#232323","railway_transit_dashline::line-color":"#0c0c0c","boundary_state::line-color":"#363636","boundary_country_z0-4::line-color":"#3b3b3b","boundary_country_z5-::line-color":"#3b3b3b","highway_name_other::text-color":"#504e4e","highway_name_other::text-halo-color":"#000000","highway_name_motorway::text-color":"#5e5e5e","place_other::text-color":"#656565","place_other::text-halo-color":"#000000","place_village::text-color":"#656565","place_village::text-halo-color":"#000000","place_town::text-color":"#656565","place_town::text-halo-color":"#000000","place_city::text-color":"#656565","place_city::text-halo-color":"#000000","place_city_large::text-color":"#656565","place_city_large::text-halo-color":"#000000","place_state::text-color":"#656565","place_state::text-halo-color":"#000000","place_country_other::text-color":"#656565","place_country_other::text-halo-color":"#000000","place_country_minor::text-color":"#656565","place_country_minor::text-halo-color":"#000000","place_country_major::text-color":"#656565","place_country_major::text-halo-color":"#000000"},light:{"background::background-color":"#f8f4f0","water::fill-color":"#9ebdff","waterway_river::line-color":"#a0c8f0","waterway_other::line-color":"#a0c8f0","water_name_point_label::text-color":"#495e91","water_name_point_label::text-halo-color":"#ffffff","water_name_line_label::text-color":"#495e91","water_name_line_label::text-halo-color":"#ffffff","landcover_ice::fill-color":"#e0ecec","landcover_wood::fill-color":"#a4d898","landcover_grass::fill-color":"#b0d59a","park::fill-color":"#d8e8c8","landuse_residential::fill-color":"#e8dece","building::fill-color":"#d4cfc9","aeroway_fill::fill-color":"#e5e4e0","road_path_pedestrian::line-color":"#ffffff","road_minor::line-color":"#ffffff","road_secondary_tertiary::line-color":"#ffeeaa","road_trunk_primary::line-color":"#ffeeaa","road_trunk_primary_casing::line-color":"#e9ac77","road_motorway::line-color":"#ffcc88","road_motorway_casing::line-color":"#e9ac77","road_motorway_link::line-color":"#ffcc88","road_minor_casing::line-color":"#cfcdca","road_service_track::line-color":"#ffffff","road_service_track_casing::line-color":"#cfcdca","road_secondary_tertiary_casing::line-color":"#e9ac77","road_link::line-color":"#ffeeaa","road_link_casing::line-color":"#e9ac77","road_motorway_link_casing::line-color":"#e9ac77","road_major_rail::line-color":"#bbbbbb","road_major_rail_hatching::line-color":"#bbbbbb","road_transit_rail::line-color":"#bbbbbb","road_transit_rail_hatching::line-color":"#bbbbbb","boundary_3::line-color":"#b3b3b3","boundary_2::line-color":"#696969","boundary_disputed::line-color":"#696969","highway-name-minor::text-color":"#666666","highway-name-major::text-color":"#666666","label_other::text-color":"#333333","label_other::text-halo-color":"#ffffff","label_village::text-color":"#000000","label_village::text-halo-color":"#ffffff","label_town::text-color":"#000000","label_town::text-halo-color":"#ffffff","label_city::text-color":"#000000","label_city::text-halo-color":"#ffffff","label_city_capital::text-color":"#000000","label_city_capital::text-halo-color":"#ffffff","label_state::text-color":"#333333","label_state::text-halo-color":"#ffffff","label_country_1::text-color":"#000000","label_country_1::text-halo-color":"#ffffff","label_country_2::text-color":"#000000","label_country_2::text-halo-color":"#ffffff","label_country_3::text-color":"#000000","label_country_3::text-halo-color":"#ffffff"}};function d(e){return l[e]||l.dark}function p(e,t){return(c[t]||c.dark)[e]||"#808080"}function g(){let t={};try{t=JSON.parse(localStorage.getItem(e))||{}}catch{}for(const[e,n]of Object.entries(i)){const e=n.name;t[e]&&t[e].bundled||(t[e]={overrides:{...n.overrides},base:n.base,bundled:!0,createdAt:t[e]?.createdAt||Date.now(),updatedAt:Date.now()}),"Debug White"!==e||t[e].overrides["*::all-color"]||(t[e].overrides["*::all-color"]="#ffffff"),"Debug Black"!==e||t[e].overrides["*::all-color"]||(t[e].overrides["*::all-color"]="#000000")}if(!localStorage.getItem(o)){for(const e of Object.values(i)){const n=t[e.name];if(!n||!n.bundled||"Debug White"===e.name||"Debug Black"===e.name)continue;const o=a[n.base||"dark"]||[];for(const t of o){const o=n.overrides[t],r=e.overrides[t];null!=o&&o!==r||(n.overrides[t]="transparent")}n.updatedAt=Date.now()}localStorage.setItem(o,"1")}if(!localStorage.getItem(r)){const e=t["Discord Gold"];e?.bundled&&(e.overrides["background::background-color"]="#171717",e.overrides["landuse_residential::fill-color"]="transparent",e.updatedAt=Date.now());const n=t["Cute & Pink"];n?.bundled&&(n.overrides["landuse_residential::fill-color"]="transparent",n.updatedAt=Date.now());const o=t.Monokai;o?.bundled&&(o.overrides["background::background-color"]="#000000",o.overrides["landuse_residential::fill-color"]="transparent",o.overrides["highway_major_subtle::line-color"]="#273a2d",o.updatedAt=Date.now()),localStorage.setItem(r,"1")}return u(t),t}function u(t){localStorage.setItem(e,JSON.stringify(t))}function m(){return localStorage.getItem(t)||""}function h(e){localStorage.setItem(t,e)}function f(e){if(!e||"string"!=typeof e)return"#000000";if(/^#[0-9A-Fa-f]{6}$/.test(e))return e;if(/^#[0-9A-Fa-f]{3}$/.test(e)){const[,t,n,o]=e.match(/^#(.)(.)(.)$/);return"#"+t+t+n+n+o+o}const t=document.createElement("div");t.style.color=e,document.body.appendChild(t);const n=getComputedStyle(t).color;document.body.removeChild(t);const o=n.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);if(!o)return"#000000";const r=e=>parseInt(e,10).toString(16).padStart(2,"0");return"#"+r(o[1])+r(o[2])+r(o[3])}let b=null,y=null;async function x(e){let t=await fetch(n+e).then(e=>e.text());return t=t.replaceAll("http://localhost:5039",n),JSON.parse(t)}async function v(e){if("dark"===e){if(!y)try{y=await x("/styleDark")}catch{return null}return JSON.parse(JSON.stringify(y))}if(!b)try{b=await x("/style")}catch{return null}return JSON.parse(JSON.stringify(b))}function w(e,t){return null!=e&&t>0?"number"==typeof e?e*t:Array.isArray(e)?["*",e,t]:"object"==typeof e&&Array.isArray(e.stops)?Object.assign({},e,{stops:e.stops.map(e=>[e[0],"number"==typeof e[1]?e[1]*t:e[1]])}):e:e}function k(e,t){const n=JSON.parse(JSON.stringify(e)),o=t["*::all-color"],r=parseFloat(t["*::line-width-mult"]),a=!isNaN(r)&&r>0&&1!==r;for(const e of n.layers){o&&e.paint&&(null!=e.paint["background-color"]&&(e.paint["background-color"]=o),null!=e.paint["fill-color"]&&(e.paint["fill-color"]=o),null!=e.paint["fill-outline-color"]&&(e.paint["fill-outline-color"]=o),null!=e.paint["line-color"]&&(e.paint["line-color"]=o),null!=e.paint["text-color"]&&(e.paint["text-color"]=o),null!=e.paint["text-halo-color"]&&(e.paint["text-halo-color"]=o),"raster"===e.type&&null!=e.paint["raster-opacity"]&&(e.paint["raster-opacity"]=0),"symbol"===e.type&&(e.paint["icon-opacity"]=0));const n=n=>{const o=e.id+"::"+n;t[o]&&(e.paint||(e.paint={}),e.paint[n]=t[o])},i=n=>{const o=e.id+"::"+n,r=t[o];if(null!=r&&""!==r){const t=parseFloat(r);isNaN(t)||(e.paint||(e.paint={}),e.paint[n]=t)}};"background"===e.type&&n("background-color"),"fill"===e.type&&(n("fill-color"),n("fill-outline-color"),i("fill-opacity")),"line"===e.type&&(n("line-color"),a&&"transportation"===e["source-layer"]&&e.paint&&null!=e.paint["line-width"]&&(e.paint["line-width"]=w(e.paint["line-width"],r))),"symbol"===e.type&&(n("text-color"),n("text-halo-color"))}return n}function E(){try{const e=(0,eval)("map");if(e&&"function"==typeof e.setStyle)return e}catch{}if("undefined"!=typeof unsafeWindow)try{const e=unsafeWindow.eval("map");if(e&&"function"==typeof e.setStyle)return e}catch{}return null}function C(){if("undefined"!=typeof unsafeWindow&&unsafeWindow.userConfig)return unsafeWindow.userConfig;if(window.userConfig)return window.userConfig;try{return JSON.parse(localStorage.getItem("userConfig"))}catch{return null}}function S(e){if(!e?.layers)return"dark";const t=new Set(e.layers.map(e=>e.id));return t.has("road_minor")||t.has("highway-name-minor")||t.has("boundary_3")?"light":"dark"}function T(e){const t="styleCustom = "+JSON.stringify(e).replace(/</g,"\\u003c");try{if(window.wrappedJSObject?.eval)return window.wrappedJSObject.eval(t),!0}catch{}try{const e=document.createElement("script");return e.textContent="(function(){try{"+t+"}catch(e){}})();",(document.head||document.documentElement).appendChild(e),e.remove(),!0}catch{}try{return(0,eval)(t),!0}catch{}return!1}function P(){try{(0,eval)('try{if(typeof drawCachedTilesOnMap==="function")drawCachedTilesOnMap()}catch(e){};try{if(typeof synchronize==="function")synchronize("partial")}catch(e){};try{if(typeof refresh==="function")refresh()}catch(e){}')}catch{}}function L(e,t){localStorage.setItem("customTheme",JSON.stringify(e));const n=C()||{};n.theme="custom",localStorage.setItem("userConfig",JSON.stringify(n));const o=E();if(!o)return void I("Map not found — please wait for the page to load.",!0);const r=o.getStyle?o.getStyle():null,a=S(r),i=t||S(e);if(r&&a===i)return function(e,t){const n=e.getStyle();if(!n?.layers)return!1;const o=new Set(n.layers.map(e=>e.id)),r=new Set(["background-color","fill-color","fill-outline-color","line-color","text-color","text-halo-color","icon-opacity","raster-opacity","fill-opacity","line-width"]);for(const n of t.layers||[])if(o.has(n.id)&&n.paint)for(const[t,o]of Object.entries(n.paint))if(r.has(t))try{e.setPaintProperty(n.id,t,o)}catch{}}(o,e),void T(e);const l=(t=0)=>{try{if(o.isStyleLoaded&&!o.isStyleLoaded()&&t<40)return setTimeout(()=>l(t+1),75);o.setStyle(e),T(e);const n=()=>{P(),setTimeout(P,120),setTimeout(P,450)};try{o.once("styledata",n)}catch{}try{o.once("idle",n)}catch{}}catch(n){if(t<40)return setTimeout(()=>l(t+1),75);const o=JSON.stringify(e).replace(/</g,"\\u003c");try{const e=document.createElement("script");e.textContent="(function(){try{styleCustom="+o+';applyTheme("custom")}catch(e){}})();',(document.head||document.documentElement).appendChild(e),e.remove(),P(),setTimeout(P,120),setTimeout(P,450)}catch{I("Failed to switch base style.",!0)}}};l()}function M(e){localStorage.setItem("customTheme",JSON.stringify(e));const t=C()||{};t.theme="custom",localStorage.setItem("userConfig",JSON.stringify(t))}function I(e,t){const n=document.getElementById("gte-toast");n&&n.remove();const o=document.createElement("div");o.id="gte-toast",o.textContent=e,Object.assign(o.style,{position:"fixed",bottom:"20px",left:"50%",transform:"translateX(-50%)",background:t?"#f38ba8":"#a6e3a1",color:"#1e1e2e",padding:"8px 18px",borderRadius:"8px",fontSize:"12px",fontWeight:"600",zIndex:"100001",boxShadow:"0 4px 12px rgba(0,0,0,.3)",transition:"opacity .3s",fontFamily:"'Segoe UI',system-ui,sans-serif"}),document.body.appendChild(o),setTimeout(()=>{o.style.opacity="0",setTimeout(()=>o.remove(),300)},2500)}function _(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function G(e){return e.replace(/"/g,"&quot;").replace(/'/g,"&#39;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}let R=null;let N={},A="",z="dark",B=!1,O=null,D=!0;function j(){B&&(clearTimeout(O),O=setTimeout(async()=>{const e=await v(z);e&&L(k(e,N),z)},120))}function H(e,t){const n=t.okey,o="number"==typeof t.def?t.def:1;let r=null!=N[n]&&""!==N[n]?parseFloat(N[n]):o;isNaN(r)&&(r=o);const a=Math.round(100*r),i=0===r,l=document.createElement("div");l.className="gte-color-row",l.innerHTML='<span class="gte-color-label">'+_(t.label)+'</span><div class="gte-color-input-wrap"><button type="button" class="gte-vis-btn '+(i?"gte-layer-hidden":"")+'" title="Toggle visibility">'+(i?"🚫":"👁️")+'</button><input type="range" class="gte-range" min="0" max="100" step="1" value="'+a+'"><span class="gte-hex-display'+(i?" gte-hidden-color":"")+'">'+(i?"hidden":a+"%")+'</span><button type="button" class="gte-reset-btn" title="Reset to default">↻</button></div>';const s=l.querySelector(".gte-range"),c=l.querySelector(".gte-hex-display"),d=l.querySelector(".gte-vis-btn"),p=l.querySelector(".gte-reset-btn"),g=e=>{const t=Math.round(100*e);s.value=t,0===e?(c.textContent="hidden",c.classList.add("gte-hidden-color"),d.textContent="🚫",d.classList.add("gte-layer-hidden")):(c.textContent=t+"%",c.classList.remove("gte-hidden-color"),d.textContent="👁️",d.classList.remove("gte-layer-hidden"))};s.addEventListener("input",e=>{const t=parseInt(e.target.value,10)/100;N[n]=t,g(t),j()}),d.addEventListener("click",()=>{const e=0===(null!=N[n]&&""!==N[n]?parseFloat(N[n]):o)?o:0;N[n]=e,g(e),j()}),p.addEventListener("click",()=>{delete N[n],g(o),j()}),e.appendChild(l)}function F(e,t){const n=t.mkey,o="number"==typeof t.def?t.def:1,r="number"==typeof t.min?t.min:.25,a="number"==typeof t.max?t.max:3,i="number"==typeof t.step?t.step:.05;let l=null!=N[n]&&""!==N[n]?parseFloat(N[n]):o;isNaN(l)&&(l=o);const s=document.createElement("div");s.className="gte-color-row",s.innerHTML='<span class="gte-color-label">'+_(t.label)+'</span><div class="gte-color-input-wrap"><input type="range" class="gte-range" min="'+r+'" max="'+a+'" step="'+i+'" value="'+l+'"><span class="gte-hex-display">'+l.toFixed(2)+'×</span><button type="button" class="gte-reset-btn" title="Reset to default">↻</button></div>';const c=s.querySelector(".gte-range"),d=s.querySelector(".gte-hex-display"),p=s.querySelector(".gte-reset-btn");c.addEventListener("input",e=>{const t=parseFloat(e.target.value);N[n]=t,d.textContent=t.toFixed(2)+"×",j()}),p.addEventListener("click",()=>{delete N[n],c.value=o,d.textContent=o.toFixed(2)+"×",j()}),e.appendChild(s)}function X(e,t,n){N=e||{},A=t||"",z=n||"dark";const o=document.getElementById("gte-panel-editor");o.innerHTML="";const r=document.createElement("div");r.className="gte-name-row",r.innerHTML='<input type="text" class="gte-name-input" id="gte-theme-name" placeholder="Theme name…" value="'+G(A)+'" maxlength="50"><select id="gte-base-select" class="gte-name-input" style="flex:0 0 auto;width:auto;padding:6px 8px;"><option value="dark" '+("dark"===z?"selected":"")+'>Dark base</option><option value="light" '+("light"===z?"selected":"")+">Light base</option></select>",r.querySelector("#gte-base-select").addEventListener("change",e=>{z=e.target.value,X(N,A,z),j()}),o.appendChild(r);const a=document.createElement("div");a.className="gte-preview-row",a.innerHTML='<input type="checkbox" id="gte-live-preview" '+(B?"checked":"")+'><label for="gte-live-preview">Live preview</label>',a.querySelector("#gte-live-preview").addEventListener("change",e=>{B=e.target.checked,B&&j()}),o.appendChild(a);const i=document.createElement("div");i.className="gte-mode-toggle",i.innerHTML='<span class="'+(D?"gte-mode-active":"")+'">Simple</span><button type="button" class="gte-mode-switch '+(D?"":"gte-on")+'" id="gte-mode-switch"></button><span class="'+(D?"":"gte-mode-active")+'">Full</span>',i.querySelector("#gte-mode-switch").addEventListener("click",()=>{D=!D,X(N,A,z)}),o.appendChild(i);const l=D?function(e){return s[e]||s.dark}(z):d(z);for(const e of l){const t=document.createElement("div");t.className="gte-group-header",t.textContent=e.group,o.appendChild(t);for(const t of e.layers){if("opacity"===t.kind){H(o,t);continue}if("mult"===t.kind){F(o,t);continue}const e=t.keys?t.keys:[t.id+"::"+t.prop],n=e[0],r=N[n]||p(n,z),a="transparent"===r,i=a?p(n,z):r,l=document.createElement("div");l.className="gte-color-row",l.innerHTML='<span class="gte-color-label">'+_(t.label)+'</span><div class="gte-color-input-wrap"><button type="button" class="gte-vis-btn '+(a?"gte-layer-hidden":"")+'" title="Toggle visibility">'+(a?"🚫":"👁️")+'</button><span class="gte-hex-display '+(a?"gte-hidden-color":"")+'">'+(a?"hidden":r)+'</span><input type="color" class="gte-color-input" value="'+i+'" '+(a?"disabled":"")+'><button type="button" class="gte-reset-btn" title="Reset to default">↻</button></div>';const s=l.querySelector(".gte-color-input"),c=l.querySelector(".gte-hex-display"),d=l.querySelector(".gte-vis-btn"),g=l.querySelector(".gte-reset-btn");s.addEventListener("input",t=>{for(const n of e)N[n]=t.target.value;c.textContent=t.target.value,j()}),d.addEventListener("click",()=>{if("transparent"===N[n]){const t=s.value;for(const n of e)N[n]=t;c.textContent=t,c.classList.remove("gte-hidden-color"),s.disabled=!1,d.textContent="👁️",d.classList.remove("gte-layer-hidden")}else{for(const t of e)N[t]="transparent";c.textContent="hidden",c.classList.add("gte-hidden-color"),s.disabled=!0,d.textContent="🚫",d.classList.add("gte-layer-hidden")}j()}),g.addEventListener("click",()=>{const t=p(n,z);for(const n of e)N[n]=t;s.value=t,c.textContent=t,c.classList.remove("gte-hidden-color"),s.disabled=!1,d.textContent="👁️",d.classList.remove("gte-layer-hidden"),j()}),o.appendChild(l)}}const c=document.createElement("div");c.className="gte-btn-row",c.innerHTML='<button class="gte-btn gte-btn-primary" id="gte-save-apply">Save &amp; Apply</button><button class="gte-btn gte-btn-secondary" id="gte-load-current">Load Current</button><button class="gte-btn gte-btn-secondary" id="gte-export-json">Export JSON</button><button class="gte-btn gte-btn-secondary" id="gte-import-json-btn">Import JSON</button><input type="file" id="gte-import-json-file" accept=".json" style="display:none">',o.appendChild(c),o.querySelector("#gte-save-apply").addEventListener("click",async()=>{const e=document.getElementById("gte-theme-name"),t=e.value.trim();if(!t)return e.style.borderColor="#f38ba8",e.focus(),void setTimeout(()=>e.style.borderColor="",1500);const n=g();n[t]={overrides:{...N},base:z,createdAt:n[t]?.createdAt||Date.now(),updatedAt:Date.now()},u(n),h(t),A=t;const o=await v(z);if(!o)return;const r=k(o,N);L(r,z),M(r),I('Theme "'+t+'" saved & applied!')}),o.querySelector("#gte-load-current").addEventListener("click",async()=>{const e=E();if(!e)return I("Map not ready.",!0);const t=e.getStyle();if(!t)return I("No style loaded.",!0);X(function(e,t){const n={},o=t=>{const o=t.indexOf("::");if(o<0)return;const r=t.slice(0,o),a=t.slice(o+2),i=e.layers.find(e=>e.id===r);if(null!=i?.paint?.[a]){let e=i.paint[a];"object"==typeof e&&!Array.isArray(e)&&e.stops&&(e=e.stops[e.stops.length-1][1]),"string"==typeof e&&(n[t]=f(e))}};for(const e of d(t||"dark"))for(const t of e.layers)t.kind||(t.keys?t.keys.forEach(o):o(t.id+"::"+t.prop));return n}(t,z),A,z),I("Loaded colors from current map.")}),o.querySelector("#gte-export-json").addEventListener("click",async()=>{const e=await v(z);if(!e)return;const t=k(e,N),n=document.getElementById("gte-theme-name").value.trim()||"custom_theme";t.name=n;const o=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),r=document.createElement("a");r.href=URL.createObjectURL(o),r.download=n.replace(/[^a-z0-9_-]/gi,"_")+".json",r.click(),URL.revokeObjectURL(r.href)}),o.querySelector("#gte-import-json-btn").addEventListener("click",()=>o.querySelector("#gte-import-json-file").click()),o.querySelector("#gte-import-json-file").addEventListener("change",async e=>{const t=e.target.files[0];if(t){try{const e=await t.text(),n=JSON.parse(e);if(!n.layers||!Array.isArray(n.layers))return I("Invalid theme JSON.",!0);const o=function(e){const t={background:["background-color"],fill:["fill-color","fill-outline-color"],line:["line-color"],symbol:["text-color","text-halo-color"]},n={};for(const o of e.layers){const e=t[o.type];if(e&&o.paint)for(const t of e){let e=o.paint[t];null!=e&&("object"==typeof e&&!Array.isArray(e)&&e.stops&&(e=e.stops[e.stops.length-1][1]),"string"==typeof e&&(n[o.id+"::"+t]=f(e)))}}return n}(n),r=n.name||t.name.replace(/\.json$/i,""),a=o["background::background-color"];X(o,r,a?function(e){const t=f(e).replace("#","");return parseInt(t.substring(0,2),16)/255*.299+parseInt(t.substring(2,4),16)/255*.587+parseInt(t.substring(4,6),16)/255*.114<.4}(a)?"dark":"light":"dark"),I('Imported "'+r+'" — adjust and Save & Apply.')}catch{I("Failed to parse JSON file.",!0)}e.target.value=""}})}function q(){const e=document.getElementById("gte-panel-manager"),t=g(),n=m(),o=Object.keys(t).sort((e,t)=>{const n="Default"===e?0:"Default Dark"===e?1:2,o="Default"===t?0:"Default Dark"===t?1:2;return n!==o?n-o:e.localeCompare(t)});let r="";if(0===o.length)r='<div class="gte-empty-msg">No saved themes yet.<br>Use the Editor tab to create one!</div>';else for(const e of o){const o=t[e],a=e===n,i=o.bundled,l="light"===(o.base||"dark");r+='<div class="gte-theme-card '+(a?"gte-active-theme":"")+'"><span class="gte-theme-card-name" title="'+G(e)+'"><span class="gte-theme-name-text">'+_(e)+(a?" ✓":"")+(i?" 📌":"")+'</span><span class="gte-theme-badge '+(l?"gte-theme-badge-light":"gte-theme-badge-dark")+'">'+(l?"Light":"Dark")+'</span></span><div class="gte-theme-card-actions"><button class="gte-btn gte-btn-primary gte-btn-sm" data-action="apply" data-name="'+G(e)+'">Apply</button><button class="gte-btn gte-btn-secondary gte-btn-sm" data-action="edit" data-name="'+G(e)+'">Edit</button>'+(i?'<span class="gte-btn gte-btn-danger gte-btn-sm" style="opacity:0.5;cursor:not-allowed;" title="Built-in">Delete</span>':'<button class="gte-btn gte-btn-danger gte-btn-sm" data-action="delete" data-name="'+G(e)+'">Delete</button>')+"</div></div>"}r+='<div class="gte-io-section"><button class="gte-btn gte-btn-secondary" id="gte-restore-default" style="width:100%">Restore Default Theme</button></div>',e.innerHTML=r,e.querySelectorAll("[data-action]").forEach(e=>e.addEventListener("click",async()=>{const t=e.dataset.action,n=e.dataset.name;"apply"===t&&await U(n),"edit"===t&&function(e){const t=g(),n=t[e];if(!n)return;R.querySelectorAll(".gte-tab").forEach(e=>e.classList.remove("gte-active")),R.querySelectorAll(".gte-panel").forEach(e=>e.classList.remove("gte-active")),R.querySelector('[data-panel="editor"]').classList.add("gte-active"),R.querySelector("#gte-panel-editor").classList.add("gte-active"),X(n.overrides,e,n.base||"dark")}(n),"delete"===t&&function(e){const t=g();if(t[e]?.bundled)return void I("Cannot delete built-in themes.",!0);if(!confirm('Delete theme "'+e+'"?'))return;delete t[e],u(t),m()===e&&h("");q(),I('Deleted "'+e+'".')}(n)}));const a=e.querySelector("#gte-restore-default");a&&a.addEventListener("click",async()=>{h(""),localStorage.removeItem("customTheme");const e=C();e&&(e.theme="default"),localStorage.setItem("userConfig",JSON.stringify(e));try{const e=await v("light");if(e){const t=E();t&&t.setStyle(e)}}catch{}q(),I("Restored default theme.")})}async function U(e){const t=g()[e];if(!t)return;const n=await v(t.base||"dark");if(!n)return;const o=k(n,t.overrides);L(o,t.base||"dark"),h(e),M(o),q(),I('Applied "'+e+'".')}!function(){if(document.getElementById("gte-style"))return;const e=document.createElement("style");e.id="gte-style",e.textContent="\n            #gte-modal { position:fixed; z-index:100000; background:#1e1e2e; color:#cdd6f4; border:1px solid #45475a; border-radius:12px; box-shadow:0 8px 32px rgba(0,0,0,.55); width:380px; max-height:80vh; display:flex; flex-direction:column; font-family:'Segoe UI',system-ui,sans-serif; font-size:13px; user-select:none; }\n            #gte-modal.gte-hidden { display:none; }\n            #gte-titlebar { display:flex; align-items:center; justify-content:space-between; padding:10px 14px; background:#181825; border-radius:12px 12px 0 0; cursor:grab; flex-shrink:0; }\n            #gte-titlebar:active { cursor:grabbing; }\n            #gte-titlebar h2 { margin:0; font-size:14px; font-weight:600; color:#cba6f7; }\n            #gte-close-btn { background:none; border:none; color:#6c7086; cursor:pointer; font-size:18px; line-height:1; padding:0 4px; }\n            #gte-close-btn:hover { color:#f38ba8; }\n            #gte-tabs { display:flex; border-bottom:1px solid #313244; flex-shrink:0; }\n            .gte-tab { flex:1; padding:8px 0; text-align:center; background:none; border:none; color:#6c7086; cursor:pointer; font-size:12px; font-weight:500; border-bottom:2px solid transparent; transition:color .15s,border-color .15s; }\n            .gte-tab:hover { color:#bac2de; }\n            .gte-tab.gte-active { color:#cba6f7; border-bottom-color:#cba6f7; }\n            #gte-body { overflow-y:auto; padding:12px 14px; flex:1; }\n            #gte-body::-webkit-scrollbar { width:6px; }\n            #gte-body::-webkit-scrollbar-thumb { background:#45475a; border-radius:3px; }\n            .gte-panel { display:none; }\n            .gte-panel.gte-active { display:block; }\n            .gte-group-header { font-size:11px; font-weight:700; text-transform:uppercase; color:#89b4fa; margin:12px 0 6px; letter-spacing:.5px; }\n            .gte-group-header:first-child { margin-top:0; }\n            .gte-color-row { display:flex; align-items:center; justify-content:space-between; padding:4px 0; }\n            .gte-color-label { font-size:12px; color:#a6adc8; }\n            .gte-color-input-wrap { display:flex; align-items:center; gap:6px; }\n            .gte-color-input { -webkit-appearance:none; appearance:none; width:32px; height:24px; border:1px solid #45475a; border-radius:4px; cursor:pointer; background:none; padding:0; }\n            .gte-color-input::-webkit-color-swatch-wrapper { padding:0; }\n            .gte-color-input::-webkit-color-swatch { border:none; border-radius:3px; }\n            .gte-hex-display { font-family:'Cascadia Code','Consolas',monospace; font-size:11px; color:#6c7086; width:62px; text-align:right; }\n            .gte-hex-display.gte-hidden-color { color:#f38ba8; font-style:italic; }\n            .gte-range { -webkit-appearance:none; appearance:none; width:80px; height:4px; border-radius:2px; background:#45475a; outline:none; cursor:pointer; accent-color:#cba6f7; padding:0; }\n            .gte-range::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:12px; height:12px; border-radius:50%; background:#cba6f7; cursor:pointer; border:none; }\n            .gte-range::-moz-range-thumb { width:12px; height:12px; border-radius:50%; background:#cba6f7; cursor:pointer; border:none; }\n            .gte-vis-btn { background:none; border:none; cursor:pointer; font-size:14px; padding:0 2px; line-height:1; opacity:0.6; transition:opacity .15s; }\n            .gte-vis-btn:hover { opacity:1; }\n            .gte-vis-btn.gte-layer-hidden { opacity:0.35; }\n            .gte-reset-btn { background:none; border:none; cursor:pointer; font-size:11px; padding:0 2px; line-height:1; opacity:0.5; transition:opacity .15s; color:#89b4fa; }\n            .gte-reset-btn:hover { opacity:1; }\n            .gte-name-row { display:flex; gap:8px; margin-bottom:12px; }\n            .gte-name-input { flex:1; padding:6px 10px; border-radius:6px; background:#313244; color:#cdd6f4; border:1px solid #45475a; font-size:13px; outline:none; }\n            .gte-name-input:focus { border-color:#cba6f7; }\n            .gte-name-input::placeholder { color:#585b70; }\n            .gte-preview-row { display:flex; align-items:center; gap:8px; margin-bottom:10px; padding:6px 8px; background:#313244; border-radius:6px; }\n            .gte-preview-row input[type=checkbox] { accent-color:#cba6f7; width:15px; height:15px; cursor:pointer; }\n            .gte-preview-row label { font-size:12px; color:#a6adc8; cursor:pointer; user-select:none; }\n            .gte-mode-toggle { display:flex; align-items:center; gap:8px; margin-bottom:10px; padding:6px 8px; background:#313244; border-radius:6px; }\n            .gte-mode-toggle span { font-size:12px; color:#a6adc8; }\n            .gte-mode-toggle span.gte-mode-active { color:#cba6f7; font-weight:600; }\n            .gte-mode-switch { position:relative; width:36px; height:18px; background:#585b70; border-radius:9px; cursor:pointer; transition:background .2s; border:none; padding:0; }\n            .gte-mode-switch.gte-on { background:#cba6f7; }\n            .gte-mode-switch::after { content:''; position:absolute; top:2px; left:2px; width:14px; height:14px; background:#fff; border-radius:50%; transition:transform .2s; }\n            .gte-mode-switch.gte-on::after { transform:translateX(18px); }\n            .gte-btn { padding:7px 14px; border:none; border-radius:6px; font-size:12px; font-weight:600; cursor:pointer; transition:filter .15s; }\n            .gte-btn:hover { filter:brightness(1.15); }\n            .gte-btn-primary { background:#cba6f7; color:#1e1e2e; }\n            .gte-btn-secondary { background:#45475a; color:#cdd6f4; }\n            .gte-btn-danger { background:#f38ba8; color:#1e1e2e; }\n            .gte-btn-sm { padding:4px 10px; font-size:11px; }\n            .gte-btn-row { display:flex; gap:8px; margin-top:12px; flex-wrap:wrap; }\n            .gte-theme-card { display:flex; align-items:center; justify-content:space-between; padding:8px 10px; margin-bottom:6px; background:#313244; border-radius:8px; border:1px solid transparent; transition:border-color .15s; }\n            .gte-theme-card.gte-active-theme { border-color:#a6e3a1; }\n            .gte-theme-card-name { display:flex; align-items:center; gap:6px; font-size:13px; font-weight:500; color:#cdd6f4; overflow:hidden; max-width:180px; }\n            .gte-theme-name-text { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n            .gte-theme-badge { font-size:10px; font-weight:700; letter-spacing:0.2px; text-transform:uppercase; border-radius:999px; padding:2px 6px; line-height:1; flex-shrink:0; border:1px solid transparent; }\n            .gte-theme-badge-light { color:#1e1e2e; background:#f9e2af; border-color:#eabf5d; }\n            .gte-theme-badge-dark { color:#cdd6f4; background:#313244; border-color:#585b70; }\n            .gte-theme-card-actions { display:flex; gap:4px; }\n            .gte-empty-msg { color:#585b70; font-size:12px; text-align:center; padding:20px 0; }\n            .gte-io-section { margin-top:14px; padding-top:12px; border-top:1px solid #313244; }\n        ",document.head.appendChild(e)}(),R=function(){const e=document.createElement("div");e.id="gte-modal",e.className="gte-hidden",e.innerHTML='<div id="gte-titlebar"><h2>🎨 Theme Editor</h2><button id="gte-close-btn">&times;</button></div><div id="gte-tabs"><button class="gte-tab gte-active" data-panel="editor">Editor</button><button class="gte-tab" data-panel="manager">My Themes</button></div><div id="gte-body"><div id="gte-panel-editor" class="gte-panel gte-active"></div><div id="gte-panel-manager" class="gte-panel"></div></div>',document.body.appendChild(e),e.style.top="60px",e.style.right="20px",e.querySelector("#gte-close-btn").addEventListener("click",()=>e.classList.add("gte-hidden")),e.querySelectorAll(".gte-tab").forEach(t=>t.addEventListener("click",()=>{e.querySelectorAll(".gte-tab").forEach(e=>e.classList.remove("gte-active")),e.querySelectorAll(".gte-panel").forEach(e=>e.classList.remove("gte-active")),t.classList.add("gte-active"),e.querySelector("#gte-panel-"+t.dataset.panel).classList.add("gte-active"),"manager"===t.dataset.panel&&q()}));let t=0,n=0,o=0,r=0;function a(a){t=o-a.clientX,n=r-a.clientY,o=a.clientX,r=a.clientY,e.style.top=Math.max(0,Math.min(window.innerHeight-50,e.offsetTop-n))+"px",e.style.left=Math.max(0,Math.min(window.innerWidth-100,e.offsetLeft-t))+"px",e.style.right="auto"}function i(){document.removeEventListener("mousemove",a),document.removeEventListener("mouseup",i)}return e.querySelector("#gte-titlebar").addEventListener("mousedown",e=>{"BUTTON"!==e.target.tagName&&(e.preventDefault(),o=e.clientX,r=e.clientY,document.addEventListener("mousemove",a),document.addEventListener("mouseup",i))}),e}(),X({},"","dark"),_themeEditor={loadThemes:g,getActiveThemeName:m,applyThemeByName:U,toggleModal:()=>{R.classList.contains("gte-hidden")?(R.classList.remove("gte-hidden"),document.getElementById("gte-theme-name")||X({},"")):R.classList.add("gte-hidden")}},(async()=>{let e=0;for(;!E()&&e<60;)await new Promise(e=>setTimeout(e,500)),e++;const t=m();if(t){const e=g();if(e[t]){const n=e[t].base||"dark",o=await v(n);if(o){const r=k(o,e[t].overrides);L(r,n),M(r)}}}})()}(),_featureStatus.themeEditor="ok",console.log("[GeoPixelcons++] ✅ Theme Editor loaded")}catch(F){_featureStatus.themeEditor="error",dbgPush(`Theme Editor init failed: ${F&&F.message?F.message:String(F)}`,{error:F,uiComponent:"Theme Editor"}),console.error("[GeoPixelcons++] ❌ Theme Editor failed:",F)}if(_settings.mapMarkers)try{(()=>{const e="gpc_mapMarkers_v1",t=e=>"gpc_mmImg_"+e;let n=[];const o=new Map,r=new Map,a=document.createElement("canvas");a.id="gpc-markers-canvas",a.className="inset-0 absolute pointer-events-none",document.body.appendChild(a);const i=new Map,l=document.createElement("div");l.id="gpc-markers-overlay",Object.assign(l.style,{position:"absolute",inset:"0",pointerEvents:"none",overflow:"hidden",zIndex:"2"});let s=null,c=null,d=null,p=null,g=!0;const u=new Set;let m=null;const h="images";let f=null;function b(){return f?Promise.resolve(f):new Promise((e,t)=>{const n=indexedDB.open("gpc_mapMarkers_imgs",1);n.onupgradeneeded=e=>{e.target.result.createObjectStore(h)},n.onsuccess=t=>{f=t.target.result,e(f)},n.onerror=e=>t(e.target.error)})}async function y(e){const t=await b();return new Promise(n=>{const o=t.transaction(h,"readonly").objectStore(h).get(e);o.onsuccess=()=>n(o.result||null),o.onerror=()=>n(null)})}async function x(e,t){const n=await b();return new Promise((o,r)=>{const a=n.transaction(h,"readwrite").objectStore(h).put(t,e);a.onsuccess=()=>o(),a.onerror=e=>r(e.target.error)})}function v(){GM_setValue(e,JSON.stringify(n))}function w(e,t){return new Promise(n=>{const r=new Image;r.onload=()=>{o.set(e,r),n(r)},r.onerror=()=>n(null),r.src=t})}function k(e){return!e.mediaType||"image"===e.mediaType}function E(e){return"gif"===e.mediaType}function C(){return("undefined"!=typeof unsafeWindow?unsafeWindow:window).gridSize||("undefined"!=typeof gridSize?gridSize:25)}function S(e){const t=C(),n=[(e.gridX-.5)*t,(e.gridY-.5+e.gridH)*t],o=[(e.gridX-.5+e.gridW)*t,(e.gridY-.5)*t],r=map.project(turf.toWgs84(n)),a=map.project(turf.toWgs84(o));return{x:r.x,y:r.y,w:a.x-r.x,h:a.y-r.y}}function T(e){return{nw:{x:e.x,y:e.y},n:{x:e.x+e.w/2,y:e.y},ne:{x:e.x+e.w,y:e.y},e:{x:e.x+e.w,y:e.y+e.h/2},se:{x:e.x+e.w,y:e.y+e.h},s:{x:e.x+e.w/2,y:e.y+e.h},sw:{x:e.x,y:e.y+e.h},w:{x:e.x,y:e.y+e.h/2}}}function P(e,t){const n=C(),o=a.getBoundingClientRect(),r=map.unproject([e-o.left,t-o.top]),i=turf.toMercator([r.lng,r.lat]);return{gridX:Math.round(i[0]/n),gridY:Math.round(i[1]/n)}}function L(e){if(!E(e))return;let t=i.get(e.id);if(!e.visible||null==e.gridX)return void(t&&(t.style.display="none"));t||(t=document.createElement("img"),Object.assign(t.style,{position:"absolute",display:"block",objectFit:"fill",maxWidth:"none",maxHeight:"none",imageRendering:"pixelated"}),i.set(e.id,t),l.appendChild(t));const n=r.get(e.id)||"";if(t.src!==n&&(t.src=n),!n)return void(t.style.display="none");const o=function(e){const t=C(),n=[(e.gridX-.5)*t,(e.gridY-.5+e.gridH)*t],o=[(e.gridX-.5+e.gridW)*t,(e.gridY-.5)*t],r=map.project(turf.toWgs84(n)),a=map.project(turf.toWgs84(o));return{x:r.x,y:r.y,w:a.x-r.x,h:a.y-r.y}}(e);t.style.display=o.w>0&&o.h>0?"block":"none",t.style.left=o.x+"px",t.style.top=o.y+"px",t.style.width=o.w+"px",t.style.height=o.h+"px",t.style.opacity=e.opacity??1}function M(){const e=document.getElementById("pixel-canvas");if(!e)return;if("undefined"==typeof map||!map||"function"!=typeof map.project)return;a.width=e.width,a.height=e.height;const t=a.getContext("2d");t.imageSmoothingEnabled=!1,t.clearRect(0,0,a.width,a.height);for(const e of n){if(!e.visible||null==e.gridX)continue;if(!k(e))continue;const n=o.get(e.id);if(!n||!n.complete)continue;const r=S(e);r.w<=0||r.h<=0||(r.x+r.w<0||r.x>a.width||r.y+r.h<0||r.y>a.height||(t.globalAlpha=e.opacity??1,t.drawImage(n,r.x,r.y,r.w,r.h),t.globalAlpha=1,d===e.id&&I(t,r)))}if(d){const e=n.find(e=>e.id===d);e&&null!=e.gridX&&!k(e)&&I(t,S(e))}if(c&&p&&p.preview){const e=p.preview,r=n.find(e=>e.id===c),a=r&&k(r)&&o.get(r.id);a&&(t.globalAlpha=.55,t.drawImage(a,e.x,e.y,e.w,e.h),t.globalAlpha=1),t.strokeStyle="#3b82f6",t.lineWidth=2,t.setLineDash([6,3]),t.strokeRect(e.x,e.y,e.w,e.h),t.setLineDash([])}!function(){for(const e of n)L(e)}()}function I(e,t){e.save(),e.strokeStyle="#3b82f6",e.lineWidth=1.5,e.setLineDash([5,3]),e.strokeRect(t.x,t.y,t.w,t.h),e.setLineDash([]);const n=T(t);for(const t of Object.values(n))e.fillStyle="#fff",e.strokeStyle="#3b82f6",e.lineWidth=2,e.beginPath(),e.arc(t.x,t.y,6,0,2*Math.PI),e.fill(),e.stroke();e.restore()}function _(e){N(),c=e,a.style.pointerEvents="auto",a.style.cursor="crosshair",O("Drag to define image size. Hold Shift to lock aspect ratio.")}function G(){c=null,p=null,a.style.pointerEvents="none",a.style.cursor="",M()}function R(e){G(),d=e,a.style.pointerEvents="auto",a.style.cursor="default",M()}function N(){d=null,p=null,a.style.pointerEvents="none",a.style.cursor="",M(),A()}function A(){const e=document.getElementById("gpc-mm-list");e&&z(e),M()}function z(e){if(e.innerHTML="",!n.length)return void(e.innerHTML='<div style="text-align:center;color:var(--color-gray-400,#9ca3af);padding:22px 14px;font-size:12px;">No markers yet.<br>Upload media above.</div>');let t=null;for(let o=0;o<n.length;o++){const r=n[o],a=document.createElement("div");a.setAttribute("data-mm-idx",String(o)),a.style.cssText="position:relative;",a.appendChild(B(r)),a.addEventListener("dragstart",e=>{m=o,e.dataTransfer.effectAllowed="move",a.style.opacity="0.45"}),a.addEventListener("dragend",()=>{a.style.opacity="",e.querySelectorAll("[data-mm-drop-indicator]").forEach(e=>e.remove())}),a.addEventListener("dragover",n=>{if(null==m||m===o)return;n.preventDefault(),n.dataTransfer.dropEffect="move",e.querySelectorAll("[data-mm-drop-indicator]").forEach(e=>e.remove());const r=document.createElement("div");r.setAttribute("data-mm-drop-indicator","1"),r.style.cssText="height:2px;background:#3b82f6;margin:0 10px;border-radius:2px;";const i=a.getBoundingClientRect(),l=n.clientY<i.top+i.height/2;l?a.insertAdjacentElement("beforebegin",r):a.insertAdjacentElement("afterend",r),t=l?o:o+1}),a.addEventListener("dragleave",()=>{}),a.addEventListener("drop",o=>{if(o.preventDefault(),e.querySelectorAll("[data-mm-drop-indicator]").forEach(e=>e.remove()),null==m||m===t)return void(m=null);const r=n.splice(m,1)[0],a=t>m?t-1:t;n.splice(a,0,r),m=null,t=null,v(),A()}),e.appendChild(a)}}function B(e){const t=c===e.id,a=d===e.id,l=!g||u.has(e.id),s=a?"var(--color-blue-50,#eff6ff)":t?"var(--color-green-50,#f0fdf4)":"var(--color-gray-50,#f9fafb)",p=a?"var(--color-blue-200,#bfdbfe)":t?"var(--color-green-200,#bbf7d0)":"var(--color-gray-200,#e5e7eb)",m=document.createElement("div");Object.assign(m.style,{margin:"4px 10px",padding:g?"6px 9px":"9px",borderRadius:"8px",display:"flex",flexDirection:"column",gap:"5px",background:s,border:"1px solid "+p,cursor:"default"});const f=document.createElement("div");Object.assign(f.style,{display:"flex",alignItems:"center",gap:"7px"});const y=document.createElement("span");y.textContent="⠇",y.title="Drag to reorder",y.draggable=!0,y.style.cssText="color:var(--color-gray-400,#9ca3af);cursor:grab;font-size:14px;flex-shrink:0;user-select:none;",f.appendChild(y),f.appendChild(function(e,t){const n=t||34,a={width:n+"px",height:n+"px",borderRadius:"4px",flexShrink:"0",border:"1px solid var(--color-gray-200,#e5e7eb)",background:"repeating-conic-gradient(#ccc 0% 25%,transparent 0% 50%) 0 0/8px 8px"};if(E(e)){const t=document.createElement("img");return t.src=r.get(e.id)||"",Object.assign(t.style,{...a,objectFit:"cover",display:"block"}),t}const i=document.createElement("canvas");i.width=n,i.height=n,Object.assign(i.style,a);const l=o.get(e.id);if(l){const t=i.getContext("2d");t.globalAlpha=e.opacity??1,t.drawImage(l,0,0,n,n),t.globalAlpha=1}return i}(e,34));const x=document.createElement("div");Object.assign(x.style,{flex:"1",minWidth:"0",display:"flex",flexDirection:"column",gap:"2px"});const w=document.createElement("div");w.textContent=function(e){return E(e)?"🎞":"🖼"}(e)+" "+e.name,w.style.cssText="font-size:12px;font-weight:700;color:var(--color-gray-800,#1f2937);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;",x.appendChild(w);const C=document.createElement("div");C.style.cssText="font-size:10px;color:"+(null!=e.gridX?"var(--color-green-600,#16a34a)":"var(--color-gray-400,#9ca3af)")+";",C.textContent=null!=e.gridX?`(${e.gridX}, ${e.gridY+e.gridH}) — ${e.gridW}×${e.gridH}`:"Not placed",x.appendChild(C),f.appendChild(x);const S=document.createElement("button");if(S.textContent=e.visible?"👁":"🚫",S.title=e.visible?"Hide":"Show",Object.assign(S.style,{background:"none",border:"none",cursor:"pointer",fontSize:"14px",padding:"1px",flexShrink:"0"}),S.onclick=()=>{e.visible=!e.visible,v(),A()},f.appendChild(S),g){const T=document.createElement("button");T.textContent=l?"▲":"▼",T.title=l?"Collapse":"Expand controls",Object.assign(T.style,{background:"none",border:"none",cursor:"pointer",fontSize:"10px",color:"var(--color-gray-500,#6b7280)",padding:"1px",flexShrink:"0"}),T.onclick=t=>{t.stopPropagation(),u.has(e.id)?u.delete(e.id):u.add(e.id),A()},f.appendChild(T),m.addEventListener("click",t=>{"BUTTON"!==t.target.tagName&&"INPUT"!==t.target.tagName&&(u.has(e.id)?u.delete(e.id):u.add(e.id),A())})}if(m.appendChild(f),l){const P=document.createElement("div");Object.assign(P.style,{display:"flex",alignItems:"center",gap:"7px"});const L=document.createElement("input");L.type="text",L.value=e.name,Object.assign(L.style,{flex:"1",padding:"3px 6px",border:"1px solid var(--color-gray-300,#d1d5db)",borderRadius:"4px",fontSize:"12px",fontWeight:"600",color:"var(--color-gray-800,#1f2937)",background:"var(--color-white,#fff)"}),L.onchange=()=>{e.name=L.value,v(),A()},P.appendChild(L),m.appendChild(P);{const B=document.createElement("div");Object.assign(B.style,{display:"flex",alignItems:"center",gap:"6px"});const O=document.createElement("span");O.textContent="Opacity",O.style.cssText="font-size:11px;color:var(--color-gray-500,#6b7280);flex-shrink:0;",B.appendChild(O);const D=document.createElement("input");D.type="range",D.min="0",D.max="1",D.step="0.05",D.value=e.opacity??1,D.style.cssText="flex:1;cursor:pointer;",D.oninput=()=>{e.opacity=parseFloat(D.value),M()},D.onchange=()=>v(),B.appendChild(D);const j=document.createElement("button");if(j.textContent=e.lockAspect?"🔒":"🔓",j.title=e.lockAspect?"Aspect locked":"Aspect free",Object.assign(j.style,{background:"none",border:"none",cursor:"pointer",fontSize:"14px",padding:"1px",flexShrink:"0"}),j.onclick=()=>{e.lockAspect=!e.lockAspect,v(),A()},B.appendChild(j),k(e)){const H=document.createElement("button");H.textContent="↺",H.title="Reset to natural aspect ratio",Object.assign(H.style,{background:"none",border:"none",cursor:"pointer",fontSize:"14px",padding:"1px",flexShrink:"0"}),H.onclick=()=>{const t=o.get(e.id);t&&(e.gridH=Math.max(1,Math.round(e.gridW/(t.naturalWidth/t.naturalHeight))),v(),M(),A())},B.appendChild(H)}m.appendChild(B)}const I=document.createElement("div");function z(e,t,n){const o=document.createElement("button");return o.textContent=e,Object.assign(o.style,{flex:"1",padding:"5px 3px",border:"none",borderRadius:"6px",cursor:"pointer",fontSize:"11px",fontWeight:"700",background:t,color:"#fff",transition:"opacity .12s"}),o.onmouseenter=()=>o.style.opacity="0.82",o.onmouseleave=()=>o.style.opacity="1",o.onclick=n,o}I.style.cssText="display:flex;gap:5px;",I.appendChild(z(t?"⏸ Stop":"📍 Place",t?"#f59e0b":"#10b981",()=>{t?G():_(e.id),A()})),null!=e.gridX&&I.appendChild(z(a?"✓ Done":"✏️ Edit",a?"#6366f1":"#3b82f6",()=>{a?N():R(e.id),A()})),I.appendChild(z("🗑 Remove","#ef4444",()=>{if(!confirm("Remove this marker?"))return;const t=n.findIndex(t=>t.id===e.id);-1!==t&&n.splice(t,1),o.delete(e.id),function(e){const t=i.get(e);t&&(t.remove(),i.delete(e)),r.delete(e)}(e.id),u.delete(e.id),async function(e){const t=await b();return new Promise(n=>{const o=t.transaction(h,"readwrite");o.objectStore(h).delete(e),o.oncomplete=()=>n(),o.onerror=()=>n()})}(e.id).catch(()=>{}),v(),d===e.id&&N(),c===e.id&&G(),A()})),m.appendChild(I)}return m}function O(e,t){const n=document.getElementById("gpc-mm-toast");n&&n.remove();const o=document.createElement("div");o.id="gpc-mm-toast",o.textContent=e,Object.assign(o.style,{position:"fixed",top:"68px",left:"50%",transform:"translateX(-50%)",padding:"8px 18px",borderRadius:"8px",fontSize:"13px",fontWeight:"700",zIndex:"100002",boxShadow:"0 4px 12px rgba(0,0,0,.2)",transition:"opacity .3s",fontFamily:"system-ui,sans-serif",background:t?"#fca5a5":"#bbf7d0",color:t?"#7f1d1d":"#166534"}),document.body.appendChild(o),setTimeout(()=>{o.style.opacity="0",setTimeout(()=>o.remove(),300)},2600)}!function(e){let t=0;!function n(){"undefined"!=typeof map&&map&&map.on?e():t++<200&&setTimeout(n,100)}()}(()=>{map.getContainer().appendChild(l),["move","rotate","zoom"].forEach(e=>map.on(e,M)),new ResizeObserver(M).observe(map.getContainer()),map.once("load",M),M()}),a.addEventListener("wheel",e=>map.getCanvas().dispatchEvent(new WheelEvent(e.type,e))),a.addEventListener("mousedown",e=>{if(0===e.button)if(e.preventDefault(),e.stopPropagation(),c)p={type:"place",startGrid:P(e.clientX,e.clientY),preview:null};else if(d){const t=n.find(e=>e.id===d);if(!t||null==t.gridX)return;const o=a.getBoundingClientRect(),r=e.clientX-o.left,i=e.clientY-o.top,l=T(S(t));let s=null;for(const[e,t]of Object.entries(l)){const n=r-t.x,o=i-t.y;if(Math.sqrt(n*n+o*o)<=9){s=e;break}}if(s)p={type:"handle",handle:s,markerId:d,startGrid:P(e.clientX,e.clientY),orig:{...t}};else{const n=S(t);r>=n.x&&r<=n.x+n.w&&i>=n.y&&i<=n.y+n.h?(a.style.cursor="grabbing",p={type:"move",markerId:d,startGrid:P(e.clientX,e.clientY),origPos:{gridX:t.gridX,gridY:t.gridY}}):N()}}}),document.addEventListener("mousemove",e=>{if(!p&&d){const t=a.getBoundingClientRect(),o=e.clientX-t.left,r=e.clientY-t.top;if(o>=0&&r>=0&&o<=a.width&&r<=a.height){const e=n.find(e=>e.id===d);if(e&&null!=e.gridX){const t=T(S(e));let n=!1;for(const e of Object.values(t))if(Math.hypot(o-e.x,r-e.y)<=9){n=!0;break}if(n)a.style.cursor="nwse-resize";else{const t=S(e);a.style.cursor=o>=t.x&&o<=t.x+t.w&&r>=t.y&&r<=t.y+t.h?"grab":"default"}}}}if(p)if("place"===p.type&&c){const t=P(e.clientX,e.clientY),r=p.startGrid,a=n.find(e=>e.id===c),i=a&&o.get(a.id);let l=Math.abs(t.gridX-r.gridX)+1,s=Math.abs(t.gridY-r.gridY)+1;if((e.shiftKey||a&&a.lockAspect)&&i){const e=i.naturalWidth/i.naturalHeight;l/s>e?s=Math.max(1,Math.round(l/e)):l=Math.max(1,Math.round(s*e))}const d=Math.min(r.gridX,t.gridX),g=Math.min(r.gridY,t.gridY),u=C(),m=map.project(turf.toWgs84([(d-.5)*u,(g-.5+s)*u])),h=map.project(turf.toWgs84([(d-.5+l)*u,(g-.5)*u]));p.preview={x:m.x,y:m.y,w:h.x-m.x,h:h.y-m.y},p.pending={gridX:d,gridY:g,gridW:l,gridH:s},M()}else if("handle"===p.type){const t=n.find(e=>e.id===p.markerId);if(!t)return;!function(e,t,n,o,r,a){const i=a?a.naturalWidth/a.naturalHeight:null,l=o||e.lockAspect,s=r.gridX+r.gridW,c=r.gridY+r.gridH;let d=r.gridX,p=r.gridY,g=r.gridW,u=r.gridH;switch(t){case"nw":d=n.gridX,g=s-n.gridX,u=n.gridY-r.gridY,l&&i&&(g/u>i?u=g/i:(g=u*i,d=s-g));break;case"ne":g=n.gridX-r.gridX,u=n.gridY-r.gridY,l&&i&&(g/u>i?u=g/i:g=u*i);break;case"sw":d=n.gridX,g=s-n.gridX,p=n.gridY,u=c-n.gridY,l&&i&&(g/u>i?(u=g/i,p=c-u):(g=u*i,d=s-g));break;case"se":g=n.gridX-r.gridX,p=n.gridY,u=c-n.gridY,l&&i&&(g/u>i?(u=g/i,p=c-u):g=u*i);break;case"n":u=n.gridY-r.gridY;break;case"s":p=n.gridY,u=c-n.gridY;break;case"e":g=n.gridX-r.gridX;break;case"w":d=n.gridX,g=s-n.gridX}g<1&&(g=1);u<1&&(u=1);e.gridX=Math.round(d),e.gridY=Math.round(p),e.gridW=Math.round(g),e.gridH=Math.round(u)}(t,p.handle,P(e.clientX,e.clientY),e.shiftKey,p.orig,o.get(t.id)),M()}else if("move"===p.type){const t=n.find(e=>e.id===p.markerId);if(!t)return;const o=P(e.clientX,e.clientY);t.gridX=p.origPos.gridX+(o.gridX-p.startGrid.gridX),t.gridY=p.origPos.gridY+(o.gridY-p.startGrid.gridY),M()}}),document.addEventListener("mouseup",e=>{if(p)if("place"===p.type&&c)if(p.pending){const e=n.find(e=>e.id===c);e&&(Object.assign(e,p.pending),v());const t=c;G(),R(t),A(),O("Placed! Drag to move, handles to resize.")}else O("Please drag to define the image size.",!0),p=null,M();else p&&"handle"===p.type?(v(),A(),p=null):p&&"move"===p.type&&(a.style.cursor="grab",v(),A(),p=null)}),function(){try{n=JSON.parse(GM_getValue(e,"[]"))}catch{n=[]}}(),async function(){await async function(){let e=0;for(const o of n){const n=GM_getValue(t(o.id),null);if(n)try{await x(o.id,n);try{GM_deleteValue(t(o.id))}catch{GM_setValue(t(o.id),"")}e++}catch(e){console.warn("[GeoPixelcons++] Map Markers: migration failed for",o.id,e)}}e>0&&console.log(`[GeoPixelcons++] Map Markers: migrated ${e} image(s) from GM_setValue to IndexedDB`)}();for(const e of n)if(E(e)){if(!r.has(e.id)){const t=await y(e.id);t&&r.set(e.id,t)}if(!o.has(e.id)){const t=r.get(e.id)||await y(e.id);t&&await w(e.id,t)}}else if(!o.has(e.id)){const t=await y(e.id);t&&await w(e.id,t)}}().then(M),_mapMarkers={openModal:function(){if(s)return void(s.style.display="none"===s.style.display?"flex":"none");s=document.createElement("div"),Object.assign(s.style,{position:"fixed",top:"60px",left:"60px",zIndex:"10000",background:"var(--color-white,#fff)",borderRadius:"12px",boxShadow:"0 8px 32px rgba(0,0,0,.2)",display:"flex",flexDirection:"column",width:"330px",maxHeight:"82vh",userSelect:"none",overflow:"hidden"});const e=document.createElement("div");Object.assign(e.style,{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"11px 14px",background:"var(--color-gray-50,#f9fafb)",borderBottom:"1px solid var(--color-gray-200,#e5e7eb)",borderRadius:"12px 12px 0 0",cursor:"grab",flexShrink:"0"}),e.innerHTML='<span style="font-weight:700;font-size:13px;color:var(--color-gray-800,#1f2937);">📌 Map Markers</span>';const t=document.createElement("button");t.title="Toggle compact view",t.textContent=g?"□":"☰",Object.assign(t.style,{background:"none",border:"none",cursor:"pointer",fontSize:"13px",color:"var(--color-gray-500,#6b7280)",padding:"1px 5px",borderRadius:"4px",marginLeft:"auto",marginRight:"4px"}),t.onclick=()=>{g=!g,t.textContent=g?"□":"☰",A()},e.appendChild(t);const o=document.createElement("button");o.textContent="✕",Object.assign(o.style,{background:"none",border:"none",cursor:"pointer",fontSize:"13px",color:"var(--color-gray-500,#6b7280)",padding:"1px 5px",borderRadius:"4px"}),o.onclick=()=>{s.style.display="none",G(),N()},e.appendChild(o),s.appendChild(e);let a=null;async function i(e,t,o){const a=o||"image",i="mm_"+Date.now()+"_"+Math.random().toString(36).slice(2,6);let l=1;if("gif"===a){const t=await w(i,e);l=t?t.naturalWidth/t.naturalHeight:1,r.set(i,e)}else{const t=await w(i,e);l=t?t.naturalWidth/t.naturalHeight:1}n.push({id:i,name:t,mediaType:a,gridX:null,gridY:null,gridW:50,gridH:Math.max(1,Math.round(50/l)),visible:!0,opacity:1,lockAspect:!0}),await x(i,e),v(),_(i),A()}e.addEventListener("mousedown",n=>{n.target!==o&&n.target!==t&&(a={x:n.clientX-s.offsetLeft,y:n.clientY-s.offsetTop},e.style.cursor="grabbing")}),document.addEventListener("mousemove",e=>{a&&(s.style.left=e.clientX-a.x+"px",s.style.top=e.clientY-a.y+"px")}),document.addEventListener("mouseup",()=>{a=null,e.style.cursor="grab"});const l=document.createElement("div");function c(e,t){const n=document.createElement("button");return n.textContent=e,Object.assign(n.style,{flex:"1 1 40%",padding:"7px",background:t,color:"#fff",border:"none",borderRadius:"7px",cursor:"pointer",fontWeight:"700",fontSize:"12px"}),n}Object.assign(l.style,{padding:"9px 14px",display:"flex",gap:"6px",flexWrap:"wrap",borderBottom:"1px solid var(--color-gray-100,#f3f4f6)",flexShrink:"0"});const d=c("+ Image / GIF","#3b82f6"),p=document.createElement("input");p.type="file",p.accept="image/png,image/jpeg,image/webp,image/gif",p.style.display="none",p.addEventListener("change",async()=>{const e=p.files[0];if(!e)return;const t=await new Promise(t=>{const n=new FileReader;n.onload=e=>t(e.target.result),n.readAsDataURL(e)}),n="image/gif"===e.type;await i(t,e.name.replace(/\.[^/.]+$/,""),n?"gif":"image"),p.value=""}),d.onclick=()=>p.click();const u=c("🔗 Image URL","#8b5cf6");u.onclick=()=>{const e=prompt("Enter image URL:");e&&e.trim()&&(O("Loading…"),GM_xmlhttpRequest({method:"GET",url:e.trim(),responseType:"blob",onload:t=>{const n=t.response.type;if(!n.startsWith("image/"))return void O("URL does not point to an image.",!0);const o="image/gif"===n,r=new FileReader;r.onload=async t=>{const n=e.split("/").pop().replace(/\?.*$/,"").replace(/\.[^/.]+$/,"")||"image";await i(t.target.result,n,o?"gif":"image")},r.readAsDataURL(t.response)},onerror:()=>O("Failed to load image from URL.",!0),ontimeout:()=>O("Request timed out.",!0)}))},l.appendChild(d),l.appendChild(p),l.appendChild(u),s.appendChild(l);const m=document.createElement("div");m.id="gpc-mm-list",Object.assign(m.style,{flex:"1",overflowY:"auto",padding:"6px 0"}),s.appendChild(m),document.body.appendChild(s),z(m)}}})(),_featureStatus.mapMarkers="ok",console.log("[GeoPixelcons++] ✅ Map Markers loaded")}catch(X){_featureStatus.mapMarkers="error",dbgPush(`Map Markers init failed: ${X&&X.message?X.message:String(X)}`,{error:X,uiComponent:"Map Markers"}),console.error("[GeoPixelcons++] ❌ Map Markers failed:",X)}if(_settings.regionScreenshot)try{const q="undefined"!=typeof unsafeWindow?unsafeWindow:window,U=q.fetch.bind(q);q.fetch=async function(...e){const t=await U(...e);try{if(("string"==typeof e[0]?e[0]:e[0]?.url||"").includes("/PlacePixels")&&isAutoScreenshotEnabled()&&_regionScreenshot){const e=loadCachedCoords();e&&t.ok&&setTimeout(()=>{_regionScreenshot.silentDownload(e)},800)}}catch{}return t},console.log("[GeoPixelcons++] ✅ Auto-screenshot fetch hook installed")}catch(W){console.error("[GeoPixelcons++] ❌ Auto-screenshot hook failed:",W)}console.log("[GeoPixelcons++] v"+VERSION+" initialized. Features:",_featureStatus)})();